diff --git a/.all-contributorsrc b/.all-contributorsrc index aa76ec1a65..55ff294842 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -478,6 +478,33 @@ "doc", "data" ] + }, + { + "login": "shachar700", + "name": "shachar700", + "avatar_url": "https://avatars.githubusercontent.com/u/48739719?v=4", + "profile": "https://github.com/shachar700", + "contributions": [ + "code" + ] + }, + { + "login": "purrfectdoodle", + "name": "Eva", + "avatar_url": "https://avatars.githubusercontent.com/u/105788407?v=4", + "profile": "http://purrfectdoodle.com", + "contributions": [ + "design" + ] + }, + { + "login": "amiosi", + "name": "amiosi", + "avatar_url": "https://avatars.githubusercontent.com/u/44352097?v=4", + "profile": "https://github.com/amiosi", + "contributions": [ + "data" + ] } ], "contributorsPerLine": 7, diff --git a/.gitattributes b/.gitattributes index 1f2aa0c6da..a2dcec5e5d 100644 --- a/.gitattributes +++ b/.gitattributes @@ -18,6 +18,9 @@ Makefile text eol=lf *.md text eol=lf *.ps1 text eol=crlf *.yml text eol=lf +*.party text eol=lf +*.cfg text eol=lf +*.ld text eol=lf *.png binary *.bin binary diff --git a/.github/ISSUE_TEMPLATE/01_battle_engine_bugs.yaml b/.github/ISSUE_TEMPLATE/01_battle_engine_bugs.yaml index 4564bad007..2f25421ea0 100644 --- a/.github/ISSUE_TEMPLATE/01_battle_engine_bugs.yaml +++ b/.github/ISSUE_TEMPLATE/01_battle_engine_bugs.yaml @@ -43,17 +43,16 @@ body: label: Version description: What version of pokeemerald-expansion are you using? options: - - 1.13.3 (Latest release) + - 1.14.1 (Latest release) - master (default, unreleased bugfixes) - upcoming (Edge) + - 1.14.0 + - 1.13.4 + - 1.13.3 - 1.13.2 - 1.13.1 - 1.13.0 - - 1.12.3 - - 1.12.2 - - 1.12.1 - - 1.12.0 - - pre-1.12.0 + - pre-1.13.0 validations: required: true - type: input diff --git a/.github/ISSUE_TEMPLATE/02_battle_ai_issues.yaml b/.github/ISSUE_TEMPLATE/02_battle_ai_issues.yaml index 8ee1d1cc17..b0ee167021 100644 --- a/.github/ISSUE_TEMPLATE/02_battle_ai_issues.yaml +++ b/.github/ISSUE_TEMPLATE/02_battle_ai_issues.yaml @@ -43,17 +43,16 @@ body: label: Version description: What version of pokeemerald-expansion are you using? options: - - 1.13.3 (Latest release) + - 1.14.1 (Latest release) - master (default, unreleased bugfixes) - upcoming (Edge) + - 1.14.0 + - 1.13.4 + - 1.13.3 - 1.13.2 - 1.13.1 - 1.13.0 - - 1.12.3 - - 1.12.2 - - 1.12.1 - - 1.12.0 - - pre-1.12.0 + - pre-1.13.0 validations: required: true - type: input diff --git a/.github/ISSUE_TEMPLATE/04_other_errors.yaml b/.github/ISSUE_TEMPLATE/04_other_errors.yaml index 5791967807..4dcb2b3093 100644 --- a/.github/ISSUE_TEMPLATE/04_other_errors.yaml +++ b/.github/ISSUE_TEMPLATE/04_other_errors.yaml @@ -43,17 +43,16 @@ body: label: Version description: What version of pokeemerald-expansion are you using? options: - - 1.13.3 (Latest release) + - 1.14.1 (Latest release) - master (default, unreleased bugfixes) - upcoming (Edge) + - 1.14.0 + - 1.13.4 + - 1.13.3 - 1.13.2 - 1.13.1 - 1.13.0 - - 1.12.3 - - 1.12.2 - - 1.12.1 - - 1.12.0 - - pre-1.12.0 + - pre-1.13.0 validations: required: true - type: input diff --git a/.github/docs_validate/inclusive_summary.py b/.github/docs_validate/inclusive_summary.py new file mode 100755 index 0000000000..76e0218abc --- /dev/null +++ b/.github/docs_validate/inclusive_summary.py @@ -0,0 +1,64 @@ +#!/usr/bin/python3 + +""" +Checks that all documentation pages that should be mentioned in +`docs/SUMMARY.md` are mentioned the file +""" + +import glob +import re +import os +from pathlib import Path + +errorLines = [] + +if not os.path.exists("Makefile"): + errorLines.append("Please run this script from your root folder.") + +summaryFile = Path("docs/SUMMARY.md") +if not errorLines: + if not summaryFile.is_file(): + errorLines.append("docs/SUMMARY.md missing") + +summaryContents = [] +if not errorLines: + with open(summaryFile, 'r', encoding='UTF-8') as file: + entry_pattern = re.compile(r" *\- \[[^\]]*\]\(([^\)]*)\)\n") + lineNo = 0 + while line:=file.readline(): + lineNo = lineNo + 1 + if line == "# Summary\n" or line == "\n": + pass + elif match:=entry_pattern.match(line): + if "" != match.group(1): + summaryContents.append(Path(match.group(1))) + else: + if not errorLines: + errorLines.append("## Unexpected lines in docs/SUMMARY.md") + errorLines.append(f"- {lineNo}: {line.strip()}") + +if not errorLines: + for pathName in glob.glob("**/*.md", root_dir="docs", recursive=True): + path = Path(pathName) + if path == Path("SUMMARY.md"): + pass + elif path == Path("changelogs/template.md"): + pass + elif path in summaryContents: + pass + else: + if not errorLines: + errorLines.append("## `docs/**/*.md` files present but not mentioned in `docs/SUMMARY.md`") + errorLines.append("- " + str(path)) + +if errorLines: + for line in errorLines: + print(line) + + if 'GITHUB_STEP_SUMMARY' in os.environ: + with open(os.environ['GITHUB_STEP_SUMMARY'], 'w', encoding='UTF-8') as file: + for line in errorLines: + file.write(line) + file.write('\n') + + quit(1) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 8620999045..da1a943e83 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -43,6 +43,18 @@ jobs: TEST: 1 run: | make -j${nproc} check + + docs_validate: + if: github.actor != 'allcontributors[bot]' + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Check that SUMMARY.md includes markdown doc files + run: | + .github/docs_validate/inclusive_summary.py + allcontributors: if: github.actor == 'allcontributors[bot]' runs-on: ubuntu-latest diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index e02d931e28..09e7c78c0c 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -17,7 +17,7 @@ jobs: fetch-depth: 0 - name: Install latest mdbook run: | - tag="v0.5.0-beta.1" + tag="v0.5.1" url="https://github.com/rust-lang/mdbook/releases/download/${tag}/mdbook-${tag}-x86_64-unknown-linux-gnu.tar.gz" mkdir mdbook curl -sSL $url | tar -xz --directory=./mdbook diff --git a/CREDITS.md b/CREDITS.md index e9d1e53354..dfec2d747c 100644 --- a/CREDITS.md +++ b/CREDITS.md @@ -78,6 +78,11 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d cawtds
cawtds

💻 Frank DeBlasio
Frank DeBlasio

💻 leo60228
leo60228

📖 🔣 + shachar700
shachar700

💻 + + + Eva
Eva

🎨 + amiosi
amiosi

🔣 diff --git a/INSTALL.md b/INSTALL.md index 072d43a858..47f00cf78f 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -32,6 +32,7 @@ Distributions with instructions: - [Debian](docs/install/linux/DEBIAN.md) - [Arch Linux](docs/install/linux/ARCH_LINUX.md) - [NixOS](docs/install/linux/NIXOS.md) +- [Fedora](docs/install/linux/FEDORA.md) Other distributions have to infer what to do from [general instructions](docs/install/linux/OTHERS.md). diff --git a/Makefile b/Makefile index 9423d16e1a..bb5b21ee1a 100644 --- a/Makefile +++ b/Makefile @@ -1,12 +1,32 @@ +GAME_VERSION ?= EMERALD +TITLE ?= POKEMON EMER +GAME_CODE ?= BPEE +BUILD_NAME ?= emerald +MAP_VERSION ?= emerald + +ifeq (firered,$(MAKECMDGOALS)) + GAME_VERSION := FIRERED + TITLE := POKEMON FIRE + GAME_CODE := BPRE + BUILD_NAME := firered + MAP_VERSION := firered +else +ifeq (leafgreen,$(MAKECMDGOALS)) + GAME_VERSION := LEAFGREEN + TITLE := POKEMON LEAF + GAME_CODE := BPGE + BUILD_NAME := leafgreen + MAP_VERSION := firered +endif +endif + # GBA rom header -TITLE := POKEMON EMER -GAME_CODE := BPEE MAKER_CODE := 01 REVISION := 0 KEEP_TEMPS ?= 0 # `File name`.gba -FILE_NAME := pokeemerald +FILE_NAME := poke$(BUILD_NAME) BUILD_DIR := build # Compares the ROM to a checksum of the original - only makes sense using when non-modern @@ -21,6 +41,9 @@ UNUSED_ERROR ?= 0 DEBUG ?= 0 # Adds -flto flag, which increases link time but results in a more efficient binary (especially in audio processing) LTO ?= 0 +# Makes an optimized build for release, also enabling NDEBUG macro and disabling other debugging features +# Enables LTO by default, but can be changed in the config.mk file +RELEASE ?= 0 ifeq (compare,$(MAKECMDGOALS)) COMPARE := 1 @@ -31,6 +54,11 @@ endif ifeq (debug,$(MAKECMDGOALS)) DEBUG := 1 endif +ifneq (,$(filter release tidyrelease,$(MAKECMDGOALS))) + RELEASE := 1 +endif + +include config.mk # Default make rule all: rom @@ -63,10 +91,15 @@ endif CPP := $(PREFIX)cpp +ifeq ($(RELEASE),1) + FILE_NAME := $(FILE_NAME)-release +endif + ROM_NAME := $(FILE_NAME).gba -OBJ_DIR_NAME := $(BUILD_DIR)/modern -OBJ_DIR_NAME_TEST := $(BUILD_DIR)/modern-test -OBJ_DIR_NAME_DEBUG := $(BUILD_DIR)/modern-debug +OBJ_DIR_NAME := $(BUILD_DIR)/$(BUILD_NAME) +OBJ_DIR_NAME_TEST := $(BUILD_DIR)/$(BUILD_NAME)-test +OBJ_DIR_NAME_DEBUG := $(BUILD_DIR)/$(BUILD_NAME)-debug +OBJ_DIR_NAME_RELEASE := $(BUILD_DIR)/$(BUILD_NAME)-release ELF_NAME := $(ROM_NAME:.gba=.elf) MAP_NAME := $(ROM_NAME:.gba=.map) @@ -86,6 +119,9 @@ endif ifeq ($(DEBUG),1) OBJ_DIR := $(OBJ_DIR_NAME_DEBUG) endif +ifeq ($(RELEASE),1) + OBJ_DIR := $(OBJ_DIR_NAME_RELEASE) +endif ELF := $(ROM:.gba=.elf) MAP := $(ROM:.gba=.map) SYM := $(ROM:.gba=.sym) @@ -110,7 +146,7 @@ TEST_BUILDDIR = $(OBJ_DIR)/$(TEST_SUBDIR) SHELL := bash -o pipefail # Set flags for tools -ASFLAGS := -mcpu=arm7tdmi -march=armv4t -meabi=5 --defsym MODERN=1 +ASFLAGS := -mcpu=arm7tdmi -march=armv4t -meabi=5 --defsym MODERN=1 --defsym $(GAME_VERSION)=1 INCLUDE_DIRS := include INCLUDE_CPP_ARGS := $(INCLUDE_DIRS:%=-iquote %) @@ -121,7 +157,13 @@ O_LEVEL ?= g else O_LEVEL ?= 2 endif -CPPFLAGS := $(INCLUDE_CPP_ARGS) -Wno-trigraphs -DMODERN=1 -DTESTING=$(TEST) -std=gnu17 +CPPFLAGS := $(INCLUDE_CPP_ARGS) -Wno-trigraphs -DMODERN=1 -DTESTING=$(TEST) -D$(GAME_VERSION) -std=gnu17 +ifeq ($(RELEASE),1) + override CPPFLAGS += -DRELEASE + ifeq ($(USE_LTO_ON_RELEASE),1) + LTO := 1 + endif +endif ARMCC := $(PREFIX)gcc PATH_ARMCC := PATH="$(PATH)" $(ARMCC) CC1 := $(shell $(PATH_ARMCC) --print-prog-name=cc1) -quiet @@ -166,7 +208,7 @@ include make_tools.mk SMOLTM := $(TOOLS_DIR)/compresSmol/compresSmolTilemap$(EXE) SMOL := $(TOOLS_DIR)/compresSmol/compresSmol$(EXE) GFX := $(TOOLS_DIR)/gbagfx/gbagfx$(EXE) -AIF := $(TOOLS_DIR)/aif2pcm/aif2pcm$(EXE) +WAV2AGB := $(TOOLS_DIR)/wav2agb/wav2agb$(EXE) MID := $(TOOLS_DIR)/mid2agb/mid2agb$(EXE) SCANINC := $(TOOLS_DIR)/scaninc/scaninc$(EXE) PREPROC := $(TOOLS_DIR)/preproc/preproc$(EXE) @@ -201,7 +243,7 @@ MISC_TOOL_DIR := $(TOOLS_DIR)/misc AUTO_GEN_TARGETS += $(INCLUDE_DIRS)/constants/script_commands.h $(DATA_SRC_SUBDIR)/wild_encounters.h: $(DATA_SRC_SUBDIR)/wild_encounters.json $(WILD_ENCOUNTERS_TOOL_DIR)/wild_encounters_to_header.py $(INCLUDE_DIRS)/config/overworld.h $(INCLUDE_DIRS)/config/dexnav.h - python3 $(WILD_ENCOUNTERS_TOOL_DIR)/wild_encounters_to_header.py > $@ + python3 $(WILD_ENCOUNTERS_TOOL_DIR)/wild_encounters_to_header.py $(INCLUDE_DIRS)/constants/script_commands.h: $(MISC_TOOL_DIR)/make_scr_cmd_constants.py $(DATA_ASM_SUBDIR)/script_cmd_table.inc python3 $(MISC_TOOL_DIR)/make_scr_cmd_constants.py @@ -222,8 +264,8 @@ MAKEFLAGS += --no-print-directory # Delete files that weren't built properly .DELETE_ON_ERROR: -RULES_NO_SCAN += libagbsyscall clean clean-assets tidy tidymodern tidycheck generated clean-generated -.PHONY: all rom agbcc modern compare check debug +RULES_NO_SCAN += libagbsyscall clean clean-assets tidy tidymodern tidycheck tidyrelease generated clean-generated +.PHONY: all rom agbcc modern compare check debug release .PHONY: $(RULES_NO_SCAN) infoshell = $(foreach line, $(shell $1 | sed "s/ /__SPACE__/g"), $(info $(subst __SPACE__, ,$(line)))) @@ -250,7 +292,7 @@ ifeq ($(SETUP_PREREQS),1) $(error Errors occurred while building tools. See error messages above for more details) endif # Oh and also generate mapjson sources before we use `SCANINC`. - $(foreach line, $(shell $(MAKE) generated | sed "s/ /__SPACE__/g"), $(info $(subst __SPACE__, ,$(line)))) + $(foreach line, $(shell $(MAKE) MAP_VERSION=$(MAP_VERSION) generated | sed "s/ /__SPACE__/g"), $(info $(subst __SPACE__, ,$(line)))) ifneq ($(.SHELLSTATUS),0) $(error Errors occurred while generating map-related sources. See error messages above for more details) endif @@ -294,6 +336,7 @@ $(shell mkdir -p $(SUBDIRS)) modern: all compare: all debug: all +release: all # Uncomment the next line, and then comment the 4 lines after it to reenable agbcc. #agbcc: all agbcc: @@ -344,7 +387,7 @@ clean-assets: find . \( -iname '*.1bpp' -o -iname '*.4bpp' -o -iname '*.8bpp' -o -iname '*.gbapal' -o -iname '*.lz' -o -iname '*.smol' -o -iname '*.fastSmol' -o -iname '*.smolTM' -o -iname '*.rl' -o -iname '*.latfont' -o -iname '*.hwjpnfont' -o -iname '*.fwjpnfont' \) -exec rm {} + find $(DATA_ASM_SUBDIR)/maps \( -iname 'connections.inc' -o -iname 'events.inc' -o -iname 'header.inc' \) -exec rm {} + -tidy: tidymodern tidycheck tidydebug +tidy: tidymodern tidycheck tidydebug tidyrelease tidymodern: rm -f $(ROM_NAME) $(ELF_NAME) $(MAP_NAME) @@ -357,6 +400,14 @@ tidycheck: tidydebug: rm -rf $(DEBUG_OBJ_DIR_NAME) +tidyrelease: +ifeq ($(RELEASE),1) + rm -f $(ROM_NAME) $(ELF_NAME) $(MAP_NAME) +else # Manually remove the release files on clean/tidy + rm -f $(FILE_NAME)-release.gba $(FILE_NAME)-release.elf $(FILE_NAME)-release.map +endif + rm -rf $(OBJ_DIR_NAME_RELEASE) + # Other rules include graphics_file_rules.mk include map_data_rules.mk @@ -374,7 +425,7 @@ generated: $(AUTO_GEN_TARGETS) %.s: ; %.png: ; %.pal: ; -%.aif: ; +%.wav: ; %.1bpp: %.png ; $(GFX) $< $@ %.4bpp: %.png ; $(GFX) $< $@ @@ -453,7 +504,7 @@ ifneq ($(NODEP),1) endif $(C_BUILDDIR)/%.o: $(C_SUBDIR)/%.s - $(PREPROC) $< charmap.txt | $(CPP) $(INCLUDE_SCANINC_ARGS) - | $(PREPROC) -ie $< charmap.txt | $(AS) $(ASFLAGS) -o $@ + $(PREPROC) $< charmap.txt | $(CPP) $(CPPFLAGS) $(INCLUDE_SCANINC_ARGS) - | $(PREPROC) -ie $< charmap.txt | $(AS) $(ASFLAGS) -o $@ $(C_BUILDDIR)/%.d: $(C_SUBDIR)/%.s $(SCANINC) -M $@ $(INCLUDE_SCANINC_ARGS) -I "" $< @@ -463,7 +514,7 @@ ifneq ($(NODEP),1) endif $(DATA_ASM_BUILDDIR)/%.o: $(DATA_ASM_SUBDIR)/%.s - $(PREPROC) $< charmap.txt | $(CPP) $(INCLUDE_SCANINC_ARGS) - | $(PREPROC) -ie $< charmap.txt | $(AS) $(ASFLAGS) -o $@ + $(PREPROC) $< charmap.txt | $(CPP) $(CPPFLAGS) $(INCLUDE_SCANINC_ARGS) - | $(PREPROC) -ie $< charmap.txt | $(AS) $(ASFLAGS) -o $@ $(DATA_ASM_BUILDDIR)/%.d: $(DATA_ASM_SUBDIR)/%.s $(SCANINC) -M $@ $(INCLUDE_SCANINC_ARGS) -I "" $< @@ -522,6 +573,9 @@ $(ROM): $(ELF) $(OBJCOPY) -O binary $< $@ $(FIX) $@ -p --silent +emerald: all +firered: all +leafgreen: all # Symbol file (`make syms`) $(SYM): $(ELF) $(OBJDUMP) -t $< | sort -u | grep -E "^0[2389]" | $(PERL) -p -e 's/^(\w{8}) (\w).{6} \S+\t(\w{8}) (\S+)$$/\1 \2 \3 \4/g' > $@ diff --git a/README.md b/README.md index 2389dfe26a..8094c29e85 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ If you use **`pokeemerald-expansion`**, please credit **RHH (Rom Hacking Hideout)**. Optionally, include the version number for clarity. ``` -Based off RHH's pokeemerald-expansion 1.13.3 https://github.com/rh-hideout/pokeemerald-expansion/ +Based off RHH's pokeemerald-expansion 1.14.1 https://github.com/rh-hideout/pokeemerald-expansion/ ``` Please consider [crediting all contributors](CREDITS.md) involved in the project! diff --git a/asm/macros/battle_script.inc b/asm/macros/battle_script.inc index 754a5221f6..7eb3b9d064 100644 --- a/asm/macros/battle_script.inc +++ b/asm/macros/battle_script.inc @@ -9,11 +9,11 @@ .2byte \move .endm - .macro attackstring + .macro printattackstring .byte 0x2 .endm - .macro ppreduce + .macro unused_0x3 .byte 0x3 .endm @@ -45,14 +45,16 @@ .byte 0xa .endm - .macro healthbarupdate battler:req + .macro healthbarupdate battler:req updateState:req .byte 0xb .byte \battler + .byte \updateState .endm - .macro datahpupdate battler:req + .macro datahpupdate battler:req updateState:req .byte 0xc .byte \battler + .byte \updateState .endm .macro critmessage @@ -363,9 +365,8 @@ .byte 0x3a .endm - .macro absorbhealthbarupdate battler:req + .macro isdmgblockedbydisguise .byte 0x3b - .byte \battler .endm .macro return @@ -678,10 +679,8 @@ .byte 0x75 .endm - .macro various battler:req, id:req + .macro unused_0x78 .byte 0x76 - .byte \battler - .byte \id .endm .macro setprotectlike @@ -701,10 +700,10 @@ .4byte \jumpInstr .endm - .macro tryhealhalfhealth failInstr:req, battler:req + .macro tryhealhalfhealth battler:req, failInstr:req .byte 0x7b - .4byte \failInstr .byte \battler + .4byte \failInstr .endm .macro trymirrormove @@ -729,14 +728,12 @@ .byte \mode .endm - .macro trysetrest failInstr:req + .macro trysetrest .byte 0x81 - .4byte \failInstr .endm - .macro jumpifnotfirstturn jumpInstr:req + .macro unused_0x82 .byte 0x82 - .4byte \jumpInstr .endm .macro unused_0x83 @@ -753,9 +750,8 @@ .byte \id .endm - .macro stockpiletobasedamage failInstr:req + .macro stockpiletobasedamage .byte 0x86 - .4byte \failInstr .endm .macro stockpiletohpheal failInstr:req @@ -767,7 +763,7 @@ callnative BS_RemoveStockpileCounters .endm - .macro setdrainedhp + .macro unused_0x88 .byte 0x88 .endm @@ -882,7 +878,7 @@ .4byte \failInstr .endm - .macro metronome + .macro setcalledmove .byte 0x9e .endm @@ -943,7 +939,7 @@ .4byte \failInstr .endm - .macro trysetdestinybondtohappen + .macro unused_0xab .byte 0xab .endm @@ -1019,8 +1015,10 @@ .4byte \jumpInstr .endm - .macro tryrestorehpberry + .macro tryactivateitem battler:req, flag:req .byte 0xbb + .byte \battler + .byte \flag .endm .macro halvehp failInstr:req @@ -1050,9 +1048,8 @@ .byte 0xc2 .endm - .macro trysetfutureattack failInstr:req + .macro setfutureattack .byte 0xc3 - .4byte \failInstr .endm .macro trydobeatup endInstr:req, failInstr:req @@ -1102,7 +1099,7 @@ .byte 0xca .endm - .macro setcharge battler:req + .macro unused_0xcb battler:req .byte 0xcb .byte \battler .endm @@ -1229,10 +1226,8 @@ .4byte \jumpInstr .endm - .macro jumpifnotcurrentmoveargtype battler:req, failInstr:req + .macro unused_0xE4 .byte 0xe4 - .byte \battler - .4byte \failInstr .endm .macro pickup @@ -1302,7 +1297,7 @@ .byte 0xf3 .endm - .macro subattackerhpbydmg + .macro unused_0xf4 .byte 0xf4 .endm @@ -1348,7 +1343,7 @@ .byte \trigger .endm - .macro tryworryseed failInstr:req + .macro tryoverwriteability failInstr:req .byte 0xfe .4byte \failInstr .endm @@ -1383,17 +1378,6 @@ .4byte \failInstr .endm - .macro jumpifcantfling battler:req, jumpInstr:req - callnative BS_JumpIfCantFling - .byte \battler - .4byte \jumpInstr - .endm - - .macro itemstatchangeeffects battler:req - callnative BS_RunStatChangeItems - .byte \battler - .endm - .macro allyswitchswapbattlers callnative BS_AllySwitchSwapBattler .endm @@ -1421,9 +1405,10 @@ .4byte \restoreBattlerInstr .endm - .macro itemcurestatus jumpInstr:req + .macro itemcurestatus jumpInstr:req, restoreBattlerInstr:req callnative BS_ItemCureStatus .4byte \jumpInstr + .4byte \restoreBattlerInstr .endm .macro itemincreasestat @@ -1443,26 +1428,17 @@ .4byte \failInstr .endm - .macro setglaiverush - callnative BS_SetGlaiveRush - .endm - .macro setpledge jumpInstr:req callnative BS_SetPledge .4byte \jumpInstr .endm - .macro setpledgestatus battler:req sidestatus:req + .macro setpledgestatus battler:req, sidestatus:req callnative BS_SetPledgeStatus .byte \battler .4byte \sidestatus .endm - .macro trycopycat failInstr:req - callnative BS_TryCopycat - .4byte \failInstr - .endm - .macro setzeffect callnative BS_SetZEffect .endm @@ -1645,14 +1621,6 @@ .4byte \failInstr .endm - .macro tryupdaterecoiltracker - callnative BS_TryUpdateRecoilTracker - .endm - - .macro tryupdateleaderscresttracker - callnative BS_TryUpdateLeadersCrestTracker - .endm - .macro trytidyup clear:req, jumpInstr:req callnative BS_TryTidyUp .byte \clear @@ -1765,10 +1733,6 @@ callnative BS_WaitFanfare .endm - .macro setbeakblast - callnative BS_SetBeakBlast - .endm - .macro cantarshotwork failInstr:req callnative BS_CanTarShotWork .4byte \failInstr @@ -1792,6 +1756,10 @@ .2byte \flags .endm + .macro clearspecialstatuses + callnative BS_ClearSpecialStatuses + .endm + .macro clearmoveresultflags flags:req callnative BS_ClearMoveResultFlags .2byte \flags @@ -1803,8 +1771,8 @@ .4byte \failInstr .endm - .macro jumpifcriticalhit failInstr:req - callnative BS_JumpIfCriticalHit + .macro jumpifnotcriticalhit failInstr:req + callnative BS_JumpIfNotCriticalHit .4byte \failInstr .endm @@ -1814,11 +1782,8 @@ .4byte \jumpInstr .endm - .macro jumpiflastuseditemholdeffect holdEffect:req, secondaryId:req, jumpInstr:req - callnative BS_JumpIfLastUsedItemHoldEffect - .byte \holdEffect - .2byte \secondaryId - .4byte \jumpInstr + .macro tryflingholdeffect + callnative BS_TryFlingHoldEffect .endm .macro swapsidestatuses @@ -1924,8 +1889,8 @@ 1: .endm - .macro jumpifabilitycantbesuppressed battler:req, jumpInstr:req - callnative BS_JumpIfAbilityCantBeSuppressed + .macro jumpifabilitycantbereactivated battler:req, jumpInstr:req + callnative BS_JumpIfAbilityCantBeReactivated .byte \battler .4byte \jumpInstr .endm @@ -2181,16 +2146,6 @@ .4byte \failInstr .endm - .macro suckerpunchcheck failInstr:req - callnative BS_SuckerPunchCheck - .4byte \failInstr - .endm - - .macro setsimplebeam failInstr:req - callnative BS_SetSimpleBeam - .4byte \failInstr - .endm - .macro tryentrainment failInstr:req callnative BS_TryEntrainment .4byte \failInstr @@ -2204,11 +2159,6 @@ callnative BS_InvertStatStages .endm - .macro trymefirst failInstr:req - callnative BS_TryMeFirst - .4byte \failInstr - .endm - .macro tryelectrify failInstr:req callnative BS_TryElectrify .4byte \failInstr @@ -2225,11 +2175,6 @@ .byte \case_ .endm - .macro trylastresort failInstr:req - callnative BS_TryLastResort - .4byte \failInstr - .endm - .macro tryautotomize failInstr:req callnative BS_TryAutotomize .4byte \failInstr @@ -2418,20 +2363,11 @@ .4byte \failInstr .endm - .macro checkpoltergeist failInstr:req - callnative BS_CheckPoltergeist + .macro setpoltergeistmessage failInstr:req + callnative BS_SetPoltergeistMessage .4byte \failInstr .endm - .macro trynoretreat failInstr:req - callnative BS_TryNoRetreat - .4byte \failInstr - .endm - - .macro curecertainstatuses - callnative BS_CureCertainStatuses - .endm - .macro tryresetnegativestatstages callnative BS_TryResetNegativeStatStages .endm diff --git a/asm/macros/event.inc b/asm/macros/event.inc index 6e08a3cdff..6abaeff265 100644 --- a/asm/macros/event.inc +++ b/asm/macros/event.inc @@ -2332,6 +2332,11 @@ callnative ScriptSetDoubleBattleFlag, requests_effects=1 .endm + @ Stop using the ORAS dowsing machine. + .macro stoporasdowsing + callnative EndORASDowsing + .endm + @ ============================ @ @ FAKE RTC MACROS @ Will only function if OW_USE_FAKE_RTC is true. If it has any additional requirements, it will be listed accordingly. @@ -2674,8 +2679,34 @@ .2byte \battlePartner .endm + @ Manually buffer a string as the speaker's name for namebox. + @ The next shown message/msgbox will include a namebox, if the provided string is not NULL. + @ An SP_NAME_* constant can also be used, it'll take the name from gSpeakerNamesTable instead. + .macro setspeaker name:req + callnative SetSpeaker + .4byte \name + .endm + @ VS Seeker .macro vsseeker_rematchid rematchId:req callnative NativeVsSeekerRematchId, requests_effects=1 .2byte \rematchId .endm + + @ Sets the move relearner state + .macro setmoverelearnerstate state:req + callnative ScrCmd_setmoverelearnerstate, requests_effects=1 + .2byte \state + .endm + + @ Retrieves the move relearner state and stores it in the specified var + .macro getmoverelearnerstate varId:req + callnative ScrCmd_getmoverelearnerstate, requests_effects=1 + .4byte \varId + .endm + + @ Execute script if bag has TMs and/or HMs + .macro istmrelearneractive destination:req + callnative ScrCmd_istmrelearneractive, requests_effects=1 + .4byte \destination + .endm diff --git a/audio_rules.mk b/audio_rules.mk index 3fce08ed3a..70d4466409 100644 --- a/audio_rules.mk +++ b/audio_rules.mk @@ -20,16 +20,17 @@ $(MID_BUILDDIR)/%.o: $(MID_ASM_DIR)/%.s $(AS) $(ASFLAGS) -I sound -o $@ $< # Compressed cries -$(CRY_BIN_DIR)/%.bin: $(CRY_SUBDIR)/%.aif - $(AIF) $< $@ --compress +$(CRY_BIN_DIR)/%.bin: $(CRY_SUBDIR)/%.wav +# NOTE: If using ipatix's High Quality Audio Mixer, remove "--no-pad" below. + $(WAV2AGB) -b -c -l 1 --no-pad $< $@ # Uncompressed cries $(CRY_BIN_DIR)/uncomp_%.bin: $(CRY_SUBDIR)/uncomp_%.aif $(AIF) $< $@ # Uncompressed sounds -$(SOUND_BIN_DIR)/%.bin: sound/%.aif - $(AIF) $< $@ +$(SOUND_BIN_DIR)/%.bin: sound/%.wav + $(WAV2AGB) -b $< $@ # For each line in midi.cfg, we do some trickery to convert it into a make rule for the `.mid` file described on the line # Data following the colon in said file corresponds to arguments passed into mid2agb diff --git a/charmap.txt b/charmap.txt index df9ba3b5a2..a6b688f553 100644 --- a/charmap.txt +++ b/charmap.txt @@ -456,6 +456,13 @@ JPN = FC 15 ENG = FC 16 PAUSE_MUSIC = FC 17 RESUME_MUSIC = FC 18 +SPEAKER = FC 19 + +@ Speaker names, the order must be matching with include/constants/speaker_names.h +NAME_NONE = 00 +NAME_MOM = 01 +NAME_PLAYER = 02 +NAME_COUNT = 03 @ fonts diff --git a/config.mk b/config.mk new file mode 100644 index 0000000000..7360c158ef --- /dev/null +++ b/config.mk @@ -0,0 +1,2 @@ +# Enable LTO when making a release build. Disable by setting to 0. +USE_LTO_ON_RELEASE ?= 1 diff --git a/data/battle_anim_scripts.s b/data/battle_anim_scripts.s index b546558daa..5623654048 100644 --- a/data/battle_anim_scripts.s +++ b/data/battle_anim_scripts.s @@ -3361,6 +3361,7 @@ gBattleAnimMove_AquaJet:: visible ANIM_ATTACKER clearmonbg ANIM_DEF_PARTNER blendoff + setarg 7, 0x1000 end gBattleAnimMove_AttackOrder:: @@ -31083,6 +31084,17 @@ gBattleAnimStatus_Nightmare:: clearmonbg ANIM_DEF_PARTNER end +gBattleAnimStatus_Frostbite:: + playsewithpan SE_M_ICY_WIND, 0 + loadspritegfx ANIM_TAG_ICE_CRYSTALS + monbg ANIM_DEF_PARTNER + splitbgprio ANIM_TARGET + call IceCrystalEffectShort + createsprite gSimplePaletteBlendSpriteTemplate, ANIM_ATTACKER, 2, F_PAL_TARGET, 5, 7, 0, RGB(0, 20, 31) + waitforvisualfinish + clearmonbg ANIM_DEF_PARTNER + end + gBattleAnimGeneral_StatsChange:: createvisualtask AnimTask_StatsChange, 5 waitforvisualfinish @@ -32122,6 +32134,16 @@ gBattleAnimGeneral_Swamp:: blendoff end +gBattleAnimGeneral_SwapToSubstitute:: + createvisualtask AnimTask_SwapMonSpriteToFromSubstitute, 2, FALSE + waitforvisualfinish + end + +gBattleAnimGeneral_SwapFromSubstitute:: + createvisualtask AnimTask_SwapMonSpriteToFromSubstitute, 2, TRUE + waitforvisualfinish + end + SnatchMoveTrySwapFromSubstitute: createvisualtask AnimTask_IsAttackerBehindSubstitute, 2 jumprettrue SnatchMoveSwapSubstituteForMon diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 638f81bf7b..6a3e29d17f 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -23,8 +23,6 @@ BattleScript_EffectFickleBeam:: attackcanceler - attackstring - ppreduce accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE ficklebeamdamagecalculation goto BattleScript_HitFromCritCalc @@ -81,19 +79,14 @@ BattleScript_LowerAtkSpAtkEnd: BattleScript_EffectSpicyExtract:: attackcanceler jumpifsubstituteblocks BattleScript_ButItFailed - accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE + accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE jumpifstat BS_TARGET, CMP_LESS_THAN, STAT_ATK, MAX_STAT_STAGE, BattleScript_SpicyExtract_CheckShouldSkipAttackAnim jumpifstat BS_TARGET, CMP_GREATER_THAN, STAT_DEF, MIN_STAT_STAGE, BattleScript_SpicyExtract_CheckShouldSkipAttackAnim goto BattleScript_ButItFailed BattleScript_SpicyExtract_CheckShouldSkipAttackAnim: jumpifbyte CMP_NOT_EQUAL, gBattleCommunication, 0, BattleScript_SpicyExtract_RaiseAtk - attackstring - ppreduce - bicword gHitMarker, HITMARKER_NO_ATTACKSTRING | HITMARKER_NO_PPDEDUCT goto BattleScript_SpicyExtract_SkipAttackAnim BattleScript_SpicyExtract_RaiseAtk: - attackstring - ppreduce attackanimation waitanimation BattleScript_SpicyExtract_SkipAttackAnim: @@ -111,9 +104,7 @@ BattleScript_EffectSpicyExtract_End: BattleScript_EffectTidyUp:: attackcanceler - attackstring pause B_WAIT_TIME_MED - ppreduce waitstate saveattacker savetarget @@ -132,31 +123,27 @@ BattleScript_EffectTidyUpDoMoveAnimation:: restoretarget goto BattleScript_EffectDragonDanceFromStatUp -BattleScript_EffectUpperHand:: - attackcanceler - tryupperhand BattleScript_FailedFromAtkString - goto BattleScript_HitFromAccCheck - BattleScript_EffectShedTail:: attackcanceler - attackstring - ppreduce waitstate jumpifvolatile BS_ATTACKER, VOLATILE_SUBSTITUTE, BattleScript_AlreadyHasSubstitute jumpifbattletype BATTLE_TYPE_ARENA, BattleScript_ButItFailed jumpifcantswitch SWITCH_IGNORE_ESCAPE_PREVENTION | BS_ATTACKER, BattleScript_ButItFailed setsubstitute jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_SUBSTITUTE_FAILED, BattleScript_SubstituteString - orword gHitMarker, HITMARKER_PASSIVE_HP_UPDATE attackanimation waitanimation - healthbarupdate BS_ATTACKER - datahpupdate BS_ATTACKER + healthbarupdate BS_ATTACKER, PASSIVE_HP_UPDATE + datahpupdate BS_ATTACKER, PASSIVE_HP_UPDATE printstring STRINGID_SHEDITSTAIL waitmessage B_WAIT_TIME_LONG moveendto MOVEEND_ATTACKER_VISIBLE moveendfrom MOVEEND_TARGET_VISIBLE - goto BattleScript_MoveSwitchOpenPartyScreen + call BattleScript_MoveSwitchOpenPartyScreenReturnWithNoAnim + switchinanim BS_ATTACKER, FALSE, TRUE + waitstate + switchineffects BS_ATTACKER + end BattleScript_EffectPsychicNoise:: printstring STRINGID_PKMNPREVENTEDFROMHEALING @@ -165,14 +152,11 @@ BattleScript_EffectPsychicNoise:: BattleScript_EffectFilletAway:: attackcanceler - attackstring - ppreduce jumpifstat BS_ATTACKER, CMP_LESS_THAN, STAT_ATK, MAX_STAT_STAGE, BattleScript_FilletAwayTryAttack jumpifstat BS_ATTACKER, CMP_LESS_THAN, STAT_SPATK, MAX_STAT_STAGE, BattleScript_FilletAwayTryAttack jumpifstat BS_ATTACKER, CMP_EQUAL, STAT_SPEED, MAX_STAT_STAGE, BattleScript_ButItFailed BattleScript_FilletAwayTryAttack:: halvehp BattleScript_ButItFailed - orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_HP_UPDATE attackanimation waitanimation setstatchanger STAT_ATK, 2, FALSE @@ -191,14 +175,12 @@ BattleScript_FilletAwayTrySpeed:: waitmessage B_WAIT_TIME_LONG BattleScript_FilletAwayEnd:: clearmoveresultflags MOVE_RESULT_NO_EFFECT - healthbarupdate BS_ATTACKER - datahpupdate BS_ATTACKER + healthbarupdate BS_ATTACKER, PASSIVE_HP_UPDATE + datahpupdate BS_ATTACKER, PASSIVE_HP_UPDATE goto BattleScript_MoveEnd BattleScript_EffectDoodle:: attackcanceler - attackstring - ppreduce trycopyability BS_ATTACKER, BattleScript_ButItFailed saveattacker attackanimation @@ -208,10 +190,8 @@ BattleScript_EffectDoodle:: BattleScript_EffectDoodle_CopyAbility: trycopyability BS_ATTACKER, BattleScript_EffectDoodleMoveEnd BattleScript_EffectDoodle_AfterCopy: -.if B_ABILITY_POP_UP == TRUE copybyte gBattlerAbility, gBattlerAttacker call BattleScript_AbilityPopUpOverwriteThenNormal -.endif recordability BS_ATTACKER printstring STRINGID_PKMNCOPIEDFOE waitmessage B_WAIT_TIME_LONG @@ -227,7 +207,7 @@ BattleScript_EffectDoodleMoveEnd: BattleScript_EffectGlaiveRush:: call BattleScript_EffectHit_Ret jumpifmoveresultflags MOVE_RESULT_DOESNT_AFFECT_FOE, BattleScript_TryFaintMon - setglaiverush + setvolatile BS_ATTACKER, VOLATILE_GLAIVE_RUSH, 2 goto BattleScript_TryFaintMon BattleScript_SyrupBombActivates:: @@ -249,7 +229,6 @@ BattleScript_EffectChillyReception:: printstring STRINGID_PKMNTELLCHILLINGRECEPTIONJOKE waitmessage B_WAIT_TIME_LONG attackcanceler - ppreduce jumpifhalfword CMP_COMMON_BITS, gBattleWeather, B_WEATHER_SUN_PRIMAL, BattleScript_EffectChillyReceptionBlockedByPrimalSun jumpifhalfword CMP_COMMON_BITS, gBattleWeather, B_WEATHER_RAIN_PRIMAL, BattleScript_EffectChillyReceptionBlockedByPrimalRain jumpifhalfword CMP_COMMON_BITS, gBattleWeather, B_WEATHER_STRONG_WINDS, BattleScript_EffectChillyReceptionBlockedByStrongWinds @@ -262,7 +241,6 @@ BattleScript_EffectChillyReception:: call BattleScript_MoveWeatherChangeRet goto BattleScript_MoveSwitch BattleScript_EffectChillyReceptionPlayAnimation: - attackstring attackanimation waitanimation return @@ -279,8 +257,8 @@ BattleScript_EffectChillyReceptionBlockedByStrongWinds: call BattleScript_MysteriousAirCurrentBlowsOnRet goto BattleScript_MoveSwitch BattleScript_EffectChillyReceptionTrySwitchWeatherFailed: - jumpifbattletype BATTLE_TYPE_ARENA, BattleScript_FailedFromAtkString - jumpifcantswitch SWITCH_IGNORE_ESCAPE_PREVENTION | BS_ATTACKER, BattleScript_FailedFromAtkString + jumpifbattletype BATTLE_TYPE_ARENA, BattleScript_ButItFailed + jumpifcantswitch SWITCH_IGNORE_ESCAPE_PREVENTION | BS_ATTACKER, BattleScript_ButItFailed call BattleScript_EffectChillyReceptionPlayAnimation return @@ -308,6 +286,14 @@ BattleScript_MoveSwitch: printstring STRINGID_PKMNWENTBACK waitmessage B_WAIT_TIME_SHORT BattleScript_MoveSwitchOpenPartyScreen:: + call BattleScript_MoveSwitchOpenPartyScreenReturnWithNoAnim + switchinanim BS_ATTACKER, FALSE, FALSE + waitstate + switchineffects BS_ATTACKER +BattleScript_MoveSwitchEnd: + end + +BattleScript_MoveSwitchOpenPartyScreenReturnWithNoAnim: openpartyscreen BS_ATTACKER, BattleScript_MoveSwitchEnd waitstate returntoball BS_ATTACKER, FALSE @@ -320,18 +306,12 @@ BattleScript_MoveSwitchOpenPartyScreen:: printstring STRINGID_EMPTYSTRING3 waitmessage 1 printstring STRINGID_SWITCHINMON - switchinanim BS_ATTACKER, FALSE, TRUE - waitstate - switchineffects BS_ATTACKER -BattleScript_MoveSwitchEnd: - end + return BattleScript_EffectPledge:: attackcanceler setpledge BattleScript_HitFromAccCheck - attackstring pause B_WAIT_TIME_MED - ppreduce printstring STRINGID_WAITINGFORPARTNERSMOVE waitmessage B_WAIT_TIME_LONG goto BattleScript_MoveEnd @@ -402,26 +382,17 @@ BattleScript_MoveEffectSaltCure:: BattleScript_SaltCureExtraDamage:: playanimation BS_ATTACKER, B_ANIM_SALT_CURE_DAMAGE, NULL waitanimation - orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_HP_UPDATE - healthbarupdate BS_ATTACKER - datahpupdate BS_ATTACKER + healthbarupdate BS_ATTACKER, PASSIVE_HP_UPDATE + datahpupdate BS_ATTACKER, PASSIVE_HP_UPDATE printstring STRINGID_TARGETISHURTBYSALTCURE waitmessage B_WAIT_TIME_LONG tryfaintmon BS_ATTACKER - tryrestorehpberry + tryactivateitem BS_ATTACKER, ACTIVATION_ON_HP_THRESHOLD end2 -BattleScript_HurtTarget_NoString: - orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_HP_UPDATE - healthbarupdate BS_TARGET - datahpupdate BS_TARGET - return - BattleScript_EffectCorrosiveGas:: attackcanceler - accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE - attackstring - ppreduce + accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE jumpifsubstituteblocks BattleScript_CorrosiveGasFail jumpifcantloseitem BS_TARGET, BattleScript_CorrosiveGasFail attackanimation @@ -442,8 +413,6 @@ BattleScript_CorrosiveGasFail: BattleScript_EffectTakeHeart:: attackcanceler - attackstring - ppreduce curestatuswithmove BattleScript_CalmMindTryToRaiseStats attackanimation waitanimation @@ -456,8 +425,6 @@ BattleScript_EffectTakeHeart:: BattleScript_EffectRevivalBlessing:: attackcanceler - attackstring - ppreduce tryrevivalblessing BattleScript_ButItFailed attackanimation waitanimation @@ -490,8 +457,6 @@ BattleScript_SpikesActivates:: BattleScript_EffectAttackUpUserAlly:: jumpifnoally BS_ATTACKER, BattleScript_EffectAttackUp attackcanceler - attackstring - ppreduce jumpifstat BS_ATTACKER, CMP_NOT_EQUAL, STAT_ATK, MAX_STAT_STAGE, BattleScript_EffectAttackUpUserAlly_Works jumpifstat BS_ATTACKER_PARTNER, CMP_EQUAL, STAT_ATK, MAX_STAT_STAGE, BattleScript_ButItFailed BattleScript_EffectAttackUpUserAlly_Works: @@ -509,7 +474,7 @@ BattleScript_EffectAttackUpUserAlly_TryAlly_: jumpifblockedbysoundproof BS_ATTACKER_PARTNER, BattleScript_EffectAttackUpUserAlly_TryAllyBlocked setstatchanger STAT_ATK, 1, FALSE statbuffchange BS_TARGET, STAT_CHANGE_ALLOW_PTR, BattleScript_EffectAttackUpUserAlly_End - jumpifbyte CMP_NOT_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_EffectAttackUpUserAlly_AllyString + jumpifbyte CMP_NOT_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_EffectAttackUpUserAlly_AllyString pause B_WAIT_TIME_SHORTEST printstring STRINGID_TARGETSTATWONTGOHIGHER waitmessage B_WAIT_TIME_LONG @@ -528,8 +493,6 @@ BattleScript_EffectAttackUpUserAlly_TryAllyBlocked: BattleScript_EffectTeatime:: attackcanceler - attackstring - ppreduce jumpifteanoberry BattleScript_ButItFailed @ at least one battler is affected attackanimation @@ -540,10 +503,8 @@ BattleScript_TeatimeLoop: jumpifelectricabilityaffected BS_TARGET, ABILITY_VOLT_ABSORB, BattleScript_Teatimesorb jumpifelectricabilityaffected BS_TARGET, ABILITY_MOTOR_DRIVE, BattleScript_Teatimemotor jumpifteainvulnerable BS_TARGET, BattleScript_Teatimevul @ in semi-invulnerable state OR held item is not a Berry - orword gHitMarker, HITMARKER_DISABLE_ANIMATION | HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_IGNORE_DISGUISE setbyte sBERRY_OVERRIDE, TRUE @ override the requirements for eating berries consumeberry BS_TARGET, TRUE @ consume the berry, then restore the item from changedItems - bicword gHitMarker, HITMARKER_DISABLE_ANIMATION | HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_IGNORE_DISGUISE setbyte sBERRY_OVERRIDE, FALSE removeitem BS_TARGET moveendto MOVEEND_NEXT_TARGET @@ -558,8 +519,8 @@ BattleScript_Teatimevul: BattleScript_Teatimesorb: call BattleScript_AbilityPopUpTarget tryhealquarterhealth BS_TARGET, BattleScript_Teatimesorb_end - healthbarupdate BS_TARGET - datahpupdate BS_TARGET + healthbarupdate BS_TARGET, PASSIVE_HP_UPDATE + datahpupdate BS_TARGET, PASSIVE_HP_UPDATE printstring STRINGID_PKMNREGAINEDHEALTH waitmessage B_WAIT_TIME_LONG BattleScript_Teatimesorb_end: @@ -644,17 +605,13 @@ BattleScript_ShellTrapSetUp:: BattleScript_EffectShellTrap:: attackcanceler jumpifshelltrap BS_ATTACKER, BattleScript_HitFromAccCheck - jumpifword CMP_COMMON_BITS, gHitMarker, HITMARKER_NO_ATTACKSTRING | HITMARKER_NO_PPDEDUCT, BattleScript_MoveEnd - ppreduce printstring STRINGID_SHELLTRAPDIDNTWORK waitmessage B_WAIT_TIME_LONG goto BattleScript_MoveEnd BattleScript_EffectCourtChange:: attackcanceler - accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE - attackstring - ppreduce + accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE swapsidestatuses attackanimation waitanimation @@ -663,7 +620,6 @@ BattleScript_EffectCourtChange:: goto BattleScript_MoveEnd BattleScript_BeakBlastSetUp:: - setbeakblast flushtextbox playanimation BS_ATTACKER, B_ANIM_BEAK_BLAST_SETUP, NULL printstring STRINGID_HEATUPBEAK @@ -679,9 +635,7 @@ BattleScript_BeakBlastBurn:: BattleScript_EffectSkyDrop:: attackcanceler jumpifvolatile BS_ATTACKER, VOLATILE_MULTIPLETURNS, BattleScript_SkyDropTurn2 - ppreduce - accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE - attackstring + accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE jumpifsubstituteblocks BattleScript_ButItFailed jumpiftargetally BattleScript_ButItFailed jumpifunder200 BattleScript_SkyDropWork @@ -696,7 +650,6 @@ BattleScript_SkyDropWork: goto BattleScript_MoveEnd BattleScript_SkyDropTurn2: call BattleScript_TwoTurnMovesSecondTurnRet - attackstring clearskydrop BattleScript_SkyDropChangedTarget jumpiftype BS_TARGET, TYPE_FLYING, BattleScript_SkyDropFlyingType goto BattleScript_HitFromCritCalc @@ -726,14 +679,11 @@ BattleScript_SkyDropFlyingAlreadyConfused: BattleScript_EffectFling:: attackcanceler - jumpifcantfling BS_ATTACKER, BattleScript_FailedFromAtkString setlastuseditem BS_ATTACKER accuracycheck BattleScript_FlingMissed, ACC_CURR_MOVE - attackstring pause B_WAIT_TIME_SHORT printstring STRINGID_PKMNFLUNG waitmessage B_WAIT_TIME_SHORT - ppreduce critcalc damagecalc adjustdamage @@ -743,28 +693,22 @@ BattleScript_EffectFling:: effectivenesssound hitanimation BS_TARGET waitstate - healthbarupdate BS_TARGET - datahpupdate BS_TARGET + healthbarupdate BS_TARGET, MOVE_DAMAGE_HP_UPDATE + datahpupdate BS_TARGET, MOVE_DAMAGE_HP_UPDATE critmessage waitmessage B_WAIT_TIME_MED resultmessage waitmessage B_WAIT_TIME_MED jumpiflastuseditemberry BattleScript_EffectFlingConsumeBerry - jumpifability BS_TARGET, ABILITY_SHIELD_DUST, BattleScript_FlingBlockedByShieldDust - jumpiflastuseditemholdeffect HOLD_EFFECT_FLAME_ORB, 0, BattleScript_FlingFlameOrb - jumpiflastuseditemholdeffect HOLD_EFFECT_FLINCH, 0, BattleScript_FlingFlinch - jumpiflastuseditemholdeffect HOLD_EFFECT_LIGHT_BALL, 0, BattleScript_FlingLightBall - jumpiflastuseditemholdeffect HOLD_EFFECT_MENTAL_HERB, 0, BattleScript_FlingMentalHerb - jumpiflastuseditemholdeffect HOLD_EFFECT_TYPE_POWER, TYPE_POISON, BattleScript_FlingPoisonBarb - jumpiflastuseditemholdeffect HOLD_EFFECT_TOXIC_ORB, 0, BattleScript_FlingToxicOrb - jumpiflastuseditemholdeffect HOLD_EFFECT_WHITE_HERB, 0, BattleScript_FlingWhiteHerb + tryflingholdeffect goto BattleScript_FlingEnd + BattleScript_EffectFlingConsumeBerry: savebattleritem battleritemtolastuseditem setbyte sBERRY_OVERRIDE, 1 @ override the requirements for eating berries orword gHitMarker, HITMARKER_DISABLE_ANIMATION - consumeberry BS_TARGET, TRUE + consumeberry BS_TARGET, FALSE bicword gHitMarker, HITMARKER_DISABLE_ANIMATION setbyte sBERRY_OVERRIDE, 0 restorebattleritem @@ -775,76 +719,31 @@ BattleScript_FlingEnd: BattleScript_FlingFailConsumeItem:: removeitem BS_ATTACKER - goto BattleScript_FailedFromAtkString + goto BattleScript_ButItFailed BattleScript_FlingBlockedByShieldDust:: printstring STRINGID_ITEMWASUSEDUP waitmessage B_WAIT_TIME_LONG goto BattleScript_FlingEnd -BattleScript_FlingFlameOrb: - seteffectsecondary BS_ATTACKER, BS_TARGET, MOVE_EFFECT_BURN - goto BattleScript_FlingEnd -BattleScript_FlingFlinch: - seteffectsecondary BS_ATTACKER, BS_TARGET, MOVE_EFFECT_FLINCH - goto BattleScript_FlingEnd -BattleScript_FlingLightBall: - seteffectsecondary BS_ATTACKER, BS_TARGET, MOVE_EFFECT_PARALYSIS - goto BattleScript_FlingEnd -BattleScript_FlingMentalHerb: - curecertainstatuses - saveattacker - copybyte gBattlerAttacker, gBattlerTarget - playanimation BS_ATTACKER, B_ANIM_HELD_ITEM_EFFECT, NULL - printfromtable gMentalHerbCureStringIds - waitmessage B_WAIT_TIME_LONG - updatestatusicon BS_ATTACKER - restoreattacker - goto BattleScript_FlingEnd -BattleScript_FlingPoisonBarb: - seteffectsecondary BS_ATTACKER, BS_TARGET, MOVE_EFFECT_POISON - goto BattleScript_FlingEnd -BattleScript_FlingToxicOrb: - seteffectsecondary BS_ATTACKER, BS_TARGET, MOVE_EFFECT_TOXIC - goto BattleScript_FlingEnd -BattleScript_FlingWhiteHerb: - tryresetnegativestatstages - swapattackerwithtarget - printstring STRINGID_PKMNSTATUSNORMAL - waitmessage B_WAIT_TIME_MED - swapattackerwithtarget - goto BattleScript_FlingEnd - BattleScript_FlingMissed: removeitem BS_ATTACKER - attackstring - ppreduce goto BattleScript_MoveMissedPause -BattleScript_EffectAuraWheel:: @ Aura Wheel can only be used by Morpeko - jumpifspecies SPECIES_MORPEKO_FULL_BELLY, BattleScript_EffectHit - jumpifspecies SPECIES_MORPEKO_HANGRY, BattleScript_EffectHit - goto BattleScript_PokemonCantUseTheMove - BattleScript_EffectClangorousSoul:: attackcanceler - attackstring - ppreduce cutonethirdhpandraisestats BattleScript_ButItFailed - orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_IGNORE_BIDE | HITMARKER_PASSIVE_HP_UPDATE | HITMARKER_IGNORE_DISGUISE attackanimation waitanimation - healthbarupdate BS_ATTACKER - datahpupdate BS_ATTACKER + healthbarupdate BS_ATTACKER, PASSIVE_HP_UPDATE + datahpupdate BS_ATTACKER, PASSIVE_HP_UPDATE call BattleScript_AllStatsUp goto BattleScript_MoveEnd BattleScript_EffectOctolock:: attackcanceler - jumpifsubstituteblocks BattleScript_FailedFromAtkString - accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE - attackstring - ppreduce + jumpifsubstituteblocks BattleScript_ButItFailed + accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE trysetoctolock BattleScript_ButItFailed attackanimation waitanimation @@ -867,21 +766,17 @@ BattleScript_OctlockTurnDmgEnd: BattleScript_EffectPoltergeist:: attackcanceler - accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE - attackstring - ppreduce - checkpoltergeist BattleScript_ButItFailed + accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE + setpoltergeistmessage BattleScript_ButItFailed printstring STRINGID_ABOUTTOUSEPOLTERGEIST waitmessage B_WAIT_TIME_LONG goto BattleScript_HitFromCritCalc BattleScript_EffectTarShot:: attackcanceler - jumpifsubstituteblocks BattleScript_FailedFromAtkString - accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE - cantarshotwork BattleScript_FailedFromAtkString - attackstring - ppreduce + jumpifsubstituteblocks BattleScript_ButItFailed + accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE + cantarshotwork BattleScript_ButItFailed setstatchanger STAT_SPEED, 1, TRUE attackanimation waitanimation @@ -896,10 +791,9 @@ BattleScript_TryTarShot: BattleScript_EffectNoRetreat:: attackcanceler - accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE - attackstring - ppreduce - trynoretreat BattleScript_ButItFailed + accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE + jumpifvolatile BS_TARGET, VOLATILE_NO_RETREAT, BattleScript_ButItFailed + setvolatile BS_TARGET, VOLATILE_NO_RETREAT attackanimation waitanimation call BattleScript_AllStatsUp @@ -956,9 +850,6 @@ BattleScript_MoveEffectLightScreen:: BattleScript_EffectStuffCheeks:: attackcanceler - attackstring - ppreduce - jumpifnotberry BS_ATTACKER, BattleScript_ButItFailed attackanimation waitanimation setbyte sBERRY_OVERRIDE, 1 @@ -976,11 +867,9 @@ BattleScript_StuffCheeksEnd: BattleScript_EffectDecorate:: attackcanceler - accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE - attackstring - ppreduce - jumpifstat BS_TARGET, CMP_NOT_EQUAL, STAT_ATK, 12, BattleScript_DecorateBoost - jumpifstat BS_TARGET, CMP_NOT_EQUAL, STAT_SPATK, 12, BattleScript_DecorateBoost + accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE + jumpifstat BS_TARGET, CMP_NOT_EQUAL, STAT_ATK, MAX_STAT_STAGE, BattleScript_DecorateBoost + jumpifstat BS_TARGET, CMP_NOT_EQUAL, STAT_SPATK, MAX_STAT_STAGE, BattleScript_DecorateBoost goto BattleScript_ButItFailed BattleScript_DecorateBoost: attackanimation @@ -1000,8 +889,6 @@ BattleScript_DecorateBoostSpAtk: BattleScript_EffectCoaching:: attackcanceler - attackstring - ppreduce jumpifnoally BS_ATTACKER, BattleScript_ButItFailed copybyte gBattlerTarget, gBattlerAttacker setallytonexttarget EffectCoaching_CheckAllyStats @@ -1029,8 +916,6 @@ BattleScript_CoachingBoostDef: BattleScript_EffectJungleHealing:: attackcanceler - attackstring - ppreduce jumpifteamhealthy BattleScript_ButItFailed attackanimation waitanimation @@ -1039,9 +924,8 @@ BattleScript_EffectJungleHealing:: JungleHealing_RestoreTargetHealth: copybyte gBattlerAttacker, gBattlerTarget tryhealquarterhealth BS_TARGET, BattleScript_JungleHealing_TryCureStatus - orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE - healthbarupdate BS_TARGET - datahpupdate BS_TARGET + healthbarupdate BS_TARGET, PASSIVE_HP_UPDATE + datahpupdate BS_TARGET, PASSIVE_HP_UPDATE printstring STRINGID_PKMNREGAINEDHEALTH waitmessage B_WAIT_TIME_LONG BattleScript_JungleHealing_TryCureStatus: @@ -1061,8 +945,6 @@ BattleScript_JungleHealingTryRestoreAlly: BattleScript_EffectLifeDew:: attackcanceler - attackstring - ppreduce jumpiffullhp BS_ATTACKER, BattleScript_EffectLifeDewCheckPartner copybyte gBattlerTarget, gBattlerAttacker attackanimation @@ -1084,19 +966,16 @@ BattleScript_EffectLifeDewCheckPartner: setallytonexttarget BattleScript_EffectLifeDewNextTarget BattleScript_EffectLifeDewHealing: - orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE tryhealquarterhealth BS_TARGET, BattleScript_EffectLifeDewEnd - healthbarupdate BS_TARGET - datahpupdate BS_TARGET + healthbarupdate BS_TARGET, PASSIVE_HP_UPDATE + datahpupdate BS_TARGET, PASSIVE_HP_UPDATE printstring STRINGID_PKMNREGAINEDHEALTH waitmessage B_WAIT_TIME_LONG return BattleScript_EffectAllySwitch:: attackcanceler - accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE - attackstring - ppreduce + accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE tryallyswitch BattleScript_ButItFailed attackanimation waitanimation @@ -1108,9 +987,7 @@ BattleScript_EffectAllySwitch:: BattleScript_EffectFairyLock:: attackcanceler - accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE - attackstring - ppreduce + accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE trysetfairylock BattleScript_ButItFailed attackanimation waitanimation @@ -1118,14 +995,6 @@ BattleScript_EffectFairyLock:: waitmessage B_WAIT_TIME_LONG goto BattleScript_MoveEnd -BattleScript_FailIfNotArgType:: - attackcanceler - attackstring - ppreduce - jumpifnotcurrentmoveargtype BS_ATTACKER, BattleScript_ButItFailed - accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE - goto BattleScript_HitFromCritCalc - BattleScript_RemoveFireType:: printstring STRINGID_ATTACKERLOSTFIRETYPE waitmessage B_WAIT_TIME_LONG @@ -1148,8 +1017,6 @@ BattleScript_DefDown_Ret: BattleScript_EffectPurify:: attackcanceler - attackstring - ppreduce accuracycheck BattleScript_ButItFailed, NO_ACC_CALC_CHECK_LOCK_ON jumpifstatus BS_TARGET, STATUS1_ANY, BattleScript_PurifyWorks goto BattleScript_ButItFailed @@ -1160,21 +1027,20 @@ BattleScript_PurifyWorks: updatestatusicon BS_TARGET printstring STRINGID_ATTACKERCUREDTARGETSTATUS waitmessage B_WAIT_TIME_LONG - tryhealhalfhealth BattleScript_AlreadyAtFullHp, BS_ATTACKER + tryhealhalfhealth BS_ATTACKER, BattleScript_AlreadyAtFullHp goto BattleScript_RestoreHp BattleScript_EffectStrengthSap:: setstatchanger STAT_ATK, 1, TRUE attackcanceler - jumpifsubstituteblocks BattleScript_FailedFromAtkString - accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE - attackstring - ppreduce + jumpifsubstituteblocks BattleScript_ButItFailed + accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE jumpifstat BS_TARGET, CMP_NOT_EQUAL, STAT_ATK, MIN_STAT_STAGE, BattleScript_StrengthSapTryLower pause B_WAIT_TIME_SHORT statbuffchange BS_TARGET, STAT_CHANGE_ALLOW_PTR, BattleScript_MoveEnd printfromtable gStatDownStringIds waitmessage B_WAIT_TIME_LONG + setmoveresultflags MOVE_RESULT_MISSED @ TODO: Is this even necessary? goto BattleScript_MoveEnd BattleScript_StrengthSapTryLower: getstatvalue STAT_ATK @@ -1183,7 +1049,7 @@ BattleScript_StrengthSapAnimation: attackanimation waitanimation statbuffchange BS_TARGET, STAT_CHANGE_ALLOW_PTR, BattleScript_StrengthSapHp - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_FELL_EMPTY, BattleScript_StrengthSapHp + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_CHANGE_EMPTY, BattleScript_StrengthSapHp printfromtable gStatDownStringIds waitmessage B_WAIT_TIME_LONG @ Drain HP without lowering a stat @@ -1193,10 +1059,9 @@ BattleScript_StrengthSapHp: jumpiffullhp BS_ATTACKER, BattleScript_MoveEnd BattleScript_StrengthSapManipulateDmg: manipulatedamage DMG_BIG_ROOT - orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE jumpifability BS_TARGET, ABILITY_LIQUID_OOZE, BattleScript_StrengthSapLiquidOoze - healthbarupdate BS_ATTACKER - datahpupdate BS_ATTACKER + healthbarupdate BS_ATTACKER, PASSIVE_HP_UPDATE + datahpupdate BS_ATTACKER, PASSIVE_HP_UPDATE printstring STRINGID_PKMNENERGYDRAINED waitmessage B_WAIT_TIME_LONG goto BattleScript_MoveEnd @@ -1204,15 +1069,15 @@ BattleScript_StrengthSapLiquidOoze: call BattleScript_AbilityPopUpTarget manipulatedamage DMG_CHANGE_SIGN setbyte cMULTISTRING_CHOOSER, B_MSG_ABSORB_OOZE - healthbarupdate BS_ATTACKER - datahpupdate BS_ATTACKER + healthbarupdate BS_ATTACKER, PASSIVE_HP_UPDATE + datahpupdate BS_ATTACKER, PASSIVE_HP_UPDATE printfromtable gAbsorbDrainStringIds waitmessage B_WAIT_TIME_LONG tryfaintmon BS_ATTACKER goto BattleScript_MoveEnd BattleScript_StrengthSapMustLower: statbuffchange BS_TARGET, STAT_CHANGE_ALLOW_PTR | STAT_CHANGE_ONLY_CHECKING, BattleScript_MoveEnd - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_FELL_EMPTY, BattleScript_MoveEnd + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_CHANGE_EMPTY, BattleScript_MoveEnd goto BattleScript_StrengthSapAnimation BattleScript_MoveEffectIncinerate:: @@ -1245,8 +1110,6 @@ BattleScript_CoreEnforcerRet: BattleScript_EffectLaserFocus:: attackcanceler - attackstring - ppreduce trysetvolatile BS_ATTACKER, VOLATILE_LASER_FOCUS, BattleScript_ButItFailed attackanimation waitanimation @@ -1261,19 +1124,19 @@ BattleScript_VCreateStatLoss:: BattleScript_VCreateStatAnim: setstatchanger STAT_DEF, 1, TRUE statbuffchange BS_ATTACKER, STAT_CHANGE_NOT_PROTECT_AFFECTED | STAT_CHANGE_CERTAIN, BattleScript_VCreateTrySpDef, BIT_SPDEF | BIT_SPEED - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_DECREASE, BattleScript_VCreateTrySpDef + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_VCreateTrySpDef printfromtable gStatDownStringIds waitmessage B_WAIT_TIME_LONG BattleScript_VCreateTrySpDef: setstatchanger STAT_SPDEF, 1, TRUE statbuffchange BS_ATTACKER, STAT_CHANGE_NOT_PROTECT_AFFECTED | STAT_CHANGE_CERTAIN, BattleScript_VCreateTrySpeed, BIT_SPEED - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_DECREASE, BattleScript_VCreateTrySpeed + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_VCreateTrySpeed printfromtable gStatDownStringIds waitmessage B_WAIT_TIME_LONG BattleScript_VCreateTrySpeed: setstatchanger STAT_SPEED, 1, TRUE statbuffchange BS_ATTACKER, STAT_CHANGE_NOT_PROTECT_AFFECTED | STAT_CHANGE_CERTAIN, BattleScript_VCreateStatLossRet - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_DECREASE, BattleScript_VCreateStatLossRet + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_VCreateStatLossRet printfromtable gStatDownStringIds waitmessage B_WAIT_TIME_LONG BattleScript_VCreateStatLossRet: @@ -1293,9 +1156,7 @@ BattleScript_SpectralThiefSteal:: BattleScript_EffectSpectralThief:: attackcanceler - accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE - attackstring - ppreduce + accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE typecalc tryspectralthiefsteal BattleScript_SpectralThiefSteal BattleScript_EffectSpectralThiefFromDamage: @@ -1309,12 +1170,10 @@ BattleScript_EffectSpectralThiefFromDamage: BattleScript_EffectPartingShot:: attackcanceler - attackstring - ppreduce jumpifstat BS_TARGET, CMP_GREATER_THAN, STAT_ATK, MIN_STAT_STAGE, BattleScript_EffectPartingShotTryAtk jumpifstat BS_TARGET, CMP_EQUAL, STAT_SPATK, MIN_STAT_STAGE, BattleScript_CantLowerMultipleStats BattleScript_EffectPartingShotTryAtk: - accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE + accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE attackanimation waitanimation setstatchanger STAT_ATK, 1, TRUE @@ -1332,9 +1191,7 @@ BattleScript_EffectPartingShotSwitch: BattleScript_EffectPowder:: attackcanceler - accuracycheck BattleScript_PrintMoveMissed, NO_ACC_CALC_CHECK_LOCK_ON - attackstring - ppreduce + accuracycheck BattleScript_MoveMissedPause, NO_ACC_CALC_CHECK_LOCK_ON jumpifvolatile BS_TARGET, VOLATILE_POWDER, BattleScript_ButItFailed setvolatile BS_TARGET, VOLATILE_POWDER attackanimation @@ -1345,8 +1202,6 @@ BattleScript_EffectPowder:: BattleScript_EffectAromaticMist:: attackcanceler - attackstring - ppreduce jumpifbyteequal gBattlerTarget, gBattlerAttacker, BattleScript_ButItFailed jumpiftargetally BattleScript_EffectAromaticMistWorks goto BattleScript_ButItFailed @@ -1364,12 +1219,11 @@ BattleScript_EffectAromaticMistWontGoHigher: pause B_WAIT_TIME_SHORTEST printstring STRINGID_TARGETSTATWONTGOHIGHER waitmessage B_WAIT_TIME_LONG + setmoveresultflags MOVE_RESULT_MISSED @ TODO: Is this even necessary? goto BattleScript_EffectAromaticMistEnd BattleScript_EffectMagneticFlux:: attackcanceler - attackstring - ppreduce setbyte gBattleCommunication, 0 BattleScript_EffectMagneticFluxStart: jumpifability BS_TARGET, ABILITY_MINUS, BattleScript_EffectMagneticFluxCheckStats @@ -1385,14 +1239,14 @@ BattleScript_EffectMagneticFluxTryDef: BattleScript_EffectMagneticFluxSkipAnim: setstatchanger STAT_DEF, 1, FALSE statbuffchange BS_TARGET, STAT_CHANGE_ALLOW_PTR, BattleScript_EffectMagneticFluxTrySpDef, BIT_SPDEF - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_EffectMagneticFluxTrySpDef + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_EffectMagneticFluxTrySpDef addbyte gBattleCommunication, 1 printfromtable gStatUpStringIds waitmessage B_WAIT_TIME_LONG BattleScript_EffectMagneticFluxTrySpDef: setstatchanger STAT_SPDEF, 1, FALSE statbuffchange BS_TARGET, STAT_CHANGE_ALLOW_PTR, BattleScript_EffectMagneticFluxLoop - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_EffectMagneticFluxLoop + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_EffectMagneticFluxLoop addbyte gBattleCommunication, 1 printfromtable gStatUpStringIds waitmessage B_WAIT_TIME_LONG @@ -1405,8 +1259,6 @@ BattleScript_EffectMagneticFluxEnd: BattleScript_EffectGearUp:: attackcanceler - attackstring - ppreduce setbyte gBattleCommunication, 0 BattleScript_EffectGearUpStart: jumpifability BS_TARGET, ABILITY_MINUS, BattleScript_EffectGearUpCheckStats @@ -1422,14 +1274,14 @@ BattleScript_EffectGearUpTryAtk: BattleScript_EffectGearUpSkipAnim: setstatchanger STAT_ATK, 1, FALSE statbuffchange BS_TARGET, STAT_CHANGE_ALLOW_PTR, BattleScript_EffectGearUpTrySpAtk, BIT_SPATK - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_EffectGearUpTrySpAtk + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_EffectGearUpTrySpAtk addbyte gBattleCommunication, 1 printfromtable gStatUpStringIds waitmessage B_WAIT_TIME_LONG BattleScript_EffectGearUpTrySpAtk: setstatchanger STAT_SPATK, 1, FALSE statbuffchange BS_TARGET, STAT_CHANGE_ALLOW_PTR, BattleScript_EffectGearUpLoop - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_EffectGearUpLoop + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_EffectGearUpLoop addbyte gBattleCommunication, 1 printfromtable gStatUpStringIds waitmessage B_WAIT_TIME_LONG @@ -1443,10 +1295,8 @@ BattleScript_EffectGearUpEnd: BattleScript_EffectAcupressure:: attackcanceler jumpifbyteequal gBattlerTarget, gBattlerAttacker, BattleScript_EffectAcupressureTry - jumpifvolatile BS_TARGET, VOLATILE_SUBSTITUTE, BattleScript_PrintMoveMissed + jumpifvolatile BS_TARGET, VOLATILE_SUBSTITUTE, BattleScript_MoveMissedPause BattleScript_EffectAcupressureTry: - attackstring - ppreduce tryacupressure BattleScript_ButItFailed attackanimation waitanimation @@ -1462,9 +1312,7 @@ BattleScript_MoveEffectFeint:: BattleScript_EffectThirdType:: attackcanceler - accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE - attackstring - ppreduce + accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE trythirdtype BattleScript_ButItFailed attackanimation waitanimation @@ -1474,8 +1322,6 @@ BattleScript_EffectThirdType:: BattleScript_EffectFlowerShield:: attackcanceler - attackstring - ppreduce savetarget selectfirstvalidtarget BattleScript_FlowerShieldIsAnyValidTarget: @@ -1494,8 +1340,8 @@ BattleScript_FlowerShieldLoop: BattleScript_FlowerShieldLoop2: setstatchanger STAT_DEF, 1, FALSE statbuffchange BS_TARGET, STAT_CHANGE_ALLOW_PTR | STAT_CHANGE_ONLY_CHECKING, BattleScript_FlowerShieldMoveTargetEnd - jumpifbyte CMP_LESS_THAN, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_FlowerShieldDoAnim - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_ROSE_EMPTY, BattleScript_FlowerShieldMoveTargetEnd + jumpifbyte CMP_LESS_THAN, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_FlowerShieldDoAnim + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_CHANGE_EMPTY, BattleScript_FlowerShieldMoveTargetEnd pause 21 goto BattleScript_FlowerShieldString BattleScript_FlowerShieldDoAnim: @@ -1509,13 +1355,11 @@ BattleScript_FlowerShieldMoveTargetEnd: moveendto MOVEEND_NEXT_TARGET jumpifnexttargetvalid BattleScript_FlowerShieldLoop restoretarget - moveendfrom MOVEEND_ITEM_EFFECTS_ATTACKER + moveendfrom MOVEEND_ITEM_EFFECTS_ATTACKER_1 end BattleScript_EffectRototiller:: attackcanceler - attackstring - ppreduce getrototillertargets BattleScript_ButItFailed @ at least one battler is affected attackanimation @@ -1530,13 +1374,13 @@ BattleScript_RototillerCheckAffected: jumpifnotrototilleraffected BattleScript_RototillerNoEffect setstatchanger STAT_ATK, 1, FALSE statbuffchange BS_TARGET, STAT_CHANGE_ALLOW_PTR, BattleScript_RototillerTrySpAtk, BIT_SPATK - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_RototillerTrySpAtk + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_RototillerTrySpAtk printfromtable gStatUpStringIds waitmessage B_WAIT_TIME_LONG BattleScript_RototillerTrySpAtk:: setstatchanger STAT_SPATK, 1, FALSE statbuffchange BS_TARGET, STAT_CHANGE_ALLOW_PTR, BattleScript_RototillerMoveTargetEnd - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_RototillerMoveTargetEnd + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_RototillerMoveTargetEnd printfromtable gStatUpStringIds waitmessage B_WAIT_TIME_LONG BattleScript_RototillerMoveTargetEnd: @@ -1560,23 +1404,20 @@ BattleScript_RototillerNoEffect: BattleScript_EffectBestow:: attackcanceler - accuracycheck BattleScript_PrintMoveMissed, NO_ACC_CALC_CHECK_LOCK_ON - attackstring - ppreduce + accuracycheck BattleScript_MoveMissedPause, NO_ACC_CALC_CHECK_LOCK_ON jumpifsubstituteblocks BattleScript_ButItFailed trybestow BattleScript_ButItFailed attackanimation waitanimation printstring STRINGID_BESTOWITEMGIVING waitmessage B_WAIT_TIME_LONG + tryactivateitem BS_TARGET, ACTIVATION_ON_USABLE_AGAIN trysymbiosis BS_ATTACKER goto BattleScript_MoveEnd BattleScript_EffectAfterYou:: attackcanceler - accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE - attackstring - ppreduce + accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE tryafteryou BattleScript_ButItFailed attackanimation waitanimation @@ -1587,17 +1428,14 @@ BattleScript_EffectAfterYou:: BattleScript_MoveEffectFlameBurst:: printstring STRINGID_BURSTINGFLAMESHIT waitmessage B_WAIT_TIME_LONG - orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_HP_UPDATE - healthbarupdate BS_SCRIPTING - datahpupdate BS_SCRIPTING + healthbarupdate BS_SCRIPTING, PASSIVE_HP_UPDATE + datahpupdate BS_SCRIPTING, PASSIVE_HP_UPDATE tryfaintmon BS_SCRIPTING return BattleScript_EffectPowerTrick:: attackcanceler - accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE - attackstring - ppreduce + accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE powertrick attackanimation waitanimation @@ -1607,9 +1445,7 @@ BattleScript_EffectPowerTrick:: BattleScript_EffectPsychoShift:: attackcanceler - accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE - attackstring - ppreduce + accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE jumpifstatus BS_ATTACKER, STATUS1_ANY, BattleScript_EffectPsychoShiftCanWork goto BattleScript_ButItFailed BattleScript_EffectPsychoShiftCanWork: @@ -1631,9 +1467,7 @@ BattleScript_EffectPsychoShiftCanWork: BattleScript_EffectSynchronoise:: attackcanceler - attackstring pause B_WAIT_TIME_MED - ppreduce trysynchronoise BattleScript_MoveEnd accuracycheck BattleScript_ButItFailed, ACC_CURR_MOVE goto BattleScript_HitFromCritCalc @@ -1659,23 +1493,29 @@ BattleScript_EffectHitEnemyHealAlly:: BattleScript_EffectDefog:: setstatchanger STAT_EVASION, 1, TRUE attackcanceler + jumpifgenconfiglowerthan CONFIG_DEFOG_EFFECT_CLEARING, GEN_5, BattleScript_DefogAfterSubstituteCheck jumpifsubstituteblocks BattleScript_DefogIfCanClearHazards +BattleScript_DefogAfterSubstituteCheck: jumpifstat BS_TARGET, CMP_NOT_EQUAL, STAT_EVASION, MIN_STAT_STAGE, BattleScript_DefogWorks BattleScript_DefogIfCanClearHazards: - trydefog FALSE, BattleScript_FailedFromAtkString + trydefog FALSE, BattleScript_ButItFailed BattleScript_DefogWorks: - accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE - attackstring - ppreduce + accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE + jumpifgenconfiglowerthan CONFIG_DEFOG_EFFECT_CLEARING, GEN_5, BattleScript_DefogWorksAfterSubstituteCheck + jumpifsubstituteblocks BattleScript_DefogTryHazardsWithAnim +BattleScript_DefogWorksAfterSubstituteCheck: statbuffchange BS_TARGET, STAT_CHANGE_ALLOW_PTR | STAT_CHANGE_ONLY_CHECKING, BattleScript_DefogTryHazardsWithAnim - jumpifbyte CMP_LESS_THAN, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_DECREASE, BattleScript_DefogDoAnim - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_FELL_EMPTY, BattleScript_DefogTryHazardsWithAnim + jumpifbyte CMP_LESS_THAN, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_DefogDoAnim + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_CHANGE_EMPTY, BattleScript_DefogTryHazardsWithAnim pause B_WAIT_TIME_SHORT + setmoveresultflags MOVE_RESULT_MISSED @ TODO: Is this even necessary? goto BattleScript_DefogPrintString BattleScript_DefogDoAnim:: attackanimation waitanimation + call BattleScript_SwapFromSubstitute statbuffchange BS_TARGET, STAT_CHANGE_ALLOW_PTR, BattleScript_DefogTryHazards + call BattleScript_SwapToSubstitute BattleScript_DefogPrintString:: printfromtable gStatDownStringIds waitmessage B_WAIT_TIME_LONG @@ -1695,23 +1535,9 @@ BattleScript_MoveEffectDefog:: restoreattacker return -BattleScript_EffectCopycat:: - attackcanceler - attackstring - pause 5 - trycopycat BattleScript_CopycatFail - attackanimation - waitanimation - jumptocalledmove TRUE -BattleScript_CopycatFail: - ppreduce - goto BattleScript_ButItFailed - BattleScript_EffectInstruct:: attackcanceler - attackstring - ppreduce - pause 5 + pause B_WAIT_TIME_SHORT tryinstruct BattleScript_ButItFailed attackanimation waitanimation @@ -1724,10 +1550,8 @@ BattleScript_EffectInstruct:: BattleScript_EffectAutotomize:: setstatchanger STAT_SPEED, 2, FALSE attackcanceler - attackstring - ppreduce statbuffchange BS_ATTACKER, STAT_CHANGE_ALLOW_PTR | STAT_CHANGE_ONLY_CHECKING, BattleScript_AutotomizeWeightLoss - jumpifbyte CMP_NOT_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_AutotomizeAttackAnim + jumpifbyte CMP_NOT_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_AutotomizeAttackAnim pause B_WAIT_TIME_SHORT goto BattleScript_AutotomizePrintString BattleScript_AutotomizeAttackAnim:: @@ -1746,8 +1570,8 @@ BattleScript_AutotomizeWeightLoss:: BattleScript_FinalGambit:: setatkhptozero - healthbarupdate BS_ATTACKER - datahpupdate BS_ATTACKER + healthbarupdate BS_ATTACKER, PASSIVE_HP_UPDATE + datahpupdate BS_ATTACKER, PASSIVE_HP_UPDATE tryfaintmon BS_ATTACKER return @@ -1765,17 +1589,15 @@ BattleScript_HitSwitchTargetForceRandomSwitchFailed: BattleScript_EffectToxicThread:: setstatchanger STAT_SPEED, 1, TRUE attackcanceler - jumpifsubstituteblocks BattleScript_FailedFromAtkString + jumpifsubstituteblocks BattleScript_ButItFailed checknonvolatiletrigger MOVE_EFFECT_POISON, BattleScript_EffectStatDownFromAccCheck - accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE - attackstring - ppreduce + accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE attackanimation waitanimation setstatchanger STAT_SPEED, 1, TRUE statbuffchange BS_TARGET, STAT_CHANGE_ALLOW_PTR | STAT_CHANGE_ONLY_CHECKING, BattleScript_ToxicThreadTryPsn - jumpifbyte CMP_LESS_THAN, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_DECREASE, BattleScript_ToxicThreadDoAnim - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_FELL_EMPTY, BattleScript_ToxicThreadTryPsn + jumpifbyte CMP_LESS_THAN, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_ToxicThreadDoAnim + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_CHANGE_EMPTY, BattleScript_ToxicThreadTryPsn pause B_WAIT_TIME_SHORT goto BattleScript_ToxicThreadPrintString BattleScript_ToxicThreadDoAnim:: @@ -1789,8 +1611,6 @@ BattleScript_ToxicThreadTryPsn:: BattleScript_EffectVenomDrench:: attackcanceler - attackstring - ppreduce jumpifstatus BS_TARGET, STATUS1_PSN_ANY, BattleScript_EffectVenomDrenchCanBeUsed goto BattleScript_ButItFailed BattleScript_EffectVenomDrenchCanBeUsed: @@ -1803,19 +1623,19 @@ BattleScript_VenomDrenchDoMoveAnim:: waitanimation setstatchanger STAT_ATK, 1, TRUE statbuffchange BS_TARGET, STAT_CHANGE_ALLOW_PTR, BattleScript_VenomDrenchTryLowerSpAtk, BIT_SPATK | BIT_SPEED - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_DECREASE, BattleScript_VenomDrenchTryLowerSpAtk + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_VenomDrenchTryLowerSpAtk printfromtable gStatDownStringIds waitmessage B_WAIT_TIME_LONG BattleScript_VenomDrenchTryLowerSpAtk:: setstatchanger STAT_SPATK, 1, TRUE statbuffchange BS_TARGET, STAT_CHANGE_ALLOW_PTR, BattleScript_VenomDrenchTryLowerSpeed, BIT_SPEED - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_DECREASE, BattleScript_VenomDrenchTryLowerSpeed + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_VenomDrenchTryLowerSpeed printfromtable gStatDownStringIds waitmessage B_WAIT_TIME_LONG BattleScript_VenomDrenchTryLowerSpeed:: setstatchanger STAT_SPEED, 1, TRUE statbuffchange BS_TARGET, STAT_CHANGE_ALLOW_PTR, BattleScript_VenomDrenchEnd - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_DECREASE, BattleScript_VenomDrenchEnd + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_VenomDrenchEnd printfromtable gStatDownStringIds waitmessage B_WAIT_TIME_LONG BattleScript_VenomDrenchEnd:: @@ -1823,8 +1643,6 @@ BattleScript_VenomDrenchEnd:: BattleScript_EffectNobleRoar:: attackcanceler - attackstring - ppreduce jumpifstat BS_TARGET, CMP_GREATER_THAN, STAT_ATK, MIN_STAT_STAGE, BattleScript_NobleRoarDoMoveAnim jumpifstat BS_TARGET, CMP_EQUAL, STAT_SPATK, MIN_STAT_STAGE, BattleScript_CantLowerMultipleStats BattleScript_NobleRoarDoMoveAnim:: @@ -1833,13 +1651,13 @@ BattleScript_NobleRoarDoMoveAnim:: waitanimation setstatchanger STAT_ATK, 1, TRUE statbuffchange BS_TARGET, STAT_CHANGE_ALLOW_PTR, BattleScript_NobleRoarTryLowerSpAtk, BIT_SPATK - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_DECREASE, BattleScript_NobleRoarTryLowerSpAtk + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_NobleRoarTryLowerSpAtk printfromtable gStatDownStringIds waitmessage B_WAIT_TIME_LONG BattleScript_NobleRoarTryLowerSpAtk:: setstatchanger STAT_SPATK, 1, TRUE statbuffchange BS_TARGET, STAT_CHANGE_ALLOW_PTR, BattleScript_NobleRoarEnd - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_DECREASE, BattleScript_NobleRoarEnd + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_NobleRoarEnd printfromtable gStatDownStringIds waitmessage B_WAIT_TIME_LONG BattleScript_NobleRoarEnd:: @@ -1847,8 +1665,6 @@ BattleScript_NobleRoarEnd:: BattleScript_EffectShellSmash:: attackcanceler - attackstring - ppreduce jumpifstat BS_ATTACKER, CMP_LESS_THAN, STAT_ATK, MAX_STAT_STAGE, BattleScript_ShellSmashTryDef jumpifstat BS_ATTACKER, CMP_LESS_THAN, STAT_SPATK, MAX_STAT_STAGE, BattleScript_ShellSmashTryDef jumpifstat BS_ATTACKER, CMP_LESS_THAN, STAT_SPEED, MAX_STAT_STAGE, BattleScript_ShellSmashTryDef @@ -1859,48 +1675,38 @@ BattleScript_ShellSmashTryDef:: waitanimation setstatchanger STAT_DEF, 1, TRUE statbuffchange BS_ATTACKER, STAT_CHANGE_ALLOW_PTR | STAT_CHANGE_CERTAIN, BattleScript_ShellSmashTrySpDef, BIT_SPDEF - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_ShellSmashTrySpDef + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_ShellSmashTrySpDef printfromtable gStatUpStringIds waitmessage B_WAIT_TIME_LONG BattleScript_ShellSmashTrySpDef: setstatchanger STAT_SPDEF, 1, TRUE statbuffchange BS_ATTACKER, STAT_CHANGE_ALLOW_PTR | STAT_CHANGE_CERTAIN, BattleScript_ShellSmashTryAttack - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_ShellSmashTryAttack + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_ShellSmashTryAttack printfromtable gStatUpStringIds waitmessage B_WAIT_TIME_LONG BattleScript_ShellSmashTryAttack: setstatchanger STAT_ATK, 2, FALSE statbuffchange BS_ATTACKER, STAT_CHANGE_ALLOW_PTR, BattleScript_ShellSmashTrySpAtk, BIT_SPATK | BIT_SPEED, - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_ShellSmashTrySpAtk + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_ShellSmashTrySpAtk printfromtable gStatUpStringIds waitmessage B_WAIT_TIME_LONG BattleScript_ShellSmashTrySpAtk: setstatchanger STAT_SPATK, 2, FALSE statbuffchange BS_ATTACKER, STAT_CHANGE_ALLOW_PTR, BattleScript_ShellSmashTrySpeed, BIT_SPEED - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_ShellSmashTrySpeed + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_ShellSmashTrySpeed printfromtable gStatUpStringIds waitmessage B_WAIT_TIME_LONG BattleScript_ShellSmashTrySpeed: setstatchanger STAT_SPEED, 2, FALSE statbuffchange BS_ATTACKER, STAT_CHANGE_ALLOW_PTR, BattleScript_ShellSmashEnd - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_ShellSmashEnd + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_ShellSmashEnd printfromtable gStatUpStringIds waitmessage B_WAIT_TIME_LONG BattleScript_ShellSmashEnd: goto BattleScript_MoveEnd -BattleScript_EffectLastResort:: - attackcanceler - attackstring - ppreduce - trylastresort BattleScript_ButItFailed - accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE - goto BattleScript_HitFromCritCalc - BattleScript_EffectGrowth:: attackcanceler - attackstring - ppreduce jumpifstat BS_ATTACKER, CMP_LESS_THAN, STAT_ATK, MAX_STAT_STAGE, BattleScript_GrowthDoMoveAnim jumpifstat BS_ATTACKER, CMP_EQUAL, STAT_SPATK, MAX_STAT_STAGE, BattleScript_CantRaiseMultipleStats BattleScript_GrowthDoMoveAnim:: @@ -1913,7 +1719,7 @@ BattleScript_GrowthAtk2: setstatchanger STAT_ATK, 2, FALSE BattleScript_GrowthAtk: statbuffchange BS_ATTACKER, STAT_CHANGE_ALLOW_PTR, BattleScript_GrowthTrySpAtk, BIT_SPATK - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_GrowthTrySpAtk + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_GrowthTrySpAtk printfromtable gStatUpStringIds waitmessage B_WAIT_TIME_LONG BattleScript_GrowthTrySpAtk:: @@ -1924,7 +1730,7 @@ BattleScript_GrowthSpAtk2: setstatchanger STAT_SPATK, 2, FALSE BattleScript_GrowthSpAtk: statbuffchange BS_ATTACKER, STAT_CHANGE_ALLOW_PTR, BattleScript_GrowthEnd - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_GrowthEnd + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_GrowthEnd printfromtable gStatUpStringIds waitmessage B_WAIT_TIME_LONG BattleScript_GrowthEnd: @@ -1932,9 +1738,7 @@ BattleScript_GrowthEnd: BattleScript_EffectSoak:: attackcanceler - accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE - attackstring - ppreduce + accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE jumpifability BS_TARGET, ABILITY_MULTITYPE, BattleScript_ButItFailed jumpifability BS_TARGET, ABILITY_RKS_SYSTEM, BattleScript_ButItFailed jumpifsubstituteblocks BattleScript_ButItFailed @@ -1947,9 +1751,7 @@ BattleScript_EffectSoak:: BattleScript_EffectReflectType:: attackcanceler - accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE - attackstring - ppreduce + accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE tryreflecttype BattleScript_ButItFailed attackanimation waitanimation @@ -1959,9 +1761,7 @@ BattleScript_EffectReflectType:: BattleScript_EffectElectrify:: attackcanceler - accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE - attackstring - ppreduce + accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE tryelectrify BattleScript_ButItFailed attackanimation waitanimation @@ -1971,8 +1771,6 @@ BattleScript_EffectElectrify:: BattleScript_EffectShiftGear:: attackcanceler - attackstring - ppreduce jumpifstat BS_ATTACKER, CMP_LESS_THAN, STAT_SPEED, MAX_STAT_STAGE, BattleScript_ShiftGearDoMoveAnim jumpifstat BS_ATTACKER, CMP_EQUAL, STAT_ATK, MAX_STAT_STAGE, BattleScript_CantRaiseMultipleStats BattleScript_ShiftGearDoMoveAnim: @@ -1985,13 +1783,13 @@ BattleScript_ShiftGearSpeedBy1: setstatchanger STAT_SPEED, 1, FALSE BattleScript_ShiftGearDoSpeed: statbuffchange BS_ATTACKER, STAT_CHANGE_ALLOW_PTR, BattleScript_ShiftGearTryAtk, BIT_ATK - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_ShiftGearTryAtk + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_ShiftGearTryAtk printfromtable gStatUpStringIds waitmessage B_WAIT_TIME_LONG BattleScript_ShiftGearTryAtk: setstatchanger STAT_ATK, 1, FALSE statbuffchange BS_ATTACKER, STAT_CHANGE_ALLOW_PTR, BattleScript_ShiftGearEnd - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_ShiftGearEnd + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_ShiftGearEnd printfromtable gStatUpStringIds waitmessage B_WAIT_TIME_LONG BattleScript_ShiftGearEnd: @@ -1999,8 +1797,6 @@ BattleScript_ShiftGearEnd: BattleScript_EffectCoil:: attackcanceler - attackstring - ppreduce jumpifstat BS_ATTACKER, CMP_LESS_THAN, STAT_ATK, MAX_STAT_STAGE, BattleScript_CoilDoMoveAnim jumpifstat BS_ATTACKER, CMP_LESS_THAN, STAT_DEF, MAX_STAT_STAGE, BattleScript_CoilDoMoveAnim jumpifstat BS_ATTACKER, CMP_EQUAL, STAT_ACC, MAX_STAT_STAGE, BattleScript_CantRaiseMultipleStats @@ -2009,19 +1805,19 @@ BattleScript_CoilDoMoveAnim: waitanimation setstatchanger STAT_ATK, 1, FALSE statbuffchange BS_ATTACKER, STAT_CHANGE_ALLOW_PTR, BattleScript_CoilTryDef, BIT_DEF | BIT_ACC - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_CoilTryDef + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_CoilTryDef printfromtable gStatUpStringIds waitmessage B_WAIT_TIME_LONG BattleScript_CoilTryDef: setstatchanger STAT_DEF, 1, FALSE statbuffchange BS_ATTACKER, STAT_CHANGE_ALLOW_PTR, BattleScript_CoilTryAcc, BIT_ACC - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_CoilTryAcc + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_CoilTryAcc printfromtable gStatUpStringIds waitmessage B_WAIT_TIME_LONG BattleScript_CoilTryAcc: setstatchanger STAT_ACC, 1, FALSE statbuffchange BS_ATTACKER, STAT_CHANGE_ALLOW_PTR, BattleScript_CoilEnd - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_CoilEnd + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_CoilEnd printfromtable gStatUpStringIds waitmessage B_WAIT_TIME_LONG BattleScript_CoilEnd: @@ -2029,8 +1825,6 @@ BattleScript_CoilEnd: BattleScript_EffectQuiverDance:: attackcanceler - attackstring - ppreduce jumpifstat BS_ATTACKER, CMP_LESS_THAN, STAT_SPATK, MAX_STAT_STAGE, BattleScript_QuiverDanceDoMoveAnim jumpifstat BS_ATTACKER, CMP_LESS_THAN, STAT_SPDEF, MAX_STAT_STAGE, BattleScript_QuiverDanceDoMoveAnim jumpifstat BS_ATTACKER, CMP_EQUAL, STAT_SPEED, MAX_STAT_STAGE, BattleScript_CantRaiseMultipleStats @@ -2039,19 +1833,19 @@ BattleScript_QuiverDanceDoMoveAnim:: waitanimation setstatchanger STAT_SPATK, 1, FALSE statbuffchange BS_ATTACKER, STAT_CHANGE_ALLOW_PTR, BattleScript_QuiverDanceTrySpDef, BIT_SPDEF | BIT_SPEED - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_QuiverDanceTrySpDef + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_QuiverDanceTrySpDef printfromtable gStatUpStringIds waitmessage B_WAIT_TIME_LONG BattleScript_QuiverDanceTrySpDef:: setstatchanger STAT_SPDEF, 1, FALSE statbuffchange BS_ATTACKER, STAT_CHANGE_ALLOW_PTR, BattleScript_QuiverDanceTrySpeed, BIT_SPEED - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_QuiverDanceTrySpeed + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_QuiverDanceTrySpeed printfromtable gStatUpStringIds waitmessage B_WAIT_TIME_LONG BattleScript_QuiverDanceTrySpeed:: setstatchanger STAT_SPEED, 1, FALSE statbuffchange BS_ATTACKER, STAT_CHANGE_ALLOW_PTR, BattleScript_QuiverDanceEnd - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_QuiverDanceEnd + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_QuiverDanceEnd printfromtable gStatUpStringIds waitmessage B_WAIT_TIME_LONG BattleScript_QuiverDanceEnd:: @@ -2059,8 +1853,6 @@ BattleScript_QuiverDanceEnd:: BattleScript_EffectVictoryDance:: attackcanceler - attackstring - ppreduce jumpifstat BS_ATTACKER, CMP_LESS_THAN, STAT_ATK, MAX_STAT_STAGE, BattleScript_VictoryDanceDoMoveAnim jumpifstat BS_ATTACKER, CMP_LESS_THAN, STAT_DEF, MAX_STAT_STAGE, BattleScript_VictoryDanceDoMoveAnim jumpifstat BS_ATTACKER, CMP_EQUAL, STAT_SPEED, MAX_STAT_STAGE, BattleScript_CantRaiseMultipleStats @@ -2069,36 +1861,26 @@ BattleScript_VictoryDanceDoMoveAnim:: waitanimation setstatchanger STAT_ATK, 1, FALSE statbuffchange BS_ATTACKER, STAT_CHANGE_ALLOW_PTR, BattleScript_VictoryDanceTryDef, BIT_DEF | BIT_SPEED - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_VictoryDanceTryDef + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_VictoryDanceTryDef printfromtable gStatUpStringIds waitmessage B_WAIT_TIME_LONG BattleScript_VictoryDanceTryDef:: setstatchanger STAT_DEF, 1, FALSE statbuffchange BS_ATTACKER, STAT_CHANGE_ALLOW_PTR, BattleScript_VictoryDanceTrySpeed, BIT_SPEED - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_VictoryDanceTrySpeed + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_VictoryDanceTrySpeed printfromtable gStatUpStringIds waitmessage B_WAIT_TIME_LONG BattleScript_VictoryDanceTrySpeed:: setstatchanger STAT_SPEED, 1, FALSE statbuffchange BS_ATTACKER, STAT_CHANGE_ALLOW_PTR, BattleScript_VictoryDanceEnd - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_VictoryDanceEnd + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_VictoryDanceEnd printfromtable gStatUpStringIds waitmessage B_WAIT_TIME_LONG BattleScript_VictoryDanceEnd:: goto BattleScript_MoveEnd -BattleScript_EffectMeFirst:: - attackcanceler - attackstring - trymefirst BattleScript_FailedFromPpReduce - attackanimation - waitanimation - jumptocalledmove TRUE - BattleScript_EffectAttackSpAttackUp:: attackcanceler - attackstring - ppreduce jumpifstat BS_ATTACKER, CMP_LESS_THAN, STAT_ATK, MAX_STAT_STAGE, BattleScript_AttackSpAttackUpDoMoveAnim jumpifstat BS_ATTACKER, CMP_EQUAL, STAT_SPATK, MAX_STAT_STAGE, BattleScript_CantRaiseMultipleStats BattleScript_AttackSpAttackUpDoMoveAnim:: @@ -2106,13 +1888,13 @@ BattleScript_AttackSpAttackUpDoMoveAnim:: waitanimation setstatchanger STAT_ATK, 1, FALSE statbuffchange BS_ATTACKER, STAT_CHANGE_ALLOW_PTR, BattleScript_AttackSpAttackUpTrySpAtk, BIT_SPATK - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_AttackSpAttackUpTrySpAtk + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_AttackSpAttackUpTrySpAtk printfromtable gStatUpStringIds waitmessage B_WAIT_TIME_LONG BattleScript_AttackSpAttackUpTrySpAtk:: setstatchanger STAT_SPATK, 1, FALSE statbuffchange BS_ATTACKER, STAT_CHANGE_ALLOW_PTR, BattleScript_AttackSpAttackUpEnd - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_AttackSpAttackUpEnd + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_AttackSpAttackUpEnd printfromtable gStatUpStringIds waitmessage B_WAIT_TIME_LONG BattleScript_AttackSpAttackUpEnd: @@ -2120,8 +1902,6 @@ BattleScript_AttackSpAttackUpEnd: BattleScript_EffectAttackAccUp:: attackcanceler - attackstring - ppreduce jumpifstat BS_ATTACKER, CMP_LESS_THAN, STAT_ATK, MAX_STAT_STAGE, BattleScript_AttackAccUpDoMoveAnim jumpifstat BS_ATTACKER, CMP_EQUAL, STAT_ACC, MAX_STAT_STAGE, BattleScript_CantRaiseMultipleStats BattleScript_AttackAccUpDoMoveAnim:: @@ -2129,13 +1909,13 @@ BattleScript_AttackAccUpDoMoveAnim:: waitanimation setstatchanger STAT_ATK, 1, FALSE statbuffchange BS_ATTACKER, STAT_CHANGE_ALLOW_PTR, BattleScript_AttackAccUpTryAcc, BIT_ACC - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_AttackAccUpTryAcc + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_AttackAccUpTryAcc printfromtable gStatUpStringIds waitmessage B_WAIT_TIME_LONG BattleScript_AttackAccUpTryAcc:: setstatchanger STAT_ACC, 1, FALSE statbuffchange BS_ATTACKER, STAT_CHANGE_ALLOW_PTR, BattleScript_AttackAccUpEnd - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_AttackAccUpEnd + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_AttackAccUpEnd printfromtable gStatUpStringIds waitmessage B_WAIT_TIME_LONG BattleScript_AttackAccUpEnd: @@ -2146,8 +1926,6 @@ BattleScript_EffectGrassyTerrain:: BattleScript_EffectElectricTerrain:: BattleScript_EffectPsychicTerrain:: attackcanceler - attackstring - ppreduce setterrain BattleScript_ButItFailed attackanimation waitanimation @@ -2159,8 +1937,6 @@ BattleScript_EffectPsychicTerrain:: BattleScript_EffectTopsyTurvy:: attackcanceler - attackstring - ppreduce accuracycheck BattleScript_ButItFailed, NO_ACC_CALC_CHECK_LOCK_ON jumpifstat BS_TARGET, CMP_NOT_EQUAL, STAT_ATK, 6, BattleScript_EffectTopsyTurvyWorks jumpifstat BS_TARGET, CMP_NOT_EQUAL, STAT_DEF, 6, BattleScript_EffectTopsyTurvyWorks @@ -2179,9 +1955,7 @@ BattleScript_EffectTopsyTurvyWorks: BattleScript_EffectIonDeluge:: attackcanceler - accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE - attackstring - ppreduce + accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE orword gFieldStatuses, STATUS_FIELD_ION_DELUGE attackanimation waitanimation @@ -2191,9 +1965,7 @@ BattleScript_EffectIonDeluge:: BattleScript_EffectQuash:: attackcanceler - accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE - attackstring - ppreduce + accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE tryquash BattleScript_ButItFailed attackanimation waitanimation @@ -2203,8 +1975,6 @@ BattleScript_EffectQuash:: BattleScript_EffectHealPulse:: attackcanceler - attackstring - ppreduce jumpifvolatile BS_ATTACKER, VOLATILE_HEAL_BLOCK, BattleScript_MoveUsedHealBlockPrevents @ stops pollen puff jumpifvolatile BS_TARGET, VOLATILE_HEAL_BLOCK, BattleScript_MoveUsedHealBlockPrevents accuracycheck BattleScript_ButItFailed, NO_ACC_CALC_CHECK_LOCK_ON @@ -2212,21 +1982,19 @@ BattleScript_EffectHealPulse:: tryhealpulse BattleScript_AlreadyAtFullHp attackanimation waitanimation - healthbarupdate BS_TARGET - datahpupdate BS_TARGET + healthbarupdate BS_TARGET, PASSIVE_HP_UPDATE + datahpupdate BS_TARGET, PASSIVE_HP_UPDATE printstring STRINGID_PKMNREGAINEDHEALTH waitmessage B_WAIT_TIME_LONG goto BattleScript_MoveEnd BattleScript_EffectEntrainment:: attackcanceler - accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE - attackstring - ppreduce + accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE tryentrainment BattleScript_ButItFailed attackanimation waitanimation - setlastusedability + switchinabilities BS_TARGET printstring STRINGID_PKMNACQUIREDABILITY waitmessage B_WAIT_TIME_LONG trytoclearprimalweather @@ -2235,37 +2003,8 @@ BattleScript_EffectEntrainment:: tryendneutralizinggas goto BattleScript_MoveEnd -BattleScript_EffectSimpleBeam:: - attackcanceler - accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE - attackstring - ppreduce - setsimplebeam BattleScript_ButItFailed - attackanimation - waitanimation -.if B_ABILITY_POP_UP == TRUE - copybyte gBattlerAbility, gBattlerTarget - call BattleScript_AbilityPopUpOverwriteThenNormal -.endif - recordability BS_TARGET - printstring STRINGID_PKMNACQUIREDSIMPLE - waitmessage B_WAIT_TIME_LONG - trytoclearprimalweather - tryrevertweatherform - flushtextbox - tryendneutralizinggas - goto BattleScript_MoveEnd - -BattleScript_EffectSuckerPunch:: - attackcanceler - suckerpunchcheck BattleScript_FailedFromAtkString - accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE - goto BattleScript_HitFromAtkString - BattleScript_EffectLuckyChant:: attackcanceler - attackstring - ppreduce setluckychant BattleScript_ButItFailed attackanimation waitanimation @@ -2275,10 +2014,8 @@ BattleScript_EffectLuckyChant:: BattleScript_EffectMetalBurst:: attackcanceler - metalburstdamagecalculator BattleScript_FailedFromAtkString - accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE - attackstring - ppreduce + metalburstdamagecalculator BattleScript_ButItFailed + accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE typecalc clearmoveresultflags MOVE_RESULT_NOT_VERY_EFFECTIVE | MOVE_RESULT_SUPER_EFFECTIVE adjustdamage @@ -2286,16 +2023,14 @@ BattleScript_EffectMetalBurst:: BattleScript_EffectHealingWish:: attackcanceler - jumpifcantswitch SWITCH_IGNORE_ESCAPE_PREVENTION | BS_ATTACKER, BattleScript_FailedFromAtkString - attackstring - ppreduce + jumpifcantswitch SWITCH_IGNORE_ESCAPE_PREVENTION | BS_ATTACKER, BattleScript_ButItFailed attackanimation waitanimation instanthpdrop setatkhptozero tryfaintmon BS_ATTACKER storehealingwish BS_ATTACKER - jumpifgenconfiglowerthan GEN_CONFIG_HEALING_WISH_SWITCH, GEN_5, BattleScript_EffectHealingWishGen4 + jumpifgenconfiglowerthan CONFIG_HEALING_WISH_SWITCH, GEN_5, BattleScript_EffectHealingWishGen4 BattleScript_EffectHealingWishEnd: moveendall end @@ -2331,8 +2066,8 @@ BattleScript_EffectHealingWishRestore: waitanimation dmgtomaxattackerhp manipulatedamage DMG_CHANGE_SIGN - healthbarupdate BS_ATTACKER - datahpupdate BS_ATTACKER + healthbarupdate BS_ATTACKER, PASSIVE_HP_UPDATE + datahpupdate BS_ATTACKER, PASSIVE_HP_UPDATE clearstatus waitstate updatestatusicon BS_ATTACKER @@ -2341,18 +2076,14 @@ BattleScript_EffectHealingWishRestore: waitmessage B_WAIT_TIME_LONG return -BattleScript_EffectWorrySeed:: +BattleScript_EffectOverwriteAbility:: attackcanceler - accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE - attackstring - ppreduce - tryworryseed BattleScript_ButItFailed + accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE + tryoverwriteability BattleScript_ButItFailed attackanimation waitanimation -.if B_ABILITY_POP_UP == TRUE copybyte gBattlerAbility, gBattlerTarget call BattleScript_AbilityPopUpOverwriteThenNormal -.endif recordability BS_TARGET printstring STRINGID_PKMNACQUIREDABILITY waitmessage B_WAIT_TIME_LONG @@ -2364,8 +2095,6 @@ BattleScript_EffectWorrySeed:: BattleScript_EffectPowerSplit:: attackcanceler - attackstring - ppreduce accuracycheck BattleScript_ButItFailed, NO_ACC_CALC_CHECK_LOCK_ON averagestats STAT_ATK averagestats STAT_SPATK @@ -2377,8 +2106,6 @@ BattleScript_EffectPowerSplit:: BattleScript_EffectGuardSplit:: attackcanceler - attackstring - ppreduce accuracycheck BattleScript_ButItFailed, NO_ACC_CALC_CHECK_LOCK_ON averagestats STAT_DEF averagestats STAT_SPDEF @@ -2390,8 +2117,6 @@ BattleScript_EffectGuardSplit:: BattleScript_EffectHeartSwap:: attackcanceler - attackstring - ppreduce accuracycheck BattleScript_ButItFailed, NO_ACC_CALC_CHECK_LOCK_ON swapstatstages STAT_ATK swapstatstages STAT_DEF @@ -2408,8 +2133,6 @@ BattleScript_EffectHeartSwap:: BattleScript_EffectPowerSwap:: attackcanceler - attackstring - ppreduce accuracycheck BattleScript_ButItFailed, NO_ACC_CALC_CHECK_LOCK_ON swapstatstages STAT_ATK swapstatstages STAT_SPATK @@ -2421,8 +2144,6 @@ BattleScript_EffectPowerSwap:: BattleScript_EffectGuardSwap:: attackcanceler - attackstring - ppreduce accuracycheck BattleScript_ButItFailed, NO_ACC_CALC_CHECK_LOCK_ON swapstatstages STAT_DEF swapstatstages STAT_SPDEF @@ -2434,8 +2155,6 @@ BattleScript_EffectGuardSwap:: BattleScript_EffectSpeedSwap:: attackcanceler - attackstring - ppreduce accuracycheck BattleScript_ButItFailed, NO_ACC_CALC_CHECK_LOCK_ON swapstats STAT_SPEED attackanimation @@ -2446,9 +2165,7 @@ BattleScript_EffectSpeedSwap:: BattleScript_EffectTelekinesis:: attackcanceler - accuracycheck BattleScript_PrintMoveMissed, NO_ACC_CALC_CHECK_LOCK_ON - attackstring - ppreduce + accuracycheck BattleScript_MoveMissedPause, NO_ACC_CALC_CHECK_LOCK_ON settelekinesis BattleScript_ButItFailed attackanimation waitanimation @@ -2458,8 +2175,6 @@ BattleScript_EffectTelekinesis:: BattleScript_EffectStealthRock:: attackcanceler - attackstring - ppreduce setstealthrock BattleScript_ButItFailed attackanimation waitanimation @@ -2469,8 +2184,6 @@ BattleScript_EffectStealthRock:: BattleScript_EffectStickyWeb:: attackcanceler - attackstring - ppreduce setstickyweb BattleScript_ButItFailed attackanimation waitanimation @@ -2480,9 +2193,7 @@ BattleScript_EffectStickyWeb:: BattleScript_EffectGastroAcid:: attackcanceler - accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE - attackstring - ppreduce + accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE jumpifvolatile BS_TARGET, VOLATILE_GASTRO_ACID, BattleScript_ButItFailed setgastroacid BattleScript_ButItFailed attackanimation @@ -2497,8 +2208,6 @@ BattleScript_EffectGastroAcid:: BattleScript_EffectToxicSpikes:: attackcanceler - attackstring - ppreduce settoxicspikes BattleScript_ButItFailed attackanimation waitanimation @@ -2508,8 +2217,6 @@ BattleScript_EffectToxicSpikes:: BattleScript_EffectMagnetRise:: attackcanceler - attackstring - ppreduce jumpifvolatile BS_ATTACKER, VOLATILE_ROOT, BattleScript_ButItFailed jumpifvolatile BS_ATTACKER, VOLATILE_SMACK_DOWN, BattleScript_ButItFailed trysetvolatile BS_ATTACKER, VOLATILE_MAGNET_RISE, BattleScript_ButItFailed @@ -2521,8 +2228,6 @@ BattleScript_EffectMagnetRise:: BattleScript_EffectTrickRoom:: attackcanceler - attackstring - ppreduce setroom attackanimation waitanimation @@ -2547,8 +2252,6 @@ BattleScript_RoomServiceLoop_NextBattler: BattleScript_EffectWonderRoom:: BattleScript_EffectMagicRoom:: attackcanceler - attackstring - ppreduce setroom attackanimation waitanimation @@ -2558,8 +2261,6 @@ BattleScript_EffectMagicRoom:: BattleScript_EffectAquaRing:: attackcanceler - attackstring - ppreduce setvolatile BS_ATTACKER, VOLATILE_AQUA_RING attackanimation waitanimation @@ -2569,9 +2270,7 @@ BattleScript_EffectAquaRing:: BattleScript_EffectEmbargo:: attackcanceler - accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE - attackstring - ppreduce + accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE setembargo BattleScript_ButItFailed attackanimation waitanimation @@ -2581,8 +2280,6 @@ BattleScript_EffectEmbargo:: BattleScript_EffectTailwind:: attackcanceler - attackstring - ppreduce settailwind BattleScript_ButItFailed attackanimation waitanimation @@ -2611,26 +2308,23 @@ BattleScript_TryTailwindAbilitiesLoop_WindRider: BattleScript_TryTailwindAbilitiesLoop_WindPower: call BattleScript_AbilityPopUp - setcharge BS_TARGET + setvolatile BS_TARGET, VOLATILE_CHARGE_TIMER, 2 printstring STRINGID_BEINGHITCHARGEDPKMNWITHPOWER waitmessage B_WAIT_TIME_LONG goto BattleScript_TryTailwindAbilitiesLoop_Increment BattleScript_EffectMiracleEye:: attackcanceler - accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE - attackstring - ppreduce + accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE setvolatile BS_TARGET, VOLATILE_MIRACLE_EYE goto BattleScript_IdentifiedFoe + BattleScript_EffectGravity:: call BattleScript_EffectGravityInternal goto BattleScript_MoveEnd BattleScript_EffectGravityInternal: attackcanceler - attackstring - ppreduce setgravity BattleScript_ButItFailed attackanimation waitanimation @@ -2657,29 +2351,23 @@ BattleScript_GravityLoopEnd: BattleScript_EffectRoost:: attackcanceler - attackstring - ppreduce - tryhealhalfhealth BattleScript_AlreadyAtFullHp, BS_TARGET + tryhealhalfhealth BS_TARGET, BattleScript_AlreadyAtFullHp setroost goto BattleScript_PresentHealTarget BattleScript_EffectCaptivate:: setstatchanger STAT_SPATK, 2, TRUE attackcanceler - attackstring - ppreduce jumpifsubstituteblocks BattleScript_ButItFailed jumpifcaptivateaffected BattleScript_CaptivateCheckAcc goto BattleScript_ButItFailed BattleScript_CaptivateCheckAcc: accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE - goto BattleScript_StatDownFromAttackString + goto BattleScript_EffectStatDownFromStatBuffChange BattleScript_EffectHealBlock:: attackcanceler - accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE - attackstring - ppreduce + accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE jumpifability BS_TARGET_SIDE, ABILITY_AROMA_VEIL, BattleScript_AromaVeilProtects sethealblock BattleScript_ButItFailed attackanimation @@ -2698,8 +2386,6 @@ BattleScript_HitEscapeSwitch: BattleScript_EffectPlaceholder:: attackcanceler - attackstring - ppreduce pause 5 printstring STRINGID_NOTDONEYET goto BattleScript_MoveEnd @@ -2707,10 +2393,7 @@ BattleScript_EffectPlaceholder:: BattleScript_EffectHit:: attackcanceler BattleScript_HitFromAccCheck:: - accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE -BattleScript_HitFromAtkString:: - attackstring - ppreduce + accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE BattleScript_HitFromCritCalc:: critcalc damagecalc @@ -2726,9 +2409,7 @@ BattleScript_MoveEnd:: BattleScript_EffectHit_Ret:: attackcanceler BattleScript_EffectHit_RetFromAccCheck:: - accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE - attackstring - ppreduce + accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE BattleScript_EffectHit_RetFromCritCalc:: critcalc damagecalc @@ -2739,8 +2420,8 @@ BattleScript_Hit_RetFromAtkAnimation:: effectivenesssound hitanimation BS_TARGET waitstate - healthbarupdate BS_TARGET - datahpupdate BS_TARGET + healthbarupdate BS_TARGET, MOVE_DAMAGE_HP_UPDATE + datahpupdate BS_TARGET, MOVE_DAMAGE_HP_UPDATE critmessage waitmessage B_WAIT_TIME_LONG resultmessage @@ -2750,8 +2431,6 @@ BattleScript_Hit_RetFromAtkAnimation:: BattleScript_EffectNaturalGift:: attackcanceler - attackstring - ppreduce jumpifnotberry BS_ATTACKER, BattleScript_ButItFailed jumpifword CMP_COMMON_BITS, gFieldStatuses, STATUS_FIELD_MAGIC_ROOM, BattleScript_ButItFailed jumpifability BS_ATTACKER, ABILITY_KLUTZ, BattleScript_ButItFailed @@ -2761,9 +2440,6 @@ BattleScript_EffectNaturalGift:: BattleScript_MakeMoveMissed:: setmoveresultflags MOVE_RESULT_MISSED -BattleScript_PrintMoveMissed:: - attackstring - ppreduce BattleScript_MoveMissedPause:: pause B_WAIT_TIME_SHORT BattleScript_MoveMissed:: @@ -2781,7 +2457,7 @@ BattleScript_TerrainPreventsEnd2:: BattleScript_ImmunityProtectedEnd2:: call BattleScript_AbilityPopUp pause B_WAIT_TIME_SHORT - printfromtable gStatusPreventionStringIds + printstring STRINGID_ITDOESNTAFFECT waitmessage B_WAIT_TIME_LONG end2 @@ -2835,14 +2511,6 @@ BattleScript_AromaVeilProtects: setmoveresultflags MOVE_RESULT_FAILED goto BattleScript_MoveEnd -BattleScript_PastelVeilProtects: - pause B_WAIT_TIME_SHORT - call BattleScript_AbilityPopUp - printstring STRINGID_PASTELVEILPROTECTED - waitmessage B_WAIT_TIME_LONG - setmoveresultflags MOVE_RESULT_FAILED - goto BattleScript_MoveEnd - BattleScript_AbilityProtectsDoesntAffectRet:: pause B_WAIT_TIME_SHORT call BattleScript_AbilityPopUp @@ -2855,7 +2523,7 @@ BattleScript_AbilityProtectsDoesntAffect:: setmoveresultflags MOVE_RESULT_FAILED goto BattleScript_MoveEnd -BattleScript_InsomniaProtects: +BattleScript_InsomniaProtects:: pause B_WAIT_TIME_SHORT call BattleScript_AbilityPopUp printstring STRINGID_PKMNSTAYEDAWAKEUSING @@ -2884,24 +2552,21 @@ BattleScript_EffectAbsorbLiquidOoze:: goto BattleScript_EffectAbsorb BattleScript_EffectAbsorb:: - absorbhealthbarupdate BS_ATTACKER - datahpupdate BS_ATTACKER + healthbarupdate BS_ATTACKER, PASSIVE_HP_UPDATE + datahpupdate BS_ATTACKER, PASSIVE_HP_UPDATE printfromtable gAbsorbDrainStringIds waitmessage B_WAIT_TIME_LONG tryfaintmon BS_ATTACKER - bicword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_HP_UPDATE | HITMARKER_PASSIVE_HP_UPDATE BattleScript_EffectAbsorbRet: return BattleScript_EffectExplosion:: attackcanceler - attackstring - ppreduce tryexplosion setatkhptozero waitstate jumpiffainted BS_TARGET, TRUE, BattleScript_MoveEnd - accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE + accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE goto BattleScript_HitFromCritCalc BattleScript_FaintAttackerForExplosion:: @@ -2909,30 +2574,20 @@ BattleScript_FaintAttackerForExplosion:: return BattleScript_MaxHp50Recoil:: - orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_HP_UPDATE - healthbarupdate BS_ATTACKER - datahpupdate BS_ATTACKER + healthbarupdate BS_ATTACKER, PASSIVE_HP_UPDATE + datahpupdate BS_ATTACKER, PASSIVE_HP_UPDATE tryfaintmon BS_ATTACKER return BattleScript_EffectDreamEater:: attackcanceler +.if B_DREAM_EATER_SUBSTITUTE < GEN_5 jumpifsubstituteblocks BattleScript_DoesntAffectTargetAtkString +.endif jumpifstatus BS_TARGET, STATUS1_SLEEP, BattleScript_HitFromAccCheck jumpifability BS_TARGET, ABILITY_COMATOSE, BattleScript_HitFromAccCheck goto BattleScript_DoesntAffectTargetAtkString -BattleScript_EffectMirrorMove:: - attackcanceler - attackstring - pause B_WAIT_TIME_LONG - trymirrormove - ppreduce - setmoveresultflags MOVE_RESULT_FAILED - printstring STRINGID_MIRRORMOVEFAILED - waitmessage B_WAIT_TIME_LONG - goto BattleScript_MoveEnd - BattleScript_EffectAttackUp:: setstatchanger STAT_ATK, 1, FALSE goto BattleScript_EffectStatUp @@ -2962,11 +2617,10 @@ BattleScript_EffectEvasionUp:: BattleScript_EffectStatUp:: attackcanceler BattleScript_EffectStatUpAfterAtkCanceler:: - attackstring - ppreduce statbuffchange BS_ATTACKER, STAT_CHANGE_ALLOW_PTR | STAT_CHANGE_ONLY_CHECKING, BattleScript_StatUpEnd - jumpifbyte CMP_NOT_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_StatUpAttackAnim + jumpifbyte CMP_NOT_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_StatUpAttackAnim pause B_WAIT_TIME_SHORT + setmoveresultflags MOVE_RESULT_MISSED @ TODO: Is this even necessary? goto BattleScript_StatUpPrintString BattleScript_StatUpAttackAnim:: attackanimation @@ -3012,17 +2666,15 @@ BattleScript_EffectEvasionDown:: setstatchanger STAT_EVASION, 1, TRUE BattleScript_EffectStatDown: attackcanceler - jumpifsubstituteblocks BattleScript_FailedFromAtkString + jumpifsubstituteblocks BattleScript_ButItFailed BattleScript_EffectStatDownFromAccCheck: - accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE -BattleScript_StatDownFromAttackString: - attackstring - ppreduce + accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE BattleScript_EffectStatDownFromStatBuffChange: statbuffchange BS_TARGET, STAT_CHANGE_ALLOW_PTR | STAT_CHANGE_ONLY_CHECKING, BattleScript_StatDownEnd - jumpifbyte CMP_LESS_THAN, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_DECREASE, BattleScript_StatDownDoAnim - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_FELL_EMPTY, BattleScript_StatDownEnd + jumpifbyte CMP_LESS_THAN, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_StatDownDoAnim + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_CHANGE_EMPTY, BattleScript_StatDownEnd pause B_WAIT_TIME_SHORT + setmoveresultflags MOVE_RESULT_MISSED @ TODO: Is this even necessary? goto BattleScript_StatDownPrintString BattleScript_StatDownDoAnim:: attackanimation @@ -3041,7 +2693,7 @@ BattleScript_MirrorArmorReflect:: jumpifvolatile BS_ATTACKER, VOLATILE_SUBSTITUTE, BattleScript_MirrorArmorDoesntAffect BattleScript_MirrorArmorReflectStatLoss: statbuffchange BS_ATTACKER, STAT_CHANGE_MIRROR_ARMOR | STAT_CHANGE_NOT_PROTECT_AFFECTED | STAT_CHANGE_ALLOW_PTR, BattleScript_MirrorArmorReflectEnd - jumpifbyte CMP_LESS_THAN, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_DECREASE, BattleScript_MirrorArmorReflectPrintString + jumpifbyte CMP_LESS_THAN, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_MirrorArmorReflectPrintString goto BattleScript_MirrorArmorReflectWontFall BattleScript_MirrorArmorReflectPrintString: printfromtable gStatDownStringIds @@ -3075,8 +2727,6 @@ BattleScript_StatDown:: BattleScript_EffectHaze:: attackcanceler - attackstring - ppreduce attackanimation waitanimation normalisebuffs @@ -3086,8 +2736,6 @@ BattleScript_EffectHaze:: BattleScript_EffectBide:: attackcanceler - attackstring - ppreduce attackanimation waitanimation setbide @@ -3095,8 +2743,6 @@ BattleScript_EffectBide:: BattleScript_EffectRoar:: attackcanceler - attackstring - ppreduce jumpifroarfails BattleScript_ButItFailed jumpifcommanderactive BattleScript_ButItFailed jumpifability BS_TARGET, ABILITY_GUARD_DOG, BattleScript_ButItFailed @@ -3127,8 +2773,6 @@ BattleScript_ScaleShot:: BattleScript_EffectConversion:: attackcanceler - attackstring - ppreduce tryconversiontypechange BattleScript_ButItFailed attackanimation waitanimation @@ -3138,15 +2782,12 @@ BattleScript_EffectConversion:: BattleScript_EffectRestoreHp:: attackcanceler - attackstring - ppreduce - tryhealhalfhealth BattleScript_AlreadyAtFullHp, BS_ATTACKER + tryhealhalfhealth BS_ATTACKER, BattleScript_AlreadyAtFullHp attackanimation waitanimation BattleScript_RestoreHp: - orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE - healthbarupdate BS_ATTACKER - datahpupdate BS_ATTACKER + healthbarupdate BS_ATTACKER, PASSIVE_HP_UPDATE + datahpupdate BS_ATTACKER, PASSIVE_HP_UPDATE printstring STRINGID_PKMNREGAINEDHEALTH waitmessage B_WAIT_TIME_LONG goto BattleScript_MoveEnd @@ -3160,29 +2801,20 @@ BattleScript_AlreadyPoisoned:: BattleScript_ImmunityProtected:: call BattleScript_AbilityPopUp - pause B_WAIT_TIME_SHORT - printfromtable gStatusPreventionStringIds - waitmessage B_WAIT_TIME_LONG - goto BattleScript_MoveEnd + goto BattleScript_DoesntAffectTargetAtkString BattleScript_EffectAuroraVeil:: attackcanceler - attackstring - ppreduce setauroraveil goto BattleScript_PrintReflectLightScreenSafeguardString BattleScript_EffectLightScreen:: attackcanceler - attackstring - ppreduce setlightscreen goto BattleScript_PrintReflectLightScreenSafeguardString BattleScript_EffectRest:: attackcanceler - attackstring - ppreduce jumpifstatus BS_ATTACKER, STATUS1_SLEEP, BattleScript_RestIsAlreadyAsleep jumpifability BS_ATTACKER, ABILITY_COMATOSE, BattleScript_RestIsAlreadyAsleep jumpifuproarwakes BattleScript_RestCantSleep @@ -3190,7 +2822,7 @@ BattleScript_EffectRest:: jumpifability BS_TARGET, ABILITY_VITAL_SPIRIT, BattleScript_InsomniaProtects jumpifability BS_ATTACKER, ABILITY_PURIFYING_SALT, BattleScript_InsomniaProtects jumpifabilitypreventsrest BS_TARGET, BattleScript_AbilityPreventsRest - trysetrest BattleScript_AlreadyAtFullHp + trysetrest pause B_WAIT_TIME_SHORT printfromtable gRestUsedStringIds waitmessage B_WAIT_TIME_LONG @@ -3219,12 +2851,9 @@ BattleScript_AbilityPreventsRest:: BattleScript_EffectOHKO:: attackcanceler - attackstring - ppreduce typecalc jumpifmovehadnoeffect BattleScript_HitFromAtkAnimation tryKO BattleScript_KOFail - trysetdestinybondtohappen goto BattleScript_HitFromAtkAnimation BattleScript_KOFail:: pause B_WAIT_TIME_LONG @@ -3236,16 +2865,14 @@ BattleScript_RecoilIfMiss:: printstring STRINGID_PKMNCRASHED waitmessage B_WAIT_TIME_LONG jumpifability BS_ATTACKER, ABILITY_MAGIC_GUARD, BattleScript_RecoilEnd - orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_HP_UPDATE | HITMARKER_IGNORE_DISGUISE - healthbarupdate BS_ATTACKER - datahpupdate BS_ATTACKER + healthbarupdate BS_ATTACKER, PASSIVE_HP_UPDATE + datahpupdate BS_ATTACKER, PASSIVE_HP_UPDATE tryfaintmon BS_ATTACKER +BattleScript_RecoilEnd: return BattleScript_EffectMist:: attackcanceler - attackstring - ppreduce setmist attackanimation waitanimation @@ -3255,8 +2882,6 @@ BattleScript_EffectMist:: BattleScript_EffectFocusEnergy:: attackcanceler - attackstring - ppreduce jumpifvolatile BS_ATTACKER, VOLATILE_DRAGON_CHEER, BattleScript_ButItFailed jumpifvolatile BS_ATTACKER, VOLATILE_FOCUS_ENERGY, BattleScript_ButItFailed setfocusenergy BS_TARGET @@ -3268,8 +2893,6 @@ BattleScript_EffectFocusEnergy:: BattleScript_EffectConfuse:: attackcanceler - attackstring - ppreduce jumpifability BS_TARGET, ABILITY_OWN_TEMPO, BattleScript_OwnTempoPrevents jumpifsubstituteblocks BattleScript_ButItFailed jumpifvolatile BS_TARGET, VOLATILE_CONFUSION, BattleScript_AlreadyConfused @@ -3328,8 +2951,6 @@ BattleScript_EffectEvasionUp2:: BattleScript_EffectTransform:: attackcanceler - attackstring - ppreduce trytoclearprimalweather tryrevertweatherform flushtextbox @@ -3372,8 +2993,6 @@ BattleScript_EffectEvasionDown2:: BattleScript_EffectReflect:: attackcanceler - attackstring - ppreduce setreflect BattleScript_PrintReflectLightScreenSafeguardString:: attackanimation @@ -3408,8 +3027,6 @@ BattleScript_PowerHerbActivation: BattleScript_EffectTwoTurnsAttack:: jumpifvolatile BS_ATTACKER, VOLATILE_MULTIPLETURNS, BattleScript_TwoTurnMovesSecondTurn - jumpifword CMP_COMMON_BITS, gHitMarker, HITMARKER_NO_ATTACKSTRING, BattleScript_TwoTurnMovesSecondTurn - jumpifword CMP_COMMON_BITS, gHitMarker, HITMARKER_ATTACKSTRING_PRINTED, BattleScript_EffectHit @ if it's not the first hit tryfiretwoturnmovewithoutcharging BS_ATTACKER, BattleScript_EffectHit @ e.g. Solar Beam call BattleScript_FirstChargingTurn tryfiretwoturnmoveaftercharging BS_ATTACKER, BattleScript_TwoTurnMovesSecondTurn @ e.g. Electro Shot @@ -3418,7 +3035,6 @@ BattleScript_EffectTwoTurnsAttack:: BattleScript_EffectGeomancy:: jumpifvolatile BS_ATTACKER, VOLATILE_MULTIPLETURNS, BattleScript_GeomancySecondTurn - jumpifword CMP_COMMON_BITS, gHitMarker, HITMARKER_NO_ATTACKSTRING, BattleScript_GeomancySecondTurn call BattleScript_FirstChargingTurn jumpifnoholdeffect BS_ATTACKER, HOLD_EFFECT_POWER_HERB, BattleScript_MoveEnd call BattleScript_PowerHerbActivation @@ -3426,8 +3042,6 @@ BattleScript_GeomancySecondTurn: attackcanceler setbyte sB_ANIM_TURN, 1 clearvolatile BS_ATTACKER, VOLATILE_MULTIPLETURNS - orword gHitMarker, HITMARKER_NO_PPDEDUCT - attackstring jumpifstat BS_ATTACKER, CMP_LESS_THAN, STAT_SPATK, MAX_STAT_STAGE, BattleScript_GeomancyDoMoveAnim jumpifstat BS_ATTACKER, CMP_LESS_THAN, STAT_SPDEF, MAX_STAT_STAGE, BattleScript_GeomancyDoMoveAnim jumpifstat BS_ATTACKER, CMP_EQUAL, STAT_SPEED, MAX_STAT_STAGE, BattleScript_CantRaiseMultipleStats @@ -3436,19 +3050,19 @@ BattleScript_GeomancyDoMoveAnim:: waitanimation setstatchanger STAT_SPATK, 2, FALSE statbuffchange BS_ATTACKER, STAT_CHANGE_ALLOW_PTR, BattleScript_GeomancyTrySpDef, BIT_SPDEF | BIT_SPEED - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_GeomancyTrySpDef + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_GeomancyTrySpDef printfromtable gStatUpStringIds waitmessage B_WAIT_TIME_LONG BattleScript_GeomancyTrySpDef:: setstatchanger STAT_SPDEF, 2, FALSE statbuffchange BS_ATTACKER, STAT_CHANGE_ALLOW_PTR, BattleScript_GeomancyTrySpeed, BIT_SPEED - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_GeomancyTrySpeed + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_GeomancyTrySpeed printfromtable gStatUpStringIds waitmessage B_WAIT_TIME_LONG BattleScript_GeomancyTrySpeed:: setstatchanger STAT_SPEED, 2, FALSE statbuffchange BS_ATTACKER, STAT_CHANGE_ALLOW_PTR, BattleScript_GeomancyEnd - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_GeomancyEnd + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_GeomancyEnd printfromtable gStatUpStringIds waitmessage B_WAIT_TIME_LONG BattleScript_GeomancyEnd:: @@ -3456,13 +3070,7 @@ BattleScript_GeomancyEnd:: BattleScript_FirstChargingTurn:: attackcanceler -@ before Gen 5, charge moves did not print an attack string on the charge turn -.if B_UPDATED_MOVE_DATA >= GEN_5 - flushtextbox - attackstring waitmessage B_WAIT_TIME_LONG -.endif - ppreduce BattleScript_FirstChargingTurnAfterAttackString: setsemiinvulnerablebit @ only for moves with EFFECT_SEMI_INVULNERABLE/EFFECT_SKY_DROP setchargingturn @@ -3475,17 +3083,12 @@ BattleScript_TwoTurnMovesSecondPowerHerbActivates: trygulpmissile @ Edge case for Cramorant ability Gulp Missile BattleScript_FromTwoTurnMovesSecondTurnRet: call BattleScript_TwoTurnMovesSecondTurnRet - accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE -@ before Gen 5, charge moves did not print an attack string on the charge turn -.if B_UPDATED_MOVE_DATA < GEN_5 - attackstring -.endif + accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE goto BattleScript_HitFromCritCalc BattleScript_TwoTurnMovesSecondTurn:: attackcanceler call BattleScript_TwoTurnMovesSecondTurnRet - orword gHitMarker, HITMARKER_NO_PPDEDUCT goto BattleScript_HitFromAccCheck BattleScript_TwoTurnMovesSecondTurnRet: @@ -3497,17 +3100,14 @@ BattleScript_TwoTurnMovesSecondTurnRet: BattleScript_EffectSubstitute:: attackcanceler - ppreduce - attackstring waitstate jumpifvolatile BS_ATTACKER, VOLATILE_SUBSTITUTE, BattleScript_AlreadyHasSubstitute setsubstitute jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_SUBSTITUTE_FAILED, BattleScript_SubstituteString - orword gHitMarker, HITMARKER_PASSIVE_HP_UPDATE attackanimation waitanimation - healthbarupdate BS_ATTACKER - datahpupdate BS_ATTACKER + healthbarupdate BS_ATTACKER, PASSIVE_HP_UPDATE + datahpupdate BS_ATTACKER, PASSIVE_HP_UPDATE BattleScript_SubstituteString:: pause B_WAIT_TIME_SHORT printfromtable gSubstituteUsedStringIds @@ -3529,15 +3129,13 @@ BattleScript_EffectRage:: attackcanceler accuracycheck BattleScript_RageMiss, ACC_CURR_MOVE seteffectprimary BS_ATTACKER, BS_TARGET, MOVE_EFFECT_RAGE - goto BattleScript_HitFromAtkString + goto BattleScript_HitFromCritCalc BattleScript_RageMiss:: clearvolatile BS_ATTACKER, VOLATILE_RAGE - goto BattleScript_PrintMoveMissed + goto BattleScript_MoveMissedPause BattleScript_EffectMimic:: attackcanceler - attackstring - ppreduce jumpifsubstituteblocks BattleScript_ButItFailed accuracycheck BattleScript_ButItFailed, NO_ACC_CALC_CHECK_LOCK_ON mimicattackcopy BattleScript_ButItFailed @@ -3547,19 +3145,9 @@ BattleScript_EffectMimic:: waitmessage B_WAIT_TIME_LONG goto BattleScript_MoveEnd -BattleScript_EffectMetronome:: - attackcanceler - attackstring - pause B_WAIT_TIME_SHORT - attackanimation - waitanimation - metronome - BattleScript_EffectLeechSeed:: attackcanceler - attackstring pause B_WAIT_TIME_SHORT - ppreduce jumpifsubstituteblocks BattleScript_ButItFailed accuracycheck BattleScript_DoLeechSeed, ACC_CURR_MOVE BattleScript_DoLeechSeed:: @@ -3572,8 +3160,6 @@ BattleScript_DoLeechSeed:: BattleScript_EffectDoNothing:: attackcanceler - attackstring - ppreduce attackanimation waitanimation incrementgamestat GAME_STAT_USED_SPLASH @@ -3583,8 +3169,6 @@ BattleScript_EffectDoNothing:: BattleScript_EffectHoldHands:: attackcanceler - attackstring - ppreduce accuracycheck BattleScript_ButItFailed, NO_ACC_CALC_CHECK_LOCK_ON jumpifbyteequal gBattlerTarget, gBattlerAttacker, BattleScript_ButItFailed attackanimation @@ -3593,8 +3177,6 @@ BattleScript_EffectHoldHands:: BattleScript_EffectCelebrate:: attackcanceler - attackstring - ppreduce attackanimation waitanimation printstring STRINGID_CELEBRATEMESSAGE @@ -3603,8 +3185,6 @@ BattleScript_EffectCelebrate:: BattleScript_EffectHappyHour:: attackcanceler - attackstring - ppreduce attackanimation waitanimation seteffectprimary BS_ATTACKER, BS_TARGET, MOVE_EFFECT_HAPPY_HOUR @@ -3612,8 +3192,6 @@ BattleScript_EffectHappyHour:: BattleScript_EffectDisable:: attackcanceler - attackstring - ppreduce jumpifability BS_TARGET_SIDE, ABILITY_AROMA_VEIL, BattleScript_AromaVeilProtects accuracycheck BattleScript_ButItFailed, ACC_CURR_MOVE disablelastusedattack BattleScript_ButItFailed @@ -3625,10 +3203,8 @@ BattleScript_EffectDisable:: BattleScript_EffectCounter:: attackcanceler - counterdamagecalculator BattleScript_FailedFromAtkString - accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE - attackstring - ppreduce + counterdamagecalculator BattleScript_ButItFailed + accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE typecalc clearmoveresultflags MOVE_RESULT_NOT_VERY_EFFECTIVE | MOVE_RESULT_SUPER_EFFECTIVE adjustdamage @@ -3636,9 +3212,7 @@ BattleScript_EffectCounter:: BattleScript_EffectEncore:: attackcanceler - accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE - attackstring - ppreduce + accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE jumpifability BS_TARGET_SIDE, ABILITY_AROMA_VEIL, BattleScript_AromaVeilProtects trysetencore BattleScript_ButItFailed attackanimation @@ -3649,43 +3223,30 @@ BattleScript_EffectEncore:: BattleScript_EffectPainSplit:: attackcanceler - attackstring - ppreduce accuracycheck BattleScript_ButItFailed, NO_ACC_CALC_CHECK_LOCK_ON painsplitdmgcalc BattleScript_ButItFailed attackanimation waitanimation - orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE - healthbarupdate BS_ATTACKER - datahpupdate BS_ATTACKER - healthbarupdate BS_TARGET - datahpupdate BS_TARGET + healthbarupdate BS_ATTACKER, PASSIVE_HP_UPDATE + datahpupdate BS_ATTACKER, PASSIVE_HP_UPDATE + healthbarupdate BS_TARGET, PASSIVE_HP_UPDATE + datahpupdate BS_TARGET, PASSIVE_HP_UPDATE printstring STRINGID_SHAREDPAIN waitmessage B_WAIT_TIME_LONG goto BattleScript_MoveEnd BattleScript_EffectSnore:: attackcanceler - jumpifability BS_ATTACKER, ABILITY_COMATOSE, BattleScript_SnoreIsAsleep - jumpifstatus BS_ATTACKER, STATUS1_SLEEP, BattleScript_SnoreIsAsleep - attackstring - ppreduce - goto BattleScript_ButItFailed -BattleScript_SnoreIsAsleep:: jumpifhalfword CMP_EQUAL, gChosenMove, MOVE_SLEEP_TALK, BattleScript_DoSnore printstring STRINGID_PKMNFASTASLEEP waitmessage B_WAIT_TIME_LONG statusanimation BS_ATTACKER BattleScript_DoSnore:: - attackstring - ppreduce accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE goto BattleScript_HitFromCritCalc BattleScript_EffectConversion2:: attackcanceler - attackstring - ppreduce settypetorandomresistance BattleScript_ButItFailed attackanimation waitanimation @@ -3695,8 +3256,6 @@ BattleScript_EffectConversion2:: BattleScript_EffectLockOn:: attackcanceler - attackstring - ppreduce jumpifsubstituteblocks BattleScript_ButItFailed accuracycheck BattleScript_ButItFailed, ACC_CURR_MOVE setalwayshitflag @@ -3708,8 +3267,6 @@ BattleScript_EffectLockOn:: BattleScript_EffectSketch:: attackcanceler - attackstring - ppreduce copymovepermanently BattleScript_ButItFailed attackanimation waitanimation @@ -3717,33 +3274,9 @@ BattleScript_EffectSketch:: waitmessage B_WAIT_TIME_LONG goto BattleScript_MoveEnd -BattleScript_EffectSleepTalk:: - attackcanceler - jumpifability BS_ATTACKER, ABILITY_COMATOSE, BattleScript_SleepTalkIsAsleep - jumpifstatus BS_ATTACKER, STATUS1_SLEEP, BattleScript_SleepTalkIsAsleep - attackstring - ppreduce - goto BattleScript_ButItFailed -BattleScript_SleepTalkIsAsleep:: - printstring STRINGID_PKMNFASTASLEEP - waitmessage B_WAIT_TIME_LONG - statusanimation BS_ATTACKER - attackstring - ppreduce - orword gHitMarker, HITMARKER_NO_PPDEDUCT - trychoosesleeptalkmove BattleScript_SleepTalkUsingMove - pause B_WAIT_TIME_LONG - goto BattleScript_ButItFailed -BattleScript_SleepTalkUsingMove:: - attackanimation - waitanimation - jumptocalledmove TRUE - BattleScript_EffectDestinyBond:: attackcanceler - attackstring - ppreduce - trysetdestinybond BattleScript_ButItFailed + setvolatile BS_ATTACKER, VOLATILE_DESTINY_BOND, 2 attackanimation waitanimation printstring STRINGID_PKMNTRYINGTOTAKEFOE @@ -3757,8 +3290,6 @@ BattleScript_MoveEffectEerieSpell:: BattleScript_EffectSpite:: attackcanceler - attackstring - ppreduce accuracycheck BattleScript_ButItFailed, ACC_CURR_MOVE tryspiteppreduce BattleScript_ButItFailed attackanimation @@ -3770,8 +3301,6 @@ BattleScript_EffectSpite:: @ TODO: Simplfy script BattleScript_EffectHealBell:: attackcanceler - attackstring - ppreduce attackanimation waitanimation healpartystatus @@ -3804,8 +3333,6 @@ BattleScript_MoveEffectAromatherapy:: BattleScript_EffectMeanLook:: attackcanceler - attackstring - ppreduce accuracycheck BattleScript_ButItFailed, NO_ACC_CALC_CHECK_LOCK_ON jumpifvolatile BS_TARGET, VOLATILE_ESCAPE_PREVENTION, BattleScript_ButItFailed jumpifsubstituteblocks BattleScript_ButItFailed @@ -3821,8 +3348,6 @@ BattleScript_EffectMeanLook:: BattleScript_EffectNightmare:: attackcanceler - attackstring - ppreduce jumpifsubstituteblocks BattleScript_ButItFailed jumpifvolatile BS_TARGET, VOLATILE_NIGHTMARE, BattleScript_ButItFailed jumpifstatus BS_TARGET, STATUS1_SLEEP, BattleScript_NightmareWorked @@ -3839,19 +3364,17 @@ BattleScript_NightmareWorked:: BattleScript_EffectMinimize:: attackcanceler setvolatile BS_ATTACKER, VOLATILE_MINIMIZE -.if B_MINIMIZE_EVASION >= GEN_5 + jumpifgenconfiglowerthan CONFIG_MINIMIZE_EVASION, GEN_5, BattleScript_EffectMinimizeGen4 setstatchanger STAT_EVASION, 2, FALSE -.else + goto BattleScript_EffectStatUpAfterAtkCanceler +BattleScript_EffectMinimizeGen4: setstatchanger STAT_EVASION, 1, FALSE -.endif goto BattleScript_EffectStatUpAfterAtkCanceler BattleScript_EffectCurse:: jumpiftype BS_ATTACKER, TYPE_GHOST, BattleScript_GhostCurse attackcanceler jumpiftype BS_ATTACKER, TYPE_GHOST, BattleScript_DoGhostCurse - attackstring - ppreduce jumpifstat BS_ATTACKER, CMP_GREATER_THAN, STAT_SPEED, MIN_STAT_STAGE, BattleScript_CurseTrySpeed jumpifstat BS_ATTACKER, CMP_NOT_EQUAL, STAT_ATK, MAX_STAT_STAGE, BattleScript_CurseTrySpeed jumpifstat BS_ATTACKER, CMP_EQUAL, STAT_DEF, MAX_STAT_STAGE, BattleScript_ButItFailed @@ -3881,32 +3404,21 @@ BattleScript_GhostCurse:: getmovetarget BattleScript_DoGhostCurse:: attackcanceler - attackstring - ppreduce accuracycheck BattleScript_ButItFailed, NO_ACC_CALC_CHECK_LOCK_ON cursetarget BattleScript_ButItFailed - orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE setbyte sB_ANIM_TURN, 0 attackanimation waitanimation - healthbarupdate BS_ATTACKER - datahpupdate BS_ATTACKER + healthbarupdate BS_ATTACKER, PASSIVE_HP_UPDATE + datahpupdate BS_ATTACKER, PASSIVE_HP_UPDATE printstring STRINGID_PKMNLAIDCURSE waitmessage B_WAIT_TIME_LONG tryfaintmon BS_ATTACKER goto BattleScript_MoveEnd -BattleScript_EffectMatBlock:: - attackcanceler - jumpifnotfirstturn BattleScript_FailedFromAtkString - goto BattleScript_ProtectLikeAtkString - BattleScript_EffectProtect:: BattleScript_EffectEndure:: attackcanceler -BattleScript_ProtectLikeAtkString: - attackstring - ppreduce setprotectlike attackanimation waitanimation @@ -3916,9 +3428,7 @@ BattleScript_ProtectLikeAtkString: BattleScript_EffectSpikes:: attackcanceler - trysetspikes BattleScript_FailedFromAtkString - attackstring - ppreduce + trysetspikes BattleScript_ButItFailed attackanimation waitanimation printstring STRINGID_SPIKESSCATTERED @@ -3927,8 +3437,6 @@ BattleScript_EffectSpikes:: BattleScript_EffectForesight:: attackcanceler - attackstring - ppreduce accuracycheck BattleScript_ButItFailed, NO_ACC_CALC_CHECK_LOCK_ON jumpifvolatile BS_TARGET, VOLATILE_FORESIGHT, BattleScript_ButItFailed setvolatile BS_TARGET, VOLATILE_FORESIGHT @@ -3941,8 +3449,6 @@ BattleScript_IdentifiedFoe: BattleScript_EffectPerishSong:: attackcanceler - attackstring - ppreduce trysetperishsong BattleScript_ButItFailed savetarget attackanimation @@ -3972,17 +3478,13 @@ BattleScript_PerishSongNotAffected: BattleScript_EffectSandstorm:: attackcanceler - attackstring - ppreduce call BattleScript_CheckPrimalWeather setfieldweather BATTLE_WEATHER_SANDSTORM goto BattleScript_MoveWeatherChange BattleScript_EffectRollout:: attackcanceler - attackstring jumpifvolatile BS_ATTACKER, VOLATILE_MULTIPLETURNS, BattleScript_RolloutCheckAccuracy - ppreduce BattleScript_RolloutCheckAccuracy:: accuracycheck BattleScript_RolloutHit, ACC_CURR_MOVE BattleScript_RolloutHit:: @@ -3993,15 +3495,13 @@ BattleScript_RolloutHit:: BattleScript_EffectSwagger:: attackcanceler jumpifsubstituteblocks BattleScript_MakeMoveMissed - accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE - attackstring - ppreduce + accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE jumpifconfusedandstatmaxed STAT_ATK, BattleScript_ButItFailed attackanimation waitanimation setstatchanger STAT_ATK, 2, FALSE statbuffchange BS_TARGET, STAT_CHANGE_ALLOW_PTR, BattleScript_SwaggerTryConfuse - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_SwaggerTryConfuse + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_SwaggerTryConfuse printfromtable gStatUpStringIds waitmessage B_WAIT_TIME_LONG BattleScript_SwaggerTryConfuse: @@ -4012,8 +3512,6 @@ BattleScript_SwaggerTryConfuse: BattleScript_EffectFuryCutter:: attackcanceler - attackstring - ppreduce accuracycheck BattleScript_FuryCutterHit, ACC_CURR_MOVE BattleScript_FuryCutterHit: handlefurycutter @@ -4028,10 +3526,15 @@ BattleScript_TryDestinyKnotTarget: playanimation BS_ATTACKER, B_ANIM_HELD_ITEM_EFFECT waitanimation printstring STRINGID_DESTINYKNOTACTIVATES - tryinfatuating BattleScript_ButItFailed + tryinfatuating BattleScript_TryDestinyKnotTargetFailed volatileanimation BS_TARGET, VOLATILE_INFATUATION waitanimation waitmessage B_WAIT_TIME_LONG + goto BattleScript_TryDestinyKnotTargetRet +BattleScript_TryDestinyKnotTargetFailed: + pause B_WAIT_TIME_SHORT + printstring STRINGID_BUTITFAILED + waitmessage B_WAIT_TIME_LONG BattleScript_TryDestinyKnotTargetRet: return @@ -4050,8 +3553,6 @@ BattleScript_TryDestinyKnotAttacker: BattleScript_EffectAttract:: attackcanceler - attackstring - ppreduce accuracycheck BattleScript_ButItFailed, ACC_CURR_MOVE jumpifability BS_TARGET_SIDE, ABILITY_AROMA_VEIL, BattleScript_AromaVeilProtects tryinfatuating BattleScript_ButItFailed @@ -4064,36 +3565,26 @@ BattleScript_EffectAttract:: BattleScript_EffectPresent:: attackcanceler - accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE - attackstring - ppreduce + accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE typecalc presentdamagecalculation BattleScript_EffectSafeguard:: attackcanceler - attackstring - ppreduce setsafeguard goto BattleScript_PrintReflectLightScreenSafeguardString BattleScript_EffectMagnitude:: - jumpifword CMP_COMMON_BITS, gHitMarker, HITMARKER_NO_ATTACKSTRING | HITMARKER_NO_PPDEDUCT, BattleScript_EffectMagnitudeTarget attackcanceler - attackstring - ppreduce magnitudedamagecalculation pause B_WAIT_TIME_SHORT printstring STRINGID_MAGNITUDESTRENGTH waitmessage B_WAIT_TIME_LONG -BattleScript_EffectMagnitudeTarget: accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE goto BattleScript_HitFromCritCalc BattleScript_EffectBatonPass:: attackcanceler - attackstring - ppreduce jumpifbattletype BATTLE_TYPE_ARENA, BattleScript_ButItFailed jumpifcantswitch SWITCH_IGNORE_ESCAPE_PREVENTION | BS_ATTACKER, BattleScript_ButItFailed attackanimation @@ -4119,15 +3610,11 @@ BattleScript_EffectSynthesis:: BattleScript_EffectMoonlight:: BattleScript_EffectShoreUp:: attackcanceler - attackstring - ppreduce recoverbasedonsunlight BattleScript_AlreadyAtFullHp goto BattleScript_PresentHealTarget BattleScript_EffectRainDance:: attackcanceler - attackstring - ppreduce call BattleScript_CheckPrimalWeather setfieldweather BATTLE_WEATHER_RAIN BattleScript_MoveWeatherChange:: @@ -4144,8 +3631,6 @@ BattleScript_MoveWeatherChangeRet:: BattleScript_EffectSunnyDay:: attackcanceler - attackstring - ppreduce call BattleScript_CheckPrimalWeather setfieldweather BATTLE_WEATHER_SUN goto BattleScript_MoveWeatherChange @@ -4220,15 +3705,12 @@ BattleScript_BlockedByPrimalWeatherRet:: BattleScript_EffectBellyDrum:: attackcanceler - attackstring - ppreduce jumpifstatignorecontrary BS_ATTACKER, CMP_EQUAL, STAT_ATK, MAX_STAT_STAGE, BattleScript_ButItFailed halvehp BattleScript_ButItFailed - orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_HP_UPDATE attackanimation waitanimation - healthbarupdate BS_ATTACKER - datahpupdate BS_ATTACKER + healthbarupdate BS_ATTACKER, PASSIVE_HP_UPDATE + datahpupdate BS_ATTACKER, PASSIVE_HP_UPDATE setstatchanger STAT_ATK, MAX_STAT_STAGE, FALSE statbuffchange BS_ATTACKER, STAT_CHANGE_ALLOW_PTR, BattleScript_MoveEnd printstring STRINGID_PKMNCUTHPMAXEDATTACK @@ -4237,8 +3719,6 @@ BattleScript_EffectBellyDrum:: BattleScript_EffectPsychUp:: attackcanceler - attackstring - ppreduce copyfoestats attackanimation waitanimation @@ -4248,10 +3728,8 @@ BattleScript_EffectPsychUp:: BattleScript_EffectMirrorCoat:: attackcanceler - mirrorcoatdamagecalculator BattleScript_FailedFromAtkString - accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE - attackstring - ppreduce + mirrorcoatdamagecalculator BattleScript_ButItFailed + accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE typecalc clearmoveresultflags MOVE_RESULT_NOT_VERY_EFFECTIVE | MOVE_RESULT_SUPER_EFFECTIVE adjustdamage @@ -4259,9 +3737,7 @@ BattleScript_EffectMirrorCoat:: BattleScript_EffectFutureSight:: attackcanceler - attackstring - ppreduce - trysetfutureattack BattleScript_ButItFailed + setfutureattack attackanimation waitanimation printfromtable gFutureMoveUsedStringIds @@ -4269,7 +3745,7 @@ BattleScript_EffectFutureSight:: goto BattleScript_MoveEnd BattleScript_EffectTeleport:: - jumpifgenconfiglowerthan GEN_CONFIG_TELEPORT_BEHAVIOR, GEN_8, BattleScript_EffectTeleportGen7 + jumpifgenconfiglowerthan CONFIG_TELEPORT_BEHAVIOR, GEN_8, BattleScript_EffectTeleportGen7 jumpifbattletype BATTLE_TYPE_TRAINER, BattleScript_EffectBatonPass jumpifside BS_ATTACKER, B_SIDE_PLAYER, BattleScript_EffectBatonPass goto BattleScript_DoEffectTeleport @@ -4277,8 +3753,6 @@ BattleScript_EffectTeleportGen7:: jumpifbattletype BATTLE_TYPE_TRAINER, BattleScript_FailedFromAtkCanceler BattleScript_DoEffectTeleport:: attackcanceler - attackstring - ppreduce isrunningimpossible jumpifbyte CMP_EQUAL, gBattleCommunication, BATTLE_RUN_FORBIDDEN, BattleScript_ButItFailed jumpifbyte CMP_EQUAL, gBattleCommunication, BATTLE_RUN_FAILURE, BattleScript_PrintAbilityMadeIneffective @@ -4290,46 +3764,23 @@ BattleScript_DoEffectTeleport:: goto BattleScript_MoveEnd BattleScript_EffectBeatUp:: + jumpifgenconfiglowerthan CONFIG_BEAT_UP, GEN_5, BattleScript_EffectBeatUpGen3 + goto BattleScript_EffectHit + +BattleScript_EffectBeatUpGen3: attackcanceler - accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE - attackstring + accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE pause B_WAIT_TIME_SHORT - ppreduce - setbyte gBattleCommunication, 0 -BattleScript_BeatUpLoop:: - movevaluescleanup - trydobeatup BattleScript_BeatUpEnd, BattleScript_ButItFailed + trydobeatup BattleScript_MoveEnd, BattleScript_ButItFailed printstring STRINGID_PKMNATTACK - critcalc - jumpifcriticalhit BattleScript_BeatUpAttack - manipulatedamage DMG_DOUBLED -BattleScript_BeatUpAttack:: - adjustdamage - attackanimation - waitanimation - effectivenesssound - hitanimation BS_TARGET - waitstate - healthbarupdate BS_TARGET - datahpupdate BS_TARGET - critmessage - waitmessage B_WAIT_TIME_LONG - resultmessage - waitmessage B_WAIT_TIME_LONG - tryfaintmon BS_TARGET - moveendto MOVEEND_NEXT_TARGET - goto BattleScript_BeatUpLoop -BattleScript_BeatUpEnd:: - end + goto BattleScript_HitFromCritCalc BattleScript_EffectDefenseCurl:: attackcanceler - attackstring - ppreduce setvolatile BS_TARGET, VOLATILE_DEFENSE_CURL setstatchanger STAT_DEF, 1, FALSE statbuffchange BS_ATTACKER, STAT_CHANGE_ALLOW_PTR | STAT_CHANGE_ONLY_CHECKING, BattleScript_DefenseCurlDoStatUpAnim - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_StatUpPrintString + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_StatUpPrintString attackanimation waitanimation BattleScript_DefenseCurlDoStatUpAnim:: @@ -4337,15 +3788,12 @@ BattleScript_DefenseCurlDoStatUpAnim:: BattleScript_EffectSoftboiled:: attackcanceler - attackstring - ppreduce - tryhealhalfhealth BattleScript_AlreadyAtFullHp, BS_TARGET + tryhealhalfhealth BS_TARGET, BattleScript_AlreadyAtFullHp BattleScript_PresentHealTarget:: attackanimation waitanimation - orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE - healthbarupdate BS_TARGET - datahpupdate BS_TARGET + healthbarupdate BS_TARGET, PASSIVE_HP_UPDATE + datahpupdate BS_TARGET, PASSIVE_HP_UPDATE printstring STRINGID_PKMNREGAINEDHEALTH waitmessage B_WAIT_TIME_LONG goto BattleScript_MoveEnd @@ -4356,17 +3804,8 @@ BattleScript_AlreadyAtFullHp:: waitmessage B_WAIT_TIME_LONG goto BattleScript_MoveEnd -BattleScript_EffectFirstTurnOnly:: - attackcanceler - jumpifnotfirstturn BattleScript_FailedFromAtkString - goto BattleScript_EffectHit - BattleScript_FailedFromAtkCanceler:: attackcanceler -BattleScript_FailedFromAtkString:: - attackstring -BattleScript_FailedFromPpReduce:: - ppreduce BattleScript_ButItFailed:: pause B_WAIT_TIME_SHORT setmoveresultflags MOVE_RESULT_FAILED @@ -4398,23 +3837,12 @@ BattleScript_NotAffectedAbilityPopUp:: waitmessage B_WAIT_TIME_LONG goto BattleScript_MoveEnd -BattleScript_EffectUproar:: - attackcanceler - accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE - attackstring - jumpifvolatile BS_ATTACKER, VOLATILE_MULTIPLETURNS, BattleScript_UproarHit - ppreduce -BattleScript_UproarHit:: - goto BattleScript_HitFromCritCalc - BattleScript_EffectStockpile:: attackcanceler - attackstring - ppreduce stockpile 0 attackanimation waitanimation - printfromtable gStockpileUsedStringIds + printstring STRINGID_PKMNSTOCKPILED waitmessage B_WAIT_TIME_LONG .if B_STOCKPILE_RAISES_DEFS < GEN_4 goto BattleScript_EffectStockpileEnd @@ -4425,13 +3853,13 @@ BattleScript_EffectStockpile:: BattleScript_EffectStockpileDef: setstatchanger STAT_DEF, 1, FALSE statbuffchange BS_ATTACKER, STAT_CHANGE_ALLOW_PTR, BattleScript_EffectStockpileSpDef, BIT_SPDEF - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_EffectStockpileSpDef + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_EffectStockpileSpDef printfromtable gStatUpStringIds waitmessage B_WAIT_TIME_LONG BattleScript_EffectStockpileSpDef:: setstatchanger STAT_SPDEF, 1, FALSE statbuffchange BS_ATTACKER, STAT_CHANGE_ALLOW_PTR, BattleScript_EffectStockpileEnd - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_EffectStockpileEnd + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_EffectStockpileEnd printfromtable gStatUpStringIds waitmessage B_WAIT_TIME_LONG BattleScript_EffectStockpileEnd: @@ -4456,67 +3884,42 @@ BattleScript_StockpileStatChangeDown_Ret: BattleScript_EffectSpitUp:: attackcanceler jumpifbyte CMP_EQUAL, cMISS_TYPE, B_MSG_PROTECTED, BattleScript_SpitUpFailProtect - attackstring - ppreduce - accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE + accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE damagecalc adjustdamage - stockpiletobasedamage BattleScript_SpitUpFail + stockpiletobasedamage call BattleScript_Hit_RetFromAtkAnimation tryfaintmon BS_TARGET removestockpilecounters - goto BattleScript_SpitUpEnd -BattleScript_SpitUpFail:: - checkparentalbondcounter 2, BattleScript_SpitUpEnd - pause B_WAIT_TIME_SHORT - printstring STRINGID_FAILEDTOSPITUP - waitmessage B_WAIT_TIME_LONG -BattleScript_SpitUpEnd: goto BattleScript_MoveEnd BattleScript_SpitUpFailProtect:: - attackstring - ppreduce pause B_WAIT_TIME_LONG - stockpiletobasedamage BattleScript_SpitUpFail + stockpiletobasedamage resultmessage waitmessage B_WAIT_TIME_LONG goto BattleScript_MoveEnd BattleScript_EffectSwallow:: attackcanceler - attackstring - ppreduce - stockpiletohpheal BattleScript_SwallowFail + stockpiletohpheal BattleScript_ButItFailed attackanimation waitanimation - orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE - healthbarupdate BS_TARGET - datahpupdate BS_TARGET + healthbarupdate BS_TARGET, PASSIVE_HP_UPDATE + datahpupdate BS_TARGET, PASSIVE_HP_UPDATE printstring STRINGID_PKMNREGAINEDHEALTH waitmessage B_WAIT_TIME_LONG removestockpilecounters goto BattleScript_MoveEnd - -BattleScript_SwallowFail:: - pause B_WAIT_TIME_SHORT - printfromtable gSwallowFailStringIds - waitmessage B_WAIT_TIME_LONG - goto BattleScript_MoveEnd - BattleScript_EffectHail:: attackcanceler - attackstring - ppreduce call BattleScript_CheckPrimalWeather setfieldweather BATTLE_WEATHER_HAIL goto BattleScript_MoveWeatherChange BattleScript_EffectTorment:: attackcanceler - attackstring - ppreduce accuracycheck BattleScript_ButItFailed, ACC_CURR_MOVE jumpifability BS_TARGET_SIDE, ABILITY_AROMA_VEIL, BattleScript_AromaVeilProtects settorment BattleScript_ButItFailed @@ -4529,15 +3932,13 @@ BattleScript_EffectTorment:: BattleScript_EffectFlatter:: attackcanceler jumpifsubstituteblocks BattleScript_MakeMoveMissed - accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE - attackstring - ppreduce + accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE jumpifconfusedandstatmaxed STAT_SPATK, BattleScript_ButItFailed attackanimation waitanimation setstatchanger STAT_SPATK, 1, FALSE statbuffchange BS_TARGET, STAT_CHANGE_ALLOW_PTR, BattleScript_FlatterTryConfuse - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_FlatterTryConfuse + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_FlatterTryConfuse printfromtable gStatUpStringIds waitmessage B_WAIT_TIME_LONG BattleScript_FlatterTryConfuse:: @@ -4553,8 +3954,6 @@ BattleScript_EffectDarkVoid:: .endif BattleScript_EffectNonVolatileStatus:: attackcanceler - attackstring - ppreduce trynonvolatilestatus accuracycheck BattleScript_ButItFailed, ACC_CURR_MOVE attackanimation @@ -4575,8 +3974,6 @@ BattleScript_AlreadyBurned:: BattleScript_EffectMemento:: attackcanceler jumpifbyte CMP_EQUAL, cMISS_TYPE, B_MSG_PROTECTED, BattleScript_MementoTargetProtect - attackstring - ppreduce trymemento BattleScript_ButItFailed setatkhptozero attackanimation @@ -4584,15 +3981,15 @@ BattleScript_EffectMemento:: jumpifsubstituteblocks BattleScript_EffectMementoPrintNoEffect setstatchanger STAT_ATK, 2, TRUE statbuffchange BS_TARGET, STAT_CHANGE_ALLOW_PTR, BattleScript_EffectMementoTrySpAtk, BIT_SPATK -@ Greater than B_MSG_DEFENDER_STAT_FELL is checking if the stat cannot decrease - jumpifbyte CMP_GREATER_THAN, cMULTISTRING_CHOOSER, B_MSG_DEFENDER_STAT_FELL, BattleScript_EffectMementoTrySpAtk +@ Greater than B_MSG_DEFENDER_STAT_CHANGED is checking if the stat cannot decrease + jumpifbyte CMP_GREATER_THAN, cMULTISTRING_CHOOSER, B_MSG_DEFENDER_STAT_CHANGED, BattleScript_EffectMementoTrySpAtk printfromtable gStatDownStringIds waitmessage B_WAIT_TIME_LONG BattleScript_EffectMementoTrySpAtk: setstatchanger STAT_SPATK, 2, TRUE statbuffchange BS_TARGET, STAT_CHANGE_ALLOW_PTR, BattleScript_EffectMementoTryFaint -@ Greater than B_MSG_DEFENDER_STAT_FELL is checking if the stat cannot decrease - jumpifbyte CMP_GREATER_THAN, cMULTISTRING_CHOOSER, B_MSG_DEFENDER_STAT_FELL, BattleScript_EffectMementoTryFaint +@ Greater than B_MSG_DEFENDER_STAT_CHANGED is checking if the stat cannot decrease + jumpifbyte CMP_GREATER_THAN, cMULTISTRING_CHOOSER, B_MSG_DEFENDER_STAT_CHANGED, BattleScript_EffectMementoTryFaint printfromtable gStatDownStringIds waitmessage B_WAIT_TIME_LONG BattleScript_EffectMementoTryFaint: @@ -4604,8 +4001,6 @@ BattleScript_EffectMementoPrintNoEffect: goto BattleScript_EffectMementoTryFaint @ If the target is protected there's no need to check the target's stats or animate, the user will just faint BattleScript_MementoTargetProtect: - attackstring - ppreduce trymemento BattleScript_MementoTargetProtectEnd BattleScript_MementoTargetProtectEnd: setatkhptozero @@ -4619,18 +4014,12 @@ BattleScript_MementoTargetProtectEnd: BattleScript_EffectFocusPunch:: attackcanceler jumpifnodamage BattleScript_HitFromAccCheck - ppreduce printstring STRINGID_PKMNLOSTFOCUS waitmessage B_WAIT_TIME_LONG goto BattleScript_MoveEnd BattleScript_EffectFollowMe:: attackcanceler - attackstring - ppreduce - .if B_UPDATED_MOVE_DATA >= GEN_8 - jumpifnotbattletype BATTLE_TYPE_DOUBLE, BattleScript_ButItFailed - .endif setforcedtarget attackanimation waitanimation @@ -4638,26 +4027,15 @@ BattleScript_EffectFollowMe:: waitmessage B_WAIT_TIME_LONG goto BattleScript_MoveEnd -BattleScript_EffectNaturePower:: - attackcanceler - attackstring - pause B_WAIT_TIME_SHORT - callenvironmentattack - printstring STRINGID_NATUREPOWERTURNEDINTO - waitmessage B_WAIT_TIME_LONG - return - BattleScript_EffectCharge:: attackcanceler - attackstring - ppreduce - setcharge BS_ATTACKER + setvolatile BS_ATTACKER, VOLATILE_CHARGE_TIMER, 2 attackanimation waitanimation .if B_CHARGE_SPDEF_RAISE >= GEN_5 setstatchanger STAT_SPDEF, 1, FALSE statbuffchange BS_ATTACKER, STAT_CHANGE_ALLOW_PTR, BattleScript_EffectChargeString - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_EffectChargeString + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_EffectChargeString printfromtable gStatUpStringIds waitmessage B_WAIT_TIME_LONG BattleScript_EffectChargeString: @@ -4668,8 +4046,6 @@ BattleScript_EffectChargeString: BattleScript_EffectTaunt:: attackcanceler - attackstring - ppreduce jumpifability BS_TARGET_SIDE, ABILITY_AROMA_VEIL, BattleScript_AromaVeilProtects accuracycheck BattleScript_ButItFailed, ACC_CURR_MOVE settaunt BattleScript_ButItFailed @@ -4681,8 +4057,6 @@ BattleScript_EffectTaunt:: BattleScript_EffectHelpingHand:: attackcanceler - attackstring - ppreduce trysethelpinghand BattleScript_ButItFailed attackanimation waitanimation @@ -4692,8 +4066,6 @@ BattleScript_EffectHelpingHand:: BattleScript_EffectTrick:: attackcanceler - attackstring - ppreduce jumpifsubstituteblocks BattleScript_ButItFailed accuracycheck BattleScript_ButItFailed, ACC_CURR_MOVE tryswapitems BattleScript_ButItFailed @@ -4707,16 +4079,12 @@ BattleScript_EffectTrick:: BattleScript_EffectRolePlay:: attackcanceler - attackstring - ppreduce accuracycheck BattleScript_ButItFailed, NO_ACC_CALC_CHECK_LOCK_ON trycopyability BS_ATTACKER, BattleScript_ButItFailed attackanimation waitanimation -.if B_ABILITY_POP_UP == TRUE copybyte gBattlerAbility, gBattlerAttacker call BattleScript_AbilityPopUpOverwriteThenNormal -.endif recordability BS_ATTACKER printstring STRINGID_PKMNCOPIEDFOE waitmessage B_WAIT_TIME_LONG @@ -4725,25 +4093,13 @@ BattleScript_EffectRolePlay:: BattleScript_EffectWish:: attackcanceler - attackstring - ppreduce trywish BattleScript_ButItFailed attackanimation waitanimation goto BattleScript_MoveEnd -BattleScript_EffectAssist:: - attackcanceler - attackstring - assistattackselect BattleScript_FailedFromPpReduce - attackanimation - waitanimation - jumptocalledmove TRUE - BattleScript_EffectIngrain:: attackcanceler - attackstring - ppreduce trysetvolatile BS_ATTACKER, VOLATILE_ROOT, BattleScript_ButItFailed attackanimation waitanimation @@ -4753,9 +4109,7 @@ BattleScript_EffectIngrain:: BattleScript_EffectMagicCoat:: attackcanceler - trysetmagiccoat BattleScript_FailedFromAtkString - attackstring - ppreduce + trysetmagiccoat BattleScript_ButItFailed attackanimation waitanimation printstring STRINGID_PKMNSHROUDEDITSELF @@ -4764,8 +4118,6 @@ BattleScript_EffectMagicCoat:: BattleScript_EffectRecycle:: attackcanceler - attackstring - ppreduce tryrecycleitem BattleScript_ButItFailed attackanimation waitanimation @@ -4775,9 +4127,7 @@ BattleScript_EffectRecycle:: BattleScript_EffectBrickBreak:: attackcanceler - accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE - attackstring - ppreduce + accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE typecalc removescreens critcalc @@ -4796,8 +4146,8 @@ BattleScript_BrickBreakDoHit:: effectivenesssound hitanimation BS_TARGET waitstate - healthbarupdate BS_TARGET - datahpupdate BS_TARGET + healthbarupdate BS_TARGET, MOVE_DAMAGE_HP_UPDATE + datahpupdate BS_TARGET, MOVE_DAMAGE_HP_UPDATE critmessage waitmessage B_WAIT_TIME_LONG resultmessage @@ -4808,8 +4158,6 @@ BattleScript_BrickBreakDoHit:: BattleScript_EffectYawn:: attackcanceler - attackstring - ppreduce trynonvolatilestatus accuracycheck BattleScript_ButItFailed, NO_ACC_CALC_CHECK_LOCK_ON setyawn BattleScript_ButItFailed @@ -4833,8 +4181,6 @@ BattleScript_PrintAbilityMadeIneffective:: BattleScript_EffectEndeavor:: attackcanceler - attackstring - ppreduce setdamagetohealthdifference BattleScript_ButItFailed accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE typecalc @@ -4845,20 +4191,16 @@ BattleScript_EffectEndeavor:: BattleScript_EffectSkillSwap:: attackcanceler - attackstring - ppreduce accuracycheck BattleScript_ButItFailed, NO_ACC_CALC_CHECK_LOCK_ON tryswapabilities BattleScript_ButItFailed attackanimation waitanimation jumpiftargetally BattleScript_EffectSkillSwap_AfterAbilityPopUp -.if B_ABILITY_POP_UP == TRUE copybyte gBattlerAbility, gBattlerAttacker call BattleScript_AbilityPopUpOverwriteThenNormal copybyte gBattlerAbility, gBattlerTarget copyhword sABILITY_OVERWRITE, gLastUsedAbility call BattleScript_AbilityPopUpOverwriteThenNormal -.endif BattleScript_EffectSkillSwap_AfterAbilityPopUp: recordability BS_ATTACKER recordability BS_TARGET @@ -4872,8 +4214,6 @@ BattleScript_EffectSkillSwap_AfterAbilityPopUp: BattleScript_EffectImprison:: attackcanceler - attackstring - ppreduce tryimprison BattleScript_ButItFailed attackanimation waitanimation @@ -4883,8 +4223,6 @@ BattleScript_EffectImprison:: BattleScript_EffectRefresh:: attackcanceler - attackstring - ppreduce curestatuswithmove BattleScript_ButItFailed attackanimation waitanimation @@ -4895,9 +4233,8 @@ BattleScript_EffectRefresh:: BattleScript_EffectGrudge:: attackcanceler - attackstring - ppreduce - trysetvolatile BS_ATTACKER, VOLATILE_GRUDGE, BattleScript_ButItFailed + jumpifvolatile BS_ATTACKER, VOLATILE_GRUDGE, BattleScript_ButItFailed + setvolatile BS_ATTACKER, VOLATILE_GRUDGE, 2 attackanimation waitanimation printstring STRINGID_PKMNWANTSGRUDGE @@ -4906,9 +4243,7 @@ BattleScript_EffectGrudge:: BattleScript_EffectSnatch:: attackcanceler - trysetsnatch BattleScript_FailedFromAtkString - attackstring - ppreduce + trysetsnatch BattleScript_ButItFailed attackanimation waitanimation pause B_WAIT_TIME_SHORT @@ -4924,8 +4259,6 @@ BattleScript_EffectStruggle:: BattleScript_EffectMudSport:: BattleScript_EffectWaterSport:: attackcanceler - attackstring - ppreduce settypebasedhalvers BattleScript_ButItFailed attackanimation waitanimation @@ -4935,8 +4268,6 @@ BattleScript_EffectWaterSport:: BattleScript_EffectTickle:: attackcanceler - attackstring - ppreduce jumpifstat BS_TARGET, CMP_GREATER_THAN, STAT_ATK, MIN_STAT_STAGE, BattleScript_TickleDoMoveAnim jumpifstat BS_TARGET, CMP_EQUAL, STAT_DEF, MIN_STAT_STAGE, BattleScript_CantLowerMultipleStats BattleScript_TickleDoMoveAnim:: @@ -4945,13 +4276,13 @@ BattleScript_TickleDoMoveAnim:: waitanimation setstatchanger STAT_ATK, 1, TRUE statbuffchange BS_TARGET, STAT_CHANGE_ALLOW_PTR, BattleScript_TickleTryLowerDef, BIT_DEF - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_DECREASE, BattleScript_TickleTryLowerDef + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_TickleTryLowerDef printfromtable gStatDownStringIds waitmessage B_WAIT_TIME_LONG BattleScript_TickleTryLowerDef:: setstatchanger STAT_DEF, 1, TRUE statbuffchange BS_TARGET, STAT_CHANGE_ALLOW_PTR, BattleScript_TickleEnd - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_DECREASE, BattleScript_TickleEnd + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_TickleEnd printfromtable gStatDownStringIds waitmessage B_WAIT_TIME_LONG BattleScript_TickleEnd:: @@ -4966,8 +4297,6 @@ BattleScript_CantLowerMultipleStats:: BattleScript_EffectCosmicPower:: attackcanceler - attackstring - ppreduce jumpifstat BS_ATTACKER, CMP_LESS_THAN, STAT_DEF, MAX_STAT_STAGE, BattleScript_CosmicPowerDoMoveAnim jumpifstat BS_ATTACKER, CMP_EQUAL, STAT_SPDEF, MAX_STAT_STAGE, BattleScript_CantRaiseMultipleStats BattleScript_CosmicPowerDoMoveAnim:: @@ -4975,13 +4304,13 @@ BattleScript_CosmicPowerDoMoveAnim:: waitanimation setstatchanger STAT_DEF, 1, FALSE statbuffchange BS_ATTACKER, STAT_CHANGE_ALLOW_PTR, BattleScript_CosmicPowerTrySpDef, BIT_SPDEF - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_CosmicPowerTrySpDef + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_CosmicPowerTrySpDef printfromtable gStatUpStringIds waitmessage B_WAIT_TIME_LONG BattleScript_CosmicPowerTrySpDef:: setstatchanger STAT_SPDEF, 1, FALSE statbuffchange BS_ATTACKER, STAT_CHANGE_ALLOW_PTR, BattleScript_CosmicPowerEnd - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_CosmicPowerEnd + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_CosmicPowerEnd printfromtable gStatUpStringIds waitmessage B_WAIT_TIME_LONG BattleScript_CosmicPowerEnd:: @@ -4989,8 +4318,6 @@ BattleScript_CosmicPowerEnd:: BattleScript_EffectBulkUp:: attackcanceler - attackstring - ppreduce jumpifstat BS_ATTACKER, CMP_LESS_THAN, STAT_ATK, MAX_STAT_STAGE, BattleScript_BulkUpDoMoveAnim jumpifstat BS_ATTACKER, CMP_EQUAL, STAT_DEF, MAX_STAT_STAGE, BattleScript_CantRaiseMultipleStats BattleScript_BulkUpDoMoveAnim:: @@ -4998,13 +4325,13 @@ BattleScript_BulkUpDoMoveAnim:: waitanimation setstatchanger STAT_ATK, 1, FALSE statbuffchange BS_ATTACKER, STAT_CHANGE_ALLOW_PTR, BattleScript_BulkUpTryDef, BIT_DEF - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_BulkUpTryDef + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_BulkUpTryDef printfromtable gStatUpStringIds waitmessage B_WAIT_TIME_LONG BattleScript_BulkUpTryDef:: setstatchanger STAT_DEF, 1, FALSE statbuffchange BS_ATTACKER, STAT_CHANGE_ALLOW_PTR, BattleScript_BulkUpEnd - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_BulkUpEnd + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_BulkUpEnd printfromtable gStatUpStringIds waitmessage B_WAIT_TIME_LONG BattleScript_BulkUpEnd:: @@ -5012,8 +4339,6 @@ BattleScript_BulkUpEnd:: BattleScript_EffectCalmMind:: attackcanceler - attackstring - ppreduce BattleScript_CalmMindTryToRaiseStats:: jumpifstat BS_ATTACKER, CMP_LESS_THAN, STAT_SPATK, MAX_STAT_STAGE, BattleScript_CalmMindDoMoveAnim jumpifstat BS_ATTACKER, CMP_EQUAL, STAT_SPDEF, MAX_STAT_STAGE, BattleScript_CantRaiseMultipleStats @@ -5023,13 +4348,13 @@ BattleScript_CalmMindDoMoveAnim:: BattleScript_CalmMindStatRaise:: setstatchanger STAT_SPATK, 1, FALSE statbuffchange BS_ATTACKER, STAT_CHANGE_ALLOW_PTR, BattleScript_CalmMindTrySpDef, BIT_SPDEF - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_CalmMindTrySpDef + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_CalmMindTrySpDef printfromtable gStatUpStringIds waitmessage B_WAIT_TIME_LONG BattleScript_CalmMindTrySpDef:: setstatchanger STAT_SPDEF, 1, FALSE statbuffchange BS_ATTACKER, STAT_CHANGE_ALLOW_PTR, BattleScript_CalmMindEnd - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_CalmMindEnd + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_CalmMindEnd printfromtable gStatUpStringIds waitmessage B_WAIT_TIME_LONG BattleScript_CalmMindEnd:: @@ -5044,8 +4369,6 @@ BattleScript_CantRaiseMultipleStats:: BattleScript_EffectDragonDance:: attackcanceler - attackstring - ppreduce BattleScript_EffectDragonDanceFromStatUp:: jumpifstat BS_ATTACKER, CMP_LESS_THAN, STAT_ATK, MAX_STAT_STAGE, BattleScript_DragonDanceDoMoveAnim jumpifstat BS_ATTACKER, CMP_EQUAL, STAT_SPEED, MAX_STAT_STAGE, BattleScript_CantRaiseMultipleStats @@ -5054,13 +4377,13 @@ BattleScript_DragonDanceDoMoveAnim:: waitanimation setstatchanger STAT_ATK, 1, FALSE statbuffchange BS_ATTACKER, STAT_CHANGE_ALLOW_PTR, BattleScript_DragonDanceTrySpeed, BIT_SPEED - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_DragonDanceTrySpeed + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_DragonDanceTrySpeed printfromtable gStatUpStringIds waitmessage B_WAIT_TIME_LONG BattleScript_DragonDanceTrySpeed:: setstatchanger STAT_SPEED, 1, FALSE statbuffchange BS_ATTACKER, STAT_CHANGE_ALLOW_PTR, BattleScript_DragonDanceEnd - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_DragonDanceEnd + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_DragonDanceEnd printfromtable gStatUpStringIds waitmessage B_WAIT_TIME_LONG BattleScript_DragonDanceEnd:: @@ -5068,8 +4391,6 @@ BattleScript_DragonDanceEnd:: BattleScript_EffectCamouflage:: attackcanceler - attackstring - ppreduce settypetoenvironment BattleScript_ButItFailed attackanimation waitanimation @@ -5077,39 +4398,22 @@ BattleScript_EffectCamouflage:: waitmessage B_WAIT_TIME_LONG goto BattleScript_MoveEnd -BattleScript_FaintAttacker:: - tryillusionoff BS_ATTACKER +BattleScript_FaintBattler:: + tryillusionoff BS_FAINTED tryactivategulpmissile - playfaintcry BS_ATTACKER + playfaintcry BS_FAINTED pause B_WAIT_TIME_LONG - dofaintanimation BS_ATTACKER - printstring STRINGID_ATTACKERFAINTED - cleareffectsonfaint BS_ATTACKER + dofaintanimation BS_FAINTED + copybyte sBATTLER, gBattlerFainted @ for message + printstring STRINGID_BATTLERFAINTED + cleareffectsonfaint BS_FAINTED trytoclearprimalweather tryrevertweatherform flushtextbox waitanimation - tryactivatereceiver BS_ATTACKER + tryactivatereceiver BS_FAINTED tryactivatesoulheart - trytrainerslidemsgfirstoff BS_ATTACKER - return - -BattleScript_FaintTarget:: - tryillusionoff BS_TARGET - tryactivategulpmissile - tryupdateleaderscresttracker - playfaintcry BS_TARGET - pause B_WAIT_TIME_LONG - dofaintanimation BS_TARGET - printstring STRINGID_TARGETFAINTED - cleareffectsonfaint BS_TARGET - trytoclearprimalweather - tryrevertweatherform - flushtextbox - waitanimation - tryactivatereceiver BS_TARGET - tryactivatesoulheart - trytrainerslidemsgfirstoff BS_TARGET + trytrainerslidemsgfirstoff BS_FAINTED return BattleScript_GiveExp:: @@ -5512,11 +4816,11 @@ BattleScript_FogEnded_Ret:: BattleScript_IceBodyHeal:: call BattleScript_AbilityPopUp playanimation BS_ATTACKER, B_ANIM_SIMPLE_HEAL - healthbarupdate BS_ATTACKER - datahpupdate BS_ATTACKER + healthbarupdate BS_ATTACKER, PASSIVE_HP_UPDATE + datahpupdate BS_ATTACKER, PASSIVE_HP_UPDATE printstring STRINGID_ICEBODYHPGAIN waitmessage B_WAIT_TIME_LONG - end3 + end2 BattleScript_OverworldStatusStarts:: printfromtable gStartingStatusStringIds @@ -5580,7 +4884,7 @@ BattleScript_MagicRoomEnds:: setbyte gBattlerTarget, 0 BattleScript_MagicRoomHealingItemsLoop: copyarraywithindex gBattlerAttacker, gBattlerByTurnOrder, gBattlerTarget, 1 - tryrestorehpberry + tryactivateitem BS_ATTACKER, ACTIVATION_ON_USABLE_AGAIN addbyte gBattlerTarget, 1 jumpifbytenotequal gBattlerTarget, gBattlersCount, BattleScript_MagicRoomHealingItemsLoop end2 @@ -5642,9 +4946,8 @@ BattleScript_LeechSeedTurnDrainHealBlockEnd2: BattleScript_LeechSeedTurnDrainRecovery:: call BattleScript_LeechSeedTurnDrain BattleScript_LeechSeedTurnDrainGainHp: - orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_HP_UPDATE - healthbarupdate BS_TARGET - datahpupdate BS_TARGET + healthbarupdate BS_TARGET, PASSIVE_HP_UPDATE + datahpupdate BS_TARGET, PASSIVE_HP_UPDATE printfromtable gLeechSeedStringIds waitmessage B_WAIT_TIME_LONG tryfaintmon BS_TARGET @@ -5652,8 +4955,8 @@ BattleScript_LeechSeedTurnDrainGainHp: BattleScript_LeechSeedTurnDrain: playanimation BS_ATTACKER, B_ANIM_LEECH_SEED_DRAIN, sB_ANIM_ARG1 - healthbarupdate BS_ATTACKER - datahpupdate BS_ATTACKER + healthbarupdate BS_ATTACKER, PASSIVE_HP_UPDATE + datahpupdate BS_ATTACKER, PASSIVE_HP_UPDATE tryfaintmon BS_ATTACKER return @@ -5678,8 +4981,8 @@ BattleScript_BideAttack:: effectivenesssound hitanimation BS_TARGET waitstate - healthbarupdate BS_TARGET - datahpupdate BS_TARGET + healthbarupdate BS_TARGET, MOVE_DAMAGE_HP_UPDATE + datahpupdate BS_TARGET, MOVE_DAMAGE_HP_UPDATE resultmessage waitmessage B_WAIT_TIME_LONG tryfaintmon BS_TARGET @@ -5738,13 +5041,13 @@ BattleScript_WeaknessPolicyAtk: waitanimation setstatchanger STAT_ATK, 2, FALSE statbuffchange BS_TARGET, STAT_CHANGE_ALLOW_PTR, BattleScript_WeaknessPolicySpAtk, BIT_SPATK - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_WeaknessPolicySpAtk + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_WeaknessPolicySpAtk printstring STRINGID_USINGITEMSTATOFPKMNROSE waitmessage B_WAIT_TIME_LONG BattleScript_WeaknessPolicySpAtk: setstatchanger STAT_SPATK, 2, FALSE statbuffchange BS_TARGET, STAT_CHANGE_ALLOW_PTR, BattleScript_WeaknessPolicyRemoveItem - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_WeaknessPolicyRemoveItem + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_WeaknessPolicyRemoveItem printstring STRINGID_USINGITEMSTATOFPKMNROSE waitmessage B_WAIT_TIME_LONG BattleScript_WeaknessPolicyRemoveItem: @@ -5755,7 +5058,7 @@ BattleScript_WeaknessPolicyEnd: BattleScript_TargetItemStatRaise:: copybyte sBATTLER, gBattlerTarget statbuffchange BS_TARGET, STAT_CHANGE_ONLY_CHECKING, BattleScript_TargetItemStatRaiseRemoveItemRet - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_TargetItemStatRaiseRemoveItemRet + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_TargetItemStatRaiseRemoveItemRet playanimation BS_TARGET, B_ANIM_HELD_ITEM_EFFECT waitanimation statbuffchange BS_TARGET, 0, BattleScript_TargetItemStatRaiseRemoveItemRet @@ -5768,7 +5071,7 @@ BattleScript_TargetItemStatRaiseRemoveItemRet: BattleScript_AttackerItemStatRaise:: copybyte sBATTLER, gBattlerAttacker statbuffchange BS_ATTACKER, STAT_CHANGE_ONLY_CHECKING, BattleScript_AttackerItemStatRaiseRet - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_AttackerItemStatRaiseRet + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_AttackerItemStatRaiseRet playanimation BS_ATTACKER, B_ANIM_HELD_ITEM_EFFECT waitanimation statbuffchange BS_ATTACKER, 0, BattleScript_AttackerItemStatRaiseRet @@ -5827,16 +5130,14 @@ BattleScript_EncoredNoMore:: BattleScript_DestinyBondTakesLife:: printstring STRINGID_PKMNTOOKFOE waitmessage B_WAIT_TIME_LONG - orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_HP_UPDATE - healthbarupdate BS_ATTACKER - datahpupdate BS_ATTACKER + healthbarupdate BS_ATTACKER, PASSIVE_HP_UPDATE + datahpupdate BS_ATTACKER, PASSIVE_HP_UPDATE tryfaintmon BS_ATTACKER return BattleScript_DmgHazardsOnAttacker:: - orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_HP_UPDATE - healthbarupdate BS_ATTACKER - datahpupdate BS_ATTACKER + healthbarupdate BS_ATTACKER, PASSIVE_HP_UPDATE + datahpupdate BS_ATTACKER, PASSIVE_HP_UPDATE call BattleScript_PrintHurtByDmgHazards tryfaintmon BS_ATTACKER tryfaintmon_spikes BS_ATTACKER, BattleScript_DmgHazardsOnAttackerFainted @@ -5849,9 +5150,8 @@ BattleScript_DmgHazardsOnAttackerFainted:: goto BattleScript_HandleFaintedMon BattleScript_DmgHazardsOnTarget:: - orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_HP_UPDATE - healthbarupdate BS_TARGET - datahpupdate BS_TARGET + healthbarupdate BS_TARGET, PASSIVE_HP_UPDATE + datahpupdate BS_TARGET, PASSIVE_HP_UPDATE call BattleScript_PrintHurtByDmgHazards tryfaintmon BS_TARGET tryfaintmon_spikes BS_TARGET, BattleScript_DmgHazardsOnTargetFainted @@ -5864,9 +5164,8 @@ BattleScript_DmgHazardsOnTargetFainted:: goto BattleScript_HandleFaintedMon BattleScript_DmgHazardsOnBattlerScripting:: - orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_HP_UPDATE - healthbarupdate BS_SCRIPTING - datahpupdate BS_SCRIPTING + healthbarupdate BS_SCRIPTING, PASSIVE_HP_UPDATE + datahpupdate BS_SCRIPTING, PASSIVE_HP_UPDATE call BattleScript_PrintHurtByDmgHazards tryfaintmon BS_SCRIPTING tryfaintmon_spikes BS_SCRIPTING, BattleScript_DmgHazardsOnBattlerScriptingFainted @@ -5879,9 +5178,8 @@ BattleScript_DmgHazardsOnBattlerScriptingFainted:: goto BattleScript_HandleFaintedMon BattleScript_DmgHazardsOnFaintedBattler:: - orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_HP_UPDATE - healthbarupdate BS_FAINTED - datahpupdate BS_FAINTED + healthbarupdate BS_FAINTED, PASSIVE_HP_UPDATE + datahpupdate BS_FAINTED, PASSIVE_HP_UPDATE call BattleScript_PrintHurtByDmgHazards tryfaintmon BS_FAINTED tryfaintmon_spikes BS_FAINTED, BattleScript_DmgHazardsOnFaintedBattlerFainted @@ -5928,7 +5226,7 @@ BattleScript_StickyWebOnSwitchIn:: waitmessage B_WAIT_TIME_LONG jumpifability BS_TARGET, ABILITY_MIRROR_ARMOR, BattleScript_MirrorArmorReflectStickyWeb statbuffchange BS_TARGET, STAT_CHANGE_CHECK_PREVENTION | STAT_CHANGE_ALLOW_PTR, BattleScript_StickyWebOnSwitchInEnd - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_FELL_EMPTY, BattleScript_StickyWebOnSwitchInEnd + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_CHANGE_EMPTY, BattleScript_StickyWebOnSwitchInEnd printfromtable gStatDownStringIds waitmessage B_WAIT_TIME_LONG BattleScript_StickyWebOnSwitchInEnd: @@ -5940,9 +5238,8 @@ BattleScript_StickyWebOnSwitchInEnd: BattleScript_PerishSongTakesLife:: printstring STRINGID_PKMNPERISHCOUNTFELL waitmessage B_WAIT_TIME_LONG - orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_HP_UPDATE - healthbarupdate BS_ATTACKER - datahpupdate BS_ATTACKER + healthbarupdate BS_ATTACKER, PASSIVE_HP_UPDATE + datahpupdate BS_ATTACKER, PASSIVE_HP_UPDATE tryfaintmon BS_ATTACKER end2 @@ -5950,20 +5247,18 @@ BattleScript_PerishBodyActivates:: call BattleScript_AbilityPopUp printstring STRINGID_PKMNSWILLPERISHIN3TURNS waitmessage B_WAIT_TIME_LONG - orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_HP_UPDATE return BattleScript_GulpMissileGorging:: call BattleScript_AbilityPopUp playanimation BS_ATTACKER, B_ANIM_GULP_MISSILE waitanimation - orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_HP_UPDATE effectivenesssound hitanimation BS_ATTACKER waitstate jumpifability BS_ATTACKER, ABILITY_MAGIC_GUARD, BattleScript_GulpMissileNoDmgGorging - healthbarupdate BS_ATTACKER - datahpupdate BS_ATTACKER + healthbarupdate BS_ATTACKER, PASSIVE_HP_UPDATE + datahpupdate BS_ATTACKER, PASSIVE_HP_UPDATE tryfaintmon BS_ATTACKER jumpiffainted BS_ATTACKER, TRUE, BattleScript_GulpMissileNoSecondEffectGorging BattleScript_GulpMissileNoDmgGorging: @@ -5984,13 +5279,12 @@ BattleScript_GulpMissileGulping:: call BattleScript_AbilityPopUp playanimation BS_ATTACKER, B_ANIM_GULP_MISSILE waitanimation - orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_HP_UPDATE effectivenesssound hitanimation BS_ATTACKER waitstate jumpifability BS_ATTACKER, ABILITY_MAGIC_GUARD, BattleScript_GulpMissileNoDmgGulping - healthbarupdate BS_ATTACKER - datahpupdate BS_ATTACKER + healthbarupdate BS_ATTACKER, PASSIVE_HP_UPDATE + datahpupdate BS_ATTACKER, PASSIVE_HP_UPDATE tryfaintmon BS_ATTACKER jumpiffainted BS_ATTACKER, TRUE, BattleScript_GulpMissileNoSecondEffectGulping BattleScript_GulpMissileNoDmgGulping: @@ -6020,32 +5314,39 @@ BattleScript_SeedSowerActivates:: call BattleScript_ActivateTerrainEffects return -BattleScript_AngerShellActivates:: +BattleScript_BerserkActivates:: saveattacker - copybyte gBattlerAttacker, gBattlerTarget + copybyte gBattlerAttacker, gEffectBattler call BattleScript_AbilityPopUp - jumpifstat BS_TARGET, CMP_LESS_THAN, STAT_ATK, MAX_STAT_STAGE, BattleScript_AngerShellTryDef - jumpifstat BS_TARGET, CMP_LESS_THAN, STAT_SPATK, MAX_STAT_STAGE, BattleScript_AngerShellTryDef - jumpifstat BS_TARGET, CMP_LESS_THAN, STAT_SPEED, MAX_STAT_STAGE, BattleScript_AngerShellTryDef - jumpifstat BS_TARGET, CMP_GREATER_THAN, STAT_DEF, MIN_STAT_STAGE, BattleScript_AngerShellTryDef - jumpifstat BS_TARGET, CMP_EQUAL, STAT_SPDEF, MIN_STAT_STAGE, BattleScript_RestoreAttackerButItFailed -BattleScript_AngerShellTryDef:: - modifybattlerstatstage BS_ATTACKER, STAT_DEF, DECREASE, 1, BattleScript_AngerShellTrySpDef, ANIM_ON -BattleScript_AngerShellTrySpDef: - modifybattlerstatstage BS_ATTACKER, STAT_SPDEF, DECREASE, 1, BattleScript_AngerShellTryAttack, ANIM_ON -BattleScript_AngerShellTryAttack: - modifybattlerstatstage BS_ATTACKER, STAT_ATK, INCREASE, 1, BattleScript_AngerShellTrySpAtk, ANIM_ON -BattleScript_AngerShellTrySpAtk: - modifybattlerstatstage BS_ATTACKER, STAT_SPATK, INCREASE, 1, BattleScript_AngerShellTrySpeed, ANIM_ON -BattleScript_AngerShellTrySpeed: - modifybattlerstatstage BS_ATTACKER, STAT_SPEED, INCREASE, 1, BattleScript_AngerShellRet, ANIM_ON -BattleScript_AngerShellRet: + statbuffchange BS_EFFECT_BATTLER, STAT_CHANGE_CERTAIN, BattleScript_BerserkActivatesTryBerry + call BattleScript_StatUp +BattleScript_BerserkActivatesTryBerry: restoreattacker return +BattleScript_AngerShellActivates:: + call BattleScript_AbilityPopUp + jumpifstat BS_EFFECT_BATTLER, CMP_LESS_THAN, STAT_ATK, MAX_STAT_STAGE, BattleScript_AngerShellTryDef + jumpifstat BS_EFFECT_BATTLER, CMP_LESS_THAN, STAT_SPATK, MAX_STAT_STAGE, BattleScript_AngerShellTryDef + jumpifstat BS_EFFECT_BATTLER, CMP_LESS_THAN, STAT_SPEED, MAX_STAT_STAGE, BattleScript_AngerShellTryDef + jumpifstat BS_EFFECT_BATTLER, CMP_GREATER_THAN, STAT_DEF, MIN_STAT_STAGE, BattleScript_AngerShellTryDef + jumpifstat BS_EFFECT_BATTLER, CMP_EQUAL, STAT_SPDEF, MIN_STAT_STAGE, BattleScript_RestoreAttackerButItFailed +BattleScript_AngerShellTryDef:: + modifybattlerstatstage BS_EFFECT_BATTLER, STAT_DEF, DECREASE, 1, BattleScript_AngerShellTrySpDef, ANIM_ON +BattleScript_AngerShellTrySpDef: + modifybattlerstatstage BS_EFFECT_BATTLER, STAT_SPDEF, DECREASE, 1, BattleScript_AngerShellTryAttack, ANIM_ON +BattleScript_AngerShellTryAttack: + modifybattlerstatstage BS_EFFECT_BATTLER, STAT_ATK, INCREASE, 1, BattleScript_AngerShellTrySpAtk, ANIM_ON +BattleScript_AngerShellTrySpAtk: + modifybattlerstatstage BS_EFFECT_BATTLER, STAT_SPATK, INCREASE, 1, BattleScript_AngerShellTrySpeed, ANIM_ON +BattleScript_AngerShellTrySpeed: + modifybattlerstatstage BS_EFFECT_BATTLER, STAT_SPEED, INCREASE, 1, BattleScript_AngerShellRet, ANIM_ON +BattleScript_AngerShellRet: + return + BattleScript_WindPowerActivates:: call BattleScript_AbilityPopUp - setcharge BS_TARGET + setvolatile BS_TARGET, VOLATILE_CHARGE_TIMER, 1 printstring STRINGID_BEINGHITCHARGEDPKMNWITHPOWER waitmessage B_WAIT_TIME_LONG return @@ -6065,9 +5366,8 @@ BattleScript_EarthEaterActivates:: call BattleScript_AbilityPopUp pause B_WAIT_TIME_LONG tryhealquarterhealth BS_TARGET, BattleScript_EarthEaterRet - orword gHitMarker, HITMARKER_IGNORE_BIDE | HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_HP_UPDATE - healthbarupdate BS_TARGET - datahpupdate BS_TARGET + healthbarupdate BS_TARGET, PASSIVE_HP_UPDATE + datahpupdate BS_TARGET, PASSIVE_HP_UPDATE printstring STRINGID_PKMNREGAINEDHEALTH waitmessage B_WAIT_TIME_LONG BattleScript_EarthEaterRet: @@ -6162,8 +5462,8 @@ BattleScript_DoFutureAttackHit:: effectivenesssound hitanimation BS_TARGET waitstate - healthbarupdate BS_TARGET - datahpupdate BS_TARGET + healthbarupdate BS_TARGET, MOVE_DAMAGE_HP_UPDATE + datahpupdate BS_TARGET, MOVE_DAMAGE_HP_UPDATE critmessage waitmessage B_WAIT_TIME_LONG BattleScript_DoFutureAttackResult: @@ -6172,17 +5472,21 @@ BattleScript_DoFutureAttackResult: tryfaintmon BS_TARGET checkteamslost BattleScript_FutureAttackEnd BattleScript_FutureAttackEnd:: + moveendcase MOVEEND_SET_VALUES moveendcase MOVEEND_RAGE moveendcase MOVEEND_ABILITIES - moveendfromto MOVEEND_ITEM_EFFECTS_ALL, MOVEEND_UPDATE_LAST_MOVES - setmoveresultflags 0 - end2 + moveendcase MOVEEND_COLOR_CHANGE + moveendcase MOVEEND_ITEM_EFFECTS_TARGET + moveendfromto MOVEEND_SYMBIOSIS, MOVEEND_UPDATE_LAST_MOVES + goto BattleScript_FutureAttackClearResults BattleScript_FutureAttackMiss:: pause B_WAIT_TIME_SHORT setmoveresultflags MOVE_RESULT_FAILED resultmessage waitmessage B_WAIT_TIME_LONG +BattleScript_FutureAttackClearResults: setmoveresultflags 0 + clearspecialstatuses end2 BattleScript_NoMovesLeft:: @@ -6194,7 +5498,7 @@ BattleScript_SelectingMoveWithNoPP:: endselectionscript BattleScript_NoPPForMove:: - attackstring + printattackstring pause B_WAIT_TIME_SHORT printstring STRINGID_BUTNOPPLEFT waitmessage B_WAIT_TIME_LONG @@ -6306,9 +5610,8 @@ BattleScript_WishComesTrue:: playanimation BS_TARGET, B_ANIM_WISH_HEAL printstring STRINGID_PKMNWISHCAMETRUE waitmessage B_WAIT_TIME_LONG - orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_IGNORE_DISGUISE - healthbarupdate BS_TARGET - datahpupdate BS_TARGET + healthbarupdate BS_TARGET, PASSIVE_HP_UPDATE + datahpupdate BS_TARGET, PASSIVE_HP_UPDATE printstring STRINGID_PKMNREGAINEDHEALTH waitmessage B_WAIT_TIME_LONG end2 @@ -6334,9 +5637,8 @@ BattleScript_IngrainTurnHeal:: printstring STRINGID_PKMNABSORBEDNUTRIENTS BattleScript_TurnHeal: waitmessage B_WAIT_TIME_LONG - orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE - healthbarupdate BS_ATTACKER - datahpupdate BS_ATTACKER + healthbarupdate BS_ATTACKER, PASSIVE_HP_UPDATE + datahpupdate BS_ATTACKER, PASSIVE_HP_UPDATE end2 BattleScript_AquaRingHeal:: @@ -6359,7 +5661,7 @@ BattleScript_PrintMonIsRootedRet:: BattleScript_AtkDefDown:: setstatchanger STAT_ATK, 1, TRUE statbuffchange BS_ATTACKER, STAT_CHANGE_CERTAIN | STAT_CHANGE_ALLOW_PTR, BattleScript_AtkDefDownTryDef, BIT_DEF - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_DECREASE, BattleScript_AtkDefDownTryDef + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_AtkDefDownTryDef printfromtable gStatDownStringIds waitmessage B_WAIT_TIME_LONG BattleScript_AtkDefDownTryDef: @@ -6373,13 +5675,13 @@ BattleScript_AtkDefDownRet: BattleScript_DefSpDefDown:: setstatchanger STAT_DEF, 1, TRUE statbuffchange BS_ATTACKER, STAT_CHANGE_CERTAIN | STAT_CHANGE_ALLOW_PTR, BattleScript_DefSpDefDownTrySpDef, BIT_SPDEF - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_DECREASE, BattleScript_DefSpDefDownTrySpDef + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_DefSpDefDownTrySpDef printfromtable gStatDownStringIds waitmessage B_WAIT_TIME_LONG BattleScript_DefSpDefDownTrySpDef:: setstatchanger STAT_SPDEF, 1, TRUE statbuffchange BS_ATTACKER, STAT_CHANGE_CERTAIN | STAT_CHANGE_ALLOW_PTR, BattleScript_DefSpDefDownRet - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_DECREASE, BattleScript_DefSpDefDownRet + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_DefSpDefDownRet printfromtable gStatDownStringIds waitmessage B_WAIT_TIME_LONG BattleScript_DefSpDefDownRet:: @@ -6391,13 +5693,13 @@ BattleScript_DefDownSpeedUp:: BattleScript_DefDownSpeedUpTryDef:: setstatchanger STAT_DEF, 1, TRUE statbuffchange BS_ATTACKER, STAT_CHANGE_ALLOW_PTR | STAT_CHANGE_CERTAIN, BattleScript_DefDownSpeedUpTrySpeed - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_DefDownSpeedUpTrySpeed + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_DefDownSpeedUpTrySpeed printfromtable gStatDownStringIds waitmessage B_WAIT_TIME_LONG BattleScript_DefDownSpeedUpTrySpeed: setstatchanger STAT_SPEED, 1, FALSE statbuffchange BS_ATTACKER, STAT_CHANGE_ALLOW_PTR | STAT_CHANGE_CERTAIN, BattleScript_DefDownSpeedUpRet - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_DefDownSpeedUpRet + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_DefDownSpeedUpRet printfromtable gStatUpStringIds waitmessage B_WAIT_TIME_LONG BattleScript_DefDownSpeedUpRet:: @@ -6428,31 +5730,21 @@ BattleScript_GrudgeTakesPp:: return BattleScript_MagicBounce:: - attackstring - ppreduce pause B_WAIT_TIME_SHORT call BattleScript_AbilityPopUp printstring STRINGID_PKMNMOVEBOUNCEDABILITY waitmessage B_WAIT_TIME_LONG setmagiccoattarget - orword gHitMarker, HITMARKER_ATTACKSTRING_PRINTED | HITMARKER_NO_PPDEDUCT | HITMARKER_ALLOW_NO_PP - bicword gHitMarker, HITMARKER_NO_ATTACKSTRING return BattleScript_MagicCoat:: - attackstring - ppreduce pause B_WAIT_TIME_SHORT setmagiccoattarget printstring STRINGID_PKMNMOVEBOUNCED waitmessage B_WAIT_TIME_LONG - orword gHitMarker, HITMARKER_ATTACKSTRING_PRINTED | HITMARKER_NO_PPDEDUCT | HITMARKER_ALLOW_NO_PP - bicword gHitMarker, HITMARKER_NO_ATTACKSTRING return BattleScript_MagicCoatPrankster:: - attackstring - ppreduce pause B_WAIT_TIME_SHORT printstring STRINGID_PKMNMOVEBOUNCED waitmessage B_WAIT_TIME_LONG @@ -6462,13 +5754,10 @@ BattleScript_MagicCoatPrankster:: goto BattleScript_MoveEnd BattleScript_SnatchedMove:: - attackstring - ppreduce snatchsetbattlers playanimation BS_TARGET, B_ANIM_SNATCH_MOVE printstring STRINGID_PKMNSNATCHEDMOVE waitmessage B_WAIT_TIME_LONG - orword gHitMarker, HITMARKER_ATTACKSTRING_PRINTED | HITMARKER_NO_PPDEDUCT | HITMARKER_ALLOW_NO_PP swapattackerwithtarget return @@ -6546,7 +5835,7 @@ BattleScript_PowerConstruct:: handleformchange BS_SCRIPTING, 2 printstring STRINGID_POWERCONSTRUCTTRANSFORM waitmessage B_WAIT_TIME_SHORT - end3 + end2 BattleScript_UltraBurst:: flushtextbox @@ -6584,7 +5873,11 @@ BattleScript_BattlerFormChangeEnd3:: BattleScript_BattlerFormChangeEnd3NoPopup:: call BattleScript_BattlerFormChangeNoPopup - end3 + end2 + +BattleScript_BattlerFormChangeEnd2:: + call BattleScript_BattlerFormChange + end2 BattleScript_BattlerFormChangeWithStringEnd3:: pause 5 @@ -6615,7 +5908,7 @@ BattleScript_BallFetch:: call BattleScript_AbilityPopUp printstring STRINGID_FETCHEDPOKEBALL waitmessage B_WAIT_TIME_LONG - end3 + end2 BattleScript_CudChewActivates:: pause B_WAIT_TIME_SHORTEST @@ -6623,13 +5916,12 @@ BattleScript_CudChewActivates:: setbyte sBERRY_OVERRIDE, 1 @ override the requirements for eating berries consumeberry BS_ATTACKER, FALSE setbyte sBERRY_OVERRIDE, 0 - end3 + end2 BattleScript_ApplyDisguiseFormChangeHPLoss:: - jumpifgenconfiglowerthan GEN_CONFIG_DISGUISE_HP_LOSS, GEN_8, BattleScript_ApplyDisguiseFormChangeHPLossReturn - orword gHitMarker, HITMARKER_PASSIVE_HP_UPDATE - healthbarupdate BS_SCRIPTING - datahpupdate BS_SCRIPTING + jumpifgenconfiglowerthan CONFIG_DISGUISE_HP_LOSS, GEN_8, BattleScript_ApplyDisguiseFormChangeHPLossReturn + healthbarupdate BS_SCRIPTING, PASSIVE_HP_UPDATE + datahpupdate BS_SCRIPTING, PASSIVE_HP_UPDATE BattleScript_ApplyDisguiseFormChangeHPLossReturn: return @@ -6673,8 +5965,10 @@ BattleScript_IllusionOffEnd3:: BattleScript_IllusionOff:: setspriteignore0hp TRUE + call BattleScript_SwapFromSubstitute playanimation BS_SCRIPTING, B_ANIM_ILLUSION_OFF waitanimation + call BattleScript_SwapToSubstitute updatenick waitstate setspriteignore0hp FALSE @@ -6693,7 +5987,7 @@ BattleScript_CottonDownLoop: setstatchanger STAT_SPEED, 1, TRUE jumpifbyteequal gBattlerTarget, gEffectBattler, BattleScript_CottonDownLoopIncrement statbuffchange BS_TARGET, STAT_CHANGE_NOT_PROTECT_AFFECTED | STAT_CHANGE_ALLOW_PTR, BattleScript_CottonDownLoopIncrement - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_DECREASE, BattleScript_CottonDownTargetSpeedCantGoLower + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_CottonDownTargetSpeedCantGoLower printfromtable gStatDownStringIds waitmessage B_WAIT_TIME_LONG goto BattleScript_CottonDownLoopIncrement @@ -6718,9 +6012,8 @@ BattleScript_AftermathDmg:: pause B_WAIT_TIME_SHORT call BattleScript_AbilityPopUpScripting jumpifability BS_ATTACKER, ABILITY_MAGIC_GUARD, BattleScript_AftermathDmgRet - orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_HP_UPDATE - healthbarupdate BS_ATTACKER - datahpupdate BS_ATTACKER + healthbarupdate BS_ATTACKER, PASSIVE_HP_UPDATE + datahpupdate BS_ATTACKER, PASSIVE_HP_UPDATE printstring STRINGID_AFTERMATHDMG waitmessage B_WAIT_TIME_LONG tryfaintmon BS_ATTACKER @@ -6761,12 +6054,11 @@ BattleScript_PoisonTurnDmg:: BattleScript_DoStatusTurnDmg:: statusanimation BS_ATTACKER BattleScript_DoTurnDmg: - orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_HP_UPDATE - healthbarupdate BS_ATTACKER - datahpupdate BS_ATTACKER + healthbarupdate BS_ATTACKER, PASSIVE_HP_UPDATE + datahpupdate BS_ATTACKER, PASSIVE_HP_UPDATE tryfaintmon BS_ATTACKER checkteamslost BattleScript_DoTurnDmgEnd - tryrestorehpberry + tryactivateitem BS_ATTACKER, ACTIVATION_ON_HP_THRESHOLD BattleScript_DoTurnDmgEnd: end2 @@ -6776,9 +6068,8 @@ BattleScript_PoisonHealActivates:: printstring STRINGID_POISONHEALHPUP waitmessage B_WAIT_TIME_LONG statusanimation BS_ATTACKER - orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_HP_UPDATE - healthbarupdate BS_ATTACKER - datahpupdate BS_ATTACKER + healthbarupdate BS_ATTACKER, PASSIVE_HP_UPDATE + datahpupdate BS_ATTACKER, PASSIVE_HP_UPDATE end2 BattleScript_BurnTurnDmg:: @@ -6829,8 +6120,6 @@ BattleScript_MoveUsedIsParalyzed:: goto BattleScript_MoveEnd BattleScript_PowderMoveNoEffect:: - attackstring - ppreduce pause B_WAIT_TIME_SHORT jumpiftype BS_TARGET, TYPE_GRASS, BattleScript_PowderMoveNoEffectPrint jumpifability BS_TARGET, ABILITY_OVERCOAT, BattleScript_PowderMoveNoEffectOvercoat @@ -6856,7 +6145,7 @@ BattleScript_MoveUsedFlinchedEnd: BattleScript_TryActivateSteadFast: setstatchanger STAT_SPEED, 1, FALSE statbuffchange BS_ATTACKER, STAT_CHANGE_ALLOW_PTR | STAT_CHANGE_ONLY_CHECKING, BattleScript_MoveUsedFlinchedEnd - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_MoveUsedFlinchedEnd + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_MoveUsedFlinchedEnd copybyte gBattlerAbility, gBattlerAttacker call BattleScript_AbilityPopUp statbuffchange BS_ATTACKER, STAT_CHANGE_ALLOW_PTR, BattleScript_MoveUsedFlinchedEnd @@ -6890,9 +6179,9 @@ BattleScript_DoSelfConfusionDmg:: effectivenesssound hitanimation BS_ATTACKER waitstate - orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_HP_UPDATE - healthbarupdate BS_ATTACKER - datahpupdate BS_ATTACKER + isdmgblockedbydisguise + healthbarupdate BS_ATTACKER, PASSIVE_HP_UPDATE + datahpupdate BS_ATTACKER, PASSIVE_HP_UPDATE resultmessage waitmessage B_WAIT_TIME_LONG tryfaintmon BS_ATTACKER @@ -6901,9 +6190,6 @@ BattleScript_MoveUsedIsConfusedRet:: return BattleScript_MoveUsedPowder:: - bicword gHitMarker, HITMARKER_NO_ATTACKSTRING | HITMARKER_ATTACKSTRING_PRINTED - attackstring - ppreduce pause B_WAIT_TIME_SHORT cancelmultiturnmoves volatileanimation BS_ATTACKER, VOLATILE_POWDER @@ -6911,9 +6197,8 @@ BattleScript_MoveUsedPowder:: effectivenesssound hitanimation BS_ATTACKER waitstate - orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_HP_UPDATE - healthbarupdate BS_ATTACKER - datahpupdate BS_ATTACKER + healthbarupdate BS_ATTACKER, PASSIVE_HP_UPDATE + datahpupdate BS_ATTACKER, PASSIVE_HP_UPDATE printstring STRINGID_POWDEREXPLODES waitmessage B_WAIT_TIME_LONG tryfaintmon BS_ATTACKER @@ -7014,7 +6299,7 @@ BattleScript_YawnEnd: BattleScript_EmbargoEndTurn:: printstring STRINGID_EMBARGOENDS waitmessage B_WAIT_TIME_LONG - tryrestorehpberry + tryactivateitem BS_ATTACKER, ACTIVATION_ON_USABLE_AGAIN end2 BattleScript_TelekinesisEndTurn:: @@ -7097,18 +6382,11 @@ BattleScript_MoveEffectConfusion:: return BattleScript_MoveEffectRecoil:: - jumpifmove MOVE_STRUGGLE, BattleScript_DoRecoil - jumpifability BS_ATTACKER, ABILITY_ROCK_HEAD, BattleScript_RecoilEnd - jumpifability BS_ATTACKER, ABILITY_MAGIC_GUARD, BattleScript_RecoilEnd -BattleScript_DoRecoil:: - orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_HP_UPDATE | HITMARKER_IGNORE_DISGUISE - healthbarupdate BS_ATTACKER - datahpupdate BS_ATTACKER + healthbarupdate BS_ATTACKER, PASSIVE_HP_UPDATE + datahpupdate BS_ATTACKER, PASSIVE_HP_UPDATE printstring STRINGID_PKMNHITWITHRECOIL waitmessage B_WAIT_TIME_LONG - tryupdaterecoiltracker tryfaintmon BS_ATTACKER -BattleScript_RecoilEnd:: return BattleScript_ItemSteal:: @@ -7157,10 +6435,8 @@ BattleScript_AbilityPopUpTarget:: copybyte gBattlerAbility, gBattlerTarget BattleScript_AbilityPopUp:: tryactivateabilityshield BS_ABILITY_BATTLER - .if B_ABILITY_POP_UP == TRUE showabilitypopup pause B_WAIT_TIME_SHORT - .endif recordability BS_ABILITY_BATTLER sethword sABILITY_OVERWRITE, 0 return @@ -7181,14 +6457,6 @@ BattleScript_AbilityPopUpOverwriteThenNormal: setbyte sFIXED_ABILITY_POPUP, FALSE return -BattleScript_SpeedBoostActivates:: - call BattleScript_AbilityPopUp - statbuffchange BS_ATTACKER, STAT_CHANGE_ALLOW_PTR, BattleScript_SpeedBoostActivatesEnd - printstring STRINGID_PKMNRAISEDSPEED - waitmessage B_WAIT_TIME_LONG -BattleScript_SpeedBoostActivatesEnd: - end3 - @ Can't compare directly to a value, have to compare to value at pointer sZero: .byte 0 @@ -7197,25 +6465,23 @@ BattleScript_MoodyActivates:: call BattleScript_AbilityPopUp jumpifbyteequal sSTATCHANGER, sZero, BattleScript_MoodyLower statbuffchange BS_ATTACKER, STAT_CHANGE_CERTAIN | STAT_CHANGE_NOT_PROTECT_AFFECTED, BattleScript_MoodyLower - jumpifbyte CMP_GREATER_THAN, cMULTISTRING_CHOOSER, B_MSG_DEFENDER_STAT_ROSE, BattleScript_MoodyLower + jumpifbyte CMP_GREATER_THAN, cMULTISTRING_CHOOSER, B_MSG_DEFENDER_STAT_CHANGED, BattleScript_MoodyLower printfromtable gStatUpStringIds waitmessage B_WAIT_TIME_LONG BattleScript_MoodyLower: jumpifbyteequal sSAVED_STAT_CHANGER, sZero, BattleScript_MoodyEnd copybyte sSTATCHANGER, sSAVED_STAT_CHANGER statbuffchange BS_ATTACKER, STAT_CHANGE_CERTAIN | STAT_CHANGE_NOT_PROTECT_AFFECTED, BattleScript_MoodyEnd - jumpifbyte CMP_GREATER_THAN, cMULTISTRING_CHOOSER, B_MSG_DEFENDER_STAT_FELL, BattleScript_MoodyEnd + jumpifbyte CMP_GREATER_THAN, cMULTISTRING_CHOOSER, B_MSG_DEFENDER_STAT_CHANGED, BattleScript_MoodyEnd printfromtable gStatDownStringIds waitmessage B_WAIT_TIME_LONG BattleScript_MoodyEnd: - end3 + end2 BattleScript_EmergencyExit:: - .if B_ABILITY_POP_UP == TRUE pause 5 call BattleScript_AbilityPopUpScripting pause B_WAIT_TIME_LONG - .endif playanimation BS_SCRIPTING, B_ANIM_SLIDE_OFFSCREEN waitanimation openpartyscreen BS_SCRIPTING, BattleScript_EmergencyExitRet @@ -7234,11 +6500,9 @@ BattleScript_EmergencyExitRet: return BattleScript_EmergencyExitWild:: - .if B_ABILITY_POP_UP == TRUE pause 5 call BattleScript_AbilityPopUpScripting pause B_WAIT_TIME_LONG - .endif playanimation BS_SCRIPTING, B_ANIM_SLIDE_OFFSCREEN waitanimation setteleportoutcome BS_SCRIPTING @@ -7297,14 +6561,13 @@ BattleScript_AbilityHpHeal: call BattleScript_AbilityPopUp printstring STRINGID_PKMNSXRESTOREDHPALITTLE2 waitmessage B_WAIT_TIME_LONG - orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE - healthbarupdate BS_ATTACKER - datahpupdate BS_ATTACKER + healthbarupdate BS_ATTACKER, PASSIVE_HP_UPDATE + datahpupdate BS_ATTACKER, PASSIVE_HP_UPDATE return BattleScript_RainDishActivates:: call BattleScript_AbilityHpHeal - end3 + end2 BattleScript_CheekPouchActivates:: copybyte sSAVED_BATTLER, gBattlerAttacker @@ -7319,9 +6582,9 @@ BattleScript_PickupActivates:: call BattleScript_AbilityPopUp printstring STRINGID_XFOUNDONEY waitmessage B_WAIT_TIME_LONG - tryrestorehpberry + tryactivateitem BS_ATTACKER, ACTIVATION_ON_PICK_UP BattleScript_PickupActivatesEnd: - end3 + end2 BattleScript_HarvestActivates:: pause 5 @@ -7329,19 +6592,18 @@ BattleScript_HarvestActivates:: call BattleScript_AbilityPopUp printstring STRINGID_HARVESTBERRY waitmessage B_WAIT_TIME_LONG - tryrestorehpberry + tryactivateitem BS_ATTACKER, ACTIVATION_ON_HARVEST BattleScript_HarvestActivatesEnd: - end3 + end2 BattleScript_SolarPowerActivates:: - orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_HP_UPDATE call BattleScript_AbilityPopUp - healthbarupdate BS_ATTACKER - datahpupdate BS_ATTACKER + healthbarupdate BS_ATTACKER, PASSIVE_HP_UPDATE + datahpupdate BS_ATTACKER, PASSIVE_HP_UPDATE printstring STRINGID_SOLARPOWERHPDROP waitmessage B_WAIT_TIME_LONG tryfaintmon BS_ATTACKER - end3 + end2 BattleScript_HealerActivates:: call BattleScript_AbilityPopUp @@ -7349,7 +6611,7 @@ BattleScript_HealerActivates:: updatestatusicon BS_SCRIPTING printstring STRINGID_HEALERCURE waitmessage B_WAIT_TIME_LONG - end3 + end2 BattleScript_SandstreamActivates:: pause B_WAIT_TIME_SHORT @@ -7374,7 +6636,7 @@ BattleScript_ShedSkinActivates:: printstring STRINGID_PKMNSXCUREDYPROBLEM waitmessage B_WAIT_TIME_LONG updatestatusicon BS_ATTACKER - end3 + end2 BattleScript_ActivateWeatherAbilities: saveattacker @@ -7391,7 +6653,6 @@ BattleScript_ActivateWeatherAbilities_Loop: return BattleScript_TryIntimidateHoldEffects: - itemstatchangeeffects BS_TARGET jumpifnoholdeffect BS_TARGET, HOLD_EFFECT_ADRENALINE_ORB, BattleScript_TryIntimidateHoldEffectsRet jumpifstat BS_TARGET, CMP_EQUAL, STAT_SPEED, MAX_STAT_STAGE, BattleScript_TryIntimidateHoldEffectsRet setstatchanger STAT_SPEED, 1, FALSE @@ -7418,8 +6679,7 @@ BattleScript_IntimidateEffect: copybyte sBATTLER, gBattlerAttacker setstatchanger STAT_ATK, 1, TRUE statbuffchange BS_TARGET, STAT_CHANGE_NOT_PROTECT_AFFECTED | STAT_CHANGE_ALLOW_PTR, BattleScript_IntimidateLoopIncrement - jumpifability BS_TARGET, ABILITY_CONTRARY, BattleScript_IntimidateContrary - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_DECREASE, BattleScript_IntimidateWontDecrease + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_IntimidateWontDecrease printstring STRINGID_PKMNCUTSATTACKWITH BattleScript_IntimidateEffect_WaitString: waitmessage B_WAIT_TIME_LONG @@ -7449,10 +6709,6 @@ BattleScript_IntimidateWontDecrease: printstring STRINGID_STATSWONTDECREASE goto BattleScript_IntimidateEffect_WaitString -BattleScript_IntimidateContrary: - printfromtable gStatUpStringIds - goto BattleScript_IntimidateEffect_WaitString - BattleScript_IntimidateInReverse:: copybyte sBATTLER, gBattlerTarget call BattleScript_AbilityPopUpTarget @@ -7475,8 +6731,7 @@ BattleScript_SupersweetSyrupEffect: copybyte sBATTLER, gBattlerAttacker setstatchanger STAT_EVASION, 1, TRUE statbuffchange BS_TARGET, STAT_CHANGE_NOT_PROTECT_AFFECTED | STAT_CHANGE_ALLOW_PTR, BattleScript_SupersweetSyrupLoopIncrement - jumpifability BS_TARGET, ABILITY_CONTRARY, BattleScript_SupersweetSyrupContrary - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_DECREASE, BattleScript_SupersweetSyrupWontDecrease + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_SupersweetSyrupWontDecrease printfromtable gStatDownStringIds BattleScript_SupersweetSyrupEffect_WaitString: waitmessage B_WAIT_TIME_LONG @@ -7500,10 +6755,6 @@ BattleScript_SupersweetSyrupWontDecrease: printstring STRINGID_STATSWONTDECREASE goto BattleScript_SupersweetSyrupEffect_WaitString -BattleScript_SupersweetSyrupContrary: - printfromtable gStatUpStringIds - goto BattleScript_SupersweetSyrupEffect_WaitString - BattleScript_DroughtActivates:: pause B_WAIT_TIME_SHORT call BattleScript_AbilityPopUp @@ -7523,11 +6774,7 @@ BattleScript_DesolateLandActivates:: end3 BattleScript_PrimalWeatherBlocksMove:: - jumpifword CMP_COMMON_BITS, gHitMarker, HITMARKER_ATTACKSTRING_PRINTED, BattleScript_MoveEnd @in case of multi-target moves, if move fails once, no point in printing the message twice - accuracycheck BattleScript_PrintMoveMissed, NO_ACC_CALC_CHECK_LOCK_ON - attackstring pause B_WAIT_TIME_SHORT - ppreduce printfromtable gPrimalWeatherBlocksStringIds waitmessage B_WAIT_TIME_LONG goto BattleScript_MoveEnd @@ -7547,6 +6794,7 @@ BattleScript_DeltaStreamActivates:: printstring STRINGID_MYSTERIOUSAIRCURRENT waitstate playanimation BS_ATTACKER, B_ANIM_STRONG_WINDS + call BattleScript_ActivateWeatherAbilities end3 BattleScript_ProtosynthesisActivates:: @@ -7600,31 +6848,31 @@ BattleScript_CommanderActivates:: BattleScript_CommanderAtkIncrease: setstatchanger STAT_ATK, 2, FALSE statbuffchange BS_ATTACKER, STAT_CHANGE_ALLOW_PTR, BattleScript_CommanderDefIncrease, BIT_DEF | BIT_SPATK | BIT_SPDEF | BIT_SPEED - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_CommanderDefIncrease + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_CommanderDefIncrease printfromtable gStatUpStringIds waitmessage B_WAIT_TIME_LONG BattleScript_CommanderDefIncrease: setstatchanger STAT_DEF, 2, FALSE statbuffchange BS_ATTACKER, STAT_CHANGE_ALLOW_PTR, BattleScript_CommanderSpAtkIncrease, BIT_SPATK | BIT_SPDEF | BIT_SPEED - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_CommanderSpAtkIncrease + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_CommanderSpAtkIncrease printfromtable gStatUpStringIds waitmessage B_WAIT_TIME_LONG BattleScript_CommanderSpAtkIncrease: setstatchanger STAT_SPATK, 2, FALSE statbuffchange BS_ATTACKER, STAT_CHANGE_ALLOW_PTR, BattleScript_CommanderSpDefIncrease, BIT_SPDEF | BIT_SPEED - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_CommanderSpDefIncrease + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_CommanderSpDefIncrease printfromtable gStatUpStringIds waitmessage B_WAIT_TIME_LONG BattleScript_CommanderSpDefIncrease: setstatchanger STAT_SPDEF, 2, FALSE statbuffchange BS_ATTACKER, STAT_CHANGE_ALLOW_PTR, BattleScript_CommanderSpeedIncrease, BIT_SPEED - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_CommanderSpeedIncrease + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_CommanderSpeedIncrease printfromtable gStatUpStringIds waitmessage B_WAIT_TIME_LONG BattleScript_CommanderSpeedIncrease: setstatchanger STAT_SPEED, 2, FALSE statbuffchange BS_ATTACKER, STAT_CHANGE_ALLOW_PTR, BattleScript_CommanderEnd - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_CommanderEnd + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_CommanderEnd printfromtable gStatUpStringIds waitmessage B_WAIT_TIME_LONG BattleScript_CommanderEnd: @@ -7636,10 +6884,9 @@ BattleScript_HospitalityActivates:: call BattleScript_AbilityPopUp printstring STRINGID_HOSPITALITYRESTORATION waitmessage B_WAIT_TIME_LONG - orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE playanimation BS_EFFECT_BATTLER, B_ANIM_SIMPLE_HEAL - healthbarupdate BS_EFFECT_BATTLER - datahpupdate BS_EFFECT_BATTLER + healthbarupdate BS_EFFECT_BATTLER, PASSIVE_HP_UPDATE + datahpupdate BS_EFFECT_BATTLER, PASSIVE_HP_UPDATE end3 BattleScript_AttackWeakenedByStrongWinds:: @@ -7741,9 +6988,8 @@ BattleScript_BadDreams_DmgAfterPopUp: printstring STRINGID_BADDREAMSDMG waitmessage B_WAIT_TIME_LONG dmg_1_8_targethp - orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_HP_UPDATE - healthbarupdate BS_TARGET - datahpupdate BS_TARGET + healthbarupdate BS_TARGET, PASSIVE_HP_UPDATE + datahpupdate BS_TARGET, PASSIVE_HP_UPDATE jumpifhasnohp BS_TARGET, BattleScript_BadDreams_HidePopUp BattleScript_BadDreamsIncrement: addbyte gBattlerTarget, 1 @@ -7752,7 +6998,7 @@ BattleScript_BadDreamsIncrement: destroyabilitypopup pause 15 BattleScript_BadDreamsEnd: - end3 + end2 BattleScript_BadDreams_ShowPopUp: copybyte gBattlerAbility, gBattlerAttacker call BattleScript_AbilityPopUp @@ -7764,11 +7010,9 @@ BattleScript_BadDreams_HidePopUp: goto BattleScript_BadDreamsIncrement BattleScript_TookAttack:: - attackstring pause B_WAIT_TIME_SHORT printstring STRINGID_PKMNSXTOOKATTACK waitmessage B_WAIT_TIME_LONG - orword gHitMarker, HITMARKER_ATTACKSTRING_PRINTED return BattleScript_SturdyPreventsOHKO:: @@ -7787,24 +7031,17 @@ BattleScript_DampStopsExplosion:: moveendcase MOVEEND_CLEAR_BITS end -BattleScript_MoveHPDrain_PPLoss:: - ppreduce BattleScript_MoveHPDrain:: - attackstring pause B_WAIT_TIME_SHORT call BattleScript_AbilityPopUp - orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE - healthbarupdate BS_TARGET - datahpupdate BS_TARGET + healthbarupdate BS_TARGET, PASSIVE_HP_UPDATE + datahpupdate BS_TARGET, PASSIVE_HP_UPDATE printstring STRINGID_PKMNRESTOREDHPUSING waitmessage B_WAIT_TIME_LONG setmoveresultflags MOVE_RESULT_DOESNT_AFFECT_FOE goto BattleScript_MoveEnd -BattleScript_MoveStatDrain_PPLoss:: - ppreduce BattleScript_MoveStatDrain:: - attackstring pause B_WAIT_TIME_SHORT call BattleScript_AbilityPopUp statbuffchange BS_TARGET, STAT_CHANGE_ALLOW_PTR, BattleScript_MoveStatDrain_Cont @@ -7819,10 +7056,7 @@ BattleScript_MoveStatDrain_Cont: clearsemiinvulnerablebit goto BattleScript_MoveEnd -BattleScript_MonMadeMoveUseless_PPLoss:: - ppreduce BattleScript_MonMadeMoveUseless:: - attackstring pause B_WAIT_TIME_SHORT call BattleScript_AbilityPopUp printstring STRINGID_PKMNSXMADEYUSELESS @@ -7830,10 +7064,7 @@ BattleScript_MonMadeMoveUseless:: setmoveresultflags MOVE_RESULT_DOESNT_AFFECT_FOE goto BattleScript_MoveEnd -BattleScript_FlashFireBoost_PPLoss:: - ppreduce BattleScript_FlashFireBoost:: - attackstring pause B_WAIT_TIME_SHORT call BattleScript_AbilityPopUp printfromtable gFlashFireStringIds @@ -7881,13 +7112,12 @@ BattleScript_FlinchPrevention:: BattleScript_OwnTempoPrevents:: pause B_WAIT_TIME_SHORT call BattleScript_AbilityPopUp + copybyte sBATTLER, gBattlerTarget printstring STRINGID_PKMNPREVENTSCONFUSIONWITH waitmessage B_WAIT_TIME_LONG goto BattleScript_MoveEnd BattleScript_SoundproofProtected:: - attackstring - ppreduce pause B_WAIT_TIME_SHORT call BattleScript_AbilityPopUp printstring STRINGID_PKMNSXBLOCKSY @@ -7900,8 +7130,6 @@ BattleScript_IceFaceNullsDamage:: return BattleScript_DazzlingProtected:: - attackstring - ppreduce pause B_WAIT_TIME_SHORT call BattleScript_AbilityPopUpScripting printstring STRINGID_POKEMONCANNOTUSEMOVE @@ -7909,17 +7137,17 @@ BattleScript_DazzlingProtected:: goto BattleScript_MoveEnd BattleScript_MoveUsedPsychicTerrainPrevents:: - printstring STRINGID_POKEMONCANNOTUSEMOVE + pause B_WAIT_TIME_SHORT + printstring STRINGID_PSYCHICTERRAINPREVENTS waitmessage B_WAIT_TIME_LONG + setmoveresultflags MOVE_RESULT_NO_EFFECT goto BattleScript_MoveEnd BattleScript_GrassyTerrainHeals:: printstring STRINGID_GRASSYTERRAINHEALS waitmessage B_WAIT_TIME_LONG - orword gHitMarker, HITMARKER_IGNORE_BIDE | HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_HP_UPDATE - healthbarupdate BS_ATTACKER - datahpupdate BS_ATTACKER - bicword gHitMarker, HITMARKER_IGNORE_BIDE | HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_HP_UPDATE + healthbarupdate BS_ATTACKER, PASSIVE_HP_UPDATE + datahpupdate BS_ATTACKER, PASSIVE_HP_UPDATE end2 BattleScript_AbilityNoSpecificStatLoss:: @@ -7927,16 +7155,20 @@ BattleScript_AbilityNoSpecificStatLoss:: call BattleScript_AbilityPopUp printstring STRINGID_PKMNSXPREVENTSYLOSS waitmessage B_WAIT_TIME_LONG - setbyte cMULTISTRING_CHOOSER, B_MSG_STAT_FELL_EMPTY + setbyte cMULTISTRING_CHOOSER, B_MSG_STAT_CHANGE_EMPTY setmoveresultflags MOVE_RESULT_NO_EFFECT return BattleScript_StickyHoldActivates:: + call BattleScript_StickyHoldActivatesRet + goto BattleScript_MoveEnd + +BattleScript_StickyHoldActivatesRet:: pause B_WAIT_TIME_SHORT call BattleScript_AbilityPopUp printstring STRINGID_PKMNSXMADEYINEFFECTIVE waitmessage B_WAIT_TIME_LONG - goto BattleScript_MoveEnd + return BattleScript_ColorChangeActivates:: call BattleScript_AbilityPopUp @@ -7970,13 +7202,11 @@ BattleScript_CursedBodyActivates:: return BattleScript_MummyActivates:: -.if B_ABILITY_POP_UP == TRUE setbyte sFIXED_ABILITY_POPUP, TRUE call BattleScript_AbilityPopUpTarget copybyte gBattlerAbility, gBattlerAttacker copyhword sABILITY_OVERWRITE, gLastUsedAbility call BattleScript_AbilityPopUpOverwriteThenNormal -.endif recordability BS_TARGET recordability BS_ATTACKER printstring STRINGID_ATTACKERACQUIREDABILITY @@ -7990,14 +7220,12 @@ BattleScript_MummyActivates:: BattleScript_WanderingSpiritActivates:: saveattacker savetarget -.if B_ABILITY_POP_UP == TRUE copybyte gBattlerAbility, gBattlerTarget sethword sABILITY_OVERWRITE, ABILITY_WANDERING_SPIRIT call BattleScript_AbilityPopUpOverwriteThenNormal copybyte gBattlerAbility, gBattlerAttacker copyhword sABILITY_OVERWRITE, gLastUsedAbility call BattleScript_AbilityPopUpOverwriteThenNormal -.endif recordability BS_TARGET recordability BS_ATTACKER printstring STRINGID_SWAPPEDABILITIES @@ -8022,7 +7250,7 @@ BattleScript_BattlerAbilityStatRaiseOnSwitchIn:: call BattleScript_AbilityPopUpScripting statbuffchange BS_SCRIPTING, STAT_CHANGE_NOT_PROTECT_AFFECTED | STAT_CHANGE_CERTAIN, BattleScript_BattlerAbilityStatRaiseOnSwitchInRet waitanimation - printstring STRINGID_BATTLERABILITYRAISEDSTAT + printstring STRINGID_SCRIPTINGABILITYSTATRAISE waitmessage B_WAIT_TIME_LONG BattleScript_BattlerAbilityStatRaiseOnSwitchInRet: end3 @@ -8043,8 +7271,8 @@ BattleScript_WeakArmorActivates:: call BattleScript_AbilityPopUp setstatchanger STAT_DEF, 1, TRUE statbuffchange BS_TARGET, STAT_CHANGE_ALLOW_PTR, BattleScript_WeakArmorActivatesSpeed - jumpifbyte CMP_LESS_THAN, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_DECREASE, BattleScript_WeakArmorDefPrintString - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_FELL_EMPTY, BattleScript_WeakArmorActivatesSpeed + jumpifbyte CMP_LESS_THAN, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_WeakArmorDefPrintString + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_CHANGE_EMPTY, BattleScript_WeakArmorActivatesSpeed pause B_WAIT_TIME_SHORTEST printfromtable gStatDownStringIds clearmoveresultflags MOVE_RESULT_MISSED @ Set by statbuffchange when stat can't be decreased @@ -8054,15 +7282,15 @@ BattleScript_WeakArmorDefPrintString: printstring STRINGID_TARGETABILITYSTATLOWER waitmessage B_WAIT_TIME_LONG BattleScript_WeakArmorActivatesSpeed: - jumpifgenconfiglowerthan GEN_CONFIG_WEAK_ARMOR_SPEED, GEN_7, BattleScript_WeakArmorSetSpeedGen6 + jumpifgenconfiglowerthan CONFIG_WEAK_ARMOR_SPEED, GEN_7, BattleScript_WeakArmorSetSpeedGen6 setstatchanger STAT_SPEED, 2, FALSE goto BattleScript_WeakArmorDoSpeed BattleScript_WeakArmorSetSpeedGen6: setstatchanger STAT_SPEED, 1, FALSE BattleScript_WeakArmorDoSpeed: statbuffchange BS_TARGET, STAT_CHANGE_ALLOW_PTR, BattleScript_WeakArmorActivatesEnd - jumpifbyte CMP_LESS_THAN, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_WeakArmorSpeedPrintString - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_ROSE_EMPTY, BattleScript_WeakArmorActivatesEnd + jumpifbyte CMP_LESS_THAN, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_WeakArmorSpeedPrintString + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_CHANGE_EMPTY, BattleScript_WeakArmorActivatesEnd pause B_WAIT_TIME_SHORTEST printstring STRINGID_TARGETSTATWONTGOHIGHER clearmoveresultflags MOVE_RESULT_MISSED @@ -8095,7 +7323,7 @@ BattleScript_AttackerAbilityStatRaise_End: BattleScript_FellStingerRaisesStat:: statbuffchange BS_ATTACKER, STAT_CHANGE_ALLOW_PTR, BattleScript_FellStingerRaisesAtkEnd - jumpifbyte CMP_GREATER_THAN, cMULTISTRING_CHOOSER, B_MSG_DEFENDER_STAT_ROSE, BattleScript_FellStingerRaisesAtkEnd + jumpifbyte CMP_GREATER_THAN, cMULTISTRING_CHOOSER, B_MSG_DEFENDER_STAT_CHANGED, BattleScript_FellStingerRaisesAtkEnd printfromtable gStatUpStringIds waitmessage B_WAIT_TIME_LONG BattleScript_FellStingerRaisesAtkEnd: @@ -8106,6 +7334,11 @@ BattleScript_AttackerAbilityStatRaiseEnd3:: restoreattacker end3 +BattleScript_AttackerAbilityStatRaiseEnd2:: + call BattleScript_AttackerAbilityStatRaise + restoreattacker + end2 + BattleScript_SwitchInAbilityMsg:: call BattleScript_AbilityPopUp printfromtable gSwitchInAbilityStringIds @@ -8159,9 +7392,8 @@ BattleScript_ImposterActivates:: end3 BattleScript_HurtAttacker: - orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_HP_UPDATE - healthbarupdate BS_ATTACKER - datahpupdate BS_ATTACKER + healthbarupdate BS_ATTACKER, PASSIVE_HP_UPDATE + datahpupdate BS_ATTACKER, PASSIVE_HP_UPDATE printstring STRINGID_PKMNHURTSWITH waitmessage B_WAIT_TIME_LONG tryfaintmon BS_ATTACKER @@ -8183,10 +7415,9 @@ BattleScript_RockyHelmetActivatesDmg: BattleScript_SpikyShieldEffect:: jumpifabsent BS_ATTACKER, BattleScript_SpikyShieldRet - orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_HP_UPDATE clearmoveresultflags MOVE_RESULT_NO_EFFECT - healthbarupdate BS_ATTACKER - datahpupdate BS_ATTACKER + healthbarupdate BS_ATTACKER, PASSIVE_HP_UPDATE + datahpupdate BS_ATTACKER, PASSIVE_HP_UPDATE printstring STRINGID_PKMNHURTSWITH waitmessage B_WAIT_TIME_LONG tryfaintmon BS_ATTACKER @@ -8195,7 +7426,6 @@ BattleScript_SpikyShieldRet:: return BattleScript_KingsShieldEffect:: - orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_HP_UPDATE clearmoveresultflags MOVE_RESULT_NO_EFFECT seteffectsecondary BS_ATTACKER, BS_TARGET, MOVE_EFFECT_NONE copybyte sBATTLER, gBattlerTarget @@ -8205,7 +7435,6 @@ BattleScript_KingsShieldEffect:: return BattleScript_BanefulBunkerEffect:: - orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_HP_UPDATE clearmoveresultflags MOVE_RESULT_NO_EFFECT setnonvolatilestatus TRIGGER_ON_PROTECT setmoveresultflags MOVE_RESULT_MISSED @@ -8252,19 +7481,19 @@ BattleScript_EffectBattleBondStatIncrease:: call BattleScript_AbilityPopUp setstatchanger STAT_ATK, 1, FALSE statbuffchange BS_ATTACKER, STAT_CHANGE_ALLOW_PTR, BattleScript_EffectBattleBondStatIncreaseTrySpAtk, BIT_SPATK | BIT_SPEED - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_EffectBattleBondStatIncreaseTrySpAtk + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_EffectBattleBondStatIncreaseTrySpAtk printfromtable gStatUpStringIds waitmessage B_WAIT_TIME_LONG BattleScript_EffectBattleBondStatIncreaseTrySpAtk: setstatchanger STAT_SPATK, 1, FALSE statbuffchange BS_ATTACKER, STAT_CHANGE_ALLOW_PTR, BattleScript_EffectBattleBondStatIncreaseTrySpeed, BIT_SPEED - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_EffectBattleBondStatIncreaseTrySpeed + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_EffectBattleBondStatIncreaseTrySpeed printfromtable gStatUpStringIds waitmessage B_WAIT_TIME_LONG BattleScript_EffectBattleBondStatIncreaseTrySpeed: setstatchanger STAT_SPEED, 1, FALSE statbuffchange BS_ATTACKER, STAT_CHANGE_ALLOW_PTR, BattleScript_EffectBattleBondStatIncreaseRet - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_EffectBattleBondStatIncreaseRet + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_EffectBattleBondStatIncreaseRet printfromtable gStatUpStringIds waitmessage B_WAIT_TIME_LONG BattleScript_EffectBattleBondStatIncreaseRet: @@ -8273,7 +7502,6 @@ BattleScript_EffectBattleBondStatIncreaseRet: BattleScript_DancerActivates:: call BattleScript_AbilityPopUp waitmessage B_WAIT_TIME_SHORT - orword gHitMarker, HITMARKER_ALLOW_NO_PP jumptocalledmove TRUE BattleScript_SynchronizeActivates:: @@ -8323,8 +7551,7 @@ BattleScript_IgnoresWhileAsleep:: BattleScript_IgnoresAndUsesRandomMove:: printstring STRINGID_PKMNIGNOREDORDERS waitmessage B_WAIT_TIME_LONG - setbyte sMOVE_EFFECT, 0 - jumptocalledmove FALSE + return BattleScript_MoveUsedLoafingAround:: jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_LOAFING, BattleScript_MoveUsedLoafingAroundMsg @@ -8360,73 +7587,13 @@ BattleScript_SubstituteFade:: printstring STRINGID_PKMNSUBSTITUTEFADED return -BattleScript_BerryCurePrlzEnd2:: - call BattleScript_BerryCureParRet +BattleScript_BerryCureStatusEnd2:: + call BattleScript_BerryCureStatusRet end2 -BattleScript_BerryCureParRet:: +BattleScript_BerryCureStatusRet:: playanimation BS_SCRIPTING, B_ANIM_HELD_ITEM_EFFECT - printstring STRINGID_PKMNSITEMCUREDPARALYSIS - waitmessage B_WAIT_TIME_LONG - updatestatusicon BS_SCRIPTING - removeitem BS_SCRIPTING - return - -BattleScript_BerryCurePsnEnd2:: - call BattleScript_BerryCurePsnRet - end2 - -BattleScript_BerryCurePsnRet:: - playanimation BS_SCRIPTING, B_ANIM_HELD_ITEM_EFFECT - printstring STRINGID_PKMNSITEMCUREDPOISON - waitmessage B_WAIT_TIME_LONG - updatestatusicon BS_SCRIPTING - removeitem BS_SCRIPTING - return - -BattleScript_BerryCureBrnEnd2:: - call BattleScript_BerryCureBrnRet - end2 - -BattleScript_BerryCureBrnRet:: - playanimation BS_SCRIPTING, B_ANIM_HELD_ITEM_EFFECT - printstring STRINGID_PKMNSITEMHEALEDBURN - waitmessage B_WAIT_TIME_LONG - updatestatusicon BS_SCRIPTING - removeitem BS_SCRIPTING - return - -BattleScript_BerryCureFrzEnd2:: - call BattleScript_BerryCureFrzRet - end2 - -BattleScript_BerryCureFrzRet:: - playanimation BS_SCRIPTING, B_ANIM_HELD_ITEM_EFFECT - printstring STRINGID_PKMNSITEMDEFROSTEDIT - waitmessage B_WAIT_TIME_LONG - updatestatusicon BS_SCRIPTING - removeitem BS_SCRIPTING - return - -BattleScript_BerryCureFrbEnd2:: - call BattleScript_BerryCureFrzRet - end2 - -BattleScript_BerryCureFrbRet:: - playanimation BS_SCRIPTING, B_ANIM_HELD_ITEM_EFFECT - printstring STRINGID_PKMNSITEMHEALEDFROSTBITE - waitmessage B_WAIT_TIME_LONG - updatestatusicon BS_SCRIPTING - removeitem BS_SCRIPTING - return - -BattleScript_BerryCureSlpEnd2:: - call BattleScript_BerryCureSlpRet - end2 - -BattleScript_BerryCureSlpRet:: - playanimation BS_SCRIPTING, B_ANIM_HELD_ITEM_EFFECT - printstring STRINGID_PKMNSITEMWOKEIT + printfromtable CureStatusBerryEffectStringID waitmessage B_WAIT_TIME_LONG updatestatusicon BS_SCRIPTING removeitem BS_SCRIPTING @@ -8461,25 +7628,12 @@ BattleScript_BerryCureConfusionRet:: removeitem BS_SCRIPTING return -BattleScript_BerryCureChosenStatusEnd2:: - call BattleScript_BerryCureChosenStatusRet - end2 - -BattleScript_BerryCureChosenStatusRet:: - playanimation BS_SCRIPTING, B_ANIM_HELD_ITEM_EFFECT - printfromtable gBerryEffectStringIds - waitmessage B_WAIT_TIME_LONG - updatestatusicon BS_SCRIPTING - removeitem BS_SCRIPTING - return - BattleScript_MentalHerbCureRet:: - playanimation BS_ATTACKER, B_ANIM_HELD_ITEM_EFFECT + playanimation BS_SCRIPTING, B_ANIM_HELD_ITEM_EFFECT printfromtable gMentalHerbCureStringIds waitmessage B_WAIT_TIME_LONG updatestatusicon BS_SCRIPTING removeitem BS_SCRIPTING - copybyte gBattlerAttacker, sSAVED_BATTLER @ restore the original attacker just to be safe return BattleScript_MentalHerbCureEnd2:: @@ -8501,14 +7655,13 @@ BattleScript_ItemHealHP_RemoveItemRet:: jumpifability BS_SCRIPTING, ABILITY_RIPEN, BattleScript_ItemHealHP_RemoveItemRet_AbilityPopUp goto BattleScript_ItemHealHP_RemoveItemRet_Anim BattleScript_ItemHealHP_RemoveItemRet_AbilityPopUp: - call BattleScript_AbilityPopUp + call BattleScript_AbilityPopUpScripting BattleScript_ItemHealHP_RemoveItemRet_Anim: playanimation BS_SCRIPTING, B_ANIM_HELD_ITEM_EFFECT printstring STRINGID_PKMNSITEMRESTOREDHEALTH waitmessage B_WAIT_TIME_LONG - orword gHitMarker, HITMARKER_IGNORE_BIDE | HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_HP_UPDATE - healthbarupdate BS_SCRIPTING - datahpupdate BS_SCRIPTING + healthbarupdate BS_SCRIPTING, PASSIVE_HP_UPDATE + datahpupdate BS_SCRIPTING, PASSIVE_HP_UPDATE removeitem BS_SCRIPTING return @@ -8516,14 +7669,13 @@ BattleScript_ItemHealHP_RemoveItemEnd2:: jumpifability BS_ATTACKER, ABILITY_RIPEN, BattleScript_ItemHealHP_RemoveItemEnd2_AbilityPopUp goto BattleScript_ItemHealHP_RemoveItemEnd2_Anim BattleScript_ItemHealHP_RemoveItemEnd2_AbilityPopUp: - call BattleScript_AbilityPopUp + call BattleScript_AbilityPopUpScripting BattleScript_ItemHealHP_RemoveItemEnd2_Anim: playanimation BS_ATTACKER, B_ANIM_HELD_ITEM_EFFECT printstring STRINGID_PKMNSITEMRESTOREDHEALTH waitmessage B_WAIT_TIME_LONG - orword gHitMarker, HITMARKER_IGNORE_BIDE | HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_HP_UPDATE - healthbarupdate BS_ATTACKER - datahpupdate BS_ATTACKER + healthbarupdate BS_ATTACKER, PASSIVE_HP_UPDATE + datahpupdate BS_ATTACKER, PASSIVE_HP_UPDATE removeitem BS_ATTACKER end2 @@ -8547,21 +7699,25 @@ BattleScript_ItemHealHP_End2:: call BattleScript_ItemHealHP_Ret end2 -BattleScript_AirBaloonMsgIn:: +BattleScript_AirBalloonMsgIn:: printstring STRINGID_AIRBALLOONFLOAT waitmessage B_WAIT_TIME_LONG end3 -BattleScript_AirBaloonMsgPop:: +BattleScript_AirBalloonMsgInRet:: + printstring STRINGID_AIRBALLOONFLOAT + waitmessage B_WAIT_TIME_LONG + return + +BattleScript_AirBalloonMsgPop:: printstring STRINGID_AIRBALLOONPOP waitmessage B_WAIT_TIME_LONG removeitem BS_TARGET return BattleScript_ItemHurtRet:: - orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_HP_UPDATE | HITMARKER_IGNORE_DISGUISE - healthbarupdate BS_ATTACKER - datahpupdate BS_ATTACKER + healthbarupdate BS_ATTACKER, PASSIVE_HP_UPDATE + datahpupdate BS_ATTACKER, PASSIVE_HP_UPDATE printstring STRINGID_HURTBYITEM waitmessage B_WAIT_TIME_LONG tryfaintmon BS_ATTACKER @@ -8577,9 +7733,8 @@ BattleScript_ItemHealHP_Ret:: playanimation BS_ATTACKER, B_ANIM_HELD_ITEM_EFFECT printstring STRINGID_PKMNSITEMRESTOREDHPALITTLE waitmessage B_WAIT_TIME_LONG - orword gHitMarker, HITMARKER_IGNORE_BIDE | HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_IGNORE_DISGUISE | HITMARKER_PASSIVE_HP_UPDATE - healthbarupdate BS_ATTACKER - datahpupdate BS_ATTACKER + healthbarupdate BS_ATTACKER, PASSIVE_HP_UPDATE + datahpupdate BS_ATTACKER, PASSIVE_HP_UPDATE return BattleScript_SelectingNotAllowedMoveChoiceItem:: @@ -8632,9 +7787,8 @@ BattleScript_BerryConfuseHealEnd2_Anim: playanimation BS_SCRIPTING, B_ANIM_HELD_ITEM_EFFECT printstring STRINGID_PKMNSITEMRESTOREDHEALTH waitmessage B_WAIT_TIME_LONG - orword gHitMarker, HITMARKER_IGNORE_BIDE | HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_HP_UPDATE - healthbarupdate BS_SCRIPTING - datahpupdate BS_SCRIPTING + healthbarupdate BS_SCRIPTING, PASSIVE_HP_UPDATE + datahpupdate BS_SCRIPTING, PASSIVE_HP_UPDATE seteffectprimary BS_SCRIPTING, BS_SCRIPTING, MOVE_EFFECT_CONFUSION removeitem BS_SCRIPTING end2 @@ -8648,9 +7802,8 @@ BattleScript_BerryConfuseHealRet_Anim: playanimation BS_SCRIPTING, B_ANIM_HELD_ITEM_EFFECT printstring STRINGID_PKMNSITEMRESTOREDHEALTH waitmessage B_WAIT_TIME_LONG - orword gHitMarker, HITMARKER_IGNORE_BIDE | HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_HP_UPDATE - healthbarupdate BS_SCRIPTING - datahpupdate BS_SCRIPTING + healthbarupdate BS_SCRIPTING, PASSIVE_HP_UPDATE + datahpupdate BS_SCRIPTING, PASSIVE_HP_UPDATE seteffectprimary BS_SCRIPTING, BS_SCRIPTING, MOVE_EFFECT_CONFUSION removeitem BS_SCRIPTING return @@ -8660,24 +7813,22 @@ BattleScript_ConsumableStatRaiseEnd2:: end2 BattleScript_ConsumableStatRaiseRet:: - @ to ensure `statbuffchange` has correct battler id, backup and use target - savetarget - copybyte gBattlerTarget, sBATTLER jumpifnotberry BS_SCRIPTING, BattleScript_ConsumableStatRaiseRet_Anim - @ check ripen popup if consuming berry jumpifability BS_SCRIPTING, ABILITY_RIPEN, BattleScript_ConsumableStatRaiseRet_AbilityPopup goto BattleScript_ConsumableStatRaiseRet_Anim BattleScript_ConsumableStatRaiseRet_AbilityPopup: call BattleScript_AbilityPopUp BattleScript_ConsumableStatRaiseRet_Anim: - statbuffchange BS_TARGET, STAT_CHANGE_ALLOW_PTR | STAT_CHANGE_ONLY_CHECKING, BattleScript_ConsumableStatRaiseRet_End + statbuffchange BS_SCRIPTING, STAT_CHANGE_ALLOW_PTR | STAT_CHANGE_ONLY_CHECKING, BattleScript_ConsumableStatRaiseRet_End playanimation BS_SCRIPTING, B_ANIM_HELD_ITEM_EFFECT, sB_ANIM_ARG1 - statbuffchange BS_TARGET, STAT_CHANGE_ALLOW_PTR, BattleScript_ConsumableStatRaiseRet_End - setbyte cMULTISTRING_CHOOSER, B_MSG_STAT_ROSE_ITEM + statbuffchange BS_SCRIPTING, STAT_CHANGE_ALLOW_PTR, BattleScript_ConsumableStatRaiseRet_End + setbyte cMULTISTRING_CHOOSER, B_MSG_STAT_CHANGED_ITEM + savetarget + copybyte gBattlerTarget, sBATTLER @ BattleScript_StatUp uses target as a message arg call BattleScript_StatUp + restoretarget removeitem BS_SCRIPTING BattleScript_ConsumableStatRaiseRet_End: - restoretarget return BattleScript_BerryFocusEnergyRet:: @@ -8841,7 +7992,7 @@ BattleScript_MirrorHerbCopyStatChange:: removeitem BS_SCRIPTING BattleScript_MirrorHerbStartCopyStats: copyfoesstatincrease BS_SCRIPTING, BattleScript_MirrorHerbStartReturn - statbuffchange BS_TARGET, STAT_CHANGE_ALLOW_PTR, BattleScript_MirrorHerbStartReturn + statbuffchange BS_SCRIPTING, STAT_CHANGE_ALLOW_PTR, BattleScript_MirrorHerbStartReturn setbyte sSTAT_ANIM_PLAYED, TRUE @ play stat change animation only once goto BattleScript_MirrorHerbStartCopyStats BattleScript_MirrorHerbStartReturn: @@ -8852,13 +8003,17 @@ BattleScript_OpportunistCopyStatChange:: call BattleScript_AbilityPopUpScripting BattleScript_OpportunistStartCopyStats: copyfoesstatincrease BS_SCRIPTING, BattleScript_OpportunistCopyStatChangeEnd - statbuffchange BS_TARGET, STAT_CHANGE_ALLOW_PTR, BattleScript_OpportunistCopyStatChangeEnd + statbuffchange BS_SCRIPTING, STAT_CHANGE_ALLOW_PTR, BattleScript_OpportunistCopyStatChangeEnd printfromtable gStatUpStringIds waitmessage B_WAIT_TIME_LONG setbyte sSTAT_ANIM_PLAYED, TRUE @ play stat change animation only once goto BattleScript_OpportunistStartCopyStats BattleScript_OpportunistCopyStatChangeEnd: setbyte sSTAT_ANIM_PLAYED, FALSE + return + +BattleScript_OpportunistCopyStatChangeEnd3:: + call BattleScript_OpportunistCopyStatChange end3 BattleScript_TotemVar:: @@ -8957,7 +8112,7 @@ BattleScript_MicleBerryActivateRet:: jumpifability BS_SCRIPTING, ABILITY_RIPEN, BattleScript_MicleBerryActivateRet_Ripen goto BattleScript_MicleBerryActivateRet_Anim BattleScript_MicleBerryActivateRet_Ripen: - call BattleScript_AbilityPopUp + call BattleScript_AbilityPopUpScripting BattleScript_MicleBerryActivateRet_Anim: playanimation BS_SCRIPTING, B_ANIM_HELD_ITEM_EFFECT printstring STRINGID_MICLEBERRYACTIVATES @@ -9000,31 +8155,21 @@ BattleScript_ZMoveActivateStatus:: copybyte sSTATCHANGER, sSAVED_STAT_CHANGER return -BattleScript_ZMoveActivatePowder:: - flushtextbox - trytrainerslidezmovemsg - savetarget - printstring STRINGID_ZPOWERSURROUNDS - playanimation BS_ATTACKER, B_ANIM_ZMOVE_ACTIVATE, NULL - setzeffect - restoretarget - goto BattleScript_MoveUsedPowder - BattleScript_ZEffectPrintString:: printfromtable gZEffectStringIds waitmessage B_WAIT_TIME_LONG return BattleScript_RecoverHPZMove:: - healthbarupdate BS_SCRIPTING - datahpupdate BS_SCRIPTING + healthbarupdate BS_SCRIPTING, PASSIVE_HP_UPDATE + datahpupdate BS_SCRIPTING, PASSIVE_HP_UPDATE printfromtable gZEffectStringIds waitmessage B_WAIT_TIME_LONG return BattleScript_StatUpZMove:: statbuffchange BS_ATTACKER, STAT_CHANGE_ALLOW_PTR, BattleScript_StatUpZMoveEnd - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_StatUpZMoveEnd + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_StatUpZMoveEnd printstring STRINGID_ZMOVESTATUP waitmessage B_WAIT_TIME_LONG printfromtable gStatUpStringIds @@ -9036,14 +8181,12 @@ BattleScript_HealReplacementZMove:: playanimation BS_SCRIPTING, B_ANIM_WISH_HEAL, 0x0 printfromtable gZEffectStringIds waitmessage B_WAIT_TIME_LONG - healthbarupdate BS_SCRIPTING - datahpupdate BS_SCRIPTING + healthbarupdate BS_SCRIPTING, PASSIVE_HP_UPDATE + datahpupdate BS_SCRIPTING, PASSIVE_HP_UPDATE return BattleScript_EffectExtremeEvoboost:: attackcanceler - attackstring - ppreduce jumpifstat BS_ATTACKER, CMP_LESS_THAN, STAT_ATK, MAX_STAT_STAGE, BattleScript_ExtremeEvoboostAnim jumpifstat BS_ATTACKER, CMP_LESS_THAN, STAT_DEF, MAX_STAT_STAGE, BattleScript_ExtremeEvoboostAnim jumpifstat BS_ATTACKER, CMP_LESS_THAN, STAT_SPEED, MAX_STAT_STAGE, BattleScript_ExtremeEvoboostAnim @@ -9080,38 +8223,6 @@ BattleScript_ExtremeEvoboostSpDef:: BattleScript_ExtremeEvoboostEnd:: goto BattleScript_MoveEnd -BattleScript_EffectHitSetTerrain:: - attackcanceler - accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE - attackstring - ppreduce - critcalc - damagecalc - adjustdamage - attackanimation - waitanimation - effectivenesssound - hitanimation BS_TARGET - waitstate - healthbarupdate BS_TARGET - datahpupdate BS_TARGET - critmessage - waitmessage B_WAIT_TIME_LONG - resultmessage - waitmessage B_WAIT_TIME_LONG - setterrain BattleScript_TryFaint - playanimation BS_ATTACKER, B_ANIM_RESTORE_BG - printfromtable gTerrainStringIds - waitmessage B_WAIT_TIME_LONG -BattleScript_TryFaint: - tryfaintmon BS_TARGET - goto BattleScript_MoveEnd - -BattleScript_EffectSteelRoller:: - attackcanceler - jumpifhalfword CMP_NO_COMMON_BITS, gFieldStatuses, STATUS_FIELD_TERRAIN_ANY, BattleScript_FailedFromAtkString - goto BattleScript_HitFromAccCheck - BattleScript_RemoveTerrain:: removeterrain playanimation BS_ATTACKER, B_ANIM_RESTORE_BG @@ -9225,8 +8336,6 @@ BattleScript_EjectPackActivates:: goto BattleScript_EjectPackActivate_Ret BattleScript_DoesntAffectTargetAtkString:: - attackstring - ppreduce pause B_WAIT_TIME_SHORT printstring STRINGID_ITDOESNTAFFECT waitmessage B_WAIT_TIME_LONG @@ -9234,8 +8343,6 @@ BattleScript_DoesntAffectTargetAtkString:: goto BattleScript_MoveEnd BattleScript_WellBakedBodyActivates:: - attackstring - ppreduce pause B_WAIT_TIME_SHORT call BattleScript_AbilityPopUpTarget setmoveresultflags MOVE_RESULT_NO_EFFECT @@ -9244,8 +8351,6 @@ BattleScript_WellBakedBodyEnd: goto BattleScript_MoveEnd BattleScript_WindRiderActivatesMoveEnd:: - attackstring - ppreduce pause B_WAIT_TIME_SHORT call BattleScript_AbilityPopUpTarget setmoveresultflags MOVE_RESULT_NO_EFFECT @@ -9254,8 +8359,6 @@ BattleScript_WindRiderActivatesMoveEnd_End: goto BattleScript_MoveEnd BattleScript_GoodAsGoldActivates:: - attackstring - ppreduce call BattleScript_AbilityPopUpTarget pause B_WAIT_TIME_SHORT printstring STRINGID_ITDOESNTAFFECT @@ -9296,8 +8399,7 @@ BattleScript_NeutralizingGasExits:: setbyte gBattlerAttacker, 0 BattleScript_NeutralizingGasExitsLoop: copyarraywithindex gBattlerTarget, gBattlerByTurnOrder, gBattlerAttacker, 1 - jumpifabilitycantbesuppressed BS_TARGET, BattleScript_NeutralizingGasExitsLoopIncrement - jumpifability BS_TARGET, ABILITY_IMPOSTER, BattleScript_NeutralizingGasExitsLoopIncrement @ Imposter only activates when first entering the field + jumpifabilitycantbereactivated BS_TARGET, BattleScript_NeutralizingGasExitsLoopIncrement saveattacker switchinabilities BS_TARGET restoreattacker @@ -9320,21 +8422,20 @@ BattleScript_SymbiosisActivates:: return BattleScript_TargetAbilityStatRaiseRet:: - copybyte sSAVED_BATTLER, gBattlerAttacker - copybyte gBattlerAbility, gEffectBattler - copybyte gBattlerAttacker, gBattlerTarget + saveattacker + copybyte gBattlerAttacker, gEffectBattler call BattleScript_AbilityPopUp statbuffchange BS_ATTACKER, STAT_CHANGE_CERTAIN, BattleScript_TargetAbilityStatRaiseRet_End call BattleScript_StatUp BattleScript_TargetAbilityStatRaiseRet_End: - copybyte gBattlerAttacker, sSAVED_BATTLER + restoreattacker return @@@ MAX MOVES @@@ BattleScript_EffectMaxMove:: attackcanceler accuracycheck BattleScript_ButItFailed, NO_ACC_CALC_CHECK_LOCK_ON - goto BattleScript_HitFromAtkString + goto BattleScript_HitFromCritCalc BattleScript_EffectRaiseStatAllies:: savetarget @@ -9344,7 +8445,7 @@ BattleScript_RaiseSideStatsLoop: jumpifabsent BS_TARGET, BattleScript_RaiseSideStatsIncrement copybyte sSTATCHANGER, sSAVED_STAT_CHANGER statbuffchange BS_TARGET, STAT_CHANGE_ALLOW_PTR, BattleScript_RaiseSideStatsIncrement - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_RaiseSideStatsIncrement + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_RaiseSideStatsIncrement printfromtable gStatUpStringIds waitmessage B_WAIT_TIME_LONG BattleScript_RaiseSideStatsIncrement: @@ -9362,7 +8463,7 @@ BattleScript_LowerSideStatsLoop: jumpifabsent BS_TARGET, BattleScript_LowerSideStatsIncrement copybyte sSTATCHANGER, sSAVED_STAT_CHANGER statbuffchange BS_TARGET, STAT_CHANGE_ALLOW_PTR, BattleScript_LowerSideStatsIncrement - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_DECREASE, BattleScript_LowerSideStatsIncrement + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_LowerSideStatsIncrement printfromtable gStatDownStringIds waitmessage B_WAIT_TIME_LONG BattleScript_LowerSideStatsIncrement: @@ -9555,9 +8656,8 @@ BattleScript_EffectHealOneSixthAllies:: BattleScript_HealOneSixthAlliesLoop: jumpifabsent BS_TARGET, BattleScript_HealOneSixthAlliesIncrement tryhealsixthhealth BattleScript_HealOneSixthAlliesIncrement - orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE - healthbarupdate BS_TARGET - datahpupdate BS_TARGET + healthbarupdate BS_TARGET, PASSIVE_HP_UPDATE + datahpupdate BS_TARGET, PASSIVE_HP_UPDATE printstring STRINGID_PKMNREGAINEDHEALTH waitmessage B_WAIT_TIME_LONG BattleScript_HealOneSixthAlliesIncrement: @@ -9639,19 +8739,13 @@ BattleScript_DynamaxEnds_Ret:: return BattleScript_MoveBlockedByDynamax:: - accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE - attackstring + accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE pause B_WAIT_TIME_SHORT - ppreduce - jumpifword CMP_COMMON_BITS, gHitMarker, HITMARKER_STRING_PRINTED, BattleScript_MoveEnd printstring STRINGID_MOVEBLOCKEDBYDYNAMAX waitmessage B_WAIT_TIME_LONG - orword gHitMarker, HITMARKER_STRING_PRINTED goto BattleScript_MoveEnd BattleScript_PokemonCantUseTheMove:: - attackstring - ppreduce pause B_WAIT_TIME_SHORT printstring STRINGID_BUTPOKEMONCANTUSETHEMOVE waitmessage B_WAIT_TIME_LONG @@ -9663,18 +8757,15 @@ BattleScript_CouldntFullyProtect:: return BattleScript_BerserkGeneRet:: - saveattacker - savetarget - copybyte gBattlerTarget, sBATTLER - statbuffchange BS_TARGET, STAT_CHANGE_ALLOW_PTR | STAT_CHANGE_ONLY_CHECKING, BattleScript_BerserkGeneRet_TryConfuse - playanimation BS_ATTACKER, B_ANIM_HELD_ITEM_EFFECT, sB_ANIM_ARG1 - statbuffchange BS_TARGET, STAT_CHANGE_ALLOW_PTR, BattleScript_BerserkGeneRet_TryConfuse - setbyte cMULTISTRING_CHOOSER, B_MSG_STAT_ROSE_ITEM + statbuffchange BS_SCRIPTING, STAT_CHANGE_ALLOW_PTR | STAT_CHANGE_ONLY_CHECKING, BattleScript_BerserkGeneRet_TryConfuse + playanimation BS_SCRIPTING, B_ANIM_HELD_ITEM_EFFECT, sB_ANIM_ARG1 + statbuffchange BS_SCRIPTING, STAT_CHANGE_ALLOW_PTR, BattleScript_BerserkGeneRet_TryConfuse + setbyte cMULTISTRING_CHOOSER, B_MSG_STAT_CHANGED_ITEM call BattleScript_StatUp BattleScript_BerserkGeneRet_TryConfuse: - jumpifability BS_ATTACKER, ABILITY_OWN_TEMPO, BattleScript_BerserkGeneRet_OwnTempoPrevents + jumpifability BS_SCRIPTING, ABILITY_OWN_TEMPO, BattleScript_BerserkGeneRet_OwnTempoPrevents jumpifsafeguard BattleScript_BerserkGeneRet_SafeguardProtected - seteffectprimary BS_ATTACKER, BS_ATTACKER, MOVE_EFFECT_CONFUSION + seteffectprimary BS_SCRIPTING, BS_SCRIPTING, MOVE_EFFECT_CONFUSION goto BattleScript_BerserkGeneRet_End BattleScript_BerserkGeneRet_SafeguardProtected:: pause B_WAIT_TIME_SHORT @@ -9683,13 +8774,11 @@ BattleScript_BerserkGeneRet_SafeguardProtected:: goto BattleScript_BerserkGeneRet_End BattleScript_BerserkGeneRet_OwnTempoPrevents: pause B_WAIT_TIME_SHORT - call BattleScript_AbilityPopUp + call BattleScript_AbilityPopUpScripting printstring STRINGID_PKMNPREVENTSCONFUSIONWITH waitmessage B_WAIT_TIME_LONG BattleScript_BerserkGeneRet_End: - restoreattacker - restoretarget - removeitem BS_ATTACKER + removeitem BS_SCRIPTING return BattleScript_BerserkGeneRetEnd2:: @@ -9712,8 +8801,6 @@ BattleScript_BoosterEnergyRet:: BattleScript_EffectSnow:: attackcanceler - attackstring - ppreduce call BattleScript_CheckPrimalWeather setfieldweather BATTLE_WEATHER_SNOW goto BattleScript_MoveWeatherChange @@ -9745,3 +8832,62 @@ BattleScript_ForfeitBattleGaveMoney:: .endif waitmessage B_WAIT_TIME_LONG end2 + +BattleScript_Attackstring:: + printattackstring + return + +BattleScript_SubmoveAttackstring:: + printattackstring + pause B_WAIT_TIME_LONG + attackanimation + waitanimation + setcalledmove + return + +BattleScript_SleepTalkAttackstring:: + printattackstring + pause B_WAIT_TIME_LONG + printstring STRINGID_PKMNFASTASLEEP + waitmessage B_WAIT_TIME_LONG + statusanimation BS_ATTACKER + attackanimation + waitanimation + setcalledmove + return + +BattleScript_MetronomeAttackstring:: + printattackstring + pause B_WAIT_TIME_LONG + attackanimation + waitanimation + setcalledmove + printstring STRINGID_WAGGLINGAFINGER + waitmessage B_WAIT_TIME_LONG + return + +BattleScript_NaturePowerAttackstring:: + printattackstring + pause B_WAIT_TIME_SHORT + setcalledmove + printstring STRINGID_NATUREPOWERTURNEDINTO + waitmessage B_WAIT_TIME_LONG + return + +BattleScript_SwapFromSubstitute:: + jumpifvolatile BS_SCRIPTING, VOLATILE_SUBSTITUTE, BattleScript_SwapFromSubstituteContinue + goto BattleScript_SwapFromSubstituteReturn +BattleScript_SwapFromSubstituteContinue: + playanimation BS_SCRIPTING, B_ANIM_SWAP_FROM_SUBSTITUTE + waitanimation +BattleScript_SwapFromSubstituteReturn: + return + +BattleScript_SwapToSubstitute:: + jumpifvolatile BS_SCRIPTING, VOLATILE_SUBSTITUTE, BattleScript_SwapToSubstituteContinue + goto BattleScript_SwapToSubstituteReturn +BattleScript_SwapToSubstituteContinue: + playanimation BS_SCRIPTING, B_ANIM_SWAP_TO_SUBSTITUTE + waitanimation +BattleScript_SwapToSubstituteReturn: + return diff --git a/data/battle_scripts_2.s b/data/battle_scripts_2.s index 586a79c5ef..5f7cc23a8c 100755 --- a/data/battle_scripts_2.s +++ b/data/battle_scripts_2.s @@ -49,9 +49,8 @@ BattleScript_UseItemMessage: BattleScript_ItemRestoreHPRet: clearmoveresultflags MOVE_RESULT_NO_EFFECT - orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE - healthbarupdate BS_SCRIPTING - datahpupdate BS_SCRIPTING + healthbarupdate BS_SCRIPTING, PASSIVE_HP_UPDATE + datahpupdate BS_SCRIPTING, PASSIVE_HP_UPDATE printstring STRINGID_ITEMRESTOREDSPECIESHEALTH waitmessage B_WAIT_TIME_LONG return @@ -75,6 +74,10 @@ BattleScript_ItemRestoreHP_Party:: return BattleScript_ItemRestoreHP_SendOutRevivedBattler: + switchhandleorder BS_SCRIPTING, 0 + getswitchedmondata BS_SCRIPTING + switchindataupdate BS_SCRIPTING + trytoclearprimalweather switchinanim BS_SCRIPTING, FALSE, FALSE waitstate switchineffects BS_SCRIPTING @@ -83,13 +86,18 @@ BattleScript_ItemRestoreHP_SendOutRevivedBattler: BattleScript_ItemCureStatus:: call BattleScript_UseItemMessage BattleScript_ItemCureStatusAfterItemMsg: - itemcurestatus BattleScript_ItemCureStatusEnd - updatestatusicon BS_SCRIPTING + itemcurestatus BattleScript_ItemCureStatusEnd, BattleScript_CureStatus_Battler printstring STRINGID_ITEMCUREDSPECIESSTATUS waitmessage B_WAIT_TIME_LONG BattleScript_ItemCureStatusEnd: end +BattleScript_CureStatus_Battler:: + updatestatusicon BS_SCRIPTING + printstring STRINGID_ITEMCUREDSPECIESSTATUS + waitmessage B_WAIT_TIME_LONG + end + BattleScript_ItemHealAndCureStatus:: call BattleScript_UseItemMessage itemrestorehp BattleScript_ItemCureStatusAfterItemMsg, BattleScript_ItemHealAndCureStatus_Battler diff --git a/data/event_scripts.s b/data/event_scripts.s index 1ddb33c9d2..c810f13cb3 100644 --- a/data/event_scripts.s +++ b/data/event_scripts.s @@ -3,6 +3,7 @@ #include "config/item.h" #include "constants/global.h" #include "constants/apprentice.h" +#include "constants/apricorn_tree.h" #include "constants/battle.h" #include "constants/battle_arena.h" #include "constants/battle_dome.h" @@ -43,6 +44,7 @@ #include "constants/maps.h" #include "constants/mauville_old_man.h" #include "constants/metatile_labels.h" +#include "constants/move_relearner.h" #include "constants/moves.h" #include "constants/party_menu.h" #include "constants/pokedex.h" @@ -62,6 +64,7 @@ #include "constants/union_room.h" #include "constants/vars.h" #include "constants/weather.h" +#include "constants/speaker_names.h" .include "asm/macros.inc" .include "asm/macros/event.inc" .include "constants/constants.inc" @@ -71,6 +74,7 @@ .set ALLOCATE_SCRIPT_CMD_TABLE, 1 .include "data/script_cmd_table.inc" +.align 2 gSpecialVars:: .4byte gSpecialVar_0x8000 .4byte gSpecialVar_0x8001 @@ -695,6 +699,7 @@ EventScript_SetBrineyLocation_Route109:: .include "data/scripts/obtain_item.inc" .include "data/scripts/record_mix.inc" .include "data/scripts/pc.inc" + .include "data/scripts/move_relearner.inc" @ scripts/notices.inc? signs.inc? See comment about text/notices.inc Common_EventScript_ShowPokemartSign:: @@ -880,6 +885,7 @@ Common_EventScript_PlayerHandedOverTheItem:: .include "data/text/pkmn_center_nurse.inc" .include "data/text/mart_clerk.inc" .include "data/text/obtain_item.inc" + .include "data/text/move_relearner.inc" @ The below and surf.inc could be split into some text/notices.inc gText_PokemartSign:: @@ -1109,9 +1115,6 @@ EventScript_VsSeekerChargingDone:: .include "data/scripts/cable_club.inc" .include "data/text/cable_club.inc" .include "data/scripts/contest_hall.inc" - .include "data/text/contest_strings.inc" - .include "data/text/contest_link.inc" - .include "data/text/contest_painting.inc" .include "data/scripts/tv.inc" .include "data/text/tv.inc" .include "data/scripts/interview.inc" @@ -1155,3 +1158,5 @@ EventScript_VsSeekerChargingDone:: .include "data/text/save.inc" .include "data/text/birch_speech.inc" .include "data/scripts/dexnav.inc" + .include "data/scripts/battle_frontier.inc" + .include "data/scripts/apricorn_tree.inc" diff --git a/data/field_effect_scripts.s b/data/field_effect_scripts.s index 34678bb293..ce71a102fd 100644 --- a/data/field_effect_scripts.s +++ b/data/field_effect_scripts.s @@ -83,6 +83,7 @@ gFieldEffectScriptPointers:: .4byte gFieldEffectScript_Defog @ FLDEFF_DEFOG .4byte gFieldEffectScript_UseRockClimb @ FLDEFF_USE_ROCK_CLIMB .4byte gFieldEffectScript_RockClimbDust @ FLDEFF_ROCK_CLIMB_DUST + .4byte gFieldEffectScript_ORASDowse @ FLDEFF_ORAS_DOWSE gFieldEffectScript_ExclamationMarkIcon1:: field_eff_callnative FldEff_ExclamationMarkIcon @@ -386,6 +387,7 @@ gFieldEffectScript_CaveDust:: gFieldEffectScript_Defog:: field_eff_callnative FldEff_Defog field_eff_end + gFieldEffectScript_UseRockClimb:: @ 82DBC3F field_eff_callnative FldEff_UseRockClimb field_eff_end @@ -394,3 +396,7 @@ gFieldEffectScript_RockClimbDust:: @ 82DBB28 field_eff_loadfadedpal_callnative gSpritePalette_BigDust, FldEff_RockClimbDust field_eff_end +gFieldEffectScript_ORASDowse:: + field_eff_callnative FldEff_ORASDowsing + field_eff_end + diff --git a/data/map_events.s b/data/map_events.s index 729f9725df..13064da025 100644 --- a/data/map_events.s +++ b/data/map_events.s @@ -13,6 +13,7 @@ #include "constants/trainer_types.h" #include "constants/berry.h" #include "constants/species.h" +#include "constants/apricorn_tree.h" .include "asm/macros.inc" .include "constants/constants.inc" diff --git a/data/maps/BattleFrontier_BattleArenaLobby/scripts.inc b/data/maps/BattleFrontier_BattleArenaLobby/scripts.inc index 72262798eb..572413d8e1 100644 --- a/data/maps/BattleFrontier_BattleArenaLobby/scripts.inc +++ b/data/maps/BattleFrontier_BattleArenaLobby/scripts.inc @@ -182,10 +182,14 @@ BattleFrontier_BattleArenaLobby_EventScript_NotEnoughValidMons:: BattleFrontier_BattleArenaLobby_EventScript_NotEnoughValidMonsLv50:: msgbox BattleFrontier_BattleArenaLobby_Text_NotEnoughValidMonsLv50, MSGBOX_DEFAULT + call BattleFrontier_ShowCaughtBannedSpecies + msgbox BattleFrontier_BattleArenaLobby_Text_NotEnoughValidMonsEnd, MSGBOX_DEFAULT goto BattleFrontier_BattleArenaLobby_EventScript_EndCancelChallenge BattleFrontier_BattleArenaLobby_EventScript_NotEnoughValidMonsLvOpen:: msgbox BattleFrontier_BattleArenaLobby_Text_NotEnoughValidMonsLvOpen, MSGBOX_DEFAULT + call BattleFrontier_ShowCaughtBannedSpecies + msgbox BattleFrontier_BattleArenaLobby_Text_NotEnoughValidMonsEnd, MSGBOX_DEFAULT goto BattleFrontier_BattleArenaLobby_EventScript_EndCancelChallenge BattleFrontier_BattleArenaLobby_EventScript_CancelChallengeSaveFailed:: @@ -375,10 +379,13 @@ BattleFrontier_BattleArenaLobby_Text_SelectThreeMons: .string "好的,\n请选择参加的3只宝可梦。$" BattleFrontier_BattleArenaLobby_Text_NotEnoughValidMonsLvOpen: - .string "尊敬的挑战者!\p您能够参加对战的\n宝可梦不满3只。\p您需要准备3只\n不同种类的宝可梦,\p且让它们分别携带不同道具\n才可参加对战。\p此外,蛋{STR_VAR_1}无法参加对战!\p请在准备就绪之后,\n再来参加吧!$" + .string "尊敬的挑战者!\p您能够参加对战的\n宝可梦不满3只。\p您需要准备3只\n不同种类的宝可梦,\p且让它们分别携带不同道具\n才可参加对战。\p此外,蛋{STR_VAR_1}。$" + +BattleFrontier_BattleArenaLobby_Text_NotEnoughValidMonsEnd: + .string "无法参加对战!\p请在准备就绪之后,\n再来参加吧!$" BattleFrontier_BattleArenaLobby_Text_NotEnoughValidMonsLv50: - .string "尊敬的挑战者!\p您能够参加对战的\n宝可梦不满3只。\p您需要准备3只等级50以内的\n不同种类的宝可梦,\p且让它们分别携带不同道具\n才可参加对战。\p此外,蛋{STR_VAR_1}无法参加对战!\p请在准备就绪之后,\n再来参加吧!$" + .string "尊敬的挑战者!\p您能够参加对战的\n宝可梦不满3只。\p您需要准备3只等级50以内的\n不同种类的宝可梦,\p且让它们分别携带不同道具\n才可参加对战。\p此外,蛋{STR_VAR_1}。$" BattleFrontier_BattleArenaLobby_Text_GuideYouToArena: .string "现在我将带您前往对战竞技场。$" diff --git a/data/maps/BattleFrontier_BattleDomeLobby/scripts.inc b/data/maps/BattleFrontier_BattleDomeLobby/scripts.inc index b435a50028..be5605dbc2 100644 --- a/data/maps/BattleFrontier_BattleDomeLobby/scripts.inc +++ b/data/maps/BattleFrontier_BattleDomeLobby/scripts.inc @@ -210,10 +210,14 @@ BattleFrontier_BattleDomeLobby_EventScript_NotEnoughValidMons:: BattleFrontier_BattleDomeLobby_EventScript_NotEnoughValidMonsLv50:: msgbox BattleFrontier_BattleDomeLobby_Text_NotEnoughValidMonsLv50, MSGBOX_DEFAULT + call BattleFrontier_ShowCaughtBannedSpecies + msgbox BattleFrontier_BattleDomeLobby_Text_NotEnoughValidMonsEnd, MSGBOX_DEFAULT goto BattleFrontier_BattleDomeLobby_EventScript_EndCancelChallenge BattleFrontier_BattleDomeLobby_EventScript_NotEnoughValidMonsLvOpen:: msgbox BattleFrontier_BattleDomeLobby_Text_NotEnoughValidMonsLvOpen, MSGBOX_DEFAULT + call BattleFrontier_ShowCaughtBannedSpecies + msgbox BattleFrontier_BattleDomeLobby_Text_NotEnoughValidMonsEnd, MSGBOX_DEFAULT goto BattleFrontier_BattleDomeLobby_EventScript_EndCancelChallenge BattleFrontier_BattleDomeLobby_EventScript_CancelChallengeSaveFailed:: @@ -455,10 +459,13 @@ BattleFrontier_BattleDomeLobby_Text_SelectThreeMons: .string "请挑选参加的\n3只宝可梦。$" BattleFrontier_BattleDomeLobby_Text_NotEnoughValidMonsLvOpen: - .string "很抱歉!\p您能够参加对战的\n宝可梦不满3只。\p您需要准备3只不同种类的\n宝可梦,\p且让它们分别携带不同道具\n才可参加对战。\p此外,蛋{STR_VAR_1}无法参加对战!\p请在准备就绪之后,\n再来参加吧!$" + .string "很抱歉!\p您能够参加对战的\n宝可梦不满3只。\p您需要准备3只不同种类的\n宝可梦,\p且让它们分别携带不同道具\n才可参加对战。\p此外,蛋{STR_VAR_1}!$" + +BattleFrontier_BattleDomeLobby_Text_NotEnoughValidMonsEnd: + .string "请在准备就绪之后,\n再来参加吧!$" BattleFrontier_BattleDomeLobby_Text_NotEnoughValidMonsLv50: - .string "很抱歉!\p您能够参加对战的\n宝可梦不满3只。\p您需要准备3只等级50以内的\n不同种类的宝可梦,\p且让它们分别携带不同道具\n才可参加对战。\p此外,蛋{STR_VAR_1}无法参加对战!\p请在准备就绪之后,\n再来参加吧!$" + .string "很抱歉!\p您能够参加对战的\n宝可梦不满3只。\p您需要准备3只等级50以内的\n不同种类的宝可梦,\p且让它们分别携带不同道具\n才可参加对战。\p此外,蛋{STR_VAR_1}!$" BattleFrontier_BattleDomeLobby_Text_ShowYouToBattleDome: .string "现在我将带您前往\n对战巨蛋。$" diff --git a/data/maps/BattleFrontier_BattlePalaceLobby/scripts.inc b/data/maps/BattleFrontier_BattlePalaceLobby/scripts.inc index b7dd33de92..3c07a4771b 100644 --- a/data/maps/BattleFrontier_BattlePalaceLobby/scripts.inc +++ b/data/maps/BattleFrontier_BattlePalaceLobby/scripts.inc @@ -202,10 +202,14 @@ BattleFrontier_BattlePalaceLobby_EventScript_NotEnoughValidMons:: BattleFrontier_BattlePalaceLobby_EventScript_NotEnoughValidMonsLv50:: msgbox BattleFrontier_BattlePalaceLobby_Text_NotEnoughValidMonsLv50, MSGBOX_DEFAULT + call BattleFrontier_ShowCaughtBannedSpecies + msgbox BattleFrontier_BattlePalaceLobby_Text_NotEnoughValidMonsEnd, MSGBOX_DEFAULT goto BattleFrontier_BattlePalaceLobby_EventScript_EndCancelChallenge BattleFrontier_BattlePalaceLobby_EventScript_NotEnoughValidMonsLvOpen:: msgbox BattleFrontier_BattlePalaceLobby_Text_NotEnoughValidMonsLvOpen, MSGBOX_DEFAULT + call BattleFrontier_ShowCaughtBannedSpecies + msgbox BattleFrontier_BattlePalaceLobby_Text_NotEnoughValidMonsEnd, MSGBOX_DEFAULT goto BattleFrontier_BattlePalaceLobby_EventScript_EndCancelChallenge BattleFrontier_BattlePalaceLobby_EventScript_CancelChallengeSaveFailed:: @@ -390,10 +394,13 @@ BattleFrontier_BattlePalaceLobby_Text_WhichChallenge: .string "对战厅有2种,\nLv. 50级和自由等级,\l您要挑战哪种?$" BattleFrontier_BattlePalaceLobby_Text_NotEnoughValidMonsLv50: - .string "哎……\p您能够参加对战的\n宝可梦不满3只。\p您需要准备3只等级50以内的\n不同种类的宝可梦,\p并且让它们分别携带不同道具\n才可参加对战。\p此外,蛋{STR_VAR_1}无法参加对战!\p请在准备就绪之后,\n再来参加吧。$" + .string "哎……\p您能够参加对战的\n宝可梦不满3只。\p您需要准备3只等级50以内的\n不同种类的宝可梦,\p并且让它们分别携带不同道具\n才可参加对战。\p此外,蛋{STR_VAR_1}!$" + +BattleFrontier_BattlePalaceLobby_Text_NotEnoughValidMonsEnd: + .string "请在准备就绪之后,\n再来参加吧。$" BattleFrontier_BattlePalaceLobby_Text_NotEnoughValidMonsLvOpen: - .string "哎……\p您能够参加对战的\n宝可梦不满3只。\p您需要准备3只\n不同种类的宝可梦,\p并且让它们分别携带不同道具\n才可参加对战。\p此外,蛋{STR_VAR_1}无法参加对战!\p请在准备就绪之后,\n再来参加吧。$" + .string "哎……\p您能够参加对战的\n宝可梦不满3只。\p您需要准备3只\n不同种类的宝可梦,\p并且让它们分别携带不同道具\n才可参加对战。\p此外,蛋{STR_VAR_1}!$" BattleFrontier_BattlePalaceLobby_Text_NowSelectThreeMons: .string "好的。那么请选择要参加的\n3只宝可梦。$" diff --git a/data/maps/BattleFrontier_BattlePikeLobby/scripts.inc b/data/maps/BattleFrontier_BattlePikeLobby/scripts.inc index 17a5fe5bfd..0ac4088e81 100644 --- a/data/maps/BattleFrontier_BattlePikeLobby/scripts.inc +++ b/data/maps/BattleFrontier_BattlePikeLobby/scripts.inc @@ -172,10 +172,14 @@ BattleFrontier_BattlePikeLobby_EventScript_NotEnoughValidMons:: BattleFrontier_BattlePikeLobby_EventScript_NotEnoughValidMonsLv50:: msgbox BattleFrontier_BattlePikeLobby_Text_NotEnoughValidMonsLv50, MSGBOX_DEFAULT + call BattleFrontier_ShowCaughtBannedSpecies + msgbox BattleFrontier_BattlePikeLobby_Text_NotEnoughValidMonsEnd, MSGBOX_DEFAULT goto BattleFrontier_BattlePikeLobby_EventScript_EndCancelChallenge BattleFrontier_BattlePikeLobby_EventScript_NotEnoughValidMonsLvOpen:: msgbox BattleFrontier_BattlePikeLobby_Text_NotEnoughValidMonsLvOpen, MSGBOX_DEFAULT + call BattleFrontier_ShowCaughtBannedSpecies + msgbox BattleFrontier_BattlePikeLobby_Text_NotEnoughValidMonsEnd, MSGBOX_DEFAULT goto BattleFrontier_BattlePikeLobby_EventScript_EndCancelChallenge BattleFrontier_BattlePikeLobby_EventScript_CancelChallengeSaveFailed:: @@ -285,10 +289,13 @@ BattleFrontier_BattlePikeLobby_Text_WhichChallengeMode: .string "您有2个选择,\nLv. 50级和自由等级。\l要挑战哪个?$" BattleFrontier_BattlePikeLobby_Text_NotEnoughValidMonsLv50: - .string "冒昧打扰,但……\p您能够参加对战的\n宝可梦不满3只。\p您需要准备3只等级50以内的\n不同种类的宝可梦,\p并且让它们分别携带不同道具\n才可参加对战。\p此外,蛋{STR_VAR_1}无法参加对战!\p请在准备就绪之后,\n再来参加吧……$" + .string "冒昧打扰,但……\p您能够参加对战的\n宝可梦不满3只。\p您需要准备3只等级50以内的\n不同种类的宝可梦,\p并且让它们分别携带不同道具\n才可参加对战。\p此外,蛋{STR_VAR_1}!$" + +BattleFrontier_BattlePikeLobby_Text_NotEnoughValidMonsEnd: + .string "请在准备就绪之后,\n再来参加吧……$" BattleFrontier_BattlePikeLobby_Text_NotEnoughValidMonsLvOpen: - .string "冒昧打扰,但……\p您能够参加对战的\n宝可梦不满3只。\p您需要准备3只\n不同种类的宝可梦,\p并且让它们分别携带不同道具\n才可参加对战。\p此外,蛋{STR_VAR_1}无法参加对战!\p请在准备就绪之后,\n再来参加吧……$" + .string "冒昧打扰,但……\p您能够参加对战的\n宝可梦不满3只。\p您需要准备3只\n不同种类的宝可梦,\p并且让它们分别携带不同道具\n才可参加对战。\p此外,蛋{STR_VAR_1}!$" BattleFrontier_BattlePikeLobby_Text_PleaseChooseThreeMons: .string "请选择要参加挑战的\n3只宝可梦……$" diff --git a/data/maps/BattleFrontier_BattlePyramidLobby/scripts.inc b/data/maps/BattleFrontier_BattlePyramidLobby/scripts.inc index f46d26c587..e2fe530739 100644 --- a/data/maps/BattleFrontier_BattlePyramidLobby/scripts.inc +++ b/data/maps/BattleFrontier_BattlePyramidLobby/scripts.inc @@ -184,10 +184,14 @@ BattleFrontier_BattlePyramidLobby_EventScript_NotEnoughValidMons:: BattleFrontier_BattlePyramidLobby_EventScript_NotEnoughValidMonsLv50:: msgbox BattleFrontier_BattlePyramidLobby_Text_NotEnoughValidMonsLv50, MSGBOX_DEFAULT + call BattleFrontier_ShowCaughtBannedSpecies + msgbox BattleFrontier_BattlePyramidLobby_Text_NotEnoughValidMonsEnd, MSGBOX_DEFAULT goto BattleFrontier_BattlePyramidLobby_EventScript_EndCancelChallenge BattleFrontier_BattlePyramidLobby_EventScript_NotEnoughValidMonsLvOpen:: msgbox BattleFrontier_BattlePyramidLobby_Text_NotEnoughValidMonsLvOpen, MSGBOX_DEFAULT + call BattleFrontier_ShowCaughtBannedSpecies + msgbox BattleFrontier_BattlePyramidLobby_Text_NotEnoughValidMonsEnd, MSGBOX_DEFAULT goto BattleFrontier_BattlePyramidLobby_EventScript_EndCancelChallenge BattleFrontier_BattlePyramidLobby_EventScript_CancelChallengeSaveFailed:: @@ -544,10 +548,13 @@ BattleFrontier_BattlePyramidLobby_Text_SelectThreeMons: .string "好的,请选择要参加挑战的\n3只宝可梦。$" BattleFrontier_BattlePyramidLobby_Text_NotEnoughValidMonsLvOpen: - .string "探险家啊,有点小问题!\p您能够参加对战的\n宝可梦不满3只。\p您需要准备3只\n不同种类的宝可梦,\p并且记得要取下它们携带的道具\n才可参加对战。\p此外,蛋{STR_VAR_1}无法参加对战!\p准备就绪后,\n请告诉我一声。$" + .string "探险家啊,有点小问题!\p您能够参加对战的\n宝可梦不满3只。\p您需要准备3只\n不同种类的宝可梦,\p并且记得要取下它们携带的道具\n才可参加对战。\p此外,蛋{STR_VAR_1}!$" BattleFrontier_BattlePyramidLobby_Text_NotEnoughValidMonsLv50: - .string "探险家啊,有点小问题!\p您能够参加对战的\n宝可梦不满3只。\p您需要准备3只等级50以内的\n不同种类的宝可梦,\p并且记得要取下它们携带的道具\n才可参加对战。\p此外,蛋{STR_VAR_1}无法参加对战!\p准备就绪后,\n请告诉我一声。$" + .string "探险家啊,有点小问题!\p您能够参加对战的\n宝可梦不满3只。\p您需要准备3只等级50以内的\n不同种类的宝可梦,\p并且记得要取下它们携带的道具\n才可参加对战。\p此外,蛋{STR_VAR_1}!$" + +BattleFrontier_BattlePyramidLobby_Text_NotEnoughValidMonsEnd: + .string "准备就绪后,\n请告诉我一声。$" BattleFrontier_BattlePyramidLobby_Text_OkayToSaveBeforeChallenge: .string "进入对战金字塔之前\n要先写入记录,可以吗?$" diff --git a/data/maps/BattleFrontier_BattleTowerLobby/scripts.inc b/data/maps/BattleFrontier_BattleTowerLobby/scripts.inc index 11ee4a3396..7d38b38a7f 100644 --- a/data/maps/BattleFrontier_BattleTowerLobby/scripts.inc +++ b/data/maps/BattleFrontier_BattleTowerLobby/scripts.inc @@ -543,16 +543,22 @@ BattleFrontier_BattleTowerLobby_EventScript_NotEnoughValidMonsLv50:: case FRONTIER_MODE_SINGLES, BattleFrontier_BattleTowerLobby_EventScript_NotEnoughValidMonsLv50Singles case FRONTIER_MODE_DOUBLES, BattleFrontier_BattleTowerLobby_EventScript_NotEnoughValidMonsLv50Doubles msgbox BattleFrontier_BattleTowerLobby_Text_NotEnoughValidMonsLv50Multis, MSGBOX_DEFAULT + call BattleFrontier_ShowCaughtBannedSpecies + msgbox BattleFrontier_BattleTowerLobby_Text_NotEnoughValidMonsEnd, MSGBOX_DEFAULT goto BattleFrontier_BattleTowerLobby_EventScript_EndCancelChallenge end BattleFrontier_BattleTowerLobby_EventScript_NotEnoughValidMonsLv50Singles:: msgbox BattleFrontier_BattleTowerLobby_Text_NotEnoughValidMonsLv50Singles, MSGBOX_DEFAULT + call BattleFrontier_ShowCaughtBannedSpecies + msgbox BattleFrontier_BattleTowerLobby_Text_NotEnoughValidMonsEnd, MSGBOX_DEFAULT goto BattleFrontier_BattleTowerLobby_EventScript_EndCancelChallenge end BattleFrontier_BattleTowerLobby_EventScript_NotEnoughValidMonsLv50Doubles:: msgbox BattleFrontier_BattleTowerLobby_Text_NotEnoughValidMonsLv50Doubles, MSGBOX_DEFAULT + call BattleFrontier_ShowCaughtBannedSpecies + msgbox BattleFrontier_BattleTowerLobby_Text_NotEnoughValidMonsEnd, MSGBOX_DEFAULT goto BattleFrontier_BattleTowerLobby_EventScript_EndCancelChallenge end @@ -561,16 +567,22 @@ BattleFrontier_BattleTowerLobby_EventScript_NotEnoughValidMonsLvOpen:: case FRONTIER_MODE_SINGLES, BattleFrontier_BattleTowerLobby_EventScript_NotEnoughValidMonsLvOpenSingles case FRONTIER_MODE_DOUBLES, BattleFrontier_BattleTowerLobby_EventScript_NotEnoughValidMonsLvOpenDoubles msgbox BattleFrontier_BattleTowerLobby_Text_NotEnoughValidMonsLvOpenMultis, MSGBOX_DEFAULT + call BattleFrontier_ShowCaughtBannedSpecies + msgbox BattleFrontier_BattleTowerLobby_Text_NotEnoughValidMonsEnd, MSGBOX_DEFAULT goto BattleFrontier_BattleTowerLobby_EventScript_EndCancelChallenge end BattleFrontier_BattleTowerLobby_EventScript_NotEnoughValidMonsLvOpenSingles:: msgbox BattleFrontier_BattleTowerLobby_Text_NotEnoughValidMonsLvOpenSingles, MSGBOX_DEFAULT + call BattleFrontier_ShowCaughtBannedSpecies + msgbox BattleFrontier_BattleTowerLobby_Text_NotEnoughValidMonsEnd, MSGBOX_DEFAULT goto BattleFrontier_BattleTowerLobby_EventScript_EndCancelChallenge end BattleFrontier_BattleTowerLobby_EventScript_NotEnoughValidMonsLvOpenDoubles:: msgbox BattleFrontier_BattleTowerLobby_Text_NotEnoughValidMonsLvOpenDoubles, MSGBOX_DEFAULT + call BattleFrontier_ShowCaughtBannedSpecies + msgbox BattleFrontier_BattleTowerLobby_Text_NotEnoughValidMonsEnd, MSGBOX_DEFAULT goto BattleFrontier_BattleTowerLobby_EventScript_EndCancelChallenge end @@ -1019,29 +1031,32 @@ BattleFrontier_BattleTowerLobby_Text_RecordLastMatch: @ Unused BattleFrontier_BattleTowerLobby_Text_NotEnoughValidMonsLv50: - .string "这位客人!\p您符合条件的宝可梦不足{STR_VAR_2}只。\p需要有{STR_VAR_2}只不同的等级50以内的\n宝可梦才可以参加比赛,\p同时这些宝可梦携带的道具\n也需要各不相同。\p蛋{STR_VAR_1}不能参加。\p准备好之后再来吧。$" + .string "这位客人!\p您符合条件的宝可梦不足{STR_VAR_2}只。\p需要有{STR_VAR_2}只不同的等级50以内的\n宝可梦才可以参加比赛,\p同时这些宝可梦携带的道具\n也需要各不相同。\p蛋{STR_VAR_1}。$" + +BattleFrontier_BattleTowerLobby_Text_NotEnoughValidMonsEnd: + .string "准备好之后再来吧。$" @ Unused BattleFrontier_BattleTowerLobby_Text_NotEnoughValidMonsLvOpen: - .string "这位客人!\p您符合条件的宝可梦不足{STR_VAR_2}只。\p需要有{STR_VAR_2}只不同的宝可梦\n才可以参加比赛,\p同时这些宝可梦携带的道具\n也需要各不相同。\p蛋{STR_VAR_1}不能参加。\p准备好之后再来吧。$" + .string "这位客人!\p您符合条件的宝可梦不足{STR_VAR_2}只。\p需要有{STR_VAR_2}只不同的宝可梦\n才可以参加比赛,\p同时这些宝可梦携带的道具\n也需要各不相同。\p蛋{STR_VAR_1}。$" BattleFrontier_BattleTowerLobby_Text_NotEnoughValidMonsLv50Singles: - .string "这位客人!\p您能够参加对战的\n宝可梦不满3只。\p您需要准备3只等级50以内的\n不同种类的宝可梦,\p且让它们分别携带不同道具\n才可参加对战。\p此外,蛋{STR_VAR_1}无法参加对战!\p请在准备就绪之后,\n再来参加吧。$" + .string "这位客人!\p您能够参加对战的\n宝可梦不满3只。\p您需要准备3只等级50以内的\n不同种类的宝可梦,\p且让它们分别携带不同道具\n才可参加对战。\p此外,蛋{STR_VAR_1}。$" BattleFrontier_BattleTowerLobby_Text_NotEnoughValidMonsLvOpenSingles: - .string "这位客人!\p您能够参加对战的\n宝可梦不满3只。\p您需要准备3只\n不同种类的宝可梦,\p且让它们分别携带不同道具\n才可参加对战。\p此外,蛋{STR_VAR_1}无法参加对战!\p请在准备就绪之后,\n再来参加吧。$" + .string "这位客人!\p您能够参加对战的\n宝可梦不满3只。\p您需要准备3只\n不同种类的宝可梦,\p且让它们分别携带不同道具\n才可参加对战。\p此外,蛋{STR_VAR_1}。$" BattleFrontier_BattleTowerLobby_Text_NotEnoughValidMonsLv50Doubles: - .string "这位客人!\p您能够参加对战的\n宝可梦不满4只。\p您需要准备4只等级50以内的\n不同种类的宝可梦,\p且让它们分别携带不同道具\n才可参加对战。\p此外,蛋{STR_VAR_1}无法参加对战!\p请在准备就绪之后,\n再来参加吧。$" + .string "这位客人!\p您能够参加对战的\n宝可梦不满4只。\p您需要准备4只等级50以内的\n不同种类的宝可梦,\p且让它们分别携带不同道具\n才可参加对战。\p此外,蛋{STR_VAR_1}。$" BattleFrontier_BattleTowerLobby_Text_NotEnoughValidMonsLvOpenDoubles: - .string "这位客人!\p您能够参加对战的\n宝可梦不满4只。\p您需要准备4只\n不同种类的宝可梦,\p且让它们分别携带不同道具\n才可参加对战。\p此外,蛋{STR_VAR_1}无法参加对战!\p请在准备就绪之后,\n再来参加吧。$" + .string "这位客人!\p您能够参加对战的\n宝可梦不满4只。\p您需要准备4只\n不同种类的宝可梦,\p且让它们分别携带不同道具\n才可参加对战。\p此外,蛋{STR_VAR_1}。$" BattleFrontier_BattleTowerLobby_Text_NotEnoughValidMonsLv50Multis: - .string "这位客人!\p您能够参加对战的\n宝可梦不满2只。\p您需要准备2只等级50以内的\n不同种类的宝可梦,\p且让它们分别携带不同道具\n才可参加对战。\p此外,蛋{STR_VAR_1}无法参加对战!\p请在准备就绪之后,\n再来参加吧。$" + .string "这位客人!\p您能够参加对战的\n宝可梦不满2只。\p您需要准备2只等级50以内的\n不同种类的宝可梦,\p且让它们分别携带不同道具\n才可参加对战。\p此外,蛋{STR_VAR_1}。$" BattleFrontier_BattleTowerLobby_Text_NotEnoughValidMonsLvOpenMultis: - .string "这位客人!\p您能够参加对战的\n宝可梦不满2只。\p您需要准备2只\n不同种类的宝可梦,\p且让它们分别携带不同道具\n才可参加对战。\p此外,蛋{STR_VAR_1}无法参加对战!\p请在准备就绪之后,\n再来参加吧。$" + .string "这位客人!\p您能够参加对战的\n宝可梦不满2只。\p您需要准备2只\n不同种类的宝可梦,\p且让它们分别携带不同道具\n才可参加对战。\p此外,蛋{STR_VAR_1}。$" BattleFrontier_BattleTowerLobby_Text_WelcomSingleBattle: .string "训练家的才能\n将在此接受考验!\p欢迎来到对战塔!\p我是您的单打对战间向导。$" diff --git a/data/maps/FallarborTown_MoveRelearnersHouse/scripts.inc b/data/maps/FallarborTown_MoveRelearnersHouse/scripts.inc index 33390c6cf2..7e84402a26 100644 --- a/data/maps/FallarborTown_MoveRelearnersHouse/scripts.inc +++ b/data/maps/FallarborTown_MoveRelearnersHouse/scripts.inc @@ -22,6 +22,7 @@ FallarborTown_MoveRelearnersHouse_EventScript_AskTeachMove:: FallarborTown_MoveRelearnersHouse_EventScript_ChooseMon:: msgbox FallarborTown_MoveRelearnersHouse_Text_TutorWhichMon, MSGBOX_DEFAULT + setmoverelearnerstate MOVE_RELEARNER_LEVEL_UP_MOVES @ Specifically supposed to teach level up moves special ChooseMonForMoveRelearner waitstate goto_if_eq VAR_0x8004, PARTY_NOTHING_CHOSEN, FallarborTown_MoveRelearnersHouse_EventScript_ComeBackWithHeartScale diff --git a/data/maps/map_groups.json b/data/maps/map_groups.json index 8a90679c8d..78e82055f6 100644 --- a/data/maps/map_groups.json +++ b/data/maps/map_groups.json @@ -620,72 +620,5 @@ ], "gMapGroup_IndoorRoute124": [ "Route124_DivingTreasureHuntersHouse" - ], - "connections_include_order": [ - "LittlerootTown", - "OldaleTown", - "DewfordTown", - "LavaridgeTown", - "FallarborTown", - "VerdanturfTown", - "PacifidlogTown", - "PetalburgCity", - "SlateportCity", - "MauvilleCity", - "RustboroCity", - "FortreeCity", - "LilycoveCity", - "MossdeepCity", - "SootopolisCity", - "EverGrandeCity", - "Route101", - "Route102", - "Route103", - "Route104", - "Route105", - "Route106", - "Route107", - "Route108", - "Route109", - "Route110", - "Route111", - "Route112", - "Route113", - "Route114", - "Route115", - "Route116", - "Route117", - "Route118", - "Route119", - "Route120", - "Route121", - "Route122", - "Route123", - "Route124", - "Route125", - "Route126", - "Route127", - "Route128", - "Route129", - "Route130", - "Route131", - "Route132", - "Route133", - "Route134", - "Underwater_Route105", - "Underwater_Route124", - "Underwater_Route125", - "Underwater_Route126", - "Underwater_Route127", - "Underwater_Route128", - "Underwater_Route129", - "SafariZone_Northwest", - "SafariZone_North", - "SafariZone_Southwest", - "SafariZone_South", - "SafariZone_Northeast", - "SafariZone_Southeast", - "BattleFrontier_OutsideWest", - "BattleFrontier_OutsideEast" ] } diff --git a/data/scripts/apricorn_tree.inc b/data/scripts/apricorn_tree.inc new file mode 100644 index 0000000000..019b2b76b0 --- /dev/null +++ b/data/scripts/apricorn_tree.inc @@ -0,0 +1,89 @@ +ApricornTreeScript:: + lock + faceplayer + message ApricornTree_Text_Intro + waitmessage + special ObjectEventInteractionGetApricornTreeData + goto_if_gt VAR_0x8005, 0, ApricornTree_EventScript_WantToPick + message ApricornTree_Text_Empty + waitmessage + waitbuttonpress + release + end + +ApricornTree_EventScript_WantToPick:: + buffernumberstring STR_VAR_2, VAR_0x8005 + msgbox ApricornTree_Text_WantToPick, MSGBOX_YESNO + goto_if_eq VAR_RESULT, YES, ApricornTree_EventScript_PickApricorn + goto_if_eq VAR_RESULT, NO, ApricornTree_EventScript_CancelPickingApricorn + +.set APRICORN_NORMAL_BAG_FULL, 0 +.set APRICORN_NORMAL_SPACE_IN_BAG, 1 + +ApricornTree_EventScript_PickApricorn:: + special ObjectEventInteractionPickApricornTree + call EventScript_BufferPocketNameAndTryFanfare + goto_if_eq VAR_0x8006, APRICORN_NORMAL_BAG_FULL, ApricornTree_EventScript_PocketFull + message ApricornTree_Text_PickedTheApricorn +.if OW_SHOW_ITEM_DESCRIPTIONS != OW_ITEM_DESCRIPTIONS_OFF + copyvar VAR_0x8006 VAR_0x8004 +.endif + delay 10 +.if OW_SHOW_ITEM_DESCRIPTIONS != OW_ITEM_DESCRIPTIONS_OFF + showberrydescription +.endif + playfanfare MUS_OBTAIN_BERRY + waitmessage + waitfanfare + waitbuttonpress + message ApricornTree_Text_PutAwayApricorn + waitmessage + waitbuttonpress +.if OW_SHOW_ITEM_DESCRIPTIONS != OW_ITEM_DESCRIPTIONS_OFF + hideitemdescription +.endif + release + end + +ApricornTree_EventScript_PocketFull:: + message ApricornTree_Text_PocketFull + waitmessage + waitbuttonpress + release + end + +ApricornTree_EventScript_CancelPickingApricorn:: + message ApricornTree_Text_ApricornLeftUnpicked + waitmessage + waitbuttonpress + release + end + +ApricornTree_Text_Intro: + .string "It's an Apricorn Tree!$" + +ApricornTree_Text_Empty: + .string "There are no Apricorns…$" + +ApricornTree_Text_WantToPick: + .string "…It's {STR_VAR_2} {STR_VAR_1}!\p" + .string "Do you want to pick the\n" + .string "{STR_VAR_1}?$" + +ApricornTree_Text_PickedTheApricorn: + .string "{PLAYER} obtained\n" + .string "{STR_VAR_2} {STR_VAR_1}.$" + +ApricornTree_Text_PutAwayApricorn: + .string "{PLAYER} put away the\n" + .string "{STR_VAR_1} in\l" + .string "the BAG's {STR_VAR_3} POCKET.$" + +ApricornTree_Text_PocketFull: + .string "The BAG's {STR_VAR_3} POCKET is full.\p" + .string "{PLAYER} gave up on the\p" + .string "{STR_VAR_1}…$" + +ApricornTree_Text_ApricornLeftUnpicked: + .string "{PLAYER} gave up on the\p" + .string "{STR_VAR_1}…$" diff --git a/data/scripts/battle_frontier.inc b/data/scripts/battle_frontier.inc new file mode 100644 index 0000000000..5ad7c30d8e --- /dev/null +++ b/data/scripts/battle_frontier.inc @@ -0,0 +1,13 @@ +BattleFrontier_ShowCaughtBannedSpecies:: + goto_if_eq VAR_0x8005, 0, BattleFrontier_ShowCaughtBannedSpeciesEnd + msgbox BattleFrontier_DoYouWantToSeeTheListOfCaughtBannedSpecies, MSGBOX_YESNO + goto_if_eq VAR_RESULT, NO, BattleFrontier_ShowCaughtBannedSpeciesEnd + callnative ShowBattleFrontierCaughtBannedSpecies + waitstate +BattleFrontier_ShowCaughtBannedSpeciesEnd: + return + + +BattleFrontier_DoYouWantToSeeTheListOfCaughtBannedSpecies: + .string "要查看无法参加的\n" + .string "宝可梦名单吗?$" diff --git a/data/scripts/debug.inc b/data/scripts/debug.inc index 83310d63fe..28e7df5990 100644 --- a/data/scripts/debug.inc +++ b/data/scripts/debug.inc @@ -87,6 +87,15 @@ Debug_FlagsNotSetBattleConfigMessage_Text: .string "请在这里定义一个可用标志:\l" .string "'include/config/battle.h'!$" +Debug_VarsNotSetBattleConfigMessage:: + message Debug_VarsNotSetBattleConfigMessage_Text + goto Debug_MessageEnd + +Debug_VarsNotSetBattleConfigMessage_Text: + .string "Feature unavailable!\n" + .string "Please define a usable var in:\l" + .string "'include/config/battle.h'!$" + Debug_BoxFilledMessage:: message Debug_BoxFilledMessage_Text goto Debug_MessageEnd @@ -387,7 +396,29 @@ Debug_EventScript_SetHiddenNature:: dynmultistack 0, 0, TRUE, 7, FALSE, 0, NULL switch VAR_RESULT case MULTI_B_PRESSED, Debug_EventScript_InflictStatus1_Close - special SetHiddenNature + special SetHiddenNature + releaseall + end + +Debug_EventScript_SetAbility:: + special ChoosePartyMon + waitstate + callnative DebugNative_GetAbilityNames + dynmultipush gStringVar1, 0 + dynmultipush gStringVar2, 1 + dynmultipush gStringVar3, 2 + dynmultistack 0, 0, FALSE, 3 FALSE, 0, NULL + switch VAR_RESULT + case MULTI_B_PRESSED, Debug_EventScript_SetAbilityClose + special SetAbility +Debug_EventScript_SetAbilityClose: + releaseall + end + +Debug_EventScript_SetFriendship:: + special ChoosePartyMon + waitstate + callnative DebugNative_Party_SetFriendship releaseall end diff --git a/data/scripts/move_relearner.inc b/data/scripts/move_relearner.inc new file mode 100644 index 0000000000..15c80733df --- /dev/null +++ b/data/scripts/move_relearner.inc @@ -0,0 +1,105 @@ +Common_EventScript_MoveRelearner:: + lockall + faceplayer + message MoveRelearner_Text_WouldLearnNewMoves + waitmessage + goto Common_EventScript_MoveRelearnerDynMultiChoice + end + +Common_EventScript_MoveRelearnerDynMultiChoice:: + dynmultipush MoveRelearner_Text_LevelUpMoves, 0 +.if P_ENABLE_MOVE_RELEARNERS == TRUE + dynmultipush MoveRelearner_Text_EggMoves, 1 + dynmultipush MoveRelearner_Text_TMMoves, 2 + dynmultipush MoveRelearner_Text_TutormoveMoves, 3 +.else + call_if_set P_FLAG_EGG_MOVES, MoveRelearner_EventScript_PushEggMoves + istmrelearneractive MoveRelearner_EventScript_PushTMMoves + call_if_set P_FLAG_TUTOR_MOVES, MoveRelearner_EventScript_PushTutorMoves +.endif @ P_ENABLE_MOVE_RELEARNERS + dynmultipush MoveRelearner_Text_SeeYa, 4 + dynmultistack 0, 0, FALSE, 5, 0, 0, DYN_MULTICHOICE_CB_NONE + closemessage + switch VAR_RESULT + case 0, MoveRelearner_EventScript_TeachLevelUpMoves + case 1, MoveRelearner_EventScript_TeachEggMoves + case 2, MoveRelearner_EventScript_TeachTMMoves + case 3, MoveRelearner_EventScript_TeachTutorMoves + case 4, MoveRelearner_EventScript_PleaseComeAgain +MoveRelearner_EventScript_PleaseComeAgain: + msgbox MoveRelearner_Text_ThankYouComeAgain, MSGBOX_DEFAULT + releaseall + end + +MoveRelearner_EventScript_PushEggMoves: + dynmultipush MoveRelearner_Text_EggMoves, 1 + return + +MoveRelearner_EventScript_PushTMMoves: + dynmultipush MoveRelearner_Text_TMMoves, 2 + return + +MoveRelearner_EventScript_PushTutorMoves: + dynmultipush MoveRelearner_Text_TutormoveMoves, 3 + return + +MoveRelearner_EventScript_TeachLevelUpMoves: + setmoverelearnerstate MOVE_RELEARNER_LEVEL_UP_MOVES + bufferstring STR_VAR_3, MoveRelearner_Text_LevelUpMoveLWR + goto MoveRelearner_EventScript_TeachMove + end + +MoveRelearner_EventScript_TeachEggMoves: + setmoverelearnerstate MOVE_RELEARNER_EGG_MOVES + bufferstring STR_VAR_3, MoveRelearner_Text_EggMoveLWR + goto MoveRelearner_EventScript_TeachMove + end + +MoveRelearner_EventScript_TeachTMMoves: + setmoverelearnerstate MOVE_RELEARNER_TM_MOVES + bufferstring STR_VAR_3, MoveRelearner_Text_TMMoveLWR + goto MoveRelearner_EventScript_TeachMove + end + +MoveRelearner_EventScript_TeachTutorMoves: + setmoverelearnerstate MOVE_RELEARNER_TUTOR_MOVES + bufferstring STR_VAR_3, MoveRelearner_Text_TutorMoveLWR + goto MoveRelearner_EventScript_TeachMove + end + +MoveRelearner_EventScript_TeachMove:: + getpartysize + goto_if_eq VAR_RESULT, 0, MoveRelearner_EventScript_NoPkmn + msgbox MoveRelearner_Text_ChoosePkmn, MSGBOX_DEFAULT + special ChooseMonForMoveRelearner + waitstate + call_if_eq VAR_0x8004, PARTY_NOTHING_CHOSEN, MoveRelearner_EventScript_AnythingElse + special IsSelectedMonEgg + call_if_eq VAR_RESULT, YES, MoveRelearner_EventScript_CantTeachMoveToEgg + call_if_eq VAR_0x8005, NO, MoveRelearner_EventScript_CantTeachMoveToPkmn + msgbox MoveRelearner_Text_WhichXmoveShouldTeach, MSGBOX_DEFAULT + special TeachMoveRelearnerMove + waitstate + goto MoveRelearner_EventScript_AnythingElse + end + +MoveRelearner_EventScript_NoPkmn: + msgbox MoveRelearner_Text_HaveNoPkmn, MSGBOX_AUTOCLOSE + releaseall + end + +MoveRelearner_EventScript_CantTeachMoveToEgg: + msgbox MoveRelearner_Text_CantTeachMoveToEgg, MSGBOX_AUTOCLOSE + goto MoveRelearner_EventScript_AnythingElse + end + +MoveRelearner_EventScript_CantTeachMoveToPkmn: + msgbox MoveRelearner_Text_CantTeachMoveToPkmn, MSGBOX_AUTOCLOSE + goto MoveRelearner_EventScript_AnythingElse + end + +MoveRelearner_EventScript_AnythingElse:: + message MoveRelearner_Text_AnythingElse + waitmessage + goto Common_EventScript_MoveRelearnerDynMultiChoice + end diff --git a/data/scripts/obtain_item.inc b/data/scripts/obtain_item.inc index 599961c821..3eb7f4f0d4 100644 --- a/data/scripts/obtain_item.inc +++ b/data/scripts/obtain_item.inc @@ -205,6 +205,7 @@ EventScript_FoundHiddenItem:: end EventScript_PutHiddenItemInPocket:: + callnative Script_ClearDowsingColor delay 10 showitemdescription waitmessage @@ -215,6 +216,7 @@ EventScript_PutHiddenItemInPocket:: hideitemdescription special TryPutTreasureInvestigatorsOnAir special SetHiddenItemFlag + callnative Script_UpdateDowseState releaseall end diff --git a/data/sound_data.s b/data/sound_data.s index d1951ecc7c..b52f9d2f86 100644 --- a/data/sound_data.s +++ b/data/sound_data.s @@ -1,5 +1,8 @@ .section .rodata + .include "asm/macros.inc" + .include "constants/constants.inc" + .include "asm/macros/m4a.inc" .include "asm/macros/music_voice.inc" .include "include/config/general.h" diff --git a/data/specials.inc b/data/specials.inc index 0a2ae2da50..f80933c011 100644 --- a/data/specials.inc +++ b/data/specials.inc @@ -564,3 +564,6 @@ gSpecials:: def_special EnterCode def_special GetCodeFeedback def_special SetHiddenNature + def_special SetAbility + def_special ObjectEventInteractionGetApricornTreeData + def_special ObjectEventInteractionPickApricornTree diff --git a/data/text/contest_link.inc b/data/text/contest_link.inc deleted file mode 100644 index bc28098d7a..0000000000 --- a/data/text/contest_link.inc +++ /dev/null @@ -1,34 +0,0 @@ -@ With the exception of Link standby, none of the below texts are used - -gTest_MissedTurn:: - .string "错过回合$" - -gText_LinkStandby4:: - .string "正在等待连接!$" - -gText_WinnerIsPlayersMonCongrats:: - .string "冠军是{STR_VAR_1}的{STR_VAR_2}!\n恭喜!$" - -gText_WinnerIsPlayersMon:: - .string "冠军是{STR_VAR_1}的{STR_VAR_2}!{0xFC 9}$" - -gText_PrimaryJudgingNumX:: - .string "第1轮评审:No.{STR_VAR_1}{0xFC 9}$" - -gText_SecondaryJudgingNumX:: - .string "第2轮评审:No.{STR_VAR_1}{0xFC 9}$" - -gText_SetEventNumX:: - .string "自定赛:No.{STR_VAR_1}{0xFC 9}$" - -gText_MoveUsedMostOften:: - .string "最常用的招式:\n{STR_VAR_1}{0xFC 9}$" - -gText_MostImpressiveMon:: - .string "最出色的宝可梦:\n{STR_VAR_1}的{STR_VAR_2}{0xFC 9}$" - -gText_SetEventNumX2:: - .string "自定赛:No.{STR_VAR_1}{0xFC 9}$" - -gText_LinkTVProgramWillNotBeMadeTrainerLost:: - .string "无法制作连接电视节目,\n因为训练家已断开连接。{0xFC 9}$" diff --git a/data/text/contest_painting.inc b/data/text/contest_painting.inc deleted file mode 100644 index 1dcd702a8e..0000000000 --- a/data/text/contest_painting.inc +++ /dev/null @@ -1,81 +0,0 @@ -gContestHallPaintingCaption:: - .string "{STR_VAR_1}\n{STR_VAR_2}的{STR_VAR_3}$" - -@ Unused -gContestPaintingContest:: - .string "比赛$" - -gContestRankNormal:: - .string "普通级$" - -gContestRankSuper:: - .string "超级级$" - -gContestRankHyper:: - .string "专家级$" - -gContestRankMaster:: - .string "大师级$" - -gContestLink:: - .string "连接$" - -gContestCoolness:: - .string "帅气$" - -gContestBeauty:: - .string "美丽$" - -gContestCuteness:: - .string "可爱$" - -gContestSmartness:: - .string "聪明$" - -gContestToughness:: - .string "强壮$" - -gContestPaintingCool1:: - .string "挡不住的帅气——\n无可估量的{STR_VAR_1}$" - -gContestPaintingCool2:: - .string "嗨那边的!\n好漂亮的宝可梦啊{STR_VAR_1}$" - -gContestPaintingCool3:: - .string "这真是让人惊奇的\n{STR_VAR_1}居然那么神奇$" - -gContestPaintingBeauty1:: - .string "{STR_VAR_1}是本世纪\n最后的维纳斯。$" - -gContestPaintingBeauty2:: - .string "{STR_VAR_1}耀眼\n而闪亮的微笑$" - -gContestPaintingBeauty3:: - .string "宝可梦中心的超级偶像——\n无与伦比的{STR_VAR_1}$" - -gContestPaintingCute1:: - .string "可爱的{STR_VAR_1}$" - -gContestPaintingCute2:: - .string "美丽的{STR_VAR_1}的\n胜利肖像$" - -gContestPaintingCute3:: - .string "让我们看看\n那个漂亮的宝可梦{STR_VAR_1}!$" - -gContestPaintingSmart1:: - .string "智慧的艺术大师——\n聪明的宝可梦{STR_VAR_1}$" - -gContestPaintingSmart2:: - .string "{STR_VAR_1}——被选中的宝可梦\n宝可梦中的宝可梦$" - -gContestPaintingSmart3:: - .string "优秀的{STR_VAR_1}的\n高贵瞬间$" - -gContestPaintingTough1:: - .string "肌肉发达的\n{STR_VAR_1}$" - -gContestPaintingTough2:: - .string "强壮,无比强壮\n的{STR_VAR_1}$" - -gContestPaintingTough3:: - .string "极为强悍的\n易激动的宝可梦{STR_VAR_1}$" diff --git a/data/text/contest_strings.inc b/data/text/contest_strings.inc deleted file mode 100644 index 1c8bd7507b..0000000000 --- a/data/text/contest_strings.inc +++ /dev/null @@ -1,464 +0,0 @@ -gText_AppealNumWhichMoveWillBePlayed:: - .string "第{STR_VAR_1}回合的表演!\n" - .string "要使用哪个招式呢?$" -@{STR_VAR_1}かいめのアピール! -@どのわざをつかう? - -gText_AppealNumButItCantParticipate:: - .string "第{STR_VAR_1}回合的表演!\n" - .string "但是无法参加!$" -@{STR_VAR_1}かいめのアピール! -@しかしさんかできない! - -gText_MonAppealedWithMove:: - .string "{STR_VAR_1}使用了\n" - .string "{STR_VAR_2}进行表演!$" -@{STR_VAR_1}は -@{STR_VAR_2}でアピール! - -gText_MonWasWatchingOthers:: - .string "{STR_VAR_1}在观察\n" - .string "其他的宝可梦!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}$" -@{STR_VAR_1}は -@みんなを みていた! - -gText_AllOutOfAppealTime:: - .string "表演时间结束!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}$" -@アピールタイム しゅうりょう! - -@ Appeal result texts -gText_BecameMoreConsciousOfOtherMons:: - .string "它变得比平时\n" - .string "更加担心其他宝可梦了!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}$" -@ほかの ポケモンが いつもより -@きに なって きた! - -gText_MonCantMakeAnAppealAfterThis:: - .string "{STR_VAR_1}此后\n" - .string "都无法再次进行表演了!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}$" -@{STR_VAR_1}は このあと -@アピール できなく なった! - -gText_SettledDownJustLittleBit:: - .string "它稍微有些\n" - .string "冷静下来了!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}$" -@ちょっと だけ -@きもちが おちついた! - -gText_BecameObliviousToOtherMons:: - .string "它变得完全\n" - .string "不关注其他宝可梦了!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}$" -@ほかの ポケモンが ぜんぜん -@きに ならなく なった! - -gText_BecameLessAwareOfOtherMons:: - .string "它变得不那么\n" - .string "关注其他宝可梦了。{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}$" -@ほかの ポケモンが あまり -@きに ならなく なった! - -gText_StoppedCaringAboutOtherMons:: - .string "它不再那么\n" - .string "留意其他宝可梦了!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}$" -@ほかの ポケモンを あまり -@きに しないように なった! - -gText_TriedToStartleOtherMons:: - .string "它试图惊吓\n" - .string "其他宝可梦!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}$" -@ほかの ポケモンを -@びっくり させようと した! - -gText_TriedToDazzleOthers:: - .string "它试图让\n" - .string "其他宝可梦眼花缭乱!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}$" -@みんなの めを -@くらませようと した! - -gText_JudgeLookedAwayFromMon:: - .string "评委的目光\n" - .string "从{STR_VAR_1}身上移开了!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}$" -@しんさいんは {STR_VAR_1}から -@めを そらして しまった! - -gText_TriedToUnnerveNextMon:: - .string "它试图让下一只\n" - .string "表演的宝可梦紧张!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}$" -@つぎに まっている ポケモンを -@きんちょう させようと した! - -gText_MonBecameNervous:: - .string "{STR_VAR_1}\n" - .string "紧张了起来!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}$" -@{STR_VAR_1}は -@きんちょう してしまった! - -gText_AppealTriedToUnnerveWaitingMons:: - .string "它试图让所有\n" - .string "之后表演的宝可梦紧张!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}$" -@アピールが まだの ポケモンを -@きんちょう させようと した! - -gText_TauntedMonsDoingWell:: - .string "它嘲笑了\n" - .string "气势良好的宝可梦!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}$" -@ちょうしが いい ポケモンを -@からかってみた! - -gText_MonRegainedItsForm:: - .string "{STR_VAR_1}的气势\n" - .string "回到了本来的样子!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}$" -@{STR_VAR_1}の ちょうしが -@もとに もどって しまった! - -gText_TriedToJamMonDoingWell:: - .string "它试图干扰那些\n" - .string "表演引人注目的宝可梦!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}$" -@ちょうしが いい ポケモンの -@じゃまを しようと した! - -gText_StandoutMonHustledEvenMore:: - .string "本来就引人注目的\n" - .string "{STR_VAR_1}更加鼓足干劲了!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}$" -@めだっている {STR_VAR_1}は -@さらに はりきった! - -gText_LargelyUnnoticedMonWorkedHard:: - .string "原本不太引人注目的\n" - .string "{STR_VAR_1}加油努力了起来!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}$" -@めだっていない {STR_VAR_1}は -@がんばりまくった! - -gText_WorkedAsMuchAsMonBefore:: - .string "它鼓足了不会输给\n" - .string "前面所有宝可梦程度的干劲!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}$" -@まえの ポケモンたちに -@まけないくらい はりきった! - -gText_MonsAppealDidNotGoWell:: - .string "{STR_VAR_1}的表演\n" - .string "没能成功奏效!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}$" -@{STR_VAR_1}は アピールを -@うまく みせられなかった! - -gText_WorkedAsMuchAsPrecedingMon:: - .string "和前面的宝可梦\n" - .string "一样地鼓足了干劲!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}$" -@まえの ポケモンと -@おなじくらい はりきった! - -gText_MonsAppealDidNotGoWell2:: - .string "{STR_VAR_1}的表演\n" - .string "没能成功奏效!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}$" -@{STR_VAR_1}は アピールを -@うまく みせられなかった! - -gText_MonsAppealDidNotGoWell3:: - .string "{STR_VAR_1}的表演\n" - .string "没能成功奏效!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}$" -@{STR_VAR_1}は アピールを -@うまく みせられなかった! - -gText_MonsAppealWentSlightlyWell:: - .string "{STR_VAR_1}的表演\n" - .string "做得还算可以!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}$" -@{STR_VAR_1}の アピールは -@すこし うまく いった! - -gText_MonsAppealWentPrettyWell:: - .string "{STR_VAR_1}的表演\n" - .string "做得不错!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}$" -@{STR_VAR_1}の アピールは -@まあまあ うまく いった! - -gText_MonsAppealWentExcellently:: - .string "{STR_VAR_1}的表演\n" - .string "做得非常出色!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}$" -@{STR_VAR_1}の アピールは -@とても うまく いった! - -gText_MonsAppealWasDud:: - .string "{STR_VAR_1}的表演\n" - .string "完全失败了!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}$" -@{STR_VAR_1}の アピールは -@しっぱい して しまった! - -gText_MonsAppealDidNotWorkVeryWell:: - .string "{STR_VAR_1}的表演\n" - .string "做得不怎么好!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}$" -@{STR_VAR_1}の アピールは -@あまり うまく いかなかった! - -gText_MonsAppealWentSlightlyWell2:: - .string "{STR_VAR_1}的表演\n" - .string "做得还算可以!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}$" -@{STR_VAR_1}の アピールは -@すこし うまく いった! - -gText_MonsAppealWentPrettyWell2:: - .string "{STR_VAR_1}的表演\n" - .string "做得不错!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}$" -@{STR_VAR_1}の アピールは -@まあまあ うまく いった! - -gText_MonsAppealWentVeryWell:: - .string "{STR_VAR_1}的表演\n" - .string "做得很好!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}$" -@{STR_VAR_1}の アピールは -@かなり うまく いった! - -gText_MonsAppealWentExcellently2:: - .string "{STR_VAR_1}的表演\n" - .string "做得非常出色!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}$" -@{STR_VAR_1}の アピールは -@とても うまく いった! - -gText_SameTypeAsOneBeforeGood:: - .string "因为和前面的宝可梦\n" - .string "类别一致而受到喜欢!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}$" -@まえの ポケモンと -@おなじタイプで きにいられた! - -gText_NotSameTypeAsOneBeforeGood:: - .string "因为和前面的宝可梦\n" - .string "类别不同而受到喜欢!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}$" -@まえの ポケモンと -@ちがうタイプで きにいられた! - -gText_StoodOutMuchMoreThanMonBefore:: - .string "比起前面的宝可梦\n" - .string "要出彩得多!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}$" -@まえの ポケモンより -@だいぶ めだった! - -gText_DidntDoAsWellAsMonBefore:: - .string "比起前面的宝可梦\n" - .string "完成得不算太好!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}$" -@まえの ポケモンより -@うまく できなかった! - -gText_MonsConditionRoseAboveUsual:: - .string "{STR_VAR_1}的气势\n" - .string "比平时有所提升!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}$" -@{STR_VAR_1}の ちょうしが -@いつもより あがった! - -gText_MonsHotStatusMadeGreatAppeal:: - .string "{STR_VAR_1}气势不错,\n" - .string "表演变得棒极了!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}$" -@{STR_VAR_1}は ちょうしが よくて -@ぜっこうの アピールに なった! - -gText_MovedUpInLineForNextAppeal:: - .string "它想要在下回合的表演里\n" - .string "更早出场而走到了前面!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}$" -@つぎの アピールを はやく -@しようと まえに でた! - -gText_MovedBackInLineForNextAppeal:: - .string "它想要在下回合的表演里\n" - .string "更晚出场而后退了一步!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}$" -@つぎの アピールを おそく -@しようと 1ぽ さがった! - -gText_ScrambledUpOrderForNextTurn:: - .string "下个回合的表演顺序\n" - .string "变得奇怪了起来!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}$" -@つぎの ターンの じゅんばん -@おかしく した! - -gText_JudgeLookedAtMonExpectantly:: - .string "评委满怀期待地\n" - .string "看着{STR_VAR_1}!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}$" -@しんさいんが きたいして -@{STR_VAR_1}を みつめた! - -gText_AppealComboWentOverWell:: - .string "前后演出的招式组合\n" - .string "得到了大家的喜爱!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}$" -@アピールの くみあわせが -@きに いって もらえた! - -gText_AppealComboWentOverVeryWell:: - .string "前后演出的招式组合\n" - .string "很受大家喜欢!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}$" -@アピールの くみあわせが -@かなり きに いられた! - -gText_AppealComboWentOverExcellently:: - .string "前后演出的招式组合\n" - .string "特别受大家喜欢!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}$" -@アピールの くみあわせが -@ものすごく きに いられた! - -gText_MonManagedToAvertGaze:: - .string "{STR_VAR_1}成功地\n" - .string "移开了视线!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}$" -@{STR_VAR_1}は なんとか -@めを そらした! - -gText_MonManagedToAvoidSeeingIt:: - .string "{STR_VAR_1}成功地\n" - .string "避开了视线!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}$" -@{STR_VAR_1}は -@そっちを みずに すんだ! - -gText_MonIsntFazedByThatSortOfThing:: - .string "{STR_VAR_1}没有受\n" - .string "这种程度的事情影响!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}$" -@{STR_VAR_1}は -@このくらいは へいきだった! - -gText_MonBecameALittleDistracted:: - .string "{STR_VAR_1}变得\n" - .string "稍稍有点分心了!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}$" -@{STR_VAR_1}は ちょっと -@きを とられて しまった! - -gText_TriedToStartleOtherPokemon:: - .string "它试图惊吓\n" - .string "其他宝可梦!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}$" -@ほかの ポケモンを -@びっくり させようと した! - -gText_MonLookedDownOutOfDistraction:: - .string "{STR_VAR_1}因为分心\n" - .string "低下了头!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}$" -@{STR_VAR_1}は きをとられて -@したを むいて しまった!(小) - -gText_MonTurnedBackOutOfDistraction:: - .string "{STR_VAR_1}因为分心\n" - .string "转过了身!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}$" -@{STR_VAR_1}は きを とられて -@ふりかえって しまった!(中) - -gText_MonCouldntHelpUtteringCry:: - .string "{STR_VAR_1}忍不住地\n" - .string "叫出了声!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}$" -@{STR_VAR_1}は おもわず -@こえを あげて しまった!(大) - -gText_MonCouldntHelpLeapingUp:: - .string "{STR_VAR_1}忍不住地\n" - .string "跳了起来!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}$" -@{STR_VAR_1}は おもわず -@とびあがって しまった!(特大) - -gText_MonTrippedOutOfDistraction:: - .string "{STR_VAR_1}因为分心\n" - .string "摔在了地上四脚朝天!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}$" -@{STR_VAR_1}は きを とられて -@ひっくり かえって しまった!(?) - -gText_MonWasTooNervousToMove:: - .string "{STR_VAR_1}因为紧张\n" - .string "无法使用招式表演了!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}$" -@{STR_VAR_1}は きんちょうして -@アピールが できなかった! - -gText_ButItMessedUp2:: - .string "但它搞砸了!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}$" -@でも しっぱい してしまった! - -gText_ButItFailedToMakeTargetNervous:: - .string "但是它没能让\n" - .string "目标宝可梦紧张!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}$" -@でも きんちょう -@させられなかった! - -gText_ButItFailedToMakeAnyoneNervous:: - .string "但是它没能让\n" - .string "任何宝可梦紧张!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}$" -@でも だれも -@きんちょう しなかった! - -gText_ButItWasIgnored:: - .string "但它被无视了……{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}$" -@でも むし されて しまった…… - -gText_CouldntImproveItsCondition:: - .string "但是它并没能\n" - .string "提升自己的气势……{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}$" -@でも ちょうしは -@あがらなかった…… - -gText_BadConditionResultedInWeakAppeal:: - .string "它因为气势不行\n" - .string "表演得一点也不好……{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}$" -@ちょうしが よく なくて -@あまり うまく できなかった…… - -gText_MonWasUnaffected:: - .string "{STR_VAR_1}\n" - .string "完全不为所动!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}$" -@{STR_VAR_1}は -@へいき だった! - -gText_RepeatedAppeal:: - .string "{STR_VAR_1}因为\n" - .string "重复表演,让大家失望了。{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}$" -@{STR_VAR_1}は おなじアピールを -@つづけて がっかり された! - -gText_MonsXWentOverGreat:: - .string "{STR_VAR_1}的{STR_VAR_3}表演\n" - .string "受到了大家的热烈欢迎!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}$" -@{STR_VAR_1}の {STR_VAR_3}が -@まわりに とても うけた! - -gText_MonsXDidntGoOverWell:: - .string "{STR_VAR_1}的{STR_VAR_3}表演\n" - .string "在这里不受欢迎……{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}$" -@{STR_VAR_1}の {STR_VAR_3}が -@ここでは うけなかった… - -gText_MonsXGotTheCrowdGoing:: - .string "{STR_VAR_1}的{STR_VAR_3}表演\n" - .string "让整个会场沸腾了!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}$" -@{STR_VAR_1}の {STR_VAR_3}に -@まわりが もりあがった! - -gText_MonCantAppealNextTurn:: - .string "{STR_VAR_1}无法参加\n" - .string "下一次的表演了!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}$" -@{STR_VAR_1}は つぎの アピールに -@さんか できなくなった! - -gText_AttractedCrowdsAttention:: - .string "吸引了\n" - .string "观众们的注意!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}$" -@かんきゃくの -@ちゅうもくを あつめた! - -gText_CrowdContinuesToWatchMon:: - .string "观众们一直\n" - .string "持续关注着{STR_VAR_3}!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}$" -@かんきゃくは -@{STR_VAR_3}を みつづけている! - -gText_MonsMoveIsIgnored:: - .string "{STR_VAR_1}的{STR_VAR_2}\n" - .string "被完全无视了……{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}$" -@{STR_VAR_1}の {STR_VAR_2}は -@めを むけられなかった…… - -gText_Contest_Shyness:: - .string "扑通扑通$" -@ドキドキ - -gText_Contest_Anxiety:: - .string "慌慌张张$" -@モジモジ - -gText_Contest_Laziness:: - .string "懒懒洋洋$" -@テレテレ - -gText_Contest_Hesitancy:: - .string "犹犹豫豫$" -@オロオロ - -@ビクビク -gText_Contest_Fear:: - .string "战战栗栗$" diff --git a/data/text/move_relearner.inc b/data/text/move_relearner.inc new file mode 100644 index 0000000000..b9400fd62b --- /dev/null +++ b/data/text/move_relearner.inc @@ -0,0 +1,55 @@ +MoveRelearner_Text_WouldLearnNewMoves: + .string "Hi, I'm the Move Relearner.\n" + .string "Would you like to learn new moves?$" + +MoveRelearner_Text_LevelUpMoves: + .string "Level Up Moves$" + +MoveRelearner_Text_EggMoves: + .string "Egg Moves$" + +MoveRelearner_Text_TMMoves: + .string "TM Moves$" + +MoveRelearner_Text_TutormoveMoves: + .string "Tutor Moves$" + +MoveRelearner_Text_SeeYa: + .string "See ya!$" + +MoveRelearner_Text_AnythingElse: + .string "Is there anything else I may do for you?$" + +MoveRelearner_Text_ChoosePkmn: + .string "Please choose your Pokémon.$" + +MoveRelearner_Text_HaveNoPkmn: + .string "You have no Pokémon.$" + +MoveRelearner_Text_CantTeachMoveToEgg: + .string "Sorry…\n" + .string "But an Egg can't learn moves.$" + +MoveRelearner_Text_CantTeachMoveToPkmn: + .string "Sorry…\p" + .string "It doesn't appear as if I have any move\n" + .string "I can teach that Pokémon.$" + +MoveRelearner_Text_LevelUpMoveLWR:: + .string "level up move$" + +MoveRelearner_Text_EggMoveLWR:: + .string "egg move$" + +MoveRelearner_Text_TMMoveLWR:: + .string "TM move$" + +MoveRelearner_Text_TutorMoveLWR:: + .string "tutor move$" + +MoveRelearner_Text_WhichXmoveShouldTeach: + .string "Which {STR_VAR_3} should I teach?$" + +MoveRelearner_Text_ThankYouComeAgain: + .string "Thank you for using our services.\n" + .string "Please come again!$" diff --git a/docs/FEATURES.md b/docs/FEATURES.md new file mode 100644 index 0000000000..892a07c16b --- /dev/null +++ b/docs/FEATURES.md @@ -0,0 +1 @@ +{{#include ../FEATURES.md}} diff --git a/docs/SUMMARY.md b/docs/SUMMARY.md index a38a539bef..e5835ea07b 100644 --- a/docs/SUMMARY.md +++ b/docs/SUMMARY.md @@ -1,12 +1,14 @@ # Summary - [README](./README.md) +- [FEATURES](./FEATURES.md) - [Installation](./INSTALL.md) - [Setting up WSL1 (Legacy Portion)](./legacy_WSL1_INSTALL.md) - [ChromeOS](./install/chromeos/CHROME_OS.md) - [Linux]() - [ARCH_LINUX](./install/linux/ARCH_LINUX.md) - [DEBIAN](./install/linux/DEBIAN.md) + - [FEDORA](./install/linux/FEDORA.md) - [NIXOS](./install/linux/NIXOS.md) - [OTHERS](./install/linux/OTHERS.md) - [UBUNTU](./install/linux/UBUNTU.md) @@ -37,9 +39,15 @@ - [How to use Follower NPCs](tutorials/how_to_follower_npc.md) - [Time-Based Encounters](tutorials/how_to_time_of_day_encounters.md) - [How to use Trainer Party Pools](tutorials/how_to_trainer_party_pool.md) + - [How to Apricorn Tree](tutorials/how_to_apricorn_tree.md) + - [How to Namebox](tutorials/how_to_namebox.md) - [Vs. Seeker](tutorials/vs_seeker.md) - [Changelog](./CHANGELOG.md) + - [1.14.x]() + - [Version 1.14.1](changelogs/1.14.x/1.14.1.md) + - [Version 1.14.0](changelogs/1.14.x/1.14.0.md) - [1.13.x]() + - [Version 1.13.4](changelogs/1.13.x/1.13.4.md) - [Version 1.13.3](changelogs/1.13.x/1.13.3.md) - [Version 1.13.2](changelogs/1.13.x/1.13.2.md) - [Version 1.13.1](changelogs/1.13.x/1.13.1.md) diff --git a/docs/changelogs/1.12.x/1.12.0.md b/docs/changelogs/1.12.x/1.12.0.md index b223e040da..965ae27b27 100644 --- a/docs/changelogs/1.12.x/1.12.0.md +++ b/docs/changelogs/1.12.x/1.12.0.md @@ -121,7 +121,7 @@ - Added option to disable object event shadows - Added option to turn DNS on or off, `OW_ENABLE_DNS` - Added option to for vanilla shadow behaviour, `OW_OBJECT_VANILLA_SHADOWS` - - Scripts containing consecutive `removeobject and `addobject ` needs a `delay 1` between the commands. + - Scripts containing consecutive `removeobject ` and `addobject ` needs a `delay 1` between the commands. ```diff removeobject MY_OBJECT + delay 1 diff --git a/docs/changelogs/1.13.x/1.13.4.md b/docs/changelogs/1.13.x/1.13.4.md new file mode 100644 index 0000000000..6884bbd95c --- /dev/null +++ b/docs/changelogs/1.13.x/1.13.4.md @@ -0,0 +1,213 @@ +```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.13.4 +`. +``` + + +## 🧬 General 🧬 +### Changed +* 1.13.3 release by @hedara90 in [#8109](https://github.com/rh-hideout/pokeemerald-expansion/pull/8109) +* Adds an auto-generated include file of script commands by @FosterProgramming in [#8156](https://github.com/rh-hideout/pokeemerald-expansion/pull/8156) +* Adjust label workflow to only run if PR is approved by @hedara90 in [#8183](https://github.com/rh-hideout/pokeemerald-expansion/pull/8183) +* Add include/constants/script_commands.h to gitignore by @AlexOn1ine in [#8169](https://github.com/rh-hideout/pokeemerald-expansion/pull/8169) +* add fdeblasio as a contributor for code by @allcontributors[bot] in [#8200](https://github.com/rh-hideout/pokeemerald-expansion/pull/8200) +* Adjust Canceler naming to contain only one l by @AlexOn1ine in [#8258](https://github.com/rh-hideout/pokeemerald-expansion/pull/8258) +* Pret merge (16th of November, 2025) by @AlexOn1ine in [#8262](https://github.com/rh-hideout/pokeemerald-expansion/pull/8262) +* *.party: text with lfs by @mrgriffin in [#8320](https://github.com/rh-hideout/pokeemerald-expansion/pull/8320) +* Fedora install instructions by @estellarc in [#8355](https://github.com/rh-hideout/pokeemerald-expansion/pull/8355) +* Indent unintented if statement by @hedara90 in [#8367](https://github.com/rh-hideout/pokeemerald-expansion/pull/8367) + +### Fixed +* Update mdbook to v0.5.0-beta.1 by @rayrobdod in [#8133](https://github.com/rh-hideout/pokeemerald-expansion/pull/8133) +* Fix wild_encounters script not closing arrays properly by @FosterProgramming in [#8123](https://github.com/rh-hideout/pokeemerald-expansion/pull/8123) +* Fix missing FREE_MATCH_CALL by @FosterProgramming in [#8171](https://github.com/rh-hideout/pokeemerald-expansion/pull/8171) +* Fix scroll prompt sometimes being off-screen with automatic line breaks by @hedara90 in [#8182](https://github.com/rh-hideout/pokeemerald-expansion/pull/8182) +* Fix gcc11 again by @AsparagusEduardo in [#8188](https://github.com/rh-hideout/pokeemerald-expansion/pull/8188) +* Fixed decompression error reporter OOB window creation by @hedara90 in [#8199](https://github.com/rh-hideout/pokeemerald-expansion/pull/8199) +* Fix error when compiling with P_FUSION_FORMS disabled by @cawtds in [#8298](https://github.com/rh-hideout/pokeemerald-expansion/pull/8298) +* Fix compile on gcc11 by @AlexOn1ine in [#8300](https://github.com/rh-hideout/pokeemerald-expansion/pull/8300) +* Fix debug battle flag never being cleared by @FosterProgramming in [#8357](https://github.com/rh-hideout/pokeemerald-expansion/pull/8357) + +## 🗺️ Overworld 🗺️ +### Changed +* Add additional comment explaing map name popup transparency side-effects by @FosterProgramming in [#8117](https://github.com/rh-hideout/pokeemerald-expansion/pull/8117) + +### Fixed +* Fix berry blender not computing flavor correctly by @FosterProgramming in [#8113](https://github.com/rh-hideout/pokeemerald-expansion/pull/8113) +* Allow vs seekers to work with script not starting with trainerbattle by @FosterProgramming in [#8062](https://github.com/rh-hideout/pokeemerald-expansion/pull/8062) + - VS seeker now work with trainers who don't start with trainer_battle. You can use `vsseeker_rematchid TRAINER_ID` to indicate that this NPC is a battling trainer and the game will fetch the appropriate rematch if necessary. ` vsseeker_rematchid` work like a `cant_see_if_trainerflag_set` with additional functionality to handle vs seeker. + All NPCs who don't start with either `vsseeker_rematchid` or `trainerbattle` will show as "X"/unmatchable by the vs seeker, so non-rematchable trainer who do not start with `trainerbattle may "lie" and not show an excalmation mark showing they haven't been fought yet. This can be fixed by including a `vsseeker_rematchid` for them too. +* Fix grade in summary screen not accounting for 26 IV by @FosterProgramming in [#8157](https://github.com/rh-hideout/pokeemerald-expansion/pull/8157) +* Fix match call regression by @FosterProgramming in [#8227](https://github.com/rh-hideout/pokeemerald-expansion/pull/8227) +* Fix mew sprite not appearing correctly by @FosterProgramming in [#8235](https://github.com/rh-hideout/pokeemerald-expansion/pull/8235) +* Fix wrong palette for types sprites in hgss dex after catching mon by @FosterProgramming in [#8153](https://github.com/rh-hideout/pokeemerald-expansion/pull/8153) +* Fix mirage tower ceiling crumble color by @FosterProgramming in [#8081](https://github.com/rh-hideout/pokeemerald-expansion/pull/8081) +* Fix light flickering when different types of light sprite are present by @FosterProgramming in [#8043](https://github.com/rh-hideout/pokeemerald-expansion/pull/8043) + - Light intensity of neon signs was reduced to avoid conflicts with other light sources + - Fix flickering when both neon signs and light ball are present on screen +* Bug Fix: NPC Followers not working on slow sideways stairs by @Bivurnum in [#8257](https://github.com/rh-hideout/pokeemerald-expansion/pull/8257) +* Fix not enough memory being allocated when moves load background in contests by @FosterProgramming in [#8284](https://github.com/rh-hideout/pokeemerald-expansion/pull/8284) +* Make MON_DATA_NICKNAME10 return a 10 character string by @FosterProgramming in [#8291](https://github.com/rh-hideout/pokeemerald-expansion/pull/8291) + - Fix bug where interviews would print bad data in their string +* Fix game freeze when trainers try to walk on sideway stairs by @FosterProgramming in [#8316](https://github.com/rh-hideout/pokeemerald-expansion/pull/8316) +* Fix tossing items applying to the wrong stack by @FosterProgramming in [#8282](https://github.com/rh-hideout/pokeemerald-expansion/pull/8282) +* Prevent moves to be changed when choosing half party by @FosterProgramming in [#8336](https://github.com/rh-hideout/pokeemerald-expansion/pull/8336) + +## 🐉 Pokémon 🐉 +### Changed +* Fix Kyurem typo in swap move tables by @Bassoonian in [#8139](https://github.com/rh-hideout/pokeemerald-expansion/pull/8139) +* Fix typo in Voltorb-Hisui pokedex entry by @PhallenTree in [#8143](https://github.com/rh-hideout/pokeemerald-expansion/pull/8143) +* Fix some followers sprites by @estellarc in [#8208](https://github.com/rh-hideout/pokeemerald-expansion/pull/8208) + +## ⚔️ Battle General ⚔️ +### Changed +* Clean up redundant todo by @AlexOn1ine in [#8094](https://github.com/rh-hideout/pokeemerald-expansion/pull/8094) +* Powder Move blocking cleanup by @PhallenTree in [#8194](https://github.com/rh-hideout/pokeemerald-expansion/pull/8194) +* Restored encourageEncore flag to non-volatile status effects by @AsparagusEduardo in [#8387](https://github.com/rh-hideout/pokeemerald-expansion/pull/8387) + +### Fixed +* Allow to send active mon to PC when capturing a Pokemon by @FosterProgramming in [#8111](https://github.com/rh-hideout/pokeemerald-expansion/pull/8111) +* Fix transform not loading the correct sprites when facing shiny or unown by @FosterProgramming in [#8146](https://github.com/rh-hideout/pokeemerald-expansion/pull/8146) +* Fixes Receiver not immediately activating copied abilities by @PhallenTree in [#8162](https://github.com/rh-hideout/pokeemerald-expansion/pull/8162) +* Fix destiny knot behavior and add tests by @FosterProgramming in [#8174](https://github.com/rh-hideout/pokeemerald-expansion/pull/8174) +* Fix recharge moves + add recharge move tests by @FosterProgramming in [#8181](https://github.com/rh-hideout/pokeemerald-expansion/pull/8181) +* Fixes Magician for spread moves by @AlexOn1ine in [#8170](https://github.com/rh-hideout/pokeemerald-expansion/pull/8170) +* Fix tera tint not applying on activation by @FosterProgramming in [#8135](https://github.com/rh-hideout/pokeemerald-expansion/pull/8135) +* Fixes wrongly assigned count for Semi Invulnerable state by @AlexOn1ine in [#8175](https://github.com/rh-hideout/pokeemerald-expansion/pull/8175) +* Fixes Drain Punch / Parental Bond / Scale Shot interaction by @AlexOn1ine in [#8198](https://github.com/rh-hideout/pokeemerald-expansion/pull/8198) +* Fix wrong ditto sprite on capture by @FosterProgramming in [#8226](https://github.com/rh-hideout/pokeemerald-expansion/pull/8226) +* Fixed an issue related to same turn Encore targeting by @LinathanZel in [#8230](https://github.com/rh-hideout/pokeemerald-expansion/pull/8230) +* Fixes Shell Trap not activating on contact but no damage by @AlexOn1ine in [#8243](https://github.com/rh-hideout/pokeemerald-expansion/pull/8243) +* Fix Magic Coat reflecting hazard moves incorrectly when used by a partner by @moostoet in [#8272](https://github.com/rh-hideout/pokeemerald-expansion/pull/8272) + - Magic Coat now properly reflects hazard moves from either slot in double battles. +* Shell Trap tests and Fix for Encore interaction by @AlexOn1ine in [#8268](https://github.com/rh-hideout/pokeemerald-expansion/pull/8268) +* Fix max mushroom unable to be selected when one stat is maxed by @FosterProgramming in [#8287](https://github.com/rh-hideout/pokeemerald-expansion/pull/8287) +* Block selecting x items when contrary pokemon are at minimum stages by @FosterProgramming in [#8288](https://github.com/rh-hideout/pokeemerald-expansion/pull/8288) +* Fix Fur Coat affecting confusion self-damage by @moostoet in [#8267](https://github.com/rh-hideout/pokeemerald-expansion/pull/8267) + - Fix confusion self-damage ignoring defense/attack abilities such as Fur Coat. +* Fixes End Turn Speed Order by @AlexOn1ine in [#8289](https://github.com/rh-hideout/pokeemerald-expansion/pull/8289) +* Make switchout abilities trigger after a pokemon has returned to its ball by @FosterProgramming in [#8304](https://github.com/rh-hideout/pokeemerald-expansion/pull/8304) +* Fix Shed Shell allowing fleeing/teleporting and Smoke Ball failing to guarantee escape by @moostoet in [#8286](https://github.com/rh-hideout/pokeemerald-expansion/pull/8286) +* Fix bug where defiant/competitive would pass their stat change to the next target by @FosterProgramming in [#8312](https://github.com/rh-hideout/pokeemerald-expansion/pull/8312) +* Fix max move message against semi invulnerable target by @FosterProgramming in [#8313](https://github.com/rh-hideout/pokeemerald-expansion/pull/8313) +* Fixes Neutralizing Gas displaying message when exiting with multiple users by @PhallenTree in [#8318](https://github.com/rh-hideout/pokeemerald-expansion/pull/8318) +* Fix Kings Rock not being ignored by flinch moves by @AlexOn1ine in [#8327](https://github.com/rh-hideout/pokeemerald-expansion/pull/8327) +* Fix Protosynthesis stat boosts ignoring speed drops by @moostoet in [#8277](https://github.com/rh-hideout/pokeemerald-expansion/pull/8277) + - Protosynthesis and Quark Drive now recalculate their boosted stat when Speed is lowered or Neutralizing Gas temporarily disables the ability. +* Fix switch-in abilities not triggering on revive by @FosterProgramming in [#8293](https://github.com/rh-hideout/pokeemerald-expansion/pull/8293) +* More Neutralizing Gas cleanup by @PhallenTree in [#8335](https://github.com/rh-hideout/pokeemerald-expansion/pull/8335) +* Fix cure status item effect not working properly in doubles by @FosterProgramming in [#8339](https://github.com/rh-hideout/pokeemerald-expansion/pull/8339) +* Fix infinite confusion (berserk gene) not being cured by cure_status bag items by @FosterProgramming in [#8343](https://github.com/rh-hideout/pokeemerald-expansion/pull/8343) +* Fix `B_PHYSICAL_SPECIAL_SPLIT` when set to Gen 4 by @AsparagusEduardo in [#8348](https://github.com/rh-hideout/pokeemerald-expansion/pull/8348) +* Refactor Beat Up handling for Gen 3/4 defaults, fix crit check, and expand test coverage by @moostoet in [#8307](https://github.com/rh-hideout/pokeemerald-expansion/pull/8307) + - BUGFIX: Beat Up (`GEN =< 5`) now no longer doubles its damage on every non-critical hit + - Beat Up now precomputes eligible party members/strikers for consistent multi-hit resolution and expanded tests covering both pre-Gen5 and Gen5+ rules +* Fix substitute graphic not disappearing after using a pivor move by @FosterProgramming in [#8340](https://github.com/rh-hideout/pokeemerald-expansion/pull/8340) +* Fixes Beak Blast burning after Beak Blast was already used by @PhallenTree in [#8361](https://github.com/rh-hideout/pokeemerald-expansion/pull/8361) +* Fix Roar not being recorded for LastUsedMove by @AlexOn1ine in [#8362](https://github.com/rh-hideout/pokeemerald-expansion/pull/8362) +* Fixes Neutralizing Gas / Mold Breaker / Dragon Darts interaction by @AlexOn1ine in [#8389](https://github.com/rh-hideout/pokeemerald-expansion/pull/8389) +* Fixes battle tv overwriting damage values by @AlexOn1ine in [#8378](https://github.com/rh-hideout/pokeemerald-expansion/pull/8378) +* Fix ball cycling not working properly when the same ball take multiple bag slots by @FosterProgramming in [#8163](https://github.com/rh-hideout/pokeemerald-expansion/pull/8163) + - Two new defines added to items.h `FIRST_BALL_INDEX` and `LAST_BALL_INDEX` + - We now assume the indexes of all regular ball usable in wild battle have consecutive indexes and some features (throw ball shortcut in battle) might break if not true + +## 🤹 Moves 🤹 +### Changed +* Fixed Uproar's description and spacing by @fdeblasio in [#8187](https://github.com/rh-hideout/pokeemerald-expansion/pull/8187) +* Clean usage of gMovesInfo by @AsparagusEduardo in [#8234](https://github.com/rh-hideout/pokeemerald-expansion/pull/8234) + - Also, fixed an OOB in `HasMoveThatChangesKOThreshold` +* Make tailwind anim mirror based on side by @FosterProgramming in [#8249](https://github.com/rh-hideout/pokeemerald-expansion/pull/8249) +* Make rainbow effect anim change based on side by @FosterProgramming in [#8269](https://github.com/rh-hideout/pokeemerald-expansion/pull/8269) + - Art assets by [SonikkuA-DatH](https://github.com/SonikkuA-DatH) +* Update Lash Out description to clarify its effect by @PhallenTree in [#8372](https://github.com/rh-hideout/pokeemerald-expansion/pull/8372) + +### Fixed +* Fix some move animations leaking VRAM and freeing already freed tags by @hedara90 in [#7977](https://github.com/rh-hideout/pokeemerald-expansion/pull/7977) + +## 🧶 Items 🧶 +### Fixed +* Allow vs seekers to work with script not starting with trainerbattle by @FosterProgramming in [#8062](https://github.com/rh-hideout/pokeemerald-expansion/pull/8062) + - VS seeker now work with trainers who don't start with trainer_battle. You can use `vsseeker_rematchid TRAINER_ID` to indicate that this NPC is a battling trainer and the game will fetch the appropriate rematch if necessary. ` vsseeker_rematchid` work like a `cant_see_if_trainerflag_set` with additional functionality to handle vs seeker. + All NPCs who don't start with either `vsseeker_rematchid` or `trainerbattle` will show as "X"/unmatchable by the vs seeker, so non-rematchable trainer who do not start with `trainerbattle may "lie" and not show an excalmation mark showing they haven't been fought yet. This can be fixed by including a `vsseeker_rematchid` for them too. + +## 🤖 Battle AI 🤖 +### Fixed +* fix (AI scoring): shield dust considerations, IsMoveEffectInMinus self effect edge case, hitsToKO zero-case consideration by @ghostyboyy97 in [#8126](https://github.com/rh-hideout/pokeemerald-expansion/pull/8126) + - The AI now sees Shield Dust on the player's Pokemon correctly + - The AI now sees self-targeted positive effect boosts correctly +* fix (contrary): Contrary stat down handling in MoveEffectInPlus by @ghostyboyy97 in [#8165](https://github.com/rh-hideout/pokeemerald-expansion/pull/8165) + - When comparing positive move effects in damaging move comparison, the AI will correctly see moves like Leaf Storm as beneficial if their Pokemon has Contrary. +* Added check for parental bond killing through sturdy by @MaximeGr00 in [#8206](https://github.com/rh-hideout/pokeemerald-expansion/pull/8206) + AI now accounts for Parental Bond when checking if a move can ko the player through sturdy/focus sash. +* Fix AI_FLAG_DOUBLE_ACE_POKEMON sending duplicate Pokémon in doubles by @moostoet in [#8279](https://github.com/rh-hideout/pokeemerald-expansion/pull/8279) + - Fixed AI_FLAG_DOUBLE_ACE_POKEMON trainers resending the same Pokémon after a KO instead of their two Ace Pokémon in double battles. +* Fix switchin KO threshold logic by @Pawkkie in [#8370](https://github.com/rh-hideout/pokeemerald-expansion/pull/8370) + +## 🧹 Other Cleanup 🧹 +* Clean up redundant todo by @AlexOn1ine in [#8094](https://github.com/rh-hideout/pokeemerald-expansion/pull/8094) +* Fix Kyurem typo in swap move tables by @Bassoonian in [#8139](https://github.com/rh-hideout/pokeemerald-expansion/pull/8139) +* Fix typo in Voltorb-Hisui pokedex entry by @PhallenTree in [#8143](https://github.com/rh-hideout/pokeemerald-expansion/pull/8143) +* Fixed Uproar's description and spacing by @fdeblasio in [#8187](https://github.com/rh-hideout/pokeemerald-expansion/pull/8187) +* Add include/constants/script_commands.h to gitignore by @AlexOn1ine in [#8169](https://github.com/rh-hideout/pokeemerald-expansion/pull/8169) +* Powder Move blocking cleanup by @PhallenTree in [#8194](https://github.com/rh-hideout/pokeemerald-expansion/pull/8194) +* Clean usage of gMovesInfo by @AsparagusEduardo in [#8234](https://github.com/rh-hideout/pokeemerald-expansion/pull/8234) + - Also, fixed an OOB in `HasMoveThatChangesKOThreshold` +* Adjust Canceler naming to contain only one l by @AlexOn1ine in [#8258](https://github.com/rh-hideout/pokeemerald-expansion/pull/8258) +* Fix wrongly renamed logs by @AlexOn1ine in [#8264](https://github.com/rh-hideout/pokeemerald-expansion/pull/8264) +* Tests for Max Moves already exist by @AlexOn1ine in [#8314](https://github.com/rh-hideout/pokeemerald-expansion/pull/8314) +* Use MAP_OFFSET by @estellarc in [#8328](https://github.com/rh-hideout/pokeemerald-expansion/pull/8328) +* Fixed broken friendship from items in battle test and added new test for opposite case by @pkmnsnfrn in [#7872](https://github.com/rh-hideout/pokeemerald-expansion/pull/7872) +* Indent unintented if statement by @hedara90 in [#8367](https://github.com/rh-hideout/pokeemerald-expansion/pull/8367) +* Update Lash Out description to clarify its effect by @PhallenTree in [#8372](https://github.com/rh-hideout/pokeemerald-expansion/pull/8372) +* Restored encourageEncore flag to non-volatile status effects by @AsparagusEduardo in [#8387](https://github.com/rh-hideout/pokeemerald-expansion/pull/8387) + +## 🧪 Test Runner 🧪 +### Added +* Prevent EXPECT functions from casting negative numbers into unsigned by @FosterProgramming in [#7866](https://github.com/rh-hideout/pokeemerald-expansion/pull/7866) + +### Changed +* Added Soundproof and Bulletproof tests by @AsparagusEduardo in [#8189](https://github.com/rh-hideout/pokeemerald-expansion/pull/8189) +* Wrote some missing tests by @AsparagusEduardo in [#8203](https://github.com/rh-hideout/pokeemerald-expansion/pull/8203) +* A couple more tests by @AsparagusEduardo in [#8209](https://github.com/rh-hideout/pokeemerald-expansion/pull/8209) +* Fixed some failing tests with GEN_LATEST = GEN_5 by @AsparagusEduardo in [#8241](https://github.com/rh-hideout/pokeemerald-expansion/pull/8241) +* Add test for mold breaker/ice scales interaction by @FosterProgramming in [#8240](https://github.com/rh-hideout/pokeemerald-expansion/pull/8240) +* Yet more tests by @AsparagusEduardo in [#8228](https://github.com/rh-hideout/pokeemerald-expansion/pull/8228) + - Added tests for: + - Dark Aura + - Fairy Aura + - Flare Boost + - Toxic Boost + - Added test names for Flying Press. +* Slightly increase headless test speed by modifying animations by @AsparagusEduardo in [#8299](https://github.com/rh-hideout/pokeemerald-expansion/pull/8299) +* Make `gTestRunnerHeadless` into a constant outside of tests by @hedara90 in [#8306](https://github.com/rh-hideout/pokeemerald-expansion/pull/8306) +* Tests for Max Moves already exist by @AlexOn1ine in [#8314](https://github.com/rh-hideout/pokeemerald-expansion/pull/8314) +* Finished fixing tests when setting `GEN_LATEST` to `GEN_5` by @AsparagusEduardo in [#8263](https://github.com/rh-hideout/pokeemerald-expansion/pull/8263) +* Wrote missing Fling tests by @AsparagusEduardo in [#8383](https://github.com/rh-hideout/pokeemerald-expansion/pull/8383) + +### Fixed +* Fixes difficulty not being restored after tests by @grintoul1 in [#8129](https://github.com/rh-hideout/pokeemerald-expansion/pull/8129) +* Reset saveblock data between test runs by @hedara90 in [#8145](https://github.com/rh-hideout/pokeemerald-expansion/pull/8145) +* Fix ohko moves ai tests by @FosterProgramming in [#8309](https://github.com/rh-hideout/pokeemerald-expansion/pull/8309) +* Fixed broken friendship from items in battle test and added new test for opposite case by @pkmnsnfrn in [#7872](https://github.com/rh-hideout/pokeemerald-expansion/pull/7872) +* Add tests to verify aromatherapy is not affected by heal bell config by @FosterProgramming in [#8344](https://github.com/rh-hideout/pokeemerald-expansion/pull/8344) +* Pre gen 5 encored move now signals the test engine a move is happening by @FosterProgramming in [#8338](https://github.com/rh-hideout/pokeemerald-expansion/pull/8338) +* Refactor Beat Up handling for Gen 3/4 defaults, fix crit check, and expand test coverage by @moostoet in [#8307](https://github.com/rh-hideout/pokeemerald-expansion/pull/8307) + - BUGFIX: Beat Up (`GEN =< 5`) now no longer doubles its damage on every non-critical hit + - Beat Up now precomputes eligible party members/strikers for consistent multi-hit resolution and expanded tests covering both pre-Gen5 and Gen5+ rules +* Fix known failing AI trace test by @FosterProgramming in [#8337](https://github.com/rh-hideout/pokeemerald-expansion/pull/8337) + +## 📚 Documentation 📚 +* Lock mdbook to v0.4.35 to fix docs not building by @grintoul1 in [#8130](https://github.com/rh-hideout/pokeemerald-expansion/pull/8130) +* Add additional comment explaing map name popup transparency side-effects by @FosterProgramming in [#8117](https://github.com/rh-hideout/pokeemerald-expansion/pull/8117) +* Fix wrongly renamed logs by @AlexOn1ine in [#8264](https://github.com/rh-hideout/pokeemerald-expansion/pull/8264) +* Use MAP_OFFSET by @estellarc in [#8328](https://github.com/rh-hideout/pokeemerald-expansion/pull/8328) +* Fedora install instructions by @estellarc in [#8355](https://github.com/rh-hideout/pokeemerald-expansion/pull/8355) + + +**Full Changelog**: https://github.com/rh-hideout/pokeemerald-expansion/compare/expansion/1.13.3...expansion/1.13.4 + + + + diff --git a/docs/changelogs/1.14.x/1.14.0.md b/docs/changelogs/1.14.x/1.14.0.md new file mode 100644 index 0000000000..3a75d35e6e --- /dev/null +++ b/docs/changelogs/1.14.x/1.14.0.md @@ -0,0 +1,534 @@ +```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.14.0 +`. +``` + +## 🌋 *REFACTORS* 🌋 +📜 = Uses a migration script. +* Refactors Attackstring and PP deduction by @AlexOn1ine in [#7402](https://github.com/rh-hideout/pokeemerald-expansion/pull/7402) +* Attackcanceller fixes and improvements by @AlexOn1ine in [#7698](https://github.com/rh-hideout/pokeemerald-expansion/pull/7698) +* Fixes activation order for a couple abilities by @AlexOn1ine in [#7732](https://github.com/rh-hideout/pokeemerald-expansion/pull/7732) +* feat: change defines in `constants/abilities.h` to an enum by @khbsd in [#7006](https://github.com/rh-hideout/pokeemerald-expansion/pull/7006) +* Item battle effect refactor by @AlexOn1ine in [#7857](https://github.com/rh-hideout/pokeemerald-expansion/pull/7857) +* Optimize GetWhichBattlerFasterOrTies by @AlexOn1ine in [#7953](https://github.com/rh-hideout/pokeemerald-expansion/pull/7953) +* Decouple passive hp updates from move damage updates by @AlexOn1ine in [#7942](https://github.com/rh-hideout/pokeemerald-expansion/pull/7942) +* Make movelist calculations happen during compilation instead of runtime by @FosterProgramming in [#7967](https://github.com/rh-hideout/pokeemerald-expansion/pull/7967) + - tmIlliterate flag in speciesInfo changed to teachingType. The options are `DEFAULT_LEARNING`, `TM_ILLITERATE` and `ALL_TEACHABLES`. The first two options match the tmIlliterate = false and tmIlliterate = true while the third one allow a pokemon to learn all teachables similarly to Mew + - Reduce EWRAM usage of HGSS dex + - Fix pokemon.c needing to be recompiled everytime a .inc file was changed + - P_TUTOR_MOVES_ARRAY has been removed (now always true when HGSS dex is enabled) + - Mew move teaching exception and univeral moves are now coded in the JSON file `src/data/pokemon/special_movesets.json` under the name signatureTeachables and universalMoves +* Grudge, Destiny Bond and FaintBattler refactor by @AlexOn1ine in [#8072](https://github.com/rh-hideout/pokeemerald-expansion/pull/8072) +* Increase number of additional move effects by @AlexOn1ine in [#8149](https://github.com/rh-hideout/pokeemerald-expansion/pull/8149) +* 📜 update: time-based encounters system tuneup and @cawtds' header script by @khbsd in [#8158](https://github.com/rh-hideout/pokeemerald-expansion/pull/8158) +* Refactor random functions to be runner specific by @FosterProgramming in [#7816](https://github.com/rh-hideout/pokeemerald-expansion/pull/7816) + +## 🧬 General 🧬 +### Added +* Battle debug menu: highlight chosen action and change separator by @grintoul1 in [#7709](https://github.com/rh-hideout/pokeemerald-expansion/pull/7709) +* Implement `field_name_box` by @mudskipper13 in [#7697](https://github.com/rh-hideout/pokeemerald-expansion/pull/7697) +* Add new actions to Debug Menu by @FosterProgramming in [#7837](https://github.com/rh-hideout/pokeemerald-expansion/pull/7837) + - Adds an action to change a Pokemon ability in the party side of the Debug Menu + - Adds an action to set the friendship of a Pokemon in the party side of the Debug Menu + +* Display TM/HM's move name in the debug menu by @estellarc in [#7994](https://github.com/rh-hideout/pokeemerald-expansion/pull/7994) + +### Changed +* Text rendering optimizations by @mrgriffin in [#7497](https://github.com/rh-hideout/pokeemerald-expansion/pull/7497) +* Battle debug menu now checks correct parties depending on battler party by @grintoul1 in [#7652](https://github.com/rh-hideout/pokeemerald-expansion/pull/7652) +* Add make release target by @jschoeny in [#7296](https://github.com/rh-hideout/pokeemerald-expansion/pull/7296) + - Most of what's above. But most importantly, that normal `make` will have all the debug stuff enabled and so releases should be done with `make release`. +* Add pool rules for Mega Stones and Z-Crystals by @hedara90 in [#7720](https://github.com/rh-hideout/pokeemerald-expansion/pull/7720) +* `field_name_box` smol followup by @mudskipper13 in [#7762](https://github.com/rh-hideout/pokeemerald-expansion/pull/7762) +* Added COMPOUND_STRINGs to region_map_entries.h by @fdeblasio in [#7669](https://github.com/rh-hideout/pokeemerald-expansion/pull/7669) +* Improve ability/heldEffect access for IsBattlerGrounded func by @AlexOn1ine in [#7753](https://github.com/rh-hideout/pokeemerald-expansion/pull/7753) +* Removed `SAVE_TYPE_ERROR_SCREEN` config by @AsparagusEduardo in [#7836](https://github.com/rh-hideout/pokeemerald-expansion/pull/7836) +* Give the Coin Case when coins are maxed by @estellarc in [#7973](https://github.com/rh-hideout/pokeemerald-expansion/pull/7973) +* Revert HGSS dex and movelist changes by @FosterProgramming in [#8016](https://github.com/rh-hideout/pokeemerald-expansion/pull/8016) +* Converts some defines to enums and name unnamed enums by @Bassoonian in [#8019](https://github.com/rh-hideout/pokeemerald-expansion/pull/8019) +* Some more documentation and cleanup by @Bassoonian in [#8020](https://github.com/rh-hideout/pokeemerald-expansion/pull/8020) +* Even more enums and documentation by @Bassoonian in [#8029](https://github.com/rh-hideout/pokeemerald-expansion/pull/8029) +* Add type enum by @Bassoonian in [#8054](https://github.com/rh-hideout/pokeemerald-expansion/pull/8054) +* Minor clean up in menu.c by @estellarc in [#8060](https://github.com/rh-hideout/pokeemerald-expansion/pull/8060) +* Adds an auto-generated include file of script commands by @FosterProgramming in [#8156](https://github.com/rh-hideout/pokeemerald-expansion/pull/8156) +* Master to upcoming merge 20251107 by @grintoul1 in [#8167](https://github.com/rh-hideout/pokeemerald-expansion/pull/8167) +* porymap default settings by @FosterProgramming in [#8038](https://github.com/rh-hideout/pokeemerald-expansion/pull/8038) + - WARNING: A change was made for new projects map files to match poymap output. This change might break people's projects with existing versions of those files. The files affected are ` data/maps/map_groups.json`, `src/data/heal_locations.json`, `src/data/region_map/region_map_sections.json` and `src/data/wild_encounters.json` + If you have an issue with one of those files during the merging process, you should run this command + `git checkout HEAD -- ` + which will reset the file to the version before you initiated the merge +* Adjust label workflow to only run if PR is approved by @hedara90 in [#8183](https://github.com/rh-hideout/pokeemerald-expansion/pull/8183) +* Add include/constants/script_commands.h to gitignore by @AlexOn1ine in [#8169](https://github.com/rh-hideout/pokeemerald-expansion/pull/8169) +* Converted landmarks to COMPOUND_STRINGs by @fdeblasio in [#8205](https://github.com/rh-hideout/pokeemerald-expansion/pull/8205) +* Added contest config and cleaned up contest category variables by @fdeblasio in [#8178](https://github.com/rh-hideout/pokeemerald-expansion/pull/8178) +* Moves name box configs into a new file by @AlexOn1ine in [#8250](https://github.com/rh-hideout/pokeemerald-expansion/pull/8250) +* Converted options text into COMPOUND_STRINGs by @fdeblasio in [#8248](https://github.com/rh-hideout/pokeemerald-expansion/pull/8248) +* Adjust Canceler naming to contain only one l by @AlexOn1ine in [#8258](https://github.com/rh-hideout/pokeemerald-expansion/pull/8258) +* Pret merge (16th of November, 2025) by @AlexOn1ine in [#8262](https://github.com/rh-hideout/pokeemerald-expansion/pull/8262) +* Fixed bKGD for last_used_ball_r_cycle.png by @montmoguri in [#8261](https://github.com/rh-hideout/pokeemerald-expansion/pull/8261) +* Small bg drawing optimization by @estellarc in [#8259](https://github.com/rh-hideout/pokeemerald-expansion/pull/8259) +* Added missing 'coolness' string by @fdeblasio in [#8274](https://github.com/rh-hideout/pokeemerald-expansion/pull/8274) +* *.party: text with lfs by @mrgriffin in [#8320](https://github.com/rh-hideout/pokeemerald-expansion/pull/8320) +* Fedora install instructions by @estellarc in [#8355](https://github.com/rh-hideout/pokeemerald-expansion/pull/8355) +* Indent unintented if statement by @hedara90 in [#8367](https://github.com/rh-hideout/pokeemerald-expansion/pull/8367) + +### Fixed +* Added brackets where needed by @hedara90 in [#7781](https://github.com/rh-hideout/pokeemerald-expansion/pull/7781) +* Fix shiny stars being freed before shiny animation was played by @FosterProgramming in [#7917](https://github.com/rh-hideout/pokeemerald-expansion/pull/7917) + - Fixes shiny sparks in battle not appearing properly in rare circumstances (more common with various speedup options) +* Make movelist calculations happen during compilation instead of runtime by @FosterProgramming in [#7967](https://github.com/rh-hideout/pokeemerald-expansion/pull/7967) + - tmIlliterate flag in speciesInfo changed to teachingType. The options are `DEFAULT_LEARNING`, `TM_ILLITERATE` and `ALL_TEACHABLES`. The first two options match the tmIlliterate = false and tmIlliterate = true while the third one allow a pokemon to learn all teachables similarly to Mew + - Reduce EWRAM usage of HGSS dex + - Fix pokemon.c needing to be recompiled everytime a .inc file was changed + - P_TUTOR_MOVES_ARRAY has been removed (now always true when HGSS dex is enabled) + - Mew move teaching exception and univeral moves are now coded in the JSON file `src/data/pokemon/special_movesets.json` under the name signatureTeachables and universalMoves +* Fix unhandled config in hgss dex by @FosterProgramming in [#7999](https://github.com/rh-hideout/pokeemerald-expansion/pull/7999) +* Fixes compilation error due to #8002 by @AlexOn1ine in [#8050](https://github.com/rh-hideout/pokeemerald-expansion/pull/8050) +* Fix compile issue in gcc 11 by @AsparagusEduardo in [#8095](https://github.com/rh-hideout/pokeemerald-expansion/pull/8095) +* Update mdbook to v0.5.0-beta.1 by @rayrobdod in [#8133](https://github.com/rh-hideout/pokeemerald-expansion/pull/8133) +* Fix build failing with NOOPT=1 due to discarding static data. by @Ultimate-Bob in [#8053](https://github.com/rh-hideout/pokeemerald-expansion/pull/8053) +* Fix wild_encounters script not closing arrays properly by @FosterProgramming in [#8123](https://github.com/rh-hideout/pokeemerald-expansion/pull/8123) +* Fix missing FREE_MATCH_CALL by @FosterProgramming in [#8171](https://github.com/rh-hideout/pokeemerald-expansion/pull/8171) +* Again fixed compiling in GCC11 by @AsparagusEduardo in [#8184](https://github.com/rh-hideout/pokeemerald-expansion/pull/8184) +* Fix scroll prompt sometimes being off-screen with automatic line breaks by @hedara90 in [#8182](https://github.com/rh-hideout/pokeemerald-expansion/pull/8182) +* Fix gcc11 again by @AsparagusEduardo in [#8188](https://github.com/rh-hideout/pokeemerald-expansion/pull/8188) +* Fixed decompression error reporter OOB window creation by @hedara90 in [#8199](https://github.com/rh-hideout/pokeemerald-expansion/pull/8199) +* Fix error when compiling with P_FUSION_FORMS disabled by @cawtds in [#8298](https://github.com/rh-hideout/pokeemerald-expansion/pull/8298) +* Fix compile on gcc11 by @AlexOn1ine in [#8300](https://github.com/rh-hideout/pokeemerald-expansion/pull/8300) +* Fix debug battle flag never being cleared by @FosterProgramming in [#8357](https://github.com/rh-hideout/pokeemerald-expansion/pull/8357) + +## 🗺️ Overworld 🗺️ +### Added +* New Feature: ORAS Dowsing by @Bivurnum in [#7211](https://github.com/rh-hideout/pokeemerald-expansion/pull/7211) + - Added ORAS Dowsing Machine mechanics. +* feat: adds stevebeller's instant text and MandL27's faster text printing by @khbsd in [#8063](https://github.com/rh-hideout/pokeemerald-expansion/pull/8063) +* Implement GSC berry/apricorn tree functionality. by @GraionDilach in [#7777](https://github.com/rh-hideout/pokeemerald-expansion/pull/7777) + - Implement GSC berry/apricorn tree functionality. + +### Changed +* Trainers trigger in local id order by @grintoul1 in [#7424](https://github.com/rh-hideout/pokeemerald-expansion/pull/7424) +* Added regional form evolution condition by @AsparagusEduardo in [#6990](https://github.com/rh-hideout/pokeemerald-expansion/pull/6990) +* Update fishing odds to match official games by @FosterProgramming in [#7574](https://github.com/rh-hideout/pokeemerald-expansion/pull/7574) + - (BREAKING!) Fishing config has been moved to a new file. If you did not use default config fishing, make sure to reapply your config settings in the new file. + - (WARNING!) If you wrote custom code that calls one the following function, you may need to include `fishing.h` to get access to them(their functionaly was not affected): + - `StartFishing`previously defined in `field_player_avatar.h` + - `CalculateChainFishingShinyRolls` previously_defined in `wild_encounter.h` + - Adds a new config option to increase fish bite chance in morning and evening to match XY + - Modifies the way fishing "proximity boost" is calculated to match XY + - Fix Sticky Hold / Suction Cups bug which were increasing odds the wrong way +* Add additional comment explaing map name popup transparency side-effects by @FosterProgramming in [#8117](https://github.com/rh-hideout/pokeemerald-expansion/pull/8117) +* update: time-based encounters system tuneup and @cawtds' header script by @khbsd in [#8158](https://github.com/rh-hideout/pokeemerald-expansion/pull/8158) +* Sets instant text speed flag to false by default by @khbsd in [#8179](https://github.com/rh-hideout/pokeemerald-expansion/pull/8179) +* Follower NPCs no longer move if the player would be forced back onto the same tile. by @Bivurnum in [#8260](https://github.com/rh-hideout/pokeemerald-expansion/pull/8260) + - Follower NPCs no longer move if the player would be forced back onto the same tile + +### Fixed +* CheckForTrainersWantingBattle trainerObjects array now initialized to zero and loop now starts at zero by @grintoul1 in [#7765](https://github.com/rh-hideout/pokeemerald-expansion/pull/7765) +* Bugfix `setspeaker` Namebox not beign drawn correctly by @estellarc in [#7771](https://github.com/rh-hideout/pokeemerald-expansion/pull/7771) +* Banned species list by @FosterProgramming in [#8003](https://github.com/rh-hideout/pokeemerald-expansion/pull/8003) + - Add a window displaying caught banned species list in the Battle Frontier instead of the string detailing all the is +* Fix namebox bug when reloading the map mid-script by @FosterProgramming in [#8073](https://github.com/rh-hideout/pokeemerald-expansion/pull/8073) +* Fix copyvar instead of setvar causing issue with LTO by @FosterProgramming in [#8097](https://github.com/rh-hideout/pokeemerald-expansion/pull/8097) +* Fix berry blender not computing flavor correctly by @FosterProgramming in [#8113](https://github.com/rh-hideout/pokeemerald-expansion/pull/8113) +* Allow vs seekers to work with script not starting with trainerbattle by @FosterProgramming in [#8062](https://github.com/rh-hideout/pokeemerald-expansion/pull/8062) + - VS seeker now work with trainers who don't start with trainer_battle. You can use `vsseeker_rematchid TRAINER_ID` to indicate that this NPC is a battling trainer and the game will fetch the appropriate rematch if necessary. ` vsseeker_rematchid` work like a `cant_see_if_trainerflag_set` with additional functionality to handle vs seeker. + - All NPCs who don't start with either `vsseeker_rematchid` or `trainerbattle` will show as "X"/unmatchable by the vs seeker, so non-rematchable trainer who do not start with `trainerbattle may "lie" and not show an excalmation mark showing they haven't been fought yet. This can be fixed by including a `vsseeker_rematchid` for them too. +* Fix grade in summary screen not accounting for 26 IV by @FosterProgramming in [#8157](https://github.com/rh-hideout/pokeemerald-expansion/pull/8157) +* Fix match call regression by @FosterProgramming in [#8227](https://github.com/rh-hideout/pokeemerald-expansion/pull/8227) +* Fix mew sprite not appearing correctly by @FosterProgramming in [#8235](https://github.com/rh-hideout/pokeemerald-expansion/pull/8235) +* Fix wrong palette for types sprites in hgss dex after catching mon by @FosterProgramming in [#8153](https://github.com/rh-hideout/pokeemerald-expansion/pull/8153) +* Fix Apricorns with OW_SHOW_ITEM_DESCRIPTIONS not off by @hedara90 in [#8253](https://github.com/rh-hideout/pokeemerald-expansion/pull/8253) +* Fix mirage tower ceiling crumble color by @FosterProgramming in [#8081](https://github.com/rh-hideout/pokeemerald-expansion/pull/8081) +* Fix light flickering when different types of light sprite are present by @FosterProgramming in [#8043](https://github.com/rh-hideout/pokeemerald-expansion/pull/8043) + - Light intensity of neon signs was reduced to avoid conflicts with other light sources + - Fix flickering when both neon signs and light ball are present on screen +* Bug Fix: NPC Followers not working on slow sideways stairs by @Bivurnum in [#8257](https://github.com/rh-hideout/pokeemerald-expansion/pull/8257) + - Fixed NPC followers on slow sideways stairs +* Fix not enough memory being allocated when moves load background in contests by @FosterProgramming in [#8284](https://github.com/rh-hideout/pokeemerald-expansion/pull/8284) +* Make MON_DATA_NICKNAME10 return a 10 character string by @FosterProgramming in [#8291](https://github.com/rh-hideout/pokeemerald-expansion/pull/8291) + - Fix bug where interviews would print bad data in their string +* Fix game freeze when trainers try to walk on sideway stairs by @FosterProgramming in [#8316](https://github.com/rh-hideout/pokeemerald-expansion/pull/8316) +* Fix tossing items applying to the wrong stack by @FosterProgramming in [#8282](https://github.com/rh-hideout/pokeemerald-expansion/pull/8282) +* Prevent moves to be changed when choosing half party by @FosterProgramming in [#8336](https://github.com/rh-hideout/pokeemerald-expansion/pull/8336) + +## 🐉 Pokémon 🐉 +### Added +* Add Legends Z-A content by @Bassoonian in [#7935](https://github.com/rh-hideout/pokeemerald-expansion/pull/7935) + * To retain compatibility with your new items and species, make sure to move the new additions behind your own additions. + * The save block will shift if you have enabled `USE_DEXNAV_SEARCH_LEVELS` (due to the new species) or if `OW_SHOW_ITEM_DESCRIPTIONS` is set to `OW_ITEM_DESCRIPTIONS_FIRST_TIME` (due to the new items). +* Move Relearners for TMs, Tutors and Egg moves by @PCG06 in [#8040](https://github.com/rh-hideout/pokeemerald-expansion/pull/8040) + - Increased the size of `MAX_RELEARNER_MOVES` to 60 to prevent crashes when viewing Mew. + +### Changed +* Nickit & Thievul visual revamp by @purrfectdoodle in [#7689](https://github.com/rh-hideout/pokeemerald-expansion/pull/7689) +* Fix Kyurem typo in swap move tables by @Bassoonian in [#8139](https://github.com/rh-hideout/pokeemerald-expansion/pull/8139) +* Fix typo in Voltorb-Hisui pokedex entry by @PhallenTree in [#8143](https://github.com/rh-hideout/pokeemerald-expansion/pull/8143) +* Fix some followers sprites by @estellarc in [#8208](https://github.com/rh-hideout/pokeemerald-expansion/pull/8208) + +### Fixed +* Fix gba sprites trying load non existent female versions by @FosterProgramming in [#7996](https://github.com/rh-hideout/pokeemerald-expansion/pull/7996) + - Fixes issues with pokemon getting gender differences in later gens when using gen3 sprite config +* GetEggSpecies: Only enabled species by @mrgriffin in [#8221](https://github.com/rh-hideout/pokeemerald-expansion/pull/8221) +* Fix compiling using `make debug` by @PCG06 in [#8380](https://github.com/rh-hideout/pokeemerald-expansion/pull/8380) + +## ⚔️ Battle General ⚔️ +### Added +* Config for capture to appear critical if the pokemon is already caught by @FosterProgramming in [#7730](https://github.com/rh-hideout/pokeemerald-expansion/pull/7730) + +### Changed +* Separates FRB and FRZ animations by @grintoul1 in [#7611](https://github.com/rh-hideout/pokeemerald-expansion/pull/7611) +* Update multiple battle messages by @AsparagusEduardo in [#7529](https://github.com/rh-hideout/pokeemerald-expansion/pull/7529) + - Removed unused messages + - Changed ability "X prevents Y" to "It doesn't affect X..." + - Eg. `"The opposing Snorlax's Immunity prevents poisoning!"` + - Removed `B_ABILITY_POP_UP`. Revert commit `b501fe7354bcd957396465c621ae7af5959ac5b0` to undo this. +* Refactors Attackstring and PP deduction by @AlexOn1ine in [#7402](https://github.com/rh-hideout/pokeemerald-expansion/pull/7402) +* Remove Uproar attack battle script by @AlexOn1ine in [#7715](https://github.com/rh-hideout/pokeemerald-expansion/pull/7715) +* Fix up end turn scripts plus small documentation by @AlexOn1ine in [#7758](https://github.com/rh-hideout/pokeemerald-expansion/pull/7758) +* Remove redundant function call by @AlexOn1ine in [#7752](https://github.com/rh-hideout/pokeemerald-expansion/pull/7752) +* Minor White Herb and Neutralizing Gas clean up by @AlexOn1ine in [#7754](https://github.com/rh-hideout/pokeemerald-expansion/pull/7754) +* Minor clean up for Lightning Rod / Storm Drain by @AlexOn1ine in [#7778](https://github.com/rh-hideout/pokeemerald-expansion/pull/7778) +* Improve ability/heldEffect access for IsBattlerGrounded func by @AlexOn1ine in [#7753](https://github.com/rh-hideout/pokeemerald-expansion/pull/7753) +* Add func GetChosenMoveFromPosition by @AlexOn1ine in [#7810](https://github.com/rh-hideout/pokeemerald-expansion/pull/7810) +* GetBattlerHoldEffect clean up by @AlexOn1ine in [#7819](https://github.com/rh-hideout/pokeemerald-expansion/pull/7819) +* Remove unused gBattleStruct fields by @Bassoonian in [#7822](https://github.com/rh-hideout/pokeemerald-expansion/pull/7822) +* feat: change defines in `constants/abilities.h` to an enum by @khbsd in [#7006](https://github.com/rh-hideout/pokeemerald-expansion/pull/7006) +* Streamline tryheal macros by @Bassoonian in [#7830](https://github.com/rh-hideout/pokeemerald-expansion/pull/7830) +* No bag use flag changed to a varable by @FosterProgramming in [#7780](https://github.com/rh-hideout/pokeemerald-expansion/pull/7780) + - IMPORTANT: The config flag B_FLAG_NO_BAG_USE has been removed + - A config var B_VAR_NO_BAG_USE has been added to replace it. It allows you to choose between: + bag available in battle, bag available in wild battle only, and unavailable bag +* Remove two unused bits from battle structs by @Bassoonian in [#7835](https://github.com/rh-hideout/pokeemerald-expansion/pull/7835) +* Removes a few redundant hitmarkers by @AlexOn1ine in [#7915](https://github.com/rh-hideout/pokeemerald-expansion/pull/7915) +* Remove EffectHitSetTerrain script to use moveeffect by @AlexOn1ine in [#7938](https://github.com/rh-hideout/pokeemerald-expansion/pull/7938) +* Clean up follow up for AtkCanceller refactor by @AlexOn1ine in [#7951](https://github.com/rh-hideout/pokeemerald-expansion/pull/7951) +* Optimize GetWhichBattlerFasterOrTies by @AlexOn1ine in [#7953](https://github.com/rh-hideout/pokeemerald-expansion/pull/7953) +* Decouple passive hp updates from move damage updates by @AlexOn1ine in [#7942](https://github.com/rh-hideout/pokeemerald-expansion/pull/7942) +* Remove appearedInBattle bitfield & redundant use of sentOut partyState by @Nopinou in [#8011](https://github.com/rh-hideout/pokeemerald-expansion/pull/8011) +* Volatile cleared in a redundant spot by @AlexOn1ine in [#8015](https://github.com/rh-hideout/pokeemerald-expansion/pull/8015) +* Moved usedHeldItem to Party State struct by @AlexOn1ine in [#8006](https://github.com/rh-hideout/pokeemerald-expansion/pull/8006) +* Remove usage of gBattlerTarget for MirrorHerb/Opportunist by @AlexOn1ine in [#8033](https://github.com/rh-hideout/pokeemerald-expansion/pull/8033) +* Fixed test "Revival Blessing cannot revive a partner's party member" by @grintoul1 in [#8031](https://github.com/rh-hideout/pokeemerald-expansion/pull/8031) +* Decouple (Overworld) Statuses from ability function by @AlexOn1ine in [#8002](https://github.com/rh-hideout/pokeemerald-expansion/pull/8002) +* Combine Simple Beam and Worry Seed into one effect by @AlexOn1ine in [#8039](https://github.com/rh-hideout/pokeemerald-expansion/pull/8039) +* Clean up for item hold effect refactor by @AlexOn1ine in [#8014](https://github.com/rh-hideout/pokeemerald-expansion/pull/8014) +* Grudge, Destiny Bond and FaintBattler refactor by @AlexOn1ine in [#8072](https://github.com/rh-hideout/pokeemerald-expansion/pull/8072) +* Parametrized Ice Face's weather form change by @AsparagusEduardo in [#8115](https://github.com/rh-hideout/pokeemerald-expansion/pull/8115) +* Clean up redundant todo by @AlexOn1ine in [#8094](https://github.com/rh-hideout/pokeemerald-expansion/pull/8094) +* Deprecate various macro by @AlexOn1ine in [#8092](https://github.com/rh-hideout/pokeemerald-expansion/pull/8092) +* Fixes hacky SetMoveEffect script calls by @AlexOn1ine in [#7987](https://github.com/rh-hideout/pokeemerald-expansion/pull/7987) +* Create BattleStruct sub struct for event states by @AlexOn1ine in [#8131](https://github.com/rh-hideout/pokeemerald-expansion/pull/8131) +* Attackstring hitmarker clean up by @AlexOn1ine in [#8136](https://github.com/rh-hideout/pokeemerald-expansion/pull/8136) +* Clean up ability effect hitmarker by @AlexOn1ine in [#8138](https://github.com/rh-hideout/pokeemerald-expansion/pull/8138) +* Increase number of additional move effects by @AlexOn1ine in [#8149](https://github.com/rh-hideout/pokeemerald-expansion/pull/8149) +* Remove redundant Future Sight flag by @AlexOn1ine in [#8185](https://github.com/rh-hideout/pokeemerald-expansion/pull/8185) +* Powder Move blocking cleanup by @PhallenTree in [#8194](https://github.com/rh-hideout/pokeemerald-expansion/pull/8194) +* Micro clean up in BattleStruct by @AlexOn1ine in [#8177](https://github.com/rh-hideout/pokeemerald-expansion/pull/8177) +* HandleAction_UseMove minor cleanup by @mrgriffin in [#8214](https://github.com/rh-hideout/pokeemerald-expansion/pull/8214) +* Revert gBattleTurnCounter change by @AlexOn1ine in [#8197](https://github.com/rh-hideout/pokeemerald-expansion/pull/8197) +* Canceller -> Canceler rename by @AlexOn1ine in [#8294](https://github.com/rh-hideout/pokeemerald-expansion/pull/8294) +* Remove leftover scrtipt redirection by @AlexOn1ine in [#8317](https://github.com/rh-hideout/pokeemerald-expansion/pull/8317) +* Expand usage of FaintedActions enum in HandleFaintedMonActions by @PhallenTree in [#8346](https://github.com/rh-hideout/pokeemerald-expansion/pull/8346) +* Move end clear bits clean up by @AlexOn1ine in [#8354](https://github.com/rh-hideout/pokeemerald-expansion/pull/8354) +* Restored encourageEncore flag to non-volatile status effects by @AsparagusEduardo in [#8387](https://github.com/rh-hideout/pokeemerald-expansion/pull/8387) + +### Fixed +* Fixes Weak Armor and items not displaying stat change attributes by @PhallenTree in [#7701](https://github.com/rh-hideout/pokeemerald-expansion/pull/7701) +* Refactors ruin ability checks into a field effect by @AlexOn1ine in [#7711](https://github.com/rh-hideout/pokeemerald-expansion/pull/7711) +* Attackcanceller fixes and improvements by @AlexOn1ine in [#7698](https://github.com/rh-hideout/pokeemerald-expansion/pull/7698) +* Fix Critical Capture RNG and Catching Charm boost by @kittenchilly in [#7534](https://github.com/rh-hideout/pokeemerald-expansion/pull/7534) +* Fixes activation order for a couple abilities by @AlexOn1ine in [#7732](https://github.com/rh-hideout/pokeemerald-expansion/pull/7732) +* More White Herb fixes/clean up by @AlexOn1ine in [#7826](https://github.com/rh-hideout/pokeemerald-expansion/pull/7826) +* Missing IsBattlerAlive checks in Opportunist/Mirror Herb by @AlexOn1ine in [#7829](https://github.com/rh-hideout/pokeemerald-expansion/pull/7829) +* Item battle effect refactor by @AlexOn1ine in [#7857](https://github.com/rh-hideout/pokeemerald-expansion/pull/7857) +* Fix Fling Mental Herb message by @AlexOn1ine in [#7984](https://github.com/rh-hideout/pokeemerald-expansion/pull/7984) +* Fixes Ruin field statuses negation conditions + upcoming cleanup by @PhallenTree in [#8042](https://github.com/rh-hideout/pokeemerald-expansion/pull/8042) +* Fix nature power string and add support for evnvironment in tests by @FosterProgramming in [#8068](https://github.com/rh-hideout/pokeemerald-expansion/pull/8068) + - Add option to choose an environment when setting up a battle test +* Corrects battler position checks in battle_message.c by @grintoul1 in [#8070](https://github.com/rh-hideout/pokeemerald-expansion/pull/8070) +* Emergency Exit on hazards activation + fix end of turn activation by @PhallenTree in [#8075](https://github.com/rh-hideout/pokeemerald-expansion/pull/8075) +* Improve sBattleIntroSlideFuncs bounds check by @hedara90 in [#8084](https://github.com/rh-hideout/pokeemerald-expansion/pull/8084) +* Fixes Sticky Barb never getting transferred to attacker + tests by @PhallenTree in [#8108](https://github.com/rh-hideout/pokeemerald-expansion/pull/8108) +* Fixes flung items sometimes being blocked by Unnerve by @PhallenTree in [#8114](https://github.com/rh-hideout/pokeemerald-expansion/pull/8114) +* Adjust faint battler script by @AlexOn1ine in [#8137](https://github.com/rh-hideout/pokeemerald-expansion/pull/8137) +* Allow to send active mon to PC when capturing a Pokemon by @FosterProgramming in [#8111](https://github.com/rh-hideout/pokeemerald-expansion/pull/8111) +* Fix transform not loading the correct sprites when facing shiny or unown by @FosterProgramming in [#8146](https://github.com/rh-hideout/pokeemerald-expansion/pull/8146) +* Fixes Receiver not immediately activating copied abilities by @PhallenTree in [#8162](https://github.com/rh-hideout/pokeemerald-expansion/pull/8162) +* Fix destiny knot behavior and add tests by @FosterProgramming in [#8174](https://github.com/rh-hideout/pokeemerald-expansion/pull/8174) +* Fix recharge moves + add recharge move tests by @FosterProgramming in [#8181](https://github.com/rh-hideout/pokeemerald-expansion/pull/8181) +* Fixes Magician for spread moves by @AlexOn1ine in [#8170](https://github.com/rh-hideout/pokeemerald-expansion/pull/8170) +* Fix tera tint not applying on activation by @FosterProgramming in [#8135](https://github.com/rh-hideout/pokeemerald-expansion/pull/8135) +* Fixes wrongly assigned count for Semi Invulnerable state by @AlexOn1ine in [#8175](https://github.com/rh-hideout/pokeemerald-expansion/pull/8175) +* Fixes Drain Punch / Parental Bond / Scale Shot interaction by @AlexOn1ine in [#8198](https://github.com/rh-hideout/pokeemerald-expansion/pull/8198) +* Avoid illegal GetBattlerAtPosition by @mrgriffin in [#8225](https://github.com/rh-hideout/pokeemerald-expansion/pull/8225) +* DamageContext: chosenMove by @mrgriffin in [#8224](https://github.com/rh-hideout/pokeemerald-expansion/pull/8224) +* AccuracyCheck: Avoid calling GetMoveEffect with NO_ACC_CALC_CHECK_LOC… by @mrgriffin in [#8222](https://github.com/rh-hideout/pokeemerald-expansion/pull/8222) +* moveend: Handle MOVE_UNAVAILABLE in MOVEEND_THIRD_MOVE_BLOCK by @mrgriffin in [#8215](https://github.com/rh-hideout/pokeemerald-expansion/pull/8215) +* Fix wrong ditto sprite on capture by @FosterProgramming in [#8226](https://github.com/rh-hideout/pokeemerald-expansion/pull/8226) +* SpriteCB_EnemyShadow: Avoid use-after-free by @mrgriffin in [#8220](https://github.com/rh-hideout/pokeemerald-expansion/pull/8220) +* trysethelpinghand avoid illegal target by @mrgriffin in [#8218](https://github.com/rh-hideout/pokeemerald-expansion/pull/8218) +* Fixed an issue related to same turn Encore targeting by @LinathanZel in [#8230](https://github.com/rh-hideout/pokeemerald-expansion/pull/8230) +* Avoid illegal move retargeting in singles by @mrgriffin in [#8217](https://github.com/rh-hideout/pokeemerald-expansion/pull/8217) +* Fixes Shell Trap not activating on contact but no damage by @AlexOn1ine in [#8243](https://github.com/rh-hideout/pokeemerald-expansion/pull/8243) +* Fix Magic Coat reflecting hazard moves incorrectly when used by a partner by @moostoet in [#8272](https://github.com/rh-hideout/pokeemerald-expansion/pull/8272) + - Magic Coat now properly reflects hazard moves from either slot in double battles. +* Shell Trap tests and Fix for Encore interaction by @AlexOn1ine in [#8268](https://github.com/rh-hideout/pokeemerald-expansion/pull/8268) +* Fix max mushroom unable to be selected when one stat is maxed by @FosterProgramming in [#8287](https://github.com/rh-hideout/pokeemerald-expansion/pull/8287) +* Block selecting x items when contrary pokemon are at minimum stages by @FosterProgramming in [#8288](https://github.com/rh-hideout/pokeemerald-expansion/pull/8288) +* Fix Fur Coat affecting confusion self-damage by @moostoet in [#8267](https://github.com/rh-hideout/pokeemerald-expansion/pull/8267) + - Fix confusion self-damage ignoring defense/attack abilities such as Fur Coat. +* Fixes End Turn Speed Order by @AlexOn1ine in [#8289](https://github.com/rh-hideout/pokeemerald-expansion/pull/8289) +* Make switchout abilities trigger after a pokemon has returned to its ball by @FosterProgramming in [#8304](https://github.com/rh-hideout/pokeemerald-expansion/pull/8304) +* Fix Shed Shell allowing fleeing/teleporting and Smoke Ball failing to guarantee escape by @moostoet in [#8286](https://github.com/rh-hideout/pokeemerald-expansion/pull/8286) +* Fix bug where defiant/competitive would pass their stat change to the next target by @FosterProgramming in [#8312](https://github.com/rh-hideout/pokeemerald-expansion/pull/8312) +* Fix max move message against semi invulnerable target by @FosterProgramming in [#8313](https://github.com/rh-hideout/pokeemerald-expansion/pull/8313) +* Fixes Neutralizing Gas displaying message when exiting with multiple users by @PhallenTree in [#8318](https://github.com/rh-hideout/pokeemerald-expansion/pull/8318) +* Fix Kings Rock not being ignored by flinch moves by @AlexOn1ine in [#8327](https://github.com/rh-hideout/pokeemerald-expansion/pull/8327) +* Fix Upper Hand failure still activating Protean by @AlexOn1ine in [#8329](https://github.com/rh-hideout/pokeemerald-expansion/pull/8329) +* Fix Protosynthesis stat boosts ignoring speed drops by @moostoet in [#8277](https://github.com/rh-hideout/pokeemerald-expansion/pull/8277) + - Protosynthesis and Quark Drive now recalculate their boosted stat when Speed is lowered or Neutralizing Gas temporarily disables the ability. +* Fix switch-in abilities not triggering on revive by @FosterProgramming in [#8293](https://github.com/rh-hideout/pokeemerald-expansion/pull/8293) +* More Neutralizing Gas cleanup by @PhallenTree in [#8335](https://github.com/rh-hideout/pokeemerald-expansion/pull/8335) +* Clear Destiny Bond/Grudge bits when not activated by @PhallenTree in [#8334](https://github.com/rh-hideout/pokeemerald-expansion/pull/8334) +* Fix cure status item effect not working properly in doubles by @FosterProgramming in [#8339](https://github.com/rh-hideout/pokeemerald-expansion/pull/8339) +* Fix infinite confusion (berserk gene) not being cured by cure_status bag items by @FosterProgramming in [#8343](https://github.com/rh-hideout/pokeemerald-expansion/pull/8343) +* Fix `B_PHYSICAL_SPECIAL_SPLIT` when set to Gen 4 by @AsparagusEduardo in [#8348](https://github.com/rh-hideout/pokeemerald-expansion/pull/8348) +* Refactor Beat Up handling for Gen 3/4 defaults, fix crit check, and expand test coverage by @moostoet in [#8307](https://github.com/rh-hideout/pokeemerald-expansion/pull/8307) + - BUGFIX: Beat Up (`GEN =< 5`) now no longer doubles its damage on every non-critical hit + - Beat Up now precomputes eligible party members/strikers for consistent multi-hit resolution and expanded tests covering both pre-Gen5 and Gen5+ rules +* Fix substitute graphic not disappearing after using a pivor move by @FosterProgramming in [#8340](https://github.com/rh-hideout/pokeemerald-expansion/pull/8340) +* Fixes Beak Blast burning after Beak Blast was already used by @PhallenTree in [#8361](https://github.com/rh-hideout/pokeemerald-expansion/pull/8361) +* Fix Roar not being recorded for LastUsedMove by @AlexOn1ine in [#8362](https://github.com/rh-hideout/pokeemerald-expansion/pull/8362) +* Fixes Neutralizing Gas / Mold Breaker / Dragon Darts interaction by @AlexOn1ine in [#8389](https://github.com/rh-hideout/pokeemerald-expansion/pull/8389) +* Fixes battle tv overwriting damage values by @AlexOn1ine in [#8378](https://github.com/rh-hideout/pokeemerald-expansion/pull/8378) +* Fix ball cycling not working properly when the same ball take multiple bag slots by @FosterProgramming in [#8163](https://github.com/rh-hideout/pokeemerald-expansion/pull/8163) + - Two new defines added to items.h `FIRST_BALL_INDEX` and `LAST_BALL_INDEX` + - We now assume the indexes of all regular ball usable in wild battle have consecutive indexes and some features (throw ball shortcut in battle) might break if not true +* Prevent double Dynamax for single-trainer 2v1 multi battles by @moostoet in [#8323](https://github.com/rh-hideout/pokeemerald-expansion/pull/8323) + - Fixed AI 2v1 multibattles incorrectly allowing both opponent leads to Dynamax in the same turn. + +## 🤹 Moves 🤹 +### Changed +* Separates FRB and FRZ animations by @grintoul1 in [#7611](https://github.com/rh-hideout/pokeemerald-expansion/pull/7611) +* Fixed test "Revival Blessing cannot revive a partner's party member" by @grintoul1 in [#8031](https://github.com/rh-hideout/pokeemerald-expansion/pull/8031) +* Fixed Uproar's description and spacing by @fdeblasio in [#8187](https://github.com/rh-hideout/pokeemerald-expansion/pull/8187) +* Clean usage of gMovesInfo by @AsparagusEduardo in [#8234](https://github.com/rh-hideout/pokeemerald-expansion/pull/8234) + - Also, fixed an OOB in `HasMoveThatChangesKOThreshold` +* Added Gen 6 contest combos by @fdeblasio in [#8251](https://github.com/rh-hideout/pokeemerald-expansion/pull/8251) +* Make tailwind anim mirror based on side by @FosterProgramming in [#8249](https://github.com/rh-hideout/pokeemerald-expansion/pull/8249) +* Make rainbow effect anim change based on side by @FosterProgramming in [#8269](https://github.com/rh-hideout/pokeemerald-expansion/pull/8269) + - Art assets by [SonikkuA-DatH](https://github.com/SonikkuA-DatH) +* Update Lash Out description to clarify its effect by @PhallenTree in [#8372](https://github.com/rh-hideout/pokeemerald-expansion/pull/8372) + +### Fixed +* Fix some move animations leaking VRAM and freeing already freed tags by @hedara90 in [#7977](https://github.com/rh-hideout/pokeemerald-expansion/pull/7977) + +## 🎭 Abilities 🎭 +### Changed +* followup: AbilityBattleEffects return type is incorrect by @khbsd in [#7827](https://github.com/rh-hideout/pokeemerald-expansion/pull/7827) + +## 🧶 Items 🧶 +### Fixed +* Allow vs seekers to work with script not starting with trainerbattle by @FosterProgramming in [#8062](https://github.com/rh-hideout/pokeemerald-expansion/pull/8062) + - VS seeker now work with trainers who don't start with trainer_battle. You can use `vsseeker_rematchid TRAINER_ID` to indicate that this NPC is a battling trainer and the game will fetch the appropriate rematch if necessary. ` vsseeker_rematchid` work like a `cant_see_if_trainerflag_set` with additional functionality to handle vs seeker. + - All NPCs who don't start with either `vsseeker_rematchid` or `trainerbattle` will show as "X"/unmatchable by the vs seeker, so non-rematchable trainer who do not start with `trainerbattle may "lie" and not show an excalmation mark showing they haven't been fought yet. This can be fixed by including a `vsseeker_rematchid` for them too. +* Removed extra period in Pokéshi Doll description by @montmoguri in [#8252](https://github.com/rh-hideout/pokeemerald-expansion/pull/8252) + +## 🤖 Battle AI 🤖 +### Added +* Improved move additional effect handling; now accounts for Shield Dust. by @surskitty in [#7650](https://github.com/rh-hideout/pokeemerald-expansion/pull/7650) +* Adjusted AI handling for Gravity; AI for weather/field status additional effects. by @surskitty in [#7651](https://github.com/rh-hideout/pokeemerald-expansion/pull/7651) +* Improved AI for status curing; trainer items, Purify, Smelling Salts, Sparkling Aria by @surskitty in [#7853](https://github.com/rh-hideout/pokeemerald-expansion/pull/7853) + +### Changed +* AI uses Magnetic Flux. by @surskitty in [#7642](https://github.com/rh-hideout/pokeemerald-expansion/pull/7642) +* AI uses Flower Shield. by @surskitty in [#7640](https://github.com/rh-hideout/pokeemerald-expansion/pull/7640) +* AI uses Life Dew. by @surskitty in [#7643](https://github.com/rh-hideout/pokeemerald-expansion/pull/7643) +* AI uses Gear Up. by @surskitty in [#7641](https://github.com/rh-hideout/pokeemerald-expansion/pull/7641) +* Correcting test AI won't use status moves if partner chose Helping Hand by @surskitty in [#7649](https://github.com/rh-hideout/pokeemerald-expansion/pull/7649) +* IncreaseStatUpScore adjustments for Simple, +3 moves, Acupressure, max move effects by @surskitty in [#7662](https://github.com/rh-hideout/pokeemerald-expansion/pull/7662) +* AI handling for Coaching. by @surskitty in [#7661](https://github.com/rh-hideout/pokeemerald-expansion/pull/7661) +* Simplifying calls to IsBattlerTrapped; treats being unable to switch as trappedness by @surskitty in [#7671](https://github.com/rh-hideout/pokeemerald-expansion/pull/7671) +* AI Tests: Gimmick Support by @mrgriffin in [#7694](https://github.com/rh-hideout/pokeemerald-expansion/pull/7694) +* AI can use Z-status moves by @surskitty in [#7666](https://github.com/rh-hideout/pokeemerald-expansion/pull/7666) +* Move some checks out of IncreaseStatUpScore to ShouldRaiseAnyStat by @surskitty in [#7722](https://github.com/rh-hideout/pokeemerald-expansion/pull/7722) +* Moving additional effects out of AI_CalcMoveEffectScore and into AI_CalcMoveAdditionalEffectScore by @surskitty in [#7727](https://github.com/rh-hideout/pokeemerald-expansion/pull/7727) +* AI sees dynamic moves and Nature Power as correct types for weather, terrain by @surskitty in [#7759](https://github.com/rh-hideout/pokeemerald-expansion/pull/7759) +* Fix abusable two-turn-move switch behaviour by @Pawkkie in [#7770](https://github.com/rh-hideout/pokeemerald-expansion/pull/7770) +* Z Status move handling: Conversion, Detect, Nature Power, Transform by @surskitty in [#7721](https://github.com/rh-hideout/pokeemerald-expansion/pull/7721) +* Use stored values for ai switch-in effectiveness checks by @AlexOn1ine in [#7794](https://github.com/rh-hideout/pokeemerald-expansion/pull/7794) +* Changing all HasBattlerSideAbility to AI_IsAbilityOnSide. by @surskitty in [#7927](https://github.com/rh-hideout/pokeemerald-expansion/pull/7927) +* Weather/Terrain AI touch-ups. by @surskitty in [#7933](https://github.com/rh-hideout/pokeemerald-expansion/pull/7933) +* Improving the checks for the AI to avoid Encore; adding RISK_ENCORE_CHANCE config. by @surskitty in [#7929](https://github.com/rh-hideout/pokeemerald-expansion/pull/7929) +* Fixes CanUseLastResort and resolves 3 KNOWN_FAILING Last Resort tests by @grintoul1 in [#8032](https://github.com/rh-hideout/pokeemerald-expansion/pull/8032) +* Add AI flag AI_FLAG_KNOW_OPPONENT_PARTY to know all species in party by @moostoet in [#8290](https://github.com/rh-hideout/pokeemerald-expansion/pull/8290) + +### Fixed +* Score adjustments towards guaranteed stat drops. by @surskitty in [#7670](https://github.com/rh-hideout/pokeemerald-expansion/pull/7670) +* AI uses Extreme Evoboost. by @surskitty in [#7706](https://github.com/rh-hideout/pokeemerald-expansion/pull/7706) +* Fixes AI scoring when Priority moves are blocked by @PhallenTree in [#7745](https://github.com/rh-hideout/pokeemerald-expansion/pull/7745) +* fix (AI scoring): shield dust considerations, IsMoveEffectInMinus self effect edge case, hitsToKO zero-case consideration by @ghostyboyy97 in [#8126](https://github.com/rh-hideout/pokeemerald-expansion/pull/8126) + - The AI now sees Shield Dust on the player's Pokemon correctly + - The AI now sees self-targeted positive effect boosts correctly +* fix (contrary): Contrary stat down handling in MoveEffectInPlus by @ghostyboyy97 in [#8165](https://github.com/rh-hideout/pokeemerald-expansion/pull/8165) + - When comparing positive move effects in damaging move comparison, the AI will correctly see moves like Leaf Storm as beneficial if their Pokemon has Contrary. +* Added check for parental bond killing through sturdy by @MaximeGr00 in [#8206](https://github.com/rh-hideout/pokeemerald-expansion/pull/8206) + - AI now accounts for Parental Bond when checking if a move can ko the player through sturdy/focus sash. +* AI: Handle MOVE_UNAVAILABLE in last used moves by @mrgriffin in [#8219](https://github.com/rh-hideout/pokeemerald-expansion/pull/8219) +* Fix AI_FLAG_DOUBLE_ACE_POKEMON sending duplicate Pokémon in doubles by @moostoet in [#8279](https://github.com/rh-hideout/pokeemerald-expansion/pull/8279) + - Fixed AI_FLAG_DOUBLE_ACE_POKEMON trainers resending the same Pokémon after a KO instead of their two Ace Pokémon in double battles. +* Rework switch AI and add more tests for ace pokemon flags by @FosterProgramming in [#8321](https://github.com/rh-hideout/pokeemerald-expansion/pull/8321) + - All remaining issues with the AI flags Ace Pokemon and Double Ace pokemon should be fixed + - The smart switching AI should be less likely to switch a pokemon about to die if it doesn't have a pokemon with a good matchup to replace it +* Fix switchin KO threshold logic by @Pawkkie in [#8370](https://github.com/rh-hideout/pokeemerald-expansion/pull/8370) + +## 🧹 Other Cleanup 🧹 +* Update multiple battle messages by @AsparagusEduardo in [#7529](https://github.com/rh-hideout/pokeemerald-expansion/pull/7529) + - Removed unused messages + - Changed ability "X prevents Y" to "It doesn't affect X..." + - Eg. `"The opposing Snorlax's Immunity prevents poisoning!"` + - Removed `B_ABILITY_POP_UP`. Revert commit `b501fe7354bcd957396465c621ae7af5959ac5b0` to undo this. +* Battle debug menu now checks correct parties depending on battler party by @grintoul1 in [#7652](https://github.com/rh-hideout/pokeemerald-expansion/pull/7652) +* Correcting test AI won't use status moves if partner chose Helping Hand by @surskitty in [#7649](https://github.com/rh-hideout/pokeemerald-expansion/pull/7649) +* Remove Uproar attack battle script by @AlexOn1ine in [#7715](https://github.com/rh-hideout/pokeemerald-expansion/pull/7715) +* Fix up end turn scripts plus small documentation by @AlexOn1ine in [#7758](https://github.com/rh-hideout/pokeemerald-expansion/pull/7758) +* `field_name_box` smol followup by @mudskipper13 in [#7762](https://github.com/rh-hideout/pokeemerald-expansion/pull/7762) +* Remove redundant function call by @AlexOn1ine in [#7752](https://github.com/rh-hideout/pokeemerald-expansion/pull/7752) +* Minor White Herb and Neutralizing Gas clean up by @AlexOn1ine in [#7754](https://github.com/rh-hideout/pokeemerald-expansion/pull/7754) +* Minor clean up for Lightning Rod / Storm Drain by @AlexOn1ine in [#7778](https://github.com/rh-hideout/pokeemerald-expansion/pull/7778) +* Add func GetChosenMoveFromPosition by @AlexOn1ine in [#7810](https://github.com/rh-hideout/pokeemerald-expansion/pull/7810) +* GetBattlerHoldEffect clean up by @AlexOn1ine in [#7819](https://github.com/rh-hideout/pokeemerald-expansion/pull/7819) +* Remove unused gBattleStruct fields by @Bassoonian in [#7822](https://github.com/rh-hideout/pokeemerald-expansion/pull/7822) +* followup: AbilityBattleEffects return type is incorrect by @khbsd in [#7827](https://github.com/rh-hideout/pokeemerald-expansion/pull/7827) +* Streamline tryheal macros by @Bassoonian in [#7830](https://github.com/rh-hideout/pokeemerald-expansion/pull/7830) +* Remove two unused bits from battle structs by @Bassoonian in [#7835](https://github.com/rh-hideout/pokeemerald-expansion/pull/7835) +* Removes a few redundant hitmarkers by @AlexOn1ine in [#7915](https://github.com/rh-hideout/pokeemerald-expansion/pull/7915) +* Remove EffectHitSetTerrain script to use moveeffect by @AlexOn1ine in [#7938](https://github.com/rh-hideout/pokeemerald-expansion/pull/7938) +* Clean up follow up for AtkCanceller refactor by @AlexOn1ine in [#7951](https://github.com/rh-hideout/pokeemerald-expansion/pull/7951) +* Remove appearedInBattle bitfield & redundant use of sentOut partyState by @Nopinou in [#8011](https://github.com/rh-hideout/pokeemerald-expansion/pull/8011) +* Some more documentation and cleanup by @Bassoonian in [#8020](https://github.com/rh-hideout/pokeemerald-expansion/pull/8020) +* Volatile cleared in a redundant spot by @AlexOn1ine in [#8015](https://github.com/rh-hideout/pokeemerald-expansion/pull/8015) +* Moved usedHeldItem to Party State struct by @AlexOn1ine in [#8006](https://github.com/rh-hideout/pokeemerald-expansion/pull/8006) +* Remove usage of gBattlerTarget for MirrorHerb/Opportunist by @AlexOn1ine in [#8033](https://github.com/rh-hideout/pokeemerald-expansion/pull/8033) +* Even more enums and documentation by @Bassoonian in [#8029](https://github.com/rh-hideout/pokeemerald-expansion/pull/8029) +* Decouple (Overworld) Statuses from ability function by @AlexOn1ine in [#8002](https://github.com/rh-hideout/pokeemerald-expansion/pull/8002) +* Fixes Ruin field statuses negation conditions + upcoming cleanup by @PhallenTree in [#8042](https://github.com/rh-hideout/pokeemerald-expansion/pull/8042) +* Minor clean up in menu.c by @estellarc in [#8060](https://github.com/rh-hideout/pokeemerald-expansion/pull/8060) +* Clean up for item hold effect refactor by @AlexOn1ine in [#8014](https://github.com/rh-hideout/pokeemerald-expansion/pull/8014) +* Parametrized Ice Face's weather form change by @AsparagusEduardo in [#8115](https://github.com/rh-hideout/pokeemerald-expansion/pull/8115) +* Clean up redundant todo by @AlexOn1ine in [#8094](https://github.com/rh-hideout/pokeemerald-expansion/pull/8094) +* Deprecate various macro by @AlexOn1ine in [#8092](https://github.com/rh-hideout/pokeemerald-expansion/pull/8092) +* Fixes hacky SetMoveEffect script calls by @AlexOn1ine in [#7987](https://github.com/rh-hideout/pokeemerald-expansion/pull/7987) +* Create BattleStruct sub struct for event states by @AlexOn1ine in [#8131](https://github.com/rh-hideout/pokeemerald-expansion/pull/8131) +* Attackstring hitmarker clean up by @AlexOn1ine in [#8136](https://github.com/rh-hideout/pokeemerald-expansion/pull/8136) +* Clean up ability effect hitmarker by @AlexOn1ine in [#8138](https://github.com/rh-hideout/pokeemerald-expansion/pull/8138) +* Fix Kyurem typo in swap move tables by @Bassoonian in [#8139](https://github.com/rh-hideout/pokeemerald-expansion/pull/8139) +* Fix typo in Voltorb-Hisui pokedex entry by @PhallenTree in [#8143](https://github.com/rh-hideout/pokeemerald-expansion/pull/8143) +* porymap default settings by @FosterProgramming in [#8038](https://github.com/rh-hideout/pokeemerald-expansion/pull/8038) + - WARNING: A change was made for new projects map files to match poymap output. This change might break people's projects with existing versions of those files. The files affected are ` data/maps/map_groups.json`, `src/data/heal_locations.json`, `src/data/region_map/region_map_sections.json` and `src/data/wild_encounters.json` + If you have an issue with one of those files during the merging process, you should run this command + `git checkout HEAD -- ` + which will reset the file to the version before you initiated the merge +* Sets instant text speed flag to false by default by @khbsd in [#8179](https://github.com/rh-hideout/pokeemerald-expansion/pull/8179) +* Remove redundant Future Sight flag by @AlexOn1ine in [#8185](https://github.com/rh-hideout/pokeemerald-expansion/pull/8185) +* Fix incorrect comments by @AlexOn1ine in [#8193](https://github.com/rh-hideout/pokeemerald-expansion/pull/8193) +* Fixed Uproar's description and spacing by @fdeblasio in [#8187](https://github.com/rh-hideout/pokeemerald-expansion/pull/8187) +* Add include/constants/script_commands.h to gitignore by @AlexOn1ine in [#8169](https://github.com/rh-hideout/pokeemerald-expansion/pull/8169) +* Powder Move blocking cleanup by @PhallenTree in [#8194](https://github.com/rh-hideout/pokeemerald-expansion/pull/8194) +* Converted landmarks to COMPOUND_STRINGs by @fdeblasio in [#8205](https://github.com/rh-hideout/pokeemerald-expansion/pull/8205) +* Micro clean up in BattleStruct by @AlexOn1ine in [#8177](https://github.com/rh-hideout/pokeemerald-expansion/pull/8177) +* Clean usage of gMovesInfo by @AsparagusEduardo in [#8234](https://github.com/rh-hideout/pokeemerald-expansion/pull/8234) + - Also, fixed an OOB in `HasMoveThatChangesKOThreshold` +* HandleAction_UseMove minor cleanup by @mrgriffin in [#8214](https://github.com/rh-hideout/pokeemerald-expansion/pull/8214) +* Revert gBattleTurnCounter change by @AlexOn1ine in [#8197](https://github.com/rh-hideout/pokeemerald-expansion/pull/8197) +* Added contest config and cleaned up contest category variables by @fdeblasio in [#8178](https://github.com/rh-hideout/pokeemerald-expansion/pull/8178) +* Adjust Canceler naming to contain only one l by @AlexOn1ine in [#8258](https://github.com/rh-hideout/pokeemerald-expansion/pull/8258) +* Fix wrongly renamed logs by @AlexOn1ine in [#8264](https://github.com/rh-hideout/pokeemerald-expansion/pull/8264) +* Test type enum indentation by @AsparagusEduardo in [#8273](https://github.com/rh-hideout/pokeemerald-expansion/pull/8273) +* Added missing 'coolness' string by @fdeblasio in [#8274](https://github.com/rh-hideout/pokeemerald-expansion/pull/8274) +* Canceller -> Canceler rename by @AlexOn1ine in [#8294](https://github.com/rh-hideout/pokeemerald-expansion/pull/8294) +* Tests for Max Moves already exist by @AlexOn1ine in [#8314](https://github.com/rh-hideout/pokeemerald-expansion/pull/8314) +* Documentation clean up for MoveCanceler by @AlexOn1ine in [#8297](https://github.com/rh-hideout/pokeemerald-expansion/pull/8297) +* Use MAP_OFFSET by @estellarc in [#8328](https://github.com/rh-hideout/pokeemerald-expansion/pull/8328) +* Remove leftover scrtipt redirection by @AlexOn1ine in [#8317](https://github.com/rh-hideout/pokeemerald-expansion/pull/8317) +* Fixed broken friendship from items in battle test and added new test for opposite case by @pkmnsnfrn in [#7872](https://github.com/rh-hideout/pokeemerald-expansion/pull/7872) +* Expand usage of FaintedActions enum in HandleFaintedMonActions by @PhallenTree in [#8346](https://github.com/rh-hideout/pokeemerald-expansion/pull/8346) +* Move end clear bits clean up by @AlexOn1ine in [#8354](https://github.com/rh-hideout/pokeemerald-expansion/pull/8354) +* Indent unintented if statement by @hedara90 in [#8367](https://github.com/rh-hideout/pokeemerald-expansion/pull/8367) +* Update Lash Out description to clarify its effect by @PhallenTree in [#8372](https://github.com/rh-hideout/pokeemerald-expansion/pull/8372) +* Slight Protect moveend cleanup by @AsparagusEduardo in [#8385](https://github.com/rh-hideout/pokeemerald-expansion/pull/8385) +* Restored encourageEncore flag to non-volatile status effects by @AsparagusEduardo in [#8387](https://github.com/rh-hideout/pokeemerald-expansion/pull/8387) + +## 🧪 Test Runner 🧪 +### Added +* Multibattle testing system by @grintoul1 in [#7257](https://github.com/rh-hideout/pokeemerald-expansion/pull/7257) +* Prevent EXPECT functions from casting negative numbers into unsigned by @FosterProgramming in [#7866](https://github.com/rh-hideout/pokeemerald-expansion/pull/7866) + +### Changed +* AI Tests: Gimmick Support by @mrgriffin in [#7694](https://github.com/rh-hideout/pokeemerald-expansion/pull/7694) +* Some tests for future Dynamax AI behavior. by @surskitty in [#7707](https://github.com/rh-hideout/pokeemerald-expansion/pull/7707) +* Add some missing move animations to the move animation tests by @FosterProgramming in [#7507](https://github.com/rh-hideout/pokeemerald-expansion/pull/7507) +* Fixes CanUseLastResort and resolves 3 KNOWN_FAILING Last Resort tests by @grintoul1 in [#8032](https://github.com/rh-hideout/pokeemerald-expansion/pull/8032) +* Fixed test "Revival Blessing cannot revive a partner's party member" by @grintoul1 in [#8031](https://github.com/rh-hideout/pokeemerald-expansion/pull/8031) +* Added Soundproof and Bulletproof tests by @AsparagusEduardo in [#8189](https://github.com/rh-hideout/pokeemerald-expansion/pull/8189) +* Wrote some missing tests by @AsparagusEduardo in [#8203](https://github.com/rh-hideout/pokeemerald-expansion/pull/8203) +* Refactor random functions to be runner specific by @FosterProgramming in [#7816](https://github.com/rh-hideout/pokeemerald-expansion/pull/7816) +* A couple more tests by @AsparagusEduardo in [#8209](https://github.com/rh-hideout/pokeemerald-expansion/pull/8209) +* Fixed some failing tests with GEN_LATEST = GEN_5 by @AsparagusEduardo in [#8241](https://github.com/rh-hideout/pokeemerald-expansion/pull/8241) +* Add test for mold breaker/ice scales interaction by @FosterProgramming in [#8240](https://github.com/rh-hideout/pokeemerald-expansion/pull/8240) +* Yet more tests by @AsparagusEduardo in [#8228](https://github.com/rh-hideout/pokeemerald-expansion/pull/8228) + - Added tests for: + - Dark Aura + - Fairy Aura + - Flare Boost + - Toxic Boost + - Added test names for Flying Press. +* Test type enum indentation by @AsparagusEduardo in [#8273](https://github.com/rh-hideout/pokeemerald-expansion/pull/8273) +* Slightly increase headless test speed by modifying animations by @AsparagusEduardo in [#8299](https://github.com/rh-hideout/pokeemerald-expansion/pull/8299) +* Make `gTestRunnerHeadless` into a constant outside of tests by @hedara90 in [#8306](https://github.com/rh-hideout/pokeemerald-expansion/pull/8306) +* Tests for Max Moves already exist by @AlexOn1ine in [#8314](https://github.com/rh-hideout/pokeemerald-expansion/pull/8314) +* Finished fixing tests when setting `GEN_LATEST` to `GEN_5` by @AsparagusEduardo in [#8263](https://github.com/rh-hideout/pokeemerald-expansion/pull/8263) +* Wrote missing Fling tests by @AsparagusEduardo in [#8383](https://github.com/rh-hideout/pokeemerald-expansion/pull/8383) + +### Fixed +* Corrects ONE_VS_TWO_BATTLE_TEST to use BATTLE_TEST_ARGS_ONE_VS_TWO by @grintoul1 in [#8061](https://github.com/rh-hideout/pokeemerald-expansion/pull/8061) +* Fixes difficulty not being restored after tests by @grintoul1 in [#8129](https://github.com/rh-hideout/pokeemerald-expansion/pull/8129) +* Reset saveblock data between test runs by @hedara90 in [#8145](https://github.com/rh-hideout/pokeemerald-expansion/pull/8145) +* Sheer force test fix by @grintoul1 in [#8142](https://github.com/rh-hideout/pokeemerald-expansion/pull/8142) +* Test only enabled species by @mrgriffin in [#8216](https://github.com/rh-hideout/pokeemerald-expansion/pull/8216) +* Fix ohko moves ai tests by @FosterProgramming in [#8309](https://github.com/rh-hideout/pokeemerald-expansion/pull/8309) +* Fixed broken friendship from items in battle test and added new test for opposite case by @pkmnsnfrn in [#7872](https://github.com/rh-hideout/pokeemerald-expansion/pull/7872) +* Add tests to verify aromatherapy is not affected by heal bell config by @FosterProgramming in [#8344](https://github.com/rh-hideout/pokeemerald-expansion/pull/8344) +* Pre gen 5 encored move now signals the test engine a move is happening by @FosterProgramming in [#8338](https://github.com/rh-hideout/pokeemerald-expansion/pull/8338) +* Refactor Beat Up handling for Gen 3/4 defaults, fix crit check, and expand test coverage by @moostoet in [#8307](https://github.com/rh-hideout/pokeemerald-expansion/pull/8307) + - BUGFIX: Beat Up (`GEN =< 5`) now no longer doubles its damage on every non-critical hit + - Beat Up now precomputes eligible party members/strikers for consistent multi-hit resolution and expanded tests covering both pre-Gen5 and Gen5+ rules +* Fix player and partner trainer sprite palettes to 8 and 9, preventing unwanted palette changes by @grintoul1 in [#8127](https://github.com/rh-hideout/pokeemerald-expansion/pull/8127) +* Fix known failing AI trace test by @FosterProgramming in [#8337](https://github.com/rh-hideout/pokeemerald-expansion/pull/8337) + +## 📚 Documentation 📚 +* Converts some defines to enums and name unnamed enums by @Bassoonian in [#8019](https://github.com/rh-hideout/pokeemerald-expansion/pull/8019) +* Some more documentation and cleanup by @Bassoonian in [#8020](https://github.com/rh-hideout/pokeemerald-expansion/pull/8020) +* Even more enums and documentation by @Bassoonian in [#8029](https://github.com/rh-hideout/pokeemerald-expansion/pull/8029) +* Add type enum by @Bassoonian in [#8054](https://github.com/rh-hideout/pokeemerald-expansion/pull/8054) +* Revert reversion by @AlexOn1ine in [#8112](https://github.com/rh-hideout/pokeemerald-expansion/pull/8112) +* Lock mdbook to v0.4.35 to fix docs not building by @grintoul1 in [#8130](https://github.com/rh-hideout/pokeemerald-expansion/pull/8130) +* Add additional comment explaing map name popup transparency side-effects by @FosterProgramming in [#8117](https://github.com/rh-hideout/pokeemerald-expansion/pull/8117) +* Fix incorrect comments by @AlexOn1ine in [#8193](https://github.com/rh-hideout/pokeemerald-expansion/pull/8193) +* Moves name box configs into a new file by @AlexOn1ine in [#8250](https://github.com/rh-hideout/pokeemerald-expansion/pull/8250) +* Fix wrongly renamed logs by @AlexOn1ine in [#8264](https://github.com/rh-hideout/pokeemerald-expansion/pull/8264) +* Documentation clean up for MoveCanceler by @AlexOn1ine in [#8297](https://github.com/rh-hideout/pokeemerald-expansion/pull/8297) +* Use MAP_OFFSET by @estellarc in [#8328](https://github.com/rh-hideout/pokeemerald-expansion/pull/8328) +* Fedora install instructions by @estellarc in [#8355](https://github.com/rh-hideout/pokeemerald-expansion/pull/8355) + +## New Contributors +* @purrfectdoodle made their first contribution in [#7689](https://github.com/rh-hideout/pokeemerald-expansion/pull/7689) +* @montmoguri made their first contribution in [#8252](https://github.com/rh-hideout/pokeemerald-expansion/pull/8252) + +**Full Changelog**: https://github.com/rh-hideout/pokeemerald-expansion/compare/expansion/1.13.3...expansion/1.14.0 + + + + diff --git a/docs/changelogs/1.14.x/1.14.1.md b/docs/changelogs/1.14.x/1.14.1.md new file mode 100644 index 0000000000..1e16317076 --- /dev/null +++ b/docs/changelogs/1.14.x/1.14.1.md @@ -0,0 +1,22 @@ +```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.14.1 +`. +``` + + +## 🧬 General 🧬 +### Changed +* Pret merge, (1st of December, 2025) by @hedara90 in [#8402](https://github.com/rh-hideout/pokeemerald-expansion/pull/8402) + - This changes all the audio samples from `.aif` to `.wav`, `.aif` support is removed. + - There's a migration script to convert from `.bin` to `.wav` in `migration_scripts/1.14/bin_to_wav.py`. + - Run the migration script with `python migration_scripts/1.14/bin_to_wav.py path/to/folder/with/bin/samples` + + + +**Full Changelog**: https://github.com/rh-hideout/pokeemerald-expansion/compare/expansion/1.14.0...expansion/1.14.1 + + + + diff --git a/docs/install/linux/FEDORA.md b/docs/install/linux/FEDORA.md new file mode 100644 index 0000000000..0dba9c1e78 --- /dev/null +++ b/docs/install/linux/FEDORA.md @@ -0,0 +1,6 @@ +# Fedora instructions +## Installing dependencies +Open a terminal and run the following command from the command line: +```console +sudo dnf install gcc g++ arm-none-eabi-binutils-cs arm-none-eabi-gcc-cs arm-none-eabi-newlib git libpng-devel python3 +``` diff --git a/docs/tutorials/how_to_apricorn_tree.md b/docs/tutorials/how_to_apricorn_tree.md new file mode 100644 index 0000000000..1efd5f62fe --- /dev/null +++ b/docs/tutorials/how_to_apricorn_tree.md @@ -0,0 +1,58 @@ +# How to interact with Apricorn Trees + +![apricorn-tree](/docs/tutorials/img/apricorn_tree/apricorn-tree.gif) + +### Adding a new apricorn tree + +To add a new tree, first increase the tree count and expand the tree list in `include/constants/apricorn_tree.h`. + +Note that each tree will take a bit in the savegame's `SaveBlock3` struct so increasing `APRICORN_TREE_COUNT` **breaks the savegame**. +Due to this, pokeemerald-expansion doesn't have any trees set up by default to prevent breaking downstream savegames. +The trees support random yields and properly use plural case on plural yields. + +```diff +#define APRICORN_TREE_NONE 0 + +-#define APRICORN_TREE_COUNT 0 ++#define APRICORN_TREE_ROUTE101_RED_TREE 1 ++ ++#define APRICORN_TREE_COUNT 32 +``` + +Then list its data in `src/data/apricorns.h`. + +```diff +const struct ApricornTree gApricornTrees[APRICORN_TREE_COUNT] = +{ + [APRICORN_TREE_NONE] = + { + .minimum = 1, + .maximum = 1, + .apricornType = APRICORN_RED, + }, + ++ [APRICORN_TREE_ROUTE101_RED_TREE] = ++ { ++ .minimum = 1, ++ .maximum = 1, ++ .apricornType = APRICORN_RED, ++ }, +}; +``` +Finally, just place your new tree using Porymap. +Similarly to berries, the Sight Radius / Berry Tree ID field is used for the tree's ID. + +![apricorn-tree-porymap](/docs/tutorials/img/apricorn_tree/apricorn-tree-porymap.png) + +### Add a new apricorn type + +After you created your new item, simply expand the `ApricornType` enum in `include/constants/apricorn_tree.h`. + +```diff +enum ApricornType +{ + [...] + APRICORN_BERRY_MARANGA = ITEM_MARANGA_BERRY, ++ APRICORN_BROWN = ITEM_BROWN_APRICORN, +}; +``` diff --git a/docs/tutorials/how_to_namebox.md b/docs/tutorials/how_to_namebox.md new file mode 100644 index 0000000000..db059af61d --- /dev/null +++ b/docs/tutorials/how_to_namebox.md @@ -0,0 +1,100 @@ +# How to Use Namebox + +_New implementation made by mudskipper13, originally made by Tustin2121._ + +## Overview + +![Npc Trainers](/docs/tutorials/img/namebox/npc_trainers.gif) +![Pokenav](/docs/tutorials/img/namebox/pokenav.gif) +![Messagebox](/docs/tutorials/img/namebox/msgbox.gif) + +This is a broad and self-contained implementation of Tustin2121's namebox feature branch [here](https://github.com/tustin2121/pokeemerald/tree/feature/namebox), which includes the following: +- Cleaner implementation of namebox onto both the field message box _and_ the field PokéNav textbox. +- New configs: + - `OW_NAME_BOX_USE_DYNAMIC_WIDTH` lets the namebox use dynamic window width depending on the speaker's string length. + - When disabled and/or the speaker name is too long, `OW_NAME_BOX_DEFAULT_WIDTH` will be used as the maximum width. + - `OW_NAME_BOX_NPC_TRAINER` lets any approaching NPC trainers shows a namebox in their dialogue automagically. + - `OW_NAME_BOX_DEFAULT_WIDTH` and `OW_NAME_BOX_DEFAULT_HEIGHT` sets the default width and height. + - `OW_NAME_BOX_FOREGROUND_COLOR` and `OW_NAME_BOX_SHADOW_COLOR` sets the default text colors, the background color is handled by the engine. + - `OW_FLAG_SUPPRESS_NAME_BOX` lets you enable/disable the namebox globally, assign a flag from [`include/constants/flags.h`](/include/constants/flags.h) onto this config to be able to use it. +- Added a Speaker Name table, frequently-used names can be stored into `gSpeakerNamesTable` in [`src/data/speaker_names.h`](/src/data/speaker_names.h) and they can accessed by using a `SP_NAME_*` constant defined in [`include/constants/speaker_names.h`](/include/constants/speaker_names.h). +- Added a new scripting macro `setspeaker ([textPointer]/[SP_NAME_*])`. + - Besides a text pointer, it is possible to use the Speaker Name table to set the textPointer with the `gSpeakerNamesTable` array instead. + - Feed it either `NULL` or `SP_NAME_NONE` will remove the namebox instead. + - `release`, `releaseall`, and `closemessage` will automatically remove the namebox, together with the messagebox. +- Added a new text control code/inline text `{SPEAKER NAME_*}`. + - Unlike the `setspeaker` macro, you can only use the `SP_NAME_*` constants for this. It is partly due to the text engine's limitation itself. + - You'll need to add the constants into `charmap.txt` to be able to use them for the same reason as above. + - Feed it `SP_NAME_NONE` to remove the namebox manually. + - Similarly, `release`, `releaseall`, and `closemessage` will automatically remove the namebox, together with the message box. + +## Usage + +### `setspeaker` +#### Using a text pointer +First, define your speaker's string. +``` +Speaker_Jeremy: + .string "Jeremy$" +``` + +And then in your script, add the `setspeaker` with the speaker's name earlier. +``` +... + setspeaker Speaker_Jeremy +... +``` + +If you are using poryscript, you can also include the string right there with the `setspeaker` aka inline. +``` +... + setspeaker("Jeremy") +... +``` +#### Using a `SP_NAME_*` constant +Add the `setspeaker` with your constant. +``` + setspeaker SP_NAME_JEREMY +``` +For instruction on how to add a new Speaker Name, continue [here](#adding-a-new-speaker-name). + +### `SPEAKER` inline +The usage is identical to using `setspeaker` with `SP_NAME_*` constant, but instead it's within your _text_ script and uses the constant you added to `charmap.txt`. +``` + "{SPEAKER NAME_JEREMY}Yo wassup!" +``` +For instruction on how to add a new Speaker Name, continue [here](#adding-a-new-speaker-name). + +### Adding a new Speaker Name +1. Add a new constant to [`include/constants/speaker_names.h`](/include/constants/speaker_names.h) just after `SP_NAME_NONE` _and_ before `SP_NAME_COUNT`. +```diff + enum SpeakerNames { + SP_NAME_NONE = 0, + SP_NAME_MOM, + SP_NAME_PLAYER, ++ SP_NAME_JEREMY, + SP_NAME_COUNT + }; + +``` + +2. Add an entry to `gSpeakerNamesTable` in [`src/data/speaker_names.h`](/src/data/speaker_names.h) with your newly added constant as the array index. +```diff + const u8 *const gSpeakerNamesTable[SP_NAME_COUNT] = + { + [SP_NAME_MOM] = COMPOUND_STRING("MOM"), + [SP_NAME_PLAYER] = COMPOUND_STRING("{PLAYER}"), ++ [SP_NAME_JEREMY] = COMPOUND_STRING("JEREMY"), + }; +``` + +3. In order for this constant to be usable for `{SPEAKER}` inline, you'll need to add your constant onto [`charmap.txt`](/charmap.txt). **Do note that the order here MUST match with the one in [`include/constants/speaker_names.h`](/include/constants/speaker_names.h)!** +```diff + @ Speaker names, the order must be matching with include/constants/speaker_names.h + NAME_NONE = 00 + NAME_MOM = 01 + NAME_PLAYER = 02 +-NAME_COUNT = 03 ++NAME_JEREMY = 03 ++NAME_COUNT = 04 +``` diff --git a/docs/tutorials/how_to_new_move.md b/docs/tutorials/how_to_new_move.md index 442e2b28c9..0f7ca1d15c 100644 --- a/docs/tutorials/how_to_new_move.md +++ b/docs/tutorials/how_to_new_move.md @@ -93,14 +93,21 @@ Contains more fundamental functions that control the flow of the battle. Functio ### data/battle_scripts_1.s Each move's effect is governed by a script defined here. For a simple example, let's look at the script for Fake Out/First Impression: +TODO: New Script ``` -BattleScript_EffectFirstTurnOnly:: +BattleScript_EffectTaunt:: attackcanceler - jumpifnotfirstturn BattleScript_FailedFromAtkString - goto BattleScript_EffectHit + jumpifability BS_TARGET_SIDE, ABILITY_AROMA_VEIL, BattleScript_AromaVeilProtects + accuracycheck BattleScript_ButItFailed, ACC_CURR_MOVE + settaunt BattleScript_ButItFailed + attackanimation + waitanimation + printstring STRINGID_PKMNFELLFORTAUNT + waitmessage B_WAIT_TIME_LONG + goto BattleScript_MoveEnd ``` -`attackcanceler` is a command that covers all the cases that could cause a move to fail before it's even attempted (e.g. paralysis). And as we can tell from the commands, if it's not the first turn, we go to `BattleScript_FailedFromAtkString` which evidently causes us to print the `attackstring` ("POKEMON used MOVE") then fail ("But it failed!"). Otherwise, we go to the generic "hit" effect which is the same script for moves that just deal damage and nothing else. +`attackcanceler` is a command that covers all cases that could cause a move to fail before it's even attempted (e.g. paralysis). The next command is a jump command. A jump command can check anything and usually comes with a jump instruction. Usually it jumps to a place from where the move should pick up because of certain conditions. The next one is an accuracy check. Accuracy checks happen after all prior move failure checks happened. The next set of commands are unique to a certain move, they are mostly the same for damaging moves but can widely differ for status moves. Lastly there is `BattleScript_MoveEnd` which the move after a succesful hit. An ability activation or specific move effect like Burn, Freeze, Absorb etc. This is the most advanced part of the ROM. There are dozens upon dozens of commands and hundreds of scripts so this guide would go on forever if I were to go into more detail. To learn how these scripts work, it's best to look at a few examples of moves you know. diff --git a/docs/tutorials/how_to_testing_system.md b/docs/tutorials/how_to_testing_system.md index b663ad54b4..c2b9912898 100644 --- a/docs/tutorials/how_to_testing_system.md +++ b/docs/tutorials/how_to_testing_system.md @@ -164,17 +164,17 @@ 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. -The main differences for doubles are: +`SINGLE_BATTLE_TEST(name, results...)`, `DOUBLE_BATTLE_TEST(name, results...)`, `MULTI_BATTLE_TEST(name, results...)`, `TWO_VS_ONE_BATTLE_TEST(name, results...)`, and `ONE_VS_TWO_BATTLE_TEST(name, results...)` +Define single-, double-, 2v2-multi-, 2v1-multi-, and 1v2- 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, 2v2, 2v1, and 1v2 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...)`, `AI_DOUBLE_BATTLE_TEST(name, results...)`, `AI_MULTI_BATTLE_TEST(name, results...)`, `AI_TWO_VS_ONE_BATTLE_TEST(name, results...)`, and `AI_ONE_VS_TWO_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. -The rules remain the same as with the `SINGLE` and `DOUBLE` battle tests with some differences: +The rules remain the same as with the `SINGLE`, `DOUBLE`, `MULTI`, `TWO_VS_ONE`, and `ONE_VS_TWO` 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 - we still control the player's action the same way @@ -268,7 +268,7 @@ GIVEN { ``` ### `PLAYER` and `OPPONENT` -`PLAYER(species)` and `OPPONENT(species` +`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)` @@ -285,11 +285,29 @@ For example to create a level 42 Wobbuffet that is poisoned: **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.** +### `MULTI_PLAYER`, `MULTI_PARTNER`, `MULTI_OPPONENT_A`, and `MULTI_OPPONENT_B` +For tests using `MULTI_BATTLE_TEST`, `AI_MULTI_BATTLE_TEST`, `TWO_VS_ONE_BATTLE_TEST`, `AI_TWO_VS_ONE_BATTLE_TEST`, `ONE_VS_TWO_BATTLE_TEST`, and `AI_ONE_VS_TWO_BATTLE_TEST`, the below must be used instead of `PLAYER(species)` and `OPPONENT(species)`. +`MULTI_PLAYER(species)`, `MULTI_PARTNER(species)`, `MULTI_OPPONENT_A(species)`, and `MULTI_OPPONENT_B(species)` +Adds the species to the player's, player partner's, opponent A's, or opponent B's party, respectively. +Pokemon can be customised as per the guidance for `PLAYER(species)` and `OPPONENT(species)`. +The functions assign the Pokémon to the party of the trainer at `B_POSITION_PLAYER_LEFT`, `B_POSITION_PLAYER_RIGHT`, `B_POSITION_OPPONENT_LEFT`, and `B_POSITION_OPPONENT_RIGHT`, respectively. +`MULTI_PLAYER(species)` and `MULTI_OPPONENT_A(species)` set Pokémon starting at party index 0, while `MULTI_PARTNER(species)` and `MULTI_OPPONENT_B(species)` set Pokémon starting at party index 3. +For `ONE_VS_TWO` tests, `MULTI_PLAYER(species)` must be used for all player-side Pokémon, and for `TWO_VS_ONE` tests, `MULTI_OPPONENT_A(species)` must be used for all opponent-side Pokémon. +All `MULTI_PLAYER(species)` Pokémon must be set before any `MULTI_PARTNER(species)` Pokémon, and all `MULTI_OPPONENT_A(species)` must be set before any `MULTI_OPPONENT_B(species)` Pokémon, else Pokémon will be set in the incorrect parties in the test. +**Note where a side in a test has two trainers, the test setup manages the assigning of correct multi-party orders, therefore when using functions such as SEND_OUT, Player and Opponent A Pokémon may be referenced using indexes 0, 1, and 2, and Player's Partner and Opponent B Pokémon may be referenced using indexes 3, 4, and 5.** + ### `AI_FLAGS` `AI_FLAGS(flags)` -Specifies which AI flags are run during the test. Has use only for AI tests. +Specifies which AI flags are run for all battlers 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. +### `BATTLER_AI_FLAGS` +`BATTLER_AI_FLAGS(battler, flags)` +Specifies additional AI flags to be applied to specific battlers (battler 0/1/2/3). Has use only for AI tests. +Must be used strictly after `AI_FLAGS(flags)`, which overwrites all existing flags. +Example: `BATTLER_AI_FLAGS(3, AI_FLAG_RISKY)` used after `AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT)` +will set `AI_FLAG_RISKY` to only `battler3` (Opponent B), in addition to the flags set by `AI_FLAGS`. + ### `WHEN` ``` ... @@ -446,6 +464,20 @@ If the expected status icon is parametrized the corresponding `STATUS1` constant STATUS_ICON(player, status1); ``` +### `SUB_HIT` +`SUB_HIT(battler, captureDamage: | subBreak:)` +Causes the test to fail the test to fail if a Substitute for the specified battler doesn't take damage. +If `captureDamage` is used, the damage the substitute takes is written to the supplied pointer. +``` +u16 damage; +... +SUB_HIT(player, captureDamage: &damage); +``` +If `subBreak` is set to `TRUE`, the test will fail unless the substitute breaks. And if set to `FALSE`, the test will fail unless the substitute survives. +``` +SUB_HIT(player, subBreak: TRUE); +``` + ### `NOT` `NOT sceneCommand` Causes the test to fail if the `SCENE` command succeeds before the following command succeeds. diff --git a/docs/tutorials/img/apricorn_tree/apricorn-tree-porymap.png b/docs/tutorials/img/apricorn_tree/apricorn-tree-porymap.png new file mode 100644 index 0000000000..1b75f885da Binary files /dev/null and b/docs/tutorials/img/apricorn_tree/apricorn-tree-porymap.png differ diff --git a/docs/tutorials/img/apricorn_tree/apricorn-tree.gif b/docs/tutorials/img/apricorn_tree/apricorn-tree.gif new file mode 100644 index 0000000000..e7769d87c8 Binary files /dev/null and b/docs/tutorials/img/apricorn_tree/apricorn-tree.gif differ diff --git a/docs/tutorials/img/namebox/msgbox.gif b/docs/tutorials/img/namebox/msgbox.gif new file mode 100644 index 0000000000..a5d9455725 Binary files /dev/null and b/docs/tutorials/img/namebox/msgbox.gif differ diff --git a/docs/tutorials/img/namebox/npc_trainers.gif b/docs/tutorials/img/namebox/npc_trainers.gif new file mode 100644 index 0000000000..6e9e1b13fb Binary files /dev/null and b/docs/tutorials/img/namebox/npc_trainers.gif differ diff --git a/docs/tutorials/img/namebox/pokenav.gif b/docs/tutorials/img/namebox/pokenav.gif new file mode 100644 index 0000000000..6de3f1370d Binary files /dev/null and b/docs/tutorials/img/namebox/pokenav.gif differ diff --git a/graphics/battle_interface/last_used_ball_r_cycle.png b/graphics/battle_interface/last_used_ball_r_cycle.png index 376773d602..55b7bc7c0c 100644 Binary files a/graphics/battle_interface/last_used_ball_r_cycle.png and b/graphics/battle_interface/last_used_ball_r_cycle.png differ diff --git a/graphics/field_effects/palettes/oras_dowsing.pal b/graphics/field_effects/palettes/oras_dowsing.pal new file mode 100644 index 0000000000..d3446e3971 --- /dev/null +++ b/graphics/field_effects/palettes/oras_dowsing.pal @@ -0,0 +1,19 @@ +JASC-PAL +0100 +16 +115 197 164 +0 0 0 +255 255 255 +255 255 255 +255 255 255 +255 255 255 +255 255 255 +255 255 255 +255 255 255 +255 255 255 +255 255 255 +255 255 255 +255 255 255 +255 255 255 +255 255 255 +255 0 255 diff --git a/graphics/field_effects/pics/oras_dowsing_brendan.png b/graphics/field_effects/pics/oras_dowsing_brendan.png new file mode 100644 index 0000000000..fd83519819 Binary files /dev/null and b/graphics/field_effects/pics/oras_dowsing_brendan.png differ diff --git a/graphics/field_effects/pics/oras_dowsing_may.png b/graphics/field_effects/pics/oras_dowsing_may.png new file mode 100644 index 0000000000..6a4eb08f02 Binary files /dev/null and b/graphics/field_effects/pics/oras_dowsing_may.png differ diff --git a/graphics/object_events/pics/misc/apricorn_tree.png b/graphics/object_events/pics/misc/apricorn_tree.png new file mode 100644 index 0000000000..6267970061 Binary files /dev/null and b/graphics/object_events/pics/misc/apricorn_tree.png differ diff --git a/graphics/pokemon/castform/back_gba.png b/graphics/pokemon/castform/back_gba.png new file mode 100644 index 0000000000..6348a35e86 Binary files /dev/null and b/graphics/pokemon/castform/back_gba.png differ diff --git a/graphics/pokemon/castform/front_gba.png b/graphics/pokemon/castform/front_gba.png new file mode 100644 index 0000000000..39bfaf4266 Binary files /dev/null and b/graphics/pokemon/castform/front_gba.png differ diff --git a/graphics/pokemon/castform/icon_gba.png b/graphics/pokemon/castform/icon_gba.png new file mode 100644 index 0000000000..56c62ad076 Binary files /dev/null and b/graphics/pokemon/castform/icon_gba.png differ diff --git a/graphics/pokemon/castform/normal_gba.pal b/graphics/pokemon/castform/normal_gba.pal new file mode 100644 index 0000000000..3fe2b76928 --- /dev/null +++ b/graphics/pokemon/castform/normal_gba.pal @@ -0,0 +1,19 @@ +JASC-PAL +0100 +16 +197 197 148 +90 82 82 +205 189 189 +230 222 222 +246 246 238 +0 0 0 +255 255 255 +222 222 246 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +148 148 148 +74 82 74 +255 255 255 +24 24 24 diff --git a/graphics/pokemon/castform/rainy/back_gba.png b/graphics/pokemon/castform/rainy/back_gba.png new file mode 100644 index 0000000000..70bad9130b Binary files /dev/null and b/graphics/pokemon/castform/rainy/back_gba.png differ diff --git a/graphics/pokemon/castform/rainy/front_gba.png b/graphics/pokemon/castform/rainy/front_gba.png new file mode 100644 index 0000000000..1553740350 Binary files /dev/null and b/graphics/pokemon/castform/rainy/front_gba.png differ diff --git a/graphics/pokemon/castform/rainy/normal_gba.pal b/graphics/pokemon/castform/rainy/normal_gba.pal new file mode 100644 index 0000000000..914cdac622 --- /dev/null +++ b/graphics/pokemon/castform/rainy/normal_gba.pal @@ -0,0 +1,19 @@ +JASC-PAL +0100 +16 +197 197 148 +57 65 90 +98 115 189 +115 139 213 +148 180 205 +0 0 0 +205 238 246 +180 197 222 +139 205 222 +131 180 197 +82 98 131 +197 197 197 +148 139 148 +90 90 82 +255 255 255 +24 24 24 diff --git a/graphics/pokemon/castform/rainy/shiny_gba.pal b/graphics/pokemon/castform/rainy/shiny_gba.pal new file mode 100644 index 0000000000..914cdac622 --- /dev/null +++ b/graphics/pokemon/castform/rainy/shiny_gba.pal @@ -0,0 +1,19 @@ +JASC-PAL +0100 +16 +197 197 148 +57 65 90 +98 115 189 +115 139 213 +148 180 205 +0 0 0 +205 238 246 +180 197 222 +139 205 222 +131 180 197 +82 98 131 +197 197 197 +148 139 148 +90 90 82 +255 255 255 +24 24 24 diff --git a/graphics/pokemon/castform/shiny_gba.pal b/graphics/pokemon/castform/shiny_gba.pal new file mode 100644 index 0000000000..2fa401dd6f --- /dev/null +++ b/graphics/pokemon/castform/shiny_gba.pal @@ -0,0 +1,19 @@ +JASC-PAL +0100 +16 +197 197 148 +98 90 90 +205 164 189 +230 197 222 +255 222 255 +0 0 0 +255 246 65 +230 180 32 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +148 148 148 +74 82 74 +255 255 255 +24 24 24 diff --git a/graphics/pokemon/castform/snowy/back_gba.png b/graphics/pokemon/castform/snowy/back_gba.png new file mode 100644 index 0000000000..b4f27cbe6d Binary files /dev/null and b/graphics/pokemon/castform/snowy/back_gba.png differ diff --git a/graphics/pokemon/castform/snowy/front_gba.png b/graphics/pokemon/castform/snowy/front_gba.png new file mode 100644 index 0000000000..a75bf647e6 Binary files /dev/null and b/graphics/pokemon/castform/snowy/front_gba.png differ diff --git a/graphics/pokemon/castform/snowy/normal_gba.pal b/graphics/pokemon/castform/snowy/normal_gba.pal new file mode 100644 index 0000000000..d1c64ac75c --- /dev/null +++ b/graphics/pokemon/castform/snowy/normal_gba.pal @@ -0,0 +1,19 @@ +JASC-PAL +0100 +16 +197 197 148 +41 82 57 +123 82 189 +139 115 213 +148 180 205 +0 0 0 +197 180 255 +156 156 197 +139 205 172 +115 164 139 +98 74 115 +189 230 230 +82 115 106 +74 82 74 +255 255 255 +24 24 24 diff --git a/graphics/pokemon/castform/snowy/shiny_gba.pal b/graphics/pokemon/castform/snowy/shiny_gba.pal new file mode 100644 index 0000000000..d1c64ac75c --- /dev/null +++ b/graphics/pokemon/castform/snowy/shiny_gba.pal @@ -0,0 +1,19 @@ +JASC-PAL +0100 +16 +197 197 148 +41 82 57 +123 82 189 +139 115 213 +148 180 205 +0 0 0 +197 180 255 +156 156 197 +139 205 172 +115 164 139 +98 74 115 +189 230 230 +82 115 106 +74 82 74 +255 255 255 +24 24 24 diff --git a/graphics/pokemon/castform/sunny/back_gba.png b/graphics/pokemon/castform/sunny/back_gba.png new file mode 100644 index 0000000000..83b27298ad Binary files /dev/null and b/graphics/pokemon/castform/sunny/back_gba.png differ diff --git a/graphics/pokemon/castform/sunny/front_gba.png b/graphics/pokemon/castform/sunny/front_gba.png new file mode 100644 index 0000000000..7e14f9892e Binary files /dev/null and b/graphics/pokemon/castform/sunny/front_gba.png differ diff --git a/graphics/pokemon/castform/sunny/normal_gba.pal b/graphics/pokemon/castform/sunny/normal_gba.pal new file mode 100644 index 0000000000..af0cfbb93b --- /dev/null +++ b/graphics/pokemon/castform/sunny/normal_gba.pal @@ -0,0 +1,19 @@ +JASC-PAL +0100 +16 +197 197 148 +98 49 41 +205 90 74 +238 123 74 +255 156 65 +0 0 0 +255 246 106 +230 213 106 +255 156 98 +213 131 74 +148 90 65 +213 205 230 +0 0 0 +90 90 82 +255 255 255 +24 24 24 diff --git a/graphics/pokemon/castform/sunny/shiny_gba.pal b/graphics/pokemon/castform/sunny/shiny_gba.pal new file mode 100644 index 0000000000..af0cfbb93b --- /dev/null +++ b/graphics/pokemon/castform/sunny/shiny_gba.pal @@ -0,0 +1,19 @@ +JASC-PAL +0100 +16 +197 197 148 +98 49 41 +205 90 74 +238 123 74 +255 156 65 +0 0 0 +255 246 106 +230 213 106 +255 156 98 +213 131 74 +148 90 65 +213 205 230 +0 0 0 +90 90 82 +255 255 255 +24 24 24 diff --git a/graphics/pokemon/deoxys/attack/back_gba.png b/graphics/pokemon/deoxys/attack/back_gba.png new file mode 100644 index 0000000000..6f9b3fd9ef Binary files /dev/null and b/graphics/pokemon/deoxys/attack/back_gba.png differ diff --git a/graphics/pokemon/deoxys/attack/front_gba.png b/graphics/pokemon/deoxys/attack/front_gba.png new file mode 100644 index 0000000000..67c092649e Binary files /dev/null and b/graphics/pokemon/deoxys/attack/front_gba.png differ diff --git a/graphics/pokemon/deoxys/attack/normal_gba.pal b/graphics/pokemon/deoxys/attack/normal_gba.pal new file mode 100644 index 0000000000..e8921dd3d5 --- /dev/null +++ b/graphics/pokemon/deoxys/attack/normal_gba.pal @@ -0,0 +1,19 @@ +JASC-PAL +0100 +16 +205 205 255 +115 74 49 +213 106 106 +255 131 74 +255 172 131 +115 213 172 +82 172 123 +57 98 90 +0 0 0 +156 156 131 +106 8 156 +0 98 230 +115 115 106 +197 197 213 +255 255 255 +24 24 24 diff --git a/graphics/pokemon/deoxys/attack/shiny_gba.pal b/graphics/pokemon/deoxys/attack/shiny_gba.pal new file mode 100644 index 0000000000..666acaa3ae --- /dev/null +++ b/graphics/pokemon/deoxys/attack/shiny_gba.pal @@ -0,0 +1,19 @@ +JASC-PAL +0100 +16 +205 205 255 +106 90 24 +197 189 65 +255 222 74 +255 246 139 +115 213 172 +82 172 123 +57 98 90 +0 0 0 +156 156 131 +106 8 156 +0 98 230 +115 115 106 +197 197 213 +255 255 255 +24 24 24 diff --git a/graphics/pokemon/deoxys/defense/back_gba.png b/graphics/pokemon/deoxys/defense/back_gba.png new file mode 100644 index 0000000000..c1fcf46738 Binary files /dev/null and b/graphics/pokemon/deoxys/defense/back_gba.png differ diff --git a/graphics/pokemon/deoxys/defense/front_gba.png b/graphics/pokemon/deoxys/defense/front_gba.png new file mode 100644 index 0000000000..5e2f38019e Binary files /dev/null and b/graphics/pokemon/deoxys/defense/front_gba.png differ diff --git a/graphics/pokemon/deoxys/defense/normal_gba.pal b/graphics/pokemon/deoxys/defense/normal_gba.pal new file mode 100644 index 0000000000..e8921dd3d5 --- /dev/null +++ b/graphics/pokemon/deoxys/defense/normal_gba.pal @@ -0,0 +1,19 @@ +JASC-PAL +0100 +16 +205 205 255 +115 74 49 +213 106 106 +255 131 74 +255 172 131 +115 213 172 +82 172 123 +57 98 90 +0 0 0 +156 156 131 +106 8 156 +0 98 230 +115 115 106 +197 197 213 +255 255 255 +24 24 24 diff --git a/graphics/pokemon/deoxys/defense/shiny_gba.pal b/graphics/pokemon/deoxys/defense/shiny_gba.pal new file mode 100644 index 0000000000..666acaa3ae --- /dev/null +++ b/graphics/pokemon/deoxys/defense/shiny_gba.pal @@ -0,0 +1,19 @@ +JASC-PAL +0100 +16 +205 205 255 +106 90 24 +197 189 65 +255 222 74 +255 246 139 +115 213 172 +82 172 123 +57 98 90 +0 0 0 +156 156 131 +106 8 156 +0 98 230 +115 115 106 +197 197 213 +255 255 255 +24 24 24 diff --git a/graphics/pokemon/deoxys/speed/back_gba.png b/graphics/pokemon/deoxys/speed/back_gba.png new file mode 100644 index 0000000000..979936c640 Binary files /dev/null and b/graphics/pokemon/deoxys/speed/back_gba.png differ diff --git a/graphics/pokemon/deoxys/speed/front_gba.png b/graphics/pokemon/deoxys/speed/front_gba.png new file mode 100644 index 0000000000..ab713aeeaf Binary files /dev/null and b/graphics/pokemon/deoxys/speed/front_gba.png differ diff --git a/graphics/pokemon/deoxys/speed/normal_gba.pal b/graphics/pokemon/deoxys/speed/normal_gba.pal new file mode 100644 index 0000000000..90fcff114b --- /dev/null +++ b/graphics/pokemon/deoxys/speed/normal_gba.pal @@ -0,0 +1,19 @@ +JASC-PAL +0100 +16 +205 205 255 +115 74 49 +213 106 106 +255 131 74 +255 172 131 +115 213 172 +131 164 156 +57 98 90 +82 74 65 +156 156 131 +139 8 205 +222 106 230 +123 115 82 +197 197 213 +255 255 255 +24 24 24 diff --git a/graphics/pokemon/deoxys/speed/shiny_gba.pal b/graphics/pokemon/deoxys/speed/shiny_gba.pal new file mode 100644 index 0000000000..74b8fc7775 --- /dev/null +++ b/graphics/pokemon/deoxys/speed/shiny_gba.pal @@ -0,0 +1,19 @@ +JASC-PAL +0100 +16 +205 205 255 +106 90 24 +197 189 65 +255 222 57 +255 246 139 +115 213 172 +82 172 123 +57 98 90 +82 74 65 +156 156 131 +106 8 156 +0 98 230 +115 115 106 +197 197 213 +255 255 255 +24 24 24 diff --git a/graphics/pokemon/flabebe/blue/overworld.png b/graphics/pokemon/flabebe/blue/overworld.png index cd98db3a57..09982c244a 100644 Binary files a/graphics/pokemon/flabebe/blue/overworld.png and b/graphics/pokemon/flabebe/blue/overworld.png differ diff --git a/graphics/pokemon/flabebe/orange/overworld.png b/graphics/pokemon/flabebe/orange/overworld.png index 482ff4f29e..cf7ca349de 100644 Binary files a/graphics/pokemon/flabebe/orange/overworld.png and b/graphics/pokemon/flabebe/orange/overworld.png differ diff --git a/graphics/pokemon/flabebe/overworld.png b/graphics/pokemon/flabebe/overworld.png index 3ad946f5f8..9bb8f7f535 100644 Binary files a/graphics/pokemon/flabebe/overworld.png and b/graphics/pokemon/flabebe/overworld.png differ diff --git a/graphics/pokemon/flabebe/white/overworld.png b/graphics/pokemon/flabebe/white/overworld.png index 35b4b2f358..df004f2fe1 100644 Binary files a/graphics/pokemon/flabebe/white/overworld.png and b/graphics/pokemon/flabebe/white/overworld.png differ diff --git a/graphics/pokemon/flabebe/yellow/overworld.png b/graphics/pokemon/flabebe/yellow/overworld.png index b0f7a47f7a..43b620a761 100644 Binary files a/graphics/pokemon/flabebe/yellow/overworld.png and b/graphics/pokemon/flabebe/yellow/overworld.png differ diff --git a/graphics/pokemon/floette/blue/overworld.png b/graphics/pokemon/floette/blue/overworld.png index 034b336557..01dd295814 100644 Binary files a/graphics/pokemon/floette/blue/overworld.png and b/graphics/pokemon/floette/blue/overworld.png differ diff --git a/graphics/pokemon/floette/eternal/overworld.png b/graphics/pokemon/floette/eternal/overworld.png index 890288792c..d8cd5c5807 100644 Binary files a/graphics/pokemon/floette/eternal/overworld.png and b/graphics/pokemon/floette/eternal/overworld.png differ diff --git a/graphics/pokemon/floette/orange/overworld.png b/graphics/pokemon/floette/orange/overworld.png index f1559fcdc5..b40d7c8c99 100644 Binary files a/graphics/pokemon/floette/orange/overworld.png and b/graphics/pokemon/floette/orange/overworld.png differ diff --git a/graphics/pokemon/floette/overworld.png b/graphics/pokemon/floette/overworld.png index 54f4dd54af..11be9e078b 100644 Binary files a/graphics/pokemon/floette/overworld.png and b/graphics/pokemon/floette/overworld.png differ diff --git a/graphics/pokemon/floette/white/overworld.png b/graphics/pokemon/floette/white/overworld.png index af49bcc921..fbf3e297a1 100644 Binary files a/graphics/pokemon/floette/white/overworld.png and b/graphics/pokemon/floette/white/overworld.png differ diff --git a/graphics/pokemon/floette/yellow/overworld.png b/graphics/pokemon/floette/yellow/overworld.png index 647e814977..6d515a7661 100644 Binary files a/graphics/pokemon/floette/yellow/overworld.png and b/graphics/pokemon/floette/yellow/overworld.png differ diff --git a/graphics/pokemon/gliscor/anim_front.png b/graphics/pokemon/gliscor/anim_front.png index 8c12ed4ef8..0454687c44 100644 Binary files a/graphics/pokemon/gliscor/anim_front.png and b/graphics/pokemon/gliscor/anim_front.png differ diff --git a/graphics/pokemon/gliscor/shiny.pal b/graphics/pokemon/gliscor/shiny.pal index 647a9cd6c5..6faf8d1e9d 100644 --- a/graphics/pokemon/gliscor/shiny.pal +++ b/graphics/pokemon/gliscor/shiny.pal @@ -15,5 +15,5 @@ JASC-PAL 168 144 0 248 216 0 64 64 80 -176 160 248 192 80 144 +104 104 120 diff --git a/graphics/pokemon/nickit/front.png b/graphics/pokemon/nickit/front.png index 9aba8f113c..6bcf9854fc 100644 Binary files a/graphics/pokemon/nickit/front.png and b/graphics/pokemon/nickit/front.png differ diff --git a/graphics/pokemon/nickit/normal.pal b/graphics/pokemon/nickit/normal.pal index 487647accd..74565685e7 100644 --- a/graphics/pokemon/nickit/normal.pal +++ b/graphics/pokemon/nickit/normal.pal @@ -5,12 +5,12 @@ JASC-PAL 40 40 32 64 64 48 16 16 16 -136 64 48 +136 64 62 64 24 16 -192 80 24 +193 108 65 216 216 224 -136 120 136 -200 184 0 +159 147 159 +197 148 0 0 0 0 0 0 0 0 0 0 diff --git a/graphics/pokemon/nickit/overworld.png b/graphics/pokemon/nickit/overworld.png index 2b868637e5..206e266190 100644 Binary files a/graphics/pokemon/nickit/overworld.png and b/graphics/pokemon/nickit/overworld.png differ diff --git a/graphics/pokemon/nickit/overworld_normal.pal b/graphics/pokemon/nickit/overworld_normal.pal index faa146c087..ff8c34acea 100644 --- a/graphics/pokemon/nickit/overworld_normal.pal +++ b/graphics/pokemon/nickit/overworld_normal.pal @@ -1,19 +1,19 @@ JASC-PAL 0100 16 -255 0 25 +128 196 156 8 8 7 -0 0 0 52 51 48 -21 20 18 -121 53 31 -185 90 59 -36 14 7 -255 255 255 -210 184 61 +91 41 25 92 92 92 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 +136 59 35 +185 90 59 +210 184 61 +159 147 159 +223 218 223 +255 255 255 +255 0 0 +255 0 0 +255 0 0 +255 0 0 +255 0 0 diff --git a/graphics/pokemon/nickit/overworld_shiny.pal b/graphics/pokemon/nickit/overworld_shiny.pal index 50a8845599..7327a9c8b6 100644 --- a/graphics/pokemon/nickit/overworld_shiny.pal +++ b/graphics/pokemon/nickit/overworld_shiny.pal @@ -1,19 +1,19 @@ JASC-PAL 0100 16 -152 208 160 -0 0 24 -0 0 0 -8 41 115 -0 16 74 -115 106 98 -164 148 139 -24 24 24 +128 196 156 +8 8 7 +51 76 95 +82 75 73 +92 92 92 +122 112 109 +167 154 149 +210 184 61 +159 147 159 +223 218 223 255 255 255 -213 189 57 -90 90 90 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 +255 0 0 +255 0 0 +255 0 0 +255 0 0 +255 0 0 diff --git a/graphics/pokemon/spinda/anim_front_gba.png b/graphics/pokemon/spinda/anim_front_gba.png new file mode 100644 index 0000000000..7ddfbef517 Binary files /dev/null and b/graphics/pokemon/spinda/anim_front_gba.png differ diff --git a/graphics/pokemon/spinda/back_gba.png b/graphics/pokemon/spinda/back_gba.png new file mode 100644 index 0000000000..c5f699e2cf Binary files /dev/null and b/graphics/pokemon/spinda/back_gba.png differ diff --git a/graphics/pokemon/spinda/icon_gba.png b/graphics/pokemon/spinda/icon_gba.png new file mode 100644 index 0000000000..75699c7cbb Binary files /dev/null and b/graphics/pokemon/spinda/icon_gba.png differ diff --git a/graphics/pokemon/spinda/normal_gba.pal b/graphics/pokemon/spinda/normal_gba.pal new file mode 100644 index 0000000000..9b0ad5bfc4 --- /dev/null +++ b/graphics/pokemon/spinda/normal_gba.pal @@ -0,0 +1,19 @@ +JASC-PAL +0100 +16 +49 164 82 +246 230 172 +230 213 164 +197 180 131 +172 148 106 +222 139 74 +222 106 57 +180 90 41 +156 57 24 +115 65 16 +172 65 90 +255 255 0 +255 255 0 +123 98 74 +90 65 49 +16 16 16 diff --git a/graphics/pokemon/spinda/shiny_gba.pal b/graphics/pokemon/spinda/shiny_gba.pal new file mode 100644 index 0000000000..6aa7481296 --- /dev/null +++ b/graphics/pokemon/spinda/shiny_gba.pal @@ -0,0 +1,19 @@ +JASC-PAL +0100 +16 +49 164 82 +246 230 172 +230 213 164 +197 180 131 +172 148 106 +180 197 90 +148 164 57 +115 131 24 +82 98 0 +49 65 0 +172 65 90 +255 255 0 +255 255 0 +123 98 74 +90 65 49 +16 16 16 diff --git a/graphics/pokemon/thievul/back.png b/graphics/pokemon/thievul/back.png index 7658e0ec22..10b145f4ea 100644 Binary files a/graphics/pokemon/thievul/back.png and b/graphics/pokemon/thievul/back.png differ diff --git a/graphics/pokemon/thievul/front.png b/graphics/pokemon/thievul/front.png index 447aeaf02b..941b0b9a2a 100644 Binary files a/graphics/pokemon/thievul/front.png and b/graphics/pokemon/thievul/front.png differ diff --git a/graphics/pokemon/thievul/normal.pal b/graphics/pokemon/thievul/normal.pal index 3f3b4bf6d1..74565685e7 100644 --- a/graphics/pokemon/thievul/normal.pal +++ b/graphics/pokemon/thievul/normal.pal @@ -2,18 +2,18 @@ JASC-PAL 0100 16 152 208 160 -24 24 16 40 40 32 +64 64 48 16 16 16 -104 56 48 +136 64 62 64 24 16 -192 80 24 -136 120 136 -136 64 48 +193 108 65 216 216 224 -216 136 0 -176 160 184 -80 72 80 +159 147 159 +197 148 0 +0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 diff --git a/graphics/pokemon/thievul/overworld.png b/graphics/pokemon/thievul/overworld.png index c835302471..53cf0b5b0e 100644 Binary files a/graphics/pokemon/thievul/overworld.png and b/graphics/pokemon/thievul/overworld.png differ diff --git a/graphics/pokemon/thievul/overworld_normal.pal b/graphics/pokemon/thievul/overworld_normal.pal index 764d23bb60..ff8c34acea 100644 --- a/graphics/pokemon/thievul/overworld_normal.pal +++ b/graphics/pokemon/thievul/overworld_normal.pal @@ -1,19 +1,19 @@ JASC-PAL 0100 16 -238 255 0 +128 196 156 8 8 7 52 51 48 -0 0 0 -121 53 31 -21 20 18 -185 90 59 -36 14 7 -255 255 255 -210 184 61 +91 41 25 92 92 92 -176 176 176 -0 0 0 -0 0 0 -0 0 0 -0 0 0 +136 59 35 +185 90 59 +210 184 61 +159 147 159 +223 218 223 +255 255 255 +255 0 0 +255 0 0 +255 0 0 +255 0 0 +255 0 0 diff --git a/graphics/pokemon/thievul/overworld_shiny.pal b/graphics/pokemon/thievul/overworld_shiny.pal index 6584b3d19e..f2d8cccbaf 100644 --- a/graphics/pokemon/thievul/overworld_shiny.pal +++ b/graphics/pokemon/thievul/overworld_shiny.pal @@ -1,19 +1,19 @@ JASC-PAL 0100 16 -238 255 0 -8 8 0 -8 41 115 -0 0 0 -115 106 98 -0 16 74 -164 148 139 -24 24 24 +128 196 156 +8 8 7 +56 76 139 +78 73 71 +92 92 92 +117 108 106 +159 148 145 +210 184 61 +159 147 159 +223 218 223 255 255 255 -213 189 57 -90 90 90 -180 180 180 -0 0 0 -0 0 0 -0 0 0 -0 0 0 +255 0 0 +255 0 0 +255 0 0 +255 0 0 +255 0 0 diff --git a/graphics/pokemon/thievul/shiny.pal b/graphics/pokemon/thievul/shiny.pal index a6c7735277..dce4bdc484 100644 --- a/graphics/pokemon/thievul/shiny.pal +++ b/graphics/pokemon/thievul/shiny.pal @@ -2,14 +2,14 @@ JASC-PAL 0100 16 152 208 160 -8 24 40 -16 40 64 +37 73 109 +14 62 109 16 16 16 88 80 80 40 40 32 168 160 152 -144 144 120 -128 120 112 +228 228 228 +175 180 191 216 216 200 216 136 0 184 184 168 diff --git a/graphics/pokenav/name_box.png b/graphics/pokenav/name_box.png new file mode 100644 index 0000000000..7c2ed7036b Binary files /dev/null and b/graphics/pokenav/name_box.png differ diff --git a/graphics/text_window/name_box.png b/graphics/text_window/name_box.png new file mode 100644 index 0000000000..735f39247e Binary files /dev/null and b/graphics/text_window/name_box.png differ diff --git a/include/apricorn_tree.h b/include/apricorn_tree.h new file mode 100644 index 0000000000..fc9e95b438 --- /dev/null +++ b/include/apricorn_tree.h @@ -0,0 +1,15 @@ +#ifndef GUARD_APRICORN_TREE_H +#define GUARD_APRICORN_TREE_H + +#include "constants/apricorn_tree.h" + +bool8 IsApricornTreePicked(u32 id); +void SetApricornTreePicked(u32 id); + +void DailyResetApricornTrees(void); +void ObjectEventInteractionGetApricornTreeData(void); +void ObjectEventInteractionPickApricornTree(void); +enum ApricornType GetApricornTypeByApricornTreeId(u32 id); +u8 GetApricornCountByApricornTreeId(u32 id); + +#endif //GUARD_APRICORN_TREE_H diff --git a/include/battle.h b/include/battle.h index 6c93e91d66..b95da58aa2 100755 --- a/include/battle.h +++ b/include/battle.h @@ -2,8 +2,12 @@ #define GUARD_BATTLE_H // should they be included here or included individually by every file? +#include "constants/battle_end_turn.h" +#include "constants/abilities.h" #include "constants/battle.h" #include "constants/form_change_types.h" +#include "constants/hold_effects.h" +#include "constants/moves.h" #include "battle_main.h" #include "battle_message.h" #include "battle_util.h" @@ -98,8 +102,7 @@ struct DisableStruct u8 battlerWithSureHit; u8 isFirstTurn; u8 mimickedMoves:4; - u8 chargeTimer:4; - u8 rechargeTimer; + u8 rechargeTimer:4; u8 autotomizeCount; u16 slowStartTimer; u16 embargoTimer; @@ -114,7 +117,6 @@ struct DisableStruct u8 usedMoves:4; u8 truantCounter:1; u8 truantSwitchInHack:1; - u8 noRetreat:1; u8 tarShot:1; u8 octolock:1; u8 cudChew:1; @@ -124,6 +126,7 @@ struct DisableStruct u8 usedProteanLibero:1; u8 flashFireBoosted:1; u8 boosterEnergyActivated:1; + u8 padding1:1; u16 overwrittenAbility; // abilities overwritten during battle (keep separate from battle history in case of switching) u8 roostActive:1; u8 unburdenActive:1; @@ -132,9 +135,10 @@ struct DisableStruct u8 unnerveActivated:1; // Unnerve and As One (Unnerve part) activate only once per switch in u8 hazardsDone:1; u8 endured:1; - u8 octolockedBy:3; u8 tryEjectPack:1; - u8 padding:4; + u8 octolockedBy:3; + u8 paradoxBoostedStat:4; + u8 padding2:1; }; // Fully Cleared each turn after end turn effects are done. A few things are cleared before end turn effects @@ -149,28 +153,26 @@ struct ProtectStruct u32 chargingTurn:1; u32 fleeType:2; // 0: Normal, 1: FLEE_ITEM, 2: FLEE_ABILITY u32 unableToUseMove:1; // Not to be confused with HITMARKER_UNABLE_TO_USE_MOVE (It is questionable though if there is a difference. Needs further research) - u32 notFirstStrike:1; + u32 laggingTail:1; u32 palaceUnableToUseMove:1; - u32 powderSelfDmg:1; u32 statRaised:1; u32 usedCustapBerry:1; // also quick claw u32 touchedProtectLike:1; u32 disableEjectPack:1; u32 pranksterElevated:1; u32 quickDraw:1; - u32 beakBlastCharge:1; u32 quash:1; u32 shellTrap:1; u32 eatMirrorHerb:1; u32 activateOpportunist:2; // 2 - to copy stats. 1 - stats copied (do not repeat). 0 - no stats to copy u16 usedAllySwitch:1; - // End of 32-bit bitfield - u32 helpingHand:3; u16 lashOutAffected:1; + // End of 32-bit bitfield + u16 helpingHand:3; u16 assuranceDoubled:1; u16 myceliumMight:1; - u16 laggingTail:1; - u16 padding:9; + u16 revengeDoubled:4; + u16 padding:7; // End of 16-bit bitfield u16 physicalDmg; u16 specialDmg; @@ -185,20 +187,20 @@ struct SpecialStatus s32 specialDmg; u8 changedStatsBattlerId; // Battler that was responsible for the latest stat change. Can be self. u8 statLowered:1; - u8 lightningRodRedirected:1; + u8 abilityRedirected:1; u8 restoredBattlerSprite: 1; u8 faintedHasReplacement:1; - u8 preventLifeOrbDamage:1; // So that Life Orb doesn't activate various effects. u8 afterYou:1; u8 enduredDamage:1; - u8 stormDrainRedirected:1; + u8 dancerUsedMove:1; + u8 padding1:1; // End of byte u8 switchInAbilityDone:1; u8 switchInItemDone:1; u8 instructedChosenTarget:3; u8 berryReduced:1; - u8 announceNeutralizingGas:1; // See Cmd_switchineffects u8 neutralizingGasRemoved:1; // See VARIOUS_TRY_END_NEUTRALIZING_GAS + u8 padding2:1; // End of byte u8 gemParam; // End of byte @@ -210,9 +212,8 @@ struct SpecialStatus u8 teraShellAbilityDone:1; u8 criticalHit:1; // End of byte - u8 dancerUsedMove:1; u8 dancerOriginalTarget:3; - u8 unused:4; + u8 padding3:5; // End of byte }; @@ -235,7 +236,7 @@ struct SideTimer u8 followmePowder:1; // Rage powder, does not affect grass type pokemon. u8 retaliateTimer; u16 damageNonTypesTimer; - u8 damageNonTypesType; + enum Type damageNonTypesType; u16 rainbowTimer; u16 seaOfFireTimer; u16 swampTimer; @@ -267,12 +268,12 @@ struct WishFutureKnock struct AI_SavedBattleMon { - u16 ability; + enum Ability ability; u16 moves[MAX_MON_MOVES]; u16 heldItem; u16 species:15; u16 saved:1; - u8 types[3]; + enum Type types[3]; }; struct AiPartyMon @@ -280,7 +281,7 @@ struct AiPartyMon u16 species; u16 item; u16 heldEffect; - u16 ability; + enum Ability ability; u16 level; u16 moves[MAX_MON_MOVES]; u32 status; @@ -313,7 +314,7 @@ struct SimulatedDamage // Ai Data used when deciding which move to use, computed only once before each turn's start. struct AiLogicData { - u16 abilities[MAX_BATTLERS_COUNT]; + enum Ability abilities[MAX_BATTLERS_COUNT]; u16 items[MAX_BATTLERS_COUNT]; u16 holdEffects[MAX_BATTLERS_COUNT]; u8 holdEffectParams[MAX_BATTLERS_COUNT]; @@ -357,7 +358,7 @@ struct AiThinkingStruct struct BattleHistory { - u16 abilities[MAX_BATTLERS_COUNT]; + enum Ability abilities[MAX_BATTLERS_COUNT]; u8 itemEffects[MAX_BATTLERS_COUNT]; u16 usedMoves[MAX_BATTLERS_COUNT][MAX_MON_MOVES]; u16 moveHistory[MAX_BATTLERS_COUNT][AI_MOVE_HISTORY_COUNT]; // 3 last used moves for each battler @@ -584,10 +585,11 @@ struct BattlerState u32 pursuitTarget:1; u32 stompingTantrumTimer:2; u32 canPickupItem:1; - u32 itemCanBeKnockedOff:1; u32 ateBoost:1; + u32 wasAboveHalfHp:1; // For Berserk, Emergency Exit, Wimp Out and Anger Shell. u32 commanderSpecies:11; - u32 padding:4; + u32 selectionScriptFinished:1; + u32 padding:3; // End of Word }; @@ -603,6 +605,23 @@ struct PartyState u32 changedSpecies:11; // For forms when multiple mons can change into the same pokemon. u32 sentOut:1; u32 padding:9; + u16 usedHeldItem; +}; + +struct EventStates +{ + enum EndTurnResolutionOrder endTurn:8; + u32 endTurnBlock:8; // FirstEventBlock, SecondEventBlock, ThirdEventBlock + enum BattlerId endTurnBattler:4; + u32 arenaTurn:8; + enum BattleSide battlerSide:4; + enum BattlerId moveEndBattler:4; + enum FirstTurnEventsStates beforeFristTurn:8; + enum FaintedActions faintedAction:8; + enum BattlerId faintedActionBattler:4; + enum MoveSuccessOrder atkCanceler:8; + enum BattleIntroStates battleIntro:8; + u32 padding:24; }; // Cleared at the beginning of the battle. Fields need to be cleared when needed manually otherwise. @@ -610,10 +629,7 @@ struct BattleStruct { struct BattlerState battlerState[MAX_BATTLERS_COUNT]; struct PartyState partyState[NUM_BATTLE_SIDES][PARTY_SIZE]; - u8 eventBlockCounter; - u8 turnEffectsBattlerId; - u8 endTurnEventsCounter; - u16 wrappedMove[MAX_BATTLERS_COUNT]; + struct EventStates eventState; u16 moveTarget[MAX_BATTLERS_COUNT]; u32 expShareExpValue; u32 expValue; @@ -625,18 +641,13 @@ struct BattleStruct u8 givenExpMons; // Bits for enemy party's pokemon that gave exp to player's party. u8 expSentInMons; // As bits for player party mons - not including exp share mons. u8 wildVictorySong; - u8 dynamicMoveType; - u8 wrappedBy[MAX_BATTLERS_COUNT]; + enum Type dynamicMoveType; u8 battlerPreventingSwitchout; u8 moneyMultiplier:6; u8 moneyMultiplierItem:1; u8 moneyMultiplierMove:1; u8 savedTurnActionNumber; - u8 eventsBeforeFirstTurnState; - u8 faintedActionsState; - u8 faintedActionsBattlerId; u8 scriptPartyIdx; // for printing the nickname - bool8 selectionScriptFinished[MAX_BATTLERS_COUNT]; u8 battlerPartyIndexes[MAX_BATTLERS_COUNT]; u8 monToSwitchIntoId[MAX_BATTLERS_COUNT]; u8 battlerPartyOrders[MAX_BATTLERS_COUNT][PARTY_SIZE / 2]; @@ -668,32 +679,26 @@ struct BattleStruct u8 multipleSwitchInState:2; u8 multipleSwitchInCursor:3; u8 sleepClauseNotBlocked:1; - u8 padding1:1; + u8 isSkyBattle:1; u8 multipleSwitchInSortedBattlers[MAX_BATTLERS_COUNT]; void (*savedCallback)(void); - u16 usedHeldItems[PARTY_SIZE][NUM_BATTLE_SIDES]; // For each party member and side. For harvest, recycle u16 chosenItem[MAX_BATTLERS_COUNT]; u16 choicedMove[MAX_BATTLERS_COUNT]; u16 changedItems[MAX_BATTLERS_COUNT]; u8 switchInBattlerCounter; - u8 arenaTurnCounter; - u8 turnSideTracker; u16 lastTakenMoveFrom[MAX_BATTLERS_COUNT][MAX_BATTLERS_COUNT]; // a 2-D array [target][attacker] union { struct LinkBattlerHeader linkBattlerHeader; struct BattleVideo battleVideo; } multiBuffer; - u8 startingStatus:6; // status to apply at battle start. defined in constants/battle.h - u8 startingStatusDone:1; - u8 terrainDone:1; - u8 overworldWeatherDone:1; + u8 startingStatus; // status to apply at battle start. defined in constants/battle.h u8 battlerKOAnimsRunning:3; - u8 isAtkCancelerForCalledMove:1; // Certain cases in atk canceler should only be checked once, when the original move is called, however others need to be checked the twice. u8 friskedAbility:1; // If identifies two mons, show the ability pop-up only once. u8 fickleBeamBoosted:1; u8 poisonPuppeteerConfusion:1; + u8 toxicChainPriority:1; // If Toxic Chain will trigger on target, all other non volatiles will be blocked + u8 moldBreakerActive:1; u16 startingStatusTimer; - u8 atkCancelerTracker; struct BattleTvMovePoints tvMovePoints; struct BattleTv tv; u8 AI_monToSwitchIntoId[MAX_BATTLERS_COUNT]; @@ -705,7 +710,6 @@ struct BattleStruct u8 debugBattler; u8 magnitudeBasePower; u8 presentBasePower; - u8 roostTypes[MAX_BATTLERS_COUNT][NUM_BATTLE_SIDES]; u8 savedBattlerTarget[5]; u8 savedBattlerAttacker[5]; u8 savedTargetCount:4; @@ -715,11 +719,9 @@ struct BattleStruct struct DynamaxData dynamax; struct BattleGimmickData gimmick; const u8 *trainerSlideMsg; - enum BattleIntroStates introState:8; u8 stolenStats[NUM_BATTLE_STATS]; // hp byte is used for which stats to raise, other inform about by how many stages u8 lastMoveTarget[MAX_BATTLERS_COUNT]; // The last target on which each mon used a move, for the sake of Instruct - u16 tracedAbility[MAX_BATTLERS_COUNT]; - u16 hpBefore[MAX_BATTLERS_COUNT]; // Hp of battlers before using a move. For Berserk and Anger Shell. + enum Ability tracedAbility[MAX_BATTLERS_COUNT]; struct Illusion illusion[MAX_BATTLERS_COUNT]; u8 soulheartBattlerId; u8 friskedBattler; // Frisk needs to identify 2 battlers in double battles. @@ -736,23 +738,19 @@ struct BattleStruct u8 throwingPokeBall:1; u8 ballSpriteIds[2]; // item gfx, window gfx u8 moveInfoSpriteId; // move info, window gfx - u8 appearedInBattle; // Bitfield to track which Pokemon appeared in battle. Used for Burmy's form change u8 skyDropTargets[MAX_BATTLERS_COUNT]; // For Sky Drop, to account for if multiple Pokemon use Sky Drop in a double battle. // When using a move which hits multiple opponents which is then bounced by a target, we need to make sure, the move hits both opponents, the one with bounce, and the one without. - u16 beatUpSpecies[PARTY_SIZE]; + u16 beatUpSpecies[PARTY_SIZE]; // Species for Gen5+ Beat Up, otherwise party indexes u8 attackerBeforeBounce:2; u8 beatUpSlot:3; u8 pledgeMove:1; u8 effectsBeforeUsingMoveDone:1; // Mega Evo and Focus Punch/Shell Trap effects. u8 spriteIgnore0Hp:1; - u8 bonusCritStages[MAX_BATTLERS_COUNT]; // G-Max Chi Strike boosts crit stages of allies. u8 itemPartyIndex[MAX_BATTLERS_COUNT]; u8 itemMoveIndex[MAX_BATTLERS_COUNT]; - u8 isSkyBattle:1; s32 aiDelayTimer; // Counts number of frames AI takes to choose an action. s32 aiDelayFrames; // Number of frames it took to choose an action. s32 aiDelayCycles; // Number of cycles it took to choose an action. - u8 stickySyrupdBy[MAX_BATTLERS_COUNT]; u8 supremeOverlordCounter[MAX_BATTLERS_COUNT]; u8 shellSideArmCategory[MAX_BATTLERS_COUNT][MAX_BATTLERS_COUNT]; u8 speedTieBreaks; // MAX_BATTLERS_COUNT! values. @@ -765,6 +763,7 @@ struct BattleStruct u8 pursuitStoredSwitch; // Stored id for the Pursuit target's switch s32 battlerExpReward; u16 prevTurnSpecies[MAX_BATTLERS_COUNT]; // Stores species the AI has in play at start of turn + s16 passiveHpUpdate[MAX_BATTLERS_COUNT]; // non-move damage and healing s16 moveDamage[MAX_BATTLERS_COUNT]; s16 critChance[MAX_BATTLERS_COUNT]; u16 moveResultFlags[MAX_BATTLERS_COUNT]; @@ -776,15 +775,19 @@ struct BattleStruct u8 printedStrongWindsWeakenedAttack:1; u8 numSpreadTargets:2; u8 noTargetPresent:1; - u8 cheekPouchActivated:1; - s16 savedcheekPouchDamage; // Cheek Pouch can happen in the middle of an attack execution so we need to store the current dmg + u8 padding2:1; struct MessageStatus slideMessageStatus; u8 trainerSlideSpriteIds[MAX_BATTLERS_COUNT]; u8 hazardsQueue[NUM_BATTLE_SIDES][HAZARDS_MAX_COUNT]; u8 numHazards[NUM_BATTLE_SIDES]; u8 hazardsCounter:4; // Counter for applying hazard on switch in + enum SubmoveState submoveAnnouncement:2; + u8 tryDestinyBond:1; + u8 tryGrudge:1; + u16 flingItem; u8 incrementEchoedVoice:1; u8 echoedVoiceCounter:3; + u8 padding3:4; }; struct AiBattleData @@ -828,7 +831,7 @@ static inline bool32 IsBattleMoveStatus(u32 move) * times with one type because it shares the 'GetBattlerTypes' result. */ #define _IS_BATTLER_ANY_TYPE(battler, ignoreTera, ...) \ ({ \ - u32 types[3]; \ + enum Type types[3]; \ GetBattlerTypes(battler, ignoreTera, types); \ RECURSIVELY(R_FOR_EACH(_IS_BATTLER_ANY_TYPE_HELPER, __VA_ARGS__)) FALSE; \ }) @@ -842,7 +845,7 @@ static inline bool32 IsBattleMoveStatus(u32 move) #define IS_BATTLER_TYPELESS(battlerId) \ ({ \ - u32 types[3]; \ + enum Type types[3]; \ GetBattlerTypes(battlerId, FALSE, types); \ types[0] == TYPE_MYSTERY && types[1] == TYPE_MYSTERY && types[2] == TYPE_MYSTERY; \ }) @@ -906,7 +909,7 @@ struct BattleScripting s32 savedDmg; u16 unused_0x2c; u16 moveEffect; - u16 multihitMoveEffect; + u16 unused_0x30; u8 illusionNickHack; // To properly display nick in STRINGID_ENEMYABOUTTOSWITCHPKMN. bool8 fixedPopup; // Force ability popup to stick until manually called back u16 abilityPopupOverwrite; @@ -1053,7 +1056,7 @@ extern u16 gChosenMove; extern u16 gCalledMove; extern s32 gBideDmg[MAX_BATTLERS_COUNT]; extern u16 gLastUsedItem; -extern u16 gLastUsedAbility; +extern enum Ability gLastUsedAbility; extern u8 gBattlerAttacker; extern u8 gBattlerTarget; extern u8 gBattlerFainted; @@ -1189,7 +1192,7 @@ static inline u32 GetBattlerSide(u32 battler) return GetBattlerPosition(battler) & BIT_SIDE; } -static inline u32 IsOnPlayerSide(u32 battler) +static inline bool32 IsOnPlayerSide(u32 battler) { return GetBattlerSide(battler) == B_SIDE_PLAYER; } @@ -1210,7 +1213,7 @@ static inline struct Pokemon* GetBattlerMon(u32 battler) return !IsOnPlayerSide(battler) ? &gEnemyParty[index] : &gPlayerParty[index]; } -static inline struct Pokemon *GetSideParty(u32 side) +static inline struct Pokemon *GetSideParty(enum BattleSide side) { return side == B_SIDE_PLAYER ? gPlayerParty : gEnemyParty; } @@ -1227,7 +1230,7 @@ static inline struct PartyState *GetBattlerPartyState(u32 battler) static inline bool32 IsDoubleBattle(void) { - return gBattleTypeFlags & BATTLE_TYPE_DOUBLE; + return (gBattleTypeFlags & BATTLE_TYPE_MORE_THAN_TWO_BATTLERS); } static inline bool32 IsSpreadMove(u32 moveTarget) @@ -1238,7 +1241,7 @@ static inline bool32 IsSpreadMove(u32 moveTarget) static inline bool32 IsDoubleSpreadMove(void) { return gBattleStruct->numSpreadTargets > 1 - && !(gHitMarker & (HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_HP_UPDATE | HITMARKER_UNABLE_TO_USE_MOVE)) + && !(gHitMarker & HITMARKER_UNABLE_TO_USE_MOVE) && IsSpreadMove(GetBattlerMoveTargetType(gBattlerAttacker, gCurrentMove)); } @@ -1254,4 +1257,18 @@ static inline u32 GetChosenMoveFromPosition(u32 battler) return gBattleMons[battler].moves[gBattleStruct->chosenMovePositions[battler]]; } +static inline void SetPassiveDamageAmount(u32 battler, s32 value) +{ + if (value == 0) + value = 1; + gBattleStruct->passiveHpUpdate[battler] = value; +} + +static inline void SetHealAmount(u32 battler, s32 value) +{ + if (value == 0) + value = 1; + gBattleStruct->passiveHpUpdate[battler] = -1 * value; +} + #endif // GUARD_BATTLE_H diff --git a/include/battle_ai_main.h b/include/battle_ai_main.h index b3bc57c4e9..4330f9d2bc 100644 --- a/include/battle_ai_main.h +++ b/include/battle_ai_main.h @@ -23,6 +23,11 @@ enum StatChange STAT_CHANGE_SPEED_2, STAT_CHANGE_SPATK_2, STAT_CHANGE_SPDEF_2, + STAT_CHANGE_ATK_3, + STAT_CHANGE_DEF_3, + STAT_CHANGE_SPEED_3, + STAT_CHANGE_SPATK_3, + STAT_CHANGE_SPDEF_3, STAT_CHANGE_ACC, STAT_CHANGE_EVASION }; diff --git a/include/battle_ai_script_commands.h b/include/battle_ai_script_commands.h deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/include/battle_ai_switch_items.h b/include/battle_ai_switch_items.h index b91d452097..7612d2084a 100644 --- a/include/battle_ai_switch_items.h +++ b/include/battle_ai_switch_items.h @@ -38,14 +38,15 @@ enum ShouldSwitchScenario enum SwitchType { SWITCH_AFTER_KO, - SWITCH_MID_BATTLE, + SWITCH_MID_BATTLE_FORCED, + SWITCH_MID_BATTLE_OPTIONAL, }; void GetAIPartyIndexes(u32 battlerId, s32 *firstId, s32 *lastId); void AI_TrySwitchOrUseItem(u32 battler); u32 GetMostSuitableMonToSwitchInto(u32 battler, enum SwitchType switchType); bool32 ShouldSwitch(u32 battler); -bool32 IsMonGrounded(u16 heldItemEffect, u32 ability, u8 type1, u8 type2); +bool32 IsMonGrounded(enum HoldEffect heldItemEffect, enum Ability ability, enum Type type1, enum Type type2); void ModifySwitchAfterMoveScoring(u32 battler); #endif // GUARD_BATTLE_AI_SWITCH_ITEMS_H diff --git a/include/battle_ai_util.h b/include/battle_ai_util.h index 46e1e2d7b7..2c87608935 100644 --- a/include/battle_ai_util.h +++ b/include/battle_ai_util.h @@ -4,8 +4,6 @@ #include "battle_ai_main.h" #include "battle_ai_field_statuses.h" -#define FOE(battler) ((BATTLE_OPPOSITE(battler)) & BIT_SIDE) - // Roll boundaries used by AI when scoring. Doesn't affect actual damage dealt. #define MAX_ROLL_PERCENTAGE DMG_ROLL_PERCENT_HI #define MIN_ROLL_PERCENTAGE DMG_ROLL_PERCENT_LO @@ -76,6 +74,7 @@ bool32 AI_IsSlower(u32 battlerAi, u32 battlerDef, u32 aiMove, u32 playerMove, en bool32 AI_IsPartyMonFaster(u32 battlerAi, u32 battlerDef, struct BattlePokemon switchinCandidate, u32 aiMove, u32 playerMove, enum ConsiderPriority considerPriority); bool32 AI_IsPartyMonSlower(u32 battlerAi, u32 battlerDef, struct BattlePokemon switchinCandidate, u32 aiMove, u32 playerMove, enum ConsiderPriority considerPriority); bool32 AI_RandLessThan(u32 val); +bool32 AI_IsBattlerGrounded(u32 battler); u32 AI_GetDamage(u32 battlerAtk, u32 battlerDef, u32 moveIndex, enum DamageCalcContext calcContext, struct AiLogicData *aiData); bool32 IsAiVsAiBattle(void); bool32 BattlerHasAi(u32 battlerId); @@ -88,9 +87,9 @@ void ClearBattlerMoveHistory(u32 battlerId); void RecordLastUsedMoveBy(u32 battlerId, u32 move); void RecordAllMoves(u32 battler); void RecordKnownMove(u32 battlerId, u32 move); -void RecordAbilityBattle(u32 battlerId, u32 abilityId); +void RecordAbilityBattle(u32 battlerId, enum Ability abilityId); void ClearBattlerAbilityHistory(u32 battlerId); -void RecordItemEffectBattle(u32 battlerId, u32 itemEffect); +void RecordItemEffectBattle(u32 battlerId, enum HoldEffect itemEffect); void ClearBattlerItemEffectHistory(u32 battlerId); void SaveBattlerData(u32 battlerId); void SetBattlerData(u32 battlerId); @@ -110,32 +109,35 @@ u32 GetBestDmgMoveFromBattler(u32 battlerAtk, u32 battlerDef, enum DamageCalcCon u32 GetBestDmgFromBattler(u32 battler, u32 battlerTarget, enum DamageCalcContext calcContext); bool32 CanTargetMoveFaintAi(u32 move, u32 battlerDef, u32 battlerAtk, u32 nHits); bool32 CanTargetFaintAiWithMod(u32 battlerDef, u32 battlerAtk, s32 hpMod, s32 dmgMod); -s32 AI_DecideKnownAbilityForTurn(u32 battlerId); -enum ItemHoldEffect AI_DecideHoldEffectForTurn(u32 battlerId); -bool32 DoesBattlerIgnoreAbilityChecks(u32 battlerAtk, u32 atkAbility, u32 move); +enum Ability AI_DecideKnownAbilityForTurn(u32 battlerId); +enum HoldEffect AI_DecideHoldEffectForTurn(u32 battlerId); +bool32 DoesBattlerIgnoreAbilityChecks(u32 battlerAtk, enum Ability atkAbility, u32 move); u32 AI_GetWeather(void); u32 AI_GetSwitchinWeather(struct BattlePokemon battleMon); enum WeatherState IsWeatherActive(u32 flags); bool32 CanAIFaintTarget(u32 battlerAtk, u32 battlerDef, u32 numHits); bool32 CanIndexMoveFaintTarget(u32 battlerAtk, u32 battlerDef, u32 index, enum DamageCalcContext calcContext); -bool32 HasDamagingMove(u32 battlerId); -bool32 HasDamagingMoveOfType(u32 battlerId, u32 type); +bool32 HasDamagingMove(u32 battler); +bool32 HasDamagingMoveOfType(u32 battler, enum Type type); u32 GetBattlerSecondaryDamage(u32 battlerId); -bool32 BattlerWillFaintFromWeather(u32 battler, u32 ability); -bool32 BattlerWillFaintFromSecondaryDamage(u32 battler, u32 ability); -bool32 ShouldTryOHKO(u32 battlerAtk, u32 battlerDef, u32 atkAbility, u32 defAbility, u32 move); +bool32 BattlerWillFaintFromWeather(u32 battler, enum Ability ability); +bool32 BattlerWillFaintFromSecondaryDamage(u32 battler, enum Ability ability); +bool32 ShouldTryOHKO(u32 battlerAtk, u32 battlerDef, enum Ability atkAbility, enum Ability defAbility, u32 move); bool32 ShouldUseRecoilMove(u32 battlerAtk, u32 battlerDef, u32 recoilDmg, u32 moveIndex); bool32 ShouldAbsorb(u32 battlerAtk, u32 battlerDef, u32 move, s32 damage); bool32 ShouldRecover(u32 battlerAtk, u32 battlerDef, u32 move, u32 healPercent); bool32 ShouldSetScreen(u32 battlerAtk, u32 battlerDef, enum BattleMoveEffects moveEffect); -enum AIPivot ShouldPivot(u32 battlerAtk, u32 battlerDef, u32 defAbility, u32 move, u32 moveIndex); +bool32 ShouldCureStatus(u32 battlerAtk, u32 battlerDef, struct AiLogicData *aiData); +bool32 ShouldCureStatusWithItem(u32 battlerAtk, u32 battlerDef, struct AiLogicData *aiData); +enum AIPivot ShouldPivot(u32 battlerAtk, u32 battlerDef, enum Ability defAbility, u32 move, u32 moveIndex); bool32 IsRecycleEncouragedItem(u32 item); bool32 ShouldRestoreHpBerry(u32 battlerAtk, u32 item); bool32 IsStatBoostingBerry(u32 item); bool32 CanKnockOffItem(u32 battler, u32 item); -bool32 IsAbilityOfRating(u32 ability, s8 rating); -bool32 AI_IsAbilityOnSide(u32 battlerId, u32 ability); -bool32 AI_MoveMakesContact(u32 ability, enum ItemHoldEffect holdEffect, u32 move); +bool32 IsAbilityOfRating(enum Ability ability, s8 rating); +bool32 AI_IsAbilityOnSide(u32 battlerId, enum Ability ability); +bool32 AI_MoveMakesContact(enum Ability ability, enum HoldEffect holdEffect, u32 move); +bool32 IsConsideringZMove(u32 battlerAtk, u32 battlerDef, u32 move); bool32 ShouldUseZMove(u32 battlerAtk, u32 battlerDef, u32 chosenMove); void SetAIUsingGimmick(u32 battler, enum AIConsiderGimmick use); bool32 IsAIUsingGimmick(u32 battler); @@ -144,13 +146,14 @@ bool32 CanEndureHit(u32 battler, u32 battlerTarget, u32 move); // stat stage checks bool32 AnyStatIsRaised(u32 battlerId); -bool32 CanLowerStat(u32 battlerAtk, u32 battlerDef, struct AiLogicData *aiData, u32 stat); -bool32 BattlerStatCanRise(u32 battler, u32 battlerAbility, u32 stat); +bool32 CanLowerStat(u32 battlerAtk, u32 battlerDef, struct AiLogicData *aiData, enum Stat stat); +bool32 BattlerStatCanRise(u32 battler, enum Ability battlerAbility, enum Stat stat); bool32 AreBattlersStatsMaxed(u32 battler); u32 CountPositiveStatStages(u32 battlerId); u32 CountNegativeStatStages(u32 battlerId); // move checks +bool32 Ai_IsPriorityBlocked(u32 battlerAtk, u32 battlerDef, u32 move, struct AiLogicData *aiData); bool32 MovesWithCategoryUnusable(u32 attacker, u32 target, enum DamageCategory category); enum MoveComparisonResult AI_WhichMoveBetter(u32 move1, u32 move2, u32 battlerAtk, u32 battlerDef, s32 noOfHitsToKo); struct SimulatedDamage AI_CalcDamageSaveBattlers(u32 move, u32 battlerAtk, u32 battlerDef, uq4_12_t *typeEffectiveness, enum AIConsiderGimmick considerGimmickAtk, enum AIConsiderGimmick considerGimmickDef); @@ -166,9 +169,10 @@ uq4_12_t AI_GetMoveEffectiveness(u32 move, u32 battlerAtk, u32 battlerDef); u16 *GetMovesArray(u32 battler); bool32 IsConfusionMoveEffect(enum BattleMoveEffects moveEffect); bool32 HasMove(u32 battlerId, u32 move); +u32 GetIndexInMoveArray(u32 battler, u32 move); bool32 HasOnlyMovesWithCategory(u32 battlerId, enum DamageCategory category, bool32 onlyOffensive); bool32 HasMoveWithCategory(u32 battler, enum DamageCategory category); -bool32 HasMoveWithType(u32 battler, u32 type); +bool32 HasMoveWithType(u32 battler, enum Type type); bool32 HasMoveWithEffect(u32 battler, enum BattleMoveEffects moveEffect); bool32 HasMoveWithAIEffect(u32 battler, u32 aiEffect); bool32 HasBattlerSideMoveWithEffect(u32 battler, u32 effect); @@ -181,15 +185,16 @@ bool32 HasBattlerSideMoveWithAdditionalEffect(u32 battler, u32 moveEffect); bool32 HasMoveWithCriticalHitChance(u32 battlerId); bool32 HasMoveWithMoveEffectExcept(u32 battlerId, u32 moveEffect, enum BattleMoveEffects exception); bool32 HasMoveThatLowersOwnStats(u32 battlerId); -bool32 HasMoveWithLowAccuracy(u32 battlerAtk, u32 battlerDef, u32 accCheck, bool32 ignoreStatus, u32 atkAbility, u32 defAbility, u32 atkHoldEffect, u32 defHoldEffect); +bool32 HasMoveWithLowAccuracy(u32 battlerAtk, u32 battlerDef, u32 accCheck, bool32 ignoreStatus); bool32 HasAnyKnownMove(u32 battlerId); bool32 IsAromaVeilProtectedEffect(enum BattleMoveEffects moveEffect); bool32 IsNonVolatileStatusMove(u32 moveEffect); -bool32 IsMoveRedirectionPrevented(u32 battlerAtk, u32 move, u32 atkAbility); +bool32 IsMoveRedirectionPrevented(u32 battlerAtk, u32 move, enum Ability atkAbility); bool32 IsHazardMove(u32 move); bool32 IsTwoTurnNotSemiInvulnerableMove(u32 battlerAtk, u32 move); bool32 IsBattlerDamagedByStatus(u32 battler); s32 ProtectChecks(u32 battlerAtk, u32 battlerDef, u32 move, u32 predictedMove); +bool32 ShouldRaiseAnyStat(u32 battlerAtk, u32 battlerDef); bool32 ShouldSetWeather(u32 battler, u32 weather); bool32 ShouldClearWeather(u32 battler, u32 weather); bool32 ShouldSetFieldStatus(u32 battler, u32 fieldStatus); @@ -215,38 +220,38 @@ bool32 IsHazardClearingMove(u32 move); bool32 IsSubstituteEffect(enum BattleMoveEffects effect); // status checks -bool32 AI_CanBeConfused(u32 battlerAtk, u32 battlerDef, u32 move, u32 ability); -bool32 IsBattlerIncapacitated(u32 battler, u32 ability); -bool32 AI_CanPutToSleep(u32 battlerAtk, u32 battlerDef, u32 defAbility, u32 move, u32 partnerMove); +bool32 AI_CanBeConfused(u32 battlerAtk, u32 battlerDef, u32 move, enum Ability ability); +bool32 IsBattlerIncapacitated(u32 battler, enum Ability ability); +bool32 AI_CanPutToSleep(u32 battlerAtk, u32 battlerDef, enum Ability defAbility, u32 move, u32 partnerMove); bool32 ShouldPoison(u32 battlerAtk, u32 battlerDef); -bool32 AI_CanPoison(u32 battlerAtk, u32 battlerDef, u32 defAbility, u32 move, u32 partnerMove); -bool32 AI_CanParalyze(u32 battlerAtk, u32 battlerDef, u32 defAbility, u32 move, u32 partnerMove); -bool32 AI_CanConfuse(u32 battlerAtk, u32 battlerDef, u32 defAbility, u32 battlerAtkPartner, u32 move, u32 partnerMove); -bool32 ShouldBurn(u32 battlerAtk, u32 battlerDef, u32 abilityDef); -bool32 ShouldFreezeOrFrostbite(u32 battlerAtk, u32 battlerDef, u32 abilityDef); -bool32 ShouldParalyze(u32 battlerAtk, u32 battlerDef, u32 abilityDef); -bool32 AI_CanBurn(u32 battlerAtk, u32 battlerDef, u32 defAbility, u32 battlerAtkPartner, u32 move, u32 partnerMove); -bool32 AI_CanGiveFrostbite(u32 battlerAtk, u32 battlerDef, u32 defAbility, u32 battlerAtkPartner, u32 move, u32 partnerMove); -bool32 AI_CanBeInfatuated(u32 battlerAtk, u32 battlerDef, u32 defAbility); +bool32 AI_CanPoison(u32 battlerAtk, u32 battlerDef, enum Ability defAbility, u32 move, u32 partnerMove); +bool32 AI_CanParalyze(u32 battlerAtk, u32 battlerDef, enum Ability defAbility, u32 move, u32 partnerMove); +bool32 AI_CanConfuse(u32 battlerAtk, u32 battlerDef, enum Ability defAbility, u32 battlerAtkPartner, u32 move, u32 partnerMove); +bool32 ShouldBurn(u32 battlerAtk, u32 battlerDef, enum Ability abilityDef); +bool32 ShouldFreezeOrFrostbite(u32 battlerAtk, u32 battlerDef, enum Ability abilityDef); +bool32 ShouldParalyze(u32 battlerAtk, u32 battlerDef, enum Ability abilityDef); +bool32 AI_CanBurn(u32 battlerAtk, u32 battlerDef, enum Ability defAbility, u32 battlerAtkPartner, u32 move, u32 partnerMove); +bool32 AI_CanGiveFrostbite(u32 battlerAtk, u32 battlerDef, enum Ability defAbility, u32 battlerAtkPartner, u32 move, u32 partnerMove); +bool32 AI_CanBeInfatuated(u32 battlerAtk, u32 battlerDef, enum Ability defAbility); bool32 AnyPartyMemberStatused(u32 battlerId, bool32 checkSoundproof); -u32 ShouldTryToFlinch(u32 battlerAtk, u32 battlerDef, u32 atkAbility, u32 defAbility, u32 move); +u32 ShouldTryToFlinch(u32 battlerAtk, u32 battlerDef, enum Ability atkAbility, enum Ability defAbility, u32 move); bool32 ShouldTrap(u32 battlerAtk, u32 battlerDef, u32 move); bool32 IsWakeupTurn(u32 battler); bool32 AI_IsBattlerAsleepOrComatose(u32 battlerId); // ability logic -bool32 IsMoxieTypeAbility(u32 ability); -bool32 DoesAbilityRaiseStatsWhenLowered(u32 ability); -bool32 ShouldTriggerAbility(u32 battlerAtk, u32 battlerDef, u32 ability); -bool32 CanEffectChangeAbility(u32 battlerAtk, u32 battlerDef, u32 effect, struct AiLogicData *aiData); -void AbilityChangeScore(u32 battlerAtk, u32 battlerDef, u32 effect, s32 *score, struct AiLogicData *aiData); -s32 BattlerBenefitsFromAbilityScore(u32 battler, u32 ability, struct AiLogicData *aiData); +bool32 IsMoxieTypeAbility(enum Ability ability); +bool32 DoesAbilityRaiseStatsWhenLowered(enum Ability ability); +bool32 ShouldTriggerAbility(u32 battlerAtk, u32 battlerDef, enum Ability ability); +bool32 CanEffectChangeAbility(u32 battlerAtk, u32 battlerDef, u32 move, struct AiLogicData *aiData); +void AbilityChangeScore(u32 battlerAtk, u32 battlerDef, u32 move, s32 *score, struct AiLogicData *aiData); +s32 BattlerBenefitsFromAbilityScore(u32 battler, enum Ability ability, struct AiLogicData *aiData); // partner logic bool32 IsTargetingPartner(u32 battlerAtk, u32 battlerDef); // IsTargetingPartner includes a check to make sure the adjacent pokemon is truly a partner. u32 GetAllyChosenMove(u32 battlerId); -bool32 IsBattle1v1(); +bool32 IsBattle1v1(void); // IsBattle1v1 is distinct from !IsDoubleBattle. If the player is fighting Maxie and Tabitha, with Steven as their partner, and both Tabitha and Steven have run out of Pokemon, the battle is 1v1, even though mechanically it is a Double Battle for how battlers and flags are set. // Most AI checks should be using IsBattle1v1; most engine checks should be using !IsDoubleBattle bool32 HasTwoOpponents(u32 battler); @@ -277,7 +282,7 @@ bool32 SideHasMoveCategory(u32 battlerId, enum DamageCategory category); // score increases u32 IncreaseStatUpScore(u32 battlerAtk, u32 battlerDef, enum StatChange statId); u32 IncreaseStatUpScoreContrary(u32 battlerAtk, u32 battlerDef, enum StatChange statId); -u32 IncreaseStatDownScore(u32 battlerAtk, u32 battlerDef, u32 stat); +u32 IncreaseStatDownScore(u32 battlerAtk, u32 battlerDef, enum Stat stat); void IncreasePoisonScore(u32 battlerAtk, u32 battlerDef, u32 move, s32 *score); void IncreaseBurnScore(u32 battlerAtk, u32 battlerDef, u32 move, s32 *score); void IncreaseParalyzeScore(u32 battlerAtk, u32 battlerDef, u32 move, s32 *score); @@ -285,7 +290,7 @@ void IncreaseSleepScore(u32 battlerAtk, u32 battlerDef, u32 move, s32 *score); void IncreaseConfusionScore(u32 battlerAtk, u32 battlerDef, u32 move, s32 *score); void IncreaseFrostbiteScore(u32 battlerAtk, u32 battlerDef, u32 move, s32 *score); -s32 AI_CalcPartyMonDamage(u32 move, u32 battlerAtk, u32 battlerDef, struct BattlePokemon switchinCandidate, enum DamageCalcContext calcContext); +s32 AI_CalcPartyMonDamage(u32 move, u32 battlerAtk, u32 battlerDef, struct BattlePokemon switchinCandidate, uq4_12_t *effectiveness, enum DamageCalcContext calcContext); u32 AI_WhoStrikesFirstPartyMon(u32 battlerAtk, u32 battlerDef, struct BattlePokemon switchinCandidate, u32 aiMoveConsidered, u32 playerMoveConsidered, enum ConsiderPriority ConsiderPriority); s32 AI_TryToClearStats(u32 battlerAtk, u32 battlerDef, bool32 isDoubleBattle); bool32 AI_ShouldCopyStatChanges(u32 battlerAtk, u32 battlerDef); @@ -297,8 +302,6 @@ bool32 IsBattlerItemEnabled(u32 battler); bool32 IsBattlerPredictedToSwitch(u32 battler); u32 GetIncomingMove(u32 battler, u32 opposingBattler, struct AiLogicData *aiData); u32 GetIncomingMoveSpeedCheck(u32 battler, u32 opposingBattler, struct AiLogicData *aiData); -bool32 HasLowAccuracyMove(u32 battlerAtk, u32 battlerDef); -bool32 HasBattlerSideAbility(u32 battlerDef, u32 ability, struct AiLogicData *aiData); bool32 IsNaturalEnemy(u32 speciesAttacker, u32 speciesTarget); // These are for the purpose of not doubling up on moves during double battles. @@ -308,7 +311,7 @@ bool32 IsNaturalEnemy(u32 speciesAttacker, u32 speciesTarget); #define AI_EFFECT_TERRAIN (1 << 1) #define AI_EFFECT_CLEAR_HAZARDS (1 << 2) #define AI_EFFECT_BREAK_SCREENS (1 << 3) -#define AI_EFFECT_RESET_STATS (1 << 4) +#define AI_EFFECT_RESET_STATS (1 << 4) #define AI_EFFECT_FORCE_SWITCH (1 << 5) #define AI_EFFECT_TORMENT (1 << 6) #define AI_EFFECT_LIGHT_SCREEN (1 << 7) diff --git a/include/battle_anim.h b/include/battle_anim.h index 7cef5445da..2c8631e899 100644 --- a/include/battle_anim.h +++ b/include/battle_anim.h @@ -211,7 +211,8 @@ u8 GetSubstituteSpriteDefault_Y(u8 battler); #define STAT_ANIM_MULTIPLE_MINUS1 57 #define STAT_ANIM_MULTIPLE_MINUS2 58 -enum { +enum StatAnimPal +{ STAT_ANIM_PAL_ATK, STAT_ANIM_PAL_DEF, STAT_ANIM_PAL_ACC, diff --git a/include/battle_anim_scripts.h b/include/battle_anim_scripts.h index 0bffbda8ea..febbfe9a2c 100644 --- a/include/battle_anim_scripts.h +++ b/include/battle_anim_scripts.h @@ -948,6 +948,7 @@ extern const u8 gBattleAnimStatus_Paralysis[]; extern const u8 gBattleAnimStatus_Freeze[]; extern const u8 gBattleAnimStatus_Curse[]; extern const u8 gBattleAnimStatus_Nightmare[]; +extern const u8 gBattleAnimStatus_Frostbite[]; // general animations extern const u8 gBattleAnimGeneral_StatsChange[]; @@ -1004,6 +1005,8 @@ extern const u8 gBattleAnimGeneral_TeraCharge[]; extern const u8 gBattleAnimGeneral_TeraActivate[]; extern const u8 gBattleAnimGeneral_SimpleHeal[]; extern const u8 gBattleAnimGeneral_PowerConstruct[]; +extern const u8 gBattleAnimGeneral_SwapToSubstitute[]; +extern const u8 gBattleAnimGeneral_SwapFromSubstitute[]; // special animations extern const u8 gBattleAnimSpecial_LevelUp[]; diff --git a/include/battle_controllers.h b/include/battle_controllers.h index 4728c17a84..c3b5fff97f 100644 --- a/include/battle_controllers.h +++ b/include/battle_controllers.h @@ -203,7 +203,7 @@ struct ChooseMoveStruct u8 currentPp[MAX_MON_MOVES]; u8 maxPp[MAX_MON_MOVES]; u16 species; - u8 monTypes[3]; + enum Type monTypes[3]; struct ZMoveData zmove; }; @@ -364,7 +364,7 @@ void BtlController_HandleSpriteInvisibility(u32 battler); bool32 TwoPlayerIntroMons(u32 battlerId); // Double battle with both player pokemon active. bool32 TwoOpponentIntroMons(u32 battlerId); // Double battle with both opponent pokemon active. void BtlController_HandleIntroTrainerBallThrow(u32 battler, u16 tagTrainerPal, const u16 *trainerPal, s16 framesToWait, void (*controllerCallback)(u32 battler)); -void BtlController_HandleDrawPartyStatusSummary(u32 battler, u32 side, bool32 considerDelay); +void BtlController_HandleDrawPartyStatusSummary(u32 battler, enum BattleSide side, bool32 considerDelay); void BtlController_HandleHidePartyStatusSummary(u32 battler); void BtlController_HandleBattleAnimation(u32 battler); @@ -395,6 +395,10 @@ void HandleChooseMoveAfterDma3(u32 battler); void SetControllerToRecordedPlayer(u32 battler); void RecordedPlayerBufferExecCompleted(u32 battler); +// recorded partner controller +void SetControllerToRecordedPartner(u32 battler); +void RecordedPartnerBufferExecCompleted(u32 battler); + // opponent controller void SetControllerToOpponent(u32 battler); void OpponentBufferExecCompleted(u32 battler); @@ -437,4 +441,7 @@ void BtlController_HandleSwitchInTryShinyAnim(u32 battler); void BtlController_HandleSwitchInSoundAndEnd(u32 battler); void BtlController_HandleSwitchInShowSubstitute(u32 battler); +bool32 ShouldBattleRestrictionsApply(u32 battler); +void FreeShinyStars(void); + #endif // GUARD_BATTLE_CONTROLLERS_H diff --git a/include/battle_dynamax.h b/include/battle_dynamax.h index ed295bb1e6..d9fa48706d 100644 --- a/include/battle_dynamax.h +++ b/include/battle_dynamax.h @@ -5,18 +5,17 @@ bool32 CanDynamax(u32 battler); bool32 IsGigantamaxed(u32 battler); -void ApplyDynamaxHPMultiplier(struct Pokemon* mon); +void ApplyDynamaxHPMultiplier(struct Pokemon *mon); void ActivateDynamax(u32 battler); u16 GetNonDynamaxHP(u32 battler); u16 GetNonDynamaxMaxHP(u32 battler); void UndoDynamax(u32 battler); bool32 IsMoveBlockedByMaxGuard(u32 move); -bool32 IsMoveBlockedByDynamax(u32 move); u16 GetMaxMove(u32 battler, u32 baseMove); u32 GetMaxMovePower(u32 move); bool32 IsMaxMove(u32 move); -void ChooseDamageNonTypesString(u8 type); +void ChooseDamageNonTypesString(enum Type type); void BS_UpdateDynamax(void); void BS_SetSteelsurge(void); diff --git a/include/battle_environment.h b/include/battle_environment.h index e9435aa454..f4870f795c 100644 --- a/include/battle_environment.h +++ b/include/battle_environment.h @@ -4,11 +4,11 @@ #include "constants/battle.h" #include "battle_bg.h" -struct BattleEnvironment { - u8 name[26]; +struct BattleEnvironment +{ u16 naturePower; u16 secretPowerEffect; - u8 camouflageType; + enum Type camouflageType; struct BattleBackground background; }; diff --git a/include/battle_hold_effects.h b/include/battle_hold_effects.h new file mode 100644 index 0000000000..51e63ea20a --- /dev/null +++ b/include/battle_hold_effects.h @@ -0,0 +1,52 @@ +#ifndef GUARD_BATTLE_HOLD_EFFECTS +#define GUARD_BATTLE_HOLD_EFFECTS + +struct HoldEffectInfo +{ + u32 onSwitchIn:1; + u32 onSwitchInFirstTurn:1; + u32 mirrorHerb:1; + u32 mirrorHerbFirstTurn:1; + u32 whiteHerb:1; + u32 whiteHerbFirstTurn:1; + u32 whiteHerbEndTurn:1; + u32 onStatusChange:1; + u32 onHpThreshold:1; + u32 keeMarangaBerry:1; + u32 MentalHerb:1; + u32 onTargetAfterHit:1; + u32 onAttackerAfterHit:1; + u32 lifeOrbShellBell:1; + u32 leftovers:1; + u32 orbs:1; + u32 onEffect:1; + u32 onFling:1; + u32 padding:14; +}; + +extern const struct HoldEffectInfo gHoldEffectsInfo[]; + +typedef bool32 (*ActivationTiming)(enum HoldEffect holdEffect); +enum ItemEffect ItemBattleEffects(u32 primaryBattler, u32 secondaryBattler, enum HoldEffect holdEffect, ActivationTiming timing); + +bool32 IsOnSwitchInActivation(enum HoldEffect holdEffect); +bool32 IsOnSwitchInFirstTurnActivation(enum HoldEffect holdEffect); +bool32 IsMirrorHerbActivation(enum HoldEffect holdEffect); +bool32 IsMirrorHerbFirstTurnActivation(enum HoldEffect holdEffect); +bool32 IsWhiteHerbActivation(enum HoldEffect holdEffect); +bool32 IsWhiteHerbFirstTurnActivation(enum HoldEffect holdEffect); +bool32 IsWhiteHerbEndTurnActivation(enum HoldEffect holdEffect); +bool32 IsOnStatusChangeActivation(enum HoldEffect holdEffect); +bool32 IsOnHpThresholdActivation(enum HoldEffect holdEffect); +bool32 IsKeeMarangaBerryActivation(enum HoldEffect holdEffect); +bool32 IsOnTargetHitActivation(enum HoldEffect holdEffect); +bool32 IsOnAttackerAfterHitActivation(enum HoldEffect holdEffect); +bool32 IsLifeOrbShellBellActivation(enum HoldEffect holdEffect); +bool32 IsLeftoversActivation(enum HoldEffect holdEffect); +bool32 IsOrbsActivation(enum HoldEffect holdEffect); +bool32 IsOnEffectActivation(enum HoldEffect holdEffect); +bool32 IsForceTriggerItemActivation(enum HoldEffect holdEffect); +bool32 IsOnBerryActivation(enum HoldEffect holdEffect); +bool32 IsOnFlingActivation(enum HoldEffect holdEffect); + +#endif // GUARD_BATTLE_HOLD_EFFECTS diff --git a/include/battle_interface.h b/include/battle_interface.h index 5bc1e10aa7..ea5559d165 100644 --- a/include/battle_interface.h +++ b/include/battle_interface.h @@ -126,7 +126,7 @@ void UpdateHealthboxAttribute(u8 healthboxSpriteId, struct Pokemon *mon, u8 elem s32 MoveBattleBar(u8 battler, u8 healthboxSpriteId, u8 whichBar, u8 unused); u8 GetScaledHPFraction(s16 hp, s16 maxhp, u8 scale); u8 GetHPBarLevel(s16 hp, s16 maxhp); -void CreateAbilityPopUp(u8 battlerId, u32 ability, bool32 isDoubleBattle); +void CreateAbilityPopUp(u8 battlerId, enum Ability ability, bool32 isDoubleBattle); void DestroyAbilityPopUp(u8 battlerId); bool32 CanThrowLastUsedBall(void); void TryHideLastUsedBall(void); diff --git a/include/battle_main.h b/include/battle_main.h index bf8e88fc5d..c08da1d9ca 100644 --- a/include/battle_main.h +++ b/include/battle_main.h @@ -1,6 +1,7 @@ #ifndef GUARD_BATTLE_MAIN_H #define GUARD_BATTLE_MAIN_H +#include "battle_util.h" #include "pokemon.h" #include "data.h" #include "constants/hold_effects.h" @@ -57,9 +58,10 @@ enum FirstTurnEventsStates FIRST_TURN_EVENTS_TOTEM_BOOST, FIRST_TURN_EVENTS_NEUTRALIZING_GAS, FIRST_TURN_EVENTS_SWITCH_IN_ABILITIES, - FIRST_TURN_EVENTS_OPPORTUNIST_1, FIRST_TURN_EVENTS_ITEM_EFFECTS, - FIRST_TURN_EVENTS_OPPORTUNIST_2, + FIRST_TURN_EVENTS_WHITE_HERB, + FIRST_TURN_EVENTS_OPPORTUNIST, + FIRST_TURN_EVENTS_MIRROR_HERB, FIRST_TURN_EVENTS_EJECT_PACK, FIRST_TURN_EVENTS_END, }; @@ -96,18 +98,15 @@ u8 IsRunningFromBattleImpossible(u32 battler); void SwitchTwoBattlersInParty(u32 battler, u32 battler2); void SwitchPartyOrder(u32 battler); void SwapTurnOrder(u8 id1, u8 id2); -u32 GetBattlerTotalSpeedStatArgs(u32 battler, u32 ability, enum ItemHoldEffect holdEffect); -u32 GetBattlerTotalSpeedStat(u32 battler); -s32 GetChosenMovePriority(u32 battler, u32 ability); -s32 GetBattleMovePriority(u32 battler, u32 ability, u32 move); -s32 GetWhichBattlerFasterArgs(u32 battler1, u32 battler2, bool32 ignoreChosenMoves, u32 ability1, u32 ability2, - enum ItemHoldEffect holdEffectBattler1, enum ItemHoldEffect holdEffectBattler2, u32 speedBattler1, u32 speedBattler2, s32 priority1, s32 priority2); -s32 GetWhichBattlerFasterOrTies(u32 battler1, u32 battler2, bool32 ignoreChosenMoves); -s32 GetWhichBattlerFaster(u32 battler1, u32 battler2, bool32 ignoreChosenMoves); +u32 GetBattlerTotalSpeedStat(u32 battler, enum Ability ability, enum HoldEffect holdEffect); +s32 GetChosenMovePriority(u32 battler, enum Ability ability); +s32 GetBattleMovePriority(u32 battler, enum Ability ability, u32 move); +s32 GetWhichBattlerFasterArgs(struct BattleContext *ctx, bool32 ignoreChosenMoves, u32 speedBattler1, u32 speedBattler2, s32 priority1, s32 priority2); +s32 GetWhichBattlerFasterOrTies(struct BattleContext *ctx, bool32 ignoreChosenMoves); +s32 GetWhichBattlerFaster(struct BattleContext *ctx, bool32 ignoreChosenMoves); void RunBattleScriptCommands_PopCallbacksStack(void); void RunBattleScriptCommands(void); -void SpecialStatusesClear(void); -u32 GetDynamicMoveType(struct Pokemon *mon, u32 move, u32 battler, enum MonState monInBattle); +enum Type GetDynamicMoveType(struct Pokemon *mon, u32 move, u32 battler, enum MonState monInBattle); void SetTypeBeforeUsingMove(u32 move, u32 battlerAtk); bool32 IsWildMonSmart(void); u8 CreateNPCTrainerPartyFromTrainer(struct Pokemon *party, const struct Trainer *trainer, bool32 firstTrainer, u32 battleTypeFlags); diff --git a/include/battle_message.h b/include/battle_message.h index 28be583551..9809589243 100644 --- a/include/battle_message.h +++ b/include/battle_message.h @@ -1,6 +1,7 @@ #ifndef GUARD_BATTLE_MESSAGE_H #define GUARD_BATTLE_MESSAGE_H +#include "constants/abilities.h" #include "constants/battle.h" #include "constants/battle_string_ids.h" @@ -238,13 +239,13 @@ struct BattleMsgData u16 currentMove; u16 originallyUsedMove; u16 lastItem; - u16 lastAbility; + enum Ability lastAbility; u8 scrActive; u8 bakScriptPartyIdx; u8 hpScale; u8 itemEffectBattler; - u8 moveType; - u16 abilities[MAX_BATTLERS_COUNT]; + enum Type moveType; + enum Ability abilities[MAX_BATTLERS_COUNT]; u8 textBuffs[3][TEXT_BUFF_ARRAY_COUNT]; }; @@ -334,5 +335,6 @@ extern const u8 gText_BattleTourney[]; extern const u16 gMissStringIds[]; extern const u16 gStatUpStringIds[]; +extern const u16 gStatDownStringIds[]; #endif // GUARD_BATTLE_MESSAGE_H diff --git a/include/battle_script_commands.h b/include/battle_script_commands.h index 4ba801b98c..d011b50947 100644 --- a/include/battle_script_commands.h +++ b/include/battle_script_commands.h @@ -40,16 +40,15 @@ union TRANSPARENT StatChangeFlags }; }; -s32 CalcCritChanceStage(u32 battlerAtk, u32 battlerDef, u32 move, bool32 recordAbility, u32 abilityAtk, u32 abilityDef, enum ItemHoldEffect holdEffectAtk); -s32 CalcCritChanceStageGen1(u32 battlerAtk, u32 battlerDef, u32 move, bool32 recordAbility, u32 abilityAtk, u32 abilityDef, enum ItemHoldEffect holdEffectAtk); +s32 CalcCritChanceStage(u32 battlerAtk, u32 battlerDef, u32 move, bool32 recordAbility, enum Ability abilityAtk, enum Ability abilityDef, enum HoldEffect holdEffectAtk); +s32 CalcCritChanceStageGen1(u32 battlerAtk, u32 battlerDef, u32 move, bool32 recordAbility, enum Ability abilityAtk, enum Ability abilityDef, enum HoldEffect holdEffectAtk); s32 GetCritHitOdds(s32 critChanceIndex); -u32 GetTotalAccuracy(u32 battlerAtk, u32 battlerDef, u32 move, u32 atkAbility, u32 defAbility, u32 atkHoldEffect, u32 defHoldEffect); bool32 HasBattlerActedThisTurn(u32 battler); u32 GetBattlerTurnOrderNum(u32 battler); bool32 NoAliveMonsForBattlerSide(u32 battler); bool32 NoAliveMonsForPlayer(void); bool32 NoAliveMonsForEitherParty(void); -void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certain); +void SetMoveEffect(u32 battler, u32 effectBattler, enum MoveEffect moveEffect, const u8 *battleScript, enum SetMoveEffectFlags effectFlags); bool32 CanBattlerSwitch(u32 battlerId); void BattleDestroyYesNoCursorAt(u8 cursorPosition); void BattleCreateYesNoCursorAt(u8 cursorPosition); @@ -60,16 +59,14 @@ bool32 DoesSubstituteBlockMove(u32 battlerAtk, u32 battlerDef, u32 move); bool32 DoesDisguiseBlockMove(u32 battler, u32 move); bool32 CanUseLastResort(u8 battlerId); u32 IsFlowerVeilProtected(u32 battler); -u32 IsLeafGuardProtected(u32 battler, u32 ability); -bool32 IsShieldsDownProtected(u32 battler, u32 ability); -u32 IsAbilityStatusProtected(u32 battler, u32 ability); +u32 IsLeafGuardProtected(u32 battler, enum Ability ability); +bool32 IsShieldsDownProtected(u32 battler, enum Ability ability); +u32 IsAbilityStatusProtected(u32 battler, enum Ability ability); bool32 TryResetBattlerStatChanges(u8 battler); bool32 CanCamouflage(u8 battlerId); -u32 GetNaturePowerMove(u32 battler); void StealTargetItem(u8 battlerStealer, u8 battlerItem); u8 GetCatchingBattler(void); -u32 GetHighestStatId(u32 battlerId); -bool32 ProteanTryChangeType(u32 battler, u32 ability, u32 move, u32 moveType); +bool32 ProteanTryChangeType(u32 battler, enum Ability ability, u32 move, enum Type moveType); bool32 IsMoveNotAllowedInSkyBattles(u32 move); bool32 DoSwitchInAbilities(u32 battlerId); u8 GetFirstFaintedPartyIndex(u8 battlerId); @@ -77,6 +74,7 @@ bool32 IsMoveAffectedByParentalBond(u32 move, u32 battler); void SaveBattlerTarget(u32 battler); void SaveBattlerAttacker(u32 battler); bool32 CanBurnHitThaw(u16 move); +bool32 EmergencyExitCanBeTriggered(u32 battler); extern void (*const gBattleScriptingCommandsTable[])(void); extern const struct StatFractions gAccuracyStageRatios[]; diff --git a/include/battle_scripts.h b/include/battle_scripts.h index 16a07e971a..e2f9f1636c 100644 --- a/include/battle_scripts.h +++ b/include/battle_scripts.h @@ -3,17 +3,18 @@ extern const u8 BattleScript_SupersweetSyrupActivates[]; extern const u8 BattleScript_OpportunistCopyStatChange[]; +extern const u8 BattleScript_OpportunistCopyStatChangeEnd3[]; extern const u8 BattleScript_MirrorHerbCopyStatChange[]; extern const u8 BattleScript_MirrorHerbCopyStatChangeEnd2[]; extern const u8 BattleScript_NotAffected[]; extern const u8 BattleScript_HitFromCritCalc[]; extern const u8 BattleScript_MoveEnd[]; extern const u8 BattleScript_MakeMoveMissed[]; -extern const u8 BattleScript_PrintMoveMissed[]; +extern const u8 BattleScript_MoveMissedPause[]; extern const u8 BattleScript_MoveMissedPause[]; extern const u8 BattleScript_MoveMissed[]; extern const u8 BattleScript_FlingFailConsumeItem[]; -extern const u8 BattleScript_FailedFromAtkString[]; +extern const u8 BattleScript_FlingBlockedByShieldDust[]; extern const u8 BattleScript_FailedFromAtkCanceler[]; extern const u8 BattleScript_ButItFailed[]; extern const u8 BattleScript_StatUp[]; @@ -21,8 +22,7 @@ extern const u8 BattleScript_StatDown[]; extern const u8 BattleScript_AlreadyAtFullHp[]; extern const u8 BattleScript_PresentHealTarget[]; extern const u8 BattleScript_MoveUsedMustRecharge[]; -extern const u8 BattleScript_FaintAttacker[]; -extern const u8 BattleScript_FaintTarget[]; +extern const u8 BattleScript_FaintBattler[]; extern const u8 BattleScript_GiveExp[]; extern const u8 BattleScript_HandleFaintedMon[]; extern const u8 BattleScript_LocalTrainerBattleWon[]; @@ -168,7 +168,6 @@ extern const u8 BattleScript_DoRecoil33[]; extern const u8 BattleScript_Recoil33End[]; extern const u8 BattleScript_ItemSteal[]; extern const u8 BattleScript_DrizzleActivates[]; -extern const u8 BattleScript_SpeedBoostActivates[]; extern const u8 BattleScript_TraceActivates[]; extern const u8 BattleScript_RainDishActivates[]; extern const u8 BattleScript_SandstreamActivates[]; @@ -180,11 +179,8 @@ extern const u8 BattleScript_DroughtActivates[]; extern const u8 BattleScript_TookAttack[]; extern const u8 BattleScript_SturdyPreventsOHKO[]; extern const u8 BattleScript_DampStopsExplosion[]; -extern const u8 BattleScript_MoveHPDrain_PPLoss[]; extern const u8 BattleScript_MoveHPDrain[]; -extern const u8 BattleScript_MonMadeMoveUseless_PPLoss[]; extern const u8 BattleScript_MonMadeMoveUseless[]; -extern const u8 BattleScript_FlashFireBoost_PPLoss[]; extern const u8 BattleScript_FlashFireBoost[]; extern const u8 BattleScript_AbilityNoStatLoss[]; extern const u8 BattleScript_ItemNoStatLoss[]; @@ -195,6 +191,7 @@ extern const u8 BattleScript_OwnTempoPrevents[]; extern const u8 BattleScript_SoundproofProtected[]; extern const u8 BattleScript_AbilityNoSpecificStatLoss[]; extern const u8 BattleScript_StickyHoldActivates[]; +extern const u8 BattleScript_StickyHoldActivatesRet[]; extern const u8 BattleScript_ColorChangeActivates[]; extern const u8 BattleScript_RoughSkinActivates[]; extern const u8 BattleScript_CuteCharmActivates[]; @@ -210,22 +207,10 @@ extern const u8 BattleScript_TruantLoafingAround[]; extern const u8 BattleScript_IgnoresAndFallsAsleep[]; extern const u8 BattleScript_IgnoresAndHitsItself[]; extern const u8 BattleScript_SubstituteFade[]; -extern const u8 BattleScript_BerryCurePrlzEnd2[]; -extern const u8 BattleScript_BerryCureParRet[]; -extern const u8 BattleScript_BerryCurePsnEnd2[]; -extern const u8 BattleScript_BerryCurePsnRet[]; -extern const u8 BattleScript_BerryCureBrnEnd2[]; -extern const u8 BattleScript_BerryCureBrnRet[]; -extern const u8 BattleScript_BerryCureFrzEnd2[]; -extern const u8 BattleScript_BerryCureFrzRet[]; -extern const u8 BattleScript_BerryCureFrbEnd2[]; -extern const u8 BattleScript_BerryCureFrbRet[]; -extern const u8 BattleScript_BerryCureSlpEnd2[]; -extern const u8 BattleScript_BerryCureSlpRet[]; +extern const u8 BattleScript_BerryCureStatusEnd2[]; +extern const u8 BattleScript_BerryCureStatusRet[]; extern const u8 BattleScript_BerryCureConfusionEnd2[]; extern const u8 BattleScript_BerryCureConfusionRet[]; -extern const u8 BattleScript_BerryCureChosenStatusEnd2[]; -extern const u8 BattleScript_BerryCureChosenStatusRet[]; extern const u8 BattleScript_WhiteHerbEnd2[]; extern const u8 BattleScript_WhiteHerbRet[]; extern const u8 BattleScript_ItemHealHP_RemoveItemRet[]; @@ -280,10 +265,10 @@ extern const u8 BattleScript_WaterSportEnds[]; extern const u8 BattleScript_SturdiedMsg[]; extern const u8 BattleScript_GravityEnds[]; extern const u8 BattleScript_MoveStatDrain[]; -extern const u8 BattleScript_MoveStatDrain_PPLoss[]; extern const u8 BattleScript_TargetsStatWasMaxedOut[]; extern const u8 BattleScript_AttackerAbilityStatRaise[]; extern const u8 BattleScript_AttackerAbilityStatRaiseEnd3[]; +extern const u8 BattleScript_AttackerAbilityStatRaiseEnd2[]; extern const u8 BattleScript_PoisonHealActivates[]; extern const u8 BattleScript_BadDreamsActivates[]; extern const u8 BattleScript_SwitchInAbilityMsg[]; @@ -329,7 +314,6 @@ extern const u8 BattleScript_ProteanActivates[]; extern const u8 BattleScript_DazzlingProtected[]; extern const u8 BattleScript_MoveUsedPsychicTerrainPrevents[]; extern const u8 BattleScript_MoveUsedPowder[]; -extern const u8 BattleScript_ZMoveActivatePowder[]; extern const u8 BattleScript_SelectingNotAllowedStuffCheeks[]; extern const u8 BattleScript_SelectingNotAllowedStuffCheeksInPalace[]; extern const u8 BattleScript_SelectingNotAllowedBelch[]; @@ -340,7 +324,6 @@ extern const u8 BattleScript_MistySurgeActivates[]; extern const u8 BattleScript_ElectricSurgeActivates[]; extern const u8 BattleScript_EffectSpectralThief[]; extern const u8 BattleScript_EffectLifeDew[]; -extern const u8 BattleScript_EffectSteelRoller[]; extern const u8 BattleScript_AbilityRaisesDefenderStat[]; extern const u8 BattleScript_PowderMoveNoEffect[]; extern const u8 BattleScript_GrassyTerrainHeals[]; @@ -361,8 +344,9 @@ extern const u8 BattleScript_WeaknessPolicy[]; extern const u8 BattleScript_TargetItemStatRaise[]; extern const u8 BattleScript_RockyHelmetActivates[]; extern const u8 BattleScript_ItemHurtEnd2[]; -extern const u8 BattleScript_AirBaloonMsgIn[]; -extern const u8 BattleScript_AirBaloonMsgPop[]; +extern const u8 BattleScript_AirBalloonMsgIn[]; +extern const u8 BattleScript_AirBalloonMsgInRet[]; +extern const u8 BattleScript_AirBalloonMsgPop[]; extern const u8 BattleScript_ItemHurtRet[]; extern const u8 BattleScript_ToxicOrb[]; extern const u8 BattleScript_FlameOrb[]; @@ -374,6 +358,7 @@ extern const u8 BattleScript_IllusionOffAndTerastallization[]; extern const u8 BattleScript_DancerActivates[]; extern const u8 BattleScript_AftermathDmg[]; extern const u8 BattleScript_BattlerFormChange[]; +extern const u8 BattleScript_BattlerFormChangeEnd2[]; extern const u8 BattleScript_BattlerFormChangeEnd3[]; extern const u8 BattleScript_AttackerFormChangeWithString[]; extern const u8 BattleScript_BattlerFormChangeWithStringEnd3[]; @@ -468,6 +453,7 @@ extern const u8 BattleScript_RemoveFireType[]; extern const u8 BattleScript_TargetAbilityStatRaiseRet[]; extern const u8 BattleScript_RemoveElectricType[]; extern const u8 BattleScript_SeedSowerActivates[]; +extern const u8 BattleScript_BerserkActivates[]; extern const u8 BattleScript_AngerShellActivates[]; extern const u8 BattleScript_WellBakedBodyActivates[]; extern const u8 BattleScript_WindRiderActivatesMoveEnd[]; @@ -583,7 +569,6 @@ extern const u8 BattleScript_EffectAbsorb[]; extern const u8 BattleScript_EffectAbsorbLiquidOoze[]; extern const u8 BattleScript_EffectExplosion[]; extern const u8 BattleScript_EffectDreamEater[]; -extern const u8 BattleScript_EffectMirrorMove[]; extern const u8 BattleScript_EffectAttackUp[]; extern const u8 BattleScript_EffectDefenseUp[]; extern const u8 BattleScript_EffectSpeedUp[]; @@ -607,6 +592,8 @@ extern const u8 BattleScript_EffectConversion[]; extern const u8 BattleScript_EffectRestoreHp[]; extern const u8 BattleScript_EffectLightScreen[]; extern const u8 BattleScript_EffectRest[]; +extern const u8 BattleScript_RestIsAlreadyAsleep[]; +extern const u8 BattleScript_InsomniaProtects[]; extern const u8 BattleScript_EffectOHKO[]; extern const u8 BattleScript_EffectHealBlock[]; extern const u8 BattleScript_RecoilIfMiss[]; @@ -633,7 +620,6 @@ extern const u8 BattleScript_EffectTwoTurnsAttack[]; extern const u8 BattleScript_EffectSubstitute[]; extern const u8 BattleScript_EffectRage[]; extern const u8 BattleScript_EffectMimic[]; -extern const u8 BattleScript_EffectMetronome[]; extern const u8 BattleScript_EffectLeechSeed[]; extern const u8 BattleScript_EffectDoNothing[]; extern const u8 BattleScript_EffectHoldHands[]; @@ -647,7 +633,6 @@ extern const u8 BattleScript_EffectSnore[]; extern const u8 BattleScript_EffectConversion2[]; extern const u8 BattleScript_EffectLockOn[]; extern const u8 BattleScript_EffectSketch[]; -extern const u8 BattleScript_EffectSleepTalk[]; extern const u8 BattleScript_EffectDestinyBond[]; extern const u8 BattleScript_EffectSpite[]; extern const u8 BattleScript_EffectHealBell[]; @@ -689,12 +674,10 @@ extern const u8 BattleScript_EffectBeatUp[]; extern const u8 BattleScript_EffectSemiInvulnerable[]; extern const u8 BattleScript_EffectDefenseCurl[]; extern const u8 BattleScript_EffectSoftboiled[]; -extern const u8 BattleScript_EffectFirstTurnOnly[]; -extern const u8 BattleScript_EffectUproar[]; extern const u8 BattleScript_EffectStockpile[]; extern const u8 BattleScript_EffectSpitUp[]; extern const u8 BattleScript_EffectSwallow[]; -extern const u8 BattleScript_EffectWorrySeed[]; +extern const u8 BattleScript_EffectOverwriteAbility[]; extern const u8 BattleScript_EffectHail[]; extern const u8 BattleScript_EffectTorment[]; extern const u8 BattleScript_EffectFlatter[]; @@ -702,14 +685,12 @@ extern const u8 BattleScript_EffectNonVolatileStatus[]; extern const u8 BattleScript_EffectMemento[]; extern const u8 BattleScript_EffectFocusPunch[]; extern const u8 BattleScript_EffectFollowMe[]; -extern const u8 BattleScript_EffectNaturePower[]; extern const u8 BattleScript_EffectCharge[]; extern const u8 BattleScript_EffectTaunt[]; extern const u8 BattleScript_EffectHelpingHand[]; extern const u8 BattleScript_EffectTrick[]; extern const u8 BattleScript_EffectRolePlay[]; extern const u8 BattleScript_EffectWish[]; -extern const u8 BattleScript_EffectAssist[]; extern const u8 BattleScript_EffectIngrain[]; extern const u8 BattleScript_EffectMagicCoat[]; extern const u8 BattleScript_EffectRecycle[]; @@ -757,8 +738,6 @@ extern const u8 BattleScript_EffectGuardSplit[]; extern const u8 BattleScript_EffectStickyWeb[]; extern const u8 BattleScript_EffectMetalBurst[]; extern const u8 BattleScript_EffectLuckyChant[]; -extern const u8 BattleScript_EffectSuckerPunch[]; -extern const u8 BattleScript_EffectSimpleBeam[]; extern const u8 BattleScript_EffectEntrainment[]; extern const u8 BattleScript_EffectHealPulse[]; extern const u8 BattleScript_EffectQuash[]; @@ -770,14 +749,12 @@ extern const u8 BattleScript_EffectElectricTerrain[]; extern const u8 BattleScript_EffectPsychicTerrain[]; extern const u8 BattleScript_EffectAttackAccUp[]; extern const u8 BattleScript_EffectAttackSpAttackUp[]; -extern const u8 BattleScript_EffectMeFirst[]; extern const u8 BattleScript_EffectQuiverDance[]; extern const u8 BattleScript_EffectCoil[]; extern const u8 BattleScript_EffectElectrify[]; extern const u8 BattleScript_EffectReflectType[]; extern const u8 BattleScript_EffectSoak[]; extern const u8 BattleScript_EffectGrowth[]; -extern const u8 BattleScript_EffectLastResort[]; extern const u8 BattleScript_EffectShellSmash[]; extern const u8 BattleScript_EffectShiftGear[]; extern const u8 BattleScript_EffectDefenseUp3[]; @@ -790,7 +767,6 @@ extern const u8 BattleScript_AbilityPreventsPhasingOutRet[]; extern const u8 BattleScript_PrintMonIsRootedRet[]; extern const u8 BattleScript_FinalGambit[]; extern const u8 BattleScript_EffectAutotomize[]; -extern const u8 BattleScript_EffectCopycat[]; extern const u8 BattleScript_EffectDefog[]; extern const u8 BattleScript_EffectHitEnemyHealAlly[]; extern const u8 BattleScript_EffectSynchronoise[]; @@ -807,14 +783,12 @@ extern const u8 BattleScript_EffectAcupressure[]; extern const u8 BattleScript_EffectAromaticMist[]; extern const u8 BattleScript_EffectPowder[]; extern const u8 BattleScript_EffectPartingShot[]; -extern const u8 BattleScript_EffectMatBlock[]; extern const u8 BattleScript_EffectInstruct[]; extern const u8 BattleScript_EffectLaserFocus[]; extern const u8 BattleScript_EffectMagneticFlux[]; extern const u8 BattleScript_EffectGearUp[]; extern const u8 BattleScript_EffectStrengthSap[]; extern const u8 BattleScript_EffectPurify[]; -extern const u8 BattleScript_FailIfNotArgType[]; extern const u8 BattleScript_EffectShoreUp[]; extern const u8 BattleScript_EffectGeomancy[]; extern const u8 BattleScript_EffectFairyLock[]; @@ -831,7 +805,6 @@ extern const u8 BattleScript_MoveEffectLeechSeed[]; extern const u8 BattleScript_MoveEffectHaze[]; extern const u8 BattleScript_MoveEffectIonDeluge[]; extern const u8 BattleScript_EffectHyperspaceFury[]; -extern const u8 BattleScript_EffectAuraWheel[]; extern const u8 BattleScript_EffectNoRetreat[]; extern const u8 BattleScript_EffectTarShot[]; extern const u8 BattleScript_EffectPoltergeist[]; @@ -841,7 +814,6 @@ extern const u8 BattleScript_EffectSkyDrop[]; extern const u8 BattleScript_EffectMeteorBeam[]; extern const u8 BattleScript_EffectCourtChange[]; extern const u8 BattleScript_EffectExtremeEvoboost[]; -extern const u8 BattleScript_EffectHitSetTerrain[]; extern const u8 BattleScript_EffectDarkVoid[]; extern const u8 BattleScript_EffectVictoryDance[]; extern const u8 BattleScript_EffectTeatime[]; @@ -859,7 +831,6 @@ extern const u8 BattleScript_EffectBrickBreak[]; extern const u8 BattleScript_EffectDoodle[]; extern const u8 BattleScript_EffectFilletAway[]; extern const u8 BattleScript_EffectShedTail[]; -extern const u8 BattleScript_EffectUpperHand[]; extern const u8 BattleScript_EffectTidyUp[]; extern const u8 BattleScript_EffectSpicyExtract[]; extern const u8 BattleScript_EffectFickleBeam[]; @@ -867,5 +838,11 @@ extern const u8 BattleScript_FickleBeamDoubled[]; extern const u8 BattleScript_QuestionForfeitBattle[]; extern const u8 BattleScript_ForfeitBattleGaveMoney[]; extern const u8 BattleScript_AbilityPopUp[]; +extern const u8 BattleScript_Attackstring[]; +extern const u8 BattleScript_SubmoveAttackstring[]; +extern const u8 BattleScript_MetronomeAttackstring[]; +extern const u8 BattleScript_SleepTalkAttackstring[]; +extern const u8 BattleScript_NaturePowerAttackstring[]; +extern const u8 BattleScript_PokemonCantUseTheMove[]; #endif // GUARD_BATTLE_SCRIPTS_H diff --git a/include/battle_setup.h b/include/battle_setup.h index 1323971f67..689d163696 100644 --- a/include/battle_setup.h +++ b/include/battle_setup.h @@ -1,6 +1,7 @@ #ifndef GUARD_BATTLE_SETUP_H #define GUARD_BATTLE_SETUP_H +#include "battle_transition.h" #include "gym_leader_rematch.h" #define REMATCHES_COUNT 5 @@ -61,9 +62,9 @@ void BattleSetup_StartLegendaryBattle(void); void StartGroudonKyogreBattle(void); void StartRegiBattle(void); enum BattleEnvironments BattleSetup_GetEnvironmentId(void); -u8 GetWildBattleTransition(void); -u8 GetTrainerBattleTransition(void); -u8 GetSpecialBattleTransition(s32 id); +enum BattleTransition GetWildBattleTransition(void); +enum BattleTransition GetTrainerBattleTransition(void); +enum BattleTransition GetSpecialBattleTransition(enum BattleTransitionGroup id); void ChooseStarter(void); void ResetTrainerOpponentIds(void); void SetMapVarsToTrainerA(void); diff --git a/include/battle_terastal.h b/include/battle_terastal.h index 6b5c385463..6bfb74986a 100644 --- a/include/battle_terastal.h +++ b/include/battle_terastal.h @@ -4,11 +4,11 @@ void ActivateTera(u32 battler); void ApplyBattlerVisualsForTeraAnim(u32 battler); bool32 CanTerastallize(u32 battler); -u32 GetBattlerTeraType(u32 battler); -void ExpendTypeStellarBoost(u32 battler, u32 type); -bool32 IsTypeStellarBoosted(u32 battler, u32 type); -uq4_12_t GetTeraMultiplier(u32 battler, u32 type); +enum Type GetBattlerTeraType(u32 battler); +void ExpendTypeStellarBoost(u32 battler, enum Type type); +bool32 IsTypeStellarBoosted(u32 battler, enum Type type); +uq4_12_t GetTeraMultiplier(struct DamageContext *ctx); -u16 GetTeraTypeRGB(u32 type); +u16 GetTeraTypeRGB(enum Type type); #endif diff --git a/include/battle_transition.h b/include/battle_transition.h index 8bc80dc642..fcfe42fde8 100644 --- a/include/battle_transition.h +++ b/include/battle_transition.h @@ -10,7 +10,8 @@ void GetBg0TilesDst(u16 **tilemap, u16 **tileset); extern const struct SpritePalette gSpritePalette_Pokeball; -enum { +enum MugshotColor +{ MUGSHOT_COLOR_NONE, MUGSHOT_COLOR_PURPLE, MUGSHOT_COLOR_GREEN, @@ -20,7 +21,8 @@ enum { MUGSHOT_COLOR_COUNT }; -enum { +enum BattleTransition +{ B_TRANSITION_BLUR, B_TRANSITION_SWIRL, B_TRANSITION_SHUFFLE, @@ -63,7 +65,8 @@ enum { }; // IDs for GetSpecialBattleTransition -enum { +enum BattleTransitionGroup +{ B_TRANSITION_GROUP_B_TOWER, B_TRANSITION_GROUP_B_DOME = 3, B_TRANSITION_GROUP_B_PALACE, diff --git a/include/battle_util.h b/include/battle_util.h index c91078db2b..8ea72866e5 100644 --- a/include/battle_util.h +++ b/include/battle_util.h @@ -3,6 +3,7 @@ #include "move.h" #include "constants/battle_string_ids.h" +#include "constants/hold_effects.h" #define MOVE_LIMITATION_ZEROMOVE (1 << 0) #define MOVE_LIMITATION_PP (1 << 1) @@ -39,42 +40,33 @@ enum MoveAbsorbed MOVE_ABSORBED_BY_BOOST_FLASH_FIRE, }; -enum { +enum FieldEffectCases +{ + FIELD_EFFECT_TRAINER_STATUSES, + FIELD_EFFECT_OVERWORLD_TERRAIN, + FIELD_EFFECT_OVERWORLD_WEATHER, +}; + +enum AbilityEffect +{ ABILITYEFFECT_ON_SWITCHIN, ABILITYEFFECT_ENDTURN, ABILITYEFFECT_MOVE_END_ATTACKER, + ABILITYEFFECT_COLOR_CHANGE, // Color Change, Berserk, Anger Shell ABILITYEFFECT_MOVE_END, ABILITYEFFECT_IMMUNITY, ABILITYEFFECT_SYNCHRONIZE, ABILITYEFFECT_ATK_SYNCHRONIZE, ABILITYEFFECT_MOVE_END_OTHER, ABILITYEFFECT_NEUTRALIZINGGAS, + ABILITYEFFECT_NEUTRALIZINGGAS_FIRST_TURN, ABILITYEFFECT_ON_WEATHER, ABILITYEFFECT_ON_TERRAIN, - ABILITYEFFECT_SWITCH_IN_TERRAIN, - ABILITYEFFECT_SWITCH_IN_WEATHER, ABILITYEFFECT_OPPORTUNIST, - ABILITYEFFECT_SWITCH_IN_STATUSES, + ABILITYEFFECT_OPPORTUNIST_FIRST_TURN, ABILITYEFFECT_ON_SWITCHIN_IMMUNITIES, }; -// For the first argument of ItemBattleEffects, to deteremine which block of item effects to try -enum ItemCaseId -{ - ITEMEFFECT_NONE, - ITEMEFFECT_ON_SWITCH_IN, - ITEMEFFECT_ON_SWITCH_IN_FIRST_TURN, - ITEMEFFECT_NORMAL, - ITEMEFFECT_TRY_HEALING, - ITEMEFFECT_MOVE_END, - ITEMEFFECT_KINGSROCK, - ITEMEFFECT_TARGET, - ITEMEFFECT_ORBS, - ITEMEFFECT_LIFEORB_SHELLBELL, - ITEMEFFECT_USE_LAST_ITEM, // move end effects for just the battler, not whole field - ITEMEFFECT_STATS_CHANGED, // For White Herb and Eject Pack -}; - enum ItemEffect { ITEM_NO_EFFECT, @@ -99,40 +91,44 @@ enum ItemEffect // for Natural Gift and Fling struct TypePower { - u8 type; + enum Type type; u8 power; u16 effect; }; enum MoveSuccessOrder { - CANCELER_FLAGS, CANCELER_STANCE_CHANGE_1, + CANCELER_CLEAR_FLAGS, CANCELER_SKY_DROP, CANCELER_RECHARGE, CANCELER_ASLEEP_OR_FROZEN, + CANCELER_POWER_POINTS, CANCELER_OBEDIENCE, CANCELER_TRUANT, CANCELER_FLINCH, CANCELER_DISABLED, - CANCELER_VOLATILE_BLOCKED, + CANCELER_VOLATILE_BLOCKED, // Gravity / Heal Block / Throat Chop CANCELER_TAUNTED, CANCELER_IMPRISONED, CANCELER_CONFUSED, - CANCELER_PARALYSED, + CANCELER_PARALYZED, CANCELER_INFATUATION, CANCELER_BIDE, + CANCELER_Z_MOVES, + CANCELER_CHOICE_LOCK, + CANCELER_CALLSUBMOVE, CANCELER_THAW, CANCELER_STANCE_CHANGE_2, - CANCELER_CHOICE_LOCK, + CANCELER_ATTACKSTRING, + CANCELER_PPDEDUCTION, CANCELER_WEATHER_PRIMAL, - CANCELER_DYNAMAX_BLOCKED, + CANCELER_MOVE_FAILURE, CANCELER_POWDER_STATUS, + CANCELER_PRIORITY_BLOCK, CANCELER_PROTEAN, - CANCELER_PSYCHIC_TERRAIN, CANCELER_EXPLODING_DAMP, CANCELER_MULTIHIT_MOVES, - CANCELER_Z_MOVES, CANCELER_MULTI_TARGET_MOVES, CANCELER_END, }; @@ -150,7 +146,8 @@ enum Obedience enum MoveCanceler { MOVE_STEP_SUCCESS, - MOVE_STEP_BREAK, + MOVE_STEP_BREAK, // Breaks out of the function to run a script + MOVE_STEP_FAILURE, // Same as break but breaks out of it due to move failure and jumps to script that handles the failure MOVE_STEP_REMOVES_STATUS, }; @@ -161,7 +158,7 @@ struct DamageContext u32 battlerAtk:3; u32 battlerDef:3; u32 move:16; - u32 moveType:5; + enum Type moveType:5; u32 isCrit:1; u32 randomFactor:1; u32 updateFlags:1; @@ -170,11 +167,23 @@ struct DamageContext u32 weather:16; u32 fixedBasePower:8; u32 padding2:8; + u32 chosenMove:16; // May be different to 'move', e.g. for Z moves. + u32 padding3:16; uq4_12_t typeEffectivenessModifier; - u32 abilityAtk:16; - u32 abilityDef:16; - enum ItemHoldEffect holdEffectAtk:16; - enum ItemHoldEffect holdEffectDef:16; + enum Ability abilityAtk; + enum Ability abilityDef; + enum HoldEffect holdEffectAtk; + enum HoldEffect holdEffectDef; +}; + +struct BattleContext +{ + u32 battlerAtk:3; + u32 battlerDef:3; + u32 currentMove:16; + u32 padding:10; + enum Ability abilities[MAX_BATTLERS_COUNT]; + enum HoldEffect holdEffects[MAX_BATTLERS_COUNT]; }; enum SleepClauseBlock @@ -196,9 +205,17 @@ enum SkyDropState #define SKY_DROP_NO_TARGET 0xFF #define SKY_DROP_RELEASED_TARGET 0xFE +enum EjectPackTiming +{ + FIRST_TURN, + END_TURN, + OTHER, +}; + void HandleAction_ThrowBall(void); u32 GetCurrentBattleWeather(void); bool32 EndOrContinueWeather(void); +bool32 IsUnnerveBlocked(u32 battler, u32 itemId); bool32 IsAffectedByFollowMe(u32 battlerAtk, u32 defSide, u32 move); bool32 HandleMoveTargetRedirection(void); void HandleAction_UseMove(void); @@ -221,7 +238,8 @@ void MarkBattlerForControllerExec(u32 battler); void MarkBattlerReceivedLinkData(u32 battler); const u8 *CancelMultiTurnMoves(u32 battler, enum SkyDropState skyDropState); bool32 WasUnableToUseMove(u32 battler); -bool32 ShouldDefiantCompetitiveActivate(u32 battler, u32 ability); +bool32 IsLastMonToMove(u32 battler); +bool32 ShouldDefiantCompetitiveActivate(u32 battler, enum Ability ability); void PrepareStringBattle(enum StringID stringId, u32 battler); void ResetSentPokesToOpponentValue(void); void OpponentSwitchInResetSentPokesToOpponentValue(u32 battler); @@ -235,48 +253,48 @@ u32 CheckMoveLimitations(u32 battler, u8 unusableMoves, u16 check); bool32 AreAllMovesUnusable(u32 battler); u8 GetImprisonedMovesCount(u32 battler, u16 move); s32 GetDrainedBigRootHp(u32 battler, s32 hp); -bool32 IsAbilityAndRecord(u32 battler, u32 battlerAbility, u32 abilityToCheck); +bool32 IsAbilityAndRecord(u32 battler, enum Ability battlerAbility, enum Ability abilityToCheck); u32 DoEndTurnEffects(void); bool32 HandleFaintedMonActions(void); void TryClearRageAndFuryCutter(void); -enum MoveCanceler AtkCanceler_MoveSuccessOrder(void); -void SetAtkCancelerForCalledMove(void); +enum MoveCanceler AtkCanceler_MoveSuccessOrder(struct BattleContext *ctx); bool32 HasNoMonsToSwitch(u32 battler, u8 partyIdBattlerOn1, u8 partyIdBattlerOn2); bool32 TryChangeBattleWeather(u32 battler, u32 battleWeatherId, u32 ability); bool32 TryChangeBattleTerrain(u32 battler, u32 statusFlag); -bool32 CanAbilityBlockMove(u32 battlerAtk, u32 battlerDef, u32 abilityAtk, u32 abilityDef, u32 move, enum FunctionCallOption option); -bool32 CanAbilityAbsorbMove(u32 battlerAtk, u32 battlerDef, u32 abilityDef, u32 move, u32 moveType, enum FunctionCallOption option); -u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 moveArg); +bool32 CanAbilityBlockMove(u32 battlerAtk, u32 battlerDef, enum Ability abilityAtk, enum Ability abilityDef, u32 move, enum FunctionCallOption option); +bool32 CanAbilityAbsorbMove(u32 battlerAtk, u32 battlerDef, enum Ability abilityDef, u32 move, enum Type moveType, enum FunctionCallOption option); +bool32 TryFieldEffects(enum FieldEffectCases caseId); +u32 AbilityBattleEffects(enum AbilityEffect caseID, u32 battler, enum Ability ability, u32 special, u32 moveArg); bool32 TryPrimalReversion(u32 battler); bool32 IsNeutralizingGasOnField(void); -bool32 IsMoldBreakerTypeAbility(u32 battler, u32 ability); +bool32 IsMoldBreakerTypeAbility(u32 battler, enum Ability ability); u32 GetBattlerAbilityIgnoreMoldBreaker(u32 battler); u32 GetBattlerAbilityNoAbilityShield(u32 battler); u32 GetBattlerAbilityInternal(u32 battler, u32 ignoreMoldBreaker, u32 noAbilityShield); -u32 GetBattlerAbility(u32 battler); -u32 IsAbilityOnSide(u32 battler, u32 ability); -u32 IsAbilityOnOpposingSide(u32 battler, u32 ability); -u32 IsAbilityOnField(u32 ability); -u32 IsAbilityOnFieldExcept(u32 battler, u32 ability); +enum Ability GetBattlerAbility(u32 battler); +u32 IsAbilityOnSide(u32 battler, enum Ability ability); +u32 IsAbilityOnOpposingSide(u32 battler, enum Ability ability); +u32 IsAbilityOnField(enum Ability ability); +u32 IsAbilityOnFieldExcept(u32 battler, enum Ability ability); u32 IsAbilityPreventingEscape(u32 battler); bool32 IsBattlerProtected(u32 battlerAtk, u32 battlerDef, u32 move); u32 GetProtectType(enum ProtectMethod method); bool32 CanBattlerEscape(u32 battler); // no ability check void BattleScriptExecute(const u8 *BS_ptr); void BattleScriptPushCursorAndCallback(const u8 *BS_ptr); -u32 ItemBattleEffects(enum ItemCaseId, u32 battler); void ClearVariousBattlerFlags(u32 battler); void HandleAction_RunBattleScript(void); u32 SetRandomTarget(u32 battler); u32 GetBattleMoveTarget(u16 move, u8 setTarget); u8 GetAttackerObedienceForAction(); -enum ItemHoldEffect GetBattlerHoldEffect(u32 battler, bool32 checkNegating); -enum ItemHoldEffect GetBattlerHoldEffectIgnoreAbility(u32 battler, bool32 checkNegating); -enum ItemHoldEffect GetBattlerHoldEffectInternal(u32 battler, bool32 checkNegating, bool32 checkAbility); +enum HoldEffect GetBattlerHoldEffect(u32 battler); +enum HoldEffect GetBattlerHoldEffectIgnoreAbility(u32 battler); +enum HoldEffect GetBattlerHoldEffectIgnoreNegation(u32 battler); +enum HoldEffect GetBattlerHoldEffectInternal(u32 battler, u32 ability); u32 GetBattlerHoldEffectParam(u32 battler); -bool32 CanBattlerAvoidContactEffects(u32 battlerAtk, u32 battlerDef, u32 abilityAtk, enum ItemHoldEffect holdEffectAtk, u32 move); -bool32 IsMoveMakingContact(u32 battlerAtk, u32 battlerDef, u32 abilityAtk, enum ItemHoldEffect holdEffectAtk, u32 move); -bool32 IsBattlerGrounded(u32 battler); +bool32 CanBattlerAvoidContactEffects(u32 battlerAtk, u32 battlerDef, enum Ability abilityAtk, enum HoldEffect holdEffectAtk, u32 move); +bool32 IsMoveMakingContact(u32 battlerAtk, u32 battlerDef, enum Ability abilityAtk, enum HoldEffect holdEffectAtk, u32 move); +bool32 IsBattlerGrounded(u32 battler, enum Ability ability, enum HoldEffect holdEffect); u32 GetMoveSlot(u16 *moves, u32 move); u32 GetBattlerWeight(u32 battler); u32 CalcRolloutBasePower(u32 battlerAtk, u32 basePower, u32 rolloutTimer); @@ -286,12 +304,12 @@ s32 CalculateMoveDamageVars(struct DamageContext *ctx); s32 DoFixedDamageMoveCalc(struct DamageContext *ctx); s32 ApplyModifiersAfterDmgRoll(struct DamageContext *ctx, s32 dmg); uq4_12_t CalcTypeEffectivenessMultiplier(struct DamageContext *ctx); -uq4_12_t CalcPartyMonTypeEffectivenessMultiplier(u16 move, u16 speciesDef, u16 abilityDef); -uq4_12_t GetTypeModifier(u32 atkType, u32 defType); -uq4_12_t GetOverworldTypeEffectiveness(struct Pokemon *mon, u8 moveType); +uq4_12_t CalcPartyMonTypeEffectivenessMultiplier(u16 move, u16 speciesDef, enum Ability abilityDef); +uq4_12_t GetTypeModifier(enum Type atkType, enum Type defType); +uq4_12_t GetOverworldTypeEffectiveness(struct Pokemon *mon, enum Type moveType); void UpdateMoveResultFlags(uq4_12_t modifier, u16 *resultFlags); s32 GetStealthHazardDamage(enum TypeSideHazard hazardType, u32 battler); -s32 GetStealthHazardDamageByTypesAndHP(enum TypeSideHazard hazardType, u8 type1, u8 type2, u32 maxHp); +s32 GetStealthHazardDamageByTypesAndHP(enum TypeSideHazard hazardType, enum Type type1, enum Type type2, u32 maxHp); bool32 CanMegaEvolve(u32 battler); bool32 CanUltraBurst(u32 battler); void ActivateMegaEvolution(u32 battler); @@ -305,13 +323,13 @@ bool32 TryBattleFormChange(u32 battler, enum FormChanges method); bool32 DoBattlersShareType(u32 battler1, u32 battler2); bool32 CanBattlerGetOrLoseItem(u32 battler, u16 itemId); u32 GetBattlerVisualSpecies(u32 battler); -bool32 TryClearIllusion(u32 battler, u32 caseID); +bool32 TryClearIllusion(u32 battler, enum AbilityEffect caseID); u32 GetIllusionMonSpecies(u32 battler); struct Pokemon *GetIllusionMonPtr(u32 battler); void ClearIllusionMon(u32 battler); u32 GetIllusionMonPartyId(struct Pokemon *party, struct Pokemon *mon, struct Pokemon *partnerMon, u32 battler); bool32 SetIllusionMon(struct Pokemon *mon, u32 battler); -u32 TryImmunityAbilityHealStatus(u32 battler, u32 caseID); +u32 TryImmunityAbilityHealStatus(u32 battler, enum AbilityEffect caseID); bool32 ShouldGetStatBadgeBoost(u16 flagId, u32 battler); uq4_12_t GetBadgeBoostModifier(void); enum DamageCategory GetBattleMoveCategory(u32 move); @@ -320,7 +338,7 @@ bool32 CanFling(u32 battler); bool32 IsTelekinesisBannedSpecies(u16 species); bool32 IsHealBlockPreventingMove(u32 battler, u32 move); bool32 IsBelchPreventingMove(u32 battler, u32 move); -bool32 HasEnoughHpToEatBerry(u32 battler, u32 hpFraction, u32 itemId); +bool32 HasEnoughHpToEatBerry(u32 battler, enum Ability ability, u32 hpFraction, u32 itemId); bool32 IsPartnerMonFromSameTrainer(u32 battler); enum DamageCategory GetCategoryBasedOnStats(u32 battler); void SetShellSideArmCategory(void); @@ -330,14 +348,10 @@ void TryRestoreHeldItems(void); bool32 CanStealItem(u32 battlerStealing, u32 battlerItem, u16 item); void TrySaveExchangedItem(u32 battler, u16 stolenItem); bool32 IsPartnerMonFromSameTrainer(u32 battler); -enum ItemEffect TryHandleSeed(u32 battler, u32 terrainFlag, u32 statId, u32 itemId, enum ItemCaseId caseID); bool32 IsBattlerAffectedByHazards(u32 battler, bool32 toxicSpikes); void SortBattlersBySpeed(u8 *battlers, bool32 slowToFast); -bool32 CompareStat(u32 battler, u8 statId, u8 cmpTo, u8 cmpKind, u32 ability); -bool32 TryRoomService(u32 battler); -void BufferStatChange(u32 battler, u8 statId, enum StringID stringId); +bool32 CompareStat(u32 battler, enum Stat statId, u8 cmpTo, u8 cmpKind, enum Ability ability); 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); @@ -356,54 +370,55 @@ bool32 CanTargetPartner(u32 battlerAtk, u32 battlerDef); bool32 TargetFullyImmuneToCurrMove(u32 battlerAtk, u32 battlerDef); bool32 MoodyCantRaiseStat(u32 stat); bool32 MoodyCantLowerStat(u32 stat); +bool32 IsBattlerTerrainAffected(u32 battler, enum Ability ability, enum HoldEffect holdEffect, u32 terrainFlag); +u32 GetHighestStatId(u32 battler); +u32 GetParadoxHighestStatId(u32 battler); +u32 GetParadoxBoostedStatId(u32 battler); -bool32 CanBeSlept(u32 battlerAtk, u32 battlerDef, u32 abilityDef, enum SleepClauseBlock isBlockedBySleepClause); -bool32 CanBePoisoned(u32 battlerAtk, u32 battlerDef, u32 abilityAtk, u32 abilityDef); -bool32 CanBeBurned(u32 battlerAtk, u32 battlerDef, u32 ability); -bool32 CanBeParalyzed(u32 battlerAtk, u32 battlerDef, u32 abilityDef); -bool32 CanBeFrozen(u32 battlerAtk, u32 battlerDef, u32 abilityDef); -bool32 CanGetFrostbite(u32 battlerAtk, u32 battlerDef, u32 abilityDef); -bool32 CanSetNonVolatileStatus(u32 battlerAtk, u32 battlerDef, u32 abilityAtk, u32 abilityDef, enum MoveEffect secondaryMoveEffect, enum FunctionCallOption option); +bool32 CanBeSlept(u32 battlerAtk, u32 battlerDef, enum Ability abilityDef, enum SleepClauseBlock isBlockedBySleepClause); +bool32 CanBePoisoned(u32 battlerAtk, u32 battlerDef, enum Ability abilityAtk, enum Ability abilityDef); +bool32 CanBeBurned(u32 battlerAtk, u32 battlerDef, enum Ability ability); +bool32 CanBeParalyzed(u32 battlerAtk, u32 battlerDef, enum Ability abilityDef); +bool32 CanBeFrozen(u32 battlerAtk, u32 battlerDef, enum Ability abilityDef); +bool32 CanGetFrostbite(u32 battlerAtk, u32 battlerDef, enum Ability abilityDef); +bool32 CanSetNonVolatileStatus(u32 battlerAtk, u32 battlerDef, enum Ability abilityAtk, enum Ability abilityDef, enum MoveEffect secondaryMoveEffect, enum FunctionCallOption option); bool32 CanBeConfused(u32 battler); -bool32 IsBattlerTerrainAffected(u32 battler, u32 terrainFlag); u32 GetBattlerAffectionHearts(u32 battler); void TryToRevertMimicryAndFlags(void); bool32 BattleArenaTurnEnd(void); u32 CountBattlerStatIncreases(u32 battler, bool32 countEvasionAcc); +bool32 BattlerHasCopyableChanges(u32 battler); bool32 ChangeTypeBasedOnTerrain(u32 battler); void RemoveConfusionStatus(u32 battler); u8 GetBattlerGender(u32 battler); bool32 AreBattlersOfOppositeGender(u32 battler1, u32 battler2); bool32 AreBattlersOfSameGender(u32 battler1, u32 battler2); -u32 CalcSecondaryEffectChance(u32 battler, u32 battlerAbility, const struct AdditionalEffect *additionalEffect); -bool32 MoveEffectIsGuaranteed(u32 battler, u32 battlerAbility, const struct AdditionalEffect *additionalEffect); -void GetBattlerTypes(u32 battler, bool32 ignoreTera, u32 types[static 3]); -u32 GetBattlerType(u32 battler, u32 typeIndex, bool32 ignoreTera); +u32 CalcSecondaryEffectChance(u32 battler, enum Ability battlerAbility, const struct AdditionalEffect *additionalEffect); +bool32 MoveEffectIsGuaranteed(u32 battler, enum Ability battlerAbility, const struct AdditionalEffect *additionalEffect); +void GetBattlerTypes(u32 battler, bool32 ignoreTera, enum Type types[static 3]); +enum Type GetBattlerType(u32 battler, u32 typeIndex, bool32 ignoreTera); bool8 CanMonParticipateInSkyBattle(struct Pokemon *mon); bool8 IsMonBannedFromSkyBattles(u16 species); -void RemoveBattlerType(u32 battler, u8 type); -u32 GetBattleMoveType(u32 move); +void RemoveBattlerType(u32 battler, enum Type type); +enum Type GetBattleMoveType(u32 move); void TryActivateSleepClause(u32 battler, u32 indexInParty); void TryDeactivateSleepClause(u32 battlerSide, u32 indexInParty); bool32 IsSleepClauseActiveForSide(u32 battlerSide); bool32 IsSleepClauseEnabled(); void ClearDamageCalcResults(void); u32 DoesDestinyBondFail(u32 battler); -bool32 IsMoveEffectBlockedByTarget(u32 ability); +bool32 IsMoveEffectBlockedByTarget(enum Ability ability); bool32 IsPursuitTargetSet(void); void ClearPursuitValuesIfSet(u32 battler); void ClearPursuitValues(void); bool32 HasWeatherEffect(void); -bool32 IsAnyTargetAffected(u32 battlerAtk); -u32 RestoreWhiteHerbStats(u32 battler); bool32 IsFutureSightAttackerInParty(u32 battlerAtk, u32 battlerDef, u32 move); bool32 HadMoreThanHalfHpNowDoesnt(u32 battler); +void ChooseStatBoostAnimation(u32 battler); void UpdateStallMons(void); -bool32 TryRestoreHPBerries(u32 battler, enum ItemCaseId caseId); -bool32 TrySwitchInEjectPack(enum ItemCaseId caseID); +bool32 TrySwitchInEjectPack(enum EjectPackTiming timing); u32 GetBattlerVolatile(u32 battler, enum Volatile _volatile); void SetMonVolatile(u32 battler, enum Volatile _volatile, u32 newValue); -u32 TryBoosterEnergy(u32 battler, u32 ability, enum ItemCaseId caseID); bool32 ItemHealMonVolatile(u32 battler, u16 itemId); void PushHazardTypeToQueue(u32 side, enum Hazards hazardType); bool32 IsHazardOnSide(u32 side, enum Hazards hazardType); @@ -411,11 +426,18 @@ bool32 AreAnyHazardsOnSide(u32 side); void RemoveAllHazardsFromField(u32 side); bool32 IsHazardOnSideAndClear(u32 side, enum Hazards hazardType); void RemoveHazardFromField(u32 side, enum Hazards hazardType); -bool32 CanMoveSkipAccuracyCalc(u32 battlerAtk, u32 battlerDef, u32 abilityAtk, u32 abilityDef, u32 move, enum FunctionCallOption option); -u32 GetTotalAccuracy(u32 battlerAtk, u32 battlerDef, u32 move, u32 atkAbility, u32 defAbility, u32 atkHoldEffect, u32 defHoldEffect); +bool32 CanMoveSkipAccuracyCalc(u32 battlerAtk, u32 battlerDef, enum Ability abilityAtk, enum Ability abilityDef, u32 move, enum FunctionCallOption option); +u32 GetTotalAccuracy(u32 battlerAtk, u32 battlerDef, u32 move, enum Ability atkAbility, enum Ability defAbility, enum HoldEffect atkHoldEffect, enum HoldEffect defHoldEffect); bool32 IsSemiInvulnerable(u32 battler, enum SemiInvulnerableExclusion excludeCommander); bool32 BreaksThroughSemiInvulnerablity(u32 battler, u32 move); bool32 HasPartnerTrainer(u32 battler); -bool32 IsAffectedByPowderMove(u32 battler, u32 ability, enum ItemHoldEffect holdEffect); +bool32 IsAffectedByPowderMove(u32 battler, u32 ability, enum HoldEffect holdEffect); +u32 GetNaturePowerMove(u32 battler); +u32 GetNaturePowerMove(u32 battler); +void RemoveAbilityFlags(u32 battler); +bool32 IsDazzlingAbility(enum Ability ability); +bool32 IsAllowedToUseBag(void); +bool32 IsAnyTargetTurnDamaged(u32 battlerAtk); +bool32 IsMimikyuDisguised(u32 battler); #endif // GUARD_BATTLE_UTIL_H diff --git a/include/config/ai.h b/include/config/ai.h index b6eb7bfe21..5a7ce40783 100644 --- a/include/config/ai.h +++ b/include/config/ai.h @@ -15,7 +15,7 @@ #define SHOULD_SWITCH_ABSORBS_MOVE_PERCENTAGE 100 #define SHOULD_SWITCH_ABSORBS_HIDDEN_POWER_PERCENTAGE 50 #define SHOULD_SWITCH_TRAPPER_PERCENTAGE 100 -#define SHOULD_SWITCH_FREE_TURN_PERCENTAGE 100 +#define SHOULD_SWITCH_FREE_TURN_PERCENTAGE 50 #define STAY_IN_ABSORBING_PERCENTAGE 66 // Chance to stay in if outgoing mon has super effective move against player, will prevent switching out for an absorber with this likelihood #define SHOULD_SWITCH_HASBADODDS_PERCENTAGE 50 #define SHOULD_SWITCH_ENCORE_STATUS_PERCENTAGE 100 @@ -110,4 +110,9 @@ #define POWER_SPLIT_ALLY_PERCENTAGE 150 #define POWER_SPLIT_ENEMY_PERCENTAGE 50 +// HP thresholds to use a status z-move. +#define Z_EFFECT_FOLLOW_ME_THRESHOLD 30 +#define Z_EFFECT_RESTORE_HP_LOWER_THRESHOLD ENABLE_RECOVERY_THRESHOLD // threshold used for moves you could conceivably use more than once +#define Z_EFFECT_RESTORE_HP_HIGHER_THRESHOLD 90 // these moves are one-time use or drop your HP + #endif // GUARD_CONFIG_AI_H diff --git a/include/config/battle.h b/include/config/battle.h index 67008ba027..dd72cdbf1b 100644 --- a/include/config/battle.h +++ b/include/config/battle.h @@ -111,7 +111,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_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_DEFOG_EFFECT_CLEARING GEN_LATEST // In Gen5+, Defog does not lower Evasion of target behind Subsitute. 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. @@ -133,6 +133,7 @@ #define B_TIME_OF_DAY_HEALING_MOVES GEN_LATEST // In Gen2, Morning Sun, Moonlight, and Synthesis heal twice as much HP based off the time of day. Also changes how much they heal. Evening affects Moonlight. // If OW_TIMES_OF_DAY is set to Gen 3, then Morning Sun is boosted during the day. #define B_DREAM_EATER_LIQUID_OOZE GEN_LATEST // In Gen5+, Dream Eater is affected by Liquid Ooze. +#define B_DREAM_EATER_SUBSTITUTE GEN_LATEST // In Gen5+, Dream Eater can successfully hit and drain from a Substitute. // Ability settings #define B_GALE_WINGS GEN_LATEST // In Gen7+ requires full HP to trigger. @@ -169,8 +170,6 @@ #define B_POWDER_OVERCOAT GEN_LATEST // In Gen6+, Overcoat blocks powder and spore moves from affecting the user. // Item settings -#define B_HP_BERRIES GEN_LATEST // In Gen4+, berries which restore HP activate immediately after HP drops to half. In Gen3, the effect occurs at the end of the turn. -#define B_BERRIES_INSTANT GEN_LATEST // In Gen4+, most berries activate on battle start/switch-in if applicable. In Gen3, they only activate either at the move end or turn end. #define B_CONFUSE_BERRIES_HEAL GEN_LATEST // Before Gen7, Figy and similar berries restore 1/8th of HP and trigger at half HP. In Gen7 they restore half HP, triggering at 25% HP. In Gen8 they heal 1/3rd of HP. #define B_X_ITEMS_BUFF GEN_LATEST // In Gen7+, the X Items raise a stat by 2 stages instead of 1. #define B_MENTAL_HERB GEN_LATEST // In Gen5+, the Mental Herb cures Taunt, Encore, Torment, Heal Block, and Disable in addition to Infatuation from before. @@ -209,7 +208,6 @@ #define B_FLAG_INVERSE_BATTLE 0 // If this flag is set, the battle's type effectiveness are inversed. For example, fire is super effective against water. #define B_FLAG_FORCE_DOUBLE_WILD 0 // If this flag is set, all land and surfing wild battles will be double battles. #define B_SMART_WILD_AI_FLAG 0 // If this flag is set, wild Pokémon will become smart, with all AI flags enabled. -#define B_FLAG_NO_BAG_USE 0 // If this flag is set, the ability to use the bag in battle is disabled. #define B_FLAG_NO_CATCHING 0 // If this flag is set, the ability to catch wild Pokémon is disabled. #define B_FLAG_NO_RUNNING 0 // If this flag is set, the ability to escape from wild battles is disabled. Also makes Roar/Whirlwind and Teleport (under Gen8) fail. #define B_FLAG_AI_VS_AI_BATTLE 0 // If this flag is set, the player's mons will be controlled by the ai next battles. @@ -231,6 +229,13 @@ #define B_VAR_DIFFICULTY 0 // If not 0, you can use this var to control which difficulty version of a Trainer is loaded. This should be manually set by the developer using Script_SetDifficulty AFTER NewGameInitData has run. +// No bag settings +#define NO_BAG_RESTRICTION 0 +#define NO_BAG_AGAINST_TRAINER 1 +#define NO_BAG_IN_BATTLE 2 + +#define B_VAR_NO_BAG_USE 0 // If 1, the ability to use the bag in battle is disabled in trainer battles. If 2, it is also disabled in wild battles. + // Sky Battles #define B_FLAG_SKY_BATTLE 0 // If this flag has a value, the player will be able to engage in scripted Sky Battles. #define B_VAR_SKY_BATTLE 0 // If this var has a value, the game will remember the positions of Pokémon used in Sky Battles. @@ -269,7 +274,6 @@ #define B_NEW_TERRAIN_BACKGROUNDS FALSE // If set to TRUE, uses new terrain backgrounds for Electric, Misty, Grassy and Psychic Terrain. // Interface settings -#define B_ABILITY_POP_UP TRUE // In Gen5+, the Pokémon abilities are displayed in a pop-up, when they activate in battle. #define B_FAST_INTRO_PKMN_TEXT TRUE // If set to TRUE, battle intro texts print at the same time as animation of a Pokémon, as opposing to waiting for the animation to end. #define B_FAST_INTRO_NO_SLIDE FALSE // If set to TRUE, the slide animation that happens at the beginning of the battle is skipped. #define B_FAST_HP_DRAIN TRUE // If set to TRUE, HP bars will move faster. @@ -288,9 +292,10 @@ // Catching settings #define B_SEMI_INVULNERABLE_CATCH GEN_LATEST // In Gen4+, you cannot throw a ball against a Pokemon that is in a semi-invulnerable state (dig/fly/etc) -#define B_CATCHING_CHARM_BOOST 20 // % boost in Critical Capture odds if player has the Catching Charm. +#define B_CATCHING_CHARM_BOOST 100 // % boost in Critical Capture odds if player has the Catching Charm. #define B_CRITICAL_CAPTURE TRUE // If set to TRUE, Critical Capture will be enabled. #define B_CRITICAL_CAPTURE_LOCAL_DEX TRUE // If set to FALSE, Critical Capture % is based off of the National Pokedex estimated by enabled generations. +#define B_CRITICAL_CAPTURE_IF_OWNED GEN_LATEST // In Gen9, a capture appear critical if the pokemon you are trying to catch already has a dex entry (has already been caught) #define B_LAST_USED_BALL TRUE // If TRUE, the "last used ball" feature from Gen 7 will be implemented #define B_LAST_USED_BALL_BUTTON R_BUTTON // If last used ball is implemented, this button (or button combo) will trigger throwing the last used ball. @@ -367,5 +372,7 @@ #define B_POOL_RULE_EXCLUDE_FORMS FALSE // Exclude different forms from the Species Clause #define B_POOL_RULE_ITEM_CLAUSE FALSE // Only allow each item to be picked once #define B_POOL_RULES_USE_ITEM_EXCLUSIONS FALSE // Exclude items listed in poolItemClauseExclusions +#define B_POOL_RULE_MEGA_STONE_CLAUSE FALSE // Pick only 1 mon with mega stone +#define B_POOL_RULE_Z_CRYSTAL_CLAUSE FALSE // Pick only 1 mon with Z-crystal #endif // GUARD_CONFIG_BATTLE_H diff --git a/include/config/contest.h b/include/config/contest.h new file mode 100644 index 0000000000..1307acc06f --- /dev/null +++ b/include/config/contest.h @@ -0,0 +1,8 @@ +#ifndef GUARD_CONFIG_CONTEST_H +#define GUARD_CONFIG_CONTEST_H + +// Move data settings +#define C_UPDATED_MOVE_CATEGORIES GEN_LATEST // Updates contest category. +#define C_UPDATED_MOVE_EFFECTS GEN_LATEST // Updates contest effects. + +#endif // GUARD_CONFIG_CONTEST_H diff --git a/include/config/debug.h b/include/config/debug.h index 2446b9360c..7e28d33504 100644 --- a/include/config/debug.h +++ b/include/config/debug.h @@ -2,16 +2,16 @@ #define GUARD_CONFIG_DEBUG_H // Overworld Debug -#define DEBUG_OVERWORLD_MENU TRUE // Enables an overworld debug menu to change flags, variables, giving pokemon and more, accessed by holding R and pressing START while in the overworld by default. +#define DEBUG_OVERWORLD_MENU DISABLED_ON_RELEASE // Enables an overworld debug menu to change flags, variables, giving pokemon and more, accessed by holding R and pressing START while in the overworld by default. #define DEBUG_OVERWORLD_HELD_KEYS (R_BUTTON) // The keys required to be held to open the debug menu. #define DEBUG_OVERWORLD_TRIGGER_EVENT pressedStartButton // The event that opens the menu when holding the key(s) defined in DEBUG_OVERWORLD_HELD_KEYS. #define DEBUG_OVERWORLD_IN_MENU FALSE // Replaces the overworld debug menu button combination with a start menu entry (above Pokédex). // Battle Debug Menu -#define DEBUG_BATTLE_MENU TRUE // If set to TRUE, enables a debug menu to use in battles by pressing the Select button. +#define DEBUG_BATTLE_MENU DISABLED_ON_RELEASE // If set to TRUE, enables a debug menu to use in battles by pressing the Select button. #define DEBUG_AI_DELAY_TIMER FALSE // If set to TRUE, displays the number of frames it takes for the AI to choose a move. Replaces the "What will PKMN do" text. Useful for devs or anyone who modifies the AI code and wants to see if it doesn't take too long to run. // Pokémon Debug -#define DEBUG_POKEMON_SPRITE_VISUALIZER TRUE // Enables a debug menu for Pokémon sprites and icons, accessed by pressing Select in the summary screen. +#define DEBUG_POKEMON_SPRITE_VISUALIZER DISABLED_ON_RELEASE // Enables a debug menu for Pokémon sprites and icons, accessed by pressing Select in the summary screen. #endif // GUARD_CONFIG_DEBUG_H diff --git a/include/config/fishing.h b/include/config/fishing.h new file mode 100644 index 0000000000..0cbf666a54 --- /dev/null +++ b/include/config/fishing.h @@ -0,0 +1,13 @@ +#ifndef GUARD_CONFIG_FISHING_H +#define GUARD_CONFIG_FISHING_H + +#define I_FISHING_BITE_ODDS GEN_LATEST // In Gen 1 and Gen 2, the Old Rod has a 100% chance for a bite, Good Rod has a 66% chance for a bite, and Super Rod has a 50% chance for a bite. In Gen 3, all rods have a base 50% chance for a bite. In Gen 4 onwards, the Old Rod has a base 25% chance for a bite, Good Rod has a 50% chance for a bite, and Super Rod has a 75% chance for a bite. +#define I_FISHING_MINIGAME GEN_3 // Each generation uses a variation of reeling in Pokémon once they have been hooked. NOTE: Only the Gen 1/2 and Gen 3 minigames are implemented right now! +#define I_FISHING_ENVIRONMENT GEN_LATEST // In Gen 3, the battle environment when fighting a hooked Pokémon is based on the tile the player is standing on. In Gen 4 onwards, the environment is based on tile that is being fished in, resulting in it usually being a water environment. +#define I_FISHING_STICKY_BOOST GEN_LATEST // In Gen 3, a Pokemon with Suction Cups or Sticky Hold in the first slot of the party causes the chance for a bite to increase by about 35%. In Gen 4 onwards, it doubles the base bite chance. +#define I_FISHING_FOLLOWER_BOOST FALSE // In HGSS, fishing bite odds are increased depending on the friendship of the current following Pokémon. +#define I_FISHING_CHAIN FALSE // Introduced in XY, hooking the same Pokémon repeatedly will increase the odds of that mon being shiny. NOTE: This implementation is an approximation of the actual feature, as XY have not been throughoutly documented or datamined. +#define I_FISHING_PROXIMITY FALSE // In XY, bite chance is boosted by the number of adjacent non-surfable tiles next to your fishing line +#define I_FISHING_TIME_OF_DAY_BOOST FALSE // In XY, bite chance is boosted during morning and evening + +#endif // GUARD_CONFIG_FISHING_H diff --git a/include/config/general.h b/include/config/general.h index 555d434314..b83d759000 100644 --- a/include/config/general.h +++ b/include/config/general.h @@ -6,11 +6,16 @@ // still has them in the ROM. This is because the developers forgot // to define NDEBUG before release, however this has been changed as // Ruby's actual debug build does not use the AGBPrint features. +// +// Use `make release` to automatically enable NDEBUG. +#ifdef RELEASE #define NDEBUG +#endif -// To enable printf debugging, comment out "#define NDEBUG". This allows +// printf debugging is now enabled by default. This allows // the various AGBPrint functions to be used. (See include/gba/isagbprint.h). // See below for enabling different pretty printing versions. +// To disable printf debugging, build a release build using `make release`. #ifndef NDEBUG @@ -63,14 +68,13 @@ #define GEN_7 6 #define GEN_8 7 #define GEN_9 8 +#define GEN_COUNT 9 // Changing GEN_LATEST's value to a different Generation will change every default setting that uses it at once. #define GEN_LATEST GEN_9 // General settings #define EXPANSION_INTRO TRUE // If TRUE, a custom RHH intro will play after the vanilla copyright screen. #define HQ_RANDOM TRUE // If TRUE, replaces the default RNG with an implementation of SFC32 RNG. May break code that relies on RNG. -#define AUTO_SCROLL_TEXT FALSE // If TRUE, text will automatically scroll to the next line after NUM_FRAMES_AUTO_SCROLL_DELAY. Players can still press A_BUTTON or B_BUTTON to scroll on their own. -#define NUM_FRAMES_AUTO_SCROLL_DELAY 49 #define PHONEMES_SHARED FALSE // If TRUE, bard phonemes all reference the same sound (sound/direct_sound_samples/phonemes/shared.bin) to save ROM space. // Measurement system constants to be used for UNITS @@ -83,5 +87,4 @@ // Naming Screen #define AUTO_LOWERCASE_KEYBOARD GEN_LATEST // Starting in GEN_6, after entering the first uppercase character, the keyboard switches to lowercase letters. -#define SAVE_TYPE_ERROR_SCREEN FALSE // When enabled, this shows an error message when the game is loaded on a cart without a flash chip or on an emulator with the wrong save type setting instead of crashing. #endif // GUARD_CONFIG_GENERAL_H diff --git a/include/config/item.h b/include/config/item.h index 4222754ead..8a5a0009dd 100644 --- a/include/config/item.h +++ b/include/config/item.h @@ -38,13 +38,15 @@ // Vs. Seeker #define I_VS_SEEKER_CHARGING 0 // If this flag is assigned, the Vs Seeker functionality will be enabled. When the player has the Vs. Seeker, Match Call rematch functions will stop working. Documentation for the Vs. Seeker can be found in docs/tutorials/vs_seeker.md. -// Fishing -#define I_FISHING_BITE_ODDS GEN_LATEST // In Gen 1 and Gen 2, the Old Rod has a 100% chance for a bite, Good Rod has a 66% chance for a bite, and Super Rod has a 50% chance for a bite. In Gen 3, all rods have a base 50% chance for a bite. In Gen 4 onwards, the Old Rod has a base 25% chance for a bite, Good Rod has a 50% chance for a bite, and Super Rod has a 75% chance for a bite. -#define I_FISHING_MINIGAME GEN_3 // Each generation uses a variation of reeling in Pokémon once they have been hooked. NOTE: Only the Gen 1/2 and Gen 3 minigames are implemented right now! -#define I_FISHING_ENVIRONMENT GEN_LATEST // In Gen 3, the battle environment when fighting a hooked Pokémon is based on the tile the player is standing on. In Gen 4 onwards, the environment is based on tile that is being fished in, resulting in it usually being a water environment. -#define I_FISHING_STICKY_BOOST GEN_LATEST // In Gen 3, a Pokemon with Suction Cups or Sticky Hold in the first slot of the party causes the chance for a bite to increase by about 35%. In Gen 4 onwards, it doubles the base bite chance. -#define I_FISHING_FOLLOWER_BOOST FALSE // In HGSS, fishing bite odds are increased depending on the friendship of the current following Pokémon. -#define I_FISHING_CHAIN FALSE // Introduced in XY, hooking the same Pokémon repeatedly will increase the odds of that mon being shiny. NOTE: This implementation is an approximation of the actual feature, as XY have not been throughoutly documented or datamined. -#define I_FISHING_PROXIMITY FALSE // Introduced in XY, fishing away from other people in enclosed areas will increase the chances of a Pokémon being hooked. NOTE: This implementation is an approximation of the actual feature, as XY have not been throughoutly documented or datamined. +// ORAS Dowsing Machine +#define I_ORAS_DOWSING_FLAG 0 // Replace 0 with an unused flag to enable the Dowsing Machine mechanic from ORAS. +#define I_ORAS_DOWSING_SOUNDS TRUE // If TRUE, the Dowsing Machine will make sounds based on how far away the hidden item is. +#define I_ORAS_DOWSING_COLOR_PAL 15 // The color within the palette that will change based on proximity to the item. +// Color values for the ORAS dowsing distances/anims +#define I_ORAS_DOWSING_COLOR_NONE RGB_GRAY +#define I_ORAS_DOWSING_COLOR_SLOW RGB2GBA(56, 120, 255) +#define I_ORAS_DOWSING_COLOR_NORMAL RGB2GBA(24, 216, 24) +#define I_ORAS_DOWSING_COLOR_FAST RGB2GBA(255, 255, 40) +#define I_ORAS_DOWSING_COLOR_FASTER RGB_RED #endif // GUARD_CONFIG_ITEM_H diff --git a/include/config/name_box.h b/include/config/name_box.h new file mode 100644 index 0000000000..715b33cad9 --- /dev/null +++ b/include/config/name_box.h @@ -0,0 +1,17 @@ +#ifndef GUARD_CONFIG_NAME_BOX_H +#define GUARD_CONFIG_NAME_BOX_H + +#define OW_FLAG_SUPPRESS_NAME_BOX 0 // If this flag is set, any namebox (whether its from a macro or a code) will not show up until this flag is unset. + +// Namebox Speaker configs +#define OW_NAME_BOX_USE_DYNAMIC_WIDTH TRUE // When TRUE, the namebox window can use different width depending on the length of the speaker's name. +#define OW_NAME_BOX_NPC_TRAINER FALSE // When TRUE, any approaching NPC trainers will have a namebox shown automagically. The name will be taken from their trainer data. +#define OW_NAME_BOX_DEFAULT_WIDTH 8 // Maximum width of what OW_NAME_BOX_USE_DYNAMIC_WIDTH can set. Also the default width when the config above is set to FALSE (or the dynamic width exceeds this value). +#define OW_NAME_BOX_DEFAULT_HEIGHT 2 // Maximum height of the namebox window. + +// Text colors of Namebox. The numbers corresponds to the palette index. +// The BG color is not provided as it always needs to be 0. +#define OW_NAME_BOX_FOREGROUND_COLOR 1 +#define OW_NAME_BOX_SHADOW_COLOR 2 + +#endif // GUARD_CONFIG_NAME_BOX_H diff --git a/include/config/overworld.h b/include/config/overworld.h index ff2ab3311e..a8a6a5dd06 100644 --- a/include/config/overworld.h +++ b/include/config/overworld.h @@ -21,7 +21,7 @@ // These generational defines only make a distinction for Berries and the OW_PC_MOVE_ORDER #define GEN_6_XY GEN_6 -#define GEN_6_ORAS GEN_LATEST + 1 +#define GEN_6_ORAS GEN_COUNT + 1 // PC settings #define OW_PC_PRESS_B GEN_LATEST // In Gen4, pressing B when holding a Pokémon is equivalent to placing it. In Gen3, it gives the "You're holding a Pokémon!" error. @@ -83,16 +83,16 @@ #define OW_FLASH_FIRE GEN_LATEST // In Gen8+, if a Pokémon with Flash Fire is leading the party, there is a 50% chance to encounter a Fire-type Pokémon. // These defines only make a distinction for OW_ALTERED_TIME_RATIO -#define GEN_8_PLA GEN_LATEST + 2 -#define TIME_DEBUG GEN_LATEST + 3 +#define GEN_8_PLA GEN_COUNT + 2 +#define TIME_DEBUG GEN_COUNT + 3 -//Time +// Time #define OW_TIMES_OF_DAY GEN_LATEST // Different generations have the times of day change at different times. #define OW_USE_FAKE_RTC FALSE // When TRUE, seconds on the in-game clock will only advance once every 60 playTimeVBlanks (every 60 frames). #define OW_ALTERED_TIME_RATIO GEN_LATEST // In GEN_8_PLA, the time in game moves forward 60 seconds for every second in the RTC. In GEN_9, it is 20 seconds. TIME_DEBUG is 1:1, and meant for debugging purposes. This has no effect if OW_USE_FAKE_RTC is FALSE. #define OW_TIME_OF_DAY_ENCOUNTERS FALSE // If TRUE, will allow the user to define and use different encounter tables based on the time of day. #define OW_TIME_OF_DAY_DISABLE_FALLBACK FALSE // If TRUE, if the encounter table for a specific map and time is empty, the area will have no encounters instead of falling back to the vanilla map and time. -#define OW_TIME_OF_DAY_FALLBACK TIME_MORNING // The time of day that encounter tables fall back to. +#define OW_TIME_OF_DAY_FALLBACK TIME_MORNING // The time of day that encounter tables fall back to. If you set OW_TIMES_OF_DAY to GEN_3, change this to TIME_DAY or you won't have any encounters! // Lighting #define OW_SHADOW_INTENSITY 4 // Ranges from 0 to 16, where 0 is fully transparent and 16 is black. diff --git a/include/config/species_enabled.h b/include/config/species_enabled.h index 23bb6d9d54..5866d24399 100644 --- a/include/config/species_enabled.h +++ b/include/config/species_enabled.h @@ -1,9 +1,6 @@ #ifndef GUARD_CONFIG_SPECIES_ENABLED_H #define GUARD_CONFIG_SPECIES_ENABLED_H -// WARNING: For some reason, using 1/0 instead of TRUE/FALSE causes cry IDs to be shifted. -// Please use TRUE/FALSE when using the family toggles. - // Modifying the latest generation WILL change the saveblock due to Dex flags and will require a new save file. // Generations of Pokémon are defined by the first member introduced, // so Pikachu depends on the Gen 1 setting despite Pichu being the lowest member of the evolution tree. @@ -29,6 +26,8 @@ #define P_GIGANTAMAX_FORMS TRUE #define P_TERA_FORMS TRUE +#define P_GEN_9_MEGA_EVOLUTIONS P_MEGA_EVOLUTIONS // Mega Evolutions introduced in Z-A and its DLC + // Fusion forms #define P_FUSION_FORMS TRUE diff --git a/include/config/summary_screen.h b/include/config/summary_screen.h index 07bae63533..e76cd478b6 100644 --- a/include/config/summary_screen.h +++ b/include/config/summary_screen.h @@ -2,16 +2,16 @@ #define GUARD_CONFIG_SUMMARY_SCREEN_H // Settings -#define P_SUMMARY_SCREEN_MOVE_RELEARNER TRUE // If TRUE, shows an option for Pokémon to relearn moves on the summary screen moves page. -#define P_SUMMARY_SCREEN_NATURE_COLORS TRUE // If TRUE, nature-based stat boosts and reductions will be red and blue in the summary screen. -#define P_SUMMARY_MOVE_RELEARNER_FULL_PP TRUE // If TRUE, the move relearner in the summary screen restores relearned moves' PP to full. +#define P_SUMMARY_SCREEN_NATURE_COLORS TRUE // If TRUE, nature-based stat boosts and reductions will be red and blue in the summary screen. #define P_SUMMARY_SCREEN_RENAME TRUE // If TRUE, an option to change Pokémon nicknames replaces the cancel prompt on the summary screen info page. + +// IV/EV settings #define P_SUMMARY_SCREEN_IV_EV_INFO FALSE // If TRUE, will allow player to cycle through the Stats, IVs, and EVs in the summary screen skills page. #define P_SUMMARY_SCREEN_IV_EV_BOX_ONLY FALSE // If TRUE, will allow player to cycle through the Stats, IVs, and EVs in the summary screen skills page, but only in the PC storage box. #define P_SUMMARY_SCREEN_IV_HYPERTRAIN TRUE // If TRUE, stats that have been hyper trained will show as 31/S when viewing them in the summary screen #define P_SUMMARY_SCREEN_IV_EV_TILESET FALSE // If TRUE, loads an alternate tileset to allow changing the "STATS" label in the summary screen skills page. Note: if it's still loading the alternate tileset after changing this and recompiling, you may need a `make clean` before compilation. #define P_SUMMARY_SCREEN_IV_EV_VALUES FALSE // If TRUE, will show the actual IV value instead of the letter grade. -/* +/* LETTER GRADE GUIDE: F = 0 @@ -26,7 +26,32 @@ Info taken from https://bulbapedia.bulbagarden.net/wiki/Stats_judge. #define P_SUMMARY_SCREEN_IV_ONLY FALSE // If TRUE, will only show IV info in the summary screen. #define P_SUMMARY_SCREEN_EV_ONLY FALSE // If TRUE, will only show EV info in the summary screen. -// Flags +// IV/EV flags #define P_FLAG_SUMMARY_SCREEN_IV_EV_INFO 0 // If this flag is set, will allow player to cycle through the Stats, IVs, and EVs in the summary screen skills page. Note: if P_SUMMARY_SCREEN_IV_EV_INFO is TRUE, this flag does nothing. +// Move Relearner settings +#define P_ENABLE_MOVE_RELEARNERS FALSE // If TRUE, it enables move relearners for egg, TM and tutor. (see below for specific configs /flags) +#define P_SORT_MOVES FALSE // If TRUE, sorts all moves alphabetically in the relearner's list. + +// Level up Relearner +#define P_PRE_EVO_MOVES FALSE // If TRUE, it enables the Pokémon to learn moves from it's pre evolution. +#define P_ENABLE_ALL_LEVEL_UP_MOVES FALSE // If TRUE, it enables the Pokémon to learn all level up moves, regardless of its level. + +// TM Relearner +#define P_TM_MOVES_RELEARNER TRUE // If TRUE, enables machine move relearner. +#define P_ENABLE_ALL_TM_MOVES FALSE // If TRUE, it enables the Pokémon to learn all TMs its compatible with, regardless of it being in the bag. + +// Relearner flags - Redundant if P_ENABLE_MOVE_RELEARNERS is TRUE, but still added here incase you don't want all relearners unlocked at the same time. +// To use the following features in scripting, replace the 0s with the flag ID you're assigning it to. +// Eg: Replace with FLAG_UNUSED_0x264 so you can use that flag to toggle the feature. +#define P_FLAG_EGG_MOVES 0 // If this flag is set, enables egg move relearner. +#define P_FLAG_TUTOR_MOVES 0 // If this flag is set, enables tutor move relearner. + +// Move Relearner summary screen +#define P_SUMMARY_SCREEN_MOVE_RELEARNER TRUE // If TRUE, shows an option for Pokémon to relearn moves on the summary screen moves page. +#define P_SUMMARY_MOVE_RELEARNER_FULL_PP TRUE // If TRUE, the move relearner in the summary screen restores relearned moves' PP to full. + +// Move Relearner party menu +#define P_PARTY_MOVE_RELEARNER FALSE // If TRUE, it enables the move relearner in the party menu. + #endif // GUARD_CONFIG_SUMMARY_SCREEN_H diff --git a/include/config/text.h b/include/config/text.h new file mode 100644 index 0000000000..81438055a1 --- /dev/null +++ b/include/config/text.h @@ -0,0 +1,19 @@ +#ifndef GUARD_CONFIG_TEXT_H +#define GUARD_CONFIG_TEXT_H + +// Text settings: +#define AUTO_SCROLL_TEXT FALSE // If TRUE, text will automatically scroll to the next line after NUM_FRAMES_AUTO_SCROLL_DELAY. Players can still press A_BUTTON or B_BUTTON to scroll on their own. +#define NUM_FRAMES_AUTO_SCROLL_DELAY 49 + +// A note on the modifiers: they are roughly multiplicative, so having them set at 1 is vanilla speed. They also are used to calculate frame delays for the speed of the scroll effect and the animated down arrow, so to that end, they are capped at 31 to prevent the text printing from desyncing with A/B button inputs. +// From testing, a value of 18 to 20 is essentially equivalent to instant text. +#define TEXT_SPEED_SLOW_MODIFIER 1 // How fast the SLOW text speed option prints +#define TEXT_SPEED_MEDIUM_MODIFIER 1 // How fast the MID text speed option prints +#define TEXT_SPEED_FAST_MODIFIER 1 // How fast the FAST text speed option prints +#define TEXT_SPEED_INSTANT_MODIFIER 12 // Needed only for the animation delays +#define TEXT_SPEED_INSTANT FALSE // Renders all text as fast as it can, basically instant. Overrides FLAG_TEXT_SPEED_INSTANT and in-game player options menu setting. + +// Text speed flag: +#define FLAG_TEXT_SPEED_INSTANT 0 // Use this if you want to toggle instant text speed + +#endif // GUARD_CONFIG_TEXT_H diff --git a/include/constants/abilities.h b/include/constants/abilities.h index 8568206137..7e17fd5287 100644 --- a/include/constants/abilities.h +++ b/include/constants/abilities.h @@ -1,344 +1,339 @@ #ifndef GUARD_CONSTANTS_ABILITIES_H #define GUARD_CONSTANTS_ABILITIES_H -#define ABILITY_NONE 0 -#define ABILITY_STENCH 1 -#define ABILITY_DRIZZLE 2 -#define ABILITY_SPEED_BOOST 3 -#define ABILITY_BATTLE_ARMOR 4 -#define ABILITY_STURDY 5 -#define ABILITY_DAMP 6 -#define ABILITY_LIMBER 7 -#define ABILITY_SAND_VEIL 8 -#define ABILITY_STATIC 9 -#define ABILITY_VOLT_ABSORB 10 -#define ABILITY_WATER_ABSORB 11 -#define ABILITY_OBLIVIOUS 12 -#define ABILITY_CLOUD_NINE 13 -#define ABILITY_COMPOUND_EYES 14 -#define ABILITY_INSOMNIA 15 -#define ABILITY_COLOR_CHANGE 16 -#define ABILITY_IMMUNITY 17 -#define ABILITY_FLASH_FIRE 18 -#define ABILITY_SHIELD_DUST 19 -#define ABILITY_OWN_TEMPO 20 -#define ABILITY_SUCTION_CUPS 21 -#define ABILITY_INTIMIDATE 22 -#define ABILITY_SHADOW_TAG 23 -#define ABILITY_ROUGH_SKIN 24 -#define ABILITY_WONDER_GUARD 25 -#define ABILITY_LEVITATE 26 -#define ABILITY_EFFECT_SPORE 27 -#define ABILITY_SYNCHRONIZE 28 -#define ABILITY_CLEAR_BODY 29 -#define ABILITY_NATURAL_CURE 30 -#define ABILITY_LIGHTNING_ROD 31 -#define ABILITY_SERENE_GRACE 32 -#define ABILITY_SWIFT_SWIM 33 -#define ABILITY_CHLOROPHYLL 34 -#define ABILITY_ILLUMINATE 35 -#define ABILITY_TRACE 36 -#define ABILITY_HUGE_POWER 37 -#define ABILITY_POISON_POINT 38 -#define ABILITY_INNER_FOCUS 39 -#define ABILITY_MAGMA_ARMOR 40 -#define ABILITY_WATER_VEIL 41 -#define ABILITY_MAGNET_PULL 42 -#define ABILITY_SOUNDPROOF 43 -#define ABILITY_RAIN_DISH 44 -#define ABILITY_SAND_STREAM 45 -#define ABILITY_PRESSURE 46 -#define ABILITY_THICK_FAT 47 -#define ABILITY_EARLY_BIRD 48 -#define ABILITY_FLAME_BODY 49 -#define ABILITY_RUN_AWAY 50 -#define ABILITY_KEEN_EYE 51 -#define ABILITY_HYPER_CUTTER 52 -#define ABILITY_PICKUP 53 -#define ABILITY_TRUANT 54 -#define ABILITY_HUSTLE 55 -#define ABILITY_CUTE_CHARM 56 -#define ABILITY_PLUS 57 -#define ABILITY_MINUS 58 -#define ABILITY_FORECAST 59 -#define ABILITY_STICKY_HOLD 60 -#define ABILITY_SHED_SKIN 61 -#define ABILITY_GUTS 62 -#define ABILITY_MARVEL_SCALE 63 -#define ABILITY_LIQUID_OOZE 64 -#define ABILITY_OVERGROW 65 -#define ABILITY_BLAZE 66 -#define ABILITY_TORRENT 67 -#define ABILITY_SWARM 68 -#define ABILITY_ROCK_HEAD 69 -#define ABILITY_DROUGHT 70 -#define ABILITY_ARENA_TRAP 71 -#define ABILITY_VITAL_SPIRIT 72 -#define ABILITY_WHITE_SMOKE 73 -#define ABILITY_PURE_POWER 74 -#define ABILITY_SHELL_ARMOR 75 -#define ABILITY_AIR_LOCK 76 +enum __attribute__((packed)) Ability +{ + ABILITY_NONE = 0, + ABILITY_STENCH = 1, + ABILITY_DRIZZLE = 2, + ABILITY_SPEED_BOOST = 3, + ABILITY_BATTLE_ARMOR = 4, + ABILITY_STURDY = 5, + ABILITY_DAMP = 6, + ABILITY_LIMBER = 7, + ABILITY_SAND_VEIL = 8, + ABILITY_STATIC = 9, + ABILITY_VOLT_ABSORB = 10, + ABILITY_WATER_ABSORB = 11, + ABILITY_OBLIVIOUS = 12, + ABILITY_CLOUD_NINE = 13, + ABILITY_COMPOUND_EYES = 14, + ABILITY_INSOMNIA = 15, + ABILITY_COLOR_CHANGE = 16, + ABILITY_IMMUNITY = 17, + ABILITY_FLASH_FIRE = 18, + ABILITY_SHIELD_DUST = 19, + ABILITY_OWN_TEMPO = 20, + ABILITY_SUCTION_CUPS = 21, + ABILITY_INTIMIDATE = 22, + ABILITY_SHADOW_TAG = 23, + ABILITY_ROUGH_SKIN = 24, + ABILITY_WONDER_GUARD = 25, + ABILITY_LEVITATE = 26, + ABILITY_EFFECT_SPORE = 27, + ABILITY_SYNCHRONIZE = 28, + ABILITY_CLEAR_BODY = 29, + ABILITY_NATURAL_CURE = 30, + ABILITY_LIGHTNING_ROD = 31, + ABILITY_SERENE_GRACE = 32, + ABILITY_SWIFT_SWIM = 33, + ABILITY_CHLOROPHYLL = 34, + ABILITY_ILLUMINATE = 35, + ABILITY_TRACE = 36, + ABILITY_HUGE_POWER = 37, + ABILITY_POISON_POINT = 38, + ABILITY_INNER_FOCUS = 39, + ABILITY_MAGMA_ARMOR = 40, + ABILITY_WATER_VEIL = 41, + ABILITY_MAGNET_PULL = 42, + ABILITY_SOUNDPROOF = 43, + ABILITY_RAIN_DISH = 44, + ABILITY_SAND_STREAM = 45, + ABILITY_PRESSURE = 46, + ABILITY_THICK_FAT = 47, + ABILITY_EARLY_BIRD = 48, + ABILITY_FLAME_BODY = 49, + ABILITY_RUN_AWAY = 50, + ABILITY_KEEN_EYE = 51, + ABILITY_HYPER_CUTTER = 52, + ABILITY_PICKUP = 53, + ABILITY_TRUANT = 54, + ABILITY_HUSTLE = 55, + ABILITY_CUTE_CHARM = 56, + ABILITY_PLUS = 57, + ABILITY_MINUS = 58, + ABILITY_FORECAST = 59, + ABILITY_STICKY_HOLD = 60, + ABILITY_SHED_SKIN = 61, + ABILITY_GUTS = 62, + ABILITY_MARVEL_SCALE = 63, + ABILITY_LIQUID_OOZE = 64, + ABILITY_OVERGROW = 65, + ABILITY_BLAZE = 66, + ABILITY_TORRENT = 67, + ABILITY_SWARM = 68, + ABILITY_ROCK_HEAD = 69, + ABILITY_DROUGHT = 70, + ABILITY_ARENA_TRAP = 71, + ABILITY_VITAL_SPIRIT = 72, + ABILITY_WHITE_SMOKE = 73, + ABILITY_PURE_POWER = 74, + ABILITY_SHELL_ARMOR = 75, + ABILITY_AIR_LOCK = 76, + ABILITIES_COUNT_GEN3, -#define ABILITIES_COUNT_GEN3 77 + // Gen 4 + ABILITY_TANGLED_FEET = ABILITIES_COUNT_GEN3, + ABILITY_MOTOR_DRIVE = 78, + ABILITY_RIVALRY = 79, + ABILITY_STEADFAST = 80, + ABILITY_SNOW_CLOAK = 81, + ABILITY_GLUTTONY = 82, + ABILITY_ANGER_POINT = 83, + ABILITY_UNBURDEN = 84, + ABILITY_HEATPROOF = 85, + ABILITY_SIMPLE = 86, + ABILITY_DRY_SKIN = 87, + ABILITY_DOWNLOAD = 88, + ABILITY_IRON_FIST = 89, + ABILITY_POISON_HEAL = 90, + ABILITY_ADAPTABILITY = 91, + ABILITY_SKILL_LINK = 92, + ABILITY_HYDRATION = 93, + ABILITY_SOLAR_POWER = 94, + ABILITY_QUICK_FEET = 95, + ABILITY_NORMALIZE = 96, + ABILITY_SNIPER = 97, + ABILITY_MAGIC_GUARD = 98, + ABILITY_NO_GUARD = 99, + ABILITY_STALL = 100, + ABILITY_TECHNICIAN = 101, + ABILITY_LEAF_GUARD = 102, + ABILITY_KLUTZ = 103, + ABILITY_MOLD_BREAKER = 104, + ABILITY_SUPER_LUCK = 105, + ABILITY_AFTERMATH = 106, + ABILITY_ANTICIPATION = 107, + ABILITY_FOREWARN = 108, + ABILITY_UNAWARE = 109, + ABILITY_TINTED_LENS = 110, + ABILITY_FILTER = 111, + ABILITY_SLOW_START = 112, + ABILITY_SCRAPPY = 113, + ABILITY_STORM_DRAIN = 114, + ABILITY_ICE_BODY = 115, + ABILITY_SOLID_ROCK = 116, + ABILITY_SNOW_WARNING = 117, + ABILITY_HONEY_GATHER = 118, + ABILITY_FRISK = 119, + ABILITY_RECKLESS = 120, + ABILITY_MULTITYPE = 121, + ABILITY_FLOWER_GIFT = 122, + ABILITY_BAD_DREAMS = 123, + ABILITIES_COUNT_GEN4, -// Gen 4 -#define ABILITY_TANGLED_FEET 77 -#define ABILITY_MOTOR_DRIVE 78 -#define ABILITY_RIVALRY 79 -#define ABILITY_STEADFAST 80 -#define ABILITY_SNOW_CLOAK 81 -#define ABILITY_GLUTTONY 82 -#define ABILITY_ANGER_POINT 83 -#define ABILITY_UNBURDEN 84 -#define ABILITY_HEATPROOF 85 -#define ABILITY_SIMPLE 86 -#define ABILITY_DRY_SKIN 87 -#define ABILITY_DOWNLOAD 88 -#define ABILITY_IRON_FIST 89 -#define ABILITY_POISON_HEAL 90 -#define ABILITY_ADAPTABILITY 91 -#define ABILITY_SKILL_LINK 92 -#define ABILITY_HYDRATION 93 -#define ABILITY_SOLAR_POWER 94 -#define ABILITY_QUICK_FEET 95 -#define ABILITY_NORMALIZE 96 -#define ABILITY_SNIPER 97 -#define ABILITY_MAGIC_GUARD 98 -#define ABILITY_NO_GUARD 99 -#define ABILITY_STALL 100 -#define ABILITY_TECHNICIAN 101 -#define ABILITY_LEAF_GUARD 102 -#define ABILITY_KLUTZ 103 -#define ABILITY_MOLD_BREAKER 104 -#define ABILITY_SUPER_LUCK 105 -#define ABILITY_AFTERMATH 106 -#define ABILITY_ANTICIPATION 107 -#define ABILITY_FOREWARN 108 -#define ABILITY_UNAWARE 109 -#define ABILITY_TINTED_LENS 110 -#define ABILITY_FILTER 111 -#define ABILITY_SLOW_START 112 -#define ABILITY_SCRAPPY 113 -#define ABILITY_STORM_DRAIN 114 -#define ABILITY_ICE_BODY 115 -#define ABILITY_SOLID_ROCK 116 -#define ABILITY_SNOW_WARNING 117 -#define ABILITY_HONEY_GATHER 118 -#define ABILITY_FRISK 119 -#define ABILITY_RECKLESS 120 -#define ABILITY_MULTITYPE 121 -#define ABILITY_FLOWER_GIFT 122 -#define ABILITY_BAD_DREAMS 123 + // Gen 5 + ABILITY_PICKPOCKET = ABILITIES_COUNT_GEN4, + ABILITY_SHEER_FORCE = 125, + ABILITY_CONTRARY = 126, + ABILITY_UNNERVE = 127, + ABILITY_DEFIANT = 128, + ABILITY_DEFEATIST = 129, + ABILITY_CURSED_BODY = 130, + ABILITY_HEALER = 131, + ABILITY_FRIEND_GUARD = 132, + ABILITY_WEAK_ARMOR = 133, + ABILITY_HEAVY_METAL = 134, + ABILITY_LIGHT_METAL = 135, + ABILITY_MULTISCALE = 136, + ABILITY_TOXIC_BOOST = 137, + ABILITY_FLARE_BOOST = 138, + ABILITY_HARVEST = 139, + ABILITY_TELEPATHY = 140, + ABILITY_MOODY = 141, + ABILITY_OVERCOAT = 142, + ABILITY_POISON_TOUCH = 143, + ABILITY_REGENERATOR = 144, + ABILITY_BIG_PECKS = 145, + ABILITY_SAND_RUSH = 146, + ABILITY_WONDER_SKIN = 147, + ABILITY_ANALYTIC = 148, + ABILITY_ILLUSION = 149, + ABILITY_IMPOSTER = 150, + ABILITY_INFILTRATOR = 151, + ABILITY_MUMMY = 152, + ABILITY_MOXIE = 153, + ABILITY_JUSTIFIED = 154, + ABILITY_RATTLED = 155, + ABILITY_MAGIC_BOUNCE = 156, + ABILITY_SAP_SIPPER = 157, + ABILITY_PRANKSTER = 158, + ABILITY_SAND_FORCE = 159, + ABILITY_IRON_BARBS = 160, + ABILITY_ZEN_MODE = 161, + ABILITY_VICTORY_STAR = 162, + ABILITY_TURBOBLAZE = 163, + ABILITY_TERAVOLT = 164, + ABILITIES_COUNT_GEN5, -#define ABILITIES_COUNT_GEN4 124 + // Gen 6 + ABILITY_AROMA_VEIL = ABILITIES_COUNT_GEN5, + ABILITY_FLOWER_VEIL = 166, + ABILITY_CHEEK_POUCH = 167, + ABILITY_PROTEAN = 168, + ABILITY_FUR_COAT = 169, + ABILITY_MAGICIAN = 170, + ABILITY_BULLETPROOF = 171, + ABILITY_COMPETITIVE = 172, + ABILITY_STRONG_JAW = 173, + ABILITY_REFRIGERATE = 174, + ABILITY_SWEET_VEIL = 175, + ABILITY_STANCE_CHANGE = 176, + ABILITY_GALE_WINGS = 177, + ABILITY_MEGA_LAUNCHER = 178, + ABILITY_GRASS_PELT = 179, + ABILITY_SYMBIOSIS = 180, + ABILITY_TOUGH_CLAWS = 181, + ABILITY_PIXILATE = 182, + ABILITY_GOOEY = 183, + ABILITY_AERILATE = 184, + ABILITY_PARENTAL_BOND = 185, + ABILITY_DARK_AURA = 186, + ABILITY_FAIRY_AURA = 187, + ABILITY_AURA_BREAK = 188, + ABILITY_PRIMORDIAL_SEA = 189, + ABILITY_DESOLATE_LAND = 190, + ABILITY_DELTA_STREAM = 191, + ABILITIES_COUNT_GEN6, -// Gen 5 -#define ABILITY_PICKPOCKET 124 -#define ABILITY_SHEER_FORCE 125 -#define ABILITY_CONTRARY 126 -#define ABILITY_UNNERVE 127 -#define ABILITY_DEFIANT 128 -#define ABILITY_DEFEATIST 129 -#define ABILITY_CURSED_BODY 130 -#define ABILITY_HEALER 131 -#define ABILITY_FRIEND_GUARD 132 -#define ABILITY_WEAK_ARMOR 133 -#define ABILITY_HEAVY_METAL 134 -#define ABILITY_LIGHT_METAL 135 -#define ABILITY_MULTISCALE 136 -#define ABILITY_TOXIC_BOOST 137 -#define ABILITY_FLARE_BOOST 138 -#define ABILITY_HARVEST 139 -#define ABILITY_TELEPATHY 140 -#define ABILITY_MOODY 141 -#define ABILITY_OVERCOAT 142 -#define ABILITY_POISON_TOUCH 143 -#define ABILITY_REGENERATOR 144 -#define ABILITY_BIG_PECKS 145 -#define ABILITY_SAND_RUSH 146 -#define ABILITY_WONDER_SKIN 147 -#define ABILITY_ANALYTIC 148 -#define ABILITY_ILLUSION 149 -#define ABILITY_IMPOSTER 150 -#define ABILITY_INFILTRATOR 151 -#define ABILITY_MUMMY 152 -#define ABILITY_MOXIE 153 -#define ABILITY_JUSTIFIED 154 -#define ABILITY_RATTLED 155 -#define ABILITY_MAGIC_BOUNCE 156 -#define ABILITY_SAP_SIPPER 157 -#define ABILITY_PRANKSTER 158 -#define ABILITY_SAND_FORCE 159 -#define ABILITY_IRON_BARBS 160 -#define ABILITY_ZEN_MODE 161 -#define ABILITY_VICTORY_STAR 162 -#define ABILITY_TURBOBLAZE 163 -#define ABILITY_TERAVOLT 164 + // Gen 7 + ABILITY_STAMINA = ABILITIES_COUNT_GEN6, + ABILITY_WIMP_OUT = 193, + ABILITY_EMERGENCY_EXIT = 194, + ABILITY_WATER_COMPACTION = 195, + ABILITY_MERCILESS = 196, + ABILITY_SHIELDS_DOWN = 197, + ABILITY_STAKEOUT = 198, + ABILITY_WATER_BUBBLE = 199, + ABILITY_STEELWORKER = 200, + ABILITY_BERSERK = 201, + ABILITY_SLUSH_RUSH = 202, + ABILITY_LONG_REACH = 203, + ABILITY_LIQUID_VOICE = 204, + ABILITY_TRIAGE = 205, + ABILITY_GALVANIZE = 206, + ABILITY_SURGE_SURFER = 207, + ABILITY_SCHOOLING = 208, + ABILITY_DISGUISE = 209, + ABILITY_BATTLE_BOND = 210, + ABILITY_POWER_CONSTRUCT = 211, + ABILITY_CORROSION = 212, + ABILITY_COMATOSE = 213, + ABILITY_QUEENLY_MAJESTY = 214, + ABILITY_INNARDS_OUT = 215, + ABILITY_DANCER = 216, + ABILITY_BATTERY = 217, + ABILITY_FLUFFY = 218, + ABILITY_DAZZLING = 219, + ABILITY_SOUL_HEART = 220, + ABILITY_TANGLING_HAIR = 221, + ABILITY_RECEIVER = 222, + ABILITY_POWER_OF_ALCHEMY = 223, + ABILITY_BEAST_BOOST = 224, + ABILITY_RKS_SYSTEM = 225, + ABILITY_ELECTRIC_SURGE = 226, + ABILITY_PSYCHIC_SURGE = 227, + ABILITY_MISTY_SURGE = 228, + ABILITY_GRASSY_SURGE = 229, + ABILITY_FULL_METAL_BODY = 230, + ABILITY_SHADOW_SHIELD = 231, + ABILITY_PRISM_ARMOR = 232, + ABILITY_NEUROFORCE = 233, + ABILITIES_COUNT_GEN7, -#define ABILITIES_COUNT_GEN5 165 + // Gen 8 + ABILITY_INTREPID_SWORD = ABILITIES_COUNT_GEN7, + ABILITY_DAUNTLESS_SHIELD = 235, + ABILITY_LIBERO = 236, + ABILITY_BALL_FETCH = 237, + ABILITY_COTTON_DOWN = 238, + ABILITY_PROPELLER_TAIL = 239, + ABILITY_MIRROR_ARMOR = 240, + ABILITY_GULP_MISSILE = 241, + ABILITY_STALWART = 242, + ABILITY_STEAM_ENGINE = 243, + ABILITY_PUNK_ROCK = 244, + ABILITY_SAND_SPIT = 245, + ABILITY_ICE_SCALES = 246, + ABILITY_RIPEN = 247, + ABILITY_ICE_FACE = 248, + ABILITY_POWER_SPOT = 249, + ABILITY_MIMICRY = 250, + ABILITY_SCREEN_CLEANER = 251, + ABILITY_STEELY_SPIRIT = 252, + ABILITY_PERISH_BODY = 253, + ABILITY_WANDERING_SPIRIT = 254, + ABILITY_GORILLA_TACTICS = 255, + ABILITY_NEUTRALIZING_GAS = 256, + ABILITY_PASTEL_VEIL = 257, + ABILITY_HUNGER_SWITCH = 258, + ABILITY_QUICK_DRAW = 259, + ABILITY_UNSEEN_FIST = 260, + ABILITY_CURIOUS_MEDICINE = 261, + ABILITY_TRANSISTOR = 262, + ABILITY_DRAGONS_MAW = 263, + ABILITY_CHILLING_NEIGH = 264, + ABILITY_GRIM_NEIGH = 265, + ABILITY_AS_ONE_ICE_RIDER = 266, + ABILITY_AS_ONE_SHADOW_RIDER = 267, + ABILITIES_COUNT_GEN8, -// Gen 6 -#define ABILITY_AROMA_VEIL 165 -#define ABILITY_FLOWER_VEIL 166 -#define ABILITY_CHEEK_POUCH 167 -#define ABILITY_PROTEAN 168 -#define ABILITY_FUR_COAT 169 -#define ABILITY_MAGICIAN 170 -#define ABILITY_BULLETPROOF 171 -#define ABILITY_COMPETITIVE 172 -#define ABILITY_STRONG_JAW 173 -#define ABILITY_REFRIGERATE 174 -#define ABILITY_SWEET_VEIL 175 -#define ABILITY_STANCE_CHANGE 176 -#define ABILITY_GALE_WINGS 177 -#define ABILITY_MEGA_LAUNCHER 178 -#define ABILITY_GRASS_PELT 179 -#define ABILITY_SYMBIOSIS 180 -#define ABILITY_TOUGH_CLAWS 181 -#define ABILITY_PIXILATE 182 -#define ABILITY_GOOEY 183 -#define ABILITY_AERILATE 184 -#define ABILITY_PARENTAL_BOND 185 -#define ABILITY_DARK_AURA 186 -#define ABILITY_FAIRY_AURA 187 -#define ABILITY_AURA_BREAK 188 -#define ABILITY_PRIMORDIAL_SEA 189 -#define ABILITY_DESOLATE_LAND 190 -#define ABILITY_DELTA_STREAM 191 - -#define ABILITIES_COUNT_GEN6 192 - -// Gen 7 -#define ABILITY_STAMINA 192 -#define ABILITY_WIMP_OUT 193 -#define ABILITY_EMERGENCY_EXIT 194 -#define ABILITY_WATER_COMPACTION 195 -#define ABILITY_MERCILESS 196 -#define ABILITY_SHIELDS_DOWN 197 -#define ABILITY_STAKEOUT 198 -#define ABILITY_WATER_BUBBLE 199 -#define ABILITY_STEELWORKER 200 -#define ABILITY_BERSERK 201 -#define ABILITY_SLUSH_RUSH 202 -#define ABILITY_LONG_REACH 203 -#define ABILITY_LIQUID_VOICE 204 -#define ABILITY_TRIAGE 205 -#define ABILITY_GALVANIZE 206 -#define ABILITY_SURGE_SURFER 207 -#define ABILITY_SCHOOLING 208 -#define ABILITY_DISGUISE 209 -#define ABILITY_BATTLE_BOND 210 -#define ABILITY_POWER_CONSTRUCT 211 -#define ABILITY_CORROSION 212 -#define ABILITY_COMATOSE 213 -#define ABILITY_QUEENLY_MAJESTY 214 -#define ABILITY_INNARDS_OUT 215 -#define ABILITY_DANCER 216 -#define ABILITY_BATTERY 217 -#define ABILITY_FLUFFY 218 -#define ABILITY_DAZZLING 219 -#define ABILITY_SOUL_HEART 220 -#define ABILITY_TANGLING_HAIR 221 -#define ABILITY_RECEIVER 222 -#define ABILITY_POWER_OF_ALCHEMY 223 -#define ABILITY_BEAST_BOOST 224 -#define ABILITY_RKS_SYSTEM 225 -#define ABILITY_ELECTRIC_SURGE 226 -#define ABILITY_PSYCHIC_SURGE 227 -#define ABILITY_MISTY_SURGE 228 -#define ABILITY_GRASSY_SURGE 229 -#define ABILITY_FULL_METAL_BODY 230 -#define ABILITY_SHADOW_SHIELD 231 -#define ABILITY_PRISM_ARMOR 232 -#define ABILITY_NEUROFORCE 233 - -#define ABILITIES_COUNT_GEN7 234 - -// Gen 8 -#define ABILITY_INTREPID_SWORD 234 -#define ABILITY_DAUNTLESS_SHIELD 235 -#define ABILITY_LIBERO 236 -#define ABILITY_BALL_FETCH 237 -#define ABILITY_COTTON_DOWN 238 -#define ABILITY_PROPELLER_TAIL 239 -#define ABILITY_MIRROR_ARMOR 240 -#define ABILITY_GULP_MISSILE 241 -#define ABILITY_STALWART 242 -#define ABILITY_STEAM_ENGINE 243 -#define ABILITY_PUNK_ROCK 244 -#define ABILITY_SAND_SPIT 245 -#define ABILITY_ICE_SCALES 246 -#define ABILITY_RIPEN 247 -#define ABILITY_ICE_FACE 248 -#define ABILITY_POWER_SPOT 249 -#define ABILITY_MIMICRY 250 -#define ABILITY_SCREEN_CLEANER 251 -#define ABILITY_STEELY_SPIRIT 252 -#define ABILITY_PERISH_BODY 253 -#define ABILITY_WANDERING_SPIRIT 254 -#define ABILITY_GORILLA_TACTICS 255 -#define ABILITY_NEUTRALIZING_GAS 256 -#define ABILITY_PASTEL_VEIL 257 -#define ABILITY_HUNGER_SWITCH 258 -#define ABILITY_QUICK_DRAW 259 -#define ABILITY_UNSEEN_FIST 260 -#define ABILITY_CURIOUS_MEDICINE 261 -#define ABILITY_TRANSISTOR 262 -#define ABILITY_DRAGONS_MAW 263 -#define ABILITY_CHILLING_NEIGH 264 -#define ABILITY_GRIM_NEIGH 265 -#define ABILITY_AS_ONE_ICE_RIDER 266 -#define ABILITY_AS_ONE_SHADOW_RIDER 267 - -#define ABILITIES_COUNT_GEN8 268 - -// Gen 9 -#define ABILITY_LINGERING_AROMA 268 -#define ABILITY_SEED_SOWER 269 -#define ABILITY_THERMAL_EXCHANGE 270 -#define ABILITY_ANGER_SHELL 271 -#define ABILITY_PURIFYING_SALT 272 -#define ABILITY_WELL_BAKED_BODY 273 -#define ABILITY_WIND_RIDER 274 -#define ABILITY_GUARD_DOG 275 -#define ABILITY_ROCKY_PAYLOAD 276 -#define ABILITY_WIND_POWER 277 -#define ABILITY_ZERO_TO_HERO 278 -#define ABILITY_COMMANDER 279 -#define ABILITY_ELECTROMORPHOSIS 280 -#define ABILITY_PROTOSYNTHESIS 281 -#define ABILITY_QUARK_DRIVE 282 -#define ABILITY_GOOD_AS_GOLD 283 -#define ABILITY_VESSEL_OF_RUIN 284 -#define ABILITY_SWORD_OF_RUIN 285 -#define ABILITY_TABLETS_OF_RUIN 286 -#define ABILITY_BEADS_OF_RUIN 287 -#define ABILITY_ORICHALCUM_PULSE 288 -#define ABILITY_HADRON_ENGINE 289 -#define ABILITY_OPPORTUNIST 290 -#define ABILITY_CUD_CHEW 291 -#define ABILITY_SHARPNESS 292 -#define ABILITY_SUPREME_OVERLORD 293 -#define ABILITY_COSTAR 294 -#define ABILITY_TOXIC_DEBRIS 295 -#define ABILITY_ARMOR_TAIL 296 -#define ABILITY_EARTH_EATER 297 -#define ABILITY_MYCELIUM_MIGHT 298 -#define ABILITY_HOSPITALITY 299 -#define ABILITY_MINDS_EYE 300 -#define ABILITY_EMBODY_ASPECT_TEAL_MASK 301 -#define ABILITY_EMBODY_ASPECT_HEARTHFLAME_MASK 302 -#define ABILITY_EMBODY_ASPECT_WELLSPRING_MASK 303 -#define ABILITY_EMBODY_ASPECT_CORNERSTONE_MASK 304 -#define ABILITY_TOXIC_CHAIN 305 -#define ABILITY_SUPERSWEET_SYRUP 306 -#define ABILITY_TERA_SHIFT 307 -#define ABILITY_TERA_SHELL 308 -#define ABILITY_TERAFORM_ZERO 309 -#define ABILITY_POISON_PUPPETEER 310 - -#define ABILITIES_COUNT_GEN9 311 - -#define ABILITIES_COUNT ABILITIES_COUNT_GEN9 + // Gen 9 + ABILITY_LINGERING_AROMA = ABILITIES_COUNT_GEN8, + ABILITY_SEED_SOWER = 269, + ABILITY_THERMAL_EXCHANGE = 270, + ABILITY_ANGER_SHELL = 271, + ABILITY_PURIFYING_SALT = 272, + ABILITY_WELL_BAKED_BODY = 273, + ABILITY_WIND_RIDER = 274, + ABILITY_GUARD_DOG = 275, + ABILITY_ROCKY_PAYLOAD = 276, + ABILITY_WIND_POWER = 277, + ABILITY_ZERO_TO_HERO = 278, + ABILITY_COMMANDER = 279, + ABILITY_ELECTROMORPHOSIS = 280, + ABILITY_PROTOSYNTHESIS = 281, + ABILITY_QUARK_DRIVE = 282, + ABILITY_GOOD_AS_GOLD = 283, + ABILITY_VESSEL_OF_RUIN = 284, + ABILITY_SWORD_OF_RUIN = 285, + ABILITY_TABLETS_OF_RUIN = 286, + ABILITY_BEADS_OF_RUIN = 287, + ABILITY_ORICHALCUM_PULSE = 288, + ABILITY_HADRON_ENGINE = 289, + ABILITY_OPPORTUNIST = 290, + ABILITY_CUD_CHEW = 291, + ABILITY_SHARPNESS = 292, + ABILITY_SUPREME_OVERLORD = 293, + ABILITY_COSTAR = 294, + ABILITY_TOXIC_DEBRIS = 295, + ABILITY_ARMOR_TAIL = 296, + ABILITY_EARTH_EATER = 297, + ABILITY_MYCELIUM_MIGHT = 298, + ABILITY_HOSPITALITY = 299, + ABILITY_MINDS_EYE = 300, + ABILITY_EMBODY_ASPECT_TEAL_MASK = 301, + ABILITY_EMBODY_ASPECT_HEARTHFLAME_MASK = 302, + ABILITY_EMBODY_ASPECT_WELLSPRING_MASK = 303, + ABILITY_EMBODY_ASPECT_CORNERSTONE_MASK = 304, + ABILITY_TOXIC_CHAIN = 305, + ABILITY_SUPERSWEET_SYRUP = 306, + ABILITY_TERA_SHIFT = 307, + ABILITY_TERA_SHELL = 308, + ABILITY_TERAFORM_ZERO = 309, + ABILITY_POISON_PUPPETEER = 310, + ABILITIES_COUNT_GEN9, + ABILITIES_COUNT = ABILITIES_COUNT_GEN9, +}; #endif // GUARD_CONSTANTS_ABILITIES_H diff --git a/include/constants/apricorn_tree.h b/include/constants/apricorn_tree.h new file mode 100644 index 0000000000..14b111adbd --- /dev/null +++ b/include/constants/apricorn_tree.h @@ -0,0 +1,90 @@ +#ifndef GUARD_CONSTANTS_APRICORN_TREE_H +#define GUARD_CONSTANTS_APRICORN_TREE_H + +#include "constants/items.h" + +// Apricorn lookup table, added to allow adding new apricorns without being forced to rearrange the item constants. +enum ApricornType +{ + APRICORN_RED = ITEM_RED_APRICORN, + APRICORN_BLUE = ITEM_BLUE_APRICORN, + APRICORN_YELLOW = ITEM_YELLOW_APRICORN, + APRICORN_GREEN = ITEM_GREEN_APRICORN, + APRICORN_PINK = ITEM_PINK_APRICORN, + APRICORN_WHITE = ITEM_WHITE_APRICORN, + APRICORN_BLACK = ITEM_BLACK_APRICORN, + APRICORN_BERRY_CHERI = ITEM_CHERI_BERRY, + APRICORN_BERRY_CHESTO = ITEM_CHESTO_BERRY, + APRICORN_BERRY_PECHA = ITEM_PECHA_BERRY, + APRICORN_BERRY_RAWST = ITEM_RAWST_BERRY, + APRICORN_BERRY_ASPEAR = ITEM_ASPEAR_BERRY, + APRICORN_BERRY_LEPPA = ITEM_LEPPA_BERRY, + APRICORN_BERRY_ORAN = ITEM_ORAN_BERRY, + APRICORN_BERRY_PERSIM = ITEM_PERSIM_BERRY, + APRICORN_BERRY_LUM = ITEM_LUM_BERRY, + APRICORN_BERRY_SITRUS = ITEM_SITRUS_BERRY, + APRICORN_BERRY_FIGY = ITEM_FIGY_BERRY, + APRICORN_BERRY_WIKI = ITEM_WIKI_BERRY, + APRICORN_BERRY_MAGO = ITEM_MAGO_BERRY, + APRICORN_BERRY_AGUAV = ITEM_AGUAV_BERRY, + APRICORN_BERRY_IAPAPA = ITEM_IAPAPA_BERRY, + APRICORN_BERRY_RAZZ = ITEM_RAZZ_BERRY, + APRICORN_BERRY_BLUK = ITEM_BLUK_BERRY, + APRICORN_BERRY_NANAB = ITEM_NANAB_BERRY, + APRICORN_BERRY_WEPEAR = ITEM_WEPEAR_BERRY, + APRICORN_BERRY_PINAP = ITEM_PINAP_BERRY, + APRICORN_BERRY_POMEG = ITEM_POMEG_BERRY, + APRICORN_BERRY_KELPSY = ITEM_KELPSY_BERRY, + APRICORN_BERRY_QUALOT = ITEM_QUALOT_BERRY, + APRICORN_BERRY_HONDEW = ITEM_HONDEW_BERRY, + APRICORN_BERRY_GREPA = ITEM_GREPA_BERRY, + APRICORN_BERRY_TAMATO = ITEM_TAMATO_BERRY, + APRICORN_BERRY_CORNN = ITEM_CORNN_BERRY, + APRICORN_BERRY_MAGOST = ITEM_MAGOST_BERRY, + APRICORN_BERRY_RABUTA = ITEM_RABUTA_BERRY, + APRICORN_BERRY_NOMEL = ITEM_NOMEL_BERRY, + APRICORN_BERRY_SPELON = ITEM_SPELON_BERRY, + APRICORN_BERRY_PAMTRE = ITEM_PAMTRE_BERRY, + APRICORN_BERRY_WATMEL = ITEM_WATMEL_BERRY, + APRICORN_BERRY_DURIN = ITEM_DURIN_BERRY, + APRICORN_BERRY_BELUE = ITEM_BELUE_BERRY, + APRICORN_BERRY_OCCA = ITEM_OCCA_BERRY, + APRICORN_BERRY_PASSHO = ITEM_PASSHO_BERRY, + APRICORN_BERRY_WACAN = ITEM_WACAN_BERRY, + APRICORN_BERRY_RINDO = ITEM_RINDO_BERRY, + APRICORN_BERRY_YACHE = ITEM_YACHE_BERRY, + APRICORN_BERRY_CHOPLE = ITEM_CHOPLE_BERRY, + APRICORN_BERRY_KEBIA = ITEM_KEBIA_BERRY, + APRICORN_BERRY_SHUCA = ITEM_SHUCA_BERRY, + APRICORN_BERRY_COBA = ITEM_COBA_BERRY, + APRICORN_BERRY_PAYAPA = ITEM_PAYAPA_BERRY, + APRICORN_BERRY_TANGA = ITEM_TANGA_BERRY, + APRICORN_BERRY_CHARTI = ITEM_CHARTI_BERRY, + APRICORN_BERRY_KASIB = ITEM_KASIB_BERRY, + APRICORN_BERRY_HABAN = ITEM_HABAN_BERRY, + APRICORN_BERRY_COLBUR = ITEM_COLBUR_BERRY, + APRICORN_BERRY_BABIRI = ITEM_BABIRI_BERRY, + APRICORN_BERRY_CHILAN = ITEM_CHILAN_BERRY, + APRICORN_BERRY_LIECHI = ITEM_LIECHI_BERRY, + APRICORN_BERRY_GANLON = ITEM_GANLON_BERRY, + APRICORN_BERRY_SALAC = ITEM_SALAC_BERRY, + APRICORN_BERRY_PETAYA = ITEM_PETAYA_BERRY, + APRICORN_BERRY_APICOT = ITEM_APICOT_BERRY, + APRICORN_BERRY_LANSAT = ITEM_LANSAT_BERRY, + APRICORN_BERRY_STARF = ITEM_STARF_BERRY, + APRICORN_BERRY_ENIGMA = ITEM_ENIGMA_BERRY, + APRICORN_BERRY_MICLE = ITEM_MICLE_BERRY, + APRICORN_BERRY_CUSTAP = ITEM_CUSTAP_BERRY, + APRICORN_BERRY_JABOCA = ITEM_JABOCA_BERRY, + APRICORN_BERRY_ROWAP = ITEM_ROWAP_BERRY, + APRICORN_BERRY_ROSELI = ITEM_ROSELI_BERRY, + APRICORN_BERRY_KEE = ITEM_KEE_BERRY, + APRICORN_BERRY_MARANGA = ITEM_MARANGA_BERRY, +}; + +// Trees +#define APRICORN_TREE_NONE 0 + +#define APRICORN_TREE_COUNT 0 + +#endif //GUARD_CONSTANTS_APRICORN_TREE_H diff --git a/include/constants/battle.h b/include/constants/battle.h index 8527ec800f..97639edfd1 100644 --- a/include/constants/battle.h +++ b/include/constants/battle.h @@ -1,6 +1,8 @@ #ifndef GUARD_CONSTANTS_BATTLE_H #define GUARD_CONSTANTS_BATTLE_H +#include "constants/moves.h" + /* * A battler may be in one of four positions on the field. The first bit determines * what side the battler is on, either the player's side or the opponent's side. @@ -45,9 +47,17 @@ enum BattlerId #define BATTLE_OPPOSITE(id) ((id) ^ BIT_SIDE) #define BATTLE_PARTNER(id) ((id) ^ BIT_FLANK) -#define B_SIDE_PLAYER 0 -#define B_SIDE_OPPONENT 1 -#define NUM_BATTLE_SIDES 2 +// Left and right are determined by how they're referred to in tests and everywhere else. +// Left is battlers 0 and 1, right 2 and 3; if you assume the battler referencing them is south, left is to the northeast and right to the northwest. +#define LEFT_FOE(battler) ((BATTLE_OPPOSITE(battler)) & BIT_SIDE) +#define RIGHT_FOE(battler) (((BATTLE_OPPOSITE(battler)) & BIT_SIDE) | BIT_FLANK) + +enum BattleSide +{ + B_SIDE_PLAYER = 0, + B_SIDE_OPPONENT = 1, + NUM_BATTLE_SIDES = 2, +}; #define B_FLANK_LEFT 0 #define B_FLANK_RIGHT 1 @@ -95,12 +105,17 @@ enum BattlerId | BATTLE_TYPE_LEGENDARY \ | BATTLE_TYPE_RECORDED | BATTLE_TYPE_TRAINER_HILL | BATTLE_TYPE_SECRET_BASE)) -#define WILD_DOUBLE_BATTLE ((gBattleTypeFlags & BATTLE_TYPE_DOUBLE && !(gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_TRAINER)))) -#define RECORDED_WILD_BATTLE ((gBattleTypeFlags & BATTLE_TYPE_RECORDED) && !(gBattleTypeFlags & (BATTLE_TYPE_TRAINER | BATTLE_TYPE_FRONTIER))) -#define BATTLE_TWO_VS_ONE_OPPONENT ((gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER && TRAINER_BATTLE_PARAM.opponentB == 0xFFFF)) -#define BATTLE_TYPE_HAS_AI (BATTLE_TYPE_TRAINER | BATTLE_TYPE_FIRST_BATTLE | BATTLE_TYPE_SAFARI | BATTLE_TYPE_ROAMER | BATTLE_TYPE_INGAME_PARTNER) +#define WILD_DOUBLE_BATTLE ((gBattleTypeFlags & BATTLE_TYPE_DOUBLE && !(gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_TRAINER)))) +#define RECORDED_WILD_BATTLE ((gBattleTypeFlags & BATTLE_TYPE_RECORDED) && !(gBattleTypeFlags & (BATTLE_TYPE_TRAINER | BATTLE_TYPE_FRONTIER))) +#define BATTLE_TWO_VS_ONE_OPPONENT ((gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER && TRAINER_BATTLE_PARAM.opponentB == 0xFFFF)) +#define BATTLE_TYPE_HAS_AI (BATTLE_TYPE_TRAINER | BATTLE_TYPE_FIRST_BATTLE | BATTLE_TYPE_SAFARI | BATTLE_TYPE_ROAMER | BATTLE_TYPE_INGAME_PARTNER) +#define BATTLE_TYPE_MORE_THAN_TWO_BATTLERS (BATTLE_TYPE_DOUBLE | BATTLE_TYPE_MULTI | BATTLE_TYPE_INGAME_PARTNER | BATTLE_TYPE_TWO_OPPONENTS) #define BATTLE_TYPE_PLAYER_HAS_PARTNER (BATTLE_TYPE_MULTI | BATTLE_TYPE_INGAME_PARTNER | BATTLE_TYPE_TOWER_LINK_MULTI) +// Multibattle test composite flags +#define BATTLE_MULTI_TEST (BATTLE_TYPE_IS_MASTER | BATTLE_TYPE_TRAINER | BATTLE_TYPE_INGAME_PARTNER | BATTLE_TYPE_MULTI | BATTLE_TYPE_TWO_OPPONENTS) +#define BATTLE_TWO_VS_ONE_TEST (BATTLE_TYPE_IS_MASTER | BATTLE_TYPE_TRAINER | BATTLE_TYPE_INGAME_PARTNER | BATTLE_TYPE_MULTI) + // Battle Outcome defines #define B_OUTCOME_WON 1 #define B_OUTCOME_LOST 2 @@ -155,6 +170,8 @@ enum VolatileFlags F(VOLATILE_LOCK_CONFUSE, lockConfusionTurns, (u32, 3)) \ F(VOLATILE_MULTIPLETURNS, multipleTurns, (u32, 1)) \ F(VOLATILE_WRAPPED, wrapped, (u32, 1)) \ + F(VOLATILE_WRAPPED_BY, wrappedBy, (enum BattlerId, MAX_BITS(4))) \ + F(VOLATILE_WRAPPED_MOVE, wrappedMove, (u32, MOVES_COUNT_ALL - 1)) \ F(VOLATILE_POWDER, powder, (u32, 1)) \ F(VOLATILE_UNUSED, padding, (u32, 1)) \ F(VOLATILE_INFATUATION, infatuation, (enum BattlerId, MAX_BITS(4))) \ @@ -162,13 +179,14 @@ enum VolatileFlags F(VOLATILE_TRANSFORMED, transformed, (u32, 1)) \ F(VOLATILE_RAGE, rage, (u32, 1)) \ F(VOLATILE_SUBSTITUTE, substitute, (u32, 1), V_BATON_PASSABLE) \ - F(VOLATILE_DESTINY_BOND, destinyBond, (u32, 1)) \ + F(VOLATILE_DESTINY_BOND, destinyBond, (u32, 2)) \ F(VOLATILE_ESCAPE_PREVENTION, escapePrevention, (u32, 1), V_BATON_PASSABLE) \ F(VOLATILE_NIGHTMARE, nightmare, (u32, 1)) \ F(VOLATILE_CURSED, cursed, (u32, 1), V_BATON_PASSABLE) \ F(VOLATILE_FORESIGHT, foresight, (u32, 1)) \ F(VOLATILE_DRAGON_CHEER, dragonCheer, (u32, 1), V_BATON_PASSABLE) \ F(VOLATILE_FOCUS_ENERGY, focusEnergy, (u32, 1), V_BATON_PASSABLE) \ + F(VOLATILE_BONUS_CRIT_STAGES, bonusCritStages, (u32, 3)) \ F(VOLATILE_SEMI_INVULNERABLE, semiInvulnerable, (u32, SEMI_INVULNERABLE_COUNT - 1)) \ F(VOLATILE_ELECTRIFIED, electrified, (u32, 1)) \ F(VOLATILE_MUD_SPORT, mudSport, (u32, 1), V_BATON_PASSABLE) \ @@ -176,12 +194,13 @@ enum VolatileFlags F(VOLATILE_INFINITE_CONFUSION, infiniteConfusion, (u32, 1), V_BATON_PASSABLE) \ F(VOLATILE_SALT_CURE, saltCure, (u32, 1)) \ F(VOLATILE_SYRUP_BOMB, syrupBomb, (u32, 1)) \ + F(VOLATILE_STICKY_SYRUPED_BY, stickySyrupedBy, (enum BattlerId, MAX_BITS(4))) \ F(VOLATILE_GLAIVE_RUSH, glaiveRush, (u32, 1)) \ F(VOLATILE_LEECH_SEED, leechSeed, (enum BattlerId, MAX_BITS(4)), V_BATON_PASSABLE) \ F(VOLATILE_LOCK_ON, lockOn, (u32, 2), V_BATON_PASSABLE) \ F(VOLATILE_PERISH_SONG, perishSong, (u32, 1), V_BATON_PASSABLE) \ F(VOLATILE_MINIMIZE, minimize, (u32, 1)) \ - F(VOLATILE_CHARGE, charge, (u32, 1)) \ + F(VOLATILE_CHARGE_TIMER, chargeTimer, (u32, 2)) \ F(VOLATILE_ROOT, root, (u32, 1), V_BATON_PASSABLE) \ F(VOLATILE_YAWN, yawn, (u32, 2)) \ F(VOLATILE_IMPRISON, imprison, (u32, 1)) \ @@ -195,7 +214,12 @@ enum VolatileFlags F(VOLATILE_HEAL_BLOCK, healBlock, (u32, 1), V_BATON_PASSABLE) \ F(VOLATILE_AQUA_RING, aquaRing, (u32, 1), V_BATON_PASSABLE) \ F(VOLATILE_LASER_FOCUS, laserFocus, (u32, 1)) \ - F(VOLATILE_POWER_TRICK, powerTrick, (u32, 1), V_BATON_PASSABLE) + F(VOLATILE_POWER_TRICK, powerTrick, (u32, 1), V_BATON_PASSABLE) \ + F(VOLATILE_NO_RETREAT, noRetreat, (u32, 1), V_BATON_PASSABLE) \ + F(VOLATILE_VESSEL_OF_RUIN, vesselOfRuin, (u32, 1)) \ + F(VOLATILE_SWORD_OF_RUIN, swordOfRuin, (u32, 1)) \ + F(VOLATILE_TABLETS_OF_RUIN, tabletsOfRuin, (u32, 1)) \ + F(VOLATILE_BEADS_OF_RUIN, beadsOfRuin, (u32, 1)) /* Use within a macro to get the maximum allowed value for a volatile. Requires _typeMaxValue as input. */ @@ -233,46 +257,41 @@ enum SemiInvulnerableExclusion EXCLUDE_COMMANDER, }; -#define HITMARKER_STRING_PRINTED (1 << 4) -#define HITMARKER_IGNORE_BIDE (1 << 5) -#define HITMARKER_DESTINYBOND (1 << 6) #define HITMARKER_NO_ANIMATIONS (1 << 7) // set from battleSceneOff. Never changed during battle -#define HITMARKER_IGNORE_SUBSTITUTE (1 << 8) -#define HITMARKER_NO_ATTACKSTRING (1 << 9) -#define HITMARKER_ATTACKSTRING_PRINTED (1 << 10) -#define HITMARKER_NO_PPDEDUCT (1 << 11) +#define HITMARKER_UNUSED_8 (1 << 8) +#define HITMARKER_UNUSED_9 (1 << 9) +#define HITMARKER_UNUSED_10 (1 << 10) +#define HITMARKER_UNUSED_11 (1 << 11) #define HITMARKER_UNUSED_12 (1 << 12) -#define HITMARKER_STATUS_ABILITY_EFFECT (1 << 13) +#define HITMARKER_UNUSED_13 (1 << 13) #define HITMARKER_UNUSED_14 (1 << 14) #define HITMARKER_RUN (1 << 15) -#define HITMARKER_IGNORE_DISGUISE (1 << 16) +#define HITMARKER_UNUSED_16 (1 << 16) #define HITMARKER_DISABLE_ANIMATION (1 << 17) // disable animations during battle scripts, e.g. for Bug Bite #define HITMARKER_UNUSED_18 (1 << 18) #define HITMARKER_UNABLE_TO_USE_MOVE (1 << 19) -#define HITMARKER_PASSIVE_HP_UPDATE (1 << 20) +#define HITMARKER_UNUSED_20 (1 << 20) #define HITMARKER_UNUSED_21 (1 << 21) #define HITMARKER_PLAYER_FAINTED (1 << 22) -#define HITMARKER_ALLOW_NO_PP (1 << 23) -#define HITMARKER_GRUDGE (1 << 24) +#define HITMARKER_UNUSED_23 (1 << 23) +#define HITMARKER_UNUSED_24 (1 << 24) #define HITMARKER_OBEYS (1 << 25) #define HITMARKER_UNUSED_26 (1 << 26) #define HITMARKER_UNUSED_27 (1 << 27) -#define HITMARKER_FAINTED(battler) (1u << (battler + 28)) -#define HITMARKER_FAINTED2(battler) HITMARKER_FAINTED(battler) +#define HITMARKER_FAINTED(battler) (1u << (battler + 28)) // Also uses bits 29, 30 and 31 // Per-side statuses that affect an entire party #define SIDE_STATUS_REFLECT (1 << 0) #define SIDE_STATUS_LIGHTSCREEN (1 << 1) #define SIDE_STATUS_SAFEGUARD (1 << 2) -#define SIDE_STATUS_FUTUREATTACK (1 << 3) -#define SIDE_STATUS_MIST (1 << 4) -#define SIDE_STATUS_TAILWIND (1 << 5) -#define SIDE_STATUS_AURORA_VEIL (1 << 6) -#define SIDE_STATUS_LUCKY_CHANT (1 << 7) -#define SIDE_STATUS_DAMAGE_NON_TYPES (1 << 8) -#define SIDE_STATUS_RAINBOW (1 << 9) -#define SIDE_STATUS_SEA_OF_FIRE (1 << 10) -#define SIDE_STATUS_SWAMP (1 << 11) +#define SIDE_STATUS_MIST (1 << 3) +#define SIDE_STATUS_TAILWIND (1 << 4) +#define SIDE_STATUS_AURORA_VEIL (1 << 5) +#define SIDE_STATUS_LUCKY_CHANT (1 << 6) +#define SIDE_STATUS_DAMAGE_NON_TYPES (1 << 7) +#define SIDE_STATUS_RAINBOW (1 << 8) +#define SIDE_STATUS_SEA_OF_FIRE (1 << 9) +#define SIDE_STATUS_SWAMP (1 << 10) #define SIDE_STATUS_SCREEN_ANY (SIDE_STATUS_REFLECT | SIDE_STATUS_LIGHTSCREEN | SIDE_STATUS_AURORA_VEIL) #define SIDE_STATUS_PLEDGE_ANY (SIDE_STATUS_RAINBOW | SIDE_STATUS_SEA_OF_FIRE | SIDE_STATUS_SWAMP) @@ -639,6 +658,17 @@ enum BattleEnvironments // Constants for Torment #define PERMANENT_TORMENT 0xF +enum FaintedActions +{ + FAINTED_ACTIONS_NO_MONS_TO_SWITCH, + FAINTED_ACTIONS_GIVE_EXP, + FAINTED_ACTIONS_SET_ABSENT_FLAGS, + FAINTED_ACTIONS_WAIT_STATE, + FAINTED_ACTIONS_HANDLE_FAINTED_MON, + FAINTED_ACTIONS_HANDLE_NEXT_BATTLER, + FAINTED_ACTIONS_MAX_CASE, +}; + // Constants for B_VAR_STARTING_STATUS // Timer value controlled by B_VAR_STARTING_STATUS_TIMER enum StartingStatus @@ -680,4 +710,11 @@ enum __attribute__((packed)) CalcDamageState CHECK_ACCURACY, }; +enum SubmoveState +{ + SUBMOVE_NO_EFFECT, + SUBMOVE_SUCCESS, + SUBMOVE_FAILURE, +}; + #endif // GUARD_CONSTANTS_BATTLE_H diff --git a/include/constants/battle_ai.h b/include/constants/battle_ai.h index c6277bf9b5..89cfd08ed0 100644 --- a/include/constants/battle_ai.h +++ b/include/constants/battle_ai.h @@ -38,6 +38,7 @@ #define AI_FLAG_ASSUME_STAB AI_FLAG(28) // AI knows player's STAB moves, but nothing else. Restricted version of AI_FLAG_OMNISCIENT. #define AI_FLAG_ASSUME_STATUS_MOVES AI_FLAG(29) // AI has a chance to know certain non-damaging moves, and also Fake Out and Super Fang. Restricted version of AI_FLAG_OMNISCIENT. #define AI_FLAG_ATTACKS_PARTNER AI_FLAG(30) // AI specific to double battles; AI can deliberately attack its 'partner.' +#define AI_FLAG_KNOW_OPPONENT_PARTY AI_FLAG(31) // AI knows all the species in the player's party, but not moves/items/abilities unless they've been seen. // The following options are enough to have a basic/smart trainer. Any other addtion could make the trainer worse/better depending on the flag #define AI_FLAG_BASIC_TRAINER (AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY) diff --git a/include/constants/battle_anim.h b/include/constants/battle_anim.h index e169b29cf3..6ac604798f 100644 --- a/include/constants/battle_anim.h +++ b/include/constants/battle_anim.h @@ -592,8 +592,9 @@ #define B_ANIM_TERA_ACTIVATE 51 #define B_ANIM_SIMPLE_HEAL 52 #define B_ANIM_POWER_CONSTRUCT 53 - -#define NUM_B_ANIMS_GENERAL 54 +#define B_ANIM_SWAP_TO_SUBSTITUTE 54 +#define B_ANIM_SWAP_FROM_SUBSTITUTE 55 +#define NUM_B_ANIMS_GENERAL 56 // special animations table (sBattleAnims_Special) #define B_ANIM_LVL_UP 0 @@ -617,8 +618,9 @@ #define B_ANIM_STATUS_FRZ 6 #define B_ANIM_STATUS_CURSED 7 #define B_ANIM_STATUS_NIGHTMARE 8 +#define B_ANIM_STATUS_FRB 9 -#define NUM_B_ANIMS_STATUS 9 +#define NUM_B_ANIMS_STATUS 10 // Tasks with return values often assign them to gBattleAnimArgs[7]. #define ARG_RET_ID 7 diff --git a/include/constants/battle_end_turn.h b/include/constants/battle_end_turn.h new file mode 100644 index 0000000000..81c0409ecd --- /dev/null +++ b/include/constants/battle_end_turn.h @@ -0,0 +1,92 @@ +#ifndef GUARD_CONSTANTS_BATTLE_END_TURN_H +#define GUARD_CONSTANTS_BATTLE_END_TURN_H + +// General End Turn Effects based on research from smogon from vanilla games: +// https://www.smogon.com/forums/threads/sword-shield-battle-mechanics-research.3655528/page-64#post-9244179 +enum EndTurnResolutionOrder +{ + ENDTURN_ORDER, + ENDTURN_VARIOUS, + ENDTURN_WEATHER, + ENDTURN_WEATHER_DAMAGE, + ENDTURN_EMERGENCY_EXIT_1, + ENDTURN_AFFECTION, + ENDTURN_FUTURE_SIGHT, + ENDTURN_WISH, + ENDTURN_FIRST_EVENT_BLOCK, + ENDTURN_EMERGENCY_EXIT_2, + ENDTURN_AQUA_RING, + ENDTURN_INGRAIN, + ENDTURN_LEECH_SEED, + ENDTURN_POISON, + ENDTURN_BURN, + ENDTURN_FROSTBITE, + ENDTURN_NIGHTMARE, + ENDTURN_CURSE, + ENDTURN_WRAP, + ENDTURN_SALT_CURE, + ENDTURN_OCTOLOCK, + ENDTURN_SYRUP_BOMB, + ENDTURN_TAUNT, + ENDTURN_TORMENT, + ENDTURN_ENCORE, + ENDTURN_DISABLE, + ENDTURN_MAGNET_RISE, + ENDTURN_TELEKINESIS, + ENDTURN_HEAL_BLOCK, + ENDTURN_EMBARGO, + ENDTURN_YAWN, + ENDTURN_PERISH_SONG, + ENDTURN_ROOST, + ENDTURN_EMERGENCY_EXIT_3, + ENDTURN_SECOND_EVENT_BLOCK, + ENDTURN_TRICK_ROOM, + ENDTURN_GRAVITY, + ENDTURN_WATER_SPORT, + ENDTURN_MUD_SPORT, + ENDTURN_WONDER_ROOM, + ENDTURN_MAGIC_ROOM, + ENDTURN_TERRAIN, + ENDTURN_THIRD_EVENT_BLOCK, + ENDTURN_EMERGENCY_EXIT_4, + ENDTURN_FORM_CHANGE_ABILITIES, + ENDTURN_EJECT_PACK, + ENDTURN_DYNAMAX, + ENDTURN_COUNT, +}; + +// Block that handles effects for each individual battler on the field (eg residual damage) +enum FirstEventBlock +{ + FIRST_EVENT_BLOCK_GMAX_MOVE_RESIDUAL, // Needs to be split + FIRST_EVENT_BLOCK_SEA_OF_FIRE_DAMAGE, + FIRST_EVENT_BLOCK_THRASH, // Thrash isn't handled here in vanilla but for now it is that best place for it. + FIRST_EVENT_BLOCK_GRASSY_TERRAIN_HEAL, + FIRST_EVENT_BLOCK_ABILITIES, + FIRST_EVENT_BLOCK_HEAL_ITEMS, +}; + +// Block that tries to remove side statuses +enum SecondEventBlock +{ + SECOND_EVENT_BLOCK_REFLECT, + SECOND_EVENT_BLOCK_LIGHT_SCREEN, + SECOND_EVENT_BLOCK_SAFEGUARD, + SECOND_EVENT_BLOCK_MIST, + SECOND_EVENT_BLOCK_TAILWIND, + SECOND_EVENT_BLOCK_LUCKY_CHANT, + SECOND_EVENT_BLOCK_RAINBOW, + SECOND_EVENT_BLOCK_SEA_OF_FIRE, + SECOND_EVENT_BLOCK_SWAMP, + SECOND_EVENT_BLOCK_AURORA_VEIL, +}; + +// Block that handles Uproar, items and non-form changing abilities +enum ThirdEventBlock +{ + THIRD_EVENT_BLOCK_UPROAR, + THIRD_EVENT_BLOCK_ABILITIES, + THIRD_EVENT_BLOCK_ITEMS, +}; + +#endif // GUARD_CONSTANTS_BATTLE_END_TURN_H diff --git a/include/constants/battle_move_effects.h b/include/constants/battle_move_effects.h index 2ddb75adf6..d1d7675603 100644 --- a/include/constants/battle_move_effects.h +++ b/include/constants/battle_move_effects.h @@ -92,6 +92,7 @@ enum __attribute__((packed)) BattleMoveEffects EFFECT_MINIMIZE, EFFECT_CURSE, EFFECT_HEALING_WISH, + EFFECT_LUNAR_DANCE, // Same as EFFECT_HEALING_WISH, but also heals PP. EFFECT_PROTECT, EFFECT_SPIKES, EFFECT_FORESIGHT, @@ -133,7 +134,7 @@ enum __attribute__((packed)) BattleMoveEffects EFFECT_STOCKPILE, EFFECT_SPIT_UP, EFFECT_SWALLOW, - EFFECT_WORRY_SEED, + EFFECT_OVERWRITE_ABILITY, EFFECT_HAIL, EFFECT_TORMENT, EFFECT_FLATTER, @@ -218,7 +219,6 @@ enum __attribute__((packed)) BattleMoveEffects EFFECT_METAL_BURST, EFFECT_LUCKY_CHANT, EFFECT_SUCKER_PUNCH, - EFFECT_SIMPLE_BEAM, EFFECT_ENTRAINMENT, EFFECT_HEAL_PULSE, EFFECT_QUASH, @@ -311,7 +311,6 @@ enum __attribute__((packed)) BattleMoveEffects EFFECT_MAX_HP_50_RECOIL, EFFECT_CHLOROBLAST, // Same effect as EFFECT_MAX_HP_50_RECOIL but follows the same rules as EFFECT_RECOIL EFFECT_EXTREME_EVOBOOST, - EFFECT_HIT_SET_TERRAIN, EFFECT_DARK_VOID, EFFECT_VICTORY_DANCE, EFFECT_TEATIME, diff --git a/include/constants/battle_script_commands.h b/include/constants/battle_script_commands.h index 2cadf215af..234ebad0b2 100644 --- a/include/constants/battle_script_commands.h +++ b/include/constants/battle_script_commands.h @@ -33,7 +33,7 @@ #define sSAVED_DMG (gBattleScripting + 0x28) // savedDmg #define sUNUSED_0x2C (gBattleScripting + 0x2C) // unused_0x2c #define sMOVE_EFFECT (gBattleScripting + 0x2E) // moveEffect -#define sMULTIHIT_EFFECT (gBattleScripting + 0x30) // multihitMoveEffect +#define sUNUSED_0x30 (gBattleScripting + 0x30) // unused_0x30 #define sILLUSION_NICK_HACK (gBattleScripting + 0x32) // illusionNickHack #define sFIXED_ABILITY_POPUP (gBattleScripting + 0x33) // fixedPopup #define sABILITY_OVERWRITE (gBattleScripting + 0x34) // abilityPopupOverwrite @@ -96,10 +96,9 @@ enum CmdVarious // Cmd_manipulatedamage #define DMG_CHANGE_SIGN 1 -#define DMG_DOUBLED 2 -#define DMG_1_8_TARGET_HP 3 -#define DMG_FULL_ATTACKER_HP 4 -#define DMG_BIG_ROOT 5 +#define DMG_1_8_TARGET_HP 2 +#define DMG_FULL_ATTACKER_HP 3 +#define DMG_BIG_ROOT 4 // Cmd_jumpifcantswitch #define SWITCH_IGNORE_ESCAPE_PREVENTION (1 << 7) @@ -125,47 +124,59 @@ enum CmdVarious #define PARTY_SCREEN_OPTIONAL (1 << 7) // Flag for first argument to openpartyscreen +enum SetMoveEffectFlags +{ + NO_FLAGS = 0, + EFFECT_PRIMARY = (1 << 0), + EFFECT_CERTAIN = (1 << 1), +}; + // cases for Cmd_moveend - Order matters! enum MoveEndEffects { - MOVEEND_SUM_DAMAGE, + MOVEEND_SET_VALUES, MOVEEND_PROTECT_LIKE_EFFECT, + MOVEEND_GRUDGE, + MOVEEND_DESTINY_BOND, MOVEEND_ABSORB, MOVEEND_RAGE, MOVEEND_SYNCHRONIZE_TARGET, MOVEEND_ABILITIES, MOVEEND_ABILITIES_ATTACKER, - MOVEEND_STATUS_IMMUNITY_ABILITIES, + MOVEEND_STATUS_IMMUNITY_ABILITIES, // TODO: Do berries come before???? MOVEEND_SYNCHRONIZE_ATTACKER, MOVEEND_ATTACKER_INVISIBLE, MOVEEND_ATTACKER_VISIBLE, MOVEEND_TARGET_VISIBLE, MOVEEND_ITEM_EFFECTS_TARGET, - MOVEEND_ITEM_EFFECTS_ALL, + MOVEEND_ITEM_EFFECTS_ATTACKER_1, MOVEEND_SYMBIOSIS, - MOVEEND_KINGSROCK, // These item effects will occur each strike of a multi-hit move MOVEEND_SUBSTITUTE, MOVEEND_SKY_DROP_CONFUSE, MOVEEND_UPDATE_LAST_MOVES, MOVEEND_MIRROR_MOVE, MOVEEND_DEFROST, MOVEEND_NEXT_TARGET, // Everything up until here is handled for each strike of a spread move + MOVEEND_HP_THRESHHOLD_ITEMS_TARGET, // Activation only during a multi hit move / ability (Parental Bond) MOVEEND_MULTIHIT_MOVE, MOVEEND_MOVE_BLOCK, - MOVEEND_ITEM_EFFECTS_ATTACKER, - MOVEEND_ITEM_THROAT_SPRAY, + MOVEEND_ITEM_EFFECTS_ATTACKER_2, MOVEEND_ABILITY_BLOCK, - MOVEEND_SHEER_FORCE, // If move is Sheer Force affected, skip until Opportunist + MOVEEND_SHEER_FORCE, // If move is Sheer Force affected, skip to Hit Escape + One + MOVEEND_COLOR_CHANGE, // Color Change / Berserk / Anger Shell + MOVEEND_KEE_MARANGA_HP_THRESHOLD_ITEM_TARGET, MOVEEND_RED_CARD, MOVEEND_EJECT_BUTTON, - MOVEEND_LIFEORB_SHELLBELL, + MOVEEND_LIFE_ORB_SHELL_BELL, MOVEEND_FORM_CHANGE, MOVEEND_EMERGENCY_EXIT, MOVEEND_EJECT_PACK, MOVEEND_HIT_ESCAPE, - MOVEEND_OPPORTUNIST, - MOVEEND_PICKPOCKET, + MOVEEND_ITEMS_EFFECTS_ALL, MOVEEND_WHITE_HERB, + MOVEEND_OPPORTUNIST, + MOVEEND_MIRROR_HERB, + MOVEEND_PICKPOCKET, MOVEEND_THIRD_MOVE_BLOCK, MOVEEND_CHANGED_ITEMS, MOVEEND_SAME_MOVE_TURNS, @@ -173,6 +184,9 @@ enum MoveEndEffects MOVEEND_DANCER, MOVEEND_PURSUIT_NEXT_ACTION, MOVEEND_COUNT, + + // This guarantees a correct jump if new moveends are added directly after MOVEEND_HIT_ESCAPE + MOVEEND_JUMP_TO_HIT_ESCAPE_PLUS_ONE = (MOVEEND_HIT_ESCAPE + 1), }; // switch cases @@ -194,4 +208,10 @@ enum TriggerOnFieldStatus ON_WEATHER, }; +enum HealthUpdate +{ + PASSIVE_HP_UPDATE, + MOVE_DAMAGE_HP_UPDATE, +}; + #endif // GUARD_CONSTANTS_BATTLE_SCRIPT_COMMANDS_H diff --git a/include/constants/battle_string_ids.h b/include/constants/battle_string_ids.h index 22d63b119c..462c64cda1 100644 --- a/include/constants/battle_string_ids.h +++ b/include/constants/battle_string_ids.h @@ -28,8 +28,7 @@ enum StringID STRINGID_STATSWONTINCREASE2, STRINGID_AVOIDEDDAMAGE, STRINGID_ITDOESNTAFFECT, - STRINGID_ATTACKERFAINTED, - STRINGID_TARGETFAINTED, + STRINGID_BATTLERFAINTED, STRINGID_PLAYERGOTMONEY, STRINGID_PLAYERWHITEOUT, STRINGID_PLAYERWHITEOUT2_WILD, @@ -61,11 +60,8 @@ enum StringID STRINGID_PKMNISPARALYZED, STRINGID_PKMNISALREADYPARALYZED, STRINGID_PKMNHEALEDPARALYSIS, - STRINGID_PKMNDREAMEATEN, STRINGID_STATSWONTINCREASE, STRINGID_STATSWONTDECREASE, - STRINGID_TEAMSTOPPEDWORKING, - STRINGID_FOESTOPPEDWORKING, STRINGID_PKMNISCONFUSED, STRINGID_PKMNHEALEDCONFUSION, STRINGID_PKMNWASCONFUSED, @@ -73,7 +69,6 @@ enum StringID STRINGID_PKMNFELLINLOVE, STRINGID_PKMNINLOVE, STRINGID_PKMNIMMOBILIZEDBYLOVE, - STRINGID_PKMNBLOWNAWAY, STRINGID_PKMNCHANGEDTYPE, STRINGID_PKMNFLINCHED, STRINGID_PKMNREGAINEDHEALTH, @@ -117,7 +112,6 @@ enum StringID STRINGID_PKMNCALMEDDOWN, STRINGID_PKMNCANTSLEEPINUPROAR, STRINGID_PKMNSTOCKPILED, - STRINGID_PKMNCANTSTOCKPILE, STRINGID_PKMNCANTSLEEPINUPROAR2, STRINGID_UPROARKEPTPKMNAWAKE, STRINGID_PKMNSTAYEDAWAKEUSING, @@ -179,7 +173,6 @@ enum StringID STRINGID_PKMNREADYTOHELP, STRINGID_PKMNSWITCHEDITEMS, STRINGID_PKMNCOPIEDFOE, - STRINGID_PKMNMADEWISH, STRINGID_PKMNWISHCAMETRUE, STRINGID_PKMNPLANTEDROOTS, STRINGID_PKMNABSORBEDNUTRIENTS, @@ -196,14 +189,11 @@ enum StringID STRINGID_PKMNWAITSFORTARGET, STRINGID_PKMNSNATCHEDMOVE, STRINGID_PKMNMADEITRAIN, - STRINGID_PKMNRAISEDSPEED, STRINGID_PKMNPROTECTEDBY, STRINGID_PKMNPREVENTSUSAGE, STRINGID_PKMNRESTOREDHPUSING, STRINGID_PKMNCHANGEDTYPEWITH, - STRINGID_PKMNPREVENTSPARALYSISWITH, STRINGID_PKMNPREVENTSROMANCEWITH, - STRINGID_PKMNPREVENTSPOISONINGWITH, STRINGID_PKMNPREVENTSCONFUSIONWITH, STRINGID_PKMNRAISEDFIREPOWERWITH, STRINGID_PKMNANCHORSITSELFWITH, @@ -233,7 +223,6 @@ enum StringID STRINGID_BUTNOTHINGHAPPENED, STRINGID_BUTITFAILED, STRINGID_ITHURTCONFUSION, - STRINGID_MIRRORMOVEFAILED, STRINGID_STARTEDTORAIN, STRINGID_DOWNPOURSTARTED, STRINGID_RAINCONTINUES, @@ -248,9 +237,6 @@ enum StringID STRINGID_STARTEDHAIL, STRINGID_HAILCONTINUES, STRINGID_HAILSTOPPED, - STRINGID_FAILEDTOSPITUP, - STRINGID_FAILEDTOSWALLOW, - STRINGID_WINDBECAMEHEATWAVE, STRINGID_STATCHANGESGONE, STRINGID_COINSSCATTERED, STRINGID_TOOWEAKFORSUBSTITUTE, @@ -307,7 +293,6 @@ enum StringID STRINGID_ITEMALLOWSONLYYMOVE, STRINGID_PKMNHUNGONWITHX, STRINGID_EMPTYSTRING3, - STRINGID_PKMNSXPREVENTSBURNS, STRINGID_PKMNSXBLOCKSY, STRINGID_PKMNSXRESTOREDHPALITTLE2, STRINGID_PKMNSXWHIPPEDUPSANDSTORM, @@ -326,8 +311,8 @@ enum StringID STRINGID_PLAYERDEFEATEDTRAINER1, STRINGID_SOOTHINGAROMA, STRINGID_ITEMSCANTBEUSEDNOW, - STRINGID_FORXCOMMAYZ, STRINGID_USINGITEMSTATOFPKMNROSE, + STRINGID_USINGITEMSTATOFPKMNFELL, STRINGID_PKMNUSEDXTOGETPUMPED, STRINGID_PKMNSXMADEYUSELESS, STRINGID_PKMNTRAPPEDBYSANDTOMB, @@ -343,7 +328,6 @@ enum StringID STRINGID_PKMNFLEDUSINGITS, STRINGID_PKMNFLEDUSING, STRINGID_PKMNWASDRAGGEDOUT, - STRINGID_PREVENTEDFROMWORKING, STRINGID_PKMNSITEMNORMALIZEDSTATUS, STRINGID_TRAINER1USEDITEM, STRINGID_BOXISFULL, @@ -354,17 +338,13 @@ enum StringID STRINGID_STATSWONTDECREASE2, STRINGID_PKMNSXBLOCKSY2, STRINGID_PKMNSXWOREOFF, - STRINGID_PKMNRAISEDDEFALITTLE, - STRINGID_PKMNRAISEDSPDEFALITTLE, STRINGID_THEWALLSHATTERED, - STRINGID_PKMNSXPREVENTSYSZ, STRINGID_PKMNSXCUREDITSYPROBLEM, STRINGID_ATTACKERCANTESCAPE, STRINGID_PKMNOBTAINEDX, STRINGID_PKMNOBTAINEDX2, STRINGID_PKMNOBTAINEDXYOBTAINEDZ, STRINGID_BUTNOEFFECT, - STRINGID_PKMNSXHADNOEFFECTONY, STRINGID_TWOENEMIESDEFEATED, STRINGID_TRAINER2LOSETEXT, STRINGID_PKMNINCAPABLEOFPOWER, @@ -423,10 +403,8 @@ enum StringID STRINGID_FELLSTRAIGHTDOWN, STRINGID_TARGETCHANGEDTYPE, STRINGID_PKMNACQUIREDSIMPLE, - STRINGID_EMPTYSTRING5, STRINGID_KINDOFFER, STRINGID_RESETSTARGETSSTATLEVELS, - STRINGID_EMPTYSTRING6, STRINGID_ALLYSWITCHPOSITION, STRINGID_RESTORETARGETSHEALTH, STRINGID_TOOKPJMNINTOTHESKY, @@ -557,10 +535,8 @@ enum StringID STRINGID_COMATOSEENTERS, STRINGID_SCREENCLEANERENTERS, STRINGID_FETCHEDPOKEBALL, - STRINGID_BATTLERABILITYRAISEDSTAT, STRINGID_ASANDSTORMKICKEDUP, STRINGID_PKMNSWILLPERISHIN3TURNS, - STRINGID_ABILITYRAISEDSTATDRASTICALLY, STRINGID_AURAFLAREDTOLIFE, STRINGID_ASONEENTERS, STRINGID_CURIOUSMEDICINEENTERS, @@ -597,7 +573,6 @@ enum StringID STRINGID_BROKETHROUGHPROTECTION, STRINGID_ABILITYALLOWSONLYMOVE, STRINGID_SWAPPEDABILITIES, - STRINGID_PASTELVEILPROTECTED, STRINGID_PASTELVEILENTERS, STRINGID_BATTLERTYPECHANGEDTO, STRINGID_BOTHCANNOLONGERESCAPE, @@ -746,33 +721,24 @@ enum StringID // They are assigned to the MULTISTRING_CHOOSER byte of gBattleCommunication // and read when e.g. the command printfromtable is used. -// gStatUpStringIds -enum StatUpStringID +// gStatUpStringIds and gStatDownStringIds +enum StatChangedStringID { - B_MSG_ATTACKER_STAT_ROSE, - B_MSG_DEFENDER_STAT_ROSE, - B_MSG_STAT_WONT_INCREASE, - B_MSG_STAT_ROSE_EMPTY, - B_MSG_STAT_ROSE_ITEM, + B_MSG_ATTACKER_STAT_CHANGED, + B_MSG_DEFENDER_STAT_CHANGED, + B_MSG_STAT_WONT_CHANGE, + B_MSG_STAT_CHANGE_EMPTY, + B_MSG_STAT_CHANGED_ITEM, B_MSG_USED_DIRE_HIT, }; -// gStatDownStringIds -enum StatDownStringID -{ - B_MSG_ATTACKER_STAT_FELL = 0, - B_MSG_DEFENDER_STAT_FELL = 1, - B_MSG_STAT_WONT_DECREASE, - B_MSG_STAT_FELL_EMPTY, -}; - // gMissStringIds enum MissStringID { B_MSG_MISSED, B_MSG_PROTECTED, B_MSG_AVOIDED_ATK, - // Ability-related messages need to below this comment + // Ability-related messages need to be below this comment B_MSG_AVOIDED_DMG, B_MSG_GROUND_MISS, }; @@ -888,20 +854,6 @@ enum UproarOverTurnStringID B_MSG_UPROAR_ENDS, }; -// gStockpileUsedStringIds -enum StockpileUsedStringID -{ - B_MSG_STOCKPILED, - B_MSG_CANT_STOCKPILE, -}; - -// gSwallowFailStringIds -enum SwallowFailStringID -{ - B_MSG_SWALLOW_FAILED, - B_MSG_SWALLOW_FULL_HP, -}; - // gKOFailedStringIds enum KOFailedStringID { @@ -1024,9 +976,15 @@ enum FlashFireStringID B_MSG_FLASH_FIRE_NO_BOOST, }; -// gBerryEffectStringIds -enum BerryEffectStringID +// CureStatusBerryEffectStringID +enum CureStatusBerryEffectStringID { + B_MSG_CURED_PARALYSIS, + B_MSG_CURED_POISON, + B_MSG_CURED_BURN, + B_MSG_CURED_FREEEZE, + B_MSG_CURED_FROSTBITE, + B_MSG_CURED_SLEEP, B_MSG_CURED_PROBLEM, B_MSG_NORMALIZED_STATUS, }; @@ -1049,17 +1007,6 @@ enum GotStatusedStringID B_MSG_STATUSED_BY_ABILITY, }; -// gStatusPreventionStringIds -enum StatusPreventionStringID -{ - B_MSG_ABILITY_PREVENTS_MOVE_BURN, - B_MSG_ABILITY_PREVENTS_MOVE_PARALYSIS, - B_MSG_ABILITY_PREVENTS_MOVE_POISON, - B_MSG_ABILITY_PREVENTS_ABILITY_STATUS, - B_MSG_STATUS_HAD_NO_EFFECT, - B_MSG_ABILITY_PASTEL_VEIL, -}; - // gGotDefrostedStringIds enum GotDefrostedStringID { diff --git a/include/constants/characters.h b/include/constants/characters.h index 6ac3c5224c..0af7b110f0 100644 --- a/include/constants/characters.h +++ b/include/constants/characters.h @@ -232,6 +232,7 @@ #define EXT_CTRL_CODE_ENG 0x16 #define EXT_CTRL_CODE_PAUSE_MUSIC 0x17 #define EXT_CTRL_CODE_RESUME_MUSIC 0x18 +#define EXT_CTRL_CODE_SPEAKER 0x19 #define TEXT_COLOR_TRANSPARENT 0x0 #define TEXT_COLOR_WHITE 0x1 diff --git a/include/constants/contest.h b/include/constants/contest.h index 3b83d4f1c3..70531f5406 100644 --- a/include/constants/contest.h +++ b/include/constants/contest.h @@ -103,29 +103,29 @@ #define CONTEST_EFFECT_REPETITION_NOT_BORING 3 #define CONTEST_EFFECT_AVOID_STARTLE_ONCE 4 #define CONTEST_EFFECT_AVOID_STARTLE 5 -#define CONTEST_EFFECT_AVOID_STARTLE_SLIGHTLY 6 -#define CONTEST_EFFECT_USER_LESS_EASILY_STARTLED 7 -#define CONTEST_EFFECT_STARTLE_FRONT_MON 8 -#define CONTEST_EFFECT_SLIGHTLY_STARTLE_PREV_MONS 9 +#define CONTEST_EFFECT_AVOID_STARTLE_SLIGHTLY 6 // Unused +#define CONTEST_EFFECT_USER_LESS_EASILY_STARTLED 7 // Unused +#define CONTEST_EFFECT_STARTLE_FRONT_MON 8 // Unused +#define CONTEST_EFFECT_SLIGHTLY_STARTLE_PREV_MONS 9 // Unused #define CONTEST_EFFECT_STARTLE_PREV_MON 10 #define CONTEST_EFFECT_STARTLE_PREV_MONS 11 #define CONTEST_EFFECT_BADLY_STARTLE_FRONT_MON 12 #define CONTEST_EFFECT_BADLY_STARTLE_PREV_MONS 13 -#define CONTEST_EFFECT_STARTLE_PREV_MON_2 14 -#define CONTEST_EFFECT_STARTLE_PREV_MONS_2 15 +#define CONTEST_EFFECT_STARTLE_PREV_MON_2 14 // Unused +#define CONTEST_EFFECT_STARTLE_PREV_MONS_2 15 // Unused #define CONTEST_EFFECT_SHIFT_JUDGE_ATTENTION 16 #define CONTEST_EFFECT_STARTLE_MON_WITH_JUDGES_ATTENTION 17 #define CONTEST_EFFECT_JAMS_OTHERS_BUT_MISS_ONE_TURN 18 #define CONTEST_EFFECT_STARTLE_MONS_SAME_TYPE_APPEAL 19 -#define CONTEST_EFFECT_STARTLE_MONS_COOL_APPEAL 20 -#define CONTEST_EFFECT_STARTLE_MONS_BEAUTY_APPEAL 21 -#define CONTEST_EFFECT_STARTLE_MONS_CUTE_APPEAL 22 -#define CONTEST_EFFECT_STARTLE_MONS_SMART_APPEAL 23 -#define CONTEST_EFFECT_STARTLE_MONS_TOUGH_APPEAL 24 -#define CONTEST_EFFECT_MAKE_FOLLOWING_MON_NERVOUS 25 +#define CONTEST_EFFECT_STARTLE_MONS_COOL_APPEAL 20 // Unused +#define CONTEST_EFFECT_STARTLE_MONS_BEAUTY_APPEAL 21 // Unused +#define CONTEST_EFFECT_STARTLE_MONS_CUTE_APPEAL 22 // Unused +#define CONTEST_EFFECT_STARTLE_MONS_SMART_APPEAL 23 // Unused +#define CONTEST_EFFECT_STARTLE_MONS_TOUGH_APPEAL 24 // Unused +#define CONTEST_EFFECT_MAKE_FOLLOWING_MON_NERVOUS 25 // Unused #define CONTEST_EFFECT_MAKE_FOLLOWING_MONS_NERVOUS 26 #define CONTEST_EFFECT_WORSEN_CONDITION_OF_PREV_MONS 27 -#define CONTEST_EFFECT_BADLY_STARTLES_MONS_IN_GOOD_CONDITION 28 +#define CONTEST_EFFECT_BADLY_STARTLES_MONS_IN_GOOD_CONDITION 28 // Unused #define CONTEST_EFFECT_BETTER_IF_FIRST 29 #define CONTEST_EFFECT_BETTER_IF_LAST 30 #define CONTEST_EFFECT_APPEAL_AS_GOOD_AS_PREV_ONES 31 @@ -133,18 +133,21 @@ #define CONTEST_EFFECT_BETTER_WHEN_LATER 33 #define CONTEST_EFFECT_QUALITY_DEPENDS_ON_TIMING 34 #define CONTEST_EFFECT_BETTER_IF_SAME_TYPE 35 -#define CONTEST_EFFECT_BETTER_IF_DIFF_TYPE 36 +#define CONTEST_EFFECT_BETTER_IF_DIFF_TYPE 36 // Unused #define CONTEST_EFFECT_AFFECTED_BY_PREV_APPEAL 37 #define CONTEST_EFFECT_IMPROVE_CONDITION_PREVENT_NERVOUSNESS 38 #define CONTEST_EFFECT_BETTER_WITH_GOOD_CONDITION 39 #define CONTEST_EFFECT_NEXT_APPEAL_EARLIER 40 #define CONTEST_EFFECT_NEXT_APPEAL_LATER 41 -#define CONTEST_EFFECT_MAKE_SCRAMBLING_TURN_ORDER_EASIER 42 +#define CONTEST_EFFECT_MAKE_SCRAMBLING_TURN_ORDER_EASIER 42 // Unused #define CONTEST_EFFECT_SCRAMBLE_NEXT_TURN_ORDER 43 #define CONTEST_EFFECT_EXCITE_AUDIENCE_IN_ANY_CONTEST 44 #define CONTEST_EFFECT_BADLY_STARTLE_MONS_WITH_GOOD_APPEALS 45 #define CONTEST_EFFECT_BETTER_WHEN_AUDIENCE_EXCITED 46 #define CONTEST_EFFECT_DONT_EXCITE_AUDIENCE 47 +//#define CONTEST_EFFECT_QUICKLY_GROW_BORED 48 // New in Gen 6 +//#define CONTEST_EFFECT_EXCITES_AUDIENCE_MORE_IF_FIRST 49 // New in Gen 6 +//#define CONTEST_EFFECT_EXCITES_AUDIENCE_MORE_IF_LAST 50 // New in Gen 6 // Each of the above effects is grouped into one of these effect type categories // Only a few of these get checked by the AI, the rest go unused @@ -157,93 +160,127 @@ #define CONTEST_EFFECT_TYPE_TURN_ORDER 6 #define CONTEST_EFFECT_TYPE_UNKNOWN 8 -#define COMBO_STARTER_POUND 1 -#define COMBO_STARTER_FIRE_PUNCH 2 -#define COMBO_STARTER_ICE_PUNCH 3 -#define COMBO_STARTER_THUNDER_PUNCH 4 -#define COMBO_STARTER_SCRATCH 5 -#define COMBO_STARTER_VICE_GRIP 6 -#define COMBO_STARTER_SWORDS_DANCE 7 -#define COMBO_STARTER_SAND_ATTACK 8 -#define COMBO_STARTER_HORN_ATTACK 9 -#define COMBO_STARTER_LEER 10 -#define COMBO_STARTER_SING 11 -#define COMBO_STARTER_SURF 12 -#define COMBO_STARTER_PECK 13 -#define COMBO_STARTER_LEECH_SEED 14 -#define COMBO_STARTER_GROWTH 15 -#define COMBO_STARTER_STRING_SHOT 16 -#define COMBO_STARTER_DRAGON_RAGE 17 -#define COMBO_STARTER_ROCK_THROW 18 -#define COMBO_STARTER_EARTHQUAKE 19 -#define COMBO_STARTER_TOXIC 20 -#define COMBO_STARTER_CONFUSION 21 -#define COMBO_STARTER_PSYCHIC 22 -#define COMBO_STARTER_HYPNOSIS 23 -#define COMBO_STARTER_RAGE 24 -#define COMBO_STARTER_DOUBLE_TEAM 25 -#define COMBO_STARTER_HARDEN 26 -#define COMBO_STARTER_DEFENSE_CURL 27 -#define COMBO_STARTER_FOCUS_ENERGY 28 -#define COMBO_STARTER_SMOG 29 -#define COMBO_STARTER_SLUDGE 30 -#define COMBO_STARTER_BONE_CLUB 31 -#define COMBO_STARTER_KINESIS 32 -#define COMBO_STARTER_SOFT_BOILED 33 -#define COMBO_STARTER_BONEMERANG 34 -#define COMBO_STARTER_REST 35 -#define COMBO_STARTER_MIND_READER 36 -#define COMBO_STARTER_CURSE 37 -#define COMBO_STARTER_POWDER_SNOW 38 -#define COMBO_STARTER_SCARY_FACE 39 -#define COMBO_STARTER_BELLY_DRUM 40 -#define COMBO_STARTER_SLUDGE_BOMB 41 -#define COMBO_STARTER_MUD_SLAP 42 -#define COMBO_STARTER_BONE_RUSH 43 -#define COMBO_STARTER_LOCK_ON 44 -#define COMBO_STARTER_SANDSTORM 45 -#define COMBO_STARTER_ENDURE 46 -#define COMBO_STARTER_CHARM 47 -#define COMBO_STARTER_MEAN_LOOK 48 -#define COMBO_STARTER_HEAL_BELL 49 -#define COMBO_STARTER_DRAGON_BREATH 50 -#define COMBO_STARTER_SWEET_SCENT 51 -#define COMBO_STARTER_RAIN_DANCE 52 -#define COMBO_STARTER_SUNNY_DAY 53 -#define COMBO_STARTER_FAKE_OUT 54 -#define COMBO_STARTER_STOCKPILE 55 -#define COMBO_STARTER_HAIL 56 -#define COMBO_STARTER_CHARGE 57 -#define COMBO_STARTER_TAUNT 58 -#define COMBO_STARTER_REVENGE 59 -#define COMBO_STARTER_YAWN 60 -#define COMBO_STARTER_DIVE 61 -#define COMBO_STARTER_MUD_SPORT 62 -#define COMBO_STARTER_METAL_SOUND 63 -#define COMBO_STARTER_WATER_SPORT 64 -#define COMBO_STARTER_CALM_MIND 65 -#define COMBO_STARTER_DRAGON_DANCE 66 -#define COMBO_STARTER_PAYBACK 67 -#define COMBO_STARTER_LUCKY_CHANT 68 -#define COMBO_STARTER_WORRY_SEED 69 -#define COMBO_STARTER_DRAGON_RUSH 70 -#define COMBO_STARTER_BRAVE_BIRD 71 -#define COMBO_STARTER_THUNDER_FANG 72 -#define COMBO_STARTER_ICE_FANG 73 -#define COMBO_STARTER_FIRE_FANG 74 -#define COMBO_STARTER_ATTACK_ORDER 75 -#define COMBO_STARTER_DEFEND_ORDER 76 -#define COMBO_STARTER_HEAL_ORDER 77 -#define COMBO_STARTER_SCALD 78 -#define COMBO_STARTER_DRAGON_TAIL 79 -#define COMBO_STARTER_HYPERSPACE_HOLE 80 -#define COMBO_STARTER_THOUSAND_ARROWS 81 -#define COMBO_STARTER_THOUSAND_WAVES 82 -#define COMBO_STARTER_HYPERSPACE_FURY 83 -#define COMBO_STARTER_SHADOW_BONE 84 -#define COMBO_STARTER_ELECTRIC_TERRAIN 85 -#define COMBO_STARTER_MISTY_TERRAIN 86 -#define COMBO_STARTER_GRASSY_TERRAIN 87 -#define COMBO_STARTER_PSYCHIC_TERRAIN 88 +enum { + COMBO_STARTER_POUND, + COMBO_STARTER_FIRE_PUNCH, + COMBO_STARTER_ICE_PUNCH, + COMBO_STARTER_THUNDER_PUNCH, + COMBO_STARTER_SCRATCH, + COMBO_STARTER_VICE_GRIP, + COMBO_STARTER_SWORDS_DANCE, + COMBO_STARTER_SAND_ATTACK, + COMBO_STARTER_HORN_ATTACK, + COMBO_STARTER_LEER, + COMBO_STARTER_SING, + COMBO_STARTER_SURF, + COMBO_STARTER_PECK, + COMBO_STARTER_LEECH_SEED, + COMBO_STARTER_GROWTH, + COMBO_STARTER_STRING_SHOT, + COMBO_STARTER_DRAGON_RAGE, + COMBO_STARTER_ROCK_THROW, + COMBO_STARTER_EARTHQUAKE, + COMBO_STARTER_TOXIC, + COMBO_STARTER_CONFUSION, + COMBO_STARTER_PSYCHIC, + COMBO_STARTER_HYPNOSIS, + COMBO_STARTER_RAGE, + COMBO_STARTER_DOUBLE_TEAM, + COMBO_STARTER_HARDEN, + COMBO_STARTER_DEFENSE_CURL, + COMBO_STARTER_FOCUS_ENERGY, + COMBO_STARTER_SMOG, + COMBO_STARTER_SLUDGE, + COMBO_STARTER_BONE_CLUB, + COMBO_STARTER_KINESIS, + COMBO_STARTER_SOFT_BOILED, + COMBO_STARTER_BONEMERANG, + COMBO_STARTER_REST, + COMBO_STARTER_MIND_READER, + COMBO_STARTER_CURSE, + COMBO_STARTER_POWDER_SNOW, + COMBO_STARTER_SCARY_FACE, + COMBO_STARTER_BELLY_DRUM, + COMBO_STARTER_SLUDGE_BOMB, + COMBO_STARTER_MUD_SLAP, + COMBO_STARTER_BONE_RUSH, + COMBO_STARTER_LOCK_ON, + COMBO_STARTER_SANDSTORM, + COMBO_STARTER_ENDURE, + COMBO_STARTER_CHARM, + COMBO_STARTER_MEAN_LOOK, + COMBO_STARTER_HEAL_BELL, + COMBO_STARTER_DRAGON_BREATH, + COMBO_STARTER_SWEET_SCENT, + COMBO_STARTER_RAIN_DANCE, + COMBO_STARTER_SUNNY_DAY, + COMBO_STARTER_FAKE_OUT, + COMBO_STARTER_STOCKPILE, + COMBO_STARTER_HAIL, + COMBO_STARTER_CHARGE, + COMBO_STARTER_TAUNT, + COMBO_STARTER_REVENGE, + COMBO_STARTER_YAWN, + COMBO_STARTER_DIVE, + COMBO_STARTER_MUD_SPORT, + COMBO_STARTER_METAL_SOUND, + COMBO_STARTER_WATER_SPORT, + COMBO_STARTER_CALM_MIND, + COMBO_STARTER_DRAGON_DANCE, + COMBO_STARTER_PAYBACK, + COMBO_STARTER_LUCKY_CHANT, + COMBO_STARTER_WORRY_SEED, + COMBO_STARTER_DRAGON_RUSH, + COMBO_STARTER_BRAVE_BIRD, + COMBO_STARTER_THUNDER_FANG, + COMBO_STARTER_ICE_FANG, + COMBO_STARTER_FIRE_FANG, + COMBO_STARTER_ATTACK_ORDER, + COMBO_STARTER_DEFEND_ORDER, + COMBO_STARTER_HEAL_ORDER, + COMBO_STARTER_SCALD, + COMBO_STARTER_DRAGON_TAIL, + COMBO_STARTER_HYPERSPACE_HOLE, + COMBO_STARTER_THOUSAND_ARROWS, + COMBO_STARTER_THOUSAND_WAVES, + COMBO_STARTER_HYPERSPACE_FURY, + COMBO_STARTER_SHADOW_BONE, + COMBO_STARTER_ELECTRIC_TERRAIN, + COMBO_STARTER_MISTY_TERRAIN, + COMBO_STARTER_GRASSY_TERRAIN, + COMBO_STARTER_PSYCHIC_TERRAIN, + COMBO_STARTER_FORCE_PALM, + COMBO_STARTER_THUNDER_WAVE, + COMBO_STARTER_AGILITY, + COMBO_STARTER_STEALTH_ROCK, + COMBO_STARTER_INFERNO, + COMBO_STARTER_WILL_O_WISP, + COMBO_STARTER_LOVELY_KISS, + COMBO_STARTER_SPORE, + COMBO_STARTER_CELEBRATE, + COMBO_STARTER_COVET, + COMBO_STARTER_HAPPY_HOUR, + COMBO_STARTER_WISH, + COMBO_STARTER_AMNESIA, + COMBO_STARTER_HONE_CLAWS, + COMBO_STARTER_ENTRAINMENT, + COMBO_STARTER_PLAY_NICE, + COMBO_STARTER_BLOCK, + COMBO_STARTER_ENCORE, + COMBO_STARTER_DARK_VOID, + COMBO_STARTER_GRASS_WHISTLE, + COMBO_STARTER_SLEEP_POWDER, + COMBO_STARTER_POISON_GAS, + COMBO_STARTER_POISON_POWDER, + COMBO_STARTER_NASTY_PLOT, + COMBO_STARTER_PARABOLIC_CHARGE, + COMBO_STARTER_SHIFT_GEAR, + COMBO_STARTER_SPIKES, + COMBO_STARTER_TOXIC_SPIKES, + COMBO_STARTER_GLARE, + COMBO_STARTER_ROCK_POLISH, + COMBO_STARTER_ROTOTILLER, + COMBO_STARTER_TORMENT, +}; #endif // GUARD_CONSTANTS_CONTEST_H diff --git a/include/constants/event_objects.h b/include/constants/event_objects.h index eacd3b3a2a..c20c2c79c3 100644 --- a/include/constants/event_objects.h +++ b/include/constants/event_objects.h @@ -246,11 +246,12 @@ #define OBJ_EVENT_GFX_POKE_BALL 239 #define OBJ_EVENT_GFX_OW_MON 240 #define OBJ_EVENT_GFX_LIGHT_SPRITE 241 +#define OBJ_EVENT_GFX_APRICORN_TREE 242 // NOTE: The maximum amount of object events has been expanded from 255 to 65535. // Since dynamic graphics ids still require at least 16 free values, the actual limit // is 65519, but even considering follower Pokémon, this should be more than enough :) -#define NUM_OBJ_EVENT_GFX 242 +#define NUM_OBJ_EVENT_GFX 243 // These are dynamic object gfx ids. diff --git a/include/constants/expansion.h b/include/constants/expansion.h index 1b9fba88a1..36a4d7c89c 100644 --- a/include/constants/expansion.h +++ b/include/constants/expansion.h @@ -1,10 +1,10 @@ #ifndef GUARD_CONSTANTS_EXPANSION_H #define GUARD_CONSTANTS_EXPANSION_H -// Last version: 1.13.3 +// Last version: 1.14.1 #define EXPANSION_VERSION_MAJOR 1 -#define EXPANSION_VERSION_MINOR 13 -#define EXPANSION_VERSION_PATCH 4 +#define EXPANSION_VERSION_MINOR 14 +#define EXPANSION_VERSION_PATCH 2 // FALSE if this this version of Expansion is not a tagged commit, i.e. // it contains unreleased changes. diff --git a/include/constants/field_effects.h b/include/constants/field_effects.h index e38b25cac7..71978fc64f 100644 --- a/include/constants/field_effects.h +++ b/include/constants/field_effects.h @@ -79,6 +79,7 @@ #define FLDEFF_DEFOG 74 #define FLDEFF_USE_ROCK_CLIMB 75 #define FLDEFF_ROCK_CLIMB_DUST 76 +#define FLDEFF_ORAS_DOWSE 77 #define FLDEFFOBJ_SHADOW_S 0 #define FLDEFFOBJ_SHADOW_M 1 @@ -123,6 +124,8 @@ #define FLDEFFOBJ_CAVE_DUST 40 #define FLDEFFOBJ_ROCK_CLIMB_BLOB 41 #define FLDEFFOBJ_ROCK_CLIMB_DUST 42 +#define FLDEFFOBJ_ORAS_DOWSE_BRENDAN 43 +#define FLDEFFOBJ_ORAS_DOWSE_MAY 44 #define FLDEFF_PAL_TAG_CUT_GRASS 0x1000 #define FLDEFF_PAL_TAG_SECRET_POWER_TREE 0x1003 @@ -138,6 +141,7 @@ #define FLDEFF_PAL_TAG_UNKNOWN 0x1011 #define FLDEFF_PAL_TAG_CAVE_DUST 0x1012 #define FLDEFF_PAL_TAG_DUST_CLOUD 0x1013 +#define FLDEFF_PAL_TAG_ORAS_DOWSE 0x1014 #define FLDEFF_PAL_TAG_FIELD_MOVE_MON 0x8400 // tile tags, for field effects that may have many copies on screen at once diff --git a/include/constants/field_specials.h b/include/constants/field_specials.h index 72966adeb8..6973f9e14f 100644 --- a/include/constants/field_specials.h +++ b/include/constants/field_specials.h @@ -2,65 +2,80 @@ #define GUARD_CONSTANTS_FIELD_SPECIALS_H // PC Locations -#define PC_LOCATION_OTHER 0 -#define PC_LOCATION_BRENDANS_HOUSE 1 -#define PC_LOCATION_MAYS_HOUSE 2 +enum PCLocation +{ + PC_LOCATION_OTHER, + PC_LOCATION_BRENDANS_HOUSE, + PC_LOCATION_MAYS_HOUSE, +}; // SS Tidal Locations -#define SS_TIDAL_LOCATION_CURRENTS 0 -#define SS_TIDAL_LOCATION_SLATEPORT 1 -#define SS_TIDAL_LOCATION_LILYCOVE 2 -#define SS_TIDAL_LOCATION_ROUTE124 3 -#define SS_TIDAL_LOCATION_ROUTE131 4 +enum SSTidalLocation +{ + SS_TIDAL_LOCATION_CURRENTS, + SS_TIDAL_LOCATION_SLATEPORT, + SS_TIDAL_LOCATION_LILYCOVE, + SS_TIDAL_LOCATION_ROUTE124, + SS_TIDAL_LOCATION_ROUTE131, +}; -#define SS_TIDAL_BOARD_SLATEPORT 1 -#define SS_TIDAL_DEPART_SLATEPORT 2 -#define SS_TIDAL_HALFWAY_LILYCOVE 3 -#define SS_TIDAL_LAND_LILYCOVE 4 -#define SS_TIDAL_BOARD_LILYCOVE 5 -#define SS_TIDAL_DEPART_LILYCOVE 6 -#define SS_TIDAL_HALFWAY_SLATEPORT 7 -#define SS_TIDAL_LAND_SLATEPORT 8 -#define SS_TIDAL_EXIT_CURRENTS_RIGHT 9 -#define SS_TIDAL_EXIT_CURRENTS_LEFT 10 +enum SSTidalState +{ + SS_TIDAL_BOARD_SLATEPORT = 1, + SS_TIDAL_DEPART_SLATEPORT, + SS_TIDAL_HALFWAY_LILYCOVE, + SS_TIDAL_LAND_LILYCOVE, + SS_TIDAL_BOARD_LILYCOVE, + SS_TIDAL_DEPART_LILYCOVE, + SS_TIDAL_HALFWAY_SLATEPORT, + SS_TIDAL_LAND_SLATEPORT, + SS_TIDAL_EXIT_CURRENTS_RIGHT, + SS_TIDAL_EXIT_CURRENTS_LEFT, +}; #define SS_TIDAL_MAX_STEPS 205 // Scrollable Multichoice Menus -#define SCROLL_MULTI_NONE 0 -#define SCROLL_MULTI_GLASS_WORKSHOP_VENDOR 1 -#define SCROLL_MULTI_POKEMON_FAN_CLUB_RATER 2 -#define SCROLL_MULTI_BF_EXCHANGE_CORNER_DECOR_VENDOR_1 3 -#define SCROLL_MULTI_BF_EXCHANGE_CORNER_DECOR_VENDOR_2 4 -#define SCROLL_MULTI_BF_EXCHANGE_CORNER_VITAMIN_VENDOR 5 -#define SCROLL_MULTI_BF_EXCHANGE_CORNER_HOLD_ITEM_VENDOR 6 -#define SCROLL_MULTI_BERRY_POWDER_VENDOR 7 -#define SCROLL_MULTI_BF_RECEPTIONIST 8 -#define SCROLL_MULTI_BF_MOVE_TUTOR_1 9 -#define SCROLL_MULTI_BF_MOVE_TUTOR_2 10 -#define SCROLL_MULTI_SS_TIDAL_DESTINATION 11 -#define SCROLL_MULTI_BATTLE_TENT_RULES 12 +enum ScrollMulti +{ + SCROLL_MULTI_NONE, + SCROLL_MULTI_GLASS_WORKSHOP_VENDOR, + SCROLL_MULTI_POKEMON_FAN_CLUB_RATER, + SCROLL_MULTI_BF_EXCHANGE_CORNER_DECOR_VENDOR_1, + SCROLL_MULTI_BF_EXCHANGE_CORNER_DECOR_VENDOR_2, + SCROLL_MULTI_BF_EXCHANGE_CORNER_VITAMIN_VENDOR, + SCROLL_MULTI_BF_EXCHANGE_CORNER_HOLD_ITEM_VENDOR, + SCROLL_MULTI_BERRY_POWDER_VENDOR, + SCROLL_MULTI_BF_RECEPTIONIST, + SCROLL_MULTI_BF_MOVE_TUTOR_1, + SCROLL_MULTI_BF_MOVE_TUTOR_2, + SCROLL_MULTI_SS_TIDAL_DESTINATION, + SCROLL_MULTI_BATTLE_TENT_RULES, +}; #define MAX_SCROLL_MULTI_ON_SCREEN 6 #define MAX_SCROLL_MULTI_LENGTH 16 // Dept Store Floor Numbers -#define DEPT_STORE_FLOORNUM_B4F 0 -#define DEPT_STORE_FLOORNUM_B3F 1 -#define DEPT_STORE_FLOORNUM_B2F 2 -#define DEPT_STORE_FLOORNUM_B1F 3 -#define DEPT_STORE_FLOORNUM_1F 4 -#define DEPT_STORE_FLOORNUM_2F 5 -#define DEPT_STORE_FLOORNUM_3F 6 -#define DEPT_STORE_FLOORNUM_4F 7 -#define DEPT_STORE_FLOORNUM_5F 8 -#define DEPT_STORE_FLOORNUM_6F 9 -#define DEPT_STORE_FLOORNUM_7F 10 -#define DEPT_STORE_FLOORNUM_8F 11 -#define DEPT_STORE_FLOORNUM_9F 12 -#define DEPT_STORE_FLOORNUM_10F 13 -#define DEPT_STORE_FLOORNUM_11F 14 -#define DEPT_STORE_FLOORNUM_ROOFTOP 15 +enum DeptStoreFloorNumber +{ + DEPT_STORE_FLOORNUM_B4F, + DEPT_STORE_FLOORNUM_B3F, + DEPT_STORE_FLOORNUM_B2F, + DEPT_STORE_FLOORNUM_B1F, + DEPT_STORE_FLOORNUM_1F, + DEPT_STORE_FLOORNUM_2F, + DEPT_STORE_FLOORNUM_3F, + DEPT_STORE_FLOORNUM_4F, + DEPT_STORE_FLOORNUM_5F, + DEPT_STORE_FLOORNUM_6F, + DEPT_STORE_FLOORNUM_7F, + DEPT_STORE_FLOORNUM_8F, + DEPT_STORE_FLOORNUM_9F, + DEPT_STORE_FLOORNUM_10F, + DEPT_STORE_FLOORNUM_11F, + DEPT_STORE_FLOORNUM_ROOFTOP, +}; // Lilycove Pokémon Trainer Fan Club #define NUM_TRAINER_FAN_CLUB_MEMBERS 8 @@ -81,10 +96,13 @@ #define FANCOUNTER_USED_BATTLE_TOWER 3 // Return values for DoDeoxysRockInteraction -#define DEOXYS_ROCK_FAILED 0 -#define DEOXYS_ROCK_PROGRESSED 1 -#define DEOXYS_ROCK_SOLVED 2 -#define DEOXYS_ROCK_COMPLETE 3 +enum DeoxysRockResult +{ + DEOXYS_ROCK_FAILED, + DEOXYS_ROCK_PROGRESSED, + DEOXYS_ROCK_SOLVED, + DEOXYS_ROCK_COMPLETE, +}; enum { OPEN_PARTY_SCREEN, diff --git a/include/constants/generational_changes.h b/include/constants/generational_changes.h index 381c77ca13..96c917840c 100644 --- a/include/constants/generational_changes.h +++ b/include/constants/generational_changes.h @@ -1,54 +1,211 @@ #ifndef GUARD_CONSTANTS_GENERATIONAL_CHANGES_H #define GUARD_CONSTANTS_GENERATIONAL_CHANGES_H -enum GenConfigTag +/* Config definitions */ +#define CONFIG_DEFINITIONS(F) \ + /* Calculation settings */ \ + F(CRIT_CHANCE, critChance, (u32, GEN_COUNT - 1)) \ + F(CRIT_MULTIPLIER, critMultiplier, (u32, GEN_COUNT - 1)) \ + F(PARALYSIS_SPEED, paralysisSpeed, (u32, GEN_COUNT - 1)) \ + F(CONFUSION_SELF_DMG_CHANCE, confusionSelfDmgChance, (u32, GEN_COUNT - 1)) \ + F(MULTI_HIT_CHANCE, multiHitChance, (u32, GEN_COUNT - 1)) \ + F(WHITEOUT_MONEY, whiteoutMoney, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \ + F(LIGHT_BALL_ATTACK_BOOST, lightBallAttackBoost, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \ + /* Experience settings */ \ + F(EXP_CATCH, expCatch, (u32, GEN_COUNT - 1)) \ + F(TRAINER_EXP_MULTIPLIER, trainerExpMultiplier, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \ + F(SPLIT_EXP, splitExp, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \ + F(SCALED_EXP, scaledExp, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \ + F(UNEVOLVED_EXP_MULTIPLIER, unevolvedExpMultiplier, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \ + F(LEVEL_UP_NOTIFICATION, levelUpNotification, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \ + /* Stat settings */ \ + F(BADGE_BOOST, badgeBoost, (u32, GEN_COUNT - 1)) \ + F(FRIENDSHIP_BOOST, friendshipBoost, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \ + F(MAX_LEVEL_EV_GAINS, maxLevelEvGains, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \ + F(RECALCULATE_STATS, recalculateStats, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \ + /* Damage settings */ \ + F(BURN_DAMAGE, burnDamage, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \ + F(BURN_FACADE_DMG, burnFacadeDmg, (u32, GEN_COUNT - 1)) \ + F(BINDING_DAMAGE, bindingDamage, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \ + F(PSYWAVE_DMG, psywaveDmg, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \ + F(PAYBACK_SWITCH_BOOST, paybackSwitchBoost, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \ + F(HIDDEN_POWER_DMG, hiddenPowerDmg, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \ + F(ROUGH_SKIN_DMG, roughSkinDmg, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \ + F(KNOCK_OFF_DMG, knockOffDmg, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \ + F(SPORT_DMG_REDUCTION, sportDmgReduction, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \ + F(EXPLOSION_DEFENSE, explosionDefense, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \ + F(PARENTAL_BOND_DMG, parentalBondDmg, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \ + F(MULTIPLE_TARGETS_DMG, multipleTargetsDmg, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \ + /* Type settings */ \ + F(GHOSTS_ESCAPE, ghostsEscape, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \ + F(PARALYZE_ELECTRIC, paralyzeElectric, (u32, GEN_COUNT - 1)) \ + F(POWDER_GRASS, powderGrass, (u32, GEN_COUNT - 1)) \ + F(POWDER_OVERCOAT, powderOvercoat, (u32, GEN_COUNT - 1)) \ + F(UPDATED_TYPE_MATCHUPS, updatedTypeMatchups, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \ + F(PRANKSTER_DARK_TYPES, pranksterDarkTypes, (u32, GEN_COUNT - 1)) \ + F(SHEER_COLD_IMMUNITY, sheerColdImmunity, (u32, GEN_COUNT - 1)) \ + F(ROOST_PURE_FLYING, roostPureFlying, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \ + F(STATUS_TYPE_IMMUNITY, statusTypeImmunity, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \ + /* Turn settings */ \ + F(BINDING_TURNS, bindingTurns, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \ + F(UPROAR_TURNS, uproarTurns, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \ + F(UPROAR_IGNORE_SOUNDPROOF, uproarIgnoreSoundproof, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \ + F(DISABLE_TURNS, disableTurns, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \ + F(TAILWIND_TURNS, tailwindTurns, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \ + F(SLEEP_TURNS, sleepTurns, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \ + F(TAUNT_TURNS, tauntTurns, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \ + F(SPORT_TURNS, sportTurns, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \ + F(MEGA_EVO_TURN_ORDER, megaEvoTurnOrder, (u32, GEN_COUNT - 1)) \ + F(RECALC_TURN_AFTER_ACTIONS, recalcTurnAfterActions, (u32, GEN_COUNT - 1)) \ + F(FAINT_SWITCH_IN, faintSwitchIn, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \ + /* Move data settings */ \ + F(UPDATED_MOVE_DATA, updatedMoveData, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \ + F(UPDATED_MOVE_TYPES, updatedMoveTypes, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \ + F(UPDATED_MOVE_FLAGS, updatedMoveFlags, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \ + F(PHYSICAL_SPECIAL_SPLIT, physicalSpecialSplit, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \ + F(RECOIL_IF_MISS_DMG, recoilIfMissDmg, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \ + F(KLUTZ_FLING_INTERACTION, klutzFlingInteraction, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \ + F(UPDATED_CONVERSION, updatedConversion, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \ + F(UPDATED_CONVERSION_2, updatedConversion2, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \ + F(PP_REDUCED_BY_SPITE, ppReducedBySpite, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \ + F(EXTRAPOLATED_MOVE_FLAGS, extrapolatedMoveFlags, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \ + /* Ability data settings */ \ + F(UPDATED_ABILITY_DATA, updatedAbilityData, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \ + /* Move accuracy settings */ \ + F(TOXIC_NEVER_MISS, toxicNeverMiss, (u32, GEN_COUNT - 1)) \ + F(MINIMIZE_DMG_ACC, minimizeDmgAcc, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \ + F(BLIZZARD_HAIL, blizzardHail, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \ + F(SHEER_COLD_ACC, sheerColdAcc, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \ + /* Move stat change settings */ \ + F(FELL_STINGER_STAT_RAISE, fellStingerStatRaise, (u32, GEN_COUNT - 1)) \ + F(KINGS_SHIELD_LOWER_ATK, kingsShieldLowerAtk, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \ + F(SPEED_BUFFING_RAPID_SPIN, speedBuffingRapidSpin, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \ + F(CHARGE_SPDEF_RAISE, chargeSpDefRaise, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \ + F(MINIMIZE_EVASION, minimizeEvasion, (u32, GEN_COUNT - 1)) \ + F(GROWTH_STAT_RAISE, growthStatRaise, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \ + F(FOCUS_ENERGY_CRIT_RATIO, focusEnergyCritRatio, (u32, GEN_COUNT - 1)) \ + /* Other move settings */ \ + F(INCINERATE_GEMS, incinerateGems, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \ + F(CAN_SPITE_FAIL, canSpiteFail, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \ + F(CRASH_IF_TARGET_IMMUNE, crashIfTargetImmune, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \ + F(MEMENTO_FAIL, mementoFail, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \ + F(GLARE_GHOST, glareGhost, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \ + F(SKILL_SWAP, skillSwap, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \ + F(BRICK_BREAK, brickBreak, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \ + F(WISH_HP_SOURCE, wishHpSource, (u32, GEN_COUNT - 1)) \ + F(RAMPAGE_CANCELLING, rampageCancelling, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \ + F(HEAL_BLOCKING, healBlocking, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \ + F(ROOTED_GROUNDING, rootedGrounding, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \ + F(METRONOME_MOVES, metronomeMoves, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \ + F(TELEPORT_BEHAVIOR, teleportBehavior, (u32, GEN_COUNT - 1)) \ + F(BEAT_UP, beatUp, (u32, GEN_COUNT - 1)) \ + F(DARK_VOID_FAIL, darkVoidFail, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \ + F(BURN_HIT_THAW, burnHitThaw, (u32, GEN_COUNT - 1)) \ + F(HEALING_WISH_SWITCH, healingWishSwitch, (u32, GEN_COUNT - 1)) \ + F(DEFOG_EFFECT_CLEARING, defogEffectClearing, (u32, GEN_COUNT - 1)) \ + F(STOCKPILE_RAISES_DEFS, stockpileRaisesDefs, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \ + F(TRANSFORM_SHINY, transformShiny, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \ + F(TRANSFORM_FORM_CHANGES, transformFormChanges, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \ + F(WIDE_GUARD, wideGuard, (u32, GEN_COUNT - 1)) \ + F(QUICK_GUARD, quickGuard, (u32, GEN_COUNT - 1)) \ + F(IMPRISON, imprison, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \ + F(ALLY_SWITCH_FAIL_CHANCE, allySwitchFailChance, (u32, GEN_COUNT - 1)) \ + F(SKETCH_BANS, sketchBans, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \ + F(KNOCK_OFF_REMOVAL, knockOffRemoval, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \ + F(HEAL_BELL_SOUNDPROOF, healBellSoundproof, (u32, GEN_COUNT - 1)) \ + F(CHARGE, charge, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \ + F(POWDER_RAIN, powderRain, (u32, GEN_COUNT - 1)) \ + F(AFTER_YOU_TURN_ORDER, afterYouTurnOrder, (u32, GEN_COUNT - 1)) \ + F(QUASH_TURN_ORDER, quashTurnOrder, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \ + F(DESTINY_BOND_FAIL, destinyBondFail, (u32, GEN_COUNT - 1)) \ + F(PURSUIT_TARGET, pursuitTarget, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \ + F(SKIP_RECHARGE, skipRecharge, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \ + F(ENCORE_TARGET, encoreTarget, (u32, GEN_COUNT - 1)) \ + F(TIME_OF_DAY_HEALING_MOVES, timeOfDayHealingMoves, (u32, GEN_COUNT - 1)) \ + F(DREAM_EATER_LIQUID_OOZE, dreamEaterLiquidOoze, (u32, GEN_COUNT - 1)) \ + /* Ability settings */ \ + F(GALE_WINGS, galeWings, (u32, GEN_COUNT - 1)) \ + F(STANCE_CHANGE_FAIL, stanceChangeFail, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \ + F(SHADOW_TAG_ESCAPE, shadowTagEscape, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \ + F(MOODY_ACC_EVASION, moodyAccEvasion, (u32, GEN_COUNT - 1)) \ + F(FLASH_FIRE_FROZEN, flashFireFrozen, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \ + F(SYNCHRONIZE_TOXIC, synchronizeToxic, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \ + F(UPDATED_INTIMIDATE, updatedIntimidate, (u32, GEN_COUNT - 1)) \ + F(OBLIVIOUS_TAUNT, obliviousTaunt, (u32, GEN_COUNT - 1)) \ + F(STURDY, sturdy, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \ + F(PLUS_MINUS_INTERACTION, plusMinusInteraction, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \ + F(WEATHER_FORMS, weatherForms, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \ + F(SYMBIOSIS_GEMS, symbiosisGems, (u32, GEN_COUNT - 1)) \ + F(ABSORBING_ABILITY_STRING, absorbingAbilityString, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \ + F(REDIRECT_ABILITY_IMMUNITY, redirectAbilityImmunity, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \ + F(REDIRECT_ABILITY_ALLIES, redirectAbilityAllies, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \ + F(LEAF_GUARD_PREVENTS_REST, leafGuardPreventsRest, (u32, GEN_COUNT - 1)) \ + F(TRANSISTOR_BOOST, transistorBoost, (u32, GEN_COUNT - 1)) \ + F(ILLUMINATE_EFFECT, illuminateEffect, (u32, GEN_COUNT - 1)) \ + F(WEAK_ARMOR_SPEED, weakArmorSpeed, (u32, GEN_COUNT - 1)) \ + F(PROTEAN_LIBERO, proteanLibero, (u32, GEN_COUNT - 1)) \ + F(INTREPID_SWORD, intrepidSword, (u32, GEN_COUNT - 1)) \ + F(DAUNTLESS_SHIELD, dauntlessShield, (u32, GEN_COUNT - 1)) \ + F(DISGUISE_HP_LOSS, disguiseHpLoss, (u32, GEN_COUNT - 1)) \ + F(ABILITY_TRIGGER_CHANCE, abilityTriggerChance, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \ + F(PICKUP_WILD, pickupWild, (u32, GEN_COUNT - 1)) \ + F(MAGIC_GUARD, magicGuard, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \ + F(BATTLE_BOND, battleBond, (u32, GEN_COUNT - 1)) \ + F(ATE_MULTIPLIER, ateMultiplier, (u32, GEN_COUNT - 1)) \ + F(DEFIANT_STICKY_WEB, defiantStickyWeb, (u32, GEN_COUNT - 1)) \ + /* Item settings */ \ + F(CONFUSE_BERRIES_HEAL, confuseBerriesHeal, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \ + F(X_ITEMS_BUFF, xItemsBuff, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \ + F(MENTAL_HERB, mentalHerb, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \ + F(TRAINERS_KNOCK_OFF_ITEMS, trainersKnockOffItems, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \ + F(RETURN_STOLEN_NPC_ITEMS, returnStolenNpcItems, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \ + F(STEAL_WILD_ITEMS, stealWildItems, (u32, GEN_COUNT - 1)) \ + F(RESTORE_HELD_BATTLE_ITEMS, restoreHeldBattleItems, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \ + F(SOUL_DEW_BOOST, soulDewBoost, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \ + F(NET_BALL_MODIFIER, netBallModifier, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \ + F(DIVE_BALL_MODIFIER, diveBallModifier, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \ + F(NEST_BALL_MODIFIER, nestBallModifier, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \ + F(REPEAT_BALL_MODIFIER, repeatBallModifier, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \ + F(TIMER_BALL_MODIFIER, timerBallModifier, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \ + F(DUSK_BALL_MODIFIER, duskBallModifier, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \ + F(QUICK_BALL_MODIFIER, quickBallModifier, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \ + F(LURE_BALL_MODIFIER, lureBallModifier, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \ + F(HEAVY_BALL_MODIFIER, heavyBallModifier, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \ + F(DREAM_BALL_MODIFIER, dreamBallModifier, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \ + F(SPORT_BALL_MODIFIER, sportBallModifier, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \ + F(SAFARI_BALL_MODIFIER, safariBallModifier, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \ + F(FRIEND_BALL_MODIFIER, friendBallModifier, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \ + F(SERENE_GRACE_BOOST, sereneGraceBoost, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \ + F(IRON_BALL, ironBall, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \ + /* Weather settings */ \ + F(ABILITY_WEATHER, abilityWeather, (u32, GEN_COUNT - 1)) \ + F(SANDSTORM_SPDEF_BOOST, sandstormSpDefBoost, (u32, GEN_COUNT - 1)) \ + F(OVERWORLD_FOG, overworldFog, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \ + F(OVERWORLD_SNOW, overworldSnow, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \ + F(SNOW_WARNING, snowWarning, (u32, GEN_COUNT - 1)) \ + F(PREFERRED_ICE_WEATHER, preferredIceWeather, (u32, B_ICE_WEATHER_SNOW)) /* TODO: use in tests */ \ + /* Terrain settings */ \ + F(TERRAIN_TYPE_BOOST, terrainTypeBoost, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \ + F(SECRET_POWER_EFFECT, secretPowerEffect, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \ + F(SECRET_POWER_ANIMATION, secretPowerAnimation, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \ + F(NATURE_POWER_MOVES, naturePowerMoves, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \ + F(CAMOUFLAGE_TYPES, camouflageTypes, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \ + /* Other settings */ \ + F(WILD_NATURAL_ENEMIES, wildNaturalEnemies, (u32, TRUE)) /* TODO: use in tests */ \ + F(AFFECTION_MECHANICS, affectionMechanics, (u32, TRUE)) /* TODO: use in tests */ \ + F(OBEDIENCE_MECHANICS, obedienceMechanics, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \ + F(USE_FROSTBITE, useFrostbite, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \ + + +#define GET_CONFIG_MAXIMUM(_typeMaxValue, ...) INVOKE_WITH_B(GET_CONFIG_MAXIMUM_, _typeMaxValue) +#define GET_CONFIG_MAXIMUM_(_type, ...) FIRST(__VA_OPT__(FIRST(__VA_ARGS__),) MAX_BITS((sizeof(_type) * 8))) + +#define UNPACK_CONFIG_ENUMS(_name, ...) CONFIG_##_name, + +enum ConfigTag { - GEN_CONFIG_CRIT_CHANCE, - GEN_CONFIG_CRIT_MULTIPLIER, - GEN_CONFIG_FOCUS_ENERGY_CRIT_RATIO, - GEN_CONFIG_PARALYSIS_SPEED, - GEN_CONFIG_CONFUSION_SELF_DMG_CHANCE, - GEN_CONFIG_MULTI_HIT_CHANCE, - GEN_CONFIG_GALE_WINGS, - GEN_CONFIG_HEAL_BELL_SOUNDPROOF, - GEN_CONFIG_TELEPORT_BEHAVIOR, - GEN_CONFIG_ABILITY_WEATHER, - GEN_CONFIG_MOODY_STATS, - GEN_CONFIG_BATTLE_BOND, - GEN_CONFIG_ATE_MULTIPLIER, - GEN_CONFIG_FELL_STINGER_STAT_RAISE, - GEN_CONFIG_DEFIANT_STICKY_WEB, - GEN_CONFIG_ENCORE_TARGET, - GEN_CONFIG_TIME_OF_DAY_HEALING_MOVES, - GEN_PICKUP_WILD, - GEN_PROTEAN_LIBERO, - GEN_INTREPID_SWORD, - GEN_DAUNTLESS_SHIELD, - GEN_ILLUMINATE_EFFECT, - GEN_STEAL_WILD_ITEMS, - GEN_SNOW_WARNING, - GEN_ALLY_SWITCH_FAIL_CHANCE, - GEN_DREAM_EATER_LIQUID_OOZE, - GEN_CONFIG_TRANSISTOR_BOOST, - GEN_CONFIG_RECALC_TURN_AFTER_ACTIONS, - GEN_CONFIG_UPDATED_INTIMIDATE, - GEN_CONFIG_DISGUISE_HP_LOSS, - GEN_CONFIG_AFTER_YOU_TURN_ORDER, - GEN_CONFIG_HEALING_WISH_SWITCH, - GEN_CONFIG_MEGA_EVO_TURN_ORDER, - GEN_CONFIG_SHEER_COLD_IMMUNITY, - GEN_CONFIG_WEAK_ARMOR_SPEED, - GEN_CONFIG_PRANKSTER_DARK_TYPES, - GEN_CONFIG_DESTINY_BOND_FAIL, - GEN_CONFIG_POWDER_RAIN, - GEN_CONFIG_POWDER_GRASS, - GEN_CONFIG_POWDER_OVERCOAT, - GEN_CONFIG_OBLIVIOUS_TAUNT, - GEN_CONFIG_TOXIC_NEVER_MISS, - GEN_CONFIG_PARALYZE_ELECTRIC, - GEN_CONFIG_BADGE_BOOST, - GEN_CONFIG_LEAF_GUARD_PREVENTS_REST, - GEN_CONFIG_COUNT + CONFIG_DEFINITIONS(UNPACK_CONFIG_ENUMS) + CONFIG_COUNT }; #endif // GUARD_CONSTANTS_GENERATIONAL_CHANGES_H diff --git a/include/constants/global.h b/include/constants/global.h index b2d892014c..fa0ebbcc0f 100644 --- a/include/constants/global.h +++ b/include/constants/global.h @@ -1,17 +1,33 @@ #ifndef GUARD_CONSTANTS_GLOBAL_H #define GUARD_CONSTANTS_GLOBAL_H -#include "config/general.h" -#include "config/battle.h" -#include "config/debug.h" -#include "config/item.h" -#include "config/caps.h" -#include "config/pokemon.h" -#include "config/overworld.h" -#include "config/dexnav.h" -#include "config/summary_screen.h" +// You can use the ENABLED_ON_RELEASE and DISABLED_ON_RELEASE macros to +// control whether a feature is enabled or disabled when making a release build. +// +// For example, the overworld debug menu is enabled by default, but when using +// `make release`, it will be automatically disabled. +// +// #define DEBUG_OVERWORLD_MENU DISABLED_ON_RELEASE +#ifdef RELEASE +#define ENABLED_ON_RELEASE TRUE +#define DISABLED_ON_RELEASE FALSE +#else +#define ENABLED_ON_RELEASE FALSE +#define DISABLED_ON_RELEASE TRUE +#endif + #include "config/ai.h" +#include "config/battle.h" +#include "config/caps.h" +#include "config/contest.h" +#include "config/debug.h" +#include "config/dexnav.h" #include "config/follower_npc.h" +#include "config/general.h" +#include "config/item.h" +#include "config/overworld.h" +#include "config/pokemon.h" +#include "config/summary_screen.h" // Invalid Versions show as "----------" in Gen 4 and Gen 5's summary screen. // In Gens 6 and 7, invalid versions instead show "a distant land" in the summary screen. @@ -101,12 +117,14 @@ #define ALL_MOVES_MASK ((1 << MAX_MON_MOVES) - 1) #define CONTESTANT_COUNT 4 -#define CONTEST_CATEGORY_COOL 0 -#define CONTEST_CATEGORY_BEAUTY 1 -#define CONTEST_CATEGORY_CUTE 2 -#define CONTEST_CATEGORY_SMART 3 -#define CONTEST_CATEGORY_TOUGH 4 -#define CONTEST_CATEGORIES_COUNT 5 +#define CONTEST_CATEGORY_COOL 0 +#define CONTEST_CATEGORY_BEAUTIFUL 1 +#define CONTEST_CATEGORY_BEAUTY CONTEST_CATEGORY_BEAUTIFUL +#define CONTEST_CATEGORY_CUTE 2 +#define CONTEST_CATEGORY_CLEVER 3 +#define CONTEST_CATEGORY_SMART CONTEST_CATEGORY_CLEVER +#define CONTEST_CATEGORY_TOUGH 4 +#define CONTEST_CATEGORIES_COUNT 5 // string lengths #define ITEM_NAME_LENGTH 20 @@ -148,6 +166,7 @@ #define OPTIONS_TEXT_SPEED_SLOW 0 #define OPTIONS_TEXT_SPEED_MID 1 #define OPTIONS_TEXT_SPEED_FAST 2 +#define OPTIONS_TEXT_SPEED_INSTANT 3 #define OPTIONS_SOUND_MONO 0 #define OPTIONS_SOUND_STEREO 1 diff --git a/include/constants/hold_effects.h b/include/constants/hold_effects.h index 101a198b81..32dacc36d3 100644 --- a/include/constants/hold_effects.h +++ b/include/constants/hold_effects.h @@ -1,7 +1,7 @@ #ifndef GUARD_HOLD_EFFECTS_H #define GUARD_HOLD_EFFECTS_H -enum ItemHoldEffect +enum __attribute__((packed)) HoldEffect { HOLD_EFFECT_NONE, HOLD_EFFECT_RESTORE_HP, @@ -120,7 +120,7 @@ enum ItemHoldEffect // Gen7 hold effects HOLD_EFFECT_PROTECTIVE_PADS, HOLD_EFFECT_TERRAIN_EXTENDER, - HOLD_EFFECT_SEEDS, + HOLD_EFFECT_TERRAIN_SEED, HOLD_EFFECT_ADRENALINE_ORB, HOLD_EFFECT_MEMORY, HOLD_EFFECT_Z_CRYSTAL, @@ -151,4 +151,12 @@ enum ItemHoldEffect #define HOLD_EFFECT_PARAM_MISTY_TERRAIN 2 #define HOLD_EFFECT_PARAM_PSYCHIC_TERRAIN 3 +enum ItemActivationState +{ + ACTIVATION_ON_USABLE_AGAIN, + ACTIVATION_ON_PICK_UP, + ACTIVATION_ON_HARVEST, + ACTIVATION_ON_HP_THRESHOLD, +}; + #endif // GUARD_HOLD_EFFECTS_H diff --git a/include/constants/item_effects.h b/include/constants/item_effects.h index dbe322beac..037f28c4bc 100644 --- a/include/constants/item_effects.h +++ b/include/constants/item_effects.h @@ -93,6 +93,9 @@ #define ITEM_EFFECT_HEAL_PP 21 #define ITEM_EFFECT_NONE 22 +#define ITEM_FRIENDSHIP_MAPSEC_BONUS 1 // The amount of bonus friendship gained when an item is used on a Pokémon whose met location matches the current map section. +#define ITEM_FRIENDSHIP_LUXURY_BONUS 1 // The amount of bonus friendship gained when a Pokémon is in the Luxury Ball. + // Since X item stat increases are now handled by battle scripts, the friendship increase effect is now handled by the battle controller in HandleAction_UseItem. #define X_ITEM_FRIENDSHIP_INCREASE 1 // The amount of friendship gained by using an X item on a Pokémon in battle. #define X_ITEM_MAX_FRIENDSHIP 200 // Friendship threshold at which Pokémon stop receiving a friendship increase from using X items on them in battle. diff --git a/include/constants/items.h b/include/constants/items.h index 58f453414f..ca25c57c3c 100644 --- a/include/constants/items.h +++ b/include/constants/items.h @@ -994,10 +994,34 @@ #define ITEM_STRANGE_BALL 828 -// HOPO BERRY -// LEGEND PLATE +#define ITEM_CLEFABLITE 829 +#define ITEM_VICTREEBELITE 830 +#define ITEM_STARMINITE 831 +#define ITEM_DRAGONINITE 832 +#define ITEM_MEGANIUMITE 833 +#define ITEM_FERALIGITE 834 +#define ITEM_SKARMORITE 835 +#define ITEM_FROSLASSITE 836 +#define ITEM_EMBOARITE 837 +#define ITEM_EXCADRITE 838 +#define ITEM_SCOLIPITE 839 +#define ITEM_SCRAFTINITE 840 +#define ITEM_EELEKTROSSITE 841 +#define ITEM_CHANDELURITE 842 +#define ITEM_CHESNAUGHTITE 843 +#define ITEM_DELPHOXITE 844 +#define ITEM_GRENINJITE 845 +#define ITEM_PYROARITE 846 +#define ITEM_FLOETTITE 847 +#define ITEM_MALAMARITE 848 +#define ITEM_BARBARACITE 849 +#define ITEM_DRAGALGITE 850 +#define ITEM_HAWLUCHANITE 851 +#define ITEM_ZYGARDITE 852 +#define ITEM_DRAMPANITE 853 +#define ITEM_FALINKSITE 854 -#define ITEMS_COUNT 829 +#define ITEMS_COUNT 855 #define ITEM_FIELD_ARROW ITEMS_COUNT // A special item id associated with "Cancel"/"Exit" etc. in a list of items or decorations diff --git a/include/constants/move_relearner.h b/include/constants/move_relearner.h new file mode 100644 index 0000000000..0229cb7f17 --- /dev/null +++ b/include/constants/move_relearner.h @@ -0,0 +1,29 @@ +#ifndef GUARD_CONSTANTS_MOVE_RELEARNER_H +#define GUARD_CONSTANTS_MOVE_RELEARNER_H + +// Max number of moves shown by the move relearner. +// Increased from 25 to 60 so Mew can display all TMs/HMs. +// If you plan on adding more TMs, increase this number too. +#define MAX_RELEARNER_MOVES 60 + +// Move Relearner menu change constants +enum MoveRelearnerStates +{ + MOVE_RELEARNER_LEVEL_UP_MOVES, + MOVE_RELEARNER_EGG_MOVES, + MOVE_RELEARNER_TM_MOVES, + MOVE_RELEARNER_TUTOR_MOVES, + MOVE_RELEARNER_COUNT, +}; + +enum RelearnMode +{ + RELEARN_MODE_NONE = 0, + RELEARN_MODE_SCRIPT = 1, // Relearning moves through an event script + // These two must stay 2 and 3, they are tied to the summary screen pages + RELEARN_MODE_PSS_PAGE_BATTLE_MOVES = 2, // Relearning moves through the summary screen's battle moves page + RELEARN_MODE_PSS_PAGE_CONTEST_MOVES = 3, // Relearning moves through the summary screen's contest moves page (defaults to contest page on relearner screen) + RELEARN_MODE_PARTY_MENU = 4, // Relearning moves through the party menu's moves submenu +}; + +#endif // GUARD_CONSTANTS_MOVE_RELEARNER_H diff --git a/include/constants/pokemon.h b/include/constants/pokemon.h index b2e6b23ead..59bf27d823 100644 --- a/include/constants/pokemon.h +++ b/include/constants/pokemon.h @@ -2,28 +2,31 @@ #define GUARD_CONSTANTS_POKEMON_H // Pokémon types -#define TYPE_NONE 0 -#define TYPE_NORMAL 1 -#define TYPE_FIGHTING 2 -#define TYPE_FLYING 3 -#define TYPE_POISON 4 -#define TYPE_GROUND 5 -#define TYPE_ROCK 6 -#define TYPE_BUG 7 -#define TYPE_GHOST 8 -#define TYPE_STEEL 9 -#define TYPE_MYSTERY 10 -#define TYPE_FIRE 11 -#define TYPE_WATER 12 -#define TYPE_GRASS 13 -#define TYPE_ELECTRIC 14 -#define TYPE_PSYCHIC 15 -#define TYPE_ICE 16 -#define TYPE_DRAGON 17 -#define TYPE_DARK 18 -#define TYPE_FAIRY 19 -#define TYPE_STELLAR 20 -#define NUMBER_OF_MON_TYPES 21 +enum __attribute__((packed)) Type +{ + TYPE_NONE = 0, + TYPE_NORMAL = 1, + TYPE_FIGHTING = 2, + TYPE_FLYING = 3, + TYPE_POISON = 4, + TYPE_GROUND = 5, + TYPE_ROCK = 6, + TYPE_BUG = 7, + TYPE_GHOST = 8, + TYPE_STEEL = 9, + TYPE_MYSTERY = 10, + TYPE_FIRE = 11, + TYPE_WATER = 12, + TYPE_GRASS = 13, + TYPE_ELECTRIC = 14, + TYPE_PSYCHIC = 15, + TYPE_ICE = 16, + TYPE_DRAGON = 17, + TYPE_DARK = 18, + TYPE_FAIRY = 19, + TYPE_STELLAR = 20, + NUMBER_OF_MON_TYPES +}; // Pokémon egg groups #define EGG_GROUP_NONE 0 @@ -74,16 +77,18 @@ #define NUM_NATURES 25 // Pokémon Stats -#define STAT_HP 0 -#define STAT_ATK 1 -#define STAT_DEF 2 -#define STAT_SPEED 3 -#define STAT_SPATK 4 -#define STAT_SPDEF 5 -#define NUM_STATS 6 - -#define STAT_ACC 6 // Only in battles. -#define STAT_EVASION 7 // Only in battles. +enum __attribute__((packed)) Stat +{ + STAT_HP, + STAT_ATK, + STAT_DEF, + STAT_SPEED, + STAT_SPATK, + STAT_SPDEF, + NUM_STATS, + STAT_ACC = NUM_STATS, // Only in battles. + STAT_EVASION, // Only in battles. +}; #define NUM_NATURE_STATS (NUM_STATS - 1) // excludes HP #define NUM_BATTLE_STATS (NUM_STATS + 2) // includes Accuracy and Evasion @@ -169,7 +174,6 @@ #define LEVEL_UP_MOVE_END 0xFFFF #define MAX_LEVEL_UP_MOVES 20 -#define MAX_RELEARNER_MOVES max(MAX_LEVEL_UP_MOVES, 25) #define MON_MALE 0x00 #define MON_FEMALE 0xFE @@ -218,7 +222,7 @@ #define EV_ITEM_RAISE_LIMIT ((I_VITAMIN_EV_CAP >= GEN_8) ? MAX_PER_STAT_EVS : 100) // Move category defines. -enum DamageCategory +enum __attribute__((packed)) DamageCategory { DAMAGE_CATEGORY_PHYSICAL, DAMAGE_CATEGORY_SPECIAL, @@ -300,6 +304,8 @@ enum EvolutionConditions { IF_PID_MODULO_100_LT, // The Pokémon's personality value's modulo by 100 is lower than the defined value. IF_MIN_OVERWORLD_STEPS, // The Player has taken a specific amount of steps in the overworld with the Pokémon following them or in the first slot of the party. IF_BAG_ITEM_COUNT, // The Player has the specific amount of an item in the bag. It then removes those items. + IF_REGION, // The Player is in the specific region. + IF_NOT_REGION, // The Player is NOT in the specific region. CONDITIONS_END }; diff --git a/include/constants/rtc.h b/include/constants/rtc.h index 65ee9c35ed..ea0748b506 100644 --- a/include/constants/rtc.h +++ b/include/constants/rtc.h @@ -81,7 +81,7 @@ #define NIGHT_HOUR_END 6 #endif -// TIMES_OF_DAY_COUNT must be last +// TIMES_OF_DAY_COUNT must be last or things will break enum TimeOfDay { TIME_MORNING, @@ -91,6 +91,10 @@ enum TimeOfDay TIMES_OF_DAY_COUNT, }; +// for incrementing/decrementing +#define TIME_FIRST 0 +#define TIME_LAST (TIMES_OF_DAY_COUNT - 1) + #define TIME_OF_DAY_DEFAULT 0 #endif // GUARD_CONSTANTS_RTC_H diff --git a/include/constants/script_commands.h b/include/constants/script_commands.h new file mode 100644 index 0000000000..4adf99ccef --- /dev/null +++ b/include/constants/script_commands.h @@ -0,0 +1,238 @@ +// +// DO NOT MODIFY THIS FILE! It is auto-generated by tools/misc/make_scr_cmd_constants.py +// +#ifndef GUARD_SCR_CMD_CONSTANTS_H +#define GUARD_SCR_CMD_CONSTANTS_H + +#define SCR_OP_NOP 0x00 +#define SCR_OP_NOP1 0x01 +#define SCR_OP_END 0x02 +#define SCR_OP_RETURN 0x03 +#define SCR_OP_CALL 0x04 +#define SCR_OP_GOTO 0x05 +#define SCR_OP_GOTO_IF 0x06 +#define SCR_OP_CALL_IF 0x07 +#define SCR_OP_GOTO_STD 0x08 +#define SCR_OP_CALL_STD 0x09 +#define SCR_OP_GOTO_STD_IF 0x0a +#define SCR_OP_CALL_STD_IF 0x0b +#define SCR_OP_RETURNRAM 0x0c +#define SCR_OP_ENDRAM 0x0d +#define SCR_OP_SETMYSTERYEVENTSTATUS 0x0e +#define SCR_OP_LOAD_WORD 0x0f +#define SCR_OP_LOAD_BYTE 0x10 +#define SCR_OP_SETPTR 0x11 +#define SCR_OP_LOADBYTEFROMPTR 0x12 +#define SCR_OP_SETPTRBYTE 0x13 +#define SCR_OP_COPYLOCAL 0x14 +#define SCR_OP_COPYBYTE 0x15 +#define SCR_OP_SETVAR 0x16 +#define SCR_OP_ADDVAR 0x17 +#define SCR_OP_SUBVAR 0x18 +#define SCR_OP_COPYVAR 0x19 +#define SCR_OP_SETORCOPYVAR 0x1a +#define SCR_OP_COMPARE_LOCAL_TO_LOCAL 0x1b +#define SCR_OP_COMPARE_LOCAL_TO_VALUE 0x1c +#define SCR_OP_COMPARE_LOCAL_TO_PTR 0x1d +#define SCR_OP_COMPARE_PTR_TO_LOCAL 0x1e +#define SCR_OP_COMPARE_PTR_TO_VALUE 0x1f +#define SCR_OP_COMPARE_PTR_TO_PTR 0x20 +#define SCR_OP_COMPARE_VAR_TO_VALUE 0x21 +#define SCR_OP_COMPARE_VAR_TO_VAR 0x22 +#define SCR_OP_CALLNATIVE 0x23 +#define SCR_OP_GOTONATIVE 0x24 +#define SCR_OP_SPECIAL 0x25 +#define SCR_OP_SPECIALVAR 0x26 +#define SCR_OP_WAITSTATE 0x27 +#define SCR_OP_DELAY 0x28 +#define SCR_OP_SETFLAG 0x29 +#define SCR_OP_CLEARFLAG 0x2a +#define SCR_OP_CHECKFLAG 0x2b +#define SCR_OP_INITCLOCK 0x2c +#define SCR_OP_DOTIMEBASEDEVENTS 0x2d +#define SCR_OP_GETTIME 0x2e +#define SCR_OP_PLAYSE 0x2f +#define SCR_OP_WAITSE 0x30 +#define SCR_OP_PLAYFANFARE 0x31 +#define SCR_OP_WAITFANFARE 0x32 +#define SCR_OP_PLAYBGM 0x33 +#define SCR_OP_SAVEBGM 0x34 +#define SCR_OP_FADEDEFAULTBGM 0x35 +#define SCR_OP_FADENEWBGM 0x36 +#define SCR_OP_FADEOUTBGM 0x37 +#define SCR_OP_FADEINBGM 0x38 +#define SCR_OP_WARP 0x39 +#define SCR_OP_WARPSILENT 0x3a +#define SCR_OP_WARPDOOR 0x3b +#define SCR_OP_WARPHOLE 0x3c +#define SCR_OP_WARPTELEPORT 0x3d +#define SCR_OP_SETWARP 0x3e +#define SCR_OP_SETDYNAMICWARP 0x3f +#define SCR_OP_SETDIVEWARP 0x40 +#define SCR_OP_SETHOLEWARP 0x41 +#define SCR_OP_GETPLAYERXY 0x42 +#define SCR_OP_GETPARTYSIZE 0x43 +#define SCR_OP_ADDITEM 0x44 +#define SCR_OP_REMOVEITEM 0x45 +#define SCR_OP_CHECKITEMSPACE 0x46 +#define SCR_OP_CHECKITEM 0x47 +#define SCR_OP_CHECKITEMTYPE 0x48 +#define SCR_OP_ADDPCITEM 0x49 +#define SCR_OP_CHECKPCITEM 0x4a +#define SCR_OP_ADDDECORATION 0x4b +#define SCR_OP_REMOVEDECORATION 0x4c +#define SCR_OP_CHECKDECOR 0x4d +#define SCR_OP_CHECKDECORSPACE 0x4e +#define SCR_OP_APPLYMOVEMENT 0x4f +#define SCR_OP_APPLYMOVEMENTAT 0x50 +#define SCR_OP_WAITMOVEMENT 0x51 +#define SCR_OP_WAITMOVEMENTAT 0x52 +#define SCR_OP_REMOVEOBJECT 0x53 +#define SCR_OP_REMOVEOBJECTAT 0x54 +#define SCR_OP_ADDOBJECT 0x55 +#define SCR_OP_ADDOBJECTAT 0x56 +#define SCR_OP_SETOBJECTXY 0x57 +#define SCR_OP_SHOWOBJECTAT 0x58 +#define SCR_OP_HIDEOBJECTAT 0x59 +#define SCR_OP_FACEPLAYER 0x5a +#define SCR_OP_TURNOBJECT 0x5b +#define SCR_OP_TRAINERBATTLE 0x5c +#define SCR_OP_DOTRAINERBATTLE 0x5d +#define SCR_OP_GOTOPOSTBATTLESCRIPT 0x5e +#define SCR_OP_GOTOBEATENSCRIPT 0x5f +#define SCR_OP_CHECKTRAINERFLAG 0x60 +#define SCR_OP_SETTRAINERFLAG 0x61 +#define SCR_OP_CLEARTRAINERFLAG 0x62 +#define SCR_OP_SETOBJECTXYPERM 0x63 +#define SCR_OP_COPYOBJECTXYTOPERM 0x64 +#define SCR_OP_SETOBJECTMOVEMENTTYPE 0x65 +#define SCR_OP_WAITMESSAGE 0x66 +#define SCR_OP_MESSAGE 0x67 +#define SCR_OP_CLOSEMESSAGE 0x68 +#define SCR_OP_LOCKALL 0x69 +#define SCR_OP_LOCK 0x6a +#define SCR_OP_RELEASEALL 0x6b +#define SCR_OP_RELEASE 0x6c +#define SCR_OP_WAITBUTTONPRESS 0x6d +#define SCR_OP_YESNOBOX 0x6e +#define SCR_OP_MULTICHOICE 0x6f +#define SCR_OP_MULTICHOICEDEFAULT 0x70 +#define SCR_OP_MULTICHOICEGRID 0x71 +#define SCR_OP_DRAWBOX 0x72 +#define SCR_OP_ERASEBOX 0x73 +#define SCR_OP_DRAWBOXTEXT 0x74 +#define SCR_OP_SHOWMONPIC 0x75 +#define SCR_OP_HIDEMONPIC 0x76 +#define SCR_OP_SHOWCONTESTPAINTING 0x77 +#define SCR_OP_BRAILLEMESSAGE 0x78 +#define SCR_OP_GIVEMON 0x79 +#define SCR_OP_GIVEEGG 0x7a +#define SCR_OP_SETMONMOVE 0x7b +#define SCR_OP_CHECKFIELDMOVE 0x7c +#define SCR_OP_BUFFERSPECIESNAME 0x7d +#define SCR_OP_BUFFERLEADMONSPECIESNAME 0x7e +#define SCR_OP_BUFFERPARTYMONNICK 0x7f +#define SCR_OP_BUFFERITEMNAME 0x80 +#define SCR_OP_BUFFERDECORATIONNAME 0x81 +#define SCR_OP_BUFFERMOVENAME 0x82 +#define SCR_OP_BUFFERNUMBERSTRING 0x83 +#define SCR_OP_BUFFERSTDSTRING 0x84 +#define SCR_OP_BUFFERSTRING 0x85 +#define SCR_OP_POKEMART 0x86 +#define SCR_OP_POKEMARTDECORATION 0x87 +#define SCR_OP_POKEMARTDECORATION2 0x88 +#define SCR_OP_PLAYSLOTMACHINE 0x89 +#define SCR_OP_SETBERRYTREE 0x8a +#define SCR_OP_CHOOSECONTESTMON 0x8b +#define SCR_OP_STARTCONTEST 0x8c +#define SCR_OP_SHOWCONTESTRESULTS 0x8d +#define SCR_OP_CONTESTLINKTRANSFER 0x8e +#define SCR_OP_RANDOM 0x8f +#define SCR_OP_ADDMONEY 0x90 +#define SCR_OP_REMOVEMONEY 0x91 +#define SCR_OP_CHECKMONEY 0x92 +#define SCR_OP_SHOWMONEYBOX 0x93 +#define SCR_OP_HIDEMONEYBOX 0x94 +#define SCR_OP_UPDATEMONEYBOX 0x95 +#define SCR_OP_GETPOKENEWSACTIVE 0x96 +#define SCR_OP_FADESCREEN 0x97 +#define SCR_OP_FADESCREENSPEED 0x98 +#define SCR_OP_SETFLASHLEVEL 0x99 +#define SCR_OP_ANIMATEFLASH 0x9a +#define SCR_OP_MESSAGEAUTOSCROLL 0x9b +#define SCR_OP_DOFIELDEFFECT 0x9c +#define SCR_OP_SETFIELDEFFECTARGUMENT 0x9d +#define SCR_OP_WAITFIELDEFFECT 0x9e +#define SCR_OP_SETRESPAWN 0x9f +#define SCR_OP_CHECKPLAYERGENDER 0xa0 +#define SCR_OP_PLAYMONCRY 0xa1 +#define SCR_OP_SETMETATILE 0xa2 +#define SCR_OP_RESETWEATHER 0xa3 +#define SCR_OP_SETWEATHER 0xa4 +#define SCR_OP_DOWEATHER 0xa5 +#define SCR_OP_SETSTEPCALLBACK 0xa6 +#define SCR_OP_SETMAPLAYOUTINDEX 0xa7 +#define SCR_OP_SETOBJECTSUBPRIORITY 0xa8 +#define SCR_OP_RESETOBJECTSUBPRIORITY 0xa9 +#define SCR_OP_CREATEVOBJECT 0xaa +#define SCR_OP_TURNVOBJECT 0xab +#define SCR_OP_OPENDOOR 0xac +#define SCR_OP_CLOSEDOOR 0xad +#define SCR_OP_WAITDOORANIM 0xae +#define SCR_OP_SETDOOROPEN 0xaf +#define SCR_OP_SETDOORCLOSED 0xb0 +#define SCR_OP_ADDELEVMENUITEM 0xb1 +#define SCR_OP_SHOWELEVMENU 0xb2 +#define SCR_OP_CHECKCOINS 0xb3 +#define SCR_OP_ADDCOINS 0xb4 +#define SCR_OP_REMOVECOINS 0xb5 +#define SCR_OP_SETWILDBATTLE 0xb6 +#define SCR_OP_DOWILDBATTLE 0xb7 +#define SCR_OP_SETVADDRESS 0xb8 +#define SCR_OP_VGOTO 0xb9 +#define SCR_OP_VCALL 0xba +#define SCR_OP_VGOTO_IF 0xbb +#define SCR_OP_VCALL_IF 0xbc +#define SCR_OP_VMESSAGE 0xbd +#define SCR_OP_VBUFFERMESSAGE 0xbe +#define SCR_OP_VBUFFERSTRING 0xbf +#define SCR_OP_SHOWCOINSBOX 0xc0 +#define SCR_OP_HIDECOINSBOX 0xc1 +#define SCR_OP_UPDATECOINSBOX 0xc2 +#define SCR_OP_INCREMENTGAMESTAT 0xc3 +#define SCR_OP_SETESCAPEWARP 0xc4 +#define SCR_OP_WAITMONCRY 0xc5 +#define SCR_OP_BUFFERBOXNAME 0xc6 +#define SCR_OP_TEXTCOLOR 0xc7 +#define SCR_OP_LOADHELP 0xc8 +#define SCR_OP_UNLOADHELP 0xc9 +#define SCR_OP_SIGNMSG 0xca +#define SCR_OP_NORMALMSG 0xcb +#define SCR_OP_COMPAREHIDDENVAR 0xcc +#define SCR_OP_SETMODERNFATEFULENCOUNTER 0xcd +#define SCR_OP_CHECKMODERNFATEFULENCOUNTER 0xce +#define SCR_OP_TRYWONDERCARDSCRIPT 0xcf +#define SCR_OP_SETWORLDMAPFLAG 0xd0 +#define SCR_OP_WARPSPINENTER 0xd1 +#define SCR_OP_SETMONMETLOCATION 0xd2 +#define SCR_OP_MOVEROTATINGTILEOBJECTS 0xd3 +#define SCR_OP_TURNROTATINGTILEOBJECTS 0xd4 +#define SCR_OP_INITROTATINGTILEPUZZLE 0xd5 +#define SCR_OP_FREEROTATINGTILEPUZZLE 0xd6 +#define SCR_OP_WARPMOSSDEEPGYM 0xd7 +#define SCR_OP_SELECTAPPROACHINGTRAINER 0xd8 +#define SCR_OP_LOCKFORTRAINER 0xd9 +#define SCR_OP_CLOSEBRAILLEMESSAGE 0xda +#define SCR_OP_MESSAGEINSTANT 0xdb +#define SCR_OP_FADESCREENSWAPBUFFERS 0xdc +#define SCR_OP_BUFFERTRAINERCLASSNAME 0xdd +#define SCR_OP_BUFFERTRAINERNAME 0xde +#define SCR_OP_POKENAVCALL 0xdf +#define SCR_OP_WARPWHITEFADE 0xe0 +#define SCR_OP_BUFFERCONTESTNAME 0xe1 +#define SCR_OP_BUFFERITEMNAMEPLURAL 0xe2 +#define SCR_OP_DYNMULTICHOICE 0xe3 +#define SCR_OP_DYNMULTIPUSH 0xe4 +#define SCR_OP_HIDEFOLLOWER 0xe5 + +#endif // GUARD_SCR_CMD_CONSTANTS_H diff --git a/include/constants/speaker_names.h b/include/constants/speaker_names.h new file mode 100644 index 0000000000..1f4f399e75 --- /dev/null +++ b/include/constants/speaker_names.h @@ -0,0 +1,11 @@ +#ifndef GUARD_CONSTANTS_SPEAKER_NAMES_H +#define GUARD_CONSTANTS_SPEAKER_NAMES_H + +enum SpeakerNames { + SP_NAME_NONE = 0, + SP_NAME_MOM, + SP_NAME_PLAYER, + SP_NAME_COUNT +}; + +#endif // GUARD_CONSTANTS_SPEAKER_NAMES_H diff --git a/include/constants/species.h b/include/constants/species.h index 3656d7664e..ed31317c36 100644 --- a/include/constants/species.h +++ b/include/constants/species.h @@ -2,7 +2,7 @@ #define GUARD_CONSTANTS_SPECIES_H // NOTE: The defines here are named in order to match Pokémon Showdown's naming conventions. This is done to avoid issues with trainerproc parsing species names. If a Pokémon does not have an entry on Showdown, use your best judgement. -// Additionally, we have tried to reduce down to as few defines as possible, because programs like porymap does not always properly handle having multiple defines. +// Additionally, we have tried to reduce down to as few defines as possible, because programs like porymap do not always properly handle having multiple defines. // Discussion: https://github.com/rh-hideout/pokeemerald-expansion/pull/5075#issuecomment-2384088602 // Showdown: https://github.com/smogon/Pokemon-Showdown/blob/master/data/pokedex.ts @@ -1637,8 +1637,35 @@ #define SPECIES_URSHIFU_RAPID_STRIKE_STYLE_GMAX SPECIES_URSHIFU_RAPID_STRIKE_GMAX #define SPECIES_MIMIKYU_BUSTED_TOTEM 1523 #define SPECIES_MIMIKYU_TOTEM_BUSTED SPECIES_MIMIKYU_BUSTED_TOTEM +// Legends Z-A +#define SPECIES_CLEFABLE_MEGA 1524 +#define SPECIES_VICTREEBEL_MEGA 1525 +#define SPECIES_STARMIE_MEGA 1526 +#define SPECIES_DRAGONITE_MEGA 1527 +#define SPECIES_MEGANIUM_MEGA 1528 +#define SPECIES_FERALIGATR_MEGA 1529 +#define SPECIES_SKARMORY_MEGA 1530 +#define SPECIES_FROSLASS_MEGA 1531 +#define SPECIES_EMBOAR_MEGA 1532 +#define SPECIES_EXCADRILL_MEGA 1533 +#define SPECIES_SCOLIPEDE_MEGA 1534 +#define SPECIES_SCRAFTY_MEGA 1535 +#define SPECIES_EELEKTROSS_MEGA 1536 +#define SPECIES_CHANDELURE_MEGA 1537 +#define SPECIES_CHESNAUGHT_MEGA 1538 +#define SPECIES_DELPHOX_MEGA 1539 +#define SPECIES_GRENINJA_MEGA 1540 +#define SPECIES_PYROAR_MEGA 1541 +#define SPECIES_MALAMAR_MEGA 1542 +#define SPECIES_DRAGALGE_MEGA 1543 +#define SPECIES_HAWLUCHA_MEGA 1544 +#define SPECIES_FLOETTE_MEGA 1545 +#define SPECIES_BARBARACLE_MEGA 1546 +#define SPECIES_ZYGARDE_MEGA 1547 +#define SPECIES_DRAMPA_MEGA 1548 +#define SPECIES_FALINKS_MEGA 1549 -#define SPECIES_EGG (SPECIES_MIMIKYU_BUSTED_TOTEM + 1) +#define SPECIES_EGG (SPECIES_FALINKS_MEGA + 1) #define NUM_SPECIES SPECIES_EGG diff --git a/include/constants/wild_encounter.h b/include/constants/wild_encounter.h index 364d18350f..364dc7b35a 100644 --- a/include/constants/wild_encounter.h +++ b/include/constants/wild_encounter.h @@ -9,7 +9,4 @@ #define NUM_ALTERING_CAVE_TABLES 9 -#define FISHING_CHAIN_LENGTH_MAX 200 -#define FISHING_CHAIN_SHINY_STREAK_MAX 20 - #endif // GUARD_CONSTANTS_WILD_ENCOUNTER_H diff --git a/include/contest.h b/include/contest.h index 80a1370541..278efaa4ac 100644 --- a/include/contest.h +++ b/include/contest.h @@ -302,6 +302,17 @@ struct ContestResources void *animBgTileBuffer; }; +struct ContestCategory +{ + const u8 *name; + const u8 *condition; + const u8 *generic; + const u8 *negativeTrait; + u8 palette; +}; + +extern const struct ContestCategory gContestCategoryInfo[CONTEST_CATEGORIES_COUNT + 1]; + #define eContest (*gContestResources->contest) #define eContestantStatus (gContestResources->status) #define eContestAppealResults (*gContestResources->appealResults) diff --git a/include/contest_effect.h b/include/contest_effect.h index 87129bd792..7db929031b 100644 --- a/include/contest_effect.h +++ b/include/contest_effect.h @@ -1,17 +1,17 @@ #ifndef GUARD_CONTEST_EFFECT_H #define GUARD_CONTEST_EFFECT_H -#define MAX_COMBO_MOVES 5 +#define MAX_COMBO_MOVES 17 struct ContestEffect { u8 effectType; u8 appeal; u8 jam; + const u8 *description; + void (*function)(void); }; extern const struct ContestEffect gContestEffects[]; -extern const u8 *const gContestEffectDescriptionPointers[]; -extern const u8 *const gContestMoveTypeTextPointers[]; bool8 AreMovesContestCombo(u16 lastMove, u16 nextMove); diff --git a/include/data.h b/include/data.h index 2128685e19..fbca022f97 100644 --- a/include/data.h +++ b/include/data.h @@ -64,14 +64,14 @@ struct TrainerMon u16 moves[4]; u16 species; u16 heldItem; - u16 ability; + enum Ability ability; u8 lvl; u8 ball; u8 friendship; u8 nature:5; bool8 gender:2; bool8 isShiny:1; - u8 teraType:5; + enum Type teraType:5; bool8 gigantamaxFactor:1; u8 shouldUseDynamax:1; u8 padding1:1; @@ -82,7 +82,7 @@ struct TrainerMon #define TRAINER_PARTY(partyArray) partyArray, .partySize = ARRAY_COUNT(partyArray) -enum TrainerBattleType +enum TrainerBattleType { TRAINER_BATTLE_TYPE_SINGLES, TRAINER_BATTLE_TYPE_DOUBLES, diff --git a/include/debug.h b/include/debug.h index 11212ce97f..01be269c4d 100644 --- a/include/debug.h +++ b/include/debug.h @@ -6,6 +6,9 @@ extern const u8 Debug_FlagsAndVarNotSetBattleConfigMessage[]; const u8 *GetWeatherName(u32 weatherId); const struct Trainer* GetDebugAiTrainer(void); +void DebugNative_GetAbilityNames(void); +void DebugNative_Party_SetFriendship(void); + extern EWRAM_DATA bool8 gIsDebugBattle; extern EWRAM_DATA u64 gDebugAIFlags; diff --git a/include/event_object_movement.h b/include/event_object_movement.h index a9d1e61277..4ec46709e3 100644 --- a/include/event_object_movement.h +++ b/include/event_object_movement.h @@ -512,4 +512,6 @@ bool8 MovementAction_EmoteX_Step0(struct ObjectEvent *, struct Sprite *); bool8 MovementAction_EmoteDoubleExclamationMark_Step0(struct ObjectEvent *, struct Sprite *); bool8 PlayerIsUnderWaterfall(struct ObjectEvent *objectEvent); +u8 GetObjectEventApricornTreeId(u8 objectEventId); + #endif //GUARD_EVENT_OBJECT_MOVEMENT_H diff --git a/include/field_name_box.h b/include/field_name_box.h new file mode 100644 index 0000000000..983ac09d09 --- /dev/null +++ b/include/field_name_box.h @@ -0,0 +1,22 @@ +#ifndef GUARD_FIELD_NAME_BOX_H +#define GUARD_FIELD_NAME_BOX_H + +#include "config/name_box.h" + +#define NAME_BOX_BASE_TILES_TOTAL (6) // Total tiles within the namebox's .png, best practice to make all images uses the same total tiles. +#define NAME_BOX_BASE_TILE_NUM (0x194 - (OW_NAME_BOX_DEFAULT_WIDTH * OW_NAME_BOX_DEFAULT_HEIGHT)) + +extern EWRAM_DATA const u8 *gSpeakerName; +extern const u8 *const gSpeakerNamesTable[]; + +void TrySpawnNamebox(u32 tileNum); +u32 GetNameboxWindowId(void); +void ResetNameboxData(void); +void DestroyNamebox(void); +void FillNamebox(void); +void DrawNamebox(u32 windowId, u32 tileNum, bool32 copyToVram); +void ClearNamebox(u32 windowId, bool32 copyToVram); +u32 GetNameboxWidth(void); +void TrySpawnAndShowNamebox(const u8 *speaker, u32 tileNum); + +#endif // GUARD_FIELD_NAME_BOX_H diff --git a/include/field_player_avatar.h b/include/field_player_avatar.h index cb7128f203..a6d56f62f7 100644 --- a/include/field_player_avatar.h +++ b/include/field_player_avatar.h @@ -64,7 +64,7 @@ bool32 IsPlayerSpinEntranceActive(void); bool32 IsPlayerSpinExitActive(void); void SetPlayerInvisibility(bool8 invisible); u8 player_get_pos_including_state_based_drift(s16 *x, s16 *y); -void StartFishing(u8 rod); +void SetPlayerAvatarFishing(u8 direction); bool8 ObjectMovingOnRockStairs(struct ObjectEvent *objectEvent, u8 direction); //sideways stairs u8 GetRightSideStairsDirection(u8 direction); diff --git a/include/field_specials.h b/include/field_specials.h index 50afecf2fb..c6bc40143f 100644 --- a/include/field_specials.h +++ b/include/field_specials.h @@ -19,7 +19,7 @@ bool32 ShouldDoScottBattleFrontierCall(void); bool32 ShouldDoRoxanneCall(void); bool32 ShouldDoRivalRayquazaCall(void); bool32 CountSSTidalStep(u16 delta); -u8 GetSSTidalLocation(s8 *mapGroup, s8 *mapNum, s16 *x, s16 *y); +enum SSTidalLocation GetSSTidalLocation(s8 *mapGroup, s8 *mapNum, s16 *x, s16 *y); void ShowScrollableMultichoice(void); void FrontierGamblerSetWonOrLost(bool8 won); u8 TryGainNewFanFromCounter(u8 incrementId); diff --git a/include/fishing.h b/include/fishing.h new file mode 100644 index 0000000000..05ee236604 --- /dev/null +++ b/include/fishing.h @@ -0,0 +1,9 @@ +#ifndef GUARD_FISHING_H +#define GUARD_FISHING_H + +void StartFishing(u8 rod); +void UpdateChainFishingStreak(); +u32 CalculateChainFishingShinyRolls(void); +bool32 ShouldUseFishingEnvironmentInBattle(); + +#endif // GUARD_FISHING_H \ No newline at end of file diff --git a/include/follower_npc.h b/include/follower_npc.h index 5a2ab0e545..680a3b6799 100644 --- a/include/follower_npc.h +++ b/include/follower_npc.h @@ -81,6 +81,13 @@ enum FollowerNPCHandleEscalatorFinishTaskStates MOVEMENT_FINISH }; +enum FollowerNPCForcedMovementStates +{ + FNPC_FORCED_NONE, + FNPC_FORCED_FOLLOW, + FNPC_FORCED_STAY +}; + #define FOLLOWER_NPC_FLAG_HAS_RUNNING_FRAMES 0x1 #define FNPC_NONE 0 diff --git a/include/frontier_util.h b/include/frontier_util.h index 5494aa5f0b..cd99f7a181 100644 --- a/include/frontier_util.h +++ b/include/frontier_util.h @@ -25,5 +25,6 @@ u8 GetFrontierBrainMonNature(u8 monId); u8 GetFrontierBrainMonEvs(u8 monId, u8 evStatId); s32 GetFronterBrainSymbol(void); void ClearEnemyPartyAfterChallenge(void); +void ShowBattleFrontierCaughtBannedSpecies(void); #endif // GUARD_FRONTIER_UTIL_H diff --git a/include/generational_changes.h b/include/generational_changes.h index 0068d74428..2e6767ca84 100644 --- a/include/generational_changes.h +++ b/include/generational_changes.h @@ -4,78 +4,20 @@ #include "constants/generational_changes.h" #include "config/battle.h" -static const u8 sGenerationalChanges[GEN_CONFIG_COUNT] = +#define UNPACK_CONFIG_STRUCT(_name, _field, _typeMaxValue, ...) INVOKE_WITH_(UNPACK_CONFIG_STRUCT_, _field, UNPACK_B(_typeMaxValue)); +#define UNPACK_CONFIG_STRUCT_(_field, _type, ...) _type FIRST(__VA_OPT__(_field:BIT_SIZE(FIRST(__VA_ARGS__)),) _field) + +struct GenChanges { - [GEN_CONFIG_CRIT_CHANCE] = B_CRIT_CHANCE, - [GEN_CONFIG_CRIT_MULTIPLIER] = B_CRIT_MULTIPLIER, - [GEN_CONFIG_FOCUS_ENERGY_CRIT_RATIO] = B_FOCUS_ENERGY_CRIT_RATIO, - [GEN_CONFIG_PARALYSIS_SPEED] = B_PARALYSIS_SPEED, - [GEN_CONFIG_CONFUSION_SELF_DMG_CHANCE] = B_CONFUSION_SELF_DMG_CHANCE, - [GEN_CONFIG_MULTI_HIT_CHANCE] = B_MULTI_HIT_CHANCE, - [GEN_CONFIG_GALE_WINGS] = B_GALE_WINGS, - [GEN_CONFIG_HEAL_BELL_SOUNDPROOF] = B_HEAL_BELL_SOUNDPROOF, - [GEN_CONFIG_TELEPORT_BEHAVIOR] = B_TELEPORT_BEHAVIOR, - [GEN_CONFIG_ABILITY_WEATHER] = B_ABILITY_WEATHER, - [GEN_CONFIG_MOODY_STATS] = B_MOODY_ACC_EVASION, - [GEN_CONFIG_BATTLE_BOND] = B_BATTLE_BOND, - [GEN_CONFIG_ATE_MULTIPLIER] = B_ATE_MULTIPLIER, - [GEN_CONFIG_FELL_STINGER_STAT_RAISE] = B_FELL_STINGER_STAT_RAISE, - [GEN_CONFIG_DEFIANT_STICKY_WEB] = B_DEFIANT_STICKY_WEB, - [GEN_CONFIG_ENCORE_TARGET] = B_ENCORE_TARGET, - [GEN_CONFIG_TIME_OF_DAY_HEALING_MOVES] = B_TIME_OF_DAY_HEALING_MOVES, - [GEN_PICKUP_WILD] = B_PICKUP_WILD, - [GEN_PROTEAN_LIBERO] = B_PROTEAN_LIBERO, - [GEN_INTREPID_SWORD] = B_INTREPID_SWORD, - [GEN_DAUNTLESS_SHIELD] = B_DAUNTLESS_SHIELD, - [GEN_ILLUMINATE_EFFECT] = B_ILLUMINATE_EFFECT, - [GEN_STEAL_WILD_ITEMS] = B_STEAL_WILD_ITEMS, - [GEN_SNOW_WARNING] = B_SNOW_WARNING, - [GEN_ALLY_SWITCH_FAIL_CHANCE] = B_ALLY_SWITCH_FAIL_CHANCE, - [GEN_DREAM_EATER_LIQUID_OOZE] = B_DREAM_EATER_LIQUID_OOZE, - [GEN_CONFIG_TRANSISTOR_BOOST] = B_TRANSISTOR_BOOST, - [GEN_CONFIG_RECALC_TURN_AFTER_ACTIONS] = B_RECALC_TURN_AFTER_ACTIONS, - [GEN_CONFIG_UPDATED_INTIMIDATE] = B_UPDATED_INTIMIDATE, - [GEN_CONFIG_DISGUISE_HP_LOSS] = B_DISGUISE_HP_LOSS, - [GEN_CONFIG_AFTER_YOU_TURN_ORDER] = B_AFTER_YOU_TURN_ORDER, - [GEN_CONFIG_HEALING_WISH_SWITCH] = B_HEALING_WISH_SWITCH, - [GEN_CONFIG_MEGA_EVO_TURN_ORDER] = B_MEGA_EVO_TURN_ORDER, - [GEN_CONFIG_SHEER_COLD_IMMUNITY] = B_SHEER_COLD_IMMUNITY, - [GEN_CONFIG_WEAK_ARMOR_SPEED] = B_WEAK_ARMOR_SPEED, - [GEN_CONFIG_PRANKSTER_DARK_TYPES] = B_PRANKSTER_DARK_TYPES, - [GEN_CONFIG_DESTINY_BOND_FAIL] = B_DESTINY_BOND_FAIL, - [GEN_CONFIG_POWDER_RAIN] = B_POWDER_RAIN, - [GEN_CONFIG_POWDER_GRASS] = B_POWDER_GRASS, - [GEN_CONFIG_POWDER_OVERCOAT] = B_POWDER_OVERCOAT, - [GEN_CONFIG_OBLIVIOUS_TAUNT] = B_OBLIVIOUS_TAUNT, - [GEN_CONFIG_TOXIC_NEVER_MISS] = B_TOXIC_NEVER_MISS, - [GEN_CONFIG_PARALYZE_ELECTRIC] = B_PARALYZE_ELECTRIC, - [GEN_CONFIG_BADGE_BOOST] = B_BADGE_BOOST, - [GEN_CONFIG_LEAF_GUARD_PREVENTS_REST] = B_LEAF_GUARD_PREVENTS_REST, + CONFIG_DEFINITIONS(UNPACK_CONFIG_STRUCT) + // Expands to: + // u32 critChance:4; + // u32 critMultiplier:4; + // ... }; -#if TESTING -extern u8 *gGenerationalChangesTestOverride; -#endif - -static inline u32 GetGenConfig(enum GenConfigTag configTag) -{ - if (configTag >= GEN_CONFIG_COUNT) return GEN_LATEST; -#if TESTING - if (gGenerationalChangesTestOverride == NULL) return sGenerationalChanges[configTag]; - return gGenerationalChangesTestOverride[configTag]; -#else - return sGenerationalChanges[configTag]; -#endif -} - -static inline void SetGenConfig(enum GenConfigTag configTag, u32 value) -{ -#if TESTING - if (configTag >= GEN_CONFIG_COUNT) return; - if (gGenerationalChangesTestOverride == NULL) return; - gGenerationalChangesTestOverride[configTag] = value; -#endif -} +u32 GetConfig(enum ConfigTag configTag); +void SetConfig(enum ConfigTag configTag, u32 value); #if TESTING void TestInitConfigData(void); diff --git a/include/global.h b/include/global.h index a3dacfb3d4..3135542e02 100644 --- a/include/global.h +++ b/include/global.h @@ -14,6 +14,7 @@ #include "constants/vars.h" #include "constants/species.h" #include "constants/pokedex.h" +#include "constants/apricorn_tree.h" #include "constants/berry.h" #include "constants/maps.h" #include "constants/pokemon.h" @@ -134,6 +135,8 @@ #define NUM_FLAG_BYTES ROUND_BITS_TO_BYTES(FLAGS_COUNT) #define NUM_TRENDY_SAYING_BYTES ROUND_BITS_TO_BYTES(NUM_TRENDY_SAYINGS) +#define NUM_APRICORN_TREE_BYTES ROUND_BITS_TO_BYTES(APRICORN_TREE_COUNT) + // This produces an error at compile-time if expr is zero. // It looks like file.c:line: size of array `id' is negative #define STATIC_ASSERT(expr, id) typedef char id[(expr) ? 1 : -1]; @@ -219,9 +222,9 @@ struct NPCFollower { u8 inProgress:1; u8 warpEnd:1; - u8 createSurfBlob:3; + u8 createSurfBlob:2; u8 comeOutDoorStairs:2; - u8 forcedMovement:1; + u8 forcedMovement:2; u8 objId; u8 currentSprite; u8 delayedState; @@ -252,6 +255,9 @@ struct SaveBlock3 u8 dexNavSearchLevels[NUM_SPECIES]; #endif u8 dexNavChain; +#if APRICORN_TREE_COUNT > 0 + u8 apricornTrees[NUM_APRICORN_TREE_BYTES]; +#endif }; /* max size 1624 bytes */ extern struct SaveBlock3 *gSaveBlock3Ptr; diff --git a/include/item.h b/include/item.h index 1f3b1fab1b..d548643af8 100644 --- a/include/item.h +++ b/include/item.h @@ -130,6 +130,8 @@ extern const struct TmHmIndexKey gTMHMItemMoveIds[]; #define UNPACK_ITEM_TO_HM_INDEX(_hm) case CAT(ITEM_HM_, _hm): return CAT(ENUM_TM_HM_, _hm) + 1; #define UNPACK_ITEM_TO_TM_MOVE_ID(_tm) case CAT(ITEM_TM_, _tm): return CAT(MOVE_, _tm); #define UNPACK_ITEM_TO_HM_MOVE_ID(_hm) case CAT(ITEM_HM_, _hm): return CAT(MOVE_, _hm); +#define UNPACK_TM_MOVE_TO_ITEM_ID(_move) case CAT(MOVE_, _move): return CAT(ITEM_TM_, _move); +#define UNPACK_HM_MOVE_TO_ITEM_ID(_move) case CAT(MOVE_, _move): return CAT(ITEM_HM_, _move); static inline enum TMHMIndex GetItemTMHMIndex(u16 item) { @@ -165,10 +167,29 @@ static inline u16 GetItemTMHMMoveId(u16 item) } } +static inline enum TMHMItemId GetTMHMItemIdFromMoveId(u16 move) +{ + switch (move) + { + /* Expands to: + * case MOVE_FOCUS_PUNCH: + * return ITEM_TM_FOCUS_PUNCH; + * case MOVE_DRAGON_CLAW: + * return ITEM_TM_DRAGON_CLAW; + * etc */ + FOREACH_TM(UNPACK_TM_MOVE_TO_ITEM_ID) + FOREACH_HM(UNPACK_HM_MOVE_TO_ITEM_ID) + default: + return ITEM_NONE; + } +} + #undef UNPACK_ITEM_TO_TM_INDEX #undef UNPACK_ITEM_TO_HM_INDEX #undef UNPACK_ITEM_TO_TM_MOVE_ID #undef UNPACK_ITEM_TO_HM_MOVE_ID +#undef UNPACK_TM_MOVE_TO_ITEM_ID +#undef UNPACK_HM_MOVE_TO_ITEM_ID static inline enum TMHMItemId GetTMHMItemId(enum TMHMIndex index) { @@ -215,6 +236,7 @@ bool32 CheckBagHasSpace(u16 itemId, u16 count); u32 GetFreeSpaceForItemInBag(u16 itemId); bool32 AddBagItem(u16 itemId, u16 count); bool32 RemoveBagItem(u16 itemId, u16 count); +void RemoveBagItemFromSlot(struct BagPocket *pocket, u16 slotId, u16 count); u8 CountUsedPCItemSlots(void); bool32 CheckPCHasItem(u16 itemId, u16 count); bool32 AddPCItem(u16 itemId, u16 count); @@ -231,7 +253,7 @@ bool32 RemovePyramidBagItem(u16 itemId, u16 count); const u8 *GetItemName(u16 itemId); u32 GetItemPrice(u16 itemId); const u8 *GetItemEffect(u32 itemId); -u32 GetItemHoldEffect(u32 itemId); +enum HoldEffect GetItemHoldEffect(u32 itemId); u32 GetItemHoldEffectParam(u32 itemId); const u8 *GetItemDescription(u16 itemId); u8 GetItemImportance(u16 itemId); @@ -245,6 +267,6 @@ u32 GetItemFlingPower(u32 itemId); u32 GetItemStatus1Mask(u16 itemId); bool32 ItemHasVolatileFlag(u16 itemId, enum Volatile volatile); u32 GetItemSellPrice(u32 itemId); -bool32 IsHoldEffectChoice(enum ItemHoldEffect holdEffect); +bool32 IsHoldEffectChoice(enum HoldEffect holdEffect); #endif // GUARD_ITEM_H diff --git a/include/item_use.h b/include/item_use.h index ad8018d67d..ccb0f4f3df 100644 --- a/include/item_use.h +++ b/include/item_use.h @@ -49,6 +49,8 @@ void Task_ItemUse_CloseMessageBoxAndReturnToField_VsSeeker(u8 taskId); void DisplayDadsAdviceCannotUseItemMessage(u8 taskId, bool8 isUsingRegisteredKeyItemOnField); void ItemUseOutOfBattle_PokeFlute(u8 taskId); void ItemUseOutOfBattle_TownMap(u8 taskId); +bool8 ItemfinderCheckForHiddenItems(const struct MapEvents *, u8); +u8 GetDirectionToHiddenItem(s16, s16); enum { BALL_THROW_UNABLE_TWO_MONS, diff --git a/include/list_menu.h b/include/list_menu.h index 184b9c416f..8d472320d6 100644 --- a/include/list_menu.h +++ b/include/list_menu.h @@ -76,8 +76,9 @@ struct ListMenuTemplate u8 lettersSpacing:3; u8 itemVerticalPadding:3; u8 scrollMultiple:2; // x40, x80 = xC0 - u8 fontId:6; // x1, x2, x4, x8, x10, x20 = x3F - u8 cursorKind:2; // x40, x80 + u8 fontId:5; // x1, x2, x4, x8, x10 = x1F + u8 cursorKind:2; // x20, x40 + u8 isDynamic:1; //Dynamic list doesn't store all items in memory but load them from ROM when necessary }; struct ListMenu diff --git a/include/match_call.h b/include/match_call.h index ed2cf506c5..468a977a13 100644 --- a/include/match_call.h +++ b/include/match_call.h @@ -19,5 +19,6 @@ void BufferPokedexRatingForMatchCall(u8 *destStr); bool32 SelectMatchCallMessage(int trainerId, u8 *str); void LoadMatchCallWindowGfx(u32 windowId, u32 destOffset, u32 paletteId); void DrawMatchCallTextBoxBorder(u32 windowId, u32 tileOffset, u32 paletteId); +void RedrawMatchCallTextBoxBorder(void); #endif //GUARD_MATCH_CALL_H diff --git a/include/menu.h b/include/menu.h index ca7f8d008c..6702552331 100644 --- a/include/menu.h +++ b/include/menu.h @@ -61,8 +61,6 @@ void PrintPlayerNameOnWindow(u8 windowId, const u8 *src, u16 x, u16 y); void ClearDialogWindowAndFrame(u8 windowId, bool8 copyToVram); void SetStandardWindowBorderStyle(u8 windowId, bool8 copyToVram); void DisplayYesNoMenuDefaultYes(void); -u32 GetPlayerTextSpeed(void); -u8 GetPlayerTextSpeedDelay(void); void Menu_LoadStdPalAt(u16 offset); void AddTextPrinterWithCallbackForMessage(bool8 canSpeedUp, void (*callback)(struct TextPrinterTemplate *, u16)); void BgDmaFill(u32 bg, u8 value, int offset, int size); @@ -106,7 +104,6 @@ void DrawStdWindowFrame(u8 windowId, bool8 copyToVram); u8 AddStartMenuWindow(u8 numActions); u8 InitMenuNormal(u8 windowId, u8 fontId, u8 left, u8 top, u8 cursorHeight, u8 numChoices, u8 initialCursorPos); void LoadMessageBoxAndFrameGfx(u8 windowId, bool8 copyToVram); -void AddTextPrinterForMessage_2(bool8 allowSkippingDelayWithButtonPress); void RemoveStartMenuWindow(void); void DisplayYesNoMenuWithDefault(u8 initialCursorPos); void BufferSaveMenuText(u8 textId, u8 *dest, u8 color); @@ -135,5 +132,6 @@ u8 AddSecondaryPopUpWindow(void); u8 GetSecondaryPopUpWindowId(void); void RemoveSecondaryPopUpWindow(void); void HBlankCB_DoublePopupWindow(void); +void RedrawDialogueFrame(void); #endif // GUARD_MENU_H diff --git a/include/move.h b/include/move.h index b1e8cba99f..fe2587a225 100644 --- a/include/move.h +++ b/include/move.h @@ -65,7 +65,7 @@ struct MoveInfo const u8 *name; const u8 *description; enum BattleMoveEffects effect; - u16 type:5; // Up to 32 + enum Type type:5; // Up to 32 enum DamageCategory category:2; u16 power:9; // up to 511 // end of word @@ -81,7 +81,7 @@ struct MoveInfo u32 strikeCount:4; // Max 15 hits. Defaults to 1 if not set. May apply its effect on each hit. u32 criticalHitStage:2; bool32 alwaysCriticalHit:1; - u32 numAdditionalEffects:2; // limited to 3 - don't want to get too crazy + u32 numAdditionalEffects:3; // limited to 7 // Flags bool32 makesContact:1; bool32 ignoresProtect:1; @@ -101,8 +101,8 @@ struct MoveInfo bool32 minimizeDoubleDamage:1; bool32 ignoresTargetAbility:1; bool32 ignoresTargetDefenseEvasionStages:1; - bool32 damagesUnderground:1; // end of word + bool32 damagesUnderground:1; bool32 damagesUnderwater:1; bool32 damagesAirborne:1; bool32 damagesAirborneDoubleDamage:1; @@ -131,7 +131,7 @@ struct MoveInfo bool32 dampBanned:1; //Other bool32 validApprenticeMove:1; - u32 padding:6; + u32 padding:5; // end of word union { @@ -149,6 +149,7 @@ struct MoveInfo u32 absorbPercentage; u32 recoilPercentage; u32 nonVolatileStatus; + u32 overwriteAbility; } argument; // primary/secondary effects @@ -192,7 +193,7 @@ static inline const u8 *GetMoveDescription(u32 moveId) return gMovesInfo[moveId].description; } -static inline u32 GetMoveType(u32 moveId) +static inline enum Type GetMoveType(u32 moveId) { return gMovesInfo[SanitizeMoveId(moveId)].type; } @@ -564,6 +565,11 @@ static inline u32 GetMoveDamagePercentage(u32 move) return gMovesInfo[SanitizeMoveId(move)].argument.damagePercentage; } +static inline u32 GetMoveOverwriteAbility(u32 move) +{ + return gMovesInfo[SanitizeMoveId(move)].argument.overwriteAbility; +} + static inline const struct AdditionalEffect *GetMoveAdditionalEffectById(u32 moveId, u32 effect) { return &gMovesInfo[SanitizeMoveId(moveId)].additionalEffects[effect]; diff --git a/include/move_relearner.h b/include/move_relearner.h index 9aab3974df..1d22d82a79 100644 --- a/include/move_relearner.h +++ b/include/move_relearner.h @@ -1,11 +1,14 @@ #ifndef GUARD_MOVE_RELEARNER_H #define GUARD_MOVE_RELEARNER_H +#include "constants/move_relearner.h" + void TeachMoveRelearnerMove(void); void MoveRelearnerShowHideHearts(s32 move); void MoveRelearnerShowHideCategoryIcon(s32); void CB2_InitLearnMove(void); -extern u8 gOriginSummaryScreenPage; +extern enum MoveRelearnerStates gMoveRelearnerState; +extern enum RelearnMode gRelearnMode; #endif //GUARD_MOVE_RELEARNER_H diff --git a/include/oras_dowse.h b/include/oras_dowse.h new file mode 100644 index 0000000000..8b490cf6c7 --- /dev/null +++ b/include/oras_dowse.h @@ -0,0 +1,39 @@ +#ifndef GUARD_ORAS_DOWSE_H +#define GUARD_ORAS_DOWSE_H + +// States for ORAS Dowsing +enum +{ + ORASD_WIGGLE_NONE, + ORASD_WIGGLE_SLOW, + ORASD_WIGGLE_NORMAL, + ORASD_WIGGLE_FAST, + ORASD_WIGGLE_FASTER +}; + +#define ANIM_ORAS_DOWSE_WIGGLE_SOUTH_SLOW (ANIM_STD_FACE_EAST + 1) +#define ANIM_ORAS_DOWSE_WIGGLE_NORTH_SLOW (ANIM_STD_FACE_EAST + 2) +#define ANIM_ORAS_DOWSE_WIGGLE_WEST_SLOW (ANIM_STD_FACE_EAST + 3) +#define ANIM_ORAS_DOWSE_WIGGLE_EAST_SLOW (ANIM_STD_FACE_EAST + 4) +#define ANIM_ORAS_DOWSE_WIGGLE_SOUTH (ANIM_STD_FACE_EAST + 5) +#define ANIM_ORAS_DOWSE_WIGGLE_NORTH (ANIM_STD_FACE_EAST + 6) +#define ANIM_ORAS_DOWSE_WIGGLE_WEST (ANIM_STD_FACE_EAST + 7) +#define ANIM_ORAS_DOWSE_WIGGLE_EAST (ANIM_STD_FACE_EAST + 8) +#define ANIM_ORAS_DOWSE_WIGGLE_SOUTH_FAST (ANIM_STD_FACE_EAST + 9) +#define ANIM_ORAS_DOWSE_WIGGLE_NORTH_FAST (ANIM_STD_FACE_EAST + 10) +#define ANIM_ORAS_DOWSE_WIGGLE_WEST_FAST (ANIM_STD_FACE_EAST + 11) +#define ANIM_ORAS_DOWSE_WIGGLE_EAST_FAST (ANIM_STD_FACE_EAST + 12) +#define ANIM_ORAS_DOWSE_WIGGLE_SOUTH_FASTER (ANIM_STD_FACE_EAST + 13) +#define ANIM_ORAS_DOWSE_WIGGLE_NORTH_FASTER (ANIM_STD_FACE_EAST + 14) +#define ANIM_ORAS_DOWSE_WIGGLE_WEST_FASTER (ANIM_STD_FACE_EAST + 15) +#define ANIM_ORAS_DOWSE_WIGGLE_EAST_FASTER (ANIM_STD_FACE_EAST + 16) + +extern const u16 gFieldEffectPal_ORASDowsing[]; + +void Task_UseORASDowsingMachine(u8 taskId); +void ResumeORASDowseFieldEffect(void); +void UpdateDowseState(struct Sprite *sprite); +void UpdateDowsingAnimDirection(struct Sprite *sprite, struct ObjectEvent *playerObj); +void EndORASDowsing(void); + +#endif // GUARD_ORAS_DOWSE_H diff --git a/include/overworld.h b/include/overworld.h index 28cd4c93f7..e0df9c3b89 100644 --- a/include/overworld.h +++ b/include/overworld.h @@ -143,7 +143,7 @@ bool32 IsOverworldLinkActive(void); void CB1_Overworld(void); void CB2_OverworldBasic(void); void UpdateTimeOfDay(void); -bool32 MapHasNaturalLight(u8 mapType); +bool32 MapHasNaturalLight(enum MapType mapType); bool32 CurrentMapHasShadows(void); void UpdateAltBgPalettes(u16 palettes); void UpdatePalettesWithTime(u32); diff --git a/include/party_menu.h b/include/party_menu.h index 38ba5202b5..acae4e0c0b 100644 --- a/include/party_menu.h +++ b/include/party_menu.h @@ -96,6 +96,7 @@ u8 GetPartyIdFromBattlePartyId(u8 battlePartyId); void ShowPartyMenuToShowcaseMultiBattleParty(void); void ChooseMonForDaycare(void); bool8 CB2_FadeFromPartyMenu(void); +void CB2_ReturnToPartyMenuFromSummaryScreen(void); void ChooseContestMon(void); void ChoosePartyMon(void); void ChooseMonForMoveRelearner(void); diff --git a/include/pokemon.h b/include/pokemon.h index 8852ba3c97..bc6af2a48e 100644 --- a/include/pokemon.h +++ b/include/pokemon.h @@ -6,10 +6,15 @@ #include "constants/battle.h" #include "constants/cries.h" #include "constants/form_change_types.h" +#include "constants/hold_effects.h" #include "constants/items.h" #include "constants/map_groups.h" #include "constants/regions.h" #include "constants/region_map_sections.h" +#include "constants/map_groups.h" +#include "constants/battle.h" +#include "constants/abilities.h" +#include "contest_effect.h" #include "constants/trainers.h" #define GET_BASE_SPECIES_ID(speciesId) (GetFormSpeciesId(speciesId, 0)) @@ -126,7 +131,7 @@ enum MonData { struct PokemonSubstruct0 { u16 species:11; // 2047 species. - u16 teraType:5; // 30 types. + enum Type teraType:5; // 30 types. u16 heldItem:10; // 1023 items. u16 unused_02:6; u32 experience:21; @@ -348,6 +353,7 @@ struct Volatiles // u32 foresight:1; // u32 dragonCheer:1; // u32 focusEnergy:1; + // u32 bonusCritStages:3; }; struct BattlePokemon @@ -367,8 +373,8 @@ struct BattlePokemon /*0x17*/ u32 spDefenseIV:5; /*0x17*/ u32 abilityNum:2; /*0x18*/ s8 statStages[NUM_BATTLE_STATS]; - /*0x20*/ u16 ability; - /*0x22*/ u8 types[3]; + /*0x20*/ enum Ability ability; + /*0x22*/ enum Type types[3]; /*0x25*/ u8 pp[MAX_MON_MOVES]; /*0x29*/ u16 hp; /*0x2B*/ u8 level; @@ -411,7 +417,7 @@ struct SpeciesInfo /*0xC4*/ u8 baseSpeed; u8 baseSpAttack; u8 baseSpDefense; - u8 types[2]; + enum Type types[2]; u8 catchRate; u8 forceTeraType; u16 expYield; // expYield was changed from u8 to u16 for the new Exp System. @@ -429,7 +435,7 @@ struct SpeciesInfo /*0xC4*/ u8 friendship; u8 growthRate; u8 eggGroups[2]; - u16 abilities[NUM_ABILITY_SLOTS]; // 3 abilities, no longer u8 because we have over 255 abilities now. + enum Ability abilities[NUM_ABILITY_SLOTS]; // 3 abilities, no longer u8 because we have over 255 abilities now. u8 safariZoneFleeRate; // Pokédex data @@ -533,7 +539,7 @@ struct SpeciesInfo /*0xC4*/ #endif //OW_POKEMON_OBJECT_EVENTS }; -struct Ability +struct AbilityInfo { u8 name[ABILITY_NAME_LENGTH + 1]; const u8 *description; @@ -597,8 +603,8 @@ enum { struct NatureInfo { const u8 *name; - u8 statUp; - u8 statDown; + enum Stat statUp; + enum Stat statDown; u8 backAnim; u8 pokeBlockAnim[2]; u8 battlePalacePercents[4]; @@ -694,7 +700,7 @@ extern const u8 gStatStageRatios[MAX_STAT_STAGE + 1][2]; extern const u16 gUnionRoomFacilityClasses[]; extern const struct SpriteTemplate gBattlerSpriteTemplates[]; extern const u32 sExpCandyExperienceTable[]; -extern const struct Ability gAbilitiesInfo[]; +extern const struct AbilityInfo gAbilitiesInfo[]; extern const struct NatureInfo gNaturesInfo[]; #if P_TUTOR_MOVES_ARRAY extern const u16 gTutorMoves[]; @@ -769,8 +775,8 @@ u8 CalculateEnemyPartyCount(void); u8 CalculateEnemyPartyCountInSide(u32 battler); u8 GetMonsStateToDoubles(void); u8 GetMonsStateToDoubles_2(void); -u16 GetAbilityBySpecies(u16 species, u8 abilityNum); -u16 GetMonAbility(struct Pokemon *mon); +enum Ability GetAbilityBySpecies(u16 species, u8 abilityNum); +enum Ability GetMonAbility(struct Pokemon *mon); void CreateSecretBaseEnemyParty(struct SecretBase *secretBaseRecord); u8 GetSecretBaseTrainerPicIndex(void); enum TrainerClassID GetSecretBaseTrainerClass(void); @@ -781,8 +787,8 @@ const u8 *GetSpeciesCategory(u16 species); const u8 *GetSpeciesPokedexDescription(u16 species); u32 GetSpeciesHeight(u16 species); u32 GetSpeciesWeight(u16 species); -u32 GetSpeciesType(u16 species, u8 slot); -u32 GetSpeciesAbility(u16 species, u8 slot); +enum Type GetSpeciesType(u16 species, u8 slot); +enum Ability GetSpeciesAbility(u16 species, u8 slot); u32 GetSpeciesBaseHP(u16 species); u32 GetSpeciesBaseAttack(u16 species); u32 GetSpeciesBaseDefense(u16 species); @@ -823,8 +829,9 @@ u8 GetPlayerFlankId(void); u16 GetLinkTrainerFlankId(u8 linkPlayerId); s32 GetBattlerMultiplayerId(u16 id); u8 GetTrainerEncounterMusicId(u16 trainerOpponentId); -u16 ModifyStatByNature(u8 nature, u16 stat, u8 statIndex); +u16 ModifyStatByNature(u8 nature, u16 stat, enum Stat statIndex); void AdjustFriendship(struct Pokemon *mon, u8 event); +u8 CalculateFriendshipBonuses(struct Pokemon *mon, u32 modifier, enum HoldEffect itemHoldEffect); void MonGainEVs(struct Pokemon *mon, u16 defeatedSpecies); u16 GetMonEVCount(struct Pokemon *mon); void RandomlyGivePartyPokerus(struct Pokemon *party); @@ -834,9 +841,15 @@ void UpdatePartyPokerusTime(u16 days); void PartySpreadPokerus(struct Pokemon *party); bool8 TryIncrementMonLevel(struct Pokemon *mon); u8 CanLearnTeachableMove(u16 species, u16 move); -u8 GetMoveRelearnerMoves(struct Pokemon *mon, u16 *moves); +u32 GetRelearnerLevelUpMoves(struct Pokemon *mon, u16 *moves); +u32 GetRelearnerEggMoves(struct Pokemon *mon, u16 *moves); +u32 GetRelearnerTMMoves(struct Pokemon *mon, u16 *moves); +u32 GetRelearnerTutorMoves(struct Pokemon *mon, u16 *moves); +bool32 HasRelearnerLevelUpMoves(struct Pokemon *mon); +bool32 HasRelearnerEggMoves(struct Pokemon *mon); +bool32 HasRelearnerTMMoves(struct Pokemon *mon); +bool32 HasRelearnerTutorMoves(struct Pokemon *mon); u8 GetLevelUpMovesBySpecies(u16 species, u16 *moves); -u8 GetNumberOfRelearnableMoves(struct Pokemon *mon); u16 SpeciesToPokedexNum(u16 species); bool32 IsSpeciesInHoennDex(u16 species); u16 GetBattleBGM(void); @@ -882,7 +895,7 @@ u16 MonTryLearningNewMoveEvolution(struct Pokemon *mon, bool8 firstMove); void RemoveIVIndexFromList(u8 *ivs, u8 selectedIv); void TrySpecialOverworldEvo(void); bool32 SpeciesHasGenderDifferences(u16 species); -bool32 TryFormChange(u32 monId, u32 side, enum FormChanges method); +bool32 TryFormChange(u32 monId, enum BattleSide side, enum FormChanges method); void TryToSetBattleFormChangeMoves(struct Pokemon *mon, enum FormChanges method); u32 GetMonFriendshipScore(struct Pokemon *pokemon); u32 GetMonAffectionHearts(struct Pokemon *pokemon); @@ -896,15 +909,15 @@ void HealPokemon(struct Pokemon *mon); void HealBoxPokemon(struct BoxPokemon *boxMon); void UpdateDaysPassedSinceFormChange(u16 days); void TrySetDayLimitToFormChange(struct Pokemon *mon); -u32 CheckDynamicMoveType(struct Pokemon *mon, u32 move, u32 battler, enum MonState state); +enum Type CheckDynamicMoveType(struct Pokemon *mon, u32 move, u32 battler, enum MonState state); uq4_12_t GetDynamaxLevelHPMultiplier(u32 dynamaxLevel, bool32 inverseMultiplier); u32 GetRegionalFormByRegion(u32 species, u32 region); bool32 IsSpeciesForeignRegionalForm(u32 species, u32 currentRegion); -u32 GetTeraTypeFromPersonality(struct Pokemon *mon); +enum Type GetTeraTypeFromPersonality(struct Pokemon *mon); bool8 ShouldSkipFriendshipChange(void); struct Pokemon *GetSavedPlayerPartyMon(u32 index); u8 *GetSavedPlayerPartyCount(void); void SavePlayerPartyMon(u32 index, struct Pokemon *mon); -u32 IsSpeciesOfType(u32 species, u32 type); +bool32 IsSpeciesOfType(u32 species, enum Type type); #endif // GUARD_POKEMON_H diff --git a/include/pokemon_summary_screen.h b/include/pokemon_summary_screen.h index 3aa8460a17..6c4128dba4 100755 --- a/include/pokemon_summary_screen.h +++ b/include/pokemon_summary_screen.h @@ -3,6 +3,7 @@ #include "main.h" #include "config/summary_screen.h" +#include "constants/move_relearner.h" extern u8 gLastViewedMonIndex; @@ -13,11 +14,12 @@ extern const struct SpritePalette gSpritePal_CategoryIcons; extern const struct SpriteTemplate gSpriteTemplate_CategoryIcons; extern MainCallback gInitialSummaryScreenCallback; -void ShowPokemonSummaryScreen(u8 mode, void *mons, u8 monIndex, u8 maxMonIndex, void (*callback)(void)); -void ShowSelectMovePokemonSummaryScreen(struct Pokemon *mons, u8 monIndex, u8 maxMonIndex, void (*callback)(void), u16 newMove); -void ShowPokemonSummaryScreenHandleDeoxys(u8 mode, struct BoxPokemon *mons, u8 monIndex, u8 maxMonIndex, void (*callback)(void)); -u8 GetMoveSlotToReplace(void); -void SummaryScreen_SetAnimDelayTaskId(u8 taskId); +enum IncrDecrUpdateValues +{ + TRY_SET_UPDATE, + TRY_INCREMENT, + TRY_DECREMENT, +}; // The Pokémon Summary Screen can operate in different modes. Certain features, // such as move re-ordering, are available in the different modes. @@ -48,4 +50,12 @@ enum PokemonSummarySkillsMode SUMMARY_SKILLS_MODE_EVS, }; +void ShowPokemonSummaryScreen(u8 mode, void *mons, u8 monIndex, u8 maxMonIndex, void (*callback)(void)); +void ShowSelectMovePokemonSummaryScreen(struct Pokemon *mons, u8 monIndex, u8 maxMonIndex, void (*callback)(void), u16 newMove); +void ShowPokemonSummaryScreenHandleDeoxys(u8 mode, struct BoxPokemon *mons, u8 monIndex, u8 maxMonIndex, void (*callback)(void)); +u8 GetMoveSlotToReplace(void); +void SummaryScreen_SetAnimDelayTaskId(u8 taskId); +void ShowRelearnPrompt(void); +void TryUpdateRelearnType(enum IncrDecrUpdateValues delta); + #endif // GUARD_POKEMON_SUMMARY_SCREEN_H diff --git a/include/random.h b/include/random.h index 816cf9b40a..84318bedc0 100644 --- a/include/random.h +++ b/include/random.h @@ -218,6 +218,10 @@ enum RandomTag RNG_BALLTHROW_CRITICAL, RNG_BALLTHROW_SHAKE, RNG_PROTECT_FAIL, + RNG_PRESENT, + RNG_MAGNITUDE, + RNG_FISHING_BITE, + RNG_FISHING_GEN3_STICKY, }; #define RandomWeighted(tag, ...) \ @@ -267,4 +271,13 @@ const void *RandomElementArrayDefault(enum RandomTag, const void *array, size_t u8 RandomWeightedIndex(u8 *weights, u8 length); +#if TESTING +u32 RandomUniformTrials(enum RandomTag tag, u32 lo, u32 hi, bool32 (*reject)(u32), void *caller); +u32 RandomUniformDefaultValue(enum RandomTag tag, u32 lo, u32 hi, bool32 (*reject)(u32), void *caller); +u32 RandomWeightedArrayTrials(enum RandomTag tag, u32 sum, u32 n, const u8 *weights, void *caller); +u32 RandomWeightedArrayDefaultValue(enum RandomTag tag, u32 n, const u8 *weights, void *caller); +const void *RandomElementArrayTrials(enum RandomTag tag, const void *array, size_t size, size_t count, void *caller); +const void *RandomElementArrayDefaultValue(enum RandomTag tag, const void *array, size_t size, size_t count, void *caller); +#endif + #endif // GUARD_RANDOM_H diff --git a/include/recorded_battle.h b/include/recorded_battle.h index faf966109f..787cf4606c 100644 --- a/include/recorded_battle.h +++ b/include/recorded_battle.h @@ -27,7 +27,7 @@ struct RecordedBattleSave u8 frontierBrainSymbol; u8 battleScene:1; u8 textSpeed:3; - u64 AI_scripts; + u64 AI_scripts[MAX_BATTLERS_COUNT]; u8 recordMixFriendName[PLAYER_NAME_LENGTH + 1]; u8 recordMixFriendClass; u8 apprenticeId; @@ -81,7 +81,7 @@ u8 GetBattleSceneInRecordedBattle(void); u8 GetTextSpeedInRecordedBattle(void); void RecordedBattle_CopyBattlerMoves(u32 battler); void RecordedBattle_CheckMovesetChanges(u8 mode); -u64 GetAiScriptsInRecordedBattle(void); +u64 GetAiScriptsInRecordedBattle(u32 battler); void RecordedBattle_SetPlaybackFinished(void); bool8 RecordedBattle_CanStopPlayback(void); void GetRecordedBattleRecordMixFriendName(u8 *dst); diff --git a/include/rtc.h b/include/rtc.h index 8ee3071615..d0bb6a43de 100644 --- a/include/rtc.h +++ b/include/rtc.h @@ -43,6 +43,7 @@ u16 GetFullYear(void); enum Month GetMonth(void); u8 GetDay(void); enum Weekday GetDayOfWeek(void); +enum TimeOfDay GenConfigTimeOfDay(enum TimeOfDay timeOfDay); enum TimeOfDay TryIncrementTimeOfDay(enum TimeOfDay timeOfDay); enum TimeOfDay TryDecrementTimeOfDay(enum TimeOfDay timeOfDay); diff --git a/include/strings.h b/include/strings.h index bd2619eb51..b42b1b36b2 100644 --- a/include/strings.h +++ b/include/strings.h @@ -246,31 +246,6 @@ extern const u8 gText_SavingTime[]; extern const u8 gText_BattlePyramidConfirmRest[]; extern const u8 gText_BattlePyramidConfirmRetire[]; -// option menu texts -extern const u8 gText_TextSpeedSlow[]; -extern const u8 gText_TextSpeedMid[]; -extern const u8 gText_TextSpeedFast[]; -extern const u8 gText_BattleSceneOn[]; -extern const u8 gText_BattleSceneOff[]; -extern const u8 gText_BattleStyleShift[]; -extern const u8 gText_BattleStyleSet[]; -extern const u8 gText_SoundMono[]; -extern const u8 gText_SoundStereo[]; -extern const u8 gText_FrameTypeNumber[]; -extern const u8 gText_FrameType[]; -extern const u8 gText_ButtonTypeNormal[]; -extern const u8 gText_ButtonTypeLR[]; -extern const u8 gText_ButtonTypeLEqualsA[]; -extern const u8 gText_Option[]; -extern const u8 gText_OptionMenu[]; -extern const u8 gText_TextSpeed[]; -extern const u8 gText_BattleScene[]; -extern const u8 gText_BattleStyle[]; -extern const u8 gText_Sound[]; -extern const u8 gText_Frame[]; -extern const u8 gText_OptionMenuCancel[]; -extern const u8 gText_ButtonMode[]; - extern const u8 gText_MaleSymbol[]; extern const u8 gText_FemaleSymbol[]; @@ -942,6 +917,9 @@ extern const u8 gText_FrontierFacilityClearStreak[]; extern const u8 gText_FrontierFacilityRoomsCleared[]; extern const u8 gText_FrontierFacilityKOsStreak[]; extern const u8 gText_FrontierFacilityFloorsCleared[]; +extern const u8 gText_FrontierFacilityTotalCaughtSpeciesBanned[]; +extern const u8 gText_FrontierFacilityIncluding[]; +extern const u8 gText_FrontierFacilityAreInelegible[]; // Battle Tower. extern const u8 BattleFrontier_BattleTowerMultiPartnerRoom_Text_Apprentice1Intro[]; @@ -2421,8 +2399,17 @@ extern const u8 gText_PlayerRegroupCenter[]; extern const u8 gText_PlayerRegroupHome[]; extern const u8 gText_Relearn[]; // move relearner from summary screen +extern const u8 gText_Relearn_LevelUp[]; +extern const u8 gText_Relearn_Egg[]; +extern const u8 gText_Relearn_TM[]; +extern const u8 gText_Relearn_Tutor[]; extern const u8 gText_Rename[]; // change nickname from summary screen +extern const u8 MoveRelearner_Text_LevelUpMoveLWR[]; +extern const u8 MoveRelearner_Text_EggMoveLWR[]; +extern const u8 MoveRelearner_Text_TMMoveLWR[]; +extern const u8 MoveRelearner_Text_TutorMoveLWR[]; + // Switch Caught Mon into Party extern const u8 gText_CannotSendMonToBoxHM[]; extern const u8 gText_CannotSendMonToBoxActive[]; diff --git a/include/test/battle.h b/include/test/battle.h index 9cd1d23b1f..f8d928fc59 100644 --- a/include/test/battle.h +++ b/include/test/battle.h @@ -194,21 +194,22 @@ * ASSUME(GetMoveEffect(MOVE_POISON_STING) == EFFECT_POISON_HIT); * } * - * 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 PARAMETRIZEd tests. - * The main differences for doubles are: + * SINGLE_BATTLE_TEST(name, results...), DOUBLE_BATTLE_TEST(name, results...), MULTI_BATTLE_TEST(name, results...), + * TWO_VS_ONE_BATTLE_TEST(name, results...), and ONE_VS_TWO_BATTLE_TEST(name, results...) + * Define single-, double-, 2v2-multi-, 2v1-multi-, and 1v2- 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, 2v2, 2v1, and 1v2 are: * - Move targets sometimes need to be explicit. * - Instead of player and opponent there is playerLeft, playerRight, * opponentLeft, and opponentRight. * - * AI_SINGLE_BATTLE_TEST(name, results...) and AI_DOUBLE_BATTLE_TEST(name, results...) + * AI_SINGLE_BATTLE_TEST(name, results...), AI_DOUBLE_BATTLE_TEST(name, results...), + * AI_MULTI_BATTLE_TEST(name, results...), AI_TWO_VS_ONE_BATTLE_TEST(name, results...), and AI_ONE_VS_TWO_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. - * The rules remain the same as with the SINGLE and DOUBLE battle tests + * The rules remain the same as with the SINGLE, DOUBLE, MULTI, TWO_VS_ONE, and ONE_VS_TWO battle tests with some differences: * with some differences: * - opponent's action is specified by the EXPECT_MOVE(s) / 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 @@ -305,10 +306,10 @@ * * WITH_CONFIG(configTag, value) * Runs the test with a specified config override. `configTag` must be - * of `enum GenConfigTag` + * of `enum ConfigTag` * Example: * GIVEN { - * WITH_CONFIG(GEN_CONFIG_GALE_WINGS, GEN_6); + * WITH_CONFIG(CONFIG_GALE_WINGS, GEN_6); * } * The `value` may be inferred from a local variable, e.g. set by * PARAMETRIZE. @@ -333,11 +334,40 @@ * Note if Moves is specified then MOVE will not automatically add moves * to the moveset. * + * For tests using MULTI_BATTLE_TEST, AI_MULTI_BATTLE_TEST, TWO_VS_ONE_BATTLE_TEST, + * AI_TWO_VS_ONE_BATTLE_TEST, ONE_VS_TWO_BATTLE_TEST, and AI_ONE_VS_TWO_BATTLE_TEST, + * the below must be used instead of PLAYER(species) and OPPONENT(species). + * MULTI_PLAYER(species), MULTI_PARTNER(species), MULTI_OPPONENT_A(species), and + * MULTI_OPPONENT_B(species) Adds the species to the player's, player partner's, + * opponent A's, or opponent B's party, respectively. + * Pokemon can be customised as per the guidance for PLAYER(species) and OPPONENT(species). + * The functions assign the Pokémon to the party of the trainer at B_POSITION_PLAYER_LEFT, + * B_POSITION_PLAYER_RIGHT, B_POSITION_OPPONENT_LEFT, and B_POSITION_OPPONENT_RIGHT, respectively. + * MULTI_PLAYER(species) and MULTI_OPPONENT_A(species) set Pokémon starting at party index 0, + * while MULTI_PARTNER(species) and MULTI_OPPONENT_B(species) set Pokémon starting at party + * index 3. + * For ONE_VS_TWO tests, MULTI_PLAYER(species) must be used for all player-side Pokémon, + * and for TWO_VS_ONE tests, MULTI_OPPONENT_A(species) must be used for all opponent-side + * Pokémon. + * All MULTI_PLAYER(species) Pokémon must be set before any MULTI_PARTNER(species) Pokémon, + * and all MULTI_OPPONENT_A(species) must be set before any MULTI_OPPONENT_B(species) Pokémon, + * else Pokémon will be set in the incorrect parties in the test. + * Note where a side in a test has two trainers, the test setup manages the assigning of correct + * multi-party orders, therefore when using functions such as SEND_OUT, Player and Opponent A + * Pokémon may be referenced using indexes 0, 1, and 2, and Player's Partner and Opponent B + * Pokémon may be referenced using indexes 3, 4, and 5. + * * AI_FLAGS - * Specifies which AI flags are run during the test. Has use only for AI tests. + * Specifies which AI flags are run for all battlers 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. * + * BATTLER_AI_FLAGS + * Specifies additional AI flags to be applied to specific battlers (battler 0/1/2/3). Has use only for AI tests. + * Must be used strictly after AI_FLAGS(flags), which overwrites all existing flags. + * Example: BATTLER_AI_FLAGS(3, AI_FLAG_RISKY) used after AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT) + * will set AI_FLAG_RISKY to only battler3 (Opponent B), in addition to the flags set by AI_FLAGS. + * * WHEN * Contains the choices that battlers make during the battle. * @@ -537,10 +567,25 @@ #define MAX_QUEUED_EVENTS 30 #define MAX_EXPECTED_ACTIONS 10 -enum { BATTLE_TEST_SINGLES, BATTLE_TEST_DOUBLES, BATTLE_TEST_WILD, BATTLE_TEST_AI_SINGLES, BATTLE_TEST_AI_DOUBLES }; +enum { + BATTLE_TEST_SINGLES, + BATTLE_TEST_DOUBLES, + BATTLE_TEST_WILD, + BATTLE_TEST_MULTI, + BATTLE_TEST_TWO_VS_ONE, + BATTLE_TEST_ONE_VS_TWO, + BATTLE_TEST_AI_SINGLES, + BATTLE_TEST_AI_DOUBLES, + BATTLE_TEST_AI_MULTI, + BATTLE_TEST_AI_TWO_VS_ONE, + BATTLE_TEST_AI_ONE_VS_TWO +}; typedef void (*SingleBattleTestFunction)(void *, const u32, struct BattlePokemon *, struct BattlePokemon *); typedef void (*DoubleBattleTestFunction)(void *, const u32, struct BattlePokemon *, struct BattlePokemon *, struct BattlePokemon *, struct BattlePokemon *); +typedef void (*MultiBattleTestFunction)(void *, const u32, struct BattlePokemon *, struct BattlePokemon *, struct BattlePokemon *, struct BattlePokemon *); +typedef void (*TwoVsOneBattleTestFunction)(void *, const u32, struct BattlePokemon *, struct BattlePokemon *, struct BattlePokemon *, struct BattlePokemon *); +typedef void (*OneVsTwoBattleTestFunction)(void *, const u32, struct BattlePokemon *, struct BattlePokemon *, struct BattlePokemon *, struct BattlePokemon *); struct BattleTest { @@ -549,6 +594,9 @@ struct BattleTest { SingleBattleTestFunction singles; DoubleBattleTestFunction doubles; + MultiBattleTestFunction multi; + TwoVsOneBattleTestFunction two_vs_one; + OneVsTwoBattleTestFunction one_vs_two; } function; size_t resultsSize; }; @@ -558,6 +606,7 @@ enum QUEUED_ABILITY_POPUP_EVENT, QUEUED_ANIMATION_EVENT, QUEUED_HP_EVENT, + QUEUED_SUB_HIT_EVENT, QUEUED_EXP_EVENT, QUEUED_MESSAGE_EVENT, QUEUED_STATUS_EVENT, @@ -566,7 +615,7 @@ enum struct QueuedAbilityEvent { u8 battlerId; - u16 ability; + enum Ability ability; }; struct QueuedAnimationEvent @@ -587,6 +636,14 @@ struct QueuedHPEvent u32 address:28; }; +struct QueuedSubHitEvent +{ + u32 battlerId:3; + u32 checkBreak:1; + u32 breakSub:1; + u32 address:27; +}; + struct QueuedExpEvent { u32 battlerId:3; @@ -616,29 +673,25 @@ struct QueuedEvent struct QueuedAbilityEvent ability; struct QueuedAnimationEvent animation; struct QueuedHPEvent hp; + struct QueuedSubHitEvent subHit; struct QueuedExpEvent exp; struct QueuedMessageEvent message; struct QueuedStatusEvent status; } as; }; -struct TurnRNG -{ - u16 tag; - u16 value; -}; - struct BattlerTurn { u8 hit:2; u8 criticalHit:2; u8 secondaryEffect:2; - struct TurnRNG rng; + struct RiggedRNG rng; }; struct ExpectedAIAction { - u16 sourceLine; + u16 sourceLine:13; // TODO: Avoid stealing these bits. + enum Gimmick gimmick:3; u8 type:4; // which action u8 moveSlots:4; // Expected move(s) to be chosen or not, marked as bits. u8 target:4; // move target or id of mon which gets sent out @@ -687,17 +740,19 @@ struct BattleTestData u8 playerPartySize; u8 opponentPartySize; - u8 explicitMoves[NUM_BATTLE_SIDES]; + u8 explicitMoves[MAX_BATTLERS_COUNT]; bool8 hasExplicitSpeeds; - u8 explicitSpeeds[NUM_BATTLE_SIDES]; + u8 explicitSpeeds[MAX_BATTLERS_COUNT]; u16 slowerThan[NUM_BATTLE_SIDES][PARTY_SIZE]; - u8 currentSide; + u8 currentPosition; u8 currentPartyIndex; struct Pokemon *currentMon; u8 gender; u8 nature; - u16 forcedAbilities[NUM_BATTLE_SIDES][PARTY_SIZE]; + bool8 isShiny; + enum Ability forcedAbilities[NUM_BATTLE_SIDES][PARTY_SIZE]; u8 chosenGimmick[NUM_BATTLE_SIDES][PARTY_SIZE]; + u8 forcedEnvironment; u8 currentMonIndexes[MAX_BATTLERS_COUNT]; u8 turnState; @@ -765,6 +820,8 @@ extern struct BattleTestRunnerState *const gBattleTestRunnerState; #define R_APPEND_TRUE(...) __VA_OPT__(FIRST(__VA_ARGS__), TRUE RECURSIVELY(R_FOR_EACH(APPEND_COMMA_TRUE, EXCEPT_1(__VA_ARGS__)))) #define AI_TRAINER_NAME "{PKMN} TRAINER LEAF" +#define AI_TRAINER_2_NAME "{PKMN} TRAINER RED" +#define AI_PARTNER_NAME "{PKMN} TRAINER 1" /* Test */ @@ -810,6 +867,60 @@ extern struct BattleTestRunnerState *const gBattleTestRunnerState; }; \ static void CAT(Test, __LINE__)(struct CAT(Result, __LINE__) *results, const u32 i, struct BattlePokemon *playerLeft, struct BattlePokemon *opponentLeft, struct BattlePokemon *playerRight, struct BattlePokemon *opponentRight) + #define BATTLE_TEST_ARGS_MULTI(_name, _type, ...) \ + struct CAT(Result, __LINE__) { RECURSIVELY(R_FOR_EACH(APPEND_SEMICOLON, __VA_ARGS__)) }; \ + static void CAT(Test, __LINE__)(struct CAT(Result, __LINE__) *, const u32, struct BattlePokemon *, struct BattlePokemon *, struct BattlePokemon *, struct BattlePokemon *); \ + __attribute__((section(".tests"), used)) static const struct Test CAT(sTest, __LINE__) = \ + { \ + .name = _name, \ + .filename = __FILE__, \ + .runner = &gBattleTestRunner, \ + .sourceLine = __LINE__, \ + .data = (void *)&(const struct BattleTest) \ + { \ + .type = _type, \ + .function = { .multi = (MultiBattleTestFunction)CAT(Test, __LINE__) }, \ + .resultsSize = sizeof(struct CAT(Result, __LINE__)), \ + }, \ + }; \ + static void CAT(Test, __LINE__)(struct CAT(Result, __LINE__) *results, const u32 i, struct BattlePokemon *playerLeft, struct BattlePokemon *opponentLeft, struct BattlePokemon *playerRight, struct BattlePokemon *opponentRight) + +#define BATTLE_TEST_ARGS_TWO_VS_ONE(_name, _type, ...) \ + struct CAT(Result, __LINE__) { RECURSIVELY(R_FOR_EACH(APPEND_SEMICOLON, __VA_ARGS__)) }; \ + static void CAT(Test, __LINE__)(struct CAT(Result, __LINE__) *, const u32, struct BattlePokemon *, struct BattlePokemon *, struct BattlePokemon *, struct BattlePokemon *); \ + __attribute__((section(".tests"), used)) static const struct Test CAT(sTest, __LINE__) = \ + { \ + .name = _name, \ + .filename = __FILE__, \ + .runner = &gBattleTestRunner, \ + .sourceLine = __LINE__, \ + .data = (void *)&(const struct BattleTest) \ + { \ + .type = _type, \ + .function = { .two_vs_one = (TwoVsOneBattleTestFunction)CAT(Test, __LINE__) }, \ + .resultsSize = sizeof(struct CAT(Result, __LINE__)), \ + }, \ + }; \ + static void CAT(Test, __LINE__)(struct CAT(Result, __LINE__) *results, const u32 i, struct BattlePokemon *playerLeft, struct BattlePokemon *opponentLeft, struct BattlePokemon *playerRight, struct BattlePokemon *opponentRight) + +#define BATTLE_TEST_ARGS_ONE_VS_TWO(_name, _type, ...) \ + struct CAT(Result, __LINE__) { RECURSIVELY(R_FOR_EACH(APPEND_SEMICOLON, __VA_ARGS__)) }; \ + static void CAT(Test, __LINE__)(struct CAT(Result, __LINE__) *, const u32, struct BattlePokemon *, struct BattlePokemon *, struct BattlePokemon *, struct BattlePokemon *); \ + __attribute__((section(".tests"), used)) static const struct Test CAT(sTest, __LINE__) = \ + { \ + .name = _name, \ + .filename = __FILE__, \ + .runner = &gBattleTestRunner, \ + .sourceLine = __LINE__, \ + .data = (void *)&(const struct BattleTest) \ + { \ + .type = _type, \ + .function = { .one_vs_two = (OneVsTwoBattleTestFunction)CAT(Test, __LINE__) }, \ + .resultsSize = sizeof(struct CAT(Result, __LINE__)), \ + }, \ + }; \ + static void CAT(Test, __LINE__)(struct CAT(Result, __LINE__) *results, const u32 i, struct BattlePokemon *playerLeft, struct BattlePokemon *opponentLeft, struct BattlePokemon *playerRight, struct BattlePokemon *opponentRight) + #define SINGLE_BATTLE_TEST(_name, ...) BATTLE_TEST_ARGS_SINGLE(_name, BATTLE_TEST_SINGLES, __VA_ARGS__) #define WILD_BATTLE_TEST(_name, ...) BATTLE_TEST_ARGS_SINGLE(_name, BATTLE_TEST_WILD, __VA_ARGS__) @@ -818,6 +929,15 @@ extern struct BattleTestRunnerState *const gBattleTestRunnerState; #define DOUBLE_BATTLE_TEST(_name, ...) BATTLE_TEST_ARGS_DOUBLE(_name, BATTLE_TEST_DOUBLES, __VA_ARGS__) #define AI_DOUBLE_BATTLE_TEST(_name, ...) BATTLE_TEST_ARGS_DOUBLE(_name, BATTLE_TEST_AI_DOUBLES, __VA_ARGS__) +#define MULTI_BATTLE_TEST(_name, ...) BATTLE_TEST_ARGS_MULTI(_name, BATTLE_TEST_MULTI, __VA_ARGS__) +#define AI_MULTI_BATTLE_TEST(_name, ...) BATTLE_TEST_ARGS_MULTI(_name, BATTLE_TEST_AI_MULTI, __VA_ARGS__) + +#define TWO_VS_ONE_BATTLE_TEST(_name, ...) BATTLE_TEST_ARGS_TWO_VS_ONE(_name, BATTLE_TEST_TWO_VS_ONE, __VA_ARGS__) +#define AI_TWO_VS_ONE_BATTLE_TEST(_name, ...) BATTLE_TEST_ARGS_TWO_VS_ONE(_name, BATTLE_TEST_AI_TWO_VS_ONE, __VA_ARGS__) + +#define ONE_VS_TWO_BATTLE_TEST(_name, ...) BATTLE_TEST_ARGS_ONE_VS_TWO(_name, BATTLE_TEST_ONE_VS_TWO, __VA_ARGS__) +#define AI_ONE_VS_TWO_BATTLE_TEST(_name, ...) BATTLE_TEST_ARGS_ONE_VS_TWO(_name, BATTLE_TEST_AI_ONE_VS_TWO, __VA_ARGS__) + /* Parametrize */ #undef PARAMETRIZE // Override test/test.h's implementation. @@ -846,13 +966,18 @@ struct moveWithPP { #define RNGSeed(seed) RNGSeed_(__LINE__, seed) #define AI_FLAGS(flags) AIFlags_(__LINE__, flags) +#define BATTLER_AI_FLAGS(battler, flags) BattlerAIFlags_(__LINE__, battler, flags) #define AI_LOG AILogScores(__LINE__) #define FLAG_SET(flagId) SetFlagForTest(__LINE__, flagId) #define WITH_CONFIG(configTag, value) TestSetConfig(__LINE__, configTag, value) -#define PLAYER(species) for (OpenPokemon(__LINE__, B_SIDE_PLAYER, species); gBattleTestRunnerState->data.currentMon; ClosePokemon(__LINE__)) -#define OPPONENT(species) for (OpenPokemon(__LINE__, B_SIDE_OPPONENT, species); gBattleTestRunnerState->data.currentMon; ClosePokemon(__LINE__)) +#define PLAYER(species) for (OpenPokemon(__LINE__, B_POSITION_PLAYER_LEFT, species); gBattleTestRunnerState->data.currentMon; ClosePokemon(__LINE__)) +#define OPPONENT(species) for (OpenPokemon(__LINE__, B_POSITION_OPPONENT_LEFT, species); gBattleTestRunnerState->data.currentMon; ClosePokemon(__LINE__)) +#define MULTI_PLAYER(species) for (OpenPokemonMulti(__LINE__, B_POSITION_PLAYER_LEFT, species); gBattleTestRunnerState->data.currentMon; ClosePokemon(__LINE__)) +#define MULTI_OPPONENT_A(species) for (OpenPokemonMulti(__LINE__, B_POSITION_OPPONENT_LEFT, species); gBattleTestRunnerState->data.currentMon; ClosePokemon(__LINE__)) +#define MULTI_PARTNER(species) for (OpenPokemonMulti(__LINE__, B_POSITION_PLAYER_RIGHT, species); gBattleTestRunnerState->data.currentMon; ClosePokemon(__LINE__)) +#define MULTI_OPPONENT_B(species) for (OpenPokemonMulti(__LINE__, B_POSITION_OPPONENT_RIGHT, species); gBattleTestRunnerState->data.currentMon; ClosePokemon(__LINE__)) #define Gender(gender) Gender_(__LINE__, gender) #define Nature(nature) Nature_(__LINE__, nature) @@ -880,20 +1005,24 @@ struct moveWithPP { #define DynamaxLevel(dynamaxLevel) DynamaxLevel_(__LINE__, dynamaxLevel) #define GigantamaxFactor(gigantamaxFactor) GigantamaxFactor_(__LINE__, gigantamaxFactor) #define TeraType(teraType) TeraType_(__LINE__, teraType) -#define Shadow(isShadow) Shadow_(__LINE__, shadow) +#define Shadow(isShadow) Shadow_(__LINE__, isShadow) +#define Shiny(isShiny) Shiny_(__LINE__, isShiny) +#define Environment(environment) Environment_(__LINE__, environment) void SetFlagForTest(u32 sourceLine, u16 flagId); -void TestSetConfig(u32 sourceLine, enum GenConfigTag configTag, u32 value); +void TestSetConfig(u32 sourceLine, enum ConfigTag configTag, u32 value); void ClearFlagAfterTest(void); -void OpenPokemon(u32 sourceLine, u32 side, u32 species); +void OpenPokemon(u32 sourceLine, enum BattlerPosition position, u32 species); +void OpenPokemonMulti(u32 sourceLine, enum BattlerPosition position, u32 species); void ClosePokemon(u32 sourceLine); void RNGSeed_(u32 sourceLine, rng_value_t seed); void AIFlags_(u32 sourceLine, u64 flags); +void BattlerAIFlags_(u32 sourceLine, u32 battler, u64 flags); void AILogScores(u32 sourceLine); void Gender_(u32 sourceLine, u32 gender); void Nature_(u32 sourceLine, u32 nature); -void Ability_(u32 sourceLine, u32 ability); +void Ability_(u32 sourceLine, enum Ability ability); void Level_(u32 sourceLine, u32 level); void MaxHP_(u32 sourceLine, u32 maxHP); void HP_(u32 sourceLine, u32 hp); @@ -916,8 +1045,26 @@ void Status1_(u32 sourceLine, u32 status1); void OTName_(u32 sourceLine, const u8 *otName); void DynamaxLevel_(u32 sourceLine, u32 dynamaxLevel); void GigantamaxFactor_(u32 sourceLine, bool32 gigantamaxFactor); -void TeraType_(u32 sourceLine, u32 teraType); +void TeraType_(u32 sourceLine, enum Type teraType); void Shadow_(u32 sourceLine, bool32 isShadow); +void Shiny_(u32 sourceLine, bool32 isShiny); +void Environment_(u32 sourceLine, u32 environment); + +static inline bool8 IsMultibattleTest(void) +{ + if (TESTING) + { + if (((gBattleTypeFlags & BATTLE_MULTI_TEST) == BATTLE_MULTI_TEST) + || ((gBattleTypeFlags & BATTLE_TWO_VS_ONE_TEST) == BATTLE_TWO_VS_ONE_TEST)) + return TRUE; + else + return FALSE; + } + else + { + return FALSE; + } +} // Created for easy use of EXPECT_MOVES, so the user can provide 1, 2, 3 or 4 moves for AI which can pass the test. struct FourMoves @@ -968,7 +1115,7 @@ enum { TURN_CLOSED, TURN_OPEN, TURN_CLOSING }; #define SKIP_TURN(battler) SkipTurn(__LINE__, battler) #define SEND_OUT(battler, partyIndex) SendOut(__LINE__, battler, partyIndex) #define USE_ITEM(battler, ...) UseItem(__LINE__, battler, (struct ItemContext) { R_APPEND_TRUE(__VA_ARGS__) }) -#define WITH_RNG(tag, value) rng: ((struct TurnRNG) { tag, value }) +#define WITH_RNG(tag, value) rng: ((struct RiggedRNG) { tag, value }) struct MoveContext { @@ -993,7 +1140,7 @@ struct MoveContext u16 explicitNotExpected:1; struct BattlePokemon *target; bool8 explicitTarget; - struct TurnRNG rng; + struct RiggedRNG rng; bool8 explicitRNG; }; @@ -1005,7 +1152,7 @@ struct ItemContext u16 explicitPartyIndex:1; u16 move; u16 explicitMove:1; - struct TurnRNG rng; + struct RiggedRNG rng; u16 explicitRNG:1; }; @@ -1036,6 +1183,7 @@ void SendOut(u32 sourceLine, struct BattlePokemon *, u32 partyIndex); #define ABILITY_POPUP(battler, ...) QueueAbility(__LINE__, battler, (struct AbilityEventContext) { __VA_ARGS__ }) #define ANIMATION(type, id, ...) QueueAnimation(__LINE__, type, id, (struct AnimationEventContext) { __VA_ARGS__ }) #define HP_BAR(battler, ...) QueueHP(__LINE__, battler, (struct HPEventContext) { R_APPEND_TRUE(__VA_ARGS__) }) +#define SUB_HIT(battler, ...) QueueSubHit(__LINE__, battler, (struct SubHitEventContext) { R_APPEND_TRUE(__VA_ARGS__) }) #define EXPERIENCE_BAR(battler, ...) QueueExp(__LINE__, battler, (struct ExpEventContext) { R_APPEND_TRUE(__VA_ARGS__) }) // Static const is needed to make the modern compiler put the pattern variable in the .rodata section, instead of putting it on stack(which can break the game). #define MESSAGE(pattern) do {static const u8 msg[] = _(pattern); QueueMessage(__LINE__, msg);} while (0) @@ -1044,17 +1192,17 @@ void SendOut(u32 sourceLine, struct BattlePokemon *, u32 partyIndex); (B_USE_FROSTBITE ? STATUS_ICON(battler, frostbite: isFrostbite) : STATUS_ICON(battler, freeze: isFrostbite)) #define SWITCH_OUT_MESSAGE(name) ONE_OF { \ - MESSAGE(name ", that's enough! Come back!"); \ - MESSAGE(name ", come back!"); \ - MESSAGE(name ", OK! Come back!"); \ - MESSAGE(name ", good! Come back!"); \ + MESSAGE(name ",好了!\n回来!"); \ + MESSAGE(name ",\n回来!"); \ + MESSAGE(name ",很好!\n回来!"); \ + MESSAGE(name ",很好!\n回来!"); \ } #define SEND_IN_MESSAGE(name) ONE_OF { \ - MESSAGE("Go! " name "!"); \ - MESSAGE("You're in charge, " name "!"); \ - MESSAGE("Go for it, " name "!"); \ - MESSAGE("Your opponent's weak! Get 'em, " name "!"); \ + MESSAGE("上吧!" name "!"); \ + MESSAGE("交给你了!" name "!"); \ + MESSAGE("加油!" name "!"); \ + MESSAGE("对手变弱了!\n机会来了!" name "!"); \ } enum QueueGroupType @@ -1066,7 +1214,7 @@ enum QueueGroupType struct AbilityEventContext { - u16 ability; + enum Ability ability; }; struct AnimationEventContext @@ -1088,6 +1236,15 @@ struct HPEventContext bool8 explicitCaptureDamage; }; +struct SubHitEventContext +{ + u8 _; + bool8 subBreak; + bool8 explicitSubBreak; + u16 *captureDamage; + bool8 explicitCaptureDamage; +}; + struct ExpEventContext { u8 _; @@ -1116,6 +1273,7 @@ void CloseQueueGroup(u32 sourceLine); void QueueAbility(u32 sourceLine, struct BattlePokemon *battler, struct AbilityEventContext); void QueueAnimation(u32 sourceLine, u32 type, u32 id, struct AnimationEventContext); void QueueHP(u32 sourceLine, struct BattlePokemon *battler, struct HPEventContext); +void QueueSubHit(u32 sourceLine, struct BattlePokemon *battler, struct SubHitEventContext); void QueueExp(u32 sourceLine, struct BattlePokemon *battler, struct ExpEventContext); void QueueMessage(u32 sourceLine, const u8 *pattern); void QueueStatus(u32 sourceLine, struct BattlePokemon *battler, struct StatusEventContext); diff --git a/include/test/test.h b/include/test/test.h index 7b3225934d..15f71d50b1 100644 --- a/include/test/test.h +++ b/include/test/test.h @@ -2,8 +2,10 @@ #define GUARD_TEST_H #include "test_runner.h" +#include "random.h" #define MAX_PROCESSES 32 // See also tools/mgba-rom-test-hydra/main.c +#define RIGGED_RNG_COUNT 8 enum TestResult { @@ -26,6 +28,9 @@ struct TestRunner void (*tearDown)(void *); bool32 (*checkProgress)(void *); bool32 (*handleExitWithResult)(void *, enum TestResult); + u32 (*randomUniform)(enum RandomTag tag, u32 lo, u32 hi, bool32 (*reject)(u32), void *caller); + u32 (*randomWeightedArray)(enum RandomTag tag, u32 sum, u32 n, const u8 *weights, void *caller); + const void* (*randomElementArray)(enum RandomTag tag, const void *array, size_t size, size_t count, void *caller); }; struct Test @@ -76,11 +81,18 @@ extern const char gTestRunnerArgv[256]; extern const struct TestRunner gAssumptionsRunner; +struct RiggedRNG +{ + u16 tag; + u16 value; +}; + struct FunctionTestRunnerState { u16 parameters; u16 runParameter; u16 checkProgressParameter; + struct RiggedRNG rngList[RIGGED_RNG_COUNT]; }; extern const struct TestRunner gFunctionTestRunner; @@ -97,6 +109,8 @@ void Test_ExpectCrash(bool32); void Test_ExitWithResult(enum TestResult, u32 stopLine, const char *fmt, ...); u32 SourceLine(u32 sourceLineOffset); u32 SourceLineOffset(u32 sourceLine); +void SetupRiggedRng(u32 sourceLine, enum RandomTag randomTag, u32 value); +void ClearRiggedRng(); s32 Test_MgbaPrintf(const char *fmt, ...); @@ -245,6 +259,8 @@ static inline struct Benchmark BenchmarkStop(void) #define PARAMETRIZE_LABEL(f, label) if (gFunctionTestRunnerState->parameters++ == gFunctionTestRunnerState->runParameter && (Test_MgbaPrintf(":N%s: " f " (%d/%d)", gTestRunnerState.test->name, label, gFunctionTestRunnerState->runParameter + 1, gFunctionTestRunnerState->parameters), 1)) +#define SET_RNG(tag, value) SetupRiggedRng(__LINE__, tag, value) + #define TO_DO \ do { \ Test_ExpectedResult(TEST_RESULT_TODO); \ diff --git a/include/test/test_runner_battle.h b/include/test/test_runner_battle.h new file mode 100644 index 0000000000..8a2c0dc64b --- /dev/null +++ b/include/test/test_runner_battle.h @@ -0,0 +1,6 @@ +#ifndef GUARD_BATTLE_TEST_RUNNER_H +#define GUARD_BATTLE_TEST_RUNNER_H + +bool8 IsMultibattleTest(void); + +#endif diff --git a/include/test_runner.h b/include/test_runner.h index b7aa69a076..fa97da9881 100644 --- a/include/test_runner.h +++ b/include/test_runner.h @@ -11,14 +11,17 @@ extern const bool8 gTestRunnerSkipIsFail; #if TESTING -void TestRunner_Battle_RecordAbilityPopUp(u32 battlerId, u32 ability); +enum Gimmick; + +void TestRunner_Battle_RecordAbilityPopUp(u32 battlerId, enum Ability ability); void TestRunner_Battle_RecordAnimation(u32 animType, u32 animId); void TestRunner_Battle_RecordHP(u32 battlerId, u32 oldHP, u32 newHP); +void TestRunner_Battle_RecordSubHit(u32 battlerId, u32 damage, bool32 broke); void TestRunner_Battle_RecordExp(u32 battlerId, u32 oldExp, u32 newExp); void TestRunner_Battle_RecordMessage(const u8 *message); void TestRunner_Battle_RecordStatus1(u32 battlerId, u32 status1); void TestRunner_Battle_AfterLastTurn(void); -void TestRunner_Battle_CheckChosenMove(u32 battlerId, u32 moveId, u32 target); +void TestRunner_Battle_CheckChosenMove(u32 battlerId, u32 moveId, u32 target, enum Gimmick gimmick); void TestRunner_Battle_CheckSwitch(u32 battlerId, u32 partyIndex); void TestRunner_Battle_CheckAiMoveScores(u32 battlerId); void TestRunner_Battle_AISetScore(const char *file, u32 line, u32 battlerId, u32 moveIndex, s32 score); @@ -30,12 +33,14 @@ void TestRunner_Battle_CheckBattleRecordActionType(u32 battlerId, u32 recordInde u32 TestRunner_Battle_GetForcedAbility(u32 side, u32 partyIndex); u32 TestRunner_Battle_GetChosenGimmick(u32 side, u32 partyIndex); +u32 TestRunner_Battle_GetForcedEnvironment(void); #else #define TestRunner_Battle_RecordAbilityPopUp(...) (void)0 #define TestRunner_Battle_RecordAnimation(...) (void)0 #define TestRunner_Battle_RecordHP(...) (void)0 +#define TestRunner_Battle_RecordSubHit(...) (void)0 #define TestRunner_Battle_RecordExp(...) (void)0 #define TestRunner_Battle_RecordMessage(...) (void)0 #define TestRunner_Battle_RecordStatus1(...) (void)0 @@ -53,6 +58,8 @@ u32 TestRunner_Battle_GetChosenGimmick(u32 side, u32 partyIndex); #define TestRunner_Battle_GetChosenGimmick(...) (u32)0 +#define TestRunner_Battle_GetForcedEnvironment(...) (u8)0 + #endif #endif diff --git a/include/text.h b/include/text.h index 040fe49f13..294bff94c7 100644 --- a/include/text.h +++ b/include/text.h @@ -1,8 +1,15 @@ #ifndef GUARD_TEXT_H #define GUARD_TEXT_H +#include "config/text.h" #include "constants/characters.h" +// This is to prevent the user from having a higher text speed modifier than the printing system can handle. +STATIC_ASSERT( TEXT_SPEED_SLOW_MODIFIER <= 31 + && TEXT_SPEED_MEDIUM_MODIFIER <= 31 + && TEXT_SPEED_FAST_MODIFIER <= 31 + && TEXT_SPEED_INSTANT_MODIFIER <= 31, TextSpeedModifiersCantGoPast31) + // Given as a text speed when all the text should be // loaded at once but not copied to vram yet. #define TEXT_SKIP_DRAW 0xFF @@ -59,9 +66,9 @@ struct TextPrinterSubStruct u8 fontId:4; // 0x14 bool8 hasPrintBeenSpedUp:1; u8 unk:3; - u8 downArrowDelay:5; - u8 downArrowYPosIdx:2; - bool8 hasFontIdBeenSet:1; + u16 utilityCounter:13; + u16 downArrowYPosIdx:2; + bool16 hasFontIdBeenSet:1; u8 autoScrollDelay; }; @@ -135,7 +142,6 @@ struct TextGlyph }; extern TextFlags gTextFlags; - extern u8 gDisableTextPrinters; extern struct TextGlyph gCurGlyph; @@ -178,4 +184,11 @@ u32 GetFontIdToFit(const u8 *string, u32 widestFontId, u32 letterSpacing, u32 wi u8 *PrependFontIdToFit(u8 *start, u8 *end, u32 fontId, u32 width); u8 *WrapFontIdToFit(u8 *start, u8 *end, u32 fontId, u32 width); +// player text speed +u32 GetPlayerTextSpeed(void); +u32 GetPlayerTextSpeedDelay(void); +u32 GetPlayerTextSpeedModifier(void); +u32 GetPlayerTextScrollSpeed(void); +bool32 IsPlayerTextSpeedInstant(void); + #endif // GUARD_TEXT_H diff --git a/include/trade.h b/include/trade.h index 24de69b036..553d5ab334 100644 --- a/include/trade.h +++ b/include/trade.h @@ -14,7 +14,7 @@ s32 GetGameProgressForLinkTrade(void); void CB2_StartCreateTradeMenu(void); void CB2_LinkTrade(void); int CanRegisterMonForTradingBoard(struct RfuGameCompatibilityData player, u16 species2, u16 species, bool8 isModernFatefulEncounter); -int GetUnionRoomTradeMessageId(struct RfuGameCompatibilityData player, struct RfuGameCompatibilityData partner, u16 playerSpecies2, u16 partnerSpecies, u8 requestedType, u16 playerSpecies, bool8 isModernFatefulEncounter); +int GetUnionRoomTradeMessageId(struct RfuGameCompatibilityData player, struct RfuGameCompatibilityData partner, u16 playerSpecies2, u16 partnerSpecies, enum Type requestedType, u16 playerSpecies, bool8 isModernFatefulEncounter); int CanSpinTradeMon(struct Pokemon *mon, u16 monIdx); void InitTradeSequenceBgGpuRegs(void); void LinkTradeDrawWindow(void); diff --git a/include/trainer_pools.h b/include/trainer_pools.h index 196657a55f..72df3e765c 100644 --- a/include/trainer_pools.h +++ b/include/trainer_pools.h @@ -56,10 +56,12 @@ enum PoolTags { struct PoolRules { - bool8 speciesClause; - bool8 excludeForms; - bool8 itemClause; - bool8 itemClauseExclusions; + u8 speciesClause:1; + u8 excludeForms:1; + u8 itemClause:1; + u8 itemClauseExclusions:1; + u8 megaStoneClause:1; + u8 zCrystalClause:1; u8 tagMaxMembers[POOL_NUM_TAGS]; bool8 tagRequired[POOL_NUM_TAGS]; }; diff --git a/include/trainer_slide.h b/include/trainer_slide.h index 19fdf7c24a..a8f1988fb8 100644 --- a/include/trainer_slide.h +++ b/include/trainer_slide.h @@ -12,7 +12,7 @@ struct MessageStatus void SetTrainerSlideMessage(enum DifficultyLevel difficulty, u32 trainerId, u32 slideId); enum TrainerSlideTargets ShouldDoTrainerSlide(u32 battler, enum TrainerSlideType slideId); -void TryInitializeFirstSTABMoveTrainerSlide(u32 battlerDef, u32 battlerAtk, u32 moveType); +void TryInitializeFirstSTABMoveTrainerSlide(u32 battlerDef, u32 battlerAtk, enum Type moveType); void TryInitializeTrainerSlidePlayerLandsFirstCriticalHit(u32 target); void TryInitializeTrainerSlideEnemyLandsFirstCriticalHit(u32 target); void TryInitializeTrainerSlidePlayerLandsFirstSuperEffectiveHit(u32 target); diff --git a/include/union_room.h b/include/union_room.h index 514a159850..5616c106d3 100644 --- a/include/union_room.h +++ b/include/union_room.h @@ -149,7 +149,7 @@ extern u8 gPlayerCurrActivity; extern struct RfuGameCompatibilityData gRfuPartnerCompatibilityData; extern u16 gUnionRoomOfferedSpecies; -extern u8 gUnionRoomRequestedMonType; +extern enum Type gUnionRoomRequestedMonType; u8 CreateTask_CreateTradeMenu(void); void SetUsingUnionRoomStartMenu(void); diff --git a/include/window.h b/include/window.h index 2dd67b123f..fc35f724d9 100644 --- a/include/window.h +++ b/include/window.h @@ -45,7 +45,7 @@ struct WindowTemplate struct Window { struct WindowTemplate window; - u8 *tileData; + ALIGNED(4) u8 *tileData; }; bool32 InitWindows(const struct WindowTemplate *templates); diff --git a/make_tools.mk b/make_tools.mk index 8251768401..f0eb2d2962 100644 --- a/make_tools.mk +++ b/make_tools.mk @@ -5,7 +5,7 @@ MAKEFLAGS += --no-print-directory # Inclusive list. If you don't want a tool to be built, don't add it here. TOOLS_DIR := tools -TOOL_NAMES := aif2pcm bin2c gbafix gbagfx jsonproc mapjson mid2agb preproc ramscrgen rsfont scaninc trainerproc compresSmol +TOOL_NAMES := bin2c gbafix gbagfx jsonproc mapjson mid2agb preproc ramscrgen rsfont scaninc trainerproc compresSmol wav2agb CHECK_TOOL_NAMES = patchelf mgba-rom-test-hydra TOOLDIRS := $(TOOL_NAMES:%=$(TOOLS_DIR)/%) diff --git a/migration_scripts/1.11/consolidate_contest_opponent_filters.py b/migration_scripts/1.11/consolidate_contest_opponent_filters.py index f6495be81d..0f8f25d0b3 100644 --- a/migration_scripts/1.11/consolidate_contest_opponent_filters.py +++ b/migration_scripts/1.11/consolidate_contest_opponent_filters.py @@ -1,45 +1,44 @@ -import glob -import re -import os - -if not os.path.exists("Makefile"): - print("Please run this script from your root folder.") - quit() - -# Read contest_opponents.h -for file in glob.glob('./src/data/contest_opponents.h'): - with open(file, 'r', encoding="utf-8") as f: - source_content = f.read() - -# Extract party info from contest_opponents.h -source_pattern = re.compile(r'(\[CONTEST_OPPONENT_.*\])\s*=\s(CONTEST_FILTER_.*)*') -source_data = {} -for match in source_pattern.findall(source_content): - if len(match) == 2: - trainer_name, contest_filter = match - source_data[trainer_name] = (contest_filter) - -# Read contest_opponents.h content -for file in glob.glob('./src/data/contest_opponents.h'): - with open(file, 'r', encoding="utf-8") as f: - destination_content = f.read() - -# Modify contest_opponents.h content -def add_filter_data(match): - trainer_name = match.group(1) - if trainer_name in source_data: - contest_filter = source_data[trainer_name] - print(f"Updating {trainer_name}: adding {contest_filter}") - #return f'{trainer_name} = {{\n .filter = {contest_filter}' - return f'{match.group(0)}\n .filter = {contest_filter}' - else: - return match.group(0) - -destination_pattern = re.compile(r'(\[CONTEST_OPPONENT_[A-Z_0-9]+\])\s*=\s*{') -modified_content = destination_pattern.sub(add_filter_data, destination_content) - -# Write the modified content back to contest_opponents.h -for file in glob.glob('./src/data/contest_opponents.h'): - with open(file, 'w', encoding="utf-8") as f: - f.write(modified_content) - print("contest_opponents.h has been updated") +import glob +import re +import os + +if not os.path.exists("Makefile"): + print("Please run this script from your root folder.") + quit() + +# Read contest_opponents.h +for file in glob.glob('./src/data/contest_opponents.h'): + with open(file, 'r', encoding="utf-8") as f: + source_content = f.read() + +# Extract party info from contest_opponents.h +source_pattern = re.compile(r'(\[CONTEST_OPPONENT_.*\])\s*=\s(CONTEST_FILTER_.*)*') +source_data = {} +for match in source_pattern.findall(source_content): + if len(match) == 2: + trainer_name, contest_filter = match + source_data[trainer_name] = (contest_filter) + +# Read contest_opponents.h content +for file in glob.glob('./src/data/contest_opponents.h'): + with open(file, 'r', encoding="utf-8") as f: + destination_content = f.read() + +# Modify contest_opponents.h content +def add_filter_data(match): + trainer_name = match.group(1) + if trainer_name in source_data: + contest_filter = source_data[trainer_name] + print(f"Updating {trainer_name}: adding {contest_filter}") + return f'{match.group(0)}\n .filter = {contest_filter}' + else: + return match.group(0) + +destination_pattern = re.compile(r'(\[CONTEST_OPPONENT_[A-Z_0-9]+\])\s*=\s*{') +modified_content = destination_pattern.sub(add_filter_data, destination_content) + +# Write the modified content back to contest_opponents.h +for file in glob.glob('./src/data/contest_opponents.h'): + with open(file, 'w', encoding="utf-8") as f: + f.write(modified_content) + print("contest_opponents.h has been updated") diff --git a/migration_scripts/1.14/bin_to_wav.py b/migration_scripts/1.14/bin_to_wav.py new file mode 100644 index 0000000000..499c7666e2 --- /dev/null +++ b/migration_scripts/1.14/bin_to_wav.py @@ -0,0 +1,301 @@ +#!/usr/bin/env python3 + +""" +Converts .bin audio files (GBA format) to .wav files. +Reads the binary format created by aif2pcm and generates WAV files +that will produce identical binaries when processed by wav2agb -b. +""" + +import struct +import sys +import os +from typing import Optional + +# Delta encoding table used for compression/decompression +# Matches the table in tools/aif2pcm/main.c +DELTA_ENCODING_TABLE = [ + 0, 1, 4, 9, 16, 25, 36, 49, + -64, -49, -36, -25, -16, -9, -4, -1, +] + + +def delta_decompress(compressed_data: bytes, expected_length: int) -> bytes: + """ + Decompress delta-encoded audio data. + + Delta compression format (from tools/aif2pcm/main.c): + - Data is organized in blocks of up to 64 samples each + - Each block starts with a base sample value (1 byte) + - Followed by a delta index (4 bits) for the second sample + - Then 31 pairs of delta indices (4 bits each, packed into bytes) + - Delta indices reference DELTA_ENCODING_TABLE to get the actual delta value + + Args: + compressed_data: The compressed audio data + expected_length: Expected length of decompressed data + + Returns: + Decompressed audio data as bytes + """ + pcm = bytearray(expected_length + 0x40) # Extra buffer space + + i = 0 # Input position + j = 0 # Output position + + while i < len(compressed_data) and j < expected_length: + # Read base sample for this block + base = compressed_data[i] + # Convert to signed int8 for calculations + base_signed = base if base < 128 else base - 256 + pcm[j] = base + i += 1 + j += 1 + + if i >= len(compressed_data) or j >= expected_length: + break + + # Read second sample using low nibble delta + lo = compressed_data[i] & 0xf + base_signed += DELTA_ENCODING_TABLE[lo] + pcm[j] = base_signed & 0xff + i += 1 + j += 1 + + if i >= len(compressed_data) or j >= expected_length: + break + + # Process up to 31 pairs of samples (62 samples total) + for k in range(31): + # High nibble + hi = (compressed_data[i] >> 4) & 0xf + base_signed += DELTA_ENCODING_TABLE[hi] + pcm[j] = base_signed & 0xff + j += 1 + + if j >= expected_length: + break + + # Low nibble + lo = compressed_data[i] & 0xf + base_signed += DELTA_ENCODING_TABLE[lo] + pcm[j] = base_signed & 0xff + j += 1 + i += 1 + + if i >= len(compressed_data): + break + if j >= expected_length: + break + + if j >= expected_length: + break + + return bytes(pcm[:j]) + + +def read_bin(bin_path: str) -> tuple: + """ + Read a GBA audio .bin file and extract all data. + + Binary format (little-endian): + - Bytes 0-3: flags (bit 0 = compression, bit 30 = loop enabled) + - Bytes 4-7: pitch value = sample_rate * 1024 + - Bytes 8-11: loop start position + - Bytes 12-15: loop end position (stored as actual_end - 1) + - Remaining bytes: audio samples (8-bit signed) + """ + with open(bin_path, 'rb') as f: + bin_data = f.read() + + if len(bin_data) < 16: + raise ValueError(f"File too small: {len(bin_data)} bytes") + + # Read header + flags = struct.unpack(' 0 else 0 + padding = bytes([last_sample] * (expected_num_samples - len(samples))) + samples = samples + padding + else: + # For uncompressed data, only read expected_num_samples + # (ignore any trailing alignment padding in the .bin file) + samples = compressed_data[:expected_num_samples] + + # For loop_end, use the expected number from the header + # This matches aif2pcm's behavior where the COMM chunk has the expected count + # even if the actual SSND data is shorter + loop_end = expected_num_samples if is_looped else 0 + + return sample_rate, is_looped, loop_start, loop_end, samples + + +def write_wav(wav_path: str, sample_rate: float, is_looped: bool, + loop_start: int, loop_end: int, samples: bytes): + """ + Write a .wav file with smpl chunk. + """ + # WAV uses unsigned 8-bit, GBA bin uses signed 8-bit + # Convert signed (-128 to +127) to unsigned (0 to 255) + samples_unsigned = bytes((b + 128) & 0xFF for b in samples) + + # For WAV fmt chunk, use integer sample rate + sample_rate_int = int(sample_rate) + num_channels = 1 + bytes_per_sample = 1 + bits_per_sample = 8 + byte_rate = sample_rate_int * num_channels * bytes_per_sample + block_align = num_channels * bytes_per_sample + + # Build fmt chunk + fmt_chunk = struct.pack(' {wav_path}") + + sample_rate, is_looped, loop_start, loop_end, samples = read_bin(bin_path) + + print(f" Sample rate: {sample_rate} Hz") + print(f" Num samples: {len(samples)}") + if is_looped: + print(f" Loop: {loop_start} -> {loop_end}") + else: + print(f" Loop: None") + + write_wav(wav_path, sample_rate, is_looped, loop_start, loop_end, samples) + print(f" Done!") + + +def main(): + if len(sys.argv) < 2: + print("Usage: bin_to_wav.py [output.wav]") + print(" or: bin_to_wav.py (converts all .bin files in directory)") + sys.exit(1) + + input_path = sys.argv[1] + + if os.path.isdir(input_path): + # Convert all .bin files in directory + for filename in sorted(os.listdir(input_path)): + if filename.lower().endswith('.bin'): + bin_path = os.path.join(input_path, filename) + convert_bin_to_wav(bin_path) + else: + # Convert single file + output_path = sys.argv[2] if len(sys.argv) > 2 else None + convert_bin_to_wav(input_path, output_path) + + +if __name__ == '__main__': + main() diff --git a/migration_scripts/1.14/consolidate_contest_effects.py b/migration_scripts/1.14/consolidate_contest_effects.py new file mode 100644 index 0000000000..b517a45d2c --- /dev/null +++ b/migration_scripts/1.14/consolidate_contest_effects.py @@ -0,0 +1,44 @@ +import glob +import re +import os + +if not os.path.exists("Makefile"): + print("Please run this script from your root folder.") + quit() + +# Read contest.c and extract the party information +for file in glob.glob('./src/contest.c'): + with open(file, 'r') as f: + source_content = f.read() + +# Extract party info from contest.c +source_pattern = re.compile(r'(\[CONTEST_EFFECT_.*\])\s*=\s(COMPOUND_STRING.*),') +source_data = {} +for match in source_pattern.findall(source_content): + if len(match) == 2: + contest_effect, effect_description = match + source_data[contest_effect] = (effect_description) + +# Read contest_moves.h content +for file in glob.glob('./src/data/contest_moves.h'): + with open(file, 'r') as f: + destination_content = f.read() + +# Modify contest_moves.h content +def add_description(match): + contest_effect = match.group(1) + if contest_effect in source_data: + effect_description = source_data[contest_effect] + print(f"Updating {contest_effect}: adding {effect_description}") + return f"{match.group(0)}\n .description = {effect_description}," + else: + return match.group(0) + +destination_pattern = re.compile(r'(\[CONTEST_EFFECT_.*\]) =\s*\n\s*{') +modified_content = destination_pattern.sub(add_description, destination_content) + +# Write the modified content back to contest_moves.h +for file in glob.glob('./src/data/contest_moves.h'): + with open(file, 'w') as f: + f.write(modified_content) + print("contest_moves.h has been updated") diff --git a/migration_scripts/add_time_based_encounters.py b/migration_scripts/add_time_based_encounters.py index aebdafc2b2..b036e46e41 100644 --- a/migration_scripts/add_time_based_encounters.py +++ b/migration_scripts/add_time_based_encounters.py @@ -7,7 +7,7 @@ try: print("Please run this script from the project's root folder.") quit() sys.path.append("./tools/wild_encounters/") - from wild_encounters_to_header import TimeOfDay, SetupUserTimeEnum + from wild_encounters_to_header import Config except ImportError: print("Could not import the file tools/wild_encounters/wild_encounters_to_header.py") quit() @@ -24,11 +24,13 @@ def GetWildEncounterFile(): print("Please run this script from the project's root folder.") quit() - timeOfDay = SetupUserTimeEnum(TimeOfDay()) - wFile = open("src/data/wild_encounters.json") wData = json.load(wFile) + config = Config('include/config/overworld.h', 'include/constants/rtc.h', wData) + timeOfDay = config.times_of_day + + wBackupData = json.dumps(wData, indent=2) wBackupFile = open("src/data/wild_encounters.json.bak", mode="w", encoding="utf-8") wBackupFile.write(wBackupData) @@ -49,7 +51,7 @@ def GetWildEncounterFile(): wEncounters_New = list() for map in wEncounters: - for suffix in timeOfDay.fvals: + for suffix in timeOfDay.values(): tempSuffix = "_" + suffix if tempSuffix in map["base_label"]: editMap = False @@ -59,7 +61,7 @@ def GetWildEncounterFile(): if editMap: k = 0 - for suffix in timeOfDay.fvals: + for suffix in timeOfDay.values(): tempDict = dict() if k == TIME_OF_DAY_DEFAULT or COPY_FULL_ENCOUNTER: tempDict = map.copy() diff --git a/python_tools/log.txt b/python_tools/log.txt index 1aa41354c3..bcc54b8660 100644 --- a/python_tools/log.txt +++ b/python_tools/log.txt @@ -1047,3 +1047,839 @@ ✅ 处理文件:c:\Users\Nox\Documents\GitHub\pokeemerald-expansion-Chinese\src\data\pokemon\species_info\gen_8_families.h ✅ 处理文件:c:\Users\Nox\Documents\GitHub\pokeemerald-expansion-Chinese\src\data\pokemon\species_info\gen_9_families.h ❌ 未找到 SPECIES_CAPSAKID,跳过 +❌ ITEM_MAX_REVIVE 没有单独道具说明,跳过 +❌ ITEM_FULL_HEAL 没有单独道具说明,跳过 +❌ ITEM_MAX_HONEY 没有单独道具说明,跳过 +❌ ITEM_PEWTER_CRUNCHIES 没有单独道具说明,跳过 +❌ ITEM_RAGE_CANDY_BAR 没有单独道具说明,跳过 +❌ ITEM_OLD_GATEAU 没有单独道具说明,跳过 +❌ ITEM_CASTELIACONE 没有单独道具说明,跳过 +❌ ITEM_LUMIOSE_GALETTE 没有单独道具说明,跳过 +❌ ITEM_SHALOUR_SABLE 没有单独道具说明,跳过 +❌ ITEM_BIG_MALASADA 没有单独道具说明,跳过 +❌ ITEM_HEALTH_FEATHER 没有单独道具说明,跳过 +❌ ITEM_MUSCLE_FEATHER 没有单独道具说明,跳过 +❌ ITEM_RESIST_FEATHER 没有单独道具说明,跳过 +❌ ITEM_GENIUS_FEATHER 没有单独道具说明,跳过 +❌ ITEM_CLEVER_FEATHER 没有单独道具说明,跳过 +❌ ITEM_SWIFT_FEATHER 没有单独道具说明,跳过 +❌ ITEM_POKE_DOLL 没有单独道具说明,跳过 +❌ ITEM_FLUFFY_TAIL 没有单独道具说明,跳过 +❌ ITEM_POKE_TOY 没有单独道具说明,跳过 +❌ ITEM_BIG_MUSHROOM 没有单独道具说明,跳过 +❌ ITEM_BALM_MUSHROOM 没有单独道具说明,跳过 +❌ ITEM_RED_SHARD 没有单独道具说明,跳过 +❌ ITEM_BLUE_SHARD 没有单独道具说明,跳过 +❌ ITEM_YELLOW_SHARD 没有单独道具说明,跳过 +❌ ITEM_GREEN_SHARD 没有单独道具说明,跳过 +❌ ITEM_ROOT_FOSSIL 没有单独道具说明,跳过 +❌ ITEM_CLAW_FOSSIL 没有单独道具说明,跳过 +❌ ITEM_FOSSILIZED_FISH 没有单独道具说明,跳过 +❌ ITEM_FOSSILIZED_DINO 没有单独道具说明,跳过 +❌ ITEM_BEAD_MAIL 没有单独道具说明,跳过 +❌ ITEM_DREAM_MAIL 没有单独道具说明,跳过 +❌ ITEM_FIRE_STONE 没有单独道具说明,跳过 +❌ ITEM_WATER_STONE 没有单独道具说明,跳过 +❌ ITEM_THUNDER_STONE 没有单独道具说明,跳过 +❌ ITEM_LEAF_STONE 没有单独道具说明,跳过 +❌ ITEM_ICE_STONE 没有单独道具说明,跳过 +❌ ITEM_SUN_STONE 没有单独道具说明,跳过 +❌ ITEM_MOON_STONE 没有单独道具说明,跳过 +❌ ITEM_SHINY_STONE 没有单独道具说明,跳过 +❌ ITEM_DUSK_STONE 没有单独道具说明,跳过 +❌ ITEM_DAWN_STONE 没有单独道具说明,跳过 +❌ ITEM_RED_NECTAR 没有单独道具说明,跳过 +❌ ITEM_YELLOW_NECTAR 没有单独道具说明,跳过 +❌ ITEM_PINK_NECTAR 没有单独道具说明,跳过 +❌ ITEM_PURPLE_NECTAR 没有单独道具说明,跳过 +❌ ITEM_CHARIZARDITE_X 没有单独道具说明,跳过 +❌ ITEM_CHARIZARDITE_Y 没有单独道具说明,跳过 +❌ ITEM_MEWTWONITE_X 没有单独道具说明,跳过 +❌ ITEM_MEWTWONITE_Y 没有单独道具说明,跳过 +❌ ITEM_SEA_INCENSE 没有单独道具说明,跳过 +❌ ITEM_ODD_INCENSE 没有单独道具说明,跳过 +❌ ITEM_ROCK_INCENSE 没有单独道具说明,跳过 +❌ ITEM_FULL_INCENSE 没有单独道具说明,跳过 +❌ ITEM_WAVE_INCENSE 没有单独道具说明,跳过 +❌ ITEM_ROSE_INCENSE 没有单独道具说明,跳过 +❌ ITEM_LUCK_INCENSE 没有单独道具说明,跳过 +❌ ITEM_PURE_INCENSE 没有单独道具说明,跳过 +❌ ITEM_MIRACLE_SEED 没有单独道具说明,跳过 +❌ ITEM_TWISTED_SPOON 没有单独道具说明,跳过 +❌ ITEM_HARD_STONE 没有单独道具说明,跳过 +❌ ITEM_KINGS_ROCK 没有单独道具说明,跳过 +❌ ITEM_AMULET_COIN 没有单独道具说明,跳过 +❌ ITEM_CLEANSE_TAG 没有单独道具说明,跳过 +❌ ITEM_LAGGING_TAIL 没有单独道具说明,跳过 +❌ ITEM_RAZOR_FANG 没有单独道具说明,跳过 +❌ ITEM_FIGY_BERRY 没有单独道具说明,跳过 +❌ ITEM_WIKI_BERRY 没有单独道具说明,跳过 +❌ ITEM_MAGO_BERRY 没有单独道具说明,跳过 +❌ ITEM_AGUAV_BERRY 没有单独道具说明,跳过 +❌ ITEM_IAPAPA_BERRY 没有单独道具说明,跳过 +❌ ITEM_TM51 没有单独道具说明,跳过 +❌ ITEM_TM52 没有单独道具说明,跳过 +❌ ITEM_TM53 没有单独道具说明,跳过 +❌ ITEM_TM54 没有单独道具说明,跳过 +❌ ITEM_TM55 没有单独道具说明,跳过 +❌ ITEM_TM56 没有单独道具说明,跳过 +❌ ITEM_TM57 没有单独道具说明,跳过 +❌ ITEM_TM58 没有单独道具说明,跳过 +❌ ITEM_TM59 没有单独道具说明,跳过 +❌ ITEM_TM60 没有单独道具说明,跳过 +❌ ITEM_TM61 没有单独道具说明,跳过 +❌ ITEM_TM62 没有单独道具说明,跳过 +❌ ITEM_TM63 没有单独道具说明,跳过 +❌ ITEM_TM64 没有单独道具说明,跳过 +❌ ITEM_TM65 没有单独道具说明,跳过 +❌ ITEM_TM66 没有单独道具说明,跳过 +❌ ITEM_TM67 没有单独道具说明,跳过 +❌ ITEM_TM68 没有单独道具说明,跳过 +❌ ITEM_TM69 没有单独道具说明,跳过 +❌ ITEM_TM70 没有单独道具说明,跳过 +❌ ITEM_TM71 没有单独道具说明,跳过 +❌ ITEM_TM72 没有单独道具说明,跳过 +❌ ITEM_TM73 没有单独道具说明,跳过 +❌ ITEM_TM74 没有单独道具说明,跳过 +❌ ITEM_TM75 没有单独道具说明,跳过 +❌ ITEM_TM76 没有单独道具说明,跳过 +❌ ITEM_TM77 没有单独道具说明,跳过 +❌ ITEM_TM78 没有单独道具说明,跳过 +❌ ITEM_TM79 没有单独道具说明,跳过 +❌ ITEM_TM80 没有单独道具说明,跳过 +❌ ITEM_TM81 没有单独道具说明,跳过 +❌ ITEM_TM82 没有单独道具说明,跳过 +❌ ITEM_TM83 没有单独道具说明,跳过 +❌ ITEM_TM84 没有单独道具说明,跳过 +❌ ITEM_TM85 没有单独道具说明,跳过 +❌ ITEM_TM86 没有单独道具说明,跳过 +❌ ITEM_TM87 没有单独道具说明,跳过 +❌ ITEM_TM88 没有单独道具说明,跳过 +❌ ITEM_TM89 没有单独道具说明,跳过 +❌ ITEM_TM90 没有单独道具说明,跳过 +❌ ITEM_TM91 没有单独道具说明,跳过 +❌ ITEM_TM92 没有单独道具说明,跳过 +❌ ITEM_TM93 没有单独道具说明,跳过 +❌ ITEM_TM94 没有单独道具说明,跳过 +❌ ITEM_TM95 没有单独道具说明,跳过 +❌ ITEM_TM96 没有单独道具说明,跳过 +❌ ITEM_TM97 没有单独道具说明,跳过 +❌ ITEM_TM98 没有单独道具说明,跳过 +❌ ITEM_TM99 没有单独道具说明,跳过 +❌ ITEM_TM100 没有单独道具说明,跳过 +❌ ITEM_KEY_TO_ROOM_1 没有单独道具说明,跳过 +❌ ITEM_KEY_TO_ROOM_2 没有单独道具说明,跳过 +❌ ITEM_KEY_TO_ROOM_4 没有单独道具说明,跳过 +❌ ITEM_KEY_TO_ROOM_6 没有单独道具说明,跳过 +❌ ITEM_BUG_TERA_SHARD 没有单独道具说明,跳过 +❌ ITEM_DARK_TERA_SHARD 没有单独道具说明,跳过 +❌ ITEM_DRAGON_TERA_SHARD 没有单独道具说明,跳过 +❌ ITEM_ELECTRIC_TERA_SHARD 没有单独道具说明,跳过 +❌ ITEM_FAIRY_TERA_SHARD 没有单独道具说明,跳过 +❌ ITEM_FIGHTING_TERA_SHARD 没有单独道具说明,跳过 +❌ ITEM_FIRE_TERA_SHARD 没有单独道具说明,跳过 +❌ ITEM_FLYING_TERA_SHARD 没有单独道具说明,跳过 +❌ ITEM_GHOST_TERA_SHARD 没有单独道具说明,跳过 +❌ ITEM_GRASS_TERA_SHARD 没有单独道具说明,跳过 +❌ ITEM_GROUND_TERA_SHARD 没有单独道具说明,跳过 +❌ ITEM_ICE_TERA_SHARD 没有单独道具说明,跳过 +❌ ITEM_NORMAL_TERA_SHARD 没有单独道具说明,跳过 +❌ ITEM_POISON_TERA_SHARD 没有单独道具说明,跳过 +❌ ITEM_PSYCHIC_TERA_SHARD 没有单独道具说明,跳过 +❌ ITEM_ROCK_TERA_SHARD 没有单独道具说明,跳过 +❌ ITEM_STEEL_TERA_SHARD 没有单独道具说明,跳过 +❌ ITEM_WATER_TERA_SHARD 没有单独道具说明,跳过 +❌ ITEM_HEALTH_MOCHI 没有单独道具说明,跳过 +❌ ITEM_MUSCLE_MOCHI 没有单独道具说明,跳过 +❌ ITEM_RESIST_MOCHI 没有单独道具说明,跳过 +❌ ITEM_GENIUS_MOCHI 没有单独道具说明,跳过 +❌ ITEM_CLEVER_MOCHI 没有单独道具说明,跳过 +❌ ITEM_SWIFT_MOCHI 没有单独道具说明,跳过 +❌ ITEM_STELLAR_TERA_SHARD 没有单独道具说明,跳过 +❌ ITEM_JUBILIFE_MUFFIN 没有单独道具说明,跳过 +❌ ITEM_SWAP_SNACK 没有单独道具说明,跳过 +❌ ITEM_TWICE_SPICED_RADISH 没有单独道具说明,跳过 +❌ ITEM_MAX_REVIVE 没有单独道具说明,跳过 +❌ ITEM_FULL_HEAL 没有单独道具说明,跳过 +❌ ITEM_MAX_HONEY 没有单独道具说明,跳过 +❌ ITEM_PEWTER_CRUNCHIES 没有单独道具说明,跳过 +❌ ITEM_RAGE_CANDY_BAR 没有单独道具说明,跳过 +❌ ITEM_OLD_GATEAU 没有单独道具说明,跳过 +❌ ITEM_CASTELIACONE 没有单独道具说明,跳过 +❌ ITEM_LUMIOSE_GALETTE 没有单独道具说明,跳过 +❌ ITEM_SHALOUR_SABLE 没有单独道具说明,跳过 +❌ ITEM_BIG_MALASADA 没有单独道具说明,跳过 +❌ ITEM_HEALTH_FEATHER 没有单独道具说明,跳过 +❌ ITEM_MUSCLE_FEATHER 没有单独道具说明,跳过 +❌ ITEM_RESIST_FEATHER 没有单独道具说明,跳过 +❌ ITEM_GENIUS_FEATHER 没有单独道具说明,跳过 +❌ ITEM_CLEVER_FEATHER 没有单独道具说明,跳过 +❌ ITEM_SWIFT_FEATHER 没有单独道具说明,跳过 +❌ ITEM_POKE_DOLL 没有单独道具说明,跳过 +❌ ITEM_FLUFFY_TAIL 没有单独道具说明,跳过 +❌ ITEM_POKE_TOY 没有单独道具说明,跳过 +❌ ITEM_BIG_MUSHROOM 没有单独道具说明,跳过 +❌ ITEM_BALM_MUSHROOM 没有单独道具说明,跳过 +❌ ITEM_RED_SHARD 没有单独道具说明,跳过 +❌ ITEM_BLUE_SHARD 没有单独道具说明,跳过 +❌ ITEM_YELLOW_SHARD 没有单独道具说明,跳过 +❌ ITEM_GREEN_SHARD 没有单独道具说明,跳过 +❌ ITEM_ROOT_FOSSIL 没有单独道具说明,跳过 +❌ ITEM_CLAW_FOSSIL 没有单独道具说明,跳过 +❌ ITEM_FOSSILIZED_FISH 没有单独道具说明,跳过 +❌ ITEM_FOSSILIZED_DINO 没有单独道具说明,跳过 +❌ ITEM_BEAD_MAIL 没有单独道具说明,跳过 +❌ ITEM_DREAM_MAIL 没有单独道具说明,跳过 +❌ ITEM_FIRE_STONE 没有单独道具说明,跳过 +❌ ITEM_WATER_STONE 没有单独道具说明,跳过 +❌ ITEM_THUNDER_STONE 没有单独道具说明,跳过 +❌ ITEM_LEAF_STONE 没有单独道具说明,跳过 +❌ ITEM_ICE_STONE 没有单独道具说明,跳过 +❌ ITEM_SUN_STONE 没有单独道具说明,跳过 +❌ ITEM_MOON_STONE 没有单独道具说明,跳过 +❌ ITEM_SHINY_STONE 没有单独道具说明,跳过 +❌ ITEM_DUSK_STONE 没有单独道具说明,跳过 +❌ ITEM_DAWN_STONE 没有单独道具说明,跳过 +❌ ITEM_RED_NECTAR 没有单独道具说明,跳过 +❌ ITEM_YELLOW_NECTAR 没有单独道具说明,跳过 +❌ ITEM_PINK_NECTAR 没有单独道具说明,跳过 +❌ ITEM_PURPLE_NECTAR 没有单独道具说明,跳过 +❌ ITEM_CHARIZARDITE_X 没有单独道具说明,跳过 +❌ ITEM_CHARIZARDITE_Y 没有单独道具说明,跳过 +❌ ITEM_MEWTWONITE_X 没有单独道具说明,跳过 +❌ ITEM_MEWTWONITE_Y 没有单独道具说明,跳过 +❌ ITEM_SEA_INCENSE 没有单独道具说明,跳过 +❌ ITEM_ODD_INCENSE 没有单独道具说明,跳过 +❌ ITEM_ROCK_INCENSE 没有单独道具说明,跳过 +❌ ITEM_FULL_INCENSE 没有单独道具说明,跳过 +❌ ITEM_WAVE_INCENSE 没有单独道具说明,跳过 +❌ ITEM_ROSE_INCENSE 没有单独道具说明,跳过 +❌ ITEM_LUCK_INCENSE 没有单独道具说明,跳过 +❌ ITEM_PURE_INCENSE 没有单独道具说明,跳过 +❌ ITEM_MIRACLE_SEED 没有单独道具说明,跳过 +❌ ITEM_TWISTED_SPOON 没有单独道具说明,跳过 +❌ ITEM_HARD_STONE 没有单独道具说明,跳过 +❌ ITEM_KINGS_ROCK 没有单独道具说明,跳过 +❌ ITEM_AMULET_COIN 没有单独道具说明,跳过 +❌ ITEM_CLEANSE_TAG 没有单独道具说明,跳过 +❌ ITEM_LAGGING_TAIL 没有单独道具说明,跳过 +❌ ITEM_RAZOR_FANG 没有单独道具说明,跳过 +❌ ITEM_FIGY_BERRY 没有单独道具说明,跳过 +❌ ITEM_WIKI_BERRY 没有单独道具说明,跳过 +❌ ITEM_MAGO_BERRY 没有单独道具说明,跳过 +❌ ITEM_AGUAV_BERRY 没有单独道具说明,跳过 +❌ ITEM_IAPAPA_BERRY 没有单独道具说明,跳过 +❌ ITEM_TM51 没有单独道具说明,跳过 +❌ ITEM_TM52 没有单独道具说明,跳过 +❌ ITEM_TM53 没有单独道具说明,跳过 +❌ ITEM_TM54 没有单独道具说明,跳过 +❌ ITEM_TM55 没有单独道具说明,跳过 +❌ ITEM_TM56 没有单独道具说明,跳过 +❌ ITEM_TM57 没有单独道具说明,跳过 +❌ ITEM_TM58 没有单独道具说明,跳过 +❌ ITEM_TM59 没有单独道具说明,跳过 +❌ ITEM_TM60 没有单独道具说明,跳过 +❌ ITEM_TM61 没有单独道具说明,跳过 +❌ ITEM_TM62 没有单独道具说明,跳过 +❌ ITEM_TM63 没有单独道具说明,跳过 +❌ ITEM_TM64 没有单独道具说明,跳过 +❌ ITEM_TM65 没有单独道具说明,跳过 +❌ ITEM_TM66 没有单独道具说明,跳过 +❌ ITEM_TM67 没有单独道具说明,跳过 +❌ ITEM_TM68 没有单独道具说明,跳过 +❌ ITEM_TM69 没有单独道具说明,跳过 +❌ ITEM_TM70 没有单独道具说明,跳过 +❌ ITEM_TM71 没有单独道具说明,跳过 +❌ ITEM_TM72 没有单独道具说明,跳过 +❌ ITEM_TM73 没有单独道具说明,跳过 +❌ ITEM_TM74 没有单独道具说明,跳过 +❌ ITEM_TM75 没有单独道具说明,跳过 +❌ ITEM_TM76 没有单独道具说明,跳过 +❌ ITEM_TM77 没有单独道具说明,跳过 +❌ ITEM_TM78 没有单独道具说明,跳过 +❌ ITEM_TM79 没有单独道具说明,跳过 +❌ ITEM_TM80 没有单独道具说明,跳过 +❌ ITEM_TM81 没有单独道具说明,跳过 +❌ ITEM_TM82 没有单独道具说明,跳过 +❌ ITEM_TM83 没有单独道具说明,跳过 +❌ ITEM_TM84 没有单独道具说明,跳过 +❌ ITEM_TM85 没有单独道具说明,跳过 +❌ ITEM_TM86 没有单独道具说明,跳过 +❌ ITEM_TM87 没有单独道具说明,跳过 +❌ ITEM_TM88 没有单独道具说明,跳过 +❌ ITEM_TM89 没有单独道具说明,跳过 +❌ ITEM_TM90 没有单独道具说明,跳过 +❌ ITEM_TM91 没有单独道具说明,跳过 +❌ ITEM_TM92 没有单独道具说明,跳过 +❌ ITEM_TM93 没有单独道具说明,跳过 +❌ ITEM_TM94 没有单独道具说明,跳过 +❌ ITEM_TM95 没有单独道具说明,跳过 +❌ ITEM_TM96 没有单独道具说明,跳过 +❌ ITEM_TM97 没有单独道具说明,跳过 +❌ ITEM_TM98 没有单独道具说明,跳过 +❌ ITEM_TM99 没有单独道具说明,跳过 +❌ ITEM_TM100 没有单独道具说明,跳过 +❌ ITEM_KEY_TO_ROOM_1 没有单独道具说明,跳过 +❌ ITEM_KEY_TO_ROOM_2 没有单独道具说明,跳过 +❌ ITEM_KEY_TO_ROOM_4 没有单独道具说明,跳过 +❌ ITEM_KEY_TO_ROOM_6 没有单独道具说明,跳过 +❌ ITEM_BUG_TERA_SHARD 没有单独道具说明,跳过 +❌ ITEM_DARK_TERA_SHARD 没有单独道具说明,跳过 +❌ ITEM_DRAGON_TERA_SHARD 没有单独道具说明,跳过 +❌ ITEM_ELECTRIC_TERA_SHARD 没有单独道具说明,跳过 +❌ ITEM_FAIRY_TERA_SHARD 没有单独道具说明,跳过 +❌ ITEM_FIGHTING_TERA_SHARD 没有单独道具说明,跳过 +❌ ITEM_FIRE_TERA_SHARD 没有单独道具说明,跳过 +❌ ITEM_FLYING_TERA_SHARD 没有单独道具说明,跳过 +❌ ITEM_GHOST_TERA_SHARD 没有单独道具说明,跳过 +❌ ITEM_GRASS_TERA_SHARD 没有单独道具说明,跳过 +❌ ITEM_GROUND_TERA_SHARD 没有单独道具说明,跳过 +❌ ITEM_ICE_TERA_SHARD 没有单独道具说明,跳过 +❌ ITEM_NORMAL_TERA_SHARD 没有单独道具说明,跳过 +❌ ITEM_POISON_TERA_SHARD 没有单独道具说明,跳过 +❌ ITEM_PSYCHIC_TERA_SHARD 没有单独道具说明,跳过 +❌ ITEM_ROCK_TERA_SHARD 没有单独道具说明,跳过 +❌ ITEM_STEEL_TERA_SHARD 没有单独道具说明,跳过 +❌ ITEM_WATER_TERA_SHARD 没有单独道具说明,跳过 +❌ ITEM_HEALTH_MOCHI 没有单独道具说明,跳过 +❌ ITEM_MUSCLE_MOCHI 没有单独道具说明,跳过 +❌ ITEM_RESIST_MOCHI 没有单独道具说明,跳过 +❌ ITEM_GENIUS_MOCHI 没有单独道具说明,跳过 +❌ ITEM_CLEVER_MOCHI 没有单独道具说明,跳过 +❌ ITEM_SWIFT_MOCHI 没有单独道具说明,跳过 +❌ ITEM_STELLAR_TERA_SHARD 没有单独道具说明,跳过 +❌ ITEM_JUBILIFE_MUFFIN 没有单独道具说明,跳过 +❌ ITEM_SWAP_SNACK 没有单独道具说明,跳过 +❌ ITEM_TWICE_SPICED_RADISH 没有单独道具说明,跳过 +✅ 处理文件:c:\Users\Nox\Documents\GitHub\pokeemerald-expansion-Chinese\src\data\pokemon\species_info\gen_1_families.h +✅ 处理文件:c:\Users\Nox\Documents\GitHub\pokeemerald-expansion-Chinese\src\data\pokemon\species_info\gen_1_families.h +❌ 未找到 SPECIES_CLEFABLE_MEGA,跳过 +❌ 未找到 SPECIES_VICTREEBEL_MEGA,跳过 +❌ 未找到 SPECIES_STARMIE_MEGA,跳过 +❌ 未找到 SPECIES_DRAGONITE_MEGA,跳过 +✅ 处理文件:c:\Users\Nox\Documents\GitHub\pokeemerald-expansion-Chinese\src\data\pokemon\species_info\gen_2_families.h +❌ 未找到 SPECIES_MEGANIUM_MEGA,跳过 +❌ 未找到 SPECIES_FERALIGATR_MEGA,跳过 +❌ 未找到 SPECIES_SKARMORY_MEGA,跳过 +✅ 处理文件:c:\Users\Nox\Documents\GitHub\pokeemerald-expansion-Chinese\src\data\pokemon\species_info\gen_3_families.h +❌ 未找到 SPECIES_FROSLASS_MEGA,跳过 +✅ 处理文件:c:\Users\Nox\Documents\GitHub\pokeemerald-expansion-Chinese\src\data\pokemon\species_info\gen_4_families.h +✅ 处理文件:c:\Users\Nox\Documents\GitHub\pokeemerald-expansion-Chinese\src\data\pokemon\species_info\gen_5_families.h +❌ 未找到 SPECIES_EMBOAR_MEGA,跳过 +❌ 未找到 SPECIES_EXCADRILL_MEGA,跳过 +❌ 未找到 SPECIES_SCOLIPEDE_MEGA,跳过 +❌ 未找到 SPECIES_SCRAFTY_MEGA,跳过 +❌ 未找到 SPECIES_EELEKTROSS_MEGA,跳过 +❌ 未找到 SPECIES_CHANDELURE_MEGA,跳过 +✅ 处理文件:c:\Users\Nox\Documents\GitHub\pokeemerald-expansion-Chinese\src\data\pokemon\species_info\gen_6_families.h +❌ 未找到 SPECIES_CHESNAUGHT_MEGA,跳过 +❌ 未找到 SPECIES_DELPHOX_MEGA,跳过 +❌ 未找到 SPECIES_GRENINJA_MEGA,跳过 +❌ 未找到 SPECIES_PYROAR_MEGA,跳过 +❌ 未找到 SPECIES_FLOETTE_MEGA,跳过 +❌ 未找到 SPECIES_MALAMAR_MEGA,跳过 +❌ 未找到 SPECIES_BARBARACLE_MEGA,跳过 +❌ 未找到 SPECIES_DRAGALGE_MEGA,跳过 +❌ 未找到 SPECIES_HAWLUCHA_MEGA,跳过 +❌ 未找到 SPECIES_ZYGARDE_10_AURA_BREAK,跳过 +❌ 未找到 SPECIES_ZYGARDE_MEGA,跳过 +✅ 处理文件:c:\Users\Nox\Documents\GitHub\pokeemerald-expansion-Chinese\src\data\pokemon\species_info\gen_7_families.h +❌ 未找到 SPECIES_MIMIKYU_BUSTED_TOTEM,跳过 +❌ 未找到 SPECIES_DRAMPA_MEGA,跳过 +✅ 处理文件:c:\Users\Nox\Documents\GitHub\pokeemerald-expansion-Chinese\src\data\pokemon\species_info\gen_8_families.h +❌ 未找到 SPECIES_FALINKS_MEGA,跳过 +✅ 处理文件:c:\Users\Nox\Documents\GitHub\pokeemerald-expansion-Chinese\src\data\pokemon\species_info\gen_9_families.h +❌ 未找到 SPECIES_CAPSAKID,跳过 +✅ 处理文件:c:\Users\Nox\Documents\GitHub\pokeemerald-expansion-Chinese\src\data\pokemon\species_info\gen_1_families.h +❌ 未找到 SPECIES_VICTREEBEL_MEGA,跳过 +❌ 未找到 SPECIES_STARMIE_MEGA,跳过 +❌ 未找到 SPECIES_DRAGONITE_MEGA,跳过 +✅ 处理文件:c:\Users\Nox\Documents\GitHub\pokeemerald-expansion-Chinese\src\data\pokemon\species_info\gen_2_families.h +❌ 未找到 SPECIES_MEGANIUM_MEGA,跳过 +❌ 未找到 SPECIES_FERALIGATR_MEGA,跳过 +❌ 未找到 SPECIES_SKARMORY_MEGA,跳过 +✅ 处理文件:c:\Users\Nox\Documents\GitHub\pokeemerald-expansion-Chinese\src\data\pokemon\species_info\gen_3_families.h +❌ 未找到 SPECIES_FROSLASS_MEGA,跳过 +✅ 处理文件:c:\Users\Nox\Documents\GitHub\pokeemerald-expansion-Chinese\src\data\pokemon\species_info\gen_4_families.h +✅ 处理文件:c:\Users\Nox\Documents\GitHub\pokeemerald-expansion-Chinese\src\data\pokemon\species_info\gen_5_families.h +❌ 未找到 SPECIES_EMBOAR_MEGA,跳过 +❌ 未找到 SPECIES_EXCADRILL_MEGA,跳过 +❌ 未找到 SPECIES_SCOLIPEDE_MEGA,跳过 +❌ 未找到 SPECIES_SCRAFTY_MEGA,跳过 +❌ 未找到 SPECIES_EELEKTROSS_MEGA,跳过 +❌ 未找到 SPECIES_CHANDELURE_MEGA,跳过 +✅ 处理文件:c:\Users\Nox\Documents\GitHub\pokeemerald-expansion-Chinese\src\data\pokemon\species_info\gen_6_families.h +❌ 未找到 SPECIES_CHESNAUGHT_MEGA,跳过 +❌ 未找到 SPECIES_DELPHOX_MEGA,跳过 +❌ 未找到 SPECIES_GRENINJA_MEGA,跳过 +❌ 未找到 SPECIES_PYROAR_MEGA,跳过 +❌ 未找到 SPECIES_FLOETTE_MEGA,跳过 +❌ 未找到 SPECIES_MALAMAR_MEGA,跳过 +❌ 未找到 SPECIES_BARBARACLE_MEGA,跳过 +❌ 未找到 SPECIES_DRAGALGE_MEGA,跳过 +❌ 未找到 SPECIES_HAWLUCHA_MEGA,跳过 +❌ 未找到 SPECIES_ZYGARDE_10_AURA_BREAK,跳过 +❌ 未找到 SPECIES_ZYGARDE_MEGA,跳过 +✅ 处理文件:c:\Users\Nox\Documents\GitHub\pokeemerald-expansion-Chinese\src\data\pokemon\species_info\gen_7_families.h +❌ 未找到 SPECIES_MIMIKYU_BUSTED_TOTEM,跳过 +❌ 未找到 SPECIES_DRAMPA_MEGA,跳过 +✅ 处理文件:c:\Users\Nox\Documents\GitHub\pokeemerald-expansion-Chinese\src\data\pokemon\species_info\gen_8_families.h +❌ 未找到 SPECIES_FALINKS_MEGA,跳过 +✅ 处理文件:c:\Users\Nox\Documents\GitHub\pokeemerald-expansion-Chinese\src\data\pokemon\species_info\gen_9_families.h +❌ 未找到 SPECIES_CAPSAKID,跳过 +❌ ITEM_MAX_REVIVE 没有单独道具说明,跳过 +❌ ITEM_FULL_HEAL 没有单独道具说明,跳过 +❌ ITEM_MAX_HONEY 没有单独道具说明,跳过 +❌ ITEM_PEWTER_CRUNCHIES 没有单独道具说明,跳过 +❌ ITEM_RAGE_CANDY_BAR 没有单独道具说明,跳过 +❌ ITEM_OLD_GATEAU 没有单独道具说明,跳过 +❌ ITEM_CASTELIACONE 没有单独道具说明,跳过 +❌ ITEM_LUMIOSE_GALETTE 没有单独道具说明,跳过 +❌ ITEM_SHALOUR_SABLE 没有单独道具说明,跳过 +❌ ITEM_BIG_MALASADA 没有单独道具说明,跳过 +❌ ITEM_HEALTH_FEATHER 没有单独道具说明,跳过 +❌ ITEM_MUSCLE_FEATHER 没有单独道具说明,跳过 +❌ ITEM_RESIST_FEATHER 没有单独道具说明,跳过 +❌ ITEM_GENIUS_FEATHER 没有单独道具说明,跳过 +❌ ITEM_CLEVER_FEATHER 没有单独道具说明,跳过 +❌ ITEM_SWIFT_FEATHER 没有单独道具说明,跳过 +❌ ITEM_POKE_DOLL 没有单独道具说明,跳过 +❌ ITEM_FLUFFY_TAIL 没有单独道具说明,跳过 +❌ ITEM_POKE_TOY 没有单独道具说明,跳过 +❌ ITEM_BIG_MUSHROOM 没有单独道具说明,跳过 +❌ ITEM_BALM_MUSHROOM 没有单独道具说明,跳过 +❌ ITEM_RED_SHARD 没有单独道具说明,跳过 +❌ ITEM_BLUE_SHARD 没有单独道具说明,跳过 +❌ ITEM_YELLOW_SHARD 没有单独道具说明,跳过 +❌ ITEM_GREEN_SHARD 没有单独道具说明,跳过 +❌ ITEM_ROOT_FOSSIL 没有单独道具说明,跳过 +❌ ITEM_CLAW_FOSSIL 没有单独道具说明,跳过 +❌ ITEM_FOSSILIZED_FISH 没有单独道具说明,跳过 +❌ ITEM_FOSSILIZED_DINO 没有单独道具说明,跳过 +❌ ITEM_BEAD_MAIL 没有单独道具说明,跳过 +❌ ITEM_DREAM_MAIL 没有单独道具说明,跳过 +❌ ITEM_FIRE_STONE 没有单独道具说明,跳过 +❌ ITEM_WATER_STONE 没有单独道具说明,跳过 +❌ ITEM_THUNDER_STONE 没有单独道具说明,跳过 +❌ ITEM_LEAF_STONE 没有单独道具说明,跳过 +❌ ITEM_ICE_STONE 没有单独道具说明,跳过 +❌ ITEM_SUN_STONE 没有单独道具说明,跳过 +❌ ITEM_MOON_STONE 没有单独道具说明,跳过 +❌ ITEM_SHINY_STONE 没有单独道具说明,跳过 +❌ ITEM_DUSK_STONE 没有单独道具说明,跳过 +❌ ITEM_DAWN_STONE 没有单独道具说明,跳过 +❌ ITEM_RED_NECTAR 没有单独道具说明,跳过 +❌ ITEM_YELLOW_NECTAR 没有单独道具说明,跳过 +❌ ITEM_PINK_NECTAR 没有单独道具说明,跳过 +❌ ITEM_PURPLE_NECTAR 没有单独道具说明,跳过 +❌ ITEM_CHARIZARDITE_X 没有单独道具说明,跳过 +❌ ITEM_CHARIZARDITE_Y 没有单独道具说明,跳过 +❌ ITEM_MEWTWONITE_X 没有单独道具说明,跳过 +❌ ITEM_MEWTWONITE_Y 没有单独道具说明,跳过 +❌ ITEM_SEA_INCENSE 没有单独道具说明,跳过 +❌ ITEM_ODD_INCENSE 没有单独道具说明,跳过 +❌ ITEM_ROCK_INCENSE 没有单独道具说明,跳过 +❌ ITEM_FULL_INCENSE 没有单独道具说明,跳过 +❌ ITEM_WAVE_INCENSE 没有单独道具说明,跳过 +❌ ITEM_ROSE_INCENSE 没有单独道具说明,跳过 +❌ ITEM_LUCK_INCENSE 没有单独道具说明,跳过 +❌ ITEM_PURE_INCENSE 没有单独道具说明,跳过 +❌ ITEM_MIRACLE_SEED 没有单独道具说明,跳过 +❌ ITEM_TWISTED_SPOON 没有单独道具说明,跳过 +❌ ITEM_HARD_STONE 没有单独道具说明,跳过 +❌ ITEM_KINGS_ROCK 没有单独道具说明,跳过 +❌ ITEM_AMULET_COIN 没有单独道具说明,跳过 +❌ ITEM_CLEANSE_TAG 没有单独道具说明,跳过 +❌ ITEM_LAGGING_TAIL 没有单独道具说明,跳过 +❌ ITEM_RAZOR_FANG 没有单独道具说明,跳过 +❌ ITEM_FIGY_BERRY 没有单独道具说明,跳过 +❌ ITEM_WIKI_BERRY 没有单独道具说明,跳过 +❌ ITEM_MAGO_BERRY 没有单独道具说明,跳过 +❌ ITEM_AGUAV_BERRY 没有单独道具说明,跳过 +❌ ITEM_IAPAPA_BERRY 没有单独道具说明,跳过 +❌ ITEM_TM51 没有单独道具说明,跳过 +❌ ITEM_TM52 没有单独道具说明,跳过 +❌ ITEM_TM53 没有单独道具说明,跳过 +❌ ITEM_TM54 没有单独道具说明,跳过 +❌ ITEM_TM55 没有单独道具说明,跳过 +❌ ITEM_TM56 没有单独道具说明,跳过 +❌ ITEM_TM57 没有单独道具说明,跳过 +❌ ITEM_TM58 没有单独道具说明,跳过 +❌ ITEM_TM59 没有单独道具说明,跳过 +❌ ITEM_TM60 没有单独道具说明,跳过 +❌ ITEM_TM61 没有单独道具说明,跳过 +❌ ITEM_TM62 没有单独道具说明,跳过 +❌ ITEM_TM63 没有单独道具说明,跳过 +❌ ITEM_TM64 没有单独道具说明,跳过 +❌ ITEM_TM65 没有单独道具说明,跳过 +❌ ITEM_TM66 没有单独道具说明,跳过 +❌ ITEM_TM67 没有单独道具说明,跳过 +❌ ITEM_TM68 没有单独道具说明,跳过 +❌ ITEM_TM69 没有单独道具说明,跳过 +❌ ITEM_TM70 没有单独道具说明,跳过 +❌ ITEM_TM71 没有单独道具说明,跳过 +❌ ITEM_TM72 没有单独道具说明,跳过 +❌ ITEM_TM73 没有单独道具说明,跳过 +❌ ITEM_TM74 没有单独道具说明,跳过 +❌ ITEM_TM75 没有单独道具说明,跳过 +❌ ITEM_TM76 没有单独道具说明,跳过 +❌ ITEM_TM77 没有单独道具说明,跳过 +❌ ITEM_TM78 没有单独道具说明,跳过 +❌ ITEM_TM79 没有单独道具说明,跳过 +❌ ITEM_TM80 没有单独道具说明,跳过 +❌ ITEM_TM81 没有单独道具说明,跳过 +❌ ITEM_TM82 没有单独道具说明,跳过 +❌ ITEM_TM83 没有单独道具说明,跳过 +❌ ITEM_TM84 没有单独道具说明,跳过 +❌ ITEM_TM85 没有单独道具说明,跳过 +❌ ITEM_TM86 没有单独道具说明,跳过 +❌ ITEM_TM87 没有单独道具说明,跳过 +❌ ITEM_TM88 没有单独道具说明,跳过 +❌ ITEM_TM89 没有单独道具说明,跳过 +❌ ITEM_TM90 没有单独道具说明,跳过 +❌ ITEM_TM91 没有单独道具说明,跳过 +❌ ITEM_TM92 没有单独道具说明,跳过 +❌ ITEM_TM93 没有单独道具说明,跳过 +❌ ITEM_TM94 没有单独道具说明,跳过 +❌ ITEM_TM95 没有单独道具说明,跳过 +❌ ITEM_TM96 没有单独道具说明,跳过 +❌ ITEM_TM97 没有单独道具说明,跳过 +❌ ITEM_TM98 没有单独道具说明,跳过 +❌ ITEM_TM99 没有单独道具说明,跳过 +❌ ITEM_TM100 没有单独道具说明,跳过 +❌ ITEM_KEY_TO_ROOM_1 没有单独道具说明,跳过 +❌ ITEM_KEY_TO_ROOM_2 没有单独道具说明,跳过 +❌ ITEM_KEY_TO_ROOM_4 没有单独道具说明,跳过 +❌ ITEM_KEY_TO_ROOM_6 没有单独道具说明,跳过 +❌ ITEM_BUG_TERA_SHARD 没有单独道具说明,跳过 +❌ ITEM_DARK_TERA_SHARD 没有单独道具说明,跳过 +❌ ITEM_DRAGON_TERA_SHARD 没有单独道具说明,跳过 +❌ ITEM_ELECTRIC_TERA_SHARD 没有单独道具说明,跳过 +❌ ITEM_FAIRY_TERA_SHARD 没有单独道具说明,跳过 +❌ ITEM_FIGHTING_TERA_SHARD 没有单独道具说明,跳过 +❌ ITEM_FIRE_TERA_SHARD 没有单独道具说明,跳过 +❌ ITEM_FLYING_TERA_SHARD 没有单独道具说明,跳过 +❌ ITEM_GHOST_TERA_SHARD 没有单独道具说明,跳过 +❌ ITEM_GRASS_TERA_SHARD 没有单独道具说明,跳过 +❌ ITEM_GROUND_TERA_SHARD 没有单独道具说明,跳过 +❌ ITEM_ICE_TERA_SHARD 没有单独道具说明,跳过 +❌ ITEM_NORMAL_TERA_SHARD 没有单独道具说明,跳过 +❌ ITEM_POISON_TERA_SHARD 没有单独道具说明,跳过 +❌ ITEM_PSYCHIC_TERA_SHARD 没有单独道具说明,跳过 +❌ ITEM_ROCK_TERA_SHARD 没有单独道具说明,跳过 +❌ ITEM_STEEL_TERA_SHARD 没有单独道具说明,跳过 +❌ ITEM_WATER_TERA_SHARD 没有单独道具说明,跳过 +❌ ITEM_HEALTH_MOCHI 没有单独道具说明,跳过 +❌ ITEM_MUSCLE_MOCHI 没有单独道具说明,跳过 +❌ ITEM_RESIST_MOCHI 没有单独道具说明,跳过 +❌ ITEM_GENIUS_MOCHI 没有单独道具说明,跳过 +❌ ITEM_CLEVER_MOCHI 没有单独道具说明,跳过 +❌ ITEM_SWIFT_MOCHI 没有单独道具说明,跳过 +❌ ITEM_STELLAR_TERA_SHARD 没有单独道具说明,跳过 +❌ ITEM_JUBILIFE_MUFFIN 没有单独道具说明,跳过 +❌ ITEM_SWAP_SNACK 没有单独道具说明,跳过 +❌ ITEM_TWICE_SPICED_RADISH 没有单独道具说明,跳过 +❌ ITEM_MAX_REVIVE 没有单独道具说明,跳过 +❌ ITEM_FULL_HEAL 没有单独道具说明,跳过 +❌ ITEM_MAX_HONEY 没有单独道具说明,跳过 +❌ ITEM_PEWTER_CRUNCHIES 没有单独道具说明,跳过 +❌ ITEM_RAGE_CANDY_BAR 没有单独道具说明,跳过 +❌ ITEM_OLD_GATEAU 没有单独道具说明,跳过 +❌ ITEM_CASTELIACONE 没有单独道具说明,跳过 +❌ ITEM_LUMIOSE_GALETTE 没有单独道具说明,跳过 +❌ ITEM_SHALOUR_SABLE 没有单独道具说明,跳过 +❌ ITEM_BIG_MALASADA 没有单独道具说明,跳过 +❌ ITEM_HEALTH_FEATHER 没有单独道具说明,跳过 +❌ ITEM_MUSCLE_FEATHER 没有单独道具说明,跳过 +❌ ITEM_RESIST_FEATHER 没有单独道具说明,跳过 +❌ ITEM_GENIUS_FEATHER 没有单独道具说明,跳过 +❌ ITEM_CLEVER_FEATHER 没有单独道具说明,跳过 +❌ ITEM_SWIFT_FEATHER 没有单独道具说明,跳过 +❌ ITEM_POKE_DOLL 没有单独道具说明,跳过 +❌ ITEM_FLUFFY_TAIL 没有单独道具说明,跳过 +❌ ITEM_POKE_TOY 没有单独道具说明,跳过 +❌ ITEM_BIG_MUSHROOM 没有单独道具说明,跳过 +❌ ITEM_BALM_MUSHROOM 没有单独道具说明,跳过 +❌ ITEM_RED_SHARD 没有单独道具说明,跳过 +❌ ITEM_BLUE_SHARD 没有单独道具说明,跳过 +❌ ITEM_YELLOW_SHARD 没有单独道具说明,跳过 +❌ ITEM_GREEN_SHARD 没有单独道具说明,跳过 +❌ ITEM_ROOT_FOSSIL 没有单独道具说明,跳过 +❌ ITEM_CLAW_FOSSIL 没有单独道具说明,跳过 +❌ ITEM_FOSSILIZED_FISH 没有单独道具说明,跳过 +❌ ITEM_FOSSILIZED_DINO 没有单独道具说明,跳过 +❌ ITEM_BEAD_MAIL 没有单独道具说明,跳过 +❌ ITEM_DREAM_MAIL 没有单独道具说明,跳过 +❌ ITEM_FIRE_STONE 没有单独道具说明,跳过 +❌ ITEM_WATER_STONE 没有单独道具说明,跳过 +❌ ITEM_THUNDER_STONE 没有单独道具说明,跳过 +❌ ITEM_LEAF_STONE 没有单独道具说明,跳过 +❌ ITEM_ICE_STONE 没有单独道具说明,跳过 +❌ ITEM_SUN_STONE 没有单独道具说明,跳过 +❌ ITEM_MOON_STONE 没有单独道具说明,跳过 +❌ ITEM_SHINY_STONE 没有单独道具说明,跳过 +❌ ITEM_DUSK_STONE 没有单独道具说明,跳过 +❌ ITEM_DAWN_STONE 没有单独道具说明,跳过 +❌ ITEM_RED_NECTAR 没有单独道具说明,跳过 +❌ ITEM_YELLOW_NECTAR 没有单独道具说明,跳过 +❌ ITEM_PINK_NECTAR 没有单独道具说明,跳过 +❌ ITEM_PURPLE_NECTAR 没有单独道具说明,跳过 +❌ ITEM_CHARIZARDITE_X 没有单独道具说明,跳过 +❌ ITEM_CHARIZARDITE_Y 没有单独道具说明,跳过 +❌ ITEM_MEWTWONITE_X 没有单独道具说明,跳过 +❌ ITEM_MEWTWONITE_Y 没有单独道具说明,跳过 +❌ ITEM_SEA_INCENSE 没有单独道具说明,跳过 +❌ ITEM_ODD_INCENSE 没有单独道具说明,跳过 +❌ ITEM_ROCK_INCENSE 没有单独道具说明,跳过 +❌ ITEM_FULL_INCENSE 没有单独道具说明,跳过 +❌ ITEM_WAVE_INCENSE 没有单独道具说明,跳过 +❌ ITEM_ROSE_INCENSE 没有单独道具说明,跳过 +❌ ITEM_LUCK_INCENSE 没有单独道具说明,跳过 +❌ ITEM_PURE_INCENSE 没有单独道具说明,跳过 +❌ ITEM_MIRACLE_SEED 没有单独道具说明,跳过 +❌ ITEM_TWISTED_SPOON 没有单独道具说明,跳过 +❌ ITEM_HARD_STONE 没有单独道具说明,跳过 +❌ ITEM_KINGS_ROCK 没有单独道具说明,跳过 +❌ ITEM_AMULET_COIN 没有单独道具说明,跳过 +❌ ITEM_CLEANSE_TAG 没有单独道具说明,跳过 +❌ ITEM_LAGGING_TAIL 没有单独道具说明,跳过 +❌ ITEM_RAZOR_FANG 没有单独道具说明,跳过 +❌ ITEM_FIGY_BERRY 没有单独道具说明,跳过 +❌ ITEM_WIKI_BERRY 没有单独道具说明,跳过 +❌ ITEM_MAGO_BERRY 没有单独道具说明,跳过 +❌ ITEM_AGUAV_BERRY 没有单独道具说明,跳过 +❌ ITEM_IAPAPA_BERRY 没有单独道具说明,跳过 +❌ ITEM_TM51 没有单独道具说明,跳过 +❌ ITEM_TM52 没有单独道具说明,跳过 +❌ ITEM_TM53 没有单独道具说明,跳过 +❌ ITEM_TM54 没有单独道具说明,跳过 +❌ ITEM_TM55 没有单独道具说明,跳过 +❌ ITEM_TM56 没有单独道具说明,跳过 +❌ ITEM_TM57 没有单独道具说明,跳过 +❌ ITEM_TM58 没有单独道具说明,跳过 +❌ ITEM_TM59 没有单独道具说明,跳过 +❌ ITEM_TM60 没有单独道具说明,跳过 +❌ ITEM_TM61 没有单独道具说明,跳过 +❌ ITEM_TM62 没有单独道具说明,跳过 +❌ ITEM_TM63 没有单独道具说明,跳过 +❌ ITEM_TM64 没有单独道具说明,跳过 +❌ ITEM_TM65 没有单独道具说明,跳过 +❌ ITEM_TM66 没有单独道具说明,跳过 +❌ ITEM_TM67 没有单独道具说明,跳过 +❌ ITEM_TM68 没有单独道具说明,跳过 +❌ ITEM_TM69 没有单独道具说明,跳过 +❌ ITEM_TM70 没有单独道具说明,跳过 +❌ ITEM_TM71 没有单独道具说明,跳过 +❌ ITEM_TM72 没有单独道具说明,跳过 +❌ ITEM_TM73 没有单独道具说明,跳过 +❌ ITEM_TM74 没有单独道具说明,跳过 +❌ ITEM_TM75 没有单独道具说明,跳过 +❌ ITEM_TM76 没有单独道具说明,跳过 +❌ ITEM_TM77 没有单独道具说明,跳过 +❌ ITEM_TM78 没有单独道具说明,跳过 +❌ ITEM_TM79 没有单独道具说明,跳过 +❌ ITEM_TM80 没有单独道具说明,跳过 +❌ ITEM_TM81 没有单独道具说明,跳过 +❌ ITEM_TM82 没有单独道具说明,跳过 +❌ ITEM_TM83 没有单独道具说明,跳过 +❌ ITEM_TM84 没有单独道具说明,跳过 +❌ ITEM_TM85 没有单独道具说明,跳过 +❌ ITEM_TM86 没有单独道具说明,跳过 +❌ ITEM_TM87 没有单独道具说明,跳过 +❌ ITEM_TM88 没有单独道具说明,跳过 +❌ ITEM_TM89 没有单独道具说明,跳过 +❌ ITEM_TM90 没有单独道具说明,跳过 +❌ ITEM_TM91 没有单独道具说明,跳过 +❌ ITEM_TM92 没有单独道具说明,跳过 +❌ ITEM_TM93 没有单独道具说明,跳过 +❌ ITEM_TM94 没有单独道具说明,跳过 +❌ ITEM_TM95 没有单独道具说明,跳过 +❌ ITEM_TM96 没有单独道具说明,跳过 +❌ ITEM_TM97 没有单独道具说明,跳过 +❌ ITEM_TM98 没有单独道具说明,跳过 +❌ ITEM_TM99 没有单独道具说明,跳过 +❌ ITEM_TM100 没有单独道具说明,跳过 +❌ ITEM_KEY_TO_ROOM_1 没有单独道具说明,跳过 +❌ ITEM_KEY_TO_ROOM_2 没有单独道具说明,跳过 +❌ ITEM_KEY_TO_ROOM_4 没有单独道具说明,跳过 +❌ ITEM_KEY_TO_ROOM_6 没有单独道具说明,跳过 +❌ ITEM_BUG_TERA_SHARD 没有单独道具说明,跳过 +❌ ITEM_DARK_TERA_SHARD 没有单独道具说明,跳过 +❌ ITEM_DRAGON_TERA_SHARD 没有单独道具说明,跳过 +❌ ITEM_ELECTRIC_TERA_SHARD 没有单独道具说明,跳过 +❌ ITEM_FAIRY_TERA_SHARD 没有单独道具说明,跳过 +❌ ITEM_FIGHTING_TERA_SHARD 没有单独道具说明,跳过 +❌ ITEM_FIRE_TERA_SHARD 没有单独道具说明,跳过 +❌ ITEM_FLYING_TERA_SHARD 没有单独道具说明,跳过 +❌ ITEM_GHOST_TERA_SHARD 没有单独道具说明,跳过 +❌ ITEM_GRASS_TERA_SHARD 没有单独道具说明,跳过 +❌ ITEM_GROUND_TERA_SHARD 没有单独道具说明,跳过 +❌ ITEM_ICE_TERA_SHARD 没有单独道具说明,跳过 +❌ ITEM_NORMAL_TERA_SHARD 没有单独道具说明,跳过 +❌ ITEM_POISON_TERA_SHARD 没有单独道具说明,跳过 +❌ ITEM_PSYCHIC_TERA_SHARD 没有单独道具说明,跳过 +❌ ITEM_ROCK_TERA_SHARD 没有单独道具说明,跳过 +❌ ITEM_STEEL_TERA_SHARD 没有单独道具说明,跳过 +❌ ITEM_WATER_TERA_SHARD 没有单独道具说明,跳过 +❌ ITEM_HEALTH_MOCHI 没有单独道具说明,跳过 +❌ ITEM_MUSCLE_MOCHI 没有单独道具说明,跳过 +❌ ITEM_RESIST_MOCHI 没有单独道具说明,跳过 +❌ ITEM_GENIUS_MOCHI 没有单独道具说明,跳过 +❌ ITEM_CLEVER_MOCHI 没有单独道具说明,跳过 +❌ ITEM_SWIFT_MOCHI 没有单独道具说明,跳过 +❌ ITEM_STELLAR_TERA_SHARD 没有单独道具说明,跳过 +❌ ITEM_JUBILIFE_MUFFIN 没有单独道具说明,跳过 +❌ ITEM_SWAP_SNACK 没有单独道具说明,跳过 +❌ ITEM_TWICE_SPICED_RADISH 没有单独道具说明,跳过 +❌ ITEM_MAX_REVIVE 没有单独道具说明,跳过 +❌ ITEM_FULL_HEAL 没有单独道具说明,跳过 +❌ ITEM_MAX_HONEY 没有单独道具说明,跳过 +❌ ITEM_PEWTER_CRUNCHIES 没有单独道具说明,跳过 +❌ ITEM_RAGE_CANDY_BAR 没有单独道具说明,跳过 +❌ ITEM_OLD_GATEAU 没有单独道具说明,跳过 +❌ ITEM_CASTELIACONE 没有单独道具说明,跳过 +❌ ITEM_LUMIOSE_GALETTE 没有单独道具说明,跳过 +❌ ITEM_SHALOUR_SABLE 没有单独道具说明,跳过 +❌ ITEM_BIG_MALASADA 没有单独道具说明,跳过 +❌ ITEM_HEALTH_FEATHER 没有单独道具说明,跳过 +❌ ITEM_MUSCLE_FEATHER 没有单独道具说明,跳过 +❌ ITEM_RESIST_FEATHER 没有单独道具说明,跳过 +❌ ITEM_GENIUS_FEATHER 没有单独道具说明,跳过 +❌ ITEM_CLEVER_FEATHER 没有单独道具说明,跳过 +❌ ITEM_SWIFT_FEATHER 没有单独道具说明,跳过 +❌ ITEM_POKE_DOLL 没有单独道具说明,跳过 +❌ ITEM_FLUFFY_TAIL 没有单独道具说明,跳过 +❌ ITEM_POKE_TOY 没有单独道具说明,跳过 +❌ ITEM_BIG_MUSHROOM 没有单独道具说明,跳过 +❌ ITEM_BALM_MUSHROOM 没有单独道具说明,跳过 +❌ ITEM_RED_SHARD 没有单独道具说明,跳过 +❌ ITEM_BLUE_SHARD 没有单独道具说明,跳过 +❌ ITEM_YELLOW_SHARD 没有单独道具说明,跳过 +❌ ITEM_GREEN_SHARD 没有单独道具说明,跳过 +❌ ITEM_ROOT_FOSSIL 没有单独道具说明,跳过 +❌ ITEM_CLAW_FOSSIL 没有单独道具说明,跳过 +❌ ITEM_FOSSILIZED_FISH 没有单独道具说明,跳过 +❌ ITEM_FOSSILIZED_DINO 没有单独道具说明,跳过 +❌ ITEM_BEAD_MAIL 没有单独道具说明,跳过 +❌ ITEM_DREAM_MAIL 没有单独道具说明,跳过 +❌ ITEM_FIRE_STONE 没有单独道具说明,跳过 +❌ ITEM_WATER_STONE 没有单独道具说明,跳过 +❌ ITEM_THUNDER_STONE 没有单独道具说明,跳过 +❌ ITEM_LEAF_STONE 没有单独道具说明,跳过 +❌ ITEM_ICE_STONE 没有单独道具说明,跳过 +❌ ITEM_SUN_STONE 没有单独道具说明,跳过 +❌ ITEM_MOON_STONE 没有单独道具说明,跳过 +❌ ITEM_SHINY_STONE 没有单独道具说明,跳过 +❌ ITEM_DUSK_STONE 没有单独道具说明,跳过 +❌ ITEM_DAWN_STONE 没有单独道具说明,跳过 +❌ ITEM_RED_NECTAR 没有单独道具说明,跳过 +❌ ITEM_YELLOW_NECTAR 没有单独道具说明,跳过 +❌ ITEM_PINK_NECTAR 没有单独道具说明,跳过 +❌ ITEM_PURPLE_NECTAR 没有单独道具说明,跳过 +❌ ITEM_CHARIZARDITE_X 没有单独道具说明,跳过 +❌ ITEM_CHARIZARDITE_Y 没有单独道具说明,跳过 +❌ ITEM_MEWTWONITE_X 没有单独道具说明,跳过 +❌ ITEM_MEWTWONITE_Y 没有单独道具说明,跳过 +❌ ITEM_SEA_INCENSE 没有单独道具说明,跳过 +❌ ITEM_ODD_INCENSE 没有单独道具说明,跳过 +❌ ITEM_ROCK_INCENSE 没有单独道具说明,跳过 +❌ ITEM_FULL_INCENSE 没有单独道具说明,跳过 +❌ ITEM_WAVE_INCENSE 没有单独道具说明,跳过 +❌ ITEM_ROSE_INCENSE 没有单独道具说明,跳过 +❌ ITEM_LUCK_INCENSE 没有单独道具说明,跳过 +❌ ITEM_PURE_INCENSE 没有单独道具说明,跳过 +❌ ITEM_MIRACLE_SEED 没有单独道具说明,跳过 +❌ ITEM_TWISTED_SPOON 没有单独道具说明,跳过 +❌ ITEM_HARD_STONE 没有单独道具说明,跳过 +❌ ITEM_KINGS_ROCK 没有单独道具说明,跳过 +❌ ITEM_AMULET_COIN 没有单独道具说明,跳过 +❌ ITEM_CLEANSE_TAG 没有单独道具说明,跳过 +❌ ITEM_LAGGING_TAIL 没有单独道具说明,跳过 +❌ ITEM_RAZOR_FANG 没有单独道具说明,跳过 +❌ ITEM_FIGY_BERRY 没有单独道具说明,跳过 +❌ ITEM_WIKI_BERRY 没有单独道具说明,跳过 +❌ ITEM_MAGO_BERRY 没有单独道具说明,跳过 +❌ ITEM_AGUAV_BERRY 没有单独道具说明,跳过 +❌ ITEM_IAPAPA_BERRY 没有单独道具说明,跳过 +❌ ITEM_TM51 没有单独道具说明,跳过 +❌ ITEM_TM52 没有单独道具说明,跳过 +❌ ITEM_TM53 没有单独道具说明,跳过 +❌ ITEM_TM54 没有单独道具说明,跳过 +❌ ITEM_TM55 没有单独道具说明,跳过 +❌ ITEM_TM56 没有单独道具说明,跳过 +❌ ITEM_TM57 没有单独道具说明,跳过 +❌ ITEM_TM58 没有单独道具说明,跳过 +❌ ITEM_TM59 没有单独道具说明,跳过 +❌ ITEM_TM60 没有单独道具说明,跳过 +❌ ITEM_TM61 没有单独道具说明,跳过 +❌ ITEM_TM62 没有单独道具说明,跳过 +❌ ITEM_TM63 没有单独道具说明,跳过 +❌ ITEM_TM64 没有单独道具说明,跳过 +❌ ITEM_TM65 没有单独道具说明,跳过 +❌ ITEM_TM66 没有单独道具说明,跳过 +❌ ITEM_TM67 没有单独道具说明,跳过 +❌ ITEM_TM68 没有单独道具说明,跳过 +❌ ITEM_TM69 没有单独道具说明,跳过 +❌ ITEM_TM70 没有单独道具说明,跳过 +❌ ITEM_TM71 没有单独道具说明,跳过 +❌ ITEM_TM72 没有单独道具说明,跳过 +❌ ITEM_TM73 没有单独道具说明,跳过 +❌ ITEM_TM74 没有单独道具说明,跳过 +❌ ITEM_TM75 没有单独道具说明,跳过 +❌ ITEM_TM76 没有单独道具说明,跳过 +❌ ITEM_TM77 没有单独道具说明,跳过 +❌ ITEM_TM78 没有单独道具说明,跳过 +❌ ITEM_TM79 没有单独道具说明,跳过 +❌ ITEM_TM80 没有单独道具说明,跳过 +❌ ITEM_TM81 没有单独道具说明,跳过 +❌ ITEM_TM82 没有单独道具说明,跳过 +❌ ITEM_TM83 没有单独道具说明,跳过 +❌ ITEM_TM84 没有单独道具说明,跳过 +❌ ITEM_TM85 没有单独道具说明,跳过 +❌ ITEM_TM86 没有单独道具说明,跳过 +❌ ITEM_TM87 没有单独道具说明,跳过 +❌ ITEM_TM88 没有单独道具说明,跳过 +❌ ITEM_TM89 没有单独道具说明,跳过 +❌ ITEM_TM90 没有单独道具说明,跳过 +❌ ITEM_TM91 没有单独道具说明,跳过 +❌ ITEM_TM92 没有单独道具说明,跳过 +❌ ITEM_TM93 没有单独道具说明,跳过 +❌ ITEM_TM94 没有单独道具说明,跳过 +❌ ITEM_TM95 没有单独道具说明,跳过 +❌ ITEM_TM96 没有单独道具说明,跳过 +❌ ITEM_TM97 没有单独道具说明,跳过 +❌ ITEM_TM98 没有单独道具说明,跳过 +❌ ITEM_TM99 没有单独道具说明,跳过 +❌ ITEM_TM100 没有单独道具说明,跳过 +❌ ITEM_KEY_TO_ROOM_1 没有单独道具说明,跳过 +❌ ITEM_KEY_TO_ROOM_2 没有单独道具说明,跳过 +❌ ITEM_KEY_TO_ROOM_4 没有单独道具说明,跳过 +❌ ITEM_KEY_TO_ROOM_6 没有单独道具说明,跳过 +❌ ITEM_BUG_TERA_SHARD 没有单独道具说明,跳过 +❌ ITEM_DARK_TERA_SHARD 没有单独道具说明,跳过 +❌ ITEM_DRAGON_TERA_SHARD 没有单独道具说明,跳过 +❌ ITEM_ELECTRIC_TERA_SHARD 没有单独道具说明,跳过 +❌ ITEM_FAIRY_TERA_SHARD 没有单独道具说明,跳过 +❌ ITEM_FIGHTING_TERA_SHARD 没有单独道具说明,跳过 +❌ ITEM_FIRE_TERA_SHARD 没有单独道具说明,跳过 +❌ ITEM_FLYING_TERA_SHARD 没有单独道具说明,跳过 +❌ ITEM_GHOST_TERA_SHARD 没有单独道具说明,跳过 +❌ ITEM_GRASS_TERA_SHARD 没有单独道具说明,跳过 +❌ ITEM_GROUND_TERA_SHARD 没有单独道具说明,跳过 +❌ ITEM_ICE_TERA_SHARD 没有单独道具说明,跳过 +❌ ITEM_NORMAL_TERA_SHARD 没有单独道具说明,跳过 +❌ ITEM_POISON_TERA_SHARD 没有单独道具说明,跳过 +❌ ITEM_PSYCHIC_TERA_SHARD 没有单独道具说明,跳过 +❌ ITEM_ROCK_TERA_SHARD 没有单独道具说明,跳过 +❌ ITEM_STEEL_TERA_SHARD 没有单独道具说明,跳过 +❌ ITEM_WATER_TERA_SHARD 没有单独道具说明,跳过 +❌ ITEM_HEALTH_MOCHI 没有单独道具说明,跳过 +❌ ITEM_MUSCLE_MOCHI 没有单独道具说明,跳过 +❌ ITEM_RESIST_MOCHI 没有单独道具说明,跳过 +❌ ITEM_GENIUS_MOCHI 没有单独道具说明,跳过 +❌ ITEM_CLEVER_MOCHI 没有单独道具说明,跳过 +❌ ITEM_SWIFT_MOCHI 没有单独道具说明,跳过 +❌ ITEM_STELLAR_TERA_SHARD 没有单独道具说明,跳过 +❌ ITEM_JUBILIFE_MUFFIN 没有单独道具说明,跳过 +❌ ITEM_SWAP_SNACK 没有单独道具说明,跳过 +❌ ITEM_TWICE_SPICED_RADISH 没有单独道具说明,跳过 diff --git a/sound/direct_sound_samples/bicycle_bell.aif b/sound/direct_sound_samples/bicycle_bell.aif deleted file mode 100644 index 578a81c2f1..0000000000 Binary files a/sound/direct_sound_samples/bicycle_bell.aif and /dev/null differ diff --git a/sound/direct_sound_samples/bicycle_bell.wav b/sound/direct_sound_samples/bicycle_bell.wav new file mode 100644 index 0000000000..92f9634069 Binary files /dev/null and b/sound/direct_sound_samples/bicycle_bell.wav differ diff --git a/sound/direct_sound_samples/classical_choir_voice_ahhs.aif b/sound/direct_sound_samples/classical_choir_voice_ahhs.aif deleted file mode 100644 index e8784682e4..0000000000 Binary files a/sound/direct_sound_samples/classical_choir_voice_ahhs.aif and /dev/null differ diff --git a/sound/direct_sound_samples/classical_choir_voice_ahhs.wav b/sound/direct_sound_samples/classical_choir_voice_ahhs.wav new file mode 100644 index 0000000000..7e38d3a3f7 Binary files /dev/null and b/sound/direct_sound_samples/classical_choir_voice_ahhs.wav differ diff --git a/sound/direct_sound_samples/cries/abomasnow.aif b/sound/direct_sound_samples/cries/abomasnow.aif deleted file mode 100644 index 83ef6b33ac..0000000000 Binary files a/sound/direct_sound_samples/cries/abomasnow.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/abomasnow.wav b/sound/direct_sound_samples/cries/abomasnow.wav new file mode 100644 index 0000000000..a403166d2c Binary files /dev/null and b/sound/direct_sound_samples/cries/abomasnow.wav differ diff --git a/sound/direct_sound_samples/cries/abomasnow_mega.aif b/sound/direct_sound_samples/cries/abomasnow_mega.aif deleted file mode 100644 index 1b6b0684cf..0000000000 Binary files a/sound/direct_sound_samples/cries/abomasnow_mega.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/abomasnow_mega.wav b/sound/direct_sound_samples/cries/abomasnow_mega.wav new file mode 100644 index 0000000000..6d825e5301 Binary files /dev/null and b/sound/direct_sound_samples/cries/abomasnow_mega.wav differ diff --git a/sound/direct_sound_samples/cries/abra.aif b/sound/direct_sound_samples/cries/abra.aif deleted file mode 100644 index 5c96619143..0000000000 Binary files a/sound/direct_sound_samples/cries/abra.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/abra.wav b/sound/direct_sound_samples/cries/abra.wav new file mode 100644 index 0000000000..14aba2d7a5 Binary files /dev/null and b/sound/direct_sound_samples/cries/abra.wav differ diff --git a/sound/direct_sound_samples/cries/absol.aif b/sound/direct_sound_samples/cries/absol.aif deleted file mode 100644 index 81e81350d5..0000000000 Binary files a/sound/direct_sound_samples/cries/absol.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/absol.wav b/sound/direct_sound_samples/cries/absol.wav new file mode 100644 index 0000000000..4a90ec5c01 Binary files /dev/null and b/sound/direct_sound_samples/cries/absol.wav differ diff --git a/sound/direct_sound_samples/cries/absol_mega.aif b/sound/direct_sound_samples/cries/absol_mega.aif deleted file mode 100644 index 415b6132f6..0000000000 Binary files a/sound/direct_sound_samples/cries/absol_mega.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/absol_mega.wav b/sound/direct_sound_samples/cries/absol_mega.wav new file mode 100644 index 0000000000..59ce8447a1 Binary files /dev/null and b/sound/direct_sound_samples/cries/absol_mega.wav differ diff --git a/sound/direct_sound_samples/cries/accelgor.aif b/sound/direct_sound_samples/cries/accelgor.aif deleted file mode 100644 index 209c309c1e..0000000000 Binary files a/sound/direct_sound_samples/cries/accelgor.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/accelgor.wav b/sound/direct_sound_samples/cries/accelgor.wav new file mode 100644 index 0000000000..09d3b0bc77 Binary files /dev/null and b/sound/direct_sound_samples/cries/accelgor.wav differ diff --git a/sound/direct_sound_samples/cries/aegislash.aif b/sound/direct_sound_samples/cries/aegislash.aif deleted file mode 100644 index d2c48b5d62..0000000000 Binary files a/sound/direct_sound_samples/cries/aegislash.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/aegislash.wav b/sound/direct_sound_samples/cries/aegislash.wav new file mode 100644 index 0000000000..33a1671947 Binary files /dev/null and b/sound/direct_sound_samples/cries/aegislash.wav differ diff --git a/sound/direct_sound_samples/cries/aerodactyl.aif b/sound/direct_sound_samples/cries/aerodactyl.aif deleted file mode 100644 index d4bf14946d..0000000000 Binary files a/sound/direct_sound_samples/cries/aerodactyl.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/aerodactyl.wav b/sound/direct_sound_samples/cries/aerodactyl.wav new file mode 100644 index 0000000000..95518884b9 Binary files /dev/null and b/sound/direct_sound_samples/cries/aerodactyl.wav differ diff --git a/sound/direct_sound_samples/cries/aerodactyl_mega.aif b/sound/direct_sound_samples/cries/aerodactyl_mega.aif deleted file mode 100644 index d323b09c59..0000000000 Binary files a/sound/direct_sound_samples/cries/aerodactyl_mega.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/aerodactyl_mega.wav b/sound/direct_sound_samples/cries/aerodactyl_mega.wav new file mode 100644 index 0000000000..2c6d876529 Binary files /dev/null and b/sound/direct_sound_samples/cries/aerodactyl_mega.wav differ diff --git a/sound/direct_sound_samples/cries/aggron.aif b/sound/direct_sound_samples/cries/aggron.aif deleted file mode 100644 index a87adf8f84..0000000000 Binary files a/sound/direct_sound_samples/cries/aggron.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/aggron.wav b/sound/direct_sound_samples/cries/aggron.wav new file mode 100644 index 0000000000..bc75b2dbdd Binary files /dev/null and b/sound/direct_sound_samples/cries/aggron.wav differ diff --git a/sound/direct_sound_samples/cries/aggron_mega.aif b/sound/direct_sound_samples/cries/aggron_mega.aif deleted file mode 100644 index 6772bdd5ee..0000000000 Binary files a/sound/direct_sound_samples/cries/aggron_mega.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/aggron_mega.wav b/sound/direct_sound_samples/cries/aggron_mega.wav new file mode 100644 index 0000000000..b679811f29 Binary files /dev/null and b/sound/direct_sound_samples/cries/aggron_mega.wav differ diff --git a/sound/direct_sound_samples/cries/aipom.aif b/sound/direct_sound_samples/cries/aipom.aif deleted file mode 100644 index e40107f787..0000000000 Binary files a/sound/direct_sound_samples/cries/aipom.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/aipom.wav b/sound/direct_sound_samples/cries/aipom.wav new file mode 100644 index 0000000000..4d7bc829cd Binary files /dev/null and b/sound/direct_sound_samples/cries/aipom.wav differ diff --git a/sound/direct_sound_samples/cries/alakazam.aif b/sound/direct_sound_samples/cries/alakazam.aif deleted file mode 100644 index d6b0126112..0000000000 Binary files a/sound/direct_sound_samples/cries/alakazam.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/alakazam.wav b/sound/direct_sound_samples/cries/alakazam.wav new file mode 100644 index 0000000000..f397363d15 Binary files /dev/null and b/sound/direct_sound_samples/cries/alakazam.wav differ diff --git a/sound/direct_sound_samples/cries/alakazam_mega.aif b/sound/direct_sound_samples/cries/alakazam_mega.aif deleted file mode 100644 index be09f22777..0000000000 Binary files a/sound/direct_sound_samples/cries/alakazam_mega.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/alakazam_mega.wav b/sound/direct_sound_samples/cries/alakazam_mega.wav new file mode 100644 index 0000000000..1b33bbe646 Binary files /dev/null and b/sound/direct_sound_samples/cries/alakazam_mega.wav differ diff --git a/sound/direct_sound_samples/cries/alcremie.aif b/sound/direct_sound_samples/cries/alcremie.aif deleted file mode 100644 index 4819688a6d..0000000000 Binary files a/sound/direct_sound_samples/cries/alcremie.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/alcremie.wav b/sound/direct_sound_samples/cries/alcremie.wav new file mode 100644 index 0000000000..64870763a7 Binary files /dev/null and b/sound/direct_sound_samples/cries/alcremie.wav differ diff --git a/sound/direct_sound_samples/cries/alomomola.aif b/sound/direct_sound_samples/cries/alomomola.aif deleted file mode 100644 index 2e47a4083a..0000000000 Binary files a/sound/direct_sound_samples/cries/alomomola.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/alomomola.wav b/sound/direct_sound_samples/cries/alomomola.wav new file mode 100644 index 0000000000..8b06465e2e Binary files /dev/null and b/sound/direct_sound_samples/cries/alomomola.wav differ diff --git a/sound/direct_sound_samples/cries/altaria.aif b/sound/direct_sound_samples/cries/altaria.aif deleted file mode 100644 index 0aa89c8fcb..0000000000 Binary files a/sound/direct_sound_samples/cries/altaria.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/altaria.wav b/sound/direct_sound_samples/cries/altaria.wav new file mode 100644 index 0000000000..ca35cbf519 Binary files /dev/null and b/sound/direct_sound_samples/cries/altaria.wav differ diff --git a/sound/direct_sound_samples/cries/altaria_mega.aif b/sound/direct_sound_samples/cries/altaria_mega.aif deleted file mode 100644 index bf2a7daec2..0000000000 Binary files a/sound/direct_sound_samples/cries/altaria_mega.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/altaria_mega.wav b/sound/direct_sound_samples/cries/altaria_mega.wav new file mode 100644 index 0000000000..1ddbcc6aff Binary files /dev/null and b/sound/direct_sound_samples/cries/altaria_mega.wav differ diff --git a/sound/direct_sound_samples/cries/amaura.aif b/sound/direct_sound_samples/cries/amaura.aif deleted file mode 100644 index 813fcaddde..0000000000 Binary files a/sound/direct_sound_samples/cries/amaura.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/amaura.wav b/sound/direct_sound_samples/cries/amaura.wav new file mode 100644 index 0000000000..cdd5ce160a Binary files /dev/null and b/sound/direct_sound_samples/cries/amaura.wav differ diff --git a/sound/direct_sound_samples/cries/ambipom.aif b/sound/direct_sound_samples/cries/ambipom.aif deleted file mode 100644 index a767329e07..0000000000 Binary files a/sound/direct_sound_samples/cries/ambipom.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/ambipom.wav b/sound/direct_sound_samples/cries/ambipom.wav new file mode 100644 index 0000000000..fc63ee7011 Binary files /dev/null and b/sound/direct_sound_samples/cries/ambipom.wav differ diff --git a/sound/direct_sound_samples/cries/amoonguss.aif b/sound/direct_sound_samples/cries/amoonguss.aif deleted file mode 100644 index d476e670bd..0000000000 Binary files a/sound/direct_sound_samples/cries/amoonguss.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/amoonguss.wav b/sound/direct_sound_samples/cries/amoonguss.wav new file mode 100644 index 0000000000..e472803369 Binary files /dev/null and b/sound/direct_sound_samples/cries/amoonguss.wav differ diff --git a/sound/direct_sound_samples/cries/ampharos.aif b/sound/direct_sound_samples/cries/ampharos.aif deleted file mode 100644 index 7eed0aa9f6..0000000000 Binary files a/sound/direct_sound_samples/cries/ampharos.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/ampharos.wav b/sound/direct_sound_samples/cries/ampharos.wav new file mode 100644 index 0000000000..346b2aa48b Binary files /dev/null and b/sound/direct_sound_samples/cries/ampharos.wav differ diff --git a/sound/direct_sound_samples/cries/ampharos_mega.aif b/sound/direct_sound_samples/cries/ampharos_mega.aif deleted file mode 100644 index e24e628667..0000000000 Binary files a/sound/direct_sound_samples/cries/ampharos_mega.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/ampharos_mega.wav b/sound/direct_sound_samples/cries/ampharos_mega.wav new file mode 100644 index 0000000000..284a01fba2 Binary files /dev/null and b/sound/direct_sound_samples/cries/ampharos_mega.wav differ diff --git a/sound/direct_sound_samples/cries/annihilape.aif b/sound/direct_sound_samples/cries/annihilape.aif deleted file mode 100644 index 889c521929..0000000000 Binary files a/sound/direct_sound_samples/cries/annihilape.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/annihilape.wav b/sound/direct_sound_samples/cries/annihilape.wav new file mode 100644 index 0000000000..c0232220b9 Binary files /dev/null and b/sound/direct_sound_samples/cries/annihilape.wav differ diff --git a/sound/direct_sound_samples/cries/anorith.aif b/sound/direct_sound_samples/cries/anorith.aif deleted file mode 100644 index ac6c774e5d..0000000000 Binary files a/sound/direct_sound_samples/cries/anorith.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/anorith.wav b/sound/direct_sound_samples/cries/anorith.wav new file mode 100644 index 0000000000..349ffacf04 Binary files /dev/null and b/sound/direct_sound_samples/cries/anorith.wav differ diff --git a/sound/direct_sound_samples/cries/appletun.aif b/sound/direct_sound_samples/cries/appletun.aif deleted file mode 100644 index 46b6ab4fcc..0000000000 Binary files a/sound/direct_sound_samples/cries/appletun.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/appletun.wav b/sound/direct_sound_samples/cries/appletun.wav new file mode 100644 index 0000000000..4cf9d895b2 Binary files /dev/null and b/sound/direct_sound_samples/cries/appletun.wav differ diff --git a/sound/direct_sound_samples/cries/applin.aif b/sound/direct_sound_samples/cries/applin.aif deleted file mode 100644 index 9e9a1de275..0000000000 Binary files a/sound/direct_sound_samples/cries/applin.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/applin.wav b/sound/direct_sound_samples/cries/applin.wav new file mode 100644 index 0000000000..55de4865de Binary files /dev/null and b/sound/direct_sound_samples/cries/applin.wav differ diff --git a/sound/direct_sound_samples/cries/araquanid.aif b/sound/direct_sound_samples/cries/araquanid.aif deleted file mode 100644 index 86aac62b80..0000000000 Binary files a/sound/direct_sound_samples/cries/araquanid.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/araquanid.wav b/sound/direct_sound_samples/cries/araquanid.wav new file mode 100644 index 0000000000..9c92577b4b Binary files /dev/null and b/sound/direct_sound_samples/cries/araquanid.wav differ diff --git a/sound/direct_sound_samples/cries/arbok.aif b/sound/direct_sound_samples/cries/arbok.aif deleted file mode 100644 index 0be4b7e624..0000000000 Binary files a/sound/direct_sound_samples/cries/arbok.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/arbok.wav b/sound/direct_sound_samples/cries/arbok.wav new file mode 100644 index 0000000000..cebc9e3e56 Binary files /dev/null and b/sound/direct_sound_samples/cries/arbok.wav differ diff --git a/sound/direct_sound_samples/cries/arboliva.aif b/sound/direct_sound_samples/cries/arboliva.aif deleted file mode 100644 index 641491ff0e..0000000000 Binary files a/sound/direct_sound_samples/cries/arboliva.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/arboliva.wav b/sound/direct_sound_samples/cries/arboliva.wav new file mode 100644 index 0000000000..c4ddb922d8 Binary files /dev/null and b/sound/direct_sound_samples/cries/arboliva.wav differ diff --git a/sound/direct_sound_samples/cries/arcanine.aif b/sound/direct_sound_samples/cries/arcanine.aif deleted file mode 100644 index cdc942c49a..0000000000 Binary files a/sound/direct_sound_samples/cries/arcanine.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/arcanine.wav b/sound/direct_sound_samples/cries/arcanine.wav new file mode 100644 index 0000000000..f6e3e36801 Binary files /dev/null and b/sound/direct_sound_samples/cries/arcanine.wav differ diff --git a/sound/direct_sound_samples/cries/arceus.aif b/sound/direct_sound_samples/cries/arceus.aif deleted file mode 100644 index 8496de2a17..0000000000 Binary files a/sound/direct_sound_samples/cries/arceus.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/arceus.wav b/sound/direct_sound_samples/cries/arceus.wav new file mode 100644 index 0000000000..5a33b4168b Binary files /dev/null and b/sound/direct_sound_samples/cries/arceus.wav differ diff --git a/sound/direct_sound_samples/cries/archaludon.aif b/sound/direct_sound_samples/cries/archaludon.aif deleted file mode 100644 index 470afe8348..0000000000 Binary files a/sound/direct_sound_samples/cries/archaludon.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/archaludon.wav b/sound/direct_sound_samples/cries/archaludon.wav new file mode 100644 index 0000000000..7195a6aa00 Binary files /dev/null and b/sound/direct_sound_samples/cries/archaludon.wav differ diff --git a/sound/direct_sound_samples/cries/archen.aif b/sound/direct_sound_samples/cries/archen.aif deleted file mode 100644 index b1b2be3ead..0000000000 Binary files a/sound/direct_sound_samples/cries/archen.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/archen.wav b/sound/direct_sound_samples/cries/archen.wav new file mode 100644 index 0000000000..05817f6633 Binary files /dev/null and b/sound/direct_sound_samples/cries/archen.wav differ diff --git a/sound/direct_sound_samples/cries/archeops.aif b/sound/direct_sound_samples/cries/archeops.aif deleted file mode 100644 index 6555f0ce3a..0000000000 Binary files a/sound/direct_sound_samples/cries/archeops.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/archeops.wav b/sound/direct_sound_samples/cries/archeops.wav new file mode 100644 index 0000000000..e79d66625c Binary files /dev/null and b/sound/direct_sound_samples/cries/archeops.wav differ diff --git a/sound/direct_sound_samples/cries/arctibax.aif b/sound/direct_sound_samples/cries/arctibax.aif deleted file mode 100644 index a18bc78081..0000000000 Binary files a/sound/direct_sound_samples/cries/arctibax.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/arctibax.wav b/sound/direct_sound_samples/cries/arctibax.wav new file mode 100644 index 0000000000..75bce7bca5 Binary files /dev/null and b/sound/direct_sound_samples/cries/arctibax.wav differ diff --git a/sound/direct_sound_samples/cries/arctovish.aif b/sound/direct_sound_samples/cries/arctovish.aif deleted file mode 100644 index 281c88f8d3..0000000000 Binary files a/sound/direct_sound_samples/cries/arctovish.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/arctovish.wav b/sound/direct_sound_samples/cries/arctovish.wav new file mode 100644 index 0000000000..6888758c3f Binary files /dev/null and b/sound/direct_sound_samples/cries/arctovish.wav differ diff --git a/sound/direct_sound_samples/cries/arctozolt.aif b/sound/direct_sound_samples/cries/arctozolt.aif deleted file mode 100644 index 3d0bb58264..0000000000 Binary files a/sound/direct_sound_samples/cries/arctozolt.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/arctozolt.wav b/sound/direct_sound_samples/cries/arctozolt.wav new file mode 100644 index 0000000000..fafc0a59fb Binary files /dev/null and b/sound/direct_sound_samples/cries/arctozolt.wav differ diff --git a/sound/direct_sound_samples/cries/ariados.aif b/sound/direct_sound_samples/cries/ariados.aif deleted file mode 100644 index 343879d70a..0000000000 Binary files a/sound/direct_sound_samples/cries/ariados.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/ariados.wav b/sound/direct_sound_samples/cries/ariados.wav new file mode 100644 index 0000000000..f059bcfc93 Binary files /dev/null and b/sound/direct_sound_samples/cries/ariados.wav differ diff --git a/sound/direct_sound_samples/cries/armaldo.aif b/sound/direct_sound_samples/cries/armaldo.aif deleted file mode 100644 index 23add2fec8..0000000000 Binary files a/sound/direct_sound_samples/cries/armaldo.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/armaldo.wav b/sound/direct_sound_samples/cries/armaldo.wav new file mode 100644 index 0000000000..de11795664 Binary files /dev/null and b/sound/direct_sound_samples/cries/armaldo.wav differ diff --git a/sound/direct_sound_samples/cries/armarouge.aif b/sound/direct_sound_samples/cries/armarouge.aif deleted file mode 100644 index 578c73392b..0000000000 Binary files a/sound/direct_sound_samples/cries/armarouge.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/armarouge.wav b/sound/direct_sound_samples/cries/armarouge.wav new file mode 100644 index 0000000000..bd891fe536 Binary files /dev/null and b/sound/direct_sound_samples/cries/armarouge.wav differ diff --git a/sound/direct_sound_samples/cries/aromatisse.aif b/sound/direct_sound_samples/cries/aromatisse.aif deleted file mode 100644 index 4880d14946..0000000000 Binary files a/sound/direct_sound_samples/cries/aromatisse.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/aromatisse.wav b/sound/direct_sound_samples/cries/aromatisse.wav new file mode 100644 index 0000000000..bcfb43e6dc Binary files /dev/null and b/sound/direct_sound_samples/cries/aromatisse.wav differ diff --git a/sound/direct_sound_samples/cries/aron.aif b/sound/direct_sound_samples/cries/aron.aif deleted file mode 100644 index d246b4c22b..0000000000 Binary files a/sound/direct_sound_samples/cries/aron.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/aron.wav b/sound/direct_sound_samples/cries/aron.wav new file mode 100644 index 0000000000..35c69f8dc4 Binary files /dev/null and b/sound/direct_sound_samples/cries/aron.wav differ diff --git a/sound/direct_sound_samples/cries/arrokuda.aif b/sound/direct_sound_samples/cries/arrokuda.aif deleted file mode 100644 index 863b6d2fb5..0000000000 Binary files a/sound/direct_sound_samples/cries/arrokuda.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/arrokuda.wav b/sound/direct_sound_samples/cries/arrokuda.wav new file mode 100644 index 0000000000..c5b040c87a Binary files /dev/null and b/sound/direct_sound_samples/cries/arrokuda.wav differ diff --git a/sound/direct_sound_samples/cries/articuno.aif b/sound/direct_sound_samples/cries/articuno.aif deleted file mode 100644 index 212114537f..0000000000 Binary files a/sound/direct_sound_samples/cries/articuno.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/articuno.wav b/sound/direct_sound_samples/cries/articuno.wav new file mode 100644 index 0000000000..348fbcd2f0 Binary files /dev/null and b/sound/direct_sound_samples/cries/articuno.wav differ diff --git a/sound/direct_sound_samples/cries/audino.aif b/sound/direct_sound_samples/cries/audino.aif deleted file mode 100644 index 873d4c947b..0000000000 Binary files a/sound/direct_sound_samples/cries/audino.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/audino.wav b/sound/direct_sound_samples/cries/audino.wav new file mode 100644 index 0000000000..fc2fb1283d Binary files /dev/null and b/sound/direct_sound_samples/cries/audino.wav differ diff --git a/sound/direct_sound_samples/cries/audino_mega.aif b/sound/direct_sound_samples/cries/audino_mega.aif deleted file mode 100644 index 04d815001e..0000000000 Binary files a/sound/direct_sound_samples/cries/audino_mega.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/audino_mega.wav b/sound/direct_sound_samples/cries/audino_mega.wav new file mode 100644 index 0000000000..5cf8619706 Binary files /dev/null and b/sound/direct_sound_samples/cries/audino_mega.wav differ diff --git a/sound/direct_sound_samples/cries/aurorus.aif b/sound/direct_sound_samples/cries/aurorus.aif deleted file mode 100644 index 9483e1b637..0000000000 Binary files a/sound/direct_sound_samples/cries/aurorus.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/aurorus.wav b/sound/direct_sound_samples/cries/aurorus.wav new file mode 100644 index 0000000000..4504fd119a Binary files /dev/null and b/sound/direct_sound_samples/cries/aurorus.wav differ diff --git a/sound/direct_sound_samples/cries/avalugg.aif b/sound/direct_sound_samples/cries/avalugg.aif deleted file mode 100644 index 95c9d7a174..0000000000 Binary files a/sound/direct_sound_samples/cries/avalugg.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/avalugg.wav b/sound/direct_sound_samples/cries/avalugg.wav new file mode 100644 index 0000000000..cbb8acb91a Binary files /dev/null and b/sound/direct_sound_samples/cries/avalugg.wav differ diff --git a/sound/direct_sound_samples/cries/axew.aif b/sound/direct_sound_samples/cries/axew.aif deleted file mode 100644 index f642085f67..0000000000 Binary files a/sound/direct_sound_samples/cries/axew.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/axew.wav b/sound/direct_sound_samples/cries/axew.wav new file mode 100644 index 0000000000..8cdab431e9 Binary files /dev/null and b/sound/direct_sound_samples/cries/axew.wav differ diff --git a/sound/direct_sound_samples/cries/azelf.aif b/sound/direct_sound_samples/cries/azelf.aif deleted file mode 100644 index ad2e96c8f9..0000000000 Binary files a/sound/direct_sound_samples/cries/azelf.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/azelf.wav b/sound/direct_sound_samples/cries/azelf.wav new file mode 100644 index 0000000000..b87f8e4d8f Binary files /dev/null and b/sound/direct_sound_samples/cries/azelf.wav differ diff --git a/sound/direct_sound_samples/cries/azumarill.aif b/sound/direct_sound_samples/cries/azumarill.aif deleted file mode 100644 index 99a497e205..0000000000 Binary files a/sound/direct_sound_samples/cries/azumarill.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/azumarill.wav b/sound/direct_sound_samples/cries/azumarill.wav new file mode 100644 index 0000000000..f9e9ed89a1 Binary files /dev/null and b/sound/direct_sound_samples/cries/azumarill.wav differ diff --git a/sound/direct_sound_samples/cries/azurill.aif b/sound/direct_sound_samples/cries/azurill.aif deleted file mode 100644 index 401385cafb..0000000000 Binary files a/sound/direct_sound_samples/cries/azurill.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/azurill.wav b/sound/direct_sound_samples/cries/azurill.wav new file mode 100644 index 0000000000..65fa56e65b Binary files /dev/null and b/sound/direct_sound_samples/cries/azurill.wav differ diff --git a/sound/direct_sound_samples/cries/bagon.aif b/sound/direct_sound_samples/cries/bagon.aif deleted file mode 100644 index f7c5c3b59e..0000000000 Binary files a/sound/direct_sound_samples/cries/bagon.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/bagon.wav b/sound/direct_sound_samples/cries/bagon.wav new file mode 100644 index 0000000000..af36a96eb8 Binary files /dev/null and b/sound/direct_sound_samples/cries/bagon.wav differ diff --git a/sound/direct_sound_samples/cries/baltoy.aif b/sound/direct_sound_samples/cries/baltoy.aif deleted file mode 100644 index 7900eb1d64..0000000000 Binary files a/sound/direct_sound_samples/cries/baltoy.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/baltoy.wav b/sound/direct_sound_samples/cries/baltoy.wav new file mode 100644 index 0000000000..395954b565 Binary files /dev/null and b/sound/direct_sound_samples/cries/baltoy.wav differ diff --git a/sound/direct_sound_samples/cries/banette.aif b/sound/direct_sound_samples/cries/banette.aif deleted file mode 100644 index 587b307e27..0000000000 Binary files a/sound/direct_sound_samples/cries/banette.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/banette.wav b/sound/direct_sound_samples/cries/banette.wav new file mode 100644 index 0000000000..f030fb66c2 Binary files /dev/null and b/sound/direct_sound_samples/cries/banette.wav differ diff --git a/sound/direct_sound_samples/cries/banette_mega.aif b/sound/direct_sound_samples/cries/banette_mega.aif deleted file mode 100644 index 974f74c31e..0000000000 Binary files a/sound/direct_sound_samples/cries/banette_mega.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/banette_mega.wav b/sound/direct_sound_samples/cries/banette_mega.wav new file mode 100644 index 0000000000..5de36a008c Binary files /dev/null and b/sound/direct_sound_samples/cries/banette_mega.wav differ diff --git a/sound/direct_sound_samples/cries/barbaracle.aif b/sound/direct_sound_samples/cries/barbaracle.aif deleted file mode 100644 index 3f724127bd..0000000000 Binary files a/sound/direct_sound_samples/cries/barbaracle.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/barbaracle.wav b/sound/direct_sound_samples/cries/barbaracle.wav new file mode 100644 index 0000000000..8c5f4c2c69 Binary files /dev/null and b/sound/direct_sound_samples/cries/barbaracle.wav differ diff --git a/sound/direct_sound_samples/cries/barboach.aif b/sound/direct_sound_samples/cries/barboach.aif deleted file mode 100644 index 926e7fc050..0000000000 Binary files a/sound/direct_sound_samples/cries/barboach.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/barboach.wav b/sound/direct_sound_samples/cries/barboach.wav new file mode 100644 index 0000000000..40539ce514 Binary files /dev/null and b/sound/direct_sound_samples/cries/barboach.wav differ diff --git a/sound/direct_sound_samples/cries/barraskewda.aif b/sound/direct_sound_samples/cries/barraskewda.aif deleted file mode 100644 index e1a75a7dc7..0000000000 Binary files a/sound/direct_sound_samples/cries/barraskewda.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/barraskewda.wav b/sound/direct_sound_samples/cries/barraskewda.wav new file mode 100644 index 0000000000..61e0b5a883 Binary files /dev/null and b/sound/direct_sound_samples/cries/barraskewda.wav differ diff --git a/sound/direct_sound_samples/cries/basculegion.aif b/sound/direct_sound_samples/cries/basculegion.aif deleted file mode 100644 index 28a8349a51..0000000000 Binary files a/sound/direct_sound_samples/cries/basculegion.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/basculegion.wav b/sound/direct_sound_samples/cries/basculegion.wav new file mode 100644 index 0000000000..61770488d1 Binary files /dev/null and b/sound/direct_sound_samples/cries/basculegion.wav differ diff --git a/sound/direct_sound_samples/cries/basculin.aif b/sound/direct_sound_samples/cries/basculin.aif deleted file mode 100644 index dfa6db25f1..0000000000 Binary files a/sound/direct_sound_samples/cries/basculin.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/basculin.wav b/sound/direct_sound_samples/cries/basculin.wav new file mode 100644 index 0000000000..177af170be Binary files /dev/null and b/sound/direct_sound_samples/cries/basculin.wav differ diff --git a/sound/direct_sound_samples/cries/bastiodon.aif b/sound/direct_sound_samples/cries/bastiodon.aif deleted file mode 100644 index 5f5646f787..0000000000 Binary files a/sound/direct_sound_samples/cries/bastiodon.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/bastiodon.wav b/sound/direct_sound_samples/cries/bastiodon.wav new file mode 100644 index 0000000000..7d693cb6cb Binary files /dev/null and b/sound/direct_sound_samples/cries/bastiodon.wav differ diff --git a/sound/direct_sound_samples/cries/baxcalibur.aif b/sound/direct_sound_samples/cries/baxcalibur.aif deleted file mode 100644 index fd8f5eff6d..0000000000 Binary files a/sound/direct_sound_samples/cries/baxcalibur.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/baxcalibur.wav b/sound/direct_sound_samples/cries/baxcalibur.wav new file mode 100644 index 0000000000..2dd6bf735f Binary files /dev/null and b/sound/direct_sound_samples/cries/baxcalibur.wav differ diff --git a/sound/direct_sound_samples/cries/bayleef.aif b/sound/direct_sound_samples/cries/bayleef.aif deleted file mode 100644 index 1b38f322a9..0000000000 Binary files a/sound/direct_sound_samples/cries/bayleef.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/bayleef.wav b/sound/direct_sound_samples/cries/bayleef.wav new file mode 100644 index 0000000000..754e6e6e6e Binary files /dev/null and b/sound/direct_sound_samples/cries/bayleef.wav differ diff --git a/sound/direct_sound_samples/cries/beartic.aif b/sound/direct_sound_samples/cries/beartic.aif deleted file mode 100644 index 1c7635357a..0000000000 Binary files a/sound/direct_sound_samples/cries/beartic.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/beartic.wav b/sound/direct_sound_samples/cries/beartic.wav new file mode 100644 index 0000000000..a7fa0481be Binary files /dev/null and b/sound/direct_sound_samples/cries/beartic.wav differ diff --git a/sound/direct_sound_samples/cries/beautifly.aif b/sound/direct_sound_samples/cries/beautifly.aif deleted file mode 100644 index 5b31f73c31..0000000000 Binary files a/sound/direct_sound_samples/cries/beautifly.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/beautifly.wav b/sound/direct_sound_samples/cries/beautifly.wav new file mode 100644 index 0000000000..f9c3f26a5b Binary files /dev/null and b/sound/direct_sound_samples/cries/beautifly.wav differ diff --git a/sound/direct_sound_samples/cries/beedrill.aif b/sound/direct_sound_samples/cries/beedrill.aif deleted file mode 100644 index 888e1e637d..0000000000 Binary files a/sound/direct_sound_samples/cries/beedrill.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/beedrill.wav b/sound/direct_sound_samples/cries/beedrill.wav new file mode 100644 index 0000000000..6ba426baea Binary files /dev/null and b/sound/direct_sound_samples/cries/beedrill.wav differ diff --git a/sound/direct_sound_samples/cries/beedrill_mega.aif b/sound/direct_sound_samples/cries/beedrill_mega.aif deleted file mode 100644 index cea7ca52d5..0000000000 Binary files a/sound/direct_sound_samples/cries/beedrill_mega.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/beedrill_mega.wav b/sound/direct_sound_samples/cries/beedrill_mega.wav new file mode 100644 index 0000000000..ed5d23ee70 Binary files /dev/null and b/sound/direct_sound_samples/cries/beedrill_mega.wav differ diff --git a/sound/direct_sound_samples/cries/beheeyem.aif b/sound/direct_sound_samples/cries/beheeyem.aif deleted file mode 100644 index fb7ce70677..0000000000 Binary files a/sound/direct_sound_samples/cries/beheeyem.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/beheeyem.wav b/sound/direct_sound_samples/cries/beheeyem.wav new file mode 100644 index 0000000000..e69067281b Binary files /dev/null and b/sound/direct_sound_samples/cries/beheeyem.wav differ diff --git a/sound/direct_sound_samples/cries/beldum.aif b/sound/direct_sound_samples/cries/beldum.aif deleted file mode 100644 index 626f94fc1c..0000000000 Binary files a/sound/direct_sound_samples/cries/beldum.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/beldum.wav b/sound/direct_sound_samples/cries/beldum.wav new file mode 100644 index 0000000000..5d6514af4c Binary files /dev/null and b/sound/direct_sound_samples/cries/beldum.wav differ diff --git a/sound/direct_sound_samples/cries/bellibolt.aif b/sound/direct_sound_samples/cries/bellibolt.aif deleted file mode 100644 index b7fc6d0175..0000000000 Binary files a/sound/direct_sound_samples/cries/bellibolt.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/bellibolt.wav b/sound/direct_sound_samples/cries/bellibolt.wav new file mode 100644 index 0000000000..2a59187760 Binary files /dev/null and b/sound/direct_sound_samples/cries/bellibolt.wav differ diff --git a/sound/direct_sound_samples/cries/bellossom.aif b/sound/direct_sound_samples/cries/bellossom.aif deleted file mode 100644 index ffe452fc5a..0000000000 Binary files a/sound/direct_sound_samples/cries/bellossom.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/bellossom.wav b/sound/direct_sound_samples/cries/bellossom.wav new file mode 100644 index 0000000000..71680c16b2 Binary files /dev/null and b/sound/direct_sound_samples/cries/bellossom.wav differ diff --git a/sound/direct_sound_samples/cries/bellsprout.aif b/sound/direct_sound_samples/cries/bellsprout.aif deleted file mode 100644 index 40e12f8e8b..0000000000 Binary files a/sound/direct_sound_samples/cries/bellsprout.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/bellsprout.wav b/sound/direct_sound_samples/cries/bellsprout.wav new file mode 100644 index 0000000000..dc7da2e277 Binary files /dev/null and b/sound/direct_sound_samples/cries/bellsprout.wav differ diff --git a/sound/direct_sound_samples/cries/bergmite.aif b/sound/direct_sound_samples/cries/bergmite.aif deleted file mode 100644 index 9dbcb7dd08..0000000000 Binary files a/sound/direct_sound_samples/cries/bergmite.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/bergmite.wav b/sound/direct_sound_samples/cries/bergmite.wav new file mode 100644 index 0000000000..89b2c96ae5 Binary files /dev/null and b/sound/direct_sound_samples/cries/bergmite.wav differ diff --git a/sound/direct_sound_samples/cries/bewear.aif b/sound/direct_sound_samples/cries/bewear.aif deleted file mode 100644 index 00979e4542..0000000000 Binary files a/sound/direct_sound_samples/cries/bewear.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/bewear.wav b/sound/direct_sound_samples/cries/bewear.wav new file mode 100644 index 0000000000..e2f83f9e12 Binary files /dev/null and b/sound/direct_sound_samples/cries/bewear.wav differ diff --git a/sound/direct_sound_samples/cries/bibarel.aif b/sound/direct_sound_samples/cries/bibarel.aif deleted file mode 100644 index 64b3f5e0ec..0000000000 Binary files a/sound/direct_sound_samples/cries/bibarel.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/bibarel.wav b/sound/direct_sound_samples/cries/bibarel.wav new file mode 100644 index 0000000000..d1db5310ff Binary files /dev/null and b/sound/direct_sound_samples/cries/bibarel.wav differ diff --git a/sound/direct_sound_samples/cries/bidoof.aif b/sound/direct_sound_samples/cries/bidoof.aif deleted file mode 100644 index 4da8f32ade..0000000000 Binary files a/sound/direct_sound_samples/cries/bidoof.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/bidoof.wav b/sound/direct_sound_samples/cries/bidoof.wav new file mode 100644 index 0000000000..7d7b519fa6 Binary files /dev/null and b/sound/direct_sound_samples/cries/bidoof.wav differ diff --git a/sound/direct_sound_samples/cries/binacle.aif b/sound/direct_sound_samples/cries/binacle.aif deleted file mode 100644 index 168952c84b..0000000000 Binary files a/sound/direct_sound_samples/cries/binacle.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/binacle.wav b/sound/direct_sound_samples/cries/binacle.wav new file mode 100644 index 0000000000..c9a5449d90 Binary files /dev/null and b/sound/direct_sound_samples/cries/binacle.wav differ diff --git a/sound/direct_sound_samples/cries/bisharp.aif b/sound/direct_sound_samples/cries/bisharp.aif deleted file mode 100644 index dd1d4c4229..0000000000 Binary files a/sound/direct_sound_samples/cries/bisharp.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/bisharp.wav b/sound/direct_sound_samples/cries/bisharp.wav new file mode 100644 index 0000000000..55ee54e0f2 Binary files /dev/null and b/sound/direct_sound_samples/cries/bisharp.wav differ diff --git a/sound/direct_sound_samples/cries/blacephalon.aif b/sound/direct_sound_samples/cries/blacephalon.aif deleted file mode 100644 index f1308e1344..0000000000 Binary files a/sound/direct_sound_samples/cries/blacephalon.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/blacephalon.wav b/sound/direct_sound_samples/cries/blacephalon.wav new file mode 100644 index 0000000000..342221ee87 Binary files /dev/null and b/sound/direct_sound_samples/cries/blacephalon.wav differ diff --git a/sound/direct_sound_samples/cries/blastoise.aif b/sound/direct_sound_samples/cries/blastoise.aif deleted file mode 100644 index c3ae9294f2..0000000000 Binary files a/sound/direct_sound_samples/cries/blastoise.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/blastoise.wav b/sound/direct_sound_samples/cries/blastoise.wav new file mode 100644 index 0000000000..fecb7733b4 Binary files /dev/null and b/sound/direct_sound_samples/cries/blastoise.wav differ diff --git a/sound/direct_sound_samples/cries/blastoise_mega.aif b/sound/direct_sound_samples/cries/blastoise_mega.aif deleted file mode 100644 index a25f49c30c..0000000000 Binary files a/sound/direct_sound_samples/cries/blastoise_mega.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/blastoise_mega.wav b/sound/direct_sound_samples/cries/blastoise_mega.wav new file mode 100644 index 0000000000..1f04ee2aaa Binary files /dev/null and b/sound/direct_sound_samples/cries/blastoise_mega.wav differ diff --git a/sound/direct_sound_samples/cries/blaziken.aif b/sound/direct_sound_samples/cries/blaziken.aif deleted file mode 100644 index fa8a46ba9c..0000000000 Binary files a/sound/direct_sound_samples/cries/blaziken.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/blaziken.wav b/sound/direct_sound_samples/cries/blaziken.wav new file mode 100644 index 0000000000..b7b663d8ec Binary files /dev/null and b/sound/direct_sound_samples/cries/blaziken.wav differ diff --git a/sound/direct_sound_samples/cries/blaziken_mega.aif b/sound/direct_sound_samples/cries/blaziken_mega.aif deleted file mode 100644 index ef5f08153e..0000000000 Binary files a/sound/direct_sound_samples/cries/blaziken_mega.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/blaziken_mega.wav b/sound/direct_sound_samples/cries/blaziken_mega.wav new file mode 100644 index 0000000000..65e06208a1 Binary files /dev/null and b/sound/direct_sound_samples/cries/blaziken_mega.wav differ diff --git a/sound/direct_sound_samples/cries/blipbug.aif b/sound/direct_sound_samples/cries/blipbug.aif deleted file mode 100644 index ac9a26d484..0000000000 Binary files a/sound/direct_sound_samples/cries/blipbug.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/blipbug.wav b/sound/direct_sound_samples/cries/blipbug.wav new file mode 100644 index 0000000000..b398671b6f Binary files /dev/null and b/sound/direct_sound_samples/cries/blipbug.wav differ diff --git a/sound/direct_sound_samples/cries/blissey.aif b/sound/direct_sound_samples/cries/blissey.aif deleted file mode 100644 index 6cb483ae72..0000000000 Binary files a/sound/direct_sound_samples/cries/blissey.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/blissey.wav b/sound/direct_sound_samples/cries/blissey.wav new file mode 100644 index 0000000000..a5012768c1 Binary files /dev/null and b/sound/direct_sound_samples/cries/blissey.wav differ diff --git a/sound/direct_sound_samples/cries/blitzle.aif b/sound/direct_sound_samples/cries/blitzle.aif deleted file mode 100644 index d730da670f..0000000000 Binary files a/sound/direct_sound_samples/cries/blitzle.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/blitzle.wav b/sound/direct_sound_samples/cries/blitzle.wav new file mode 100644 index 0000000000..e026b158d4 Binary files /dev/null and b/sound/direct_sound_samples/cries/blitzle.wav differ diff --git a/sound/direct_sound_samples/cries/boldore.aif b/sound/direct_sound_samples/cries/boldore.aif deleted file mode 100644 index 9dbee00115..0000000000 Binary files a/sound/direct_sound_samples/cries/boldore.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/boldore.wav b/sound/direct_sound_samples/cries/boldore.wav new file mode 100644 index 0000000000..463e54d938 Binary files /dev/null and b/sound/direct_sound_samples/cries/boldore.wav differ diff --git a/sound/direct_sound_samples/cries/boltund.aif b/sound/direct_sound_samples/cries/boltund.aif deleted file mode 100644 index 819142f86c..0000000000 Binary files a/sound/direct_sound_samples/cries/boltund.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/boltund.wav b/sound/direct_sound_samples/cries/boltund.wav new file mode 100644 index 0000000000..5545f33685 Binary files /dev/null and b/sound/direct_sound_samples/cries/boltund.wav differ diff --git a/sound/direct_sound_samples/cries/bombirdier.aif b/sound/direct_sound_samples/cries/bombirdier.aif deleted file mode 100644 index 27f334acbb..0000000000 Binary files a/sound/direct_sound_samples/cries/bombirdier.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/bombirdier.wav b/sound/direct_sound_samples/cries/bombirdier.wav new file mode 100644 index 0000000000..db0e74d7c1 Binary files /dev/null and b/sound/direct_sound_samples/cries/bombirdier.wav differ diff --git a/sound/direct_sound_samples/cries/bonsly.aif b/sound/direct_sound_samples/cries/bonsly.aif deleted file mode 100644 index 15bd56f232..0000000000 Binary files a/sound/direct_sound_samples/cries/bonsly.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/bonsly.wav b/sound/direct_sound_samples/cries/bonsly.wav new file mode 100644 index 0000000000..7914868463 Binary files /dev/null and b/sound/direct_sound_samples/cries/bonsly.wav differ diff --git a/sound/direct_sound_samples/cries/bouffalant.aif b/sound/direct_sound_samples/cries/bouffalant.aif deleted file mode 100644 index e9502a94b6..0000000000 Binary files a/sound/direct_sound_samples/cries/bouffalant.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/bouffalant.wav b/sound/direct_sound_samples/cries/bouffalant.wav new file mode 100644 index 0000000000..a1af3a6b90 Binary files /dev/null and b/sound/direct_sound_samples/cries/bouffalant.wav differ diff --git a/sound/direct_sound_samples/cries/bounsweet.aif b/sound/direct_sound_samples/cries/bounsweet.aif deleted file mode 100644 index b1d21fb390..0000000000 Binary files a/sound/direct_sound_samples/cries/bounsweet.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/bounsweet.wav b/sound/direct_sound_samples/cries/bounsweet.wav new file mode 100644 index 0000000000..2a4120aa01 Binary files /dev/null and b/sound/direct_sound_samples/cries/bounsweet.wav differ diff --git a/sound/direct_sound_samples/cries/braixen.aif b/sound/direct_sound_samples/cries/braixen.aif deleted file mode 100644 index d5d9e800b0..0000000000 Binary files a/sound/direct_sound_samples/cries/braixen.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/braixen.wav b/sound/direct_sound_samples/cries/braixen.wav new file mode 100644 index 0000000000..640edbfb2b Binary files /dev/null and b/sound/direct_sound_samples/cries/braixen.wav differ diff --git a/sound/direct_sound_samples/cries/brambleghast.aif b/sound/direct_sound_samples/cries/brambleghast.aif deleted file mode 100644 index 404e7d1dc6..0000000000 Binary files a/sound/direct_sound_samples/cries/brambleghast.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/brambleghast.wav b/sound/direct_sound_samples/cries/brambleghast.wav new file mode 100644 index 0000000000..30f2f133be Binary files /dev/null and b/sound/direct_sound_samples/cries/brambleghast.wav differ diff --git a/sound/direct_sound_samples/cries/bramblin.aif b/sound/direct_sound_samples/cries/bramblin.aif deleted file mode 100644 index b55e43fe77..0000000000 Binary files a/sound/direct_sound_samples/cries/bramblin.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/bramblin.wav b/sound/direct_sound_samples/cries/bramblin.wav new file mode 100644 index 0000000000..68596b96a1 Binary files /dev/null and b/sound/direct_sound_samples/cries/bramblin.wav differ diff --git a/sound/direct_sound_samples/cries/braviary.aif b/sound/direct_sound_samples/cries/braviary.aif deleted file mode 100644 index 0cf3fc403e..0000000000 Binary files a/sound/direct_sound_samples/cries/braviary.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/braviary.wav b/sound/direct_sound_samples/cries/braviary.wav new file mode 100644 index 0000000000..a05d45f955 Binary files /dev/null and b/sound/direct_sound_samples/cries/braviary.wav differ diff --git a/sound/direct_sound_samples/cries/breloom.aif b/sound/direct_sound_samples/cries/breloom.aif deleted file mode 100644 index aa6e22f1b9..0000000000 Binary files a/sound/direct_sound_samples/cries/breloom.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/breloom.wav b/sound/direct_sound_samples/cries/breloom.wav new file mode 100644 index 0000000000..49f57f53ec Binary files /dev/null and b/sound/direct_sound_samples/cries/breloom.wav differ diff --git a/sound/direct_sound_samples/cries/brionne.aif b/sound/direct_sound_samples/cries/brionne.aif deleted file mode 100644 index ac026ada88..0000000000 Binary files a/sound/direct_sound_samples/cries/brionne.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/brionne.wav b/sound/direct_sound_samples/cries/brionne.wav new file mode 100644 index 0000000000..f72a6df30a Binary files /dev/null and b/sound/direct_sound_samples/cries/brionne.wav differ diff --git a/sound/direct_sound_samples/cries/bronzong.aif b/sound/direct_sound_samples/cries/bronzong.aif deleted file mode 100644 index 628ec30895..0000000000 Binary files a/sound/direct_sound_samples/cries/bronzong.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/bronzong.wav b/sound/direct_sound_samples/cries/bronzong.wav new file mode 100644 index 0000000000..019013e0da Binary files /dev/null and b/sound/direct_sound_samples/cries/bronzong.wav differ diff --git a/sound/direct_sound_samples/cries/bronzor.aif b/sound/direct_sound_samples/cries/bronzor.aif deleted file mode 100644 index 857bef1056..0000000000 Binary files a/sound/direct_sound_samples/cries/bronzor.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/bronzor.wav b/sound/direct_sound_samples/cries/bronzor.wav new file mode 100644 index 0000000000..133c581532 Binary files /dev/null and b/sound/direct_sound_samples/cries/bronzor.wav differ diff --git a/sound/direct_sound_samples/cries/brute_bonnet.aif b/sound/direct_sound_samples/cries/brute_bonnet.aif deleted file mode 100644 index 3a6369e8be..0000000000 Binary files a/sound/direct_sound_samples/cries/brute_bonnet.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/brute_bonnet.wav b/sound/direct_sound_samples/cries/brute_bonnet.wav new file mode 100644 index 0000000000..f3fe7e9799 Binary files /dev/null and b/sound/direct_sound_samples/cries/brute_bonnet.wav differ diff --git a/sound/direct_sound_samples/cries/bruxish.aif b/sound/direct_sound_samples/cries/bruxish.aif deleted file mode 100644 index f725043bc7..0000000000 Binary files a/sound/direct_sound_samples/cries/bruxish.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/bruxish.wav b/sound/direct_sound_samples/cries/bruxish.wav new file mode 100644 index 0000000000..cd5bfbf912 Binary files /dev/null and b/sound/direct_sound_samples/cries/bruxish.wav differ diff --git a/sound/direct_sound_samples/cries/budew.aif b/sound/direct_sound_samples/cries/budew.aif deleted file mode 100644 index bebc52a8df..0000000000 Binary files a/sound/direct_sound_samples/cries/budew.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/budew.wav b/sound/direct_sound_samples/cries/budew.wav new file mode 100644 index 0000000000..97960bf335 Binary files /dev/null and b/sound/direct_sound_samples/cries/budew.wav differ diff --git a/sound/direct_sound_samples/cries/buizel.aif b/sound/direct_sound_samples/cries/buizel.aif deleted file mode 100644 index b138be7a4f..0000000000 Binary files a/sound/direct_sound_samples/cries/buizel.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/buizel.wav b/sound/direct_sound_samples/cries/buizel.wav new file mode 100644 index 0000000000..21bb4d26aa Binary files /dev/null and b/sound/direct_sound_samples/cries/buizel.wav differ diff --git a/sound/direct_sound_samples/cries/bulbasaur.aif b/sound/direct_sound_samples/cries/bulbasaur.aif deleted file mode 100644 index cff5d718b3..0000000000 Binary files a/sound/direct_sound_samples/cries/bulbasaur.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/bulbasaur.wav b/sound/direct_sound_samples/cries/bulbasaur.wav new file mode 100644 index 0000000000..77a2d1bd1c Binary files /dev/null and b/sound/direct_sound_samples/cries/bulbasaur.wav differ diff --git a/sound/direct_sound_samples/cries/buneary.aif b/sound/direct_sound_samples/cries/buneary.aif deleted file mode 100644 index f02bf1b465..0000000000 Binary files a/sound/direct_sound_samples/cries/buneary.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/buneary.wav b/sound/direct_sound_samples/cries/buneary.wav new file mode 100644 index 0000000000..00af6ec1d8 Binary files /dev/null and b/sound/direct_sound_samples/cries/buneary.wav differ diff --git a/sound/direct_sound_samples/cries/bunnelby.aif b/sound/direct_sound_samples/cries/bunnelby.aif deleted file mode 100644 index 7588776e93..0000000000 Binary files a/sound/direct_sound_samples/cries/bunnelby.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/bunnelby.wav b/sound/direct_sound_samples/cries/bunnelby.wav new file mode 100644 index 0000000000..469b6d371b Binary files /dev/null and b/sound/direct_sound_samples/cries/bunnelby.wav differ diff --git a/sound/direct_sound_samples/cries/burmy.aif b/sound/direct_sound_samples/cries/burmy.aif deleted file mode 100644 index 80478166f5..0000000000 Binary files a/sound/direct_sound_samples/cries/burmy.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/burmy.wav b/sound/direct_sound_samples/cries/burmy.wav new file mode 100644 index 0000000000..6f8db1d2a4 Binary files /dev/null and b/sound/direct_sound_samples/cries/burmy.wav differ diff --git a/sound/direct_sound_samples/cries/butterfree.aif b/sound/direct_sound_samples/cries/butterfree.aif deleted file mode 100644 index e59865ae5a..0000000000 Binary files a/sound/direct_sound_samples/cries/butterfree.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/butterfree.wav b/sound/direct_sound_samples/cries/butterfree.wav new file mode 100644 index 0000000000..796a1afa9a Binary files /dev/null and b/sound/direct_sound_samples/cries/butterfree.wav differ diff --git a/sound/direct_sound_samples/cries/buzzwole.aif b/sound/direct_sound_samples/cries/buzzwole.aif deleted file mode 100644 index 242edabdce..0000000000 Binary files a/sound/direct_sound_samples/cries/buzzwole.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/buzzwole.wav b/sound/direct_sound_samples/cries/buzzwole.wav new file mode 100644 index 0000000000..69f4f7c1a0 Binary files /dev/null and b/sound/direct_sound_samples/cries/buzzwole.wav differ diff --git a/sound/direct_sound_samples/cries/cacnea.aif b/sound/direct_sound_samples/cries/cacnea.aif deleted file mode 100644 index 4d1771b18d..0000000000 Binary files a/sound/direct_sound_samples/cries/cacnea.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/cacnea.wav b/sound/direct_sound_samples/cries/cacnea.wav new file mode 100644 index 0000000000..b2786069b6 Binary files /dev/null and b/sound/direct_sound_samples/cries/cacnea.wav differ diff --git a/sound/direct_sound_samples/cries/cacturne.aif b/sound/direct_sound_samples/cries/cacturne.aif deleted file mode 100644 index d81f86d9fc..0000000000 Binary files a/sound/direct_sound_samples/cries/cacturne.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/cacturne.wav b/sound/direct_sound_samples/cries/cacturne.wav new file mode 100644 index 0000000000..34c4525227 Binary files /dev/null and b/sound/direct_sound_samples/cries/cacturne.wav differ diff --git a/sound/direct_sound_samples/cries/calyrex.aif b/sound/direct_sound_samples/cries/calyrex.aif deleted file mode 100644 index 59c41a4fdb..0000000000 Binary files a/sound/direct_sound_samples/cries/calyrex.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/calyrex.wav b/sound/direct_sound_samples/cries/calyrex.wav new file mode 100644 index 0000000000..365d22f27e Binary files /dev/null and b/sound/direct_sound_samples/cries/calyrex.wav differ diff --git a/sound/direct_sound_samples/cries/calyrex_ice.aif b/sound/direct_sound_samples/cries/calyrex_ice.aif deleted file mode 100644 index a6be291e1d..0000000000 Binary files a/sound/direct_sound_samples/cries/calyrex_ice.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/calyrex_ice.wav b/sound/direct_sound_samples/cries/calyrex_ice.wav new file mode 100644 index 0000000000..d1bb9330fe Binary files /dev/null and b/sound/direct_sound_samples/cries/calyrex_ice.wav differ diff --git a/sound/direct_sound_samples/cries/calyrex_shadow.aif b/sound/direct_sound_samples/cries/calyrex_shadow.aif deleted file mode 100644 index 2d3c43d978..0000000000 Binary files a/sound/direct_sound_samples/cries/calyrex_shadow.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/calyrex_shadow.wav b/sound/direct_sound_samples/cries/calyrex_shadow.wav new file mode 100644 index 0000000000..8c5fabed08 Binary files /dev/null and b/sound/direct_sound_samples/cries/calyrex_shadow.wav differ diff --git a/sound/direct_sound_samples/cries/camerupt.aif b/sound/direct_sound_samples/cries/camerupt.aif deleted file mode 100644 index 82a7f237cf..0000000000 Binary files a/sound/direct_sound_samples/cries/camerupt.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/camerupt.wav b/sound/direct_sound_samples/cries/camerupt.wav new file mode 100644 index 0000000000..95fdce3575 Binary files /dev/null and b/sound/direct_sound_samples/cries/camerupt.wav differ diff --git a/sound/direct_sound_samples/cries/camerupt_mega.aif b/sound/direct_sound_samples/cries/camerupt_mega.aif deleted file mode 100644 index 0c7966b8ea..0000000000 Binary files a/sound/direct_sound_samples/cries/camerupt_mega.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/camerupt_mega.wav b/sound/direct_sound_samples/cries/camerupt_mega.wav new file mode 100644 index 0000000000..b76cd2d974 Binary files /dev/null and b/sound/direct_sound_samples/cries/camerupt_mega.wav differ diff --git a/sound/direct_sound_samples/cries/capsakid.aif b/sound/direct_sound_samples/cries/capsakid.aif deleted file mode 100644 index a93a531cdb..0000000000 Binary files a/sound/direct_sound_samples/cries/capsakid.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/capsakid.wav b/sound/direct_sound_samples/cries/capsakid.wav new file mode 100644 index 0000000000..1a5837c9cd Binary files /dev/null and b/sound/direct_sound_samples/cries/capsakid.wav differ diff --git a/sound/direct_sound_samples/cries/carbink.aif b/sound/direct_sound_samples/cries/carbink.aif deleted file mode 100644 index dfdc907bd7..0000000000 Binary files a/sound/direct_sound_samples/cries/carbink.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/carbink.wav b/sound/direct_sound_samples/cries/carbink.wav new file mode 100644 index 0000000000..34ccc0db3b Binary files /dev/null and b/sound/direct_sound_samples/cries/carbink.wav differ diff --git a/sound/direct_sound_samples/cries/carkol.aif b/sound/direct_sound_samples/cries/carkol.aif deleted file mode 100644 index a1f19de7f4..0000000000 Binary files a/sound/direct_sound_samples/cries/carkol.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/carkol.wav b/sound/direct_sound_samples/cries/carkol.wav new file mode 100644 index 0000000000..526f8f473f Binary files /dev/null and b/sound/direct_sound_samples/cries/carkol.wav differ diff --git a/sound/direct_sound_samples/cries/carnivine.aif b/sound/direct_sound_samples/cries/carnivine.aif deleted file mode 100644 index 491e846a1a..0000000000 Binary files a/sound/direct_sound_samples/cries/carnivine.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/carnivine.wav b/sound/direct_sound_samples/cries/carnivine.wav new file mode 100644 index 0000000000..cdb7d8a358 Binary files /dev/null and b/sound/direct_sound_samples/cries/carnivine.wav differ diff --git a/sound/direct_sound_samples/cries/carracosta.aif b/sound/direct_sound_samples/cries/carracosta.aif deleted file mode 100644 index f75692c3a1..0000000000 Binary files a/sound/direct_sound_samples/cries/carracosta.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/carracosta.wav b/sound/direct_sound_samples/cries/carracosta.wav new file mode 100644 index 0000000000..4367ed1372 Binary files /dev/null and b/sound/direct_sound_samples/cries/carracosta.wav differ diff --git a/sound/direct_sound_samples/cries/carvanha.aif b/sound/direct_sound_samples/cries/carvanha.aif deleted file mode 100644 index 2c0a6a5d8c..0000000000 Binary files a/sound/direct_sound_samples/cries/carvanha.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/carvanha.wav b/sound/direct_sound_samples/cries/carvanha.wav new file mode 100644 index 0000000000..ae10c3b10c Binary files /dev/null and b/sound/direct_sound_samples/cries/carvanha.wav differ diff --git a/sound/direct_sound_samples/cries/cascoon.aif b/sound/direct_sound_samples/cries/cascoon.aif deleted file mode 100644 index a256131caf..0000000000 Binary files a/sound/direct_sound_samples/cries/cascoon.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/cascoon.wav b/sound/direct_sound_samples/cries/cascoon.wav new file mode 100644 index 0000000000..fff0be6815 Binary files /dev/null and b/sound/direct_sound_samples/cries/cascoon.wav differ diff --git a/sound/direct_sound_samples/cries/castform.aif b/sound/direct_sound_samples/cries/castform.aif deleted file mode 100644 index 4fce6e5075..0000000000 Binary files a/sound/direct_sound_samples/cries/castform.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/castform.wav b/sound/direct_sound_samples/cries/castform.wav new file mode 100644 index 0000000000..83748d45b8 Binary files /dev/null and b/sound/direct_sound_samples/cries/castform.wav differ diff --git a/sound/direct_sound_samples/cries/caterpie.aif b/sound/direct_sound_samples/cries/caterpie.aif deleted file mode 100644 index 4ce12c5fb7..0000000000 Binary files a/sound/direct_sound_samples/cries/caterpie.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/caterpie.wav b/sound/direct_sound_samples/cries/caterpie.wav new file mode 100644 index 0000000000..ccdf1ba1ac Binary files /dev/null and b/sound/direct_sound_samples/cries/caterpie.wav differ diff --git a/sound/direct_sound_samples/cries/celebi.aif b/sound/direct_sound_samples/cries/celebi.aif deleted file mode 100644 index df1c4cd195..0000000000 Binary files a/sound/direct_sound_samples/cries/celebi.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/celebi.wav b/sound/direct_sound_samples/cries/celebi.wav new file mode 100644 index 0000000000..e217a99e81 Binary files /dev/null and b/sound/direct_sound_samples/cries/celebi.wav differ diff --git a/sound/direct_sound_samples/cries/celesteela.aif b/sound/direct_sound_samples/cries/celesteela.aif deleted file mode 100644 index acab333235..0000000000 Binary files a/sound/direct_sound_samples/cries/celesteela.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/celesteela.wav b/sound/direct_sound_samples/cries/celesteela.wav new file mode 100644 index 0000000000..fd5cae47f9 Binary files /dev/null and b/sound/direct_sound_samples/cries/celesteela.wav differ diff --git a/sound/direct_sound_samples/cries/centiskorch.aif b/sound/direct_sound_samples/cries/centiskorch.aif deleted file mode 100644 index 01c6bc23a5..0000000000 Binary files a/sound/direct_sound_samples/cries/centiskorch.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/centiskorch.wav b/sound/direct_sound_samples/cries/centiskorch.wav new file mode 100644 index 0000000000..cc669c123f Binary files /dev/null and b/sound/direct_sound_samples/cries/centiskorch.wav differ diff --git a/sound/direct_sound_samples/cries/ceruledge.aif b/sound/direct_sound_samples/cries/ceruledge.aif deleted file mode 100644 index de4b1bb7c8..0000000000 Binary files a/sound/direct_sound_samples/cries/ceruledge.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/ceruledge.wav b/sound/direct_sound_samples/cries/ceruledge.wav new file mode 100644 index 0000000000..158bf548e0 Binary files /dev/null and b/sound/direct_sound_samples/cries/ceruledge.wav differ diff --git a/sound/direct_sound_samples/cries/cetitan.aif b/sound/direct_sound_samples/cries/cetitan.aif deleted file mode 100644 index 45302ff844..0000000000 Binary files a/sound/direct_sound_samples/cries/cetitan.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/cetitan.wav b/sound/direct_sound_samples/cries/cetitan.wav new file mode 100644 index 0000000000..9f6df2ec42 Binary files /dev/null and b/sound/direct_sound_samples/cries/cetitan.wav differ diff --git a/sound/direct_sound_samples/cries/cetoddle.aif b/sound/direct_sound_samples/cries/cetoddle.aif deleted file mode 100644 index f85f3d201f..0000000000 Binary files a/sound/direct_sound_samples/cries/cetoddle.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/cetoddle.wav b/sound/direct_sound_samples/cries/cetoddle.wav new file mode 100644 index 0000000000..93f34e1cf7 Binary files /dev/null and b/sound/direct_sound_samples/cries/cetoddle.wav differ diff --git a/sound/direct_sound_samples/cries/chandelure.aif b/sound/direct_sound_samples/cries/chandelure.aif deleted file mode 100644 index 29cd52e1c1..0000000000 Binary files a/sound/direct_sound_samples/cries/chandelure.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/chandelure.wav b/sound/direct_sound_samples/cries/chandelure.wav new file mode 100644 index 0000000000..2539f2c239 Binary files /dev/null and b/sound/direct_sound_samples/cries/chandelure.wav differ diff --git a/sound/direct_sound_samples/cries/chansey.aif b/sound/direct_sound_samples/cries/chansey.aif deleted file mode 100644 index b6a8a29020..0000000000 Binary files a/sound/direct_sound_samples/cries/chansey.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/chansey.wav b/sound/direct_sound_samples/cries/chansey.wav new file mode 100644 index 0000000000..62d8e6cd9f Binary files /dev/null and b/sound/direct_sound_samples/cries/chansey.wav differ diff --git a/sound/direct_sound_samples/cries/charcadet.aif b/sound/direct_sound_samples/cries/charcadet.aif deleted file mode 100644 index 60f5512ca6..0000000000 Binary files a/sound/direct_sound_samples/cries/charcadet.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/charcadet.wav b/sound/direct_sound_samples/cries/charcadet.wav new file mode 100644 index 0000000000..509e7b4968 Binary files /dev/null and b/sound/direct_sound_samples/cries/charcadet.wav differ diff --git a/sound/direct_sound_samples/cries/charizard.aif b/sound/direct_sound_samples/cries/charizard.aif deleted file mode 100644 index cc5f2bdd33..0000000000 Binary files a/sound/direct_sound_samples/cries/charizard.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/charizard.wav b/sound/direct_sound_samples/cries/charizard.wav new file mode 100644 index 0000000000..fbbf3c555d Binary files /dev/null and b/sound/direct_sound_samples/cries/charizard.wav differ diff --git a/sound/direct_sound_samples/cries/charizard_mega_x.aif b/sound/direct_sound_samples/cries/charizard_mega_x.aif deleted file mode 100644 index f9c0f76597..0000000000 Binary files a/sound/direct_sound_samples/cries/charizard_mega_x.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/charizard_mega_x.wav b/sound/direct_sound_samples/cries/charizard_mega_x.wav new file mode 100644 index 0000000000..053f05caad Binary files /dev/null and b/sound/direct_sound_samples/cries/charizard_mega_x.wav differ diff --git a/sound/direct_sound_samples/cries/charizard_mega_y.aif b/sound/direct_sound_samples/cries/charizard_mega_y.aif deleted file mode 100644 index 2cf5b3ea7f..0000000000 Binary files a/sound/direct_sound_samples/cries/charizard_mega_y.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/charizard_mega_y.wav b/sound/direct_sound_samples/cries/charizard_mega_y.wav new file mode 100644 index 0000000000..1d354bb938 Binary files /dev/null and b/sound/direct_sound_samples/cries/charizard_mega_y.wav differ diff --git a/sound/direct_sound_samples/cries/charjabug.aif b/sound/direct_sound_samples/cries/charjabug.aif deleted file mode 100644 index ed5bd7d88b..0000000000 Binary files a/sound/direct_sound_samples/cries/charjabug.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/charjabug.wav b/sound/direct_sound_samples/cries/charjabug.wav new file mode 100644 index 0000000000..686e72aa6f Binary files /dev/null and b/sound/direct_sound_samples/cries/charjabug.wav differ diff --git a/sound/direct_sound_samples/cries/charmander.aif b/sound/direct_sound_samples/cries/charmander.aif deleted file mode 100644 index dda65af549..0000000000 Binary files a/sound/direct_sound_samples/cries/charmander.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/charmander.wav b/sound/direct_sound_samples/cries/charmander.wav new file mode 100644 index 0000000000..3d82aca2fa Binary files /dev/null and b/sound/direct_sound_samples/cries/charmander.wav differ diff --git a/sound/direct_sound_samples/cries/charmeleon.aif b/sound/direct_sound_samples/cries/charmeleon.aif deleted file mode 100644 index 9a9a14e3bb..0000000000 Binary files a/sound/direct_sound_samples/cries/charmeleon.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/charmeleon.wav b/sound/direct_sound_samples/cries/charmeleon.wav new file mode 100644 index 0000000000..a491f0586e Binary files /dev/null and b/sound/direct_sound_samples/cries/charmeleon.wav differ diff --git a/sound/direct_sound_samples/cries/chatot.aif b/sound/direct_sound_samples/cries/chatot.aif deleted file mode 100644 index 62a961a82f..0000000000 Binary files a/sound/direct_sound_samples/cries/chatot.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/chatot.wav b/sound/direct_sound_samples/cries/chatot.wav new file mode 100644 index 0000000000..5f76a91472 Binary files /dev/null and b/sound/direct_sound_samples/cries/chatot.wav differ diff --git a/sound/direct_sound_samples/cries/cherrim.aif b/sound/direct_sound_samples/cries/cherrim.aif deleted file mode 100644 index d70cf77b02..0000000000 Binary files a/sound/direct_sound_samples/cries/cherrim.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/cherrim.wav b/sound/direct_sound_samples/cries/cherrim.wav new file mode 100644 index 0000000000..ca0dc7a4c0 Binary files /dev/null and b/sound/direct_sound_samples/cries/cherrim.wav differ diff --git a/sound/direct_sound_samples/cries/cherubi.aif b/sound/direct_sound_samples/cries/cherubi.aif deleted file mode 100644 index 703c1d5f8b..0000000000 Binary files a/sound/direct_sound_samples/cries/cherubi.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/cherubi.wav b/sound/direct_sound_samples/cries/cherubi.wav new file mode 100644 index 0000000000..2a87affb57 Binary files /dev/null and b/sound/direct_sound_samples/cries/cherubi.wav differ diff --git a/sound/direct_sound_samples/cries/chesnaught.aif b/sound/direct_sound_samples/cries/chesnaught.aif deleted file mode 100644 index 80cff83698..0000000000 Binary files a/sound/direct_sound_samples/cries/chesnaught.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/chesnaught.wav b/sound/direct_sound_samples/cries/chesnaught.wav new file mode 100644 index 0000000000..27044e80a4 Binary files /dev/null and b/sound/direct_sound_samples/cries/chesnaught.wav differ diff --git a/sound/direct_sound_samples/cries/chespin.aif b/sound/direct_sound_samples/cries/chespin.aif deleted file mode 100644 index 48136a98a0..0000000000 Binary files a/sound/direct_sound_samples/cries/chespin.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/chespin.wav b/sound/direct_sound_samples/cries/chespin.wav new file mode 100644 index 0000000000..5e5f5a7c6a Binary files /dev/null and b/sound/direct_sound_samples/cries/chespin.wav differ diff --git a/sound/direct_sound_samples/cries/chewtle.aif b/sound/direct_sound_samples/cries/chewtle.aif deleted file mode 100644 index d551d27156..0000000000 Binary files a/sound/direct_sound_samples/cries/chewtle.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/chewtle.wav b/sound/direct_sound_samples/cries/chewtle.wav new file mode 100644 index 0000000000..a9f609dc4c Binary files /dev/null and b/sound/direct_sound_samples/cries/chewtle.wav differ diff --git a/sound/direct_sound_samples/cries/chi_yu.aif b/sound/direct_sound_samples/cries/chi_yu.aif deleted file mode 100644 index 60131a9e46..0000000000 Binary files a/sound/direct_sound_samples/cries/chi_yu.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/chi_yu.wav b/sound/direct_sound_samples/cries/chi_yu.wav new file mode 100644 index 0000000000..8db88a2de6 Binary files /dev/null and b/sound/direct_sound_samples/cries/chi_yu.wav differ diff --git a/sound/direct_sound_samples/cries/chien_pao.aif b/sound/direct_sound_samples/cries/chien_pao.aif deleted file mode 100644 index c598dac8d2..0000000000 Binary files a/sound/direct_sound_samples/cries/chien_pao.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/chien_pao.wav b/sound/direct_sound_samples/cries/chien_pao.wav new file mode 100644 index 0000000000..2575663d5d Binary files /dev/null and b/sound/direct_sound_samples/cries/chien_pao.wav differ diff --git a/sound/direct_sound_samples/cries/chikorita.aif b/sound/direct_sound_samples/cries/chikorita.aif deleted file mode 100644 index 63d5c95033..0000000000 Binary files a/sound/direct_sound_samples/cries/chikorita.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/chikorita.wav b/sound/direct_sound_samples/cries/chikorita.wav new file mode 100644 index 0000000000..65cb0c1765 Binary files /dev/null and b/sound/direct_sound_samples/cries/chikorita.wav differ diff --git a/sound/direct_sound_samples/cries/chimchar.aif b/sound/direct_sound_samples/cries/chimchar.aif deleted file mode 100644 index 06514a4d90..0000000000 Binary files a/sound/direct_sound_samples/cries/chimchar.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/chimchar.wav b/sound/direct_sound_samples/cries/chimchar.wav new file mode 100644 index 0000000000..cd862e218a Binary files /dev/null and b/sound/direct_sound_samples/cries/chimchar.wav differ diff --git a/sound/direct_sound_samples/cries/chimecho.aif b/sound/direct_sound_samples/cries/chimecho.aif deleted file mode 100644 index 7b2b45fac2..0000000000 Binary files a/sound/direct_sound_samples/cries/chimecho.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/chimecho.wav b/sound/direct_sound_samples/cries/chimecho.wav new file mode 100644 index 0000000000..a063bf739e Binary files /dev/null and b/sound/direct_sound_samples/cries/chimecho.wav differ diff --git a/sound/direct_sound_samples/cries/chinchou.aif b/sound/direct_sound_samples/cries/chinchou.aif deleted file mode 100644 index 846df5079c..0000000000 Binary files a/sound/direct_sound_samples/cries/chinchou.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/chinchou.wav b/sound/direct_sound_samples/cries/chinchou.wav new file mode 100644 index 0000000000..8822996828 Binary files /dev/null and b/sound/direct_sound_samples/cries/chinchou.wav differ diff --git a/sound/direct_sound_samples/cries/chingling.aif b/sound/direct_sound_samples/cries/chingling.aif deleted file mode 100644 index dd3b00915b..0000000000 Binary files a/sound/direct_sound_samples/cries/chingling.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/chingling.wav b/sound/direct_sound_samples/cries/chingling.wav new file mode 100644 index 0000000000..af4d305106 Binary files /dev/null and b/sound/direct_sound_samples/cries/chingling.wav differ diff --git a/sound/direct_sound_samples/cries/cinccino.aif b/sound/direct_sound_samples/cries/cinccino.aif deleted file mode 100644 index 6205aaf2b0..0000000000 Binary files a/sound/direct_sound_samples/cries/cinccino.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/cinccino.wav b/sound/direct_sound_samples/cries/cinccino.wav new file mode 100644 index 0000000000..beb20a3ce0 Binary files /dev/null and b/sound/direct_sound_samples/cries/cinccino.wav differ diff --git a/sound/direct_sound_samples/cries/cinderace.aif b/sound/direct_sound_samples/cries/cinderace.aif deleted file mode 100644 index 1e7bed5bfd..0000000000 Binary files a/sound/direct_sound_samples/cries/cinderace.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/cinderace.wav b/sound/direct_sound_samples/cries/cinderace.wav new file mode 100644 index 0000000000..01caaae4d6 Binary files /dev/null and b/sound/direct_sound_samples/cries/cinderace.wav differ diff --git a/sound/direct_sound_samples/cries/clamperl.aif b/sound/direct_sound_samples/cries/clamperl.aif deleted file mode 100644 index 186a1f9b40..0000000000 Binary files a/sound/direct_sound_samples/cries/clamperl.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/clamperl.wav b/sound/direct_sound_samples/cries/clamperl.wav new file mode 100644 index 0000000000..6615de8779 Binary files /dev/null and b/sound/direct_sound_samples/cries/clamperl.wav differ diff --git a/sound/direct_sound_samples/cries/clauncher.aif b/sound/direct_sound_samples/cries/clauncher.aif deleted file mode 100644 index ab9cbf9ce1..0000000000 Binary files a/sound/direct_sound_samples/cries/clauncher.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/clauncher.wav b/sound/direct_sound_samples/cries/clauncher.wav new file mode 100644 index 0000000000..19a07f395a Binary files /dev/null and b/sound/direct_sound_samples/cries/clauncher.wav differ diff --git a/sound/direct_sound_samples/cries/clawitzer.aif b/sound/direct_sound_samples/cries/clawitzer.aif deleted file mode 100644 index bd14270c38..0000000000 Binary files a/sound/direct_sound_samples/cries/clawitzer.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/clawitzer.wav b/sound/direct_sound_samples/cries/clawitzer.wav new file mode 100644 index 0000000000..7947944ace Binary files /dev/null and b/sound/direct_sound_samples/cries/clawitzer.wav differ diff --git a/sound/direct_sound_samples/cries/claydol.aif b/sound/direct_sound_samples/cries/claydol.aif deleted file mode 100644 index 9da5f5bbb7..0000000000 Binary files a/sound/direct_sound_samples/cries/claydol.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/claydol.wav b/sound/direct_sound_samples/cries/claydol.wav new file mode 100644 index 0000000000..037a9a4063 Binary files /dev/null and b/sound/direct_sound_samples/cries/claydol.wav differ diff --git a/sound/direct_sound_samples/cries/clefable.aif b/sound/direct_sound_samples/cries/clefable.aif deleted file mode 100644 index e04bf536ad..0000000000 Binary files a/sound/direct_sound_samples/cries/clefable.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/clefable.wav b/sound/direct_sound_samples/cries/clefable.wav new file mode 100644 index 0000000000..09b0d19b86 Binary files /dev/null and b/sound/direct_sound_samples/cries/clefable.wav differ diff --git a/sound/direct_sound_samples/cries/clefairy.aif b/sound/direct_sound_samples/cries/clefairy.aif deleted file mode 100644 index b38fa6e9d7..0000000000 Binary files a/sound/direct_sound_samples/cries/clefairy.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/clefairy.wav b/sound/direct_sound_samples/cries/clefairy.wav new file mode 100644 index 0000000000..b447b700cd Binary files /dev/null and b/sound/direct_sound_samples/cries/clefairy.wav differ diff --git a/sound/direct_sound_samples/cries/cleffa.aif b/sound/direct_sound_samples/cries/cleffa.aif deleted file mode 100644 index e3243d0998..0000000000 Binary files a/sound/direct_sound_samples/cries/cleffa.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/cleffa.wav b/sound/direct_sound_samples/cries/cleffa.wav new file mode 100644 index 0000000000..53d18df415 Binary files /dev/null and b/sound/direct_sound_samples/cries/cleffa.wav differ diff --git a/sound/direct_sound_samples/cries/clobbopus.aif b/sound/direct_sound_samples/cries/clobbopus.aif deleted file mode 100644 index ebce642966..0000000000 Binary files a/sound/direct_sound_samples/cries/clobbopus.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/clobbopus.wav b/sound/direct_sound_samples/cries/clobbopus.wav new file mode 100644 index 0000000000..f26d8c1cdd Binary files /dev/null and b/sound/direct_sound_samples/cries/clobbopus.wav differ diff --git a/sound/direct_sound_samples/cries/clodsire.aif b/sound/direct_sound_samples/cries/clodsire.aif deleted file mode 100644 index 17aea97e46..0000000000 Binary files a/sound/direct_sound_samples/cries/clodsire.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/clodsire.wav b/sound/direct_sound_samples/cries/clodsire.wav new file mode 100644 index 0000000000..44cad4cb71 Binary files /dev/null and b/sound/direct_sound_samples/cries/clodsire.wav differ diff --git a/sound/direct_sound_samples/cries/cloyster.aif b/sound/direct_sound_samples/cries/cloyster.aif deleted file mode 100644 index b69d0478bf..0000000000 Binary files a/sound/direct_sound_samples/cries/cloyster.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/cloyster.wav b/sound/direct_sound_samples/cries/cloyster.wav new file mode 100644 index 0000000000..4fc766ae19 Binary files /dev/null and b/sound/direct_sound_samples/cries/cloyster.wav differ diff --git a/sound/direct_sound_samples/cries/coalossal.aif b/sound/direct_sound_samples/cries/coalossal.aif deleted file mode 100644 index 5d62b25fba..0000000000 Binary files a/sound/direct_sound_samples/cries/coalossal.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/coalossal.wav b/sound/direct_sound_samples/cries/coalossal.wav new file mode 100644 index 0000000000..7b2a758d23 Binary files /dev/null and b/sound/direct_sound_samples/cries/coalossal.wav differ diff --git a/sound/direct_sound_samples/cries/cobalion.aif b/sound/direct_sound_samples/cries/cobalion.aif deleted file mode 100644 index 4a21505b5b..0000000000 Binary files a/sound/direct_sound_samples/cries/cobalion.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/cobalion.wav b/sound/direct_sound_samples/cries/cobalion.wav new file mode 100644 index 0000000000..2cbc6bbd55 Binary files /dev/null and b/sound/direct_sound_samples/cries/cobalion.wav differ diff --git a/sound/direct_sound_samples/cries/cofagrigus.aif b/sound/direct_sound_samples/cries/cofagrigus.aif deleted file mode 100644 index 6fbf1c16f8..0000000000 Binary files a/sound/direct_sound_samples/cries/cofagrigus.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/cofagrigus.wav b/sound/direct_sound_samples/cries/cofagrigus.wav new file mode 100644 index 0000000000..2096837cd9 Binary files /dev/null and b/sound/direct_sound_samples/cries/cofagrigus.wav differ diff --git a/sound/direct_sound_samples/cries/combee.aif b/sound/direct_sound_samples/cries/combee.aif deleted file mode 100644 index 6aaedb642d..0000000000 Binary files a/sound/direct_sound_samples/cries/combee.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/combee.wav b/sound/direct_sound_samples/cries/combee.wav new file mode 100644 index 0000000000..d2e370227e Binary files /dev/null and b/sound/direct_sound_samples/cries/combee.wav differ diff --git a/sound/direct_sound_samples/cries/combusken.aif b/sound/direct_sound_samples/cries/combusken.aif deleted file mode 100644 index 58707c30b8..0000000000 Binary files a/sound/direct_sound_samples/cries/combusken.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/combusken.wav b/sound/direct_sound_samples/cries/combusken.wav new file mode 100644 index 0000000000..8da9de64a1 Binary files /dev/null and b/sound/direct_sound_samples/cries/combusken.wav differ diff --git a/sound/direct_sound_samples/cries/comfey.aif b/sound/direct_sound_samples/cries/comfey.aif deleted file mode 100644 index cb91d0cbd7..0000000000 Binary files a/sound/direct_sound_samples/cries/comfey.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/comfey.wav b/sound/direct_sound_samples/cries/comfey.wav new file mode 100644 index 0000000000..b178f02a69 Binary files /dev/null and b/sound/direct_sound_samples/cries/comfey.wav differ diff --git a/sound/direct_sound_samples/cries/conkeldurr.aif b/sound/direct_sound_samples/cries/conkeldurr.aif deleted file mode 100644 index 09885ab2ef..0000000000 Binary files a/sound/direct_sound_samples/cries/conkeldurr.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/conkeldurr.wav b/sound/direct_sound_samples/cries/conkeldurr.wav new file mode 100644 index 0000000000..fa56aac5e9 Binary files /dev/null and b/sound/direct_sound_samples/cries/conkeldurr.wav differ diff --git a/sound/direct_sound_samples/cries/copperajah.aif b/sound/direct_sound_samples/cries/copperajah.aif deleted file mode 100644 index 97484e695b..0000000000 Binary files a/sound/direct_sound_samples/cries/copperajah.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/copperajah.wav b/sound/direct_sound_samples/cries/copperajah.wav new file mode 100644 index 0000000000..23df3fd99c Binary files /dev/null and b/sound/direct_sound_samples/cries/copperajah.wav differ diff --git a/sound/direct_sound_samples/cries/corphish.aif b/sound/direct_sound_samples/cries/corphish.aif deleted file mode 100644 index 9bc708e2fb..0000000000 Binary files a/sound/direct_sound_samples/cries/corphish.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/corphish.wav b/sound/direct_sound_samples/cries/corphish.wav new file mode 100644 index 0000000000..990029d333 Binary files /dev/null and b/sound/direct_sound_samples/cries/corphish.wav differ diff --git a/sound/direct_sound_samples/cries/corsola.aif b/sound/direct_sound_samples/cries/corsola.aif deleted file mode 100644 index 087308d8fd..0000000000 Binary files a/sound/direct_sound_samples/cries/corsola.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/corsola.wav b/sound/direct_sound_samples/cries/corsola.wav new file mode 100644 index 0000000000..890208bc73 Binary files /dev/null and b/sound/direct_sound_samples/cries/corsola.wav differ diff --git a/sound/direct_sound_samples/cries/corviknight.aif b/sound/direct_sound_samples/cries/corviknight.aif deleted file mode 100644 index 8a7e200da3..0000000000 Binary files a/sound/direct_sound_samples/cries/corviknight.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/corviknight.wav b/sound/direct_sound_samples/cries/corviknight.wav new file mode 100644 index 0000000000..2f536e1280 Binary files /dev/null and b/sound/direct_sound_samples/cries/corviknight.wav differ diff --git a/sound/direct_sound_samples/cries/corvisquire.aif b/sound/direct_sound_samples/cries/corvisquire.aif deleted file mode 100644 index a18e64c9c0..0000000000 Binary files a/sound/direct_sound_samples/cries/corvisquire.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/corvisquire.wav b/sound/direct_sound_samples/cries/corvisquire.wav new file mode 100644 index 0000000000..b0600991c0 Binary files /dev/null and b/sound/direct_sound_samples/cries/corvisquire.wav differ diff --git a/sound/direct_sound_samples/cries/cosmoem.aif b/sound/direct_sound_samples/cries/cosmoem.aif deleted file mode 100644 index f2c8c0e2b4..0000000000 Binary files a/sound/direct_sound_samples/cries/cosmoem.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/cosmoem.wav b/sound/direct_sound_samples/cries/cosmoem.wav new file mode 100644 index 0000000000..8f9523bced Binary files /dev/null and b/sound/direct_sound_samples/cries/cosmoem.wav differ diff --git a/sound/direct_sound_samples/cries/cosmog.aif b/sound/direct_sound_samples/cries/cosmog.aif deleted file mode 100644 index deeb60b94d..0000000000 Binary files a/sound/direct_sound_samples/cries/cosmog.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/cosmog.wav b/sound/direct_sound_samples/cries/cosmog.wav new file mode 100644 index 0000000000..c52927d1b0 Binary files /dev/null and b/sound/direct_sound_samples/cries/cosmog.wav differ diff --git a/sound/direct_sound_samples/cries/cottonee.aif b/sound/direct_sound_samples/cries/cottonee.aif deleted file mode 100644 index 207ac9d12d..0000000000 Binary files a/sound/direct_sound_samples/cries/cottonee.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/cottonee.wav b/sound/direct_sound_samples/cries/cottonee.wav new file mode 100644 index 0000000000..a7c0e6ce5b Binary files /dev/null and b/sound/direct_sound_samples/cries/cottonee.wav differ diff --git a/sound/direct_sound_samples/cries/crabominable.aif b/sound/direct_sound_samples/cries/crabominable.aif deleted file mode 100644 index 1d6b3d4caf..0000000000 Binary files a/sound/direct_sound_samples/cries/crabominable.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/crabominable.wav b/sound/direct_sound_samples/cries/crabominable.wav new file mode 100644 index 0000000000..ca783994b8 Binary files /dev/null and b/sound/direct_sound_samples/cries/crabominable.wav differ diff --git a/sound/direct_sound_samples/cries/crabrawler.aif b/sound/direct_sound_samples/cries/crabrawler.aif deleted file mode 100644 index 8c42fb18e5..0000000000 Binary files a/sound/direct_sound_samples/cries/crabrawler.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/crabrawler.wav b/sound/direct_sound_samples/cries/crabrawler.wav new file mode 100644 index 0000000000..b5afae8c1d Binary files /dev/null and b/sound/direct_sound_samples/cries/crabrawler.wav differ diff --git a/sound/direct_sound_samples/cries/cradily.aif b/sound/direct_sound_samples/cries/cradily.aif deleted file mode 100644 index 3fa5e006f9..0000000000 Binary files a/sound/direct_sound_samples/cries/cradily.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/cradily.wav b/sound/direct_sound_samples/cries/cradily.wav new file mode 100644 index 0000000000..bb9d5bd425 Binary files /dev/null and b/sound/direct_sound_samples/cries/cradily.wav differ diff --git a/sound/direct_sound_samples/cries/cramorant.aif b/sound/direct_sound_samples/cries/cramorant.aif deleted file mode 100644 index 01151693ff..0000000000 Binary files a/sound/direct_sound_samples/cries/cramorant.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/cramorant.wav b/sound/direct_sound_samples/cries/cramorant.wav new file mode 100644 index 0000000000..a21c49b1c4 Binary files /dev/null and b/sound/direct_sound_samples/cries/cramorant.wav differ diff --git a/sound/direct_sound_samples/cries/cranidos.aif b/sound/direct_sound_samples/cries/cranidos.aif deleted file mode 100644 index dc67035a76..0000000000 Binary files a/sound/direct_sound_samples/cries/cranidos.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/cranidos.wav b/sound/direct_sound_samples/cries/cranidos.wav new file mode 100644 index 0000000000..5ceba87269 Binary files /dev/null and b/sound/direct_sound_samples/cries/cranidos.wav differ diff --git a/sound/direct_sound_samples/cries/crawdaunt.aif b/sound/direct_sound_samples/cries/crawdaunt.aif deleted file mode 100644 index 7f8ee48beb..0000000000 Binary files a/sound/direct_sound_samples/cries/crawdaunt.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/crawdaunt.wav b/sound/direct_sound_samples/cries/crawdaunt.wav new file mode 100644 index 0000000000..e270a31791 Binary files /dev/null and b/sound/direct_sound_samples/cries/crawdaunt.wav differ diff --git a/sound/direct_sound_samples/cries/cresselia.aif b/sound/direct_sound_samples/cries/cresselia.aif deleted file mode 100644 index 5edd1b0194..0000000000 Binary files a/sound/direct_sound_samples/cries/cresselia.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/cresselia.wav b/sound/direct_sound_samples/cries/cresselia.wav new file mode 100644 index 0000000000..dd73997250 Binary files /dev/null and b/sound/direct_sound_samples/cries/cresselia.wav differ diff --git a/sound/direct_sound_samples/cries/croagunk.aif b/sound/direct_sound_samples/cries/croagunk.aif deleted file mode 100644 index c5d42a42bf..0000000000 Binary files a/sound/direct_sound_samples/cries/croagunk.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/croagunk.wav b/sound/direct_sound_samples/cries/croagunk.wav new file mode 100644 index 0000000000..f3935f1b85 Binary files /dev/null and b/sound/direct_sound_samples/cries/croagunk.wav differ diff --git a/sound/direct_sound_samples/cries/crobat.aif b/sound/direct_sound_samples/cries/crobat.aif deleted file mode 100644 index 956be378c7..0000000000 Binary files a/sound/direct_sound_samples/cries/crobat.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/crobat.wav b/sound/direct_sound_samples/cries/crobat.wav new file mode 100644 index 0000000000..fdad8d4a63 Binary files /dev/null and b/sound/direct_sound_samples/cries/crobat.wav differ diff --git a/sound/direct_sound_samples/cries/crocalor.aif b/sound/direct_sound_samples/cries/crocalor.aif deleted file mode 100644 index 9a622026df..0000000000 Binary files a/sound/direct_sound_samples/cries/crocalor.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/crocalor.wav b/sound/direct_sound_samples/cries/crocalor.wav new file mode 100644 index 0000000000..17cba90fd9 Binary files /dev/null and b/sound/direct_sound_samples/cries/crocalor.wav differ diff --git a/sound/direct_sound_samples/cries/croconaw.aif b/sound/direct_sound_samples/cries/croconaw.aif deleted file mode 100644 index b72db75f3f..0000000000 Binary files a/sound/direct_sound_samples/cries/croconaw.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/croconaw.wav b/sound/direct_sound_samples/cries/croconaw.wav new file mode 100644 index 0000000000..deb2a70035 Binary files /dev/null and b/sound/direct_sound_samples/cries/croconaw.wav differ diff --git a/sound/direct_sound_samples/cries/crustle.aif b/sound/direct_sound_samples/cries/crustle.aif deleted file mode 100644 index 62014a79c8..0000000000 Binary files a/sound/direct_sound_samples/cries/crustle.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/crustle.wav b/sound/direct_sound_samples/cries/crustle.wav new file mode 100644 index 0000000000..6e1388bad8 Binary files /dev/null and b/sound/direct_sound_samples/cries/crustle.wav differ diff --git a/sound/direct_sound_samples/cries/cry_unused_265.aif b/sound/direct_sound_samples/cries/cry_unused_265.aif deleted file mode 100644 index 7f5965f06b..0000000000 Binary files a/sound/direct_sound_samples/cries/cry_unused_265.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/cry_unused_268.aif b/sound/direct_sound_samples/cries/cry_unused_268.aif deleted file mode 100644 index 5cae364c38..0000000000 Binary files a/sound/direct_sound_samples/cries/cry_unused_268.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/cryogonal.aif b/sound/direct_sound_samples/cries/cryogonal.aif deleted file mode 100644 index b2f551274e..0000000000 Binary files a/sound/direct_sound_samples/cries/cryogonal.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/cryogonal.wav b/sound/direct_sound_samples/cries/cryogonal.wav new file mode 100644 index 0000000000..22f6b994db Binary files /dev/null and b/sound/direct_sound_samples/cries/cryogonal.wav differ diff --git a/sound/direct_sound_samples/cries/cubchoo.aif b/sound/direct_sound_samples/cries/cubchoo.aif deleted file mode 100644 index e10ca5a0cc..0000000000 Binary files a/sound/direct_sound_samples/cries/cubchoo.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/cubchoo.wav b/sound/direct_sound_samples/cries/cubchoo.wav new file mode 100644 index 0000000000..5bbe309951 Binary files /dev/null and b/sound/direct_sound_samples/cries/cubchoo.wav differ diff --git a/sound/direct_sound_samples/cries/cubone.aif b/sound/direct_sound_samples/cries/cubone.aif deleted file mode 100644 index 1ebc283ef8..0000000000 Binary files a/sound/direct_sound_samples/cries/cubone.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/cubone.wav b/sound/direct_sound_samples/cries/cubone.wav new file mode 100644 index 0000000000..b198c25403 Binary files /dev/null and b/sound/direct_sound_samples/cries/cubone.wav differ diff --git a/sound/direct_sound_samples/cries/cufant.aif b/sound/direct_sound_samples/cries/cufant.aif deleted file mode 100644 index 9f8f55b245..0000000000 Binary files a/sound/direct_sound_samples/cries/cufant.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/cufant.wav b/sound/direct_sound_samples/cries/cufant.wav new file mode 100644 index 0000000000..a9cb12d5ed Binary files /dev/null and b/sound/direct_sound_samples/cries/cufant.wav differ diff --git a/sound/direct_sound_samples/cries/cursola.aif b/sound/direct_sound_samples/cries/cursola.aif deleted file mode 100644 index 1bdba8731a..0000000000 Binary files a/sound/direct_sound_samples/cries/cursola.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/cursola.wav b/sound/direct_sound_samples/cries/cursola.wav new file mode 100644 index 0000000000..076aed18f5 Binary files /dev/null and b/sound/direct_sound_samples/cries/cursola.wav differ diff --git a/sound/direct_sound_samples/cries/cutiefly.aif b/sound/direct_sound_samples/cries/cutiefly.aif deleted file mode 100644 index 61535bbdd8..0000000000 Binary files a/sound/direct_sound_samples/cries/cutiefly.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/cutiefly.wav b/sound/direct_sound_samples/cries/cutiefly.wav new file mode 100644 index 0000000000..612b06dc22 Binary files /dev/null and b/sound/direct_sound_samples/cries/cutiefly.wav differ diff --git a/sound/direct_sound_samples/cries/cyclizar.aif b/sound/direct_sound_samples/cries/cyclizar.aif deleted file mode 100644 index eb32c91d59..0000000000 Binary files a/sound/direct_sound_samples/cries/cyclizar.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/cyclizar.wav b/sound/direct_sound_samples/cries/cyclizar.wav new file mode 100644 index 0000000000..324dcbda08 Binary files /dev/null and b/sound/direct_sound_samples/cries/cyclizar.wav differ diff --git a/sound/direct_sound_samples/cries/cyndaquil.aif b/sound/direct_sound_samples/cries/cyndaquil.aif deleted file mode 100644 index 287c6496ad..0000000000 Binary files a/sound/direct_sound_samples/cries/cyndaquil.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/cyndaquil.wav b/sound/direct_sound_samples/cries/cyndaquil.wav new file mode 100644 index 0000000000..87921c52eb Binary files /dev/null and b/sound/direct_sound_samples/cries/cyndaquil.wav differ diff --git a/sound/direct_sound_samples/cries/dachsbun.aif b/sound/direct_sound_samples/cries/dachsbun.aif deleted file mode 100644 index 8e3ddbd781..0000000000 Binary files a/sound/direct_sound_samples/cries/dachsbun.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/dachsbun.wav b/sound/direct_sound_samples/cries/dachsbun.wav new file mode 100644 index 0000000000..870cb99aee Binary files /dev/null and b/sound/direct_sound_samples/cries/dachsbun.wav differ diff --git a/sound/direct_sound_samples/cries/darkrai.aif b/sound/direct_sound_samples/cries/darkrai.aif deleted file mode 100644 index bfb37fca5b..0000000000 Binary files a/sound/direct_sound_samples/cries/darkrai.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/darkrai.wav b/sound/direct_sound_samples/cries/darkrai.wav new file mode 100644 index 0000000000..3ff71721d5 Binary files /dev/null and b/sound/direct_sound_samples/cries/darkrai.wav differ diff --git a/sound/direct_sound_samples/cries/darmanitan.aif b/sound/direct_sound_samples/cries/darmanitan.aif deleted file mode 100644 index 902fdb69b4..0000000000 Binary files a/sound/direct_sound_samples/cries/darmanitan.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/darmanitan.wav b/sound/direct_sound_samples/cries/darmanitan.wav new file mode 100644 index 0000000000..c39aafe52e Binary files /dev/null and b/sound/direct_sound_samples/cries/darmanitan.wav differ diff --git a/sound/direct_sound_samples/cries/dartrix.aif b/sound/direct_sound_samples/cries/dartrix.aif deleted file mode 100644 index 894fefb331..0000000000 Binary files a/sound/direct_sound_samples/cries/dartrix.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/dartrix.wav b/sound/direct_sound_samples/cries/dartrix.wav new file mode 100644 index 0000000000..ac4ef1cfa7 Binary files /dev/null and b/sound/direct_sound_samples/cries/dartrix.wav differ diff --git a/sound/direct_sound_samples/cries/darumaka.aif b/sound/direct_sound_samples/cries/darumaka.aif deleted file mode 100644 index 849f0f1dab..0000000000 Binary files a/sound/direct_sound_samples/cries/darumaka.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/darumaka.wav b/sound/direct_sound_samples/cries/darumaka.wav new file mode 100644 index 0000000000..f0feff8958 Binary files /dev/null and b/sound/direct_sound_samples/cries/darumaka.wav differ diff --git a/sound/direct_sound_samples/cries/decidueye.aif b/sound/direct_sound_samples/cries/decidueye.aif deleted file mode 100644 index dde3a574a9..0000000000 Binary files a/sound/direct_sound_samples/cries/decidueye.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/decidueye.wav b/sound/direct_sound_samples/cries/decidueye.wav new file mode 100644 index 0000000000..df44f57bc0 Binary files /dev/null and b/sound/direct_sound_samples/cries/decidueye.wav differ diff --git a/sound/direct_sound_samples/cries/dedenne.aif b/sound/direct_sound_samples/cries/dedenne.aif deleted file mode 100644 index 843f5cf38f..0000000000 Binary files a/sound/direct_sound_samples/cries/dedenne.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/dedenne.wav b/sound/direct_sound_samples/cries/dedenne.wav new file mode 100644 index 0000000000..8b2472660b Binary files /dev/null and b/sound/direct_sound_samples/cries/dedenne.wav differ diff --git a/sound/direct_sound_samples/cries/deerling.aif b/sound/direct_sound_samples/cries/deerling.aif deleted file mode 100644 index 9a4e8809b9..0000000000 Binary files a/sound/direct_sound_samples/cries/deerling.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/deerling.wav b/sound/direct_sound_samples/cries/deerling.wav new file mode 100644 index 0000000000..655c5916c3 Binary files /dev/null and b/sound/direct_sound_samples/cries/deerling.wav differ diff --git a/sound/direct_sound_samples/cries/deino.aif b/sound/direct_sound_samples/cries/deino.aif deleted file mode 100644 index e5074d0821..0000000000 Binary files a/sound/direct_sound_samples/cries/deino.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/deino.wav b/sound/direct_sound_samples/cries/deino.wav new file mode 100644 index 0000000000..f13aab187c Binary files /dev/null and b/sound/direct_sound_samples/cries/deino.wav differ diff --git a/sound/direct_sound_samples/cries/delcatty.aif b/sound/direct_sound_samples/cries/delcatty.aif deleted file mode 100644 index d4fe6c5c59..0000000000 Binary files a/sound/direct_sound_samples/cries/delcatty.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/delcatty.wav b/sound/direct_sound_samples/cries/delcatty.wav new file mode 100644 index 0000000000..dce5e73b7a Binary files /dev/null and b/sound/direct_sound_samples/cries/delcatty.wav differ diff --git a/sound/direct_sound_samples/cries/delibird.aif b/sound/direct_sound_samples/cries/delibird.aif deleted file mode 100644 index f2e0d44642..0000000000 Binary files a/sound/direct_sound_samples/cries/delibird.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/delibird.wav b/sound/direct_sound_samples/cries/delibird.wav new file mode 100644 index 0000000000..7ccf645de6 Binary files /dev/null and b/sound/direct_sound_samples/cries/delibird.wav differ diff --git a/sound/direct_sound_samples/cries/delphox.aif b/sound/direct_sound_samples/cries/delphox.aif deleted file mode 100644 index 857af9f0ad..0000000000 Binary files a/sound/direct_sound_samples/cries/delphox.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/delphox.wav b/sound/direct_sound_samples/cries/delphox.wav new file mode 100644 index 0000000000..b202343deb Binary files /dev/null and b/sound/direct_sound_samples/cries/delphox.wav differ diff --git a/sound/direct_sound_samples/cries/deoxys.aif b/sound/direct_sound_samples/cries/deoxys.aif deleted file mode 100644 index d9e3976e3c..0000000000 Binary files a/sound/direct_sound_samples/cries/deoxys.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/deoxys.wav b/sound/direct_sound_samples/cries/deoxys.wav new file mode 100644 index 0000000000..7ed0f65cc1 Binary files /dev/null and b/sound/direct_sound_samples/cries/deoxys.wav differ diff --git a/sound/direct_sound_samples/cries/dewgong.aif b/sound/direct_sound_samples/cries/dewgong.aif deleted file mode 100644 index daa3e5fd5c..0000000000 Binary files a/sound/direct_sound_samples/cries/dewgong.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/dewgong.wav b/sound/direct_sound_samples/cries/dewgong.wav new file mode 100644 index 0000000000..24af04411a Binary files /dev/null and b/sound/direct_sound_samples/cries/dewgong.wav differ diff --git a/sound/direct_sound_samples/cries/dewott.aif b/sound/direct_sound_samples/cries/dewott.aif deleted file mode 100644 index e654be2372..0000000000 Binary files a/sound/direct_sound_samples/cries/dewott.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/dewott.wav b/sound/direct_sound_samples/cries/dewott.wav new file mode 100644 index 0000000000..378ab5fbcb Binary files /dev/null and b/sound/direct_sound_samples/cries/dewott.wav differ diff --git a/sound/direct_sound_samples/cries/dewpider.aif b/sound/direct_sound_samples/cries/dewpider.aif deleted file mode 100644 index 0d8ade106b..0000000000 Binary files a/sound/direct_sound_samples/cries/dewpider.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/dewpider.wav b/sound/direct_sound_samples/cries/dewpider.wav new file mode 100644 index 0000000000..97ad9d8262 Binary files /dev/null and b/sound/direct_sound_samples/cries/dewpider.wav differ diff --git a/sound/direct_sound_samples/cries/dhelmise.aif b/sound/direct_sound_samples/cries/dhelmise.aif deleted file mode 100644 index 892faf1909..0000000000 Binary files a/sound/direct_sound_samples/cries/dhelmise.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/dhelmise.wav b/sound/direct_sound_samples/cries/dhelmise.wav new file mode 100644 index 0000000000..0659563c76 Binary files /dev/null and b/sound/direct_sound_samples/cries/dhelmise.wav differ diff --git a/sound/direct_sound_samples/cries/dialga.aif b/sound/direct_sound_samples/cries/dialga.aif deleted file mode 100644 index ead8acb9a1..0000000000 Binary files a/sound/direct_sound_samples/cries/dialga.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/dialga.wav b/sound/direct_sound_samples/cries/dialga.wav new file mode 100644 index 0000000000..bb421999f1 Binary files /dev/null and b/sound/direct_sound_samples/cries/dialga.wav differ diff --git a/sound/direct_sound_samples/cries/diancie.aif b/sound/direct_sound_samples/cries/diancie.aif deleted file mode 100644 index a32ad4ff93..0000000000 Binary files a/sound/direct_sound_samples/cries/diancie.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/diancie.wav b/sound/direct_sound_samples/cries/diancie.wav new file mode 100644 index 0000000000..ce1a602ebb Binary files /dev/null and b/sound/direct_sound_samples/cries/diancie.wav differ diff --git a/sound/direct_sound_samples/cries/diancie_mega.aif b/sound/direct_sound_samples/cries/diancie_mega.aif deleted file mode 100644 index be62683153..0000000000 Binary files a/sound/direct_sound_samples/cries/diancie_mega.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/diancie_mega.wav b/sound/direct_sound_samples/cries/diancie_mega.wav new file mode 100644 index 0000000000..80bec59a51 Binary files /dev/null and b/sound/direct_sound_samples/cries/diancie_mega.wav differ diff --git a/sound/direct_sound_samples/cries/diggersby.aif b/sound/direct_sound_samples/cries/diggersby.aif deleted file mode 100644 index 10dffad8ee..0000000000 Binary files a/sound/direct_sound_samples/cries/diggersby.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/diggersby.wav b/sound/direct_sound_samples/cries/diggersby.wav new file mode 100644 index 0000000000..af1792443c Binary files /dev/null and b/sound/direct_sound_samples/cries/diggersby.wav differ diff --git a/sound/direct_sound_samples/cries/diglett.aif b/sound/direct_sound_samples/cries/diglett.aif deleted file mode 100644 index cd212878fd..0000000000 Binary files a/sound/direct_sound_samples/cries/diglett.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/diglett.wav b/sound/direct_sound_samples/cries/diglett.wav new file mode 100644 index 0000000000..8eecd3bedb Binary files /dev/null and b/sound/direct_sound_samples/cries/diglett.wav differ diff --git a/sound/direct_sound_samples/cries/dipplin.aif b/sound/direct_sound_samples/cries/dipplin.aif deleted file mode 100644 index 5591528f9b..0000000000 Binary files a/sound/direct_sound_samples/cries/dipplin.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/dipplin.wav b/sound/direct_sound_samples/cries/dipplin.wav new file mode 100644 index 0000000000..79f2d7a74c Binary files /dev/null and b/sound/direct_sound_samples/cries/dipplin.wav differ diff --git a/sound/direct_sound_samples/cries/ditto.aif b/sound/direct_sound_samples/cries/ditto.aif deleted file mode 100644 index 8a1de24b25..0000000000 Binary files a/sound/direct_sound_samples/cries/ditto.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/ditto.wav b/sound/direct_sound_samples/cries/ditto.wav new file mode 100644 index 0000000000..bbd9d02804 Binary files /dev/null and b/sound/direct_sound_samples/cries/ditto.wav differ diff --git a/sound/direct_sound_samples/cries/dodrio.aif b/sound/direct_sound_samples/cries/dodrio.aif deleted file mode 100644 index 507e4ef876..0000000000 Binary files a/sound/direct_sound_samples/cries/dodrio.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/dodrio.wav b/sound/direct_sound_samples/cries/dodrio.wav new file mode 100644 index 0000000000..e43a8a9770 Binary files /dev/null and b/sound/direct_sound_samples/cries/dodrio.wav differ diff --git a/sound/direct_sound_samples/cries/doduo.aif b/sound/direct_sound_samples/cries/doduo.aif deleted file mode 100644 index 02c736d5a0..0000000000 Binary files a/sound/direct_sound_samples/cries/doduo.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/doduo.wav b/sound/direct_sound_samples/cries/doduo.wav new file mode 100644 index 0000000000..065e9fd62f Binary files /dev/null and b/sound/direct_sound_samples/cries/doduo.wav differ diff --git a/sound/direct_sound_samples/cries/dolliv.aif b/sound/direct_sound_samples/cries/dolliv.aif deleted file mode 100644 index d0aae0c9ec..0000000000 Binary files a/sound/direct_sound_samples/cries/dolliv.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/dolliv.wav b/sound/direct_sound_samples/cries/dolliv.wav new file mode 100644 index 0000000000..df8eb73f81 Binary files /dev/null and b/sound/direct_sound_samples/cries/dolliv.wav differ diff --git a/sound/direct_sound_samples/cries/dondozo.aif b/sound/direct_sound_samples/cries/dondozo.aif deleted file mode 100644 index eddac5cc27..0000000000 Binary files a/sound/direct_sound_samples/cries/dondozo.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/dondozo.wav b/sound/direct_sound_samples/cries/dondozo.wav new file mode 100644 index 0000000000..1462faa4a9 Binary files /dev/null and b/sound/direct_sound_samples/cries/dondozo.wav differ diff --git a/sound/direct_sound_samples/cries/donphan.aif b/sound/direct_sound_samples/cries/donphan.aif deleted file mode 100644 index 795cdaef45..0000000000 Binary files a/sound/direct_sound_samples/cries/donphan.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/donphan.wav b/sound/direct_sound_samples/cries/donphan.wav new file mode 100644 index 0000000000..ba6caf5bd8 Binary files /dev/null and b/sound/direct_sound_samples/cries/donphan.wav differ diff --git a/sound/direct_sound_samples/cries/dottler.aif b/sound/direct_sound_samples/cries/dottler.aif deleted file mode 100644 index 4ab520a4ae..0000000000 Binary files a/sound/direct_sound_samples/cries/dottler.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/dottler.wav b/sound/direct_sound_samples/cries/dottler.wav new file mode 100644 index 0000000000..7c21ff1251 Binary files /dev/null and b/sound/direct_sound_samples/cries/dottler.wav differ diff --git a/sound/direct_sound_samples/cries/doublade.aif b/sound/direct_sound_samples/cries/doublade.aif deleted file mode 100644 index d931b3de0a..0000000000 Binary files a/sound/direct_sound_samples/cries/doublade.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/doublade.wav b/sound/direct_sound_samples/cries/doublade.wav new file mode 100644 index 0000000000..4b76e5ccce Binary files /dev/null and b/sound/direct_sound_samples/cries/doublade.wav differ diff --git a/sound/direct_sound_samples/cries/dracovish.aif b/sound/direct_sound_samples/cries/dracovish.aif deleted file mode 100644 index e59b15f274..0000000000 Binary files a/sound/direct_sound_samples/cries/dracovish.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/dracovish.wav b/sound/direct_sound_samples/cries/dracovish.wav new file mode 100644 index 0000000000..1d8e2ee1f2 Binary files /dev/null and b/sound/direct_sound_samples/cries/dracovish.wav differ diff --git a/sound/direct_sound_samples/cries/dracozolt.aif b/sound/direct_sound_samples/cries/dracozolt.aif deleted file mode 100644 index 0c2b86f4b0..0000000000 Binary files a/sound/direct_sound_samples/cries/dracozolt.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/dracozolt.wav b/sound/direct_sound_samples/cries/dracozolt.wav new file mode 100644 index 0000000000..bce799d026 Binary files /dev/null and b/sound/direct_sound_samples/cries/dracozolt.wav differ diff --git a/sound/direct_sound_samples/cries/dragalge.aif b/sound/direct_sound_samples/cries/dragalge.aif deleted file mode 100644 index a9d11e9b65..0000000000 Binary files a/sound/direct_sound_samples/cries/dragalge.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/dragalge.wav b/sound/direct_sound_samples/cries/dragalge.wav new file mode 100644 index 0000000000..a4ce94444c Binary files /dev/null and b/sound/direct_sound_samples/cries/dragalge.wav differ diff --git a/sound/direct_sound_samples/cries/dragapult.aif b/sound/direct_sound_samples/cries/dragapult.aif deleted file mode 100644 index 7e34c9bb1b..0000000000 Binary files a/sound/direct_sound_samples/cries/dragapult.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/dragapult.wav b/sound/direct_sound_samples/cries/dragapult.wav new file mode 100644 index 0000000000..b0086241f5 Binary files /dev/null and b/sound/direct_sound_samples/cries/dragapult.wav differ diff --git a/sound/direct_sound_samples/cries/dragonair.aif b/sound/direct_sound_samples/cries/dragonair.aif deleted file mode 100644 index 6cdc594f63..0000000000 Binary files a/sound/direct_sound_samples/cries/dragonair.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/dragonair.wav b/sound/direct_sound_samples/cries/dragonair.wav new file mode 100644 index 0000000000..3fd2efee29 Binary files /dev/null and b/sound/direct_sound_samples/cries/dragonair.wav differ diff --git a/sound/direct_sound_samples/cries/dragonite.aif b/sound/direct_sound_samples/cries/dragonite.aif deleted file mode 100644 index ab1a7af1c1..0000000000 Binary files a/sound/direct_sound_samples/cries/dragonite.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/dragonite.wav b/sound/direct_sound_samples/cries/dragonite.wav new file mode 100644 index 0000000000..8517e0da0f Binary files /dev/null and b/sound/direct_sound_samples/cries/dragonite.wav differ diff --git a/sound/direct_sound_samples/cries/drakloak.aif b/sound/direct_sound_samples/cries/drakloak.aif deleted file mode 100644 index 7b9beaad89..0000000000 Binary files a/sound/direct_sound_samples/cries/drakloak.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/drakloak.wav b/sound/direct_sound_samples/cries/drakloak.wav new file mode 100644 index 0000000000..e8cc04483f Binary files /dev/null and b/sound/direct_sound_samples/cries/drakloak.wav differ diff --git a/sound/direct_sound_samples/cries/drampa.aif b/sound/direct_sound_samples/cries/drampa.aif deleted file mode 100644 index 81e185711e..0000000000 Binary files a/sound/direct_sound_samples/cries/drampa.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/drampa.wav b/sound/direct_sound_samples/cries/drampa.wav new file mode 100644 index 0000000000..fd7b9b4f50 Binary files /dev/null and b/sound/direct_sound_samples/cries/drampa.wav differ diff --git a/sound/direct_sound_samples/cries/drapion.aif b/sound/direct_sound_samples/cries/drapion.aif deleted file mode 100644 index 4ce0382fdc..0000000000 Binary files a/sound/direct_sound_samples/cries/drapion.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/drapion.wav b/sound/direct_sound_samples/cries/drapion.wav new file mode 100644 index 0000000000..2aae89e669 Binary files /dev/null and b/sound/direct_sound_samples/cries/drapion.wav differ diff --git a/sound/direct_sound_samples/cries/dratini.aif b/sound/direct_sound_samples/cries/dratini.aif deleted file mode 100644 index d79420d9c6..0000000000 Binary files a/sound/direct_sound_samples/cries/dratini.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/dratini.wav b/sound/direct_sound_samples/cries/dratini.wav new file mode 100644 index 0000000000..711c6b9a30 Binary files /dev/null and b/sound/direct_sound_samples/cries/dratini.wav differ diff --git a/sound/direct_sound_samples/cries/drednaw.aif b/sound/direct_sound_samples/cries/drednaw.aif deleted file mode 100644 index 8dd2c85409..0000000000 Binary files a/sound/direct_sound_samples/cries/drednaw.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/drednaw.wav b/sound/direct_sound_samples/cries/drednaw.wav new file mode 100644 index 0000000000..ea83c848ef Binary files /dev/null and b/sound/direct_sound_samples/cries/drednaw.wav differ diff --git a/sound/direct_sound_samples/cries/dreepy.aif b/sound/direct_sound_samples/cries/dreepy.aif deleted file mode 100644 index 12217a7f49..0000000000 Binary files a/sound/direct_sound_samples/cries/dreepy.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/dreepy.wav b/sound/direct_sound_samples/cries/dreepy.wav new file mode 100644 index 0000000000..9e3dd46766 Binary files /dev/null and b/sound/direct_sound_samples/cries/dreepy.wav differ diff --git a/sound/direct_sound_samples/cries/drifblim.aif b/sound/direct_sound_samples/cries/drifblim.aif deleted file mode 100644 index 891c49f205..0000000000 Binary files a/sound/direct_sound_samples/cries/drifblim.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/drifblim.wav b/sound/direct_sound_samples/cries/drifblim.wav new file mode 100644 index 0000000000..04d211e1ba Binary files /dev/null and b/sound/direct_sound_samples/cries/drifblim.wav differ diff --git a/sound/direct_sound_samples/cries/drifloon.aif b/sound/direct_sound_samples/cries/drifloon.aif deleted file mode 100644 index ba4c94e979..0000000000 Binary files a/sound/direct_sound_samples/cries/drifloon.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/drifloon.wav b/sound/direct_sound_samples/cries/drifloon.wav new file mode 100644 index 0000000000..6cc70ceb21 Binary files /dev/null and b/sound/direct_sound_samples/cries/drifloon.wav differ diff --git a/sound/direct_sound_samples/cries/drilbur.aif b/sound/direct_sound_samples/cries/drilbur.aif deleted file mode 100644 index 105867ee08..0000000000 Binary files a/sound/direct_sound_samples/cries/drilbur.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/drilbur.wav b/sound/direct_sound_samples/cries/drilbur.wav new file mode 100644 index 0000000000..c2c986331d Binary files /dev/null and b/sound/direct_sound_samples/cries/drilbur.wav differ diff --git a/sound/direct_sound_samples/cries/drizzile.aif b/sound/direct_sound_samples/cries/drizzile.aif deleted file mode 100644 index fde8abfbfe..0000000000 Binary files a/sound/direct_sound_samples/cries/drizzile.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/drizzile.wav b/sound/direct_sound_samples/cries/drizzile.wav new file mode 100644 index 0000000000..ebea7fbca0 Binary files /dev/null and b/sound/direct_sound_samples/cries/drizzile.wav differ diff --git a/sound/direct_sound_samples/cries/drowzee.aif b/sound/direct_sound_samples/cries/drowzee.aif deleted file mode 100644 index d25203e123..0000000000 Binary files a/sound/direct_sound_samples/cries/drowzee.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/drowzee.wav b/sound/direct_sound_samples/cries/drowzee.wav new file mode 100644 index 0000000000..4132109663 Binary files /dev/null and b/sound/direct_sound_samples/cries/drowzee.wav differ diff --git a/sound/direct_sound_samples/cries/druddigon.aif b/sound/direct_sound_samples/cries/druddigon.aif deleted file mode 100644 index 01bed53f92..0000000000 Binary files a/sound/direct_sound_samples/cries/druddigon.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/druddigon.wav b/sound/direct_sound_samples/cries/druddigon.wav new file mode 100644 index 0000000000..b1c7c7ce21 Binary files /dev/null and b/sound/direct_sound_samples/cries/druddigon.wav differ diff --git a/sound/direct_sound_samples/cries/dubwool.aif b/sound/direct_sound_samples/cries/dubwool.aif deleted file mode 100644 index 42f23089af..0000000000 Binary files a/sound/direct_sound_samples/cries/dubwool.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/dubwool.wav b/sound/direct_sound_samples/cries/dubwool.wav new file mode 100644 index 0000000000..a70cb4b18b Binary files /dev/null and b/sound/direct_sound_samples/cries/dubwool.wav differ diff --git a/sound/direct_sound_samples/cries/ducklett.aif b/sound/direct_sound_samples/cries/ducklett.aif deleted file mode 100644 index a95520506b..0000000000 Binary files a/sound/direct_sound_samples/cries/ducklett.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/ducklett.wav b/sound/direct_sound_samples/cries/ducklett.wav new file mode 100644 index 0000000000..1748d7cb75 Binary files /dev/null and b/sound/direct_sound_samples/cries/ducklett.wav differ diff --git a/sound/direct_sound_samples/cries/dudunsparce.aif b/sound/direct_sound_samples/cries/dudunsparce.aif deleted file mode 100644 index faec8aae53..0000000000 Binary files a/sound/direct_sound_samples/cries/dudunsparce.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/dudunsparce.wav b/sound/direct_sound_samples/cries/dudunsparce.wav new file mode 100644 index 0000000000..dc0244f241 Binary files /dev/null and b/sound/direct_sound_samples/cries/dudunsparce.wav differ diff --git a/sound/direct_sound_samples/cries/dugtrio.aif b/sound/direct_sound_samples/cries/dugtrio.aif deleted file mode 100644 index 1a0a05ecd0..0000000000 Binary files a/sound/direct_sound_samples/cries/dugtrio.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/dugtrio.wav b/sound/direct_sound_samples/cries/dugtrio.wav new file mode 100644 index 0000000000..d159a2fae0 Binary files /dev/null and b/sound/direct_sound_samples/cries/dugtrio.wav differ diff --git a/sound/direct_sound_samples/cries/dunsparce.aif b/sound/direct_sound_samples/cries/dunsparce.aif deleted file mode 100644 index da70bedf08..0000000000 Binary files a/sound/direct_sound_samples/cries/dunsparce.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/dunsparce.wav b/sound/direct_sound_samples/cries/dunsparce.wav new file mode 100644 index 0000000000..5154546d10 Binary files /dev/null and b/sound/direct_sound_samples/cries/dunsparce.wav differ diff --git a/sound/direct_sound_samples/cries/duosion.aif b/sound/direct_sound_samples/cries/duosion.aif deleted file mode 100644 index 4022984f1a..0000000000 Binary files a/sound/direct_sound_samples/cries/duosion.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/duosion.wav b/sound/direct_sound_samples/cries/duosion.wav new file mode 100644 index 0000000000..1850cd3937 Binary files /dev/null and b/sound/direct_sound_samples/cries/duosion.wav differ diff --git a/sound/direct_sound_samples/cries/duraludon.aif b/sound/direct_sound_samples/cries/duraludon.aif deleted file mode 100644 index 09be7c3ed9..0000000000 Binary files a/sound/direct_sound_samples/cries/duraludon.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/duraludon.wav b/sound/direct_sound_samples/cries/duraludon.wav new file mode 100644 index 0000000000..ae0345be14 Binary files /dev/null and b/sound/direct_sound_samples/cries/duraludon.wav differ diff --git a/sound/direct_sound_samples/cries/durant.aif b/sound/direct_sound_samples/cries/durant.aif deleted file mode 100644 index c0b19642c1..0000000000 Binary files a/sound/direct_sound_samples/cries/durant.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/durant.wav b/sound/direct_sound_samples/cries/durant.wav new file mode 100644 index 0000000000..8a798caf7f Binary files /dev/null and b/sound/direct_sound_samples/cries/durant.wav differ diff --git a/sound/direct_sound_samples/cries/dusclops.aif b/sound/direct_sound_samples/cries/dusclops.aif deleted file mode 100644 index 084c74ee87..0000000000 Binary files a/sound/direct_sound_samples/cries/dusclops.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/dusclops.wav b/sound/direct_sound_samples/cries/dusclops.wav new file mode 100644 index 0000000000..81353887b9 Binary files /dev/null and b/sound/direct_sound_samples/cries/dusclops.wav differ diff --git a/sound/direct_sound_samples/cries/dusknoir.aif b/sound/direct_sound_samples/cries/dusknoir.aif deleted file mode 100644 index bb1d605671..0000000000 Binary files a/sound/direct_sound_samples/cries/dusknoir.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/dusknoir.wav b/sound/direct_sound_samples/cries/dusknoir.wav new file mode 100644 index 0000000000..333bd0448c Binary files /dev/null and b/sound/direct_sound_samples/cries/dusknoir.wav differ diff --git a/sound/direct_sound_samples/cries/duskull.aif b/sound/direct_sound_samples/cries/duskull.aif deleted file mode 100644 index 523997cbf0..0000000000 Binary files a/sound/direct_sound_samples/cries/duskull.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/duskull.wav b/sound/direct_sound_samples/cries/duskull.wav new file mode 100644 index 0000000000..eba8fc3ff1 Binary files /dev/null and b/sound/direct_sound_samples/cries/duskull.wav differ diff --git a/sound/direct_sound_samples/cries/dustox.aif b/sound/direct_sound_samples/cries/dustox.aif deleted file mode 100644 index 5ab919b520..0000000000 Binary files a/sound/direct_sound_samples/cries/dustox.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/dustox.wav b/sound/direct_sound_samples/cries/dustox.wav new file mode 100644 index 0000000000..42f23c1289 Binary files /dev/null and b/sound/direct_sound_samples/cries/dustox.wav differ diff --git a/sound/direct_sound_samples/cries/dwebble.aif b/sound/direct_sound_samples/cries/dwebble.aif deleted file mode 100644 index 1aff103323..0000000000 Binary files a/sound/direct_sound_samples/cries/dwebble.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/dwebble.wav b/sound/direct_sound_samples/cries/dwebble.wav new file mode 100644 index 0000000000..81d2af0f7f Binary files /dev/null and b/sound/direct_sound_samples/cries/dwebble.wav differ diff --git a/sound/direct_sound_samples/cries/eelektrik.aif b/sound/direct_sound_samples/cries/eelektrik.aif deleted file mode 100644 index d39453bc0d..0000000000 Binary files a/sound/direct_sound_samples/cries/eelektrik.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/eelektrik.wav b/sound/direct_sound_samples/cries/eelektrik.wav new file mode 100644 index 0000000000..d0bf262cd3 Binary files /dev/null and b/sound/direct_sound_samples/cries/eelektrik.wav differ diff --git a/sound/direct_sound_samples/cries/eelektross.aif b/sound/direct_sound_samples/cries/eelektross.aif deleted file mode 100644 index b618fa5e97..0000000000 Binary files a/sound/direct_sound_samples/cries/eelektross.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/eelektross.wav b/sound/direct_sound_samples/cries/eelektross.wav new file mode 100644 index 0000000000..4b65a7aced Binary files /dev/null and b/sound/direct_sound_samples/cries/eelektross.wav differ diff --git a/sound/direct_sound_samples/cries/eevee.aif b/sound/direct_sound_samples/cries/eevee.aif deleted file mode 100644 index 0706209843..0000000000 Binary files a/sound/direct_sound_samples/cries/eevee.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/eevee.wav b/sound/direct_sound_samples/cries/eevee.wav new file mode 100644 index 0000000000..e21ce1f0e7 Binary files /dev/null and b/sound/direct_sound_samples/cries/eevee.wav differ diff --git a/sound/direct_sound_samples/cries/eiscue_ice_face.aif b/sound/direct_sound_samples/cries/eiscue_ice_face.aif deleted file mode 100644 index 5c6c7d52dd..0000000000 Binary files a/sound/direct_sound_samples/cries/eiscue_ice_face.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/eiscue_ice_face.wav b/sound/direct_sound_samples/cries/eiscue_ice_face.wav new file mode 100644 index 0000000000..cf21e9ed35 Binary files /dev/null and b/sound/direct_sound_samples/cries/eiscue_ice_face.wav differ diff --git a/sound/direct_sound_samples/cries/eiscue_noice_face.aif b/sound/direct_sound_samples/cries/eiscue_noice_face.aif deleted file mode 100644 index e591e3e2ca..0000000000 Binary files a/sound/direct_sound_samples/cries/eiscue_noice_face.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/eiscue_noice_face.wav b/sound/direct_sound_samples/cries/eiscue_noice_face.wav new file mode 100644 index 0000000000..b928e3211c Binary files /dev/null and b/sound/direct_sound_samples/cries/eiscue_noice_face.wav differ diff --git a/sound/direct_sound_samples/cries/ekans.aif b/sound/direct_sound_samples/cries/ekans.aif deleted file mode 100644 index 80bc2fdfec..0000000000 Binary files a/sound/direct_sound_samples/cries/ekans.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/ekans.wav b/sound/direct_sound_samples/cries/ekans.wav new file mode 100644 index 0000000000..2ae3e4a180 Binary files /dev/null and b/sound/direct_sound_samples/cries/ekans.wav differ diff --git a/sound/direct_sound_samples/cries/eldegoss.aif b/sound/direct_sound_samples/cries/eldegoss.aif deleted file mode 100644 index 56f9419b36..0000000000 Binary files a/sound/direct_sound_samples/cries/eldegoss.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/eldegoss.wav b/sound/direct_sound_samples/cries/eldegoss.wav new file mode 100644 index 0000000000..d5c9ccd7e6 Binary files /dev/null and b/sound/direct_sound_samples/cries/eldegoss.wav differ diff --git a/sound/direct_sound_samples/cries/electabuzz.aif b/sound/direct_sound_samples/cries/electabuzz.aif deleted file mode 100644 index 6071f1d4a9..0000000000 Binary files a/sound/direct_sound_samples/cries/electabuzz.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/electabuzz.wav b/sound/direct_sound_samples/cries/electabuzz.wav new file mode 100644 index 0000000000..b555d6631a Binary files /dev/null and b/sound/direct_sound_samples/cries/electabuzz.wav differ diff --git a/sound/direct_sound_samples/cries/electivire.aif b/sound/direct_sound_samples/cries/electivire.aif deleted file mode 100644 index 9b9c17907d..0000000000 Binary files a/sound/direct_sound_samples/cries/electivire.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/electivire.wav b/sound/direct_sound_samples/cries/electivire.wav new file mode 100644 index 0000000000..33f250d046 Binary files /dev/null and b/sound/direct_sound_samples/cries/electivire.wav differ diff --git a/sound/direct_sound_samples/cries/electrike.aif b/sound/direct_sound_samples/cries/electrike.aif deleted file mode 100644 index e7dcc64248..0000000000 Binary files a/sound/direct_sound_samples/cries/electrike.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/electrike.wav b/sound/direct_sound_samples/cries/electrike.wav new file mode 100644 index 0000000000..8a210865bf Binary files /dev/null and b/sound/direct_sound_samples/cries/electrike.wav differ diff --git a/sound/direct_sound_samples/cries/electrode.aif b/sound/direct_sound_samples/cries/electrode.aif deleted file mode 100644 index 96e627bba5..0000000000 Binary files a/sound/direct_sound_samples/cries/electrode.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/electrode.wav b/sound/direct_sound_samples/cries/electrode.wav new file mode 100644 index 0000000000..8f28521464 Binary files /dev/null and b/sound/direct_sound_samples/cries/electrode.wav differ diff --git a/sound/direct_sound_samples/cries/elekid.aif b/sound/direct_sound_samples/cries/elekid.aif deleted file mode 100644 index 99b3f959d5..0000000000 Binary files a/sound/direct_sound_samples/cries/elekid.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/elekid.wav b/sound/direct_sound_samples/cries/elekid.wav new file mode 100644 index 0000000000..82a9a2f675 Binary files /dev/null and b/sound/direct_sound_samples/cries/elekid.wav differ diff --git a/sound/direct_sound_samples/cries/elgyem.aif b/sound/direct_sound_samples/cries/elgyem.aif deleted file mode 100644 index 04e9ec7ab6..0000000000 Binary files a/sound/direct_sound_samples/cries/elgyem.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/elgyem.wav b/sound/direct_sound_samples/cries/elgyem.wav new file mode 100644 index 0000000000..825cb7f86a Binary files /dev/null and b/sound/direct_sound_samples/cries/elgyem.wav differ diff --git a/sound/direct_sound_samples/cries/emboar.aif b/sound/direct_sound_samples/cries/emboar.aif deleted file mode 100644 index 7bf61d285e..0000000000 Binary files a/sound/direct_sound_samples/cries/emboar.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/emboar.wav b/sound/direct_sound_samples/cries/emboar.wav new file mode 100644 index 0000000000..29d0d5dbe1 Binary files /dev/null and b/sound/direct_sound_samples/cries/emboar.wav differ diff --git a/sound/direct_sound_samples/cries/emolga.aif b/sound/direct_sound_samples/cries/emolga.aif deleted file mode 100644 index 20172f1446..0000000000 Binary files a/sound/direct_sound_samples/cries/emolga.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/emolga.wav b/sound/direct_sound_samples/cries/emolga.wav new file mode 100644 index 0000000000..a15a472d96 Binary files /dev/null and b/sound/direct_sound_samples/cries/emolga.wav differ diff --git a/sound/direct_sound_samples/cries/empoleon.aif b/sound/direct_sound_samples/cries/empoleon.aif deleted file mode 100644 index 742bdf8124..0000000000 Binary files a/sound/direct_sound_samples/cries/empoleon.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/empoleon.wav b/sound/direct_sound_samples/cries/empoleon.wav new file mode 100644 index 0000000000..e7edb4111f Binary files /dev/null and b/sound/direct_sound_samples/cries/empoleon.wav differ diff --git a/sound/direct_sound_samples/cries/enamorus_incarnate.aif b/sound/direct_sound_samples/cries/enamorus_incarnate.aif deleted file mode 100644 index 71068d9b7b..0000000000 Binary files a/sound/direct_sound_samples/cries/enamorus_incarnate.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/enamorus_incarnate.wav b/sound/direct_sound_samples/cries/enamorus_incarnate.wav new file mode 100644 index 0000000000..22cb614f7b Binary files /dev/null and b/sound/direct_sound_samples/cries/enamorus_incarnate.wav differ diff --git a/sound/direct_sound_samples/cries/enamorus_therian.aif b/sound/direct_sound_samples/cries/enamorus_therian.aif deleted file mode 100644 index 4286a98b69..0000000000 Binary files a/sound/direct_sound_samples/cries/enamorus_therian.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/enamorus_therian.wav b/sound/direct_sound_samples/cries/enamorus_therian.wav new file mode 100644 index 0000000000..d7fa97072b Binary files /dev/null and b/sound/direct_sound_samples/cries/enamorus_therian.wav differ diff --git a/sound/direct_sound_samples/cries/entei.aif b/sound/direct_sound_samples/cries/entei.aif deleted file mode 100644 index 1e5eff6876..0000000000 Binary files a/sound/direct_sound_samples/cries/entei.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/entei.wav b/sound/direct_sound_samples/cries/entei.wav new file mode 100644 index 0000000000..cf7e9c0c2f Binary files /dev/null and b/sound/direct_sound_samples/cries/entei.wav differ diff --git a/sound/direct_sound_samples/cries/escavalier.aif b/sound/direct_sound_samples/cries/escavalier.aif deleted file mode 100644 index 7ef48d2293..0000000000 Binary files a/sound/direct_sound_samples/cries/escavalier.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/escavalier.wav b/sound/direct_sound_samples/cries/escavalier.wav new file mode 100644 index 0000000000..950107a7e1 Binary files /dev/null and b/sound/direct_sound_samples/cries/escavalier.wav differ diff --git a/sound/direct_sound_samples/cries/espathra.aif b/sound/direct_sound_samples/cries/espathra.aif deleted file mode 100644 index 5a196762b1..0000000000 Binary files a/sound/direct_sound_samples/cries/espathra.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/espathra.wav b/sound/direct_sound_samples/cries/espathra.wav new file mode 100644 index 0000000000..8959b7c05a Binary files /dev/null and b/sound/direct_sound_samples/cries/espathra.wav differ diff --git a/sound/direct_sound_samples/cries/espeon.aif b/sound/direct_sound_samples/cries/espeon.aif deleted file mode 100644 index bf1f52c94d..0000000000 Binary files a/sound/direct_sound_samples/cries/espeon.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/espeon.wav b/sound/direct_sound_samples/cries/espeon.wav new file mode 100644 index 0000000000..20743268e1 Binary files /dev/null and b/sound/direct_sound_samples/cries/espeon.wav differ diff --git a/sound/direct_sound_samples/cries/espurr.aif b/sound/direct_sound_samples/cries/espurr.aif deleted file mode 100644 index 6d82769b36..0000000000 Binary files a/sound/direct_sound_samples/cries/espurr.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/espurr.wav b/sound/direct_sound_samples/cries/espurr.wav new file mode 100644 index 0000000000..4cb90cdf66 Binary files /dev/null and b/sound/direct_sound_samples/cries/espurr.wav differ diff --git a/sound/direct_sound_samples/cries/eternatus.aif b/sound/direct_sound_samples/cries/eternatus.aif deleted file mode 100644 index 235bba61f9..0000000000 Binary files a/sound/direct_sound_samples/cries/eternatus.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/eternatus.wav b/sound/direct_sound_samples/cries/eternatus.wav new file mode 100644 index 0000000000..64f43baa78 Binary files /dev/null and b/sound/direct_sound_samples/cries/eternatus.wav differ diff --git a/sound/direct_sound_samples/cries/eternatus_eternamax.aif b/sound/direct_sound_samples/cries/eternatus_eternamax.aif deleted file mode 100644 index 7c6b292d4d..0000000000 Binary files a/sound/direct_sound_samples/cries/eternatus_eternamax.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/eternatus_eternamax.wav b/sound/direct_sound_samples/cries/eternatus_eternamax.wav new file mode 100644 index 0000000000..3d7638de16 Binary files /dev/null and b/sound/direct_sound_samples/cries/eternatus_eternamax.wav differ diff --git a/sound/direct_sound_samples/cries/excadrill.aif b/sound/direct_sound_samples/cries/excadrill.aif deleted file mode 100644 index cd372dffdb..0000000000 Binary files a/sound/direct_sound_samples/cries/excadrill.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/excadrill.wav b/sound/direct_sound_samples/cries/excadrill.wav new file mode 100644 index 0000000000..4ba4a2d1ff Binary files /dev/null and b/sound/direct_sound_samples/cries/excadrill.wav differ diff --git a/sound/direct_sound_samples/cries/exeggcute.aif b/sound/direct_sound_samples/cries/exeggcute.aif deleted file mode 100644 index bd634c7570..0000000000 Binary files a/sound/direct_sound_samples/cries/exeggcute.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/exeggcute.wav b/sound/direct_sound_samples/cries/exeggcute.wav new file mode 100644 index 0000000000..bfd825f800 Binary files /dev/null and b/sound/direct_sound_samples/cries/exeggcute.wav differ diff --git a/sound/direct_sound_samples/cries/exeggutor.aif b/sound/direct_sound_samples/cries/exeggutor.aif deleted file mode 100644 index 094b27bc6f..0000000000 Binary files a/sound/direct_sound_samples/cries/exeggutor.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/exeggutor.wav b/sound/direct_sound_samples/cries/exeggutor.wav new file mode 100644 index 0000000000..f2a0d6bedc Binary files /dev/null and b/sound/direct_sound_samples/cries/exeggutor.wav differ diff --git a/sound/direct_sound_samples/cries/exploud.aif b/sound/direct_sound_samples/cries/exploud.aif deleted file mode 100644 index 98dafb1ee1..0000000000 Binary files a/sound/direct_sound_samples/cries/exploud.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/exploud.wav b/sound/direct_sound_samples/cries/exploud.wav new file mode 100644 index 0000000000..9b3cbf896b Binary files /dev/null and b/sound/direct_sound_samples/cries/exploud.wav differ diff --git a/sound/direct_sound_samples/cries/falinks.aif b/sound/direct_sound_samples/cries/falinks.aif deleted file mode 100644 index 6fa1af8df4..0000000000 Binary files a/sound/direct_sound_samples/cries/falinks.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/falinks.wav b/sound/direct_sound_samples/cries/falinks.wav new file mode 100644 index 0000000000..f3df8ba9cf Binary files /dev/null and b/sound/direct_sound_samples/cries/falinks.wav differ diff --git a/sound/direct_sound_samples/cries/farfetchd.aif b/sound/direct_sound_samples/cries/farfetchd.aif deleted file mode 100644 index 5a710ed7de..0000000000 Binary files a/sound/direct_sound_samples/cries/farfetchd.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/farfetchd.wav b/sound/direct_sound_samples/cries/farfetchd.wav new file mode 100644 index 0000000000..d090445d41 Binary files /dev/null and b/sound/direct_sound_samples/cries/farfetchd.wav differ diff --git a/sound/direct_sound_samples/cries/farigiraf.aif b/sound/direct_sound_samples/cries/farigiraf.aif deleted file mode 100644 index d862b0d30e..0000000000 Binary files a/sound/direct_sound_samples/cries/farigiraf.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/farigiraf.wav b/sound/direct_sound_samples/cries/farigiraf.wav new file mode 100644 index 0000000000..9b3c261949 Binary files /dev/null and b/sound/direct_sound_samples/cries/farigiraf.wav differ diff --git a/sound/direct_sound_samples/cries/fearow.aif b/sound/direct_sound_samples/cries/fearow.aif deleted file mode 100644 index 7922698482..0000000000 Binary files a/sound/direct_sound_samples/cries/fearow.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/fearow.wav b/sound/direct_sound_samples/cries/fearow.wav new file mode 100644 index 0000000000..6ef7eadee9 Binary files /dev/null and b/sound/direct_sound_samples/cries/fearow.wav differ diff --git a/sound/direct_sound_samples/cries/feebas.aif b/sound/direct_sound_samples/cries/feebas.aif deleted file mode 100644 index fc6e757134..0000000000 Binary files a/sound/direct_sound_samples/cries/feebas.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/feebas.wav b/sound/direct_sound_samples/cries/feebas.wav new file mode 100644 index 0000000000..a8f60a55f6 Binary files /dev/null and b/sound/direct_sound_samples/cries/feebas.wav differ diff --git a/sound/direct_sound_samples/cries/fennekin.aif b/sound/direct_sound_samples/cries/fennekin.aif deleted file mode 100644 index 3feb83cdf8..0000000000 Binary files a/sound/direct_sound_samples/cries/fennekin.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/fennekin.wav b/sound/direct_sound_samples/cries/fennekin.wav new file mode 100644 index 0000000000..3e187d6d1b Binary files /dev/null and b/sound/direct_sound_samples/cries/fennekin.wav differ diff --git a/sound/direct_sound_samples/cries/feraligatr.aif b/sound/direct_sound_samples/cries/feraligatr.aif deleted file mode 100644 index c71d66722b..0000000000 Binary files a/sound/direct_sound_samples/cries/feraligatr.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/feraligatr.wav b/sound/direct_sound_samples/cries/feraligatr.wav new file mode 100644 index 0000000000..d1da192f90 Binary files /dev/null and b/sound/direct_sound_samples/cries/feraligatr.wav differ diff --git a/sound/direct_sound_samples/cries/ferroseed.aif b/sound/direct_sound_samples/cries/ferroseed.aif deleted file mode 100644 index 1acd8342d0..0000000000 Binary files a/sound/direct_sound_samples/cries/ferroseed.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/ferroseed.wav b/sound/direct_sound_samples/cries/ferroseed.wav new file mode 100644 index 0000000000..0c74da6aea Binary files /dev/null and b/sound/direct_sound_samples/cries/ferroseed.wav differ diff --git a/sound/direct_sound_samples/cries/ferrothorn.aif b/sound/direct_sound_samples/cries/ferrothorn.aif deleted file mode 100644 index 7e7f1ad3ad..0000000000 Binary files a/sound/direct_sound_samples/cries/ferrothorn.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/ferrothorn.wav b/sound/direct_sound_samples/cries/ferrothorn.wav new file mode 100644 index 0000000000..30d61a2f2b Binary files /dev/null and b/sound/direct_sound_samples/cries/ferrothorn.wav differ diff --git a/sound/direct_sound_samples/cries/fezandipiti.aif b/sound/direct_sound_samples/cries/fezandipiti.aif deleted file mode 100644 index d24a32b9c7..0000000000 Binary files a/sound/direct_sound_samples/cries/fezandipiti.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/fezandipiti.wav b/sound/direct_sound_samples/cries/fezandipiti.wav new file mode 100644 index 0000000000..cb99f08edd Binary files /dev/null and b/sound/direct_sound_samples/cries/fezandipiti.wav differ diff --git a/sound/direct_sound_samples/cries/fidough.aif b/sound/direct_sound_samples/cries/fidough.aif deleted file mode 100644 index f2063bc79b..0000000000 Binary files a/sound/direct_sound_samples/cries/fidough.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/fidough.wav b/sound/direct_sound_samples/cries/fidough.wav new file mode 100644 index 0000000000..d0af55bac8 Binary files /dev/null and b/sound/direct_sound_samples/cries/fidough.wav differ diff --git a/sound/direct_sound_samples/cries/finizen.aif b/sound/direct_sound_samples/cries/finizen.aif deleted file mode 100644 index 07af24f696..0000000000 Binary files a/sound/direct_sound_samples/cries/finizen.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/finizen.wav b/sound/direct_sound_samples/cries/finizen.wav new file mode 100644 index 0000000000..f7d338dd7c Binary files /dev/null and b/sound/direct_sound_samples/cries/finizen.wav differ diff --git a/sound/direct_sound_samples/cries/finneon.aif b/sound/direct_sound_samples/cries/finneon.aif deleted file mode 100644 index c2fe2f38ba..0000000000 Binary files a/sound/direct_sound_samples/cries/finneon.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/finneon.wav b/sound/direct_sound_samples/cries/finneon.wav new file mode 100644 index 0000000000..d5a706b1c8 Binary files /dev/null and b/sound/direct_sound_samples/cries/finneon.wav differ diff --git a/sound/direct_sound_samples/cries/flaaffy.aif b/sound/direct_sound_samples/cries/flaaffy.aif deleted file mode 100644 index 068e82e76c..0000000000 Binary files a/sound/direct_sound_samples/cries/flaaffy.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/flaaffy.wav b/sound/direct_sound_samples/cries/flaaffy.wav new file mode 100644 index 0000000000..a0cf3df062 Binary files /dev/null and b/sound/direct_sound_samples/cries/flaaffy.wav differ diff --git a/sound/direct_sound_samples/cries/flabebe.aif b/sound/direct_sound_samples/cries/flabebe.aif deleted file mode 100644 index a6dbe0321c..0000000000 Binary files a/sound/direct_sound_samples/cries/flabebe.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/flabebe.wav b/sound/direct_sound_samples/cries/flabebe.wav new file mode 100644 index 0000000000..d93a0f4a4b Binary files /dev/null and b/sound/direct_sound_samples/cries/flabebe.wav differ diff --git a/sound/direct_sound_samples/cries/flamigo.aif b/sound/direct_sound_samples/cries/flamigo.aif deleted file mode 100644 index 2b022da5b0..0000000000 Binary files a/sound/direct_sound_samples/cries/flamigo.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/flamigo.wav b/sound/direct_sound_samples/cries/flamigo.wav new file mode 100644 index 0000000000..1a47bf593a Binary files /dev/null and b/sound/direct_sound_samples/cries/flamigo.wav differ diff --git a/sound/direct_sound_samples/cries/flapple.aif b/sound/direct_sound_samples/cries/flapple.aif deleted file mode 100644 index 844318022e..0000000000 Binary files a/sound/direct_sound_samples/cries/flapple.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/flapple.wav b/sound/direct_sound_samples/cries/flapple.wav new file mode 100644 index 0000000000..4120296cc7 Binary files /dev/null and b/sound/direct_sound_samples/cries/flapple.wav differ diff --git a/sound/direct_sound_samples/cries/flareon.aif b/sound/direct_sound_samples/cries/flareon.aif deleted file mode 100644 index b8d33df49e..0000000000 Binary files a/sound/direct_sound_samples/cries/flareon.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/flareon.wav b/sound/direct_sound_samples/cries/flareon.wav new file mode 100644 index 0000000000..6bd51168b3 Binary files /dev/null and b/sound/direct_sound_samples/cries/flareon.wav differ diff --git a/sound/direct_sound_samples/cries/fletchinder.aif b/sound/direct_sound_samples/cries/fletchinder.aif deleted file mode 100644 index 2267e3fdfc..0000000000 Binary files a/sound/direct_sound_samples/cries/fletchinder.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/fletchinder.wav b/sound/direct_sound_samples/cries/fletchinder.wav new file mode 100644 index 0000000000..a5e0a7bac4 Binary files /dev/null and b/sound/direct_sound_samples/cries/fletchinder.wav differ diff --git a/sound/direct_sound_samples/cries/fletchling.aif b/sound/direct_sound_samples/cries/fletchling.aif deleted file mode 100644 index ce9085845f..0000000000 Binary files a/sound/direct_sound_samples/cries/fletchling.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/fletchling.wav b/sound/direct_sound_samples/cries/fletchling.wav new file mode 100644 index 0000000000..7b8cb393ec Binary files /dev/null and b/sound/direct_sound_samples/cries/fletchling.wav differ diff --git a/sound/direct_sound_samples/cries/flittle.aif b/sound/direct_sound_samples/cries/flittle.aif deleted file mode 100644 index d81016a64d..0000000000 Binary files a/sound/direct_sound_samples/cries/flittle.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/flittle.wav b/sound/direct_sound_samples/cries/flittle.wav new file mode 100644 index 0000000000..da2b154d2a Binary files /dev/null and b/sound/direct_sound_samples/cries/flittle.wav differ diff --git a/sound/direct_sound_samples/cries/floatzel.aif b/sound/direct_sound_samples/cries/floatzel.aif deleted file mode 100644 index 36f34f5e90..0000000000 Binary files a/sound/direct_sound_samples/cries/floatzel.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/floatzel.wav b/sound/direct_sound_samples/cries/floatzel.wav new file mode 100644 index 0000000000..33e8eecf43 Binary files /dev/null and b/sound/direct_sound_samples/cries/floatzel.wav differ diff --git a/sound/direct_sound_samples/cries/floette.aif b/sound/direct_sound_samples/cries/floette.aif deleted file mode 100644 index 4244ce8eda..0000000000 Binary files a/sound/direct_sound_samples/cries/floette.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/floette.wav b/sound/direct_sound_samples/cries/floette.wav new file mode 100644 index 0000000000..36000d14ac Binary files /dev/null and b/sound/direct_sound_samples/cries/floette.wav differ diff --git a/sound/direct_sound_samples/cries/floette_eternal.aif b/sound/direct_sound_samples/cries/floette_eternal.aif deleted file mode 100644 index 386815f082..0000000000 Binary files a/sound/direct_sound_samples/cries/floette_eternal.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/floette_eternal.wav b/sound/direct_sound_samples/cries/floette_eternal.wav new file mode 100644 index 0000000000..a4cc2b3a81 Binary files /dev/null and b/sound/direct_sound_samples/cries/floette_eternal.wav differ diff --git a/sound/direct_sound_samples/cries/floragato.aif b/sound/direct_sound_samples/cries/floragato.aif deleted file mode 100644 index 4fc8832423..0000000000 Binary files a/sound/direct_sound_samples/cries/floragato.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/floragato.wav b/sound/direct_sound_samples/cries/floragato.wav new file mode 100644 index 0000000000..64fa6df859 Binary files /dev/null and b/sound/direct_sound_samples/cries/floragato.wav differ diff --git a/sound/direct_sound_samples/cries/florges.aif b/sound/direct_sound_samples/cries/florges.aif deleted file mode 100644 index e652e68fa9..0000000000 Binary files a/sound/direct_sound_samples/cries/florges.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/florges.wav b/sound/direct_sound_samples/cries/florges.wav new file mode 100644 index 0000000000..180c6490bb Binary files /dev/null and b/sound/direct_sound_samples/cries/florges.wav differ diff --git a/sound/direct_sound_samples/cries/flutter_mane.aif b/sound/direct_sound_samples/cries/flutter_mane.aif deleted file mode 100644 index ad4c636fe7..0000000000 Binary files a/sound/direct_sound_samples/cries/flutter_mane.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/flutter_mane.wav b/sound/direct_sound_samples/cries/flutter_mane.wav new file mode 100644 index 0000000000..c52aeabc5c Binary files /dev/null and b/sound/direct_sound_samples/cries/flutter_mane.wav differ diff --git a/sound/direct_sound_samples/cries/flygon.aif b/sound/direct_sound_samples/cries/flygon.aif deleted file mode 100644 index c8b793f4f9..0000000000 Binary files a/sound/direct_sound_samples/cries/flygon.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/flygon.wav b/sound/direct_sound_samples/cries/flygon.wav new file mode 100644 index 0000000000..b6c5d90ba0 Binary files /dev/null and b/sound/direct_sound_samples/cries/flygon.wav differ diff --git a/sound/direct_sound_samples/cries/fomantis.aif b/sound/direct_sound_samples/cries/fomantis.aif deleted file mode 100644 index a82e4d4524..0000000000 Binary files a/sound/direct_sound_samples/cries/fomantis.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/fomantis.wav b/sound/direct_sound_samples/cries/fomantis.wav new file mode 100644 index 0000000000..d3de05db55 Binary files /dev/null and b/sound/direct_sound_samples/cries/fomantis.wav differ diff --git a/sound/direct_sound_samples/cries/foongus.aif b/sound/direct_sound_samples/cries/foongus.aif deleted file mode 100644 index ca83e1b475..0000000000 Binary files a/sound/direct_sound_samples/cries/foongus.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/foongus.wav b/sound/direct_sound_samples/cries/foongus.wav new file mode 100644 index 0000000000..6c2c2381e0 Binary files /dev/null and b/sound/direct_sound_samples/cries/foongus.wav differ diff --git a/sound/direct_sound_samples/cries/forretress.aif b/sound/direct_sound_samples/cries/forretress.aif deleted file mode 100644 index 9b8af8baa4..0000000000 Binary files a/sound/direct_sound_samples/cries/forretress.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/forretress.wav b/sound/direct_sound_samples/cries/forretress.wav new file mode 100644 index 0000000000..3f704f65b5 Binary files /dev/null and b/sound/direct_sound_samples/cries/forretress.wav differ diff --git a/sound/direct_sound_samples/cries/fraxure.aif b/sound/direct_sound_samples/cries/fraxure.aif deleted file mode 100644 index 4586702b00..0000000000 Binary files a/sound/direct_sound_samples/cries/fraxure.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/fraxure.wav b/sound/direct_sound_samples/cries/fraxure.wav new file mode 100644 index 0000000000..6759da7a1d Binary files /dev/null and b/sound/direct_sound_samples/cries/fraxure.wav differ diff --git a/sound/direct_sound_samples/cries/frigibax.aif b/sound/direct_sound_samples/cries/frigibax.aif deleted file mode 100644 index e8318a0cf1..0000000000 Binary files a/sound/direct_sound_samples/cries/frigibax.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/frigibax.wav b/sound/direct_sound_samples/cries/frigibax.wav new file mode 100644 index 0000000000..200f6f7da4 Binary files /dev/null and b/sound/direct_sound_samples/cries/frigibax.wav differ diff --git a/sound/direct_sound_samples/cries/frillish.aif b/sound/direct_sound_samples/cries/frillish.aif deleted file mode 100644 index 71511b8bcf..0000000000 Binary files a/sound/direct_sound_samples/cries/frillish.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/frillish.wav b/sound/direct_sound_samples/cries/frillish.wav new file mode 100644 index 0000000000..45adf7c08c Binary files /dev/null and b/sound/direct_sound_samples/cries/frillish.wav differ diff --git a/sound/direct_sound_samples/cries/froakie.aif b/sound/direct_sound_samples/cries/froakie.aif deleted file mode 100644 index d6955de8bc..0000000000 Binary files a/sound/direct_sound_samples/cries/froakie.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/froakie.wav b/sound/direct_sound_samples/cries/froakie.wav new file mode 100644 index 0000000000..0099799d73 Binary files /dev/null and b/sound/direct_sound_samples/cries/froakie.wav differ diff --git a/sound/direct_sound_samples/cries/frogadier.aif b/sound/direct_sound_samples/cries/frogadier.aif deleted file mode 100644 index 918abc5d84..0000000000 Binary files a/sound/direct_sound_samples/cries/frogadier.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/frogadier.wav b/sound/direct_sound_samples/cries/frogadier.wav new file mode 100644 index 0000000000..f7fcff3f05 Binary files /dev/null and b/sound/direct_sound_samples/cries/frogadier.wav differ diff --git a/sound/direct_sound_samples/cries/froslass.aif b/sound/direct_sound_samples/cries/froslass.aif deleted file mode 100644 index 75febf4311..0000000000 Binary files a/sound/direct_sound_samples/cries/froslass.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/froslass.wav b/sound/direct_sound_samples/cries/froslass.wav new file mode 100644 index 0000000000..7c1baee478 Binary files /dev/null and b/sound/direct_sound_samples/cries/froslass.wav differ diff --git a/sound/direct_sound_samples/cries/frosmoth.aif b/sound/direct_sound_samples/cries/frosmoth.aif deleted file mode 100644 index 324034d15e..0000000000 Binary files a/sound/direct_sound_samples/cries/frosmoth.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/frosmoth.wav b/sound/direct_sound_samples/cries/frosmoth.wav new file mode 100644 index 0000000000..b65a91e531 Binary files /dev/null and b/sound/direct_sound_samples/cries/frosmoth.wav differ diff --git a/sound/direct_sound_samples/cries/fuecoco.aif b/sound/direct_sound_samples/cries/fuecoco.aif deleted file mode 100644 index ee40234e0b..0000000000 Binary files a/sound/direct_sound_samples/cries/fuecoco.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/fuecoco.wav b/sound/direct_sound_samples/cries/fuecoco.wav new file mode 100644 index 0000000000..7b3a68eaea Binary files /dev/null and b/sound/direct_sound_samples/cries/fuecoco.wav differ diff --git a/sound/direct_sound_samples/cries/furfrou.aif b/sound/direct_sound_samples/cries/furfrou.aif deleted file mode 100644 index d989bde3d3..0000000000 Binary files a/sound/direct_sound_samples/cries/furfrou.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/furfrou.wav b/sound/direct_sound_samples/cries/furfrou.wav new file mode 100644 index 0000000000..3800ae8c38 Binary files /dev/null and b/sound/direct_sound_samples/cries/furfrou.wav differ diff --git a/sound/direct_sound_samples/cries/furret.aif b/sound/direct_sound_samples/cries/furret.aif deleted file mode 100644 index cdf9447d73..0000000000 Binary files a/sound/direct_sound_samples/cries/furret.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/furret.wav b/sound/direct_sound_samples/cries/furret.wav new file mode 100644 index 0000000000..e3e4ec5842 Binary files /dev/null and b/sound/direct_sound_samples/cries/furret.wav differ diff --git a/sound/direct_sound_samples/cries/gabite.aif b/sound/direct_sound_samples/cries/gabite.aif deleted file mode 100644 index 5ca21cec7a..0000000000 Binary files a/sound/direct_sound_samples/cries/gabite.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/gabite.wav b/sound/direct_sound_samples/cries/gabite.wav new file mode 100644 index 0000000000..b8bd906101 Binary files /dev/null and b/sound/direct_sound_samples/cries/gabite.wav differ diff --git a/sound/direct_sound_samples/cries/gallade.aif b/sound/direct_sound_samples/cries/gallade.aif deleted file mode 100644 index 1eb55aeed9..0000000000 Binary files a/sound/direct_sound_samples/cries/gallade.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/gallade.wav b/sound/direct_sound_samples/cries/gallade.wav new file mode 100644 index 0000000000..bc0671f08f Binary files /dev/null and b/sound/direct_sound_samples/cries/gallade.wav differ diff --git a/sound/direct_sound_samples/cries/gallade_mega.aif b/sound/direct_sound_samples/cries/gallade_mega.aif deleted file mode 100644 index 5b0d5eb5cc..0000000000 Binary files a/sound/direct_sound_samples/cries/gallade_mega.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/gallade_mega.wav b/sound/direct_sound_samples/cries/gallade_mega.wav new file mode 100644 index 0000000000..c1725b2a80 Binary files /dev/null and b/sound/direct_sound_samples/cries/gallade_mega.wav differ diff --git a/sound/direct_sound_samples/cries/galvantula.aif b/sound/direct_sound_samples/cries/galvantula.aif deleted file mode 100644 index 8d890a2463..0000000000 Binary files a/sound/direct_sound_samples/cries/galvantula.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/galvantula.wav b/sound/direct_sound_samples/cries/galvantula.wav new file mode 100644 index 0000000000..d08ff5388c Binary files /dev/null and b/sound/direct_sound_samples/cries/galvantula.wav differ diff --git a/sound/direct_sound_samples/cries/garbodor.aif b/sound/direct_sound_samples/cries/garbodor.aif deleted file mode 100644 index 09cad5cd7f..0000000000 Binary files a/sound/direct_sound_samples/cries/garbodor.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/garbodor.wav b/sound/direct_sound_samples/cries/garbodor.wav new file mode 100644 index 0000000000..d5c66fbf25 Binary files /dev/null and b/sound/direct_sound_samples/cries/garbodor.wav differ diff --git a/sound/direct_sound_samples/cries/garchomp.aif b/sound/direct_sound_samples/cries/garchomp.aif deleted file mode 100644 index f96c62f93b..0000000000 Binary files a/sound/direct_sound_samples/cries/garchomp.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/garchomp.wav b/sound/direct_sound_samples/cries/garchomp.wav new file mode 100644 index 0000000000..828a1a49a2 Binary files /dev/null and b/sound/direct_sound_samples/cries/garchomp.wav differ diff --git a/sound/direct_sound_samples/cries/garchomp_mega.aif b/sound/direct_sound_samples/cries/garchomp_mega.aif deleted file mode 100644 index 65637139f2..0000000000 Binary files a/sound/direct_sound_samples/cries/garchomp_mega.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/garchomp_mega.wav b/sound/direct_sound_samples/cries/garchomp_mega.wav new file mode 100644 index 0000000000..0b1f9df662 Binary files /dev/null and b/sound/direct_sound_samples/cries/garchomp_mega.wav differ diff --git a/sound/direct_sound_samples/cries/gardevoir.aif b/sound/direct_sound_samples/cries/gardevoir.aif deleted file mode 100644 index 9285affb9d..0000000000 Binary files a/sound/direct_sound_samples/cries/gardevoir.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/gardevoir.wav b/sound/direct_sound_samples/cries/gardevoir.wav new file mode 100644 index 0000000000..bd3a99acc2 Binary files /dev/null and b/sound/direct_sound_samples/cries/gardevoir.wav differ diff --git a/sound/direct_sound_samples/cries/gardevoir_mega.aif b/sound/direct_sound_samples/cries/gardevoir_mega.aif deleted file mode 100644 index 71ba65d455..0000000000 Binary files a/sound/direct_sound_samples/cries/gardevoir_mega.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/gardevoir_mega.wav b/sound/direct_sound_samples/cries/gardevoir_mega.wav new file mode 100644 index 0000000000..f94e401a96 Binary files /dev/null and b/sound/direct_sound_samples/cries/gardevoir_mega.wav differ diff --git a/sound/direct_sound_samples/cries/garganacl.aif b/sound/direct_sound_samples/cries/garganacl.aif deleted file mode 100644 index 3c530cea53..0000000000 Binary files a/sound/direct_sound_samples/cries/garganacl.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/garganacl.wav b/sound/direct_sound_samples/cries/garganacl.wav new file mode 100644 index 0000000000..5730bea348 Binary files /dev/null and b/sound/direct_sound_samples/cries/garganacl.wav differ diff --git a/sound/direct_sound_samples/cries/gastly.aif b/sound/direct_sound_samples/cries/gastly.aif deleted file mode 100644 index 5174cabffd..0000000000 Binary files a/sound/direct_sound_samples/cries/gastly.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/gastly.wav b/sound/direct_sound_samples/cries/gastly.wav new file mode 100644 index 0000000000..1bc2ff9667 Binary files /dev/null and b/sound/direct_sound_samples/cries/gastly.wav differ diff --git a/sound/direct_sound_samples/cries/gastrodon.aif b/sound/direct_sound_samples/cries/gastrodon.aif deleted file mode 100644 index d564820e83..0000000000 Binary files a/sound/direct_sound_samples/cries/gastrodon.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/gastrodon.wav b/sound/direct_sound_samples/cries/gastrodon.wav new file mode 100644 index 0000000000..164666f314 Binary files /dev/null and b/sound/direct_sound_samples/cries/gastrodon.wav differ diff --git a/sound/direct_sound_samples/cries/genesect.aif b/sound/direct_sound_samples/cries/genesect.aif deleted file mode 100644 index 49e430ee9a..0000000000 Binary files a/sound/direct_sound_samples/cries/genesect.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/genesect.wav b/sound/direct_sound_samples/cries/genesect.wav new file mode 100644 index 0000000000..443ea6f0df Binary files /dev/null and b/sound/direct_sound_samples/cries/genesect.wav differ diff --git a/sound/direct_sound_samples/cries/gengar.aif b/sound/direct_sound_samples/cries/gengar.aif deleted file mode 100644 index 3c5e291ba3..0000000000 Binary files a/sound/direct_sound_samples/cries/gengar.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/gengar.wav b/sound/direct_sound_samples/cries/gengar.wav new file mode 100644 index 0000000000..9e8c24c28b Binary files /dev/null and b/sound/direct_sound_samples/cries/gengar.wav differ diff --git a/sound/direct_sound_samples/cries/gengar_mega.aif b/sound/direct_sound_samples/cries/gengar_mega.aif deleted file mode 100644 index 7967d6dcfb..0000000000 Binary files a/sound/direct_sound_samples/cries/gengar_mega.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/gengar_mega.wav b/sound/direct_sound_samples/cries/gengar_mega.wav new file mode 100644 index 0000000000..b0c8ab70c6 Binary files /dev/null and b/sound/direct_sound_samples/cries/gengar_mega.wav differ diff --git a/sound/direct_sound_samples/cries/geodude.aif b/sound/direct_sound_samples/cries/geodude.aif deleted file mode 100644 index a09b2ca345..0000000000 Binary files a/sound/direct_sound_samples/cries/geodude.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/geodude.wav b/sound/direct_sound_samples/cries/geodude.wav new file mode 100644 index 0000000000..f355fc7e1a Binary files /dev/null and b/sound/direct_sound_samples/cries/geodude.wav differ diff --git a/sound/direct_sound_samples/cries/gholdengo.aif b/sound/direct_sound_samples/cries/gholdengo.aif deleted file mode 100644 index 4cef67ba29..0000000000 Binary files a/sound/direct_sound_samples/cries/gholdengo.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/gholdengo.wav b/sound/direct_sound_samples/cries/gholdengo.wav new file mode 100644 index 0000000000..37bb7ed39a Binary files /dev/null and b/sound/direct_sound_samples/cries/gholdengo.wav differ diff --git a/sound/direct_sound_samples/cries/gible.aif b/sound/direct_sound_samples/cries/gible.aif deleted file mode 100644 index f3d4b4882f..0000000000 Binary files a/sound/direct_sound_samples/cries/gible.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/gible.wav b/sound/direct_sound_samples/cries/gible.wav new file mode 100644 index 0000000000..49bd85b916 Binary files /dev/null and b/sound/direct_sound_samples/cries/gible.wav differ diff --git a/sound/direct_sound_samples/cries/gigalith.aif b/sound/direct_sound_samples/cries/gigalith.aif deleted file mode 100644 index 00ad607cc6..0000000000 Binary files a/sound/direct_sound_samples/cries/gigalith.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/gigalith.wav b/sound/direct_sound_samples/cries/gigalith.wav new file mode 100644 index 0000000000..ae3b47aa7e Binary files /dev/null and b/sound/direct_sound_samples/cries/gigalith.wav differ diff --git a/sound/direct_sound_samples/cries/gimmighoul.aif b/sound/direct_sound_samples/cries/gimmighoul.aif deleted file mode 100644 index fe8db162c9..0000000000 Binary files a/sound/direct_sound_samples/cries/gimmighoul.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/gimmighoul.wav b/sound/direct_sound_samples/cries/gimmighoul.wav new file mode 100644 index 0000000000..f915238a95 Binary files /dev/null and b/sound/direct_sound_samples/cries/gimmighoul.wav differ diff --git a/sound/direct_sound_samples/cries/gimmighoul_roaming.aif b/sound/direct_sound_samples/cries/gimmighoul_roaming.aif deleted file mode 100644 index 9f3c4483e9..0000000000 Binary files a/sound/direct_sound_samples/cries/gimmighoul_roaming.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/girafarig.aif b/sound/direct_sound_samples/cries/girafarig.aif deleted file mode 100644 index af5af89268..0000000000 Binary files a/sound/direct_sound_samples/cries/girafarig.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/girafarig.wav b/sound/direct_sound_samples/cries/girafarig.wav new file mode 100644 index 0000000000..d78162a29f Binary files /dev/null and b/sound/direct_sound_samples/cries/girafarig.wav differ diff --git a/sound/direct_sound_samples/cries/giratina.aif b/sound/direct_sound_samples/cries/giratina.aif deleted file mode 100644 index 319e2c1323..0000000000 Binary files a/sound/direct_sound_samples/cries/giratina.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/giratina.wav b/sound/direct_sound_samples/cries/giratina.wav new file mode 100644 index 0000000000..f2b4dff5c8 Binary files /dev/null and b/sound/direct_sound_samples/cries/giratina.wav differ diff --git a/sound/direct_sound_samples/cries/glaceon.aif b/sound/direct_sound_samples/cries/glaceon.aif deleted file mode 100644 index e38ebdef91..0000000000 Binary files a/sound/direct_sound_samples/cries/glaceon.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/glaceon.wav b/sound/direct_sound_samples/cries/glaceon.wav new file mode 100644 index 0000000000..b67779f873 Binary files /dev/null and b/sound/direct_sound_samples/cries/glaceon.wav differ diff --git a/sound/direct_sound_samples/cries/glalie.aif b/sound/direct_sound_samples/cries/glalie.aif deleted file mode 100644 index 38291bef49..0000000000 Binary files a/sound/direct_sound_samples/cries/glalie.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/glalie.wav b/sound/direct_sound_samples/cries/glalie.wav new file mode 100644 index 0000000000..bf35bd147b Binary files /dev/null and b/sound/direct_sound_samples/cries/glalie.wav differ diff --git a/sound/direct_sound_samples/cries/glalie_mega.aif b/sound/direct_sound_samples/cries/glalie_mega.aif deleted file mode 100644 index cae5ba57f1..0000000000 Binary files a/sound/direct_sound_samples/cries/glalie_mega.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/glalie_mega.wav b/sound/direct_sound_samples/cries/glalie_mega.wav new file mode 100644 index 0000000000..366b61e630 Binary files /dev/null and b/sound/direct_sound_samples/cries/glalie_mega.wav differ diff --git a/sound/direct_sound_samples/cries/glameow.aif b/sound/direct_sound_samples/cries/glameow.aif deleted file mode 100644 index a2d7ab1fa3..0000000000 Binary files a/sound/direct_sound_samples/cries/glameow.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/glameow.wav b/sound/direct_sound_samples/cries/glameow.wav new file mode 100644 index 0000000000..8fe17099bb Binary files /dev/null and b/sound/direct_sound_samples/cries/glameow.wav differ diff --git a/sound/direct_sound_samples/cries/glastrier.aif b/sound/direct_sound_samples/cries/glastrier.aif deleted file mode 100644 index 80c44e0b76..0000000000 Binary files a/sound/direct_sound_samples/cries/glastrier.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/glastrier.wav b/sound/direct_sound_samples/cries/glastrier.wav new file mode 100644 index 0000000000..bd9885ce2b Binary files /dev/null and b/sound/direct_sound_samples/cries/glastrier.wav differ diff --git a/sound/direct_sound_samples/cries/gligar.aif b/sound/direct_sound_samples/cries/gligar.aif deleted file mode 100644 index e2103c2ff8..0000000000 Binary files a/sound/direct_sound_samples/cries/gligar.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/gligar.wav b/sound/direct_sound_samples/cries/gligar.wav new file mode 100644 index 0000000000..8fa3efa6b1 Binary files /dev/null and b/sound/direct_sound_samples/cries/gligar.wav differ diff --git a/sound/direct_sound_samples/cries/glimmet.aif b/sound/direct_sound_samples/cries/glimmet.aif deleted file mode 100644 index e89ac2ea59..0000000000 Binary files a/sound/direct_sound_samples/cries/glimmet.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/glimmet.wav b/sound/direct_sound_samples/cries/glimmet.wav new file mode 100644 index 0000000000..37dbf6c8b1 Binary files /dev/null and b/sound/direct_sound_samples/cries/glimmet.wav differ diff --git a/sound/direct_sound_samples/cries/glimmora.aif b/sound/direct_sound_samples/cries/glimmora.aif deleted file mode 100644 index 64fb682289..0000000000 Binary files a/sound/direct_sound_samples/cries/glimmora.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/glimmora.wav b/sound/direct_sound_samples/cries/glimmora.wav new file mode 100644 index 0000000000..9edf26f989 Binary files /dev/null and b/sound/direct_sound_samples/cries/glimmora.wav differ diff --git a/sound/direct_sound_samples/cries/gliscor.aif b/sound/direct_sound_samples/cries/gliscor.aif deleted file mode 100644 index 1df92dc9a9..0000000000 Binary files a/sound/direct_sound_samples/cries/gliscor.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/gliscor.wav b/sound/direct_sound_samples/cries/gliscor.wav new file mode 100644 index 0000000000..1146423758 Binary files /dev/null and b/sound/direct_sound_samples/cries/gliscor.wav differ diff --git a/sound/direct_sound_samples/cries/gloom.aif b/sound/direct_sound_samples/cries/gloom.aif deleted file mode 100644 index bcedd48d5e..0000000000 Binary files a/sound/direct_sound_samples/cries/gloom.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/gloom.wav b/sound/direct_sound_samples/cries/gloom.wav new file mode 100644 index 0000000000..abc408a0f7 Binary files /dev/null and b/sound/direct_sound_samples/cries/gloom.wav differ diff --git a/sound/direct_sound_samples/cries/gogoat.aif b/sound/direct_sound_samples/cries/gogoat.aif deleted file mode 100644 index 6717a2ff26..0000000000 Binary files a/sound/direct_sound_samples/cries/gogoat.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/gogoat.wav b/sound/direct_sound_samples/cries/gogoat.wav new file mode 100644 index 0000000000..6ab6d386e4 Binary files /dev/null and b/sound/direct_sound_samples/cries/gogoat.wav differ diff --git a/sound/direct_sound_samples/cries/golbat.aif b/sound/direct_sound_samples/cries/golbat.aif deleted file mode 100644 index 2e91f76966..0000000000 Binary files a/sound/direct_sound_samples/cries/golbat.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/golbat.wav b/sound/direct_sound_samples/cries/golbat.wav new file mode 100644 index 0000000000..20d2ecf5c9 Binary files /dev/null and b/sound/direct_sound_samples/cries/golbat.wav differ diff --git a/sound/direct_sound_samples/cries/goldeen.aif b/sound/direct_sound_samples/cries/goldeen.aif deleted file mode 100644 index 687f8d3920..0000000000 Binary files a/sound/direct_sound_samples/cries/goldeen.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/goldeen.wav b/sound/direct_sound_samples/cries/goldeen.wav new file mode 100644 index 0000000000..342df710c9 Binary files /dev/null and b/sound/direct_sound_samples/cries/goldeen.wav differ diff --git a/sound/direct_sound_samples/cries/golduck.aif b/sound/direct_sound_samples/cries/golduck.aif deleted file mode 100644 index bc6c5f5b16..0000000000 Binary files a/sound/direct_sound_samples/cries/golduck.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/golduck.wav b/sound/direct_sound_samples/cries/golduck.wav new file mode 100644 index 0000000000..a9bf91b2da Binary files /dev/null and b/sound/direct_sound_samples/cries/golduck.wav differ diff --git a/sound/direct_sound_samples/cries/golem.aif b/sound/direct_sound_samples/cries/golem.aif deleted file mode 100644 index 95fbef9c47..0000000000 Binary files a/sound/direct_sound_samples/cries/golem.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/golem.wav b/sound/direct_sound_samples/cries/golem.wav new file mode 100644 index 0000000000..17ed6128e4 Binary files /dev/null and b/sound/direct_sound_samples/cries/golem.wav differ diff --git a/sound/direct_sound_samples/cries/golett.aif b/sound/direct_sound_samples/cries/golett.aif deleted file mode 100644 index 58c6f09cd8..0000000000 Binary files a/sound/direct_sound_samples/cries/golett.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/golett.wav b/sound/direct_sound_samples/cries/golett.wav new file mode 100644 index 0000000000..46c3664e65 Binary files /dev/null and b/sound/direct_sound_samples/cries/golett.wav differ diff --git a/sound/direct_sound_samples/cries/golisopod.aif b/sound/direct_sound_samples/cries/golisopod.aif deleted file mode 100644 index 429f445ede..0000000000 Binary files a/sound/direct_sound_samples/cries/golisopod.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/golisopod.wav b/sound/direct_sound_samples/cries/golisopod.wav new file mode 100644 index 0000000000..66912c8b08 Binary files /dev/null and b/sound/direct_sound_samples/cries/golisopod.wav differ diff --git a/sound/direct_sound_samples/cries/golurk.aif b/sound/direct_sound_samples/cries/golurk.aif deleted file mode 100644 index abc95bd808..0000000000 Binary files a/sound/direct_sound_samples/cries/golurk.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/golurk.wav b/sound/direct_sound_samples/cries/golurk.wav new file mode 100644 index 0000000000..b6e41c1fe0 Binary files /dev/null and b/sound/direct_sound_samples/cries/golurk.wav differ diff --git a/sound/direct_sound_samples/cries/goodra.aif b/sound/direct_sound_samples/cries/goodra.aif deleted file mode 100644 index b2f407cc94..0000000000 Binary files a/sound/direct_sound_samples/cries/goodra.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/goodra.wav b/sound/direct_sound_samples/cries/goodra.wav new file mode 100644 index 0000000000..ffb6bd7f44 Binary files /dev/null and b/sound/direct_sound_samples/cries/goodra.wav differ diff --git a/sound/direct_sound_samples/cries/goomy.aif b/sound/direct_sound_samples/cries/goomy.aif deleted file mode 100644 index bd2524ebe1..0000000000 Binary files a/sound/direct_sound_samples/cries/goomy.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/goomy.wav b/sound/direct_sound_samples/cries/goomy.wav new file mode 100644 index 0000000000..d7fdac2cec Binary files /dev/null and b/sound/direct_sound_samples/cries/goomy.wav differ diff --git a/sound/direct_sound_samples/cries/gorebyss.aif b/sound/direct_sound_samples/cries/gorebyss.aif deleted file mode 100644 index a93b1aa6fc..0000000000 Binary files a/sound/direct_sound_samples/cries/gorebyss.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/gorebyss.wav b/sound/direct_sound_samples/cries/gorebyss.wav new file mode 100644 index 0000000000..3d375f6dcf Binary files /dev/null and b/sound/direct_sound_samples/cries/gorebyss.wav differ diff --git a/sound/direct_sound_samples/cries/gossifleur.aif b/sound/direct_sound_samples/cries/gossifleur.aif deleted file mode 100644 index dae1731c8f..0000000000 Binary files a/sound/direct_sound_samples/cries/gossifleur.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/gossifleur.wav b/sound/direct_sound_samples/cries/gossifleur.wav new file mode 100644 index 0000000000..a666b937c4 Binary files /dev/null and b/sound/direct_sound_samples/cries/gossifleur.wav differ diff --git a/sound/direct_sound_samples/cries/gothita.aif b/sound/direct_sound_samples/cries/gothita.aif deleted file mode 100644 index 00476d94bd..0000000000 Binary files a/sound/direct_sound_samples/cries/gothita.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/gothita.wav b/sound/direct_sound_samples/cries/gothita.wav new file mode 100644 index 0000000000..1d8ad153b4 Binary files /dev/null and b/sound/direct_sound_samples/cries/gothita.wav differ diff --git a/sound/direct_sound_samples/cries/gothitelle.aif b/sound/direct_sound_samples/cries/gothitelle.aif deleted file mode 100644 index d8f334784a..0000000000 Binary files a/sound/direct_sound_samples/cries/gothitelle.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/gothitelle.wav b/sound/direct_sound_samples/cries/gothitelle.wav new file mode 100644 index 0000000000..3d7c2046d0 Binary files /dev/null and b/sound/direct_sound_samples/cries/gothitelle.wav differ diff --git a/sound/direct_sound_samples/cries/gothorita.aif b/sound/direct_sound_samples/cries/gothorita.aif deleted file mode 100644 index d5491f83b5..0000000000 Binary files a/sound/direct_sound_samples/cries/gothorita.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/gothorita.wav b/sound/direct_sound_samples/cries/gothorita.wav new file mode 100644 index 0000000000..47686081f5 Binary files /dev/null and b/sound/direct_sound_samples/cries/gothorita.wav differ diff --git a/sound/direct_sound_samples/cries/gouging_fire.aif b/sound/direct_sound_samples/cries/gouging_fire.aif deleted file mode 100644 index 996a7d8070..0000000000 Binary files a/sound/direct_sound_samples/cries/gouging_fire.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/gouging_fire.wav b/sound/direct_sound_samples/cries/gouging_fire.wav new file mode 100644 index 0000000000..6748b9c9d8 Binary files /dev/null and b/sound/direct_sound_samples/cries/gouging_fire.wav differ diff --git a/sound/direct_sound_samples/cries/gourgeist.aif b/sound/direct_sound_samples/cries/gourgeist.aif deleted file mode 100644 index b1790cdd3c..0000000000 Binary files a/sound/direct_sound_samples/cries/gourgeist.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/gourgeist.wav b/sound/direct_sound_samples/cries/gourgeist.wav new file mode 100644 index 0000000000..f3db74b554 Binary files /dev/null and b/sound/direct_sound_samples/cries/gourgeist.wav differ diff --git a/sound/direct_sound_samples/cries/gourgeist_super.aif b/sound/direct_sound_samples/cries/gourgeist_super.aif deleted file mode 100644 index cdf93aca58..0000000000 Binary files a/sound/direct_sound_samples/cries/gourgeist_super.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/gourgeist_super.wav b/sound/direct_sound_samples/cries/gourgeist_super.wav new file mode 100644 index 0000000000..e319d5ba84 Binary files /dev/null and b/sound/direct_sound_samples/cries/gourgeist_super.wav differ diff --git a/sound/direct_sound_samples/cries/grafaiai.aif b/sound/direct_sound_samples/cries/grafaiai.aif deleted file mode 100644 index d8e8511eec..0000000000 Binary files a/sound/direct_sound_samples/cries/grafaiai.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/grafaiai.wav b/sound/direct_sound_samples/cries/grafaiai.wav new file mode 100644 index 0000000000..2d16b5e805 Binary files /dev/null and b/sound/direct_sound_samples/cries/grafaiai.wav differ diff --git a/sound/direct_sound_samples/cries/granbull.aif b/sound/direct_sound_samples/cries/granbull.aif deleted file mode 100644 index 87ed96a842..0000000000 Binary files a/sound/direct_sound_samples/cries/granbull.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/granbull.wav b/sound/direct_sound_samples/cries/granbull.wav new file mode 100644 index 0000000000..959793b724 Binary files /dev/null and b/sound/direct_sound_samples/cries/granbull.wav differ diff --git a/sound/direct_sound_samples/cries/grapploct.aif b/sound/direct_sound_samples/cries/grapploct.aif deleted file mode 100644 index 289d636ecb..0000000000 Binary files a/sound/direct_sound_samples/cries/grapploct.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/grapploct.wav b/sound/direct_sound_samples/cries/grapploct.wav new file mode 100644 index 0000000000..fb3b48ccc6 Binary files /dev/null and b/sound/direct_sound_samples/cries/grapploct.wav differ diff --git a/sound/direct_sound_samples/cries/graveler.aif b/sound/direct_sound_samples/cries/graveler.aif deleted file mode 100644 index fbf463c4fd..0000000000 Binary files a/sound/direct_sound_samples/cries/graveler.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/graveler.wav b/sound/direct_sound_samples/cries/graveler.wav new file mode 100644 index 0000000000..6b8591406f Binary files /dev/null and b/sound/direct_sound_samples/cries/graveler.wav differ diff --git a/sound/direct_sound_samples/cries/great_tusk.aif b/sound/direct_sound_samples/cries/great_tusk.aif deleted file mode 100644 index 4ca76ff6c0..0000000000 Binary files a/sound/direct_sound_samples/cries/great_tusk.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/great_tusk.wav b/sound/direct_sound_samples/cries/great_tusk.wav new file mode 100644 index 0000000000..0c7d0773ea Binary files /dev/null and b/sound/direct_sound_samples/cries/great_tusk.wav differ diff --git a/sound/direct_sound_samples/cries/greavard.aif b/sound/direct_sound_samples/cries/greavard.aif deleted file mode 100644 index 434c1dceb0..0000000000 Binary files a/sound/direct_sound_samples/cries/greavard.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/greavard.wav b/sound/direct_sound_samples/cries/greavard.wav new file mode 100644 index 0000000000..b93fd39327 Binary files /dev/null and b/sound/direct_sound_samples/cries/greavard.wav differ diff --git a/sound/direct_sound_samples/cries/greedent.aif b/sound/direct_sound_samples/cries/greedent.aif deleted file mode 100644 index 523cd57c3e..0000000000 Binary files a/sound/direct_sound_samples/cries/greedent.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/greedent.wav b/sound/direct_sound_samples/cries/greedent.wav new file mode 100644 index 0000000000..351e21c9e3 Binary files /dev/null and b/sound/direct_sound_samples/cries/greedent.wav differ diff --git a/sound/direct_sound_samples/cries/greninja.aif b/sound/direct_sound_samples/cries/greninja.aif deleted file mode 100644 index 988d66b062..0000000000 Binary files a/sound/direct_sound_samples/cries/greninja.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/greninja.wav b/sound/direct_sound_samples/cries/greninja.wav new file mode 100644 index 0000000000..3d097d8022 Binary files /dev/null and b/sound/direct_sound_samples/cries/greninja.wav differ diff --git a/sound/direct_sound_samples/cries/grimer.aif b/sound/direct_sound_samples/cries/grimer.aif deleted file mode 100644 index 050fb9620c..0000000000 Binary files a/sound/direct_sound_samples/cries/grimer.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/grimer.wav b/sound/direct_sound_samples/cries/grimer.wav new file mode 100644 index 0000000000..092dfeed61 Binary files /dev/null and b/sound/direct_sound_samples/cries/grimer.wav differ diff --git a/sound/direct_sound_samples/cries/grimmsnarl.aif b/sound/direct_sound_samples/cries/grimmsnarl.aif deleted file mode 100644 index 838312fde3..0000000000 Binary files a/sound/direct_sound_samples/cries/grimmsnarl.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/grimmsnarl.wav b/sound/direct_sound_samples/cries/grimmsnarl.wav new file mode 100644 index 0000000000..7fd3bb5c03 Binary files /dev/null and b/sound/direct_sound_samples/cries/grimmsnarl.wav differ diff --git a/sound/direct_sound_samples/cries/grookey.aif b/sound/direct_sound_samples/cries/grookey.aif deleted file mode 100644 index 919063484f..0000000000 Binary files a/sound/direct_sound_samples/cries/grookey.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/grookey.wav b/sound/direct_sound_samples/cries/grookey.wav new file mode 100644 index 0000000000..42ebd7ef1f Binary files /dev/null and b/sound/direct_sound_samples/cries/grookey.wav differ diff --git a/sound/direct_sound_samples/cries/grotle.aif b/sound/direct_sound_samples/cries/grotle.aif deleted file mode 100644 index 2b08bca67e..0000000000 Binary files a/sound/direct_sound_samples/cries/grotle.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/grotle.wav b/sound/direct_sound_samples/cries/grotle.wav new file mode 100644 index 0000000000..65cdfe49c6 Binary files /dev/null and b/sound/direct_sound_samples/cries/grotle.wav differ diff --git a/sound/direct_sound_samples/cries/groudon.aif b/sound/direct_sound_samples/cries/groudon.aif deleted file mode 100644 index 9fe253745a..0000000000 Binary files a/sound/direct_sound_samples/cries/groudon.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/groudon.wav b/sound/direct_sound_samples/cries/groudon.wav new file mode 100644 index 0000000000..680d0ec047 Binary files /dev/null and b/sound/direct_sound_samples/cries/groudon.wav differ diff --git a/sound/direct_sound_samples/cries/groudon_primal.aif b/sound/direct_sound_samples/cries/groudon_primal.aif deleted file mode 100644 index a93d06a3fe..0000000000 Binary files a/sound/direct_sound_samples/cries/groudon_primal.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/groudon_primal.wav b/sound/direct_sound_samples/cries/groudon_primal.wav new file mode 100644 index 0000000000..d3e5f41191 Binary files /dev/null and b/sound/direct_sound_samples/cries/groudon_primal.wav differ diff --git a/sound/direct_sound_samples/cries/grovyle.aif b/sound/direct_sound_samples/cries/grovyle.aif deleted file mode 100644 index c21c58ad09..0000000000 Binary files a/sound/direct_sound_samples/cries/grovyle.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/grovyle.wav b/sound/direct_sound_samples/cries/grovyle.wav new file mode 100644 index 0000000000..7e2f1acd0f Binary files /dev/null and b/sound/direct_sound_samples/cries/grovyle.wav differ diff --git a/sound/direct_sound_samples/cries/growlithe.aif b/sound/direct_sound_samples/cries/growlithe.aif deleted file mode 100644 index 37b7233c29..0000000000 Binary files a/sound/direct_sound_samples/cries/growlithe.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/growlithe.wav b/sound/direct_sound_samples/cries/growlithe.wav new file mode 100644 index 0000000000..3f72ea6f97 Binary files /dev/null and b/sound/direct_sound_samples/cries/growlithe.wav differ diff --git a/sound/direct_sound_samples/cries/grubbin.aif b/sound/direct_sound_samples/cries/grubbin.aif deleted file mode 100644 index 8e071f7815..0000000000 Binary files a/sound/direct_sound_samples/cries/grubbin.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/grubbin.wav b/sound/direct_sound_samples/cries/grubbin.wav new file mode 100644 index 0000000000..f76a663051 Binary files /dev/null and b/sound/direct_sound_samples/cries/grubbin.wav differ diff --git a/sound/direct_sound_samples/cries/grumpig.aif b/sound/direct_sound_samples/cries/grumpig.aif deleted file mode 100644 index d5b766f43e..0000000000 Binary files a/sound/direct_sound_samples/cries/grumpig.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/grumpig.wav b/sound/direct_sound_samples/cries/grumpig.wav new file mode 100644 index 0000000000..e9c8157e0f Binary files /dev/null and b/sound/direct_sound_samples/cries/grumpig.wav differ diff --git a/sound/direct_sound_samples/cries/gulpin.aif b/sound/direct_sound_samples/cries/gulpin.aif deleted file mode 100644 index 4b0bc89b96..0000000000 Binary files a/sound/direct_sound_samples/cries/gulpin.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/gulpin.wav b/sound/direct_sound_samples/cries/gulpin.wav new file mode 100644 index 0000000000..d1ab06b6b0 Binary files /dev/null and b/sound/direct_sound_samples/cries/gulpin.wav differ diff --git a/sound/direct_sound_samples/cries/gumshoos.aif b/sound/direct_sound_samples/cries/gumshoos.aif deleted file mode 100644 index 9f078f85db..0000000000 Binary files a/sound/direct_sound_samples/cries/gumshoos.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/gumshoos.wav b/sound/direct_sound_samples/cries/gumshoos.wav new file mode 100644 index 0000000000..9bbfb863b6 Binary files /dev/null and b/sound/direct_sound_samples/cries/gumshoos.wav differ diff --git a/sound/direct_sound_samples/cries/gurdurr.aif b/sound/direct_sound_samples/cries/gurdurr.aif deleted file mode 100644 index 055d366a91..0000000000 Binary files a/sound/direct_sound_samples/cries/gurdurr.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/gurdurr.wav b/sound/direct_sound_samples/cries/gurdurr.wav new file mode 100644 index 0000000000..ba73ebdcc1 Binary files /dev/null and b/sound/direct_sound_samples/cries/gurdurr.wav differ diff --git a/sound/direct_sound_samples/cries/guzzlord.aif b/sound/direct_sound_samples/cries/guzzlord.aif deleted file mode 100644 index 958e0b7ed3..0000000000 Binary files a/sound/direct_sound_samples/cries/guzzlord.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/guzzlord.wav b/sound/direct_sound_samples/cries/guzzlord.wav new file mode 100644 index 0000000000..15404dea56 Binary files /dev/null and b/sound/direct_sound_samples/cries/guzzlord.wav differ diff --git a/sound/direct_sound_samples/cries/gyarados.aif b/sound/direct_sound_samples/cries/gyarados.aif deleted file mode 100644 index f4b5dbf945..0000000000 Binary files a/sound/direct_sound_samples/cries/gyarados.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/gyarados.wav b/sound/direct_sound_samples/cries/gyarados.wav new file mode 100644 index 0000000000..6a4124085e Binary files /dev/null and b/sound/direct_sound_samples/cries/gyarados.wav differ diff --git a/sound/direct_sound_samples/cries/gyarados_mega.aif b/sound/direct_sound_samples/cries/gyarados_mega.aif deleted file mode 100644 index 33f9eadc3b..0000000000 Binary files a/sound/direct_sound_samples/cries/gyarados_mega.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/gyarados_mega.wav b/sound/direct_sound_samples/cries/gyarados_mega.wav new file mode 100644 index 0000000000..d14a015dd6 Binary files /dev/null and b/sound/direct_sound_samples/cries/gyarados_mega.wav differ diff --git a/sound/direct_sound_samples/cries/hakamo_o.aif b/sound/direct_sound_samples/cries/hakamo_o.aif deleted file mode 100644 index 03d2ff241a..0000000000 Binary files a/sound/direct_sound_samples/cries/hakamo_o.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/hakamo_o.wav b/sound/direct_sound_samples/cries/hakamo_o.wav new file mode 100644 index 0000000000..c668cad629 Binary files /dev/null and b/sound/direct_sound_samples/cries/hakamo_o.wav differ diff --git a/sound/direct_sound_samples/cries/happiny.aif b/sound/direct_sound_samples/cries/happiny.aif deleted file mode 100644 index bee72680ac..0000000000 Binary files a/sound/direct_sound_samples/cries/happiny.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/happiny.wav b/sound/direct_sound_samples/cries/happiny.wav new file mode 100644 index 0000000000..6d310d8d59 Binary files /dev/null and b/sound/direct_sound_samples/cries/happiny.wav differ diff --git a/sound/direct_sound_samples/cries/hariyama.aif b/sound/direct_sound_samples/cries/hariyama.aif deleted file mode 100644 index 0a61e0d8ae..0000000000 Binary files a/sound/direct_sound_samples/cries/hariyama.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/hariyama.wav b/sound/direct_sound_samples/cries/hariyama.wav new file mode 100644 index 0000000000..5567aae3a1 Binary files /dev/null and b/sound/direct_sound_samples/cries/hariyama.wav differ diff --git a/sound/direct_sound_samples/cries/hatenna.aif b/sound/direct_sound_samples/cries/hatenna.aif deleted file mode 100644 index 3c431dd65f..0000000000 Binary files a/sound/direct_sound_samples/cries/hatenna.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/hatenna.wav b/sound/direct_sound_samples/cries/hatenna.wav new file mode 100644 index 0000000000..78e63ac2b4 Binary files /dev/null and b/sound/direct_sound_samples/cries/hatenna.wav differ diff --git a/sound/direct_sound_samples/cries/hatterene.aif b/sound/direct_sound_samples/cries/hatterene.aif deleted file mode 100644 index db21eb2e20..0000000000 Binary files a/sound/direct_sound_samples/cries/hatterene.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/hatterene.wav b/sound/direct_sound_samples/cries/hatterene.wav new file mode 100644 index 0000000000..27dfcf2db7 Binary files /dev/null and b/sound/direct_sound_samples/cries/hatterene.wav differ diff --git a/sound/direct_sound_samples/cries/hattrem.aif b/sound/direct_sound_samples/cries/hattrem.aif deleted file mode 100644 index 444c770283..0000000000 Binary files a/sound/direct_sound_samples/cries/hattrem.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/hattrem.wav b/sound/direct_sound_samples/cries/hattrem.wav new file mode 100644 index 0000000000..5da7c40af1 Binary files /dev/null and b/sound/direct_sound_samples/cries/hattrem.wav differ diff --git a/sound/direct_sound_samples/cries/haunter.aif b/sound/direct_sound_samples/cries/haunter.aif deleted file mode 100644 index c9192cf9bc..0000000000 Binary files a/sound/direct_sound_samples/cries/haunter.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/haunter.wav b/sound/direct_sound_samples/cries/haunter.wav new file mode 100644 index 0000000000..e22b1cfc13 Binary files /dev/null and b/sound/direct_sound_samples/cries/haunter.wav differ diff --git a/sound/direct_sound_samples/cries/hawlucha.aif b/sound/direct_sound_samples/cries/hawlucha.aif deleted file mode 100644 index 0e4d9c78d1..0000000000 Binary files a/sound/direct_sound_samples/cries/hawlucha.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/hawlucha.wav b/sound/direct_sound_samples/cries/hawlucha.wav new file mode 100644 index 0000000000..629365ac41 Binary files /dev/null and b/sound/direct_sound_samples/cries/hawlucha.wav differ diff --git a/sound/direct_sound_samples/cries/haxorus.aif b/sound/direct_sound_samples/cries/haxorus.aif deleted file mode 100644 index 8414951d49..0000000000 Binary files a/sound/direct_sound_samples/cries/haxorus.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/haxorus.wav b/sound/direct_sound_samples/cries/haxorus.wav new file mode 100644 index 0000000000..7ebe8ba8d5 Binary files /dev/null and b/sound/direct_sound_samples/cries/haxorus.wav differ diff --git a/sound/direct_sound_samples/cries/heatmor.aif b/sound/direct_sound_samples/cries/heatmor.aif deleted file mode 100644 index 2a254ef0d9..0000000000 Binary files a/sound/direct_sound_samples/cries/heatmor.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/heatmor.wav b/sound/direct_sound_samples/cries/heatmor.wav new file mode 100644 index 0000000000..d340755c8a Binary files /dev/null and b/sound/direct_sound_samples/cries/heatmor.wav differ diff --git a/sound/direct_sound_samples/cries/heatran.aif b/sound/direct_sound_samples/cries/heatran.aif deleted file mode 100644 index 56c373d8d8..0000000000 Binary files a/sound/direct_sound_samples/cries/heatran.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/heatran.wav b/sound/direct_sound_samples/cries/heatran.wav new file mode 100644 index 0000000000..f3388a0756 Binary files /dev/null and b/sound/direct_sound_samples/cries/heatran.wav differ diff --git a/sound/direct_sound_samples/cries/heliolisk.aif b/sound/direct_sound_samples/cries/heliolisk.aif deleted file mode 100644 index d87e7bfd2a..0000000000 Binary files a/sound/direct_sound_samples/cries/heliolisk.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/heliolisk.wav b/sound/direct_sound_samples/cries/heliolisk.wav new file mode 100644 index 0000000000..801d5968c3 Binary files /dev/null and b/sound/direct_sound_samples/cries/heliolisk.wav differ diff --git a/sound/direct_sound_samples/cries/helioptile.aif b/sound/direct_sound_samples/cries/helioptile.aif deleted file mode 100644 index aa1a9fb3a6..0000000000 Binary files a/sound/direct_sound_samples/cries/helioptile.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/helioptile.wav b/sound/direct_sound_samples/cries/helioptile.wav new file mode 100644 index 0000000000..39c1fc5327 Binary files /dev/null and b/sound/direct_sound_samples/cries/helioptile.wav differ diff --git a/sound/direct_sound_samples/cries/heracross.aif b/sound/direct_sound_samples/cries/heracross.aif deleted file mode 100644 index 1fe12ed524..0000000000 Binary files a/sound/direct_sound_samples/cries/heracross.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/heracross.wav b/sound/direct_sound_samples/cries/heracross.wav new file mode 100644 index 0000000000..ed68648ba8 Binary files /dev/null and b/sound/direct_sound_samples/cries/heracross.wav differ diff --git a/sound/direct_sound_samples/cries/heracross_mega.aif b/sound/direct_sound_samples/cries/heracross_mega.aif deleted file mode 100644 index e1993473c2..0000000000 Binary files a/sound/direct_sound_samples/cries/heracross_mega.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/heracross_mega.wav b/sound/direct_sound_samples/cries/heracross_mega.wav new file mode 100644 index 0000000000..79d9a58797 Binary files /dev/null and b/sound/direct_sound_samples/cries/heracross_mega.wav differ diff --git a/sound/direct_sound_samples/cries/herdier.aif b/sound/direct_sound_samples/cries/herdier.aif deleted file mode 100644 index bc798f60b5..0000000000 Binary files a/sound/direct_sound_samples/cries/herdier.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/herdier.wav b/sound/direct_sound_samples/cries/herdier.wav new file mode 100644 index 0000000000..f272d2b01b Binary files /dev/null and b/sound/direct_sound_samples/cries/herdier.wav differ diff --git a/sound/direct_sound_samples/cries/hippopotas.aif b/sound/direct_sound_samples/cries/hippopotas.aif deleted file mode 100644 index a8828805fe..0000000000 Binary files a/sound/direct_sound_samples/cries/hippopotas.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/hippopotas.wav b/sound/direct_sound_samples/cries/hippopotas.wav new file mode 100644 index 0000000000..c94da0f439 Binary files /dev/null and b/sound/direct_sound_samples/cries/hippopotas.wav differ diff --git a/sound/direct_sound_samples/cries/hippowdon.aif b/sound/direct_sound_samples/cries/hippowdon.aif deleted file mode 100644 index 94649f3f25..0000000000 Binary files a/sound/direct_sound_samples/cries/hippowdon.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/hippowdon.wav b/sound/direct_sound_samples/cries/hippowdon.wav new file mode 100644 index 0000000000..ee24375a55 Binary files /dev/null and b/sound/direct_sound_samples/cries/hippowdon.wav differ diff --git a/sound/direct_sound_samples/cries/hitmonchan.aif b/sound/direct_sound_samples/cries/hitmonchan.aif deleted file mode 100644 index 279370fc9c..0000000000 Binary files a/sound/direct_sound_samples/cries/hitmonchan.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/hitmonchan.wav b/sound/direct_sound_samples/cries/hitmonchan.wav new file mode 100644 index 0000000000..806d206d35 Binary files /dev/null and b/sound/direct_sound_samples/cries/hitmonchan.wav differ diff --git a/sound/direct_sound_samples/cries/hitmonlee.aif b/sound/direct_sound_samples/cries/hitmonlee.aif deleted file mode 100644 index d388565df8..0000000000 Binary files a/sound/direct_sound_samples/cries/hitmonlee.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/hitmonlee.wav b/sound/direct_sound_samples/cries/hitmonlee.wav new file mode 100644 index 0000000000..e40d852b99 Binary files /dev/null and b/sound/direct_sound_samples/cries/hitmonlee.wav differ diff --git a/sound/direct_sound_samples/cries/hitmontop.aif b/sound/direct_sound_samples/cries/hitmontop.aif deleted file mode 100644 index 237e0a6b0f..0000000000 Binary files a/sound/direct_sound_samples/cries/hitmontop.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/hitmontop.wav b/sound/direct_sound_samples/cries/hitmontop.wav new file mode 100644 index 0000000000..652222dc6c Binary files /dev/null and b/sound/direct_sound_samples/cries/hitmontop.wav differ diff --git a/sound/direct_sound_samples/cries/ho_oh.aif b/sound/direct_sound_samples/cries/ho_oh.aif deleted file mode 100644 index 886d66813a..0000000000 Binary files a/sound/direct_sound_samples/cries/ho_oh.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/ho_oh.wav b/sound/direct_sound_samples/cries/ho_oh.wav new file mode 100644 index 0000000000..acf8812532 Binary files /dev/null and b/sound/direct_sound_samples/cries/ho_oh.wav differ diff --git a/sound/direct_sound_samples/cries/honchkrow.aif b/sound/direct_sound_samples/cries/honchkrow.aif deleted file mode 100644 index ae3ceda671..0000000000 Binary files a/sound/direct_sound_samples/cries/honchkrow.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/honchkrow.wav b/sound/direct_sound_samples/cries/honchkrow.wav new file mode 100644 index 0000000000..6ebbb5e429 Binary files /dev/null and b/sound/direct_sound_samples/cries/honchkrow.wav differ diff --git a/sound/direct_sound_samples/cries/honedge.aif b/sound/direct_sound_samples/cries/honedge.aif deleted file mode 100644 index e1204fddfe..0000000000 Binary files a/sound/direct_sound_samples/cries/honedge.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/honedge.wav b/sound/direct_sound_samples/cries/honedge.wav new file mode 100644 index 0000000000..bf3136b3ad Binary files /dev/null and b/sound/direct_sound_samples/cries/honedge.wav differ diff --git a/sound/direct_sound_samples/cries/hoopa_confined.aif b/sound/direct_sound_samples/cries/hoopa_confined.aif deleted file mode 100644 index 2d91b4982a..0000000000 Binary files a/sound/direct_sound_samples/cries/hoopa_confined.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/hoopa_confined.wav b/sound/direct_sound_samples/cries/hoopa_confined.wav new file mode 100644 index 0000000000..d5f50a8b42 Binary files /dev/null and b/sound/direct_sound_samples/cries/hoopa_confined.wav differ diff --git a/sound/direct_sound_samples/cries/hoopa_unbound.aif b/sound/direct_sound_samples/cries/hoopa_unbound.aif deleted file mode 100644 index 2b4d84015b..0000000000 Binary files a/sound/direct_sound_samples/cries/hoopa_unbound.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/hoopa_unbound.wav b/sound/direct_sound_samples/cries/hoopa_unbound.wav new file mode 100644 index 0000000000..319a519a88 Binary files /dev/null and b/sound/direct_sound_samples/cries/hoopa_unbound.wav differ diff --git a/sound/direct_sound_samples/cries/hoothoot.aif b/sound/direct_sound_samples/cries/hoothoot.aif deleted file mode 100644 index 52bccc8e91..0000000000 Binary files a/sound/direct_sound_samples/cries/hoothoot.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/hoothoot.wav b/sound/direct_sound_samples/cries/hoothoot.wav new file mode 100644 index 0000000000..e7ca2f5780 Binary files /dev/null and b/sound/direct_sound_samples/cries/hoothoot.wav differ diff --git a/sound/direct_sound_samples/cries/hoppip.aif b/sound/direct_sound_samples/cries/hoppip.aif deleted file mode 100644 index e715705f08..0000000000 Binary files a/sound/direct_sound_samples/cries/hoppip.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/hoppip.wav b/sound/direct_sound_samples/cries/hoppip.wav new file mode 100644 index 0000000000..ab14fdaec7 Binary files /dev/null and b/sound/direct_sound_samples/cries/hoppip.wav differ diff --git a/sound/direct_sound_samples/cries/horsea.aif b/sound/direct_sound_samples/cries/horsea.aif deleted file mode 100644 index 12801a2076..0000000000 Binary files a/sound/direct_sound_samples/cries/horsea.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/horsea.wav b/sound/direct_sound_samples/cries/horsea.wav new file mode 100644 index 0000000000..ab67381edd Binary files /dev/null and b/sound/direct_sound_samples/cries/horsea.wav differ diff --git a/sound/direct_sound_samples/cries/houndoom.aif b/sound/direct_sound_samples/cries/houndoom.aif deleted file mode 100644 index 09c6e4957f..0000000000 Binary files a/sound/direct_sound_samples/cries/houndoom.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/houndoom.wav b/sound/direct_sound_samples/cries/houndoom.wav new file mode 100644 index 0000000000..a34e4cda2b Binary files /dev/null and b/sound/direct_sound_samples/cries/houndoom.wav differ diff --git a/sound/direct_sound_samples/cries/houndoom_mega.aif b/sound/direct_sound_samples/cries/houndoom_mega.aif deleted file mode 100644 index 102f822cc6..0000000000 Binary files a/sound/direct_sound_samples/cries/houndoom_mega.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/houndoom_mega.wav b/sound/direct_sound_samples/cries/houndoom_mega.wav new file mode 100644 index 0000000000..3b50f94920 Binary files /dev/null and b/sound/direct_sound_samples/cries/houndoom_mega.wav differ diff --git a/sound/direct_sound_samples/cries/houndour.aif b/sound/direct_sound_samples/cries/houndour.aif deleted file mode 100644 index 352d8fd897..0000000000 Binary files a/sound/direct_sound_samples/cries/houndour.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/houndour.wav b/sound/direct_sound_samples/cries/houndour.wav new file mode 100644 index 0000000000..51310524a8 Binary files /dev/null and b/sound/direct_sound_samples/cries/houndour.wav differ diff --git a/sound/direct_sound_samples/cries/houndstone.aif b/sound/direct_sound_samples/cries/houndstone.aif deleted file mode 100644 index 99e699b7ba..0000000000 Binary files a/sound/direct_sound_samples/cries/houndstone.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/houndstone.wav b/sound/direct_sound_samples/cries/houndstone.wav new file mode 100644 index 0000000000..d70441d7bd Binary files /dev/null and b/sound/direct_sound_samples/cries/houndstone.wav differ diff --git a/sound/direct_sound_samples/cries/huntail.aif b/sound/direct_sound_samples/cries/huntail.aif deleted file mode 100644 index b520d2b7a8..0000000000 Binary files a/sound/direct_sound_samples/cries/huntail.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/huntail.wav b/sound/direct_sound_samples/cries/huntail.wav new file mode 100644 index 0000000000..b2e3f99853 Binary files /dev/null and b/sound/direct_sound_samples/cries/huntail.wav differ diff --git a/sound/direct_sound_samples/cries/hydrapple.aif b/sound/direct_sound_samples/cries/hydrapple.aif deleted file mode 100644 index 45f5fd9ca0..0000000000 Binary files a/sound/direct_sound_samples/cries/hydrapple.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/hydrapple.wav b/sound/direct_sound_samples/cries/hydrapple.wav new file mode 100644 index 0000000000..e3da4677a8 Binary files /dev/null and b/sound/direct_sound_samples/cries/hydrapple.wav differ diff --git a/sound/direct_sound_samples/cries/hydreigon.aif b/sound/direct_sound_samples/cries/hydreigon.aif deleted file mode 100644 index 8227c6d21f..0000000000 Binary files a/sound/direct_sound_samples/cries/hydreigon.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/hydreigon.wav b/sound/direct_sound_samples/cries/hydreigon.wav new file mode 100644 index 0000000000..ce816dcc58 Binary files /dev/null and b/sound/direct_sound_samples/cries/hydreigon.wav differ diff --git a/sound/direct_sound_samples/cries/hypno.aif b/sound/direct_sound_samples/cries/hypno.aif deleted file mode 100644 index 7c4bde1936..0000000000 Binary files a/sound/direct_sound_samples/cries/hypno.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/hypno.wav b/sound/direct_sound_samples/cries/hypno.wav new file mode 100644 index 0000000000..4369110c2c Binary files /dev/null and b/sound/direct_sound_samples/cries/hypno.wav differ diff --git a/sound/direct_sound_samples/cries/igglybuff.aif b/sound/direct_sound_samples/cries/igglybuff.aif deleted file mode 100644 index 0f2db1e52c..0000000000 Binary files a/sound/direct_sound_samples/cries/igglybuff.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/igglybuff.wav b/sound/direct_sound_samples/cries/igglybuff.wav new file mode 100644 index 0000000000..efec9bf4c4 Binary files /dev/null and b/sound/direct_sound_samples/cries/igglybuff.wav differ diff --git a/sound/direct_sound_samples/cries/illumise.aif b/sound/direct_sound_samples/cries/illumise.aif deleted file mode 100644 index 26807295bd..0000000000 Binary files a/sound/direct_sound_samples/cries/illumise.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/illumise.wav b/sound/direct_sound_samples/cries/illumise.wav new file mode 100644 index 0000000000..6570492f79 Binary files /dev/null and b/sound/direct_sound_samples/cries/illumise.wav differ diff --git a/sound/direct_sound_samples/cries/impidimp.aif b/sound/direct_sound_samples/cries/impidimp.aif deleted file mode 100644 index 0abad6cb1e..0000000000 Binary files a/sound/direct_sound_samples/cries/impidimp.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/impidimp.wav b/sound/direct_sound_samples/cries/impidimp.wav new file mode 100644 index 0000000000..1bc578a9b8 Binary files /dev/null and b/sound/direct_sound_samples/cries/impidimp.wav differ diff --git a/sound/direct_sound_samples/cries/incineroar.aif b/sound/direct_sound_samples/cries/incineroar.aif deleted file mode 100644 index b7f3e2201e..0000000000 Binary files a/sound/direct_sound_samples/cries/incineroar.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/incineroar.wav b/sound/direct_sound_samples/cries/incineroar.wav new file mode 100644 index 0000000000..f4b9bcd598 Binary files /dev/null and b/sound/direct_sound_samples/cries/incineroar.wav differ diff --git a/sound/direct_sound_samples/cries/indeedee_female.aif b/sound/direct_sound_samples/cries/indeedee_female.aif deleted file mode 100644 index b5e5fe4547..0000000000 Binary files a/sound/direct_sound_samples/cries/indeedee_female.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/indeedee_female.wav b/sound/direct_sound_samples/cries/indeedee_female.wav new file mode 100644 index 0000000000..f7b563c1d1 Binary files /dev/null and b/sound/direct_sound_samples/cries/indeedee_female.wav differ diff --git a/sound/direct_sound_samples/cries/indeedee_male.aif b/sound/direct_sound_samples/cries/indeedee_male.aif deleted file mode 100644 index b5d950391e..0000000000 Binary files a/sound/direct_sound_samples/cries/indeedee_male.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/indeedee_male.wav b/sound/direct_sound_samples/cries/indeedee_male.wav new file mode 100644 index 0000000000..554ec96593 Binary files /dev/null and b/sound/direct_sound_samples/cries/indeedee_male.wav differ diff --git a/sound/direct_sound_samples/cries/infernape.aif b/sound/direct_sound_samples/cries/infernape.aif deleted file mode 100644 index d4570a8f3a..0000000000 Binary files a/sound/direct_sound_samples/cries/infernape.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/infernape.wav b/sound/direct_sound_samples/cries/infernape.wav new file mode 100644 index 0000000000..71e4af161d Binary files /dev/null and b/sound/direct_sound_samples/cries/infernape.wav differ diff --git a/sound/direct_sound_samples/cries/inkay.aif b/sound/direct_sound_samples/cries/inkay.aif deleted file mode 100644 index 04753026e0..0000000000 Binary files a/sound/direct_sound_samples/cries/inkay.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/inkay.wav b/sound/direct_sound_samples/cries/inkay.wav new file mode 100644 index 0000000000..dace2b5c24 Binary files /dev/null and b/sound/direct_sound_samples/cries/inkay.wav differ diff --git a/sound/direct_sound_samples/cries/inteleon.aif b/sound/direct_sound_samples/cries/inteleon.aif deleted file mode 100644 index 8153b02889..0000000000 Binary files a/sound/direct_sound_samples/cries/inteleon.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/inteleon.wav b/sound/direct_sound_samples/cries/inteleon.wav new file mode 100644 index 0000000000..8bef61a449 Binary files /dev/null and b/sound/direct_sound_samples/cries/inteleon.wav differ diff --git a/sound/direct_sound_samples/cries/iron_boulder.aif b/sound/direct_sound_samples/cries/iron_boulder.aif deleted file mode 100644 index 0ffdefdffb..0000000000 Binary files a/sound/direct_sound_samples/cries/iron_boulder.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/iron_boulder.wav b/sound/direct_sound_samples/cries/iron_boulder.wav new file mode 100644 index 0000000000..df02d73d5c Binary files /dev/null and b/sound/direct_sound_samples/cries/iron_boulder.wav differ diff --git a/sound/direct_sound_samples/cries/iron_bundle.aif b/sound/direct_sound_samples/cries/iron_bundle.aif deleted file mode 100644 index 51c9e0b60c..0000000000 Binary files a/sound/direct_sound_samples/cries/iron_bundle.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/iron_bundle.wav b/sound/direct_sound_samples/cries/iron_bundle.wav new file mode 100644 index 0000000000..796ee101fe Binary files /dev/null and b/sound/direct_sound_samples/cries/iron_bundle.wav differ diff --git a/sound/direct_sound_samples/cries/iron_crown.aif b/sound/direct_sound_samples/cries/iron_crown.aif deleted file mode 100644 index 8c310455dc..0000000000 Binary files a/sound/direct_sound_samples/cries/iron_crown.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/iron_crown.wav b/sound/direct_sound_samples/cries/iron_crown.wav new file mode 100644 index 0000000000..984f1c5a79 Binary files /dev/null and b/sound/direct_sound_samples/cries/iron_crown.wav differ diff --git a/sound/direct_sound_samples/cries/iron_hands.aif b/sound/direct_sound_samples/cries/iron_hands.aif deleted file mode 100644 index 621e4fdc19..0000000000 Binary files a/sound/direct_sound_samples/cries/iron_hands.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/iron_hands.wav b/sound/direct_sound_samples/cries/iron_hands.wav new file mode 100644 index 0000000000..c5b0332263 Binary files /dev/null and b/sound/direct_sound_samples/cries/iron_hands.wav differ diff --git a/sound/direct_sound_samples/cries/iron_jugulis.aif b/sound/direct_sound_samples/cries/iron_jugulis.aif deleted file mode 100644 index 8409934f89..0000000000 Binary files a/sound/direct_sound_samples/cries/iron_jugulis.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/iron_jugulis.wav b/sound/direct_sound_samples/cries/iron_jugulis.wav new file mode 100644 index 0000000000..a6e883a57b Binary files /dev/null and b/sound/direct_sound_samples/cries/iron_jugulis.wav differ diff --git a/sound/direct_sound_samples/cries/iron_leaves.aif b/sound/direct_sound_samples/cries/iron_leaves.aif deleted file mode 100644 index 45e0a420e2..0000000000 Binary files a/sound/direct_sound_samples/cries/iron_leaves.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/iron_leaves.wav b/sound/direct_sound_samples/cries/iron_leaves.wav new file mode 100644 index 0000000000..b22f193e99 Binary files /dev/null and b/sound/direct_sound_samples/cries/iron_leaves.wav differ diff --git a/sound/direct_sound_samples/cries/iron_moth.aif b/sound/direct_sound_samples/cries/iron_moth.aif deleted file mode 100644 index fb90d30481..0000000000 Binary files a/sound/direct_sound_samples/cries/iron_moth.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/iron_moth.wav b/sound/direct_sound_samples/cries/iron_moth.wav new file mode 100644 index 0000000000..297be2d0b9 Binary files /dev/null and b/sound/direct_sound_samples/cries/iron_moth.wav differ diff --git a/sound/direct_sound_samples/cries/iron_thorns.aif b/sound/direct_sound_samples/cries/iron_thorns.aif deleted file mode 100644 index ac88055c6d..0000000000 Binary files a/sound/direct_sound_samples/cries/iron_thorns.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/iron_thorns.wav b/sound/direct_sound_samples/cries/iron_thorns.wav new file mode 100644 index 0000000000..b04462c057 Binary files /dev/null and b/sound/direct_sound_samples/cries/iron_thorns.wav differ diff --git a/sound/direct_sound_samples/cries/iron_treads.aif b/sound/direct_sound_samples/cries/iron_treads.aif deleted file mode 100644 index e3b0471711..0000000000 Binary files a/sound/direct_sound_samples/cries/iron_treads.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/iron_treads.wav b/sound/direct_sound_samples/cries/iron_treads.wav new file mode 100644 index 0000000000..51f3143b5b Binary files /dev/null and b/sound/direct_sound_samples/cries/iron_treads.wav differ diff --git a/sound/direct_sound_samples/cries/iron_valiant.aif b/sound/direct_sound_samples/cries/iron_valiant.aif deleted file mode 100644 index 04220e9f62..0000000000 Binary files a/sound/direct_sound_samples/cries/iron_valiant.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/iron_valiant.wav b/sound/direct_sound_samples/cries/iron_valiant.wav new file mode 100644 index 0000000000..bf110f88a3 Binary files /dev/null and b/sound/direct_sound_samples/cries/iron_valiant.wav differ diff --git a/sound/direct_sound_samples/cries/ivysaur.aif b/sound/direct_sound_samples/cries/ivysaur.aif deleted file mode 100644 index 40ee462805..0000000000 Binary files a/sound/direct_sound_samples/cries/ivysaur.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/ivysaur.wav b/sound/direct_sound_samples/cries/ivysaur.wav new file mode 100644 index 0000000000..07d10c0e8d Binary files /dev/null and b/sound/direct_sound_samples/cries/ivysaur.wav differ diff --git a/sound/direct_sound_samples/cries/jangmo_o.aif b/sound/direct_sound_samples/cries/jangmo_o.aif deleted file mode 100644 index 29f8f86b51..0000000000 Binary files a/sound/direct_sound_samples/cries/jangmo_o.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/jangmo_o.wav b/sound/direct_sound_samples/cries/jangmo_o.wav new file mode 100644 index 0000000000..96e08b0c96 Binary files /dev/null and b/sound/direct_sound_samples/cries/jangmo_o.wav differ diff --git a/sound/direct_sound_samples/cries/jellicent.aif b/sound/direct_sound_samples/cries/jellicent.aif deleted file mode 100644 index 33f6cf5aea..0000000000 Binary files a/sound/direct_sound_samples/cries/jellicent.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/jellicent.wav b/sound/direct_sound_samples/cries/jellicent.wav new file mode 100644 index 0000000000..221c787864 Binary files /dev/null and b/sound/direct_sound_samples/cries/jellicent.wav differ diff --git a/sound/direct_sound_samples/cries/jigglypuff.aif b/sound/direct_sound_samples/cries/jigglypuff.aif deleted file mode 100644 index 09249f6dd6..0000000000 Binary files a/sound/direct_sound_samples/cries/jigglypuff.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/jigglypuff.wav b/sound/direct_sound_samples/cries/jigglypuff.wav new file mode 100644 index 0000000000..d3e925fe94 Binary files /dev/null and b/sound/direct_sound_samples/cries/jigglypuff.wav differ diff --git a/sound/direct_sound_samples/cries/jirachi.aif b/sound/direct_sound_samples/cries/jirachi.aif deleted file mode 100644 index 0da759794c..0000000000 Binary files a/sound/direct_sound_samples/cries/jirachi.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/jirachi.wav b/sound/direct_sound_samples/cries/jirachi.wav new file mode 100644 index 0000000000..43850cbaa0 Binary files /dev/null and b/sound/direct_sound_samples/cries/jirachi.wav differ diff --git a/sound/direct_sound_samples/cries/jolteon.aif b/sound/direct_sound_samples/cries/jolteon.aif deleted file mode 100644 index acd96714ae..0000000000 Binary files a/sound/direct_sound_samples/cries/jolteon.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/jolteon.wav b/sound/direct_sound_samples/cries/jolteon.wav new file mode 100644 index 0000000000..8c5f8bea4c Binary files /dev/null and b/sound/direct_sound_samples/cries/jolteon.wav differ diff --git a/sound/direct_sound_samples/cries/joltik.aif b/sound/direct_sound_samples/cries/joltik.aif deleted file mode 100644 index a67354d74c..0000000000 Binary files a/sound/direct_sound_samples/cries/joltik.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/joltik.wav b/sound/direct_sound_samples/cries/joltik.wav new file mode 100644 index 0000000000..4fa360d6b6 Binary files /dev/null and b/sound/direct_sound_samples/cries/joltik.wav differ diff --git a/sound/direct_sound_samples/cries/jumpluff.aif b/sound/direct_sound_samples/cries/jumpluff.aif deleted file mode 100644 index 2b93dad558..0000000000 Binary files a/sound/direct_sound_samples/cries/jumpluff.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/jumpluff.wav b/sound/direct_sound_samples/cries/jumpluff.wav new file mode 100644 index 0000000000..cce951b1f7 Binary files /dev/null and b/sound/direct_sound_samples/cries/jumpluff.wav differ diff --git a/sound/direct_sound_samples/cries/jynx.aif b/sound/direct_sound_samples/cries/jynx.aif deleted file mode 100644 index cbcd7ee99d..0000000000 Binary files a/sound/direct_sound_samples/cries/jynx.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/jynx.wav b/sound/direct_sound_samples/cries/jynx.wav new file mode 100644 index 0000000000..faacb1e957 Binary files /dev/null and b/sound/direct_sound_samples/cries/jynx.wav differ diff --git a/sound/direct_sound_samples/cries/kabuto.aif b/sound/direct_sound_samples/cries/kabuto.aif deleted file mode 100644 index 2ed73716cb..0000000000 Binary files a/sound/direct_sound_samples/cries/kabuto.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/kabuto.wav b/sound/direct_sound_samples/cries/kabuto.wav new file mode 100644 index 0000000000..448b178914 Binary files /dev/null and b/sound/direct_sound_samples/cries/kabuto.wav differ diff --git a/sound/direct_sound_samples/cries/kabutops.aif b/sound/direct_sound_samples/cries/kabutops.aif deleted file mode 100644 index 79a4b304a8..0000000000 Binary files a/sound/direct_sound_samples/cries/kabutops.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/kabutops.wav b/sound/direct_sound_samples/cries/kabutops.wav new file mode 100644 index 0000000000..0c7b74fea3 Binary files /dev/null and b/sound/direct_sound_samples/cries/kabutops.wav differ diff --git a/sound/direct_sound_samples/cries/kadabra.aif b/sound/direct_sound_samples/cries/kadabra.aif deleted file mode 100644 index 3f03ee03f0..0000000000 Binary files a/sound/direct_sound_samples/cries/kadabra.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/kadabra.wav b/sound/direct_sound_samples/cries/kadabra.wav new file mode 100644 index 0000000000..d7030b27a2 Binary files /dev/null and b/sound/direct_sound_samples/cries/kadabra.wav differ diff --git a/sound/direct_sound_samples/cries/kakuna.aif b/sound/direct_sound_samples/cries/kakuna.aif deleted file mode 100644 index 8331b0b0e5..0000000000 Binary files a/sound/direct_sound_samples/cries/kakuna.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/kakuna.wav b/sound/direct_sound_samples/cries/kakuna.wav new file mode 100644 index 0000000000..f147428e38 Binary files /dev/null and b/sound/direct_sound_samples/cries/kakuna.wav differ diff --git a/sound/direct_sound_samples/cries/kangaskhan.aif b/sound/direct_sound_samples/cries/kangaskhan.aif deleted file mode 100644 index 26a8ac43a4..0000000000 Binary files a/sound/direct_sound_samples/cries/kangaskhan.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/kangaskhan.wav b/sound/direct_sound_samples/cries/kangaskhan.wav new file mode 100644 index 0000000000..eaf7244627 Binary files /dev/null and b/sound/direct_sound_samples/cries/kangaskhan.wav differ diff --git a/sound/direct_sound_samples/cries/kangaskhan_mega.aif b/sound/direct_sound_samples/cries/kangaskhan_mega.aif deleted file mode 100644 index 417cb04f49..0000000000 Binary files a/sound/direct_sound_samples/cries/kangaskhan_mega.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/kangaskhan_mega.wav b/sound/direct_sound_samples/cries/kangaskhan_mega.wav new file mode 100644 index 0000000000..5c96747381 Binary files /dev/null and b/sound/direct_sound_samples/cries/kangaskhan_mega.wav differ diff --git a/sound/direct_sound_samples/cries/karrablast.aif b/sound/direct_sound_samples/cries/karrablast.aif deleted file mode 100644 index 7b5a2c3948..0000000000 Binary files a/sound/direct_sound_samples/cries/karrablast.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/karrablast.wav b/sound/direct_sound_samples/cries/karrablast.wav new file mode 100644 index 0000000000..b77a4399de Binary files /dev/null and b/sound/direct_sound_samples/cries/karrablast.wav differ diff --git a/sound/direct_sound_samples/cries/kartana.aif b/sound/direct_sound_samples/cries/kartana.aif deleted file mode 100644 index b43fa40d78..0000000000 Binary files a/sound/direct_sound_samples/cries/kartana.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/kartana.wav b/sound/direct_sound_samples/cries/kartana.wav new file mode 100644 index 0000000000..af53ba2608 Binary files /dev/null and b/sound/direct_sound_samples/cries/kartana.wav differ diff --git a/sound/direct_sound_samples/cries/kecleon.aif b/sound/direct_sound_samples/cries/kecleon.aif deleted file mode 100644 index 51dae29350..0000000000 Binary files a/sound/direct_sound_samples/cries/kecleon.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/kecleon.wav b/sound/direct_sound_samples/cries/kecleon.wav new file mode 100644 index 0000000000..96ab74ff2b Binary files /dev/null and b/sound/direct_sound_samples/cries/kecleon.wav differ diff --git a/sound/direct_sound_samples/cries/keldeo.aif b/sound/direct_sound_samples/cries/keldeo.aif deleted file mode 100644 index 6f23ad0885..0000000000 Binary files a/sound/direct_sound_samples/cries/keldeo.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/keldeo.wav b/sound/direct_sound_samples/cries/keldeo.wav new file mode 100644 index 0000000000..e1733f1660 Binary files /dev/null and b/sound/direct_sound_samples/cries/keldeo.wav differ diff --git a/sound/direct_sound_samples/cries/kilowattrel.aif b/sound/direct_sound_samples/cries/kilowattrel.aif deleted file mode 100644 index d54d4a43b5..0000000000 Binary files a/sound/direct_sound_samples/cries/kilowattrel.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/kilowattrel.wav b/sound/direct_sound_samples/cries/kilowattrel.wav new file mode 100644 index 0000000000..b1b27b8ebe Binary files /dev/null and b/sound/direct_sound_samples/cries/kilowattrel.wav differ diff --git a/sound/direct_sound_samples/cries/kingambit.aif b/sound/direct_sound_samples/cries/kingambit.aif deleted file mode 100644 index 38a3d1b6cc..0000000000 Binary files a/sound/direct_sound_samples/cries/kingambit.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/kingambit.wav b/sound/direct_sound_samples/cries/kingambit.wav new file mode 100644 index 0000000000..0770f23f5a Binary files /dev/null and b/sound/direct_sound_samples/cries/kingambit.wav differ diff --git a/sound/direct_sound_samples/cries/kingdra.aif b/sound/direct_sound_samples/cries/kingdra.aif deleted file mode 100644 index a9cc1d9fe4..0000000000 Binary files a/sound/direct_sound_samples/cries/kingdra.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/kingdra.wav b/sound/direct_sound_samples/cries/kingdra.wav new file mode 100644 index 0000000000..2a47d1479d Binary files /dev/null and b/sound/direct_sound_samples/cries/kingdra.wav differ diff --git a/sound/direct_sound_samples/cries/kingler.aif b/sound/direct_sound_samples/cries/kingler.aif deleted file mode 100644 index b836829731..0000000000 Binary files a/sound/direct_sound_samples/cries/kingler.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/kingler.wav b/sound/direct_sound_samples/cries/kingler.wav new file mode 100644 index 0000000000..62418456d0 Binary files /dev/null and b/sound/direct_sound_samples/cries/kingler.wav differ diff --git a/sound/direct_sound_samples/cries/kirlia.aif b/sound/direct_sound_samples/cries/kirlia.aif deleted file mode 100644 index 0beaebf16f..0000000000 Binary files a/sound/direct_sound_samples/cries/kirlia.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/kirlia.wav b/sound/direct_sound_samples/cries/kirlia.wav new file mode 100644 index 0000000000..c7dd3078c8 Binary files /dev/null and b/sound/direct_sound_samples/cries/kirlia.wav differ diff --git a/sound/direct_sound_samples/cries/klang.aif b/sound/direct_sound_samples/cries/klang.aif deleted file mode 100644 index 13b28861f4..0000000000 Binary files a/sound/direct_sound_samples/cries/klang.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/klang.wav b/sound/direct_sound_samples/cries/klang.wav new file mode 100644 index 0000000000..2524393b24 Binary files /dev/null and b/sound/direct_sound_samples/cries/klang.wav differ diff --git a/sound/direct_sound_samples/cries/klawf.aif b/sound/direct_sound_samples/cries/klawf.aif deleted file mode 100644 index 8359e13b17..0000000000 Binary files a/sound/direct_sound_samples/cries/klawf.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/klawf.wav b/sound/direct_sound_samples/cries/klawf.wav new file mode 100644 index 0000000000..8d557afc68 Binary files /dev/null and b/sound/direct_sound_samples/cries/klawf.wav differ diff --git a/sound/direct_sound_samples/cries/kleavor.aif b/sound/direct_sound_samples/cries/kleavor.aif deleted file mode 100644 index c84a31cf2f..0000000000 Binary files a/sound/direct_sound_samples/cries/kleavor.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/kleavor.wav b/sound/direct_sound_samples/cries/kleavor.wav new file mode 100644 index 0000000000..ac60149c3f Binary files /dev/null and b/sound/direct_sound_samples/cries/kleavor.wav differ diff --git a/sound/direct_sound_samples/cries/klink.aif b/sound/direct_sound_samples/cries/klink.aif deleted file mode 100644 index 0bd6b65f74..0000000000 Binary files a/sound/direct_sound_samples/cries/klink.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/klink.wav b/sound/direct_sound_samples/cries/klink.wav new file mode 100644 index 0000000000..0233d44ce2 Binary files /dev/null and b/sound/direct_sound_samples/cries/klink.wav differ diff --git a/sound/direct_sound_samples/cries/klinklang.aif b/sound/direct_sound_samples/cries/klinklang.aif deleted file mode 100644 index 35117bf30a..0000000000 Binary files a/sound/direct_sound_samples/cries/klinklang.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/klinklang.wav b/sound/direct_sound_samples/cries/klinklang.wav new file mode 100644 index 0000000000..6cba25f48c Binary files /dev/null and b/sound/direct_sound_samples/cries/klinklang.wav differ diff --git a/sound/direct_sound_samples/cries/koffing.aif b/sound/direct_sound_samples/cries/koffing.aif deleted file mode 100644 index 50d5bc978b..0000000000 Binary files a/sound/direct_sound_samples/cries/koffing.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/koffing.wav b/sound/direct_sound_samples/cries/koffing.wav new file mode 100644 index 0000000000..afa520c03e Binary files /dev/null and b/sound/direct_sound_samples/cries/koffing.wav differ diff --git a/sound/direct_sound_samples/cries/komala.aif b/sound/direct_sound_samples/cries/komala.aif deleted file mode 100644 index e084c9a7c4..0000000000 Binary files a/sound/direct_sound_samples/cries/komala.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/komala.wav b/sound/direct_sound_samples/cries/komala.wav new file mode 100644 index 0000000000..ce1077a9ac Binary files /dev/null and b/sound/direct_sound_samples/cries/komala.wav differ diff --git a/sound/direct_sound_samples/cries/kommo_o.aif b/sound/direct_sound_samples/cries/kommo_o.aif deleted file mode 100644 index 057153e907..0000000000 Binary files a/sound/direct_sound_samples/cries/kommo_o.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/kommo_o.wav b/sound/direct_sound_samples/cries/kommo_o.wav new file mode 100644 index 0000000000..0782ecd776 Binary files /dev/null and b/sound/direct_sound_samples/cries/kommo_o.wav differ diff --git a/sound/direct_sound_samples/cries/koraidon.aif b/sound/direct_sound_samples/cries/koraidon.aif deleted file mode 100644 index 6ab93ad73e..0000000000 Binary files a/sound/direct_sound_samples/cries/koraidon.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/koraidon.wav b/sound/direct_sound_samples/cries/koraidon.wav new file mode 100644 index 0000000000..cf5de8aff3 Binary files /dev/null and b/sound/direct_sound_samples/cries/koraidon.wav differ diff --git a/sound/direct_sound_samples/cries/krabby.aif b/sound/direct_sound_samples/cries/krabby.aif deleted file mode 100644 index 33b8ea294b..0000000000 Binary files a/sound/direct_sound_samples/cries/krabby.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/krabby.wav b/sound/direct_sound_samples/cries/krabby.wav new file mode 100644 index 0000000000..0072ea777a Binary files /dev/null and b/sound/direct_sound_samples/cries/krabby.wav differ diff --git a/sound/direct_sound_samples/cries/kricketot.aif b/sound/direct_sound_samples/cries/kricketot.aif deleted file mode 100644 index 7b301cc485..0000000000 Binary files a/sound/direct_sound_samples/cries/kricketot.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/kricketot.wav b/sound/direct_sound_samples/cries/kricketot.wav new file mode 100644 index 0000000000..126bbecee8 Binary files /dev/null and b/sound/direct_sound_samples/cries/kricketot.wav differ diff --git a/sound/direct_sound_samples/cries/kricketune.aif b/sound/direct_sound_samples/cries/kricketune.aif deleted file mode 100644 index b3ebcbf8ae..0000000000 Binary files a/sound/direct_sound_samples/cries/kricketune.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/kricketune.wav b/sound/direct_sound_samples/cries/kricketune.wav new file mode 100644 index 0000000000..832069528a Binary files /dev/null and b/sound/direct_sound_samples/cries/kricketune.wav differ diff --git a/sound/direct_sound_samples/cries/krokorok.aif b/sound/direct_sound_samples/cries/krokorok.aif deleted file mode 100644 index 39765627ec..0000000000 Binary files a/sound/direct_sound_samples/cries/krokorok.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/krokorok.wav b/sound/direct_sound_samples/cries/krokorok.wav new file mode 100644 index 0000000000..cf2f75dc8e Binary files /dev/null and b/sound/direct_sound_samples/cries/krokorok.wav differ diff --git a/sound/direct_sound_samples/cries/krookodile.aif b/sound/direct_sound_samples/cries/krookodile.aif deleted file mode 100644 index 4b532b3bd1..0000000000 Binary files a/sound/direct_sound_samples/cries/krookodile.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/krookodile.wav b/sound/direct_sound_samples/cries/krookodile.wav new file mode 100644 index 0000000000..0abdce9be7 Binary files /dev/null and b/sound/direct_sound_samples/cries/krookodile.wav differ diff --git a/sound/direct_sound_samples/cries/kubfu.aif b/sound/direct_sound_samples/cries/kubfu.aif deleted file mode 100644 index dd45534b88..0000000000 Binary files a/sound/direct_sound_samples/cries/kubfu.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/kubfu.wav b/sound/direct_sound_samples/cries/kubfu.wav new file mode 100644 index 0000000000..899b03f7a9 Binary files /dev/null and b/sound/direct_sound_samples/cries/kubfu.wav differ diff --git a/sound/direct_sound_samples/cries/kyogre.aif b/sound/direct_sound_samples/cries/kyogre.aif deleted file mode 100644 index c20d2cf324..0000000000 Binary files a/sound/direct_sound_samples/cries/kyogre.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/kyogre.wav b/sound/direct_sound_samples/cries/kyogre.wav new file mode 100644 index 0000000000..00db984c66 Binary files /dev/null and b/sound/direct_sound_samples/cries/kyogre.wav differ diff --git a/sound/direct_sound_samples/cries/kyogre_primal.aif b/sound/direct_sound_samples/cries/kyogre_primal.aif deleted file mode 100644 index b7999915b3..0000000000 Binary files a/sound/direct_sound_samples/cries/kyogre_primal.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/kyogre_primal.wav b/sound/direct_sound_samples/cries/kyogre_primal.wav new file mode 100644 index 0000000000..1688dad88b Binary files /dev/null and b/sound/direct_sound_samples/cries/kyogre_primal.wav differ diff --git a/sound/direct_sound_samples/cries/kyurem.aif b/sound/direct_sound_samples/cries/kyurem.aif deleted file mode 100644 index 0345a0c175..0000000000 Binary files a/sound/direct_sound_samples/cries/kyurem.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/kyurem.wav b/sound/direct_sound_samples/cries/kyurem.wav new file mode 100644 index 0000000000..d33514448e Binary files /dev/null and b/sound/direct_sound_samples/cries/kyurem.wav differ diff --git a/sound/direct_sound_samples/cries/kyurem_black.aif b/sound/direct_sound_samples/cries/kyurem_black.aif deleted file mode 100644 index 9b5320bd63..0000000000 Binary files a/sound/direct_sound_samples/cries/kyurem_black.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/kyurem_black.wav b/sound/direct_sound_samples/cries/kyurem_black.wav new file mode 100644 index 0000000000..385bd7824f Binary files /dev/null and b/sound/direct_sound_samples/cries/kyurem_black.wav differ diff --git a/sound/direct_sound_samples/cries/kyurem_white.aif b/sound/direct_sound_samples/cries/kyurem_white.aif deleted file mode 100644 index 1e6f0283ec..0000000000 Binary files a/sound/direct_sound_samples/cries/kyurem_white.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/kyurem_white.wav b/sound/direct_sound_samples/cries/kyurem_white.wav new file mode 100644 index 0000000000..7a4b8dbd7c Binary files /dev/null and b/sound/direct_sound_samples/cries/kyurem_white.wav differ diff --git a/sound/direct_sound_samples/cries/lairon.aif b/sound/direct_sound_samples/cries/lairon.aif deleted file mode 100644 index 44bc57df17..0000000000 Binary files a/sound/direct_sound_samples/cries/lairon.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/lairon.wav b/sound/direct_sound_samples/cries/lairon.wav new file mode 100644 index 0000000000..574ffac745 Binary files /dev/null and b/sound/direct_sound_samples/cries/lairon.wav differ diff --git a/sound/direct_sound_samples/cries/lampent.aif b/sound/direct_sound_samples/cries/lampent.aif deleted file mode 100644 index 9d5a8a3c01..0000000000 Binary files a/sound/direct_sound_samples/cries/lampent.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/lampent.wav b/sound/direct_sound_samples/cries/lampent.wav new file mode 100644 index 0000000000..e92380e5ad Binary files /dev/null and b/sound/direct_sound_samples/cries/lampent.wav differ diff --git a/sound/direct_sound_samples/cries/landorus_incarnate.aif b/sound/direct_sound_samples/cries/landorus_incarnate.aif deleted file mode 100644 index 03111963d7..0000000000 Binary files a/sound/direct_sound_samples/cries/landorus_incarnate.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/landorus_incarnate.wav b/sound/direct_sound_samples/cries/landorus_incarnate.wav new file mode 100644 index 0000000000..82c79ea48f Binary files /dev/null and b/sound/direct_sound_samples/cries/landorus_incarnate.wav differ diff --git a/sound/direct_sound_samples/cries/landorus_therian.aif b/sound/direct_sound_samples/cries/landorus_therian.aif deleted file mode 100644 index 6a641cf6f4..0000000000 Binary files a/sound/direct_sound_samples/cries/landorus_therian.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/landorus_therian.wav b/sound/direct_sound_samples/cries/landorus_therian.wav new file mode 100644 index 0000000000..246f4b2595 Binary files /dev/null and b/sound/direct_sound_samples/cries/landorus_therian.wav differ diff --git a/sound/direct_sound_samples/cries/lanturn.aif b/sound/direct_sound_samples/cries/lanturn.aif deleted file mode 100644 index e88570f68d..0000000000 Binary files a/sound/direct_sound_samples/cries/lanturn.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/lanturn.wav b/sound/direct_sound_samples/cries/lanturn.wav new file mode 100644 index 0000000000..6d8b21dd99 Binary files /dev/null and b/sound/direct_sound_samples/cries/lanturn.wav differ diff --git a/sound/direct_sound_samples/cries/lapras.aif b/sound/direct_sound_samples/cries/lapras.aif deleted file mode 100644 index 9bc9023730..0000000000 Binary files a/sound/direct_sound_samples/cries/lapras.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/lapras.wav b/sound/direct_sound_samples/cries/lapras.wav new file mode 100644 index 0000000000..d79819a971 Binary files /dev/null and b/sound/direct_sound_samples/cries/lapras.wav differ diff --git a/sound/direct_sound_samples/cries/larvesta.aif b/sound/direct_sound_samples/cries/larvesta.aif deleted file mode 100644 index a025df32bf..0000000000 Binary files a/sound/direct_sound_samples/cries/larvesta.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/larvesta.wav b/sound/direct_sound_samples/cries/larvesta.wav new file mode 100644 index 0000000000..3c1fb5a46a Binary files /dev/null and b/sound/direct_sound_samples/cries/larvesta.wav differ diff --git a/sound/direct_sound_samples/cries/larvitar.aif b/sound/direct_sound_samples/cries/larvitar.aif deleted file mode 100644 index fd91d5bc7d..0000000000 Binary files a/sound/direct_sound_samples/cries/larvitar.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/larvitar.wav b/sound/direct_sound_samples/cries/larvitar.wav new file mode 100644 index 0000000000..e0e22cd6f5 Binary files /dev/null and b/sound/direct_sound_samples/cries/larvitar.wav differ diff --git a/sound/direct_sound_samples/cries/latias.aif b/sound/direct_sound_samples/cries/latias.aif deleted file mode 100644 index 90f558abc8..0000000000 Binary files a/sound/direct_sound_samples/cries/latias.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/latias.wav b/sound/direct_sound_samples/cries/latias.wav new file mode 100644 index 0000000000..87e6205ada Binary files /dev/null and b/sound/direct_sound_samples/cries/latias.wav differ diff --git a/sound/direct_sound_samples/cries/latias_mega.aif b/sound/direct_sound_samples/cries/latias_mega.aif deleted file mode 100644 index 0dc1b89906..0000000000 Binary files a/sound/direct_sound_samples/cries/latias_mega.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/latias_mega.wav b/sound/direct_sound_samples/cries/latias_mega.wav new file mode 100644 index 0000000000..c1b5d48233 Binary files /dev/null and b/sound/direct_sound_samples/cries/latias_mega.wav differ diff --git a/sound/direct_sound_samples/cries/latios.aif b/sound/direct_sound_samples/cries/latios.aif deleted file mode 100644 index f42446256c..0000000000 Binary files a/sound/direct_sound_samples/cries/latios.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/latios.wav b/sound/direct_sound_samples/cries/latios.wav new file mode 100644 index 0000000000..1409dba11a Binary files /dev/null and b/sound/direct_sound_samples/cries/latios.wav differ diff --git a/sound/direct_sound_samples/cries/latios_mega.aif b/sound/direct_sound_samples/cries/latios_mega.aif deleted file mode 100644 index 88a896035b..0000000000 Binary files a/sound/direct_sound_samples/cries/latios_mega.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/latios_mega.wav b/sound/direct_sound_samples/cries/latios_mega.wav new file mode 100644 index 0000000000..9a1b9754e7 Binary files /dev/null and b/sound/direct_sound_samples/cries/latios_mega.wav differ diff --git a/sound/direct_sound_samples/cries/leafeon.aif b/sound/direct_sound_samples/cries/leafeon.aif deleted file mode 100644 index b3e7494b69..0000000000 Binary files a/sound/direct_sound_samples/cries/leafeon.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/leafeon.wav b/sound/direct_sound_samples/cries/leafeon.wav new file mode 100644 index 0000000000..3a248e47f8 Binary files /dev/null and b/sound/direct_sound_samples/cries/leafeon.wav differ diff --git a/sound/direct_sound_samples/cries/leavanny.aif b/sound/direct_sound_samples/cries/leavanny.aif deleted file mode 100644 index 503a08ffe8..0000000000 Binary files a/sound/direct_sound_samples/cries/leavanny.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/leavanny.wav b/sound/direct_sound_samples/cries/leavanny.wav new file mode 100644 index 0000000000..e07d790e3b Binary files /dev/null and b/sound/direct_sound_samples/cries/leavanny.wav differ diff --git a/sound/direct_sound_samples/cries/lechonk.aif b/sound/direct_sound_samples/cries/lechonk.aif deleted file mode 100644 index f1ab3af238..0000000000 Binary files a/sound/direct_sound_samples/cries/lechonk.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/lechonk.wav b/sound/direct_sound_samples/cries/lechonk.wav new file mode 100644 index 0000000000..7c1b4e71bd Binary files /dev/null and b/sound/direct_sound_samples/cries/lechonk.wav differ diff --git a/sound/direct_sound_samples/cries/ledian.aif b/sound/direct_sound_samples/cries/ledian.aif deleted file mode 100644 index cbc86ba6ac..0000000000 Binary files a/sound/direct_sound_samples/cries/ledian.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/ledian.wav b/sound/direct_sound_samples/cries/ledian.wav new file mode 100644 index 0000000000..554829075d Binary files /dev/null and b/sound/direct_sound_samples/cries/ledian.wav differ diff --git a/sound/direct_sound_samples/cries/ledyba.aif b/sound/direct_sound_samples/cries/ledyba.aif deleted file mode 100644 index d90f684401..0000000000 Binary files a/sound/direct_sound_samples/cries/ledyba.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/ledyba.wav b/sound/direct_sound_samples/cries/ledyba.wav new file mode 100644 index 0000000000..e539c3d60a Binary files /dev/null and b/sound/direct_sound_samples/cries/ledyba.wav differ diff --git a/sound/direct_sound_samples/cries/lickilicky.aif b/sound/direct_sound_samples/cries/lickilicky.aif deleted file mode 100644 index 542bbcaf8b..0000000000 Binary files a/sound/direct_sound_samples/cries/lickilicky.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/lickilicky.wav b/sound/direct_sound_samples/cries/lickilicky.wav new file mode 100644 index 0000000000..e0e6ccf237 Binary files /dev/null and b/sound/direct_sound_samples/cries/lickilicky.wav differ diff --git a/sound/direct_sound_samples/cries/lickitung.aif b/sound/direct_sound_samples/cries/lickitung.aif deleted file mode 100644 index c21d1b0365..0000000000 Binary files a/sound/direct_sound_samples/cries/lickitung.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/lickitung.wav b/sound/direct_sound_samples/cries/lickitung.wav new file mode 100644 index 0000000000..33a0ab5ff3 Binary files /dev/null and b/sound/direct_sound_samples/cries/lickitung.wav differ diff --git a/sound/direct_sound_samples/cries/liepard.aif b/sound/direct_sound_samples/cries/liepard.aif deleted file mode 100644 index eec210c0e7..0000000000 Binary files a/sound/direct_sound_samples/cries/liepard.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/liepard.wav b/sound/direct_sound_samples/cries/liepard.wav new file mode 100644 index 0000000000..f88311694c Binary files /dev/null and b/sound/direct_sound_samples/cries/liepard.wav differ diff --git a/sound/direct_sound_samples/cries/lileep.aif b/sound/direct_sound_samples/cries/lileep.aif deleted file mode 100644 index e1b750ba94..0000000000 Binary files a/sound/direct_sound_samples/cries/lileep.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/lileep.wav b/sound/direct_sound_samples/cries/lileep.wav new file mode 100644 index 0000000000..f890086d37 Binary files /dev/null and b/sound/direct_sound_samples/cries/lileep.wav differ diff --git a/sound/direct_sound_samples/cries/lilligant.aif b/sound/direct_sound_samples/cries/lilligant.aif deleted file mode 100644 index e00b1aafc4..0000000000 Binary files a/sound/direct_sound_samples/cries/lilligant.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/lilligant.wav b/sound/direct_sound_samples/cries/lilligant.wav new file mode 100644 index 0000000000..f49cd46afd Binary files /dev/null and b/sound/direct_sound_samples/cries/lilligant.wav differ diff --git a/sound/direct_sound_samples/cries/lillipup.aif b/sound/direct_sound_samples/cries/lillipup.aif deleted file mode 100644 index 825f5054cf..0000000000 Binary files a/sound/direct_sound_samples/cries/lillipup.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/lillipup.wav b/sound/direct_sound_samples/cries/lillipup.wav new file mode 100644 index 0000000000..2ca638186c Binary files /dev/null and b/sound/direct_sound_samples/cries/lillipup.wav differ diff --git a/sound/direct_sound_samples/cries/linoone.aif b/sound/direct_sound_samples/cries/linoone.aif deleted file mode 100644 index 1db1958d4c..0000000000 Binary files a/sound/direct_sound_samples/cries/linoone.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/linoone.wav b/sound/direct_sound_samples/cries/linoone.wav new file mode 100644 index 0000000000..b8c191bcd0 Binary files /dev/null and b/sound/direct_sound_samples/cries/linoone.wav differ diff --git a/sound/direct_sound_samples/cries/litleo.aif b/sound/direct_sound_samples/cries/litleo.aif deleted file mode 100644 index 417d3d4708..0000000000 Binary files a/sound/direct_sound_samples/cries/litleo.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/litleo.wav b/sound/direct_sound_samples/cries/litleo.wav new file mode 100644 index 0000000000..bbd5814c1f Binary files /dev/null and b/sound/direct_sound_samples/cries/litleo.wav differ diff --git a/sound/direct_sound_samples/cries/litten.aif b/sound/direct_sound_samples/cries/litten.aif deleted file mode 100644 index c2c486dd98..0000000000 Binary files a/sound/direct_sound_samples/cries/litten.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/litten.wav b/sound/direct_sound_samples/cries/litten.wav new file mode 100644 index 0000000000..faf794123f Binary files /dev/null and b/sound/direct_sound_samples/cries/litten.wav differ diff --git a/sound/direct_sound_samples/cries/litwick.aif b/sound/direct_sound_samples/cries/litwick.aif deleted file mode 100644 index c13b749200..0000000000 Binary files a/sound/direct_sound_samples/cries/litwick.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/litwick.wav b/sound/direct_sound_samples/cries/litwick.wav new file mode 100644 index 0000000000..da405865a3 Binary files /dev/null and b/sound/direct_sound_samples/cries/litwick.wav differ diff --git a/sound/direct_sound_samples/cries/lokix.aif b/sound/direct_sound_samples/cries/lokix.aif deleted file mode 100644 index 739ae1ad56..0000000000 Binary files a/sound/direct_sound_samples/cries/lokix.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/lokix.wav b/sound/direct_sound_samples/cries/lokix.wav new file mode 100644 index 0000000000..b3d94004d7 Binary files /dev/null and b/sound/direct_sound_samples/cries/lokix.wav differ diff --git a/sound/direct_sound_samples/cries/lombre.aif b/sound/direct_sound_samples/cries/lombre.aif deleted file mode 100644 index 3839f7a327..0000000000 Binary files a/sound/direct_sound_samples/cries/lombre.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/lombre.wav b/sound/direct_sound_samples/cries/lombre.wav new file mode 100644 index 0000000000..6d7888619e Binary files /dev/null and b/sound/direct_sound_samples/cries/lombre.wav differ diff --git a/sound/direct_sound_samples/cries/lopunny.aif b/sound/direct_sound_samples/cries/lopunny.aif deleted file mode 100644 index f793790785..0000000000 Binary files a/sound/direct_sound_samples/cries/lopunny.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/lopunny.wav b/sound/direct_sound_samples/cries/lopunny.wav new file mode 100644 index 0000000000..8897e582a4 Binary files /dev/null and b/sound/direct_sound_samples/cries/lopunny.wav differ diff --git a/sound/direct_sound_samples/cries/lopunny_mega.aif b/sound/direct_sound_samples/cries/lopunny_mega.aif deleted file mode 100644 index 212df776de..0000000000 Binary files a/sound/direct_sound_samples/cries/lopunny_mega.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/lopunny_mega.wav b/sound/direct_sound_samples/cries/lopunny_mega.wav new file mode 100644 index 0000000000..e02e8a69ef Binary files /dev/null and b/sound/direct_sound_samples/cries/lopunny_mega.wav differ diff --git a/sound/direct_sound_samples/cries/lotad.aif b/sound/direct_sound_samples/cries/lotad.aif deleted file mode 100644 index 290ec54859..0000000000 Binary files a/sound/direct_sound_samples/cries/lotad.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/lotad.wav b/sound/direct_sound_samples/cries/lotad.wav new file mode 100644 index 0000000000..8e28b10f32 Binary files /dev/null and b/sound/direct_sound_samples/cries/lotad.wav differ diff --git a/sound/direct_sound_samples/cries/loudred.aif b/sound/direct_sound_samples/cries/loudred.aif deleted file mode 100644 index d9c7465573..0000000000 Binary files a/sound/direct_sound_samples/cries/loudred.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/loudred.wav b/sound/direct_sound_samples/cries/loudred.wav new file mode 100644 index 0000000000..ff8b2c8104 Binary files /dev/null and b/sound/direct_sound_samples/cries/loudred.wav differ diff --git a/sound/direct_sound_samples/cries/lucario.aif b/sound/direct_sound_samples/cries/lucario.aif deleted file mode 100644 index 80064d64fb..0000000000 Binary files a/sound/direct_sound_samples/cries/lucario.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/lucario.wav b/sound/direct_sound_samples/cries/lucario.wav new file mode 100644 index 0000000000..78cfeac18b Binary files /dev/null and b/sound/direct_sound_samples/cries/lucario.wav differ diff --git a/sound/direct_sound_samples/cries/lucario_mega.aif b/sound/direct_sound_samples/cries/lucario_mega.aif deleted file mode 100644 index 1a100f4dab..0000000000 Binary files a/sound/direct_sound_samples/cries/lucario_mega.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/lucario_mega.wav b/sound/direct_sound_samples/cries/lucario_mega.wav new file mode 100644 index 0000000000..7121965167 Binary files /dev/null and b/sound/direct_sound_samples/cries/lucario_mega.wav differ diff --git a/sound/direct_sound_samples/cries/ludicolo.aif b/sound/direct_sound_samples/cries/ludicolo.aif deleted file mode 100644 index 690cf75fe4..0000000000 Binary files a/sound/direct_sound_samples/cries/ludicolo.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/ludicolo.wav b/sound/direct_sound_samples/cries/ludicolo.wav new file mode 100644 index 0000000000..420ac54595 Binary files /dev/null and b/sound/direct_sound_samples/cries/ludicolo.wav differ diff --git a/sound/direct_sound_samples/cries/lugia.aif b/sound/direct_sound_samples/cries/lugia.aif deleted file mode 100644 index 884b48591e..0000000000 Binary files a/sound/direct_sound_samples/cries/lugia.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/lugia.wav b/sound/direct_sound_samples/cries/lugia.wav new file mode 100644 index 0000000000..855920839e Binary files /dev/null and b/sound/direct_sound_samples/cries/lugia.wav differ diff --git a/sound/direct_sound_samples/cries/lumineon.aif b/sound/direct_sound_samples/cries/lumineon.aif deleted file mode 100644 index 0577fb5575..0000000000 Binary files a/sound/direct_sound_samples/cries/lumineon.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/lumineon.wav b/sound/direct_sound_samples/cries/lumineon.wav new file mode 100644 index 0000000000..fccb69a383 Binary files /dev/null and b/sound/direct_sound_samples/cries/lumineon.wav differ diff --git a/sound/direct_sound_samples/cries/lunala.aif b/sound/direct_sound_samples/cries/lunala.aif deleted file mode 100644 index d95185de79..0000000000 Binary files a/sound/direct_sound_samples/cries/lunala.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/lunala.wav b/sound/direct_sound_samples/cries/lunala.wav new file mode 100644 index 0000000000..e82139ef18 Binary files /dev/null and b/sound/direct_sound_samples/cries/lunala.wav differ diff --git a/sound/direct_sound_samples/cries/lunatone.aif b/sound/direct_sound_samples/cries/lunatone.aif deleted file mode 100644 index e27d7f2f60..0000000000 Binary files a/sound/direct_sound_samples/cries/lunatone.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/lunatone.wav b/sound/direct_sound_samples/cries/lunatone.wav new file mode 100644 index 0000000000..8edd9a17e1 Binary files /dev/null and b/sound/direct_sound_samples/cries/lunatone.wav differ diff --git a/sound/direct_sound_samples/cries/lurantis.aif b/sound/direct_sound_samples/cries/lurantis.aif deleted file mode 100644 index 36ab7d71e2..0000000000 Binary files a/sound/direct_sound_samples/cries/lurantis.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/lurantis.wav b/sound/direct_sound_samples/cries/lurantis.wav new file mode 100644 index 0000000000..d85d414356 Binary files /dev/null and b/sound/direct_sound_samples/cries/lurantis.wav differ diff --git a/sound/direct_sound_samples/cries/luvdisc.aif b/sound/direct_sound_samples/cries/luvdisc.aif deleted file mode 100644 index 396aceff5e..0000000000 Binary files a/sound/direct_sound_samples/cries/luvdisc.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/luvdisc.wav b/sound/direct_sound_samples/cries/luvdisc.wav new file mode 100644 index 0000000000..da1c84b80e Binary files /dev/null and b/sound/direct_sound_samples/cries/luvdisc.wav differ diff --git a/sound/direct_sound_samples/cries/luxio.aif b/sound/direct_sound_samples/cries/luxio.aif deleted file mode 100644 index f56ffe1ea0..0000000000 Binary files a/sound/direct_sound_samples/cries/luxio.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/luxio.wav b/sound/direct_sound_samples/cries/luxio.wav new file mode 100644 index 0000000000..9f3189f78e Binary files /dev/null and b/sound/direct_sound_samples/cries/luxio.wav differ diff --git a/sound/direct_sound_samples/cries/luxray.aif b/sound/direct_sound_samples/cries/luxray.aif deleted file mode 100644 index 76bf5cb5d1..0000000000 Binary files a/sound/direct_sound_samples/cries/luxray.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/luxray.wav b/sound/direct_sound_samples/cries/luxray.wav new file mode 100644 index 0000000000..7c393e1b4a Binary files /dev/null and b/sound/direct_sound_samples/cries/luxray.wav differ diff --git a/sound/direct_sound_samples/cries/lycanroc_dusk.aif b/sound/direct_sound_samples/cries/lycanroc_dusk.aif deleted file mode 100644 index 61d985e64a..0000000000 Binary files a/sound/direct_sound_samples/cries/lycanroc_dusk.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/lycanroc_dusk.wav b/sound/direct_sound_samples/cries/lycanroc_dusk.wav new file mode 100644 index 0000000000..6f7e05e2c7 Binary files /dev/null and b/sound/direct_sound_samples/cries/lycanroc_dusk.wav differ diff --git a/sound/direct_sound_samples/cries/lycanroc_midday.aif b/sound/direct_sound_samples/cries/lycanroc_midday.aif deleted file mode 100644 index 380d192c22..0000000000 Binary files a/sound/direct_sound_samples/cries/lycanroc_midday.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/lycanroc_midday.wav b/sound/direct_sound_samples/cries/lycanroc_midday.wav new file mode 100644 index 0000000000..db29524ad4 Binary files /dev/null and b/sound/direct_sound_samples/cries/lycanroc_midday.wav differ diff --git a/sound/direct_sound_samples/cries/lycanroc_midnight.aif b/sound/direct_sound_samples/cries/lycanroc_midnight.aif deleted file mode 100644 index e81dac8c3e..0000000000 Binary files a/sound/direct_sound_samples/cries/lycanroc_midnight.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/lycanroc_midnight.wav b/sound/direct_sound_samples/cries/lycanroc_midnight.wav new file mode 100644 index 0000000000..19bb4175fd Binary files /dev/null and b/sound/direct_sound_samples/cries/lycanroc_midnight.wav differ diff --git a/sound/direct_sound_samples/cries/mabosstiff.aif b/sound/direct_sound_samples/cries/mabosstiff.aif deleted file mode 100644 index b66bbf731f..0000000000 Binary files a/sound/direct_sound_samples/cries/mabosstiff.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/mabosstiff.wav b/sound/direct_sound_samples/cries/mabosstiff.wav new file mode 100644 index 0000000000..245078423a Binary files /dev/null and b/sound/direct_sound_samples/cries/mabosstiff.wav differ diff --git a/sound/direct_sound_samples/cries/machamp.aif b/sound/direct_sound_samples/cries/machamp.aif deleted file mode 100644 index 99bcfea898..0000000000 Binary files a/sound/direct_sound_samples/cries/machamp.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/machamp.wav b/sound/direct_sound_samples/cries/machamp.wav new file mode 100644 index 0000000000..b7e091dc72 Binary files /dev/null and b/sound/direct_sound_samples/cries/machamp.wav differ diff --git a/sound/direct_sound_samples/cries/machoke.aif b/sound/direct_sound_samples/cries/machoke.aif deleted file mode 100644 index 241731b6fe..0000000000 Binary files a/sound/direct_sound_samples/cries/machoke.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/machoke.wav b/sound/direct_sound_samples/cries/machoke.wav new file mode 100644 index 0000000000..5e0fc98bf1 Binary files /dev/null and b/sound/direct_sound_samples/cries/machoke.wav differ diff --git a/sound/direct_sound_samples/cries/machop.aif b/sound/direct_sound_samples/cries/machop.aif deleted file mode 100644 index c878dfe99f..0000000000 Binary files a/sound/direct_sound_samples/cries/machop.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/machop.wav b/sound/direct_sound_samples/cries/machop.wav new file mode 100644 index 0000000000..a34a0ccc80 Binary files /dev/null and b/sound/direct_sound_samples/cries/machop.wav differ diff --git a/sound/direct_sound_samples/cries/magby.aif b/sound/direct_sound_samples/cries/magby.aif deleted file mode 100644 index 69f77a3b35..0000000000 Binary files a/sound/direct_sound_samples/cries/magby.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/magby.wav b/sound/direct_sound_samples/cries/magby.wav new file mode 100644 index 0000000000..8b083206c2 Binary files /dev/null and b/sound/direct_sound_samples/cries/magby.wav differ diff --git a/sound/direct_sound_samples/cries/magcargo.aif b/sound/direct_sound_samples/cries/magcargo.aif deleted file mode 100644 index f1127dabc4..0000000000 Binary files a/sound/direct_sound_samples/cries/magcargo.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/magcargo.wav b/sound/direct_sound_samples/cries/magcargo.wav new file mode 100644 index 0000000000..6d97b90c1b Binary files /dev/null and b/sound/direct_sound_samples/cries/magcargo.wav differ diff --git a/sound/direct_sound_samples/cries/magearna.aif b/sound/direct_sound_samples/cries/magearna.aif deleted file mode 100644 index 2e01fe5aa3..0000000000 Binary files a/sound/direct_sound_samples/cries/magearna.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/magearna.wav b/sound/direct_sound_samples/cries/magearna.wav new file mode 100644 index 0000000000..121867385d Binary files /dev/null and b/sound/direct_sound_samples/cries/magearna.wav differ diff --git a/sound/direct_sound_samples/cries/magikarp.aif b/sound/direct_sound_samples/cries/magikarp.aif deleted file mode 100644 index 71bdbf3939..0000000000 Binary files a/sound/direct_sound_samples/cries/magikarp.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/magikarp.wav b/sound/direct_sound_samples/cries/magikarp.wav new file mode 100644 index 0000000000..6c665d9e75 Binary files /dev/null and b/sound/direct_sound_samples/cries/magikarp.wav differ diff --git a/sound/direct_sound_samples/cries/magmar.aif b/sound/direct_sound_samples/cries/magmar.aif deleted file mode 100644 index c2a6a171ae..0000000000 Binary files a/sound/direct_sound_samples/cries/magmar.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/magmar.wav b/sound/direct_sound_samples/cries/magmar.wav new file mode 100644 index 0000000000..902c15bf2e Binary files /dev/null and b/sound/direct_sound_samples/cries/magmar.wav differ diff --git a/sound/direct_sound_samples/cries/magmortar.aif b/sound/direct_sound_samples/cries/magmortar.aif deleted file mode 100644 index ae7f0ea502..0000000000 Binary files a/sound/direct_sound_samples/cries/magmortar.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/magmortar.wav b/sound/direct_sound_samples/cries/magmortar.wav new file mode 100644 index 0000000000..6db0fc45de Binary files /dev/null and b/sound/direct_sound_samples/cries/magmortar.wav differ diff --git a/sound/direct_sound_samples/cries/magnemite.aif b/sound/direct_sound_samples/cries/magnemite.aif deleted file mode 100644 index d468102ac9..0000000000 Binary files a/sound/direct_sound_samples/cries/magnemite.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/magnemite.wav b/sound/direct_sound_samples/cries/magnemite.wav new file mode 100644 index 0000000000..4fdc93f296 Binary files /dev/null and b/sound/direct_sound_samples/cries/magnemite.wav differ diff --git a/sound/direct_sound_samples/cries/magneton.aif b/sound/direct_sound_samples/cries/magneton.aif deleted file mode 100644 index 30327cdbc3..0000000000 Binary files a/sound/direct_sound_samples/cries/magneton.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/magneton.wav b/sound/direct_sound_samples/cries/magneton.wav new file mode 100644 index 0000000000..d69c276443 Binary files /dev/null and b/sound/direct_sound_samples/cries/magneton.wav differ diff --git a/sound/direct_sound_samples/cries/magnezone.aif b/sound/direct_sound_samples/cries/magnezone.aif deleted file mode 100644 index 750cbd3ac4..0000000000 Binary files a/sound/direct_sound_samples/cries/magnezone.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/magnezone.wav b/sound/direct_sound_samples/cries/magnezone.wav new file mode 100644 index 0000000000..5e6adaeeaa Binary files /dev/null and b/sound/direct_sound_samples/cries/magnezone.wav differ diff --git a/sound/direct_sound_samples/cries/makuhita.aif b/sound/direct_sound_samples/cries/makuhita.aif deleted file mode 100644 index 2dffab4bcc..0000000000 Binary files a/sound/direct_sound_samples/cries/makuhita.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/makuhita.wav b/sound/direct_sound_samples/cries/makuhita.wav new file mode 100644 index 0000000000..79b055ef98 Binary files /dev/null and b/sound/direct_sound_samples/cries/makuhita.wav differ diff --git a/sound/direct_sound_samples/cries/malamar.aif b/sound/direct_sound_samples/cries/malamar.aif deleted file mode 100644 index 80428bfb16..0000000000 Binary files a/sound/direct_sound_samples/cries/malamar.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/malamar.wav b/sound/direct_sound_samples/cries/malamar.wav new file mode 100644 index 0000000000..37a33ffb84 Binary files /dev/null and b/sound/direct_sound_samples/cries/malamar.wav differ diff --git a/sound/direct_sound_samples/cries/mamoswine.aif b/sound/direct_sound_samples/cries/mamoswine.aif deleted file mode 100644 index 48625c1a6f..0000000000 Binary files a/sound/direct_sound_samples/cries/mamoswine.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/mamoswine.wav b/sound/direct_sound_samples/cries/mamoswine.wav new file mode 100644 index 0000000000..ce0488818b Binary files /dev/null and b/sound/direct_sound_samples/cries/mamoswine.wav differ diff --git a/sound/direct_sound_samples/cries/manaphy.aif b/sound/direct_sound_samples/cries/manaphy.aif deleted file mode 100644 index 7df4dc8338..0000000000 Binary files a/sound/direct_sound_samples/cries/manaphy.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/manaphy.wav b/sound/direct_sound_samples/cries/manaphy.wav new file mode 100644 index 0000000000..ddd3ea6c38 Binary files /dev/null and b/sound/direct_sound_samples/cries/manaphy.wav differ diff --git a/sound/direct_sound_samples/cries/mandibuzz.aif b/sound/direct_sound_samples/cries/mandibuzz.aif deleted file mode 100644 index 1a3a3afec3..0000000000 Binary files a/sound/direct_sound_samples/cries/mandibuzz.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/mandibuzz.wav b/sound/direct_sound_samples/cries/mandibuzz.wav new file mode 100644 index 0000000000..2db3dfaf39 Binary files /dev/null and b/sound/direct_sound_samples/cries/mandibuzz.wav differ diff --git a/sound/direct_sound_samples/cries/manectric.aif b/sound/direct_sound_samples/cries/manectric.aif deleted file mode 100644 index cb0783a0c9..0000000000 Binary files a/sound/direct_sound_samples/cries/manectric.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/manectric.wav b/sound/direct_sound_samples/cries/manectric.wav new file mode 100644 index 0000000000..939fc16093 Binary files /dev/null and b/sound/direct_sound_samples/cries/manectric.wav differ diff --git a/sound/direct_sound_samples/cries/manectric_mega.aif b/sound/direct_sound_samples/cries/manectric_mega.aif deleted file mode 100644 index 6e9717fe89..0000000000 Binary files a/sound/direct_sound_samples/cries/manectric_mega.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/manectric_mega.wav b/sound/direct_sound_samples/cries/manectric_mega.wav new file mode 100644 index 0000000000..cd4f1e11aa Binary files /dev/null and b/sound/direct_sound_samples/cries/manectric_mega.wav differ diff --git a/sound/direct_sound_samples/cries/mankey.aif b/sound/direct_sound_samples/cries/mankey.aif deleted file mode 100644 index b2634d3f7b..0000000000 Binary files a/sound/direct_sound_samples/cries/mankey.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/mankey.wav b/sound/direct_sound_samples/cries/mankey.wav new file mode 100644 index 0000000000..ab15ac9af6 Binary files /dev/null and b/sound/direct_sound_samples/cries/mankey.wav differ diff --git a/sound/direct_sound_samples/cries/mantine.aif b/sound/direct_sound_samples/cries/mantine.aif deleted file mode 100644 index f3f6af3213..0000000000 Binary files a/sound/direct_sound_samples/cries/mantine.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/mantine.wav b/sound/direct_sound_samples/cries/mantine.wav new file mode 100644 index 0000000000..919242e8fe Binary files /dev/null and b/sound/direct_sound_samples/cries/mantine.wav differ diff --git a/sound/direct_sound_samples/cries/mantyke.aif b/sound/direct_sound_samples/cries/mantyke.aif deleted file mode 100644 index edf6a76ef1..0000000000 Binary files a/sound/direct_sound_samples/cries/mantyke.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/mantyke.wav b/sound/direct_sound_samples/cries/mantyke.wav new file mode 100644 index 0000000000..6c602275d1 Binary files /dev/null and b/sound/direct_sound_samples/cries/mantyke.wav differ diff --git a/sound/direct_sound_samples/cries/maractus.aif b/sound/direct_sound_samples/cries/maractus.aif deleted file mode 100644 index ad2488ec86..0000000000 Binary files a/sound/direct_sound_samples/cries/maractus.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/maractus.wav b/sound/direct_sound_samples/cries/maractus.wav new file mode 100644 index 0000000000..944aac4465 Binary files /dev/null and b/sound/direct_sound_samples/cries/maractus.wav differ diff --git a/sound/direct_sound_samples/cries/mareanie.aif b/sound/direct_sound_samples/cries/mareanie.aif deleted file mode 100644 index 75a73d5edb..0000000000 Binary files a/sound/direct_sound_samples/cries/mareanie.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/mareanie.wav b/sound/direct_sound_samples/cries/mareanie.wav new file mode 100644 index 0000000000..8889530143 Binary files /dev/null and b/sound/direct_sound_samples/cries/mareanie.wav differ diff --git a/sound/direct_sound_samples/cries/mareep.aif b/sound/direct_sound_samples/cries/mareep.aif deleted file mode 100644 index 2dfc9e88bc..0000000000 Binary files a/sound/direct_sound_samples/cries/mareep.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/mareep.wav b/sound/direct_sound_samples/cries/mareep.wav new file mode 100644 index 0000000000..386925f5d5 Binary files /dev/null and b/sound/direct_sound_samples/cries/mareep.wav differ diff --git a/sound/direct_sound_samples/cries/marill.aif b/sound/direct_sound_samples/cries/marill.aif deleted file mode 100644 index 1c3b6bc41f..0000000000 Binary files a/sound/direct_sound_samples/cries/marill.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/marill.wav b/sound/direct_sound_samples/cries/marill.wav new file mode 100644 index 0000000000..93201d1c51 Binary files /dev/null and b/sound/direct_sound_samples/cries/marill.wav differ diff --git a/sound/direct_sound_samples/cries/marowak.aif b/sound/direct_sound_samples/cries/marowak.aif deleted file mode 100644 index c081ba9f9d..0000000000 Binary files a/sound/direct_sound_samples/cries/marowak.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/marowak.wav b/sound/direct_sound_samples/cries/marowak.wav new file mode 100644 index 0000000000..7bddb4b347 Binary files /dev/null and b/sound/direct_sound_samples/cries/marowak.wav differ diff --git a/sound/direct_sound_samples/cries/marshadow.aif b/sound/direct_sound_samples/cries/marshadow.aif deleted file mode 100644 index 3092b639f2..0000000000 Binary files a/sound/direct_sound_samples/cries/marshadow.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/marshadow.wav b/sound/direct_sound_samples/cries/marshadow.wav new file mode 100644 index 0000000000..a9cfdf6a14 Binary files /dev/null and b/sound/direct_sound_samples/cries/marshadow.wav differ diff --git a/sound/direct_sound_samples/cries/marshtomp.aif b/sound/direct_sound_samples/cries/marshtomp.aif deleted file mode 100644 index 79728eb087..0000000000 Binary files a/sound/direct_sound_samples/cries/marshtomp.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/marshtomp.wav b/sound/direct_sound_samples/cries/marshtomp.wav new file mode 100644 index 0000000000..0caa959e29 Binary files /dev/null and b/sound/direct_sound_samples/cries/marshtomp.wav differ diff --git a/sound/direct_sound_samples/cries/maschiff.aif b/sound/direct_sound_samples/cries/maschiff.aif deleted file mode 100644 index ee93b59ade..0000000000 Binary files a/sound/direct_sound_samples/cries/maschiff.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/maschiff.wav b/sound/direct_sound_samples/cries/maschiff.wav new file mode 100644 index 0000000000..7b4412d147 Binary files /dev/null and b/sound/direct_sound_samples/cries/maschiff.wav differ diff --git a/sound/direct_sound_samples/cries/masquerain.aif b/sound/direct_sound_samples/cries/masquerain.aif deleted file mode 100644 index e3ef3b9d81..0000000000 Binary files a/sound/direct_sound_samples/cries/masquerain.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/masquerain.wav b/sound/direct_sound_samples/cries/masquerain.wav new file mode 100644 index 0000000000..b0c5372ae3 Binary files /dev/null and b/sound/direct_sound_samples/cries/masquerain.wav differ diff --git a/sound/direct_sound_samples/cries/maushold_four.aif b/sound/direct_sound_samples/cries/maushold_four.aif deleted file mode 100644 index c7c0aee6ee..0000000000 Binary files a/sound/direct_sound_samples/cries/maushold_four.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/maushold_four.wav b/sound/direct_sound_samples/cries/maushold_four.wav new file mode 100644 index 0000000000..b4cc4eb70f Binary files /dev/null and b/sound/direct_sound_samples/cries/maushold_four.wav differ diff --git a/sound/direct_sound_samples/cries/maushold_three.aif b/sound/direct_sound_samples/cries/maushold_three.aif deleted file mode 100644 index 0e771535ea..0000000000 Binary files a/sound/direct_sound_samples/cries/maushold_three.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/maushold_three.wav b/sound/direct_sound_samples/cries/maushold_three.wav new file mode 100644 index 0000000000..5e62f29003 Binary files /dev/null and b/sound/direct_sound_samples/cries/maushold_three.wav differ diff --git a/sound/direct_sound_samples/cries/mawile.aif b/sound/direct_sound_samples/cries/mawile.aif deleted file mode 100644 index 8374bf4797..0000000000 Binary files a/sound/direct_sound_samples/cries/mawile.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/mawile.wav b/sound/direct_sound_samples/cries/mawile.wav new file mode 100644 index 0000000000..9c54d40a48 Binary files /dev/null and b/sound/direct_sound_samples/cries/mawile.wav differ diff --git a/sound/direct_sound_samples/cries/mawile_mega.aif b/sound/direct_sound_samples/cries/mawile_mega.aif deleted file mode 100644 index a6e7ec8c83..0000000000 Binary files a/sound/direct_sound_samples/cries/mawile_mega.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/mawile_mega.wav b/sound/direct_sound_samples/cries/mawile_mega.wav new file mode 100644 index 0000000000..fd19d9e096 Binary files /dev/null and b/sound/direct_sound_samples/cries/mawile_mega.wav differ diff --git a/sound/direct_sound_samples/cries/medicham.aif b/sound/direct_sound_samples/cries/medicham.aif deleted file mode 100644 index 02818ba0dd..0000000000 Binary files a/sound/direct_sound_samples/cries/medicham.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/medicham.wav b/sound/direct_sound_samples/cries/medicham.wav new file mode 100644 index 0000000000..be3668b173 Binary files /dev/null and b/sound/direct_sound_samples/cries/medicham.wav differ diff --git a/sound/direct_sound_samples/cries/medicham_mega.aif b/sound/direct_sound_samples/cries/medicham_mega.aif deleted file mode 100644 index 36db11b2f7..0000000000 Binary files a/sound/direct_sound_samples/cries/medicham_mega.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/medicham_mega.wav b/sound/direct_sound_samples/cries/medicham_mega.wav new file mode 100644 index 0000000000..c71155ae4b Binary files /dev/null and b/sound/direct_sound_samples/cries/medicham_mega.wav differ diff --git a/sound/direct_sound_samples/cries/meditite.aif b/sound/direct_sound_samples/cries/meditite.aif deleted file mode 100644 index e3dc9dd802..0000000000 Binary files a/sound/direct_sound_samples/cries/meditite.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/meditite.wav b/sound/direct_sound_samples/cries/meditite.wav new file mode 100644 index 0000000000..23db4f297f Binary files /dev/null and b/sound/direct_sound_samples/cries/meditite.wav differ diff --git a/sound/direct_sound_samples/cries/meganium.aif b/sound/direct_sound_samples/cries/meganium.aif deleted file mode 100644 index abada35482..0000000000 Binary files a/sound/direct_sound_samples/cries/meganium.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/meganium.wav b/sound/direct_sound_samples/cries/meganium.wav new file mode 100644 index 0000000000..8f7920e937 Binary files /dev/null and b/sound/direct_sound_samples/cries/meganium.wav differ diff --git a/sound/direct_sound_samples/cries/melmetal.aif b/sound/direct_sound_samples/cries/melmetal.aif deleted file mode 100644 index 5590164d1e..0000000000 Binary files a/sound/direct_sound_samples/cries/melmetal.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/melmetal.wav b/sound/direct_sound_samples/cries/melmetal.wav new file mode 100644 index 0000000000..0d16f9494c Binary files /dev/null and b/sound/direct_sound_samples/cries/melmetal.wav differ diff --git a/sound/direct_sound_samples/cries/meloetta.aif b/sound/direct_sound_samples/cries/meloetta.aif deleted file mode 100644 index 298a5214be..0000000000 Binary files a/sound/direct_sound_samples/cries/meloetta.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/meloetta.wav b/sound/direct_sound_samples/cries/meloetta.wav new file mode 100644 index 0000000000..ff7d225b4b Binary files /dev/null and b/sound/direct_sound_samples/cries/meloetta.wav differ diff --git a/sound/direct_sound_samples/cries/meltan.aif b/sound/direct_sound_samples/cries/meltan.aif deleted file mode 100644 index 42b258f517..0000000000 Binary files a/sound/direct_sound_samples/cries/meltan.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/meltan.wav b/sound/direct_sound_samples/cries/meltan.wav new file mode 100644 index 0000000000..8b55a26e23 Binary files /dev/null and b/sound/direct_sound_samples/cries/meltan.wav differ diff --git a/sound/direct_sound_samples/cries/meowscarada.aif b/sound/direct_sound_samples/cries/meowscarada.aif deleted file mode 100644 index 981a07a206..0000000000 Binary files a/sound/direct_sound_samples/cries/meowscarada.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/meowscarada.wav b/sound/direct_sound_samples/cries/meowscarada.wav new file mode 100644 index 0000000000..d251942128 Binary files /dev/null and b/sound/direct_sound_samples/cries/meowscarada.wav differ diff --git a/sound/direct_sound_samples/cries/meowstic.aif b/sound/direct_sound_samples/cries/meowstic.aif deleted file mode 100644 index a8536832b2..0000000000 Binary files a/sound/direct_sound_samples/cries/meowstic.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/meowstic.wav b/sound/direct_sound_samples/cries/meowstic.wav new file mode 100644 index 0000000000..aba57fdda0 Binary files /dev/null and b/sound/direct_sound_samples/cries/meowstic.wav differ diff --git a/sound/direct_sound_samples/cries/meowth.aif b/sound/direct_sound_samples/cries/meowth.aif deleted file mode 100644 index d919e99e63..0000000000 Binary files a/sound/direct_sound_samples/cries/meowth.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/meowth.wav b/sound/direct_sound_samples/cries/meowth.wav new file mode 100644 index 0000000000..bebca1c27e Binary files /dev/null and b/sound/direct_sound_samples/cries/meowth.wav differ diff --git a/sound/direct_sound_samples/cries/mesprit.aif b/sound/direct_sound_samples/cries/mesprit.aif deleted file mode 100644 index 0c76a7f0f4..0000000000 Binary files a/sound/direct_sound_samples/cries/mesprit.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/mesprit.wav b/sound/direct_sound_samples/cries/mesprit.wav new file mode 100644 index 0000000000..cd85af6499 Binary files /dev/null and b/sound/direct_sound_samples/cries/mesprit.wav differ diff --git a/sound/direct_sound_samples/cries/metagross.aif b/sound/direct_sound_samples/cries/metagross.aif deleted file mode 100644 index bb3bc21c67..0000000000 Binary files a/sound/direct_sound_samples/cries/metagross.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/metagross.wav b/sound/direct_sound_samples/cries/metagross.wav new file mode 100644 index 0000000000..5112b3afa8 Binary files /dev/null and b/sound/direct_sound_samples/cries/metagross.wav differ diff --git a/sound/direct_sound_samples/cries/metagross_mega.aif b/sound/direct_sound_samples/cries/metagross_mega.aif deleted file mode 100644 index e1125b659f..0000000000 Binary files a/sound/direct_sound_samples/cries/metagross_mega.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/metagross_mega.wav b/sound/direct_sound_samples/cries/metagross_mega.wav new file mode 100644 index 0000000000..56fbcfb78b Binary files /dev/null and b/sound/direct_sound_samples/cries/metagross_mega.wav differ diff --git a/sound/direct_sound_samples/cries/metang.aif b/sound/direct_sound_samples/cries/metang.aif deleted file mode 100644 index 225cdfbfe1..0000000000 Binary files a/sound/direct_sound_samples/cries/metang.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/metang.wav b/sound/direct_sound_samples/cries/metang.wav new file mode 100644 index 0000000000..700759d207 Binary files /dev/null and b/sound/direct_sound_samples/cries/metang.wav differ diff --git a/sound/direct_sound_samples/cries/metapod.aif b/sound/direct_sound_samples/cries/metapod.aif deleted file mode 100644 index e875755db0..0000000000 Binary files a/sound/direct_sound_samples/cries/metapod.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/metapod.wav b/sound/direct_sound_samples/cries/metapod.wav new file mode 100644 index 0000000000..6df3b6aefb Binary files /dev/null and b/sound/direct_sound_samples/cries/metapod.wav differ diff --git a/sound/direct_sound_samples/cries/mew.aif b/sound/direct_sound_samples/cries/mew.aif deleted file mode 100644 index f0649ee6f8..0000000000 Binary files a/sound/direct_sound_samples/cries/mew.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/mew.wav b/sound/direct_sound_samples/cries/mew.wav new file mode 100644 index 0000000000..e75fa95f35 Binary files /dev/null and b/sound/direct_sound_samples/cries/mew.wav differ diff --git a/sound/direct_sound_samples/cries/mewtwo.aif b/sound/direct_sound_samples/cries/mewtwo.aif deleted file mode 100644 index 2bafa47083..0000000000 Binary files a/sound/direct_sound_samples/cries/mewtwo.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/mewtwo.wav b/sound/direct_sound_samples/cries/mewtwo.wav new file mode 100644 index 0000000000..947984f672 Binary files /dev/null and b/sound/direct_sound_samples/cries/mewtwo.wav differ diff --git a/sound/direct_sound_samples/cries/mewtwo_mega_x.aif b/sound/direct_sound_samples/cries/mewtwo_mega_x.aif deleted file mode 100644 index c484f7b9eb..0000000000 Binary files a/sound/direct_sound_samples/cries/mewtwo_mega_x.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/mewtwo_mega_x.wav b/sound/direct_sound_samples/cries/mewtwo_mega_x.wav new file mode 100644 index 0000000000..84c83efb10 Binary files /dev/null and b/sound/direct_sound_samples/cries/mewtwo_mega_x.wav differ diff --git a/sound/direct_sound_samples/cries/mewtwo_mega_y.aif b/sound/direct_sound_samples/cries/mewtwo_mega_y.aif deleted file mode 100644 index 87a5d54ad9..0000000000 Binary files a/sound/direct_sound_samples/cries/mewtwo_mega_y.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/mewtwo_mega_y.wav b/sound/direct_sound_samples/cries/mewtwo_mega_y.wav new file mode 100644 index 0000000000..b885771fd3 Binary files /dev/null and b/sound/direct_sound_samples/cries/mewtwo_mega_y.wav differ diff --git a/sound/direct_sound_samples/cries/mienfoo.aif b/sound/direct_sound_samples/cries/mienfoo.aif deleted file mode 100644 index 5f9525d87e..0000000000 Binary files a/sound/direct_sound_samples/cries/mienfoo.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/mienfoo.wav b/sound/direct_sound_samples/cries/mienfoo.wav new file mode 100644 index 0000000000..521448e71f Binary files /dev/null and b/sound/direct_sound_samples/cries/mienfoo.wav differ diff --git a/sound/direct_sound_samples/cries/mienshao.aif b/sound/direct_sound_samples/cries/mienshao.aif deleted file mode 100644 index da04c18fc9..0000000000 Binary files a/sound/direct_sound_samples/cries/mienshao.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/mienshao.wav b/sound/direct_sound_samples/cries/mienshao.wav new file mode 100644 index 0000000000..439026ff57 Binary files /dev/null and b/sound/direct_sound_samples/cries/mienshao.wav differ diff --git a/sound/direct_sound_samples/cries/mightyena.aif b/sound/direct_sound_samples/cries/mightyena.aif deleted file mode 100644 index 099c8b9c7b..0000000000 Binary files a/sound/direct_sound_samples/cries/mightyena.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/mightyena.wav b/sound/direct_sound_samples/cries/mightyena.wav new file mode 100644 index 0000000000..0149976e2b Binary files /dev/null and b/sound/direct_sound_samples/cries/mightyena.wav differ diff --git a/sound/direct_sound_samples/cries/milcery.aif b/sound/direct_sound_samples/cries/milcery.aif deleted file mode 100644 index 003fbb4a62..0000000000 Binary files a/sound/direct_sound_samples/cries/milcery.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/milcery.wav b/sound/direct_sound_samples/cries/milcery.wav new file mode 100644 index 0000000000..754329ea32 Binary files /dev/null and b/sound/direct_sound_samples/cries/milcery.wav differ diff --git a/sound/direct_sound_samples/cries/milotic.aif b/sound/direct_sound_samples/cries/milotic.aif deleted file mode 100644 index 796a87f358..0000000000 Binary files a/sound/direct_sound_samples/cries/milotic.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/milotic.wav b/sound/direct_sound_samples/cries/milotic.wav new file mode 100644 index 0000000000..20db44692f Binary files /dev/null and b/sound/direct_sound_samples/cries/milotic.wav differ diff --git a/sound/direct_sound_samples/cries/miltank.aif b/sound/direct_sound_samples/cries/miltank.aif deleted file mode 100644 index cb8ad93ce9..0000000000 Binary files a/sound/direct_sound_samples/cries/miltank.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/miltank.wav b/sound/direct_sound_samples/cries/miltank.wav new file mode 100644 index 0000000000..5f51f525bb Binary files /dev/null and b/sound/direct_sound_samples/cries/miltank.wav differ diff --git a/sound/direct_sound_samples/cries/mime_jr.aif b/sound/direct_sound_samples/cries/mime_jr.aif deleted file mode 100644 index 604c678fae..0000000000 Binary files a/sound/direct_sound_samples/cries/mime_jr.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/mime_jr.wav b/sound/direct_sound_samples/cries/mime_jr.wav new file mode 100644 index 0000000000..a02ccdb3b8 Binary files /dev/null and b/sound/direct_sound_samples/cries/mime_jr.wav differ diff --git a/sound/direct_sound_samples/cries/mimikyu.aif b/sound/direct_sound_samples/cries/mimikyu.aif deleted file mode 100644 index 15f3720dc7..0000000000 Binary files a/sound/direct_sound_samples/cries/mimikyu.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/mimikyu.wav b/sound/direct_sound_samples/cries/mimikyu.wav new file mode 100644 index 0000000000..8f8eab2e64 Binary files /dev/null and b/sound/direct_sound_samples/cries/mimikyu.wav differ diff --git a/sound/direct_sound_samples/cries/minccino.aif b/sound/direct_sound_samples/cries/minccino.aif deleted file mode 100644 index d49eb07414..0000000000 Binary files a/sound/direct_sound_samples/cries/minccino.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/minccino.wav b/sound/direct_sound_samples/cries/minccino.wav new file mode 100644 index 0000000000..b6c21d7d0e Binary files /dev/null and b/sound/direct_sound_samples/cries/minccino.wav differ diff --git a/sound/direct_sound_samples/cries/minior.aif b/sound/direct_sound_samples/cries/minior.aif deleted file mode 100644 index d739824e04..0000000000 Binary files a/sound/direct_sound_samples/cries/minior.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/minior.wav b/sound/direct_sound_samples/cries/minior.wav new file mode 100644 index 0000000000..a1c2689224 Binary files /dev/null and b/sound/direct_sound_samples/cries/minior.wav differ diff --git a/sound/direct_sound_samples/cries/minun.aif b/sound/direct_sound_samples/cries/minun.aif deleted file mode 100644 index 1b0d3405b9..0000000000 Binary files a/sound/direct_sound_samples/cries/minun.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/minun.wav b/sound/direct_sound_samples/cries/minun.wav new file mode 100644 index 0000000000..9e9a62f7e8 Binary files /dev/null and b/sound/direct_sound_samples/cries/minun.wav differ diff --git a/sound/direct_sound_samples/cries/miraidon.aif b/sound/direct_sound_samples/cries/miraidon.aif deleted file mode 100644 index f07c1c360c..0000000000 Binary files a/sound/direct_sound_samples/cries/miraidon.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/miraidon.wav b/sound/direct_sound_samples/cries/miraidon.wav new file mode 100644 index 0000000000..e0b09ed9f4 Binary files /dev/null and b/sound/direct_sound_samples/cries/miraidon.wav differ diff --git a/sound/direct_sound_samples/cries/misdreavus.aif b/sound/direct_sound_samples/cries/misdreavus.aif deleted file mode 100644 index 774a832ea1..0000000000 Binary files a/sound/direct_sound_samples/cries/misdreavus.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/misdreavus.wav b/sound/direct_sound_samples/cries/misdreavus.wav new file mode 100644 index 0000000000..f632986da9 Binary files /dev/null and b/sound/direct_sound_samples/cries/misdreavus.wav differ diff --git a/sound/direct_sound_samples/cries/mismagius.aif b/sound/direct_sound_samples/cries/mismagius.aif deleted file mode 100644 index a9146205ba..0000000000 Binary files a/sound/direct_sound_samples/cries/mismagius.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/mismagius.wav b/sound/direct_sound_samples/cries/mismagius.wav new file mode 100644 index 0000000000..0a19c2bff4 Binary files /dev/null and b/sound/direct_sound_samples/cries/mismagius.wav differ diff --git a/sound/direct_sound_samples/cries/moltres.aif b/sound/direct_sound_samples/cries/moltres.aif deleted file mode 100644 index 39570a316c..0000000000 Binary files a/sound/direct_sound_samples/cries/moltres.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/moltres.wav b/sound/direct_sound_samples/cries/moltres.wav new file mode 100644 index 0000000000..7173a8cad4 Binary files /dev/null and b/sound/direct_sound_samples/cries/moltres.wav differ diff --git a/sound/direct_sound_samples/cries/monferno.aif b/sound/direct_sound_samples/cries/monferno.aif deleted file mode 100644 index 4f34c1de91..0000000000 Binary files a/sound/direct_sound_samples/cries/monferno.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/monferno.wav b/sound/direct_sound_samples/cries/monferno.wav new file mode 100644 index 0000000000..030db53f08 Binary files /dev/null and b/sound/direct_sound_samples/cries/monferno.wav differ diff --git a/sound/direct_sound_samples/cries/morelull.aif b/sound/direct_sound_samples/cries/morelull.aif deleted file mode 100644 index 0b38baf6a4..0000000000 Binary files a/sound/direct_sound_samples/cries/morelull.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/morelull.wav b/sound/direct_sound_samples/cries/morelull.wav new file mode 100644 index 0000000000..05c6d3e75a Binary files /dev/null and b/sound/direct_sound_samples/cries/morelull.wav differ diff --git a/sound/direct_sound_samples/cries/morgrem.aif b/sound/direct_sound_samples/cries/morgrem.aif deleted file mode 100644 index b972242d37..0000000000 Binary files a/sound/direct_sound_samples/cries/morgrem.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/morgrem.wav b/sound/direct_sound_samples/cries/morgrem.wav new file mode 100644 index 0000000000..d478cc0406 Binary files /dev/null and b/sound/direct_sound_samples/cries/morgrem.wav differ diff --git a/sound/direct_sound_samples/cries/morpeko_full_belly.aif b/sound/direct_sound_samples/cries/morpeko_full_belly.aif deleted file mode 100644 index 2feb33beb8..0000000000 Binary files a/sound/direct_sound_samples/cries/morpeko_full_belly.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/morpeko_full_belly.wav b/sound/direct_sound_samples/cries/morpeko_full_belly.wav new file mode 100644 index 0000000000..21943e1a4d Binary files /dev/null and b/sound/direct_sound_samples/cries/morpeko_full_belly.wav differ diff --git a/sound/direct_sound_samples/cries/morpeko_hangry.aif b/sound/direct_sound_samples/cries/morpeko_hangry.aif deleted file mode 100644 index 84a89a2c01..0000000000 Binary files a/sound/direct_sound_samples/cries/morpeko_hangry.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/morpeko_hangry.wav b/sound/direct_sound_samples/cries/morpeko_hangry.wav new file mode 100644 index 0000000000..80c5eed428 Binary files /dev/null and b/sound/direct_sound_samples/cries/morpeko_hangry.wav differ diff --git a/sound/direct_sound_samples/cries/mothim.aif b/sound/direct_sound_samples/cries/mothim.aif deleted file mode 100644 index d2a2c7b8c3..0000000000 Binary files a/sound/direct_sound_samples/cries/mothim.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/mothim.wav b/sound/direct_sound_samples/cries/mothim.wav new file mode 100644 index 0000000000..c1f085d528 Binary files /dev/null and b/sound/direct_sound_samples/cries/mothim.wav differ diff --git a/sound/direct_sound_samples/cries/mr_mime.aif b/sound/direct_sound_samples/cries/mr_mime.aif deleted file mode 100644 index 991eeb9d1c..0000000000 Binary files a/sound/direct_sound_samples/cries/mr_mime.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/mr_mime.wav b/sound/direct_sound_samples/cries/mr_mime.wav new file mode 100644 index 0000000000..23cf310532 Binary files /dev/null and b/sound/direct_sound_samples/cries/mr_mime.wav differ diff --git a/sound/direct_sound_samples/cries/mr_rime.aif b/sound/direct_sound_samples/cries/mr_rime.aif deleted file mode 100644 index 86bbd33304..0000000000 Binary files a/sound/direct_sound_samples/cries/mr_rime.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/mr_rime.wav b/sound/direct_sound_samples/cries/mr_rime.wav new file mode 100644 index 0000000000..653cb286c8 Binary files /dev/null and b/sound/direct_sound_samples/cries/mr_rime.wav differ diff --git a/sound/direct_sound_samples/cries/mudbray.aif b/sound/direct_sound_samples/cries/mudbray.aif deleted file mode 100644 index f7d0c8b287..0000000000 Binary files a/sound/direct_sound_samples/cries/mudbray.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/mudbray.wav b/sound/direct_sound_samples/cries/mudbray.wav new file mode 100644 index 0000000000..72f138c9b7 Binary files /dev/null and b/sound/direct_sound_samples/cries/mudbray.wav differ diff --git a/sound/direct_sound_samples/cries/mudkip.aif b/sound/direct_sound_samples/cries/mudkip.aif deleted file mode 100644 index 0162f94001..0000000000 Binary files a/sound/direct_sound_samples/cries/mudkip.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/mudkip.wav b/sound/direct_sound_samples/cries/mudkip.wav new file mode 100644 index 0000000000..c965efe30c Binary files /dev/null and b/sound/direct_sound_samples/cries/mudkip.wav differ diff --git a/sound/direct_sound_samples/cries/mudsdale.aif b/sound/direct_sound_samples/cries/mudsdale.aif deleted file mode 100644 index 2776ec02da..0000000000 Binary files a/sound/direct_sound_samples/cries/mudsdale.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/mudsdale.wav b/sound/direct_sound_samples/cries/mudsdale.wav new file mode 100644 index 0000000000..01222f6e18 Binary files /dev/null and b/sound/direct_sound_samples/cries/mudsdale.wav differ diff --git a/sound/direct_sound_samples/cries/muk.aif b/sound/direct_sound_samples/cries/muk.aif deleted file mode 100644 index 2abfd59591..0000000000 Binary files a/sound/direct_sound_samples/cries/muk.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/muk.wav b/sound/direct_sound_samples/cries/muk.wav new file mode 100644 index 0000000000..27cd6bdeb1 Binary files /dev/null and b/sound/direct_sound_samples/cries/muk.wav differ diff --git a/sound/direct_sound_samples/cries/munchlax.aif b/sound/direct_sound_samples/cries/munchlax.aif deleted file mode 100644 index ce347a32f4..0000000000 Binary files a/sound/direct_sound_samples/cries/munchlax.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/munchlax.wav b/sound/direct_sound_samples/cries/munchlax.wav new file mode 100644 index 0000000000..ead5eb1974 Binary files /dev/null and b/sound/direct_sound_samples/cries/munchlax.wav differ diff --git a/sound/direct_sound_samples/cries/munkidori.aif b/sound/direct_sound_samples/cries/munkidori.aif deleted file mode 100644 index 7cb192732e..0000000000 Binary files a/sound/direct_sound_samples/cries/munkidori.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/munkidori.wav b/sound/direct_sound_samples/cries/munkidori.wav new file mode 100644 index 0000000000..d37e97ac54 Binary files /dev/null and b/sound/direct_sound_samples/cries/munkidori.wav differ diff --git a/sound/direct_sound_samples/cries/munna.aif b/sound/direct_sound_samples/cries/munna.aif deleted file mode 100644 index 443bb80899..0000000000 Binary files a/sound/direct_sound_samples/cries/munna.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/munna.wav b/sound/direct_sound_samples/cries/munna.wav new file mode 100644 index 0000000000..2de57dd376 Binary files /dev/null and b/sound/direct_sound_samples/cries/munna.wav differ diff --git a/sound/direct_sound_samples/cries/murkrow.aif b/sound/direct_sound_samples/cries/murkrow.aif deleted file mode 100644 index 1e7c6dd792..0000000000 Binary files a/sound/direct_sound_samples/cries/murkrow.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/murkrow.wav b/sound/direct_sound_samples/cries/murkrow.wav new file mode 100644 index 0000000000..5da336fa90 Binary files /dev/null and b/sound/direct_sound_samples/cries/murkrow.wav differ diff --git a/sound/direct_sound_samples/cries/musharna.aif b/sound/direct_sound_samples/cries/musharna.aif deleted file mode 100644 index 69dd2800cf..0000000000 Binary files a/sound/direct_sound_samples/cries/musharna.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/musharna.wav b/sound/direct_sound_samples/cries/musharna.wav new file mode 100644 index 0000000000..cac55c51ff Binary files /dev/null and b/sound/direct_sound_samples/cries/musharna.wav differ diff --git a/sound/direct_sound_samples/cries/nacli.aif b/sound/direct_sound_samples/cries/nacli.aif deleted file mode 100644 index b29d579ee2..0000000000 Binary files a/sound/direct_sound_samples/cries/nacli.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/nacli.wav b/sound/direct_sound_samples/cries/nacli.wav new file mode 100644 index 0000000000..93ec1a80f6 Binary files /dev/null and b/sound/direct_sound_samples/cries/nacli.wav differ diff --git a/sound/direct_sound_samples/cries/naclstack.aif b/sound/direct_sound_samples/cries/naclstack.aif deleted file mode 100644 index 31eca0bd49..0000000000 Binary files a/sound/direct_sound_samples/cries/naclstack.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/naclstack.wav b/sound/direct_sound_samples/cries/naclstack.wav new file mode 100644 index 0000000000..f223208317 Binary files /dev/null and b/sound/direct_sound_samples/cries/naclstack.wav differ diff --git a/sound/direct_sound_samples/cries/naganadel.aif b/sound/direct_sound_samples/cries/naganadel.aif deleted file mode 100644 index 4cd829612b..0000000000 Binary files a/sound/direct_sound_samples/cries/naganadel.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/naganadel.wav b/sound/direct_sound_samples/cries/naganadel.wav new file mode 100644 index 0000000000..989d068a6b Binary files /dev/null and b/sound/direct_sound_samples/cries/naganadel.wav differ diff --git a/sound/direct_sound_samples/cries/natu.aif b/sound/direct_sound_samples/cries/natu.aif deleted file mode 100644 index 7609439888..0000000000 Binary files a/sound/direct_sound_samples/cries/natu.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/natu.wav b/sound/direct_sound_samples/cries/natu.wav new file mode 100644 index 0000000000..4a2c853178 Binary files /dev/null and b/sound/direct_sound_samples/cries/natu.wav differ diff --git a/sound/direct_sound_samples/cries/necrozma.aif b/sound/direct_sound_samples/cries/necrozma.aif deleted file mode 100644 index db81bc135a..0000000000 Binary files a/sound/direct_sound_samples/cries/necrozma.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/necrozma.wav b/sound/direct_sound_samples/cries/necrozma.wav new file mode 100644 index 0000000000..526ead7f45 Binary files /dev/null and b/sound/direct_sound_samples/cries/necrozma.wav differ diff --git a/sound/direct_sound_samples/cries/necrozma_dawn_wings.aif b/sound/direct_sound_samples/cries/necrozma_dawn_wings.aif deleted file mode 100644 index f33539121e..0000000000 Binary files a/sound/direct_sound_samples/cries/necrozma_dawn_wings.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/necrozma_dawn_wings.wav b/sound/direct_sound_samples/cries/necrozma_dawn_wings.wav new file mode 100644 index 0000000000..0ffa398c79 Binary files /dev/null and b/sound/direct_sound_samples/cries/necrozma_dawn_wings.wav differ diff --git a/sound/direct_sound_samples/cries/necrozma_dusk_mane.aif b/sound/direct_sound_samples/cries/necrozma_dusk_mane.aif deleted file mode 100644 index fce3fb2f61..0000000000 Binary files a/sound/direct_sound_samples/cries/necrozma_dusk_mane.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/necrozma_dusk_mane.wav b/sound/direct_sound_samples/cries/necrozma_dusk_mane.wav new file mode 100644 index 0000000000..b601790ba7 Binary files /dev/null and b/sound/direct_sound_samples/cries/necrozma_dusk_mane.wav differ diff --git a/sound/direct_sound_samples/cries/necrozma_ultra.aif b/sound/direct_sound_samples/cries/necrozma_ultra.aif deleted file mode 100644 index cfc9c5f27b..0000000000 Binary files a/sound/direct_sound_samples/cries/necrozma_ultra.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/necrozma_ultra.wav b/sound/direct_sound_samples/cries/necrozma_ultra.wav new file mode 100644 index 0000000000..dfbceebaf4 Binary files /dev/null and b/sound/direct_sound_samples/cries/necrozma_ultra.wav differ diff --git a/sound/direct_sound_samples/cries/nickit.aif b/sound/direct_sound_samples/cries/nickit.aif deleted file mode 100644 index a4d660bb9d..0000000000 Binary files a/sound/direct_sound_samples/cries/nickit.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/nickit.wav b/sound/direct_sound_samples/cries/nickit.wav new file mode 100644 index 0000000000..820a0d5568 Binary files /dev/null and b/sound/direct_sound_samples/cries/nickit.wav differ diff --git a/sound/direct_sound_samples/cries/nidoking.aif b/sound/direct_sound_samples/cries/nidoking.aif deleted file mode 100644 index 5a645ca83a..0000000000 Binary files a/sound/direct_sound_samples/cries/nidoking.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/nidoking.wav b/sound/direct_sound_samples/cries/nidoking.wav new file mode 100644 index 0000000000..556b20bdac Binary files /dev/null and b/sound/direct_sound_samples/cries/nidoking.wav differ diff --git a/sound/direct_sound_samples/cries/nidoqueen.aif b/sound/direct_sound_samples/cries/nidoqueen.aif deleted file mode 100644 index 878570d3f6..0000000000 Binary files a/sound/direct_sound_samples/cries/nidoqueen.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/nidoqueen.wav b/sound/direct_sound_samples/cries/nidoqueen.wav new file mode 100644 index 0000000000..7c23623a17 Binary files /dev/null and b/sound/direct_sound_samples/cries/nidoqueen.wav differ diff --git a/sound/direct_sound_samples/cries/nidoran_f.aif b/sound/direct_sound_samples/cries/nidoran_f.aif deleted file mode 100644 index cf02133949..0000000000 Binary files a/sound/direct_sound_samples/cries/nidoran_f.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/nidoran_f.wav b/sound/direct_sound_samples/cries/nidoran_f.wav new file mode 100644 index 0000000000..2997c2b579 Binary files /dev/null and b/sound/direct_sound_samples/cries/nidoran_f.wav differ diff --git a/sound/direct_sound_samples/cries/nidoran_m.aif b/sound/direct_sound_samples/cries/nidoran_m.aif deleted file mode 100644 index 2e691595bf..0000000000 Binary files a/sound/direct_sound_samples/cries/nidoran_m.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/nidoran_m.wav b/sound/direct_sound_samples/cries/nidoran_m.wav new file mode 100644 index 0000000000..160ab71e7f Binary files /dev/null and b/sound/direct_sound_samples/cries/nidoran_m.wav differ diff --git a/sound/direct_sound_samples/cries/nidorina.aif b/sound/direct_sound_samples/cries/nidorina.aif deleted file mode 100644 index 3f73fd947f..0000000000 Binary files a/sound/direct_sound_samples/cries/nidorina.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/nidorina.wav b/sound/direct_sound_samples/cries/nidorina.wav new file mode 100644 index 0000000000..a46c416701 Binary files /dev/null and b/sound/direct_sound_samples/cries/nidorina.wav differ diff --git a/sound/direct_sound_samples/cries/nidorino.aif b/sound/direct_sound_samples/cries/nidorino.aif deleted file mode 100644 index 75e48cc721..0000000000 Binary files a/sound/direct_sound_samples/cries/nidorino.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/nidorino.wav b/sound/direct_sound_samples/cries/nidorino.wav new file mode 100644 index 0000000000..38db59c2f1 Binary files /dev/null and b/sound/direct_sound_samples/cries/nidorino.wav differ diff --git a/sound/direct_sound_samples/cries/nihilego.aif b/sound/direct_sound_samples/cries/nihilego.aif deleted file mode 100644 index 17c56e8cbf..0000000000 Binary files a/sound/direct_sound_samples/cries/nihilego.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/nihilego.wav b/sound/direct_sound_samples/cries/nihilego.wav new file mode 100644 index 0000000000..8467b70a1f Binary files /dev/null and b/sound/direct_sound_samples/cries/nihilego.wav differ diff --git a/sound/direct_sound_samples/cries/nincada.aif b/sound/direct_sound_samples/cries/nincada.aif deleted file mode 100644 index d4695111cd..0000000000 Binary files a/sound/direct_sound_samples/cries/nincada.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/nincada.wav b/sound/direct_sound_samples/cries/nincada.wav new file mode 100644 index 0000000000..dd5feb818d Binary files /dev/null and b/sound/direct_sound_samples/cries/nincada.wav differ diff --git a/sound/direct_sound_samples/cries/ninetales.aif b/sound/direct_sound_samples/cries/ninetales.aif deleted file mode 100644 index 51a260f9e9..0000000000 Binary files a/sound/direct_sound_samples/cries/ninetales.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/ninetales.wav b/sound/direct_sound_samples/cries/ninetales.wav new file mode 100644 index 0000000000..f84b874364 Binary files /dev/null and b/sound/direct_sound_samples/cries/ninetales.wav differ diff --git a/sound/direct_sound_samples/cries/ninjask.aif b/sound/direct_sound_samples/cries/ninjask.aif deleted file mode 100644 index 06693156a7..0000000000 Binary files a/sound/direct_sound_samples/cries/ninjask.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/ninjask.wav b/sound/direct_sound_samples/cries/ninjask.wav new file mode 100644 index 0000000000..b61f4d37f5 Binary files /dev/null and b/sound/direct_sound_samples/cries/ninjask.wav differ diff --git a/sound/direct_sound_samples/cries/noctowl.aif b/sound/direct_sound_samples/cries/noctowl.aif deleted file mode 100644 index 2a96488f28..0000000000 Binary files a/sound/direct_sound_samples/cries/noctowl.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/noctowl.wav b/sound/direct_sound_samples/cries/noctowl.wav new file mode 100644 index 0000000000..ab705b6f2c Binary files /dev/null and b/sound/direct_sound_samples/cries/noctowl.wav differ diff --git a/sound/direct_sound_samples/cries/noibat.aif b/sound/direct_sound_samples/cries/noibat.aif deleted file mode 100644 index 6f3c18f40d..0000000000 Binary files a/sound/direct_sound_samples/cries/noibat.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/noibat.wav b/sound/direct_sound_samples/cries/noibat.wav new file mode 100644 index 0000000000..346fb772bd Binary files /dev/null and b/sound/direct_sound_samples/cries/noibat.wav differ diff --git a/sound/direct_sound_samples/cries/noivern.aif b/sound/direct_sound_samples/cries/noivern.aif deleted file mode 100644 index 5806e69713..0000000000 Binary files a/sound/direct_sound_samples/cries/noivern.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/noivern.wav b/sound/direct_sound_samples/cries/noivern.wav new file mode 100644 index 0000000000..eb44488e8a Binary files /dev/null and b/sound/direct_sound_samples/cries/noivern.wav differ diff --git a/sound/direct_sound_samples/cries/nosepass.aif b/sound/direct_sound_samples/cries/nosepass.aif deleted file mode 100644 index 04c28caa6b..0000000000 Binary files a/sound/direct_sound_samples/cries/nosepass.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/nosepass.wav b/sound/direct_sound_samples/cries/nosepass.wav new file mode 100644 index 0000000000..1e15fb10d3 Binary files /dev/null and b/sound/direct_sound_samples/cries/nosepass.wav differ diff --git a/sound/direct_sound_samples/cries/numel.aif b/sound/direct_sound_samples/cries/numel.aif deleted file mode 100644 index 9d6c2e0517..0000000000 Binary files a/sound/direct_sound_samples/cries/numel.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/numel.wav b/sound/direct_sound_samples/cries/numel.wav new file mode 100644 index 0000000000..2d2d16f021 Binary files /dev/null and b/sound/direct_sound_samples/cries/numel.wav differ diff --git a/sound/direct_sound_samples/cries/nuzleaf.aif b/sound/direct_sound_samples/cries/nuzleaf.aif deleted file mode 100644 index 2d836705be..0000000000 Binary files a/sound/direct_sound_samples/cries/nuzleaf.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/nuzleaf.wav b/sound/direct_sound_samples/cries/nuzleaf.wav new file mode 100644 index 0000000000..5efb6e8068 Binary files /dev/null and b/sound/direct_sound_samples/cries/nuzleaf.wav differ diff --git a/sound/direct_sound_samples/cries/nymble.aif b/sound/direct_sound_samples/cries/nymble.aif deleted file mode 100644 index bc41462fb6..0000000000 Binary files a/sound/direct_sound_samples/cries/nymble.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/nymble.wav b/sound/direct_sound_samples/cries/nymble.wav new file mode 100644 index 0000000000..aad585fc6c Binary files /dev/null and b/sound/direct_sound_samples/cries/nymble.wav differ diff --git a/sound/direct_sound_samples/cries/obstagoon.aif b/sound/direct_sound_samples/cries/obstagoon.aif deleted file mode 100644 index f1c4a45366..0000000000 Binary files a/sound/direct_sound_samples/cries/obstagoon.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/obstagoon.wav b/sound/direct_sound_samples/cries/obstagoon.wav new file mode 100644 index 0000000000..2b65e063ab Binary files /dev/null and b/sound/direct_sound_samples/cries/obstagoon.wav differ diff --git a/sound/direct_sound_samples/cries/octillery.aif b/sound/direct_sound_samples/cries/octillery.aif deleted file mode 100644 index 1964004551..0000000000 Binary files a/sound/direct_sound_samples/cries/octillery.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/octillery.wav b/sound/direct_sound_samples/cries/octillery.wav new file mode 100644 index 0000000000..190d42c674 Binary files /dev/null and b/sound/direct_sound_samples/cries/octillery.wav differ diff --git a/sound/direct_sound_samples/cries/oddish.aif b/sound/direct_sound_samples/cries/oddish.aif deleted file mode 100644 index 4f30f7ddb4..0000000000 Binary files a/sound/direct_sound_samples/cries/oddish.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/oddish.wav b/sound/direct_sound_samples/cries/oddish.wav new file mode 100644 index 0000000000..de6855d369 Binary files /dev/null and b/sound/direct_sound_samples/cries/oddish.wav differ diff --git a/sound/direct_sound_samples/cries/ogerpon.aif b/sound/direct_sound_samples/cries/ogerpon.aif deleted file mode 100644 index 17b9d94d62..0000000000 Binary files a/sound/direct_sound_samples/cries/ogerpon.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/ogerpon.wav b/sound/direct_sound_samples/cries/ogerpon.wav new file mode 100644 index 0000000000..82a3a54b16 Binary files /dev/null and b/sound/direct_sound_samples/cries/ogerpon.wav differ diff --git a/sound/direct_sound_samples/cries/oinkologne_f.aif b/sound/direct_sound_samples/cries/oinkologne_f.aif deleted file mode 100644 index 885f2e3a7d..0000000000 Binary files a/sound/direct_sound_samples/cries/oinkologne_f.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/oinkologne_f.wav b/sound/direct_sound_samples/cries/oinkologne_f.wav new file mode 100644 index 0000000000..f075ebb3cf Binary files /dev/null and b/sound/direct_sound_samples/cries/oinkologne_f.wav differ diff --git a/sound/direct_sound_samples/cries/oinkologne_m.aif b/sound/direct_sound_samples/cries/oinkologne_m.aif deleted file mode 100644 index 611794de31..0000000000 Binary files a/sound/direct_sound_samples/cries/oinkologne_m.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/oinkologne_m.wav b/sound/direct_sound_samples/cries/oinkologne_m.wav new file mode 100644 index 0000000000..ca0a7e450e Binary files /dev/null and b/sound/direct_sound_samples/cries/oinkologne_m.wav differ diff --git a/sound/direct_sound_samples/cries/okidogi.aif b/sound/direct_sound_samples/cries/okidogi.aif deleted file mode 100644 index f22f3ba335..0000000000 Binary files a/sound/direct_sound_samples/cries/okidogi.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/okidogi.wav b/sound/direct_sound_samples/cries/okidogi.wav new file mode 100644 index 0000000000..1370c786d0 Binary files /dev/null and b/sound/direct_sound_samples/cries/okidogi.wav differ diff --git a/sound/direct_sound_samples/cries/omanyte.aif b/sound/direct_sound_samples/cries/omanyte.aif deleted file mode 100644 index eeedac34db..0000000000 Binary files a/sound/direct_sound_samples/cries/omanyte.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/omanyte.wav b/sound/direct_sound_samples/cries/omanyte.wav new file mode 100644 index 0000000000..3db237ac3f Binary files /dev/null and b/sound/direct_sound_samples/cries/omanyte.wav differ diff --git a/sound/direct_sound_samples/cries/omastar.aif b/sound/direct_sound_samples/cries/omastar.aif deleted file mode 100644 index 9d4f738efd..0000000000 Binary files a/sound/direct_sound_samples/cries/omastar.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/omastar.wav b/sound/direct_sound_samples/cries/omastar.wav new file mode 100644 index 0000000000..69a4ea868f Binary files /dev/null and b/sound/direct_sound_samples/cries/omastar.wav differ diff --git a/sound/direct_sound_samples/cries/onix.aif b/sound/direct_sound_samples/cries/onix.aif deleted file mode 100644 index 6203ce5689..0000000000 Binary files a/sound/direct_sound_samples/cries/onix.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/onix.wav b/sound/direct_sound_samples/cries/onix.wav new file mode 100644 index 0000000000..57da601410 Binary files /dev/null and b/sound/direct_sound_samples/cries/onix.wav differ diff --git a/sound/direct_sound_samples/cries/oranguru.aif b/sound/direct_sound_samples/cries/oranguru.aif deleted file mode 100644 index ec919ba93c..0000000000 Binary files a/sound/direct_sound_samples/cries/oranguru.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/oranguru.wav b/sound/direct_sound_samples/cries/oranguru.wav new file mode 100644 index 0000000000..e8fa50d5d3 Binary files /dev/null and b/sound/direct_sound_samples/cries/oranguru.wav differ diff --git a/sound/direct_sound_samples/cries/orbeetle.aif b/sound/direct_sound_samples/cries/orbeetle.aif deleted file mode 100644 index 4b99afad15..0000000000 Binary files a/sound/direct_sound_samples/cries/orbeetle.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/orbeetle.wav b/sound/direct_sound_samples/cries/orbeetle.wav new file mode 100644 index 0000000000..384fe691d6 Binary files /dev/null and b/sound/direct_sound_samples/cries/orbeetle.wav differ diff --git a/sound/direct_sound_samples/cries/oricorio_baile.aif b/sound/direct_sound_samples/cries/oricorio_baile.aif deleted file mode 100644 index c5ec5af19b..0000000000 Binary files a/sound/direct_sound_samples/cries/oricorio_baile.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/oricorio_baile.wav b/sound/direct_sound_samples/cries/oricorio_baile.wav new file mode 100644 index 0000000000..e1719cf8e9 Binary files /dev/null and b/sound/direct_sound_samples/cries/oricorio_baile.wav differ diff --git a/sound/direct_sound_samples/cries/oricorio_pau.aif b/sound/direct_sound_samples/cries/oricorio_pau.aif deleted file mode 100644 index 4faa6cc083..0000000000 Binary files a/sound/direct_sound_samples/cries/oricorio_pau.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/oricorio_pau.wav b/sound/direct_sound_samples/cries/oricorio_pau.wav new file mode 100644 index 0000000000..71fa963187 Binary files /dev/null and b/sound/direct_sound_samples/cries/oricorio_pau.wav differ diff --git a/sound/direct_sound_samples/cries/oricorio_sensu.aif b/sound/direct_sound_samples/cries/oricorio_sensu.aif deleted file mode 100644 index bdc25a7749..0000000000 Binary files a/sound/direct_sound_samples/cries/oricorio_sensu.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/oricorio_sensu.wav b/sound/direct_sound_samples/cries/oricorio_sensu.wav new file mode 100644 index 0000000000..dc7687252a Binary files /dev/null and b/sound/direct_sound_samples/cries/oricorio_sensu.wav differ diff --git a/sound/direct_sound_samples/cries/orthworm.aif b/sound/direct_sound_samples/cries/orthworm.aif deleted file mode 100644 index f88eec62f0..0000000000 Binary files a/sound/direct_sound_samples/cries/orthworm.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/orthworm.wav b/sound/direct_sound_samples/cries/orthworm.wav new file mode 100644 index 0000000000..df86b5f9d8 Binary files /dev/null and b/sound/direct_sound_samples/cries/orthworm.wav differ diff --git a/sound/direct_sound_samples/cries/oshawott.aif b/sound/direct_sound_samples/cries/oshawott.aif deleted file mode 100644 index 81bf2917ed..0000000000 Binary files a/sound/direct_sound_samples/cries/oshawott.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/oshawott.wav b/sound/direct_sound_samples/cries/oshawott.wav new file mode 100644 index 0000000000..8669120bb3 Binary files /dev/null and b/sound/direct_sound_samples/cries/oshawott.wav differ diff --git a/sound/direct_sound_samples/cries/overqwil.aif b/sound/direct_sound_samples/cries/overqwil.aif deleted file mode 100644 index 8b9a8a2dff..0000000000 Binary files a/sound/direct_sound_samples/cries/overqwil.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/overqwil.wav b/sound/direct_sound_samples/cries/overqwil.wav new file mode 100644 index 0000000000..5b278516fc Binary files /dev/null and b/sound/direct_sound_samples/cries/overqwil.wav differ diff --git a/sound/direct_sound_samples/cries/pachirisu.aif b/sound/direct_sound_samples/cries/pachirisu.aif deleted file mode 100644 index 6471363ee6..0000000000 Binary files a/sound/direct_sound_samples/cries/pachirisu.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/pachirisu.wav b/sound/direct_sound_samples/cries/pachirisu.wav new file mode 100644 index 0000000000..311b40aa53 Binary files /dev/null and b/sound/direct_sound_samples/cries/pachirisu.wav differ diff --git a/sound/direct_sound_samples/cries/palafin_hero.aif b/sound/direct_sound_samples/cries/palafin_hero.aif deleted file mode 100644 index 5ef87ddeb8..0000000000 Binary files a/sound/direct_sound_samples/cries/palafin_hero.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/palafin_hero.wav b/sound/direct_sound_samples/cries/palafin_hero.wav new file mode 100644 index 0000000000..8ec713357d Binary files /dev/null and b/sound/direct_sound_samples/cries/palafin_hero.wav differ diff --git a/sound/direct_sound_samples/cries/palafin_zero.aif b/sound/direct_sound_samples/cries/palafin_zero.aif deleted file mode 100644 index 16051848be..0000000000 Binary files a/sound/direct_sound_samples/cries/palafin_zero.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/palafin_zero.wav b/sound/direct_sound_samples/cries/palafin_zero.wav new file mode 100644 index 0000000000..f8526574c7 Binary files /dev/null and b/sound/direct_sound_samples/cries/palafin_zero.wav differ diff --git a/sound/direct_sound_samples/cries/palkia.aif b/sound/direct_sound_samples/cries/palkia.aif deleted file mode 100644 index dee52b9a59..0000000000 Binary files a/sound/direct_sound_samples/cries/palkia.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/palkia.wav b/sound/direct_sound_samples/cries/palkia.wav new file mode 100644 index 0000000000..b3f057c1a0 Binary files /dev/null and b/sound/direct_sound_samples/cries/palkia.wav differ diff --git a/sound/direct_sound_samples/cries/palossand.aif b/sound/direct_sound_samples/cries/palossand.aif deleted file mode 100644 index a4a1da4fee..0000000000 Binary files a/sound/direct_sound_samples/cries/palossand.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/palossand.wav b/sound/direct_sound_samples/cries/palossand.wav new file mode 100644 index 0000000000..2908e31766 Binary files /dev/null and b/sound/direct_sound_samples/cries/palossand.wav differ diff --git a/sound/direct_sound_samples/cries/palpitoad.aif b/sound/direct_sound_samples/cries/palpitoad.aif deleted file mode 100644 index 054d2dba0b..0000000000 Binary files a/sound/direct_sound_samples/cries/palpitoad.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/palpitoad.wav b/sound/direct_sound_samples/cries/palpitoad.wav new file mode 100644 index 0000000000..04b404c1c7 Binary files /dev/null and b/sound/direct_sound_samples/cries/palpitoad.wav differ diff --git a/sound/direct_sound_samples/cries/pancham.aif b/sound/direct_sound_samples/cries/pancham.aif deleted file mode 100644 index 5a986eddf4..0000000000 Binary files a/sound/direct_sound_samples/cries/pancham.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/pancham.wav b/sound/direct_sound_samples/cries/pancham.wav new file mode 100644 index 0000000000..dbee7918fc Binary files /dev/null and b/sound/direct_sound_samples/cries/pancham.wav differ diff --git a/sound/direct_sound_samples/cries/pangoro.aif b/sound/direct_sound_samples/cries/pangoro.aif deleted file mode 100644 index 47f7bcf2d0..0000000000 Binary files a/sound/direct_sound_samples/cries/pangoro.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/pangoro.wav b/sound/direct_sound_samples/cries/pangoro.wav new file mode 100644 index 0000000000..e277056884 Binary files /dev/null and b/sound/direct_sound_samples/cries/pangoro.wav differ diff --git a/sound/direct_sound_samples/cries/panpour.aif b/sound/direct_sound_samples/cries/panpour.aif deleted file mode 100644 index 18b65158eb..0000000000 Binary files a/sound/direct_sound_samples/cries/panpour.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/panpour.wav b/sound/direct_sound_samples/cries/panpour.wav new file mode 100644 index 0000000000..8a2042cd63 Binary files /dev/null and b/sound/direct_sound_samples/cries/panpour.wav differ diff --git a/sound/direct_sound_samples/cries/pansage.aif b/sound/direct_sound_samples/cries/pansage.aif deleted file mode 100644 index a4d277230f..0000000000 Binary files a/sound/direct_sound_samples/cries/pansage.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/pansage.wav b/sound/direct_sound_samples/cries/pansage.wav new file mode 100644 index 0000000000..30004e0637 Binary files /dev/null and b/sound/direct_sound_samples/cries/pansage.wav differ diff --git a/sound/direct_sound_samples/cries/pansear.aif b/sound/direct_sound_samples/cries/pansear.aif deleted file mode 100644 index 4d76d6089c..0000000000 Binary files a/sound/direct_sound_samples/cries/pansear.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/pansear.wav b/sound/direct_sound_samples/cries/pansear.wav new file mode 100644 index 0000000000..fde72b7e45 Binary files /dev/null and b/sound/direct_sound_samples/cries/pansear.wav differ diff --git a/sound/direct_sound_samples/cries/paras.aif b/sound/direct_sound_samples/cries/paras.aif deleted file mode 100644 index fbfbfaf07b..0000000000 Binary files a/sound/direct_sound_samples/cries/paras.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/paras.wav b/sound/direct_sound_samples/cries/paras.wav new file mode 100644 index 0000000000..ba4a051c9f Binary files /dev/null and b/sound/direct_sound_samples/cries/paras.wav differ diff --git a/sound/direct_sound_samples/cries/parasect.aif b/sound/direct_sound_samples/cries/parasect.aif deleted file mode 100644 index 1251cbabef..0000000000 Binary files a/sound/direct_sound_samples/cries/parasect.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/parasect.wav b/sound/direct_sound_samples/cries/parasect.wav new file mode 100644 index 0000000000..5ff6ac2907 Binary files /dev/null and b/sound/direct_sound_samples/cries/parasect.wav differ diff --git a/sound/direct_sound_samples/cries/passimian.aif b/sound/direct_sound_samples/cries/passimian.aif deleted file mode 100644 index ac824012e5..0000000000 Binary files a/sound/direct_sound_samples/cries/passimian.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/passimian.wav b/sound/direct_sound_samples/cries/passimian.wav new file mode 100644 index 0000000000..f17f2ec250 Binary files /dev/null and b/sound/direct_sound_samples/cries/passimian.wav differ diff --git a/sound/direct_sound_samples/cries/patrat.aif b/sound/direct_sound_samples/cries/patrat.aif deleted file mode 100644 index f1e17939ab..0000000000 Binary files a/sound/direct_sound_samples/cries/patrat.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/patrat.wav b/sound/direct_sound_samples/cries/patrat.wav new file mode 100644 index 0000000000..51982fbc78 Binary files /dev/null and b/sound/direct_sound_samples/cries/patrat.wav differ diff --git a/sound/direct_sound_samples/cries/pawmi.aif b/sound/direct_sound_samples/cries/pawmi.aif deleted file mode 100644 index fa9a9197cb..0000000000 Binary files a/sound/direct_sound_samples/cries/pawmi.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/pawmi.wav b/sound/direct_sound_samples/cries/pawmi.wav new file mode 100644 index 0000000000..ac07672b4a Binary files /dev/null and b/sound/direct_sound_samples/cries/pawmi.wav differ diff --git a/sound/direct_sound_samples/cries/pawmo.aif b/sound/direct_sound_samples/cries/pawmo.aif deleted file mode 100644 index 7fbf646c2f..0000000000 Binary files a/sound/direct_sound_samples/cries/pawmo.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/pawmo.wav b/sound/direct_sound_samples/cries/pawmo.wav new file mode 100644 index 0000000000..8ffc03d005 Binary files /dev/null and b/sound/direct_sound_samples/cries/pawmo.wav differ diff --git a/sound/direct_sound_samples/cries/pawmot.aif b/sound/direct_sound_samples/cries/pawmot.aif deleted file mode 100644 index 40ad2d5bf2..0000000000 Binary files a/sound/direct_sound_samples/cries/pawmot.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/pawmot.wav b/sound/direct_sound_samples/cries/pawmot.wav new file mode 100644 index 0000000000..81fe4267c8 Binary files /dev/null and b/sound/direct_sound_samples/cries/pawmot.wav differ diff --git a/sound/direct_sound_samples/cries/pawniard.aif b/sound/direct_sound_samples/cries/pawniard.aif deleted file mode 100644 index 6196892837..0000000000 Binary files a/sound/direct_sound_samples/cries/pawniard.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/pawniard.wav b/sound/direct_sound_samples/cries/pawniard.wav new file mode 100644 index 0000000000..25663a52c0 Binary files /dev/null and b/sound/direct_sound_samples/cries/pawniard.wav differ diff --git a/sound/direct_sound_samples/cries/pecharunt.aif b/sound/direct_sound_samples/cries/pecharunt.aif deleted file mode 100644 index 024e6bb587..0000000000 Binary files a/sound/direct_sound_samples/cries/pecharunt.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/pecharunt.wav b/sound/direct_sound_samples/cries/pecharunt.wav new file mode 100644 index 0000000000..9d9fadf408 Binary files /dev/null and b/sound/direct_sound_samples/cries/pecharunt.wav differ diff --git a/sound/direct_sound_samples/cries/pelipper.aif b/sound/direct_sound_samples/cries/pelipper.aif deleted file mode 100644 index 64a0080360..0000000000 Binary files a/sound/direct_sound_samples/cries/pelipper.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/pelipper.wav b/sound/direct_sound_samples/cries/pelipper.wav new file mode 100644 index 0000000000..665dbcac9e Binary files /dev/null and b/sound/direct_sound_samples/cries/pelipper.wav differ diff --git a/sound/direct_sound_samples/cries/perrserker.aif b/sound/direct_sound_samples/cries/perrserker.aif deleted file mode 100644 index b790ce5c51..0000000000 Binary files a/sound/direct_sound_samples/cries/perrserker.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/perrserker.wav b/sound/direct_sound_samples/cries/perrserker.wav new file mode 100644 index 0000000000..80845b8c07 Binary files /dev/null and b/sound/direct_sound_samples/cries/perrserker.wav differ diff --git a/sound/direct_sound_samples/cries/persian.aif b/sound/direct_sound_samples/cries/persian.aif deleted file mode 100644 index d87fe2cbe1..0000000000 Binary files a/sound/direct_sound_samples/cries/persian.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/persian.wav b/sound/direct_sound_samples/cries/persian.wav new file mode 100644 index 0000000000..96acf8296c Binary files /dev/null and b/sound/direct_sound_samples/cries/persian.wav differ diff --git a/sound/direct_sound_samples/cries/petilil.aif b/sound/direct_sound_samples/cries/petilil.aif deleted file mode 100644 index 6252c76247..0000000000 Binary files a/sound/direct_sound_samples/cries/petilil.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/petilil.wav b/sound/direct_sound_samples/cries/petilil.wav new file mode 100644 index 0000000000..0bda09b259 Binary files /dev/null and b/sound/direct_sound_samples/cries/petilil.wav differ diff --git a/sound/direct_sound_samples/cries/phanpy.aif b/sound/direct_sound_samples/cries/phanpy.aif deleted file mode 100644 index 0c541c3bf1..0000000000 Binary files a/sound/direct_sound_samples/cries/phanpy.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/phanpy.wav b/sound/direct_sound_samples/cries/phanpy.wav new file mode 100644 index 0000000000..4de13cafe1 Binary files /dev/null and b/sound/direct_sound_samples/cries/phanpy.wav differ diff --git a/sound/direct_sound_samples/cries/phantump.aif b/sound/direct_sound_samples/cries/phantump.aif deleted file mode 100644 index 1afccc074c..0000000000 Binary files a/sound/direct_sound_samples/cries/phantump.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/phantump.wav b/sound/direct_sound_samples/cries/phantump.wav new file mode 100644 index 0000000000..3f0db048ad Binary files /dev/null and b/sound/direct_sound_samples/cries/phantump.wav differ diff --git a/sound/direct_sound_samples/cries/pheromosa.aif b/sound/direct_sound_samples/cries/pheromosa.aif deleted file mode 100644 index bcf57050d3..0000000000 Binary files a/sound/direct_sound_samples/cries/pheromosa.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/pheromosa.wav b/sound/direct_sound_samples/cries/pheromosa.wav new file mode 100644 index 0000000000..a8f41396d3 Binary files /dev/null and b/sound/direct_sound_samples/cries/pheromosa.wav differ diff --git a/sound/direct_sound_samples/cries/phione.aif b/sound/direct_sound_samples/cries/phione.aif deleted file mode 100644 index ba31bd9a5d..0000000000 Binary files a/sound/direct_sound_samples/cries/phione.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/phione.wav b/sound/direct_sound_samples/cries/phione.wav new file mode 100644 index 0000000000..bbc661c9eb Binary files /dev/null and b/sound/direct_sound_samples/cries/phione.wav differ diff --git a/sound/direct_sound_samples/cries/pichu.aif b/sound/direct_sound_samples/cries/pichu.aif deleted file mode 100644 index a0cff3f6f3..0000000000 Binary files a/sound/direct_sound_samples/cries/pichu.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/pichu.wav b/sound/direct_sound_samples/cries/pichu.wav new file mode 100644 index 0000000000..d325103719 Binary files /dev/null and b/sound/direct_sound_samples/cries/pichu.wav differ diff --git a/sound/direct_sound_samples/cries/pidgeot.aif b/sound/direct_sound_samples/cries/pidgeot.aif deleted file mode 100644 index 67f49406a9..0000000000 Binary files a/sound/direct_sound_samples/cries/pidgeot.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/pidgeot.wav b/sound/direct_sound_samples/cries/pidgeot.wav new file mode 100644 index 0000000000..f93ed99656 Binary files /dev/null and b/sound/direct_sound_samples/cries/pidgeot.wav differ diff --git a/sound/direct_sound_samples/cries/pidgeot_mega.aif b/sound/direct_sound_samples/cries/pidgeot_mega.aif deleted file mode 100644 index a1639ba4e9..0000000000 Binary files a/sound/direct_sound_samples/cries/pidgeot_mega.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/pidgeot_mega.wav b/sound/direct_sound_samples/cries/pidgeot_mega.wav new file mode 100644 index 0000000000..1cbd3d7a62 Binary files /dev/null and b/sound/direct_sound_samples/cries/pidgeot_mega.wav differ diff --git a/sound/direct_sound_samples/cries/pidgeotto.aif b/sound/direct_sound_samples/cries/pidgeotto.aif deleted file mode 100644 index f31d3df8cf..0000000000 Binary files a/sound/direct_sound_samples/cries/pidgeotto.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/pidgeotto.wav b/sound/direct_sound_samples/cries/pidgeotto.wav new file mode 100644 index 0000000000..8b40a41e99 Binary files /dev/null and b/sound/direct_sound_samples/cries/pidgeotto.wav differ diff --git a/sound/direct_sound_samples/cries/pidgey.aif b/sound/direct_sound_samples/cries/pidgey.aif deleted file mode 100644 index 3b4b6ece27..0000000000 Binary files a/sound/direct_sound_samples/cries/pidgey.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/pidgey.wav b/sound/direct_sound_samples/cries/pidgey.wav new file mode 100644 index 0000000000..34a1d1bd6a Binary files /dev/null and b/sound/direct_sound_samples/cries/pidgey.wav differ diff --git a/sound/direct_sound_samples/cries/pidove.aif b/sound/direct_sound_samples/cries/pidove.aif deleted file mode 100644 index b2bd5590bc..0000000000 Binary files a/sound/direct_sound_samples/cries/pidove.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/pidove.wav b/sound/direct_sound_samples/cries/pidove.wav new file mode 100644 index 0000000000..56527c92c5 Binary files /dev/null and b/sound/direct_sound_samples/cries/pidove.wav differ diff --git a/sound/direct_sound_samples/cries/pignite.aif b/sound/direct_sound_samples/cries/pignite.aif deleted file mode 100644 index 8e1f78ae2f..0000000000 Binary files a/sound/direct_sound_samples/cries/pignite.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/pignite.wav b/sound/direct_sound_samples/cries/pignite.wav new file mode 100644 index 0000000000..94095d9373 Binary files /dev/null and b/sound/direct_sound_samples/cries/pignite.wav differ diff --git a/sound/direct_sound_samples/cries/pikachu.aif b/sound/direct_sound_samples/cries/pikachu.aif deleted file mode 100644 index 4a7b270245..0000000000 Binary files a/sound/direct_sound_samples/cries/pikachu.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/pikachu.wav b/sound/direct_sound_samples/cries/pikachu.wav new file mode 100644 index 0000000000..d5f68416f2 Binary files /dev/null and b/sound/direct_sound_samples/cries/pikachu.wav differ diff --git a/sound/direct_sound_samples/cries/pikipek.aif b/sound/direct_sound_samples/cries/pikipek.aif deleted file mode 100644 index 04efe56a4c..0000000000 Binary files a/sound/direct_sound_samples/cries/pikipek.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/pikipek.wav b/sound/direct_sound_samples/cries/pikipek.wav new file mode 100644 index 0000000000..67d05ca2d9 Binary files /dev/null and b/sound/direct_sound_samples/cries/pikipek.wav differ diff --git a/sound/direct_sound_samples/cries/piloswine.aif b/sound/direct_sound_samples/cries/piloswine.aif deleted file mode 100644 index 2511d3fd70..0000000000 Binary files a/sound/direct_sound_samples/cries/piloswine.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/piloswine.wav b/sound/direct_sound_samples/cries/piloswine.wav new file mode 100644 index 0000000000..4f181b7ec6 Binary files /dev/null and b/sound/direct_sound_samples/cries/piloswine.wav differ diff --git a/sound/direct_sound_samples/cries/pincurchin.aif b/sound/direct_sound_samples/cries/pincurchin.aif deleted file mode 100644 index 76f68e2111..0000000000 Binary files a/sound/direct_sound_samples/cries/pincurchin.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/pincurchin.wav b/sound/direct_sound_samples/cries/pincurchin.wav new file mode 100644 index 0000000000..070485416f Binary files /dev/null and b/sound/direct_sound_samples/cries/pincurchin.wav differ diff --git a/sound/direct_sound_samples/cries/pineco.aif b/sound/direct_sound_samples/cries/pineco.aif deleted file mode 100644 index acb6de8a0c..0000000000 Binary files a/sound/direct_sound_samples/cries/pineco.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/pineco.wav b/sound/direct_sound_samples/cries/pineco.wav new file mode 100644 index 0000000000..70d841b9e5 Binary files /dev/null and b/sound/direct_sound_samples/cries/pineco.wav differ diff --git a/sound/direct_sound_samples/cries/pinsir.aif b/sound/direct_sound_samples/cries/pinsir.aif deleted file mode 100644 index bfbb268d68..0000000000 Binary files a/sound/direct_sound_samples/cries/pinsir.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/pinsir.wav b/sound/direct_sound_samples/cries/pinsir.wav new file mode 100644 index 0000000000..3d3dcc7929 Binary files /dev/null and b/sound/direct_sound_samples/cries/pinsir.wav differ diff --git a/sound/direct_sound_samples/cries/pinsir_mega.aif b/sound/direct_sound_samples/cries/pinsir_mega.aif deleted file mode 100644 index c2e57d2a39..0000000000 Binary files a/sound/direct_sound_samples/cries/pinsir_mega.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/pinsir_mega.wav b/sound/direct_sound_samples/cries/pinsir_mega.wav new file mode 100644 index 0000000000..36815cbc71 Binary files /dev/null and b/sound/direct_sound_samples/cries/pinsir_mega.wav differ diff --git a/sound/direct_sound_samples/cries/piplup.aif b/sound/direct_sound_samples/cries/piplup.aif deleted file mode 100644 index e8c161eb35..0000000000 Binary files a/sound/direct_sound_samples/cries/piplup.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/piplup.wav b/sound/direct_sound_samples/cries/piplup.wav new file mode 100644 index 0000000000..aacf7d92a0 Binary files /dev/null and b/sound/direct_sound_samples/cries/piplup.wav differ diff --git a/sound/direct_sound_samples/cries/plusle.aif b/sound/direct_sound_samples/cries/plusle.aif deleted file mode 100644 index e584201a8f..0000000000 Binary files a/sound/direct_sound_samples/cries/plusle.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/plusle.wav b/sound/direct_sound_samples/cries/plusle.wav new file mode 100644 index 0000000000..1b3cf87497 Binary files /dev/null and b/sound/direct_sound_samples/cries/plusle.wav differ diff --git a/sound/direct_sound_samples/cries/poipole.aif b/sound/direct_sound_samples/cries/poipole.aif deleted file mode 100644 index c2a141ac85..0000000000 Binary files a/sound/direct_sound_samples/cries/poipole.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/poipole.wav b/sound/direct_sound_samples/cries/poipole.wav new file mode 100644 index 0000000000..9e0ad029c9 Binary files /dev/null and b/sound/direct_sound_samples/cries/poipole.wav differ diff --git a/sound/direct_sound_samples/cries/politoed.aif b/sound/direct_sound_samples/cries/politoed.aif deleted file mode 100644 index 2739c2a428..0000000000 Binary files a/sound/direct_sound_samples/cries/politoed.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/politoed.wav b/sound/direct_sound_samples/cries/politoed.wav new file mode 100644 index 0000000000..6472a08f55 Binary files /dev/null and b/sound/direct_sound_samples/cries/politoed.wav differ diff --git a/sound/direct_sound_samples/cries/poliwag.aif b/sound/direct_sound_samples/cries/poliwag.aif deleted file mode 100644 index d76e209495..0000000000 Binary files a/sound/direct_sound_samples/cries/poliwag.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/poliwag.wav b/sound/direct_sound_samples/cries/poliwag.wav new file mode 100644 index 0000000000..d35c8f4d8f Binary files /dev/null and b/sound/direct_sound_samples/cries/poliwag.wav differ diff --git a/sound/direct_sound_samples/cries/poliwhirl.aif b/sound/direct_sound_samples/cries/poliwhirl.aif deleted file mode 100644 index 4aee053d7f..0000000000 Binary files a/sound/direct_sound_samples/cries/poliwhirl.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/poliwhirl.wav b/sound/direct_sound_samples/cries/poliwhirl.wav new file mode 100644 index 0000000000..0c59fbed64 Binary files /dev/null and b/sound/direct_sound_samples/cries/poliwhirl.wav differ diff --git a/sound/direct_sound_samples/cries/poliwrath.aif b/sound/direct_sound_samples/cries/poliwrath.aif deleted file mode 100644 index bb9d78f3c3..0000000000 Binary files a/sound/direct_sound_samples/cries/poliwrath.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/poliwrath.wav b/sound/direct_sound_samples/cries/poliwrath.wav new file mode 100644 index 0000000000..c32bd44859 Binary files /dev/null and b/sound/direct_sound_samples/cries/poliwrath.wav differ diff --git a/sound/direct_sound_samples/cries/poltchageist.aif b/sound/direct_sound_samples/cries/poltchageist.aif deleted file mode 100644 index 855eb010ce..0000000000 Binary files a/sound/direct_sound_samples/cries/poltchageist.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/poltchageist.wav b/sound/direct_sound_samples/cries/poltchageist.wav new file mode 100644 index 0000000000..33d929e811 Binary files /dev/null and b/sound/direct_sound_samples/cries/poltchageist.wav differ diff --git a/sound/direct_sound_samples/cries/polteageist.aif b/sound/direct_sound_samples/cries/polteageist.aif deleted file mode 100644 index f9051a25c4..0000000000 Binary files a/sound/direct_sound_samples/cries/polteageist.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/polteageist.wav b/sound/direct_sound_samples/cries/polteageist.wav new file mode 100644 index 0000000000..94131a981b Binary files /dev/null and b/sound/direct_sound_samples/cries/polteageist.wav differ diff --git a/sound/direct_sound_samples/cries/ponyta.aif b/sound/direct_sound_samples/cries/ponyta.aif deleted file mode 100644 index ec66a33faf..0000000000 Binary files a/sound/direct_sound_samples/cries/ponyta.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/ponyta.wav b/sound/direct_sound_samples/cries/ponyta.wav new file mode 100644 index 0000000000..911954226d Binary files /dev/null and b/sound/direct_sound_samples/cries/ponyta.wav differ diff --git a/sound/direct_sound_samples/cries/poochyena.aif b/sound/direct_sound_samples/cries/poochyena.aif deleted file mode 100644 index bfa6a00ae2..0000000000 Binary files a/sound/direct_sound_samples/cries/poochyena.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/poochyena.wav b/sound/direct_sound_samples/cries/poochyena.wav new file mode 100644 index 0000000000..16cabc29c6 Binary files /dev/null and b/sound/direct_sound_samples/cries/poochyena.wav differ diff --git a/sound/direct_sound_samples/cries/popplio.aif b/sound/direct_sound_samples/cries/popplio.aif deleted file mode 100644 index cbb3a0ff30..0000000000 Binary files a/sound/direct_sound_samples/cries/popplio.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/popplio.wav b/sound/direct_sound_samples/cries/popplio.wav new file mode 100644 index 0000000000..f3226c862a Binary files /dev/null and b/sound/direct_sound_samples/cries/popplio.wav differ diff --git a/sound/direct_sound_samples/cries/porygon.aif b/sound/direct_sound_samples/cries/porygon.aif deleted file mode 100644 index 79160cdbbb..0000000000 Binary files a/sound/direct_sound_samples/cries/porygon.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/porygon.wav b/sound/direct_sound_samples/cries/porygon.wav new file mode 100644 index 0000000000..11dd528dda Binary files /dev/null and b/sound/direct_sound_samples/cries/porygon.wav differ diff --git a/sound/direct_sound_samples/cries/porygon2.aif b/sound/direct_sound_samples/cries/porygon2.aif deleted file mode 100644 index 94237057b1..0000000000 Binary files a/sound/direct_sound_samples/cries/porygon2.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/porygon2.wav b/sound/direct_sound_samples/cries/porygon2.wav new file mode 100644 index 0000000000..5699d8e450 Binary files /dev/null and b/sound/direct_sound_samples/cries/porygon2.wav differ diff --git a/sound/direct_sound_samples/cries/porygon_z.aif b/sound/direct_sound_samples/cries/porygon_z.aif deleted file mode 100644 index 55448d13c0..0000000000 Binary files a/sound/direct_sound_samples/cries/porygon_z.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/porygon_z.wav b/sound/direct_sound_samples/cries/porygon_z.wav new file mode 100644 index 0000000000..215d9b7e6d Binary files /dev/null and b/sound/direct_sound_samples/cries/porygon_z.wav differ diff --git a/sound/direct_sound_samples/cries/primarina.aif b/sound/direct_sound_samples/cries/primarina.aif deleted file mode 100644 index 7952fda82e..0000000000 Binary files a/sound/direct_sound_samples/cries/primarina.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/primarina.wav b/sound/direct_sound_samples/cries/primarina.wav new file mode 100644 index 0000000000..60e0cef0b6 Binary files /dev/null and b/sound/direct_sound_samples/cries/primarina.wav differ diff --git a/sound/direct_sound_samples/cries/primeape.aif b/sound/direct_sound_samples/cries/primeape.aif deleted file mode 100644 index 35898bf2e6..0000000000 Binary files a/sound/direct_sound_samples/cries/primeape.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/primeape.wav b/sound/direct_sound_samples/cries/primeape.wav new file mode 100644 index 0000000000..bcd98e6bb4 Binary files /dev/null and b/sound/direct_sound_samples/cries/primeape.wav differ diff --git a/sound/direct_sound_samples/cries/prinplup.aif b/sound/direct_sound_samples/cries/prinplup.aif deleted file mode 100644 index 62311c1cbf..0000000000 Binary files a/sound/direct_sound_samples/cries/prinplup.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/prinplup.wav b/sound/direct_sound_samples/cries/prinplup.wav new file mode 100644 index 0000000000..8b914e4add Binary files /dev/null and b/sound/direct_sound_samples/cries/prinplup.wav differ diff --git a/sound/direct_sound_samples/cries/probopass.aif b/sound/direct_sound_samples/cries/probopass.aif deleted file mode 100644 index ac831dbf20..0000000000 Binary files a/sound/direct_sound_samples/cries/probopass.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/probopass.wav b/sound/direct_sound_samples/cries/probopass.wav new file mode 100644 index 0000000000..b749429c8a Binary files /dev/null and b/sound/direct_sound_samples/cries/probopass.wav differ diff --git a/sound/direct_sound_samples/cries/psyduck.aif b/sound/direct_sound_samples/cries/psyduck.aif deleted file mode 100644 index e99270f05f..0000000000 Binary files a/sound/direct_sound_samples/cries/psyduck.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/psyduck.wav b/sound/direct_sound_samples/cries/psyduck.wav new file mode 100644 index 0000000000..bdc0d673e3 Binary files /dev/null and b/sound/direct_sound_samples/cries/psyduck.wav differ diff --git a/sound/direct_sound_samples/cries/pumpkaboo.aif b/sound/direct_sound_samples/cries/pumpkaboo.aif deleted file mode 100644 index 6960875e58..0000000000 Binary files a/sound/direct_sound_samples/cries/pumpkaboo.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/pumpkaboo.wav b/sound/direct_sound_samples/cries/pumpkaboo.wav new file mode 100644 index 0000000000..ac870aaa23 Binary files /dev/null and b/sound/direct_sound_samples/cries/pumpkaboo.wav differ diff --git a/sound/direct_sound_samples/cries/pumpkaboo_super.aif b/sound/direct_sound_samples/cries/pumpkaboo_super.aif deleted file mode 100644 index f6c7500f68..0000000000 Binary files a/sound/direct_sound_samples/cries/pumpkaboo_super.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/pumpkaboo_super.wav b/sound/direct_sound_samples/cries/pumpkaboo_super.wav new file mode 100644 index 0000000000..62b4bc3743 Binary files /dev/null and b/sound/direct_sound_samples/cries/pumpkaboo_super.wav differ diff --git a/sound/direct_sound_samples/cries/pupitar.aif b/sound/direct_sound_samples/cries/pupitar.aif deleted file mode 100644 index eb4674d521..0000000000 Binary files a/sound/direct_sound_samples/cries/pupitar.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/pupitar.wav b/sound/direct_sound_samples/cries/pupitar.wav new file mode 100644 index 0000000000..5e797d420f Binary files /dev/null and b/sound/direct_sound_samples/cries/pupitar.wav differ diff --git a/sound/direct_sound_samples/cries/purrloin.aif b/sound/direct_sound_samples/cries/purrloin.aif deleted file mode 100644 index ceb00874c5..0000000000 Binary files a/sound/direct_sound_samples/cries/purrloin.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/purrloin.wav b/sound/direct_sound_samples/cries/purrloin.wav new file mode 100644 index 0000000000..1abbc33d21 Binary files /dev/null and b/sound/direct_sound_samples/cries/purrloin.wav differ diff --git a/sound/direct_sound_samples/cries/purugly.aif b/sound/direct_sound_samples/cries/purugly.aif deleted file mode 100644 index 9f6460a630..0000000000 Binary files a/sound/direct_sound_samples/cries/purugly.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/purugly.wav b/sound/direct_sound_samples/cries/purugly.wav new file mode 100644 index 0000000000..662bdaafe8 Binary files /dev/null and b/sound/direct_sound_samples/cries/purugly.wav differ diff --git a/sound/direct_sound_samples/cries/pyroar.aif b/sound/direct_sound_samples/cries/pyroar.aif deleted file mode 100644 index 7bf77d50cb..0000000000 Binary files a/sound/direct_sound_samples/cries/pyroar.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/pyroar.wav b/sound/direct_sound_samples/cries/pyroar.wav new file mode 100644 index 0000000000..9e145824f1 Binary files /dev/null and b/sound/direct_sound_samples/cries/pyroar.wav differ diff --git a/sound/direct_sound_samples/cries/pyukumuku.aif b/sound/direct_sound_samples/cries/pyukumuku.aif deleted file mode 100644 index ad1d740c31..0000000000 Binary files a/sound/direct_sound_samples/cries/pyukumuku.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/pyukumuku.wav b/sound/direct_sound_samples/cries/pyukumuku.wav new file mode 100644 index 0000000000..eb2a7eaf4f Binary files /dev/null and b/sound/direct_sound_samples/cries/pyukumuku.wav differ diff --git a/sound/direct_sound_samples/cries/quagsire.aif b/sound/direct_sound_samples/cries/quagsire.aif deleted file mode 100644 index 7373b6bb0c..0000000000 Binary files a/sound/direct_sound_samples/cries/quagsire.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/quagsire.wav b/sound/direct_sound_samples/cries/quagsire.wav new file mode 100644 index 0000000000..e4a8c0aad3 Binary files /dev/null and b/sound/direct_sound_samples/cries/quagsire.wav differ diff --git a/sound/direct_sound_samples/cries/quaquaval.aif b/sound/direct_sound_samples/cries/quaquaval.aif deleted file mode 100644 index d04fac23ff..0000000000 Binary files a/sound/direct_sound_samples/cries/quaquaval.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/quaquaval.wav b/sound/direct_sound_samples/cries/quaquaval.wav new file mode 100644 index 0000000000..65cce8b829 Binary files /dev/null and b/sound/direct_sound_samples/cries/quaquaval.wav differ diff --git a/sound/direct_sound_samples/cries/quaxly.aif b/sound/direct_sound_samples/cries/quaxly.aif deleted file mode 100644 index 81606b4a19..0000000000 Binary files a/sound/direct_sound_samples/cries/quaxly.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/quaxly.wav b/sound/direct_sound_samples/cries/quaxly.wav new file mode 100644 index 0000000000..b886a0b8ce Binary files /dev/null and b/sound/direct_sound_samples/cries/quaxly.wav differ diff --git a/sound/direct_sound_samples/cries/quaxwell.aif b/sound/direct_sound_samples/cries/quaxwell.aif deleted file mode 100644 index 62669362ea..0000000000 Binary files a/sound/direct_sound_samples/cries/quaxwell.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/quaxwell.wav b/sound/direct_sound_samples/cries/quaxwell.wav new file mode 100644 index 0000000000..f0ff99f2aa Binary files /dev/null and b/sound/direct_sound_samples/cries/quaxwell.wav differ diff --git a/sound/direct_sound_samples/cries/quilava.aif b/sound/direct_sound_samples/cries/quilava.aif deleted file mode 100644 index 40d3db5594..0000000000 Binary files a/sound/direct_sound_samples/cries/quilava.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/quilava.wav b/sound/direct_sound_samples/cries/quilava.wav new file mode 100644 index 0000000000..ef0bd7381f Binary files /dev/null and b/sound/direct_sound_samples/cries/quilava.wav differ diff --git a/sound/direct_sound_samples/cries/quilladin.aif b/sound/direct_sound_samples/cries/quilladin.aif deleted file mode 100644 index 9b6dfabdc6..0000000000 Binary files a/sound/direct_sound_samples/cries/quilladin.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/quilladin.wav b/sound/direct_sound_samples/cries/quilladin.wav new file mode 100644 index 0000000000..1cce00c5ca Binary files /dev/null and b/sound/direct_sound_samples/cries/quilladin.wav differ diff --git a/sound/direct_sound_samples/cries/qwilfish.aif b/sound/direct_sound_samples/cries/qwilfish.aif deleted file mode 100644 index a5a56480f1..0000000000 Binary files a/sound/direct_sound_samples/cries/qwilfish.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/qwilfish.wav b/sound/direct_sound_samples/cries/qwilfish.wav new file mode 100644 index 0000000000..0b11276dec Binary files /dev/null and b/sound/direct_sound_samples/cries/qwilfish.wav differ diff --git a/sound/direct_sound_samples/cries/raboot.aif b/sound/direct_sound_samples/cries/raboot.aif deleted file mode 100644 index b1a6d09892..0000000000 Binary files a/sound/direct_sound_samples/cries/raboot.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/raboot.wav b/sound/direct_sound_samples/cries/raboot.wav new file mode 100644 index 0000000000..02fa5e3761 Binary files /dev/null and b/sound/direct_sound_samples/cries/raboot.wav differ diff --git a/sound/direct_sound_samples/cries/rabsca.aif b/sound/direct_sound_samples/cries/rabsca.aif deleted file mode 100644 index 5665f79865..0000000000 Binary files a/sound/direct_sound_samples/cries/rabsca.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/rabsca.wav b/sound/direct_sound_samples/cries/rabsca.wav new file mode 100644 index 0000000000..ca041c6cee Binary files /dev/null and b/sound/direct_sound_samples/cries/rabsca.wav differ diff --git a/sound/direct_sound_samples/cries/raging_bolt.aif b/sound/direct_sound_samples/cries/raging_bolt.aif deleted file mode 100644 index 5b787e8116..0000000000 Binary files a/sound/direct_sound_samples/cries/raging_bolt.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/raging_bolt.wav b/sound/direct_sound_samples/cries/raging_bolt.wav new file mode 100644 index 0000000000..f7e920d1b0 Binary files /dev/null and b/sound/direct_sound_samples/cries/raging_bolt.wav differ diff --git a/sound/direct_sound_samples/cries/raichu.aif b/sound/direct_sound_samples/cries/raichu.aif deleted file mode 100644 index 001dcba627..0000000000 Binary files a/sound/direct_sound_samples/cries/raichu.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/raichu.wav b/sound/direct_sound_samples/cries/raichu.wav new file mode 100644 index 0000000000..4e5dbaeb40 Binary files /dev/null and b/sound/direct_sound_samples/cries/raichu.wav differ diff --git a/sound/direct_sound_samples/cries/raikou.aif b/sound/direct_sound_samples/cries/raikou.aif deleted file mode 100644 index ac1e846691..0000000000 Binary files a/sound/direct_sound_samples/cries/raikou.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/raikou.wav b/sound/direct_sound_samples/cries/raikou.wav new file mode 100644 index 0000000000..fefeb1e3a5 Binary files /dev/null and b/sound/direct_sound_samples/cries/raikou.wav differ diff --git a/sound/direct_sound_samples/cries/ralts.aif b/sound/direct_sound_samples/cries/ralts.aif deleted file mode 100644 index 660438548c..0000000000 Binary files a/sound/direct_sound_samples/cries/ralts.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/ralts.wav b/sound/direct_sound_samples/cries/ralts.wav new file mode 100644 index 0000000000..4327c13a12 Binary files /dev/null and b/sound/direct_sound_samples/cries/ralts.wav differ diff --git a/sound/direct_sound_samples/cries/rampardos.aif b/sound/direct_sound_samples/cries/rampardos.aif deleted file mode 100644 index edec1aac4f..0000000000 Binary files a/sound/direct_sound_samples/cries/rampardos.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/rampardos.wav b/sound/direct_sound_samples/cries/rampardos.wav new file mode 100644 index 0000000000..de2cfc5002 Binary files /dev/null and b/sound/direct_sound_samples/cries/rampardos.wav differ diff --git a/sound/direct_sound_samples/cries/rapidash.aif b/sound/direct_sound_samples/cries/rapidash.aif deleted file mode 100644 index c070475d18..0000000000 Binary files a/sound/direct_sound_samples/cries/rapidash.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/rapidash.wav b/sound/direct_sound_samples/cries/rapidash.wav new file mode 100644 index 0000000000..14ce75be75 Binary files /dev/null and b/sound/direct_sound_samples/cries/rapidash.wav differ diff --git a/sound/direct_sound_samples/cries/raticate.aif b/sound/direct_sound_samples/cries/raticate.aif deleted file mode 100644 index fd726b655f..0000000000 Binary files a/sound/direct_sound_samples/cries/raticate.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/raticate.wav b/sound/direct_sound_samples/cries/raticate.wav new file mode 100644 index 0000000000..545ebfcf12 Binary files /dev/null and b/sound/direct_sound_samples/cries/raticate.wav differ diff --git a/sound/direct_sound_samples/cries/rattata.aif b/sound/direct_sound_samples/cries/rattata.aif deleted file mode 100644 index af6a4f2468..0000000000 Binary files a/sound/direct_sound_samples/cries/rattata.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/rattata.wav b/sound/direct_sound_samples/cries/rattata.wav new file mode 100644 index 0000000000..9e7a6b3cf6 Binary files /dev/null and b/sound/direct_sound_samples/cries/rattata.wav differ diff --git a/sound/direct_sound_samples/cries/rayquaza.aif b/sound/direct_sound_samples/cries/rayquaza.aif deleted file mode 100644 index ba7a73c7ee..0000000000 Binary files a/sound/direct_sound_samples/cries/rayquaza.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/rayquaza.wav b/sound/direct_sound_samples/cries/rayquaza.wav new file mode 100644 index 0000000000..c4e50535fc Binary files /dev/null and b/sound/direct_sound_samples/cries/rayquaza.wav differ diff --git a/sound/direct_sound_samples/cries/rayquaza_mega.aif b/sound/direct_sound_samples/cries/rayquaza_mega.aif deleted file mode 100644 index 1b78a94e93..0000000000 Binary files a/sound/direct_sound_samples/cries/rayquaza_mega.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/rayquaza_mega.wav b/sound/direct_sound_samples/cries/rayquaza_mega.wav new file mode 100644 index 0000000000..ee9804b9ad Binary files /dev/null and b/sound/direct_sound_samples/cries/rayquaza_mega.wav differ diff --git a/sound/direct_sound_samples/cries/regice.aif b/sound/direct_sound_samples/cries/regice.aif deleted file mode 100644 index 812737a805..0000000000 Binary files a/sound/direct_sound_samples/cries/regice.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/regice.wav b/sound/direct_sound_samples/cries/regice.wav new file mode 100644 index 0000000000..b65a79b4d4 Binary files /dev/null and b/sound/direct_sound_samples/cries/regice.wav differ diff --git a/sound/direct_sound_samples/cries/regidrago.aif b/sound/direct_sound_samples/cries/regidrago.aif deleted file mode 100644 index d67dbe0ce3..0000000000 Binary files a/sound/direct_sound_samples/cries/regidrago.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/regidrago.wav b/sound/direct_sound_samples/cries/regidrago.wav new file mode 100644 index 0000000000..2231254c30 Binary files /dev/null and b/sound/direct_sound_samples/cries/regidrago.wav differ diff --git a/sound/direct_sound_samples/cries/regieleki.aif b/sound/direct_sound_samples/cries/regieleki.aif deleted file mode 100644 index 75061bccff..0000000000 Binary files a/sound/direct_sound_samples/cries/regieleki.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/regieleki.wav b/sound/direct_sound_samples/cries/regieleki.wav new file mode 100644 index 0000000000..036545f82e Binary files /dev/null and b/sound/direct_sound_samples/cries/regieleki.wav differ diff --git a/sound/direct_sound_samples/cries/regigigas.aif b/sound/direct_sound_samples/cries/regigigas.aif deleted file mode 100644 index 9de9e451d8..0000000000 Binary files a/sound/direct_sound_samples/cries/regigigas.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/regigigas.wav b/sound/direct_sound_samples/cries/regigigas.wav new file mode 100644 index 0000000000..379ea83936 Binary files /dev/null and b/sound/direct_sound_samples/cries/regigigas.wav differ diff --git a/sound/direct_sound_samples/cries/regirock.aif b/sound/direct_sound_samples/cries/regirock.aif deleted file mode 100644 index b9c2948095..0000000000 Binary files a/sound/direct_sound_samples/cries/regirock.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/regirock.wav b/sound/direct_sound_samples/cries/regirock.wav new file mode 100644 index 0000000000..0df3c1a720 Binary files /dev/null and b/sound/direct_sound_samples/cries/regirock.wav differ diff --git a/sound/direct_sound_samples/cries/registeel.aif b/sound/direct_sound_samples/cries/registeel.aif deleted file mode 100644 index 5afe87279e..0000000000 Binary files a/sound/direct_sound_samples/cries/registeel.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/registeel.wav b/sound/direct_sound_samples/cries/registeel.wav new file mode 100644 index 0000000000..0e2b21beb2 Binary files /dev/null and b/sound/direct_sound_samples/cries/registeel.wav differ diff --git a/sound/direct_sound_samples/cries/relicanth.aif b/sound/direct_sound_samples/cries/relicanth.aif deleted file mode 100644 index a9c2b69e60..0000000000 Binary files a/sound/direct_sound_samples/cries/relicanth.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/relicanth.wav b/sound/direct_sound_samples/cries/relicanth.wav new file mode 100644 index 0000000000..1a8c04473c Binary files /dev/null and b/sound/direct_sound_samples/cries/relicanth.wav differ diff --git a/sound/direct_sound_samples/cries/rellor.aif b/sound/direct_sound_samples/cries/rellor.aif deleted file mode 100644 index 0a2f79805f..0000000000 Binary files a/sound/direct_sound_samples/cries/rellor.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/rellor.wav b/sound/direct_sound_samples/cries/rellor.wav new file mode 100644 index 0000000000..813e82b3ac Binary files /dev/null and b/sound/direct_sound_samples/cries/rellor.wav differ diff --git a/sound/direct_sound_samples/cries/remoraid.aif b/sound/direct_sound_samples/cries/remoraid.aif deleted file mode 100644 index f879cf2835..0000000000 Binary files a/sound/direct_sound_samples/cries/remoraid.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/remoraid.wav b/sound/direct_sound_samples/cries/remoraid.wav new file mode 100644 index 0000000000..0465e033f1 Binary files /dev/null and b/sound/direct_sound_samples/cries/remoraid.wav differ diff --git a/sound/direct_sound_samples/cries/reshiram.aif b/sound/direct_sound_samples/cries/reshiram.aif deleted file mode 100644 index 870d3cf515..0000000000 Binary files a/sound/direct_sound_samples/cries/reshiram.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/reshiram.wav b/sound/direct_sound_samples/cries/reshiram.wav new file mode 100644 index 0000000000..7dc4f6d0fe Binary files /dev/null and b/sound/direct_sound_samples/cries/reshiram.wav differ diff --git a/sound/direct_sound_samples/cries/reuniclus.aif b/sound/direct_sound_samples/cries/reuniclus.aif deleted file mode 100644 index ab22f0f97e..0000000000 Binary files a/sound/direct_sound_samples/cries/reuniclus.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/reuniclus.wav b/sound/direct_sound_samples/cries/reuniclus.wav new file mode 100644 index 0000000000..addb5c3a1c Binary files /dev/null and b/sound/direct_sound_samples/cries/reuniclus.wav differ diff --git a/sound/direct_sound_samples/cries/revavroom.aif b/sound/direct_sound_samples/cries/revavroom.aif deleted file mode 100644 index e52bf1c6fe..0000000000 Binary files a/sound/direct_sound_samples/cries/revavroom.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/revavroom.wav b/sound/direct_sound_samples/cries/revavroom.wav new file mode 100644 index 0000000000..a9457ee018 Binary files /dev/null and b/sound/direct_sound_samples/cries/revavroom.wav differ diff --git a/sound/direct_sound_samples/cries/rhydon.aif b/sound/direct_sound_samples/cries/rhydon.aif deleted file mode 100644 index c02623703d..0000000000 Binary files a/sound/direct_sound_samples/cries/rhydon.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/rhydon.wav b/sound/direct_sound_samples/cries/rhydon.wav new file mode 100644 index 0000000000..e4f024f312 Binary files /dev/null and b/sound/direct_sound_samples/cries/rhydon.wav differ diff --git a/sound/direct_sound_samples/cries/rhyhorn.aif b/sound/direct_sound_samples/cries/rhyhorn.aif deleted file mode 100644 index 9a80e08f01..0000000000 Binary files a/sound/direct_sound_samples/cries/rhyhorn.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/rhyhorn.wav b/sound/direct_sound_samples/cries/rhyhorn.wav new file mode 100644 index 0000000000..10c6841f43 Binary files /dev/null and b/sound/direct_sound_samples/cries/rhyhorn.wav differ diff --git a/sound/direct_sound_samples/cries/rhyperior.aif b/sound/direct_sound_samples/cries/rhyperior.aif deleted file mode 100644 index 210a7c8fd3..0000000000 Binary files a/sound/direct_sound_samples/cries/rhyperior.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/rhyperior.wav b/sound/direct_sound_samples/cries/rhyperior.wav new file mode 100644 index 0000000000..57a5002684 Binary files /dev/null and b/sound/direct_sound_samples/cries/rhyperior.wav differ diff --git a/sound/direct_sound_samples/cries/ribombee.aif b/sound/direct_sound_samples/cries/ribombee.aif deleted file mode 100644 index fb7dcd1f87..0000000000 Binary files a/sound/direct_sound_samples/cries/ribombee.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/ribombee.wav b/sound/direct_sound_samples/cries/ribombee.wav new file mode 100644 index 0000000000..36e292cc32 Binary files /dev/null and b/sound/direct_sound_samples/cries/ribombee.wav differ diff --git a/sound/direct_sound_samples/cries/rillaboom.aif b/sound/direct_sound_samples/cries/rillaboom.aif deleted file mode 100644 index f7e4624e88..0000000000 Binary files a/sound/direct_sound_samples/cries/rillaboom.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/rillaboom.wav b/sound/direct_sound_samples/cries/rillaboom.wav new file mode 100644 index 0000000000..2757ed87cb Binary files /dev/null and b/sound/direct_sound_samples/cries/rillaboom.wav differ diff --git a/sound/direct_sound_samples/cries/riolu.aif b/sound/direct_sound_samples/cries/riolu.aif deleted file mode 100644 index cd25b09faf..0000000000 Binary files a/sound/direct_sound_samples/cries/riolu.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/riolu.wav b/sound/direct_sound_samples/cries/riolu.wav new file mode 100644 index 0000000000..051e7e2acf Binary files /dev/null and b/sound/direct_sound_samples/cries/riolu.wav differ diff --git a/sound/direct_sound_samples/cries/roaring_moon.aif b/sound/direct_sound_samples/cries/roaring_moon.aif deleted file mode 100644 index 3c258496dc..0000000000 Binary files a/sound/direct_sound_samples/cries/roaring_moon.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/roaring_moon.wav b/sound/direct_sound_samples/cries/roaring_moon.wav new file mode 100644 index 0000000000..72ed1c9139 Binary files /dev/null and b/sound/direct_sound_samples/cries/roaring_moon.wav differ diff --git a/sound/direct_sound_samples/cries/rockruff.aif b/sound/direct_sound_samples/cries/rockruff.aif deleted file mode 100644 index 90f6bed36b..0000000000 Binary files a/sound/direct_sound_samples/cries/rockruff.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/rockruff.wav b/sound/direct_sound_samples/cries/rockruff.wav new file mode 100644 index 0000000000..520eaf194f Binary files /dev/null and b/sound/direct_sound_samples/cries/rockruff.wav differ diff --git a/sound/direct_sound_samples/cries/roggenrola.aif b/sound/direct_sound_samples/cries/roggenrola.aif deleted file mode 100644 index 8f2f7c8fa0..0000000000 Binary files a/sound/direct_sound_samples/cries/roggenrola.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/roggenrola.wav b/sound/direct_sound_samples/cries/roggenrola.wav new file mode 100644 index 0000000000..34e9fe2f4a Binary files /dev/null and b/sound/direct_sound_samples/cries/roggenrola.wav differ diff --git a/sound/direct_sound_samples/cries/rolycoly.aif b/sound/direct_sound_samples/cries/rolycoly.aif deleted file mode 100644 index cf6a7cefa6..0000000000 Binary files a/sound/direct_sound_samples/cries/rolycoly.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/rolycoly.wav b/sound/direct_sound_samples/cries/rolycoly.wav new file mode 100644 index 0000000000..bae65dde29 Binary files /dev/null and b/sound/direct_sound_samples/cries/rolycoly.wav differ diff --git a/sound/direct_sound_samples/cries/rookidee.aif b/sound/direct_sound_samples/cries/rookidee.aif deleted file mode 100644 index 6fba48730a..0000000000 Binary files a/sound/direct_sound_samples/cries/rookidee.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/rookidee.wav b/sound/direct_sound_samples/cries/rookidee.wav new file mode 100644 index 0000000000..42217ed7eb Binary files /dev/null and b/sound/direct_sound_samples/cries/rookidee.wav differ diff --git a/sound/direct_sound_samples/cries/roselia.aif b/sound/direct_sound_samples/cries/roselia.aif deleted file mode 100644 index c6c53f3c1f..0000000000 Binary files a/sound/direct_sound_samples/cries/roselia.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/roselia.wav b/sound/direct_sound_samples/cries/roselia.wav new file mode 100644 index 0000000000..cd01f19f68 Binary files /dev/null and b/sound/direct_sound_samples/cries/roselia.wav differ diff --git a/sound/direct_sound_samples/cries/roserade.aif b/sound/direct_sound_samples/cries/roserade.aif deleted file mode 100644 index 7c9de96a0e..0000000000 Binary files a/sound/direct_sound_samples/cries/roserade.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/roserade.wav b/sound/direct_sound_samples/cries/roserade.wav new file mode 100644 index 0000000000..25faa52091 Binary files /dev/null and b/sound/direct_sound_samples/cries/roserade.wav differ diff --git a/sound/direct_sound_samples/cries/rotom.aif b/sound/direct_sound_samples/cries/rotom.aif deleted file mode 100644 index 81080115c2..0000000000 Binary files a/sound/direct_sound_samples/cries/rotom.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/rotom.wav b/sound/direct_sound_samples/cries/rotom.wav new file mode 100644 index 0000000000..621aeeae99 Binary files /dev/null and b/sound/direct_sound_samples/cries/rotom.wav differ diff --git a/sound/direct_sound_samples/cries/rowlet.aif b/sound/direct_sound_samples/cries/rowlet.aif deleted file mode 100644 index c201336015..0000000000 Binary files a/sound/direct_sound_samples/cries/rowlet.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/rowlet.wav b/sound/direct_sound_samples/cries/rowlet.wav new file mode 100644 index 0000000000..82b82415ce Binary files /dev/null and b/sound/direct_sound_samples/cries/rowlet.wav differ diff --git a/sound/direct_sound_samples/cries/rufflet.aif b/sound/direct_sound_samples/cries/rufflet.aif deleted file mode 100644 index b7cc6cab12..0000000000 Binary files a/sound/direct_sound_samples/cries/rufflet.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/rufflet.wav b/sound/direct_sound_samples/cries/rufflet.wav new file mode 100644 index 0000000000..5b11300983 Binary files /dev/null and b/sound/direct_sound_samples/cries/rufflet.wav differ diff --git a/sound/direct_sound_samples/cries/runerigus.aif b/sound/direct_sound_samples/cries/runerigus.aif deleted file mode 100644 index c04d5003c4..0000000000 Binary files a/sound/direct_sound_samples/cries/runerigus.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/runerigus.wav b/sound/direct_sound_samples/cries/runerigus.wav new file mode 100644 index 0000000000..405d3d4644 Binary files /dev/null and b/sound/direct_sound_samples/cries/runerigus.wav differ diff --git a/sound/direct_sound_samples/cries/sableye.aif b/sound/direct_sound_samples/cries/sableye.aif deleted file mode 100644 index 885a3b0b35..0000000000 Binary files a/sound/direct_sound_samples/cries/sableye.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/sableye.wav b/sound/direct_sound_samples/cries/sableye.wav new file mode 100644 index 0000000000..9f32fbdd60 Binary files /dev/null and b/sound/direct_sound_samples/cries/sableye.wav differ diff --git a/sound/direct_sound_samples/cries/sableye_mega.aif b/sound/direct_sound_samples/cries/sableye_mega.aif deleted file mode 100644 index 7f869cd7b8..0000000000 Binary files a/sound/direct_sound_samples/cries/sableye_mega.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/sableye_mega.wav b/sound/direct_sound_samples/cries/sableye_mega.wav new file mode 100644 index 0000000000..6a5bb8f9bf Binary files /dev/null and b/sound/direct_sound_samples/cries/sableye_mega.wav differ diff --git a/sound/direct_sound_samples/cries/salamence.aif b/sound/direct_sound_samples/cries/salamence.aif deleted file mode 100644 index f733e098dd..0000000000 Binary files a/sound/direct_sound_samples/cries/salamence.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/salamence.wav b/sound/direct_sound_samples/cries/salamence.wav new file mode 100644 index 0000000000..1c426adfad Binary files /dev/null and b/sound/direct_sound_samples/cries/salamence.wav differ diff --git a/sound/direct_sound_samples/cries/salamence_mega.aif b/sound/direct_sound_samples/cries/salamence_mega.aif deleted file mode 100644 index 90ce0b6ff8..0000000000 Binary files a/sound/direct_sound_samples/cries/salamence_mega.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/salamence_mega.wav b/sound/direct_sound_samples/cries/salamence_mega.wav new file mode 100644 index 0000000000..dc0b96bc5e Binary files /dev/null and b/sound/direct_sound_samples/cries/salamence_mega.wav differ diff --git a/sound/direct_sound_samples/cries/salandit.aif b/sound/direct_sound_samples/cries/salandit.aif deleted file mode 100644 index 90de8f0573..0000000000 Binary files a/sound/direct_sound_samples/cries/salandit.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/salandit.wav b/sound/direct_sound_samples/cries/salandit.wav new file mode 100644 index 0000000000..631129c553 Binary files /dev/null and b/sound/direct_sound_samples/cries/salandit.wav differ diff --git a/sound/direct_sound_samples/cries/salazzle.aif b/sound/direct_sound_samples/cries/salazzle.aif deleted file mode 100644 index 7447bfc0bf..0000000000 Binary files a/sound/direct_sound_samples/cries/salazzle.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/salazzle.wav b/sound/direct_sound_samples/cries/salazzle.wav new file mode 100644 index 0000000000..0fbb0268f6 Binary files /dev/null and b/sound/direct_sound_samples/cries/salazzle.wav differ diff --git a/sound/direct_sound_samples/cries/samurott.aif b/sound/direct_sound_samples/cries/samurott.aif deleted file mode 100644 index fc8aa1c7c8..0000000000 Binary files a/sound/direct_sound_samples/cries/samurott.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/samurott.wav b/sound/direct_sound_samples/cries/samurott.wav new file mode 100644 index 0000000000..e8c54366fa Binary files /dev/null and b/sound/direct_sound_samples/cries/samurott.wav differ diff --git a/sound/direct_sound_samples/cries/sandaconda.aif b/sound/direct_sound_samples/cries/sandaconda.aif deleted file mode 100644 index 3fd1b08d96..0000000000 Binary files a/sound/direct_sound_samples/cries/sandaconda.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/sandaconda.wav b/sound/direct_sound_samples/cries/sandaconda.wav new file mode 100644 index 0000000000..24d92b705a Binary files /dev/null and b/sound/direct_sound_samples/cries/sandaconda.wav differ diff --git a/sound/direct_sound_samples/cries/sandile.aif b/sound/direct_sound_samples/cries/sandile.aif deleted file mode 100644 index 316b66aec9..0000000000 Binary files a/sound/direct_sound_samples/cries/sandile.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/sandile.wav b/sound/direct_sound_samples/cries/sandile.wav new file mode 100644 index 0000000000..e57af83a74 Binary files /dev/null and b/sound/direct_sound_samples/cries/sandile.wav differ diff --git a/sound/direct_sound_samples/cries/sandshrew.aif b/sound/direct_sound_samples/cries/sandshrew.aif deleted file mode 100644 index 02dd3c1182..0000000000 Binary files a/sound/direct_sound_samples/cries/sandshrew.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/sandshrew.wav b/sound/direct_sound_samples/cries/sandshrew.wav new file mode 100644 index 0000000000..8c324ed3d6 Binary files /dev/null and b/sound/direct_sound_samples/cries/sandshrew.wav differ diff --git a/sound/direct_sound_samples/cries/sandslash.aif b/sound/direct_sound_samples/cries/sandslash.aif deleted file mode 100644 index 59304e2dfe..0000000000 Binary files a/sound/direct_sound_samples/cries/sandslash.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/sandslash.wav b/sound/direct_sound_samples/cries/sandslash.wav new file mode 100644 index 0000000000..95bcdb8698 Binary files /dev/null and b/sound/direct_sound_samples/cries/sandslash.wav differ diff --git a/sound/direct_sound_samples/cries/sandy_shocks.aif b/sound/direct_sound_samples/cries/sandy_shocks.aif deleted file mode 100644 index d26cfc8817..0000000000 Binary files a/sound/direct_sound_samples/cries/sandy_shocks.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/sandy_shocks.wav b/sound/direct_sound_samples/cries/sandy_shocks.wav new file mode 100644 index 0000000000..694ffe888f Binary files /dev/null and b/sound/direct_sound_samples/cries/sandy_shocks.wav differ diff --git a/sound/direct_sound_samples/cries/sandygast.aif b/sound/direct_sound_samples/cries/sandygast.aif deleted file mode 100644 index b99472bbaf..0000000000 Binary files a/sound/direct_sound_samples/cries/sandygast.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/sandygast.wav b/sound/direct_sound_samples/cries/sandygast.wav new file mode 100644 index 0000000000..88997b8ed5 Binary files /dev/null and b/sound/direct_sound_samples/cries/sandygast.wav differ diff --git a/sound/direct_sound_samples/cries/sawk.aif b/sound/direct_sound_samples/cries/sawk.aif deleted file mode 100644 index c040994edc..0000000000 Binary files a/sound/direct_sound_samples/cries/sawk.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/sawk.wav b/sound/direct_sound_samples/cries/sawk.wav new file mode 100644 index 0000000000..b8ea999444 Binary files /dev/null and b/sound/direct_sound_samples/cries/sawk.wav differ diff --git a/sound/direct_sound_samples/cries/sawsbuck.aif b/sound/direct_sound_samples/cries/sawsbuck.aif deleted file mode 100644 index 9dcc4f927c..0000000000 Binary files a/sound/direct_sound_samples/cries/sawsbuck.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/sawsbuck.wav b/sound/direct_sound_samples/cries/sawsbuck.wav new file mode 100644 index 0000000000..562bc74a4f Binary files /dev/null and b/sound/direct_sound_samples/cries/sawsbuck.wav differ diff --git a/sound/direct_sound_samples/cries/scatterbug.aif b/sound/direct_sound_samples/cries/scatterbug.aif deleted file mode 100644 index c553fb4771..0000000000 Binary files a/sound/direct_sound_samples/cries/scatterbug.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/scatterbug.wav b/sound/direct_sound_samples/cries/scatterbug.wav new file mode 100644 index 0000000000..8afef83e92 Binary files /dev/null and b/sound/direct_sound_samples/cries/scatterbug.wav differ diff --git a/sound/direct_sound_samples/cries/sceptile.aif b/sound/direct_sound_samples/cries/sceptile.aif deleted file mode 100644 index c460e445d5..0000000000 Binary files a/sound/direct_sound_samples/cries/sceptile.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/sceptile.wav b/sound/direct_sound_samples/cries/sceptile.wav new file mode 100644 index 0000000000..32673bc773 Binary files /dev/null and b/sound/direct_sound_samples/cries/sceptile.wav differ diff --git a/sound/direct_sound_samples/cries/sceptile_mega.aif b/sound/direct_sound_samples/cries/sceptile_mega.aif deleted file mode 100644 index 50a16a1ee3..0000000000 Binary files a/sound/direct_sound_samples/cries/sceptile_mega.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/sceptile_mega.wav b/sound/direct_sound_samples/cries/sceptile_mega.wav new file mode 100644 index 0000000000..228b21d4ed Binary files /dev/null and b/sound/direct_sound_samples/cries/sceptile_mega.wav differ diff --git a/sound/direct_sound_samples/cries/scizor.aif b/sound/direct_sound_samples/cries/scizor.aif deleted file mode 100644 index eb423f61dd..0000000000 Binary files a/sound/direct_sound_samples/cries/scizor.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/scizor.wav b/sound/direct_sound_samples/cries/scizor.wav new file mode 100644 index 0000000000..8196df16b2 Binary files /dev/null and b/sound/direct_sound_samples/cries/scizor.wav differ diff --git a/sound/direct_sound_samples/cries/scizor_mega.aif b/sound/direct_sound_samples/cries/scizor_mega.aif deleted file mode 100644 index c970f8083b..0000000000 Binary files a/sound/direct_sound_samples/cries/scizor_mega.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/scizor_mega.wav b/sound/direct_sound_samples/cries/scizor_mega.wav new file mode 100644 index 0000000000..010cb05e66 Binary files /dev/null and b/sound/direct_sound_samples/cries/scizor_mega.wav differ diff --git a/sound/direct_sound_samples/cries/scolipede.aif b/sound/direct_sound_samples/cries/scolipede.aif deleted file mode 100644 index 0372641b70..0000000000 Binary files a/sound/direct_sound_samples/cries/scolipede.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/scolipede.wav b/sound/direct_sound_samples/cries/scolipede.wav new file mode 100644 index 0000000000..1b493ce18d Binary files /dev/null and b/sound/direct_sound_samples/cries/scolipede.wav differ diff --git a/sound/direct_sound_samples/cries/scorbunny.aif b/sound/direct_sound_samples/cries/scorbunny.aif deleted file mode 100644 index c0963bbc1c..0000000000 Binary files a/sound/direct_sound_samples/cries/scorbunny.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/scorbunny.wav b/sound/direct_sound_samples/cries/scorbunny.wav new file mode 100644 index 0000000000..dd9e54c722 Binary files /dev/null and b/sound/direct_sound_samples/cries/scorbunny.wav differ diff --git a/sound/direct_sound_samples/cries/scovillain.aif b/sound/direct_sound_samples/cries/scovillain.aif deleted file mode 100644 index d84cb24087..0000000000 Binary files a/sound/direct_sound_samples/cries/scovillain.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/scovillain.wav b/sound/direct_sound_samples/cries/scovillain.wav new file mode 100644 index 0000000000..a7d8f058e8 Binary files /dev/null and b/sound/direct_sound_samples/cries/scovillain.wav differ diff --git a/sound/direct_sound_samples/cries/scrafty.aif b/sound/direct_sound_samples/cries/scrafty.aif deleted file mode 100644 index bc351aa3de..0000000000 Binary files a/sound/direct_sound_samples/cries/scrafty.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/scrafty.wav b/sound/direct_sound_samples/cries/scrafty.wav new file mode 100644 index 0000000000..e64613dfb8 Binary files /dev/null and b/sound/direct_sound_samples/cries/scrafty.wav differ diff --git a/sound/direct_sound_samples/cries/scraggy.aif b/sound/direct_sound_samples/cries/scraggy.aif deleted file mode 100644 index bd836ebc46..0000000000 Binary files a/sound/direct_sound_samples/cries/scraggy.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/scraggy.wav b/sound/direct_sound_samples/cries/scraggy.wav new file mode 100644 index 0000000000..e5c014a432 Binary files /dev/null and b/sound/direct_sound_samples/cries/scraggy.wav differ diff --git a/sound/direct_sound_samples/cries/scream_tail.aif b/sound/direct_sound_samples/cries/scream_tail.aif deleted file mode 100644 index a64bbdb051..0000000000 Binary files a/sound/direct_sound_samples/cries/scream_tail.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/scream_tail.wav b/sound/direct_sound_samples/cries/scream_tail.wav new file mode 100644 index 0000000000..c7f133809d Binary files /dev/null and b/sound/direct_sound_samples/cries/scream_tail.wav differ diff --git a/sound/direct_sound_samples/cries/scyther.aif b/sound/direct_sound_samples/cries/scyther.aif deleted file mode 100644 index 88bc85cdbb..0000000000 Binary files a/sound/direct_sound_samples/cries/scyther.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/scyther.wav b/sound/direct_sound_samples/cries/scyther.wav new file mode 100644 index 0000000000..5b6ba415a1 Binary files /dev/null and b/sound/direct_sound_samples/cries/scyther.wav differ diff --git a/sound/direct_sound_samples/cries/seadra.aif b/sound/direct_sound_samples/cries/seadra.aif deleted file mode 100644 index 19852ad231..0000000000 Binary files a/sound/direct_sound_samples/cries/seadra.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/seadra.wav b/sound/direct_sound_samples/cries/seadra.wav new file mode 100644 index 0000000000..c68a68a196 Binary files /dev/null and b/sound/direct_sound_samples/cries/seadra.wav differ diff --git a/sound/direct_sound_samples/cries/seaking.aif b/sound/direct_sound_samples/cries/seaking.aif deleted file mode 100644 index f572ce5dd4..0000000000 Binary files a/sound/direct_sound_samples/cries/seaking.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/seaking.wav b/sound/direct_sound_samples/cries/seaking.wav new file mode 100644 index 0000000000..6f2533e946 Binary files /dev/null and b/sound/direct_sound_samples/cries/seaking.wav differ diff --git a/sound/direct_sound_samples/cries/sealeo.aif b/sound/direct_sound_samples/cries/sealeo.aif deleted file mode 100644 index 9a0aedda62..0000000000 Binary files a/sound/direct_sound_samples/cries/sealeo.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/sealeo.wav b/sound/direct_sound_samples/cries/sealeo.wav new file mode 100644 index 0000000000..ad01a5fed3 Binary files /dev/null and b/sound/direct_sound_samples/cries/sealeo.wav differ diff --git a/sound/direct_sound_samples/cries/seedot.aif b/sound/direct_sound_samples/cries/seedot.aif deleted file mode 100644 index eac082184f..0000000000 Binary files a/sound/direct_sound_samples/cries/seedot.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/seedot.wav b/sound/direct_sound_samples/cries/seedot.wav new file mode 100644 index 0000000000..b4d74f65d6 Binary files /dev/null and b/sound/direct_sound_samples/cries/seedot.wav differ diff --git a/sound/direct_sound_samples/cries/seel.aif b/sound/direct_sound_samples/cries/seel.aif deleted file mode 100644 index 1cc31998f2..0000000000 Binary files a/sound/direct_sound_samples/cries/seel.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/seel.wav b/sound/direct_sound_samples/cries/seel.wav new file mode 100644 index 0000000000..6e252b375a Binary files /dev/null and b/sound/direct_sound_samples/cries/seel.wav differ diff --git a/sound/direct_sound_samples/cries/seismitoad.aif b/sound/direct_sound_samples/cries/seismitoad.aif deleted file mode 100644 index 521f9b741b..0000000000 Binary files a/sound/direct_sound_samples/cries/seismitoad.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/seismitoad.wav b/sound/direct_sound_samples/cries/seismitoad.wav new file mode 100644 index 0000000000..ad833ea8e0 Binary files /dev/null and b/sound/direct_sound_samples/cries/seismitoad.wav differ diff --git a/sound/direct_sound_samples/cries/sentret.aif b/sound/direct_sound_samples/cries/sentret.aif deleted file mode 100644 index ffbce9c7c5..0000000000 Binary files a/sound/direct_sound_samples/cries/sentret.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/sentret.wav b/sound/direct_sound_samples/cries/sentret.wav new file mode 100644 index 0000000000..0c6746c456 Binary files /dev/null and b/sound/direct_sound_samples/cries/sentret.wav differ diff --git a/sound/direct_sound_samples/cries/serperior.aif b/sound/direct_sound_samples/cries/serperior.aif deleted file mode 100644 index 9a2eb0baad..0000000000 Binary files a/sound/direct_sound_samples/cries/serperior.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/serperior.wav b/sound/direct_sound_samples/cries/serperior.wav new file mode 100644 index 0000000000..427443c56f Binary files /dev/null and b/sound/direct_sound_samples/cries/serperior.wav differ diff --git a/sound/direct_sound_samples/cries/servine.aif b/sound/direct_sound_samples/cries/servine.aif deleted file mode 100644 index 7098f526d9..0000000000 Binary files a/sound/direct_sound_samples/cries/servine.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/servine.wav b/sound/direct_sound_samples/cries/servine.wav new file mode 100644 index 0000000000..61da20ea83 Binary files /dev/null and b/sound/direct_sound_samples/cries/servine.wav differ diff --git a/sound/direct_sound_samples/cries/seviper.aif b/sound/direct_sound_samples/cries/seviper.aif deleted file mode 100644 index 5e3968db6d..0000000000 Binary files a/sound/direct_sound_samples/cries/seviper.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/seviper.wav b/sound/direct_sound_samples/cries/seviper.wav new file mode 100644 index 0000000000..b467378f4c Binary files /dev/null and b/sound/direct_sound_samples/cries/seviper.wav differ diff --git a/sound/direct_sound_samples/cries/sewaddle.aif b/sound/direct_sound_samples/cries/sewaddle.aif deleted file mode 100644 index 9a3ac12721..0000000000 Binary files a/sound/direct_sound_samples/cries/sewaddle.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/sewaddle.wav b/sound/direct_sound_samples/cries/sewaddle.wav new file mode 100644 index 0000000000..9751d50cf1 Binary files /dev/null and b/sound/direct_sound_samples/cries/sewaddle.wav differ diff --git a/sound/direct_sound_samples/cries/sharpedo.aif b/sound/direct_sound_samples/cries/sharpedo.aif deleted file mode 100644 index b68c24bb81..0000000000 Binary files a/sound/direct_sound_samples/cries/sharpedo.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/sharpedo.wav b/sound/direct_sound_samples/cries/sharpedo.wav new file mode 100644 index 0000000000..26c52b43c3 Binary files /dev/null and b/sound/direct_sound_samples/cries/sharpedo.wav differ diff --git a/sound/direct_sound_samples/cries/sharpedo_mega.aif b/sound/direct_sound_samples/cries/sharpedo_mega.aif deleted file mode 100644 index 3fa5b49e92..0000000000 Binary files a/sound/direct_sound_samples/cries/sharpedo_mega.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/sharpedo_mega.wav b/sound/direct_sound_samples/cries/sharpedo_mega.wav new file mode 100644 index 0000000000..232b0c5241 Binary files /dev/null and b/sound/direct_sound_samples/cries/sharpedo_mega.wav differ diff --git a/sound/direct_sound_samples/cries/shaymin_land.aif b/sound/direct_sound_samples/cries/shaymin_land.aif deleted file mode 100644 index ab0c40f156..0000000000 Binary files a/sound/direct_sound_samples/cries/shaymin_land.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/shaymin_land.wav b/sound/direct_sound_samples/cries/shaymin_land.wav new file mode 100644 index 0000000000..9665e3b2ac Binary files /dev/null and b/sound/direct_sound_samples/cries/shaymin_land.wav differ diff --git a/sound/direct_sound_samples/cries/shaymin_sky.aif b/sound/direct_sound_samples/cries/shaymin_sky.aif deleted file mode 100644 index ee3dfa8457..0000000000 Binary files a/sound/direct_sound_samples/cries/shaymin_sky.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/shaymin_sky.wav b/sound/direct_sound_samples/cries/shaymin_sky.wav new file mode 100644 index 0000000000..54f116f4b5 Binary files /dev/null and b/sound/direct_sound_samples/cries/shaymin_sky.wav differ diff --git a/sound/direct_sound_samples/cries/shedinja.aif b/sound/direct_sound_samples/cries/shedinja.aif deleted file mode 100644 index d891bd382c..0000000000 Binary files a/sound/direct_sound_samples/cries/shedinja.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/shedinja.wav b/sound/direct_sound_samples/cries/shedinja.wav new file mode 100644 index 0000000000..956ae0be9f Binary files /dev/null and b/sound/direct_sound_samples/cries/shedinja.wav differ diff --git a/sound/direct_sound_samples/cries/shelgon.aif b/sound/direct_sound_samples/cries/shelgon.aif deleted file mode 100644 index b202dc0376..0000000000 Binary files a/sound/direct_sound_samples/cries/shelgon.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/shelgon.wav b/sound/direct_sound_samples/cries/shelgon.wav new file mode 100644 index 0000000000..7648d06f9a Binary files /dev/null and b/sound/direct_sound_samples/cries/shelgon.wav differ diff --git a/sound/direct_sound_samples/cries/shellder.aif b/sound/direct_sound_samples/cries/shellder.aif deleted file mode 100644 index 3f2df4a82c..0000000000 Binary files a/sound/direct_sound_samples/cries/shellder.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/shellder.wav b/sound/direct_sound_samples/cries/shellder.wav new file mode 100644 index 0000000000..1fe4367d78 Binary files /dev/null and b/sound/direct_sound_samples/cries/shellder.wav differ diff --git a/sound/direct_sound_samples/cries/shellos.aif b/sound/direct_sound_samples/cries/shellos.aif deleted file mode 100644 index f590731202..0000000000 Binary files a/sound/direct_sound_samples/cries/shellos.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/shellos.wav b/sound/direct_sound_samples/cries/shellos.wav new file mode 100644 index 0000000000..99e9254347 Binary files /dev/null and b/sound/direct_sound_samples/cries/shellos.wav differ diff --git a/sound/direct_sound_samples/cries/shelmet.aif b/sound/direct_sound_samples/cries/shelmet.aif deleted file mode 100644 index 472b6658c0..0000000000 Binary files a/sound/direct_sound_samples/cries/shelmet.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/shelmet.wav b/sound/direct_sound_samples/cries/shelmet.wav new file mode 100644 index 0000000000..3cb2bcecc6 Binary files /dev/null and b/sound/direct_sound_samples/cries/shelmet.wav differ diff --git a/sound/direct_sound_samples/cries/shieldon.aif b/sound/direct_sound_samples/cries/shieldon.aif deleted file mode 100644 index 5ea98bf174..0000000000 Binary files a/sound/direct_sound_samples/cries/shieldon.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/shieldon.wav b/sound/direct_sound_samples/cries/shieldon.wav new file mode 100644 index 0000000000..dc7c1c5a3b Binary files /dev/null and b/sound/direct_sound_samples/cries/shieldon.wav differ diff --git a/sound/direct_sound_samples/cries/shiftry.aif b/sound/direct_sound_samples/cries/shiftry.aif deleted file mode 100644 index dbc65b749e..0000000000 Binary files a/sound/direct_sound_samples/cries/shiftry.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/shiftry.wav b/sound/direct_sound_samples/cries/shiftry.wav new file mode 100644 index 0000000000..533115f404 Binary files /dev/null and b/sound/direct_sound_samples/cries/shiftry.wav differ diff --git a/sound/direct_sound_samples/cries/shiinotic.aif b/sound/direct_sound_samples/cries/shiinotic.aif deleted file mode 100644 index 972aef0769..0000000000 Binary files a/sound/direct_sound_samples/cries/shiinotic.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/shiinotic.wav b/sound/direct_sound_samples/cries/shiinotic.wav new file mode 100644 index 0000000000..32ce942636 Binary files /dev/null and b/sound/direct_sound_samples/cries/shiinotic.wav differ diff --git a/sound/direct_sound_samples/cries/shinx.aif b/sound/direct_sound_samples/cries/shinx.aif deleted file mode 100644 index 08f7ad8a4c..0000000000 Binary files a/sound/direct_sound_samples/cries/shinx.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/shinx.wav b/sound/direct_sound_samples/cries/shinx.wav new file mode 100644 index 0000000000..2f62c5d966 Binary files /dev/null and b/sound/direct_sound_samples/cries/shinx.wav differ diff --git a/sound/direct_sound_samples/cries/shroodle.aif b/sound/direct_sound_samples/cries/shroodle.aif deleted file mode 100644 index b60ef3ade3..0000000000 Binary files a/sound/direct_sound_samples/cries/shroodle.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/shroodle.wav b/sound/direct_sound_samples/cries/shroodle.wav new file mode 100644 index 0000000000..0166fa68ca Binary files /dev/null and b/sound/direct_sound_samples/cries/shroodle.wav differ diff --git a/sound/direct_sound_samples/cries/shroomish.aif b/sound/direct_sound_samples/cries/shroomish.aif deleted file mode 100644 index 9c092ae072..0000000000 Binary files a/sound/direct_sound_samples/cries/shroomish.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/shroomish.wav b/sound/direct_sound_samples/cries/shroomish.wav new file mode 100644 index 0000000000..07658c8801 Binary files /dev/null and b/sound/direct_sound_samples/cries/shroomish.wav differ diff --git a/sound/direct_sound_samples/cries/shuckle.aif b/sound/direct_sound_samples/cries/shuckle.aif deleted file mode 100644 index a5523506b5..0000000000 Binary files a/sound/direct_sound_samples/cries/shuckle.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/shuckle.wav b/sound/direct_sound_samples/cries/shuckle.wav new file mode 100644 index 0000000000..bb196dbfe9 Binary files /dev/null and b/sound/direct_sound_samples/cries/shuckle.wav differ diff --git a/sound/direct_sound_samples/cries/shuppet.aif b/sound/direct_sound_samples/cries/shuppet.aif deleted file mode 100644 index 8f48e8b5fd..0000000000 Binary files a/sound/direct_sound_samples/cries/shuppet.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/shuppet.wav b/sound/direct_sound_samples/cries/shuppet.wav new file mode 100644 index 0000000000..6b043a2772 Binary files /dev/null and b/sound/direct_sound_samples/cries/shuppet.wav differ diff --git a/sound/direct_sound_samples/cries/sigilyph.aif b/sound/direct_sound_samples/cries/sigilyph.aif deleted file mode 100644 index cf84e7dcf9..0000000000 Binary files a/sound/direct_sound_samples/cries/sigilyph.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/sigilyph.wav b/sound/direct_sound_samples/cries/sigilyph.wav new file mode 100644 index 0000000000..5d43af49f5 Binary files /dev/null and b/sound/direct_sound_samples/cries/sigilyph.wav differ diff --git a/sound/direct_sound_samples/cries/silcoon.aif b/sound/direct_sound_samples/cries/silcoon.aif deleted file mode 100644 index 89cd186676..0000000000 Binary files a/sound/direct_sound_samples/cries/silcoon.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/silcoon.wav b/sound/direct_sound_samples/cries/silcoon.wav new file mode 100644 index 0000000000..15827329e4 Binary files /dev/null and b/sound/direct_sound_samples/cries/silcoon.wav differ diff --git a/sound/direct_sound_samples/cries/silicobra.aif b/sound/direct_sound_samples/cries/silicobra.aif deleted file mode 100644 index 3b9f5e13fc..0000000000 Binary files a/sound/direct_sound_samples/cries/silicobra.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/silicobra.wav b/sound/direct_sound_samples/cries/silicobra.wav new file mode 100644 index 0000000000..92392561ef Binary files /dev/null and b/sound/direct_sound_samples/cries/silicobra.wav differ diff --git a/sound/direct_sound_samples/cries/silvally.aif b/sound/direct_sound_samples/cries/silvally.aif deleted file mode 100644 index 48856c7d16..0000000000 Binary files a/sound/direct_sound_samples/cries/silvally.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/silvally.wav b/sound/direct_sound_samples/cries/silvally.wav new file mode 100644 index 0000000000..833dbb9286 Binary files /dev/null and b/sound/direct_sound_samples/cries/silvally.wav differ diff --git a/sound/direct_sound_samples/cries/simipour.aif b/sound/direct_sound_samples/cries/simipour.aif deleted file mode 100644 index 91e891b63f..0000000000 Binary files a/sound/direct_sound_samples/cries/simipour.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/simipour.wav b/sound/direct_sound_samples/cries/simipour.wav new file mode 100644 index 0000000000..f5507327b0 Binary files /dev/null and b/sound/direct_sound_samples/cries/simipour.wav differ diff --git a/sound/direct_sound_samples/cries/simisage.aif b/sound/direct_sound_samples/cries/simisage.aif deleted file mode 100644 index 944f5ff831..0000000000 Binary files a/sound/direct_sound_samples/cries/simisage.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/simisage.wav b/sound/direct_sound_samples/cries/simisage.wav new file mode 100644 index 0000000000..91bcf71d9d Binary files /dev/null and b/sound/direct_sound_samples/cries/simisage.wav differ diff --git a/sound/direct_sound_samples/cries/simisear.aif b/sound/direct_sound_samples/cries/simisear.aif deleted file mode 100644 index e3e8eb860a..0000000000 Binary files a/sound/direct_sound_samples/cries/simisear.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/simisear.wav b/sound/direct_sound_samples/cries/simisear.wav new file mode 100644 index 0000000000..737b37ba78 Binary files /dev/null and b/sound/direct_sound_samples/cries/simisear.wav differ diff --git a/sound/direct_sound_samples/cries/sinistcha.aif b/sound/direct_sound_samples/cries/sinistcha.aif deleted file mode 100644 index e9a619c3f0..0000000000 Binary files a/sound/direct_sound_samples/cries/sinistcha.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/sinistcha.wav b/sound/direct_sound_samples/cries/sinistcha.wav new file mode 100644 index 0000000000..f3cb98dd7b Binary files /dev/null and b/sound/direct_sound_samples/cries/sinistcha.wav differ diff --git a/sound/direct_sound_samples/cries/sinistea.aif b/sound/direct_sound_samples/cries/sinistea.aif deleted file mode 100644 index 912a0800f9..0000000000 Binary files a/sound/direct_sound_samples/cries/sinistea.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/sinistea.wav b/sound/direct_sound_samples/cries/sinistea.wav new file mode 100644 index 0000000000..b91d77cae2 Binary files /dev/null and b/sound/direct_sound_samples/cries/sinistea.wav differ diff --git a/sound/direct_sound_samples/cries/sirfetchd.aif b/sound/direct_sound_samples/cries/sirfetchd.aif deleted file mode 100644 index a5ca065a75..0000000000 Binary files a/sound/direct_sound_samples/cries/sirfetchd.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/sirfetchd.wav b/sound/direct_sound_samples/cries/sirfetchd.wav new file mode 100644 index 0000000000..cfa590d2ca Binary files /dev/null and b/sound/direct_sound_samples/cries/sirfetchd.wav differ diff --git a/sound/direct_sound_samples/cries/sizzlipede.aif b/sound/direct_sound_samples/cries/sizzlipede.aif deleted file mode 100644 index 99aade0666..0000000000 Binary files a/sound/direct_sound_samples/cries/sizzlipede.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/sizzlipede.wav b/sound/direct_sound_samples/cries/sizzlipede.wav new file mode 100644 index 0000000000..d2ee4859fc Binary files /dev/null and b/sound/direct_sound_samples/cries/sizzlipede.wav differ diff --git a/sound/direct_sound_samples/cries/skarmory.aif b/sound/direct_sound_samples/cries/skarmory.aif deleted file mode 100644 index 5641486234..0000000000 Binary files a/sound/direct_sound_samples/cries/skarmory.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/skarmory.wav b/sound/direct_sound_samples/cries/skarmory.wav new file mode 100644 index 0000000000..2924973023 Binary files /dev/null and b/sound/direct_sound_samples/cries/skarmory.wav differ diff --git a/sound/direct_sound_samples/cries/skeledirge.aif b/sound/direct_sound_samples/cries/skeledirge.aif deleted file mode 100644 index 720e102019..0000000000 Binary files a/sound/direct_sound_samples/cries/skeledirge.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/skeledirge.wav b/sound/direct_sound_samples/cries/skeledirge.wav new file mode 100644 index 0000000000..284cd7f5fd Binary files /dev/null and b/sound/direct_sound_samples/cries/skeledirge.wav differ diff --git a/sound/direct_sound_samples/cries/skiddo.aif b/sound/direct_sound_samples/cries/skiddo.aif deleted file mode 100644 index 5b2dc104f7..0000000000 Binary files a/sound/direct_sound_samples/cries/skiddo.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/skiddo.wav b/sound/direct_sound_samples/cries/skiddo.wav new file mode 100644 index 0000000000..ce3e1e35ef Binary files /dev/null and b/sound/direct_sound_samples/cries/skiddo.wav differ diff --git a/sound/direct_sound_samples/cries/skiploom.aif b/sound/direct_sound_samples/cries/skiploom.aif deleted file mode 100644 index 4517e39c7a..0000000000 Binary files a/sound/direct_sound_samples/cries/skiploom.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/skiploom.wav b/sound/direct_sound_samples/cries/skiploom.wav new file mode 100644 index 0000000000..30f9c26662 Binary files /dev/null and b/sound/direct_sound_samples/cries/skiploom.wav differ diff --git a/sound/direct_sound_samples/cries/skitty.aif b/sound/direct_sound_samples/cries/skitty.aif deleted file mode 100644 index 0f903b5377..0000000000 Binary files a/sound/direct_sound_samples/cries/skitty.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/skitty.wav b/sound/direct_sound_samples/cries/skitty.wav new file mode 100644 index 0000000000..02aaa4fcbd Binary files /dev/null and b/sound/direct_sound_samples/cries/skitty.wav differ diff --git a/sound/direct_sound_samples/cries/skorupi.aif b/sound/direct_sound_samples/cries/skorupi.aif deleted file mode 100644 index a638cb4645..0000000000 Binary files a/sound/direct_sound_samples/cries/skorupi.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/skorupi.wav b/sound/direct_sound_samples/cries/skorupi.wav new file mode 100644 index 0000000000..ae1317e264 Binary files /dev/null and b/sound/direct_sound_samples/cries/skorupi.wav differ diff --git a/sound/direct_sound_samples/cries/skrelp.aif b/sound/direct_sound_samples/cries/skrelp.aif deleted file mode 100644 index 12bb27c043..0000000000 Binary files a/sound/direct_sound_samples/cries/skrelp.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/skrelp.wav b/sound/direct_sound_samples/cries/skrelp.wav new file mode 100644 index 0000000000..4bbecd7a62 Binary files /dev/null and b/sound/direct_sound_samples/cries/skrelp.wav differ diff --git a/sound/direct_sound_samples/cries/skuntank.aif b/sound/direct_sound_samples/cries/skuntank.aif deleted file mode 100644 index 354f2af92c..0000000000 Binary files a/sound/direct_sound_samples/cries/skuntank.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/skuntank.wav b/sound/direct_sound_samples/cries/skuntank.wav new file mode 100644 index 0000000000..315c8a41cf Binary files /dev/null and b/sound/direct_sound_samples/cries/skuntank.wav differ diff --git a/sound/direct_sound_samples/cries/skwovet.aif b/sound/direct_sound_samples/cries/skwovet.aif deleted file mode 100644 index b5a27241d5..0000000000 Binary files a/sound/direct_sound_samples/cries/skwovet.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/skwovet.wav b/sound/direct_sound_samples/cries/skwovet.wav new file mode 100644 index 0000000000..7765154b91 Binary files /dev/null and b/sound/direct_sound_samples/cries/skwovet.wav differ diff --git a/sound/direct_sound_samples/cries/slaking.aif b/sound/direct_sound_samples/cries/slaking.aif deleted file mode 100644 index d023af7681..0000000000 Binary files a/sound/direct_sound_samples/cries/slaking.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/slaking.wav b/sound/direct_sound_samples/cries/slaking.wav new file mode 100644 index 0000000000..ef34d94d69 Binary files /dev/null and b/sound/direct_sound_samples/cries/slaking.wav differ diff --git a/sound/direct_sound_samples/cries/slakoth.aif b/sound/direct_sound_samples/cries/slakoth.aif deleted file mode 100644 index 54248b2d85..0000000000 Binary files a/sound/direct_sound_samples/cries/slakoth.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/slakoth.wav b/sound/direct_sound_samples/cries/slakoth.wav new file mode 100644 index 0000000000..d4588b3a21 Binary files /dev/null and b/sound/direct_sound_samples/cries/slakoth.wav differ diff --git a/sound/direct_sound_samples/cries/sliggoo.aif b/sound/direct_sound_samples/cries/sliggoo.aif deleted file mode 100644 index ed141e69c5..0000000000 Binary files a/sound/direct_sound_samples/cries/sliggoo.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/sliggoo.wav b/sound/direct_sound_samples/cries/sliggoo.wav new file mode 100644 index 0000000000..c988d4244a Binary files /dev/null and b/sound/direct_sound_samples/cries/sliggoo.wav differ diff --git a/sound/direct_sound_samples/cries/slither_wing.aif b/sound/direct_sound_samples/cries/slither_wing.aif deleted file mode 100644 index 699f74f2f9..0000000000 Binary files a/sound/direct_sound_samples/cries/slither_wing.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/slither_wing.wav b/sound/direct_sound_samples/cries/slither_wing.wav new file mode 100644 index 0000000000..35baf10669 Binary files /dev/null and b/sound/direct_sound_samples/cries/slither_wing.wav differ diff --git a/sound/direct_sound_samples/cries/slowbro.aif b/sound/direct_sound_samples/cries/slowbro.aif deleted file mode 100644 index c3778734e3..0000000000 Binary files a/sound/direct_sound_samples/cries/slowbro.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/slowbro.wav b/sound/direct_sound_samples/cries/slowbro.wav new file mode 100644 index 0000000000..fe03ab4cdd Binary files /dev/null and b/sound/direct_sound_samples/cries/slowbro.wav differ diff --git a/sound/direct_sound_samples/cries/slowbro_mega.aif b/sound/direct_sound_samples/cries/slowbro_mega.aif deleted file mode 100644 index 6ae2a0fb68..0000000000 Binary files a/sound/direct_sound_samples/cries/slowbro_mega.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/slowbro_mega.wav b/sound/direct_sound_samples/cries/slowbro_mega.wav new file mode 100644 index 0000000000..4dee27f96e Binary files /dev/null and b/sound/direct_sound_samples/cries/slowbro_mega.wav differ diff --git a/sound/direct_sound_samples/cries/slowking.aif b/sound/direct_sound_samples/cries/slowking.aif deleted file mode 100644 index e135c9e0db..0000000000 Binary files a/sound/direct_sound_samples/cries/slowking.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/slowking.wav b/sound/direct_sound_samples/cries/slowking.wav new file mode 100644 index 0000000000..f802796282 Binary files /dev/null and b/sound/direct_sound_samples/cries/slowking.wav differ diff --git a/sound/direct_sound_samples/cries/slowpoke.aif b/sound/direct_sound_samples/cries/slowpoke.aif deleted file mode 100644 index e92ed0c208..0000000000 Binary files a/sound/direct_sound_samples/cries/slowpoke.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/slowpoke.wav b/sound/direct_sound_samples/cries/slowpoke.wav new file mode 100644 index 0000000000..b3a45bef0a Binary files /dev/null and b/sound/direct_sound_samples/cries/slowpoke.wav differ diff --git a/sound/direct_sound_samples/cries/slowpoke_galar.aif b/sound/direct_sound_samples/cries/slowpoke_galar.aif deleted file mode 100644 index 30251a2e8c..0000000000 Binary files a/sound/direct_sound_samples/cries/slowpoke_galar.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/slowpoke_galar.wav b/sound/direct_sound_samples/cries/slowpoke_galar.wav new file mode 100644 index 0000000000..8e72b6d83e Binary files /dev/null and b/sound/direct_sound_samples/cries/slowpoke_galar.wav differ diff --git a/sound/direct_sound_samples/cries/slugma.aif b/sound/direct_sound_samples/cries/slugma.aif deleted file mode 100644 index 3526b7f6e7..0000000000 Binary files a/sound/direct_sound_samples/cries/slugma.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/slugma.wav b/sound/direct_sound_samples/cries/slugma.wav new file mode 100644 index 0000000000..389bc88657 Binary files /dev/null and b/sound/direct_sound_samples/cries/slugma.wav differ diff --git a/sound/direct_sound_samples/cries/slurpuff.aif b/sound/direct_sound_samples/cries/slurpuff.aif deleted file mode 100644 index 93b59e8e35..0000000000 Binary files a/sound/direct_sound_samples/cries/slurpuff.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/slurpuff.wav b/sound/direct_sound_samples/cries/slurpuff.wav new file mode 100644 index 0000000000..e7f4be9876 Binary files /dev/null and b/sound/direct_sound_samples/cries/slurpuff.wav differ diff --git a/sound/direct_sound_samples/cries/smeargle.aif b/sound/direct_sound_samples/cries/smeargle.aif deleted file mode 100644 index 76cc479ccc..0000000000 Binary files a/sound/direct_sound_samples/cries/smeargle.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/smeargle.wav b/sound/direct_sound_samples/cries/smeargle.wav new file mode 100644 index 0000000000..e206f8f61b Binary files /dev/null and b/sound/direct_sound_samples/cries/smeargle.wav differ diff --git a/sound/direct_sound_samples/cries/smoliv.aif b/sound/direct_sound_samples/cries/smoliv.aif deleted file mode 100644 index 44b688aff9..0000000000 Binary files a/sound/direct_sound_samples/cries/smoliv.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/smoliv.wav b/sound/direct_sound_samples/cries/smoliv.wav new file mode 100644 index 0000000000..9662fc1e52 Binary files /dev/null and b/sound/direct_sound_samples/cries/smoliv.wav differ diff --git a/sound/direct_sound_samples/cries/smoochum.aif b/sound/direct_sound_samples/cries/smoochum.aif deleted file mode 100644 index 812586940c..0000000000 Binary files a/sound/direct_sound_samples/cries/smoochum.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/smoochum.wav b/sound/direct_sound_samples/cries/smoochum.wav new file mode 100644 index 0000000000..a4abdde7ec Binary files /dev/null and b/sound/direct_sound_samples/cries/smoochum.wav differ diff --git a/sound/direct_sound_samples/cries/sneasel.aif b/sound/direct_sound_samples/cries/sneasel.aif deleted file mode 100644 index e4bf7129c4..0000000000 Binary files a/sound/direct_sound_samples/cries/sneasel.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/sneasel.wav b/sound/direct_sound_samples/cries/sneasel.wav new file mode 100644 index 0000000000..da76aefb71 Binary files /dev/null and b/sound/direct_sound_samples/cries/sneasel.wav differ diff --git a/sound/direct_sound_samples/cries/sneasler.aif b/sound/direct_sound_samples/cries/sneasler.aif deleted file mode 100644 index b8537fef07..0000000000 Binary files a/sound/direct_sound_samples/cries/sneasler.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/sneasler.wav b/sound/direct_sound_samples/cries/sneasler.wav new file mode 100644 index 0000000000..4dbc8c5eea Binary files /dev/null and b/sound/direct_sound_samples/cries/sneasler.wav differ diff --git a/sound/direct_sound_samples/cries/snivy.aif b/sound/direct_sound_samples/cries/snivy.aif deleted file mode 100644 index cd0335decb..0000000000 Binary files a/sound/direct_sound_samples/cries/snivy.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/snivy.wav b/sound/direct_sound_samples/cries/snivy.wav new file mode 100644 index 0000000000..1d9ba8c4a6 Binary files /dev/null and b/sound/direct_sound_samples/cries/snivy.wav differ diff --git a/sound/direct_sound_samples/cries/snom.aif b/sound/direct_sound_samples/cries/snom.aif deleted file mode 100644 index 9591fa1d7d..0000000000 Binary files a/sound/direct_sound_samples/cries/snom.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/snom.wav b/sound/direct_sound_samples/cries/snom.wav new file mode 100644 index 0000000000..384269745a Binary files /dev/null and b/sound/direct_sound_samples/cries/snom.wav differ diff --git a/sound/direct_sound_samples/cries/snorlax.aif b/sound/direct_sound_samples/cries/snorlax.aif deleted file mode 100644 index d65557c798..0000000000 Binary files a/sound/direct_sound_samples/cries/snorlax.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/snorlax.wav b/sound/direct_sound_samples/cries/snorlax.wav new file mode 100644 index 0000000000..12e717be17 Binary files /dev/null and b/sound/direct_sound_samples/cries/snorlax.wav differ diff --git a/sound/direct_sound_samples/cries/snorunt.aif b/sound/direct_sound_samples/cries/snorunt.aif deleted file mode 100644 index 21bae9fc67..0000000000 Binary files a/sound/direct_sound_samples/cries/snorunt.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/snorunt.wav b/sound/direct_sound_samples/cries/snorunt.wav new file mode 100644 index 0000000000..b4ecc4537f Binary files /dev/null and b/sound/direct_sound_samples/cries/snorunt.wav differ diff --git a/sound/direct_sound_samples/cries/snover.aif b/sound/direct_sound_samples/cries/snover.aif deleted file mode 100644 index d02aceda4c..0000000000 Binary files a/sound/direct_sound_samples/cries/snover.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/snover.wav b/sound/direct_sound_samples/cries/snover.wav new file mode 100644 index 0000000000..1ddb86c7bc Binary files /dev/null and b/sound/direct_sound_samples/cries/snover.wav differ diff --git a/sound/direct_sound_samples/cries/snubbull.aif b/sound/direct_sound_samples/cries/snubbull.aif deleted file mode 100644 index 5e2ca9adb0..0000000000 Binary files a/sound/direct_sound_samples/cries/snubbull.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/snubbull.wav b/sound/direct_sound_samples/cries/snubbull.wav new file mode 100644 index 0000000000..37cacda8f7 Binary files /dev/null and b/sound/direct_sound_samples/cries/snubbull.wav differ diff --git a/sound/direct_sound_samples/cries/sobble.aif b/sound/direct_sound_samples/cries/sobble.aif deleted file mode 100644 index bdb1d937fa..0000000000 Binary files a/sound/direct_sound_samples/cries/sobble.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/sobble.wav b/sound/direct_sound_samples/cries/sobble.wav new file mode 100644 index 0000000000..6a384d1de2 Binary files /dev/null and b/sound/direct_sound_samples/cries/sobble.wav differ diff --git a/sound/direct_sound_samples/cries/solgaleo.aif b/sound/direct_sound_samples/cries/solgaleo.aif deleted file mode 100644 index 8cb9ad0cb5..0000000000 Binary files a/sound/direct_sound_samples/cries/solgaleo.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/solgaleo.wav b/sound/direct_sound_samples/cries/solgaleo.wav new file mode 100644 index 0000000000..575978e635 Binary files /dev/null and b/sound/direct_sound_samples/cries/solgaleo.wav differ diff --git a/sound/direct_sound_samples/cries/solosis.aif b/sound/direct_sound_samples/cries/solosis.aif deleted file mode 100644 index 701424bbd6..0000000000 Binary files a/sound/direct_sound_samples/cries/solosis.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/solosis.wav b/sound/direct_sound_samples/cries/solosis.wav new file mode 100644 index 0000000000..edb4b6ba7a Binary files /dev/null and b/sound/direct_sound_samples/cries/solosis.wav differ diff --git a/sound/direct_sound_samples/cries/solrock.aif b/sound/direct_sound_samples/cries/solrock.aif deleted file mode 100644 index ed58aeecae..0000000000 Binary files a/sound/direct_sound_samples/cries/solrock.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/solrock.wav b/sound/direct_sound_samples/cries/solrock.wav new file mode 100644 index 0000000000..12f766af71 Binary files /dev/null and b/sound/direct_sound_samples/cries/solrock.wav differ diff --git a/sound/direct_sound_samples/cries/spearow.aif b/sound/direct_sound_samples/cries/spearow.aif deleted file mode 100644 index 9fb8d0cc8f..0000000000 Binary files a/sound/direct_sound_samples/cries/spearow.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/spearow.wav b/sound/direct_sound_samples/cries/spearow.wav new file mode 100644 index 0000000000..a648481368 Binary files /dev/null and b/sound/direct_sound_samples/cries/spearow.wav differ diff --git a/sound/direct_sound_samples/cries/spectrier.aif b/sound/direct_sound_samples/cries/spectrier.aif deleted file mode 100644 index a43dc77a6c..0000000000 Binary files a/sound/direct_sound_samples/cries/spectrier.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/spectrier.wav b/sound/direct_sound_samples/cries/spectrier.wav new file mode 100644 index 0000000000..dbfbfef08d Binary files /dev/null and b/sound/direct_sound_samples/cries/spectrier.wav differ diff --git a/sound/direct_sound_samples/cries/spewpa.aif b/sound/direct_sound_samples/cries/spewpa.aif deleted file mode 100644 index 34cd82b989..0000000000 Binary files a/sound/direct_sound_samples/cries/spewpa.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/spewpa.wav b/sound/direct_sound_samples/cries/spewpa.wav new file mode 100644 index 0000000000..f260c20c64 Binary files /dev/null and b/sound/direct_sound_samples/cries/spewpa.wav differ diff --git a/sound/direct_sound_samples/cries/spheal.aif b/sound/direct_sound_samples/cries/spheal.aif deleted file mode 100644 index 44d21a9739..0000000000 Binary files a/sound/direct_sound_samples/cries/spheal.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/spheal.wav b/sound/direct_sound_samples/cries/spheal.wav new file mode 100644 index 0000000000..818caf8cd8 Binary files /dev/null and b/sound/direct_sound_samples/cries/spheal.wav differ diff --git a/sound/direct_sound_samples/cries/spidops.aif b/sound/direct_sound_samples/cries/spidops.aif deleted file mode 100644 index 626aa0c3f5..0000000000 Binary files a/sound/direct_sound_samples/cries/spidops.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/spidops.wav b/sound/direct_sound_samples/cries/spidops.wav new file mode 100644 index 0000000000..cfde8c39b3 Binary files /dev/null and b/sound/direct_sound_samples/cries/spidops.wav differ diff --git a/sound/direct_sound_samples/cries/spinarak.aif b/sound/direct_sound_samples/cries/spinarak.aif deleted file mode 100644 index f49c856aca..0000000000 Binary files a/sound/direct_sound_samples/cries/spinarak.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/spinarak.wav b/sound/direct_sound_samples/cries/spinarak.wav new file mode 100644 index 0000000000..3c45731327 Binary files /dev/null and b/sound/direct_sound_samples/cries/spinarak.wav differ diff --git a/sound/direct_sound_samples/cries/spinda.aif b/sound/direct_sound_samples/cries/spinda.aif deleted file mode 100644 index 01914a5d09..0000000000 Binary files a/sound/direct_sound_samples/cries/spinda.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/spinda.wav b/sound/direct_sound_samples/cries/spinda.wav new file mode 100644 index 0000000000..4481e3a887 Binary files /dev/null and b/sound/direct_sound_samples/cries/spinda.wav differ diff --git a/sound/direct_sound_samples/cries/spiritomb.aif b/sound/direct_sound_samples/cries/spiritomb.aif deleted file mode 100644 index 7a504adfb0..0000000000 Binary files a/sound/direct_sound_samples/cries/spiritomb.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/spiritomb.wav b/sound/direct_sound_samples/cries/spiritomb.wav new file mode 100644 index 0000000000..45b6574232 Binary files /dev/null and b/sound/direct_sound_samples/cries/spiritomb.wav differ diff --git a/sound/direct_sound_samples/cries/spoink.aif b/sound/direct_sound_samples/cries/spoink.aif deleted file mode 100644 index 102f53d8f1..0000000000 Binary files a/sound/direct_sound_samples/cries/spoink.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/spoink.wav b/sound/direct_sound_samples/cries/spoink.wav new file mode 100644 index 0000000000..36447fb84b Binary files /dev/null and b/sound/direct_sound_samples/cries/spoink.wav differ diff --git a/sound/direct_sound_samples/cries/sprigatito.aif b/sound/direct_sound_samples/cries/sprigatito.aif deleted file mode 100644 index 13616f9686..0000000000 Binary files a/sound/direct_sound_samples/cries/sprigatito.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/sprigatito.wav b/sound/direct_sound_samples/cries/sprigatito.wav new file mode 100644 index 0000000000..822c2d70fc Binary files /dev/null and b/sound/direct_sound_samples/cries/sprigatito.wav differ diff --git a/sound/direct_sound_samples/cries/spritzee.aif b/sound/direct_sound_samples/cries/spritzee.aif deleted file mode 100644 index 3bf2499d72..0000000000 Binary files a/sound/direct_sound_samples/cries/spritzee.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/spritzee.wav b/sound/direct_sound_samples/cries/spritzee.wav new file mode 100644 index 0000000000..18dc72256f Binary files /dev/null and b/sound/direct_sound_samples/cries/spritzee.wav differ diff --git a/sound/direct_sound_samples/cries/squawkabilly.aif b/sound/direct_sound_samples/cries/squawkabilly.aif deleted file mode 100644 index 0c88f36f74..0000000000 Binary files a/sound/direct_sound_samples/cries/squawkabilly.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/squawkabilly.wav b/sound/direct_sound_samples/cries/squawkabilly.wav new file mode 100644 index 0000000000..77d90d6f4d Binary files /dev/null and b/sound/direct_sound_samples/cries/squawkabilly.wav differ diff --git a/sound/direct_sound_samples/cries/squirtle.aif b/sound/direct_sound_samples/cries/squirtle.aif deleted file mode 100644 index 8e6cf8644d..0000000000 Binary files a/sound/direct_sound_samples/cries/squirtle.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/squirtle.wav b/sound/direct_sound_samples/cries/squirtle.wav new file mode 100644 index 0000000000..0cf32c6b6c Binary files /dev/null and b/sound/direct_sound_samples/cries/squirtle.wav differ diff --git a/sound/direct_sound_samples/cries/stakataka.aif b/sound/direct_sound_samples/cries/stakataka.aif deleted file mode 100644 index cabe903b43..0000000000 Binary files a/sound/direct_sound_samples/cries/stakataka.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/stakataka.wav b/sound/direct_sound_samples/cries/stakataka.wav new file mode 100644 index 0000000000..c5ca06ea58 Binary files /dev/null and b/sound/direct_sound_samples/cries/stakataka.wav differ diff --git a/sound/direct_sound_samples/cries/stantler.aif b/sound/direct_sound_samples/cries/stantler.aif deleted file mode 100644 index 231466ebea..0000000000 Binary files a/sound/direct_sound_samples/cries/stantler.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/stantler.wav b/sound/direct_sound_samples/cries/stantler.wav new file mode 100644 index 0000000000..f59953beb0 Binary files /dev/null and b/sound/direct_sound_samples/cries/stantler.wav differ diff --git a/sound/direct_sound_samples/cries/staraptor.aif b/sound/direct_sound_samples/cries/staraptor.aif deleted file mode 100644 index 05ccd1f024..0000000000 Binary files a/sound/direct_sound_samples/cries/staraptor.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/staraptor.wav b/sound/direct_sound_samples/cries/staraptor.wav new file mode 100644 index 0000000000..acbbdc0ece Binary files /dev/null and b/sound/direct_sound_samples/cries/staraptor.wav differ diff --git a/sound/direct_sound_samples/cries/staravia.aif b/sound/direct_sound_samples/cries/staravia.aif deleted file mode 100644 index 235d14eaf8..0000000000 Binary files a/sound/direct_sound_samples/cries/staravia.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/staravia.wav b/sound/direct_sound_samples/cries/staravia.wav new file mode 100644 index 0000000000..97d6bfe631 Binary files /dev/null and b/sound/direct_sound_samples/cries/staravia.wav differ diff --git a/sound/direct_sound_samples/cries/starly.aif b/sound/direct_sound_samples/cries/starly.aif deleted file mode 100644 index 2b0dd3960a..0000000000 Binary files a/sound/direct_sound_samples/cries/starly.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/starly.wav b/sound/direct_sound_samples/cries/starly.wav new file mode 100644 index 0000000000..f897be9a81 Binary files /dev/null and b/sound/direct_sound_samples/cries/starly.wav differ diff --git a/sound/direct_sound_samples/cries/starmie.aif b/sound/direct_sound_samples/cries/starmie.aif deleted file mode 100644 index a2daf86800..0000000000 Binary files a/sound/direct_sound_samples/cries/starmie.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/starmie.wav b/sound/direct_sound_samples/cries/starmie.wav new file mode 100644 index 0000000000..e3ace4fcf2 Binary files /dev/null and b/sound/direct_sound_samples/cries/starmie.wav differ diff --git a/sound/direct_sound_samples/cries/staryu.aif b/sound/direct_sound_samples/cries/staryu.aif deleted file mode 100644 index cd0cbc6b2b..0000000000 Binary files a/sound/direct_sound_samples/cries/staryu.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/staryu.wav b/sound/direct_sound_samples/cries/staryu.wav new file mode 100644 index 0000000000..c726206f43 Binary files /dev/null and b/sound/direct_sound_samples/cries/staryu.wav differ diff --git a/sound/direct_sound_samples/cries/steelix.aif b/sound/direct_sound_samples/cries/steelix.aif deleted file mode 100644 index 060cd00be4..0000000000 Binary files a/sound/direct_sound_samples/cries/steelix.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/steelix.wav b/sound/direct_sound_samples/cries/steelix.wav new file mode 100644 index 0000000000..8683e3d242 Binary files /dev/null and b/sound/direct_sound_samples/cries/steelix.wav differ diff --git a/sound/direct_sound_samples/cries/steelix_mega.aif b/sound/direct_sound_samples/cries/steelix_mega.aif deleted file mode 100644 index dfb068e161..0000000000 Binary files a/sound/direct_sound_samples/cries/steelix_mega.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/steelix_mega.wav b/sound/direct_sound_samples/cries/steelix_mega.wav new file mode 100644 index 0000000000..1ce3f8a0e3 Binary files /dev/null and b/sound/direct_sound_samples/cries/steelix_mega.wav differ diff --git a/sound/direct_sound_samples/cries/steenee.aif b/sound/direct_sound_samples/cries/steenee.aif deleted file mode 100644 index 54b9df83b7..0000000000 Binary files a/sound/direct_sound_samples/cries/steenee.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/steenee.wav b/sound/direct_sound_samples/cries/steenee.wav new file mode 100644 index 0000000000..c6749208e9 Binary files /dev/null and b/sound/direct_sound_samples/cries/steenee.wav differ diff --git a/sound/direct_sound_samples/cries/stonjourner.aif b/sound/direct_sound_samples/cries/stonjourner.aif deleted file mode 100644 index c1a24f3779..0000000000 Binary files a/sound/direct_sound_samples/cries/stonjourner.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/stonjourner.wav b/sound/direct_sound_samples/cries/stonjourner.wav new file mode 100644 index 0000000000..81064b70cf Binary files /dev/null and b/sound/direct_sound_samples/cries/stonjourner.wav differ diff --git a/sound/direct_sound_samples/cries/stoutland.aif b/sound/direct_sound_samples/cries/stoutland.aif deleted file mode 100644 index 5479323d49..0000000000 Binary files a/sound/direct_sound_samples/cries/stoutland.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/stoutland.wav b/sound/direct_sound_samples/cries/stoutland.wav new file mode 100644 index 0000000000..f95b522660 Binary files /dev/null and b/sound/direct_sound_samples/cries/stoutland.wav differ diff --git a/sound/direct_sound_samples/cries/stufful.aif b/sound/direct_sound_samples/cries/stufful.aif deleted file mode 100644 index abd70624f0..0000000000 Binary files a/sound/direct_sound_samples/cries/stufful.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/stufful.wav b/sound/direct_sound_samples/cries/stufful.wav new file mode 100644 index 0000000000..f03666ef8f Binary files /dev/null and b/sound/direct_sound_samples/cries/stufful.wav differ diff --git a/sound/direct_sound_samples/cries/stunfisk.aif b/sound/direct_sound_samples/cries/stunfisk.aif deleted file mode 100644 index 3d7f116cfd..0000000000 Binary files a/sound/direct_sound_samples/cries/stunfisk.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/stunfisk.wav b/sound/direct_sound_samples/cries/stunfisk.wav new file mode 100644 index 0000000000..68165add79 Binary files /dev/null and b/sound/direct_sound_samples/cries/stunfisk.wav differ diff --git a/sound/direct_sound_samples/cries/stunky.aif b/sound/direct_sound_samples/cries/stunky.aif deleted file mode 100644 index bb9a34bc62..0000000000 Binary files a/sound/direct_sound_samples/cries/stunky.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/stunky.wav b/sound/direct_sound_samples/cries/stunky.wav new file mode 100644 index 0000000000..50faa537e6 Binary files /dev/null and b/sound/direct_sound_samples/cries/stunky.wav differ diff --git a/sound/direct_sound_samples/cries/sudowoodo.aif b/sound/direct_sound_samples/cries/sudowoodo.aif deleted file mode 100644 index 64ef66ef0c..0000000000 Binary files a/sound/direct_sound_samples/cries/sudowoodo.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/sudowoodo.wav b/sound/direct_sound_samples/cries/sudowoodo.wav new file mode 100644 index 0000000000..48661df94e Binary files /dev/null and b/sound/direct_sound_samples/cries/sudowoodo.wav differ diff --git a/sound/direct_sound_samples/cries/suicune.aif b/sound/direct_sound_samples/cries/suicune.aif deleted file mode 100644 index 10840f92c1..0000000000 Binary files a/sound/direct_sound_samples/cries/suicune.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/suicune.wav b/sound/direct_sound_samples/cries/suicune.wav new file mode 100644 index 0000000000..f675d8fdc4 Binary files /dev/null and b/sound/direct_sound_samples/cries/suicune.wav differ diff --git a/sound/direct_sound_samples/cries/sunflora.aif b/sound/direct_sound_samples/cries/sunflora.aif deleted file mode 100644 index e64c7ab4e4..0000000000 Binary files a/sound/direct_sound_samples/cries/sunflora.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/sunflora.wav b/sound/direct_sound_samples/cries/sunflora.wav new file mode 100644 index 0000000000..613422881c Binary files /dev/null and b/sound/direct_sound_samples/cries/sunflora.wav differ diff --git a/sound/direct_sound_samples/cries/sunkern.aif b/sound/direct_sound_samples/cries/sunkern.aif deleted file mode 100644 index ecead99e99..0000000000 Binary files a/sound/direct_sound_samples/cries/sunkern.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/sunkern.wav b/sound/direct_sound_samples/cries/sunkern.wav new file mode 100644 index 0000000000..b183f9ee94 Binary files /dev/null and b/sound/direct_sound_samples/cries/sunkern.wav differ diff --git a/sound/direct_sound_samples/cries/surskit.aif b/sound/direct_sound_samples/cries/surskit.aif deleted file mode 100644 index 445daa6129..0000000000 Binary files a/sound/direct_sound_samples/cries/surskit.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/surskit.wav b/sound/direct_sound_samples/cries/surskit.wav new file mode 100644 index 0000000000..04b1be882d Binary files /dev/null and b/sound/direct_sound_samples/cries/surskit.wav differ diff --git a/sound/direct_sound_samples/cries/swablu.aif b/sound/direct_sound_samples/cries/swablu.aif deleted file mode 100644 index 0940910ce3..0000000000 Binary files a/sound/direct_sound_samples/cries/swablu.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/swablu.wav b/sound/direct_sound_samples/cries/swablu.wav new file mode 100644 index 0000000000..f24d349307 Binary files /dev/null and b/sound/direct_sound_samples/cries/swablu.wav differ diff --git a/sound/direct_sound_samples/cries/swadloon.aif b/sound/direct_sound_samples/cries/swadloon.aif deleted file mode 100644 index d2606953b2..0000000000 Binary files a/sound/direct_sound_samples/cries/swadloon.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/swadloon.wav b/sound/direct_sound_samples/cries/swadloon.wav new file mode 100644 index 0000000000..c2d2ff2eb4 Binary files /dev/null and b/sound/direct_sound_samples/cries/swadloon.wav differ diff --git a/sound/direct_sound_samples/cries/swalot.aif b/sound/direct_sound_samples/cries/swalot.aif deleted file mode 100644 index 87e57c9b70..0000000000 Binary files a/sound/direct_sound_samples/cries/swalot.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/swalot.wav b/sound/direct_sound_samples/cries/swalot.wav new file mode 100644 index 0000000000..cfed979342 Binary files /dev/null and b/sound/direct_sound_samples/cries/swalot.wav differ diff --git a/sound/direct_sound_samples/cries/swampert.aif b/sound/direct_sound_samples/cries/swampert.aif deleted file mode 100644 index 132844c705..0000000000 Binary files a/sound/direct_sound_samples/cries/swampert.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/swampert.wav b/sound/direct_sound_samples/cries/swampert.wav new file mode 100644 index 0000000000..a06f15992f Binary files /dev/null and b/sound/direct_sound_samples/cries/swampert.wav differ diff --git a/sound/direct_sound_samples/cries/swampert_mega.aif b/sound/direct_sound_samples/cries/swampert_mega.aif deleted file mode 100644 index c19ec99835..0000000000 Binary files a/sound/direct_sound_samples/cries/swampert_mega.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/swampert_mega.wav b/sound/direct_sound_samples/cries/swampert_mega.wav new file mode 100644 index 0000000000..6abd498819 Binary files /dev/null and b/sound/direct_sound_samples/cries/swampert_mega.wav differ diff --git a/sound/direct_sound_samples/cries/swanna.aif b/sound/direct_sound_samples/cries/swanna.aif deleted file mode 100644 index 9b2ef724f6..0000000000 Binary files a/sound/direct_sound_samples/cries/swanna.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/swanna.wav b/sound/direct_sound_samples/cries/swanna.wav new file mode 100644 index 0000000000..f2390b1fc4 Binary files /dev/null and b/sound/direct_sound_samples/cries/swanna.wav differ diff --git a/sound/direct_sound_samples/cries/swellow.aif b/sound/direct_sound_samples/cries/swellow.aif deleted file mode 100644 index a5bf66627d..0000000000 Binary files a/sound/direct_sound_samples/cries/swellow.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/swellow.wav b/sound/direct_sound_samples/cries/swellow.wav new file mode 100644 index 0000000000..637ff46540 Binary files /dev/null and b/sound/direct_sound_samples/cries/swellow.wav differ diff --git a/sound/direct_sound_samples/cries/swinub.aif b/sound/direct_sound_samples/cries/swinub.aif deleted file mode 100644 index 7b2a08bf6f..0000000000 Binary files a/sound/direct_sound_samples/cries/swinub.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/swinub.wav b/sound/direct_sound_samples/cries/swinub.wav new file mode 100644 index 0000000000..93eafa458d Binary files /dev/null and b/sound/direct_sound_samples/cries/swinub.wav differ diff --git a/sound/direct_sound_samples/cries/swirlix.aif b/sound/direct_sound_samples/cries/swirlix.aif deleted file mode 100644 index 89fa6ecd16..0000000000 Binary files a/sound/direct_sound_samples/cries/swirlix.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/swirlix.wav b/sound/direct_sound_samples/cries/swirlix.wav new file mode 100644 index 0000000000..e1340299c5 Binary files /dev/null and b/sound/direct_sound_samples/cries/swirlix.wav differ diff --git a/sound/direct_sound_samples/cries/swoobat.aif b/sound/direct_sound_samples/cries/swoobat.aif deleted file mode 100644 index 32f8d406c5..0000000000 Binary files a/sound/direct_sound_samples/cries/swoobat.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/swoobat.wav b/sound/direct_sound_samples/cries/swoobat.wav new file mode 100644 index 0000000000..be69ad2430 Binary files /dev/null and b/sound/direct_sound_samples/cries/swoobat.wav differ diff --git a/sound/direct_sound_samples/cries/sylveon.aif b/sound/direct_sound_samples/cries/sylveon.aif deleted file mode 100644 index 0ded5d19d1..0000000000 Binary files a/sound/direct_sound_samples/cries/sylveon.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/sylveon.wav b/sound/direct_sound_samples/cries/sylveon.wav new file mode 100644 index 0000000000..7652199061 Binary files /dev/null and b/sound/direct_sound_samples/cries/sylveon.wav differ diff --git a/sound/direct_sound_samples/cries/tadbulb.aif b/sound/direct_sound_samples/cries/tadbulb.aif deleted file mode 100644 index 4680059cde..0000000000 Binary files a/sound/direct_sound_samples/cries/tadbulb.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/tadbulb.wav b/sound/direct_sound_samples/cries/tadbulb.wav new file mode 100644 index 0000000000..42eec08df8 Binary files /dev/null and b/sound/direct_sound_samples/cries/tadbulb.wav differ diff --git a/sound/direct_sound_samples/cries/taillow.aif b/sound/direct_sound_samples/cries/taillow.aif deleted file mode 100644 index c30cdb275b..0000000000 Binary files a/sound/direct_sound_samples/cries/taillow.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/taillow.wav b/sound/direct_sound_samples/cries/taillow.wav new file mode 100644 index 0000000000..9f1bb25f48 Binary files /dev/null and b/sound/direct_sound_samples/cries/taillow.wav differ diff --git a/sound/direct_sound_samples/cries/talonflame.aif b/sound/direct_sound_samples/cries/talonflame.aif deleted file mode 100644 index d16a4a2128..0000000000 Binary files a/sound/direct_sound_samples/cries/talonflame.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/talonflame.wav b/sound/direct_sound_samples/cries/talonflame.wav new file mode 100644 index 0000000000..b418813d10 Binary files /dev/null and b/sound/direct_sound_samples/cries/talonflame.wav differ diff --git a/sound/direct_sound_samples/cries/tandemaus.aif b/sound/direct_sound_samples/cries/tandemaus.aif deleted file mode 100644 index c6aeb27e0c..0000000000 Binary files a/sound/direct_sound_samples/cries/tandemaus.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/tandemaus.wav b/sound/direct_sound_samples/cries/tandemaus.wav new file mode 100644 index 0000000000..88ddc17353 Binary files /dev/null and b/sound/direct_sound_samples/cries/tandemaus.wav differ diff --git a/sound/direct_sound_samples/cries/tangela.aif b/sound/direct_sound_samples/cries/tangela.aif deleted file mode 100644 index e463f2b7e6..0000000000 Binary files a/sound/direct_sound_samples/cries/tangela.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/tangela.wav b/sound/direct_sound_samples/cries/tangela.wav new file mode 100644 index 0000000000..023a0362f9 Binary files /dev/null and b/sound/direct_sound_samples/cries/tangela.wav differ diff --git a/sound/direct_sound_samples/cries/tangrowth.aif b/sound/direct_sound_samples/cries/tangrowth.aif deleted file mode 100644 index 23e3d995b7..0000000000 Binary files a/sound/direct_sound_samples/cries/tangrowth.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/tangrowth.wav b/sound/direct_sound_samples/cries/tangrowth.wav new file mode 100644 index 0000000000..941a8d9d24 Binary files /dev/null and b/sound/direct_sound_samples/cries/tangrowth.wav differ diff --git a/sound/direct_sound_samples/cries/tapu_bulu.aif b/sound/direct_sound_samples/cries/tapu_bulu.aif deleted file mode 100644 index ab84791fa7..0000000000 Binary files a/sound/direct_sound_samples/cries/tapu_bulu.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/tapu_bulu.wav b/sound/direct_sound_samples/cries/tapu_bulu.wav new file mode 100644 index 0000000000..45b7a0ff69 Binary files /dev/null and b/sound/direct_sound_samples/cries/tapu_bulu.wav differ diff --git a/sound/direct_sound_samples/cries/tapu_fini.aif b/sound/direct_sound_samples/cries/tapu_fini.aif deleted file mode 100644 index 301b0a70b8..0000000000 Binary files a/sound/direct_sound_samples/cries/tapu_fini.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/tapu_fini.wav b/sound/direct_sound_samples/cries/tapu_fini.wav new file mode 100644 index 0000000000..6a9a1fea48 Binary files /dev/null and b/sound/direct_sound_samples/cries/tapu_fini.wav differ diff --git a/sound/direct_sound_samples/cries/tapu_koko.aif b/sound/direct_sound_samples/cries/tapu_koko.aif deleted file mode 100644 index 2fae1a3b0b..0000000000 Binary files a/sound/direct_sound_samples/cries/tapu_koko.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/tapu_koko.wav b/sound/direct_sound_samples/cries/tapu_koko.wav new file mode 100644 index 0000000000..2f93829ee1 Binary files /dev/null and b/sound/direct_sound_samples/cries/tapu_koko.wav differ diff --git a/sound/direct_sound_samples/cries/tapu_lele.aif b/sound/direct_sound_samples/cries/tapu_lele.aif deleted file mode 100644 index c15bb31862..0000000000 Binary files a/sound/direct_sound_samples/cries/tapu_lele.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/tapu_lele.wav b/sound/direct_sound_samples/cries/tapu_lele.wav new file mode 100644 index 0000000000..6e93a9a4de Binary files /dev/null and b/sound/direct_sound_samples/cries/tapu_lele.wav differ diff --git a/sound/direct_sound_samples/cries/tarountula.aif b/sound/direct_sound_samples/cries/tarountula.aif deleted file mode 100644 index d8d2438565..0000000000 Binary files a/sound/direct_sound_samples/cries/tarountula.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/tarountula.wav b/sound/direct_sound_samples/cries/tarountula.wav new file mode 100644 index 0000000000..13aa6c89f8 Binary files /dev/null and b/sound/direct_sound_samples/cries/tarountula.wav differ diff --git a/sound/direct_sound_samples/cries/tatsugiri_curly.aif b/sound/direct_sound_samples/cries/tatsugiri_curly.aif deleted file mode 100644 index 16c03553ab..0000000000 Binary files a/sound/direct_sound_samples/cries/tatsugiri_curly.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/tatsugiri_curly.wav b/sound/direct_sound_samples/cries/tatsugiri_curly.wav new file mode 100644 index 0000000000..c8eb9c8929 Binary files /dev/null and b/sound/direct_sound_samples/cries/tatsugiri_curly.wav differ diff --git a/sound/direct_sound_samples/cries/tatsugiri_droopy.aif b/sound/direct_sound_samples/cries/tatsugiri_droopy.aif deleted file mode 100644 index 20131039e5..0000000000 Binary files a/sound/direct_sound_samples/cries/tatsugiri_droopy.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/tatsugiri_droopy.wav b/sound/direct_sound_samples/cries/tatsugiri_droopy.wav new file mode 100644 index 0000000000..999a846311 Binary files /dev/null and b/sound/direct_sound_samples/cries/tatsugiri_droopy.wav differ diff --git a/sound/direct_sound_samples/cries/tatsugiri_stretchy.aif b/sound/direct_sound_samples/cries/tatsugiri_stretchy.aif deleted file mode 100644 index 08e5680433..0000000000 Binary files a/sound/direct_sound_samples/cries/tatsugiri_stretchy.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/tatsugiri_stretchy.wav b/sound/direct_sound_samples/cries/tatsugiri_stretchy.wav new file mode 100644 index 0000000000..62653400ae Binary files /dev/null and b/sound/direct_sound_samples/cries/tatsugiri_stretchy.wav differ diff --git a/sound/direct_sound_samples/cries/tauros.aif b/sound/direct_sound_samples/cries/tauros.aif deleted file mode 100644 index 1b4bdfa5c4..0000000000 Binary files a/sound/direct_sound_samples/cries/tauros.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/tauros.wav b/sound/direct_sound_samples/cries/tauros.wav new file mode 100644 index 0000000000..a982d052d9 Binary files /dev/null and b/sound/direct_sound_samples/cries/tauros.wav differ diff --git a/sound/direct_sound_samples/cries/teddiursa.aif b/sound/direct_sound_samples/cries/teddiursa.aif deleted file mode 100644 index 19ba558c3b..0000000000 Binary files a/sound/direct_sound_samples/cries/teddiursa.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/teddiursa.wav b/sound/direct_sound_samples/cries/teddiursa.wav new file mode 100644 index 0000000000..adc9b80d9c Binary files /dev/null and b/sound/direct_sound_samples/cries/teddiursa.wav differ diff --git a/sound/direct_sound_samples/cries/tentacool.aif b/sound/direct_sound_samples/cries/tentacool.aif deleted file mode 100644 index 8918f25627..0000000000 Binary files a/sound/direct_sound_samples/cries/tentacool.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/tentacool.wav b/sound/direct_sound_samples/cries/tentacool.wav new file mode 100644 index 0000000000..cd8f5afc7a Binary files /dev/null and b/sound/direct_sound_samples/cries/tentacool.wav differ diff --git a/sound/direct_sound_samples/cries/tentacruel.aif b/sound/direct_sound_samples/cries/tentacruel.aif deleted file mode 100644 index 2497d178df..0000000000 Binary files a/sound/direct_sound_samples/cries/tentacruel.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/tentacruel.wav b/sound/direct_sound_samples/cries/tentacruel.wav new file mode 100644 index 0000000000..dfbc8c7f09 Binary files /dev/null and b/sound/direct_sound_samples/cries/tentacruel.wav differ diff --git a/sound/direct_sound_samples/cries/tepig.aif b/sound/direct_sound_samples/cries/tepig.aif deleted file mode 100644 index 45b7b4ecda..0000000000 Binary files a/sound/direct_sound_samples/cries/tepig.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/tepig.wav b/sound/direct_sound_samples/cries/tepig.wav new file mode 100644 index 0000000000..766107639e Binary files /dev/null and b/sound/direct_sound_samples/cries/tepig.wav differ diff --git a/sound/direct_sound_samples/cries/terapagos.aif b/sound/direct_sound_samples/cries/terapagos.aif deleted file mode 100644 index a99810cca9..0000000000 Binary files a/sound/direct_sound_samples/cries/terapagos.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/terapagos.wav b/sound/direct_sound_samples/cries/terapagos.wav new file mode 100644 index 0000000000..bbda64cb64 Binary files /dev/null and b/sound/direct_sound_samples/cries/terapagos.wav differ diff --git a/sound/direct_sound_samples/cries/terrakion.aif b/sound/direct_sound_samples/cries/terrakion.aif deleted file mode 100644 index e567be0f1e..0000000000 Binary files a/sound/direct_sound_samples/cries/terrakion.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/terrakion.wav b/sound/direct_sound_samples/cries/terrakion.wav new file mode 100644 index 0000000000..ec3d1e52a6 Binary files /dev/null and b/sound/direct_sound_samples/cries/terrakion.wav differ diff --git a/sound/direct_sound_samples/cries/thievul.aif b/sound/direct_sound_samples/cries/thievul.aif deleted file mode 100644 index 8bf63fd888..0000000000 Binary files a/sound/direct_sound_samples/cries/thievul.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/thievul.wav b/sound/direct_sound_samples/cries/thievul.wav new file mode 100644 index 0000000000..2a3fc4e49c Binary files /dev/null and b/sound/direct_sound_samples/cries/thievul.wav differ diff --git a/sound/direct_sound_samples/cries/throh.aif b/sound/direct_sound_samples/cries/throh.aif deleted file mode 100644 index eeeba64e4b..0000000000 Binary files a/sound/direct_sound_samples/cries/throh.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/throh.wav b/sound/direct_sound_samples/cries/throh.wav new file mode 100644 index 0000000000..9568bd7ca1 Binary files /dev/null and b/sound/direct_sound_samples/cries/throh.wav differ diff --git a/sound/direct_sound_samples/cries/thundurus_incarnate.aif b/sound/direct_sound_samples/cries/thundurus_incarnate.aif deleted file mode 100644 index 8b1c81b9f9..0000000000 Binary files a/sound/direct_sound_samples/cries/thundurus_incarnate.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/thundurus_incarnate.wav b/sound/direct_sound_samples/cries/thundurus_incarnate.wav new file mode 100644 index 0000000000..bee2249eef Binary files /dev/null and b/sound/direct_sound_samples/cries/thundurus_incarnate.wav differ diff --git a/sound/direct_sound_samples/cries/thundurus_therian.aif b/sound/direct_sound_samples/cries/thundurus_therian.aif deleted file mode 100644 index f5ac69f177..0000000000 Binary files a/sound/direct_sound_samples/cries/thundurus_therian.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/thundurus_therian.wav b/sound/direct_sound_samples/cries/thundurus_therian.wav new file mode 100644 index 0000000000..e31bda03bc Binary files /dev/null and b/sound/direct_sound_samples/cries/thundurus_therian.wav differ diff --git a/sound/direct_sound_samples/cries/thwackey.aif b/sound/direct_sound_samples/cries/thwackey.aif deleted file mode 100644 index 579df5c965..0000000000 Binary files a/sound/direct_sound_samples/cries/thwackey.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/thwackey.wav b/sound/direct_sound_samples/cries/thwackey.wav new file mode 100644 index 0000000000..d91325a387 Binary files /dev/null and b/sound/direct_sound_samples/cries/thwackey.wav differ diff --git a/sound/direct_sound_samples/cries/timburr.aif b/sound/direct_sound_samples/cries/timburr.aif deleted file mode 100644 index 49edb74efb..0000000000 Binary files a/sound/direct_sound_samples/cries/timburr.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/timburr.wav b/sound/direct_sound_samples/cries/timburr.wav new file mode 100644 index 0000000000..4a332408a1 Binary files /dev/null and b/sound/direct_sound_samples/cries/timburr.wav differ diff --git a/sound/direct_sound_samples/cries/ting_lu.aif b/sound/direct_sound_samples/cries/ting_lu.aif deleted file mode 100644 index a4a5ed2118..0000000000 Binary files a/sound/direct_sound_samples/cries/ting_lu.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/ting_lu.wav b/sound/direct_sound_samples/cries/ting_lu.wav new file mode 100644 index 0000000000..5f262d014e Binary files /dev/null and b/sound/direct_sound_samples/cries/ting_lu.wav differ diff --git a/sound/direct_sound_samples/cries/tinkatink.aif b/sound/direct_sound_samples/cries/tinkatink.aif deleted file mode 100644 index a6229c1338..0000000000 Binary files a/sound/direct_sound_samples/cries/tinkatink.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/tinkatink.wav b/sound/direct_sound_samples/cries/tinkatink.wav new file mode 100644 index 0000000000..e20cf33933 Binary files /dev/null and b/sound/direct_sound_samples/cries/tinkatink.wav differ diff --git a/sound/direct_sound_samples/cries/tinkaton.aif b/sound/direct_sound_samples/cries/tinkaton.aif deleted file mode 100644 index fd88cb8459..0000000000 Binary files a/sound/direct_sound_samples/cries/tinkaton.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/tinkaton.wav b/sound/direct_sound_samples/cries/tinkaton.wav new file mode 100644 index 0000000000..eaac1993bd Binary files /dev/null and b/sound/direct_sound_samples/cries/tinkaton.wav differ diff --git a/sound/direct_sound_samples/cries/tinkatuff.aif b/sound/direct_sound_samples/cries/tinkatuff.aif deleted file mode 100644 index aa096ef113..0000000000 Binary files a/sound/direct_sound_samples/cries/tinkatuff.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/tinkatuff.wav b/sound/direct_sound_samples/cries/tinkatuff.wav new file mode 100644 index 0000000000..e077d63a2d Binary files /dev/null and b/sound/direct_sound_samples/cries/tinkatuff.wav differ diff --git a/sound/direct_sound_samples/cries/tirtouga.aif b/sound/direct_sound_samples/cries/tirtouga.aif deleted file mode 100644 index 2233557d22..0000000000 Binary files a/sound/direct_sound_samples/cries/tirtouga.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/tirtouga.wav b/sound/direct_sound_samples/cries/tirtouga.wav new file mode 100644 index 0000000000..c22f087842 Binary files /dev/null and b/sound/direct_sound_samples/cries/tirtouga.wav differ diff --git a/sound/direct_sound_samples/cries/toedscool.aif b/sound/direct_sound_samples/cries/toedscool.aif deleted file mode 100644 index a153ed4d87..0000000000 Binary files a/sound/direct_sound_samples/cries/toedscool.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/toedscool.wav b/sound/direct_sound_samples/cries/toedscool.wav new file mode 100644 index 0000000000..21c119feec Binary files /dev/null and b/sound/direct_sound_samples/cries/toedscool.wav differ diff --git a/sound/direct_sound_samples/cries/toedscruel.aif b/sound/direct_sound_samples/cries/toedscruel.aif deleted file mode 100644 index 1f2fade60c..0000000000 Binary files a/sound/direct_sound_samples/cries/toedscruel.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/toedscruel.wav b/sound/direct_sound_samples/cries/toedscruel.wav new file mode 100644 index 0000000000..7e1b4a6321 Binary files /dev/null and b/sound/direct_sound_samples/cries/toedscruel.wav differ diff --git a/sound/direct_sound_samples/cries/togedemaru.aif b/sound/direct_sound_samples/cries/togedemaru.aif deleted file mode 100644 index 366ce2be96..0000000000 Binary files a/sound/direct_sound_samples/cries/togedemaru.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/togedemaru.wav b/sound/direct_sound_samples/cries/togedemaru.wav new file mode 100644 index 0000000000..7249f3eb6e Binary files /dev/null and b/sound/direct_sound_samples/cries/togedemaru.wav differ diff --git a/sound/direct_sound_samples/cries/togekiss.aif b/sound/direct_sound_samples/cries/togekiss.aif deleted file mode 100644 index c66baeaf55..0000000000 Binary files a/sound/direct_sound_samples/cries/togekiss.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/togekiss.wav b/sound/direct_sound_samples/cries/togekiss.wav new file mode 100644 index 0000000000..84ae1d7bc9 Binary files /dev/null and b/sound/direct_sound_samples/cries/togekiss.wav differ diff --git a/sound/direct_sound_samples/cries/togepi.aif b/sound/direct_sound_samples/cries/togepi.aif deleted file mode 100644 index 0785a662ab..0000000000 Binary files a/sound/direct_sound_samples/cries/togepi.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/togepi.wav b/sound/direct_sound_samples/cries/togepi.wav new file mode 100644 index 0000000000..e13355c554 Binary files /dev/null and b/sound/direct_sound_samples/cries/togepi.wav differ diff --git a/sound/direct_sound_samples/cries/togetic.aif b/sound/direct_sound_samples/cries/togetic.aif deleted file mode 100644 index f577120c6d..0000000000 Binary files a/sound/direct_sound_samples/cries/togetic.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/togetic.wav b/sound/direct_sound_samples/cries/togetic.wav new file mode 100644 index 0000000000..957a45dc94 Binary files /dev/null and b/sound/direct_sound_samples/cries/togetic.wav differ diff --git a/sound/direct_sound_samples/cries/torchic.aif b/sound/direct_sound_samples/cries/torchic.aif deleted file mode 100644 index 3accc1b3c8..0000000000 Binary files a/sound/direct_sound_samples/cries/torchic.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/torchic.wav b/sound/direct_sound_samples/cries/torchic.wav new file mode 100644 index 0000000000..39a2522b32 Binary files /dev/null and b/sound/direct_sound_samples/cries/torchic.wav differ diff --git a/sound/direct_sound_samples/cries/torkoal.aif b/sound/direct_sound_samples/cries/torkoal.aif deleted file mode 100644 index b73d06ef5e..0000000000 Binary files a/sound/direct_sound_samples/cries/torkoal.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/torkoal.wav b/sound/direct_sound_samples/cries/torkoal.wav new file mode 100644 index 0000000000..497e92af20 Binary files /dev/null and b/sound/direct_sound_samples/cries/torkoal.wav differ diff --git a/sound/direct_sound_samples/cries/tornadus_incarnate.aif b/sound/direct_sound_samples/cries/tornadus_incarnate.aif deleted file mode 100644 index b980ce2bb5..0000000000 Binary files a/sound/direct_sound_samples/cries/tornadus_incarnate.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/tornadus_incarnate.wav b/sound/direct_sound_samples/cries/tornadus_incarnate.wav new file mode 100644 index 0000000000..46c02fa112 Binary files /dev/null and b/sound/direct_sound_samples/cries/tornadus_incarnate.wav differ diff --git a/sound/direct_sound_samples/cries/tornadus_therian.aif b/sound/direct_sound_samples/cries/tornadus_therian.aif deleted file mode 100644 index a1d98062b6..0000000000 Binary files a/sound/direct_sound_samples/cries/tornadus_therian.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/tornadus_therian.wav b/sound/direct_sound_samples/cries/tornadus_therian.wav new file mode 100644 index 0000000000..3d6d421d2d Binary files /dev/null and b/sound/direct_sound_samples/cries/tornadus_therian.wav differ diff --git a/sound/direct_sound_samples/cries/torracat.aif b/sound/direct_sound_samples/cries/torracat.aif deleted file mode 100644 index 44bb001375..0000000000 Binary files a/sound/direct_sound_samples/cries/torracat.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/torracat.wav b/sound/direct_sound_samples/cries/torracat.wav new file mode 100644 index 0000000000..fb8cf24c61 Binary files /dev/null and b/sound/direct_sound_samples/cries/torracat.wav differ diff --git a/sound/direct_sound_samples/cries/torterra.aif b/sound/direct_sound_samples/cries/torterra.aif deleted file mode 100644 index e659181e23..0000000000 Binary files a/sound/direct_sound_samples/cries/torterra.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/torterra.wav b/sound/direct_sound_samples/cries/torterra.wav new file mode 100644 index 0000000000..3fdb2e6d12 Binary files /dev/null and b/sound/direct_sound_samples/cries/torterra.wav differ diff --git a/sound/direct_sound_samples/cries/totodile.aif b/sound/direct_sound_samples/cries/totodile.aif deleted file mode 100644 index 98fbb528be..0000000000 Binary files a/sound/direct_sound_samples/cries/totodile.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/totodile.wav b/sound/direct_sound_samples/cries/totodile.wav new file mode 100644 index 0000000000..93c0788473 Binary files /dev/null and b/sound/direct_sound_samples/cries/totodile.wav differ diff --git a/sound/direct_sound_samples/cries/toucannon.aif b/sound/direct_sound_samples/cries/toucannon.aif deleted file mode 100644 index 83a90bab9c..0000000000 Binary files a/sound/direct_sound_samples/cries/toucannon.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/toucannon.wav b/sound/direct_sound_samples/cries/toucannon.wav new file mode 100644 index 0000000000..f8b3938483 Binary files /dev/null and b/sound/direct_sound_samples/cries/toucannon.wav differ diff --git a/sound/direct_sound_samples/cries/toxapex.aif b/sound/direct_sound_samples/cries/toxapex.aif deleted file mode 100644 index 3369da2f70..0000000000 Binary files a/sound/direct_sound_samples/cries/toxapex.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/toxapex.wav b/sound/direct_sound_samples/cries/toxapex.wav new file mode 100644 index 0000000000..a2e759b11d Binary files /dev/null and b/sound/direct_sound_samples/cries/toxapex.wav differ diff --git a/sound/direct_sound_samples/cries/toxel.aif b/sound/direct_sound_samples/cries/toxel.aif deleted file mode 100644 index 0f917edddb..0000000000 Binary files a/sound/direct_sound_samples/cries/toxel.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/toxel.wav b/sound/direct_sound_samples/cries/toxel.wav new file mode 100644 index 0000000000..2f43210fab Binary files /dev/null and b/sound/direct_sound_samples/cries/toxel.wav differ diff --git a/sound/direct_sound_samples/cries/toxicroak.aif b/sound/direct_sound_samples/cries/toxicroak.aif deleted file mode 100644 index ada83b0a2b..0000000000 Binary files a/sound/direct_sound_samples/cries/toxicroak.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/toxicroak.wav b/sound/direct_sound_samples/cries/toxicroak.wav new file mode 100644 index 0000000000..5dd49163fe Binary files /dev/null and b/sound/direct_sound_samples/cries/toxicroak.wav differ diff --git a/sound/direct_sound_samples/cries/toxtricity_amped.aif b/sound/direct_sound_samples/cries/toxtricity_amped.aif deleted file mode 100644 index 0775c8a049..0000000000 Binary files a/sound/direct_sound_samples/cries/toxtricity_amped.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/toxtricity_amped.wav b/sound/direct_sound_samples/cries/toxtricity_amped.wav new file mode 100644 index 0000000000..236fc88417 Binary files /dev/null and b/sound/direct_sound_samples/cries/toxtricity_amped.wav differ diff --git a/sound/direct_sound_samples/cries/toxtricity_low_key.aif b/sound/direct_sound_samples/cries/toxtricity_low_key.aif deleted file mode 100644 index 57740d974d..0000000000 Binary files a/sound/direct_sound_samples/cries/toxtricity_low_key.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/toxtricity_low_key.wav b/sound/direct_sound_samples/cries/toxtricity_low_key.wav new file mode 100644 index 0000000000..6c1bb8a111 Binary files /dev/null and b/sound/direct_sound_samples/cries/toxtricity_low_key.wav differ diff --git a/sound/direct_sound_samples/cries/tranquill.aif b/sound/direct_sound_samples/cries/tranquill.aif deleted file mode 100644 index 6a4e8a7661..0000000000 Binary files a/sound/direct_sound_samples/cries/tranquill.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/tranquill.wav b/sound/direct_sound_samples/cries/tranquill.wav new file mode 100644 index 0000000000..d8ade54fc1 Binary files /dev/null and b/sound/direct_sound_samples/cries/tranquill.wav differ diff --git a/sound/direct_sound_samples/cries/trapinch.aif b/sound/direct_sound_samples/cries/trapinch.aif deleted file mode 100644 index cc27653fd4..0000000000 Binary files a/sound/direct_sound_samples/cries/trapinch.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/trapinch.wav b/sound/direct_sound_samples/cries/trapinch.wav new file mode 100644 index 0000000000..5cad4ad23e Binary files /dev/null and b/sound/direct_sound_samples/cries/trapinch.wav differ diff --git a/sound/direct_sound_samples/cries/treecko.aif b/sound/direct_sound_samples/cries/treecko.aif deleted file mode 100644 index e9a47979e0..0000000000 Binary files a/sound/direct_sound_samples/cries/treecko.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/treecko.wav b/sound/direct_sound_samples/cries/treecko.wav new file mode 100644 index 0000000000..0c982f8408 Binary files /dev/null and b/sound/direct_sound_samples/cries/treecko.wav differ diff --git a/sound/direct_sound_samples/cries/trevenant.aif b/sound/direct_sound_samples/cries/trevenant.aif deleted file mode 100644 index 018a80e8c2..0000000000 Binary files a/sound/direct_sound_samples/cries/trevenant.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/trevenant.wav b/sound/direct_sound_samples/cries/trevenant.wav new file mode 100644 index 0000000000..da2efb4594 Binary files /dev/null and b/sound/direct_sound_samples/cries/trevenant.wav differ diff --git a/sound/direct_sound_samples/cries/tropius.aif b/sound/direct_sound_samples/cries/tropius.aif deleted file mode 100644 index 81046fe1cf..0000000000 Binary files a/sound/direct_sound_samples/cries/tropius.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/tropius.wav b/sound/direct_sound_samples/cries/tropius.wav new file mode 100644 index 0000000000..55de362aa7 Binary files /dev/null and b/sound/direct_sound_samples/cries/tropius.wav differ diff --git a/sound/direct_sound_samples/cries/trubbish.aif b/sound/direct_sound_samples/cries/trubbish.aif deleted file mode 100644 index 09c1aac572..0000000000 Binary files a/sound/direct_sound_samples/cries/trubbish.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/trubbish.wav b/sound/direct_sound_samples/cries/trubbish.wav new file mode 100644 index 0000000000..5ee879913b Binary files /dev/null and b/sound/direct_sound_samples/cries/trubbish.wav differ diff --git a/sound/direct_sound_samples/cries/trumbeak.aif b/sound/direct_sound_samples/cries/trumbeak.aif deleted file mode 100644 index c6e477c401..0000000000 Binary files a/sound/direct_sound_samples/cries/trumbeak.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/trumbeak.wav b/sound/direct_sound_samples/cries/trumbeak.wav new file mode 100644 index 0000000000..389e543a1f Binary files /dev/null and b/sound/direct_sound_samples/cries/trumbeak.wav differ diff --git a/sound/direct_sound_samples/cries/tsareena.aif b/sound/direct_sound_samples/cries/tsareena.aif deleted file mode 100644 index bff64b0f3f..0000000000 Binary files a/sound/direct_sound_samples/cries/tsareena.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/tsareena.wav b/sound/direct_sound_samples/cries/tsareena.wav new file mode 100644 index 0000000000..f062986677 Binary files /dev/null and b/sound/direct_sound_samples/cries/tsareena.wav differ diff --git a/sound/direct_sound_samples/cries/turtonator.aif b/sound/direct_sound_samples/cries/turtonator.aif deleted file mode 100644 index b5d27b630f..0000000000 Binary files a/sound/direct_sound_samples/cries/turtonator.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/turtonator.wav b/sound/direct_sound_samples/cries/turtonator.wav new file mode 100644 index 0000000000..0bc247246a Binary files /dev/null and b/sound/direct_sound_samples/cries/turtonator.wav differ diff --git a/sound/direct_sound_samples/cries/turtwig.aif b/sound/direct_sound_samples/cries/turtwig.aif deleted file mode 100644 index a2e4ad60b3..0000000000 Binary files a/sound/direct_sound_samples/cries/turtwig.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/turtwig.wav b/sound/direct_sound_samples/cries/turtwig.wav new file mode 100644 index 0000000000..afa0b43969 Binary files /dev/null and b/sound/direct_sound_samples/cries/turtwig.wav differ diff --git a/sound/direct_sound_samples/cries/tympole.aif b/sound/direct_sound_samples/cries/tympole.aif deleted file mode 100644 index d643216736..0000000000 Binary files a/sound/direct_sound_samples/cries/tympole.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/tympole.wav b/sound/direct_sound_samples/cries/tympole.wav new file mode 100644 index 0000000000..f8455239eb Binary files /dev/null and b/sound/direct_sound_samples/cries/tympole.wav differ diff --git a/sound/direct_sound_samples/cries/tynamo.aif b/sound/direct_sound_samples/cries/tynamo.aif deleted file mode 100644 index ca9e2962fc..0000000000 Binary files a/sound/direct_sound_samples/cries/tynamo.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/tynamo.wav b/sound/direct_sound_samples/cries/tynamo.wav new file mode 100644 index 0000000000..031a336a6c Binary files /dev/null and b/sound/direct_sound_samples/cries/tynamo.wav differ diff --git a/sound/direct_sound_samples/cries/type_null.aif b/sound/direct_sound_samples/cries/type_null.aif deleted file mode 100644 index 6b6be2dcfb..0000000000 Binary files a/sound/direct_sound_samples/cries/type_null.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/type_null.wav b/sound/direct_sound_samples/cries/type_null.wav new file mode 100644 index 0000000000..9850d88e4a Binary files /dev/null and b/sound/direct_sound_samples/cries/type_null.wav differ diff --git a/sound/direct_sound_samples/cries/typhlosion.aif b/sound/direct_sound_samples/cries/typhlosion.aif deleted file mode 100644 index cc993c8052..0000000000 Binary files a/sound/direct_sound_samples/cries/typhlosion.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/typhlosion.wav b/sound/direct_sound_samples/cries/typhlosion.wav new file mode 100644 index 0000000000..f1759989d7 Binary files /dev/null and b/sound/direct_sound_samples/cries/typhlosion.wav differ diff --git a/sound/direct_sound_samples/cries/tyranitar.aif b/sound/direct_sound_samples/cries/tyranitar.aif deleted file mode 100644 index 3572da7667..0000000000 Binary files a/sound/direct_sound_samples/cries/tyranitar.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/tyranitar.wav b/sound/direct_sound_samples/cries/tyranitar.wav new file mode 100644 index 0000000000..5bec5f7279 Binary files /dev/null and b/sound/direct_sound_samples/cries/tyranitar.wav differ diff --git a/sound/direct_sound_samples/cries/tyranitar_mega.aif b/sound/direct_sound_samples/cries/tyranitar_mega.aif deleted file mode 100644 index 020118b388..0000000000 Binary files a/sound/direct_sound_samples/cries/tyranitar_mega.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/tyranitar_mega.wav b/sound/direct_sound_samples/cries/tyranitar_mega.wav new file mode 100644 index 0000000000..dedb9d2560 Binary files /dev/null and b/sound/direct_sound_samples/cries/tyranitar_mega.wav differ diff --git a/sound/direct_sound_samples/cries/tyrantrum.aif b/sound/direct_sound_samples/cries/tyrantrum.aif deleted file mode 100644 index 88e9506129..0000000000 Binary files a/sound/direct_sound_samples/cries/tyrantrum.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/tyrantrum.wav b/sound/direct_sound_samples/cries/tyrantrum.wav new file mode 100644 index 0000000000..766cbab204 Binary files /dev/null and b/sound/direct_sound_samples/cries/tyrantrum.wav differ diff --git a/sound/direct_sound_samples/cries/tyrogue.aif b/sound/direct_sound_samples/cries/tyrogue.aif deleted file mode 100644 index 7caea851b3..0000000000 Binary files a/sound/direct_sound_samples/cries/tyrogue.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/tyrogue.wav b/sound/direct_sound_samples/cries/tyrogue.wav new file mode 100644 index 0000000000..46d032063d Binary files /dev/null and b/sound/direct_sound_samples/cries/tyrogue.wav differ diff --git a/sound/direct_sound_samples/cries/tyrunt.aif b/sound/direct_sound_samples/cries/tyrunt.aif deleted file mode 100644 index e693736005..0000000000 Binary files a/sound/direct_sound_samples/cries/tyrunt.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/tyrunt.wav b/sound/direct_sound_samples/cries/tyrunt.wav new file mode 100644 index 0000000000..9cb0531dad Binary files /dev/null and b/sound/direct_sound_samples/cries/tyrunt.wav differ diff --git a/sound/direct_sound_samples/cries/umbreon.aif b/sound/direct_sound_samples/cries/umbreon.aif deleted file mode 100644 index 93c739dd74..0000000000 Binary files a/sound/direct_sound_samples/cries/umbreon.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/umbreon.wav b/sound/direct_sound_samples/cries/umbreon.wav new file mode 100644 index 0000000000..48f62064af Binary files /dev/null and b/sound/direct_sound_samples/cries/umbreon.wav differ diff --git a/sound/direct_sound_samples/cries/uncomp_klefki.aif b/sound/direct_sound_samples/cries/uncomp_klefki.aif deleted file mode 100644 index c059b56628..0000000000 Binary files a/sound/direct_sound_samples/cries/uncomp_klefki.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/uncomp_klefki.wav b/sound/direct_sound_samples/cries/uncomp_klefki.wav new file mode 100644 index 0000000000..9e606820eb Binary files /dev/null and b/sound/direct_sound_samples/cries/uncomp_klefki.wav differ diff --git a/sound/direct_sound_samples/cries/uncomp_oricorio_pom_pom.aif b/sound/direct_sound_samples/cries/uncomp_oricorio_pom_pom.aif deleted file mode 100644 index aa5fce23b6..0000000000 Binary files a/sound/direct_sound_samples/cries/uncomp_oricorio_pom_pom.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/uncomp_oricorio_pom_pom.wav b/sound/direct_sound_samples/cries/uncomp_oricorio_pom_pom.wav new file mode 100644 index 0000000000..912a9f3831 Binary files /dev/null and b/sound/direct_sound_samples/cries/uncomp_oricorio_pom_pom.wav differ diff --git a/sound/direct_sound_samples/cries/unfezant.aif b/sound/direct_sound_samples/cries/unfezant.aif deleted file mode 100644 index 1fde88bf0e..0000000000 Binary files a/sound/direct_sound_samples/cries/unfezant.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/unfezant.wav b/sound/direct_sound_samples/cries/unfezant.wav new file mode 100644 index 0000000000..fa21282be0 Binary files /dev/null and b/sound/direct_sound_samples/cries/unfezant.wav differ diff --git a/sound/direct_sound_samples/cries/unown.aif b/sound/direct_sound_samples/cries/unown.aif deleted file mode 100644 index 0b3edf577f..0000000000 Binary files a/sound/direct_sound_samples/cries/unown.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/unown.wav b/sound/direct_sound_samples/cries/unown.wav new file mode 100644 index 0000000000..1956ecef75 Binary files /dev/null and b/sound/direct_sound_samples/cries/unown.wav differ diff --git a/sound/direct_sound_samples/cries/unused_265.wav b/sound/direct_sound_samples/cries/unused_265.wav new file mode 100644 index 0000000000..12c3d8640f Binary files /dev/null and b/sound/direct_sound_samples/cries/unused_265.wav differ diff --git a/sound/direct_sound_samples/cries/unused_268.wav b/sound/direct_sound_samples/cries/unused_268.wav new file mode 100644 index 0000000000..3501b24ef8 Binary files /dev/null and b/sound/direct_sound_samples/cries/unused_268.wav differ diff --git a/sound/direct_sound_samples/cries/ursaluna.aif b/sound/direct_sound_samples/cries/ursaluna.aif deleted file mode 100644 index 7ce14c630e..0000000000 Binary files a/sound/direct_sound_samples/cries/ursaluna.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/ursaluna.wav b/sound/direct_sound_samples/cries/ursaluna.wav new file mode 100644 index 0000000000..b6e99a6015 Binary files /dev/null and b/sound/direct_sound_samples/cries/ursaluna.wav differ diff --git a/sound/direct_sound_samples/cries/ursaring.aif b/sound/direct_sound_samples/cries/ursaring.aif deleted file mode 100644 index 7837ba6597..0000000000 Binary files a/sound/direct_sound_samples/cries/ursaring.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/ursaring.wav b/sound/direct_sound_samples/cries/ursaring.wav new file mode 100644 index 0000000000..b3d4a99cb7 Binary files /dev/null and b/sound/direct_sound_samples/cries/ursaring.wav differ diff --git a/sound/direct_sound_samples/cries/urshifu_rapid_strike.aif b/sound/direct_sound_samples/cries/urshifu_rapid_strike.aif deleted file mode 100644 index 8ac12bc909..0000000000 Binary files a/sound/direct_sound_samples/cries/urshifu_rapid_strike.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/urshifu_rapid_strike.wav b/sound/direct_sound_samples/cries/urshifu_rapid_strike.wav new file mode 100644 index 0000000000..74a7f35206 Binary files /dev/null and b/sound/direct_sound_samples/cries/urshifu_rapid_strike.wav differ diff --git a/sound/direct_sound_samples/cries/urshifu_single_strike.aif b/sound/direct_sound_samples/cries/urshifu_single_strike.aif deleted file mode 100644 index 7dec47854a..0000000000 Binary files a/sound/direct_sound_samples/cries/urshifu_single_strike.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/urshifu_single_strike.wav b/sound/direct_sound_samples/cries/urshifu_single_strike.wav new file mode 100644 index 0000000000..549e5cd2dc Binary files /dev/null and b/sound/direct_sound_samples/cries/urshifu_single_strike.wav differ diff --git a/sound/direct_sound_samples/cries/uxie.aif b/sound/direct_sound_samples/cries/uxie.aif deleted file mode 100644 index da67cfc996..0000000000 Binary files a/sound/direct_sound_samples/cries/uxie.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/uxie.wav b/sound/direct_sound_samples/cries/uxie.wav new file mode 100644 index 0000000000..336ff25f58 Binary files /dev/null and b/sound/direct_sound_samples/cries/uxie.wav differ diff --git a/sound/direct_sound_samples/cries/vanillish.aif b/sound/direct_sound_samples/cries/vanillish.aif deleted file mode 100644 index 625921a24b..0000000000 Binary files a/sound/direct_sound_samples/cries/vanillish.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/vanillish.wav b/sound/direct_sound_samples/cries/vanillish.wav new file mode 100644 index 0000000000..29f2e853c4 Binary files /dev/null and b/sound/direct_sound_samples/cries/vanillish.wav differ diff --git a/sound/direct_sound_samples/cries/vanillite.aif b/sound/direct_sound_samples/cries/vanillite.aif deleted file mode 100644 index 03d25f9615..0000000000 Binary files a/sound/direct_sound_samples/cries/vanillite.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/vanillite.wav b/sound/direct_sound_samples/cries/vanillite.wav new file mode 100644 index 0000000000..db303dd8e7 Binary files /dev/null and b/sound/direct_sound_samples/cries/vanillite.wav differ diff --git a/sound/direct_sound_samples/cries/vanilluxe.aif b/sound/direct_sound_samples/cries/vanilluxe.aif deleted file mode 100644 index e515359ee0..0000000000 Binary files a/sound/direct_sound_samples/cries/vanilluxe.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/vanilluxe.wav b/sound/direct_sound_samples/cries/vanilluxe.wav new file mode 100644 index 0000000000..d75e877475 Binary files /dev/null and b/sound/direct_sound_samples/cries/vanilluxe.wav differ diff --git a/sound/direct_sound_samples/cries/vaporeon.aif b/sound/direct_sound_samples/cries/vaporeon.aif deleted file mode 100644 index 3c9bf7ee8b..0000000000 Binary files a/sound/direct_sound_samples/cries/vaporeon.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/vaporeon.wav b/sound/direct_sound_samples/cries/vaporeon.wav new file mode 100644 index 0000000000..8ec3094851 Binary files /dev/null and b/sound/direct_sound_samples/cries/vaporeon.wav differ diff --git a/sound/direct_sound_samples/cries/varoom.aif b/sound/direct_sound_samples/cries/varoom.aif deleted file mode 100644 index 731bdce2d6..0000000000 Binary files a/sound/direct_sound_samples/cries/varoom.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/varoom.wav b/sound/direct_sound_samples/cries/varoom.wav new file mode 100644 index 0000000000..1774dd3dc4 Binary files /dev/null and b/sound/direct_sound_samples/cries/varoom.wav differ diff --git a/sound/direct_sound_samples/cries/veluza.aif b/sound/direct_sound_samples/cries/veluza.aif deleted file mode 100644 index d76ed74b66..0000000000 Binary files a/sound/direct_sound_samples/cries/veluza.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/veluza.wav b/sound/direct_sound_samples/cries/veluza.wav new file mode 100644 index 0000000000..731b664ac3 Binary files /dev/null and b/sound/direct_sound_samples/cries/veluza.wav differ diff --git a/sound/direct_sound_samples/cries/venipede.aif b/sound/direct_sound_samples/cries/venipede.aif deleted file mode 100644 index d1c1e04e7b..0000000000 Binary files a/sound/direct_sound_samples/cries/venipede.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/venipede.wav b/sound/direct_sound_samples/cries/venipede.wav new file mode 100644 index 0000000000..c1b88a3e25 Binary files /dev/null and b/sound/direct_sound_samples/cries/venipede.wav differ diff --git a/sound/direct_sound_samples/cries/venomoth.aif b/sound/direct_sound_samples/cries/venomoth.aif deleted file mode 100644 index eb4ad02af7..0000000000 Binary files a/sound/direct_sound_samples/cries/venomoth.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/venomoth.wav b/sound/direct_sound_samples/cries/venomoth.wav new file mode 100644 index 0000000000..ab5179df66 Binary files /dev/null and b/sound/direct_sound_samples/cries/venomoth.wav differ diff --git a/sound/direct_sound_samples/cries/venonat.aif b/sound/direct_sound_samples/cries/venonat.aif deleted file mode 100644 index 5bf36808c4..0000000000 Binary files a/sound/direct_sound_samples/cries/venonat.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/venonat.wav b/sound/direct_sound_samples/cries/venonat.wav new file mode 100644 index 0000000000..450c2bb222 Binary files /dev/null and b/sound/direct_sound_samples/cries/venonat.wav differ diff --git a/sound/direct_sound_samples/cries/venusaur.aif b/sound/direct_sound_samples/cries/venusaur.aif deleted file mode 100644 index 91386c177d..0000000000 Binary files a/sound/direct_sound_samples/cries/venusaur.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/venusaur.wav b/sound/direct_sound_samples/cries/venusaur.wav new file mode 100644 index 0000000000..fdd299ae27 Binary files /dev/null and b/sound/direct_sound_samples/cries/venusaur.wav differ diff --git a/sound/direct_sound_samples/cries/venusaur_mega.aif b/sound/direct_sound_samples/cries/venusaur_mega.aif deleted file mode 100644 index cec11aaae2..0000000000 Binary files a/sound/direct_sound_samples/cries/venusaur_mega.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/venusaur_mega.wav b/sound/direct_sound_samples/cries/venusaur_mega.wav new file mode 100644 index 0000000000..e8e01ee0c3 Binary files /dev/null and b/sound/direct_sound_samples/cries/venusaur_mega.wav differ diff --git a/sound/direct_sound_samples/cries/vespiquen.aif b/sound/direct_sound_samples/cries/vespiquen.aif deleted file mode 100644 index c86e9a403b..0000000000 Binary files a/sound/direct_sound_samples/cries/vespiquen.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/vespiquen.wav b/sound/direct_sound_samples/cries/vespiquen.wav new file mode 100644 index 0000000000..a1fdfe215c Binary files /dev/null and b/sound/direct_sound_samples/cries/vespiquen.wav differ diff --git a/sound/direct_sound_samples/cries/vibrava.aif b/sound/direct_sound_samples/cries/vibrava.aif deleted file mode 100644 index 7e0a13c6df..0000000000 Binary files a/sound/direct_sound_samples/cries/vibrava.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/vibrava.wav b/sound/direct_sound_samples/cries/vibrava.wav new file mode 100644 index 0000000000..5370104875 Binary files /dev/null and b/sound/direct_sound_samples/cries/vibrava.wav differ diff --git a/sound/direct_sound_samples/cries/victini.aif b/sound/direct_sound_samples/cries/victini.aif deleted file mode 100644 index cada6fbf07..0000000000 Binary files a/sound/direct_sound_samples/cries/victini.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/victini.wav b/sound/direct_sound_samples/cries/victini.wav new file mode 100644 index 0000000000..381efef3f6 Binary files /dev/null and b/sound/direct_sound_samples/cries/victini.wav differ diff --git a/sound/direct_sound_samples/cries/victreebel.aif b/sound/direct_sound_samples/cries/victreebel.aif deleted file mode 100644 index 62bb048d4c..0000000000 Binary files a/sound/direct_sound_samples/cries/victreebel.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/victreebel.wav b/sound/direct_sound_samples/cries/victreebel.wav new file mode 100644 index 0000000000..19f11202f9 Binary files /dev/null and b/sound/direct_sound_samples/cries/victreebel.wav differ diff --git a/sound/direct_sound_samples/cries/vigoroth.aif b/sound/direct_sound_samples/cries/vigoroth.aif deleted file mode 100644 index 8e3560ab1d..0000000000 Binary files a/sound/direct_sound_samples/cries/vigoroth.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/vigoroth.wav b/sound/direct_sound_samples/cries/vigoroth.wav new file mode 100644 index 0000000000..5d21bd23b0 Binary files /dev/null and b/sound/direct_sound_samples/cries/vigoroth.wav differ diff --git a/sound/direct_sound_samples/cries/vikavolt.aif b/sound/direct_sound_samples/cries/vikavolt.aif deleted file mode 100644 index badd95c3c5..0000000000 Binary files a/sound/direct_sound_samples/cries/vikavolt.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/vikavolt.wav b/sound/direct_sound_samples/cries/vikavolt.wav new file mode 100644 index 0000000000..ac1d363120 Binary files /dev/null and b/sound/direct_sound_samples/cries/vikavolt.wav differ diff --git a/sound/direct_sound_samples/cries/vileplume.aif b/sound/direct_sound_samples/cries/vileplume.aif deleted file mode 100644 index e190e21511..0000000000 Binary files a/sound/direct_sound_samples/cries/vileplume.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/vileplume.wav b/sound/direct_sound_samples/cries/vileplume.wav new file mode 100644 index 0000000000..7189097b18 Binary files /dev/null and b/sound/direct_sound_samples/cries/vileplume.wav differ diff --git a/sound/direct_sound_samples/cries/virizion.aif b/sound/direct_sound_samples/cries/virizion.aif deleted file mode 100644 index 7f1d8292b0..0000000000 Binary files a/sound/direct_sound_samples/cries/virizion.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/virizion.wav b/sound/direct_sound_samples/cries/virizion.wav new file mode 100644 index 0000000000..4254006b8c Binary files /dev/null and b/sound/direct_sound_samples/cries/virizion.wav differ diff --git a/sound/direct_sound_samples/cries/vivillon.aif b/sound/direct_sound_samples/cries/vivillon.aif deleted file mode 100644 index bf7474dd95..0000000000 Binary files a/sound/direct_sound_samples/cries/vivillon.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/vivillon.wav b/sound/direct_sound_samples/cries/vivillon.wav new file mode 100644 index 0000000000..e681a1011a Binary files /dev/null and b/sound/direct_sound_samples/cries/vivillon.wav differ diff --git a/sound/direct_sound_samples/cries/volbeat.aif b/sound/direct_sound_samples/cries/volbeat.aif deleted file mode 100644 index 8d73e2c21d..0000000000 Binary files a/sound/direct_sound_samples/cries/volbeat.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/volbeat.wav b/sound/direct_sound_samples/cries/volbeat.wav new file mode 100644 index 0000000000..ae6375b95f Binary files /dev/null and b/sound/direct_sound_samples/cries/volbeat.wav differ diff --git a/sound/direct_sound_samples/cries/volcanion.aif b/sound/direct_sound_samples/cries/volcanion.aif deleted file mode 100644 index 72c78807a6..0000000000 Binary files a/sound/direct_sound_samples/cries/volcanion.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/volcanion.wav b/sound/direct_sound_samples/cries/volcanion.wav new file mode 100644 index 0000000000..47b59afb3e Binary files /dev/null and b/sound/direct_sound_samples/cries/volcanion.wav differ diff --git a/sound/direct_sound_samples/cries/volcarona.aif b/sound/direct_sound_samples/cries/volcarona.aif deleted file mode 100644 index f62e6e9e38..0000000000 Binary files a/sound/direct_sound_samples/cries/volcarona.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/volcarona.wav b/sound/direct_sound_samples/cries/volcarona.wav new file mode 100644 index 0000000000..53b0fde6bc Binary files /dev/null and b/sound/direct_sound_samples/cries/volcarona.wav differ diff --git a/sound/direct_sound_samples/cries/voltorb.aif b/sound/direct_sound_samples/cries/voltorb.aif deleted file mode 100644 index 832429cbf2..0000000000 Binary files a/sound/direct_sound_samples/cries/voltorb.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/voltorb.wav b/sound/direct_sound_samples/cries/voltorb.wav new file mode 100644 index 0000000000..e303a3db73 Binary files /dev/null and b/sound/direct_sound_samples/cries/voltorb.wav differ diff --git a/sound/direct_sound_samples/cries/vullaby.aif b/sound/direct_sound_samples/cries/vullaby.aif deleted file mode 100644 index 49d0648e9f..0000000000 Binary files a/sound/direct_sound_samples/cries/vullaby.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/vullaby.wav b/sound/direct_sound_samples/cries/vullaby.wav new file mode 100644 index 0000000000..7be4f722c6 Binary files /dev/null and b/sound/direct_sound_samples/cries/vullaby.wav differ diff --git a/sound/direct_sound_samples/cries/vulpix.aif b/sound/direct_sound_samples/cries/vulpix.aif deleted file mode 100644 index 32b149999e..0000000000 Binary files a/sound/direct_sound_samples/cries/vulpix.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/vulpix.wav b/sound/direct_sound_samples/cries/vulpix.wav new file mode 100644 index 0000000000..71d58b0a72 Binary files /dev/null and b/sound/direct_sound_samples/cries/vulpix.wav differ diff --git a/sound/direct_sound_samples/cries/wailmer.aif b/sound/direct_sound_samples/cries/wailmer.aif deleted file mode 100644 index 8bada495e4..0000000000 Binary files a/sound/direct_sound_samples/cries/wailmer.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/wailmer.wav b/sound/direct_sound_samples/cries/wailmer.wav new file mode 100644 index 0000000000..ef43c515fd Binary files /dev/null and b/sound/direct_sound_samples/cries/wailmer.wav differ diff --git a/sound/direct_sound_samples/cries/wailord.aif b/sound/direct_sound_samples/cries/wailord.aif deleted file mode 100644 index ea0f553cf8..0000000000 Binary files a/sound/direct_sound_samples/cries/wailord.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/wailord.wav b/sound/direct_sound_samples/cries/wailord.wav new file mode 100644 index 0000000000..a7e9d89f69 Binary files /dev/null and b/sound/direct_sound_samples/cries/wailord.wav differ diff --git a/sound/direct_sound_samples/cries/walking_wake.aif b/sound/direct_sound_samples/cries/walking_wake.aif deleted file mode 100644 index 88518dd200..0000000000 Binary files a/sound/direct_sound_samples/cries/walking_wake.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/walking_wake.wav b/sound/direct_sound_samples/cries/walking_wake.wav new file mode 100644 index 0000000000..ea856c0cf7 Binary files /dev/null and b/sound/direct_sound_samples/cries/walking_wake.wav differ diff --git a/sound/direct_sound_samples/cries/walrein.aif b/sound/direct_sound_samples/cries/walrein.aif deleted file mode 100644 index 2843617fbf..0000000000 Binary files a/sound/direct_sound_samples/cries/walrein.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/walrein.wav b/sound/direct_sound_samples/cries/walrein.wav new file mode 100644 index 0000000000..cbc5fa8cb4 Binary files /dev/null and b/sound/direct_sound_samples/cries/walrein.wav differ diff --git a/sound/direct_sound_samples/cries/wartortle.aif b/sound/direct_sound_samples/cries/wartortle.aif deleted file mode 100644 index de2aa25480..0000000000 Binary files a/sound/direct_sound_samples/cries/wartortle.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/wartortle.wav b/sound/direct_sound_samples/cries/wartortle.wav new file mode 100644 index 0000000000..950f87d74b Binary files /dev/null and b/sound/direct_sound_samples/cries/wartortle.wav differ diff --git a/sound/direct_sound_samples/cries/watchog.aif b/sound/direct_sound_samples/cries/watchog.aif deleted file mode 100644 index df08e7a296..0000000000 Binary files a/sound/direct_sound_samples/cries/watchog.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/watchog.wav b/sound/direct_sound_samples/cries/watchog.wav new file mode 100644 index 0000000000..f69adc8aef Binary files /dev/null and b/sound/direct_sound_samples/cries/watchog.wav differ diff --git a/sound/direct_sound_samples/cries/wattrel.aif b/sound/direct_sound_samples/cries/wattrel.aif deleted file mode 100644 index 361ead8356..0000000000 Binary files a/sound/direct_sound_samples/cries/wattrel.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/wattrel.wav b/sound/direct_sound_samples/cries/wattrel.wav new file mode 100644 index 0000000000..b803ef4042 Binary files /dev/null and b/sound/direct_sound_samples/cries/wattrel.wav differ diff --git a/sound/direct_sound_samples/cries/weavile.aif b/sound/direct_sound_samples/cries/weavile.aif deleted file mode 100644 index 5bfb5019df..0000000000 Binary files a/sound/direct_sound_samples/cries/weavile.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/weavile.wav b/sound/direct_sound_samples/cries/weavile.wav new file mode 100644 index 0000000000..36b8875373 Binary files /dev/null and b/sound/direct_sound_samples/cries/weavile.wav differ diff --git a/sound/direct_sound_samples/cries/weedle.aif b/sound/direct_sound_samples/cries/weedle.aif deleted file mode 100644 index ac5b0eb765..0000000000 Binary files a/sound/direct_sound_samples/cries/weedle.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/weedle.wav b/sound/direct_sound_samples/cries/weedle.wav new file mode 100644 index 0000000000..6a209fede1 Binary files /dev/null and b/sound/direct_sound_samples/cries/weedle.wav differ diff --git a/sound/direct_sound_samples/cries/weepinbell.aif b/sound/direct_sound_samples/cries/weepinbell.aif deleted file mode 100644 index 0b20df8089..0000000000 Binary files a/sound/direct_sound_samples/cries/weepinbell.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/weepinbell.wav b/sound/direct_sound_samples/cries/weepinbell.wav new file mode 100644 index 0000000000..48f7225cf5 Binary files /dev/null and b/sound/direct_sound_samples/cries/weepinbell.wav differ diff --git a/sound/direct_sound_samples/cries/weezing.aif b/sound/direct_sound_samples/cries/weezing.aif deleted file mode 100644 index b7b8d93da5..0000000000 Binary files a/sound/direct_sound_samples/cries/weezing.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/weezing.wav b/sound/direct_sound_samples/cries/weezing.wav new file mode 100644 index 0000000000..b5a7b189d0 Binary files /dev/null and b/sound/direct_sound_samples/cries/weezing.wav differ diff --git a/sound/direct_sound_samples/cries/whimsicott.aif b/sound/direct_sound_samples/cries/whimsicott.aif deleted file mode 100644 index 873d8a1b41..0000000000 Binary files a/sound/direct_sound_samples/cries/whimsicott.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/whimsicott.wav b/sound/direct_sound_samples/cries/whimsicott.wav new file mode 100644 index 0000000000..712aab7154 Binary files /dev/null and b/sound/direct_sound_samples/cries/whimsicott.wav differ diff --git a/sound/direct_sound_samples/cries/whirlipede.aif b/sound/direct_sound_samples/cries/whirlipede.aif deleted file mode 100644 index c9b64404b8..0000000000 Binary files a/sound/direct_sound_samples/cries/whirlipede.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/whirlipede.wav b/sound/direct_sound_samples/cries/whirlipede.wav new file mode 100644 index 0000000000..c468feb0f5 Binary files /dev/null and b/sound/direct_sound_samples/cries/whirlipede.wav differ diff --git a/sound/direct_sound_samples/cries/whiscash.aif b/sound/direct_sound_samples/cries/whiscash.aif deleted file mode 100644 index 71cd9fd00a..0000000000 Binary files a/sound/direct_sound_samples/cries/whiscash.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/whiscash.wav b/sound/direct_sound_samples/cries/whiscash.wav new file mode 100644 index 0000000000..ebec93d188 Binary files /dev/null and b/sound/direct_sound_samples/cries/whiscash.wav differ diff --git a/sound/direct_sound_samples/cries/whismur.aif b/sound/direct_sound_samples/cries/whismur.aif deleted file mode 100644 index c5a2369ba9..0000000000 Binary files a/sound/direct_sound_samples/cries/whismur.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/whismur.wav b/sound/direct_sound_samples/cries/whismur.wav new file mode 100644 index 0000000000..af3e3e0e31 Binary files /dev/null and b/sound/direct_sound_samples/cries/whismur.wav differ diff --git a/sound/direct_sound_samples/cries/wigglytuff.aif b/sound/direct_sound_samples/cries/wigglytuff.aif deleted file mode 100644 index 07fcc8ebd3..0000000000 Binary files a/sound/direct_sound_samples/cries/wigglytuff.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/wigglytuff.wav b/sound/direct_sound_samples/cries/wigglytuff.wav new file mode 100644 index 0000000000..a6b632a6ce Binary files /dev/null and b/sound/direct_sound_samples/cries/wigglytuff.wav differ diff --git a/sound/direct_sound_samples/cries/wiglett.aif b/sound/direct_sound_samples/cries/wiglett.aif deleted file mode 100644 index d377681aef..0000000000 Binary files a/sound/direct_sound_samples/cries/wiglett.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/wiglett.wav b/sound/direct_sound_samples/cries/wiglett.wav new file mode 100644 index 0000000000..c555b6035e Binary files /dev/null and b/sound/direct_sound_samples/cries/wiglett.wav differ diff --git a/sound/direct_sound_samples/cries/wimpod.aif b/sound/direct_sound_samples/cries/wimpod.aif deleted file mode 100644 index 5b75964096..0000000000 Binary files a/sound/direct_sound_samples/cries/wimpod.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/wimpod.wav b/sound/direct_sound_samples/cries/wimpod.wav new file mode 100644 index 0000000000..36b28c501d Binary files /dev/null and b/sound/direct_sound_samples/cries/wimpod.wav differ diff --git a/sound/direct_sound_samples/cries/wingull.aif b/sound/direct_sound_samples/cries/wingull.aif deleted file mode 100644 index 49b04d9d96..0000000000 Binary files a/sound/direct_sound_samples/cries/wingull.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/wingull.wav b/sound/direct_sound_samples/cries/wingull.wav new file mode 100644 index 0000000000..4e158409ad Binary files /dev/null and b/sound/direct_sound_samples/cries/wingull.wav differ diff --git a/sound/direct_sound_samples/cries/wishiwashi_school.aif b/sound/direct_sound_samples/cries/wishiwashi_school.aif deleted file mode 100644 index e63ce913a2..0000000000 Binary files a/sound/direct_sound_samples/cries/wishiwashi_school.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/wishiwashi_school.wav b/sound/direct_sound_samples/cries/wishiwashi_school.wav new file mode 100644 index 0000000000..ef49075f1c Binary files /dev/null and b/sound/direct_sound_samples/cries/wishiwashi_school.wav differ diff --git a/sound/direct_sound_samples/cries/wishiwashi_solo.aif b/sound/direct_sound_samples/cries/wishiwashi_solo.aif deleted file mode 100644 index e6e26b75c6..0000000000 Binary files a/sound/direct_sound_samples/cries/wishiwashi_solo.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/wishiwashi_solo.wav b/sound/direct_sound_samples/cries/wishiwashi_solo.wav new file mode 100644 index 0000000000..456a7c74f8 Binary files /dev/null and b/sound/direct_sound_samples/cries/wishiwashi_solo.wav differ diff --git a/sound/direct_sound_samples/cries/wo_chien.aif b/sound/direct_sound_samples/cries/wo_chien.aif deleted file mode 100644 index f50bd73e8d..0000000000 Binary files a/sound/direct_sound_samples/cries/wo_chien.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/wo_chien.wav b/sound/direct_sound_samples/cries/wo_chien.wav new file mode 100644 index 0000000000..562665fee3 Binary files /dev/null and b/sound/direct_sound_samples/cries/wo_chien.wav differ diff --git a/sound/direct_sound_samples/cries/wobbuffet.aif b/sound/direct_sound_samples/cries/wobbuffet.aif deleted file mode 100644 index 8e50da47bb..0000000000 Binary files a/sound/direct_sound_samples/cries/wobbuffet.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/wobbuffet.wav b/sound/direct_sound_samples/cries/wobbuffet.wav new file mode 100644 index 0000000000..17e7464ad9 Binary files /dev/null and b/sound/direct_sound_samples/cries/wobbuffet.wav differ diff --git a/sound/direct_sound_samples/cries/woobat.aif b/sound/direct_sound_samples/cries/woobat.aif deleted file mode 100644 index db8ae140e2..0000000000 Binary files a/sound/direct_sound_samples/cries/woobat.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/woobat.wav b/sound/direct_sound_samples/cries/woobat.wav new file mode 100644 index 0000000000..e8d3523e83 Binary files /dev/null and b/sound/direct_sound_samples/cries/woobat.wav differ diff --git a/sound/direct_sound_samples/cries/wooloo.aif b/sound/direct_sound_samples/cries/wooloo.aif deleted file mode 100644 index db1360386c..0000000000 Binary files a/sound/direct_sound_samples/cries/wooloo.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/wooloo.wav b/sound/direct_sound_samples/cries/wooloo.wav new file mode 100644 index 0000000000..adc8ad4ade Binary files /dev/null and b/sound/direct_sound_samples/cries/wooloo.wav differ diff --git a/sound/direct_sound_samples/cries/wooper.aif b/sound/direct_sound_samples/cries/wooper.aif deleted file mode 100644 index d4b9ea1b4a..0000000000 Binary files a/sound/direct_sound_samples/cries/wooper.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/wooper.wav b/sound/direct_sound_samples/cries/wooper.wav new file mode 100644 index 0000000000..83c7e589df Binary files /dev/null and b/sound/direct_sound_samples/cries/wooper.wav differ diff --git a/sound/direct_sound_samples/cries/wormadam.aif b/sound/direct_sound_samples/cries/wormadam.aif deleted file mode 100644 index 3645108206..0000000000 Binary files a/sound/direct_sound_samples/cries/wormadam.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/wormadam.wav b/sound/direct_sound_samples/cries/wormadam.wav new file mode 100644 index 0000000000..f03247f1dd Binary files /dev/null and b/sound/direct_sound_samples/cries/wormadam.wav differ diff --git a/sound/direct_sound_samples/cries/wugtrio.aif b/sound/direct_sound_samples/cries/wugtrio.aif deleted file mode 100644 index 6c92cae873..0000000000 Binary files a/sound/direct_sound_samples/cries/wugtrio.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/wugtrio.wav b/sound/direct_sound_samples/cries/wugtrio.wav new file mode 100644 index 0000000000..d885b422f3 Binary files /dev/null and b/sound/direct_sound_samples/cries/wugtrio.wav differ diff --git a/sound/direct_sound_samples/cries/wurmple.aif b/sound/direct_sound_samples/cries/wurmple.aif deleted file mode 100644 index 1754d7e2b7..0000000000 Binary files a/sound/direct_sound_samples/cries/wurmple.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/wurmple.wav b/sound/direct_sound_samples/cries/wurmple.wav new file mode 100644 index 0000000000..b58d5007cf Binary files /dev/null and b/sound/direct_sound_samples/cries/wurmple.wav differ diff --git a/sound/direct_sound_samples/cries/wynaut.aif b/sound/direct_sound_samples/cries/wynaut.aif deleted file mode 100644 index ddd289f9a4..0000000000 Binary files a/sound/direct_sound_samples/cries/wynaut.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/wynaut.wav b/sound/direct_sound_samples/cries/wynaut.wav new file mode 100644 index 0000000000..6febe26aa4 Binary files /dev/null and b/sound/direct_sound_samples/cries/wynaut.wav differ diff --git a/sound/direct_sound_samples/cries/wyrdeer.aif b/sound/direct_sound_samples/cries/wyrdeer.aif deleted file mode 100644 index 597df62ab8..0000000000 Binary files a/sound/direct_sound_samples/cries/wyrdeer.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/wyrdeer.wav b/sound/direct_sound_samples/cries/wyrdeer.wav new file mode 100644 index 0000000000..50bba2a433 Binary files /dev/null and b/sound/direct_sound_samples/cries/wyrdeer.wav differ diff --git a/sound/direct_sound_samples/cries/xatu.aif b/sound/direct_sound_samples/cries/xatu.aif deleted file mode 100644 index da4afe62ca..0000000000 Binary files a/sound/direct_sound_samples/cries/xatu.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/xatu.wav b/sound/direct_sound_samples/cries/xatu.wav new file mode 100644 index 0000000000..7c84f65723 Binary files /dev/null and b/sound/direct_sound_samples/cries/xatu.wav differ diff --git a/sound/direct_sound_samples/cries/xerneas.aif b/sound/direct_sound_samples/cries/xerneas.aif deleted file mode 100644 index 4745e8e685..0000000000 Binary files a/sound/direct_sound_samples/cries/xerneas.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/xerneas.wav b/sound/direct_sound_samples/cries/xerneas.wav new file mode 100644 index 0000000000..f08dd0ca93 Binary files /dev/null and b/sound/direct_sound_samples/cries/xerneas.wav differ diff --git a/sound/direct_sound_samples/cries/xurkitree.aif b/sound/direct_sound_samples/cries/xurkitree.aif deleted file mode 100644 index 3b0f5f3812..0000000000 Binary files a/sound/direct_sound_samples/cries/xurkitree.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/xurkitree.wav b/sound/direct_sound_samples/cries/xurkitree.wav new file mode 100644 index 0000000000..2c521b1f2c Binary files /dev/null and b/sound/direct_sound_samples/cries/xurkitree.wav differ diff --git a/sound/direct_sound_samples/cries/yamask.aif b/sound/direct_sound_samples/cries/yamask.aif deleted file mode 100644 index 51f07034b8..0000000000 Binary files a/sound/direct_sound_samples/cries/yamask.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/yamask.wav b/sound/direct_sound_samples/cries/yamask.wav new file mode 100644 index 0000000000..e04533c5af Binary files /dev/null and b/sound/direct_sound_samples/cries/yamask.wav differ diff --git a/sound/direct_sound_samples/cries/yamper.aif b/sound/direct_sound_samples/cries/yamper.aif deleted file mode 100644 index c57246e4ad..0000000000 Binary files a/sound/direct_sound_samples/cries/yamper.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/yamper.wav b/sound/direct_sound_samples/cries/yamper.wav new file mode 100644 index 0000000000..ad8491f1f1 Binary files /dev/null and b/sound/direct_sound_samples/cries/yamper.wav differ diff --git a/sound/direct_sound_samples/cries/yanma.aif b/sound/direct_sound_samples/cries/yanma.aif deleted file mode 100644 index 3d8354bb59..0000000000 Binary files a/sound/direct_sound_samples/cries/yanma.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/yanma.wav b/sound/direct_sound_samples/cries/yanma.wav new file mode 100644 index 0000000000..166b373616 Binary files /dev/null and b/sound/direct_sound_samples/cries/yanma.wav differ diff --git a/sound/direct_sound_samples/cries/yanmega.aif b/sound/direct_sound_samples/cries/yanmega.aif deleted file mode 100644 index 6f3a3eb2dd..0000000000 Binary files a/sound/direct_sound_samples/cries/yanmega.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/yanmega.wav b/sound/direct_sound_samples/cries/yanmega.wav new file mode 100644 index 0000000000..b464686713 Binary files /dev/null and b/sound/direct_sound_samples/cries/yanmega.wav differ diff --git a/sound/direct_sound_samples/cries/yungoos.aif b/sound/direct_sound_samples/cries/yungoos.aif deleted file mode 100644 index 13b633a98a..0000000000 Binary files a/sound/direct_sound_samples/cries/yungoos.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/yungoos.wav b/sound/direct_sound_samples/cries/yungoos.wav new file mode 100644 index 0000000000..94a83e9223 Binary files /dev/null and b/sound/direct_sound_samples/cries/yungoos.wav differ diff --git a/sound/direct_sound_samples/cries/yveltal.aif b/sound/direct_sound_samples/cries/yveltal.aif deleted file mode 100644 index 3c2bbcb021..0000000000 Binary files a/sound/direct_sound_samples/cries/yveltal.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/yveltal.wav b/sound/direct_sound_samples/cries/yveltal.wav new file mode 100644 index 0000000000..5bc4fec4fe Binary files /dev/null and b/sound/direct_sound_samples/cries/yveltal.wav differ diff --git a/sound/direct_sound_samples/cries/zacian_crowned_sword.aif b/sound/direct_sound_samples/cries/zacian_crowned_sword.aif deleted file mode 100644 index 597c5ddd26..0000000000 Binary files a/sound/direct_sound_samples/cries/zacian_crowned_sword.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/zacian_crowned_sword.wav b/sound/direct_sound_samples/cries/zacian_crowned_sword.wav new file mode 100644 index 0000000000..ee135a12bc Binary files /dev/null and b/sound/direct_sound_samples/cries/zacian_crowned_sword.wav differ diff --git a/sound/direct_sound_samples/cries/zacian_hero_of_many_battles.aif b/sound/direct_sound_samples/cries/zacian_hero_of_many_battles.aif deleted file mode 100644 index f67d857332..0000000000 Binary files a/sound/direct_sound_samples/cries/zacian_hero_of_many_battles.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/zacian_hero_of_many_battles.wav b/sound/direct_sound_samples/cries/zacian_hero_of_many_battles.wav new file mode 100644 index 0000000000..d3354b55a2 Binary files /dev/null and b/sound/direct_sound_samples/cries/zacian_hero_of_many_battles.wav differ diff --git a/sound/direct_sound_samples/cries/zamazenta_crowned_shield.aif b/sound/direct_sound_samples/cries/zamazenta_crowned_shield.aif deleted file mode 100644 index 05d170baba..0000000000 Binary files a/sound/direct_sound_samples/cries/zamazenta_crowned_shield.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/zamazenta_crowned_shield.wav b/sound/direct_sound_samples/cries/zamazenta_crowned_shield.wav new file mode 100644 index 0000000000..f4fad6e6b0 Binary files /dev/null and b/sound/direct_sound_samples/cries/zamazenta_crowned_shield.wav differ diff --git a/sound/direct_sound_samples/cries/zamazenta_hero_of_many_battles.aif b/sound/direct_sound_samples/cries/zamazenta_hero_of_many_battles.aif deleted file mode 100644 index 3674b2937f..0000000000 Binary files a/sound/direct_sound_samples/cries/zamazenta_hero_of_many_battles.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/zamazenta_hero_of_many_battles.wav b/sound/direct_sound_samples/cries/zamazenta_hero_of_many_battles.wav new file mode 100644 index 0000000000..50c1b217a0 Binary files /dev/null and b/sound/direct_sound_samples/cries/zamazenta_hero_of_many_battles.wav differ diff --git a/sound/direct_sound_samples/cries/zangoose.aif b/sound/direct_sound_samples/cries/zangoose.aif deleted file mode 100644 index dc6182b784..0000000000 Binary files a/sound/direct_sound_samples/cries/zangoose.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/zangoose.wav b/sound/direct_sound_samples/cries/zangoose.wav new file mode 100644 index 0000000000..b1e3e9ffc3 Binary files /dev/null and b/sound/direct_sound_samples/cries/zangoose.wav differ diff --git a/sound/direct_sound_samples/cries/zapdos.aif b/sound/direct_sound_samples/cries/zapdos.aif deleted file mode 100644 index 83bbd043e4..0000000000 Binary files a/sound/direct_sound_samples/cries/zapdos.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/zapdos.wav b/sound/direct_sound_samples/cries/zapdos.wav new file mode 100644 index 0000000000..58415b9344 Binary files /dev/null and b/sound/direct_sound_samples/cries/zapdos.wav differ diff --git a/sound/direct_sound_samples/cries/zarude.aif b/sound/direct_sound_samples/cries/zarude.aif deleted file mode 100644 index d1a2a76aa4..0000000000 Binary files a/sound/direct_sound_samples/cries/zarude.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/zarude.wav b/sound/direct_sound_samples/cries/zarude.wav new file mode 100644 index 0000000000..252ff52573 Binary files /dev/null and b/sound/direct_sound_samples/cries/zarude.wav differ diff --git a/sound/direct_sound_samples/cries/zebstrika.aif b/sound/direct_sound_samples/cries/zebstrika.aif deleted file mode 100644 index 0609b145b2..0000000000 Binary files a/sound/direct_sound_samples/cries/zebstrika.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/zebstrika.wav b/sound/direct_sound_samples/cries/zebstrika.wav new file mode 100644 index 0000000000..f6f305f66c Binary files /dev/null and b/sound/direct_sound_samples/cries/zebstrika.wav differ diff --git a/sound/direct_sound_samples/cries/zekrom.aif b/sound/direct_sound_samples/cries/zekrom.aif deleted file mode 100644 index dd74f80911..0000000000 Binary files a/sound/direct_sound_samples/cries/zekrom.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/zekrom.wav b/sound/direct_sound_samples/cries/zekrom.wav new file mode 100644 index 0000000000..61a2b1e6c3 Binary files /dev/null and b/sound/direct_sound_samples/cries/zekrom.wav differ diff --git a/sound/direct_sound_samples/cries/zeraora.aif b/sound/direct_sound_samples/cries/zeraora.aif deleted file mode 100644 index b1455a0100..0000000000 Binary files a/sound/direct_sound_samples/cries/zeraora.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/zeraora.wav b/sound/direct_sound_samples/cries/zeraora.wav new file mode 100644 index 0000000000..570cb398bb Binary files /dev/null and b/sound/direct_sound_samples/cries/zeraora.wav differ diff --git a/sound/direct_sound_samples/cries/zigzagoon.aif b/sound/direct_sound_samples/cries/zigzagoon.aif deleted file mode 100644 index 8f7b32f818..0000000000 Binary files a/sound/direct_sound_samples/cries/zigzagoon.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/zigzagoon.wav b/sound/direct_sound_samples/cries/zigzagoon.wav new file mode 100644 index 0000000000..ac0b68edcd Binary files /dev/null and b/sound/direct_sound_samples/cries/zigzagoon.wav differ diff --git a/sound/direct_sound_samples/cries/zoroark.aif b/sound/direct_sound_samples/cries/zoroark.aif deleted file mode 100644 index 91e7ab0ce9..0000000000 Binary files a/sound/direct_sound_samples/cries/zoroark.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/zoroark.wav b/sound/direct_sound_samples/cries/zoroark.wav new file mode 100644 index 0000000000..34b6f1241d Binary files /dev/null and b/sound/direct_sound_samples/cries/zoroark.wav differ diff --git a/sound/direct_sound_samples/cries/zorua.aif b/sound/direct_sound_samples/cries/zorua.aif deleted file mode 100644 index 674681f5bc..0000000000 Binary files a/sound/direct_sound_samples/cries/zorua.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/zorua.wav b/sound/direct_sound_samples/cries/zorua.wav new file mode 100644 index 0000000000..fe7c4ed8c6 Binary files /dev/null and b/sound/direct_sound_samples/cries/zorua.wav differ diff --git a/sound/direct_sound_samples/cries/zubat.aif b/sound/direct_sound_samples/cries/zubat.aif deleted file mode 100644 index 9ba4d36489..0000000000 Binary files a/sound/direct_sound_samples/cries/zubat.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/zubat.wav b/sound/direct_sound_samples/cries/zubat.wav new file mode 100644 index 0000000000..dc0756a06d Binary files /dev/null and b/sound/direct_sound_samples/cries/zubat.wav differ diff --git a/sound/direct_sound_samples/cries/zweilous.aif b/sound/direct_sound_samples/cries/zweilous.aif deleted file mode 100644 index fc9a366ce9..0000000000 Binary files a/sound/direct_sound_samples/cries/zweilous.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/zweilous.wav b/sound/direct_sound_samples/cries/zweilous.wav new file mode 100644 index 0000000000..5474c4681c Binary files /dev/null and b/sound/direct_sound_samples/cries/zweilous.wav differ diff --git a/sound/direct_sound_samples/cries/zygarde_10.aif b/sound/direct_sound_samples/cries/zygarde_10.aif deleted file mode 100644 index a8301cdc16..0000000000 Binary files a/sound/direct_sound_samples/cries/zygarde_10.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/zygarde_10.wav b/sound/direct_sound_samples/cries/zygarde_10.wav new file mode 100644 index 0000000000..da90abe5bb Binary files /dev/null and b/sound/direct_sound_samples/cries/zygarde_10.wav differ diff --git a/sound/direct_sound_samples/cries/zygarde_50.aif b/sound/direct_sound_samples/cries/zygarde_50.aif deleted file mode 100644 index 92daba8bcb..0000000000 Binary files a/sound/direct_sound_samples/cries/zygarde_50.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/zygarde_50.wav b/sound/direct_sound_samples/cries/zygarde_50.wav new file mode 100644 index 0000000000..5bfe28b2ac Binary files /dev/null and b/sound/direct_sound_samples/cries/zygarde_50.wav differ diff --git a/sound/direct_sound_samples/cries/zygarde_complete.aif b/sound/direct_sound_samples/cries/zygarde_complete.aif deleted file mode 100644 index 2eae63203b..0000000000 Binary files a/sound/direct_sound_samples/cries/zygarde_complete.aif and /dev/null differ diff --git a/sound/direct_sound_samples/cries/zygarde_complete.wav b/sound/direct_sound_samples/cries/zygarde_complete.wav new file mode 100644 index 0000000000..5e295a0645 Binary files /dev/null and b/sound/direct_sound_samples/cries/zygarde_complete.wav differ diff --git a/sound/direct_sound_samples/dance_drums_ride_bell.aif b/sound/direct_sound_samples/dance_drums_ride_bell.aif deleted file mode 100644 index db36a54bd0..0000000000 Binary files a/sound/direct_sound_samples/dance_drums_ride_bell.aif and /dev/null differ diff --git a/sound/direct_sound_samples/dance_drums_ride_bell.wav b/sound/direct_sound_samples/dance_drums_ride_bell.wav new file mode 100644 index 0000000000..a79a5c26f9 Binary files /dev/null and b/sound/direct_sound_samples/dance_drums_ride_bell.wav differ diff --git a/sound/direct_sound_samples/drum_and_percussion_kick.aif b/sound/direct_sound_samples/drum_and_percussion_kick.aif deleted file mode 100644 index 628421990e..0000000000 Binary files a/sound/direct_sound_samples/drum_and_percussion_kick.aif and /dev/null differ diff --git a/sound/direct_sound_samples/drum_and_percussion_kick.wav b/sound/direct_sound_samples/drum_and_percussion_kick.wav new file mode 100644 index 0000000000..49ba617f0c Binary files /dev/null and b/sound/direct_sound_samples/drum_and_percussion_kick.wav differ diff --git a/sound/direct_sound_samples/ethnic_flavours_atarigane.aif b/sound/direct_sound_samples/ethnic_flavours_atarigane.aif deleted file mode 100644 index 4a4268210e..0000000000 Binary files a/sound/direct_sound_samples/ethnic_flavours_atarigane.aif and /dev/null differ diff --git a/sound/direct_sound_samples/ethnic_flavours_atarigane.wav b/sound/direct_sound_samples/ethnic_flavours_atarigane.wav new file mode 100644 index 0000000000..d1fb2c1a4f Binary files /dev/null and b/sound/direct_sound_samples/ethnic_flavours_atarigane.wav differ diff --git a/sound/direct_sound_samples/ethnic_flavours_hyoushigi.aif b/sound/direct_sound_samples/ethnic_flavours_hyoushigi.aif deleted file mode 100644 index 5219bdf5d5..0000000000 Binary files a/sound/direct_sound_samples/ethnic_flavours_hyoushigi.aif and /dev/null differ diff --git a/sound/direct_sound_samples/ethnic_flavours_hyoushigi.wav b/sound/direct_sound_samples/ethnic_flavours_hyoushigi.wav new file mode 100644 index 0000000000..18731f5034 Binary files /dev/null and b/sound/direct_sound_samples/ethnic_flavours_hyoushigi.wav differ diff --git a/sound/direct_sound_samples/ethnic_flavours_kotsuzumi.aif b/sound/direct_sound_samples/ethnic_flavours_kotsuzumi.aif deleted file mode 100644 index 1696bd02e0..0000000000 Binary files a/sound/direct_sound_samples/ethnic_flavours_kotsuzumi.aif and /dev/null differ diff --git a/sound/direct_sound_samples/ethnic_flavours_kotsuzumi.wav b/sound/direct_sound_samples/ethnic_flavours_kotsuzumi.wav new file mode 100644 index 0000000000..5c99fedf38 Binary files /dev/null and b/sound/direct_sound_samples/ethnic_flavours_kotsuzumi.wav differ diff --git a/sound/direct_sound_samples/ethnic_flavours_ohtsuzumi.aif b/sound/direct_sound_samples/ethnic_flavours_ohtsuzumi.aif deleted file mode 100644 index 69267ca1c6..0000000000 Binary files a/sound/direct_sound_samples/ethnic_flavours_ohtsuzumi.aif and /dev/null differ diff --git a/sound/direct_sound_samples/ethnic_flavours_ohtsuzumi.wav b/sound/direct_sound_samples/ethnic_flavours_ohtsuzumi.wav new file mode 100644 index 0000000000..c12ae6de34 Binary files /dev/null and b/sound/direct_sound_samples/ethnic_flavours_ohtsuzumi.wav differ diff --git a/sound/direct_sound_samples/heart_of_asia_gamelan.aif b/sound/direct_sound_samples/heart_of_asia_gamelan.aif deleted file mode 100644 index adaf6a0c53..0000000000 Binary files a/sound/direct_sound_samples/heart_of_asia_gamelan.aif and /dev/null differ diff --git a/sound/direct_sound_samples/heart_of_asia_gamelan.wav b/sound/direct_sound_samples/heart_of_asia_gamelan.wav new file mode 100644 index 0000000000..a6258c97d4 Binary files /dev/null and b/sound/direct_sound_samples/heart_of_asia_gamelan.wav differ diff --git a/sound/direct_sound_samples/phonemes/01.aif b/sound/direct_sound_samples/phonemes/01.aif deleted file mode 100644 index 4b15a94b77..0000000000 Binary files a/sound/direct_sound_samples/phonemes/01.aif and /dev/null differ diff --git a/sound/direct_sound_samples/phonemes/01.wav b/sound/direct_sound_samples/phonemes/01.wav new file mode 100644 index 0000000000..d7f43544f5 Binary files /dev/null and b/sound/direct_sound_samples/phonemes/01.wav differ diff --git a/sound/direct_sound_samples/phonemes/02.aif b/sound/direct_sound_samples/phonemes/02.aif deleted file mode 100644 index 74c1290730..0000000000 Binary files a/sound/direct_sound_samples/phonemes/02.aif and /dev/null differ diff --git a/sound/direct_sound_samples/phonemes/02.wav b/sound/direct_sound_samples/phonemes/02.wav new file mode 100644 index 0000000000..6b9e4134c8 Binary files /dev/null and b/sound/direct_sound_samples/phonemes/02.wav differ diff --git a/sound/direct_sound_samples/phonemes/03.aif b/sound/direct_sound_samples/phonemes/03.aif deleted file mode 100644 index 359972c169..0000000000 Binary files a/sound/direct_sound_samples/phonemes/03.aif and /dev/null differ diff --git a/sound/direct_sound_samples/phonemes/03.wav b/sound/direct_sound_samples/phonemes/03.wav new file mode 100644 index 0000000000..a080496adb Binary files /dev/null and b/sound/direct_sound_samples/phonemes/03.wav differ diff --git a/sound/direct_sound_samples/phonemes/04.aif b/sound/direct_sound_samples/phonemes/04.aif deleted file mode 100644 index 3b136fa434..0000000000 Binary files a/sound/direct_sound_samples/phonemes/04.aif and /dev/null differ diff --git a/sound/direct_sound_samples/phonemes/04.wav b/sound/direct_sound_samples/phonemes/04.wav new file mode 100644 index 0000000000..0525f8f5d3 Binary files /dev/null and b/sound/direct_sound_samples/phonemes/04.wav differ diff --git a/sound/direct_sound_samples/phonemes/05.aif b/sound/direct_sound_samples/phonemes/05.aif deleted file mode 100644 index fd72512cf1..0000000000 Binary files a/sound/direct_sound_samples/phonemes/05.aif and /dev/null differ diff --git a/sound/direct_sound_samples/phonemes/05.wav b/sound/direct_sound_samples/phonemes/05.wav new file mode 100644 index 0000000000..5df5562768 Binary files /dev/null and b/sound/direct_sound_samples/phonemes/05.wav differ diff --git a/sound/direct_sound_samples/phonemes/06.aif b/sound/direct_sound_samples/phonemes/06.aif deleted file mode 100644 index 6f7794bec8..0000000000 Binary files a/sound/direct_sound_samples/phonemes/06.aif and /dev/null differ diff --git a/sound/direct_sound_samples/phonemes/06.wav b/sound/direct_sound_samples/phonemes/06.wav new file mode 100644 index 0000000000..3774664d97 Binary files /dev/null and b/sound/direct_sound_samples/phonemes/06.wav differ diff --git a/sound/direct_sound_samples/phonemes/07.aif b/sound/direct_sound_samples/phonemes/07.aif deleted file mode 100644 index 89b845f21b..0000000000 Binary files a/sound/direct_sound_samples/phonemes/07.aif and /dev/null differ diff --git a/sound/direct_sound_samples/phonemes/07.wav b/sound/direct_sound_samples/phonemes/07.wav new file mode 100644 index 0000000000..fc44b7f771 Binary files /dev/null and b/sound/direct_sound_samples/phonemes/07.wav differ diff --git a/sound/direct_sound_samples/phonemes/08.aif b/sound/direct_sound_samples/phonemes/08.aif deleted file mode 100644 index 1d99a3a932..0000000000 Binary files a/sound/direct_sound_samples/phonemes/08.aif and /dev/null differ diff --git a/sound/direct_sound_samples/phonemes/08.wav b/sound/direct_sound_samples/phonemes/08.wav new file mode 100644 index 0000000000..47c50d63b0 Binary files /dev/null and b/sound/direct_sound_samples/phonemes/08.wav differ diff --git a/sound/direct_sound_samples/phonemes/09.aif b/sound/direct_sound_samples/phonemes/09.aif deleted file mode 100644 index 8833981298..0000000000 Binary files a/sound/direct_sound_samples/phonemes/09.aif and /dev/null differ diff --git a/sound/direct_sound_samples/phonemes/09.wav b/sound/direct_sound_samples/phonemes/09.wav new file mode 100644 index 0000000000..762ece0dd8 Binary files /dev/null and b/sound/direct_sound_samples/phonemes/09.wav differ diff --git a/sound/direct_sound_samples/phonemes/10.aif b/sound/direct_sound_samples/phonemes/10.aif deleted file mode 100644 index 776815e636..0000000000 Binary files a/sound/direct_sound_samples/phonemes/10.aif and /dev/null differ diff --git a/sound/direct_sound_samples/phonemes/10.wav b/sound/direct_sound_samples/phonemes/10.wav new file mode 100644 index 0000000000..da9fa6727c Binary files /dev/null and b/sound/direct_sound_samples/phonemes/10.wav differ diff --git a/sound/direct_sound_samples/phonemes/11.aif b/sound/direct_sound_samples/phonemes/11.aif deleted file mode 100644 index 545bd12920..0000000000 Binary files a/sound/direct_sound_samples/phonemes/11.aif and /dev/null differ diff --git a/sound/direct_sound_samples/phonemes/11.wav b/sound/direct_sound_samples/phonemes/11.wav new file mode 100644 index 0000000000..5cd1904b42 Binary files /dev/null and b/sound/direct_sound_samples/phonemes/11.wav differ diff --git a/sound/direct_sound_samples/phonemes/12.aif b/sound/direct_sound_samples/phonemes/12.aif deleted file mode 100644 index c0a3be10d0..0000000000 Binary files a/sound/direct_sound_samples/phonemes/12.aif and /dev/null differ diff --git a/sound/direct_sound_samples/phonemes/12.wav b/sound/direct_sound_samples/phonemes/12.wav new file mode 100644 index 0000000000..da638d82b0 Binary files /dev/null and b/sound/direct_sound_samples/phonemes/12.wav differ diff --git a/sound/direct_sound_samples/phonemes/13.aif b/sound/direct_sound_samples/phonemes/13.aif deleted file mode 100644 index d26ecdd6de..0000000000 Binary files a/sound/direct_sound_samples/phonemes/13.aif and /dev/null differ diff --git a/sound/direct_sound_samples/phonemes/13.wav b/sound/direct_sound_samples/phonemes/13.wav new file mode 100644 index 0000000000..2eb58a5f3f Binary files /dev/null and b/sound/direct_sound_samples/phonemes/13.wav differ diff --git a/sound/direct_sound_samples/phonemes/14.aif b/sound/direct_sound_samples/phonemes/14.aif deleted file mode 100644 index 2b51201a48..0000000000 Binary files a/sound/direct_sound_samples/phonemes/14.aif and /dev/null differ diff --git a/sound/direct_sound_samples/phonemes/14.wav b/sound/direct_sound_samples/phonemes/14.wav new file mode 100644 index 0000000000..fef0bb0ded Binary files /dev/null and b/sound/direct_sound_samples/phonemes/14.wav differ diff --git a/sound/direct_sound_samples/phonemes/15.aif b/sound/direct_sound_samples/phonemes/15.aif deleted file mode 100644 index cf5ac4e038..0000000000 Binary files a/sound/direct_sound_samples/phonemes/15.aif and /dev/null differ diff --git a/sound/direct_sound_samples/phonemes/15.wav b/sound/direct_sound_samples/phonemes/15.wav new file mode 100644 index 0000000000..1dbe8cbfa3 Binary files /dev/null and b/sound/direct_sound_samples/phonemes/15.wav differ diff --git a/sound/direct_sound_samples/phonemes/16.aif b/sound/direct_sound_samples/phonemes/16.aif deleted file mode 100644 index 606742e608..0000000000 Binary files a/sound/direct_sound_samples/phonemes/16.aif and /dev/null differ diff --git a/sound/direct_sound_samples/phonemes/16.wav b/sound/direct_sound_samples/phonemes/16.wav new file mode 100644 index 0000000000..83f1818582 Binary files /dev/null and b/sound/direct_sound_samples/phonemes/16.wav differ diff --git a/sound/direct_sound_samples/phonemes/17.aif b/sound/direct_sound_samples/phonemes/17.aif deleted file mode 100644 index 71d4987d64..0000000000 Binary files a/sound/direct_sound_samples/phonemes/17.aif and /dev/null differ diff --git a/sound/direct_sound_samples/phonemes/17.wav b/sound/direct_sound_samples/phonemes/17.wav new file mode 100644 index 0000000000..ad55b8bda5 Binary files /dev/null and b/sound/direct_sound_samples/phonemes/17.wav differ diff --git a/sound/direct_sound_samples/phonemes/18.aif b/sound/direct_sound_samples/phonemes/18.aif deleted file mode 100644 index 070c44a37c..0000000000 Binary files a/sound/direct_sound_samples/phonemes/18.aif and /dev/null differ diff --git a/sound/direct_sound_samples/phonemes/18.wav b/sound/direct_sound_samples/phonemes/18.wav new file mode 100644 index 0000000000..ecadb6f608 Binary files /dev/null and b/sound/direct_sound_samples/phonemes/18.wav differ diff --git a/sound/direct_sound_samples/phonemes/19.aif b/sound/direct_sound_samples/phonemes/19.aif deleted file mode 100644 index b0ca84a38f..0000000000 Binary files a/sound/direct_sound_samples/phonemes/19.aif and /dev/null differ diff --git a/sound/direct_sound_samples/phonemes/19.wav b/sound/direct_sound_samples/phonemes/19.wav new file mode 100644 index 0000000000..ff905abe22 Binary files /dev/null and b/sound/direct_sound_samples/phonemes/19.wav differ diff --git a/sound/direct_sound_samples/phonemes/20.aif b/sound/direct_sound_samples/phonemes/20.aif deleted file mode 100644 index f44101b23c..0000000000 Binary files a/sound/direct_sound_samples/phonemes/20.aif and /dev/null differ diff --git a/sound/direct_sound_samples/phonemes/20.wav b/sound/direct_sound_samples/phonemes/20.wav new file mode 100644 index 0000000000..595702e084 Binary files /dev/null and b/sound/direct_sound_samples/phonemes/20.wav differ diff --git a/sound/direct_sound_samples/phonemes/21.aif b/sound/direct_sound_samples/phonemes/21.aif deleted file mode 100644 index a33809d423..0000000000 Binary files a/sound/direct_sound_samples/phonemes/21.aif and /dev/null differ diff --git a/sound/direct_sound_samples/phonemes/21.wav b/sound/direct_sound_samples/phonemes/21.wav new file mode 100644 index 0000000000..7d1709212c Binary files /dev/null and b/sound/direct_sound_samples/phonemes/21.wav differ diff --git a/sound/direct_sound_samples/phonemes/22.aif b/sound/direct_sound_samples/phonemes/22.aif deleted file mode 100644 index 6a005efccf..0000000000 Binary files a/sound/direct_sound_samples/phonemes/22.aif and /dev/null differ diff --git a/sound/direct_sound_samples/phonemes/22.wav b/sound/direct_sound_samples/phonemes/22.wav new file mode 100644 index 0000000000..274f6137aa Binary files /dev/null and b/sound/direct_sound_samples/phonemes/22.wav differ diff --git a/sound/direct_sound_samples/phonemes/23.aif b/sound/direct_sound_samples/phonemes/23.aif deleted file mode 100644 index 62f9493fdb..0000000000 Binary files a/sound/direct_sound_samples/phonemes/23.aif and /dev/null differ diff --git a/sound/direct_sound_samples/phonemes/23.wav b/sound/direct_sound_samples/phonemes/23.wav new file mode 100644 index 0000000000..72633f73c1 Binary files /dev/null and b/sound/direct_sound_samples/phonemes/23.wav differ diff --git a/sound/direct_sound_samples/phonemes/24.aif b/sound/direct_sound_samples/phonemes/24.aif deleted file mode 100644 index 5767bd6d9a..0000000000 Binary files a/sound/direct_sound_samples/phonemes/24.aif and /dev/null differ diff --git a/sound/direct_sound_samples/phonemes/24.wav b/sound/direct_sound_samples/phonemes/24.wav new file mode 100644 index 0000000000..1d0e7b1a14 Binary files /dev/null and b/sound/direct_sound_samples/phonemes/24.wav differ diff --git a/sound/direct_sound_samples/phonemes/25.aif b/sound/direct_sound_samples/phonemes/25.aif deleted file mode 100644 index 33e328a82e..0000000000 Binary files a/sound/direct_sound_samples/phonemes/25.aif and /dev/null differ diff --git a/sound/direct_sound_samples/phonemes/25.wav b/sound/direct_sound_samples/phonemes/25.wav new file mode 100644 index 0000000000..135bb246dd Binary files /dev/null and b/sound/direct_sound_samples/phonemes/25.wav differ diff --git a/sound/direct_sound_samples/phonemes/26.aif b/sound/direct_sound_samples/phonemes/26.aif deleted file mode 100644 index 548e740c8d..0000000000 Binary files a/sound/direct_sound_samples/phonemes/26.aif and /dev/null differ diff --git a/sound/direct_sound_samples/phonemes/26.wav b/sound/direct_sound_samples/phonemes/26.wav new file mode 100644 index 0000000000..e466df4d86 Binary files /dev/null and b/sound/direct_sound_samples/phonemes/26.wav differ diff --git a/sound/direct_sound_samples/phonemes/27.aif b/sound/direct_sound_samples/phonemes/27.aif deleted file mode 100644 index cbbe09266a..0000000000 Binary files a/sound/direct_sound_samples/phonemes/27.aif and /dev/null differ diff --git a/sound/direct_sound_samples/phonemes/27.wav b/sound/direct_sound_samples/phonemes/27.wav new file mode 100644 index 0000000000..c4d4ce8008 Binary files /dev/null and b/sound/direct_sound_samples/phonemes/27.wav differ diff --git a/sound/direct_sound_samples/phonemes/28.aif b/sound/direct_sound_samples/phonemes/28.aif deleted file mode 100644 index 8bdf7faaae..0000000000 Binary files a/sound/direct_sound_samples/phonemes/28.aif and /dev/null differ diff --git a/sound/direct_sound_samples/phonemes/28.wav b/sound/direct_sound_samples/phonemes/28.wav new file mode 100644 index 0000000000..fe9dde8e35 Binary files /dev/null and b/sound/direct_sound_samples/phonemes/28.wav differ diff --git a/sound/direct_sound_samples/phonemes/29.aif b/sound/direct_sound_samples/phonemes/29.aif deleted file mode 100644 index f96f8853b2..0000000000 Binary files a/sound/direct_sound_samples/phonemes/29.aif and /dev/null differ diff --git a/sound/direct_sound_samples/phonemes/29.wav b/sound/direct_sound_samples/phonemes/29.wav new file mode 100644 index 0000000000..d05658c97e Binary files /dev/null and b/sound/direct_sound_samples/phonemes/29.wav differ diff --git a/sound/direct_sound_samples/phonemes/30.aif b/sound/direct_sound_samples/phonemes/30.aif deleted file mode 100644 index ab9abbf795..0000000000 Binary files a/sound/direct_sound_samples/phonemes/30.aif and /dev/null differ diff --git a/sound/direct_sound_samples/phonemes/30.wav b/sound/direct_sound_samples/phonemes/30.wav new file mode 100644 index 0000000000..aaf163ae97 Binary files /dev/null and b/sound/direct_sound_samples/phonemes/30.wav differ diff --git a/sound/direct_sound_samples/phonemes/31.aif b/sound/direct_sound_samples/phonemes/31.aif deleted file mode 100644 index 9d21d0ab49..0000000000 Binary files a/sound/direct_sound_samples/phonemes/31.aif and /dev/null differ diff --git a/sound/direct_sound_samples/phonemes/31.wav b/sound/direct_sound_samples/phonemes/31.wav new file mode 100644 index 0000000000..64b2c7f6db Binary files /dev/null and b/sound/direct_sound_samples/phonemes/31.wav differ diff --git a/sound/direct_sound_samples/phonemes/32.aif b/sound/direct_sound_samples/phonemes/32.aif deleted file mode 100644 index c037ed4afc..0000000000 Binary files a/sound/direct_sound_samples/phonemes/32.aif and /dev/null differ diff --git a/sound/direct_sound_samples/phonemes/32.wav b/sound/direct_sound_samples/phonemes/32.wav new file mode 100644 index 0000000000..98862f1b64 Binary files /dev/null and b/sound/direct_sound_samples/phonemes/32.wav differ diff --git a/sound/direct_sound_samples/phonemes/33.aif b/sound/direct_sound_samples/phonemes/33.aif deleted file mode 100644 index ac1f8b66f0..0000000000 Binary files a/sound/direct_sound_samples/phonemes/33.aif and /dev/null differ diff --git a/sound/direct_sound_samples/phonemes/33.wav b/sound/direct_sound_samples/phonemes/33.wav new file mode 100644 index 0000000000..f96a5e49fd Binary files /dev/null and b/sound/direct_sound_samples/phonemes/33.wav differ diff --git a/sound/direct_sound_samples/phonemes/34.aif b/sound/direct_sound_samples/phonemes/34.aif deleted file mode 100644 index 1fd9111c8b..0000000000 Binary files a/sound/direct_sound_samples/phonemes/34.aif and /dev/null differ diff --git a/sound/direct_sound_samples/phonemes/34.wav b/sound/direct_sound_samples/phonemes/34.wav new file mode 100644 index 0000000000..1439810d44 Binary files /dev/null and b/sound/direct_sound_samples/phonemes/34.wav differ diff --git a/sound/direct_sound_samples/phonemes/35.aif b/sound/direct_sound_samples/phonemes/35.aif deleted file mode 100644 index 5d6ae2282f..0000000000 Binary files a/sound/direct_sound_samples/phonemes/35.aif and /dev/null differ diff --git a/sound/direct_sound_samples/phonemes/35.wav b/sound/direct_sound_samples/phonemes/35.wav new file mode 100644 index 0000000000..aa6599bcc8 Binary files /dev/null and b/sound/direct_sound_samples/phonemes/35.wav differ diff --git a/sound/direct_sound_samples/phonemes/36.aif b/sound/direct_sound_samples/phonemes/36.aif deleted file mode 100644 index f267006907..0000000000 Binary files a/sound/direct_sound_samples/phonemes/36.aif and /dev/null differ diff --git a/sound/direct_sound_samples/phonemes/36.wav b/sound/direct_sound_samples/phonemes/36.wav new file mode 100644 index 0000000000..59f90f4614 Binary files /dev/null and b/sound/direct_sound_samples/phonemes/36.wav differ diff --git a/sound/direct_sound_samples/phonemes/37.aif b/sound/direct_sound_samples/phonemes/37.aif deleted file mode 100644 index 3ba97a9fc3..0000000000 Binary files a/sound/direct_sound_samples/phonemes/37.aif and /dev/null differ diff --git a/sound/direct_sound_samples/phonemes/37.wav b/sound/direct_sound_samples/phonemes/37.wav new file mode 100644 index 0000000000..4df9cffee6 Binary files /dev/null and b/sound/direct_sound_samples/phonemes/37.wav differ diff --git a/sound/direct_sound_samples/phonemes/38.aif b/sound/direct_sound_samples/phonemes/38.aif deleted file mode 100644 index 37f1be4b14..0000000000 Binary files a/sound/direct_sound_samples/phonemes/38.aif and /dev/null differ diff --git a/sound/direct_sound_samples/phonemes/38.wav b/sound/direct_sound_samples/phonemes/38.wav new file mode 100644 index 0000000000..759a23d514 Binary files /dev/null and b/sound/direct_sound_samples/phonemes/38.wav differ diff --git a/sound/direct_sound_samples/phonemes/39.aif b/sound/direct_sound_samples/phonemes/39.aif deleted file mode 100644 index 4b3facb99a..0000000000 Binary files a/sound/direct_sound_samples/phonemes/39.aif and /dev/null differ diff --git a/sound/direct_sound_samples/phonemes/39.wav b/sound/direct_sound_samples/phonemes/39.wav new file mode 100644 index 0000000000..da335b2690 Binary files /dev/null and b/sound/direct_sound_samples/phonemes/39.wav differ diff --git a/sound/direct_sound_samples/phonemes/40.aif b/sound/direct_sound_samples/phonemes/40.aif deleted file mode 100644 index 8a4d7653ba..0000000000 Binary files a/sound/direct_sound_samples/phonemes/40.aif and /dev/null differ diff --git a/sound/direct_sound_samples/phonemes/40.wav b/sound/direct_sound_samples/phonemes/40.wav new file mode 100644 index 0000000000..14944784a4 Binary files /dev/null and b/sound/direct_sound_samples/phonemes/40.wav differ diff --git a/sound/direct_sound_samples/phonemes/41.aif b/sound/direct_sound_samples/phonemes/41.aif deleted file mode 100644 index db5bae2449..0000000000 Binary files a/sound/direct_sound_samples/phonemes/41.aif and /dev/null differ diff --git a/sound/direct_sound_samples/phonemes/41.wav b/sound/direct_sound_samples/phonemes/41.wav new file mode 100644 index 0000000000..57e38fb3c8 Binary files /dev/null and b/sound/direct_sound_samples/phonemes/41.wav differ diff --git a/sound/direct_sound_samples/phonemes/42.aif b/sound/direct_sound_samples/phonemes/42.aif deleted file mode 100644 index 6612dd54db..0000000000 Binary files a/sound/direct_sound_samples/phonemes/42.aif and /dev/null differ diff --git a/sound/direct_sound_samples/phonemes/42.wav b/sound/direct_sound_samples/phonemes/42.wav new file mode 100644 index 0000000000..a990969146 Binary files /dev/null and b/sound/direct_sound_samples/phonemes/42.wav differ diff --git a/sound/direct_sound_samples/phonemes/43.aif b/sound/direct_sound_samples/phonemes/43.aif deleted file mode 100644 index 441eecfcda..0000000000 Binary files a/sound/direct_sound_samples/phonemes/43.aif and /dev/null differ diff --git a/sound/direct_sound_samples/phonemes/43.wav b/sound/direct_sound_samples/phonemes/43.wav new file mode 100644 index 0000000000..ab4a046743 Binary files /dev/null and b/sound/direct_sound_samples/phonemes/43.wav differ diff --git a/sound/direct_sound_samples/phonemes/44.aif b/sound/direct_sound_samples/phonemes/44.aif deleted file mode 100644 index 95670cf0a2..0000000000 Binary files a/sound/direct_sound_samples/phonemes/44.aif and /dev/null differ diff --git a/sound/direct_sound_samples/phonemes/44.wav b/sound/direct_sound_samples/phonemes/44.wav new file mode 100644 index 0000000000..efca4e3f97 Binary files /dev/null and b/sound/direct_sound_samples/phonemes/44.wav differ diff --git a/sound/direct_sound_samples/phonemes/45.aif b/sound/direct_sound_samples/phonemes/45.aif deleted file mode 100644 index 0fadcba8e8..0000000000 Binary files a/sound/direct_sound_samples/phonemes/45.aif and /dev/null differ diff --git a/sound/direct_sound_samples/phonemes/45.wav b/sound/direct_sound_samples/phonemes/45.wav new file mode 100644 index 0000000000..0369d3c2a1 Binary files /dev/null and b/sound/direct_sound_samples/phonemes/45.wav differ diff --git a/sound/direct_sound_samples/phonemes/46.aif b/sound/direct_sound_samples/phonemes/46.aif deleted file mode 100644 index 6017c55b4a..0000000000 Binary files a/sound/direct_sound_samples/phonemes/46.aif and /dev/null differ diff --git a/sound/direct_sound_samples/phonemes/46.wav b/sound/direct_sound_samples/phonemes/46.wav new file mode 100644 index 0000000000..0fa8eb1f88 Binary files /dev/null and b/sound/direct_sound_samples/phonemes/46.wav differ diff --git a/sound/direct_sound_samples/phonemes/47.aif b/sound/direct_sound_samples/phonemes/47.aif deleted file mode 100644 index 2327b6d657..0000000000 Binary files a/sound/direct_sound_samples/phonemes/47.aif and /dev/null differ diff --git a/sound/direct_sound_samples/phonemes/47.wav b/sound/direct_sound_samples/phonemes/47.wav new file mode 100644 index 0000000000..a55f03a153 Binary files /dev/null and b/sound/direct_sound_samples/phonemes/47.wav differ diff --git a/sound/direct_sound_samples/phonemes/48.aif b/sound/direct_sound_samples/phonemes/48.aif deleted file mode 100644 index 19ceca0d08..0000000000 Binary files a/sound/direct_sound_samples/phonemes/48.aif and /dev/null differ diff --git a/sound/direct_sound_samples/phonemes/48.wav b/sound/direct_sound_samples/phonemes/48.wav new file mode 100644 index 0000000000..f6c7dd4502 Binary files /dev/null and b/sound/direct_sound_samples/phonemes/48.wav differ diff --git a/sound/direct_sound_samples/phonemes/49.aif b/sound/direct_sound_samples/phonemes/49.aif deleted file mode 100644 index 8438d301ab..0000000000 Binary files a/sound/direct_sound_samples/phonemes/49.aif and /dev/null differ diff --git a/sound/direct_sound_samples/phonemes/49.wav b/sound/direct_sound_samples/phonemes/49.wav new file mode 100644 index 0000000000..4168f2e137 Binary files /dev/null and b/sound/direct_sound_samples/phonemes/49.wav differ diff --git a/sound/direct_sound_samples/phonemes/50.aif b/sound/direct_sound_samples/phonemes/50.aif deleted file mode 100644 index 74d4bcf4af..0000000000 Binary files a/sound/direct_sound_samples/phonemes/50.aif and /dev/null differ diff --git a/sound/direct_sound_samples/phonemes/50.wav b/sound/direct_sound_samples/phonemes/50.wav new file mode 100644 index 0000000000..88ce07d9d7 Binary files /dev/null and b/sound/direct_sound_samples/phonemes/50.wav differ diff --git a/sound/direct_sound_samples/phonemes/51.aif b/sound/direct_sound_samples/phonemes/51.aif deleted file mode 100644 index dfef8a82be..0000000000 Binary files a/sound/direct_sound_samples/phonemes/51.aif and /dev/null differ diff --git a/sound/direct_sound_samples/phonemes/51.wav b/sound/direct_sound_samples/phonemes/51.wav new file mode 100644 index 0000000000..bd1a514180 Binary files /dev/null and b/sound/direct_sound_samples/phonemes/51.wav differ diff --git a/sound/direct_sound_samples/phonemes/shared.aif b/sound/direct_sound_samples/phonemes/shared.aif deleted file mode 100644 index 98c3a19651..0000000000 Binary files a/sound/direct_sound_samples/phonemes/shared.aif and /dev/null differ diff --git a/sound/direct_sound_samples/phonemes/shared.wav b/sound/direct_sound_samples/phonemes/shared.wav new file mode 100644 index 0000000000..63207e6e22 Binary files /dev/null and b/sound/direct_sound_samples/phonemes/shared.wav differ diff --git a/sound/direct_sound_samples/register_noise.aif b/sound/direct_sound_samples/register_noise.aif deleted file mode 100644 index e56c5c1311..0000000000 Binary files a/sound/direct_sound_samples/register_noise.aif and /dev/null differ diff --git a/sound/direct_sound_samples/register_noise.wav b/sound/direct_sound_samples/register_noise.wav new file mode 100644 index 0000000000..89d94e61cc Binary files /dev/null and b/sound/direct_sound_samples/register_noise.wav differ diff --git a/sound/direct_sound_samples/sc88pro_accordion.aif b/sound/direct_sound_samples/sc88pro_accordion.aif deleted file mode 100644 index 6d6c2e998b..0000000000 Binary files a/sound/direct_sound_samples/sc88pro_accordion.aif and /dev/null differ diff --git a/sound/direct_sound_samples/sc88pro_accordion.wav b/sound/direct_sound_samples/sc88pro_accordion.wav new file mode 100644 index 0000000000..f19a98d277 Binary files /dev/null and b/sound/direct_sound_samples/sc88pro_accordion.wav differ diff --git a/sound/direct_sound_samples/sc88pro_accordion_duplicate.aif b/sound/direct_sound_samples/sc88pro_accordion_duplicate.aif deleted file mode 100644 index 6d6c2e998b..0000000000 Binary files a/sound/direct_sound_samples/sc88pro_accordion_duplicate.aif and /dev/null differ diff --git a/sound/direct_sound_samples/sc88pro_accordion_duplicate.wav b/sound/direct_sound_samples/sc88pro_accordion_duplicate.wav new file mode 100644 index 0000000000..f19a98d277 Binary files /dev/null and b/sound/direct_sound_samples/sc88pro_accordion_duplicate.wav differ diff --git a/sound/direct_sound_samples/sc88pro_bubbles.aif b/sound/direct_sound_samples/sc88pro_bubbles.aif deleted file mode 100644 index 89872bf558..0000000000 Binary files a/sound/direct_sound_samples/sc88pro_bubbles.aif and /dev/null differ diff --git a/sound/direct_sound_samples/sc88pro_bubbles.wav b/sound/direct_sound_samples/sc88pro_bubbles.wav new file mode 100644 index 0000000000..d6e61596d5 Binary files /dev/null and b/sound/direct_sound_samples/sc88pro_bubbles.wav differ diff --git a/sound/direct_sound_samples/sc88pro_church_organ3_high.aif b/sound/direct_sound_samples/sc88pro_church_organ3_high.aif deleted file mode 100644 index 8663a62614..0000000000 Binary files a/sound/direct_sound_samples/sc88pro_church_organ3_high.aif and /dev/null differ diff --git a/sound/direct_sound_samples/sc88pro_church_organ3_high.wav b/sound/direct_sound_samples/sc88pro_church_organ3_high.wav new file mode 100644 index 0000000000..0766a8503d Binary files /dev/null and b/sound/direct_sound_samples/sc88pro_church_organ3_high.wav differ diff --git a/sound/direct_sound_samples/sc88pro_church_organ3_low.aif b/sound/direct_sound_samples/sc88pro_church_organ3_low.aif deleted file mode 100644 index a2618653f6..0000000000 Binary files a/sound/direct_sound_samples/sc88pro_church_organ3_low.aif and /dev/null differ diff --git a/sound/direct_sound_samples/sc88pro_church_organ3_low.wav b/sound/direct_sound_samples/sc88pro_church_organ3_low.wav new file mode 100644 index 0000000000..afc9c18907 Binary files /dev/null and b/sound/direct_sound_samples/sc88pro_church_organ3_low.wav differ diff --git a/sound/direct_sound_samples/sc88pro_fingered_bass.aif b/sound/direct_sound_samples/sc88pro_fingered_bass.aif deleted file mode 100644 index f244a9982d..0000000000 Binary files a/sound/direct_sound_samples/sc88pro_fingered_bass.aif and /dev/null differ diff --git a/sound/direct_sound_samples/sc88pro_fingered_bass.wav b/sound/direct_sound_samples/sc88pro_fingered_bass.wav new file mode 100644 index 0000000000..0e723b742b Binary files /dev/null and b/sound/direct_sound_samples/sc88pro_fingered_bass.wav differ diff --git a/sound/direct_sound_samples/sc88pro_flute.aif b/sound/direct_sound_samples/sc88pro_flute.aif deleted file mode 100644 index 703f3adbd0..0000000000 Binary files a/sound/direct_sound_samples/sc88pro_flute.aif and /dev/null differ diff --git a/sound/direct_sound_samples/sc88pro_flute.wav b/sound/direct_sound_samples/sc88pro_flute.wav new file mode 100644 index 0000000000..409ce0f744 Binary files /dev/null and b/sound/direct_sound_samples/sc88pro_flute.wav differ diff --git a/sound/direct_sound_samples/sc88pro_french_horn_60.aif b/sound/direct_sound_samples/sc88pro_french_horn_60.aif deleted file mode 100644 index 742c4385e9..0000000000 Binary files a/sound/direct_sound_samples/sc88pro_french_horn_60.aif and /dev/null differ diff --git a/sound/direct_sound_samples/sc88pro_french_horn_60.wav b/sound/direct_sound_samples/sc88pro_french_horn_60.wav new file mode 100644 index 0000000000..105c186a2a Binary files /dev/null and b/sound/direct_sound_samples/sc88pro_french_horn_60.wav differ diff --git a/sound/direct_sound_samples/sc88pro_french_horn_72.aif b/sound/direct_sound_samples/sc88pro_french_horn_72.aif deleted file mode 100644 index 004fda6a18..0000000000 Binary files a/sound/direct_sound_samples/sc88pro_french_horn_72.aif and /dev/null differ diff --git a/sound/direct_sound_samples/sc88pro_french_horn_72.wav b/sound/direct_sound_samples/sc88pro_french_horn_72.wav new file mode 100644 index 0000000000..380d796307 Binary files /dev/null and b/sound/direct_sound_samples/sc88pro_french_horn_72.wav differ diff --git a/sound/direct_sound_samples/sc88pro_fretless_bass.aif b/sound/direct_sound_samples/sc88pro_fretless_bass.aif deleted file mode 100644 index f3aa47d913..0000000000 Binary files a/sound/direct_sound_samples/sc88pro_fretless_bass.aif and /dev/null differ diff --git a/sound/direct_sound_samples/sc88pro_fretless_bass.wav b/sound/direct_sound_samples/sc88pro_fretless_bass.wav new file mode 100644 index 0000000000..f639d5ccf2 Binary files /dev/null and b/sound/direct_sound_samples/sc88pro_fretless_bass.wav differ diff --git a/sound/direct_sound_samples/sc88pro_glockenspiel.aif b/sound/direct_sound_samples/sc88pro_glockenspiel.aif deleted file mode 100644 index 199ead8112..0000000000 Binary files a/sound/direct_sound_samples/sc88pro_glockenspiel.aif and /dev/null differ diff --git a/sound/direct_sound_samples/sc88pro_glockenspiel.wav b/sound/direct_sound_samples/sc88pro_glockenspiel.wav new file mode 100644 index 0000000000..4c9cbae149 Binary files /dev/null and b/sound/direct_sound_samples/sc88pro_glockenspiel.wav differ diff --git a/sound/direct_sound_samples/sc88pro_harp.aif b/sound/direct_sound_samples/sc88pro_harp.aif deleted file mode 100644 index 083c45e3da..0000000000 Binary files a/sound/direct_sound_samples/sc88pro_harp.aif and /dev/null differ diff --git a/sound/direct_sound_samples/sc88pro_harp.wav b/sound/direct_sound_samples/sc88pro_harp.wav new file mode 100644 index 0000000000..bdb176720c Binary files /dev/null and b/sound/direct_sound_samples/sc88pro_harp.wav differ diff --git a/sound/direct_sound_samples/sc88pro_jingle_bell.aif b/sound/direct_sound_samples/sc88pro_jingle_bell.aif deleted file mode 100644 index 0eaf313093..0000000000 Binary files a/sound/direct_sound_samples/sc88pro_jingle_bell.aif and /dev/null differ diff --git a/sound/direct_sound_samples/sc88pro_jingle_bell.wav b/sound/direct_sound_samples/sc88pro_jingle_bell.wav new file mode 100644 index 0000000000..1eb6b1de1a Binary files /dev/null and b/sound/direct_sound_samples/sc88pro_jingle_bell.wav differ diff --git a/sound/direct_sound_samples/sc88pro_mute_high_conga.aif b/sound/direct_sound_samples/sc88pro_mute_high_conga.aif deleted file mode 100644 index 2e1bf9c641..0000000000 Binary files a/sound/direct_sound_samples/sc88pro_mute_high_conga.aif and /dev/null differ diff --git a/sound/direct_sound_samples/sc88pro_mute_high_conga.wav b/sound/direct_sound_samples/sc88pro_mute_high_conga.wav new file mode 100644 index 0000000000..c009d7265c Binary files /dev/null and b/sound/direct_sound_samples/sc88pro_mute_high_conga.wav differ diff --git a/sound/direct_sound_samples/sc88pro_nylon_str_guitar.aif b/sound/direct_sound_samples/sc88pro_nylon_str_guitar.aif deleted file mode 100644 index dea429a254..0000000000 Binary files a/sound/direct_sound_samples/sc88pro_nylon_str_guitar.aif and /dev/null differ diff --git a/sound/direct_sound_samples/sc88pro_nylon_str_guitar.wav b/sound/direct_sound_samples/sc88pro_nylon_str_guitar.wav new file mode 100644 index 0000000000..7538f508ad Binary files /dev/null and b/sound/direct_sound_samples/sc88pro_nylon_str_guitar.wav differ diff --git a/sound/direct_sound_samples/sc88pro_open_low_conga.aif b/sound/direct_sound_samples/sc88pro_open_low_conga.aif deleted file mode 100644 index 8e1cb620a6..0000000000 Binary files a/sound/direct_sound_samples/sc88pro_open_low_conga.aif and /dev/null differ diff --git a/sound/direct_sound_samples/sc88pro_open_low_conga.wav b/sound/direct_sound_samples/sc88pro_open_low_conga.wav new file mode 100644 index 0000000000..34a1e3f32a Binary files /dev/null and b/sound/direct_sound_samples/sc88pro_open_low_conga.wav differ diff --git a/sound/direct_sound_samples/sc88pro_orchestra_cymbal_crash.aif b/sound/direct_sound_samples/sc88pro_orchestra_cymbal_crash.aif deleted file mode 100644 index 576e3e19e1..0000000000 Binary files a/sound/direct_sound_samples/sc88pro_orchestra_cymbal_crash.aif and /dev/null differ diff --git a/sound/direct_sound_samples/sc88pro_orchestra_cymbal_crash.wav b/sound/direct_sound_samples/sc88pro_orchestra_cymbal_crash.wav new file mode 100644 index 0000000000..c3f89f9c78 Binary files /dev/null and b/sound/direct_sound_samples/sc88pro_orchestra_cymbal_crash.wav differ diff --git a/sound/direct_sound_samples/sc88pro_orchestra_snare.aif b/sound/direct_sound_samples/sc88pro_orchestra_snare.aif deleted file mode 100644 index 36b6407588..0000000000 Binary files a/sound/direct_sound_samples/sc88pro_orchestra_snare.aif and /dev/null differ diff --git a/sound/direct_sound_samples/sc88pro_orchestra_snare.wav b/sound/direct_sound_samples/sc88pro_orchestra_snare.wav new file mode 100644 index 0000000000..96b10bb05f Binary files /dev/null and b/sound/direct_sound_samples/sc88pro_orchestra_snare.wav differ diff --git a/sound/direct_sound_samples/sc88pro_organ2.aif b/sound/direct_sound_samples/sc88pro_organ2.aif deleted file mode 100644 index 6372bbc324..0000000000 Binary files a/sound/direct_sound_samples/sc88pro_organ2.aif and /dev/null differ diff --git a/sound/direct_sound_samples/sc88pro_organ2.wav b/sound/direct_sound_samples/sc88pro_organ2.wav new file mode 100644 index 0000000000..bf6f2ba520 Binary files /dev/null and b/sound/direct_sound_samples/sc88pro_organ2.wav differ diff --git a/sound/direct_sound_samples/sc88pro_piano1_48.aif b/sound/direct_sound_samples/sc88pro_piano1_48.aif deleted file mode 100644 index c2b3757b09..0000000000 Binary files a/sound/direct_sound_samples/sc88pro_piano1_48.aif and /dev/null differ diff --git a/sound/direct_sound_samples/sc88pro_piano1_48.wav b/sound/direct_sound_samples/sc88pro_piano1_48.wav new file mode 100644 index 0000000000..c7bcfca138 Binary files /dev/null and b/sound/direct_sound_samples/sc88pro_piano1_48.wav differ diff --git a/sound/direct_sound_samples/sc88pro_piano1_60.aif b/sound/direct_sound_samples/sc88pro_piano1_60.aif deleted file mode 100644 index 7de586c9bd..0000000000 Binary files a/sound/direct_sound_samples/sc88pro_piano1_60.aif and /dev/null differ diff --git a/sound/direct_sound_samples/sc88pro_piano1_60.wav b/sound/direct_sound_samples/sc88pro_piano1_60.wav new file mode 100644 index 0000000000..7199386c7b Binary files /dev/null and b/sound/direct_sound_samples/sc88pro_piano1_60.wav differ diff --git a/sound/direct_sound_samples/sc88pro_piano1_72.aif b/sound/direct_sound_samples/sc88pro_piano1_72.aif deleted file mode 100644 index 5236141ba6..0000000000 Binary files a/sound/direct_sound_samples/sc88pro_piano1_72.aif and /dev/null differ diff --git a/sound/direct_sound_samples/sc88pro_piano1_72.wav b/sound/direct_sound_samples/sc88pro_piano1_72.wav new file mode 100644 index 0000000000..603006eb6f Binary files /dev/null and b/sound/direct_sound_samples/sc88pro_piano1_72.wav differ diff --git a/sound/direct_sound_samples/sc88pro_piano1_84.aif b/sound/direct_sound_samples/sc88pro_piano1_84.aif deleted file mode 100644 index a7c4e94f8f..0000000000 Binary files a/sound/direct_sound_samples/sc88pro_piano1_84.aif and /dev/null differ diff --git a/sound/direct_sound_samples/sc88pro_piano1_84.wav b/sound/direct_sound_samples/sc88pro_piano1_84.wav new file mode 100644 index 0000000000..0d76370756 Binary files /dev/null and b/sound/direct_sound_samples/sc88pro_piano1_84.wav differ diff --git a/sound/direct_sound_samples/sc88pro_pizzicato_strings.aif b/sound/direct_sound_samples/sc88pro_pizzicato_strings.aif deleted file mode 100644 index 1c0a027f7a..0000000000 Binary files a/sound/direct_sound_samples/sc88pro_pizzicato_strings.aif and /dev/null differ diff --git a/sound/direct_sound_samples/sc88pro_pizzicato_strings.wav b/sound/direct_sound_samples/sc88pro_pizzicato_strings.wav new file mode 100644 index 0000000000..6bb6bc74a9 Binary files /dev/null and b/sound/direct_sound_samples/sc88pro_pizzicato_strings.wav differ diff --git a/sound/direct_sound_samples/sc88pro_rnd_kick.aif b/sound/direct_sound_samples/sc88pro_rnd_kick.aif deleted file mode 100644 index 9c504e3d05..0000000000 Binary files a/sound/direct_sound_samples/sc88pro_rnd_kick.aif and /dev/null differ diff --git a/sound/direct_sound_samples/sc88pro_rnd_kick.wav b/sound/direct_sound_samples/sc88pro_rnd_kick.wav new file mode 100644 index 0000000000..b05d88a812 Binary files /dev/null and b/sound/direct_sound_samples/sc88pro_rnd_kick.wav differ diff --git a/sound/direct_sound_samples/sc88pro_rnd_snare.aif b/sound/direct_sound_samples/sc88pro_rnd_snare.aif deleted file mode 100644 index 544b187d5e..0000000000 Binary files a/sound/direct_sound_samples/sc88pro_rnd_snare.aif and /dev/null differ diff --git a/sound/direct_sound_samples/sc88pro_rnd_snare.wav b/sound/direct_sound_samples/sc88pro_rnd_snare.wav new file mode 100644 index 0000000000..c00ee759f7 Binary files /dev/null and b/sound/direct_sound_samples/sc88pro_rnd_snare.wav differ diff --git a/sound/direct_sound_samples/sc88pro_slap_bass.aif b/sound/direct_sound_samples/sc88pro_slap_bass.aif deleted file mode 100644 index 9175b63c5b..0000000000 Binary files a/sound/direct_sound_samples/sc88pro_slap_bass.aif and /dev/null differ diff --git a/sound/direct_sound_samples/sc88pro_slap_bass.wav b/sound/direct_sound_samples/sc88pro_slap_bass.wav new file mode 100644 index 0000000000..41d747259e Binary files /dev/null and b/sound/direct_sound_samples/sc88pro_slap_bass.wav differ diff --git a/sound/direct_sound_samples/sc88pro_square_wave.aif b/sound/direct_sound_samples/sc88pro_square_wave.aif deleted file mode 100644 index 09e17f0ca7..0000000000 Binary files a/sound/direct_sound_samples/sc88pro_square_wave.aif and /dev/null differ diff --git a/sound/direct_sound_samples/sc88pro_square_wave.wav b/sound/direct_sound_samples/sc88pro_square_wave.wav new file mode 100644 index 0000000000..020dae03a4 Binary files /dev/null and b/sound/direct_sound_samples/sc88pro_square_wave.wav differ diff --git a/sound/direct_sound_samples/sc88pro_string_ensemble_60.aif b/sound/direct_sound_samples/sc88pro_string_ensemble_60.aif deleted file mode 100644 index bfaa5c196c..0000000000 Binary files a/sound/direct_sound_samples/sc88pro_string_ensemble_60.aif and /dev/null differ diff --git a/sound/direct_sound_samples/sc88pro_string_ensemble_60.wav b/sound/direct_sound_samples/sc88pro_string_ensemble_60.wav new file mode 100644 index 0000000000..26e9db076c Binary files /dev/null and b/sound/direct_sound_samples/sc88pro_string_ensemble_60.wav differ diff --git a/sound/direct_sound_samples/sc88pro_string_ensemble_72.aif b/sound/direct_sound_samples/sc88pro_string_ensemble_72.aif deleted file mode 100644 index 3e76cacddc..0000000000 Binary files a/sound/direct_sound_samples/sc88pro_string_ensemble_72.aif and /dev/null differ diff --git a/sound/direct_sound_samples/sc88pro_string_ensemble_72.wav b/sound/direct_sound_samples/sc88pro_string_ensemble_72.wav new file mode 100644 index 0000000000..1699f831ca Binary files /dev/null and b/sound/direct_sound_samples/sc88pro_string_ensemble_72.wav differ diff --git a/sound/direct_sound_samples/sc88pro_string_ensemble_84.aif b/sound/direct_sound_samples/sc88pro_string_ensemble_84.aif deleted file mode 100644 index 2647c78ecb..0000000000 Binary files a/sound/direct_sound_samples/sc88pro_string_ensemble_84.aif and /dev/null differ diff --git a/sound/direct_sound_samples/sc88pro_string_ensemble_84.wav b/sound/direct_sound_samples/sc88pro_string_ensemble_84.wav new file mode 100644 index 0000000000..5616d094a0 Binary files /dev/null and b/sound/direct_sound_samples/sc88pro_string_ensemble_84.wav differ diff --git a/sound/direct_sound_samples/sc88pro_synth_bass.aif b/sound/direct_sound_samples/sc88pro_synth_bass.aif deleted file mode 100644 index f39931a7e4..0000000000 Binary files a/sound/direct_sound_samples/sc88pro_synth_bass.aif and /dev/null differ diff --git a/sound/direct_sound_samples/sc88pro_synth_bass.wav b/sound/direct_sound_samples/sc88pro_synth_bass.wav new file mode 100644 index 0000000000..5aa61ab8ca Binary files /dev/null and b/sound/direct_sound_samples/sc88pro_synth_bass.wav differ diff --git a/sound/direct_sound_samples/sc88pro_taiko.aif b/sound/direct_sound_samples/sc88pro_taiko.aif deleted file mode 100644 index a8046cee8c..0000000000 Binary files a/sound/direct_sound_samples/sc88pro_taiko.aif and /dev/null differ diff --git a/sound/direct_sound_samples/sc88pro_taiko.wav b/sound/direct_sound_samples/sc88pro_taiko.wav new file mode 100644 index 0000000000..af01253368 Binary files /dev/null and b/sound/direct_sound_samples/sc88pro_taiko.wav differ diff --git a/sound/direct_sound_samples/sc88pro_tambourine.aif b/sound/direct_sound_samples/sc88pro_tambourine.aif deleted file mode 100644 index 39ec57d29b..0000000000 Binary files a/sound/direct_sound_samples/sc88pro_tambourine.aif and /dev/null differ diff --git a/sound/direct_sound_samples/sc88pro_tambourine.wav b/sound/direct_sound_samples/sc88pro_tambourine.wav new file mode 100644 index 0000000000..016b2cc209 Binary files /dev/null and b/sound/direct_sound_samples/sc88pro_tambourine.wav differ diff --git a/sound/direct_sound_samples/sc88pro_timpani.aif b/sound/direct_sound_samples/sc88pro_timpani.aif deleted file mode 100644 index dfdfd702e0..0000000000 Binary files a/sound/direct_sound_samples/sc88pro_timpani.aif and /dev/null differ diff --git a/sound/direct_sound_samples/sc88pro_timpani.wav b/sound/direct_sound_samples/sc88pro_timpani.wav new file mode 100644 index 0000000000..bed5f113a1 Binary files /dev/null and b/sound/direct_sound_samples/sc88pro_timpani.wav differ diff --git a/sound/direct_sound_samples/sc88pro_timpani_with_snare.aif b/sound/direct_sound_samples/sc88pro_timpani_with_snare.aif deleted file mode 100644 index 7270872d64..0000000000 Binary files a/sound/direct_sound_samples/sc88pro_timpani_with_snare.aif and /dev/null differ diff --git a/sound/direct_sound_samples/sc88pro_timpani_with_snare.wav b/sound/direct_sound_samples/sc88pro_timpani_with_snare.wav new file mode 100644 index 0000000000..8ab1862d02 Binary files /dev/null and b/sound/direct_sound_samples/sc88pro_timpani_with_snare.wav differ diff --git a/sound/direct_sound_samples/sc88pro_tr909_hand_clap.aif b/sound/direct_sound_samples/sc88pro_tr909_hand_clap.aif deleted file mode 100644 index b11787ffc8..0000000000 Binary files a/sound/direct_sound_samples/sc88pro_tr909_hand_clap.aif and /dev/null differ diff --git a/sound/direct_sound_samples/sc88pro_tr909_hand_clap.wav b/sound/direct_sound_samples/sc88pro_tr909_hand_clap.wav new file mode 100644 index 0000000000..2e07040cb4 Binary files /dev/null and b/sound/direct_sound_samples/sc88pro_tr909_hand_clap.wav differ diff --git a/sound/direct_sound_samples/sc88pro_trumpet_60.aif b/sound/direct_sound_samples/sc88pro_trumpet_60.aif deleted file mode 100644 index e56df7f605..0000000000 Binary files a/sound/direct_sound_samples/sc88pro_trumpet_60.aif and /dev/null differ diff --git a/sound/direct_sound_samples/sc88pro_trumpet_60.wav b/sound/direct_sound_samples/sc88pro_trumpet_60.wav new file mode 100644 index 0000000000..0c857d971d Binary files /dev/null and b/sound/direct_sound_samples/sc88pro_trumpet_60.wav differ diff --git a/sound/direct_sound_samples/sc88pro_trumpet_72.aif b/sound/direct_sound_samples/sc88pro_trumpet_72.aif deleted file mode 100644 index 8c68a83b31..0000000000 Binary files a/sound/direct_sound_samples/sc88pro_trumpet_72.aif and /dev/null differ diff --git a/sound/direct_sound_samples/sc88pro_trumpet_72.wav b/sound/direct_sound_samples/sc88pro_trumpet_72.wav new file mode 100644 index 0000000000..93a62dc0ef Binary files /dev/null and b/sound/direct_sound_samples/sc88pro_trumpet_72.wav differ diff --git a/sound/direct_sound_samples/sc88pro_trumpet_84.aif b/sound/direct_sound_samples/sc88pro_trumpet_84.aif deleted file mode 100644 index a03bafc974..0000000000 Binary files a/sound/direct_sound_samples/sc88pro_trumpet_84.aif and /dev/null differ diff --git a/sound/direct_sound_samples/sc88pro_trumpet_84.wav b/sound/direct_sound_samples/sc88pro_trumpet_84.wav new file mode 100644 index 0000000000..12549376b5 Binary files /dev/null and b/sound/direct_sound_samples/sc88pro_trumpet_84.wav differ diff --git a/sound/direct_sound_samples/sc88pro_tuba_39.aif b/sound/direct_sound_samples/sc88pro_tuba_39.aif deleted file mode 100644 index d4077b4816..0000000000 Binary files a/sound/direct_sound_samples/sc88pro_tuba_39.aif and /dev/null differ diff --git a/sound/direct_sound_samples/sc88pro_tuba_39.wav b/sound/direct_sound_samples/sc88pro_tuba_39.wav new file mode 100644 index 0000000000..c3b78eea55 Binary files /dev/null and b/sound/direct_sound_samples/sc88pro_tuba_39.wav differ diff --git a/sound/direct_sound_samples/sc88pro_tuba_51.aif b/sound/direct_sound_samples/sc88pro_tuba_51.aif deleted file mode 100644 index 2ad86876be..0000000000 Binary files a/sound/direct_sound_samples/sc88pro_tuba_51.aif and /dev/null differ diff --git a/sound/direct_sound_samples/sc88pro_tuba_51.wav b/sound/direct_sound_samples/sc88pro_tuba_51.wav new file mode 100644 index 0000000000..fed8c72f43 Binary files /dev/null and b/sound/direct_sound_samples/sc88pro_tuba_51.wav differ diff --git a/sound/direct_sound_samples/sc88pro_tubular_bell.aif b/sound/direct_sound_samples/sc88pro_tubular_bell.aif deleted file mode 100644 index 9d00ecae6b..0000000000 Binary files a/sound/direct_sound_samples/sc88pro_tubular_bell.aif and /dev/null differ diff --git a/sound/direct_sound_samples/sc88pro_tubular_bell.wav b/sound/direct_sound_samples/sc88pro_tubular_bell.wav new file mode 100644 index 0000000000..8c892236b9 Binary files /dev/null and b/sound/direct_sound_samples/sc88pro_tubular_bell.wav differ diff --git a/sound/direct_sound_samples/sc88pro_wind.aif b/sound/direct_sound_samples/sc88pro_wind.aif deleted file mode 100644 index ece919ea51..0000000000 Binary files a/sound/direct_sound_samples/sc88pro_wind.aif and /dev/null differ diff --git a/sound/direct_sound_samples/sc88pro_wind.wav b/sound/direct_sound_samples/sc88pro_wind.wav new file mode 100644 index 0000000000..3856a4af1f Binary files /dev/null and b/sound/direct_sound_samples/sc88pro_wind.wav differ diff --git a/sound/direct_sound_samples/sc88pro_xylophone.aif b/sound/direct_sound_samples/sc88pro_xylophone.aif deleted file mode 100644 index 1bd43ca92e..0000000000 Binary files a/sound/direct_sound_samples/sc88pro_xylophone.aif and /dev/null differ diff --git a/sound/direct_sound_samples/sc88pro_xylophone.wav b/sound/direct_sound_samples/sc88pro_xylophone.wav new file mode 100644 index 0000000000..a08296baa1 Binary files /dev/null and b/sound/direct_sound_samples/sc88pro_xylophone.wav differ diff --git a/sound/direct_sound_samples/sd90_ambient_tom.aif b/sound/direct_sound_samples/sd90_ambient_tom.aif deleted file mode 100644 index 08f1acf388..0000000000 Binary files a/sound/direct_sound_samples/sd90_ambient_tom.aif and /dev/null differ diff --git a/sound/direct_sound_samples/sd90_ambient_tom.wav b/sound/direct_sound_samples/sd90_ambient_tom.wav new file mode 100644 index 0000000000..6f390959fc Binary files /dev/null and b/sound/direct_sound_samples/sd90_ambient_tom.wav differ diff --git a/sound/direct_sound_samples/sd90_classical_detuned_ep1_high.aif b/sound/direct_sound_samples/sd90_classical_detuned_ep1_high.aif deleted file mode 100644 index 86ea0fa760..0000000000 Binary files a/sound/direct_sound_samples/sd90_classical_detuned_ep1_high.aif and /dev/null differ diff --git a/sound/direct_sound_samples/sd90_classical_detuned_ep1_high.wav b/sound/direct_sound_samples/sd90_classical_detuned_ep1_high.wav new file mode 100644 index 0000000000..3c96f1cbca Binary files /dev/null and b/sound/direct_sound_samples/sd90_classical_detuned_ep1_high.wav differ diff --git a/sound/direct_sound_samples/sd90_classical_detuned_ep1_low.aif b/sound/direct_sound_samples/sd90_classical_detuned_ep1_low.aif deleted file mode 100644 index fced037122..0000000000 Binary files a/sound/direct_sound_samples/sd90_classical_detuned_ep1_low.aif and /dev/null differ diff --git a/sound/direct_sound_samples/sd90_classical_detuned_ep1_low.wav b/sound/direct_sound_samples/sd90_classical_detuned_ep1_low.wav new file mode 100644 index 0000000000..39e25a89ce Binary files /dev/null and b/sound/direct_sound_samples/sd90_classical_detuned_ep1_low.wav differ diff --git a/sound/direct_sound_samples/sd90_classical_distortion_guitar_high.aif b/sound/direct_sound_samples/sd90_classical_distortion_guitar_high.aif deleted file mode 100644 index b0f0e82a1a..0000000000 Binary files a/sound/direct_sound_samples/sd90_classical_distortion_guitar_high.aif and /dev/null differ diff --git a/sound/direct_sound_samples/sd90_classical_distortion_guitar_high.wav b/sound/direct_sound_samples/sd90_classical_distortion_guitar_high.wav new file mode 100644 index 0000000000..097d91f734 Binary files /dev/null and b/sound/direct_sound_samples/sd90_classical_distortion_guitar_high.wav differ diff --git a/sound/direct_sound_samples/sd90_classical_distortion_guitar_low.aif b/sound/direct_sound_samples/sd90_classical_distortion_guitar_low.aif deleted file mode 100644 index c4f7082ed7..0000000000 Binary files a/sound/direct_sound_samples/sd90_classical_distortion_guitar_low.aif and /dev/null differ diff --git a/sound/direct_sound_samples/sd90_classical_distortion_guitar_low.wav b/sound/direct_sound_samples/sd90_classical_distortion_guitar_low.wav new file mode 100644 index 0000000000..d281d77572 Binary files /dev/null and b/sound/direct_sound_samples/sd90_classical_distortion_guitar_low.wav differ diff --git a/sound/direct_sound_samples/sd90_classical_oboe.aif b/sound/direct_sound_samples/sd90_classical_oboe.aif deleted file mode 100644 index 41b6fec12f..0000000000 Binary files a/sound/direct_sound_samples/sd90_classical_oboe.aif and /dev/null differ diff --git a/sound/direct_sound_samples/sd90_classical_oboe.wav b/sound/direct_sound_samples/sd90_classical_oboe.wav new file mode 100644 index 0000000000..2b9e96afc4 Binary files /dev/null and b/sound/direct_sound_samples/sd90_classical_oboe.wav differ diff --git a/sound/direct_sound_samples/sd90_classical_overdrive_guitar.aif b/sound/direct_sound_samples/sd90_classical_overdrive_guitar.aif deleted file mode 100644 index d37c79c056..0000000000 Binary files a/sound/direct_sound_samples/sd90_classical_overdrive_guitar.aif and /dev/null differ diff --git a/sound/direct_sound_samples/sd90_classical_overdrive_guitar.wav b/sound/direct_sound_samples/sd90_classical_overdrive_guitar.wav new file mode 100644 index 0000000000..7380be1e1b Binary files /dev/null and b/sound/direct_sound_samples/sd90_classical_overdrive_guitar.wav differ diff --git a/sound/direct_sound_samples/sd90_classical_shakuhachi.aif b/sound/direct_sound_samples/sd90_classical_shakuhachi.aif deleted file mode 100644 index e04a34f642..0000000000 Binary files a/sound/direct_sound_samples/sd90_classical_shakuhachi.aif and /dev/null differ diff --git a/sound/direct_sound_samples/sd90_classical_shakuhachi.wav b/sound/direct_sound_samples/sd90_classical_shakuhachi.wav new file mode 100644 index 0000000000..587cee2cb7 Binary files /dev/null and b/sound/direct_sound_samples/sd90_classical_shakuhachi.wav differ diff --git a/sound/direct_sound_samples/sd90_classical_whistle.aif b/sound/direct_sound_samples/sd90_classical_whistle.aif deleted file mode 100644 index b4be7482f0..0000000000 Binary files a/sound/direct_sound_samples/sd90_classical_whistle.aif and /dev/null differ diff --git a/sound/direct_sound_samples/sd90_classical_whistle.wav b/sound/direct_sound_samples/sd90_classical_whistle.wav new file mode 100644 index 0000000000..61a58445bf Binary files /dev/null and b/sound/direct_sound_samples/sd90_classical_whistle.wav differ diff --git a/sound/direct_sound_samples/sd90_cowbell.aif b/sound/direct_sound_samples/sd90_cowbell.aif deleted file mode 100644 index 43515f5427..0000000000 Binary files a/sound/direct_sound_samples/sd90_cowbell.aif and /dev/null differ diff --git a/sound/direct_sound_samples/sd90_cowbell.wav b/sound/direct_sound_samples/sd90_cowbell.wav new file mode 100644 index 0000000000..9c35bf6541 Binary files /dev/null and b/sound/direct_sound_samples/sd90_cowbell.wav differ diff --git a/sound/direct_sound_samples/sd90_enhanced_delay_shaku.aif b/sound/direct_sound_samples/sd90_enhanced_delay_shaku.aif deleted file mode 100644 index c64ef6b037..0000000000 Binary files a/sound/direct_sound_samples/sd90_enhanced_delay_shaku.aif and /dev/null differ diff --git a/sound/direct_sound_samples/sd90_enhanced_delay_shaku.wav b/sound/direct_sound_samples/sd90_enhanced_delay_shaku.wav new file mode 100644 index 0000000000..d87fc68b2b Binary files /dev/null and b/sound/direct_sound_samples/sd90_enhanced_delay_shaku.wav differ diff --git a/sound/direct_sound_samples/sd90_open_triangle.aif b/sound/direct_sound_samples/sd90_open_triangle.aif deleted file mode 100644 index 0d0b3e3ca2..0000000000 Binary files a/sound/direct_sound_samples/sd90_open_triangle.aif and /dev/null differ diff --git a/sound/direct_sound_samples/sd90_open_triangle.wav b/sound/direct_sound_samples/sd90_open_triangle.wav new file mode 100644 index 0000000000..92df2b3074 Binary files /dev/null and b/sound/direct_sound_samples/sd90_open_triangle.wav differ diff --git a/sound/direct_sound_samples/sd90_solo_snare.aif b/sound/direct_sound_samples/sd90_solo_snare.aif deleted file mode 100644 index 93b6793584..0000000000 Binary files a/sound/direct_sound_samples/sd90_solo_snare.aif and /dev/null differ diff --git a/sound/direct_sound_samples/sd90_solo_snare.wav b/sound/direct_sound_samples/sd90_solo_snare.wav new file mode 100644 index 0000000000..ad5d872844 Binary files /dev/null and b/sound/direct_sound_samples/sd90_solo_snare.wav differ diff --git a/sound/direct_sound_samples/sd90_special_scream_drive.aif b/sound/direct_sound_samples/sd90_special_scream_drive.aif deleted file mode 100644 index 8b7a7da405..0000000000 Binary files a/sound/direct_sound_samples/sd90_special_scream_drive.aif and /dev/null differ diff --git a/sound/direct_sound_samples/sd90_special_scream_drive.wav b/sound/direct_sound_samples/sd90_special_scream_drive.wav new file mode 100644 index 0000000000..8b4b563ac7 Binary files /dev/null and b/sound/direct_sound_samples/sd90_special_scream_drive.wav differ diff --git a/sound/direct_sound_samples/steinway_b_piano.aif b/sound/direct_sound_samples/steinway_b_piano.aif deleted file mode 100644 index e98c64db4d..0000000000 Binary files a/sound/direct_sound_samples/steinway_b_piano.aif and /dev/null differ diff --git a/sound/direct_sound_samples/steinway_b_piano.wav b/sound/direct_sound_samples/steinway_b_piano.wav new file mode 100644 index 0000000000..5a4d94b0a8 Binary files /dev/null and b/sound/direct_sound_samples/steinway_b_piano.wav differ diff --git a/sound/direct_sound_samples/trinity_30303_mega_bass.aif b/sound/direct_sound_samples/trinity_30303_mega_bass.aif deleted file mode 100644 index 09fe6f12ea..0000000000 Binary files a/sound/direct_sound_samples/trinity_30303_mega_bass.aif and /dev/null differ diff --git a/sound/direct_sound_samples/trinity_30303_mega_bass.wav b/sound/direct_sound_samples/trinity_30303_mega_bass.wav new file mode 100644 index 0000000000..6ad677b7d8 Binary files /dev/null and b/sound/direct_sound_samples/trinity_30303_mega_bass.wav differ diff --git a/sound/direct_sound_samples/trinity_big_boned.aif b/sound/direct_sound_samples/trinity_big_boned.aif deleted file mode 100644 index 455ced13e9..0000000000 Binary files a/sound/direct_sound_samples/trinity_big_boned.aif and /dev/null differ diff --git a/sound/direct_sound_samples/trinity_big_boned.wav b/sound/direct_sound_samples/trinity_big_boned.wav new file mode 100644 index 0000000000..7f42b9fcd9 Binary files /dev/null and b/sound/direct_sound_samples/trinity_big_boned.wav differ diff --git a/sound/direct_sound_samples/trinity_cymbal_crash.aif b/sound/direct_sound_samples/trinity_cymbal_crash.aif deleted file mode 100644 index 4aec6882ff..0000000000 Binary files a/sound/direct_sound_samples/trinity_cymbal_crash.aif and /dev/null differ diff --git a/sound/direct_sound_samples/trinity_cymbal_crash.wav b/sound/direct_sound_samples/trinity_cymbal_crash.wav new file mode 100644 index 0000000000..c3e52d3e29 Binary files /dev/null and b/sound/direct_sound_samples/trinity_cymbal_crash.wav differ diff --git a/sound/direct_sound_samples/unknown_01.aif b/sound/direct_sound_samples/unknown_01.aif deleted file mode 100644 index ee6ff45b7f..0000000000 Binary files a/sound/direct_sound_samples/unknown_01.aif and /dev/null differ diff --git a/sound/direct_sound_samples/unknown_01.wav b/sound/direct_sound_samples/unknown_01.wav new file mode 100644 index 0000000000..75d05e7f4d Binary files /dev/null and b/sound/direct_sound_samples/unknown_01.wav differ diff --git a/sound/direct_sound_samples/unknown_02.aif b/sound/direct_sound_samples/unknown_02.aif deleted file mode 100644 index 2e09d08223..0000000000 Binary files a/sound/direct_sound_samples/unknown_02.aif and /dev/null differ diff --git a/sound/direct_sound_samples/unknown_02.wav b/sound/direct_sound_samples/unknown_02.wav new file mode 100644 index 0000000000..1a25b1fe18 Binary files /dev/null and b/sound/direct_sound_samples/unknown_02.wav differ diff --git a/sound/direct_sound_samples/unknown_03.aif b/sound/direct_sound_samples/unknown_03.aif deleted file mode 100644 index 49f24936fa..0000000000 Binary files a/sound/direct_sound_samples/unknown_03.aif and /dev/null differ diff --git a/sound/direct_sound_samples/unknown_03.wav b/sound/direct_sound_samples/unknown_03.wav new file mode 100644 index 0000000000..1a64c4b25d Binary files /dev/null and b/sound/direct_sound_samples/unknown_03.wav differ diff --git a/sound/direct_sound_samples/unknown_04.aif b/sound/direct_sound_samples/unknown_04.aif deleted file mode 100644 index 5c55d91ed8..0000000000 Binary files a/sound/direct_sound_samples/unknown_04.aif and /dev/null differ diff --git a/sound/direct_sound_samples/unknown_04.wav b/sound/direct_sound_samples/unknown_04.wav new file mode 100644 index 0000000000..a278be2758 Binary files /dev/null and b/sound/direct_sound_samples/unknown_04.wav differ diff --git a/sound/direct_sound_samples/unknown_05.aif b/sound/direct_sound_samples/unknown_05.aif deleted file mode 100644 index 515818a4da..0000000000 Binary files a/sound/direct_sound_samples/unknown_05.aif and /dev/null differ diff --git a/sound/direct_sound_samples/unknown_05.wav b/sound/direct_sound_samples/unknown_05.wav new file mode 100644 index 0000000000..dd5eee1d2c Binary files /dev/null and b/sound/direct_sound_samples/unknown_05.wav differ diff --git a/sound/direct_sound_samples/unknown_06.aif b/sound/direct_sound_samples/unknown_06.aif deleted file mode 100644 index 102830efa5..0000000000 Binary files a/sound/direct_sound_samples/unknown_06.aif and /dev/null differ diff --git a/sound/direct_sound_samples/unknown_06.wav b/sound/direct_sound_samples/unknown_06.wav new file mode 100644 index 0000000000..396eb3e721 Binary files /dev/null and b/sound/direct_sound_samples/unknown_06.wav differ diff --git a/sound/direct_sound_samples/unknown_07.aif b/sound/direct_sound_samples/unknown_07.aif deleted file mode 100644 index 556be02382..0000000000 Binary files a/sound/direct_sound_samples/unknown_07.aif and /dev/null differ diff --git a/sound/direct_sound_samples/unknown_07.wav b/sound/direct_sound_samples/unknown_07.wav new file mode 100644 index 0000000000..b1e0a0d08f Binary files /dev/null and b/sound/direct_sound_samples/unknown_07.wav differ diff --git a/sound/direct_sound_samples/unknown_08.aif b/sound/direct_sound_samples/unknown_08.aif deleted file mode 100644 index dd80b1185a..0000000000 Binary files a/sound/direct_sound_samples/unknown_08.aif and /dev/null differ diff --git a/sound/direct_sound_samples/unknown_08.wav b/sound/direct_sound_samples/unknown_08.wav new file mode 100644 index 0000000000..420ee23ce3 Binary files /dev/null and b/sound/direct_sound_samples/unknown_08.wav differ diff --git a/sound/direct_sound_samples/unknown_09.aif b/sound/direct_sound_samples/unknown_09.aif deleted file mode 100644 index ebd46eeaa2..0000000000 Binary files a/sound/direct_sound_samples/unknown_09.aif and /dev/null differ diff --git a/sound/direct_sound_samples/unknown_09.wav b/sound/direct_sound_samples/unknown_09.wav new file mode 100644 index 0000000000..fd1ee4dd78 Binary files /dev/null and b/sound/direct_sound_samples/unknown_09.wav differ diff --git a/sound/direct_sound_samples/unknown_10.aif b/sound/direct_sound_samples/unknown_10.aif deleted file mode 100644 index 6a11945c55..0000000000 Binary files a/sound/direct_sound_samples/unknown_10.aif and /dev/null differ diff --git a/sound/direct_sound_samples/unknown_10.wav b/sound/direct_sound_samples/unknown_10.wav new file mode 100644 index 0000000000..63cf6043cb Binary files /dev/null and b/sound/direct_sound_samples/unknown_10.wav differ diff --git a/sound/direct_sound_samples/unknown_11.aif b/sound/direct_sound_samples/unknown_11.aif deleted file mode 100644 index a0fb49f89b..0000000000 Binary files a/sound/direct_sound_samples/unknown_11.aif and /dev/null differ diff --git a/sound/direct_sound_samples/unknown_11.wav b/sound/direct_sound_samples/unknown_11.wav new file mode 100644 index 0000000000..f2e648045b Binary files /dev/null and b/sound/direct_sound_samples/unknown_11.wav differ diff --git a/sound/direct_sound_samples/unknown_12.aif b/sound/direct_sound_samples/unknown_12.aif deleted file mode 100644 index 9521d0b6e8..0000000000 Binary files a/sound/direct_sound_samples/unknown_12.aif and /dev/null differ diff --git a/sound/direct_sound_samples/unknown_12.wav b/sound/direct_sound_samples/unknown_12.wav new file mode 100644 index 0000000000..146db2c348 Binary files /dev/null and b/sound/direct_sound_samples/unknown_12.wav differ diff --git a/sound/direct_sound_samples/unknown_13.aif b/sound/direct_sound_samples/unknown_13.aif deleted file mode 100644 index 2519572e2c..0000000000 Binary files a/sound/direct_sound_samples/unknown_13.aif and /dev/null differ diff --git a/sound/direct_sound_samples/unknown_13.wav b/sound/direct_sound_samples/unknown_13.wav new file mode 100644 index 0000000000..1618ea28b5 Binary files /dev/null and b/sound/direct_sound_samples/unknown_13.wav differ diff --git a/sound/direct_sound_samples/unknown_14.aif b/sound/direct_sound_samples/unknown_14.aif deleted file mode 100644 index d411e66128..0000000000 Binary files a/sound/direct_sound_samples/unknown_14.aif and /dev/null differ diff --git a/sound/direct_sound_samples/unknown_14.wav b/sound/direct_sound_samples/unknown_14.wav new file mode 100644 index 0000000000..4c509795ad Binary files /dev/null and b/sound/direct_sound_samples/unknown_14.wav differ diff --git a/sound/direct_sound_samples/unknown_15.aif b/sound/direct_sound_samples/unknown_15.aif deleted file mode 100644 index 3bc1aa839b..0000000000 Binary files a/sound/direct_sound_samples/unknown_15.aif and /dev/null differ diff --git a/sound/direct_sound_samples/unknown_15.wav b/sound/direct_sound_samples/unknown_15.wav new file mode 100644 index 0000000000..080c4ad841 Binary files /dev/null and b/sound/direct_sound_samples/unknown_15.wav differ diff --git a/sound/direct_sound_samples/unknown_16.aif b/sound/direct_sound_samples/unknown_16.aif deleted file mode 100644 index 3bacf36765..0000000000 Binary files a/sound/direct_sound_samples/unknown_16.aif and /dev/null differ diff --git a/sound/direct_sound_samples/unknown_16.wav b/sound/direct_sound_samples/unknown_16.wav new file mode 100644 index 0000000000..72cf7dcc95 Binary files /dev/null and b/sound/direct_sound_samples/unknown_16.wav differ diff --git a/sound/direct_sound_samples/unknown_17.aif b/sound/direct_sound_samples/unknown_17.aif deleted file mode 100644 index 5ddaa153da..0000000000 Binary files a/sound/direct_sound_samples/unknown_17.aif and /dev/null differ diff --git a/sound/direct_sound_samples/unknown_17.wav b/sound/direct_sound_samples/unknown_17.wav new file mode 100644 index 0000000000..5a277f7d44 Binary files /dev/null and b/sound/direct_sound_samples/unknown_17.wav differ diff --git a/sound/direct_sound_samples/unknown_18.aif b/sound/direct_sound_samples/unknown_18.aif deleted file mode 100644 index e1715fd030..0000000000 Binary files a/sound/direct_sound_samples/unknown_18.aif and /dev/null differ diff --git a/sound/direct_sound_samples/unknown_18.wav b/sound/direct_sound_samples/unknown_18.wav new file mode 100644 index 0000000000..9ee0027921 Binary files /dev/null and b/sound/direct_sound_samples/unknown_18.wav differ diff --git a/sound/direct_sound_samples/unknown_bell.aif b/sound/direct_sound_samples/unknown_bell.aif deleted file mode 100644 index 7de79e7478..0000000000 Binary files a/sound/direct_sound_samples/unknown_bell.aif and /dev/null differ diff --git a/sound/direct_sound_samples/unknown_bell.wav b/sound/direct_sound_samples/unknown_bell.wav new file mode 100644 index 0000000000..4dc82a170b Binary files /dev/null and b/sound/direct_sound_samples/unknown_bell.wav differ diff --git a/sound/direct_sound_samples/unknown_close_hihat.aif b/sound/direct_sound_samples/unknown_close_hihat.aif deleted file mode 100644 index 8747aef28d..0000000000 Binary files a/sound/direct_sound_samples/unknown_close_hihat.aif and /dev/null differ diff --git a/sound/direct_sound_samples/unknown_close_hihat.wav b/sound/direct_sound_samples/unknown_close_hihat.wav new file mode 100644 index 0000000000..86774ce3ce Binary files /dev/null and b/sound/direct_sound_samples/unknown_close_hihat.wav differ diff --git a/sound/direct_sound_samples/unknown_female_voice.aif b/sound/direct_sound_samples/unknown_female_voice.aif deleted file mode 100644 index b310823a79..0000000000 Binary files a/sound/direct_sound_samples/unknown_female_voice.aif and /dev/null differ diff --git a/sound/direct_sound_samples/unknown_female_voice.wav b/sound/direct_sound_samples/unknown_female_voice.wav new file mode 100644 index 0000000000..44e73b3395 Binary files /dev/null and b/sound/direct_sound_samples/unknown_female_voice.wav differ diff --git a/sound/direct_sound_samples/unknown_koto_high.aif b/sound/direct_sound_samples/unknown_koto_high.aif deleted file mode 100644 index 9c531de113..0000000000 Binary files a/sound/direct_sound_samples/unknown_koto_high.aif and /dev/null differ diff --git a/sound/direct_sound_samples/unknown_koto_high.wav b/sound/direct_sound_samples/unknown_koto_high.wav new file mode 100644 index 0000000000..b9591a098f Binary files /dev/null and b/sound/direct_sound_samples/unknown_koto_high.wav differ diff --git a/sound/direct_sound_samples/unknown_koto_low.aif b/sound/direct_sound_samples/unknown_koto_low.aif deleted file mode 100644 index 67c40f1966..0000000000 Binary files a/sound/direct_sound_samples/unknown_koto_low.aif and /dev/null differ diff --git a/sound/direct_sound_samples/unknown_koto_low.wav b/sound/direct_sound_samples/unknown_koto_low.wav new file mode 100644 index 0000000000..a1736cafc7 Binary files /dev/null and b/sound/direct_sound_samples/unknown_koto_low.wav differ diff --git a/sound/direct_sound_samples/unknown_open_hihat.aif b/sound/direct_sound_samples/unknown_open_hihat.aif deleted file mode 100644 index 5ad9410d00..0000000000 Binary files a/sound/direct_sound_samples/unknown_open_hihat.aif and /dev/null differ diff --git a/sound/direct_sound_samples/unknown_open_hihat.wav b/sound/direct_sound_samples/unknown_open_hihat.wav new file mode 100644 index 0000000000..3a9ee824c1 Binary files /dev/null and b/sound/direct_sound_samples/unknown_open_hihat.wav differ diff --git a/sound/direct_sound_samples/unknown_snare.aif b/sound/direct_sound_samples/unknown_snare.aif deleted file mode 100644 index e7184ec6f6..0000000000 Binary files a/sound/direct_sound_samples/unknown_snare.aif and /dev/null differ diff --git a/sound/direct_sound_samples/unknown_snare.wav b/sound/direct_sound_samples/unknown_snare.wav new file mode 100644 index 0000000000..03295e4763 Binary files /dev/null and b/sound/direct_sound_samples/unknown_snare.wav differ diff --git a/sound/direct_sound_samples/unknown_synth_snare.aif b/sound/direct_sound_samples/unknown_synth_snare.aif deleted file mode 100644 index b3122457de..0000000000 Binary files a/sound/direct_sound_samples/unknown_synth_snare.aif and /dev/null differ diff --git a/sound/direct_sound_samples/unknown_synth_snare.wav b/sound/direct_sound_samples/unknown_synth_snare.wav new file mode 100644 index 0000000000..774194423d Binary files /dev/null and b/sound/direct_sound_samples/unknown_synth_snare.wav differ diff --git a/sound/direct_sound_samples/unused_guitar_separates_power_chord.aif b/sound/direct_sound_samples/unused_guitar_separates_power_chord.aif deleted file mode 100644 index 7647a74a70..0000000000 Binary files a/sound/direct_sound_samples/unused_guitar_separates_power_chord.aif and /dev/null differ diff --git a/sound/direct_sound_samples/unused_guitar_separates_power_chord.wav b/sound/direct_sound_samples/unused_guitar_separates_power_chord.wav new file mode 100644 index 0000000000..c75373087b Binary files /dev/null and b/sound/direct_sound_samples/unused_guitar_separates_power_chord.wav differ diff --git a/sound/direct_sound_samples/unused_heart_of_asia_indian_drum.aif b/sound/direct_sound_samples/unused_heart_of_asia_indian_drum.aif deleted file mode 100644 index 2e67f1d737..0000000000 Binary files a/sound/direct_sound_samples/unused_heart_of_asia_indian_drum.aif and /dev/null differ diff --git a/sound/direct_sound_samples/unused_heart_of_asia_indian_drum.wav b/sound/direct_sound_samples/unused_heart_of_asia_indian_drum.wav new file mode 100644 index 0000000000..49d67a30f3 Binary files /dev/null and b/sound/direct_sound_samples/unused_heart_of_asia_indian_drum.wav differ diff --git a/sound/direct_sound_samples/unused_sc55_tom.aif b/sound/direct_sound_samples/unused_sc55_tom.aif deleted file mode 100644 index 04f990b13c..0000000000 Binary files a/sound/direct_sound_samples/unused_sc55_tom.aif and /dev/null differ diff --git a/sound/direct_sound_samples/unused_sc55_tom.wav b/sound/direct_sound_samples/unused_sc55_tom.wav new file mode 100644 index 0000000000..b4c225827f Binary files /dev/null and b/sound/direct_sound_samples/unused_sc55_tom.wav differ diff --git a/sound/direct_sound_samples/unused_sc88pro_unison_slap.aif b/sound/direct_sound_samples/unused_sc88pro_unison_slap.aif deleted file mode 100644 index 46d6e7d131..0000000000 Binary files a/sound/direct_sound_samples/unused_sc88pro_unison_slap.aif and /dev/null differ diff --git a/sound/direct_sound_samples/unused_sc88pro_unison_slap.wav b/sound/direct_sound_samples/unused_sc88pro_unison_slap.wav new file mode 100644 index 0000000000..690cbc9183 Binary files /dev/null and b/sound/direct_sound_samples/unused_sc88pro_unison_slap.wav differ diff --git a/sound/direct_sound_samples/unused_sd90_oboe.aif b/sound/direct_sound_samples/unused_sd90_oboe.aif deleted file mode 100644 index 2a0ea2a266..0000000000 Binary files a/sound/direct_sound_samples/unused_sd90_oboe.aif and /dev/null differ diff --git a/sound/direct_sound_samples/unused_sd90_oboe.wav b/sound/direct_sound_samples/unused_sd90_oboe.wav new file mode 100644 index 0000000000..e7609ed53d Binary files /dev/null and b/sound/direct_sound_samples/unused_sd90_oboe.wav differ diff --git a/sound/direct_sound_samples/unused_unknown_male_voice.aif b/sound/direct_sound_samples/unused_unknown_male_voice.aif deleted file mode 100644 index a2382d700f..0000000000 Binary files a/sound/direct_sound_samples/unused_unknown_male_voice.aif and /dev/null differ diff --git a/sound/direct_sound_samples/unused_unknown_male_voice.wav b/sound/direct_sound_samples/unused_unknown_male_voice.wav new file mode 100644 index 0000000000..7612c9b61d Binary files /dev/null and b/sound/direct_sound_samples/unused_unknown_male_voice.wav differ diff --git a/spritesheet_rules.mk b/spritesheet_rules.mk index 7c05219f8a..a14fd18813 100644 --- a/spritesheet_rules.mk +++ b/spritesheet_rules.mk @@ -612,6 +612,8 @@ $(OBJEVENTGFXDIR)/berry_trees/rowap.4bpp: %.4bpp: %.png $(OBJEVENTGFXDIR)/berry_trees/micle.4bpp: %.4bpp: %.png $(GFX) $< $@ -mwidth 2 -mheight 4 +$(OBJEVENTGFXDIR)/misc/apricorn_tree.4bpp: %.4bpp: %.png + $(GFX) $< $@ -mwidth 2 -mheight 2 $(OBJEVENTGFXDIR)/misc/breakable_rock.4bpp: %.4bpp: %.png $(GFX) $< $@ -mwidth 2 -mheight 2 @@ -694,6 +696,12 @@ $(FLDEFFGFXDIR)/surf_blob.4bpp: %.4bpp: %.png $(FLDEFFGFXDIR)/rock_climb_blob.4bpp: %.4bpp: %.png $(GFX) $< $@ -mwidth 4 -mheight 4 +$(FLDEFFGFXDIR)/oras_dowsing_brendan.4bpp: %.4bpp: %.png + $(GFX) $< $@ -mwidth 2 -mheight 4 + +$(FLDEFFGFXDIR)/oras_dowsing_may.4bpp: %.4bpp: %.png + $(GFX) $< $@ -mwidth 2 -mheight 4 + $(FLDEFFGFXDIR)/tall_grass.4bpp: %.4bpp: %.png $(GFX) $< $@ -mwidth 2 -mheight 2 diff --git a/src/apricorn_tree.c b/src/apricorn_tree.c new file mode 100644 index 0000000000..b7784a6a85 --- /dev/null +++ b/src/apricorn_tree.c @@ -0,0 +1,86 @@ +#include "global.h" +#include "apricorn_tree.h" +#include "event_data.h" +#include "event_object_movement.h" +#include "event_scripts.h" +#include "item.h" +#include "random.h" +#include "string_util.h" +#include "data/apricorns.h" + +void DailyResetApricornTrees(void) +{ +#if (APRICORN_TREE_COUNT > 0) + memset(&gSaveBlock3Ptr->apricornTrees[0], 0, NUM_APRICORN_TREE_BYTES); +#endif +} + +void ObjectEventInteractionGetApricornTreeData(void) +{ + u32 id = GetObjectEventApricornTreeId(gSelectedObjectEvent); + gSpecialVar_0x8004 = GetApricornTypeByApricornTreeId(id); + gSpecialVar_0x8005 = GetApricornCountByApricornTreeId(id); + + CopyItemNameHandlePlural(gSpecialVar_0x8004, gStringVar1, gSpecialVar_0x8005); +} + +void ObjectEventInteractionPickApricornTree(void) +{ + u32 id = GetObjectEventApricornTreeId(gSelectedObjectEvent); + enum ApricornType apricorn = GetApricornTypeByApricornTreeId(id); + gSpecialVar_0x8006 = CheckBagHasSpace(apricorn, GetApricornCountByApricornTreeId(id)); + + if (gSpecialVar_0x8006) + { + AddBagItem(apricorn, GetApricornCountByApricornTreeId(id)); + SetApricornTreePicked(id); + } + gSpecialVar_Result = GetItemPocket(apricorn); +} + +enum ApricornType GetApricornTypeByApricornTreeId(u32 id) +{ + if (APRICORN_TREE_COUNT > 0) + return gApricornTrees[id].apricornType; + else + return 0; +} + +u8 GetApricornCountByApricornTreeId(u32 id) +{ + if (IsApricornTreePicked(id)) + return 0; + + if (APRICORN_TREE_COUNT > 0) + { + if (gApricornTrees[id].maximum > gApricornTrees[id].minimum) + return gApricornTrees[id].minimum + Random() % (gApricornTrees[id].maximum - gApricornTrees[id].minimum); + else + return gApricornTrees[id].minimum; + } + else + return 0; +} + +bool8 IsApricornTreePicked(u32 id) +{ + if (id > APRICORN_TREE_COUNT) + return TRUE; + +#if (APRICORN_TREE_COUNT > 0) + return gSaveBlock3Ptr->apricornTrees[id / 8] & (1 << (id % 8)); +#else + return TRUE; +#endif +} + +void SetApricornTreePicked(u32 id) +{ + if (id > APRICORN_TREE_COUNT) + return; + +#if (APRICORN_TREE_COUNT > 0) + u8 *flagByte = &gSaveBlock3Ptr->apricornTrees[id / 8]; + *flagByte = (*flagByte) | (1 << (id % 8)); +#endif +} diff --git a/src/battle_ai_field_statuses.c b/src/battle_ai_field_statuses.c index bd7bdd8e17..030d99a94e 100644 --- a/src/battle_ai_field_statuses.c +++ b/src/battle_ai_field_statuses.c @@ -20,12 +20,11 @@ #include "constants/abilities.h" #include "constants/battle_ai.h" #include "constants/battle_move_effects.h" -#include "constants/hold_effects.h" #include "constants/moves.h" #include "constants/items.h" -static bool32 DoesAbilityBenefitFromWeather(u32 ability, u32 weather); -static bool32 DoesAbilityBenefitFromFieldStatus(u32 ability, u32 fieldStatus); +static bool32 DoesAbilityBenefitFromWeather(enum Ability ability, u32 weather); +static bool32 DoesAbilityBenefitFromFieldStatus(enum Ability ability, u32 fieldStatus); // A move is light sensitive if it is boosted by Sunny Day and weakened by low light weathers. static bool32 IsLightSensitiveMove(u32 move); static bool32 HasLightSensitiveMove(u32 battler); @@ -44,6 +43,7 @@ static enum FieldEffectOutcome BenefitsFromElectricTerrain(u32 battler); static enum FieldEffectOutcome BenefitsFromGrassyTerrain(u32 battler); static enum FieldEffectOutcome BenefitsFromMistyTerrain(u32 battler); static enum FieldEffectOutcome BenefitsFromPsychicTerrain(u32 battler); +static enum FieldEffectOutcome BenefitsFromGravity(u32 battler); static enum FieldEffectOutcome BenefitsFromTrickRoom(u32 battler); bool32 WeatherChecker(u32 battler, u32 weather, enum FieldEffectOutcome desiredResult) @@ -108,6 +108,8 @@ bool32 FieldStatusChecker(u32 battler, u32 fieldStatus, enum FieldEffectOutcome result = BenefitsFromPsychicTerrain(battler); // other field statuses + if (fieldStatus & STATUS_FIELD_GRAVITY) + result = BenefitsFromGravity(battler); if (fieldStatus & STATUS_FIELD_TRICK_ROOM) result = BenefitsFromTrickRoom(battler); @@ -125,7 +127,7 @@ bool32 FieldStatusChecker(u32 battler, u32 fieldStatus, enum FieldEffectOutcome return (result == desiredResult); } -static bool32 DoesAbilityBenefitFromWeather(u32 ability, u32 weather) +static bool32 DoesAbilityBenefitFromWeather(enum Ability ability, u32 weather) { switch (ability) { @@ -163,7 +165,7 @@ static bool32 DoesAbilityBenefitFromWeather(u32 ability, u32 weather) return FALSE; } -static bool32 DoesAbilityBenefitFromFieldStatus(u32 ability, u32 fieldStatus) +static bool32 DoesAbilityBenefitFromFieldStatus(enum Ability ability, u32 fieldStatus) { switch (ability) { @@ -217,7 +219,7 @@ static bool32 HasLightSensitiveMove(u32 battler) // Utility Umbrella does NOT block Ancient Pokemon from their stat boosts. static enum FieldEffectOutcome BenefitsFromSun(u32 battler) { - u32 ability = gAiLogicData->abilities[battler]; + enum Ability ability = gAiLogicData->abilities[battler]; if (gAiLogicData->holdEffects[battler] == HOLD_EFFECT_UTILITY_UMBRELLA) { @@ -248,9 +250,9 @@ static enum FieldEffectOutcome BenefitsFromSandstorm(u32 battler) if (gAiLogicData->holdEffects[battler] == HOLD_EFFECT_SAFETY_GOGGLES || IS_BATTLER_ANY_TYPE(battler, TYPE_ROCK, TYPE_GROUND, TYPE_STEEL)) { - if (!(IS_BATTLER_ANY_TYPE(FOE(battler), TYPE_ROCK, TYPE_GROUND, TYPE_STEEL)) - || gAiLogicData->holdEffects[FOE(battler)] == HOLD_EFFECT_SAFETY_GOGGLES - || DoesAbilityBenefitFromWeather(gAiLogicData->abilities[FOE(battler)], B_WEATHER_SANDSTORM)) + if (!(IS_BATTLER_ANY_TYPE(LEFT_FOE(battler), TYPE_ROCK, TYPE_GROUND, TYPE_STEEL)) + || gAiLogicData->holdEffects[LEFT_FOE(battler)] == HOLD_EFFECT_SAFETY_GOGGLES + || DoesAbilityBenefitFromWeather(gAiLogicData->abilities[LEFT_FOE(battler)], B_WEATHER_SANDSTORM)) return FIELD_EFFECT_POSITIVE; else return FIELD_EFFECT_NEUTRAL; @@ -274,7 +276,7 @@ static enum FieldEffectOutcome BenefitsFromHailOrSnow(u32 battler, u32 weather) if (HasLightSensitiveMove(battler)) return FIELD_EFFECT_NEGATIVE; - if (HasMoveWithFlag(FOE(battler), MoveAlwaysHitsInHailSnow)) + if (HasMoveWithFlag(LEFT_FOE(battler), MoveAlwaysHitsInHailSnow)) return FIELD_EFFECT_NEGATIVE; return FIELD_EFFECT_NEUTRAL; @@ -294,7 +296,7 @@ static enum FieldEffectOutcome BenefitsFromRain(u32 battler) if (HasLightSensitiveMove(battler) || HasDamagingMoveOfType(battler, TYPE_FIRE)) return FIELD_EFFECT_NEGATIVE; - if (HasMoveWithFlag(FOE(battler), MoveAlwaysHitsInRain)) + if (HasMoveWithFlag(LEFT_FOE(battler), MoveAlwaysHitsInRain)) return FIELD_EFFECT_NEGATIVE; return FIELD_EFFECT_NEUTRAL; @@ -309,11 +311,12 @@ static enum FieldEffectOutcome BenefitsFromElectricTerrain(u32 battler) if (HasMoveWithEffect(battler, EFFECT_RISING_VOLTAGE)) return FIELD_EFFECT_POSITIVE; - if (HasMoveWithEffect(FOE(battler), EFFECT_REST) && IsBattlerGrounded(FOE(battler))) + if ((HasMoveWithEffect(LEFT_FOE(battler), EFFECT_REST) && AI_IsBattlerGrounded(LEFT_FOE(battler))) + || (HasMoveWithEffect(RIGHT_FOE(battler), EFFECT_REST) && AI_IsBattlerGrounded(RIGHT_FOE(battler)))) return FIELD_EFFECT_POSITIVE; - bool32 grounded = IsBattlerGrounded(battler); - if (grounded && HasBattlerSideMoveWithAdditionalEffect(FOE(battler), MOVE_EFFECT_SLEEP)) + bool32 grounded = AI_IsBattlerGrounded(battler); + if (grounded && HasBattlerSideMoveWithAdditionalEffect(LEFT_FOE(battler), MOVE_EFFECT_SLEEP)) return FIELD_EFFECT_POSITIVE; if (grounded && ((gBattleMons[battler].status1 & STATUS1_SLEEP) @@ -321,7 +324,7 @@ static enum FieldEffectOutcome BenefitsFromElectricTerrain(u32 battler) || HasDamagingMoveOfType(battler, TYPE_ELECTRIC))) return FIELD_EFFECT_POSITIVE; - if (HasBattlerSideMoveWithEffect(FOE(battler), EFFECT_RISING_VOLTAGE)) + if (HasBattlerSideMoveWithEffect(LEFT_FOE(battler), EFFECT_RISING_VOLTAGE)) return FIELD_EFFECT_NEGATIVE; @@ -334,22 +337,22 @@ static enum FieldEffectOutcome BenefitsFromGrassyTerrain(u32 battler) if (DoesAbilityBenefitFromFieldStatus(gAiLogicData->abilities[battler], STATUS_FIELD_GRASSY_TERRAIN)) return FIELD_EFFECT_POSITIVE; - if (HasMoveWithEffect(battler, EFFECT_GRASSY_GLIDE)) + if (HasBattlerSideMoveWithEffect(battler, EFFECT_GRASSY_GLIDE)) return FIELD_EFFECT_POSITIVE; if (HasMoveWithAdditionalEffect(battler, MOVE_EFFECT_FLORAL_HEALING)) return FIELD_EFFECT_POSITIVE; - bool32 grounded = IsBattlerGrounded(battler); + bool32 grounded = AI_IsBattlerGrounded(battler); // Weaken spamming Earthquake, Magnitude, and Bulldoze. - if (grounded && (HasBattlerSideMoveWithEffect(FOE(battler), EFFECT_EARTHQUAKE) - || HasBattlerSideMoveWithEffect(FOE(battler), EFFECT_MAGNITUDE))) + if (grounded && (HasBattlerSideMoveWithEffect(LEFT_FOE(battler), EFFECT_EARTHQUAKE) + || HasBattlerSideMoveWithEffect(LEFT_FOE(battler), EFFECT_MAGNITUDE))) return FIELD_EFFECT_POSITIVE; if (grounded && HasDamagingMoveOfType(battler, TYPE_GRASS)) return FIELD_EFFECT_POSITIVE; - if (HasBattlerSideMoveWithEffect(FOE(battler), EFFECT_GRASSY_GLIDE)) + if (HasBattlerSideMoveWithEffect(LEFT_FOE(battler), EFFECT_GRASSY_GLIDE)) return FIELD_EFFECT_NEGATIVE; @@ -365,21 +368,22 @@ static enum FieldEffectOutcome BenefitsFromMistyTerrain(u32 battler) if (HasBattlerSideMoveWithEffect(battler, EFFECT_MISTY_EXPLOSION)) return FIELD_EFFECT_POSITIVE; - bool32 grounded = IsBattlerGrounded(battler); + bool32 grounded = AI_IsBattlerGrounded(battler); bool32 allyGrounded = FALSE; if (HasPartner(battler)) - allyGrounded = IsBattlerGrounded(BATTLE_PARTNER(battler)); + allyGrounded = AI_IsBattlerGrounded(BATTLE_PARTNER(battler)); - if (HasMoveWithEffect(FOE(battler), EFFECT_REST) && IsBattlerGrounded(FOE(battler))) + if ((HasMoveWithEffect(LEFT_FOE(battler), EFFECT_REST) && AI_IsBattlerGrounded(LEFT_FOE(battler))) + || (HasMoveWithEffect(RIGHT_FOE(battler), EFFECT_REST) && AI_IsBattlerGrounded(RIGHT_FOE(battler)))) return FIELD_EFFECT_POSITIVE; // harass dragons - if ((grounded || allyGrounded) - && (HasDamagingMoveOfType(FOE(battler), TYPE_DRAGON) || HasDamagingMoveOfType(BATTLE_PARTNER(FOE(battler)), TYPE_DRAGON))) + if ((grounded || allyGrounded) + && (HasDamagingMoveOfType(LEFT_FOE(battler), TYPE_DRAGON) || HasDamagingMoveOfType(RIGHT_FOE(battler), TYPE_DRAGON))) return FIELD_EFFECT_POSITIVE; - if ((grounded || allyGrounded) - && (HasNonVolatileMoveEffect(FOE(battler), MOVE_EFFECT_SLEEP) || HasNonVolatileMoveEffect(BATTLE_PARTNER(FOE(battler)), MOVE_EFFECT_SLEEP))) + if ((grounded || allyGrounded) + && (HasNonVolatileMoveEffect(LEFT_FOE(battler), MOVE_EFFECT_SLEEP) || HasNonVolatileMoveEffect(RIGHT_FOE(battler), MOVE_EFFECT_SLEEP))) return FIELD_EFFECT_POSITIVE; if (grounded && (gBattleMons[battler].status1 & STATUS1_SLEEP || gBattleMons[battler].volatiles.yawn)) @@ -394,48 +398,77 @@ static enum FieldEffectOutcome BenefitsFromPsychicTerrain(u32 battler) if (DoesAbilityBenefitFromFieldStatus(gAiLogicData->abilities[battler], STATUS_FIELD_PSYCHIC_TERRAIN)) return FIELD_EFFECT_POSITIVE; - if (HasMoveWithEffect(battler, EFFECT_EXPANDING_FORCE)) + if (HasBattlerSideMoveWithEffect(battler, EFFECT_EXPANDING_FORCE)) return FIELD_EFFECT_POSITIVE; - bool32 grounded = IsBattlerGrounded(battler); + bool32 grounded = AI_IsBattlerGrounded(battler); bool32 allyGrounded = FALSE; if (HasPartner(battler)) - allyGrounded = IsBattlerGrounded(BATTLE_PARTNER(battler)); + allyGrounded = AI_IsBattlerGrounded(BATTLE_PARTNER(battler)); // don't bother if we're not grounded if (grounded || allyGrounded) { // harass priority - if (HasBattlerSideAbility(FOE(battler), ABILITY_GALE_WINGS, gAiLogicData) - || HasBattlerSideAbility(FOE(battler), ABILITY_TRIAGE, gAiLogicData) - || HasBattlerSideAbility(FOE(battler), ABILITY_PRANKSTER, gAiLogicData)) + if (AI_IsAbilityOnSide(LEFT_FOE(battler), ABILITY_GALE_WINGS) + || AI_IsAbilityOnSide(LEFT_FOE(battler), ABILITY_TRIAGE) + || AI_IsAbilityOnSide(LEFT_FOE(battler), ABILITY_PRANKSTER)) return FIELD_EFFECT_POSITIVE; } - if (grounded && (HasDamagingMoveOfType(battler, TYPE_PSYCHIC))) + if (grounded && HasDamagingMoveOfType(battler, TYPE_PSYCHIC)) return FIELD_EFFECT_POSITIVE; - if (HasBattlerSideMoveWithEffect(FOE(battler), EFFECT_EXPANDING_FORCE)) + if (HasBattlerSideMoveWithEffect(LEFT_FOE(battler), EFFECT_EXPANDING_FORCE)) return FIELD_EFFECT_NEGATIVE; - if (HasBattlerSideAbility(battler, ABILITY_GALE_WINGS, gAiLogicData) - || HasBattlerSideAbility(battler, ABILITY_TRIAGE, gAiLogicData) - || HasBattlerSideAbility(battler, ABILITY_PRANKSTER, gAiLogicData)) + if (AI_IsAbilityOnSide(battler, ABILITY_GALE_WINGS) + || AI_IsAbilityOnSide(battler, ABILITY_TRIAGE) + || AI_IsAbilityOnSide(battler, ABILITY_PRANKSTER)) return FIELD_EFFECT_NEGATIVE; return FIELD_EFFECT_NEUTRAL; } +static enum FieldEffectOutcome BenefitsFromGravity(u32 battler) +{ + if (!AI_IsBattlerGrounded(battler)) + return FIELD_EFFECT_NEGATIVE; + + if (AI_IsAbilityOnSide(battler, ABILITY_HUSTLE)) + return FIELD_EFFECT_POSITIVE; + + if (HasMoveWithFlag(battler, IsMoveGravityBanned)) + return FIELD_EFFECT_NEGATIVE; + + if (IsBattlerAlive(LEFT_FOE(battler))) + { + if (HasMoveWithLowAccuracy(battler, LEFT_FOE(battler), LOW_ACCURACY_THRESHOLD, FALSE) + || (!AI_IsBattlerGrounded(LEFT_FOE(battler)) && HasDamagingMoveOfType(battler, TYPE_GROUND))) + return FIELD_EFFECT_POSITIVE; + } + + if (IsBattlerAlive(RIGHT_FOE(battler))) + { + if (HasMoveWithLowAccuracy(battler, RIGHT_FOE(battler), LOW_ACCURACY_THRESHOLD, FALSE) + || (!AI_IsBattlerGrounded(RIGHT_FOE(battler)) && HasDamagingMoveOfType(battler, TYPE_GROUND))) + return FIELD_EFFECT_POSITIVE; + } + + return FIELD_EFFECT_NEUTRAL; +} + + static enum FieldEffectOutcome BenefitsFromTrickRoom(u32 battler) { // If we're in singles, we literally only care about speed. if (IsBattle1v1()) { - if (gAiLogicData->speedStats[battler] < gAiLogicData->speedStats[FOE(battler)]) + if (gAiLogicData->speedStats[battler] < gAiLogicData->speedStats[LEFT_FOE(battler)]) return FIELD_EFFECT_POSITIVE; // If we tie, we shouldn't change trick room state. - else if (gAiLogicData->speedStats[battler] == gAiLogicData->speedStats[FOE(battler)]) - return FIELD_EFFECT_NEUTRAL; + else if (gAiLogicData->speedStats[battler] == gAiLogicData->speedStats[LEFT_FOE(battler)]) + return FIELD_EFFECT_NEUTRAL; else return FIELD_EFFECT_NEGATIVE; } @@ -455,7 +488,7 @@ static enum FieldEffectOutcome BenefitsFromTrickRoom(u32 battler) } // If we are faster or tie, we don't want trick room. - if ((gAiLogicData->speedStats[battler] >= gAiLogicData->speedStats[FOE(battler)]) || (gAiLogicData->speedStats[battler] >= gAiLogicData->speedStats[BATTLE_PARTNER(FOE(battler))])) + if ((gAiLogicData->speedStats[battler] >= gAiLogicData->speedStats[LEFT_FOE(battler)]) || (gAiLogicData->speedStats[battler] >= gAiLogicData->speedStats[RIGHT_FOE(battler)])) return FIELD_EFFECT_NEGATIVE; return FIELD_EFFECT_POSITIVE; diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index d2d81c2a53..9fe1b819ba 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -1,5 +1,3 @@ -// Note that FOE specifically returns the left-side battler; BATTLE_OPPOSITE is the diagonal. - #include "global.h" #include "main.h" #include "malloc.h" @@ -25,7 +23,6 @@ #include "constants/abilities.h" #include "constants/battle_ai.h" #include "constants/battle_move_effects.h" -#include "constants/hold_effects.h" #include "constants/moves.h" #include "constants/items.h" #include "constants/trainers.h" @@ -40,7 +37,7 @@ static u32 ChooseMoveOrAction_Singles(u32 battler); static u32 ChooseMoveOrAction_Doubles(u32 battler); static inline void BattleAI_DoAIProcessing(struct AiThinkingStruct *aiThink, u32 battlerAtk, u32 battlerDef); static inline void BattleAI_DoAIProcessing_PredictedSwitchin(struct AiThinkingStruct *aiThink, struct AiLogicData *aiData, u32 battlerAtk, u32 battlerDef); -static bool32 IsPinchBerryItemEffect(enum ItemHoldEffect holdEffect); +static bool32 IsPinchBerryItemEffect(enum HoldEffect holdEffect); static void AI_CompareDamagingMoves(u32 battlerAtk, u32 battlerDef); // ewram @@ -185,7 +182,7 @@ static u64 GetWildAiFlags(void) return flags; } -static u64 GetAiFlags(u16 trainerId) +static u64 GetAiFlags(u16 trainerId, u32 battler) { u64 flags = 0; @@ -198,7 +195,7 @@ static u64 GetAiFlags(u16 trainerId) else { if (gBattleTypeFlags & BATTLE_TYPE_RECORDED) - flags = GetAiScriptsInRecordedBattle(); + flags = GetAiScriptsInRecordedBattle(battler); else if (gBattleTypeFlags & BATTLE_TYPE_SAFARI) flags = AI_FLAG_SAFARI; else if (gBattleTypeFlags & BATTLE_TYPE_ROAMER) @@ -235,7 +232,7 @@ static u64 GetAiFlags(u16 trainerId) void BattleAI_SetupFlags(void) { if (IsAiVsAiBattle()) - gAiThinkingStruct->aiFlags[B_POSITION_PLAYER_LEFT] = GetAiFlags(gPartnerTrainerId); + gAiThinkingStruct->aiFlags[B_POSITION_PLAYER_LEFT] = GetAiFlags(gPartnerTrainerId, B_POSITION_PLAYER_LEFT); else gAiThinkingStruct->aiFlags[B_POSITION_PLAYER_LEFT] = 0; // player has no AI @@ -249,8 +246,8 @@ void BattleAI_SetupFlags(void) if (IsWildMonSmart() && !(gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_TRAINER))) { // smart wild AI - gAiThinkingStruct->aiFlags[B_POSITION_OPPONENT_LEFT] = GetAiFlags(0xFFFF); - gAiThinkingStruct->aiFlags[B_POSITION_OPPONENT_RIGHT] = GetAiFlags(0xFFFF); + gAiThinkingStruct->aiFlags[B_POSITION_OPPONENT_LEFT] = GetAiFlags(0xFFFF, B_POSITION_OPPONENT_LEFT); + gAiThinkingStruct->aiFlags[B_POSITION_OPPONENT_RIGHT] = GetAiFlags(0xFFFF, B_POSITION_OPPONENT_RIGHT); // The check is here because wild natural enemies are not symmetrical. if (B_WILD_NATURAL_ENEMIES && IsDoubleBattle()) @@ -262,20 +259,19 @@ void BattleAI_SetupFlags(void) if (IsNaturalEnemy(speciesRight, speciesLeft)) gAiThinkingStruct->aiFlags[B_POSITION_OPPONENT_RIGHT] |= AI_FLAG_ATTACKS_PARTNER; } - } else { - gAiThinkingStruct->aiFlags[B_POSITION_OPPONENT_LEFT] = GetAiFlags(TRAINER_BATTLE_PARAM.opponentA); - if (TRAINER_BATTLE_PARAM.opponentB != 0 && TRAINER_BATTLE_PARAM.opponentB != 0xFFFF) - gAiThinkingStruct->aiFlags[B_POSITION_OPPONENT_RIGHT] = GetAiFlags(TRAINER_BATTLE_PARAM.opponentB); + gAiThinkingStruct->aiFlags[B_POSITION_OPPONENT_LEFT] = GetAiFlags(TRAINER_BATTLE_PARAM.opponentA, B_POSITION_OPPONENT_LEFT); + if ((TRAINER_BATTLE_PARAM.opponentB != 0) && (TRAINER_BATTLE_PARAM.opponentB != 0xFFFF)) + gAiThinkingStruct->aiFlags[B_POSITION_OPPONENT_RIGHT] = GetAiFlags(TRAINER_BATTLE_PARAM.opponentB, B_POSITION_OPPONENT_RIGHT); else gAiThinkingStruct->aiFlags[B_POSITION_OPPONENT_RIGHT] = gAiThinkingStruct->aiFlags[B_POSITION_OPPONENT_LEFT]; } if (gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER) { - gAiThinkingStruct->aiFlags[B_POSITION_PLAYER_RIGHT] = GetAiFlags(gPartnerTrainerId); + gAiThinkingStruct->aiFlags[B_POSITION_PLAYER_RIGHT] = GetAiFlags(gPartnerTrainerId, B_POSITION_PLAYER_RIGHT); } else if (IsDoubleBattle() && IsAiVsAiBattle()) { @@ -283,7 +279,8 @@ void BattleAI_SetupFlags(void) } else // Assign ai flags for player for prediction { - u64 aiFlags = GetAiFlags(TRAINER_BATTLE_PARAM.opponentA) | GetAiFlags(TRAINER_BATTLE_PARAM.opponentB); + u64 aiFlags = GetAiFlags(TRAINER_BATTLE_PARAM.opponentA, B_POSITION_OPPONENT_LEFT) + | GetAiFlags(TRAINER_BATTLE_PARAM.opponentB, B_POSITION_OPPONENT_RIGHT); gAiThinkingStruct->aiFlags[B_POSITION_PLAYER_RIGHT] = aiFlags; gAiThinkingStruct->aiFlags[B_POSITION_PLAYER_LEFT] = aiFlags; } @@ -362,13 +359,13 @@ void ComputeBattlerDecisions(u32 battler) if (isAiBattler || CanAiPredictMove()) { // Risky AI switches aggressively even mid battle - enum SwitchType switchType = (gAiThinkingStruct->aiFlags[battler] & AI_FLAG_RISKY) ? SWITCH_AFTER_KO : SWITCH_MID_BATTLE; + enum SwitchType switchType = (gAiThinkingStruct->aiFlags[battler] & AI_FLAG_RISKY) ? SWITCH_AFTER_KO : SWITCH_MID_BATTLE_OPTIONAL; gAiLogicData->aiCalcInProgress = TRUE; // Setup battler and prediction data BattleAI_SetupAIData(0xF, battler); - SetupAIPredictionData(battler, switchType); + SetupAIPredictionData(battler, SWITCH_MID_BATTLE_OPTIONAL); // AI's own switching data if (isAiBattler) @@ -450,6 +447,7 @@ void Ai_InitPartyStruct(void) { u32 i; bool32 isOmniscient = (gAiThinkingStruct->aiFlags[B_POSITION_OPPONENT_LEFT] & AI_FLAG_OMNISCIENT) || (gAiThinkingStruct->aiFlags[B_POSITION_OPPONENT_RIGHT] & AI_FLAG_OMNISCIENT); + bool32 hasPartyKnowledge = (gAiThinkingStruct->aiFlags[B_POSITION_OPPONENT_LEFT] & AI_FLAG_KNOW_OPPONENT_PARTY) || (gAiThinkingStruct->aiFlags[B_POSITION_OPPONENT_RIGHT] & AI_FLAG_KNOW_OPPONENT_PARTY); struct Pokemon *mon; gAiPartyData->count[B_SIDE_PLAYER] = CalculatePlayerPartyCount(); @@ -470,13 +468,16 @@ void Ai_InitPartyStruct(void) // Find fainted mons for (i = 0; i < gAiPartyData->count[B_SIDE_PLAYER]; i++) { + mon = &gPlayerParty[i]; if (GetMonData(&gPlayerParty[i], MON_DATA_HP) == 0) gAiPartyData->mons[B_SIDE_PLAYER][i].isFainted = TRUE; + if (isOmniscient || hasPartyKnowledge) + gAiPartyData->mons[B_SIDE_PLAYER][i].species = GetMonData(mon, MON_DATA_SPECIES); + if (isOmniscient) { u32 j; - mon = &gPlayerParty[i]; gAiPartyData->mons[B_SIDE_PLAYER][i].item = GetMonData(mon, MON_DATA_HELD_ITEM); gAiPartyData->mons[B_SIDE_PLAYER][i].heldEffect = GetItemHoldEffect(gAiPartyData->mons[B_SIDE_PLAYER][i].item); gAiPartyData->mons[B_SIDE_PLAYER][i].ability = GetMonAbility(mon); @@ -549,15 +550,17 @@ void RecordStatusMoves(u32 battler) void SetBattlerAiData(u32 battler, struct AiLogicData *aiData) { - u32 ability, holdEffect; + enum Ability ability; + u32 holdEffect; + ability = aiData->abilities[battler] = AI_DecideKnownAbilityForTurn(battler); aiData->items[battler] = gBattleMons[battler].item; holdEffect = aiData->holdEffects[battler] = AI_DecideHoldEffectForTurn(battler); aiData->holdEffectParams[battler] = GetBattlerHoldEffectParam(battler); - aiData->lastUsedMove[battler] = gLastMoves[battler]; + aiData->lastUsedMove[battler] = (gLastMoves[battler] == MOVE_UNAVAILABLE) ? MOVE_NONE : gLastMoves[battler]; aiData->hpPercents[battler] = GetHealthPercentage(battler); aiData->moveLimitations[battler] = CheckMoveLimitations(battler, 0, MOVE_LIMITATIONS_ALL); - aiData->speedStats[battler] = GetBattlerTotalSpeedStatArgs(battler, ability, holdEffect); + aiData->speedStats[battler] = GetBattlerTotalSpeedStat(battler, ability, holdEffect); if (IsAiBattlerAssumingStab()) RecordMovesBasedOnStab(battler); @@ -570,8 +573,8 @@ void SetBattlerAiData(u32 battler, struct AiLogicData *aiData) static u32 Ai_SetMoveAccuracy(struct AiLogicData *aiData, u32 battlerAtk, u32 battlerDef, u32 move) { u32 accuracy; - u32 abilityAtk = aiData->abilities[battlerAtk]; - u32 abilityDef = aiData->abilities[battlerDef]; + enum Ability abilityAtk = aiData->abilities[battlerAtk]; + enum Ability abilityDef = aiData->abilities[battlerDef]; if (CanMoveSkipAccuracyCalc(battlerAtk, battlerDef, abilityAtk, abilityDef, move, AI_CHECK)) { accuracy = BYPASSES_ACCURACY_CALC; @@ -637,6 +640,7 @@ void SetAiLogicDataForTurn(struct AiLogicData *aiData) u32 battlerAtk, battlersCount, weather; memset(aiData, 0, sizeof(struct AiLogicData)); + gAiBattleData->aiUsingGimmick = 0; if (!(gBattleTypeFlags & BATTLE_TYPE_HAS_AI) && !IsWildMonSmart()) return; @@ -691,7 +695,7 @@ u32 GetPartyMonAbility(struct Pokemon *mon) { // Doesn't have any special handling yet u32 species = GetMonData(mon, MON_DATA_SPECIES); - u32 ability = GetSpeciesAbility(species, GetMonData(mon, MON_DATA_ABILITY_NUM)); + enum Ability ability = GetSpeciesAbility(species, GetMonData(mon, MON_DATA_ABILITY_NUM)); return ability; } @@ -711,9 +715,9 @@ static u32 PpStallReduction(u32 move, u32 battlerAtk) continue; PokemonToBattleMon(&gPlayerParty[partyIndex], &gBattleMons[tempBattleMonIndex]); u32 species = GetMonData(&gPlayerParty[partyIndex], MON_DATA_SPECIES); - u32 abilityAtk = ABILITY_NONE; - u32 abilityDef = GetPartyMonAbility(&gPlayerParty[partyIndex]); - u32 moveType = GetBattleMoveType(move); // Probably doesn't handle dynamic types right now + enum Ability abilityAtk = ABILITY_NONE; + enum Ability abilityDef = GetPartyMonAbility(&gPlayerParty[partyIndex]); + enum Type moveType = GetBattleMoveType(move); // Probably doesn't handle dynamic types right now if (CanAbilityAbsorbMove(battlerAtk, tempBattleMonIndex, abilityDef, move, moveType, CHECK_TRIGGER) || CanAbilityBlockMove(battlerAtk, tempBattleMonIndex, abilityAtk, abilityDef, move, CHECK_TRIGGER) || (CalcPartyMonTypeEffectivenessMultiplier(move, species, abilityDef) == 0)) @@ -1071,7 +1075,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) // move data enum BattleMoveEffects moveEffect = GetMoveEffect(move); u32 nonVolatileStatus = GetMoveNonVolatileStatus(move); - s32 moveType; + enum Type moveType; u32 moveTarget = GetBattlerMoveTargetType(battlerAtk, move); struct AiLogicData *aiData = gAiLogicData; uq4_12_t effectiveness = aiData->effectiveness[battlerAtk][battlerDef][gAiThinkingStruct->movesetIndex]; @@ -1082,8 +1086,8 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) u32 weather; u32 predictedMove = GetIncomingMove(battlerAtk, battlerDef, gAiLogicData); u32 predictedMoveSpeedCheck = GetIncomingMoveSpeedCheck(battlerAtk, battlerDef, gAiLogicData); - u32 abilityAtk = aiData->abilities[battlerAtk]; - u32 abilityDef = aiData->abilities[battlerDef]; + enum Ability abilityAtk = aiData->abilities[battlerAtk]; + enum Ability abilityDef = aiData->abilities[battlerDef]; s32 atkPriority = GetBattleMovePriority(battlerAtk, abilityAtk, move); SetTypeBeforeUsingMove(move, battlerAtk); @@ -1141,6 +1145,9 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) // check non-user target if (!(moveTarget & MOVE_TARGET_USER)) { + if (Ai_IsPriorityBlocked(battlerAtk, battlerDef, move, aiData)) + RETURN_SCORE_MINUS(20); + if (CanAbilityBlockMove(battlerAtk, battlerDef, abilityAtk, abilityDef, move, AI_CHECK)) RETURN_SCORE_MINUS(20); @@ -1221,6 +1228,8 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) && IsNonVolatileStatusMove(move)) RETURN_SCORE_MINUS(10); break; + default: + break; } // def ability checks // target partner ability checks & not attacking partner @@ -1252,29 +1261,31 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) if (IsAromaVeilProtectedEffect(moveEffect)) RETURN_SCORE_MINUS(10); break; + default: + break; } } // def partner ability checks // gen7+ dark type mons immune to priority->elevated moves from prankster - if (GetGenConfig(GEN_CONFIG_PRANKSTER_DARK_TYPES) >= GEN_7 && IS_BATTLER_OF_TYPE(battlerDef, TYPE_DARK) + if (GetConfig(CONFIG_PRANKSTER_DARK_TYPES) >= GEN_7 && IS_BATTLER_OF_TYPE(battlerDef, TYPE_DARK) && aiData->abilities[battlerAtk] == ABILITY_PRANKSTER && IsBattleMoveStatus(move) && !(moveTarget & (MOVE_TARGET_OPPONENTS_FIELD | MOVE_TARGET_USER))) RETURN_SCORE_MINUS(10); // terrain & effect checks - if (IsBattlerTerrainAffected(battlerDef, STATUS_FIELD_ELECTRIC_TERRAIN)) + if (IsBattlerTerrainAffected(battlerDef, abilityDef, aiData->holdEffects[battlerDef], STATUS_FIELD_ELECTRIC_TERRAIN)) { if (nonVolatileStatus == MOVE_EFFECT_SLEEP) RETURN_SCORE_MINUS(20); } - if (IsBattlerTerrainAffected(battlerDef, STATUS_FIELD_MISTY_TERRAIN)) + if (IsBattlerTerrainAffected(battlerDef, abilityDef, aiData->holdEffects[battlerDef], STATUS_FIELD_MISTY_TERRAIN)) { if (IsNonVolatileStatusMove(move) || IsConfusionMoveEffect(moveEffect)) RETURN_SCORE_MINUS(20); } - if (IsBattlerTerrainAffected(battlerAtk, STATUS_FIELD_PSYCHIC_TERRAIN) && atkPriority > 0) + if (IsBattlerTerrainAffected(battlerAtk, abilityAtk, aiData->holdEffects[battlerAtk], STATUS_FIELD_PSYCHIC_TERRAIN) && atkPriority > 0) { RETURN_SCORE_MINUS(20); } @@ -1283,7 +1294,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) // the following checks apply to any target (including user) // throat chop check - if (gDisableStructs[battlerAtk].throatChopTimer > gBattleTurnCounter && IsSoundMove(move)) + if (gDisableStructs[battlerAtk].throatChopTimer > 0 && IsSoundMove(move)) return 0; // Can't even select move at all // heal block check if (gBattleMons[battlerAtk].volatiles.healBlock && IsHealBlockPreventingMove(battlerAtk, move)) @@ -1437,7 +1448,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) } break; case EFFECT_CHARGE: - if (gBattleMons[battlerAtk].volatiles.charge) + if (gBattleMons[battlerAtk].volatiles.chargeTimer > 0) ADJUST_SCORE(-20); else if (!HasMoveWithType(battlerAtk, TYPE_ELECTRIC)) ADJUST_SCORE(-10); @@ -1447,7 +1458,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) break; case EFFECT_QUIVER_DANCE: case EFFECT_GEOMANCY: - if (HasBattlerSideAbility(battlerDef, ABILITY_UNAWARE, aiData)) + if (AI_IsAbilityOnSide(battlerDef, ABILITY_UNAWARE)) ADJUST_SCORE(-10); if (gBattleMons[battlerAtk].statStages[STAT_SPATK] >= MAX_STAT_STAGE || !HasMoveWithCategory(battlerAtk, DAMAGE_CATEGORY_SPECIAL)) ADJUST_SCORE(-10); @@ -1498,10 +1509,10 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) if (hasPartner) { if (!(IS_BATTLER_OF_TYPE(battlerAtk, TYPE_GRASS) - && IsBattlerGrounded(battlerAtk) + && AI_IsBattlerGrounded(battlerAtk) && (BattlerStatCanRise(battlerAtk, aiData->abilities[battlerAtk], STAT_ATK) || BattlerStatCanRise(battlerAtk, aiData->abilities[battlerAtk], STAT_SPATK))) && !(IS_BATTLER_OF_TYPE(BATTLE_PARTNER(battlerAtk), TYPE_GRASS) - && IsBattlerGrounded(BATTLE_PARTNER(battlerAtk)) + && AI_IsBattlerGrounded(BATTLE_PARTNER(battlerAtk)) && aiData->abilities[BATTLE_PARTNER(battlerAtk)] != ABILITY_CONTRARY && (BattlerStatCanRise(BATTLE_PARTNER(battlerAtk), aiData->abilities[BATTLE_PARTNER(battlerAtk)], STAT_ATK) || BattlerStatCanRise(BATTLE_PARTNER(battlerAtk), aiData->abilities[BATTLE_PARTNER(battlerAtk)], STAT_SPATK)))) @@ -1510,7 +1521,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) } } else if (!(IS_BATTLER_OF_TYPE(battlerAtk, TYPE_GRASS) - && IsBattlerGrounded(battlerAtk) + && AI_IsBattlerGrounded(battlerAtk) && (BattlerStatCanRise(battlerAtk, aiData->abilities[battlerAtk], STAT_ATK) || BattlerStatCanRise(battlerAtk, aiData->abilities[battlerAtk], STAT_SPATK)))) { ADJUST_SCORE(-10); @@ -1526,12 +1537,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) ADJUST_SCORE(-8); break; } - else if (!hasPartner) - { - ADJUST_SCORE(-10); // no partner and our stats wont rise, so don't use - } - - if (hasPartner) + else if (hasPartner) { if (aiData->abilities[BATTLE_PARTNER(battlerAtk)] == ABILITY_PLUS || aiData->abilities[BATTLE_PARTNER(battlerAtk)] == ABILITY_MINUS) { @@ -1544,6 +1550,10 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) ADJUST_SCORE(-10); // nor our or our partner's ability is plus/minus } } + else + { + ADJUST_SCORE(-10); // no partner and our stats wont rise, so don't use + } break; case EFFECT_ACUPRESSURE: if (DoesSubstituteBlockMove(battlerAtk, battlerDef, move) || AreBattlersStatsMaxed(battlerDef)) @@ -1557,12 +1567,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) else if (!BattlerStatCanRise(battlerAtk, aiData->abilities[battlerAtk], STAT_SPDEF)) ADJUST_SCORE(-8); } - else if (!hasPartner) - { - ADJUST_SCORE(-10); // our stats wont rise from this move - } - - if (hasPartner) + else if (hasPartner) { if (aiData->abilities[BATTLE_PARTNER(battlerAtk)] == ABILITY_PLUS || aiData->abilities[BATTLE_PARTNER(battlerAtk)] == ABILITY_MINUS) { @@ -1576,6 +1581,10 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) ADJUST_SCORE(-10); // nor our or our partner's ability is plus/minus } } + else + { + ADJUST_SCORE(-10); // our stats wont rise from this move + } break; // stat lowering effects case EFFECT_ATTACK_DOWN: @@ -1720,7 +1729,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) ADJUST_SCORE(-10); break; case EFFECT_SHEER_COLD: - if (GetGenConfig(GEN_CONFIG_SHEER_COLD_IMMUNITY) >= GEN_7 && IS_BATTLER_OF_TYPE(battlerDef, TYPE_ICE)) + if (GetConfig(CONFIG_SHEER_COLD_IMMUNITY) >= GEN_7 && IS_BATTLER_OF_TYPE(battlerDef, TYPE_ICE)) RETURN_SCORE_MINUS(20); // fallthrough case EFFECT_OHKO: @@ -1784,7 +1793,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) { if (AI_IsFaster(battlerAtk, battlerDef, move, predictedMoveSpeedCheck, CONSIDER_PRIORITY)) // Attacker should go first { - if (gLastMoves[battlerDef] == MOVE_NONE || gLastMoves[battlerDef] == 0xFFFF) + if (aiData->lastUsedMove[battlerDef] == MOVE_NONE) ADJUST_SCORE(-10); // no anticipated move to disable } else if (predictedMove == MOVE_NONE) @@ -1806,7 +1815,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) { if (AI_IsFaster(battlerAtk, battlerDef, move, predictedMoveSpeedCheck, CONSIDER_PRIORITY)) // Attacker should go first { - if (gLastMoves[battlerDef] == MOVE_NONE || gLastMoves[battlerDef] == 0xFFFF) + if (aiData->lastUsedMove[battlerDef] == MOVE_NONE) ADJUST_SCORE(-10); // no anticipated move to encore } else if (predictedMove == MOVE_NONE) @@ -1892,15 +1901,15 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) { if (CountUsablePartyMons(battlerAtk) == 0 && aiData->abilities[battlerAtk] != ABILITY_SOUNDPROOF - && aiData->abilities[BATTLE_PARTNER(battlerAtk)] != ABILITY_SOUNDPROOF - && CountUsablePartyMons(FOE(battlerAtk)) >= 1) + && CountUsablePartyMons(battlerDef) >= 1 + && (aiData->abilities[BATTLE_PARTNER(battlerAtk)] != ABILITY_SOUNDPROOF || !IsBattlerAlive(BATTLE_PARTNER(battlerAtk)))) { ADJUST_SCORE(-10); //Don't wipe your team if you're going to lose } - else if ((!IsBattlerAlive(FOE(battlerAtk)) || aiData->abilities[FOE(battlerAtk)] == ABILITY_SOUNDPROOF - || gBattleMons[FOE(battlerAtk)].volatiles.perishSong) - && (!IsBattlerAlive(BATTLE_PARTNER(FOE(battlerAtk))) || aiData->abilities[BATTLE_PARTNER(FOE(battlerAtk))] == ABILITY_SOUNDPROOF - || gBattleMons[BATTLE_PARTNER(FOE(battlerAtk))].volatiles.perishSong)) + else if ((!IsBattlerAlive(LEFT_FOE(battlerAtk)) || aiData->abilities[LEFT_FOE(battlerAtk)] == ABILITY_SOUNDPROOF + || gBattleMons[LEFT_FOE(battlerAtk)].volatiles.perishSong) + && (!IsBattlerAlive(RIGHT_FOE(battlerAtk)) || aiData->abilities[RIGHT_FOE(battlerAtk)] == ABILITY_SOUNDPROOF + || gBattleMons[RIGHT_FOE(battlerAtk)].volatiles.perishSong)) { ADJUST_SCORE(-10); //Both enemies are perish songed } @@ -1915,7 +1924,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) && CountUsablePartyMons(battlerDef) >= 1) ADJUST_SCORE(-10); - if (gBattleMons[FOE(battlerAtk)].volatiles.perishSong || aiData->abilities[FOE(battlerAtk)] == ABILITY_SOUNDPROOF) + if (gBattleMons[battlerDef].volatiles.perishSong || aiData->abilities[battlerDef] == ABILITY_SOUNDPROOF) ADJUST_SCORE(-10); } break; @@ -1981,16 +1990,16 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) break; case EFFECT_BELLY_DRUM: case EFFECT_FILLET_AWAY: - if (HasBattlerSideAbility(battlerDef, ABILITY_UNAWARE, aiData)) + if (AI_IsAbilityOnSide(battlerDef, ABILITY_UNAWARE)) ADJUST_SCORE(-10); if (aiData->abilities[battlerAtk] == ABILITY_CONTRARY) ADJUST_SCORE(-10); - else if (aiData->hpPercents[battlerAtk] <= 60) + else if (aiData->hpPercents[battlerAtk] <= 60 && !IsConsideringZMove(battlerAtk, battlerDef, move)) ADJUST_SCORE(-10); break; case EFFECT_FUTURE_SIGHT: - if (gSideStatuses[GetBattlerSide(battlerDef)] & SIDE_STATUS_FUTUREATTACK - || gSideStatuses[GetBattlerSide(battlerAtk)] & SIDE_STATUS_FUTUREATTACK) + if (gWishFutureKnock.futureSightCounter[LEFT_FOE(battlerAtk)] > 0 + || gWishFutureKnock.futureSightCounter[RIGHT_FOE(battlerAtk)] > 0) ADJUST_SCORE(-12); else ADJUST_SCORE(GOOD_EFFECT); @@ -2048,6 +2057,15 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) ADJUST_SCORE(-20); break; case EFFECT_TRICK: + if ((gBattleMons[battlerAtk].item == ITEM_NONE && aiData->items[battlerDef] == ITEM_NONE) + || !CanBattlerGetOrLoseItem(battlerAtk, gBattleMons[battlerAtk].item) + || !CanBattlerGetOrLoseItem(battlerAtk, aiData->items[battlerDef]) + || !CanBattlerGetOrLoseItem(battlerDef, aiData->items[battlerDef]) + || !CanBattlerGetOrLoseItem(battlerDef, gBattleMons[battlerAtk].item) + || aiData->abilities[battlerAtk] == ABILITY_STICKY_HOLD + || aiData->abilities[battlerDef] == ABILITY_STICKY_HOLD + || DoesSubstituteBlockMove(battlerAtk, battlerDef, move)) + ADJUST_SCORE(-10); case EFFECT_KNOCK_OFF: case EFFECT_CORROSIVE_GAS: if (aiData->abilities[battlerDef] == ABILITY_STICKY_HOLD) @@ -2062,7 +2080,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) ADJUST_SCORE(-10); break; case EFFECT_RECYCLE: - if (GetUsedHeldItem(battlerAtk) == 0 || gBattleMons[battlerAtk].item != 0) + if (GetBattlerPartyState(battlerAtk)->usedHeldItem == 0 || gBattleMons[battlerAtk].item != 0) ADJUST_SCORE(-10); break; case EFFECT_IMPRISON: @@ -2070,7 +2088,8 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) ADJUST_SCORE(-10); break; case EFFECT_REFRESH: - if (!(gBattleMons[battlerAtk].status1 & STATUS1_CAN_MOVE)) + if (!(gBattleMons[battlerAtk].status1 & STATUS1_CAN_MOVE) + || !ShouldCureStatus(battlerAtk, battlerAtk, aiData)) ADJUST_SCORE(-10); break; case EFFECT_PSYCHO_SHIFT: @@ -2168,15 +2187,32 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) else if ((AI_GetWeather() & (B_WEATHER_LOW_LIGHT))) ADJUST_SCORE(-3); break; + case EFFECT_LIFE_DEW: + if (AI_BattlerAtMaxHp(battlerAtk)) + { + if (hasPartner) + { + if (AI_BattlerAtMaxHp(BATTLE_PARTNER(battlerAtk))) + ADJUST_SCORE(-10); + } + else + { + ADJUST_SCORE(-10); + } + } + break; case EFFECT_PURIFY: if (!(gBattleMons[battlerDef].status1 & STATUS1_ANY)) ADJUST_SCORE(-10); else if (battlerDef == BATTLE_PARTNER(battlerAtk)) break; //Always heal your ally - else if (AI_BattlerAtMaxHp(battlerAtk)) - ADJUST_SCORE(-10); - else if (aiData->hpPercents[battlerAtk] >= 90) - ADJUST_SCORE(-8); //No point in healing, but should at least do it if nothing better + else if (!ShouldCureStatus(battlerAtk, battlerDef, aiData)) + { + if (AI_BattlerAtMaxHp(battlerAtk)) + ADJUST_SCORE(-10); + else if (aiData->hpPercents[battlerAtk] >= 90) + ADJUST_SCORE(-8); //No point in healing, but should at least do it if nothing better + } break; case EFFECT_RECOIL_IF_MISS: if (aiData->abilities[battlerAtk] != ABILITY_MAGIC_GUARD && gAiLogicData->moveAccuracy[battlerAtk][battlerDef][gAiThinkingStruct->movesetIndex] < 75 @@ -2193,13 +2229,12 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) case EFFECT_MIMIC: if (AI_IsFaster(battlerAtk, battlerDef, move, predictedMoveSpeedCheck, CONSIDER_PRIORITY)) // Attacker should go first { - if (gLastMoves[battlerDef] == MOVE_NONE - || gLastMoves[battlerDef] == 0xFFFF) + if (aiData->lastUsedMove[battlerDef] == MOVE_NONE) ADJUST_SCORE(-10); } else if (predictedMove == MOVE_NONE) { - // TODO predicted move separate from gLastMoves + // TODO predicted move separate from aiData->lastUsedMove ADJUST_SCORE(-10); } break; @@ -2223,13 +2258,13 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) ADJUST_SCORE(-8); break; case EFFECT_SKETCH: - if (gLastMoves[battlerDef] == MOVE_NONE) + if (aiData->lastUsedMove[battlerDef] == MOVE_NONE) ADJUST_SCORE(-10); break; case EFFECT_DESTINY_BOND: if (DoesDestinyBondFail(battlerAtk)) ADJUST_SCORE(-10); - if (gBattleMons[battlerDef].volatiles.destinyBond) + if (gBattleMons[battlerAtk].volatiles.destinyBond) ADJUST_SCORE(-10); else if (GetActiveGimmick(battlerDef) == GIMMICK_DYNAMAX) ADJUST_SCORE(-10); @@ -2256,7 +2291,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) } break; case PROTECT_WIDE_GUARD: - if(!(GetBattlerMoveTargetType(battlerAtk, predictedMove) & (MOVE_TARGET_FOES_AND_ALLY | MOVE_TARGET_BOTH))) + if (!(GetBattlerMoveTargetType(battlerAtk, predictedMove) & (MOVE_TARGET_FOES_AND_ALLY | MOVE_TARGET_BOTH))) { ADJUST_SCORE(-10); decreased = TRUE; @@ -2331,11 +2366,11 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) ADJUST_SCORE(-9); break; case EFFECT_COURT_CHANGE: - if (gSideStatuses[GetBattlerSide(FOE(battlerAtk))] & SIDE_STATUS_BAD_COURT) + if (gSideStatuses[GetBattlerSide(battlerDef)] & SIDE_STATUS_BAD_COURT) ADJUST_SCORE(BAD_EFFECT); if (gSideStatuses[GetBattlerSide(battlerAtk)] & SIDE_STATUS_GOOD_COURT) ADJUST_SCORE(BAD_EFFECT); - if (AreAnyHazardsOnSide(GetBattlerSide(FOE(battlerAtk))) && CountUsablePartyMons(battlerAtk) != 0) + if (AreAnyHazardsOnSide(GetBattlerSide(battlerDef)) && CountUsablePartyMons(battlerAtk) != 0) ADJUST_SCORE(WORST_EFFECT); if (hasPartner) { @@ -2424,12 +2459,16 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) ADJUST_SCORE(-10); break; case EFFECT_BESTOW: - if (aiData->holdEffects[battlerAtk] == HOLD_EFFECT_NONE - || !CanBattlerGetOrLoseItem(battlerAtk, gBattleMons[battlerAtk].item)) // AI knows its own item + if (gBattleMons[battlerAtk].item == ITEM_NONE + || aiData->items[battlerDef] != ITEM_NONE + || !CanBattlerGetOrLoseItem(battlerAtk, gBattleMons[battlerAtk].item) // AI knows its own item + || !CanBattlerGetOrLoseItem(battlerDef, gBattleMons[battlerAtk].item) + || aiData->abilities[battlerAtk] == ABILITY_STICKY_HOLD + || DoesSubstituteBlockMove(battlerAtk, battlerDef, move)) ADJUST_SCORE(-10); break; case EFFECT_WISH: - if (gWishFutureKnock.wishCounter[battlerAtk] > gBattleTurnCounter) + if (gWishFutureKnock.wishCounter[battlerAtk] > 0) ADJUST_SCORE(-10); break; case EFFECT_ASSIST: @@ -2452,10 +2491,9 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) case EFFECT_ENTRAINMENT: case EFFECT_GASTRO_ACID: case EFFECT_ROLE_PLAY: - case EFFECT_SIMPLE_BEAM: case EFFECT_SKILL_SWAP: - case EFFECT_WORRY_SEED: - if (!CanEffectChangeAbility(battlerAtk, battlerDef, moveEffect, aiData) + case EFFECT_OVERWRITE_ABILITY: + if (!CanEffectChangeAbility(battlerAtk, battlerDef, move, aiData) || DoesPartnerHaveSameMoveEffect(BATTLE_PARTNER(battlerAtk), battlerDef, move, aiData->partnerMove)) ADJUST_AND_RETURN_SCORE(NO_DAMAGE_OR_FAILS); break; @@ -2600,7 +2638,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) { // This only happens if the ally already rolled on double trick room on final turn. // Both Pokemon use Trick Room on the final turn of Trick Room to anticipate both opponents Protecting to stall out. - if (gFieldStatuses & STATUS_FIELD_TRICK_ROOM && gFieldTimers.trickRoomTimer == (gBattleTurnCounter + 1)) + if (gFieldStatuses & STATUS_FIELD_TRICK_ROOM && gFieldTimers.trickRoomTimer == 1) ADJUST_SCORE(PERFECT_EFFECT); else ADJUST_SCORE(-10); @@ -2611,7 +2649,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) if (!(gFieldStatuses & STATUS_FIELD_TRICK_ROOM) && !ShouldSetFieldStatus(battlerAtk, STATUS_FIELD_TRICK_ROOM)) ADJUST_SCORE(-10); // Don't unset a trick room that doesn't harm you unless it's about to expire. - else if ((gFieldStatuses & STATUS_FIELD_TRICK_ROOM) && gFieldTimers.trickRoomTimer != (gBattleTurnCounter + 1) && !ShouldClearFieldStatus(battlerAtk, STATUS_FIELD_TRICK_ROOM)) + else if ((gFieldStatuses & STATUS_FIELD_TRICK_ROOM) && gFieldTimers.trickRoomTimer > 1 && !ShouldClearFieldStatus(battlerAtk, STATUS_FIELD_TRICK_ROOM)) ADJUST_SCORE(-10); } break; @@ -2687,7 +2725,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) break; case EFFECT_SOAK: { - u32 types[3]; + enum Type types[3]; u32 typeArg = GetMoveArgType(move); GetBattlerTypes(battlerDef, FALSE, types); @@ -2746,6 +2784,8 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) case EFFECT_HOLD_HANDS: case EFFECT_CELEBRATE: case EFFECT_HAPPY_HOUR: + if (IsConsideringZMove(battlerAtk, battlerDef, move)) + break; ADJUST_SCORE(-10); break; case EFFECT_INSTRUCT: @@ -2754,13 +2794,13 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) if (AI_IsSlower(battlerAtk, battlerDef, move, predictedMoveSpeedCheck, CONSIDER_PRIORITY)) instructedMove = predictedMove; else - instructedMove = gLastMoves[battlerDef]; + instructedMove = aiData->lastUsedMove[battlerDef]; if (instructedMove == MOVE_NONE || IsMoveInstructBanned(instructedMove) || MoveHasAdditionalEffectSelf(instructedMove, MOVE_EFFECT_RECHARGE) || IsZMove(instructedMove) - || (gLockedMoves[battlerDef] != 0 && gLockedMoves[battlerDef] != 0xFFFF) + || (gLockedMoves[battlerDef] != MOVE_NONE && gLockedMoves[battlerDef] != MOVE_UNAVAILABLE) || gBattleMons[battlerDef].volatiles.multipleTurns || PartnerMoveIsSameAsAttacker(BATTLE_PARTNER(battlerAtk), battlerDef, move, aiData->partnerMove)) { @@ -2808,7 +2848,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) case EFFECT_TAILWIND: if (gSideStatuses[GetBattlerSide(battlerAtk)] & SIDE_STATUS_TAILWIND || PartnerMoveEffectIs(BATTLE_PARTNER(battlerAtk), aiData->partnerMove, EFFECT_TAILWIND) - || (gFieldStatuses & STATUS_FIELD_TRICK_ROOM && gFieldTimers.trickRoomTimer != (gBattleTurnCounter + 1))) + || (gFieldStatuses & STATUS_FIELD_TRICK_ROOM && gFieldTimers.trickRoomTimer == 1)) ADJUST_SCORE(-10); break; case EFFECT_LUCKY_CHANT: @@ -2818,12 +2858,12 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) break; case EFFECT_MAGNET_RISE: if (gFieldStatuses & STATUS_FIELD_GRAVITY - || gDisableStructs[battlerAtk].magnetRiseTimer > gBattleTurnCounter + || gDisableStructs[battlerAtk].magnetRiseTimer > 0 || aiData->holdEffects[battlerAtk] == HOLD_EFFECT_IRON_BALL || gBattleMons[battlerAtk].volatiles.smackDown || gBattleMons[battlerAtk].volatiles.root || gBattleMons[battlerAtk].volatiles.magnetRise - || !IsBattlerGrounded(battlerAtk)) + || !AI_IsBattlerGrounded(battlerAtk)) ADJUST_SCORE(-10); break; case EFFECT_CAMOUFLAGE: @@ -2857,7 +2897,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) ADJUST_SCORE(-10); break; case EFFECT_NO_RETREAT: - if (gDisableStructs[battlerAtk].noRetreat) + if (gBattleMons[battlerAtk].volatiles.noRetreat) ADJUST_SCORE(-10); break; case EFFECT_EXTREME_EVOBOOST: @@ -2878,12 +2918,17 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) ADJUST_SCORE(-10); break; case EFFECT_JUNGLE_HEALING: - if (AI_BattlerAtMaxHp(battlerAtk) - && AI_BattlerAtMaxHp(BATTLE_PARTNER(battlerAtk)) - && !(gBattleMons[battlerAtk].status1 & STATUS1_ANY) - && !(gBattleMons[BATTLE_PARTNER(battlerAtk)].status1 & STATUS1_ANY)) + { + bool32 canCureSelf = (gBattleMons[battlerAtk].status1 & STATUS1_ANY) && ShouldCureStatus(battlerAtk, battlerAtk, aiData); + bool32 canCurePartner = (gBattleMons[BATTLE_PARTNER(battlerAtk)].status1 & STATUS1_ANY) && ShouldCureStatus(battlerAtk, BATTLE_PARTNER(battlerAtk), aiData); + + if (AI_BattlerAtMaxHp(battlerAtk) + && AI_BattlerAtMaxHp(BATTLE_PARTNER(battlerAtk)) + && !canCureSelf + && !canCurePartner) ADJUST_SCORE(-10); break; + } case EFFECT_TAKE_HEART: if ((!(gBattleMons[battlerAtk].status1 & STATUS1_ANY) || PartnerMoveEffectIs(BATTLE_PARTNER(battlerAtk), aiData->partnerMove, EFFECT_JUNGLE_HEALING) @@ -2969,7 +3014,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) else if (GetBattleMoveCategory(move) == DAMAGE_CATEGORY_STATUS && (CountUsablePartyMons(battlerAtk) < 1 || gAiLogicData->mostSuitableMonId[battlerAtk] == PARTY_SIZE - || (!AI_CanBattlerEscape(battlerAtk) && IsBattlerTrapped(battlerDef, battlerAtk)))) + || IsBattlerTrapped(battlerDef, battlerAtk))) ADJUST_SCORE(-30); } @@ -2979,6 +3024,19 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) return score; } +static s32 AI_GetWhichBattlerFasterOrTies(u32 battlerAtk, u32 battlerDef, bool32 ignoreChosenMoves) +{ + struct BattleContext ctx = {0}; + ctx.battlerAtk = battlerAtk; + ctx.battlerDef = battlerDef; + ctx.abilities[battlerAtk] = gAiLogicData->abilities[battlerAtk]; + ctx.abilities[battlerDef] = gAiLogicData->abilities[battlerDef]; + ctx.holdEffects[battlerAtk] = gAiLogicData->holdEffects[battlerAtk]; + ctx.holdEffects[battlerDef] = gAiLogicData->holdEffects[battlerDef]; + + return GetWhichBattlerFasterOrTies(&ctx, ignoreChosenMoves); +} + static s32 AI_TryToFaint(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) { u32 movesetIndex = gAiThinkingStruct->movesetIndex; @@ -3000,7 +3058,7 @@ static s32 AI_TryToFaint(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) ADJUST_SCORE(SLOW_KILL); } else if (CanTargetFaintAi(battlerDef, battlerAtk) - && GetWhichBattlerFasterOrTies(battlerAtk, battlerDef, TRUE) != AI_IS_FASTER + && AI_GetWhichBattlerFasterOrTies(battlerAtk, battlerDef, TRUE) != AI_IS_FASTER && GetBattleMovePriority(battlerAtk, gAiLogicData->abilities[battlerAtk], move) > 0) { if (RandomPercentage(RNG_AI_PRIORITIZE_LAST_CHANCE, PRIORITIZE_LAST_CHANCE_CHANCE)) @@ -3016,7 +3074,7 @@ static s32 AI_TryToFaint(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) { // move data - u32 moveType = GetMoveType(move); + enum Type moveType = GetMoveType(move); enum BattleMoveEffects effect = GetMoveEffect(move); u32 moveTarget = GetBattlerMoveTargetType(battlerAtk, move); // ally data @@ -3100,38 +3158,38 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) } else { - u32 ownHitsToKOFoe1 = GetBestNoOfHitsToKO(battlerAtk, BATTLE_OPPOSITE(battlerAtk), AI_ATTACKING); - u32 partnerHitsToKOFoe1 = GetBestNoOfHitsToKO(battlerAtkPartner, BATTLE_OPPOSITE(battlerAtk), AI_ATTACKING); - u32 ownHitsToKOFoe2 = GetBestNoOfHitsToKO(battlerAtk, BATTLE_OPPOSITE(battlerAtkPartner), AI_ATTACKING); - u32 partnerHitsToKOFoe2 = GetBestNoOfHitsToKO(battlerAtkPartner, BATTLE_OPPOSITE(battlerAtkPartner), AI_ATTACKING); + u32 ownHitsToKOFoe1 = GetBestNoOfHitsToKO(battlerAtk, LEFT_FOE(battlerAtk), AI_ATTACKING); + u32 partnerHitsToKOFoe1 = GetBestNoOfHitsToKO(battlerAtkPartner, LEFT_FOE(battlerAtk), AI_ATTACKING); + u32 ownHitsToKOFoe2 = GetBestNoOfHitsToKO(battlerAtk, RIGHT_FOE(battlerAtk), AI_ATTACKING); + u32 partnerHitsToKOFoe2 = GetBestNoOfHitsToKO(battlerAtkPartner, RIGHT_FOE(battlerAtk), AI_ATTACKING); if (hasTwoOpponents) { // Might be about to die - if (CanTargetFaintAi(BATTLE_OPPOSITE(battlerAtk), battlerAtk) && CanTargetFaintAi(BATTLE_OPPOSITE(battlerAtkPartner), battlerAtk) - && AI_IsSlower(battlerAtk, BATTLE_OPPOSITE(battlerAtk), move, predictedMove, DONT_CONSIDER_PRIORITY) - && AI_IsSlower(battlerAtk, BATTLE_OPPOSITE(battlerAtkPartner), move, predictedMove, DONT_CONSIDER_PRIORITY)) + if (CanTargetFaintAi(LEFT_FOE(battlerAtk), battlerAtk) && CanTargetFaintAi(RIGHT_FOE(battlerAtk), battlerAtk) + && AI_IsSlower(battlerAtk, LEFT_FOE(battlerAtk), move, predictedMove, DONT_CONSIDER_PRIORITY) + && AI_IsSlower(battlerAtk, RIGHT_FOE(battlerAtk), move, predictedMove, DONT_CONSIDER_PRIORITY)) ADJUST_SCORE(GOOD_EFFECT); if (ownHitsToKOFoe1 > partnerHitsToKOFoe1 && partnerHitsToKOFoe1 > 1 && ownHitsToKOFoe2 > partnerHitsToKOFoe2 && partnerHitsToKOFoe2 > 1) ADJUST_SCORE(GOOD_EFFECT); } - else if (IsBattlerAlive(BATTLE_OPPOSITE(battlerAtk))) + else if (IsBattlerAlive(LEFT_FOE(battlerAtk))) { // Might be about to die - if (CanTargetFaintAi(BATTLE_OPPOSITE(battlerAtk), battlerAtk) - && AI_IsSlower(battlerAtk, BATTLE_OPPOSITE(battlerAtk), move, predictedMove, DONT_CONSIDER_PRIORITY)) + if (CanTargetFaintAi(LEFT_FOE(battlerAtk), battlerAtk) + && AI_IsSlower(battlerAtk, LEFT_FOE(battlerAtk), move, predictedMove, DONT_CONSIDER_PRIORITY)) ADJUST_SCORE(GOOD_EFFECT); if (ownHitsToKOFoe1 > partnerHitsToKOFoe1 && partnerHitsToKOFoe1 > 1) ADJUST_SCORE(GOOD_EFFECT); } - else if (IsBattlerAlive(BATTLE_OPPOSITE(battlerAtkPartner))) + else if (IsBattlerAlive(RIGHT_FOE(battlerAtk))) { // Might be about to die - if (CanTargetFaintAi(BATTLE_OPPOSITE(battlerAtkPartner), battlerAtk) - && AI_IsSlower(battlerAtk, BATTLE_OPPOSITE(battlerAtkPartner), move, predictedMove, DONT_CONSIDER_PRIORITY)) + if (CanTargetFaintAi(RIGHT_FOE(battlerAtk), battlerAtk) + && AI_IsSlower(battlerAtk, RIGHT_FOE(battlerAtk), move, predictedMove, DONT_CONSIDER_PRIORITY)) ADJUST_SCORE(GOOD_EFFECT); if (ownHitsToKOFoe2 > partnerHitsToKOFoe2 && partnerHitsToKOFoe2 > 1) @@ -3145,7 +3203,7 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) ADJUST_SCORE(WEAK_EFFECT); break; case EFFECT_MAGNET_RISE: - if (IsBattlerGrounded(battlerAtk) + if (AI_IsBattlerGrounded(battlerAtk) && (HasMoveWithEffect(battlerAtkPartner, EFFECT_EARTHQUAKE) || HasMoveWithEffect(battlerAtkPartner, EFFECT_MAGNITUDE)) && (AI_GetMoveEffectiveness(MOVE_EARTHQUAKE, battlerAtk, battlerAtkPartner) != UQ_4_12(0.0))) // Doesn't resist ground move { @@ -3163,6 +3221,20 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) || HasMoveWithCriticalHitChance(battlerAtkPartner)) ADJUST_SCORE(GOOD_EFFECT); break; + case EFFECT_COACHING: + if (!hasPartner + || !HasMoveWithCategory(battlerAtkPartner, DAMAGE_CATEGORY_PHYSICAL)) + { + ADJUST_SCORE(WORST_EFFECT); + } + else + { + ADJUST_SCORE(IncreaseStatUpScore(battlerAtkPartner, BATTLE_OPPOSITE(battlerAtk), STAT_CHANGE_ATK)); + ADJUST_SCORE(IncreaseStatUpScore(battlerAtkPartner, BATTLE_OPPOSITE(battlerAtk), STAT_CHANGE_DEF)); + ADJUST_SCORE(IncreaseStatUpScore(battlerAtkPartner, BATTLE_OPPOSITE(battlerAtkPartner), STAT_CHANGE_ATK)); + ADJUST_SCORE(IncreaseStatUpScore(battlerAtkPartner, BATTLE_OPPOSITE(battlerAtkPartner), STAT_CHANGE_DEF)); + } + break; default: break; } // our effect relative to partner @@ -3173,7 +3245,7 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) // Both Pokemon use Trick Room on the final turn of Trick Room to anticipate both opponents Protecting to stall out. // This unsets Trick Room and resets it with a full timer. case EFFECT_TRICK_ROOM: - if (hasPartner && gFieldStatuses & STATUS_FIELD_TRICK_ROOM && gFieldTimers.trickRoomTimer == (gBattleTurnCounter + 1) + if (hasPartner && gFieldStatuses & STATUS_FIELD_TRICK_ROOM && gFieldTimers.trickRoomTimer == 1 && ShouldSetFieldStatus(battlerAtk, STATUS_FIELD_TRICK_ROOM) && HasMoveWithEffect(battlerAtkPartner, EFFECT_TRICK_ROOM) && RandomPercentage(RNG_AI_REFRESH_TRICK_ROOM_ON_LAST_TURN, DOUBLE_TRICK_ROOM_ON_LAST_TURN_CHANCE)) @@ -3181,7 +3253,7 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) break; case EFFECT_TAILWIND: // Anticipate both opponents protecting to stall out Trick Room, and apply Tailwind. - if (gFieldStatuses & STATUS_FIELD_TRICK_ROOM && gFieldTimers.trickRoomTimer == (gBattleTurnCounter + 1) + if (gFieldStatuses & STATUS_FIELD_TRICK_ROOM && gFieldTimers.trickRoomTimer == 1 && RandomPercentage(RNG_AI_APPLY_TAILWIND_ON_LAST_TURN_OF_TRICK_ROOM, TAILWIND_IN_TRICK_ROOM_CHANCE)) ADJUST_SCORE(BEST_EFFECT); break; @@ -3550,10 +3622,9 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) case EFFECT_ENTRAINMENT: case EFFECT_GASTRO_ACID: case EFFECT_ROLE_PLAY: - case EFFECT_SIMPLE_BEAM: case EFFECT_SKILL_SWAP: - case EFFECT_WORRY_SEED: - AbilityChangeScore(battlerAtk, battlerAtkPartner, effect, &score, aiData); + case EFFECT_OVERWRITE_ABILITY: + AbilityChangeScore(battlerAtk, battlerAtkPartner, move, &score, aiData); return score; case EFFECT_SPICY_EXTRACT: if (AI_ShouldSpicyExtract(battlerAtk, battlerAtkPartner, move, aiData)) @@ -3565,8 +3636,18 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) if (gBattleMons[battlerAtkPartner].status1 & STATUS1_ANY) { if (gBattleMons[battlerAtkPartner].status1 & STATUS1_CAN_MOVE) + { + if (ShouldCureStatus(battlerAtk, battlerAtkPartner, aiData)) + ADJUST_SCORE(DECENT_EFFECT); + } + else + { + ADJUST_SCORE(DECENT_EFFECT); + } + + if ((!IsBattlerAlive(LEFT_FOE(battlerAtk)) || ShouldRecover(battlerAtk, LEFT_FOE(battlerAtk), move, 50)) + && (!IsBattlerAlive(RIGHT_FOE(battlerAtk)) || ShouldRecover(battlerAtk, RIGHT_FOE(battlerAtk), move, 50))) RETURN_SCORE_PLUS(WEAK_EFFECT); - RETURN_SCORE_PLUS(GOOD_EFFECT); } break; case EFFECT_SWAGGER: @@ -3619,7 +3700,7 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) if (AI_IsFaster(battlerAtk, battlerAtkPartner, move, predictedMoveSpeedCheck, CONSIDER_PRIORITY)) instructedMove = aiData->partnerMove; else - instructedMove = gLastMoves[battlerAtkPartner]; + instructedMove = aiData->lastUsedMove[battlerAtkPartner]; if (instructedMove != MOVE_NONE && !IsBattleMoveStatus(instructedMove) @@ -3633,8 +3714,8 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) if (!(gFieldStatuses & STATUS_FIELD_TRICK_ROOM) && HasMoveWithEffect(battlerAtkPartner, EFFECT_TRICK_ROOM)) ADJUST_SCORE(DECENT_EFFECT); - if (AI_IsSlower(battlerAtkPartner, FOE(battlerAtkPartner), aiData->partnerMove, predictedMoveSpeedCheck, CONSIDER_PRIORITY) // Opponent mon 1 goes before partner - && AI_IsSlower(battlerAtkPartner, BATTLE_PARTNER(FOE(battlerAtkPartner)), aiData->partnerMove, predictedMoveSpeedCheck, CONSIDER_PRIORITY)) // Opponent mon 2 goes before partner + if (AI_IsSlower(battlerAtkPartner, LEFT_FOE(battlerAtk), aiData->partnerMove, predictedMoveSpeedCheck, CONSIDER_PRIORITY) // Opponent mon 1 goes before partner + && AI_IsSlower(battlerAtkPartner, RIGHT_FOE(battlerAtk), aiData->partnerMove, predictedMoveSpeedCheck, CONSIDER_PRIORITY)) // Opponent mon 2 goes before partner { if (partnerEffect == EFFECT_COUNTER || partnerEffect == EFFECT_MIRROR_COAT) break; // These moves need to go last @@ -3643,8 +3724,8 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) break; case EFFECT_HEAL_PULSE: case EFFECT_HIT_ENEMY_HEAL_ALLY: - if (AI_IsFaster(battlerAtk, FOE(battlerAtk), move, predictedMoveSpeedCheck, CONSIDER_PRIORITY) - && AI_IsFaster(battlerAtk, BATTLE_PARTNER(FOE(battlerAtk)), move, predictedMoveSpeedCheck, CONSIDER_PRIORITY) + if (AI_IsFaster(battlerAtk, LEFT_FOE(battlerAtk), move, predictedMoveSpeedCheck, CONSIDER_PRIORITY) + && AI_IsFaster(battlerAtk, RIGHT_FOE(battlerAtk), move, predictedMoveSpeedCheck, CONSIDER_PRIORITY) && gBattleMons[battlerAtkPartner].hp < gBattleMons[battlerAtkPartner].maxHP / 2) RETURN_SCORE_PLUS(WEAK_EFFECT); break; @@ -3731,7 +3812,7 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) return score; } -static bool32 IsPinchBerryItemEffect(enum ItemHoldEffect holdEffect) +static bool32 IsPinchBerryItemEffect(enum HoldEffect holdEffect) { switch (holdEffect) { @@ -3962,10 +4043,9 @@ static void AI_CompareDamagingMoves(u32 battlerAtk, u32 battlerDef) } } -static u32 AI_CalcHoldEffectMoveScore(u32 battlerAtk, u32 battlerDef, u32 move) +static s32 AI_CalcHoldEffectMoveScore(u32 battlerAtk, u32 battlerDef, u32 move, struct AiLogicData *aiData) { - struct AiLogicData *aiData = gAiLogicData; - enum ItemHoldEffect holdEffect = aiData->holdEffects[battlerAtk]; + enum HoldEffect holdEffect = aiData->holdEffects[battlerAtk]; s32 score = 0; @@ -3992,18 +4072,17 @@ static u32 AI_CalcHoldEffectMoveScore(u32 battlerAtk, u32 battlerDef, u32 move) return score; } -static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) +static s32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move, struct AiLogicData *aiData) { // move data enum BattleMoveEffects moveEffect = GetMoveEffect(move); - struct AiLogicData *aiData = gAiLogicData; u32 movesetIndex = gAiThinkingStruct->movesetIndex; uq4_12_t effectiveness = aiData->effectiveness[battlerAtk][battlerDef][movesetIndex]; s32 score = 0; - u32 predictedMove = GetIncomingMove(battlerAtk, battlerDef, gAiLogicData); - u32 predictedMoveSpeedCheck = GetIncomingMoveSpeedCheck(battlerAtk, battlerDef, gAiLogicData); - u32 predictedType = GetMoveType(predictedMove); + u32 predictedMove = GetIncomingMove(battlerAtk, battlerDef, aiData); + u32 predictedMoveSpeedCheck = GetIncomingMoveSpeedCheck(battlerAtk, battlerDef, aiData); + enum Type predictedType = GetMoveType(predictedMove); u32 predictedMoveSlot = GetMoveSlot(GetMovesArray(battlerDef), predictedMove); bool32 isBattle1v1 = IsBattle1v1(); bool32 hasTwoOpponents = HasTwoOpponents(battlerAtk); @@ -4019,12 +4098,25 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) if (gAiThinkingStruct->aiFlags[battlerAtk] & AI_FLAG_PREFER_STATUS_MOVES && IsBattleMoveStatus(move) && effectiveness != UQ_4_12(0.0)) ADJUST_SCORE(10); + // don't get baited into encore + if (gBattleMoveEffects[moveEffect].encourageEncore + && HasBattlerSideMoveWithEffect(battlerDef, EFFECT_ENCORE) + && (B_MENTAL_HERB < GEN_5 || aiData->holdEffects[battlerAtk] != HOLD_EFFECT_MENTAL_HERB)) + { + if (!AI_IsAbilityOnSide(battlerAtk, ABILITY_AROMA_VEIL) + || IsMoldBreakerTypeAbility(battlerDef, aiData->abilities[battlerDef]) + || aiData->abilities[battlerDef] == ABILITY_MYCELIUM_MIGHT + || IsMoldBreakerTypeAbility(BATTLE_PARTNER(battlerDef), aiData->abilities[BATTLE_PARTNER(battlerDef)]) + || aiData->abilities[BATTLE_PARTNER(battlerDef)] == ABILITY_MYCELIUM_MIGHT) + return score; + } + // check thawing moves if (gBattleMons[battlerAtk].status1 & STATUS1_ICY_ANY && MoveThawsUser(move)) ADJUST_SCORE(10); // check burn / frostbite - if (gAiThinkingStruct->aiFlags[battlerAtk] & AI_FLAG_SMART_SWITCHING && gAiLogicData->abilities[battlerAtk] == ABILITY_NATURAL_CURE) + if (gAiThinkingStruct->aiFlags[battlerAtk] & AI_FLAG_SMART_SWITCHING && aiData->abilities[battlerAtk] == ABILITY_NATURAL_CURE) { if ((gBattleMons[battlerAtk].status1 & STATUS1_BURN && HasOnlyMovesWithCategory(battlerAtk, DAMAGE_CATEGORY_PHYSICAL, TRUE)) || (gBattleMons[battlerAtk].status1 & STATUS1_FROSTBITE && HasOnlyMovesWithCategory(battlerAtk, DAMAGE_CATEGORY_SPECIAL, TRUE))) @@ -4108,13 +4200,15 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) ADJUST_SCORE(IncreaseStatUpScore(battlerAtk, battlerDef, STAT_CHANGE_ATK_2)); break; case EFFECT_DEFENSE_UP: - case EFFECT_DEFENSE_UP_3: ADJUST_SCORE(IncreaseStatUpScore(battlerAtk, battlerDef, STAT_CHANGE_DEF)); break; case EFFECT_STUFF_CHEEKS: case EFFECT_DEFENSE_UP_2: ADJUST_SCORE(IncreaseStatUpScore(battlerAtk, battlerDef, STAT_CHANGE_DEF_2)); break; + case EFFECT_DEFENSE_UP_3: + ADJUST_SCORE(IncreaseStatUpScore(battlerAtk, battlerDef, STAT_CHANGE_DEF_3)); + break; case EFFECT_SPEED_UP: ADJUST_SCORE(IncreaseStatUpScore(battlerAtk, battlerDef, STAT_CHANGE_SPEED)); break; @@ -4126,9 +4220,11 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) ADJUST_SCORE(IncreaseStatUpScore(battlerAtk, battlerDef, STAT_CHANGE_SPATK)); break; case EFFECT_SPECIAL_ATTACK_UP_2: - case EFFECT_SPECIAL_ATTACK_UP_3: ADJUST_SCORE(IncreaseStatUpScore(battlerAtk, battlerDef, STAT_CHANGE_SPATK_2)); break; + case EFFECT_SPECIAL_ATTACK_UP_3: + ADJUST_SCORE(IncreaseStatUpScore(battlerAtk, battlerDef, STAT_CHANGE_SPATK_3)); + break; case EFFECT_SPECIAL_DEFENSE_UP: ADJUST_SCORE(IncreaseStatUpScore(battlerAtk, battlerDef, STAT_CHANGE_SPDEF)); break; @@ -4177,7 +4273,34 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) case EFFECT_BIDE: if (aiData->hpPercents[battlerAtk] < 90) ADJUST_SCORE(-2); // Should be either removed or turned into increasing score + // treat as offense booster case EFFECT_ACUPRESSURE: + ADJUST_SCORE(IncreaseStatUpScore(battlerAtk, battlerDef, STAT_CHANGE_ATK_2)); + ADJUST_SCORE(IncreaseStatUpScore(battlerAtk, battlerDef, STAT_CHANGE_SPATK_2)); + break; + case EFFECT_GEAR_UP: + if (aiData->abilities[battlerAtk] == ABILITY_PLUS || aiData->abilities[battlerAtk] == ABILITY_MINUS) + { + ADJUST_SCORE(IncreaseStatUpScore(battlerAtk, battlerDef, STAT_CHANGE_ATK)); + ADJUST_SCORE(IncreaseStatUpScore(battlerAtk, battlerDef, STAT_CHANGE_SPATK)); + } + if (hasPartner && (aiData->abilities[BATTLE_PARTNER(battlerAtk)] == ABILITY_PLUS || aiData->abilities[BATTLE_PARTNER(battlerAtk)] == ABILITY_MINUS)) + { + ADJUST_SCORE(IncreaseStatUpScore(BATTLE_PARTNER(battlerAtk), battlerDef, STAT_CHANGE_ATK)); + ADJUST_SCORE(IncreaseStatUpScore(BATTLE_PARTNER(battlerAtk), battlerDef, STAT_CHANGE_SPATK)); + } + break; + case EFFECT_MAGNETIC_FLUX: + if (aiData->abilities[battlerAtk] == ABILITY_PLUS || aiData->abilities[battlerAtk] == ABILITY_MINUS) + { + ADJUST_SCORE(IncreaseStatUpScore(battlerAtk, battlerDef, STAT_CHANGE_DEF)); + ADJUST_SCORE(IncreaseStatUpScore(battlerAtk, battlerDef, STAT_CHANGE_SPDEF)); + } + if (hasPartner && (aiData->abilities[BATTLE_PARTNER(battlerAtk)] == ABILITY_PLUS || aiData->abilities[BATTLE_PARTNER(battlerAtk)] == ABILITY_MINUS)) + { + ADJUST_SCORE(IncreaseStatUpScore(BATTLE_PARTNER(battlerAtk), battlerDef, STAT_CHANGE_DEF)); + ADJUST_SCORE(IncreaseStatUpScore(BATTLE_PARTNER(battlerAtk), battlerDef, STAT_CHANGE_SPDEF)); + } break; case EFFECT_ATTACK_ACCURACY_UP: // hone claws ADJUST_SCORE(IncreaseStatUpScore(battlerAtk, battlerDef, STAT_CHANGE_ATK)); @@ -4189,31 +4312,55 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) ADJUST_SCORE(IncreaseStatUpScore(battlerAtk, battlerDef, STAT_CHANGE_SPATK)); break; case EFFECT_ROTOTILLER: - if (IS_BATTLER_OF_TYPE(battlerAtk, TYPE_GRASS) && IsBattlerGrounded(battlerAtk)) + if (IS_BATTLER_OF_TYPE(battlerAtk, TYPE_GRASS) && AI_IsBattlerGrounded(battlerAtk)) { ADJUST_SCORE(IncreaseStatUpScore(battlerAtk, battlerDef, STAT_CHANGE_ATK)); ADJUST_SCORE(IncreaseStatUpScore(battlerAtk, battlerDef, STAT_CHANGE_SPATK)); } - if (hasPartner && IS_BATTLER_OF_TYPE(BATTLE_PARTNER(battlerAtk), TYPE_GRASS) && IsBattlerGrounded(BATTLE_PARTNER(battlerAtk))) + if (hasPartner && IS_BATTLER_OF_TYPE(BATTLE_PARTNER(battlerAtk), TYPE_GRASS) && AI_IsBattlerGrounded(BATTLE_PARTNER(battlerAtk))) { ADJUST_SCORE(IncreaseStatUpScore(BATTLE_PARTNER(battlerAtk), battlerDef, STAT_CHANGE_ATK)); ADJUST_SCORE(IncreaseStatUpScore(BATTLE_PARTNER(battlerAtk), battlerDef, STAT_CHANGE_SPATK)); } - if (IS_BATTLER_OF_TYPE(FOE(battlerAtk), TYPE_GRASS) && IsBattlerGrounded(FOE(battlerAtk))) + if (IS_BATTLER_OF_TYPE(LEFT_FOE(battlerAtk), TYPE_GRASS) && AI_IsBattlerGrounded(LEFT_FOE(battlerAtk))) { - if (aiData->abilities[FOE(battlerAtk)] == ABILITY_CONTRARY) + if (aiData->abilities[LEFT_FOE(battlerAtk)] == ABILITY_CONTRARY) ADJUST_SCORE(WEAK_EFFECT); else ADJUST_SCORE(AWFUL_EFFECT); } - if (IS_BATTLER_OF_TYPE(BATTLE_PARTNER(FOE(battlerAtk)), TYPE_GRASS) && IsBattlerGrounded(BATTLE_PARTNER(FOE(battlerAtk)))) + if (IS_BATTLER_OF_TYPE(RIGHT_FOE(battlerAtk), TYPE_GRASS) && AI_IsBattlerGrounded(RIGHT_FOE(battlerAtk))) { - if (aiData->abilities[BATTLE_PARTNER(FOE(battlerAtk))] == ABILITY_CONTRARY) + if (aiData->abilities[RIGHT_FOE(battlerAtk)] == ABILITY_CONTRARY) ADJUST_SCORE(WEAK_EFFECT); else ADJUST_SCORE(AWFUL_EFFECT); } break; + case EFFECT_FLOWER_SHIELD: + if (IS_BATTLER_OF_TYPE(battlerAtk, TYPE_GRASS)) + { + ADJUST_SCORE(IncreaseStatUpScore(battlerAtk, battlerDef, STAT_CHANGE_DEF)); + } + if (hasPartner && IS_BATTLER_OF_TYPE(BATTLE_PARTNER(battlerAtk), TYPE_GRASS)) + { + ADJUST_SCORE(IncreaseStatUpScore(BATTLE_PARTNER(battlerAtk), battlerDef, STAT_CHANGE_DEF)); + } + if (IS_BATTLER_OF_TYPE(LEFT_FOE(battlerAtk), TYPE_GRASS)) + { + if (aiData->abilities[LEFT_FOE(battlerAtk)] == ABILITY_CONTRARY) + ADJUST_SCORE(WEAK_EFFECT); + else + ADJUST_SCORE(AWFUL_EFFECT); + } + if (IS_BATTLER_OF_TYPE(RIGHT_FOE(battlerAtk), TYPE_GRASS)) + { + if (aiData->abilities[RIGHT_FOE(battlerAtk)] == ABILITY_CONTRARY) + ADJUST_SCORE(WEAK_EFFECT); + else + ADJUST_SCORE(AWFUL_EFFECT); + } + break; case EFFECT_HAZE: if (AnyStatIsRaised(BATTLE_PARTNER(battlerAtk)) || DoesPartnerHaveSameMoveEffect(BATTLE_PARTNER(battlerAtk), battlerDef, move, aiData->partnerMove)) @@ -4238,7 +4385,13 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) break; case EFFECT_CONVERSION: if (!IS_BATTLER_OF_TYPE(battlerAtk, GetMoveType(gBattleMons[battlerAtk].moves[0]))) + { ADJUST_SCORE(WEAK_EFFECT); + if (aiData->abilities[battlerAtk] == ABILITY_ADAPTABILITY) + ADJUST_SCORE(WEAK_EFFECT); + if (IsConsideringZMove(battlerAtk, battlerDef, move)) + ADJUST_SCORE(BEST_EFFECT); + } break; case EFFECT_SWALLOW: if (gDisableStructs[battlerAtk].stockpileCounter == 0) @@ -4276,6 +4429,12 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) if (ShouldRecover(battlerAtk, battlerDef, move, 50)) ADJUST_SCORE(GOOD_EFFECT); break; + case EFFECT_LIFE_DEW: + if (ShouldRecover(battlerAtk, battlerDef, move, 25)) + ADJUST_SCORE(GOOD_EFFECT); + if (ShouldRecover(BATTLE_PARTNER(battlerAtk), battlerDef, move, 25)) + ADJUST_SCORE(GOOD_EFFECT); + break; case EFFECT_LIGHT_SCREEN: case EFFECT_REFLECT: case EFFECT_AURORA_VEIL: @@ -4332,9 +4491,9 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) case EFFECT_MIMIC: if (AI_IsFaster(battlerAtk, battlerDef, move, predictedMoveSpeedCheck, CONSIDER_PRIORITY)) { - if (gLastMoves[battlerDef] != MOVE_NONE && gLastMoves[battlerDef] != 0xFFFF - && (GetMoveEffect(gLastMoves[battlerDef]) != GetMoveEffect(move))) - return AI_CheckViability(battlerAtk, battlerDef, gLastMoves[battlerDef], score); + if (aiData->lastUsedMove[battlerDef] != MOVE_NONE + && (GetMoveEffect(aiData->lastUsedMove[battlerDef]) != GetMoveEffect(move))) + return AI_CheckViability(battlerAtk, battlerDef, aiData->lastUsedMove[battlerDef], score); } break; case EFFECT_LEECH_SEED: @@ -4346,7 +4505,7 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) break; ADJUST_SCORE(GOOD_EFFECT); if (!HasDamagingMove(battlerDef) - || (!AI_CanBattlerEscape(battlerDef) && IsBattlerTrapped(battlerAtk, battlerDef)) + || IsBattlerTrapped(battlerAtk, battlerDef) || aiData->holdEffects[battlerAtk] == HOLD_EFFECT_BIG_ROOT) ADJUST_SCORE(DECENT_EFFECT); break; @@ -4354,7 +4513,9 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) case EFFECT_HOLD_HANDS: case EFFECT_CELEBRATE: case EFFECT_HAPPY_HOUR: - //todo - check z splash, z celebrate, z happy hour (lol) + case EFFECT_LAST_RESORT: + if (IsConsideringZMove(battlerAtk, battlerDef, move)) + ADJUST_SCORE(BEST_EFFECT); break; case EFFECT_TELEPORT: // Either remove or add better logic if (!(gBattleTypeFlags & BATTLE_TYPE_TRAINER) || !IsOnPlayerSide(battlerAtk)) @@ -4387,7 +4548,7 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) } break; case EFFECT_BATON_PASS: - if ((gAiLogicData->shouldSwitch & (1u << battlerAtk)) && (gBattleMons[battlerAtk].volatiles.substitute + if ((aiData->shouldSwitch & (1u << battlerAtk)) && (gBattleMons[battlerAtk].volatiles.substitute || gBattleMons[battlerAtk].volatiles.powerTrick || gBattleMons[battlerAtk].volatiles.magnetRise || gBattleMons[battlerAtk].volatiles.aquaRing @@ -4399,12 +4560,11 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) if (GetActiveGimmick(battlerDef) == GIMMICK_DYNAMAX) break; else if (gDisableStructs[battlerDef].disableTimer == 0 - && (gLastMoves[battlerDef] != MOVE_NONE) - && (gLastMoves[battlerDef] != 0xFFFF) + && (aiData->lastUsedMove[battlerDef] != MOVE_NONE) && (B_MENTAL_HERB < GEN_5 || aiData->holdEffects[battlerDef] != HOLD_EFFECT_MENTAL_HERB) && (AI_IsFaster(battlerAtk, battlerDef, move, predictedMoveSpeedCheck, CONSIDER_PRIORITY))) { - if (CanTargetMoveFaintAi(gLastMoves[battlerDef], battlerDef, battlerAtk, 1)) + if (CanTargetMoveFaintAi(aiData->lastUsedMove[battlerDef], battlerDef, battlerAtk, 1)) ADJUST_SCORE(GOOD_EFFECT); // Disable move that can kill attacker } break; @@ -4413,9 +4573,9 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) if (GetActiveGimmick(battlerDef) == GIMMICK_DYNAMAX) break; - bool32 encourage = gBattleMoveEffects[GetMoveEffect(gLastMoves[battlerDef])].encourageEncore; + bool32 encourage = gBattleMoveEffects[GetMoveEffect(aiData->lastUsedMove[battlerDef])].encourageEncore; - switch(GetMoveNonVolatileStatus(gLastMoves[battlerDef])) + switch(GetMoveNonVolatileStatus(aiData->lastUsedMove[battlerDef])) { case MOVE_EFFECT_POISON: case MOVE_EFFECT_PARALYSIS: @@ -4436,7 +4596,7 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) case EFFECT_LOCK_ON: if (HasMoveWithEffect(battlerAtk, EFFECT_OHKO) || HasMoveWithEffect(battlerAtk, EFFECT_SHEER_COLD)) ADJUST_SCORE(GOOD_EFFECT); - else if (HasMoveWithLowAccuracy(battlerAtk, battlerDef, 85, TRUE, aiData->abilities[battlerAtk], aiData->abilities[battlerDef], aiData->holdEffects[battlerAtk], aiData->holdEffects[battlerDef])) + else if (HasMoveWithLowAccuracy(battlerAtk, battlerDef, 85, TRUE)) ADJUST_SCORE(GOOD_EFFECT); break; case EFFECT_DESTINY_BOND: @@ -4453,10 +4613,19 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) if (ShouldUseWishAromatherapy(battlerAtk, battlerDef, move)) ADJUST_SCORE(DECENT_EFFECT); break; + case EFFECT_PURIFY: + if (gBattleMons[battlerDef].status1 & STATUS1_ANY) + { + if (ShouldCureStatus(battlerAtk, battlerDef, aiData)) + ADJUST_SCORE(GOOD_EFFECT); + if (ShouldRecover(battlerAtk, battlerDef, move, 50)) + RETURN_SCORE_PLUS(WEAK_EFFECT); + } + break; case EFFECT_CURSE: if (IS_BATTLER_OF_TYPE(battlerAtk, TYPE_GHOST)) { - if (!AI_CanBattlerEscape(battlerDef) && IsBattlerTrapped(battlerAtk, battlerDef)) + if (IsBattlerTrapped(battlerAtk, battlerDef)) ADJUST_SCORE(GOOD_EFFECT); else ADJUST_SCORE(WEAK_EFFECT); @@ -4468,7 +4637,7 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) } break; case EFFECT_PROTECT: - if (predictedMove == 0xFFFF) + if (predictedMove == MOVE_UNAVAILABLE) predictedMove = MOVE_NONE; enum ProtectMethod protectMethod = GetMoveProtectMethod(move); switch (protectMethod) @@ -4554,7 +4723,7 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) ADJUST_SCORE(DECENT_EFFECT); break; case EFFECT_PERISH_SONG: - if (!AI_CanBattlerEscape(battlerDef) && IsBattlerTrapped(battlerAtk, battlerDef)) + if (IsBattlerTrapped(battlerAtk, battlerDef)) ADJUST_SCORE(GOOD_EFFECT); break; case EFFECT_SANDSTORM: @@ -4713,19 +4882,19 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) break; // Don't use if the attract won't have a change to activate if (gBattleMons[battlerDef].status1 & STATUS1_ANY || gBattleMons[battlerDef].volatiles.confusionTurns > 0 - || (!AI_CanBattlerEscape(battlerDef) && IsBattlerTrapped(battlerAtk, battlerDef))) + || IsBattlerTrapped(battlerAtk, battlerDef)) ADJUST_SCORE(GOOD_EFFECT); else ADJUST_SCORE(DECENT_EFFECT); break; case EFFECT_SAFEGUARD: - if (!IsBattlerTerrainAffected(battlerAtk, STATUS_FIELD_MISTY_TERRAIN) || !IsBattlerGrounded(battlerAtk)) + if (!IsBattlerTerrainAffected(battlerAtk, aiData->abilities[battlerAtk], aiData->holdEffects[battlerAtk], STATUS_FIELD_MISTY_TERRAIN) || !AI_IsBattlerGrounded(battlerAtk)) ADJUST_SCORE(DECENT_EFFECT); // TODO: check if opp has status move? //if (CountUsablePartyMons(battlerDef) != 0) //ADJUST_SCORE(8); break; case EFFECT_COURT_CHANGE: - if (gSideStatuses[GetBattlerSide(FOE(battlerAtk))] & SIDE_STATUS_GOOD_COURT) + if (gSideStatuses[GetBattlerSide(battlerDef)] & SIDE_STATUS_GOOD_COURT) ADJUST_SCORE(WEAK_EFFECT); if (gSideStatuses[GetBattlerSide(battlerAtk)] & SIDE_STATUS_BAD_COURT) ADJUST_SCORE(WEAK_EFFECT); @@ -4771,7 +4940,7 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) && (!IsPowderMove(move) || IsAffectedByPowderMove(battlerDef, aiData->abilities[battlerDef], aiData->holdEffects[battlerDef]))) // Rage Powder doesn't affect powder immunities { - u32 predictedMoveOnPartner = gLastMoves[BATTLE_PARTNER(battlerAtk)]; + u32 predictedMoveOnPartner = aiData->lastUsedMove[BATTLE_PARTNER(battlerAtk)]; if (predictedMoveOnPartner != MOVE_NONE && !IsBattleMoveStatus(predictedMoveOnPartner)) ADJUST_SCORE(GOOD_EFFECT); } @@ -4816,7 +4985,7 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) ADJUST_SCORE(DECENT_EFFECT); break; case HOLD_EFFECT_IRON_BALL: - if (!HasMoveWithEffect(battlerDef, EFFECT_FLING) || !IsBattlerGrounded(battlerDef)) + if (!HasMoveWithEffect(battlerDef, EFFECT_FLING) || !AI_IsBattlerGrounded(battlerDef)) ADJUST_SCORE(DECENT_EFFECT); break; case HOLD_EFFECT_LAGGING_TAIL: @@ -4837,6 +5006,8 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) if (AI_GetWeather() & B_WEATHER_SUN) ADJUST_SCORE(DECENT_EFFECT); // Slow 'em down break; + default: + break; } } break; @@ -4907,19 +5078,19 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) ADJUST_SCORE(GOOD_EFFECT); break; case EFFECT_RECYCLE: - if (GetUsedHeldItem(battlerAtk) != ITEM_NONE) + if (GetBattlerPartyState(battlerAtk)->usedHeldItem != ITEM_NONE) ADJUST_SCORE(WEAK_EFFECT); - if (IsRecycleEncouragedItem(GetUsedHeldItem(battlerAtk))) + if (IsRecycleEncouragedItem(GetBattlerPartyState(battlerAtk)->usedHeldItem)) ADJUST_SCORE(WEAK_EFFECT); if (aiData->abilities[battlerAtk] == ABILITY_RIPEN) { - u32 item = GetUsedHeldItem(battlerAtk); + u32 item = GetBattlerPartyState(battlerAtk)->usedHeldItem; u32 toHeal = (GetItemHoldEffectParam(item) == 10) ? 10 : gBattleMons[battlerAtk].maxHP / GetItemHoldEffectParam(item); if (IsStatBoostingBerry(item) && aiData->hpPercents[battlerAtk] > 60) ADJUST_SCORE(WEAK_EFFECT); else if (ShouldRestoreHpBerry(battlerAtk, item) && !CanAIFaintTarget(battlerAtk, battlerDef, 0) - && ((GetWhichBattlerFasterOrTies(battlerAtk, battlerDef, TRUE) == 1 && CanTargetFaintAiWithMod(battlerDef, battlerAtk, 0, 0)) + && ((AI_GetWhichBattlerFasterOrTies(battlerAtk, battlerDef, TRUE) == 1 && CanTargetFaintAiWithMod(battlerDef, battlerAtk, 0, 0)) || !CanTargetFaintAiWithMod(battlerDef, battlerAtk, toHeal, 0))) ADJUST_SCORE(WEAK_EFFECT); // Recycle healing berry if we can't otherwise faint the target and the target wont kill us after we activate the berry } @@ -4937,10 +5108,9 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) case EFFECT_ENTRAINMENT: case EFFECT_GASTRO_ACID: case EFFECT_ROLE_PLAY: - case EFFECT_SIMPLE_BEAM: case EFFECT_SKILL_SWAP: - case EFFECT_WORRY_SEED: - AbilityChangeScore(battlerAtk, battlerDef, moveEffect, &score, aiData); + case EFFECT_OVERWRITE_ABILITY: + AbilityChangeScore(battlerAtk, battlerDef, move, &score, aiData); return score; case EFFECT_IMPRISON: if (predictedMove != MOVE_NONE && HasMove(battlerAtk, predictedMove)) @@ -4949,7 +5119,8 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) ADJUST_SCORE(WEAK_EFFECT); break; case EFFECT_REFRESH: - if (gBattleMons[battlerAtk].status1 & STATUS1_CAN_MOVE) + if ((gBattleMons[battlerAtk].status1 & STATUS1_CAN_MOVE) + && ShouldCureStatus(battlerAtk, battlerAtk, aiData)) ADJUST_SCORE(DECENT_EFFECT); break; case EFFECT_TAKE_HEART: @@ -5122,7 +5293,7 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) if (ShouldSetFieldStatus(battlerAtk, STATUS_FIELD_ELECTRIC_TERRAIN)) { ADJUST_SCORE(GOOD_EFFECT); - if (gBattleMons[battlerAtk].volatiles.yawn && IsBattlerGrounded(battlerAtk)) + if (gBattleMons[battlerAtk].volatiles.yawn && AI_IsBattlerGrounded(battlerAtk)) ADJUST_SCORE(BEST_EFFECT); if (aiData->holdEffects[battlerAtk] == HOLD_EFFECT_TERRAIN_EXTENDER || HasBattlerSideMoveWithEffect(battlerAtk, EFFECT_TERRAIN_PULSE)) ADJUST_SCORE(WEAK_EFFECT); @@ -5132,7 +5303,7 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) if (ShouldSetFieldStatus(battlerAtk, STATUS_FIELD_MISTY_TERRAIN)) { ADJUST_SCORE(GOOD_EFFECT); - if (gBattleMons[battlerAtk].volatiles.yawn && IsBattlerGrounded(battlerAtk)) + if (gBattleMons[battlerAtk].volatiles.yawn && AI_IsBattlerGrounded(battlerAtk)) ADJUST_SCORE(BEST_EFFECT); if (aiData->holdEffects[battlerAtk] == HOLD_EFFECT_TERRAIN_EXTENDER || HasBattlerSideMoveWithEffect(battlerAtk, EFFECT_TERRAIN_PULSE)) ADJUST_SCORE(WEAK_EFFECT); @@ -5185,7 +5356,7 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) else if (!(gFieldStatuses & STATUS_FIELD_TRICK_ROOM) && !hasPartner && (CountUsablePartyMons(battlerAtk) != 0)) ADJUST_SCORE(DECENT_EFFECT); // Don't unset it on last turn. - else if (gFieldStatuses & STATUS_FIELD_TRICK_ROOM && gFieldTimers.trickRoomTimer != (gBattleTurnCounter + 1) && ShouldClearFieldStatus(battlerAtk, STATUS_FIELD_TRICK_ROOM)) + else if (gFieldStatuses & STATUS_FIELD_TRICK_ROOM && gFieldTimers.trickRoomTimer > 1 && ShouldClearFieldStatus(battlerAtk, STATUS_FIELD_TRICK_ROOM)) ADJUST_SCORE(GOOD_EFFECT); } break; @@ -5202,11 +5373,16 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) ADJUST_SCORE(DECENT_EFFECT); break; case EFFECT_GRAVITY: - if (!(gFieldStatuses & STATUS_FIELD_GRAVITY)) + if (!(gFieldStatuses & STATUS_FIELD_GRAVITY || ShouldClearFieldStatus(battlerAtk, STATUS_FIELD_GRAVITY))) { - if (HasSleepMoveWithLowAccuracy(battlerAtk, battlerDef)) // Has Gravity for a move like Hypnosis + // improve accuracy of Hypnosis + if (HasSleepMoveWithLowAccuracy(battlerAtk, battlerDef) + || HasSleepMoveWithLowAccuracy(BATTLE_PARTNER(battlerAtk), battlerDef)) IncreaseSleepScore(battlerAtk, battlerDef, move, &score); - if (HasMoveWithLowAccuracy(battlerAtk, battlerDef, 90, FALSE, aiData->abilities[battlerAtk], aiData->abilities[battlerDef], aiData->holdEffects[battlerAtk], aiData->holdEffects[battlerDef])) + if (HasMoveWithLowAccuracy(battlerAtk, battlerDef, 90, TRUE) + || HasMoveWithLowAccuracy(BATTLE_PARTNER(battlerAtk), battlerDef, 90, TRUE)) + ADJUST_SCORE(WEAK_EFFECT); + if (ShouldSetFieldStatus(battlerAtk, STATUS_FIELD_GRAVITY)) ADJUST_SCORE(DECENT_EFFECT); } break; @@ -5249,8 +5425,7 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) ADJUST_SCORE(DECENT_EFFECT); break; case EFFECT_TELEKINESIS: - if (HasMoveWithLowAccuracy(battlerAtk, battlerDef, 90, FALSE, aiData->abilities[battlerAtk], aiData->abilities[battlerDef], aiData->holdEffects[battlerAtk], aiData->holdEffects[battlerDef]) - || !IsBattlerGrounded(battlerDef)) + if (HasMoveWithLowAccuracy(battlerAtk, battlerDef, 90, FALSE) || !AI_IsBattlerGrounded(battlerDef)) ADJUST_SCORE(DECENT_EFFECT); break; case EFFECT_HEAL_BLOCK: @@ -5293,7 +5468,7 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) break; case EFFECT_TAILWIND: { - if (gFieldStatuses & STATUS_FIELD_TRICK_ROOM && gFieldTimers.trickRoomTimer != (gBattleTurnCounter + 1)) + if (gFieldStatuses & STATUS_FIELD_TRICK_ROOM && gFieldTimers.trickRoomTimer > 1) break; if (HasBattlerSideMoveWithEffect(battlerAtk, EFFECT_ELECTRO_BALL)) @@ -5312,8 +5487,8 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) u32 tailwindScore = 0; u32 speed = aiData->speedStats[battlerAtk]; u32 partnerSpeed = aiData->speedStats[BATTLE_PARTNER(battlerAtk)]; - u32 foe1Speed = aiData->speedStats[FOE(battlerAtk)]; - u32 foe2Speed = aiData->speedStats[BATTLE_PARTNER(FOE(battlerAtk))]; + u32 foe1Speed = aiData->speedStats[LEFT_FOE(battlerAtk)]; + u32 foe2Speed = aiData->speedStats[RIGHT_FOE(battlerAtk)]; if (speed <= foe1Speed && (speed * 2) > foe1Speed) tailwindScore += 1; @@ -5336,7 +5511,7 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) ADJUST_SCORE(GOOD_EFFECT); break; case EFFECT_MAGNET_RISE: - if (IsBattlerGrounded(battlerAtk) && HasDamagingMoveOfType(battlerDef, TYPE_ELECTRIC) + if (AI_IsBattlerGrounded(battlerAtk) && HasDamagingMoveOfType(battlerDef, TYPE_ELECTRIC) && !(effectiveness == UQ_4_12(0.0))) // Doesn't resist ground move { if (AI_IsFaster(battlerAtk, battlerDef, move, predictedMoveSpeedCheck, CONSIDER_PRIORITY)) // Attacker goes first @@ -5388,9 +5563,9 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) if (GetFirstFaintedPartyIndex(battlerAtk) != PARTY_SIZE) { ADJUST_SCORE(DECENT_EFFECT); - if (gAiLogicData->shouldSwitch & (1u << battlerAtk)) // Bad matchup + if (aiData->shouldSwitch & (1u << battlerAtk)) // Bad matchup ADJUST_SCORE(WEAK_EFFECT); - if (gAiLogicData->mostSuitableMonId[battlerAtk] != PARTY_SIZE) // Good mon to send in after + if (aiData->mostSuitableMonId[battlerAtk] != PARTY_SIZE) // Good mon to send in after ADJUST_SCORE(WEAK_EFFECT); } break; @@ -5403,12 +5578,17 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) //case EFFECT_SKY_DROP //break; case EFFECT_JUNGLE_HEALING: + { + bool32 canCureSelf = (gBattleMons[battlerAtk].status1 & STATUS1_ANY) && ShouldCureStatus(battlerAtk, battlerAtk, aiData); + bool32 canCurePartner = (gBattleMons[BATTLE_PARTNER(battlerAtk)].status1 & STATUS1_ANY) && ShouldCureStatus(battlerAtk, BATTLE_PARTNER(battlerAtk), aiData); + if (ShouldRecover(battlerAtk, battlerDef, move, 25) || ShouldRecover(BATTLE_PARTNER(battlerAtk), battlerDef, move, 25) - || gBattleMons[battlerAtk].status1 & STATUS1_ANY - || gBattleMons[BATTLE_PARTNER(battlerAtk)].status1 & STATUS1_ANY) + || canCureSelf + || canCurePartner) ADJUST_SCORE(GOOD_EFFECT); break; + } case EFFECT_RAPID_SPIN: if ((AreAnyHazardsOnSide(GetBattlerSide(battlerAtk)) && CountUsablePartyMons(battlerAtk) != 0) || (gBattleMons[battlerAtk].volatiles.leechSeed || gBattleMons[battlerAtk].volatiles.wrapped)) @@ -5418,7 +5598,7 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) ADJUST_SCORE(AI_ShouldCopyStatChanges(battlerAtk, battlerDef)); break; case EFFECT_SMACK_DOWN: - if (!IsBattlerGrounded(battlerDef) && HasDamagingMoveOfType(battlerAtk, TYPE_GROUND) && !CanTargetFaintAi(battlerDef, battlerAtk)) + if (!AI_IsBattlerGrounded(battlerDef) && HasDamagingMoveOfType(battlerAtk, TYPE_GROUND) && !CanTargetFaintAi(battlerDef, battlerAtk)) ADJUST_SCORE(DECENT_EFFECT); break; case EFFECT_KNOCK_OFF: @@ -5496,11 +5676,30 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) break; } // move effect checks + return score; +} + +static s32 AI_CalcAdditionalEffectScore(u32 battlerAtk, u32 battlerDef, u32 move, struct AiLogicData *aiData) +{ + // move data + s32 score = 0; + + u32 predictedMove = GetIncomingMove(battlerAtk, battlerDef, aiData); + bool32 hasPartner = HasPartner(battlerAtk); + u32 i; u32 additionalEffectCount = GetMoveAdditionalEffectCount(move); + // check move additional effects that are likely to happen for (i = 0; i < additionalEffectCount; i++) { const struct AdditionalEffect *additionalEffect = GetMoveAdditionalEffectById(move, i); + + if (aiData->abilities[battlerAtk] == ABILITY_SHEER_FORCE) + { + if ((additionalEffect->chance > 0) != additionalEffect->sheerForceOverride) + continue; + } + // Only consider effects with a guaranteed chance to happen if (!MoveEffectIsGuaranteed(battlerAtk, aiData->abilities[battlerAtk], additionalEffect)) continue; @@ -5600,32 +5799,74 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) break; case MOVE_EFFECT_SPD_MINUS_1: case MOVE_EFFECT_SPD_MINUS_2: - ADJUST_SCORE(IncreaseStatDownScore(battlerAtk, battlerDef, STAT_SPEED)); + if (CanLowerStat(battlerAtk, battlerDef, aiData, STAT_SPEED)) + ADJUST_SCORE(IncreaseStatDownScore(battlerAtk, battlerDef, STAT_SPEED)); + break; + case MOVE_EFFECT_ACC_MINUS_1: + case MOVE_EFFECT_ACC_MINUS_2: + if (CanLowerStat(battlerAtk, battlerDef, aiData, STAT_ACC)) + { + u32 scoreIncrease = IncreaseStatDownScore(battlerAtk, battlerDef, STAT_ACC); + if (scoreIncrease == WEAK_EFFECT) + scoreIncrease = DECENT_EFFECT; + ADJUST_SCORE(scoreIncrease); + } break; case MOVE_EFFECT_ATK_MINUS_1: case MOVE_EFFECT_DEF_MINUS_1: case MOVE_EFFECT_SP_ATK_MINUS_1: case MOVE_EFFECT_SP_DEF_MINUS_1: - case MOVE_EFFECT_ACC_MINUS_1: case MOVE_EFFECT_EVS_MINUS_1: - if (aiData->abilities[battlerDef] != ABILITY_CONTRARY) - ADJUST_SCORE(DECENT_EFFECT); + { + u32 statId = STAT_ATK + additionalEffect->moveEffect - MOVE_EFFECT_ATK_MINUS_1; + if (CanLowerStat(battlerAtk, battlerDef, aiData, statId)) + ADJUST_SCORE(IncreaseStatDownScore(battlerAtk, battlerDef, statId)); break; + } case MOVE_EFFECT_ATK_MINUS_2: case MOVE_EFFECT_DEF_MINUS_2: case MOVE_EFFECT_SP_ATK_MINUS_2: case MOVE_EFFECT_SP_DEF_MINUS_2: - case MOVE_EFFECT_ACC_MINUS_2: case MOVE_EFFECT_EVS_MINUS_2: - if (aiData->abilities[battlerDef] != ABILITY_CONTRARY) - ADJUST_SCORE(DECENT_EFFECT); + { + u32 statId = STAT_ATK + additionalEffect->moveEffect - MOVE_EFFECT_ATK_MINUS_2; + if (CanLowerStat(battlerAtk, battlerDef, aiData, statId)) + ADJUST_SCORE(IncreaseStatDownScore(battlerAtk, battlerDef, statId)); break; + } + case MOVE_EFFECT_RAISE_TEAM_ATTACK: + case MOVE_EFFECT_RAISE_TEAM_DEFENSE: + case MOVE_EFFECT_RAISE_TEAM_SPEED: + case MOVE_EFFECT_RAISE_TEAM_SP_ATK: + case MOVE_EFFECT_RAISE_TEAM_SP_DEF: + { + enum StatChange StageStatId = STAT_CHANGE_ATK + additionalEffect->moveEffect - MOVE_EFFECT_RAISE_TEAM_ATTACK; + ADJUST_SCORE(IncreaseStatUpScore(battlerAtk, battlerDef, StageStatId)); + if (hasPartner) + ADJUST_SCORE(IncreaseStatUpScore(BATTLE_PARTNER(battlerAtk), battlerDef, StageStatId)); + break; + } + case MOVE_EFFECT_LOWER_ATTACK_SIDE: + case MOVE_EFFECT_LOWER_DEFENSE_SIDE: + case MOVE_EFFECT_LOWER_SPEED_SIDE: + case MOVE_EFFECT_LOWER_SP_ATK_SIDE: + case MOVE_EFFECT_LOWER_SP_DEF_SIDE: + { + u32 statId = STAT_ATK + additionalEffect->moveEffect - MOVE_EFFECT_LOWER_ATTACK_SIDE; + if (CanLowerStat(battlerAtk, battlerDef, aiData, statId)) + ADJUST_SCORE(IncreaseStatDownScore(battlerAtk, battlerDef, statId)); + break; + } case MOVE_EFFECT_POISON: IncreasePoisonScore(battlerAtk, battlerDef, move, &score); break; case MOVE_EFFECT_CLEAR_SMOG: + { + bool32 moveTargetsBothOpponents = HasTwoOpponents(battlerAtk) && (gMovesInfo[move].target & (MOVE_TARGET_BOTH | MOVE_TARGET_FOES_AND_ALLY | MOVE_TARGET_ALL_BATTLERS)); + score += AI_TryToClearStats(battlerAtk, battlerDef, moveTargetsBothOpponents); break; + } case MOVE_EFFECT_BUG_BITE: // And pluck if (gBattleMons[battlerDef].volatiles.substitute || aiData->abilities[battlerDef] == ABILITY_STICKY_HOLD) break; @@ -5639,7 +5880,7 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) ADJUST_SCORE(DECENT_EFFECT); break; case MOVE_EFFECT_STEALTH_ROCK: - if (AI_ShouldSetUpHazards(battlerAtk, battlerDef, move, aiData)); + if (AI_ShouldSetUpHazards(battlerAtk, battlerDef, move, aiData)) { if (gDisableStructs[battlerAtk].isFirstTurn) ADJUST_SCORE(BEST_EFFECT); @@ -5654,6 +5895,8 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) case MOVE_EFFECT_THROAT_CHOP: if (IsSoundMove(GetBestDmgMoveFromBattler(battlerDef, battlerAtk, AI_DEFENDING))) { + u32 predictedMoveSpeedCheck = GetIncomingMoveSpeedCheck(battlerAtk, battlerDef, aiData); + if (AI_IsFaster(battlerAtk, battlerDef, move, predictedMoveSpeedCheck, CONSIDER_PRIORITY)) ADJUST_SCORE(GOOD_EFFECT); else @@ -5668,18 +5911,102 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) if (IS_BATTLER_OF_TYPE(battlerDef, TYPE_WATER) || IS_BATTLER_OF_TYPE(battlerDef, TYPE_STEEL)) ADJUST_SCORE(DECENT_EFFECT); break; + case MOVE_EFFECT_SUN: + if (ShouldSetWeather(battlerAtk, B_WEATHER_SUN)) + ADJUST_SCORE(DECENT_EFFECT); + if (ShouldClearWeather(battlerAtk, B_WEATHER_SUN)) + ADJUST_SCORE(BAD_EFFECT); + break; + case MOVE_EFFECT_RAIN: + if (ShouldSetWeather(battlerAtk, B_WEATHER_RAIN)) + ADJUST_SCORE(DECENT_EFFECT); + if (ShouldClearWeather(battlerAtk, B_WEATHER_RAIN)) + ADJUST_SCORE(BAD_EFFECT); + break; + case MOVE_EFFECT_SANDSTORM: + if (ShouldSetWeather(battlerAtk, B_WEATHER_SANDSTORM)) + ADJUST_SCORE(DECENT_EFFECT); + if (ShouldClearWeather(battlerAtk, B_WEATHER_SANDSTORM)) + ADJUST_SCORE(BAD_EFFECT); + break; + case MOVE_EFFECT_HAIL: + if (ShouldSetWeather(battlerAtk, B_WEATHER_HAIL)) + ADJUST_SCORE(DECENT_EFFECT); + if (ShouldClearWeather(battlerAtk, B_WEATHER_HAIL)) + ADJUST_SCORE(BAD_EFFECT); + break; + case MOVE_EFFECT_MISTY_TERRAIN: + if (ShouldClearFieldStatus(battlerAtk, STATUS_FIELD_MISTY_TERRAIN)) + { + ADJUST_SCORE(BAD_EFFECT); + break; + } + if (ShouldSetFieldStatus(battlerAtk, STATUS_FIELD_MISTY_TERRAIN) + || ShouldClearFieldStatus(battlerAtk, gFieldStatuses & STATUS_FIELD_TERRAIN_ANY)) + ADJUST_SCORE(DECENT_EFFECT); + break; + case MOVE_EFFECT_GRASSY_TERRAIN: + if (ShouldClearFieldStatus(battlerAtk, STATUS_FIELD_GRASSY_TERRAIN)) + { + ADJUST_SCORE(BAD_EFFECT); + break; + } + if (ShouldSetFieldStatus(battlerAtk, STATUS_FIELD_GRASSY_TERRAIN) + || ShouldClearFieldStatus(battlerAtk, gFieldStatuses & STATUS_FIELD_TERRAIN_ANY)) + ADJUST_SCORE(DECENT_EFFECT); + break; + case MOVE_EFFECT_ELECTRIC_TERRAIN: + if (ShouldClearFieldStatus(battlerAtk, STATUS_FIELD_ELECTRIC_TERRAIN)) + { + ADJUST_SCORE(BAD_EFFECT); + break; + } + if (ShouldSetFieldStatus(battlerAtk, STATUS_FIELD_ELECTRIC_TERRAIN) + || ShouldClearFieldStatus(battlerAtk, gFieldStatuses & STATUS_FIELD_TERRAIN_ANY)) + ADJUST_SCORE(DECENT_EFFECT); + break; + case MOVE_EFFECT_PSYCHIC_TERRAIN: + if (ShouldClearFieldStatus(battlerAtk, STATUS_FIELD_PSYCHIC_TERRAIN)) + { + ADJUST_SCORE(BAD_EFFECT); + break; + } + if (ShouldSetFieldStatus(battlerAtk, STATUS_FIELD_PSYCHIC_TERRAIN) + || ShouldClearFieldStatus(battlerAtk, gFieldStatuses & STATUS_FIELD_TERRAIN_ANY)) + ADJUST_SCORE(DECENT_EFFECT); + break; + case MOVE_EFFECT_GRAVITY: + if (!(gFieldStatuses & STATUS_FIELD_GRAVITY) && ShouldSetFieldStatus(battlerAtk, STATUS_FIELD_GRAVITY)) + ADJUST_SCORE(DECENT_EFFECT); + break; + case MOVE_EFFECT_AURORA_VEIL: + if (ShouldSetScreen(battlerAtk, battlerDef, EFFECT_AURORA_VEIL)) + ADJUST_SCORE(DECENT_EFFECT); + break; + case MOVE_EFFECT_REMOVE_STATUS: + if (gBattleMons[battlerDef].status1 & GetMoveEffectArg_Status(move)) + { + if (ShouldCureStatus(battlerAtk, battlerDef, aiData)) + ADJUST_SCORE(DECENT_EFFECT); + else if (aiData->holdEffects[battlerDef] == HOLD_EFFECT_FLAME_ORB || aiData->holdEffects[battlerDef] == HOLD_EFFECT_TOXIC_ORB) + ADJUST_SCORE(WEAK_EFFECT); + else + ADJUST_SCORE(BAD_EFFECT); + } + break; default: break; } } } - return score; } // AI_FLAG_CHECK_VIABILITY - Chooses best possible move to hit player static s32 AI_CheckViability(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) { + struct AiLogicData *aiData = gAiLogicData; + // Targeting partner, check benefits of doing that instead if (IsTargetingPartner(battlerAtk, battlerDef)) return score; @@ -5696,8 +6023,9 @@ static s32 AI_CheckViability(u32 battlerAtk, u32 battlerDef, u32 move, s32 score } } - ADJUST_SCORE(AI_CalcMoveEffectScore(battlerAtk, battlerDef, move)); - ADJUST_SCORE(AI_CalcHoldEffectMoveScore(battlerAtk, battlerDef, move)); + ADJUST_SCORE(AI_CalcMoveEffectScore(battlerAtk, battlerDef, move, aiData)); + ADJUST_SCORE(AI_CalcAdditionalEffectScore(battlerAtk, battlerDef, move, aiData)); + ADJUST_SCORE(AI_CalcHoldEffectMoveScore(battlerAtk, battlerDef, move, aiData)); return score; } @@ -5921,7 +6249,7 @@ static s32 AI_AttacksPartner(u32 battlerAtk, u32 battlerDef, u32 move, s32 score u32 hitsToKO = GetNoOfHitsToKOBattler(battlerAtk, battlerDef, gAiThinkingStruct->movesetIndex, AI_ATTACKING); if (GetMoveTarget(move) == MOVE_TARGET_FOES_AND_ALLY && hitsToKO > 0 && - (GetNoOfHitsToKOBattler(battlerAtk, FOE(battlerAtk), gAiThinkingStruct->movesetIndex, AI_ATTACKING) > 0 || GetNoOfHitsToKOBattler(battlerAtk, FOE(battlerDef), gAiThinkingStruct->movesetIndex, AI_ATTACKING) > 0)) + (GetNoOfHitsToKOBattler(battlerAtk, LEFT_FOE(battlerAtk), gAiThinkingStruct->movesetIndex, AI_ATTACKING) > 0 || GetNoOfHitsToKOBattler(battlerAtk, LEFT_FOE(battlerDef), gAiThinkingStruct->movesetIndex, AI_ATTACKING) > 0)) ADJUST_SCORE(BEST_EFFECT); if (hitsToKO > 0) @@ -5937,7 +6265,7 @@ static s32 AI_PreferBatonPass(u32 battlerAtk, u32 battlerDef, u32 move, s32 scor || CountUsablePartyMons(battlerAtk) == 0 || !IsBattleMoveStatus(move) || !HasMoveWithEffect(battlerAtk, EFFECT_BATON_PASS) - || (!AI_CanBattlerEscape(battlerAtk) && IsBattlerTrapped(battlerDef, battlerAtk))) + || IsBattlerTrapped(battlerAtk, battlerDef)) return score; enum BattleMoveEffects effect = GetMoveEffect(move); @@ -5964,7 +6292,7 @@ static s32 AI_PreferBatonPass(u32 battlerAtk, u32 battlerDef, u32 move, s32 scor ADJUST_SCORE(DECENT_EFFECT); break; case EFFECT_PROTECT: - if (GetProtectType(GetMoveProtectMethod(gLastMoves[battlerAtk])) == PROTECT_TYPE_SINGLE) + if (GetProtectType(GetMoveProtectMethod(gAiLogicData->lastUsedMove[battlerAtk])) == PROTECT_TYPE_SINGLE) ADJUST_SCORE(-2); else ADJUST_SCORE(DECENT_EFFECT); @@ -5986,7 +6314,7 @@ static s32 AI_PreferBatonPass(u32 battlerAtk, u32 battlerDef, u32 move, s32 scor static s32 AI_HPAware(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) { enum BattleMoveEffects effect = GetMoveEffect(move); - u32 moveType = 0; + enum Type moveType = 0; SetTypeBeforeUsingMove(move, battlerAtk); moveType = GetBattleMoveType(move); @@ -6001,8 +6329,8 @@ static s32 AI_HPAware(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) if (gBattleMons[battlerDef].volatiles.healBlock) return 0; - if (CanTargetFaintAi(FOE(battlerAtk), BATTLE_PARTNER(battlerAtk)) - || (CanTargetFaintAi(BATTLE_PARTNER(FOE(battlerAtk)), BATTLE_PARTNER(battlerAtk)))) + if (CanTargetFaintAi(LEFT_FOE(battlerAtk), BATTLE_PARTNER(battlerAtk)) + || CanTargetFaintAi(RIGHT_FOE(battlerAtk), BATTLE_PARTNER(battlerAtk))) ADJUST_SCORE(-1); if (gAiLogicData->hpPercents[battlerDef] <= 50) @@ -6295,7 +6623,7 @@ static s32 AI_PredictSwitch(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) { u32 i; u32 unmodifiedScore = score; - u32 ability = gBattleMons[battlerAtk].ability; + enum Ability ability = gBattleMons[battlerAtk].ability; bool32 opposingHazardFlags = DoesSideHaveDamagingHazards(GetBattlerSide(battlerDef)); bool32 aiHazardFlags = AreAnyHazardsOnSide(GetBattlerSide(battlerAtk)); enum BattleMoveEffects moveEffect = GetMoveEffect(move); diff --git a/src/battle_ai_switch_items.c b/src/battle_ai_switch_items.c index 29b58ed9e6..5b924d23e5 100644 --- a/src/battle_ai_switch_items.c +++ b/src/battle_ai_switch_items.c @@ -7,7 +7,6 @@ #include "battle_anim.h" #include "battle_controllers.h" #include "battle_main.h" -#include "constants/hold_effects.h" #include "battle_setup.h" #include "data.h" #include "item.h" @@ -29,7 +28,7 @@ static bool32 AiExpectsToFaintPlayer(u32 battler); static bool32 AI_ShouldHeal(u32 battler, u32 healAmount); static bool32 AI_OpponentCanFaintAiWithMod(u32 battler, u32 healAmount); static u32 GetSwitchinHazardsDamage(u32 battler, struct BattlePokemon *battleMon); -static bool32 CanAbilityTrapOpponent(u16 ability, u32 opponent); +static bool32 CanAbilityTrapOpponent(enum Ability ability, u32 opponent); static u32 GetHPHealAmount(u8 itemEffectParam, struct Pokemon *mon); static u32 GetBattleMonTypeMatchup(struct BattlePokemon opposingBattleMon, struct BattlePokemon battleMon); @@ -165,7 +164,7 @@ static bool32 AI_DoesChoiceEffectBlockMove(u32 battler, u32 move) { // Choice locked into something else if (gAiLogicData->lastUsedMove[battler] != MOVE_NONE && gAiLogicData->lastUsedMove[battler] != move - && ((IsHoldEffectChoice(GetBattlerHoldEffect(battler, FALSE)) && IsBattlerItemEnabled(battler)) + && (IsHoldEffectChoice(GetBattlerHoldEffect(battler) && IsBattlerItemEnabled(battler)) || gBattleMons[battler].ability == ABILITY_GORILLA_TACTICS)) return TRUE; return FALSE; @@ -276,7 +275,7 @@ static bool32 ShouldSwitchIfHasBadOdds(u32 battler) if (!IsBattleMoveStatus(aiMove) && !AI_DoesChoiceEffectBlockMove(battler, aiMove)) { // Check if mon has a super effective move - if (AI_GetMoveEffectiveness(aiMove, battler, opposingBattler) >= UQ_4_12(2.0)) + if (gAiLogicData->effectiveness[battler][opposingBattler][i] >= UQ_4_12(2.0)) hasSuperEffectiveMove = TRUE; // Get maximum damage mon can deal @@ -408,9 +407,10 @@ static bool32 ShouldSwitchIfAllMovesBad(u32 battler) for (moveIndex = 0; moveIndex < MAX_MON_MOVES; moveIndex++) { aiMove = gBattleMons[battler].moves[moveIndex]; - if ((AI_GetMoveEffectiveness(aiMove, battler, opposingBattler) > UQ_4_12(0.0) - || AI_GetMoveEffectiveness(aiMove, battler, opposingPartner) > UQ_4_12(0.0)) - && aiMove != MOVE_NONE) + if (aiMove == MOVE_NONE) + continue; + if (gAiLogicData->effectiveness[battler][opposingBattler][moveIndex] > UQ_4_12(0.0) + || gAiLogicData->effectiveness[battler][opposingPartner][moveIndex] > UQ_4_12(0.0)) return FALSE; } } @@ -419,7 +419,7 @@ static bool32 ShouldSwitchIfAllMovesBad(u32 battler) for (moveIndex = 0; moveIndex < MAX_MON_MOVES; moveIndex++) { aiMove = gBattleMons[battler].moves[moveIndex]; - if (AI_GetMoveEffectiveness(aiMove, battler, opposingBattler) > UQ_4_12(0.0) && aiMove != MOVE_NONE + if (gAiLogicData->effectiveness[battler][opposingBattler][moveIndex] > UQ_4_12(0.0) && aiMove != MOVE_NONE && !CanAbilityAbsorbMove(battler, opposingBattler, gAiLogicData->abilities[opposingBattler], aiMove, GetBattleMoveType(aiMove), AI_CHECK) && !CanAbilityBlockMove(battler, opposingBattler, gBattleMons[battler].ability, gAiLogicData->abilities[opposingBattler], aiMove, AI_CHECK) && (!ALL_MOVES_BAD_STATUS_MOVES_BAD || GetMovePower(aiMove) != 0)) // If using ALL_MOVES_BAD_STATUS_MOVES_BAD, then need power to be non-zero @@ -441,7 +441,7 @@ static bool32 ShouldSwitchIfAllMovesBad(u32 battler) static bool32 ShouldSwitchIfWonderGuard(u32 battler) { u32 opposingBattler = GetOppositeBattler(battler); - u32 i, move; + u32 i; if (IsDoubleBattle()) return FALSE; @@ -452,12 +452,8 @@ static bool32 ShouldSwitchIfWonderGuard(u32 battler) // Check if Pokémon has a super effective move. for (i = 0; i < MAX_MON_MOVES; i++) { - move = gBattleMons[battler].moves[i]; - if (move != MOVE_NONE) - { - if (AI_GetMoveEffectiveness(move, battler, opposingBattler) >= UQ_4_12(2.0)) - return FALSE; - } + if (gBattleMons[battler].moves[i] != MOVE_NONE && gAiLogicData->effectiveness[battler][opposingBattler][i] >= UQ_4_12(2.0)) + return FALSE; } if (RandomPercentage(RNG_AI_SWITCH_WONDER_GUARD, GetSwitchChance(SHOULD_SWITCH_WONDER_GUARD))) @@ -475,14 +471,15 @@ static bool32 FindMonThatAbsorbsOpponentsMove(u32 battler) { u8 battlerIn1, battlerIn2; u8 numAbsorbingAbilities = 0; - u16 absorbingTypeAbilities[3]; // Array size is maximum number of absorbing abilities for a single type + enum Ability absorbingTypeAbilities[3]; // Array size is maximum number of absorbing abilities for a single type s32 firstId; s32 lastId; struct Pokemon *party; - u16 monAbility, aiMove; + enum Ability monAbility; + u16 aiMove; u32 opposingBattler = GetOppositeBattler(battler); u32 incomingMove = GetIncomingMove(battler, opposingBattler, gAiLogicData); - u32 incomingType = CheckDynamicMoveType(GetBattlerMon(opposingBattler), incomingMove, opposingBattler, MON_IN_BATTLE); + enum Type incomingType = CheckDynamicMoveType(GetBattlerMon(opposingBattler), incomingMove, opposingBattler, MON_IN_BATTLE); bool32 isOpposingBattlerChargingOrInvulnerable = !BreaksThroughSemiInvulnerablity(opposingBattler, incomingMove) || IsTwoTurnNotSemiInvulnerableMove(opposingBattler, incomingMove); s32 i, j; @@ -621,6 +618,7 @@ static bool32 ShouldSwitchIfOpponentChargingOrInvulnerable(u32 battler) if (IsDoubleBattle() || !(gAiThinkingStruct->aiFlags[battler] & AI_FLAG_SMART_SWITCHING)) return FALSE; + // In a world with a unified ShouldSwitch function, also want to check whether we already win 1v1 and if we do don't switch; not worth doubling the HasBadOdds computation for now if (isOpposingBattlerChargingOrInvulnerable && gAiLogicData->mostSuitableMonId[battler] != PARTY_SIZE && RandomPercentage(RNG_AI_SWITCH_FREE_TURN, GetSwitchChance(SHOULD_SWITCH_FREE_TURN))) return SetSwitchinAndSwitch(battler, PARTY_SIZE); @@ -633,7 +631,7 @@ static bool32 ShouldSwitchIfTrapperInParty(u32 battler) s32 lastId; struct Pokemon *party; s32 i; - u16 monAbility; + enum Ability monAbility; s32 opposingBattler = GetOppositeBattler(battler); // Only use this if AI_FLAG_SMART_SWITCHING is set for the trainer @@ -658,7 +656,7 @@ static bool32 ShouldSwitchIfTrapperInParty(u32 battler) if (CanAbilityTrapOpponent(monAbility, opposingBattler) || (CanAbilityTrapOpponent(gAiLogicData->abilities[opposingBattler], opposingBattler) && monAbility == ABILITY_TRACE)) { // If mon in slot i is the most suitable switchin candidate, then it's a trapper than wins 1v1 - if (i == gAiLogicData->mostSuitableMonId[battler] && RandomPercentage(RNG_AI_SWITCH_FREE_TURN, GetSwitchChance(SHOULD_SWITCH_FREE_TURN))) + if (i == gAiLogicData->mostSuitableMonId[battler] && RandomPercentage(RNG_AI_SWITCH_TRAPPER, GetSwitchChance(SHOULD_SWITCH_TRAPPER))) return SetSwitchinAndSwitch(battler, PARTY_SIZE); } } @@ -668,8 +666,8 @@ static bool32 ShouldSwitchIfTrapperInParty(u32 battler) static bool32 ShouldSwitchIfBadlyStatused(u32 battler) { bool32 switchMon = FALSE; - u16 monAbility = gAiLogicData->abilities[battler]; - enum ItemHoldEffect holdEffect = gAiLogicData->holdEffects[battler]; + enum Ability monAbility = gAiLogicData->abilities[battler]; + enum HoldEffect holdEffect = gAiLogicData->holdEffects[battler]; u8 opposingPosition = BATTLE_OPPOSITE(GetBattlerPosition(battler)); u8 opposingBattler = GetBattlerAtPosition(opposingPosition); bool32 hasStatRaised = AnyStatIsRaised(battler); @@ -706,8 +704,8 @@ static bool32 ShouldSwitchIfBadlyStatused(u32 battler) || monAbility == ABILITY_EARLY_BIRD) || holdEffect == (HOLD_EFFECT_CURE_SLP | HOLD_EFFECT_CURE_STATUS) || HasMove(battler, MOVE_SLEEP_TALK) - || (HasMoveWithEffect(battler, MOVE_SNORE) && AI_GetMoveEffectiveness(MOVE_SNORE, battler, opposingBattler) >= UQ_4_12(2.0)) - || (IsBattlerGrounded(battler) + || (HasMove(battler, MOVE_SNORE) && gAiLogicData->effectiveness[battler][opposingBattler][GetIndexInMoveArray(battler, MOVE_SNORE)] >= UQ_4_12(2.0)) + || (IsBattlerGrounded(battler, monAbility, gAiLogicData->holdEffects[battler]) && (HasMove(battler, MOVE_MISTY_TERRAIN) || HasMove(battler, MOVE_ELECTRIC_TERRAIN))) ) switchMon = FALSE; @@ -717,7 +715,7 @@ static bool32 ShouldSwitchIfBadlyStatused(u32 battler) && gAiLogicData->abilities[opposingBattler] != ABILITY_UNAWARE && gAiLogicData->abilities[opposingBattler] != ABILITY_KEEN_EYE && gAiLogicData->abilities[opposingBattler] != ABILITY_MINDS_EYE - && (GetGenConfig(GEN_ILLUMINATE_EFFECT) >= GEN_9 && gAiLogicData->abilities[opposingBattler] != ABILITY_ILLUMINATE) + && (GetConfig(CONFIG_ILLUMINATE_EFFECT) >= GEN_9 && gAiLogicData->abilities[opposingBattler] != ABILITY_ILLUMINATE) && !gBattleMons[battler].volatiles.foresight && !gBattleMons[battler].volatiles.miracleEye) switchMon = FALSE; @@ -830,10 +828,8 @@ static bool32 CanUseSuperEffectiveMoveAgainstOpponents(u32 battler) if (move == MOVE_NONE || AI_DoesChoiceEffectBlockMove(battler, move)) continue; - if (AI_GetMoveEffectiveness(move, battler, opposingBattler) >= UQ_4_12(2.0)) - { + if (gAiLogicData->effectiveness[battler][opposingBattler][i] >= UQ_4_12(2.0)) return TRUE; - } } } if (!IsDoubleBattle()) @@ -849,10 +845,8 @@ static bool32 CanUseSuperEffectiveMoveAgainstOpponents(u32 battler) if (move == MOVE_NONE || AI_DoesChoiceEffectBlockMove(battler, move)) continue; - if (AI_GetMoveEffectiveness(move, battler, opposingBattler) >= UQ_4_12(2.0)) - { + if (gAiLogicData->effectiveness[battler][opposingBattler][i] >= UQ_4_12(2.0)) return TRUE; - } } } @@ -900,7 +894,8 @@ static bool32 FindMonWithFlagsAndSuperEffective(u32 battler, u16 flags, u32 perc for (i = firstId; i < lastId; i++) { - u16 species, monAbility; + u16 species; + enum Ability monAbility; uq4_12_t typeMultiplier; u16 moveFlags = 0; @@ -928,7 +923,7 @@ static bool32 FindMonWithFlagsAndSuperEffective(u32 battler, u16 flags, u32 perc for (j = 0; j < MAX_MON_MOVES; j++) { move = GetMonData(&party[i], MON_DATA_MOVE1 + j); - if (move == 0) + if (move == MOVE_NONE) continue; if (AI_GetMoveEffectiveness(move, battler, battlerIn1) >= UQ_4_12(2.0) && (RandomPercentage(RNG_AI_SWITCH_SE_DEFENSIVE, percentChance) || gAiLogicData->aiPredictionInProgress)) @@ -944,7 +939,7 @@ static bool32 CanMonSurviveHazardSwitchin(u32 battler) { u32 battlerIn1, battlerIn2; u32 hazardDamage = 0, battlerHp = gBattleMons[battler].hp; - u32 ability = gAiLogicData->abilities[battler], aiMove; + enum Ability ability = gAiLogicData->abilities[battler], aiMove; s32 firstId, lastId, i, j; struct Pokemon *party; @@ -1019,7 +1014,7 @@ static bool32 ShouldSwitchIfEncored(u32 battler) return SetSwitchinAndSwitch(battler, PARTY_SIZE); // Stay in if effective move - else if (AI_GetMoveEffectiveness(encoredMove, battler, opposingBattler) >= UQ_4_12(2.0)) + else if (gAiLogicData->effectiveness[battler][opposingBattler][GetIndexInMoveArray(battler, encoredMove)] >= UQ_4_12(2.0)) return FALSE; // Switch out 50% of the time otherwise @@ -1031,7 +1026,7 @@ static bool32 ShouldSwitchIfEncored(u32 battler) static bool32 ShouldSwitchIfBadChoiceLock(u32 battler) { - enum ItemHoldEffect holdEffect = GetBattlerHoldEffect(battler, FALSE); + enum HoldEffect holdEffect = GetBattlerHoldEffect(battler); u32 lastUsedMove = gAiLogicData->lastUsedMove[battler]; u32 opposingBattler = GetOppositeBattler(battler); bool32 moveAffectsTarget = TRUE; @@ -1356,6 +1351,7 @@ void AI_TrySwitchOrUseItem(u32 battler) if (gAiLogicData->shouldSwitch & (1u << battler) && IsSwitchinValid(battler)) { BtlController_EmitTwoReturnValues(battler, B_COMM_TO_ENGINE, B_ACTION_SWITCH, 0); + SetAIUsingGimmick(battler, NO_GIMMICK); if (gBattleStruct->AI_monToSwitchIntoId[battler] == PARTY_SIZE) { s32 monToSwitchId = gAiLogicData->mostSuitableMonId[battler]; @@ -1402,6 +1398,7 @@ void AI_TrySwitchOrUseItem(u32 battler) } else if (ShouldUseItem(battler)) { + SetAIUsingGimmick(battler, NO_GIMMICK); return; } } @@ -1494,8 +1491,8 @@ static u32 GetBestMonDmg(struct Pokemon *party, int firstId, int lastId, u8 inva int i, j; int dmg, bestDmg = 0; int bestMonId = PARTY_SIZE; - u32 aiMove; + uq4_12_t effectiveness; // 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++) @@ -1509,7 +1506,7 @@ static u32 GetBestMonDmg(struct Pokemon *party, int firstId, int lastId, u8 inva if (aiMove != MOVE_NONE && !IsBattleMoveStatus(aiMove)) { aiMove = GetMonData(&party[i], MON_DATA_MOVE1 + j); - dmg = AI_CalcPartyMonDamage(aiMove, battler, opposingBattler, gAiLogicData->switchinCandidate.battleMon, AI_ATTACKING); + dmg = AI_CalcPartyMonDamage(aiMove, battler, opposingBattler, gAiLogicData->switchinCandidate.battleMon, &effectiveness, AI_ATTACKING); if (bestDmg < dmg) { bestDmg = dmg; @@ -1522,25 +1519,22 @@ static u32 GetBestMonDmg(struct Pokemon *party, int firstId, int lastId, u8 inva return bestMonId; } -static u32 GetFirstNonInvalidMon(u32 firstId, u32 lastId, u32 invalidMons, u32 battlerIn1, u32 battlerIn2) +static u32 GetFirstNonInvalidMon(u32 firstId, u32 lastId, u32 invalidMons) { - if (!IsDoubleBattle()) - return PARTY_SIZE; - - if (PARTY_SIZE != gBattleStruct->monToSwitchIntoId[battlerIn1] - && PARTY_SIZE != gBattleStruct->monToSwitchIntoId[battlerIn2]) - return PARTY_SIZE; - - for (u32 chosenMonId = (lastId-1); chosenMonId >= firstId; chosenMonId--) + u32 chosenMonId = PARTY_SIZE; + for (u32 i = (lastId-1); i > firstId; i--) { - if ((1 << (chosenMonId)) & invalidMons) - continue; - return chosenMonId; // first non invalid mon found + if (!((1 << i) & invalidMons)) + { + // first non invalid mon found + chosenMonId = i; + break; + } } - return PARTY_SIZE; + return chosenMonId; } -bool32 IsMonGrounded(u16 heldItemEffect, u32 ability, u8 type1, u8 type2) +bool32 IsMonGrounded(enum HoldEffect heldItemEffect, enum Ability ability, enum Type type1, enum Type type2) { // List that makes mon not grounded if (type1 == TYPE_FLYING || type2 == TYPE_FLYING || ability == ABILITY_LEVITATE @@ -1559,9 +1553,11 @@ bool32 IsMonGrounded(u16 heldItemEffect, u32 ability, u8 type1, u8 type2) // Gets hazard damage static u32 GetSwitchinHazardsDamage(u32 battler, struct BattlePokemon *battleMon) { - u8 defType1 = battleMon->types[0], defType2 = battleMon->types[1], tSpikesLayers; + enum Type defType1 = battleMon->types[0], defType2 = battleMon->types[1]; + u8 tSpikesLayers; u16 heldItemEffect = GetItemHoldEffect(battleMon->item); - u32 maxHP = battleMon->maxHP, ability = battleMon->ability, status = battleMon->status1; + u32 maxHP = battleMon->maxHP; + enum Ability ability = battleMon->ability, status = battleMon->status1; u32 spikesDamage = 0, tSpikesDamage = 0, hazardDamage = 0; u32 side = GetBattlerSide(battler); @@ -1576,7 +1572,7 @@ static u32 GetSwitchinHazardsDamage(u32 battler, struct BattlePokemon *battleMon if (IsHazardOnSide(side, HAZARDS_STEELSURGE) && heldItemEffect != HOLD_EFFECT_HEAVY_DUTY_BOOTS) hazardDamage += GetStealthHazardDamageByTypesAndHP(TYPE_SIDE_HAZARD_SHARP_STEEL, defType1, defType2, battleMon->maxHP); // Spikes - if (IsHazardOnSide(side, HAZARDS_TOXIC_SPIKES) && IsMonGrounded(heldItemEffect, ability, defType1, defType2)) + if (IsHazardOnSide(side, HAZARDS_SPIKES) && IsMonGrounded(heldItemEffect, ability, defType1, defType2)) { spikesDamage = maxHP / ((5 - gSideTimers[GetBattlerSide(battler)].spikesAmount) * 2); if (spikesDamage == 0) @@ -1584,13 +1580,13 @@ static u32 GetSwitchinHazardsDamage(u32 battler, struct BattlePokemon *battleMon hazardDamage += spikesDamage; } - if (IsHazardOnSide(side, HAZARDS_SPIKES) && (defType1 != TYPE_POISON && defType2 != TYPE_POISON + if (IsHazardOnSide(side, HAZARDS_TOXIC_SPIKES) && (defType1 != TYPE_POISON && defType2 != TYPE_POISON && defType1 != TYPE_STEEL && defType2 != TYPE_STEEL && ability != ABILITY_IMMUNITY && ability != ABILITY_POISON_HEAL && ability != ABILITY_COMATOSE && status == 0 && !(gSideStatuses[GetBattlerSide(battler)] & SIDE_STATUS_SAFEGUARD) && !IsAbilityOnSide(battler, ABILITY_PASTEL_VEIL) - && !IsBattlerTerrainAffected(battler, STATUS_FIELD_MISTY_TERRAIN) + && !IsBattlerTerrainAffected(battler, ability, gAiLogicData->holdEffects[battler], STATUS_FIELD_MISTY_TERRAIN) && !IsAbilityStatusProtected(battler, ability) && heldItemEffect != HOLD_EFFECT_CURE_PSN && heldItemEffect != HOLD_EFFECT_CURE_STATUS && IsMonGrounded(heldItemEffect, ability, defType1, defType2))) @@ -1617,8 +1613,9 @@ static u32 GetSwitchinHazardsDamage(u32 battler, struct BattlePokemon *battleMon // Gets damage / healing from weather static s32 GetSwitchinWeatherImpact(void) { - s32 weatherImpact = 0, maxHP = gAiLogicData->switchinCandidate.battleMon.maxHP, ability = gAiLogicData->switchinCandidate.battleMon.ability; - enum ItemHoldEffect holdEffect = GetItemHoldEffect(gAiLogicData->switchinCandidate.battleMon.item); + s32 weatherImpact = 0, maxHP = gAiLogicData->switchinCandidate.battleMon.maxHP; + enum Ability ability = gAiLogicData->switchinCandidate.battleMon.ability; + enum HoldEffect holdEffect = GetItemHoldEffect(gAiLogicData->switchinCandidate.battleMon.item); if (HasWeatherEffect()) { @@ -1681,8 +1678,9 @@ static s32 GetSwitchinWeatherImpact(void) // Gets one turn of recurring healing static u32 GetSwitchinRecurringHealing(void) { - u32 recurringHealing = 0, maxHP = gAiLogicData->switchinCandidate.battleMon.maxHP, ability = gAiLogicData->switchinCandidate.battleMon.ability; - enum ItemHoldEffect holdEffect = GetItemHoldEffect(gAiLogicData->switchinCandidate.battleMon.item); + u32 recurringHealing = 0, maxHP = gAiLogicData->switchinCandidate.battleMon.maxHP; + enum Ability ability = gAiLogicData->switchinCandidate.battleMon.ability; + enum HoldEffect holdEffect = GetItemHoldEffect(gAiLogicData->switchinCandidate.battleMon.item); // Items if (ability != ABILITY_KLUTZ) @@ -1715,8 +1713,9 @@ static u32 GetSwitchinRecurringHealing(void) // Gets one turn of recurring damage static u32 GetSwitchinRecurringDamage(void) { - u32 passiveDamage = 0, maxHP = gAiLogicData->switchinCandidate.battleMon.maxHP, ability = gAiLogicData->switchinCandidate.battleMon.ability; - enum ItemHoldEffect holdEffect = GetItemHoldEffect(gAiLogicData->switchinCandidate.battleMon.item); + u32 passiveDamage = 0, maxHP = gAiLogicData->switchinCandidate.battleMon.maxHP; + enum Ability ability = gAiLogicData->switchinCandidate.battleMon.ability; + enum HoldEffect holdEffect = GetItemHoldEffect(gAiLogicData->switchinCandidate.battleMon.item); // Items if (ability != ABILITY_MAGIC_GUARD && ability != ABILITY_KLUTZ) @@ -1746,10 +1745,11 @@ static u32 GetSwitchinRecurringDamage(void) // Gets one turn of status damage static u32 GetSwitchinStatusDamage(u32 battler) { - u8 defType1 = gAiLogicData->switchinCandidate.battleMon.types[0], defType2 = gAiLogicData->switchinCandidate.battleMon.types[1]; + enum Type defType1 = gAiLogicData->switchinCandidate.battleMon.types[0], defType2 = gAiLogicData->switchinCandidate.battleMon.types[1]; u8 tSpikesLayers = gSideTimers[GetBattlerSide(battler)].toxicSpikesAmount; u16 heldItemEffect = GetItemHoldEffect(gAiLogicData->switchinCandidate.battleMon.item); - u32 status = gAiLogicData->switchinCandidate.battleMon.status1, ability = gAiLogicData->switchinCandidate.battleMon.ability, maxHP = gAiLogicData->switchinCandidate.battleMon.maxHP; + u32 status = gAiLogicData->switchinCandidate.battleMon.status1; + enum Ability ability = gAiLogicData->switchinCandidate.battleMon.ability, maxHP = gAiLogicData->switchinCandidate.battleMon.maxHP; u32 statusDamage = 0; // Status condition damage @@ -1829,7 +1829,7 @@ static u32 GetSwitchinHitsToKO(s32 damageTaken, u32 battler) u16 maxHP = gAiLogicData->switchinCandidate.battleMon.maxHP, item = gAiLogicData->switchinCandidate.battleMon.item, heldItemEffect = GetItemHoldEffect(item); u8 weatherDuration = gWishFutureKnock.weatherDuration, holdEffectParam = GetItemHoldEffectParam(item); u32 opposingBattler = GetOppositeBattler(battler); - u32 opposingAbility = gAiLogicData->abilities[opposingBattler], ability = gAiLogicData->switchinCandidate.battleMon.ability; + enum Ability opposingAbility = gAiLogicData->abilities[opposingBattler], ability = gAiLogicData->switchinCandidate.battleMon.ability; bool32 usedSingleUseHealingItem = FALSE, opponentCanBreakMold = IsMoldBreakerTypeAbility(opposingBattler, opposingAbility); s32 currentHP = startingHP, singleUseItemHeal = 0; @@ -1934,8 +1934,8 @@ static u32 GetBattleMonTypeMatchup(struct BattlePokemon opposingBattleMon, struc { // Check type matchup u32 typeEffectiveness1 = UQ_4_12(1.0), typeEffectiveness2 = UQ_4_12(1.0); - u8 atkType1 = opposingBattleMon.types[0], atkType2 = opposingBattleMon.types[1], - defType1 = battleMon.types[0], defType2 = battleMon.types[1]; + enum Type atkType1 = opposingBattleMon.types[0], atkType2 = opposingBattleMon.types[1]; + enum Type defType1 = battleMon.types[0], defType2 = battleMon.types[1]; // Add each independent defensive type matchup together typeEffectiveness1 = uq4_12_multiply(typeEffectiveness1, (GetTypeModifier(atkType1, defType1))); @@ -1986,13 +1986,14 @@ static s32 GetMaxDamagePlayerCouldDealToSwitchin(u32 battler, u32 opposingBattle u32 playerMove; u16 *playerMoves = GetMovesArray(opposingBattler); s32 damageTaken = 0, maxDamageTaken = 0; + uq4_12_t effectiveness; for (i = 0; i < MAX_MON_MOVES; i++) { playerMove = SMART_SWITCHING_OMNISCIENT ? gBattleMons[opposingBattler].moves[i] : playerMoves[i]; if (playerMove != MOVE_NONE && !IsBattleMoveStatus(playerMove) && GetMoveEffect(playerMove) != EFFECT_FOCUS_PUNCH && gBattleMons[opposingBattler].pp[i] > 0) { - damageTaken = AI_CalcPartyMonDamage(playerMove, opposingBattler, battler, battleMon, AI_DEFENDING); + damageTaken = AI_CalcPartyMonDamage(playerMove, opposingBattler, battler, battleMon, &effectiveness, AI_DEFENDING); if (playerMove == gBattleStruct->choicedMove[opposingBattler]) // If player is choiced, only care about the choice locked move { *bestPlayerMove = playerMove; @@ -2014,6 +2015,7 @@ static s32 GetMaxPriorityDamagePlayerCouldDealToSwitchin(u32 battler, u32 opposi u32 playerMove; u16 *playerMoves = GetMovesArray(opposingBattler); s32 damageTaken = 0, maxDamageTaken = 0; + uq4_12_t effectiveness = UQ_4_12(1.0); for (i = 0; i < MAX_MON_MOVES; i++) { @@ -2024,7 +2026,7 @@ static s32 GetMaxPriorityDamagePlayerCouldDealToSwitchin(u32 battler, u32 opposi if (GetBattleMovePriority(opposingBattler, gAiLogicData->abilities[opposingBattler], playerMove) > 0 && playerMove != MOVE_NONE && !IsBattleMoveStatus(playerMove) && GetMoveEffect(playerMove) != EFFECT_FOCUS_PUNCH && gBattleMons[opposingBattler].pp[i] > 0) { - damageTaken = AI_CalcPartyMonDamage(playerMove, opposingBattler, battler, battleMon, AI_DEFENDING); + damageTaken = AI_CalcPartyMonDamage(playerMove, opposingBattler, battler, battleMon, &effectiveness, AI_DEFENDING); if (playerMove == gBattleStruct->choicedMove[opposingBattler]) // If player is choiced, only care about the choice locked move { *bestPlayerPriorityMove = playerMove; @@ -2040,7 +2042,7 @@ static s32 GetMaxPriorityDamagePlayerCouldDealToSwitchin(u32 battler, u32 opposi return maxDamageTaken; } -static bool32 CanAbilityTrapOpponent(u16 ability, u32 opponent) +static bool32 CanAbilityTrapOpponent(enum Ability ability, u32 opponent) { if ((B_GHOSTS_ESCAPE >= GEN_6 && IS_BATTLER_OF_TYPE(opponent, TYPE_GHOST))) return FALSE; @@ -2051,7 +2053,7 @@ static bool32 CanAbilityTrapOpponent(u16 ability, u32 opponent) else return TRUE; } - else if (ability == ABILITY_ARENA_TRAP && IsBattlerGrounded(opponent)) + else if (ability == ABILITY_ARENA_TRAP && IsBattlerGrounded(opponent, gAiLogicData->abilities[opponent], gAiLogicData->holdEffects[opponent])) return TRUE; else if (ability == ABILITY_MAGNET_PULL && IS_BATTLER_OF_TYPE(opponent, TYPE_STEEL)) return TRUE; @@ -2072,7 +2074,7 @@ static inline bool32 IsFreeSwitch(enum SwitchType switchType, u32 battlerSwitchi return TRUE; if (gAiLogicData->ejectPackSwitch) { - u32 opposingAbility = GetBattlerAbilityIgnoreMoldBreaker(opposingBattler); + enum Ability opposingAbility = GetBattlerAbilityIgnoreMoldBreaker(opposingBattler); // If faster, not a free switch; likely lowered own stats if (!movedSecond && opposingAbility != ABILITY_INTIMIDATE && opposingAbility != ABILITY_SUPERSWEET_SYRUP) // Intimidate triggers switches before turn starts return FALSE; @@ -2122,11 +2124,12 @@ static u32 GetBestMonIntegrated(struct Pokemon *party, int firstId, int lastId, int batonPassId = PARTY_SIZE, typeMatchupId = PARTY_SIZE, typeMatchupEffectiveId = PARTY_SIZE, defensiveMonId = PARTY_SIZE, aceMonId = PARTY_SIZE, trapperId = PARTY_SIZE; int i, j, aliveCount = 0, bits = 0, aceMonCount = 0; s32 defensiveMonHitKOThreshold = 3; // 3HKO threshold that candidate defensive mons must exceed - s32 playerMonHP = gBattleMons[opposingBattler].hp, maxDamageDealt = 0, damageDealt = 0; + s32 playerMonHP = gBattleMons[opposingBattler].hp, maxDamageDealt = 0, damageDealt = 0, monMaxDamage = 0; u32 aiMove, hitsToKOAI, hitsToKOPlayer, hitsToKOAIPriority, bestPlayerMove = MOVE_NONE, bestPlayerPriorityMove = MOVE_NONE, maxHitsToKO = 0; u32 bestResist = UQ_4_12(2.0), bestResistEffective = UQ_4_12(2.0), typeMatchup; // 2.0 is the default "Neutral" matchup from GetBattleMonTypeMatchup bool32 isFreeSwitch = IsFreeSwitch(switchType, battlerIn1, opposingBattler), isSwitchinFirst, isSwitchinFirstPriority, canSwitchinWin1v1; u32 invalidMons = 0; + uq4_12_t effectiveness = UQ_4_12(1.0); // Iterate through mons for (i = firstId; i < lastId; i++) @@ -2163,6 +2166,8 @@ static u32 GetBestMonIntegrated(struct Pokemon *party, int firstId, int lastId, hitsToKOAIPriority = GetSwitchinHitsToKO(GetMaxPriorityDamagePlayerCouldDealToSwitchin(battler, opposingBattler, gAiLogicData->switchinCandidate.battleMon, &bestPlayerPriorityMove), battler); typeMatchup = GetBattleMonTypeMatchup(gBattleMons[opposingBattler], gAiLogicData->switchinCandidate.battleMon); + monMaxDamage = 0; + // Check through current mon's moves for (j = 0; j < MAX_MON_MOVES; j++) { @@ -2171,7 +2176,7 @@ static u32 GetBestMonIntegrated(struct Pokemon *party, int firstId, int lastId, continue; aiMove = gAiLogicData->switchinCandidate.battleMon.moves[j]; - damageDealt = AI_CalcPartyMonDamage(aiMove, battler, opposingBattler, gAiLogicData->switchinCandidate.battleMon, AI_ATTACKING); + damageDealt = AI_CalcPartyMonDamage(aiMove, battler, opposingBattler, gAiLogicData->switchinCandidate.battleMon, &effectiveness, AI_ATTACKING); hitsToKOPlayer = GetNoOfHitsToKOBattlerDmg(damageDealt, opposingBattler); // Offensive switchin decisions are based on which whether switchin moves first and whether it can win a 1v1 @@ -2212,7 +2217,7 @@ static u32 GetBestMonIntegrated(struct Pokemon *party, int firstId, int lastId, { if (typeMatchup < bestResistEffective) { - if (AI_GetMoveEffectiveness(aiMove, battler, opposingBattler) >= UQ_4_12(2.0)) + if (effectiveness >= UQ_4_12(2.0)) { if (canSwitchinWin1v1) { @@ -2228,6 +2233,8 @@ static u32 GetBestMonIntegrated(struct Pokemon *party, int firstId, int lastId, && damageDealt < playerMonHP) continue; + if (damageDealt > monMaxDamage) + monMaxDamage = damageDealt; // Check that mon isn't one shot and set best damage mon if (damageDealt > maxDamageDealt) { @@ -2240,7 +2247,7 @@ static u32 GetBestMonIntegrated(struct Pokemon *party, int firstId, int lastId, // Check if current mon can revenge kill in some capacity // If AI mon can one shot - if (damageDealt > playerMonHP) + if (damageDealt >= playerMonHP) { if (canSwitchinWin1v1) { @@ -2252,7 +2259,7 @@ static u32 GetBestMonIntegrated(struct Pokemon *party, int firstId, int lastId, } // If AI mon can two shot - if (damageDealt > playerMonHP / 2) + if (damageDealt >= (playerMonHP / 2 + playerMonHP % 2)) // Modulo to handle odd numbers in non-decimal division { if (canSwitchinWin1v1) { @@ -2271,6 +2278,8 @@ static u32 GetBestMonIntegrated(struct Pokemon *party, int firstId, int lastId, trapperId = i; } } + if (monMaxDamage == 0) + invalidMons |= 1u << i; } batonPassId = GetRandomSwitchinWithBatonPass(aliveCount, bits, firstId, lastId, i); @@ -2300,16 +2309,19 @@ static u32 GetBestMonIntegrated(struct Pokemon *party, int firstId, int lastId, else if (batonPassId != PARTY_SIZE) return batonPassId; else if (generic1v1MonId != PARTY_SIZE) return generic1v1MonId; } - // If ace mon is the last available Pokemon and U-Turn/Volt Switch or Eject Pack/Button was used - switch to the mon. - if (aceMonId != PARTY_SIZE && CountUsablePartyMons(battler) <= aceMonCount - && (IsSwitchOutEffect(GetMoveEffect(gCurrentMove)) || gAiLogicData->ejectButtonSwitch || gAiLogicData->ejectPackSwitch)) - return aceMonId; + + if (switchType == SWITCH_MID_BATTLE_OPTIONAL) + return PARTY_SIZE; // Fallback - u32 bestMonId = GetFirstNonInvalidMon(firstId, lastId, invalidMons, battlerIn1, battlerIn2); + u32 bestMonId = GetFirstNonInvalidMon(firstId, lastId, invalidMons); if (bestMonId != PARTY_SIZE) return bestMonId; + // If ace mon is the last available Pokemon and U-Turn/Volt Switch or Eject Pack/Button was used - switch to the mon. + if (aceMonId != PARTY_SIZE && CountUsablePartyMons(battler) <= aceMonCount) + return aceMonId; + return PARTY_SIZE; } @@ -2425,16 +2437,17 @@ u32 GetMostSuitableMonToSwitchInto(u32 battler, enum SwitchType switchType) if (bestMonId != PARTY_SIZE) return bestMonId; - // If ace mon is the last available Pokemon and U-Turn/Volt Switch or Eject Pack/Button was used - switch to the mon. - if (aceMonId != PARTY_SIZE && CountUsablePartyMons(battler) <= aceMonCount - && (IsSwitchOutEffect(GetMoveEffect(gCurrentMove)) || gAiLogicData->ejectButtonSwitch || gAiLogicData->ejectPackSwitch)) - return aceMonId; + if (switchType == SWITCH_MID_BATTLE_OPTIONAL) + return PARTY_SIZE; // Fallback - bestMonId = GetFirstNonInvalidMon(firstId, lastId, invalidMons, battlerIn1, battlerIn2); + bestMonId = GetFirstNonInvalidMon(firstId, lastId, invalidMons); if (bestMonId != PARTY_SIZE) return bestMonId; + if (aceMonId != PARTY_SIZE && CountUsablePartyMons(battler) <= aceMonCount) + return aceMonId; + return PARTY_SIZE; } } @@ -2513,18 +2526,13 @@ static bool32 ShouldUseItem(u32 battler) shouldUse = AI_ShouldHeal(battler, healAmount); break; case EFFECT_ITEM_CURE_STATUS: - if (itemEffects[3] & ITEM3_SLEEP && gBattleMons[battler].status1 & STATUS1_SLEEP) - shouldUse = TRUE; - if (itemEffects[3] & ITEM3_POISON && gBattleMons[battler].status1 & STATUS1_PSN_ANY) - shouldUse = TRUE; - if (itemEffects[3] & ITEM3_BURN && gBattleMons[battler].status1 & STATUS1_BURN) - shouldUse = TRUE; - if (itemEffects[3] & ITEM3_FREEZE && gBattleMons[battler].status1 & STATUS1_ICY_ANY) - shouldUse = TRUE; - if (itemEffects[3] & ITEM3_PARALYSIS && gBattleMons[battler].status1 & STATUS1_PARALYSIS) - shouldUse = TRUE; - if (itemEffects[3] & ITEM3_CONFUSION && gBattleMons[battler].volatiles.confusionTurns > 0) - shouldUse = TRUE; + if ((itemEffects[3] & ITEM3_SLEEP && gBattleMons[battler].status1 & STATUS1_SLEEP) + || (itemEffects[3] & ITEM3_POISON && gBattleMons[battler].status1 & STATUS1_PSN_ANY) + || (itemEffects[3] & ITEM3_BURN && gBattleMons[battler].status1 & STATUS1_BURN) + || (itemEffects[3] & ITEM3_FREEZE && gBattleMons[battler].status1 & STATUS1_ICY_ANY) + || (itemEffects[3] & ITEM3_PARALYSIS && gBattleMons[battler].status1 & STATUS1_PARALYSIS) + || (itemEffects[3] & ITEM3_CONFUSION && gBattleMons[battler].volatiles.confusionTurns > 0)) + shouldUse = ShouldCureStatusWithItem(battler, battler, gAiLogicData); break; case EFFECT_ITEM_INCREASE_STAT: case EFFECT_ITEM_INCREASE_ALL_STATS: diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index e39e80a2d2..413bbcc8ac 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -20,7 +20,6 @@ #include "constants/abilities.h" #include "constants/battle_ai.h" #include "constants/battle_move_effects.h" -#include "constants/hold_effects.h" #include "constants/moves.h" #include "constants/items.h" @@ -28,7 +27,7 @@ static u32 GetAIEffectGroup(enum BattleMoveEffects effect); static u32 GetAIEffectGroupFromMove(u32 battler, u32 move); // Functions -static u32 AI_GetMoldBreakerSanitizedAbility(u32 battlerAtk, u32 abilityAtk, u32 abilityDef, u32 holdEffectDef, u32 move) +static u32 AI_GetMoldBreakerSanitizedAbility(u32 battlerAtk, enum Ability abilityAtk, enum Ability abilityDef, u32 holdEffectDef, u32 move) { if (MoveIgnoresTargetAbility(move)) return ABILITY_NONE; @@ -65,6 +64,11 @@ static bool32 AI_IsDoubleSpreadMove(u32 battlerAtk, u32 move) return FALSE; } +bool32 AI_IsBattlerGrounded(u32 battler) +{ + return IsBattlerGrounded(battler, gAiLogicData->abilities[battler], gAiLogicData->holdEffects[battler]); +} + u32 AI_GetDamage(u32 battlerAtk, u32 battlerDef, u32 moveIndex, enum DamageCalcContext calcContext, struct AiLogicData *aiData) { if (calcContext == AI_ATTACKING && BattlerHasAi(battlerAtk)) @@ -256,7 +260,7 @@ void RecordAllMoves(u32 battler) memcpy(gAiPartyData->mons[GetBattlerSide(battler)][gBattlerPartyIndexes[battler]].moves, gBattleMons[battler].moves, MAX_MON_MOVES * sizeof(u16)); } -void RecordAbilityBattle(u32 battlerId, u32 abilityId) +void RecordAbilityBattle(u32 battlerId, enum Ability abilityId) { gBattleHistory->abilities[battlerId] = abilityId; gAiPartyData->mons[GetBattlerSide(battlerId)][gBattlerPartyIndexes[battlerId]].ability = abilityId; @@ -267,7 +271,7 @@ void ClearBattlerAbilityHistory(u32 battlerId) gBattleHistory->abilities[battlerId] = ABILITY_NONE; } -void RecordItemEffectBattle(u32 battlerId, u32 itemEffect) +void RecordItemEffectBattle(u32 battlerId, enum HoldEffect itemEffect) { gBattleHistory->itemEffects[battlerId] = itemEffect; gAiPartyData->mons[GetBattlerSide(battlerId)][gBattlerPartyIndexes[battlerId]].heldEffect = itemEffect; @@ -468,7 +472,7 @@ bool32 AI_BattlerAtMaxHp(u32 battlerId) bool32 AI_CanBattlerEscape(u32 battler) { - enum ItemHoldEffect holdEffect = gAiLogicData->holdEffects[battler]; + enum HoldEffect holdEffect = gAiLogicData->holdEffects[battler]; if (B_GHOSTS_ESCAPE >= GEN_6 && IS_BATTLER_OF_TYPE(battler, TYPE_GHOST)) return TRUE; @@ -480,6 +484,9 @@ bool32 AI_CanBattlerEscape(u32 battler) bool32 IsBattlerTrapped(u32 battlerAtk, u32 battlerDef) { + if (AI_CanBattlerEscape(battlerDef)) + return FALSE; + if (gBattleMons[battlerDef].volatiles.wrapped) return TRUE; if (gBattleMons[battlerDef].volatiles.escapePrevention) @@ -494,23 +501,26 @@ bool32 IsBattlerTrapped(u32 battlerAtk, u32 battlerDef) && (B_SHADOW_TAG_ESCAPE >= GEN_4 && gAiLogicData->abilities[battlerDef] != ABILITY_SHADOW_TAG)) return TRUE; if (AI_IsAbilityOnSide(battlerAtk, ABILITY_ARENA_TRAP) - && IsBattlerGrounded(battlerAtk)) + && AI_IsBattlerGrounded(battlerAtk)) return TRUE; if (AI_IsAbilityOnSide(battlerAtk, ABILITY_MAGNET_PULL) && IS_BATTLER_OF_TYPE(battlerAtk, TYPE_STEEL)) return TRUE; + if (gBattleTypeFlags & BATTLE_TYPE_TRAINER && CountUsablePartyMons(battlerDef) == 0) + return TRUE; + return FALSE; } u32 GetTotalBaseStat(u32 species) { return GetSpeciesBaseHP(species) - + GetSpeciesBaseAttack(species) - + GetSpeciesBaseDefense(species) - + GetSpeciesBaseSpeed(species) - + GetSpeciesBaseSpAttack(species) - + GetSpeciesBaseSpDefense(species); + + GetSpeciesBaseAttack(species) + + GetSpeciesBaseDefense(species) + + GetSpeciesBaseSpeed(species) + + GetSpeciesBaseSpAttack(species) + + GetSpeciesBaseSpDefense(species); } bool32 IsTruantMonVulnerable(u32 battlerAI, u32 opposingBattler) @@ -530,6 +540,25 @@ bool32 IsTruantMonVulnerable(u32 battlerAI, u32 opposingBattler) return FALSE; } +bool32 Ai_IsPriorityBlocked(u32 battlerAtk, u32 battlerDef, u32 move, struct AiLogicData *aiData) +{ + s32 atkPriority = GetBattleMovePriority(battlerAtk, aiData->abilities[battlerAtk], move); + + if (atkPriority <= 0 || IsBattlerAlly(battlerAtk, battlerDef)) + return FALSE; + + if (IsMoldBreakerTypeAbility(battlerAtk, aiData->abilities[battlerAtk]) || MoveIgnoresTargetAbility(move)) + return FALSE; + + if (IsDazzlingAbility(aiData->abilities[battlerDef])) + return TRUE; + + if (IsDoubleBattle() && IsDazzlingAbility(aiData->abilities[BATTLE_PARTNER(battlerDef)])) + return TRUE; + + return FALSE; +} + // This function checks if all physical/special moves are either unusable or unreasonable to use. // Consider a pokemon boosting their attack against a ghost pokemon having only normal-type physical attacks. bool32 MovesWithCategoryUnusable(u32 attacker, u32 target, enum DamageCategory category) @@ -555,7 +584,7 @@ bool32 MovesWithCategoryUnusable(u32 attacker, u32 target, enum DamageCategory c if (GetBattleMoveCategory(moves[i]) == category) { SetTypeBeforeUsingMove(moves[i], attacker); - ctx.move = moves[i]; + ctx.move = ctx.chosenMove = moves[i]; ctx.moveType = GetBattleMoveType(moves[i]); if (CalcTypeEffectivenessMultiplier(&ctx)) @@ -604,8 +633,8 @@ static inline s32 DmgRoll(s32 dmg) bool32 IsDamageMoveUnusable(struct DamageContext *ctx) { - u32 battlerDefAbility; - u32 partnerDefAbility; + enum Ability battlerDefAbility; + enum Ability partnerDefAbility; struct AiLogicData *aiData = gAiLogicData; if (ctx->typeEffectivenessModifier == UQ_4_12(0.0)) @@ -625,6 +654,9 @@ bool32 IsDamageMoveUnusable(struct DamageContext *ctx) partnerDefAbility = aiData->abilities[BATTLE_PARTNER(ctx->battlerDef)]; } + if (Ai_IsPriorityBlocked(ctx->battlerAtk, ctx->battlerDef, ctx->move, aiData)) + return TRUE; + if (CanAbilityBlockMove(ctx->battlerAtk, ctx->battlerDef, ctx->abilityAtk, battlerDefAbility, ctx->move, AI_CHECK)) return TRUE; @@ -660,7 +692,7 @@ bool32 IsDamageMoveUnusable(struct DamageContext *ctx) return TRUE; break; case EFFECT_LAST_RESORT: - if (!CanUseLastResort(ctx->battlerAtk)) + if (!CanUseLastResort(ctx->battlerAtk) && !IsConsideringZMove(ctx->battlerAtk, ctx->battlerDef, ctx->move)) return TRUE; break; case EFFECT_LOW_KICK: @@ -731,14 +763,14 @@ static inline s32 SetFixedMoveBasePower(u32 battlerAtk, u32 move) return fixedBasePower; } -static inline void AI_StoreBattlerTypes(u32 battlerAtk, u32 *types) +static inline void AI_StoreBattlerTypes(u32 battlerAtk, enum Type *types) { types[0] = gBattleMons[battlerAtk].types[0]; types[1] = gBattleMons[battlerAtk].types[1]; types[2] = gBattleMons[battlerAtk].types[2]; } -static inline void AI_RestoreBattlerTypes(u32 battlerAtk, u32 *types) +static inline void AI_RestoreBattlerTypes(u32 battlerAtk, enum Type *types) { gBattleMons[battlerAtk].types[0] = types[0]; gBattleMons[battlerAtk].types[1] = types[1]; @@ -786,7 +818,7 @@ static inline void CalcDynamicMoveDamage(struct DamageContext *ctx, u16 *medianD median = maximum = minimum = max(0, gBattleMons[ctx->battlerDef].hp - gBattleMons[ctx->battlerAtk].hp); break; case EFFECT_BEAT_UP: - if (B_BEAT_UP >= GEN_5) + if (GetConfig(CONFIG_BEAT_UP) >= GEN_5) { u32 partyCount = CalculatePartyCount(GetBattlerParty(ctx->battlerAtk)); u32 i; @@ -841,7 +873,7 @@ static inline bool32 ShouldCalcCritDamage(u32 battlerAtk, u32 battlerDef, u32 mo s32 critChanceIndex = 0; // Get crit chance - if (GetGenConfig(GEN_CONFIG_CRIT_CHANCE) == GEN_1) + if (GetConfig(CONFIG_CRIT_CHANCE) == GEN_1) critChanceIndex = CalcCritChanceStageGen1(battlerAtk, battlerDef, move, FALSE, aiData->abilities[battlerAtk], aiData->abilities[battlerDef], aiData->holdEffects[battlerAtk]); else critChanceIndex = CalcCritChanceStage(battlerAtk, battlerDef, move, FALSE, aiData->abilities[battlerAtk], aiData->abilities[battlerDef], aiData->holdEffects[battlerAtk]); @@ -850,18 +882,18 @@ static inline bool32 ShouldCalcCritDamage(u32 battlerAtk, u32 battlerDef, u32 mo return TRUE; if (critChanceIndex >= RISKY_AI_CRIT_STAGE_THRESHOLD // Not guaranteed but above Risky threshold && (gAiThinkingStruct->aiFlags[battlerAtk] & AI_FLAG_RISKY) - && GetGenConfig(GEN_CONFIG_CRIT_CHANCE) != GEN_1) + && GetConfig(CONFIG_CRIT_CHANCE) != GEN_1) return TRUE; if (critChanceIndex >= RISKY_AI_CRIT_THRESHOLD_GEN_1 // Not guaranteed but above Risky threshold && (gAiThinkingStruct->aiFlags[battlerAtk] & AI_FLAG_RISKY) - && GetGenConfig(GEN_CONFIG_CRIT_CHANCE) == GEN_1) + && GetConfig(CONFIG_CRIT_CHANCE) == GEN_1) return TRUE; return FALSE; } struct SimulatedDamage AI_CalcDamage(u32 move, u32 battlerAtk, u32 battlerDef, uq4_12_t *typeEffectiveness, enum AIConsiderGimmick considerGimmickAtk, enum AIConsiderGimmick considerGimmickDef, u32 weather) { - struct SimulatedDamage simDamage; + struct SimulatedDamage simDamage = {0}; enum BattleMoveEffects moveEffect = GetMoveEffect(move); bool32 isDamageMoveUnusable = FALSE; bool32 toggledGimmickAtk = FALSE; @@ -876,10 +908,6 @@ struct SimulatedDamage AI_CalcDamage(u32 move, u32 battlerAtk, u32 battlerDef, u if (gBattleStruct->gimmick.usableGimmick[battlerAtk] && GetActiveGimmick(battlerAtk) == GIMMICK_NONE && gBattleStruct->gimmick.usableGimmick[battlerAtk] != GIMMICK_NONE && considerGimmickAtk == USE_GIMMICK) { - // Set Z-Move variables if needed - if (gBattleStruct->gimmick.usableGimmick[battlerAtk] == GIMMICK_Z_MOVE && IsViableZMove(battlerAtk, move)) - gBattleStruct->zmove.baseMoves[battlerAtk] = move; - toggledGimmickAtk = TRUE; SetActiveGimmick(battlerAtk, gBattleStruct->gimmick.usableGimmick[battlerAtk]); } @@ -901,7 +929,7 @@ struct SimulatedDamage AI_CalcDamage(u32 move, u32 battlerAtk, u32 battlerDef, u struct DamageContext ctx = {0}; ctx.battlerAtk = battlerAtk; ctx.battlerDef = battlerDef; - ctx.move = move; + ctx.move = ctx.chosenMove = move; ctx.moveType = GetBattleMoveType(move); ctx.isCrit = ShouldCalcCritDamage(battlerAtk, battlerDef, move, aiData); ctx.randomFactor = FALSE; @@ -920,7 +948,7 @@ struct SimulatedDamage AI_CalcDamage(u32 move, u32 battlerAtk, u32 battlerDef, u if (movePower && !isDamageMoveUnusable) { - u32 types[3]; + enum Type types[3]; AI_StoreBattlerTypes(battlerAtk, types); ProteanTryChangeType(battlerAtk, aiData->abilities[battlerAtk], move, ctx.moveType); @@ -979,7 +1007,6 @@ struct SimulatedDamage AI_CalcDamage(u32 move, u32 battlerAtk, u32 battlerDef, u // Undo temporary settings gBattleStruct->dynamicMoveType = 0; gBattleStruct->swapDamageCategory = FALSE; - gBattleStruct->zmove.baseMoves[battlerAtk] = MOVE_NONE; if (toggledGimmickAtk) SetActiveGimmick(battlerAtk, GIMMICK_NONE); if (toggledGimmickDef) @@ -990,7 +1017,7 @@ struct SimulatedDamage AI_CalcDamage(u32 move, u32 battlerAtk, u32 battlerDef, u bool32 AI_IsDamagedByRecoil(u32 battler) { - u32 ability = gAiLogicData->abilities[battler]; + enum Ability ability = gAiLogicData->abilities[battler]; if (ability == ABILITY_MAGIC_GUARD || ability == ABILITY_ROCK_HEAD) return FALSE; return TRUE; @@ -1000,8 +1027,8 @@ bool32 AI_IsDamagedByRecoil(u32 battler) static bool32 AI_IsMoveEffectInPlus(u32 battlerAtk, u32 battlerDef, u32 move, s32 noOfHitsToKo) { u32 i; - u32 abilityDef = gAiLogicData->abilities[battlerDef]; - u32 abilityAtk = gAiLogicData->abilities[battlerAtk]; + enum Ability abilityDef = gAiLogicData->abilities[battlerDef]; + enum Ability abilityAtk = gAiLogicData->abilities[battlerAtk]; switch (GetMoveEffect(move)) { @@ -1178,8 +1205,8 @@ static bool32 AI_IsMoveEffectInPlus(u32 battlerAtk, u32 battlerDef, u32 move, s3 static bool32 AI_IsMoveEffectInMinus(u32 battlerAtk, u32 battlerDef, u32 move, s32 noOfHitsToKo) { - u32 abilityAtk = gAiLogicData->abilities[battlerAtk]; - u32 abilityDef = gAiLogicData->abilities[battlerDef]; + enum Ability abilityAtk = gAiLogicData->abilities[battlerAtk]; + enum Ability abilityDef = gAiLogicData->abilities[battlerDef]; u8 i; switch (GetMoveEffect(move)) @@ -1259,8 +1286,8 @@ static bool32 AI_IsMoveEffectInMinus(u32 battlerAtk, u32 battlerDef, u32 move, s enum MoveComparisonResult AI_WhichMoveBetter(u32 move1, u32 move2, u32 battlerAtk, u32 battlerDef, s32 noOfHitsToKo) { bool32 effect1, effect2; - u32 defAbility = gAiLogicData->abilities[battlerDef]; - u32 atkAbility = gAiLogicData->abilities[battlerAtk]; + enum Ability defAbility = gAiLogicData->abilities[battlerDef]; + enum Ability atkAbility = gAiLogicData->abilities[battlerAtk]; // Check if physical moves hurt. if (gAiLogicData->holdEffects[battlerAtk] != HOLD_EFFECT_PROTECTIVE_PADS && atkAbility != ABILITY_LONG_REACH @@ -1355,7 +1382,7 @@ uq4_12_t AI_GetMoveEffectiveness(u32 move, u32 battlerAtk, u32 battlerDef) struct DamageContext ctx = {0}; ctx.battlerAtk = battlerAtk; ctx.battlerDef = battlerDef; - ctx.move = move; + ctx.move = ctx.chosenMove = move; ctx.moveType = GetBattleMoveType(move); ctx.updateFlags = FALSE; ctx.abilityAtk = gAiLogicData->abilities[battlerAtk]; @@ -1379,10 +1406,10 @@ uq4_12_t AI_GetMoveEffectiveness(u32 move, u32 battlerAtk, u32 battlerDef) s32 AI_WhoStrikesFirst(u32 battlerAI, u32 battler, u32 aiMoveConsidered, u32 playerMoveConsidered, enum ConsiderPriority considerPriority) { u32 speedBattlerAI, speedBattler; - enum ItemHoldEffect holdEffectAI = gAiLogicData->holdEffects[battlerAI]; - enum ItemHoldEffect holdEffectPlayer = gAiLogicData->holdEffects[battler]; - u32 abilityAI = gAiLogicData->abilities[battlerAI]; - u32 abilityPlayer = gAiLogicData->abilities[battler]; + enum HoldEffect holdEffectAI = gAiLogicData->holdEffects[battlerAI]; + enum HoldEffect holdEffectPlayer = gAiLogicData->holdEffects[battler]; + enum Ability abilityAI = gAiLogicData->abilities[battlerAI]; + enum Ability abilityPlayer = gAiLogicData->abilities[battler]; if (considerPriority == CONSIDER_PRIORITY) { @@ -1395,8 +1422,8 @@ s32 AI_WhoStrikesFirst(u32 battlerAI, u32 battler, u32 aiMoveConsidered, u32 pla return AI_IS_SLOWER; } - speedBattlerAI = GetBattlerTotalSpeedStatArgs(battlerAI, abilityAI, holdEffectAI); - speedBattler = GetBattlerTotalSpeedStatArgs(battler, abilityPlayer, holdEffectPlayer); + speedBattlerAI = GetBattlerTotalSpeedStat(battlerAI, abilityAI, holdEffectAI); + speedBattler = GetBattlerTotalSpeedStat(battler, abilityPlayer, holdEffectPlayer); if (holdEffectAI == HOLD_EFFECT_LAGGING_TAIL && holdEffectPlayer != HOLD_EFFECT_LAGGING_TAIL) return AI_IS_SLOWER; @@ -1444,7 +1471,7 @@ bool32 CanEndureHit(u32 battler, u32 battlerTarget, u32 move) { if (B_STURDY >= GEN_5 && gAiLogicData->abilities[battlerTarget] == ABILITY_STURDY) return TRUE; - if (gBattleMons[battlerTarget].species == SPECIES_MIMIKYU_DISGUISED) + if (IsMimikyuDisguised(battlerTarget)) return TRUE; } @@ -1661,7 +1688,7 @@ bool32 CanTargetFaintAiWithMod(u32 battlerDef, u32 battlerAtk, s32 hpMod, s32 dm return FALSE; } -bool32 AI_IsAbilityOnSide(u32 battlerId, u32 ability) +bool32 AI_IsAbilityOnSide(u32 battlerId, enum Ability ability) { if (IsBattlerAlive(battlerId) && gAiLogicData->abilities[battlerId] == ability) return TRUE; @@ -1672,13 +1699,13 @@ bool32 AI_IsAbilityOnSide(u32 battlerId, u32 ability) } // does NOT include ability suppression checks -s32 AI_DecideKnownAbilityForTurn(u32 battlerId) +enum Ability AI_DecideKnownAbilityForTurn(u32 battlerId) { u32 validAbilities[NUM_ABILITY_SLOTS]; u8 i, numValidAbilities = 0; - u32 knownAbility = GetBattlerAbilityIgnoreMoldBreaker(battlerId); // during ai checking for mold breaker could lead to inaccuracies - u32 indexAbility; - u32 abilityAiRatings[NUM_ABILITY_SLOTS] = {0}; + enum Ability knownAbility = GetBattlerAbilityIgnoreMoldBreaker(battlerId); + enum Ability indexAbility; + enum Ability abilityAiRatings[NUM_ABILITY_SLOTS] = {0}; // We've had ability overwritten by e.g. Worry Seed. It is not part of gAiPartyData in case of switching if (gDisableStructs[battlerId].overwrittenAbility) @@ -1718,9 +1745,9 @@ s32 AI_DecideKnownAbilityForTurn(u32 battlerId) return ABILITY_NONE; // Unknown. } -enum ItemHoldEffect AI_DecideHoldEffectForTurn(u32 battlerId) +enum HoldEffect AI_DecideHoldEffectForTurn(u32 battlerId) { - enum ItemHoldEffect holdEffect = HOLD_EFFECT_NONE; + enum HoldEffect holdEffect = HOLD_EFFECT_NONE; if (gBattleMons[battlerId].item == ITEM_NONE) // Failsafe for when user recorded an item but it was consumed return holdEffect; @@ -1728,7 +1755,7 @@ enum ItemHoldEffect AI_DecideHoldEffectForTurn(u32 battlerId) if (!IsAiBattlerAware(battlerId)) holdEffect = gAiPartyData->mons[GetBattlerSide(battlerId)][gBattlerPartyIndexes[battlerId]].heldEffect; else - holdEffect = GetBattlerHoldEffect(battlerId, FALSE); + holdEffect = GetBattlerHoldEffectIgnoreNegation(battlerId); if (gAiThinkingStruct->aiFlags[battlerId] & AI_FLAG_NEGATE_UNAWARE) return holdEffect; @@ -1743,7 +1770,7 @@ enum ItemHoldEffect AI_DecideHoldEffectForTurn(u32 battlerId) return holdEffect; } -bool32 DoesBattlerIgnoreAbilityChecks(u32 battlerAtk, u32 atkAbility, u32 move) +bool32 DoesBattlerIgnoreAbilityChecks(u32 battlerAtk, enum Ability atkAbility, u32 move) { if (gAiThinkingStruct->aiFlags[battlerAtk] & AI_FLAG_NEGATE_UNAWARE) return FALSE; // AI handicap flag: doesn't understand ability suppression concept @@ -1777,7 +1804,7 @@ u32 AI_GetWeather(void) u32 AI_GetSwitchinWeather(struct BattlePokemon battleMon) { - u32 ability = battleMon.ability; + enum Ability ability = battleMon.ability; // Forced weather behaviour if (!AI_WeatherHasEffect()) return B_WEATHER_NONE; @@ -1796,7 +1823,7 @@ u32 AI_GetSwitchinWeather(struct BattlePokemon battleMon) case ABILITY_SAND_STREAM: return B_WEATHER_SANDSTORM; case ABILITY_SNOW_WARNING: - return B_SNOW_WARNING >= GEN_9 ? B_WEATHER_SNOW : B_WEATHER_HAIL; + return GetConfig(CONFIG_SNOW_WARNING) >= GEN_9 ? B_WEATHER_SNOW : B_WEATHER_HAIL; default: return gBattleWeather; } @@ -1897,7 +1924,7 @@ bool32 IsHazardClearingMove(u32 move) case EFFECT_TIDY_UP: return TRUE; case EFFECT_DEFOG: - if (B_DEFOG_EFFECT_CLEARING >= GEN_6) + if (GetConfig(CONFIG_DEFOG_EFFECT_CLEARING) >= GEN_6) return TRUE; break; } @@ -1963,7 +1990,7 @@ bool32 IsAllyProtectingFromMove(u32 battlerAtk, u32 attackerMove, u32 allyMove) } } -bool32 IsMoveRedirectionPrevented(u32 battlerAtk, u32 move, u32 atkAbility) +bool32 IsMoveRedirectionPrevented(u32 battlerAtk, u32 move, enum Ability atkAbility) { if (gAiThinkingStruct->aiFlags[battlerAtk] & AI_FLAG_NEGATE_UNAWARE) return FALSE; @@ -1977,9 +2004,9 @@ bool32 IsMoveRedirectionPrevented(u32 battlerAtk, u32 move, u32 atkAbility) return FALSE; } -bool32 ShouldTryOHKO(u32 battlerAtk, u32 battlerDef, u32 atkAbility, u32 defAbility, u32 move) +bool32 ShouldTryOHKO(u32 battlerAtk, u32 battlerDef, enum Ability atkAbility, enum Ability defAbility, u32 move) { - enum ItemHoldEffect holdEffect = gAiLogicData->holdEffects[battlerDef]; + enum HoldEffect holdEffect = gAiLogicData->holdEffects[battlerDef]; u32 accuracy = gAiLogicData->moveAccuracy[battlerAtk][battlerDef][gAiThinkingStruct->movesetIndex]; gPotentialItemEffectBattler = battlerDef; @@ -2009,8 +2036,44 @@ bool32 ShouldTryOHKO(u32 battlerAtk, u32 battlerDef, u32 atkAbility, u32 defAbil return FALSE; } +bool32 ShouldRaiseAnyStat(u32 battlerAtk, u32 battlerDef) +{ + if (AreBattlersStatsMaxed(battlerAtk)) + return FALSE; + + // Don't increase stats if opposing battler has Unaware + if (AI_IsAbilityOnSide(battlerDef, ABILITY_UNAWARE)) + return FALSE; + + // Don't set up if AI is dead to residual damage from weather + if (GetBattlerSecondaryDamage(battlerAtk) >= gBattleMons[battlerAtk].hp) + return FALSE; + + // Don't increase stats if opposing battler has Opportunist + if (AI_IsAbilityOnSide(battlerDef, ABILITY_OPPORTUNIST)) + return FALSE; + + // Don't increase stats if opposing battler has used Haze effect or AI effect + if (!RandomPercentage(RNG_AI_BOOST_INTO_HAZE, BOOST_INTO_HAZE_CHANCE) + && HasBattlerSideUsedMoveWithEffect(battlerDef, EFFECT_HAZE)) + return FALSE; + + if (CountPositiveStatStages(battlerAtk) > 0 + && HasBattlerSideMoveWithAIEffect(battlerDef, AI_EFFECT_RESET_STATS)) + return FALSE; + + // Don't increase stats if AI could KO target through Sturdy effect, as otherwise it always 2HKOs + if (CanBattlerKOTargetIgnoringSturdy(battlerAtk, battlerDef)) + return FALSE; + + return TRUE; +} + bool32 ShouldSetWeather(u32 battler, u32 weather) { + if (AI_GetWeather() & weather) + return FALSE; + return WeatherChecker(battler, weather, FIELD_EFFECT_POSITIVE); } @@ -2021,6 +2084,15 @@ bool32 ShouldClearWeather(u32 battler, u32 weather) bool32 ShouldSetFieldStatus(u32 battler, u32 fieldStatus) { + if (gFieldStatuses & fieldStatus) + { + if (!(fieldStatus & STATUS_FIELD_TRICK_ROOM)) + return FALSE; + // DOUBLE_TRICK_ROOM_ON_LAST_TURN_CHANCE + else if (gFieldTimers.trickRoomTimer != 1) + return FALSE; + } + return FieldStatusChecker(battler, fieldStatus, FIELD_EFFECT_POSITIVE); } @@ -2083,7 +2155,7 @@ s32 ProtectChecks(u32 battlerAtk, u32 battlerDef, u32 move, u32 predictedMove) } // stat stages -bool32 CanLowerStat(u32 battlerAtk, u32 battlerDef, struct AiLogicData *aiData, u32 stat) +bool32 CanLowerStat(u32 battlerAtk, u32 battlerDef, struct AiLogicData *aiData, enum Stat stat) { if (gBattleMons[battlerDef].statStages[stat] == MIN_STAT_STAGE) return FALSE; @@ -2092,7 +2164,7 @@ bool32 CanLowerStat(u32 battlerAtk, u32 battlerDef, struct AiLogicData *aiData, return FALSE; u32 move = gAiThinkingStruct->moveConsidered; - u32 abilityAtk = aiData->abilities[battlerAtk]; + enum Ability abilityAtk = aiData->abilities[battlerAtk]; if (gSideStatuses[GetBattlerSide(battlerDef)] & SIDE_STATUS_MIST && abilityAtk != ABILITY_INFILTRATOR) return FALSE; @@ -2114,7 +2186,7 @@ bool32 CanLowerStat(u32 battlerAtk, u32 battlerDef, struct AiLogicData *aiData, if (stat == STAT_DEF) return FALSE; case ABILITY_ILLUMINATE: - if (GetGenConfig(GEN_ILLUMINATE_EFFECT) < GEN_9) + if (GetConfig(CONFIG_ILLUMINATE_EFFECT) < GEN_9) break; case ABILITY_KEEN_EYE: case ABILITY_MINDS_EYE: @@ -2125,6 +2197,10 @@ bool32 CanLowerStat(u32 battlerAtk, u32 battlerDef, struct AiLogicData *aiData, case ABILITY_WHITE_SMOKE: case ABILITY_FULL_METAL_BODY: return FALSE; + case ABILITY_SHIELD_DUST: + if (!IsBattleMoveStatus(move) && GetActiveGimmick(battlerAtk) != GIMMICK_DYNAMAX) + return FALSE; + break; default: break; } @@ -2142,7 +2218,7 @@ bool32 CanLowerStat(u32 battlerAtk, u32 battlerDef, struct AiLogicData *aiData, return TRUE; } -u32 IncreaseStatDownScore(u32 battlerAtk, u32 battlerDef, u32 stat) +u32 IncreaseStatDownScore(u32 battlerAtk, u32 battlerDef, enum Stat stat) { u32 tempScore = NO_INCREASE; @@ -2154,10 +2230,6 @@ u32 IncreaseStatDownScore(u32 battlerAtk, u32 battlerDef, u32 stat) if (GetBattlerSecondaryDamage(battlerDef) >= gBattleMons[battlerDef].hp) return NO_INCREASE; - // Don't decrease stat if opposing battler has Encore - if (HasBattlerSideMoveWithEffect(battlerDef, EFFECT_ENCORE)) - return NO_INCREASE; - if (DoesAbilityRaiseStatsWhenLowered(gAiLogicData->abilities[battlerDef])) return NO_INCREASE; @@ -2172,13 +2244,15 @@ u32 IncreaseStatDownScore(u32 battlerAtk, u32 battlerDef, u32 stat) tempScore += DECENT_EFFECT; break; case STAT_DEF: - if (HasMoveWithCategory(battlerAtk, DAMAGE_CATEGORY_PHYSICAL)) + if (HasMoveWithCategory(battlerAtk, DAMAGE_CATEGORY_PHYSICAL) + || HasMoveWithCategory(BATTLE_PARTNER(battlerAtk), DAMAGE_CATEGORY_PHYSICAL)) tempScore += DECENT_EFFECT; break; case STAT_SPEED: { u32 predictedMoveSpeedCheck = GetIncomingMoveSpeedCheck(battlerAtk, battlerDef, gAiLogicData); - if (AI_IsSlower(battlerAtk, battlerDef, gAiThinkingStruct->moveConsidered, predictedMoveSpeedCheck, DONT_CONSIDER_PRIORITY)) + if (AI_IsSlower(battlerAtk, battlerDef, MOVE_NONE, predictedMoveSpeedCheck, DONT_CONSIDER_PRIORITY) + || AI_IsSlower(BATTLE_PARTNER(battlerAtk), battlerDef, MOVE_NONE, predictedMoveSpeedCheck, DONT_CONSIDER_PRIORITY)) tempScore += DECENT_EFFECT; break; } @@ -2187,16 +2261,16 @@ u32 IncreaseStatDownScore(u32 battlerAtk, u32 battlerDef, u32 stat) tempScore += DECENT_EFFECT; break; case STAT_SPDEF: - if (HasMoveWithCategory(battlerAtk, DAMAGE_CATEGORY_SPECIAL)) + if (HasMoveWithCategory(battlerAtk, DAMAGE_CATEGORY_SPECIAL) + || HasMoveWithCategory(BATTLE_PARTNER(battlerAtk), DAMAGE_CATEGORY_SPECIAL)) tempScore += DECENT_EFFECT; break; case STAT_ACC: - if (gBattleMons[battlerDef].status1 & STATUS1_PSN_ANY) - tempScore += WEAK_EFFECT; + tempScore += WEAK_EFFECT; + if (IsBattlerTrapped(battlerAtk, battlerDef)) + tempScore += DECENT_EFFECT; if (gBattleMons[battlerDef].volatiles.leechSeed) tempScore += WEAK_EFFECT; - if (gBattleMons[battlerDef].volatiles.root) - tempScore += WEAK_EFFECT; if (gBattleMons[battlerDef].volatiles.cursed) tempScore += WEAK_EFFECT; break; @@ -2210,12 +2284,14 @@ u32 IncreaseStatDownScore(u32 battlerAtk, u32 battlerDef, u32 stat) if (gBattleMons[battlerDef].volatiles.cursed) tempScore += WEAK_EFFECT; break; + default: + break; } return (tempScore > BEST_EFFECT) ? BEST_EFFECT : tempScore; // don't inflate score so only max +4 } -bool32 BattlerStatCanRise(u32 battler, u32 battlerAbility, u32 stat) +bool32 BattlerStatCanRise(u32 battler, enum Ability battlerAbility, enum Stat stat) { if ((gBattleMons[battler].statStages[stat] < MAX_STAT_STAGE && battlerAbility != ABILITY_CONTRARY) || (battlerAbility == ABILITY_CONTRARY && gBattleMons[battler].statStages[stat] > MIN_STAT_STAGE)) @@ -2225,7 +2301,7 @@ bool32 BattlerStatCanRise(u32 battler, u32 battlerAbility, u32 stat) bool32 AreBattlersStatsMaxed(u32 battlerId) { - u32 i; + enum Stat i; for (i = STAT_ATK; i < NUM_BATTLE_STATS; i++) { if (gBattleMons[battlerId].statStages[i] < MAX_STAT_STAGE) @@ -2236,7 +2312,7 @@ bool32 AreBattlersStatsMaxed(u32 battlerId) bool32 AnyStatIsRaised(u32 battlerId) { - u32 i; + enum Stat i; for (i = STAT_ATK; i < NUM_BATTLE_STATS; i++) { @@ -2249,7 +2325,7 @@ bool32 AnyStatIsRaised(u32 battlerId) u32 CountPositiveStatStages(u32 battlerId) { u32 count = 0; - u32 i; + enum Stat i; for (i = STAT_ATK; i < NUM_BATTLE_STATS; i++) { if (gBattleMons[battlerId].statStages[i] > DEFAULT_STAT_STAGE) @@ -2261,7 +2337,7 @@ u32 CountPositiveStatStages(u32 battlerId) u32 CountNegativeStatStages(u32 battlerId) { u32 count = 0; - u32 i; + enum Stat i; for (i = STAT_ATK; i < NUM_BATTLE_STATS; i++) { if (gBattleMons[battlerId].statStages[i] < DEFAULT_STAT_STAGE) @@ -2293,6 +2369,18 @@ u16 *GetMovesArray(u32 battler) return gBattleHistory->usedMoves[battler]; } +u32 GetIndexInMoveArray(u32 battler, u32 move) +{ + u16 *moves = GetMovesArray(battler); + u32 i; + for (i = 0; i < MAX_MON_MOVES; i++) + { + if (moves[i] == move) + return i; + } + return MAX_MON_MOVES; +} + bool32 HasOnlyMovesWithCategory(u32 battlerId, enum DamageCategory category, bool32 onlyOffensive) { u32 i; @@ -2322,7 +2410,7 @@ bool32 HasMoveWithCategory(u32 battler, enum DamageCategory category) return FALSE; } -bool32 HasMoveWithType(u32 battler, u32 type) +bool32 HasMoveWithType(u32 battler, enum Type type) { s32 i; u16 *moves = GetMovesArray(battler); @@ -2575,7 +2663,7 @@ bool32 HasMoveThatRaisesOwnStats(u32 battlerId) return FALSE; } -bool32 HasMoveWithLowAccuracy(u32 battlerAtk, u32 battlerDef, u32 accCheck, bool32 ignoreStatus, u32 atkAbility, u32 defAbility, u32 atkHoldEffect, u32 defHoldEffect) +bool32 HasMoveWithLowAccuracy(u32 battlerAtk, u32 battlerDef, u32 accCheck, bool32 ignoreStatus) { s32 i; u16 *moves = GetMovesArray(battlerAtk); @@ -2838,7 +2926,7 @@ bool32 IsSwitchOutEffect(enum BattleMoveEffects effect) switch (effect) { case EFFECT_TELEPORT: - if (GetGenConfig(GEN_CONFIG_TELEPORT_BEHAVIOR) >= GEN_8) + if (GetConfig(CONFIG_TELEPORT_BEHAVIOR) >= GEN_8) return TRUE; case EFFECT_HIT_ESCAPE: case EFFECT_PARTING_SHOT: @@ -2914,30 +3002,38 @@ static inline bool32 IsMoveSleepClauseTrigger(u32 move) return FALSE; } -bool32 HasDamagingMove(u32 battlerId) +bool32 HasDamagingMove(u32 battler) { u32 i; - u16 *moves = GetMovesArray(battlerId); + u16 *moves = GetMovesArray(battler); for (i = 0; i < MAX_MON_MOVES; i++) { - if (moves[i] != MOVE_NONE && moves[i] != MOVE_UNAVAILABLE && !IsBattleMoveStatus(moves[i])) + if (moves[i] != MOVE_NONE && moves[i] != MOVE_UNAVAILABLE && GetMovePower(moves[i]) > 0) return TRUE; } return FALSE; } -bool32 HasDamagingMoveOfType(u32 battlerId, u32 type) +bool32 HasDamagingMoveOfType(u32 battler, enum Type type) { s32 i; - u16 *moves = GetMovesArray(battlerId); + u16 *moves = GetMovesArray(battler); for (i = 0; i < MAX_MON_MOVES; i++) { - if (moves[i] != MOVE_NONE && moves[i] != MOVE_UNAVAILABLE - && GetMoveType(moves[i]) == type && !IsBattleMoveStatus(moves[i])) - return TRUE; + if (moves[i] != MOVE_NONE && moves[i] != MOVE_UNAVAILABLE && GetMovePower(moves[i]) > 0) + { + enum Type moveType = GetDynamicMoveType(GetBattlerMon(battler), moves[i], battler, MON_IN_BATTLE); + + if (moveType != TYPE_NONE && type == moveType) + return TRUE; + if (GetMoveType(moves[i]) == type) + return TRUE; + if (GetMoveEffect(moves[i]) == EFFECT_NATURE_POWER && GetMoveType(GetNaturePowerMove(moves[i])) == type) + return TRUE; + } } return FALSE; @@ -3009,17 +3105,16 @@ static u32 GetCurseDamage(u32 battlerId) return damage; } -static u32 GetTrapDamage(u32 battlerId) +static u32 GetTrapDamage(u32 battler) { // ai has no knowledge about turns remaining u32 damage = 0; - enum ItemHoldEffect holdEffect = gAiLogicData->holdEffects[gBattleStruct->wrappedBy[battlerId]]; - if (gBattleMons[battlerId].volatiles.wrapped) + if (gBattleMons[battler].volatiles.wrapped) { - if (holdEffect == HOLD_EFFECT_BINDING_BAND) - damage = GetNonDynamaxMaxHP(battlerId) / (B_BINDING_DAMAGE >= GEN_6 ? 6 : 8); + if (gAiLogicData->holdEffects[gBattleMons[battler].volatiles.wrappedBy] == HOLD_EFFECT_BINDING_BAND) + damage = GetNonDynamaxMaxHP(battler) / (B_BINDING_DAMAGE >= GEN_6 ? 6 : 8); else - damage = GetNonDynamaxMaxHP(battlerId) / (B_BINDING_DAMAGE >= GEN_6 ? 8 : 16); + damage = GetNonDynamaxMaxHP(battler) / (B_BINDING_DAMAGE >= GEN_6 ? 8 : 16); if (damage == 0) damage = 1; @@ -3053,7 +3148,7 @@ static u32 GetPoisonDamage(u32 battlerId) return damage; } -static bool32 BattlerAffectedBySandstorm(u32 battlerId, u32 ability) +static bool32 BattlerAffectedBySandstorm(u32 battlerId, enum Ability ability) { if (!IS_BATTLER_ANY_TYPE(battlerId, TYPE_ROCK, TYPE_GROUND, TYPE_STEEL) && ability != ABILITY_SAND_VEIL @@ -3064,7 +3159,7 @@ static bool32 BattlerAffectedBySandstorm(u32 battlerId, u32 ability) return FALSE; } -static bool32 BattlerAffectedByHail(u32 battlerId, u32 ability) +static bool32 BattlerAffectedByHail(u32 battlerId, enum Ability ability) { if (!IS_BATTLER_OF_TYPE(battlerId, TYPE_ICE) && ability != ABILITY_SNOW_CLOAK @@ -3076,8 +3171,8 @@ static bool32 BattlerAffectedByHail(u32 battlerId, u32 ability) static u32 GetWeatherDamage(u32 battlerId) { - u32 ability = gAiLogicData->abilities[battlerId]; - enum ItemHoldEffect holdEffect = gAiLogicData->holdEffects[battlerId]; + enum Ability ability = gAiLogicData->abilities[battlerId]; + enum HoldEffect holdEffect = gAiLogicData->holdEffects[battlerId]; u32 damage = 0; u32 weather = AI_GetWeather(); if (!weather) @@ -3127,7 +3222,7 @@ u32 GetBattlerSecondaryDamage(u32 battlerId) return secondaryDamage; } -bool32 BattlerWillFaintFromWeather(u32 battler, u32 ability) +bool32 BattlerWillFaintFromWeather(u32 battler, enum Ability ability) { if ((BattlerAffectedBySandstorm(battler, ability) || BattlerAffectedByHail(battler, ability)) && gBattleMons[battler].hp <= max(1, gBattleMons[battler].maxHP / 16)) @@ -3136,7 +3231,7 @@ bool32 BattlerWillFaintFromWeather(u32 battler, u32 ability) return FALSE; } -bool32 BattlerWillFaintFromSecondaryDamage(u32 battler, u32 ability) +bool32 BattlerWillFaintFromSecondaryDamage(u32 battler, enum Ability ability) { if (GetBattlerSecondaryDamage(battler) != 0 && gBattleMons[battler].hp <= max(1, gBattleMons[battler].maxHP / 16)) @@ -3146,7 +3241,7 @@ bool32 BattlerWillFaintFromSecondaryDamage(u32 battler, u32 ability) static bool32 AnyUsefulStatIsRaised(u32 battler) { - u32 statId; + enum Stat statId; for (statId = STAT_ATK; statId < NUM_BATTLE_STATS; statId++) { @@ -3164,6 +3259,8 @@ static bool32 AnyUsefulStatIsRaised(u32 battler) break; case STAT_SPEED: return TRUE; + default: + break; } } } @@ -3174,12 +3271,12 @@ static bool32 AnyUsefulStatIsRaised(u32 battler) static bool32 PartyBattlerShouldAvoidHazards(u32 currBattler, u32 switchBattler) { struct Pokemon *mon = &GetBattlerParty(currBattler)[switchBattler]; - u32 ability = GetMonAbility(mon); // we know our own party data - enum ItemHoldEffect holdEffect; + enum Ability ability = GetMonAbility(mon); // we know our own party data + enum HoldEffect holdEffect; u32 species = GetMonData(mon, MON_DATA_SPECIES); s32 hazardDamage = 0; - u32 type1 = GetSpeciesType(species, 0); - u32 type2 = GetSpeciesType(species, 1); + enum Type type1 = GetSpeciesType(species, 0); + enum Type type2 = GetSpeciesType(species, 1); u32 maxHp = GetMonData(mon, MON_DATA_MAX_HP); u32 side = GetBattlerSide(currBattler); @@ -3215,7 +3312,7 @@ static bool32 PartyBattlerShouldAvoidHazards(u32 currBattler, u32 switchBattler) return FALSE; } -enum AIPivot ShouldPivot(u32 battlerAtk, u32 battlerDef, u32 defAbility, u32 move, u32 moveIndex) +enum AIPivot ShouldPivot(u32 battlerAtk, u32 battlerDef, enum Ability defAbility, u32 move, u32 moveIndex) { bool32 hasStatBoost = AnyUsefulStatIsRaised(battlerAtk) || gBattleMons[battlerDef].statStages[STAT_EVASION] >= 9; //Significant boost in evasion for any class u32 battlerToSwitch; @@ -3417,7 +3514,7 @@ bool32 CanKnockOffItem(u32 battler, u32 item) } // status checks -bool32 IsBattlerIncapacitated(u32 battler, u32 ability) +bool32 IsBattlerIncapacitated(u32 battler, enum Ability ability) { if ((gBattleMons[battler].status1 & STATUS1_FREEZE) && !HasThawingMove(battler)) return TRUE; // if battler has thawing move we assume they will definitely use it, and thus being frozen should be neglected @@ -3431,7 +3528,7 @@ bool32 IsBattlerIncapacitated(u32 battler, u32 ability) return FALSE; } -bool32 AI_CanPutToSleep(u32 battlerAtk, u32 battlerDef, u32 defAbility, u32 move, u32 partnerMove) +bool32 AI_CanPutToSleep(u32 battlerAtk, u32 battlerDef, enum Ability defAbility, u32 move, u32 partnerMove) { if (!CanBeSlept(battlerAtk, battlerDef, defAbility, BLOCKED_BY_SLEEP_CLAUSE) || DoesSubstituteBlockMove(battlerAtk, battlerDef, move) @@ -3440,7 +3537,7 @@ bool32 AI_CanPutToSleep(u32 battlerAtk, u32 battlerDef, u32 defAbility, u32 move return TRUE; } -static inline bool32 DoesBattlerBenefitFromAllVolatileStatus(u32 battler, u32 ability) +static inline bool32 DoesBattlerBenefitFromAllVolatileStatus(u32 battler, enum Ability ability) { if (ability == ABILITY_MARVEL_SCALE || ability == ABILITY_QUICK_FEET @@ -3454,7 +3551,7 @@ static inline bool32 DoesBattlerBenefitFromAllVolatileStatus(u32 battler, u32 ab bool32 ShouldPoison(u32 battlerAtk, u32 battlerDef) { - u32 abilityDef = gAiLogicData->abilities[battlerDef]; + enum Ability abilityDef = gAiLogicData->abilities[battlerDef]; // Battler can be poisoned and has move/ability that synergizes with being poisoned if (CanBePoisoned(battlerAtk, battlerDef, gAiLogicData->abilities[battlerAtk], abilityDef) && ( DoesBattlerBenefitFromAllVolatileStatus(battlerDef, abilityDef) @@ -3472,7 +3569,7 @@ bool32 ShouldPoison(u32 battlerAtk, u32 battlerDef) return TRUE; } -bool32 ShouldBurn(u32 battlerAtk, u32 battlerDef, u32 abilityDef) +bool32 ShouldBurn(u32 battlerAtk, u32 battlerDef, enum Ability abilityDef) { // Battler can be burned and has move/ability that synergizes with being burned if (CanBeBurned(battlerAtk, battlerDef, abilityDef) && ( @@ -3492,7 +3589,7 @@ bool32 ShouldBurn(u32 battlerAtk, u32 battlerDef, u32 abilityDef) return TRUE; } -bool32 ShouldFreezeOrFrostbite(u32 battlerAtk, u32 battlerDef, u32 abilityDef) +bool32 ShouldFreezeOrFrostbite(u32 battlerAtk, u32 battlerDef, enum Ability abilityDef) { if (!B_USE_FROSTBITE) { @@ -3524,7 +3621,7 @@ bool32 ShouldFreezeOrFrostbite(u32 battlerAtk, u32 battlerDef, u32 abilityDef) } } -bool32 ShouldParalyze(u32 battlerAtk, u32 battlerDef, u32 abilityDef) +bool32 ShouldParalyze(u32 battlerAtk, u32 battlerDef, enum Ability abilityDef) { // Battler can be paralyzed and has move/ability that synergizes with being paralyzed if (CanBeParalyzed(battlerAtk, battlerDef, abilityDef) && ( @@ -3541,7 +3638,7 @@ bool32 ShouldParalyze(u32 battlerAtk, u32 battlerDef, u32 abilityDef) return TRUE; } -bool32 AI_CanPoison(u32 battlerAtk, u32 battlerDef, u32 defAbility, u32 move, u32 partnerMove) +bool32 AI_CanPoison(u32 battlerAtk, u32 battlerDef, enum Ability defAbility, u32 move, u32 partnerMove) { if (!CanBePoisoned(battlerAtk, battlerDef, gAiLogicData->abilities[battlerAtk], defAbility) || gAiLogicData->effectiveness[battlerAtk][battlerDef][gAiThinkingStruct->movesetIndex] == UQ_4_12(0.0) @@ -3552,7 +3649,7 @@ bool32 AI_CanPoison(u32 battlerAtk, u32 battlerDef, u32 defAbility, u32 move, u3 return TRUE; } -bool32 AI_CanParalyze(u32 battlerAtk, u32 battlerDef, u32 defAbility, u32 move, u32 partnerMove) +bool32 AI_CanParalyze(u32 battlerAtk, u32 battlerDef, enum Ability defAbility, u32 move, u32 partnerMove) { if (!CanBeParalyzed(battlerAtk, battlerDef, defAbility) || gAiLogicData->effectiveness[battlerAtk][battlerDef][gAiThinkingStruct->movesetIndex] == UQ_4_12(0.0) @@ -3562,18 +3659,18 @@ bool32 AI_CanParalyze(u32 battlerAtk, u32 battlerDef, u32 defAbility, u32 move, return TRUE; } -bool32 AI_CanBeConfused(u32 battlerAtk, u32 battlerDef, u32 move, u32 ability) +bool32 AI_CanBeConfused(u32 battlerAtk, u32 battlerDef, u32 move, enum Ability abilityDef) { if (gBattleMons[battlerDef].volatiles.confusionTurns > 0 - || (ability == ABILITY_OWN_TEMPO && !DoesBattlerIgnoreAbilityChecks(battlerAtk, gAiLogicData->abilities[battlerAtk], move)) - || IsBattlerTerrainAffected(battlerDef, STATUS_FIELD_MISTY_TERRAIN) + || (abilityDef == ABILITY_OWN_TEMPO && !DoesBattlerIgnoreAbilityChecks(battlerAtk, gAiLogicData->abilities[battlerAtk], move)) + || IsBattlerTerrainAffected(battlerDef, abilityDef, gAiLogicData->holdEffects[battlerDef], STATUS_FIELD_MISTY_TERRAIN) || gSideStatuses[GetBattlerSide(battlerDef)] & SIDE_STATUS_SAFEGUARD || DoesSubstituteBlockMove(battlerAtk, battlerDef, move)) return FALSE; return TRUE; } -bool32 AI_CanConfuse(u32 battlerAtk, u32 battlerDef, u32 defAbility, u32 battlerAtkPartner, u32 move, u32 partnerMove) +bool32 AI_CanConfuse(u32 battlerAtk, u32 battlerDef, enum Ability defAbility, u32 battlerAtkPartner, u32 move, u32 partnerMove) { if (GetBattlerMoveTargetType(battlerAtk, move) == MOVE_TARGET_FOES_AND_ALLY && AI_CanBeConfused(battlerAtk, battlerDef, move, defAbility) @@ -3587,7 +3684,7 @@ bool32 AI_CanConfuse(u32 battlerAtk, u32 battlerDef, u32 defAbility, u32 battler return TRUE; } -bool32 AI_CanBurn(u32 battlerAtk, u32 battlerDef, u32 defAbility, u32 battlerAtkPartner, u32 move, u32 partnerMove) +bool32 AI_CanBurn(u32 battlerAtk, u32 battlerDef, enum Ability defAbility, u32 battlerAtkPartner, u32 move, u32 partnerMove) { if (!CanBeBurned(battlerAtk, battlerDef, defAbility) || gAiLogicData->effectiveness[battlerAtk][battlerDef][gAiThinkingStruct->movesetIndex] == UQ_4_12(0.0) @@ -3599,7 +3696,7 @@ bool32 AI_CanBurn(u32 battlerAtk, u32 battlerDef, u32 defAbility, u32 battlerAtk return TRUE; } -bool32 AI_CanGiveFrostbite(u32 battlerAtk, u32 battlerDef, u32 defAbility, u32 battlerAtkPartner, u32 move, u32 partnerMove) +bool32 AI_CanGiveFrostbite(u32 battlerAtk, u32 battlerDef, enum Ability defAbility, u32 battlerAtkPartner, u32 move, u32 partnerMove) { if (!CanBeFrozen(battlerAtk, battlerDef, defAbility) || gAiLogicData->effectiveness[battlerAtk][battlerDef][gAiThinkingStruct->movesetIndex] == UQ_4_12(0.0) @@ -3611,7 +3708,7 @@ bool32 AI_CanGiveFrostbite(u32 battlerAtk, u32 battlerDef, u32 defAbility, u32 b return TRUE; } -bool32 AI_CanBeInfatuated(u32 battlerAtk, u32 battlerDef, u32 defAbility) +bool32 AI_CanBeInfatuated(u32 battlerAtk, u32 battlerDef, enum Ability defAbility) { if (gBattleMons[battlerDef].volatiles.infatuation || gAiLogicData->effectiveness[battlerAtk][battlerDef][gAiThinkingStruct->movesetIndex] == UQ_4_12(0.0) @@ -3622,7 +3719,7 @@ bool32 AI_CanBeInfatuated(u32 battlerAtk, u32 battlerDef, u32 defAbility) return TRUE; } -u32 ShouldTryToFlinch(u32 battlerAtk, u32 battlerDef, u32 atkAbility, u32 defAbility, u32 move) +u32 ShouldTryToFlinch(u32 battlerAtk, u32 battlerDef, enum Ability atkAbility, enum Ability defAbility, u32 move) { u32 predictedMoveSpeedCheck = GetIncomingMoveSpeedCheck(battlerAtk, battlerDef, gAiLogicData); if (((!IsMoldBreakerTypeAbility(battlerAtk, gAiLogicData->abilities[battlerAtk]) && (defAbility == ABILITY_SHIELD_DUST || defAbility == ABILITY_INNER_FOCUS)) @@ -3699,14 +3796,14 @@ bool32 IsFlinchGuaranteed(u32 battlerAtk, u32 battlerDef, u32 move) bool32 HasChoiceEffect(u32 battler) { - u32 ability = gAiLogicData->abilities[battler]; + enum Ability ability = gAiLogicData->abilities[battler]; if (ability == ABILITY_GORILLA_TACTICS) return TRUE; if (ability == ABILITY_KLUTZ) return FALSE; - enum ItemHoldEffect holdEffect = gAiLogicData->holdEffects[battler]; + enum HoldEffect holdEffect = gAiLogicData->holdEffects[battler]; switch (holdEffect) { case HOLD_EFFECT_CHOICE_BAND: @@ -3742,6 +3839,7 @@ bool32 AnyPartyMemberStatused(u32 battlerId, bool32 checkSoundproof) { struct Pokemon *party; u32 i, battlerOnField1, battlerOnField2; + bool32 hasStatusToCure = FALSE; party = GetBattlerParty(battlerId); @@ -3750,11 +3848,12 @@ bool32 AnyPartyMemberStatused(u32 battlerId, bool32 checkSoundproof) battlerOnField1 = gBattlerPartyIndexes[battlerId]; battlerOnField2 = gBattlerPartyIndexes[GetPartnerBattler(battlerId)]; // Check partner's status - if ((GetGenConfig(GEN_CONFIG_HEAL_BELL_SOUNDPROOF) == GEN_5 + if ((GetConfig(CONFIG_HEAL_BELL_SOUNDPROOF) == GEN_5 || gAiLogicData->abilities[BATTLE_PARTNER(battlerId)] != ABILITY_SOUNDPROOF || !checkSoundproof) - && GetMonData(&party[battlerOnField2], MON_DATA_STATUS) != STATUS1_NONE) - return TRUE; + && GetMonData(&party[battlerOnField2], MON_DATA_STATUS) != STATUS1_NONE + && ShouldCureStatus(battlerId, BATTLE_PARTNER(battlerId), gAiLogicData)) + hasStatusToCure = TRUE; } else // In singles there's only one battlerId by side. { @@ -3763,18 +3862,19 @@ bool32 AnyPartyMemberStatused(u32 battlerId, bool32 checkSoundproof) } // Check attacker's status - if ((GetGenConfig(GEN_CONFIG_HEAL_BELL_SOUNDPROOF) == GEN_5 - || GetGenConfig(GEN_CONFIG_HEAL_BELL_SOUNDPROOF) >= GEN_8 + if ((GetConfig(CONFIG_HEAL_BELL_SOUNDPROOF) == GEN_5 + || GetConfig(CONFIG_HEAL_BELL_SOUNDPROOF) >= GEN_8 || gAiLogicData->abilities[battlerId] != ABILITY_SOUNDPROOF || !checkSoundproof) - && GetMonData(&party[battlerOnField1], MON_DATA_STATUS) != STATUS1_NONE) - return TRUE; + && GetMonData(&party[battlerOnField1], MON_DATA_STATUS) != STATUS1_NONE + && ShouldCureStatus(battlerId, battlerId, gAiLogicData)) + hasStatusToCure = TRUE; // Check inactive party mons' status for (i = 0; i < PARTY_SIZE; i++) { if (i == battlerOnField1 || i == battlerOnField2) continue; - if (GetGenConfig(GEN_CONFIG_HEAL_BELL_SOUNDPROOF) < GEN_5 + if (GetConfig(CONFIG_HEAL_BELL_SOUNDPROOF) < GEN_5 && checkSoundproof && GetMonAbility(&party[i]) == ABILITY_SOUNDPROOF) continue; @@ -3782,7 +3882,7 @@ bool32 AnyPartyMemberStatused(u32 battlerId, bool32 checkSoundproof) return TRUE; } - return FALSE; + return hasStatusToCure; } bool32 ShouldUseRecoilMove(u32 battlerAtk, u32 battlerDef, u32 recoilDmg, u32 moveIndex) @@ -3890,8 +3990,104 @@ bool32 ShouldSetScreen(u32 battlerAtk, u32 battlerDef, enum BattleMoveEffects mo return FALSE; } +static bool32 ShouldCureStatusInternal(u32 battlerAtk, u32 battlerDef, bool32 usingItem, struct AiLogicData *aiData) +{ + bool32 targetingSelf = (battlerAtk == battlerDef); + bool32 targetingAlly = IsTargetingPartner(battlerAtk, battlerDef); + u32 status = gBattleMons[battlerDef].status1; + + if (status & STATUS1_SLEEP) + { + if (targetingAlly || targetingSelf) + { + if (HasMoveWithEffect(battlerDef, EFFECT_SLEEP_TALK) || HasMoveWithEffect(battlerDef, EFFECT_SNORE)) + return FALSE; + else + return usingItem || targetingAlly; + } + return FALSE; + } + + if (status & STATUS1_FREEZE) + { + if (targetingAlly || targetingSelf) + { + if (HasThawingMove(battlerDef)) + return FALSE; + return usingItem || targetingAlly; + } + return FALSE; + } + + bool32 isHarmless = FALSE; + + if (DoesBattlerBenefitFromAllVolatileStatus(battlerDef, aiData->abilities[battlerDef])) + isHarmless = TRUE; + + if (status & STATUS1_PSN_ANY) + { + if (aiData->holdEffects[battlerDef] == HOLD_EFFECT_TOXIC_ORB) + return FALSE; + + if (aiData->abilities[battlerDef] == ABILITY_POISON_HEAL) + isHarmless = TRUE; + + if (aiData->abilities[battlerDef] == ABILITY_TOXIC_BOOST && !isHarmless) + { + if (HasMoveWithCategory(battlerDef, DAMAGE_CATEGORY_PHYSICAL)) + isHarmless = TRUE; + else if (!(targetingSelf || targetingAlly) && !HasMoveWithCategory(battlerDef, DAMAGE_CATEGORY_SPECIAL)) + isHarmless = TRUE; + } + } + + if (status & STATUS1_BURN) + { + if (aiData->holdEffects[battlerDef] == HOLD_EFFECT_FLAME_ORB) + return FALSE; + + if (aiData->abilities[battlerDef] == ABILITY_FLARE_BOOST && !isHarmless) + { + if (HasMoveWithCategory(battlerDef, DAMAGE_CATEGORY_SPECIAL)) + isHarmless = TRUE; + else if (!(targetingSelf || targetingAlly) && !HasMoveWithCategory(battlerDef, DAMAGE_CATEGORY_PHYSICAL)) + isHarmless = TRUE; + } + } + +/* + if (status & STATUS1_PARALYSIS) + if (status & STATUS1_FROSTBITE) +*/ + + if (isHarmless) + { + if (targetingSelf || targetingAlly) + return FALSE; + else + return TRUE; + } + else + { + if (targetingSelf || targetingAlly) + return TRUE; + else + return FALSE; + } +} + +bool32 ShouldCureStatus(u32 battlerAtk, u32 battlerDef, struct AiLogicData *aiData) +{ + return ShouldCureStatusInternal(battlerAtk, battlerDef, FALSE, aiData); +} + +bool32 ShouldCureStatusWithItem(u32 battlerAtk, u32 battlerDef, struct AiLogicData *aiData) +{ + return ShouldCureStatusInternal(battlerAtk, battlerDef, TRUE, aiData); +} + // Partner Logic -bool32 IsBattle1v1() +bool32 IsBattle1v1(void) { if (IsDoubleBattle() && ((IsBattlerAlive(B_POSITION_PLAYER_LEFT) && IsBattlerAlive(B_POSITION_PLAYER_RIGHT)) @@ -3903,7 +4099,7 @@ bool32 IsBattle1v1() bool32 HasTwoOpponents(u32 battler) { if (IsDoubleBattle() - && IsBattlerAlive(FOE(battler)) && IsBattlerAlive(BATTLE_PARTNER(FOE(battler)))) + && IsBattlerAlive(LEFT_FOE(battler)) && IsBattlerAlive(RIGHT_FOE(battler))) return TRUE; return FALSE; } @@ -3943,9 +4139,9 @@ u32 GetAllyChosenMove(u32 battlerId) if (!IsBattlerAlive(partnerBattler) || !IsAiBattlerAware(partnerBattler)) return MOVE_NONE; else if (partnerBattler > battlerId) // Battler with the lower id chooses the move first. - return gLastMoves[partnerBattler]; + return gAiLogicData->lastUsedMove[partnerBattler]; else - return gBattleMons[partnerBattler].moves[gBattleStruct->chosenMovePositions[partnerBattler]]; + return GetChosenMoveFromPosition(partnerBattler); } bool32 AreMovesEquivalent(u32 battlerAtk, u32 battlerAtkPartner, u32 move, u32 partnerMove) @@ -4039,9 +4235,8 @@ static u32 GetAIEffectGroup(enum BattleMoveEffects effect) case EFFECT_ENTRAINMENT: case EFFECT_GASTRO_ACID: case EFFECT_ROLE_PLAY: - case EFFECT_SIMPLE_BEAM: case EFFECT_SKILL_SWAP: - case EFFECT_WORRY_SEED: + case EFFECT_OVERWRITE_ABILITY: aiEffect |= AI_EFFECT_CHANGE_ABILITY; break; default: @@ -4270,11 +4465,32 @@ void FreeRestoreBattleMons(struct BattlePokemon *savedBattleMons) Free(savedBattleMons); } +// Set potential field effect from ability for switch in +static void SetBattlerFieldStatusForSwitchin(u32 battler) +{ + switch (gAiLogicData->abilities[battler]) + { + case ABILITY_VESSEL_OF_RUIN: + gBattleMons[battler].volatiles.vesselOfRuin = TRUE; + break; + case ABILITY_SWORD_OF_RUIN: + gBattleMons[battler].volatiles.swordOfRuin = TRUE; + break; + case ABILITY_TABLETS_OF_RUIN: + gBattleMons[battler].volatiles.tabletsOfRuin = TRUE; + break; + case ABILITY_BEADS_OF_RUIN: + gBattleMons[battler].volatiles.beadsOfRuin = TRUE; + break; + default: + break; + } +} + // party logic -s32 AI_CalcPartyMonDamage(u32 move, u32 battlerAtk, u32 battlerDef, struct BattlePokemon switchinCandidate, enum DamageCalcContext calcContext) +s32 AI_CalcPartyMonDamage(u32 move, u32 battlerAtk, u32 battlerDef, struct BattlePokemon switchinCandidate, uq4_12_t *effectiveness, enum DamageCalcContext calcContext) { struct SimulatedDamage dmg; - uq4_12_t effectiveness; struct BattlePokemon *savedBattleMons = AllocSaveBattleMons(); if (calcContext == AI_ATTACKING) @@ -4282,6 +4498,7 @@ s32 AI_CalcPartyMonDamage(u32 move, u32 battlerAtk, u32 battlerDef, struct Battl gBattleMons[battlerAtk] = switchinCandidate; gAiThinkingStruct->saved[battlerDef].saved = TRUE; SetBattlerAiData(battlerAtk, gAiLogicData); // set known opposing battler data + SetBattlerFieldStatusForSwitchin(battlerAtk); gAiThinkingStruct->saved[battlerDef].saved = FALSE; } else if (calcContext == AI_DEFENDING) @@ -4289,10 +4506,11 @@ s32 AI_CalcPartyMonDamage(u32 move, u32 battlerAtk, u32 battlerDef, struct Battl gBattleMons[battlerDef] = switchinCandidate; gAiThinkingStruct->saved[battlerAtk].saved = TRUE; SetBattlerAiData(battlerDef, gAiLogicData); // set known opposing battler data + SetBattlerFieldStatusForSwitchin(battlerDef); gAiThinkingStruct->saved[battlerAtk].saved = FALSE; } - dmg = AI_CalcDamage(move, battlerAtk, battlerDef, &effectiveness, NO_GIMMICK, NO_GIMMICK, AI_GetSwitchinWeather(switchinCandidate)); + dmg = AI_CalcDamage(move, battlerAtk, battlerDef, effectiveness, NO_GIMMICK, NO_GIMMICK, AI_GetSwitchinWeather(switchinCandidate)); // restores original gBattleMon struct FreeRestoreBattleMons(savedBattleMons); @@ -4352,7 +4570,9 @@ s32 CountUsablePartyMons(u32 battlerId) } ret = 0; - for (i = 0; i < PARTY_SIZE; i++) + s32 firstId, lastId; + GetAIPartyIndexes(battlerId, &firstId, &lastId); + for (i = firstId; i < lastId; i++) { if (i != battlerOnField1 && i != battlerOnField2 && GetMonData(&party[i], MON_DATA_HP) != 0 @@ -4426,7 +4646,7 @@ bool32 SideHasMoveCategory(u32 battlerId, enum DamageCategory category) return FALSE; } -bool32 IsAbilityOfRating(u32 ability, s8 rating) +bool32 IsAbilityOfRating(enum Ability ability, s8 rating) { if (gAbilitiesInfo[ability].aiRating >= rating) return TRUE; @@ -4533,7 +4753,7 @@ static bool32 HasMoveThatChangesKOThreshold(u32 battlerId, u32 noOfHitsToFaint, case MOVE_EFFECT_SPD_MINUS_1: case MOVE_EFFECT_SPD_MINUS_2: { - if(aiIsFaster) + if (aiIsFaster && !additionalEffect->self) return TRUE; } default: @@ -4546,24 +4766,29 @@ static bool32 HasMoveThatChangesKOThreshold(u32 battlerId, u32 noOfHitsToFaint, return FALSE; } -static u32 GetStatBeingChanged(enum StatChange statChange) +static enum Stat GetStatBeingChanged(enum StatChange statChange) { switch(statChange) { case STAT_CHANGE_ATK: case STAT_CHANGE_ATK_2: + case STAT_CHANGE_ATK_3: return STAT_ATK; case STAT_CHANGE_DEF: case STAT_CHANGE_DEF_2: + case STAT_CHANGE_DEF_3: return STAT_DEF; case STAT_CHANGE_SPEED: case STAT_CHANGE_SPEED_2: + case STAT_CHANGE_SPEED_3: return STAT_SPEED; case STAT_CHANGE_SPATK: case STAT_CHANGE_SPATK_2: + case STAT_CHANGE_SPATK_3: return STAT_SPATK; case STAT_CHANGE_SPDEF: case STAT_CHANGE_SPDEF_2: + case STAT_CHANGE_SPDEF_3: return STAT_SPDEF; case STAT_CHANGE_ACC: return STAT_ACC; @@ -4573,6 +4798,34 @@ static u32 GetStatBeingChanged(enum StatChange statChange) return 0; // STAT_HP, should never be getting changed } +static u32 GetStagesOfStatChange(enum StatChange statChange) +{ + switch(statChange) + { + case STAT_CHANGE_ATK: + case STAT_CHANGE_DEF: + case STAT_CHANGE_SPEED: + case STAT_CHANGE_SPATK: + case STAT_CHANGE_SPDEF: + case STAT_CHANGE_ACC: + case STAT_CHANGE_EVASION: + return 1; + case STAT_CHANGE_ATK_2: + case STAT_CHANGE_DEF_2: + case STAT_CHANGE_SPEED_2: + case STAT_CHANGE_SPATK_2: + case STAT_CHANGE_SPDEF_2: + return 2; + case STAT_CHANGE_ATK_3: + case STAT_CHANGE_DEF_3: + case STAT_CHANGE_SPEED_3: + case STAT_CHANGE_SPATK_3: + case STAT_CHANGE_SPDEF_3: + return 3; + } + return 0; // STAT_HP, should never be getting changed +} + static enum AIScore IncreaseStatUpScoreInternal(u32 battlerAtk, u32 battlerDef, enum StatChange statChange, bool32 considerContrary) { enum AIScore tempScore = NO_INCREASE; @@ -4581,13 +4834,13 @@ static enum AIScore IncreaseStatUpScoreInternal(u32 battlerAtk, u32 battlerDef, u32 aiIsFaster = AI_IsFaster(battlerAtk, battlerDef, MOVE_NONE, predictedMoveSpeedCheck, DONT_CONSIDER_PRIORITY); // Don't care about the priority of our setup move, care about outspeeding otherwise u32 shouldSetUp = ((noOfHitsToFaint >= 2 && aiIsFaster) || (noOfHitsToFaint >= 3 && !aiIsFaster) || noOfHitsToFaint == UNKNOWN_NO_OF_HITS); u32 i; - u32 statId = GetStatBeingChanged(statChange); + enum Stat statId = GetStatBeingChanged(statChange); + u32 stages = GetStagesOfStatChange(statChange); if (considerContrary && gAiLogicData->abilities[battlerAtk] == ABILITY_CONTRARY) return NO_INCREASE; - // Don't increase stats if opposing battler has Unaware - if (HasBattlerSideAbility(battlerDef, ABILITY_UNAWARE, gAiLogicData)) + if (!ShouldRaiseAnyStat(battlerAtk, battlerDef)) return NO_INCREASE; // Don't increase stat if AI is at +4 @@ -4598,36 +4851,14 @@ static enum AIScore IncreaseStatUpScoreInternal(u32 battlerAtk, u32 battlerDef, if (gAiLogicData->hpPercents[battlerAtk] < 70 && noOfHitsToFaint == UNKNOWN_NO_OF_HITS) return NO_INCREASE; - // Don't set up if AI is dead to residual damage from weather - if (GetBattlerSecondaryDamage(battlerAtk) >= gBattleMons[battlerAtk].hp) - return NO_INCREASE; - - // Don't increase stats if opposing battler has Opportunist - if (gAiLogicData->abilities[battlerDef] == ABILITY_OPPORTUNIST) - return NO_INCREASE; - - // Don't increase stats if opposing battler has Encore - if (HasBattlerSideMoveWithEffect(battlerDef, EFFECT_ENCORE)) - return NO_INCREASE; - - // Don't increase stats if opposing battler has used Haze effect or AI effect - if (!RandomPercentage(RNG_AI_BOOST_INTO_HAZE, BOOST_INTO_HAZE_CHANCE) - && HasBattlerSideUsedMoveWithEffect(battlerDef, EFFECT_HAZE)) - return NO_INCREASE; - - // Don't increase if AI is at +1 and opponent has Haze effect - if (gBattleMons[battlerAtk].statStages[statId] >= MAX_STAT_STAGE - 5 - && HasBattlerSideMoveWithAIEffect(battlerDef, AI_EFFECT_RESET_STATS)) - return NO_INCREASE; - - // Don't increase stats if AI could KO target through Sturdy effect, as otherwise it always 2HKOs - if (CanBattlerKOTargetIgnoringSturdy(battlerAtk, battlerDef)) - return NO_INCREASE; - // Don't increase stats if player has a move that can change the KO threshold if (HasMoveThatChangesKOThreshold(battlerDef, noOfHitsToFaint, aiIsFaster)) return NO_INCREASE; + // Stat stages are effectively doubled under Simple. + if (gAiLogicData->abilities[battlerAtk] == ABILITY_SIMPLE) + stages *= 2; + // Predicting switch if (IsBattlerPredictedToSwitch(battlerDef)) { @@ -4646,80 +4877,75 @@ static enum AIScore IncreaseStatUpScoreInternal(u32 battlerAtk, u32 battlerDef, tempScore += WEAK_EFFECT; } - switch (statChange) + switch (statId) { - case STAT_CHANGE_ATK: + case STAT_ATK: if (HasMoveWithCategory(battlerAtk, DAMAGE_CATEGORY_PHYSICAL) && shouldSetUp) - tempScore += DECENT_EFFECT; + { + if (stages == 1) + tempScore += DECENT_EFFECT; + else + tempScore += GOOD_EFFECT; + } break; - case STAT_CHANGE_DEF: + case STAT_DEF: if (HasMoveWithCategory(battlerDef, DAMAGE_CATEGORY_PHYSICAL) || !HasMoveWithCategory(battlerDef, DAMAGE_CATEGORY_SPECIAL)) { if (gAiThinkingStruct->aiFlags[battlerAtk] & AI_FLAG_STALL) - tempScore += DECENT_EFFECT; - else tempScore += WEAK_EFFECT; + if (stages == 1) + tempScore += WEAK_EFFECT; + else + tempScore += DECENT_EFFECT; } break; - case STAT_CHANGE_SPEED: + case STAT_SPEED: if ((noOfHitsToFaint >= 3 && !aiIsFaster) || noOfHitsToFaint == UNKNOWN_NO_OF_HITS) - tempScore += DECENT_EFFECT; + { + if (stages == 1) + tempScore += DECENT_EFFECT; + else + tempScore += GOOD_EFFECT; + } break; - case STAT_CHANGE_SPATK: + case STAT_SPATK: if (HasMoveWithCategory(battlerAtk, DAMAGE_CATEGORY_SPECIAL) && shouldSetUp) - tempScore += DECENT_EFFECT; + { + if (stages == 1) + tempScore += DECENT_EFFECT; + else + tempScore += GOOD_EFFECT; + } break; - case STAT_CHANGE_SPDEF: + case STAT_SPDEF: if (HasMoveWithCategory(battlerDef, DAMAGE_CATEGORY_SPECIAL) || !HasMoveWithCategory(battlerDef, DAMAGE_CATEGORY_PHYSICAL)) { if (gAiThinkingStruct->aiFlags[battlerAtk] & AI_FLAG_STALL) - tempScore += DECENT_EFFECT; - else tempScore += WEAK_EFFECT; - } - break; - case STAT_CHANGE_ATK_2: - if (HasMoveWithCategory(battlerAtk, DAMAGE_CATEGORY_PHYSICAL) && shouldSetUp) - tempScore += GOOD_EFFECT; - break; - case STAT_CHANGE_DEF_2: - if (HasMoveWithCategory(battlerDef, DAMAGE_CATEGORY_PHYSICAL) || !HasMoveWithCategory(battlerDef, DAMAGE_CATEGORY_SPECIAL)) - { - if (gAiThinkingStruct->aiFlags[battlerAtk] & AI_FLAG_STALL) - tempScore += GOOD_EFFECT; + if (stages == 1) + tempScore += WEAK_EFFECT; else tempScore += DECENT_EFFECT; } break; - case STAT_CHANGE_SPEED_2: - if ((noOfHitsToFaint >= 3 && !aiIsFaster) || noOfHitsToFaint == UNKNOWN_NO_OF_HITS) - tempScore += GOOD_EFFECT; - break; - case STAT_CHANGE_SPATK_2: - if (HasMoveWithCategory(battlerAtk, DAMAGE_CATEGORY_SPECIAL) && shouldSetUp) - tempScore += GOOD_EFFECT; - break; - case STAT_CHANGE_SPDEF_2: - if (HasMoveWithCategory(battlerDef, DAMAGE_CATEGORY_SPECIAL) || !HasMoveWithCategory(battlerDef, DAMAGE_CATEGORY_PHYSICAL)) - { - if (gAiThinkingStruct->aiFlags[battlerAtk] & AI_FLAG_STALL) - tempScore += GOOD_EFFECT; - else - tempScore += DECENT_EFFECT; - } - break; - case STAT_CHANGE_ACC: + case STAT_ACC: if (gBattleMons[battlerAtk].statStages[statId] <= 3) // Increase only if necessary tempScore += DECENT_EFFECT; break; - case STAT_CHANGE_EVASION: + case STAT_EVASION: if (noOfHitsToFaint > 3 || noOfHitsToFaint == UNKNOWN_NO_OF_HITS) tempScore += GOOD_EFFECT; else tempScore += DECENT_EFFECT; break; + default: + break; } + // if already inclined to boost, be slightly more likely to if boost levels matter + if (tempScore > 0 && HasMoveWithEffect(battlerAtk, EFFECT_STORED_POWER)) + tempScore += WEAK_EFFECT; + return tempScore; } @@ -4864,7 +5090,7 @@ void IncreaseFrostbiteScore(u32 battlerAtk, u32 battlerDef, u32 move, s32 *score } } -bool32 AI_MoveMakesContact(u32 ability, enum ItemHoldEffect holdEffect, u32 move) +bool32 AI_MoveMakesContact(enum Ability ability, enum HoldEffect holdEffect, u32 move) { if (MoveMakesContact(move) && ability != ABILITY_LONG_REACH @@ -4873,35 +5099,160 @@ bool32 AI_MoveMakesContact(u32 ability, enum ItemHoldEffect holdEffect, u32 move return FALSE; } + +bool32 IsConsideringZMove(u32 battlerAtk, u32 battlerDef, u32 move) +{ + if (GetMovePower(move) == 0 && GetMoveZEffect(move) == Z_EFFECT_NONE) + return FALSE; + + return gBattleStruct->gimmick.usableGimmick[battlerAtk] == GIMMICK_Z_MOVE && ShouldUseZMove(battlerAtk, battlerDef, move); +} + //TODO - this could use some more sophisticated logic 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 ((IsDoubleBattle()) && battlerDef == BATTLE_PARTNER(battlerAtk)) + if ((IsDoubleBattle()) && battlerDef == BATTLE_PARTNER(battlerAtk) && !(GetBattlerMoveTargetType(battlerAtk, chosenMove) & MOVE_TARGET_ALLY)) return FALSE; // don't use z move on partner if (HasTrainerUsedGimmick(battlerAtk, GIMMICK_Z_MOVE)) return FALSE; // can't use z move twice if (IsViableZMove(battlerAtk, chosenMove)) { - uq4_12_t effectiveness; + enum BattleMoveEffects baseEffect = GetMoveEffect(chosenMove); + bool32 isEager = FALSE; // more likely to use a z move than typical + + u32 predictedMoveSpeedCheck = GetIncomingMoveSpeedCheck(battlerAtk, battlerDef, gAiLogicData); + bool32 isSlower = AI_IsSlower(battlerAtk, battlerDef, chosenMove, predictedMoveSpeedCheck, CONSIDER_PRIORITY); + + switch (baseEffect) + { + case EFFECT_BELLY_DRUM: + case EFFECT_FILLET_AWAY: + if (isSlower) + return TRUE; + isEager = TRUE; + break; + case EFFECT_PROTECT: + if (HasDamagingMoveOfType(battlerAtk, GetMoveType(gMovesInfo[chosenMove].type))) + return FALSE; + else + isEager = TRUE; + break; + case EFFECT_TELEPORT: + isEager = TRUE; + break; + case EFFECT_TRANSFORM: + if (IsBattlerTrapped(battlerDef, battlerAtk) && !HasDamagingMoveOfType(battlerDef, GetMoveType(gMovesInfo[chosenMove].type))) + return TRUE; + if (isSlower) + isEager = TRUE; + break; + default: + break; + } + u32 zMove = GetUsableZMove(battlerAtk, chosenMove); + + if (IsBattleMoveStatus(chosenMove)) + { + u8 zEffect = GetMoveZEffect(chosenMove); + enum StatChange statChange = 0; + + if (zEffect == Z_EFFECT_CURSE) + { + if (IS_BATTLER_OF_TYPE(battlerAtk, TYPE_GHOST)) + zEffect = Z_EFFECT_RECOVER_HP; + else + zEffect = Z_EFFECT_ATK_UP_1; + } + + switch (zEffect) + { + case Z_EFFECT_NONE: + if (GetMovePower(chosenMove) == 0) + return FALSE; + break; + case Z_EFFECT_RESET_STATS: + if (CountNegativeStatStages(battlerAtk) > 1) + return TRUE; + break; + case Z_EFFECT_ALL_STATS_UP_1: + return ShouldRaiseAnyStat(battlerAtk, battlerDef); + case Z_EFFECT_BOOST_CRITS: + return TRUE; + case Z_EFFECT_FOLLOW_ME: + return HasPartnerIgnoreFlags(battlerAtk) && (GetHealthPercentage(battlerAtk) <= Z_EFFECT_FOLLOW_ME_THRESHOLD || GetBestNoOfHitsToKO(battlerDef, battlerAtk, AI_DEFENDING) == 1); + break; + case Z_EFFECT_RECOVER_HP: + if (GetBestNoOfHitsToKO(battlerDef, battlerAtk, AI_DEFENDING) == 1 && GetHealthPercentage(battlerAtk) > Z_EFFECT_RESTORE_HP_HIGHER_THRESHOLD) + return TRUE; + if (isEager) + return GetHealthPercentage(battlerAtk) <= Z_EFFECT_RESTORE_HP_HIGHER_THRESHOLD; + return GetHealthPercentage(battlerAtk) <= Z_EFFECT_RESTORE_HP_LOWER_THRESHOLD; + case Z_EFFECT_RESTORE_REPLACEMENT_HP: + break; + case Z_EFFECT_ACC_UP_1: + case Z_EFFECT_ACC_UP_2: + case Z_EFFECT_ACC_UP_3: + statChange = STAT_CHANGE_ACC; + break; + case Z_EFFECT_EVSN_UP_1: + case Z_EFFECT_EVSN_UP_2: + case Z_EFFECT_EVSN_UP_3: + statChange = STAT_CHANGE_EVASION; + break; + case Z_EFFECT_ATK_UP_1: + case Z_EFFECT_DEF_UP_1: + case Z_EFFECT_SPD_UP_1: + case Z_EFFECT_SPATK_UP_1: + case Z_EFFECT_SPDEF_UP_1: + statChange = STAT_CHANGE_ATK + zEffect - Z_EFFECT_ATK_UP_1; + break; + case Z_EFFECT_ATK_UP_2: + case Z_EFFECT_DEF_UP_2: + case Z_EFFECT_SPD_UP_2: + case Z_EFFECT_SPATK_UP_2: + case Z_EFFECT_SPDEF_UP_2: + statChange = STAT_CHANGE_ATK_2 + zEffect - Z_EFFECT_ATK_UP_2; + break; + case Z_EFFECT_ATK_UP_3: + case Z_EFFECT_DEF_UP_3: + case Z_EFFECT_SPD_UP_3: + case Z_EFFECT_SPATK_UP_3: + case Z_EFFECT_SPDEF_UP_3: + statChange = STAT_CHANGE_ATK_2 + zEffect - Z_EFFECT_ATK_UP_3; + break; + default: + return FALSE; + } + + if (statChange != 0 && (isEager || IncreaseStatUpScore(battlerAtk, battlerDef, statChange) > 0)) + return TRUE; + + } + else if (GetMoveEffect(zMove) == EFFECT_EXTREME_EVOBOOST) + { + return ShouldRaiseAnyStat(battlerAtk, battlerDef); + } + else if (!IsBattleMoveStatus(chosenMove) && IsBattleMoveStatus(zMove)) + { + return FALSE; + } + + uq4_12_t effectiveness; struct SimulatedDamage dmg; if (gBattleMons[battlerDef].ability == ABILITY_DISGUISE && !MoveIgnoresTargetAbility(zMove) - && (gBattleMons[battlerDef].species == SPECIES_MIMIKYU_DISGUISED || gBattleMons[battlerDef].species == SPECIES_MIMIKYU_TOTEM_DISGUISED)) + && IsMimikyuDisguised(battlerDef)) return FALSE; // Don't waste a Z-Move busting disguise if (gBattleMons[battlerDef].ability == ABILITY_ICE_FACE && !MoveIgnoresTargetAbility(zMove) && gBattleMons[battlerDef].species == SPECIES_EISCUE_ICE && IsBattleMovePhysical(chosenMove)) return FALSE; // Don't waste a Z-Move busting Ice Face - if (IsBattleMoveStatus(chosenMove) && !IsBattleMoveStatus(zMove)) - return FALSE; - else if (!IsBattleMoveStatus(chosenMove) && IsBattleMoveStatus(zMove)) - return FALSE; - dmg = AI_CalcDamageSaveBattlers(chosenMove, battlerAtk, battlerDef, &effectiveness, NO_GIMMICK, NO_GIMMICK); if (!IsBattleMoveStatus(chosenMove) && dmg.minimum >= gBattleMons[battlerDef].hp) @@ -5013,7 +5364,8 @@ void DecideTerastal(u32 battler) #define takenWithTera altCalcs->takenWithTera #define takenWithoutTera gAiLogicData->simulatedDmg[opposingBattler][battler] -enum AIConsiderGimmick ShouldTeraFromCalcs(u32 battler, u32 opposingBattler, struct AltTeraCalcs *altCalcs) { +enum AIConsiderGimmick ShouldTeraFromCalcs(u32 battler, u32 opposingBattler, struct AltTeraCalcs *altCalcs) +{ struct Pokemon* party = GetBattlerParty(battler); // Check how many pokemon we have that could tera @@ -5190,7 +5542,7 @@ s32 AI_TryToClearStats(u32 battlerAtk, u32 battlerDef, bool32 isDoubleBattle) bool32 AI_ShouldCopyStatChanges(u32 battlerAtk, u32 battlerDef) { - u8 i; + enum Stat i; // Want to copy positive stat changes for (i = STAT_ATK; i < NUM_BATTLE_STATS; i++) { @@ -5203,13 +5555,15 @@ bool32 AI_ShouldCopyStatChanges(u32 battlerAtk, u32 battlerDef) case STAT_SPATK: return (HasMoveWithCategory(battlerAtk, DAMAGE_CATEGORY_SPECIAL)); case STAT_ACC: - return (HasLowAccuracyMove(battlerAtk, battlerDef)); + return HasMoveWithLowAccuracy(battlerAtk, battlerDef, LOW_ACCURACY_THRESHOLD, FALSE); case STAT_EVASION: case STAT_SPEED: return TRUE; case STAT_DEF: case STAT_SPDEF: return (gAiThinkingStruct->aiFlags[battlerAtk] & AI_FLAG_STALL); + default: + break; } } } @@ -5264,14 +5618,14 @@ void IncreaseTidyUpScore(u32 battlerAtk, u32 battlerDef, u32 move, s32 *score) bool32 AI_ShouldSpicyExtract(u32 battlerAtk, u32 battlerAtkPartner, u32 move, struct AiLogicData *aiData) { u32 preventsStatLoss; - u32 partnerAbility = aiData->abilities[battlerAtkPartner]; + enum Ability partnerAbility = aiData->abilities[battlerAtkPartner]; u32 opposingPosition = BATTLE_OPPOSITE(GetBattlerPosition(battlerAtk)); u32 opposingBattler = GetBattlerAtPosition(opposingPosition); if (gBattleMons[battlerAtkPartner].statStages[STAT_ATK] == MAX_STAT_STAGE || partnerAbility == ABILITY_CONTRARY || partnerAbility == ABILITY_GOOD_AS_GOLD - || HasBattlerSideMoveWithEffect(FOE(battlerAtk), EFFECT_FOUL_PLAY)) + || HasBattlerSideMoveWithEffect(LEFT_FOE(battlerAtk), EFFECT_FOUL_PLAY)) return FALSE; preventsStatLoss = !CanLowerStat(battlerAtk, battlerAtkPartner, aiData, STAT_DEF); @@ -5334,17 +5688,6 @@ u32 IncreaseSubstituteMoveScore(u32 battlerAtk, u32 battlerDef, u32 move) return scoreIncrease; } -bool32 HasLowAccuracyMove(u32 battlerAtk, u32 battlerDef) -{ - int i; - for (i = 0; i < MAX_MON_MOVES; i++) - { - if (gAiLogicData->moveAccuracy[battlerAtk][battlerDef][i] <= LOW_ACCURACY_THRESHOLD) - return TRUE; - } - return FALSE; -} - bool32 IsBattlerItemEnabled(u32 battler) { if (gAiThinkingStruct->aiFlags[battler] & AI_FLAG_NEGATE_UNAWARE) @@ -5358,15 +5701,6 @@ bool32 IsBattlerItemEnabled(u32 battler) return TRUE; } -bool32 HasBattlerSideAbility(u32 battler, u32 ability, struct AiLogicData *aiData) -{ - if (aiData->abilities[battler] == ability) - return TRUE; - if (HasPartnerIgnoreFlags(battler) && gAiLogicData->abilities[BATTLE_PARTNER(battler)] == ability) - return TRUE; - return FALSE; -} - u32 GetFriendlyFireKOThreshold(u32 battler) { if (gAiThinkingStruct->aiFlags[battler] & AI_FLAG_RISKY) @@ -5379,7 +5713,7 @@ u32 GetFriendlyFireKOThreshold(u32 battler) return FRIENDLY_FIRE_NORMAL_THRESHOLD; } -bool32 IsMoxieTypeAbility(u32 ability) +bool32 IsMoxieTypeAbility(enum Ability ability) { switch (ability) { @@ -5395,7 +5729,7 @@ bool32 IsMoxieTypeAbility(u32 ability) } } -bool32 DoesAbilityRaiseStatsWhenLowered(u32 ability) +bool32 DoesAbilityRaiseStatsWhenLowered(enum Ability ability) { switch (ability) { @@ -5408,7 +5742,7 @@ bool32 DoesAbilityRaiseStatsWhenLowered(u32 ability) } } -bool32 DoesIntimidateRaiseStats(u32 ability) +bool32 DoesIntimidateRaiseStats(enum Ability ability) { switch (ability) { @@ -5424,7 +5758,7 @@ bool32 DoesIntimidateRaiseStats(u32 ability) } // TODO: work out when to attack into the player's contextually 'beneficial' ability -bool32 ShouldTriggerAbility(u32 battlerAtk, u32 battlerDef, u32 ability) +bool32 ShouldTriggerAbility(u32 battlerAtk, u32 battlerDef, enum Ability ability) { if (IsTargetingPartner(battlerAtk, battlerDef)) { @@ -5479,8 +5813,10 @@ bool32 ShouldTriggerAbility(u32 battlerAtk, u32 battlerDef, u32 ability) // Used by CheckBadMove; this is determining purely if the effect CAN change an ability, not if it SHOULD. // At the moment, the parts about Mummy and Wandering Spirit are not actually used. -bool32 CanEffectChangeAbility(u32 battlerAtk, u32 battlerDef, u32 effect, struct AiLogicData *aiData) +bool32 CanEffectChangeAbility(u32 battlerAtk, u32 battlerDef, u32 move, struct AiLogicData *aiData) { + u32 effect = GetMoveEffect(move); + // Dynamaxed Pokemon are immune to some ability-changing effects. if (GetActiveGimmick(battlerDef) == GIMMICK_DYNAMAX) { @@ -5497,8 +5833,8 @@ bool32 CanEffectChangeAbility(u32 battlerAtk, u32 battlerDef, u32 effect, struct if (gBattleMons[battlerDef].volatiles.gastroAcid) return FALSE; - u32 atkAbility = aiData->abilities[battlerAtk]; - u32 defAbility = aiData->abilities[battlerDef]; + enum Ability atkAbility = aiData->abilities[battlerAtk]; + enum Ability defAbility = aiData->abilities[battlerDef]; bool32 hasSameAbility = (atkAbility == defAbility); if (defAbility == ABILITY_NONE) @@ -5556,13 +5892,8 @@ bool32 CanEffectChangeAbility(u32 battlerAtk, u32 battlerDef, u32 effect, struct return FALSE; break; - case EFFECT_SIMPLE_BEAM: - if (defAbility == ABILITY_SIMPLE || gAbilitiesInfo[defAbility].cantBeOverwritten) - return FALSE; - break; - - case EFFECT_WORRY_SEED: - if (defAbility == ABILITY_INSOMNIA || gAbilitiesInfo[defAbility].cantBeOverwritten) + case EFFECT_OVERWRITE_ABILITY: + if (defAbility == GetMoveOverwriteAbility(move) || gAbilitiesInfo[defAbility].cantBeOverwritten) return FALSE; break; @@ -5577,9 +5908,8 @@ bool32 CanEffectChangeAbility(u32 battlerAtk, u32 battlerDef, u32 effect, struct case EFFECT_ENTRAINMENT: case EFFECT_GASTRO_ACID: case EFFECT_ROLE_PLAY: - case EFFECT_SIMPLE_BEAM: case EFFECT_SKILL_SWAP: - case EFFECT_WORRY_SEED: + case EFFECT_OVERWRITE_ABILITY: return FALSE; default: break; @@ -5608,20 +5938,20 @@ bool32 DoesEffectReplaceTargetAbility(u32 effect) { case EFFECT_ENTRAINMENT: case EFFECT_GASTRO_ACID: - case EFFECT_SIMPLE_BEAM: case EFFECT_SKILL_SWAP: - case EFFECT_WORRY_SEED: + case EFFECT_OVERWRITE_ABILITY: return TRUE; default: return FALSE; } } -void AbilityChangeScore(u32 battlerAtk, u32 battlerDef, u32 effect, s32 *score, struct AiLogicData *aiData) +void AbilityChangeScore(u32 battlerAtk, u32 battlerDef, u32 move, s32 *score, struct AiLogicData *aiData) { + u32 effect = GetMoveEffect(move); bool32 isTargetingPartner = IsTargetingPartner(battlerAtk, battlerDef); - u32 abilityAtk = aiData->abilities[battlerAtk]; - u32 abilityDef = aiData->abilities[battlerDef]; + enum Ability abilityAtk = aiData->abilities[battlerAtk]; + enum Ability abilityDef = aiData->abilities[battlerDef]; bool32 partnerHasBadAbility = FALSE; u32 partnerAbility = ABILITY_NONE; bool32 attackerHasBadAbility = (gAbilitiesInfo[abilityAtk].aiRating < 0); @@ -5636,10 +5966,8 @@ void AbilityChangeScore(u32 battlerAtk, u32 battlerDef, u32 effect, s32 *score, if (effect == EFFECT_GASTRO_ACID) abilityAtk = ABILITY_NONE; - else if (effect == EFFECT_SIMPLE_BEAM) - abilityAtk = ABILITY_SIMPLE; - else if (effect == EFFECT_WORRY_SEED) - abilityAtk = ABILITY_INSOMNIA; + else if (effect == EFFECT_OVERWRITE_ABILITY) + abilityAtk = GetMoveOverwriteAbility(move); if (effect == EFFECT_DOODLE || effect == EFFECT_ROLE_PLAY || effect == EFFECT_SKILL_SWAP) { @@ -5691,7 +6019,7 @@ void AbilityChangeScore(u32 battlerAtk, u32 battlerDef, u32 effect, s32 *score, } } -s32 BattlerBenefitsFromAbilityScore(u32 battler, u32 ability, struct AiLogicData *aiData) +s32 BattlerBenefitsFromAbilityScore(u32 battler, enum Ability ability, struct AiLogicData *aiData) { if (gAbilitiesInfo[ability].aiRating < 0) return WORST_EFFECT; @@ -5709,7 +6037,8 @@ s32 BattlerBenefitsFromAbilityScore(u32 battler, u32 ability, struct AiLogicData return GOOD_EFFECT; // Conditional ability logic goes here. case ABILITY_COMPOUND_EYES: - if (HasMoveWithLowAccuracy(battler, FOE(battler), 90, TRUE, aiData->abilities[battler], aiData->abilities[FOE(battler)], aiData->holdEffects[battler], aiData->holdEffects[FOE(battler)])) + if (HasMoveWithLowAccuracy(battler, LEFT_FOE(battler), 90, FALSE) + || HasMoveWithLowAccuracy(battler, RIGHT_FOE(battler), 90, FALSE)) return GOOD_EFFECT; break; case ABILITY_CONTRARY: @@ -5741,7 +6070,7 @@ s32 BattlerBenefitsFromAbilityScore(u32 battler, u32 ability, struct AiLogicData break; case ABILITY_INTIMIDATE: { - u32 abilityDef = aiData->abilities[FOE(battler)]; + enum Ability abilityDef = aiData->abilities[LEFT_FOE(battler)]; if (DoesIntimidateRaiseStats(abilityDef)) { return AWFUL_EFFECT; @@ -5750,26 +6079,27 @@ s32 BattlerBenefitsFromAbilityScore(u32 battler, u32 ability, struct AiLogicData { if (HasTwoOpponents(battler)) { - abilityDef = aiData->abilities[BATTLE_PARTNER(FOE(battler))]; + abilityDef = aiData->abilities[RIGHT_FOE(battler)]; if (DoesIntimidateRaiseStats(abilityDef)) { return AWFUL_EFFECT; } else { - s32 score1 = IncreaseStatDownScore(battler, FOE(battler), STAT_ATK); - s32 score2 = IncreaseStatDownScore(battler, BATTLE_PARTNER(FOE(battler)), STAT_ATK); + s32 score1 = IncreaseStatDownScore(battler, LEFT_FOE(battler), STAT_ATK); + s32 score2 = IncreaseStatDownScore(battler, RIGHT_FOE(battler), STAT_ATK); if (score1 > score2) return score1; else return score2; } } - return IncreaseStatDownScore(battler, FOE(battler), STAT_ATK); + return IncreaseStatDownScore(battler, LEFT_FOE(battler), STAT_ATK); } } case ABILITY_NO_GUARD: - if (HasLowAccuracyMove(battler, FOE(battler))) + if (HasMoveWithLowAccuracy(battler, LEFT_FOE(battler), LOW_ACCURACY_THRESHOLD, FALSE) + || HasMoveWithLowAccuracy(battler, RIGHT_FOE(battler), LOW_ACCURACY_THRESHOLD, FALSE)) return GOOD_EFFECT; break; // Toxic counter ticks upward while Poison Healed; losing Poison Heal while Toxiced can KO. diff --git a/src/battle_anim.c b/src/battle_anim.c index 839f319031..0e17819213 100644 --- a/src/battle_anim.c +++ b/src/battle_anim.c @@ -196,6 +196,7 @@ static const u8* const sBattleAnims_StatusConditions[NUM_B_ANIMS_STATUS] = [B_ANIM_STATUS_FRZ] = gBattleAnimStatus_Freeze, [B_ANIM_STATUS_CURSED] = gBattleAnimStatus_Curse, [B_ANIM_STATUS_NIGHTMARE] = gBattleAnimStatus_Nightmare, + [B_ANIM_STATUS_FRB] = gBattleAnimStatus_Frostbite, }; static const u8* const sBattleAnims_General[NUM_B_ANIMS_GENERAL] = @@ -254,6 +255,8 @@ static const u8* const sBattleAnims_General[NUM_B_ANIMS_GENERAL] = [B_ANIM_TERA_ACTIVATE] = gBattleAnimGeneral_TeraActivate, [B_ANIM_SIMPLE_HEAL] = gBattleAnimGeneral_SimpleHeal, [B_ANIM_POWER_CONSTRUCT] = gBattleAnimGeneral_PowerConstruct, + [B_ANIM_SWAP_TO_SUBSTITUTE] = gBattleAnimGeneral_SwapToSubstitute, + [B_ANIM_SWAP_FROM_SUBSTITUTE] = gBattleAnimGeneral_SwapFromSubstitute, }; static const u8* const sBattleAnims_Special[NUM_B_ANIMS_SPECIAL] = @@ -1572,9 +1575,9 @@ void LoadMoveBg(u16 bgId) void *decompressionBuffer = malloc_and_decompress(gBattleAnimBackgroundTable[bgId].tilemap, NULL); RelocateBattleBgPal(GetBattleBgPaletteNum(), decompressionBuffer, 0x100, FALSE); DmaCopy32(3, decompressionBuffer, (void *)BG_SCREEN_ADDR(26), 0x800); + Free(decompressionBuffer); DecompressDataWithHeaderVram(gBattleAnimBackgroundTable[bgId].image, (void *)BG_SCREEN_ADDR(4)); LoadPalette(gBattleAnimBackgroundTable[bgId].palette, BG_PLTT_ID(GetBattleBgPaletteNum()), PLTT_SIZE_4BPP); - Free(decompressionBuffer); } else { @@ -2221,7 +2224,7 @@ static void Cmd_stopsound(void) static void Cmd_jumpifmovetypeequal(void) { - const u8 *type = sBattleAnimScriptPtr + 1; + const enum Type *type = sBattleAnimScriptPtr + 1; sBattleAnimScriptPtr += 2; if (*type != GetBattleMoveType(gCurrentMove)) sBattleAnimScriptPtr += 4; diff --git a/src/battle_anim_effects_1.c b/src/battle_anim_effects_1.c index 49ec4e5e3a..4699f2008a 100644 --- a/src/battle_anim_effects_1.c +++ b/src/battle_anim_effects_1.c @@ -6831,10 +6831,10 @@ static void TrySwapStickyWebBattlerId(u32 battlerAtk, u32 battlerPartner) static void TrySwapWishBattlerIds(u32 battlerAtk, u32 battlerPartner) { u32 i, temp; - u32 oppSide = GetBattlerSide(BATTLE_OPPOSITE(battlerAtk)); // if used future sight on opposing side, properly track who used it - if (gSideStatuses[oppSide] & SIDE_STATUS_FUTUREATTACK) + if (gWishFutureKnock.futureSightCounter[LEFT_FOE(battlerAtk)] > 0 + || gWishFutureKnock.futureSightCounter[RIGHT_FOE(battlerAtk)] > 0) { for (i = 0; i < gBattlersCount; i++) { @@ -6858,8 +6858,8 @@ static void TrySwapWishBattlerIds(u32 battlerAtk, u32 battlerPartner) } // swap wish party indices - if (gWishFutureKnock.wishCounter[battlerAtk] > gBattleTurnCounter - || gWishFutureKnock.wishCounter[battlerPartner] > gBattleTurnCounter) + if (gWishFutureKnock.wishCounter[battlerAtk] > 0 + || gWishFutureKnock.wishCounter[battlerPartner] > 0) SWAP(gWishFutureKnock.wishPartyId[battlerAtk], gWishFutureKnock.wishPartyId[battlerPartner], temp); } @@ -6964,7 +6964,7 @@ static void AnimTask_AllySwitchDataSwap(u8 taskId) // For Snipe Shot and abilities Stalwart/Propeller Tail - keep the original target. for (i = 0; i < gBattlersCount; i++) { - u16 ability = GetBattlerAbility(i); + enum Ability ability = GetBattlerAbility(i); // if not targeting a slot that got switched, continue if (!IsBattlerAlly(gBattleStruct->moveTarget[i], battlerAtk)) continue; diff --git a/src/battle_anim_effects_3.c b/src/battle_anim_effects_3.c index e30a8afd15..cc6203ce5b 100644 --- a/src/battle_anim_effects_3.c +++ b/src/battle_anim_effects_3.c @@ -5775,7 +5775,7 @@ static void AnimRecycle_Step(struct Sprite *sprite) void AnimTask_GetWeather(u8 taskId) { - bool32 utilityUmbrellaAffected = GetBattlerHoldEffect(gBattleAnimAttacker, TRUE) == HOLD_EFFECT_UTILITY_UMBRELLA; + bool32 utilityUmbrellaAffected = GetBattlerHoldEffect(gBattleAnimAttacker) == HOLD_EFFECT_UTILITY_UMBRELLA; gBattleAnimArgs[ARG_RET_ID] = ANIM_WEATHER_NONE; if (gWeatherMoveAnim & B_WEATHER_SUN && !utilityUmbrellaAffected) diff --git a/src/battle_anim_new.c b/src/battle_anim_new.c index 378fde42a4..fff35b4073 100644 --- a/src/battle_anim_new.c +++ b/src/battle_anim_new.c @@ -9058,7 +9058,7 @@ void AnimTask_ShellSideArm(u8 taskId) void AnimTask_TerrainPulse(u8 taskId) { - if (IsBattlerTerrainAffected(gBattleAnimAttacker, STATUS_FIELD_TERRAIN_ANY)) + if (IsBattlerTerrainAffected(gBattleAnimAttacker, GetBattlerAbility(gBattleAnimAttacker), GetBattlerHoldEffect(gBattleAnimAttacker), STATUS_FIELD_TERRAIN_ANY)) { if (gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN) gBattleAnimArgs[0] = TYPE_ELECTRIC; diff --git a/src/battle_anim_status_effects.c b/src/battle_anim_status_effects.c index b70f481d6c..f27d7da0ea 100644 --- a/src/battle_anim_status_effects.c +++ b/src/battle_anim_status_effects.c @@ -530,7 +530,7 @@ static void AnimTask_FrozenIceCube_Step4(u8 taskId) void AnimTask_StatsChange(u8 taskId) { bool16 goesDown = FALSE; - s16 animStatId = 0; + enum StatAnimPal animStatId = 0; bool16 sharply = FALSE; switch (gBattleSpritesDataPtr->animationData->animArg) diff --git a/src/battle_anim_throw.c b/src/battle_anim_throw.c index 5860a57630..d276c80ddb 100644 --- a/src/battle_anim_throw.c +++ b/src/battle_anim_throw.c @@ -2313,7 +2313,7 @@ void AnimTask_SwapMonSpriteToFromSubstitute(u8 taskId) { u8 spriteId; u32 x; - u32 done = FALSE; + bool32 done = FALSE; spriteId = gBattlerSpriteIds[gBattleAnimAttacker]; switch (gTasks[taskId].data[10]) diff --git a/src/battle_anim_utility_funcs.c b/src/battle_anim_utility_funcs.c index 54b9f949ba..54aa3e14aa 100644 --- a/src/battle_anim_utility_funcs.c +++ b/src/battle_anim_utility_funcs.c @@ -480,7 +480,7 @@ static void StatsChangeAnimation_Step2(u8 taskId) AnimLoadCompressedBgTilemapHandleContest(&animBgData, gStatAnim_Decrease_Tilemap, FALSE); AnimLoadCompressedBgGfx(animBgData.bgId, gStatAnim_Gfx, animBgData.tilesOffset); - switch (sAnimStatsChangeData->aAnimStatId) + switch ((enum StatAnimPal)sAnimStatsChangeData->aAnimStatId) { case STAT_ANIM_PAL_ATK: LoadPalette(gStatAnim_Attack_Pal, BG_PLTT_ID(animBgData.paletteId), PLTT_SIZE_4BPP); diff --git a/src/battle_arena.c b/src/battle_arena.c index 8474595b0d..3708fec024 100644 --- a/src/battle_arena.c +++ b/src/battle_arena.c @@ -427,14 +427,11 @@ void BattleArena_DeductSkillPoints(u8 battler, enum StringID stringId) case STRINGID_PKMNSXBLOCKSY2: case STRINGID_PKMNSXPREVENTSYLOSS: case STRINGID_PKMNSXMADEYINEFFECTIVE: - case STRINGID_PKMNSXPREVENTSBURNS: case STRINGID_PKMNSXBLOCKSY: case STRINGID_PKMNPROTECTEDBY: case STRINGID_PKMNPREVENTSUSAGE: case STRINGID_PKMNRESTOREDHPUSING: - case STRINGID_PKMNPREVENTSPARALYSISWITH: case STRINGID_PKMNPREVENTSROMANCEWITH: - case STRINGID_PKMNPREVENTSPOISONINGWITH: case STRINGID_PKMNPREVENTSCONFUSIONWITH: case STRINGID_PKMNRAISEDFIREPOWERWITH: case STRINGID_PKMNANCHORSITSELFWITH: diff --git a/src/battle_bg.c b/src/battle_bg.c index 3524dbee2d..14244c4e95 100644 --- a/src/battle_bg.c +++ b/src/battle_bg.c @@ -19,6 +19,7 @@ #include "sound.h" #include "sprite.h" #include "task.h" +#include "test_runner.h" #include "text_window.h" #include "trig.h" #include "window.h" @@ -650,7 +651,13 @@ static u8 GetBattleEnvironmentOverride(void) { u8 battleScene = GetCurrentMapBattleScene(); - if (gBattleTypeFlags & (BATTLE_TYPE_FRONTIER | BATTLE_TYPE_LINK | BATTLE_TYPE_RECORDED_LINK | BATTLE_TYPE_EREADER_TRAINER)) + if (TestRunner_Battle_GetForcedEnvironment() + && gBattleEnvironmentInfo[gBattleEnvironment].background.tilemap + && gBattleEnvironmentInfo[gBattleEnvironment].background.tileset) + { + return gBattleEnvironment; + } + else if (gBattleTypeFlags & (BATTLE_TYPE_FRONTIER | BATTLE_TYPE_LINK | BATTLE_TYPE_RECORDED_LINK | BATTLE_TYPE_EREADER_TRAINER)) return BATTLE_ENVIRONMENT_FRONTIER; else if (gBattleTypeFlags & BATTLE_TYPE_LEGENDARY) { @@ -1022,7 +1029,13 @@ void DrawBattleEntryBackground(void) } else if (gBattleTypeFlags & (BATTLE_TYPE_FRONTIER | BATTLE_TYPE_LINK | BATTLE_TYPE_RECORDED_LINK | BATTLE_TYPE_EREADER_TRAINER)) { - if (!(gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER) || gPartnerTrainerId > TRAINER_PARTNER(PARTNER_NONE)) + if (TestRunner_Battle_GetForcedEnvironment() + && gBattleEnvironmentInfo[gBattleEnvironment].background.tilemap + && gBattleEnvironmentInfo[gBattleEnvironment].background.tileset) + { + LoadBattleEnvironmentEntryGfx(gBattleEnvironment); + } + else if (!(gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER) || gPartnerTrainerId > TRAINER_PARTNER(PARTNER_NONE)) { LoadBattleEnvironmentEntryGfx(BATTLE_ENVIRONMENT_BUILDING); } diff --git a/src/battle_controller_link_opponent.c b/src/battle_controller_link_opponent.c index 658a2d3831..3418293530 100644 --- a/src/battle_controller_link_opponent.c +++ b/src/battle_controller_link_opponent.c @@ -150,8 +150,7 @@ static void Intro_WaitForShinyAnimAndHealthbox(u32 battler) gBattleSpritesDataPtr->healthBoxesData[BATTLE_PARTNER(battler)].triedShinyMonAnim = FALSE; gBattleSpritesDataPtr->healthBoxesData[BATTLE_PARTNER(battler)].finishedShinyMonAnim = FALSE; - FreeSpriteTilesByTag(ANIM_TAG_GOLD_STARS); - FreeSpritePaletteByTag(ANIM_TAG_GOLD_STARS); + FreeShinyStars(); } else { @@ -163,8 +162,7 @@ static void Intro_WaitForShinyAnimAndHealthbox(u32 battler) if (GetBattlerPosition(battler) == B_POSITION_OPPONENT_RIGHT) { - FreeSpriteTilesByTag(ANIM_TAG_GOLD_STARS); - FreeSpritePaletteByTag(ANIM_TAG_GOLD_STARS); + FreeShinyStars(); } } diff --git a/src/battle_controller_opponent.c b/src/battle_controller_opponent.c index 1f1953ea61..a2d40bc5e1 100644 --- a/src/battle_controller_opponent.c +++ b/src/battle_controller_opponent.c @@ -39,6 +39,8 @@ #include "constants/trainers.h" #include "trainer_hill.h" #include "test_runner.h" +#include "test/battle.h" +#include "test/test_runner_battle.h" static void OpponentHandleDrawTrainerPic(u32 battler); static void OpponentHandleTrainerSlideBack(u32 battler); @@ -49,8 +51,6 @@ static void OpponentHandleChoosePokemon(u32 battler); static void OpponentHandleIntroTrainerBallThrow(u32 battler); static void OpponentHandleDrawPartyStatusSummary(u32 battler); static void OpponentHandleEndLinkBattle(u32 battler); -static u8 CountAIAliveNonEggMonsExcept(u8 slotToIgnore); - static void OpponentBufferRunCommand(u32 battler); static void (*const sOpponentBufferCommands[CONTROLLER_CMDS_COUNT])(u32 battler) = @@ -159,8 +159,7 @@ static void Intro_WaitForShinyAnimAndHealthbox(u32 battler) gBattleSpritesDataPtr->healthBoxesData[battler].finishedShinyMonAnim = FALSE; gBattleSpritesDataPtr->healthBoxesData[BATTLE_PARTNER(battler)].triedShinyMonAnim = FALSE; gBattleSpritesDataPtr->healthBoxesData[BATTLE_PARTNER(battler)].finishedShinyMonAnim = FALSE; - FreeSpriteTilesByTag(ANIM_TAG_GOLD_STARS); - FreeSpritePaletteByTag(ANIM_TAG_GOLD_STARS); + FreeShinyStars(); } else { @@ -174,8 +173,7 @@ static void Intro_WaitForShinyAnimAndHealthbox(u32 battler) if (!gBattleSpritesDataPtr->healthBoxesData[BATTLE_PARTNER(battler)].triedShinyMonAnim && !gBattleSpritesDataPtr->healthBoxesData[BATTLE_PARTNER(battler)].finishedShinyMonAnim) { - FreeSpriteTilesByTag(ANIM_TAG_GOLD_STARS); - FreeSpritePaletteByTag(ANIM_TAG_GOLD_STARS); + FreeShinyStars(); } else { @@ -371,18 +369,40 @@ static u32 OpponentGetTrainerPicId(u32 battlerId) static void OpponentHandleDrawTrainerPic(u32 battler) { s16 xPos; - u32 trainerPicId = OpponentGetTrainerPicId(battler); - - if (gBattleTypeFlags & (BATTLE_TYPE_MULTI | BATTLE_TYPE_TWO_OPPONENTS) && !BATTLE_TWO_VS_ONE_OPPONENT) + u32 trainerPicId; + + // Sets Multibattle test opponent sprites to not be Hiker + if (IsMultibattleTest()) { - if ((GetBattlerPosition(battler) & BIT_FLANK) != 0) // second mon + if (GetBattlerPosition(battler) == B_POSITION_OPPONENT_LEFT) + { + trainerPicId = TRAINER_PIC_LEAF; + if (!(gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS)) + xPos = 176; + else + xPos = 200; + } + else + { + trainerPicId = TRAINER_PIC_RED; xPos = 152; - else // first mon - xPos = 200; + } } else { - xPos = 176; + trainerPicId = OpponentGetTrainerPicId(battler); + + if (gBattleTypeFlags & (BATTLE_TYPE_MULTI | BATTLE_TYPE_TWO_OPPONENTS) && !BATTLE_TWO_VS_ONE_OPPONENT) + { + if ((GetBattlerPosition(battler) & BIT_FLANK) != 0) // second mon + xPos = 152; + else // first mon + xPos = 200; + } + else + { + xPos = 176; + } } BtlController_HandleDrawTrainerPic(battler, trainerPicId, TRUE, xPos, 40, -1); @@ -442,12 +462,15 @@ static void OpponentHandleChooseMove(u32 battler) gBattlerTarget = GetBattlerAtPosition(B_POSITION_PLAYER_RIGHT); } // If opponent can and should use a gimmick (considering trainer data), do it - if (gBattleStruct->gimmick.usableGimmick[battler] != GIMMICK_NONE && IsAIUsingGimmick(battler)) + enum Gimmick usableGimmick = gBattleStruct->gimmick.usableGimmick[battler]; + if (usableGimmick != GIMMICK_NONE && IsAIUsingGimmick(battler) && !HasTrainerUsedGimmick(battler, usableGimmick)) { + gBattleStruct->gimmick.toActivate |= 1u << battler; BtlController_EmitTwoReturnValues(battler, B_COMM_TO_ENGINE, B_ACTION_EXEC_SCRIPT, (chosenMoveIndex) | (RET_GIMMICK) | (gBattlerTarget << 8)); } else { + SetAIUsingGimmick(battler, NO_GIMMICK); BtlController_EmitTwoReturnValues(battler, B_COMM_TO_ENGINE, B_ACTION_EXEC_SCRIPT, (chosenMoveIndex) | (gBattlerTarget << 8)); } } @@ -505,70 +528,9 @@ static void OpponentHandleChooseItem(u32 battler) BtlController_Complete(battler); } -static inline bool32 IsAcePokemon(u32 chosenMonId, u32 pokemonInBattle, u32 battler) -{ - return gAiThinkingStruct->aiFlags[battler] & AI_FLAG_ACE_POKEMON - && (chosenMonId == CalculateEnemyPartyCountInSide(battler) - 1) - && CountAIAliveNonEggMonsExcept(PARTY_SIZE) != pokemonInBattle; -} - -static inline bool32 IsDoubleAceSlot(u32 battler, u32 partyId) -{ - u32 partyCountEnd; - - if (!(gAiThinkingStruct->aiFlags[battler] & AI_FLAG_DOUBLE_ACE_POKEMON)) - return FALSE; - - partyCountEnd = CalculateEnemyPartyCountInSide(battler); - if (partyCountEnd == 0) - return FALSE; - - if (partyId == partyCountEnd - 1) - return TRUE; - if (partyCountEnd > 1 && partyId == partyCountEnd - 2) - return TRUE; - - return FALSE; -} - -static inline bool32 IsDoubleAcePokemon(u32 chosenMonId, u32 pokemonInBattle, u32 battler) -{ - s32 battler1, battler2, firstId, lastId; - s32 i; - - if (!IsDoubleAceSlot(battler, chosenMonId)) - return FALSE; - - if (!IsDoubleBattle()) - { - battler2 = battler1 = GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT); - } - else - { - battler1 = GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT); - battler2 = GetBattlerAtPosition(B_POSITION_OPPONENT_RIGHT); - } - - GetAIPartyIndexes(battler, &firstId, &lastId); - for (i = firstId; i < lastId; i++) - { - if (!IsValidForBattle(&gEnemyParty[i]) - || i == gBattlerPartyIndexes[battler1] - || i == gBattlerPartyIndexes[battler2] - || i == chosenMonId) - continue; - - if (!IsAcePokemon(i, pokemonInBattle, battler) && !IsDoubleAceSlot(battler, i)) - return TRUE; - } - - return FALSE; -} - static void OpponentHandleChoosePokemon(u32 battler) { s32 chosenMonId; - s32 pokemonInBattle = 1; enum SwitchType switchType = SWITCH_AFTER_KO; // Choosing Revival Blessing target @@ -580,7 +542,7 @@ static void OpponentHandleChoosePokemon(u32 battler) else if (gBattleStruct->AI_monToSwitchIntoId[battler] == PARTY_SIZE) { if (IsSwitchOutEffect(GetMoveEffect(gCurrentMove)) || gAiLogicData->ejectButtonSwitch || gAiLogicData->ejectPackSwitch) - switchType = SWITCH_MID_BATTLE; + switchType = SWITCH_MID_BATTLE_FORCED; // reset the AI data to consider the correct on-field state at time of switch SetBattlerAiData(GetBattlerAtPosition(B_POSITION_PLAYER_LEFT), gAiLogicData); @@ -588,7 +550,7 @@ static void OpponentHandleChoosePokemon(u32 battler) SetBattlerAiData(GetBattlerAtPosition(B_POSITION_PLAYER_RIGHT), gAiLogicData); chosenMonId = GetMostSuitableMonToSwitchInto(battler, switchType); - if (chosenMonId == PARTY_SIZE) + if (chosenMonId == PARTY_SIZE) // Advanced logic failed so we pick the next available battler { s32 battler1, battler2, firstId, lastId; @@ -600,31 +562,24 @@ static void OpponentHandleChoosePokemon(u32 battler) { battler1 = GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT); battler2 = GetBattlerAtPosition(B_POSITION_OPPONENT_RIGHT); - pokemonInBattle = 2; } GetAIPartyIndexes(battler, &firstId, &lastId); - for (chosenMonId = (lastId-1); chosenMonId >= firstId; chosenMonId--) + for (chosenMonId = firstId; chosenMonId < lastId; chosenMonId++) { - if (!IsValidForBattle(&gEnemyParty[chosenMonId]) - || chosenMonId == gBattlerPartyIndexes[battler1] - || chosenMonId == gBattlerPartyIndexes[battler2]) - continue; - - if (!IsAcePokemon(chosenMonId, pokemonInBattle, battler) - && !IsDoubleAcePokemon(chosenMonId, pokemonInBattle, battler)) + if (IsValidForBattle(&gEnemyParty[chosenMonId]) + && chosenMonId != gBattlerPartyIndexes[battler1] + && chosenMonId != gBattlerPartyIndexes[battler2]) break; } } gBattleStruct->monToSwitchIntoId[battler] = chosenMonId; - GetBattlerPartyState(battler)->sentOut = TRUE; } else { chosenMonId = gBattleStruct->AI_monToSwitchIntoId[battler]; gBattleStruct->AI_monToSwitchIntoId[battler] = PARTY_SIZE; gBattleStruct->monToSwitchIntoId[battler] = chosenMonId; - GetBattlerPartyState(battler)->sentOut = TRUE; } #if TESTING TestRunner_Battle_CheckSwitch(battler, chosenMonId); @@ -633,22 +588,6 @@ static void OpponentHandleChoosePokemon(u32 battler) BtlController_Complete(battler); } -static u8 CountAIAliveNonEggMonsExcept(u8 slotToIgnore) -{ - u16 i, count; - - for (i = 0, count = 0; i < PARTY_SIZE; i++) - { - if (i != slotToIgnore - && IsValidForBattle(&gEnemyParty[i])) - { - count++; - } - } - - return count; -} - static void OpponentHandleIntroTrainerBallThrow(u32 battler) { BtlController_HandleIntroTrainerBallThrow(battler, 0, NULL, 0, Intro_TryShinyAnimShowHealthbox); diff --git a/src/battle_controller_player.c b/src/battle_controller_player.c index 1882a092c1..548e4eb871 100644 --- a/src/battle_controller_player.c +++ b/src/battle_controller_player.c @@ -35,7 +35,6 @@ #include "constants/battle_anim.h" #include "constants/battle_move_effects.h" #include "constants/battle_partner.h" -#include "constants/hold_effects.h" #include "constants/items.h" #include "constants/moves.h" #include "constants/party_menu.h" @@ -47,6 +46,8 @@ #include "pokemon_summary_screen.h" #include "type_icons.h" #include "pokedex.h" +#include "test/battle.h" +#include "test/test_runner_battle.h" static void PlayerHandleLoadMonSprite(u32 battler); static void PlayerHandleDrawTrainerPic(u32 battler); @@ -197,46 +198,36 @@ static void CompleteOnBattlerSpritePosX_0(u32 battler) static u16 GetPrevBall(u16 ballId) { - u16 ballPrev; - s32 i, j; - CompactItemsInBagPocket(POCKET_POKE_BALLS); - for (i = 0; i < gBagPockets[POCKET_POKE_BALLS].capacity; i++) + s32 i; + s32 index = ItemIdToBallId(ballId); + u32 newBall = 0; + for (i = 0; i < POKEBALL_COUNT; i++) { - if (ballId == GetBagItemId(POCKET_POKE_BALLS, i)) - { - if (i <= 0) - { - for (j = gBagPockets[POCKET_POKE_BALLS].capacity - 1; j >= 0; j--) - { - ballPrev = GetBagItemId(POCKET_POKE_BALLS, j); - if (ballPrev != ITEM_NONE) - return ballPrev; - } - } - i--; - break; - } + index--; + if (index == -1) + index = POKEBALL_COUNT - 1; + newBall = gBallItemIds[index]; + if (CheckBagHasItem(newBall, 1)) + return newBall; } - return GetBagItemId(POCKET_POKE_BALLS, i); + return ballId; } static u32 GetNextBall(u32 ballId) { - u32 ballNext = ITEM_NONE; s32 i; - CompactItemsInBagPocket(POCKET_POKE_BALLS); - for (i = 1; i < gBagPockets[POCKET_POKE_BALLS].capacity; i++) + s32 index = ItemIdToBallId(ballId); + u32 newBall = 0; + for (i = 0; i < POKEBALL_COUNT; i++) { - if (ballId == GetBagItemId(POCKET_POKE_BALLS, i-1)) - { - ballNext = GetBagItemId(POCKET_POKE_BALLS, i); - break; - } + index++; + if (index == POKEBALL_COUNT) + index = 0; + newBall = gBallItemIds[index]; + if (CheckBagHasItem(newBall, 1)) + return newBall; } - if (ballNext == ITEM_NONE) - return GetBagItemId(POCKET_POKE_BALLS, 0); // Zeroth slot - else - return ballNext; + return ballId; } static void HandleInputChooseAction(u32 battler) @@ -1254,8 +1245,7 @@ static void Intro_WaitForShinyAnimAndHealthbox(u32 battler) gBattleSpritesDataPtr->healthBoxesData[battler].finishedShinyMonAnim = FALSE; gBattleSpritesDataPtr->healthBoxesData[BATTLE_PARTNER(battler)].triedShinyMonAnim = FALSE; gBattleSpritesDataPtr->healthBoxesData[BATTLE_PARTNER(battler)].finishedShinyMonAnim = FALSE; - FreeSpriteTilesByTag(ANIM_TAG_GOLD_STARS); - FreeSpritePaletteByTag(ANIM_TAG_GOLD_STARS); + FreeShinyStars(); HandleLowHpMusicChange(GetBattlerMon(battler), battler); @@ -1680,7 +1670,7 @@ static void MoveSelectionDisplayMoveType(u32 battler) struct ChooseMoveStruct *moveInfo = (struct ChooseMoveStruct *)(&gBattleResources->bufferA[battler][4]); txtPtr = StringCopy(gDisplayedStringBattle, gText_MoveInterfaceType); u32 move = moveInfo->moves[gMoveSelectionCursor[battler]]; - u32 type = GetMoveType(move); + enum Type type = GetMoveType(move); enum BattleMoveEffects effect = GetMoveEffect(move); if (effect == EFFECT_TERA_BLAST) @@ -1884,30 +1874,40 @@ static void PlayerHandleDrawTrainerPic(u32 battler) bool32 isFrontPic; s16 xPos, yPos; u32 trainerPicId; - - trainerPicId = PlayerGetTrainerBackPicId(); - if (gBattleTypeFlags & BATTLE_TYPE_MULTI) + if (IsMultibattleTest()) { - if ((GetBattlerPosition(battler) & BIT_FLANK) != B_FLANK_LEFT) // Second mon, on the right. - xPos = 90; - else // First mon, on the left. + trainerPicId = TRAINER_BACK_PIC_BRENDAN; + if (gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER) xPos = 32; - - if (gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER && gPartnerTrainerId < TRAINER_PARTNER(PARTNER_NONE)) - { - xPos = 90; - yPos = 80; - } else - { - yPos = (8 - gTrainerBacksprites[trainerPicId].coordinates.size) * 4 + 80; - } - + xPos = 80; + yPos = (8 - gTrainerBacksprites[trainerPicId].coordinates.size) * 4 + 80; } else { - xPos = 80; - yPos = (8 - gTrainerBacksprites[trainerPicId].coordinates.size) * 4 + 80; + trainerPicId = PlayerGetTrainerBackPicId(); + if (gBattleTypeFlags & BATTLE_TYPE_MULTI) + { + if ((GetBattlerPosition(battler) & BIT_FLANK) != B_FLANK_LEFT) // Second mon, on the right. + xPos = 90; + else // First mon, on the left. + xPos = 32; + + if (gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER && gPartnerTrainerId < TRAINER_PARTNER(PARTNER_NONE)) + { + xPos = 90; + yPos = 80; + } + else + { + yPos = (8 - gTrainerBacksprites[trainerPicId].coordinates.size) * 4 + 80; + } + } + else + { + xPos = 80; + yPos = (8 - gTrainerBacksprites[trainerPicId].coordinates.size) * 4 + 80; + } } // Use front pic table for any tag battles unless your partner is Steven or a custom partner. @@ -2007,7 +2007,7 @@ static void PlayerHandleChooseAction(u32 battler) if (B_SHOW_PARTNER_TARGET && gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER && IsBattlerAlive(B_POSITION_PLAYER_RIGHT)) { StringCopy(gStringVar1, COMPOUND_STRING("我方同伴将使用:\n")); - u32 move = gBattleMons[B_POSITION_PLAYER_RIGHT].moves[gBattleStruct->chosenMovePositions[B_POSITION_PLAYER_RIGHT]]; + u32 move = GetChosenMoveFromPosition(B_POSITION_PLAYER_RIGHT); StringAppend(gStringVar1, GetMoveName(move)); u32 moveTarget = GetBattlerMoveTargetType(B_POSITION_PLAYER_RIGHT, move); if (moveTarget == MOVE_TARGET_SELECTED) @@ -2375,8 +2375,8 @@ static u32 CheckTypeEffectiveness(u32 battlerAtk, u32 battlerDef) ctx.updateFlags = FALSE; ctx.abilityAtk = GetBattlerAbility(battlerAtk); ctx.abilityDef = GetBattlerAbility(battlerDef); - ctx.holdEffectAtk = GetBattlerHoldEffect(battlerAtk, TRUE); - ctx.holdEffectDef = GetBattlerHoldEffect(battlerDef, TRUE); + ctx.holdEffectAtk = GetBattlerHoldEffect(battlerAtk); + ctx.holdEffectDef = GetBattlerHoldEffect(battlerDef); uq4_12_t modifier = CalcTypeEffectivenessMultiplier(&ctx); diff --git a/src/battle_controller_player_partner.c b/src/battle_controller_player_partner.c index 58911f1518..37af6497df 100644 --- a/src/battle_controller_player_partner.c +++ b/src/battle_controller_player_partner.c @@ -31,6 +31,8 @@ #include "constants/songs.h" #include "constants/party_menu.h" #include "constants/trainers.h" +#include "test/battle.h" +#include "test/test_runner_battle.h" static void PlayerPartnerHandleDrawTrainerPic(u32 battler); static void PlayerPartnerHandleTrainerSlideBack(u32 battler); @@ -204,7 +206,13 @@ static void PlayerPartnerHandleDrawTrainerPic(u32 battler) enum DifficultyLevel difficulty = GetBattlePartnerDifficultyLevel(gPartnerTrainerId); - if (gPartnerTrainerId > TRAINER_PARTNER(PARTNER_NONE)) + if (IsMultibattleTest()) + { + trainerPicId = TRAINER_BACK_PIC_STEVEN; + xPos = 90; + yPos = (8 - gTrainerBacksprites[trainerPicId].coordinates.size) * 4 + 80; + } + else if (gPartnerTrainerId > TRAINER_PARTNER(PARTNER_NONE)) { trainerPicId = gBattlePartners[difficulty][gPartnerTrainerId - TRAINER_PARTNER(PARTNER_NONE)].trainerBackPic; xPos = 90; @@ -261,12 +269,15 @@ static void PlayerPartnerHandleChooseMove(u32 battler) gBattlerTarget = GetBattlerAtPosition(B_POSITION_OPPONENT_RIGHT); } // If partner can and should use a gimmick (considering trainer data), do it - if (gBattleStruct->gimmick.usableGimmick[battler] != GIMMICK_NONE && IsAIUsingGimmick(battler)) + enum Gimmick usableGimmick = gBattleStruct->gimmick.usableGimmick[battler]; + if (usableGimmick != GIMMICK_NONE && IsAIUsingGimmick(battler) && !HasTrainerUsedGimmick(battler, usableGimmick)) { + gBattleStruct->gimmick.toActivate |= 1u << battler; BtlController_EmitTwoReturnValues(battler, B_COMM_TO_ENGINE, B_ACTION_EXEC_SCRIPT, (chosenMoveIndex) | (RET_GIMMICK) | (gBattlerTarget << 8)); } else { + SetAIUsingGimmick(battler, NO_GIMMICK); BtlController_EmitTwoReturnValues(battler, B_COMM_TO_ENGINE, B_ACTION_EXEC_SCRIPT, (chosenMoveIndex) | (gBattlerTarget << 8)); } @@ -302,15 +313,15 @@ static void PlayerPartnerHandleChoosePokemon(u32 battler) } } gBattleStruct->monToSwitchIntoId[battler] = chosenMonId; - GetBattlerPartyState(battler)->sentOut = TRUE; } else // Mon to switch out has been already chosen. { chosenMonId = gBattleStruct->monToSwitchIntoId[battler]; gBattleStruct->AI_monToSwitchIntoId[battler] = PARTY_SIZE; gBattleStruct->monToSwitchIntoId[battler] = chosenMonId; - GetBattlerPartyState(battler)->sentOut = TRUE; } + if (TESTING) + TestRunner_Battle_CheckSwitch(battler, chosenMonId); BtlController_EmitChosenMonReturnValue(battler, B_COMM_TO_ENGINE, chosenMonId, NULL); BtlController_Complete(battler); } diff --git a/src/battle_controller_recorded_opponent.c b/src/battle_controller_recorded_opponent.c index a27318aee8..954fdc4bc3 100644 --- a/src/battle_controller_recorded_opponent.c +++ b/src/battle_controller_recorded_opponent.c @@ -31,6 +31,8 @@ #include "constants/battle_anim.h" #include "constants/songs.h" #include "constants/trainers.h" +#include "test/battle.h" +#include "test/test_runner_battle.h" static void RecordedOpponentHandleDrawTrainerPic(u32 battler); static void RecordedOpponentHandleTrainerSlideBack(u32 battler); @@ -170,8 +172,7 @@ static void Intro_WaitForShinyAnimAndHealthbox(u32 battler) gBattleSpritesDataPtr->healthBoxesData[battler].finishedShinyMonAnim = FALSE; gBattleSpritesDataPtr->healthBoxesData[BATTLE_PARTNER(battler)].triedShinyMonAnim = FALSE; gBattleSpritesDataPtr->healthBoxesData[BATTLE_PARTNER(battler)].finishedShinyMonAnim = FALSE; - FreeSpriteTilesByTag(ANIM_TAG_GOLD_STARS); - FreeSpritePaletteByTag(ANIM_TAG_GOLD_STARS); + FreeShinyStars(); } gBattleSpritesDataPtr->healthBoxesData[battler].introEndDelay = 3; @@ -274,7 +275,24 @@ static void RecordedOpponentHandleDrawTrainerPic(u32 battler) s16 xPos; u32 trainerPicId; - if (gBattleTypeFlags & BATTLE_TYPE_MULTI) + // Sets Multibattle test opponent sprites to not be Hiker + if (IsMultibattleTest()) + { + if (GetBattlerPosition(battler) == B_POSITION_OPPONENT_LEFT) + { + trainerPicId = TRAINER_PIC_LEAF; + if (!(gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS)) + xPos = 176; + else + xPos = 200; + } + else + { + trainerPicId = TRAINER_PIC_RED; + xPos = 152; + } + } + else if (gBattleTypeFlags & BATTLE_TYPE_MULTI) { if ((GetBattlerPosition(battler) & BIT_FLANK) != 0) // second mon xPos = 152; diff --git a/src/battle_controller_recorded_partner.c b/src/battle_controller_recorded_partner.c new file mode 100644 index 0000000000..d135329635 --- /dev/null +++ b/src/battle_controller_recorded_partner.c @@ -0,0 +1,269 @@ +#include "global.h" +#include "battle.h" +#include "battle_ai_main.h" +#include "battle_ai_util.h" +#include "battle_anim.h" +#include "battle_controllers.h" +#include "battle_message.h" +#include "battle_interface.h" +#include "battle_setup.h" +#include "battle_tower.h" +#include "battle_z_move.h" +#include "bg.h" +#include "data.h" +#include "item_use.h" +#include "link.h" +#include "main.h" +#include "m4a.h" +#include "palette.h" +#include "party_menu.h" +#include "pokeball.h" +#include "pokemon.h" +#include "recorded_battle.h" +#include "reshow_battle_screen.h" +#include "sound.h" +#include "string_util.h" +#include "task.h" +#include "test_runner.h" +#include "text.h" +#include "util.h" +#include "window.h" +#include "constants/battle_anim.h" +#include "constants/battle_partner.h" +#include "constants/songs.h" +#include "constants/party_menu.h" +#include "constants/trainers.h" + +static void RecordedPartnerHandleDrawTrainerPic(u32 battler); +static void RecordedPartnerHandleTrainerSlideBack(u32 battler); +static void RecordedPartnerHandleChooseAction(u32 battler); +static void RecordedPartnerHandleChooseMove(u32 battler); +static void RecordedPartnerHandleChoosePokemon(u32 battler); +static void RecordedPartnerHandleIntroTrainerBallThrow(u32 battler); +static void RecordedPartnerHandleDrawPartyStatusSummary(u32 battler); +static void RecordedPartnerHandleEndLinkBattle(u32 battler); +static void RecordedPartnerBufferRunCommand(u32 battler); + +static void (*const sRecordedPartnerBufferCommands[CONTROLLER_CMDS_COUNT])(u32 battler) = +{ + [CONTROLLER_GETMONDATA] = BtlController_HandleGetMonData, + [CONTROLLER_GETRAWMONDATA] = BtlController_Empty, + [CONTROLLER_SETMONDATA] = BtlController_HandleSetMonData, + [CONTROLLER_SETRAWMONDATA] = BtlController_HandleSetRawMonData, + [CONTROLLER_LOADMONSPRITE] = BtlController_HandleLoadMonSprite, + [CONTROLLER_SWITCHINANIM] = BtlController_HandleSwitchInAnim, + [CONTROLLER_RETURNMONTOBALL] = BtlController_HandleReturnMonToBall, + [CONTROLLER_DRAWTRAINERPIC] = RecordedPartnerHandleDrawTrainerPic, + [CONTROLLER_TRAINERSLIDE] = BtlController_Empty, + [CONTROLLER_TRAINERSLIDEBACK] = RecordedPartnerHandleTrainerSlideBack, + [CONTROLLER_FAINTANIMATION] = BtlController_HandleFaintAnimation, + [CONTROLLER_PALETTEFADE] = BtlController_Empty, + [CONTROLLER_SUCCESSBALLTHROWANIM] = BtlController_Empty, + [CONTROLLER_BALLTHROWANIM] = BtlController_Empty, + [CONTROLLER_PAUSE] = BtlController_Empty, + [CONTROLLER_MOVEANIMATION] = BtlController_HandleMoveAnimation, + [CONTROLLER_PRINTSTRING] = BtlController_HandlePrintString, + [CONTROLLER_PRINTSTRINGPLAYERONLY] = BtlController_Empty, + [CONTROLLER_CHOOSEACTION] = RecordedPartnerHandleChooseAction, + [CONTROLLER_YESNOBOX] = BtlController_Empty, + [CONTROLLER_CHOOSEMOVE] = RecordedPartnerHandleChooseMove, + [CONTROLLER_OPENBAG] = BtlController_Empty, + [CONTROLLER_CHOOSEPOKEMON] = RecordedPartnerHandleChoosePokemon, + [CONTROLLER_23] = BtlController_Empty, + [CONTROLLER_HEALTHBARUPDATE] = BtlController_HandleHealthBarUpdate, + [CONTROLLER_EXPUPDATE] = PlayerHandleExpUpdate, // Partner's player gets experience the same way as the player. + [CONTROLLER_STATUSICONUPDATE] = BtlController_HandleStatusIconUpdate, + [CONTROLLER_STATUSANIMATION] = BtlController_HandleStatusAnimation, + [CONTROLLER_STATUSXOR] = BtlController_Empty, + [CONTROLLER_DATATRANSFER] = BtlController_Empty, + [CONTROLLER_DMA3TRANSFER] = BtlController_Empty, + [CONTROLLER_PLAYBGM] = BtlController_Empty, + [CONTROLLER_32] = BtlController_Empty, + [CONTROLLER_TWORETURNVALUES] = BtlController_Empty, + [CONTROLLER_CHOSENMONRETURNVALUE] = BtlController_Empty, + [CONTROLLER_ONERETURNVALUE] = BtlController_Empty, + [CONTROLLER_ONERETURNVALUE_DUPLICATE] = BtlController_Empty, + [CONTROLLER_HITANIMATION] = BtlController_HandleHitAnimation, + [CONTROLLER_CANTSWITCH] = BtlController_Empty, + [CONTROLLER_PLAYSE] = BtlController_HandlePlaySE, + [CONTROLLER_PLAYFANFAREORBGM] = BtlController_HandlePlayFanfareOrBGM, + [CONTROLLER_FAINTINGCRY] = BtlController_HandleFaintingCry, + [CONTROLLER_INTROSLIDE] = BtlController_HandleIntroSlide, + [CONTROLLER_INTROTRAINERBALLTHROW] = RecordedPartnerHandleIntroTrainerBallThrow, + [CONTROLLER_DRAWPARTYSTATUSSUMMARY] = RecordedPartnerHandleDrawPartyStatusSummary, + [CONTROLLER_HIDEPARTYSTATUSSUMMARY] = BtlController_HandleHidePartyStatusSummary, + [CONTROLLER_ENDBOUNCE] = BtlController_Empty, + [CONTROLLER_SPRITEINVISIBILITY] = BtlController_HandleSpriteInvisibility, + [CONTROLLER_BATTLEANIMATION] = BtlController_HandleBattleAnimation, + [CONTROLLER_LINKSTANDBYMSG] = BtlController_Empty, + [CONTROLLER_RESETACTIONMOVESELECTION] = BtlController_Empty, + [CONTROLLER_ENDLINKBATTLE] = RecordedPartnerHandleEndLinkBattle, + [CONTROLLER_DEBUGMENU] = BtlController_Empty, + [CONTROLLER_TERMINATOR_NOP] = BtlController_TerminatorNop +}; + +void SetControllerToRecordedPartner(u32 battler) +{ + gBattlerControllerEndFuncs[battler] = RecordedPartnerBufferExecCompleted; + gBattlerControllerFuncs[battler] = RecordedPartnerBufferRunCommand; +} + +static void RecordedPartnerBufferRunCommand(u32 battler) +{ + if (IsBattleControllerActiveOnLocal(battler)) + { + if (gBattleResources->bufferA[battler][0] < ARRAY_COUNT(sRecordedPartnerBufferCommands)) + sRecordedPartnerBufferCommands[gBattleResources->bufferA[battler][0]](battler); + else + BtlController_Complete(battler); + } +} + +static void Intro_WaitForHealthbox(u32 battler) +{ + bool32 finished = FALSE; + + if (!IsDoubleBattle() || (IsDoubleBattle() && (gBattleTypeFlags & BATTLE_TYPE_MULTI))) + { + if (gSprites[gHealthboxSpriteIds[battler]].callback == SpriteCallbackDummy) + finished = TRUE; + } + else + { + if (gSprites[gHealthboxSpriteIds[battler]].callback == SpriteCallbackDummy + && gSprites[gHealthboxSpriteIds[BATTLE_PARTNER(battler)]].callback == SpriteCallbackDummy) + { + finished = TRUE; + } + } + + if (IsCryPlayingOrClearCrySongs()) + finished = FALSE; + + if (finished) + { + gBattleSpritesDataPtr->healthBoxesData[battler].introEndDelay = 3; + gBattlerControllerFuncs[battler] = BtlController_Intro_DelayAndEnd; + } +} + +void Controller_RecordedPartnerShowIntroHealthbox(u32 battler) +{ + if (!gBattleSpritesDataPtr->healthBoxesData[battler].ballAnimActive + && !gBattleSpritesDataPtr->healthBoxesData[BATTLE_PARTNER(battler)].ballAnimActive + && gSprites[gBattleControllerData[battler]].callback == SpriteCallbackDummy + && gSprites[gBattlerSpriteIds[battler]].callback == SpriteCallbackDummy + && ++gBattleSpritesDataPtr->healthBoxesData[battler].introEndDelay != 1) + { + gBattleSpritesDataPtr->healthBoxesData[battler].introEndDelay = 0; + TryShinyAnimation(battler, GetBattlerMon(battler)); + + if (IsDoubleBattle() && !(gBattleTypeFlags & BATTLE_TYPE_MULTI)) + { + DestroySprite(&gSprites[gBattleControllerData[BATTLE_PARTNER(battler)]]); + UpdateHealthboxAttribute(gHealthboxSpriteIds[BATTLE_PARTNER(battler)], GetBattlerMon(BATTLE_PARTNER(battler)), HEALTHBOX_ALL); + StartHealthboxSlideIn(BATTLE_PARTNER(battler)); + SetHealthboxSpriteVisible(gHealthboxSpriteIds[BATTLE_PARTNER(battler)]); + } + + DestroySprite(&gSprites[gBattleControllerData[battler]]); + UpdateHealthboxAttribute(gHealthboxSpriteIds[battler], GetBattlerMon(battler), HEALTHBOX_ALL); + StartHealthboxSlideIn(battler); + SetHealthboxSpriteVisible(gHealthboxSpriteIds[battler]); + + gBattleSpritesDataPtr->animationData->introAnimActive = FALSE; + + gBattlerControllerFuncs[battler] = Intro_WaitForHealthbox; + } +} + +void RecordedPartnerBufferExecCompleted(u32 battler) +{ + gBattlerControllerFuncs[battler] = RecordedPartnerBufferRunCommand; + if (gBattleTypeFlags & BATTLE_TYPE_LINK) + { + u8 playerId = GetMultiplayerId(); + + PrepareBufferDataTransferLink(battler, B_COMM_CONTROLLER_IS_DONE, 4, &playerId); + gBattleResources->bufferA[battler][0] = CONTROLLER_TERMINATOR_NOP; + } + else + { + MarkBattleControllerIdleOnLocal(battler); + } +} + +// some explanation here +// in emerald it's possible to have a tag battle in the battle frontier facilities with AI +// which use the front sprite for both the player and the partner as opposed to any other battles (including the one with Steven) that use the back pic as well as animate it +static void RecordedPartnerHandleDrawTrainerPic(u32 battler) +{ + bool32 isFrontPic; + s16 xPos, yPos; + u32 trainerPicId; + + trainerPicId = TRAINER_BACK_PIC_STEVEN; + xPos = 90; + yPos = (8 - gTrainerBacksprites[trainerPicId].coordinates.size) * 4 + 80; + + isFrontPic = FALSE; + + BtlController_HandleDrawTrainerPic(battler, trainerPicId, isFrontPic, xPos, yPos, -1); +} + +static void RecordedPartnerHandleTrainerSlideBack(u32 battler) +{ + BtlController_HandleTrainerSlideBack(battler, 35, FALSE); +} + +static void RecordedPartnerHandleChooseAction(u32 battler) +{ + BtlController_EmitTwoReturnValues(battler, B_COMM_TO_ENGINE, RecordedBattle_GetBattlerAction(RECORDED_ACTION_TYPE, battler), 0); + BtlController_Complete(battler); +} + +static void RecordedPartnerHandleChooseMove(u32 battler) +{ + u8 moveIndex = RecordedBattle_GetBattlerAction(RECORDED_MOVE_SLOT, battler); + u8 target = RecordedBattle_GetBattlerAction(RECORDED_MOVE_TARGET, battler); + BtlController_EmitTwoReturnValues(battler, B_COMM_TO_ENGINE, B_ACTION_EXEC_SCRIPT, moveIndex | (target << 8)); + + BtlController_Complete(battler); +} + +static void RecordedPartnerHandleChoosePokemon(u32 battler) +{ + gBattleStruct->monToSwitchIntoId[battler] = RecordedBattle_GetBattlerAction(RECORDED_PARTY_INDEX, battler); + gSelectedMonPartyId = gBattleStruct->monToSwitchIntoId[battler]; // Revival Blessing + BtlController_EmitChosenMonReturnValue(battler, B_COMM_TO_ENGINE, gBattleStruct->monToSwitchIntoId[battler], NULL); + BtlController_Complete(battler); +} + +static void RecordedPartnerHandleIntroTrainerBallThrow(u32 battler) +{ + const u16 *trainerPal; + enum DifficultyLevel difficulty = GetBattlePartnerDifficultyLevel(gPartnerTrainerId); + + if (gPartnerTrainerId > TRAINER_PARTNER(PARTNER_NONE)) + trainerPal = gTrainerBacksprites[gBattlePartners[difficulty][gPartnerTrainerId - TRAINER_PARTNER(PARTNER_NONE)].trainerPic].palette.data; + else if (IsAiVsAiBattle()) + trainerPal = gTrainerSprites[GetTrainerPicFromId(gPartnerTrainerId)].palette.data; + else + trainerPal = gTrainerSprites[GetFrontierTrainerFrontSpriteId(gPartnerTrainerId)].palette.data; // 2 vs 2 multi battle in Battle Frontier, load front sprite and pal. + + BtlController_HandleIntroTrainerBallThrow(battler, 0xD6F9, trainerPal, 24, Controller_RecordedPartnerShowIntroHealthbox); +} + +static void RecordedPartnerHandleDrawPartyStatusSummary(u32 battler) +{ + BtlController_HandleDrawPartyStatusSummary(battler, B_SIDE_PLAYER, TRUE); +} + +static void RecordedPartnerHandleEndLinkBattle(u32 battler) +{ + gBattleOutcome = gBattleResources->bufferA[battler][1]; + FadeOutMapMusic(5); + BeginFastPaletteFade(3); + BtlController_Complete(battler); + gBattlerControllerFuncs[battler] = SetBattleEndCallbacks; +} diff --git a/src/battle_controller_recorded_player.c b/src/battle_controller_recorded_player.c index 0230451827..51bfa5327b 100644 --- a/src/battle_controller_recorded_player.c +++ b/src/battle_controller_recorded_player.c @@ -28,6 +28,8 @@ #include "constants/battle_anim.h" #include "constants/songs.h" #include "constants/trainers.h" +#include "test/battle.h" +#include "test/test_runner_battle.h" static void RecordedPlayerHandleDrawTrainerPic(u32 battler); static void RecordedPlayerHandleTrainerSlideBack(u32 battler); @@ -40,7 +42,6 @@ static void RecordedPlayerHandleStatusAnimation(u32 battler); static void RecordedPlayerHandleIntroTrainerBallThrow(u32 battler); static void RecordedPlayerHandleDrawPartyStatusSummary(u32 battler); static void RecordedPlayerHandleEndLinkBattle(u32 battler); - static void RecordedPlayerBufferRunCommand(u32 battler); static void (*const sRecordedPlayerBufferCommands[CONTROLLER_CMDS_COUNT])(u32 battler) = @@ -147,8 +148,7 @@ static void Intro_WaitForShinyAnimAndHealthbox(u32 battler) gBattleSpritesDataPtr->healthBoxesData[BATTLE_PARTNER(battler)].triedShinyMonAnim = FALSE; gBattleSpritesDataPtr->healthBoxesData[BATTLE_PARTNER(battler)].finishedShinyMonAnim = FALSE; - FreeSpriteTilesByTag(ANIM_TAG_GOLD_STARS); - FreeSpritePaletteByTag(ANIM_TAG_GOLD_STARS); + FreeShinyStars(); HandleLowHpMusicChange(GetBattlerMon(battler), battler); if (IsDoubleBattle()) @@ -276,43 +276,54 @@ static void RecordedPlayerHandleDrawTrainerPic(u32 battler) s16 xPos, yPos; u32 trainerPicId; - if (gBattleTypeFlags & BATTLE_TYPE_RECORDED_LINK) + // Sets Multibattle test player sprites to not be Hiker + if (IsMultibattleTest()) { - if (gBattleTypeFlags & BATTLE_TYPE_MULTI) - trainerPicId = GetBattlerLinkPlayerGender(battler); - else - trainerPicId = gLinkPlayers[gRecordedBattleMultiplayerId].gender; - } - else - { - trainerPicId = gLinkPlayers[0].gender; - } - - if (gBattleTypeFlags & BATTLE_TYPE_MULTI) - { - if ((GetBattlerPosition(battler) & BIT_FLANK) != 0) // second mon - xPos = 90; - else // first mon - xPos = 32; - + trainerPicId = TRAINER_BACK_PIC_BRENDAN; if (gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER) - { - xPos = 90; - yPos = 80; - } + xPos = 32; else - { - yPos = (8 - gTrainerBacksprites[trainerPicId].coordinates.size) * 4 + 80; - } - - } - else - { - xPos = 80; + xPos = 80; yPos = (8 - gTrainerBacksprites[trainerPicId].coordinates.size) * 4 + 80; } + else + { + if (gBattleTypeFlags & BATTLE_TYPE_RECORDED_LINK) + { + if (gBattleTypeFlags & BATTLE_TYPE_MULTI) + trainerPicId = GetBattlerLinkPlayerGender(battler); + else + trainerPicId = gLinkPlayers[gRecordedBattleMultiplayerId].gender; + } + else + trainerPicId = gLinkPlayers[0].gender; - if (gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER) + if (gBattleTypeFlags & BATTLE_TYPE_MULTI) + { + if ((GetBattlerPosition(battler) & BIT_FLANK) != 0) // second mon + xPos = 90; + else // first mon + xPos = 32; + + // !TESTING added as otherwise first test battle sprite is positioned incorrectly + if (gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER && !TESTING) + { + xPos = 90; + yPos = 80; + } + else + { + yPos = (8 - gTrainerBacksprites[trainerPicId].coordinates.size) * 4 + 80; + } + } + else + { + xPos = 80; + yPos = (8 - gTrainerBacksprites[trainerPicId].coordinates.size) * 4 + 80; + } + } + + if (gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER && !TESTING) isFrontPic = TRUE; else isFrontPic = FALSE; diff --git a/src/battle_controller_wally.c b/src/battle_controller_wally.c index 932b4a26b4..11955787d9 100644 --- a/src/battle_controller_wally.c +++ b/src/battle_controller_wally.c @@ -255,8 +255,7 @@ static void Intro_WaitForShinyAnimAndHealthbox(u32 battler) gBattleSpritesDataPtr->healthBoxesData[BATTLE_PARTNER(battler)].triedShinyMonAnim = FALSE; gBattleSpritesDataPtr->healthBoxesData[BATTLE_PARTNER(battler)].finishedShinyMonAnim = FALSE; - FreeSpriteTilesByTag(ANIM_TAG_GOLD_STARS); - FreeSpritePaletteByTag(ANIM_TAG_GOLD_STARS); + FreeShinyStars(); CreateTask(Task_PlayerController_RestoreBgmAfterCry, 10); HandleLowHpMusicChange(GetBattlerMon(battler), battler); diff --git a/src/battle_controllers.c b/src/battle_controllers.c index 79828d065d..06ed79c892 100644 --- a/src/battle_controllers.c +++ b/src/battle_controllers.c @@ -29,6 +29,9 @@ #include "constants/abilities.h" #include "constants/item_effects.h" #include "constants/songs.h" +#include "test/battle.h" +#include "test/test.h" +#include "test/test_runner_battle.h" #include "pokemon_animation.h" static EWRAM_DATA u8 sLinkSendTaskId = 0; @@ -144,6 +147,7 @@ static void InitBtlControllersInternal(void) if ((gBattleTypeFlags & BATTLE_TYPE_BATTLE_TOWER) || !isMulti + || (IsMultibattleTest()) || (!isLink && !isRecorded) || (isLink && !isDouble)) { @@ -168,64 +172,82 @@ static void InitBtlControllersInternal(void) if (isLink) { if (isDouble && isMulti && !isMaster) - gBattlerControllerFuncs[gBattlerPositions[B_BATTLER_0]] = SetControllerToLinkPartner; + gBattlerControllerFuncs[GetBattlerPosition(B_BATTLER_0)] = SetControllerToLinkPartner; else - gBattlerControllerFuncs[gBattlerPositions[B_BATTLER_0]] = SetControllerToPlayer; + gBattlerControllerFuncs[GetBattlerPosition(B_BATTLER_0)] = SetControllerToPlayer; if (!isDouble || !isMulti || !isMaster) { - gBattlerControllerFuncs[gBattlerPositions[B_BATTLER_1]] = SetControllerToLinkOpponent; - gBattlerControllerFuncs[gBattlerPositions[B_BATTLER_2]] = SetControllerToPlayer; - gBattlerControllerFuncs[gBattlerPositions[B_BATTLER_3]] = SetControllerToLinkOpponent; + gBattlerControllerFuncs[GetBattlerPosition(B_BATTLER_1)] = SetControllerToLinkOpponent; + gBattlerControllerFuncs[GetBattlerPosition(B_BATTLER_2)] = SetControllerToPlayer; + gBattlerControllerFuncs[GetBattlerPosition(B_BATTLER_3)] = SetControllerToLinkOpponent; } else { - gBattlerControllerFuncs[gBattlerPositions[B_BATTLER_1]] = SetControllerToOpponent; - gBattlerControllerFuncs[gBattlerPositions[B_BATTLER_2]] = SetControllerToLinkPartner; - gBattlerControllerFuncs[gBattlerPositions[B_BATTLER_3]] = SetControllerToOpponent; + gBattlerControllerFuncs[GetBattlerPosition(B_BATTLER_1)] = SetControllerToOpponent; + gBattlerControllerFuncs[GetBattlerPosition(B_BATTLER_2)] = SetControllerToLinkPartner; + gBattlerControllerFuncs[GetBattlerPosition(B_BATTLER_3)] = SetControllerToOpponent; } } else { // Player 1 if (isRecorded) - gBattlerControllerFuncs[gBattlerPositions[B_BATTLER_0]] = SetControllerToRecordedPlayer; + gBattlerControllerFuncs[GetBattlerPosition(B_BATTLER_0)] = SetControllerToRecordedPlayer; else if (gBattleTypeFlags & BATTLE_TYPE_SAFARI) - gBattlerControllerFuncs[gBattlerPositions[B_BATTLER_0]] = SetControllerToSafari; + gBattlerControllerFuncs[GetBattlerPosition(B_BATTLER_0)] = SetControllerToSafari; else if (gBattleTypeFlags & BATTLE_TYPE_WALLY_TUTORIAL) - gBattlerControllerFuncs[gBattlerPositions[B_BATTLER_0]] = SetControllerToWally; + gBattlerControllerFuncs[GetBattlerPosition(B_BATTLER_0)] = SetControllerToWally; else if (isAIvsAI) - gBattlerControllerFuncs[gBattlerPositions[B_BATTLER_0]] = SetControllerToPlayerPartner; + gBattlerControllerFuncs[GetBattlerPosition(B_BATTLER_0)] = SetControllerToPlayerPartner; else - gBattlerControllerFuncs[gBattlerPositions[B_BATTLER_0]] = SetControllerToPlayer; + gBattlerControllerFuncs[GetBattlerPosition(B_BATTLER_0)] = SetControllerToPlayer; // Opponent 1 bool32 isOpponent1Recorded; if (isDouble) - isOpponent1Recorded = (!isInGamePartner && isRecorded && !isMulti && isRecordedLink); + isOpponent1Recorded = ((!isInGamePartner && isRecorded && !isMulti && isRecordedLink) || (IsMultibattleTest() && isRecordedLink)); else isOpponent1Recorded = isRecorded && isRecordedLink; if (isOpponent1Recorded) - gBattlerControllerFuncs[gBattlerPositions[B_BATTLER_1]] = SetControllerToRecordedOpponent; + gBattlerControllerFuncs[GetBattlerPosition(B_BATTLER_1)] = SetControllerToRecordedOpponent; else - gBattlerControllerFuncs[gBattlerPositions[B_BATTLER_1]] = SetControllerToOpponent; + gBattlerControllerFuncs[GetBattlerPosition(B_BATTLER_1)] = SetControllerToOpponent; // Player 2 - if (isInGamePartner) - gBattlerControllerFuncs[gBattlerPositions[B_BATTLER_2]] = SetControllerToPlayerPartner; + if (IsMultibattleTest() && isRecordedLink) + { + gBattlerControllerFuncs[GetBattlerPosition(B_BATTLER_2)] = SetControllerToRecordedPartner; + } + else if (IsMultibattleTest() && isRecorded && !isRecordedLink) + { // Sets to PlayerPartner if EXPECT_XXXX used in test for partner trainer, else sets to RecordedPartner. + if (gBattleTestRunnerState->data.expectedAiActions[B_BATTLER_2][0].actionSet == TRUE) + gBattlerControllerFuncs[GetBattlerPosition(B_BATTLER_2)] = SetControllerToPlayerPartner; + else + gBattlerControllerFuncs[GetBattlerPosition(B_BATTLER_2)] = SetControllerToRecordedPartner; + } + else if ((isInGamePartner && !isRecorded) + || isAIvsAI) + { + gBattlerControllerFuncs[GetBattlerPosition(B_BATTLER_2)] = SetControllerToPlayerPartner; + } else if (isRecorded) - gBattlerControllerFuncs[gBattlerPositions[B_BATTLER_2]] = SetControllerToRecordedPlayer; - else if (isAIvsAI) - gBattlerControllerFuncs[gBattlerPositions[B_BATTLER_2]] = SetControllerToPlayerPartner; + { + gBattlerControllerFuncs[GetBattlerPosition(B_BATTLER_2)] = SetControllerToRecordedPlayer; + } else - gBattlerControllerFuncs[gBattlerPositions[B_BATTLER_2]] = SetControllerToPlayer; + { + gBattlerControllerFuncs[GetBattlerPosition(B_BATTLER_2)] = SetControllerToPlayer; + } // Opponent 2 - if (isInGamePartner || !isRecorded || isMulti || !isRecordedLink) - gBattlerControllerFuncs[gBattlerPositions[B_BATTLER_3]] = SetControllerToOpponent; + if (IsMultibattleTest() && isRecordedLink) + gBattlerControllerFuncs[GetBattlerPosition(B_BATTLER_3)] = SetControllerToRecordedOpponent; + else if (isInGamePartner || !isRecorded || isMulti || !isRecordedLink) + gBattlerControllerFuncs[GetBattlerPosition(B_BATTLER_3)] = SetControllerToOpponent; else - gBattlerControllerFuncs[gBattlerPositions[B_BATTLER_3]] = SetControllerToRecordedOpponent; + gBattlerControllerFuncs[GetBattlerPosition(B_BATTLER_3)] = SetControllerToRecordedOpponent; } bool32 bufferPartyOrders; @@ -308,6 +330,14 @@ bool32 IsValidForBattle(struct Pokemon *mon) && GetMonData(mon, MON_DATA_IS_EGG) == FALSE); } +bool32 IsValidForBattleButDead(struct Pokemon *mon) +{ + u32 species = GetMonData(mon, MON_DATA_SPECIES_OR_EGG); + return (species != SPECIES_NONE + && species != SPECIES_EGG + && GetMonData(mon, MON_DATA_IS_EGG) == FALSE); +} + static inline bool32 IsControllerPlayer(u32 battler) { return (gBattlerControllerEndFuncs[battler] == PlayerBufferExecCompleted); @@ -318,6 +348,11 @@ static inline bool32 IsControllerRecordedPlayer(u32 battler) return (gBattlerControllerEndFuncs[battler] == RecordedPlayerBufferExecCompleted); } +static inline bool32 IsControllerRecordedPartner(u32 battler) +{ + return (gBattlerControllerEndFuncs[battler] == RecordedPartnerBufferExecCompleted); +} + static inline bool32 IsControllerOpponent(u32 battler) { return (gBattlerControllerEndFuncs[battler] == OpponentBufferExecCompleted); @@ -388,21 +423,41 @@ static void SetBattlePartyIds(void) { if (IsOnPlayerSide(i)) { - if (IsValidForBattle(&gPlayerParty[j]) && gBattlerPartyIndexes[i - 2] != j) + if (gBattlerPartyIndexes[i - 2] == j) + { + // Exclude already assigned pokemon; + } + else if (IsValidForBattle(&gPlayerParty[j])) { gBattlerPartyIndexes[i] = j; break; } + else if (IsValidForBattleButDead(&gPlayerParty[j]) && gBattlerPartyIndexes[i] < PARTY_SIZE) + { + // Put an "option" on a dead mon that can be revived; + gBattlerPartyIndexes[i] = j + PARTY_SIZE; + } } else { - if (IsValidForBattle(&gEnemyParty[j]) && gBattlerPartyIndexes[i - 2] != j) + if (gBattlerPartyIndexes[i - 2] == j) + { + // Exclude already assigned pokemon; + } + else if (IsValidForBattle(&gEnemyParty[j])) { gBattlerPartyIndexes[i] = j; break; } + else if (IsValidForBattleButDead(&gEnemyParty[j]) && gBattlerPartyIndexes[i] < PARTY_SIZE) + { + // Put an "option" on a dead mon that can be revived; + gBattlerPartyIndexes[i] = j + PARTY_SIZE; + } } + if (gBattlerPartyIndexes[i] >= PARTY_SIZE) + continue; // No valid mons were found. Add the empty slot. if (gBattlerPartyIndexes[i - 2] == 0) gBattlerPartyIndexes[i] = 1; @@ -410,6 +465,8 @@ static void SetBattlePartyIds(void) gBattlerPartyIndexes[i] = 0; } } + if (gBattlerPartyIndexes[i] >= PARTY_SIZE) + gBattlerPartyIndexes[i] -= PARTY_SIZE; } if (gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS) @@ -2249,6 +2306,7 @@ void BtlController_HandleSwitchInAnim(u32 battler) bool32 isPlayerSide = (IsControllerPlayer(battler) || IsControllerPlayerPartner(battler) || IsControllerRecordedPlayer(battler) + || IsControllerRecordedPartner(battler) || IsControllerLinkPartner(battler)); if (IsControllerPlayer(battler)) @@ -2339,7 +2397,8 @@ void BtlController_HandleDrawTrainerPic(u32 battler, u32 trainerPicId, bool32 is if ((gBattleTypeFlags & BATTLE_TYPE_SAFARI) && GetBattlerPosition(battler) == B_POSITION_PLAYER_LEFT) gBattlerSpriteIds[battler] = gBattleStruct->trainerSlideSpriteIds[battler]; - gSprites[gBattleStruct->trainerSlideSpriteIds[battler]].oam.paletteNum = battler; + // Aiming for palette slots 8 and 9 for Player and PlayerPartner to prevent Trainer Slides causing mons to change colour + gSprites[gBattleStruct->trainerSlideSpriteIds[battler]].oam.paletteNum = (8 + battler/2); } gSprites[gBattleStruct->trainerSlideSpriteIds[battler]].x2 = DISPLAY_WIDTH; gSprites[gBattleStruct->trainerSlideSpriteIds[battler]].sSpeedX = -2; @@ -2364,7 +2423,8 @@ void BtlController_HandleTrainerSlide(u32 battler, u32 trainerPicId) 30); if ((gBattleTypeFlags & BATTLE_TYPE_SAFARI) && GetBattlerPosition(battler) == B_POSITION_PLAYER_LEFT) gBattlerSpriteIds[battler] = gBattleStruct->trainerSlideSpriteIds[battler]; - gSprites[gBattleStruct->trainerSlideSpriteIds[battler]].oam.paletteNum = battler; + // Aiming for palette slots 8 and 9 for Player and PlayerPartner to prevent Trainer Slides causing mons to change colour + gSprites[gBattleStruct->trainerSlideSpriteIds[battler]].oam.paletteNum = (8 + battler/2); gSprites[gBattleStruct->trainerSlideSpriteIds[battler]].x2 = -96; gSprites[gBattleStruct->trainerSlideSpriteIds[battler]].sSpeedX = 2; } @@ -2541,6 +2601,7 @@ void BtlController_HandleHealthBarUpdate(u32 battler) SetBattleBarStruct(battler, gHealthboxSpriteIds[battler], maxHP, 0, hpVal); if (IsControllerPlayer(battler) || IsControllerRecordedPlayer(battler) + || IsControllerRecordedPartner(battler) || IsControllerWally(battler)) UpdateHpTextInHealthbox(gHealthboxSpriteIds[battler], HP_CURRENT, 0, maxHP); TestRunner_Battle_RecordHP(battler, curHP, 0); @@ -2578,7 +2639,7 @@ void BtlController_HandleStatusAnimation(u32 battler) void BtlController_HandleHitAnimation(u32 battler) { - if (gSprites[gBattlerSpriteIds[battler]].invisible == TRUE || gTestRunnerHeadless) + if (gSprites[gBattlerSpriteIds[battler]].invisible == TRUE || (gTestRunnerHeadless && !gBattleTestRunnerState->forceMoveAnim)) { BtlController_Complete(battler); } @@ -2593,7 +2654,7 @@ void BtlController_HandleHitAnimation(u32 battler) void BtlController_HandlePlaySE(u32 battler) { - if (gTestRunnerHeadless) + if (gTestRunnerHeadless && !gBattleTestRunnerState->forceMoveAnim) { BtlController_Complete(battler); return; @@ -2606,7 +2667,7 @@ void BtlController_HandlePlaySE(u32 battler) void BtlController_HandlePlayFanfareOrBGM(u32 battler) { - if (gTestRunnerHeadless) + if (gTestRunnerHeadless && !gBattleTestRunnerState->forceMoveAnim) { BtlController_Complete(battler); return; @@ -2686,7 +2747,7 @@ bool32 TwoOpponentIntroMons(u32 battler) // Double battle with both opponent pok void BtlController_HandleIntroTrainerBallThrow(u32 battler, u16 tagTrainerPal, const u16 *trainerPal, s16 framesToWait, void (*controllerCallback)(u32 battler)) { u8 paletteNum, taskId; - u32 side = GetBattlerSide(battler); + enum BattleSide side = GetBattlerSide(battler); SetSpritePrimaryCoordsFromSecondaryCoords(&gSprites[gBattleStruct->trainerSlideSpriteIds[battler]]); if (side == B_SIDE_PLAYER) @@ -2711,7 +2772,7 @@ void BtlController_HandleIntroTrainerBallThrow(u32 battler, u16 tagTrainerPal, c paletteNum = AllocSpritePalette(tagTrainerPal); LoadPalette(trainerPal, OBJ_PLTT_ID(paletteNum), PLTT_SIZE_4BPP); - gSprites[gBattleStruct->trainerSlideSpriteIds[battler]].oam.paletteNum = paletteNum; + gSprites[gBattleStruct->trainerSlideSpriteIds[battler]].oam.paletteNum = (8 + battler/2); } else { @@ -2812,7 +2873,7 @@ static void SpriteCB_FreeOpponentSprite(struct Sprite *sprite) #undef sBattlerId -void BtlController_HandleDrawPartyStatusSummary(u32 battler, u32 side, bool32 considerDelay) +void BtlController_HandleDrawPartyStatusSummary(u32 battler, enum BattleSide side, bool32 considerDelay) { if (gBattleResources->bufferA[battler][1] != 0 && IsOnPlayerSide(battler)) { @@ -2950,8 +3011,7 @@ void TryShinyAnimAfterMonAnim(u32 battler) { gBattleSpritesDataPtr->healthBoxesData[battler].triedShinyMonAnim = FALSE; gBattleSpritesDataPtr->healthBoxesData[battler].finishedShinyMonAnim = FALSE; - FreeSpriteTilesByTag(ANIM_TAG_GOLD_STARS); - FreeSpritePaletteByTag(ANIM_TAG_GOLD_STARS); + FreeShinyStars(); BtlController_Complete(battler); } } @@ -3016,14 +3076,13 @@ void BtlController_HandleSwitchInSoundAndEnd(u32 battler) void BtlController_HandleSwitchInShowHealthbox(u32 battler) { - u32 side = GetBattlerSide(battler); + enum BattleSide side = GetBattlerSide(battler); if (gBattleSpritesDataPtr->healthBoxesData[battler].finishedShinyMonAnim && (side == B_SIDE_PLAYER || gSprites[gBattlerSpriteIds[battler]].callback == SpriteCallbackDummy)) { gBattleSpritesDataPtr->healthBoxesData[battler].triedShinyMonAnim = FALSE; gBattleSpritesDataPtr->healthBoxesData[battler].finishedShinyMonAnim = FALSE; - FreeSpriteTilesByTag(ANIM_TAG_GOLD_STARS); - FreeSpritePaletteByTag(ANIM_TAG_GOLD_STARS); + FreeShinyStars(); if (side == B_SIDE_PLAYER) { @@ -3053,8 +3112,7 @@ static void SwitchIn_CleanShinyAnimShowSubstitute(u32 battler) // Reset shiny anim (even if it didn't occur) gBattleSpritesDataPtr->healthBoxesData[battler].triedShinyMonAnim = FALSE; gBattleSpritesDataPtr->healthBoxesData[battler].finishedShinyMonAnim = FALSE; - FreeSpriteTilesByTag(ANIM_TAG_GOLD_STARS); - FreeSpritePaletteByTag(ANIM_TAG_GOLD_STARS); + FreeShinyStars(); // Check if Substitute should be shown if (gBattleSpritesDataPtr->battlerData[battler].behindSubstitute) @@ -3106,24 +3164,7 @@ void UpdateFriendshipFromXItem(u32 battler) if (friendship < X_ITEM_MAX_FRIENDSHIP) { - if (GetItemHoldEffect(heldItem) == HOLD_EFFECT_FRIENDSHIP_UP) - friendship += 150 * X_ITEM_FRIENDSHIP_INCREASE / 100; - else - friendship += X_ITEM_FRIENDSHIP_INCREASE; - - u8 pokeball; - gBattleResources->bufferA[battler][1] = REQUEST_POKEBALL_BATTLE; - GetBattlerMonData(battler, party, gBattlerPartyIndexes[battler], &pokeball); - - if (pokeball == BALL_LUXURY) - friendship++; - - u8 metLocation; - gBattleResources->bufferA[battler][1] = REQUEST_MET_LOCATION_BATTLE; - GetBattlerMonData(battler, party, gBattlerPartyIndexes[battler], &metLocation); - - if (metLocation == GetCurrentRegionMapSectionId()) - friendship++; + friendship += CalculateFriendshipBonuses(GetBattlerMon(battler), X_ITEM_FRIENDSHIP_INCREASE, GetItemHoldEffect(heldItem)); if (friendship > MAX_FRIENDSHIP) friendship = MAX_FRIENDSHIP; @@ -3134,3 +3175,19 @@ void UpdateFriendshipFromXItem(u32 battler) SetBattlerMonData(battler, GetBattlerParty(battler), gBattlerPartyIndexes[battler]); } } + +bool32 ShouldBattleRestrictionsApply(u32 battler) +{ + return IsControllerPlayer(battler); +} + +void FreeShinyStars(void) +{ + for (u32 battler = 0; battler < gBattlersCount; battler++) + { + if (gBattleSpritesDataPtr->healthBoxesData[battler].triedShinyMonAnim) + return; + } + FreeSpriteTilesByTag(ANIM_TAG_GOLD_STARS); + FreeSpritePaletteByTag(ANIM_TAG_GOLD_STARS); +} diff --git a/src/battle_debug.c b/src/battle_debug.c index 4b87c97aae..6a789e6b99 100644 --- a/src/battle_debug.c +++ b/src/battle_debug.c @@ -35,7 +35,6 @@ #include "constants/moves.h" #include "constants/items.h" #include "constants/rgb.h" -#include "constants/hold_effects.h" #define MAX_MODIFY_DIGITS 4 @@ -230,7 +229,7 @@ enum }; // Static Declarations -static const u8 *GetHoldEffectName(enum ItemHoldEffect holdEffect); +static const u8 *GetHoldEffectName(enum HoldEffect holdEffect); // const rom data static const u8 sText_Ability[] = _("特性"); @@ -379,7 +378,7 @@ static const struct ListMenuItem sVolatileStatusListItems[] = {COMPOUND_STRING("锁定"), VOLATILE_LOCK_ON}, {COMPOUND_STRING("终焉之歌"), VOLATILE_PERISH_SONG}, {COMPOUND_STRING("变小"), VOLATILE_MINIMIZE}, - {COMPOUND_STRING("充电"), VOLATILE_CHARGE}, + {COMPOUND_STRING("充电"), VOLATILE_CHARGE_TIMER}, {COMPOUND_STRING("扎根"), VOLATILE_ROOT}, {COMPOUND_STRING("哈欠"), VOLATILE_YAWN}, {COMPOUND_STRING("封印"), VOLATILE_IMPRISON}, @@ -719,17 +718,27 @@ void CB2_BattleDebugMenu(void) } } +enum { + COLORID_RED, +}; + +static const u8 sTextColorTable[][3] = +{ + [COLORID_RED] = {TEXT_COLOR_WHITE, TEXT_COLOR_RED, TEXT_COLOR_LIGHT_RED}, +}; + static void PutMovesPointsText(struct BattleDebugMenu *data) { - u32 i, j, count, battlerDef; + u32 i, j, count, battlerDef, chosenMoveIndex = gAiBattleData->chosenMoveIndex[data->aiBattlerId]; u8 *text = Alloc(0x50); FillWindowPixelBuffer(data->aiMovesWindowId, 0x11); + AddTextPrinterParameterized(data->aiMovesWindowId, FONT_NORMAL, COMPOUND_STRING("Score/Dmg"), 3, 0, 0, NULL); for (i = 0; i < MAX_MON_MOVES; i++) { text[0] = CHAR_SPACE; StringCopy(text + 1, GetMoveName(gBattleMons[data->aiBattlerId].moves[i])); - AddTextPrinterParameterized(data->aiMovesWindowId, FONT_NORMAL, text, 0, i * 15, 0, NULL); + AddTextPrinterParameterized(data->aiMovesWindowId, FONT_NORMAL, text, 0, (i * 15) + 15, 0, NULL); for (count = 0, j = 0; j < MAX_BATTLERS_COUNT; j++) { if (data->spriteIds.aiIconSpriteIds[j] == 0xFF) @@ -738,12 +747,24 @@ static void PutMovesPointsText(struct BattleDebugMenu *data) ConvertIntToDecimalStringN(text, gAiBattleData->finalScore[data->aiBattlerId][battlerDef][i], STR_CONV_MODE_RIGHT_ALIGN, 3); - AddTextPrinterParameterized(data->aiMovesWindowId, FONT_NORMAL, text, 83 + count * 54, i * 15, 0, NULL); + // If chosen move and chosen target + if ((chosenMoveIndex == i) && (gAiBattleData->chosenTarget[data->aiBattlerId] == j) && !(gAiLogicData->shouldSwitch & (1u << data->aiBattlerId))) + AddTextPrinterParameterized3(data->aiMovesWindowId, FONT_NORMAL, 84 + count * 54, (i * 15) + 15, sTextColorTable[COLORID_RED], 0, text); + else + AddTextPrinterParameterized(data->aiMovesWindowId, FONT_NORMAL, text, 84 + count * 54, (i * 15) + 15, 0, NULL); + + if ((chosenMoveIndex == i) && (gAiBattleData->chosenTarget[data->aiBattlerId] == j) && !(gAiLogicData->shouldSwitch & (1u << data->aiBattlerId))) + AddTextPrinterParameterized3(data->aiMovesWindowId, FONT_NORMAL, 103 + count * 54, (i * 15) + 15, sTextColorTable[COLORID_RED], 0, COMPOUND_STRING("/")); + else + AddTextPrinterParameterized(data->aiMovesWindowId, FONT_NORMAL, COMPOUND_STRING("/"), 103 + count * 54, (i * 15) + 15, 0, NULL); ConvertIntToDecimalStringN(text, AI_GetDamage(data->aiBattlerId, battlerDef, i, AI_ATTACKING, gAiLogicData), - STR_CONV_MODE_RIGHT_ALIGN, 3); - AddTextPrinterParameterized(data->aiMovesWindowId, FONT_NORMAL, text, 110 + count * 54, i * 15, 0, NULL); + STR_CONV_MODE_LEADING_ZEROS, 3); + if ((chosenMoveIndex == i) && (gAiBattleData->chosenTarget[data->aiBattlerId] == j) && !(gAiLogicData->shouldSwitch & (1u << data->aiBattlerId))) + AddTextPrinterParameterized3(data->aiMovesWindowId, FONT_NORMAL, 110 + count * 54, (i * 15) + 15, sTextColorTable[COLORID_RED], 0, text); + else + AddTextPrinterParameterized(data->aiMovesWindowId, FONT_NORMAL, text, 110 + count * 54, (i * 15) + 15, 0, NULL); count++; } @@ -751,15 +772,10 @@ static void PutMovesPointsText(struct BattleDebugMenu *data) if (gAiLogicData->shouldSwitch & (1u << data->aiBattlerId)) { - u32 switchMon = GetMonData(&gEnemyParty[gAiLogicData->mostSuitableMonId[data->aiBattlerId]], MON_DATA_SPECIES); - AddTextPrinterParameterized(data->aiMovesWindowId, FONT_NORMAL, COMPOUND_STRING("替换为"), 74, 64, 0, NULL); - AddTextPrinterParameterized(data->aiMovesWindowId, FONT_NORMAL, gSpeciesInfo[switchMon].speciesName, 74 + 68, 64, 0, NULL); - } - else - { - u32 chosenMoveIndex = gAiBattleData->chosenMoveIndex[data->aiBattlerId]; - AddTextPrinterParameterized(data->aiMovesWindowId, FONT_NORMAL, COMPOUND_STRING("Chosen move: "), 74, 64, 0, NULL); - AddTextPrinterParameterized(data->aiMovesWindowId, FONT_NORMAL, GetMoveName(gBattleMons[data->aiBattlerId].moves[chosenMoveIndex]), 74 + 68, 64, 0, NULL); + struct Pokemon *party = GetBattlerParty(data->aiBattlerId); + u32 switchMon = GetMonData(&party[gAiLogicData->mostSuitableMonId[data->aiBattlerId]], MON_DATA_SPECIES); + AddTextPrinterParameterized3(data->aiMovesWindowId, FONT_NORMAL, 74, 79, sTextColorTable[COLORID_RED], 0, COMPOUND_STRING("替换为")); + AddTextPrinterParameterized3(data->aiMovesWindowId, FONT_NORMAL, 74 + 68, 79, sTextColorTable[COLORID_RED], 0, gSpeciesInfo[switchMon].speciesName); } CopyWindowToVram(data->aiMovesWindowId, COPYWIN_FULL); @@ -811,7 +827,7 @@ static void Task_ShowAiPoints(u8 taskId) { data->spriteIds.aiIconSpriteIds[i] = CreateMonIcon(gBattleMons[i].species, SpriteCallbackDummy, - 95 + (count * 60), 17, 0, 0); + 106 + (count * 54), 17, 0, 0); gSprites[data->spriteIds.aiIconSpriteIds[i]].data[0] = i; // battler id count++; } @@ -826,7 +842,7 @@ static void Task_ShowAiPoints(u8 taskId) GetMonData(mon, MON_DATA_IS_SHINY), gBattleMons[data->aiBattlerId].personality, TRUE, - 39, 130, 15, TAG_NONE); + 39, 135, 15, TAG_NONE); data->aiViewState++; break; // Put text @@ -902,8 +918,8 @@ static void PutAiInfoText(struct BattleDebugMenu *data) { if (IsOnPlayerSide(i) && IsBattlerAlive(i)) { - u16 ability = gAiLogicData->abilities[i]; - enum ItemHoldEffect holdEffect = gAiLogicData->holdEffects[i]; + enum Ability ability = gAiLogicData->abilities[i]; + enum HoldEffect holdEffect = gAiLogicData->holdEffects[i]; u16 item = gAiLogicData->items[i]; u8 x = (i == B_POSITION_PLAYER_LEFT) ? 83 + (i) * 75 : 83 + (i-1) * 75; AddTextPrinterParameterized(data->aiMovesWindowId, FONT_SMALL, gAbilitiesInfo[ability].name, x, 0, 0, NULL); @@ -1478,7 +1494,7 @@ static void PrintSecondaryEntries(struct BattleDebugMenu *data) case LIST_ITEM_TYPES: for (i = 0; i < 3; i++) { - u8 *types = &gBattleMons[data->battlerId].types[0]; + enum Type *types = &gBattleMons[data->battlerId].types[0]; PadString(gTypesInfo[types[i]].name, text); printer.currentY = printer.y = (i * yMultiplier) + sSecondaryListTemplate.upText_Y; @@ -2141,7 +2157,7 @@ static void UpdateMonData(struct BattleDebugMenu *data) static const u8 *const sHoldEffectNames[HOLD_EFFECT_COUNT] = { - [HOLD_EFFECT_NONE] = COMPOUND_STRING("不眠"), + [HOLD_EFFECT_NONE] = COMPOUND_STRING("???"), [HOLD_EFFECT_RESTORE_HP] = COMPOUND_STRING("回复HP"), [HOLD_EFFECT_CURE_PAR] = COMPOUND_STRING("麻痹解除"), [HOLD_EFFECT_CURE_SLP] = COMPOUND_STRING("睡眠解除"), @@ -2254,7 +2270,7 @@ static const u8 *const sHoldEffectNames[HOLD_EFFECT_COUNT] = [HOLD_EFFECT_PRIMAL_ORB] = COMPOUND_STRING("原始回归宝珠"), [HOLD_EFFECT_PROTECTIVE_PADS] = COMPOUND_STRING("部位护具"), [HOLD_EFFECT_TERRAIN_EXTENDER] = COMPOUND_STRING("大地膜"), - [HOLD_EFFECT_SEEDS] = COMPOUND_STRING("场地种子"), + [HOLD_EFFECT_TERRAIN_SEED] = COMPOUND_STRING("场地种子"), [HOLD_EFFECT_ADRENALINE_ORB] = COMPOUND_STRING("胆怯球"), [HOLD_EFFECT_MEMORY] = COMPOUND_STRING("属性存储碟"), [HOLD_EFFECT_Z_CRYSTAL] = COMPOUND_STRING("Z纯晶"), @@ -2274,7 +2290,8 @@ static const u8 *const sHoldEffectNames[HOLD_EFFECT_COUNT] = [HOLD_EFFECT_OGERPON_MASK] = COMPOUND_STRING("厄诡椪面具"), [HOLD_EFFECT_BERSERK_GENE] = COMPOUND_STRING("破坏基因"), }; -static const u8 *GetHoldEffectName(enum ItemHoldEffect holdEffect) + +static const u8 *GetHoldEffectName(enum HoldEffect holdEffect) { if (sHoldEffectNames[holdEffect] == NULL) return sHoldEffectNames[0]; diff --git a/src/battle_dome.c b/src/battle_dome.c index 68bd6af252..df96737f8d 100644 --- a/src/battle_dome.c +++ b/src/battle_dome.c @@ -2136,9 +2136,8 @@ static void InitDomeTrainers(void) static void CalcDomeMonStats(const struct TrainerMon *fmon, int level, u8 ivs, int *stats) { int evs[NUM_STATS]; - int i; - for (i = 0; i < NUM_STATS; i++) + for (enum Stat i = 0; i < NUM_STATS; i++) { if (fmon->ev != NULL) evs[i] = fmon->ev[i]; @@ -2393,8 +2392,9 @@ static int SelectOpponentMonsFromParty(int *partyMovePoints, bool8 allowRandom) static int GetTypeEffectivenessPoints(int move, int targetSpecies, int mode) { - int defType1, defType2, defAbility, moveType; + enum Type defType1, defType2, moveType; int typePower = TYPE_x1; + enum Ability defAbility; if (move == MOVE_NONE || move == MOVE_UNAVAILABLE || IsBattleMoveStatus(move)) return 0; @@ -5141,7 +5141,7 @@ static u16 GetWinningMove(int winnerTournamentId, int loserTournamentId, u8 roun { u32 personality = 0; u32 targetSpecies = 0; - u32 targetAbility = 0; + enum Ability targetAbility = 0; uq4_12_t typeMultiplier = 0; do { diff --git a/src/battle_dynamax.c b/src/battle_dynamax.c index c6e91742e8..d5edbc0e61 100644 --- a/src/battle_dynamax.c +++ b/src/battle_dynamax.c @@ -19,7 +19,6 @@ #include "constants/battle_move_effects.h" #include "constants/battle_string_ids.h" #include "constants/flags.h" -#include "constants/hold_effects.h" #include "constants/items.h" #include "constants/moves.h" @@ -28,7 +27,7 @@ static u32 GetMaxPowerTier(u32 move); struct GMaxMove { u16 species; - u8 moveType; + enum Type moveType; u16 gmaxMove; }; @@ -66,15 +65,15 @@ static const struct GMaxMove sGMaxMoveTable[] = {SPECIES_ALCREMIE_GMAX, TYPE_FAIRY, MOVE_G_MAX_FINALE}, {SPECIES_COPPERAJAH_GMAX, TYPE_STEEL, MOVE_G_MAX_STEELSURGE}, {SPECIES_DURALUDON_GMAX, TYPE_DRAGON, MOVE_G_MAX_DEPLETION}, - {SPECIES_URSHIFU_SINGLE_STRIKE_GMAX,TYPE_DARK, MOVE_G_MAX_ONE_BLOW}, - {SPECIES_URSHIFU_RAPID_STRIKE_GMAX, TYPE_WATER, MOVE_G_MAX_RAPID_FLOW}, + {SPECIES_URSHIFU_SINGLE_STRIKE_GMAX, TYPE_DARK, MOVE_G_MAX_ONE_BLOW}, + {SPECIES_URSHIFU_RAPID_STRIKE_GMAX, TYPE_WATER, MOVE_G_MAX_RAPID_FLOW}, }; // Returns whether a battler can Dynamax. bool32 CanDynamax(u32 battler) { u16 species = GetBattlerVisualSpecies(battler); - enum ItemHoldEffect holdEffect = GetBattlerHoldEffect(battler, FALSE); + enum HoldEffect holdEffect = GetBattlerHoldEffectIgnoreNegation(battler); // Prevents Zigzagoon from dynamaxing in vanilla. if (gBattleTypeFlags & BATTLE_TYPE_FIRST_BATTLE && !IsOnPlayerSide(battler)) @@ -178,7 +177,7 @@ void ActivateDynamax(u32 battler) // Set appropriate use flags. SetActiveGimmick(battler, GIMMICK_DYNAMAX); SetGimmickAsActivated(battler, GIMMICK_DYNAMAX); - gBattleStruct->dynamax.dynamaxTurns[battler] = gBattleTurnCounter + DYNAMAX_TURNS_COUNT; + gBattleStruct->dynamax.dynamaxTurns[battler] = DYNAMAX_TURNS_COUNT; // Substitute is removed upon Dynamaxing. gBattleMons[battler].volatiles.substitute = FALSE; @@ -234,22 +233,7 @@ bool32 IsMoveBlockedByMaxGuard(u32 move) return FALSE; } -// Weight-based moves (and some other moves in Raids) are blocked by Dynamax. -bool32 IsMoveBlockedByDynamax(u32 move) -{ - // TODO: Certain moves are banned in raids. - switch (GetMoveEffect(move)) - { - case EFFECT_HEAT_CRASH: - case EFFECT_LOW_KICK: - return TRUE; - default: - break; - } - return FALSE; -} - -static u16 GetTypeBasedMaxMove(u32 battler, u32 type) +static u16 GetTypeBasedMaxMove(u32 battler, enum Type type) { // Gigantamax check u32 i; @@ -280,7 +264,7 @@ static u16 GetTypeBasedMaxMove(u32 battler, u32 type) // Returns the appropriate Max Move or G-Max Move for a battler to use. u16 GetMaxMove(u32 battler, u32 baseMove) { - u32 moveType; + enum Type moveType; SetTypeBeforeUsingMove(baseMove, battler); moveType = GetBattleMoveType(baseMove); @@ -333,7 +317,7 @@ u32 GetMaxMovePower(u32 move) } tier = GetMaxPowerTier(move); - u32 moveType = GetMoveType(move); + enum Type moveType = GetMoveType(move); if (moveType == TYPE_FIGHTING || moveType == TYPE_POISON || move == MOVE_MULTI_ATTACK) @@ -453,7 +437,7 @@ bool32 IsMaxMove(u32 move) } // Assigns the multistring to use for the "Damage Non- Types" G-Max effect. -void ChooseDamageNonTypesString(u8 type) +void ChooseDamageNonTypesString(enum Type type) { switch (type) { @@ -469,6 +453,8 @@ void ChooseDamageNonTypesString(u8 type) case TYPE_ROCK: gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SURROUNDED_BY_ROCKS; break; + default: + break; } } diff --git a/src/battle_end_turn.c b/src/battle_end_turn.c index 62a8f67006..ca4c46fa11 100644 --- a/src/battle_end_turn.c +++ b/src/battle_end_turn.c @@ -1,5 +1,6 @@ #include "global.h" #include "battle.h" +#include "battle_hold_effects.h" #include "battle_util.h" #include "battle_controllers.h" #include "battle_ai_util.h" @@ -7,100 +8,10 @@ #include "battle_scripts.h" #include "constants/battle.h" #include "constants/battle_string_ids.h" -#include "constants/hold_effects.h" #include "constants/abilities.h" #include "constants/items.h" #include "constants/moves.h" -// General End Turn Effects based on research from smogon from vanilla games: -// https://www.smogon.com/forums/threads/sword-shield-battle-mechanics-research.3655528/page-64#post-9244179 -enum EndTurnResolutionOrder -{ - ENDTURN_ORDER, - ENDTURN_VARIOUS, - ENDTURN_WEATHER, - ENDTURN_WEATHER_DAMAGE, - ENDTURN_GEN_3_BERRY_ACTIVATION, - ENDTURN_EMERGENCY_EXIT_1, - ENDTURN_AFFECTION, - ENDTURN_FUTURE_SIGHT, - ENDTURN_WISH, - ENDTURN_FIRST_EVENT_BLOCK, - ENDTURN_EMERGENCY_EXIT_2, - ENDTURN_AQUA_RING, - ENDTURN_INGRAIN, - ENDTURN_LEECH_SEED, - ENDTURN_POISON, - ENDTURN_BURN, - ENDTURN_FROSTBITE, - ENDTURN_NIGHTMARE, - ENDTURN_CURSE, - ENDTURN_WRAP, - ENDTURN_SALT_CURE, - ENDTURN_OCTOLOCK, - ENDTURN_SYRUP_BOMB, - ENDTURN_TAUNT, - ENDTURN_TORMENT, - ENDTURN_ENCORE, - ENDTURN_DISABLE, - ENDTURN_MAGNET_RISE, - ENDTURN_TELEKINESIS, - ENDTURN_HEAL_BLOCK, - ENDTURN_EMBARGO, - ENDTURN_YAWN, - ENDTURN_PERISH_SONG, - ENDTURN_ROOST, - ENDTURN_EMERGENCY_EXIT_3, - ENDTURN_SECOND_EVENT_BLOCK, - ENDTURN_TRICK_ROOM, - ENDTURN_GRAVITY, - ENDTURN_WATER_SPORT, - ENDTURN_MUD_SPORT, - ENDTURN_WONDER_ROOM, - ENDTURN_MAGIC_ROOM, - ENDTURN_TERRAIN, - ENDTURN_THIRD_EVENT_BLOCK, - ENDTURN_EMERGENCY_EXIT_4, - ENDTURN_FORM_CHANGE_ABILITIES, - ENDTURN_EJECT_PACK, - ENDTURN_DYNAMAX, - ENDTURN_COUNT, -}; - -// Block that handles effects for each individual battler on the field (eg residual damage) -enum FirstEventBlock -{ - FIRST_EVENT_BLOCK_GMAX_MOVE_RESIDUAL, // Needs to be split - FIRST_EVENT_BLOCK_SEA_OF_FIRE_DAMAGE, - FIRST_EVENT_BLOCK_THRASH, // Thrash isn't handled here in vanilla but for now it is that best place for it. - FIRST_EVENT_BLOCK_GRASSY_TERRAIN_HEAL, - FIRST_EVENT_BLOCK_ABILITIES, - FIRST_EVENT_BLOCK_HEAL_ITEMS, -}; - -// Block that tries to remove side statuses -enum SecondEventBlock -{ - SECOND_EVENT_BLOCK_REFLECT, - SECOND_EVENT_BLOCK_LIGHT_SCREEN, - SECOND_EVENT_BLOCK_SAFEGUARD, - SECOND_EVENT_BLOCK_MIST, - SECOND_EVENT_BLOCK_TAILWIND, - SECOND_EVENT_BLOCK_LUCKY_CHANT, - SECOND_EVENT_BLOCK_RAINBOW, - SECOND_EVENT_BLOCK_SEA_OF_FIRE, - SECOND_EVENT_BLOCK_SWAMP, - SECOND_EVENT_BLOCK_AURORA_VEIL, -}; - -// Block that handles Uproar, items and non-form changing abilities -enum ThirdEventBlock -{ - THIRD_EVENT_BLOCK_UPROAR, - THIRD_EVENT_BLOCK_ABILITIES, - THIRD_EVENT_BLOCK_ITEMS, -}; - static u32 GetBattlerSideForMessage(u32 side) { u32 battler = 0; @@ -119,7 +30,7 @@ static bool32 HandleEndTurnOrder(u32 battler) bool32 effect = FALSE; gBattleTurnCounter++; - gBattleStruct->endTurnEventsCounter++; + gBattleStruct->eventState.endTurn++; for (u32 i = 0; i < gBattlersCount; i++) gBattlerByTurnOrder[i] = i; @@ -133,29 +44,32 @@ static bool32 HandleEndTurnVarious(u32 battler) u32 i; bool32 effect = FALSE; - gBattleStruct->endTurnEventsCounter++; + gBattleStruct->eventState.endTurn++; - if (gFieldStatuses & STATUS_FIELD_FAIRY_LOCK && gFieldTimers.fairyLockTimer == gBattleTurnCounter) + if (gFieldTimers.fairyLockTimer > 0 && --gFieldTimers.fairyLockTimer == 0) gFieldStatuses &= ~STATUS_FIELD_FAIRY_LOCK; for (i = 0; i < NUM_BATTLE_SIDES; i++) { - if (gSideStatuses[i] & SIDE_STATUS_DAMAGE_NON_TYPES && gSideTimers[i].damageNonTypesTimer == gBattleTurnCounter) + if (gSideTimers[i].damageNonTypesTimer > 0 && --gSideTimers[i].damageNonTypesTimer == 0) gSideStatuses[i] &= ~SIDE_STATUS_DAMAGE_NON_TYPES; } for (i = 0; i < gBattlersCount; i++) { + if (gDisableStructs[i].throatChopTimer > 0) + gDisableStructs[i].throatChopTimer--; + if (gBattleMons[i].volatiles.lockOn > 0) gBattleMons[i].volatiles.lockOn--; - if (gDisableStructs[i].chargeTimer && --gDisableStructs[i].chargeTimer == 0) - gBattleMons[i].volatiles.charge = FALSE; + if (B_CHARGE < GEN_9 && gBattleMons[i].volatiles.chargeTimer > 0) + gBattleMons[i].volatiles.chargeTimer--; - if (gBattleMons[i].volatiles.laserFocus && gDisableStructs[i].laserFocusTimer == gBattleTurnCounter) + if (gDisableStructs[i].laserFocusTimer > 0 && --gDisableStructs[i].laserFocusTimer == 0) gBattleMons[i].volatiles.laserFocus = FALSE; - gBattleStruct->hpBefore[i] = gBattleMons[i].hp; + gBattleStruct->battlerState[i].wasAboveHalfHp = gBattleMons[i].hp > gBattleMons[i].maxHP / 2; } if (gBattleStruct->incrementEchoedVoice) @@ -174,7 +88,7 @@ static bool32 HandleEndTurnVarious(u32 battler) static bool32 HandleEndTurnWeather(u32 battler) { - gBattleStruct->endTurnEventsCounter++; + gBattleStruct->eventState.endTurn++; return EndOrContinueWeather(); } @@ -182,18 +96,18 @@ static bool32 HandleEndTurnWeatherDamage(u32 battler) { bool32 effect = FALSE; - u32 ability = GetBattlerAbility(battler); + enum Ability ability = GetBattlerAbility(battler); u32 currBattleWeather = GetCurrentBattleWeather(); if (currBattleWeather == 0xFF) { // If there is no weather on the field, no need to check other battlers so go to next state - gBattleStruct->turnEffectsBattlerId = 0; - gBattleStruct->endTurnEventsCounter++; + gBattleStruct->eventState.endTurnBattler = 0; + gBattleStruct->eventState.endTurn++; return effect; } - gBattleStruct->turnEffectsBattlerId++; + gBattleStruct->eventState.endTurnBattler++; if (!IsBattlerAlive(battler) || !HasWeatherEffect()) return effect; @@ -229,12 +143,10 @@ static bool32 HandleEndTurnWeatherDamage(u32 battler) && !IS_BATTLER_ANY_TYPE(battler, TYPE_ROCK, TYPE_GROUND, TYPE_STEEL) && gBattleMons[battler].volatiles.semiInvulnerable != STATE_UNDERGROUND && gBattleMons[battler].volatiles.semiInvulnerable != STATE_UNDERWATER - && GetBattlerHoldEffect(battler, TRUE) != HOLD_EFFECT_SAFETY_GOGGLES + && GetBattlerHoldEffect(battler) != HOLD_EFFECT_SAFETY_GOGGLES && !IsAbilityAndRecord(battler, ability, ABILITY_MAGIC_GUARD)) { - gBattleStruct->moveDamage[battler] = GetNonDynamaxMaxHP(battler) / 16; - if (gBattleStruct->moveDamage[battler] == 0) - gBattleStruct->moveDamage[battler] = 1; + SetPassiveDamageAmount(battler, GetNonDynamaxMaxHP(battler) / 16); gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SANDSTORM; BattleScriptExecute(BattleScript_DamagingWeather); effect = TRUE; @@ -254,12 +166,10 @@ static bool32 HandleEndTurnWeatherDamage(u32 battler) && !IS_BATTLER_OF_TYPE(battler, TYPE_ICE) && gBattleMons[battler].volatiles.semiInvulnerable != STATE_UNDERGROUND && gBattleMons[battler].volatiles.semiInvulnerable != STATE_UNDERWATER - && GetBattlerHoldEffect(battler, TRUE) != HOLD_EFFECT_SAFETY_GOGGLES + && GetBattlerHoldEffect(battler) != HOLD_EFFECT_SAFETY_GOGGLES && !IsAbilityAndRecord(battler, ability, ABILITY_MAGIC_GUARD)) { - gBattleStruct->moveDamage[battler] = GetNonDynamaxMaxHP(battler) / 16; - if (gBattleStruct->moveDamage[battler] == 0) - gBattleStruct->moveDamage[battler] = 1; + SetPassiveDamageAmount(battler, GetNonDynamaxMaxHP(battler) / 16); gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_HAIL; BattleScriptExecute(BattleScript_DamagingWeather); effect = TRUE; @@ -271,48 +181,24 @@ static bool32 HandleEndTurnWeatherDamage(u32 battler) return effect; } -static bool32 HandleEndTurnGenThreeBerryActivation(u32 battler) -{ - bool32 effect = FALSE; - - if (B_HP_BERRIES >= GEN_4) // Skip handler for > Gen3 - { - gBattleStruct->endTurnEventsCounter++; - return effect; - } - gBattleStruct->turnEffectsBattlerId++; - effect = TryRestoreHPBerries(battler, ITEMEFFECT_NORMAL); - return effect; -} - static bool32 HandleEndTurnEmergencyExit(u32 battler) { bool32 effect = FALSE; - u32 ability = GetBattlerAbility(battler); + enum Ability ability = GetBattlerAbility(battler); - gBattleStruct->turnEffectsBattlerId++; + gBattleStruct->eventState.endTurnBattler++; - if (ability == ABILITY_EMERGENCY_EXIT || ability == ABILITY_WIMP_OUT) + if (EmergencyExitCanBeTriggered(battler)) { - u32 cutoff = gBattleMons[battler].maxHP / 2; - bool32 HadMoreThanHalfHpNowDoesnt = gBattleStruct->hpBefore[battler] > cutoff && gBattleMons[battler].hp <= cutoff; + gBattlerAbility = battler; + gLastUsedAbility = ability; - if (HadMoreThanHalfHpNowDoesnt - && IsBattlerAlive(battler) - && (CanBattlerSwitch(battler) || !(gBattleTypeFlags & BATTLE_TYPE_TRAINER)) - && !(gBattleTypeFlags & BATTLE_TYPE_ARENA) - && gBattleMons[battler].volatiles.semiInvulnerable != STATE_SKY_DROP) // Not currently held by Sky Drop - { - gBattlerAbility = battler; - gLastUsedAbility = ability; + if (gBattleTypeFlags & BATTLE_TYPE_TRAINER) + BattleScriptExecute(BattleScript_EmergencyExitEnd2); + else + BattleScriptExecute(BattleScript_EmergencyExitWildEnd2); - if (gBattleTypeFlags & BATTLE_TYPE_TRAINER) - BattleScriptExecute(BattleScript_EmergencyExitEnd2); - else - BattleScriptExecute(BattleScript_EmergencyExitWildEnd2); - - effect = TRUE; - } + effect = TRUE; } return effect; @@ -322,7 +208,7 @@ static bool32 HandleEndTurnAffection(u32 battler) { bool32 effect = FALSE; - gBattleStruct->turnEffectsBattlerId++; + gBattleStruct->eventState.endTurnBattler++; if (!B_AFFECTION_MECHANICS || !IsBattlerAlive(battler) @@ -345,16 +231,10 @@ static bool32 HandleEndTurnFutureSight(u32 battler) { bool32 effect = FALSE; - gBattleStruct->turnEffectsBattlerId++; + gBattleStruct->eventState.endTurnBattler++; - if (gWishFutureKnock.futureSightCounter[battler] == gBattleTurnCounter) + if (gWishFutureKnock.futureSightCounter[battler] > 0 && --gWishFutureKnock.futureSightCounter[battler] == 0) { - if (gWishFutureKnock.futureSightCounter[battler] == gBattleTurnCounter - && gWishFutureKnock.futureSightCounter[BATTLE_PARTNER(battler)] <= gBattleTurnCounter) - { - gSideStatuses[GetBattlerSide(battler)] &= ~SIDE_STATUS_FUTUREATTACK; - } - if (!IsBattlerAlive(battler)) return effect; @@ -383,25 +263,26 @@ static bool32 HandleEndTurnWish(u32 battler) { bool32 effect = FALSE; - gBattleStruct->turnEffectsBattlerId++; + gBattleStruct->eventState.endTurnBattler++; - if (gWishFutureKnock.wishCounter[battler] == gBattleTurnCounter && IsBattlerAlive(battler)) + if (gWishFutureKnock.wishCounter[battler] > 0 && --gWishFutureKnock.wishCounter[battler] == 0 && IsBattlerAlive(battler)) { + s32 wishHeal = 0; gBattlerTarget = battler; PREPARE_MON_NICK_WITH_PREFIX_BUFFER(gBattleTextBuff1, battler, gWishFutureKnock.wishPartyId[battler]) - if (B_WISH_HP_SOURCE >= GEN_5) + if (GetConfig(CONFIG_WISH_HP_SOURCE) >= GEN_5) { if (IsOnPlayerSide(battler)) - gBattleStruct->moveDamage[battler] = max(1, GetMonData(&gPlayerParty[gWishFutureKnock.wishPartyId[battler]], MON_DATA_MAX_HP) / 2); + wishHeal = GetMonData(&gPlayerParty[gWishFutureKnock.wishPartyId[battler]], MON_DATA_MAX_HP) / 2; else - gBattleStruct->moveDamage[battler] = max(1, GetMonData(&gEnemyParty[gWishFutureKnock.wishPartyId[battler]], MON_DATA_MAX_HP) / 2); + wishHeal = GetMonData(&gEnemyParty[gWishFutureKnock.wishPartyId[battler]], MON_DATA_MAX_HP) / 2; } else { - gBattleStruct->moveDamage[battler] = max(1, GetNonDynamaxMaxHP(battler) / 2); + wishHeal = GetNonDynamaxMaxHP(battler) / 2; } - gBattleStruct->moveDamage[battler] *= -1; + SetHealAmount(battler, wishHeal); if (gBattleMons[battler].volatiles.healBlock) BattleScriptExecute(BattleScript_WishButHealBlocked); else if (gBattleMons[battler].hp == gBattleMons[battler].maxHP) @@ -418,39 +299,43 @@ static bool32 HandleEndTurnWish(u32 battler) static bool32 HandleEndTurnFirstEventBlock(u32 battler) { bool32 effect = FALSE; - u32 side; - switch (gBattleStruct->eventBlockCounter) + if (!IsBattlerAlive(battler)) + { + gBattleStruct->eventState.endTurnBlock = 0; + gBattleStruct->eventState.endTurnBattler++; + return effect; + } + + switch (gBattleStruct->eventState.endTurnBlock) { case FIRST_EVENT_BLOCK_GMAX_MOVE_RESIDUAL: // TODO: Has to be split into 3 statuses and needs a queue side = GetBattlerSide(battler); if (gSideStatuses[side] & SIDE_STATUS_DAMAGE_NON_TYPES) { - if (IsBattlerAlive(battler) - && !IS_BATTLER_OF_TYPE(battler, gSideTimers[side].damageNonTypesType) + if (!IS_BATTLER_OF_TYPE(battler, gSideTimers[side].damageNonTypesType) && !IsAbilityAndRecord(battler, GetBattlerAbility(battler), ABILITY_MAGIC_GUARD)) { - gBattlerAttacker = battler; - gBattleStruct->moveDamage[battler] = GetNonDynamaxMaxHP(battler) / 6; + SetPassiveDamageAmount(battler, GetNonDynamaxMaxHP(battler) / 6); ChooseDamageNonTypesString(gSideTimers[side].damageNonTypesType); BattleScriptExecute(BattleScript_DamageNonTypesContinues); effect = TRUE; } } - gBattleStruct->eventBlockCounter++; + gBattleStruct->eventState.endTurnBlock++; break; case FIRST_EVENT_BLOCK_SEA_OF_FIRE_DAMAGE: - if (gSideStatuses[GetBattlerSide(battler)] & SIDE_STATUS_SEA_OF_FIRE && IsBattlerAlive(battler)) + if (gSideStatuses[GetBattlerSide(battler)] & SIDE_STATUS_SEA_OF_FIRE) { gBattlerAttacker = battler; - gBattleStruct->moveDamage[battler] = GetNonDynamaxMaxHP(battler) / 8; + SetPassiveDamageAmount(battler, GetNonDynamaxMaxHP(battler) / 8); BtlController_EmitStatusAnimation(battler, B_COMM_TO_CONTROLLER, FALSE, STATUS1_BURN); MarkBattlerForControllerExec(battler); BattleScriptExecute(BattleScript_HurtByTheSeaOfFire); effect = TRUE; } - gBattleStruct->eventBlockCounter++; + gBattleStruct->eventState.endTurnBlock++; break; case FIRST_EVENT_BLOCK_THRASH: if (gBattleMons[battler].volatiles.lockConfusionTurns && gBattleMons[battler].volatiles.semiInvulnerable != STATE_SKY_DROP) @@ -465,36 +350,31 @@ static bool32 HandleEndTurnFirstEventBlock(u32 battler) gBattleMons[battler].volatiles.multipleTurns = FALSE; if (!gBattleMons[battler].volatiles.confusionTurns) { - gBattleScripting.moveEffect = MOVE_EFFECT_CONFUSION; - SetMoveEffect(battler, battler, TRUE, FALSE); + SetMoveEffect(battler, battler, MOVE_EFFECT_CONFUSION, gBattlescriptCurrInstr, EFFECT_PRIMARY); if (gBattleMons[battler].volatiles.confusionTurns) BattleScriptExecute(BattleScript_ThrashConfuses); effect = TRUE; } } } - gBattleStruct->eventBlockCounter++; + gBattleStruct->eventState.endTurnBlock++; break; case FIRST_EVENT_BLOCK_GRASSY_TERRAIN_HEAL: if (gFieldStatuses & STATUS_FIELD_GRASSY_TERRAIN - && IsBattlerAlive(battler) && !IsBattlerAtMaxHp(battler) && !gBattleMons[battler].volatiles.healBlock && !IsSemiInvulnerable(battler, CHECK_ALL) - && IsBattlerGrounded(battler)) + && IsBattlerGrounded(battler, GetBattlerAbility(battler), GetBattlerHoldEffect(battler))) { - gBattlerAttacker = battler; - gBattleStruct->moveDamage[battler] = -(GetNonDynamaxMaxHP(battler) / 16); - if (gBattleStruct->moveDamage[battler] == 0) - gBattleStruct->moveDamage[battler] = -1; + SetHealAmount(battler, GetNonDynamaxMaxHP(battler) / 16); BattleScriptExecute(BattleScript_GrassyTerrainHeals); effect = TRUE; } - gBattleStruct->eventBlockCounter++; + gBattleStruct->eventState.endTurnBlock++; break; case FIRST_EVENT_BLOCK_ABILITIES: { - u32 ability = GetBattlerAbility(battler); + enum Ability ability = GetBattlerAbility(battler); switch (ability) { case ABILITY_HEALER: @@ -503,27 +383,18 @@ static bool32 HandleEndTurnFirstEventBlock(u32 battler) if (AbilityBattleEffects(ABILITYEFFECT_ENDTURN, battler, ability, 0, MOVE_NONE)) effect = TRUE; break; - } - gBattleStruct->eventBlockCounter++; - break; - } - case FIRST_EVENT_BLOCK_HEAL_ITEMS: - { - enum ItemHoldEffect holdEffect = GetBattlerHoldEffect(battler, TRUE); - switch (holdEffect) - { - case HOLD_EFFECT_LEFTOVERS: - case HOLD_EFFECT_BLACK_SLUDGE: - if (ItemBattleEffects(ITEMEFFECT_NORMAL, battler)) - effect = TRUE; - break; default: break; } - gBattleStruct->eventBlockCounter = 0; - gBattleStruct->turnEffectsBattlerId++; + gBattleStruct->eventState.endTurnBlock++; break; } + case FIRST_EVENT_BLOCK_HEAL_ITEMS: + if (ItemBattleEffects(battler, 0, GetBattlerHoldEffect(battler), IsLeftoversActivation)) + effect = TRUE; + gBattleStruct->eventState.endTurnBlock = 0; + gBattleStruct->eventState.endTurnBattler++; + break; } return effect; @@ -533,14 +404,14 @@ static bool32 HandleEndTurnAquaRing(u32 battler) { bool32 effect = FALSE; - gBattleStruct->turnEffectsBattlerId++; + gBattleStruct->eventState.endTurnBattler++; if (gBattleMons[battler].volatiles.aquaRing && !gBattleMons[battler].volatiles.healBlock && !IsBattlerAtMaxHp(battler) && IsBattlerAlive(battler)) { - gBattleStruct->moveDamage[battler] = GetDrainedBigRootHp(battler, GetNonDynamaxMaxHP(battler) / 16); + SetHealAmount(battler, GetDrainedBigRootHp(battler, GetNonDynamaxMaxHP(battler) / 16)); BattleScriptExecute(BattleScript_AquaRingHeal); effect = TRUE; } @@ -552,14 +423,14 @@ static bool32 HandleEndTurnIngrain(u32 battler) { bool32 effect = FALSE; - gBattleStruct->turnEffectsBattlerId++; + gBattleStruct->eventState.endTurnBattler++; if (gBattleMons[battler].volatiles.root && !gBattleMons[battler].volatiles.healBlock && !IsBattlerAtMaxHp(battler) && IsBattlerAlive(battler)) { - gBattleStruct->moveDamage[battler] = GetDrainedBigRootHp(battler, GetNonDynamaxMaxHP(battler) / 16); + SetHealAmount(battler, GetDrainedBigRootHp(battler, GetNonDynamaxMaxHP(battler) / 16)); BattleScriptExecute(BattleScript_IngrainTurnHeal); effect = TRUE; } @@ -571,7 +442,7 @@ static bool32 HandleEndTurnLeechSeed(u32 battler) { bool32 effect = FALSE; - gBattleStruct->turnEffectsBattlerId++; + gBattleStruct->eventState.endTurnBattler++; if (gBattleMons[battler].volatiles.leechSeed && IsBattlerAlive(gBattleMons[battler].volatiles.leechSeed - 1) @@ -581,12 +452,12 @@ static bool32 HandleEndTurnLeechSeed(u32 battler) gBattlerTarget = gBattleMons[battler].volatiles.leechSeed - 1; // leech seed receiver gBattleScripting.animArg1 = gBattlerTarget; gBattleScripting.animArg2 = gBattlerAttacker; - gBattleStruct->moveDamage[gBattlerAttacker] = max(1, GetNonDynamaxMaxHP(battler) / 8); - gBattleStruct->moveDamage[gBattlerTarget] = GetDrainedBigRootHp(gBattlerTarget, gBattleStruct->moveDamage[gBattlerAttacker]); - gHitMarker |= HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_HP_UPDATE; + s32 drainAmount = GetNonDynamaxMaxHP(gBattlerAttacker) / 8; + s32 healAmount = GetDrainedBigRootHp(gBattlerTarget, drainAmount); if (GetBattlerAbility(battler) == ABILITY_LIQUID_OOZE) { - gBattleStruct->moveDamage[gBattlerTarget] = gBattleStruct->moveDamage[gBattlerTarget] * -1; + SetPassiveDamageAmount(gBattlerAttacker, drainAmount); + SetPassiveDamageAmount(gBattlerTarget, healAmount); gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_LEECH_SEED_OOZE; BattleScriptExecute(BattleScript_LeechSeedTurnDrainLiquidOoze); } @@ -596,6 +467,8 @@ static bool32 HandleEndTurnLeechSeed(u32 battler) } else { + SetPassiveDamageAmount(gBattlerAttacker, drainAmount); + SetHealAmount(gBattlerTarget, healAmount); gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_LEECH_SEED_DRAIN; BattleScriptExecute(BattleScript_LeechSeedTurnDrainRecovery); } @@ -609,9 +482,9 @@ static bool32 HandleEndTurnPoison(u32 battler) { bool32 effect = FALSE; - u32 ability = GetBattlerAbility(battler); + enum Ability ability = GetBattlerAbility(battler); - gBattleStruct->turnEffectsBattlerId++; + gBattleStruct->eventState.endTurnBattler++; if ((gBattleMons[battler].status1 & STATUS1_POISON || gBattleMons[battler].status1 & STATUS1_TOXIC_POISON) && IsBattlerAlive(battler) @@ -621,30 +494,23 @@ static bool32 HandleEndTurnPoison(u32 battler) { if (!IsBattlerAtMaxHp(battler) && !gBattleMons[battler].volatiles.healBlock) { - gBattleStruct->moveDamage[battler] = GetNonDynamaxMaxHP(battler) / 8; - if (gBattleStruct->moveDamage[battler] == 0) - gBattleStruct->moveDamage[battler] = 1; - gBattleStruct->moveDamage[battler] *= -1; + SetHealAmount(battler, GetNonDynamaxMaxHP(battler) / 8); BattleScriptExecute(BattleScript_PoisonHealActivates); effect = TRUE; } } else if (gBattleMons[battler].status1 & STATUS1_TOXIC_POISON) { - gBattleStruct->moveDamage[battler] = GetNonDynamaxMaxHP(battler) / 16; - if (gBattleStruct->moveDamage[battler] == 0) - gBattleStruct->moveDamage[battler] = 1; + SetPassiveDamageAmount(battler, GetNonDynamaxMaxHP(battler) / 16); if ((gBattleMons[battler].status1 & STATUS1_TOXIC_COUNTER) != STATUS1_TOXIC_TURN(15)) // not 16 turns gBattleMons[battler].status1 += STATUS1_TOXIC_TURN(1); - gBattleStruct->moveDamage[battler] *= (gBattleMons[battler].status1 & STATUS1_TOXIC_COUNTER) >> 8; + gBattleStruct->passiveHpUpdate[battler] *= (gBattleMons[battler].status1 & STATUS1_TOXIC_COUNTER) >> 8; BattleScriptExecute(BattleScript_PoisonTurnDmg); effect = TRUE; } else { - gBattleStruct->moveDamage[battler] = GetNonDynamaxMaxHP(battler) / 8; - if (gBattleStruct->moveDamage[battler] == 0) - gBattleStruct->moveDamage[battler] = 1; + SetPassiveDamageAmount(battler, GetNonDynamaxMaxHP(battler) / 8); BattleScriptExecute(BattleScript_PoisonTurnDmg); effect = TRUE; } @@ -657,23 +523,22 @@ static bool32 HandleEndTurnBurn(u32 battler) { bool32 effect = FALSE; - u32 ability = GetBattlerAbility(battler); + enum Ability ability = GetBattlerAbility(battler); - gBattleStruct->turnEffectsBattlerId++; + gBattleStruct->eventState.endTurnBattler++; if (gBattleMons[battler].status1 & STATUS1_BURN && IsBattlerAlive(battler) && !IsAbilityAndRecord(battler, ability, ABILITY_MAGIC_GUARD)) { - gBattleStruct->moveDamage[battler] = GetNonDynamaxMaxHP(battler) / (B_BURN_DAMAGE >= GEN_7 ? 16 : 8); + s32 burnDamage = GetNonDynamaxMaxHP(battler) / (B_BURN_DAMAGE >= GEN_7 ? 16 : 8); if (ability == ABILITY_HEATPROOF) { - if (gBattleStruct->moveDamage[battler] > (gBattleStruct->moveDamage[battler] / 2) + 1) // Record ability if the burn takes less damage than it normally would. + if (burnDamage > (burnDamage / 2) + 1) // Record ability if the burn takes less damage than it normally would. RecordAbilityBattle(battler, ABILITY_HEATPROOF); - gBattleStruct->moveDamage[battler] /= 2; + burnDamage /= 2; } - if (gBattleStruct->moveDamage[battler] == 0) - gBattleStruct->moveDamage[battler] = 1; + SetPassiveDamageAmount(battler, burnDamage); BattleScriptExecute(BattleScript_BurnTurnDmg); effect = TRUE; } @@ -685,15 +550,13 @@ static bool32 HandleEndTurnFrostbite(u32 battler) { bool32 effect = FALSE; - gBattleStruct->turnEffectsBattlerId++; + gBattleStruct->eventState.endTurnBattler++; if (gBattleMons[battler].status1 & STATUS1_FROSTBITE && IsBattlerAlive(battler) && !IsAbilityAndRecord(battler, GetBattlerAbility(battler), ABILITY_MAGIC_GUARD)) { - gBattleStruct->moveDamage[battler] = GetNonDynamaxMaxHP(battler) / (B_BURN_DAMAGE >= GEN_7 ? 16 : 8); - if (gBattleStruct->moveDamage[battler] == 0) - gBattleStruct->moveDamage[battler] = 1; + SetPassiveDamageAmount(battler, GetNonDynamaxMaxHP(battler) / (B_BURN_DAMAGE >= GEN_7 ? 16 : 8)); BattleScriptExecute(BattleScript_FrostbiteTurnDmg); effect = TRUE; } @@ -705,7 +568,7 @@ static bool32 HandleEndTurnNightmare(u32 battler) { bool32 effect = FALSE; - gBattleStruct->turnEffectsBattlerId++; + gBattleStruct->eventState.endTurnBattler++; if (gBattleMons[battler].volatiles.nightmare && IsBattlerAlive(battler) @@ -713,9 +576,7 @@ static bool32 HandleEndTurnNightmare(u32 battler) { if (gBattleMons[battler].status1 & STATUS1_SLEEP) { - gBattleStruct->moveDamage[battler] = GetNonDynamaxMaxHP(battler) / 4; - if (gBattleStruct->moveDamage[battler] == 0) - gBattleStruct->moveDamage[battler] = 1; + SetPassiveDamageAmount(battler, GetNonDynamaxMaxHP(battler) / 4); BattleScriptExecute(BattleScript_NightmareTurnDmg); effect = TRUE; } @@ -732,15 +593,13 @@ static bool32 HandleEndTurnCurse(u32 battler) { bool32 effect = FALSE; - gBattleStruct->turnEffectsBattlerId++; + gBattleStruct->eventState.endTurnBattler++; if (gBattleMons[battler].volatiles.cursed && IsBattlerAlive(battler) && !IsAbilityAndRecord(battler, GetBattlerAbility(battler), ABILITY_MAGIC_GUARD)) { - gBattleStruct->moveDamage[battler] = GetNonDynamaxMaxHP(battler) / 4; - if (gBattleStruct->moveDamage[battler] == 0) - gBattleStruct->moveDamage[battler] = 1; + SetPassiveDamageAmount(battler, GetNonDynamaxMaxHP(battler) / 4); BattleScriptExecute(BattleScript_CurseTurnDmg); effect = TRUE; } @@ -752,7 +611,7 @@ static bool32 HandleEndTurnWrap(u32 battler) { bool32 effect = FALSE; - gBattleStruct->turnEffectsBattlerId++; + gBattleStruct->eventState.endTurnBattler++; if (gBattleMons[battler].volatiles.wrapped && IsBattlerAlive(battler)) { @@ -762,22 +621,21 @@ static bool32 HandleEndTurnWrap(u32 battler) if (IsAbilityAndRecord(battler, GetBattlerAbility(battler), ABILITY_MAGIC_GUARD)) return effect; - gBattleScripting.animArg1 = gBattleStruct->wrappedMove[battler]; - gBattleScripting.animArg2 = gBattleStruct->wrappedMove[battler] >> 8; - PREPARE_MOVE_BUFFER(gBattleTextBuff1, gBattleStruct->wrappedMove[battler]); + gBattleScripting.animArg1 = gBattleMons[battler].volatiles.wrappedMove; + gBattleScripting.animArg2 = gBattleMons[battler].volatiles.wrappedMove >> 8; + PREPARE_MOVE_BUFFER(gBattleTextBuff1, gBattleMons[battler].volatiles.wrappedMove); BattleScriptExecute(BattleScript_WrapTurnDmg); - if (GetBattlerHoldEffect(gBattleStruct->wrappedBy[battler], TRUE) == HOLD_EFFECT_BINDING_BAND) - gBattleStruct->moveDamage[battler] = GetNonDynamaxMaxHP(battler) / (B_BINDING_DAMAGE >= GEN_6 ? 6 : 8); + s32 bindDamage = 0; + if (GetBattlerHoldEffect(gBattleMons[battler].volatiles.wrappedBy) == HOLD_EFFECT_BINDING_BAND) + bindDamage = GetNonDynamaxMaxHP(battler) / (B_BINDING_DAMAGE >= GEN_6 ? 6 : 8); else - gBattleStruct->moveDamage[battler] = GetNonDynamaxMaxHP(battler) / (B_BINDING_DAMAGE >= GEN_6 ? 8 : 16); - - if (gBattleStruct->moveDamage[battler] == 0) - gBattleStruct->moveDamage[battler] = 1; + bindDamage = GetNonDynamaxMaxHP(battler) / (B_BINDING_DAMAGE >= GEN_6 ? 8 : 16); + SetPassiveDamageAmount(battler, bindDamage); } else // broke free { gBattleMons[battler].volatiles.wrapped = FALSE; - PREPARE_MOVE_BUFFER(gBattleTextBuff1, gBattleStruct->wrappedMove[battler]); + PREPARE_MOVE_BUFFER(gBattleTextBuff1, gBattleMons[battler].volatiles.wrappedMove); BattleScriptExecute(BattleScript_WrapEnds); } effect = TRUE; @@ -790,18 +648,18 @@ static bool32 HandleEndTurnSaltCure(u32 battler) { bool32 effect = FALSE; - gBattleStruct->turnEffectsBattlerId++; + gBattleStruct->eventState.endTurnBattler++; if (gBattleMons[battler].volatiles.saltCure && IsBattlerAlive(battler) && !IsAbilityAndRecord(battler, GetBattlerAbility(battler), ABILITY_MAGIC_GUARD)) { + s32 saltCureDamage = 0; if (IS_BATTLER_ANY_TYPE(battler, TYPE_STEEL, TYPE_WATER)) - gBattleStruct->moveDamage[battler] = GetNonDynamaxMaxHP(battler) / 4; + saltCureDamage = GetNonDynamaxMaxHP(battler) / 4; else - gBattleStruct->moveDamage[battler] = GetNonDynamaxMaxHP(battler) / 8; - if (gBattleStruct->moveDamage[battler] == 0) - gBattleStruct->moveDamage[battler] = 1; + saltCureDamage = GetNonDynamaxMaxHP(battler) / 8; + SetPassiveDamageAmount(battler, saltCureDamage); PREPARE_MOVE_BUFFER(gBattleTextBuff1, MOVE_SALT_CURE); BattleScriptExecute(BattleScript_SaltCureExtraDamage); effect = TRUE; @@ -814,7 +672,7 @@ static bool32 HandleEndTurnOctolock(u32 battler) { bool32 effect = FALSE; - gBattleStruct->turnEffectsBattlerId++; + gBattleStruct->eventState.endTurnBattler++; if (gDisableStructs[battler].octolock) { @@ -831,7 +689,7 @@ static bool32 HandleEndTurnSyrupBomb(u32 battler) { bool32 effect = FALSE; - gBattleStruct->turnEffectsBattlerId++; + gBattleStruct->eventState.endTurnBattler++; if (gBattleMons[battler].volatiles.syrupBomb && (IsBattlerAlive(battler))) { @@ -850,10 +708,11 @@ static bool32 HandleEndTurnTaunt(u32 battler) { bool32 effect = FALSE; - gBattleStruct->turnEffectsBattlerId++; + gBattleStruct->eventState.endTurnBattler++; if (gDisableStructs[battler].tauntTimer && --gDisableStructs[battler].tauntTimer == 0) { + gBattleScripting.battler = battler; BattleScriptExecute(BattleScript_BufferEndTurn); PREPARE_MOVE_BUFFER(gBattleTextBuff1, MOVE_TAUNT); effect = TRUE; @@ -866,11 +725,12 @@ static bool32 HandleEndTurnTorment(u32 battler) { bool32 effect = FALSE; - gBattleStruct->turnEffectsBattlerId++; + gBattleStruct->eventState.endTurnBattler++; - if (gDisableStructs[battler].tormentTimer == gBattleTurnCounter) + if (gDisableStructs[battler].tormentTimer > 0 && --gDisableStructs[battler].tormentTimer == 0) { gBattleMons[battler].volatiles.torment = FALSE; + gBattleScripting.battler = battler; BattleScriptExecute(BattleScript_TormentEnds); effect = TRUE; } @@ -882,7 +742,7 @@ static bool32 HandleEndTurnEncore(u32 battler) { bool32 effect = FALSE; - gBattleStruct->turnEffectsBattlerId++; + gBattleStruct->eventState.endTurnBattler++; if (gDisableStructs[battler].encoreTimer != 0) { @@ -896,6 +756,7 @@ static bool32 HandleEndTurnEncore(u32 battler) { gDisableStructs[battler].encoredMove = 0; gDisableStructs[battler].encoreTimer = 0; + gBattleScripting.battler = battler; BattleScriptExecute(BattleScript_EncoredNoMore); effect = TRUE; } @@ -909,7 +770,7 @@ static bool32 HandleEndTurnDisable(u32 battler) bool32 effect = FALSE; u32 moveIndex = 0; - gBattleStruct->turnEffectsBattlerId++; + gBattleStruct->eventState.endTurnBattler++; if (gDisableStructs[battler].disableTimer != 0) { @@ -926,6 +787,7 @@ static bool32 HandleEndTurnDisable(u32 battler) else if (--gDisableStructs[battler].disableTimer == 0) // disable ends { gDisableStructs[battler].disabledMove = 0; + gBattleScripting.battler = battler; BattleScriptExecute(BattleScript_DisabledNoMore); effect = TRUE; } @@ -938,9 +800,9 @@ static bool32 HandleEndTurnMagnetRise(u32 battler) { bool32 effect = FALSE; - gBattleStruct->turnEffectsBattlerId++; + gBattleStruct->eventState.endTurnBattler++; - if (gBattleMons[battler].volatiles.magnetRise && gDisableStructs[battler].magnetRiseTimer == gBattleTurnCounter) + if (gDisableStructs[battler].magnetRiseTimer > 0 && --gDisableStructs[battler].magnetRiseTimer == 0) { gBattleMons[battler].volatiles.magnetRise = FALSE; BattleScriptExecute(BattleScript_BufferEndTurn); @@ -955,9 +817,9 @@ static bool32 HandleEndTurnTelekinesis(u32 battler) { bool32 effect = FALSE; - gBattleStruct->turnEffectsBattlerId++; + gBattleStruct->eventState.endTurnBattler++; - if (gBattleMons[battler].volatiles.telekinesis && gDisableStructs[battler].telekinesisTimer == gBattleTurnCounter) + if (gDisableStructs[battler].telekinesisTimer > 0 && --gDisableStructs[battler].telekinesisTimer == 0) { gBattleMons[battler].volatiles.telekinesis = FALSE; BattleScriptExecute(BattleScript_TelekinesisEndTurn); @@ -971,11 +833,12 @@ static bool32 HandleEndTurnHealBlock(u32 battler) { bool32 effect = FALSE; - gBattleStruct->turnEffectsBattlerId++; + gBattleStruct->eventState.endTurnBattler++; - if (gBattleMons[battler].volatiles.healBlock && gDisableStructs[battler].healBlockTimer == gBattleTurnCounter) + if (gDisableStructs[battler].healBlockTimer > 0 && --gDisableStructs[battler].healBlockTimer == 0) { gBattleMons[battler].volatiles.healBlock = FALSE; + gBattleScripting.battler = battler; BattleScriptExecute(BattleScript_BufferEndTurn); PREPARE_MOVE_BUFFER(gBattleTextBuff1, MOVE_HEAL_BLOCK); effect = TRUE; @@ -988,9 +851,9 @@ static bool32 HandleEndTurnEmbargo(u32 battler) { bool32 effect = FALSE; - gBattleStruct->turnEffectsBattlerId++; + gBattleStruct->eventState.endTurnBattler++; - if (gBattleMons[battler].volatiles.embargo && gDisableStructs[battler].embargoTimer == gBattleTurnCounter) + if (gDisableStructs[battler].embargoTimer > 0 && --gDisableStructs[battler].embargoTimer == 0) { gBattleMons[battler].volatiles.embargo = FALSE; BattleScriptExecute(BattleScript_EmbargoEndTurn); @@ -1004,9 +867,9 @@ static bool32 HandleEndTurnYawn(u32 battler) { bool32 effect = FALSE; - u32 ability = GetBattlerAbility(battler); + enum Ability ability = GetBattlerAbility(battler); - gBattleStruct->turnEffectsBattlerId++; + gBattleStruct->eventState.endTurnBattler++; if (gBattleMons[battler].volatiles.yawn > 0) { @@ -1019,12 +882,13 @@ static bool32 HandleEndTurnYawn(u32 battler) && !IsLeafGuardProtected(battler, ability)) { gEffectBattler = gBattlerTarget = battler; - if (IsBattlerTerrainAffected(battler, STATUS_FIELD_ELECTRIC_TERRAIN)) + enum HoldEffect holdEffect = GetBattlerHoldEffect(battler); + if (IsBattlerTerrainAffected(battler, ability, holdEffect, STATUS_FIELD_ELECTRIC_TERRAIN)) { gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_TERRAINPREVENTS_ELECTRIC; BattleScriptExecute(BattleScript_TerrainPreventsEnd2); } - else if (IsBattlerTerrainAffected(battler, STATUS_FIELD_MISTY_TERRAIN)) + else if (IsBattlerTerrainAffected(battler, ability, holdEffect, STATUS_FIELD_MISTY_TERRAIN)) { gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_TERRAINPREVENTS_MISTY; BattleScriptExecute(BattleScript_TerrainPreventsEnd2); @@ -1065,7 +929,7 @@ static bool32 HandleEndTurnPerishSong(u32 battler) { bool32 effect = FALSE; - gBattleStruct->turnEffectsBattlerId++; + gBattleStruct->eventState.endTurnBattler++; if (IsBattlerAlive(battler) && gBattleMons[battler].volatiles.perishSong) { @@ -1073,7 +937,7 @@ static bool32 HandleEndTurnPerishSong(u32 battler) if (gDisableStructs[battler].perishSongTimer == 0) { gBattleMons[battler].volatiles.perishSong = FALSE; - gBattleStruct->moveDamage[battler] = gBattleMons[battler].hp; + SetPassiveDamageAmount(battler, gBattleMons[battler].hp); BattleScriptExecute(BattleScript_PerishSongTakesLife); } else @@ -1091,7 +955,7 @@ static bool32 HandleEndTurnRoost(u32 battler) { bool32 effect = FALSE; - gBattleStruct->turnEffectsBattlerId++; + gBattleStruct->eventState.endTurnBattler++; if (gDisableStructs[battler].roostActive) gDisableStructs[battler].roostActive = FALSE; @@ -1103,12 +967,12 @@ static bool32 HandleEndTurnSecondEventBlock(u32 battler) { bool32 effect = FALSE; - u32 side = gBattleStruct->turnSideTracker; + u32 side = gBattleStruct->eventState.battlerSide; - switch (gBattleStruct->eventBlockCounter) + switch (gBattleStruct->eventState.endTurnBlock) { case SECOND_EVENT_BLOCK_REFLECT: - if (gSideStatuses[side] & SIDE_STATUS_REFLECT && gSideTimers[side].reflectTimer == gBattleTurnCounter) + if (gSideTimers[side].reflectTimer > 0 && --gSideTimers[side].reflectTimer == 0) { gBattlerAttacker = GetBattlerSideForMessage(side); gSideStatuses[side] &= ~SIDE_STATUS_REFLECT; @@ -1117,10 +981,10 @@ static bool32 HandleEndTurnSecondEventBlock(u32 battler) PREPARE_MOVE_BUFFER(gBattleTextBuff1, MOVE_REFLECT); effect = TRUE; } - gBattleStruct->eventBlockCounter++; + gBattleStruct->eventState.endTurnBlock++; break; case SECOND_EVENT_BLOCK_LIGHT_SCREEN: - if (gSideStatuses[side] & SIDE_STATUS_LIGHTSCREEN && gSideTimers[side].lightscreenTimer == gBattleTurnCounter) + if (gSideTimers[side].lightscreenTimer > 0 && --gSideTimers[side].lightscreenTimer == 0) { gBattlerAttacker = GetBattlerSideForMessage(side); gSideStatuses[side] &= ~SIDE_STATUS_LIGHTSCREEN; @@ -1129,20 +993,20 @@ static bool32 HandleEndTurnSecondEventBlock(u32 battler) PREPARE_MOVE_BUFFER(gBattleTextBuff1, MOVE_LIGHT_SCREEN); effect = TRUE; } - gBattleStruct->eventBlockCounter++; + gBattleStruct->eventState.endTurnBlock++; break; case SECOND_EVENT_BLOCK_SAFEGUARD: - if (gSideStatuses[side] & SIDE_STATUS_SAFEGUARD && gSideTimers[side].safeguardTimer == gBattleTurnCounter) + if (gSideTimers[side].safeguardTimer > 0 && --gSideTimers[side].safeguardTimer == 0) { gBattlerAttacker = GetBattlerSideForMessage(side); gSideStatuses[side] &= ~SIDE_STATUS_SAFEGUARD; BattleScriptExecute(BattleScript_SafeguardEnds); effect = TRUE; } - gBattleStruct->eventBlockCounter++; + gBattleStruct->eventState.endTurnBlock++; break; case SECOND_EVENT_BLOCK_MIST: - if (gSideTimers[side].mistTimer != 0 && gSideTimers[side].mistTimer == gBattleTurnCounter) + if (gSideTimers[side].mistTimer > 0 && --gSideTimers[side].mistTimer == 0) { gBattlerAttacker = GetBattlerSideForMessage(side); gSideStatuses[side] &= ~SIDE_STATUS_MIST; @@ -1151,59 +1015,59 @@ static bool32 HandleEndTurnSecondEventBlock(u32 battler) PREPARE_MOVE_BUFFER(gBattleTextBuff1, MOVE_MIST); effect = TRUE; } - gBattleStruct->eventBlockCounter++; + gBattleStruct->eventState.endTurnBlock++; break; case SECOND_EVENT_BLOCK_TAILWIND: - if (gSideStatuses[side] & SIDE_STATUS_TAILWIND && gSideTimers[side].tailwindTimer == gBattleTurnCounter) + if (gSideTimers[side].tailwindTimer > 0 && --gSideTimers[side].tailwindTimer == 0) { gBattlerAttacker = GetBattlerSideForMessage(side); gSideStatuses[side] &= ~SIDE_STATUS_TAILWIND; BattleScriptExecute(BattleScript_TailwindEnds); effect = TRUE; } - gBattleStruct->eventBlockCounter++; + gBattleStruct->eventState.endTurnBlock++; break; case SECOND_EVENT_BLOCK_LUCKY_CHANT: - if (gSideStatuses[side] & SIDE_STATUS_LUCKY_CHANT && gSideTimers[side].luckyChantTimer == gBattleTurnCounter) + if (gSideTimers[side].luckyChantTimer > 0 && --gSideTimers[side].luckyChantTimer == 0) { gBattlerAttacker = GetBattlerSideForMessage(side); gSideStatuses[side] &= ~SIDE_STATUS_LUCKY_CHANT; BattleScriptExecute(BattleScript_LuckyChantEnds); effect = TRUE; } - gBattleStruct->eventBlockCounter++; + gBattleStruct->eventState.endTurnBlock++; break; case SECOND_EVENT_BLOCK_RAINBOW: gBattlerAttacker = GetBattlerSideForMessage(side); - if (gSideStatuses[side] & SIDE_STATUS_RAINBOW && gSideTimers[side].rainbowTimer == gBattleTurnCounter) + if (gSideTimers[side].rainbowTimer > 0 && --gSideTimers[side].rainbowTimer == 0) { gSideStatuses[side] &= ~SIDE_STATUS_RAINBOW; BattleScriptExecute(BattleScript_TheRainbowDisappeared); effect = TRUE; } - gBattleStruct->eventBlockCounter++; + gBattleStruct->eventState.endTurnBlock++; break; case SECOND_EVENT_BLOCK_SEA_OF_FIRE: - if (gSideStatuses[side] & SIDE_STATUS_SEA_OF_FIRE && gSideTimers[side].seaOfFireTimer == gBattleTurnCounter) + if (gSideTimers[side].seaOfFireTimer > 0 && --gSideTimers[side].seaOfFireTimer == 0) { gSideStatuses[side] &= ~SIDE_STATUS_SEA_OF_FIRE; BattleScriptExecute(BattleScript_TheSeaOfFireDisappeared); effect = TRUE; } - gBattleStruct->eventBlockCounter++; + gBattleStruct->eventState.endTurnBlock++; break; case SECOND_EVENT_BLOCK_SWAMP: gBattlerAttacker = GetBattlerSideForMessage(side); - if (gSideStatuses[side] & SIDE_STATUS_SWAMP && gSideTimers[side].swampTimer == gBattleTurnCounter) + if (gSideTimers[side].swampTimer > 0 && --gSideTimers[side].swampTimer == 0) { gSideStatuses[side] &= ~SIDE_STATUS_SWAMP; BattleScriptExecute(BattleScript_TheSwampDisappeared); effect = TRUE; } - gBattleStruct->eventBlockCounter++; + gBattleStruct->eventState.endTurnBlock++; break; case SECOND_EVENT_BLOCK_AURORA_VEIL: - if (gSideStatuses[side] & SIDE_STATUS_AURORA_VEIL && gSideTimers[side].auroraVeilTimer == gBattleTurnCounter) + if (gSideTimers[side].auroraVeilTimer > 0 && --gSideTimers[side].auroraVeilTimer == 0) { gBattlerAttacker = GetBattlerSideForMessage(side); gSideStatuses[side] &= ~SIDE_STATUS_AURORA_VEIL; @@ -1212,8 +1076,8 @@ static bool32 HandleEndTurnSecondEventBlock(u32 battler) PREPARE_MOVE_BUFFER(gBattleTextBuff1, MOVE_AURORA_VEIL); effect = TRUE; } - gBattleStruct->turnSideTracker++; - gBattleStruct->eventBlockCounter = 0; + gBattleStruct->eventState.battlerSide++; + gBattleStruct->eventState.endTurnBlock = 0; break; } @@ -1224,9 +1088,9 @@ static bool32 HandleEndTurnTrickRoom(u32 battler) { bool32 effect = FALSE; - gBattleStruct->endTurnEventsCounter++; + gBattleStruct->eventState.endTurn++; - if (gFieldStatuses & STATUS_FIELD_TRICK_ROOM && gFieldTimers.trickRoomTimer == gBattleTurnCounter) + if (gFieldTimers.trickRoomTimer > 0 && --gFieldTimers.trickRoomTimer == 0) { gFieldStatuses &= ~STATUS_FIELD_TRICK_ROOM; BattleScriptExecute(BattleScript_TrickRoomEnds); @@ -1240,9 +1104,9 @@ static bool32 HandleEndTurnGravity(u32 battler) { bool32 effect = FALSE; - gBattleStruct->endTurnEventsCounter++; + gBattleStruct->eventState.endTurn++; - if (gFieldStatuses & STATUS_FIELD_GRAVITY && gFieldTimers.gravityTimer == gBattleTurnCounter) + if (gFieldTimers.gravityTimer > 0 && --gFieldTimers.gravityTimer == 0) { gFieldStatuses &= ~STATUS_FIELD_GRAVITY; BattleScriptExecute(BattleScript_GravityEnds); @@ -1256,9 +1120,9 @@ static bool32 HandleEndTurnWaterSport(u32 battler) { bool32 effect = FALSE; - gBattleStruct->endTurnEventsCounter++; + gBattleStruct->eventState.endTurn++; - if (gFieldStatuses & STATUS_FIELD_WATERSPORT && gFieldTimers.waterSportTimer == gBattleTurnCounter) + if (gFieldTimers.waterSportTimer > 0 && --gFieldTimers.waterSportTimer == 0) { gFieldStatuses &= ~STATUS_FIELD_WATERSPORT; BattleScriptExecute(BattleScript_WaterSportEnds); @@ -1272,9 +1136,9 @@ static bool32 HandleEndTurnMudSport(u32 battler) { bool32 effect = FALSE; - gBattleStruct->endTurnEventsCounter++; + gBattleStruct->eventState.endTurn++; - if (gFieldStatuses & STATUS_FIELD_MUDSPORT && gFieldTimers.mudSportTimer == gBattleTurnCounter) + if (gFieldTimers.mudSportTimer > 0 && --gFieldTimers.mudSportTimer == 0) { gFieldStatuses &= ~STATUS_FIELD_MUDSPORT; BattleScriptExecute(BattleScript_MudSportEnds); @@ -1288,9 +1152,9 @@ static bool32 HandleEndTurnWonderRoom(u32 battler) { bool32 effect = FALSE; - gBattleStruct->endTurnEventsCounter++; + gBattleStruct->eventState.endTurn++; - if (gFieldStatuses & STATUS_FIELD_WONDER_ROOM && gFieldTimers.wonderRoomTimer == gBattleTurnCounter) + if (gFieldTimers.wonderRoomTimer > 0 && --gFieldTimers.wonderRoomTimer == 0) { gFieldStatuses &= ~STATUS_FIELD_WONDER_ROOM; BattleScriptExecute(BattleScript_WonderRoomEnds); @@ -1304,9 +1168,9 @@ static bool32 HandleEndTurnMagicRoom(u32 battler) { bool32 effect = FALSE; - gBattleStruct->endTurnEventsCounter++; + gBattleStruct->eventState.endTurn++; - if (gFieldStatuses & STATUS_FIELD_MAGIC_ROOM && gFieldTimers.magicRoomTimer == gBattleTurnCounter) + if (gFieldTimers.magicRoomTimer > 0 && --gFieldTimers.magicRoomTimer == 0) { gFieldStatuses &= ~STATUS_FIELD_MAGIC_ROOM; BattleScriptExecute(BattleScript_MagicRoomEnds); @@ -1318,7 +1182,7 @@ static bool32 HandleEndTurnMagicRoom(u32 battler) static bool32 EndTurnTerrain(u32 terrainFlag, u32 stringTableId) { - if (gFieldStatuses & terrainFlag && gFieldTimers.terrainTimer == gBattleTurnCounter) + if (gFieldTimers.terrainTimer > 0 && --gFieldTimers.terrainTimer == 0) { gFieldStatuses &= ~terrainFlag; TryToRevertMimicryAndFlags(); @@ -1334,7 +1198,7 @@ static bool32 HandleEndTurnTerrain(u32 battler) { bool32 effect = FALSE; - gBattleStruct->endTurnEventsCounter++; + gBattleStruct->eventState.endTurn++; if (gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN) effect = EndTurnTerrain(STATUS_FIELD_ELECTRIC_TERRAIN, B_MSG_TERRAIN_END_ELECTRIC); @@ -1354,11 +1218,11 @@ static bool32 HandleEndTurnThirdEventBlock(u32 battler) if (!IsBattlerAlive(battler)) { - gBattleStruct->turnEffectsBattlerId++; + gBattleStruct->eventState.endTurnBattler++; return effect; } - switch (gBattleStruct->eventBlockCounter) + switch (gBattleStruct->eventState.endTurnBlock) { case THIRD_EVENT_BLOCK_UPROAR: if (gBattleMons[battler].volatiles.uproarTurns) @@ -1401,11 +1265,11 @@ static bool32 HandleEndTurnThirdEventBlock(u32 battler) effect = TRUE; } } - gBattleStruct->eventBlockCounter++; + gBattleStruct->eventState.endTurnBlock++; break; case THIRD_EVENT_BLOCK_ABILITIES: { - u32 ability = GetBattlerAbility(battler); + enum Ability ability = GetBattlerAbility(battler); switch (ability) { case ABILITY_TRUANT: // Not fully accurate but it has to be handled somehow. TODO: Find a better way. @@ -1420,30 +1284,33 @@ static bool32 HandleEndTurnThirdEventBlock(u32 battler) if (AbilityBattleEffects(ABILITYEFFECT_ENDTURN, battler, ability, 0, MOVE_NONE)) effect = TRUE; break; + default: + break; } - gBattleStruct->eventBlockCounter++; + gBattleStruct->eventState.endTurnBlock++; break; } case THIRD_EVENT_BLOCK_ITEMS: { - enum ItemHoldEffect holdEffect = GetBattlerHoldEffect(battler, TRUE); + // TODO: simplify + enum HoldEffect holdEffect = GetBattlerHoldEffect(battler); switch (holdEffect) { case HOLD_EFFECT_FLAME_ORB: case HOLD_EFFECT_STICKY_BARB: case HOLD_EFFECT_TOXIC_ORB: - if (ItemBattleEffects(ITEMEFFECT_ORBS, battler)) + if (ItemBattleEffects(battler, 0, holdEffect, IsOrbsActivation)) effect = TRUE; break; case HOLD_EFFECT_WHITE_HERB: - if (ItemBattleEffects(ITEMEFFECT_NORMAL, battler)) + if (ItemBattleEffects(battler, 0, holdEffect, IsWhiteHerbEndTurnActivation)) effect = TRUE; break; default: break; } - gBattleStruct->eventBlockCounter = 0; - gBattleStruct->turnEffectsBattlerId++; + gBattleStruct->eventState.endTurnBlock = 0; + gBattleStruct->eventState.endTurnBattler++; break; } } @@ -1455,9 +1322,9 @@ static bool32 HandleEndTurnFormChangeAbilities(u32 battler) { bool32 effect = FALSE; - u32 ability = GetBattlerAbility(battler); + enum Ability ability = GetBattlerAbility(battler); - gBattleStruct->turnEffectsBattlerId++; + gBattleStruct->eventState.endTurnBattler++; switch (ability) { @@ -1468,6 +1335,8 @@ static bool32 HandleEndTurnFormChangeAbilities(u32 battler) case ABILITY_HUNGER_SWITCH: if (AbilityBattleEffects(ABILITYEFFECT_ENDTURN, battler, ability, 0, MOVE_NONE)) effect = TRUE; + default: + break; } return effect; @@ -1475,17 +1344,17 @@ static bool32 HandleEndTurnFormChangeAbilities(u32 battler) static bool32 HandleEndTurnEjectPack(u32 battler) { - gBattleStruct->turnEffectsBattlerId++; - return TrySwitchInEjectPack(ITEMEFFECT_NORMAL); + gBattleStruct->eventState.endTurn++; + return TrySwitchInEjectPack(END_TURN); } static bool32 HandleEndTurnDynamax(u32 battler) { bool32 effect = FALSE; - gBattleStruct->turnEffectsBattlerId++; + gBattleStruct->eventState.endTurnBattler++; - if (GetActiveGimmick(battler) == GIMMICK_DYNAMAX && gBattleStruct->dynamax.dynamaxTurns[battler] == gBattleTurnCounter) + if (GetActiveGimmick(battler) == GIMMICK_DYNAMAX && gBattleStruct->dynamax.dynamaxTurns[battler] > 0 && --gBattleStruct->dynamax.dynamaxTurns[battler] == 0) { gBattleScripting.battler = battler; UndoDynamax(battler); @@ -1496,13 +1365,25 @@ static bool32 HandleEndTurnDynamax(u32 battler) return effect; } +/* + * Various end turn effects that happen after all battlers moved. + * Each Case will apply the effects for each battler. Moving to the next case when all battlers are done. + * If an effect is going to be applied on a better, the bool effect will be set to TRUE and a script set. + * The script is set with `BattleScriptExecute` and should have the ending `end2` + Example: + BattleScriptExecute(BattleScript_X); + + (in battle_scripts_1.s) + BattleScript_X: + some commands + end2 + */ static bool32 (*const sEndTurnEffectHandlers[])(u32 battler) = { [ENDTURN_ORDER] = HandleEndTurnOrder, [ENDTURN_VARIOUS] = HandleEndTurnVarious, [ENDTURN_WEATHER] = HandleEndTurnWeather, [ENDTURN_WEATHER_DAMAGE] = HandleEndTurnWeatherDamage, - [ENDTURN_GEN_3_BERRY_ACTIVATION] = HandleEndTurnGenThreeBerryActivation, [ENDTURN_EMERGENCY_EXIT_1] = HandleEndTurnEmergencyExit, [ENDTURN_AFFECTION] = HandleEndTurnAffection, [ENDTURN_FUTURE_SIGHT] = HandleEndTurnFutureSight, @@ -1551,29 +1432,25 @@ static bool32 (*const sEndTurnEffectHandlers[])(u32 battler) = u32 DoEndTurnEffects(void) { u32 battler = MAX_BATTLERS_COUNT; - gHitMarker |= (HITMARKER_GRUDGE | HITMARKER_IGNORE_BIDE); for (;;) { // If either turnEffectsBattlerId or turnSideTracker are at max count, reest values and go to the next state - if (gBattleStruct->turnEffectsBattlerId == gBattlersCount || gBattleStruct->turnSideTracker == NUM_BATTLE_SIDES) + if (gBattleStruct->eventState.endTurnBattler == gBattlersCount || gBattleStruct->eventState.battlerSide == NUM_BATTLE_SIDES) { - gBattleStruct->turnEffectsBattlerId = 0; - gBattleStruct->turnSideTracker = 0; - gBattleStruct->eventBlockCounter = 0; - gBattleStruct->endTurnEventsCounter++; + gBattleStruct->eventState.endTurnBattler = 0; + gBattleStruct->eventState.battlerSide = 0; + gBattleStruct->eventState.endTurnBlock = 0; + gBattleStruct->eventState.endTurn++; } // Jump out if possible after endTurnEventsCounter was increased in the above code block - if (gBattleStruct->endTurnEventsCounter == ENDTURN_COUNT) - { - gHitMarker &= ~(HITMARKER_GRUDGE | HITMARKER_IGNORE_BIDE); + if (gBattleStruct->eventState.endTurn == ENDTURN_COUNT) return FALSE; - } - battler = gBattlerAttacker = gBattlerByTurnOrder[gBattleStruct->turnEffectsBattlerId]; + battler = gBattlerAttacker = gBattlerByTurnOrder[gBattleStruct->eventState.endTurnBattler]; - if (sEndTurnEffectHandlers[gBattleStruct->endTurnEventsCounter](battler)) + if (sEndTurnEffectHandlers[gBattleStruct->eventState.endTurn](battler)) return TRUE; } } diff --git a/src/battle_gfx_sfx_util.c b/src/battle_gfx_sfx_util.c index a6362bb24f..0ae16a69cb 100644 --- a/src/battle_gfx_sfx_util.c +++ b/src/battle_gfx_sfx_util.c @@ -466,8 +466,10 @@ void InitAndLaunchChosenStatusAnimation(u32 battler, bool32 isVolatile, u32 stat gBattleSpritesDataPtr->healthBoxesData[battler].statusAnimActive = 1; if (!isVolatile) { - if (status == STATUS1_FREEZE || status == STATUS1_FROSTBITE) + if (status == STATUS1_FREEZE) LaunchStatusAnimation(battler, B_ANIM_STATUS_FRZ); + else if (status == STATUS1_FROSTBITE) + LaunchStatusAnimation(battler, B_ANIM_STATUS_FRB); else if (status == STATUS1_POISON || status & STATUS1_TOXIC_POISON) LaunchStatusAnimation(battler, B_ANIM_STATUS_PSN); else if (status == STATUS1_BURN) @@ -544,6 +546,9 @@ static bool8 ShouldAnimBeDoneRegardlessOfSubstitute(u8 animId) { switch (animId) { + case B_ANIM_ILLUSION_OFF: + case B_ANIM_SWAP_TO_SUBSTITUTE: + case B_ANIM_SWAP_FROM_SUBSTITUTE: case B_ANIM_SUBSTITUTE_FADE: case B_ANIM_RAIN_CONTINUES: case B_ANIM_SUN_CONTINUES: @@ -552,6 +557,7 @@ static bool8 ShouldAnimBeDoneRegardlessOfSubstitute(u8 animId) case B_ANIM_SNOW_CONTINUES: case B_ANIM_FOG_CONTINUES: case B_ANIM_SNATCH_MOVE: + case B_ANIM_STATS_CHANGE: return TRUE; default: return FALSE; @@ -653,7 +659,7 @@ void BattleLoadMonSpriteGfx(struct Pokemon *mon, u32 battler) LoadPalette(paletteData, BG_PLTT_ID(8) + BG_PLTT_ID(battler), PLTT_SIZE_4BPP); // transform's pink color - if (gBattleSpritesDataPtr->battlerData[battler].transformSpecies != SPECIES_NONE) + if (gBattleMons[battler].volatiles.transformed) { BlendPalette(paletteOffset, 16, 6, RGB_WHITE); CpuCopy32(&gPlttBufferFaded[paletteOffset], &gPlttBufferUnfaded[paletteOffset], PLTT_SIZEOF(16)); @@ -694,8 +700,9 @@ void DecompressTrainerBackPic(u16 backPicId, u8 battler) { u8 position = GetBattlerPosition(battler); CopyTrainerBackspriteFramesToDest(backPicId, gMonSpritesGfxPtr->spritesGfx[position]); + // Aiming for palette slots 8 and 9 for Player and PlayerPartner to prevent Trainer Slides causing mons to change colour LoadPalette(gTrainerBacksprites[backPicId].palette.data, - OBJ_PLTT_ID(battler), PLTT_SIZE_4BPP); + OBJ_PLTT_ID(8 + battler/2), PLTT_SIZE_4BPP); } void FreeTrainerFrontPicPalette(u16 frontPicId) @@ -931,7 +938,7 @@ void HandleSpeciesGfxDataChange(u8 battlerAtk, u8 battlerDef, u8 changeType) else { position = GetBattlerPosition(battlerAtk); - if (gBattleSpritesDataPtr->battlerData[battlerAtk].transformSpecies == SPECIES_NONE) + if (changeType == SPECIES_GFX_CHANGE_TRANSFORM) { // Get base form if its currently Gigantamax if (IsGigantamaxed(battlerDef)) @@ -940,12 +947,12 @@ void HandleSpeciesGfxDataChange(u8 battlerAtk, u8 battlerDef, u8 changeType) targetSpecies = GetIllusionMonSpecies(battlerDef); else targetSpecies = GetMonData(monDef, MON_DATA_SPECIES); - gBattleSpritesDataPtr->battlerData[battlerAtk].transformSpecies = targetSpecies; } else { - targetSpecies = gBattleSpritesDataPtr->battlerData[battlerAtk].transformSpecies; + targetSpecies = GetMonData(monAtk, MON_DATA_SPECIES); } + gBattleSpritesDataPtr->battlerData[battlerAtk].transformSpecies = targetSpecies; if (changeType == SPECIES_GFX_CHANGE_TRANSFORM) { @@ -1237,6 +1244,12 @@ void LoadAndCreateEnemyShadowSprites(void) void SpriteCB_EnemyShadow(struct Sprite *shadowSprite) { + if (gBattleSpritesDataPtr == NULL) + { + shadowSprite->callback = SpriteCB_SetInvisible; + return; + } + bool8 invisible = FALSE; u8 battler = shadowSprite->tBattlerId; struct Sprite *battlerSprite = &gSprites[gBattlerSpriteIds[battler]]; diff --git a/src/battle_gimmick.c b/src/battle_gimmick.c index 38d60d4365..7a94b185b6 100644 --- a/src/battle_gimmick.c +++ b/src/battle_gimmick.c @@ -91,20 +91,15 @@ bool32 ShouldTrainerBattlerUseGimmick(u32 battler, enum Gimmick gimmick) // Returns whether a trainer has used a gimmick during a battle. bool32 HasTrainerUsedGimmick(u32 battler, enum Gimmick gimmick) { - // Check whether partner battler has used gimmick or plans to during turn. - if (IsDoubleBattle() - && IsPartnerMonFromSameTrainer(battler) - && (gBattleStruct->gimmick.activated[BATTLE_PARTNER(battler)][gimmick] - || ((gBattleStruct->gimmick.toActivate & (1u << BATTLE_PARTNER(battler)) - && gBattleStruct->gimmick.usableGimmick[BATTLE_PARTNER(battler)] == gimmick)))) + if (IsDoubleBattle() && IsPartnerMonFromSameTrainer(battler)) { - return TRUE; - } - // Otherwise, return whether current battler has used gimmick. - else - { - return gBattleStruct->gimmick.activated[battler][gimmick]; + u32 partner = BATTLE_PARTNER(battler); + if (gBattleStruct->gimmick.activated[partner][gimmick] + || ((gBattleStruct->gimmick.toActivate & (1u << partner)) && gBattleStruct->gimmick.usableGimmick[partner] == gimmick)) + return TRUE; } + + return gBattleStruct->gimmick.activated[battler][gimmick]; } // Sets a gimmick as used by a trainer with checks for Multi Battles. @@ -152,7 +147,7 @@ void CreateGimmickTriggerSprite(u32 battler) if (gBattleStruct->gimmick.triggerSpriteId == 0xFF) { - if (IsDoubleBattle()) + if (GetBattlerCoordsIndex(battler) == BATTLE_COORDS_DOUBLES) 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); @@ -209,7 +204,7 @@ static void SpriteCb_GimmickTrigger(struct Sprite *sprite) s32 yDiff; s32 xHealthbox = gSprites[gHealthboxSpriteIds[sprite->tBattler]].x; - if (IsDoubleBattle()) + if (GetBattlerCoordsIndex(sprite->tBattler) == BATTLE_COORDS_DOUBLES) { xSlide = DOUBLES_GIMMICK_TRIGGER_POS_X_SLIDE; xPriority = DOUBLES_GIMMICK_TRIGGER_POS_X_PRIORITY; diff --git a/src/battle_hold_effects.c b/src/battle_hold_effects.c new file mode 100644 index 0000000000..9f363ea120 --- /dev/null +++ b/src/battle_hold_effects.c @@ -0,0 +1,1275 @@ +#include "global.h" +#include "battle.h" +#include "battle_anim.h" +#include "battle_ai_util.h" // maybe move some stuff over to battle.h +#include "battle_controllers.h" +#include "battle_util.h" +#include "battle_hold_effects.h" +#include "battle_scripts.h" +#include "item.h" +#include "string_util.h" +#include "data/hold_effects.h" +#include "constants/berry.h" + +bool32 IsOnSwitchInActivation(enum HoldEffect holdEffect) { return gHoldEffectsInfo[holdEffect].onSwitchIn; } +bool32 IsOnSwitchInFirstTurnActivation(enum HoldEffect holdEffect) { return gHoldEffectsInfo[holdEffect].onSwitchInFirstTurn; } +bool32 IsMirrorHerbActivation(enum HoldEffect holdEffect) { return gHoldEffectsInfo[holdEffect].mirrorHerb; } +bool32 IsMirrorHerbFirstTurnActivation(enum HoldEffect holdEffect) { return gHoldEffectsInfo[holdEffect].mirrorHerbFirstTurn; } +bool32 IsWhiteHerbActivation(enum HoldEffect holdEffect) { return gHoldEffectsInfo[holdEffect].whiteHerb; } +bool32 IsWhiteHerbFirstTurnActivation(enum HoldEffect holdEffect) { return gHoldEffectsInfo[holdEffect].whiteHerbFirstTurn; } +bool32 IsWhiteHerbEndTurnActivation(enum HoldEffect holdEffect) { return gHoldEffectsInfo[holdEffect].whiteHerbEndTurn; } +bool32 IsOnStatusChangeActivation(enum HoldEffect holdEffect) { return gHoldEffectsInfo[holdEffect].onStatusChange; } +bool32 IsOnHpThresholdActivation(enum HoldEffect holdEffect) { return gHoldEffectsInfo[holdEffect].onHpThreshold; } +bool32 IsKeeMarangaBerryActivation(enum HoldEffect holdEffect) { return gHoldEffectsInfo[holdEffect].keeMarangaBerry; } +bool32 IsOnTargetHitActivation(enum HoldEffect holdEffect) { return gHoldEffectsInfo[holdEffect].onTargetAfterHit; } +bool32 IsOnAttackerAfterHitActivation(enum HoldEffect holdEffect) { return gHoldEffectsInfo[holdEffect].onAttackerAfterHit; } +bool32 IsLifeOrbShellBellActivation(enum HoldEffect holdEffect) { return gHoldEffectsInfo[holdEffect].lifeOrbShellBell; } +bool32 IsLeftoversActivation(enum HoldEffect holdEffect) { return gHoldEffectsInfo[holdEffect].leftovers; } +bool32 IsOrbsActivation(enum HoldEffect holdEffect) { return gHoldEffectsInfo[holdEffect].orbs; } +bool32 IsOnEffectActivation(enum HoldEffect holdEffect) { return gHoldEffectsInfo[holdEffect].onEffect; } +bool32 IsOnBerryActivation(enum HoldEffect holdEffect) { return GetItemPocket(gLastUsedItem) == POCKET_BERRIES; } +bool32 IsOnFlingActivation(enum HoldEffect holdEffect) { return gHoldEffectsInfo[holdEffect].onFling; } + +bool32 IsForceTriggerItemActivation(enum HoldEffect holdEffect) +{ + return gHoldEffectsInfo[holdEffect].onSwitchIn + || gHoldEffectsInfo[holdEffect].whiteHerb + || gHoldEffectsInfo[holdEffect].onStatusChange + || gHoldEffectsInfo[holdEffect].onHpThreshold; +} + +static enum ItemEffect TryDoublePrize(u32 battler) +{ + enum ItemEffect effect = ITEM_NO_EFFECT; + + if (IsOnPlayerSide(battler) && !gBattleStruct->moneyMultiplierItem) + { + gBattleStruct->moneyMultiplier *= 2; + gBattleStruct->moneyMultiplierItem = TRUE; + } + + return effect; +} + +enum ItemEffect TryBoosterEnergy(u32 battler, enum Ability ability, ActivationTiming timing) +{ + enum ItemEffect effect = ITEM_NO_EFFECT; + + if (gDisableStructs[battler].boosterEnergyActivated || gBattleMons[battler].volatiles.transformed) + return ITEM_NO_EFFECT; + + if (((ability == ABILITY_PROTOSYNTHESIS) && !((gBattleWeather & B_WEATHER_SUN) && HasWeatherEffect())) + || ((ability == ABILITY_QUARK_DRIVE) && !(gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN))) + { + gDisableStructs[battler].paradoxBoostedStat = GetParadoxHighestStatId(battler); + PREPARE_STAT_BUFFER(gBattleTextBuff1, gDisableStructs[battler].paradoxBoostedStat); + gBattlerAbility = gBattleScripting.battler = battler; + gDisableStructs[battler].boosterEnergyActivated = TRUE; + RecordAbilityBattle(battler, ability); + if (timing == IsOnSwitchInFirstTurnActivation) + BattleScriptExecute(BattleScript_BoosterEnergyEnd2); + else + BattleScriptCall(BattleScript_BoosterEnergyRet); + effect = ITEM_EFFECT_OTHER; + } + + return effect; +} + +static enum ItemEffect TryRoomService(u32 battler, ActivationTiming timing) +{ + if (gFieldStatuses & STATUS_FIELD_TRICK_ROOM && CompareStat(battler, STAT_SPEED, MIN_STAT_STAGE, CMP_GREATER_THAN, GetBattlerAbility(battler))) + { + gEffectBattler = gBattleScripting.battler = battler; + SET_STATCHANGER(STAT_SPEED, 1, TRUE); + gBattleScripting.animArg1 = STAT_ANIM_PLUS1 + STAT_SPEED; + gBattleScripting.animArg2 = 0; + + if (timing == IsOnSwitchInFirstTurnActivation) + BattleScriptExecute(BattleScript_ConsumableStatRaiseEnd2); + else + BattleScriptCall(BattleScript_ConsumableStatRaiseRet); + + return ITEM_STATS_CHANGE; + } + + return ITEM_NO_EFFECT; +} + +enum ItemEffect TryHandleSeed(u32 battler, u32 terrainFlag, enum Stat statId, ActivationTiming timing) +{ + if (gFieldStatuses & terrainFlag && CompareStat(battler, statId, MAX_STAT_STAGE, CMP_LESS_THAN, GetBattlerAbility(battler))) + { + gEffectBattler = gBattleScripting.battler = battler; + SET_STATCHANGER(statId, 1, FALSE); + gBattleScripting.animArg1 = STAT_ANIM_PLUS1 + statId; + gBattleScripting.animArg2 = 0; + if (timing == IsOnSwitchInFirstTurnActivation) + BattleScriptExecute(BattleScript_ConsumableStatRaiseEnd2); + else + BattleScriptCall(BattleScript_ConsumableStatRaiseRet); + return ITEM_STATS_CHANGE; + } + return ITEM_NO_EFFECT; +} + +static enum ItemEffect TryTerrainSeeds(u32 battler, u32 item, ActivationTiming timing) +{ + enum ItemEffect effect = ITEM_NO_EFFECT; + + switch (GetItemHoldEffectParam(item)) + { + case HOLD_EFFECT_PARAM_ELECTRIC_TERRAIN: + effect = TryHandleSeed(battler, STATUS_FIELD_ELECTRIC_TERRAIN, STAT_DEF, timing); + break; + case HOLD_EFFECT_PARAM_GRASSY_TERRAIN: + effect = TryHandleSeed(battler, STATUS_FIELD_GRASSY_TERRAIN, STAT_DEF, timing); + break; + case HOLD_EFFECT_PARAM_MISTY_TERRAIN: + effect = TryHandleSeed(battler, STATUS_FIELD_MISTY_TERRAIN, STAT_SPDEF, timing); + break; + case HOLD_EFFECT_PARAM_PSYCHIC_TERRAIN: + effect = TryHandleSeed(battler, STATUS_FIELD_PSYCHIC_TERRAIN, STAT_SPDEF, timing); + break; + } + + return effect; +} + +static bool32 CanBeInfinitelyConfused(u32 battler) +{ + enum Ability ability = GetBattlerAbility(battler); + if (ability == ABILITY_OWN_TEMPO + || IsBattlerTerrainAffected(battler, ability, GetBattlerHoldEffect(battler), STATUS_FIELD_MISTY_TERRAIN) + || gSideStatuses[GetBattlerSide(battler)] & SIDE_STATUS_SAFEGUARD) + return FALSE; + return TRUE; +} + +static enum ItemEffect TryBerserkGene(u32 battler, ActivationTiming timing) +{ + if (CanBeInfinitelyConfused(battler)) + gBattleMons[battler].volatiles.infiniteConfusion = TRUE; + + SET_STATCHANGER(STAT_ATK, 2, FALSE); + gBattleScripting.animArg1 = STAT_ANIM_PLUS1 + STAT_ATK; + gBattleScripting.animArg2 = 0; + if (timing == IsOnSwitchInFirstTurnActivation) + BattleScriptExecute(BattleScript_BerserkGeneRetEnd2); + else + BattleScriptCall(BattleScript_BerserkGeneRet); + + return ITEM_STATS_CHANGE; +} + +static enum ItemEffect RestoreWhiteHerbStats(u32 battler, ActivationTiming timing) +{ + enum ItemEffect effect = ITEM_NO_EFFECT; + + for (u32 i = 0; i < NUM_BATTLE_STATS; i++) + { + if (gBattleMons[battler].statStages[i] < DEFAULT_STAT_STAGE) + { + gBattleMons[battler].statStages[i] = DEFAULT_STAT_STAGE; + effect = ITEM_STATS_CHANGE; + } + } + if (effect != ITEM_NO_EFFECT) + { + if (timing == IsWhiteHerbActivation || timing == IsOnFlingActivation) + BattleScriptCall(BattleScript_WhiteHerbRet); + else + BattleScriptExecute(BattleScript_WhiteHerbEnd2); + } + + return effect; +} + +static enum ItemEffect TryConsumeMirrorHerb(u32 battler, ActivationTiming timing) +{ + enum ItemEffect effect = ITEM_NO_EFFECT; + + if (gProtectStructs[battler].eatMirrorHerb) + { + gProtectStructs[battler].eatMirrorHerb = 0; + ChooseStatBoostAnimation(battler); + if (timing == IsMirrorHerbFirstTurnActivation) + BattleScriptExecute(BattleScript_MirrorHerbCopyStatChangeEnd2); + else + BattleScriptCall(BattleScript_MirrorHerbCopyStatChange); + effect = ITEM_STATS_CHANGE; + } + + return effect; +} + +static enum ItemEffect TryKingsRock(u32 battlerAtk, u32 battlerDef, u32 item) +{ + enum ItemEffect effect = ITEM_NO_EFFECT; + + if (!IsBattlerAlive(battlerDef) + || !IsBattlerTurnDamaged(battlerDef) + || MoveIgnoresKingsRock(gCurrentMove) + || MoveHasAdditionalEffect(gCurrentMove, MOVE_EFFECT_FLINCH)) + return effect; + + enum Ability ability = GetBattlerAbility(battlerAtk); + u32 holdEffectParam = GetItemHoldEffectParam(item); + + if (B_SERENE_GRACE_BOOST >= GEN_5 && ability == ABILITY_SERENE_GRACE) + holdEffectParam *= 2; + if (gSideStatuses[GetBattlerSide(battlerAtk)] & SIDE_STATUS_RAINBOW && gCurrentMove != MOVE_SECRET_POWER) + holdEffectParam *= 2; + if (ability != ABILITY_STENCH && RandomPercentage(RNG_HOLD_EFFECT_FLINCH, holdEffectParam)) + { + SetMoveEffect(battlerAtk, battlerDef, MOVE_EFFECT_FLINCH, gBattlescriptCurrInstr, NO_FLAGS); + effect = ITEM_EFFECT_OTHER; + } + + return effect; +} + +static enum ItemEffect TryAirBalloon(u32 battler, ActivationTiming timing) +{ + enum ItemEffect effect = ITEM_NO_EFFECT; + + if (timing == IsOnTargetHitActivation) + { + if (IsBattlerTurnDamaged(battler)) + { + BattleScriptCall(BattleScript_AirBalloonMsgPop); + effect = ITEM_EFFECT_OTHER; + } + } + else if (!gSpecialStatuses[battler].switchInItemDone) + { + gSpecialStatuses[battler].switchInItemDone = TRUE; + if (timing == IsOnSwitchInFirstTurnActivation) + BattleScriptPushCursorAndCallback(BattleScript_AirBalloonMsgIn); + else + BattleScriptCall(BattleScript_AirBalloonMsgInRet); + RecordItemEffectBattle(battler, HOLD_EFFECT_AIR_BALLOON); + effect = ITEM_EFFECT_OTHER; + } + + return effect; +} + +static enum ItemEffect TryRockyHelmet(u32 battlerDef, u32 battlerAtk, u32 item) +{ + enum ItemEffect effect = ITEM_NO_EFFECT; + enum Ability ability = GetBattlerAbility(battlerAtk); + + if (IsBattlerTurnDamaged(battlerDef) + && IsBattlerAlive(battlerAtk) + && !CanBattlerAvoidContactEffects(battlerAtk, battlerDef, ability, GetBattlerHoldEffect(battlerAtk), gCurrentMove) + && !IsAbilityAndRecord(battlerAtk, ability, ABILITY_MAGIC_GUARD)) + { + SetPassiveDamageAmount(battlerAtk, GetNonDynamaxMaxHP(battlerAtk) / 6); + PREPARE_ITEM_BUFFER(gBattleTextBuff1, item); + BattleScriptCall(BattleScript_RockyHelmetActivates); + effect = ITEM_HP_CHANGE; + } + + return effect; +} + +static enum ItemEffect TryWeaknessPolicy(u32 battlerDef) +{ + enum ItemEffect effect = ITEM_NO_EFFECT; + + if (IsBattlerAlive(battlerDef) + && IsBattlerTurnDamaged(battlerDef) + && gBattleStruct->moveResultFlags[battlerDef] & MOVE_RESULT_SUPER_EFFECTIVE) + { + BattleScriptCall(BattleScript_WeaknessPolicy); + effect = ITEM_STATS_CHANGE; + } + + return effect; +} + +static enum ItemEffect TrySnowball(u32 battlerDef) +{ + enum ItemEffect effect = ITEM_NO_EFFECT; + + if (IsBattlerAlive(battlerDef) + && IsBattlerTurnDamaged(battlerDef) + && GetBattleMoveType(gCurrentMove) == TYPE_ICE) + { + BattleScriptCall(BattleScript_TargetItemStatRaise); + SET_STATCHANGER(STAT_ATK, 1, FALSE); + effect = ITEM_STATS_CHANGE; + } + + return effect; +} + +static enum ItemEffect TryLuminousMoss(u32 battlerDef) +{ + enum ItemEffect effect = ITEM_NO_EFFECT; + + if (IsBattlerAlive(battlerDef) + && IsBattlerTurnDamaged(battlerDef) + && GetBattleMoveType(gCurrentMove) == TYPE_WATER) + { + BattleScriptCall(BattleScript_TargetItemStatRaise); + SET_STATCHANGER(STAT_SPDEF, 1, FALSE); + effect = ITEM_STATS_CHANGE; + } + + return effect; +} + +static enum ItemEffect TryCellBattery(u32 battlerDef) +{ + enum ItemEffect effect = ITEM_NO_EFFECT; + + if (IsBattlerAlive(battlerDef) + && IsBattlerTurnDamaged(battlerDef) + && GetBattleMoveType(gCurrentMove) == TYPE_ELECTRIC) + { + BattleScriptCall(BattleScript_TargetItemStatRaise); + SET_STATCHANGER(STAT_ATK, 1, FALSE); + effect = ITEM_STATS_CHANGE; + } + + return effect; +} + +static enum ItemEffect TryAbsorbBulb(u32 battlerDef) +{ + enum ItemEffect effect = ITEM_NO_EFFECT; + + if (IsBattlerAlive(battlerDef) + && IsBattlerTurnDamaged(battlerDef) + && GetBattleMoveType(gCurrentMove) == TYPE_WATER) + { + effect = ITEM_STATS_CHANGE; + BattleScriptCall(BattleScript_TargetItemStatRaise); + SET_STATCHANGER(STAT_SPATK, 1, FALSE); + } + + return effect; +} + +static enum ItemEffect TryJabocaBerry(u32 battlerDef, u32 battlerAtk, u32 item) +{ + enum ItemEffect effect = ITEM_NO_EFFECT; + + if (IsBattlerAlive(battlerAtk) + && IsBattlerTurnDamaged(battlerDef) + && !DoesSubstituteBlockMove(battlerAtk, battlerDef, gCurrentMove) + && IsBattleMovePhysical(gCurrentMove) + && !IsAbilityAndRecord(battlerAtk, GetBattlerAbility(battlerAtk), ABILITY_MAGIC_GUARD)) + { + s32 jabocaDamage = GetNonDynamaxMaxHP(battlerAtk) / 8; + if (GetBattlerAbility(battlerDef) == ABILITY_RIPEN) + jabocaDamage *= 2; + SetPassiveDamageAmount(battlerAtk, jabocaDamage); + BattleScriptCall(BattleScript_JabocaRowapBerryActivates); + PREPARE_ITEM_BUFFER(gBattleTextBuff1, item); + effect = ITEM_HP_CHANGE; + } + + return effect; +} + +static enum ItemEffect TryRowapBerry(u32 battlerDef, u32 battlerAtk, u32 item) +{ + enum ItemEffect effect = ITEM_NO_EFFECT; + + if (IsBattlerAlive(battlerAtk) + && IsBattlerTurnDamaged(battlerDef) + && !DoesSubstituteBlockMove(battlerAtk, battlerDef, gCurrentMove) + && IsBattleMoveSpecial(gCurrentMove) + && !IsAbilityAndRecord(battlerAtk, GetBattlerAbility(battlerAtk), ABILITY_MAGIC_GUARD)) + { + s32 rowapDamage = GetNonDynamaxMaxHP(battlerAtk) / 8; + if (GetBattlerAbility(battlerDef) == ABILITY_RIPEN) + rowapDamage *= 2; + SetPassiveDamageAmount(battlerAtk, rowapDamage); + BattleScriptCall(BattleScript_JabocaRowapBerryActivates); + PREPARE_ITEM_BUFFER(gBattleTextBuff1, item); + effect = ITEM_HP_CHANGE; + } + + return effect; +} + +static enum ItemEffect TrySetEnigmaBerry(u32 battlerDef, u32 battlerAtk) +{ + enum ItemEffect effect = ITEM_NO_EFFECT; + + if (IsBattlerAlive(battlerDef) + && !DoesSubstituteBlockMove(battlerAtk, battlerDef, gCurrentMove) + && ((IsBattlerTurnDamaged(battlerDef) && gBattleStruct->moveResultFlags[battlerDef] & MOVE_RESULT_SUPER_EFFECTIVE) || gBattleScripting.overrideBerryRequirements) + && !(gBattleScripting.overrideBerryRequirements && gBattleMons[battlerDef].hp == gBattleMons[battlerDef].maxHP) + && !(B_HEAL_BLOCKING >= GEN_5 && gBattleMons[battlerDef].volatiles.healBlock)) + { + s32 healAmount = gBattleMons[battlerDef].maxHP * 25 / 100; + if (GetBattlerAbility(battlerDef) == ABILITY_RIPEN) + healAmount *= 2; + SetHealAmount(battlerDef, healAmount); + BattleScriptCall(BattleScript_ItemHealHP_RemoveItemRet); + effect = ITEM_HP_CHANGE; + } + + return effect; +} + +static enum ItemEffect TryBlunderPolicy(u32 battlerAtk) +{ + enum ItemEffect effect = ITEM_NO_EFFECT; + + if (gBattleStruct->blunderPolicy + && IsBattlerAlive(battlerAtk) + && CompareStat(battlerAtk, STAT_SPEED, MAX_STAT_STAGE, CMP_LESS_THAN, GetBattlerAbility(battlerAtk))) + { + gBattleStruct->blunderPolicy = FALSE; + SET_STATCHANGER(STAT_SPEED, 2, FALSE); + BattleScriptCall(BattleScript_AttackerItemStatRaise); + effect = ITEM_STATS_CHANGE; + } + + return effect; +} + +static enum ItemEffect TryMentalHerb(u32 battler) +{ + enum ItemEffect effect = ITEM_NO_EFFECT; + + // Check infatuation + if (gBattleMons[battler].volatiles.infatuation) + { + gBattleMons[battler].volatiles.infatuation = 0; + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_MENTALHERBCURE_INFATUATION; + StringCopy(gBattleTextBuff1, gStatusConditionString_LoveJpn); + effect = ITEM_EFFECT_OTHER; + } + if (B_MENTAL_HERB >= GEN_5) + { + // Check taunt + if (gDisableStructs[battler].tauntTimer != 0) + { + gDisableStructs[battler].tauntTimer = 0; + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_MENTALHERBCURE_TAUNT; + PREPARE_MOVE_BUFFER(gBattleTextBuff1, MOVE_TAUNT); + effect = ITEM_EFFECT_OTHER; + } + // Check encore + if (gDisableStructs[battler].encoreTimer != 0) + { + gDisableStructs[battler].encoredMove = 0; + gDisableStructs[battler].encoreTimer = 0; + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_MENTALHERBCURE_ENCORE; + effect = ITEM_EFFECT_OTHER; + } + // Check torment + if (gBattleMons[battler].volatiles.torment == TRUE) + { + gBattleMons[battler].volatiles.torment = FALSE; + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_MENTALHERBCURE_TORMENT; + effect = ITEM_EFFECT_OTHER; + } + // Check heal block + if (gBattleMons[battler].volatiles.healBlock) + { + gBattleMons[battler].volatiles.healBlock = FALSE; + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_MENTALHERBCURE_HEALBLOCK; + effect = ITEM_EFFECT_OTHER; + } + // Check disable + if (gDisableStructs[battler].disableTimer != 0) + { + gDisableStructs[battler].disableTimer = 0; + gDisableStructs[battler].disabledMove = 0; + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_MENTALHERBCURE_DISABLE; + effect = ITEM_EFFECT_OTHER; + } + } + + if (effect) + BattleScriptCall(BattleScript_MentalHerbCureRet); + + return effect; +} + +static enum ItemEffect TryThroatSpray(u32 battlerAtk) +{ + enum ItemEffect effect = ITEM_NO_EFFECT; + + if (IsSoundMove(gCurrentMove) + && gMultiHitCounter == 0 + && IsBattlerAlive(battlerAtk) + && IsAnyTargetTurnDamaged(battlerAtk) + && CompareStat(battlerAtk, STAT_SPATK, MAX_STAT_STAGE, CMP_LESS_THAN, GetBattlerAbility(battlerAtk)) + && !NoAliveMonsForEitherParty()) // Don't activate if battle will end + { + SET_STATCHANGER(STAT_SPATK, 1, FALSE); + BattleScriptCall(BattleScript_AttackerItemStatRaise); + effect = ITEM_STATS_CHANGE; + } + + return effect; +} + +static enum ItemEffect DamagedStatBoostBerryEffect(u32 battlerDef, u32 battlerAtk, enum Stat statId, enum DamageCategory category) +{ + enum ItemEffect effect = ITEM_NO_EFFECT; + + if (!IsBattlerAlive(battlerDef) || !CompareStat(battlerDef, statId, MAX_STAT_STAGE, CMP_LESS_THAN, GetBattlerAbility(battlerDef))) + return effect; + + if (gBattleScripting.overrideBerryRequirements + || (!DoesSubstituteBlockMove(battlerAtk, battlerDef, gCurrentMove) + && GetBattleMoveCategory(gCurrentMove) == category + && IsBattlerTurnDamaged(battlerDef))) + { + if (GetBattlerAbility(battlerDef) == ABILITY_RIPEN) + SET_STATCHANGER(statId, 2, FALSE); + else + SET_STATCHANGER(statId, 1, FALSE); + + gBattleScripting.animArg1 = STAT_ANIM_PLUS1 + statId; + gBattleScripting.animArg2 = 0; + BattleScriptCall(BattleScript_ConsumableStatRaiseRet); + effect = ITEM_STATS_CHANGE; + } + + return effect; +} + +static enum ItemEffect TryShellBell(u32 battlerAtk) +{ + enum ItemEffect effect = ITEM_NO_EFFECT; + + if (gBattleScripting.savedDmg > 0 + && !(gHitMarker & HITMARKER_UNABLE_TO_USE_MOVE) + && (IsAnyTargetTurnDamaged(battlerAtk) || gBattleScripting.savedDmg > 0) + && !IsBattlerAtMaxHp(battlerAtk) + && IsBattlerAlive(battlerAtk) + && GetMoveEffect(gCurrentMove) != EFFECT_PAIN_SPLIT + && !IsFutureSightAttackerInParty(battlerAtk, gBattlerTarget, gCurrentMove) + && !(B_HEAL_BLOCKING >= GEN_5 && gBattleMons[battlerAtk].volatiles.healBlock)) + { + SetHealAmount(battlerAtk, gBattleScripting.savedDmg / GetBattlerHoldEffectParam(battlerAtk)); + BattleScriptCall(BattleScript_ItemHealHP_Ret); + effect = ITEM_HP_CHANGE; + } + + return effect; +} + +static enum ItemEffect TryLifeOrb(u32 battlerAtk) +{ + enum ItemEffect effect = ITEM_NO_EFFECT; + + if (IsBattlerAlive(battlerAtk) + && !(gHitMarker & HITMARKER_UNABLE_TO_USE_MOVE) + && (IsAnyTargetTurnDamaged(battlerAtk) || gBattleScripting.savedDmg > 0) + && !IsAbilityAndRecord(battlerAtk, GetBattlerAbility(battlerAtk), ABILITY_MAGIC_GUARD) + && GetMoveEffect(gCurrentMove) != EFFECT_PAIN_SPLIT + && !IsFutureSightAttackerInParty(battlerAtk, gBattlerTarget, gCurrentMove)) + { + SetPassiveDamageAmount(battlerAtk, GetNonDynamaxMaxHP(battlerAtk) / 10); + BattleScriptCall(BattleScript_ItemHurtRet); + effect = ITEM_HP_CHANGE; + } + + return effect; +} + +static enum ItemEffect TryStickyBarbOnTargetHit(u32 battlerDef, u32 battlerAtk, u32 item) +{ + enum ItemEffect effect = ITEM_NO_EFFECT; + + if (IsBattlerTurnDamaged(battlerDef) + && !CanBattlerAvoidContactEffects(battlerAtk, battlerDef, GetBattlerAbility(battlerAtk), GetBattlerHoldEffect(battlerAtk), gCurrentMove) + && !DoesSubstituteBlockMove(battlerAtk, battlerDef, gCurrentMove) + && IsBattlerAlive(battlerAtk) + && CanStealItem(battlerAtk, battlerDef, item) + && gBattleMons[battlerAtk].item == ITEM_NONE) + { + // No sticky hold checks. + gEffectBattler = battlerDef; + StealTargetItem(battlerAtk, battlerDef); // Attacker takes target's barb + BattleScriptCall(BattleScript_StickyBarbTransfer); + effect = ITEM_EFFECT_OTHER; + } + + return effect; +} + +static enum ItemEffect TryStickyBarbOnEndTurn(u32 battler, u32 item) +{ + enum ItemEffect effect = ITEM_NO_EFFECT; + + if (!IsAbilityAndRecord(battler, GetBattlerAbility(battler), ABILITY_MAGIC_GUARD)) + { + SetPassiveDamageAmount(battler, GetNonDynamaxMaxHP(battler) / 8); + PREPARE_ITEM_BUFFER(gBattleTextBuff1, item); + BattleScriptExecute(BattleScript_ItemHurtEnd2); + effect = ITEM_HP_CHANGE; + } + + return effect; +} + +static enum ItemEffect TryToxicOrb(u32 battler) +{ + enum ItemEffect effect = ITEM_NO_EFFECT; + enum Ability ability = GetBattlerAbility(battler); + + if (CanBePoisoned(battler, battler, ability, ability)) // Can corrosion trigger toxic orb on itself? + { + gBattleMons[battler].status1 = STATUS1_TOXIC_POISON; + BattleScriptExecute(BattleScript_ToxicOrb); + effect = ITEM_STATUS_CHANGE; + } + + return effect; +} + +static enum ItemEffect TryFlameOrb(u32 battler) +{ + enum ItemEffect effect = ITEM_NO_EFFECT; + enum Ability ability = GetBattlerAbility(battler); + + if (CanBeBurned(battler, battler, ability)) + { + gBattleMons[battler].status1 = STATUS1_BURN; + BattleScriptExecute(BattleScript_FlameOrb); + effect = ITEM_STATUS_CHANGE; + } + + return effect; +} + +static enum ItemEffect TryLeftovers(u32 battler, enum HoldEffect holdEffect) +{ + enum ItemEffect effect = ITEM_NO_EFFECT; + + if (gBattleMons[battler].hp < gBattleMons[battler].maxHP + && !(B_HEAL_BLOCKING >= GEN_5 && gBattleMons[battler].volatiles.healBlock)) + { + SetHealAmount(battler, GetNonDynamaxMaxHP(battler) / 16); + RecordItemEffectBattle(battler, holdEffect); + BattleScriptExecute(BattleScript_ItemHealHP_End2); + effect = ITEM_HP_CHANGE; + } + + return effect; +} + +static enum ItemEffect TryBlackSludgeDamage(u32 battler, enum HoldEffect holdEffect) +{ + enum ItemEffect effect = ITEM_NO_EFFECT; + + if (!IsAbilityAndRecord(battler, GetBattlerAbility(battler), ABILITY_MAGIC_GUARD)) + { + SetPassiveDamageAmount(battler, GetNonDynamaxMaxHP(battler) / 8); + RecordItemEffectBattle(battler, holdEffect); + BattleScriptExecute(BattleScript_ItemHurtEnd2); + effect = ITEM_HP_CHANGE; + } + + return effect; +} + +static enum ItemEffect TryCureParalysis(u32 battler, ActivationTiming timing) +{ + enum ItemEffect effect = ITEM_NO_EFFECT; + + if (gBattleMons[battler].status1 & STATUS1_PARALYSIS) + { + gBattleMons[battler].status1 &= ~STATUS1_PARALYSIS; + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_CURED_PARALYSIS; + if (timing == IsOnSwitchInFirstTurnActivation) + BattleScriptExecute(BattleScript_BerryCureStatusEnd2); + else + BattleScriptCall(BattleScript_BerryCureStatusRet); + effect = ITEM_STATUS_CHANGE; + } + + return effect; +} + +static enum ItemEffect TryCurePoison(u32 battler, ActivationTiming timing) +{ + enum ItemEffect effect = ITEM_NO_EFFECT; + + if (gBattleMons[battler].status1 & STATUS1_PSN_ANY) + { + gBattleMons[battler].status1 &= ~(STATUS1_PSN_ANY | STATUS1_TOXIC_COUNTER); + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_CURED_POISON; + if (timing == IsOnSwitchInFirstTurnActivation) + BattleScriptExecute(BattleScript_BerryCureStatusEnd2); + else + BattleScriptCall(BattleScript_BerryCureStatusRet); + effect = ITEM_STATUS_CHANGE; + } + + return effect; +} + +static enum ItemEffect TryCureBurn(u32 battler, ActivationTiming timing) +{ + enum ItemEffect effect = ITEM_NO_EFFECT; + + if (gBattleMons[battler].status1 & STATUS1_BURN) + { + gBattleMons[battler].status1 &= ~STATUS1_BURN; + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_CURED_BURN; + if (timing == IsOnSwitchInFirstTurnActivation) + BattleScriptExecute(BattleScript_BerryCureStatusEnd2); + else + BattleScriptCall(BattleScript_BerryCureStatusRet); + effect = ITEM_STATUS_CHANGE; + } + + return effect; +} + +static enum ItemEffect TryCureFreezeOrFrostbite(u32 battler, ActivationTiming timing) +{ + enum ItemEffect effect = ITEM_NO_EFFECT; + + if (gBattleMons[battler].status1 & STATUS1_FREEZE) + { + gBattleMons[battler].status1 &= ~STATUS1_FREEZE; + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_CURED_FREEEZE; + effect = ITEM_STATUS_CHANGE; + } + else if (gBattleMons[battler].status1 & STATUS1_FROSTBITE) + { + gBattleMons[battler].status1 &= ~STATUS1_FROSTBITE; + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_CURED_FROSTBITE; + effect = ITEM_STATUS_CHANGE; + } + + if (effect == ITEM_STATUS_CHANGE) + { + if (timing == IsOnSwitchInFirstTurnActivation) + BattleScriptExecute(BattleScript_BerryCureStatusEnd2); + else + BattleScriptCall(BattleScript_BerryCureStatusRet); + } + + return effect; +} + +static enum ItemEffect TryCureSleep(u32 battler, ActivationTiming timing) +{ + enum ItemEffect effect = ITEM_NO_EFFECT; + + if (gBattleMons[battler].status1 & STATUS1_SLEEP) + { + gBattleMons[battler].status1 &= ~STATUS1_SLEEP; + gBattleMons[battler].volatiles.nightmare = FALSE; + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_CURED_SLEEP; + TryDeactivateSleepClause(GetBattlerSide(battler), gBattlerPartyIndexes[battler]); + if (timing == IsOnSwitchInFirstTurnActivation) + BattleScriptExecute(BattleScript_BerryCureStatusEnd2); + else + BattleScriptCall(BattleScript_BerryCureStatusRet); + effect = ITEM_STATUS_CHANGE; + } + + return effect; +} + +static enum ItemEffect TryCureConfusion(u32 battler, ActivationTiming timing) +{ + enum ItemEffect effect = ITEM_NO_EFFECT; + + if (gBattleMons[battler].volatiles.confusionTurns > 0) + { + RemoveConfusionStatus(battler); + if (timing == IsOnSwitchInFirstTurnActivation) + BattleScriptExecute(BattleScript_BerryCureConfusionEnd2); + else + BattleScriptCall(BattleScript_BerryCureConfusionRet); + effect = ITEM_EFFECT_OTHER; + } + + return effect; +} + +static enum ItemEffect TryCureAnyStatus(u32 battler, ActivationTiming timing) +{ + enum ItemEffect effect = ITEM_NO_EFFECT; + u32 string = 0; + + if ((gBattleMons[battler].status1 & STATUS1_ANY || gBattleMons[battler].volatiles.confusionTurns > 0)) + { + if (gBattleMons[battler].status1 & STATUS1_PSN_ANY) + { + StringCopy(gBattleTextBuff1, gStatusConditionString_PoisonJpn); + string++; + } + if (gBattleMons[battler].status1 & STATUS1_SLEEP) + { + gBattleMons[battler].volatiles.nightmare = FALSE; + StringCopy(gBattleTextBuff1, gStatusConditionString_SleepJpn); + TryDeactivateSleepClause(GetBattlerSide(battler), gBattlerPartyIndexes[battler]); + string++; + } + if (gBattleMons[battler].status1 & STATUS1_PARALYSIS) + { + StringCopy(gBattleTextBuff1, gStatusConditionString_ParalysisJpn); + string++; + } + if (gBattleMons[battler].status1 & STATUS1_BURN) + { + StringCopy(gBattleTextBuff1, gStatusConditionString_BurnJpn); + string++; + } + if (gBattleMons[battler].status1 & STATUS1_FREEZE || gBattleMons[battler].status1 & STATUS1_FROSTBITE) + { + StringCopy(gBattleTextBuff1, gStatusConditionString_IceJpn); + string++; + } + if (gBattleMons[battler].volatiles.confusionTurns > 0) + { + StringCopy(gBattleTextBuff1, gStatusConditionString_ConfusionJpn); + string++; + } + if (string <= 1) + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_CURED_PROBLEM; + else + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_NORMALIZED_STATUS; + gBattleMons[battler].status1 = 0; + RemoveConfusionStatus(battler); + if (timing == IsOnSwitchInFirstTurnActivation) + BattleScriptExecute(BattleScript_BerryCureStatusEnd2); + else + BattleScriptCall(BattleScript_BerryCureStatusRet); + effect = ITEM_STATUS_CHANGE; + } + + return effect; +} + +enum HealAmount +{ + FIXED_HEAL_AMOUNT, + PERCENT_HEAL_AMOUNT, +}; + +static u32 ItemHealHp(u32 battler, u32 itemId, enum HealAmount percentHeal, ActivationTiming timing) +{ + enum ItemEffect effect = ITEM_NO_EFFECT; + enum Ability ability = GetBattlerAbility(battler); + + if (!(gBattleScripting.overrideBerryRequirements && gBattleMons[battler].hp == gBattleMons[battler].maxHP) + && !(B_HEAL_BLOCKING >= GEN_5 && gBattleMons[battler].volatiles.healBlock) + && HasEnoughHpToEatBerry(battler, ability, 2, itemId)) + { + s32 healAmount = 0; + if (percentHeal == PERCENT_HEAL_AMOUNT) + healAmount = (GetNonDynamaxMaxHP(battler) * GetItemHoldEffectParam(itemId) / 100); + else + healAmount = GetItemHoldEffectParam(itemId); + + if (ability == ABILITY_RIPEN && GetItemPocket(itemId) == POCKET_BERRIES) + healAmount *= 2; + + SetHealAmount(battler, healAmount); + if (timing == IsOnSwitchInFirstTurnActivation) + BattleScriptExecute(BattleScript_ItemHealHP_RemoveItemEnd2); + else + BattleScriptCall(BattleScript_ItemHealHP_RemoveItemRet); + + effect = ITEM_HP_CHANGE; + } + + return effect; +} + +static u32 ItemRestorePp(u32 battler, u32 itemId, ActivationTiming timing) +{ + enum ItemEffect effect = ITEM_NO_EFFECT; + struct Pokemon *mon = GetBattlerMon(battler); + u32 i, changedPP = 0; + enum Ability ability = GetBattlerAbility(battler); + + for (i = 0; i < MAX_MON_MOVES; i++) + { + u32 move = GetMonData(mon, MON_DATA_MOVE1 + i); + u32 currentPP = GetMonData(mon, MON_DATA_PP1 + i); + u32 ppBonuses = GetMonData(mon, MON_DATA_PP_BONUSES); + u32 maxPP = CalculatePPWithBonus(move, ppBonuses, i); + if (move && (currentPP == 0 || (gBattleScripting.overrideBerryRequirements && currentPP != maxPP))) + { + u32 ppRestored = GetItemHoldEffectParam(itemId); + + if (ability == ABILITY_RIPEN) + { + ppRestored *= 2; + gBattlerAbility = battler; + } + if (currentPP + ppRestored > maxPP) + changedPP = maxPP; + else + changedPP = currentPP + ppRestored; + + PREPARE_MOVE_BUFFER(gBattleTextBuff1, move); + + if (timing == IsOnSwitchInFirstTurnActivation) + BattleScriptExecute(BattleScript_BerryPPHealEnd2); + else + BattleScriptCall(BattleScript_BerryPPHealRet); + + gBattleScripting.battler = battler; + BtlController_EmitSetMonData(battler, B_COMM_TO_CONTROLLER, i + REQUEST_PPMOVE1_BATTLE, 0, 1, &changedPP); + MarkBattlerForControllerExec(battler); + if (MOVE_IS_PERMANENT(battler, i)) + gBattleMons[battler].pp[i] = changedPP; + effect = ITEM_PP_CHANGE; + } + } + return effect; +} + +static enum ItemEffect HealConfuseBerry(u32 battler, u32 itemId, u32 flavorId, ActivationTiming timing) +{ + enum ItemEffect effect = ITEM_NO_EFFECT; + u32 hpFraction = B_CONFUSE_BERRIES_HEAL >= GEN_7 ? 4 : 2; + u32 ability = GetBattlerAbility(battler); + + if (HasEnoughHpToEatBerry(battler, ability, hpFraction, itemId) + && !(B_HEAL_BLOCKING >= GEN_5 && gBattleMons[battler].volatiles.healBlock)) + { + s32 healAmount = GetNonDynamaxMaxHP(battler) / GetItemHoldEffectParam(itemId); + if (ability == ABILITY_RIPEN) + healAmount *= 2; + SetHealAmount(battler, healAmount); + if (timing == IsOnSwitchInFirstTurnActivation) + { + if (GetFlavorRelationByPersonality(gBattleMons[battler].personality, flavorId) < 0) + BattleScriptExecute(BattleScript_BerryConfuseHealEnd2); + else + BattleScriptExecute(BattleScript_ItemHealHP_RemoveItemEnd2); + } + else + { + if (GetFlavorRelationByPersonality(gBattleMons[battler].personality, flavorId) < 0) + BattleScriptCall(BattleScript_BerryConfuseHealRet); + else + BattleScriptCall(BattleScript_ItemHealHP_RemoveItemRet); + } + PREPARE_FLAVOR_BUFFER(gBattleTextBuff1, flavorId); + effect = ITEM_HP_CHANGE; + } + + return effect; +} + +static enum ItemEffect StatRaiseBerry(u32 battler, u32 itemId, enum Stat statId, ActivationTiming timing) +{ + enum ItemEffect effect = ITEM_NO_EFFECT; + enum Ability ability = GetBattlerAbility(battler); + + if (CompareStat(battler, statId, MAX_STAT_STAGE, CMP_LESS_THAN, ability) + && HasEnoughHpToEatBerry(battler, ability, GetItemHoldEffectParam(itemId), itemId)) + { + gEffectBattler = gBattleScripting.battler = battler; + SET_STATCHANGER(statId, ability == ABILITY_RIPEN ? 2 : 1, FALSE); + gBattleScripting.animArg1 = STAT_ANIM_PLUS1 + statId; + gBattleScripting.animArg2 = 0; + + if (timing == IsOnSwitchInFirstTurnActivation) + BattleScriptExecute(BattleScript_ConsumableStatRaiseEnd2); + else + BattleScriptCall(BattleScript_ConsumableStatRaiseRet); + effect = ITEM_STATS_CHANGE; + } + + return effect; +} + +static enum ItemEffect CriticalHitRatioUp(u32 battler, u32 itemId, ActivationTiming timing) +{ + enum ItemEffect effect = ITEM_NO_EFFECT; + + if (!gBattleMons[battler].volatiles.focusEnergy + && !gBattleMons[battler].volatiles.dragonCheer + && HasEnoughHpToEatBerry(battler, GetBattlerAbility(battler), GetItemHoldEffectParam(itemId), itemId)) + { + gBattleMons[battler].volatiles.focusEnergy = TRUE; + if (timing == IsOnSwitchInFirstTurnActivation) + BattleScriptExecute(BattleScript_BerryFocusEnergyEnd2); + else + BattleScriptCall(BattleScript_BerryFocusEnergyRet); + effect = ITEM_EFFECT_OTHER; + } + + return effect; +} + +static enum ItemEffect RandomStatRaiseBerry(u32 battler, u32 itemId, ActivationTiming timing) +{ + enum ItemEffect effect = ITEM_NO_EFFECT; + enum Stat stat; + enum Ability ability = GetBattlerAbility(battler); + + for (stat = STAT_ATK; stat < NUM_STATS; stat++) + { + if (CompareStat(battler, stat, MAX_STAT_STAGE, CMP_LESS_THAN, ability)) + break; + } + + if (stat == NUM_STATS) + return effect; + + if (HasEnoughHpToEatBerry(battler, ability, GetItemHoldEffectParam(itemId), itemId)) + { + u32 savedAttacker = gBattlerAttacker; + // MoodyCantRaiseStat requires that the battler is set to gBattlerAttacker + gBattlerAttacker = gBattleScripting.battler = battler; + gBattleScripting.statChanger = 0; + if (ability != ABILITY_CONTRARY) + stat = RandomUniformExcept(RNG_RANDOM_STAT_UP, STAT_ATK, NUM_STATS - 1, MoodyCantRaiseStat); + else + stat = RandomUniformExcept(RNG_RANDOM_STAT_UP, STAT_ATK, NUM_STATS - 1, MoodyCantLowerStat); + gBattlerAttacker = savedAttacker; + + PREPARE_STAT_BUFFER(gBattleTextBuff1, stat); + SET_STATCHANGER(stat, ability == ABILITY_RIPEN ? 4 : 2, FALSE); + gBattleScripting.animArg1 = STAT_ANIM_PLUS2 + stat; + gBattleScripting.animArg2 = 0; + if (timing == IsOnSwitchInFirstTurnActivation) + BattleScriptExecute(BattleScript_ConsumableStatRaiseEnd2); + else + BattleScriptCall(BattleScript_ConsumableStatRaiseRet); + effect = ITEM_STATS_CHANGE; + } + + return effect; +} + +static enum ItemEffect TrySetMicleBerry(u32 battler, u32 itemId, ActivationTiming timing) +{ + enum ItemEffect effect = ITEM_NO_EFFECT; + + if (HasEnoughHpToEatBerry(battler, GetBattlerAbility(battler), 4, itemId)) + { + gBattleStruct->battlerState[battler].usedMicleBerry = TRUE; + if (timing == IsOnSwitchInFirstTurnActivation) + BattleScriptExecute(BattleScript_MicleBerryActivateEnd2); + else + BattleScriptCall(BattleScript_MicleBerryActivateRet); + effect = ITEM_EFFECT_OTHER; + } + return effect; +} + +enum ItemEffect ItemBattleEffects(u32 itemBattler, u32 battler, enum HoldEffect holdEffect, ActivationTiming timing) +{ + enum ItemEffect effect = ITEM_NO_EFFECT; + u32 item; + + if (timing == IsOnBerryActivation || timing == IsOnFlingActivation) + item = gLastUsedItem; + else + item = gBattleMons[itemBattler].item; + + if (holdEffect == HOLD_EFFECT_NONE + || !timing(holdEffect) + || IsUnnerveBlocked(itemBattler, item)) + return effect; + + if (!IsBattlerAlive(itemBattler) + && holdEffect != HOLD_EFFECT_ROWAP_BERRY // Hacky workaround for them right now + && holdEffect != HOLD_EFFECT_JABOCA_BERRY + && holdEffect != HOLD_EFFECT_ROCKY_HELMET) + return effect; + + switch (holdEffect) + { + case HOLD_EFFECT_DOUBLE_PRIZE: + effect = TryDoublePrize(itemBattler); + break; + case HOLD_EFFECT_ROOM_SERVICE: + effect = TryRoomService(itemBattler, timing); + break; + case HOLD_EFFECT_TERRAIN_SEED: + effect = TryTerrainSeeds(itemBattler, item, timing); + break; + case HOLD_EFFECT_BERSERK_GENE: + effect = TryBerserkGene(itemBattler, timing); + break; + case HOLD_EFFECT_BOOSTER_ENERGY: + effect = TryBoosterEnergy(itemBattler, GetBattlerAbility(itemBattler), timing); + break; + case HOLD_EFFECT_WHITE_HERB: + effect = RestoreWhiteHerbStats(itemBattler, timing); + break; + case HOLD_EFFECT_MIRROR_HERB: + effect = TryConsumeMirrorHerb(itemBattler, timing); + break; + case HOLD_EFFECT_FLINCH: // Kings Rock + effect = TryKingsRock(itemBattler, battler, item); + break; + case HOLD_EFFECT_AIR_BALLOON: + effect = TryAirBalloon(itemBattler, timing); + break; + case HOLD_EFFECT_ROCKY_HELMET: + effect = TryRockyHelmet(itemBattler, battler, item); + break; + case HOLD_EFFECT_WEAKNESS_POLICY: + effect = TryWeaknessPolicy(itemBattler); + break; + case HOLD_EFFECT_SNOWBALL: + effect = TrySnowball(itemBattler); + break; + case HOLD_EFFECT_LUMINOUS_MOSS: + effect = TryLuminousMoss(itemBattler); + break; + case HOLD_EFFECT_CELL_BATTERY: + effect = TryCellBattery(itemBattler); + break; + case HOLD_EFFECT_ABSORB_BULB: + effect = TryAbsorbBulb(itemBattler); + break; + case HOLD_EFFECT_JABOCA_BERRY: + effect = TryJabocaBerry(itemBattler, battler, item); + break; + case HOLD_EFFECT_ROWAP_BERRY: + effect = TryRowapBerry(itemBattler, battler, item); + break; + case HOLD_EFFECT_ENIGMA_BERRY: // consume and heal if hit by super effective move + effect = TrySetEnigmaBerry(itemBattler, battler); + break; + case HOLD_EFFECT_BLUNDER_POLICY: + effect = TryBlunderPolicy(itemBattler); + break; + case HOLD_EFFECT_MENTAL_HERB: + effect = TryMentalHerb(itemBattler); + break; + case HOLD_EFFECT_THROAT_SPRAY: + effect = TryThroatSpray(itemBattler); + break; + case HOLD_EFFECT_KEE_BERRY: // consume and boost defense if used physical move + effect = DamagedStatBoostBerryEffect(itemBattler, battler, STAT_DEF, DAMAGE_CATEGORY_PHYSICAL); + break; + case HOLD_EFFECT_MARANGA_BERRY: // consume and boost sp. defense if used special move + effect = DamagedStatBoostBerryEffect(itemBattler, battler, STAT_SPDEF, DAMAGE_CATEGORY_SPECIAL); + break; + case HOLD_EFFECT_SHELL_BELL: + effect = TryShellBell(itemBattler); + break; + case HOLD_EFFECT_LIFE_ORB: + effect = TryLifeOrb(itemBattler); + break; + case HOLD_EFFECT_STICKY_BARB: + if (timing == IsOnTargetHitActivation) + effect = TryStickyBarbOnTargetHit(itemBattler, battler, item); + else + effect = TryStickyBarbOnEndTurn(itemBattler, item); + break; + case HOLD_EFFECT_TOXIC_ORB: + effect = TryToxicOrb(itemBattler); + break; + case HOLD_EFFECT_FLAME_ORB: + effect = TryFlameOrb(itemBattler); + break; + case HOLD_EFFECT_LEFTOVERS: + effect = TryLeftovers(itemBattler, holdEffect); + break; + case HOLD_EFFECT_BLACK_SLUDGE: + if (IS_BATTLER_OF_TYPE(itemBattler, TYPE_POISON)) + effect = TryLeftovers(itemBattler, holdEffect); + else + effect = TryBlackSludgeDamage(itemBattler, holdEffect); + break; + case HOLD_EFFECT_CURE_PAR: // Cheri Berry + effect = TryCureParalysis(itemBattler, timing); + break; + case HOLD_EFFECT_CURE_PSN: // Pecha Berry + effect = TryCurePoison(itemBattler, timing); + break; + case HOLD_EFFECT_CURE_BRN: // Rawst Berry + effect = TryCureBurn(itemBattler, timing); + break; + case HOLD_EFFECT_CURE_FRZ: // Aspear Berry + effect = TryCureFreezeOrFrostbite(itemBattler, timing); + break; + case HOLD_EFFECT_CURE_SLP: // Chesto Berry + effect = TryCureSleep(itemBattler, timing); + break; + case HOLD_EFFECT_CURE_CONFUSION: // Persim Berry + effect = TryCureConfusion(itemBattler, timing); + break; + case HOLD_EFFECT_CURE_STATUS: // Lum Berry + effect = TryCureAnyStatus(itemBattler, timing); + break; + case HOLD_EFFECT_RESTORE_HP: // Oran / Sitrus Berry / Berry Juice + effect = ItemHealHp(itemBattler, item, FIXED_HEAL_AMOUNT, timing); + break; + case HOLD_EFFECT_RESTORE_PCT_HP: // Sitrus Berry + effect = ItemHealHp(itemBattler, item, PERCENT_HEAL_AMOUNT, timing); + break; + case HOLD_EFFECT_RESTORE_PP: // Leppa Berry + effect = ItemRestorePp(itemBattler, item, timing); + break; + case HOLD_EFFECT_CONFUSE_SPICY: // Figy Berry + effect = HealConfuseBerry(itemBattler, item, FLAVOR_SPICY, timing); + break; + case HOLD_EFFECT_CONFUSE_DRY: // Wiki Berry + effect = HealConfuseBerry(itemBattler, item, FLAVOR_DRY, timing); + break; + case HOLD_EFFECT_CONFUSE_SWEET: // Mago Berry + effect = HealConfuseBerry(itemBattler, item, FLAVOR_SWEET, timing); + break; + case HOLD_EFFECT_CONFUSE_BITTER: // Aguav Berry + effect = HealConfuseBerry(itemBattler, item, FLAVOR_BITTER, timing); + break; + case HOLD_EFFECT_CONFUSE_SOUR: // Iapapa Berry + effect = HealConfuseBerry(itemBattler, item, FLAVOR_SOUR, timing); + break; + case HOLD_EFFECT_ATTACK_UP: // Liechi Berry + effect = StatRaiseBerry(itemBattler, item, STAT_ATK, timing); + break; + case HOLD_EFFECT_DEFENSE_UP: // Ganlon Berry + effect = StatRaiseBerry(itemBattler, item, STAT_DEF, timing); + break; + case HOLD_EFFECT_SPEED_UP: // Salac Berry + effect = StatRaiseBerry(itemBattler, item, STAT_SPEED, timing); + break; + case HOLD_EFFECT_SP_ATTACK_UP: // Petaya Berry + effect = StatRaiseBerry(itemBattler, item, STAT_SPATK, timing); + break; + case HOLD_EFFECT_SP_DEFENSE_UP: // Apicot Berry + effect = StatRaiseBerry(itemBattler, item, STAT_SPDEF, timing); + break; + case HOLD_EFFECT_CRITICAL_UP: // Lansat Berry + effect = CriticalHitRatioUp(itemBattler, item, timing); + break; + case HOLD_EFFECT_RANDOM_STAT_UP: // Starf Berry + effect = RandomStatRaiseBerry(itemBattler, item, timing); + break; + case HOLD_EFFECT_MICLE_BERRY: + effect = TrySetMicleBerry(itemBattler, item, timing); + break; + default: + break; + } + + if (effect == ITEM_STATUS_CHANGE) + { + BtlController_EmitSetMonData(itemBattler, B_COMM_TO_CONTROLLER, REQUEST_STATUS_BATTLE, 0, 4, &gBattleMons[itemBattler].status1); + MarkBattlerForControllerExec(itemBattler); + } + + if (effect) + { + gLastUsedItem = item; + gBattleScripting.battler = gPotentialItemEffectBattler = itemBattler; + if ((item >= FIRST_BERRY_INDEX && item <= LAST_BERRY_INDEX)) + GetBattlerPartyState(itemBattler)->ateBerry = TRUE; + } + + return effect; +} diff --git a/src/battle_interface.c b/src/battle_interface.c index e914792c72..e3aa330d1e 100644 --- a/src/battle_interface.c +++ b/src/battle_interface.c @@ -2605,7 +2605,7 @@ static void PrintBattlerOnAbilityPopUp(u8 battler, u8 spriteId1, u8 spriteId2) TRUE, gSprites[spriteId1].sBattlerId); } -static void PrintAbilityOnAbilityPopUp(u32 ability, u8 spriteId1, u8 spriteId2) +static void PrintAbilityOnAbilityPopUp(enum Ability ability, u8 spriteId1, u8 spriteId2) { PrintOnAbilityPopUp(COMPOUND_STRING(" "), (void *)(OBJ_VRAM0) + TILE_OFFSET_4BPP(gSprites[spriteId1].oam.tileNum) + TILE_OFFSET_4BPP(8), @@ -2633,16 +2633,13 @@ static inline bool32 IsAnyAbilityPopUpActive(void) return activeAbilityPopUps; } -void CreateAbilityPopUp(u8 battler, u32 ability, bool32 isDoubleBattle) +void CreateAbilityPopUp(u8 battler, enum Ability ability, bool32 isDoubleBattle) { u8 *spriteIds; u32 xSlide, tileTag, battlerPosition = GetBattlerPosition(battler); struct SpriteTemplate template; const s16 (*coords)[2]; - if (!B_ABILITY_POP_UP) - return; - if (gBattleScripting.abilityPopupOverwrite) ability = gBattleScripting.abilityPopupOverwrite; @@ -2701,7 +2698,7 @@ void CreateAbilityPopUp(u8 battler, u32 ability, bool32 isDoubleBattle) void UpdateAbilityPopup(u8 battler) { u8 *spriteIds = gBattleStruct->abilityPopUpSpriteIds[battler]; - u16 ability = (gBattleScripting.abilityPopupOverwrite) ? gBattleScripting.abilityPopupOverwrite + enum Ability ability = (gBattleScripting.abilityPopupOverwrite) ? gBattleScripting.abilityPopupOverwrite : gBattleMons[battler].ability; PrintAbilityOnAbilityPopUp(ability, spriteIds[0], spriteIds[1]); } diff --git a/src/battle_intro.c b/src/battle_intro.c index 5239a81575..ebc737dac1 100644 --- a/src/battle_intro.c +++ b/src/battle_intro.c @@ -125,6 +125,9 @@ void HandleIntroSlide(u8 environment) } else { + if (environment >= NELEMS(sBattleIntroSlideFuncs) + || sBattleIntroSlideFuncs[environment] == NULL) + environment = BATTLE_ENVIRONMENT_PLAIN; taskId = CreateTask(sBattleIntroSlideFuncs[environment], 0); } diff --git a/src/battle_main.c b/src/battle_main.c index 2c18774f9c..20538985a5 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -6,6 +6,7 @@ #include "battle_arena.h" #include "battle_controllers.h" #include "battle_end_turn.h" +#include "battle_hold_effects.h" #include "battle_interface.h" #include "battle_main.h" #include "battle_message.h" @@ -13,7 +14,6 @@ #include "battle_scripts.h" #include "battle_setup.h" #include "battle_tower.h" -#include "battle_util.h" #include "battle_z_move.h" #include "battle_gimmick.h" #include "berry.h" @@ -53,6 +53,7 @@ #include "string_util.h" #include "strings.h" #include "task.h" +#include "test/battle.h" #include "test_runner.h" #include "text.h" #include "trainer_pools.h" @@ -66,7 +67,6 @@ #include "constants/battle_move_effects.h" #include "constants/battle_string_ids.h" #include "constants/battle_partner.h" -#include "constants/hold_effects.h" #include "constants/items.h" #include "constants/moves.h" #include "constants/party_menu.h" @@ -76,6 +76,7 @@ #include "constants/trainers.h" #include "constants/weather.h" #include "cable_club.h" +#include "test/test_runner_battle.h" extern const struct BgTemplate gBattleBgTemplates[]; extern const struct WindowTemplate *const gBattleWindowTemplates[]; @@ -112,7 +113,7 @@ static void SetActionsAndBattlersTurnOrder(void); static void UpdateBattlerPartyOrdersOnSwitch(u32 battler); static bool8 AllAtActionConfirmed(void); static void TryChangeTurnOrder(void); -static void TryChangingTurnOrderEffects(u32 battler1, u32 battler2, u32 *quickClawRandom, u32 *quickDrawRandom); +static void TryChangingTurnOrderEffects(struct BattleContext *ctx, u32 *quickClawRandom, u32 *quickDrawRandom); static void CheckChangingTurnOrderEffects(void); static void FreeResetData_ReturnToOvOrDoEvolutions(void); static void ReturnFromBattleToOverworld(void); @@ -167,7 +168,7 @@ EWRAM_DATA u16 gChosenMove = 0; EWRAM_DATA u16 gCalledMove = 0; EWRAM_DATA s32 gBideDmg[MAX_BATTLERS_COUNT] = {0}; EWRAM_DATA u16 gLastUsedItem = 0; -EWRAM_DATA u16 gLastUsedAbility = 0; +EWRAM_DATA enum Ability gLastUsedAbility = 0; EWRAM_DATA u8 gBattlerAttacker = 0; EWRAM_DATA u8 gBattlerTarget = 0; EWRAM_DATA u8 gBattlerFainted = 0; @@ -520,6 +521,8 @@ static void CB2_InitBattleInternal(void) } if (gBattleTypeFlags & BATTLE_TYPE_RECORDED) gBattleEnvironment = BATTLE_ENVIRONMENT_BUILDING; + if (TestRunner_Battle_GetForcedEnvironment()) + gBattleEnvironment = TestRunner_Battle_GetForcedEnvironment() - 1; if (gBattleTypeFlags & BATTLE_TYPE_TRAINER && !(gBattleTypeFlags & (BATTLE_TYPE_FRONTIER | BATTLE_TYPE_EREADER_TRAINER @@ -547,9 +550,9 @@ static void CB2_InitBattleInternal(void) SetVBlankCallback(VBlankCB_Battle); SetUpBattleVarsAndBirchZigzagoon(); - if (gBattleTypeFlags & BATTLE_TYPE_MULTI && gBattleTypeFlags & BATTLE_TYPE_BATTLE_TOWER) - SetMainCallback2(CB2_HandleStartMultiPartnerBattle); - else if (gBattleTypeFlags & BATTLE_TYPE_MULTI && gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER) + if ((IsMultibattleTest() && gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER) + || (gBattleTypeFlags & BATTLE_TYPE_MULTI && gBattleTypeFlags & BATTLE_TYPE_BATTLE_TOWER) + || (gBattleTypeFlags & BATTLE_TYPE_MULTI && gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER)) SetMainCallback2(CB2_HandleStartMultiPartnerBattle); else if (gBattleTypeFlags & BATTLE_TYPE_MULTI) SetMainCallback2(CB2_HandleStartMultiBattle); @@ -1984,7 +1987,7 @@ u8 CreateNPCTrainerPartyFromTrainer(struct Pokemon *party, const struct Trainer } if (partyData[monIndex].isShiny) { - u32 data = TRUE; + bool32 data = TRUE; SetMonData(&party[i], MON_DATA_IS_SHINY, &data); } if (partyData[monIndex].dynamaxLevel > 0) @@ -2002,7 +2005,7 @@ u8 CreateNPCTrainerPartyFromTrainer(struct Pokemon *party, const struct Trainer if (partyData[monIndex].teraType > 0) { gBattleStruct->opponentMonCanTera |= 1 << i; - u32 data = partyData[monIndex].teraType; + enum Type data = partyData[monIndex].teraType; SetMonData(&party[i], MON_DATA_TERA_TYPE, &data); } CalculateMonStats(&party[i]); @@ -2981,7 +2984,7 @@ void BeginBattleIntro(void) { BattleStartClearSetData(); gBattleCommunication[1] = 0; - gBattleStruct->introState = 0; + gBattleStruct->eventState.battleIntro = 0; gBattleMainFunc = DoBattleIntro; } @@ -3006,7 +3009,7 @@ static void ClearSetBScriptingStruct(void) gBattleScripting.battleStyle = OPTIONS_BATTLE_STYLE_SET; else gBattleScripting.battleStyle = gSaveBlock2Ptr->optionsBattleStyle; - gBattleScripting.expOnCatch = (B_EXP_CATCH >= GEN_6); + gBattleScripting.expOnCatch = (GetConfig(CONFIG_EXP_CATCH) >= GEN_6); gBattleScripting.specialTrainerBattleType = specialBattleType; } @@ -3015,7 +3018,7 @@ static void BattleStartClearSetData(void) s32 i; TurnValuesCleanUp(FALSE); - SpecialStatusesClear(); + memset(&gSpecialStatuses, 0, sizeof(gSpecialStatuses)); memset(&gDisableStructs, 0, sizeof(gDisableStructs)); memset(&gFieldTimers, 0, sizeof(gFieldTimers)); @@ -3105,13 +3108,12 @@ static void BattleStartClearSetData(void) { gSideTimers[i].stickyWebBattlerId = 0xFF; } - gBattleStruct->appearedInBattle = 0; gBattleStruct->beatUpSlot = 0; for (i = 0; i < PARTY_SIZE; i++) { - gBattleStruct->usedHeldItems[i][B_SIDE_PLAYER] = 0; - gBattleStruct->usedHeldItems[i][B_SIDE_OPPONENT] = 0; + gBattleStruct->partyState[B_SIDE_PLAYER][i].usedHeldItem = ITEM_NONE; + gBattleStruct->partyState[B_SIDE_OPPONENT][i].usedHeldItem = ITEM_NONE; 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; @@ -3187,9 +3189,9 @@ void SwitchInClearSetData(u32 battler, struct Volatiles *volatilesCopy) { if (gBattleMons[i].volatiles.infatuation == INFATUATED_WITH(battler)) gBattleMons[i].volatiles.infatuation = 0; - if (gBattleMons[i].volatiles.wrapped && gBattleStruct->wrappedBy[i] == battler) + if (gBattleMons[i].volatiles.wrapped && gBattleMons[i].volatiles.wrappedBy == battler) gBattleMons[i].volatiles.wrapped = FALSE; - if (gBattleMons[i].volatiles.syrupBomb && gBattleStruct->stickySyrupdBy[i] == battler) + if (gBattleMons[i].volatiles.syrupBomb && gBattleMons[i].volatiles.stickySyrupedBy == battler) gBattleMons[i].volatiles.syrupBomb = FALSE; if (gDisableStructs[i].octolock && gDisableStructs[i].octolockedBy == battler) gDisableStructs[i].octolock = FALSE; @@ -3238,6 +3240,7 @@ void SwitchInClearSetData(u32 battler, struct Volatiles *volatilesCopy) gBattleStruct->battlerState[battler].stompingTantrumTimer = 0; gBattleStruct->palaceFlags &= ~(1u << battler); gBattleStruct->battlerState[battler].canPickupItem = FALSE; + gBattleStruct->battlerState[battler].wasAboveHalfHp = gBattleMons[battler].hp > gBattleMons[battler].maxHP / 2; gBattleStruct->hazardsCounter = 0; gDisableStructs[battler].hazardsDone = FALSE; gSpecialStatuses[battler].switchInItemDone = FALSE; @@ -3260,8 +3263,7 @@ void SwitchInClearSetData(u32 battler, struct Volatiles *volatilesCopy) } gBattleStruct->choicedMove[battler] = MOVE_NONE; - gCurrentMove = MOVE_NONE; - gBattleStruct->arenaTurnCounter = 0xFF; + gBattleStruct->eventState.arenaTurn = 0xFF; // Restore struct member so replacement does not miss timing gSpecialStatuses[battler].switchInAbilityDone = FALSE; @@ -3275,9 +3277,6 @@ void SwitchInClearSetData(u32 battler, struct Volatiles *volatilesCopy) gAiLogicData->ejectButtonSwitch = FALSE; gAiLogicData->ejectPackSwitch = FALSE; - // Reset G-Max Chi Strike boosts. - gBattleStruct->bonusCritStages[battler] = 0; - // Clear selected party ID so Revival Blessing doesn't get confused. gSelectedMonPartyId = PARTY_SIZE; @@ -3313,9 +3312,9 @@ const u8* FaintClearSetData(u32 battler) gBattleMons[i].volatiles.escapePrevention = FALSE; if (gBattleMons[i].volatiles.infatuation == INFATUATED_WITH(battler)) gBattleMons[i].volatiles.infatuation = 0; - if (gBattleMons[i].volatiles.wrapped && gBattleStruct->wrappedBy[i] == battler) + if (gBattleMons[i].volatiles.wrapped && gBattleMons[i].volatiles.wrappedBy == battler) gBattleMons[i].volatiles.wrapped = FALSE; - if (gBattleMons[i].volatiles.syrupBomb && gBattleStruct->stickySyrupdBy[i] == battler) + if (gBattleMons[i].volatiles.syrupBomb && gBattleMons[i].volatiles.stickySyrupedBy == battler) gBattleMons[i].volatiles.syrupBomb = FALSE; if (gDisableStructs[i].octolock && gDisableStructs[i].octolockedBy == battler) gDisableStructs[i].octolock = FALSE; @@ -3339,7 +3338,6 @@ const u8* FaintClearSetData(u32 battler) gProtectStructs[battler].confusionSelfDmg = FALSE; gProtectStructs[battler].chargingTurn = FALSE; gProtectStructs[battler].fleeType = 0; - gProtectStructs[battler].notFirstStrike = FALSE; gProtectStructs[battler].statRaised = FALSE; gProtectStructs[battler].pranksterElevated = FALSE; @@ -3423,9 +3421,10 @@ const u8* FaintClearSetData(u32 battler) // If the released mon can be confused, do so. // Don't use CanBeConfused here, since it can cause issues in edge cases. - if (!(GetBattlerAbility(otherSkyDropper) == ABILITY_OWN_TEMPO + enum Ability ability = GetBattlerAbility(otherSkyDropper); + if (!(ability == ABILITY_OWN_TEMPO || gBattleMons[otherSkyDropper].volatiles.confusionTurns - || IsBattlerTerrainAffected(otherSkyDropper, STATUS_FIELD_MISTY_TERRAIN))) + || IsBattlerTerrainAffected(otherSkyDropper, ability, GetBattlerHoldEffect(otherSkyDropper), STATUS_FIELD_MISTY_TERRAIN))) { gBattleMons[otherSkyDropper].volatiles.confusionTurns = ((Random()) % 4) + 2; gBattlerAttacker = otherSkyDropper; @@ -3443,21 +3442,21 @@ static void DoBattleIntro(void) s32 i; u32 battler; - switch ((enum BattleIntroStates)gBattleStruct->introState) + switch ((enum BattleIntroStates)gBattleStruct->eventState.battleIntro) { case BATTLE_INTRO_STATE_GET_MON_DATA: battler = gBattleCommunication[1]; BtlController_EmitGetMonData(battler, B_COMM_TO_CONTROLLER, REQUEST_ALL_BATTLE, 0); MarkBattlerForControllerExec(battler); - gBattleStruct->introState++; + gBattleStruct->eventState.battleIntro++; break; case BATTLE_INTRO_STATE_LOOP_BATTLER_DATA: if (!gBattleControllerExecFlags) { if (++gBattleCommunication[1] == gBattlersCount) - gBattleStruct->introState++; + gBattleStruct->eventState.battleIntro++; else - gBattleStruct->introState = BATTLE_INTRO_STATE_GET_MON_DATA; + gBattleStruct->eventState.battleIntro = BATTLE_INTRO_STATE_GET_MON_DATA; } break; case BATTLE_INTRO_STATE_PREPARE_BG_SLIDE: @@ -3468,12 +3467,12 @@ static void DoBattleIntro(void) MarkBattlerForControllerExec(battler); gBattleCommunication[0] = 0; gBattleCommunication[1] = 0; - gBattleStruct->introState++; + gBattleStruct->eventState.battleIntro++; } break; case BATTLE_INTRO_STATE_WAIT_FOR_BG_SLIDE: if (!gBattleControllerExecFlags) - gBattleStruct->introState++; + gBattleStruct->eventState.battleIntro++; break; case BATTLE_INTRO_STATE_DRAW_SPRITES: for (battler = 0; battler < gBattlersCount; battler++) @@ -3554,9 +3553,9 @@ static void DoBattleIntro(void) } if (gBattleTypeFlags & BATTLE_TYPE_TRAINER) - gBattleStruct->introState++; + gBattleStruct->eventState.battleIntro++; else // Skip party summary since it is a wild battle. - gBattleStruct->introState = BATTLE_INTRO_STATE_INTRO_TEXT; + gBattleStruct->eventState.battleIntro = BATTLE_INTRO_STATE_INTRO_TEXT; break; case BATTLE_INTRO_STATE_DRAW_PARTY_SUMMARY: if (!gBattleControllerExecFlags) @@ -3601,18 +3600,18 @@ static void DoBattleIntro(void) BtlController_EmitDrawPartyStatusSummary(battler, B_COMM_TO_CONTROLLER, hpStatus, PARTY_SUMM_SKIP_DRAW_DELAY); MarkBattlerForControllerExec(battler); - gBattleStruct->introState++; + gBattleStruct->eventState.battleIntro++; } break; case BATTLE_INTRO_STATE_WAIT_FOR_PARTY_SUMMARY: if (!gBattleControllerExecFlags) - gBattleStruct->introState++; + gBattleStruct->eventState.battleIntro++; break; case BATTLE_INTRO_STATE_INTRO_TEXT: if (!IsBattlerMarkedForControllerExec(GetBattlerAtPosition(B_POSITION_PLAYER_LEFT))) { PrepareStringBattle(STRINGID_INTROMSG, GetBattlerAtPosition(B_POSITION_PLAYER_LEFT)); - gBattleStruct->introState++; + gBattleStruct->eventState.battleIntro++; } break; case BATTLE_INTRO_STATE_WAIT_FOR_INTRO_TEXT: @@ -3620,14 +3619,14 @@ static void DoBattleIntro(void) { if (gBattleTypeFlags & BATTLE_TYPE_TRAINER) { - gBattleStruct->introState++; + gBattleStruct->eventState.battleIntro++; } else { if (B_FAST_INTRO_PKMN_TEXT == TRUE) - gBattleStruct->introState = BATTLE_INTRO_STATE_WAIT_FOR_WILD_BATTLE_TEXT; + gBattleStruct->eventState.battleIntro = BATTLE_INTRO_STATE_WAIT_FOR_WILD_BATTLE_TEXT; else - gBattleStruct->introState = BATTLE_INTRO_STATE_WAIT_FOR_TRAINER_2_SEND_OUT_ANIM; + gBattleStruct->eventState.battleIntro = BATTLE_INTRO_STATE_WAIT_FOR_TRAINER_2_SEND_OUT_ANIM; } } break; @@ -3636,11 +3635,11 @@ static void DoBattleIntro(void) PrepareStringBattle(STRINGID_INTROSENDOUT, GetBattlerAtPosition(B_POSITION_PLAYER_LEFT)); else PrepareStringBattle(STRINGID_INTROSENDOUT, GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT)); - gBattleStruct->introState++; + gBattleStruct->eventState.battleIntro++; break; case BATTLE_INTRO_STATE_WAIT_FOR_TRAINER_SEND_OUT_TEXT: if (!gBattleControllerExecFlags) - gBattleStruct->introState++; + gBattleStruct->eventState.battleIntro++; break; case BATTLE_INTRO_STATE_TRAINER_1_SEND_OUT_ANIM: if (gBattleTypeFlags & BATTLE_TYPE_RECORDED_LINK && !(gBattleTypeFlags & BATTLE_TYPE_RECORDED_IS_MASTER)) @@ -3650,7 +3649,7 @@ static void DoBattleIntro(void) BtlController_EmitIntroTrainerBallThrow(battler, B_COMM_TO_CONTROLLER); MarkBattlerForControllerExec(battler); - gBattleStruct->introState++; + gBattleStruct->eventState.battleIntro++; break; case BATTLE_INTRO_STATE_TRAINER_2_SEND_OUT_ANIM: if (gBattleTypeFlags & (BATTLE_TYPE_MULTI | BATTLE_TYPE_TWO_OPPONENTS) && !BATTLE_TWO_VS_ONE_OPPONENT) @@ -3665,17 +3664,17 @@ static void DoBattleIntro(void) } if (B_FAST_INTRO_PKMN_TEXT == TRUE && !(gBattleTypeFlags & (BATTLE_TYPE_RECORDED | BATTLE_TYPE_RECORDED_LINK | BATTLE_TYPE_RECORDED_IS_MASTER | BATTLE_TYPE_LINK))) - gBattleStruct->introState = BATTLE_INTRO_STATE_WAIT_FOR_WILD_BATTLE_TEXT; // Print at the same time as trainer sends out second mon. + gBattleStruct->eventState.battleIntro = BATTLE_INTRO_STATE_WAIT_FOR_WILD_BATTLE_TEXT; // Print at the same time as trainer sends out second mon. else - gBattleStruct->introState++; + gBattleStruct->eventState.battleIntro++; break; case BATTLE_INTRO_STATE_WAIT_FOR_TRAINER_2_SEND_OUT_ANIM: if (!gBattleControllerExecFlags) - gBattleStruct->introState++; + gBattleStruct->eventState.battleIntro++; break; case BATTLE_INTRO_STATE_WAIT_FOR_WILD_BATTLE_TEXT: if (!IsBattlerMarkedForControllerExec(GetBattlerAtPosition(B_POSITION_PLAYER_LEFT))) - gBattleStruct->introState++; + gBattleStruct->eventState.battleIntro++; break; case BATTLE_INTRO_STATE_PRINT_PLAYER_SEND_OUT_TEXT: if (!(gBattleTypeFlags & BATTLE_TYPE_SAFARI)) @@ -3696,7 +3695,7 @@ static void DoBattleIntro(void) PrepareStringBattle(STRINGID_INTROSENDOUT, battler); } - gBattleStruct->introState++; + gBattleStruct->eventState.battleIntro++; break; case BATTLE_INTRO_STATE_WAIT_FOR_PLAYER_SEND_OUT_TEXT: if (!(gBattleTypeFlags & BATTLE_TYPE_LINK && gBattleControllerExecFlags)) @@ -3707,7 +3706,7 @@ static void DoBattleIntro(void) battler = GetBattlerAtPosition(B_POSITION_PLAYER_LEFT); if (!IsBattlerMarkedForControllerExec(battler)) - gBattleStruct->introState++; + gBattleStruct->eventState.battleIntro++; } break; case BATTLE_INTRO_STATE_PRINT_PLAYER_1_SEND_OUT_TEXT: @@ -3718,7 +3717,7 @@ static void DoBattleIntro(void) BtlController_EmitIntroTrainerBallThrow(battler, B_COMM_TO_CONTROLLER); MarkBattlerForControllerExec(battler); - gBattleStruct->introState++; + gBattleStruct->eventState.battleIntro++; break; case BATTLE_INTRO_STATE_PRINT_PLAYER_2_SEND_OUT_TEXT: if (gBattleTypeFlags & (BATTLE_TYPE_MULTI | BATTLE_TYPE_INGAME_PARTNER)) @@ -3731,14 +3730,13 @@ static void DoBattleIntro(void) BtlController_EmitIntroTrainerBallThrow(battler, B_COMM_TO_CONTROLLER); MarkBattlerForControllerExec(battler); } - gBattleStruct->introState++; + gBattleStruct->eventState.battleIntro++; break; case BATTLE_INTRO_STATE_SET_DEX_AND_BATTLE_VARS: if (!gBattleControllerExecFlags) { - gBattleStruct->eventsBeforeFirstTurnState = 0; + gBattleStruct->eventState.beforeFristTurn = 0; gBattleStruct->switchInBattlerCounter = 0; - gBattleStruct->overworldWeatherDone = FALSE; Ai_InitPartyStruct(); // Save mons party counts, and first 2/4 mons on the battlefield. // mark all battlers as sent out @@ -3775,7 +3773,7 @@ static void TryDoEventsBeforeFirstTurn(void) if (gBattleControllerExecFlags) return; - switch ((enum FirstTurnEventsStates)gBattleStruct->eventsBeforeFirstTurnState) + switch (gBattleStruct->eventState.beforeFristTurn) { case FIRST_TURN_EVENTS_START: // Set invalid mons as absent(for example when starting a double battle with only one pokemon). @@ -3807,45 +3805,40 @@ static void TryDoEventsBeforeFirstTurn(void) gBattleStruct->speedTieBreaks = RandomUniform(RNG_SPEED_TIE, 0, Factorial(MAX_BATTLERS_COUNT) - 1); gBattleTurnCounter = 0; + struct BattleContext ctx = {0}; for (i = 0; i < gBattlersCount; i++) + { gBattlerByTurnOrder[i] = i; + ctx.abilities[i] = GetBattlerAbility(i); + ctx.holdEffects[i] = GetBattlerHoldEffect(i); + } for (i = 0; i < gBattlersCount - 1; i++) { for (j = i + 1; j < gBattlersCount; j++) { - if (GetWhichBattlerFaster(gBattlerByTurnOrder[i], gBattlerByTurnOrder[j], TRUE) == -1) + ctx.battlerAtk = gBattlerByTurnOrder[i]; + ctx.battlerDef = gBattlerByTurnOrder[j]; + + if (GetWhichBattlerFaster(&ctx, TRUE) == -1) SwapTurnOrder(i, j); } } - gBattleStruct->eventsBeforeFirstTurnState++; + gBattleStruct->eventState.beforeFristTurn++; break; case FIRST_TURN_EVENTS_OVERWORLD_WEATHER: - if (!gBattleStruct->overworldWeatherDone - && AbilityBattleEffects(ABILITYEFFECT_SWITCH_IN_WEATHER, 0, 0, ABILITYEFFECT_SWITCH_IN_WEATHER, 0) != 0) - { - gBattleStruct->overworldWeatherDone = TRUE; + gBattleStruct->eventState.beforeFristTurn++; + if (TryFieldEffects(FIELD_EFFECT_OVERWORLD_WEATHER)) return; - } - gBattleStruct->eventsBeforeFirstTurnState++; break; case FIRST_TURN_EVENTS_TERRAIN: - if (!gBattleStruct->terrainDone - && AbilityBattleEffects(ABILITYEFFECT_SWITCH_IN_TERRAIN, 0, 0, ABILITYEFFECT_SWITCH_IN_TERRAIN, 0) != 0) - { - gBattleStruct->terrainDone = TRUE; + gBattleStruct->eventState.beforeFristTurn++; + if (TryFieldEffects(FIELD_EFFECT_OVERWORLD_TERRAIN)) return; - } - gBattleStruct->eventsBeforeFirstTurnState++; break; case FIRST_TURN_EVENTS_STARTING_STATUS: - if (!gBattleStruct->startingStatusDone - && gBattleStruct->startingStatus - && AbilityBattleEffects(ABILITYEFFECT_SWITCH_IN_STATUSES, 0, 0, ABILITYEFFECT_SWITCH_IN_STATUSES, 0) != 0) - { - gBattleStruct->startingStatusDone = TRUE; + gBattleStruct->eventState.beforeFristTurn++; + if (TryFieldEffects(FIELD_EFFECT_TRAINER_STATUSES)) return; - } - gBattleStruct->eventsBeforeFirstTurnState++; break; case FIRST_TURN_EVENTS_TOTEM_BOOST: for (i = 0; i < gBattlersCount; i++) @@ -3858,52 +3851,78 @@ static void TryDoEventsBeforeFirstTurn(void) } } memset(gQueuedStatBoosts, 0, sizeof(gQueuedStatBoosts)); // erase all totem boosts for Mirror Herb and Opportunist - gBattleStruct->eventsBeforeFirstTurnState++; + gBattleStruct->eventState.beforeFristTurn++; break; case FIRST_TURN_EVENTS_NEUTRALIZING_GAS: - if (AbilityBattleEffects(ABILITYEFFECT_NEUTRALIZINGGAS, 0, 0, 0, 0) != 0) - return; - gBattleStruct->eventsBeforeFirstTurnState++; + while (gBattleStruct->switchInBattlerCounter < gBattlersCount) // From fastest to slowest + { + i = gBattlerByTurnOrder[gBattleStruct->switchInBattlerCounter++]; + if (AbilityBattleEffects(ABILITYEFFECT_NEUTRALIZINGGAS_FIRST_TURN, i, 0, 0, 0) != 0) + return; + } + gBattleStruct->switchInBattlerCounter = 0; + gBattleStruct->eventState.beforeFristTurn++; break; case FIRST_TURN_EVENTS_SWITCH_IN_ABILITIES: while (gBattleStruct->switchInBattlerCounter < gBattlersCount) // From fastest to slowest { - i = gBattlerByTurnOrder[gBattleStruct->switchInBattlerCounter++]; + u32 battler = gBattlerByTurnOrder[gBattleStruct->switchInBattlerCounter++]; - if (TryPrimalReversion(i)) + if (TryPrimalReversion(battler)) return; - if (AbilityBattleEffects(ABILITYEFFECT_ON_SWITCHIN, i, 0, 0, 0) != 0) + if (AbilityBattleEffects(ABILITYEFFECT_ON_SWITCHIN, battler, 0, 0, 0)) return; - if (TryClearIllusion(i, ABILITYEFFECT_ON_SWITCHIN)) + if (TryClearIllusion(battler, ABILITYEFFECT_ON_SWITCHIN)) return; - if (AbilityBattleEffects(ABILITYEFFECT_ON_SWITCHIN_IMMUNITIES, i, 0, 0, 0) != 0) + if (AbilityBattleEffects(ABILITYEFFECT_ON_SWITCHIN_IMMUNITIES, battler, 0, 0, 0) != 0) return; } gBattleStruct->switchInBattlerCounter = 0; - gBattleStruct->eventsBeforeFirstTurnState++; - break; - case FIRST_TURN_EVENTS_OPPORTUNIST_1: - if (AbilityBattleEffects(ABILITYEFFECT_OPPORTUNIST, 0, 0, 0, 0)) - return; - gBattleStruct->eventsBeforeFirstTurnState++; + gBattleStruct->eventState.beforeFristTurn++; break; case FIRST_TURN_EVENTS_ITEM_EFFECTS: while (gBattleStruct->switchInBattlerCounter < gBattlersCount) // From fastest to slowest { - if (ItemBattleEffects(ITEMEFFECT_ON_SWITCH_IN_FIRST_TURN, gBattlerByTurnOrder[gBattleStruct->switchInBattlerCounter++])) + u32 battler = gBattlerByTurnOrder[gBattleStruct->switchInBattlerCounter++]; + if (ItemBattleEffects(battler, 0, GetBattlerHoldEffect(battler), IsOnSwitchInFirstTurnActivation)) return; } gBattleStruct->switchInBattlerCounter = 0; - gBattleStruct->eventsBeforeFirstTurnState++; + gBattleStruct->eventState.beforeFristTurn++; break; - case FIRST_TURN_EVENTS_OPPORTUNIST_2: - if (AbilityBattleEffects(ABILITYEFFECT_OPPORTUNIST, 0, 0, 0, 0)) - return; - gBattleStruct->eventsBeforeFirstTurnState++; + case FIRST_TURN_EVENTS_WHITE_HERB: + while (gBattleStruct->switchInBattlerCounter < gBattlersCount) // From fastest to slowest + { + u32 battler = gBattlerByTurnOrder[gBattleStruct->switchInBattlerCounter++]; + if (ItemBattleEffects(battler, 0, GetBattlerHoldEffect(battler), IsWhiteHerbFirstTurnActivation)) + return; + } + gBattleStruct->switchInBattlerCounter = 0; + gBattleStruct->eventState.beforeFristTurn++; + break; + case FIRST_TURN_EVENTS_OPPORTUNIST: + while (gBattleStruct->switchInBattlerCounter < gBattlersCount) // From fastest to slowest + { + u32 battler = gBattlerByTurnOrder[gBattleStruct->switchInBattlerCounter++]; + if (AbilityBattleEffects(ABILITYEFFECT_OPPORTUNIST_FIRST_TURN, battler, GetBattlerAbility(battler), 0, 0)) + return; + } + gBattleStruct->switchInBattlerCounter = 0; + gBattleStruct->eventState.beforeFristTurn++; + break; + case FIRST_TURN_EVENTS_MIRROR_HERB: + while (gBattleStruct->switchInBattlerCounter < gBattlersCount) // From fastest to slowest + { + u32 battler = gBattlerByTurnOrder[gBattleStruct->switchInBattlerCounter++]; + if (ItemBattleEffects(battler, 0, GetBattlerHoldEffect(battler), IsMirrorHerbFirstTurnActivation)) + return; + } + gBattleStruct->switchInBattlerCounter = 0; + gBattleStruct->eventState.beforeFristTurn++; break; case FIRST_TURN_EVENTS_EJECT_PACK: - gBattleStruct->eventsBeforeFirstTurnState++; - if (TrySwitchInEjectPack(ITEMEFFECT_ON_SWITCH_IN_FIRST_TURN)) + gBattleStruct->eventState.beforeFristTurn++; + if (TrySwitchInEjectPack(FIRST_TURN)) return; break; case FIRST_TURN_EVENTS_END: @@ -3914,7 +3933,7 @@ static void TryDoEventsBeforeFirstTurn(void) gChosenMoveByBattler[i] = MOVE_NONE; } TurnValuesCleanUp(FALSE); - SpecialStatusesClear(); + memset(&gSpecialStatuses, 0, sizeof(gSpecialStatuses)); BattlePutTextOnWindow(gText_EmptyString3, B_WIN_MSG); AssignUsableGimmicks(); gBattleMainFunc = HandleTurnActionSelectionState; @@ -3923,19 +3942,11 @@ static void TryDoEventsBeforeFirstTurn(void) for (i = 0; i < BATTLE_COMMUNICATION_ENTRIES_COUNT; i++) gBattleCommunication[i] = 0; - for (i = 0; i < gBattlersCount; i++) - { - gBattleMons[i].volatiles.flinched = FALSE; - // Record party slots of player's mons that appeared in battle - if (!BattlerHasAi(i)) - gBattleStruct->appearedInBattle |= 1u << gBattlerPartyIndexes[i]; - } - - *(&gBattleStruct->eventBlockCounter) = 0; - *(&gBattleStruct->turnEffectsBattlerId) = 0; + gBattleStruct->eventState.endTurnBlock = 0; + gBattleStruct->eventState.endTurnBattler = 0; gBattleScripting.moveendState = 0; - gBattleStruct->faintedActionsState = 0; - gBattleStruct->endTurnEventsCounter = 0; + gBattleStruct->eventState.faintedAction = 0; + gBattleStruct->eventState.endTurn = 0; memset(gQueuedStatBoosts, 0, sizeof(gQueuedStatBoosts)); SetShellSideArmCategory(); @@ -3949,7 +3960,7 @@ static void TryDoEventsBeforeFirstTurn(void) if ((i = ShouldDoTrainerSlide(GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT), TRAINER_SLIDE_BEFORE_FIRST_TURN))) BattleScriptExecute(i == 1 ? BattleScript_TrainerASlideMsgEnd2 : BattleScript_TrainerBSlideMsgEnd2); - gBattleStruct->eventsBeforeFirstTurnState = 0; + gBattleStruct->eventState.beforeFristTurn = 0; break; } } @@ -3969,9 +3980,9 @@ static void HandleEndTurn_ContinueBattle(void) if ((gBattleMons[i].status1 & STATUS1_SLEEP) && (gBattleMons[i].volatiles.multipleTurns)) CancelMultiTurnMoves(i, SKY_DROP_IGNORE); } - gBattleStruct->eventBlockCounter = 0; - gBattleStruct->turnEffectsBattlerId = 0; - gBattleStruct->endTurnEventsCounter = 0; + gBattleStruct->eventState.endTurnBlock = 0; + gBattleStruct->eventState.endTurnBattler = 0; + gBattleStruct->eventState.endTurn = 0; } } @@ -3990,13 +4001,11 @@ void BattleTurnPassed(void) if (HandleFaintedMonActions()) return; - gBattleStruct->faintedActionsState = 0; + gBattleStruct->eventState.faintedAction = 0; TurnValuesCleanUp(FALSE); - gHitMarker &= ~HITMARKER_NO_ATTACKSTRING; gHitMarker &= ~HITMARKER_UNABLE_TO_USE_MOVE; gHitMarker &= ~HITMARKER_PLAYER_FAINTED; - gHitMarker &= ~HITMARKER_PASSIVE_HP_UPDATE; gBattleScripting.animTurn = 0; gBattleScripting.animTargetsHit = 0; gBattleScripting.moveendState = 0; @@ -4014,7 +4023,7 @@ void BattleTurnPassed(void) if (gBattleResults.battleTurnCounter < 0xFF) { gBattleResults.battleTurnCounter++; - gBattleStruct->arenaTurnCounter++; + gBattleStruct->eventState.arenaTurn++; } for (i = 0; i < gBattlersCount; i++) @@ -4046,7 +4055,7 @@ void BattleTurnPassed(void) if (gBattleTypeFlags & BATTLE_TYPE_PALACE) BattleScriptExecute(BattleScript_PalacePrintFlavorText); - else if (gBattleTypeFlags & BATTLE_TYPE_ARENA && gBattleStruct->arenaTurnCounter == 0) + else if (gBattleTypeFlags & BATTLE_TYPE_ARENA && gBattleStruct->eventState.arenaTurn == 0) BattleScriptExecute(BattleScript_ArenaTurnBeginning); else if ((i = ShouldDoTrainerSlide(GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT), TRAINER_SLIDE_LAST_LOW_HP))) BattleScriptExecute(i == 1 ? BattleScript_TrainerASlideMsgEnd2 : BattleScript_TrainerBSlideMsgEnd2); @@ -4066,7 +4075,7 @@ void BattleTurnPassed(void) u8 IsRunningFromBattleImpossible(u32 battler) { - enum ItemHoldEffect holdEffect; + enum HoldEffect holdEffect; u32 i; if (FlagGet(B_FLAG_NO_RUNNING)) @@ -4258,16 +4267,23 @@ static void HandleTurnActionSelectionState(void) if (AreAllMovesUnusable(battler)) { gBattleCommunication[battler] = STATE_SELECTION_SCRIPT; - gBattleStruct->selectionScriptFinished[battler] = FALSE; + gBattleStruct->battlerState[battler].selectionScriptFinished = FALSE; gBattleStruct->stateIdAfterSelScript[battler] = STATE_WAIT_ACTION_CONFIRMED_STANDBY; gBattleStruct->moveTarget[battler] = gBattleResources->bufferB[battler][3]; return; } - else if (GetGenConfig(GEN_CONFIG_ENCORE_TARGET) < GEN_5 && gDisableStructs[battler].encoredMove != MOVE_NONE) + else if (GetConfig(CONFIG_ENCORE_TARGET) < GEN_5 && gDisableStructs[battler].encoredMove != MOVE_NONE) { gChosenMoveByBattler[battler] = gDisableStructs[battler].encoredMove; gBattleStruct->chosenMovePositions[battler] = gDisableStructs[battler].encoredMovePos; gBattleCommunication[battler] = STATE_WAIT_ACTION_CONFIRMED_STANDBY; + if (gTestRunnerEnabled) + { + UNUSED enum Gimmick gimmick = GIMMICK_NONE; + if (gBattleResources->bufferB[battler][2] & RET_GIMMICK) + gimmick = gBattleStruct->gimmick.usableGimmick[battler]; + TestRunner_Battle_CheckChosenMove(battler, gDisableStructs[battler].encoredMove, gDisableStructs[battler].encoredMovePos, gimmick); + } return; } else @@ -4295,12 +4311,12 @@ static void HandleTurnActionSelectionState(void) } break; case B_ACTION_USE_ITEM: - if (FlagGet(B_FLAG_NO_BAG_USE)) + if (ShouldBattleRestrictionsApply(battler) && !IsAllowedToUseBag()) { RecordedBattle_ClearBattlerAction(battler, 1); gSelectionBattleScripts[battler] = BattleScript_ActionSelectionItemsCantBeUsed; gBattleCommunication[battler] = STATE_SELECTION_SCRIPT; - gBattleStruct->selectionScriptFinished[battler] = FALSE; + gBattleStruct->battlerState[battler].selectionScriptFinished = FALSE; gBattleStruct->stateIdAfterSelScript[battler] = STATE_BEFORE_ACTION_CHOSEN; return; } @@ -4316,7 +4332,7 @@ static void HandleTurnActionSelectionState(void) RecordedBattle_ClearBattlerAction(battler, 1); gSelectionBattleScripts[battler] = BattleScript_ActionSelectionItemsCantBeUsed; gBattleCommunication[battler] = STATE_SELECTION_SCRIPT; - gBattleStruct->selectionScriptFinished[battler] = FALSE; + gBattleStruct->battlerState[battler].selectionScriptFinished = FALSE; gBattleStruct->stateIdAfterSelScript[battler] = STATE_BEFORE_ACTION_CHOSEN; return; } @@ -4329,7 +4345,7 @@ static void HandleTurnActionSelectionState(void) case B_ACTION_SWITCH: gBattleStruct->battlerPartyIndexes[battler] = gBattlerPartyIndexes[battler]; if (gBattleTypeFlags & BATTLE_TYPE_ARENA - || (!CanBattlerEscape(battler) && GetBattlerHoldEffect(battler, TRUE) != HOLD_EFFECT_SHED_SHELL)) + || (!CanBattlerEscape(battler) && GetBattlerHoldEffect(battler) != HOLD_EFFECT_SHED_SHELL)) { BtlController_EmitChoosePokemon(battler, B_COMM_TO_CONTROLLER, PARTY_ACTION_CANT_SWITCH, PARTY_SIZE, ABILITY_NONE, 0, gBattleStruct->battlerPartyOrders[battler]); } @@ -4354,7 +4370,7 @@ static void HandleTurnActionSelectionState(void) { gSelectionBattleScripts[battler] = BattleScript_PrintFullBox; gBattleCommunication[battler] = STATE_SELECTION_SCRIPT; - gBattleStruct->selectionScriptFinished[battler] = FALSE; + gBattleStruct->battlerState[battler].selectionScriptFinished = FALSE; gBattleStruct->stateIdAfterSelScript[battler] = STATE_BEFORE_ACTION_CHOSEN; return; } @@ -4415,7 +4431,7 @@ static void HandleTurnActionSelectionState(void) { gSelectionBattleScripts[battler] = BattleScript_AskIfWantsToForfeitMatch; gBattleCommunication[battler] = STATE_SELECTION_SCRIPT_MAY_RUN; - gBattleStruct->selectionScriptFinished[battler] = FALSE; + gBattleStruct->battlerState[battler].selectionScriptFinished = FALSE; gBattleStruct->stateIdAfterSelScript[battler] = STATE_BEFORE_ACTION_CHOSEN; return; } @@ -4423,7 +4439,7 @@ static void HandleTurnActionSelectionState(void) { gSelectionBattleScripts[battler] = BattleScript_QuestionForfeitBattle; gBattleCommunication[battler] = STATE_SELECTION_SCRIPT_MAY_RUN; - gBattleStruct->selectionScriptFinished[battler] = FALSE; + gBattleStruct->battlerState[battler].selectionScriptFinished = FALSE; gBattleStruct->stateIdAfterSelScript[battler] = STATE_BEFORE_ACTION_CHOSEN; return; } @@ -4440,7 +4456,7 @@ static void HandleTurnActionSelectionState(void) { gSelectionBattleScripts[battler] = BattleScript_PrintCantEscapeFromBattle; gBattleCommunication[battler] = STATE_SELECTION_SCRIPT; - gBattleStruct->selectionScriptFinished[battler] = FALSE; + gBattleStruct->battlerState[battler].selectionScriptFinished = FALSE; gBattleStruct->stateIdAfterSelScript[battler] = STATE_BEFORE_ACTION_CHOSEN; return; } @@ -4482,7 +4498,7 @@ static void HandleTurnActionSelectionState(void) { RecordedBattle_ClearBattlerAction(battler, 1); gBattleCommunication[battler] = STATE_SELECTION_SCRIPT; - gBattleStruct->selectionScriptFinished[battler] = FALSE; + gBattleStruct->battlerState[battler].selectionScriptFinished = FALSE; gBattleResources->bufferB[battler][1] = B_ACTION_USE_MOVE; gBattleStruct->stateIdAfterSelScript[battler] = STATE_WAIT_ACTION_CHOSEN; return; @@ -4497,11 +4513,11 @@ static void HandleTurnActionSelectionState(void) // Get the chosen move position (and thus the chosen move) and target from the returned buffer. gBattleStruct->chosenMovePositions[battler] = gBattleResources->bufferB[battler][2] & ~RET_GIMMICK; - gChosenMoveByBattler[battler] = gBattleMons[battler].moves[gBattleStruct->chosenMovePositions[battler]]; + gChosenMoveByBattler[battler] = GetChosenMoveFromPosition(battler); gBattleStruct->moveTarget[battler] = gBattleResources->bufferB[battler][3]; if (IsBattleMoveStatus(gChosenMoveByBattler[battler]) && GetBattlerAbility(battler) == ABILITY_MYCELIUM_MIGHT) gProtectStructs[battler].myceliumMight = TRUE; - if (GetBattlerHoldEffect(battler, TRUE) == HOLD_EFFECT_LAGGING_TAIL) + if (GetBattlerHoldEffect(battler) == HOLD_EFFECT_LAGGING_TAIL) gProtectStructs[battler].laggingTail = TRUE; // Check to see if any gimmicks need to be prepared. @@ -4511,13 +4527,16 @@ static void HandleTurnActionSelectionState(void) // Max Move check if (GetActiveGimmick(battler) == GIMMICK_DYNAMAX || IsGimmickSelected(battler, GIMMICK_DYNAMAX)) { - gBattleStruct->dynamax.baseMoves[battler] = gBattleMons[battler].moves[gBattleStruct->chosenMovePositions[battler]]; + gBattleStruct->dynamax.baseMoves[battler] = GetChosenMoveFromPosition(battler); } gBattleCommunication[battler]++; if (gTestRunnerEnabled) { - TestRunner_Battle_CheckChosenMove(battler, gChosenMoveByBattler[battler], gBattleStruct->moveTarget[battler]); + UNUSED enum Gimmick gimmick = GIMMICK_NONE; + if (gBattleResources->bufferB[battler][2] & RET_GIMMICK) + gimmick = gBattleStruct->gimmick.usableGimmick[battler]; + TestRunner_Battle_CheckChosenMove(battler, gChosenMoveByBattler[battler], gBattleStruct->moveTarget[battler], gimmick); } } break; @@ -4613,7 +4632,7 @@ static void HandleTurnActionSelectionState(void) } break; case STATE_SELECTION_SCRIPT: - if (gBattleStruct->selectionScriptFinished[battler]) + if (gBattleStruct->battlerState[battler].selectionScriptFinished) { gBattleCommunication[battler] = gBattleStruct->stateIdAfterSelScript[battler]; } @@ -4635,7 +4654,7 @@ static void HandleTurnActionSelectionState(void) } break; case STATE_SELECTION_SCRIPT_MAY_RUN: - if (gBattleStruct->selectionScriptFinished[battler]) + if (gBattleStruct->battlerState[battler].selectionScriptFinished) { if (gBattleResources->bufferB[battler][1] == B_ACTION_NOTHING_FAINTED) { @@ -4736,7 +4755,7 @@ void SwapTurnOrder(u8 id1, u8 id2) } // For AI, so it doesn't 'cheat' by knowing player's ability -u32 GetBattlerTotalSpeedStatArgs(u32 battler, u32 ability, enum ItemHoldEffect holdEffect) +u32 GetBattlerTotalSpeedStat(u32 battler, enum Ability ability, enum HoldEffect holdEffect) { u32 speed = gBattleMons[battler].speed; @@ -4765,9 +4784,9 @@ u32 GetBattlerTotalSpeedStatArgs(u32 battler, u32 ability, enum ItemHoldEffect h else if (ability == ABILITY_SLOW_START && gDisableStructs[battler].slowStartTimer != 0) speed /= 2; else if (ability == ABILITY_PROTOSYNTHESIS && !(gBattleMons[battler].volatiles.transformed) && ((gBattleWeather & B_WEATHER_SUN && HasWeatherEffect()) || gDisableStructs[battler].boosterEnergyActivated)) - speed = (GetHighestStatId(battler) == STAT_SPEED) ? (speed * 150) / 100 : speed; + speed = (GetParadoxBoostedStatId(battler) == STAT_SPEED) ? (speed * 150) / 100 : speed; else if (ability == ABILITY_QUARK_DRIVE && !(gBattleMons[battler].volatiles.transformed) && (gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN || gDisableStructs[battler].boosterEnergyActivated)) - speed = (GetHighestStatId(battler) == STAT_SPEED) ? (speed * 150) / 100 : speed; + speed = (GetParadoxBoostedStatId(battler) == STAT_SPEED) ? (speed * 150) / 100 : speed; else if (ability == ABILITY_UNBURDEN && gDisableStructs[battler].unburdenActive) speed *= 2; @@ -4795,7 +4814,7 @@ u32 GetBattlerTotalSpeedStatArgs(u32 battler, u32 ability, enum ItemHoldEffect h // paralysis drop if (gBattleMons[battler].status1 & STATUS1_PARALYSIS && ability != ABILITY_QUICK_FEET) - speed /= GetGenConfig(GEN_CONFIG_PARALYSIS_SPEED) >= GEN_7 ? 2 : 4; + speed /= GetConfig(CONFIG_PARALYSIS_SPEED) >= GEN_7 ? 2 : 4; if (gSideStatuses[GetBattlerSide(battler)] & SIDE_STATUS_SWAMP) speed /= 4; @@ -4803,14 +4822,7 @@ u32 GetBattlerTotalSpeedStatArgs(u32 battler, u32 ability, enum ItemHoldEffect h return speed; } -u32 GetBattlerTotalSpeedStat(u32 battler) -{ - u32 ability = GetBattlerAbility(battler); - enum ItemHoldEffect holdEffect = GetBattlerHoldEffect(battler, TRUE); - return GetBattlerTotalSpeedStatArgs(battler, ability, holdEffect); -} - -s32 GetChosenMovePriority(u32 battler, u32 ability) +s32 GetChosenMovePriority(u32 battler, enum Ability ability) { u16 move; @@ -4818,12 +4830,12 @@ s32 GetChosenMovePriority(u32 battler, u32 ability) if (gProtectStructs[battler].noValidMoves) move = MOVE_STRUGGLE; else - move = gBattleMons[battler].moves[gBattleStruct->chosenMovePositions[battler]]; + move = GetChosenMoveFromPosition(battler); return GetBattleMovePriority(battler, ability, move); } -s32 GetBattleMovePriority(u32 battler, u32 ability, u32 move) +s32 GetBattleMovePriority(u32 battler, enum Ability ability, u32 move) { s32 priority = 0; @@ -4841,7 +4853,7 @@ s32 GetBattleMovePriority(u32 battler, u32 ability, u32 move) priority = -8; } else if (ability == ABILITY_GALE_WINGS - && (GetGenConfig(GEN_CONFIG_GALE_WINGS) < GEN_7 || IsBattlerAtMaxHp(battler)) + && (GetConfig(CONFIG_GALE_WINGS) < GEN_7 || IsBattlerAtMaxHp(battler)) && GetMoveType(move) == TYPE_FLYING) { priority++; @@ -4851,7 +4863,7 @@ s32 GetBattleMovePriority(u32 battler, u32 ability, u32 move) gProtectStructs[battler].pranksterElevated = 1; priority++; } - else if (GetMoveEffect(move) == EFFECT_GRASSY_GLIDE && IsBattlerTerrainAffected(battler, STATUS_FIELD_GRASSY_TERRAIN) && GetActiveGimmick(gBattlerAttacker) != GIMMICK_DYNAMAX && !IsGimmickSelected(battler, GIMMICK_DYNAMAX)) + else if (GetMoveEffect(move) == EFFECT_GRASSY_GLIDE && IsBattlerTerrainAffected(battler, ability, GetBattlerHoldEffect(battler), STATUS_FIELD_GRASSY_TERRAIN) && GetActiveGimmick(gBattlerAttacker) != GIMMICK_DYNAMAX && !IsGimmickSelected(battler, GIMMICK_DYNAMAX)) { priority++; } @@ -4863,8 +4875,7 @@ s32 GetBattleMovePriority(u32 battler, u32 ability, u32 move) return priority; } -s32 GetWhichBattlerFasterArgs(u32 battler1, u32 battler2, bool32 ignoreChosenMoves, u32 ability1, u32 ability2, - enum ItemHoldEffect holdEffectBattler1, enum ItemHoldEffect holdEffectBattler2, u32 speedBattler1, u32 speedBattler2, s32 priority1, s32 priority2) +s32 GetWhichBattlerFasterArgs(struct BattleContext *ctx, bool32 ignoreChosenMoves, u32 speedBattler1, u32 speedBattler2, s32 priority1, s32 priority2) { u32 strikesFirst = 0; @@ -4873,18 +4884,18 @@ s32 GetWhichBattlerFasterArgs(u32 battler1, u32 battler2, bool32 ignoreChosenMov // Quick Claw / Quick Draw / Custap Berry - always first // Stall / Mycelium Might - last but before Lagging Tail // Lagging Tail - always last - bool32 battler1HasQuickEffect = gProtectStructs[battler1].quickDraw || gProtectStructs[battler1].usedCustapBerry; - bool32 battler2HasQuickEffect = gProtectStructs[battler2].quickDraw || gProtectStructs[battler2].usedCustapBerry; - bool32 battler1HasStallingAbility = ability1 == ABILITY_STALL || gProtectStructs[battler1].myceliumMight; - bool32 battler2HasStallingAbility = ability2 == ABILITY_STALL || gProtectStructs[battler2].myceliumMight; + bool32 battler1HasQuickEffect = gProtectStructs[ctx->battlerAtk].quickDraw || gProtectStructs[ctx->battlerAtk].usedCustapBerry; + bool32 battler2HasQuickEffect = gProtectStructs[ctx->battlerDef].quickDraw || gProtectStructs[ctx->battlerDef].usedCustapBerry; + bool32 battler1HasStallingAbility = ctx->abilities[ctx->battlerAtk] == ABILITY_STALL || gProtectStructs[ctx->battlerAtk].myceliumMight; + bool32 battler2HasStallingAbility = ctx->abilities[ctx->battlerDef] == ABILITY_STALL || gProtectStructs[ctx->battlerDef].myceliumMight; if (battler1HasQuickEffect && !battler2HasQuickEffect) strikesFirst = 1; else if (battler2HasQuickEffect && !battler1HasQuickEffect) strikesFirst = -1; - else if (gProtectStructs[battler1].laggingTail && !gProtectStructs[battler2].laggingTail) + else if (gProtectStructs[ctx->battlerAtk].laggingTail && !gProtectStructs[ctx->battlerDef].laggingTail) strikesFirst = -1; - else if (gProtectStructs[battler2].laggingTail && !gProtectStructs[battler1].laggingTail) + else if (gProtectStructs[ctx->battlerDef].laggingTail && !gProtectStructs[ctx->battlerAtk].laggingTail) strikesFirst = 1; else if (battler1HasStallingAbility && !battler2HasStallingAbility) strikesFirst = -1; @@ -4926,32 +4937,27 @@ s32 GetWhichBattlerFasterArgs(u32 battler1, u32 battler2, bool32 ignoreChosenMov return strikesFirst; } -s32 GetWhichBattlerFasterOrTies(u32 battler1, u32 battler2, bool32 ignoreChosenMoves) +s32 GetWhichBattlerFasterOrTies(struct BattleContext *ctx, bool32 ignoreChosenMoves) { s32 priority1 = 0, priority2 = 0; - u32 ability1 = GetBattlerAbility(battler1); - u32 speedBattler1 = GetBattlerTotalSpeedStat(battler1); - enum ItemHoldEffect holdEffectBattler1 = GetBattlerHoldEffect(battler1, TRUE); - u32 speedBattler2 = GetBattlerTotalSpeedStat(battler2); - enum ItemHoldEffect holdEffectBattler2 = GetBattlerHoldEffect(battler2, TRUE); - u32 ability2 = GetBattlerAbility(battler2); + u32 speedBattler1 = GetBattlerTotalSpeedStat(ctx->battlerAtk, ctx->abilities[ctx->battlerAtk], ctx->holdEffects[ctx->battlerAtk]); + u32 speedBattler2 = GetBattlerTotalSpeedStat(ctx->battlerDef, ctx->abilities[ctx->battlerDef], ctx->holdEffects[ctx->battlerDef]); if (!ignoreChosenMoves) { - if (gChosenActionByBattler[battler1] == B_ACTION_USE_MOVE) - priority1 = GetChosenMovePriority(battler1, ability1); - if (gChosenActionByBattler[battler2] == B_ACTION_USE_MOVE) - priority2 = GetChosenMovePriority(battler2, ability2); + if (gChosenActionByBattler[ctx->battlerAtk] == B_ACTION_USE_MOVE) + priority1 = GetChosenMovePriority(ctx->battlerAtk, ctx->abilities[ctx->battlerAtk]); + if (gChosenActionByBattler[ctx->battlerDef] == B_ACTION_USE_MOVE) + priority2 = GetChosenMovePriority(ctx->battlerDef, ctx->abilities[ctx->battlerDef]); } return GetWhichBattlerFasterArgs( - battler1, battler2, + ctx, ignoreChosenMoves, - ability1, ability2, - holdEffectBattler1, holdEffectBattler2, - speedBattler1, speedBattler2, - priority1, priority2 - ); + speedBattler1, + speedBattler2, + priority1, + priority2); } // 24 == MAX_BATTLERS_COUNT!. @@ -4985,13 +4991,13 @@ static const u8 sBattlerOrders[24][4] = { 3, 2, 1, 0 }, }; -s32 GetWhichBattlerFaster(u32 battler1, u32 battler2, bool32 ignoreChosenMoves) +s32 GetWhichBattlerFaster(struct BattleContext *ctx, bool32 ignoreChosenMoves) { - s32 strikesFirst = GetWhichBattlerFasterOrTies(battler1, battler2, ignoreChosenMoves); + s32 strikesFirst = GetWhichBattlerFasterOrTies(ctx, ignoreChosenMoves); if (strikesFirst == 0) { - s32 order1 = sBattlerOrders[gBattleStruct->speedTieBreaks][battler1]; - s32 order2 = sBattlerOrders[gBattleStruct->speedTieBreaks][battler2]; + s32 order1 = sBattlerOrders[gBattleStruct->speedTieBreaks][ctx->battlerAtk]; + s32 order2 = sBattlerOrders[gBattleStruct->speedTieBreaks][ctx->battlerDef]; if (order1 < order2) strikesFirst = 1; else @@ -5085,13 +5091,19 @@ static void SetActionsAndBattlersTurnOrder(void) turnOrderId++; } } + struct BattleContext ctx = {0}; + for (i = 0; i < gBattlersCount; i++) + { + ctx.abilities[i] = GetBattlerAbility(i); + ctx.holdEffects[i] = GetBattlerHoldEffect(i); + } for (i = 0; i < gBattlersCount - 1; i++) { for (j = i + 1; j < gBattlersCount; j++) { - u8 battler1 = gBattlerByTurnOrder[i]; - u8 battler2 = gBattlerByTurnOrder[j]; - TryChangingTurnOrderEffects(battler1, battler2, quickClawRandom, quickDrawRandom); + ctx.battlerAtk = gBattlerByTurnOrder[i]; + ctx.battlerDef = gBattlerByTurnOrder[j]; + TryChangingTurnOrderEffects(&ctx, quickClawRandom, quickDrawRandom); if (gActionsByTurnOrder[i] != B_ACTION_USE_ITEM && gActionsByTurnOrder[j] != B_ACTION_USE_ITEM && gActionsByTurnOrder[i] != B_ACTION_SWITCH @@ -5099,7 +5111,7 @@ static void SetActionsAndBattlersTurnOrder(void) && gActionsByTurnOrder[i] != B_ACTION_THROW_BALL && gActionsByTurnOrder[j] != B_ACTION_THROW_BALL) { - if (GetWhichBattlerFaster(battler1, battler2, FALSE) == -1) + if (GetWhichBattlerFaster(&ctx, FALSE) == -1) SwapTurnOrder(i, j); } } @@ -5135,6 +5147,7 @@ static void TurnValuesCleanUp(bool8 var0) gDisableStructs[i].rechargeTimer--; gBattleStruct->battlerState[i].canPickupItem = FALSE; + gBattleStruct->battlerState[i].wasAboveHalfHp = FALSE; } if (gDisableStructs[i].substituteHP == 0) @@ -5153,15 +5166,12 @@ static void TurnValuesCleanUp(bool8 var0) gSideTimers[B_SIDE_OPPONENT].followmeTimer = 0; gBattleStruct->pledgeMove = FALSE; // combined pledge move may not have been used due to a canceler + gBattleStruct->tryDestinyBond = FALSE; + gBattleStruct->tryGrudge = FALSE; ClearPursuitValues(); ClearDamageCalcResults(); } -void SpecialStatusesClear(void) -{ - memset(&gSpecialStatuses, 0, sizeof(gSpecialStatuses)); -} - static void PopulateArrayWithBattlers(u8 *battlers) { u32 i; @@ -5201,7 +5211,7 @@ static bool32 TryDoGimmicksBeforeMoves(void) } } - if (GetGenConfig(GEN_CONFIG_MEGA_EVO_TURN_ORDER) >= GEN_7) + if (GetConfig(CONFIG_MEGA_EVO_TURN_ORDER) >= GEN_7) TryChangeTurnOrder(); // This will just do nothing if no mon has mega evolved. return FALSE; } @@ -5249,29 +5259,38 @@ static bool32 TryDoMoveEffectsBeforeMoves(void) static void TryChangeTurnOrder(void) { u32 i, j; + + struct BattleContext ctx = {0}; + for (i = 0; i < gBattlersCount; i++) + { + ctx.abilities[i] = GetBattlerAbility(i); + ctx.holdEffects[i] = GetBattlerHoldEffect(i); + } for (i = gCurrentTurnActionNumber; i < gBattlersCount - 1; i++) { for (j = i + 1; j < gBattlersCount; j++) { - u32 battler1 = gBattlerByTurnOrder[i]; - u32 battler2 = gBattlerByTurnOrder[j]; + ctx.battlerAtk = gBattlerByTurnOrder[i]; + ctx.battlerDef = gBattlerByTurnOrder[j]; if (gActionsByTurnOrder[i] == B_ACTION_USE_MOVE && gActionsByTurnOrder[j] == B_ACTION_USE_MOVE) { - if (GetWhichBattlerFaster(battler1, battler2, FALSE) == -1) + if (GetWhichBattlerFaster(&ctx, FALSE) == -1) SwapTurnOrder(i, j); } } } } -static void TryChangingTurnOrderEffects(u32 battler1, u32 battler2, u32 *quickClawRandom, u32 *quickDrawRandom) +static void TryChangingTurnOrderEffects(struct BattleContext *ctx, u32 *quickClawRandom, u32 *quickDrawRandom) { - u32 ability1 = GetBattlerAbility(battler1); - enum ItemHoldEffect holdEffectBattler1 = GetBattlerHoldEffect(battler1, TRUE); - enum ItemHoldEffect holdEffectBattler2 = GetBattlerHoldEffect(battler2, TRUE); - u32 ability2 = GetBattlerAbility(battler2); + u32 battler1 = ctx->battlerAtk; + u32 battler2 = ctx->battlerDef; + enum Ability ability1 = ctx->abilities[ctx->battlerAtk]; + enum Ability ability2 = ctx->abilities[ctx->battlerDef]; + enum HoldEffect holdEffectBattler1 = ctx->holdEffects[ctx->battlerAtk]; + enum HoldEffect holdEffectBattler2 = ctx->holdEffects[ctx->battlerDef]; // Battler 1 // Quick Draw @@ -5280,7 +5299,7 @@ static void TryChangingTurnOrderEffects(u32 battler1, u32 battler2, u32 *quickCl // Quick Claw and Custap Berry if (!gProtectStructs[battler1].quickDraw && ((holdEffectBattler1 == HOLD_EFFECT_QUICK_CLAW && quickClawRandom[battler1]) - || (holdEffectBattler1 == HOLD_EFFECT_CUSTAP_BERRY && HasEnoughHpToEatBerry(battler1, 4, gBattleMons[battler1].item)))) + || (holdEffectBattler1 == HOLD_EFFECT_CUSTAP_BERRY && HasEnoughHpToEatBerry(battler1, ability1, 4, gBattleMons[battler1].item)))) gProtectStructs[battler1].usedCustapBerry = TRUE; // Battler 2 @@ -5290,7 +5309,7 @@ static void TryChangingTurnOrderEffects(u32 battler1, u32 battler2, u32 *quickCl // Quick Claw and Custap Berry if (!gProtectStructs[battler2].quickDraw && ((holdEffectBattler2 == HOLD_EFFECT_QUICK_CLAW && quickClawRandom[battler2]) - || (holdEffectBattler2 == HOLD_EFFECT_CUSTAP_BERRY && HasEnoughHpToEatBerry(battler2, 4, gBattleMons[battler2].item)))) + || (holdEffectBattler2 == HOLD_EFFECT_CUSTAP_BERRY && HasEnoughHpToEatBerry(battler2, ability2, 4, gBattleMons[battler2].item)))) gProtectStructs[battler2].usedCustapBerry = TRUE; } @@ -5315,14 +5334,14 @@ static void CheckChangingTurnOrderEffects(void) { gLastUsedItem = gBattleMons[battler].item; PREPARE_ITEM_BUFFER(gBattleTextBuff1, gLastUsedItem); - if (GetBattlerHoldEffect(battler, FALSE) == HOLD_EFFECT_CUSTAP_BERRY) + if (GetBattlerHoldEffect(battler) == HOLD_EFFECT_CUSTAP_BERRY) { // don't record berry since its gone now BattleScriptExecute(BattleScript_CustapBerryActivation); } else { - RecordItemEffectBattle(battler, GetBattlerHoldEffect(battler, FALSE)); + RecordItemEffectBattle(battler, GetBattlerHoldEffect(battler)); BattleScriptExecute(BattleScript_QuickClawActivation); } } @@ -5355,7 +5374,6 @@ static void CheckChangingTurnOrderEffects(void) gBattleMainFunc = RunTurnActionsFunctions; gBattleCommunication[3] = 0; gBattleCommunication[4] = 0; - gBattleScripting.multihitMoveEffect = 0; gBattleResources->battleScriptsStack->size = 0; } @@ -5387,16 +5405,12 @@ static void RunTurnActionsFunctions(void) if (gCurrentTurnActionNumber >= gBattlersCount) // everyone did their actions, turn finished { - gHitMarker &= ~HITMARKER_PASSIVE_HP_UPDATE; gBattleMainFunc = sEndTurnFuncsTable[gBattleOutcome & 0x7F]; } else { if (gBattleStruct->savedTurnActionNumber != gCurrentTurnActionNumber) // action turn has been done, clear hitmarker bits for another battler - { - gHitMarker &= ~HITMARKER_NO_ATTACKSTRING; gHitMarker &= ~HITMARKER_UNABLE_TO_USE_MOVE; - } } } @@ -5582,7 +5596,7 @@ static void HandleEndTurn_FinishBattle(void) | BATTLE_TYPE_TRAINER_HILL | BATTLE_TYPE_FRONTIER))) { - for (u32 side = 0; side < NUM_BATTLE_SIDES; side++) + for (enum BattleSide side = 0; side < NUM_BATTLE_SIDES; side++) { struct Pokemon *party = GetSideParty(side); @@ -5627,8 +5641,7 @@ static void HandleEndTurn_FinishBattle(void) for (i = 0; i < PARTY_SIZE; i++) { - bool8 changedForm = TryRevertPartyMonFormChange(i); - gBattleStruct->partyState[B_SIDE_OPPONENT][i].changedSpecies = SPECIES_NONE; + bool32 changedForm = TryRevertPartyMonFormChange(i); // Recalculate the stats of every party member before the end if (!changedForm && B_RECALCULATE_STATS >= GEN_5) @@ -5800,9 +5813,9 @@ void RunBattleScriptCommands(void) gBattleScriptingCommandsTable[gBattlescriptCurrInstr[0]](); } -u32 TrySetAteType(u32 move, u32 battlerAtk, u32 attackerAbility) +enum Type TrySetAteType(u32 move, u32 battlerAtk, enum Ability attackerAbility) { - u32 ateType = TYPE_NONE; + enum Type ateType = TYPE_NONE; switch (GetMoveEffect(move)) { @@ -5848,12 +5861,14 @@ u32 TrySetAteType(u32 move, u32 battlerAtk, u32 attackerAbility) } // Returns TYPE_NONE if type doesn't change. -u32 GetDynamicMoveType(struct Pokemon *mon, u32 move, u32 battler, enum MonState state) +enum Type GetDynamicMoveType(struct Pokemon *mon, u32 move, u32 battler, enum MonState state) { - u32 moveType = GetMoveType(move); + enum Type moveType = GetMoveType(move); enum BattleMoveEffects moveEffect = GetMoveEffect(move); - u32 species, heldItem, ability, type1, type2, type3; - enum ItemHoldEffect holdEffect; + u32 species, heldItem; + enum Type type1, type2, type3; + enum Ability ability; + enum HoldEffect holdEffect; enum Gimmick gimmick = GetActiveGimmick(battler); if (state == MON_IN_BATTLE) @@ -5863,7 +5878,7 @@ u32 GetDynamicMoveType(struct Pokemon *mon, u32 move, u32 battler, enum MonState species = gBattleMons[battler].species; heldItem = gBattleMons[battler].item; - holdEffect = GetBattlerHoldEffect(battler, TRUE); + holdEffect = GetBattlerHoldEffect(battler); ability = GetBattlerAbility(battler); type1 = gBattleMons[battler].types[0]; type2 = gBattleMons[battler].types[1]; @@ -5961,7 +5976,7 @@ u32 GetDynamicMoveType(struct Pokemon *mon, u32 move, u32 battler, enum MonState case EFFECT_REVELATION_DANCE: if (gimmick != GIMMICK_Z_MOVE) { - u32 teraType; + enum Type teraType; if (gimmick == GIMMICK_TERA && ((teraType = GetMonData(mon, MON_DATA_TERA_TYPE)) != TYPE_STELLAR)) return teraType; else if (type1 != TYPE_MYSTERY && !(gDisableStructs[battler].roostActive && type1 == TYPE_FLYING)) @@ -6005,7 +6020,7 @@ u32 GetDynamicMoveType(struct Pokemon *mon, u32 move, u32 battler, enum MonState case EFFECT_TERRAIN_PULSE: if (state == MON_IN_BATTLE) { - if (IsBattlerTerrainAffected(battler, STATUS_FIELD_TERRAIN_ANY)) + if (IsBattlerTerrainAffected(battler, GetBattlerAbility(battler), GetBattlerHoldEffect(battler), STATUS_FIELD_TERRAIN_ANY)) { if (gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN) return TYPE_ELECTRIC; @@ -6086,9 +6101,9 @@ u32 GetDynamicMoveType(struct Pokemon *mon, u32 move, u32 battler, enum MonState void SetTypeBeforeUsingMove(u32 move, u32 battler) { - u32 moveType; + enum Type moveType; u32 heldItem = gBattleMons[battler].item; - enum ItemHoldEffect holdEffect = GetBattlerHoldEffect(battler, TRUE); + enum HoldEffect holdEffect = GetBattlerHoldEffect(battler); gBattleStruct->dynamicMoveType = 0; gBattleStruct->battlerState[battler].ateBoost = FALSE; diff --git a/src/battle_message.c b/src/battle_message.c index b58fba0c14..5260de5cf4 100644 --- a/src/battle_message.c +++ b/src/battle_message.c @@ -67,7 +67,7 @@ const u8 gText_PkmnsXPreventsSwitching[] = _("因{B_BUFF1}的{B_LAST_ABILITY}\n const u8 gText_StatSharply[] = _("大幅"); const u8 gText_StatRose[] = _("提高了!"); const u8 gText_StatFell[] = _("降低了!"); -const u8 gText_DefendersStatRose[] = _("{B_DEF_NAME_WITH_PREFIX}的\n{B_BUFF1}{B_BUFF2}"); +const u8 gText_DefendersStatRose[] = _("{B_DEF_NAME_WITH_PREFIX}的\n{B_BUFF1}{B_BUFF2}提高了!"); static const u8 sText_GotAwaySafely[] = _("{PLAY_SE SE_FLEE}顺利逃走了!\p"); static const u8 sText_PlayerDefeatedLinkTrainer[] = _("战胜了\n{B_LINK_OPPONENT1_NAME}!"); static const u8 sText_TwoLinkTrainersDefeated[] = _("战胜了\n{B_LINK_OPPONENT1_NAME}和{B_LINK_OPPONENT2_NAME}!"); @@ -108,6 +108,7 @@ static const u8 sText_PkmnComeBack[] = _("{B_BUFF1},\n回来!"); static const u8 sText_PkmnOkComeBack[] = _("{B_BUFF1},很好!\n回来!"); static const u8 sText_PkmnGoodComeBack[] = _("{B_BUFF1},干得漂亮!\n回来!"); static const u8 sText_Trainer1WithdrewPkmn[] = _("{B_TRAINER1_NAME_WITH_CLASS}换下了\n{B_BUFF1}!"); +static const u8 sText_Trainer2WithdrewPkmn[] = _("{B_TRAINER2_NAME_WITH_CLASS}换下了\n{B_BUFF1}!"); static const u8 sText_LinkTrainer1WithdrewPkmn[] = _("{B_LINK_OPPONENT1_NAME}换下了\n{B_BUFF1}!"); static const u8 sText_LinkTrainer2WithdrewPkmn[] = _("{B_LINK_SCR_TRAINER_NAME}换下了\n{B_BUFF1}!"); static const u8 sText_WildPkmnPrefix[] = _("野生的"); @@ -187,8 +188,7 @@ const u8 *const gBattleStringsTable[STRINGID_COUNT] = [STRINGID_STATSWONTINCREASE2] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX}的\n能力已经无法再提高了!"), [STRINGID_AVOIDEDDAMAGE] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX}因{B_DEF_ABILITY},\n没有收到伤害!"), //not in gen 5+, ability popup [STRINGID_ITDOESNTAFFECT] = COMPOUND_STRING("对于{B_DEF_NAME_WITH_PREFIX2},\n好像没有效果……"), - [STRINGID_ATTACKERFAINTED] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX}倒下了!\p"), - [STRINGID_TARGETFAINTED] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX}倒下了!\p"), + [STRINGID_BATTLERFAINTED] = COMPOUND_STRING("{B_SCR_NAME_WITH_PREFIX}倒下了!\p"), [STRINGID_PLAYERGOTMONEY] = COMPOUND_STRING("作为奖金,\n{B_PLAYER_NAME}获得了¥{B_BUFF1}!\p"), [STRINGID_PLAYERWHITEOUT] = COMPOUND_STRING("{B_PLAYER_NAME}的手上没有\n可以战斗的宝可梦!\p"), [STRINGID_PLAYERWHITEOUT2_WILD] = COMPOUND_STRING("{B_PLAYER_NAME}在慌乱中\n丢失了¥{B_BUFF1}……"), @@ -220,11 +220,8 @@ const u8 *const gBattleStringsTable[STRINGID_COUNT] = [STRINGID_PKMNISPARALYZED] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX}\n因身体麻痹而无法行动!"), [STRINGID_PKMNISALREADYPARALYZED] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX}\n已经麻痹了。"), [STRINGID_PKMNHEALEDPARALYSIS] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX}的\n麻痹被解除了!"), - [STRINGID_PKMNDREAMEATEN] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX}的\n梦被吃掉了!"), //not in gen 5+, expansion doesn't use anymore [STRINGID_STATSWONTINCREASE] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX}的\n{B_BUFF1}已经无法再提高了!"), [STRINGID_STATSWONTDECREASE] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX}的\n{B_BUFF1}已经无法再降低了!"), - [STRINGID_TEAMSTOPPEDWORKING] = COMPOUND_STRING("我方的{B_BUFF1}\n失去了作用!"), //unused - [STRINGID_FOESTOPPEDWORKING] = COMPOUND_STRING("对手的{B_BUFF1}\n失去了作用!"), //unused [STRINGID_PKMNISCONFUSED] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX}\n正在混乱中!"), [STRINGID_PKMNHEALEDCONFUSION] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX}的\n混乱解除了!"), [STRINGID_PKMNWASCONFUSED] = COMPOUND_STRING("{B_EFF_NAME_WITH_PREFIX}混乱了!"), @@ -232,7 +229,6 @@ const u8 *const gBattleStringsTable[STRINGID_COUNT] = [STRINGID_PKMNFELLINLOVE] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX}\n着迷了!"), [STRINGID_PKMNINLOVE] = COMPOUND_STRING("{B_SCR_NAME_WITH_PREFIX2}让\n{B_ATK_NAME_WITH_PREFIX}着迷了!"), [STRINGID_PKMNIMMOBILIZEDBYLOVE] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX}\n因着迷了而无法使出招式!"), - [STRINGID_PKMNBLOWNAWAY] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX}被吹走了!"), //unused [STRINGID_PKMNCHANGEDTYPE] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX}\n变成了{B_BUFF1}属性!"), [STRINGID_PKMNFLINCHED] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX}畏缩了,\n无法使出招式!"), [STRINGID_PKMNREGAINEDHEALTH] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX}的\n体力回复了!"), @@ -276,7 +272,6 @@ const u8 *const gBattleStringsTable[STRINGID_COUNT] = [STRINGID_PKMNCALMEDDOWN] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX}\n平静了下来!"), [STRINGID_PKMNCANTSLEEPINUPROAR] = COMPOUND_STRING("但是,{B_DEF_NAME_WITH_PREFIX2}\n吵闹个不停,无法入睡!"), [STRINGID_PKMNSTOCKPILED] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX}\n蓄力了{B_BUFF1}次!"), - [STRINGID_PKMNCANTSTOCKPILE] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX}\n无法再蓄力了!"), //I think this was replaced with just "But it failed!" [STRINGID_PKMNCANTSLEEPINUPROAR2] = COMPOUND_STRING("但是,{B_DEF_NAME_WITH_PREFIX2}\n吵闹个不停,无法入睡!"), [STRINGID_UPROARKEPTPKMNAWAKE] = COMPOUND_STRING("但是,{B_DEF_NAME_WITH_PREFIX2}\n被吵得无法入睡!"), [STRINGID_PKMNSTAYEDAWAKEUSING] = COMPOUND_STRING("因为{B_DEF_ABILITY},\n{B_DEF_NAME_WITH_PREFIX}不会睡着!"), //not in gen 5+, ability popup @@ -294,10 +289,10 @@ const u8 *const gBattleStringsTable[STRINGID_COUNT] = [STRINGID_PKMNRAGEBUILDING] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX}的\n怒气正在上升!"), [STRINGID_PKMNMOVEWASDISABLED] = COMPOUND_STRING("封住了{B_DEF_NAME_WITH_PREFIX}的\n{B_BUFF1}!"), [STRINGID_PKMNMOVEISDISABLED] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX}因定身法\n而无法使出{B_CURRENT_MOVE}!\p"), - [STRINGID_PKMNMOVEDISABLEDNOMORE] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX}的\n定身法解除了!"), + [STRINGID_PKMNMOVEDISABLEDNOMORE] = COMPOUND_STRING("{B_SCR_NAME_WITH_PREFIX}的\n定身法解除了!"), [STRINGID_PKMNGOTENCORE] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX}\n接受了再来一次!"), [STRINGID_PKMNGOTENCOREDMOVE] = COMPOUND_STRING("{B_SCR_NAME_WITH_PREFIX}\n只能使用{B_CURRENT_MOVE}!\p"), - [STRINGID_PKMNENCOREENDED] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX}的\n再来一次状态解除了!"), + [STRINGID_PKMNENCOREENDED] = COMPOUND_STRING("{B_SCR_NAME_WITH_PREFIX}的\n再来一次状态解除了!"), [STRINGID_PKMNTOOKAIM] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX}将目标对准了\n{B_DEF_NAME_WITH_PREFIX2}!"), [STRINGID_PKMNSKETCHEDMOVE] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX}\n对{B_BUFF1}进行了写生!"), [STRINGID_PKMNTRYINGTOTAKEFOE] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX}\n想和对手同归于尽!"), @@ -324,7 +319,7 @@ const u8 *const gBattleStringsTable[STRINGID_COUNT] = [STRINGID_PKMNFLEDFROMBATTLE] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX}\n脱离了战斗!"), [STRINGID_PKMNFORESAWATTACK] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX}\n预知了未来的攻击!"), [STRINGID_PKMNTOOKATTACK] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX}\n受到了{B_BUFF1}的攻击!"), - [STRINGID_PKMNATTACK] = COMPOUND_STRING("{B_BUFF1}的攻击!"), //not in gen 5+, expansion doesn't use anymore + [STRINGID_PKMNATTACK] = COMPOUND_STRING("{B_BUFF1}的攻击!"), //not in gen 5+ [STRINGID_PKMNCENTERATTENTION] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX}\n变得万众瞩目了!"), [STRINGID_PKMNCHARGINGPOWER] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX}\n开始充电了!"), [STRINGID_NATUREPOWERTURNEDINTO] = COMPOUND_STRING("自然之力变成了{B_CURRENT_MOVE}!"), @@ -338,7 +333,6 @@ const u8 *const gBattleStringsTable[STRINGID_COUNT] = [STRINGID_PKMNREADYTOHELP] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX}摆出了\n帮助{B_DEF_NAME_WITH_PREFIX2}的架势!"), [STRINGID_PKMNSWITCHEDITEMS] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX}\n互换了各自的道具"), [STRINGID_PKMNCOPIEDFOE] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX}复制了\n{B_DEF_NAME_WITH_PREFIX2}的特性!"), - [STRINGID_PKMNMADEWISH] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX}许了一个愿!"), //unused [STRINGID_PKMNWISHCAMETRUE] = COMPOUND_STRING("{B_BUFF1}的\n祈愿实现了!"), [STRINGID_PKMNPLANTEDROOTS] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX}\n扎下了根!"), [STRINGID_PKMNABSORBEDNUTRIENTS] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX}\n从根上吸取了养分!"), @@ -355,15 +349,12 @@ const u8 *const gBattleStringsTable[STRINGID_COUNT] = [STRINGID_PKMNWAITSFORTARGET] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX}\n正在观察对手的动向!"), [STRINGID_PKMNSNATCHEDMOVE] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX}抢夺了\n{B_SCR_NAME_WITH_PREFIX2}的招式!"), [STRINGID_PKMNMADEITRAIN] = COMPOUND_STRING("因{B_SCR_NAME_WITH_PREFIX}的{B_SCR_ABILITY},\n开始下雨了!"), //not in gen 5+, ability popup - [STRINGID_PKMNRAISEDSPEED] = COMPOUND_STRING("因为{B_SCR_ABILITY},{B_SCR_NAME_WITH_PREFIX}的\n速度提高了!"), //not in gen 5+, ability popup [STRINGID_PKMNPROTECTEDBY] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX}\n受到了{B_DEF_ABILITY}的保护!"), //not in gen 5+, ability popup [STRINGID_PKMNPREVENTSUSAGE] = COMPOUND_STRING("因{B_DEF_NAME_WITH_PREFIX}的{B_DEF_ABILITY},\n{B_ATK_NAME_WITH_PREFIX2}不能使用\l{B_CURRENT_MOVE}!"), //I don't see this in SV text [STRINGID_PKMNRESTOREDHPUSING] = COMPOUND_STRING("因{B_DEF_ABILITY},{B_DEF_NAME_WITH_PREFIX}的\n体力回复了!"), //not in gen 5+, ability popup - [STRINGID_PKMNCHANGEDTYPEWITH] = COMPOUND_STRING("因为{B_DEF_ABILITY},{B_DEF_NAME_WITH_PREFIX}\n变成了{B_BUFF1}属性!"), //not in gen 5+, ability popup - [STRINGID_PKMNPREVENTSPARALYSISWITH] = COMPOUND_STRING("因为{B_LAST_ABILITY},{B_DEF_NAME_WITH_PREFIX}\n不会麻痹!"), //not in gen 5+, ability popup + [STRINGID_PKMNCHANGEDTYPEWITH] = COMPOUND_STRING("因为{B_DEF_ABILITY},{B_EFF_NAME_WITH_PREFIX}\n变成了{B_BUFF1}属性!"), //not in gen 5+, ability popup [STRINGID_PKMNPREVENTSROMANCEWITH] = COMPOUND_STRING("因为{B_DEF_ABILITY},{B_DEF_NAME_WITH_PREFIX}\n不会着迷!"), //not in gen 5+, ability popup - [STRINGID_PKMNPREVENTSPOISONINGWITH] = COMPOUND_STRING("因为{B_LAST_ABILITY},{B_DEF_NAME_WITH_PREFIX}\n不会中毒!"), //not in gen 5+, ability popup - [STRINGID_PKMNPREVENTSCONFUSIONWITH] = COMPOUND_STRING("因为{B_DEF_ABILITY},{B_DEF_NAME_WITH_PREFIX}\n不会混乱!"), //not in gen 5+, ability popup + [STRINGID_PKMNPREVENTSCONFUSIONWITH] = COMPOUND_STRING("因为{B_DEF_ABILITY},{B_SCR_NAME_WITH_PREFIX}\n不会混乱!"), //not in gen 5+, ability popup [STRINGID_PKMNRAISEDFIREPOWERWITH] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX}因{B_DEF_ABILITY}\n提高了火属性招式的威力!"), //not in gen 5+, ability popup [STRINGID_PKMNANCHORSITSELFWITH] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX}\n用吸盘吸住了!"), //not in gen 5+, ability popup [STRINGID_PKMNCUTSATTACKWITH] = COMPOUND_STRING("因{B_SCR_NAME_WITH_PREFIX}的{B_SCR_ABILITY},\n{B_DEF_NAME_WITH_PREFIX2}的攻击降低了!"), //not in gen 5+, ability popup @@ -374,10 +365,10 @@ const u8 *const gBattleStringsTable[STRINGID_COUNT] = [STRINGID_STATROSE] = gText_StatRose, [STRINGID_STATHARSHLY] = COMPOUND_STRING("大幅"), [STRINGID_STATFELL] = gText_StatFell, - [STRINGID_ATTACKERSSTATROSE] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX}的\n{B_BUFF1}{B_BUFF2}"), + [STRINGID_ATTACKERSSTATROSE] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX}的\n{B_BUFF1}{B_BUFF2}提高了!"), [STRINGID_DEFENDERSSTATROSE] = gText_DefendersStatRose, - [STRINGID_ATTACKERSSTATFELL] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX}的\n{B_BUFF1}{B_BUFF2}"), - [STRINGID_DEFENDERSSTATFELL] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX}的\n{B_BUFF1}{B_BUFF2}"), + [STRINGID_ATTACKERSSTATFELL] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX}的\n{B_BUFF1}{B_BUFF2}降低了!"), + [STRINGID_DEFENDERSSTATFELL] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX}的\n{B_BUFF1}{B_BUFF2}降低了!"), [STRINGID_CRITICALHIT] = COMPOUND_STRING("击中了要害!"), [STRINGID_ONEHITKO] = COMPOUND_STRING("一击必杀!"), [STRINGID_123POOF] = COMPOUND_STRING("{PAUSE 32}1,{PAUSE 15}2,{PAUSE 15}……{PAUSE 15}……{PAUSE 15}……{PAUSE 15}{PLAY_SE SE_BALL_BOUNCE_1}空!\p"), @@ -392,7 +383,6 @@ const u8 *const gBattleStringsTable[STRINGID_COUNT] = [STRINGID_BUTNOTHINGHAPPENED] = COMPOUND_STRING("但是,什么也没有发生!"), [STRINGID_BUTITFAILED] = COMPOUND_STRING("但是,没有起到效果!!"), [STRINGID_ITHURTCONFUSION] = COMPOUND_STRING("不知所以地攻击了自己!"), - [STRINGID_MIRRORMOVEFAILED] = COMPOUND_STRING("鹦鹉学舌没有起到效果!"), //not in gen 5+, uses "but it failed" [STRINGID_STARTEDTORAIN] = COMPOUND_STRING("开始下雨了!"), [STRINGID_DOWNPOURSTARTED] = COMPOUND_STRING("开始下大雨了!"), // corresponds to DownpourText in pokegold and pokecrystal and is used by Rain Dance in GSC [STRINGID_RAINCONTINUES] = COMPOUND_STRING("雨一直在下。"), //not in gen 5+ @@ -407,9 +397,6 @@ const u8 *const gBattleStringsTable[STRINGID_COUNT] = [STRINGID_STARTEDHAIL] = COMPOUND_STRING("开始下冰雹了!"), [STRINGID_HAILCONTINUES] = COMPOUND_STRING("冰雹还在持续。"), [STRINGID_HAILSTOPPED] = COMPOUND_STRING("冰雹不下了!"), - [STRINGID_FAILEDTOSPITUP] = COMPOUND_STRING("但是,没有喷出任何东西!"), //not in gen 5+, uses "but it failed" - [STRINGID_FAILEDTOSWALLOW] = COMPOUND_STRING("但是,没有吞下任何东西!"), //not in gen 5+, uses "but it failed" - [STRINGID_WINDBECAMEHEATWAVE] = COMPOUND_STRING("风变成了热风!"), //unused [STRINGID_STATCHANGESGONE] = COMPOUND_STRING("所有能力都复原了!"), [STRINGID_COINSSCATTERED] = COMPOUND_STRING("金币散落一地!"), [STRINGID_TOOWEAKFORSUBSTITUTE] = COMPOUND_STRING("但是,体力已经不够\n放出替身了!"), @@ -466,7 +453,6 @@ const u8 *const gBattleStringsTable[STRINGID_COUNT] = [STRINGID_ITEMALLOWSONLYYMOVE] = COMPOUND_STRING("因为{B_LAST_ITEM}的效果,\n只能使出{B_CURRENT_MOVE}!\p"), [STRINGID_PKMNHUNGONWITHX] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX}\n用{B_LAST_ITEM}撑住了!"), [STRINGID_EMPTYSTRING3] = gText_EmptyString3, - [STRINGID_PKMNSXPREVENTSBURNS] = COMPOUND_STRING("因为{B_LAST_ABILITY},{B_DEF_NAME_WITH_PREFIX}\n不会灼伤!"), //not in gen 5+, ability popup [STRINGID_PKMNSXBLOCKSY] = COMPOUND_STRING("因为{B_DEF_ABILITY},{B_DEF_NAME_WITH_PREFIX}\n抵御了{B_CURRENT_MOVE}!"), //not in gen 5+, ability popup [STRINGID_PKMNSXRESTOREDHPALITTLE2] = COMPOUND_STRING("因为{B_ATK_ABILITY},{B_ATK_NAME_WITH_PREFIX}\n回复了少许HP。"), //not in gen 5+, ability popup [STRINGID_PKMNSXWHIPPEDUPSANDSTORM] = COMPOUND_STRING("因{B_SCR_NAME_WITH_PREFIX}的{B_SCR_ABILITY},\n开始刮沙暴了!"), //not in gen 5+, ability popup @@ -485,8 +471,8 @@ const u8 *const gBattleStringsTable[STRINGID_COUNT] = [STRINGID_PLAYERDEFEATEDTRAINER1] = sText_PlayerDefeatedLinkTrainerTrainer1, [STRINGID_SOOTHINGAROMA] = COMPOUND_STRING("怡人的香气扩散了开来!"), [STRINGID_ITEMSCANTBEUSEDNOW] = COMPOUND_STRING("现在不能使用道具。{PAUSE 64}"), //not in gen 5+, i think - [STRINGID_FORXCOMMAYZ] = COMPOUND_STRING("对于{B_SCR_NAME_WITH_PREFIX2}而言,\n{B_LAST_ITEM}{B_BUFF1}"), //not in gen 5+, expansion doesn't use anymore - [STRINGID_USINGITEMSTATOFPKMNROSE] = COMPOUND_STRING("因为{B_LAST_ITEM},{B_SCR_NAME_WITH_PREFIX}的\n{B_BUFF1}{B_BUFF2}"), //todo: update this, will require code changes + [STRINGID_USINGITEMSTATOFPKMNROSE] = COMPOUND_STRING("因为{B_LAST_ITEM},{B_SCR_NAME_WITH_PREFIX}的\n{B_BUFF1}{B_BUFF2}提高了!"), //todo: update this, will require code changes + [STRINGID_USINGITEMSTATOFPKMNFELL] = COMPOUND_STRING("因为{B_LAST_ITEM},{B_SCR_NAME_WITH_PREFIX}的\n{B_BUFF1}{B_BUFF2}降低了!"), [STRINGID_PKMNUSEDXTOGETPUMPED] = COMPOUND_STRING("{B_SCR_NAME_WITH_PREFIX}\n使用了{B_LAST_ITEM},拿出了干劲!"), [STRINGID_PKMNSXMADEYUSELESS] = COMPOUND_STRING("因{B_DEF_NAME_WITH_PREFIX}的{B_DEF_ABILITY},\n{B_CURRENT_MOVE}无效了!"), //not in gen 5+, ability popup [STRINGID_PKMNTRAPPEDBYSANDTOMB] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX}\n陷入了流沙地狱!"), @@ -502,7 +488,6 @@ const u8 *const gBattleStringsTable[STRINGID_COUNT] = [STRINGID_PKMNFLEDUSINGITS] = COMPOUND_STRING("{PLAY_SE SE_FLEE}{B_ATK_NAME_WITH_PREFIX}\n使用其所携带的{B_LAST_ITEM}逃走了!\p"), [STRINGID_PKMNFLEDUSING] = COMPOUND_STRING("{PLAY_SE SE_FLEE}{B_ATK_NAME_WITH_PREFIX}\n使用{B_ATK_ABILITY}逃走了!\p"), //not in gen 5+ [STRINGID_PKMNWASDRAGGEDOUT] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX}\n被拖进了战斗!\p"), - [STRINGID_PREVENTEDFROMWORKING] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX}的{B_DEF_ABILITY}\n让{B_SCR_NAME_WITH_PREFIX2}的\l{B_BUFF1}不起作用!"), //unused [STRINGID_PKMNSITEMNORMALIZEDSTATUS] = COMPOUND_STRING("{B_SCR_NAME_WITH_PREFIX}用{B_LAST_ITEM}\n治愈了异常状态!"), [STRINGID_TRAINER1USEDITEM] = COMPOUND_STRING("{B_ATK_TRAINER_NAME_WITH_CLASS}\n使用了{B_LAST_ITEM}!"), [STRINGID_BOXISFULL] = COMPOUND_STRING("盒子已满,\n无法再进行捕捉!\p"), @@ -513,17 +498,13 @@ const u8 *const gBattleStringsTable[STRINGID_COUNT] = [STRINGID_STATSWONTDECREASE2] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX}的\n能力已经无法再降低了!"), [STRINGID_PKMNSXBLOCKSY2] = COMPOUND_STRING("因为{B_SCR_ABILITY},{B_SCR_NAME_WITH_PREFIX}\n抵御了{B_CURRENT_MOVE}!"), //not in gen 5+, ability popup [STRINGID_PKMNSXWOREOFF] = COMPOUND_STRING("{B_ATK_TEAM1}的{B_BUFF1}消失了!"), - [STRINGID_PKMNRAISEDDEFALITTLE] = COMPOUND_STRING("{B_CURRENT_MOVE}使{B_ATK_PREFIX1}的\n物理抗性略微提高了!"), //expansion doesn't use anymore - [STRINGID_PKMNRAISEDSPDEFALITTLE] = COMPOUND_STRING("{B_CURRENT_MOVE}使{B_ATK_PREFIX1}的\n特殊抗性略微提高了!"), //expansion doesn't use anymore [STRINGID_THEWALLSHATTERED] = COMPOUND_STRING("墙壁碎掉了!"), //not in gen5+, uses "your teams light screen wore off!" etc instead - [STRINGID_PKMNSXPREVENTSYSZ] = COMPOUND_STRING("因{B_ATK_NAME_WITH_PREFIX}的{B_ATK_ABILITY},\n{B_DEF_NAME_WITH_PREFIX2}的\l{B_DEF_ABILITY}不起作用!"), [STRINGID_PKMNSXCUREDITSYPROBLEM] = COMPOUND_STRING("因为{B_SCR_ABILITY},{B_SCR_NAME_WITH_PREFIX}的\n{B_BUFF1}状态治愈了!"), //not in gen 5+, ability popup [STRINGID_ATTACKERCANTESCAPE] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX}\n无法逃走!"), [STRINGID_PKMNOBTAINEDX] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX}\n获得了{B_BUFF1}!"), [STRINGID_PKMNOBTAINEDX2] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX}\n获得了{B_BUFF2}!"), [STRINGID_PKMNOBTAINEDXYOBTAINEDZ] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX}\n获得了{B_BUFF1}!\p{B_DEF_NAME_WITH_PREFIX}\n获得了{B_BUFF2}!"), [STRINGID_BUTNOEFFECT] = COMPOUND_STRING("但是,没有效果!"), - [STRINGID_PKMNSXHADNOEFFECTONY] = COMPOUND_STRING("目标正受到{B_LAST_ABILITY}的保护!"), //not in gen 5+, ability popup 个人汉化 [STRINGID_TWOENEMIESDEFEATED] = sText_TwoInGameTrainersDefeated, [STRINGID_TRAINER2LOSETEXT] = COMPOUND_STRING("{B_TRAINER2_LOSE_TEXT}"), [STRINGID_PKMNINCAPABLEOFPOWER] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX}\n似乎无法发挥自身的力量!"), @@ -582,10 +563,8 @@ const u8 *const gBattleStringsTable[STRINGID_COUNT] = [STRINGID_FELLSTRAIGHTDOWN] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX}\n被击落,掉到了地面!"), [STRINGID_TARGETCHANGEDTYPE] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX}\n变成了{B_BUFF1}属性!"), [STRINGID_PKMNACQUIREDSIMPLE] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX}的特性\n变为单纯了!"), //shouldn't directly use the name - [STRINGID_EMPTYSTRING5] = sText_EmptyString4, [STRINGID_KINDOFFER] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX}\n接受了对手的好意!"), [STRINGID_RESETSTARGETSSTATLEVELS] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX}的\n能力变化消失了!"), - [STRINGID_EMPTYSTRING6] = sText_EmptyString4, [STRINGID_ALLYSWITCHPOSITION] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX}和\n{B_SCR_NAME_WITH_PREFIX2}互换了场地!"), [STRINGID_RESTORETARGETSHEALTH] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX}的\n体力回复了!"), [STRINGID_TOOKPJMNINTOTHESKY] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX}\n将{B_DEF_NAME_WITH_PREFIX}带上了高空!"), @@ -595,7 +574,7 @@ const u8 *const gBattleStringsTable[STRINGID_COUNT] = [STRINGID_TRANSFERHELDITEM] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX}从{B_ATK_NAME_WITH_PREFIX2}\n那里获得了{B_LAST_ITEM}!"), [STRINGID_EMBARGOENDS] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX}\n变得可以使用道具了!"), [STRINGID_ELECTROMAGNETISM] = COMPOUND_STRING("电磁力"), - [STRINGID_BUFFERENDS] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX}的\n{B_BUFF1}消失了!"), + [STRINGID_BUFFERENDS] = COMPOUND_STRING("{B_SCR_NAME_WITH_PREFIX}的\n{B_BUFF1}消失了!"), [STRINGID_TELEKINESISENDS] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX}\n摆脱了意念移物!"), [STRINGID_TAILWINDENDS] = COMPOUND_STRING("{B_ATK_TEAM1}的顺风停止了!"), [STRINGID_LUCKYCHANTENDS] = COMPOUND_STRING("{B_ATK_TEAM1}的幸运咒语解除了!"), @@ -610,9 +589,9 @@ const u8 *const gBattleStringsTable[STRINGID_COUNT] = [STRINGID_MISTYTERRAINENDS] = COMPOUND_STRING("脚下的雾气消失不见了!"), [STRINGID_PSYCHICTERRAINENDS] = COMPOUND_STRING("脚下的奇妙感觉消失了!"), [STRINGID_GRASSYTERRAINENDS] = COMPOUND_STRING("脚下的青草消失不见了!"), - [STRINGID_TARGETABILITYSTATRAISE] = COMPOUND_STRING("因为{B_DEF_ABILITY},\n{B_DEF_NAME_WITH_PREFIX}的{B_BUFF1}提高了!"), + [STRINGID_TARGETABILITYSTATRAISE] = COMPOUND_STRING("因为{B_DEF_ABILITY},\n{B_DEF_NAME_WITH_PREFIX}的{B_BUFF1}{B_BUFF2}提高了!"), [STRINGID_TARGETSSTATWASMAXEDOUT] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX}的{B_DEF_ABILITY}\n攻击被提高到了最大!"), - [STRINGID_ATTACKERABILITYSTATRAISE] = COMPOUND_STRING("因为{B_SCR_ABILITY},\n{B_SCR_NAME_WITH_PREFIX}的{B_BUFF1}提高了!"), + [STRINGID_ATTACKERABILITYSTATRAISE] = COMPOUND_STRING("因为{B_SCR_ABILITY},\n{B_SCR_NAME_WITH_PREFIX}的{B_BUFF1}{B_BUFF2}提高了!"), [STRINGID_POISONHEALHPUP] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX2}\n利用毒素回复了体力!"), //don't think this message is displayed anymore [STRINGID_BADDREAMSDMG] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX}\n正被恶梦缠身!"), [STRINGID_MOLDBREAKERENTERS] = COMPOUND_STRING("{B_SCR_NAME_WITH_PREFIX}\n打破了常规!"), @@ -642,7 +621,7 @@ const u8 *const gBattleStringsTable[STRINGID_COUNT] = [STRINGID_LUNARDANCECAMETRUE] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX}\n被神秘的月光包围了!"), [STRINGID_CURSEDBODYDISABLED] = COMPOUND_STRING("因{B_DEF_NAME_WITH_PREFIX2}的{B_DEF_ABILITY},\n封住了{B_ATK_NAME_WITH_PREFIX}的\l{B_BUFF1}!"), [STRINGID_ATTACKERACQUIREDABILITY] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX}的特性\n变为{B_LAST_ABILITY}了!"), - [STRINGID_TARGETABILITYSTATLOWER] = COMPOUND_STRING("因为{B_DEF_ABILITY},\n{B_DEF_NAME_WITH_PREFIX}的{B_BUFF1}降低了!"), + [STRINGID_TARGETABILITYSTATLOWER] = COMPOUND_STRING("因为{B_DEF_ABILITY},\n{B_DEF_NAME_WITH_PREFIX}的{B_BUFF1}{B_BUFF2}降低了!"), [STRINGID_TARGETSTATWONTGOHIGHER] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX}的\n{B_BUFF1}已经无法再提高了!"), [STRINGID_PKMNMOVEBOUNCEDABILITY] = COMPOUND_STRING("因{B_DEF_NAME_WITH_PREFIX2}的{B_DEF_ABILITY},\n将{B_ATK_NAME_WITH_PREFIX}的\l{B_CURRENT_MOVE}反射了回去!"), [STRINGID_IMPOSTERTRANSFORM] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX}因{B_LAST_ABILITY}\n变成了{B_DEF_NAME_WITH_PREFIX2}!"), @@ -687,7 +666,7 @@ const u8 *const gBattleStringsTable[STRINGID_COUNT] = [STRINGID_SWEETVEILPROTECTED] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX}\n因甜幕而不会睡着!"), [STRINGID_AROMAVEILPROTECTED] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX}\n正受到芳香幕的保护!"), [STRINGID_CELEBRATEMESSAGE] = COMPOUND_STRING("恭喜恭喜!\n{B_PLAYER_NAME}!"), - [STRINGID_USEDINSTRUCTEDMOVE] = COMPOUND_STRING("根据{B_BUFF1}的指示,\n{B_ATK_NAME_WITH_PREFIX}使出了招式!"), + [STRINGID_USEDINSTRUCTEDMOVE] = COMPOUND_STRING("根据{B_SCR_NAME_WITH_PREFIX2}的指示,\n{B_ATK_NAME_WITH_PREFIX}使出了招式!"), [STRINGID_THROATCHOPENDS] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX}\n变得可以使出声音的招式了!"), [STRINGID_PKMNCANTUSEMOVETHROATCHOP] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX2}\n因深渊突刺的效果无法使出招式!\p"), [STRINGID_LASERFOCUS] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX}\n磨砺了精神!"), @@ -701,7 +680,7 @@ const u8 *const gBattleStringsTable[STRINGID_COUNT] = [STRINGID_ATTACKERCUREDTARGETSTATUS] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX}\n治愈了{B_DEF_NAME_WITH_PREFIX2}的异常状态!"), [STRINGID_ATTACKERLOSTFIRETYPE] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX}的火焰燃尽了!"), [STRINGID_HEALERCURE] = COMPOUND_STRING("因{B_ATK_NAME_WITH_PREFIX}的{B_LAST_ABILITY},\n{B_SCR_NAME_WITH_PREFIX2}的异常状态治愈了!"), - [STRINGID_SCRIPTINGABILITYSTATRAISE] = COMPOUND_STRING("因为{B_SCR_ABILITY},\n{B_SCR_NAME_WITH_PREFIX}的{B_BUFF1}提高了!"), + [STRINGID_SCRIPTINGABILITYSTATRAISE] = COMPOUND_STRING("因为{B_SCR_ABILITY},\n{B_SCR_NAME_WITH_PREFIX}的{B_BUFF1}{B_BUFF2}提高了!"), [STRINGID_RECEIVERABILITYTAKEOVER] = COMPOUND_STRING("继承了{B_SCR_NAME_WITH_PREFIX}的\n{B_SCR_ABILITY}!"), [STRINGID_PKNMABSORBINGPOWER] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX}\n正在积蓄力量!"), [STRINGID_NOONEWILLBEABLETORUNAWAY] = COMPOUND_STRING("下回合无法逃走!"), @@ -717,10 +696,8 @@ const u8 *const gBattleStringsTable[STRINGID_COUNT] = [STRINGID_COMATOSEENTERS] = COMPOUND_STRING("{B_SCR_NAME_WITH_PREFIX}\n处于半梦半醒状态!"), [STRINGID_SCREENCLEANERENTERS] = COMPOUND_STRING("双方场上的反射壁、光墙\n和极光幕消失了!"), [STRINGID_FETCHEDPOKEBALL] = COMPOUND_STRING("{B_SCR_NAME_WITH_PREFIX}\n捡来了{B_LAST_ITEM}!"), - [STRINGID_BATTLERABILITYRAISEDSTAT] = COMPOUND_STRING("因为{B_SCR_ABILITY},\n{B_SCR_NAME_WITH_PREFIX}的{B_BUFF1}提高了!"), [STRINGID_ASANDSTORMKICKEDUP] = COMPOUND_STRING("开始刮沙暴了!"), [STRINGID_PKMNSWILLPERISHIN3TURNS] = COMPOUND_STRING("双方将在3回合后灭亡!"), //don't think this message is displayed anymore - [STRINGID_ABILITYRAISEDSTATDRASTICALLY] = COMPOUND_STRING("因为{B_DEF_ABILITY},\n{B_DEF_NAME_WITH_PREFIX2}的{B_BUFF1}巨幅提高了!"), [STRINGID_AURAFLAREDTOLIFE] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX}让气场覆盖全身!"), [STRINGID_ASONEENTERS] = COMPOUND_STRING("{B_SCR_NAME_WITH_PREFIX}\n同时拥有了两种特性!"), [STRINGID_CURIOUSMEDICINEENTERS] = COMPOUND_STRING("{B_EFF_NAME_WITH_PREFIX}的\n能力变化消失了!"), @@ -733,9 +710,9 @@ const u8 *const gBattleStringsTable[STRINGID_COUNT] = [STRINGID_PKMNBURNHEALED] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX}的\n灼伤治愈了!"), [STRINGID_REDCARDACTIVATE] = COMPOUND_STRING("{B_SCR_NAME_WITH_PREFIX}猛地向\n{B_ATK_NAME_WITH_PREFIX2}出示了红牌!"), [STRINGID_EJECTBUTTONACTIVATE] = COMPOUND_STRING("{B_SCR_NAME_WITH_PREFIX}\n要用{B_LAST_ITEM}回去了!"), - [STRINGID_ATKGOTOVERINFATUATION] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX}的\n着迷状态治愈了!"), - [STRINGID_TORMENTEDNOMORE] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX}的\n无理取闹的效果消失了!"), - [STRINGID_HEALBLOCKEDNOMORE] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX}的\n回复封锁的效果消失了!"), + [STRINGID_ATKGOTOVERINFATUATION] = COMPOUND_STRING("{B_SCR_NAME_WITH_PREFIX}的\n着迷状态治愈了!"), + [STRINGID_TORMENTEDNOMORE] = COMPOUND_STRING("{B_SCR_NAME_WITH_PREFIX}的\n无理取闹的效果消失了!"), + [STRINGID_HEALBLOCKEDNOMORE] = COMPOUND_STRING("{B_SCR_NAME_WITH_PREFIX}的\n回复封锁的效果消失了!"), [STRINGID_ATTACKERBECAMEFULLYCHARGED] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX}\n浑身充满了牵绊之力!\p"), [STRINGID_ATTACKERBECAMEASHSPECIES] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX}\n变身成了小智版甲贺忍蛙!\p"), [STRINGID_EXTREMELYHARSHSUNLIGHT] = COMPOUND_STRING("日照变得非常强了!"), @@ -757,7 +734,6 @@ const u8 *const gBattleStringsTable[STRINGID_COUNT] = [STRINGID_BROKETHROUGHPROTECTION] = COMPOUND_STRING("打破了\n{B_DEF_NAME_WITH_PREFIX2}的防守!"), [STRINGID_ABILITYALLOWSONLYMOVE] = COMPOUND_STRING("因为{B_ATK_ABILITY}的效果,\n只能使出{B_CURRENT_MOVE}!\p"), [STRINGID_SWAPPEDABILITIES] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX}\n互换了各自的特性!"), - [STRINGID_PASTELVEILPROTECTED] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX}\n正受到粉彩护幕的保护!"), [STRINGID_PASTELVEILENTERS] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX}的毒\n消失得干干净净!"), [STRINGID_BATTLERTYPECHANGEDTO] = COMPOUND_STRING("{B_SCR_NAME_WITH_PREFIX}\n变成了{B_BUFF1}属性!"), [STRINGID_BOTHCANNOLONGERESCAPE] = COMPOUND_STRING("双方的宝可梦无法逃走了!"), @@ -1094,24 +1070,12 @@ const u16 gUproarOverTurnStringIds[] = [B_MSG_UPROAR_ENDS] = STRINGID_PKMNCALMEDDOWN }; -const u16 gStockpileUsedStringIds[] = -{ - [B_MSG_STOCKPILED] = STRINGID_PKMNSTOCKPILED, - [B_MSG_CANT_STOCKPILE] = STRINGID_PKMNCANTSTOCKPILE, -}; - const u16 gWokeUpStringIds[] = { [B_MSG_WOKE_UP] = STRINGID_PKMNWOKEUP, [B_MSG_WOKE_UP_UPROAR] = STRINGID_PKMNWOKEUPINUPROAR }; -const u16 gSwallowFailStringIds[] = -{ - [B_MSG_SWALLOW_FAILED] = STRINGID_FAILEDTOSWALLOW, - [B_MSG_SWALLOW_FULL_HP] = STRINGID_PKMNHPFULL -}; - const u16 gUproarAwakeStringIds[] = { [B_MSG_CANT_SLEEP_UPROAR] = STRINGID_PKMNCANTSLEEPINUPROAR2, @@ -1120,20 +1084,21 @@ const u16 gUproarAwakeStringIds[] = const u16 gStatUpStringIds[] = { - [B_MSG_ATTACKER_STAT_ROSE] = STRINGID_ATTACKERSSTATROSE, - [B_MSG_DEFENDER_STAT_ROSE] = STRINGID_DEFENDERSSTATROSE, - [B_MSG_STAT_WONT_INCREASE] = STRINGID_STATSWONTINCREASE, - [B_MSG_STAT_ROSE_EMPTY] = STRINGID_EMPTYSTRING3, - [B_MSG_STAT_ROSE_ITEM] = STRINGID_USINGITEMSTATOFPKMNROSE, - [B_MSG_USED_DIRE_HIT] = STRINGID_PKMNUSEDXTOGETPUMPED, + [B_MSG_ATTACKER_STAT_CHANGED] = STRINGID_ATTACKERSSTATROSE, + [B_MSG_DEFENDER_STAT_CHANGED] = STRINGID_DEFENDERSSTATROSE, + [B_MSG_STAT_WONT_CHANGE] = STRINGID_STATSWONTINCREASE, + [B_MSG_STAT_CHANGE_EMPTY] = STRINGID_EMPTYSTRING3, + [B_MSG_STAT_CHANGED_ITEM] = STRINGID_USINGITEMSTATOFPKMNROSE, + [B_MSG_USED_DIRE_HIT] = STRINGID_PKMNUSEDXTOGETPUMPED, }; const u16 gStatDownStringIds[] = { - [B_MSG_ATTACKER_STAT_FELL] = STRINGID_ATTACKERSSTATFELL, - [B_MSG_DEFENDER_STAT_FELL] = STRINGID_DEFENDERSSTATFELL, - [B_MSG_STAT_WONT_DECREASE] = STRINGID_STATSWONTDECREASE, - [B_MSG_STAT_FELL_EMPTY] = STRINGID_EMPTYSTRING3, + [B_MSG_ATTACKER_STAT_CHANGED] = STRINGID_ATTACKERSSTATFELL, + [B_MSG_DEFENDER_STAT_CHANGED] = STRINGID_DEFENDERSSTATFELL, + [B_MSG_STAT_WONT_CHANGE] = STRINGID_STATSWONTDECREASE, + [B_MSG_STAT_CHANGE_EMPTY] = STRINGID_EMPTYSTRING3, + [B_MSG_STAT_CHANGED_ITEM] = STRINGID_USINGITEMSTATOFPKMNFELL, }; // Index copied from move's index in sTrappingMoves @@ -1327,22 +1292,18 @@ const u16 gSafariPokeblockResultStringIds[] = [B_MSG_MON_IGNORED] = STRINGID_PKMNIGNOREDX }; -const u16 gBerryEffectStringIds[] = +const u16 CureStatusBerryEffectStringID[] = { + [B_MSG_CURED_PARALYSIS] = STRINGID_PKMNSITEMCUREDPARALYSIS, + [B_MSG_CURED_POISON] = STRINGID_PKMNSITEMCUREDPOISON, + [B_MSG_CURED_BURN] = STRINGID_PKMNSITEMHEALEDBURN, + [B_MSG_CURED_FREEEZE] = STRINGID_PKMNSITEMDEFROSTEDIT, + [B_MSG_CURED_FROSTBITE] = STRINGID_PKMNSITEMHEALEDFROSTBITE, + [B_MSG_CURED_SLEEP] = STRINGID_PKMNSITEMWOKEIT, [B_MSG_CURED_PROBLEM] = STRINGID_PKMNSITEMCUREDPROBLEM, [B_MSG_NORMALIZED_STATUS] = STRINGID_PKMNSITEMNORMALIZEDSTATUS }; -const u16 gStatusPreventionStringIds[] = -{ - [B_MSG_ABILITY_PREVENTS_MOVE_BURN] = STRINGID_PKMNSXPREVENTSBURNS, - [B_MSG_ABILITY_PREVENTS_MOVE_PARALYSIS] = STRINGID_PKMNPREVENTSPARALYSISWITH, - [B_MSG_ABILITY_PREVENTS_MOVE_POISON] = STRINGID_PKMNPREVENTSPOISONINGWITH, - [B_MSG_ABILITY_PREVENTS_ABILITY_STATUS] = STRINGID_PKMNSXPREVENTSYSZ, - [B_MSG_STATUS_HAD_NO_EFFECT] = STRINGID_PKMNSXHADNOEFFECTONY, - [B_MSG_ABILITY_PASTEL_VEIL] = STRINGID_PASTELVEILPROTECTED -}; - const u16 gItemSwapStringIds[] = { [B_MSG_ITEM_SWAP_TAKEN] = STRINGID_PKMNOBTAINEDX, @@ -1482,6 +1443,8 @@ static const u8 sText_TwoTrainersSentPkmn[] = _("{B_TRAINER1_NAME_WITH_CLASS}\n static const u8 sText_Trainer2SentOutPkmn[] = _("{B_TRAINER2_NAME_WITH_CLASS}\n派出了{B_BUFF1}!"); static const u8 sText_TwoTrainersWantToBattle[] = _("{B_TRAINER1_NAME_WITH_CLASS}和\n{B_TRAINER2_NAME_WITH_CLASS}\l前来挑战了!\p"); static const u8 sText_InGamePartnerSentOutZGoN[] = _("{B_PARTNER_NAME_WITH_CLASS}\n派出了{B_PLAYER_MON2_NAME}!\l上吧!{B_PLAYER_MON1_NAME}!"); +static const u8 sText_InGamePartnerSentOutPkmn2[] = _("{B_PARTNER_NAME_WITH_CLASS}\n派出了{B_PLAYER_MON2_NAME}!"); +static const u8 sText_InGamePartnerWithdrewPkmn2[] = _("{B_PARTNER_NAME_WITH_CLASS}\n换下了{B_PLAYER_MON2_NAME}!"); const u16 gBattlePalaceFlavorTextTable[] = { @@ -2104,9 +2067,31 @@ void BufferStringBattle(enum StringID stringID, u32 battler) else if (gBattleTypeFlags & BATTLE_TYPE_MULTI) { if (gBattleTypeFlags & BATTLE_TYPE_RECORDED) - stringPtr = sText_TwoLinkTrainersWantToBattlePause; + { + if (TESTING && gBattleTypeFlags & BATTLE_TYPE_MULTI) + { + if (!(gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS)) + stringPtr = sText_Trainer1WantsToBattle; + else + stringPtr = sText_TwoTrainersWantToBattle; + } + else if (TESTING && gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS) + { + stringPtr = sText_TwoTrainersWantToBattle; + } + else if (!(gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS)) + { + stringPtr = sText_LinkTrainerWantsToBattlePause; + } + else + { + stringPtr = sText_TwoLinkTrainersWantToBattlePause; + } + } else + { stringPtr = sText_TwoLinkTrainersWantToBattle; + } } else { @@ -2192,7 +2177,9 @@ void BufferStringBattle(enum StringID stringID, u32 battler) case STRINGID_RETURNMON: // sending poke to ball msg if (IsOnPlayerSide(battler)) { - if (*(&gBattleStruct->hpScale) == 0) + if (gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER && GetBattlerPosition(battler) == B_POSITION_PLAYER_RIGHT) + stringPtr = sText_InGamePartnerWithdrewPkmn2; + else if (*(&gBattleStruct->hpScale) == 0) stringPtr = sText_PkmnThatsEnough; else if (*(&gBattleStruct->hpScale) == 1 || IsDoubleBattle()) stringPtr = sText_PkmnComeBack; @@ -2212,14 +2199,27 @@ void BufferStringBattle(enum StringID stringID, u32 battler) } else { - stringPtr = sText_Trainer1WithdrewPkmn; + if (gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS) + { + if (GetBattlerPosition(battler) == B_POSITION_OPPONENT_LEFT) + stringPtr = sText_Trainer1WithdrewPkmn; + else + stringPtr = sText_Trainer2WithdrewPkmn; + + } + else + { + stringPtr = sText_Trainer1WithdrewPkmn; + } } } break; case STRINGID_SWITCHINMON: // switch-in msg if (IsOnPlayerSide(gBattleScripting.battler)) { - if (*(&gBattleStruct->hpScale) == 0 || IsDoubleBattle()) + if ((gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER) && (GetBattlerAtPosition(gBattleScripting.battler) == 2)) + stringPtr = sText_InGamePartnerSentOutPkmn2; + else if (*(&gBattleStruct->hpScale) == 0 || IsDoubleBattle()) stringPtr = sText_GoPkmn2; else if (*(&gBattleStruct->hpScale) == 1) stringPtr = sText_DoItPkmn; @@ -2241,12 +2241,39 @@ void BufferStringBattle(enum StringID stringID, u32 battler) } else { - if (gBattleTypeFlags & BATTLE_TYPE_MULTI) + if (TESTING && gBattleTypeFlags & BATTLE_TYPE_MULTI) + { + if (gBattleScripting.battler == 1) + { + stringPtr = sText_Trainer1SentOutPkmn; + } + else + { + if (gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS) + stringPtr = sText_Trainer2SentOutPkmn; + else + stringPtr = sText_Trainer1SentOutPkmn2; + } + } + else if (TESTING && gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS) + { + if (gBattleScripting.battler == 1) + stringPtr = sText_Trainer1SentOutPkmn; + else + stringPtr = sText_Trainer2SentOutPkmn; + } + else if (gBattleTypeFlags & BATTLE_TYPE_MULTI) + { stringPtr = sText_LinkTrainerMultiSentOutPkmn; + } else if (TRAINER_BATTLE_PARAM.opponentA == TRAINER_UNION_ROOM) + { stringPtr = sText_Trainer1SentOutPkmn2; + } else + { stringPtr = sText_LinkTrainerSentOutPkmn2; + } } } else diff --git a/src/battle_pike.c b/src/battle_pike.c index 3218ef3846..6330e04373 100644 --- a/src/battle_pike.c +++ b/src/battle_pike.c @@ -811,7 +811,7 @@ static void HealMon(struct Pokemon *mon) static bool8 DoesAbilityPreventStatus(struct Pokemon *mon, u32 status) { - u16 ability = GetMonAbility(mon); + enum Ability ability = GetMonAbility(mon); bool8 ret = FALSE; if (ability == ABILITY_COMATOSE) @@ -862,7 +862,7 @@ static bool8 DoesTypePreventStatus(u16 species, u32 status) break; case STATUS1_PARALYSIS: if (GetSpeciesType(species, 0) == TYPE_GROUND || GetSpeciesType(species, 1) == TYPE_GROUND - || (GetGenConfig(GEN_CONFIG_PARALYZE_ELECTRIC) >= GEN_6 && (GetSpeciesType(species, 0) == TYPE_ELECTRIC || GetSpeciesType(species, 1) == TYPE_ELECTRIC))) + || (GetConfig(CONFIG_PARALYZE_ELECTRIC) >= GEN_6 && (GetSpeciesType(species, 0) == TYPE_ELECTRIC || GetSpeciesType(species, 1) == TYPE_ELECTRIC))) ret = TRUE; break; case STATUS1_BURN: @@ -1623,7 +1623,7 @@ static bool8 CanEncounterWildMon(u8 enemyMonLevel) { if (!GetMonData(&gPlayerParty[0], MON_DATA_SANITY_IS_EGG)) { - u16 monAbility = GetMonAbility(&gPlayerParty[0]); + enum Ability monAbility = GetMonAbility(&gPlayerParty[0]); if (monAbility == ABILITY_KEEN_EYE || monAbility == ABILITY_INTIMIDATE) { u8 playerMonLevel = GetMonData(&gPlayerParty[0], MON_DATA_LEVEL); diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c old mode 100755 new mode 100644 index d8c8e32e91..92c4bff67c --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -1,5 +1,6 @@ #include "global.h" #include "battle.h" +#include "battle_hold_effects.h" #include "battle_message.h" #include "battle_anim.h" #include "battle_ai_main.h" @@ -53,7 +54,6 @@ #include "constants/battle_move_effects.h" #include "constants/battle_string_ids.h" #include "constants/battle_partner.h" -#include "constants/hold_effects.h" #include "constants/items.h" #include "constants/item_effects.h" #include "constants/moves.h" @@ -67,8 +67,10 @@ #include "constants/pokemon.h" #include "config/battle.h" #include "data/battle_move_effects.h" +#include "test/battle.h" #include "follower_npc.h" #include "load_save.h" +#include "test/test_runner_battle.h" // table to avoid ugly powing on gba (courtesy of doesnt) // this returns (i^2.5)/4 @@ -308,8 +310,7 @@ enum GiveCaughtMonStates #define TAG_LVLUP_BANNER_MON_ICON 55130 -static void TrySetDestinyBondToHappen(void); -static u32 ChangeStatBuffs(u32 battler, s8 statValue, u32 statId, union StatChangeFlags flags, u32 stats, const u8 *BS_ptr); +static u32 ChangeStatBuffs(u32 battler, s8 statValue, enum Stat statId, union StatChangeFlags flags, u32 stats, const u8 *BS_ptr); static bool32 IsMonGettingExpSentOut(void); static void InitLevelUpBanner(void); static bool8 SlideInLevelUpBanner(void); @@ -321,26 +322,27 @@ static void DrawLevelUpBannerText(void); static void SpriteCB_MonIconOnLvlUpBanner(struct Sprite *sprite); static bool32 CriticalCapture(u32 odds); static void BestowItem(u32 battlerAtk, u32 battlerDef); -static bool8 IsFinalStrikeEffect(enum BattleMoveEffects moveEffect); +static bool32 IsFinalStrikeEffect(enum MoveEffect moveEffect); static void TryUpdateRoundTurnOrder(void); static bool32 ChangeOrderTargetAfterAttacker(void); static bool32 SetTargetToNextPursuiter(u32 battlerDef); void ApplyExperienceMultipliers(s32 *expAmount, u8 expGetterMonId, u8 faintedBattler); static void RemoveAllWeather(void); static void RemoveAllTerrains(void); -static bool32 CanAbilityPreventStatLoss(u32 abilityDef); +static bool32 CanAbilityPreventStatLoss(enum Ability abilityDef); static u32 GetNextTarget(u32 moveTarget, bool32 excludeCurrent); static void TryUpdateEvolutionTracker(u32 evolutionCondition, u32 upAmount, u16 usedMove); static void AccuracyCheck(bool32 recalcDragonDarts, const u8 *nextInstr, const u8 *failInstr, u16 move); static void ResetValuesForCalledMove(void); -static void TryRestoreDamageAfterCheekPouch(u32 battler); static bool32 TrySymbiosis(u32 battler, u32 itemId, bool32 moveEnd); static bool32 CanAbilityShieldActivateForBattler(u32 battler); +static void TryClearChargeVolatile(u32 moveType); +static bool32 IsAnyTargetAffected(void); static void Cmd_attackcanceler(void); static void Cmd_accuracycheck(void); -static void Cmd_attackstring(void); -static void Cmd_ppreduce(void); +static void Cmd_printattackstring(void); +static void Cmd_unused_0x3(void); static void Cmd_critcalc(void); static void Cmd_damagecalc(void); static void Cmd_typecalc(void); @@ -396,7 +398,7 @@ static void Cmd_bichalfword(void); static void Cmd_bicword(void); static void Cmd_pause(void); static void Cmd_waitstate(void); -static void Cmd_absorb(void); +static void Cmd_isdmgblockedbydisguise(void); static void Cmd_return(void); static void Cmd_end(void); static void Cmd_end2(void); @@ -455,25 +457,25 @@ static void Cmd_jumpifplayerran(void); static void Cmd_hpthresholds(void); static void Cmd_hpthresholds2(void); static void Cmd_useitemonopponent(void); -static void Cmd_various(void); +static void Cmd_unused_0x78(void); static void Cmd_setprotectlike(void); static void Cmd_tryexplosion(void); static void Cmd_setatkhptozero(void); static void Cmd_jumpifnexttargetvalid(void); static void Cmd_tryhealhalfhealth(void); -static void Cmd_trymirrormove(void); +static void Cmd_unused_0x7e(void); static void Cmd_setfieldweather(void); static void Cmd_setreflect(void); static void Cmd_setseeded(void); static void Cmd_manipulatedamage(void); static void Cmd_trysetrest(void); -static void Cmd_jumpifnotfirstturn(void); +static void Cmd_unused_0x82(void); static void Cmd_unused_0x83(void); static void Cmd_jumpifuproarwakes(void); static void Cmd_stockpile(void); static void Cmd_stockpiletobasedamage(void); static void Cmd_stockpiletohpheal(void); -static void Cmd_setdrainedhp(void); +static void Cmd_unused_0x88(void); static void Cmd_statbuffchange(void); static void Cmd_normalisebuffs(void); static void Cmd_setbide(void); @@ -495,7 +497,7 @@ static void Cmd_setfocusenergy(void); static void Cmd_transformdataexecution(void); static void Cmd_setsubstitute(void); static void Cmd_mimicattackcopy(void); -static void Cmd_metronome(void); +static void Cmd_setcalledmove(void); static void Cmd_unused_0x9f(void); static void Cmd_unused_0xA0(void); static void Cmd_counterdamagecalculator(void); @@ -506,9 +508,9 @@ static void Cmd_painsplitdmgcalc(void); static void Cmd_settypetorandomresistance(void); static void Cmd_setalwayshitflag(void); static void Cmd_copymovepermanently(void); -static void Cmd_trychoosesleeptalkmove(void); -static void Cmd_trysetdestinybond(void); -static void Cmd_trysetdestinybondtohappen(void); +static void Cmd_unused_0xA9(void); +static void Cmd_unused_AA(void); +static void Cmd_unused_0xab(void); static void Cmd_settailwind(void); static void Cmd_tryspiteppreduce(void); static void Cmd_healpartystatus(void); @@ -524,7 +526,7 @@ static void Cmd_presentdamagecalculation(void); static void Cmd_setsafeguard(void); static void Cmd_magnitudedamagecalculation(void); static void Cmd_jumpifnopursuitswitchdmg(void); -static void Cmd_tryrestorehpberry(void); +static void Cmd_tryactivateitem(void); static void Cmd_halvehp(void); static void Cmd_copyfoestats(void); static void Cmd_rapidspinfree(void); @@ -532,7 +534,7 @@ static void Cmd_unused_0xBF(void); static void Cmd_recoverbasedonsunlight(void); static void Cmd_setstickyweb(void); static void Cmd_selectfirstvalidtarget(void); -static void Cmd_trysetfutureattack(void); +static void Cmd_setfutureattack(void); static void Cmd_trydobeatup(void); static void Cmd_setsemiinvulnerablebit(void); static void Cmd_tryfiretwoturnmovenowbyeffect(void); @@ -540,8 +542,8 @@ static void Cmd_unused_0xC7(void); static void Cmd_unused_c8(void); static void Cmd_trymemento(void); static void Cmd_setforcedtarget(void); -static void Cmd_setcharge(void); -static void Cmd_callenvironmentattack(void); +static void Cmd_unused_0xcb(void); +static void Cmd_unused_0xCC(void); static void Cmd_curestatuswithmove(void); static void Cmd_settorment(void); static void Cmd_jumpifnodamage(void); @@ -559,13 +561,13 @@ static void Cmd_tryswapabilities(void); static void Cmd_tryimprison(void); static void Cmd_setstealthrock(void); static void Cmd_trysetvolatile(void); -static void Cmd_assistattackselect(void); +static void Cmd_unused_0xde(void); static void Cmd_trysetmagiccoat(void); static void Cmd_trysetsnatch(void); static void Cmd_unused2(void); static void Cmd_switchoutabilities(void); static void Cmd_jumpifhasnohp(void); -static void Cmd_jumpifnotcurrentmoveargtype(void); +static void Cmd_unused_0xE4(void); static void Cmd_pickup(void); static void Cmd_unused_0xE6(void); static void Cmd_unused_0xE7(void); @@ -581,7 +583,7 @@ static void Cmd_givecaughtmon(void); static void Cmd_trysetcaughtmondexflags(void); static void Cmd_displaydexinfo(void); static void Cmd_trygivecaughtmonnick(void); -static void Cmd_subattackerhpbydmg(void); +static void Cmd_unused_0xf4(void); static void Cmd_removeattackerstatus1(void); static void Cmd_finishaction(void); static void Cmd_finishturn(void); @@ -591,15 +593,15 @@ static void Cmd_swapstatstages(void); static void Cmd_averagestats(void); static void Cmd_jumpifcaptivateaffected(void); static void Cmd_setnonvolatilestatus(void); -static void Cmd_tryworryseed(void); +static void Cmd_tryoverwriteability(void); static void Cmd_callnative(void); void (*const gBattleScriptingCommandsTable[])(void) = { Cmd_attackcanceler, //0x0 Cmd_accuracycheck, //0x1 - Cmd_attackstring, //0x2 - Cmd_ppreduce, //0x3 + Cmd_printattackstring, //0x2 + Cmd_unused_0x3, //0x3 Cmd_critcalc, //0x4 Cmd_damagecalc, //0x5 Cmd_typecalc, //0x6 @@ -655,7 +657,7 @@ void (*const gBattleScriptingCommandsTable[])(void) = Cmd_bicword, //0x38 Cmd_pause, //0x39 Cmd_waitstate, //0x3A - Cmd_absorb, //0x3B + Cmd_isdmgblockedbydisguise, //0x3B Cmd_return, //0x3C Cmd_end, //0x3D Cmd_end2, //0x3E @@ -714,25 +716,25 @@ void (*const gBattleScriptingCommandsTable[])(void) = Cmd_hpthresholds, //0x73 Cmd_hpthresholds2, //0x74 Cmd_useitemonopponent, //0x75 - Cmd_various, //0x76 + Cmd_unused_0x78, //0x76 Cmd_setprotectlike, //0x77 Cmd_tryexplosion, //0x78 Cmd_setatkhptozero, //0x79 Cmd_jumpifnexttargetvalid, //0x7A Cmd_tryhealhalfhealth, //0x7B - Cmd_trymirrormove, //0x7C + Cmd_unused_0x7e, //0x7C Cmd_setfieldweather, //0x7D Cmd_setreflect, //0x7E Cmd_setseeded, //0x7F Cmd_manipulatedamage, //0x80 Cmd_trysetrest, //0x81 - Cmd_jumpifnotfirstturn, //0x82 + Cmd_unused_0x82, //0x82 Cmd_unused_0x83, //0x83 Cmd_jumpifuproarwakes, //0x84 Cmd_stockpile, //0x85 Cmd_stockpiletobasedamage, //0x86 Cmd_stockpiletohpheal, //0x87 - Cmd_setdrainedhp, //0x88 + Cmd_unused_0x88, //0x88 Cmd_statbuffchange, //0x89 Cmd_normalisebuffs, //0x8A Cmd_setbide, //0x8B @@ -754,7 +756,7 @@ void (*const gBattleScriptingCommandsTable[])(void) = Cmd_transformdataexecution, //0x9B Cmd_setsubstitute, //0x9C Cmd_mimicattackcopy, //0x9D - Cmd_metronome, //0x9E + Cmd_setcalledmove, //0x9E Cmd_unused_0x9f, //0x9F Cmd_unused_0xA0, //0xA0 Cmd_counterdamagecalculator, //0xA1 @@ -765,9 +767,9 @@ void (*const gBattleScriptingCommandsTable[])(void) = Cmd_settypetorandomresistance, //0xA6 Cmd_setalwayshitflag, //0xA7 Cmd_copymovepermanently, //0xA8 - Cmd_trychoosesleeptalkmove, //0xA9 - Cmd_trysetdestinybond, //0xAA - Cmd_trysetdestinybondtohappen, //0xAB + Cmd_unused_0xA9, //0xA9 + Cmd_unused_AA, //0xAA + Cmd_unused_0xab, //0xAB Cmd_settailwind, //0xAC Cmd_tryspiteppreduce, //0xAD Cmd_healpartystatus, //0xAE @@ -783,7 +785,7 @@ void (*const gBattleScriptingCommandsTable[])(void) = Cmd_setsafeguard, //0xB8 Cmd_magnitudedamagecalculation, //0xB9 Cmd_jumpifnopursuitswitchdmg, //0xBA - Cmd_tryrestorehpberry, //0xBB + Cmd_tryactivateitem, //0xBB Cmd_halvehp, //0xBC Cmd_copyfoestats, //0xBD Cmd_rapidspinfree, //0xBE @@ -791,7 +793,7 @@ void (*const gBattleScriptingCommandsTable[])(void) = Cmd_recoverbasedonsunlight, //0xC0 Cmd_setstickyweb, //0xC1 Cmd_selectfirstvalidtarget, //0xC2 - Cmd_trysetfutureattack, //0xC3 + Cmd_setfutureattack, //0xC3 Cmd_trydobeatup, //0xC4 Cmd_setsemiinvulnerablebit, //0xC5 Cmd_tryfiretwoturnmovenowbyeffect, //0xC6 @@ -799,8 +801,8 @@ void (*const gBattleScriptingCommandsTable[])(void) = Cmd_unused_c8, //0xC8 Cmd_trymemento, //0xC9 Cmd_setforcedtarget, //0xCA - Cmd_setcharge, //0xCB - Cmd_callenvironmentattack, //0xCC + Cmd_unused_0xcb, //0xCB + Cmd_unused_0xCC, //0xCC Cmd_curestatuswithmove, //0xCD Cmd_settorment, //0xCE Cmd_jumpifnodamage, //0xCF @@ -818,13 +820,13 @@ void (*const gBattleScriptingCommandsTable[])(void) = Cmd_tryimprison, //0xDB Cmd_setstealthrock, //0xDC Cmd_trysetvolatile, //0xDD - Cmd_assistattackselect, //0xDE + Cmd_unused_0xde, //0xDE Cmd_trysetmagiccoat, //0xDF Cmd_trysetsnatch, //0xE0 Cmd_unused2, //0xE1 Cmd_switchoutabilities, //0xE2 Cmd_jumpifhasnohp, //0xE3 - Cmd_jumpifnotcurrentmoveargtype, //0xE4 + Cmd_unused_0xE4, //0xE4 Cmd_pickup, //0xE5 Cmd_unused_0xE6, //0xE6 Cmd_unused_0xE7, //0xE7 @@ -840,7 +842,7 @@ void (*const gBattleScriptingCommandsTable[])(void) = Cmd_trysetcaughtmondexflags, //0xF1 Cmd_displaydexinfo, //0xF2 Cmd_trygivecaughtmonnick, //0xF3 - Cmd_subattackerhpbydmg, //0xF4 + Cmd_unused_0xf4, //0xF4 Cmd_removeattackerstatus1, //0xF5 Cmd_finishaction, //0xF6 Cmd_finishturn, //0xF7 @@ -850,7 +852,7 @@ void (*const gBattleScriptingCommandsTable[])(void) = Cmd_averagestats, //0xFB Cmd_jumpifcaptivateaffected, //0xFC Cmd_setnonvolatilestatus, //0xFD - Cmd_tryworryseed, //0xFE + Cmd_tryoverwriteability, //0xFE Cmd_callnative, //0xFF }; @@ -915,15 +917,6 @@ static const struct SpriteTemplate sSpriteTemplate_MonIconOnLvlUpBanner = static const u16 sProtectSuccessRates[] = {USHRT_MAX, USHRT_MAX / 2, USHRT_MAX / 4, USHRT_MAX / 8}; -static const u16 sFinalStrikeOnlyEffects[] = -{ - MOVE_EFFECT_REMOVE_ARG_TYPE, - MOVE_EFFECT_REMOVE_STATUS, - MOVE_EFFECT_RECOIL_HP_25, - MOVE_EFFECT_PREVENT_ESCAPE, - MOVE_EFFECT_WRAP, -}; - #define _ 0 static const struct PickupItem sPickupTable[] = @@ -962,6 +955,24 @@ static const struct PickupItem sPickupTable[] = #undef _ +static void ValidateSavedBattlerCounts(void) +{ + if (gBattleStruct->savedAttackerCount > 0) + { + if (TESTING) + Test_ExitWithResult(TEST_RESULT_ERROR, 0, "savedAttackerCount is greater than 0! More calls to SaveBattlerAttacker than RestoreBattlerAttacker!", __FILE__, __LINE__); + else + DebugPrintfLevel(MGBA_LOG_WARN, "savedAttackerCount is greater than 0! More calls to SaveBattlerAttacker than RestoreBattlerAttacker!"); + } + if (gBattleStruct->savedTargetCount > 0) + { + if (TESTING) + Test_ExitWithResult(TEST_RESULT_ERROR, 0, "savedTargetCount is greater than 0! More calls to SaveBattlerTarget than RestoreBattlerTarget!", __FILE__, __LINE__); + else + DebugPrintfLevel(MGBA_LOG_WARN, "savedTargetCount is greater than 0! More calls to SaveBattlerTarget than RestoreBattlerTarget!"); + } +} + static bool32 NoTargetPresent(u8 battler, u32 move) { if (!IsBattlerAlive(gBattlerTarget)) @@ -988,7 +999,7 @@ static bool32 NoTargetPresent(u8 battler, u32 move) return FALSE; } -bool32 ProteanTryChangeType(u32 battler, u32 ability, u32 move, u32 moveType) +bool32 ProteanTryChangeType(u32 battler, enum Ability ability, u32 move, enum Type moveType) { if ((ability == ABILITY_PROTEAN || ability == ABILITY_LIBERO) && !gDisableStructs[gBattlerAttacker].usedProteanLibero @@ -1008,6 +1019,34 @@ bool32 IsMoveNotAllowedInSkyBattles(u32 move) return (gBattleStruct->isSkyBattle && IsMoveSkyBattleBanned(gCurrentMove)); } +static void TryClearChargeVolatile(u32 moveType) +{ + if (B_CHARGE < GEN_9) // Prior to gen9, charge is cleared during the end turn + return; + + if (moveType == TYPE_ELECTRIC && gBattleMons[gBattlerAttacker].volatiles.chargeTimer == 1) + gBattleMons[gBattlerAttacker].volatiles.chargeTimer = 0; + + for (u32 battler = 0; battler < gBattlersCount; battler++) + { + if (gBattleMons[battler].volatiles.chargeTimer == 2) // Has been set this turn by move + gBattleMons[battler].volatiles.chargeTimer--; + } +} + +static bool32 IsAnyTargetAffected(void) +{ + for (u32 battler = 0; battler < gBattlersCount; battler++) + { + if (battler == gBattlerAttacker) + continue; + + if (!(gBattleStruct->moveResultFlags[battler] & MOVE_RESULT_NO_EFFECT)) + return TRUE; + } + return FALSE; +} + u32 NumAffectedSpreadMoveTargets(void) { u32 targetCount = 0; @@ -1040,11 +1079,11 @@ u32 NumFaintedBattlersByAttacker(u32 battlerAtk) return numMonsFainted; } -bool32 IsPowderMoveBlocked(u32 battlerAtk, u32 battlerDef, u32 move) +bool32 IsPowderMoveBlocked(struct BattleContext *ctx) { - if (!IsPowderMove(move) - || battlerAtk == battlerDef - || IsAffectedByPowderMove(battlerDef, GetBattlerAbility(battlerDef), GetBattlerHoldEffect(battlerDef, TRUE))) + if (!IsPowderMove(ctx->currentMove) + || ctx->battlerAtk == ctx->battlerDef + || IsAffectedByPowderMove(ctx->battlerDef, ctx->abilities[ctx->battlerDef], GetBattlerHoldEffect(ctx->battlerDef))) return FALSE; gBattlescriptCurrInstr = BattleScript_PowderMoveNoEffect; @@ -1053,13 +1092,12 @@ bool32 IsPowderMoveBlocked(u32 battlerAtk, u32 battlerDef, u32 move) bool32 EmergencyExitCanBeTriggered(u32 battler) { - u32 ability = GetBattlerAbility(battler); + enum Ability ability = GetBattlerAbility(battler); if (ability != ABILITY_EMERGENCY_EXIT && ability != ABILITY_WIMP_OUT) return FALSE; - if (IsBattlerTurnDamaged(battler) - && IsBattlerAlive(battler) + if (IsBattlerAlive(battler) && HadMoreThanHalfHpNowDoesnt(battler) && (CanBattlerSwitch(battler) || !(gBattleTypeFlags & BATTLE_TYPE_TRAINER)) && !(gBattleTypeFlags & BATTLE_TYPE_ARENA) @@ -1069,6 +1107,15 @@ bool32 EmergencyExitCanBeTriggered(u32 battler) return FALSE; } +static inline bool32 IsBattlerUsingBeakBlast(u32 battler) +{ + if (gChosenActionByBattler[battler] != B_ACTION_USE_MOVE) + return FALSE; + if (GetMoveEffect(gChosenMoveByBattler[battler]) != EFFECT_BEAK_BLAST) + return FALSE; + return !HasBattlerActedThisTurn(battler); +} + static void Cmd_attackcanceler(void) { CMD_ARGS(); @@ -1086,22 +1133,31 @@ static void Cmd_attackcanceler(void) return; } - enum BattleMoveEffects effect = GetMoveEffect(gCurrentMove); + struct BattleContext ctx = {0}; + ctx.battlerAtk = gBattlerAttacker; + ctx.battlerDef = gBattlerTarget; + ctx.currentMove = gCurrentMove; + + enum BattleMoveEffects moveEffect = GetMoveEffect(ctx.currentMove); if (!IsBattlerAlive(gBattlerAttacker) - && effect != EFFECT_EXPLOSION - && effect != EFFECT_MISTY_EXPLOSION - && !(gHitMarker & HITMARKER_NO_ATTACKSTRING)) + && moveEffect != EFFECT_EXPLOSION + && moveEffect != EFFECT_MISTY_EXPLOSION) { gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; gBattlescriptCurrInstr = BattleScript_MoveEnd; return; } - if (AtkCanceler_MoveSuccessOrder() != MOVE_STEP_SUCCESS) + + // With how attackcanceler works right now we only need attacker and target abilities. Might change in the future + ctx.abilities[ctx.battlerAtk] = GetBattlerAbility(ctx.battlerAtk); + ctx.abilities[ctx.battlerDef] = GetBattlerAbility(ctx.battlerDef); + + if (AtkCanceler_MoveSuccessOrder(&ctx) != MOVE_STEP_SUCCESS) return; if (gSpecialStatuses[gBattlerAttacker].parentalBondState == PARENTAL_BOND_OFF - && GetBattlerAbility(gBattlerAttacker) == ABILITY_PARENTAL_BOND + && ctx.abilities[ctx.battlerAtk] == ABILITY_PARENTAL_BOND && IsMoveAffectedByParentalBond(gCurrentMove, gBattlerAttacker) && !(gAbsentBattlerFlags & (1u << gBattlerTarget)) && GetActiveGimmick(gBattlerAttacker) != GIMMICK_Z_MOVE) @@ -1112,56 +1168,43 @@ static void Cmd_attackcanceler(void) return; } - - u32 abilityDef = GetBattlerAbility(gBattlerTarget); if (CanAbilityBlockMove( - gBattlerAttacker, - gBattlerTarget, - GetBattlerAbility(gBattlerAttacker), - abilityDef, - gCurrentMove, + ctx.battlerAtk, + ctx.battlerDef, + ctx.abilities[ctx.battlerAtk], + ctx.abilities[ctx.battlerDef], + ctx.currentMove, RUN_SCRIPT)) return; - if (GetMoveNonVolatileStatus(gCurrentMove) == MOVE_EFFECT_PARALYSIS) + if (GetMoveNonVolatileStatus(ctx.currentMove) == MOVE_EFFECT_PARALYSIS) { if (CanAbilityAbsorbMove( - gBattlerAttacker, - gBattlerTarget, - abilityDef, - gCurrentMove, - GetBattleMoveType(gCurrentMove), + ctx.battlerAtk, + ctx.battlerDef, + ctx.abilities[ctx.battlerDef], + ctx.currentMove, + GetBattleMoveType(ctx.currentMove), RUN_SCRIPT)) return; } - if (IsPowderMoveBlocked(gBattlerAttacker, gBattlerTarget, gCurrentMove)) + if (IsPowderMoveBlocked(&ctx)) return; - if (!gBattleMons[gBattlerAttacker].pp[gCurrMovePos] && gCurrentMove != MOVE_STRUGGLE - && !(gHitMarker & (HITMARKER_ALLOW_NO_PP | HITMARKER_NO_ATTACKSTRING | HITMARKER_NO_PPDEDUCT)) - && !(gBattleMons[gBattlerAttacker].volatiles.multipleTurns)) - { - gBattlescriptCurrInstr = BattleScript_NoPPForMove; - gBattleStruct->moveResultFlags[gBattlerTarget] |= MOVE_RESULT_MISSED; - return; - } - - gHitMarker &= ~HITMARKER_ALLOW_NO_PP; - // Check if no available target present on the field or if Sky Battles ban the move if ((NoTargetPresent(gBattlerAttacker, gCurrentMove) - && (!gBattleMoveEffects[effect].twoTurnEffect || (gBattleMons[gBattlerAttacker].volatiles.multipleTurns))) + && (!gBattleMoveEffects[moveEffect].twoTurnEffect || (gBattleMons[gBattlerAttacker].volatiles.multipleTurns))) || (IsMoveNotAllowedInSkyBattles(gCurrentMove))) { gBattleStruct->noTargetPresent = TRUE; - if (effect == EFFECT_FLING) // Edge case for removing a mon's item when there is no target available after using Fling. + if (moveEffect == EFFECT_FLING) // Edge case for removing a mon's item when there is no target available after using Fling. gBattlescriptCurrInstr = BattleScript_FlingFailConsumeItem; else - gBattlescriptCurrInstr = BattleScript_FailedFromAtkString; + gBattlescriptCurrInstr = BattleScript_ButItFailed; - if (!gBattleMoveEffects[effect].twoTurnEffect || (gBattleMons[gBattlerAttacker].volatiles.multipleTurns)) + if (!gBattleMoveEffects[moveEffect].twoTurnEffect || (gBattleMons[gBattlerAttacker].volatiles.multipleTurns)) CancelMultiTurnMoves(gBattlerAttacker, SKY_DROP_ATTACKCANCELER_CHECK); return; } @@ -1192,9 +1235,6 @@ static void Cmd_attackcanceler(void) { gBattleStruct->bouncedMoveIsUsed = TRUE; // Edge case for bouncing a powder move against a grass type pokemon. - - ClearDamageCalcResults(); - SetAtkCancelerForCalledMove(); gEffectBattler = gBattlerTarget; if (BlocksPrankster(gCurrentMove, gBattlerTarget, gBattlerAttacker, TRUE)) { @@ -1212,7 +1252,7 @@ static void Cmd_attackcanceler(void) { u32 battler = gBattlerTarget; - if (abilityDef == ABILITY_MAGIC_BOUNCE) + if (ctx.abilities[ctx.battlerDef] == ABILITY_MAGIC_BOUNCE) { battler = gBattlerTarget; gBattleStruct->bouncedMoveIsUsed = TRUE; @@ -1227,8 +1267,6 @@ static void Cmd_attackcanceler(void) if (gBattleStruct->bouncedMoveIsUsed) { - ClearDamageCalcResults(); - SetAtkCancelerForCalledMove(); // Edge case for bouncing a powder move against a grass type pokemon. BattleScriptCall(BattleScript_MagicBounce); gBattlerAbility = battler; return; @@ -1258,28 +1296,17 @@ static void Cmd_attackcanceler(void) } } - if (gSpecialStatuses[gBattlerTarget].lightningRodRedirected) + if (gSpecialStatuses[gBattlerTarget].abilityRedirected) { - gSpecialStatuses[gBattlerTarget].lightningRodRedirected = FALSE; - gLastUsedAbility = ABILITY_LIGHTNING_ROD; + gSpecialStatuses[gBattlerTarget].abilityRedirected = FALSE; BattleScriptCall(BattleScript_TookAttack); - RecordAbilityBattle(gBattlerTarget, gLastUsedAbility); - } - else if (gSpecialStatuses[gBattlerTarget].stormDrainRedirected) - { - gSpecialStatuses[gBattlerTarget].stormDrainRedirected = FALSE; - gLastUsedAbility = ABILITY_STORM_DRAIN; - BattleScriptCall(BattleScript_TookAttack); - RecordAbilityBattle(gBattlerTarget, gLastUsedAbility); } else if (IsBattlerProtected(gBattlerAttacker, gBattlerTarget, gCurrentMove) - && (effect != EFFECT_CURSE || IS_BATTLER_OF_TYPE(gBattlerAttacker, TYPE_GHOST)) - && (!gBattleMoveEffects[effect].twoTurnEffect || (gBattleMons[gBattlerAttacker].volatiles.multipleTurns)) - && effect != EFFECT_SUCKER_PUNCH - && effect != EFFECT_COUNTER - && effect != EFFECT_UPPER_HAND) + && (moveEffect != EFFECT_CURSE || IS_BATTLER_OF_TYPE(gBattlerAttacker, TYPE_GHOST)) + && (!gBattleMoveEffects[moveEffect].twoTurnEffect || (gBattleMons[gBattlerAttacker].volatiles.multipleTurns)) + && moveEffect != EFFECT_COUNTER) { - if (!CanBattlerAvoidContactEffects(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerAttacker), GetBattlerHoldEffect(gBattlerAttacker, TRUE), gCurrentMove)) + if (!CanBattlerAvoidContactEffects(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerAttacker), GetBattlerHoldEffect(gBattlerAttacker), gCurrentMove)) gProtectStructs[gBattlerAttacker].touchedProtectLike = TRUE; CancelMultiTurnMoves(gBattlerAttacker, SKY_DROP_ATTACKCANCELER_CHECK); gBattleStruct->moveResultFlags[gBattlerTarget] |= MOVE_RESULT_MISSED; @@ -1295,7 +1322,8 @@ static void Cmd_attackcanceler(void) gBattleCommunication[MISS_TYPE] = B_MSG_PROTECTED; gBattlescriptCurrInstr = cmd->nextInstr; } - else if (gProtectStructs[gBattlerTarget].beakBlastCharge && !CanBattlerAvoidContactEffects(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerAttacker), GetBattlerHoldEffect(gBattlerAttacker, TRUE), gCurrentMove)) + else if (IsBattlerUsingBeakBlast(gBattlerTarget) + && !CanBattlerAvoidContactEffects(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerAttacker), GetBattlerHoldEffect(gBattlerAttacker), gCurrentMove)) { gProtectStructs[gBattlerAttacker].touchedProtectLike = TRUE; gBattlescriptCurrInstr = cmd->nextInstr; @@ -1317,8 +1345,6 @@ static void JumpIfMoveFailed(u32 adder, u32 move, u32 moveType, const u8 *failIn } else { - TrySetDestinyBondToHappen(); - if (CanAbilityAbsorbMove(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerTarget), @@ -1361,18 +1387,34 @@ static void AccuracyCheck(bool32 recalcDragonDarts, const u8 *nextInstr, const u if (move == ACC_CURR_MOVE) move = gCurrentMove; - enum BattleMoveEffects effect = GetMoveEffect(move); - u32 abilityAtk = GetBattlerAbility(gBattlerAttacker); - enum ItemHoldEffect holdEffectAtk = GetBattlerHoldEffect(gBattlerAttacker, TRUE); - if (move == NO_ACC_CALC_CHECK_LOCK_ON) { if (gBattleMons[gBattlerTarget].volatiles.lockOn && gDisableStructs[gBattlerTarget].battlerWithSureHit == gBattlerAttacker) + { gBattlescriptCurrInstr = nextInstr; + } else if (IsSemiInvulnerable(gBattlerTarget, CHECK_ALL)) + { + if (gBattlerTarget != BATTLE_PARTNER(gBattlerAttacker)) + { + gBattleStruct->moveResultFlags[gBattlerTarget] |= MOVE_RESULT_MISSED; + gBattleStruct->missStringId[gBattlerTarget] = gBattleCommunication[MISS_TYPE] = B_MSG_AVOIDED_ATK; + } gBattlescriptCurrInstr = failInstr; - else if (!JumpIfMoveAffectedByProtect(gCurrentMove, gBattlerTarget, TRUE, failInstr)) + } + else if (IsBattlerProtected(gBattlerAttacker, gBattlerTarget, gCurrentMove)) + { + gBattleStruct->moveResultFlags[gBattlerTarget] |= MOVE_RESULT_MISSED; + gBattleStruct->missStringId[gBattlerTarget] = gBattleCommunication[MISS_TYPE] = B_MSG_PROTECTED; + gLastLandedMoves[gBattlerTarget] = 0; + gLastHitByType[gBattlerTarget] = 0; + gBattlescriptCurrInstr = failInstr; + } + else + { gBattlescriptCurrInstr = nextInstr; + } + if (GetActiveGimmick(gBattlerAttacker) == GIMMICK_DYNAMAX) { if (gProtectStructs[gBattlerTarget].protected == PROTECT_MAX_GUARD) @@ -1385,8 +1427,14 @@ static void AccuracyCheck(bool32 recalcDragonDarts, const u8 *nextInstr, const u GetBattleMoveType(gCurrentMove), RUN_SCRIPT); } + return; } - else if (gSpecialStatuses[gBattlerAttacker].parentalBondState == PARENTAL_BOND_2ND_HIT + + enum Ability abilityAtk = GetBattlerAbility(gBattlerAttacker); + enum HoldEffect holdEffectAtk = GetBattlerHoldEffect(gBattlerAttacker); + enum BattleMoveEffects effect = GetMoveEffect(move); + + if (gSpecialStatuses[gBattlerAttacker].parentalBondState == PARENTAL_BOND_2ND_HIT || (gSpecialStatuses[gBattlerAttacker].multiHitOn && (abilityAtk == ABILITY_SKILL_LINK || holdEffectAtk == HOLD_EFFECT_LOADED_DICE || !(effect == EFFECT_TRIPLE_KICK || effect == EFFECT_POPULATION_BOMB)))) @@ -1414,12 +1462,12 @@ static void AccuracyCheck(bool32 recalcDragonDarts, const u8 *nextInstr, const u continue; numTargets++; - u32 abilityDef = GetBattlerAbility(battlerDef); + enum Ability abilityDef = GetBattlerAbility(battlerDef); if (JumpIfMoveAffectedByProtect(move, battlerDef, FALSE, failInstr) || CanMoveSkipAccuracyCalc(gBattlerAttacker, battlerDef, abilityAtk, abilityDef, move, RUN_SCRIPT)) continue; - u32 holdEffectDef = GetBattlerHoldEffect(battlerDef, TRUE); + u32 holdEffectDef = GetBattlerHoldEffect(battlerDef); u32 accuracy = GetTotalAccuracy(gBattlerAttacker, battlerDef, move, @@ -1456,6 +1504,7 @@ static void AccuracyCheck(bool32 recalcDragonDarts, const u8 *nextInstr, const u ctx.battlerAtk = gBattlerAttacker; ctx.battlerDef = battlerDef; ctx.move = move; + ctx.chosenMove = gChosenMove; ctx.moveType = moveType; ctx.updateFlags = TRUE; ctx.abilityAtk = abilityAtk; @@ -1491,76 +1540,20 @@ static void Cmd_accuracycheck(void) AccuracyCheck(FALSE, cmd->nextInstr, cmd->failInstr, cmd->move); } -static void Cmd_attackstring(void) +static void Cmd_printattackstring(void) { CMD_ARGS(); if (gBattleControllerExecFlags) return; - if (!(gHitMarker & (HITMARKER_NO_ATTACKSTRING | HITMARKER_ATTACKSTRING_PRINTED))) - { - PrepareStringBattle(STRINGID_USEDMOVE, gBattlerAttacker); - gHitMarker |= HITMARKER_ATTACKSTRING_PRINTED; - } - gBattlescriptCurrInstr = cmd->nextInstr; + PrepareStringBattle(STRINGID_USEDMOVE, gBattlerAttacker); gBattleCommunication[MSG_DISPLAY] = 0; + gBattlescriptCurrInstr = cmd->nextInstr; } -static void Cmd_ppreduce(void) +static void Cmd_unused_0x3(void) { - CMD_ARGS(); - - s32 i, ppToDeduct = 1; - u32 moveTarget = GetBattlerMoveTargetType(gBattlerAttacker, gCurrentMove); - - if (gBattleControllerExecFlags) - return; - - if (gBattleMons[gBattlerAttacker].volatiles.multipleTurns) - gHitMarker |= HITMARKER_NO_PPDEDUCT; - - if (moveTarget == MOVE_TARGET_BOTH - || moveTarget == MOVE_TARGET_FOES_AND_ALLY - || moveTarget == MOVE_TARGET_ALL_BATTLERS - || MoveForcesPressure(gCurrentMove)) - { - for (i = 0; i < gBattlersCount; i++) - { - if (!IsBattlerAlly(i, gBattlerAttacker) && IsBattlerAlive(i)) - ppToDeduct += (GetBattlerAbility(i) == ABILITY_PRESSURE); - } - } - else if (moveTarget != MOVE_TARGET_OPPONENTS_FIELD) - { - if (gBattlerAttacker != gBattlerTarget && GetBattlerAbility(gBattlerTarget) == ABILITY_PRESSURE) - ppToDeduct++; - } - - if (!(gHitMarker & (HITMARKER_NO_PPDEDUCT | HITMARKER_NO_ATTACKSTRING)) && gBattleMons[gBattlerAttacker].pp[gCurrMovePos]) - { - gProtectStructs[gBattlerAttacker].notFirstStrike = TRUE; - - // For item Metronome, echoed voice - if (gCurrentMove != gLastResultingMoves[gBattlerAttacker] || WasUnableToUseMove(gBattlerAttacker)) - gBattleStruct->metronomeItemCounter[gBattlerAttacker] = 0; - - if (gBattleMons[gBattlerAttacker].pp[gCurrMovePos] > ppToDeduct) - gBattleMons[gBattlerAttacker].pp[gCurrMovePos] -= ppToDeduct; - else - gBattleMons[gBattlerAttacker].pp[gCurrMovePos] = 0; - - if (MOVE_IS_PERMANENT(gBattlerAttacker, gCurrMovePos)) - { - BtlController_EmitSetMonData(gBattlerAttacker, B_COMM_TO_CONTROLLER, REQUEST_PPMOVE1_BATTLE + gCurrMovePos, 0, - sizeof(gBattleMons[gBattlerAttacker].pp[gCurrMovePos]), - &gBattleMons[gBattlerAttacker].pp[gCurrMovePos]); - MarkBattlerForControllerExec(gBattlerAttacker); - } - } - - gHitMarker &= ~HITMARKER_NO_PPDEDUCT; - gBattlescriptCurrInstr = cmd->nextInstr; } // The chance is 1/N for each stage. @@ -1571,17 +1564,17 @@ static const u32 sGen2CriticalHitOdds[] = {17, 32, 64, 85, 128}; // X/256 static inline u32 GetCriticalHitOdds(u32 critChance) { - if (GetGenConfig(GEN_CONFIG_CRIT_CHANCE) >= GEN_7) + if (GetConfig(CONFIG_CRIT_CHANCE) >= GEN_7) return sGen7CriticalHitOdds[critChance]; - if (GetGenConfig(GEN_CONFIG_CRIT_CHANCE) == GEN_6) + if (GetConfig(CONFIG_CRIT_CHANCE) == GEN_6) return sGen6CriticalHitOdds[critChance]; - if (GetGenConfig(GEN_CONFIG_CRIT_CHANCE) == GEN_2) + if (GetConfig(CONFIG_CRIT_CHANCE) == GEN_2) return sGen2CriticalHitOdds[critChance]; return sCriticalHitOdds[critChance]; } -static inline u32 IsBattlerLeekAffected(u32 battler, enum ItemHoldEffect holdEffect) +static inline u32 IsBattlerLeekAffected(u32 battler, enum HoldEffect holdEffect) { if (holdEffect == HOLD_EFFECT_LEEK) { @@ -1591,7 +1584,7 @@ static inline u32 IsBattlerLeekAffected(u32 battler, enum ItemHoldEffect holdEff return FALSE; } -static inline u32 GetHoldEffectCritChanceIncrease(u32 battler, enum ItemHoldEffect holdEffect) +static inline u32 GetHoldEffectCritChanceIncrease(u32 battler, enum HoldEffect holdEffect) { u32 critStageIncrease = 0; @@ -1616,11 +1609,11 @@ static inline u32 GetHoldEffectCritChanceIncrease(u32 battler, enum ItemHoldEffe return critStageIncrease; } -s32 CalcCritChanceStage(u32 battlerAtk, u32 battlerDef, u32 move, bool32 recordAbility, u32 abilityAtk, u32 abilityDef, enum ItemHoldEffect holdEffectAtk) +s32 CalcCritChanceStage(u32 battlerAtk, u32 battlerDef, u32 move, bool32 recordAbility, enum Ability abilityAtk, enum Ability abilityDef, enum HoldEffect holdEffectAtk) { s32 critChance = 0; - if (gSideStatuses[battlerDef] & SIDE_STATUS_LUCKY_CHANT) + if (gSideStatuses[GetBattlerSide(battlerDef)] & SIDE_STATUS_LUCKY_CHANT) { critChance = CRITICAL_HIT_BLOCKED; } @@ -1638,7 +1631,7 @@ s32 CalcCritChanceStage(u32 battlerAtk, u32 battlerDef, u32 move, bool32 recordA + GetHoldEffectCritChanceIncrease(battlerAtk, holdEffectAtk) + ((B_AFFECTION_MECHANICS == TRUE && GetBattlerAffectionHearts(battlerAtk) == AFFECTION_FIVE_HEARTS) ? 2 : 0) + (abilityAtk == ABILITY_SUPER_LUCK ? 1 : 0) - + gBattleStruct->bonusCritStages[gBattlerAttacker]; + + gBattleMons[battlerAtk].volatiles.bonusCritStages; if (critChance >= ARRAY_COUNT(sCriticalHitOdds)) critChance = ARRAY_COUNT(sCriticalHitOdds) - 1; @@ -1665,11 +1658,11 @@ s32 CalcCritChanceStage(u32 battlerAtk, u32 battlerDef, u32 move, bool32 recordA // Threshold = Base Speed / 2 // High crit move = 8 * (Base Speed / 2) // Focus Energy = 4 * (Base Speed / 2) -s32 CalcCritChanceStageGen1(u32 battlerAtk, u32 battlerDef, u32 move, bool32 recordAbility, u32 abilityAtk, u32 abilityDef, enum ItemHoldEffect holdEffectAtk) +s32 CalcCritChanceStageGen1(u32 battlerAtk, u32 battlerDef, u32 move, bool32 recordAbility, enum Ability abilityAtk, enum Ability abilityDef, enum HoldEffect holdEffectAtk) { s32 critChance = 0; s32 moveCritStage = GetMoveCriticalHitStage(gCurrentMove); - s32 bonusCritStage = gBattleStruct->bonusCritStages[battlerAtk]; // G-Max Chi Strike + s32 bonusCritStage = gBattleMons[battlerAtk].volatiles.bonusCritStages; // G-Max Chi Strike u32 holdEffectCritStage = GetHoldEffectCritChanceIncrease(battlerAtk, holdEffectAtk); u16 baseSpeed = GetSpeciesBaseSpeed(gBattleMons[battlerAtk].species); @@ -1731,10 +1724,9 @@ static void Cmd_critcalc(void) u32 partySlot = gBattlerPartyIndexes[gBattlerAttacker], moveTarget = GetBattlerMoveTargetType(gBattlerAttacker, gCurrentMove), - abilityAtk = GetBattlerAbility(gBattlerAttacker), battlerDef; bool32 calcSpreadMoveDamage = IsSpreadMove(moveTarget) && !IsBattleMoveStatus(gCurrentMove); - enum ItemHoldEffect holdEffectAtk = GetBattlerHoldEffect(gBattlerAttacker, TRUE); + enum HoldEffect holdEffectAtk = GetBattlerHoldEffect(gBattlerAttacker); gPotentialItemEffectBattler = gBattlerAttacker; for (battlerDef = 0; battlerDef < gBattlersCount; battlerDef++) @@ -1750,9 +1742,10 @@ static void Cmd_critcalc(void) || gBattleStruct->moveResultFlags[battlerDef] & MOVE_RESULT_NO_EFFECT) continue; - u32 abilityDef = GetBattlerAbility(battlerDef); + enum Ability abilityDef = GetBattlerAbility(battlerDef); + enum Ability abilityAtk = GetBattlerAbility(gBattlerAttacker); - if (GetGenConfig(GEN_CONFIG_CRIT_CHANCE) == GEN_1) + if (GetConfig(CONFIG_CRIT_CHANCE) == GEN_1) gBattleStruct->critChance[battlerDef] = CalcCritChanceStageGen1(gBattlerAttacker, battlerDef, gCurrentMove, TRUE, abilityAtk, abilityDef, holdEffectAtk); else gBattleStruct->critChance[battlerDef] = CalcCritChanceStage(gBattlerAttacker, battlerDef, gCurrentMove, TRUE, abilityAtk, abilityDef, holdEffectAtk); @@ -1765,9 +1758,9 @@ static void Cmd_critcalc(void) gSpecialStatuses[battlerDef].criticalHit = TRUE; else { - if (GetGenConfig(GEN_CONFIG_CRIT_CHANCE) == GEN_1) + if (GetConfig(CONFIG_CRIT_CHANCE) == GEN_1) gSpecialStatuses[battlerDef].criticalHit = RandomChance(RNG_CRITICAL_HIT, gBattleStruct->critChance[battlerDef], 256); - else if (GetGenConfig(GEN_CONFIG_CRIT_CHANCE) == GEN_2) + else if (GetConfig(CONFIG_CRIT_CHANCE) == GEN_2) gSpecialStatuses[battlerDef].criticalHit = RandomChance(RNG_CRITICAL_HIT, GetCriticalHitOdds(gBattleStruct->critChance[battlerDef]), 256); else gSpecialStatuses[battlerDef].criticalHit = RandomChance(RNG_CRITICAL_HIT, 1, GetCriticalHitOdds(gBattleStruct->critChance[battlerDef])); @@ -1812,6 +1805,7 @@ static void Cmd_damagecalc(void) struct DamageContext ctx = {0}; ctx.battlerAtk = gBattlerAttacker; ctx.move = gCurrentMove; + ctx.chosenMove = gChosenMove; ctx.moveType = GetBattleMoveType(gCurrentMove); ctx.randomFactor = TRUE; ctx.updateFlags = TRUE; @@ -1849,12 +1843,13 @@ static void Cmd_typecalc(void) ctx.battlerAtk = gBattlerAttacker; ctx.battlerDef = gBattlerTarget; ctx.move = gCurrentMove; + ctx.chosenMove = gChosenMove; ctx.moveType = GetBattleMoveType(gCurrentMove); ctx.updateFlags = TRUE; ctx.abilityAtk = GetBattlerAbility(gBattlerAttacker); ctx.abilityDef = GetBattlerAbility(gBattlerTarget); - ctx.holdEffectAtk = GetBattlerHoldEffect(gBattlerAttacker, TRUE); - ctx.holdEffectDef = GetBattlerHoldEffect(gBattlerTarget, TRUE); + ctx.holdEffectAtk = GetBattlerHoldEffect(gBattlerAttacker); + ctx.holdEffectDef = GetBattlerHoldEffect(gBattlerTarget); CalcTypeEffectivenessMultiplier(&ctx); } @@ -1866,7 +1861,7 @@ static void Cmd_adjustdamage(void) { CMD_ARGS(); - enum ItemHoldEffect holdEffect; + enum HoldEffect holdEffect; u8 param; u32 battlerDef; u32 rand = Random() % 100; @@ -1912,7 +1907,7 @@ static void Cmd_adjustdamage(void) if (gBattleMons[battlerDef].hp > gBattleStruct->moveDamage[battlerDef]) continue; - holdEffect = GetBattlerHoldEffect(battlerDef, TRUE); + holdEffect = GetBattlerHoldEffect(battlerDef); param = GetBattlerHoldEffectParam(battlerDef); affectionScore = GetBattlerAffectionHearts(battlerDef); @@ -2014,7 +2009,7 @@ static void Cmd_multihitresultmessage(void) static inline bool32 DoesBattlerNegateDamage(u32 battler) { u32 species = gBattleMons[battler].species; - u32 ability = GetBattlerAbility(battler); + enum Ability ability = GetBattlerAbility(battler); if (gBattleMons[battler].volatiles.transformed) return FALSE; @@ -2094,6 +2089,11 @@ static inline bool32 TryTeraShellDistortTypeMatchups(u32 battlerDef) // It doesn't have any impact on gameplay and is only a visual thing which can be adjusted later. static inline bool32 TryActivateWeaknessBerry(u32 battlerDef) { + if (DoesDisguiseBlockMove(battlerDef, gCurrentMove)) + { + gSpecialStatuses[battlerDef].berryReduced = FALSE; + return FALSE; + } if (gSpecialStatuses[battlerDef].berryReduced && gBattleMons[battlerDef].item != ITEM_NONE) { gBattleScripting.battler = battlerDef; @@ -2260,8 +2260,7 @@ static void Cmd_waitanimation(void) static void DoublesHPBarReduction(void) { - if (gBattleStruct->doneDoublesSpreadHit - || gHitMarker & (HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_HP_UPDATE)) + if (gBattleStruct->doneDoublesSpreadHit) return; for (u32 battlerDef = 0; battlerDef < gBattlersCount; battlerDef++) @@ -2273,12 +2272,10 @@ static void DoublesHPBarReduction(void) || DoesDisguiseBlockMove(battlerDef, gCurrentMove)) continue; - s32 currDmg = gBattleStruct->moveDamage[battlerDef]; - s32 healthValue = min(currDmg, 10000); // Max damage (10000) not present in R/S, ensures that huge damage values don't change sign - BtlController_EmitHealthBarUpdate(battlerDef, B_COMM_TO_CONTROLLER, healthValue); + s32 dmgUpdate = min(gBattleStruct->moveDamage[battlerDef], 10000); + BtlController_EmitHealthBarUpdate(battlerDef, B_COMM_TO_CONTROLLER, dmgUpdate); MarkBattlerForControllerExec(battlerDef); - - if (IsOnPlayerSide(battlerDef) && currDmg > 0) + if (IsOnPlayerSide(battlerDef) && dmgUpdate > 0) gBattleResults.playerMonWasDamaged = TRUE; } @@ -2287,185 +2284,201 @@ static void DoublesHPBarReduction(void) static void Cmd_healthbarupdate(void) { - CMD_ARGS(u8 battler); + CMD_ARGS(u8 battler, u8 updateState); u32 battler = GetBattlerForBattleScript(cmd->battler); if (gBattleControllerExecFlags) return; - if (!(gBattleStruct->moveResultFlags[battler] & MOVE_RESULT_NO_EFFECT) || (gHitMarker & HITMARKER_PASSIVE_HP_UPDATE)) + switch (cmd->updateState) { - if (DoesSubstituteBlockMove(gBattlerAttacker, battler, gCurrentMove) && gDisableStructs[battler].substituteHP && !(gHitMarker & HITMARKER_IGNORE_SUBSTITUTE)) + case PASSIVE_HP_UPDATE: + BtlController_EmitHealthBarUpdate(battler, B_COMM_TO_CONTROLLER, min(gBattleStruct->passiveHpUpdate[battler], 10000)); + MarkBattlerForControllerExec(battler); + break; + case MOVE_DAMAGE_HP_UPDATE: + if (IsDoubleSpreadMove()) + { + DoublesHPBarReduction(); + if (DoesSubstituteBlockMove(gBattlerAttacker, battler, gCurrentMove)) + PrepareStringBattle(STRINGID_SUBSTITUTEDAMAGED, battler); + } + else if (DoesSubstituteBlockMove(gBattlerAttacker, battler, gCurrentMove)) { PrepareStringBattle(STRINGID_SUBSTITUTEDAMAGED, battler); - if (IsDoubleSpreadMove()) - DoublesHPBarReduction(); } - else if (!DoesDisguiseBlockMove(battler, gCurrentMove)) + else if (!(gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_NO_EFFECT) + && !DoesDisguiseBlockMove(battler, gCurrentMove)) { - if (IsDoubleSpreadMove()) - { - DoublesHPBarReduction(); - } - else - { - s16 healthValue = min(gBattleStruct->moveDamage[battler], 10000); // Max damage (10000) not present in R/S, ensures that huge damage values don't change sign - - BtlController_EmitHealthBarUpdate(battler, B_COMM_TO_CONTROLLER, healthValue); - MarkBattlerForControllerExec(battler); - - if (IsOnPlayerSide(battler) && gBattleStruct->moveDamage[battler] > 0) - gBattleResults.playerMonWasDamaged = TRUE; - } + s32 damage = min(gBattleStruct->moveDamage[battler], 10000); + BtlController_EmitHealthBarUpdate(battler, B_COMM_TO_CONTROLLER, damage); + MarkBattlerForControllerExec(battler); + if (IsOnPlayerSide(battler) && damage > 0) + gBattleResults.playerMonWasDamaged = TRUE; } - } - else if (IsDoubleSpreadMove()) - { - DoublesHPBarReduction(); + break; } gBattlescriptCurrInstr = cmd->nextInstr; } -// Update the active battler's HP and various HP trackers (Substitute, Bide, etc.) +static void PassiveDataHpUpdate(u32 battler, const u8 *nextInstr) +{ + if (gBattleStruct->passiveHpUpdate[battler] < 0) + { + // Negative damage is HP gain + gBattleMons[battler].hp += -gBattleStruct->passiveHpUpdate[battler]; + if (gBattleMons[battler].hp > gBattleMons[battler].maxHP) + gBattleMons[battler].hp = gBattleMons[battler].maxHP; + } + else + { + if (gBattleMons[battler].hp > gBattleStruct->passiveHpUpdate[battler]) + gBattleMons[battler].hp -= gBattleStruct->passiveHpUpdate[battler]; + else + gBattleMons[battler].hp = 0; + // Since this is reset for the next turn, it should be fine to set it here. + gProtectStructs[battler].assuranceDoubled = TRUE; + } + + // Send updated HP + BtlController_EmitSetMonData( + battler, + B_COMM_TO_CONTROLLER, + REQUEST_HP_BATTLE, + 0, + sizeof(gBattleMons[battler].hp), &gBattleMons[battler].hp); + MarkBattlerForControllerExec(battler); + + gBattleStruct->passiveHpUpdate[battler] = 0; + gBattlescriptCurrInstr = nextInstr; +} + +static void MoveDamageDataHpUpdate(u32 battler, u32 scriptBattler, const u8 *nextInstr) +{ + if (gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_NO_EFFECT) + { + gBattlescriptCurrInstr = nextInstr; + return; + } + else if (DoesSubstituteBlockMove(gBattlerAttacker, battler, gCurrentMove) && gDisableStructs[battler].substituteHP) + { + if (gDisableStructs[battler].substituteHP >= gBattleStruct->moveDamage[battler]) + { + TestRunner_Battle_RecordSubHit(battler, gBattleStruct->moveDamage[battler], FALSE); + gDisableStructs[battler].substituteHP -= gBattleStruct->moveDamage[battler]; + } + else + { + TestRunner_Battle_RecordSubHit(battler, gDisableStructs[battler].substituteHP, TRUE); + gBattleStruct->moveDamage[battler] = gDisableStructs[battler].substituteHP; + gDisableStructs[battler].substituteHP = 0; + } + // check substitute fading + if (gDisableStructs[battler].substituteHP == 0) + { + gBattlescriptCurrInstr = nextInstr; + BattleScriptCall(BattleScript_SubstituteFade); + } + else + { + gBattlescriptCurrInstr = nextInstr; + } + return; + } + else if (DoesDisguiseBlockMove(battler, gCurrentMove)) + { + // TODO: Convert this to a proper FORM_CHANGE type. + gBattleScripting.battler = battler; + gBattleStruct->moveDamage[battler] = 0; + gBattleStruct->moveResultFlags[battler] &= ~(MOVE_RESULT_NOT_VERY_EFFECTIVE | MOVE_RESULT_SUPER_EFFECTIVE); + if (GetBattlerPartyState(battler)->changedSpecies == SPECIES_NONE) + GetBattlerPartyState(battler)->changedSpecies = gBattleMons[battler].species; + if (gBattleMons[battler].species == SPECIES_MIMIKYU_TOTEM_DISGUISED) + gBattleMons[battler].species = SPECIES_MIMIKYU_BUSTED_TOTEM; + else + gBattleMons[battler].species = SPECIES_MIMIKYU_BUSTED; + if (GetConfig(CONFIG_DISGUISE_HP_LOSS) >= GEN_8) + SetPassiveDamageAmount(battler, GetNonDynamaxMaxHP(battler) / 8); + BattleScriptPush(nextInstr); + gBattlescriptCurrInstr = BattleScript_TargetFormChange; + } + else + { + if (gBattleStruct->moveDamage[battler] < 0) + { + // Negative damage is HP gain + gBattleMons[battler].hp += -gBattleStruct->moveDamage[battler]; + if (gBattleMons[battler].hp > gBattleMons[battler].maxHP) + gBattleMons[battler].hp = gBattleMons[battler].maxHP; + } + else + { + gBideDmg[battler] += gBattleStruct->moveDamage[battler]; + if (scriptBattler == BS_TARGET) + gBideTarget[battler] = gBattlerAttacker; + else + gBideTarget[battler] = gBattlerTarget; + + // Deal damage to the battler + if (gBattleMons[battler].hp > gBattleStruct->moveDamage[battler]) + { + gBattleMons[battler].hp -= gBattleStruct->moveDamage[battler]; + } + else + { + gBattleStruct->moveDamage[battler] = gBattleMons[battler].hp; + gBattleMons[battler].hp = 0; + } + gProtectStructs[battler].assuranceDoubled = TRUE; + gProtectStructs[battler].revengeDoubled |= 1u << gBattlerAttacker; + + } + // Send updated HP + BtlController_EmitSetMonData(battler, B_COMM_TO_CONTROLLER, REQUEST_HP_BATTLE, 0, sizeof(gBattleMons[battler].hp), &gBattleMons[battler].hp); + MarkBattlerForControllerExec(battler); + gBattlescriptCurrInstr = nextInstr; + } + + // Note: While physicalDmg/specialDmg below are only distinguished between for Counter/Mirror Coat, + // they are used in combination as general damage trackers for other purposes. + if (IsBattleMovePhysical(gCurrentMove)) + { + gProtectStructs[battler].physicalDmg = gBattleStruct->moveDamage[battler] + 1; + gSpecialStatuses[battler].physicalDmg = gBattleStruct->moveDamage[battler] + 1; + gProtectStructs[battler].physicalBattlerId = gBattlerAttacker; + } + else // Special move + { + gProtectStructs[battler].specialDmg = gBattleStruct->moveDamage[battler] + 1; + gSpecialStatuses[battler].specialDmg = gBattleStruct->moveDamage[battler] + 1; + gProtectStructs[battler].specialBattlerId = gBattlerAttacker; + } + + if (IsBattlerTurnDamaged(gBattlerTarget) && GetMoveCategory(gCurrentMove) != DAMAGE_CATEGORY_STATUS) + GetBattlerPartyState(battler)->timesGotHit++; +} + static void Cmd_datahpupdate(void) { - CMD_ARGS(u8 battler); - bool32 isPassiveHpUpdate = gHitMarker & HITMARKER_PASSIVE_HP_UPDATE; - bool32 disguiseActivates = FALSE; + CMD_ARGS(u8 battler, u8 updateState); + u32 battler = GetBattlerForBattleScript(cmd->battler); if (gBattleControllerExecFlags) return; - u32 battler = GetBattlerForBattleScript(cmd->battler); - - if (!(gBattleStruct->moveResultFlags[battler] & MOVE_RESULT_NO_EFFECT) || (gHitMarker & HITMARKER_PASSIVE_HP_UPDATE)) + switch (cmd->updateState) { - if (DoesSubstituteBlockMove(gBattlerAttacker, battler, gCurrentMove) && gDisableStructs[battler].substituteHP && !(gHitMarker & HITMARKER_IGNORE_SUBSTITUTE)) - { - if (gDisableStructs[battler].substituteHP >= gBattleStruct->moveDamage[battler]) - { - gDisableStructs[battler].substituteHP -= gBattleStruct->moveDamage[battler]; - } - else - { - gBattleStruct->moveDamage[battler] = gDisableStructs[battler].substituteHP; - gDisableStructs[battler].substituteHP = 0; - } - // check substitute fading - if (gDisableStructs[battler].substituteHP == 0) - { - gBattlescriptCurrInstr = cmd->nextInstr; - BattleScriptCall(BattleScript_SubstituteFade); - return; - } - } - else if (DoesDisguiseBlockMove(battler, gCurrentMove)) - { - // TODO: Convert this to a proper FORM_CHANGE type. - gBattleScripting.battler = battler; - if (GetBattlerPartyState(battler)->changedSpecies == SPECIES_NONE) - GetBattlerPartyState(battler)->changedSpecies = gBattleMons[battler].species; - if (gBattleMons[battler].species == SPECIES_MIMIKYU_TOTEM_DISGUISED) - gBattleMons[battler].species = SPECIES_MIMIKYU_BUSTED_TOTEM; - else - gBattleMons[battler].species = SPECIES_MIMIKYU_BUSTED; - if (GetGenConfig(GEN_CONFIG_DISGUISE_HP_LOSS) >= GEN_8) - gBattleStruct->moveDamage[battler] = GetNonDynamaxMaxHP(battler) / 8; - BattleScriptPush(cmd->nextInstr); - gBattlescriptCurrInstr = BattleScript_TargetFormChange; - disguiseActivates = TRUE; - } - else - { - gHitMarker &= ~HITMARKER_IGNORE_SUBSTITUTE; - if (gBattleStruct->moveDamage[battler] < 0) - { - // Negative damage is HP gain - gBattleMons[battler].hp += -gBattleStruct->moveDamage[battler]; - if (gBattleMons[battler].hp > gBattleMons[battler].maxHP) - gBattleMons[battler].hp = gBattleMons[battler].maxHP; - } - else - { - if (gHitMarker & HITMARKER_IGNORE_BIDE) - { - gHitMarker &= ~HITMARKER_IGNORE_BIDE; - } - else - { - gBideDmg[battler] += gBattleStruct->moveDamage[battler]; - if (cmd->battler == BS_TARGET) - gBideTarget[battler] = gBattlerAttacker; - else - gBideTarget[battler] = gBattlerTarget; - } - - // Deal damage to the battler - if (gBattleMons[battler].hp > gBattleStruct->moveDamage[battler]) - { - gBattleMons[battler].hp -= gBattleStruct->moveDamage[battler]; - } - else - { - gBattleStruct->moveDamage[battler] = gBattleMons[battler].hp; - gBattleMons[battler].hp = 0; - } - - enum BattleMoveEffects effect = GetMoveEffect(gCurrentMove); - - // Note: While physicalDmg/specialDmg below are only distinguished between for Counter/Mirror Coat, they are - // used in combination as general damage trackers for other purposes. specialDmg is additionally used - // to help determine if a fire move should defrost the target. - if (IsBattleMovePhysical(gCurrentMove) && !(gHitMarker & HITMARKER_PASSIVE_HP_UPDATE) && effect != EFFECT_PAIN_SPLIT) - { - gProtectStructs[battler].physicalDmg = gBattleStruct->moveDamage[battler]; - gSpecialStatuses[battler].physicalDmg = gBattleStruct->moveDamage[battler]; - if (cmd->battler == BS_TARGET) - gProtectStructs[battler].physicalBattlerId = gBattlerAttacker; - else - gProtectStructs[battler].physicalBattlerId = gBattlerTarget; - gProtectStructs[battler].assuranceDoubled = TRUE; - } - else if (!IsBattleMovePhysical(gCurrentMove) && !(gHitMarker & HITMARKER_PASSIVE_HP_UPDATE) && effect != EFFECT_PAIN_SPLIT) - { - // Record special damage/attacker for Mirror Coat - gProtectStructs[battler].specialDmg = gBattleStruct->moveDamage[battler]; - gSpecialStatuses[battler].specialDmg = gBattleStruct->moveDamage[battler]; - if (cmd->battler == BS_TARGET) - gProtectStructs[battler].specialBattlerId = gBattlerAttacker; - else - gProtectStructs[battler].specialBattlerId = gBattlerTarget; - gProtectStructs[battler].assuranceDoubled = TRUE; - } - } - gHitMarker &= ~HITMARKER_PASSIVE_HP_UPDATE; - // Send updated HP - BtlController_EmitSetMonData(battler, B_COMM_TO_CONTROLLER, REQUEST_HP_BATTLE, 0, sizeof(gBattleMons[battler].hp), &gBattleMons[battler].hp); - MarkBattlerForControllerExec(battler); - } - - if (gBattlerAttacker != gBattlerTarget - && !isPassiveHpUpdate - && GetMoveCategory(gCurrentMove) != DAMAGE_CATEGORY_STATUS - && IsBattlerTurnDamaged(gBattlerTarget)) - GetBattlerPartyState(gBattlerTarget)->timesGotHit++; - - if (GetMoveEffect(gCurrentMove) == EFFECT_KNOCK_OFF - && !isPassiveHpUpdate - && IsBattlerTurnDamaged(gBattlerTarget) - && gBattleMons[gBattlerTarget].item != ITEM_NONE - && !DoesSubstituteBlockMove(gBattlerAttacker, battler, gCurrentMove) - && CanBattlerGetOrLoseItem(gBattlerTarget, gBattleMons[gBattlerTarget].item) - && !NoAliveMonsForEitherParty()) - gBattleStruct->battlerState[gBattlerTarget].itemCanBeKnockedOff = TRUE; - - if (disguiseActivates) - return; + case PASSIVE_HP_UPDATE: + PassiveDataHpUpdate(battler, cmd->nextInstr); + break; + case MOVE_DAMAGE_HP_UPDATE: + MoveDamageDataHpUpdate(battler, cmd->battler, cmd->nextInstr); + break; } + if (gBattleMons[battler].hp > gBattleMons[battler].maxHP / 2) + gBattleStruct->battlerState[battler].wasAboveHalfHp = TRUE; - TryRestoreDamageAfterCheekPouch(battler); - gBattlescriptCurrInstr = cmd->nextInstr; } static void Cmd_critmessage(void) @@ -2849,7 +2862,7 @@ void StealTargetItem(u8 battlerStealer, u8 itemBattler) gLastUsedItem = gBattleMons[itemBattler].item; gBattleMons[itemBattler].item = ITEM_NONE; - if (GetGenConfig(GEN_STEAL_WILD_ITEMS) >= GEN_9 + if (GetConfig(CONFIG_STEAL_WILD_ITEMS) >= GEN_9 && !(gBattleTypeFlags & (BATTLE_TYPE_TRAINER | BATTLE_TYPE_PALACE)) && GetMoveEffect(gCurrentMove) == EFFECT_STEAL_ITEM && battlerStealer == gBattlerAttacker) // ensure that Pickpocket isn't activating this @@ -2884,10 +2897,10 @@ static inline bool32 TrySetReflect(u32 battler) if (!(gSideStatuses[side] & SIDE_STATUS_REFLECT)) { gSideStatuses[side] |= SIDE_STATUS_REFLECT; - if (GetBattlerHoldEffect(battler, TRUE) == HOLD_EFFECT_LIGHT_CLAY) - gSideTimers[side].reflectTimer = gBattleTurnCounter + 8; + if (GetBattlerHoldEffect(battler) == HOLD_EFFECT_LIGHT_CLAY) + gSideTimers[side].reflectTimer = 8; else - gSideTimers[side].reflectTimer = gBattleTurnCounter + 5; + gSideTimers[side].reflectTimer = 5; if (IsDoubleBattle() && CountAliveMonsInBattle(BATTLE_ALIVE_SIDE, battler) == 2) gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SET_REFLECT_DOUBLE; @@ -2905,10 +2918,10 @@ static inline bool32 TrySetLightScreen(u32 battler) if (!(gSideStatuses[side] & SIDE_STATUS_LIGHTSCREEN)) { gSideStatuses[side] |= SIDE_STATUS_LIGHTSCREEN; - if (GetBattlerHoldEffect(battler, TRUE) == HOLD_EFFECT_LIGHT_CLAY) - gSideTimers[side].lightscreenTimer = gBattleTurnCounter + 8; + if (GetBattlerHoldEffect(battler) == HOLD_EFFECT_LIGHT_CLAY) + gSideTimers[side].lightscreenTimer = 8; else - gSideTimers[side].lightscreenTimer = gBattleTurnCounter + 5; + gSideTimers[side].lightscreenTimer = 5; if (IsDoubleBattle() && CountAliveMonsInBattle(BATTLE_ALIVE_SIDE, battler) == 2) gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SET_LIGHTSCREEN_DOUBLE; @@ -2920,7 +2933,7 @@ static inline bool32 TrySetLightScreen(u32 battler) return FALSE; } -static void SetNonVolatileStatus(u32 effectBattler, enum MoveEffect effect, enum StatusTrigger trigger) +static void SetNonVolatileStatus(u32 effectBattler, enum MoveEffect effect, const u8 *battleScript, enum StatusTrigger trigger) { gEffectBattler = effectBattler; @@ -2933,7 +2946,7 @@ static void SetNonVolatileStatus(u32 effectBattler, enum MoveEffect effect, enum gBattlescriptCurrInstr = cancelMultiTurnMovesResult; } - BattleScriptPush(gBattlescriptCurrInstr + 1); + BattleScriptPush(battleScript); switch (effect) { @@ -2995,9 +3008,11 @@ static void SetNonVolatileStatus(u32 effectBattler, enum MoveEffect effect, enum } // To avoid confusion the arguments are naned battler/effectBattler since they can be different from gBattlerAttacker/gBattlerTarget -void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certain) +void SetMoveEffect(u32 battler, u32 effectBattler, enum MoveEffect moveEffect, const u8 *battleScript, enum SetMoveEffectFlags effectFlags) { s32 i; + bool32 primary = effectFlags & EFFECT_PRIMARY; + bool32 certain = effectFlags & EFFECT_CERTAIN; bool32 affectsUser = (battler == effectBattler); bool32 mirrorArmorReflected = (GetBattlerAbility(gBattlerTarget) == ABILITY_MIRROR_ARMOR); union StatChangeFlags flags = {0}; @@ -3005,48 +3020,49 @@ void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certai bool32 activateAfterFaint = FALSE; // NULL move effect - if (gBattleScripting.moveEffect == MOVE_EFFECT_NONE) + if (moveEffect == MOVE_EFFECT_NONE) return; if (gSpecialStatuses[gBattlerAttacker].parentalBondState == PARENTAL_BOND_1ST_HIT && IsBattlerAlive(gBattlerTarget) - && IsFinalStrikeEffect(gBattleScripting.moveEffect)) + && IsFinalStrikeEffect(moveEffect)) { - gBattlescriptCurrInstr++; + gBattlescriptCurrInstr = battleScript; return; } - switch (gBattleScripting.moveEffect) // Set move effects which happen later on + switch (moveEffect) // Set move effects which happen later on { case MOVE_EFFECT_STEALTH_ROCK: case MOVE_EFFECT_PAYDAY: case MOVE_EFFECT_BUG_BITE: activateAfterFaint = TRUE; break; + default: + break; } gBattleScripting.battler = battler; gEffectBattler = effectBattler; battlerAbility = GetBattlerAbility(gEffectBattler); - if (!primary && !affectsUser - && !(gHitMarker & HITMARKER_STATUS_ABILITY_EFFECT) - && IsMoveEffectBlockedByTarget(battlerAbility)) - gBattleScripting.moveEffect = MOVE_EFFECT_NONE; - else if (!(gHitMarker & HITMARKER_STATUS_ABILITY_EFFECT) + if (!primary && !affectsUser && IsMoveEffectBlockedByTarget(battlerAbility)) + moveEffect = MOVE_EFFECT_NONE; + else if (!primary && TestIfSheerForceAffected(gBattlerAttacker, gCurrentMove) - && !(GetMoveEffect(gCurrentMove) == EFFECT_ORDER_UP && gBattleStruct->battlerState[gBattlerAttacker].commanderSpecies != SPECIES_NONE) - && !primary) - gBattleScripting.moveEffect = MOVE_EFFECT_NONE; + && !(GetMoveEffect(gCurrentMove) == EFFECT_ORDER_UP && gBattleStruct->battlerState[gBattlerAttacker].commanderSpecies != SPECIES_NONE)) + moveEffect = MOVE_EFFECT_NONE; else if (!IsBattlerAlive(gEffectBattler) && !activateAfterFaint) - gBattleScripting.moveEffect = MOVE_EFFECT_NONE; + moveEffect = MOVE_EFFECT_NONE; else if (DoesSubstituteBlockMove(gBattlerAttacker, gEffectBattler, gCurrentMove) && !affectsUser) - gBattleScripting.moveEffect = MOVE_EFFECT_NONE; + moveEffect = MOVE_EFFECT_NONE; - switch (gBattleScripting.moveEffect) + gBattleScripting.moveEffect = moveEffect; // ChangeStatBuffs still needs the global moveEffect + + switch (moveEffect) { case MOVE_EFFECT_NONE: - gBattlescriptCurrInstr++; + gBattlescriptCurrInstr = battleScript; break; case MOVE_EFFECT_SLEEP: case MOVE_EFFECT_POISON: @@ -3055,23 +3071,23 @@ void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certai case MOVE_EFFECT_PARALYSIS: case MOVE_EFFECT_TOXIC: case MOVE_EFFECT_FROSTBITE: - if (gSideStatuses[GetBattlerSide(gEffectBattler)] & SIDE_STATUS_SAFEGUARD && !(gHitMarker & HITMARKER_STATUS_ABILITY_EFFECT) && !primary) - gBattlescriptCurrInstr++; + if (gSideStatuses[GetBattlerSide(gEffectBattler)] & SIDE_STATUS_SAFEGUARD && !primary) + gBattlescriptCurrInstr = battleScript; else if (CanSetNonVolatileStatus( gBattlerAttacker, gEffectBattler, GetBattlerAbility(gBattlerAttacker), battlerAbility, - gBattleScripting.moveEffect, + moveEffect, CHECK_TRIGGER)) - SetNonVolatileStatus(gEffectBattler, gBattleScripting.moveEffect, TRIGGER_ON_MOVE); + SetNonVolatileStatus(gEffectBattler, moveEffect, battleScript, TRIGGER_ON_MOVE); break; case MOVE_EFFECT_CONFUSION: if (!CanBeConfused(gEffectBattler) || gBattleMons[gEffectBattler].volatiles.confusionTurns - || (gSideStatuses[GetBattlerSide(gEffectBattler)] & SIDE_STATUS_SAFEGUARD && !(gHitMarker & HITMARKER_STATUS_ABILITY_EFFECT) && !primary)) + || (gSideStatuses[GetBattlerSide(gEffectBattler)] & SIDE_STATUS_SAFEGUARD && !primary)) { - gBattlescriptCurrInstr++; + gBattlescriptCurrInstr = battleScript; } else { @@ -3087,7 +3103,7 @@ void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certai } else { - BattleScriptPush(gBattlescriptCurrInstr + 1); + BattleScriptPush(battleScript); gBattlescriptCurrInstr = BattleScript_MoveEffectConfusion; } } @@ -3102,27 +3118,27 @@ void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certai gLastUsedAbility = ABILITY_INNER_FOCUS; gBattlerAbility = gEffectBattler; RecordAbilityBattle(gEffectBattler, ABILITY_INNER_FOCUS); - BattleScriptPush(gBattlescriptCurrInstr + 1); + BattleScriptPush(battleScript); gBattlescriptCurrInstr = BattleScript_FlinchPrevention; } else { - gBattlescriptCurrInstr++; + gBattlescriptCurrInstr = battleScript; } } else if (gBattleMons[gEffectBattler].volatiles.flinched) { - gBattlescriptCurrInstr++; + gBattlescriptCurrInstr = battleScript; } else if (!HasBattlerActedThisTurn(gEffectBattler) && GetActiveGimmick(gEffectBattler) != GIMMICK_DYNAMAX) { gBattleMons[gEffectBattler].volatiles.flinched = TRUE; - gBattlescriptCurrInstr++; + gBattlescriptCurrInstr = battleScript; } else { - gBattlescriptCurrInstr++; + gBattlescriptCurrInstr = battleScript; } break; case MOVE_EFFECT_UPROAR: @@ -3132,12 +3148,12 @@ void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certai gLockedMoves[gEffectBattler] = gCurrentMove; gBattleMons[gEffectBattler].volatiles.uproarTurns = B_UPROAR_TURNS >= GEN_5 ? 3 : (Random() & 3) + 2; - BattleScriptPush(gBattlescriptCurrInstr + 1); + BattleScriptPush(battleScript); gBattlescriptCurrInstr = BattleScript_MoveEffectUproar; } else { - gBattlescriptCurrInstr++; + gBattlescriptCurrInstr = battleScript; } break; case MOVE_EFFECT_PAYDAY: @@ -3154,15 +3170,15 @@ void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certai // we only want to print the message on the final hit if (!(NumAffectedSpreadMoveTargets() > 1 && GetNextTarget(moveTarget, TRUE) != MAX_BATTLERS_COUNT)) { - BattleScriptPush(gBattlescriptCurrInstr + 1); + BattleScriptPush(battleScript); gBattlescriptCurrInstr = BattleScript_MoveEffectPayDay; } else - gBattlescriptCurrInstr++; + gBattlescriptCurrInstr = battleScript; } else { - gBattlescriptCurrInstr++; + gBattlescriptCurrInstr = battleScript; } break; case MOVE_EFFECT_HAPPY_HOUR: @@ -3171,12 +3187,12 @@ void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certai gBattleStruct->moneyMultiplier *= 2; gBattleStruct->moneyMultiplierMove = 1; } - gBattlescriptCurrInstr++; + gBattlescriptCurrInstr = battleScript; break; case MOVE_EFFECT_TRI_ATTACK: if (gBattleMons[gEffectBattler].status1) { - gBattlescriptCurrInstr++; + gBattlescriptCurrInstr = battleScript; } else { @@ -3186,27 +3202,24 @@ void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certai MOVE_EFFECT_FREEZE_OR_FROSTBITE, MOVE_EFFECT_PARALYSIS }; - gBattleScripting.moveEffect = RandomElement(RNG_TRI_ATTACK, sTriAttackEffects); - SetMoveEffect(battler, effectBattler, primary, certain); + SetMoveEffect(battler, effectBattler, RandomElement(RNG_TRI_ATTACK, sTriAttackEffects), battleScript, effectFlags); } break; case MOVE_EFFECT_WRAP: if (gBattleMons[gEffectBattler].volatiles.wrapped) { - gBattlescriptCurrInstr++; + gBattlescriptCurrInstr = battleScript; } else { - gBattleMons[gEffectBattler].volatiles.wrapped = TRUE; - if (GetBattlerHoldEffect(gBattlerAttacker, TRUE) == HOLD_EFFECT_GRIP_CLAW) + if (GetBattlerHoldEffect(gBattlerAttacker) == HOLD_EFFECT_GRIP_CLAW) gDisableStructs[gEffectBattler].wrapTurns = B_BINDING_TURNS >= GEN_5 ? 7 : 5; else gDisableStructs[gEffectBattler].wrapTurns = B_BINDING_TURNS >= GEN_5 ? RandomUniform(RNG_WRAP, 4, 5) : RandomUniform(RNG_WRAP, 2, 5); - - gBattleStruct->wrappedMove[gEffectBattler] = gCurrentMove; - gBattleStruct->wrappedBy[gEffectBattler] = gBattlerAttacker; - - BattleScriptPush(gBattlescriptCurrInstr + 1); + gBattleMons[gEffectBattler].volatiles.wrapped = TRUE; + gBattleMons[gEffectBattler].volatiles.wrappedMove = gCurrentMove; + gBattleMons[gEffectBattler].volatiles.wrappedBy = gBattlerAttacker; + BattleScriptPush(battleScript); gBattlescriptCurrInstr = BattleScript_MoveEffectWrap; } break; @@ -3221,17 +3234,17 @@ void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certai || ChangeStatBuffs( effectBattler, SET_STAT_BUFF_VALUE(1), - gBattleScripting.moveEffect - MOVE_EFFECT_ATK_PLUS_1 + 1, + moveEffect - MOVE_EFFECT_ATK_PLUS_1 + 1, STAT_CHANGE_UPDATE_MOVE_EFFECT, 0, 0) == STAT_CHANGE_DIDNT_WORK) { - gBattlescriptCurrInstr++; + gBattlescriptCurrInstr = battleScript; } else { - gBattleScripting.animArg1 = gBattleScripting.moveEffect; + gBattleScripting.animArg1 = moveEffect; gBattleScripting.animArg2 = 0; - BattleScriptPush(gBattlescriptCurrInstr + 1); + BattleScriptPush(battleScript); gBattlescriptCurrInstr = BattleScript_StatUp; } break; @@ -3251,18 +3264,18 @@ void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certai if (ChangeStatBuffs( effectBattler, SET_STAT_BUFF_VALUE(1) | STAT_BUFF_NEGATIVE, - gBattleScripting.moveEffect - MOVE_EFFECT_ATK_MINUS_1 + 1, + moveEffect - MOVE_EFFECT_ATK_MINUS_1 + 1, flags, - 0, gBattlescriptCurrInstr + 1) == STAT_CHANGE_DIDNT_WORK) + 0, battleScript) == STAT_CHANGE_DIDNT_WORK) { if (!mirrorArmorReflected) - gBattlescriptCurrInstr++; + gBattlescriptCurrInstr = battleScript; } else { - gBattleScripting.animArg1 = gBattleScripting.moveEffect; + gBattleScripting.animArg1 = moveEffect; gBattleScripting.animArg2 = 0; - BattleScriptPush(gBattlescriptCurrInstr + 1); + BattleScriptPush(battleScript); gBattlescriptCurrInstr = BattleScript_StatDown; } break; @@ -3277,17 +3290,17 @@ void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certai || ChangeStatBuffs( effectBattler, SET_STAT_BUFF_VALUE(2), - gBattleScripting.moveEffect - MOVE_EFFECT_ATK_PLUS_2 + 1, + moveEffect - MOVE_EFFECT_ATK_PLUS_2 + 1, STAT_CHANGE_UPDATE_MOVE_EFFECT, 0, 0) == STAT_CHANGE_DIDNT_WORK) { - gBattlescriptCurrInstr++; + gBattlescriptCurrInstr = battleScript; } else { - gBattleScripting.animArg1 = gBattleScripting.moveEffect; + gBattleScripting.animArg1 = moveEffect; gBattleScripting.animArg2 = 0; - BattleScriptPush(gBattlescriptCurrInstr + 1); + BattleScriptPush(battleScript); gBattlescriptCurrInstr = BattleScript_StatUp; } break; @@ -3307,18 +3320,18 @@ void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certai if (ChangeStatBuffs( effectBattler, SET_STAT_BUFF_VALUE(2) | STAT_BUFF_NEGATIVE, - gBattleScripting.moveEffect - MOVE_EFFECT_ATK_MINUS_2 + 1, + moveEffect - MOVE_EFFECT_ATK_MINUS_2 + 1, flags, - 0, gBattlescriptCurrInstr + 1) == STAT_CHANGE_DIDNT_WORK) + 0, battleScript) == STAT_CHANGE_DIDNT_WORK) { if (!mirrorArmorReflected) - gBattlescriptCurrInstr++; + gBattlescriptCurrInstr = battleScript; } else { - gBattleScripting.animArg1 = gBattleScripting.moveEffect; + gBattleScripting.animArg1 = moveEffect; gBattleScripting.animArg2 = 0; - BattleScriptPush(gBattlescriptCurrInstr + 1); + BattleScriptPush(battleScript); gBattlescriptCurrInstr = BattleScript_StatDown; } break; @@ -3328,60 +3341,63 @@ void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certai gDisableStructs[gEffectBattler].rechargeTimer = 2; gLockedMoves[gEffectBattler] = gCurrentMove; - gBattlescriptCurrInstr++; + gBattlescriptCurrInstr = battleScript; break; case MOVE_EFFECT_RAGE: gBattleMons[gBattlerAttacker].volatiles.rage = TRUE; - gBattlescriptCurrInstr++; + gBattlescriptCurrInstr = battleScript; break; case MOVE_EFFECT_PREVENT_ESCAPE: - if (!gBattleMons[gBattlerTarget].volatiles.escapePrevention) + if (!gBattleMons[gBattlerTarget].volatiles.escapePrevention) // Do we need to check if the status is already set? { gBattleMons[gBattlerTarget].volatiles.escapePrevention = TRUE; gDisableStructs[gBattlerTarget].battlerPreventingEscape = gBattlerAttacker; } - gBattlescriptCurrInstr++; + gBattlescriptCurrInstr = battleScript; break; case MOVE_EFFECT_NIGHTMARE: gBattleMons[gBattlerTarget].volatiles.nightmare = TRUE; - gBattlescriptCurrInstr++; + gBattlescriptCurrInstr = battleScript; break; case MOVE_EFFECT_ALL_STATS_UP: if (!NoAliveMonsForEitherParty()) { - BattleScriptPush(gBattlescriptCurrInstr + 1); + BattleScriptPush(battleScript); gBattlescriptCurrInstr = BattleScript_AllStatsUp; } break; case MOVE_EFFECT_ATK_DEF_DOWN: // SuperPower if (!NoAliveMonsForEitherParty()) { - BattleScriptPush(gBattlescriptCurrInstr + 1); + BattleScriptPush(battleScript); gBattlescriptCurrInstr = BattleScript_AtkDefDown; } break; case MOVE_EFFECT_DEF_SPDEF_DOWN: // Close Combat if (!NoAliveMonsForEitherParty()) { - BattleScriptPush(gBattlescriptCurrInstr + 1); + BattleScriptPush(battleScript); gBattlescriptCurrInstr = BattleScript_DefSpDefDown; } break; case MOVE_EFFECT_RECOIL_HP_25: // Struggle - gBattleStruct->moveDamage[gEffectBattler] = (gBattleMons[gEffectBattler].maxHP) / 4; - if (gBattleStruct->moveDamage[gEffectBattler] == 0) - gBattleStruct->moveDamage[gEffectBattler] = 1; + { + s32 recoil = (gBattleMons[gEffectBattler].maxHP) / 4; + if (recoil == 0) + recoil = 1; if (GetBattlerAbility(gEffectBattler) == ABILITY_PARENTAL_BOND) - gBattleStruct->moveDamage[gEffectBattler] *= 2; - - BattleScriptPush(gBattlescriptCurrInstr + 1); + recoil *= 2; + SetPassiveDamageAmount(gEffectBattler, recoil); + TryUpdateEvolutionTracker(IF_RECOIL_DAMAGE_GE, gBattleStruct->passiveHpUpdate[gBattlerAttacker], MOVE_NONE); + BattleScriptPush(battleScript); gBattlescriptCurrInstr = BattleScript_MoveEffectRecoil; break; + } case MOVE_EFFECT_THRASH: // Petal Dance doesn't lock mons that copy the move with Dancer if (gSpecialStatuses[gEffectBattler].dancerUsedMove || gBattleMons[gEffectBattler].volatiles.lockConfusionTurns) { - gBattlescriptCurrInstr++; + gBattlescriptCurrInstr = battleScript; } else { @@ -3400,7 +3416,7 @@ void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certai { for (i = 0; i < NUM_BATTLE_STATS; i++) gBattleMons[gEffectBattler].statStages[i] = DEFAULT_STAT_STAGE; - BattleScriptPush(gBattlescriptCurrInstr + 1); + BattleScriptPush(battleScript); gBattlescriptCurrInstr = BattleScript_MoveEffectClearSmog; } break; @@ -3409,11 +3425,10 @@ void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certai && !IsSemiInvulnerable(BATTLE_PARTNER(gBattlerTarget), CHECK_ALL) && GetBattlerAbility(BATTLE_PARTNER(gBattlerTarget)) != ABILITY_MAGIC_GUARD) { - gBattleScripting.battler = i = BATTLE_PARTNER(gBattlerTarget); - gBattleStruct->moveDamage[i] = gBattleMons[i].maxHP / 16; - if (gBattleStruct->moveDamage[i] == 0) - gBattleStruct->moveDamage[i] = 1; - BattleScriptPush(gBattlescriptCurrInstr + 1); + u32 partnerTarget = BATTLE_PARTNER(gBattlerTarget); + gBattleScripting.battler = partnerTarget; + SetPassiveDamageAmount(partnerTarget, gBattleMons[partnerTarget].maxHP / 16); + BattleScriptPush(battleScript); gBattlescriptCurrInstr = BattleScript_MoveEffectFlameBurst; } break; @@ -3432,7 +3447,7 @@ void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certai } if (i) { - BattleScriptPush(gBattlescriptCurrInstr + 1); + BattleScriptPush(battleScript); if (gCurrentMove == MOVE_HYPERSPACE_FURY) gBattlescriptCurrInstr = BattleScript_HyperspaceFuryRemoveProtect; else @@ -3442,7 +3457,7 @@ void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certai case MOVE_EFFECT_V_CREATE: if (!NoAliveMonsForEitherParty()) { - BattleScriptPush(gBattlescriptCurrInstr + 1); + BattleScriptPush(battleScript); gBattlescriptCurrInstr = BattleScript_VCreateStatLoss; } break; @@ -3450,17 +3465,17 @@ void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certai if (HasBattlerActedThisTurn(gBattlerTarget) && !NoAliveMonsForEitherParty()) { - BattleScriptPush(gBattlescriptCurrInstr + 1); + BattleScriptPush(battleScript); gBattlescriptCurrInstr = BattleScript_MoveEffectCoreEnforcer; } break; case MOVE_EFFECT_THROAT_CHOP: - gDisableStructs[gEffectBattler].throatChopTimer = gBattleTurnCounter + 2; - gBattlescriptCurrInstr++; + gDisableStructs[gEffectBattler].throatChopTimer = 2; + gBattlescriptCurrInstr = battleScript; break; case MOVE_EFFECT_INCINERATE: if ((gBattleMons[gEffectBattler].item >= FIRST_BERRY_INDEX && gBattleMons[gEffectBattler].item <= LAST_BERRY_INDEX) - || (B_INCINERATE_GEMS >= GEN_6 && GetBattlerHoldEffect(gEffectBattler, FALSE) == HOLD_EFFECT_GEMS)) + || (B_INCINERATE_GEMS >= GEN_6 && GetBattlerHoldEffect(gEffectBattler) == HOLD_EFFECT_GEMS)) { gLastUsedItem = gBattleMons[gEffectBattler].item; gBattleMons[gEffectBattler].item = 0; @@ -3468,15 +3483,15 @@ void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certai BtlController_EmitSetMonData(gEffectBattler, B_COMM_TO_CONTROLLER, REQUEST_HELDITEM_BATTLE, 0, sizeof(gBattleMons[gEffectBattler].item), &gBattleMons[gEffectBattler].item); MarkBattlerForControllerExec(gEffectBattler); - BattleScriptPush(gBattlescriptCurrInstr + 1); + BattleScriptPush(battleScript); gBattlescriptCurrInstr = BattleScript_MoveEffectIncinerate; } break; case MOVE_EFFECT_BUG_BITE: - if (GetBattlerHoldEffect(gEffectBattler, TRUE) == HOLD_EFFECT_JABOCA_BERRY) + if (GetBattlerHoldEffect(gEffectBattler) == HOLD_EFFECT_JABOCA_BERRY) { // jaboca berry triggers instead of being stolen - gBattlescriptCurrInstr++; + gBattlescriptCurrInstr = battleScript; } else if (GetItemPocket(gBattleMons[gEffectBattler].item) == POCKET_BERRIES && battlerAbility != ABILITY_STICKY_HOLD) @@ -3488,14 +3503,14 @@ void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certai BtlController_EmitSetMonData(gEffectBattler, B_COMM_TO_CONTROLLER, REQUEST_HELDITEM_BATTLE, 0, sizeof(gBattleMons[gEffectBattler].item), &gBattleMons[gEffectBattler].item); MarkBattlerForControllerExec(gEffectBattler); - BattleScriptPush(gBattlescriptCurrInstr + 1); + BattleScriptPush(battleScript); gBattlescriptCurrInstr = BattleScript_MoveEffectBugBite; } break; case MOVE_EFFECT_TRAP_BOTH: if (!(gBattleMons[gBattlerTarget].volatiles.escapePrevention || gBattleMons[gBattlerAttacker].volatiles.escapePrevention)) { - BattleScriptPush(gBattlescriptCurrInstr + 1); + BattleScriptPush(battleScript); gBattlescriptCurrInstr = BattleScript_BothCanNoLongerEscape; } if (!gBattleMons[gBattlerTarget].volatiles.escapePrevention) @@ -3511,7 +3526,7 @@ void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certai { u32 type = GetMoveArgType(gCurrentMove); // This seems unnecessary but is done to make it work properly with Parental Bond - BattleScriptPush(gBattlescriptCurrInstr + 1); + BattleScriptPush(battleScript); switch (type) { case TYPE_FIRE: // Burn Up @@ -3529,21 +3544,20 @@ void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certai } case MOVE_EFFECT_ROUND: TryUpdateRoundTurnOrder(); // If another Pokémon uses Round before the user this turn, the user will use Round directly after it - gBattlescriptCurrInstr++; + gBattlescriptCurrInstr = battleScript; break; case MOVE_EFFECT_DIRE_CLAW: if (!gBattleMons[gEffectBattler].status1) { static const u8 sDireClawEffects[] = { MOVE_EFFECT_POISON, MOVE_EFFECT_PARALYSIS, MOVE_EFFECT_SLEEP }; - gBattleScripting.moveEffect = RandomElement(RNG_DIRE_CLAW, sDireClawEffects); - SetMoveEffect(battler, effectBattler, primary, certain); + SetMoveEffect(battler, effectBattler, RandomElement(RNG_DIRE_CLAW, sDireClawEffects), battleScript, effectFlags); } break; case MOVE_EFFECT_STEALTH_ROCK: if (!IsHazardOnSide(GetBattlerSide(gEffectBattler), HAZARDS_STEALTH_ROCK)) { gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_POINTEDSTONESFLOAT; - BattleScriptPush(gBattlescriptCurrInstr + 1); + BattleScriptPush(battleScript); gBattlescriptCurrInstr = BattleScript_StealthRockActivates; } break; @@ -3553,10 +3567,10 @@ void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certai struct Pokemon *mon = GetBattlerMon(gBattlerAttacker); gBattleMons[gEffectBattler].volatiles.syrupBomb = TRUE; + gBattleMons[gEffectBattler].volatiles.stickySyrupedBy = gBattlerAttacker; gDisableStructs[gEffectBattler].syrupBombTimer = 3; gDisableStructs[gEffectBattler].syrupBombIsShiny = IsMonShiny(mon); - gBattleStruct->stickySyrupdBy[gEffectBattler] = gBattlerAttacker; - BattleScriptPush(gBattlescriptCurrInstr + 1); + BattleScriptPush(battleScript); gBattlescriptCurrInstr = BattleScript_SyrupBombActivates; } break; @@ -3566,25 +3580,24 @@ void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certai switch (gFieldStatuses & STATUS_FIELD_TERRAIN_ANY) { case STATUS_FIELD_MISTY_TERRAIN: - gBattleScripting.moveEffect = MOVE_EFFECT_SP_ATK_MINUS_1; + moveEffect = MOVE_EFFECT_SP_ATK_MINUS_1; break; case STATUS_FIELD_GRASSY_TERRAIN: - gBattleScripting.moveEffect = MOVE_EFFECT_SLEEP; + moveEffect = MOVE_EFFECT_SLEEP; break; case STATUS_FIELD_ELECTRIC_TERRAIN: - gBattleScripting.moveEffect = MOVE_EFFECT_PARALYSIS; + moveEffect = MOVE_EFFECT_PARALYSIS; break; case STATUS_FIELD_PSYCHIC_TERRAIN: - gBattleScripting.moveEffect = MOVE_EFFECT_SPD_MINUS_1; + moveEffect = MOVE_EFFECT_SPD_MINUS_1; break; default: - gBattleScripting.moveEffect = MOVE_EFFECT_PARALYSIS; + moveEffect = MOVE_EFFECT_PARALYSIS; break; } } else - gBattleScripting.moveEffect = gBattleEnvironmentInfo[gBattleEnvironment].secretPowerEffect; - SetMoveEffect(battler, effectBattler, primary, certain); + SetMoveEffect(battler, effectBattler, gBattleEnvironmentInfo[gBattleEnvironment].secretPowerEffect, battleScript, effectFlags); break; case MOVE_EFFECT_PSYCHIC_NOISE: battlerAbility = IsAbilityOnSide(gEffectBattler, ABILITY_AROMA_VEIL); @@ -3592,14 +3605,14 @@ void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certai if (battlerAbility) { gBattlerAbility = battlerAbility - 1; - BattleScriptPush(gBattlescriptCurrInstr + 1); + BattleScriptPush(battleScript); gBattlescriptCurrInstr = BattleScript_AromaVeilProtectsRet; } else if (!gBattleMons[gEffectBattler].volatiles.healBlock) { gBattleMons[gEffectBattler].volatiles.healBlock = TRUE; - gDisableStructs[gEffectBattler].healBlockTimer = gBattleTurnCounter + 2; - BattleScriptPush(gBattlescriptCurrInstr + 1); + gDisableStructs[gEffectBattler].healBlockTimer = 2; + BattleScriptPush(battleScript); gBattlescriptCurrInstr = BattleScript_EffectPsychicNoise; } break; @@ -3608,13 +3621,13 @@ void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certai && GetBattlerTeraType(gEffectBattler) == TYPE_STELLAR && !NoAliveMonsForEitherParty()) { - BattleScriptPush(gBattlescriptCurrInstr + 1); + BattleScriptPush(battleScript); gBattlescriptCurrInstr = BattleScript_LowerAtkSpAtk; } break; case MOVE_EFFECT_ORDER_UP: { - u32 stat = 0; + enum Stat stat = 0; bool32 commanderAffected = TRUE; switch (gBattleStruct->battlerState[gEffectBattler].commanderSpecies) { @@ -3641,13 +3654,13 @@ void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certai 0, 0) == STAT_CHANGE_DIDNT_WORK) { - gBattlescriptCurrInstr++; + gBattlescriptCurrInstr = battleScript; } else { - gBattleScripting.animArg1 = gBattleScripting.moveEffect; + gBattleScripting.animArg1 = moveEffect; gBattleScripting.animArg2 = 0; - BattleScriptPush(gBattlescriptCurrInstr + 1); + BattleScriptPush(battleScript); gBattlescriptCurrInstr = BattleScript_StatUp; } } @@ -3656,35 +3669,35 @@ void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certai if (!(gFieldStatuses & STATUS_FIELD_ION_DELUGE)) { gFieldStatuses |= STATUS_FIELD_ION_DELUGE; - BattleScriptPush(gBattlescriptCurrInstr + 1); + BattleScriptPush(battleScript); gBattlescriptCurrInstr = BattleScript_MoveEffectIonDeluge; } break; case MOVE_EFFECT_HAZE: for (i = 0; i < gBattlersCount; i++) TryResetBattlerStatChanges(i); - BattleScriptPush(gBattlescriptCurrInstr + 1); + BattleScriptPush(battleScript); gBattlescriptCurrInstr = BattleScript_MoveEffectHaze; break; case MOVE_EFFECT_LEECH_SEED: if (!IS_BATTLER_OF_TYPE(gBattlerTarget, TYPE_GRASS) && !gBattleMons[gBattlerTarget].volatiles.leechSeed) { gBattleMons[gBattlerTarget].volatiles.leechSeed = LEECHSEEDED_BY(gBattlerAttacker); - BattleScriptPush(gBattlescriptCurrInstr + 1); + BattleScriptPush(battleScript); gBattlescriptCurrInstr = BattleScript_MoveEffectLeechSeed; } break; case MOVE_EFFECT_REFLECT: if (TrySetReflect(gBattlerAttacker)) { - BattleScriptPush(gBattlescriptCurrInstr + 1); + BattleScriptPush(battleScript); gBattlescriptCurrInstr = BattleScript_MoveEffectReflect; } break; case MOVE_EFFECT_LIGHT_SCREEN: if (TrySetLightScreen(gBattlerAttacker)) { - BattleScriptPush(gBattlescriptCurrInstr + 1); + BattleScriptPush(battleScript); gBattlescriptCurrInstr = BattleScript_MoveEffectLightScreen; } break; @@ -3692,7 +3705,7 @@ void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certai if (!gBattleMons[gBattlerTarget].volatiles.saltCure) { gBattleMons[gBattlerTarget].volatiles.saltCure = TRUE; - BattleScriptPush(gBattlescriptCurrInstr + 1); + BattleScriptPush(battleScript); gBattlescriptCurrInstr = BattleScript_MoveEffectSaltCure; } break; @@ -3728,7 +3741,7 @@ void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certai if (gBattleMons[gBattlerTarget].pp[i] == 0 && gBattleStruct->skyDropTargets[gBattlerTarget] == SKY_DROP_NO_TARGET) CancelMultiTurnMoves(gBattlerTarget, SKY_DROP_IGNORE); - BattleScriptPush(gBattlescriptCurrInstr + 1); + BattleScriptPush(battleScript); gBattlescriptCurrInstr = BattleScript_MoveEffectEerieSpell; } } @@ -3738,7 +3751,7 @@ void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certai { // Max Effects are ordered by stat ID. SET_STATCHANGER(STAT_ATK, 1, FALSE); - BattleScriptPush(gBattlescriptCurrInstr + 1); + BattleScriptPush(battleScript); gBattlescriptCurrInstr = BattleScript_EffectRaiseStatAllies; } break; @@ -3747,7 +3760,7 @@ void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certai { // Max Effects are ordered by stat ID. SET_STATCHANGER(STAT_DEF, 1, FALSE); - BattleScriptPush(gBattlescriptCurrInstr + 1); + BattleScriptPush(battleScript); gBattlescriptCurrInstr = BattleScript_EffectRaiseStatAllies; } break; @@ -3756,7 +3769,7 @@ void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certai { // Max Effects are ordered by stat ID. SET_STATCHANGER(STAT_SPEED, 1, FALSE); - BattleScriptPush(gBattlescriptCurrInstr + 1); + BattleScriptPush(battleScript); gBattlescriptCurrInstr = BattleScript_EffectRaiseStatAllies; } break; @@ -3765,7 +3778,7 @@ void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certai { // Max Effects are ordered by stat ID. SET_STATCHANGER(STAT_SPATK, 1, FALSE); - BattleScriptPush(gBattlescriptCurrInstr + 1); + BattleScriptPush(battleScript); gBattlescriptCurrInstr = BattleScript_EffectRaiseStatAllies; } break; @@ -3774,7 +3787,7 @@ void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certai { // Max Effects are ordered by stat ID. SET_STATCHANGER(STAT_SPDEF, 1, FALSE); - BattleScriptPush(gBattlescriptCurrInstr + 1); + BattleScriptPush(battleScript); gBattlescriptCurrInstr = BattleScript_EffectRaiseStatAllies; } break; @@ -3787,9 +3800,9 @@ void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certai case MOVE_EFFECT_LOWER_EVASIVENESS_SIDE: if (!NoAliveMonsForEitherParty()) { - u32 statId = 0; + enum Stat statId = 0; u32 stage = 1; - switch (gBattleScripting.moveEffect) + switch (moveEffect) { case MOVE_EFFECT_LOWER_SPEED_2_SIDE: statId = STAT_SPEED; @@ -3800,11 +3813,11 @@ void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certai break; default: // Max Effects are ordered by stat ID. - statId = gBattleScripting.moveEffect - MOVE_EFFECT_LOWER_ATTACK_SIDE + 1; + statId = moveEffect - MOVE_EFFECT_LOWER_ATTACK_SIDE + 1; break; } SET_STATCHANGER(statId, stage, TRUE); - BattleScriptPush(gBattlescriptCurrInstr + 1); + BattleScriptPush(battleScript); gBattlescriptCurrInstr = BattleScript_EffectLowerStatFoes; } break; @@ -3814,7 +3827,7 @@ void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certai case MOVE_EFFECT_HAIL: { u8 weather = 0, msg = 0; - switch (gBattleScripting.moveEffect) + switch (moveEffect) { case MOVE_EFFECT_SUN: weather = BATTLE_WEATHER_SUN; @@ -3840,11 +3853,13 @@ void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certai msg = B_MSG_STARTED_HAIL; } break; + default: + break; } if (TryChangeBattleWeather(gBattlerAttacker, weather, ABILITY_NONE)) { gBattleCommunication[MULTISTRING_CHOOSER] = msg; - BattleScriptPush(gBattlescriptCurrInstr + 1); + BattleScriptPush(battleScript); gBattlescriptCurrInstr = BattleScript_EffectSetWeather; } break; @@ -3855,7 +3870,7 @@ void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certai case MOVE_EFFECT_PSYCHIC_TERRAIN: { u32 statusFlag = 0; - switch (gBattleScripting.moveEffect) + switch (moveEffect) { case MOVE_EFFECT_MISTY_TERRAIN: statusFlag = STATUS_FIELD_MISTY_TERRAIN; @@ -3873,16 +3888,18 @@ void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certai statusFlag = STATUS_FIELD_PSYCHIC_TERRAIN; gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_TERRAIN_SET_PSYCHIC; break; + default: + break; } if (!(gFieldStatuses & statusFlag) && statusFlag != 0) { gFieldStatuses &= ~STATUS_FIELD_TERRAIN_ANY; gFieldStatuses |= statusFlag; - if (GetBattlerHoldEffect(gBattlerAttacker, TRUE) == HOLD_EFFECT_TERRAIN_EXTENDER) - gFieldTimers.terrainTimer = gBattleTurnCounter + 8; + if (GetBattlerHoldEffect(gBattlerAttacker) == HOLD_EFFECT_TERRAIN_EXTENDER) + gFieldTimers.terrainTimer = 8; else - gFieldTimers.terrainTimer = gBattleTurnCounter + 5; - BattleScriptPush(gBattlescriptCurrInstr + 1); + gFieldTimers.terrainTimer = 5; + BattleScriptPush(battleScript); gBattlescriptCurrInstr = BattleScript_EffectSetTerrain; } break; @@ -3897,9 +3914,9 @@ void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certai { u32 moveType = GetMoveType(gCurrentMove); gSideStatuses[side] |= SIDE_STATUS_DAMAGE_NON_TYPES; - gSideTimers[side].damageNonTypesTimer = gBattleTurnCounter + 5; // damage is dealt for 4 turns, ends on 5th + gSideTimers[side].damageNonTypesTimer = 5; gSideTimers[side].damageNonTypesType = moveType; - BattleScriptPush(gBattlescriptCurrInstr + 1); + BattleScriptPush(battleScript); ChooseDamageNonTypesString(moveType); gBattlescriptCurrInstr = BattleScript_DamageNonTypesStarts; } @@ -3909,7 +3926,7 @@ void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certai if (!IsHazardOnSide(GetBattlerSide(gBattlerTarget), HAZARDS_STEELSURGE)) { gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SHARPSTEELFLOATS; - BattleScriptPush(gBattlescriptCurrInstr + 1); + BattleScriptPush(battleScript); gBattlescriptCurrInstr = BattleScript_EffectSteelsurge; } break; @@ -3919,7 +3936,7 @@ void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certai || AreAnyHazardsOnSide(GetBattlerSide(gBattlerAttacker)) || gFieldStatuses & STATUS_FIELD_TERRAIN_ANY) { - BattleScriptPush(gBattlescriptCurrInstr + 1); + BattleScriptPush(battleScript); gBattlescriptCurrInstr = BattleScript_MoveEffectDefog; } break; @@ -3927,12 +3944,12 @@ void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certai if (!(gSideStatuses[GetBattlerSide(gBattlerAttacker)] & SIDE_STATUS_AURORA_VEIL)) { gSideStatuses[GetBattlerSide(gBattlerAttacker)] |= SIDE_STATUS_AURORA_VEIL; - if (GetBattlerHoldEffect(gBattlerAttacker, TRUE) == HOLD_EFFECT_LIGHT_CLAY) - gSideTimers[GetBattlerSide(gBattlerAttacker)].auroraVeilTimer = gBattleTurnCounter + 8; + if (GetBattlerHoldEffect(gBattlerAttacker) == HOLD_EFFECT_LIGHT_CLAY) + gSideTimers[GetBattlerSide(gBattlerAttacker)].auroraVeilTimer = 8; else - gSideTimers[GetBattlerSide(gBattlerAttacker)].auroraVeilTimer = gBattleTurnCounter + 5; + gSideTimers[GetBattlerSide(gBattlerAttacker)].auroraVeilTimer = 5; gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SET_SAFEGUARD; - BattleScriptPush(gBattlescriptCurrInstr + 1); + BattleScriptPush(battleScript); gBattlescriptCurrInstr = BattleScript_MoveEffectAuroraVeil; } break; @@ -3940,8 +3957,8 @@ void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certai if (!(gFieldStatuses & STATUS_FIELD_GRAVITY)) { gFieldStatuses |= STATUS_FIELD_GRAVITY; - gFieldTimers.gravityTimer = gBattleTurnCounter + 5; - BattleScriptPush(gBattlescriptCurrInstr + 1); + gFieldTimers.gravityTimer = 5; + BattleScriptPush(battleScript); gBattlescriptCurrInstr = BattleScript_EffectGravitySuccess; } break; @@ -3957,16 +3974,16 @@ void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certai if (!gBattleMons[battler].volatiles.wrapped) { gBattleMons[battler].volatiles.wrapped = TRUE; - if (GetBattlerHoldEffect(gBattlerAttacker, TRUE) == HOLD_EFFECT_GRIP_CLAW) + if (GetBattlerHoldEffect(gBattlerAttacker) == HOLD_EFFECT_GRIP_CLAW) gDisableStructs[battler].wrapTurns = (B_BINDING_TURNS >= GEN_5) ? 7 : 5; else gDisableStructs[battler].wrapTurns = (Random() % 2) + 4; // The Wrap effect does not expire when the user switches, so here's some cheese. - gBattleStruct->wrappedBy[battler] = gBattlerTarget; - if (gBattleScripting.moveEffect == MOVE_EFFECT_SANDBLAST_SIDE) - gBattleStruct->wrappedMove[battler] = MOVE_SAND_TOMB; + gBattleMons[battler].volatiles.wrappedBy = gBattlerTarget; + if (moveEffect == MOVE_EFFECT_SANDBLAST_SIDE) + gBattleMons[battler].volatiles.wrappedMove = MOVE_SAND_TOMB; else - gBattleStruct->wrappedMove[battler] = MOVE_FIRE_SPIN; + gBattleMons[battler].volatiles.wrappedMove = MOVE_FIRE_SPIN; } } break; @@ -3978,7 +3995,7 @@ void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certai && RandomPercentage(RNG_G_MAX_SNOOZE, 50)) { gBattleMons[gBattlerTarget].volatiles.yawn = 2; - BattleScriptPush(gBattlescriptCurrInstr + 1); + BattleScriptPush(battleScript); gBattlescriptCurrInstr = BattleScript_MoveEffectYawnSide; } break; @@ -3987,24 +4004,24 @@ void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certai if (gLastMoves[gBattlerTarget] != MOVE_NONE && gLastMoves[gBattlerTarget] != MOVE_UNAVAILABLE) { - BattleScriptPush(gBattlescriptCurrInstr + 1); + BattleScriptPush(battleScript); gBattlescriptCurrInstr = BattleScript_EffectTryReducePP; } break; case MOVE_EFFECT_PARALYZE_SIDE: - BattleScriptPush(gBattlescriptCurrInstr + 1); + BattleScriptPush(battleScript); gBattlescriptCurrInstr = BattleScript_EffectParalyzeSide; break; case MOVE_EFFECT_POISON_SIDE: - BattleScriptPush(gBattlescriptCurrInstr + 1); + BattleScriptPush(battleScript); gBattlescriptCurrInstr = BattleScript_EffectPoisonSide; break; case MOVE_EFFECT_POISON_PARALYZE_SIDE: - BattleScriptPush(gBattlescriptCurrInstr + 1); + BattleScriptPush(battleScript); gBattlescriptCurrInstr = BattleScript_EffectPoisonParalyzeSide; break; case MOVE_EFFECT_EFFECT_SPORE_SIDE: - BattleScriptPush(gBattlescriptCurrInstr + 1); + BattleScriptPush(battleScript); gBattlescriptCurrInstr = BattleScript_EffectEffectSporeSide; break; case MOVE_EFFECT_CONFUSE_PAY_DAY_SIDE: @@ -4018,39 +4035,41 @@ void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certai } // fall through case MOVE_EFFECT_CONFUSE_SIDE: - BattleScriptPush(gBattlescriptCurrInstr + 1); + BattleScriptPush(battleScript); gBattlescriptCurrInstr = BattleScript_EffectConfuseSide; break; case MOVE_EFFECT_INFATUATE_SIDE: - BattleScriptPush(gBattlescriptCurrInstr + 1); + BattleScriptPush(battleScript); gBattlescriptCurrInstr = BattleScript_EffectInfatuateSide; break; case MOVE_EFFECT_TORMENT_SIDE: - BattleScriptPush(gBattlescriptCurrInstr + 1); + BattleScriptPush(battleScript); gBattlescriptCurrInstr = BattleScript_EffectTormentSide; break; case MOVE_EFFECT_PREVENT_ESCAPE_SIDE: - BattleScriptPush(gBattlescriptCurrInstr + 1); + BattleScriptPush(battleScript); gBattlescriptCurrInstr = BattleScript_EffectMeanLookSide; break; case MOVE_EFFECT_CRIT_PLUS_SIDE: - gBattleStruct->bonusCritStages[gBattlerAttacker]++; - gBattleStruct->bonusCritStages[BATTLE_PARTNER(gBattlerAttacker)]++; - BattleScriptPush(gBattlescriptCurrInstr + 1); + if (gBattleMons[gBattlerAttacker].volatiles.bonusCritStages < 3) + gBattleMons[gBattlerAttacker].volatiles.bonusCritStages++; + if (gBattleMons[BATTLE_PARTNER(gBattlerAttacker)].volatiles.bonusCritStages < 3) + gBattleMons[BATTLE_PARTNER(gBattlerAttacker)].volatiles.bonusCritStages++; + BattleScriptPush(battleScript); gBattlescriptCurrInstr = BattleScript_EffectRaiseCritAlliesAnim; break; case MOVE_EFFECT_HEAL_TEAM: - BattleScriptPush(gBattlescriptCurrInstr + 1); + BattleScriptPush(battleScript); gBattlescriptCurrInstr = BattleScript_EffectHealOneSixthAllies; break; case MOVE_EFFECT_AROMATHERAPY: - BattleScriptPush(gBattlescriptCurrInstr + 1); + BattleScriptPush(battleScript); gBattlescriptCurrInstr = BattleScript_MoveEffectAromatherapy; break; case MOVE_EFFECT_RECYCLE_BERRIES: if (RandomPercentage(RNG_G_MAX_REPLENISH, 50)) { - BattleScriptPush(gBattlescriptCurrInstr + 1); + BattleScriptPush(battleScript); gBattlescriptCurrInstr = BattleScript_EffectRecycleBerriesAllies; } break; @@ -4063,7 +4082,7 @@ void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certai gBattleMons[gEffectBattler].status1 &= ~(argStatus); BtlController_EmitSetMonData(gEffectBattler, 0, REQUEST_STATUS_BATTLE, 0, 4, &gBattleMons[gEffectBattler].status1); MarkBattlerForControllerExec(gEffectBattler); - BattleScriptPush(gBattlescriptCurrInstr + 1); + BattleScriptPush(battleScript); switch (argStatus) { @@ -4092,13 +4111,19 @@ void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certai } break; } + default: + break; } - gBattleScripting.moveEffect = 0; + gBattleScripting.moveEffect = MOVE_EFFECT_NONE; } static bool32 CanApplyAdditionalEffect(const struct AdditionalEffect *additionalEffect) { + // If Toxic Chain will activate it blocks all other non volatile effects + if (gBattleStruct->toxicChainPriority && additionalEffect->moveEffect <= MOVE_EFFECT_FROSTBITE) + return FALSE; + if (additionalEffect->self && NumAffectedSpreadMoveTargets() > 1 && GetNextTarget(GetBattlerMoveTargetType(gBattlerAttacker, gCurrentMove), TRUE) != MAX_BATTLERS_COUNT) @@ -4115,6 +4140,20 @@ static bool32 CanApplyAdditionalEffect(const struct AdditionalEffect *additional return TRUE; } +static void SetToxicChainPriority(void) +{ + if (gBattleStruct->toxicChainPriority) + return; + + enum Ability abilityAtk = GetBattlerAbility(gBattlerAttacker); + if (abilityAtk == ABILITY_TOXIC_CHAIN + && IsBattlerAlive(gBattlerTarget) + && CanBePoisoned(gBattlerAttacker, gBattlerTarget, abilityAtk, GetBattlerAbility(gBattlerTarget)) + && IsBattlerTurnDamaged(gBattlerTarget) + && RandomWeighted(RNG_TOXIC_CHAIN, 7, 3)) + gBattleStruct->toxicChainPriority = TRUE; +} + static void Cmd_setadditionaleffects(void) { CMD_ARGS(); @@ -4122,6 +4161,7 @@ static void Cmd_setadditionaleffects(void) if (!(gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_NO_EFFECT)) { u32 numAdditionalEffects = GetMoveAdditionalEffectCount(gCurrentMove); + SetToxicChainPriority(); if (numAdditionalEffects > gBattleStruct->additionalEffectsCounter) { u32 percentChance; @@ -4136,14 +4176,18 @@ static void Cmd_setadditionaleffects(void) // Activate effect if it's primary (chance == 0) or if RNGesus says so if ((percentChance == 0) || RandomPercentage(RNG_SECONDARY_EFFECT + gBattleStruct->additionalEffectsCounter, percentChance)) { - gBattleScripting.moveEffect = additionalEffect->moveEffect; gBattleCommunication[MULTISTRING_CHOOSER] = *((u8 *) &additionalEffect->multistring); + enum SetMoveEffectFlags flags = NO_FLAGS; + if (percentChance == 0) flags |= EFFECT_PRIMARY; + if (percentChance >= 100) flags |= EFFECT_CERTAIN; + SetMoveEffect( gBattlerAttacker, additionalEffect->self ? gBattlerAttacker : gBattlerTarget, - percentChance == 0, // a primary effect - percentChance >= 100 // certain to happen + additionalEffect->moveEffect, + cmd->nextInstr, + flags ); } } @@ -4170,8 +4214,6 @@ static void Cmd_setadditionaleffects(void) gBattleScripting.moveEffect = 0; gBattlescriptCurrInstr = cmd->nextInstr; } - - gBattleScripting.multihitMoveEffect = 0; } static void Cmd_seteffectprimary(void) @@ -4180,8 +4222,7 @@ static void Cmd_seteffectprimary(void) u32 battler = GetBattlerForBattleScript(cmd->battler); u32 effectBattler = GetBattlerForBattleScript(cmd->effectBattler); - gBattlescriptCurrInstr = cmd->nextInstr - 1; - SetMoveEffect(battler, effectBattler, TRUE, FALSE); + SetMoveEffect(battler, effectBattler, gBattleScripting.moveEffect, cmd->nextInstr, EFFECT_PRIMARY); } static void Cmd_seteffectsecondary(void) @@ -4190,8 +4231,7 @@ static void Cmd_seteffectsecondary(void) u32 battler = GetBattlerForBattleScript(cmd->battler); u32 effectBattler = GetBattlerForBattleScript(cmd->effectBattler); - gBattlescriptCurrInstr = cmd->nextInstr - 1; - SetMoveEffect(battler, effectBattler, FALSE, FALSE); + SetMoveEffect(battler, effectBattler, gBattleScripting.moveEffect, cmd->nextInstr, EFFECT_PRIMARY); } static void Cmd_clearvolatile(void) @@ -4205,13 +4245,12 @@ static void Cmd_clearvolatile(void) gProtectStructs[battler].chargingTurn = FALSE; gBattlescriptCurrInstr = cmd->nextInstr; - gBattleScripting.multihitMoveEffect = 0; } static void Cmd_tryfaintmon(void) { CMD_ARGS(u8 battler, bool8 isSpikes, const u8 *instr); - u32 battler, destinyBondBattler; + u32 battler; const u8 *faintScript; battler = GetBattlerForBattleScript(cmd->battler); @@ -4229,25 +4268,24 @@ static void Cmd_tryfaintmon(void) } else { - if (gBattleMons[battler].ability == ABILITY_NEUTRALIZING_GAS + if (gDisableStructs[battler].neutralizingGas && !(gAbsentBattlerFlags & (1u << battler)) && !IsBattlerAlive(battler)) { - gBattleMons[battler].ability = ABILITY_NONE; - BattleScriptPush(gBattlescriptCurrInstr); - gBattlescriptCurrInstr = BattleScript_NeutralizingGasExits; - return; + gDisableStructs[battler].neutralizingGas = FALSE; + if (!IsNeutralizingGasOnField()) + { + BattleScriptPush(gBattlescriptCurrInstr); + gBattlescriptCurrInstr = BattleScript_NeutralizingGasExits; + return; + } } + if (cmd->battler == BS_ATTACKER) - { - destinyBondBattler = gBattlerTarget; - faintScript = BattleScript_FaintAttacker; - } - else - { - destinyBondBattler = gBattlerAttacker; - faintScript = BattleScript_FaintTarget; - } + TryUpdateEvolutionTracker(IF_DEFEAT_X_WITH_ITEMS, 1, MOVE_NONE); + + gBattlerFainted = battler; + faintScript = BattleScript_FaintBattler; if (!(gAbsentBattlerFlags & (1u << battler)) && !IsBattlerAlive(battler)) { @@ -4269,30 +4307,11 @@ static void Cmd_tryfaintmon(void) gBattleResults.lastOpponentSpecies = GetMonData(GetBattlerMon(battler), MON_DATA_SPECIES, NULL); gSideTimers[B_SIDE_OPPONENT].retaliateTimer = 2; } - if ((gHitMarker & HITMARKER_DESTINYBOND) && IsBattlerAlive(gBattlerAttacker) - && !(GetActiveGimmick(gBattlerAttacker) == GIMMICK_DYNAMAX)) - { - gHitMarker &= ~HITMARKER_DESTINYBOND; - BattleScriptPush(gBattlescriptCurrInstr); - gBattleStruct->moveDamage[destinyBondBattler] = gBattleMons[destinyBondBattler].hp; - gBattlescriptCurrInstr = BattleScript_DestinyBondTakesLife; - } - if (gBattleMons[gBattlerTarget].volatiles.grudge - && !(gHitMarker & HITMARKER_GRUDGE) - && !IsBattlerAlly(gBattlerAttacker, gBattlerTarget) - && IsBattlerAlive(gBattlerAttacker) - && gCurrentMove != MOVE_STRUGGLE) - { - u8 moveIndex = gBattleStruct->chosenMovePositions[gBattlerAttacker]; - gBattleMons[gBattlerAttacker].pp[moveIndex] = 0; - BattleScriptPush(gBattlescriptCurrInstr); - gBattlescriptCurrInstr = BattleScript_GrudgeTakesPp; - BtlController_EmitSetMonData(gBattlerAttacker, B_COMM_TO_CONTROLLER, moveIndex + REQUEST_PPMOVE1_BATTLE, 0, sizeof(gBattleMons[gBattlerAttacker].pp[moveIndex]), &gBattleMons[gBattlerAttacker].pp[moveIndex]); - MarkBattlerForControllerExec(gBattlerAttacker); - - PREPARE_MOVE_BUFFER(gBattleTextBuff1, gBattleMons[gBattlerAttacker].moves[moveIndex]) - } + if (gBattleMons[gBattlerTarget].volatiles.destinyBond) + gBattleStruct->tryDestinyBond = TRUE; + if (gBattleMons[gBattlerTarget].volatiles.grudge) + gBattleStruct->tryGrudge = TRUE; TryDeactivateSleepClause(GetBattlerSide(battler), gBattlerPartyIndexes[battler]); } @@ -4377,11 +4396,11 @@ static void Cmd_jumpifvolatile(void) static void Cmd_jumpifability(void) { - CMD_ARGS(u8 battler, u16 ability, const u8 *jumpInstr); + CMD_ARGS(u8 battler, enum Ability ability, const u8 *jumpInstr); u32 battler; bool32 hasAbility = FALSE; - u32 ability = cmd->ability; + enum Ability ability = cmd->ability; switch (cmd->battler) { @@ -4516,7 +4535,7 @@ static bool32 BattleTypeAllowsExp(void) static u32 GetMonHoldEffect(struct Pokemon *mon) { - enum ItemHoldEffect holdEffect; + enum HoldEffect holdEffect; u32 item = GetMonData(mon, MON_DATA_HELD_ITEM); if (item == ITEM_ENIGMA_BERRY_E_READER) @@ -4535,7 +4554,7 @@ static void Cmd_getexp(void) { CMD_ARGS(u8 battler); - enum ItemHoldEffect holdEffect; + enum HoldEffect holdEffect; s32 i; // also used as stringId u8 *expMonId = &gBattleStruct->expGetterMonId; u32 currLvl; @@ -4664,7 +4683,7 @@ static void Cmd_getexp(void) if (!(gBattleTypeFlags & BATTLE_TYPE_TRAINER) && (gBattleMons[0].hp || (IsDoubleBattle() && gBattleMons[2].hp)) && !IsBattlerAlive(GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT)) - && !IsBattlerAlive(GetBattlerAtPosition(B_POSITION_OPPONENT_RIGHT)) + && (!IsDoubleBattle() || !IsBattlerAlive(GetBattlerAtPosition(B_POSITION_OPPONENT_RIGHT))) && !gBattleStruct->wildVictorySong) { BattleStopLowHpSound(); @@ -4844,8 +4863,6 @@ static void Cmd_getexp(void) // not sure why gf clears the item and ability here gBattleStruct->expOrderId = 0; gBattleStruct->teamGotExpMsgPrinted = FALSE; - gBattleMons[gBattlerFainted].item = ITEM_NONE; - gBattleMons[gBattlerFainted].ability = ABILITY_NONE; gBattlescriptCurrInstr = cmd->nextInstr; } break; @@ -4891,16 +4908,14 @@ bool32 NoAliveMonsForPlayer(void) { HP_count += GetMonData(&gPlayerParty[i], MON_DATA_HP); } - // Get the number of fainted mons or eggs (not empty slots) in the first three party slots. if (i < 3 && ((GetMonData(&gPlayerParty[i], MON_DATA_SPECIES) && !GetMonData(&gPlayerParty[i], MON_DATA_HP)) || GetMonData(&gPlayerParty[i], MON_DATA_IS_EGG))) ineligibleMonsCount++; } - // Get the number of inelligible slots in the saved player party. if (B_MULTI_BATTLE_WHITEOUT > GEN_3 && gBattleTypeFlags & (BATTLE_TYPE_MULTI | BATTLE_TYPE_INGAME_PARTNER) - && !(gBattleTypeFlags & BATTLE_TYPE_ARENA)) + && !(gBattleTypeFlags & BATTLE_TYPE_ARENA) && !(IsMultibattleTest())) // Multibattle tests appear to not save the player party data for the check below. { for (i = 0; i < PARTY_SIZE; i++) { @@ -4953,7 +4968,6 @@ static void Cmd_checkteamslost(void) if (NoAliveMonsForPlayer()) gBattleOutcome |= B_OUTCOME_LOST; - if (NoAliveMonsForOpponent()) gBattleOutcome |= B_OUTCOME_WON; @@ -4968,14 +4982,14 @@ static void Cmd_checkteamslost(void) for (emptyPlayerSpots = 0, i = 0; i < gBattlersCount; i += 2) { - if ((gHitMarker & HITMARKER_FAINTED2(i)) && (!gSpecialStatuses[i].faintedHasReplacement)) + if ((gHitMarker & HITMARKER_FAINTED(i)) && (!gSpecialStatuses[i].faintedHasReplacement)) emptyPlayerSpots++; } emptyOpponentSpots = 0; for (i = 1; i < gBattlersCount; i += 2) { - if ((gHitMarker & HITMARKER_FAINTED2(i)) && (!gSpecialStatuses[i].faintedHasReplacement)) + if ((gHitMarker & HITMARKER_FAINTED(i)) && (!gSpecialStatuses[i].faintedHasReplacement)) emptyOpponentSpots++; } @@ -5010,8 +5024,8 @@ static void MoveValuesCleanUp(void) gBattleScripting.moveEffect = MOVE_EFFECT_NONE; gBattleStruct->synchronizeMoveEffect = MOVE_EFFECT_NONE; gBattleCommunication[MISS_TYPE] = 0; - if (!gMultiHitCounter) - gHitMarker &= ~HITMARKER_DESTINYBOND; + gBattleStruct->tryDestinyBond = FALSE; + gBattleStruct->tryGrudge = FALSE; } static void Cmd_movevaluescleanup(void) @@ -5361,21 +5375,29 @@ static void Cmd_waitstate(void) gBattlescriptCurrInstr = cmd->nextInstr; } -static void Cmd_absorb(void) +static void Cmd_isdmgblockedbydisguise(void) { - CMD_ARGS(u8 battler); + CMD_ARGS(); - if (gBattleControllerExecFlags) + if (!IsMimikyuDisguised(gBattlerAttacker) + || gBattleMons[gBattlerAttacker].volatiles.transformed + || !IsAbilityAndRecord(gBattlerAttacker, GetBattlerAbility(gBattlerAttacker), ABILITY_DISGUISE)) + { + gBattlescriptCurrInstr = cmd->nextInstr; return; + } - u32 battler = GetBattlerForBattleScript(cmd->battler); - BtlController_EmitHealthBarUpdate(battler, B_COMM_TO_CONTROLLER, gBattleStruct->moveDamage[battler]); - MarkBattlerForControllerExec(battler); - - if (IsOnPlayerSide(battler) && gBattleStruct->moveDamage[battler] > 0) - gBattleResults.playerMonWasDamaged = TRUE; - - gBattlescriptCurrInstr = cmd->nextInstr; + gBattleScripting.battler = gBattlerAttacker; + if (GetBattlerPartyState(gBattlerAttacker)->changedSpecies == SPECIES_NONE) + GetBattlerPartyState(gBattlerAttacker)->changedSpecies = gBattleMons[gBattlerAttacker].species; + if (gBattleMons[gBattlerAttacker].species == SPECIES_MIMIKYU_TOTEM_DISGUISED) + gBattleMons[gBattlerAttacker].species = SPECIES_MIMIKYU_BUSTED_TOTEM; + else + gBattleMons[gBattlerAttacker].species = SPECIES_MIMIKYU_BUSTED; + if (GetConfig(CONFIG_DISGUISE_HP_LOSS) >= GEN_8) + SetPassiveDamageAmount(gBattlerAttacker, GetNonDynamaxMaxHP(gBattlerAttacker) / 8); + BattleScriptPush(BattleScript_MoveEnd); + gBattlescriptCurrInstr = BattleScript_TargetFormChange; } static void Cmd_return(void) @@ -5424,18 +5446,15 @@ static void Cmd_setroost(void) CMD_ARGS(); gDisableStructs[gBattlerAttacker].roostActive = TRUE; - gBattleStruct->roostTypes[gBattlerAttacker][0] = gBattleMons[gBattlerAttacker].types[0]; - gBattleStruct->roostTypes[gBattlerAttacker][1] = gBattleMons[gBattlerAttacker].types[1]; - gBattlescriptCurrInstr = cmd->nextInstr; } static void Cmd_jumpifabilitypresent(void) { - CMD_ARGS(u16 ability, const u8 *jumpInstr); + CMD_ARGS(enum Ability ability, const u8 *jumpInstr); - u16 ability = cmd->ability; - u32 abilityBattler = IsAbilityOnField(ability); + enum Ability ability = cmd->ability; + enum Ability abilityBattler = IsAbilityOnField(ability); if (abilityBattler) { gBattlerAbility = abilityBattler - 1; @@ -5450,8 +5469,7 @@ static void Cmd_jumpifabilitypresent(void) static void Cmd_endselectionscript(void) { CMD_ARGS(); - - *(gBattlerAttacker + gBattleStruct->selectionScriptFinished) = TRUE; + gBattleStruct->battlerState[gBattlerAttacker].selectionScriptFinished = TRUE; } static void PlayAnimation(u32 battler, u8 animId, const u16 *argPtr, const u8 *nextInstr) @@ -5565,7 +5583,7 @@ static u32 GetNextTarget(u32 moveTarget, bool32 excludeCurrent) return battler; } -static inline bool32 IsProtectivePadsProtected(u32 battler, enum ItemHoldEffect holdEffect) +static inline bool32 IsProtectivePadsProtected(u32 battler, enum HoldEffect holdEffect) { if (holdEffect != HOLD_EFFECT_PROTECTIVE_PADS) return FALSE; @@ -5576,7 +5594,7 @@ static inline bool32 IsProtectivePadsProtected(u32 battler, enum ItemHoldEffect static inline bool32 CanEjectButtonTrigger(u32 battlerAtk, u32 battlerDef, enum BattleMoveEffects moveEffect) { - if (GetBattlerHoldEffect(battlerDef, TRUE) == HOLD_EFFECT_EJECT_BUTTON + if (GetBattlerHoldEffect(battlerDef) == HOLD_EFFECT_EJECT_BUTTON && battlerAtk != battlerDef && IsBattlerTurnDamaged(battlerDef) && IsBattlerAlive(battlerDef) @@ -5590,7 +5608,7 @@ static inline bool32 CanEjectButtonTrigger(u32 battlerAtk, u32 battlerDef, enum static inline bool32 CanEjectPackTrigger(u32 battlerAtk, u32 battlerDef, enum BattleMoveEffects moveEffect) { if (gDisableStructs[battlerDef].tryEjectPack - && GetBattlerHoldEffect(battlerDef, TRUE) == HOLD_EFFECT_EJECT_PACK + && GetBattlerHoldEffect(battlerDef) == HOLD_EFFECT_EJECT_PACK && IsBattlerAlive(battlerDef) && CountUsablePartyMons(battlerDef) > 0 && !gProtectStructs[battlerDef].disableEjectPack @@ -5604,7 +5622,7 @@ static inline bool32 CanEjectPackTrigger(u32 battlerAtk, u32 battlerDef, enum Ba static bool32 HandleMoveEndAbilityBlock(u32 battlerAtk, u32 battlerDef, u32 move) { bool32 effect = FALSE; - u32 abilityAtk = GetBattlerAbility(battlerAtk); + enum Ability abilityAtk = GetBattlerAbility(battlerAtk); switch (abilityAtk) { @@ -5669,7 +5687,7 @@ static bool32 HandleMoveEndAbilityBlock(u32 battlerAtk, u32 battlerDef, u32 move if (!IsBattlerAlive(battlerAtk) || NoAliveMonsForEitherParty()) break; - u32 stat = STAT_ATK; + enum Stat stat = STAT_ATK; u32 numMonsFainted = NumFaintedBattlersByAttacker(battlerAtk); if (abilityAtk == ABILITY_BEAST_BOOST) @@ -5703,7 +5721,7 @@ static bool32 HandleMoveEndAbilityBlock(u32 battlerAtk, u32 battlerDef, u32 move if (GetBattlerPartyState(battlerAtk)->battleBondBoost) break; - if (GetGenConfig(GEN_CONFIG_BATTLE_BOND) < GEN_9 && gBattleMons[battlerAtk].species == SPECIES_GRENINJA_BATTLE_BOND) + if (GetConfig(CONFIG_BATTLE_BOND) < GEN_9 && gBattleMons[battlerAtk].species == SPECIES_GRENINJA_BATTLE_BOND) { // TODO: Convert this to a proper FORM_CHANGE type. gLastUsedAbility = abilityAtk; @@ -5747,6 +5765,8 @@ static bool32 HandleMoveEndAbilityBlock(u32 battlerAtk, u32 battlerDef, u32 move } } break; + default: + break; } return effect; @@ -5757,17 +5777,29 @@ static bool32 HandleMoveEndMoveBlock(u32 moveEffect) if (gHitMarker & HITMARKER_UNABLE_TO_USE_MOVE) return FALSE; - u32 effect = FALSE; - u32 side = GetBattlerSide(gBattlerTarget); + bool32 effect = FALSE; + enum BattleSide side = GetBattlerSide(gBattlerTarget); switch (moveEffect) { case EFFECT_KNOCK_OFF: - if (gBattleStruct->battlerState[gBattlerTarget].itemCanBeKnockedOff - && gBattleMons[gBattlerTarget].item != ITEM_NONE - && IsBattlerTurnDamaged(gBattlerTarget) + if (gBattleMons[gBattlerTarget].item != ITEM_NONE && IsBattlerAlive(gBattlerAttacker) - && !(B_KNOCK_OFF_REMOVAL >= GEN_5 && side == B_SIDE_PLAYER && !(gBattleTypeFlags & BATTLE_TYPE_TRAINER))) + && !(B_KNOCK_OFF_REMOVAL >= GEN_5 && side == B_SIDE_PLAYER && !(gBattleTypeFlags & BATTLE_TYPE_TRAINER)) + && IsBattlerTurnDamaged(gBattlerTarget) + && !DoesSubstituteBlockMove(gBattlerAttacker, gBattlerTarget, gCurrentMove) + && CanBattlerGetOrLoseItem(gBattlerTarget, gBattleMons[gBattlerTarget].item) + && !NoAliveMonsForEitherParty()) { + u32 side = GetBattlerSide(gBattlerTarget); + + if (GetBattlerAbility(gBattlerTarget) == ABILITY_STICKY_HOLD) + { + gBattlerAbility = gBattlerTarget; + BattleScriptPushCursor(); + gBattlescriptCurrInstr = BattleScript_StickyHoldActivatesRet; + effect = TRUE; + break; + } gLastUsedItem = gBattleMons[gBattlerTarget].item; gBattleMons[gBattlerTarget].item = 0; if (gBattleMons[gBattlerTarget].ability != ABILITY_GORILLA_TACTICS) @@ -5787,11 +5819,9 @@ static bool32 HandleMoveEndMoveBlock(u32 moveEffect) gWishFutureKnock.knockedOffMons[side] |= 1u << gBattlerPartyIndexes[gBattlerTarget]; } - gBattleStruct->battlerState[gBattlerTarget].itemCanBeKnockedOff = FALSE; BattleScriptCall(BattleScript_KnockedOff); effect = TRUE; } - gBattleStruct->battlerState[gBattlerTarget].itemCanBeKnockedOff = FALSE; break; case EFFECT_STEAL_ITEM: if (!CanStealItem(gBattlerAttacker, gBattlerTarget, gBattleMons[gBattlerTarget].item) @@ -5813,7 +5843,7 @@ static bool32 HandleMoveEndMoveBlock(u32 moveEffect) { StealTargetItem(gBattlerAttacker, gBattlerTarget); // Attacker steals target item - if (!(GetGenConfig(GEN_STEAL_WILD_ITEMS) >= GEN_9 + if (!(GetConfig(CONFIG_STEAL_WILD_ITEMS) >= GEN_9 && !(gBattleTypeFlags & (BATTLE_TYPE_TRAINER | BATTLE_TYPE_PALACE)))) { gBattleMons[gBattlerAttacker].item = ITEM_NONE; // Item assigned later on with thief (see MOVEEND_CHANGED_ITEMS) @@ -5855,7 +5885,7 @@ static bool32 HandleMoveEndMoveBlock(u32 moveEffect) } break; case EFFECT_SMACK_DOWN: - if (!IsBattlerGrounded(gBattlerTarget) + if (!IsBattlerGrounded(gBattlerTarget, GetBattlerAbility(gBattlerTarget), GetBattlerHoldEffect(gBattlerTarget)) && IsBattlerTurnDamaged(gBattlerTarget) && IsBattlerAlive(gBattlerTarget) && !DoesSubstituteBlockMove(gBattlerAttacker, gBattlerTarget, gCurrentMove)) @@ -5873,24 +5903,32 @@ static bool32 HandleMoveEndMoveBlock(u32 moveEffect) && (!IsBattlerTurnDamaged(gBattlerTarget) || gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_NO_EFFECT) && !gBattleStruct->noTargetPresent) { + s32 recoil = 0; if (B_RECOIL_IF_MISS_DMG >= GEN_5 || (B_CRASH_IF_TARGET_IMMUNE == GEN_4 && gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_DOESNT_AFFECT_FOE)) - gBattleStruct->moveDamage[gBattlerAttacker] = GetNonDynamaxMaxHP(gBattlerAttacker) / 2; + recoil = GetNonDynamaxMaxHP(gBattlerAttacker) / 2; else if (B_RECOIL_IF_MISS_DMG == GEN_4 && (GetNonDynamaxMaxHP(gBattlerTarget) / 2) < gBattleStruct->moveDamage[gBattlerTarget]) - gBattleStruct->moveDamage[gBattlerAttacker] = GetNonDynamaxMaxHP(gBattlerTarget) / 2; - else // Fallback if B_RECOIL_IF_MISS_DMG is set to gen3 or lower. - gBattleStruct->moveDamage[gBattlerAttacker] = GetNonDynamaxMaxHP(gBattlerTarget) / 2; - - if (gBattleStruct->moveDamage[gBattlerAttacker] == 0) - gBattleStruct->moveDamage[gBattlerAttacker] = 1; - + recoil = GetNonDynamaxMaxHP(gBattlerTarget) / 2; + else if (B_RECOIL_IF_MISS_DMG == GEN_3) + recoil = GetNonDynamaxMaxHP(gBattlerTarget) / 2; + else if (B_RECOIL_IF_MISS_DMG == GEN_2) + recoil = GetNonDynamaxMaxHP(gBattlerTarget) / 8; + else + recoil = 1; + SetPassiveDamageAmount(gBattlerAttacker, recoil); BattleScriptCall(BattleScript_RecoilIfMiss); effect = TRUE; } break; case EFFECT_RECOIL: - if (IsBattlerTurnDamaged(gBattlerTarget) && IsBattlerAlive(gBattlerAttacker)) + if (IsBattlerTurnDamaged(gBattlerTarget) && IsBattlerAlive(gBattlerAttacker) && gBattleStruct->moveDamage[gBattlerTarget] > 0) { - gBattleStruct->moveDamage[gBattlerAttacker] = max(1, gBattleScripting.savedDmg * max(1, GetMoveRecoil(gCurrentMove)) / 100); + enum Ability ability = GetBattlerAbility(gBattlerAttacker); + if (IsAbilityAndRecord(gBattlerAttacker, ability, ABILITY_ROCK_HEAD) + || IsAbilityAndRecord(gBattlerAttacker, ability, ABILITY_MAGIC_GUARD)) + break; + + SetPassiveDamageAmount(gBattlerAttacker, gBattleScripting.savedDmg * max(1, GetMoveRecoil(gCurrentMove)) / 100); + TryUpdateEvolutionTracker(IF_RECOIL_DAMAGE_GE, gBattleStruct->passiveHpUpdate[gBattlerAttacker], MOVE_NONE); BattleScriptCall(BattleScript_MoveEffectRecoil); effect = TRUE; } @@ -5899,7 +5937,7 @@ static bool32 HandleMoveEndMoveBlock(u32 moveEffect) case EFFECT_MISTY_EXPLOSION: if (!IsAbilityOnField(ABILITY_DAMP)) { - gBattleStruct->moveDamage[gBattlerAttacker] = 0; + gBattleStruct->passiveHpUpdate[gBattlerAttacker] = 0; BattleScriptCall(BattleScript_FaintAttackerForExplosion); effect = TRUE; } @@ -5907,9 +5945,11 @@ static bool32 HandleMoveEndMoveBlock(u32 moveEffect) case EFFECT_MAX_HP_50_RECOIL: if (IsBattlerAlive(gBattlerAttacker) && !(gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_FAILED) - && GetBattlerAbility(gBattlerAttacker) != ABILITY_MAGIC_GUARD) + && !IsAbilityAndRecord(gBattlerAttacker, GetBattlerAbility(gBattlerAttacker), ABILITY_MAGIC_GUARD)) { - gBattleStruct->moveDamage[gBattlerAttacker] = (GetNonDynamaxMaxHP(gBattlerAttacker) + 1) / 2; // Half of Max HP Rounded UP + s32 recoil = (GetNonDynamaxMaxHP(gBattlerAttacker) + 1) / 2; // Half of Max HP Rounded UP + SetPassiveDamageAmount(gBattlerAttacker, recoil); + TryUpdateEvolutionTracker(IF_RECOIL_DAMAGE_GE, gBattleStruct->passiveHpUpdate[gBattlerAttacker], MOVE_NONE); BattleScriptCall(BattleScript_MaxHp50Recoil); effect = TRUE; } @@ -5917,7 +5957,14 @@ static bool32 HandleMoveEndMoveBlock(u32 moveEffect) case EFFECT_CHLOROBLAST: if (IsBattlerTurnDamaged(gBattlerTarget) && IsBattlerAlive(gBattlerAttacker)) { - gBattleStruct->moveDamage[gBattlerAttacker] = (GetNonDynamaxMaxHP(gBattlerAttacker) + 1) / 2; // Half of Max HP Rounded UP + enum Ability ability = GetBattlerAbility(gBattlerAttacker); + if (IsAbilityAndRecord(gBattlerAttacker, ability, ABILITY_ROCK_HEAD) + || IsAbilityAndRecord(gBattlerAttacker, ability, ABILITY_MAGIC_GUARD)) + break; + + s32 recoil = (GetNonDynamaxMaxHP(gBattlerAttacker) + 1) / 2; // Half of Max HP Rounded UP + SetPassiveDamageAmount(gBattlerAttacker, recoil); + TryUpdateEvolutionTracker(IF_RECOIL_DAMAGE_GE, gBattleStruct->passiveHpUpdate[gBattlerAttacker], MOVE_NONE); BattleScriptCall(BattleScript_MoveEffectRecoil); effect = TRUE; } @@ -5936,7 +5983,7 @@ static bool32 HandleMoveEndMoveBlock(u32 moveEffect) && !NoAliveMonsForEitherParty() && CompareStat(gBattlerAttacker, STAT_ATK, MAX_STAT_STAGE, CMP_LESS_THAN, GetBattlerAbility(gBattlerAttacker))) { - SET_STATCHANGER(STAT_ATK, GetGenConfig(GEN_CONFIG_FELL_STINGER_STAT_RAISE) >= GEN_7 ? 3 : 2, FALSE); + SET_STATCHANGER(STAT_ATK, GetConfig(CONFIG_FELL_STINGER_STAT_RAISE) >= GEN_7 ? 3 : 2, FALSE); PREPARE_STAT_BUFFER(gBattleTextBuff1, STAT_ATK); BattleScriptPushCursor(); gBattlescriptCurrInstr = BattleScript_FellStingerRaisesStat; @@ -6007,8 +6054,9 @@ static void Cmd_moveend(void) { switch (gBattleScripting.moveendState) { - case MOVEEND_SUM_DAMAGE: // Sum and store damage dealt for multi strike recoil + case MOVEEND_SET_VALUES: gBattleScripting.savedDmg += gBattleStruct->moveDamage[gBattlerTarget]; + gBattleStruct->eventState.moveEndBattler = 0; gBattleScripting.moveendState++; break; case MOVEEND_PROTECT_LIKE_EFFECT: @@ -6019,25 +6067,21 @@ static void Cmd_moveend(void) { case PROTECT_SPIKY_SHIELD: if (moveEffect != EFFECT_COUNTER - && !IsProtectivePadsProtected(gBattlerAttacker, GetBattlerHoldEffect(gBattlerAttacker, TRUE)) + && !IsProtectivePadsProtected(gBattlerAttacker, GetBattlerHoldEffect(gBattlerAttacker)) && !IsAbilityAndRecord(gBattlerAttacker, GetBattlerAbility(gBattlerAttacker), ABILITY_MAGIC_GUARD)) { gProtectStructs[gBattlerAttacker].touchedProtectLike = FALSE; - gBattleStruct->moveDamage[gBattlerAttacker] = GetNonDynamaxMaxHP(gBattlerAttacker) / 8; - if (gBattleStruct->moveDamage[gBattlerAttacker] == 0) - gBattleStruct->moveDamage[gBattlerAttacker] = 1; + SetPassiveDamageAmount(gBattlerAttacker, GetNonDynamaxMaxHP(gBattlerAttacker) / 8); PREPARE_MOVE_BUFFER(gBattleTextBuff1, MOVE_SPIKY_SHIELD); BattleScriptCall(BattleScript_SpikyShieldEffect); effect = 1; } break; case PROTECT_KINGS_SHIELD: - if (!IsProtectivePadsProtected(gBattlerAttacker, GetBattlerHoldEffect(gBattlerAttacker, TRUE))) + if (!IsProtectivePadsProtected(gBattlerAttacker, GetBattlerHoldEffect(gBattlerAttacker))) { gProtectStructs[gBattlerAttacker].touchedProtectLike = FALSE; - i = gBattlerAttacker; - gBattlerAttacker = gBattlerTarget; - gBattlerTarget = i; // gBattlerTarget and gBattlerAttacker are swapped in order to activate Defiant, if applicable + SWAP(gBattlerAttacker, gBattlerTarget, i); // gBattlerTarget and gBattlerAttacker are swapped in order to activate Defiant, if applicable if (B_KINGS_SHIELD_LOWER_ATK >= GEN_8) gBattleScripting.moveEffect = MOVE_EFFECT_ATK_MINUS_1; else @@ -6047,49 +6091,40 @@ static void Cmd_moveend(void) } break; case PROTECT_BANEFUL_BUNKER: - if (!IsProtectivePadsProtected(gBattlerAttacker, GetBattlerHoldEffect(gBattlerAttacker, TRUE)) + if (!IsProtectivePadsProtected(gBattlerAttacker, GetBattlerHoldEffect(gBattlerAttacker)) && CanBePoisoned(gBattlerTarget, gBattlerAttacker, gLastUsedAbility, GetBattlerAbility(gBattlerAttacker))) { gProtectStructs[gBattlerAttacker].touchedProtectLike = FALSE; gBattleScripting.moveEffect = MOVE_EFFECT_POISON; - PREPARE_MOVE_BUFFER(gBattleTextBuff1, MOVE_BANEFUL_BUNKER); BattleScriptCall(BattleScript_BanefulBunkerEffect); effect = 1; } break; case PROTECT_BURNING_BULWARK: - if (!IsProtectivePadsProtected(gBattlerAttacker, GetBattlerHoldEffect(gBattlerAttacker, TRUE)) + if (!IsProtectivePadsProtected(gBattlerAttacker, GetBattlerHoldEffect(gBattlerAttacker)) && CanBeBurned(gBattlerTarget, gBattlerAttacker, GetBattlerAbility(gBattlerAttacker))) { - gEffectBattler = gProtectStructs[gBattlerAttacker].touchedProtectLike = FALSE; gBattleScripting.moveEffect = MOVE_EFFECT_BURN; - PREPARE_MOVE_BUFFER(gBattleTextBuff1, MOVE_BURNING_BULWARK); BattleScriptCall(BattleScript_BanefulBunkerEffect); effect = 1; } break; case PROTECT_OBSTRUCT: - if (moveEffect != EFFECT_SUCKER_PUNCH // Why??? - && moveEffect != EFFECT_UPPER_HAND // Why??? - && !IsProtectivePadsProtected(gBattlerAttacker, GetBattlerHoldEffect(gBattlerAttacker, TRUE))) + if (!IsProtectivePadsProtected(gBattlerAttacker, GetBattlerHoldEffect(gBattlerAttacker))) { gProtectStructs[gBattlerAttacker].touchedProtectLike = FALSE; - i = gBattlerAttacker; - gBattlerAttacker = gBattlerTarget; - gBattlerTarget = i; // gBattlerTarget and gBattlerAttacker are swapped in order to activate Defiant, if applicable + SWAP(gBattlerAttacker, gBattlerTarget, i); // gBattlerTarget and gBattlerAttacker are swapped in order to activate Defiant, if applicable gBattleScripting.moveEffect = MOVE_EFFECT_DEF_MINUS_2; BattleScriptCall(BattleScript_KingsShieldEffect); effect = 1; } break; case PROTECT_SILK_TRAP: - if (!IsProtectivePadsProtected(gBattlerAttacker, GetBattlerHoldEffect(gBattlerAttacker, TRUE))) + if (!IsProtectivePadsProtected(gBattlerAttacker, GetBattlerHoldEffect(gBattlerAttacker))) { gProtectStructs[gBattlerAttacker].touchedProtectLike = FALSE; - i = gBattlerAttacker; - gBattlerAttacker = gBattlerTarget; - gBattlerTarget = i; // gBattlerTarget and gBattlerAttacker are swapped in order to activate Defiant, if applicable + SWAP(gBattlerAttacker, gBattlerTarget, i); // gBattlerTarget and gBattlerAttacker are swapped in order to activate Defiant, if applicable gBattleScripting.moveEffect = MOVE_EFFECT_SPD_MINUS_1; BattleScriptCall(BattleScript_KingsShieldEffect); effect = 1; @@ -6100,7 +6135,7 @@ static void Cmd_moveend(void) } // Not strictly a protect effect, but works the same way - if (gProtectStructs[gBattlerTarget].beakBlastCharge + if (IsBattlerUsingBeakBlast(gBattlerTarget) && CanBeBurned(gBattlerAttacker, gBattlerAttacker, GetBattlerAbility(gBattlerAttacker)) && !(gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_NO_EFFECT)) { @@ -6114,6 +6149,43 @@ static void Cmd_moveend(void) } gBattleScripting.moveendState++; break; + + case MOVEEND_GRUDGE: + if (gBattleStruct->tryGrudge + && IsBattlerTurnDamaged(gBattlerTarget) + && !IsBattlerAlive(gBattlerTarget) + && IsBattlerAlive(gBattlerAttacker) + && !IsBattlerAlly(gBattlerAttacker, gBattlerTarget) + && !IsZMove(gCurrentMove) + && gCurrentMove != MOVE_STRUGGLE) + { + u32 moveIndex = gBattleStruct->chosenMovePositions[gBattlerAttacker]; + + gBattleStruct->tryGrudge = FALSE; + gBattleMons[gBattlerAttacker].pp[moveIndex] = 0; + BattleScriptCall(BattleScript_GrudgeTakesPp); + BtlController_EmitSetMonData(gBattlerAttacker, B_COMM_TO_CONTROLLER, moveIndex + REQUEST_PPMOVE1_BATTLE, 0, sizeof(gBattleMons[gBattlerAttacker].pp[moveIndex]), &gBattleMons[gBattlerAttacker].pp[moveIndex]); + MarkBattlerForControllerExec(gBattlerAttacker); + PREPARE_MOVE_BUFFER(gBattleTextBuff1, gBattleMons[gBattlerAttacker].moves[moveIndex]) + } + gBattleScripting.moveendState++; + break; + + case MOVEEND_DESTINY_BOND: + if (gBattleStruct->tryDestinyBond + && IsBattlerTurnDamaged(gBattlerTarget) + && !IsBattlerAlive(gBattlerTarget) + && IsBattlerAlive(gBattlerAttacker) + && !(GetActiveGimmick(gBattlerAttacker) == GIMMICK_DYNAMAX) + && !IsBattlerAlly(gBattlerAttacker, gBattlerTarget)) + { + gBattleStruct->tryDestinyBond = FALSE; + gBattleStruct->passiveHpUpdate[gBattlerAttacker] = gBattleMons[gBattlerAttacker].hp; + BattleScriptCall(BattleScript_DestinyBondTakesLife); + effect = TRUE; + } + gBattleScripting.moveendState++; + break; case MOVEEND_ABSORB: if (gHitMarker & HITMARKER_UNABLE_TO_USE_MOVE || !IsBattlerTurnDamaged(gBattlerTarget)) @@ -6129,20 +6201,19 @@ static void Cmd_moveend(void) && gBattleStruct->moveDamage[gBattlerTarget] > 0 && IsBattlerAlive(gBattlerAttacker)) { - gBattleStruct->moveDamage[gBattlerAttacker] = max(1, (gBattleStruct->moveDamage[gBattlerTarget] * GetMoveAbsorbPercentage(gCurrentMove) / 100)); - gBattleStruct->moveDamage[gBattlerAttacker] = GetDrainedBigRootHp(gBattlerAttacker, gBattleStruct->moveDamage[gBattlerAttacker]); - - gHitMarker |= HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_IGNORE_DISGUISE | HITMARKER_PASSIVE_HP_UPDATE; + s32 healAmount = (gBattleStruct->moveDamage[gBattlerTarget] * GetMoveAbsorbPercentage(gCurrentMove) / 100); + healAmount = GetDrainedBigRootHp(gBattlerAttacker, healAmount); effect = TRUE; - if ((moveEffect == EFFECT_DREAM_EATER && GetGenConfig(GEN_DREAM_EATER_LIQUID_OOZE) < GEN_5) + if ((moveEffect == EFFECT_DREAM_EATER && GetConfig(CONFIG_DREAM_EATER_LIQUID_OOZE) < GEN_5) || GetBattlerAbility(gBattlerTarget) != ABILITY_LIQUID_OOZE) { + SetHealAmount(gBattlerAttacker, healAmount); gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_ABSORB; BattleScriptCall(BattleScript_EffectAbsorb); } - else + else // Liquid Ooze damage { - gBattleStruct->moveDamage[gBattlerAttacker] *= -1; + SetPassiveDamageAmount(gBattlerAttacker, healAmount); gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_ABSORB_OOZE; BattleScriptCall(BattleScript_EffectAbsorbLiquidOoze); } @@ -6195,7 +6266,7 @@ static void Cmd_moveend(void) if (AbilityBattleEffects(ABILITYEFFECT_IMMUNITY, battler, 0, 0, 0)) effect = TRUE; } - if(!effect) + if (!effect) gBattleScripting.moveendState++; break; case MOVEEND_SYNCHRONIZE_ATTACKER: // attacker synchronize @@ -6204,15 +6275,29 @@ static void Cmd_moveend(void) gBattleScripting.moveendState++; break; case MOVEEND_ITEM_EFFECTS_TARGET: - if (ItemBattleEffects(ITEMEFFECT_TARGET, gBattlerTarget)) + { + enum HoldEffect holdEffect = GetBattlerHoldEffect(gBattlerTarget); + if (ItemBattleEffects(gBattlerTarget, gBattlerAttacker, holdEffect, IsOnTargetHitActivation) + || ItemBattleEffects(gBattlerTarget, gBattlerAttacker, holdEffect, IsOnStatusChangeActivation)) effect = TRUE; gBattleScripting.moveendState++; break; + } + case MOVEEND_ITEM_EFFECTS_ATTACKER_1: + { + enum HoldEffect holdEffect = GetBattlerHoldEffect(gBattlerAttacker); + if (ItemBattleEffects(gBattlerAttacker, gBattlerTarget, holdEffect, IsOnAttackerAfterHitActivation) + || ItemBattleEffects(gBattlerAttacker, gBattlerTarget, holdEffect, IsOnStatusChangeActivation) + || ItemBattleEffects(gBattlerAttacker, gBattlerTarget, holdEffect, IsOnHpThresholdActivation)) + effect = TRUE; + gBattleScripting.moveendState++; + break; + } case MOVEEND_SYMBIOSIS: for (i = 0; i < gBattlersCount; i++) { if ((gSpecialStatuses[i].berryReduced - || (B_SYMBIOSIS_GEMS >= GEN_7 && gSpecialStatuses[i].gemBoost)) + || (GetConfig(CONFIG_SYMBIOSIS_GEMS) >= GEN_7 && gSpecialStatuses[i].gemBoost)) && TryTriggerSymbiosis(i, BATTLE_PARTNER(i))) { BestowItem(BATTLE_PARTNER(i), i); @@ -6227,12 +6312,6 @@ static void Cmd_moveend(void) } gBattleScripting.moveendState++; break; - case MOVEEND_ITEM_EFFECTS_ALL: // item effects for all battlers - if (ItemBattleEffects(ITEMEFFECT_MOVE_END, 0)) - effect = TRUE; - else - gBattleScripting.moveendState++; - break; case MOVEEND_ATTACKER_INVISIBLE: // make attacker sprite invisible if (IsSemiInvulnerable(gBattlerAttacker, CHECK_ALL) && gHitMarker & (HITMARKER_NO_ANIMATIONS | HITMARKER_DISABLE_ANIMATION)) @@ -6270,12 +6349,6 @@ static void Cmd_moveend(void) } gBattleScripting.moveendState++; break; - case MOVEEND_KINGSROCK: // King's rock - // These effects will occur at each hit in a multi-strike move - if (ItemBattleEffects(ITEMEFFECT_KINGSROCK, 0)) - effect = TRUE; - gBattleScripting.moveendState++; - break; case MOVEEND_SUBSTITUTE: for (i = 0; i < gBattlersCount; i++) { @@ -6315,7 +6388,7 @@ static void Cmd_moveend(void) if (!IsOnPlayerSide(gBattlerAttacker)) UpdateStallMons(); if ((gBattleStruct->moveResultFlags[gBattlerTarget] & (MOVE_RESULT_FAILED | MOVE_RESULT_DOESNT_AFFECT_FOE)) - || (gBattleMons[gBattlerAttacker].volatiles.flinched) + || gBattleMons[gBattlerAttacker].volatiles.flinched || gBattleStruct->pledgeMove == TRUE // Is the battler that uses the first Pledge move in the combo || gProtectStructs[gBattlerAttacker].nonVolatileStatusImmobility) gBattleStruct->battlerState[gBattlerAttacker].stompingTantrumTimer = 2; @@ -6348,17 +6421,12 @@ static void Cmd_moveend(void) { gDisableStructs[gBattlerAttacker].usedMoves |= 1u << gCurrMovePos; gBattleStruct->lastMoveTarget[gBattlerAttacker] = gBattlerTarget; - if (gHitMarker & HITMARKER_ATTACKSTRING_PRINTED) - { - gLastPrintedMoves[gBattlerAttacker] = gChosenMove; - gLastUsedMove = gCurrentMove; - if (IsMaxMove(gCurrentMove)) - gBattleStruct->dynamax.lastUsedBaseMove = gBattleStruct->dynamax.baseMoves[gBattlerAttacker]; - } } enum BattleMoveEffects originalEffect = GetMoveEffect(originallyUsedMove); - if (!(gAbsentBattlerFlags & (1u << gBattlerAttacker)) - && originalEffect != EFFECT_BATON_PASS && originalEffect != EFFECT_HEALING_WISH) + if (IsBattlerAlive(gBattlerAttacker) + && originalEffect != EFFECT_BATON_PASS + && originalEffect != EFFECT_HEALING_WISH + && originalEffect != EFFECT_LUNAR_DANCE) { if (gHitMarker & HITMARKER_OBEYS) { @@ -6390,6 +6458,12 @@ static void Cmd_moveend(void) { gLastLandedMoves[gBattlerTarget] = gCurrentMove; gLastHitByType[gBattlerTarget] = GetBattleMoveType(gCurrentMove); + if (!gSpecialStatuses[gBattlerAttacker].dancerUsedMove) + { + gLastUsedMove = gCurrentMove; + if (IsMaxMove(gCurrentMove)) + gBattleStruct->dynamax.lastUsedBaseMove = gBattleStruct->dynamax.baseMoves[gBattlerAttacker]; + } } } else @@ -6450,11 +6524,9 @@ static void Cmd_moveend(void) && IsDoubleBattle() && !gProtectStructs[gBattlerAttacker].chargingTurn && (moveTarget == MOVE_TARGET_BOTH - || moveTarget == MOVE_TARGET_FOES_AND_ALLY) - && !(gHitMarker & HITMARKER_NO_ATTACKSTRING)) + || moveTarget == MOVE_TARGET_FOES_AND_ALLY)) { u32 nextTarget = GetNextTarget(moveTarget, FALSE); - gHitMarker |= HITMARKER_NO_PPDEDUCT; if (nextTarget != MAX_BATTLERS_COUNT) { @@ -6462,8 +6534,12 @@ static void Cmd_moveend(void) gBattleScripting.moveendState = 0; MoveValuesCleanUp(); - if (moveEffect == EFFECT_EXPLOSION || moveEffect == EFFECT_MISTY_EXPLOSION // Edge case for Explosion not changing targets - || moveEffect == EFFECT_SYNCHRONOISE) // So we don't go back to the Synchronoise script + // Edge cases for moves that shouldn't repeat their own script + if (moveEffect == EFFECT_EXPLOSION + || moveEffect == EFFECT_MISTY_EXPLOSION + || moveEffect == EFFECT_MAGNITUDE + || moveEffect == EFFECT_SYNCHRONOISE + || gBattleMoveEffects[moveEffect].battleScript == BattleScript_EffectTwoTurnsAttack) BattleScriptPush(gBattleMoveEffects[EFFECT_HIT].battleScript); else BattleScriptPush(GetMoveBattleScript(gCurrentMove)); @@ -6493,14 +6569,17 @@ static void Cmd_moveend(void) return; } } - - gHitMarker |= HITMARKER_NO_ATTACKSTRING; - gHitMarker &= ~HITMARKER_NO_PPDEDUCT; } RecordLastUsedMoveBy(gBattlerAttacker, gCurrentMove); gBattleScripting.moveendState++; break; } + case MOVEEND_HP_THRESHHOLD_ITEMS_TARGET: + if (gMultiHitCounter + && ItemBattleEffects(gBattlerTarget, gBattlerAttacker, GetBattlerHoldEffect(gBattlerTarget), IsOnHpThresholdActivation)) + effect = TRUE; + gBattleScripting.moveendState++; + break; case MOVEEND_MULTIHIT_MOVE: { if (!(gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_NO_EFFECT) @@ -6542,7 +6621,6 @@ static void Cmd_moveend(void) if (gSpecialStatuses[gBattlerAttacker].parentalBondState) gSpecialStatuses[gBattlerAttacker].parentalBondState--; - gHitMarker |= (HITMARKER_NO_PPDEDUCT | HITMARKER_NO_ATTACKSTRING); gBattleScripting.animTargetsHit = 0; gBattleScripting.moveendState = 0; gSpecialStatuses[gBattlerAttacker].multiHitOn = TRUE; @@ -6568,31 +6646,15 @@ static void Cmd_moveend(void) effect = HandleMoveEndMoveBlock(moveEffect); gBattleScripting.moveendState++; break; - case MOVEEND_ITEM_EFFECTS_ATTACKER: - // ITEMEFFECT_MOVE_END loops over all battlers, not just attacker. - // It will executre only the first mon with an applicable item. - // So presumably it is a bug - if (ItemBattleEffects(ITEMEFFECT_MOVE_END, gBattlerAttacker)) + case MOVEEND_ITEM_EFFECTS_ATTACKER_2: + { + enum HoldEffect holdEffect = GetBattlerHoldEffect(gBattlerAttacker); + if (ItemBattleEffects(gBattlerAttacker, gBattlerTarget, holdEffect, IsOnStatusChangeActivation) + || ItemBattleEffects(gBattlerAttacker, gBattlerTarget, holdEffect, IsOnHpThresholdActivation)) effect = TRUE; gBattleScripting.moveendState++; break; - case MOVEEND_ITEM_THROAT_SPRAY: - if (IsSoundMove(gCurrentMove) - && !(gHitMarker & HITMARKER_UNABLE_TO_USE_MOVE) - && GetBattlerHoldEffect(gBattlerAttacker, TRUE) == HOLD_EFFECT_THROAT_SPRAY - && IsBattlerAlive(gBattlerAttacker) - && IsAnyTargetAffected(gBattlerAttacker) - && CompareStat(gBattlerAttacker, STAT_SPATK, MAX_STAT_STAGE, CMP_LESS_THAN, GetBattlerAbility(gBattlerAttacker)) - && !NoAliveMonsForEitherParty()) // Don't activate if battle will end - { - gLastUsedItem = gBattleMons[gBattlerAttacker].item; - gBattleScripting.battler = gBattlerAttacker; - SET_STATCHANGER(STAT_SPATK, 1, FALSE); - effect = TRUE; - BattleScriptCall(BattleScript_AttackerItemStatRaise); - } - gBattleScripting.moveendState++; - break; + } case MOVEEND_ABILITY_BLOCK: effect = HandleMoveEndAbilityBlock(gBattlerAttacker, gBattlerTarget, gCurrentMove); gBattleScripting.moveendState++; @@ -6603,6 +6665,31 @@ static void Cmd_moveend(void) else gBattleScripting.moveendState++; break; + case MOVEEND_COLOR_CHANGE: + while (gBattleStruct->eventState.moveEndBattler < gBattlersCount) + { + u32 battler = gBattleStruct->eventState.moveEndBattler++; + if (battler == gBattlerAttacker) + continue; + if (AbilityBattleEffects(ABILITYEFFECT_COLOR_CHANGE, battler, GetBattlerAbility(battler), 0, 0)) + return; + } + gBattleStruct->eventState.moveEndBattler = 0; + gBattleScripting.moveendState++; + break; + case MOVEEND_KEE_MARANGA_HP_THRESHOLD_ITEM_TARGET: + while (gBattleStruct->eventState.moveEndBattler < gBattlersCount) + { + u32 battlerDef = gBattleStruct->eventState.moveEndBattler++; + if (battlerDef == gBattlerAttacker) + continue; + enum HoldEffect holdEffect = GetBattlerHoldEffect(battlerDef); + if (ItemBattleEffects(battlerDef, gBattlerAttacker, holdEffect, IsKeeMarangaBerryActivation) + || ItemBattleEffects(battlerDef, gBattlerAttacker, holdEffect, IsOnHpThresholdActivation)) + return; + } + gBattleScripting.moveendState++; + break; case MOVEEND_RED_CARD: { u32 redCardBattlers = 0, i; @@ -6610,7 +6697,7 @@ static void Cmd_moveend(void) { if (i == gBattlerAttacker) continue; - if (GetBattlerHoldEffect(i, TRUE) == HOLD_EFFECT_RED_CARD) + if (GetBattlerHoldEffect(i) == HOLD_EFFECT_RED_CARD) redCardBattlers |= (1u << i); } if (redCardBattlers && IsBattlerAlive(gBattlerAttacker)) @@ -6650,7 +6737,7 @@ static void Cmd_moveend(void) } } if (effect) - gBattleScripting.moveendState = MOVEEND_OPPORTUNIST; + gBattleScripting.moveendState = MOVEEND_JUMP_TO_HIT_ESCAPE_PLUS_ONE; else gBattleScripting.moveendState++; break; @@ -6699,12 +6786,12 @@ static void Cmd_moveend(void) } } if (effect) - gBattleScripting.moveendState = MOVEEND_OPPORTUNIST; + gBattleScripting.moveendState = MOVEEND_JUMP_TO_HIT_ESCAPE_PLUS_ONE; else gBattleScripting.moveendState++; break; - case MOVEEND_LIFEORB_SHELLBELL: - if (ItemBattleEffects(ITEMEFFECT_LIFEORB_SHELLBELL, 0)) + case MOVEEND_LIFE_ORB_SHELL_BELL: + if (ItemBattleEffects(gBattlerAttacker, 0, GetBattlerHoldEffect(gBattlerAttacker), IsLifeOrbShellBellActivation)) effect = TRUE; gBattleScripting.moveendState++; break; @@ -6719,13 +6806,13 @@ static void Cmd_moveend(void) case MOVEEND_EMERGENCY_EXIT: // Special case, because moves hitting multiple opponents stop after switching out { // Because sorting the battlers by speed takes lots of cycles, - // we check if EE can be activated and cound how many. + // we check if EE can be activated and count how many. u32 numEmergencyExitBattlers = 0; u32 emergencyExitBattlers = 0; for (i = 0; i < gBattlersCount; i++) { - if (EmergencyExitCanBeTriggered(i)) + if (IsBattlerTurnDamaged(i) && EmergencyExitCanBeTriggered(i)) { emergencyExitBattlers |= 1u << i; numEmergencyExitBattlers++; @@ -6764,10 +6851,22 @@ static void Cmd_moveend(void) } } if (effect) - gBattleScripting.moveendState = MOVEEND_OPPORTUNIST; + gBattleScripting.moveendState = MOVEEND_JUMP_TO_HIT_ESCAPE_PLUS_ONE; else gBattleScripting.moveendState++; break; + case MOVEEND_HIT_ESCAPE: + if (moveEffect == EFFECT_HIT_ESCAPE + && !(gHitMarker & HITMARKER_UNABLE_TO_USE_MOVE) + && IsBattlerTurnDamaged(gBattlerTarget) + && IsBattlerAlive(gBattlerAttacker) + && !NoAliveMonsForBattlerSide(gBattlerTarget)) + { + effect = TRUE; + BattleScriptCall(BattleScript_EffectHitEscape); + } + gBattleScripting.moveendState++; + break; case MOVEEND_EJECT_PACK: { // Because sorting the battlers by speed takes lots of cycles, it's better to just check if any of the battlers has the Eject items. @@ -6803,10 +6902,6 @@ static void Cmd_moveend(void) if (!(ejectPackBattlers & 1u << battler)) continue; - // Hit escape moves activate before Eject Pack for user - if (moveEffect == EFFECT_HIT_ESCAPE && gBattlerAttacker == battler) - continue; - gBattleScripting.battler = battler; gLastUsedItem = gBattleMons[battler].item; effect = TRUE; @@ -6816,34 +6911,64 @@ static void Cmd_moveend(void) break; // Only the fastest Eject item activates } } - if (effect) - gBattleScripting.moveendState = MOVEEND_OPPORTUNIST; - else - gBattleScripting.moveendState++; + gBattleScripting.moveendState++; break; - case MOVEEND_HIT_ESCAPE: - if (moveEffect == EFFECT_HIT_ESCAPE - && !(gHitMarker & HITMARKER_UNABLE_TO_USE_MOVE) - && IsBattlerTurnDamaged(gBattlerTarget) - && IsBattlerAlive(gBattlerAttacker) - && !NoAliveMonsForBattlerSide(gBattlerTarget)) + + case MOVEEND_ITEMS_EFFECTS_ALL: + while (gBattleStruct->eventState.moveEndBattler < gBattlersCount) { - effect = TRUE; - BattleScriptCall(BattleScript_EffectHitEscape); + u32 battler = gBattleStruct->eventState.moveEndBattler++; + enum HoldEffect holdEffect = GetBattlerHoldEffect(battler); + if (ItemBattleEffects(battler, 0, holdEffect, IsOnStatusChangeActivation) + || ItemBattleEffects(battler, 0, holdEffect, IsOnHpThresholdActivation)) + return; } + gBattleStruct->eventState.moveEndBattler = 0; + gBattleScripting.moveendState++; + break; + case MOVEEND_WHITE_HERB: + while (gBattleStruct->eventState.moveEndBattler < gBattlersCount) + { + u32 battler = gBattleStruct->eventState.moveEndBattler++; + if (!IsBattlerAlive(battler)) + continue; + + if (ItemBattleEffects(battler, 0, GetBattlerHoldEffect(battler), IsWhiteHerbActivation)) + return; + } + gBattleStruct->eventState.moveEndBattler = 0; gBattleScripting.moveendState++; break; case MOVEEND_OPPORTUNIST: - if (AbilityBattleEffects(ABILITYEFFECT_OPPORTUNIST, 0, 0, 0, 0)) - effect = TRUE; // it loops through all battlers, so we increment after its done with all battlers - else - gBattleScripting.moveendState++; + while (gBattleStruct->eventState.moveEndBattler < gBattlersCount) + { + u32 battler = gBattleStruct->eventState.moveEndBattler++; + if (!IsBattlerAlive(battler)) + continue; + if (AbilityBattleEffects(ABILITYEFFECT_OPPORTUNIST, battler, GetBattlerAbility(battler), 0, 0)) + return; + } + gBattleStruct->eventState.moveEndBattler = 0; + gBattleScripting.moveendState++; + break; + case MOVEEND_MIRROR_HERB: + while (gBattleStruct->eventState.moveEndBattler < gBattlersCount) + { + u32 battler = gBattleStruct->eventState.moveEndBattler++; + if (!IsBattlerAlive(battler)) + continue; + + if (ItemBattleEffects(battler, 0, GetBattlerHoldEffect(battler), IsMirrorHerbActivation)) + return; + } + gBattleStruct->eventState.moveEndBattler = 0; + gBattleScripting.moveendState++; break; case MOVEEND_PICKPOCKET: if (IsBattlerAlive(gBattlerAttacker) && gBattleMons[gBattlerAttacker].item != ITEM_NONE // Attacker must be holding an item && !(gWishFutureKnock.knockedOffMons[GetBattlerSide(gBattlerAttacker)] & (1u << gBattlerPartyIndexes[gBattlerAttacker])) // But not knocked off - && IsMoveMakingContact(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerAttacker), GetBattlerHoldEffect(gBattlerAttacker, TRUE), gCurrentMove) // Pickpocket requires contact + && IsMoveMakingContact(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerAttacker), GetBattlerHoldEffect(gBattlerAttacker), gCurrentMove) // Pickpocket requires contact && !(gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_NO_EFFECT)) // Obviously attack needs to have worked { u8 battlers[4] = {0, 1, 2, 3}; @@ -6874,37 +6999,18 @@ static void Cmd_moveend(void) } gBattleScripting.moveendState++; break; - case MOVEEND_WHITE_HERB: - for (i = 0; i < gBattlersCount; i++) - { - if (!IsBattlerAlive(i)) - continue; - - if (GetBattlerHoldEffect(i, TRUE) == HOLD_EFFECT_WHITE_HERB - && RestoreWhiteHerbStats(i)) - { - BattleScriptCall(BattleScript_WhiteHerbRet); - effect = TRUE; - break; - } - } - if (!effect) - gBattleScripting.moveendState++; - break; case MOVEEND_THIRD_MOVE_BLOCK: - // Special case for Steel Roller since it has to check the chosen move - if (GetMoveEffect(gChosenMove) == EFFECT_STEEL_ROLLER && IsBattlerTurnDamaged(gBattlerTarget)) - { - BattleScriptCall(BattleScript_RemoveTerrain); - effect = TRUE; - gBattleScripting.moveendState++; - break; - } - switch (moveEffect) { + case EFFECT_STEEL_ROLLER: + if (gFieldStatuses & STATUS_FIELD_TERRAIN_ANY && IsBattlerTurnDamaged(gBattlerTarget)) + { + BattleScriptCall(BattleScript_RemoveTerrain); + effect = TRUE; + } case EFFECT_ICE_SPINNER: if (gFieldStatuses & STATUS_FIELD_TERRAIN_ANY + && gLastPrintedMoves[gBattlerAttacker] == gCurrentMove && IsBattlerAlive(gBattlerAttacker) && IsBattlerTurnDamaged(gBattlerTarget)) { @@ -6918,7 +7024,7 @@ static void Cmd_moveend(void) u32 item = gBattleMons[gBattlerAttacker].item; gBattleMons[gBattlerAttacker].item = ITEM_NONE; gBattleStruct->battlerState[gBattlerAttacker].canPickupItem = TRUE; - gBattleStruct->usedHeldItems[gBattlerPartyIndexes[gBattlerAttacker]][GetBattlerSide(gBattlerAttacker)] = item; + GetBattlerPartyState(gBattlerAttacker)->usedHeldItem = item; CheckSetUnburden(gBattlerAttacker); BtlController_EmitSetMonData( gBattlerAttacker, @@ -6950,9 +7056,7 @@ static void Cmd_moveend(void) gBattleScripting.moveendState++; break; case MOVEEND_SAME_MOVE_TURNS: - if (gCurrentMove != gLastResultingMoves[gBattlerAttacker] - || gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_NO_EFFECT - || gHitMarker & HITMARKER_UNABLE_TO_USE_MOVE) + if (gCurrentMove != gLastResultingMoves[gBattlerAttacker] || (gHitMarker & HITMARKER_UNABLE_TO_USE_MOVE) || !IsAnyTargetAffected()) gBattleStruct->metronomeItemCounter[gBattlerAttacker] = 0; else if (gCurrentMove == gLastResultingMoves[gBattlerAttacker] && gSpecialStatuses[gBattlerAttacker].parentalBondState != PARENTAL_BOND_1ST_HIT) gBattleStruct->metronomeItemCounter[gBattlerAttacker]++; @@ -6974,41 +7078,27 @@ static void Cmd_moveend(void) && gBattleMons[gBattlerAttacker].volatiles.lockConfusionTurns != 1) // And won't end this turn CancelMultiTurnMoves(gBattlerAttacker, SKY_DROP_IGNORE); // Cancel it - if (gBattleStruct->savedAttackerCount > 0) - { - if (TESTING) - Test_ExitWithResult(TEST_RESULT_ERROR, 0, "savedAttackerCount is greater than 0! More calls to SaveBattlerAttacker than RestoreBattlerAttacker!", __FILE__, __LINE__); - else - DebugPrintfLevel(MGBA_LOG_WARN, "savedAttackerCount is greater than 0! More calls to SaveBattlerAttacker than RestoreBattlerAttacker!"); - } - if (gBattleStruct->savedTargetCount > 0) - { - if (TESTING) - Test_ExitWithResult(TEST_RESULT_ERROR, 0, "savedTargetCount is greater than 0! More calls to SaveBattlerTarget than RestoreBattlerTarget!", __FILE__, __LINE__); - else - DebugPrintfLevel(MGBA_LOG_WARN, "savedTargetCount is greater than 0! More calls to SaveBattlerTarget than RestoreBattlerTarget!"); - } - + TryClearChargeVolatile(moveType); + ValidateSavedBattlerCounts(); gProtectStructs[gBattlerAttacker].shellTrap = FALSE; gBattleStruct->battlerState[gBattlerAttacker].ateBoost = FALSE; - gSpecialStatuses[gBattlerAttacker].gemBoost = FALSE; - gSpecialStatuses[gBattlerTarget].berryReduced = FALSE; - gSpecialStatuses[gBattlerTarget].distortedTypeMatchups = FALSE; gBattleScripting.moveEffect = MOVE_EFFECT_NONE; - gBattleStruct->isAtkCancelerForCalledMove = FALSE; gBattleStruct->swapDamageCategory = FALSE; gBattleStruct->categoryOverride = FALSE; gBattleStruct->additionalEffectsCounter = 0; gBattleStruct->poisonPuppeteerConfusion = FALSE; gBattleStruct->fickleBeamBoosted = FALSE; + gBattleStruct->tryDestinyBond = FALSE; + gBattleStruct->tryGrudge = FALSE; gBattleStruct->battlerState[gBattlerAttacker].usedMicleBerry = FALSE; gBattleStruct->noTargetPresent = FALSE; + gBattleStruct->toxicChainPriority = FALSE; if (gHitMarker & HITMARKER_UNABLE_TO_USE_MOVE) gBattleStruct->pledgeMove = FALSE; if (GetActiveGimmick(gBattlerAttacker) == GIMMICK_Z_MOVE) SetActiveGimmick(gBattlerAttacker, GIMMICK_NONE); - if (B_CHARGE >= GEN_9 && moveType == TYPE_ELECTRIC && (IsBattlerTurnDamaged(gBattlerTarget) || gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_NO_EFFECT)) - gBattleMons[gBattlerAttacker].volatiles.charge = FALSE; + if (gBattleMons[gBattlerAttacker].volatiles.destinyBond > 0) + gBattleMons[gBattlerAttacker].volatiles.destinyBond--; if (moveEffect == EFFECT_ECHOED_VOICE && !(gHitMarker & HITMARKER_UNABLE_TO_USE_MOVE)) gBattleStruct->incrementEchoedVoice = TRUE; // check if Stellar type boost should be used up @@ -7036,11 +7126,7 @@ static void Cmd_moveend(void) gBattleScripting.moveendState++; break; case MOVEEND_DANCER: - if (gCurrentMove == MOVE_NONE) - originallyUsedMove = gChosenMove; // Fallback to chosen move in case attacker is switched out in the middle of an attack resolution (eg red card) - else - originallyUsedMove = gCurrentMove; - if (IsDanceMove(originallyUsedMove) && !gBattleStruct->snatchedMoveIsUsed) + if (IsDanceMove(gCurrentMove) && !gBattleStruct->snatchedMoveIsUsed) { u32 battler, nextDancer = 0; bool32 hasDancerTriggered = FALSE; @@ -7055,7 +7141,7 @@ static void Cmd_moveend(void) } } - if (!(gBattleStruct->moveResultFlags[gBattlerTarget] & (MOVE_RESULT_FAILED | MOVE_RESULT_DOESNT_AFFECT_FOE) + if (!(!IsAnyTargetAffected() || (gHitMarker & HITMARKER_UNABLE_TO_USE_MOVE && !hasDancerTriggered) || (!gSpecialStatuses[gBattlerAttacker].dancerUsedMove && gBattleStruct->bouncedMoveIsUsed))) { // Dance move succeeds @@ -7074,7 +7160,7 @@ static void Cmd_moveend(void) nextDancer = battler | 0x4; } } - if (nextDancer && AbilityBattleEffects(ABILITYEFFECT_MOVE_END_OTHER, nextDancer & 0x3, 0, 0, originallyUsedMove)) + if (nextDancer && AbilityBattleEffects(ABILITYEFFECT_MOVE_END_OTHER, nextDancer & 0x3, 0, 0, gCurrentMove)) effect = TRUE; } } @@ -7130,7 +7216,7 @@ static void Cmd_sethealblock(void) else { gBattleMons[gBattlerTarget].volatiles.healBlock = TRUE; - gDisableStructs[gBattlerTarget].healBlockTimer = gBattleTurnCounter + 5; + gDisableStructs[gBattlerTarget].healBlockTimer = 5; gBattlescriptCurrInstr = cmd->nextInstr; } } @@ -7157,7 +7243,7 @@ static void Cmd_getswitchedmondata(void) if (TESTING && gBattlerPartyIndexes[battler] == gBattleStruct->monToSwitchIntoId[battler] - && gBattleStruct->hpBefore[battler] != 0) // battler is alive + && IsBattlerAlive(battler)) Test_ExitWithResult(TEST_RESULT_ERROR, 0, ":L:%s:%d: battler is trying to switch to themself", __FILE__, __LINE__); gBattlerPartyIndexes[battler] = gBattleStruct->monToSwitchIntoId[battler]; @@ -7433,7 +7519,7 @@ static void Cmd_jumpifcantswitch(void) CMD_ARGS(u8 battler:7, u8 ignoreEscapePrevention:1, const u8 *jumpInstr); u32 battler = GetBattlerForBattleScript(cmd->battler); - if (!cmd->ignoreEscapePrevention && !CanBattlerEscape(battler) && GetBattlerHoldEffect(battler, TRUE) != HOLD_EFFECT_SHED_SHELL) + if (!cmd->ignoreEscapePrevention && !CanBattlerEscape(battler) && GetBattlerHoldEffect(battler) != HOLD_EFFECT_SHED_SHELL) { gBattlescriptCurrInstr = cmd->jumpInstr; } @@ -7505,7 +7591,7 @@ static void Cmd_openpartyscreen(void) { if (((1u << i) & hitmarkerFaintBits)) { - u32 skipPartnerCheck = FALSE; + bool32 skipPartnerCheck = FALSE; if (gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS && GetBattlerSide(i) == B_SIDE_OPPONENT && TRAINER_BATTLE_PARAM.opponentB != TRAINER_NONE) @@ -7751,15 +7837,10 @@ static void UpdateSentMonFlags(u32 battler) gHitMarker &= ~HITMARKER_FAINTED(battler); gSpecialStatuses[battler].faintedHasReplacement = FALSE; - - if (!BattlerHasAi(battler)) - gBattleStruct->appearedInBattle |= 1u << gBattlerPartyIndexes[battler]; } static void SetDmgHazardsBattlescript(u8 battler, u8 multistringId) { - gBattleMons[battler].volatiles.destinyBond = FALSE; - gHitMarker &= ~HITMARKER_DESTINYBOND; gBattleScripting.battler = battler; gBattleCommunication[MULTISTRING_CHOOSER] = multistringId; @@ -7780,19 +7861,20 @@ void TryHazardsOnSwitchIn(u32 battler, u32 side, enum Hazards hazardType) case HAZARDS_NONE: break; case HAZARDS_SPIKES: - if (GetBattlerAbility(battler) != ABILITY_MAGIC_GUARD + { + enum Ability ability = GetBattlerAbility(battler); + if (ability != ABILITY_MAGIC_GUARD && IsBattlerAffectedByHazards(battler, FALSE) - && IsBattlerGrounded(battler)) + && IsBattlerGrounded(battler, ability, GetBattlerHoldEffect(battler))) { - u8 spikesDmg = (5 - gSideTimers[side].spikesAmount) * 2; - gBattleStruct->moveDamage[battler] = GetNonDynamaxMaxHP(battler) / (spikesDmg); - if (gBattleStruct->moveDamage[battler] == 0) - gBattleStruct->moveDamage[battler] = 1; + s32 spikesDmg = GetNonDynamaxMaxHP(battler) / ((5 - gSideTimers[side].spikesAmount) * 2); + SetPassiveDamageAmount(battler, spikesDmg); SetDmgHazardsBattlescript(battler, B_MSG_PKMNHURTBYSPIKES); } break; + } case HAZARDS_STICKY_WEB: - if (IsBattlerAffectedByHazards(battler, FALSE) && IsBattlerGrounded(battler)) + if (IsBattlerAffectedByHazards(battler, FALSE) && IsBattlerGrounded(battler, GetBattlerAbility(battler), GetBattlerHoldEffect(battler))) { gBattleScripting.battler = battler; SET_STATCHANGER(STAT_SPEED, 1, TRUE); @@ -7800,7 +7882,7 @@ void TryHazardsOnSwitchIn(u32 battler, u32 side, enum Hazards hazardType) } break; case HAZARDS_TOXIC_SPIKES: - if (!IsBattlerGrounded(battler)) + if (!IsBattlerGrounded(battler, GetBattlerAbility(battler), GetBattlerHoldEffect(battler))) break; if (IS_BATTLER_OF_TYPE(battler, TYPE_POISON)) // Absorb the toxic spikes. @@ -7834,16 +7916,16 @@ void TryHazardsOnSwitchIn(u32 battler, u32 side, enum Hazards hazardType) case HAZARDS_STEALTH_ROCK: if (IsBattlerAffectedByHazards(battler, FALSE) && GetBattlerAbility(battler) != ABILITY_MAGIC_GUARD) { - gBattleStruct->moveDamage[battler] = GetStealthHazardDamage(TYPE_SIDE_HAZARD_POINTED_STONES, battler); - if (gBattleStruct->moveDamage[battler] != 0) + gBattleStruct->passiveHpUpdate[battler] = GetStealthHazardDamage(TYPE_SIDE_HAZARD_POINTED_STONES, battler); + if (gBattleStruct->passiveHpUpdate[battler] != 0) SetDmgHazardsBattlescript(battler, B_MSG_STEALTHROCKDMG); } break; case HAZARDS_STEELSURGE: if (IsBattlerAffectedByHazards(battler, FALSE) && GetBattlerAbility(battler) != ABILITY_MAGIC_GUARD) { - gBattleStruct->moveDamage[battler] = GetStealthHazardDamage(TYPE_SIDE_HAZARD_SHARP_STEEL, battler); - if (gBattleStruct->moveDamage[battler] != 0) + gBattleStruct->passiveHpUpdate[battler] = GetStealthHazardDamage(TYPE_SIDE_HAZARD_SHARP_STEEL, battler); + if (gBattleStruct->passiveHpUpdate[battler] != 0) SetDmgHazardsBattlescript(battler, B_MSG_SHARPSTEELDMG); } break; @@ -7857,30 +7939,44 @@ static bool32 DoSwitchInEffectsForBattler(u32 battler) u32 i = 0; u32 side = GetBattlerSide(battler); // Neutralizing Gas announces itself before hazards - if (gBattleMons[battler].ability == ABILITY_NEUTRALIZING_GAS && gSpecialStatuses[battler].announceNeutralizingGas == 0) + if (AbilityBattleEffects(ABILITYEFFECT_NEUTRALIZINGGAS, battler, 0, 0, 0)) { - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SWITCHIN_NEUTRALIZING_GAS; - gSpecialStatuses[battler].announceNeutralizingGas = TRUE; - gDisableStructs[battler].neutralizingGas = TRUE; - gBattlerAbility = battler; - BattleScriptCall(BattleScript_SwitchInAbilityMsgRet); + return TRUE; } - // 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->battlerState[battler].storedHealingWish || gBattleStruct->battlerState[battler].storedLunarDance) - && (gBattleMons[battler].hp != gBattleMons[battler].maxHP || gBattleMons[battler].status1 != 0 || GetGenConfig(GEN_CONFIG_HEALING_WISH_SWITCH) < GEN_8)) + // Healing Wish and Lunar Dance activate before hazards. + // Starting from Gen8 - it heals only pokemon which can be healed. + // In Gen5-7 the effect activates anyways. + else if ((gBattleStruct->battlerState[battler].storedHealingWish) + && (GetConfig(CONFIG_HEALING_WISH_SWITCH) < GEN_8 + || gBattleMons[battler].hp != gBattleMons[battler].maxHP + || gBattleMons[battler].status1 != 0)) { gBattlerAttacker = battler; - if (gBattleStruct->battlerState[battler].storedHealingWish) - { - BattleScriptCall(BattleScript_HealingWishActivates); - gBattleStruct->battlerState[battler].storedHealingWish = FALSE; - } - else // Lunar Dance - { - BattleScriptCall(BattleScript_LunarDanceActivates); - gBattleStruct->battlerState[battler].storedLunarDance = FALSE; - } + BattleScriptCall(BattleScript_HealingWishActivates); + gBattleStruct->battlerState[battler].storedHealingWish = FALSE; + } + else if ((gBattleStruct->battlerState[battler].storedLunarDance) + && (GetConfig(CONFIG_HEALING_WISH_SWITCH) < GEN_8 + || gBattleMons[battler].hp != gBattleMons[battler].maxHP + || gBattleMons[battler].status1 != 0 + || gBattleMons[battler].pp[0] < CalculatePPWithBonus(gBattleMons[battler].moves[0], gBattleMons[battler].ppBonuses, 0) + || gBattleMons[battler].pp[1] < CalculatePPWithBonus(gBattleMons[battler].moves[1], gBattleMons[battler].ppBonuses, 1) + || gBattleMons[battler].pp[2] < CalculatePPWithBonus(gBattleMons[battler].moves[2], gBattleMons[battler].ppBonuses, 2) + || gBattleMons[battler].pp[3] < CalculatePPWithBonus(gBattleMons[battler].moves[3], gBattleMons[battler].ppBonuses, 3))) + { + gBattlerAttacker = battler; + BattleScriptCall(BattleScript_LunarDanceActivates); + gBattleStruct->battlerState[battler].storedLunarDance = FALSE; + } + else if (EmergencyExitCanBeTriggered(battler)) + { + gBattleScripting.battler = gBattlerAbility = battler; + gSpecialStatuses[battler].switchInItemDone = FALSE; + gBattleStruct->battlerState[battler].forcedSwitch = FALSE; + if (gBattleTypeFlags & BATTLE_TYPE_TRAINER) + BattleScriptCall(BattleScript_EmergencyExit); + else + BattleScriptCall(BattleScript_EmergencyExitWild); } else if (!gDisableStructs[battler].hazardsDone) { @@ -7897,15 +7993,14 @@ static bool32 DoSwitchInEffectsForBattler(u32 battler) else if (gBattleMons[battler].hp != gBattleMons[battler].maxHP && gBattleStruct->zmove.healReplacement) { gBattleStruct->zmove.healReplacement = FALSE; - gBattleStruct->moveDamage[battler] = -1 * (gBattleMons[battler].maxHP); + SetHealAmount(battler, gBattleMons[battler].maxHP); gBattleScripting.battler = battler; gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_Z_HP_TRAP; BattleScriptCall(BattleScript_HealReplacementZMove); - return TRUE; } else { - u32 battlerAbility = GetBattlerAbility(battler); + enum Ability battlerAbility = GetBattlerAbility(battler); // There is a hack here to ensure the truant counter will be 0 when the battler's next turn starts. // The truant counter is not updated in the case where a mon switches in after a lost judgment in the battle arena. if (battlerAbility == ABILITY_TRUANT @@ -7915,9 +8010,10 @@ static bool32 DoSwitchInEffectsForBattler(u32 battler) gDisableStructs[battler].truantSwitchInHack = 0; - if (DoSwitchInAbilities(battler) || ItemBattleEffects(ITEMEFFECT_ON_SWITCH_IN, battler)) + if (DoSwitchInAbilities(battler)) return TRUE; - else if (AbilityBattleEffects(ABILITYEFFECT_OPPORTUNIST, battler, 0, 0, 0)) + + if (ItemBattleEffects(battler, 0, GetBattlerHoldEffect(battler), IsOnSwitchInActivation)) return TRUE; for (i = 0; i < gBattlersCount; i++) @@ -7925,24 +8021,43 @@ static bool32 DoSwitchInEffectsForBattler(u32 battler) if (i == battler) continue; - switch (GetBattlerAbility(i)) + enum Ability ability = GetBattlerAbility(i); + switch (ability) { case ABILITY_TRACE: case ABILITY_COMMANDER: - if (AbilityBattleEffects(ABILITYEFFECT_ON_SWITCHIN, i, 0, 0, 0)) + if (AbilityBattleEffects(ABILITYEFFECT_ON_SWITCHIN, i, ability, 0, 0)) return TRUE; break; case ABILITY_FORECAST: case ABILITY_FLOWER_GIFT: case ABILITY_PROTOSYNTHESIS: - if (AbilityBattleEffects(ABILITYEFFECT_ON_WEATHER, i, 0, 0, 0)) + if (AbilityBattleEffects(ABILITYEFFECT_ON_WEATHER, i, ability, 0, 0)) return TRUE; break; + default: + break; } if (TryClearIllusion(i, ABILITYEFFECT_ON_SWITCHIN)) return TRUE; } + for (i = 0; i < gBattlersCount; i++) + { + if (ItemBattleEffects(i, 0, GetBattlerHoldEffect(i), IsWhiteHerbActivation)) + return TRUE; + } + for (i = 0; i < gBattlersCount; i++) + { + if (AbilityBattleEffects(ABILITYEFFECT_OPPORTUNIST, i, GetBattlerAbility(i), 0, 0)) + return TRUE; + } + for (i = 0; i < gBattlersCount; i++) + { + if (ItemBattleEffects(i, 0, GetBattlerHoldEffect(i), IsMirrorHerbActivation)) + return TRUE; + } + for (i = 0; i < gBattlersCount; i++) { if (gBattlerByTurnOrder[i] == battler) @@ -7951,7 +8066,9 @@ static bool32 DoSwitchInEffectsForBattler(u32 battler) gBattleStruct->hpOnSwitchout[GetBattlerSide(i)] = gBattleMons[i].hp; } + gSpecialStatuses[battler].switchInItemDone = FALSE; gBattleStruct->battlerState[battler].forcedSwitch = FALSE; + gBattleStruct->battlerState[battler].wasAboveHalfHp = FALSE; return FALSE; } @@ -8002,7 +8119,7 @@ static void Cmd_switchineffects(void) return; } } - if (TrySwitchInEjectPack(ITEMEFFECT_NONE)) + if (TrySwitchInEjectPack(OTHER)) return; // All battlers done, end for (i = 0; i < gBattlersCount; i++) @@ -8014,7 +8131,7 @@ static void Cmd_switchineffects(void) break; default: UpdateSentMonFlags(battler); - if (!DoSwitchInEffectsForBattler(battler) && !TrySwitchInEjectPack(ITEMEFFECT_NONE)) + if (!DoSwitchInEffectsForBattler(battler) && !TrySwitchInEjectPack(OTHER)) gBattlescriptCurrInstr = cmd->nextInstr; break; } @@ -8317,6 +8434,7 @@ static void Cmd_yesnoboxstoplearningmove(void) } } +// TODO: passive damage hit anim for sub static void Cmd_hitanimation(void) { CMD_ARGS(u8 battler); @@ -8327,7 +8445,7 @@ static void Cmd_hitanimation(void) if (!(gBattleStruct->moveResultFlags[battler] & MOVE_RESULT_NO_EFFECT)) { - if (!(gHitMarker & HITMARKER_IGNORE_SUBSTITUTE) + if (gBattleStruct->passiveHpUpdate[battler] > 0 || !(DoesSubstituteBlockMove(gBattlerAttacker, battler, gCurrentMove)) || gDisableStructs[battler].substituteHP == 0) { @@ -8345,8 +8463,7 @@ static void Cmd_hitanimation(void) || gBattleStruct->noResultString[battlerDef] != CAN_DAMAGE) continue; - if (!(gHitMarker & HITMARKER_IGNORE_SUBSTITUTE) - || !(DoesSubstituteBlockMove(gBattlerAttacker, battlerDef, gCurrentMove)) + if (!(DoesSubstituteBlockMove(gBattlerAttacker, battlerDef, gCurrentMove)) || gDisableStructs[battlerDef].substituteHP == 0) { BtlController_EmitHitAnimation(battlerDef, B_COMM_TO_CONTROLLER); @@ -8531,9 +8648,9 @@ static void Cmd_hidepartystatussummary(void) static void ResetValuesForCalledMove(void) { if (gBattlerByTurnOrder[gCurrentTurnActionNumber] != gBattlerAttacker) - gBattleStruct->atkCancelerTracker = 0; + gBattleStruct->eventState.atkCanceler = 0; else - SetAtkCancelerForCalledMove(); + gBattleStruct->eventState.atkCanceler = CANCELER_VOLATILE_BLOCKED; gBattleScripting.animTurn = 0; gBattleScripting.animTargetsHit = 0; SetTypeBeforeUsingMove(gCurrentMove, gBattlerAttacker); @@ -8650,7 +8767,7 @@ static void Cmd_setgravity(void) else { gFieldStatuses |= STATUS_FIELD_GRAVITY; - gFieldTimers.gravityTimer = gBattleTurnCounter + 5; + gFieldTimers.gravityTimer = 5; gBattlescriptCurrInstr = cmd->nextInstr; } } @@ -8663,13 +8780,8 @@ static bool32 TryCheekPouch(u32 battler, u32 itemId) && GetBattlerPartyState(battler)->ateBerry && !IsBattlerAtMaxHp(battler)) { - gBattleStruct->cheekPouchActivated = TRUE; - gBattleStruct->savedcheekPouchDamage = gBattleStruct->moveDamage[battler]; - gBattleStruct->moveDamage[battler] = GetNonDynamaxMaxHP(battler) / 3; - if (gBattleStruct->moveDamage[battler] == 0) - gBattleStruct->moveDamage[battler] = 1; - gBattleStruct->moveDamage[battler] *= -1; gBattlerAbility = battler; + SetHealAmount(battler, GetNonDynamaxMaxHP(battler) / 3); BattleScriptPush(gBattlescriptCurrInstr + 2); gBattlescriptCurrInstr = BattleScript_CheekPouchActivates; return TRUE; @@ -8677,16 +8789,6 @@ static bool32 TryCheekPouch(u32 battler, u32 itemId) return FALSE; } -// When Cheek Pouch activates mid-battle it overwrites the current damage, so restore it -static void TryRestoreDamageAfterCheekPouch(u32 battler) -{ - if (gBattleStruct->cheekPouchActivated) - { - gBattleStruct->moveDamage[battler] = gBattleStruct->savedcheekPouchDamage; - gBattleStruct->cheekPouchActivated = FALSE; - } -} - // Used by Bestow and Symbiosis to take an item from one battler and give to another. static void BestowItem(u32 battlerAtk, u32 battlerDef) { @@ -8708,9 +8810,9 @@ static bool32 TrySymbiosis(u32 battler, u32 itemId, bool32 moveEnd) { if (!gBattleStruct->itemLost[B_SIDE_PLAYER][gBattlerPartyIndexes[battler]].stolen && gBattleStruct->changedItems[battler] == ITEM_NONE - && GetBattlerHoldEffect(battler, TRUE) != HOLD_EFFECT_EJECT_BUTTON - && GetBattlerHoldEffect(battler, TRUE) != HOLD_EFFECT_EJECT_PACK - && (B_SYMBIOSIS_GEMS < GEN_7 || !(gSpecialStatuses[battler].gemBoost)) + && GetBattlerHoldEffect(battler) != HOLD_EFFECT_EJECT_BUTTON + && GetBattlerHoldEffect(battler) != HOLD_EFFECT_EJECT_PACK + && (GetConfig(CONFIG_SYMBIOSIS_GEMS) < GEN_7 || !(gSpecialStatuses[battler].gemBoost)) && GetMoveEffect(gCurrentMove) != EFFECT_FLING //Fling and damage-reducing berries are handled separately. && !gSpecialStatuses[battler].berryReduced && TryTriggerSymbiosis(battler, BATTLE_PARTNER(battler))) @@ -8748,9 +8850,9 @@ static void Cmd_removeitem(void) // Popped Air Balloon cannot be restored by any means. // Corroded items cannot be restored either. - if (GetBattlerHoldEffect(battler, TRUE) != HOLD_EFFECT_AIR_BALLOON - && GetMoveEffect(gCurrentMove) != EFFECT_CORROSIVE_GAS) - gBattleStruct->usedHeldItems[gBattlerPartyIndexes[battler]][GetBattlerSide(battler)] = itemId; // Remember if switched out + if (GetBattlerHoldEffect(battler) != HOLD_EFFECT_AIR_BALLOON + && GetMoveEffect(gCurrentMove) != EFFECT_CORROSIVE_GAS) + GetBattlerPartyState(battler)->usedHeldItem = itemId; // Remember if switched out gBattleMons[battler].item = ITEM_NONE; gBattleStruct->battlerState[battler].canPickupItem = TRUE; @@ -9177,18 +9279,18 @@ static void Cmd_useitemonopponent(void) bool32 CanUseLastResort(u8 battler) { - u32 i; - u32 knownMovesCount = 0, usedMovesCount = 0; - - for (i = 0; i < 4; i++) + u32 moveIndex; + for (moveIndex = 0; moveIndex < MAX_MON_MOVES; moveIndex++) { - if (gBattleMons[battler].moves[i] != MOVE_NONE) - knownMovesCount++; - if (i != gCurrMovePos && gDisableStructs[battler].usedMoves & (1u << i)) // Increment used move count for all moves except current Last Resort. - usedMovesCount++; + u32 move = gBattleMons[battler].moves[moveIndex]; + // Assumes that an empty slot cannot have a non-empty slot after it + if (move == MOVE_NONE) + break; + // If not Last Resort and has not been used, can't use Last Resort + if (GetMoveEffect(move) != EFFECT_LAST_RESORT && !(gDisableStructs[battler].usedMoves & (1u << moveIndex))) + return FALSE; } - - return (knownMovesCount >= 2 && usedMovesCount >= knownMovesCount - 1); + return moveIndex >= 2; // At least two usable moves that are either Last Resort or have been used } static void RemoveAllWeather(void) @@ -9304,7 +9406,7 @@ 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); } - if (B_DEFOG_EFFECT_CLEARING >= GEN_6) + if (GetConfig(CONFIG_DEFOG_EFFECT_CLEARING) >= GEN_6) { gBattlerAttacker = i; // For correct battle string. Ally's / Foe's if (DefogClearHazards(saveBattler, i, clear)) @@ -9312,14 +9414,20 @@ static bool32 TryDefogClear(u32 battlerAtk, bool32 clear) } if (gBattleWeather & B_WEATHER_FOG) { - gBattleWeather &= ~B_WEATHER_FOG; - BattleScriptCall(BattleScript_FogEnded_Ret); + if (clear) + { + gBattleWeather &= ~B_WEATHER_FOG; + BattleScriptCall(BattleScript_FogEnded_Ret); + } return TRUE; } - if (B_DEFOG_EFFECT_CLEARING >= GEN_8 && (gFieldStatuses & STATUS_FIELD_TERRAIN_ANY)) + if (GetConfig(CONFIG_DEFOG_EFFECT_CLEARING) >= GEN_8 && (gFieldStatuses & STATUS_FIELD_TERRAIN_ANY)) { - RemoveAllTerrains(); - BattleScriptCall(BattleScript_TerrainEnds_Ret); + if (clear) + { + RemoveAllTerrains(); + BattleScriptCall(BattleScript_TerrainEnds_Ret); + } return TRUE; } } @@ -9369,7 +9477,7 @@ u32 IsFlowerVeilProtected(u32 battler) return 0; } -u32 IsLeafGuardProtected(u32 battler, u32 ability) +u32 IsLeafGuardProtected(u32 battler, enum Ability ability) { if (IsBattlerWeatherAffected(battler, B_WEATHER_SUN)) return ability == ABILITY_LEAF_GUARD; @@ -9377,43 +9485,24 @@ u32 IsLeafGuardProtected(u32 battler, u32 ability) return 0; } -bool32 IsShieldsDownProtected(u32 battler, u32 ability) +bool32 IsShieldsDownProtected(u32 battler, enum Ability ability) { return (ability == ABILITY_SHIELDS_DOWN && GetFormIdFromFormSpeciesId(gBattleMons[battler].species) < GetFormIdFromFormSpeciesId(SPECIES_MINIOR_CORE_RED)); // Minior is not in core form } -u32 IsAbilityStatusProtected(u32 battler, u32 ability) +u32 IsAbilityStatusProtected(u32 battler, enum Ability ability) { return IsLeafGuardProtected(battler, ability) || IsShieldsDownProtected(battler, ability) || IsFlowerVeilProtected(battler); } -u32 GetHighestStatId(u32 battler) -{ - u32 i, highestId = STAT_ATK, highestStat = gBattleMons[battler].attack; - - for (i = STAT_DEF; i < NUM_STATS; i++) - { - u16 *statVal = &gBattleMons[battler].attack + (i - 1); - if (*statVal > highestStat && i != STAT_SPEED) - { - highestStat = *statVal; - highestId = i; - } - } - if (gBattleMons[battler].speed > highestStat) - highestId = STAT_SPEED; - - return highestId; -} - static bool32 IsRototillerAffected(u32 battler) { if (!IsBattlerAlive(battler)) return FALSE; - if (!IsBattlerGrounded(battler)) + if (!IsBattlerGrounded(battler, GetBattlerAbility(battler), GetBattlerHoldEffect(battler))) return FALSE; // Only grounded battlers affected if (!IS_BATTLER_OF_TYPE(battler, TYPE_GRASS)) return FALSE; // Only grass types affected @@ -9424,7 +9513,7 @@ static bool32 IsRototillerAffected(u32 battler) return TRUE; } -static bool32 IsElectricAbilityAffected(u32 battler, u32 ability) +static bool32 IsElectricAbilityAffected(u32 battler, enum Ability ability) { u32 moveType; @@ -9566,7 +9655,7 @@ static bool32 ChangeOrderTargetAfterAttacker(void) if (attackerTurnOrderNum > targetTurnOrderNum) return FALSE; if (attackerTurnOrderNum + 1 == targetTurnOrderNum) - return GetGenConfig(GEN_CONFIG_AFTER_YOU_TURN_ORDER) >= GEN_8; + return GetConfig(CONFIG_AFTER_YOU_TURN_ORDER) >= GEN_8; for (i = 0; i < MAX_BATTLERS_COUNT; i++) { @@ -9599,15 +9688,8 @@ static bool32 ChangeOrderTargetAfterAttacker(void) return TRUE; } -// will be deprecated next release cycle -static void Cmd_various(void) +static void Cmd_unused_0x78(void) { - CMD_ARGS(u8 battler, u8 id); - - if (gBattleControllerExecFlags) - return; - - gBattlescriptCurrInstr = cmd->nextInstr; } static void TryResetProtectUseCounter(u32 battler) @@ -9616,8 +9698,8 @@ static void TryResetProtectUseCounter(u32 battler) enum BattleMoveEffects lastEffect = GetMoveEffect(lastMove); if (lastMove == MOVE_UNAVAILABLE || (!gBattleMoveEffects[lastEffect].usesProtectCounter - && ((GetGenConfig(GEN_ALLY_SWITCH_FAIL_CHANCE) >= GEN_9 && lastEffect != EFFECT_ALLY_SWITCH) - || GetGenConfig(GEN_ALLY_SWITCH_FAIL_CHANCE) < GEN_9))) + && ((GetConfig(CONFIG_ALLY_SWITCH_FAIL_CHANCE) >= GEN_9 && lastEffect != EFFECT_ALLY_SWITCH) + || GetConfig(CONFIG_ALLY_SWITCH_FAIL_CHANCE) < GEN_9))) gDisableStructs[battler].protectUses = 0; } @@ -9631,12 +9713,12 @@ static void Cmd_setprotectlike(void) TryResetProtectUseCounter(gBattlerAttacker); - if (gCurrentTurnActionNumber == (gBattlersCount - 1)) + if (IsLastMonToMove(gBattlerAttacker)) notLastTurn = FALSE; if ((sProtectSuccessRates[gDisableStructs[gBattlerAttacker].protectUses] >= RandomUniform(RNG_PROTECT_FAIL, 0, USHRT_MAX) && notLastTurn) - || (protectMethod == PROTECT_WIDE_GUARD && B_WIDE_GUARD != GEN_5) - || (protectMethod == PROTECT_QUICK_GUARD && B_QUICK_GUARD != GEN_5)) + || (protectMethod == PROTECT_WIDE_GUARD && GetConfig(CONFIG_WIDE_GUARD) >= GEN_6) + || (protectMethod == PROTECT_QUICK_GUARD && GetConfig(CONFIG_QUICK_GUARD) >= GEN_6)) { if (GetMoveEffect(gCurrentMove) == EFFECT_ENDURE) { @@ -9676,7 +9758,7 @@ static void Cmd_tryexplosion(void) if (gBattleControllerExecFlags) return; - gBattleStruct->moveDamage[gBattlerAttacker] = gBattleMons[gBattlerAttacker].hp; + gBattleStruct->passiveHpUpdate[gBattlerAttacker] = gBattleMons[gBattlerAttacker].hp; BtlController_EmitHealthBarUpdate(gBattlerAttacker, B_COMM_TO_CONTROLLER, INSTANT_HP_BAR_DROP); MarkBattlerForControllerExec(gBattlerAttacker); gBattlescriptCurrInstr = cmd->nextInstr; @@ -9723,77 +9805,22 @@ static void Cmd_jumpifnexttargetvalid(void) static void Cmd_tryhealhalfhealth(void) { - CMD_ARGS(const u8 *failInstr, u8 battler); + CMD_ARGS(u8 battler, const u8 *failInstr); const u8 *failInstr = cmd->failInstr; if (cmd->battler == BS_ATTACKER) gBattlerTarget = gBattlerAttacker; - gBattleStruct->moveDamage[gBattlerTarget] = GetNonDynamaxMaxHP(gBattlerTarget) / 2; - if (gBattleStruct->moveDamage[gBattlerTarget] == 0) - gBattleStruct->moveDamage[gBattlerTarget] = 1; - gBattleStruct->moveDamage[gBattlerTarget] *= -1; - + SetHealAmount(gBattlerTarget, GetNonDynamaxMaxHP(gBattlerTarget) / 2); if (gBattleMons[gBattlerTarget].hp == gBattleMons[gBattlerTarget].maxHP) gBattlescriptCurrInstr = failInstr; else gBattlescriptCurrInstr = cmd->nextInstr; } -static void SetMoveForMirrorMove(u32 move) +static void Cmd_unused_0x7e(void) { - gHitMarker &= ~HITMARKER_ATTACKSTRING_PRINTED; - // Edge case, we used Z Mirror Move, got the stat boost and now need to use the Z-move - if (GetActiveGimmick(gBattlerAttacker) == GIMMICK_Z_MOVE && !IsBattleMoveStatus(move)) - { - gBattleStruct->zmove.baseMoves[gBattlerAttacker] = move; - gCurrentMove = GetTypeBasedZMove(move); - } - else - { - gCurrentMove = move; - } - - gBattlerTarget = GetBattleMoveTarget(gCurrentMove, NO_TARGET_OVERRIDE); - ResetValuesForCalledMove(); - gBattlescriptCurrInstr = GetMoveBattleScript(gCurrentMove); -} - -static void Cmd_trymirrormove(void) -{ - CMD_ARGS(); - - s32 i, validMovesCount; - u16 move; - u16 validMoves[MAX_BATTLERS_COUNT] = {0}; - - for (validMovesCount = 0, i = 0; i < gBattlersCount; i++) - { - if (i != gBattlerAttacker) - { - move = gBattleStruct->lastTakenMoveFrom[gBattlerAttacker][i]; - if (move != MOVE_NONE && move != MOVE_UNAVAILABLE) - { - validMoves[validMovesCount] = move; - validMovesCount++; - } - } - } - - move = gBattleStruct->lastTakenMove[gBattlerAttacker]; - if (move != MOVE_NONE && move != MOVE_UNAVAILABLE) - { - SetMoveForMirrorMove(move); - } - else if (validMovesCount != 0) - { - SetMoveForMirrorMove(validMoves[Random() % validMovesCount]); - } - else // no valid moves found - { - gBattlescriptCurrInstr = cmd->nextInstr; - } } static void Cmd_setfieldweather(void) @@ -9875,21 +9902,16 @@ static void Cmd_manipulatedamage(void) switch (cmd->mode) { case DMG_CHANGE_SIGN: - gBattleStruct->moveDamage[gBattlerAttacker] *= -1; - break; - case DMG_DOUBLED: - gBattleStruct->moveDamage[gBattlerTarget] *= 2; + gBattleStruct->passiveHpUpdate[gBattlerAttacker] *= -1; break; case DMG_1_8_TARGET_HP: - gBattleStruct->moveDamage[gBattlerTarget] = GetNonDynamaxMaxHP(gBattlerTarget) / 8; - if (gBattleStruct->moveDamage[gBattlerTarget] == 0) - gBattleStruct->moveDamage[gBattlerTarget] = 1; + SetPassiveDamageAmount(gBattlerTarget, GetNonDynamaxMaxHP(gBattlerTarget) / 8); break; case DMG_FULL_ATTACKER_HP: - gBattleStruct->moveDamage[gBattlerTarget] = GetNonDynamaxMaxHP(gBattlerAttacker); + gBattleStruct->passiveHpUpdate[gBattlerTarget] = GetNonDynamaxMaxHP(gBattlerAttacker); break; case DMG_BIG_ROOT: - gBattleStruct->moveDamage[gBattlerAttacker] = GetDrainedBigRootHp(gBattlerAttacker, gBattleStruct->moveDamage[gBattlerAttacker]); + gBattleStruct->passiveHpUpdate[gBattlerAttacker] = -1 * GetDrainedBigRootHp(gBattlerAttacker, gBattleStruct->passiveHpUpdate[gBattlerAttacker]); break; } @@ -9898,21 +9920,18 @@ static void Cmd_manipulatedamage(void) static void Cmd_trysetrest(void) { - CMD_ARGS(const u8 *failInstr); + CMD_ARGS(); - const u8 *failInstr = cmd->failInstr; gBattlerTarget = gBattlerAttacker; - gBattleStruct->moveDamage[gBattlerTarget] = gBattleMons[gBattlerTarget].maxHP * (-1); + SetHealAmount(gBattlerTarget, gBattleMons[gBattlerTarget].maxHP); + enum Ability ability = GetBattlerAbility(gBattlerTarget); + enum HoldEffect holdEffect = GetBattlerHoldEffect(gBattlerTarget); - if (gBattleMons[gBattlerTarget].hp == gBattleMons[gBattlerTarget].maxHP) - { - gBattlescriptCurrInstr = failInstr; - } - else if (IsBattlerTerrainAffected(gBattlerTarget, STATUS_FIELD_ELECTRIC_TERRAIN)) + if (IsBattlerTerrainAffected(gBattlerTarget, ability, holdEffect, STATUS_FIELD_ELECTRIC_TERRAIN)) { gBattlescriptCurrInstr = BattleScript_ElectricTerrainPrevents; } - else if (IsBattlerTerrainAffected(gBattlerTarget, STATUS_FIELD_MISTY_TERRAIN)) + else if (IsBattlerTerrainAffected(gBattlerTarget, ability, holdEffect, STATUS_FIELD_MISTY_TERRAIN)) { gBattlescriptCurrInstr = BattleScript_MistyTerrainPrevents; } @@ -9930,16 +9949,8 @@ static void Cmd_trysetrest(void) } } -static void Cmd_jumpifnotfirstturn(void) +static void Cmd_unused_0x82(void) { - CMD_ARGS(const u8 *jumpInstr); - - const u8 *jumpInstr = cmd->jumpInstr; - - if (gDisableStructs[gBattlerAttacker].isFirstTurn && !(gSpecialStatuses[gBattlerAttacker].instructedChosenTarget)) - gBattlescriptCurrInstr = cmd->nextInstr; - else - gBattlescriptCurrInstr = jumpInstr; } static void Cmd_unused_0x83(void) @@ -9991,19 +10002,10 @@ static void Cmd_stockpile(void) switch (cmd->id) { case 0: - if (gDisableStructs[gBattlerAttacker].stockpileCounter >= 3) - { - gBattleStruct->moveResultFlags[gBattlerTarget] |= MOVE_RESULT_MISSED; - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_CANT_STOCKPILE; - } - else - { - gDisableStructs[gBattlerAttacker].stockpileCounter++; - gDisableStructs[gBattlerAttacker].stockpileBeforeDef = gBattleMons[gBattlerAttacker].statStages[STAT_DEF]; - gDisableStructs[gBattlerAttacker].stockpileBeforeSpDef = gBattleMons[gBattlerAttacker].statStages[STAT_SPDEF]; - PREPARE_BYTE_NUMBER_BUFFER(gBattleTextBuff1, 1, gDisableStructs[gBattlerAttacker].stockpileCounter); - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_STOCKPILED; - } + gDisableStructs[gBattlerAttacker].stockpileCounter++; + gDisableStructs[gBattlerAttacker].stockpileBeforeDef = gBattleMons[gBattlerAttacker].statStages[STAT_DEF]; + gDisableStructs[gBattlerAttacker].stockpileBeforeSpDef = gBattleMons[gBattlerAttacker].statStages[STAT_SPDEF]; + PREPARE_BYTE_NUMBER_BUFFER(gBattleTextBuff1, 1, gDisableStructs[gBattlerAttacker].stockpileCounter); break; case 1: // Save def/sp def stats. if (!(gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_NO_EFFECT)) @@ -10019,20 +10021,12 @@ static void Cmd_stockpile(void) static void Cmd_stockpiletobasedamage(void) { - CMD_ARGS(const u8 *failInstr); + CMD_ARGS(); - const u8 *failInstr = cmd->failInstr; - if (gDisableStructs[gBattlerAttacker].stockpileCounter == 0) - { - gBattlescriptCurrInstr = failInstr; - } - else - { - if (gBattleCommunication[MISS_TYPE] != B_MSG_PROTECTED) - gBattleScripting.animTurn = gDisableStructs[gBattlerAttacker].stockpileCounter; + if (gBattleCommunication[MISS_TYPE] != B_MSG_PROTECTED) + gBattleScripting.animTurn = gDisableStructs[gBattlerAttacker].stockpileCounter; - gBattlescriptCurrInstr = cmd->nextInstr; - } + gBattlescriptCurrInstr = cmd->nextInstr; } static void Cmd_stockpiletohpheal(void) @@ -10041,40 +10035,27 @@ static void Cmd_stockpiletohpheal(void) const u8 *failInstr = cmd->failInstr; - if (gDisableStructs[gBattlerAttacker].stockpileCounter == 0 && !gBattleStruct->snatchedMoveIsUsed) + if (gBattleMons[gBattlerAttacker].maxHP == gBattleMons[gBattlerAttacker].hp) { + gDisableStructs[gBattlerAttacker].stockpileCounter = 0; gBattlescriptCurrInstr = failInstr; - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SWALLOW_FAILED; + gBattlerTarget = gBattlerAttacker; } else { - if (gBattleMons[gBattlerAttacker].maxHP == gBattleMons[gBattlerAttacker].hp) + if (gDisableStructs[gBattlerAttacker].stockpileCounter > 0) { - gDisableStructs[gBattlerAttacker].stockpileCounter = 0; - gBattlescriptCurrInstr = failInstr; - gBattlerTarget = gBattlerAttacker; - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SWALLOW_FULL_HP; + SetHealAmount(gBattlerAttacker, GetNonDynamaxMaxHP(gBattlerAttacker) / (1 << (3 - gDisableStructs[gBattlerAttacker].stockpileCounter))); + gBattleScripting.animTurn = gDisableStructs[gBattlerAttacker].stockpileCounter; } - else + else // Snatched move { - if (gDisableStructs[gBattlerAttacker].stockpileCounter > 0) - { - gBattleStruct->moveDamage[gBattlerAttacker] = GetNonDynamaxMaxHP(gBattlerAttacker) / (1 << (3 - gDisableStructs[gBattlerAttacker].stockpileCounter)); - gBattleScripting.animTurn = gDisableStructs[gBattlerAttacker].stockpileCounter; - } - else // Snatched move - { - gBattleStruct->moveDamage[gBattlerAttacker] = GetNonDynamaxMaxHP(gBattlerAttacker) / 4; - gBattleScripting.animTurn = 1; - } - - if (gBattleStruct->moveDamage[gBattlerAttacker] == 0) - gBattleStruct->moveDamage[gBattlerAttacker] = 1; - gBattleStruct->moveDamage[gBattlerAttacker] *= -1; - - gBattlescriptCurrInstr = cmd->nextInstr; - gBattlerTarget = gBattlerAttacker; + SetHealAmount(gBattlerAttacker, GetNonDynamaxMaxHP(gBattlerAttacker) / 4); + gBattleScripting.animTurn = 1; } + + gBattlescriptCurrInstr = cmd->nextInstr; + gBattlerTarget = gBattlerAttacker; } } @@ -10096,17 +10077,8 @@ void BS_RemoveStockpileCounters(void) } } -// Sign change for drained HP handled in GetDrainedBigRootHp -static void Cmd_setdrainedhp(void) +static void Cmd_unused_0x88(void) { - CMD_ARGS(); - - gBattleStruct->moveDamage[gBattlerAttacker] = (gBattleStruct->moveDamage[gBattlerTarget] * GetMoveAbsorbPercentage(gCurrentMove) / 100); - - if (gBattleStruct->moveDamage[gBattlerAttacker] == 0) - gBattleStruct->moveDamage[gBattlerAttacker] = 1; - - gBattlescriptCurrInstr = cmd->nextInstr; } static u16 ReverseStatChangeMoveEffect(u16 moveEffect) @@ -10177,9 +10149,9 @@ static u16 ReverseStatChangeMoveEffect(u16 moveEffect) } } -static void TryPlayStatChangeAnimation(u32 battler, u32 ability, u32 stats, s32 statValue, u32 statId, bool32 certain) +static void TryPlayStatChangeAnimation(u32 battler, enum Ability ability, u32 stats, s32 statValue, u32 statId, bool32 certain) { - u32 currStat = 0; + enum Stat currStat = 0; u32 changeableStatsCount = 1; // current stat is counted automatically u32 statAnimId = statId; bool32 statChangeByTwo = statValue > 1 || statValue < -1; @@ -10204,7 +10176,7 @@ static void TryPlayStatChangeAnimation(u32 battler, u32 ability, u32 stats, s32 } } else if (!((ability == ABILITY_KEEN_EYE || ability == ABILITY_MINDS_EYE) && currStat == STAT_ACC) - && !(GetGenConfig(GEN_ILLUMINATE_EFFECT) >= GEN_9 && ability == ABILITY_ILLUMINATE && currStat == STAT_ACC) + && !(GetConfig(CONFIG_ILLUMINATE_EFFECT) >= GEN_9 && ability == ABILITY_ILLUMINATE && currStat == STAT_ACC) && !(ability == ABILITY_HYPER_CUTTER && currStat == STAT_ATK) && !(ability == ABILITY_BIG_PECKS && currStat == STAT_DEF)) { @@ -10265,12 +10237,12 @@ static void TryPlayStatChangeAnimation(u32 battler, u32 ability, u32 stats, s32 } } -static u32 ChangeStatBuffs(u32 battler, s8 statValue, u32 statId, union StatChangeFlags flags, u32 stats, const u8 *BS_ptr) +static u32 ChangeStatBuffs(u32 battler, s8 statValue, enum Stat statId, union StatChangeFlags flags, u32 stats, const u8 *BS_ptr) { u32 index, battlerAbility; - enum ItemHoldEffect battlerHoldEffect; + enum HoldEffect battlerHoldEffect; battlerAbility = GetBattlerAbility(battler); - battlerHoldEffect = GetBattlerHoldEffect(battler, TRUE); + battlerHoldEffect = GetBattlerHoldEffect(battler); gSpecialStatuses[battler].changedStatsBattlerId = gBattlerAttacker; if (battlerAbility == ABILITY_CONTRARY) @@ -10373,7 +10345,7 @@ static u32 ChangeStatBuffs(u32 battler, s8 statValue, u32 statId, union StatChan } else if (!flags.certain && (((battlerAbility == ABILITY_KEEN_EYE || battlerAbility == ABILITY_MINDS_EYE) && statId == STAT_ACC) - || (GetGenConfig(GEN_ILLUMINATE_EFFECT) >= GEN_9 && battlerAbility == ABILITY_ILLUMINATE && statId == STAT_ACC) + || (GetConfig(CONFIG_ILLUMINATE_EFFECT) >= GEN_9 && battlerAbility == ABILITY_ILLUMINATE && statId == STAT_ACC) || (battlerAbility == ABILITY_HYPER_CUTTER && statId == STAT_ATK) || (battlerAbility == ABILITY_BIG_PECKS && statId == STAT_DEF))) { @@ -10408,37 +10380,32 @@ static u32 ChangeStatBuffs(u32 battler, s8 statValue, u32 statId, union StatChan statValue = -1; else if (gBattleMons[battler].statStages[statId] == 2 && statValue < -2) statValue = -2; - gBattleTextBuff2[0] = B_BUFF_PLACEHOLDER_BEGIN; - index = 1; + if (statValue == -2) { - gBattleTextBuff2[1] = B_BUFF_STRING; - gBattleTextBuff2[2] = STRINGID_STATHARSHLY; - gBattleTextBuff2[3] = STRINGID_STATHARSHLY >> 8; - index = 4; + PREPARE_STRING_BUFFER(gBattleTextBuff2, STRINGID_STATHARSHLY); } else if (statValue <= -3) { - gBattleTextBuff2[1] = B_BUFF_STRING; - gBattleTextBuff2[2] = STRINGID_SEVERELY & 0xFF; - gBattleTextBuff2[3] = STRINGID_SEVERELY >> 8; - index = 4; + PREPARE_STRING_BUFFER(gBattleTextBuff2, STRINGID_SEVERELY); + } + else + { + PREPARE_STRING_BUFFER(gBattleTextBuff2, STRINGID_EMPTYSTRING3); } - gBattleTextBuff2[index++] = B_BUFF_STRING; - gBattleTextBuff2[index++] = STRINGID_STATFELL; - gBattleTextBuff2[index++] = STRINGID_STATFELL >> 8; - gBattleTextBuff2[index] = B_BUFF_EOS; - gBattleCommunication[MULTISTRING_CHOOSER] = (gBattlerTarget == battler); // B_MSG_ATTACKER_STAT_FELL or B_MSG_DEFENDER_STAT_FELL + gBattleCommunication[MULTISTRING_CHOOSER] = (gBattlerTarget == battler); // B_MSG_ATTACKER_STAT_CHANGED or B_MSG_DEFENDER_STAT_CHANGED if (gBattleMons[battler].statStages[statId] == MIN_STAT_STAGE) { - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_STAT_WONT_DECREASE; + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_STAT_WONT_CHANGE; + gBattleScripting.statChanger |= STAT_BUFF_NEGATIVE; } else if (!flags.onlyChecking) { gDisableStructs[battler].tryEjectPack = TRUE; gProtectStructs[battler].lashOutAffected = TRUE; + gBattleScripting.statChanger |= STAT_BUFF_NEGATIVE; } } } @@ -10449,32 +10416,26 @@ static u32 ChangeStatBuffs(u32 battler, s8 statValue, u32 statId, union StatChan statValue = 1; else if (gBattleMons[battler].statStages[statId] == 10 && statValue > 2) statValue = 2; - gBattleTextBuff2[0] = B_BUFF_PLACEHOLDER_BEGIN; - index = 1; + if (statValue == 2) { - gBattleTextBuff2[1] = B_BUFF_STRING; - gBattleTextBuff2[2] = STRINGID_STATSHARPLY; - gBattleTextBuff2[3] = STRINGID_STATSHARPLY >> 8; - index = 4; + PREPARE_STRING_BUFFER(gBattleTextBuff2, STRINGID_STATSHARPLY); } else if (statValue >= 3) { - gBattleTextBuff2[1] = B_BUFF_STRING; - gBattleTextBuff2[2] = STRINGID_DRASTICALLY & 0xFF; - gBattleTextBuff2[3] = STRINGID_DRASTICALLY >> 8; - index = 4; + PREPARE_STRING_BUFFER(gBattleTextBuff2, STRINGID_DRASTICALLY); + } + else + { + PREPARE_STRING_BUFFER(gBattleTextBuff2, STRINGID_EMPTYSTRING3); } - gBattleTextBuff2[index++] = B_BUFF_STRING; - gBattleTextBuff2[index++] = STRINGID_STATROSE; - gBattleTextBuff2[index++] = STRINGID_STATROSE >> 8; - gBattleTextBuff2[index] = B_BUFF_EOS; - gBattleCommunication[MULTISTRING_CHOOSER] = (gBattlerTarget == battler); // B_MSG_ATTACKER_STAT_ROSE or B_MSG_DEFENDER_STAT_ROSE + gBattleCommunication[MULTISTRING_CHOOSER] = (gBattlerTarget == battler); // B_MSG_ATTACKER_STAT_CHANGED or B_MSG_DEFENDER_STAT_CHANGED if (gBattleMons[battler].statStages[statId] == MAX_STAT_STAGE) { - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_STAT_WONT_INCREASE; + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_STAT_WONT_CHANGE; + gBattleScripting.statChanger &= ~STAT_BUFF_NEGATIVE; } else if (!flags.onlyChecking) { @@ -10485,6 +10446,7 @@ static u32 ChangeStatBuffs(u32 battler, s8 statValue, u32 statId, union StatChan statIncrease = statValue; gProtectStructs[battler].statRaised = TRUE; + gBattleScripting.statChanger &= ~STAT_BUFF_NEGATIVE; if (statIncrease) { @@ -10499,7 +10461,7 @@ static u32 ChangeStatBuffs(u32 battler, s8 statValue, u32 statId, union StatChan { gProtectStructs[index].activateOpportunist = 2; // set stats to copy } - if (GetBattlerHoldEffect(index, TRUE) == HOLD_EFFECT_MIRROR_HERB) + if (GetBattlerHoldEffect(index) == HOLD_EFFECT_MIRROR_HERB) { gProtectStructs[index].eatMirrorHerb = 1; } @@ -10514,11 +10476,10 @@ static u32 ChangeStatBuffs(u32 battler, s8 statValue, u32 statId, union StatChan } } - if (gBattleCommunication[MULTISTRING_CHOOSER] == B_MSG_STAT_WONT_INCREASE) // same as B_MSG_STAT_WONT_DECREASE + if (gBattleCommunication[MULTISTRING_CHOOSER] == B_MSG_STAT_WONT_CHANGE) // at max or min { if (!flags.allowPtr) return STAT_CHANGE_DIDNT_WORK; - gBattleStruct->moveResultFlags[gBattlerTarget] |= MOVE_RESULT_MISSED; return STAT_CHANGE_WORKED; } @@ -10979,8 +10940,8 @@ static void Cmd_tryKO(void) CMD_ARGS(const u8 *failInstr); enum BattleMoveEffects effect = GetMoveEffect(gCurrentMove); - enum ItemHoldEffect holdEffect = GetBattlerHoldEffect(gBattlerTarget, TRUE); - u16 targetAbility = GetBattlerAbility(gBattlerTarget); + enum HoldEffect holdEffect = GetBattlerHoldEffect(gBattlerTarget); + enum Ability targetAbility = GetBattlerAbility(gBattlerTarget); u32 rand = Random() % 100; u32 affectionScore = GetBattlerAffectionHearts(gBattlerTarget); u32 endured = NOT_ENDURED; @@ -11205,7 +11166,7 @@ static void Cmd_setmist(void) } else { - gSideTimers[GetBattlerSide(gBattlerAttacker)].mistTimer = gBattleTurnCounter + 5; + gSideTimers[GetBattlerSide(gBattlerAttacker)].mistTimer = 5; gSideStatuses[GetBattlerSide(gBattlerAttacker)] |= SIDE_STATUS_MIST; gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SET_MIST; } @@ -11231,8 +11192,8 @@ static void Cmd_setfocusenergy(void) } else { - if (GetGenConfig(GEN_CONFIG_FOCUS_ENERGY_CRIT_RATIO) >= GEN_3 - || GetGenConfig(GEN_CONFIG_CRIT_CHANCE) == GEN_1) + if (GetConfig(CONFIG_FOCUS_ENERGY_CRIT_RATIO) >= GEN_3 + || GetConfig(CONFIG_CRIT_CHANCE) == GEN_1) gBattleMons[battler].volatiles.focusEnergy = TRUE; else gBattleMons[battler].volatiles.dragonCheer = TRUE; @@ -11307,7 +11268,7 @@ static void Cmd_setsubstitute(void) CMD_ARGS(); u32 factor = GetMoveEffect(gCurrentMove) == EFFECT_SHED_TAIL ? 2 : 4; - u32 hp; + s32 hp = 0; if (factor == 2) hp = (GetNonDynamaxMaxHP(gBattlerAttacker)+1) / factor; // shed tail rounds up @@ -11319,25 +11280,22 @@ static void Cmd_setsubstitute(void) if (gBattleMons[gBattlerAttacker].hp <= hp) { - gBattleStruct->moveDamage[gBattlerAttacker] = 0; + hp = 0; gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SUBSTITUTE_FAILED; } else { - gBattleStruct->moveDamage[gBattlerAttacker] = hp; // one bit value will only work for Pokémon which max hp can go to 1020(which is more than possible in games) - if (gBattleStruct->moveDamage[gBattlerAttacker] == 0) - gBattleStruct->moveDamage[gBattlerAttacker] = 1; - gBattleMons[gBattlerAttacker].volatiles.substitute = TRUE; gBattleMons[gBattlerAttacker].volatiles.wrapped = FALSE; + // gDisableStructs[gBattlerAttacker].substituteHP = (factor == 2) ? (hp / 2) : hp; if (factor == 2) - gDisableStructs[gBattlerAttacker].substituteHP = gBattleStruct->moveDamage[gBattlerAttacker] / 2; + gDisableStructs[gBattlerAttacker].substituteHP = hp / 2; else - gDisableStructs[gBattlerAttacker].substituteHP = gBattleStruct->moveDamage[gBattlerAttacker]; + gDisableStructs[gBattlerAttacker].substituteHP = hp; gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SET_SUBSTITUTE; - gHitMarker |= HITMARKER_IGNORE_SUBSTITUTE; } + gBattleStruct->passiveHpUpdate[gBattlerAttacker] = hp; gBattlescriptCurrInstr = cmd->nextInstr; } @@ -11384,41 +11342,11 @@ static void Cmd_mimicattackcopy(void) } } -static bool32 InvalidMetronomeMove(u32 move) -{ - return GetMoveEffect(move) == EFFECT_PLACEHOLDER - || IsMoveMetronomeBanned(move); -} - -static void Cmd_metronome(void) +static void Cmd_setcalledmove(void) { CMD_ARGS(); - -#if B_METRONOME_MOVES >= GEN_9 - u32 moveCount = MOVES_COUNT_GEN9; -#elif B_METRONOME_MOVES >= GEN_8 - u32 moveCount = MOVES_COUNT_GEN8; -#elif B_METRONOME_MOVES >= GEN_7 - u32 moveCount = MOVES_COUNT_GEN7; -#elif B_METRONOME_MOVES >= GEN_6 - u32 moveCount = MOVES_COUNT_GEN6; -#elif B_METRONOME_MOVES >= GEN_5 - u32 moveCount = MOVES_COUNT_GEN5; -#elif B_METRONOME_MOVES >= GEN_4 - u32 moveCount = MOVES_COUNT_GEN4; -#elif B_METRONOME_MOVES >= GEN_3 - u32 moveCount = MOVES_COUNT_GEN3; -#elif B_METRONOME_MOVES >= GEN_2 - u32 moveCount = MOVES_COUNT_GEN2; -#else - u32 moveCount = MOVES_COUNT_GEN1; -#endif - - gCurrentMove = RandomUniformExcept(RNG_METRONOME, 1, moveCount - 1, InvalidMetronomeMove); - PrepareStringBattle(STRINGID_WAGGLINGAFINGER, gBattlerAttacker); - gBattlescriptCurrInstr = GetMoveBattleScript(gCurrentMove); - gBattlerTarget = GetBattleMoveTarget(gCurrentMove, NO_TARGET_OVERRIDE); - ResetValuesForCalledMove(); + gCurrentMove = gCalledMove; + gBattlescriptCurrInstr = cmd->nextInstr; } static void Cmd_unused_0x9f(void) @@ -11429,6 +11357,13 @@ static void Cmd_unused_0xA0(void) { } +static void CalcReflectBackDamage(u32 baseDamage, u32 percentMult) +{ + s32 damage = (baseDamage - 1) * percentMult / 100; + damage = max(damage, 1); + gBattleStruct->moveDamage[gBattlerTarget] = damage; +} + static void Cmd_counterdamagecalculator(void) { CMD_ARGS(const u8 *failInstr); @@ -11445,7 +11380,7 @@ static void Cmd_counterdamagecalculator(void) else gBattlerTarget = gProtectStructs[gBattlerAttacker].physicalBattlerId; - gBattleStruct->moveDamage[gBattlerTarget] = gProtectStructs[gBattlerAttacker].physicalDmg * 2; + CalcReflectBackDamage(gProtectStructs[gBattlerAttacker].physicalDmg, 200); gBattlescriptCurrInstr = cmd->nextInstr; } else @@ -11472,7 +11407,7 @@ static void Cmd_mirrorcoatdamagecalculator(void) else gBattlerTarget = gProtectStructs[gBattlerAttacker].specialBattlerId; - gBattleStruct->moveDamage[gBattlerTarget] = gProtectStructs[gBattlerAttacker].specialDmg * 2; + CalcReflectBackDamage(gProtectStructs[gBattlerAttacker].specialDmg, 200); gBattlescriptCurrInstr = cmd->nextInstr; } else @@ -11573,8 +11508,8 @@ static void Cmd_painsplitdmgcalc(void) { s32 hpDiff = (gBattleMons[gBattlerAttacker].hp + GetNonDynamaxHP(gBattlerTarget)) / 2; - gBattleStruct->moveDamage[gBattlerTarget] = GetNonDynamaxHP(gBattlerTarget) - hpDiff; - gBattleStruct->moveDamage[gBattlerAttacker] = gBattleMons[gBattlerAttacker].hp - hpDiff; + gBattleStruct->passiveHpUpdate[gBattlerTarget] = GetNonDynamaxHP(gBattlerTarget) - hpDiff; + gBattleStruct->passiveHpUpdate[gBattlerAttacker] = gBattleMons[gBattlerAttacker].hp - hpDiff; gBattlescriptCurrInstr = cmd->nextInstr; } @@ -11769,49 +11704,8 @@ static void Cmd_copymovepermanently(void) } } -static void Cmd_trychoosesleeptalkmove(void) +static void Cmd_unused_0xA9(void) { - CMD_ARGS(const u8 *failInstr); - - u32 i, unusableMovesBits = 0, movePosition; - - for (i = 0; i < MAX_MON_MOVES; i++) - { - if (IsMoveSleepTalkBanned(gBattleMons[gBattlerAttacker].moves[i]) - || gBattleMoveEffects[GetMoveEffect(gBattleMons[gBattlerAttacker].moves[i])].twoTurnEffect) - { - unusableMovesBits |= (1 << (i)); - } - } - - unusableMovesBits = CheckMoveLimitations(gBattlerAttacker, unusableMovesBits, ~(MOVE_LIMITATION_PP | MOVE_LIMITATION_CHOICE_ITEM)); - if (unusableMovesBits == ALL_MOVES_MASK) // all 4 moves cannot be chosen - { - gBattlescriptCurrInstr = cmd->nextInstr; - } - else // at least one move can be chosen - { - // Set Sleep Talk as used move, so it works with Last Resort. - gDisableStructs[gBattlerAttacker].usedMoves |= 1u << gCurrMovePos; - do - { - movePosition = MOD(Random(), MAX_MON_MOVES); - } while ((1u << movePosition) & unusableMovesBits); - - if (GetActiveGimmick(gBattlerAttacker) == GIMMICK_Z_MOVE && !IsBattleMoveStatus(gBattleMons[gBattlerAttacker].moves[movePosition])) - { - gBattleStruct->zmove.baseMoves[gBattlerAttacker] = gBattleMons[gBattlerAttacker].moves[movePosition]; - gCalledMove = GetTypeBasedZMove(gBattleMons[gBattlerAttacker].moves[movePosition]); - } - else - { - gCalledMove = gBattleMons[gBattlerAttacker].moves[movePosition]; - } - gCurrMovePos = movePosition; - gHitMarker &= ~HITMARKER_ATTACKSTRING_PRINTED; - gBattlerTarget = GetBattleMoveTarget(gCalledMove, NO_TARGET_OVERRIDE); - gBattlescriptCurrInstr = cmd->failInstr; - } } static inline bool32 IsDanamaxMonPresent(void) @@ -11828,41 +11722,12 @@ static inline bool32 IsDanamaxMonPresent(void) return FALSE; } -static void Cmd_trysetdestinybond(void) +static void Cmd_unused_AA(void) { - CMD_ARGS(const u8 *failInstr); - - if (IsDanamaxMonPresent()) - { - gBattlescriptCurrInstr = BattleScript_MoveBlockedByDynamax; - } - else if (DoesDestinyBondFail(gBattlerAttacker)) - { - gBattlescriptCurrInstr = cmd->failInstr; - } - else - { - gBattleMons[gBattlerAttacker].volatiles.destinyBond = TRUE; - gBattlescriptCurrInstr = cmd->nextInstr; - } } -static void TrySetDestinyBondToHappen(void) +static void Cmd_unused_0xab(void) { - if (gBattleMons[gBattlerTarget].volatiles.destinyBond - && !IsBattlerAlly(gBattlerAttacker, gBattlerTarget) - && !(gHitMarker & HITMARKER_GRUDGE)) - { - gHitMarker |= HITMARKER_DESTINYBOND; - } -} - -static void Cmd_trysetdestinybondtohappen(void) -{ - CMD_ARGS(); - - TrySetDestinyBondToHappen(); - gBattlescriptCurrInstr = cmd->nextInstr; } static void Cmd_settailwind(void) @@ -11874,7 +11739,7 @@ static void Cmd_settailwind(void) if (!(gSideStatuses[side] & SIDE_STATUS_TAILWIND)) { gSideStatuses[side] |= SIDE_STATUS_TAILWIND; - gSideTimers[side].tailwindTimer = gBattleTurnCounter + (B_TAILWIND_TURNS >= GEN_5 ? 4 : 3); + gSideTimers[side].tailwindTimer = (B_TAILWIND_TURNS >= GEN_5 ? 4 : 3); gBattlescriptCurrInstr = cmd->nextInstr; } else @@ -11964,8 +11829,8 @@ static void Cmd_healpartystatus(void) struct Pokemon *party = GetBattlerParty(gBattlerAttacker); bool32 isSoundMove = IsSoundMove(gCurrentMove); - if (GetGenConfig(GEN_CONFIG_HEAL_BELL_SOUNDPROOF) == GEN_5 - || GetGenConfig(GEN_CONFIG_HEAL_BELL_SOUNDPROOF) >= GEN_8 + if (GetConfig(CONFIG_HEAL_BELL_SOUNDPROOF) == GEN_5 + || GetConfig(CONFIG_HEAL_BELL_SOUNDPROOF) >= GEN_8 || !(isSoundMove && GetBattlerAbility(gBattlerAttacker) == ABILITY_SOUNDPROOF)) { if (isSoundMove) @@ -11985,7 +11850,7 @@ static void Cmd_healpartystatus(void) if (IsBattlerAlive(partner)) { - if (GetGenConfig(GEN_CONFIG_HEAL_BELL_SOUNDPROOF) == GEN_5 + if (GetConfig(CONFIG_HEAL_BELL_SOUNDPROOF) == GEN_5 || !(isSoundMove && GetBattlerAbility(partner) == ABILITY_SOUNDPROOF)) { gBattleMons[partner].status1 = 0; @@ -12007,14 +11872,14 @@ static void Cmd_healpartystatus(void) if (species != SPECIES_NONE && species != SPECIES_EGG) { - u16 ability; + enum Ability ability; bool32 isAttacker = gBattlerPartyIndexes[gBattlerAttacker] == i; bool32 isDoublesPartner = gBattlerPartyIndexes[partner] == i && IsBattlerAlive(partner); - if (GetGenConfig(GEN_CONFIG_HEAL_BELL_SOUNDPROOF) == GEN_5 - || (GetGenConfig(GEN_CONFIG_HEAL_BELL_SOUNDPROOF) >= GEN_8 && isAttacker)) + if (GetConfig(CONFIG_HEAL_BELL_SOUNDPROOF) == GEN_5 + || (GetConfig(CONFIG_HEAL_BELL_SOUNDPROOF) >= GEN_8 && isAttacker)) ability = ABILITY_NONE; - else if (GetGenConfig(GEN_CONFIG_HEAL_BELL_SOUNDPROOF) > GEN_5 && !isAttacker && !isDoublesPartner) + else if (GetConfig(CONFIG_HEAL_BELL_SOUNDPROOF) > GEN_5 && !isAttacker && !isDoublesPartner) ability = ABILITY_NONE; else if (isAttacker) ability = GetBattlerAbility(gBattlerAttacker); @@ -12061,10 +11926,7 @@ static void Cmd_cursetarget(void) else { gBattleMons[gBattlerTarget].volatiles.cursed = TRUE; - gBattleStruct->moveDamage[gBattlerAttacker] = GetNonDynamaxMaxHP(gBattlerAttacker) / 2; - if (gBattleStruct->moveDamage[gBattlerAttacker] == 0) - gBattleStruct->moveDamage[gBattlerAttacker] = 1; - + SetPassiveDamageAmount(gBattlerAttacker, GetNonDynamaxMaxHP(gBattlerAttacker) / 2); gBattlescriptCurrInstr = cmd->nextInstr; } } @@ -12202,7 +12064,7 @@ static void Cmd_setembargo(void) else { gBattleMons[gBattlerTarget].volatiles.embargo = TRUE; - gDisableStructs[gBattlerTarget].embargoTimer = gBattleTurnCounter + 5; + gDisableStructs[gBattlerTarget].embargoTimer = 5; gBattlescriptCurrInstr = cmd->nextInstr; } } @@ -12211,7 +12073,7 @@ static void Cmd_presentdamagecalculation(void) { CMD_ARGS(); - u32 rand = Random() & 0xFF; + u32 rand = RandomUniform(RNG_PRESENT, 0, 0xFF); /* Don't reroll present effect/power for the second hit of Parental Bond. * Not sure if this is the correct behaviour, but bulbapedia states @@ -12235,11 +12097,7 @@ static void Cmd_presentdamagecalculation(void) } else { - // TODO: Check if this is correct - gBattleStruct->moveDamage[gBattlerTarget] = GetNonDynamaxMaxHP(gBattlerTarget) / 4; - if (gBattleStruct->moveDamage[gBattlerTarget] == 0) - gBattleStruct->moveDamage[gBattlerTarget] = 1; - gBattleStruct->moveDamage[gBattlerTarget] *= -1; + SetHealAmount(gBattlerTarget, GetNonDynamaxMaxHP(gBattlerTarget) / 4); gBattleStruct->presentBasePower = 0; } } @@ -12271,7 +12129,7 @@ static void Cmd_setsafeguard(void) else { gSideStatuses[GetBattlerSide(gBattlerAttacker)] |= SIDE_STATUS_SAFEGUARD; - gSideTimers[GetBattlerSide(gBattlerAttacker)].safeguardTimer = gBattleTurnCounter + 5; + gSideTimers[GetBattlerSide(gBattlerAttacker)].safeguardTimer = 5; gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SET_SAFEGUARD; } @@ -12282,7 +12140,7 @@ static void Cmd_magnitudedamagecalculation(void) { CMD_ARGS(); - u32 magnitude = Random() % 100; + u32 magnitude = RandomUniform(RNG_MAGNITUDE, 0, 99); if (magnitude < 5) { @@ -12377,12 +12235,30 @@ static void Cmd_jumpifnopursuitswitchdmg(void) } } -static void Cmd_tryrestorehpberry(void) +static void Cmd_tryactivateitem(void) { - CMD_ARGS(); - if (TryRestoreHPBerries(gBattlerAttacker, ITEMEFFECT_TRY_HEALING)) - return; + CMD_ARGS(u8 battler, u8 flag); + u32 battler = GetBattlerForBattleScript(cmd->battler); + gBattlescriptCurrInstr = cmd->nextInstr; + + switch ((enum ItemActivationState)cmd->flag) + { + case ACTIVATION_ON_USABLE_AGAIN: + case ACTIVATION_ON_PICK_UP: + if (ItemBattleEffects(battler, 0, GetBattlerHoldEffect(battler), IsForceTriggerItemActivation)) + return; + break; + case ACTIVATION_ON_HARVEST: + gLastUsedItem = gBattleMons[battler].item; + if (ItemBattleEffects(battler, 0, GetBattlerHoldEffect(battler), IsOnBerryActivation)) + return; + break; + case ACTIVATION_ON_HP_THRESHOLD: + if (ItemBattleEffects(battler, 0, GetBattlerHoldEffect(battler), IsOnHpThresholdActivation)) + return; + break; + } } // Belly Drum, Fillet Away @@ -12397,10 +12273,7 @@ static void Cmd_halvehp(void) if (gBattleMons[gBattlerAttacker].hp > halfHp) { - gBattleStruct->moveDamage[gBattlerAttacker] = GetNonDynamaxMaxHP(gBattlerAttacker) / 2; - if (gBattleStruct->moveDamage[gBattlerAttacker] == 0) - gBattleStruct->moveDamage[gBattlerAttacker] = 1; - + SetPassiveDamageAmount(gBattlerAttacker, GetNonDynamaxMaxHP(gBattlerAttacker) / 2); gBattlescriptCurrInstr = cmd->nextInstr; } else @@ -12435,8 +12308,8 @@ static void Cmd_rapidspinfree(void) { gBattleScripting.battler = gBattlerTarget; gBattleMons[gBattlerAttacker].volatiles.wrapped = FALSE; - gBattlerTarget = gBattleStruct->wrappedBy[gBattlerAttacker]; - PREPARE_MOVE_BUFFER(gBattleTextBuff1, gBattleStruct->wrappedMove[gBattlerAttacker]); + gBattlerTarget = gBattleMons[gBattlerAttacker].volatiles.wrappedBy; + PREPARE_MOVE_BUFFER(gBattleTextBuff1, gBattleMons[gBattlerAttacker].volatiles.wrappedMove); BattleScriptCall(BattleScript_WrapFree); } else if (gBattleMons[gBattlerAttacker].volatiles.leechSeed) @@ -12474,21 +12347,22 @@ static void Cmd_recoverbasedonsunlight(void) gBattlerTarget = gBattlerAttacker; if (gBattleMons[gBattlerAttacker].hp != gBattleMons[gBattlerAttacker].maxHP) { + s32 recoverAmount = 0; if (GetMoveEffect(gCurrentMove) == EFFECT_SHORE_UP) { if (HasWeatherEffect() && gBattleWeather & B_WEATHER_SANDSTORM) - gBattleStruct->moveDamage[gBattlerAttacker] = 20 * GetNonDynamaxMaxHP(gBattlerAttacker) / 30; + recoverAmount = 20 * GetNonDynamaxMaxHP(gBattlerAttacker) / 30; else - gBattleStruct->moveDamage[gBattlerAttacker] = GetNonDynamaxMaxHP(gBattlerAttacker) / 2; + recoverAmount = GetNonDynamaxMaxHP(gBattlerAttacker) / 2; } - else if (GetGenConfig(GEN_CONFIG_TIME_OF_DAY_HEALING_MOVES) != GEN_2) + else if (GetConfig(CONFIG_TIME_OF_DAY_HEALING_MOVES) != GEN_2) { - if (!(gBattleWeather & B_WEATHER_ANY) || !HasWeatherEffect() || GetBattlerHoldEffect(gBattlerAttacker, TRUE) == HOLD_EFFECT_UTILITY_UMBRELLA) - gBattleStruct->moveDamage[gBattlerAttacker] = GetNonDynamaxMaxHP(gBattlerAttacker) / 2; + if (!(gBattleWeather & B_WEATHER_ANY) || !HasWeatherEffect() || GetBattlerHoldEffect(gBattlerAttacker) == HOLD_EFFECT_UTILITY_UMBRELLA) + recoverAmount = GetNonDynamaxMaxHP(gBattlerAttacker) / 2; else if (gBattleWeather & B_WEATHER_SUN) - gBattleStruct->moveDamage[gBattlerAttacker] = 20 * GetNonDynamaxMaxHP(gBattlerAttacker) / 30; + recoverAmount = 20 * GetNonDynamaxMaxHP(gBattlerAttacker) / 30; else // not sunny weather - gBattleStruct->moveDamage[gBattlerAttacker] = GetNonDynamaxMaxHP(gBattlerAttacker) / 4; + recoverAmount = GetNonDynamaxMaxHP(gBattlerAttacker) / 4; } else // B_TIME_OF_DAY_HEALING_MOVES == GEN_2 { @@ -12515,19 +12389,16 @@ static void Cmd_recoverbasedonsunlight(void) break; } - if (!(gBattleWeather & B_WEATHER_ANY) || !HasWeatherEffect() || GetBattlerHoldEffect(gBattlerAttacker, TRUE) == HOLD_EFFECT_UTILITY_UMBRELLA) - gBattleStruct->moveDamage[gBattlerAttacker] = healingModifier * GetNonDynamaxMaxHP(gBattlerAttacker) / 4; + if (!(gBattleWeather & B_WEATHER_ANY) || !HasWeatherEffect() || GetBattlerHoldEffect(gBattlerAttacker) == HOLD_EFFECT_UTILITY_UMBRELLA) + recoverAmount = healingModifier * GetNonDynamaxMaxHP(gBattlerAttacker) / 4; else if (gBattleWeather & B_WEATHER_SUN) - gBattleStruct->moveDamage[gBattlerAttacker] = healingModifier * GetNonDynamaxMaxHP(gBattlerAttacker) / 2; + recoverAmount = healingModifier * GetNonDynamaxMaxHP(gBattlerAttacker) / 2; else // not sunny weather - gBattleStruct->moveDamage[gBattlerAttacker] = healingModifier * GetNonDynamaxMaxHP(gBattlerAttacker) / 8; + recoverAmount = healingModifier * GetNonDynamaxMaxHP(gBattlerAttacker) / 8; } - if (gBattleStruct->moveDamage[gBattlerAttacker] == 0) - gBattleStruct->moveDamage[gBattlerAttacker] = 1; - gBattleStruct->moveDamage[gBattlerAttacker] *= -1; - + SetHealAmount(gBattlerAttacker, recoverAmount); gBattlescriptCurrInstr = cmd->nextInstr; } else @@ -12571,76 +12442,40 @@ static void Cmd_selectfirstvalidtarget(void) gBattlescriptCurrInstr = cmd->nextInstr; } -static void Cmd_trysetfutureattack(void) +static void Cmd_setfutureattack(void) { - CMD_ARGS(const u8 *failInstr); + CMD_ARGS(); - if (gWishFutureKnock.futureSightCounter[gBattlerTarget] > gBattleTurnCounter) - { - gBattlescriptCurrInstr = cmd->failInstr; - } + gWishFutureKnock.futureSightMove[gBattlerTarget] = gCurrentMove; + gWishFutureKnock.futureSightBattlerIndex[gBattlerTarget] = gBattlerAttacker; + gWishFutureKnock.futureSightPartyIndex[gBattlerTarget] = gBattlerPartyIndexes[gBattlerAttacker]; + gWishFutureKnock.futureSightCounter[gBattlerTarget] = 3; + + if (gCurrentMove == MOVE_DOOM_DESIRE) + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_DOOM_DESIRE; else - { - gSideStatuses[GetBattlerSide(gBattlerTarget)] |= SIDE_STATUS_FUTUREATTACK; - gWishFutureKnock.futureSightMove[gBattlerTarget] = gCurrentMove; - gWishFutureKnock.futureSightBattlerIndex[gBattlerTarget] = gBattlerAttacker; - gWishFutureKnock.futureSightPartyIndex[gBattlerTarget] = gBattlerPartyIndexes[gBattlerAttacker]; - gWishFutureKnock.futureSightCounter[gBattlerTarget] = gBattleTurnCounter + 3; + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_FUTURE_SIGHT; - if (gCurrentMove == MOVE_DOOM_DESIRE) - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_DOOM_DESIRE; - else - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_FUTURE_SIGHT; - - gBattlescriptCurrInstr = cmd->nextInstr; - } + gBattlescriptCurrInstr = cmd->nextInstr; } static void Cmd_trydobeatup(void) { CMD_ARGS(const u8 *endInstr, const u8 *failInstr); - struct Pokemon *party = GetBattlerParty(gBattlerAttacker); if (!IsBattlerAlive(gBattlerTarget)) { + gMultiHitCounter = 0; gBattlescriptCurrInstr = cmd->endInstr; } + else if (gBattleStruct->beatUpSlot == 0 && gMultiHitCounter == 0) + { + gBattlescriptCurrInstr = cmd->failInstr; + } else { - u8 beforeLoop = gBattleCommunication[0]; - for (;gBattleCommunication[0] < PARTY_SIZE; gBattleCommunication[0]++) - { - if (GetMonData(&party[gBattleCommunication[0]], MON_DATA_HP) - && GetMonData(&party[gBattleCommunication[0]], MON_DATA_SPECIES_OR_EGG) != SPECIES_NONE - && GetMonData(&party[gBattleCommunication[0]], MON_DATA_SPECIES_OR_EGG) != SPECIES_EGG - && !GetMonData(&party[gBattleCommunication[0]], MON_DATA_STATUS)) - break; - } - - if (gBattleCommunication[0] < PARTY_SIZE) - { - PREPARE_MON_NICK_WITH_PREFIX_BUFFER(gBattleTextBuff1, gBattlerAttacker, gBattleCommunication[0]) - - gBattlescriptCurrInstr = cmd->nextInstr; - - gBattleStruct->moveDamage[gBattlerTarget] = GetSpeciesBaseAttack(GetMonData(&party[gBattleCommunication[0]], MON_DATA_SPECIES)); - gBattleStruct->moveDamage[gBattlerTarget] *= GetMovePower(gCurrentMove); - gBattleStruct->moveDamage[gBattlerTarget] *= (GetMonData(&party[gBattleCommunication[0]], MON_DATA_LEVEL) * 2 / 5 + 2); - gBattleStruct->moveDamage[gBattlerTarget] /= GetSpeciesBaseDefense(gBattleMons[gBattlerTarget].species); - gBattleStruct->moveDamage[gBattlerTarget] = (gBattleStruct->moveDamage[gBattlerTarget] / 50) + 2; - if (gProtectStructs[gBattlerAttacker].helpingHand) - gBattleStruct->moveDamage[gBattlerTarget] = gBattleStruct->moveDamage[gBattlerTarget] * 15 / 10; - - gBattleCommunication[0]++; - } - else if (beforeLoop != 0) - { - gBattlescriptCurrInstr = cmd->endInstr; - } - else - { - gBattlescriptCurrInstr = cmd->failInstr; - } + PREPARE_MON_NICK_WITH_PREFIX_BUFFER(gBattleTextBuff1, gBattlerAttacker, gBattleStruct->beatUpSpecies[gBattleStruct->beatUpSlot]) + gBattlescriptCurrInstr = cmd->nextInstr; } } @@ -12725,9 +12560,10 @@ static void Cmd_trymemento(void) else { // Success, drop user's HP bar to 0 - gBattleStruct->moveDamage[gBattlerAttacker] = gBattleMons[gBattlerAttacker].hp; + gBattleStruct->passiveHpUpdate[gBattlerAttacker] = gBattleMons[gBattlerAttacker].hp; BtlController_EmitHealthBarUpdate(gBattlerAttacker, B_COMM_TO_CONTROLLER, INSTANT_HP_BAR_DROP); MarkBattlerForControllerExec(gBattlerAttacker); + gBattlescriptCurrInstr = cmd->nextInstr; } } @@ -12743,52 +12579,12 @@ static void Cmd_setforcedtarget(void) gBattlescriptCurrInstr = cmd->nextInstr; } -static void Cmd_setcharge(void) +static void Cmd_unused_0xcb(void) { - CMD_ARGS(u8 battler); - - u8 battler = GetBattlerForBattleScript(cmd->battler); - gBattleMons[battler].volatiles.charge = TRUE; - if (B_CHARGE < GEN_9) - gDisableStructs[battler].chargeTimer = 2; - else - gDisableStructs[battler].chargeTimer = 0; - gBattlescriptCurrInstr = cmd->nextInstr; } -// Nature Power -static void Cmd_callenvironmentattack(void) +static void Cmd_unused_0xCC(void) { - CMD_ARGS(); - - gHitMarker &= ~HITMARKER_ATTACKSTRING_PRINTED; - gCurrentMove = GetNaturePowerMove(gBattlerAttacker); - gBattlerTarget = GetBattleMoveTarget(gCurrentMove, NO_TARGET_OVERRIDE); - BattleScriptPush(GetMoveBattleScript(gCurrentMove)); - gBattlescriptCurrInstr = cmd->nextInstr; -} - -u32 GetNaturePowerMove(u32 battler) -{ - u32 move = gBattleEnvironmentInfo[gBattleEnvironment].naturePower; - if (gFieldStatuses & STATUS_FIELD_MISTY_TERRAIN) - move = MOVE_MOONBLAST; - else if (gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN) - move = MOVE_THUNDERBOLT; - else if (gFieldStatuses & STATUS_FIELD_GRASSY_TERRAIN) - move = MOVE_ENERGY_BALL; - else if (gFieldStatuses & STATUS_FIELD_PSYCHIC_TERRAIN) - move = MOVE_PSYCHIC; - else if (gBattleEnvironmentInfo[gBattleEnvironment].naturePower == MOVE_NONE) - move = MOVE_TRI_ATTACK; - - if (GetActiveGimmick(battler) == GIMMICK_Z_MOVE) - { - gBattleStruct->zmove.baseMoves[gBattlerAttacker] = move; - move = GetTypeBasedZMove(move); - } - - return move; } static void Cmd_curestatuswithmove(void) @@ -12847,7 +12643,7 @@ static void Cmd_settaunt(void) { CMD_ARGS(const u8 *failInstr); - if (GetGenConfig(GEN_CONFIG_OBLIVIOUS_TAUNT) >= GEN_6 && GetBattlerAbility(gBattlerTarget) == ABILITY_OBLIVIOUS) + if (GetConfig(CONFIG_OBLIVIOUS_TAUNT) >= GEN_6 && GetBattlerAbility(gBattlerTarget) == ABILITY_OBLIVIOUS) { gBattlescriptCurrInstr = BattleScript_NotAffectedAbilityPopUp; gLastUsedAbility = ABILITY_OBLIVIOUS; @@ -12884,11 +12680,16 @@ static void Cmd_trysethelpinghand(void) { CMD_ARGS(const u8 *failInstr); + if (!IsDoubleBattle()) + { + gBattlescriptCurrInstr = cmd->failInstr; + return; + } + gBattlerTarget = GetBattlerAtPosition(BATTLE_PARTNER(GetBattlerPosition(gBattlerAttacker))); - if (IsDoubleBattle() - && !(gAbsentBattlerFlags & (1u << gBattlerTarget)) - && !HasBattlerActedThisTurn(gBattlerTarget)) + if (!(gAbsentBattlerFlags & (1u << gBattlerTarget)) + && !HasBattlerActedThisTurn(gBattlerTarget)) { gProtectStructs[gBattlerTarget].helpingHand++; gBattlescriptCurrInstr = cmd->nextInstr; @@ -12944,6 +12745,10 @@ static void Cmd_tryswapitems(void) gBattlescriptCurrInstr = cmd->failInstr; } // check if ability prevents swapping + else if (GetBattlerAbility(gBattlerAttacker) == ABILITY_STICKY_HOLD) + { + gBattlescriptCurrInstr = cmd->failInstr; + } else if (GetBattlerAbility(gBattlerTarget) == ABILITY_STICKY_HOLD) { gBattlescriptCurrInstr = BattleScript_StickyHoldActivates; @@ -13012,7 +12817,7 @@ static void Cmd_tryswapitems(void) static bool32 CanAbilityShieldActivateForBattler(u32 battler) { - if (GetBattlerHoldEffectIgnoreAbility(battler, TRUE) != HOLD_EFFECT_ABILITY_SHIELD) + if (GetBattlerHoldEffectIgnoreAbility(battler) != HOLD_EFFECT_ABILITY_SHIELD) return FALSE; RecordItemEffectBattle(battler, HOLD_EFFECT_ABILITY_SHIELD); @@ -13028,7 +12833,7 @@ static void Cmd_trycopyability(void) u32 battler = GetBattlerForBattleScript(cmd->battler); u32 partner = BATTLE_PARTNER(battler); - u16 defAbility = gBattleMons[gBattlerTarget].ability; + enum Ability defAbility = gBattleMons[gBattlerTarget].ability; bool32 shouldConsiderPartner = IsBattlerAlive(partner) && GetMoveEffect(gCurrentMove) == EFFECT_DOODLE; if (gBattleMons[battler].ability == defAbility @@ -13046,6 +12851,7 @@ static void Cmd_trycopyability(void) } else { + RemoveAbilityFlags(battler); gBattleScripting.abilityPopupOverwrite = gBattleMons[battler].ability; gBattleMons[battler].ability = gDisableStructs[battler].overwrittenAbility = defAbility; gLastUsedAbility = defAbility; @@ -13061,9 +12867,9 @@ static void Cmd_trywish(void) { gBattlescriptCurrInstr = cmd->failInstr; } - else if (gWishFutureKnock.wishCounter[gBattlerAttacker] <= gBattleTurnCounter) + else if (gWishFutureKnock.wishCounter[gBattlerAttacker] == 0) { - gWishFutureKnock.wishCounter[gBattlerAttacker] = gBattleTurnCounter + 2; + gWishFutureKnock.wishCounter[gBattlerAttacker] = 2; gWishFutureKnock.wishPartyId[gBattlerAttacker] = gBattlerPartyIndexes[gBattlerAttacker]; gBattlescriptCurrInstr = cmd->nextInstr; } @@ -13099,14 +12905,14 @@ static void Cmd_setgastroacid(void) { gBattlescriptCurrInstr = cmd->failInstr; } - else if (GetBattlerHoldEffectIgnoreAbility(gBattlerTarget, TRUE) == HOLD_EFFECT_ABILITY_SHIELD) + else if (GetBattlerHoldEffectIgnoreAbility(gBattlerTarget) == HOLD_EFFECT_ABILITY_SHIELD) { RecordItemEffectBattle(gBattlerTarget, HOLD_EFFECT_ABILITY_SHIELD); gBattlescriptCurrInstr = cmd->failInstr; } else { - if (gBattleMons[gBattlerTarget].ability == ABILITY_NEUTRALIZING_GAS) + if (gDisableStructs[gBattlerTarget].neutralizingGas) gSpecialStatuses[gBattlerTarget].neutralizingGasRemoved = TRUE; gBattleMons[gBattlerTarget].volatiles.gastroAcid = TRUE; @@ -13117,19 +12923,21 @@ static void Cmd_setgastroacid(void) static void Cmd_setyawn(void) { CMD_ARGS(const u8 *failInstr); + enum Ability ability = GetBattlerAbility(gBattlerTarget); + enum HoldEffect holdEffect = GetBattlerHoldEffect(gBattlerTarget); if (gBattleMons[gBattlerTarget].volatiles.yawn || gBattleMons[gBattlerTarget].status1 & STATUS1_ANY) { gBattlescriptCurrInstr = cmd->failInstr; } - else if (IsBattlerTerrainAffected(gBattlerTarget, STATUS_FIELD_ELECTRIC_TERRAIN)) + else if (IsBattlerTerrainAffected(gBattlerTarget, ability, holdEffect, STATUS_FIELD_ELECTRIC_TERRAIN)) { // When Yawn is used while Electric Terrain is set and drowsiness is set from Yawn being used against target in the previous turn: // "But it failed" will display first. gBattlescriptCurrInstr = BattleScript_ElectricTerrainPrevents; } - else if (IsBattlerTerrainAffected(gBattlerTarget, STATUS_FIELD_MISTY_TERRAIN)) + else if (IsBattlerTerrainAffected(gBattlerTarget, ability, holdEffect, STATUS_FIELD_MISTY_TERRAIN)) { // When Yawn is used while Misty Terrain is set and drowsiness is set from Yawn being used against target in the previous turn: // "But it failed" will display first. @@ -13167,7 +12975,7 @@ static void HandleRoomMove(u32 statusFlag, u16 *timer, u8 stringId) else { gFieldStatuses |= statusFlag; - *timer = gBattleTurnCounter + 5; + *timer = 5; gBattleCommunication[MULTISTRING_CHOOSER] = stringId; } } @@ -13221,6 +13029,8 @@ static void Cmd_tryswapabilities(void) if (!IsBattlerAlly(gBattlerAttacker, gBattlerTarget)) gBattleScripting.abilityPopupOverwrite = gBattleMons[gBattlerAttacker].ability; gLastUsedAbility = gBattleMons[gBattlerTarget].ability; + RemoveAbilityFlags(gBattlerTarget); + RemoveAbilityFlags(gBattlerAttacker); gBattleMons[gBattlerTarget].ability = gDisableStructs[gBattlerTarget].overwrittenAbility = gBattleMons[gBattlerAttacker].ability; gBattleMons[gBattlerAttacker].ability = gDisableStructs[gBattlerAttacker].overwrittenAbility = gLastUsedAbility; @@ -13308,10 +13118,10 @@ static void Cmd_trysetvolatile(void) switch (cmd->_volatile) { case VOLATILE_MAGNET_RISE: - gDisableStructs[battler].magnetRiseTimer = gBattleTurnCounter + 5; + gDisableStructs[battler].magnetRiseTimer = 5; break; case VOLATILE_LASER_FOCUS: - gDisableStructs[battler].laserFocusTimer = gBattleTurnCounter + 2; + gDisableStructs[battler].laserFocusTimer = 2; break; default: break; @@ -13320,60 +13130,15 @@ static void Cmd_trysetvolatile(void) } } -static void Cmd_assistattackselect(void) +static void Cmd_unused_0xde(void) { - CMD_ARGS(const u8 *failInstr); - - s32 chooseableMovesNo = 0; - struct Pokemon *party; - s32 monId, moveId; - u16 *validMoves = Alloc(sizeof(u16) * PARTY_SIZE * MAX_MON_MOVES); - - if (validMoves != NULL) - { - party = GetBattlerParty(gBattlerAttacker); - - for (monId = 0; monId < PARTY_SIZE; monId++) - { - if (monId == gBattlerPartyIndexes[gBattlerAttacker]) - continue; - if (GetMonData(&party[monId], MON_DATA_SPECIES_OR_EGG) == SPECIES_NONE) - continue; - if (GetMonData(&party[monId], MON_DATA_SPECIES_OR_EGG) == SPECIES_EGG) - continue; - - for (moveId = 0; moveId < MAX_MON_MOVES; moveId++) - { - u16 move = GetMonData(&party[monId], MON_DATA_MOVE1 + moveId); - - if (IsMoveAssistBanned(move)) - continue; - - validMoves[chooseableMovesNo++] = move; - } - } - } - - if (chooseableMovesNo) - { - gHitMarker &= ~HITMARKER_ATTACKSTRING_PRINTED; - gCalledMove = validMoves[Random() % chooseableMovesNo]; - gBattlerTarget = GetBattleMoveTarget(gCalledMove, NO_TARGET_OVERRIDE); - gBattlescriptCurrInstr = cmd->nextInstr; - } - else - { - gBattlescriptCurrInstr = cmd->failInstr; - } - - TRY_FREE_AND_SET_NULL(validMoves); } static void Cmd_trysetmagiccoat(void) { CMD_ARGS(const u8 *failInstr); - if (gCurrentTurnActionNumber == gBattlersCount - 1) // moves last turn + if (IsLastMonToMove(gBattlerAttacker)) // fails if moving last { gBattlescriptCurrInstr = cmd->failInstr; } @@ -13389,7 +13154,7 @@ static void Cmd_trysetsnatch(void) { CMD_ARGS(const u8 *failInstr); - if (gCurrentTurnActionNumber == gBattlersCount - 1) // moves last turn + if (IsLastMonToMove(gBattlerAttacker)) // fails if moving last { gBattlescriptCurrInstr = cmd->failInstr; } @@ -13409,44 +13174,48 @@ static void Cmd_switchoutabilities(void) CMD_ARGS(u8 battler); u32 battler = GetBattlerForBattleScript(cmd->battler); - if (gBattleMons[battler].ability == ABILITY_NEUTRALIZING_GAS) + if (gDisableStructs[battler].neutralizingGas) { - gBattleMons[battler].ability = ABILITY_NONE; - BattleScriptPush(gBattlescriptCurrInstr); - gBattlescriptCurrInstr = BattleScript_NeutralizingGasExits; + gDisableStructs[battler].neutralizingGas = FALSE; + if (!IsNeutralizingGasOnField()) + { + BattleScriptPush(gBattlescriptCurrInstr); + gBattlescriptCurrInstr = BattleScript_NeutralizingGasExits; + return; + } } - else + + switch (GetBattlerAbility(battler)) { - switch (GetBattlerAbility(battler)) - { - case ABILITY_NATURAL_CURE: - if (gBattleMons[battler].status1 & STATUS1_SLEEP) - TryDeactivateSleepClause(GetBattlerSide(battler), gBattlerPartyIndexes[battler]); + case ABILITY_NATURAL_CURE: + if (gBattleMons[battler].status1 & STATUS1_SLEEP) + TryDeactivateSleepClause(GetBattlerSide(battler), gBattlerPartyIndexes[battler]); - gBattleMons[battler].status1 = 0; - BtlController_EmitSetMonData(battler, B_COMM_TO_CONTROLLER, REQUEST_STATUS_BATTLE, - 1u << gBattleStruct->battlerPartyIndexes[battler], - sizeof(gBattleMons[battler].status1), - &gBattleMons[battler].status1); - MarkBattlerForControllerExec(battler); - break; - case ABILITY_REGENERATOR: - { - u32 regenerate = GetNonDynamaxMaxHP(battler) / 3; - regenerate += gBattleMons[battler].hp; - if (regenerate > gBattleMons[battler].maxHP) - regenerate = gBattleMons[battler].maxHP; - BtlController_EmitSetMonData(battler, B_COMM_TO_CONTROLLER, REQUEST_HP_BATTLE, - 1u << gBattleStruct->battlerPartyIndexes[battler], - sizeof(regenerate), - ®enerate); - MarkBattlerForControllerExec(battler); - break; - } - } - - gBattlescriptCurrInstr = cmd->nextInstr; + gBattleMons[battler].status1 = 0; + BtlController_EmitSetMonData(battler, B_COMM_TO_CONTROLLER, REQUEST_STATUS_BATTLE, + 1u << gBattleStruct->battlerPartyIndexes[battler], + sizeof(gBattleMons[battler].status1), + &gBattleMons[battler].status1); + MarkBattlerForControllerExec(battler); + break; + case ABILITY_REGENERATOR: + { + u32 regenerate = GetNonDynamaxMaxHP(battler) / 3; + regenerate += gBattleMons[battler].hp; + if (regenerate > gBattleMons[battler].maxHP) + regenerate = gBattleMons[battler].maxHP; + BtlController_EmitSetMonData(battler, B_COMM_TO_CONTROLLER, REQUEST_HP_BATTLE, + 1u << gBattleStruct->battlerPartyIndexes[battler], + sizeof(regenerate), + ®enerate); + MarkBattlerForControllerExec(battler); + break; } + default: + break; + } + + gBattlescriptCurrInstr = cmd->nextInstr; } static void Cmd_jumpifhasnohp(void) @@ -13461,18 +13230,8 @@ static void Cmd_jumpifhasnohp(void) gBattlescriptCurrInstr = cmd->nextInstr; } -static void Cmd_jumpifnotcurrentmoveargtype(void) +static void Cmd_unused_0xE4(void) { - CMD_ARGS(u8 battler, const u8 *failInstr); - - u8 battler = GetBattlerForBattleScript(cmd->battler); - const u8 *failInstr = cmd->failInstr; - u32 type = GetMoveArgType(gCurrentMove); - - if (!IS_BATTLER_OF_TYPE(battler, type)) - gBattlescriptCurrInstr = failInstr; - else - gBattlescriptCurrInstr = cmd->nextInstr; } static void Cmd_pickup(void) @@ -13480,8 +13239,9 @@ static void Cmd_pickup(void) CMD_ARGS(); u32 i, j; - u16 species, heldItem, ability; + u16 species, heldItem; u8 lvlDivBy10; + enum Ability ability; if (!InBattlePike()) // No items in Battle Pike. { @@ -13570,7 +13330,7 @@ static void Cmd_settypebasedhalvers(void) if (!(gFieldStatuses & STATUS_FIELD_MUDSPORT)) { gFieldStatuses |= STATUS_FIELD_MUDSPORT; - gFieldTimers.mudSportTimer = gBattleTurnCounter + 5; + gFieldTimers.mudSportTimer = 5; gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_WEAKEN_ELECTRIC; worked = TRUE; } @@ -13592,7 +13352,7 @@ static void Cmd_settypebasedhalvers(void) if (!(gFieldStatuses & STATUS_FIELD_WATERSPORT)) { gFieldStatuses |= STATUS_FIELD_WATERSPORT; - gFieldTimers.waterSportTimer = gBattleTurnCounter + 5; + gFieldTimers.waterSportTimer = 5; gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_WEAKEN_FIRE; worked = TRUE; } @@ -13628,11 +13388,10 @@ bool32 DoesSubstituteBlockMove(u32 battlerAtk, u32 battlerDef, u32 move) bool32 DoesDisguiseBlockMove(u32 battler, u32 move) { - if (!(gBattleMons[battler].species == SPECIES_MIMIKYU_DISGUISED || gBattleMons[battler].species == SPECIES_MIMIKYU_TOTEM_DISGUISED) - || gBattleMons[battler].volatiles.transformed - || (!gProtectStructs[battler].confusionSelfDmg && (IsBattleMoveStatus(move) || gHitMarker & HITMARKER_PASSIVE_HP_UPDATE)) - || gHitMarker & HITMARKER_IGNORE_DISGUISE - || !IsAbilityAndRecord(battler, GetBattlerAbility(battler), ABILITY_DISGUISE)) + if (!IsMimikyuDisguised(battler) + || gBattleMons[battler].volatiles.transformed + || (!gProtectStructs[battler].confusionSelfDmg && IsBattleMoveStatus(move)) + || !IsAbilityAndRecord(battler, GetBattlerAbility(battler), ABILITY_DISGUISE)) return FALSE; else return TRUE; @@ -13655,9 +13414,9 @@ static void Cmd_tryrecycleitem(void) u16 *usedHeldItem; if (gCurrentMove == MOVE_NONE && GetBattlerAbility(gBattlerAttacker) == ABILITY_PICKUP) - usedHeldItem = &gBattleStruct->usedHeldItems[gBattlerPartyIndexes[gBattlerTarget]][GetBattlerSide(gBattlerTarget)]; + usedHeldItem = &GetBattlerPartyState(gBattlerTarget)->usedHeldItem; else - usedHeldItem = &gBattleStruct->usedHeldItems[gBattlerPartyIndexes[gBattlerAttacker]][GetBattlerSide(gBattlerAttacker)]; + usedHeldItem = &GetBattlerPartyState(gBattlerAttacker)->usedHeldItem; if (*usedHeldItem != ITEM_NONE && gBattleMons[gBattlerAttacker].item == ITEM_NONE) { gLastUsedItem = *usedHeldItem; @@ -14085,9 +13844,13 @@ static void Cmd_handleballthrow(void) if (shakes == maxShakes) // mon caught, copy of the code above { - if (IsCriticalCapture()) + enum NationalDexOrder natDexNo = SpeciesToNationalPokedexNum(gBattleMons[gBattlerTarget].species); + if ((B_CRITICAL_CAPTURE_IF_OWNED >= GEN_9 && GetSetPokedexFlag(natDexNo, FLAG_GET_CAUGHT)) + || IsCriticalCapture()) + { + gBattleSpritesDataPtr->animationData->isCriticalCapture = TRUE; gBattleSpritesDataPtr->animationData->criticalCaptureSuccess = TRUE; - + } TryBattleFormChange(gBattlerTarget, FORM_CHANGE_END_BATTLE); gBattlescriptCurrInstr = BattleScript_SuccessBallThrow; struct Pokemon *caughtMon = GetBattlerMon(gBattlerTarget); @@ -14503,12 +14266,8 @@ static void Cmd_trygivecaughtmonnick(void) } } -static void Cmd_subattackerhpbydmg(void) +static void Cmd_unused_0xf4(void) { - CMD_ARGS(); - - gBattleMons[gBattlerAttacker].hp -= gBattleStruct->moveDamage[gBattlerTarget]; - gBattlescriptCurrInstr = cmd->nextInstr; } static void Cmd_removeattackerstatus1(void) @@ -14580,7 +14339,7 @@ static void Cmd_settelekinesis(void) else { gBattleMons[gBattlerTarget].volatiles.telekinesis = TRUE; - gDisableStructs[gBattlerTarget].telekinesisTimer = gBattleTurnCounter + 3; + gDisableStructs[gBattlerTarget].telekinesisTimer = 3; gBattlescriptCurrInstr = cmd->nextInstr; } } @@ -14599,7 +14358,7 @@ static void Cmd_swapstatstages(void) gBattlescriptCurrInstr = cmd->nextInstr; } -static u16 *GetBattlerStat(struct BattlePokemon *battler, u32 stat) +static u16 *GetBattlerStat(struct BattlePokemon *battler, enum Stat stat) { switch (stat) { @@ -14646,31 +14405,30 @@ static void Cmd_jumpifcaptivateaffected(void) static void Cmd_setnonvolatilestatus(void) { CMD_ARGS(u8 trigger); - gBattlescriptCurrInstr = cmd->nextInstr - 1; switch (cmd->trigger) { case TRIGGER_ON_ABILITY: if (gBattleScripting.moveEffect >= MOVE_EFFECT_CONFUSION) - SetMoveEffect(gBattleScripting.battler, gEffectBattler, FALSE, FALSE); + SetMoveEffect(gBattleScripting.battler, gEffectBattler, gBattleScripting.moveEffect, cmd->nextInstr, EFFECT_PRIMARY); else - SetNonVolatileStatus(gEffectBattler, gBattleScripting.moveEffect, TRIGGER_ON_ABILITY); + SetNonVolatileStatus(gEffectBattler, gBattleScripting.moveEffect, cmd->nextInstr, TRIGGER_ON_ABILITY); break; case TRIGGER_ON_MOVE: - SetNonVolatileStatus(gBattlerTarget, GetMoveNonVolatileStatus(gCurrentMove), TRIGGER_ON_MOVE); + SetNonVolatileStatus(gBattlerTarget, GetMoveNonVolatileStatus(gCurrentMove), cmd->nextInstr, TRIGGER_ON_MOVE); break; case TRIGGER_ON_PROTECT: - SetNonVolatileStatus(gBattlerAttacker, gBattleScripting.moveEffect, TRIGGER_ON_PROTECT); + SetNonVolatileStatus(gBattlerAttacker, gBattleScripting.moveEffect, cmd->nextInstr, TRIGGER_ON_PROTECT); break; } } -static void Cmd_tryworryseed(void) +static void Cmd_tryoverwriteability(void) { CMD_ARGS(const u8 *failInstr); if (gAbilitiesInfo[gBattleMons[gBattlerTarget].ability].cantBeOverwritten - || gBattleMons[gBattlerTarget].ability == ABILITY_INSOMNIA) + || gBattleMons[gBattlerTarget].ability == GetMoveOverwriteAbility(gCurrentMove)) { RecordAbilityBattle(gBattlerTarget, gBattleMons[gBattlerTarget].ability); gBattlescriptCurrInstr = cmd->failInstr; @@ -14682,11 +14440,12 @@ static void Cmd_tryworryseed(void) } else { - if (gBattleMons[gBattlerTarget].ability == ABILITY_NEUTRALIZING_GAS) + if (gDisableStructs[gBattlerTarget].neutralizingGas) gSpecialStatuses[gBattlerTarget].neutralizingGasRemoved = TRUE; + RemoveAbilityFlags(gBattlerTarget); gBattleScripting.abilityPopupOverwrite = gBattleMons[gBattlerTarget].ability; - gBattleMons[gBattlerTarget].ability = gDisableStructs[gBattlerTarget].overwrittenAbility = ABILITY_INSOMNIA; + gBattleMons[gBattlerTarget].ability = gDisableStructs[gBattlerTarget].overwrittenAbility = GetMoveOverwriteAbility(gCurrentMove); gBattlescriptCurrInstr = cmd->nextInstr; } } @@ -14785,7 +14544,7 @@ void BS_CalcMetalBurstDmg(void) else gBattlerTarget = gProtectStructs[gBattlerAttacker].physicalBattlerId; - gBattleStruct->moveDamage[gBattlerTarget] = gProtectStructs[gBattlerAttacker].physicalDmg * 150 / 100; + CalcReflectBackDamage(gProtectStructs[gBattlerAttacker].physicalDmg, 150); gBattlescriptCurrInstr = cmd->nextInstr; } else if (gProtectStructs[gBattlerAttacker].specialDmg @@ -14798,7 +14557,7 @@ void BS_CalcMetalBurstDmg(void) else gBattlerTarget = gProtectStructs[gBattlerAttacker].specialBattlerId; - gBattleStruct->moveDamage[gBattlerTarget] = gProtectStructs[gBattlerAttacker].specialDmg * 150 / 100; + CalcReflectBackDamage(gProtectStructs[gBattlerAttacker].specialDmg, 150); gBattlescriptCurrInstr = cmd->nextInstr; } else @@ -14807,17 +14566,6 @@ void BS_CalcMetalBurstDmg(void) } } -void BS_JumpIfCantFling(void) -{ - NATIVE_ARGS(u8 battler, const u8 *jumpInstr); - - u32 battler = GetBattlerForBattleScript(cmd->battler); - if (!CanFling(battler)) - gBattlescriptCurrInstr = cmd->jumpInstr; - else - gBattlescriptCurrInstr = cmd->nextInstr; -} - void BS_JumpIfMoreThanHalfHP(void) { NATIVE_ARGS(u8 battler, const u8 *jumpInstr); @@ -14856,6 +14604,7 @@ static bool32 CriticalCapture(u32 odds) { u32 numCaught; u32 totalDexCount; + u32 charmBoost = 1; if (B_CRITICAL_CAPTURE == FALSE) return FALSE; @@ -14865,23 +14614,25 @@ static bool32 CriticalCapture(u32 odds) else totalDexCount = NATIONAL_DEX_COUNT; - numCaught = GetNationalPokedexCount(FLAG_GET_CAUGHT); - - if (numCaught <= (totalDexCount * 30) / 650) - odds = 0; - else if (numCaught <= (totalDexCount * 150) / 650) - odds /= 2; - else if (numCaught <= (totalDexCount * 300) / 650) - ; // odds = (odds * 100) / 100; - else if (numCaught <= (totalDexCount * 450) / 650) - odds = (odds * 150) / 100; - else if (numCaught <= (totalDexCount * 600) / 650) - odds *= 2; - else - odds = (odds * 250) / 100; - if (CheckBagHasItem(ITEM_CATCHING_CHARM, 1)) - odds = (odds * (100 + B_CATCHING_CHARM_BOOST)) / 100; + charmBoost = (100 + B_CATCHING_CHARM_BOOST) / 100; + + numCaught = GetNationalPokedexCount(FLAG_GET_CAUGHT); + if (numCaught > (totalDexCount * 600) / 650) + odds = (odds * (250 * charmBoost)) / 100; + else if (numCaught > (totalDexCount * 450) / 650) + odds = (odds * (200 * charmBoost)) / 100; + else if (numCaught > (totalDexCount * 300) / 650) + odds = (odds * (150 * charmBoost)) / 100; + else if (numCaught > (totalDexCount * 150) / 650) + odds = (odds * (100 * charmBoost)) / 100; + else if (numCaught > (totalDexCount * 30) / 650) + odds = (odds * (50 * charmBoost)) / 100; + else + return FALSE; + + if (odds > 255) + odds = 255; odds /= 6; if (RandomUniform(RNG_BALLTHROW_CRITICAL, 0, MAX_u8) < odds) @@ -14923,19 +14674,22 @@ bool32 IsMoveAffectedByParentalBond(u32 move, u32 battler) return FALSE; } -static bool8 IsFinalStrikeEffect(enum BattleMoveEffects moveEffect) +static bool32 IsFinalStrikeEffect(enum MoveEffect moveEffect) { - u32 i; - - for (i = 0; i < ARRAY_COUNT(sFinalStrikeOnlyEffects); i++) + switch (moveEffect) { - if (moveEffect == sFinalStrikeOnlyEffects[i]) - return TRUE; + case MOVE_EFFECT_REMOVE_ARG_TYPE: + case MOVE_EFFECT_REMOVE_STATUS: + case MOVE_EFFECT_RECOIL_HP_25: + case MOVE_EFFECT_PREVENT_ESCAPE: + case MOVE_EFFECT_WRAP: + return TRUE; + default: + return FALSE; } - return FALSE; } -static bool32 CanAbilityPreventStatLoss(u32 abilityDef) +static bool32 CanAbilityPreventStatLoss(enum Ability abilityDef) { switch (abilityDef) { @@ -14943,6 +14697,8 @@ static bool32 CanAbilityPreventStatLoss(u32 abilityDef) case ABILITY_FULL_METAL_BODY: case ABILITY_WHITE_SMOKE: return TRUE; + default: + break; } return FALSE; } @@ -14951,7 +14707,7 @@ bool32 CanBurnHitThaw(u16 move) { u8 i; - if (B_BURN_HIT_THAW >= GEN_6) + if (GetConfig(CONFIG_BURN_HIT_THAW) >= GEN_6) { u32 numAdditionalEffects = GetMoveAdditionalEffectCount(move); for (i = 0; i < numAdditionalEffects; i++) @@ -15103,7 +14859,7 @@ u8 GetFirstFaintedPartyIndex(u8 battler) void ApplyExperienceMultipliers(s32 *expAmount, u8 expGetterMonId, u8 faintedBattler) { - enum ItemHoldEffect holdEffect = GetMonHoldEffect(&gPlayerParty[expGetterMonId]); + enum HoldEffect holdEffect = GetMonHoldEffect(&gPlayerParty[expGetterMonId]); if (IsTradedMon(&gPlayerParty[expGetterMonId])) *expAmount = (*expAmount * 150) / 100; @@ -15183,7 +14939,7 @@ void BS_ItemRestoreHP(void) // Heal is applied as move damage if battler is active. if (battler != MAX_BATTLERS_COUNT && hp != 0) { - gBattleStruct->moveDamage[battler] = -healAmount; + gBattleStruct->passiveHpUpdate[battler] = -healAmount; gBattlescriptCurrInstr = cmd->restoreBattlerInstr; } else @@ -15191,12 +14947,14 @@ void BS_ItemRestoreHP(void) hp += healAmount; SetMonData(&party[gBattleStruct->itemPartyIndex[gBattlerAttacker]], MON_DATA_HP, &hp); - // Revived battlers on the field need to be brought back. - if (IsDoubleBattle() && battler != MAX_BATTLERS_COUNT) + u32 partner = BATTLE_PARTNER(gBattlerAttacker); + // Absent battlers on the field need to be replaced + if (IsDoubleBattle() && (gAbsentBattlerFlags & (1u << partner))) { - gAbsentBattlerFlags &= ~(1u << battler); - gBattleMons[battler].hp = hp; + gAbsentBattlerFlags &= ~(1u << partner); gBattleCommunication[MULTIUSE_STATE] = TRUE; + gBattleScripting.battler = partner; + BtlController_EmitChosenMonReturnValue(partner, B_COMM_TO_ENGINE, gBattleStruct->itemPartyIndex[gBattlerAttacker], NULL); } gBattlescriptCurrInstr = cmd->nextInstr; } @@ -15205,37 +14963,47 @@ void BS_ItemRestoreHP(void) void BS_ItemCureStatus(void) { - NATIVE_ARGS(const u8 *noStatusInstr); - u32 battler = gBattlerAttacker; + NATIVE_ARGS(const u8 *noStatusInstr, const u8 *restoreBattlerInstr); + u32 targetBattler = MAX_BATTLERS_COUNT; bool32 statusChanged = FALSE; struct Pokemon *party = GetBattlerParty(gBattlerAttacker); // Heal volatile conditions if battler is active. if (gBattleStruct->itemPartyIndex[gBattlerAttacker] == gBattlerPartyIndexes[gBattlerAttacker]) - statusChanged = ItemHealMonVolatile(battler, gLastUsedItem); + { + statusChanged = ItemHealMonVolatile(gBattlerAttacker, gLastUsedItem); + targetBattler = gBattlerAttacker; + } else if (IsDoubleBattle() && gBattleStruct->itemPartyIndex[gBattlerAttacker] == gBattlerPartyIndexes[BATTLE_PARTNER(gBattlerAttacker)]) + { statusChanged = ItemHealMonVolatile(BATTLE_PARTNER(gBattlerAttacker), gLastUsedItem); + targetBattler = BATTLE_PARTNER(gBattlerAttacker); + } // Heal Status1 conditions. - if (!HealStatusConditions(&party[gBattleStruct->itemPartyIndex[gBattlerAttacker]], GetItemStatus1Mask(gLastUsedItem), battler)) + if (!HealStatusConditions(&party[gBattleStruct->itemPartyIndex[gBattlerAttacker]], GetItemStatus1Mask(gLastUsedItem), targetBattler)) { statusChanged = TRUE; if (GetItemStatus1Mask(gLastUsedItem) & STATUS1_SLEEP) - gBattleMons[battler].volatiles.nightmare = FALSE; - if (ItemHasVolatileFlag(gLastUsedItem, VOLATILE_CONFUSION)) - gBattleMons[battler].volatiles.infiniteConfusion = FALSE; + gBattleMons[targetBattler].volatiles.nightmare = FALSE; } - if (statusChanged) + if (!statusChanged) + { + gBattlescriptCurrInstr = cmd->noStatusInstr; + return; + } + + PREPARE_SPECIES_BUFFER(gBattleTextBuff1, GetMonData(&party[gBattleStruct->itemPartyIndex[gBattlerAttacker]], MON_DATA_SPECIES)); + if (targetBattler == MAX_BATTLERS_COUNT) { - gBattleScripting.battler = battler; - PREPARE_SPECIES_BUFFER(gBattleTextBuff1, GetMonData(&party[gBattleStruct->itemPartyIndex[gBattlerAttacker]], MON_DATA_SPECIES)); gBattlescriptCurrInstr = cmd->nextInstr; } else { - gBattlescriptCurrInstr = cmd->noStatusInstr; + gBattleScripting.battler = targetBattler; + gBattlescriptCurrInstr = cmd->restoreBattlerInstr; } } @@ -15355,7 +15123,7 @@ void BS_JumpIfShellTrap(void) void BS_JumpIfElectricAbilityAffected(void) { - NATIVE_ARGS(u8 battler, u16 ability, const u8 *jumpInstr); + NATIVE_ARGS(u8 battler, enum Ability ability, const u8 *jumpInstr); u32 battler = GetBattlerForBattleScript(cmd->battler); if (IsElectricAbilityAffected(battler, cmd->ability)) @@ -15399,13 +15167,6 @@ void BS_SetTerrain(void) gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_TERRAIN_SET_PSYCHIC; } break; - case EFFECT_HIT_SET_TERRAIN: - if (!(gFieldStatuses & GetMoveTerrainFlag(gCurrentMove))) - { - statusFlag = GetMoveTerrainFlag(gCurrentMove); - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_TERRAIN_SET_PSYCHIC; - } - break; default: break; } @@ -15429,7 +15190,7 @@ void BS_JumpIfTerrainAffected(void) NATIVE_ARGS(u8 battler, u32 flags, const u8 *jumpInstr); u32 battler = GetBattlerForBattleScript(cmd->battler); - if (IsBattlerTerrainAffected(battler, cmd->flags)) + if (IsBattlerTerrainAffected(battler, GetBattlerAbility(battler), GetBattlerHoldEffect(battler), cmd->flags)) gBattlescriptCurrInstr = cmd->jumpInstr; else gBattlescriptCurrInstr = cmd->nextInstr; @@ -15439,7 +15200,7 @@ void BS_TryReflectType(void) { NATIVE_ARGS(const u8 *failInstr); u16 targetBaseSpecies = GET_BASE_SPECIES_ID(gBattleMons[gBattlerTarget].species); - u32 targetTypes[3]; + enum Type targetTypes[3]; GetBattlerTypes(gBattlerTarget, FALSE, targetTypes); if (targetBaseSpecies == SPECIES_ARCEUS || targetBaseSpecies == SPECIES_SILVALLY) @@ -15502,27 +15263,17 @@ void BS_TrySetOctolock(void) } } -void BS_SetGlaiveRush(void) -{ - NATIVE_ARGS(); - gBattleMons[gBattlerAttacker].volatiles.glaiveRush = TRUE; - gBattlescriptCurrInstr = cmd->nextInstr; -} - void BS_SetPledge(void) { NATIVE_ARGS(const u8 *jumpInstr); u32 partner = BATTLE_PARTNER(gBattlerAttacker); - u32 partnerMove = gBattleMons[partner].moves[gBattleStruct->chosenMovePositions[partner]]; + u32 partnerMove = GetChosenMoveFromPosition(partner); u32 i = 0; u32 k = 0; if (gBattleStruct->pledgeMove && !(gHitMarker & HITMARKER_UNABLE_TO_USE_MOVE)) { - PrepareStringBattle(STRINGID_USEDMOVE, gBattlerAttacker); - gHitMarker |= HITMARKER_ATTACKSTRING_PRINTED; - if ((gCurrentMove == MOVE_GRASS_PLEDGE && partnerMove == MOVE_WATER_PLEDGE) || (gCurrentMove == MOVE_WATER_PLEDGE && partnerMove == MOVE_GRASS_PLEDGE)) { @@ -15607,13 +15358,13 @@ void BS_SetPledgeStatus(void) switch (cmd->sideStatus) { case SIDE_STATUS_RAINBOW: - gSideTimers[side].rainbowTimer = gBattleTurnCounter + 4; + gSideTimers[side].rainbowTimer = 4; break; case SIDE_STATUS_SEA_OF_FIRE: - gSideTimers[side].seaOfFireTimer = gBattleTurnCounter + 4; + gSideTimers[side].seaOfFireTimer = 4; break; case SIDE_STATUS_SWAMP: - gSideTimers[side].swampTimer = gBattleTurnCounter + 4; + gSideTimers[side].swampTimer = 4; } gBattlescriptCurrInstr = cmd->nextInstr; @@ -15676,45 +15427,15 @@ void BS_TryHealPulse(void) } else { + s32 healAmount = 0; if (GetBattlerAbility(gBattlerAttacker) == ABILITY_MEGA_LAUNCHER && IsPulseMove(gCurrentMove)) - gBattleStruct->moveDamage[gBattlerTarget] = -(GetNonDynamaxMaxHP(gBattlerTarget) * 75 / 100); + healAmount = GetNonDynamaxMaxHP(gBattlerTarget) * 75 / 100; else if (gFieldStatuses & STATUS_FIELD_GRASSY_TERRAIN && GetMoveEffectArg_MoveProperty(gCurrentMove) == MOVE_EFFECT_FLORAL_HEALING) - gBattleStruct->moveDamage[gBattlerTarget] = -(GetNonDynamaxMaxHP(gBattlerTarget) * 2 / 3); + healAmount = GetNonDynamaxMaxHP(gBattlerTarget) * 2 / 3; else - gBattleStruct->moveDamage[gBattlerTarget] = -(GetNonDynamaxMaxHP(gBattlerTarget) / 2); + healAmount = GetNonDynamaxMaxHP(gBattlerTarget) / 2; - if (gBattleStruct->moveDamage[gBattlerTarget] == 0) - gBattleStruct->moveDamage[gBattlerTarget] = -1; - gBattlescriptCurrInstr = cmd->nextInstr; - } -} - -void BS_TryCopycat(void) -{ - NATIVE_ARGS(const u8 *failInstr); - - if (gLastUsedMove == MOVE_NONE || gLastUsedMove == MOVE_UNAVAILABLE || IsMoveCopycatBanned(gLastUsedMove) || IsZMove(gLastUsedMove)) - { - gBattlescriptCurrInstr = cmd->failInstr; - } - else - { - if (GetActiveGimmick(gBattlerAttacker) == GIMMICK_Z_MOVE && !IsBattleMoveStatus(gLastUsedMove)) - { - gBattleStruct->zmove.baseMoves[gBattlerAttacker] = gLastUsedMove; - gCalledMove = GetTypeBasedZMove(gLastUsedMove); - } - else if (IsMaxMove(gLastUsedMove)) - { - gCalledMove = gBattleStruct->dynamax.lastUsedBaseMove; - } - else - { - gCalledMove = gLastUsedMove; - } - - gHitMarker &= ~HITMARKER_ATTACKSTRING_PRINTED; - gBattlerTarget = GetBattleMoveTarget(gCalledMove, NO_TARGET_OVERRIDE); + SetHealAmount(gBattlerTarget, healAmount); gBattlescriptCurrInstr = cmd->nextInstr; } } @@ -15739,23 +15460,6 @@ void BS_TryDefog(void) } } -void BS_TryUpperHand(void) -{ - NATIVE_ARGS(const u8 *failInstr); - - u32 abilityDef = GetBattlerAbility(gBattlerTarget); - u32 prio = GetChosenMovePriority(gBattlerTarget, abilityDef); - - if (HasBattlerActedThisTurn(gBattlerTarget) - || gChosenMoveByBattler[gBattlerTarget] == MOVE_NONE - || IsBattleMoveStatus(gChosenMoveByBattler[gBattlerTarget]) - || prio < 1 - || prio > 3) // Fails if priority is less than 1 or greater than 3, if target already moved, or if using a status - gBattlescriptCurrInstr = cmd->failInstr; - else - gBattlescriptCurrInstr = cmd->nextInstr; -} - void BS_TryTriggerStatusForm(void) { NATIVE_ARGS(); @@ -15787,7 +15491,7 @@ void BS_TryAllySwitch(void) { gBattlescriptCurrInstr = cmd->failInstr; } - else if (GetGenConfig(GEN_ALLY_SWITCH_FAIL_CHANCE) >= GEN_9) + else if (GetConfig(CONFIG_ALLY_SWITCH_FAIL_CHANCE) >= GEN_9) { TryResetProtectUseCounter(gBattlerAttacker); if (sProtectSuccessRates[gDisableStructs[gBattlerAttacker].protectUses] < Random()) @@ -15807,15 +15511,6 @@ void BS_TryAllySwitch(void) } } -void BS_RunStatChangeItems(void) -{ - NATIVE_ARGS(u8 battler); - - // Change instruction before calling ItemBattleEffects. - gBattlescriptCurrInstr = cmd->nextInstr; - ItemBattleEffects(ITEMEFFECT_STATS_CHANGED, GetBattlerForBattleScript(cmd->battler)); -} - static void TryUpdateEvolutionTracker(u32 evolutionCondition, u32 upAmount, u16 usedMove) { u32 i, j; @@ -15871,20 +15566,6 @@ static void TryUpdateEvolutionTracker(u32 evolutionCondition, u32 upAmount, u16 } } -void BS_TryUpdateRecoilTracker(void) -{ - NATIVE_ARGS(); - TryUpdateEvolutionTracker(IF_RECOIL_DAMAGE_GE, gBattleStruct->moveDamage[gBattlerAttacker], MOVE_NONE); - gBattlescriptCurrInstr = cmd->nextInstr; -} - -void BS_TryUpdateLeadersCrestTracker(void) -{ - NATIVE_ARGS(); - TryUpdateEvolutionTracker(IF_DEFEAT_X_WITH_ITEMS, 1, MOVE_NONE); - gBattlescriptCurrInstr = cmd->nextInstr; -} - void BS_TryTidyUp(void) { NATIVE_ARGS(u8 clear, const u8 *jumpInstr); @@ -15933,12 +15614,8 @@ void BS_TryActivateGulpMissile(void) && gBattleMons[gBattlerTarget].species != SPECIES_CRAMORANT && GetBattlerAbility(gBattlerTarget) == ABILITY_GULP_MISSILE) { - if (GetBattlerAbility(gBattlerAttacker) != ABILITY_MAGIC_GUARD) - { - gBattleStruct->moveDamage[gBattlerTarget] = GetNonDynamaxMaxHP(gBattlerAttacker) / 4; - if (gBattleStruct->moveDamage[gBattlerTarget] == 0) - gBattleStruct->moveDamage[gBattlerTarget] = 1; - } + if (!IsAbilityAndRecord(gBattlerAttacker, GetBattlerAbility(gBattlerAttacker), ABILITY_MAGIC_GUARD)) + SetPassiveDamageAmount(gBattlerTarget, GetNonDynamaxMaxHP(gBattlerAttacker) / 4); switch(gBattleMons[gBattlerTarget].species) { @@ -15970,13 +15647,22 @@ void BS_TryQuash(void) // If the above condition is not true, it means we are faster than the foe, so we can set the quash bit gProtectStructs[gBattlerTarget].quash = TRUE; + struct BattleContext ctx = {0}; + for (i = 0; i < gBattlersCount; i++) + { + ctx.abilities[i] = GetBattlerAbility(i); + ctx.holdEffects[i] = GetBattlerHoldEffect(i); + } // this implementation assumes turn order is correct when using Quash i = GetBattlerTurnOrderNum(gBattlerTarget); for (j = i + 1; j < gBattlersCount; j++) { + ctx.battlerAtk = gBattlerByTurnOrder[i]; + ctx.battlerDef = gBattlerByTurnOrder[j]; + // Gen 7- config makes target go last so that the order of quash targets is kept for the correct turn order // Gen 8+ config alters Turn Order of the target according to speed, dynamic speed should handle the rest - if (B_QUASH_TURN_ORDER < GEN_8 || GetWhichBattlerFaster(gBattlerByTurnOrder[i], gBattlerByTurnOrder[j], FALSE) == -1) + if (B_QUASH_TURN_ORDER < GEN_8 || GetWhichBattlerFaster(&ctx, FALSE) == -1) SwapTurnOrder(i, j); else break; @@ -16012,7 +15698,6 @@ void BS_CopyFoesStatIncrease(void) SET_STATCHANGER(stat + 1, gQueuedStatBoosts[battler].statChanges[stat], FALSE); gQueuedStatBoosts[battler].stats &= ~(1 << stat); - gBattlerTarget = battler; gBattlescriptCurrInstr = cmd->nextInstr; return; } @@ -16085,9 +15770,9 @@ void BS_TryTarShot(void) void BS_CanTarShotWork(void) { NATIVE_ARGS(const u8 *failInstr); - // Tar Shot will fail if it's already been used on the target or if its speed can't be lowered further - if (!gDisableStructs[gBattlerTarget].tarShot - && CompareStat(gBattlerTarget, STAT_SPEED, MAX_STAT_STAGE, CMP_LESS_THAN, GetBattlerAbility(gBattlerTarget))) + // Tar Shot fails if the target can't be made weaker to fire and it's speed can't be lowered further + if (!(gDisableStructs[gBattlerTarget].tarShot || GetActiveGimmick(gBattlerTarget) == GIMMICK_TERA) + || CompareStat(gBattlerTarget, STAT_SPEED, MAX_STAT_STAGE, CMP_LESS_THAN, GetBattlerAbility(gBattlerTarget))) gBattlescriptCurrInstr = cmd->nextInstr; else gBattlescriptCurrInstr = cmd->failInstr; @@ -16117,6 +15802,7 @@ void BS_SetMagicCoatTarget(void) gBattlerAttacker = gBattlerTarget; gBattlerTarget = gBattleStruct->attackerBeforeBounce; HandleMoveTargetRedirection(); + ClearDamageCalcResults(); gBattlescriptCurrInstr = cmd->nextInstr; } @@ -16153,7 +15839,7 @@ void BS_TryWindRiderPower(void) NATIVE_ARGS(u8 battler, const u8 *failInstr); u32 battler = GetBattlerForBattleScript(cmd->battler); - u16 ability = GetBattlerAbility(battler); + enum Ability ability = GetBattlerAbility(battler); if (IsBattlerAlly(battler, gBattlerAttacker) && (ability == ABILITY_WIND_RIDER || ability == ABILITY_WIND_POWER)) { @@ -16201,7 +15887,7 @@ void BS_StoreHealingWish(void) NATIVE_ARGS(u8 battler); u32 battler = GetBattlerForBattleScript(cmd->battler); - if (gCurrentMove == MOVE_LUNAR_DANCE) + if (GetMoveEffect(gCurrentMove) == EFFECT_LUNAR_DANCE) gBattleStruct->battlerState[battler].storedLunarDance = TRUE; else gBattleStruct->battlerState[battler].storedHealingWish = TRUE; @@ -16323,13 +16009,6 @@ void BS_WaitFanfare(void) gBattlescriptCurrInstr = cmd->nextInstr; } -void BS_SetBeakBlast(void) -{ - NATIVE_ARGS(); - gProtectStructs[gBattlerAttacker].beakBlastCharge = TRUE; - gBattlescriptCurrInstr = cmd->nextInstr; -} - void BS_RemoveTerrain(void) { NATIVE_ARGS(); @@ -16350,7 +16029,7 @@ void BS_TrySpectralThiefSteal(void) bool32 contrary = GetBattlerAbility(gBattlerAttacker) == ABILITY_CONTRARY; gBattleStruct->stolenStats[0] = 0; // Stats to steal. gBattleScripting.animArg1 = 0; - for (u32 stat = STAT_ATK; stat < NUM_BATTLE_STATS; stat++) + for (enum Stat stat = STAT_ATK; stat < NUM_BATTLE_STATS; stat++) { if (gBattleMons[gBattlerTarget].statStages[stat] > DEFAULT_STAT_STAGE && gBattleMons[gBattlerAttacker].statStages[stat] != MAX_STAT_STAGE) { @@ -16395,7 +16074,7 @@ void BS_SpectralThiefPrintStats(void) { NATIVE_ARGS(); - for (u32 stat = STAT_ATK; stat < NUM_BATTLE_STATS; stat++) + for (enum Stat stat = STAT_ATK; stat < NUM_BATTLE_STATS; stat++) { if (gBattleStruct->stolenStats[0] & (1u << stat)) { @@ -16430,6 +16109,13 @@ void BS_ClearMoveResultFlags(void) gBattlescriptCurrInstr = cmd->nextInstr; } +void BS_ClearSpecialStatuses(void) +{ + NATIVE_ARGS(); + memset(&gSpecialStatuses, 0, sizeof(gSpecialStatuses)); + gBattlescriptCurrInstr = cmd->nextInstr; +} + void BS_JumpIfMoveResultFlags(void) { NATIVE_ARGS(u16 value, const u8 *jumpInstr); @@ -16440,11 +16126,11 @@ void BS_JumpIfMoveResultFlags(void) gBattlescriptCurrInstr = cmd->nextInstr; } -void BS_JumpIfCriticalHit(void) +void BS_JumpIfNotCriticalHit(void) { NATIVE_ARGS(const u8 *jumpInstr); - if (gSpecialStatuses[gBattlerTarget].criticalHit) + if (!gSpecialStatuses[gBattlerTarget].criticalHit) gBattlescriptCurrInstr = cmd->jumpInstr; else gBattlescriptCurrInstr = cmd->nextInstr; @@ -16454,7 +16140,7 @@ void BS_SwapStats(void) { NATIVE_ARGS(u8 stat); - u32 stat = cmd->stat; + enum Stat stat = cmd->stat; u32 temp; switch (stat) @@ -16477,6 +16163,8 @@ void BS_SwapStats(void) case STAT_SPDEF: SWAP(gBattleMons[gBattlerAttacker].spDefense, gBattleMons[gBattlerTarget].spDefense, temp); break; + default: + break; } PREPARE_STAT_BUFFER(gBattleTextBuff1, stat); gBattlescriptCurrInstr = cmd->nextInstr; @@ -16485,40 +16173,25 @@ void BS_SwapStats(void) static void TrySetParalysis(const u8 *nextInstr, const u8 *failInstr) { if (CanBeParalyzed(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerTarget))) - { - gBattlescriptCurrInstr = nextInstr - 1; - SetNonVolatileStatus(gBattlerTarget, MOVE_EFFECT_PARALYSIS, TRIGGER_ON_MOVE); - } + SetNonVolatileStatus(gBattlerTarget, MOVE_EFFECT_PARALYSIS, nextInstr, TRIGGER_ON_MOVE); else - { gBattlescriptCurrInstr = failInstr; - } } static void TrySetPoison(const u8 *nextInstr, const u8 *failInstr) { if (CanBePoisoned(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerAttacker), GetBattlerAbility(gBattlerTarget))) - { - gBattlescriptCurrInstr = nextInstr - 1; - SetNonVolatileStatus(gBattlerTarget, MOVE_EFFECT_POISON, TRIGGER_ON_MOVE); - } + SetNonVolatileStatus(gBattlerTarget, MOVE_EFFECT_POISON, nextInstr, TRIGGER_ON_MOVE); else - { gBattlescriptCurrInstr = failInstr; - } } static void TrySetSleep(const u8 *nextInstr, const u8 *failInstr) { if (CanBeSlept(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerTarget), BLOCKED_BY_SLEEP_CLAUSE)) - { - gBattlescriptCurrInstr = nextInstr - 1; - SetNonVolatileStatus(gBattlerTarget, MOVE_EFFECT_SLEEP, TRIGGER_ON_MOVE); - } + SetNonVolatileStatus(gBattlerTarget, MOVE_EFFECT_SLEEP, nextInstr, TRIGGER_ON_MOVE); else - { gBattlescriptCurrInstr = failInstr; - } } void BS_TrySetParalysis(void) @@ -16623,7 +16296,7 @@ void BS_TrySetTorment(void) && !IsAbilityOnSide(gBattlerTarget, ABILITY_AROMA_VEIL)) { gBattleMons[gBattlerTarget].volatiles.torment = TRUE; - gDisableStructs[gBattlerTarget].tormentTimer = gBattleTurnCounter + 3; // 3 turns excluding current turn + gDisableStructs[gBattlerTarget].tormentTimer = 3; gEffectBattler = gBattlerTarget; gBattlescriptCurrInstr = cmd->nextInstr; } @@ -16637,11 +16310,7 @@ void BS_TrySetTorment(void) void BS_HealOneSixth(void) { NATIVE_ARGS(const u8* failInstr); - gBattleStruct->moveDamage[gBattlerTarget] = gBattleMons[gBattlerTarget].maxHP / 6; - if (gBattleStruct->moveDamage[gBattlerTarget] == 0) - gBattleStruct->moveDamage[gBattlerTarget] = 1; - gBattleStruct->moveDamage[gBattlerTarget] *= -1; - + SetHealAmount(gBattlerTarget, gBattleMons[gBattlerTarget].maxHP / 6); if (gBattleMons[gBattlerTarget].hp == gBattleMons[gBattlerTarget].maxHP) gBattlescriptCurrInstr = cmd->failInstr; // fail else @@ -16652,7 +16321,7 @@ void BS_HealOneSixth(void) void BS_TryRecycleBerry(void) { NATIVE_ARGS(const u8 *failInstr); - u16* usedHeldItem = &gBattleStruct->usedHeldItems[gBattlerPartyIndexes[gBattlerTarget]][GetBattlerSide(gBattlerTarget)]; + u16 *usedHeldItem = &GetBattlerPartyState(gBattlerTarget)->usedHeldItem; if (gBattleMons[gBattlerTarget].item == ITEM_NONE && gBattleStruct->changedItems[gBattlerTarget] == ITEM_NONE // Will not inherit an item && GetItemPocket(*usedHeldItem) == POCKET_BERRIES) @@ -16692,8 +16361,8 @@ void BS_JumpIfIntimidateAbilityPrevented(void) { NATIVE_ARGS(); - u32 hasAbility = FALSE; - u32 ability = GetBattlerAbility(gBattlerTarget); + bool32 hasAbility = FALSE; + enum Ability ability = GetBattlerAbility(gBattlerTarget); switch (ability) { @@ -16701,7 +16370,7 @@ void BS_JumpIfIntimidateAbilityPrevented(void) case ABILITY_SCRAPPY: case ABILITY_OWN_TEMPO: case ABILITY_OBLIVIOUS: - if (GetGenConfig(GEN_CONFIG_UPDATED_INTIMIDATE) >= GEN_8) + if (GetConfig(CONFIG_UPDATED_INTIMIDATE) >= GEN_8) { hasAbility = TRUE; gBattlescriptCurrInstr = BattleScript_IntimidatePrevented; @@ -16740,14 +16409,54 @@ void BS_JumpIfCanGigantamax(void) gBattlescriptCurrInstr = cmd->nextInstr; } -void BS_JumpIfLastUsedItemHoldEffect(void) +void BS_TryFlingHoldEffect(void) { - NATIVE_ARGS(u8 holdEffect, u16 secondaryId, const u8 *jumpInstr); - if (GetItemHoldEffect(gLastUsedItem) == cmd->holdEffect - && (cmd->secondaryId == 0 || GetItemSecondaryId(gLastUsedItem) == cmd->secondaryId)) - gBattlescriptCurrInstr = cmd->jumpInstr; - else + NATIVE_ARGS(); + enum HoldEffect holdEffect = GetItemHoldEffect(gBattleStruct->flingItem); + gBattleStruct->flingItem = ITEM_NONE; + + if (IsMoveEffectBlockedByTarget(GetBattlerAbility(gBattlerTarget))) + { + gBattlescriptCurrInstr = BattleScript_FlingBlockedByShieldDust; + return; + } + + switch (holdEffect) + { + case HOLD_EFFECT_FLAME_ORB: + SetMoveEffect(gBattlerAttacker, gBattlerTarget, MOVE_EFFECT_BURN, cmd->nextInstr, NO_FLAGS); + break; + case HOLD_EFFECT_TOXIC_ORB: + SetMoveEffect(gBattlerAttacker, gBattlerTarget, MOVE_EFFECT_TOXIC, cmd->nextInstr, NO_FLAGS); + break; + case HOLD_EFFECT_LIGHT_BALL: + SetMoveEffect(gBattlerAttacker, gBattlerTarget, MOVE_EFFECT_PARALYSIS, cmd->nextInstr, NO_FLAGS); + break; + case HOLD_EFFECT_TYPE_POWER: + if (GetItemSecondaryId(gLastUsedItem) != TYPE_POISON) + gBattlescriptCurrInstr = cmd->nextInstr; + else + SetMoveEffect(gBattlerAttacker, gBattlerTarget, MOVE_EFFECT_POISON, cmd->nextInstr, NO_FLAGS); + break; + case HOLD_EFFECT_FLINCH: + SetMoveEffect(gBattlerAttacker, gBattlerTarget, MOVE_EFFECT_FLINCH, cmd->nextInstr, NO_FLAGS); + break; + case HOLD_EFFECT_MENTAL_HERB: + if (ItemBattleEffects(gBattlerTarget, 0, holdEffect, IsOnFlingActivation)) + return; + else + gBattlescriptCurrInstr = cmd->nextInstr; + break; + case HOLD_EFFECT_WHITE_HERB: + if (ItemBattleEffects(gBattlerTarget, 0, holdEffect, IsOnFlingActivation)) + return; + else + gBattlescriptCurrInstr = cmd->nextInstr; + break; + default: gBattlescriptCurrInstr = cmd->nextInstr; + break; + } } void BS_JumpIfNoWhiteOut(void) @@ -16766,38 +16475,51 @@ void BS_TryBoosterEnergy(void) for (u32 orderNum = 0; orderNum < gBattlersCount; orderNum++) { - u32 battlerByTurnOrder = gBattlerByTurnOrder[orderNum]; - if (GetBattlerHoldEffect(battlerByTurnOrder, TRUE) != HOLD_EFFECT_BOOSTER_ENERGY) + u32 battler = gBattlerByTurnOrder[orderNum]; + enum HoldEffect holdEffect = GetBattlerHoldEffect(battler); + if (holdEffect != HOLD_EFFECT_BOOSTER_ENERGY) continue; - u32 ability = GetBattlerAbility(battlerByTurnOrder); + enum Ability ability = GetBattlerAbility(battler); if (!(ability == ABILITY_PROTOSYNTHESIS && cmd->onFieldStatus != ON_TERRAIN) && !(ability == ABILITY_QUARK_DRIVE && cmd->onFieldStatus != ON_WEATHER)) continue; - if (TryBoosterEnergy(battlerByTurnOrder, ability, ITEMEFFECT_NONE)) + if (ItemBattleEffects(battler, 0, holdEffect, IsOnEffectActivation)) return; } gBattlescriptCurrInstr = cmd->nextInstr; } -void BS_JumpIfAbilityCantBeSuppressed(void) +void BS_JumpIfAbilityCantBeReactivated(void) { NATIVE_ARGS(u8 battler, const u8 *jumpInstr); u32 battler = GetBattlerForBattleScript(cmd->battler); + u32 ability = gBattleMons[battler].ability; - if (gAbilitiesInfo[gBattleMons[battler].ability].cantBeSuppressed) + switch (ability) + { + case ABILITY_IMPOSTER: + case ABILITY_NEUTRALIZING_GAS: + case ABILITY_AIR_LOCK: + case ABILITY_CLOUD_NINE: gBattlescriptCurrInstr = cmd->jumpInstr; - else - gBattlescriptCurrInstr = cmd->nextInstr; + break; + default: + if (gAbilitiesInfo[ability].cantBeSuppressed) + gBattlescriptCurrInstr = cmd->jumpInstr; + else + gBattlescriptCurrInstr = cmd->nextInstr; + break; + } } void BS_TryActivateAbilityShield(void) { NATIVE_ARGS(u8 battler); u32 battler = GetBattlerForBattleScript(cmd->battler); - u32 ability = GetBattlerAbility(battler); + enum Ability ability = GetBattlerAbility(battler); gBattlescriptCurrInstr = cmd->nextInstr; @@ -16878,7 +16600,7 @@ void BS_JumpIfHoldEffect(void) { NATIVE_ARGS(u8 battler, u8 holdEffect, const u8 *jumpInstr, u8 equal); u32 battler = GetBattlerForBattleScript(cmd->battler); - if ((GetBattlerHoldEffect(battler, TRUE) == cmd->holdEffect) == cmd->equal) + if ((GetBattlerHoldEffect(battler) == cmd->holdEffect) == cmd->equal) { if (cmd->equal) gLastUsedItem = gBattleMons[battler].item; // For B_LAST_USED_ITEM @@ -16906,6 +16628,7 @@ void BS_SetLastUsedItem(void) { NATIVE_ARGS(u8 battler); gLastUsedItem = gBattleMons[GetBattlerForBattleScript(cmd->battler)].item; + gBattleStruct->flingItem = gLastUsedItem; gBattlescriptCurrInstr = cmd->nextInstr; } @@ -16919,7 +16642,7 @@ void BS_TrySetFairyLock(void) else { gFieldStatuses |= STATUS_FIELD_FAIRY_LOCK; - gFieldTimers.fairyLockTimer = gBattleTurnCounter + 2; + gFieldTimers.fairyLockTimer = 2; gBattlescriptCurrInstr = cmd->nextInstr; } } @@ -16928,9 +16651,9 @@ void BS_GetStatValue(void) { NATIVE_ARGS(u8 stat); u32 stat = cmd->stat; - gBattleStruct->moveDamage[gBattlerAttacker] = *(u16 *)(&gBattleMons[gBattlerTarget].attack) + (stat - 1); - gBattleStruct->moveDamage[gBattlerAttacker] *= gStatStageRatios[gBattleMons[gBattlerTarget].statStages[stat]][0]; - gBattleStruct->moveDamage[gBattlerAttacker] /= gStatStageRatios[gBattleMons[gBattlerTarget].statStages[stat]][1]; + gBattleStruct->passiveHpUpdate[gBattlerAttacker] = *(u16 *)(&gBattleMons[gBattlerTarget].attack) + (stat - 1); + gBattleStruct->passiveHpUpdate[gBattlerAttacker] *= gStatStageRatios[gBattleMons[gBattlerTarget].statStages[stat]][0]; + gBattleStruct->passiveHpUpdate[gBattlerAttacker] /= gStatStageRatios[gBattleMons[gBattlerTarget].statStages[stat]][1]; gBattlescriptCurrInstr = cmd->nextInstr; } @@ -16954,7 +16677,7 @@ void BS_TryFriskMessage(void) && gBattleMons[gBattlerTarget].item != ITEM_NONE) { gLastUsedItem = gBattleMons[gBattlerTarget].item; - RecordItemEffectBattle(gBattlerTarget, GetBattlerHoldEffect(gBattlerTarget, FALSE)); + RecordItemEffectBattle(gBattlerTarget, GetBattlerHoldEffectIgnoreNegation(gBattlerTarget)); // If Frisk identifies two mons' items, show the pop-up only once. if (gBattleStruct->friskedAbility) { @@ -17030,7 +16753,7 @@ void BS_TryAcupressure(void) { NATIVE_ARGS(const u8 *failInstr); u32 bits = 0; - for (u32 stat = STAT_ATK; stat < NUM_BATTLE_STATS; stat++) + for (enum Stat stat = STAT_ATK; stat < NUM_BATTLE_STATS; stat++) { if (CompareStat(gBattlerTarget, stat, MAX_STAT_STAGE, CMP_LESS_THAN, GetBattlerAbility(gBattlerTarget))) bits |= 1u << stat; @@ -17411,7 +17134,7 @@ void BS_TryActivateReceiver(void) u32 partnerAbility = GetBattlerAbility(gBattlerAbility); if (IsBattlerAlive(gBattlerAbility) && (partnerAbility == ABILITY_RECEIVER || partnerAbility == ABILITY_POWER_OF_ALCHEMY) - && GetBattlerHoldEffect(battler, TRUE) != HOLD_EFFECT_ABILITY_SHIELD + && GetBattlerHoldEffectIgnoreAbility(battler) != HOLD_EFFECT_ABILITY_SHIELD && !gAbilitiesInfo[gBattleMons[battler].ability].cantBeCopied) { gBattleStruct->tracedAbility[gBattlerAbility] = gBattleMons[battler].ability; // re-using the variable for trace @@ -17471,7 +17194,7 @@ void BS_SetLuckyChant(void) if (!(gSideStatuses[side] & SIDE_STATUS_LUCKY_CHANT)) { gSideStatuses[side] |= SIDE_STATUS_LUCKY_CHANT; - gSideTimers[side].luckyChantTimer = gBattleTurnCounter + 5; + gSideTimers[side].luckyChantTimer = 5; gBattlescriptCurrInstr = cmd->nextInstr; } else @@ -17480,44 +17203,6 @@ void BS_SetLuckyChant(void) } } -void BS_SuckerPunchCheck(void) -{ - NATIVE_ARGS(const u8 *failInstr); - if (gProtectStructs[gBattlerTarget].protected == PROTECT_OBSTRUCT) - gBattlescriptCurrInstr = cmd->failInstr; - else if (HasBattlerActedThisTurn(gBattlerTarget)) - gBattlescriptCurrInstr = cmd->failInstr; - else if (IsBattleMoveStatus(gBattleMons[gBattlerTarget].moves[gBattleStruct->chosenMovePositions[gBattlerTarget]]) && !gProtectStructs[gBattlerTarget].noValidMoves) - gBattlescriptCurrInstr = cmd->failInstr; - else - gBattlescriptCurrInstr = cmd->nextInstr; -} - -void BS_SetSimpleBeam(void) -{ - NATIVE_ARGS(const u8 *failInstr); - if (gAbilitiesInfo[gBattleMons[gBattlerTarget].ability].cantBeOverwritten - || gBattleMons[gBattlerTarget].ability == ABILITY_SIMPLE) - { - RecordAbilityBattle(gBattlerTarget, gBattleMons[gBattlerTarget].ability); - gBattlescriptCurrInstr = cmd->failInstr; - } - else if (CanAbilityShieldActivateForBattler(gBattlerTarget)) - { - gBattlescriptCurrInstr = BattleScript_MoveEnd; - BattleScriptCall(BattleScript_AbilityShieldProtects); - } - else - { - if (gBattleMons[gBattlerTarget].ability == ABILITY_NEUTRALIZING_GAS) - gSpecialStatuses[gBattlerTarget].neutralizingGasRemoved = TRUE; - - gBattleScripting.abilityPopupOverwrite = gBattleMons[gBattlerTarget].ability; - gBattleMons[gBattlerTarget].ability = gDisableStructs[gBattlerTarget].overwrittenAbility = ABILITY_SIMPLE; - gBattlescriptCurrInstr = cmd->nextInstr; - } -} - void BS_TryEntrainment(void) { NATIVE_ARGS(const u8 *failInstr); @@ -17541,6 +17226,7 @@ void BS_TryEntrainment(void) } else { + RemoveAbilityFlags(gBattlerTarget); gBattleMons[gBattlerTarget].ability = gDisableStructs[gBattlerTarget].overwrittenAbility = gBattleMons[gBattlerAttacker].ability; gBattlescriptCurrInstr = cmd->nextInstr; } @@ -17567,32 +17253,6 @@ void BS_InvertStatStages(void) gBattlescriptCurrInstr = cmd->nextInstr; } -void BS_TryMeFirst(void) -{ - NATIVE_ARGS(const u8 *failInstr); - u16 move = gBattleMons[gBattlerTarget].moves[gBattleStruct->chosenMovePositions[gBattlerTarget]]; - if (IsBattleMoveStatus(move) || IsMoveMeFirstBanned(move) - || HasBattlerActedThisTurn(gBattlerTarget)) - { - gBattlescriptCurrInstr = cmd->failInstr; - } - else - { - if (GetActiveGimmick(gBattlerAttacker) == GIMMICK_Z_MOVE && !IsBattleMoveStatus(move)) - { - gBattleStruct->zmove.baseMoves[gBattlerAttacker] = move; - gCalledMove = GetTypeBasedZMove(move); - } - else - { - gCalledMove = move; - } - gHitMarker &= ~HITMARKER_ATTACKSTRING_PRINTED; - gBattlerTarget = GetBattleMoveTarget(gCalledMove, NO_TARGET_OVERRIDE); - gBattlescriptCurrInstr = cmd->nextInstr; - } -} - void BS_TryElectrify(void) { NATIVE_ARGS(const u8 *failInstr); @@ -17610,9 +17270,9 @@ void BS_TryElectrify(void) void BS_TrySoak(void) { NATIVE_ARGS(const u8 *failInstr); - u32 types[3]; + enum Type types[3]; GetBattlerTypes(gBattlerTarget, FALSE, types); - u32 typeToSet = GetMoveArgType(gCurrentMove); + enum Type typeToSet = GetMoveArgType(gCurrentMove); if ((types[0] == typeToSet && types[1] == typeToSet) || GetActiveGimmick(gBattlerTarget) == GIMMICK_TERA) { @@ -17648,15 +17308,6 @@ void BS_HandleFormChange(void) gBattlescriptCurrInstr = cmd->nextInstr; } -void BS_TryLastResort(void) -{ - NATIVE_ARGS(const u8 *failInstr); - if (CanUseLastResort(gBattlerAttacker)) - gBattlescriptCurrInstr = cmd->nextInstr; - else - gBattlescriptCurrInstr = cmd->failInstr; -} - void BS_TryAutotomize(void) { NATIVE_ARGS(const u8 *failInstr); @@ -17694,19 +17345,18 @@ void BS_TryInstruct(void) if (gBattleMons[gBattlerTarget].moves[moveIndex] == gCalledMove) { gCurrMovePos = moveIndex; - moveIndex = 4; + moveIndex = MAX_MON_MOVES; break; } } - if (moveIndex != 4 || gBattleMons[gBattlerTarget].pp[gCurrMovePos] == 0) + if (moveIndex != MAX_MON_MOVES || gBattleMons[gBattlerTarget].pp[gCurrMovePos] == 0) { gBattlescriptCurrInstr = cmd->failInstr; } else { + gBattleScripting.battler = gBattlerAttacker; // for message gEffectBattler = gBattleStruct->lastMoveTarget[gBattlerTarget]; - gHitMarker &= ~HITMARKER_ATTACKSTRING_PRINTED; - PREPARE_MON_NICK_WITH_PREFIX_BUFFER(gBattleTextBuff1, gBattlerTarget, gBattlerPartyIndexes[gBattlerTarget]); gBattlescriptCurrInstr = cmd->nextInstr; } } @@ -17831,6 +17481,7 @@ void BS_TryBestow(void) || gBattleMons[gBattlerTarget].item != ITEM_NONE || !CanBattlerGetOrLoseItem(gBattlerAttacker, gBattleMons[gBattlerAttacker].item) || !CanBattlerGetOrLoseItem(gBattlerTarget, gBattleMons[gBattlerAttacker].item) + || GetBattlerAbility(gBattlerAttacker) == ABILITY_STICKY_HOLD || gWishFutureKnock.knockedOffMons[GetBattlerSide(gBattlerTarget)] & (1u << gBattlerPartyIndexes[gBattlerTarget])) { gBattlescriptCurrInstr = cmd->failInstr; @@ -17907,8 +17558,7 @@ void BS_SetAuroraVeil(void) { NATIVE_ARGS(); u32 side = GetBattlerSide(gBattlerAttacker); - if (gSideStatuses[side] & SIDE_STATUS_AURORA_VEIL - || !(HasWeatherEffect() && gBattleWeather & (B_WEATHER_HAIL | B_WEATHER_SNOW))) + if (gSideStatuses[side] & SIDE_STATUS_AURORA_VEIL) { gBattleStruct->moveResultFlags[gBattlerTarget] |= MOVE_RESULT_MISSED; gBattleCommunication[MULTISTRING_CHOOSER] = 0; @@ -17916,10 +17566,10 @@ void BS_SetAuroraVeil(void) else { gSideStatuses[side] |= SIDE_STATUS_AURORA_VEIL; - if (GetBattlerHoldEffect(gBattlerAttacker, TRUE) == HOLD_EFFECT_LIGHT_CLAY) - gSideTimers[GetBattlerSide(gBattlerAttacker)].auroraVeilTimer = gBattleTurnCounter + 8; + if (GetBattlerHoldEffect(gBattlerAttacker) == HOLD_EFFECT_LIGHT_CLAY) + gSideTimers[GetBattlerSide(gBattlerAttacker)].auroraVeilTimer = 8; else - gSideTimers[GetBattlerSide(gBattlerAttacker)].auroraVeilTimer = gBattleTurnCounter + 5; + gSideTimers[GetBattlerSide(gBattlerAttacker)].auroraVeilTimer = 5; if (IsDoubleBattle() && CountAliveMonsInBattle(BATTLE_ALIVE_SIDE, gBattlerAttacker) == 2) gBattleCommunication[MULTISTRING_CHOOSER] = 5; @@ -17994,8 +17644,14 @@ void BS_GetTotemBoost(void) void BS_ActivateItemEffects(void) { NATIVE_ARGS(); - if (ItemBattleEffects(ITEMEFFECT_TRY_HEALING, gBattlerTarget)) - return; + for (u32 battler = 0; battler < gBattlersCount; battler++) + { + if (!IsBattlerAlive(battler)) + continue; + + if (ItemBattleEffects(battler, 0, GetBattlerHoldEffect(battler), IsForceTriggerItemActivation)) + return; + } gBattlescriptCurrInstr = cmd->nextInstr; } @@ -18003,43 +17659,19 @@ void BS_TryRoomService(void) { NATIVE_ARGS(u8 battler, const u8 *failInstr); u32 battler = GetBattlerForBattleScript(cmd->battler); - if (GetBattlerHoldEffect(battler, TRUE) == HOLD_EFFECT_ROOM_SERVICE && TryRoomService(battler)) - { - BattleScriptCall(BattleScript_ConsumableStatRaiseRet); - } - else - { - gBattlescriptCurrInstr = cmd->failInstr; - } + enum HoldEffect holdEffect = GetBattlerHoldEffect(battler); + if (holdEffect == HOLD_EFFECT_ROOM_SERVICE && ItemBattleEffects(battler, 0, holdEffect, IsOnEffectActivation)) + return; + gBattlescriptCurrInstr = cmd->failInstr; } void BS_TryTerrainSeed(void) { NATIVE_ARGS(u8 battler, const u8 *failInstr); u32 battler = GetBattlerForBattleScript(cmd->battler); - if (GetBattlerHoldEffect(battler, TRUE) == HOLD_EFFECT_SEEDS) - { - enum ItemEffect effect = ITEM_NO_EFFECT; - u16 item = gBattleMons[battler].item; - switch (GetBattlerHoldEffectParam(battler)) - { - case HOLD_EFFECT_PARAM_ELECTRIC_TERRAIN: - effect = TryHandleSeed(battler, STATUS_FIELD_ELECTRIC_TERRAIN, STAT_DEF, item, ITEMEFFECT_NONE); - break; - case HOLD_EFFECT_PARAM_GRASSY_TERRAIN: - effect = TryHandleSeed(battler, STATUS_FIELD_GRASSY_TERRAIN, STAT_DEF, item, ITEMEFFECT_NONE); - break; - case HOLD_EFFECT_PARAM_MISTY_TERRAIN: - effect = TryHandleSeed(battler, STATUS_FIELD_MISTY_TERRAIN, STAT_SPDEF, item, ITEMEFFECT_NONE); - break; - case HOLD_EFFECT_PARAM_PSYCHIC_TERRAIN: - effect = TryHandleSeed(battler, STATUS_FIELD_PSYCHIC_TERRAIN, STAT_SPDEF, item, ITEMEFFECT_NONE); - break; - } - - if (effect != ITEM_NO_EFFECT) - return; - } + enum HoldEffect holdEffect = GetBattlerHoldEffect(battler); + if (holdEffect == HOLD_EFFECT_TERRAIN_SEED && ItemBattleEffects(battler, 0, holdEffect, IsOnEffectActivation)) + return; gBattlescriptCurrInstr = cmd->failInstr; } @@ -18082,11 +17714,7 @@ void BS_TryHealQuarterHealth(void) { NATIVE_ARGS(u8 battler, const u8 *failInstr); u32 battler = GetBattlerForBattleScript(cmd->battler); - gBattleStruct->moveDamage[battler] = GetNonDynamaxMaxHP(battler) / 4; - if (gBattleStruct->moveDamage[battler] == 0) - gBattleStruct->moveDamage[battler] = 1; - gBattleStruct->moveDamage[battler] *= -1; - + SetHealAmount(battler, GetNonDynamaxMaxHP(battler) / 4); if (gBattleMons[battler].hp == gBattleMons[battler].maxHP) gBattlescriptCurrInstr = cmd->failInstr; // fail else @@ -18196,7 +17824,7 @@ void BS_TryToClearPrimalWeather(void) for (u32 i = 0; i < gBattlersCount; i++) { - u32 ability = GetBattlerAbility(i); + enum Ability ability = GetBattlerAbility(i); if (((ability == ABILITY_DESOLATE_LAND && gBattleWeather & B_WEATHER_SUN_PRIMAL) || (ability == ABILITY_PRIMORDIAL_SEA && gBattleWeather & B_WEATHER_RAIN_PRIMAL) || (ability == ABILITY_DELTA_STREAM && gBattleWeather & B_WEATHER_STRONG_WINDS)) @@ -18230,13 +17858,16 @@ void BS_TryEndNeutralizingGas(void) if (gSpecialStatuses[gBattlerTarget].neutralizingGasRemoved) { gSpecialStatuses[gBattlerTarget].neutralizingGasRemoved = FALSE; - BattleScriptPush(cmd->nextInstr); - gBattlescriptCurrInstr = BattleScript_NeutralizingGasExits; - } - else - { - gBattlescriptCurrInstr = cmd->nextInstr; + gDisableStructs[gBattlerTarget].neutralizingGas = FALSE; + if (!IsNeutralizingGasOnField()) + { + BattleScriptPush(cmd->nextInstr); + gBattlescriptCurrInstr = BattleScript_NeutralizingGasExits; + return; + } } + + gBattlescriptCurrInstr = cmd->nextInstr; } void BS_GetRototillerTargets(void) @@ -18273,23 +17904,29 @@ void BS_JumpIfNotRototillerAffected(void) } } +// TODO: There might be a way to do it without a flag void BS_ConsumeBerry(void) { NATIVE_ARGS(u8 battler, bool8 fromBattler); u32 battler = GetBattlerForBattleScript(cmd->battler); - if (gBattleScripting.overrideBerryRequirements == 2) - { - gBattlescriptCurrInstr = cmd->nextInstr; - return; - } if (cmd->fromBattler) gLastUsedItem = gBattleMons[battler].item; - GetBattlerPartyState(battler)->ateBerry = TRUE; - gBattleScripting.battler = gEffectBattler = gBattlerTarget = battler; // Cover all berry effect battler cases. e.g. ChangeStatBuffs uses target ID - if (ItemBattleEffects(ITEMEFFECT_USE_LAST_ITEM, battler)) + if (GetItemPocket(gLastUsedItem) != POCKET_BERRIES || gBattleScripting.overrideBerryRequirements == 2) + { + gBattleScripting.overrideBerryRequirements = 0; + gBattlescriptCurrInstr = cmd->nextInstr; return; + } + + gBattleScripting.overrideBerryRequirements = 1; + GetBattlerPartyState(battler)->ateBerry = TRUE; + if (ItemBattleEffects(battler, 0, GetItemHoldEffect(gLastUsedItem), IsOnBerryActivation)) + { + gBattleScripting.overrideBerryRequirements = 2; + return; + } gBattlescriptCurrInstr = cmd->nextInstr; } @@ -18317,7 +17954,7 @@ void BS_JumpIfAbilityPreventsRest(void) NATIVE_ARGS(u8 battler, const u8 *jumpInstr); u32 battler = GetBattlerForBattleScript(cmd->battler); u32 ability = GetBattlerAbility(battler); - if (GetGenConfig(GEN_CONFIG_LEAF_GUARD_PREVENTS_REST) >= GEN_5 && IsLeafGuardProtected(battler, ability)) + if (GetConfig(CONFIG_LEAF_GUARD_PREVENTS_REST) >= GEN_5 && IsLeafGuardProtected(battler, ability)) gBattlescriptCurrInstr = cmd->jumpInstr; else if (IsShieldsDownProtected(battler, ability)) gBattlescriptCurrInstr = cmd->jumpInstr; @@ -18340,9 +17977,7 @@ void BS_SetAttackerToStickyWebUser(void) void BS_CutOneThirdHpAndRaiseStats(void) { NATIVE_ARGS(const u8 *failInstr); - - bool8 atLeastOneStatBoosted = FALSE; - u16 hpFraction = max(1, GetNonDynamaxMaxHP(gBattlerAttacker) / 3); + bool32 atLeastOneStatBoosted = FALSE; u32 ability = GetBattlerAbility(gBattlerAttacker); for (u32 stat = 1; stat < NUM_STATS; stat++) @@ -18353,9 +17988,9 @@ void BS_CutOneThirdHpAndRaiseStats(void) break; } } - if (atLeastOneStatBoosted && gBattleMons[gBattlerAttacker].hp > hpFraction) + if (atLeastOneStatBoosted) { - gBattleStruct->moveDamage[gBattlerAttacker] = hpFraction; + SetPassiveDamageAmount(gBattlerAttacker, GetNonDynamaxMaxHP(gBattlerAttacker) / 3); gBattlescriptCurrInstr = cmd->nextInstr; } else @@ -18364,81 +17999,11 @@ void BS_CutOneThirdHpAndRaiseStats(void) } } -void BS_CheckPoltergeist(void) +void BS_SetPoltergeistMessage(void) { NATIVE_ARGS(const u8 *failInstr); - if (gBattleMons[gBattlerTarget].item == ITEM_NONE - || gFieldStatuses & STATUS_FIELD_MAGIC_ROOM - || GetBattlerAbility(gBattlerTarget) == ABILITY_KLUTZ) - { - gBattlescriptCurrInstr = cmd->failInstr; - } - else - { - PREPARE_ITEM_BUFFER(gBattleTextBuff1, gBattleMons[gBattlerTarget].item); - gLastUsedItem = gBattleMons[gBattlerTarget].item; - gBattlescriptCurrInstr = cmd->nextInstr; - } -} - -void BS_TryNoRetreat(void) -{ - NATIVE_ARGS(const u8 *failInstr); - if (gDisableStructs[gBattlerTarget].noRetreat) - { - gBattlescriptCurrInstr = cmd->failInstr; - } - else - { - if (!gBattleMons[gBattlerTarget].volatiles.escapePrevention) - gDisableStructs[gBattlerTarget].noRetreat = TRUE; - gBattlescriptCurrInstr = cmd->nextInstr; - } -} - -void BS_CureCertainStatuses(void) -{ - NATIVE_ARGS(); - // Check infatuation - if (gBattleMons[gBattlerTarget].volatiles.infatuation) - { - gBattleMons[gBattlerTarget].volatiles.infatuation = 0; - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_MENTALHERBCURE_INFATUATION; // STRINGID_TARGETGOTOVERINFATUATION - StringCopy(gBattleTextBuff1, gStatusConditionString_LoveJpn); - } - // Check taunt - if (gDisableStructs[gBattlerTarget].tauntTimer != 0) - { - gDisableStructs[gBattlerTarget].tauntTimer = 0; - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_MENTALHERBCURE_TAUNT; - PREPARE_MOVE_BUFFER(gBattleTextBuff1, MOVE_TAUNT); - } - // Check encore - if (gDisableStructs[gBattlerTarget].encoreTimer != 0) - { - gDisableStructs[gBattlerTarget].encoredMove = 0; - gDisableStructs[gBattlerTarget].encoreTimer = 0; - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_MENTALHERBCURE_ENCORE; // STRINGID_PKMNENCOREENDED - } - // Check torment - if (gBattleMons[gBattlerTarget].volatiles.torment == TRUE) - { - gBattleMons[gBattlerTarget].volatiles.torment = FALSE; - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_MENTALHERBCURE_TORMENT; - } - // Check heal block - if (gBattleMons[gBattlerTarget].volatiles.healBlock) - { - gBattleMons[gBattlerTarget].volatiles.healBlock = FALSE; - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_MENTALHERBCURE_HEALBLOCK; - } - // Check disable - if (gDisableStructs[gBattlerTarget].disableTimer != 0) - { - gDisableStructs[gBattlerTarget].disableTimer = 0; - gDisableStructs[gBattlerTarget].disabledMove = 0; - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_MENTALHERBCURE_DISABLE; - } + PREPARE_ITEM_BUFFER(gBattleTextBuff1, gBattleMons[gBattlerTarget].item); + gLastUsedItem = gBattleMons[gBattlerTarget].item; gBattlescriptCurrInstr = cmd->nextInstr; } @@ -18484,7 +18049,7 @@ void BS_BattlerItemToLastUsedItem(void) void BS_JumpIfGenConfigLowerThan(void) { NATIVE_ARGS(u16 tag, u8 gen, const u8 *jumpInstr); - if (GetGenConfig(cmd->tag) < cmd->gen) + if (GetConfig(cmd->tag) < cmd->gen) gBattlescriptCurrInstr = cmd->jumpInstr; else gBattlescriptCurrInstr = cmd->nextInstr; diff --git a/src/battle_setup.c b/src/battle_setup.c index 1505f6af65..1ad284d05e 100644 --- a/src/battle_setup.c +++ b/src/battle_setup.c @@ -42,6 +42,7 @@ #include "data.h" #include "vs_seeker.h" #include "item.h" +#include "field_name_box.h" #include "constants/battle_frontier.h" #include "constants/battle_setup.h" #include "constants/event_objects.h" @@ -51,9 +52,10 @@ #include "constants/trainers.h" #include "constants/trainer_hill.h" #include "constants/weather.h" -#include "wild_encounter.h" +#include "fishing.h" -enum { +enum TransitionType +{ TRANSITION_TYPE_NORMAL, TRANSITION_TYPE_CAVE, TRANSITION_TYPE_FLASH, @@ -259,7 +261,7 @@ static void Task_BattleStart(u8 taskId) } } -static void CreateBattleStartTask(u8 transition, u16 song) +static void CreateBattleStartTask(enum BattleTransition transition, u16 song) { u8 taskId = CreateTask(Task_BattleStart, 1); @@ -532,7 +534,7 @@ void StartGroudonKyogreBattle(void) void StartRegiBattle(void) { - u8 transitionId; + enum BattleTransition transitionId; u16 species; LockPlayerFieldControls(); @@ -626,7 +628,7 @@ enum BattleEnvironments BattleSetup_GetEnvironmentId(void) u16 tileBehavior; s16 x, y; - if (I_FISHING_ENVIRONMENT >= GEN_4 && gIsFishingEncounter) + if (ShouldUseFishingEnvironmentInBattle()) GetXYCoordsOneStepInFrontOfPlayer(&x, &y); else PlayerGetDestCoords(&x, &y); @@ -685,7 +687,7 @@ enum BattleEnvironments BattleSetup_GetEnvironmentId(void) return BATTLE_ENVIRONMENT_PLAIN; } -static u8 GetBattleTransitionTypeByMap(void) +static enum TransitionType GetBattleTransitionTypeByMap(void) { u16 tileBehavior; s16 x, y; @@ -748,7 +750,7 @@ static u8 GetSumOfEnemyPartyLevel(u16 opponentId, u8 numMons) return sum; } -u8 GetWildBattleTransition(void) +enum BattleTransition GetWildBattleTransition(void) { u8 transitionType = GetBattleTransitionTypeByMap(); u8 enemyLevel = GetMonData(&gEnemyParty[0], MON_DATA_LEVEL); @@ -770,7 +772,7 @@ u8 GetWildBattleTransition(void) } } -u8 GetTrainerBattleTransition(void) +enum BattleTransition GetTrainerBattleTransition(void) { u8 minPartyCount = 1; u8 transitionType; @@ -813,7 +815,7 @@ u8 GetTrainerBattleTransition(void) } #define RANDOM_TRANSITION(table) (table[Random() % ARRAY_COUNT(table)]) -u8 GetSpecialBattleTransition(s32 id) +enum BattleTransition GetSpecialBattleTransition(enum BattleTransitionGroup id) { u16 var; u8 enemyLevel = GetMonData(&gEnemyParty[0], MON_DATA_LEVEL); @@ -831,6 +833,8 @@ u8 GetSpecialBattleTransition(s32 id) return RANDOM_TRANSITION(sBattleTransitionTable_BattlePyramid); case B_TRANSITION_GROUP_B_DOME: return RANDOM_TRANSITION(sBattleTransitionTable_BattleDome); + default: + break; } if (VarGet(VAR_FRONTIER_BATTLE_MODE) != FRONTIER_MODE_LINK_MULTIS) @@ -848,6 +852,8 @@ u8 GetSpecialBattleTransition(s32 id) return RANDOM_TRANSITION(sBattleTransitionTable_BattlePyramid); case B_TRANSITION_GROUP_B_DOME: return RANDOM_TRANSITION(sBattleTransitionTable_BattleDome); + default: + break; } if (VarGet(VAR_FRONTIER_BATTLE_MODE) != FRONTIER_MODE_LINK_MULTIS) @@ -1299,6 +1305,7 @@ static void CB2_EndTrainerBattle(void) { HandleBattleVariantEndParty(); + gIsDebugBattle = FALSE; if (FollowerNPCIsBattlePartner()) { RestorePartyAfterFollowerNPCBattle(); @@ -1499,9 +1506,19 @@ static const u8 *ReturnEmptyStringIfNull(const u8 *string) static const u8 *GetIntroSpeechOfApproachingTrainer(void) { if (gApproachingTrainerId == 0) + { + if (OW_NAME_BOX_NPC_TRAINER) + gSpeakerName = GetTrainerNameFromId(TRAINER_BATTLE_PARAM.opponentA); + return ReturnEmptyStringIfNull(TRAINER_BATTLE_PARAM.introTextA); + } else + { + if (OW_NAME_BOX_NPC_TRAINER) + gSpeakerName = GetTrainerNameFromId(TRAINER_BATTLE_PARAM.opponentB); + return ReturnEmptyStringIfNull(TRAINER_BATTLE_PARAM.introTextB); + } } const u8 *GetTrainerALoseText(void) diff --git a/src/battle_terastal.c b/src/battle_terastal.c index 8799dc7ab2..f0e720c93e 100644 --- a/src/battle_terastal.c +++ b/src/battle_terastal.c @@ -14,7 +14,6 @@ #include "sprite.h" #include "util.h" #include "constants/abilities.h" -#include "constants/hold_effects.h" #include "constants/rgb.h" // Sets flags and variables upon a battler's Terastallization. @@ -62,7 +61,7 @@ void ApplyBattlerVisualsForTeraAnim(u32 battler) // Returns whether a battler can Terastallize. bool32 CanTerastallize(u32 battler) { - enum ItemHoldEffect holdEffect = GetBattlerHoldEffect(battler, FALSE); + enum HoldEffect holdEffect = GetBattlerHoldEffectIgnoreNegation(battler); if (gBattleMons[battler].volatiles.transformed && GET_BASE_SPECIES_ID(gBattleMons[battler].species) == SPECIES_TERAPAGOS) return FALSE; @@ -109,20 +108,20 @@ bool32 CanTerastallize(u32 battler) } // Returns a battler's Tera type. -u32 GetBattlerTeraType(u32 battler) +enum Type GetBattlerTeraType(u32 battler) { return GetMonData(GetBattlerMon(battler), MON_DATA_TERA_TYPE); } // Uses up a type's Stellar boost. -void ExpendTypeStellarBoost(u32 battler, u32 type) +void ExpendTypeStellarBoost(u32 battler, enum Type type) { if (type < 32 && gBattleMons[battler].species != SPECIES_TERAPAGOS_STELLAR) // avoid OOB access gBattleStruct->stellarBoostFlags[GetBattlerSide(battler)] |= 1u << type; } // Checks whether a type's Stellar boost has been expended. -bool32 IsTypeStellarBoosted(u32 battler, u32 type) +bool32 IsTypeStellarBoosted(u32 battler, enum Type type) { if (type < 32) // avoid OOB access return !(gBattleStruct->stellarBoostFlags[GetBattlerSide(battler)] & (1u << type)); @@ -132,20 +131,19 @@ bool32 IsTypeStellarBoosted(u32 battler, u32 type) // Returns the STAB power multiplier to use when Terastallized. // Power multipliers from Smogon Research thread. -uq4_12_t GetTeraMultiplier(u32 battler, u32 type) +uq4_12_t GetTeraMultiplier(struct DamageContext *ctx) { - u32 teraType = GetBattlerTeraType(battler); - bool32 hasAdaptability = (GetBattlerAbility(battler) == ABILITY_ADAPTABILITY); + enum Type teraType = GetBattlerTeraType(ctx->battlerAtk); // Safety check. - if (GetActiveGimmick(battler) != GIMMICK_TERA) + if (GetActiveGimmick(ctx->battlerAtk) != GIMMICK_TERA) return UQ_4_12(1.0); // Stellar-type checks. if (teraType == TYPE_STELLAR) { - bool32 shouldBoost = IsTypeStellarBoosted(battler, type); - if (IS_BATTLER_OF_BASE_TYPE(battler, type)) + bool32 shouldBoost = IsTypeStellarBoosted(ctx->battlerAtk, ctx->moveType); + if (IS_BATTLER_OF_BASE_TYPE(ctx->battlerAtk, ctx->moveType)) { if (shouldBoost) return UQ_4_12(2.0); @@ -158,18 +156,18 @@ uq4_12_t GetTeraMultiplier(u32 battler, u32 type) return UQ_4_12(1.0); } // Base and Tera type. - if (type == teraType && IS_BATTLER_OF_BASE_TYPE(battler, type)) + if (ctx->moveType == teraType && IS_BATTLER_OF_BASE_TYPE(ctx->battlerAtk, ctx->moveType)) { - if (hasAdaptability) + if (ctx->abilityAtk == ABILITY_ADAPTABILITY) return UQ_4_12(2.25); else return UQ_4_12(2.0); } // Base or Tera type only. - else if ((type == teraType && !IS_BATTLER_OF_BASE_TYPE(battler, type)) - || (type != teraType && IS_BATTLER_OF_BASE_TYPE(battler, type))) + else if ((ctx->moveType == teraType && !IS_BATTLER_OF_BASE_TYPE(ctx->battlerAtk, ctx->moveType)) + || (ctx->moveType != teraType && IS_BATTLER_OF_BASE_TYPE(ctx->battlerAtk, ctx->moveType))) { - if (hasAdaptability) + if (ctx->abilityAtk == ABILITY_ADAPTABILITY) return UQ_4_12(2.0); else return UQ_4_12(1.5); @@ -181,7 +179,7 @@ uq4_12_t GetTeraMultiplier(u32 battler, u32 type) } } -u16 GetTeraTypeRGB(u32 type) +u16 GetTeraTypeRGB(enum Type type) { return gTypesInfo[type].teraTypeRGBValue; } diff --git a/src/battle_tower.c b/src/battle_tower.c index 44ef64305c..a54272e130 100644 --- a/src/battle_tower.c +++ b/src/battle_tower.c @@ -40,6 +40,8 @@ #include "constants/trainers.h" #include "constants/event_objects.h" #include "constants/moves.h" +#include "test/battle.h" +#include "test/test_runner_battle.h" // EWRAM vars. EWRAM_DATA const struct BattleFrontierTrainer *gFacilityTrainers = NULL; @@ -1569,7 +1571,8 @@ void CreateFacilityMon(const struct TrainerMon *fmon, u16 level, u8 fixedIV, u32 { u8 ball = (fmon->ball == 0xFF) ? Random() % POKEBALL_COUNT : fmon->ball; u16 move; - u32 personality = 0, ability, friendship, j; + u32 personality = 0, friendship, j; + enum Ability ability; if (fmon->gender == TRAINER_MON_MALE) { @@ -1629,7 +1632,7 @@ void CreateFacilityMon(const struct TrainerMon *fmon, u16 level, u8 fixedIV, u32 if (fmon->isShiny) { - u32 data = TRUE; + bool32 data = TRUE; SetMonData(dst, MON_DATA_IS_SHINY, &data); } if (fmon->dynamaxLevel > 0) @@ -1644,7 +1647,7 @@ void CreateFacilityMon(const struct TrainerMon *fmon, u16 level, u8 fixedIV, u32 } if (fmon->teraType) { - u32 data = fmon->teraType; + enum Type data = fmon->teraType; SetMonData(dst, MON_DATA_TERA_TYPE, &data); } @@ -3556,18 +3559,20 @@ bool32 ValidateBattleTowerRecord(u8 recordId) // unused void TrySetLinkBattleTowerEnemyPartyLevel(void) { - if (gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_RECORDED_LINK)) + if (!IsMultibattleTest()) { - s32 i; - u8 enemyLevel = SetFacilityPtrsGetLevel(); - - for (i = 0; i < PARTY_SIZE; i++) + if (gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_RECORDED_LINK)) { - u32 species = GetMonData(&gEnemyParty[i], MON_DATA_SPECIES, NULL); - if (species) + u8 enemyLevel = SetFacilityPtrsGetLevel(); + + for (u32 i = 0; i < PARTY_SIZE; i++) { - SetMonData(&gEnemyParty[i], MON_DATA_EXP, &gExperienceTables[gSpeciesInfo[species].growthRate][enemyLevel]); - CalculateMonStats(&gEnemyParty[i]); + u32 species = GetMonData(&gEnemyParty[i], MON_DATA_SPECIES, NULL); + if (species) + { + SetMonData(&gEnemyParty[i], MON_DATA_EXP, &gExperienceTables[gSpeciesInfo[species].growthRate][enemyLevel]); + CalculateMonStats(&gEnemyParty[i]); + } } } } diff --git a/src/battle_transition.c b/src/battle_transition.c index 114248b93d..2b28bf7dc7 100644 --- a/src/battle_transition.c +++ b/src/battle_transition.c @@ -2280,7 +2280,7 @@ static bool8 Mugshot_SetGfx(struct Task *task) s16 i, j; u16 *tilemap, *tileset; const u16 *mugshotsMap = sMugshotsTilemap; - u8 mugshotColor = GetTrainerMugshotColorFromId(TRAINER_BATTLE_PARAM.opponentA); + enum MugshotColor mugshotColor = GetTrainerMugshotColorFromId(TRAINER_BATTLE_PARAM.opponentA); GetBg0TilesDst(&tilemap, &tileset); CpuSet(sEliteFour_Tileset, tileset, 0xF0); diff --git a/src/battle_tv.c b/src/battle_tv.c index 2fc8fad7b7..cecab5efb3 100644 --- a/src/battle_tv.c +++ b/src/battle_tv.c @@ -14,7 +14,7 @@ static bool8 IsNotSpecialBattleString(enum StringID stringId); static void AddMovePoints(u8 caseId, u16 arg1, u8 arg2, u8 arg3); static void TrySetBattleSeminarShow(void); -static void AddPointsOnFainting(bool8 targetFainted); +static void AddPointsOnFainting(void); static void AddPointsBasedOnWeather(u16 weatherFlags, u16 move, u8 moveSlot); static bool8 ShouldCalculateDamage(u16 move, s32 *dmg, u16 *powerOverride); @@ -124,12 +124,23 @@ static const u16 *const sPointsArray[] = // even if current Pokémon does not have corresponding move static const u16 sSpecialBattleStrings[] = { - STRINGID_PKMNPERISHCOUNTFELL, STRINGID_PKMNWISHCAMETRUE, STRINGID_PKMNLOSTPPGRUDGE, - STRINGID_PKMNTOOKFOE, STRINGID_PKMNABSORBEDNUTRIENTS, STRINGID_PKMNANCHOREDITSELF, - STRINGID_PKMNAFFLICTEDBYCURSE, STRINGID_PKMNSAPPEDBYLEECHSEED, STRINGID_PKMNLOCKEDINNIGHTMARE, - STRINGID_PKMNHURTBY, STRINGID_PKMNHURTBYBURN, STRINGID_PKMNHURTBYPOISON, - STRINGID_PKMNHURTBYSPIKES, STRINGID_ATTACKERFAINTED, STRINGID_TARGETFAINTED, - STRINGID_PKMNHITWITHRECOIL, STRINGID_PKMNCRASHED, TABLE_END + STRINGID_PKMNPERISHCOUNTFELL, + STRINGID_PKMNWISHCAMETRUE, + STRINGID_PKMNLOSTPPGRUDGE, + STRINGID_PKMNTOOKFOE, + STRINGID_PKMNABSORBEDNUTRIENTS, + STRINGID_PKMNANCHOREDITSELF, + STRINGID_PKMNAFFLICTEDBYCURSE, + STRINGID_PKMNSAPPEDBYLEECHSEED, + STRINGID_PKMNLOCKEDINNIGHTMARE, + STRINGID_PKMNHURTBY, + STRINGID_PKMNHURTBYBURN, + STRINGID_PKMNHURTBYPOISON, + STRINGID_PKMNHURTBYSPIKES, + STRINGID_BATTLERFAINTED, + STRINGID_PKMNHITWITHRECOIL, + STRINGID_PKMNCRASHED, + TABLE_END }; // code @@ -139,7 +150,7 @@ void BattleTv_SetDataBasedOnString(enum StringID stringId) u32 atkSide, defSide, effSide, scriptingSide; struct Pokemon *atkMon, *defMon; u8 moveSlot; - u32 atkFlank, defFlank, effFlank; + u32 atkFlank, defFlank, effFlank, flank; u8 *perishCount; u16 *statStringId, *finishedMoveId; @@ -452,8 +463,6 @@ void BattleTv_SetDataBasedOnString(enum StringID stringId) tvPtr->pos[atkSide][atkFlank].mudSportMonId = gBattlerPartyIndexes[gBattlerAttacker] + 1; tvPtr->pos[atkSide][atkFlank].mudSportMoveSlot = moveSlot; break; - case STRINGID_ATTACKERFAINTED: - AddPointsOnFainting(FALSE); case STRINGID_RETURNMON: if (tvPtr->pos[atkSide][atkFlank].waterSportMonId != 0) { @@ -466,26 +475,29 @@ void BattleTv_SetDataBasedOnString(enum StringID stringId) tvPtr->pos[atkSide][atkFlank].mudSportMoveSlot = 0; } break; - case STRINGID_TARGETFAINTED: - AddPointsOnFainting(TRUE); - if (tvPtr->pos[atkSide][defFlank].waterSportMonId != 0) + case STRINGID_BATTLERFAINTED: + AddPointsOnFainting(); + if (gBattlerAttacker == gBattleScripting.battler) + flank = atkFlank; + else + flank = defFlank; + + if (tvPtr->pos[atkSide][flank].waterSportMonId != 0) { - tvPtr->pos[atkSide][defFlank].waterSportMonId = 0; - tvPtr->pos[atkSide][defFlank].waterSportMoveSlot = 0; + tvPtr->pos[atkSide][flank].waterSportMonId = 0; + tvPtr->pos[atkSide][flank].waterSportMoveSlot = 0; } - if (tvPtr->pos[atkSide][defFlank].mudSportMonId != 0) + if (tvPtr->pos[atkSide][flank].mudSportMonId != 0) { - tvPtr->pos[atkSide][defFlank].mudSportMonId = 0; - tvPtr->pos[atkSide][defFlank].mudSportMoveSlot = 0; + tvPtr->pos[atkSide][flank].mudSportMonId = 0; + tvPtr->pos[atkSide][flank].mudSportMoveSlot = 0; } break; case STRINGID_PKMNRAISEDDEF: - case STRINGID_PKMNRAISEDDEFALITTLE: tvPtr->side[atkSide].reflectMonId = gBattlerPartyIndexes[gBattlerAttacker] + 1; tvPtr->side[atkSide].reflectMoveSlot = moveSlot; break; case STRINGID_PKMNRAISEDSPDEF: - case STRINGID_PKMNRAISEDSPDEFALITTLE: tvPtr->side[atkSide].lightScreenMonId = gBattlerPartyIndexes[gBattlerAttacker] + 1; tvPtr->side[atkSide].lightScreenMoveSlot = moveSlot; break; @@ -591,7 +603,7 @@ void BattleTv_SetDataBasedOnMove(u16 move, u16 weatherFlags, struct DisableStruc tvPtr->side[atkSide].usedMoveSlot = moveSlot; AddMovePoints(PTS_MOVE_EFFECT, moveSlot, move, 0); AddPointsBasedOnWeather(weatherFlags, move, moveSlot); - if (gBattleMons[gBattlerAttacker].volatiles.charge) + if (gBattleMons[gBattlerAttacker].volatiles.chargeTimer > 0) AddMovePoints(PTS_ELECTRIC, move, moveSlot, 0); if (move == MOVE_WISH) @@ -1066,7 +1078,7 @@ static void AddMovePoints(u8 caseId, u16 arg1, u8 arg2, u8 arg3) } } -static void AddPointsOnFainting(bool8 targetFainted) +static void AddPointsOnFainting(void) { struct BattleTv *tvPtr = &gBattleStruct->tv; u32 atkSide = GetBattlerSide(gBattlerAttacker); @@ -1189,7 +1201,7 @@ static void AddPointsOnFainting(bool8 targetFainted) } break; case FNT_RECOIL: - if (targetFainted == TRUE) + if (gBattlerAttacker == gBattleScripting.battler) { AddMovePoints(PTS_FAINT_SET_UP, 0, atkSide, (gBattlerPartyIndexes[gBattlerAttacker]) * 4 + tvPtr->side[atkSide].usedMoveSlot); @@ -1253,24 +1265,24 @@ static void TrySetBattleSeminarShow(void) dmgByMove[gMoveSelectionCursor[gBattlerAttacker]] = gBattleStruct->moveDamage[gBattlerTarget]; // TODO: Not sure currMoveSaved = gCurrentMove; + u16 storedMoveResultFlags = gBattleStruct->moveResultFlags[gBattlerTarget]; for (i = 0; i < MAX_MON_MOVES; i++) { gCurrentMove = gBattleMons[gBattlerAttacker].moves[i]; powerOverride = 0; if (ShouldCalculateDamage(gCurrentMove, &dmgByMove[i], &powerOverride)) { - struct DamageContext ctx; + struct DamageContext ctx = {0}; ctx.battlerAtk = gBattlerAttacker; ctx.battlerDef = gBattlerTarget; - ctx.move = gCurrentMove; + ctx.move = ctx.chosenMove = gCurrentMove; ctx.moveType = GetMoveType(gCurrentMove); ctx.isCrit = FALSE; ctx.randomFactor = FALSE; ctx.updateFlags = FALSE; ctx.isSelfInflicted = FALSE; ctx.fixedBasePower = powerOverride; - gBattleStruct->moveDamage[gBattlerTarget] = CalculateMoveDamage(&ctx); - dmgByMove[i] = gBattleStruct->moveDamage[gBattlerTarget]; + dmgByMove[i] = CalculateMoveDamage(&ctx); if (dmgByMove[i] == 0 && !(gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_NO_EFFECT)) dmgByMove[i] = 1; } @@ -1301,8 +1313,8 @@ static void TrySetBattleSeminarShow(void) } } - gBattleStruct->moveDamage[gBattlerTarget] = dmgByMove[gMoveSelectionCursor[gBattlerAttacker]]; gCurrentMove = currMoveSaved; + gBattleStruct->moveResultFlags[gBattlerTarget] = storedMoveResultFlags; } static bool8 ShouldCalculateDamage(u16 move, s32 *dmg, u16 *powerOverride) diff --git a/src/battle_util.c b/src/battle_util.c index 696efdea4d..da74fe3b7f 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -2,6 +2,7 @@ #include "battle.h" #include "battle_anim.h" #include "battle_arena.h" +#include "battle_environment.h" #include "battle_pyramid.h" #include "battle_util.h" #include "battle_controllers.h" @@ -9,6 +10,7 @@ #include "battle_setup.h" #include "battle_z_move.h" #include "battle_gimmick.h" +#include "battle_hold_effects.h" #include "generational_changes.h" #include "party_menu.h" #include "pokemon.h" @@ -42,7 +44,6 @@ #include "constants/battle_move_effects.h" #include "constants/battle_script_commands.h" #include "constants/battle_string_ids.h" -#include "constants/hold_effects.h" #include "constants/items.h" #include "constants/item_effects.h" #include "constants/moves.h" @@ -63,11 +64,20 @@ static bool32 TryRemoveScreens(u32 battler); static bool32 IsUnnerveAbilityOnOpposingSide(u32 battler); static u32 GetFlingPowerFromItemId(u32 itemId); static void SetRandomMultiHitCounter(); -static u32 GetBattlerItemHoldEffectParam(u32 battler, u32 item); -static bool32 CanBeInfinitelyConfused(u32 battler); -static bool32 IsNonVolatileStatusBlocked(u32 battlerDef, u32 abilityDef, u32 abilityAffected, const u8 *battleScript, enum FunctionCallOption option); +static bool32 IsNonVolatileStatusBlocked(u32 battlerDef, enum Ability abilityDef, enum Ability abilityAffected, const u8 *battleScript, enum FunctionCallOption option); static bool32 CanSleepDueToSleepClause(u32 battlerAtk, u32 battlerDef, enum FunctionCallOption option); static bool32 IsOpposingSideEmpty(u32 battler); +static void ResetParadoxWeatherStat(u32 battler); +static void ResetParadoxTerrainStat(u32 battler); +static bool32 CanBattlerFormChange(u32 battler, enum FormChanges method); + +// Submoves +static u32 GetMirrorMoveMove(void); +static u32 GetMetronomeMove(void); +static u32 GetAssistMove(void); +static u32 GetSleepTalkMove(void); +static u32 GetCopyCatMove(void); +static u32 GetMeFirstMove(void); ARM_FUNC NOINLINE static uq4_12_t PercentToUQ4_12(u32 percent); ARM_FUNC NOINLINE static uq4_12_t PercentToUQ4_12_Floored(u32 percent); @@ -206,18 +216,18 @@ static const struct BattleWeatherInfo sBattleWeatherInfo[BATTLE_WEATHER_COUNT] = // Helper function for actual dmg calcs during battle. For simulated AI dmg, CalcTypeEffectivenessMultiplier should be used directly // This should stay a static function. Ideally everything else is handled through CalcTypeEffectivenessMultiplier just like AI -static uq4_12_t CalcTypeEffectivenessMultiplierHelper(u32 move, u32 moveType, u32 battlerAtk, u32 battlerDef, u32 abilityAtk, u32 abilityDef, bool32 recordAbilities) +static uq4_12_t CalcTypeEffectivenessMultiplierHelper(u32 move, enum Type moveType, u32 battlerAtk, u32 battlerDef, enum Ability abilityAtk, enum Ability abilityDef, bool32 recordAbilities) { struct DamageContext ctx = {0}; ctx.battlerAtk = battlerAtk; ctx.battlerDef = battlerDef; - ctx.move = move; + ctx.move = ctx.chosenMove = move; ctx.moveType = moveType; ctx.updateFlags = recordAbilities; ctx.abilityAtk = abilityAtk; ctx.abilityDef = abilityDef; - ctx.holdEffectAtk = GetBattlerHoldEffect(battlerAtk, TRUE); - ctx.holdEffectDef = GetBattlerHoldEffect(battlerDef, TRUE); + ctx.holdEffectAtk = GetBattlerHoldEffect(battlerAtk); + ctx.holdEffectDef = GetBattlerHoldEffect(battlerDef); return CalcTypeEffectivenessMultiplier(&ctx); } @@ -249,7 +259,10 @@ bool32 EndOrContinueWeather(void) { gBattleWeather = B_WEATHER_NONE; for (u32 battler = 0; battler < gBattlersCount; battler++) + { gDisableStructs[battler].weatherAbilityDone = FALSE; + ResetParadoxWeatherStat(battler); + } gBattleCommunication[MULTISTRING_CHOOSER] = sBattleWeatherInfo[currBattleWeather].endMessage; BattleScriptExecute(BattleScript_WeatherFaded); return TRUE; @@ -265,13 +278,36 @@ bool32 EndOrContinueWeather(void) return FALSE; } +// Gen5+ static u32 CalcBeatUpPower(void) { u32 species = gBattleStruct->beatUpSpecies[gBattleStruct->beatUpSlot++]; return (GetSpeciesBaseAttack(species) / 10) + 5; } -static bool32 ShouldTeraShellDistortTypeMatchups(u32 move, u32 battlerDef, u32 abilityDef) +// Gen 3/4 +static s32 CalcBeatUpDamage(struct DamageContext *ctx) +{ + u32 partyIndex = gBattleStruct->beatUpSpecies[gBattleStruct->beatUpSlot++]; + struct Pokemon *party = GetBattlerParty(ctx->battlerAtk); + u32 species = GetMonData(&party[partyIndex], MON_DATA_SPECIES); + u32 levelFactor = GetMonData(&party[partyIndex], MON_DATA_LEVEL) * 2 / 5 + 2; + s32 dmg = GetSpeciesBaseAttack(species); + + dmg *= GetMovePower(ctx->move); + dmg *= levelFactor; + dmg /= GetSpeciesBaseDefense(gBattleMons[ctx->battlerDef].species); + dmg = (dmg / 50) + 2; + + if (gProtectStructs[ctx->battlerAtk].helpingHand) + dmg = dmg * 15 / 10; + if (ctx->isCrit) + dmg *= 2; + + return dmg; +} + +static bool32 ShouldTeraShellDistortTypeMatchups(u32 move, u32 battlerDef, enum Ability abilityDef) { if (!gSpecialStatuses[battlerDef].distortedTypeMatchups && gBattleMons[battlerDef].species == SPECIES_TERAPAGOS_TERASTAL @@ -294,9 +330,48 @@ static inline bool32 IsDragonDartsSecondHit(u32 effect) return FALSE; } +bool32 IsUnnerveBlocked(u32 battler, u32 itemId) +{ + if (GetItemPocket(itemId) != POCKET_BERRIES) + return FALSE; + + if (gBattleScripting.overrideBerryRequirements > 0) // Berries that aren't eaten naturally ignore unnerve + return FALSE; + + if (IsUnnerveAbilityOnOpposingSide(battler)) + return TRUE; + + return FALSE; +} + +static bool32 IsUnnerveAbilityOnOpposingSide(u32 battler) +{ + for (u32 battlerDef = 0; battlerDef < gBattlersCount; battlerDef++) + { + if (battler == battlerDef || IsBattlerAlly(battler, battlerDef)) + continue; + + if (!IsBattlerAlive(battlerDef)) + continue; + + enum Ability ability = GetBattlerAbility(battlerDef); + switch (ability) + { + case ABILITY_UNNERVE: + case ABILITY_AS_ONE_ICE_RIDER: + case ABILITY_AS_ONE_SHADOW_RIDER: + return TRUE; + default: + break; + } + } + + return FALSE; +} + bool32 IsAffectedByFollowMe(u32 battlerAtk, u32 defSide, u32 move) { - u32 ability = GetBattlerAbility(battlerAtk); + enum Ability ability = GetBattlerAbility(battlerAtk); enum BattleMoveEffects effect = GetMoveEffect(move); if (gSideTimers[defSide].followmeTimer == 0 @@ -310,7 +385,7 @@ bool32 IsAffectedByFollowMe(u32 battlerAtk, u32 defSide, u32 move) if (effect == EFFECT_PURSUIT && IsPursuitTargetSet()) return FALSE; - if (gSideTimers[defSide].followmePowder && !IsAffectedByPowderMove(battlerAtk, ability, GetBattlerHoldEffect(battlerAtk, TRUE))) + if (gSideTimers[defSide].followmePowder && !IsAffectedByPowderMove(battlerAtk, ability, GetBattlerHoldEffect(battlerAtk))) return FALSE; return TRUE; @@ -320,10 +395,10 @@ bool32 HandleMoveTargetRedirection(void) { u32 redirectorOrderNum = MAX_BATTLERS_COUNT; u16 moveTarget = GetBattlerMoveTargetType(gBattlerAttacker, gCurrentMove); - u32 moveType = GetBattleMoveType(gCurrentMove); + enum Type moveType = GetBattleMoveType(gCurrentMove); enum BattleMoveEffects moveEffect = GetMoveEffect(gCurrentMove); u32 side = BATTLE_OPPOSITE(GetBattlerSide(gBattlerAttacker)); - u32 ability = GetBattlerAbility(gBattleStruct->moveTarget[gBattlerAttacker]); + enum Ability ability = GetBattlerAbility(gBattleStruct->moveTarget[gBattlerAttacker]); if (IsAffectedByFollowMe(gBattlerAttacker, side, gCurrentMove) && moveTarget == MOVE_TARGET_SELECTED @@ -339,7 +414,7 @@ bool32 HandleMoveTargetRedirection(void) || (ability != ABILITY_STORM_DRAIN && moveType == TYPE_WATER))) { // Find first battler that redirects the move (in turn order) - u32 abilityAtk = GetBattlerAbility(gBattlerAttacker); + enum Ability abilityAtk = GetBattlerAbility(gBattlerAttacker); u32 battler; for (battler = 0; battler < gBattlersCount; battler++) { @@ -358,17 +433,13 @@ bool32 HandleMoveTargetRedirection(void) redirectorOrderNum = GetBattlerTurnOrderNum(battler); } } - if (redirectorOrderNum != MAX_BATTLERS_COUNT) + if (redirectorOrderNum != MAX_BATTLERS_COUNT && gCurrentMove != MOVE_TEATIME) { - u16 battlerAbility; + enum Ability battlerAbility; battler = gBattlerByTurnOrder[redirectorOrderNum]; battlerAbility = GetBattlerAbility(battler); - - RecordAbilityBattle(battler, gBattleMons[battler].ability); - if (battlerAbility == ABILITY_LIGHTNING_ROD && gCurrentMove != MOVE_TEATIME) - gSpecialStatuses[battler].lightningRodRedirected = TRUE; - else if (battlerAbility == ABILITY_STORM_DRAIN) - gSpecialStatuses[battler].stormDrainRedirected = TRUE; + RecordAbilityBattle(battler, battlerAbility); + gSpecialStatuses[battler].abilityRedirected = TRUE; gBattlerTarget = battler; return TRUE; } @@ -390,11 +461,6 @@ void HandleAction_UseMove(void) return; } - gBattleStruct->atkCancelerTracker = 0; - ClearDamageCalcResults(); - gMultiHitCounter = 0; - gBattleScripting.savedDmg = 0; - gBattleCommunication[MISS_TYPE] = 0; gCurrMovePos = gChosenMovePos = gBattleStruct->chosenMovePositions[gBattlerAttacker]; // choose move @@ -402,7 +468,6 @@ void HandleAction_UseMove(void) { gProtectStructs[gBattlerAttacker].noValidMoves = FALSE; gCurrentMove = gChosenMove = MOVE_STRUGGLE; - gHitMarker |= HITMARKER_NO_PPDEDUCT; gBattleStruct->moveTarget[gBattlerAttacker] = GetBattleMoveTarget(MOVE_STRUGGLE, NO_TARGET_OVERRIDE); } else if (gBattleMons[gBattlerAttacker].volatiles.multipleTurns || gDisableStructs[gBattlerAttacker].rechargeTimer > 0) @@ -415,7 +480,7 @@ void HandleAction_UseMove(void) { gCurrentMove = gChosenMove = gDisableStructs[gBattlerAttacker].encoredMove; gCurrMovePos = gChosenMovePos = gDisableStructs[gBattlerAttacker].encoredMovePos; - if (GetGenConfig(GEN_CONFIG_ENCORE_TARGET) < GEN_5) + if (GetConfig(CONFIG_ENCORE_TARGET) < GEN_5) gBattleStruct->moveTarget[gBattlerAttacker] = GetBattleMoveTarget(gCurrentMove, NO_TARGET_OVERRIDE); } // check if the encored move wasn't overwritten @@ -463,6 +528,11 @@ void HandleAction_UseMove(void) gCurrentMove = gChosenMove = GetMaxMove(gBattlerAttacker, gCurrentMove); } + gBattleStruct->eventState.atkCanceler = 0; + ClearDamageCalcResults(); + gMultiHitCounter = 0; + gBattleCommunication[MISS_TYPE] = 0; + moveTarget = GetBattlerMoveTargetType(gBattlerAttacker, gCurrentMove); if (!HandleMoveTargetRedirection()) @@ -499,9 +569,10 @@ void HandleAction_UseMove(void) } else { - gBattlerTarget = *(gBattleStruct->moveTarget + gBattlerAttacker); + gBattlerTarget = gBattleStruct->moveTarget[gBattlerAttacker]; if (!IsBattlerAlive(gBattlerTarget) && moveTarget != MOVE_TARGET_OPPONENTS_FIELD + && IsDoubleBattle() && (!IsBattlerAlly(gBattlerAttacker, gBattlerTarget))) { gBattlerTarget = GetBattlerAtPosition(BATTLE_PARTNER(GetBattlerPosition(gBattlerTarget))); @@ -548,7 +619,7 @@ void HandleAction_UseMove(void) BattleArena_AddMindPoints(gBattlerAttacker); for (i = 0; i < MAX_BATTLERS_COUNT; i++) - gBattleStruct->hpBefore[i] = gBattleMons[i].hp; + gBattleStruct->battlerState[i].wasAboveHalfHp = gBattleMons[i].hp > gBattleMons[i].maxHP / 2; gCurrentActionFuncId = B_ACTION_EXEC_SCRIPT; } @@ -733,7 +804,7 @@ void HandleAction_Run(void) } else { - if (GetBattlerHoldEffect(gBattlerAttacker, TRUE) != HOLD_EFFECT_CAN_ALWAYS_RUN + if (GetBattlerHoldEffect(gBattlerAttacker) != HOLD_EFFECT_CAN_ALWAYS_RUN && GetBattlerAbility(gBattlerAttacker) != ABILITY_RUN_AWAY && !CanBattlerEscape(gBattlerAttacker)) { @@ -863,7 +934,7 @@ void HandleAction_TryFinish(void) { if (!HandleFaintedMonActions()) { - gBattleStruct->faintedActionsState = 0; + gBattleStruct->eventState.faintedAction = 0; gCurrentActionFuncId = B_ACTION_FINISHED; } } @@ -873,13 +944,7 @@ void HandleAction_NothingIsFainted(void) gCurrentTurnActionNumber++; gCurrentActionFuncId = gActionsByTurnOrder[gCurrentTurnActionNumber]; gBattleStruct->synchronizeMoveEffect = MOVE_EFFECT_NONE; - gHitMarker &= ~(HITMARKER_DESTINYBOND - | HITMARKER_IGNORE_SUBSTITUTE - | HITMARKER_ATTACKSTRING_PRINTED - | HITMARKER_NO_PPDEDUCT - | HITMARKER_STATUS_ABILITY_EFFECT - | HITMARKER_PASSIVE_HP_UPDATE - | HITMARKER_OBEYS); + gHitMarker &= ~(HITMARKER_OBEYS); } void HandleAction_ActionFinished(void) @@ -889,18 +954,11 @@ void HandleAction_ActionFinished(void) gBattleStruct->monToSwitchIntoId[gBattlerByTurnOrder[gCurrentTurnActionNumber]] = gSelectedMonPartyId = PARTY_SIZE; gCurrentTurnActionNumber++; gCurrentActionFuncId = gActionsByTurnOrder[gCurrentTurnActionNumber]; - SpecialStatusesClear(); - gHitMarker &= ~(HITMARKER_DESTINYBOND - | HITMARKER_IGNORE_SUBSTITUTE - | HITMARKER_ATTACKSTRING_PRINTED - | HITMARKER_NO_PPDEDUCT - | HITMARKER_STATUS_ABILITY_EFFECT - | HITMARKER_PASSIVE_HP_UPDATE - | HITMARKER_OBEYS - | HITMARKER_IGNORE_DISGUISE); + memset(&gSpecialStatuses, 0, sizeof(gSpecialStatuses)); + gHitMarker &= ~(HITMARKER_OBEYS); + gCurrentMove = MOVE_NONE; ClearDamageCalcResults(); - gCurrentMove = 0; gBattleScripting.animTurn = 0; gBattleScripting.animTargetsHit = 0; gBattleStruct->dynamicMoveType = 0; @@ -909,35 +967,41 @@ void HandleAction_ActionFinished(void) gBattleScripting.moveendState = 0; gBattleCommunication[3] = 0; gBattleCommunication[4] = 0; - gBattleScripting.multihitMoveEffect = 0; gBattleResources->battleScriptsStack->size = 0; gBattleStruct->synchronizeMoveEffect = MOVE_EFFECT_NONE; - if (GetGenConfig(GEN_CONFIG_RECALC_TURN_AFTER_ACTIONS) >= GEN_8 && !afterYouActive && !gBattleStruct->pledgeMove && !IsPursuitTargetSet()) + if (GetConfig(CONFIG_RECALC_TURN_AFTER_ACTIONS) >= GEN_8 && !afterYouActive && !gBattleStruct->pledgeMove && !IsPursuitTargetSet()) { // i starts at `gCurrentTurnActionNumber` because we don't want to recalculate turn order for mon that have already // taken action. It's been previously increased, which we want in order to not recalculate the turn of the mon that just finished its action + + struct BattleContext ctx = {0}; + for (i = 0; i < gBattlersCount; i++) + { + ctx.abilities[i] = GetBattlerAbility(i); + ctx.holdEffects[i] = GetBattlerHoldEffect(i); + } for (i = gCurrentTurnActionNumber; i < gBattlersCount - 1; i++) { for (j = i + 1; j < gBattlersCount; j++) { - u32 battler1 = gBattlerByTurnOrder[i]; - u32 battler2 = gBattlerByTurnOrder[j]; + ctx.battlerAtk = gBattlerByTurnOrder[i]; + ctx.battlerDef = gBattlerByTurnOrder[j]; - if (gProtectStructs[battler1].quash || gProtectStructs[battler2].quash - || gProtectStructs[battler1].shellTrap || gProtectStructs[battler2].shellTrap) + if (gProtectStructs[ctx.battlerAtk].quash || gProtectStructs[ctx.battlerDef].quash + || gProtectStructs[ctx.battlerAtk].shellTrap || gProtectStructs[ctx.battlerDef].shellTrap) continue; // We recalculate order only for action of the same priority. If any action other than switch/move has been taken, they should // have been executed before. The only recalculation needed is for moves/switch. Mega evolution is handled in src/battle_main.c/TryChangeOrder if ((gActionsByTurnOrder[i] == B_ACTION_USE_MOVE && gActionsByTurnOrder[j] == B_ACTION_USE_MOVE)) { - if (GetWhichBattlerFaster(battler1, battler2, FALSE) == -1) + if (GetWhichBattlerFaster(&ctx, FALSE) == -1) SwapTurnOrder(i, j); } else if ((gActionsByTurnOrder[i] == B_ACTION_SWITCH && gActionsByTurnOrder[j] == B_ACTION_SWITCH)) { - if (GetWhichBattlerFaster(battler1, battler2, TRUE) == -1) // If the actions chosen are switching, we recalc order but ignoring the moves + if (GetWhichBattlerFaster(&ctx, TRUE) == -1) // If the actions chosen are switching, we recalc order but ignoring the moves SwapTurnOrder(i, j); } } @@ -1071,9 +1135,10 @@ const u8 *CheckSkyDropState(u32 battler, enum SkyDropState skyDropState) // If the target can be confused, confuse them. // Don't use CanBeConfused, can cause issues in edge cases. + enum Ability ability = GetBattlerAbility(otherSkyDropper); if (!(gBattleMons[otherSkyDropper].volatiles.confusionTurns > 0 - || IsAbilityAndRecord(otherSkyDropper, GetBattlerAbility(otherSkyDropper), ABILITY_OWN_TEMPO) - || IsBattlerTerrainAffected(otherSkyDropper, STATUS_FIELD_MISTY_TERRAIN))) + || IsAbilityAndRecord(otherSkyDropper, ability, ABILITY_OWN_TEMPO) + || IsBattlerTerrainAffected(otherSkyDropper, ability, GetBattlerHoldEffect(otherSkyDropper), STATUS_FIELD_MISTY_TERRAIN))) { // Set confused status gBattleMons[otherSkyDropper].volatiles.confusionTurns = ((Random()) % 4) + 2; @@ -1146,13 +1211,32 @@ bool32 WasUnableToUseMove(u32 battler) { if (gProtectStructs[battler].nonVolatileStatusImmobility || gProtectStructs[battler].unableToUseMove - || gProtectStructs[battler].powderSelfDmg || gProtectStructs[battler].confusionSelfDmg) return TRUE; return FALSE; } -bool32 ShouldDefiantCompetitiveActivate(u32 battler, u32 ability) +// Returns TRUE if no other battler after this one in turn order will use a move +bool32 IsLastMonToMove(u32 battler) +{ + u32 i; + u32 battlerTurnOrderNum = GetBattlerTurnOrderNum(battler); + + if (battlerTurnOrderNum >= gBattlersCount - 1) + return TRUE; + + for (i = battlerTurnOrderNum + 1; i < gBattlersCount; i++) + { + u32 otherBattler = gBattlerByTurnOrder[i]; + if (!IsBattlerAlive(otherBattler)) + continue; + if (gActionsByTurnOrder[i] == B_ACTION_USE_MOVE) + return FALSE; + } + return TRUE; +} + +bool32 ShouldDefiantCompetitiveActivate(u32 battler, enum Ability ability) { u32 side = GetBattlerSide(battler); if (ability != ABILITY_DEFIANT && ability != ABILITY_COMPETITIVE) @@ -1161,7 +1245,7 @@ bool32 ShouldDefiantCompetitiveActivate(u32 battler, u32 ability) if (IsBattlerAlly(gSpecialStatuses[battler].changedStatsBattlerId, battler) && !gBattleScripting.stickyWebStatDrop) return FALSE; - if (GetGenConfig(GEN_CONFIG_DEFIANT_STICKY_WEB) >= GEN_9 || !gBattleScripting.stickyWebStatDrop) + if (GetConfig(CONFIG_DEFIANT_STICKY_WEB) >= GEN_9 || !gBattleScripting.stickyWebStatDrop) return TRUE; // only activate Defiant/Competitive if Web was setup by foe return gSideTimers[side].stickyWebBattlerSide != side; @@ -1174,19 +1258,54 @@ void PrepareStringBattle(enum StringID stringId, u32 battler) // Support for Contrary ability. // If a move attempted to raise stat - print "won't increase". // If a move attempted to lower stat - print "won't decrease". - if (stringId == STRINGID_STATSWONTDECREASE && !(gBattleScripting.statChanger & STAT_BUFF_NEGATIVE)) - stringId = STRINGID_STATSWONTINCREASE; - else if (stringId == STRINGID_STATSWONTINCREASE && gBattleScripting.statChanger & STAT_BUFF_NEGATIVE) - stringId = STRINGID_STATSWONTDECREASE; + switch (stringId) + { + case STRINGID_ATTACKERSSTATROSE: + case STRINGID_DEFENDERSSTATROSE: + case STRINGID_STATSWONTINCREASE: + case STRINGID_USINGITEMSTATOFPKMNROSE: + if (gBattleScripting.statChanger & STAT_BUFF_NEGATIVE) + stringId = gStatDownStringIds[gBattleCommunication[MULTISTRING_CHOOSER]]; + break; + case STRINGID_ATTACKERSSTATFELL: + case STRINGID_DEFENDERSSTATFELL: + case STRINGID_STATSWONTDECREASE: + case STRINGID_USINGITEMSTATOFPKMNFELL: + if (!(gBattleScripting.statChanger & STAT_BUFF_NEGATIVE)) + stringId = gStatUpStringIds[gBattleCommunication[MULTISTRING_CHOOSER]]; + break; + case STRINGID_STATSWONTINCREASE2: + if (battlerAbility == ABILITY_CONTRARY) + stringId = STRINGID_STATSWONTDECREASE2; + break; + case STRINGID_STATSWONTDECREASE2: + if (battlerAbility == ABILITY_CONTRARY) + stringId = STRINGID_STATSWONTINCREASE2; + break; + case STRINGID_PKMNCUTSATTACKWITH: + if (GetConfig(CONFIG_UPDATED_INTIMIDATE) >= GEN_8 + && targetAbility == ABILITY_RATTLED + && CompareStat(gBattlerTarget, STAT_SPEED, MAX_STAT_STAGE, CMP_LESS_THAN, targetAbility)) + { + gBattlerAbility = gBattlerTarget; + BattleScriptCall(BattleScript_AbilityRaisesDefenderStat); + SET_STATCHANGER(STAT_SPEED, 1, FALSE); + } + else if (targetAbility == ABILITY_CONTRARY) + { + stringId = STRINGID_DEFENDERSSTATROSE; + } + break; + case STRINGID_ITDOESNTAFFECT: + case STRINGID_PKMNUNAFFECTED: + TryInitializeTrainerSlideEnemyMonUnaffected(gBattlerTarget); + break; + default: + break; + } - else if (stringId == STRINGID_STATSWONTDECREASE2 && battlerAbility == ABILITY_CONTRARY) - stringId = STRINGID_STATSWONTINCREASE2; - else if (stringId == STRINGID_STATSWONTINCREASE2 && battlerAbility == ABILITY_CONTRARY) - stringId = STRINGID_STATSWONTDECREASE2; - - // Check Defiant and Competitive stat raise whenever a stat is lowered. - else if ((stringId == STRINGID_DEFENDERSSTATFELL || stringId == STRINGID_PKMNCUTSATTACKWITH) - && ShouldDefiantCompetitiveActivate(gBattlerTarget, targetAbility)) + if ((stringId == STRINGID_PKMNCUTSATTACKWITH || stringId == STRINGID_DEFENDERSSTATFELL) + && ShouldDefiantCompetitiveActivate(gBattlerTarget, targetAbility)) { gBattlerAbility = gBattlerTarget; BattleScriptCall(BattleScript_AbilityRaisesDefenderStat); @@ -1195,18 +1314,6 @@ void PrepareStringBattle(enum StringID stringId, u32 battler) else SET_STATCHANGER(STAT_SPATK, 2, FALSE); } - else if (GetGenConfig(GEN_CONFIG_UPDATED_INTIMIDATE) >= GEN_8 - && stringId == STRINGID_PKMNCUTSATTACKWITH - && targetAbility == ABILITY_RATTLED - && CompareStat(gBattlerTarget, STAT_SPEED, MAX_STAT_STAGE, CMP_LESS_THAN, targetAbility)) - { - gBattlerAbility = gBattlerTarget; - BattleScriptCall(BattleScript_AbilityRaisesDefenderStat); - SET_STATCHANGER(STAT_SPEED, 1, FALSE); - } - - if ((stringId == STRINGID_ITDOESNTAFFECT || stringId == STRINGID_PKMNUNAFFECTED)) - TryInitializeTrainerSlideEnemyMonUnaffected(gBattlerTarget); BtlController_EmitPrintString(battler, B_COMM_TO_CONTROLLER, stringId); MarkBattlerForControllerExec(battler); @@ -1314,11 +1421,11 @@ u32 TrySetCantSelectMoveBattleScript(u32 battler) u32 limitations = 0; u8 moveId = gBattleResources->bufferB[battler][2] & ~RET_GIMMICK; u32 move = gBattleMons[battler].moves[moveId]; - enum ItemHoldEffect holdEffect = GetBattlerHoldEffect(battler, TRUE); + enum HoldEffect holdEffect = GetBattlerHoldEffect(battler); u16 *choicedMove = &gBattleStruct->choicedMove[battler]; enum BattleMoveEffects moveEffect = GetMoveEffect(move); - if (GetGenConfig(GEN_CONFIG_ENCORE_TARGET) >= GEN_5 + if (GetConfig(CONFIG_ENCORE_TARGET) >= GEN_5 && DYNAMAX_BYPASS_CHECK && GetActiveGimmick(battler) != GIMMICK_Z_MOVE && gDisableStructs[battler].encoredMove != move && gDisableStructs[battler].encoredMove != MOVE_NONE) { gBattleScripting.battler = battler; @@ -1385,7 +1492,7 @@ u32 TrySetCantSelectMoveBattleScript(u32 battler) } } - if (DYNAMAX_BYPASS_CHECK && GetActiveGimmick(battler) != GIMMICK_Z_MOVE && gDisableStructs[battler].throatChopTimer > gBattleTurnCounter && IsSoundMove(move)) + if (DYNAMAX_BYPASS_CHECK && GetActiveGimmick(battler) != GIMMICK_Z_MOVE && gDisableStructs[battler].throatChopTimer > 0 && IsSoundMove(move)) { gCurrentMove = move; if (gBattleTypeFlags & BATTLE_TYPE_PALACE) @@ -1576,7 +1683,7 @@ u32 CheckMoveLimitations(u32 battler, u8 unusableMoves, u16 check) { u32 move; enum BattleMoveEffects moveEffect; - enum ItemHoldEffect holdEffect = GetBattlerHoldEffect(battler, TRUE); + enum HoldEffect holdEffect = GetBattlerHoldEffect(battler); u16 *choicedMove = &gBattleStruct->choicedMove[battler]; s32 i; @@ -1626,7 +1733,7 @@ u32 CheckMoveLimitations(u32 battler, u8 unusableMoves, u16 check) else if (check & MOVE_LIMITATION_BELCH && IsBelchPreventingMove(battler, move)) unusableMoves |= 1u << i; // Throat Chop - else if (check & MOVE_LIMITATION_THROAT_CHOP && gDisableStructs[battler].throatChopTimer > gBattleTurnCounter && IsSoundMove(move)) + else if (check & MOVE_LIMITATION_THROAT_CHOP && gDisableStructs[battler].throatChopTimer > 0 && IsSoundMove(move)) unusableMoves |= 1u << i; // Stuff Cheeks else if (check & MOVE_LIMITATION_STUFF_CHEEKS && moveEffect == EFFECT_STUFF_CHEEKS && GetItemPocket(gBattleMons[battler].item) != POCKET_BERRIES) @@ -1718,6 +1825,7 @@ void TryToRevertMimicryAndFlags(void) for (u32 battler = 0; battler < gBattlersCount; battler++) { gDisableStructs[battler].terrainAbilityDone = FALSE; + ResetParadoxTerrainStat(battler); if (IsAbilityAndRecord(battler, GetBattlerAbility(battler), ABILITY_MIMICRY)) RESTORE_BATTLER_TYPE(battler); } @@ -1725,10 +1833,8 @@ void TryToRevertMimicryAndFlags(void) bool32 BattleArenaTurnEnd(void) { - gHitMarker |= (HITMARKER_GRUDGE | HITMARKER_IGNORE_BIDE); - if ((gBattleTypeFlags & BATTLE_TYPE_ARENA) - && gBattleStruct->arenaTurnCounter == 2 + && gBattleStruct->eventState.arenaTurn == 2 && IsBattlerAlive(B_POSITION_PLAYER_LEFT) && IsBattlerAlive(B_POSITION_OPPONENT_LEFT)) { for (u32 battler = 0; battler < 2; battler++) @@ -1738,25 +1844,22 @@ bool32 BattleArenaTurnEnd(void) BattleScriptExecute(BattleScript_ArenaDoJudgment); return TRUE; } - - gHitMarker &= ~(HITMARKER_GRUDGE | HITMARKER_IGNORE_BIDE); - return FALSE; } // Ingrain, Leech Seed, Strength Sap and Aqua Ring s32 GetDrainedBigRootHp(u32 battler, s32 hp) { - if (GetBattlerHoldEffect(battler, TRUE) == HOLD_EFFECT_BIG_ROOT) + if (GetBattlerHoldEffect(battler) == HOLD_EFFECT_BIG_ROOT) hp = (hp * 1300) / 1000; if (hp == 0) hp = 1; - return hp * -1; + return hp; } // Should always be the last check. Otherwise the ability might be wrongly recorded. -bool32 IsAbilityAndRecord(u32 battler, u32 battlerAbility, u32 abilityToCheck) +bool32 IsAbilityAndRecord(u32 battler, enum Ability battlerAbility, enum Ability abilityToCheck) { if (battlerAbility != abilityToCheck) return FALSE; @@ -1765,7 +1868,6 @@ bool32 IsAbilityAndRecord(u32 battler, u32 battlerAbility, u32 abilityToCheck) return TRUE; } -#define FAINTED_ACTIONS_MAX_CASE 6 bool32 HandleFaintedMonActions(void) { if (gBattleTypeFlags & BATTLE_TYPE_SAFARI) @@ -1773,38 +1875,38 @@ bool32 HandleFaintedMonActions(void) do { s32 i; - switch (gBattleStruct->faintedActionsState) + switch (gBattleStruct->eventState.faintedAction) { - case 0: - gBattleStruct->faintedActionsBattlerId = 0; - gBattleStruct->faintedActionsState++; + case FAINTED_ACTIONS_NO_MONS_TO_SWITCH: + gBattleStruct->eventState.faintedActionBattler = 0; + gBattleStruct->eventState.faintedAction++; for (i = 0; i < gBattlersCount; i++) { if (gAbsentBattlerFlags & (1u << i) && !HasNoMonsToSwitch(i, PARTY_SIZE, PARTY_SIZE)) gAbsentBattlerFlags &= ~(1u << i); } // fall through - case 1: + case FAINTED_ACTIONS_GIVE_EXP: do { - gBattlerFainted = gBattlerTarget = gBattleStruct->faintedActionsBattlerId; - if (gBattleMons[gBattleStruct->faintedActionsBattlerId].hp == 0 - && !(gBattleStruct->givenExpMons & (1u << gBattlerPartyIndexes[gBattleStruct->faintedActionsBattlerId])) - && !(gAbsentBattlerFlags & (1u << gBattleStruct->faintedActionsBattlerId))) + gBattlerFainted = gBattlerTarget = gBattleStruct->eventState.faintedActionBattler; + if (gBattleMons[gBattleStruct->eventState.faintedActionBattler].hp == 0 + && !(gBattleStruct->givenExpMons & (1u << gBattlerPartyIndexes[gBattleStruct->eventState.faintedActionBattler])) + && !(gAbsentBattlerFlags & (1u << gBattleStruct->eventState.faintedActionBattler))) { BattleScriptExecute(BattleScript_GiveExp); - gBattleStruct->faintedActionsState = 2; + gBattleStruct->eventState.faintedAction = FAINTED_ACTIONS_SET_ABSENT_FLAGS; return TRUE; } - } while (++gBattleStruct->faintedActionsBattlerId != gBattlersCount); - gBattleStruct->faintedActionsState = 3; + } while (++gBattleStruct->eventState.faintedActionBattler != gBattlersCount); + gBattleStruct->eventState.faintedAction = FAINTED_ACTIONS_WAIT_STATE; break; - case 2: + case FAINTED_ACTIONS_SET_ABSENT_FLAGS: OpponentSwitchInResetSentPokesToOpponentValue(gBattlerFainted); - if (++gBattleStruct->faintedActionsBattlerId == gBattlersCount) - gBattleStruct->faintedActionsState = 3; + if (++gBattleStruct->eventState.faintedActionBattler == gBattlersCount) + gBattleStruct->eventState.faintedAction = FAINTED_ACTIONS_WAIT_STATE; else - gBattleStruct->faintedActionsState = 1; + gBattleStruct->eventState.faintedAction = FAINTED_ACTIONS_GIVE_EXP; // Don't switch mons until all pokemon performed their actions or the battle's over. if (B_FAINT_SWITCH_IN >= GEN_4 && gBattleOutcome == 0 @@ -1812,11 +1914,11 @@ bool32 HandleFaintedMonActions(void) && gCurrentTurnActionNumber != gBattlersCount) { gAbsentBattlerFlags |= 1u << gBattlerFainted; - if (gBattleStruct->faintedActionsState != 1) + if (gBattleStruct->eventState.faintedAction != FAINTED_ACTIONS_GIVE_EXP) return FALSE; } break; - case 3: + case FAINTED_ACTIONS_WAIT_STATE: // Don't switch mons until all pokemon performed their actions or the battle's over. if (B_FAINT_SWITCH_IN >= GEN_4 && gBattleOutcome == 0 @@ -1825,33 +1927,33 @@ bool32 HandleFaintedMonActions(void) { return FALSE; } - gBattleStruct->faintedActionsBattlerId = 0; - gBattleStruct->faintedActionsState++; + gBattleStruct->eventState.faintedActionBattler = 0; + gBattleStruct->eventState.faintedAction++; // fall through - case 4: + case FAINTED_ACTIONS_HANDLE_FAINTED_MON: do { - gBattlerFainted = gBattlerTarget = gBattleStruct->faintedActionsBattlerId; - if (gBattleMons[gBattleStruct->faintedActionsBattlerId].hp == 0 - && !(gAbsentBattlerFlags & (1u << gBattleStruct->faintedActionsBattlerId))) + gBattlerFainted = gBattlerTarget = gBattleStruct->eventState.faintedActionBattler; + if (gBattleMons[gBattleStruct->eventState.faintedActionBattler].hp == 0 + && !(gAbsentBattlerFlags & (1u << gBattleStruct->eventState.faintedActionBattler))) { BattleScriptExecute(BattleScript_HandleFaintedMon); - gBattleStruct->faintedActionsState = 5; + gBattleStruct->eventState.faintedAction = FAINTED_ACTIONS_HANDLE_NEXT_BATTLER; return TRUE; } - } while (++gBattleStruct->faintedActionsBattlerId != gBattlersCount); - gBattleStruct->faintedActionsState = FAINTED_ACTIONS_MAX_CASE; + } while (++gBattleStruct->eventState.faintedActionBattler != gBattlersCount); + gBattleStruct->eventState.faintedAction = FAINTED_ACTIONS_MAX_CASE; break; - case 5: - if (++gBattleStruct->faintedActionsBattlerId == gBattlersCount) - gBattleStruct->faintedActionsState = FAINTED_ACTIONS_MAX_CASE; + case FAINTED_ACTIONS_HANDLE_NEXT_BATTLER: + if (++gBattleStruct->eventState.faintedActionBattler == gBattlersCount) + gBattleStruct->eventState.faintedAction = FAINTED_ACTIONS_MAX_CASE; else - gBattleStruct->faintedActionsState = 4; + gBattleStruct->eventState.faintedAction = FAINTED_ACTIONS_HANDLE_FAINTED_MON; break; case FAINTED_ACTIONS_MAX_CASE: break; } - } while (gBattleStruct->faintedActionsState != FAINTED_ACTIONS_MAX_CASE); + } while (gBattleStruct->eventState.faintedAction != FAINTED_ACTIONS_MAX_CASE); return FALSE; } @@ -1882,7 +1984,7 @@ static inline bool32 TryFormChangeBeforeMove(void) static inline bool32 TryActivatePowderStatus(u32 move) { - u32 partnerMove = gBattleMons[BATTLE_PARTNER(gBattlerAttacker)].moves[gBattleStruct->chosenMovePositions[BATTLE_PARTNER(gBattlerAttacker)]]; + u32 partnerMove = GetChosenMoveFromPosition(BATTLE_PARTNER(gBattlerAttacker)); if (!gBattleMons[gBattlerAttacker].volatiles.powder) return FALSE; if (GetBattleMoveType(move) == TYPE_FIRE && !gBattleStruct->pledgeMove) @@ -1894,61 +1996,54 @@ static inline bool32 TryActivatePowderStatus(u32 move) return FALSE; } -void SetAtkCancelerForCalledMove(void) +static enum MoveCanceler CancelerClearFlags(struct BattleContext *ctx) { - gBattleStruct->atkCancelerTracker = CANCELER_VOLATILE_BLOCKED; - gBattleStruct->isAtkCancelerForCalledMove = TRUE; -} - -static enum MoveCanceler CancelerFlags(void) -{ - gBattleMons[gBattlerAttacker].volatiles.destinyBond = FALSE; - gBattleMons[gBattlerAttacker].volatiles.grudge = FALSE; - gBattleMons[gBattlerAttacker].volatiles.glaiveRush = FALSE; + gBattleMons[ctx->battlerAtk].volatiles.grudge = FALSE; + gBattleMons[ctx->battlerAtk].volatiles.glaiveRush = FALSE; return MOVE_STEP_SUCCESS; } -static enum MoveCanceler CancelerStanceChangeOne(void) +static enum MoveCanceler CancelerStanceChangeOne(struct BattleContext *ctx) { - if (B_STANCE_CHANGE_FAIL < GEN_7 && TryFormChangeBeforeMove()) + if (B_STANCE_CHANGE_FAIL < GEN_7 && gChosenMove == ctx->currentMove && TryFormChangeBeforeMove()) return MOVE_STEP_BREAK; return MOVE_STEP_SUCCESS; } -static enum MoveCanceler CancelerSkyDrop(void) +static enum MoveCanceler CancelerSkyDrop(struct BattleContext *ctx) { // If Pokemon is being held in Sky Drop - if (gBattleMons[gBattlerAttacker].volatiles.semiInvulnerable == STATE_SKY_DROP) + if (gBattleMons[ctx->battlerAtk].volatiles.semiInvulnerable == STATE_SKY_DROP) { gBattlescriptCurrInstr = BattleScript_MoveEnd; gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; - return MOVE_STEP_BREAK; + return MOVE_STEP_FAILURE; } return MOVE_STEP_SUCCESS; } -static enum MoveCanceler CancelerRecharge(void) +static enum MoveCanceler CancelerRecharge(struct BattleContext *ctx) { - if (gDisableStructs[gBattlerAttacker].rechargeTimer > 0) + if (gDisableStructs[ctx->battlerAtk].rechargeTimer > 0) { - CancelMultiTurnMoves(gBattlerAttacker, SKY_DROP_ATTACKCANCELER_CHECK); + CancelMultiTurnMoves(ctx->battlerAtk, SKY_DROP_ATTACKCANCELER_CHECK); gBattlescriptCurrInstr = BattleScript_MoveUsedMustRecharge; gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; - return MOVE_STEP_BREAK; + return MOVE_STEP_FAILURE; } return MOVE_STEP_SUCCESS; } -static enum MoveCanceler CancelerAsleepOrFrozen(void) +static enum MoveCanceler CancelerAsleepOrFrozen(struct BattleContext *ctx) { - if (gBattleMons[gBattlerAttacker].status1 & STATUS1_SLEEP) + if (gBattleMons[ctx->battlerAtk].status1 & STATUS1_SLEEP) { - if (UproarWakeUpCheck(gBattlerAttacker)) + if (UproarWakeUpCheck(ctx->battlerAtk)) { - TryDeactivateSleepClause(GetBattlerSide(gBattlerAttacker), gBattlerPartyIndexes[gBattlerAttacker]); - gBattleMons[gBattlerAttacker].status1 &= ~STATUS1_SLEEP; - gBattleMons[gBattlerAttacker].volatiles.nightmare = FALSE; - gEffectBattler = gBattlerAttacker; + TryDeactivateSleepClause(GetBattlerSide(ctx->battlerAtk), gBattlerPartyIndexes[ctx->battlerAtk]); + gBattleMons[ctx->battlerAtk].status1 &= ~STATUS1_SLEEP; + gBattleMons[ctx->battlerAtk].volatiles.nightmare = FALSE; + gEffectBattler = ctx->battlerAtk; gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_WOKE_UP_UPROAR; BattleScriptCall(BattleScript_MoveUsedWokeUp); return MOVE_STEP_REMOVES_STATUS; @@ -1956,191 +2051,209 @@ static enum MoveCanceler CancelerAsleepOrFrozen(void) else { u8 toSub; - if (IsAbilityAndRecord(gBattlerAttacker, GetBattlerAbility(gBattlerAttacker), ABILITY_EARLY_BIRD)) + if (IsAbilityAndRecord(ctx->battlerAtk, ctx->abilities[ctx->battlerAtk], ABILITY_EARLY_BIRD)) toSub = 2; else toSub = 1; - if ((gBattleMons[gBattlerAttacker].status1 & STATUS1_SLEEP) < toSub) - gBattleMons[gBattlerAttacker].status1 &= ~STATUS1_SLEEP; + if ((gBattleMons[ctx->battlerAtk].status1 & STATUS1_SLEEP) < toSub) + gBattleMons[ctx->battlerAtk].status1 &= ~STATUS1_SLEEP; else - gBattleMons[gBattlerAttacker].status1 -= toSub; - if (gBattleMons[gBattlerAttacker].status1 & STATUS1_SLEEP) + gBattleMons[ctx->battlerAtk].status1 -= toSub; + + enum BattleMoveEffects moveEffect = GetMoveEffect(ctx->currentMove); + if (gBattleMons[ctx->battlerAtk].status1 & STATUS1_SLEEP) { - enum BattleMoveEffects moveEffect = GetMoveEffect(gChosenMove); if (moveEffect != EFFECT_SNORE && moveEffect != EFFECT_SLEEP_TALK) { - gProtectStructs[gBattlerAttacker].nonVolatileStatusImmobility = TRUE; + gProtectStructs[ctx->battlerAtk].nonVolatileStatusImmobility = TRUE; gBattlescriptCurrInstr = BattleScript_MoveUsedIsAsleep; gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; - return MOVE_STEP_REMOVES_STATUS; + return MOVE_STEP_FAILURE; } } else { - TryDeactivateSleepClause(GetBattlerSide(gBattlerAttacker), gBattlerPartyIndexes[gBattlerAttacker]); - gBattleMons[gBattlerAttacker].volatiles.nightmare = FALSE; + TryDeactivateSleepClause(GetBattlerSide(ctx->battlerAtk), gBattlerPartyIndexes[ctx->battlerAtk]); + gBattleMons[ctx->battlerAtk].volatiles.nightmare = FALSE; gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_WOKE_UP; BattleScriptCall(BattleScript_MoveUsedWokeUp); return MOVE_STEP_REMOVES_STATUS; } } } - else if (gBattleMons[gBattlerAttacker].status1 & STATUS1_FREEZE && !MoveThawsUser(gCurrentMove)) + else if (gBattleMons[ctx->battlerAtk].status1 & STATUS1_FREEZE && !MoveThawsUser(ctx->currentMove)) { if (!RandomPercentage(RNG_FROZEN, 20)) { - gProtectStructs[gBattlerAttacker].nonVolatileStatusImmobility = TRUE; + gProtectStructs[ctx->battlerAtk].nonVolatileStatusImmobility = TRUE; gBattlescriptCurrInstr = BattleScript_MoveUsedIsFrozen; - gHitMarker |= (HITMARKER_NO_ATTACKSTRING | HITMARKER_UNABLE_TO_USE_MOVE); + gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; } else // unfreeze { - gBattleMons[gBattlerAttacker].status1 &= ~STATUS1_FREEZE; + gBattleMons[ctx->battlerAtk].status1 &= ~STATUS1_FREEZE; BattleScriptCall(BattleScript_MoveUsedUnfroze); gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_DEFROSTED; } - return MOVE_STEP_REMOVES_STATUS; + return MOVE_STEP_REMOVES_STATUS; // Move failure but also removes status } return MOVE_STEP_SUCCESS; } -static enum MoveCanceler CancelerObedience(void) +static enum MoveCanceler CancelerObedience(struct BattleContext *ctx) { - enum Obedience obedienceResult = GetAttackerObedienceForAction(); - if (!(gHitMarker & HITMARKER_NO_PPDEDUCT) // Don't check obedience after first hit of multi target move or multi hit moves - && !gBattleMons[gBattlerAttacker].volatiles.multipleTurns) + if (!gBattleMons[ctx->battlerAtk].volatiles.multipleTurns) { + enum Obedience obedienceResult = GetAttackerObedienceForAction(); switch (obedienceResult) { case OBEYS: gHitMarker |= HITMARKER_OBEYS; - break; + return MOVE_STEP_SUCCESS; case DISOBEYS_LOAFS: // Randomly select, then print a disobedient string // B_MSG_LOAFING, B_MSG_WONT_OBEY, B_MSG_TURNED_AWAY, or B_MSG_PRETEND_NOT_NOTICE gBattleCommunication[MULTISTRING_CHOOSER] = MOD(Random(), NUM_LOAF_STRINGS); gBattlescriptCurrInstr = BattleScript_MoveUsedLoafingAround; - gBattleStruct->moveResultFlags[gBattlerTarget] |= MOVE_RESULT_MISSED; - break; + gBattleStruct->moveResultFlags[ctx->battlerDef] |= MOVE_RESULT_MISSED; + return MOVE_STEP_FAILURE; case DISOBEYS_HITS_SELF: - gBattlerTarget = gBattlerAttacker; - struct DamageContext ctx; - ctx.battlerAtk = ctx.battlerDef = gBattlerAttacker; - ctx.move = MOVE_NONE; - ctx.moveType = TYPE_MYSTERY; - ctx.isCrit = FALSE; - ctx.randomFactor = FALSE; - ctx.updateFlags = TRUE; - ctx.isSelfInflicted = TRUE; - ctx.fixedBasePower = 40; - gBattleStruct->moveDamage[gBattlerAttacker] = CalculateMoveDamage(&ctx); + gBattlerTarget = ctx->battlerAtk; + struct DamageContext dmgCtx = {0}; + dmgCtx.battlerAtk = dmgCtx.battlerDef = ctx->battlerAtk; + dmgCtx.move = dmgCtx.chosenMove = MOVE_NONE; + dmgCtx.moveType = TYPE_MYSTERY; + dmgCtx.isCrit = FALSE; + dmgCtx.randomFactor = FALSE; + dmgCtx.updateFlags = TRUE; + dmgCtx.isSelfInflicted = TRUE; + dmgCtx.fixedBasePower = 40; + gBattleStruct->moveDamage[ctx->battlerAtk] = CalculateMoveDamage(&dmgCtx); gBattlescriptCurrInstr = BattleScript_IgnoresAndHitsItself; gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; gHitMarker |= HITMARKER_OBEYS; - break; + return MOVE_STEP_FAILURE; // Move doesn't fail but mon hits itself case DISOBEYS_FALL_ASLEEP: if (IsSleepClauseEnabled()) - gBattleStruct->battlerState[gBattlerAttacker].sleepClauseEffectExempt = TRUE; + gBattleStruct->battlerState[ctx->battlerAtk].sleepClauseEffectExempt = TRUE; gBattlescriptCurrInstr = BattleScript_IgnoresAndFallsAsleep; - gBattleStruct->moveResultFlags[gBattlerTarget] |= MOVE_RESULT_MISSED; + gBattleStruct->moveResultFlags[ctx->battlerDef] |= MOVE_RESULT_MISSED; + return MOVE_STEP_FAILURE; break; case DISOBEYS_WHILE_ASLEEP: gBattlescriptCurrInstr = BattleScript_IgnoresWhileAsleep; - gBattleStruct->moveResultFlags[gBattlerTarget] |= MOVE_RESULT_MISSED; - break; + gBattleStruct->moveResultFlags[ctx->battlerDef] |= MOVE_RESULT_MISSED; + return MOVE_STEP_FAILURE; case DISOBEYS_RANDOM_MOVE: - gCalledMove = gBattleMons[gBattlerAttacker].moves[gCurrMovePos]; - SetAtkCancelerForCalledMove(); - gBattlescriptCurrInstr = BattleScript_IgnoresAndUsesRandomMove; + gCurrentMove = gCalledMove = gBattleMons[ctx->battlerAtk].moves[gCurrMovePos]; + BattleScriptCall(BattleScript_IgnoresAndUsesRandomMove); gBattlerTarget = GetBattleMoveTarget(gCalledMove, NO_TARGET_OVERRIDE); gHitMarker |= HITMARKER_OBEYS; - break; + return MOVE_STEP_BREAK; } - return MOVE_STEP_BREAK; } gHitMarker |= HITMARKER_OBEYS; return MOVE_STEP_SUCCESS; } -static enum MoveCanceler CancelerTruant(void) +static enum MoveCanceler CancelerPowerPoints(struct BattleContext *ctx) { - if (GetBattlerAbility(gBattlerAttacker) == ABILITY_TRUANT && gDisableStructs[gBattlerAttacker].truantCounter) + if (gBattleMons[ctx->battlerAtk].pp[gCurrMovePos] == 0 + && ctx->currentMove != MOVE_STRUGGLE + && !gSpecialStatuses[ctx->battlerAtk].dancerUsedMove + && !gBattleMons[ctx->battlerAtk].volatiles.multipleTurns) { - CancelMultiTurnMoves(gBattlerAttacker, SKY_DROP_ATTACKCANCELER_CHECK); + gBattlescriptCurrInstr = BattleScript_NoPPForMove; + gBattleStruct->moveResultFlags[ctx->battlerDef] |= MOVE_RESULT_MISSED; + return MOVE_STEP_FAILURE; + } + + return MOVE_STEP_SUCCESS; +} + +static enum MoveCanceler CancelerTruant(struct BattleContext *ctx) +{ + if (GetBattlerAbility(ctx->battlerAtk) == ABILITY_TRUANT && gDisableStructs[ctx->battlerAtk].truantCounter) + { + CancelMultiTurnMoves(ctx->battlerAtk, SKY_DROP_ATTACKCANCELER_CHECK); gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_LOAFING; - gBattlerAbility = gBattlerAttacker; + gBattlerAbility = ctx->battlerAtk; gBattlescriptCurrInstr = BattleScript_TruantLoafingAround; - gBattleStruct->moveResultFlags[gBattlerTarget] |= MOVE_RESULT_MISSED; - return MOVE_STEP_BREAK; + gBattleStruct->moveResultFlags[ctx->battlerDef] |= MOVE_RESULT_MISSED; + return MOVE_STEP_FAILURE; } return MOVE_STEP_SUCCESS; } -static enum MoveCanceler CancelerFlinch(void) +static enum MoveCanceler CancelerFlinch(struct BattleContext *ctx) { - if (gBattleMons[gBattlerAttacker].volatiles.flinched) + if (gBattleMons[ctx->battlerAtk].volatiles.flinched) { - gProtectStructs[gBattlerAttacker].unableToUseMove = TRUE; - CancelMultiTurnMoves(gBattlerAttacker, SKY_DROP_ATTACKCANCELER_CHECK); + gProtectStructs[ctx->battlerAtk].unableToUseMove = TRUE; + CancelMultiTurnMoves(ctx->battlerAtk, SKY_DROP_ATTACKCANCELER_CHECK); gBattlescriptCurrInstr = BattleScript_MoveUsedFlinched; gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; - return MOVE_STEP_BREAK; + return MOVE_STEP_FAILURE; } return MOVE_STEP_SUCCESS; } -static enum MoveCanceler CancelerDisabled(void) +static enum MoveCanceler CancelerDisabled(struct BattleContext *ctx) { - if (GetActiveGimmick(gBattlerAttacker) != GIMMICK_Z_MOVE && gDisableStructs[gBattlerAttacker].disabledMove == gCurrentMove && gDisableStructs[gBattlerAttacker].disabledMove != MOVE_NONE) + if (GetActiveGimmick(ctx->battlerAtk) != GIMMICK_Z_MOVE + && gDisableStructs[ctx->battlerAtk].disabledMove == ctx->currentMove + && gDisableStructs[ctx->battlerAtk].disabledMove != MOVE_NONE) { - gProtectStructs[gBattlerAttacker].unableToUseMove = TRUE; - gBattleScripting.battler = gBattlerAttacker; - CancelMultiTurnMoves(gBattlerAttacker, SKY_DROP_ATTACKCANCELER_CHECK); + gProtectStructs[ctx->battlerAtk].unableToUseMove = TRUE; + gBattleScripting.battler = ctx->battlerAtk; + CancelMultiTurnMoves(ctx->battlerAtk, SKY_DROP_ATTACKCANCELER_CHECK); gBattlescriptCurrInstr = BattleScript_MoveUsedIsDisabled; gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; - return MOVE_STEP_BREAK; + return MOVE_STEP_FAILURE; } return MOVE_STEP_SUCCESS; } -static enum MoveCanceler CancelerVolatileBlocked(void) +static enum MoveCanceler CancelerVolatileBlocked(struct BattleContext *ctx) { - if (GetActiveGimmick(gBattlerAttacker) != GIMMICK_Z_MOVE && gBattleMons[gBattlerAttacker].volatiles.healBlock && IsHealBlockPreventingMove(gBattlerAttacker, gCurrentMove)) + if (GetActiveGimmick(ctx->battlerAtk) != GIMMICK_Z_MOVE + && gBattleMons[ctx->battlerAtk].volatiles.healBlock + && IsHealBlockPreventingMove(ctx->battlerAtk, ctx->currentMove)) { - gProtectStructs[gBattlerAttacker].unableToUseMove = TRUE; - gBattleScripting.battler = gBattlerAttacker; - CancelMultiTurnMoves(gBattlerAttacker, SKY_DROP_ATTACKCANCELER_CHECK); + gProtectStructs[ctx->battlerAtk].unableToUseMove = TRUE; + gBattleScripting.battler = ctx->battlerAtk; + CancelMultiTurnMoves(ctx->battlerAtk, SKY_DROP_ATTACKCANCELER_CHECK); gBattlescriptCurrInstr = BattleScript_MoveUsedHealBlockPrevents; gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; - return MOVE_STEP_BREAK; + return MOVE_STEP_FAILURE; } - else if (gFieldStatuses & STATUS_FIELD_GRAVITY && IsGravityPreventingMove(gCurrentMove)) + else if (gFieldStatuses & STATUS_FIELD_GRAVITY && IsGravityPreventingMove(ctx->currentMove)) { - gProtectStructs[gBattlerAttacker].unableToUseMove = TRUE; - gBattleScripting.battler = gBattlerAttacker; - CancelMultiTurnMoves(gBattlerAttacker, SKY_DROP_ATTACKCANCELER_CHECK); + gProtectStructs[ctx->battlerAtk].unableToUseMove = TRUE; + gBattleScripting.battler = ctx->battlerAtk; + CancelMultiTurnMoves(ctx->battlerAtk, SKY_DROP_ATTACKCANCELER_CHECK); gBattlescriptCurrInstr = BattleScript_MoveUsedGravityPrevents; gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; - return MOVE_STEP_BREAK; + return MOVE_STEP_FAILURE; } - else if (GetActiveGimmick(gBattlerAttacker) != GIMMICK_Z_MOVE && gDisableStructs[gBattlerAttacker].throatChopTimer > gBattleTurnCounter && IsSoundMove(gCurrentMove)) + else if (GetActiveGimmick(ctx->battlerAtk) != GIMMICK_Z_MOVE && gDisableStructs[ctx->battlerAtk].throatChopTimer > 0 && IsSoundMove(ctx->currentMove)) { - gProtectStructs[gBattlerAttacker].unableToUseMove = TRUE; - CancelMultiTurnMoves(gBattlerAttacker, SKY_DROP_ATTACKCANCELER_CHECK); + gProtectStructs[ctx->battlerAtk].unableToUseMove = TRUE; + CancelMultiTurnMoves(ctx->battlerAtk, SKY_DROP_ATTACKCANCELER_CHECK); gBattlescriptCurrInstr = BattleScript_MoveUsedIsThroatChopPrevented; gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; - return MOVE_STEP_BREAK; + return MOVE_STEP_FAILURE; } return MOVE_STEP_SUCCESS; } -static enum MoveCanceler CancelerTaunted(void) +static enum MoveCanceler CancelerTaunted(struct BattleContext *ctx) { - if (GetActiveGimmick(gBattlerAttacker) != GIMMICK_Z_MOVE && gDisableStructs[gBattlerAttacker].tauntTimer && IsBattleMoveStatus(gCurrentMove)) + if (GetActiveGimmick(ctx->battlerAtk) != GIMMICK_Z_MOVE && gDisableStructs[ctx->battlerAtk].tauntTimer && IsBattleMoveStatus(ctx->currentMove)) { - gProtectStructs[gBattlerAttacker].unableToUseMove = TRUE; - CancelMultiTurnMoves(gBattlerAttacker, SKY_DROP_ATTACKCANCELER_CHECK); + gProtectStructs[ctx->battlerAtk].unableToUseMove = TRUE; + CancelMultiTurnMoves(ctx->battlerAtk, SKY_DROP_ATTACKCANCELER_CHECK); gBattlescriptCurrInstr = BattleScript_MoveUsedIsTaunted; gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; return MOVE_STEP_BREAK; @@ -2148,108 +2261,106 @@ static enum MoveCanceler CancelerTaunted(void) return MOVE_STEP_SUCCESS; } -static enum MoveCanceler CancelerImprisoned(void) +static enum MoveCanceler CancelerImprisoned(struct BattleContext *ctx) { - if (GetActiveGimmick(gBattlerAttacker) != GIMMICK_Z_MOVE && GetImprisonedMovesCount(gBattlerAttacker, gCurrentMove)) + if (GetActiveGimmick(ctx->battlerAtk) != GIMMICK_Z_MOVE && GetImprisonedMovesCount(ctx->battlerAtk, ctx->currentMove)) { - gProtectStructs[gBattlerAttacker].unableToUseMove = TRUE; - CancelMultiTurnMoves(gBattlerAttacker, SKY_DROP_ATTACKCANCELER_CHECK); + gProtectStructs[ctx->battlerAtk].unableToUseMove = TRUE; + CancelMultiTurnMoves(ctx->battlerAtk, SKY_DROP_ATTACKCANCELER_CHECK); gBattlescriptCurrInstr = BattleScript_MoveUsedIsImprisoned; gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; - return MOVE_STEP_BREAK; + return MOVE_STEP_FAILURE; } return MOVE_STEP_SUCCESS; } -static enum MoveCanceler CancelerConfused(void) +static enum MoveCanceler CancelerConfused(struct BattleContext *ctx) { - if (gBattleStruct->isAtkCancelerForCalledMove) - return MOVE_STEP_SUCCESS; - - if (gBattleMons[gBattlerAttacker].volatiles.confusionTurns) + if (gBattleMons[ctx->battlerAtk].volatiles.confusionTurns) { - if (!gBattleMons[gBattlerAttacker].volatiles.infiniteConfusion) - gBattleMons[gBattlerAttacker].volatiles.confusionTurns--; - if (gBattleMons[gBattlerAttacker].volatiles.confusionTurns) + if (!gBattleMons[ctx->battlerAtk].volatiles.infiniteConfusion) + gBattleMons[ctx->battlerAtk].volatiles.confusionTurns--; + if (gBattleMons[ctx->battlerAtk].volatiles.confusionTurns) { // confusion dmg - if (RandomPercentage(RNG_CONFUSION, (GetGenConfig(GEN_CONFIG_CONFUSION_SELF_DMG_CHANCE) >= GEN_7 ? 33 : 50))) + if (RandomPercentage(RNG_CONFUSION, (GetConfig(CONFIG_CONFUSION_SELF_DMG_CHANCE) >= GEN_7 ? 33 : 50))) { gBattleCommunication[MULTISTRING_CHOOSER] = TRUE; - gBattlerTarget = gBattlerAttacker; - struct DamageContext ctx; - ctx.battlerAtk = ctx.battlerDef = gBattlerAttacker; - ctx.move = MOVE_NONE; - ctx.moveType = TYPE_MYSTERY; - ctx.isCrit = FALSE; - ctx.randomFactor = FALSE; - ctx.updateFlags = TRUE; - ctx.isSelfInflicted = TRUE; - ctx.fixedBasePower = 40; - gBattleStruct->moveDamage[gBattlerAttacker] = CalculateMoveDamage(&ctx); - gProtectStructs[gBattlerAttacker].confusionSelfDmg = TRUE; + struct DamageContext dmgCtx = {0}; + dmgCtx.battlerAtk = dmgCtx.battlerDef = ctx->battlerAtk; + dmgCtx.move = dmgCtx.chosenMove = MOVE_NONE; + dmgCtx.moveType = TYPE_MYSTERY; + dmgCtx.isCrit = FALSE; + dmgCtx.randomFactor = FALSE; + dmgCtx.updateFlags = TRUE; + dmgCtx.isSelfInflicted = TRUE; + dmgCtx.fixedBasePower = 40; + gBattleStruct->passiveHpUpdate[ctx->battlerAtk] = CalculateMoveDamage(&dmgCtx); + gProtectStructs[ctx->battlerAtk].confusionSelfDmg = TRUE; gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; gBattlescriptCurrInstr = BattleScript_MoveUsedIsConfused; + return MOVE_STEP_FAILURE; } else { gBattleCommunication[MULTISTRING_CHOOSER] = FALSE; BattleScriptCall(BattleScript_MoveUsedIsConfused); + return MOVE_STEP_BREAK; } } else // snapped out of confusion { BattleScriptCall(BattleScript_MoveUsedIsConfusedNoMore); + return MOVE_STEP_BREAK; } - return MOVE_STEP_BREAK; } return MOVE_STEP_SUCCESS; } -static enum MoveCanceler CancelerParalysed(void) +static enum MoveCanceler CancelerParalyzed(struct BattleContext *ctx) { - if (!gBattleStruct->isAtkCancelerForCalledMove - && (gBattleMons[gBattlerAttacker].status1 & STATUS1_PARALYSIS) - && !(B_MAGIC_GUARD == GEN_4 && IsAbilityAndRecord(gBattlerAttacker, GetBattlerAbility(gBattlerAttacker), ABILITY_MAGIC_GUARD)) + if (gBattleMons[ctx->battlerAtk].status1 & STATUS1_PARALYSIS + && !(B_MAGIC_GUARD == GEN_4 && IsAbilityAndRecord(ctx->battlerAtk, ctx->abilities[ctx->battlerAtk], ABILITY_MAGIC_GUARD)) && !RandomPercentage(RNG_PARALYSIS, 75)) { - gProtectStructs[gBattlerAttacker].nonVolatileStatusImmobility = TRUE; + gProtectStructs[ctx->battlerAtk].nonVolatileStatusImmobility = TRUE; // This is removed in FRLG and Emerald for some reason //CancelMultiTurnMoves(gBattlerAttacker, SKY_DROP_ATTACKCANCELER_CHECK); gBattlescriptCurrInstr = BattleScript_MoveUsedIsParalyzed; gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; - return MOVE_STEP_BREAK; + return MOVE_STEP_FAILURE; } return MOVE_STEP_SUCCESS; } -static enum MoveCanceler CancelerInfatuation(void) +static enum MoveCanceler CancelerInfatuation(struct BattleContext *ctx) { - if (!gBattleStruct->isAtkCancelerForCalledMove && gBattleMons[gBattlerAttacker].volatiles.infatuation) + if (gBattleMons[ctx->battlerAtk].volatiles.infatuation) { - gBattleScripting.battler = gBattleMons[gBattlerAttacker].volatiles.infatuation - 1; + gBattleScripting.battler = gBattleMons[ctx->battlerAtk].volatiles.infatuation - 1; if (!RandomPercentage(RNG_INFATUATION, 50)) { BattleScriptCall(BattleScript_MoveUsedIsInLove); + return MOVE_STEP_BREAK; } else { BattleScriptPush(BattleScript_MoveUsedIsInLoveCantAttack); gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; - gProtectStructs[gBattlerAttacker].unableToUseMove = TRUE; - CancelMultiTurnMoves(gBattlerAttacker, SKY_DROP_ATTACKCANCELER_CHECK); + gProtectStructs[ctx->battlerAtk].unableToUseMove = TRUE; + CancelMultiTurnMoves(ctx->battlerAtk, SKY_DROP_ATTACKCANCELER_CHECK); gBattlescriptCurrInstr = BattleScript_MoveUsedIsInLove; + return MOVE_STEP_FAILURE; } - return MOVE_STEP_BREAK; } return MOVE_STEP_SUCCESS; } -static enum MoveCanceler CancelerBide(void) +static enum MoveCanceler CancelerBide(struct BattleContext *ctx) { - if (gBattleMons[gBattlerAttacker].volatiles.bideTurns) + if (gBattleMons[ctx->battlerAtk].volatiles.bideTurns) { - if (--gBattleMons[gBattlerAttacker].volatiles.bideTurns) + if (--gBattleMons[ctx->battlerAtk].volatiles.bideTurns) { gBattlescriptCurrInstr = BattleScript_BideStoringEnergy; } @@ -2257,70 +2368,58 @@ static enum MoveCanceler CancelerBide(void) { // This is removed in FRLG and Emerald for some reason //gBattleMons[gBattlerAttacker].volatiles.multipleTurns = FALSE; - if (gBideDmg[gBattlerAttacker]) + if (gBideDmg[ctx->battlerAtk]) { gCurrentMove = MOVE_BIDE; - gBattlerTarget = gBideTarget[gBattlerAttacker]; - if (gAbsentBattlerFlags & (1u << gBattlerTarget)) + gBattlerTarget = gBideTarget[ctx->battlerAtk]; + if (gAbsentBattlerFlags & (1u << ctx->battlerDef)) gBattlerTarget = GetBattleMoveTarget(MOVE_BIDE, MOVE_TARGET_SELECTED + 1); gBattlescriptCurrInstr = BattleScript_BideAttack; + return MOVE_STEP_BREAK; // Jumps to a different script but no failure } else { gBattlescriptCurrInstr = BattleScript_BideNoEnergyToAttack; + return MOVE_STEP_FAILURE; } } + } + return MOVE_STEP_SUCCESS; +} + +static enum MoveCanceler CancelerZMoves(struct BattleContext *ctx) +{ + if (GetActiveGimmick(ctx->battlerAtk) == GIMMICK_Z_MOVE) + { + // attacker has a queued z move + RecordItemEffectBattle(ctx->battlerAtk, HOLD_EFFECT_Z_CRYSTAL); + SetGimmickAsActivated(ctx->battlerAtk, GIMMICK_Z_MOVE); + + gBattleScripting.battler = ctx->battlerAtk; + if (GetMoveCategory(ctx->currentMove) == DAMAGE_CATEGORY_STATUS) + BattleScriptCall(BattleScript_ZMoveActivateStatus); + else + BattleScriptCall(BattleScript_ZMoveActivateDamaging); + return MOVE_STEP_BREAK; } return MOVE_STEP_SUCCESS; } -static enum MoveCanceler CancelerThaw(void) +static enum MoveCanceler CancelerChoiceLock(struct BattleContext *ctx) { - if (gBattleMons[gBattlerAttacker].status1 & STATUS1_FREEZE) - { - if (!(IsMoveEffectRemoveSpeciesType(gCurrentMove, MOVE_EFFECT_REMOVE_ARG_TYPE, TYPE_FIRE) && !IS_BATTLER_OF_TYPE(gBattlerAttacker, TYPE_FIRE))) - { - gBattleMons[gBattlerAttacker].status1 &= ~STATUS1_FREEZE; - BattleScriptCall(BattleScript_MoveUsedUnfroze); - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_DEFROSTED_BY_MOVE; - } - return MOVE_STEP_REMOVES_STATUS; - } - if (gBattleMons[gBattlerAttacker].status1 & STATUS1_FROSTBITE && MoveThawsUser(gCurrentMove)) - { - if (!(IsMoveEffectRemoveSpeciesType(gCurrentMove, MOVE_EFFECT_REMOVE_ARG_TYPE, TYPE_FIRE) && !IS_BATTLER_OF_TYPE(gBattlerAttacker, TYPE_FIRE))) - { - gBattleMons[gBattlerAttacker].status1 &= ~STATUS1_FROSTBITE; - BattleScriptCall(BattleScript_MoveUsedUnfrostbite); - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_FROSTBITE_HEALED_BY_MOVE; - } - return MOVE_STEP_REMOVES_STATUS; - } - return MOVE_STEP_SUCCESS; -} - -static enum MoveCanceler CancelerStanceChangeTwo(void) -{ - if (B_STANCE_CHANGE_FAIL >= GEN_7 && !gBattleStruct->isAtkCancelerForCalledMove && TryFormChangeBeforeMove()) - return MOVE_STEP_BREAK; - return MOVE_STEP_SUCCESS; -} - -static enum MoveCanceler CancelerChoiceLock(void) -{ - u16 *choicedMoveAtk = &gBattleStruct->choicedMove[gBattlerAttacker]; - enum ItemHoldEffect holdEffect = GetBattlerHoldEffect(gBattlerAttacker, TRUE); + u16 *choicedMoveAtk = &gBattleStruct->choicedMove[ctx->battlerAtk]; + enum HoldEffect holdEffect = GetBattlerHoldEffect(ctx->battlerAtk); if (gChosenMove != MOVE_STRUGGLE && (*choicedMoveAtk == MOVE_NONE || *choicedMoveAtk == MOVE_UNAVAILABLE) - && (IsHoldEffectChoice(holdEffect) || GetBattlerAbility(gBattlerAttacker) == ABILITY_GORILLA_TACTICS)) + && (IsHoldEffectChoice(holdEffect) || ctx->abilities[ctx->battlerAtk] == ABILITY_GORILLA_TACTICS)) *choicedMoveAtk = gChosenMove; u32 moveIndex; for (moveIndex = 0; moveIndex < MAX_MON_MOVES; moveIndex++) { - if (gBattleMons[gBattlerAttacker].moves[moveIndex] == *choicedMoveAtk) + if (gBattleMons[ctx->battlerAtk].moves[moveIndex] == *choicedMoveAtk) break; } @@ -2330,72 +2429,435 @@ static enum MoveCanceler CancelerChoiceLock(void) return MOVE_STEP_SUCCESS; } -static enum MoveCanceler CancelerWeatherPrimal(void) +static enum MoveCanceler CancelerCallSubmove(struct BattleContext *ctx) +{ + bool32 noEffect = FALSE; + u32 calledMove = MOVE_NONE; + const u8 *battleScript = NULL; + battleScript = BattleScript_SubmoveAttackstring; + + switch(GetMoveEffect(ctx->currentMove)) + { + case EFFECT_MIRROR_MOVE: + calledMove = GetMirrorMoveMove(); + break; + case EFFECT_METRONOME: + calledMove = GetMetronomeMove(); + battleScript = BattleScript_MetronomeAttackstring; + break; + case EFFECT_ASSIST: + calledMove = GetAssistMove(); + break; + case EFFECT_NATURE_POWER: + calledMove = GetNaturePowerMove(ctx->battlerAtk); + battleScript = BattleScript_NaturePowerAttackstring; + break; + case EFFECT_SLEEP_TALK: + calledMove = GetSleepTalkMove(); + battleScript = BattleScript_SleepTalkAttackstring; + break; + case EFFECT_COPYCAT: + calledMove = GetCopyCatMove(); + break; + case EFFECT_ME_FIRST: + calledMove = GetMeFirstMove(); + break; + default: + noEffect = TRUE; + break; + } + + if (noEffect) + { + gBattleStruct->submoveAnnouncement = SUBMOVE_NO_EFFECT; + return MOVE_STEP_SUCCESS; + } + + if (calledMove != MOVE_NONE) + { + if (GetActiveGimmick(ctx->battlerAtk) == GIMMICK_Z_MOVE && !IsBattleMoveStatus(calledMove)) + calledMove = GetTypeBasedZMove(calledMove); + if (GetMoveEffect(ctx->currentMove) == EFFECT_COPYCAT && IsMaxMove(calledMove)) + calledMove = gBattleStruct->dynamax.lastUsedBaseMove; + + gBattleStruct->submoveAnnouncement = SUBMOVE_SUCCESS; + gCalledMove = calledMove; + BattleScriptCall(battleScript); + return MOVE_STEP_BREAK; + } + + gBattleStruct->submoveAnnouncement = SUBMOVE_FAILURE; + return MOVE_STEP_SUCCESS; +} + +static enum MoveCanceler CancelerThaw(struct BattleContext *ctx) +{ + if (gBattleMons[ctx->battlerAtk].status1 & STATUS1_FREEZE) + { + if (!(IsMoveEffectRemoveSpeciesType(ctx->currentMove, MOVE_EFFECT_REMOVE_ARG_TYPE, TYPE_FIRE) && !IS_BATTLER_OF_TYPE(ctx->battlerAtk, TYPE_FIRE))) + { + gBattleMons[ctx->battlerAtk].status1 &= ~STATUS1_FREEZE; + BattleScriptCall(BattleScript_MoveUsedUnfroze); + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_DEFROSTED_BY_MOVE; + } + return MOVE_STEP_REMOVES_STATUS; + } + if (gBattleMons[ctx->battlerAtk].status1 & STATUS1_FROSTBITE && MoveThawsUser(ctx->currentMove)) + { + if (!(IsMoveEffectRemoveSpeciesType(ctx->currentMove, MOVE_EFFECT_REMOVE_ARG_TYPE, TYPE_FIRE) && !IS_BATTLER_OF_TYPE(ctx->battlerAtk, TYPE_FIRE))) + { + gBattleMons[ctx->battlerAtk].status1 &= ~STATUS1_FROSTBITE; + BattleScriptCall(BattleScript_MoveUsedUnfrostbite); + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_FROSTBITE_HEALED_BY_MOVE; + } + return MOVE_STEP_REMOVES_STATUS; + } + return MOVE_STEP_SUCCESS; +} + +static enum MoveCanceler CancelerStanceChangeTwo(struct BattleContext *ctx) +{ + if (B_STANCE_CHANGE_FAIL >= GEN_7 && gChosenMove == ctx->currentMove && TryFormChangeBeforeMove()) + return MOVE_STEP_BREAK; + return MOVE_STEP_SUCCESS; +} + +static enum MoveCanceler CancelerAttackstring(struct BattleContext *ctx) +{ + BattleScriptCall(BattleScript_Attackstring); + if (!gSpecialStatuses[gBattlerAttacker].dancerUsedMove) + gLastPrintedMoves[gBattlerAttacker] = gChosenMove; + return MOVE_STEP_BREAK; +} + +static enum MoveCanceler CancelerPPDeduction(struct BattleContext *ctx) +{ + if (gBattleMons[ctx->battlerAtk].volatiles.multipleTurns + || gSpecialStatuses[ctx->battlerAtk].dancerUsedMove + || ctx->currentMove == MOVE_STRUGGLE) + return MOVE_STEP_SUCCESS; + + s32 ppToDeduct = 1; + u32 moveTarget = GetBattlerMoveTargetType(ctx->battlerAtk, ctx->currentMove); + u32 movePosition = gCurrMovePos; + + if (gBattleStruct->submoveAnnouncement == SUBMOVE_SUCCESS) + movePosition = gChosenMovePos; + + if (moveTarget == MOVE_TARGET_BOTH + || moveTarget == MOVE_TARGET_FOES_AND_ALLY + || moveTarget == MOVE_TARGET_ALL_BATTLERS + || MoveForcesPressure(ctx->currentMove)) + { + for (u32 i = 0; i < gBattlersCount; i++) + { + if (!IsBattlerAlly(i, ctx->battlerAtk) && IsBattlerAlive(i)) + ppToDeduct += (GetBattlerAbility(i) == ABILITY_PRESSURE); + } + } + else if (moveTarget != MOVE_TARGET_OPPONENTS_FIELD) + { + if (ctx->battlerAtk != ctx->battlerDef && ctx->abilities[ctx->battlerDef] == ABILITY_PRESSURE) + ppToDeduct++; + } + + // For item Metronome, echoed voice + if (ctx->currentMove != gLastResultingMoves[ctx->battlerAtk] || WasUnableToUseMove(ctx->battlerAtk)) + gBattleStruct->metronomeItemCounter[ctx->battlerAtk] = 0; + + if (gBattleMons[ctx->battlerAtk].pp[movePosition] > ppToDeduct) + gBattleMons[ctx->battlerAtk].pp[movePosition] -= ppToDeduct; + else + gBattleMons[ctx->battlerAtk].pp[movePosition] = 0; + + if (MOVE_IS_PERMANENT(ctx->battlerAtk, movePosition)) + { + BtlController_EmitSetMonData( + ctx->battlerAtk, + B_COMM_TO_CONTROLLER, + REQUEST_PPMOVE1_BATTLE + movePosition, + 0, + sizeof(gBattleMons[ctx->battlerAtk].pp[movePosition]), + &gBattleMons[ctx->battlerAtk].pp[movePosition]); + MarkBattlerForControllerExec(ctx->battlerAtk); + } + + if (gBattleStruct->submoveAnnouncement != SUBMOVE_NO_EFFECT) + { + if (gBattleStruct->submoveAnnouncement == SUBMOVE_FAILURE) + { + gBattleStruct->submoveAnnouncement = SUBMOVE_NO_EFFECT; + gBattlescriptCurrInstr = BattleScript_ButItFailed; + return MOVE_STEP_FAILURE; + } + else if (CancelerVolatileBlocked(ctx) == MOVE_STEP_FAILURE) // Check Gravity/Heal Block/Throat Chop for Submove + { + gBattleStruct->submoveAnnouncement = SUBMOVE_NO_EFFECT; + return MOVE_STEP_FAILURE; + } + else + { + gBattleStruct->submoveAnnouncement = SUBMOVE_NO_EFFECT; + gBattlerTarget = GetBattleMoveTarget(ctx->currentMove, NO_TARGET_OVERRIDE); + gBattleScripting.animTurn = 0; + gBattleScripting.animTargetsHit = 0; + + // Possibly better to just move type setting and redirection to attackcanceler as a new case at this point + SetTypeBeforeUsingMove(ctx->currentMove, ctx->battlerAtk); + HandleMoveTargetRedirection(); + ClearDamageCalcResults(); + gBattlescriptCurrInstr = GetMoveBattleScript(ctx->currentMove); + return MOVE_STEP_BREAK; + } + } + + return MOVE_STEP_SUCCESS; +} + +static enum MoveCanceler CancelerWeatherPrimal(struct BattleContext *ctx) { enum MoveCanceler effect = MOVE_STEP_SUCCESS; - if (HasWeatherEffect() && GetMovePower(gCurrentMove) > 0) + if (HasWeatherEffect() && GetMovePower(ctx->currentMove) > 0) { - u32 moveType = GetBattleMoveType(gCurrentMove); - if (moveType == TYPE_FIRE && (gBattleWeather & B_WEATHER_RAIN_PRIMAL) && (GetGenConfig(GEN_CONFIG_POWDER_RAIN) >= GEN_7 || !TryActivatePowderStatus(gCurrentMove))) + enum Type moveType = GetBattleMoveType(ctx->currentMove); + if (moveType == TYPE_FIRE && (gBattleWeather & B_WEATHER_RAIN_PRIMAL) && (GetConfig(CONFIG_POWDER_RAIN) >= GEN_7 || !TryActivatePowderStatus(ctx->currentMove))) { gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_PRIMAL_WEATHER_FIZZLED_BY_RAIN; - effect = MOVE_STEP_BREAK; + effect = MOVE_STEP_FAILURE; } else if (moveType == TYPE_WATER && (gBattleWeather & B_WEATHER_SUN_PRIMAL)) { gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_PRIMAL_WEATHER_EVAPORATED_IN_SUN; - effect = MOVE_STEP_BREAK; + effect = MOVE_STEP_FAILURE; } - if (effect == MOVE_STEP_BREAK) + if (effect == MOVE_STEP_FAILURE) { - gBattleScripting.moveEffect = MOVE_EFFECT_NONE; - gProtectStructs[gBattlerAttacker].chargingTurn = FALSE; - CancelMultiTurnMoves(gBattlerAttacker, SKY_DROP_ATTACKCANCELER_CHECK); + gProtectStructs[ctx->battlerAtk].chargingTurn = FALSE; + CancelMultiTurnMoves(ctx->battlerAtk, SKY_DROP_ATTACKCANCELER_CHECK); gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; - BattleScriptCall(BattleScript_PrimalWeatherBlocksMove); + gBattlescriptCurrInstr = BattleScript_PrimalWeatherBlocksMove; } } return effect; } -static enum MoveCanceler CancelerDynamaxBlocked(void) +static enum MoveCanceler CancelerMoveFailure(struct BattleContext *ctx) { - if ((GetActiveGimmick(gBattlerTarget) == GIMMICK_DYNAMAX) && IsMoveBlockedByDynamax(gCurrentMove)) + const u8 *battleScript = NULL; + + switch (GetMoveEffect(ctx->currentMove)) + { + case EFFECT_FAIL_IF_NOT_ARG_TYPE: + if (!IS_BATTLER_OF_TYPE(ctx->battlerAtk, GetMoveArgType(ctx->currentMove))) + battleScript = BattleScript_ButItFailed; + break; + case EFFECT_AURA_WHEEL: + if (gBattleMons[ctx->battlerAtk].species != SPECIES_MORPEKO_FULL_BELLY + && gBattleMons[ctx->battlerAtk].species != SPECIES_MORPEKO_HANGRY) + battleScript = BattleScript_PokemonCantUseTheMove; + break; + case EFFECT_AURORA_VEIL: + if (!(gBattleWeather & (B_WEATHER_HAIL | B_WEATHER_SNOW) && HasWeatherEffect())) + battleScript = BattleScript_ButItFailed; + break; + case EFFECT_CLANGOROUS_SOUL: + if (gBattleMons[ctx->battlerAtk].hp <= max(1, GetNonDynamaxMaxHP(ctx->battlerAtk) / 3)) + battleScript = BattleScript_ButItFailed; + break; + case EFFECT_COUNTER: + case EFFECT_MIRROR_COAT: + case EFFECT_METAL_BURST: + // TODO: Needs a refactor because the moves currently don't work according to new gens + break; + case EFFECT_DESTINY_BOND: + if (DoesDestinyBondFail(ctx->battlerAtk)) + battleScript = BattleScript_ButItFailed; + break; + case EFFECT_FIRST_TURN_ONLY: + if (!gDisableStructs[ctx->battlerAtk].isFirstTurn || gSpecialStatuses[ctx->battlerAtk].instructedChosenTarget) + battleScript = BattleScript_ButItFailed; + break; + case EFFECT_MAT_BLOCK: + if (!gDisableStructs[ctx->battlerAtk].isFirstTurn || gSpecialStatuses[ctx->battlerAtk].instructedChosenTarget) + battleScript = BattleScript_ButItFailed; + break; + case EFFECT_FLING: + if (!CanFling(ctx->battlerAtk)) + battleScript = BattleScript_ButItFailed; + break; + case EFFECT_FOLLOW_ME: + if (B_UPDATED_MOVE_DATA >= GEN_8 && !(gBattleTypeFlags & BATTLE_TYPE_DOUBLE)) + battleScript = BattleScript_ButItFailed; + break; + case EFFECT_FUTURE_SIGHT: + if (gWishFutureKnock.futureSightCounter[ctx->battlerDef] > 0) + battleScript = BattleScript_ButItFailed; + break; + case EFFECT_LAST_RESORT: + if (!CanUseLastResort(ctx->battlerAtk)) + battleScript = BattleScript_ButItFailed; + break; + case EFFECT_NO_RETREAT: + if (gBattleMons[ctx->battlerDef].volatiles.noRetreat) + battleScript = BattleScript_ButItFailed; + break; + case EFFECT_POLTERGEIST: + if (gBattleMons[ctx->battlerDef].item == ITEM_NONE + || gFieldStatuses & STATUS_FIELD_MAGIC_ROOM + || ctx->abilities[ctx->battlerDef] == ABILITY_KLUTZ) + battleScript = BattleScript_ButItFailed; + break; + case EFFECT_PROTECT: + // TODO + break; + case EFFECT_REST: + if (gBattleMons[ctx->battlerAtk].status1 & STATUS1_SLEEP + || ctx->abilities[ctx->battlerAtk] == ABILITY_COMATOSE) + battleScript = BattleScript_RestIsAlreadyAsleep; + else if (gBattleMons[ctx->battlerAtk].hp == gBattleMons[ctx->battlerAtk].maxHP) + battleScript = BattleScript_AlreadyAtFullHp; + else if (ctx->abilities[ctx->battlerAtk] == ABILITY_INSOMNIA + || ctx->abilities[ctx->battlerAtk] == ABILITY_VITAL_SPIRIT + || ctx->abilities[ctx->battlerAtk] == ABILITY_PURIFYING_SALT) + battleScript = BattleScript_InsomniaProtects; + break; + case EFFECT_SUCKER_PUNCH: + if (HasBattlerActedThisTurn(ctx->battlerDef) + || (IsBattleMoveStatus(GetChosenMoveFromPosition(ctx->battlerDef)) && !gProtectStructs[ctx->battlerDef].noValidMoves)) + battleScript = BattleScript_ButItFailed; + break; + case EFFECT_UPPER_HAND: + { + u32 prio = GetChosenMovePriority(ctx->battlerDef, ctx->abilities[ctx->battlerDef]); + if (prio < 1 || prio > 3 // Fails if priority is less than 1 or greater than 3, if target already moved, or if using a status + || HasBattlerActedThisTurn(ctx->battlerDef) + || gChosenMoveByBattler[ctx->battlerDef] == MOVE_NONE + || IsBattleMoveStatus(gChosenMoveByBattler[ctx->battlerDef])) + battleScript = BattleScript_ButItFailed; + break; + } + case EFFECT_SNORE: + if (!(gBattleMons[ctx->battlerAtk].status1 & STATUS1_SLEEP) + && ctx->abilities[ctx->battlerAtk] != ABILITY_COMATOSE) + battleScript = BattleScript_ButItFailed; + break; + case EFFECT_STEEL_ROLLER: + if (!(gFieldStatuses & STATUS_FIELD_TERRAIN_ANY)) + battleScript = BattleScript_ButItFailed; + break; + case EFFECT_STOCKPILE: + if (gDisableStructs[ctx->battlerAtk].stockpileCounter >= 3) + battleScript = BattleScript_ButItFailed; + break; + case EFFECT_STUFF_CHEEKS: + if (GetItemPocket(gBattleMons[ctx->battlerAtk].item) != POCKET_BERRIES) + battleScript = BattleScript_ButItFailed; + break; + case EFFECT_SWALLOW: + case EFFECT_SPIT_UP: + if (gDisableStructs[ctx->battlerAtk].stockpileCounter == 0 && !gBattleStruct->snatchedMoveIsUsed) + battleScript = BattleScript_ButItFailed; + break; + case EFFECT_TELEPORT: + // TODO: follow up: Can't make sense of teleport logic + break; + case EFFECT_LOW_KICK: + case EFFECT_HEAT_CRASH: + if (GetActiveGimmick(ctx->battlerDef) == GIMMICK_DYNAMAX) + battleScript = BattleScript_MoveBlockedByDynamax; + break; + default: + break; + } + + if (battleScript != NULL) { gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; - BattleScriptCall(BattleScript_MoveBlockedByDynamax); - return MOVE_STEP_BREAK; + gBattlescriptCurrInstr = battleScript; + return MOVE_STEP_FAILURE; } + return MOVE_STEP_SUCCESS; } -static enum MoveCanceler CancelerPowderStatus(void) +static enum MoveCanceler CancelerPowderStatus(struct BattleContext *ctx) { - if (TryActivatePowderStatus(gCurrentMove)) + if (TryActivatePowderStatus(ctx->currentMove)) { - gProtectStructs[gBattlerAttacker].powderSelfDmg = TRUE; - if (!IsAbilityAndRecord(gBattlerAttacker, GetBattlerAbility(gBattlerAttacker), ABILITY_MAGIC_GUARD)) - gBattleStruct->moveDamage[gBattlerAttacker] = GetNonDynamaxMaxHP(gBattlerAttacker) / 4; + if (!IsAbilityAndRecord(ctx->battlerAtk, ctx->abilities[ctx->battlerAtk], ABILITY_MAGIC_GUARD)) + SetPassiveDamageAmount(ctx->battlerAtk, GetNonDynamaxMaxHP(ctx->battlerAtk) / 4); - if (GetActiveGimmick(gBattlerAttacker) != GIMMICK_Z_MOVE - || HasTrainerUsedGimmick(gBattlerAttacker, GIMMICK_Z_MOVE)) + // This might be incorrect + if (GetActiveGimmick(ctx->battlerAtk) != GIMMICK_Z_MOVE + || HasTrainerUsedGimmick(ctx->battlerAtk, GIMMICK_Z_MOVE)) gBattlescriptCurrInstr = BattleScript_MoveUsedPowder; gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; - return MOVE_STEP_BREAK; + return MOVE_STEP_FAILURE; } return MOVE_STEP_SUCCESS; } -static enum MoveCanceler CancelerProtean(void) +bool32 IsDazzlingAbility(enum Ability ability) { - u32 moveType = GetBattleMoveType(gCurrentMove); - if (ProteanTryChangeType(gBattlerAttacker, GetBattlerAbility(gBattlerAttacker), gCurrentMove, moveType)) + switch (ability) { - if (GetGenConfig(GEN_PROTEAN_LIBERO) >= GEN_9) - gDisableStructs[gBattlerAttacker].usedProteanLibero = TRUE; + case ABILITY_DAZZLING: return TRUE; + case ABILITY_QUEENLY_MAJESTY: return TRUE; + case ABILITY_ARMOR_TAIL: return TRUE; + default: break; + } + return FALSE; +} + +static enum MoveCanceler CancelerPriorityBlock(struct BattleContext *ctx) +{ + bool32 effect = FALSE; + s32 priority = GetChosenMovePriority(ctx->battlerAtk, ctx->abilities[ctx->battlerAtk]); + u32 blockAbility = ABILITY_NONE; // ability of battler who is blocking + u32 blockedByBattler = ctx->battlerDef; + + if (priority <= 0 || IsBattlerAlly(ctx->battlerAtk, ctx->battlerDef)) + return MOVE_STEP_SUCCESS; + + if (IsDazzlingAbility(ctx->abilities[ctx->battlerDef])) + { + blockAbility = ctx->abilities[ctx->battlerDef]; + effect = TRUE; + } + else if (IsDoubleBattle() && IsBattlerAlive(BATTLE_PARTNER(ctx->battlerDef))) + { + blockAbility = GetBattlerAbility(BATTLE_PARTNER(ctx->battlerDef)); + if (IsDazzlingAbility(blockAbility)) + { + blockedByBattler = BATTLE_PARTNER(ctx->battlerDef); + effect = TRUE; + } + } + + if (effect) + { + gMultiHitCounter = 0; // Prevent multi-hit moves from hitting more than once after move has been absorbed. + gLastUsedAbility = blockAbility; + RecordAbilityBattle(blockedByBattler, blockAbility); + gBattleScripting.battler = gBattlerAbility = blockedByBattler; + gBattlescriptCurrInstr = BattleScript_DazzlingProtected; + gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; + return MOVE_STEP_FAILURE; + } + + return MOVE_STEP_SUCCESS; +} + +static enum MoveCanceler CancelerProtean(struct BattleContext *ctx) +{ + enum Type moveType = GetBattleMoveType(ctx->currentMove); + if (ProteanTryChangeType(ctx->battlerAtk, ctx->abilities[ctx->battlerAtk], ctx->currentMove, moveType)) + { + if (GetConfig(CONFIG_PROTEAN_LIBERO) >= GEN_9) + gDisableStructs[ctx->battlerAtk].usedProteanLibero = TRUE; PREPARE_TYPE_BUFFER(gBattleTextBuff1, moveType); - gBattlerAbility = gBattlerAttacker; - PrepareStringBattle(STRINGID_EMPTYSTRING3, gBattlerAttacker); + gBattlerAbility = ctx->battlerAtk; + PrepareStringBattle(STRINGID_EMPTYSTRING3, ctx->battlerAtk); gBattleCommunication[MSG_DISPLAY] = 1; BattleScriptCall(BattleScript_ProteanActivates); return MOVE_STEP_BREAK; @@ -2403,48 +2865,32 @@ static enum MoveCanceler CancelerProtean(void) return MOVE_STEP_SUCCESS; } -static enum MoveCanceler CancelerPsychicTerrain(void) -{ - if (IsBattlerTerrainAffected(gBattlerTarget, STATUS_FIELD_PSYCHIC_TERRAIN) - && GetChosenMovePriority(gBattlerAttacker, GetBattlerAbility(gBattlerAttacker)) > 0 - && GetMoveTarget(gCurrentMove) != MOVE_TARGET_ALL_BATTLERS - && GetMoveTarget(gCurrentMove) != MOVE_TARGET_OPPONENTS_FIELD - && !IsBattlerAlly(gBattlerAttacker, gBattlerTarget)) - { - CancelMultiTurnMoves(gBattlerAttacker, SKY_DROP_ATTACKCANCELER_CHECK); - gBattlescriptCurrInstr = BattleScript_MoveUsedPsychicTerrainPrevents; - gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; - return MOVE_STEP_BREAK; - } - return MOVE_STEP_SUCCESS; -} - -static enum MoveCanceler CancelerExplodingDamp(void) +static enum MoveCanceler CancelerExplodingDamp(struct BattleContext *ctx) { u32 dampBattler = IsAbilityOnField(ABILITY_DAMP); - if (dampBattler && IsMoveDampBanned(gCurrentMove)) + if (dampBattler && IsMoveDampBanned(ctx->currentMove)) { gBattleScripting.battler = dampBattler - 1; gBattlescriptCurrInstr = BattleScript_DampStopsExplosion; gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; - return MOVE_STEP_BREAK; + return MOVE_STEP_FAILURE; } return MOVE_STEP_SUCCESS; } -static enum MoveCanceler CancelerMultihitMoves(void) +static enum MoveCanceler CancelerMultihitMoves(struct BattleContext *ctx) { - if (GetMoveEffect(gCurrentMove) == EFFECT_MULTI_HIT) + if (GetMoveEffect(ctx->currentMove) == EFFECT_MULTI_HIT) { - u32 ability = GetBattlerAbility(gBattlerAttacker); + enum Ability ability = ctx->abilities[ctx->battlerAtk]; if (ability == ABILITY_SKILL_LINK) { gMultiHitCounter = 5; } else if (ability == ABILITY_BATTLE_BOND - && gCurrentMove == MOVE_WATER_SHURIKEN - && gBattleMons[gBattlerAttacker].species == SPECIES_GRENINJA_ASH) + && ctx->currentMove == MOVE_WATER_SHURIKEN + && gBattleMons[ctx->battlerAtk].species == SPECIES_GRENINJA_ASH) { gMultiHitCounter = 3; } @@ -2455,30 +2901,32 @@ static enum MoveCanceler CancelerMultihitMoves(void) PREPARE_BYTE_NUMBER_BUFFER(gBattleScripting.multihitString, 1, 0) } - else if (GetMoveStrikeCount(gCurrentMove) > 1) + else if (GetMoveStrikeCount(ctx->currentMove) > 1) { - if (GetMoveEffect(gCurrentMove) == EFFECT_POPULATION_BOMB && GetBattlerHoldEffect(gBattlerAttacker, TRUE) == HOLD_EFFECT_LOADED_DICE) + if (GetMoveEffect(ctx->currentMove) == EFFECT_POPULATION_BOMB && GetBattlerHoldEffect(ctx->battlerAtk) == HOLD_EFFECT_LOADED_DICE) { gMultiHitCounter = RandomUniform(RNG_LOADED_DICE, 4, 10); } else { - gMultiHitCounter = GetMoveStrikeCount(gCurrentMove); + gMultiHitCounter = GetMoveStrikeCount(ctx->currentMove); - if (GetMoveEffect(gCurrentMove) == EFFECT_DRAGON_DARTS - && !IsAffectedByFollowMe(gBattlerAttacker, GetBattlerSide(gBattlerTarget), gCurrentMove) - && CanTargetPartner(gBattlerAttacker, gBattlerTarget) - && TargetFullyImmuneToCurrMove(gBattlerAttacker, gBattlerTarget)) - gBattlerTarget = BATTLE_PARTNER(gBattlerTarget); + if (GetMoveEffect(ctx->currentMove) == EFFECT_DRAGON_DARTS + && !IsAffectedByFollowMe(ctx->battlerAtk, GetBattlerSide(ctx->battlerDef), ctx->currentMove) + && CanTargetPartner(ctx->battlerAtk, ctx->battlerDef) + && TargetFullyImmuneToCurrMove(ctx->battlerAtk, ctx->battlerDef)) + gBattlerTarget = BATTLE_PARTNER(ctx->battlerDef); } PREPARE_BYTE_NUMBER_BUFFER(gBattleScripting.multihitString, 3, 0) } - else if (B_BEAT_UP >= GEN_5 && GetMoveEffect(gCurrentMove) == EFFECT_BEAT_UP) + else if (GetMoveEffect(ctx->currentMove) == EFFECT_BEAT_UP) { - struct Pokemon* party = GetBattlerParty(gBattlerAttacker); + struct Pokemon* party = GetBattlerParty(ctx->battlerAtk); int i; gBattleStruct->beatUpSlot = 0; + gMultiHitCounter = 0; + memset(gBattleStruct->beatUpSpecies, 0xFF, sizeof(gBattleStruct->beatUpSpecies)); for (i = 0; i < PARTY_SIZE; i++) { @@ -2488,12 +2936,14 @@ static enum MoveCanceler CancelerMultihitMoves(void) && !GetMonData(&party[i], MON_DATA_IS_EGG) && !GetMonData(&party[i], MON_DATA_STATUS)) { - gBattleStruct->beatUpSpecies[gBattleStruct->beatUpSlot++] = species; + if (GetConfig(CONFIG_BEAT_UP) >= GEN_5) + gBattleStruct->beatUpSpecies[gMultiHitCounter] = species; + else + gBattleStruct->beatUpSpecies[gMultiHitCounter] = i; gMultiHitCounter++; } } - gBattleStruct->beatUpSlot = 0; PREPARE_BYTE_NUMBER_BUFFER(gBattleScripting.multihitString, 1, 0) } else @@ -2504,42 +2954,10 @@ static enum MoveCanceler CancelerMultihitMoves(void) return MOVE_STEP_SUCCESS; } -static enum MoveCanceler CancelerZMoves(void) +static enum MoveCanceler CancelerMultiTargetMoves(struct BattleContext *ctx) { - if (GetActiveGimmick(gBattlerAttacker) == GIMMICK_Z_MOVE) - { - // For Z-Mirror Move, so it doesn't play the animation twice. - bool32 alreadyUsed = HasTrainerUsedGimmick(gBattlerAttacker, GIMMICK_Z_MOVE); - - // attacker has a queued z move - RecordItemEffectBattle(gBattlerAttacker, HOLD_EFFECT_Z_CRYSTAL); - SetGimmickAsActivated(gBattlerAttacker, GIMMICK_Z_MOVE); - - gBattleScripting.battler = gBattlerAttacker; - if (gProtectStructs[gBattlerAttacker].powderSelfDmg) - { - if (!alreadyUsed) - BattleScriptCall(BattleScript_ZMoveActivatePowder); - } - else if (GetMoveCategory(gCurrentMove) == DAMAGE_CATEGORY_STATUS) - { - if (!alreadyUsed) - BattleScriptCall(BattleScript_ZMoveActivateStatus); - } - else - { - if (!alreadyUsed) - BattleScriptCall(BattleScript_ZMoveActivateDamaging); - } - return MOVE_STEP_BREAK; // The original move is cancelled, not the z move - } - return MOVE_STEP_SUCCESS; -} - -static enum MoveCanceler CancelerMultiTargetMoves(void) -{ - u32 moveTarget = GetBattlerMoveTargetType(gBattlerAttacker, gCurrentMove); - u32 abilityAtk = GetBattlerAbility(gBattlerAttacker); + u32 moveTarget = GetBattlerMoveTargetType(ctx->battlerAtk, ctx->currentMove); + enum Ability abilityAtk = ctx->abilities[ctx->battlerAtk]; if (IsSpreadMove(moveTarget)) { @@ -2548,88 +2966,97 @@ static enum MoveCanceler CancelerMultiTargetMoves(void) if (gBattleStruct->bouncedMoveIsUsed && !IsOnPlayerSide(battlerDef)) continue; - u32 abilityDef = GetBattlerAbility(battlerDef); + enum Ability abilityDef = GetBattlerAbility(battlerDef); - if (gBattlerAttacker == battlerDef + if (ctx->battlerAtk == battlerDef || !IsBattlerAlive(battlerDef) - || (GetMoveEffect(gCurrentMove) == EFFECT_SYNCHRONOISE && !DoBattlersShareType(gBattlerAttacker, battlerDef)) - || (moveTarget == MOVE_TARGET_BOTH && gBattlerAttacker == BATTLE_PARTNER(battlerDef)) - || IsBattlerProtected(gBattlerAttacker, battlerDef, gCurrentMove)) // Missing Invulnerable check + || (GetMoveEffect(ctx->currentMove) == EFFECT_SYNCHRONOISE && !DoBattlersShareType(ctx->battlerAtk, battlerDef)) + || (moveTarget == MOVE_TARGET_BOTH && ctx->battlerAtk == BATTLE_PARTNER(battlerDef)) + || IsBattlerProtected(ctx->battlerAtk, battlerDef, ctx->currentMove)) // Missing Invulnerable check { gBattleStruct->moveResultFlags[battlerDef] = MOVE_RESULT_NO_EFFECT; gBattleStruct->noResultString[battlerDef] = WILL_FAIL; } - else if (CanAbilityBlockMove(gBattlerAttacker, battlerDef, abilityAtk, abilityDef, gCurrentMove, CHECK_TRIGGER) - || (IsBattlerTerrainAffected(gBattlerAttacker, STATUS_FIELD_PSYCHIC_TERRAIN) && GetBattleMovePriority(gBattlerAttacker, abilityAtk, gCurrentMove) > 0)) + else if (CanAbilityBlockMove(ctx->battlerAtk, battlerDef, abilityAtk, abilityDef, ctx->currentMove, CHECK_TRIGGER)) { gBattleStruct->moveResultFlags[battlerDef] = 0; gBattleStruct->noResultString[battlerDef] = WILL_FAIL; } - else if (CanAbilityAbsorbMove(gBattlerAttacker, battlerDef, abilityDef, gCurrentMove, GetBattleMoveType(gCurrentMove), CHECK_TRIGGER)) + else if (CanAbilityAbsorbMove(ctx->battlerAtk, battlerDef, abilityDef, ctx->currentMove, GetBattleMoveType(gCurrentMove), CHECK_TRIGGER)) { gBattleStruct->moveResultFlags[battlerDef] = 0; gBattleStruct->noResultString[battlerDef] = CHECK_ACCURACY; } else { - CalcTypeEffectivenessMultiplierHelper(gCurrentMove, GetBattleMoveType(gCurrentMove), gBattlerAttacker, battlerDef, abilityAtk, abilityDef, TRUE); // Sets moveResultFlags + CalcTypeEffectivenessMultiplierHelper(ctx->currentMove, GetBattleMoveType(ctx->currentMove), ctx->battlerAtk, battlerDef, abilityAtk, abilityDef, TRUE); // Sets moveResultFlags gBattleStruct->noResultString[battlerDef] = CAN_DAMAGE; } } if (moveTarget == MOVE_TARGET_BOTH) - gBattleStruct->numSpreadTargets = CountAliveMonsInBattle(BATTLE_ALIVE_EXCEPT_BATTLER_SIDE, gBattlerAttacker); + gBattleStruct->numSpreadTargets = CountAliveMonsInBattle(BATTLE_ALIVE_EXCEPT_BATTLER_SIDE, ctx->battlerAtk); else - gBattleStruct->numSpreadTargets = CountAliveMonsInBattle(BATTLE_ALIVE_EXCEPT_BATTLER, gBattlerAttacker); + gBattleStruct->numSpreadTargets = CountAliveMonsInBattle(BATTLE_ALIVE_EXCEPT_BATTLER, ctx->battlerAtk); } return MOVE_STEP_SUCCESS; } -static enum MoveCanceler (*const sMoveSuccessOrderCancelers[])(void) = +static enum MoveCanceler (*const sMoveSuccessOrderCancelers[])(struct BattleContext *ctx) = { - [CANCELER_FLAGS] = CancelerFlags, + [CANCELER_CLEAR_FLAGS] = CancelerClearFlags, [CANCELER_STANCE_CHANGE_1] = CancelerStanceChangeOne, [CANCELER_SKY_DROP] = CancelerSkyDrop, [CANCELER_RECHARGE] = CancelerRecharge, [CANCELER_ASLEEP_OR_FROZEN] = CancelerAsleepOrFrozen, [CANCELER_OBEDIENCE] = CancelerObedience, + [CANCELER_POWER_POINTS] = CancelerPowerPoints, [CANCELER_TRUANT] = CancelerTruant, [CANCELER_FLINCH] = CancelerFlinch, - [CANCELER_INFATUATION] = CancelerInfatuation, [CANCELER_DISABLED] = CancelerDisabled, [CANCELER_VOLATILE_BLOCKED] = CancelerVolatileBlocked, [CANCELER_TAUNTED] = CancelerTaunted, [CANCELER_IMPRISONED] = CancelerImprisoned, [CANCELER_CONFUSED] = CancelerConfused, - [CANCELER_PARALYSED] = CancelerParalysed, + [CANCELER_PARALYZED] = CancelerParalyzed, + [CANCELER_INFATUATION] = CancelerInfatuation, [CANCELER_BIDE] = CancelerBide, + [CANCELER_Z_MOVES] = CancelerZMoves, + [CANCELER_CHOICE_LOCK] = CancelerChoiceLock, + [CANCELER_CALLSUBMOVE] = CancelerCallSubmove, [CANCELER_THAW] = CancelerThaw, [CANCELER_STANCE_CHANGE_2] = CancelerStanceChangeTwo, - [CANCELER_CHOICE_LOCK] = CancelerChoiceLock, + [CANCELER_ATTACKSTRING] = CancelerAttackstring, + [CANCELER_PPDEDUCTION] = CancelerPPDeduction, [CANCELER_WEATHER_PRIMAL] = CancelerWeatherPrimal, - [CANCELER_DYNAMAX_BLOCKED] = CancelerDynamaxBlocked, + [CANCELER_MOVE_FAILURE] = CancelerMoveFailure, [CANCELER_POWDER_STATUS] = CancelerPowderStatus, + [CANCELER_PRIORITY_BLOCK] = CancelerPriorityBlock, [CANCELER_PROTEAN] = CancelerProtean, - [CANCELER_PSYCHIC_TERRAIN] = CancelerPsychicTerrain, [CANCELER_EXPLODING_DAMP] = CancelerExplodingDamp, [CANCELER_MULTIHIT_MOVES] = CancelerMultihitMoves, - [CANCELER_Z_MOVES] = CancelerZMoves, [CANCELER_MULTI_TARGET_MOVES] = CancelerMultiTargetMoves, }; -enum MoveCanceler AtkCanceler_MoveSuccessOrder(void) +enum MoveCanceler AtkCanceler_MoveSuccessOrder(struct BattleContext *ctx) { enum MoveCanceler effect = MOVE_STEP_SUCCESS; - while (gBattleStruct->atkCancelerTracker < CANCELER_END && effect == MOVE_STEP_SUCCESS) + while (gBattleStruct->eventState.atkCanceler < CANCELER_END && effect == MOVE_STEP_SUCCESS) { - effect = sMoveSuccessOrderCancelers[gBattleStruct->atkCancelerTracker](); - gBattleStruct->atkCancelerTracker++; + effect = sMoveSuccessOrderCancelers[gBattleStruct->eventState.atkCanceler](ctx); + gBattleStruct->eventState.atkCanceler++; } if (effect == MOVE_STEP_REMOVES_STATUS) { - BtlController_EmitSetMonData(gBattlerAttacker, B_COMM_TO_CONTROLLER, REQUEST_STATUS_BATTLE, 0, 4, &gBattleMons[gBattlerAttacker].status1); - MarkBattlerForControllerExec(gBattlerAttacker); + BtlController_EmitSetMonData( + ctx->battlerAtk, + B_COMM_TO_CONTROLLER, + REQUEST_STATUS_BATTLE, + 0, + 4, + &gBattleMons[gBattlerAttacker].status1); + MarkBattlerForControllerExec(ctx->battlerAtk); } return effect; @@ -2806,11 +3233,14 @@ bool32 TryChangeBattleWeather(u32 battler, u32 battleWeatherId, u32 ability) { return FALSE; } - else if (GetGenConfig(GEN_CONFIG_ABILITY_WEATHER) < GEN_6 && ability != ABILITY_NONE) + else if (GetConfig(CONFIG_ABILITY_WEATHER) < GEN_6 && ability != ABILITY_NONE) { gBattleWeather = sBattleWeatherInfo[battleWeatherId].flag; for (u32 i = 0; i < gBattlersCount; i++) + { gDisableStructs[i].weatherAbilityDone = FALSE; + ResetParadoxWeatherStat(i); + } return TRUE; } else @@ -2819,12 +3249,15 @@ bool32 TryChangeBattleWeather(u32 battler, u32 battleWeatherId, u32 ability) gBattleWeather = sBattleWeatherInfo[battleWeatherId].flag; if (gBattleWeather & B_WEATHER_PRIMAL_ANY) gWishFutureKnock.weatherDuration = 0; - else if (rock != 0 && GetBattlerHoldEffect(battler, TRUE) == rock) + else if (rock != 0 && GetBattlerHoldEffect(battler) == rock) gWishFutureKnock.weatherDuration = 8; else gWishFutureKnock.weatherDuration = 5; for (u32 i = 0; i < gBattlersCount; i++) + { gDisableStructs[i].weatherAbilityDone = FALSE; + ResetParadoxWeatherStat(i); + } return TRUE; } @@ -2841,11 +3274,14 @@ bool32 TryChangeBattleTerrain(u32 battler, u32 statusFlag) gFieldStatuses &= ~STATUS_FIELD_TERRAIN_ANY; gFieldStatuses |= statusFlag; for (u32 i = 0; i < gBattlersCount; i++) + { gDisableStructs[i].terrainAbilityDone = FALSE; - if (GetBattlerHoldEffect(battler, TRUE) == HOLD_EFFECT_TERRAIN_EXTENDER) - gFieldTimers.terrainTimer = gBattleTurnCounter + 8; + ResetParadoxTerrainStat(i); + } + if (GetBattlerHoldEffect(battler) == HOLD_EFFECT_TERRAIN_EXTENDER) + gFieldTimers.terrainTimer = 8; else - gFieldTimers.terrainTimer = gBattleTurnCounter + 5; + gFieldTimers.terrainTimer = 5; gBattleScripting.battler = battler; return TRUE; } @@ -2917,7 +3353,7 @@ static void ForewarnChooseMove(u32 battler) bool32 ChangeTypeBasedOnTerrain(u32 battler) { - u32 battlerType; + enum Type battlerType; if (gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN) battlerType = TYPE_ELECTRIC; @@ -2935,7 +3371,7 @@ bool32 ChangeTypeBasedOnTerrain(u32 battler) return TRUE; } -static inline u8 GetSideFaintCounter(u32 side) +static inline u8 GetSideFaintCounter(enum BattleSide side) { return (side == B_SIDE_PLAYER) ? gBattleResults.playerFaintCounter : gBattleResults.opponentFaintCounter; } @@ -2953,10 +3389,9 @@ static inline uq4_12_t GetSupremeOverlordModifier(u32 battler) bool32 HadMoreThanHalfHpNowDoesnt(u32 battler) { - u32 cutoff = gBattleMons[battler].maxHP / 2; // Had more than half of hp before, now has less - return gBattleStruct->hpBefore[battler] > cutoff - && gBattleMons[battler].hp <= cutoff; + return gBattleStruct->battlerState[battler].wasAboveHalfHp + && gBattleMons[battler].hp <= gBattleMons[battler].maxHP / 2; } #define ANIM_STAT_HP 0 @@ -2967,7 +3402,7 @@ bool32 HadMoreThanHalfHpNowDoesnt(u32 battler) #define ANIM_STAT_SPEED 5 #define ANIM_STAT_ACC 6 #define ANIM_STAT_EVASION 7 -static void ChooseStatBoostAnimation(u32 battler) +void ChooseStatBoostAnimation(u32 battler) { u32 stat; bool32 statBuffMoreThan1 = FALSE; @@ -3007,44 +3442,19 @@ static void ChooseStatBoostAnimation(u32 battler) #undef ANIM_STAT_ACC #undef ANIM_STAT_EVASION -bool32 CanAbilityBlockMove(u32 battlerAtk, u32 battlerDef, u32 abilityAtk, u32 abilityDef, u32 move, enum FunctionCallOption option) +bool32 CanAbilityBlockMove(u32 battlerAtk, u32 battlerDef, enum Ability abilityAtk, enum Ability abilityDef, u32 move, enum FunctionCallOption option) { const u8 *battleScriptBlocksMove = NULL; - u32 battlerAbility = battlerDef; - s32 atkPriority = 0; - - if (option == AI_CHECK) - atkPriority = GetBattleMovePriority(battlerAtk, abilityAtk, move); - else - atkPriority = GetChosenMovePriority(battlerAtk, abilityAtk); switch (abilityDef) { case ABILITY_SOUNDPROOF: if (IsSoundMove(move) && !(GetBattlerMoveTargetType(battlerAtk, move) & MOVE_TARGET_USER)) - { - if (gBattleMons[battlerAtk].volatiles.multipleTurns) - gHitMarker |= HITMARKER_NO_PPDEDUCT; battleScriptBlocksMove = BattleScript_SoundproofProtected; - } break; case ABILITY_BULLETPROOF: if (IsBallisticMove(move)) - { - if (gBattleMons[battlerAtk].volatiles.multipleTurns) - gHitMarker |= HITMARKER_NO_PPDEDUCT; battleScriptBlocksMove = BattleScript_SoundproofProtected; - } - break; - case ABILITY_DAZZLING: - case ABILITY_QUEENLY_MAJESTY: - case ABILITY_ARMOR_TAIL: - if (atkPriority > 0 && !IsBattlerAlly(battlerAtk, battlerDef)) - { - if (gBattleMons[battlerAtk].volatiles.multipleTurns) - gHitMarker |= HITMARKER_NO_PPDEDUCT; - battleScriptBlocksMove = BattleScript_DazzlingProtected; - } break; case ABILITY_GOOD_AS_GOLD: if (IsBattleMoveStatus(move)) @@ -3053,44 +3463,43 @@ bool32 CanAbilityBlockMove(u32 battlerAtk, u32 battlerDef, u32 abilityAtk, u32 a battleScriptBlocksMove = BattleScript_GoodAsGoldActivates; } break; + default: + break; } - if (atkPriority > 0) + if (battleScriptBlocksMove == NULL) { - // Prankster check - if (battleScriptBlocksMove == NULL - && IsBattleMoveStatus(move) - && BlocksPrankster(move, battlerAtk, battlerDef, TRUE) - && !(IsBattleMoveStatus(move) && (abilityDef == ABILITY_MAGIC_BOUNCE || gProtectStructs[battlerDef].bounceMove))) + s32 atkPriority = 0; + if (option == AI_CHECK) + atkPriority = GetBattleMovePriority(battlerAtk, abilityAtk, move); + else + atkPriority = GetChosenMovePriority(battlerAtk, abilityAtk); + + if (atkPriority <= 0) + { + // Not a priority move + } + else if (IsBattleMoveStatus(move) + && BlocksPrankster(move, battlerAtk, battlerDef, TRUE) + && !(IsBattleMoveStatus(move) && (abilityDef == ABILITY_MAGIC_BOUNCE || gProtectStructs[battlerDef].bounceMove))) { if (option == RUN_SCRIPT && !IsSpreadMove(GetBattlerMoveTargetType(battlerAtk, move))) CancelMultiTurnMoves(battlerAtk, SKY_DROP_ATTACKCANCELER_CHECK); // Don't cancel moves that can hit two targets bc one target might not be protected - battleScriptBlocksMove = BattleScript_DoesntAffectTargetAtkString; } - - // Check def partner ability - u32 partnerDef = BATTLE_PARTNER(battlerDef); - if (battleScriptBlocksMove == NULL - && IsDoubleBattle() - && IsBattlerAlive(partnerDef) - && !IsBattlerAlly(battlerAtk, partnerDef)) + else if (IsBattlerTerrainAffected(battlerDef, abilityDef, GetBattlerHoldEffect(battlerDef), STATUS_FIELD_PSYCHIC_TERRAIN) // Not an ability but similar conditions + && !IsBattlerAlly(battlerAtk, battlerDef) + && GetMoveTarget(move) != MOVE_TARGET_ALL_BATTLERS + && GetMoveTarget(move) != MOVE_TARGET_OPPONENTS_FIELD) { - if (option == AI_CHECK) - abilityDef = gAiLogicData->abilities[partnerDef]; - else - abilityDef = GetBattlerAbility(partnerDef); - - switch (abilityDef) + battleScriptBlocksMove = BattleScript_MoveUsedPsychicTerrainPrevents; + if (option == RUN_SCRIPT) { - case ABILITY_DAZZLING: - case ABILITY_QUEENLY_MAJESTY: - case ABILITY_ARMOR_TAIL: - if (gBattleMons[battlerAtk].volatiles.multipleTurns) - gHitMarker |= HITMARKER_NO_PPDEDUCT; - battlerAbility = partnerDef; - battleScriptBlocksMove = BattleScript_DazzlingProtected; - break; + gMultiHitCounter = 0; // Prevent multi-hit moves from hitting more than once after move has been absorbed. + if (!IsSpreadMove(GetBattlerMoveTargetType(battlerAtk, move))) + CancelMultiTurnMoves(battlerAtk, SKY_DROP_ATTACKCANCELER_CHECK); // Don't cancel moves that can hit two targets bc one target might not be protected + gBattlescriptCurrInstr = BattleScript_MoveUsedPsychicTerrainPrevents; + return TRUE; // Early return since we don't want to set remaining values } } } @@ -3100,21 +3509,21 @@ bool32 CanAbilityBlockMove(u32 battlerAtk, u32 battlerDef, u32 abilityAtk, u32 a if (option == RUN_SCRIPT) { - gMultiHitCounter = 0; // Prevent multi-hit moves from hitting more than once after move has been absorbed. + gMultiHitCounter = 0; // Prevent multi-hit moves from hitting more than once after move has been absorbed. gLastUsedAbility = abilityDef; RecordAbilityBattle(battlerDef, abilityDef); - gBattleScripting.battler = gBattlerAbility = battlerAbility; + gBattleScripting.battler = gBattlerAbility = battlerDef; gBattlescriptCurrInstr = battleScriptBlocksMove; } return TRUE; } -bool32 CanAbilityAbsorbMove(u32 battlerAtk, u32 battlerDef, u32 abilityDef, u32 move, u32 moveType, enum FunctionCallOption option) +bool32 CanAbilityAbsorbMove(u32 battlerAtk, u32 battlerDef, enum Ability abilityDef, u32 move, enum Type moveType, enum FunctionCallOption option) { enum MoveAbsorbed effect = MOVE_ABSORBED_BY_NO_ABILITY; const u8 *battleScript = NULL; - u32 statId = 0; + enum Stat statId = 0; u32 statAmount = 1; switch (abilityDef) @@ -3195,40 +3604,23 @@ bool32 CanAbilityAbsorbMove(u32 battlerAtk, u32 battlerDef, u32 abilityDef, u32 gBattleStruct->pledgeMove = FALSE; if (IsBattlerAtMaxHp(battlerDef) || (B_HEAL_BLOCKING >= GEN_5 && gBattleMons[battlerDef].volatiles.healBlock)) { - if ((gProtectStructs[battlerAtk].notFirstStrike)) - battleScript = BattleScript_MonMadeMoveUseless; - else - battleScript = BattleScript_MonMadeMoveUseless_PPLoss; + battleScript = BattleScript_MonMadeMoveUseless; } else { - if (gProtectStructs[battlerAtk].notFirstStrike) - battleScript = BattleScript_MoveHPDrain; - else - battleScript = BattleScript_MoveHPDrain_PPLoss; - - gBattleStruct->moveDamage[battlerDef] = GetNonDynamaxMaxHP(battlerDef) / 4; - if (gBattleStruct->moveDamage[battlerDef] == 0) - gBattleStruct->moveDamage[battlerDef] = 1; - gBattleStruct->moveDamage[battlerDef] *= -1; + battleScript = BattleScript_MoveHPDrain; + SetHealAmount(battlerDef, GetNonDynamaxMaxHP(battlerDef) / 4); } break; case MOVE_ABSORBED_BY_STAT_INCREASE_ABILITY: gBattleStruct->pledgeMove = FALSE; if (!CompareStat(battlerDef, statId, MAX_STAT_STAGE, CMP_LESS_THAN, abilityDef)) { - if ((gProtectStructs[battlerAtk].notFirstStrike)) - battleScript = BattleScript_MonMadeMoveUseless; - else - battleScript = BattleScript_MonMadeMoveUseless_PPLoss; + battleScript = BattleScript_MonMadeMoveUseless; } else { - if (gProtectStructs[battlerAtk].notFirstStrike) - battleScript = BattleScript_MoveStatDrain; - else - battleScript = BattleScript_MoveStatDrain_PPLoss; - + battleScript = BattleScript_MoveStatDrain; SET_STATCHANGER(statId, statAmount, FALSE); if (B_ABSORBING_ABILITY_STRING < GEN_5) PREPARE_STAT_BUFFER(gBattleTextBuff1, statId); @@ -3239,19 +3631,13 @@ bool32 CanAbilityAbsorbMove(u32 battlerAtk, u32 battlerDef, u32 abilityDef, u32 if (!gDisableStructs[battlerDef].flashFireBoosted) { gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_FLASH_FIRE_BOOST; - if (gProtectStructs[battlerAtk].notFirstStrike) - battleScript = BattleScript_FlashFireBoost; - else - battleScript = BattleScript_FlashFireBoost_PPLoss; + battleScript = BattleScript_FlashFireBoost; gDisableStructs[battlerDef].flashFireBoosted = TRUE; } else { gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_FLASH_FIRE_NO_BOOST; - if (gProtectStructs[battlerAtk].notFirstStrike) - battleScript = BattleScript_FlashFireBoost; - else - battleScript = BattleScript_FlashFireBoost_PPLoss; + battleScript = BattleScript_FlashFireBoost; } break; } @@ -3268,7 +3654,7 @@ bool32 CanAbilityAbsorbMove(u32 battlerAtk, u32 battlerDef, u32 abilityDef, u32 return effect; } -static inline u32 SetStartingFieldStatus(u32 flag, u32 message, u32 anim, u16 *timer) +static inline bool32 SetStartingFieldStatus(u32 flag, u32 message, u32 anim, u16 *timer) { if (!(gFieldStatuses & flag)) { @@ -3276,17 +3662,17 @@ static inline u32 SetStartingFieldStatus(u32 flag, u32 message, u32 anim, u16 *t gFieldStatuses |= flag; gBattleScripting.animArg1 = anim; if (gBattleStruct->startingStatusTimer) - *timer = gBattleTurnCounter + gBattleStruct->startingStatusTimer; + *timer = gBattleStruct->startingStatusTimer; else *timer = 0; // Infinite - return 1; + return TRUE; } - return 0; + return FALSE; } -static inline u32 SetStartingSideStatus(u32 flag, u32 side, u32 message, u32 anim, u16 *timer) +static inline bool32 SetStartingSideStatus(u32 flag, u32 side, u32 message, u32 anim, u16 *timer) { if (!(gSideStatuses[side] & flag)) { @@ -3295,20 +3681,254 @@ static inline u32 SetStartingSideStatus(u32 flag, u32 side, u32 message, u32 ani gSideStatuses[side] |= flag; gBattleScripting.animArg1 = anim; if (gBattleStruct->startingStatusTimer) - *timer = gBattleTurnCounter + gBattleStruct->startingStatusTimer; + *timer = gBattleStruct->startingStatusTimer; else *timer = 0; // Infinite - return 1; + return TRUE; } - return 0; + return FALSE; } -u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 moveArg) +bool32 TryFieldEffects(enum FieldEffectCases caseId) +{ + bool32 effect = FALSE; + bool32 isTerrain = FALSE; + + if (gBattleTypeFlags & BATTLE_TYPE_SAFARI) + return FALSE; + + switch (caseId) + { + case FIELD_EFFECT_TRAINER_STATUSES: // starting field/side/etc statuses with a variable + switch ((enum StartingStatus) gBattleStruct->startingStatus) + { + case STARTING_STATUS_NONE: + break; + case STARTING_STATUS_ELECTRIC_TERRAIN: + effect = SetStartingFieldStatus( + STATUS_FIELD_ELECTRIC_TERRAIN, + B_MSG_TERRAIN_SET_ELECTRIC, + 0, + &gFieldTimers.terrainTimer); + isTerrain = TRUE; + break; + case STARTING_STATUS_MISTY_TERRAIN: + effect = SetStartingFieldStatus( + STATUS_FIELD_MISTY_TERRAIN, + B_MSG_TERRAIN_SET_MISTY, + 0, + &gFieldTimers.terrainTimer); + isTerrain = TRUE; + break; + case STARTING_STATUS_GRASSY_TERRAIN: + effect = SetStartingFieldStatus( + STATUS_FIELD_GRASSY_TERRAIN, + B_MSG_TERRAIN_SET_GRASSY, + 0, + &gFieldTimers.terrainTimer); + isTerrain = TRUE; + break; + case STARTING_STATUS_PSYCHIC_TERRAIN: + effect = SetStartingFieldStatus( + STATUS_FIELD_PSYCHIC_TERRAIN, + B_MSG_TERRAIN_SET_PSYCHIC, + 0, + &gFieldTimers.terrainTimer); + isTerrain = TRUE; + break; + case STARTING_STATUS_TRICK_ROOM: + effect = SetStartingFieldStatus( + STATUS_FIELD_TRICK_ROOM, + B_MSG_SET_TRICK_ROOM, + B_ANIM_TRICK_ROOM, + &gFieldTimers.trickRoomTimer); + break; + case STARTING_STATUS_MAGIC_ROOM: + effect = SetStartingFieldStatus( + STATUS_FIELD_MAGIC_ROOM, + B_MSG_SET_MAGIC_ROOM, + B_ANIM_MAGIC_ROOM, + &gFieldTimers.magicRoomTimer); + break; + case STARTING_STATUS_WONDER_ROOM: + effect = SetStartingFieldStatus( + STATUS_FIELD_WONDER_ROOM, + B_MSG_SET_WONDER_ROOM, + B_ANIM_WONDER_ROOM, + &gFieldTimers.wonderRoomTimer); + break; + case STARTING_STATUS_TAILWIND_PLAYER: + effect = SetStartingSideStatus( + SIDE_STATUS_TAILWIND, + B_SIDE_PLAYER, + B_MSG_SET_TAILWIND, + B_ANIM_TAILWIND, + &gSideTimers[B_SIDE_PLAYER].tailwindTimer); + break; + case STARTING_STATUS_TAILWIND_OPPONENT: + effect = SetStartingSideStatus( + SIDE_STATUS_TAILWIND, + B_SIDE_OPPONENT, + B_MSG_SET_TAILWIND, + B_ANIM_TAILWIND, + &gSideTimers[B_SIDE_OPPONENT].tailwindTimer); + break; + case STARTING_STATUS_RAINBOW_PLAYER: + effect = SetStartingSideStatus( + SIDE_STATUS_RAINBOW, + B_SIDE_PLAYER, + B_MSG_SET_RAINBOW, + B_ANIM_RAINBOW, + &gSideTimers[B_SIDE_PLAYER].rainbowTimer); + break; + case STARTING_STATUS_RAINBOW_OPPONENT: + effect = SetStartingSideStatus( + SIDE_STATUS_RAINBOW, + B_SIDE_OPPONENT, + B_MSG_SET_RAINBOW, + B_ANIM_RAINBOW, + &gSideTimers[B_SIDE_OPPONENT].rainbowTimer); + break; + case STARTING_STATUS_SEA_OF_FIRE_PLAYER: + effect = SetStartingSideStatus( + SIDE_STATUS_SEA_OF_FIRE, + B_SIDE_PLAYER, + B_MSG_SET_SEA_OF_FIRE, + B_ANIM_SEA_OF_FIRE, + &gSideTimers[B_SIDE_PLAYER].seaOfFireTimer); + break; + case STARTING_STATUS_SEA_OF_FIRE_OPPONENT: + effect = SetStartingSideStatus( + SIDE_STATUS_SEA_OF_FIRE, + B_SIDE_OPPONENT, + B_MSG_SET_SEA_OF_FIRE, + B_ANIM_SEA_OF_FIRE, + &gSideTimers[B_SIDE_OPPONENT].seaOfFireTimer); + break; + case STARTING_STATUS_SWAMP_PLAYER: + effect = SetStartingSideStatus( + SIDE_STATUS_SWAMP, + B_SIDE_PLAYER, + B_MSG_SET_SWAMP, + B_ANIM_SWAMP, + &gSideTimers[B_SIDE_PLAYER].swampTimer); + break; + case STARTING_STATUS_SWAMP_OPPONENT: + effect = SetStartingSideStatus( + SIDE_STATUS_SWAMP, + B_SIDE_OPPONENT, + B_MSG_SET_SWAMP, + B_ANIM_SWAMP, + &gSideTimers[B_SIDE_OPPONENT].swampTimer); + break; + } + if (effect) + { + if (isTerrain) + BattleScriptPushCursorAndCallback(BattleScript_OverworldTerrain); + else + BattleScriptPushCursorAndCallback(BattleScript_OverworldStatusStarts); + } + break; + case FIELD_EFFECT_OVERWORLD_TERRAIN: // terrain starting from overworld weather + if (B_THUNDERSTORM_TERRAIN == TRUE + && !(gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN) + && GetCurrentWeather() == WEATHER_RAIN_THUNDERSTORM) + { + // overworld weather started rain, so just do electric terrain anim + gFieldStatuses = STATUS_FIELD_ELECTRIC_TERRAIN; + gFieldTimers.terrainTimer = 0; + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_TERRAIN_SET_ELECTRIC; + BattleScriptPushCursorAndCallback(BattleScript_OverworldTerrain); + effect = TRUE; + } + else if (B_OVERWORLD_FOG >= GEN_8 + && (GetCurrentWeather() == WEATHER_FOG_HORIZONTAL || GetCurrentWeather() == WEATHER_FOG_DIAGONAL) + && !(gFieldStatuses & STATUS_FIELD_MISTY_TERRAIN)) + { + gFieldStatuses = STATUS_FIELD_MISTY_TERRAIN; + gFieldTimers.terrainTimer = 0; + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_TERRAIN_SET_MISTY; + BattleScriptPushCursorAndCallback(BattleScript_OverworldTerrain); + effect = TRUE; + } + break; + case FIELD_EFFECT_OVERWORLD_WEATHER: + if (!(gBattleTypeFlags & BATTLE_TYPE_RECORDED)) + { + switch (GetCurrentWeather()) + { + case WEATHER_RAIN: + case WEATHER_RAIN_THUNDERSTORM: + case WEATHER_DOWNPOUR: + if (!(gBattleWeather & B_WEATHER_RAIN)) + { + gBattleWeather = B_WEATHER_RAIN_NORMAL; + gBattleScripting.animArg1 = B_ANIM_RAIN_CONTINUES; + effect = TRUE; + } + break; + case WEATHER_SANDSTORM: + if (!(gBattleWeather & B_WEATHER_SANDSTORM)) + { + gBattleWeather = B_WEATHER_SANDSTORM; + gBattleScripting.animArg1 = B_ANIM_SANDSTORM_CONTINUES; + effect = TRUE; + } + break; + case WEATHER_DROUGHT: + if (!(gBattleWeather & B_WEATHER_SUN)) + { + gBattleWeather = B_WEATHER_SUN_NORMAL; + gBattleScripting.animArg1 = B_ANIM_SUN_CONTINUES; + effect = TRUE; + } + break; + case WEATHER_SNOW: + if (!(gBattleWeather & (B_WEATHER_HAIL | B_WEATHER_SNOW))) + { + if (B_OVERWORLD_SNOW >= GEN_9) + { + gBattleWeather = B_WEATHER_SNOW; + gBattleScripting.animArg1 = B_ANIM_SNOW_CONTINUES; + } + else + { + gBattleWeather = B_WEATHER_HAIL; + gBattleScripting.animArg1 = B_ANIM_HAIL_CONTINUES; + } + effect = TRUE; + } + break; + case WEATHER_FOG_DIAGONAL: + case WEATHER_FOG_HORIZONTAL: + if (B_OVERWORLD_FOG == GEN_4 && !(gBattleWeather & B_WEATHER_FOG)) + { + gBattleWeather = B_WEATHER_FOG; + gBattleScripting.animArg1 = B_ANIM_FOG_CONTINUES; + effect = TRUE; + } + break; + } + } + if (effect) + { + gBattleCommunication[MULTISTRING_CHOOSER] = GetCurrentWeather(); + BattleScriptPushCursorAndCallback(BattleScript_OverworldWeatherStarts); + } + break; + } + + return effect; +} + +u32 AbilityBattleEffects(enum AbilityEffect caseID, u32 battler, enum Ability ability, u32 special, u32 moveArg) { u32 effect = 0; - u32 moveType = 0, move = 0; + enum Type moveType = 0; + u32 move = 0; u32 side = 0; u32 i = 0, j = 0; u32 partner = 0; @@ -3335,212 +3955,6 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 switch (caseID) { - case ABILITYEFFECT_SWITCH_IN_STATUSES: // starting field/side/etc statuses with a variable - { - gBattleScripting.battler = battler; - switch (gBattleStruct->startingStatus) - { - case STARTING_STATUS_ELECTRIC_TERRAIN: - effect = SetStartingFieldStatus(STATUS_FIELD_ELECTRIC_TERRAIN, - B_MSG_TERRAIN_SET_ELECTRIC, - 0, - &gFieldTimers.terrainTimer); - effect = (effect == 1) ? 2 : 0; - break; - case STARTING_STATUS_MISTY_TERRAIN: - effect = SetStartingFieldStatus(STATUS_FIELD_MISTY_TERRAIN, - B_MSG_TERRAIN_SET_MISTY, - 0, - &gFieldTimers.terrainTimer); - effect = (effect == 1) ? 2 : 0; - break; - case STARTING_STATUS_GRASSY_TERRAIN: - effect = SetStartingFieldStatus(STATUS_FIELD_GRASSY_TERRAIN, - B_MSG_TERRAIN_SET_GRASSY, - 0, - &gFieldTimers.terrainTimer); - effect = (effect == 1) ? 2 : 0; - break; - case STARTING_STATUS_PSYCHIC_TERRAIN: - effect = SetStartingFieldStatus(STATUS_FIELD_PSYCHIC_TERRAIN, - B_MSG_TERRAIN_SET_PSYCHIC, - 0, - &gFieldTimers.terrainTimer); - effect = (effect == 1) ? 2 : 0; - break; - case STARTING_STATUS_TRICK_ROOM: - effect = SetStartingFieldStatus(STATUS_FIELD_TRICK_ROOM, - B_MSG_SET_TRICK_ROOM, - B_ANIM_TRICK_ROOM, - &gFieldTimers.trickRoomTimer); - break; - case STARTING_STATUS_MAGIC_ROOM: - effect = SetStartingFieldStatus(STATUS_FIELD_MAGIC_ROOM, - B_MSG_SET_MAGIC_ROOM, - B_ANIM_MAGIC_ROOM, - &gFieldTimers.magicRoomTimer); - break; - case STARTING_STATUS_WONDER_ROOM: - effect = SetStartingFieldStatus(STATUS_FIELD_WONDER_ROOM, - B_MSG_SET_WONDER_ROOM, - B_ANIM_WONDER_ROOM, - &gFieldTimers.wonderRoomTimer); - break; - case STARTING_STATUS_TAILWIND_PLAYER: - effect = SetStartingSideStatus(SIDE_STATUS_TAILWIND, - B_SIDE_PLAYER, - B_MSG_SET_TAILWIND, - B_ANIM_TAILWIND, - &gSideTimers[B_SIDE_PLAYER].tailwindTimer); - break; - case STARTING_STATUS_TAILWIND_OPPONENT: - effect = SetStartingSideStatus(SIDE_STATUS_TAILWIND, - B_SIDE_OPPONENT, - B_MSG_SET_TAILWIND, - B_ANIM_TAILWIND, - &gSideTimers[B_SIDE_OPPONENT].tailwindTimer); - break; - case STARTING_STATUS_RAINBOW_PLAYER: - effect = SetStartingSideStatus(SIDE_STATUS_RAINBOW, - B_SIDE_PLAYER, - B_MSG_SET_RAINBOW, - B_ANIM_RAINBOW, - &gSideTimers[B_SIDE_PLAYER].rainbowTimer); - break; - case STARTING_STATUS_RAINBOW_OPPONENT: - effect = SetStartingSideStatus(SIDE_STATUS_RAINBOW, - B_SIDE_OPPONENT, - B_MSG_SET_RAINBOW, - B_ANIM_RAINBOW, - &gSideTimers[B_SIDE_OPPONENT].rainbowTimer); - break; - case STARTING_STATUS_SEA_OF_FIRE_PLAYER: - effect = SetStartingSideStatus(SIDE_STATUS_SEA_OF_FIRE, - B_SIDE_PLAYER, - B_MSG_SET_SEA_OF_FIRE, - B_ANIM_SEA_OF_FIRE, - &gSideTimers[B_SIDE_PLAYER].seaOfFireTimer); - break; - case STARTING_STATUS_SEA_OF_FIRE_OPPONENT: - effect = SetStartingSideStatus(SIDE_STATUS_SEA_OF_FIRE, - B_SIDE_OPPONENT, - B_MSG_SET_SEA_OF_FIRE, - B_ANIM_SEA_OF_FIRE, - &gSideTimers[B_SIDE_OPPONENT].seaOfFireTimer); - break; - case STARTING_STATUS_SWAMP_PLAYER: - effect = SetStartingSideStatus(SIDE_STATUS_SWAMP, - B_SIDE_PLAYER, - B_MSG_SET_SWAMP, - B_ANIM_SWAMP, - &gSideTimers[B_SIDE_PLAYER].swampTimer); - break; - case STARTING_STATUS_SWAMP_OPPONENT: - effect = SetStartingSideStatus(SIDE_STATUS_SWAMP, - B_SIDE_OPPONENT, - B_MSG_SET_SWAMP, - B_ANIM_SWAMP, - &gSideTimers[B_SIDE_OPPONENT].swampTimer); - break; - } - - if (effect == 1) - BattleScriptPushCursorAndCallback(BattleScript_OverworldStatusStarts); - else if (effect == 2) - BattleScriptPushCursorAndCallback(BattleScript_OverworldTerrain); - } - break; - case ABILITYEFFECT_SWITCH_IN_TERRAIN: // terrain starting from overworld weather - if (B_THUNDERSTORM_TERRAIN == TRUE - && !(gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN) - && GetCurrentWeather() == WEATHER_RAIN_THUNDERSTORM) - { - // overworld weather started rain, so just do electric terrain anim - gFieldStatuses = STATUS_FIELD_ELECTRIC_TERRAIN; - gFieldTimers.terrainTimer = 0; - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_TERRAIN_SET_ELECTRIC; - BattleScriptPushCursorAndCallback(BattleScript_OverworldTerrain); - effect++; - } - else if (B_OVERWORLD_FOG >= GEN_8 - && (GetCurrentWeather() == WEATHER_FOG_HORIZONTAL || GetCurrentWeather() == WEATHER_FOG_DIAGONAL) - && !(gFieldStatuses & STATUS_FIELD_MISTY_TERRAIN)) - { - gFieldStatuses = STATUS_FIELD_MISTY_TERRAIN; - gFieldTimers.terrainTimer = 0; - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_TERRAIN_SET_MISTY; - BattleScriptPushCursorAndCallback(BattleScript_OverworldTerrain); - effect++; - } - break; - case ABILITYEFFECT_SWITCH_IN_WEATHER: - gBattleScripting.battler = battler; - if (!(gBattleTypeFlags & BATTLE_TYPE_RECORDED)) - { - switch (GetCurrentWeather()) - { - case WEATHER_RAIN: - case WEATHER_RAIN_THUNDERSTORM: - case WEATHER_DOWNPOUR: - if (!(gBattleWeather & B_WEATHER_RAIN)) - { - gBattleWeather = B_WEATHER_RAIN_NORMAL; - gBattleScripting.animArg1 = B_ANIM_RAIN_CONTINUES; - effect++; - } - break; - case WEATHER_SANDSTORM: - if (!(gBattleWeather & B_WEATHER_SANDSTORM)) - { - gBattleWeather = B_WEATHER_SANDSTORM; - gBattleScripting.animArg1 = B_ANIM_SANDSTORM_CONTINUES; - effect++; - } - break; - case WEATHER_DROUGHT: - if (!(gBattleWeather & B_WEATHER_SUN)) - { - gBattleWeather = B_WEATHER_SUN_NORMAL; - gBattleScripting.animArg1 = B_ANIM_SUN_CONTINUES; - effect++; - } - break; - case WEATHER_SNOW: - if (!(gBattleWeather & (B_WEATHER_HAIL | B_WEATHER_SNOW))) - { - if (B_OVERWORLD_SNOW >= GEN_9) - { - gBattleWeather = B_WEATHER_SNOW; - gBattleScripting.animArg1 = B_ANIM_SNOW_CONTINUES; - } - else - { - gBattleWeather = B_WEATHER_HAIL; - gBattleScripting.animArg1 = B_ANIM_HAIL_CONTINUES; - } - effect++; - } - break; - case WEATHER_FOG_DIAGONAL: - case WEATHER_FOG_HORIZONTAL: - if (B_OVERWORLD_FOG == GEN_4) - { - if (!(gBattleWeather & B_WEATHER_FOG)) - { - gBattleWeather = B_WEATHER_FOG; - gBattleScripting.animArg1 = B_ANIM_FOG_CONTINUES; - effect++; - } - break; - } - } - } - if (effect != 0) - { - gBattleCommunication[MULTISTRING_CHOOSER] = GetCurrentWeather(); - BattleScriptPushCursorAndCallback(BattleScript_OverworldWeatherStarts); - } - break; case ABILITYEFFECT_ON_SWITCHIN: gBattleScripting.battler = battler; switch (gLastUsedAbility) @@ -3553,7 +3967,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 if (gSpecialStatuses[battler].switchInAbilityDone) break; - if (GetBattlerHoldEffectIgnoreAbility(battler, TRUE) == HOLD_EFFECT_ABILITY_SHIELD) + if (GetBattlerHoldEffectIgnoreAbility(battler) == HOLD_EFFECT_ABILITY_SHIELD) break; side = (BATTLE_OPPOSITE(GetBattlerPosition(battler))) & BIT_SIDE; @@ -3640,7 +4054,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 case ABILITY_SLOW_START: if (!gSpecialStatuses[battler].switchInAbilityDone) { - gDisableStructs[battler].slowStartTimer = gBattleTurnCounter + 5; + gDisableStructs[battler].slowStartTimer = 5; gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SWITCHIN_SLOWSTART; gSpecialStatuses[battler].switchInAbilityDone = TRUE; BattleScriptPushCursorAndCallback(BattleScript_SwitchInAbilityMsg); @@ -3709,7 +4123,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 ctx.battlerAtk = i; ctx.battlerDef = battler; - ctx.move = move; + ctx.move = ctx.chosenMove = move; ctx.moveType = moveType; ctx.isAnticipation = TRUE; modifier = CalcTypeEffectivenessMultiplier(&ctx); @@ -3754,7 +4168,8 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 case ABILITY_DOWNLOAD: if (!gSpecialStatuses[battler].switchInAbilityDone) { - u32 statId, opposingBattler; + enum Stat statId; + u32 opposingBattler; u32 opposingDef = 0, opposingSpDef = 0; opposingBattler = BATTLE_OPPOSITE(battler); @@ -3884,12 +4299,12 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 } break; case ABILITY_SNOW_WARNING: - if (GetGenConfig(GEN_SNOW_WARNING) >= GEN_9 && TryChangeBattleWeather(battler, BATTLE_WEATHER_SNOW, gLastUsedAbility)) + if (GetConfig(CONFIG_SNOW_WARNING) >= GEN_9 && TryChangeBattleWeather(battler, BATTLE_WEATHER_SNOW, gLastUsedAbility)) { BattleScriptPushCursorAndCallback(BattleScript_SnowWarningActivatesSnow); effect++; } - else if (GetGenConfig(GEN_SNOW_WARNING) < GEN_9 && TryChangeBattleWeather(battler, BATTLE_WEATHER_HAIL, gLastUsedAbility)) + else if (GetConfig(CONFIG_SNOW_WARNING) < GEN_9 && TryChangeBattleWeather(battler, BATTLE_WEATHER_HAIL, gLastUsedAbility)) { BattleScriptPushCursorAndCallback(BattleScript_SnowWarningActivatesHail); effect++; @@ -3988,7 +4403,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 if (!gSpecialStatuses[battler].switchInAbilityDone && !GetBattlerPartyState(battler)->intrepidSwordBoost) { - if (GetGenConfig(GEN_INTREPID_SWORD) == GEN_9) + if (GetConfig(CONFIG_INTREPID_SWORD) == GEN_9) GetBattlerPartyState(battler)->intrepidSwordBoost = TRUE; gSpecialStatuses[battler].switchInAbilityDone = TRUE; if (CompareStat(battler, STAT_ATK, MAX_STAT_STAGE, CMP_LESS_THAN, gLastUsedAbility)) @@ -4003,7 +4418,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 if (!gSpecialStatuses[battler].switchInAbilityDone && !GetBattlerPartyState(battler)->dauntlessShieldBoost) { - if (GetGenConfig(GEN_DAUNTLESS_SHIELD) == GEN_9) + if (GetConfig(CONFIG_DAUNTLESS_SHIELD) == GEN_9) GetBattlerPartyState(battler)->dauntlessShieldBoost = TRUE; gSpecialStatuses[battler].switchInAbilityDone = TRUE; if (CompareStat(battler, STAT_DEF, MAX_STAT_STAGE, CMP_LESS_THAN, gLastUsedAbility)) @@ -4049,6 +4464,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 case ABILITY_VESSEL_OF_RUIN: if (!gSpecialStatuses[battler].switchInAbilityDone) { + gBattleMons[battler].volatiles.vesselOfRuin = TRUE; PREPARE_STAT_BUFFER(gBattleTextBuff1, STAT_SPATK); gSpecialStatuses[battler].switchInAbilityDone = TRUE; BattleScriptPushCursorAndCallback(BattleScript_RuinAbilityActivates); @@ -4058,6 +4474,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 case ABILITY_SWORD_OF_RUIN: if (!gSpecialStatuses[battler].switchInAbilityDone) { + gBattleMons[battler].volatiles.swordOfRuin = TRUE; PREPARE_STAT_BUFFER(gBattleTextBuff1, STAT_DEF); gSpecialStatuses[battler].switchInAbilityDone = TRUE; BattleScriptPushCursorAndCallback(BattleScript_RuinAbilityActivates); @@ -4067,6 +4484,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 case ABILITY_TABLETS_OF_RUIN: if (!gSpecialStatuses[battler].switchInAbilityDone) { + gBattleMons[battler].volatiles.tabletsOfRuin = TRUE; PREPARE_STAT_BUFFER(gBattleTextBuff1, STAT_ATK); gSpecialStatuses[battler].switchInAbilityDone = TRUE; BattleScriptPushCursorAndCallback(BattleScript_RuinAbilityActivates); @@ -4076,6 +4494,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 case ABILITY_BEADS_OF_RUIN: if (!gSpecialStatuses[battler].switchInAbilityDone) { + gBattleMons[battler].volatiles.beadsOfRuin = TRUE; PREPARE_STAT_BUFFER(gBattleTextBuff1, STAT_SPDEF); gSpecialStatuses[battler].switchInAbilityDone = TRUE; BattleScriptPushCursorAndCallback(BattleScript_RuinAbilityActivates); @@ -4095,15 +4514,20 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 } break; case ABILITY_COSTAR: + partner = BATTLE_PARTNER(battler); if (!gSpecialStatuses[battler].switchInAbilityDone && IsDoubleBattle() - && IsBattlerAlive(BATTLE_PARTNER(battler)) - && CountBattlerStatIncreases(BATTLE_PARTNER(battler), FALSE)) + && IsBattlerAlive(partner) + && BattlerHasCopyableChanges(partner)) { gSpecialStatuses[battler].switchInAbilityDone = TRUE; for (i = 0; i < NUM_BATTLE_STATS; i++) - gBattleMons[battler].statStages[i] = gBattleMons[BATTLE_PARTNER(battler)].statStages[i]; - gEffectBattler = BATTLE_PARTNER(battler); + gBattleMons[battler].statStages[i] = gBattleMons[partner].statStages[i]; + // Copy crit boosts (Focus Energy, Dragon Cheer, G-Max Chi Strike) + gBattleMons[battler].volatiles.focusEnergy = gBattleMons[partner].volatiles.focusEnergy; + gBattleMons[battler].volatiles.dragonCheer = gBattleMons[partner].volatiles.dragonCheer; + gBattleMons[battler].volatiles.bonusCritStages = gBattleMons[partner].volatiles.bonusCritStages; + gEffectBattler = partner; BattleScriptPushCursorAndCallback(BattleScript_CostarActivates); effect++; } @@ -4130,7 +4554,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 { gEffectBattler = partner; gSpecialStatuses[battler].switchInAbilityDone = TRUE; - gBattleStruct->moveDamage[partner] = (GetNonDynamaxMaxHP(partner) / 4) * -1; + SetHealAmount(partner, GetNonDynamaxMaxHP(partner) / 4); BattleScriptPushCursorAndCallback(BattleScript_HospitalityActivates); effect++; } @@ -4141,7 +4565,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 case ABILITY_EMBODY_ASPECT_CORNERSTONE_MASK: if (!gSpecialStatuses[battler].switchInAbilityDone) { - u32 stat; + enum Stat stat; if (gLastUsedAbility == ABILITY_EMBODY_ASPECT_HEARTHFLAME_MASK) stat = STAT_ATK; @@ -4172,17 +4596,6 @@ 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 - && !(gBattleMons[battler].volatiles.transformed)) - { - // TODO: Convert this to a proper FORM_CHANGE type. - gBattleMons[battler].species = SPECIES_EISCUE_ICE; - BattleScriptPushCursorAndCallback(BattleScript_BattlerFormChangeWithStringEnd3); - effect++; - } - break; case ABILITY_COMMANDER: partner = BATTLE_PARTNER(battler); if (!gSpecialStatuses[battler].switchInAbilityDone @@ -4206,6 +4619,8 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 effect++; } break; + default: + break; } break; case ABILITYEFFECT_ENDTURN: @@ -4220,8 +4635,8 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 && PickupHasValidTarget(battler)) { gBattlerTarget = RandomUniformExcept(RNG_PICKUP, 0, gBattlersCount - 1, CantPickupItem); - gLastUsedItem = GetUsedHeldItem(gBattlerTarget); - BattleScriptPushCursorAndCallback(BattleScript_PickupActivates); + gLastUsedItem = GetBattlerPartyState(gBattlerTarget)->usedHeldItem; + BattleScriptExecute(BattleScript_PickupActivates); effect++; } break; @@ -4229,10 +4644,10 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 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 - && GetItemPocket(GetUsedHeldItem(battler)) == POCKET_BERRIES) + && GetItemPocket(GetBattlerPartyState(battler)->usedHeldItem) == POCKET_BERRIES) { - gLastUsedItem = GetUsedHeldItem(battler); - BattleScriptPushCursorAndCallback(BattleScript_HarvestActivates); + gLastUsedItem = GetBattlerPartyState(battler)->usedHeldItem; + BattleScriptExecute(BattleScript_HarvestActivates); effect++; } break; @@ -4243,11 +4658,8 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 && gBattleMons[battler].volatiles.semiInvulnerable != STATE_UNDERWATER && !gBattleMons[battler].volatiles.healBlock) { - BattleScriptPushCursorAndCallback(BattleScript_IceBodyHeal); - gBattleStruct->moveDamage[battler] = GetNonDynamaxMaxHP(battler) / 16; - if (gBattleStruct->moveDamage[battler] == 0) - gBattleStruct->moveDamage[battler] = 1; - gBattleStruct->moveDamage[battler] *= -1; + BattleScriptExecute(BattleScript_IceBodyHeal); + SetHealAmount(battler, GetNonDynamaxMaxHP(battler) / 16); effect++; } break; @@ -4260,11 +4672,9 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 && !IsBattlerAtMaxHp(battler) && !gBattleMons[battler].volatiles.healBlock) { - BattleScriptPushCursorAndCallback(BattleScript_RainDishActivates); - gBattleStruct->moveDamage[battler] = GetNonDynamaxMaxHP(battler) / (gLastUsedAbility == ABILITY_RAIN_DISH ? 16 : 8); - if (gBattleStruct->moveDamage[battler] == 0) - gBattleStruct->moveDamage[battler] = 1; - gBattleStruct->moveDamage[battler] *= -1; + s32 healAmount = gLastUsedAbility == ABILITY_RAIN_DISH ? 16 : 8; + SetHealAmount(battler, GetNonDynamaxMaxHP(battler) / healAmount); + BattleScriptExecute(BattleScript_RainDishActivates); effect++; } break; @@ -4298,7 +4708,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 gBattleMons[battler].status1 = 0; gBattleMons[battler].volatiles.nightmare = FALSE; gBattleScripting.battler = battler; - BattleScriptPushCursorAndCallback(BattleScript_ShedSkinActivates); + BattleScriptExecute(BattleScript_ShedSkinActivates); BtlController_EmitSetMonData(battler, B_COMM_TO_CONTROLLER, REQUEST_STATUS_BATTLE, 0, 4, &gBattleMons[battler].status1); MarkBattlerForControllerExec(battler); effect++; @@ -4307,8 +4717,9 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 case ABILITY_SPEED_BOOST: if (CompareStat(battler, STAT_SPEED, MAX_STAT_STAGE, CMP_LESS_THAN, gLastUsedAbility) && gDisableStructs[battler].isFirstTurn != 2) { + SaveBattlerAttacker(gBattlerAttacker); SET_STATCHANGER(STAT_SPEED, 1, FALSE); - BattleScriptPushCursorAndCallback(BattleScript_SpeedBoostActivates); + BattleScriptExecute(BattleScript_AttackerAbilityStatRaiseEnd2); gBattleScripting.battler = battler; effect++; } @@ -4317,7 +4728,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 if (gDisableStructs[battler].isFirstTurn != 2) { u32 validToRaise = 0, validToLower = 0; - u32 statsNum = GetGenConfig(GEN_CONFIG_MOODY_STATS) >= GEN_8 ? NUM_STATS : NUM_BATTLE_STATS; + u32 statsNum = GetConfig(CONFIG_MOODY_ACC_EVASION) >= GEN_8 ? NUM_STATS : NUM_BATTLE_STATS; for (i = STAT_ATK; i < statsNum; i++) { @@ -4340,7 +4751,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 i = RandomUniformExcept(RNG_MOODY_DECREASE, STAT_ATK, statsNum - 1, MoodyCantLowerStat); SET_STATCHANGER2(gBattleScripting.savedStatChanger, i, 1, TRUE); } - BattleScriptPushCursorAndCallback(BattleScript_MoodyActivates); + BattleScriptExecute(BattleScript_MoodyActivates); effect++; } break; @@ -4348,24 +4759,22 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 gDisableStructs[gBattlerAttacker].truantCounter ^= 1; break; case ABILITY_SLOW_START: - if (gDisableStructs[battler].slowStartTimer == gBattleTurnCounter) + if (gDisableStructs[battler].slowStartTimer > 0 && --gDisableStructs[battler].slowStartTimer == 0) { BattleScriptExecute(BattleScript_SlowStartEnds); effect++; } break; case ABILITY_BAD_DREAMS: - BattleScriptPushCursorAndCallback(BattleScript_BadDreamsActivates); + BattleScriptExecute(BattleScript_BadDreamsActivates); effect++; break; case ABILITY_SOLAR_POWER: if (IsBattlerWeatherAffected(battler, B_WEATHER_SUN)) { SOLAR_POWER_HP_DROP: - BattleScriptPushCursorAndCallback(BattleScript_SolarPowerActivates); - gBattleStruct->moveDamage[battler] = GetNonDynamaxMaxHP(battler) / 8; - if (gBattleStruct->moveDamage[battler] == 0) - gBattleStruct->moveDamage[battler] = 1; + SetPassiveDamageAmount(battler, GetNonDynamaxMaxHP(battler) / 8); + BattleScriptExecute(BattleScript_SolarPowerActivates); effect++; } break; @@ -4375,7 +4784,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 && gBattleMons[gBattleScripting.battler].status1 & STATUS1_ANY && RandomPercentage(RNG_HEALER, 30)) { - BattleScriptPushCursorAndCallback(BattleScript_HealerActivates); + BattleScriptExecute(BattleScript_HealerActivates); effect++; } break; @@ -4388,7 +4797,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 if (TryBattleFormChange(battler, FORM_CHANGE_BATTLE_HP_PERCENT)) { gBattleScripting.battler = battler; - BattleScriptPushCursorAndCallback(BattleScript_BattlerFormChangeEnd3); + BattleScriptExecute(BattleScript_BattlerFormChangeEnd2); effect++; } break; @@ -4396,7 +4805,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 if (TryBattleFormChange(battler, FORM_CHANGE_BATTLE_HP_PERCENT)) { gBattleScripting.battler = battler; - BattleScriptPushCursorAndCallback(BattleScript_PowerConstruct); + BattleScriptExecute(BattleScript_PowerConstruct); effect++; } break; @@ -4411,7 +4820,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 BtlController_EmitSetMonData(battler, B_COMM_TO_CONTROLLER, REQUEST_HELDITEM_BATTLE, 0, 2, &gLastUsedItem); MarkBattlerForControllerExec(battler); gHasFetchedBall = TRUE; - BattleScriptPushCursorAndCallback(BattleScript_BallFetch); + BattleScriptExecute(BattleScript_BallFetch); effect++; } break; @@ -4421,7 +4830,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 && TryBattleFormChange(battler, FORM_CHANGE_BATTLE_TURN_END)) { gBattleScripting.battler = battler; - BattleScriptPushCursorAndCallback(BattleScript_BattlerFormChangeEnd3NoPopup); + BattleScriptExecute(BattleScript_BattlerFormChangeEnd3NoPopup); effect++; } break; @@ -4430,39 +4839,75 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 { gBattleScripting.battler = battler; gDisableStructs[battler].cudChew = FALSE; - gLastUsedItem = gBattleStruct->usedHeldItems[gBattlerPartyIndexes[battler]][GetBattlerSide(battler)]; - gBattleStruct->usedHeldItems[gBattlerPartyIndexes[battler]][GetBattlerSide(battler)] = ITEM_NONE; - BattleScriptPushCursorAndCallback(BattleScript_CudChewActivates); + gLastUsedItem = GetBattlerPartyState(battler)->usedHeldItem; + GetBattlerPartyState(battler)->usedHeldItem = ITEM_NONE; + BattleScriptExecute(BattleScript_CudChewActivates); effect++; } - else if (!gDisableStructs[battler].cudChew && GetItemPocket(GetUsedHeldItem(battler)) == POCKET_BERRIES) + else if (!gDisableStructs[battler].cudChew && GetItemPocket(GetBattlerPartyState(battler)->usedHeldItem) == POCKET_BERRIES) { gDisableStructs[battler].cudChew = TRUE; } break; + default: + break; } } break; + case ABILITYEFFECT_COLOR_CHANGE: + switch (gLastUsedAbility) + { + case ABILITY_COLOR_CHANGE: + if (IsBattlerTurnDamaged(battler) + && IsBattlerAlive(battler) + && !IS_BATTLER_OF_TYPE(battler, moveType) + && move != MOVE_STRUGGLE + && moveType != TYPE_STELLAR + && moveType != TYPE_MYSTERY) + { + gEffectBattler = gBattlerAbility = battler; + SET_BATTLER_TYPE(battler, moveType); + PREPARE_TYPE_BUFFER(gBattleTextBuff1, moveType); + BattleScriptCall(BattleScript_ColorChangeActivates); + effect++; + } + break; + case ABILITY_BERSERK: + if (IsBattlerTurnDamaged(battler) + && IsBattlerAlive(battler) + && HadMoreThanHalfHpNowDoesnt(battler) + && CompareStat(battler, STAT_SPATK, MAX_STAT_STAGE, CMP_LESS_THAN, gLastUsedAbility)) + { + gEffectBattler = gBattlerAbility = battler; + SET_STATCHANGER(STAT_SPATK, 1, FALSE); + BattleScriptCall(BattleScript_BerserkActivates); + effect++; + } + break; + case ABILITY_ANGER_SHELL: + if (IsBattlerTurnDamaged(battler) + && IsBattlerAlive(battler) + && HadMoreThanHalfHpNowDoesnt(battler)) + { + gEffectBattler = gBattlerAbility = battler; + BattleScriptCall(BattleScript_AngerShellActivates); + effect++; + } + break; + default: + break; + } + break; case ABILITYEFFECT_MOVE_END: // Think contact abilities. switch (gLastUsedAbility) { - case ABILITY_STICKY_HOLD: - if (gBattleStruct->battlerState[gBattlerTarget].itemCanBeKnockedOff && IsBattlerAlive(gBattlerTarget)) - { - gBattleStruct->battlerState[gBattlerTarget].itemCanBeKnockedOff = FALSE; - gBattlerAbility = gBattlerTarget; - BattleScriptPushCursor(); - gBattlescriptCurrInstr = BattleScript_StickyHoldActivates; - effect++; - } - break; case ABILITY_JUSTIFIED: if (IsBattlerTurnDamaged(battler) && IsBattlerAlive(battler) && moveType == TYPE_DARK && CompareStat(battler, STAT_ATK, MAX_STAT_STAGE, CMP_LESS_THAN, gLastUsedAbility)) { - gEffectBattler = battler; + gEffectBattler = gBattlerAbility = battler; SET_STATCHANGER(STAT_ATK, 1, FALSE); BattleScriptCall(BattleScript_TargetAbilityStatRaiseRet); effect++; @@ -4474,7 +4919,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 && (moveType == TYPE_DARK || moveType == TYPE_BUG || moveType == TYPE_GHOST) && CompareStat(battler, STAT_SPEED, MAX_STAT_STAGE, CMP_LESS_THAN, gLastUsedAbility)) { - gEffectBattler = battler; + gEffectBattler = gBattlerAbility = battler; SET_STATCHANGER(STAT_SPEED, 1, FALSE); BattleScriptCall(BattleScript_TargetAbilityStatRaiseRet); effect++; @@ -4486,7 +4931,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 && moveType == TYPE_WATER && CompareStat(battler, STAT_DEF, MAX_STAT_STAGE, CMP_LESS_THAN, gLastUsedAbility)) { - gEffectBattler = battler; + gEffectBattler = gBattlerAbility = battler; SET_STATCHANGER(STAT_DEF, 2, FALSE); BattleScriptCall(BattleScript_TargetAbilityStatRaiseRet); effect++; @@ -4498,26 +4943,12 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 && IsBattlerAlive(battler) && CompareStat(battler, STAT_DEF, MAX_STAT_STAGE, CMP_LESS_THAN, gLastUsedAbility)) { - gEffectBattler = battler; + gEffectBattler = gBattlerAbility = battler; SET_STATCHANGER(STAT_DEF, 1, FALSE); BattleScriptCall(BattleScript_TargetAbilityStatRaiseRet); effect++; } break; - case ABILITY_BERSERK: - if (IsBattlerTurnDamaged(battler) - && IsBattlerAlive(battler) - && HadMoreThanHalfHpNowDoesnt(battler) - && (gMultiHitCounter == 0 || gMultiHitCounter == 1) - && !(TestIfSheerForceAffected(gBattlerAttacker, gCurrentMove)) - && CompareStat(battler, STAT_SPATK, MAX_STAT_STAGE, CMP_LESS_THAN, gLastUsedAbility)) - { - gEffectBattler = battler; - SET_STATCHANGER(STAT_SPATK, 1, FALSE); - BattleScriptCall(BattleScript_TargetAbilityStatRaiseRet); - effect++; - } - break; case ABILITY_WEAK_ARMOR: if (IsBattlerTurnDamaged(battler) && IsBattlerAlive(battler) @@ -4551,18 +4982,19 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 case ABILITY_MUMMY: if (IsBattlerAlive(gBattlerAttacker) && IsBattlerTurnDamaged(gBattlerTarget) - && !CanBattlerAvoidContactEffects(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerAttacker), GetBattlerHoldEffect(gBattlerAttacker, TRUE), move) + && !CanBattlerAvoidContactEffects(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerAttacker), GetBattlerHoldEffect(gBattlerAttacker), move) && gDisableStructs[gBattlerAttacker].overwrittenAbility != GetBattlerAbility(gBattlerTarget) && gBattleMons[gBattlerAttacker].ability != ABILITY_MUMMY && gBattleMons[gBattlerAttacker].ability != ABILITY_LINGERING_AROMA && !gAbilitiesInfo[gBattleMons[gBattlerAttacker].ability].cantBeSuppressed) { - if (GetBattlerHoldEffectIgnoreAbility(gBattlerAttacker, TRUE) == HOLD_EFFECT_ABILITY_SHIELD) + if (GetBattlerHoldEffectIgnoreAbility(gBattlerAttacker) == HOLD_EFFECT_ABILITY_SHIELD) { RecordItemEffectBattle(gBattlerAttacker, HOLD_EFFECT_ABILITY_SHIELD); break; } + RemoveAbilityFlags(gBattlerAttacker); gLastUsedAbility = gBattleMons[gBattlerAttacker].ability; gBattleMons[gBattlerAttacker].ability = gDisableStructs[gBattlerAttacker].overwrittenAbility = gBattleMons[gBattlerTarget].ability; BattleScriptCall(BattleScript_MummyActivates); @@ -4573,21 +5005,22 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 case ABILITY_WANDERING_SPIRIT: if (IsBattlerAlive(gBattlerAttacker) && IsBattlerTurnDamaged(gBattlerTarget) - && !CanBattlerAvoidContactEffects(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerAttacker), GetBattlerHoldEffect(gBattlerAttacker, TRUE), move) + && !CanBattlerAvoidContactEffects(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerAttacker), GetBattlerHoldEffect(gBattlerAttacker), move) && !(GetActiveGimmick(gBattlerTarget) == GIMMICK_DYNAMAX) && !gAbilitiesInfo[gBattleMons[gBattlerAttacker].ability].cantBeSwapped) { - if (GetBattlerHoldEffectIgnoreAbility(gBattlerAttacker, TRUE) == HOLD_EFFECT_ABILITY_SHIELD) + if (GetBattlerHoldEffectIgnoreAbility(gBattlerAttacker) == HOLD_EFFECT_ABILITY_SHIELD) { RecordItemEffectBattle(gBattlerAttacker, HOLD_EFFECT_ABILITY_SHIELD); break; } - if (GetBattlerHoldEffectIgnoreAbility(gBattlerTarget, TRUE) == HOLD_EFFECT_ABILITY_SHIELD) + if (GetBattlerHoldEffectIgnoreAbility(gBattlerTarget) == HOLD_EFFECT_ABILITY_SHIELD) { RecordItemEffectBattle(gBattlerTarget, HOLD_EFFECT_ABILITY_SHIELD); break; } + RemoveAbilityFlags(gBattlerAttacker); gLastUsedAbility = gBattleMons[gBattlerAttacker].ability; gBattleMons[gBattlerAttacker].ability = gDisableStructs[gBattlerAttacker].overwrittenAbility = gBattleMons[gBattlerTarget].ability; gBattleMons[gBattlerTarget].ability = gDisableStructs[gBattlerTarget].overwrittenAbility = gLastUsedAbility; @@ -4607,33 +5040,17 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 effect++; } break; - case ABILITY_COLOR_CHANGE: - if (move != MOVE_STRUGGLE - && !IsBattleMoveStatus(move) - && IsBattlerTurnDamaged(battler) - && !IS_BATTLER_OF_TYPE(battler, moveType) - && moveType != TYPE_STELLAR - && moveType != TYPE_MYSTERY - && IsBattlerAlive(battler)) - { - SET_BATTLER_TYPE(battler, moveType); - PREPARE_TYPE_BUFFER(gBattleTextBuff1, moveType); - BattleScriptCall(BattleScript_ColorChangeActivates); - effect++; - } - break; case ABILITY_GOOEY: case ABILITY_TANGLING_HAIR: if (IsBattlerAlive(gBattlerAttacker) && (CompareStat(gBattlerAttacker, STAT_SPEED, MIN_STAT_STAGE, CMP_GREATER_THAN, gLastUsedAbility) || GetBattlerAbility(gBattlerAttacker) == ABILITY_MIRROR_ARMOR) && !gProtectStructs[gBattlerAttacker].confusionSelfDmg && IsBattlerTurnDamaged(gBattlerTarget) - && !CanBattlerAvoidContactEffects(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerAttacker), GetBattlerHoldEffect(gBattlerAttacker, TRUE), move)) + && !CanBattlerAvoidContactEffects(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerAttacker), GetBattlerHoldEffect(gBattlerAttacker), move)) { SET_STATCHANGER(STAT_SPEED, 1, TRUE); PREPARE_ABILITY_BUFFER(gBattleTextBuff1, gLastUsedAbility); BattleScriptCall(BattleScript_GooeyActivates); - gHitMarker |= HITMARKER_STATUS_ABILITY_EFFECT; effect++; } break; @@ -4642,11 +5059,9 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 if (IsBattlerAlive(gBattlerAttacker) && !gProtectStructs[gBattlerAttacker].confusionSelfDmg && IsBattlerTurnDamaged(gBattlerTarget) - && !CanBattlerAvoidContactEffects(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerAttacker), GetBattlerHoldEffect(gBattlerAttacker, TRUE), move)) + && !CanBattlerAvoidContactEffects(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerAttacker), GetBattlerHoldEffect(gBattlerAttacker), move)) { - gBattleStruct->moveDamage[gBattlerAttacker] = GetNonDynamaxMaxHP(gBattlerAttacker) / (B_ROUGH_SKIN_DMG >= GEN_4 ? 8 : 16); - if (gBattleStruct->moveDamage[gBattlerAttacker] == 0) - gBattleStruct->moveDamage[gBattlerAttacker] = 1; + SetPassiveDamageAmount(gBattlerAttacker, GetNonDynamaxMaxHP(gBattlerAttacker) / (B_ROUGH_SKIN_DMG >= GEN_4 ? 8 : 16)); PREPARE_ABILITY_BUFFER(gBattleTextBuff1, gLastUsedAbility); BattleScriptCall(BattleScript_RoughSkinActivates); effect++; @@ -4656,7 +5071,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 if (!(gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_NO_EFFECT) && !IsBattlerAlive(gBattlerTarget) && IsBattlerAlive(gBattlerAttacker) - && !CanBattlerAvoidContactEffects(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerAttacker), GetBattlerHoldEffect(gBattlerAttacker, TRUE), move)) + && !CanBattlerAvoidContactEffects(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerAttacker), GetBattlerHoldEffect(gBattlerAttacker), move)) { if ((battler = IsAbilityOnField(ABILITY_DAMP))) { @@ -4666,9 +5081,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 else { gBattleScripting.battler = gBattlerTarget; - gBattleStruct->moveDamage[gBattlerAttacker] = GetNonDynamaxMaxHP(gBattlerAttacker) / 4; - if (gBattleStruct->moveDamage[gBattlerAttacker] == 0) - gBattleStruct->moveDamage[gBattlerAttacker] = 1; + SetPassiveDamageAmount(gBattlerAttacker, GetNonDynamaxMaxHP(gBattlerAttacker) / 4); BattleScriptCall(BattleScript_AftermathDmg); } effect++; @@ -4684,15 +5097,15 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 break; gBattleScripting.battler = gBattlerTarget; - gBattleStruct->moveDamage[gBattlerAttacker] = gBattleStruct->moveDamage[gBattlerTarget]; + SetPassiveDamageAmount(gBattlerAttacker, gBattleStruct->moveDamage[gBattlerTarget]); BattleScriptCall(BattleScript_AftermathDmg); effect++; } break; case ABILITY_EFFECT_SPORE: { - u32 abilityAtk = GetBattlerAbility(gBattlerAttacker); - enum ItemHoldEffect holdEffectAtk = GetBattlerHoldEffect(gBattlerAttacker, TRUE); + enum Ability abilityAtk = GetBattlerAbility(gBattlerAttacker); + enum HoldEffect holdEffectAtk = GetBattlerHoldEffect(gBattlerAttacker); if (IsAffectedByPowderMove(gBattlerAttacker, abilityAtk, holdEffectAtk)) { u32 poison, paralysis, sleep; @@ -4739,12 +5152,12 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 { POISON_POINT: { - u32 abilityAtk = GetBattlerAbility(gBattlerAttacker); + enum Ability abilityAtk = GetBattlerAbility(gBattlerAttacker); if (IsBattlerAlive(gBattlerAttacker) && !gProtectStructs[gBattlerAttacker].confusionSelfDmg && IsBattlerTurnDamaged(gBattlerTarget) && CanBePoisoned(gBattlerTarget, gBattlerAttacker, gLastUsedAbility, abilityAtk) - && !CanBattlerAvoidContactEffects(gBattlerAttacker, gBattlerTarget, abilityAtk, GetBattlerHoldEffect(gBattlerAttacker, TRUE), move)) + && !CanBattlerAvoidContactEffects(gBattlerAttacker, gBattlerTarget, abilityAtk, GetBattlerHoldEffect(gBattlerAttacker), move)) { gEffectBattler = gBattlerAttacker; gBattleScripting.battler = gBattlerTarget; @@ -4761,12 +5174,12 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 { STATIC: { - u32 abilityAtk = GetBattlerAbility(gBattlerAttacker); + enum Ability abilityAtk = GetBattlerAbility(gBattlerAttacker); if (IsBattlerAlive(gBattlerAttacker) && !gProtectStructs[gBattlerAttacker].confusionSelfDmg && IsBattlerTurnDamaged(gBattlerTarget) && CanBeParalyzed(gBattlerTarget, gBattlerAttacker, abilityAtk) - && !CanBattlerAvoidContactEffects(gBattlerAttacker, gBattlerTarget, abilityAtk, GetBattlerHoldEffect(gBattlerAttacker, TRUE), move)) + && !CanBattlerAvoidContactEffects(gBattlerAttacker, gBattlerTarget, abilityAtk, GetBattlerHoldEffect(gBattlerAttacker), move)) { gEffectBattler = gBattlerAttacker; gBattleScripting.battler = gBattlerTarget; @@ -4781,7 +5194,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 case ABILITY_FLAME_BODY: if (IsBattlerAlive(gBattlerAttacker) && !gProtectStructs[gBattlerAttacker].confusionSelfDmg - && !CanBattlerAvoidContactEffects(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerAttacker), GetBattlerHoldEffect(gBattlerAttacker, TRUE), move) + && !CanBattlerAvoidContactEffects(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerAttacker), GetBattlerHoldEffect(gBattlerAttacker), move) && IsBattlerTurnDamaged(gBattlerTarget) && CanBeBurned(gBattlerTarget, gBattlerAttacker, GetBattlerAbility(gBattlerAttacker)) && (B_ABILITY_TRIGGER_CHANCE >= GEN_4 ? RandomPercentage(RNG_FLAME_BODY, 30) : RandomChance(RNG_FLAME_BODY, 1, 3))) @@ -4803,7 +5216,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 && !(gBattleMons[gBattlerAttacker].volatiles.infatuation) && AreBattlersOfOppositeGender(gBattlerAttacker, gBattlerTarget) && !IsAbilityAndRecord(gBattlerAttacker, GetBattlerAbility(gBattlerAttacker), ABILITY_OBLIVIOUS) - && !CanBattlerAvoidContactEffects(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerAttacker), GetBattlerHoldEffect(gBattlerAttacker, TRUE), move) + && !CanBattlerAvoidContactEffects(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerAttacker), GetBattlerHoldEffect(gBattlerAttacker), move) && !IsAbilityOnSide(gBattlerAttacker, ABILITY_AROMA_VEIL)) { gBattleMons[gBattlerAttacker].volatiles.infatuation = INFATUATED_WITH(gBattlerTarget); @@ -4835,7 +5248,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 && CompareStat(battler, STAT_SPEED, MAX_STAT_STAGE, CMP_LESS_THAN, gLastUsedAbility) && (moveType == TYPE_FIRE || moveType == TYPE_WATER)) { - gEffectBattler = battler; + gEffectBattler = gBattlerAbility = battler; SET_STATCHANGER(STAT_SPEED, 6, FALSE); BattleScriptCall(BattleScript_TargetAbilityStatRaiseRet); effect++; @@ -4863,7 +5276,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 if (!gProtectStructs[gBattlerAttacker].confusionSelfDmg && IsBattlerTurnDamaged(gBattlerTarget) && IsBattlerAlive(battler) - && !CanBattlerAvoidContactEffects(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerAttacker), GetBattlerHoldEffect(gBattlerAttacker, TRUE), move) + && !CanBattlerAvoidContactEffects(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerAttacker), GetBattlerHoldEffect(gBattlerAttacker), move) && !gBattleMons[gBattlerAttacker].volatiles.perishSong) { if (!gBattleMons[battler].volatiles.perishSong) @@ -4883,14 +5296,10 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 && IsBattlerAlive(gBattlerAttacker) && gBattleMons[gBattlerTarget].species != SPECIES_CRAMORANT) { - if (GetBattlerAbility(gBattlerAttacker) != ABILITY_MAGIC_GUARD) - { - gBattleStruct->moveDamage[gBattlerAttacker] = GetNonDynamaxMaxHP(gBattlerAttacker) / 4; - if (gBattleStruct->moveDamage[gBattlerAttacker] == 0) - gBattleStruct->moveDamage[gBattlerAttacker] = 1; - } + if (!IsAbilityAndRecord(gBattlerAttacker, GetBattlerAbility(gBattlerAttacker), ABILITY_MAGIC_GUARD)) + SetPassiveDamageAmount(gBattlerAttacker, GetNonDynamaxMaxHP(gBattlerAttacker) / 4); - switch(gBattleMons[gBattlerTarget].species) + switch (gBattleMons[gBattlerTarget].species) { case SPECIES_CRAMORANT_GORGING: TryBattleFormChange(battler, FORM_CHANGE_HIT_BY_MOVE); @@ -4921,24 +5330,12 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 && CompareStat(gBattlerTarget, STAT_ATK, MAX_STAT_STAGE, CMP_LESS_THAN, gLastUsedAbility) && moveType == TYPE_FIRE) { - gEffectBattler = gBattlerTarget; + gEffectBattler = gBattlerAbility = gBattlerTarget; SET_STATCHANGER(STAT_ATK, 1, FALSE); BattleScriptCall(BattleScript_TargetAbilityStatRaiseRet); effect++; } break; - case ABILITY_ANGER_SHELL: - if (!gProtectStructs[gBattlerAttacker].confusionSelfDmg - && IsBattlerTurnDamaged(gBattlerTarget) - && (gMultiHitCounter == 0 || gMultiHitCounter == 1) // Activates after all hits from a multi-hit move. - && IsBattlerAlive(gBattlerTarget) - && HadMoreThanHalfHpNowDoesnt(gBattlerTarget) - && !(TestIfSheerForceAffected(gBattlerAttacker, gCurrentMove))) - { - BattleScriptCall(BattleScript_AngerShellActivates); - effect++; - } - break; case ABILITY_WIND_POWER: if (!IsWindMove(gCurrentMove)) break; @@ -4967,6 +5364,8 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 effect++; } break; + default: + break; } break; case ABILITYEFFECT_MOVE_END_ATTACKER: // Same as above, but for attacker @@ -4976,7 +5375,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 if (IsBattlerAlive(gBattlerTarget) && !gProtectStructs[gBattlerAttacker].confusionSelfDmg && CanBePoisoned(gBattlerAttacker, gBattlerTarget, gLastUsedAbility, GetBattlerAbility(gBattlerTarget)) - && !CanBattlerAvoidContactEffects(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerAttacker), GetBattlerHoldEffect(gBattlerAttacker, TRUE), move) + && !CanBattlerAvoidContactEffects(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerAttacker), GetBattlerHoldEffect(gBattlerAttacker), move) && IsBattlerTurnDamaged(gBattlerTarget) // Need to actually hit the target && RandomPercentage(RNG_POISON_TOUCH, 30)) { @@ -4989,13 +5388,9 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 } break; case ABILITY_TOXIC_CHAIN: - if (!(gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_NO_EFFECT) - && IsBattlerAlive(gBattlerTarget) - && !gProtectStructs[gBattlerAttacker].confusionSelfDmg - && CanBePoisoned(gBattlerAttacker, gBattlerTarget, gLastUsedAbility, GetBattlerAbility(gBattlerTarget)) - && IsBattlerTurnDamaged(gBattlerTarget) // Need to actually hit the target - && RandomWeighted(RNG_TOXIC_CHAIN, 7, 3)) + if (gBattleStruct->toxicChainPriority) { + gBattleStruct->toxicChainPriority = FALSE; gEffectBattler = gBattlerTarget; gBattleScripting.battler = gBattlerAttacker; gBattleScripting.moveEffect = MOVE_EFFECT_TOXIC; @@ -5011,10 +5406,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 && IsBattlerTurnDamaged(gBattlerTarget) && !MoveHasAdditionalEffect(gCurrentMove, MOVE_EFFECT_FLINCH)) { - gBattleScripting.moveEffect = MOVE_EFFECT_FLINCH; - BattleScriptPushCursor(); - SetMoveEffect(gBattlerAttacker, gBattlerTarget, FALSE, FALSE); - BattleScriptPop(); + SetMoveEffect(gBattlerAttacker, gBattlerTarget, MOVE_EFFECT_FLINCH, gBattlescriptCurrInstr, EFFECT_PRIMARY); effect++; } break; @@ -5037,10 +5429,11 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 gBattleScripting.moveEffect = MOVE_EFFECT_CONFUSION; PREPARE_ABILITY_BUFFER(gBattleTextBuff1, gLastUsedAbility); BattleScriptCall(BattleScript_AbilityStatusEffect); - gHitMarker |= HITMARKER_STATUS_ABILITY_EFFECT; effect++; } break; + default: + break; } break; case ABILITYEFFECT_MOVE_END_OTHER: // Abilities that activate on *another* battler's moveend: Dancer, Soul-Heart, Receiver, Symbiosis @@ -5061,39 +5454,36 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 // Set the target to the original target of the mon that first used a Dance move gBattlerTarget = gBattleScripting.savedBattler & 0x3; - // Edge case for dance moves that hit multiply targets - gHitMarker &= ~HITMARKER_NO_ATTACKSTRING; - // Make sure that the target isn't an ally - if it is, target the original user if (IsBattlerAlly(gBattlerTarget, gBattlerAttacker)) gBattlerTarget = (gBattleScripting.savedBattler & 0xF0) >> 4; - gHitMarker &= ~HITMARKER_ATTACKSTRING_PRINTED; BattleScriptExecute(BattleScript_DancerActivates); effect++; } break; + default: + break; } break; case ABILITYEFFECT_OPPORTUNIST: - /* Similar to ABILITYEFFECT_IMMUNITY in that it loops through all battlers. - * Is called after ABILITYEFFECT_ON_SWITCHIN to copy any boosts - * from switch in abilities e.g. intrepid sword, as - */ - for (battler = 0; battler < gBattlersCount; battler++) + case ABILITYEFFECT_OPPORTUNIST_FIRST_TURN: + switch (ability) { - switch (GetBattlerAbility(battler)) + case ABILITY_OPPORTUNIST: + if (gProtectStructs[battler].activateOpportunist == 2) { - case ABILITY_OPPORTUNIST: - if (gProtectStructs[battler].activateOpportunist == 2) - { - gBattleScripting.battler = battler; - gProtectStructs[battler].activateOpportunist--; - ChooseStatBoostAnimation(battler); - BattleScriptPushCursorAndCallback(BattleScript_OpportunistCopyStatChange); - effect = 1; - } - break; + gBattleScripting.battler = battler; + gProtectStructs[battler].activateOpportunist--; + ChooseStatBoostAnimation(battler); + if (caseID == ABILITYEFFECT_OPPORTUNIST_FIRST_TURN) + BattleScriptPushCursorAndCallback(BattleScript_OpportunistCopyStatChangeEnd3); + else + BattleScriptCall(BattleScript_OpportunistCopyStatChange); + effect = 1; } + break; + default: + break; } break; case ABILITYEFFECT_IMMUNITY: @@ -5169,55 +5559,44 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 break; case ABILITYEFFECT_NEUTRALIZINGGAS: + case ABILITYEFFECT_NEUTRALIZINGGAS_FIRST_TURN: // Prints message only. separate from ABILITYEFFECT_ON_SWITCHIN bc activates before entry hazards - for (i = 0; i < gBattlersCount; i++) + if (gLastUsedAbility == ABILITY_NEUTRALIZING_GAS && !gDisableStructs[battler].neutralizingGas) { - if (gBattleMons[i].ability == ABILITY_NEUTRALIZING_GAS && !gDisableStructs[i].neutralizingGas) - { - gDisableStructs[i].neutralizingGas = TRUE; - gBattlerAbility = i; - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SWITCHIN_NEUTRALIZING_GAS; + gDisableStructs[battler].neutralizingGas = TRUE; + gBattlerAbility = battler; + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SWITCHIN_NEUTRALIZING_GAS; + if (caseID == ABILITYEFFECT_NEUTRALIZINGGAS_FIRST_TURN) BattleScriptPushCursorAndCallback(BattleScript_SwitchInAbilityMsg); - effect++; - } - - if (effect != 0) - break; + else + BattleScriptCall(BattleScript_SwitchInAbilityMsgRet); + effect++; } break; case ABILITYEFFECT_ON_WEATHER: // For ability effects that activate when the battle weather changes. + if (!IsBattlerAlive(battler)) + return effect; gLastUsedAbility = GetBattlerAbility(battler); switch (gLastUsedAbility) { case ABILITY_FORECAST: case ABILITY_FLOWER_GIFT: - if ((IsBattlerWeatherAffected(battler, gBattleWeather) + case ABILITY_ICE_FACE: + { + u32 battlerWeatherAffected = IsBattlerWeatherAffected(battler, gBattleWeather); + if (battlerWeatherAffected && !CanBattlerFormChange(battler, FORM_CHANGE_BATTLE_WEATHER)) + { + // If Hail/Snow activates when in Eiscue is in base, prevent reversion when Eiscue Noice gets broken + gDisableStructs[battler].weatherAbilityDone = TRUE; + } + + if (((!gDisableStructs[battler].weatherAbilityDone && battlerWeatherAffected) || gBattleWeather == B_WEATHER_NONE || !HasWeatherEffect()) // Air Lock active && TryBattleFormChange(battler, FORM_CHANGE_BATTLE_WEATHER)) { gBattleScripting.battler = battler; - BattleScriptPushCursorAndCallback(BattleScript_BattlerFormChangeWithStringEnd3); - effect++; - } - break; - case ABILITY_ICE_FACE: - { - u32 battlerWeatherAffected = IsBattlerWeatherAffected(battler, B_WEATHER_HAIL | B_WEATHER_SNOW); - if (battlerWeatherAffected && gBattleMons[battler].species == SPECIES_EISCUE) - { - // If Hail/Snow activates when in Eiscue is in base, prevent reversion when Eiscue Noice gets broken gDisableStructs[battler].weatherAbilityDone = TRUE; - } - if (!gDisableStructs[battler].weatherAbilityDone - && battlerWeatherAffected - && gBattleMons[battler].species == SPECIES_EISCUE_NOICE - && !(gBattleMons[battler].volatiles.transformed)) - { - // TODO: Convert this to a proper FORM_CHANGE type. - gBattleScripting.battler = battler; - gDisableStructs[battler].weatherAbilityDone = TRUE; - gBattleMons[battler].species = SPECIES_EISCUE_ICE; BattleScriptPushCursorAndCallback(BattleScript_BattlerFormChangeWithStringEnd3); effect++; } @@ -5230,15 +5609,20 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 && !gDisableStructs[battler].boosterEnergyActivated) { gDisableStructs[battler].weatherAbilityDone = TRUE; - PREPARE_STAT_BUFFER(gBattleTextBuff1, GetHighestStatId(battler)); + gDisableStructs[battler].paradoxBoostedStat = GetParadoxHighestStatId(battler); + PREPARE_STAT_BUFFER(gBattleTextBuff1, gDisableStructs[battler].paradoxBoostedStat); gBattleScripting.battler = battler; BattleScriptPushCursorAndCallback(BattleScript_ProtosynthesisActivates); effect++; } break; + default: + break; } break; case ABILITYEFFECT_ON_TERRAIN: // For ability effects that activate when the field terrain changes. + if (!IsBattlerAlive(battler)) + return effect; gLastUsedAbility = GetBattlerAbility(battler); switch (gLastUsedAbility) { @@ -5259,12 +5643,15 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 && !gDisableStructs[battler].boosterEnergyActivated) { gDisableStructs[battler].terrainAbilityDone = TRUE; - PREPARE_STAT_BUFFER(gBattleTextBuff1, GetHighestStatId(battler)); + gDisableStructs[battler].paradoxBoostedStat = GetParadoxHighestStatId(battler); + PREPARE_STAT_BUFFER(gBattleTextBuff1, gDisableStructs[battler].paradoxBoostedStat); gBattlerAbility = gBattleScripting.battler = battler; BattleScriptPushCursorAndCallback(BattleScript_QuarkDriveActivates); effect++; } break; + default: + break; } break; } @@ -5279,7 +5666,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 bool32 TryPrimalReversion(u32 battler) { - if (GetBattlerHoldEffect(battler, FALSE) == HOLD_EFFECT_PRIMAL_ORB + if (GetBattlerHoldEffectIgnoreNegation(battler) == HOLD_EFFECT_PRIMAL_ORB && GetBattleFormChangeTargetSpecies(battler, FORM_CHANGE_BATTLE_PRIMAL_REVERSION) != gBattleMons[battler].species) { gBattleScripting.battler = battler; @@ -5295,14 +5682,14 @@ bool32 IsNeutralizingGasOnField(void) for (i = 0; i < gBattlersCount; i++) { - if (IsBattlerAlive(i) && gBattleMons[i].ability == ABILITY_NEUTRALIZING_GAS && !gBattleMons[i].volatiles.gastroAcid) + if (gDisableStructs[i].neutralizingGas && !gBattleMons[i].volatiles.gastroAcid) return TRUE; } return FALSE; } -bool32 IsMoldBreakerTypeAbility(u32 battler, u32 ability) +bool32 IsMoldBreakerTypeAbility(u32 battler, enum Ability ability) { if (gBattleMons[battler].volatiles.gastroAcid) return FALSE; @@ -5319,17 +5706,11 @@ bool32 IsMoldBreakerTypeAbility(u32 battler, u32 ability) return FALSE; } -static inline bool32 CanBreakThroughAbility(u32 battlerAtk, u32 battlerDef, u32 ability, u32 hasAbilityShield, u32 ignoreMoldBreaker) +static inline bool32 CanBreakThroughAbility(u32 battlerAtk, u32 battlerDef, u32 hasAbilityShield, u32 ignoreMoldBreaker) { - if (hasAbilityShield || ignoreMoldBreaker) + if (hasAbilityShield || ignoreMoldBreaker || battlerDef == battlerAtk) return FALSE; - - return ((IsMoldBreakerTypeAbility(battlerAtk, ability) || MoveIgnoresTargetAbility(gCurrentMove)) - && battlerDef != battlerAtk - && gAbilitiesInfo[gBattleMons[battlerDef].ability].breakable - && gBattlerByTurnOrder[gCurrentTurnActionNumber] == battlerAtk - && gActionsByTurnOrder[gCurrentTurnActionNumber] == B_ACTION_USE_MOVE - && gCurrentTurnActionNumber < gBattlersCount); + return gBattleStruct->moldBreakerActive && gAbilitiesInfo[gBattleMons[battlerDef].ability].breakable; } u32 GetBattlerAbilityNoAbilityShield(u32 battler) @@ -5342,14 +5723,14 @@ u32 GetBattlerAbilityIgnoreMoldBreaker(u32 battler) return GetBattlerAbilityInternal(battler, TRUE, FALSE); } -u32 GetBattlerAbility(u32 battler) +enum Ability GetBattlerAbility(u32 battler) { return GetBattlerAbilityInternal(battler, FALSE, FALSE); } u32 GetBattlerAbilityInternal(u32 battler, u32 ignoreMoldBreaker, u32 noAbilityShield) { - bool32 hasAbilityShield = !noAbilityShield && GetBattlerHoldEffectIgnoreAbility(battler, TRUE) == HOLD_EFFECT_ABILITY_SHIELD; + bool32 hasAbilityShield = !noAbilityShield && GetBattlerHoldEffectIgnoreAbility(battler) == HOLD_EFFECT_ABILITY_SHIELD; bool32 abilityCantBeSuppressed = gAbilitiesInfo[gBattleMons[battler].ability].cantBeSuppressed; if (abilityCantBeSuppressed) @@ -5360,7 +5741,7 @@ u32 GetBattlerAbilityInternal(u32 battler, u32 ignoreMoldBreaker, u32 noAbilityS && gBattleMons[battler].ability == ABILITY_COMATOSE) return ABILITY_NONE; - if (CanBreakThroughAbility(gBattlerAttacker, battler, gBattleMons[gBattlerAttacker].ability, hasAbilityShield, ignoreMoldBreaker)) + if (CanBreakThroughAbility(gBattlerAttacker, battler, hasAbilityShield, ignoreMoldBreaker)) return ABILITY_NONE; return gBattleMons[battler].ability; @@ -5371,16 +5752,16 @@ u32 GetBattlerAbilityInternal(u32 battler, u32 ignoreMoldBreaker, u32 noAbilityS if (!hasAbilityShield && IsNeutralizingGasOnField() - && gBattleMons[battler].ability != ABILITY_NEUTRALIZING_GAS) + && (gBattleMons[battler].ability != ABILITY_NEUTRALIZING_GAS || gBattleMons[battler].volatiles.gastroAcid)) return ABILITY_NONE; - if (CanBreakThroughAbility(gBattlerAttacker, battler, gBattleMons[gBattlerAttacker].ability, hasAbilityShield, ignoreMoldBreaker)) + if (CanBreakThroughAbility(gBattlerAttacker, battler, hasAbilityShield, ignoreMoldBreaker)) return ABILITY_NONE; return gBattleMons[battler].ability; } -u32 IsAbilityOnSide(u32 battler, u32 ability) +u32 IsAbilityOnSide(u32 battler, enum Ability ability) { if (IsBattlerAlive(battler) && GetBattlerAbility(battler) == ability) return battler + 1; @@ -5390,12 +5771,12 @@ u32 IsAbilityOnSide(u32 battler, u32 ability) return 0; } -u32 IsAbilityOnOpposingSide(u32 battler, u32 ability) +u32 IsAbilityOnOpposingSide(u32 battler, enum Ability ability) { return IsAbilityOnSide(BATTLE_OPPOSITE(battler), ability); } -u32 IsAbilityOnField(u32 ability) +u32 IsAbilityOnField(enum Ability ability) { u32 i; @@ -5408,7 +5789,7 @@ u32 IsAbilityOnField(u32 ability) return 0; } -u32 IsAbilityOnFieldExcept(u32 battler, u32 ability) +u32 IsAbilityOnFieldExcept(u32 battler, enum Ability ability) { u32 i; @@ -5426,17 +5807,18 @@ u32 IsAbilityPreventingEscape(u32 battler) if (B_GHOSTS_ESCAPE >= GEN_6 && IS_BATTLER_OF_TYPE(battler, TYPE_GHOST)) return 0; + bool32 isBattlerGrounded = IsBattlerGrounded(battler, GetBattlerAbility(battler), GetBattlerHoldEffect(battler)); for (u32 battlerDef = 0; battlerDef < gBattlersCount; battlerDef++) { if (battler == battlerDef || IsBattlerAlly(battler, battlerDef)) continue; - u32 ability = GetBattlerAbility(battlerDef); + enum Ability ability = GetBattlerAbility(battlerDef); if (ability == ABILITY_SHADOW_TAG && (B_SHADOW_TAG_ESCAPE <= GEN_3 || GetBattlerAbility(battler) != ABILITY_SHADOW_TAG)) return battlerDef + 1; - if (ability == ABILITY_ARENA_TRAP && IsBattlerGrounded(battler)) + if (ability == ABILITY_ARENA_TRAP && isBattlerGrounded) return battlerDef + 1; if (ability == ABILITY_MAGNET_PULL && IS_BATTLER_OF_TYPE(battler, TYPE_STEEL)) @@ -5481,17 +5863,119 @@ void BattleScriptPushCursorAndCallback(const u8 *BS_ptr) gBattleMainFunc = RunBattleScriptCommands; } -bool32 IsBattlerTerrainAffected(u32 battler, u32 terrainFlag) +bool32 IsBattlerTerrainAffected(u32 battler, enum Ability ability, enum HoldEffect holdEffect, u32 terrainFlag) { if (!(gFieldStatuses & terrainFlag)) return FALSE; if (IsSemiInvulnerable(battler, CHECK_ALL)) return FALSE; - return IsBattlerGrounded(battler); + return IsBattlerGrounded(battler, ability, holdEffect); } -bool32 CanBeSlept(u32 battlerAtk, u32 battlerDef, u32 abilityDef, enum SleepClauseBlock isBlockedBySleepClause) +u32 GetHighestStatId(u32 battler) +{ + u32 highestId = STAT_ATK; + u32 highestStat = gBattleMons[battler].attack; + + for (u32 stat = STAT_DEF; stat < NUM_STATS; stat++) + { + if (stat == STAT_SPEED) + continue; + + u16 *statVal = &gBattleMons[battler].attack + (stat - 1); + if (*statVal > highestStat) + { + highestStat = *statVal; + highestId = stat; + } + } + + if (gBattleMons[battler].speed > highestStat) + highestId = STAT_SPEED; + + return highestId; +} + +static u32 GetStatValueWithStages(u32 battler, u32 stat) +{ + u32 statValue; + + switch (stat) + { + case STAT_ATK: + statValue = gBattleMons[battler].attack; + break; + case STAT_DEF: + statValue = gBattleMons[battler].defense; + break; + case STAT_SPATK: + statValue = gBattleMons[battler].spAttack; + break; + case STAT_SPDEF: + statValue = gBattleMons[battler].spDefense; + break; + case STAT_SPEED: + statValue = gBattleMons[battler].speed; + break; + default: + return 0; + } + + statValue *= gStatStageRatios[gBattleMons[battler].statStages[stat]][0]; + statValue /= gStatStageRatios[gBattleMons[battler].statStages[stat]][1]; + + return statValue; +} + +u32 GetParadoxHighestStatId(u32 battler) +{ + u32 highestId = STAT_ATK; + u32 highestStat = GetStatValueWithStages(battler, STAT_ATK); + + for (u32 stat = STAT_DEF; stat < NUM_STATS; stat++) + { + if (stat == STAT_SPEED) + continue; + + u32 statValue = GetStatValueWithStages(battler, stat); + if (statValue > highestStat) + { + highestStat = statValue; + highestId = stat; + } + } + + u32 speed = GetStatValueWithStages(battler, STAT_SPEED); + if (speed > highestStat) + highestId = STAT_SPEED; + + return highestId; +} + +static void ResetParadoxWeatherStat(u32 battler) +{ + if (gBattleMons[battler].ability == ABILITY_PROTOSYNTHESIS + && !gDisableStructs[battler].boosterEnergyActivated) + gDisableStructs[battler].paradoxBoostedStat = 0; +} + +static void ResetParadoxTerrainStat(u32 battler) +{ + if (gBattleMons[battler].ability == ABILITY_QUARK_DRIVE + && !gDisableStructs[battler].boosterEnergyActivated) + gDisableStructs[battler].paradoxBoostedStat = 0; +} + +u32 GetParadoxBoostedStatId(u32 battler) +{ + if (gDisableStructs[battler].paradoxBoostedStat == 0) + gDisableStructs[battler].paradoxBoostedStat = GetParadoxHighestStatId(battler); + + return gDisableStructs[battler].paradoxBoostedStat; +} + +bool32 CanBeSlept(u32 battlerAtk, u32 battlerDef, enum Ability abilityDef, enum SleepClauseBlock isBlockedBySleepClause) { if (IsSleepClauseActiveForSide(GetBattlerSide(battlerDef)) && isBlockedBySleepClause != NOT_BLOCKED_BY_SLEEP_CLAUSE) return FALSE; @@ -5513,7 +5997,7 @@ bool32 CanBeSlept(u32 battlerAtk, u32 battlerDef, u32 abilityDef, enum SleepClau return effect; } -bool32 CanBePoisoned(u32 battlerAtk, u32 battlerDef, u32 abilityAtk, u32 abilityDef) +bool32 CanBePoisoned(u32 battlerAtk, u32 battlerDef, enum Ability abilityAtk, enum Ability abilityDef) { if (CanSetNonVolatileStatus( battlerAtk, @@ -5526,7 +6010,8 @@ bool32 CanBePoisoned(u32 battlerAtk, u32 battlerDef, u32 abilityAtk, u32 ability return FALSE; } -bool32 CanBeBurned(u32 battlerAtk, u32 battlerDef, u32 abilityDef) +// TODO: check order of battlerAtk and battlerDef +bool32 CanBeBurned(u32 battlerAtk, u32 battlerDef, enum Ability abilityDef) { if (CanSetNonVolatileStatus( battlerAtk, @@ -5539,7 +6024,7 @@ bool32 CanBeBurned(u32 battlerAtk, u32 battlerDef, u32 abilityDef) return FALSE; } -bool32 CanBeParalyzed(u32 battlerAtk, u32 battlerDef, u32 abilityDef) +bool32 CanBeParalyzed(u32 battlerAtk, u32 battlerDef, enum Ability abilityDef) { if (CanSetNonVolatileStatus( battlerAtk, @@ -5552,7 +6037,7 @@ bool32 CanBeParalyzed(u32 battlerAtk, u32 battlerDef, u32 abilityDef) return FALSE; } -bool32 CanBeFrozen(u32 battlerAtk, u32 battlerDef, u32 abilityDef) +bool32 CanBeFrozen(u32 battlerAtk, u32 battlerDef, enum Ability abilityDef) { if (CanSetNonVolatileStatus( battlerAtk, @@ -5564,9 +6049,8 @@ bool32 CanBeFrozen(u32 battlerAtk, u32 battlerDef, u32 abilityDef) return TRUE; return FALSE; } - -// Unused, technically also redundant -bool32 CanGetFrostbite(u32 battlerAtk, u32 battlerDef, u32 abilityDef) +// Unused, technically also redundant because it is just a copy of CanBeFrozen +bool32 CanGetFrostbite(u32 battlerAtk, u32 battlerDef, enum Ability abilityDef) { if (CanSetNonVolatileStatus( battlerAtk, @@ -5579,7 +6063,7 @@ bool32 CanGetFrostbite(u32 battlerAtk, u32 battlerDef, u32 abilityDef) return FALSE; } -bool32 CanSetNonVolatileStatus(u32 battlerAtk, u32 battlerDef, u32 abilityAtk, u32 abilityDef, enum MoveEffect effect, enum FunctionCallOption option) +bool32 CanSetNonVolatileStatus(u32 battlerAtk, u32 battlerDef, enum Ability abilityAtk, enum Ability abilityDef, enum MoveEffect effect, enum FunctionCallOption option) { const u8 *battleScript = NULL; u32 sideBattler = ABILITY_NONE; @@ -5603,13 +6087,11 @@ bool32 CanSetNonVolatileStatus(u32 battlerAtk, u32 battlerDef, u32 abilityAtk, u abilityAffected = TRUE; battlerDef = sideBattler - 1; abilityDef = ABILITY_PASTEL_VEIL; - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_ABILITY_PASTEL_VEIL; battleScript = BattleScript_ImmunityProtected; } else if (abilityDef == ABILITY_IMMUNITY) { abilityAffected = TRUE; - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_ABILITY_PREVENTS_MOVE_POISON; battleScript = BattleScript_ImmunityProtected; } break; @@ -5618,7 +6100,7 @@ bool32 CanSetNonVolatileStatus(u32 battlerAtk, u32 battlerDef, u32 abilityAtk, u { battleScript = BattleScript_AlreadyParalyzed; } - else if (GetGenConfig(GEN_CONFIG_PARALYZE_ELECTRIC) >= GEN_6 && IS_BATTLER_OF_TYPE(battlerDef, TYPE_ELECTRIC)) + else if (GetConfig(CONFIG_PARALYZE_ELECTRIC) >= GEN_6 && IS_BATTLER_OF_TYPE(battlerDef, TYPE_ELECTRIC)) { battleScript = BattleScript_NotAffected; } @@ -5631,7 +6113,6 @@ bool32 CanSetNonVolatileStatus(u32 battlerAtk, u32 battlerDef, u32 abilityAtk, u else if (abilityDef == ABILITY_LIMBER) { abilityAffected = TRUE; - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_ABILITY_PREVENTS_MOVE_PARALYSIS; battleScript = BattleScript_ImmunityProtected; } break; @@ -5647,7 +6128,6 @@ bool32 CanSetNonVolatileStatus(u32 battlerAtk, u32 battlerDef, u32 abilityAtk, u else if (abilityDef == ABILITY_WATER_VEIL || abilityDef == ABILITY_WATER_BUBBLE) { abilityAffected = TRUE; - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_ABILITY_PREVENTS_MOVE_BURN; battleScript = BattleScript_ImmunityProtected; } else if (abilityDef == ABILITY_THERMAL_EXCHANGE) @@ -5669,7 +6149,7 @@ bool32 CanSetNonVolatileStatus(u32 battlerAtk, u32 battlerDef, u32 abilityAtk, u { battleScript = BattleScript_SleepClauseBlocked; } - else if (IsBattlerTerrainAffected(battlerDef, STATUS_FIELD_ELECTRIC_TERRAIN)) + else if (IsBattlerTerrainAffected(battlerDef, abilityDef, GetBattlerHoldEffect(battlerDef), STATUS_FIELD_ELECTRIC_TERRAIN)) { battleScript = BattleScript_ElectricTerrainPrevents; } @@ -5678,7 +6158,6 @@ bool32 CanSetNonVolatileStatus(u32 battlerAtk, u32 battlerDef, u32 abilityAtk, u abilityAffected = TRUE; battlerDef = sideBattler - 1; abilityDef = ABILITY_SWEET_VEIL; - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_STATUS_HAD_NO_EFFECT; battleScript = BattleScript_ImmunityProtected; } else if (abilityDef == ABILITY_VITAL_SPIRIT || abilityDef == ABILITY_INSOMNIA) @@ -5717,7 +6196,7 @@ bool32 CanSetNonVolatileStatus(u32 battlerAtk, u32 battlerDef, u32 abilityAtk, u abilityAffected = TRUE; battleScript = BattleScript_AbilityProtectsDoesntAffect; } - else if (IsBattlerTerrainAffected(battlerDef, STATUS_FIELD_MISTY_TERRAIN)) + else if (IsBattlerTerrainAffected(battlerDef, abilityDef, GetBattlerHoldEffect(battlerDef), STATUS_FIELD_MISTY_TERRAIN)) { battleScript = BattleScript_MistyTerrainPrevents; } @@ -5753,7 +6232,7 @@ bool32 CanSetNonVolatileStatus(u32 battlerAtk, u32 battlerDef, u32 abilityAtk, u return TRUE; } -static bool32 IsNonVolatileStatusBlocked(u32 battlerDef, u32 abilityDef, u32 abilityAffected, const u8 *battleScript, enum FunctionCallOption option) +static bool32 IsNonVolatileStatusBlocked(u32 battlerDef, enum Ability abilityDef, enum Ability abilityAffected, const u8 *battleScript, enum FunctionCallOption option) { if (battleScript != NULL) { @@ -5799,29 +6278,25 @@ static bool32 CanSleepDueToSleepClause(u32 battlerAtk, u32 battlerDef, enum Func bool32 CanBeConfused(u32 battler) { + enum Ability ability = GetBattlerAbility(battler); if (gBattleMons[battler].volatiles.confusionTurns > 0 - || IsBattlerTerrainAffected(battler, STATUS_FIELD_MISTY_TERRAIN) - || IsAbilityAndRecord(battler, GetBattlerAbility(battler),ABILITY_OWN_TEMPO)) + || IsBattlerTerrainAffected(battler, ability, GetBattlerHoldEffect(battler), STATUS_FIELD_MISTY_TERRAIN) + || IsAbilityAndRecord(battler, ability, ABILITY_OWN_TEMPO)) return FALSE; return TRUE; } // second argument is 1/X of current hp compared to max hp -bool32 HasEnoughHpToEatBerry(u32 battler, u32 hpFraction, u32 itemId) +bool32 HasEnoughHpToEatBerry(u32 battler, enum Ability ability, u32 hpFraction, u32 itemId) { - bool32 isBerry = (GetItemPocket(itemId) == POCKET_BERRIES); - if (!IsBattlerAlive(battler)) return FALSE; if (gBattleScripting.overrideBerryRequirements) return TRUE; - // Unnerve prevents consumption of opponents' berries. - if (isBerry && IsUnnerveAbilityOnOpposingSide(battler)) - return FALSE; if (gBattleMons[battler].hp <= gBattleMons[battler].maxHP / hpFraction) return TRUE; - if (hpFraction <= 4 && isBerry + if (hpFraction <= 4 && GetItemPocket(itemId) == POCKET_BERRIES && gBattleMons[battler].hp <= gBattleMons[battler].maxHP / 2 && IsAbilityAndRecord(battler, GetBattlerAbility(battler), ABILITY_GLUTTONY)) return TRUE; @@ -5829,1424 +6304,10 @@ bool32 HasEnoughHpToEatBerry(u32 battler, u32 hpFraction, u32 itemId) return FALSE; } -static enum ItemEffect HealConfuseBerry(u32 battler, u32 itemId, u32 flavorId, enum ItemCaseId caseID) -{ - if (HasEnoughHpToEatBerry(battler, (B_CONFUSE_BERRIES_HEAL >= GEN_7 ? 4 : 2), itemId) - && (B_HEAL_BLOCKING < GEN_5 || !gBattleMons[battler].volatiles.healBlock)) - { - PREPARE_FLAVOR_BUFFER(gBattleTextBuff1, flavorId); - - gBattleStruct->moveDamage[battler] = GetNonDynamaxMaxHP(battler) / GetBattlerItemHoldEffectParam(battler, itemId); - if (gBattleStruct->moveDamage[battler] == 0) - gBattleStruct->moveDamage[battler] = 1; - gBattleStruct->moveDamage[battler] *= -1; - - if (GetBattlerAbility(battler) == ABILITY_RIPEN) - { - gBattleStruct->moveDamage[battler] *= 2; - gBattlerAbility = battler; - } - gBattleScripting.battler = battler; - if (caseID == ITEMEFFECT_ON_SWITCH_IN_FIRST_TURN || caseID == ITEMEFFECT_NORMAL) - { - if (GetFlavorRelationByPersonality(gBattleMons[battler].personality, flavorId) < 0) - BattleScriptExecute(BattleScript_BerryConfuseHealEnd2); - else - BattleScriptExecute(BattleScript_ItemHealHP_RemoveItemEnd2); - } - else - { - if (GetFlavorRelationByPersonality(gBattleMons[battler].personality, flavorId) < 0) - BattleScriptCall(BattleScript_BerryConfuseHealRet); - else - BattleScriptCall(BattleScript_ItemHealHP_RemoveItemRet); - } - - return ITEM_HP_CHANGE; - } - return ITEM_NO_EFFECT; -} - -static enum ItemEffect StatRaiseBerry(u32 battler, u32 itemId, u32 statId, enum ItemCaseId caseID) -{ - u32 ability = GetBattlerAbility(battler); - if (CompareStat(battler, statId, MAX_STAT_STAGE, CMP_LESS_THAN, ability) && HasEnoughHpToEatBerry(battler, GetBattlerItemHoldEffectParam(battler, itemId), itemId)) - { - BufferStatChange(battler, statId, STRINGID_STATROSE); - gEffectBattler = gBattleScripting.battler = battler; - if (ability == ABILITY_RIPEN) - SET_STATCHANGER(statId, 2, FALSE); - else - SET_STATCHANGER(statId, 1, FALSE); - - gBattleScripting.animArg1 = STAT_ANIM_PLUS1 + statId; - gBattleScripting.animArg2 = 0; - - if (caseID == ITEMEFFECT_ON_SWITCH_IN_FIRST_TURN || caseID == ITEMEFFECT_NORMAL) - BattleScriptExecute(BattleScript_ConsumableStatRaiseEnd2); - else - BattleScriptCall(BattleScript_ConsumableStatRaiseRet); - return ITEM_STATS_CHANGE; - } - return ITEM_NO_EFFECT; -} - -static enum ItemEffect RandomStatRaiseBerry(u32 battler, u32 itemId, enum ItemCaseId caseID) -{ - s32 stat; - enum StringID stringId; - u32 battlerAbility = GetBattlerAbility(battler); - - for (stat = STAT_ATK; stat < NUM_STATS; stat++) - { - if (CompareStat(battler, stat, MAX_STAT_STAGE, CMP_LESS_THAN, battlerAbility)) - break; - } - if (stat != NUM_STATS && HasEnoughHpToEatBerry(battler, GetBattlerItemHoldEffectParam(battler, itemId), itemId)) - { - u32 savedAttacker = gBattlerAttacker; - // MoodyCantRaiseStat requires that the battler is set to gBattlerAttacker - gBattlerAttacker = gBattleScripting.battler = battler; - stat = RandomUniformExcept(RNG_RANDOM_STAT_UP, STAT_ATK, NUM_STATS - 1, MoodyCantRaiseStat); - gBattlerAttacker = savedAttacker; - - PREPARE_STAT_BUFFER(gBattleTextBuff1, stat); - stringId = (battlerAbility == ABILITY_CONTRARY) ? STRINGID_STATFELL : STRINGID_STATROSE; - gBattleTextBuff2[0] = B_BUFF_PLACEHOLDER_BEGIN; - gBattleTextBuff2[1] = B_BUFF_STRING; - gBattleTextBuff2[2] = STRINGID_STATSHARPLY; - gBattleTextBuff2[3] = STRINGID_STATSHARPLY >> 8; - gBattleTextBuff2[4] = B_BUFF_STRING; - gBattleTextBuff2[5] = stringId; - gBattleTextBuff2[6] = stringId >> 8; - gBattleTextBuff2[7] = EOS; - gEffectBattler = battler; - if (battlerAbility == ABILITY_RIPEN) - SET_STATCHANGER(stat, 4, FALSE); - else - SET_STATCHANGER(stat, 2, FALSE); - - gBattleScripting.animArg1 = STAT_ANIM_PLUS2 + stat; - gBattleScripting.animArg2 = 0; - if (caseID == ITEMEFFECT_ON_SWITCH_IN_FIRST_TURN || caseID == ITEMEFFECT_NORMAL) - BattleScriptExecute(BattleScript_ConsumableStatRaiseEnd2); - else - BattleScriptCall(BattleScript_ConsumableStatRaiseRet); - return ITEM_STATS_CHANGE; - } - return ITEM_NO_EFFECT; -} - -static enum ItemEffect TrySetMicleBerry(u32 battler, u32 itemId, enum ItemCaseId caseID) -{ - if (HasEnoughHpToEatBerry(battler, 4, itemId)) - { - gBattleStruct->battlerState[battler].usedMicleBerry = TRUE; - if (caseID == ITEMEFFECT_ON_SWITCH_IN_FIRST_TURN || caseID == ITEMEFFECT_NORMAL) - { - BattleScriptExecute(BattleScript_MicleBerryActivateEnd2); - } - else - { - BattleScriptCall(BattleScript_MicleBerryActivateRet); - } - return ITEM_EFFECT_OTHER; - } - return ITEM_NO_EFFECT; -} - -static enum ItemEffect TrySetEnigmaBerry(u32 battler) -{ - if (IsBattlerAlive(battler) - && !DoesSubstituteBlockMove(gBattlerAttacker, battler, gCurrentMove) - && ((IsBattlerTurnDamaged(battler) && gBattleStruct->moveResultFlags[battler] & MOVE_RESULT_SUPER_EFFECTIVE) || gBattleScripting.overrideBerryRequirements) - && !(gBattleScripting.overrideBerryRequirements && gBattleMons[battler].hp == gBattleMons[battler].maxHP) - && (B_HEAL_BLOCKING < GEN_5 || !gBattleMons[battler].volatiles.healBlock)) - { - gBattleScripting.battler = battler; - gBattleStruct->moveDamage[battler] = (gBattleMons[battler].maxHP * 25 / 100) * -1; - if (GetBattlerAbility(battler) == ABILITY_RIPEN) - gBattleStruct->moveDamage[battler] *= 2; - - BattleScriptCall(BattleScript_ItemHealHP_RemoveItemRet); - return ITEM_HP_CHANGE; - } - return ITEM_NO_EFFECT; -} - -static enum ItemEffect DamagedStatBoostBerryEffect(u32 battler, u8 statId, enum DamageCategory category) -{ - u32 ability = GetBattlerAbility(battler); - if (IsBattlerAlive(battler) - && CompareStat(battler, statId, MAX_STAT_STAGE, CMP_LESS_THAN, ability) - && (gBattleScripting.overrideBerryRequirements - || (!DoesSubstituteBlockMove(gBattlerAttacker, battler, gCurrentMove) - && GetBattleMoveCategory(gCurrentMove) == category - && battler != gBattlerAttacker - && IsBattlerTurnDamaged(battler))) - ) - { - BufferStatChange(battler, statId, STRINGID_STATROSE); - - gEffectBattler = battler; - if (ability == ABILITY_RIPEN) - SET_STATCHANGER(statId, 2, FALSE); - else - SET_STATCHANGER(statId, 1, FALSE); - - gBattleScripting.battler = battler; - gBattleScripting.animArg1 = STAT_ANIM_PLUS1 + statId; - gBattleScripting.animArg2 = 0; - BattleScriptCall(BattleScript_ConsumableStatRaiseRet); - return ITEM_STATS_CHANGE; - } - return ITEM_NO_EFFECT; -} - -enum ItemEffect TryHandleSeed(u32 battler, u32 terrainFlag, u32 statId, u32 itemId, enum ItemCaseId caseID) -{ - if (gFieldStatuses & terrainFlag && CompareStat(battler, statId, MAX_STAT_STAGE, CMP_LESS_THAN, GetBattlerAbility(battler))) - { - BufferStatChange(battler, statId, STRINGID_STATROSE); - gLastUsedItem = itemId; // For surge abilities - gEffectBattler = gBattleScripting.battler = battler; - SET_STATCHANGER(statId, 1, FALSE); - gBattleScripting.animArg1 = STAT_ANIM_PLUS1 + statId; - gBattleScripting.animArg2 = 0; - if (caseID == ITEMEFFECT_ON_SWITCH_IN_FIRST_TURN) - BattleScriptExecute(BattleScript_ConsumableStatRaiseEnd2); - else - BattleScriptCall(BattleScript_ConsumableStatRaiseRet); - return ITEM_STATS_CHANGE; - } - return ITEM_NO_EFFECT; -} - -static enum ItemEffect ConsumeBerserkGene(u32 battler, enum ItemCaseId caseID) -{ - if (CanBeInfinitelyConfused(battler)) - gBattleMons[battler].volatiles.infiniteConfusion = TRUE; - - BufferStatChange(battler, STAT_ATK, STRINGID_STATROSE); - gBattlerAttacker = gEffectBattler = battler; - SET_STATCHANGER(STAT_ATK, 2, FALSE); - gBattleScripting.animArg1 = STAT_ANIM_PLUS1 + STAT_ATK; - gBattleScripting.animArg2 = 0; - if (caseID == ITEMEFFECT_ON_SWITCH_IN_FIRST_TURN || caseID == ITEMEFFECT_NORMAL) - BattleScriptExecute(BattleScript_BerserkGeneRetEnd2); - else - BattleScriptCall(BattleScript_BerserkGeneRet); - return ITEM_STATS_CHANGE; -} - -static u32 ItemRestorePp(u32 battler, u32 itemId, enum ItemCaseId caseID) -{ - struct Pokemon *mon = GetBattlerMon(battler); - u32 i, changedPP = 0; - - for (i = 0; i < MAX_MON_MOVES; i++) - { - u32 move = GetMonData(mon, MON_DATA_MOVE1 + i); - u32 currentPP = GetMonData(mon, MON_DATA_PP1 + i); - u32 ppBonuses = GetMonData(mon, MON_DATA_PP_BONUSES); - u32 maxPP = CalculatePPWithBonus(move, ppBonuses, i); - if (move && (currentPP == 0 || (gBattleScripting.overrideBerryRequirements && currentPP != maxPP))) - { - u32 ppRestored = GetBattlerItemHoldEffectParam(battler, itemId); - - if (GetBattlerAbility(battler) == ABILITY_RIPEN) - { - ppRestored *= 2; - gBattlerAbility = battler; - } - if (currentPP + ppRestored > maxPP) - changedPP = maxPP; - else - changedPP = currentPP + ppRestored; - - PREPARE_MOVE_BUFFER(gBattleTextBuff1, move); - - if (caseID == ITEMEFFECT_ON_SWITCH_IN_FIRST_TURN || caseID == ITEMEFFECT_NORMAL) - BattleScriptExecute(BattleScript_BerryPPHealEnd2); - else - BattleScriptCall(BattleScript_BerryPPHealRet); - - gBattleScripting.battler = battler; - BtlController_EmitSetMonData(battler, B_COMM_TO_CONTROLLER, i + REQUEST_PPMOVE1_BATTLE, 0, 1, &changedPP); - MarkBattlerForControllerExec(battler); - if (MOVE_IS_PERMANENT(battler, i)) - gBattleMons[battler].pp[i] = changedPP; - return ITEM_PP_CHANGE; - } - } - return 0; -} - -static u32 ItemHealHp(u32 battler, u32 itemId, enum ItemCaseId caseID, bool32 percentHeal) -{ - if (!(gBattleScripting.overrideBerryRequirements && gBattleMons[battler].hp == gBattleMons[battler].maxHP) - && (B_HEAL_BLOCKING < GEN_5 || !gBattleMons[battler].volatiles.healBlock) - && HasEnoughHpToEatBerry(battler, 2, itemId)) - { - if (percentHeal) - gBattleStruct->moveDamage[battler] = (GetNonDynamaxMaxHP(battler) * GetBattlerItemHoldEffectParam(battler, itemId) / 100) * -1; - else - gBattleStruct->moveDamage[battler] = GetBattlerItemHoldEffectParam(battler, itemId) * -1; - - // check ripen - if (GetItemPocket(itemId) == POCKET_BERRIES && GetBattlerAbility(battler) == ABILITY_RIPEN) - gBattleStruct->moveDamage[battler] *= 2; - - gBattlerAbility = battler; // in SWSH, berry juice shows ability pop up but has no effect. This is mimicked here - if (caseID == ITEMEFFECT_ON_SWITCH_IN_FIRST_TURN || caseID == ITEMEFFECT_NORMAL) - BattleScriptExecute(BattleScript_ItemHealHP_RemoveItemEnd2); - else - BattleScriptCall(BattleScript_ItemHealHP_RemoveItemRet); - - return ITEM_HP_CHANGE; - } - return 0; -} - -static bool32 UnnerveOn(u32 battler, u32 itemId) -{ - if (gBattleScripting.overrideBerryRequirements > 0) // Berries that aren't eaten naturally ignore unnerve - return FALSE; - - if (GetItemPocket(itemId) == POCKET_BERRIES && IsUnnerveAbilityOnOpposingSide(battler)) - return TRUE; - return FALSE; -} - -static bool32 GetMentalHerbEffect(u32 battler) -{ - bool32 ret = FALSE; - - // Check infatuation - if (gBattleMons[battler].volatiles.infatuation) - { - gBattleMons[battler].volatiles.infatuation = 0; - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_MENTALHERBCURE_INFATUATION; // STRINGID_TARGETGOTOVERINFATUATION - StringCopy(gBattleTextBuff1, gStatusConditionString_LoveJpn); - ret = TRUE; - } - if (B_MENTAL_HERB >= GEN_5) - { - // Check taunt - if (gDisableStructs[battler].tauntTimer != 0) - { - gDisableStructs[battler].tauntTimer = 0; - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_MENTALHERBCURE_TAUNT; - PREPARE_MOVE_BUFFER(gBattleTextBuff1, MOVE_TAUNT); - ret = TRUE; - } - // Check encore - if (gDisableStructs[battler].encoreTimer != 0) - { - gDisableStructs[battler].encoredMove = 0; - gDisableStructs[battler].encoreTimer = 0; - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_MENTALHERBCURE_ENCORE; // STRINGID_PKMNENCOREENDED - ret = TRUE; - } - // Check torment - if (gBattleMons[battler].volatiles.torment == TRUE) - { - gBattleMons[battler].volatiles.torment = FALSE; - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_MENTALHERBCURE_TORMENT; - ret = TRUE; - } - // Check heal block - if (gBattleMons[battler].volatiles.healBlock) - { - gBattleMons[battler].volatiles.healBlock = FALSE; - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_MENTALHERBCURE_HEALBLOCK; - ret = TRUE; - } - // Check disable - if (gDisableStructs[battler].disableTimer != 0) - { - gDisableStructs[battler].disableTimer = 0; - gDisableStructs[battler].disabledMove = 0; - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_MENTALHERBCURE_DISABLE; - ret = TRUE; - } - } - return ret; -} - -static u32 TryConsumeMirrorHerb(u32 battler, enum ItemCaseId caseID) -{ - u32 effect = 0; - - if (gProtectStructs[battler].eatMirrorHerb) - { - gLastUsedItem = gBattleMons[battler].item; - gBattleScripting.battler = battler; - gProtectStructs[battler].eatMirrorHerb = 0; - ChooseStatBoostAnimation(battler); - if (caseID == ITEMEFFECT_ON_SWITCH_IN_FIRST_TURN || caseID == ITEMEFFECT_NORMAL) - BattleScriptExecute(BattleScript_MirrorHerbCopyStatChangeEnd2); - else - BattleScriptCall(BattleScript_MirrorHerbCopyStatChange); - effect = ITEM_STATS_CHANGE; - } - return effect; -} - -u32 TryBoosterEnergy(u32 battler, u32 ability, enum ItemCaseId caseID) -{ - if (gDisableStructs[battler].boosterEnergyActivated || gBattleMons[battler].volatiles.transformed) - return ITEM_NO_EFFECT; - - if (((ability == ABILITY_PROTOSYNTHESIS) && !((gBattleWeather & B_WEATHER_SUN) && HasWeatherEffect())) - || ((ability == ABILITY_QUARK_DRIVE) && !(gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN))) - { - PREPARE_STAT_BUFFER(gBattleTextBuff1, GetHighestStatId(battler)); - gBattlerAbility = gBattleScripting.battler = battler; - gDisableStructs[battler].boosterEnergyActivated = TRUE; - gLastUsedItem = ITEM_BOOSTER_ENERGY; - RecordAbilityBattle(battler, ability); - if (caseID == ITEMEFFECT_ON_SWITCH_IN_FIRST_TURN || caseID == ITEMEFFECT_NORMAL) - BattleScriptExecute(BattleScript_BoosterEnergyEnd2); - else - BattleScriptCall(BattleScript_BoosterEnergyRet); - return ITEM_EFFECT_OTHER; - } - - return ITEM_NO_EFFECT; -} - -u32 RestoreWhiteHerbStats(u32 battler) -{ - u32 i, effect = 0; - - for (i = 0; i < NUM_BATTLE_STATS; i++) - { - if (gBattleMons[battler].statStages[i] < DEFAULT_STAT_STAGE) - { - gBattleMons[battler].statStages[i] = DEFAULT_STAT_STAGE; - effect = ITEM_STATS_CHANGE; - } - } - if (effect != 0) - { - gLastUsedItem = gBattleMons[battler].item; - gBattleScripting.battler = battler; - gPotentialItemEffectBattler = battler; - } - return effect; -} - -static u8 ItemEffectMoveEnd(u32 battler, enum ItemHoldEffect holdEffect) -{ - u8 effect = 0; - - switch (holdEffect) - { - case HOLD_EFFECT_MICLE_BERRY: - if (B_HP_BERRIES >= GEN_4) - effect = TrySetMicleBerry(battler, gLastUsedItem, ITEMEFFECT_NONE); - break; - case HOLD_EFFECT_RESTORE_HP: - if (B_HP_BERRIES >= GEN_4) - effect = ItemHealHp(battler, gLastUsedItem, ITEMEFFECT_NONE, FALSE); - break; - case HOLD_EFFECT_RESTORE_PCT_HP: - if (B_BERRIES_INSTANT >= GEN_4) - effect = ItemHealHp(battler, gLastUsedItem, ITEMEFFECT_NONE, TRUE); - break; - case HOLD_EFFECT_RESTORE_PP: - if (B_BERRIES_INSTANT >= GEN_4) - effect = ItemRestorePp(battler, gLastUsedItem, ITEMEFFECT_NONE); - break; - case HOLD_EFFECT_CONFUSE_SPICY: - if (B_BERRIES_INSTANT >= GEN_4) - effect = HealConfuseBerry(battler, gLastUsedItem, FLAVOR_SPICY, ITEMEFFECT_NONE); - break; - case HOLD_EFFECT_CONFUSE_DRY: - if (B_BERRIES_INSTANT >= GEN_4) - effect = HealConfuseBerry(battler, gLastUsedItem, FLAVOR_DRY, ITEMEFFECT_NONE); - break; - case HOLD_EFFECT_CONFUSE_SWEET: - if (B_BERRIES_INSTANT >= GEN_4) - effect = HealConfuseBerry(battler, gLastUsedItem, FLAVOR_SWEET, ITEMEFFECT_NONE); - break; - case HOLD_EFFECT_CONFUSE_BITTER: - if (B_BERRIES_INSTANT >= GEN_4) - effect = HealConfuseBerry(battler, gLastUsedItem, FLAVOR_BITTER, ITEMEFFECT_NONE); - break; - case HOLD_EFFECT_CONFUSE_SOUR: - if (B_BERRIES_INSTANT >= GEN_4) - effect = HealConfuseBerry(battler, gLastUsedItem, FLAVOR_SOUR, ITEMEFFECT_NONE); - break; - case HOLD_EFFECT_ATTACK_UP: - if (B_BERRIES_INSTANT >= GEN_4) - effect = StatRaiseBerry(battler, gLastUsedItem, STAT_ATK, ITEMEFFECT_NONE); - break; - case HOLD_EFFECT_DEFENSE_UP: - if (B_BERRIES_INSTANT >= GEN_4) - effect = StatRaiseBerry(battler, gLastUsedItem, STAT_DEF, ITEMEFFECT_NONE); - break; - case HOLD_EFFECT_SPEED_UP: - if (B_BERRIES_INSTANT >= GEN_4) - effect = StatRaiseBerry(battler, gLastUsedItem, STAT_SPEED, ITEMEFFECT_NONE); - break; - case HOLD_EFFECT_SP_ATTACK_UP: - if (B_BERRIES_INSTANT >= GEN_4) - effect = StatRaiseBerry(battler, gLastUsedItem, STAT_SPATK, ITEMEFFECT_NONE); - break; - case HOLD_EFFECT_SP_DEFENSE_UP: - if (B_BERRIES_INSTANT >= GEN_4) - effect = StatRaiseBerry(battler, gLastUsedItem, STAT_SPDEF, ITEMEFFECT_NONE); - break; - case HOLD_EFFECT_ENIGMA_BERRY: // consume and heal if hit by super effective move - effect = TrySetEnigmaBerry(battler); - break; - case HOLD_EFFECT_KEE_BERRY: // consume and boost defense if used physical move - effect = DamagedStatBoostBerryEffect(battler, STAT_DEF, DAMAGE_CATEGORY_PHYSICAL); - break; - case HOLD_EFFECT_MARANGA_BERRY: // consume and boost sp. defense if used special move - effect = DamagedStatBoostBerryEffect(battler, STAT_SPDEF, DAMAGE_CATEGORY_SPECIAL); - break; - case HOLD_EFFECT_RANDOM_STAT_UP: - if (B_BERRIES_INSTANT >= GEN_4) - effect = RandomStatRaiseBerry(battler, gLastUsedItem, ITEMEFFECT_NONE); - break; - case HOLD_EFFECT_CURE_PAR: - if (gBattleMons[battler].status1 & STATUS1_PARALYSIS && !UnnerveOn(battler, gLastUsedItem)) - { - gBattleMons[battler].status1 &= ~STATUS1_PARALYSIS; - BattleScriptCall(BattleScript_BerryCureParRet); - effect = ITEM_STATUS_CHANGE; - } - break; - case HOLD_EFFECT_CURE_PSN: - if (gBattleMons[battler].status1 & STATUS1_PSN_ANY && !UnnerveOn(battler, gLastUsedItem)) - { - gBattleMons[battler].status1 &= ~(STATUS1_PSN_ANY | STATUS1_TOXIC_COUNTER); - BattleScriptCall(BattleScript_BerryCurePsnRet); - effect = ITEM_STATUS_CHANGE; - } - break; - case HOLD_EFFECT_CURE_BRN: - if (gBattleMons[battler].status1 & STATUS1_BURN && !UnnerveOn(battler, gLastUsedItem)) - { - gBattleMons[battler].status1 &= ~STATUS1_BURN; - BattleScriptCall(BattleScript_BerryCureBrnRet); - effect = ITEM_STATUS_CHANGE; - } - break; - case HOLD_EFFECT_CURE_FRZ: - if (gBattleMons[battler].status1 & STATUS1_FREEZE && !UnnerveOn(battler, gLastUsedItem)) - { - gBattleMons[battler].status1 &= ~STATUS1_FREEZE; - BattleScriptCall(BattleScript_BerryCureFrzRet); - effect = ITEM_STATUS_CHANGE; - } - if (gBattleMons[battler].status1 & STATUS1_FROSTBITE && !UnnerveOn(battler, gLastUsedItem)) - { - gBattleMons[battler].status1 &= ~STATUS1_FROSTBITE; - BattleScriptCall(BattleScript_BerryCureFrbRet); - effect = ITEM_STATUS_CHANGE; - } - break; - case HOLD_EFFECT_CURE_SLP: - if (gBattleMons[battler].status1 & STATUS1_SLEEP && !UnnerveOn(battler, gLastUsedItem)) - { - gBattleMons[battler].status1 &= ~STATUS1_SLEEP; - gBattleMons[battler].volatiles.nightmare = FALSE; - BattleScriptCall(BattleScript_BerryCureSlpRet); - effect = ITEM_STATUS_CHANGE; - TryDeactivateSleepClause(GetBattlerSide(battler), gBattlerPartyIndexes[battler]); - } - break; - case HOLD_EFFECT_CURE_CONFUSION: - if (gBattleMons[battler].volatiles.confusionTurns > 0 && !UnnerveOn(battler, gLastUsedItem)) - { - RemoveConfusionStatus(battler); - BattleScriptCall(BattleScript_BerryCureConfusionRet); - effect = ITEM_EFFECT_OTHER; - } - break; - case HOLD_EFFECT_MENTAL_HERB: - if (GetMentalHerbEffect(battler)) - { - gBattleScripting.savedBattler = gBattlerAttacker; - gBattlerAttacker = battler; - BattleScriptCall(BattleScript_MentalHerbCureRet); - effect = ITEM_EFFECT_OTHER; - } - break; - case HOLD_EFFECT_CURE_STATUS: - if ((gBattleMons[battler].status1 & STATUS1_ANY || gBattleMons[battler].volatiles.confusionTurns > 0) && !UnnerveOn(battler, gLastUsedItem)) - { - if (gBattleMons[battler].status1 & STATUS1_PSN_ANY) - StringCopy(gBattleTextBuff1, gStatusConditionString_PoisonJpn); - - if (gBattleMons[battler].status1 & STATUS1_SLEEP) - { - gBattleMons[battler].volatiles.nightmare = FALSE; - StringCopy(gBattleTextBuff1, gStatusConditionString_SleepJpn); - TryDeactivateSleepClause(GetBattlerSide(battler), gBattlerPartyIndexes[battler]); - } - - if (gBattleMons[battler].status1 & STATUS1_PARALYSIS) - StringCopy(gBattleTextBuff1, gStatusConditionString_ParalysisJpn); - - if (gBattleMons[battler].status1 & STATUS1_BURN) - StringCopy(gBattleTextBuff1, gStatusConditionString_BurnJpn); - - if (gBattleMons[battler].status1 & STATUS1_FREEZE || gBattleMons[battler].status1 & STATUS1_FROSTBITE) - StringCopy(gBattleTextBuff1, gStatusConditionString_IceJpn); - - if (gBattleMons[battler].volatiles.confusionTurns > 0) - StringCopy(gBattleTextBuff1, gStatusConditionString_ConfusionJpn); - - gBattleMons[battler].status1 = 0; - RemoveConfusionStatus(battler); - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_CURED_PROBLEM; - BattleScriptCall(BattleScript_BerryCureChosenStatusRet); - effect = ITEM_STATUS_CHANGE; - } - break; - case HOLD_EFFECT_CRITICAL_UP: // lansat berry - if (B_BERRIES_INSTANT >= GEN_4 - && !(gBattleMons[battler].volatiles.dragonCheer || gBattleMons[battler].volatiles.focusEnergy) - && HasEnoughHpToEatBerry(battler, GetBattlerItemHoldEffectParam(battler, gLastUsedItem), gLastUsedItem)) - { - gBattleMons[battler].volatiles.focusEnergy = TRUE; - gBattleScripting.battler = battler; - gPotentialItemEffectBattler = battler; - BattleScriptCall(BattleScript_BerryFocusEnergyRet); - effect = ITEM_EFFECT_OTHER; - } - break; - case HOLD_EFFECT_BERSERK_GENE: - effect = ConsumeBerserkGene(battler, ITEMEFFECT_NONE); - break; - case HOLD_EFFECT_MIRROR_HERB: - effect = TryConsumeMirrorHerb(battler, ITEMEFFECT_NONE); - break; - default: - break; - } - - return effect; -} - -static inline bool32 TryCureStatus(u32 battler, enum ItemCaseId caseId) -{ - u32 effect = ITEM_NO_EFFECT; - u32 string = 0; - - if ((gBattleMons[battler].status1 & STATUS1_ANY || gBattleMons[battler].volatiles.confusionTurns > 0) && !UnnerveOn(battler, gLastUsedItem)) - { - if (gBattleMons[battler].status1 & STATUS1_PSN_ANY) - { - StringCopy(gBattleTextBuff1, gStatusConditionString_PoisonJpn); - string++; - } - if (gBattleMons[battler].status1 & STATUS1_SLEEP) - { - gBattleMons[battler].volatiles.nightmare = FALSE; - StringCopy(gBattleTextBuff1, gStatusConditionString_SleepJpn); - string++; - TryDeactivateSleepClause(GetBattlerSide(battler), gBattlerPartyIndexes[battler]); - } - if (gBattleMons[battler].status1 & STATUS1_PARALYSIS) - { - StringCopy(gBattleTextBuff1, gStatusConditionString_ParalysisJpn); - string++; - } - if (gBattleMons[battler].status1 & STATUS1_BURN) - { - StringCopy(gBattleTextBuff1, gStatusConditionString_BurnJpn); - string++; - } - if (gBattleMons[battler].status1 & STATUS1_FREEZE || gBattleMons[battler].status1 & STATUS1_FROSTBITE) - { - StringCopy(gBattleTextBuff1, gStatusConditionString_IceJpn); - string++; - } - if (gBattleMons[battler].volatiles.confusionTurns > 0) - { - StringCopy(gBattleTextBuff1, gStatusConditionString_ConfusionJpn); - string++; - } - if (string <= 1) - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_CURED_PROBLEM; - else - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_NORMALIZED_STATUS; - gBattleMons[battler].status1 = 0; - RemoveConfusionStatus(battler); - if (caseId == ITEMEFFECT_ON_SWITCH_IN_FIRST_TURN || caseId == ITEMEFFECT_NORMAL) - BattleScriptExecute(BattleScript_BerryCureChosenStatusEnd2); - else - BattleScriptCall(BattleScript_BerryCureChosenStatusRet); - effect = ITEM_STATUS_CHANGE; - } - - return effect; -} - -u32 ItemBattleEffects(enum ItemCaseId caseID, u32 battler) -{ - u32 moveType = 0; - enum ItemEffect effect = ITEM_NO_EFFECT; - enum ItemHoldEffect battlerHoldEffect = 0, atkHoldEffect = 0; - u32 atkHoldEffectParam = 0; - u32 atkItem = 0; - - if (caseID != ITEMEFFECT_USE_LAST_ITEM) - { - gLastUsedItem = gBattleMons[battler].item; - battlerHoldEffect = GetBattlerHoldEffect(battler, TRUE); - } - - atkItem = gBattleMons[gBattlerAttacker].item; - atkHoldEffect = GetBattlerHoldEffect(gBattlerAttacker, TRUE); - atkHoldEffectParam = GetBattlerHoldEffectParam(gBattlerAttacker); - - switch (caseID) - { - case ITEMEFFECT_NONE: - break; - case ITEMEFFECT_ON_SWITCH_IN: - case ITEMEFFECT_ON_SWITCH_IN_FIRST_TURN: - if (!gSpecialStatuses[battler].switchInItemDone) - { - switch (battlerHoldEffect) - { - case HOLD_EFFECT_DOUBLE_PRIZE: - if (IsOnPlayerSide(battler) && !gBattleStruct->moneyMultiplierItem) - { - gBattleStruct->moneyMultiplier *= 2; - gBattleStruct->moneyMultiplierItem = 1; - } - break; - case HOLD_EFFECT_WHITE_HERB: - effect = RestoreWhiteHerbStats(battler); - if (effect != 0) - BattleScriptExecute(BattleScript_WhiteHerbEnd2); - break; - case HOLD_EFFECT_CONFUSE_SPICY: - if (B_BERRIES_INSTANT >= GEN_4) - effect = HealConfuseBerry(battler, gLastUsedItem, FLAVOR_SPICY, caseID); - break; - case HOLD_EFFECT_CONFUSE_DRY: - if (B_BERRIES_INSTANT >= GEN_4) - effect = HealConfuseBerry(battler, gLastUsedItem, FLAVOR_DRY, caseID); - break; - case HOLD_EFFECT_CONFUSE_SWEET: - if (B_BERRIES_INSTANT >= GEN_4) - effect = HealConfuseBerry(battler, gLastUsedItem, FLAVOR_SWEET, caseID); - break; - case HOLD_EFFECT_CONFUSE_BITTER: - if (B_BERRIES_INSTANT >= GEN_4) - effect = HealConfuseBerry(battler, gLastUsedItem, FLAVOR_BITTER, caseID); - break; - case HOLD_EFFECT_CONFUSE_SOUR: - if (B_BERRIES_INSTANT >= GEN_4) - effect = HealConfuseBerry(battler, gLastUsedItem, FLAVOR_SOUR, caseID); - break; - case HOLD_EFFECT_ATTACK_UP: - if (B_BERRIES_INSTANT >= GEN_4) - effect = StatRaiseBerry(battler, gLastUsedItem, STAT_ATK, caseID); - break; - case HOLD_EFFECT_DEFENSE_UP: - if (B_BERRIES_INSTANT >= GEN_4) - effect = StatRaiseBerry(battler, gLastUsedItem, STAT_DEF, caseID); - break; - case HOLD_EFFECT_SPEED_UP: - if (B_BERRIES_INSTANT >= GEN_4) - effect = StatRaiseBerry(battler, gLastUsedItem, STAT_SPEED, caseID); - break; - case HOLD_EFFECT_SP_ATTACK_UP: - if (B_BERRIES_INSTANT >= GEN_4) - effect = StatRaiseBerry(battler, gLastUsedItem, STAT_SPATK, caseID); - break; - case HOLD_EFFECT_SP_DEFENSE_UP: - if (B_BERRIES_INSTANT >= GEN_4) - effect = StatRaiseBerry(battler, gLastUsedItem, STAT_SPDEF, caseID); - break; - case HOLD_EFFECT_CRITICAL_UP: - if (B_BERRIES_INSTANT >= GEN_4 - && !(gBattleMons[battler].volatiles.dragonCheer || gBattleMons[battler].volatiles.focusEnergy) - && HasEnoughHpToEatBerry(battler, GetBattlerItemHoldEffectParam(battler, gLastUsedItem), gLastUsedItem)) - { - gBattleMons[battler].volatiles.focusEnergy = TRUE; - gBattleScripting.battler = battler; - BattleScriptExecute(BattleScript_BerryFocusEnergyEnd2); - effect = ITEM_EFFECT_OTHER; - } - break; - case HOLD_EFFECT_RANDOM_STAT_UP: - if (B_BERRIES_INSTANT >= GEN_4) - effect = RandomStatRaiseBerry(battler, gLastUsedItem, caseID); - break; - case HOLD_EFFECT_CURE_PAR: - if (B_BERRIES_INSTANT >= GEN_4 - && gBattleMons[battler].status1 & STATUS1_PARALYSIS - && !UnnerveOn(battler, gLastUsedItem)) - { - gBattleMons[battler].status1 &= ~STATUS1_PARALYSIS; - BattleScriptExecute(BattleScript_BerryCurePrlzEnd2); - effect = ITEM_STATUS_CHANGE; - } - break; - case HOLD_EFFECT_CURE_PSN: - if (B_BERRIES_INSTANT >= GEN_4 - && (gBattleMons[battler].status1 & STATUS1_PSN_ANY) - && !UnnerveOn(battler, gLastUsedItem)) - { - gBattleMons[battler].status1 &= ~(STATUS1_PSN_ANY | STATUS1_TOXIC_COUNTER); - BattleScriptExecute(BattleScript_BerryCurePsnEnd2); - effect = ITEM_STATUS_CHANGE; - } - break; - case HOLD_EFFECT_CURE_BRN: - if (B_BERRIES_INSTANT >= GEN_4 - && (gBattleMons[battler].status1 & STATUS1_BURN) - && !UnnerveOn(battler, gLastUsedItem)) - { - gBattleMons[battler].status1 &= ~STATUS1_BURN; - BattleScriptExecute(BattleScript_BerryCureBrnEnd2); - effect = ITEM_STATUS_CHANGE; - } - break; - case HOLD_EFFECT_CURE_FRZ: - if (B_BERRIES_INSTANT >= GEN_4 - && (gBattleMons[battler].status1 & STATUS1_FREEZE) - && !UnnerveOn(battler, gLastUsedItem)) - { - gBattleMons[battler].status1 &= ~STATUS1_FREEZE; - BattleScriptExecute(BattleScript_BerryCureFrzEnd2); - effect = ITEM_STATUS_CHANGE; - } - if (B_BERRIES_INSTANT >= GEN_4 - && (gBattleMons[battler].status1 & STATUS1_FROSTBITE) - && !UnnerveOn(battler, gLastUsedItem)) - { - gBattleMons[battler].status1 &= ~STATUS1_FROSTBITE; - BattleScriptExecute(BattleScript_BerryCureFrbEnd2); - effect = ITEM_STATUS_CHANGE; - } - break; - case HOLD_EFFECT_CURE_SLP: - if (B_BERRIES_INSTANT >= GEN_4 - && (gBattleMons[battler].status1 & STATUS1_SLEEP) - && !UnnerveOn(battler, gLastUsedItem)) - { - gBattleMons[battler].status1 &= ~STATUS1_SLEEP; - gBattleMons[battler].volatiles.nightmare = FALSE; - BattleScriptExecute(BattleScript_BerryCureSlpEnd2); - effect = ITEM_STATUS_CHANGE; - TryDeactivateSleepClause(GetBattlerSide(battler), gBattlerPartyIndexes[battler]); - } - break; - case HOLD_EFFECT_CURE_STATUS: - if (B_BERRIES_INSTANT >= GEN_4) - effect = TryCureStatus(battler, caseID); - break; - case HOLD_EFFECT_RESTORE_HP: - if (B_BERRIES_INSTANT >= GEN_4) - effect = ItemHealHp(battler, gLastUsedItem, caseID, FALSE); - break; - case HOLD_EFFECT_RESTORE_PCT_HP: - if (B_BERRIES_INSTANT >= GEN_4) - effect = ItemHealHp(battler, gLastUsedItem, caseID, TRUE); - break; - case HOLD_EFFECT_RESTORE_PP: - effect = ItemRestorePp(battler, gLastUsedItem, caseID); - break; - case HOLD_EFFECT_AIR_BALLOON: - effect = ITEM_EFFECT_OTHER; - gBattleScripting.battler = battler; - BattleScriptPushCursorAndCallback(BattleScript_AirBaloonMsgIn); - RecordItemEffectBattle(battler, HOLD_EFFECT_AIR_BALLOON); - break; - case HOLD_EFFECT_ROOM_SERVICE: - if (TryRoomService(battler)) - { - BattleScriptExecute(BattleScript_ConsumableStatRaiseEnd2); - effect = ITEM_STATS_CHANGE; - } - break; - case HOLD_EFFECT_SEEDS: - switch (GetBattlerHoldEffectParam(battler)) - { - case HOLD_EFFECT_PARAM_ELECTRIC_TERRAIN: - effect = TryHandleSeed(battler, STATUS_FIELD_ELECTRIC_TERRAIN, STAT_DEF, gLastUsedItem, caseID); - break; - case HOLD_EFFECT_PARAM_GRASSY_TERRAIN: - effect = TryHandleSeed(battler, STATUS_FIELD_GRASSY_TERRAIN, STAT_DEF, gLastUsedItem, caseID); - break; - case HOLD_EFFECT_PARAM_MISTY_TERRAIN: - effect = TryHandleSeed(battler, STATUS_FIELD_MISTY_TERRAIN, STAT_SPDEF, gLastUsedItem, caseID); - break; - case HOLD_EFFECT_PARAM_PSYCHIC_TERRAIN: - effect = TryHandleSeed(battler, STATUS_FIELD_PSYCHIC_TERRAIN, STAT_SPDEF, gLastUsedItem, caseID); - break; - } - break; - case HOLD_EFFECT_BERSERK_GENE: - effect = ConsumeBerserkGene(battler, caseID); - break; - case HOLD_EFFECT_MIRROR_HERB: - effect = TryConsumeMirrorHerb(battler, caseID); - break; - case HOLD_EFFECT_BOOSTER_ENERGY: - effect = TryBoosterEnergy(battler, GetBattlerAbility(battler), caseID); - break; - default: - break; - } - if (effect != 0) - { - gSpecialStatuses[battler].switchInItemDone = TRUE; - gBattlerAttacker = gPotentialItemEffectBattler = gBattleScripting.battler = battler; - if (effect == ITEM_STATUS_CHANGE) - { - BtlController_EmitSetMonData(battler, B_COMM_TO_CONTROLLER, REQUEST_STATUS_BATTLE, 0, 4, &gBattleMons[battler].status1); - MarkBattlerForControllerExec(battler); - } - } - } - break; - case ITEMEFFECT_NORMAL: - case ITEMEFFECT_TRY_HEALING: - if (gBattleMons[battler].hp) - { - switch (battlerHoldEffect) - { - case HOLD_EFFECT_RESTORE_HP: - effect = ItemHealHp(battler, gLastUsedItem, caseID, FALSE); - break; - case HOLD_EFFECT_RESTORE_PCT_HP: - effect = ItemHealHp(battler, gLastUsedItem, caseID, TRUE); - break; - case HOLD_EFFECT_RESTORE_PP: - effect = ItemRestorePp(battler, gLastUsedItem, caseID); - break; - case HOLD_EFFECT_WHITE_HERB: - effect = RestoreWhiteHerbStats(battler); - if (effect != 0) - BattleScriptExecute(BattleScript_WhiteHerbEnd2); - break; - case HOLD_EFFECT_BLACK_SLUDGE: - if (IS_BATTLER_OF_TYPE(battler, TYPE_POISON)) - { - goto LEFTOVERS; - } - else if (!IsAbilityAndRecord(battler, GetBattlerAbility(battler), ABILITY_MAGIC_GUARD)) - { - gBattleStruct->moveDamage[battler] = GetNonDynamaxMaxHP(battler) / 8; - if (gBattleStruct->moveDamage[battler] == 0) - gBattleStruct->moveDamage[battler] = 1; - BattleScriptExecute(BattleScript_ItemHurtEnd2); - effect = ITEM_HP_CHANGE; - RecordItemEffectBattle(battler, battlerHoldEffect); - PREPARE_ITEM_BUFFER(gBattleTextBuff1, gLastUsedItem); - } - break; - case HOLD_EFFECT_LEFTOVERS: - LEFTOVERS: - if (gBattleMons[battler].hp < gBattleMons[battler].maxHP - && (B_HEAL_BLOCKING < GEN_5 || !gBattleMons[battler].volatiles.healBlock)) - { - gBattleStruct->moveDamage[battler] = GetNonDynamaxMaxHP(battler) / 16; - if (gBattleStruct->moveDamage[battler] == 0) - gBattleStruct->moveDamage[battler] = 1; - gBattleStruct->moveDamage[battler] *= -1; - BattleScriptExecute(BattleScript_ItemHealHP_End2); - effect = ITEM_HP_CHANGE; - RecordItemEffectBattle(battler, battlerHoldEffect); - } - break; - case HOLD_EFFECT_CONFUSE_SPICY: - effect = HealConfuseBerry(battler, gLastUsedItem, FLAVOR_SPICY, caseID); - break; - case HOLD_EFFECT_CONFUSE_DRY: - effect = HealConfuseBerry(battler, gLastUsedItem, FLAVOR_DRY, caseID); - break; - case HOLD_EFFECT_CONFUSE_SWEET: - effect = HealConfuseBerry(battler, gLastUsedItem, FLAVOR_SWEET, caseID); - break; - case HOLD_EFFECT_CONFUSE_BITTER: - effect = HealConfuseBerry(battler, gLastUsedItem, FLAVOR_BITTER, caseID); - break; - case HOLD_EFFECT_CONFUSE_SOUR: - effect = HealConfuseBerry(battler, gLastUsedItem, FLAVOR_SOUR, caseID); - break; - case HOLD_EFFECT_ATTACK_UP: - effect = StatRaiseBerry(battler, gLastUsedItem, STAT_ATK, caseID); - break; - case HOLD_EFFECT_DEFENSE_UP: - effect = StatRaiseBerry(battler, gLastUsedItem, STAT_DEF, caseID); - break; - case HOLD_EFFECT_SPEED_UP: - effect = StatRaiseBerry(battler, gLastUsedItem, STAT_SPEED, caseID); - break; - case HOLD_EFFECT_SP_ATTACK_UP: - effect = StatRaiseBerry(battler, gLastUsedItem, STAT_SPATK, caseID); - break; - case HOLD_EFFECT_SP_DEFENSE_UP: - effect = StatRaiseBerry(battler, gLastUsedItem, STAT_SPDEF, caseID); - break; - case HOLD_EFFECT_CRITICAL_UP: - if (!(gBattleMons[battler].volatiles.dragonCheer || gBattleMons[battler].volatiles.focusEnergy) - && HasEnoughHpToEatBerry(battler, GetBattlerItemHoldEffectParam(battler, gLastUsedItem), gLastUsedItem)) - { - gBattleMons[battler].volatiles.focusEnergy = TRUE; - gBattleScripting.battler = battler; - BattleScriptExecute(BattleScript_BerryFocusEnergyEnd2); - effect = ITEM_EFFECT_OTHER; - } - break; - case HOLD_EFFECT_RANDOM_STAT_UP: - effect = RandomStatRaiseBerry(battler, gLastUsedItem, caseID); - break; - case HOLD_EFFECT_CURE_PAR: - if (gBattleMons[battler].status1 & STATUS1_PARALYSIS && !UnnerveOn(battler, gLastUsedItem)) - { - gBattleMons[battler].status1 &= ~STATUS1_PARALYSIS; - BattleScriptExecute(BattleScript_BerryCurePrlzEnd2); - effect = ITEM_STATUS_CHANGE; - } - break; - case HOLD_EFFECT_CURE_PSN: - if (gBattleMons[battler].status1 & STATUS1_PSN_ANY && !UnnerveOn(battler, gLastUsedItem)) - { - gBattleMons[battler].status1 &= ~(STATUS1_PSN_ANY | STATUS1_TOXIC_COUNTER); - BattleScriptExecute(BattleScript_BerryCurePsnEnd2); - effect = ITEM_STATUS_CHANGE; - } - break; - case HOLD_EFFECT_CURE_BRN: - if (gBattleMons[battler].status1 & STATUS1_BURN && !UnnerveOn(battler, gLastUsedItem)) - { - gBattleMons[battler].status1 &= ~STATUS1_BURN; - BattleScriptExecute(BattleScript_BerryCureBrnEnd2); - effect = ITEM_STATUS_CHANGE; - } - break; - case HOLD_EFFECT_CURE_FRZ: - if (gBattleMons[battler].status1 & STATUS1_FREEZE && !UnnerveOn(battler, gLastUsedItem)) - { - gBattleMons[battler].status1 &= ~STATUS1_FREEZE; - BattleScriptExecute(BattleScript_BerryCureFrzEnd2); - effect = ITEM_STATUS_CHANGE; - } - if (gBattleMons[battler].status1 & STATUS1_FROSTBITE && !UnnerveOn(battler, gLastUsedItem)) - { - gBattleMons[battler].status1 &= ~STATUS1_FROSTBITE; - BattleScriptExecute(BattleScript_BerryCureFrbEnd2); - effect = ITEM_STATUS_CHANGE; - } - break; - case HOLD_EFFECT_CURE_SLP: - if (gBattleMons[battler].status1 & STATUS1_SLEEP && !UnnerveOn(battler, gLastUsedItem)) - { - gBattleMons[battler].status1 &= ~STATUS1_SLEEP; - gBattleMons[battler].volatiles.nightmare = FALSE; - BattleScriptExecute(BattleScript_BerryCureSlpEnd2); - effect = ITEM_STATUS_CHANGE; - TryDeactivateSleepClause(GetBattlerSide(battler), gBattlerPartyIndexes[battler]); - } - break; - case HOLD_EFFECT_CURE_CONFUSION: - if (gBattleMons[battler].volatiles.confusionTurns > 0 && !UnnerveOn(battler, gLastUsedItem)) - { - RemoveConfusionStatus(battler); - BattleScriptExecute(BattleScript_BerryCureConfusionEnd2); - effect = ITEM_EFFECT_OTHER; - } - break; - case HOLD_EFFECT_CURE_STATUS: - effect = TryCureStatus(battler, caseID); - break; - case HOLD_EFFECT_MENTAL_HERB: - if (GetMentalHerbEffect(battler)) - { - gBattleScripting.savedBattler = gBattlerAttacker; - gBattlerAttacker = battler; - BattleScriptExecute(BattleScript_MentalHerbCureEnd2); - effect = ITEM_EFFECT_OTHER; - } - break; - case HOLD_EFFECT_MICLE_BERRY: - effect = TrySetMicleBerry(battler, gLastUsedItem, caseID); - break; - case HOLD_EFFECT_BERSERK_GENE: - effect = ConsumeBerserkGene(battler, caseID); - break; - case HOLD_EFFECT_MIRROR_HERB: - effect = TryConsumeMirrorHerb(battler, caseID); - break; - default: - break; - } - - if (effect != 0) - { - gBattlerAttacker = gPotentialItemEffectBattler = gBattleScripting.battler = battler; - if (effect == ITEM_STATUS_CHANGE) - { - BtlController_EmitSetMonData(battler, B_COMM_TO_CONTROLLER, REQUEST_STATUS_BATTLE, 0, 4, &gBattleMons[battler].status1); - MarkBattlerForControllerExec(battler); - } - } - } - break; - case ITEMEFFECT_USE_LAST_ITEM: - effect = ItemEffectMoveEnd(battler, GetItemHoldEffect(gLastUsedItem)); - gBattleScripting.overrideBerryRequirements = 2; // to exit VARIOUS_CONSUME_BERRIES - if (effect) - { - gPotentialItemEffectBattler = gBattleScripting.battler = battler; - if (effect == ITEM_STATUS_CHANGE) - { - BtlController_EmitSetMonData(battler, B_COMM_TO_CONTROLLER, REQUEST_STATUS_BATTLE, 0, 4, &gBattleMons[battler].status1); - MarkBattlerForControllerExec(battler); - } - break; - } - break; - case ITEMEFFECT_MOVE_END: - for (battler = 0; battler < gBattlersCount; battler++) - { - // If item can be knocked off berry activation will be blocked, but not other items - if (gBattleStruct->battlerState[battler].itemCanBeKnockedOff - && (GetItemPocket(gBattleMons[battler].item) == POCKET_BERRIES - || GetBattlerHoldEffect(battler, TRUE) == HOLD_EFFECT_RESTORE_HP)) - continue; - - gLastUsedItem = gBattleMons[battler].item; - effect = ItemEffectMoveEnd(battler, GetBattlerHoldEffect(battler, TRUE)); - if (effect) - { - gPotentialItemEffectBattler = gBattleScripting.battler = battler; - if (effect == ITEM_STATUS_CHANGE) - { - BtlController_EmitSetMonData(battler, B_COMM_TO_CONTROLLER, REQUEST_STATUS_BATTLE, 0, 4, &gBattleMons[battler].status1); - MarkBattlerForControllerExec(battler); - } - break; - } - } - break; - case ITEMEFFECT_KINGSROCK: - // Occur on each hit of a multi-strike move - switch (atkHoldEffect) - { - case HOLD_EFFECT_FLINCH: - { - u16 ability = GetBattlerAbility(gBattlerAttacker); - if (B_SERENE_GRACE_BOOST >= GEN_5 && ability == ABILITY_SERENE_GRACE) - atkHoldEffectParam *= 2; - if (gSideStatuses[GetBattlerSide(battler)] & SIDE_STATUS_RAINBOW && gCurrentMove != MOVE_SECRET_POWER) - atkHoldEffectParam *= 2; - if (IsBattlerTurnDamaged(gBattlerTarget) - && !MoveIgnoresKingsRock(gCurrentMove) - && gBattleMons[gBattlerTarget].hp - && RandomPercentage(RNG_HOLD_EFFECT_FLINCH, atkHoldEffectParam) - && ability != ABILITY_STENCH) - { - gBattleScripting.moveEffect = MOVE_EFFECT_FLINCH; - BattleScriptPushCursor(); - SetMoveEffect(gBattlerAttacker, gBattlerTarget, FALSE, FALSE); - BattleScriptPop(); - } - } - break; - case HOLD_EFFECT_BLUNDER_POLICY: - if (gBattleStruct->blunderPolicy - && IsBattlerAlive(gBattlerAttacker) - && CompareStat(gBattlerAttacker, STAT_SPEED, MAX_STAT_STAGE, CMP_LESS_THAN, GetBattlerAbility(gBattlerAttacker))) - { - gBattleStruct->blunderPolicy = FALSE; - gLastUsedItem = atkItem; - SET_STATCHANGER(STAT_SPEED, 2, FALSE); - effect = ITEM_STATS_CHANGE; - BattleScriptCall(BattleScript_AttackerItemStatRaise); - } - break; - default: - break; - } - break; - case ITEMEFFECT_LIFEORB_SHELLBELL: - // Occur after the final hit of a multi-strike move - switch (atkHoldEffect) - { - case HOLD_EFFECT_SHELL_BELL: - if (gBattleScripting.savedDmg > 0 - && !(gHitMarker & HITMARKER_UNABLE_TO_USE_MOVE) - && !(gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_NO_EFFECT) - && gBattlerAttacker != gBattlerTarget - && !IsBattlerAtMaxHp(gBattlerAttacker) - && IsBattlerAlive(gBattlerAttacker) - && GetMoveEffect(gCurrentMove) != EFFECT_FUTURE_SIGHT - && GetMoveEffect(gCurrentMove) != EFFECT_PAIN_SPLIT - && (B_HEAL_BLOCKING < GEN_5 || !gBattleMons[battler].volatiles.healBlock)) - { - gLastUsedItem = atkItem; - gPotentialItemEffectBattler = gBattlerAttacker; - gBattleScripting.battler = gBattlerAttacker; - gBattleStruct->moveDamage[gBattlerAttacker] = (gBattleScripting.savedDmg / atkHoldEffectParam) * -1; - if (gBattleStruct->moveDamage[gBattlerAttacker] == 0) - gBattleStruct->moveDamage[gBattlerAttacker] = -1; - BattleScriptCall(BattleScript_ItemHealHP_Ret); - effect = ITEM_HP_CHANGE; - } - break; - case HOLD_EFFECT_LIFE_ORB: - if (IsBattlerAlive(gBattlerAttacker) - && !(gHitMarker & HITMARKER_UNABLE_TO_USE_MOVE) - && (IsBattlerTurnDamaged(gBattlerTarget) || gBattleScripting.savedDmg > 0) - && !IsAbilityAndRecord(gBattlerAttacker, GetBattlerAbility(gBattlerAttacker), ABILITY_MAGIC_GUARD) - && !IsFutureSightAttackerInParty(gBattlerAttacker, gBattlerTarget, gCurrentMove)) - { - gBattleStruct->moveDamage[gBattlerAttacker] = GetNonDynamaxMaxHP(gBattlerAttacker) / 10; - if (gBattleStruct->moveDamage[gBattlerAttacker] == 0) - gBattleStruct->moveDamage[gBattlerAttacker] = 1; - effect = ITEM_HP_CHANGE; - BattleScriptCall(BattleScript_ItemHurtRet); - gLastUsedItem = atkItem; - } - break; - default: - break; - } - break; - case ITEMEFFECT_TARGET: - if (!(gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_NO_EFFECT)) - { - moveType = GetBattleMoveType(gCurrentMove); - switch (battlerHoldEffect) - { - case HOLD_EFFECT_AIR_BALLOON: - if (IsBattlerTurnDamaged(gBattlerTarget)) - { - effect = ITEM_EFFECT_OTHER; - BattleScriptCall(BattleScript_AirBaloonMsgPop); - } - break; - case HOLD_EFFECT_ROCKY_HELMET: - if (IsBattlerTurnDamaged(gBattlerTarget) - && !CanBattlerAvoidContactEffects(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerAttacker), GetBattlerHoldEffect(gBattlerAttacker, TRUE), gCurrentMove) - && IsBattlerAlive(gBattlerAttacker) - && GetBattlerAbility(gBattlerAttacker) != ABILITY_MAGIC_GUARD) - { - gBattleStruct->moveDamage[gBattlerAttacker] = GetNonDynamaxMaxHP(gBattlerAttacker) / 6; - if (gBattleStruct->moveDamage[gBattlerAttacker] == 0) - gBattleStruct->moveDamage[gBattlerAttacker] = 1; - effect = ITEM_HP_CHANGE; - BattleScriptCall(BattleScript_RockyHelmetActivates); - PREPARE_ITEM_BUFFER(gBattleTextBuff1, gLastUsedItem); - RecordItemEffectBattle(battler, HOLD_EFFECT_ROCKY_HELMET); - } - break; - case HOLD_EFFECT_WEAKNESS_POLICY: - if (IsBattlerAlive(battler) - && IsBattlerTurnDamaged(gBattlerTarget) - && gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_SUPER_EFFECTIVE) - { - effect = ITEM_STATS_CHANGE; - BattleScriptCall(BattleScript_WeaknessPolicy); - } - break; - case HOLD_EFFECT_SNOWBALL: - if (IsBattlerAlive(battler) - && IsBattlerTurnDamaged(gBattlerTarget) - && moveType == TYPE_ICE) - { - effect = ITEM_STATS_CHANGE; - BattleScriptCall(BattleScript_TargetItemStatRaise); - SET_STATCHANGER(STAT_ATK, 1, FALSE); - } - break; - case HOLD_EFFECT_LUMINOUS_MOSS: - if (IsBattlerAlive(battler) - && IsBattlerTurnDamaged(gBattlerTarget) - && moveType == TYPE_WATER) - { - effect = ITEM_STATS_CHANGE; - BattleScriptCall(BattleScript_TargetItemStatRaise); - SET_STATCHANGER(STAT_SPDEF, 1, FALSE); - } - break; - case HOLD_EFFECT_CELL_BATTERY: - if (IsBattlerAlive(battler) - && IsBattlerTurnDamaged(gBattlerTarget) - && moveType == TYPE_ELECTRIC) - { - effect = ITEM_STATS_CHANGE; - BattleScriptCall(BattleScript_TargetItemStatRaise); - SET_STATCHANGER(STAT_ATK, 1, FALSE); - } - break; - case HOLD_EFFECT_ABSORB_BULB: - if (IsBattlerAlive(battler) - && IsBattlerTurnDamaged(gBattlerTarget) - && moveType == TYPE_WATER) - { - effect = ITEM_STATS_CHANGE; - BattleScriptCall(BattleScript_TargetItemStatRaise); - SET_STATCHANGER(STAT_SPATK, 1, FALSE); - } - break; - case HOLD_EFFECT_ENIGMA_BERRY: // consume and heal if hit by super effective move - effect = TrySetEnigmaBerry(battler); - break; - case HOLD_EFFECT_JABOCA_BERRY: // consume and damage attacker if used physical move - if (IsBattlerAlive(gBattlerAttacker) - && IsBattlerTurnDamaged(gBattlerTarget) - && !DoesSubstituteBlockMove(gBattlerAttacker, battler, gCurrentMove) - && IsBattleMovePhysical(gCurrentMove) - && GetBattlerAbility(gBattlerAttacker) != ABILITY_MAGIC_GUARD) - { - gBattleStruct->moveDamage[gBattlerAttacker] = GetNonDynamaxMaxHP(gBattlerAttacker) / 8; - if (gBattleStruct->moveDamage[gBattlerAttacker] == 0) - gBattleStruct->moveDamage[gBattlerAttacker] = 1; - if (GetBattlerAbility(battler) == ABILITY_RIPEN) - gBattleStruct->moveDamage[gBattlerAttacker] *= 2; - - effect = ITEM_HP_CHANGE; - BattleScriptCall(BattleScript_JabocaRowapBerryActivates); - PREPARE_ITEM_BUFFER(gBattleTextBuff1, gLastUsedItem); - RecordItemEffectBattle(battler, HOLD_EFFECT_JABOCA_BERRY); - } - break; - case HOLD_EFFECT_ROWAP_BERRY: // consume and damage attacker if used special move - if (IsBattlerAlive(gBattlerAttacker) - && IsBattlerTurnDamaged(gBattlerTarget) - && !DoesSubstituteBlockMove(gBattlerAttacker, battler, gCurrentMove) - && IsBattleMoveSpecial(gCurrentMove) - && GetBattlerAbility(gBattlerAttacker) != ABILITY_MAGIC_GUARD) - { - gBattleStruct->moveDamage[gBattlerAttacker] = GetNonDynamaxMaxHP(gBattlerAttacker) / 8; - if (gBattleStruct->moveDamage[gBattlerAttacker] == 0) - gBattleStruct->moveDamage[gBattlerAttacker] = 1; - if (GetBattlerAbility(battler) == ABILITY_RIPEN) - gBattleStruct->moveDamage[gBattlerAttacker] *= 2; - - effect = ITEM_HP_CHANGE; - BattleScriptCall(BattleScript_JabocaRowapBerryActivates); - PREPARE_ITEM_BUFFER(gBattleTextBuff1, gLastUsedItem); - RecordItemEffectBattle(battler, HOLD_EFFECT_ROWAP_BERRY); - } - break; - case HOLD_EFFECT_KEE_BERRY: // consume and boost defense if used physical move - effect = DamagedStatBoostBerryEffect(battler, STAT_DEF, DAMAGE_CATEGORY_PHYSICAL); - break; - case HOLD_EFFECT_MARANGA_BERRY: // consume and boost sp. defense if used special move - effect = DamagedStatBoostBerryEffect(battler, STAT_SPDEF, DAMAGE_CATEGORY_SPECIAL); - break; - case HOLD_EFFECT_CURE_STATUS: // only Toxic Chain's interaction with Knock Off - case HOLD_EFFECT_CURE_PSN: - if (gBattleMons[battler].status1 & STATUS1_PSN_ANY && !UnnerveOn(battler, gLastUsedItem) && GetBattlerAbility(gBattlerAttacker) == ABILITY_TOXIC_CHAIN && GetMoveEffect(gCurrentMove) == EFFECT_KNOCK_OFF) - { - gBattleScripting.battler = battler; - gBattleMons[battler].status1 &= ~(STATUS1_PSN_ANY | STATUS1_TOXIC_COUNTER); - BattleScriptExecute(BattleScript_BerryCurePsnEnd2); - BtlController_EmitSetMonData(battler, 0, REQUEST_STATUS_BATTLE, 0, 4, &gBattleMons[battler].status1); - MarkBattlerForControllerExec(battler); - effect = ITEM_STATUS_CHANGE; - } - break; - case HOLD_EFFECT_STICKY_BARB: - if (IsBattlerTurnDamaged(gBattlerTarget) - && !(gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_NO_EFFECT) - && !CanBattlerAvoidContactEffects(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerAttacker), GetBattlerHoldEffect(gBattlerAttacker, TRUE), gCurrentMove) - && !DoesSubstituteBlockMove(gBattlerAttacker, battler, gCurrentMove) - && IsBattlerAlive(gBattlerAttacker) - && CanStealItem(gBattlerAttacker, gBattlerTarget, gBattleMons[gBattlerTarget].item) - && gBattleMons[gBattlerAttacker].item == ITEM_NONE) - { - // No sticky hold checks. - gEffectBattler = battler; // gEffectBattler = target - StealTargetItem(gBattlerAttacker, gBattlerTarget); // Attacker takes target's barb - BattleScriptCall(BattleScript_StickyBarbTransfer); - effect = ITEM_EFFECT_OTHER; - } - break; - default: - break; - } - } - break; - case ITEMEFFECT_ORBS: - { - u16 battlerAbility = GetBattlerAbility(battler); - switch (battlerHoldEffect) - { - case HOLD_EFFECT_TOXIC_ORB: - if (CanBePoisoned(battler, battler, battlerAbility, battlerAbility)) // Can corrosion trigger toxic orb on itself? - { - effect = ITEM_STATUS_CHANGE; - gBattleMons[battler].status1 = STATUS1_TOXIC_POISON; - BattleScriptExecute(BattleScript_ToxicOrb); - RecordItemEffectBattle(battler, battlerHoldEffect); - } - break; - case HOLD_EFFECT_FLAME_ORB: - if (CanBeBurned(battler, battler, battlerAbility)) - { - effect = ITEM_STATUS_CHANGE; - gBattleMons[battler].status1 = STATUS1_BURN; - BattleScriptExecute(BattleScript_FlameOrb); - RecordItemEffectBattle(battler, battlerHoldEffect); - } - break; - case HOLD_EFFECT_STICKY_BARB: // Not an orb per se, but similar effect, and needs to NOT activate with pickpocket - if (battlerAbility != ABILITY_MAGIC_GUARD) - { - gBattleStruct->moveDamage[battler] = GetNonDynamaxMaxHP(battler) / 8; - if (gBattleStruct->moveDamage[battler] == 0) - gBattleStruct->moveDamage[battler] = 1; - BattleScriptExecute(BattleScript_ItemHurtEnd2); - effect = ITEM_HP_CHANGE; - RecordItemEffectBattle(battler, battlerHoldEffect); - PREPARE_ITEM_BUFFER(gBattleTextBuff1, gLastUsedItem); - } - break; - default: - break; - } - - if (effect == ITEM_STATUS_CHANGE) - { - BtlController_EmitSetMonData(battler, B_COMM_TO_CONTROLLER, REQUEST_STATUS_BATTLE, 0, 4, &gBattleMons[battler].status1); - MarkBattlerForControllerExec(battler); - } - } - break; - case ITEMEFFECT_STATS_CHANGED: - switch (battlerHoldEffect) - { - case HOLD_EFFECT_WHITE_HERB: - effect = RestoreWhiteHerbStats(battler); - if (effect != 0) - BattleScriptCall(BattleScript_WhiteHerbRet); - break; - default: - break; - } - break; - } - - // Berry was successfully used on a Pokemon. - if (effect && (gLastUsedItem >= FIRST_BERRY_INDEX && gLastUsedItem <= LAST_BERRY_INDEX)) - GetBattlerPartyState(battler)->ateBerry = TRUE; - - return effect; -} - void ClearVariousBattlerFlags(u32 battler) { gDisableStructs[battler].furyCutterCounter = 0; - gBattleMons[battler].volatiles.destinyBond = FALSE; + gBattleMons[battler].volatiles.destinyBond = 0; gBattleMons[battler].volatiles.glaiveRush = FALSE; gBattleMons[battler].volatiles.grudge = FALSE; } @@ -7284,7 +6345,7 @@ u32 GetBattleMoveTarget(u16 move, u8 setTarget) { u8 targetBattler = 0; u32 moveTarget, side; - u32 moveType = GetBattleMoveType(move); + enum Type moveType = GetBattleMoveType(move); if (setTarget != NO_TARGET_OVERRIDE) moveTarget = setTarget - 1; @@ -7302,7 +6363,7 @@ u32 GetBattleMoveTarget(u16 move, u8 setTarget) } else { - u32 battlerAbilityOnField = 0; + enum Ability battlerAbilityOnField = 0; targetBattler = SetRandomTarget(gBattlerAttacker); if (moveType == TYPE_ELECTRIC && GetBattlerAbility(targetBattler) != ABILITY_LIGHTNING_ROD) @@ -7316,7 +6377,7 @@ u32 GetBattleMoveTarget(u16 move, u8 setTarget) { targetBattler = battlerAbilityOnField - 1; RecordAbilityBattle(targetBattler, gBattleMons[targetBattler].ability); - gSpecialStatuses[targetBattler].lightningRodRedirected = TRUE; + gSpecialStatuses[targetBattler].abilityRedirected = TRUE; } } else if (moveType == TYPE_WATER && GetBattlerAbility(targetBattler) != ABILITY_STORM_DRAIN) @@ -7330,7 +6391,7 @@ u32 GetBattleMoveTarget(u16 move, u8 setTarget) { targetBattler = battlerAbilityOnField - 1; RecordAbilityBattle(targetBattler, gBattleMons[targetBattler].ability); - gSpecialStatuses[targetBattler].lightningRodRedirected = TRUE; + gSpecialStatuses[targetBattler].abilityRedirected = TRUE; } } } @@ -7339,7 +6400,7 @@ u32 GetBattleMoveTarget(u16 move, u8 setTarget) case MOVE_TARGET_BOTH: case MOVE_TARGET_FOES_AND_ALLY: targetBattler = GetOpposingSideBattler(gBattlerAttacker); - if (!IsBattlerAlive(targetBattler)) + if (IsDoubleBattle() && !IsBattlerAlive(targetBattler)) targetBattler ^= BIT_FLANK; break; case MOVE_TARGET_OPPONENTS_FIELD: @@ -7474,27 +6535,24 @@ u8 GetAttackerObedienceForAction() } } -enum ItemHoldEffect GetBattlerHoldEffect(u32 battler, bool32 checkNegating) +enum HoldEffect GetBattlerHoldEffect(u32 battler) { - return GetBattlerHoldEffectInternal(battler, checkNegating, TRUE); + return GetBattlerHoldEffectInternal(battler, GetBattlerAbility(battler)); } -enum ItemHoldEffect GetBattlerHoldEffectIgnoreAbility(u32 battler, bool32 checkNegating) +enum HoldEffect GetBattlerHoldEffectIgnoreAbility(u32 battler) { - return GetBattlerHoldEffectInternal(battler, checkNegating, FALSE); + return GetBattlerHoldEffectInternal(battler, ABILITY_NONE); } -enum ItemHoldEffect GetBattlerHoldEffectInternal(u32 battler, bool32 checkNegating, bool32 checkAbility) +enum HoldEffect GetBattlerHoldEffectInternal(u32 battler, u32 ability) { - if (checkNegating) - { - if (gBattleMons[battler].volatiles.embargo) - return HOLD_EFFECT_NONE; - if (gFieldStatuses & STATUS_FIELD_MAGIC_ROOM) - return HOLD_EFFECT_NONE; - if (checkAbility && GetBattlerAbility(battler) == ABILITY_KLUTZ && !gBattleMons[battler].volatiles.gastroAcid) - return HOLD_EFFECT_NONE; - } + if (gBattleMons[battler].volatiles.embargo) + return HOLD_EFFECT_NONE; + if (gFieldStatuses & STATUS_FIELD_MAGIC_ROOM) + return HOLD_EFFECT_NONE; + if (ability == ABILITY_KLUTZ && !gBattleMons[battler].volatiles.gastroAcid) + return HOLD_EFFECT_NONE; gPotentialItemEffectBattler = battler; @@ -7504,12 +6562,13 @@ enum ItemHoldEffect GetBattlerHoldEffectInternal(u32 battler, bool32 checkNegati return GetItemHoldEffect(gBattleMons[battler].item); } -static u32 GetBattlerItemHoldEffectParam(u32 battler, u32 item) +enum HoldEffect GetBattlerHoldEffectIgnoreNegation(u32 battler) { - if (item == ITEM_ENIGMA_BERRY_E_READER) - return gEnigmaBerries[battler].holdEffectParam; + gPotentialItemEffectBattler = battler; + if (gBattleMons[battler].item == ITEM_ENIGMA_BERRY_E_READER) + return gEnigmaBerries[battler].holdEffect; else - return GetItemHoldEffectParam(item); + return GetItemHoldEffect(gBattleMons[battler].item); } u32 GetBattlerHoldEffectParam(u32 battler) @@ -7520,7 +6579,7 @@ u32 GetBattlerHoldEffectParam(u32 battler) return GetItemHoldEffectParam(gBattleMons[battler].item); } -bool32 CanBattlerAvoidContactEffects(u32 battlerAtk, u32 battlerDef, u32 abilityAtk, enum ItemHoldEffect holdEffectAtk, u32 move) +bool32 CanBattlerAvoidContactEffects(u32 battlerAtk, u32 battlerDef, enum Ability abilityAtk, enum HoldEffect holdEffectAtk, u32 move) { if (holdEffectAtk == HOLD_EFFECT_PROTECTIVE_PADS) { @@ -7531,7 +6590,7 @@ bool32 CanBattlerAvoidContactEffects(u32 battlerAtk, u32 battlerDef, u32 ability return !IsMoveMakingContact(battlerAtk, battlerDef, abilityAtk, holdEffectAtk, move); } -bool32 IsMoveMakingContact(u32 battlerAtk, u32 battlerDef, u32 abilityAtk, enum ItemHoldEffect holdEffectAtk, u32 move) +bool32 IsMoveMakingContact(u32 battlerAtk, u32 battlerDef, enum Ability abilityAtk, enum HoldEffect holdEffectAtk, u32 move) { if (!(MoveMakesContact(move) || (GetMoveEffect(move) == EFFECT_SHELL_SIDE_ARM && gBattleStruct->shellSideArmCategory[battlerAtk][battlerDef] == DAMAGE_CATEGORY_PHYSICAL))) @@ -7568,7 +6627,7 @@ bool32 IsBattlerProtected(u32 battlerAtk, u32 battlerDef, u32 move) if (IsZMove(move) || IsMaxMove(move)) return FALSE; // Z-Moves and Max Moves bypass protection (except Max Guard). if (GetBattlerAbility(battlerAtk) == ABILITY_UNSEEN_FIST - && IsMoveMakingContact(battlerAtk, battlerDef, ABILITY_UNSEEN_FIST, GetBattlerHoldEffect(battlerAtk, TRUE), move)) + && IsMoveMakingContact(battlerAtk, battlerDef, ABILITY_UNSEEN_FIST, GetBattlerHoldEffect(battlerAtk), move)) return FALSE; } @@ -7649,11 +6708,9 @@ enum IronBallCheck }; // Only called directly when calculating damage type effectiveness, and Iron Ball's type effectiveness mechanics -static bool32 IsBattlerGroundedInverseCheck(u32 battler, u32 ability, enum InverseBattleCheck checkInverse, enum IronBallCheck checkIronBall, bool32 isAnticipation) +static bool32 IsBattlerGroundedInverseCheck(u32 battler, enum Ability ability, enum HoldEffect holdEffect, enum InverseBattleCheck checkInverse, bool32 isAnticipation) { - enum ItemHoldEffect holdEffect = GetBattlerHoldEffect(battler, TRUE); - - if (!(checkIronBall == IGNORE_IRON_BALL) && holdEffect == HOLD_EFFECT_IRON_BALL) + if (holdEffect == HOLD_EFFECT_IRON_BALL) return TRUE; if (gFieldStatuses & STATUS_FIELD_GRAVITY && isAnticipation == FALSE) return TRUE; @@ -7669,14 +6726,14 @@ static bool32 IsBattlerGroundedInverseCheck(u32 battler, u32 ability, enum Inver return FALSE; if (ability == ABILITY_LEVITATE) return FALSE; - if (IS_BATTLER_OF_TYPE(battler, TYPE_FLYING) && (!(checkInverse == INVERSE_BATTLE) || !FlagGet(B_FLAG_INVERSE_BATTLE))) + if (IS_BATTLER_OF_TYPE(battler, TYPE_FLYING) && (checkInverse != INVERSE_BATTLE || !FlagGet(B_FLAG_INVERSE_BATTLE))) return FALSE; return TRUE; } -bool32 IsBattlerGrounded(u32 battler) +bool32 IsBattlerGrounded(u32 battler, enum Ability ability, enum HoldEffect holdEffect) { - return IsBattlerGroundedInverseCheck(battler, GetBattlerAbility(battler), NOT_INVERSE_BATTLE, CHECK_IRON_BALL, FALSE); + return IsBattlerGroundedInverseCheck(battler, ability, holdEffect, NOT_INVERSE_BATTLE, FALSE); } u32 GetMoveSlot(u16 *moves, u32 move) @@ -7695,8 +6752,8 @@ u32 GetBattlerWeight(u32 battler) { u32 i; u32 weight = GetSpeciesWeight(gBattleMons[battler].species); - u32 ability = GetBattlerAbility(battler); - enum ItemHoldEffect holdEffect = GetBattlerHoldEffect(battler, TRUE); + enum Ability ability = GetBattlerAbility(battler); + enum HoldEffect holdEffect = GetBattlerHoldEffect(battler); if (ability == ABILITY_HEAVY_METAL) weight *= 2; @@ -7727,7 +6784,7 @@ u32 GetBattlerWeight(u32 battler) u32 CountBattlerStatIncreases(u32 battler, bool32 countEvasionAcc) { - u32 i; + enum Stat i; u32 count = 0; for (i = 0; i < NUM_BATTLE_STATS; i++) @@ -7741,6 +6798,24 @@ u32 CountBattlerStatIncreases(u32 battler, bool32 countEvasionAcc) return count; } +bool32 BattlerHasCopyableChanges(u32 battler) +{ + u32 i; + + for (i = 0; i < NUM_BATTLE_STATS; i++) + { + if (gBattleMons[battler].statStages[i] != DEFAULT_STAT_STAGE) + return TRUE; + } + + if (gBattleMons[battler].volatiles.focusEnergy + || gBattleMons[battler].volatiles.dragonCheer + || gBattleMons[battler].volatiles.bonusCritStages != 0) + return TRUE; + + return FALSE; +} + u32 GetMoveTargetCount(struct DamageContext *ctx) { u32 battlerAtk = ctx->battlerAtk; @@ -7884,7 +6959,7 @@ u32 CalcFuryCutterBasePower(u32 basePower, u32 furyCutterCounter) return basePower; } -static inline u32 IsFieldMudSportAffected(u32 moveType) +static inline u32 IsFieldMudSportAffected(enum Type moveType) { if (moveType == TYPE_ELECTRIC && (gFieldStatuses & STATUS_FIELD_MUDSPORT)) return TRUE; @@ -7901,7 +6976,7 @@ static inline u32 IsFieldMudSportAffected(u32 moveType) return FALSE; } -static inline u32 IsFieldWaterSportAffected(u32 moveType) +static inline u32 IsFieldWaterSportAffected(enum Type moveType) { if (moveType == TYPE_FIRE && (gFieldStatuses & STATUS_FIELD_WATERSPORT)) return TRUE; @@ -7930,7 +7005,7 @@ static inline u32 CalcMoveBasePower(struct DamageContext *ctx) u32 weight, hpFraction, speed; if (GetActiveGimmick(battlerAtk) == GIMMICK_Z_MOVE) - return GetZMovePower(gBattleStruct->zmove.baseMoves[battlerAtk]); + return GetZMovePower(gCurrentMove); if (GetActiveGimmick(battlerAtk) == GIMMICK_DYNAMAX) return GetMaxMovePower(move); @@ -7981,10 +7056,7 @@ static inline u32 CalcMoveBasePower(struct DamageContext *ctx) basePower = 100 * gDisableStructs[battlerAtk].stockpileCounter; break; case EFFECT_REVENGE: - if ((gProtectStructs[battlerAtk].physicalDmg - && gProtectStructs[battlerAtk].physicalBattlerId == battlerDef) - || (gProtectStructs[battlerAtk].specialDmg - && gProtectStructs[battlerAtk].specialBattlerId == battlerDef)) + if (gProtectStructs[battlerAtk].revengeDoubled & 1u << battlerDef) basePower *= 2; break; case EFFECT_WEATHER_BALL: @@ -8024,7 +7096,7 @@ static inline u32 CalcMoveBasePower(struct DamageContext *ctx) case EFFECT_ACROBATICS: if (gBattleMons[battlerAtk].item == ITEM_NONE // Edge case, because removal of items happens after damage calculation. - || (gSpecialStatuses[battlerAtk].gemBoost && GetBattlerHoldEffect(battlerAtk, FALSE) == HOLD_EFFECT_GEMS)) + || (gSpecialStatuses[battlerAtk].gemBoost && GetBattlerHoldEffect(battlerAtk) == HOLD_EFFECT_GEMS)) basePower *= 2; break; case EFFECT_LOW_KICK: @@ -8055,21 +7127,21 @@ static inline u32 CalcMoveBasePower(struct DamageContext *ctx) basePower += (CountBattlerStatIncreases(battlerAtk, TRUE) * 20); break; case EFFECT_ELECTRO_BALL: - speed = GetBattlerTotalSpeedStat(battlerAtk) / GetBattlerTotalSpeedStat(battlerDef); + speed = GetBattlerTotalSpeedStat(battlerAtk, ctx->abilityAtk, ctx->holdEffectAtk) / GetBattlerTotalSpeedStat(battlerDef, ctx->abilityDef, ctx->holdEffectDef); if (speed >= ARRAY_COUNT(sSpeedDiffPowerTable)) speed = ARRAY_COUNT(sSpeedDiffPowerTable) - 1; basePower = sSpeedDiffPowerTable[speed]; break; case EFFECT_GYRO_BALL: { - u32 attackerSpeed = GetBattlerTotalSpeedStat(battlerAtk); + u32 attackerSpeed = GetBattlerTotalSpeedStat(battlerAtk, ctx->abilityAtk, ctx->holdEffectAtk); if (attackerSpeed == 0) { basePower = 1; } else { - basePower = ((25 * GetBattlerTotalSpeedStat(battlerDef)) / attackerSpeed) + 1; + basePower = ((25 * GetBattlerTotalSpeedStat(battlerDef, ctx->abilityDef, ctx->holdEffectDef)) / attackerSpeed) + 1; if (basePower > 150) basePower = 150; } @@ -8110,7 +7182,7 @@ static inline u32 CalcMoveBasePower(struct DamageContext *ctx) basePower *= 2; break; case EFFECT_MISTY_EXPLOSION: - if (IsBattlerTerrainAffected(battlerAtk, STATUS_FIELD_MISTY_TERRAIN)) + if (IsBattlerTerrainAffected(battlerAtk, ctx->abilityAtk, ctx->holdEffectAtk, STATUS_FIELD_MISTY_TERRAIN)) basePower = uq4_12_multiply(basePower, UQ_4_12(1.5)); break; case EFFECT_DYNAMAX_DOUBLE_DMG: @@ -8137,19 +7209,19 @@ static inline u32 CalcMoveBasePower(struct DamageContext *ctx) basePower = uq4_12_multiply(basePower, UQ_4_12(1.5)); break; case EFFECT_TERRAIN_PULSE: - if (IsBattlerTerrainAffected(battlerAtk, STATUS_FIELD_TERRAIN_ANY)) + if (IsBattlerTerrainAffected(battlerAtk, ctx->abilityAtk, ctx->holdEffectAtk, STATUS_FIELD_TERRAIN_ANY)) basePower *= 2; break; case EFFECT_EXPANDING_FORCE: - if (IsBattlerTerrainAffected(battlerAtk, STATUS_FIELD_PSYCHIC_TERRAIN)) + if (IsBattlerTerrainAffected(battlerAtk, ctx->abilityAtk, ctx->holdEffectAtk, STATUS_FIELD_PSYCHIC_TERRAIN)) basePower = uq4_12_multiply(basePower, UQ_4_12(1.5)); break; case EFFECT_RISING_VOLTAGE: - if (IsBattlerTerrainAffected(battlerDef, STATUS_FIELD_ELECTRIC_TERRAIN)) + if (IsBattlerTerrainAffected(battlerDef, ctx->abilityDef, ctx->holdEffectDef, STATUS_FIELD_ELECTRIC_TERRAIN)) basePower *= 2; break; case EFFECT_BEAT_UP: - if (B_BEAT_UP >= GEN_5) + if (GetConfig(CONFIG_BEAT_UP) >= GEN_5) basePower = CalcBeatUpPower(); break; case EFFECT_PSYBLADE: @@ -8157,7 +7229,7 @@ static inline u32 CalcMoveBasePower(struct DamageContext *ctx) basePower = uq4_12_multiply(basePower, UQ_4_12(1.5)); break; case EFFECT_MAX_MOVE: - basePower = GetMaxMovePower(gBattleMons[battlerAtk].moves[gBattleStruct->chosenMovePositions[battlerAtk]]); + basePower = GetMaxMovePower(GetChosenMoveFromPosition(battlerAtk)); break; case EFFECT_RAGE_FIST: basePower += 50 * GetBattlerPartyState(battlerAtk)->timesGotHit; @@ -8199,7 +7271,7 @@ static inline u32 CalcMoveBasePowerAfterModifiers(struct DamageContext *ctx) u32 battlerAtk = ctx->battlerAtk; u32 battlerDef = ctx->battlerDef; u32 move = ctx->move; - u32 moveType = ctx->moveType; + enum Type moveType = ctx->moveType; enum BattleMoveEffects moveEffect = GetMoveEffect(move); uq4_12_t holdEffectModifier; @@ -8250,17 +7322,17 @@ static inline u32 CalcMoveBasePowerAfterModifiers(struct DamageContext *ctx) if (gSpecialStatuses[battlerAtk].gemBoost) modifier = uq4_12_multiply(modifier, uq4_12_add(UQ_4_12(1.0), PercentToUQ4_12(gSpecialStatuses[battlerAtk].gemParam))); - if (gBattleMons[battlerAtk].volatiles.charge && moveType == TYPE_ELECTRIC) + if (moveType == TYPE_ELECTRIC && gBattleMons[battlerAtk].volatiles.chargeTimer > 0) modifier = uq4_12_multiply(modifier, UQ_4_12(2.0)); - if (GetMoveEffect(gChosenMove) == EFFECT_ME_FIRST) + if (GetMoveEffect(ctx->chosenMove) == EFFECT_ME_FIRST) modifier = uq4_12_multiply(modifier, UQ_4_12(1.5)); - if (IsBattlerTerrainAffected(battlerAtk, STATUS_FIELD_GRASSY_TERRAIN) && moveType == TYPE_GRASS) + if (IsBattlerTerrainAffected(battlerAtk, ctx->abilityAtk, ctx->holdEffectAtk, STATUS_FIELD_GRASSY_TERRAIN) && moveType == TYPE_GRASS) modifier = uq4_12_multiply(modifier, (B_TERRAIN_TYPE_BOOST >= GEN_8 ? UQ_4_12(1.3) : UQ_4_12(1.5))); - if (IsBattlerTerrainAffected(battlerDef, STATUS_FIELD_MISTY_TERRAIN) && moveType == TYPE_DRAGON) + if (IsBattlerTerrainAffected(battlerDef, ctx->abilityDef, ctx->holdEffectDef, STATUS_FIELD_MISTY_TERRAIN) && moveType == TYPE_DRAGON) modifier = uq4_12_multiply(modifier, UQ_4_12(0.5)); - if (IsBattlerTerrainAffected(battlerAtk, STATUS_FIELD_ELECTRIC_TERRAIN) && moveType == TYPE_ELECTRIC) + if (IsBattlerTerrainAffected(battlerAtk, ctx->abilityAtk, ctx->holdEffectAtk, STATUS_FIELD_ELECTRIC_TERRAIN) && moveType == TYPE_ELECTRIC) modifier = uq4_12_multiply(modifier, (B_TERRAIN_TYPE_BOOST >= GEN_8 ? UQ_4_12(1.3) : UQ_4_12(1.5))); - if (IsBattlerTerrainAffected(battlerAtk, STATUS_FIELD_PSYCHIC_TERRAIN) && moveType == TYPE_PSYCHIC) + if (IsBattlerTerrainAffected(battlerAtk, ctx->abilityAtk, ctx->holdEffectAtk, STATUS_FIELD_PSYCHIC_TERRAIN) && moveType == TYPE_PSYCHIC) modifier = uq4_12_multiply(modifier, (B_TERRAIN_TYPE_BOOST >= GEN_8 ? UQ_4_12(1.3) : UQ_4_12(1.5))); if (IsFieldMudSportAffected(ctx->moveType)) modifier = uq4_12_multiply(modifier, UQ_4_12(B_SPORT_DMG_REDUCTION >= GEN_5 ? 0.33 : 0.5)); @@ -8306,7 +7378,7 @@ static inline u32 CalcMoveBasePowerAfterModifiers(struct DamageContext *ctx) modifier = uq4_12_multiply(modifier, UQ_4_12(0.75)); break; case ABILITY_ANALYTIC: - if (GetBattlerTurnOrderNum(battlerAtk) == gBattlersCount - 1 && move != MOVE_FUTURE_SIGHT && move != MOVE_DOOM_DESIRE) + if (IsLastMonToMove(battlerAtk) && move != MOVE_FUTURE_SIGHT && move != MOVE_DOOM_DESIRE) modifier = uq4_12_multiply(modifier, UQ_4_12(1.3)); break; case ABILITY_TOUGH_CLAWS: @@ -8331,22 +7403,22 @@ static inline u32 CalcMoveBasePowerAfterModifiers(struct DamageContext *ctx) break; case ABILITY_PIXILATE: if (moveType == TYPE_FAIRY && gBattleStruct->battlerState[battlerAtk].ateBoost) - modifier = uq4_12_multiply(modifier, UQ_4_12(GetGenConfig(GEN_CONFIG_ATE_MULTIPLIER) >= GEN_7 ? 1.2 : 1.3)); + modifier = uq4_12_multiply(modifier, UQ_4_12(GetConfig(CONFIG_ATE_MULTIPLIER) >= GEN_7 ? 1.2 : 1.3)); break; case ABILITY_GALVANIZE: if (moveType == TYPE_ELECTRIC && gBattleStruct->battlerState[battlerAtk].ateBoost) - modifier = uq4_12_multiply(modifier, UQ_4_12(GetGenConfig(GEN_CONFIG_ATE_MULTIPLIER) >= GEN_7 ? 1.2 : 1.3)); + modifier = uq4_12_multiply(modifier, UQ_4_12(GetConfig(CONFIG_ATE_MULTIPLIER) >= GEN_7 ? 1.2 : 1.3)); break; case ABILITY_REFRIGERATE: if (moveType == TYPE_ICE && gBattleStruct->battlerState[battlerAtk].ateBoost) - modifier = uq4_12_multiply(modifier, UQ_4_12(GetGenConfig(GEN_CONFIG_ATE_MULTIPLIER) >= GEN_7 ? 1.2 : 1.3)); + modifier = uq4_12_multiply(modifier, UQ_4_12(GetConfig(CONFIG_ATE_MULTIPLIER) >= GEN_7 ? 1.2 : 1.3)); break; case ABILITY_AERILATE: if (moveType == TYPE_FLYING && gBattleStruct->battlerState[battlerAtk].ateBoost) - modifier = uq4_12_multiply(modifier, UQ_4_12(GetGenConfig(GEN_CONFIG_ATE_MULTIPLIER) >= GEN_7 ? 1.2 : 1.3)); + modifier = uq4_12_multiply(modifier, UQ_4_12(GetConfig(CONFIG_ATE_MULTIPLIER) >= GEN_7 ? 1.2 : 1.3)); break; case ABILITY_NORMALIZE: - if (moveType == TYPE_NORMAL && gBattleStruct->battlerState[battlerAtk].ateBoost && GetGenConfig(GEN_CONFIG_ATE_MULTIPLIER) >= GEN_7) + if (moveType == TYPE_NORMAL && gBattleStruct->battlerState[battlerAtk].ateBoost && GetConfig(CONFIG_ATE_MULTIPLIER) >= GEN_7) modifier = uq4_12_multiply(modifier, UQ_4_12(1.2)); break; case ABILITY_PUNK_ROCK: @@ -8364,6 +7436,8 @@ static inline u32 CalcMoveBasePowerAfterModifiers(struct DamageContext *ctx) case ABILITY_SUPREME_OVERLORD: modifier = uq4_12_multiply(modifier, GetSupremeOverlordModifier(battlerAtk)); break; + default: + break; } // field abilities @@ -8392,6 +7466,8 @@ static inline u32 CalcMoveBasePowerAfterModifiers(struct DamageContext *ctx) if (moveType == TYPE_STEEL) modifier = uq4_12_multiply(modifier, UQ_4_12(1.5)); break; + default: + break; } } @@ -8413,7 +7489,7 @@ static inline u32 CalcMoveBasePowerAfterModifiers(struct DamageContext *ctx) break; case ABILITY_PROTOSYNTHESIS: { - u8 defHighestStat = GetHighestStatId(battlerDef); + enum Stat defHighestStat = GetParadoxBoostedStatId(battlerDef); if (((ctx->weather & B_WEATHER_SUN && HasWeatherEffect()) || gDisableStructs[battlerDef].boosterEnergyActivated) && ((IsBattleMovePhysical(move) && defHighestStat == STAT_DEF) || (IsBattleMoveSpecial(move) && defHighestStat == STAT_SPDEF)) && !(gBattleMons[battlerDef].volatiles.transformed)) @@ -8422,13 +7498,15 @@ static inline u32 CalcMoveBasePowerAfterModifiers(struct DamageContext *ctx) break; case ABILITY_QUARK_DRIVE: { - u8 defHighestStat = GetHighestStatId(battlerDef); + u32 defHighestStat = GetParadoxBoostedStatId(battlerDef); if ((gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN || gDisableStructs[battlerDef].boosterEnergyActivated) && ((IsBattleMovePhysical(move) && defHighestStat == STAT_DEF) || (IsBattleMoveSpecial(move) && defHighestStat == STAT_SPDEF)) && !(gBattleMons[battlerDef].volatiles.transformed)) modifier = uq4_12_multiply(modifier, UQ_4_12(0.7)); } break; + default: + break; } holdEffectParamAtk = GetBattlerHoldEffectParam(battlerAtk); @@ -8501,6 +7579,26 @@ static inline u32 CalcMoveBasePowerAfterModifiers(struct DamageContext *ctx) return uq4_12_multiply_by_int_half_down(modifier, basePower); } +static bool32 IsRuinStatusActive(u32 fieldEffect) +{ + bool32 isNeutralizingGasOnField = IsNeutralizingGasOnField(); + for (u32 battler = 0; battler < gBattlersCount; battler++) + { + // Mold Breaker doesn't ignore Ruin field status but Gastro Acid and Neutralizing Gas do + if (gBattleMons[battler].volatiles.gastroAcid) + continue; + if (GetBattlerHoldEffectIgnoreAbility(battler) != HOLD_EFFECT_ABILITY_SHIELD + && isNeutralizingGasOnField + && gBattleMons[battler].ability != ABILITY_NEUTRALIZING_GAS) + continue; + + if (GetBattlerVolatile(battler, fieldEffect)) + return TRUE; + } + + return FALSE; +} + static inline uq4_12_t ApplyOffensiveBadgeBoost(uq4_12_t modifier, u32 battler, u32 move) { if (ShouldGetStatBadgeBoost(B_FLAG_BADGE_BOOST_ATTACK, battler) && IsBattleMovePhysical(move)) @@ -8528,7 +7626,7 @@ static inline u32 CalcAttackStat(struct DamageContext *ctx) u32 battlerAtk = ctx->battlerAtk; u32 battlerDef = ctx->battlerDef; u32 move = ctx->move; - u32 moveType = ctx->moveType; + enum Type moveType = ctx->moveType; enum BattleMoveEffects moveEffect = GetMoveEffect(move); atkBaseSpeciesId = GET_BASE_SPECIES_ID(gBattleMons[battlerAtk].species); @@ -8602,7 +7700,7 @@ static inline u32 CalcAttackStat(struct DamageContext *ctx) modifier = uq4_12_multiply_half_down(modifier, UQ_4_12(2.0)); break; case ABILITY_SLOW_START: - if (gDisableStructs[battlerAtk].slowStartTimer > gBattleTurnCounter) + if (gDisableStructs[battlerAtk].slowStartTimer > 0) modifier = uq4_12_multiply_half_down(modifier, UQ_4_12(0.5)); break; case ABILITY_SOLAR_POWER: @@ -8636,7 +7734,7 @@ static inline u32 CalcAttackStat(struct DamageContext *ctx) case ABILITY_PLUS: if (IsBattleMoveSpecial(move) && IsBattlerAlive(BATTLE_PARTNER(battlerAtk))) { - u32 partnerAbility = GetBattlerAbility(BATTLE_PARTNER(battlerAtk)); + enum Ability partnerAbility = GetBattlerAbility(BATTLE_PARTNER(battlerAtk)); if (partnerAbility == ABILITY_MINUS || (B_PLUS_MINUS_INTERACTION >= GEN_5 && partnerAbility == ABILITY_PLUS)) modifier = uq4_12_multiply_half_down(modifier, UQ_4_12(1.5)); @@ -8645,7 +7743,7 @@ static inline u32 CalcAttackStat(struct DamageContext *ctx) case ABILITY_MINUS: if (IsBattleMoveSpecial(move) && IsBattlerAlive(BATTLE_PARTNER(battlerAtk))) { - u32 partnerAbility = GetBattlerAbility(BATTLE_PARTNER(battlerAtk)); + enum Ability partnerAbility = GetBattlerAbility(BATTLE_PARTNER(battlerAtk)); if (partnerAbility == ABILITY_PLUS || (B_PLUS_MINUS_INTERACTION >= GEN_5 && partnerAbility == ABILITY_MINUS)) modifier = uq4_12_multiply_half_down(modifier, UQ_4_12(1.5)); @@ -8670,7 +7768,7 @@ static inline u32 CalcAttackStat(struct DamageContext *ctx) case ABILITY_TRANSISTOR: if (moveType == TYPE_ELECTRIC) { - if (GetGenConfig(GEN_CONFIG_TRANSISTOR_BOOST) >= GEN_9) + if (GetConfig(CONFIG_TRANSISTOR_BOOST) >= GEN_9) modifier = uq4_12_multiply(modifier, UQ_4_12(1.3)); else modifier = uq4_12_multiply(modifier, UQ_4_12(1.5)); @@ -8691,7 +7789,7 @@ static inline u32 CalcAttackStat(struct DamageContext *ctx) case ABILITY_PROTOSYNTHESIS: if (!(gBattleMons[battlerAtk].volatiles.transformed)) { - u32 atkHighestStat = GetHighestStatId(battlerAtk); + enum Stat atkHighestStat = GetParadoxBoostedStatId(battlerAtk); if (((ctx->weather & B_WEATHER_SUN) && HasWeatherEffect()) || gDisableStructs[battlerAtk].boosterEnergyActivated) { if ((IsBattleMovePhysical(move) && atkHighestStat == STAT_ATK) || (IsBattleMoveSpecial(move) && atkHighestStat == STAT_SPATK)) @@ -8702,7 +7800,7 @@ static inline u32 CalcAttackStat(struct DamageContext *ctx) case ABILITY_QUARK_DRIVE: if (!(gBattleMons[battlerAtk].volatiles.transformed)) { - u32 atkHighestStat = GetHighestStatId(battlerAtk); + enum Stat atkHighestStat = GetParadoxBoostedStatId(battlerAtk); if (gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN || gDisableStructs[battlerAtk].boosterEnergyActivated) { if ((IsBattleMovePhysical(move) && atkHighestStat == STAT_ATK) || (IsBattleMoveSpecial(move) && atkHighestStat == STAT_SPATK)) @@ -8718,6 +7816,8 @@ static inline u32 CalcAttackStat(struct DamageContext *ctx) if (gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN && IsBattleMoveSpecial(move)) modifier = uq4_12_multiply(modifier, UQ_4_12(1.3333)); break; + default: + break; } // target's abilities @@ -8739,6 +7839,8 @@ static inline u32 CalcAttackStat(struct DamageContext *ctx) RecordAbilityBattle(battlerDef, ABILITY_PURIFYING_SALT); } break; + default: + break; } // ally's abilities @@ -8750,14 +7852,16 @@ static inline u32 CalcAttackStat(struct DamageContext *ctx) if (gBattleMons[BATTLE_PARTNER(battlerAtk)].species == SPECIES_CHERRIM_SUNSHINE && IsBattlerWeatherAffected(BATTLE_PARTNER(battlerAtk), B_WEATHER_SUN) && IsBattleMovePhysical(move)) modifier = uq4_12_multiply_half_down(modifier, UQ_4_12(1.5)); break; + default: + break; } } - // field abilities - if (IsAbilityOnField(ABILITY_VESSEL_OF_RUIN) && ctx->abilityAtk != ABILITY_VESSEL_OF_RUIN && IsBattleMoveSpecial(move)) + // Ruin field effects + if (IsBattleMoveSpecial(move) && !gBattleMons[ctx->battlerAtk].volatiles.vesselOfRuin && IsRuinStatusActive(VOLATILE_VESSEL_OF_RUIN)) modifier = uq4_12_multiply_half_down(modifier, UQ_4_12(0.75)); - if (IsAbilityOnField(ABILITY_TABLETS_OF_RUIN) && ctx->abilityAtk != ABILITY_TABLETS_OF_RUIN && IsBattleMovePhysical(move)) + if (IsBattleMovePhysical(move) && !gBattleMons[ctx->battlerAtk].volatiles.tabletsOfRuin && IsRuinStatusActive(VOLATILE_TABLETS_OF_RUIN)) modifier = uq4_12_multiply_half_down(modifier, UQ_4_12(0.75)); // attacker's hold effect @@ -8906,6 +8010,8 @@ static inline u32 CalcDefenseStat(struct DamageContext *ctx) if (gBattleMons[battlerDef].species == SPECIES_CHERRIM_SUNSHINE && IsBattlerWeatherAffected(battlerDef, B_WEATHER_SUN) && !usesDefStat) modifier = uq4_12_multiply_half_down(modifier, UQ_4_12(1.5)); break; + default: + break; } // ally's abilities @@ -8917,14 +8023,16 @@ static inline u32 CalcDefenseStat(struct DamageContext *ctx) if (gBattleMons[BATTLE_PARTNER(battlerDef)].species == SPECIES_CHERRIM_SUNSHINE && IsBattlerWeatherAffected(BATTLE_PARTNER(battlerDef), B_WEATHER_SUN) && !usesDefStat) modifier = uq4_12_multiply_half_down(modifier, UQ_4_12(1.5)); break; + default: + break; } } - // field abilities - if (IsAbilityOnField(ABILITY_SWORD_OF_RUIN) && ctx->abilityDef != ABILITY_SWORD_OF_RUIN && usesDefStat) + // Ruin field effects + if (usesDefStat && !gBattleMons[ctx->battlerDef].volatiles.swordOfRuin && IsRuinStatusActive(VOLATILE_SWORD_OF_RUIN)) modifier = uq4_12_multiply_half_down(modifier, UQ_4_12(0.75)); - if (IsAbilityOnField(ABILITY_BEADS_OF_RUIN) && ctx->abilityDef != ABILITY_BEADS_OF_RUIN && !usesDefStat) + if (!usesDefStat && !gBattleMons[ctx->battlerDef].volatiles.beadsOfRuin && IsRuinStatusActive(VOLATILE_BEADS_OF_RUIN)) modifier = uq4_12_multiply_half_down(modifier, UQ_4_12(0.75)); // target's hold effects @@ -8958,7 +8066,7 @@ static inline u32 CalcDefenseStat(struct DamageContext *ctx) } // sandstorm sp.def boost for rock types - if (B_SANDSTORM_SPDEF_BOOST >= GEN_4 && IS_BATTLER_OF_TYPE(battlerDef, TYPE_ROCK) && IsBattlerWeatherAffected(battlerDef, B_WEATHER_SANDSTORM) && !usesDefStat) + if (GetConfig(CONFIG_SANDSTORM_SPDEF_BOOST) >= GEN_4 && IS_BATTLER_OF_TYPE(battlerDef, TYPE_ROCK) && IsBattlerWeatherAffected(battlerDef, B_WEATHER_SANDSTORM) && !usesDefStat) modifier = uq4_12_multiply_half_down(modifier, UQ_4_12(1.5)); // snow def boost for ice types if (IS_BATTLER_OF_TYPE(battlerDef, TYPE_ICE) && IsBattlerWeatherAffected(battlerDef, B_WEATHER_SNOW) && usesDefStat) @@ -8977,8 +8085,13 @@ static inline s32 CalculateBaseDamage(u32 power, u32 userFinalAttack, u32 level, static inline uq4_12_t GetTargetDamageModifier(struct DamageContext *ctx) { - if (IsDoubleBattle() && GetMoveTargetCount(ctx) >= 2) - return B_MULTIPLE_TARGETS_DMG >= GEN_4 ? UQ_4_12(0.75) : UQ_4_12(0.5); + if (IsDoubleBattle()) + { + if (GetMoveTargetCount(ctx) == 2) + return B_MULTIPLE_TARGETS_DMG >= GEN_4 ? UQ_4_12(0.75) : UQ_4_12(0.5); + else if (GetMoveTargetCount(ctx) >= 3) + return B_MULTIPLE_TARGETS_DMG >= GEN_4 ? UQ_4_12(0.75) : UQ_4_12(1.0); + } return UQ_4_12(1.0); } @@ -9031,12 +8144,12 @@ static inline uq4_12_t GetBurnOrFrostBiteModifier(struct DamageContext *ctx) if (gBattleMons[ctx->battlerAtk].status1 & STATUS1_BURN && IsBattleMovePhysical(ctx->move) - && (B_BURN_FACADE_DMG < GEN_6 || moveEffect != EFFECT_FACADE) + && (GetConfig(CONFIG_BURN_FACADE_DMG) < GEN_6 || moveEffect != EFFECT_FACADE) && ctx->abilityAtk != ABILITY_GUTS) return UQ_4_12(0.5); if (gBattleMons[ctx->battlerAtk].status1 & STATUS1_FROSTBITE && IsBattleMoveSpecial(ctx->move) - && (B_BURN_FACADE_DMG < GEN_6 || moveEffect != EFFECT_FACADE)) + && (GetConfig(CONFIG_BURN_FACADE_DMG) < GEN_6 || moveEffect != EFFECT_FACADE)) return UQ_4_12(0.5); return UQ_4_12(1.0); } @@ -9044,7 +8157,7 @@ static inline uq4_12_t GetBurnOrFrostBiteModifier(struct DamageContext *ctx) static inline uq4_12_t GetCriticalModifier(bool32 isCrit) { if (isCrit) - return GetGenConfig(GEN_CONFIG_CRIT_MULTIPLIER) >= GEN_6 ? UQ_4_12(1.5) : UQ_4_12(2.0); + return GetConfig(CONFIG_CRIT_MULTIPLIER) >= GEN_6 ? UQ_4_12(1.5) : UQ_4_12(2.0); return UQ_4_12(1.0); } @@ -9125,7 +8238,7 @@ static inline uq4_12_t GetCollisionCourseElectroDriftModifier(u32 move, uq4_12_t return UQ_4_12(1.0); } -static inline uq4_12_t GetAttackerAbilitiesModifier(u32 battlerAtk, uq4_12_t typeEffectivenessModifier, bool32 isCrit, u32 abilityAtk) +static inline uq4_12_t GetAttackerAbilitiesModifier(u32 battlerAtk, uq4_12_t typeEffectivenessModifier, bool32 isCrit, enum Ability abilityAtk) { switch (abilityAtk) { @@ -9141,6 +8254,8 @@ static inline uq4_12_t GetAttackerAbilitiesModifier(u32 battlerAtk, uq4_12_t typ if (typeEffectivenessModifier <= UQ_4_12(0.5)) return UQ_4_12(2.0); break; + default: + break; } return UQ_4_12(1.0); } @@ -9195,6 +8310,8 @@ static inline uq4_12_t GetDefenderAbilitiesModifier(struct DamageContext *ctx) recordAbility = TRUE; } break; + default: + break; } if (recordAbility && ctx->updateFlags) @@ -9213,11 +8330,13 @@ static inline uq4_12_t GetDefenderPartnerAbilitiesModifier(u32 battlerPartnerDef case ABILITY_FRIEND_GUARD: return UQ_4_12(0.75); break; + default: + break; } return UQ_4_12(1.0); } -static inline uq4_12_t GetAttackerItemsModifier(u32 battlerAtk, uq4_12_t typeEffectivenessModifier, enum ItemHoldEffect holdEffectAtk) +static inline uq4_12_t GetAttackerItemsModifier(u32 battlerAtk, uq4_12_t typeEffectivenessModifier, enum HoldEffect holdEffectAtk) { u32 metronomeTurns; uq4_12_t metronomeBoostBase; @@ -9248,7 +8367,7 @@ static inline uq4_12_t GetDefenderItemsModifier(struct DamageContext *ctx) switch (ctx->holdEffectDef) { case HOLD_EFFECT_RESIST_BERRY: - if (UnnerveOn(ctx->battlerDef, gBattleMons[ctx->battlerDef].item)) + if (IsUnnerveBlocked(ctx->battlerDef, gBattleMons[ctx->battlerDef].item)) return UQ_4_12(1.0); if (ctx->moveType == GetBattlerHoldEffectParam(ctx->battlerDef) && (ctx->moveType == TYPE_NORMAL || ctx->typeEffectivenessModifier >= UQ_4_12(2.0))) { @@ -9356,7 +8475,7 @@ static inline s32 DoMoveDamageCalcVars(struct DamageContext *ctx) s32 ApplyModifiersAfterDmgRoll(struct DamageContext *ctx, s32 dmg) { if (GetActiveGimmick(ctx->battlerAtk) == GIMMICK_TERA) - DAMAGE_APPLY_MODIFIER(GetTeraMultiplier(ctx->battlerAtk, ctx->moveType)); + DAMAGE_APPLY_MODIFIER(GetTeraMultiplier(ctx)); else DAMAGE_APPLY_MODIFIER(GetSameTypeAttackBonusModifier(ctx)); DAMAGE_APPLY_MODIFIER(ctx->typeEffectivenessModifier); @@ -9390,6 +8509,12 @@ s32 DoFixedDamageMoveCalc(struct DamageContext *ctx) case EFFECT_FINAL_GAMBIT: dmg = GetNonDynamaxHP(ctx->battlerAtk); break; + case EFFECT_BEAT_UP: + if (GetConfig(CONFIG_BEAT_UP) < GEN_5) + dmg = CalcBeatUpDamage(ctx); + else + return INT32_MAX; + break; default: return INT32_MAX; } @@ -9413,8 +8538,8 @@ static inline s32 DoMoveDamageCalc(struct DamageContext *ctx) ctx->abilityAtk = GetBattlerAbility(ctx->battlerAtk); ctx->abilityDef = GetBattlerAbility(ctx->battlerDef); - ctx->holdEffectDef = GetBattlerHoldEffect(ctx->battlerDef, TRUE); - ctx->holdEffectAtk = GetBattlerHoldEffect(ctx->battlerAtk, TRUE); + ctx->holdEffectDef = GetBattlerHoldEffect(ctx->battlerDef); + ctx->holdEffectAtk = GetBattlerHoldEffect(ctx->battlerAtk); return DoMoveDamageCalcVars(ctx); } @@ -9427,7 +8552,7 @@ static inline s32 DoFutureSightAttackDamageCalcVars(struct DamageContext *ctx) u32 battlerAtk = ctx->battlerAtk; u32 battlerDef = ctx->battlerDef; u32 move = ctx->move; - u32 moveType = ctx->moveType; + enum Type moveType = ctx->moveType; struct Pokemon *party = GetBattlerParty(battlerAtk); struct Pokemon *partyMon = &party[gWishFutureKnock.futureSightPartyIndex[battlerDef]]; @@ -9502,8 +8627,8 @@ s32 CalculateMoveDamage(struct DamageContext *ctx) ctx->weather = GetWeather(); ctx->abilityAtk = GetBattlerAbility(ctx->battlerAtk); ctx->abilityDef = GetBattlerAbility(ctx->battlerDef); - ctx->holdEffectAtk = GetBattlerHoldEffect(ctx->battlerAtk, TRUE); - ctx->holdEffectDef = GetBattlerHoldEffect(ctx->battlerDef, TRUE); + ctx->holdEffectAtk = GetBattlerHoldEffect(ctx->battlerAtk); + ctx->holdEffectDef = GetBattlerHoldEffect(ctx->battlerDef); ctx->typeEffectivenessModifier = CalcTypeEffectivenessMultiplier(ctx); @@ -9523,7 +8648,7 @@ s32 CalculateMoveDamageVars(struct DamageContext *ctx) return DoMoveDamageCalcVars(ctx); } -static inline void MulByTypeEffectiveness(struct DamageContext *ctx, uq4_12_t *modifier, u32 defType) +static inline void MulByTypeEffectiveness(struct DamageContext *ctx, uq4_12_t *modifier, enum Type defType) { uq4_12_t mod = GetTypeModifier(ctx->moveType, defType); @@ -9550,7 +8675,7 @@ static inline void MulByTypeEffectiveness(struct DamageContext *ctx, uq4_12_t *m mod = UQ_4_12(1.0); if (GetMoveEffect(ctx->move) == EFFECT_SUPER_EFFECTIVE_ON_ARG && defType == GetMoveArgType(ctx->move) && !ctx->isAnticipation) mod = UQ_4_12(2.0); - if (ctx->moveType == TYPE_GROUND && defType == TYPE_FLYING && IsBattlerGrounded(ctx->battlerDef) && mod == UQ_4_12(0.0)) + if (ctx->moveType == TYPE_GROUND && defType == TYPE_FLYING && IsBattlerGrounded(ctx->battlerDef, ctx->abilityDef, ctx->holdEffectDef) && mod == UQ_4_12(0.0)) mod = UQ_4_12(1.0); if (ctx->moveType == TYPE_STELLAR && GetActiveGimmick(ctx->battlerDef) == GIMMICK_TERA) mod = UQ_4_12(2.0); @@ -9576,7 +8701,7 @@ static inline void MulByTypeEffectiveness(struct DamageContext *ctx, uq4_12_t *m *modifier = uq4_12_multiply(*modifier, mod); } -static inline void TryNoticeIllusionInTypeEffectiveness(u32 move, u32 moveType, u32 battlerAtk, u32 battlerDef, uq4_12_t resultingModifier, u32 illusionSpecies) +static inline void TryNoticeIllusionInTypeEffectiveness(u32 move, enum Type moveType, u32 battlerAtk, u32 battlerDef, uq4_12_t resultingModifier, u32 illusionSpecies) { // Check if the type effectiveness would've been different if the pokemon really had the types as the disguise. uq4_12_t presumedModifier = UQ_4_12(1.0); @@ -9584,13 +8709,13 @@ static inline void TryNoticeIllusionInTypeEffectiveness(u32 move, u32 moveType, struct DamageContext ctx = {0}; ctx.battlerAtk = battlerAtk; ctx.battlerDef = battlerDef; - ctx.move = move; + ctx.move = ctx.chosenMove = move; ctx.moveType = moveType; ctx.updateFlags = FALSE; ctx.abilityAtk = GetBattlerAbility(battlerAtk); ctx.abilityDef = ABILITY_ILLUSION; - ctx.holdEffectAtk = GetBattlerHoldEffect(battlerAtk, TRUE); - ctx.holdEffectDef = GetBattlerHoldEffect(battlerDef, TRUE); + ctx.holdEffectAtk = GetBattlerHoldEffect(battlerAtk); + ctx.holdEffectDef = GetBattlerHoldEffect(battlerDef); MulByTypeEffectiveness(&ctx, &presumedModifier, GetSpeciesType(illusionSpecies, 0)); if (GetSpeciesType(illusionSpecies, 1) != GetSpeciesType(illusionSpecies, 0)) @@ -9627,7 +8752,7 @@ void UpdateMoveResultFlags(uq4_12_t modifier, u16 *resultFlags) static inline uq4_12_t CalcTypeEffectivenessMultiplierInternal(struct DamageContext *ctx, uq4_12_t modifier) { u32 illusionSpecies; - u32 types[3]; + enum Type types[3]; GetBattlerTypes(ctx->battlerDef, FALSE, types); MulByTypeEffectiveness(ctx, &modifier, types[0]); @@ -9647,7 +8772,7 @@ static inline uq4_12_t CalcTypeEffectivenessMultiplierInternal(struct DamageCont if (B_GLARE_GHOST < GEN_4 && ctx->move == MOVE_GLARE && IS_BATTLER_OF_TYPE(ctx->battlerDef, TYPE_GHOST)) modifier = UQ_4_12(0.0); } - else if (ctx->moveType == TYPE_GROUND && !IsBattlerGroundedInverseCheck(ctx->battlerDef, ctx->abilityDef, INVERSE_BATTLE, CHECK_IRON_BALL, ctx->isAnticipation) && !(MoveIgnoresTypeIfFlyingAndUngrounded(ctx->move))) + else if (ctx->moveType == TYPE_GROUND && !IsBattlerGroundedInverseCheck(ctx->battlerDef, ctx->abilityDef, ctx->holdEffectDef, INVERSE_BATTLE, ctx->isAnticipation) && !(MoveIgnoresTypeIfFlyingAndUngrounded(ctx->move))) { modifier = UQ_4_12(0.0); if (ctx->updateFlags && ctx->abilityDef == ABILITY_LEVITATE) @@ -9659,14 +8784,14 @@ static inline uq4_12_t CalcTypeEffectivenessMultiplierInternal(struct DamageCont RecordAbilityBattle(ctx->battlerDef, ABILITY_LEVITATE); } } - else if (GetGenConfig(GEN_CONFIG_SHEER_COLD_IMMUNITY) >= GEN_7 && GetMoveEffect(ctx->move) == EFFECT_SHEER_COLD && IS_BATTLER_OF_TYPE(ctx->battlerDef, TYPE_ICE)) + else if (GetConfig(CONFIG_SHEER_COLD_IMMUNITY) >= GEN_7 && GetMoveEffect(ctx->move) == EFFECT_SHEER_COLD && IS_BATTLER_OF_TYPE(ctx->battlerDef, TYPE_ICE)) { modifier = UQ_4_12(0.0); } // Thousand Arrows ignores type modifiers for flying mons - if (!IsBattlerGrounded(ctx->battlerDef) - && MoveIgnoresTypeIfFlyingAndUngrounded(ctx->move) + if (MoveIgnoresTypeIfFlyingAndUngrounded(ctx->move) + && !IsBattlerGrounded(ctx->battlerDef, ctx->abilityDef, ctx->holdEffectDef) && IS_BATTLER_OF_TYPE(ctx->battlerDef, TYPE_FLYING)) { modifier = UQ_4_12(1.0); @@ -9675,9 +8800,9 @@ static inline uq4_12_t CalcTypeEffectivenessMultiplierInternal(struct DamageCont // Iron Ball ignores type modifiers for flying-type mons if it is the only source of grounding if (B_IRON_BALL >= GEN_5 && ctx->moveType == TYPE_GROUND + && ctx->holdEffectDef == HOLD_EFFECT_IRON_BALL && IS_BATTLER_OF_TYPE(ctx->battlerDef, TYPE_FLYING) - && GetBattlerHoldEffect(ctx->battlerDef, TRUE) == HOLD_EFFECT_IRON_BALL - && !IsBattlerGroundedInverseCheck(ctx->battlerDef, ctx->abilityDef, NOT_INVERSE_BATTLE, IGNORE_IRON_BALL, FALSE) + && !IsBattlerGrounded(ctx->battlerDef, ctx->abilityDef, HOLD_EFFECT_NONE) // We want to ignore Iron Ball so skip item check && !FlagGet(B_FLAG_INVERSE_BATTLE)) { modifier = UQ_4_12(1.0); @@ -9723,15 +8848,15 @@ uq4_12_t CalcTypeEffectivenessMultiplier(struct DamageContext *ctx) return modifier; } -uq4_12_t CalcPartyMonTypeEffectivenessMultiplier(u16 move, u16 speciesDef, u16 abilityDef) +uq4_12_t CalcPartyMonTypeEffectivenessMultiplier(u16 move, u16 speciesDef, enum Ability abilityDef) { uq4_12_t modifier = UQ_4_12(1.0); - u32 moveType = GetBattleMoveType(move); + enum Type moveType = GetBattleMoveType(move); if (move != MOVE_STRUGGLE && moveType != TYPE_MYSTERY) { struct DamageContext ctx = {0}; - ctx.move = move; + ctx.move = ctx.chosenMove = move; ctx.moveType = moveType; ctx.updateFlags = FALSE; ctx.abilityDef = abilityDef; @@ -9764,19 +8889,19 @@ static uq4_12_t GetInverseTypeMultiplier(uq4_12_t multiplier) } } -uq4_12_t GetOverworldTypeEffectiveness(struct Pokemon *mon, u8 moveType) +uq4_12_t GetOverworldTypeEffectiveness(struct Pokemon *mon, enum Type moveType) { uq4_12_t modifier = UQ_4_12(1.0); - u16 abilityDef = GetMonAbility(mon); + enum Ability abilityDef = GetMonAbility(mon); u16 speciesDef = GetMonData(mon, MON_DATA_SPECIES); - u8 type1 = GetSpeciesType(speciesDef, 0); - u8 type2 = GetSpeciesType(speciesDef, 1); + enum Type type1 = GetSpeciesType(speciesDef, 0); + enum Type type2 = GetSpeciesType(speciesDef, 1); if (moveType == TYPE_MYSTERY) return modifier; struct DamageContext ctx = {0}; - ctx.move = MOVE_POUND; + ctx.move = ctx.chosenMove = MOVE_POUND; ctx.moveType = moveType; ctx.updateFlags = FALSE; @@ -9791,14 +8916,14 @@ uq4_12_t GetOverworldTypeEffectiveness(struct Pokemon *mon, u8 moveType) return modifier; } -uq4_12_t GetTypeModifier(u32 atkType, u32 defType) +uq4_12_t GetTypeModifier(enum Type atkType, enum Type defType) { if (B_FLAG_INVERSE_BATTLE != 0 && FlagGet(B_FLAG_INVERSE_BATTLE)) return GetInverseTypeMultiplier(gTypeEffectivenessTable[atkType][defType]); return gTypeEffectivenessTable[atkType][defType]; } -s32 GetStealthHazardDamageByTypesAndHP(enum TypeSideHazard hazardType, u8 type1, u8 type2, u32 maxHp) +s32 GetStealthHazardDamageByTypesAndHP(enum TypeSideHazard hazardType, enum Type type1, enum Type type2, u32 maxHp) { s32 dmg = 0; uq4_12_t modifier = UQ_4_12(1.0); @@ -9844,7 +8969,7 @@ s32 GetStealthHazardDamageByTypesAndHP(enum TypeSideHazard hazardType, u8 type1, s32 GetStealthHazardDamage(enum TypeSideHazard hazardType, u32 battler) { - u32 types[3]; + enum Type types[3]; GetBattlerTypes(battler, FALSE, types); u32 maxHp = gBattleMons[battler].maxHP; @@ -9853,14 +8978,10 @@ s32 GetStealthHazardDamage(enum TypeSideHazard hazardType, u32 battler) bool32 IsPartnerMonFromSameTrainer(u32 battler) { - if (!IsOnPlayerSide(battler) && gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS) - return FALSE; - else if (IsOnPlayerSide(battler) && gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER) - return FALSE; - else if (gBattleTypeFlags & BATTLE_TYPE_MULTI) - return FALSE; + if (!IsOnPlayerSide(battler)) + return !(gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS); else - return TRUE; + return !(gBattleTypeFlags & BATTLE_TYPE_MULTI); } bool32 DoesSpeciesUseHoldItemToChangeForm(u16 species, u16 heldItemId) @@ -9890,7 +9011,7 @@ bool32 DoesSpeciesUseHoldItemToChangeForm(u16 species, u16 heldItemId) bool32 CanMegaEvolve(u32 battler) { - enum ItemHoldEffect holdEffect = GetBattlerHoldEffect(battler, FALSE); + enum HoldEffect holdEffect = GetBattlerHoldEffectIgnoreNegation(battler); // Check if Player has a Mega Ring. if (!TESTING @@ -9928,7 +9049,7 @@ bool32 CanMegaEvolve(u32 battler) bool32 CanUltraBurst(u32 battler) { - enum ItemHoldEffect holdEffect = GetBattlerHoldEffect(battler, FALSE); + enum HoldEffect holdEffect = GetBattlerHoldEffectIgnoreNegation(battler); // Check if Player has a Z-Ring if (!TESTING && (GetBattlerPosition(battler) == B_POSITION_PLAYER_LEFT @@ -10115,7 +9236,7 @@ u16 GetBattleFormChangeTargetSpecies(u32 battler, enum FormChanges method) return targetSpecies; } -bool32 CanBattlerFormChange(u32 battler, enum FormChanges method) +static bool32 CanBattlerFormChange(u32 battler, enum FormChanges method) { // Can't change form if transformed. if (gBattleMons[battler].volatiles.transformed @@ -10149,7 +9270,7 @@ bool32 TryRevertPartyMonFormChange(u32 partyIndex) bool32 changedForm = FALSE; // Appeared in battle and didn't faint - if ((gBattleStruct->appearedInBattle & (1u << partyIndex)) && GetMonData(&gPlayerParty[partyIndex], MON_DATA_HP, NULL) != 0) + if (gBattleStruct->partyState[B_SIDE_PLAYER][partyIndex].sentOut && GetMonData(&gPlayerParty[partyIndex], MON_DATA_HP, NULL) != 0) changedForm = TryFormChange(partyIndex, B_SIDE_PLAYER, FORM_CHANGE_END_BATTLE_ENVIRONMENT); if (!changedForm) @@ -10210,7 +9331,7 @@ bool32 TryBattleFormChange(u32 battler, enum FormChanges method) if (restoreSpecies) { - u32 abilityForm = gBattleMons[battler].ability; + enum Ability abilityForm = gBattleMons[battler].ability; // Reverts the original species TryToSetBattleFormChangeMoves(&party[monId], method); u32 changedSpecies = GetBattlerPartyState(battler)->changedSpecies; @@ -10229,7 +9350,7 @@ bool32 TryBattleFormChange(u32 battler, enum FormChanges method) bool32 DoBattlersShareType(u32 battler1, u32 battler2) { s32 i; - u32 types1[3], types2[3]; + enum Type types1[3], types2[3]; GetBattlerTypes(battler1, FALSE, types1); GetBattlerTypes(battler2, FALSE, types2); @@ -10250,7 +9371,7 @@ bool32 DoBattlersShareType(u32 battler1, u32 battler2) bool32 CanBattlerGetOrLoseItem(u32 battler, u16 itemId) { u16 species = gBattleMons[battler].species; - enum ItemHoldEffect holdEffect = GetItemHoldEffect(itemId); + enum HoldEffect holdEffect = GetItemHoldEffect(itemId); if (ItemIsMail(itemId)) return FALSE; @@ -10275,7 +9396,7 @@ u32 GetBattlerVisualSpecies(u32 battler) return gBattleMons[battler].species; } -bool32 TryClearIllusion(u32 battler, u32 caseID) +bool32 TryClearIllusion(u32 battler, enum AbilityEffect caseID) { if (gBattleStruct->illusion[battler].state != ILLUSION_ON) return FALSE; @@ -10319,10 +9440,10 @@ u32 GetIllusionMonPartyId(struct Pokemon *party, struct Pokemon *mon, struct Pok s32 partyStart=0; // Adjust party search range for Multibattles and Player vs two-trainers - if((GetBattlerSide(battler) == B_SIDE_PLAYER && (gBattleTypeFlags & BATTLE_TYPE_MULTI)) + if ((GetBattlerSide(battler) == B_SIDE_PLAYER && (gBattleTypeFlags & BATTLE_TYPE_MULTI)) || (GetBattlerSide(battler) == B_SIDE_OPPONENT && (gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS))) { - if((GetBattlerPosition(battler) == B_POSITION_PLAYER_LEFT) || (GetBattlerPosition(battler) == B_POSITION_OPPONENT_LEFT)) + if ((GetBattlerPosition(battler) == B_POSITION_PLAYER_LEFT) || (GetBattlerPosition(battler) == B_POSITION_OPPONENT_LEFT)) { partyEnd = 3; partyStart = 0; @@ -10380,7 +9501,7 @@ bool32 SetIllusionMon(struct Pokemon *mon, u32 battler) return FALSE; } -u32 TryImmunityAbilityHealStatus(u32 battler, u32 caseID) +u32 TryImmunityAbilityHealStatus(u32 battler, enum AbilityEffect caseID) { u32 effect = 0; switch (GetBattlerAbilityIgnoreMoldBreaker(battler)) @@ -10436,7 +9557,7 @@ u32 TryImmunityAbilityHealStatus(u32 battler, u32 caseID) case ABILITY_OBLIVIOUS: if (gBattleMons[battler].volatiles.infatuation) effect = 3; - else if (GetGenConfig(GEN_CONFIG_OBLIVIOUS_TAUNT) >= GEN_6 && gDisableStructs[battler].tauntTimer != 0) + else if (GetConfig(CONFIG_OBLIVIOUS_TAUNT) >= GEN_6 && gDisableStructs[battler].tauntTimer != 0) effect = 4; break; } @@ -10447,28 +9568,28 @@ u32 TryImmunityAbilityHealStatus(u32 battler, u32 caseID) { case 1: // status cleared gBattleMons[battler].status1 = 0; - if(caseID == ABILITYEFFECT_ON_SWITCHIN_IMMUNITIES) + if (caseID == ABILITYEFFECT_ON_SWITCHIN_IMMUNITIES) BattleScriptExecute(BattleScript_AbilityCuredStatusEnd3); else BattleScriptCall(BattleScript_AbilityCuredStatus); break; case 2: // get rid of confusion RemoveConfusionStatus(battler); - if(caseID == ABILITYEFFECT_ON_SWITCHIN_IMMUNITIES) + if (caseID == ABILITYEFFECT_ON_SWITCHIN_IMMUNITIES) BattleScriptExecute(BattleScript_AbilityCuredStatusEnd3); else BattleScriptCall(BattleScript_AbilityCuredStatus); break; case 3: // get rid of infatuation gBattleMons[battler].volatiles.infatuation = 0; - if(caseID == ABILITYEFFECT_ON_SWITCHIN_IMMUNITIES) + if (caseID == ABILITYEFFECT_ON_SWITCHIN_IMMUNITIES) BattleScriptExecute(BattleScript_AbilityCuredStatusEnd3); else BattleScriptCall(BattleScript_AbilityCuredStatus); break; case 4: // get rid of taunt gDisableStructs[battler].tauntTimer = 0; - if(caseID == ABILITYEFFECT_ON_SWITCHIN_IMMUNITIES) + if (caseID == ABILITYEFFECT_ON_SWITCHIN_IMMUNITIES) BattleScriptExecute(BattleScript_AbilityCuredStatusEnd3); else BattleScriptCall(BattleScript_AbilityCuredStatus); @@ -10486,7 +9607,7 @@ u32 TryImmunityAbilityHealStatus(u32 battler, u32 caseID) uq4_12_t GetBadgeBoostModifier(void) { - if (GetGenConfig(GEN_CONFIG_BADGE_BOOST) < GEN_3) + if (GetConfig(CONFIG_BADGE_BOOST) < GEN_3) return UQ_4_12(1.125); else return UQ_4_12(1.1); @@ -10494,7 +9615,7 @@ uq4_12_t GetBadgeBoostModifier(void) bool32 ShouldGetStatBadgeBoost(u16 badgeFlag, u32 battler) { - if (GetGenConfig(GEN_CONFIG_BADGE_BOOST) <= GEN_3 && badgeFlag != 0) + if (GetConfig(CONFIG_BADGE_BOOST) <= GEN_3 && badgeFlag != 0) { if (gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_EREADER_TRAINER | BATTLE_TYPE_RECORDED_LINK | BATTLE_TYPE_FRONTIER)) return FALSE; @@ -10532,7 +9653,7 @@ enum DamageCategory GetBattleMoveCategory(u32 move) return DAMAGE_CATEGORY_STATUS; } - if (B_PHYSICAL_SPECIAL_SPLIT <= GEN_4) + if (B_PHYSICAL_SPECIAL_SPLIT < GEN_4) return gTypesInfo[GetBattleMoveType(move)].damageCategory; return GetMoveCategory(move); @@ -10586,29 +9707,6 @@ static bool32 TryRemoveScreens(u32 battler) return removed; } -static bool32 IsUnnerveAbilityOnOpposingSide(u32 battler) -{ - for (u32 battlerDef = 0; battlerDef < gBattlersCount; battlerDef++) - { - if (battler == battlerDef || IsBattlerAlly(battler, battlerDef)) - continue; - - if (!IsBattlerAlive(battlerDef)) - continue; - - u32 ability = GetBattlerAbility(battlerDef); - switch (ability) - { - case ABILITY_UNNERVE: - case ABILITY_AS_ONE_ICE_RIDER: - case ABILITY_AS_ONE_SHADOW_RIDER: - return TRUE; - } - } - - return FALSE; -} - // Photon Geyser, Light That Burns the Sky, Tera Blast enum DamageCategory GetCategoryBasedOnStats(u32 battler) { @@ -10663,7 +9761,10 @@ void SortBattlersBySpeed(u8 *battlers, bool32 slowToFast) u16 speeds[MAX_BATTLERS_COUNT] = {0}; for (i = 0; i < gBattlersCount; i++) - speeds[i] = GetBattlerTotalSpeedStat(battlers[i]); + { + u32 battler = battlers[i]; + speeds[i] = GetBattlerTotalSpeedStat(battler, GetBattlerAbility(battler), GetBattlerHoldEffect(battler)); + } for (i = 1; i < gBattlersCount; i++) { @@ -10720,7 +9821,7 @@ void TryRestoreHeldItems(void) bool32 CanStealItem(u32 battlerStealing, u32 battlerItem, u16 item) { - u8 stealerSide = GetBattlerSide(battlerStealing); + enum BattleSide stealerSide = GetBattlerSide(battlerStealing); if (gBattleTypeFlags & BATTLE_TYPE_TRAINER_HILL) return FALSE; @@ -10777,7 +9878,7 @@ void TrySaveExchangedItem(u32 battler, u16 stolenItem) bool32 IsBattlerAffectedByHazards(u32 battler, bool32 toxicSpikes) { bool32 ret = TRUE; - enum ItemHoldEffect holdEffect = GetBattlerHoldEffect(battler, TRUE); + enum HoldEffect holdEffect = GetBattlerHoldEffect(battler); if (toxicSpikes && holdEffect == HOLD_EFFECT_HEAVY_DUTY_BOOTS && !IS_BATTLER_OF_TYPE(battler, TYPE_POISON)) { ret = FALSE; @@ -10796,8 +9897,8 @@ bool32 TestIfSheerForceAffected(u32 battler, u16 move) return GetBattlerAbility(battler) == ABILITY_SHEER_FORCE && MoveIsAffectedBySheerForce(move); } -// This function is the body of "jumpifstat", but can be used dynamically in a function. It considers Contrary. -bool32 CompareStat(u32 battler, u8 statId, u8 cmpTo, u8 cmpKind, u32 ability) +// This function is the body of "jumpifstat", but can be used dynamically in a function +bool32 CompareStat(u32 battler, enum Stat statId, u8 cmpTo, u8 cmpKind, enum Ability ability) { bool32 ret = FALSE; u8 statValue = gBattleMons[battler].statStages[statId]; @@ -10848,52 +9949,9 @@ bool32 CompareStat(u32 battler, u8 statId, u8 cmpTo, u8 cmpKind, u32 ability) return ret; } -void BufferStatChange(u32 battler, u8 statId, enum StringID stringId) -{ - bool32 hasContrary = (GetBattlerAbility(battler) == ABILITY_CONTRARY); - - PREPARE_STAT_BUFFER(gBattleTextBuff1, statId); - if (stringId == STRINGID_STATFELL) - { - if (hasContrary) - PREPARE_STRING_BUFFER(gBattleTextBuff2, STRINGID_STATROSE) - else - PREPARE_STRING_BUFFER(gBattleTextBuff2, STRINGID_STATFELL) - } - else if (stringId == STRINGID_STATROSE) - { - if (hasContrary) - PREPARE_STRING_BUFFER(gBattleTextBuff2, STRINGID_STATFELL) - else - PREPARE_STRING_BUFFER(gBattleTextBuff2, STRINGID_STATROSE) - } - else - { - PREPARE_STRING_BUFFER(gBattleTextBuff2, stringId) - } -} - -bool32 TryRoomService(u32 battler) -{ - if (gFieldStatuses & STATUS_FIELD_TRICK_ROOM && CompareStat(battler, STAT_SPEED, MIN_STAT_STAGE, CMP_GREATER_THAN, GetBattlerAbility(battler))) - { - BufferStatChange(battler, STAT_SPEED, STRINGID_STATFELL); - gEffectBattler = gBattleScripting.battler = battler; - SET_STATCHANGER(STAT_SPEED, 1, TRUE); - gBattleScripting.animArg1 = STAT_ANIM_PLUS1 + STAT_SPEED; - gBattleScripting.animArg2 = 0; - gLastUsedItem = gBattleMons[battler].item; - return TRUE; - } - else - { - return FALSE; - } -} - bool32 BlocksPrankster(u16 move, u32 battlerPrankster, u32 battlerDef, bool32 checkTarget) { - if (GetGenConfig(GEN_CONFIG_PRANKSTER_DARK_TYPES) < GEN_7) + if (GetConfig(CONFIG_PRANKSTER_DARK_TYPES) < GEN_7) return FALSE; if (!gProtectStructs[battlerPrankster].pranksterElevated) return FALSE; @@ -10909,17 +9967,12 @@ bool32 BlocksPrankster(u16 move, u32 battlerPrankster, u32 battlerDef, bool32 ch return TRUE; } -u16 GetUsedHeldItem(u32 battler) -{ - return gBattleStruct->usedHeldItems[gBattlerPartyIndexes[battler]][GetBattlerSide(battler)]; -} - bool32 CantPickupItem(u32 battler) { // Used by RandomUniformExcept() for RNG_PICKUP - if (battler == gBattlerAttacker && (GetGenConfig(GEN_PICKUP_WILD) < GEN_9 || gBattleTypeFlags & (BATTLE_TYPE_TRAINER | BATTLE_TYPE_LINK))) + if (battler == gBattlerAttacker && (GetConfig(CONFIG_PICKUP_WILD) < GEN_9 || gBattleTypeFlags & (BATTLE_TYPE_TRAINER | BATTLE_TYPE_LINK))) return TRUE; - return !(IsBattlerAlive(battler) && GetUsedHeldItem(battler) && gBattleStruct->battlerState[battler].canPickupItem); + return !(IsBattlerAlive(battler) && GetBattlerPartyState(battler)->usedHeldItem && gBattleStruct->battlerState[battler].canPickupItem); } bool32 PickupHasValidTarget(u32 battler) @@ -10938,7 +9991,7 @@ bool32 IsBattlerWeatherAffected(u32 battler, u32 weatherFlags) if (gBattleWeather & weatherFlags && HasWeatherEffect()) { // given weather is active -> check if its sun, rain against utility umbrella (since only 1 weather can be active at once) - if (gBattleWeather & (B_WEATHER_SUN | B_WEATHER_RAIN) && GetBattlerHoldEffect(battler, TRUE) == HOLD_EFFECT_UTILITY_UMBRELLA) + if (gBattleWeather & (B_WEATHER_SUN | B_WEATHER_RAIN) && GetBattlerHoldEffect(battler) == HOLD_EFFECT_UTILITY_UMBRELLA) return FALSE; // utility umbrella blocks sun, rain effects return TRUE; @@ -10948,12 +10001,13 @@ bool32 IsBattlerWeatherAffected(u32 battler, u32 weatherFlags) // Gets move target before redirection effects etc. are applied // Possible return values are defined in battle.h following MOVE_TARGET_SELECTED +// TODO: Add args: ability and hold effect u32 GetBattlerMoveTargetType(u32 battler, u32 move) { enum BattleMoveEffects effect = GetMoveEffect(move); if (effect == EFFECT_CURSE && !IS_BATTLER_OF_TYPE(battler, TYPE_GHOST)) return MOVE_TARGET_USER; - if (effect == EFFECT_EXPANDING_FORCE && IsBattlerTerrainAffected(battler, STATUS_FIELD_PSYCHIC_TERRAIN)) + if (effect == EFFECT_EXPANDING_FORCE && IsBattlerTerrainAffected(battler, GetBattlerAbility(battler), GetBattlerHoldEffect(battler), STATUS_FIELD_PSYCHIC_TERRAIN)) return MOVE_TARGET_BOTH; if (effect == EFFECT_TERA_STARSTORM && gBattleMons[battler].species == SPECIES_TERAPAGOS_STELLAR) return MOVE_TARGET_BOTH; @@ -10976,9 +10030,9 @@ bool32 CanTargetBattler(u32 battlerAtk, u32 battlerDef, u16 move) static void SetRandomMultiHitCounter() { - if (GetBattlerHoldEffect(gBattlerAttacker, TRUE) == HOLD_EFFECT_LOADED_DICE) + if (GetBattlerHoldEffect(gBattlerAttacker) == HOLD_EFFECT_LOADED_DICE) gMultiHitCounter = RandomUniform(RNG_LOADED_DICE, 4, 5); - else if (GetGenConfig(GEN_CONFIG_MULTI_HIT_CHANCE) >= GEN_5) + else if (GetConfig(CONFIG_MULTI_HIT_CHANCE) >= GEN_5) gMultiHitCounter = RandomWeighted(RNG_HITS, 0, 0, 7, 7, 3, 3); // 35%: 2 hits, 35%: 3 hits, 15% 4 hits, 15% 5 hits. else gMultiHitCounter = RandomWeighted(RNG_HITS, 0, 0, 3, 3, 1, 1); // 37.5%: 2 hits, 37.5%: 3 hits, 12.5% 4 hits, 12.5% 5 hits. @@ -11036,17 +10090,6 @@ void RemoveConfusionStatus(u32 battler) gBattleMons[battler].volatiles.infiniteConfusion = FALSE; } -static bool32 CanBeInfinitelyConfused(u32 battler) -{ - if (GetBattlerAbility(battler) == ABILITY_OWN_TEMPO - || IsBattlerTerrainAffected(battler, STATUS_FIELD_MISTY_TERRAIN) - || gSideStatuses[GetBattlerSide(battler)] & SIDE_STATUS_SAFEGUARD) - { - return FALSE; - } - return TRUE; -} - u8 GetBattlerGender(u32 battler) { return GetGenderFromSpeciesAndPersonality(gBattleMons[battler].species, @@ -11069,7 +10112,7 @@ bool32 AreBattlersOfSameGender(u32 battler1, u32 battler2) return (gender1 != MON_GENDERLESS && gender2 != MON_GENDERLESS && gender1 == gender2); } -u32 CalcSecondaryEffectChance(u32 battler, u32 battlerAbility, const struct AdditionalEffect *additionalEffect) +u32 CalcSecondaryEffectChance(u32 battler, enum Ability battlerAbility, const struct AdditionalEffect *additionalEffect) { bool8 hasSereneGrace = (battlerAbility == ABILITY_SERENE_GRACE); bool8 hasRainbow = (gSideStatuses[GetBattlerSide(battler)] & SIDE_STATUS_RAINBOW) != 0; @@ -11086,7 +10129,7 @@ u32 CalcSecondaryEffectChance(u32 battler, u32 battlerAbility, const struct Addi return secondaryEffectChance; } -bool32 MoveEffectIsGuaranteed(u32 battler, u32 battlerAbility, const struct AdditionalEffect *additionalEffect) +bool32 MoveEffectIsGuaranteed(u32 battler, enum Ability battlerAbility, const struct AdditionalEffect *additionalEffect) { return additionalEffect->chance == 0 || CalcSecondaryEffectChance(battler, battlerAbility, additionalEffect) >= 100; } @@ -11220,13 +10263,13 @@ bool8 IsMonBannedFromSkyBattles(u16 species) } } -void GetBattlerTypes(u32 battler, bool32 ignoreTera, u32 types[static 3]) +void GetBattlerTypes(u32 battler, bool32 ignoreTera, enum Type types[static 3]) { // Terastallization. bool32 isTera = GetActiveGimmick(battler) == GIMMICK_TERA; if (!ignoreTera && isTera) { - u32 teraType = GetBattlerTeraType(battler); + enum Type teraType = GetBattlerTeraType(battler); if (teraType != TYPE_STELLAR) { types[0] = types[1] = types[2] = teraType; @@ -11250,14 +10293,14 @@ void GetBattlerTypes(u32 battler, bool32 ignoreTera, u32 types[static 3]) } } -u32 GetBattlerType(u32 battler, u32 typeIndex, bool32 ignoreTera) +enum Type GetBattlerType(u32 battler, u32 typeIndex, bool32 ignoreTera) { - u32 types[3]; + enum Type types[3]; GetBattlerTypes(battler, ignoreTera, types); return types[typeIndex]; } -void RemoveBattlerType(u32 battler, u8 type) +void RemoveBattlerType(u32 battler, enum Type type) { u32 i; if (GetActiveGimmick(battler) == GIMMICK_TERA) // don't remove type if Terastallized @@ -11335,9 +10378,9 @@ bool32 CanTargetPartner(u32 battlerAtk, u32 battlerDef) && battlerDef != BATTLE_PARTNER(battlerAtk)); } -static inline bool32 DoesBattlerHaveAbilityImmunity(u32 battlerAtk, u32 battlerDef, u32 moveType) +static inline bool32 DoesBattlerHaveAbilityImmunity(u32 battlerAtk, u32 battlerDef, enum Type moveType) { - u32 abilityDef = GetBattlerAbility(battlerDef); + enum Ability abilityDef = GetBattlerAbility(battlerDef); return CanAbilityBlockMove(battlerAtk, battlerDef, GetBattlerAbility(battlerAtk), abilityDef, gCurrentMove, CHECK_TRIGGER) || CanAbilityAbsorbMove(battlerAtk, battlerDef, abilityDef, gCurrentMove, moveType, CHECK_TRIGGER); @@ -11345,14 +10388,14 @@ static inline bool32 DoesBattlerHaveAbilityImmunity(u32 battlerAtk, u32 battlerD bool32 TargetFullyImmuneToCurrMove(u32 battlerAtk, u32 battlerDef) { - u32 moveType = GetBattleMoveType(gCurrentMove); + enum Type moveType = GetBattleMoveType(gCurrentMove); return ((CalcTypeEffectivenessMultiplierHelper(gCurrentMove, moveType, battlerAtk, battlerDef, GetBattlerAbility(battlerAtk), GetBattlerAbility(battlerDef), FALSE) == UQ_4_12(0.0)) || IsBattlerProtected(battlerAtk, battlerDef, gCurrentMove) || !BreaksThroughSemiInvulnerablity(battlerDef, gCurrentMove) || DoesBattlerHaveAbilityImmunity(battlerAtk, battlerDef, moveType)); } -u32 GetBattleMoveType(u32 move) +enum Type GetBattleMoveType(u32 move) { if (gMain.inBattle && gBattleStruct->dynamicMoveType) return gBattleStruct->dynamicMoveType & DYNAMIC_TYPE_MASK; @@ -11407,8 +10450,8 @@ void ClearDamageCalcResults(void) { gBattleStruct->moveDamage[battler] = 0; gBattleStruct->critChance[battler] = 0; - gBattleStruct->moveResultFlags[battler] = CAN_DAMAGE; - gBattleStruct->noResultString[battler] = 0; + gBattleStruct->moveResultFlags[battler] = 0; + gBattleStruct->noResultString[battler] = CAN_DAMAGE; gBattleStruct->missStringId[battler] = 0; gSpecialStatuses[battler].criticalHit = FALSE; } @@ -11418,26 +10461,27 @@ void ClearDamageCalcResults(void) gBattleStruct->calculatedSpreadMoveAccuracy = FALSE; gBattleStruct->printedStrongWindsWeakenedAttack = FALSE; gBattleStruct->numSpreadTargets = 0; + gBattleScripting.savedDmg = 0; + if (gCurrentMove != MOVE_NONE) + gBattleStruct->moldBreakerActive = IsMoldBreakerTypeAbility(gBattlerAttacker, GetBattlerAbility(gBattlerAttacker)) || MoveIgnoresTargetAbility(gCurrentMove); + else + gBattleStruct->moldBreakerActive = FALSE; } bool32 DoesDestinyBondFail(u32 battler) { - if (GetGenConfig(GEN_CONFIG_DESTINY_BOND_FAIL) >= GEN_7 - && GetMoveEffect(gLastLandedMoves[battler]) == EFFECT_DESTINY_BOND - && GetMoveEffect(gLastResultingMoves[battler]) == EFFECT_DESTINY_BOND) - return TRUE; - return FALSE; + return GetConfig(CONFIG_DESTINY_BOND_FAIL) >= GEN_7 && gBattleMons[battler].volatiles.destinyBond; } // This check has always to be the last in a condtion statement because of the recording of AI data. -bool32 IsMoveEffectBlockedByTarget(u32 ability) +bool32 IsMoveEffectBlockedByTarget(enum Ability ability) { if (ability == ABILITY_SHIELD_DUST) { RecordAbilityBattle(gBattlerTarget, ability); return TRUE; } - else if (GetBattlerHoldEffect(gBattlerTarget, TRUE) == HOLD_EFFECT_COVERT_CLOAK) + else if (GetBattlerHoldEffect(gBattlerTarget) == HOLD_EFFECT_COVERT_CLOAK) { RecordItemEffectBattle(gBattlerTarget, HOLD_EFFECT_COVERT_CLOAK); return TRUE; @@ -11476,40 +10520,29 @@ bool32 HasWeatherEffect(void) if (!IsBattlerAlive(battler)) continue; - u32 ability = GetBattlerAbility(battler); + enum Ability ability = GetBattlerAbility(battler); switch (ability) { case ABILITY_CLOUD_NINE: case ABILITY_AIR_LOCK: return FALSE; + default: + break; } } return TRUE; } -bool32 IsAnyTargetAffected(u32 battlerAtk) -{ - for (u32 battlerDef = 0; battlerDef < gBattlersCount; battlerDef++) - { - if (battlerAtk == battlerDef) - continue; - - if (!(gBattleStruct->moveResultFlags[battlerDef] & MOVE_RESULT_NO_EFFECT)) - return TRUE; - } - return FALSE; -} - void UpdateStallMons(void) { if (IsBattlerTurnDamaged(gBattlerTarget) || IsBattlerProtected(gBattlerAttacker, gBattlerTarget, gCurrentMove) || GetMoveCategory(gCurrentMove) == DAMAGE_CATEGORY_STATUS) return; if (!IsDoubleBattle() || GetMoveTarget(gCurrentMove) == MOVE_TARGET_SELECTED) { - u32 moveType = GetBattleMoveType(gCurrentMove); // Probably doesn't handle dynamic move types right now - u32 abilityAtk = GetBattlerAbility(gBattlerAttacker); - u32 abilityDef = GetBattlerAbility(gBattlerTarget); + enum Type moveType = GetBattleMoveType(gCurrentMove); // Probably doesn't handle dynamic move types right now + enum Ability abilityAtk = GetBattlerAbility(gBattlerAttacker); + enum Ability abilityDef = GetBattlerAbility(gBattlerTarget); if (CanAbilityAbsorbMove(gBattlerAttacker, gBattlerTarget, abilityDef, gCurrentMove, moveType, CHECK_TRIGGER)) { gAiBattleData->playerStallMons[gBattlerPartyIndexes[gBattlerTarget]]++; @@ -11526,18 +10559,7 @@ void UpdateStallMons(void) // Handling for moves that target multiple opponents in doubles not handled currently } -bool32 TryRestoreHPBerries(u32 battler, enum ItemCaseId caseId) -{ - if (gItemsInfo[gBattleMons[battler].item].pocket == POCKET_BERRIES - || GetBattlerHoldEffect(battler, TRUE) == HOLD_EFFECT_RESTORE_HP) // Edge case for Berry Juice - { - if (ItemBattleEffects(caseId, battler)) - return TRUE; - } - return FALSE; -} - -bool32 TrySwitchInEjectPack(enum ItemCaseId caseID) +bool32 TrySwitchInEjectPack(enum EjectPackTiming timing) { // Because sorting the battlers by speed takes lots of cycles, it's better to just check if any of the battlers has the Eject items. u32 ejectPackBattlers = 0; @@ -11546,7 +10568,7 @@ bool32 TrySwitchInEjectPack(enum ItemCaseId caseID) for (u32 i = 0; i < gBattlersCount; i++) { if (gDisableStructs[i].tryEjectPack - && GetBattlerHoldEffect(i, TRUE) == HOLD_EFFECT_EJECT_PACK + && GetBattlerHoldEffect(i) == HOLD_EFFECT_EJECT_PACK && IsBattlerAlive(i) && CountUsablePartyMons(i) > 0) { @@ -11574,9 +10596,9 @@ bool32 TrySwitchInEjectPack(enum ItemCaseId caseID) gBattleScripting.battler = battler; gLastUsedItem = gBattleMons[battler].item; - if (caseID == ITEMEFFECT_ON_SWITCH_IN_FIRST_TURN) + if (timing == FIRST_TURN) BattleScriptPushCursorAndCallback(BattleScript_EjectPackActivate_End3); - else if (caseID == ITEMEFFECT_NORMAL) + else if (timing == END_TURN) BattleScriptExecute(BattleScript_EjectPackActivate_End2); else BattleScriptCall(BattleScript_EjectPackActivate_Ret); @@ -11630,9 +10652,10 @@ bool32 ItemHealMonVolatile(u32 battler, u16 itemId) const u8 *effect = GetItemEffect(itemId); if (effect[3] & ITEM3_STATUS_ALL) { - statusChanged = (gBattleMons[battler].volatiles.infatuation || gBattleMons[battler].volatiles.confusionTurns > 0); + statusChanged = (gBattleMons[battler].volatiles.infatuation || gBattleMons[battler].volatiles.confusionTurns > 0 || gBattleMons[battler].volatiles.infiniteConfusion); gBattleMons[battler].volatiles.infatuation = 0; gBattleMons[battler].volatiles.confusionTurns = 0; + gBattleMons[battler].volatiles.infiniteConfusion = FALSE; } else if (effect[0] & ITEM0_INFATUATION) { @@ -11641,8 +10664,9 @@ bool32 ItemHealMonVolatile(u32 battler, u16 itemId) } else if (effect[3] & ITEM3_CONFUSION) { - statusChanged = gBattleMons[battler].volatiles.confusionTurns > 0; + statusChanged = (gBattleMons[battler].volatiles.confusionTurns > 0 || gBattleMons[battler].volatiles.infiniteConfusion); gBattleMons[battler].volatiles.confusionTurns = 0; + gBattleMons[battler].volatiles.infiniteConfusion = FALSE; } return statusChanged; @@ -11724,15 +10748,15 @@ void RemoveHazardFromField(u32 side, enum Hazards hazardType) } } -bool32 CanMoveSkipAccuracyCalc(u32 battlerAtk, u32 battlerDef, u32 abilityAtk, u32 abilityDef, u32 move, enum FunctionCallOption option) +bool32 CanMoveSkipAccuracyCalc(u32 battlerAtk, u32 battlerDef, enum Ability abilityAtk, enum Ability abilityDef, u32 move, enum FunctionCallOption option) { bool32 effect = FALSE; - u32 ability = ABILITY_NONE; + enum Ability ability = ABILITY_NONE; enum BattleMoveEffects moveEffect = GetMoveEffect(move); u32 nonVolatileStatus = GetMoveNonVolatileStatus(move); if ((gBattleMons[battlerDef].volatiles.lockOn && gDisableStructs[battlerDef].battlerWithSureHit == battlerAtk) - || (GetGenConfig(GEN_CONFIG_TOXIC_NEVER_MISS) >= GEN_6 && nonVolatileStatus == MOVE_EFFECT_TOXIC && IS_BATTLER_OF_TYPE(battlerAtk, TYPE_POISON)) + || (GetConfig(CONFIG_TOXIC_NEVER_MISS) >= GEN_6 && nonVolatileStatus == MOVE_EFFECT_TOXIC && IS_BATTLER_OF_TYPE(battlerAtk, TYPE_POISON)) || gBattleMons[battlerDef].volatiles.glaiveRush) { effect = TRUE; @@ -11808,7 +10832,7 @@ bool32 CanMoveSkipAccuracyCalc(u32 battlerAtk, u32 battlerDef, u32 abilityAtk, u return effect; } -u32 GetTotalAccuracy(u32 battlerAtk, u32 battlerDef, u32 move, u32 atkAbility, u32 defAbility, u32 atkHoldEffect, u32 defHoldEffect) +u32 GetTotalAccuracy(u32 battlerAtk, u32 battlerDef, u32 move, enum Ability atkAbility, enum Ability defAbility, enum HoldEffect atkHoldEffect, enum HoldEffect defHoldEffect) { u32 calc, moveAcc; s8 buff, accStage, evasionStage; @@ -11819,7 +10843,7 @@ u32 GetTotalAccuracy(u32 battlerAtk, u32 battlerDef, u32 move, u32 atkAbility, u accStage = gBattleMons[battlerAtk].statStages[STAT_ACC]; evasionStage = gBattleMons[battlerDef].statStages[STAT_EVASION]; if (atkAbility == ABILITY_UNAWARE || atkAbility == ABILITY_KEEN_EYE || atkAbility == ABILITY_MINDS_EYE - || (GetGenConfig(GEN_ILLUMINATE_EFFECT) >= GEN_9 && atkAbility == ABILITY_ILLUMINATE)) + || (GetConfig(CONFIG_ILLUMINATE_EFFECT) >= GEN_9 && atkAbility == ABILITY_ILLUMINATE)) evasionStage = DEFAULT_STAT_STAGE; if (MoveIgnoresDefenseEvasionStages(move)) evasionStage = DEFAULT_STAT_STAGE; @@ -11860,23 +10884,27 @@ u32 GetTotalAccuracy(u32 battlerAtk, u32 battlerDef, u32 move, u32 atkAbility, u if (IsBattleMovePhysical(move)) calc = (calc * 80) / 100; // 1.2 hustle loss break; + default: + break; } // Target's ability switch (defAbility) { case ABILITY_SAND_VEIL: - if (HasWeatherEffect() && gBattleWeather & B_WEATHER_SANDSTORM) + if (gBattleWeather & B_WEATHER_SANDSTORM && HasWeatherEffect()) calc = (calc * 80) / 100; // 1.2 sand veil loss break; case ABILITY_SNOW_CLOAK: - if (HasWeatherEffect() && (gBattleWeather & (B_WEATHER_HAIL | B_WEATHER_SNOW))) + if ((gBattleWeather & (B_WEATHER_HAIL | B_WEATHER_SNOW)) && HasWeatherEffect()) calc = (calc * 80) / 100; // 1.2 snow cloak loss break; case ABILITY_TANGLED_FEET: if (gBattleMons[battlerDef].volatiles.confusionTurns) calc = (calc * 50) / 100; // 1.5 tangled feet loss break; + default: + break; } // Attacker's ally's ability @@ -11887,6 +10915,8 @@ u32 GetTotalAccuracy(u32 battlerAtk, u32 battlerDef, u32 move, u32 atkAbility, u if (IsBattlerAlive(atkAlly)) calc = (calc * 110) / 100; // 1.1 ally's victory star boost break; + default: + break; } // Attacker's hold effect @@ -11899,6 +10929,8 @@ u32 GetTotalAccuracy(u32 battlerAtk, u32 battlerDef, u32 move, u32 atkAbility, u if (HasBattlerActedThisTurn(battlerDef)) calc = (calc * (100 + atkParam)) / 100; break; + default: + break; } // Target's hold effect @@ -11907,10 +10939,13 @@ u32 GetTotalAccuracy(u32 battlerAtk, u32 battlerDef, u32 move, u32 atkAbility, u case HOLD_EFFECT_EVASION_UP: calc = (calc * (100 - defParam)) / 100; break; + default: + break; } if (gBattleStruct->battlerState[battlerAtk].usedMicleBerry) { + // TODO: Is this true? if (atkAbility == ABILITY_RIPEN) calc = (calc * 140) / 100; // ripen gives 40% acc boost else @@ -11982,11 +11017,245 @@ static bool32 IsOpposingSideEmpty(u32 battler) return TRUE; } -bool32 IsAffectedByPowderMove(u32 battler, u32 ability, enum ItemHoldEffect holdEffect) +bool32 IsAffectedByPowderMove(u32 battler, u32 ability, enum HoldEffect holdEffect) { - if ((GetGenConfig(GEN_CONFIG_POWDER_OVERCOAT) >= GEN_6 && ability == ABILITY_OVERCOAT) - || (GetGenConfig(GEN_CONFIG_POWDER_GRASS) >= GEN_6 && IS_BATTLER_OF_TYPE(battler, TYPE_GRASS)) + if ((GetConfig(CONFIG_POWDER_OVERCOAT) >= GEN_6 && ability == ABILITY_OVERCOAT) + || (GetConfig(CONFIG_POWDER_GRASS) >= GEN_6 && IS_BATTLER_OF_TYPE(battler, TYPE_GRASS)) || holdEffect == HOLD_EFFECT_SAFETY_GOGGLES) return FALSE; return TRUE; } + +static u32 GetMirrorMoveMove(void) +{ + s32 i, validMovesCount; + u16 move = MOVE_NONE; + u16 validMoves[MAX_BATTLERS_COUNT] = {0}; + + for (validMovesCount = 0, i = 0; i < gBattlersCount; i++) + { + if (i != gBattlerAttacker) + { + move = gBattleStruct->lastTakenMoveFrom[gBattlerAttacker][i]; + if (move != MOVE_NONE && move != MOVE_UNAVAILABLE) + { + validMoves[validMovesCount] = move; + validMovesCount++; + } + } + } + + move = gBattleStruct->lastTakenMove[gBattlerAttacker]; + if ((move == MOVE_NONE || move == MOVE_UNAVAILABLE) && validMovesCount != 0) + move = validMoves[Random() % validMovesCount]; + + if (GetActiveGimmick(gBattlerAttacker) == GIMMICK_Z_MOVE && !IsBattleMoveStatus(move)) + move = GetTypeBasedZMove(move); + + return move; +} + +static bool32 InvalidMetronomeMove(u32 move) +{ + return GetMoveEffect(move) == EFFECT_PLACEHOLDER + || IsMoveMetronomeBanned(move); +} + +static u32 GetMetronomeMove(void) +{ + u32 move = MOVE_NONE; + +#if B_METRONOME_MOVES >= GEN_9 + u32 moveCount = MOVES_COUNT_GEN9; +#elif B_METRONOME_MOVES >= GEN_8 + u32 moveCount = MOVES_COUNT_GEN8; +#elif B_METRONOME_MOVES >= GEN_7 + u32 moveCount = MOVES_COUNT_GEN7; +#elif B_METRONOME_MOVES >= GEN_6 + u32 moveCount = MOVES_COUNT_GEN6; +#elif B_METRONOME_MOVES >= GEN_5 + u32 moveCount = MOVES_COUNT_GEN5; +#elif B_METRONOME_MOVES >= GEN_4 + u32 moveCount = MOVES_COUNT_GEN4; +#elif B_METRONOME_MOVES >= GEN_3 + u32 moveCount = MOVES_COUNT_GEN3; +#elif B_METRONOME_MOVES >= GEN_2 + u32 moveCount = MOVES_COUNT_GEN2; +#else + u32 moveCount = MOVES_COUNT_GEN1; +#endif + + move = RandomUniformExcept(RNG_METRONOME, 1, moveCount - 1, InvalidMetronomeMove); + return move; +} + +static u32 GetAssistMove(void) +{ + u32 move = MOVE_NONE; + s32 chooseableMovesNo = 0; + struct Pokemon *party; + u16 *validMoves = Alloc(sizeof(u16) * PARTY_SIZE * MAX_MON_MOVES); + + if (validMoves != NULL) + { + party = GetBattlerParty(gBattlerAttacker); + + for (u32 monId = 0; monId < PARTY_SIZE; monId++) + { + if (monId == gBattlerPartyIndexes[gBattlerAttacker]) + continue; + if (GetMonData(&party[monId], MON_DATA_SPECIES_OR_EGG) == SPECIES_NONE) + continue; + if (GetMonData(&party[monId], MON_DATA_SPECIES_OR_EGG) == SPECIES_EGG) + continue; + + for (u32 moveId = 0; moveId < MAX_MON_MOVES; moveId++) + { + u16 move = GetMonData(&party[monId], MON_DATA_MOVE1 + moveId); + + if (IsMoveAssistBanned(move)) + continue; + + validMoves[chooseableMovesNo++] = move; + } + } + } + + if (chooseableMovesNo) + move = validMoves[Random() % chooseableMovesNo]; + + TRY_FREE_AND_SET_NULL(validMoves); + + return move; +} + +u32 GetNaturePowerMove(u32 battler) +{ + u32 move = gBattleEnvironmentInfo[gBattleEnvironment].naturePower; + if (gFieldStatuses & STATUS_FIELD_MISTY_TERRAIN) + move = MOVE_MOONBLAST; + else if (gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN) + move = MOVE_THUNDERBOLT; + else if (gFieldStatuses & STATUS_FIELD_GRASSY_TERRAIN) + move = MOVE_ENERGY_BALL; + else if (gFieldStatuses & STATUS_FIELD_PSYCHIC_TERRAIN) + move = MOVE_PSYCHIC; + else if (gBattleEnvironmentInfo[gBattleEnvironment].naturePower == MOVE_NONE) + move = MOVE_TRI_ATTACK; + + return move; +} + +static u32 GetSleepTalkMove(void) +{ + u32 move = MOVE_NONE; + + u32 i, unusableMovesBits = 0, movePosition; + + if (GetBattlerAbility(gBattlerAttacker) != ABILITY_COMATOSE + && !(gBattleMons[gBattlerAttacker].status1 & STATUS1_SLEEP)) + return move; + + for (i = 0; i < MAX_MON_MOVES; i++) + { + if (IsMoveSleepTalkBanned(gBattleMons[gBattlerAttacker].moves[i]) + || gBattleMoveEffects[GetMoveEffect(gBattleMons[gBattlerAttacker].moves[i])].twoTurnEffect) + unusableMovesBits |= (1 << (i)); + } + + unusableMovesBits = CheckMoveLimitations(gBattlerAttacker, unusableMovesBits, ~(MOVE_LIMITATION_PP | MOVE_LIMITATION_CHOICE_ITEM)); + if (unusableMovesBits == ALL_MOVES_MASK) // all 4 moves cannot be chosen + return move; + + // Set Sleep Talk as used move, so it works with Last Resort. + gDisableStructs[gBattlerAttacker].usedMoves |= 1u << gCurrMovePos; + do + { + movePosition = MOD(Random(), MAX_MON_MOVES); + } while ((1u << movePosition) & unusableMovesBits); + + move = gBattleMons[gBattlerAttacker].moves[movePosition]; + gCurrMovePos = movePosition; + + return move; +} + +static u32 GetCopyCatMove(void) +{ + if (gLastUsedMove == MOVE_NONE + || gLastUsedMove == MOVE_UNAVAILABLE + || IsMoveCopycatBanned(gLastUsedMove) + || IsZMove(gLastUsedMove)) + return MOVE_NONE; + + return gLastUsedMove; +} + +static u32 GetMeFirstMove(void) +{ + u32 move = GetChosenMoveFromPosition(gBattlerTarget); + + if (IsBattleMoveStatus(move) + || IsMoveMeFirstBanned(move) + || HasBattlerActedThisTurn(gBattlerTarget)) + return MOVE_NONE; + + return move; +} + +void RemoveAbilityFlags(u32 battler) +{ + switch (GetBattlerAbility(battler)) + { + case ABILITY_FLASH_FIRE: + gDisableStructs[battler].flashFireBoosted = FALSE; + break; + case ABILITY_VESSEL_OF_RUIN: + gBattleMons[battler].volatiles.vesselOfRuin = FALSE; + break; + case ABILITY_TABLETS_OF_RUIN: + gBattleMons[battler].volatiles.tabletsOfRuin = FALSE; + break; + case ABILITY_SWORD_OF_RUIN: + gBattleMons[battler].volatiles.swordOfRuin = FALSE; + break; + case ABILITY_BEADS_OF_RUIN: + gBattleMons[battler].volatiles.beadsOfRuin = FALSE; + break; + default: + break; + } +} + +bool32 IsAnyTargetTurnDamaged(u32 battlerAtk) +{ + for (u32 battlerDef = 0; battlerDef < gBattlersCount; battlerDef++) + { + if (battlerDef == battlerAtk) + continue; + if (IsBattlerTurnDamaged(battlerDef)) + return TRUE; + } + return FALSE; +} + +bool32 IsAllowedToUseBag(void) +{ + switch(VarGet(B_VAR_NO_BAG_USE)) + { + case NO_BAG_RESTRICTION: + return TRUE; + case NO_BAG_AGAINST_TRAINER: //True in wild battle; False in trainer battle + return (!(gBattleTypeFlags & BATTLE_TYPE_TRAINER)); + case NO_BAG_IN_BATTLE: + return FALSE; + default: + return TRUE; // Undefined Behavior + } +} + +bool32 IsMimikyuDisguised(u32 battler) +{ + return gBattleMons[battler].species == SPECIES_MIMIKYU_DISGUISED + || gBattleMons[battler].species == SPECIES_MIMIKYU_TOTEM_DISGUISED; +} diff --git a/src/battle_z_move.c b/src/battle_z_move.c index f91f05a449..a407c222cc 100644 --- a/src/battle_z_move.c +++ b/src/battle_z_move.c @@ -36,7 +36,6 @@ #include "constants/songs.h" #include "constants/items.h" #include "constants/species.h" -#include "constants/hold_effects.h" #include "constants/battle_string_ids.h" #include "constants/battle_move_effects.h" #include "constants/abilities.h" @@ -112,7 +111,7 @@ bool32 IsZMove(u32 move) bool32 CanUseZMove(u32 battler) { - enum ItemHoldEffect holdEffect = GetBattlerHoldEffect(battler, FALSE); + enum HoldEffect holdEffect = GetBattlerHoldEffectIgnoreNegation(battler); // Check if Player has Z-Power Ring. if (!TESTING && (battler == B_POSITION_PLAYER_LEFT @@ -143,7 +142,7 @@ bool32 CanUseZMove(u32 battler) u32 GetUsableZMove(u32 battler, u32 move) { u32 item = gBattleMons[battler].item; - enum ItemHoldEffect holdEffect = GetBattlerHoldEffect(battler, FALSE); + enum HoldEffect holdEffect = GetBattlerHoldEffectIgnoreNegation(battler); if (holdEffect == HOLD_EFFECT_Z_CRYSTAL) { @@ -160,14 +159,13 @@ u32 GetUsableZMove(u32 battler, u32 move) void ActivateZMove(u32 battler) { - gBattleStruct->zmove.baseMoves[battler] = gBattleMons[battler].moves[gBattleStruct->chosenMovePositions[battler]]; SetActiveGimmick(battler, GIMMICK_Z_MOVE); } bool32 IsViableZMove(u32 battler, u32 move) { u32 item; - enum ItemHoldEffect holdEffect = GetBattlerHoldEffect(battler, FALSE); + enum HoldEffect holdEffect = GetBattlerHoldEffectIgnoreNegation(battler); int moveSlotIndex; item = gBattleMons[battler].item; @@ -419,7 +417,7 @@ static void ZMoveSelectionDisplayPpNumber(u32 battler) static void ZMoveSelectionDisplayMoveType(u16 zMove, u32 battler) { u8 *txtPtr, *end; - u32 zMoveType = GetBattleMoveType(zMove); + enum Type zMoveType = GetBattleMoveType(zMove); txtPtr = StringCopy(gDisplayedStringBattle, gText_MoveInterfaceType); *(txtPtr)++ = EXT_CTRL_CODE_BEGIN; @@ -437,7 +435,7 @@ static void ZMoveSelectionDisplayMoveType(u16 zMove, u32 battler) void SetZEffect(void) { u32 i; - u32 effect = GetMoveZEffect(gBattleStruct->zmove.baseMoves[gBattlerAttacker]); + u32 effect = GetMoveZEffect(gChosenMove); if (effect == Z_EFFECT_CURSE) { @@ -507,7 +505,7 @@ void SetZEffect(void) case Z_EFFECT_RECOVER_HP: if (gBattleMons[gBattlerAttacker].hp != gBattleMons[gBattlerAttacker].maxHP) { - gBattleStruct->moveDamage[gBattlerAttacker] = (-1) * gBattleMons[gBattlerAttacker].maxHP; + SetHealAmount(gBattlerAttacker, gBattleMons[gBattlerAttacker].maxHP); gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_Z_RECOVER_HP; BattleScriptPush(gBattlescriptCurrInstr + Z_EFFECT_BS_LENGTH); gBattlescriptCurrInstr = BattleScript_RecoverHPZMove; diff --git a/src/berry_crush.c b/src/berry_crush.c index a571511ee2..e3927d8780 100644 --- a/src/berry_crush.c +++ b/src/berry_crush.c @@ -4,6 +4,7 @@ #include "berry_powder.h" #include "bg.h" #include "decompress.h" +#include "digit_obj_util.h" #include "dynamic_placeholder_text_util.h" #include "event_data.h" #include "gpu_regs.h" @@ -17,11 +18,10 @@ #include "malloc.h" #include "math_util.h" #include "menu.h" +#include "minigame_countdown.h" #include "overworld.h" #include "palette.h" -#include "minigame_countdown.h" #include "random.h" -#include "digit_obj_util.h" #include "save.h" #include "scanline_effect.h" #include "script.h" @@ -1157,18 +1157,7 @@ static void SetNamesAndTextSpeed(struct BerryCrushGame *game) game->players[i].name[PLAYER_NAME_LENGTH] = EOS; } - switch (gSaveBlock2Ptr->optionsTextSpeed) - { - case OPTIONS_TEXT_SPEED_SLOW: - game->textSpeed = 8; - break; - case OPTIONS_TEXT_SPEED_MID: - game->textSpeed = 4; - break; - case OPTIONS_TEXT_SPEED_FAST: - game->textSpeed = 1; - break; - } + game->textSpeed = GetPlayerTextSpeedDelay(); } static s32 ShowGameDisplay(void) diff --git a/src/bg.c b/src/bg.c index bfc719a25f..9080adf22c 100644 --- a/src/bg.c +++ b/src/bg.c @@ -911,8 +911,6 @@ void CopyBgTilemapBufferToVram(u32 bg) void CopyToBgTilemapBufferRect(u32 bg, const void *src, u8 destX, u8 destY, u8 width, u8 height) { - u16 destX16; - u16 destY16; u16 mode; if (!IsInvalidBg(bg) && !IsTileMapOutsideWram(bg)) @@ -922,11 +920,11 @@ void CopyToBgTilemapBufferRect(u32 bg, const void *src, u8 destX, u8 destY, u8 w case BG_TYPE_NORMAL: { const u16 *srcCopy = src; - for (destY16 = destY; destY16 < (destY + height); destY16++) + for (u32 j = destY; j < (destY + height); j++) { - for (destX16 = destX; destX16 < (destX + width); destX16++) + for (u32 i = destX; i < (destX + width); i++) { - ((u16 *)sGpuBgConfigs2[bg].tilemap)[((destY16 * 0x20) + destX16)] = *srcCopy++; + ((u16 *)sGpuBgConfigs2[bg].tilemap)[((j * 0x20) + i)] = *srcCopy++; } } break; @@ -935,11 +933,11 @@ void CopyToBgTilemapBufferRect(u32 bg, const void *src, u8 destX, u8 destY, u8 w { const u8 *srcCopy = src; mode = GetBgMetricAffineMode(bg, 0x1); - for (destY16 = destY; destY16 < (destY + height); destY16++) + for (u32 j = destY; j < (destY + height); j++) { - for (destX16 = destX; destX16 < (destX + width); destX16++) + for (u32 i = destX; i < (destX + width); i++) { - ((u8 *)sGpuBgConfigs2[bg].tilemap)[((destY16 * mode) + destX16)] = *srcCopy++; + ((u8 *)sGpuBgConfigs2[bg].tilemap)[((j * mode) + i)] = *srcCopy++; } } break; @@ -958,7 +956,6 @@ void CopyRectToBgTilemapBufferRect(u32 bg, const void *src, u8 srcX, u8 srcY, u8 u16 screenWidth, screenHeight, screenSize; u16 var; const void *srcPtr; - u16 i, j; if (!IsInvalidBg(bg) && !IsTileMapOutsideWram(bg)) { @@ -969,11 +966,11 @@ void CopyRectToBgTilemapBufferRect(u32 bg, const void *src, u8 srcX, u8 srcY, u8 { case BG_TYPE_NORMAL: srcPtr = src + ((srcY * srcWidth) + srcX) * 2; - for (i = destY; i < (destY + rectHeight); i++) + for (u32 j = destY; j < (destY + rectHeight); j++) { - for (j = destX; j < (destX + rectWidth); j++) + for (u32 i = destX; i < (destX + rectWidth); i++) { - u16 index = GetTileMapIndexFromCoords(j, i, screenSize, screenWidth, screenHeight); + u16 index = GetTileMapIndexFromCoords(i, j, screenSize, screenWidth, screenHeight); CopyTileMapEntry(srcPtr, sGpuBgConfigs2[bg].tilemap + (index * 2), palette1, tileOffset, palette2); srcPtr += 2; } @@ -983,11 +980,11 @@ void CopyRectToBgTilemapBufferRect(u32 bg, const void *src, u8 srcX, u8 srcY, u8 case BG_TYPE_AFFINE: srcPtr = src + ((srcY * srcWidth) + srcX); var = GetBgMetricAffineMode(bg, 0x1); - for (i = destY; i < (destY + rectHeight); i++) + for (u32 j = destY; j < (destY + rectHeight); j++) { - for (j = destX; j < (destX + rectWidth); j++) + for (u32 i = destX; i < (destX + rectWidth); i++) { - *(u8 *)(sGpuBgConfigs2[bg].tilemap + ((var * i) + j)) = *(u8 *)(srcPtr) + tileOffset; + *(u8 *)(sGpuBgConfigs2[bg].tilemap + ((var * j) + i)) = *(u8 *)(srcPtr) + tileOffset; srcPtr++; } srcPtr += (srcWidth - rectWidth); @@ -999,8 +996,6 @@ void CopyRectToBgTilemapBufferRect(u32 bg, const void *src, u8 srcX, u8 srcY, u8 void FillBgTilemapBufferRect_Palette0(u32 bg, u16 tileNum, u8 x, u8 y, u8 width, u8 height) { - u16 x16; - u16 y16; u16 mode; if (!IsInvalidBg(bg) && !IsTileMapOutsideWram(bg)) @@ -1008,21 +1003,21 @@ void FillBgTilemapBufferRect_Palette0(u32 bg, u16 tileNum, u8 x, u8 y, u8 width, switch (GetBgType(bg)) { case BG_TYPE_NORMAL: - for (y16 = y; y16 < (y + height); y16++) + for (u32 j = y; j < (y + height); j++) { - for (x16 = x; x16 < (x + width); x16++) + for (u32 i = x; i < (x + width); i++) { - ((u16 *)sGpuBgConfigs2[bg].tilemap)[((y16 * 0x20) + x16)] = tileNum; + ((u16 *)sGpuBgConfigs2[bg].tilemap)[((j * 0x20) + i)] = tileNum; } } break; case BG_TYPE_AFFINE: mode = GetBgMetricAffineMode(bg, 0x1); - for (y16 = y; y16 < (y + height); y16++) + for (u32 j = y; j < (y + height); j++) { - for (x16 = x; x16 < (x + width); x16++) + for (u32 i = x; i < (x + width); i++) { - ((u8 *)sGpuBgConfigs2[bg].tilemap)[((y16 * mode) + x16)] = tileNum; + ((u8 *)sGpuBgConfigs2[bg].tilemap)[((j * mode) + i)] = tileNum; } } break; @@ -1041,7 +1036,6 @@ void WriteSequenceToBgTilemapBuffer(u32 bg, u16 firstTileNum, u8 x, u8 y, u8 wid u16 mode2; u16 attribute; u16 mode3; - u16 x16, y16; if (!IsInvalidBg(bg) && !IsTileMapOutsideWram(bg)) { @@ -1051,22 +1045,22 @@ void WriteSequenceToBgTilemapBuffer(u32 bg, u16 firstTileNum, u8 x, u8 y, u8 wid switch (GetBgType(bg)) { case BG_TYPE_NORMAL: - for (y16 = y; y16 < (y + height); y16++) + for (u32 j = y; j < (y + height); j++) { - for (x16 = x; x16 < (x + width); x16++) + for (u32 i = x; i < (x + width); i++) { - CopyTileMapEntry(&firstTileNum, &((u16 *)sGpuBgConfigs2[bg].tilemap)[(u16)GetTileMapIndexFromCoords(x16, y16, attribute, mode, mode2)], paletteSlot, 0, 0); + CopyTileMapEntry(&firstTileNum, &((u16 *)sGpuBgConfigs2[bg].tilemap)[(u16)GetTileMapIndexFromCoords(i, j, attribute, mode, mode2)], paletteSlot, 0, 0); firstTileNum = (firstTileNum & 0xFC00) + ((firstTileNum + tileNumDelta) & 0x3FF); } } break; case BG_TYPE_AFFINE: mode3 = GetBgMetricAffineMode(bg, 0x1); - for (y16 = y; y16 < (y + height); y16++) + for (u32 j = y; j < (y + height); j++) { - for (x16 = x; x16 < (x + width); x16++) + for (u32 i = x; i < (x + width); i++) { - ((u8 *)sGpuBgConfigs2[bg].tilemap)[(y16 * mode3) + x16] = firstTileNum; + ((u8 *)sGpuBgConfigs2[bg].tilemap)[(j * mode3) + i] = firstTileNum; firstTileNum = (firstTileNum & 0xFC00) + ((firstTileNum + tileNumDelta) & 0x3FF); } } diff --git a/src/bike.c b/src/bike.c index 50ed705da3..3f4181f129 100644 --- a/src/bike.c +++ b/src/bike.c @@ -5,6 +5,7 @@ #include "fieldmap.h" #include "field_specials.h" #include "metatile_behavior.h" +#include "oras_dowse.h" #include "overworld.h" #include "sound.h" #include "constants/songs.h" @@ -1003,6 +1004,7 @@ void GetOnOffBike(u8 transitionFlags) } else { + EndORASDowsing(); SetPlayerAvatarTransitionFlags(transitionFlags); Overworld_SetSavedMusic(MUS_CYCLING); Overworld_ChangeMusicTo(MUS_CYCLING); diff --git a/src/braille.c b/src/braille.c index 91872b88a0..310384ba32 100644 --- a/src/braille.c +++ b/src/braille.c @@ -1,18 +1,12 @@ #include "global.h" #include "main.h" -#include "window.h" #include "text.h" #include "sound.h" +#include "window.h" // This file handles the braille font. // For printing braille messages, see ScrCmd_braillemessage -ALIGNED(4) -static const u8 sScrollDistances[] = { - [OPTIONS_TEXT_SPEED_SLOW] = 1, - [OPTIONS_TEXT_SPEED_MID] = 2, - [OPTIONS_TEXT_SPEED_FAST] = 4, -}; static const u16 sFont_Braille[] = INCBIN_U16("graphics/fonts/braille.fwjpnfont"); static void DecompressGlyph_Braille(u16); @@ -22,6 +16,7 @@ u16 FontFunc_Braille(struct TextPrinter *textPrinter) u16 char_; struct TextPrinterSubStruct *subStruct; subStruct = (struct TextPrinterSubStruct *)(&textPrinter->subStructFields); + u32 scrollSpeed = GetPlayerTextScrollSpeed(); switch (textPrinter->state) { @@ -164,15 +159,15 @@ u16 FontFunc_Braille(struct TextPrinter *textPrinter) case RENDER_STATE_SCROLL: if (textPrinter->scrollDistance) { - if (textPrinter->scrollDistance < sScrollDistances[gSaveBlock2Ptr->optionsTextSpeed]) + if (textPrinter->scrollDistance < scrollSpeed) { ScrollWindow(textPrinter->printerTemplate.windowId, 0, textPrinter->scrollDistance, PIXEL_FILL(textPrinter->printerTemplate.bgColor)); textPrinter->scrollDistance = 0; } else { - ScrollWindow(textPrinter->printerTemplate.windowId, 0, sScrollDistances[gSaveBlock2Ptr->optionsTextSpeed], PIXEL_FILL(textPrinter->printerTemplate.bgColor)); - textPrinter->scrollDistance -= sScrollDistances[gSaveBlock2Ptr->optionsTextSpeed]; + ScrollWindow(textPrinter->printerTemplate.windowId, 0, scrollSpeed, PIXEL_FILL(textPrinter->printerTemplate.bgColor)); + textPrinter->scrollDistance -= scrollSpeed; } CopyWindowToVram(textPrinter->printerTemplate.windowId, COPYWIN_GFX); } diff --git a/src/clock.c b/src/clock.c index 142e62ebf2..2440f5b5a6 100644 --- a/src/clock.c +++ b/src/clock.c @@ -13,6 +13,7 @@ #include "tv.h" #include "wallclock.h" #include "constants/form_change_types.h" +#include "apricorn_tree.h" static void UpdatePerDay(struct Time *localTime); static void UpdatePerMinute(struct Time *localTime); @@ -55,6 +56,7 @@ static void UpdatePerDay(struct Time *localTime) SetShoalItemFlag(daysSince); SetRandomLotteryNumber(daysSince); UpdateDaysPassedSinceFormChange(daysSince); + DailyResetApricornTrees(); *days = localTime->days; } } diff --git a/src/contest.c b/src/contest.c index 0da5d78e08..c04aa306a2 100644 --- a/src/contest.c +++ b/src/contest.c @@ -360,10 +360,32 @@ EWRAM_DATA u8 gCurContestWinnerSaveIdx = 0; // IWRAM common vars. COMMON_DATA rng_value_t gContestRngValue = {0}; -extern const u8 gText_LinkStandby4[]; +const u8 gText_LinkStandby4[] = COMPOUND_STRING("正在等待连接!"); extern const u8 gText_BDot[]; extern const u8 gText_CDot[]; -extern void (*const gContestEffectFuncs[])(void); + +//Text +const u8 gText_AppealNumWhichMoveWillBePlayed[] = COMPOUND_STRING("第{STR_VAR_1}回合的表演!\n要使用哪个招式呢?"); +const u8 gText_AppealNumButItCantParticipate[] = COMPOUND_STRING("第{STR_VAR_1}回合的表演!\n但是无法参加!"); +const u8 gText_MonAppealedWithMove[] = COMPOUND_STRING("{STR_VAR_1}使用了\n{STR_VAR_2}进行表演!"); +const u8 gText_MonWasWatchingOthers[] = COMPOUND_STRING("{STR_VAR_1}在观察\n其他的宝可梦!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}"); +const u8 gText_AllOutOfAppealTime[] = COMPOUND_STRING("表演时间结束!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}"); +const u8 gText_JudgeLookedAtMonExpectantly[] = COMPOUND_STRING("评委满怀期待地\n看着{STR_VAR_1}!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}"); +const u8 gText_AppealComboWentOverWell[] = COMPOUND_STRING("前后演出的招式组合\n得到了大家的喜爱!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}"); +const u8 gText_AppealComboWentOverVeryWell[] = COMPOUND_STRING("前后演出的招式组合\n很受大家喜欢!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}"); +const u8 gText_AppealComboWentOverExcellently[] = COMPOUND_STRING("前后演出的招式组合\n特别受大家喜欢!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}"); +const u8 gText_MonWasTooNervousToMove[] = COMPOUND_STRING("{STR_VAR_1}因为紧张\n无法使用招式表演了!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}"); +const u8 gText_CouldntImproveItsCondition[] = COMPOUND_STRING("但是它并没能提升自己的气势……{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}"); +const u8 gText_BadConditionResultedInWeakAppeal[] = COMPOUND_STRING("它因为气势不行表演得一点也不好……{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}"); +const u8 gText_MonWasUnaffected[] = COMPOUND_STRING("{STR_VAR_1}完全不为所动!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}"); +const u8 gText_RepeatedAppeal[] = COMPOUND_STRING("{STR_VAR_1}因为重复表演,让大家失望了。{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}"); +const u8 gText_MonsXWentOverGreat[] = COMPOUND_STRING("{STR_VAR_1}的{STR_VAR_3}表演\n受到了大家的热烈欢迎!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}"); +const u8 gText_MonsXDidntGoOverWell[] = COMPOUND_STRING("{STR_VAR_1}的{STR_VAR_3}表演\n在这里不受欢迎……{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}"); +const u8 gText_MonsXGotTheCrowdGoing[] = COMPOUND_STRING("{STR_VAR_1}的{STR_VAR_3}表演\n让整个会场沸腾了!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}"); +const u8 gText_MonCantAppealNextTurn[] = COMPOUND_STRING("{STR_VAR_1}无法参加下一次的表演了!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}"); +const u8 gText_AttractedCrowdsAttention[] = COMPOUND_STRING("吸引了观众们的注意!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}"); +const u8 gText_CrowdContinuesToWatchMon[] = COMPOUND_STRING("观众们一直持续关注着{STR_VAR_3}!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}"); +const u8 gText_MonsMoveIsIgnored[] = COMPOUND_STRING("{STR_VAR_1}的{STR_VAR_2}被完全无视了……{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}"); static const u8 sSliderHeartYPositions[CONTESTANT_COUNT] = { @@ -688,84 +710,57 @@ static const u16 sText_Pal[] = INCBIN_U16("graphics/contest/text.gbapal"); #include "data/contest_text_tables.h" -const u8 *const gContestEffectDescriptionPointers[] = +const struct ContestCategory gContestCategoryInfo[CONTEST_CATEGORIES_COUNT + 1] = { - [CONTEST_EFFECT_HIGHLY_APPEALING] = COMPOUND_STRING("能够吸引人的表演。"), - [CONTEST_EFFECT_USER_MORE_EASILY_STARTLED] = COMPOUND_STRING("虽然能够演出很好的表演,\n但是之后会更容易受干扰。"), - [CONTEST_EFFECT_GREAT_APPEAL_BUT_NO_MORE_MOVES] = COMPOUND_STRING("极具吸引力的表演,\n但是此后无法再进行表演。"), - [CONTEST_EFFECT_REPETITION_NOT_BORING] = COMPOUND_STRING("即使重复演出也不会\n让评委感到无聊。"), - [CONTEST_EFFECT_AVOID_STARTLE_ONCE] = COMPOUND_STRING("即使被之后的宝可梦干扰\n也会挺住一次。"), - [CONTEST_EFFECT_AVOID_STARTLE] = COMPOUND_STRING("即使被之后的宝可梦干扰\n也会挺住。"), - [CONTEST_EFFECT_AVOID_STARTLE_SLIGHTLY] = COMPOUND_STRING("能够稍稍避免受到\n被其他宝可梦干扰。"), - [CONTEST_EFFECT_USER_LESS_EASILY_STARTLED] = COMPOUND_STRING("在表演这个招式之后\n宝可梦会变得不易受干扰。"), - [CONTEST_EFFECT_STARTLE_FRONT_MON] = COMPOUND_STRING("稍稍干扰在自己之前表演的\n宝可梦。"), - [CONTEST_EFFECT_SLIGHTLY_STARTLE_PREV_MONS] = COMPOUND_STRING("稍稍干扰表演完成的\n所有宝可梦。"), - [CONTEST_EFFECT_STARTLE_PREV_MON] = COMPOUND_STRING("干扰在自己之前表演的\n宝可梦。"), - [CONTEST_EFFECT_STARTLE_PREV_MONS] = COMPOUND_STRING("干扰表演完成的\n所有宝可梦。"), - [CONTEST_EFFECT_BADLY_STARTLE_FRONT_MON] = COMPOUND_STRING("严重干扰在自己之前表演的\n宝可梦。"), - [CONTEST_EFFECT_BADLY_STARTLE_PREV_MONS] = COMPOUND_STRING("严重干扰表演完成的\n所有宝可梦。"), - [CONTEST_EFFECT_STARTLE_PREV_MON_2] = COMPOUND_STRING("干扰在自己之前表演的\n宝可梦。"), - [CONTEST_EFFECT_STARTLE_PREV_MONS_2] = COMPOUND_STRING("干扰表演完成的\n所有宝可梦。"), - [CONTEST_EFFECT_SHIFT_JUDGE_ATTENTION] = COMPOUND_STRING("分散评委对之前宝可梦的\n注意。"), - [CONTEST_EFFECT_STARTLE_MON_WITH_JUDGES_ATTENTION] = COMPOUND_STRING("特别干扰评委注意的\n宝可梦。"), - [CONTEST_EFFECT_JAMS_OTHERS_BUT_MISS_ONE_TURN] = COMPOUND_STRING("激烈地干扰大家,\n但无法参加下一次表演。"), - [CONTEST_EFFECT_STARTLE_MONS_SAME_TYPE_APPEAL] = COMPOUND_STRING("特别干扰演出了相同类别的\n宝可梦。"), - [CONTEST_EFFECT_STARTLE_MONS_COOL_APPEAL] = COMPOUND_STRING("特别干扰演出了帅气招式的\n宝可梦。"), - [CONTEST_EFFECT_STARTLE_MONS_BEAUTY_APPEAL] = COMPOUND_STRING("特别干扰演出了美丽招式的\n宝可梦。"), - [CONTEST_EFFECT_STARTLE_MONS_CUTE_APPEAL] = COMPOUND_STRING("特别干扰演出了可爱招式的\n宝可梦。"), - [CONTEST_EFFECT_STARTLE_MONS_SMART_APPEAL] = COMPOUND_STRING("特别干扰演出了聪明招式的\n宝可梦。"), - [CONTEST_EFFECT_STARTLE_MONS_TOUGH_APPEAL] = COMPOUND_STRING("特别干扰演出了强壮招式的\n宝可梦。"), - [CONTEST_EFFECT_MAKE_FOLLOWING_MON_NERVOUS] = COMPOUND_STRING("让下一只表演的宝可梦\n感到紧张。"), - [CONTEST_EFFECT_MAKE_FOLLOWING_MONS_NERVOUS] = COMPOUND_STRING("让之后表演的所有宝可梦\n都感到紧张。"), - [CONTEST_EFFECT_WORSEN_CONDITION_OF_PREV_MONS] = COMPOUND_STRING("降低表演完成的\n宝可梦的气势。"), - [CONTEST_EFFECT_BADLY_STARTLES_MONS_IN_GOOD_CONDITION] = COMPOUND_STRING("严重干扰气势良好的\n所有宝可梦。"), - [CONTEST_EFFECT_BETTER_IF_FIRST] = COMPOUND_STRING("最先演出时表演\n会更加吸引人。"), - [CONTEST_EFFECT_BETTER_IF_LAST] = COMPOUND_STRING("最后演出时表演\n会更加吸引人。"), - [CONTEST_EFFECT_APPEAL_AS_GOOD_AS_PREV_ONES] = COMPOUND_STRING("演出和此前所有宝可梦表演\n吸引力程度相当的表演。"), - [CONTEST_EFFECT_APPEAL_AS_GOOD_AS_PREV_ONE] = COMPOUND_STRING("和前一位宝可梦的\n表演一样吸引人。"), - [CONTEST_EFFECT_BETTER_WHEN_LATER] = COMPOUND_STRING("演出时排序越靠后,\n越能演出吸引人的表演。"), - [CONTEST_EFFECT_QUALITY_DEPENDS_ON_TIMING] = COMPOUND_STRING("每次演出的结果都不同。"), - [CONTEST_EFFECT_BETTER_IF_SAME_TYPE] = COMPOUND_STRING("和前一位宝可梦的表演类别\n相同时会更吸引人。"), - [CONTEST_EFFECT_BETTER_IF_DIFF_TYPE] = COMPOUND_STRING("和前一位宝可梦的表演类别\n不同时会更吸引人。"), - [CONTEST_EFFECT_AFFECTED_BY_PREV_APPEAL] = COMPOUND_STRING("演出水平受前一位宝可梦\n表演吸引程度的影响。"), - [CONTEST_EFFECT_IMPROVE_CONDITION_PREVENT_NERVOUSNESS] = COMPOUND_STRING("提升表演的气势,\n变得不容易感到紧张。"), - [CONTEST_EFFECT_BETTER_WITH_GOOD_CONDITION] = COMPOUND_STRING("气势良好时表演\n会非常吸引人。"), - [CONTEST_EFFECT_NEXT_APPEAL_EARLIER] = COMPOUND_STRING("下一次表演时最先出场。"), - [CONTEST_EFFECT_NEXT_APPEAL_LATER] = COMPOUND_STRING("下一次表演时最后出场。"), - [CONTEST_EFFECT_MAKE_SCRAMBLING_TURN_ORDER_EASIER] = COMPOUND_STRING("使下一次表演的顺序\n容易被打乱。"), - [CONTEST_EFFECT_SCRAMBLE_NEXT_TURN_ORDER] = COMPOUND_STRING("打乱下一次表演的顺序。"), - [CONTEST_EFFECT_EXCITE_AUDIENCE_IN_ANY_CONTEST] = COMPOUND_STRING("任何类别的华丽大赛中\n都会让会场兴奋的表演。"), - [CONTEST_EFFECT_BADLY_STARTLE_MONS_WITH_GOOD_APPEALS] = COMPOUND_STRING("严重干扰表演具有吸引力的\n所有宝可梦。"), - [CONTEST_EFFECT_BETTER_WHEN_AUDIENCE_EXCITED] = COMPOUND_STRING("会场越兴奋,\n表演越吸引人。"), - [CONTEST_EFFECT_DONT_EXCITE_AUDIENCE] = COMPOUND_STRING("表演后会场暂时不会\n变得更加兴奋。"), -}; + [CONTEST_CATEGORY_COOL] = + { + .name = COMPOUND_STRING("帅气"), + .condition = COMPOUND_STRING("帅气"), + .generic = COMPOUND_STRING("帅气"), + .negativeTrait = COMPOUND_STRING("害羞"), + .palette = 13, + }, -const u8 *const gContestMoveTypeTextPointers[] = -{ - [CONTEST_CATEGORY_COOL] = COMPOUND_STRING("帅气"), - [CONTEST_CATEGORY_BEAUTY] = COMPOUND_STRING("美丽"), - [CONTEST_CATEGORY_CUTE] = COMPOUND_STRING("可爱"), - [CONTEST_CATEGORY_SMART] = COMPOUND_STRING("聪明"), - [CONTEST_CATEGORY_TOUGH] = COMPOUND_STRING("强壮"), -}; + [CONTEST_CATEGORY_BEAUTY] = + { + .name = COMPOUND_STRING("美丽"), + .condition = COMPOUND_STRING("美丽"), + .generic = COMPOUND_STRING("美丽招式"), + .negativeTrait = COMPOUND_STRING("焦虑"), + .palette = 14, + }, -static const u8 *const sContestConditions[] = -{ - [CONTEST_CATEGORY_COOL] = COMPOUND_STRING("帅气"), - [CONTEST_CATEGORY_BEAUTY] = COMPOUND_STRING("美丽"), - [CONTEST_CATEGORY_CUTE] = COMPOUND_STRING("可爱"), - [CONTEST_CATEGORY_SMART] = COMPOUND_STRING("聪明"), - [CONTEST_CATEGORY_TOUGH] = COMPOUND_STRING("强壮"), -}; + [CONTEST_CATEGORY_CUTE] = + { + .name = COMPOUND_STRING("可爱"), + .condition = COMPOUND_STRING("可爱"), + .generic = COMPOUND_STRING("可爱招式"), + .negativeTrait = COMPOUND_STRING("懒惰"), + .palette = 14, + }, -static const u8 *const sInvalidContestMoveNames[] = -{ - [CONTEST_CATEGORY_COOL] = COMPOUND_STRING("帅气招式"), - [CONTEST_CATEGORY_BEAUTY] = COMPOUND_STRING("美丽招式"), - [CONTEST_CATEGORY_CUTE] = COMPOUND_STRING("可爱招式"), - [CONTEST_CATEGORY_SMART] = COMPOUND_STRING("聪明招式"), - [CONTEST_CATEGORY_TOUGH] = COMPOUND_STRING("强壮招式"), - [CONTEST_CATEGORIES_COUNT] = COMPOUND_STRING("???"), + [CONTEST_CATEGORY_SMART] = + { + .name = COMPOUND_STRING("聪明"), + .condition = COMPOUND_STRING("聪明"), + .generic = COMPOUND_STRING("聪明招式"), + .negativeTrait = COMPOUND_STRING("犹豫"), + .palette = 15, + }, + + [CONTEST_CATEGORY_TOUGH] = + { + .name = COMPOUND_STRING("强壮"), + .condition = COMPOUND_STRING("强壮"), + .generic = COMPOUND_STRING("强壮招式"), + .negativeTrait = COMPOUND_STRING("害怕"), + .palette = 13, + }, + + [CONTEST_CATEGORIES_COUNT] = + { + .generic = COMPOUND_STRING("???"), + }, }; // Takes the .attentionLevel of a contestant as an index. @@ -1914,7 +1909,7 @@ static void Task_DoAppeals(u8 taskId) if (eContestantStatus[contestant].currMove < MOVES_COUNT) StringCopy(gStringVar2, GetMoveName(eContestantStatus[contestant].currMove)); else - StringCopy(gStringVar2, sInvalidContestMoveNames[eContestantStatus[contestant].moveCategory]); + StringCopy(gStringVar2, gContestCategoryInfo[eContestantStatus[contestant].moveCategory].generic); StringExpandPlaceholders(gStringVar4, gText_MonAppealedWithMove); Contest_StartTextPrinter(gStringVar4, TRUE); gTasks[taskId].tState = APPEALSTATE_WAIT_USED_MOVE_MSG; @@ -2310,7 +2305,7 @@ static void Task_DoAppeals(u8 taskId) } else { - StringCopy(gStringVar3, sContestConditions[GetMoveContestCategory(eContestantStatus[contestant].currMove)]); + StringCopy(gStringVar3, gContestCategoryInfo[GetMoveContestCategory(eContestantStatus[contestant].currMove)].condition); } if (r3 > 0 && eContestantStatus[contestant].repeatedMove) @@ -3330,7 +3325,7 @@ static void PrintContestMoveDescription(u16 move) ContestBG_FillBoxWithTile(0, TILE_FILLED_JAM_HEART, 0x15, 0x20, numHearts, 0x01, 0x11); FillWindowPixelBuffer(WIN_MOVE_DESCRIPTION, PIXEL_FILL(0)); - Contest_PrintTextToBg0WindowStd(WIN_MOVE_DESCRIPTION, gContestEffectDescriptionPointers[GetMoveContestEffect(move)]); + Contest_PrintTextToBg0WindowStd(WIN_MOVE_DESCRIPTION, gContestEffects[GetMoveContestEffect(move)].description); Contest_PrintTextToBg0WindowStd(WIN_SLASH, gText_Slash); } @@ -4559,7 +4554,7 @@ static void CalculateAppealMoveImpact(u8 contestant) && !AreMovesContestCombo(eContestantStatus[contestant].prevMove, eContestantStatus[contestant].currMove)) eContestantStatus[contestant].hasJudgesAttention = FALSE; - gContestEffectFuncs[effect](); + gContestEffects[effect].function(); if (eContestantStatus[contestant].conditionMod == CONDITION_GAIN) eContestantStatus[contestant].appeal += eContestantStatus[contestant].condition - 10; @@ -4664,16 +4659,7 @@ static void PrintAppealMoveResultText(u8 contestant, u8 stringId) { StringCopy(gStringVar1, gContestMons[contestant].nickname); StringCopy(gStringVar2, GetMoveName(eContestantStatus[contestant].currMove)); - if (GetMoveContestCategory(eContestantStatus[eContestAppealResults.contestant].currMove) == CONTEST_CATEGORY_COOL) - StringCopy(gStringVar3, gText_Contest_Shyness); - else if (GetMoveContestCategory(eContestantStatus[eContestAppealResults.contestant].currMove) == CONTEST_CATEGORY_BEAUTY) - StringCopy(gStringVar3, gText_Contest_Anxiety); - else if (GetMoveContestCategory(eContestantStatus[eContestAppealResults.contestant].currMove) == CONTEST_CATEGORY_CUTE) - StringCopy(gStringVar3, gText_Contest_Laziness); - else if (GetMoveContestCategory(eContestantStatus[eContestAppealResults.contestant].currMove) == CONTEST_CATEGORY_SMART) - StringCopy(gStringVar3, gText_Contest_Hesitancy); - else - StringCopy(gStringVar3, gText_Contest_Fear); + StringCopy(gStringVar3, gContestCategoryInfo[GetMoveContestCategory(eContestantStatus[eContestAppealResults.contestant].currMove)].negativeTrait); StringExpandPlaceholders(gStringVar4, sAppealResultTexts[stringId]); ContestClearGeneralTextWindow(); Contest_StartTextPrinter(gStringVar4, TRUE); diff --git a/src/contest_ai.c b/src/contest_ai.c index 77f27fcc91..8d4a347280 100644 --- a/src/contest_ai.c +++ b/src/contest_ai.c @@ -1199,7 +1199,7 @@ static void ContestAICmd_if_condition_not_eq(void) static void ContestAICmd_get_used_combo_starter(void) { - u16 result = FALSE; + bool32 result = FALSE; u8 contestant = GetContestantIdByTurn(gAIScriptPtr[1]); if (IsContestantAllowedToCombo(contestant)) diff --git a/src/contest_effect.c b/src/contest_effect.c index 51416ba14a..3190e98443 100644 --- a/src/contest_effect.c +++ b/src/contest_effect.c @@ -133,7 +133,7 @@ static void ContestEffect_UserLessEasilyStartled(void) SetContestantEffectStringID(eContestAppealResults.contestant,CONTEST_STRING_STOPPED_CARING); } -// Slightly startles the POK�MON in front. +// Badly startles the Pokémon in front. static void ContestEffect_StartleFrontMon(void) { u8 idx = 0; @@ -611,6 +611,7 @@ static void ContestEffect_BetterWhenLater(void) } // The appeal's quality varies depending on its timing. +// Despite the name, it seems to be random and not based on timing static void ContestEffect_QualityDependsOnTiming(void) { u8 rval = Random() % 10; diff --git a/src/contest_painting.c b/src/contest_painting.c index e8f929ef4b..f2b0a6c64d 100644 --- a/src/contest_painting.c +++ b/src/contest_painting.c @@ -42,32 +42,7 @@ static void PrintContestPaintingCaption(u8, u8); static void VBlankCB_ContestPainting(void); static void _InitContestMonPixels(u8 *spriteGfx, u16 *palette, u16 (*destPixels)[64][64]); -extern const u8 gContestHallPaintingCaption[]; -extern const u8 gContestCoolness[]; -extern const u8 gContestBeauty[]; -extern const u8 gContestCuteness[]; -extern const u8 gContestSmartness[]; -extern const u8 gContestToughness[]; -extern const u8 gContestRankNormal[]; -extern const u8 gContestRankSuper[]; -extern const u8 gContestRankHyper[]; -extern const u8 gContestRankMaster[]; -extern const u8 gContestLink[]; -extern const u8 gContestPaintingCool1[]; -extern const u8 gContestPaintingCool2[]; -extern const u8 gContestPaintingCool3[]; -extern const u8 gContestPaintingBeauty1[]; -extern const u8 gContestPaintingBeauty2[]; -extern const u8 gContestPaintingBeauty3[]; -extern const u8 gContestPaintingCute1[]; -extern const u8 gContestPaintingCute2[]; -extern const u8 gContestPaintingCute3[]; -extern const u8 gContestPaintingSmart1[]; -extern const u8 gContestPaintingSmart2[]; -extern const u8 gContestPaintingSmart3[]; -extern const u8 gContestPaintingTough1[]; -extern const u8 gContestPaintingTough2[]; -extern const u8 gContestPaintingTough3[]; +const u8 gContestHallPaintingCaption[] = COMPOUND_STRING("{STR_VAR_1}\n{STR_VAR_2}的{STR_VAR_3}"); static const u16 sPictureFramePalettes[] = INCBIN_U16("graphics/picture_frame/bg.gbapal"); static const u32 sPictureFrameTiles_Cool[] = INCBIN_U32("graphics/picture_frame/cool.4bpp.smol"); @@ -85,20 +60,20 @@ static const u32 sPictureFrameTilemap_HallLobby[] = INCBIN_U32("graphics/picture static const u8 *const sContestCategoryNames_Unused[] = { - [CONTEST_CATEGORY_COOL] = gContestCoolness, - [CONTEST_CATEGORY_BEAUTY] = gContestBeauty, - [CONTEST_CATEGORY_CUTE] = gContestCuteness, - [CONTEST_CATEGORY_SMART] = gContestSmartness, - [CONTEST_CATEGORY_TOUGH] = gContestToughness, + [CONTEST_CATEGORY_COOL] = COMPOUND_STRING("帅气"), + [CONTEST_CATEGORY_BEAUTY] = COMPOUND_STRING("美丽"), + [CONTEST_CATEGORY_CUTE] = COMPOUND_STRING("可爱"), + [CONTEST_CATEGORY_SMART] = COMPOUND_STRING("聪明"), + [CONTEST_CATEGORY_TOUGH] = COMPOUND_STRING("强壮"), }; static const u8 *const sContestRankNames[] = { - [CONTEST_RANK_NORMAL] = gContestRankNormal, - [CONTEST_RANK_SUPER] = gContestRankSuper, - [CONTEST_RANK_HYPER] = gContestRankHyper, - [CONTEST_RANK_MASTER] = gContestRankMaster, - [CONTEST_RANK_LINK] = gContestLink, + [CONTEST_RANK_NORMAL] = COMPOUND_STRING("普通级"), + [CONTEST_RANK_SUPER] = COMPOUND_STRING("高手级"), + [CONTEST_RANK_HYPER] = COMPOUND_STRING("究极级"), + [CONTEST_RANK_MASTER] = COMPOUND_STRING("大师级"), + [CONTEST_RANK_LINK] = COMPOUND_STRING("连接"), }; static const struct BgTemplate sBgTemplates[] = @@ -127,21 +102,21 @@ static const struct WindowTemplate sWindowTemplate = static const u8 *const sMuseumCaptions[NUM_PAINTING_CAPTIONS * CONTEST_CATEGORIES_COUNT] = { - [0 + NUM_PAINTING_CAPTIONS * CONTEST_CATEGORY_COOL] = gContestPaintingCool1, - [1 + NUM_PAINTING_CAPTIONS * CONTEST_CATEGORY_COOL] = gContestPaintingCool2, - [2 + NUM_PAINTING_CAPTIONS * CONTEST_CATEGORY_COOL] = gContestPaintingCool3, - [0 + NUM_PAINTING_CAPTIONS * CONTEST_CATEGORY_BEAUTY] = gContestPaintingBeauty1, - [1 + NUM_PAINTING_CAPTIONS * CONTEST_CATEGORY_BEAUTY] = gContestPaintingBeauty2, - [2 + NUM_PAINTING_CAPTIONS * CONTEST_CATEGORY_BEAUTY] = gContestPaintingBeauty3, - [0 + NUM_PAINTING_CAPTIONS * CONTEST_CATEGORY_CUTE] = gContestPaintingCute1, - [1 + NUM_PAINTING_CAPTIONS * CONTEST_CATEGORY_CUTE] = gContestPaintingCute2, - [2 + NUM_PAINTING_CAPTIONS * CONTEST_CATEGORY_CUTE] = gContestPaintingCute3, - [0 + NUM_PAINTING_CAPTIONS * CONTEST_CATEGORY_SMART] = gContestPaintingSmart1, - [1 + NUM_PAINTING_CAPTIONS * CONTEST_CATEGORY_SMART] = gContestPaintingSmart2, - [2 + NUM_PAINTING_CAPTIONS * CONTEST_CATEGORY_SMART] = gContestPaintingSmart3, - [0 + NUM_PAINTING_CAPTIONS * CONTEST_CATEGORY_TOUGH] = gContestPaintingTough1, - [1 + NUM_PAINTING_CAPTIONS * CONTEST_CATEGORY_TOUGH] = gContestPaintingTough2, - [2 + NUM_PAINTING_CAPTIONS * CONTEST_CATEGORY_TOUGH] = gContestPaintingTough3, + [0 + NUM_PAINTING_CAPTIONS * CONTEST_CATEGORY_COOL] = COMPOUND_STRING("Nonstop supercool--\nthe inestimable {STR_VAR_1}"), + [1 + NUM_PAINTING_CAPTIONS * CONTEST_CATEGORY_COOL] = COMPOUND_STRING("Hey, there!\nThe good-looking POKéMON {STR_VAR_1}"), + [2 + NUM_PAINTING_CAPTIONS * CONTEST_CATEGORY_COOL] = COMPOUND_STRING("The marvelous, wonderful, and\nvery great {STR_VAR_1}"), + [0 + NUM_PAINTING_CAPTIONS * CONTEST_CATEGORY_BEAUTY] = COMPOUND_STRING("This century's last Venus--\nthe beautiful {STR_VAR_1}"), + [1 + NUM_PAINTING_CAPTIONS * CONTEST_CATEGORY_BEAUTY] = COMPOUND_STRING("{STR_VAR_1}'s dazzling,\nglittering smile"), + [2 + NUM_PAINTING_CAPTIONS * CONTEST_CATEGORY_BEAUTY] = COMPOUND_STRING("POKéMON CENTER's super idol--\nthe incomparable {STR_VAR_1}"), + [0 + NUM_PAINTING_CAPTIONS * CONTEST_CATEGORY_CUTE] = COMPOUND_STRING("The lovely and sweet {STR_VAR_1}"), + [1 + NUM_PAINTING_CAPTIONS * CONTEST_CATEGORY_CUTE] = COMPOUND_STRING("The pretty {STR_VAR_1}'s\nwinning portrait"), + [2 + NUM_PAINTING_CAPTIONS * CONTEST_CATEGORY_CUTE] = COMPOUND_STRING("Give us a wink!\nThe cutie POKéMON {STR_VAR_1}"), + [0 + NUM_PAINTING_CAPTIONS * CONTEST_CATEGORY_SMART] = COMPOUND_STRING("The smartness maestro--\nthe wise POKéMON {STR_VAR_1}"), + [1 + NUM_PAINTING_CAPTIONS * CONTEST_CATEGORY_SMART] = COMPOUND_STRING("{STR_VAR_1}--the one chosen\nabove all POKéMON"), + [2 + NUM_PAINTING_CAPTIONS * CONTEST_CATEGORY_SMART] = COMPOUND_STRING("The excellent {STR_VAR_1}'s\nmoment of elegance"), + [0 + NUM_PAINTING_CAPTIONS * CONTEST_CATEGORY_TOUGH] = COMPOUND_STRING("The powerfully muscular\nspeedster {STR_VAR_1}"), + [1 + NUM_PAINTING_CAPTIONS * CONTEST_CATEGORY_TOUGH] = COMPOUND_STRING("The strong, stronger, and\nstrongest {STR_VAR_1}"), + [2 + NUM_PAINTING_CAPTIONS * CONTEST_CATEGORY_TOUGH] = COMPOUND_STRING("The mighty tough\nhyper POKéMON {STR_VAR_1}"), }; static const struct OamData sContestPaintingMonOamData = diff --git a/src/contest_util.c b/src/contest_util.c index d0260944c6..db97fd0177 100644 --- a/src/contest_util.c +++ b/src/contest_util.c @@ -1961,7 +1961,7 @@ void TryEnterContestMon(void) u16 HasMonWonThisContestBefore(void) { - u16 hasRankRibbon = FALSE; + bool32 hasRankRibbon = FALSE; struct Pokemon *mon = &gPlayerParty[gContestMonPartyIndex]; switch (gSpecialVar_ContestCategory) { diff --git a/src/data/abilities.h b/src/data/abilities.h index 658c0d96f8..3dd18a4977 100644 --- a/src/data/abilities.h +++ b/src/data/abilities.h @@ -1,4 +1,4 @@ -const struct Ability gAbilitiesInfo[ABILITIES_COUNT] = +const struct AbilityInfo gAbilitiesInfo[ABILITIES_COUNT] = { [ABILITY_NONE] = { @@ -1247,6 +1247,7 @@ const struct Ability gAbilitiesInfo[ABILITIES_COUNT] = .name = _("花幕"), .description = COMPOUND_STRING("守护己方草宝可梦能力状态"), .aiRating = 0, + .breakable = TRUE, }, [ABILITY_CHEEK_POUCH] = @@ -1410,6 +1411,7 @@ const struct Ability gAbilitiesInfo[ABILITIES_COUNT] = .name = _("气场破坏"), .description = COMPOUND_STRING("让气场的效果发生逆转"), .aiRating = 3, + .breakable = TRUE, }, [ABILITY_PRIMORDIAL_SEA] = @@ -1492,6 +1494,7 @@ const struct Ability gAbilitiesInfo[ABILITIES_COUNT] = .name = _("水泡"), .description = COMPOUND_STRING("降低火招式伤害且不会灼伤"), .aiRating = 8, + .breakable = TRUE, }, [ABILITY_STEELWORKER] = diff --git a/src/data/apricorns.h b/src/data/apricorns.h new file mode 100644 index 0000000000..4f76f30648 --- /dev/null +++ b/src/data/apricorns.h @@ -0,0 +1,18 @@ +struct ApricornTree +{ + u8 minimum; + u8 maximum; + enum ApricornType apricornType; +}; + +const struct ApricornTree gApricornTrees[APRICORN_TREE_COUNT] = +{ + #if APRICORN_TREE_COUNT > 0 + [APRICORN_TREE_NONE] = + { + .minimum = 1, + .maximum = 1, + .apricornType = APRICORN_RED, + }, + #endif +}; diff --git a/src/data/battle_environment.h b/src/data/battle_environment.h index 1773e6ced3..5e485ad5b1 100644 --- a/src/data/battle_environment.h +++ b/src/data/battle_environment.h @@ -130,9 +130,7 @@ const struct BattleEnvironment gBattleEnvironmentInfo[BATTLE_ENVIRONMENT_COUNT] [BATTLE_ENVIRONMENT_CAVE] = { #if B_NATURE_POWER_MOVES >= GEN_6 - .naturePower = MOVE_EARTH_POWER, - #elif B_NATURE_POWER_MOVES >= GEN_5 - .naturePower = MOVE_EARTHQUAKE, + .naturePower = MOVE_POWER_GEM, #elif B_NATURE_POWER_MOVES >= GEN_4 .naturePower = MOVE_ROCK_SLIDE, #else @@ -160,8 +158,8 @@ const struct BattleEnvironment gBattleEnvironmentInfo[BATTLE_ENVIRONMENT_COUNT] #else .naturePower = MOVE_SWIFT, #endif - .secretPowerEffect = MOVE_EFFECT_PARALYSIS, - .camouflageType = B_CAMOUFLAGE_TYPES >= GEN_4 ? TYPE_GROUND : TYPE_NORMAL, + .secretPowerEffect = (B_SECRET_POWER_EFFECT == GEN_4 || B_SECRET_POWER_EFFECT == GEN_5) ? MOVE_EFFECT_ACC_MINUS_1 : MOVE_EFFECT_PARALYSIS, + .camouflageType = (B_CAMOUFLAGE_TYPES == GEN_4 || B_CAMOUFLAGE_TYPES == GEN_5) ? TYPE_GROUND : TYPE_NORMAL, .background = { .tileset = gBattleEnvironmentTiles_Building, diff --git a/src/data/battle_frontier/battle_pyramid_wild_requirements.h b/src/data/battle_frontier/battle_pyramid_wild_requirements.h index fd5695344a..6679905f58 100644 --- a/src/data/battle_frontier/battle_pyramid_wild_requirements.h +++ b/src/data/battle_frontier/battle_pyramid_wild_requirements.h @@ -5,9 +5,9 @@ struct BattlePyramidRequirement { const u16 *moves; /* use moves instead of effects so we don't need to find moves with said effect in our loop */ - u16 abilities[10]; + enum Ability abilities[10]; u8 nAbilities; - u8 type; + enum Type type; u8 nMoves; const u16 *evoItems; u8 nEvoItems; diff --git a/src/data/battle_move_effects.h b/src/data/battle_move_effects.h index 51bbdba0eb..24ed815aa2 100644 --- a/src/data/battle_move_effects.h +++ b/src/data/battle_move_effects.h @@ -20,6 +20,7 @@ const struct BattleMoveEffect gBattleMoveEffects[NUM_BATTLE_MOVE_EFFECTS] = { .battleScript = BattleScript_EffectNonVolatileStatus, .battleTvScore = 0, // Handled within the battle TV functions + .encourageEncore = TRUE, }, [EFFECT_ABSORB] = @@ -49,7 +50,7 @@ const struct BattleMoveEffect gBattleMoveEffects[NUM_BATTLE_MOVE_EFFECTS] = [EFFECT_MIRROR_MOVE] = { - .battleScript = BattleScript_EffectMirrorMove, + .battleScript = BattleScript_EffectHit, .battleTvScore = 1, }, @@ -398,7 +399,7 @@ const struct BattleMoveEffect gBattleMoveEffects[NUM_BATTLE_MOVE_EFFECTS] = [EFFECT_METRONOME] = { - .battleScript = BattleScript_EffectMetronome, + .battleScript = BattleScript_EffectHit, .battleTvScore = 1, }, @@ -502,7 +503,7 @@ const struct BattleMoveEffect gBattleMoveEffects[NUM_BATTLE_MOVE_EFFECTS] = [EFFECT_SLEEP_TALK] = { - .battleScript = BattleScript_EffectSleepTalk, + .battleScript = BattleScript_EffectHit, .battleTvScore = 3, .encourageEncore = TRUE, }, @@ -577,6 +578,12 @@ const struct BattleMoveEffect gBattleMoveEffects[NUM_BATTLE_MOVE_EFFECTS] = .battleTvScore = 0, // TODO: Assign points }, + [EFFECT_LUNAR_DANCE] = + { + .battleScript = BattleScript_EffectHealingWish, + .battleTvScore = 0, // TODO: Assign points + }, + [EFFECT_PROTECT] = { .battleScript = BattleScript_EffectProtect, @@ -791,7 +798,7 @@ const struct BattleMoveEffect gBattleMoveEffects[NUM_BATTLE_MOVE_EFFECTS] = [EFFECT_BEAT_UP] = { - .battleScript = (B_BEAT_UP >= GEN_5) ? BattleScript_EffectHit : BattleScript_EffectBeatUp, + .battleScript = BattleScript_EffectBeatUp, .battleTvScore = 2, }, @@ -819,14 +826,14 @@ const struct BattleMoveEffect gBattleMoveEffects[NUM_BATTLE_MOVE_EFFECTS] = [EFFECT_FIRST_TURN_ONLY] = { - .battleScript = BattleScript_EffectFirstTurnOnly, + .battleScript = BattleScript_EffectHit, .battleTvScore = 4, .encourageEncore = TRUE, }, [EFFECT_UPROAR] = { - .battleScript = BattleScript_EffectUproar, + .battleScript = BattleScript_EffectHit, .battleTvScore = 4, }, @@ -851,9 +858,9 @@ const struct BattleMoveEffect gBattleMoveEffects[NUM_BATTLE_MOVE_EFFECTS] = .encourageEncore = TRUE, }, - [EFFECT_WORRY_SEED] = + [EFFECT_OVERWRITE_ABILITY] = { - .battleScript = BattleScript_EffectWorrySeed, + .battleScript = BattleScript_EffectOverwriteAbility, .battleTvScore = 0, // TODO: Assign points .encourageEncore = TRUE, }, @@ -911,7 +918,7 @@ const struct BattleMoveEffect gBattleMoveEffects[NUM_BATTLE_MOVE_EFFECTS] = [EFFECT_NATURE_POWER] = { - .battleScript = BattleScript_EffectNaturePower, + .battleScript = BattleScript_EffectHit, .battleTvScore = 0, // TODO: Assign points }, @@ -956,7 +963,7 @@ const struct BattleMoveEffect gBattleMoveEffects[NUM_BATTLE_MOVE_EFFECTS] = [EFFECT_ASSIST] = { - .battleScript = BattleScript_EffectAssist, + .battleScript = BattleScript_EffectHit, .battleTvScore = 2, }, @@ -1392,13 +1399,7 @@ const struct BattleMoveEffect gBattleMoveEffects[NUM_BATTLE_MOVE_EFFECTS] = [EFFECT_SUCKER_PUNCH] = { - .battleScript = BattleScript_EffectSuckerPunch, - .battleTvScore = 0, // TODO: Assign points - }, - - [EFFECT_SIMPLE_BEAM] = - { - .battleScript = BattleScript_EffectSimpleBeam, + .battleScript = BattleScript_EffectHit, .battleTvScore = 0, // TODO: Assign points }, @@ -1486,7 +1487,7 @@ const struct BattleMoveEffect gBattleMoveEffects[NUM_BATTLE_MOVE_EFFECTS] = [EFFECT_ME_FIRST] = { - .battleScript = BattleScript_EffectMeFirst, + .battleScript = BattleScript_EffectHit, .battleTvScore = 0, // TODO: Assign points }, @@ -1531,7 +1532,7 @@ const struct BattleMoveEffect gBattleMoveEffects[NUM_BATTLE_MOVE_EFFECTS] = [EFFECT_LAST_RESORT] = { - .battleScript = BattleScript_EffectLastResort, + .battleScript = BattleScript_EffectHit, .battleTvScore = 0, // TODO: Assign points }, @@ -1601,7 +1602,7 @@ const struct BattleMoveEffect gBattleMoveEffects[NUM_BATTLE_MOVE_EFFECTS] = [EFFECT_COPYCAT] = { - .battleScript = BattleScript_EffectCopycat, + .battleScript = BattleScript_EffectHit, .battleTvScore = 0, // TODO: Assign points }, @@ -1721,7 +1722,7 @@ const struct BattleMoveEffect gBattleMoveEffects[NUM_BATTLE_MOVE_EFFECTS] = [EFFECT_MAT_BLOCK] = { - .battleScript = BattleScript_EffectMatBlock, + .battleScript = BattleScript_EffectProtect, .battleTvScore = 0, // TODO: Assign points .encourageEncore = TRUE, }, @@ -1774,7 +1775,7 @@ const struct BattleMoveEffect gBattleMoveEffects[NUM_BATTLE_MOVE_EFFECTS] = [EFFECT_FAIL_IF_NOT_ARG_TYPE] = { - .battleScript = BattleScript_FailIfNotArgType, + .battleScript = BattleScript_EffectHit, .battleTvScore = 0, // TODO: Assign points }, @@ -1881,7 +1882,7 @@ const struct BattleMoveEffect gBattleMoveEffects[NUM_BATTLE_MOVE_EFFECTS] = [EFFECT_AURA_WHEEL] = { - .battleScript = BattleScript_EffectAuraWheel, + .battleScript = BattleScript_EffectHit, .battleTvScore = 0, // TODO: Assign points }, @@ -1984,12 +1985,6 @@ const struct BattleMoveEffect gBattleMoveEffects[NUM_BATTLE_MOVE_EFFECTS] = .battleTvScore = 0, // TODO: Assign points }, - [EFFECT_HIT_SET_TERRAIN] = - { - .battleScript = BattleScript_EffectHitSetTerrain, - .battleTvScore = 0, // TODO: Assign points - }, - [EFFECT_DARK_VOID] = { .battleScript = BattleScript_EffectDarkVoid, @@ -2133,7 +2128,7 @@ const struct BattleMoveEffect gBattleMoveEffects[NUM_BATTLE_MOVE_EFFECTS] = [EFFECT_UPPER_HAND] = { - .battleScript = BattleScript_EffectUpperHand, + .battleScript = BattleScript_EffectHit, .battleTvScore = 0, // TODO: Assign points .encourageEncore = TRUE, }, @@ -2233,7 +2228,7 @@ const struct BattleMoveEffect gBattleMoveEffects[NUM_BATTLE_MOVE_EFFECTS] = [EFFECT_STEEL_ROLLER] = { - .battleScript = BattleScript_EffectSteelRoller, + .battleScript = BattleScript_EffectHit, .battleTvScore = 0, // TODO: Assign points }, diff --git a/src/data/battle_pool_rules.h b/src/data/battle_pool_rules.h index b88db3c797..eefb101f55 100644 --- a/src/data/battle_pool_rules.h +++ b/src/data/battle_pool_rules.h @@ -12,6 +12,8 @@ const struct PoolRules defaultPoolRules = .excludeForms = B_POOL_RULE_EXCLUDE_FORMS, .itemClause = B_POOL_RULE_ITEM_CLAUSE, .itemClauseExclusions = B_POOL_RULES_USE_ITEM_EXCLUSIONS, + .megaStoneClause = B_POOL_RULE_MEGA_STONE_CLAUSE, + .zCrystalClause = B_POOL_RULE_Z_CRYSTAL_CLAUSE, }; const struct PoolRules gPoolRulesetsList[] = { @@ -20,6 +22,8 @@ const struct PoolRules gPoolRulesetsList[] = { .excludeForms = B_POOL_RULE_EXCLUDE_FORMS, .itemClause = B_POOL_RULE_ITEM_CLAUSE, .itemClauseExclusions = B_POOL_RULES_USE_ITEM_EXCLUSIONS, + .megaStoneClause = B_POOL_RULE_MEGA_STONE_CLAUSE, + .zCrystalClause = B_POOL_RULE_Z_CRYSTAL_CLAUSE, .tagMaxMembers[POOL_TAG_LEAD] = 1, .tagMaxMembers[POOL_TAG_ACE] = 1, }, @@ -28,6 +32,8 @@ const struct PoolRules gPoolRulesetsList[] = { .excludeForms = B_POOL_RULE_EXCLUDE_FORMS, .itemClause = B_POOL_RULE_ITEM_CLAUSE, .itemClauseExclusions = B_POOL_RULES_USE_ITEM_EXCLUSIONS, + .megaStoneClause = B_POOL_RULE_MEGA_STONE_CLAUSE, + .zCrystalClause = B_POOL_RULE_Z_CRYSTAL_CLAUSE, .tagMaxMembers[POOL_TAG_LEAD] = 2, .tagMaxMembers[POOL_TAG_ACE] = 2, }, @@ -36,6 +42,8 @@ const struct PoolRules gPoolRulesetsList[] = { .excludeForms = B_POOL_RULE_EXCLUDE_FORMS, .itemClause = B_POOL_RULE_ITEM_CLAUSE, .itemClauseExclusions = B_POOL_RULES_USE_ITEM_EXCLUSIONS, + .megaStoneClause = B_POOL_RULE_MEGA_STONE_CLAUSE, + .zCrystalClause = B_POOL_RULE_Z_CRYSTAL_CLAUSE, .tagMaxMembers[POOL_TAG_LEAD] = 1, .tagMaxMembers[POOL_TAG_ACE] = 1, .tagMaxMembers[POOL_TAG_WEATHER_SETTER] = 1, @@ -48,6 +56,8 @@ const struct PoolRules gPoolRulesetsList[] = { .excludeForms = B_POOL_RULE_EXCLUDE_FORMS, .itemClause = B_POOL_RULE_ITEM_CLAUSE, .itemClauseExclusions = B_POOL_RULES_USE_ITEM_EXCLUSIONS, + .megaStoneClause = B_POOL_RULE_MEGA_STONE_CLAUSE, + .zCrystalClause = B_POOL_RULE_Z_CRYSTAL_CLAUSE, .tagMaxMembers[POOL_TAG_LEAD] = 2, .tagMaxMembers[POOL_TAG_ACE] = 2, .tagMaxMembers[POOL_TAG_WEATHER_SETTER] = 1, @@ -60,6 +70,8 @@ const struct PoolRules gPoolRulesetsList[] = { .excludeForms = B_POOL_RULE_EXCLUDE_FORMS, .itemClause = B_POOL_RULE_ITEM_CLAUSE, .itemClauseExclusions = B_POOL_RULES_USE_ITEM_EXCLUSIONS, + .megaStoneClause = B_POOL_RULE_MEGA_STONE_CLAUSE, + .zCrystalClause = B_POOL_RULE_Z_CRYSTAL_CLAUSE, .tagMaxMembers[POOL_TAG_LEAD] = 2, .tagMaxMembers[POOL_TAG_ACE] = 2, .tagMaxMembers[POOL_TAG_SUPPORT] = 1, diff --git a/src/data/contest_moves.h b/src/data/contest_moves.h index ce88430bb6..61260e9ee4 100644 --- a/src/data/contest_moves.h +++ b/src/data/contest_moves.h @@ -2,342 +2,422 @@ const struct ContestEffect gContestEffects[] = { [CONTEST_EFFECT_HIGHLY_APPEALING] = { + #if C_UPDATED_MOVE_EFFECTS >= GEN_6 + .description = COMPOUND_STRING("能够吸引人的表演。"), + #else + .description = COMPOUND_STRING("能够吸引人的表演。"), + #endif .effectType = CONTEST_EFFECT_TYPE_APPEAL, .appeal = 40, .jam = 0, + .function = ContestEffect_HighlyAppealing, }, [CONTEST_EFFECT_USER_MORE_EASILY_STARTLED] = { + .description = COMPOUND_STRING("虽然能够演出很好的表演,\n但是之后会更容易受干扰。"), .effectType = CONTEST_EFFECT_TYPE_APPEAL, .appeal = 60, .jam = 0, + .function = ContestEffect_UserMoreEasilyStartled, }, [CONTEST_EFFECT_GREAT_APPEAL_BUT_NO_MORE_MOVES] = { + .description = COMPOUND_STRING("极具吸引力的表演,\n但是此后无法再进行表演。"), .effectType = CONTEST_EFFECT_TYPE_APPEAL, .appeal = 80, .jam = 0, + .function = ContestEffect_GreatAppealButNoMoreMoves, }, [CONTEST_EFFECT_REPETITION_NOT_BORING] = { + .description = COMPOUND_STRING("即使重复演出也不会\n让评委感到无聊。"), .effectType = CONTEST_EFFECT_TYPE_APPEAL, .appeal = 30, .jam = 0, + .function = ContestEffect_RepetitionNotBoring, }, [CONTEST_EFFECT_AVOID_STARTLE_ONCE] = { + .description = COMPOUND_STRING("即使被之后的宝可梦干扰\n也会挺住一次。"), .effectType = CONTEST_EFFECT_TYPE_AVOID_STARTLE, .appeal = 20, .jam = 0, + .function = ContestEffect_AvoidStartleOnce, }, [CONTEST_EFFECT_AVOID_STARTLE] = { + .description = COMPOUND_STRING("即使被之后的宝可梦干扰\n也会挺住。"), .effectType = CONTEST_EFFECT_TYPE_AVOID_STARTLE, .appeal = 10, .jam = 0, + .function = ContestEffect_AvoidStartle, }, [CONTEST_EFFECT_AVOID_STARTLE_SLIGHTLY] = { + .description = COMPOUND_STRING("能够稍稍避免受到\n被其他宝可梦干扰。"), .effectType = CONTEST_EFFECT_TYPE_AVOID_STARTLE, .appeal = 30, .jam = 0, + .function = ContestEffect_AvoidStartleSlightly, }, [CONTEST_EFFECT_USER_LESS_EASILY_STARTLED] = { + .description = COMPOUND_STRING("在表演这个招式之后\n宝可梦会变得不易受干扰。"), .effectType = CONTEST_EFFECT_TYPE_AVOID_STARTLE, .appeal = 30, .jam = 0, + .function = ContestEffect_UserLessEasilyStartled, }, [CONTEST_EFFECT_STARTLE_FRONT_MON] = { + .description = COMPOUND_STRING("稍稍干扰在自己之前表演的\n宝可梦。"), .effectType = CONTEST_EFFECT_TYPE_STARTLE_MON, .appeal = 30, .jam = 20, + .function = ContestEffect_StartleFrontMon, }, [CONTEST_EFFECT_SLIGHTLY_STARTLE_PREV_MONS] = { + .description = COMPOUND_STRING("稍稍干扰表演完成的\n所有宝可梦。"), .effectType = CONTEST_EFFECT_TYPE_STARTLE_MONS, .appeal = 30, .jam = 10, + .function = ContestEffect_StartlePrevMons, }, [CONTEST_EFFECT_STARTLE_PREV_MON] = { + #if C_UPDATED_MOVE_EFFECTS >= GEN_6 + .description = COMPOUND_STRING("干扰在自己之前表演的\n宝可梦。"), + #else + .description = COMPOUND_STRING("干扰在自己之前表演的\n宝可梦。"), + #endif .effectType = CONTEST_EFFECT_TYPE_STARTLE_MON, .appeal = 20, .jam = 30, + .function = ContestEffect_StartleFrontMon, }, [CONTEST_EFFECT_STARTLE_PREV_MONS] = { + #if C_UPDATED_MOVE_EFFECTS >= GEN_6 + .description = COMPOUND_STRING("干扰表演完成的\n所有宝可梦。"), + #else + .description = COMPOUND_STRING("干扰表演完成的\n所有宝可梦。"), + #endif .effectType = CONTEST_EFFECT_TYPE_STARTLE_MONS, .appeal = 20, .jam = 20, + .function = ContestEffect_StartlePrevMons, }, [CONTEST_EFFECT_BADLY_STARTLE_FRONT_MON] = { + .description = COMPOUND_STRING("严重干扰在自己之前表演的\n宝可梦。"), .effectType = CONTEST_EFFECT_TYPE_STARTLE_MON, .appeal = 10, .jam = 40, + .function = ContestEffect_StartleFrontMon, }, [CONTEST_EFFECT_BADLY_STARTLE_PREV_MONS] = { + .description = COMPOUND_STRING("严重干扰表演完成的\n所有宝可梦。"), .effectType = CONTEST_EFFECT_TYPE_STARTLE_MONS, .appeal = 10, .jam = 30, + .function = ContestEffect_StartlePrevMons, }, [CONTEST_EFFECT_STARTLE_PREV_MON_2] = { + .description = COMPOUND_STRING("干扰在自己之前表演的\n宝可梦。"), .effectType = CONTEST_EFFECT_TYPE_STARTLE_MON, .appeal = 30, .jam = 20, + .function = ContestEffect_StartlePrevMon2, }, [CONTEST_EFFECT_STARTLE_PREV_MONS_2] = { + .description = COMPOUND_STRING("干扰表演完成的\n所有宝可梦。"), .effectType = CONTEST_EFFECT_TYPE_STARTLE_MONS, .appeal = 30, .jam = 10, + .function = ContestEffect_StartlePrevMons2, }, [CONTEST_EFFECT_SHIFT_JUDGE_ATTENTION] = { + #if C_UPDATED_MOVE_EFFECTS >= GEN_6 + .description = COMPOUND_STRING("分散评委对之前宝可梦的\n注意。"), + #else + .description = COMPOUND_STRING("分散评委对之前宝可梦的\n注意。"), + #endif .effectType = CONTEST_EFFECT_TYPE_WORSEN, .appeal = 30, .jam = 0, + .function = ContestEffect_ShiftJudgeAttention, }, [CONTEST_EFFECT_STARTLE_MON_WITH_JUDGES_ATTENTION] = { + .description = COMPOUND_STRING("特别干扰评委注意的\n宝可梦。"), .effectType = CONTEST_EFFECT_TYPE_STARTLE_MONS, .appeal = 20, .jam = 10, + .function = ContestEffect_StartleMonWithJudgesAttention, }, [CONTEST_EFFECT_JAMS_OTHERS_BUT_MISS_ONE_TURN] = { + .description = COMPOUND_STRING("激烈地干扰大家,\n但无法参加下一次表演。"), .effectType = CONTEST_EFFECT_TYPE_STARTLE_MONS, .appeal = 40, .jam = 40, + .function = ContestEffect_JamsOthersButMissOneTurn, }, [CONTEST_EFFECT_STARTLE_MONS_SAME_TYPE_APPEAL] = { + .description = COMPOUND_STRING("特别干扰演出了相同类别的\n宝可梦。"), .effectType = CONTEST_EFFECT_TYPE_STARTLE_MONS, .appeal = 20, .jam = 10, + .function = ContestEffect_StartleMonsSameTypeAppeal, }, [CONTEST_EFFECT_STARTLE_MONS_COOL_APPEAL] = { + .description = COMPOUND_STRING("特别干扰演出了帅气招式的\n宝可梦。"), .effectType = CONTEST_EFFECT_TYPE_STARTLE_MONS, .appeal = 20, .jam = 10, + .function = ContestEffect_StartleMonsCoolAppeal, }, [CONTEST_EFFECT_STARTLE_MONS_BEAUTY_APPEAL] = { + .description = COMPOUND_STRING("特别干扰演出了美丽招式的\n宝可梦。"), .effectType = CONTEST_EFFECT_TYPE_STARTLE_MONS, .appeal = 20, .jam = 10, + .function = ContestEffect_StartleMonsBeautyAppeal, }, [CONTEST_EFFECT_STARTLE_MONS_CUTE_APPEAL] = { + .description = COMPOUND_STRING("特别干扰演出了可爱招式的\n宝可梦。"), .effectType = CONTEST_EFFECT_TYPE_STARTLE_MONS, .appeal = 20, .jam = 10, + .function = ContestEffect_StartleMonsCuteAppeal, }, [CONTEST_EFFECT_STARTLE_MONS_SMART_APPEAL] = { + .description = COMPOUND_STRING("特别干扰演出了聪明招式的\n宝可梦。"), .effectType = CONTEST_EFFECT_TYPE_STARTLE_MONS, .appeal = 20, .jam = 10, + .function = ContestEffect_StartleMonsSmartAppeal, }, [CONTEST_EFFECT_STARTLE_MONS_TOUGH_APPEAL] = { + .description = COMPOUND_STRING("特别干扰演出了强壮招式的\n宝可梦。"), .effectType = CONTEST_EFFECT_TYPE_STARTLE_MONS, .appeal = 20, .jam = 10, + .function = ContestEffect_StartleMonsToughAppeal, }, [CONTEST_EFFECT_MAKE_FOLLOWING_MON_NERVOUS] = { + .description = COMPOUND_STRING("让下一只表演的宝可梦\n感到紧张。"), .effectType = CONTEST_EFFECT_TYPE_WORSEN, .appeal = 20, .jam = 0, + .function = ContestEffect_MakeFollowingMonNervous, }, [CONTEST_EFFECT_MAKE_FOLLOWING_MONS_NERVOUS] = { + #if C_UPDATED_MOVE_EFFECTS >= GEN_6 + .description = COMPOUND_STRING("让之后表演的所有宝可梦\n都感到紧张。"), + #else + .description = COMPOUND_STRING("让之后表演的所有宝可梦\n都感到紧张。"), + #endif .effectType = CONTEST_EFFECT_TYPE_WORSEN, .appeal = 20, .jam = 0, + .function = ContestEffect_MakeFollowingMonsNervous, }, [CONTEST_EFFECT_WORSEN_CONDITION_OF_PREV_MONS] = { + .description = COMPOUND_STRING("降低表演完成的\n宝可梦的气势。"), .effectType = CONTEST_EFFECT_TYPE_WORSEN, .appeal = 30, .jam = 0, + .function = ContestEffect_WorsenConditionOfPrevMons, }, [CONTEST_EFFECT_BADLY_STARTLES_MONS_IN_GOOD_CONDITION] = { + .description = COMPOUND_STRING("严重干扰气势良好的\n所有宝可梦。"), .effectType = CONTEST_EFFECT_TYPE_STARTLE_MONS, .appeal = 30, .jam = 10, + .function = ContestEffect_BadlyStartlesMonsInGoodCondition, }, [CONTEST_EFFECT_BETTER_IF_FIRST] = { + .description = COMPOUND_STRING("最先演出时表演\n会更加吸引人。"), .effectType = CONTEST_EFFECT_TYPE_SPECIAL_APPEAL, .appeal = 20, .jam = 0, + .function = ContestEffect_BetterIfFirst, }, [CONTEST_EFFECT_BETTER_IF_LAST] = { + .description = COMPOUND_STRING("最后演出时表演\n会更加吸引人。"), .effectType = CONTEST_EFFECT_TYPE_SPECIAL_APPEAL, .appeal = 20, .jam = 0, + .function = ContestEffect_BetterIfLast, }, [CONTEST_EFFECT_APPEAL_AS_GOOD_AS_PREV_ONES] = { + .description = COMPOUND_STRING("演出和此前所有宝可梦表演\n吸引力程度相当的表演。"), .effectType = CONTEST_EFFECT_TYPE_SPECIAL_APPEAL, .appeal = 10, .jam = 0, + .function = ContestEffect_AppealAsGoodAsPrevOnes, }, [CONTEST_EFFECT_APPEAL_AS_GOOD_AS_PREV_ONE] = { + .description = COMPOUND_STRING("和前一位宝可梦的\n表演一样吸引人。"), .effectType = CONTEST_EFFECT_TYPE_SPECIAL_APPEAL, .appeal = 10, .jam = 0, + .function = ContestEffect_AppealAsGoodAsPrevOne, }, [CONTEST_EFFECT_BETTER_WHEN_LATER] = { + .description = COMPOUND_STRING("演出时排序越靠后,\n越能演出吸引人的表演。"), .effectType = CONTEST_EFFECT_TYPE_SPECIAL_APPEAL, .appeal = 10, .jam = 0, + .function = ContestEffect_BetterWhenLater, }, [CONTEST_EFFECT_QUALITY_DEPENDS_ON_TIMING] = { + #if C_UPDATED_MOVE_EFFECTS >= GEN_6 + .description = COMPOUND_STRING("每次演出的结果都不同。"), + #else + .description = COMPOUND_STRING("每次演出的结果都不同。"), + #endif .effectType = CONTEST_EFFECT_TYPE_SPECIAL_APPEAL, .appeal = 10, .jam = 0, + .function = ContestEffect_QualityDependsOnTiming, }, [CONTEST_EFFECT_BETTER_IF_SAME_TYPE] = { + .description = COMPOUND_STRING("和前一位宝可梦的表演类别\n相同时会更吸引人。"), .effectType = CONTEST_EFFECT_TYPE_SPECIAL_APPEAL, .appeal = 20, .jam = 0, + .function = ContestEffect_BetterIfSameType, }, [CONTEST_EFFECT_BETTER_IF_DIFF_TYPE] = { + .description = COMPOUND_STRING("和前一位宝可梦的表演类别\n不同时会更吸引人。"), .effectType = CONTEST_EFFECT_TYPE_SPECIAL_APPEAL, .appeal = 20, .jam = 0, + .function = ContestEffect_BetterIfDiffType, }, [CONTEST_EFFECT_AFFECTED_BY_PREV_APPEAL] = { + #if C_UPDATED_MOVE_EFFECTS >= GEN_6 + .description = COMPOUND_STRING("演出水平受前一位宝可梦\n表演吸引程度的影响。"), + #else + .description = COMPOUND_STRING("演出水平受前一位宝可梦\n表演吸引程度的影响。"), + #endif .effectType = CONTEST_EFFECT_TYPE_SPECIAL_APPEAL, .appeal = 30, .jam = 0, + .function = ContestEffect_AffectedByPrevAppeal, }, [CONTEST_EFFECT_IMPROVE_CONDITION_PREVENT_NERVOUSNESS] = { + .description = COMPOUND_STRING("提升表演的气势,\n变得不容易感到紧张。"), .effectType = CONTEST_EFFECT_TYPE_SPECIAL_APPEAL, .appeal = 10, .jam = 0, + .function = ContestEffect_ImproveConditionPreventNervousness, }, [CONTEST_EFFECT_BETTER_WITH_GOOD_CONDITION] = { + .description = COMPOUND_STRING("气势良好时表演\n会非常吸引人。"), .effectType = CONTEST_EFFECT_TYPE_SPECIAL_APPEAL, .appeal = 10, .jam = 0, + .function = ContestEffect_BetterWithGoodCondition, }, [CONTEST_EFFECT_NEXT_APPEAL_EARLIER] = { + #if C_UPDATED_MOVE_EFFECTS >= GEN_6 + .description = COMPOUND_STRING("下一次表演时最先出场。"), + #else + .description = COMPOUND_STRING("下一次表演时最先出场。"), + #endif .effectType = CONTEST_EFFECT_TYPE_TURN_ORDER, .appeal = 30, .jam = 0, + .function = ContestEffect_NextAppealEarlier, }, [CONTEST_EFFECT_NEXT_APPEAL_LATER] = { + #if C_UPDATED_MOVE_EFFECTS >= GEN_6 + .description = COMPOUND_STRING("下一次表演时最后出场。"), + #else + .description = COMPOUND_STRING("下一次表演时最后出场。"), + #endif .effectType = CONTEST_EFFECT_TYPE_TURN_ORDER, .appeal = 30, .jam = 0, + .function = ContestEffect_NextAppealLater, }, [CONTEST_EFFECT_MAKE_SCRAMBLING_TURN_ORDER_EASIER] = { + .description = COMPOUND_STRING("使下一次表演的顺序\n容易被打乱。"), .effectType = CONTEST_EFFECT_TYPE_TURN_ORDER, .appeal = 30, .jam = 0, + .function = ContestEffect_MakeScramblingTurnOrderEasier, }, [CONTEST_EFFECT_SCRAMBLE_NEXT_TURN_ORDER] = { + .description = COMPOUND_STRING("打乱下一次表演的顺序。"), .effectType = CONTEST_EFFECT_TYPE_TURN_ORDER, .appeal = 30, .jam = 0, + .function = ContestEffect_ScrambleNextTurnOrder, }, [CONTEST_EFFECT_EXCITE_AUDIENCE_IN_ANY_CONTEST] = { + .description = COMPOUND_STRING("任何类别的华丽大赛中\n都会让会场兴奋的表演。"), .effectType = CONTEST_EFFECT_TYPE_SPECIAL_APPEAL, - .appeal = 10, + .appeal = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? 20 : 10, .jam = 0, + .function = ContestEffect_ExciteAudienceInAnyContest, }, [CONTEST_EFFECT_BADLY_STARTLE_MONS_WITH_GOOD_APPEALS] = { + .description = COMPOUND_STRING("严重干扰表演具有吸引力的\n所有宝可梦。"), .effectType = CONTEST_EFFECT_TYPE_STARTLE_MONS, .appeal = 20, .jam = 10, + .function = ContestEffect_BadlyStartleMonsWithGoodAppeals, }, [CONTEST_EFFECT_BETTER_WHEN_AUDIENCE_EXCITED] = { + .description = COMPOUND_STRING("会场越兴奋,\n表演越吸引人。"), .effectType = CONTEST_EFFECT_TYPE_SPECIAL_APPEAL, .appeal = 10, .jam = 0, + .function = ContestEffect_BetterWhenAudienceExcited, }, [CONTEST_EFFECT_DONT_EXCITE_AUDIENCE] = { + .description = COMPOUND_STRING("表演后会场暂时不会\n变得更加兴奋。"), .effectType = CONTEST_EFFECT_TYPE_WORSEN, .appeal = 30, .jam = 0, + .function = ContestEffect_DontExciteAudience, }, }; - -void (*const gContestEffectFuncs[])(void) = -{ - ContestEffect_HighlyAppealing, - ContestEffect_UserMoreEasilyStartled, - ContestEffect_GreatAppealButNoMoreMoves, - ContestEffect_RepetitionNotBoring, - ContestEffect_AvoidStartleOnce, - ContestEffect_AvoidStartle, - ContestEffect_AvoidStartleSlightly, - ContestEffect_UserLessEasilyStartled, - ContestEffect_StartleFrontMon, - ContestEffect_StartlePrevMons, - ContestEffect_StartleFrontMon, - ContestEffect_StartlePrevMons, - ContestEffect_StartleFrontMon, - ContestEffect_StartlePrevMons, - ContestEffect_StartlePrevMon2, - ContestEffect_StartlePrevMons2, - ContestEffect_ShiftJudgeAttention, - ContestEffect_StartleMonWithJudgesAttention, - ContestEffect_JamsOthersButMissOneTurn, - ContestEffect_StartleMonsSameTypeAppeal, - ContestEffect_StartleMonsCoolAppeal, - ContestEffect_StartleMonsBeautyAppeal, - ContestEffect_StartleMonsCuteAppeal, - ContestEffect_StartleMonsSmartAppeal, - ContestEffect_StartleMonsToughAppeal, - ContestEffect_MakeFollowingMonNervous, - ContestEffect_MakeFollowingMonsNervous, - ContestEffect_WorsenConditionOfPrevMons, - ContestEffect_BadlyStartlesMonsInGoodCondition, - ContestEffect_BetterIfFirst, - ContestEffect_BetterIfLast, - ContestEffect_AppealAsGoodAsPrevOnes, - ContestEffect_AppealAsGoodAsPrevOne, - ContestEffect_BetterWhenLater, - ContestEffect_QualityDependsOnTiming, - ContestEffect_BetterIfSameType, - ContestEffect_BetterIfDiffType, - ContestEffect_AffectedByPrevAppeal, - ContestEffect_ImproveConditionPreventNervousness, - ContestEffect_BetterWithGoodCondition, - ContestEffect_NextAppealEarlier, - ContestEffect_NextAppealLater, - ContestEffect_MakeScramblingTurnOrderEasier, - ContestEffect_ScrambleNextTurnOrder, - ContestEffect_ExciteAudienceInAnyContest, - ContestEffect_BadlyStartleMonsWithGoodAppeals, - ContestEffect_BetterWhenAudienceExcited, - ContestEffect_DontExciteAudience, -}; diff --git a/src/data/contest_text_tables.h b/src/data/contest_text_tables.h index 3560b2af04..3724a615c9 100644 --- a/src/data/contest_text_tables.h +++ b/src/data/contest_text_tables.h @@ -1,151 +1,73 @@ #include "global.h" // sAppealResultTexts -extern const u8 gText_BecameMoreConsciousOfOtherMons[]; -extern const u8 gText_MonCantMakeAnAppealAfterThis[]; -extern const u8 gText_SettledDownJustLittleBit[]; -extern const u8 gText_BecameObliviousToOtherMons[]; -extern const u8 gText_BecameLessAwareOfOtherMons[]; -extern const u8 gText_StoppedCaringAboutOtherMons[]; -extern const u8 gText_TriedToStartleOtherMons[]; -extern const u8 gText_TriedToDazzleOthers[]; -extern const u8 gText_JudgeLookedAwayFromMon[]; -extern const u8 gText_TriedToUnnerveNextMon[]; -extern const u8 gText_MonBecameNervous[]; -extern const u8 gText_AppealTriedToUnnerveWaitingMons[]; -extern const u8 gText_TauntedMonsDoingWell[]; -extern const u8 gText_MonRegainedItsForm[]; -extern const u8 gText_TriedToJamMonDoingWell[]; -extern const u8 gText_StandoutMonHustledEvenMore[]; -extern const u8 gText_LargelyUnnoticedMonWorkedHard[]; -extern const u8 gText_WorkedAsMuchAsMonBefore[]; -extern const u8 gText_WorkedAsMuchAsPrecedingMon[]; -extern const u8 gText_MonsAppealWasDud[]; -extern const u8 gText_MonsAppealDidNotGoWell[]; -extern const u8 gText_MonsAppealDidNotGoWell2[]; -extern const u8 gText_MonsAppealDidNotGoWell3[]; -extern const u8 gText_MonsAppealDidNotWorkVeryWell[]; -extern const u8 gText_MonsAppealWentSlightlyWell[]; -extern const u8 gText_MonsAppealWentSlightlyWell2[]; -extern const u8 gText_MonsAppealWentPrettyWell[]; -extern const u8 gText_MonsAppealWentPrettyWell2[]; -extern const u8 gText_MonsAppealWentVeryWell[]; -extern const u8 gText_MonsAppealWentExcellently[]; -extern const u8 gText_MonsAppealWentExcellently2[]; -extern const u8 gText_SameTypeAsOneBeforeGood[]; -extern const u8 gText_NotSameTypeAsOneBeforeGood[]; -extern const u8 gText_StoodOutMuchMoreThanMonBefore[]; -extern const u8 gText_DidntDoAsWellAsMonBefore[]; -extern const u8 gText_MonsConditionRoseAboveUsual[]; -extern const u8 gText_MonsHotStatusMadeGreatAppeal[]; -extern const u8 gText_MovedUpInLineForNextAppeal[]; -extern const u8 gText_MovedBackInLineForNextAppeal[]; -extern const u8 gText_ScrambledUpOrderForNextTurn[]; extern const u8 gText_JudgeLookedAtMonExpectantly[]; extern const u8 gText_AppealComboWentOverWell[]; extern const u8 gText_AppealComboWentOverVeryWell[]; extern const u8 gText_AppealComboWentOverExcellently[]; -extern const u8 gText_MonManagedToAvertGaze[]; -extern const u8 gText_MonManagedToAvoidSeeingIt[]; -extern const u8 gText_MonIsntFazedByThatSortOfThing[]; -extern const u8 gText_MonBecameALittleDistracted[]; -extern const u8 gText_TriedToStartleOtherPokemon[]; -extern const u8 gText_MonLookedDownOutOfDistraction[]; -extern const u8 gText_MonTurnedBackOutOfDistraction[]; -extern const u8 gText_MonCouldntHelpUtteringCry[]; -extern const u8 gText_MonCouldntHelpLeapingUp[]; -extern const u8 gText_MonTrippedOutOfDistraction[]; -extern const u8 gText_ButItMessedUp2[]; -extern const u8 gText_ButItFailedToMakeTargetNervous[]; -extern const u8 gText_ButItFailedToMakeAnyoneNervous[]; -extern const u8 gText_ButItWasIgnored[]; -extern const u8 gText_CouldntImproveItsCondition[]; -extern const u8 gText_BadConditionResultedInWeakAppeal[]; -extern const u8 gText_MonWasUnaffected[]; -extern const u8 gText_AttractedCrowdsAttention[]; - -// Misc, used directly -extern const u8 gText_MonAppealedWithMove[]; -extern const u8 gText_MonCantAppealNextTurn[]; -extern const u8 gText_RepeatedAppeal[]; -extern const u8 gText_MonsXDidntGoOverWell[]; -extern const u8 gText_MonsXWentOverGreat[]; -extern const u8 gText_MonsXGotTheCrowdGoing[]; -extern const u8 gText_CrowdContinuesToWatchMon[]; -extern const u8 gText_MonsMoveIsIgnored[]; -extern const u8 gText_MonWasTooNervousToMove[]; -extern const u8 gText_MonWasWatchingOthers[]; -extern const u8 gText_AllOutOfAppealTime[]; -extern const u8 gText_Contest_Shyness[]; -extern const u8 gText_Contest_Anxiety[]; -extern const u8 gText_Contest_Laziness[]; -extern const u8 gText_Contest_Hesitancy[]; -extern const u8 gText_Contest_Fear[]; -extern const u8 gText_AppealNumWhichMoveWillBePlayed[]; -extern const u8 gText_AppealNumButItCantParticipate[]; static const u8 *const sAppealResultTexts[] = { - [CONTEST_STRING_MORE_CONSCIOUS] = gText_BecameMoreConsciousOfOtherMons, - [CONTEST_STRING_NO_APPEAL] = gText_MonCantMakeAnAppealAfterThis, - [CONTEST_STRING_SETTLE_DOWN] = gText_SettledDownJustLittleBit, - [CONTEST_STRING_OBLIVIOUS_TO_OTHERS] = gText_BecameObliviousToOtherMons, - [CONTEST_STRING_LESS_AWARE] = gText_BecameLessAwareOfOtherMons, - [CONTEST_STRING_STOPPED_CARING] = gText_StoppedCaringAboutOtherMons, - [CONTEST_STRING_STARTLE_ATTEMPT] = gText_TriedToStartleOtherMons, - [CONTEST_STRING_DAZZLE_ATTEMPT] = gText_TriedToDazzleOthers, - [CONTEST_STRING_JUDGE_LOOK_AWAY2] = gText_JudgeLookedAwayFromMon, - [CONTEST_STRING_UNNERVE_ATTEMPT] = gText_TriedToUnnerveNextMon, - [CONTEST_STRING_NERVOUS] = gText_MonBecameNervous, - [CONTEST_STRING_UNNERVE_WAITING] = gText_AppealTriedToUnnerveWaitingMons, - [CONTEST_STRING_TAUNT_WELL] = gText_TauntedMonsDoingWell, - [CONTEST_STRING_REGAINED_FORM] = gText_MonRegainedItsForm, - [CONTEST_STRING_JAM_WELL] = gText_TriedToJamMonDoingWell, - [CONTEST_STRING_HUSTLE_STANDOUT] = gText_StandoutMonHustledEvenMore, - [CONTEST_STRING_WORK_HARD_UNNOTICED] = gText_LargelyUnnoticedMonWorkedHard, - [CONTEST_STRING_WORK_BEFORE] = gText_WorkedAsMuchAsMonBefore, - [CONTEST_STRING_APPEAL_NOT_WELL] = gText_MonsAppealDidNotGoWell, - [CONTEST_STRING_WORK_PRECEDING] = gText_WorkedAsMuchAsPrecedingMon, - [CONTEST_STRING_APPEAL_NOT_WELL2] = gText_MonsAppealDidNotGoWell2, - [CONTEST_STRING_APPEAL_NOT_SHOWN_WELL] = gText_MonsAppealDidNotGoWell3, - [CONTEST_STRING_APPEAL_SLIGHTLY_WELL] = gText_MonsAppealWentSlightlyWell, - [CONTEST_STRING_APPEAL_PRETTY_WELL] = gText_MonsAppealWentPrettyWell, - [CONTEST_STRING_APPEAL_EXCELLENTLY] = gText_MonsAppealWentExcellently, - [CONTEST_STRING_APPEAL_DUD] = gText_MonsAppealWasDud, - [CONTEST_STRING_APPEAL_NOT_VERY_WELL] = gText_MonsAppealDidNotWorkVeryWell, - [CONTEST_STRING_APPEAL_SLIGHTLY_WELL2] = gText_MonsAppealWentSlightlyWell2, - [CONTEST_STRING_APPEAL_PRETTY_WELL2] = gText_MonsAppealWentPrettyWell2, - [CONTEST_STRING_APPEAL_VERY_WELL] = gText_MonsAppealWentVeryWell, - [CONTEST_STRING_APPEAL_EXCELLENTLY2] = gText_MonsAppealWentExcellently2, - [CONTEST_STRING_SAME_TYPE_GOOD] = gText_SameTypeAsOneBeforeGood, - [CONTEST_STRING_DIFF_TYPE_GOOD] = gText_NotSameTypeAsOneBeforeGood, - [CONTEST_STRING_STOOD_OUT_AS_MUCH] = gText_StoodOutMuchMoreThanMonBefore, - [CONTEST_STRING_NOT_AS_WELL] = gText_DidntDoAsWellAsMonBefore, - [CONTEST_STRING_CONDITION_ROSE] = gText_MonsConditionRoseAboveUsual, - [CONTEST_STRING_HOT_STATUS] = gText_MonsHotStatusMadeGreatAppeal, - [CONTEST_STRING_MOVE_UP_LINE] = gText_MovedUpInLineForNextAppeal, - [CONTEST_STRING_MOVE_BACK_LINE] = gText_MovedBackInLineForNextAppeal, - [CONTEST_STRING_SCRAMBLE_ORDER] = gText_ScrambledUpOrderForNextTurn, + [CONTEST_STRING_MORE_CONSCIOUS] = COMPOUND_STRING("它变得比平时\n更加担心其他宝可梦了!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}"), + [CONTEST_STRING_NO_APPEAL] = COMPOUND_STRING("{STR_VAR_1}此后\n都无法再次进行表演了!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}"), + [CONTEST_STRING_SETTLE_DOWN] = COMPOUND_STRING("它稍微有些\n冷静下来了!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}"), + [CONTEST_STRING_OBLIVIOUS_TO_OTHERS] = COMPOUND_STRING("它变得完全\n不关注其他宝可梦了!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}"), + [CONTEST_STRING_LESS_AWARE] = COMPOUND_STRING("它变得不那么\n关注其他宝可梦了。{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}"), + [CONTEST_STRING_STOPPED_CARING] = COMPOUND_STRING("它不再那么\n留意其他宝可梦了!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}"), + [CONTEST_STRING_STARTLE_ATTEMPT] = COMPOUND_STRING("它试图惊吓\n其他宝可梦!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}"), + [CONTEST_STRING_DAZZLE_ATTEMPT] = COMPOUND_STRING("它试图让\n其他宝可梦眼花缭乱!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}"), + [CONTEST_STRING_JUDGE_LOOK_AWAY2] = COMPOUND_STRING("评委的目光\n从{STR_VAR_1}身上移开了!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}"), + [CONTEST_STRING_UNNERVE_ATTEMPT] = COMPOUND_STRING("它试图让下一只\n表演的宝可梦紧张!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}"), + [CONTEST_STRING_NERVOUS] = COMPOUND_STRING("{STR_VAR_1}\n紧张了起来!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}"), + [CONTEST_STRING_UNNERVE_WAITING] = COMPOUND_STRING("它试图让所有\n之后表演的宝可梦紧张!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}"), + [CONTEST_STRING_TAUNT_WELL] = COMPOUND_STRING("它嘲笑了\n气势良好的宝可梦!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}"), + [CONTEST_STRING_REGAINED_FORM] = COMPOUND_STRING("{STR_VAR_1}的气势\n回到了本来的样子!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}"), + [CONTEST_STRING_JAM_WELL] = COMPOUND_STRING("它试图干扰那些\n表演引人注目的宝可梦!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}"), + [CONTEST_STRING_HUSTLE_STANDOUT] = COMPOUND_STRING("本来就引人注目的\n{STR_VAR_1}更加鼓足干劲了!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}"), + [CONTEST_STRING_WORK_HARD_UNNOTICED] = COMPOUND_STRING("原本不太引人注目的\n{STR_VAR_1}加油努力了起来!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}"), + [CONTEST_STRING_WORK_BEFORE] = COMPOUND_STRING("它鼓足了不会输给\n前面所有宝可梦程度的干劲!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}"), + [CONTEST_STRING_APPEAL_NOT_WELL] = COMPOUND_STRING("{STR_VAR_1}的表演\n没能成功奏效!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}"), + [CONTEST_STRING_WORK_PRECEDING] = COMPOUND_STRING("和前面的宝可梦\n一样地鼓足了干劲!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}"), + [CONTEST_STRING_APPEAL_NOT_WELL2] = COMPOUND_STRING("{STR_VAR_1}的表演\n没能成功奏效!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}"), + [CONTEST_STRING_APPEAL_NOT_SHOWN_WELL] = COMPOUND_STRING("{STR_VAR_1}的表演\n没能成功奏效!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}"), + [CONTEST_STRING_APPEAL_SLIGHTLY_WELL] = COMPOUND_STRING("{STR_VAR_1}的表演\n做得还算可以!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}"), + [CONTEST_STRING_APPEAL_PRETTY_WELL] = COMPOUND_STRING("{STR_VAR_1}的表演\n做得不错!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}"), + [CONTEST_STRING_APPEAL_EXCELLENTLY] = COMPOUND_STRING("{STR_VAR_1}的表演\n做得非常出色!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}"), + [CONTEST_STRING_APPEAL_DUD] = COMPOUND_STRING("{STR_VAR_1}的表演\n完全失败了!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}"), + [CONTEST_STRING_APPEAL_NOT_VERY_WELL] = COMPOUND_STRING("{STR_VAR_1}的表演\n做得不怎么好!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}"), + [CONTEST_STRING_APPEAL_SLIGHTLY_WELL2] = COMPOUND_STRING("{STR_VAR_1}的表演\n做得还算可以!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}"), + [CONTEST_STRING_APPEAL_PRETTY_WELL2] = COMPOUND_STRING("{STR_VAR_1}的表演\n做得不错!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}"), + [CONTEST_STRING_APPEAL_VERY_WELL] = COMPOUND_STRING("{STR_VAR_1}的表演\n做得很好!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}"), + [CONTEST_STRING_APPEAL_EXCELLENTLY2] = COMPOUND_STRING("{STR_VAR_1}的表演\n做得非常出色!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}"), + [CONTEST_STRING_SAME_TYPE_GOOD] = COMPOUND_STRING("因为和前面的宝可梦\n类别一致而受到喜欢!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}"), + [CONTEST_STRING_DIFF_TYPE_GOOD] = COMPOUND_STRING("因为和前面的宝可梦\n类别不同而受到喜欢!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}"), + [CONTEST_STRING_STOOD_OUT_AS_MUCH] = COMPOUND_STRING("比起前面的宝可梦\n要出彩得多!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}"), + [CONTEST_STRING_NOT_AS_WELL] = COMPOUND_STRING("比起前面的宝可梦\n完成得不算太好!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}"), + [CONTEST_STRING_CONDITION_ROSE] = COMPOUND_STRING("{STR_VAR_1}的气势\n比平时有所提升!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}"), + [CONTEST_STRING_HOT_STATUS] = COMPOUND_STRING("{STR_VAR_1}气势不错,\n表演变得棒极了!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}"), + [CONTEST_STRING_MOVE_UP_LINE] = COMPOUND_STRING("它想要在下回合的表演里\n更早出场而走到了前面!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}"), + [CONTEST_STRING_MOVE_BACK_LINE] = COMPOUND_STRING("它想要在下回合的表演里\n更晚出场而后退了一步!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}"), + [CONTEST_STRING_SCRAMBLE_ORDER] = COMPOUND_STRING("下个回合的表演顺序\n变得奇怪了起来!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}"), [CONTEST_STRING_JUDGE_EXPECTANTLY2] = gText_JudgeLookedAtMonExpectantly, [CONTEST_STRING_WENT_OVER_WELL] = gText_AppealComboWentOverWell, [CONTEST_STRING_WENT_OVER_VERY_WELL] = gText_AppealComboWentOverVeryWell, [CONTEST_STRING_APPEAL_COMBO_EXCELLENTLY] = gText_AppealComboWentOverExcellently, - [CONTEST_STRING_AVERT_GAZE] = gText_MonManagedToAvertGaze, - [CONTEST_STRING_AVOID_SEEING] = gText_MonManagedToAvoidSeeingIt, - [CONTEST_STRING_NOT_FAZED] = gText_MonIsntFazedByThatSortOfThing, - [CONTEST_STRING_LITTLE_DISTRACTED] = gText_MonBecameALittleDistracted, - [CONTEST_STRING_ATTEMPT_STARTLE] = gText_TriedToStartleOtherPokemon, - [CONTEST_STRING_LOOKED_DOWN] = gText_MonLookedDownOutOfDistraction, - [CONTEST_STRING_TURNED_BACK] = gText_MonTurnedBackOutOfDistraction, - [CONTEST_STRING_UTTER_CRY] = gText_MonCouldntHelpUtteringCry, - [CONTEST_STRING_LEAPT_UP] = gText_MonCouldntHelpLeapingUp, - [CONTEST_STRING_TRIPPED_OVER] = gText_MonTrippedOutOfDistraction, - [CONTEST_STRING_MESSED_UP2] = gText_ButItMessedUp2, - [CONTEST_STRING_FAILED_TARGET_NERVOUS] = gText_ButItFailedToMakeTargetNervous, - [CONTEST_STRING_FAILED_ANYONE_NERVOUS] = gText_ButItFailedToMakeAnyoneNervous, - [CONTEST_STRING_IGNORED] = gText_ButItWasIgnored, - [CONTEST_STRING_NO_CONDITION_IMPROVE] = gText_CouldntImproveItsCondition, - [CONTEST_STRING_BAD_CONDITION_WEAK_APPEAL] = gText_BadConditionResultedInWeakAppeal, - [CONTEST_STRING_UNAFFECTED] = gText_MonWasUnaffected, - [CONTEST_STRING_ATTRACTED_ATTENTION] = gText_AttractedCrowdsAttention + [CONTEST_STRING_AVERT_GAZE] = COMPOUND_STRING("{STR_VAR_1}成功地\n移开了视线!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}"), + [CONTEST_STRING_AVOID_SEEING] = COMPOUND_STRING("{STR_VAR_1}成功地\n避开了视线!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}"), + [CONTEST_STRING_NOT_FAZED] = COMPOUND_STRING("{STR_VAR_1}没有受\n这种程度的事情影响!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}"), + [CONTEST_STRING_LITTLE_DISTRACTED] = COMPOUND_STRING("{STR_VAR_1}变得\n稍稍有点分心了!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}"), + [CONTEST_STRING_ATTEMPT_STARTLE] = COMPOUND_STRING("它试图惊吓\n其他宝可梦!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}"), + [CONTEST_STRING_LOOKED_DOWN] = COMPOUND_STRING("{STR_VAR_1}因为分心\n低下了头!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}"), + [CONTEST_STRING_TURNED_BACK] = COMPOUND_STRING("{STR_VAR_1}因为分心\n转过了身!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}"), + [CONTEST_STRING_UTTER_CRY] = COMPOUND_STRING("{STR_VAR_1}忍不住地\n叫出了声!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}"), + [CONTEST_STRING_LEAPT_UP] = COMPOUND_STRING("{STR_VAR_1}忍不住地\n跳了起来!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}"), + [CONTEST_STRING_TRIPPED_OVER] = COMPOUND_STRING("{STR_VAR_1}因为分心\n摔在了地上四脚朝天!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}"), + [CONTEST_STRING_MESSED_UP2] = COMPOUND_STRING("但它搞砸了!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}"), + [CONTEST_STRING_FAILED_TARGET_NERVOUS] = COMPOUND_STRING("但是它没能让\n目标宝可梦紧张!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}"), + [CONTEST_STRING_FAILED_ANYONE_NERVOUS] = COMPOUND_STRING("但是它没能让\n任何宝可梦紧张!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}"), + [CONTEST_STRING_IGNORED] = COMPOUND_STRING("但它被无视了……{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}"), + [CONTEST_STRING_NO_CONDITION_IMPROVE] = COMPOUND_STRING("但是它并没能\n提升自己的气势……{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}"), + [CONTEST_STRING_BAD_CONDITION_WEAK_APPEAL] = COMPOUND_STRING("它因为气势不行\n表演得一点也不好……{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}"), + [CONTEST_STRING_UNAFFECTED] = COMPOUND_STRING("{STR_VAR_1}\n完全不为所动!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}"), + [CONTEST_STRING_ATTRACTED_ATTENTION] = COMPOUND_STRING("吸引了\n观众们的注意!{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}") }; diff --git a/src/data/field_effects/field_effect_object_template_pointers.h b/src/data/field_effects/field_effect_object_template_pointers.h index 281c664f03..369b5821a9 100755 --- a/src/data/field_effects/field_effect_object_template_pointers.h +++ b/src/data/field_effects/field_effect_object_template_pointers.h @@ -42,6 +42,8 @@ extern const struct SpriteTemplate gFieldEffectObjectTemplate_SpotTracks; extern const struct SpriteTemplate gFieldEffectObjectTemplate_CaveDust; extern const struct SpriteTemplate gFieldEffectObjectTemplate_RockClimbBlob; extern const struct SpriteTemplate gFieldEffectObjectTemplate_RockClimbDust; +extern const struct SpriteTemplate gFieldEffectObjectTemplate_ORASDowsingBrendan; +extern const struct SpriteTemplate gFieldEffectObjectTemplate_ORASDowsingMay; const struct SpriteTemplate *const gFieldEffectObjectTemplatePointers[] = { [FLDEFFOBJ_SHADOW_S] = &gFieldEffectObjectTemplate_ShadowSmall, @@ -87,4 +89,6 @@ const struct SpriteTemplate *const gFieldEffectObjectTemplatePointers[] = { [FLDEFFOBJ_CAVE_DUST] = &gFieldEffectObjectTemplate_CaveDust, [FLDEFFOBJ_ROCK_CLIMB_BLOB] = &gFieldEffectObjectTemplate_RockClimbBlob, [FLDEFFOBJ_ROCK_CLIMB_DUST] = &gFieldEffectObjectTemplate_RockClimbDust, + [FLDEFFOBJ_ORAS_DOWSE_BRENDAN] = &gFieldEffectObjectTemplate_ORASDowsingBrendan, + [FLDEFFOBJ_ORAS_DOWSE_MAY] = &gFieldEffectObjectTemplate_ORASDowsingMay, }; diff --git a/src/data/graphics/pokemon.h b/src/data/graphics/pokemon.h index 1b70cf3aa4..5ac450114f 100644 --- a/src/data/graphics/pokemon.h +++ b/src/data/graphics/pokemon.h @@ -12050,11 +12050,22 @@ const u32 gObjectEventPic_Substitute[] = INCBIN_COMP("graphics/pokemon/question_ #endif //P_FAMILY_SPOINK #if P_FAMILY_SPINDA +#if !P_GBA_STYLE_SPECIES_GFX const u32 gMonFrontPic_Spinda[] = INCBIN_U32("graphics/pokemon/spinda/anim_front.4bpp.smol"); const u16 gMonPalette_Spinda[] = INCBIN_U16("graphics/pokemon/spinda/normal.gbapal"); const u32 gMonBackPic_Spinda[] = INCBIN_U32("graphics/pokemon/spinda/back.4bpp.smol"); const u16 gMonShinyPalette_Spinda[] = INCBIN_U16("graphics/pokemon/spinda/shiny.gbapal"); +#else + const u32 gMonFrontPic_Spinda[] = INCBIN_U32("graphics/pokemon/spinda/anim_front_gba.4bpp.smol"); + const u16 gMonPalette_Spinda[] = INCBIN_U16("graphics/pokemon/spinda/normal_gba.gbapal"); + const u32 gMonBackPic_Spinda[] = INCBIN_U32("graphics/pokemon/spinda/back_gba.4bpp.smol"); + const u16 gMonShinyPalette_Spinda[] = INCBIN_U16("graphics/pokemon/spinda/shiny_gba.gbapal"); +#endif //P_GBA_STYLE_SPECIES_GFX +#if !P_GBA_STYLE_SPECIES_ICONS const u8 gMonIcon_Spinda[] = INCBIN_U8("graphics/pokemon/spinda/icon.4bpp"); +#else + const u8 gMonIcon_Spinda[] = INCBIN_U8("graphics/pokemon/spinda/icon_gba.4bpp"); +#endif //P_GBA_STYLE_SPECIES_ICONS #if P_FOOTPRINTS const u8 gMonFootprint_Spinda[] = INCBIN_U8("graphics/pokemon/spinda/footprint.1bpp"); #endif //P_FOOTPRINTS @@ -12745,31 +12756,58 @@ const u32 gObjectEventPic_Substitute[] = INCBIN_COMP("graphics/pokemon/question_ #endif //P_FAMILY_FEEBAS #if P_FAMILY_CASTFORM +#if !P_GBA_STYLE_SPECIES_GFX const u32 gMonFrontPic_CastformNormal[] = INCBIN_U32("graphics/pokemon/castform/anim_front.4bpp.smol"); const u16 gMonPalette_CastformNormal[] = INCBIN_U16("graphics/pokemon/castform/normal.gbapal"); const u32 gMonBackPic_CastformNormal[] = INCBIN_U32("graphics/pokemon/castform/back.4bpp.smol"); const u16 gMonShinyPalette_CastformNormal[] = INCBIN_U16("graphics/pokemon/castform/shiny.gbapal"); - const u8 gMonIcon_CastformNormal[] = INCBIN_U8("graphics/pokemon/castform/icon.4bpp"); -#if P_FOOTPRINTS - const u8 gMonFootprint_Castform[] = INCBIN_U8("graphics/pokemon/castform/footprint.1bpp"); -#endif //P_FOOTPRINTS const u32 gMonFrontPic_CastformSunny[] = INCBIN_U32("graphics/pokemon/castform/sunny/anim_front.4bpp.smol"); const u16 gMonPalette_CastformSunny[] = INCBIN_U16("graphics/pokemon/castform/sunny/normal.gbapal"); const u32 gMonBackPic_CastformSunny[] = INCBIN_U32("graphics/pokemon/castform/sunny/back.4bpp.smol"); const u16 gMonShinyPalette_CastformSunny[] = INCBIN_U16("graphics/pokemon/castform/sunny/shiny.gbapal"); - const u8 gMonIcon_CastformSunny[] = INCBIN_U8("graphics/pokemon/castform/sunny/icon.4bpp"); const u32 gMonFrontPic_CastformRainy[] = INCBIN_U32("graphics/pokemon/castform/rainy/anim_front.4bpp.smol"); const u16 gMonPalette_CastformRainy[] = INCBIN_U16("graphics/pokemon/castform/rainy/normal.gbapal"); const u32 gMonBackPic_CastformRainy[] = INCBIN_U32("graphics/pokemon/castform/rainy/back.4bpp.smol"); const u16 gMonShinyPalette_CastformRainy[] = INCBIN_U16("graphics/pokemon/castform/rainy/shiny.gbapal"); - const u8 gMonIcon_CastformRainy[] = INCBIN_U8("graphics/pokemon/castform/rainy/icon.4bpp"); const u32 gMonFrontPic_CastformSnowy[] = INCBIN_U32("graphics/pokemon/castform/snowy/anim_front.4bpp.smol"); const u16 gMonPalette_CastformSnowy[] = INCBIN_U16("graphics/pokemon/castform/snowy/normal.gbapal"); const u32 gMonBackPic_CastformSnowy[] = INCBIN_U32("graphics/pokemon/castform/snowy/back.4bpp.smol"); const u16 gMonShinyPalette_CastformSnowy[] = INCBIN_U16("graphics/pokemon/castform/snowy/shiny.gbapal"); +#else + const u32 gMonFrontPic_CastformNormal[] = INCBIN_U32("graphics/pokemon/castform/front_gba.4bpp.smol"); + const u16 gMonPalette_CastformNormal[] = INCBIN_U16("graphics/pokemon/castform/normal_gba.gbapal"); + const u32 gMonBackPic_CastformNormal[] = INCBIN_U32("graphics/pokemon/castform/back_gba.4bpp.smol"); + const u16 gMonShinyPalette_CastformNormal[] = INCBIN_U16("graphics/pokemon/castform/shiny_gba.gbapal"); + + const u32 gMonFrontPic_CastformSunny[] = INCBIN_U32("graphics/pokemon/castform/sunny/front_gba.4bpp.smol"); + const u16 gMonPalette_CastformSunny[] = INCBIN_U16("graphics/pokemon/castform/sunny/normal_gba.gbapal"); + const u32 gMonBackPic_CastformSunny[] = INCBIN_U32("graphics/pokemon/castform/sunny/back_gba.4bpp.smol"); + const u16 gMonShinyPalette_CastformSunny[] = INCBIN_U16("graphics/pokemon/castform/sunny/shiny_gba.gbapal"); + + const u32 gMonFrontPic_CastformRainy[] = INCBIN_U32("graphics/pokemon/castform/rainy/front_gba.4bpp.smol"); + const u16 gMonPalette_CastformRainy[] = INCBIN_U16("graphics/pokemon/castform/rainy/normal_gba.gbapal"); + const u32 gMonBackPic_CastformRainy[] = INCBIN_U32("graphics/pokemon/castform/rainy/back_gba.4bpp.smol"); + const u16 gMonShinyPalette_CastformRainy[] = INCBIN_U16("graphics/pokemon/castform/rainy/shiny_gba.gbapal"); + + const u32 gMonFrontPic_CastformSnowy[] = INCBIN_U32("graphics/pokemon/castform/snowy/front_gba.4bpp.smol"); + const u16 gMonPalette_CastformSnowy[] = INCBIN_U16("graphics/pokemon/castform/snowy/normal_gba.gbapal"); + const u32 gMonBackPic_CastformSnowy[] = INCBIN_U32("graphics/pokemon/castform/snowy/back_gba.4bpp.smol"); + const u16 gMonShinyPalette_CastformSnowy[] = INCBIN_U16("graphics/pokemon/castform/snowy/shiny_gba.gbapal"); +#endif //P_GBA_STYLE_SPECIES_GFX +#if !P_GBA_STYLE_SPECIES_ICONS + const u8 gMonIcon_CastformNormal[] = INCBIN_U8("graphics/pokemon/castform/icon.4bpp"); +#else + const u8 gMonIcon_CastformNormal[] = INCBIN_U8("graphics/pokemon/castform/icon_gba.4bpp"); +#endif //P_GBA_STYLE_SPECIES_ICONS +#if P_FOOTPRINTS + const u8 gMonFootprint_Castform[] = INCBIN_U8("graphics/pokemon/castform/footprint.1bpp"); +#endif //P_FOOTPRINTS + + const u8 gMonIcon_CastformSunny[] = INCBIN_U8("graphics/pokemon/castform/sunny/icon.4bpp"); + const u8 gMonIcon_CastformRainy[] = INCBIN_U8("graphics/pokemon/castform/rainy/icon.4bpp"); const u8 gMonIcon_CastformSnowy[] = INCBIN_U8("graphics/pokemon/castform/snowy/icon.4bpp"); #if OW_POKEMON_OBJECT_EVENTS @@ -13943,11 +13981,41 @@ const u32 gObjectEventPic_Substitute[] = INCBIN_COMP("graphics/pokemon/question_ const u16 gMonPalette_DeoxysNormal[] = INCBIN_U16("graphics/pokemon/deoxys/normal.gbapal"); const u32 gMonBackPic_DeoxysNormal[] = INCBIN_U32("graphics/pokemon/deoxys/back.4bpp.smol"); const u16 gMonShinyPalette_DeoxysNormal[] = INCBIN_U16("graphics/pokemon/deoxys/shiny.gbapal"); + + const u32 gMonFrontPic_DeoxysAttack[] = INCBIN_U32("graphics/pokemon/deoxys/attack/anim_front.4bpp.smol"); + const u16 gMonPalette_DeoxysAttack[] = INCBIN_U16("graphics/pokemon/deoxys/attack/normal.gbapal"); + const u32 gMonBackPic_DeoxysAttack[] = INCBIN_U32("graphics/pokemon/deoxys/attack/back.4bpp.smol"); + const u16 gMonShinyPalette_DeoxysAttack[] = INCBIN_U16("graphics/pokemon/deoxys/attack/shiny.gbapal"); + + const u32 gMonFrontPic_DeoxysDefense[] = INCBIN_U32("graphics/pokemon/deoxys/defense/anim_front.4bpp.smol"); + const u16 gMonPalette_DeoxysDefense[] = INCBIN_U16("graphics/pokemon/deoxys/defense/normal.gbapal"); + const u32 gMonBackPic_DeoxysDefense[] = INCBIN_U32("graphics/pokemon/deoxys/defense/back.4bpp.smol"); + const u16 gMonShinyPalette_DeoxysDefense[] = INCBIN_U16("graphics/pokemon/deoxys/defense/shiny.gbapal"); + + const u32 gMonFrontPic_DeoxysSpeed[] = INCBIN_U32("graphics/pokemon/deoxys/speed/anim_front.4bpp.smol"); + const u16 gMonPalette_DeoxysSpeed[] = INCBIN_U16("graphics/pokemon/deoxys/speed/normal.gbapal"); + const u32 gMonBackPic_DeoxysSpeed[] = INCBIN_U32("graphics/pokemon/deoxys/speed/back.4bpp.smol"); + const u16 gMonShinyPalette_DeoxysSpeed[] = INCBIN_U16("graphics/pokemon/deoxys/speed/shiny.gbapal"); #else const u32 gMonFrontPic_DeoxysNormal[] = INCBIN_U32("graphics/pokemon/deoxys/anim_front_gba.4bpp.smol"); const u16 gMonPalette_DeoxysNormal[] = INCBIN_U16("graphics/pokemon/deoxys/normal_gba.gbapal"); const u32 gMonBackPic_DeoxysNormal[] = INCBIN_U32("graphics/pokemon/deoxys/back_gba.4bpp.smol"); const u16 gMonShinyPalette_DeoxysNormal[] = INCBIN_U16("graphics/pokemon/deoxys/shiny_gba.gbapal"); + + const u32 gMonFrontPic_DeoxysAttack[] = INCBIN_U32("graphics/pokemon/deoxys/attack/front_gba.4bpp.smol"); + const u16 gMonPalette_DeoxysAttack[] = INCBIN_U16("graphics/pokemon/deoxys/attack/normal_gba.gbapal"); + const u32 gMonBackPic_DeoxysAttack[] = INCBIN_U32("graphics/pokemon/deoxys/attack/back_gba.4bpp.smol"); + const u16 gMonShinyPalette_DeoxysAttack[] = INCBIN_U16("graphics/pokemon/deoxys/attack/shiny_gba.gbapal"); + + const u32 gMonFrontPic_DeoxysDefense[] = INCBIN_U32("graphics/pokemon/deoxys/defense/front_gba.4bpp.smol"); + const u16 gMonPalette_DeoxysDefense[] = INCBIN_U16("graphics/pokemon/deoxys/defense/normal_gba.gbapal"); + const u32 gMonBackPic_DeoxysDefense[] = INCBIN_U32("graphics/pokemon/deoxys/defense/back_gba.4bpp.smol"); + const u16 gMonShinyPalette_DeoxysDefense[] = INCBIN_U16("graphics/pokemon/deoxys/defense/shiny_gba.gbapal"); + + const u32 gMonFrontPic_DeoxysSpeed[] = INCBIN_U32("graphics/pokemon/deoxys/speed/front_gba.4bpp.smol"); + const u16 gMonPalette_DeoxysSpeed[] = INCBIN_U16("graphics/pokemon/deoxys/speed/normal_gba.gbapal"); + const u32 gMonBackPic_DeoxysSpeed[] = INCBIN_U32("graphics/pokemon/deoxys/speed/back_gba.4bpp.smol"); + const u16 gMonShinyPalette_DeoxysSpeed[] = INCBIN_U16("graphics/pokemon/deoxys/speed/shiny_gba.gbapal"); #endif //P_GBA_STYLE_SPECIES_GFX #if !P_GBA_STYLE_SPECIES_ICONS const u8 gMonIcon_DeoxysNormal[] = INCBIN_U8("graphics/pokemon/deoxys/icon.4bpp"); @@ -13958,22 +14026,8 @@ const u32 gObjectEventPic_Substitute[] = INCBIN_COMP("graphics/pokemon/question_ const u8 gMonFootprint_Deoxys[] = INCBIN_U8("graphics/pokemon/deoxys/footprint.1bpp"); #endif //P_FOOTPRINTS - const u32 gMonFrontPic_DeoxysAttack[] = INCBIN_U32("graphics/pokemon/deoxys/attack/anim_front.4bpp.smol"); - const u16 gMonPalette_DeoxysAttack[] = INCBIN_U16("graphics/pokemon/deoxys/attack/normal.gbapal"); - const u32 gMonBackPic_DeoxysAttack[] = INCBIN_U32("graphics/pokemon/deoxys/attack/back.4bpp.smol"); - const u16 gMonShinyPalette_DeoxysAttack[] = INCBIN_U16("graphics/pokemon/deoxys/attack/shiny.gbapal"); const u8 gMonIcon_DeoxysAttack[] = INCBIN_U8("graphics/pokemon/deoxys/attack/icon.4bpp"); - - const u32 gMonFrontPic_DeoxysDefense[] = INCBIN_U32("graphics/pokemon/deoxys/defense/anim_front.4bpp.smol"); - const u16 gMonPalette_DeoxysDefense[] = INCBIN_U16("graphics/pokemon/deoxys/defense/normal.gbapal"); - const u32 gMonBackPic_DeoxysDefense[] = INCBIN_U32("graphics/pokemon/deoxys/defense/back.4bpp.smol"); - const u16 gMonShinyPalette_DeoxysDefense[] = INCBIN_U16("graphics/pokemon/deoxys/defense/shiny.gbapal"); const u8 gMonIcon_DeoxysDefense[] = INCBIN_U8("graphics/pokemon/deoxys/defense/icon.4bpp"); - - const u32 gMonFrontPic_DeoxysSpeed[] = INCBIN_U32("graphics/pokemon/deoxys/speed/anim_front.4bpp.smol"); - const u16 gMonPalette_DeoxysSpeed[] = INCBIN_U16("graphics/pokemon/deoxys/speed/normal.gbapal"); - const u32 gMonBackPic_DeoxysSpeed[] = INCBIN_U32("graphics/pokemon/deoxys/speed/back.4bpp.smol"); - const u16 gMonShinyPalette_DeoxysSpeed[] = INCBIN_U16("graphics/pokemon/deoxys/speed/shiny.gbapal"); const u8 gMonIcon_DeoxysSpeed[] = INCBIN_U8("graphics/pokemon/deoxys/speed/icon.4bpp"); #if OW_POKEMON_OBJECT_EVENTS diff --git a/src/data/heal_locations.json b/src/data/heal_locations.json index 3bfa468729..bd789dbdf5 100644 --- a/src/data/heal_locations.json +++ b/src/data/heal_locations.json @@ -6,9 +6,9 @@ "x": 4, "y": 2, "respawn_map": "MAP_LITTLEROOT_TOWN_BRENDANS_HOUSE_1F", + "respawn_npc": "LOCALID_PLAYERS_HOUSE_1F_MOM", "respawn_x": 2, - "respawn_y": 7, - "respawn_npc": "LOCALID_PLAYERS_HOUSE_1F_MOM" + "respawn_y": 7 }, { "id": "HEAL_LOCATION_LITTLEROOT_TOWN_MAYS_HOUSE_2F", @@ -16,9 +16,9 @@ "x": 4, "y": 2, "respawn_map": "MAP_LITTLEROOT_TOWN_MAYS_HOUSE_1F", + "respawn_npc": "LOCALID_PLAYERS_HOUSE_1F_MOM", "respawn_x": 8, - "respawn_y": 7, - "respawn_npc": "LOCALID_PLAYERS_HOUSE_1F_MOM" + "respawn_y": 7 }, { "id": "HEAL_LOCATION_PETALBURG_CITY", @@ -98,9 +98,9 @@ "x": 5, "y": 9, "respawn_map": "MAP_LITTLEROOT_TOWN_BRENDANS_HOUSE_1F", + "respawn_npc": "LOCALID_PLAYERS_HOUSE_1F_MOM", "respawn_x": 2, - "respawn_y": 7, - "respawn_npc": "LOCALID_PLAYERS_HOUSE_1F_MOM" + "respawn_y": 7 }, { "id": "HEAL_LOCATION_LITTLEROOT_TOWN_MAYS_HOUSE", @@ -108,9 +108,9 @@ "x": 14, "y": 9, "respawn_map": "MAP_LITTLEROOT_TOWN_MAYS_HOUSE_1F", + "respawn_npc": "LOCALID_PLAYERS_HOUSE_1F_MOM", "respawn_x": 8, - "respawn_y": 7, - "respawn_npc": "LOCALID_PLAYERS_HOUSE_1F_MOM" + "respawn_y": 7 }, { "id": "HEAL_LOCATION_OLDALE_TOWN", @@ -166,9 +166,9 @@ "x": 18, "y": 6, "respawn_map": "MAP_EVER_GRANDE_CITY_POKEMON_LEAGUE_1F", + "respawn_npc": "LOCALID_LEAGUE_NURSE", "respawn_x": 3, - "respawn_y": 4, - "respawn_npc": "LOCALID_LEAGUE_NURSE" + "respawn_y": 4 }, { "id": "HEAL_LOCATION_SOUTHERN_ISLAND_EXTERIOR", diff --git a/src/data/hold_effects.h b/src/data/hold_effects.h new file mode 100644 index 0000000000..221c9e166f --- /dev/null +++ b/src/data/hold_effects.h @@ -0,0 +1,649 @@ +const struct HoldEffectInfo gHoldEffectsInfo[HOLD_EFFECT_COUNT] = +{ + [HOLD_EFFECT_NONE] = + { + }, + + [HOLD_EFFECT_RESTORE_HP] = + { + .onSwitchIn = TRUE, + .onSwitchInFirstTurn = TRUE, + .onHpThreshold = TRUE, + }, + + [HOLD_EFFECT_CURE_PAR] = + { + .onSwitchIn = TRUE, + .onSwitchInFirstTurn = TRUE, + .onStatusChange = TRUE, + }, + + [HOLD_EFFECT_CURE_SLP] = + { + .onSwitchIn = TRUE, + .onSwitchInFirstTurn = TRUE, + .onStatusChange = TRUE, + }, + + [HOLD_EFFECT_CURE_PSN] = + { + .onSwitchIn = TRUE, + .onSwitchInFirstTurn = TRUE, + .onStatusChange = TRUE, + }, + + [HOLD_EFFECT_CURE_BRN] = + { + .onSwitchIn = TRUE, + .onSwitchInFirstTurn = TRUE, + .onStatusChange = TRUE, + }, + + [HOLD_EFFECT_CURE_FRZ] = + { + .onSwitchIn = TRUE, + .onSwitchInFirstTurn = TRUE, + .onStatusChange = TRUE, + }, + + [HOLD_EFFECT_RESTORE_PP] = + { + .onSwitchIn = TRUE, + .onSwitchInFirstTurn = TRUE, + .onAttackerAfterHit = TRUE, + }, + + [HOLD_EFFECT_CURE_CONFUSION] = + { + .onSwitchIn = TRUE, + .onSwitchInFirstTurn = TRUE, + .onStatusChange = TRUE, + }, + + [HOLD_EFFECT_CURE_STATUS] = + { + .onSwitchIn = TRUE, + .onSwitchInFirstTurn = TRUE, + .onStatusChange = TRUE, + }, + + [HOLD_EFFECT_CONFUSE_SPICY] = + { + .onSwitchIn = TRUE, + .onSwitchInFirstTurn = TRUE, + .onHpThreshold = TRUE, + }, + + [HOLD_EFFECT_CONFUSE_DRY] = + { + .onSwitchIn = TRUE, + .onSwitchInFirstTurn = TRUE, + .onHpThreshold = TRUE, + }, + + [HOLD_EFFECT_CONFUSE_SWEET] = + { + .onSwitchIn = TRUE, + .onSwitchInFirstTurn = TRUE, + .onHpThreshold = TRUE, + }, + + [HOLD_EFFECT_CONFUSE_BITTER] = + { + .onSwitchIn = TRUE, + .onSwitchInFirstTurn = TRUE, + .onHpThreshold = TRUE, + }, + + [HOLD_EFFECT_CONFUSE_SOUR] = + { + .onSwitchIn = TRUE, + .onSwitchInFirstTurn = TRUE, + .onHpThreshold = TRUE, + }, + + [HOLD_EFFECT_ATTACK_UP] = + { + .onSwitchIn = TRUE, + .onSwitchInFirstTurn = TRUE, + .onHpThreshold = TRUE, + }, + + [HOLD_EFFECT_DEFENSE_UP] = + { + .onSwitchIn = TRUE, + .onSwitchInFirstTurn = TRUE, + .onHpThreshold = TRUE, + }, + + [HOLD_EFFECT_SPEED_UP] = + { + .onSwitchIn = TRUE, + .onSwitchInFirstTurn = TRUE, + .onHpThreshold = TRUE, + }, + + [HOLD_EFFECT_SP_ATTACK_UP] = + { + .onSwitchIn = TRUE, + .onSwitchInFirstTurn = TRUE, + .onHpThreshold = TRUE, + }, + + [HOLD_EFFECT_SP_DEFENSE_UP] = + { + .onSwitchIn = TRUE, + .onSwitchInFirstTurn = TRUE, + .onHpThreshold = TRUE, + }, + + [HOLD_EFFECT_CRITICAL_UP] = + { + .onSwitchIn = TRUE, + .onSwitchInFirstTurn = TRUE, + .onHpThreshold = TRUE, + }, + + [HOLD_EFFECT_RANDOM_STAT_UP] = + { + .onSwitchIn = TRUE, + .onSwitchInFirstTurn = TRUE, + .onHpThreshold = TRUE, + }, + + [HOLD_EFFECT_EVASION_UP] = + { + .onSwitchIn = TRUE, + .onSwitchInFirstTurn = TRUE, + .onHpThreshold = TRUE, + }, + + [HOLD_EFFECT_WHITE_HERB] = + { + .whiteHerb = TRUE, + .whiteHerbFirstTurn = TRUE, + .whiteHerbEndTurn = TRUE, + .onFling = TRUE, + }, + + [HOLD_EFFECT_MACHO_BRACE] = + { + }, + + [HOLD_EFFECT_EXP_SHARE] = + { + }, + + [HOLD_EFFECT_QUICK_CLAW] = + { + }, + + [HOLD_EFFECT_FRIENDSHIP_UP] = + { + }, + + [HOLD_EFFECT_MENTAL_HERB] = + { + .onTargetAfterHit = TRUE, + .onAttackerAfterHit = TRUE, + .onFling = TRUE, + }, + + [HOLD_EFFECT_CHOICE_BAND] = + { + }, + + [HOLD_EFFECT_FLINCH] = + { + .onAttackerAfterHit = TRUE, + }, + + [HOLD_EFFECT_DOUBLE_PRIZE] = + { + .onSwitchIn = TRUE, + .onSwitchInFirstTurn = TRUE, + }, + + [HOLD_EFFECT_REPEL] = + { + }, + + [HOLD_EFFECT_SOUL_DEW] = + { + }, + + [HOLD_EFFECT_DEEP_SEA_TOOTH] = + { + }, + + [HOLD_EFFECT_DEEP_SEA_SCALE] = + { + }, + + [HOLD_EFFECT_CAN_ALWAYS_RUN] = + { + }, + + [HOLD_EFFECT_PREVENT_EVOLVE] = + { + }, + + [HOLD_EFFECT_FOCUS_BAND] = + { + }, + + [HOLD_EFFECT_LUCKY_EGG] = + { + }, + + [HOLD_EFFECT_SCOPE_LENS] = + { + }, + + [HOLD_EFFECT_LEFTOVERS] = + { + .leftovers = TRUE, + }, + + [HOLD_EFFECT_DRAGON_SCALE] = + { + }, + + [HOLD_EFFECT_LIGHT_BALL] = + { + }, + + [HOLD_EFFECT_TYPE_POWER] = + { + }, + + [HOLD_EFFECT_UPGRADE] = + { + }, + + [HOLD_EFFECT_SHELL_BELL] = + { + .lifeOrbShellBell = TRUE, + }, + + [HOLD_EFFECT_LUCKY_PUNCH] = + { + }, + + [HOLD_EFFECT_METAL_POWDER] = + { + }, + + [HOLD_EFFECT_THICK_CLUB] = + { + }, + + [HOLD_EFFECT_LEEK] = + { + }, + + [HOLD_EFFECT_CHOICE_SCARF] = + { + }, + + [HOLD_EFFECT_CHOICE_SPECS] = + { + }, + + [HOLD_EFFECT_DAMP_ROCK] = + { + }, + + [HOLD_EFFECT_GRIP_CLAW] = + { + }, + + [HOLD_EFFECT_HEAT_ROCK] = + { + }, + + [HOLD_EFFECT_ICY_ROCK] = + { + }, + + [HOLD_EFFECT_LIGHT_CLAY] = + { + }, + + [HOLD_EFFECT_SMOOTH_ROCK] = + { + }, + + [HOLD_EFFECT_POWER_HERB] = + { + }, + + [HOLD_EFFECT_BIG_ROOT] = + { + }, + + [HOLD_EFFECT_EXPERT_BELT] = + { + }, + + [HOLD_EFFECT_LIFE_ORB] = + { + .lifeOrbShellBell = TRUE, + }, + + [HOLD_EFFECT_METRONOME] = + { + }, + + [HOLD_EFFECT_MUSCLE_BAND] = + { + }, + + [HOLD_EFFECT_WIDE_LENS] = + { + }, + + [HOLD_EFFECT_WISE_GLASSES] = + { + }, + + [HOLD_EFFECT_ZOOM_LENS] = + { + }, + + [HOLD_EFFECT_LAGGING_TAIL] = + { + }, + + [HOLD_EFFECT_FOCUS_SASH] = + { + }, + + [HOLD_EFFECT_FLAME_ORB] = + { + .orbs = TRUE, + }, + + [HOLD_EFFECT_TOXIC_ORB] = + { + .orbs = TRUE, + }, + + [HOLD_EFFECT_STICKY_BARB] = + { + .onTargetAfterHit = TRUE, + .orbs = TRUE, + }, + + [HOLD_EFFECT_IRON_BALL] = + { + }, + + [HOLD_EFFECT_BLACK_SLUDGE] = + { + .leftovers = TRUE, + }, + + [HOLD_EFFECT_DESTINY_KNOT] = + { + }, + + [HOLD_EFFECT_SHED_SHELL] = + { + }, + + [HOLD_EFFECT_QUICK_POWDER] = + { + }, + + [HOLD_EFFECT_ADAMANT_ORB] = + { + }, + + [HOLD_EFFECT_LUSTROUS_ORB] = + { + }, + + [HOLD_EFFECT_GRISEOUS_ORB] = + { + }, + + [HOLD_EFFECT_ENIGMA_BERRY] = + { + .onTargetAfterHit = TRUE, + }, + + [HOLD_EFFECT_RESIST_BERRY] = + { + }, + + [HOLD_EFFECT_POWER_ITEM] = + { + }, + + [HOLD_EFFECT_RESTORE_PCT_HP] = + { + .onSwitchIn = TRUE, + .onSwitchInFirstTurn = TRUE, + .onHpThreshold = TRUE, + }, + + [HOLD_EFFECT_MICLE_BERRY] = + { + .onSwitchIn = TRUE, + .onSwitchInFirstTurn = TRUE, + .onHpThreshold = TRUE, + }, + + [HOLD_EFFECT_CUSTAP_BERRY] = + { + }, + + [HOLD_EFFECT_JABOCA_BERRY] = + { + .onTargetAfterHit = TRUE, + }, + + [HOLD_EFFECT_ROWAP_BERRY] = + { + .onTargetAfterHit = TRUE, + }, + + [HOLD_EFFECT_KEE_BERRY] = + { + .keeMarangaBerry = TRUE, + }, + + [HOLD_EFFECT_MARANGA_BERRY] = + { + .keeMarangaBerry = TRUE, + }, + + [HOLD_EFFECT_PLATE] = + { + }, + + [HOLD_EFFECT_FLOAT_STONE] = + { + }, + + [HOLD_EFFECT_EVIOLITE] = + { + }, + + [HOLD_EFFECT_ASSAULT_VEST] = + { + }, + + [HOLD_EFFECT_DRIVE] = + { + }, + + [HOLD_EFFECT_GEMS] = + { + }, + + [HOLD_EFFECT_ROCKY_HELMET] = + { + .onTargetAfterHit = TRUE, + }, + + [HOLD_EFFECT_AIR_BALLOON] = + { + .onTargetAfterHit = TRUE, + .onSwitchIn = TRUE, + .onSwitchInFirstTurn = TRUE, + }, + + [HOLD_EFFECT_RED_CARD] = + { + }, + + [HOLD_EFFECT_RING_TARGET] = + { + }, + + [HOLD_EFFECT_BINDING_BAND] = + { + }, + + [HOLD_EFFECT_EJECT_BUTTON] = + { + }, + + [HOLD_EFFECT_ABSORB_BULB] = + { + .onTargetAfterHit = TRUE, + }, + + [HOLD_EFFECT_CELL_BATTERY] = + { + .onTargetAfterHit = TRUE, + }, + + [HOLD_EFFECT_MEGA_STONE] = + { + }, + + [HOLD_EFFECT_SAFETY_GOGGLES] = + { + }, + + [HOLD_EFFECT_LUMINOUS_MOSS] = + { + .onTargetAfterHit = TRUE, + }, + + [HOLD_EFFECT_SNOWBALL] = + { + .onTargetAfterHit = TRUE, + }, + + [HOLD_EFFECT_WEAKNESS_POLICY] = + { + .onTargetAfterHit = TRUE, + }, + + [HOLD_EFFECT_PRIMAL_ORB] = + { + }, + + [HOLD_EFFECT_PROTECTIVE_PADS] = + { + }, + + [HOLD_EFFECT_TERRAIN_EXTENDER] = + { + }, + + [HOLD_EFFECT_TERRAIN_SEED] = + { + .onSwitchIn = TRUE, + .onSwitchInFirstTurn = TRUE, + .onEffect = TRUE, + }, + + [HOLD_EFFECT_ADRENALINE_ORB] = + { + }, + + [HOLD_EFFECT_MEMORY] = + { + }, + + [HOLD_EFFECT_Z_CRYSTAL] = + { + }, + + [HOLD_EFFECT_UTILITY_UMBRELLA] = + { + }, + + [HOLD_EFFECT_EJECT_PACK] = + { + }, + + [HOLD_EFFECT_ROOM_SERVICE] = + { + .onSwitchIn = TRUE, + .onSwitchInFirstTurn = TRUE, + .onEffect = TRUE, + }, + + [HOLD_EFFECT_BLUNDER_POLICY] = + { + .onAttackerAfterHit = TRUE, + }, + + [HOLD_EFFECT_HEAVY_DUTY_BOOTS] = + { + }, + + [HOLD_EFFECT_THROAT_SPRAY] = + { + .onAttackerAfterHit = TRUE, + }, + + [HOLD_EFFECT_ABILITY_SHIELD] = + { + }, + + [HOLD_EFFECT_CLEAR_AMULET] = + { + }, + + [HOLD_EFFECT_MIRROR_HERB] = + { + .mirrorHerb = TRUE, + .mirrorHerbFirstTurn = TRUE, + }, + + [HOLD_EFFECT_PUNCHING_GLOVE] = + { + }, + + [HOLD_EFFECT_COVERT_CLOAK] = + { + }, + + [HOLD_EFFECT_LOADED_DICE] = + { + }, + + [HOLD_EFFECT_BOOSTER_ENERGY] = + { + .onSwitchIn = TRUE, + .onSwitchInFirstTurn = TRUE, + .onEffect = TRUE, + }, + + [HOLD_EFFECT_OGERPON_MASK] = + { + }, + + [HOLD_EFFECT_BERSERK_GENE] = + { + .onSwitchIn = TRUE, + .onSwitchInFirstTurn = TRUE, + }, +}; diff --git a/src/data/items.h b/src/data/items.h index 2600be4610..33eb0f984f 100644 --- a/src/data/items.h +++ b/src/data/items.h @@ -616,6 +616,7 @@ const struct Item gItemsInfo[] = "宝可梦回复20H\n" "P。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HEALTH_RECOVERY, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .battleUsage = EFFECT_ITEM_RESTORE_HP, @@ -635,6 +636,7 @@ const struct Item gItemsInfo[] = "宝可梦回复60H\n" "P。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HEALTH_RECOVERY, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .battleUsage = EFFECT_ITEM_RESTORE_HP, @@ -654,6 +656,7 @@ const struct Item gItemsInfo[] = "宝可梦回复120\n" "HP。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HEALTH_RECOVERY, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .battleUsage = EFFECT_ITEM_RESTORE_HP, @@ -673,6 +676,7 @@ const struct Item gItemsInfo[] = "宝可梦回复所有H\n" "P。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HEALTH_RECOVERY, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .battleUsage = EFFECT_ITEM_RESTORE_HP, @@ -692,6 +696,7 @@ const struct Item gItemsInfo[] = "有HP并治愈所有\n" "异常状态。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HEALTH_RECOVERY, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .battleUsage = EFFECT_ITEM_HEAL_AND_CURE_STATUS, @@ -710,6 +715,7 @@ const struct Item gItemsInfo[] = "的宝可梦复活,并\n" "回复一半HP。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HEALTH_RECOVERY, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .battleUsage = EFFECT_ITEM_REVIVE, @@ -725,6 +731,7 @@ const struct Item gItemsInfo[] = .price = 4000, .description = sMaxReviveDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HEALTH_RECOVERY, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .battleUsage = EFFECT_ITEM_REVIVE, @@ -744,6 +751,7 @@ const struct Item gItemsInfo[] = "能让宝可梦回复3\n" "0HP。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HEALTH_RECOVERY, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .battleUsage = EFFECT_ITEM_RESTORE_HP, @@ -763,6 +771,7 @@ const struct Item gItemsInfo[] = "。能让宝可梦回复\n" "50HP。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HEALTH_RECOVERY, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .battleUsage = EFFECT_ITEM_RESTORE_HP, @@ -782,6 +791,7 @@ const struct Item gItemsInfo[] = "能让宝可梦回复7\n" "0HP。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HEALTH_RECOVERY, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .battleUsage = EFFECT_ITEM_RESTORE_HP, @@ -801,6 +811,7 @@ const struct Item gItemsInfo[] = "。能让宝可梦回复\n" "100HP。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HEALTH_RECOVERY, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .battleUsage = EFFECT_ITEM_RESTORE_HP, @@ -819,6 +830,7 @@ const struct Item gItemsInfo[] = "让宝可梦回复60\n" "HP。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HEALTH_RECOVERY, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .battleUsage = EFFECT_ITEM_RESTORE_HP, @@ -837,6 +849,7 @@ const struct Item gItemsInfo[] = "宝可梦回复120\n" "HP。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HEALTH_RECOVERY, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .battleUsage = EFFECT_ITEM_RESTORE_HP, @@ -855,6 +868,7 @@ const struct Item gItemsInfo[] = "治愈宝可梦的所有\n" "异常状态。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_STATUS_RECOVERY, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .battleUsage = EFFECT_ITEM_CURE_STATUS, @@ -873,6 +887,7 @@ const struct Item gItemsInfo[] = "让1只昏厥的宝可\n" "梦回复所有HP。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HEALTH_RECOVERY, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .battleUsage = EFFECT_ITEM_REVIVE, @@ -891,6 +906,7 @@ const struct Item gItemsInfo[] = "愈宝可梦的中毒状\n" "态。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_STATUS_RECOVERY, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .battleUsage = EFFECT_ITEM_CURE_STATUS, @@ -909,6 +925,7 @@ const struct Item gItemsInfo[] = "愈宝可梦的麻痹状\n" "态。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_STATUS_RECOVERY, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .battleUsage = EFFECT_ITEM_CURE_STATUS, @@ -927,6 +944,7 @@ const struct Item gItemsInfo[] = "愈宝可梦的灼伤状\n" "态。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_STATUS_RECOVERY, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .battleUsage = EFFECT_ITEM_CURE_STATUS, @@ -945,6 +963,7 @@ const struct Item gItemsInfo[] = "愈宝可梦的冰冻状\n" "态。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_STATUS_RECOVERY, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .battleUsage = EFFECT_ITEM_CURE_STATUS, @@ -963,6 +982,7 @@ const struct Item gItemsInfo[] = "愈宝可梦的睡眠状\n" "态。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_STATUS_RECOVERY, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .battleUsage = EFFECT_ITEM_CURE_STATUS, @@ -978,6 +998,7 @@ const struct Item gItemsInfo[] = .price = (I_PRICE >= GEN_7) ? 400 : 600, .description = sFullHealDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_STATUS_RECOVERY, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .battleUsage = EFFECT_ITEM_CURE_STATUS, @@ -997,6 +1018,7 @@ const struct Item gItemsInfo[] = "其中1个招式回复\n" "10PP。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_PP_RECOVERY, .type = ITEM_USE_PARTY_MENU_MOVES, .fieldUseFunc = ItemUseOutOfBattle_PPRecovery, .battleUsage = EFFECT_ITEM_RESTORE_PP, @@ -1016,6 +1038,7 @@ const struct Item gItemsInfo[] = "其中1个招式回复\n" "所有PP。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_PP_RECOVERY, .type = ITEM_USE_PARTY_MENU_MOVES, .fieldUseFunc = ItemUseOutOfBattle_PPRecovery, .battleUsage = EFFECT_ITEM_RESTORE_PP, @@ -1035,6 +1058,7 @@ const struct Item gItemsInfo[] = "4个招式各回复1\n" "0PP。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_PP_RECOVERY, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_PPRecovery, .battleUsage = EFFECT_ITEM_RESTORE_PP, @@ -1054,6 +1078,7 @@ const struct Item gItemsInfo[] = "4个招式回复所有\n" "PP。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_PP_RECOVERY, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_PPRecovery, .battleUsage = EFFECT_ITEM_RESTORE_PP, @@ -1074,6 +1099,7 @@ const struct Item gItemsInfo[] = "。能让宝可梦回复\n" "20HP。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HEALTH_RECOVERY, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .battleUsage = EFFECT_ITEM_RESTORE_HP, @@ -1092,6 +1118,7 @@ const struct Item gItemsInfo[] = "部宝可梦回复所有\n" "HP。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HEALTH_RECOVERY, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_SacredAsh, .effect = gItemEffect_SacredAsh, @@ -1110,6 +1137,7 @@ const struct Item gItemsInfo[] = "。能让宝可梦回复\n" "20HP。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HEALTH_RECOVERY, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .battleUsage = EFFECT_ITEM_RESTORE_HP, @@ -1125,6 +1153,7 @@ const struct Item gItemsInfo[] = .price = 8000, .description = sMaxReviveDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HEALTH_RECOVERY, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .battleUsage = EFFECT_ITEM_REVIVE, @@ -1142,6 +1171,7 @@ const struct Item gItemsInfo[] = .price = 250, .description = sFullHealDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_STATUS_RECOVERY, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .battleUsage = EFFECT_ITEM_CURE_STATUS, @@ -1157,6 +1187,7 @@ const struct Item gItemsInfo[] = .price = (I_PRICE >= GEN_7) ? 350 : 300, .description = sFullHealDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_STATUS_RECOVERY, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .battleUsage = EFFECT_ITEM_CURE_STATUS, @@ -1175,6 +1206,7 @@ const struct Item gItemsInfo[] = "能治愈宝可梦的所\n" "有异常状态。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_STATUS_RECOVERY, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .battleUsage = EFFECT_ITEM_CURE_STATUS, @@ -1190,6 +1222,7 @@ const struct Item gItemsInfo[] = .price = (I_PRICE >= GEN_7) ? 350 : 200, .description = sFullHealDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_STATUS_RECOVERY, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .battleUsage = EFFECT_ITEM_CURE_STATUS, @@ -1205,6 +1238,7 @@ const struct Item gItemsInfo[] = .price = (I_PRICE >= GEN_7) ? 350 : 100, .description = sFullHealDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_STATUS_RECOVERY, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .battleUsage = EFFECT_ITEM_CURE_STATUS, @@ -1220,6 +1254,7 @@ const struct Item gItemsInfo[] = .price = (I_PRICE >= GEN_7) ? 350 : 200, .description = sFullHealDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_STATUS_RECOVERY, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .battleUsage = EFFECT_ITEM_CURE_STATUS, @@ -1235,6 +1270,7 @@ const struct Item gItemsInfo[] = .price = (I_PRICE >= GEN_7) ? 350 : 200, .description = sFullHealDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_STATUS_RECOVERY, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .battleUsage = EFFECT_ITEM_CURE_STATUS, @@ -1250,6 +1286,7 @@ const struct Item gItemsInfo[] = .price = 350, .description = sFullHealDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_STATUS_RECOVERY, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .battleUsage = EFFECT_ITEM_CURE_STATUS, @@ -1270,6 +1307,7 @@ const struct Item gItemsInfo[] = "。能提高宝可梦的\n" "HP的基础点数。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_STAT_BOOST_DRINK, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .effect = gItemEffect_HPUp, @@ -1287,6 +1325,7 @@ const struct Item gItemsInfo[] = "。能提高宝可梦的\n" "攻击的基础点数。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_STAT_BOOST_DRINK, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .effect = gItemEffect_Protein, @@ -1304,6 +1343,7 @@ const struct Item gItemsInfo[] = "。能提高宝可梦的\n" "防御的基础点数。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_STAT_BOOST_DRINK, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .effect = gItemEffect_Iron, @@ -1321,6 +1361,7 @@ const struct Item gItemsInfo[] = "。能提高宝可梦的\n" "特攻的基础点数。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_STAT_BOOST_DRINK, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .effect = gItemEffect_Calcium, @@ -1338,6 +1379,7 @@ const struct Item gItemsInfo[] = "。能提高宝可梦的\n" "特防的基础点数。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_STAT_BOOST_DRINK, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .effect = gItemEffect_Zinc, @@ -1355,6 +1397,7 @@ const struct Item gItemsInfo[] = "。能提高宝可梦的\n" "速度的基础点数。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_STAT_BOOST_DRINK, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .effect = gItemEffect_Carbos, @@ -1372,6 +1415,7 @@ const struct Item gItemsInfo[] = "其中1个招式PP\n" "最大值少量提高。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_STAT_BOOST_DRINK, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_PPUp, .effect = gItemEffect_PPUp, @@ -1389,6 +1433,7 @@ const struct Item gItemsInfo[] = "其中1个招式PP\n" "最大值提至最高。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_STAT_BOOST_DRINK, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_PPUp, .effect = gItemEffect_PPMax, @@ -1405,6 +1450,7 @@ const struct Item gItemsInfo[] = .price = (I_PRICE >= GEN_7) ? 300 : 3000, .description = sHealthFeatherDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_STAT_BOOST_FEATHER, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .effect = gItemEffect_HpFeather, @@ -1419,6 +1465,7 @@ const struct Item gItemsInfo[] = .price = (I_PRICE >= GEN_7) ? 300 : 3000, .description = sMuscleFeatherDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_STAT_BOOST_FEATHER, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .effect = gItemEffect_AtkFeather, @@ -1433,6 +1480,7 @@ const struct Item gItemsInfo[] = .price = (I_PRICE >= GEN_7) ? 300 : 3000, .description = sResistFeatherDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_STAT_BOOST_FEATHER, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .effect = gItemEffect_DefFeather, @@ -1447,6 +1495,7 @@ const struct Item gItemsInfo[] = .price = (I_PRICE >= GEN_7) ? 300 : 3000, .description = sGeniusFeatherDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_STAT_BOOST_FEATHER, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .effect = gItemEffect_SpatkFeather, @@ -1461,6 +1510,7 @@ const struct Item gItemsInfo[] = .price = (I_PRICE >= GEN_7) ? 300 : 3000, .description = sCleverFeatherDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_STAT_BOOST_FEATHER, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .effect = gItemEffect_SpdefFeather, @@ -1475,6 +1525,7 @@ const struct Item gItemsInfo[] = .price = (I_PRICE >= GEN_7) ? 300 : 3000, .description = sSwiftFeatherDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_STAT_BOOST_FEATHER, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .effect = gItemEffect_SpeedFeather, @@ -1495,6 +1546,7 @@ const struct Item gItemsInfo[] = "的宝可梦特性变为\n" "另一种的胶囊。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_FIELD_USE, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_AbilityCapsule, .iconPic = gItemIcon_AbilityCapsule, @@ -1511,6 +1563,7 @@ const struct Item gItemsInfo[] = "性的膏药。其特性\n" "会变为稀有特性。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_FIELD_USE, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_AbilityPatch, .iconPic = gItemIcon_AbilityPatch, @@ -1528,6 +1581,7 @@ const struct Item gItemsInfo[] = "击会易于提高,而\n" "防御则难以提高。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_NATURE_MINT, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Mint, .secondaryId = NATURE_LONELY, @@ -1545,6 +1599,7 @@ const struct Item gItemsInfo[] = "击会易于提高,而\n" "特攻则难以提高。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_NATURE_MINT, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Mint, .secondaryId = NATURE_ADAMANT, @@ -1562,6 +1617,7 @@ const struct Item gItemsInfo[] = "击容易提高,而特\n" "防则难以提高。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_NATURE_MINT, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Mint, .secondaryId = NATURE_NAUGHTY, @@ -1579,6 +1635,7 @@ const struct Item gItemsInfo[] = "击容易提高,而速\n" "度则难以提高。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_NATURE_MINT, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Mint, .secondaryId = NATURE_BRAVE, @@ -1596,6 +1653,7 @@ const struct Item gItemsInfo[] = "御容易提高,而攻\n" "击则难以提高。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_NATURE_MINT, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Mint, .secondaryId = NATURE_BOLD, @@ -1613,6 +1671,7 @@ const struct Item gItemsInfo[] = "御容易提高,而特\n" "攻则难以提高。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_NATURE_MINT, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Mint, .secondaryId = NATURE_IMPISH, @@ -1630,6 +1689,7 @@ const struct Item gItemsInfo[] = "御容易提高,而特\n" "防则难以提高。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_NATURE_MINT, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Mint, .secondaryId = NATURE_LAX, @@ -1647,6 +1707,7 @@ const struct Item gItemsInfo[] = "御容易提高,而速\n" "度则难以提高。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_NATURE_MINT, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Mint, .secondaryId = NATURE_RELAXED, @@ -1664,6 +1725,7 @@ const struct Item gItemsInfo[] = "攻容易提高,而攻\n" "击则难以提高。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_NATURE_MINT, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Mint, .secondaryId = NATURE_MODEST, @@ -1681,6 +1743,7 @@ const struct Item gItemsInfo[] = "攻容易提高,而防\n" "御则难以提高。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_NATURE_MINT, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Mint, .secondaryId = NATURE_MILD, @@ -1698,6 +1761,7 @@ const struct Item gItemsInfo[] = "攻容易提高,而特\n" "防则难以提高。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_NATURE_MINT, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Mint, .secondaryId = NATURE_RASH, @@ -1715,6 +1779,7 @@ const struct Item gItemsInfo[] = "攻容易提高,而速\n" "度则难以提高。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_NATURE_MINT, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Mint, .secondaryId = NATURE_QUIET, @@ -1732,6 +1797,7 @@ const struct Item gItemsInfo[] = "防容易提高,而攻\n" "击则难以提高。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_NATURE_MINT, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Mint, .secondaryId = NATURE_CALM, @@ -1749,6 +1815,7 @@ const struct Item gItemsInfo[] = "防容易提高,而防\n" "御则难以提高。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_NATURE_MINT, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Mint, .secondaryId = NATURE_GENTLE, @@ -1766,6 +1833,7 @@ const struct Item gItemsInfo[] = "防容易提高,而特\n" "攻则难以提高。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_NATURE_MINT, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Mint, .secondaryId = NATURE_CAREFUL, @@ -1783,6 +1851,7 @@ const struct Item gItemsInfo[] = "防容易提高,而速\n" "度则难以提高。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_NATURE_MINT, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Mint, .secondaryId = NATURE_SASSY, @@ -1800,6 +1869,7 @@ const struct Item gItemsInfo[] = "度容易提高,而攻\n" "击则难以提高。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_NATURE_MINT, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Mint, .secondaryId = NATURE_TIMID, @@ -1817,6 +1887,7 @@ const struct Item gItemsInfo[] = "度容易提高,而防\n" "御则难以提高。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_NATURE_MINT, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Mint, .secondaryId = NATURE_HASTY, @@ -1834,6 +1905,7 @@ const struct Item gItemsInfo[] = "度容易提高,而特\n" "攻则难以提高。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_NATURE_MINT, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Mint, .secondaryId = NATURE_JOLLY, @@ -1851,6 +1923,7 @@ const struct Item gItemsInfo[] = "度容易提高,而特\n" "防则难以提高。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_NATURE_MINT, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Mint, .secondaryId = NATURE_NAIVE, @@ -1867,6 +1940,7 @@ const struct Item gItemsInfo[] = "宝可梦闻了后,能\n" "力全方位提高。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_NATURE_MINT, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Mint, .secondaryId = NATURE_SERIOUS, @@ -1886,6 +1960,7 @@ const struct Item gItemsInfo[] = "给宝可梦后,等级\n" "会提高1。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_LEVEL_UP_ITEM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_RareCandy, .effect = gItemEffect_RareCandy, @@ -1904,6 +1979,7 @@ const struct Item gItemsInfo[] = "给宝可梦后,可增\n" "加一点点经验值。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_LEVEL_UP_ITEM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_RareCandy, .effect = gItemEffect_RareCandy, @@ -1922,6 +1998,7 @@ const struct Item gItemsInfo[] = "给宝可梦后,可增\n" "加少许经验值。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_LEVEL_UP_ITEM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_RareCandy, .effect = gItemEffect_RareCandy, @@ -1940,6 +2017,7 @@ const struct Item gItemsInfo[] = "给宝可梦后,可增\n" "加经验值。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_LEVEL_UP_ITEM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_RareCandy, .effect = gItemEffect_RareCandy, @@ -1958,6 +2036,7 @@ const struct Item gItemsInfo[] = "给宝可梦后,可增\n" "加许多经验值。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_LEVEL_UP_ITEM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_RareCandy, .effect = gItemEffect_RareCandy, @@ -1976,6 +2055,7 @@ const struct Item gItemsInfo[] = "给宝可梦后,可增\n" "加大量经验值。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_LEVEL_UP_ITEM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_RareCandy, .effect = gItemEffect_RareCandy, @@ -1993,6 +2073,7 @@ const struct Item gItemsInfo[] = "给宝可梦后,极巨\n" "化等级能提高1。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_LEVEL_UP_ITEM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_DynamaxCandy, .flingPower = 30, @@ -2012,6 +2093,7 @@ const struct Item gItemsInfo[] = "眠状态。"), .notConsumed = TRUE, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_FLUTE, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .battleUsage = EFFECT_ITEM_CURE_STATUS, @@ -2031,6 +2113,7 @@ const struct Item gItemsInfo[] = "乱状态。"), .notConsumed = TRUE, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_FLUTE, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .battleUsage = EFFECT_ITEM_CURE_STATUS, @@ -2050,6 +2133,7 @@ const struct Item gItemsInfo[] = "迷状态。"), .notConsumed = TRUE, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_FLUTE, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .battleUsage = EFFECT_ITEM_CURE_STATUS, @@ -2072,6 +2156,7 @@ const struct Item gItemsInfo[] = "强大的宝可梦。"), .notConsumed = TRUE, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_FLUTE, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_BlackWhiteFlute, .flingPower = 30, @@ -2090,6 +2175,7 @@ const struct Item gItemsInfo[] = "弱小的宝可梦。"), .notConsumed = TRUE, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_FLUTE, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_BlackWhiteFlute, .flingPower = 30, @@ -2109,6 +2195,7 @@ const struct Item gItemsInfo[] = ",弱小的野生宝可\n" "梦将不会出现。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_FIELD_USE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_Repel, .flingPower = 30, @@ -2126,6 +2213,7 @@ const struct Item gItemsInfo[] = "将不会出现。效果\n" "比除虫喷雾持久。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_FIELD_USE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_Repel, .flingPower = 30, @@ -2143,6 +2231,7 @@ const struct Item gItemsInfo[] = "将不会出现。效果\n" "比白银喷雾持久。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_FIELD_USE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_Repel, .flingPower = 30, @@ -2160,6 +2249,7 @@ const struct Item gItemsInfo[] = "时间内,稀有宝可\n" "梦会更容易出现。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_FIELD_USE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_Lure, .secondaryId = 0, @@ -2178,6 +2268,7 @@ const struct Item gItemsInfo[] = "会更易出现。效果\n" "比引虫香水持久。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_FIELD_USE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_Lure, .secondaryId = 0, @@ -2196,6 +2287,7 @@ const struct Item gItemsInfo[] = "会更易出现。效果\n" "比白银香水持久。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_FIELD_USE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_Lure, .secondaryId = 0, @@ -2215,6 +2307,7 @@ const struct Item gItemsInfo[] = .price = 0, .importance = 1, .pocket = POCKET_KEY_ITEMS, + .sortType = ITEM_TYPE_FIELD_USE, #else .price = (I_PRICE >= GEN_7) ? 1000 : 550, .pocket = POCKET_ITEMS, @@ -2237,6 +2330,7 @@ const struct Item gItemsInfo[] = "大幅提高战斗中宝\n" "可梦攻击的道具。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_X_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .battleUsage = EFFECT_ITEM_INCREASE_STAT, @@ -2255,6 +2349,7 @@ const struct Item gItemsInfo[] = "大幅提高战斗中宝\n" "可梦防御的道具。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_X_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .battleUsage = EFFECT_ITEM_INCREASE_STAT, @@ -2273,6 +2368,7 @@ const struct Item gItemsInfo[] = "大幅提高战斗中宝\n" "可梦特攻的道具。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_X_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .battleUsage = EFFECT_ITEM_INCREASE_STAT, @@ -2291,6 +2387,7 @@ const struct Item gItemsInfo[] = "大幅提高战斗中宝\n" "可梦特防的道具。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_X_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .battleUsage = EFFECT_ITEM_INCREASE_STAT, @@ -2309,6 +2406,7 @@ const struct Item gItemsInfo[] = "大幅提高战斗中宝\n" "可梦速度的道具。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_X_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .battleUsage = EFFECT_ITEM_INCREASE_STAT, @@ -2327,6 +2425,7 @@ const struct Item gItemsInfo[] = "大幅提高战斗中宝\n" "可梦命中的道具。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_X_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .battleUsage = EFFECT_ITEM_INCREASE_STAT, @@ -2345,6 +2444,7 @@ const struct Item gItemsInfo[] = "大幅提高。只能使\n" "用1次。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_X_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .battleUsage = EFFECT_ITEM_SET_FOCUS_ENERGY, @@ -2363,6 +2463,7 @@ const struct Item gItemsInfo[] = "内不让我方能力降\n" "低的道具。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_X_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .battleUsage = EFFECT_ITEM_SET_MIST, @@ -2378,6 +2479,7 @@ const struct Item gItemsInfo[] = .price = (I_PRICE < GEN_7) ? 1000 : ((I_PRICE == GEN_7) ? 100 : 300), .description = sPokeDollDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_BATTLE_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .battleUsage = EFFECT_ITEM_ESCAPE, @@ -2392,6 +2494,7 @@ const struct Item gItemsInfo[] = .price = (I_PRICE >= GEN_7) ? 100 : 1000, .description = sPokeDollDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_BATTLE_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .battleUsage = EFFECT_ITEM_ESCAPE, @@ -2406,6 +2509,7 @@ const struct Item gItemsInfo[] = .price = (I_PRICE >= GEN_7) ? 100 : 1000, .description = sPokeDollDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_BATTLE_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .battleUsage = EFFECT_ITEM_ESCAPE, @@ -2423,6 +2527,7 @@ const struct Item gItemsInfo[] = "蘑菇,能改变宝可\n" "梦极巨化的样子。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_BATTLE_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .battleUsage = EFFECT_ITEM_INCREASE_ALL_STATS, @@ -2442,6 +2547,7 @@ const struct Item gItemsInfo[] = "有些人收到它会很\n" "高兴。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_SELLABLE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -2458,6 +2564,7 @@ const struct Item gItemsInfo[] = "有些人收到它会很\n" "高兴。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_SELLABLE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -2474,6 +2581,7 @@ const struct Item gItemsInfo[] = "制成的珠子。可以\n" "在商店高价出售。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_SELLABLE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -2490,6 +2598,7 @@ const struct Item gItemsInfo[] = "光的大珠子。可以\n" "在商店高价出售。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_SELLABLE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 130, @@ -2506,6 +2615,7 @@ const struct Item gItemsInfo[] = "一些爱好者中有着\n" "相当高的人气。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_SELLABLE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -2519,6 +2629,7 @@ const struct Item gItemsInfo[] = .price = 5000 * TREASURE_FACTOR, .description = sBigMushroomDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_SELLABLE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -2532,6 +2643,7 @@ const struct Item gItemsInfo[] = .price = (I_PRICE >= GEN_7) ? 15000 * TREASURE_FACTOR: 12500, .description = sBigMushroomDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_SELLABLE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -2548,6 +2660,7 @@ const struct Item gItemsInfo[] = "小的珍珠。可以在\n" "商店低价出售。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_SELLABLE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -2564,6 +2677,7 @@ const struct Item gItemsInfo[] = "大颗的珍珠。可以\n" "在商店高价出售。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_SELLABLE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -2580,6 +2694,7 @@ const struct Item gItemsInfo[] = "大颗的珍珠。可以\n" "在商店高价出售。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_SELLABLE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -2596,6 +2711,7 @@ const struct Item gItemsInfo[] = "红色沙子。可以在\n" "商店低价出售。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_SELLABLE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -2612,6 +2728,7 @@ const struct Item gItemsInfo[] = "的宝石碎片。可以\n" "在商店高价出售。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_SELLABLE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -2628,6 +2745,7 @@ const struct Item gItemsInfo[] = "地表的碎片。可以\n" "在商店高价出售。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_SELLABLE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -2643,6 +2761,7 @@ const struct Item gItemsInfo[] = "在浅滩洞穴这地方\n" "找到的海盐。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_SELLABLE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -2658,6 +2777,7 @@ const struct Item gItemsInfo[] = "在浅滩洞穴这地方\n" "找到的贝壳。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_SELLABLE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -2671,6 +2791,7 @@ const struct Item gItemsInfo[] = .price = (I_PRICE >= GEN_7) ? 1000 : 200, .description = sShardsDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_SHARD, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -2684,6 +2805,7 @@ const struct Item gItemsInfo[] = .price = (I_PRICE >= GEN_7) ? 1000 : 200, .description = sShardsDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_SHARD, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -2697,6 +2819,7 @@ const struct Item gItemsInfo[] = .price = (I_PRICE >= GEN_7) ? 1000 : 200, .description = sShardsDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_SHARD, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -2710,6 +2833,7 @@ const struct Item gItemsInfo[] = .price = (I_PRICE >= GEN_7) ? 1000 : 200, .description = sShardsDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_SHARD, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -2726,6 +2850,7 @@ const struct Item gItemsInfo[] = "的珍稀鳞片。有些\n" "人收到会很高兴。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_SELLABLE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -2742,6 +2867,7 @@ const struct Item gItemsInfo[] = "芬芳的花蜜。可在\n" "商店里廉价出售。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_STATUS_RECOVERY, .type = ITEM_USE_FIELD, .fieldUseFunc = ItemUseOutOfBattle_Honey, .flingPower = 30, @@ -2758,6 +2884,7 @@ const struct Item gItemsInfo[] = "重的骨头。可以在\n" "商店高价出售。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_SELLABLE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 100, @@ -2774,6 +2901,7 @@ const struct Item gItemsInfo[] = "石头。有时能从石\n" "头里听到声音。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_SELLABLE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -2790,6 +2918,7 @@ const struct Item gItemsInfo[] = "有任何效果,极其\n" "普通的羽毛。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_SELLABLE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 20, @@ -2805,6 +2934,7 @@ const struct Item gItemsInfo[] = "约3000年前的\n" "文明使用的铜币。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_RELIC, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -2820,6 +2950,7 @@ const struct Item gItemsInfo[] = "约3000年前的\n" "文明使用的银币。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_RELIC, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -2835,6 +2966,7 @@ const struct Item gItemsInfo[] = "约3000年前的\n" "文明使用的金币。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_RELIC, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -2850,6 +2982,7 @@ const struct Item gItemsInfo[] = "约3000年前的\n" "文明制造的壶。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_RELIC, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -2865,6 +2998,7 @@ const struct Item gItemsInfo[] = "约3000年前的\n" "文明制造的手镯。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_RELIC, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -2880,6 +3014,7 @@ const struct Item gItemsInfo[] = "约3000年前的\n" "文明制造的石像。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_RELIC, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -2895,6 +3030,7 @@ const struct Item gItemsInfo[] = "约3000年前的\n" "文明制造的王冠。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_RELIC, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -2911,6 +3047,7 @@ const struct Item gItemsInfo[] = "被称为守护神宝可\n" "梦而制作的摆设。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_RELIC, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -2930,6 +3067,7 @@ const struct Item gItemsInfo[] = #if I_KEY_FOSSILS >= GEN_4 .price = (I_PRICE >= GEN_7) ? 7000: 1000, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_FOSSIL, #else .price = 0, .importance = 1, @@ -2952,6 +3090,7 @@ const struct Item gItemsInfo[] = #if I_KEY_FOSSILS >= GEN_4 .price = (I_PRICE >= GEN_7) ? 7000: 1000, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_FOSSIL, #else .price = 0, .importance = 1, @@ -2974,6 +3113,7 @@ const struct Item gItemsInfo[] = #if I_KEY_FOSSILS >= GEN_4 .price = 1000, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_FOSSIL, #else .price = 0, .importance = 1, @@ -2993,6 +3133,7 @@ const struct Item gItemsInfo[] = #if I_KEY_FOSSILS >= GEN_4 .price = (I_PRICE >= GEN_7) ? 7000: 1000, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_FOSSIL, #else .price = 0, .importance = 1, @@ -3012,6 +3153,7 @@ const struct Item gItemsInfo[] = #if I_KEY_FOSSILS >= GEN_4 .price = (I_PRICE >= GEN_7) ? 7000: 1000, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_FOSSIL, #else .price = 0, .importance = 1, @@ -3033,6 +3175,7 @@ const struct Item gItemsInfo[] = "可梦的化石。好像\n" "是领饰的一部分。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_FOSSIL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 100, @@ -3049,6 +3192,7 @@ const struct Item gItemsInfo[] = "可梦的化石。好像\n" "是头部的一部分。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_FOSSIL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 100, @@ -3065,6 +3209,7 @@ const struct Item gItemsInfo[] = "可梦的化石。好像\n" "是后背的一部分。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_FOSSIL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 100, @@ -3081,6 +3226,7 @@ const struct Item gItemsInfo[] = "先的化石。好像是\n" "翅膀的一部分。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_FOSSIL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 100, @@ -3097,6 +3243,7 @@ const struct Item gItemsInfo[] = "可梦的化石。好像\n" "是巨颚的一部分。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_FOSSIL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 100, @@ -3113,6 +3260,7 @@ const struct Item gItemsInfo[] = "梦的化石。好像是\n" "头鳍的一部分。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_FOSSIL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 100, @@ -3129,6 +3277,7 @@ const struct Item gItemsInfo[] = "石残片。本来面目\n" "至今是未解之谜。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_FOSSIL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 100, @@ -3142,6 +3291,7 @@ const struct Item gItemsInfo[] = .price = 5000, .description = sFossilizedFishDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_FOSSIL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 100, @@ -3158,6 +3308,7 @@ const struct Item gItemsInfo[] = "石残片。本来面目\n" "至今是未解之谜。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_FOSSIL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 100, @@ -3171,6 +3322,7 @@ const struct Item gItemsInfo[] = .price = 5000, .description = sFossilizedFishDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_FOSSIL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 100, @@ -3193,6 +3345,7 @@ const struct Item gItemsInfo[] = .description = sGenericMulchDesc, #endif .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_GROWTH, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = ITEM_TO_MULCH(ITEM_GROWTH_MULCH), @@ -3214,6 +3367,7 @@ const struct Item gItemsInfo[] = .description = sGenericMulchDesc, #endif .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_GROWTH, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = ITEM_TO_MULCH(ITEM_DAMP_MULCH), @@ -3235,6 +3389,7 @@ const struct Item gItemsInfo[] = .description = sGenericMulchDesc, #endif .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_GROWTH, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = ITEM_TO_MULCH(ITEM_STABLE_MULCH), @@ -3256,6 +3411,7 @@ const struct Item gItemsInfo[] = .description = sGenericMulchDesc, #endif .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_GROWTH, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = ITEM_TO_MULCH(ITEM_GOOEY_MULCH), @@ -3277,6 +3433,7 @@ const struct Item gItemsInfo[] = .description = sGenericMulchDesc, #endif .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_GROWTH, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = ITEM_TO_MULCH(ITEM_RICH_MULCH), @@ -3298,6 +3455,7 @@ const struct Item gItemsInfo[] = .description = sGenericMulchDesc, #endif .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_GROWTH, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = ITEM_TO_MULCH(ITEM_SURPRISE_MULCH), @@ -3319,6 +3477,7 @@ const struct Item gItemsInfo[] = .description = sGenericMulchDesc, #endif .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_GROWTH, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = ITEM_TO_MULCH(ITEM_BOOST_MULCH), @@ -3340,6 +3499,7 @@ const struct Item gItemsInfo[] = .description = sGenericMulchDesc, #endif .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_GROWTH, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = ITEM_TO_MULCH(ITEM_AMAZE_MULCH), @@ -3358,6 +3518,7 @@ const struct Item gItemsInfo[] = "红色的球果。有种\n" "刺鼻的气味。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_GROWTH, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .iconPic = gItemIcon_RedApricorn, @@ -3372,6 +3533,7 @@ const struct Item gItemsInfo[] = "蓝色的球果。略有\n" "一股青草的香味。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_GROWTH, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .iconPic = gItemIcon_BlueApricorn, @@ -3386,6 +3548,7 @@ const struct Item gItemsInfo[] = "黄色的球果。有种\n" "清爽的香味。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_GROWTH, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .iconPic = gItemIcon_YellowApricorn, @@ -3401,6 +3564,7 @@ const struct Item gItemsInfo[] = "焦香的香味,非常\n" "神奇。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_GROWTH, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .iconPic = gItemIcon_GreenApricorn, @@ -3416,6 +3580,7 @@ const struct Item gItemsInfo[] = "种甜甜的,好闻的\n" "香味。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_GROWTH, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .iconPic = gItemIcon_PinkApricorn, @@ -3430,6 +3595,7 @@ const struct Item gItemsInfo[] = "白色的球果。没有\n" "任何气味。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_GROWTH, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .iconPic = gItemIcon_WhiteApricorn, @@ -3444,6 +3610,7 @@ const struct Item gItemsInfo[] = "黑色的球果。有种\n" "无法形容的气味。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_GROWTH, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .iconPic = gItemIcon_BlackApricorn, @@ -3459,6 +3626,7 @@ const struct Item gItemsInfo[] = "穴里会吸引极巨化\n" "宝可梦。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_SELLABLE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, // Todo .flingPower = 50, @@ -3475,6 +3643,7 @@ const struct Item gItemsInfo[] = "可以用来制作某种\n" "宝可梦的饰品。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -3490,6 +3659,7 @@ const struct Item gItemsInfo[] = "能够在铠岛找出的\n" "珍稀石头。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -3505,6 +3675,7 @@ const struct Item gItemsInfo[] = "能够在王冠雪原找\n" "出的珍稀石头。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -3523,6 +3694,7 @@ const struct Item gItemsInfo[] = ",可以让宝可梦携\n" "带。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MAIL, .type = ITEM_USE_MAIL, .fieldUseFunc = ItemUseOutOfBattle_Mail, .secondaryId = ITEM_TO_MAIL(ITEM_ORANGE_MAIL), @@ -3539,6 +3711,7 @@ const struct Item gItemsInfo[] = ",可以让宝可梦携\n" "带。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MAIL, .type = ITEM_USE_MAIL, .fieldUseFunc = ItemUseOutOfBattle_Mail, .secondaryId = ITEM_TO_MAIL(ITEM_HARBOR_MAIL), @@ -3555,6 +3728,7 @@ const struct Item gItemsInfo[] = ",可以让宝可梦携\n" "带。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MAIL, .type = ITEM_USE_MAIL, .fieldUseFunc = ItemUseOutOfBattle_Mail, .secondaryId = ITEM_TO_MAIL(ITEM_GLITTER_MAIL), @@ -3571,6 +3745,7 @@ const struct Item gItemsInfo[] = ",可以让宝可梦携\n" "带。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MAIL, .type = ITEM_USE_MAIL, .fieldUseFunc = ItemUseOutOfBattle_Mail, .secondaryId = ITEM_TO_MAIL(ITEM_MECH_MAIL), @@ -3587,6 +3762,7 @@ const struct Item gItemsInfo[] = ",可以让宝可梦携\n" "带。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MAIL, .type = ITEM_USE_MAIL, .fieldUseFunc = ItemUseOutOfBattle_Mail, .secondaryId = ITEM_TO_MAIL(ITEM_WOOD_MAIL), @@ -3603,6 +3779,7 @@ const struct Item gItemsInfo[] = ",可以让宝可梦携\n" "带。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MAIL, .type = ITEM_USE_MAIL, .fieldUseFunc = ItemUseOutOfBattle_Mail, .secondaryId = ITEM_TO_MAIL(ITEM_WAVE_MAIL), @@ -3616,6 +3793,7 @@ const struct Item gItemsInfo[] = .price = 50, .description = sBeadMailDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MAIL, .type = ITEM_USE_MAIL, .fieldUseFunc = ItemUseOutOfBattle_Mail, .secondaryId = ITEM_TO_MAIL(ITEM_BEAD_MAIL), @@ -3632,6 +3810,7 @@ const struct Item gItemsInfo[] = ",可以让宝可梦携\n" "带。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MAIL, .type = ITEM_USE_MAIL, .fieldUseFunc = ItemUseOutOfBattle_Mail, .secondaryId = ITEM_TO_MAIL(ITEM_SHADOW_MAIL), @@ -3648,6 +3827,7 @@ const struct Item gItemsInfo[] = ",可以让宝可梦携\n" "带。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MAIL, .type = ITEM_USE_MAIL, .fieldUseFunc = ItemUseOutOfBattle_Mail, .secondaryId = ITEM_TO_MAIL(ITEM_TROPIC_MAIL), @@ -3661,6 +3841,7 @@ const struct Item gItemsInfo[] = .price = 50, .description = sBeadMailDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MAIL, .type = ITEM_USE_MAIL, .fieldUseFunc = ItemUseOutOfBattle_Mail, .secondaryId = ITEM_TO_MAIL(ITEM_DREAM_MAIL), @@ -3677,6 +3858,7 @@ const struct Item gItemsInfo[] = "可以让宝可梦携带\n" "。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MAIL, .type = ITEM_USE_MAIL, .fieldUseFunc = ItemUseOutOfBattle_Mail, .secondaryId = ITEM_TO_MAIL(ITEM_FAB_MAIL), @@ -3693,6 +3875,7 @@ const struct Item gItemsInfo[] = "信纸,可以让宝可\n" "梦携带。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MAIL, .type = ITEM_USE_MAIL, .fieldUseFunc = ItemUseOutOfBattle_Mail, .secondaryId = ITEM_TO_MAIL(ITEM_RETRO_MAIL), @@ -3708,6 +3891,7 @@ const struct Item gItemsInfo[] = .price = (I_PRICE >= GEN_7) ? 3000 : 2100, .description = sEvolutionStoneDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_STONE, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_EvolutionStone, .effect = gItemEffect_EvoItem, @@ -3722,6 +3906,7 @@ const struct Item gItemsInfo[] = .price = (I_PRICE >= GEN_7) ? 3000 : 2100, .description = sEvolutionStoneDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_STONE, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_EvolutionStone, .effect = gItemEffect_EvoItem, @@ -3736,6 +3921,7 @@ const struct Item gItemsInfo[] = .price = (I_PRICE >= GEN_7) ? 3000 : 2100, .description = sEvolutionStoneDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_STONE, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_EvolutionStone, .effect = gItemEffect_EvoItem, @@ -3750,6 +3936,7 @@ const struct Item gItemsInfo[] = .price = (I_PRICE >= GEN_7) ? 3000 : 2100, .description = sEvolutionStoneDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_STONE, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_EvolutionStone, .effect = gItemEffect_EvoItem, @@ -3764,6 +3951,7 @@ const struct Item gItemsInfo[] = .price = (I_PRICE >= GEN_7) ? 3000 : 2100, .description = sEvolutionStoneDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_STONE, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_EvolutionStone, .effect = gItemEffect_EvoItem, @@ -3778,6 +3966,7 @@ const struct Item gItemsInfo[] = .price = (I_PRICE >= GEN_7) ? 3000 : 2100, .description = sEvolutionStoneDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_STONE, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_EvolutionStone, .effect = gItemEffect_EvoItem, @@ -3792,6 +3981,7 @@ const struct Item gItemsInfo[] = .price = (I_PRICE >= GEN_7) ? 3000 : 2100, .description = sEvolutionStoneDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_STONE, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_EvolutionStone, .effect = gItemEffect_EvoItem, @@ -3806,6 +3996,7 @@ const struct Item gItemsInfo[] = .price = (I_PRICE >= GEN_7) ? 3000 : 2100, .description = sEvolutionStoneDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_STONE, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_EvolutionStone, .effect = gItemEffect_EvoItem, @@ -3820,6 +4011,7 @@ const struct Item gItemsInfo[] = .price = (I_PRICE >= GEN_7) ? 3000 : 2100, .description = sEvolutionStoneDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_STONE, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_EvolutionStone, .effect = gItemEffect_EvoItem, @@ -3834,6 +4026,7 @@ const struct Item gItemsInfo[] = .price = (I_PRICE >= GEN_7) ? 3000 : 2100, .description = sEvolutionStoneDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_STONE, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_EvolutionStone, .effect = gItemEffect_EvoItem, @@ -3851,6 +4044,7 @@ const struct Item gItemsInfo[] = "以使特定的宝可梦\n" "进化。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_EvolutionStone, .effect = gItemEffect_EvoItem, @@ -3868,6 +4062,7 @@ const struct Item gItemsInfo[] = "以使特定的宝可梦\n" "进化。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_EvolutionStone, .effect = gItemEffect_EvoItem, @@ -3885,6 +4080,7 @@ const struct Item gItemsInfo[] = "有破裂,可以使特\n" "定的宝可梦进化。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_EvolutionStone, .effect = gItemEffect_EvoItem, @@ -3902,6 +4098,7 @@ const struct Item gItemsInfo[] = "有缺陷,可以使特\n" "定的宝可梦进化。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_EvolutionStone, .effect = gItemEffect_EvoItem, @@ -3919,6 +4116,7 @@ const struct Item gItemsInfo[] = "手环。伽勒尔呆呆\n" "兽戴上会很开心。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_EvolutionStone, .effect = gItemEffect_EvoItem, @@ -3936,6 +4134,7 @@ const struct Item gItemsInfo[] = "花冠。伽勒尔呆呆\n" "兽戴上会很开心。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_EvolutionStone, .effect = gItemEffect_EvoItem, @@ -3955,6 +4154,7 @@ const struct Item gItemsInfo[] = "。龙属性宝可梦有\n" "时会携带它。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = EVO_HELD_ITEM_TYPE, .fieldUseFunc = EVO_HELD_ITEM_FIELD_FUNC, .effect = gItemEffect_EvoItem, @@ -3973,6 +4173,7 @@ const struct Item gItemsInfo[] = "息的透明机器。西\n" "尔佛公司制造。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = EVO_HELD_ITEM_TYPE, .fieldUseFunc = EVO_HELD_ITEM_FIELD_FUNC, .effect = gItemEffect_EvoItem, @@ -3990,6 +4191,7 @@ const struct Item gItemsInfo[] = "硬而且沉重。某种\n" "宝可梦很喜欢它。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = EVO_HELD_ITEM_TYPE, .fieldUseFunc = EVO_HELD_ITEM_FIELD_FUNC, .effect = gItemEffect_EvoItem, @@ -4007,6 +4209,7 @@ const struct Item gItemsInfo[] = "量的箱子。某种宝\n" "可梦很喜欢它。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = EVO_HELD_ITEM_TYPE, .fieldUseFunc = EVO_HELD_ITEM_FIELD_FUNC, .effect = gItemEffect_EvoItem, @@ -4024,6 +4227,7 @@ const struct Item gItemsInfo[] = "量的箱子。某种宝\n" "可梦很喜欢它。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = EVO_HELD_ITEM_TYPE, .fieldUseFunc = EVO_HELD_ITEM_FIELD_FUNC, .effect = gItemEffect_EvoItem, @@ -4041,6 +4245,7 @@ const struct Item gItemsInfo[] = "息的透明机器。制\n" "造者不明。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = EVO_HELD_ITEM_TYPE, .fieldUseFunc = EVO_HELD_ITEM_FIELD_FUNC, .effect = gItemEffect_EvoItem, @@ -4058,6 +4263,7 @@ const struct Item gItemsInfo[] = "力的布。某种宝可\n" "梦很喜欢它。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = EVO_HELD_ITEM_TYPE, .fieldUseFunc = EVO_HELD_ITEM_FIELD_FUNC, .effect = gItemEffect_EvoItem, @@ -4075,6 +4281,7 @@ const struct Item gItemsInfo[] = "化的神奇鳞片。散\n" "发着虹色光辉。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = EVO_HELD_ITEM_TYPE, .fieldUseFunc = EVO_HELD_ITEM_FIELD_FUNC, .effect = gItemEffect_EvoItem, @@ -4092,6 +4299,7 @@ const struct Item gItemsInfo[] = "甜的奶油。某种宝\n" "可梦很喜欢它。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = EVO_HELD_ITEM_TYPE, .fieldUseFunc = EVO_HELD_ITEM_FIELD_FUNC, .effect = gItemEffect_EvoItem, @@ -4109,6 +4317,7 @@ const struct Item gItemsInfo[] = "料的袋子。某种宝\n" "可梦很喜欢它。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = EVO_HELD_ITEM_TYPE, .fieldUseFunc = EVO_HELD_ITEM_FIELD_FUNC, .effect = gItemEffect_EvoItem, @@ -4126,6 +4335,7 @@ const struct Item gItemsInfo[] = "化的神奇石头。像\n" "珠子一般圆润。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = EVO_HELD_ITEM_TYPE, .fieldUseFunc = EVO_HELD_ITEM_FIELD_FUNC, .effect = gItemEffect_EvoItem, @@ -4143,6 +4353,7 @@ const struct Item gItemsInfo[] = "果。小仙奶非常喜\n" "欢。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -4159,6 +4370,7 @@ const struct Item gItemsInfo[] = "果。小仙奶非常喜\n" "欢。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -4175,6 +4387,7 @@ const struct Item gItemsInfo[] = "果。小仙奶非常喜\n" "欢。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -4191,6 +4404,7 @@ const struct Item gItemsInfo[] = "糖果。小仙奶非常\n" "喜欢。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -4207,6 +4421,7 @@ const struct Item gItemsInfo[] = "果。小仙奶非常喜\n" "欢。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -4223,6 +4438,7 @@ const struct Item gItemsInfo[] = "果。小仙奶非常喜\n" "欢。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -4239,6 +4455,7 @@ const struct Item gItemsInfo[] = "糖果。小仙奶非常\n" "喜欢。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -4256,6 +4473,7 @@ const struct Item gItemsInfo[] = "此期间不会进化的\n" "神奇石头。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -4272,6 +4490,7 @@ const struct Item gItemsInfo[] = .holdEffectParam = 0, .description = sNectarDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_NECTAR, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_FormChange_ConsumedOnUse, .flingPower = 10, @@ -4286,6 +4505,7 @@ const struct Item gItemsInfo[] = .holdEffectParam = 0, .description = sNectarDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_NECTAR, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_FormChange_ConsumedOnUse, .flingPower = 10, @@ -4300,6 +4520,7 @@ const struct Item gItemsInfo[] = .holdEffectParam = 0, .description = sNectarDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_NECTAR, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_FormChange_ConsumedOnUse, .flingPower = 10, @@ -4314,6 +4535,7 @@ const struct Item gItemsInfo[] = .holdEffectParam = 0, .description = sNectarDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_NECTAR, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_FormChange_ConsumedOnUse, .flingPower = 10, @@ -4334,6 +4556,7 @@ const struct Item gItemsInfo[] = "带后,火招式威力\n" "会增强。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_PLATE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_FIRE, @@ -4353,6 +4576,7 @@ const struct Item gItemsInfo[] = "带后,水招式威力\n" "会增强。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_PLATE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_WATER, @@ -4372,6 +4596,7 @@ const struct Item gItemsInfo[] = "带后,电招式威力\n" "会增强。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_PLATE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_ELECTRIC, @@ -4391,6 +4616,7 @@ const struct Item gItemsInfo[] = "带后,草招式威力\n" "会增强。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_PLATE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_GRASS, @@ -4410,6 +4636,7 @@ const struct Item gItemsInfo[] = "带后,冰招式威力\n" "会增强。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_PLATE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_ICE, @@ -4429,6 +4656,7 @@ const struct Item gItemsInfo[] = "携带后,格斗招式\n" "威力会增强。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_PLATE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_FIGHTING, @@ -4448,6 +4676,7 @@ const struct Item gItemsInfo[] = "带后,毒招式威力\n" "会增强。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_PLATE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_POISON, @@ -4467,6 +4696,7 @@ const struct Item gItemsInfo[] = "携带后,地面招式\n" "威力会增强。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_PLATE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_GROUND, @@ -4486,6 +4716,7 @@ const struct Item gItemsInfo[] = "携带后,飞行招式\n" "威力会增强。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_PLATE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_FLYING, @@ -4505,6 +4736,7 @@ const struct Item gItemsInfo[] = "携带后,超能招式\n" "威力会增强。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_PLATE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_PSYCHIC, @@ -4524,6 +4756,7 @@ const struct Item gItemsInfo[] = "带后,虫招式威力\n" "会增强。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_PLATE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_BUG, @@ -4543,6 +4776,7 @@ const struct Item gItemsInfo[] = "携带后,岩石招式\n" "威力会增强。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_PLATE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_ROCK, @@ -4562,6 +4796,7 @@ const struct Item gItemsInfo[] = "携带后,幽灵招式\n" "威力会增强。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_PLATE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_GHOST, @@ -4581,6 +4816,7 @@ const struct Item gItemsInfo[] = "带后,龙招式威力\n" "会增强。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_PLATE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_DRAGON, @@ -4600,6 +4836,7 @@ const struct Item gItemsInfo[] = "带后,恶招式威力\n" "会增强。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_PLATE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_DARK, @@ -4619,6 +4856,7 @@ const struct Item gItemsInfo[] = "带后,钢招式威力\n" "会增强。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_PLATE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_STEEL, @@ -4638,6 +4876,7 @@ const struct Item gItemsInfo[] = "携带后,妖精招式\n" "威力会增强。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_PLATE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_FAIRY, @@ -4658,6 +4897,7 @@ const struct Item gItemsInfo[] = "特的某招式就会变\n" "为水属性。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_DRIVE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_WATER, @@ -4676,6 +4916,7 @@ const struct Item gItemsInfo[] = "特的某招式就会变\n" "为电属性。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_DRIVE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_ELECTRIC, @@ -4694,6 +4935,7 @@ const struct Item gItemsInfo[] = "特的某招式就会变\n" "为火属性。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_DRIVE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_FIRE, @@ -4712,6 +4954,7 @@ const struct Item gItemsInfo[] = "特的某招式就会变\n" "为冰属性。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_DRIVE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_ICE, @@ -4733,6 +4976,7 @@ const struct Item gItemsInfo[] = "碟。某宝可梦携带\n" "后属性会变化。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEMORY, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_FIRE, @@ -4752,6 +4996,7 @@ const struct Item gItemsInfo[] = "碟。某宝可梦携带\n" "后属性会变化。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEMORY, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_WATER, @@ -4771,6 +5016,7 @@ const struct Item gItemsInfo[] = "碟。某宝可梦携带\n" "后属性会变化。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEMORY, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_ELECTRIC, @@ -4790,6 +5036,7 @@ const struct Item gItemsInfo[] = "碟。某宝可梦携带\n" "后属性会变化。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEMORY, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_GRASS, @@ -4809,6 +5056,7 @@ const struct Item gItemsInfo[] = "碟。某宝可梦携带\n" "后属性会变化。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEMORY, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_ICE, @@ -4828,6 +5076,7 @@ const struct Item gItemsInfo[] = "储碟。某宝可梦携\n" "带后属性会变化。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEMORY, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_FIGHTING, @@ -4847,6 +5096,7 @@ const struct Item gItemsInfo[] = "碟。某宝可梦携带\n" "后属性会变化。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEMORY, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_POISON, @@ -4866,6 +5116,7 @@ const struct Item gItemsInfo[] = "储碟。某宝可梦携\n" "带后属性会变化。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEMORY, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_GROUND, @@ -4885,6 +5136,7 @@ const struct Item gItemsInfo[] = "储碟。某宝可梦携\n" "带后属性会变化。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEMORY, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_FLYING, @@ -4904,6 +5156,7 @@ const struct Item gItemsInfo[] = "储碟。某宝可梦携\n" "带后属性会变化。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEMORY, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_PSYCHIC, @@ -4923,6 +5176,7 @@ const struct Item gItemsInfo[] = "碟。某宝可梦携带\n" "后属性会变化。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEMORY, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_BUG, @@ -4942,6 +5196,7 @@ const struct Item gItemsInfo[] = "储碟。某宝可梦携\n" "带后属性会变化。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEMORY, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_ROCK, @@ -4961,6 +5216,7 @@ const struct Item gItemsInfo[] = "储碟。某宝可梦携\n" "带后属性会变化。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEMORY, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_GHOST, @@ -4980,6 +5236,7 @@ const struct Item gItemsInfo[] = "碟。某宝可梦携带\n" "后属性会变化。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEMORY, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_DRAGON, @@ -4999,6 +5256,7 @@ const struct Item gItemsInfo[] = "碟。某宝可梦携带\n" "后属性会变化。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEMORY, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_DARK, @@ -5018,6 +5276,7 @@ const struct Item gItemsInfo[] = "碟。某宝可梦携带\n" "后属性会变化。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEMORY, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_STEEL, @@ -5037,6 +5296,7 @@ const struct Item gItemsInfo[] = "储碟。某宝可梦携\n" "带后属性会变化。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEMORY, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_FAIRY, @@ -5054,6 +5314,7 @@ const struct Item gItemsInfo[] = "的剑。而现在早已\n" "变得锈迹斑斑。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_SPECIAL_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .iconPic = gItemIcon_RustedSword, @@ -5069,6 +5330,7 @@ const struct Item gItemsInfo[] = "的盾。而现在早已\n" "变得锈迹斑斑。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_SPECIAL_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .iconPic = gItemIcon_RustedShield, @@ -5087,6 +5349,7 @@ const struct Item gItemsInfo[] = "宝珠。据说和丰缘\n" "传说渊源颇深。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_SPECIAL_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .iconPic = gItemIcon_RedOrb, @@ -5103,6 +5366,7 @@ const struct Item gItemsInfo[] = "宝珠。据说和丰缘\n" "传说渊源颇深。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_SPECIAL_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .iconPic = gItemIcon_BlueOrb, @@ -5121,6 +5385,7 @@ const struct Item gItemsInfo[] = "在战斗时能超级进\n" "化的超级石。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5135,6 +5400,7 @@ const struct Item gItemsInfo[] = .holdEffect = HOLD_EFFECT_MEGA_STONE, .description = sCharizarditeDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5149,6 +5415,7 @@ const struct Item gItemsInfo[] = .holdEffect = HOLD_EFFECT_MEGA_STONE, .description = sCharizarditeDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5166,6 +5433,7 @@ const struct Item gItemsInfo[] = "在战斗时能超级进\n" "化的超级石。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5183,6 +5451,7 @@ const struct Item gItemsInfo[] = "战斗时能超级进化\n" "的超级石。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5200,6 +5469,7 @@ const struct Item gItemsInfo[] = "在战斗时能超级进\n" "化的超级石。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5217,6 +5487,7 @@ const struct Item gItemsInfo[] = "战斗时能超级进化\n" "的超级石。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5234,6 +5505,7 @@ const struct Item gItemsInfo[] = "在战斗时能超级进\n" "化的超级石。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5251,6 +5523,7 @@ const struct Item gItemsInfo[] = "战斗时能超级进化\n" "的超级石。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5268,6 +5541,7 @@ const struct Item gItemsInfo[] = "战斗时能超级进化\n" "的超级石。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5285,6 +5559,7 @@ const struct Item gItemsInfo[] = "在战斗时能超级进\n" "化的超级石。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5302,6 +5577,7 @@ const struct Item gItemsInfo[] = "在战斗时能超级进\n" "化的超级石。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5319,6 +5595,7 @@ const struct Item gItemsInfo[] = ",在战斗时能超级\n" "进化的超级石。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5333,6 +5610,7 @@ const struct Item gItemsInfo[] = .holdEffect = HOLD_EFFECT_MEGA_STONE, .description = sMewtwoniteDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5347,6 +5625,7 @@ const struct Item gItemsInfo[] = .holdEffect = HOLD_EFFECT_MEGA_STONE, .description = sMewtwoniteDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5364,6 +5643,7 @@ const struct Item gItemsInfo[] = "斗时就能超级进化\n" "的超级石。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5381,6 +5661,7 @@ const struct Item gItemsInfo[] = "在战斗时能超级进\n" "化的超级石。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5398,6 +5679,7 @@ const struct Item gItemsInfo[] = ",在战斗时能超级\n" "进化的超级石。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5415,6 +5697,7 @@ const struct Item gItemsInfo[] = "后,在战斗时能超\n" "级进化的超级石。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5432,6 +5715,7 @@ const struct Item gItemsInfo[] = "在战斗时能超级进\n" "化的超级石。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5449,6 +5733,7 @@ const struct Item gItemsInfo[] = ",在战斗时能超级\n" "进化的超级石。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5466,6 +5751,7 @@ const struct Item gItemsInfo[] = "在战斗时能超级进\n" "化的超级石。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5483,6 +5769,7 @@ const struct Item gItemsInfo[] = "在战斗时能超级进\n" "化的超级石。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5500,6 +5787,7 @@ const struct Item gItemsInfo[] = "在战斗时能超级进\n" "化的超级石。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5517,6 +5805,7 @@ const struct Item gItemsInfo[] = "在战斗时能超级进\n" "化的超级石。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5534,6 +5823,7 @@ const struct Item gItemsInfo[] = "在战斗时能超级进\n" "化的超级石。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5551,6 +5841,7 @@ const struct Item gItemsInfo[] = "在战斗时能超级进\n" "化的超级石。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5568,6 +5859,7 @@ const struct Item gItemsInfo[] = "后,在战斗时能超\n" "级进化的超级石。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5585,6 +5877,7 @@ const struct Item gItemsInfo[] = "在战斗时能超级进\n" "化的超级石。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5602,6 +5895,7 @@ const struct Item gItemsInfo[] = "在战斗时能超级进\n" "化的超级石。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5619,6 +5913,7 @@ const struct Item gItemsInfo[] = "在战斗时能超级进\n" "化的超级石。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5636,6 +5931,7 @@ const struct Item gItemsInfo[] = "战斗时能超级进化\n" "的超级石。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5653,6 +5949,7 @@ const struct Item gItemsInfo[] = ",在战斗时能超级\n" "进化的超级石。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5670,6 +5967,7 @@ const struct Item gItemsInfo[] = ",在战斗时能超级\n" "进化的超级石。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5687,6 +5985,7 @@ const struct Item gItemsInfo[] = ",在战斗时能超级\n" "进化的超级石。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5704,6 +6003,7 @@ const struct Item gItemsInfo[] = "在战斗时能超级进\n" "化的超级石。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5721,6 +6021,7 @@ const struct Item gItemsInfo[] = "战斗时能超级进化\n" "的超级石。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5738,6 +6039,7 @@ const struct Item gItemsInfo[] = "在战斗时能超级进\n" "化的超级石。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5755,6 +6057,7 @@ const struct Item gItemsInfo[] = ",在战斗时能超级\n" "进化的超级石。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5772,6 +6075,7 @@ const struct Item gItemsInfo[] = ",在战斗时能超级\n" "进化的超级石。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5789,6 +6093,7 @@ const struct Item gItemsInfo[] = "战斗时能超级进化\n" "的超级石。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5806,6 +6111,7 @@ const struct Item gItemsInfo[] = ",在战斗时能超级\n" "进化的超级石。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5823,6 +6129,7 @@ const struct Item gItemsInfo[] = ",在战斗时能超级\n" "进化的超级石。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5840,6 +6147,7 @@ const struct Item gItemsInfo[] = "在战斗时能超级进\n" "化的超级石。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5857,6 +6165,7 @@ const struct Item gItemsInfo[] = ",在战斗时能超级\n" "进化的超级石。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5874,6 +6183,7 @@ const struct Item gItemsInfo[] = "后,在战斗时能超\n" "级进化的超级石。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5892,12 +6202,463 @@ const struct Item gItemsInfo[] = "化的超级石。"), .pocket = POCKET_ITEMS, .type = ITEM_USE_BAG_MENU, + .sortType = ITEM_TYPE_MEGA_STONE, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, .iconPic = gItemIcon_Diancite, .iconPalette = gItemIconPalette_Diancite, }, + [ITEM_CLEFABLITE] = + { + .name = ITEM_NAME("Clefablite"), + .price = 0, + .holdEffect = HOLD_EFFECT_MEGA_STONE, + .description = COMPOUND_STRING( + "This stone enables\n" + "Diancie to Mega\n" + "Evolve in battle."), + .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, + .type = ITEM_USE_BAG_MENU, + .fieldUseFunc = ItemUseOutOfBattle_CannotUse, + .flingPower = 80, + .iconPic = gItemIcon_QuestionMark, // gItemIcon_Victreebelite, + .iconPalette = gItemIconPalette_QuestionMark, // gItemIconPalette_Victreebelite, + }, + + [ITEM_STARMINITE] = + { + .name = ITEM_NAME("Starminite"), + .price = 0, + .holdEffect = HOLD_EFFECT_MEGA_STONE, + .description = COMPOUND_STRING( + "This stone enables\n" + "Starmie to Mega\n" + "Evolve in battle."), + .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, + .type = ITEM_USE_BAG_MENU, + .fieldUseFunc = ItemUseOutOfBattle_CannotUse, + .flingPower = 80, + .iconPic = gItemIcon_QuestionMark, // gItemIcon_Starminite, + .iconPalette = gItemIconPalette_QuestionMark, // gItemIconPalette_Starminite, + }, + + [ITEM_DRAGONINITE] = + { + .name = ITEM_NAME("Dragoninite"), + .price = 0, + .holdEffect = HOLD_EFFECT_MEGA_STONE, + .description = COMPOUND_STRING( + "This stone enables\n" + "Dragonite to Mega\n" + "Evolve in battle."), + .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, + .type = ITEM_USE_BAG_MENU, + .fieldUseFunc = ItemUseOutOfBattle_CannotUse, + .flingPower = 80, + .iconPic = gItemIcon_QuestionMark, // gItemIcon_Dragoninite, + .iconPalette = gItemIconPalette_QuestionMark, // gItemIconPalette_Dragoninite, + }, + + [ITEM_MEGANIUMITE] = + { + .name = ITEM_NAME("Meganiumite"), + .price = 0, + .holdEffect = HOLD_EFFECT_MEGA_STONE, + .description = COMPOUND_STRING( + "This stone enables\n" + "Meganium to Mega\n" + "Evolve in battle."), + .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, + .type = ITEM_USE_BAG_MENU, + .fieldUseFunc = ItemUseOutOfBattle_CannotUse, + .flingPower = 80, + .iconPic = gItemIcon_QuestionMark, // gItemIcon_Meganiumite, + .iconPalette = gItemIconPalette_QuestionMark, // gItemIconPalette_Meganiumite, + }, + + [ITEM_FERALIGITE] = + { + .name = ITEM_NAME("Feraligite"), + .price = 0, + .holdEffect = HOLD_EFFECT_MEGA_STONE, + .description = COMPOUND_STRING( + "This stone enables\n" + "Feraligatr to Mega\n" + "Evolve in battle."), + .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, + .type = ITEM_USE_BAG_MENU, + .fieldUseFunc = ItemUseOutOfBattle_CannotUse, + .flingPower = 80, + .iconPic = gItemIcon_QuestionMark, // gItemIcon_Feraligite, + .iconPalette = gItemIconPalette_QuestionMark, // gItemIconPalette_Feraligite, + }, + + [ITEM_SKARMORITE] = + { + .name = ITEM_NAME("Skarmorite"), + .price = 0, + .holdEffect = HOLD_EFFECT_MEGA_STONE, + .description = COMPOUND_STRING( + "This stone enables\n" + "Skarmory to Mega\n" + "Evolve in battle."), + .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, + .type = ITEM_USE_BAG_MENU, + .fieldUseFunc = ItemUseOutOfBattle_CannotUse, + .flingPower = 80, + .iconPic = gItemIcon_QuestionMark, // gItemIcon_Skarmorite, + .iconPalette = gItemIconPalette_QuestionMark, // gItemIconPalette_Skarmorite, + }, + + [ITEM_FROSLASSITE] = + { + .name = ITEM_NAME("Froslassite"), + .price = 0, + .holdEffect = HOLD_EFFECT_MEGA_STONE, + .description = COMPOUND_STRING( + "This stone enables\n" + "Froslass to Mega\n" + "Evolve in battle."), + .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, + .type = ITEM_USE_BAG_MENU, + .fieldUseFunc = ItemUseOutOfBattle_CannotUse, + .flingPower = 80, + .iconPic = gItemIcon_QuestionMark, // gItemIcon_Froslassite, + .iconPalette = gItemIconPalette_QuestionMark, // gItemIconPalette_Froslassite, + }, + + [ITEM_EMBOARITE] = + { + .name = ITEM_NAME("Emboarite"), + .price = 0, + .holdEffect = HOLD_EFFECT_MEGA_STONE, + .description = COMPOUND_STRING( + "This stone enables\n" + "Emboar to Mega\n" + "Evolve in battle."), + .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, + .type = ITEM_USE_BAG_MENU, + .fieldUseFunc = ItemUseOutOfBattle_CannotUse, + .flingPower = 80, + .iconPic = gItemIcon_QuestionMark, // gItemIcon_Emboarite, + .iconPalette = gItemIconPalette_QuestionMark, // gItemIconPalette_Emboarite, + }, + + [ITEM_EXCADRITE] = + { + .name = ITEM_NAME("Excadrite"), + .price = 0, + .holdEffect = HOLD_EFFECT_MEGA_STONE, + .description = COMPOUND_STRING( + "This stone enables\n" + "Excadrill to Mega\n" + "Evolve in battle."), + .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, + .type = ITEM_USE_BAG_MENU, + .fieldUseFunc = ItemUseOutOfBattle_CannotUse, + .flingPower = 80, + .iconPic = gItemIcon_QuestionMark, // gItemIcon_Excadrite, + .iconPalette = gItemIconPalette_QuestionMark, // gItemIconPalette_Excadrite, + }, + + [ITEM_SCOLIPITE] = + { + .name = ITEM_NAME("Scolipite"), + .price = 0, + .holdEffect = HOLD_EFFECT_MEGA_STONE, + .description = COMPOUND_STRING( + "This stone enables\n" + "Scolipede to Mega\n" + "Evolve in battle."), + .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, + .type = ITEM_USE_BAG_MENU, + .fieldUseFunc = ItemUseOutOfBattle_CannotUse, + .flingPower = 80, + .iconPic = gItemIcon_QuestionMark, // gItemIcon_Scolipite, + .iconPalette = gItemIconPalette_QuestionMark, // gItemIconPalette_Scolipite, + }, + + [ITEM_SCRAFTINITE] = + { + .name = ITEM_NAME("Scraftinite"), + .price = 0, + .holdEffect = HOLD_EFFECT_MEGA_STONE, + .description = COMPOUND_STRING( + "This stone enables\n" + "Scrafty to Mega\n" + "Evolve in battle."), + .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, + .type = ITEM_USE_BAG_MENU, + .fieldUseFunc = ItemUseOutOfBattle_CannotUse, + .flingPower = 80, + .iconPic = gItemIcon_QuestionMark, // gItemIcon_Scraftinite, + .iconPalette = gItemIconPalette_QuestionMark, // gItemIconPalette_Scraftinite, + }, + + [ITEM_EELEKTROSSITE] = + { + .name = ITEM_NAME("Eelektrossite"), + .price = 0, + .holdEffect = HOLD_EFFECT_MEGA_STONE, + .description = COMPOUND_STRING( + "This stone enables\n" + "Eelektross to Mega\n" + "Evolve in battle."), + .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, + .type = ITEM_USE_BAG_MENU, + .fieldUseFunc = ItemUseOutOfBattle_CannotUse, + .flingPower = 80, + .iconPic = gItemIcon_QuestionMark, // gItemIcon_Eelektrossite, + .iconPalette = gItemIconPalette_QuestionMark, // gItemIconPalette_Eelektrossite, + }, + + [ITEM_CHANDELURITE] = + { + .name = ITEM_NAME("Chandelurite"), + .price = 0, + .holdEffect = HOLD_EFFECT_MEGA_STONE, + .description = COMPOUND_STRING( + "This stone enables\n" + "Chandelure to Mega\n" + "Evolve in battle."), + .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, + .type = ITEM_USE_BAG_MENU, + .fieldUseFunc = ItemUseOutOfBattle_CannotUse, + .flingPower = 80, + .iconPic = gItemIcon_QuestionMark, // gItemIcon_Chandelurite, + .iconPalette = gItemIconPalette_QuestionMark, // gItemIconPalette_Chandelurite, + }, + + [ITEM_CHESNAUGHTITE] = + { + .name = ITEM_NAME("Chesnaughtite"), + .price = 0, + .holdEffect = HOLD_EFFECT_MEGA_STONE, + .description = COMPOUND_STRING( + "This stone enables\n" + "Chesnaught to Mega\n" + "Evolve in battle."), + .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, + .type = ITEM_USE_BAG_MENU, + .fieldUseFunc = ItemUseOutOfBattle_CannotUse, + .flingPower = 80, + .iconPic = gItemIcon_QuestionMark, // gItemIcon_Chesnaughtite, + .iconPalette = gItemIconPalette_QuestionMark, // gItemIconPalette_Chesnaughtite, + }, + + [ITEM_DELPHOXITE] = + { + .name = ITEM_NAME("Delphoxite"), + .price = 0, + .holdEffect = HOLD_EFFECT_MEGA_STONE, + .description = COMPOUND_STRING( + "This stone enables\n" + "Delphox to Mega\n" + "Evolve in battle."), + .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, + .type = ITEM_USE_BAG_MENU, + .fieldUseFunc = ItemUseOutOfBattle_CannotUse, + .flingPower = 80, + .iconPic = gItemIcon_QuestionMark, // gItemIcon_Delphoxite, + .iconPalette = gItemIconPalette_QuestionMark, // gItemIconPalette_Delphoxite, + }, + + [ITEM_GRENINJITE] = + { + .name = ITEM_NAME("Greninjite"), + .price = 0, + .holdEffect = HOLD_EFFECT_MEGA_STONE, + .description = COMPOUND_STRING( + "This stone enables\n" + "Greninja to Mega\n" + "Evolve in battle."), + .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, + .type = ITEM_USE_BAG_MENU, + .fieldUseFunc = ItemUseOutOfBattle_CannotUse, + .flingPower = 80, + .iconPic = gItemIcon_QuestionMark, // gItemIcon_Greninjite, + .iconPalette = gItemIconPalette_QuestionMark, // gItemIconPalette_Greninjite, + }, + + [ITEM_PYROARITE] = + { + .name = ITEM_NAME("Pyroarite"), + .price = 0, + .holdEffect = HOLD_EFFECT_MEGA_STONE, + .description = COMPOUND_STRING( + "This stone enables\n" + "Pyroar to Mega\n" + "Evolve in battle."), + .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, + .type = ITEM_USE_BAG_MENU, + .fieldUseFunc = ItemUseOutOfBattle_CannotUse, + .flingPower = 80, + .iconPic = gItemIcon_QuestionMark, // gItemIcon_Pyroarite, + .iconPalette = gItemIconPalette_QuestionMark, // gItemIconPalette_Pyroarite, + }, + + [ITEM_FLOETTITE] = + { + .name = ITEM_NAME("Floettite"), + .price = 0, + .holdEffect = HOLD_EFFECT_MEGA_STONE, + .description = COMPOUND_STRING( + "This stone enables\n" + "Floette to Mega\n" + "Evolve in battle."), + .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, + .type = ITEM_USE_BAG_MENU, + .fieldUseFunc = ItemUseOutOfBattle_CannotUse, + .flingPower = 80, + .iconPic = gItemIcon_QuestionMark, // gItemIcon_Floettite, + .iconPalette = gItemIconPalette_QuestionMark, // gItemIconPalette_Floettite, + }, + + [ITEM_MALAMARITE] = + { + .name = ITEM_NAME("Malamarite"), + .price = 0, + .holdEffect = HOLD_EFFECT_MEGA_STONE, + .description = COMPOUND_STRING( + "This stone enables\n" + "Malamar to Mega\n" + "Evolve in battle."), + .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, + .type = ITEM_USE_BAG_MENU, + .fieldUseFunc = ItemUseOutOfBattle_CannotUse, + .flingPower = 80, + .iconPic = gItemIcon_QuestionMark, // gItemIcon_Malamarite, + .iconPalette = gItemIconPalette_QuestionMark, // gItemIconPalette_Malamarite, + }, + + [ITEM_BARBARACITE] = + { + .name = ITEM_NAME("Barbaracite"), + .price = 0, + .holdEffect = HOLD_EFFECT_MEGA_STONE, + .description = COMPOUND_STRING( + "This stone enables\n" + "Barbaracle to Mega\n" + "Evolve in battle."), + .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, + .type = ITEM_USE_BAG_MENU, + .fieldUseFunc = ItemUseOutOfBattle_CannotUse, + .flingPower = 80, + .iconPic = gItemIcon_QuestionMark, // gItemIcon_Barbaracite, + .iconPalette = gItemIconPalette_QuestionMark, // gItemIconPalette_Barbaracite, + }, + + [ITEM_DRAGALGITE] = + { + .name = ITEM_NAME("Dragalgite"), + .price = 0, + .holdEffect = HOLD_EFFECT_MEGA_STONE, + .description = COMPOUND_STRING( + "This stone enables\n" + "Dragalge to Mega\n" + "Evolve in battle."), + .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, + .type = ITEM_USE_BAG_MENU, + .fieldUseFunc = ItemUseOutOfBattle_CannotUse, + .flingPower = 80, + .iconPic = gItemIcon_QuestionMark, // gItemIcon_Dragalgite, + .iconPalette = gItemIconPalette_QuestionMark, // gItemIconPalette_Dragalgite, + }, + + [ITEM_HAWLUCHANITE] = + { + .name = ITEM_NAME("Hawluchanite"), + .price = 0, + .holdEffect = HOLD_EFFECT_MEGA_STONE, + .description = COMPOUND_STRING( + "This stone enables\n" + "Hawlucha to Mega\n" + "Evolve in battle."), + .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, + .type = ITEM_USE_BAG_MENU, + .fieldUseFunc = ItemUseOutOfBattle_CannotUse, + .flingPower = 80, + .iconPic = gItemIcon_QuestionMark, // gItemIcon_Hawluchanite, + .iconPalette = gItemIconPalette_QuestionMark, // gItemIconPalette_Hawluchanite, + }, + + [ITEM_ZYGARDITE] = + { + .name = ITEM_NAME("Zygardite"), + .price = 0, + .holdEffect = HOLD_EFFECT_MEGA_STONE, + .description = COMPOUND_STRING( + "This stone enables\n" + "Zygarde to Mega\n" + "Evolve in battle."), + .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, + .type = ITEM_USE_BAG_MENU, + .fieldUseFunc = ItemUseOutOfBattle_CannotUse, + .flingPower = 80, + .iconPic = gItemIcon_QuestionMark, // gItemIcon_Zygardite, + .iconPalette = gItemIconPalette_QuestionMark, // gItemIconPalette_Zygardite, + }, + + [ITEM_DRAMPANITE] = + { + .name = ITEM_NAME("Drampanite"), + .price = 0, + .holdEffect = HOLD_EFFECT_MEGA_STONE, + .description = COMPOUND_STRING( + "This stone enables\n" + "Drampa to Mega\n" + "Evolve in battle."), + .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, + .type = ITEM_USE_BAG_MENU, + .fieldUseFunc = ItemUseOutOfBattle_CannotUse, + .flingPower = 80, + .iconPic = gItemIcon_QuestionMark, // gItemIcon_Drampanite, + .iconPalette = gItemIconPalette_QuestionMark, // gItemIconPalette_Drampanite, + }, + + [ITEM_FALINKSITE] = + { + .name = ITEM_NAME("Falinksite"), + .price = 0, + .holdEffect = HOLD_EFFECT_MEGA_STONE, + .description = COMPOUND_STRING( + "This stone enables\n" + "Falinks to Mega\n" + "Evolve in battle."), + .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, + .type = ITEM_USE_BAG_MENU, + .fieldUseFunc = ItemUseOutOfBattle_CannotUse, + .flingPower = 80, + .iconPic = gItemIcon_QuestionMark, // gItemIcon_Falinksite, + .iconPalette = gItemIconPalette_QuestionMark, // gItemIconPalette_Falinksite, + }, + // Gems [ITEM_NORMAL_GEM] = @@ -5911,6 +6672,7 @@ const struct Item gItemsInfo[] = "携带后,一般招式\n" "威力会增强1次。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_GEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_NORMAL, @@ -5929,6 +6691,7 @@ const struct Item gItemsInfo[] = "带后,火招式威力\n" "会增强1次。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_GEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_FIRE, @@ -5947,6 +6710,7 @@ const struct Item gItemsInfo[] = "带后,水招式威力\n" "会增强1次。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_GEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_WATER, @@ -5965,6 +6729,7 @@ const struct Item gItemsInfo[] = "带后,电招式威力\n" "会增强1次。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_GEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_ELECTRIC, @@ -5983,6 +6748,7 @@ const struct Item gItemsInfo[] = "带后,草招式威力\n" "会增强1次。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_GEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_GRASS, @@ -6001,6 +6767,7 @@ const struct Item gItemsInfo[] = "带后,冰招式威力\n" "会增强1次。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_GEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_ICE, @@ -6019,6 +6786,7 @@ const struct Item gItemsInfo[] = "携带后,格斗招式\n" "威力会增强1次。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_GEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_FIGHTING, @@ -6037,6 +6805,7 @@ const struct Item gItemsInfo[] = "带后,毒招式威力\n" "会增强1次。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_GEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_POISON, @@ -6055,6 +6824,7 @@ const struct Item gItemsInfo[] = "携带后,地面招式\n" "威力会增强1次。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_GEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_GROUND, @@ -6073,6 +6843,7 @@ const struct Item gItemsInfo[] = "携带后,飞行招式\n" "威力会增强1次。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_GEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_FLYING, @@ -6091,6 +6862,7 @@ const struct Item gItemsInfo[] = "携带后,超能招式\n" "威力会增强1次。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_GEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_PSYCHIC, @@ -6109,6 +6881,7 @@ const struct Item gItemsInfo[] = "带后,虫招式威力\n" "会增强1次。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_GEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_BUG, @@ -6127,6 +6900,7 @@ const struct Item gItemsInfo[] = "携带后,岩石招式\n" "威力会增强1次。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_GEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_ROCK, @@ -6145,6 +6919,7 @@ const struct Item gItemsInfo[] = "携带后,幽灵招式\n" "威力会增强1次。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_GEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_GHOST, @@ -6163,6 +6938,7 @@ const struct Item gItemsInfo[] = "带后,龙招式威力\n" "会增强1次。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_GEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_DRAGON, @@ -6181,6 +6957,7 @@ const struct Item gItemsInfo[] = "带后,恶招式威力\n" "会增强1次。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_GEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_DARK, @@ -6199,6 +6976,7 @@ const struct Item gItemsInfo[] = "带后,钢招式威力\n" "会增强1次。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_GEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_STEEL, @@ -6217,6 +6995,7 @@ const struct Item gItemsInfo[] = "携带后,妖精招式\n" "威力会增强1次。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_GEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_FAIRY, @@ -6236,6 +7015,7 @@ const struct Item gItemsInfo[] = "式升级成Z招式的\n" "Z结晶。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_Z_CRYSTAL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_NORMAL, @@ -6253,6 +7033,7 @@ const struct Item gItemsInfo[] = "升级成Z招式的Z\n" "结晶。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_Z_CRYSTAL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_FIRE, @@ -6270,6 +7051,7 @@ const struct Item gItemsInfo[] = "升级成Z招式的Z\n" "结晶。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_Z_CRYSTAL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_WATER, @@ -6287,6 +7069,7 @@ const struct Item gItemsInfo[] = "升级成Z招式的Z\n" "结晶。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_Z_CRYSTAL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_ELECTRIC, @@ -6304,6 +7087,7 @@ const struct Item gItemsInfo[] = "升级成Z招式的Z\n" "结晶。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_Z_CRYSTAL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_GRASS, @@ -6321,6 +7105,7 @@ const struct Item gItemsInfo[] = "升级成Z招式的Z\n" "结晶。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_Z_CRYSTAL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_ICE, @@ -6338,6 +7123,7 @@ const struct Item gItemsInfo[] = "式升级成Z招式的\n" "Z结晶。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_Z_CRYSTAL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_FIGHTING, @@ -6355,6 +7141,7 @@ const struct Item gItemsInfo[] = "升级成Z招式的Z\n" "结晶。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_Z_CRYSTAL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_POISON, @@ -6372,6 +7159,7 @@ const struct Item gItemsInfo[] = "式升级成Z招式的\n" "Z结晶。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_Z_CRYSTAL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_GROUND, @@ -6389,6 +7177,7 @@ const struct Item gItemsInfo[] = "式升级成Z招式的\n" "Z结晶。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_Z_CRYSTAL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_FLYING, @@ -6406,6 +7195,7 @@ const struct Item gItemsInfo[] = "式升级成Z招式的\n" "Z结晶。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_Z_CRYSTAL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_PSYCHIC, @@ -6423,6 +7213,7 @@ const struct Item gItemsInfo[] = "升级成Z招式的Z\n" "结晶。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_Z_CRYSTAL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_BUG, @@ -6440,6 +7231,7 @@ const struct Item gItemsInfo[] = "式升级成Z招式的\n" "Z结晶。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_Z_CRYSTAL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_ROCK, @@ -6457,6 +7249,7 @@ const struct Item gItemsInfo[] = "式升级成Z招式的\n" "Z结晶。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_Z_CRYSTAL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_GHOST, @@ -6474,6 +7267,7 @@ const struct Item gItemsInfo[] = "升级成Z招式的Z\n" "结晶。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_Z_CRYSTAL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_DRAGON, @@ -6491,6 +7285,7 @@ const struct Item gItemsInfo[] = "升级成Z招式的Z\n" "结晶。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_Z_CRYSTAL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_DARK, @@ -6508,6 +7303,7 @@ const struct Item gItemsInfo[] = "升级成Z招式的Z\n" "结晶。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_Z_CRYSTAL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_STEEL, @@ -6525,6 +7321,7 @@ const struct Item gItemsInfo[] = "式升级成Z招式的\n" "Z结晶。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_Z_CRYSTAL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_FAIRY, @@ -6542,6 +7339,7 @@ const struct Item gItemsInfo[] = "攻击升级成Z招式\n" "的Z结晶。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_Z_CRYSTAL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = 255, // signature z move @@ -6559,6 +7357,7 @@ const struct Item gItemsInfo[] = "级成Z招式的Z结\n" "晶。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_Z_CRYSTAL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = 255, // signature z move @@ -6576,6 +7375,7 @@ const struct Item gItemsInfo[] = "冲击升级成Z招式\n" "的Z结晶。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_Z_CRYSTAL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = 255, // signature z move @@ -6593,6 +7393,7 @@ const struct Item gItemsInfo[] = "念升级成Z招式的\n" "Z结晶。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_Z_CRYSTAL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = 255, // signature z move @@ -6610,6 +7411,7 @@ const struct Item gItemsInfo[] = "影升级成Z招式的\n" "Z结晶。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_Z_CRYSTAL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = 255, // signature z move @@ -6627,6 +7429,7 @@ const struct Item gItemsInfo[] = "DD金勾臂升级成\n" "Z招式的Z结晶。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_Z_CRYSTAL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = 255, // signature z move @@ -6644,6 +7447,7 @@ const struct Item gItemsInfo[] = "影的咏叹调升级成\n" "Z招式的Z结晶。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_Z_CRYSTAL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = 255, // signature z move @@ -6661,6 +7465,7 @@ const struct Item gItemsInfo[] = "石攻击升级成Z招\n" "式的Z结晶。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_Z_CRYSTAL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = 255, // signature z move @@ -6678,6 +7483,7 @@ const struct Item gItemsInfo[] = "升级成Z招式的Z\n" "结晶。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_Z_CRYSTAL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = 255, // signature z move @@ -6695,6 +7501,7 @@ const struct Item gItemsInfo[] = "鳞片噪音升级成Z\n" "招式的Z结晶。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_Z_CRYSTAL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = 255, // signature z move @@ -6712,6 +7519,7 @@ const struct Item gItemsInfo[] = "之怒升级成Z招式\n" "的Z结晶。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_Z_CRYSTAL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = 255, //signature z move @@ -6729,6 +7537,7 @@ const struct Item gItemsInfo[] = "流星闪冲升级成Z\n" "招式的Z结晶。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_Z_CRYSTAL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = 255, // signature z move @@ -6746,6 +7555,7 @@ const struct Item gItemsInfo[] = "影之光升级成Z招\n" "式的Z结晶。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_Z_CRYSTAL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = 255, // signature z move @@ -6763,6 +7573,7 @@ const struct Item gItemsInfo[] = "偷盗升级成Z招式\n" "的Z结晶。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_Z_CRYSTAL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = 255, // signature z move @@ -6780,6 +7591,7 @@ const struct Item gItemsInfo[] = "十万伏特升级成Z\n" "招式的Z结晶。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_Z_CRYSTAL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = 255, // signature z move @@ -6797,6 +7609,7 @@ const struct Item gItemsInfo[] = "的十万伏特升级成\n" "Z招式的Z结晶。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_Z_CRYSTAL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = 255, // signature z move @@ -6814,6 +7627,7 @@ const struct Item gItemsInfo[] = "洛兹玛变成崭新样\n" "子的结晶。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_Z_CRYSTAL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = 255, //signature z move @@ -6833,6 +7647,7 @@ const struct Item gItemsInfo[] = "攻击和特攻提高的\n" "神奇之球。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -6850,6 +7665,7 @@ const struct Item gItemsInfo[] = "招式会变得容易击\n" "中要害的大葱。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 60, @@ -6867,6 +7683,7 @@ const struct Item gItemsInfo[] = "嘎啦携带后,攻击\n" "就会提高的骨头。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 90, @@ -6884,6 +7701,7 @@ const struct Item gItemsInfo[] = "招式会变得容易击\n" "中要害的拳套。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 40, @@ -6901,6 +7719,7 @@ const struct Item gItemsInfo[] = "防御就会提高的神\n" "奇粉末。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -6918,6 +7737,7 @@ const struct Item gItemsInfo[] = "速度就会提高的神\n" "奇粉末。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -6935,6 +7755,7 @@ const struct Item gItemsInfo[] = "特防就会提高的鳞\n" "片。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = EVO_HELD_ITEM_TYPE, .fieldUseFunc = EVO_HELD_ITEM_FIELD_FUNC, .effect = gItemEffect_EvoItem, @@ -6953,6 +7774,7 @@ const struct Item gItemsInfo[] = "特攻就会提高的牙\n" "齿。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = EVO_HELD_ITEM_TYPE, .fieldUseFunc = EVO_HELD_ITEM_FIELD_FUNC, .effect = gItemEffect_EvoItem, @@ -6972,6 +7794,7 @@ const struct Item gItemsInfo[] = "能和龙招式威力提\n" "高的神奇珠子。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_SPECIAL_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -6990,6 +7813,7 @@ const struct Item gItemsInfo[] = "话,龙和钢招式威\n" "力就会提高。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_SPECIAL_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 60, @@ -7008,6 +7832,7 @@ const struct Item gItemsInfo[] = "话,龙和水招式威\n" "力就会提高。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_SPECIAL_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 60, @@ -7026,6 +7851,7 @@ const struct Item gItemsInfo[] = "话,龙和幽灵招式\n" "威力就会提高。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_SPECIAL_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 60, @@ -7043,6 +7869,7 @@ const struct Item gItemsInfo[] = .holdEffectParam = 20, .description = sSeaIncenseDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_INCENSE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_WATER, @@ -7062,6 +7889,7 @@ const struct Item gItemsInfo[] = "会变得不容易命中\n" "。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_INCENSE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -7077,6 +7905,7 @@ const struct Item gItemsInfo[] = .holdEffectParam = 20, .description = sOddIncenseDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_INCENSE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_PSYCHIC, @@ -7093,6 +7922,7 @@ const struct Item gItemsInfo[] = .holdEffectParam = 20, .description = sRockIncenseDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_INCENSE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_ROCK, @@ -7109,6 +7939,7 @@ const struct Item gItemsInfo[] = .holdEffectParam = 5, .description = sFullIncenseDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_INCENSE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -7124,6 +7955,7 @@ const struct Item gItemsInfo[] = .holdEffectParam = 20, .description = sSeaIncenseDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_INCENSE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_WATER, @@ -7140,6 +7972,7 @@ const struct Item gItemsInfo[] = .holdEffectParam = 20, .description = sRoseIncenseDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_INCENSE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_GRASS, @@ -7155,6 +7988,7 @@ const struct Item gItemsInfo[] = .holdEffect = HOLD_EFFECT_DOUBLE_PRIZE, .description = sLuckIncenseDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_INCENSE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -7169,6 +8003,7 @@ const struct Item gItemsInfo[] = .holdEffect = HOLD_EFFECT_REPEL, .description = sPureIncenseDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_INCENSE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -7187,6 +8022,7 @@ const struct Item gItemsInfo[] = "大赛的话会比平时\n" "更加帅气。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_CONTEST_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -7203,6 +8039,7 @@ const struct Item gItemsInfo[] = "大赛的话会比平时\n" "更加美丽。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_CONTEST_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -7219,6 +8056,7 @@ const struct Item gItemsInfo[] = "大赛的话会比平时\n" "更加可爱。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_CONTEST_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -7235,6 +8073,7 @@ const struct Item gItemsInfo[] = "大赛的话会比平时\n" "更加聪明。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_CONTEST_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -7251,6 +8090,7 @@ const struct Item gItemsInfo[] = "大赛的话会比平时\n" "更加强壮。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_CONTEST_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -7270,6 +8110,7 @@ const struct Item gItemsInfo[] = "降低,但会比平时\n" "更容易成长。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EV_BOOST_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 60, @@ -7288,6 +8129,7 @@ const struct Item gItemsInfo[] = "降低,但HP会比\n" "平时成长得更高。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EV_BOOST_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = STAT_HP, @@ -7307,6 +8149,7 @@ const struct Item gItemsInfo[] = "降低,但攻击会比\n" "平时成长得更高。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EV_BOOST_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = STAT_ATK, @@ -7326,6 +8169,7 @@ const struct Item gItemsInfo[] = "降低,但防御会比\n" "平时成长得更高。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EV_BOOST_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = STAT_DEF, @@ -7345,6 +8189,7 @@ const struct Item gItemsInfo[] = "降低,但特攻会比\n" "平时成长得更高。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EV_BOOST_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = STAT_SPATK, @@ -7364,6 +8209,7 @@ const struct Item gItemsInfo[] = "降低,但特防会比\n" "平时成长得更高。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EV_BOOST_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = STAT_SPDEF, @@ -7383,6 +8229,7 @@ const struct Item gItemsInfo[] = "降低,但速度会比\n" "平时成长得更高。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EV_BOOST_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = STAT_SPEED, @@ -7404,6 +8251,7 @@ const struct Item gItemsInfo[] = "携带后,一般招式\n" "威力会提高。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_TYPE_BOOST_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_NORMAL, @@ -7423,6 +8271,7 @@ const struct Item gItemsInfo[] = "带后,火招式威力\n" "会提高。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_TYPE_BOOST_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_FIRE, @@ -7442,6 +8291,7 @@ const struct Item gItemsInfo[] = "携带后,水招式威\n" "力会提高。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_TYPE_BOOST_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_WATER, @@ -7461,6 +8311,7 @@ const struct Item gItemsInfo[] = "后,电招式威力会\n" "提高。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_TYPE_BOOST_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_ELECTRIC, @@ -7475,11 +8326,9 @@ const struct Item gItemsInfo[] = .price = (I_PRICE >= GEN_9) ? 3000 : ((I_PRICE >= GEN_7) ? 1000 : 100), .holdEffect = HOLD_EFFECT_TYPE_POWER, .holdEffectParam = TYPE_BOOST_PARAM, - .description = COMPOUND_STRING( - "孕育生命的种子。\n" - "携带后,草招式威\n" - "力会提高。"), + .description = sRoseIncenseDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_TYPE_BOOST_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_GRASS, @@ -7499,6 +8348,7 @@ const struct Item gItemsInfo[] = "携带后,冰招式威\n" "力会提高。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_TYPE_BOOST_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_ICE, @@ -7518,6 +8368,7 @@ const struct Item gItemsInfo[] = "。携带后,格斗招\n" "式威力会提高。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_TYPE_BOOST_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_FIGHTING, @@ -7537,6 +8388,7 @@ const struct Item gItemsInfo[] = "后,毒招式威力会\n" "提高。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_TYPE_BOOST_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_POISON, @@ -7556,6 +8408,7 @@ const struct Item gItemsInfo[] = "携带后,地面招式\n" "威力会提高。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_TYPE_BOOST_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_GROUND, @@ -7575,6 +8428,7 @@ const struct Item gItemsInfo[] = "携带后,飞行招式\n" "威力会提高。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_TYPE_BOOST_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_FLYING, @@ -7589,11 +8443,9 @@ const struct Item gItemsInfo[] = .price = (I_PRICE >= GEN_9) ? 3000 : ((I_PRICE >= GEN_7) ? 1000 : 100), .holdEffect = HOLD_EFFECT_TYPE_POWER, .holdEffectParam = TYPE_BOOST_PARAM, - .description = COMPOUND_STRING( - "注入了念力的汤匙\n" - "。携带后,超能力\n" - "招式威力会提高。"), + .description = sOddIncenseDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_TYPE_BOOST_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_PSYCHIC, @@ -7613,6 +8465,7 @@ const struct Item gItemsInfo[] = "粉末。携带后,虫\n" "招式威力会提高。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_TYPE_BOOST_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_BUG, @@ -7627,11 +8480,9 @@ const struct Item gItemsInfo[] = .price = (I_PRICE >= GEN_9) ? 3000 : ((I_PRICE >= GEN_7) ? 1000 : 100), .holdEffect = HOLD_EFFECT_TYPE_POWER, .holdEffectParam = TYPE_BOOST_PARAM, - .description = COMPOUND_STRING( - "绝对不会裂开的石\n" - "头。携带后,岩石\n" - "招式威力会提高。"), + .description = sRockIncenseDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_TYPE_BOOST_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_ROCK, @@ -7651,6 +8502,7 @@ const struct Item gItemsInfo[] = "携带后,幽灵招式\n" "威力会提高。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_TYPE_BOOST_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_GHOST, @@ -7670,6 +8522,7 @@ const struct Item gItemsInfo[] = "携带后,龙招式威\n" "力会提高。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_TYPE_BOOST_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_DRAGON, @@ -7689,6 +8542,7 @@ const struct Item gItemsInfo[] = "镜。携带后,恶招\n" "式威力会提高。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_TYPE_BOOST_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_DARK, @@ -7708,6 +8562,7 @@ const struct Item gItemsInfo[] = "带后,钢招式威力\n" "会提高。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_TYPE_BOOST_HELD_ITEM, .type = EVO_HELD_ITEM_TYPE, .fieldUseFunc = EVO_HELD_ITEM_FIELD_FUNC, .effect = gItemEffect_EvoItem, @@ -7729,6 +8584,7 @@ const struct Item gItemsInfo[] = "携带后攻击提升但\n" "只能用相同招式。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -7746,6 +8602,7 @@ const struct Item gItemsInfo[] = "携带后特攻提升但\n" "只能用相同招式。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -7763,6 +8620,7 @@ const struct Item gItemsInfo[] = "携带后速度提升但\n" "只能用相同招式。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -7782,6 +8640,7 @@ const struct Item gItemsInfo[] = "宝珠。携带后在战\n" "斗时会灼伤。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -7799,6 +8658,7 @@ const struct Item gItemsInfo[] = "珠。携带后在战斗\n" "时会中剧毒。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -7818,6 +8678,7 @@ const struct Item gItemsInfo[] = "雨后持续时间就会\n" "更长。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 60, @@ -7835,6 +8696,7 @@ const struct Item gItemsInfo[] = "晴天后持续时间就\n" "会更长。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 60, @@ -7852,6 +8714,7 @@ const struct Item gItemsInfo[] = "暴后持续时间就会\n" "更长。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -7869,6 +8732,7 @@ const struct Item gItemsInfo[] = "雹后持续时间就会\n" "更长。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 40, @@ -7882,13 +8746,14 @@ const struct Item gItemsInfo[] = { .name = ITEM_NAME("电气种子"), .price = (I_PRICE >= GEN_9) ? 20000 : 4000, - .holdEffect = HOLD_EFFECT_SEEDS, + .holdEffect = HOLD_EFFECT_TERRAIN_SEED, .holdEffectParam = HOLD_EFFECT_PARAM_ELECTRIC_TERRAIN, .description = COMPOUND_STRING( "携带后,在电气场\n" "地上使用,防御就\n" "会提高。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -7900,13 +8765,14 @@ const struct Item gItemsInfo[] = { .name = ITEM_NAME("精神种子"), .price = (I_PRICE >= GEN_9) ? 20000 : 4000, - .holdEffect = HOLD_EFFECT_SEEDS, + .holdEffect = HOLD_EFFECT_TERRAIN_SEED, .holdEffectParam = HOLD_EFFECT_PARAM_PSYCHIC_TERRAIN, .description = COMPOUND_STRING( "携带后,在精神场\n" "地上使用,特防就\n" "会提高。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -7918,13 +8784,14 @@ const struct Item gItemsInfo[] = { .name = ITEM_NAME("薄雾种子"), .price = (I_PRICE >= GEN_9) ? 20000 : 4000, - .holdEffect = HOLD_EFFECT_SEEDS, + .holdEffect = HOLD_EFFECT_TERRAIN_SEED, .holdEffectParam = HOLD_EFFECT_PARAM_MISTY_TERRAIN, .description = COMPOUND_STRING( "携带后,在薄雾场\n" "地上使用,特防就\n" "会提高。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -7936,13 +8803,14 @@ const struct Item gItemsInfo[] = { .name = ITEM_NAME("青草种子"), .price = (I_PRICE >= GEN_9) ? 20000 : 4000, - .holdEffect = HOLD_EFFECT_SEEDS, + .holdEffect = HOLD_EFFECT_TERRAIN_SEED, .holdEffectParam = HOLD_EFFECT_PARAM_GRASSY_TERRAIN, .description = COMPOUND_STRING( "携带后,在青草场\n" "地上使用,防御就\n" "会提高。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -7963,6 +8831,7 @@ const struct Item gItemsInfo[] = "宝可梦受到水招式\n" ",特攻就会提高。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -7981,6 +8850,7 @@ const struct Item gItemsInfo[] = "宝可梦受到电招式\n" ",攻击就会提高。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -7999,6 +8869,7 @@ const struct Item gItemsInfo[] = "宝可梦受到水招式\n" ",特防就会提高。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -8017,6 +8888,7 @@ const struct Item gItemsInfo[] = "宝可梦受到冰属性\n" ",攻击就会提高。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -8037,6 +8909,7 @@ const struct Item gItemsInfo[] = "式变得不易命中的\n" "闪闪发光的粉末。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -8054,6 +8927,7 @@ const struct Item gItemsInfo[] = "降低时,仅能回到\n" "之前的状态1次。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -8071,6 +8945,7 @@ const struct Item gItemsInfo[] = "的所有宝可梦获得\n" "经验值的装置。"), .pocket = I_EXP_SHARE_ITEM >= GEN_6 ? POCKET_KEY_ITEMS : POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_FIELD, .fieldUseFunc = ItemUseOutOfBattle_ExpShare, .flingPower = 30, @@ -8089,6 +8964,7 @@ const struct Item gItemsInfo[] = "。携带后,有时能\n" "先一步行动。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -8106,6 +8982,7 @@ const struct Item gItemsInfo[] = "携带宝可梦会变得\n" "容易亲密。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -8123,6 +9000,7 @@ const struct Item gItemsInfo[] = "自由使出招式时,\n" "仅会回复1次。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -8138,6 +9016,7 @@ const struct Item gItemsInfo[] = .holdEffectParam = 10, .description = sKingsRockDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = EVO_HELD_ITEM_TYPE, .fieldUseFunc = EVO_HELD_ITEM_FIELD_FUNC, .effect = gItemEffect_EvoItem, @@ -8153,6 +9032,7 @@ const struct Item gItemsInfo[] = .holdEffect = HOLD_EFFECT_DOUBLE_PRIZE, .description = sLuckIncenseDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -8167,6 +9047,7 @@ const struct Item gItemsInfo[] = .holdEffect = HOLD_EFFECT_REPEL, .description = sPureIncenseDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -8184,6 +9065,7 @@ const struct Item gItemsInfo[] = "生宝可梦的战斗中\n" "绝对可以逃走。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -8202,6 +9084,7 @@ const struct Item gItemsInfo[] = "致命招式有时也能\n" "以1HP撑过去。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -8219,6 +9102,7 @@ const struct Item gItemsInfo[] = "携带后获得的经验\n" "值会少量增加。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -8236,6 +9120,7 @@ const struct Item gItemsInfo[] = "。携带后会变得容\n" "易击中要害。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -8254,6 +9139,7 @@ const struct Item gItemsInfo[] = "HP会在战斗期间\n" "缓缓回复。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -8272,6 +9158,7 @@ const struct Item gItemsInfo[] = "伤害时,能回复少\n" "量HP。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -8290,6 +9177,7 @@ const struct Item gItemsInfo[] = "中率就会少量提高\n" "的镜片。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -8308,6 +9196,7 @@ const struct Item gItemsInfo[] = "的威力就会少量提\n" "高的头带。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -8326,6 +9215,7 @@ const struct Item gItemsInfo[] = "的威力就会少量提\n" "高的眼镜。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -8345,6 +9235,7 @@ const struct Item gItemsInfo[] = "佳时的招式威力就\n" "会少量提高。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -8362,6 +9253,7 @@ const struct Item gItemsInfo[] = "或反射壁时,效果\n" "会持续得更长。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -8379,6 +9271,7 @@ const struct Item gItemsInfo[] = "攻击时HP减少,\n" "但威力会提高。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -8396,6 +9289,7 @@ const struct Item gItemsInfo[] = "次机会直接使出需\n" "要蓄力的招式。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -8413,6 +9307,7 @@ const struct Item gItemsInfo[] = "命伤,也能以1H\n" "P撑过去1次。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -8431,6 +9326,7 @@ const struct Item gItemsInfo[] = "手行动迟缓时,招\n" "式会容易命中。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -8449,6 +9345,7 @@ const struct Item gItemsInfo[] = "相同招式时,威力\n" "就会提高。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -8467,6 +9364,7 @@ const struct Item gItemsInfo[] = "会被地面招式击中\n" "。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 130, @@ -8481,6 +9379,7 @@ const struct Item gItemsInfo[] = .holdEffect = HOLD_EFFECT_LAGGING_TAIL, .description = sFullIncenseDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -8498,6 +9397,7 @@ const struct Item gItemsInfo[] = "迷时能让对手也着\n" "迷的红色细线。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -8515,6 +9415,7 @@ const struct Item gItemsInfo[] = "缓回HP。其他属\n" "性HP则会减少。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -8532,6 +9433,7 @@ const struct Item gItemsInfo[] = "等招式的回合数会\n" "增加。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 90, @@ -8549,6 +9451,7 @@ const struct Item gItemsInfo[] = "会受伤。有时也会\n" "附到触碰对手上。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -8566,6 +9469,7 @@ const struct Item gItemsInfo[] = "携带宝可梦必定可\n" "以换下。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -8584,6 +9488,7 @@ const struct Item gItemsInfo[] = "式能更多地回复自\n" "己的HP。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -8601,6 +9506,7 @@ const struct Item gItemsInfo[] = "后,招式会变得容\n" "易击中要害。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = EVO_HELD_ITEM_TYPE, .fieldUseFunc = EVO_HELD_ITEM_FIELD_FUNC, .effect = gItemEffect_EvoItem, @@ -8617,6 +9523,7 @@ const struct Item gItemsInfo[] = .holdEffectParam = 10, .description = sKingsRockDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = EVO_HELD_ITEM_TYPE, .fieldUseFunc = EVO_HELD_ITEM_FIELD_FUNC, .effect = gItemEffect_EvoItem, @@ -8636,6 +9543,7 @@ const struct Item gItemsInfo[] = "的宝可梦的防御和\n" "特防就会提高。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 40, @@ -8653,6 +9561,7 @@ const struct Item gItemsInfo[] = "带后,宝可梦的体\n" "重会变轻。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -8671,6 +9580,7 @@ const struct Item gItemsInfo[] = "击招式攻击时,能\n" "给予对手伤害。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 60, @@ -8689,6 +9599,7 @@ const struct Item gItemsInfo[] = "浮在空中。受到攻\n" "击就会破裂。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -8707,6 +9618,7 @@ const struct Item gItemsInfo[] = "招式的对手退场的\n" "卡片。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -8725,6 +9637,7 @@ const struct Item gItemsInfo[] = "的招式现在能够击\n" "中自己。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -8742,6 +9655,7 @@ const struct Item gItemsInfo[] = "的威力会变强的束\n" "带。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -8760,6 +9674,7 @@ const struct Item gItemsInfo[] = "到招式攻击,就能\n" "换下脱战。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -8778,6 +9693,7 @@ const struct Item gItemsInfo[] = "击和特攻就会大幅\n" "提高。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -8796,6 +9712,7 @@ const struct Item gItemsInfo[] = "提高,但会无法使\n" "出变化招式。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -8813,6 +9730,7 @@ const struct Item gItemsInfo[] = "粉末招式效果的护\n" "目镜。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -8829,6 +9747,7 @@ const struct Item gItemsInfo[] = "携带后,在受到威\n" "吓时速度会提高。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -8846,6 +9765,7 @@ const struct Item gItemsInfo[] = "时,持续时间会比\n" "平时更长。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 60, @@ -8863,6 +9783,7 @@ const struct Item gItemsInfo[] = "对手时本应受到的\n" "效果。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -8880,6 +9801,7 @@ const struct Item gItemsInfo[] = "式时,特攻会提高\n" "。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -8897,6 +9819,7 @@ const struct Item gItemsInfo[] = "时,同行宝可梦就\n" "会自动替换上场。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 50, @@ -8913,6 +9836,7 @@ const struct Item gItemsInfo[] = "不受脚下陷阱等的\n" "影响。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -8930,6 +9854,7 @@ const struct Item gItemsInfo[] = "而落空时,速度会\n" "大幅提高。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -8947,6 +9872,7 @@ const struct Item gItemsInfo[] = "间使用时,速度会\n" "下降。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 100, @@ -8964,6 +9890,7 @@ const struct Item gItemsInfo[] = "不受各种天气的影\n" "响。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 60, @@ -8982,6 +9909,7 @@ const struct Item gItemsInfo[] = "携带后,可以治愈\n" "麻痹。"), .pocket = POCKET_BERRIES, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .battleUsage = EFFECT_ITEM_CURE_STATUS, @@ -10159,7 +11087,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_FOCUS_PUNCH, }, [ITEM_TM_DRAGON_CLAW] = @@ -10173,7 +11100,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_DRAGON_CLAW, }, [ITEM_TM_WATER_PULSE] = @@ -10188,7 +11114,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_WATER_PULSE, }, [ITEM_TM_CALM_MIND] = @@ -10203,7 +11128,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_CALM_MIND, }, [ITEM_TM_ROAR] = @@ -10218,7 +11142,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_ROAR, }, [ITEM_TM_TOXIC] = @@ -10233,7 +11156,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_TOXIC, }, [ITEM_TM_HAIL] = @@ -10255,7 +11177,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_HAIL, }, [ITEM_TM_BULK_UP] = @@ -10270,7 +11191,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_BULK_UP, }, [ITEM_TM_BULLET_SEED] = @@ -10285,7 +11205,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_BULLET_SEED, }, [ITEM_TM_HIDDEN_POWER] = @@ -10300,7 +11219,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_HIDDEN_POWER, }, [ITEM_TM_SUNNY_DAY] = @@ -10315,7 +11233,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_SUNNY_DAY, }, [ITEM_TM_TAUNT] = @@ -10330,7 +11247,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_TAUNT, }, [ITEM_TM_ICE_BEAM] = @@ -10345,7 +11261,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_ICE_BEAM, }, [ITEM_TM_BLIZZARD] = @@ -10360,7 +11275,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_BLIZZARD, }, [ITEM_TM_HYPER_BEAM] = @@ -10375,7 +11289,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_HYPER_BEAM, }, [ITEM_TM_LIGHT_SCREEN] = @@ -10390,7 +11303,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_LIGHT_SCREEN, }, [ITEM_TM_PROTECT] = @@ -10405,7 +11317,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_PROTECT, }, [ITEM_TM_RAIN_DANCE] = @@ -10420,7 +11331,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_RAIN_DANCE, }, [ITEM_TM_GIGA_DRAIN] = @@ -10435,7 +11345,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_GIGA_DRAIN, }, [ITEM_TM_SAFEGUARD] = @@ -10450,7 +11359,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_SAFEGUARD, }, [ITEM_TM_FRUSTRATION] = @@ -10465,7 +11373,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_FRUSTRATION, }, [ITEM_TM_SOLAR_BEAM] = @@ -10480,7 +11387,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_SOLAR_BEAM, }, [ITEM_TM_IRON_TAIL] = @@ -10495,7 +11401,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_IRON_TAIL, }, [ITEM_TM_THUNDERBOLT] = @@ -10510,7 +11415,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_THUNDERBOLT, }, [ITEM_TM_THUNDER] = @@ -10525,7 +11429,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_THUNDER, }, [ITEM_TM_EARTHQUAKE] = @@ -10540,7 +11443,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_EARTHQUAKE, }, [ITEM_TM_RETURN] = @@ -10555,7 +11457,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_RETURN, }, [ITEM_TM_DIG] = @@ -10570,7 +11471,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_DIG, }, [ITEM_TM_PSYCHIC] = @@ -10585,7 +11485,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_PSYCHIC, }, [ITEM_TM_SHADOW_BALL] = @@ -10600,7 +11499,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_SHADOW_BALL, }, [ITEM_TM_BRICK_BREAK] = @@ -10615,7 +11513,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_BRICK_BREAK, }, [ITEM_TM_DOUBLE_TEAM] = @@ -10630,7 +11527,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_DOUBLE_TEAM, }, [ITEM_TM_REFLECT] = @@ -10645,7 +11541,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_REFLECT, }, [ITEM_TM_SHOCK_WAVE] = @@ -10660,7 +11555,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_SHOCK_WAVE, }, [ITEM_TM_FLAMETHROWER] = @@ -10675,7 +11569,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_FLAMETHROWER, }, [ITEM_TM_SLUDGE_BOMB] = @@ -10690,7 +11583,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_SLUDGE_BOMB, }, [ITEM_TM_SANDSTORM] = @@ -10705,7 +11597,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_SANDSTORM, }, [ITEM_TM_FIRE_BLAST] = @@ -10720,7 +11611,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_FIRE_BLAST, }, [ITEM_TM_ROCK_TOMB] = @@ -10735,7 +11625,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_ROCK_TOMB, }, [ITEM_TM_AERIAL_ACE] = @@ -10750,7 +11639,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_AERIAL_ACE, }, [ITEM_TM_TORMENT] = @@ -10765,7 +11653,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_TORMENT, }, [ITEM_TM_FACADE] = @@ -10780,7 +11667,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_FACADE, }, [ITEM_TM_SECRET_POWER] = @@ -10795,7 +11681,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_SECRET_POWER, }, [ITEM_TM_REST] = @@ -10810,7 +11695,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_REST, }, [ITEM_TM_ATTRACT] = @@ -10825,7 +11709,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_ATTRACT, }, [ITEM_TM_THIEF] = @@ -10840,7 +11723,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_THIEF, }, [ITEM_TM_STEEL_WING] = @@ -10855,7 +11737,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_STEEL_WING, }, [ITEM_TM_SKILL_SWAP] = @@ -10870,7 +11751,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_SKILL_SWAP, }, [ITEM_TM_SNATCH] = @@ -10885,7 +11765,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_SNATCH, }, [ITEM_TM_OVERHEAT] = @@ -10900,7 +11779,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_OVERHEAT, }, [ITEM_TM51] = @@ -10912,7 +11790,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM52] = @@ -10924,7 +11801,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM53] = @@ -10936,7 +11812,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM54] = @@ -10948,7 +11823,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM55] = @@ -10960,7 +11834,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM56] = @@ -10972,7 +11845,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM57] = @@ -10984,7 +11856,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM58] = @@ -10996,7 +11867,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM59] = @@ -11008,7 +11878,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM60] = @@ -11020,7 +11889,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM61] = @@ -11032,7 +11900,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM62] = @@ -11044,7 +11911,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM63] = @@ -11056,7 +11922,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM64] = @@ -11068,7 +11933,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM65] = @@ -11080,7 +11944,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM66] = @@ -11092,7 +11955,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM67] = @@ -11104,7 +11966,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM68] = @@ -11116,7 +11977,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM69] = @@ -11128,7 +11988,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM70] = @@ -11140,7 +11999,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM71] = @@ -11152,7 +12010,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM72] = @@ -11164,7 +12021,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM73] = @@ -11176,7 +12032,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM74] = @@ -11188,7 +12043,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM75] = @@ -11200,7 +12054,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM76] = @@ -11212,7 +12065,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM77] = @@ -11224,7 +12076,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM78] = @@ -11236,7 +12087,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM79] = @@ -11248,7 +12098,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM80] = @@ -11260,7 +12109,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM81] = @@ -11272,7 +12120,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM82] = @@ -11284,7 +12131,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM83] = @@ -11296,7 +12142,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM84] = @@ -11308,7 +12153,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM85] = @@ -11320,7 +12164,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM86] = @@ -11332,7 +12175,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM87] = @@ -11344,7 +12186,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM88] = @@ -11356,7 +12197,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM89] = @@ -11368,7 +12208,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM90] = @@ -11380,7 +12219,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM91] = @@ -11392,7 +12230,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM92] = @@ -11404,7 +12241,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM93] = @@ -11416,7 +12252,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM94] = @@ -11428,7 +12263,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM95] = @@ -11440,7 +12274,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM96] = @@ -11452,7 +12285,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM97] = @@ -11464,7 +12296,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM98] = @@ -11476,7 +12307,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM99] = @@ -11488,7 +12318,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM100] = @@ -11500,7 +12329,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_HM_CUT] = @@ -11514,7 +12342,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_CUT, }, [ITEM_HM_FLY] = @@ -11529,7 +12356,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_FLY, }, [ITEM_HM_SURF] = @@ -11544,7 +12370,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_SURF, }, [ITEM_HM_STRENGTH] = @@ -11558,7 +12383,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_STRENGTH, }, [ITEM_HM_FLASH] = @@ -11573,7 +12397,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_FLASH, }, [ITEM_HM_ROCK_SMASH] = @@ -11588,7 +12411,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_ROCK_SMASH, }, [ITEM_HM_WATERFALL] = @@ -11603,7 +12425,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_WATERFALL, }, [ITEM_HM_DIVE] = @@ -11618,7 +12439,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_DIVE, }, @@ -12753,6 +13573,7 @@ const struct Item gItemsInfo[] = "威力提高,且不会\n" "接触到对手。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -12770,6 +13591,7 @@ const struct Item gItemsInfo[] = "受到招式的追加效\n" "果影响。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -12787,6 +13609,7 @@ const struct Item gItemsInfo[] = "续招式时,能使出\n" "较多次招式。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -12803,6 +13626,7 @@ const struct Item gItemsInfo[] = "化的神奇铠甲。蕴\n" "含着祝贺的感情。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_EvolutionStone, .effect = gItemEffect_EvoItem, @@ -12821,6 +13645,7 @@ const struct Item gItemsInfo[] = "可梦携带后能力会\n" "提升的胶囊。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -12837,6 +13662,7 @@ const struct Item gItemsInfo[] = "在部分美食家中拥\n" "有非常高人气。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_SELLABLE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -12853,6 +13679,7 @@ const struct Item gItemsInfo[] = "。索财灵珍爱有加\n" "地收集着它。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .iconPic = gItemIcon_GimmighoulCoin, @@ -12868,6 +13695,7 @@ const struct Item gItemsInfo[] = "兵群体的劈斩司令\n" "能携带着的碎片。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .iconPic = gItemIcon_LeadersCrest, @@ -12883,6 +13711,7 @@ const struct Item gItemsInfo[] = "化的神奇铠甲。蕴\n" "含着诅咒的感情。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_EvolutionStone, .effect = gItemEffect_EvoItem, @@ -12901,6 +13730,7 @@ const struct Item gItemsInfo[] = "提高能力时,模仿\n" "提高同样的能力。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -12918,6 +13748,7 @@ const struct Item gItemsInfo[] = "面写着恶之奥秘。"), .importance = 1, .pocket = POCKET_KEY_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_EvolutionStone, .effect = gItemEffect_EvoItem, @@ -12935,6 +13766,7 @@ const struct Item gItemsInfo[] = "面写着水之奥秘。"), .importance = 1, .pocket = POCKET_KEY_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_EvolutionStone, .effect = gItemEffect_EvoItem, @@ -12952,6 +13784,7 @@ const struct Item gItemsInfo[] = "让宝可梦太晶化。"), .importance = 1, .pocket = POCKET_KEY_ITEMS, + .sortType = ITEM_TYPE_SELLABLE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .iconPic = gItemIcon_TeraOrb, @@ -12980,6 +13813,7 @@ const struct Item gItemsInfo[] = .price = 0, .description = sTeraShardDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_TERA_SHARD, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .iconPic = gItemIcon_TeraShard, @@ -12992,6 +13826,7 @@ const struct Item gItemsInfo[] = .price = 0, .description = sTeraShardDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_TERA_SHARD, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .iconPic = gItemIcon_TeraShard, @@ -13004,6 +13839,7 @@ const struct Item gItemsInfo[] = .price = 0, .description = sTeraShardDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_TERA_SHARD, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .iconPic = gItemIcon_TeraShard, @@ -13016,6 +13852,7 @@ const struct Item gItemsInfo[] = .price = 0, .description = sTeraShardDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_TERA_SHARD, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .iconPic = gItemIcon_TeraShard, @@ -13028,6 +13865,7 @@ const struct Item gItemsInfo[] = .price = 0, .description = sTeraShardDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_TERA_SHARD, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .iconPic = gItemIcon_TeraShard, @@ -13040,6 +13878,7 @@ const struct Item gItemsInfo[] = .price = 0, .description = sTeraShardDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_TERA_SHARD, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .iconPic = gItemIcon_TeraShard, @@ -13052,6 +13891,7 @@ const struct Item gItemsInfo[] = .price = 0, .description = sTeraShardDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_TERA_SHARD, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .iconPic = gItemIcon_TeraShard, @@ -13064,6 +13904,7 @@ const struct Item gItemsInfo[] = .price = 0, .description = sTeraShardDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_TERA_SHARD, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .iconPic = gItemIcon_TeraShard, @@ -13076,6 +13917,7 @@ const struct Item gItemsInfo[] = .price = 0, .description = sTeraShardDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_TERA_SHARD, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .iconPic = gItemIcon_TeraShard, @@ -13088,6 +13930,7 @@ const struct Item gItemsInfo[] = .price = 0, .description = sTeraShardDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_TERA_SHARD, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .iconPic = gItemIcon_TeraShard, @@ -13100,6 +13943,7 @@ const struct Item gItemsInfo[] = .price = 0, .description = sTeraShardDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_TERA_SHARD, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .iconPic = gItemIcon_TeraShard, @@ -13112,6 +13956,7 @@ const struct Item gItemsInfo[] = .price = 0, .description = sTeraShardDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_TERA_SHARD, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .iconPic = gItemIcon_TeraShard, @@ -13124,6 +13969,7 @@ const struct Item gItemsInfo[] = .price = 0, .description = sTeraShardDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_TERA_SHARD, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .iconPic = gItemIcon_TeraShard, @@ -13136,6 +13982,7 @@ const struct Item gItemsInfo[] = .price = 0, .description = sTeraShardDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_TERA_SHARD, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .iconPic = gItemIcon_TeraShard, @@ -13148,6 +13995,7 @@ const struct Item gItemsInfo[] = .price = 0, .description = sTeraShardDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_TERA_SHARD, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .iconPic = gItemIcon_TeraShard, @@ -13160,6 +14008,7 @@ const struct Item gItemsInfo[] = .price = 0, .description = sTeraShardDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_TERA_SHARD, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .iconPic = gItemIcon_TeraShard, @@ -13172,6 +14021,7 @@ const struct Item gItemsInfo[] = .price = 0, .description = sTeraShardDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_TERA_SHARD, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .iconPic = gItemIcon_TeraShard, @@ -13184,6 +14034,7 @@ const struct Item gItemsInfo[] = .price = 0, .description = sTeraShardDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_TERA_SHARD, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .iconPic = gItemIcon_TeraShard, @@ -13201,6 +14052,7 @@ const struct Item gItemsInfo[] = ",能使之力量高涨\n" "并改变形态。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 60, @@ -13219,6 +14071,7 @@ const struct Item gItemsInfo[] = ",能使之力量高涨\n" "并改变形态。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 60, @@ -13237,6 +14090,7 @@ const struct Item gItemsInfo[] = ",能使之力量高涨\n" "并改变形态。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 60, @@ -13253,6 +14107,7 @@ const struct Item gItemsInfo[] = "玻璃的黑石。某种\n" "宝可梦很喜欢它。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_EvolutionStone, .effect = gItemEffect_EvoItem, @@ -13270,6 +14125,7 @@ const struct Item gItemsInfo[] = "量的绳子。某种宝\n" "可梦们很喜欢它。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_EvolutionStone, .effect = gItemEffect_EvoItem, @@ -13287,6 +14143,7 @@ const struct Item gItemsInfo[] = "炭块。某种宝可梦\n" "很喜欢它。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_EvolutionStone, .effect = gItemEffect_EvoItem, @@ -13305,6 +14162,7 @@ const struct Item gItemsInfo[] = "高,但会造成混乱\n" "。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -13323,6 +14181,7 @@ const struct Item gItemsInfo[] = "羽毛。携带后妖精\n" "招式威力提高。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_TYPE_BOOST_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_FAIRY, @@ -13340,6 +14199,7 @@ const struct Item gItemsInfo[] = "以使特定的宝可梦\n" "进化。富含蜜汁。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_EvolutionStone, .effect = gItemEffect_EvoItem, @@ -13357,6 +14217,7 @@ const struct Item gItemsInfo[] = "然破裂,可以使特\n" "定的宝可梦进化。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_EvolutionStone, .effect = gItemEffect_EvoItem, @@ -13374,6 +14235,7 @@ const struct Item gItemsInfo[] = "然破缺,可以使特\n" "定的宝可梦进化。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_EvolutionStone, .effect = gItemEffect_EvoItem, @@ -13393,6 +14255,7 @@ const struct Item gItemsInfo[] = "会用岩石属性覆盖\n" "全身进行战斗。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_SPECIAL_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .iconPic = gItemIcon_CornerstoneMask, @@ -13410,6 +14273,7 @@ const struct Item gItemsInfo[] = "会用水属性覆盖全\n" "身进行战斗。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_SPECIAL_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .iconPic = gItemIcon_WellspringMask, @@ -13427,6 +14291,7 @@ const struct Item gItemsInfo[] = "会用火属性覆盖全\n" "身进行战斗。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_SPECIAL_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .iconPic = gItemIcon_HearthflameMask, @@ -13439,6 +14304,7 @@ const struct Item gItemsInfo[] = .price = 500, .description = sHealthFeatherDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_STAT_BOOST_MOCHI, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .effect = gItemEffect_HpMochi, @@ -13453,6 +14319,7 @@ const struct Item gItemsInfo[] = .price = 500, .description = sMuscleFeatherDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_STAT_BOOST_MOCHI, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .effect = gItemEffect_AtkMochi, @@ -13467,6 +14334,7 @@ const struct Item gItemsInfo[] = .price = 500, .description = sResistFeatherDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_STAT_BOOST_MOCHI, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .effect = gItemEffect_DefMochi, @@ -13481,6 +14349,7 @@ const struct Item gItemsInfo[] = .price = 500, .description = sGeniusFeatherDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_STAT_BOOST_MOCHI, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .effect = gItemEffect_SpatkMochi, @@ -13495,6 +14364,7 @@ const struct Item gItemsInfo[] = .price = 500, .description = sCleverFeatherDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_STAT_BOOST_MOCHI, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .effect = gItemEffect_SpdefMochi, @@ -13509,6 +14379,7 @@ const struct Item gItemsInfo[] = .price = 500, .description = sSwiftFeatherDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_STAT_BOOST_MOCHI, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .effect = gItemEffect_SpeedMochi, @@ -13526,6 +14397,7 @@ const struct Item gItemsInfo[] = "能让宝可梦的基础\n" "点数全部消失。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_STAT_BOOST_MOCHI, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_ResetEVs, .effect = gItemEffect_ResetMochi, @@ -13544,6 +14416,7 @@ const struct Item gItemsInfo[] = "获得更多太晶碎块\n" "的护符。"), .pocket = POCKET_KEY_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .iconPic = gItemIcon_GlimmeringCharm, @@ -13572,6 +14445,7 @@ const struct Item gItemsInfo[] = .price = 0, .description = sTeraShardDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_TERA_SHARD, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .iconPic = gItemIcon_StellarTeraShard, @@ -13584,6 +14458,7 @@ const struct Item gItemsInfo[] = .price = 250, .description = sFullHealDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_STATUS_RECOVERY, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .battleUsage = EFFECT_ITEM_CURE_STATUS, @@ -13602,6 +14477,7 @@ const struct Item gItemsInfo[] = "0HP,但很苦,\n" "友好度会降低。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HEALTH_RECOVERY, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .battleUsage = EFFECT_ITEM_RESTORE_HP, @@ -13620,6 +14496,7 @@ const struct Item gItemsInfo[] = "00HP,但很苦\n" ",友好度会降低。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HEALTH_RECOVERY, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .battleUsage = EFFECT_ITEM_RESTORE_HP, @@ -13638,6 +14515,7 @@ const struct Item gItemsInfo[] = "50HP,但很苦\n" ",友好度会降低。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HEALTH_RECOVERY, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .battleUsage = EFFECT_ITEM_RESTORE_HP, @@ -13657,6 +14535,7 @@ const struct Item gItemsInfo[] = "变得较不易被对手\n" "招式命中的道具。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_AUX_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, //.effect = currently missing @@ -13674,6 +14553,7 @@ const struct Item gItemsInfo[] = "可梦防守力的道具\n" "。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_AUX_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, //.effect = currently missing @@ -13691,6 +14571,7 @@ const struct Item gItemsInfo[] = "可梦进攻力的道具\n" "。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_AUX_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, //.effect = currently missing @@ -13708,6 +14589,7 @@ const struct Item gItemsInfo[] = "可梦进攻力和防守\n" "力的道具。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_AUX_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, //.effect = currently missing @@ -13763,9 +14645,13 @@ const struct Item gItemsInfo[] = "玩具。可以在杂货\n" "店出售。"), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_SELLABLE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .iconPic = gItemIcon_PokeshiDoll, .iconPalette = gItemIconPalette_PokeshiDoll, }, }; + +#undef ITEM_NAME +#undef ITEM_PLURAL_NAME diff --git a/src/data/moves_info.h b/src/data/moves_info.h index e05f76acb6..8421147287 100644 --- a/src/data/moves_info.h +++ b/src/data/moves_info.h @@ -164,15 +164,15 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = "容易击中要害。"), .effect = EFFECT_HIT, .power = 50, - .type = TYPE_FIGHTING, + .type = B_UPDATED_MOVE_TYPES >= GEN_2 ? TYPE_FIGHTING : TYPE_NORMAL, .accuracy = 100, - .criticalHitStage = 1, + .criticalHitStage = B_UPDATED_MOVE_DATA >= GEN_3 ? 1 : 2, .pp = 25, .target = MOVE_TARGET_SELECTED, .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, .makesContact = TRUE, - .contestEffect = CONTEST_EFFECT_AFFECTED_BY_PREV_APPEAL, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_HIGHLY_APPEALING : CONTEST_EFFECT_AFFECTED_BY_PREV_APPEAL, .contestCategory = CONTEST_CATEGORY_TOUGH, .contestComboStarterId = 0, .contestComboMoves = {COMBO_STARTER_FOCUS_ENERGY}, @@ -195,8 +195,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, .makesContact = TRUE, - .contestEffect = CONTEST_EFFECT_STARTLE_MON_WITH_JUDGES_ATTENTION, - .contestCategory = CONTEST_CATEGORY_TOUGH, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_QUALITY_DEPENDS_ON_TIMING : CONTEST_EFFECT_STARTLE_MON_WITH_JUDGES_ATTENTION, + .contestCategory = C_UPDATED_MOVE_CATEGORIES >= GEN_6 ? CONTEST_CATEGORY_CUTE : CONTEST_CATEGORY_TOUGH, .contestComboStarterId = 0, .contestComboMoves = {COMBO_STARTER_POUND}, .battleAnimScript = gBattleAnimMove_DoubleSlap, @@ -219,7 +219,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .category = DAMAGE_CATEGORY_PHYSICAL, .makesContact = TRUE, .punchingMove = TRUE, - .contestEffect = CONTEST_EFFECT_BETTER_IF_SAME_TYPE, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_QUALITY_DEPENDS_ON_TIMING : CONTEST_EFFECT_BETTER_IF_SAME_TYPE, .contestCategory = CONTEST_CATEGORY_TOUGH, .contestComboStarterId = 0, .contestComboMoves = {0}, @@ -241,7 +241,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .category = DAMAGE_CATEGORY_PHYSICAL, .makesContact = TRUE, .punchingMove = TRUE, - .contestEffect = CONTEST_EFFECT_HIGHLY_APPEALING, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_REPETITION_NOT_BORING : CONTEST_EFFECT_HIGHLY_APPEALING, .contestCategory = CONTEST_CATEGORY_TOUGH, .contestComboStarterId = 0, .contestComboMoves = {COMBO_STARTER_FOCUS_ENERGY, COMBO_STARTER_MIND_READER}, @@ -266,7 +266,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_PAYDAY, }), - .contestEffect = CONTEST_EFFECT_BETTER_WHEN_AUDIENCE_EXCITED, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_EXCITE_AUDIENCE_IN_ANY_CONTEST : CONTEST_EFFECT_BETTER_WHEN_AUDIENCE_EXCITED, .contestCategory = CONTEST_CATEGORY_SMART, .contestComboStarterId = 0, .contestComboMoves = {0}, @@ -294,7 +294,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .chance = 10, }), .contestEffect = CONTEST_EFFECT_HIGHLY_APPEALING, - .contestCategory = CONTEST_CATEGORY_BEAUTY, + .contestCategory = C_UPDATED_MOVE_CATEGORIES >= GEN_6 ? CONTEST_CATEGORY_COOL : CONTEST_CATEGORY_BEAUTY, .contestComboStarterId = COMBO_STARTER_FIRE_PUNCH, .contestComboMoves = {COMBO_STARTER_ICE_PUNCH, COMBO_STARTER_SUNNY_DAY, COMBO_STARTER_THUNDER_PUNCH}, .battleAnimScript = gBattleAnimMove_FirePunch, @@ -433,8 +433,14 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .effect = EFFECT_TWO_TURNS_ATTACK, .power = 80, .type = TYPE_NORMAL, - .accuracy = 100, - .criticalHitStage = 1, + .accuracy = B_UPDATED_MOVE_DATA >= GEN_3 ? 100 : 75, + #if B_UPDATED_MOVE_DATA >= GEN_4 + .criticalHitStage = 1, + #elif B_UPDATED_MOVE_DATA == GEN_3 + .criticalHitStage = 0, + #else + .criticalHitStage = 2, + #endif .pp = 10, .target = MOVE_TARGET_BOTH, .priority = 0, @@ -491,7 +497,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .category = DAMAGE_CATEGORY_PHYSICAL, .makesContact = TRUE, .slicingMove = TRUE, - .contestEffect = CONTEST_EFFECT_BADLY_STARTLE_MONS_WITH_GOOD_APPEALS, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_HIGHLY_APPEALING : CONTEST_EFFECT_BADLY_STARTLE_MONS_WITH_GOOD_APPEALS, .contestCategory = CONTEST_CATEGORY_COOL, .contestComboStarterId = 0, .contestComboMoves = {COMBO_STARTER_SWORDS_DANCE}, @@ -506,16 +512,16 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = "袭向对手进行攻击。"), .effect = EFFECT_HIT, .power = 40, - .type = TYPE_FLYING, + .type = B_UPDATED_MOVE_TYPES >= GEN_2 ? TYPE_FLYING : TYPE_NORMAL, .accuracy = 100, .pp = 35, .target = MOVE_TARGET_SELECTED, .priority = 0, .category = DAMAGE_CATEGORY_SPECIAL, .ignoresKingsRock = (B_UPDATED_MOVE_FLAGS == GEN_4) || (B_UPDATED_MOVE_FLAGS < GEN_3), - .damagesAirborneDoubleDamage = TRUE, + .damagesAirborneDoubleDamage = B_UPDATED_MOVE_FLAGS >= GEN_2, .windMove = TRUE, - .contestEffect = CONTEST_EFFECT_SCRAMBLE_NEXT_TURN_ORDER, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_STARTLE_PREV_MON : CONTEST_EFFECT_SCRAMBLE_NEXT_TURN_ORDER, .contestCategory = CONTEST_CATEGORY_SMART, .contestComboStarterId = 0, .contestComboMoves = {0}, @@ -529,7 +535,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = "大大地展开美丽的翅膀,\n" "将其撞向对手攻击。"), .effect = EFFECT_HIT, - .power = 60, + .power = B_UPDATED_MOVE_DATA >= GEN_2 ? 60 : 35, .type = TYPE_FLYING, .accuracy = 100, .pp = 35, @@ -537,7 +543,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, .makesContact = TRUE, - .contestEffect = CONTEST_EFFECT_BETTER_IF_SAME_TYPE, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_HIGHLY_APPEALING : CONTEST_EFFECT_BETTER_IF_SAME_TYPE, .contestCategory = CONTEST_CATEGORY_COOL, .contestComboStarterId = 0, .contestComboMoves = {0}, @@ -553,22 +559,33 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .effect = EFFECT_ROAR, .power = 0, .type = TYPE_NORMAL, - .accuracy = B_UPDATED_MOVE_DATA >= GEN_6 ? 0 : 100, + #if B_UPDATED_MOVE_DATA >= GEN_6 + .accuracy = 0, + .priority = -6, + #elif B_UPDATED_MOVE_DATA >= GEN_3 + .accuracy = 100, + .priority = -6, + #elif B_UPDATED_MOVE_DATA == GEN_2 + .accuracy = 100, + .priority = -1, + #else + .accuracy = 85, + .priority = 0, + #endif .pp = 20, .target = MOVE_TARGET_SELECTED, - .priority = -6, .category = DAMAGE_CATEGORY_STATUS, .zMove = { .effect = Z_EFFECT_SPDEF_UP_1 }, .windMove = TRUE, .ignoresProtect = B_UPDATED_MOVE_FLAGS >= GEN_6, .ignoresSubstitute = TRUE, .magicCoatAffected = B_UPDATED_MOVE_FLAGS >= GEN_5, - .copycatBanned = TRUE, - .assistBanned = TRUE, - .contestEffect = CONTEST_EFFECT_SCRAMBLE_NEXT_TURN_ORDER, + .copycatBanned = B_UPDATED_MOVE_FLAGS >= GEN_6, + .assistBanned = B_UPDATED_MOVE_FLAGS >= GEN_6, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_NEXT_APPEAL_LATER : CONTEST_EFFECT_SCRAMBLE_NEXT_TURN_ORDER, .contestCategory = CONTEST_CATEGORY_SMART, .contestComboStarterId = 0, - .contestComboMoves = {0}, + .contestComboMoves = {COMBO_STARTER_STEALTH_ROCK, COMBO_STARTER_SPIKES, COMBO_STARTER_TOXIC_SPIKES}, .battleAnimScript = gBattleAnimMove_Whirlwind, .validApprenticeMove = TRUE, }, @@ -591,9 +608,9 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .gravityBanned = TRUE, .sleepTalkBanned = TRUE, .instructBanned = TRUE, - .assistBanned = TRUE, + .assistBanned = B_UPDATED_MOVE_FLAGS >= GEN_6, .argument.twoTurnAttack = { .stringId = STRINGID_PKMNFLEWHIGH, .status = STATE_ON_AIR }, - .contestEffect = CONTEST_EFFECT_AVOID_STARTLE, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_AVOID_STARTLE_ONCE : CONTEST_EFFECT_AVOID_STARTLE, .contestCategory = CONTEST_CATEGORY_SMART, .contestComboStarterId = 0, .contestComboMoves = {0}, @@ -645,7 +662,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .category = DAMAGE_CATEGORY_PHYSICAL, .makesContact = TRUE, .skyBattleBanned = TRUE, - .contestEffect = CONTEST_EFFECT_STARTLE_MONS_SAME_TYPE_APPEAL, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_HIGHLY_APPEALING : CONTEST_EFFECT_STARTLE_MONS_SAME_TYPE_APPEAL, .contestCategory = CONTEST_CATEGORY_TOUGH, .contestComboStarterId = 0, .contestComboMoves = {COMBO_STARTER_POUND}, @@ -696,13 +713,13 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, .makesContact = TRUE, - .minimizeDoubleDamage = TRUE, + .minimizeDoubleDamage = B_UPDATED_MOVE_FLAGS >= GEN_2, .skyBattleBanned = TRUE, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_FLINCH, .chance = 30, }), - .contestEffect = CONTEST_EFFECT_BADLY_STARTLE_FRONT_MON, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_HIGHLY_APPEALING : CONTEST_EFFECT_BADLY_STARTLE_FRONT_MON, .contestCategory = CONTEST_CATEGORY_TOUGH, .contestComboStarterId = 0, .contestComboMoves = {COMBO_STARTER_LEER}, @@ -726,7 +743,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .category = DAMAGE_CATEGORY_PHYSICAL, .makesContact = TRUE, .strikeCount = 2, - .contestEffect = CONTEST_EFFECT_BETTER_IF_SAME_TYPE, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_STARTLE_MONS_SAME_TYPE_APPEAL : CONTEST_EFFECT_BETTER_IF_SAME_TYPE, .contestCategory = CONTEST_CATEGORY_COOL, .contestComboStarterId = 0, .contestComboMoves = {0}, @@ -749,7 +766,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, .makesContact = TRUE, - .contestEffect = CONTEST_EFFECT_HIGHLY_APPEALING, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_BETTER_WHEN_AUDIENCE_EXCITED : CONTEST_EFFECT_HIGHLY_APPEALING, .contestCategory = CONTEST_CATEGORY_COOL, .contestComboStarterId = 0, .contestComboMoves = {COMBO_STARTER_FOCUS_ENERGY, COMBO_STARTER_MIND_READER}, @@ -765,7 +782,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = "如果踢偏则自己会受到伤害。"), #if B_UPDATED_MOVE_DATA >= GEN_5 .power = 100, - #elif B_UPDATED_MOVE_DATA >= GEN_4 + #elif B_UPDATED_MOVE_DATA == GEN_4 .power = 85, #else .power = 70, @@ -807,7 +824,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .moveEffect = MOVE_EFFECT_FLINCH, .chance = 30, }), - .contestEffect = CONTEST_EFFECT_BADLY_STARTLE_PREV_MONS, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_HIGHLY_APPEALING : CONTEST_EFFECT_BADLY_STARTLE_PREV_MONS, .contestCategory = CONTEST_CATEGORY_COOL, .contestComboStarterId = 0, .contestComboMoves = {0}, @@ -823,7 +840,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = "从而降低命中率。"), .effect = EFFECT_ACCURACY_DOWN, .power = 0, - .type = TYPE_GROUND, + .type = B_UPDATED_MOVE_TYPES >= GEN_2 ? TYPE_GROUND : TYPE_NORMAL, .accuracy = 100, .pp = 15, .target = MOVE_TARGET_SELECTED, @@ -831,7 +848,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .category = DAMAGE_CATEGORY_STATUS, .zMove = { .effect = Z_EFFECT_EVSN_UP_1 }, .magicCoatAffected = TRUE, - .contestEffect = CONTEST_EFFECT_STARTLE_MON_WITH_JUDGES_ATTENTION, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_SHIFT_JUDGE_ATTENTION : CONTEST_EFFECT_STARTLE_MON_WITH_JUDGES_ATTENTION, .contestCategory = CONTEST_CATEGORY_CUTE, .contestComboStarterId = COMBO_STARTER_SAND_ATTACK, .contestComboMoves = {COMBO_STARTER_MUD_SLAP, COMBO_STARTER_SANDSTORM}, @@ -858,7 +875,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .moveEffect = MOVE_EFFECT_FLINCH, .chance = 30, }), - .contestEffect = CONTEST_EFFECT_STARTLE_PREV_MON, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_HIGHLY_APPEALING : CONTEST_EFFECT_STARTLE_PREV_MON, .contestCategory = CONTEST_CATEGORY_TOUGH, .contestComboStarterId = 0, .contestComboMoves = {COMBO_STARTER_FOCUS_ENERGY}, @@ -902,7 +919,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, .makesContact = TRUE, - .contestEffect = CONTEST_EFFECT_STARTLE_MON_WITH_JUDGES_ATTENTION, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_QUALITY_DEPENDS_ON_TIMING : CONTEST_EFFECT_STARTLE_MON_WITH_JUDGES_ATTENTION, .contestCategory = CONTEST_CATEGORY_COOL, .contestComboStarterId = 0, .contestComboMoves = {COMBO_STARTER_HORN_ATTACK, COMBO_STARTER_PECK}, @@ -1004,6 +1021,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, .makesContact = TRUE, + .ignoresKingsRock = B_UPDATED_MOVE_FLAGS < GEN_3, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_WRAP, .multistring.wrapped = B_MSG_WRAPPED_WRAP, @@ -1060,7 +1078,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .moveEffect = MOVE_EFFECT_THRASH, .self = TRUE, }), - .contestEffect = CONTEST_EFFECT_JAMS_OTHERS_BUT_MISS_ONE_TURN, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_USER_MORE_EASILY_STARTLED : CONTEST_EFFECT_JAMS_OTHERS_BUT_MISS_ONE_TURN, .contestCategory = CONTEST_CATEGORY_TOUGH, .contestComboStarterId = 0, .contestComboMoves = {COMBO_STARTER_RAGE}, @@ -1075,14 +1093,14 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = "拼命地猛撞向对手攻击。\n" "自己也会受到不小的伤害。"), .effect = EFFECT_RECOIL, - .power = 120, + .power = B_UPDATED_MOVE_DATA >= GEN_2 ? 120 : 100, .type = TYPE_NORMAL, .accuracy = 100, .pp = 15, .target = MOVE_TARGET_SELECTED, .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, - .argument = { .recoilPercentage = 33 }, + .argument = { .recoilPercentage = B_UPDATED_MOVE_DATA >= GEN_3 ? 33 : 25 }, .makesContact = TRUE, .contestEffect = CONTEST_EFFECT_USER_MORE_EASILY_STARTLED, .contestCategory = CONTEST_CATEGORY_TOUGH, @@ -1131,7 +1149,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .category = DAMAGE_CATEGORY_PHYSICAL, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_POISON, - .chance = 30, + .chance = B_UPDATED_MOVE_DATA >= GEN_2 ? 30 : 20, }), .contestEffect = CONTEST_EFFECT_STARTLE_PREV_MON, .contestCategory = CONTEST_CATEGORY_SMART, @@ -1160,7 +1178,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .moveEffect = MOVE_EFFECT_POISON, .chance = 20, }), - .contestEffect = CONTEST_EFFECT_STARTLE_PREV_MON, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_BETTER_IF_SAME_TYPE : CONTEST_EFFECT_STARTLE_PREV_MON, .contestCategory = CONTEST_CATEGORY_COOL, .contestComboStarterId = 0, .contestComboMoves = {0}, @@ -1182,7 +1200,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .target = MOVE_TARGET_SELECTED, .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, - .contestEffect = CONTEST_EFFECT_STARTLE_MON_WITH_JUDGES_ATTENTION, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_QUALITY_DEPENDS_ON_TIMING : CONTEST_EFFECT_STARTLE_MON_WITH_JUDGES_ATTENTION, .contestCategory = CONTEST_CATEGORY_COOL, .contestComboStarterId = 0, .contestComboMoves = {0}, @@ -1205,7 +1223,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .category = DAMAGE_CATEGORY_STATUS, .zMove = { .effect = Z_EFFECT_ATK_UP_1 }, .magicCoatAffected = TRUE, - .contestEffect = CONTEST_EFFECT_DONT_EXCITE_AUDIENCE, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_STARTLE_MON_WITH_JUDGES_ATTENTION : CONTEST_EFFECT_DONT_EXCITE_AUDIENCE, .contestCategory = CONTEST_CATEGORY_COOL, .contestComboStarterId = COMBO_STARTER_LEER, .contestComboMoves = {COMBO_STARTER_RAGE, COMBO_STARTER_SCARY_FACE}, @@ -1220,7 +1238,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = "有时会使对手畏缩。"), .effect = EFFECT_HIT, .power = 60, - .type = TYPE_DARK, + .type = B_UPDATED_MOVE_TYPES >= GEN_2 ? TYPE_DARK : TYPE_NORMAL, .accuracy = 100, .pp = 25, .target = MOVE_TARGET_SELECTED, @@ -1230,9 +1248,9 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .bitingMove = TRUE, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_FLINCH, - .chance = 30, + .chance = B_UPDATED_MOVE_DATA >= GEN_2 ? 30 : 10, }), - .contestEffect = CONTEST_EFFECT_BADLY_STARTLE_PREV_MONS, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_STARTLE_PREV_MON : CONTEST_EFFECT_BADLY_STARTLE_PREV_MONS, .contestCategory = CONTEST_CATEGORY_TOUGH, .contestComboStarterId = 0, .contestComboMoves = {COMBO_STARTER_LEER, COMBO_STARTER_SCARY_FACE}, @@ -1277,19 +1295,25 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .accuracy = B_UPDATED_MOVE_DATA >= GEN_6 ? 0 : 100, .pp = 20, .target = MOVE_TARGET_SELECTED, - .priority = -6, + #if B_UPDATED_MOVE_DATA >= GEN_3 + .priority = -6, + #elif B_UPDATED_MOVE_DATA == GEN_2 + .priority = -1, + #else + .priority = 0, + #endif .category = DAMAGE_CATEGORY_STATUS, .zMove = { .effect = Z_EFFECT_DEF_UP_1 }, .ignoresProtect = B_UPDATED_MOVE_FLAGS >= GEN_6, .ignoresSubstitute = B_UPDATED_MOVE_FLAGS >= GEN_6, .magicCoatAffected = B_UPDATED_MOVE_FLAGS >= GEN_5, .soundMove = TRUE, - .copycatBanned = TRUE, - .assistBanned = TRUE, - .contestEffect = CONTEST_EFFECT_SCRAMBLE_NEXT_TURN_ORDER, + .copycatBanned = B_UPDATED_MOVE_FLAGS >= GEN_6, + .assistBanned = B_UPDATED_MOVE_FLAGS >= GEN_6, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_NEXT_APPEAL_LATER : CONTEST_EFFECT_SCRAMBLE_NEXT_TURN_ORDER, .contestCategory = CONTEST_CATEGORY_COOL, .contestComboStarterId = 0, - .contestComboMoves = {0}, + .contestComboMoves = {COMBO_STARTER_STEALTH_ROCK, COMBO_STARTER_ENTRAINMENT, COMBO_STARTER_PLAY_NICE, COMBO_STARTER_SPIKES, COMBO_STARTER_TOXIC_SPIKES}, .battleAnimScript = gBattleAnimMove_Roar, .validApprenticeMove = TRUE, }, @@ -1339,7 +1363,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .ignoresSubstitute = B_UPDATED_MOVE_FLAGS >= GEN_6, .magicCoatAffected = TRUE, .soundMove = TRUE, - .contestEffect = CONTEST_EFFECT_SCRAMBLE_NEXT_TURN_ORDER, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_SHIFT_JUDGE_ATTENTION : CONTEST_EFFECT_SCRAMBLE_NEXT_TURN_ORDER, .contestCategory = CONTEST_CATEGORY_SMART, .contestComboStarterId = 0, .contestComboMoves = {0}, @@ -1362,7 +1386,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .priority = 0, .category = DAMAGE_CATEGORY_SPECIAL, .argument = { .fixedDamage = 20 }, - .contestEffect = CONTEST_EFFECT_BETTER_IF_SAME_TYPE, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_REPETITION_NOT_BORING : CONTEST_EFFECT_BETTER_IF_SAME_TYPE, .contestCategory = CONTEST_CATEGORY_COOL, .contestComboStarterId = 0, .contestComboMoves = {0}, @@ -1417,9 +1441,9 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .category = DAMAGE_CATEGORY_SPECIAL, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = B_UPDATED_MOVE_DATA >= GEN_4 ? MOVE_EFFECT_SP_DEF_MINUS_1 : MOVE_EFFECT_DEF_MINUS_1, - .chance = 10, + .chance = B_UPDATED_MOVE_DATA >= GEN_2 ? 10 : 33, }), - .contestEffect = CONTEST_EFFECT_BADLY_STARTLE_FRONT_MON, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_WORSEN_CONDITION_OF_PREV_MONS : CONTEST_EFFECT_BADLY_STARTLE_FRONT_MON, .contestCategory = CONTEST_CATEGORY_SMART, .contestComboStarterId = 0, .contestComboMoves = {0}, @@ -1445,7 +1469,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .chance = 10, }), .contestEffect = CONTEST_EFFECT_HIGHLY_APPEALING, - .contestCategory = CONTEST_CATEGORY_BEAUTY, + .contestCategory = C_UPDATED_MOVE_CATEGORIES >= GEN_6 ? CONTEST_CATEGORY_CUTE : CONTEST_CATEGORY_BEAUTY, .contestComboStarterId = 0, .contestComboMoves = {COMBO_STARTER_SUNNY_DAY}, .battleAnimScript = gBattleAnimMove_Ember, @@ -1538,7 +1562,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .target = MOVE_TARGET_SELECTED, .priority = 0, .category = DAMAGE_CATEGORY_SPECIAL, - .contestEffect = CONTEST_EFFECT_HIGHLY_APPEALING, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_BETTER_WHEN_AUDIENCE_EXCITED : CONTEST_EFFECT_HIGHLY_APPEALING, .contestCategory = CONTEST_CATEGORY_BEAUTY, .contestComboStarterId = 0, .contestComboMoves = {COMBO_STARTER_RAIN_DANCE}, @@ -1562,7 +1586,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .category = DAMAGE_CATEGORY_SPECIAL, .damagesUnderwater = TRUE, .skyBattleBanned = TRUE, - .contestEffect = CONTEST_EFFECT_AFFECTED_BY_PREV_APPEAL, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_STARTLE_PREV_MONS : CONTEST_EFFECT_AFFECTED_BY_PREV_APPEAL, .contestCategory = CONTEST_CATEGORY_BEAUTY, .contestComboStarterId = COMBO_STARTER_SURF, .contestComboMoves = {COMBO_STARTER_DIVE, COMBO_STARTER_RAIN_DANCE}, @@ -1590,7 +1614,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .moveEffect = MOVE_EFFECT_FREEZE_OR_FROSTBITE, .chance = 10, }), - .contestEffect = CONTEST_EFFECT_STARTLE_MONS_SAME_TYPE_APPEAL, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_BADLY_STARTLE_FRONT_MON : CONTEST_EFFECT_STARTLE_MONS_SAME_TYPE_APPEAL, .contestCategory = CONTEST_CATEGORY_BEAUTY, .contestComboStarterId = 0, .contestComboMoves = {COMBO_STARTER_HAIL}, @@ -1607,7 +1631,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .effect = EFFECT_HIT, .power = B_UPDATED_MOVE_DATA >= GEN_6 ? 110 : 120, .type = TYPE_ICE, - .accuracy = 70, + .accuracy = B_UPDATED_MOVE_DATA >= GEN_2 ? 70 : 90, .pp = 5, .target = MOVE_TARGET_BOTH, .priority = 0, @@ -1618,7 +1642,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .moveEffect = MOVE_EFFECT_FREEZE_OR_FROSTBITE, .chance = 10, }), - .contestEffect = CONTEST_EFFECT_HIGHLY_APPEALING, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_BADLY_STARTLE_PREV_MONS : CONTEST_EFFECT_HIGHLY_APPEALING, .contestCategory = CONTEST_CATEGORY_BEAUTY, .contestComboStarterId = 0, .contestComboMoves = {COMBO_STARTER_HAIL, COMBO_STARTER_POWDER_SNOW}, @@ -1644,7 +1668,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .moveEffect = MOVE_EFFECT_CONFUSION, .chance = 10, }), - .contestEffect = CONTEST_EFFECT_SCRAMBLE_NEXT_TURN_ORDER, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_SHIFT_JUDGE_ATTENTION : CONTEST_EFFECT_SCRAMBLE_NEXT_TURN_ORDER, .contestCategory = CONTEST_CATEGORY_BEAUTY, .contestComboStarterId = 0, .contestComboMoves = {COMBO_STARTER_CALM_MIND}, @@ -1668,9 +1692,9 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .category = DAMAGE_CATEGORY_SPECIAL, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_SPD_MINUS_1, - .chance = 10, + .chance = B_UPDATED_MOVE_DATA >= GEN_2 ? 10 : 33, }), - .contestEffect = CONTEST_EFFECT_BADLY_STARTLE_PREV_MONS, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_STARTLE_PREV_MON : CONTEST_EFFECT_BADLY_STARTLE_PREV_MONS, .contestCategory = CONTEST_CATEGORY_BEAUTY, .contestComboStarterId = 0, .contestComboMoves = {COMBO_STARTER_RAIN_DANCE}, @@ -1693,9 +1717,9 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .category = DAMAGE_CATEGORY_SPECIAL, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_ATK_MINUS_1, - .chance = 10, + .chance = B_UPDATED_MOVE_DATA >= GEN_2 ? 10 : 33, }), - .contestEffect = CONTEST_EFFECT_STARTLE_MONS_SAME_TYPE_APPEAL, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_STARTLE_PREV_MON : CONTEST_EFFECT_STARTLE_MONS_SAME_TYPE_APPEAL, .contestCategory = CONTEST_CATEGORY_BEAUTY, .contestComboStarterId = 0, .contestComboMoves = {COMBO_STARTER_HAIL}, @@ -1764,7 +1788,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, .makesContact = TRUE, - .contestEffect = CONTEST_EFFECT_HIGHLY_APPEALING, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_AFFECTED_BY_PREV_APPEAL : CONTEST_EFFECT_HIGHLY_APPEALING, .contestCategory = CONTEST_CATEGORY_COOL, .contestComboStarterId = 0, .contestComboMoves = {COMBO_STARTER_PECK}, @@ -1805,13 +1829,13 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .effect = EFFECT_LOW_KICK, .power = 1, .type = TYPE_FIGHTING, - .accuracy = 100, + .accuracy = B_UPDATED_MOVE_DATA >= GEN_3 ? 100 : 90, .pp = 20, .target = MOVE_TARGET_SELECTED, .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, .makesContact = TRUE, - .contestEffect = CONTEST_EFFECT_BADLY_STARTLE_FRONT_MON, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_BETTER_WHEN_LATER : CONTEST_EFFECT_BADLY_STARTLE_FRONT_MON, .contestCategory = CONTEST_CATEGORY_TOUGH, .contestComboStarterId = 0, .contestComboMoves = {0}, @@ -1834,15 +1858,17 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .priority = -5, .category = DAMAGE_CATEGORY_PHYSICAL, .makesContact = TRUE, + .ignoresProtect = B_UPDATED_MOVE_FLAGS < GEN_5, .ignoresKingsRock = (B_UPDATED_MOVE_FLAGS == GEN_3 || B_UPDATED_MOVE_FLAGS == GEN_4), .meFirstBanned = TRUE, .metronomeBanned = B_UPDATED_MOVE_FLAGS >= GEN_2, .copycatBanned = TRUE, .assistBanned = TRUE, - .contestEffect = CONTEST_EFFECT_AVOID_STARTLE_ONCE, + .mirrorMoveBanned = B_UPDATED_MOVE_FLAGS >= GEN_4, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_BETTER_IF_LAST : CONTEST_EFFECT_AVOID_STARTLE_ONCE, .contestCategory = CONTEST_CATEGORY_TOUGH, .contestComboStarterId = 0, - .contestComboMoves = {COMBO_STARTER_TAUNT}, + .contestComboMoves = {COMBO_STARTER_TAUNT, COMBO_STARTER_ENCORE, COMBO_STARTER_TORMENT}, .battleAnimScript = gBattleAnimMove_Counter, .validApprenticeMove = TRUE, }, @@ -1863,10 +1889,10 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .category = DAMAGE_CATEGORY_PHYSICAL, .makesContact = TRUE, .skyBattleBanned = TRUE, - .contestEffect = CONTEST_EFFECT_STARTLE_MONS_SAME_TYPE_APPEAL, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_REPETITION_NOT_BORING : CONTEST_EFFECT_STARTLE_MONS_SAME_TYPE_APPEAL, .contestCategory = CONTEST_CATEGORY_TOUGH, .contestComboStarterId = 0, - .contestComboMoves = {COMBO_STARTER_FAKE_OUT}, + .contestComboMoves = {COMBO_STARTER_FAKE_OUT, COMBO_STARTER_ENTRAINMENT, COMBO_STARTER_PLAY_NICE}, .battleAnimScript = gBattleAnimMove_SeismicToss, .validApprenticeMove = TRUE, }, @@ -1886,7 +1912,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, .makesContact = TRUE, - .contestEffect = CONTEST_EFFECT_STARTLE_MONS_SAME_TYPE_APPEAL, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_HIGHLY_APPEALING : CONTEST_EFFECT_STARTLE_MONS_SAME_TYPE_APPEAL, .contestCategory = CONTEST_CATEGORY_TOUGH, .contestComboStarterId = 0, .contestComboMoves = {0}, @@ -1911,7 +1937,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .argument = { .absorbPercentage = 50 }, .ignoresKingsRock = (B_UPDATED_MOVE_FLAGS == GEN_3 || B_UPDATED_MOVE_FLAGS == GEN_4), .healingMove = B_HEAL_BLOCKING >= GEN_6, - .contestEffect = CONTEST_EFFECT_STARTLE_PREV_MON, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_HIGHLY_APPEALING : CONTEST_EFFECT_STARTLE_PREV_MON, .contestCategory = CONTEST_CATEGORY_SMART, .contestComboStarterId = 0, .contestComboMoves = {COMBO_STARTER_GROWTH}, @@ -1934,7 +1960,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .zMove = { .powerOverride = 120 }, .ignoresKingsRock = (B_UPDATED_MOVE_FLAGS == GEN_3 || B_UPDATED_MOVE_FLAGS == GEN_4), .healingMove = B_HEAL_BLOCKING >= GEN_6, - .contestEffect = CONTEST_EFFECT_BADLY_STARTLE_FRONT_MON, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_STARTLE_PREV_MON : CONTEST_EFFECT_BADLY_STARTLE_FRONT_MON, .contestCategory = CONTEST_CATEGORY_SMART, .contestComboStarterId = 0, .contestComboMoves = {COMBO_STARTER_GROWTH}, @@ -1957,10 +1983,10 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .category = DAMAGE_CATEGORY_STATUS, .zMove = { .effect = Z_EFFECT_RESET_STATS }, .magicCoatAffected = TRUE, - .contestEffect = CONTEST_EFFECT_STARTLE_PREV_MONS, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_IMPROVE_CONDITION_PREVENT_NERVOUSNESS : CONTEST_EFFECT_STARTLE_PREV_MONS, .contestCategory = CONTEST_CATEGORY_SMART, .contestComboStarterId = COMBO_STARTER_LEECH_SEED, - .contestComboMoves = {COMBO_STARTER_GROWTH, COMBO_STARTER_WORRY_SEED}, + .contestComboMoves = {COMBO_STARTER_GROWTH, COMBO_STARTER_WORRY_SEED, COMBO_STARTER_ROTOTILLER}, .battleAnimScript = gBattleAnimMove_LeechSeed, .validApprenticeMove = TRUE, }, @@ -1986,7 +2012,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .contestEffect = CONTEST_EFFECT_IMPROVE_CONDITION_PREVENT_NERVOUSNESS, .contestCategory = CONTEST_CATEGORY_BEAUTY, .contestComboStarterId = COMBO_STARTER_GROWTH, - .contestComboMoves = {0}, + .contestComboMoves = {COMBO_STARTER_SUNNY_DAY}, .battleAnimScript = gBattleAnimMove_Growth, .validApprenticeMove = TRUE, }, @@ -2001,13 +2027,13 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .power = 55, .type = TYPE_GRASS, .accuracy = 95, - .criticalHitStage = 1, + .criticalHitStage = B_UPDATED_MOVE_DATA >= GEN_3 ? 1 : 2, .pp = 25, .target = MOVE_TARGET_BOTH, .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, .slicingMove = TRUE, - .contestEffect = CONTEST_EFFECT_AFFECTED_BY_PREV_APPEAL, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_HIGHLY_APPEALING : CONTEST_EFFECT_AFFECTED_BY_PREV_APPEAL, .contestCategory = CONTEST_CATEGORY_COOL, .contestComboStarterId = 0, .contestComboMoves = {COMBO_STARTER_GROWTH}, @@ -2032,7 +2058,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .sleepTalkBanned = TRUE, .instructBanned = TRUE, .argument.twoTurnAttack = { .stringId = STRINGID_PKMNTOOKSUNLIGHT, .status = B_WEATHER_SUN }, - .contestEffect = CONTEST_EFFECT_HIGHLY_APPEALING, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_AFFECTED_BY_PREV_APPEAL : CONTEST_EFFECT_HIGHLY_APPEALING, .contestCategory = CONTEST_CATEGORY_COOL, .contestComboStarterId = 0, .contestComboMoves = {COMBO_STARTER_GROWTH, COMBO_STARTER_SUNNY_DAY}, @@ -2060,7 +2086,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .powderMove = TRUE, .contestEffect = CONTEST_EFFECT_WORSEN_CONDITION_OF_PREV_MONS, .contestCategory = CONTEST_CATEGORY_SMART, - .contestComboStarterId = 0, + .contestComboStarterId = COMBO_STARTER_POISON_POWDER, .contestComboMoves = {COMBO_STARTER_SWEET_SCENT}, .battleAnimScript = gBattleAnimMove_PoisonPowder, .validApprenticeMove = TRUE, @@ -2112,7 +2138,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .powderMove = TRUE, .contestEffect = CONTEST_EFFECT_BADLY_STARTLE_PREV_MONS, .contestCategory = CONTEST_CATEGORY_SMART, - .contestComboStarterId = 0, + .contestComboStarterId = COMBO_STARTER_SLEEP_POWDER, .contestComboMoves = {COMBO_STARTER_SWEET_SCENT}, .battleAnimScript = gBattleAnimMove_SleepPowder, .validApprenticeMove = TRUE, @@ -2145,7 +2171,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .moveEffect = MOVE_EFFECT_THRASH, .self = TRUE, }), - .contestEffect = CONTEST_EFFECT_JAMS_OTHERS_BUT_MISS_ONE_TURN, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_USER_MORE_EASILY_STARTLED : CONTEST_EFFECT_JAMS_OTHERS_BUT_MISS_ONE_TURN, .contestCategory = CONTEST_CATEGORY_BEAUTY, .contestComboStarterId = 0, .contestComboMoves = {COMBO_STARTER_GROWTH}, @@ -2192,7 +2218,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .category = DAMAGE_CATEGORY_SPECIAL, .ignoresKingsRock = (B_UPDATED_MOVE_FLAGS == GEN_4) || (B_UPDATED_MOVE_FLAGS < GEN_3), .argument = { .fixedDamage = 40 }, - .contestEffect = CONTEST_EFFECT_BETTER_WHEN_LATER, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_REPETITION_NOT_BORING : CONTEST_EFFECT_BETTER_WHEN_LATER, .contestCategory = CONTEST_CATEGORY_COOL, .contestComboStarterId = COMBO_STARTER_DRAGON_RAGE, .contestComboMoves = {COMBO_STARTER_DRAGON_BREATH, COMBO_STARTER_DRAGON_DANCE, COMBO_STARTER_DRAGON_RUSH, COMBO_STARTER_DRAGON_TAIL}, @@ -2295,9 +2321,9 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .argument = { .nonVolatileStatus = MOVE_EFFECT_PARALYSIS }, .zMove = { .effect = Z_EFFECT_SPDEF_UP_1 }, .magicCoatAffected = TRUE, - .contestEffect = CONTEST_EFFECT_BADLY_STARTLE_MONS_WITH_GOOD_APPEALS, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_BADLY_STARTLE_PREV_MONS : CONTEST_EFFECT_BADLY_STARTLE_MONS_WITH_GOOD_APPEALS, .contestCategory = CONTEST_CATEGORY_COOL, - .contestComboStarterId = 0, + .contestComboStarterId = COMBO_STARTER_THUNDER_WAVE, .contestComboMoves = {COMBO_STARTER_CHARGE}, .battleAnimScript = gBattleAnimMove_ThunderWave, .validApprenticeMove = TRUE, @@ -2317,14 +2343,14 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .target = MOVE_TARGET_SELECTED, .priority = 0, .category = DAMAGE_CATEGORY_SPECIAL, - .damagesAirborne = TRUE, + .damagesAirborne = B_UPDATED_MOVE_FLAGS >= GEN_2, .alwaysHitsInRain = TRUE, .accuracy50InSun = TRUE, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_PARALYSIS, - .chance = 30, + .chance = B_UPDATED_MOVE_DATA >= GEN_2 ? 30 : 10, }), - .contestEffect = CONTEST_EFFECT_STARTLE_PREV_MONS, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_BETTER_WHEN_AUDIENCE_EXCITED : CONTEST_EFFECT_STARTLE_PREV_MONS, .contestCategory = CONTEST_CATEGORY_COOL, .contestComboStarterId = 0, .contestComboMoves = {COMBO_STARTER_CHARGE, COMBO_STARTER_LOCK_ON, COMBO_STARTER_RAIN_DANCE}, @@ -2341,12 +2367,12 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .effect = EFFECT_HIT, .power = 50, .type = TYPE_ROCK, - .accuracy = 90, + .accuracy = B_UPDATED_MOVE_DATA >= GEN_2 ? 90 : 65, .pp = 15, .target = MOVE_TARGET_SELECTED, .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, - .contestEffect = CONTEST_EFFECT_BETTER_IF_SAME_TYPE, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_HIGHLY_APPEALING : CONTEST_EFFECT_BETTER_IF_SAME_TYPE, .contestCategory = CONTEST_CATEGORY_TOUGH, .contestComboStarterId = COMBO_STARTER_ROCK_THROW, .contestComboMoves = {0}, @@ -2368,9 +2394,9 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, .ignoresKingsRock = B_UPDATED_MOVE_FLAGS < GEN_3, - .damagesUnderground = TRUE, + .damagesUnderground = B_UPDATED_MOVE_FLAGS >= GEN_2, .skyBattleBanned = TRUE, - .contestEffect = CONTEST_EFFECT_BADLY_STARTLE_PREV_MONS, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_BADLY_STARTLE_MONS_WITH_GOOD_APPEALS : CONTEST_EFFECT_BADLY_STARTLE_PREV_MONS, .contestCategory = CONTEST_CATEGORY_TOUGH, .contestComboStarterId = COMBO_STARTER_EARTHQUAKE, .contestComboMoves = {0}, @@ -2409,7 +2435,13 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = "第1回合钻入地底,\n" "第2回合攻击对手。"), .effect = EFFECT_SEMI_INVULNERABLE, - .power = B_UPDATED_MOVE_DATA >= GEN_4 ? 80 : 60, + #if B_UPDATED_MOVE_DATA >= GEN_4 + .power = 80, + #elif B_UPDATED_MOVE_DATA >= GEN_2 + .power = 60, + #else + .power = 100, + #endif .type = TYPE_GROUND, .accuracy = 100, .pp = 10, @@ -2419,11 +2451,11 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .makesContact = TRUE, .sleepTalkBanned = TRUE, .instructBanned = TRUE, - .assistBanned = TRUE, + .assistBanned = B_UPDATED_MOVE_FLAGS >= GEN_6, .skyBattleBanned = TRUE, .argument.twoTurnAttack = { .stringId = STRINGID_PKMNDUGHOLE, .status = STATE_UNDERGROUND }, - .contestEffect = CONTEST_EFFECT_AVOID_STARTLE, - .contestCategory = CONTEST_CATEGORY_SMART, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_AVOID_STARTLE_ONCE : CONTEST_EFFECT_AVOID_STARTLE, + .contestCategory = C_UPDATED_MOVE_CATEGORIES >= GEN_6 ? CONTEST_CATEGORY_TOUGH : CONTEST_CATEGORY_SMART, .contestComboStarterId = 0, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_Dig, @@ -2473,7 +2505,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .moveEffect = MOVE_EFFECT_CONFUSION, .chance = 10, }), - .contestEffect = CONTEST_EFFECT_STARTLE_PREV_MON, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_HIGHLY_APPEALING : CONTEST_EFFECT_STARTLE_PREV_MON, .contestCategory = CONTEST_CATEGORY_SMART, .contestComboStarterId = COMBO_STARTER_CONFUSION, .contestComboMoves = {COMBO_STARTER_CALM_MIND, COMBO_STARTER_KINESIS, COMBO_STARTER_PSYCHIC}, @@ -2496,9 +2528,9 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .category = DAMAGE_CATEGORY_SPECIAL, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_SP_DEF_MINUS_1, - .chance = 10, + .chance = B_UPDATED_MOVE_DATA >= GEN_2 ? 10 : 33, }), - .contestEffect = CONTEST_EFFECT_BADLY_STARTLE_PREV_MONS, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_HIGHLY_APPEALING : CONTEST_EFFECT_BADLY_STARTLE_PREV_MONS, .contestCategory = CONTEST_CATEGORY_SMART, .contestComboStarterId = COMBO_STARTER_PSYCHIC, .contestComboMoves = {COMBO_STARTER_CALM_MIND, COMBO_STARTER_CONFUSION, COMBO_STARTER_KINESIS}, @@ -2577,7 +2609,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .snatchAffected = TRUE, .contestEffect = CONTEST_EFFECT_NEXT_APPEAL_EARLIER, .contestCategory = CONTEST_CATEGORY_COOL, - .contestComboStarterId = 0, + .contestComboStarterId = COMBO_STARTER_AGILITY, .contestComboMoves = {COMBO_STARTER_DOUBLE_TEAM}, .battleAnimScript = gBattleAnimMove_Agility, .validApprenticeMove = TRUE, @@ -2621,8 +2653,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, .makesContact = TRUE, - .contestEffect = CONTEST_EFFECT_REPETITION_NOT_BORING, - .contestCategory = CONTEST_CATEGORY_COOL, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_BADLY_STARTLE_PREV_MONS : CONTEST_EFFECT_REPETITION_NOT_BORING, + .contestCategory = C_UPDATED_MOVE_CATEGORIES >= GEN_6 ? CONTEST_CATEGORY_TOUGH : CONTEST_CATEGORY_COOL, .contestComboStarterId = COMBO_STARTER_RAGE, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_Rage, @@ -2640,7 +2672,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .accuracy = 0, .pp = 20, .target = MOVE_TARGET_USER, - .priority = -6, + .priority = B_UPDATED_MOVE_DATA >= GEN_8 ? -6 : 0, .category = DAMAGE_CATEGORY_STATUS, .zMove = { .effect = Z_EFFECT_RECOVER_HP }, .ignoresProtect = TRUE, @@ -2666,7 +2698,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .target = MOVE_TARGET_SELECTED, .priority = 0, .category = DAMAGE_CATEGORY_SPECIAL, - .contestEffect = CONTEST_EFFECT_STARTLE_MONS_SAME_TYPE_APPEAL, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_REPETITION_NOT_BORING : CONTEST_EFFECT_STARTLE_MONS_SAME_TYPE_APPEAL, .contestCategory = CONTEST_CATEGORY_SMART, .contestComboStarterId = 0, .contestComboMoves = {0}, @@ -2683,7 +2715,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .effect = EFFECT_MIMIC, .power = 0, .type = TYPE_NORMAL, - .accuracy = 0, + .accuracy = B_UPDATED_MOVE_DATA >= GEN_3 ? 0 : 100, .pp = 10, .target = MOVE_TARGET_SELECTED, .priority = 0, @@ -2723,7 +2755,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .ignoresSubstitute = B_UPDATED_MOVE_FLAGS >= GEN_6, .magicCoatAffected = TRUE, .soundMove = TRUE, - .contestEffect = CONTEST_EFFECT_BADLY_STARTLE_PREV_MONS, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_SHIFT_JUDGE_ATTENTION : CONTEST_EFFECT_BADLY_STARTLE_PREV_MONS, .contestCategory = CONTEST_CATEGORY_SMART, .contestComboStarterId = 0, .contestComboMoves = {0}, @@ -2749,7 +2781,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .ignoresProtect = TRUE, .mirrorMoveBanned = TRUE, .snatchAffected = TRUE, - .contestEffect = CONTEST_EFFECT_AVOID_STARTLE_ONCE, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_IMPROVE_CONDITION_PREVENT_NERVOUSNESS : CONTEST_EFFECT_AVOID_STARTLE_ONCE, .contestCategory = CONTEST_CATEGORY_COOL, .contestComboStarterId = COMBO_STARTER_DOUBLE_TEAM, .contestComboMoves = {0}, @@ -2782,7 +2814,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .mirrorMoveBanned = TRUE, .healingMove = TRUE, .snatchAffected = TRUE, - .contestEffect = CONTEST_EFFECT_STARTLE_MONS_SAME_TYPE_APPEAL, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_BETTER_IF_SAME_TYPE : CONTEST_EFFECT_STARTLE_MONS_SAME_TYPE_APPEAL, .contestCategory = CONTEST_CATEGORY_SMART, .contestComboStarterId = 0, .contestComboMoves = {0}, @@ -2834,7 +2866,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .ignoresProtect = TRUE, .mirrorMoveBanned = TRUE, .snatchAffected = TRUE, - .contestEffect = CONTEST_EFFECT_AVOID_STARTLE_ONCE, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_AVOID_STARTLE : CONTEST_EFFECT_AVOID_STARTLE_ONCE, .contestCategory = CONTEST_CATEGORY_CUTE, .contestComboStarterId = 0, .contestComboMoves = {0}, @@ -2858,7 +2890,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .category = DAMAGE_CATEGORY_STATUS, .zMove = { .effect = Z_EFFECT_EVSN_UP_1 }, .magicCoatAffected = TRUE, - .contestEffect = CONTEST_EFFECT_SHIFT_JUDGE_ATTENTION, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_STARTLE_PREV_MON : CONTEST_EFFECT_SHIFT_JUDGE_ATTENTION, .contestCategory = CONTEST_CATEGORY_SMART, .contestComboStarterId = 0, .contestComboMoves = {COMBO_STARTER_SMOG}, @@ -2882,7 +2914,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .category = DAMAGE_CATEGORY_STATUS, .zMove = { .effect = Z_EFFECT_SPATK_UP_1 }, .magicCoatAffected = TRUE, - .contestEffect = CONTEST_EFFECT_SCRAMBLE_NEXT_TURN_ORDER, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_STARTLE_MON_WITH_JUDGES_ATTENTION : CONTEST_EFFECT_SCRAMBLE_NEXT_TURN_ORDER, .contestCategory = CONTEST_CATEGORY_SMART, .contestComboStarterId = 0, .contestComboMoves = {0}, @@ -2908,7 +2940,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .ignoresProtect = TRUE, .mirrorMoveBanned = TRUE, .snatchAffected = TRUE, - .contestEffect = CONTEST_EFFECT_AVOID_STARTLE, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_AVOID_STARTLE_ONCE : CONTEST_EFFECT_AVOID_STARTLE, .contestCategory = CONTEST_CATEGORY_CUTE, .contestComboStarterId = 0, .contestComboMoves = {COMBO_STARTER_RAIN_DANCE}, @@ -2986,7 +3018,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .ignoresProtect = TRUE, .mirrorMoveBanned = TRUE, .snatchAffected = TRUE, - .contestEffect = CONTEST_EFFECT_AVOID_STARTLE, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_AVOID_STARTLE_ONCE : CONTEST_EFFECT_AVOID_STARTLE, .contestCategory = CONTEST_CATEGORY_BEAUTY, .contestComboStarterId = 0, .contestComboMoves = {COMBO_STARTER_CALM_MIND}, @@ -3038,7 +3070,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .ignoresProtect = TRUE, .mirrorMoveBanned = TRUE, .snatchAffected = TRUE, - .contestEffect = CONTEST_EFFECT_AVOID_STARTLE, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_AVOID_STARTLE_ONCE : CONTEST_EFFECT_AVOID_STARTLE, .contestCategory = CONTEST_CATEGORY_SMART, .contestComboStarterId = 0, .contestComboMoves = {COMBO_STARTER_CALM_MIND}, @@ -3065,7 +3097,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .ignoresProtect = TRUE, .mirrorMoveBanned = TRUE, .snatchAffected = TRUE, - .contestEffect = CONTEST_EFFECT_BADLY_STARTLE_PREV_MONS, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_IMPROVE_CONDITION_PREVENT_NERVOUSNESS : CONTEST_EFFECT_BADLY_STARTLE_PREV_MONS, .contestCategory = CONTEST_CATEGORY_COOL, .contestComboStarterId = COMBO_STARTER_FOCUS_ENERGY, .contestComboMoves = {0}, @@ -3082,16 +3114,24 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .effect = EFFECT_BIDE, .power = 1, .type = TYPE_NORMAL, - .accuracy = B_UPDATED_MOVE_DATA >= GEN_4 ? 0 : 100, + #if B_UPDATED_MOVE_DATA >= GEN_4 + .accuracy = 0, + .priority = 1, + #elif B_UPDATED_MOVE_DATA >= GEN_2 + .accuracy = 100, + .priority = 0, + #else + .accuracy = 0, + .priority = 0, + #endif .pp = 10, .target = MOVE_TARGET_USER, - .priority = B_UPDATED_MOVE_DATA >= GEN_4 ? 1 : 0, .category = DAMAGE_CATEGORY_PHYSICAL, .makesContact = TRUE, .sleepTalkBanned = TRUE, .instructBanned = TRUE, .mirrorMoveBanned = TRUE, - .contestEffect = CONTEST_EFFECT_AVOID_STARTLE, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_NEXT_APPEAL_LATER : CONTEST_EFFECT_AVOID_STARTLE, .contestCategory = CONTEST_CATEGORY_TOUGH, .contestComboStarterId = 0, .contestComboMoves = {0}, @@ -3121,7 +3161,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .instructBanned = TRUE, .encoreBanned = TRUE, .assistBanned = TRUE, - .contestEffect = CONTEST_EFFECT_REPETITION_NOT_BORING, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_QUALITY_DEPENDS_ON_TIMING : CONTEST_EFFECT_REPETITION_NOT_BORING, .contestCategory = CONTEST_CATEGORY_CUTE, .contestComboStarterId = 0, .contestComboMoves = {0}, @@ -3166,7 +3206,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = "引发爆炸,攻击周围所有的\n" "宝可梦。使用后陷入昏厥。"), .effect = EFFECT_EXPLOSION, - .power = 200, + .power = B_UPDATED_MOVE_DATA >= GEN_2 ? 200 : 130, .type = TYPE_NORMAL, .accuracy = 100, .pp = 5, @@ -3178,7 +3218,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .contestEffect = CONTEST_EFFECT_GREAT_APPEAL_BUT_NO_MORE_MOVES, .contestCategory = CONTEST_CATEGORY_BEAUTY, .contestComboStarterId = 0, - .contestComboMoves = {0}, + .contestComboMoves = {COMBO_STARTER_MEAN_LOOK, COMBO_STARTER_BLOCK}, .battleAnimScript = gBattleAnimMove_SelfDestruct, .validApprenticeMove = TRUE, }, @@ -3199,7 +3239,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .category = DAMAGE_CATEGORY_PHYSICAL, .ballisticMove = TRUE, .contestEffect = CONTEST_EFFECT_HIGHLY_APPEALING, - .contestCategory = CONTEST_CATEGORY_TOUGH, + .contestCategory = C_UPDATED_MOVE_CATEGORIES >= GEN_6 ? CONTEST_CATEGORY_CUTE : CONTEST_CATEGORY_TOUGH, .contestComboStarterId = 0, .contestComboMoves = {COMBO_STARTER_SOFT_BOILED}, .battleAnimScript = gBattleAnimMove_EggBomb, @@ -3225,8 +3265,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .moveEffect = MOVE_EFFECT_PARALYSIS, .chance = 30, }), - .contestEffect = CONTEST_EFFECT_BADLY_STARTLE_FRONT_MON, - .contestCategory = CONTEST_CATEGORY_TOUGH, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_STARTLE_PREV_MON : CONTEST_EFFECT_BADLY_STARTLE_FRONT_MON, + .contestCategory = C_UPDATED_MOVE_CATEGORIES >= GEN_6 ? CONTEST_CATEGORY_CUTE : CONTEST_CATEGORY_TOUGH, .contestComboStarterId = 0, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_Lick, @@ -3251,7 +3291,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .moveEffect = MOVE_EFFECT_POISON, .chance = 40, }), - .contestEffect = CONTEST_EFFECT_BADLY_STARTLE_PREV_MONS, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_HIGHLY_APPEALING : CONTEST_EFFECT_BADLY_STARTLE_PREV_MONS, .contestCategory = CONTEST_CATEGORY_TOUGH, .contestComboStarterId = COMBO_STARTER_SMOG, .contestComboMoves = {0}, @@ -3274,9 +3314,9 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .category = DAMAGE_CATEGORY_SPECIAL, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_POISON, - .chance = 30, + .chance = B_UPDATED_MOVE_DATA >= GEN_2 ? 30 : 40, }), - .contestEffect = CONTEST_EFFECT_BADLY_STARTLE_FRONT_MON, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_STARTLE_PREV_MON : CONTEST_EFFECT_BADLY_STARTLE_FRONT_MON, .contestCategory = CONTEST_CATEGORY_TOUGH, .contestComboStarterId = COMBO_STARTER_SLUDGE, .contestComboMoves = {COMBO_STARTER_SLUDGE_BOMB}, @@ -3301,7 +3341,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .moveEffect = MOVE_EFFECT_FLINCH, .chance = 10, }), - .contestEffect = CONTEST_EFFECT_STARTLE_MON_WITH_JUDGES_ATTENTION, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_REPETITION_NOT_BORING : CONTEST_EFFECT_STARTLE_MON_WITH_JUDGES_ATTENTION, .contestCategory = CONTEST_CATEGORY_TOUGH, .contestComboStarterId = COMBO_STARTER_BONE_CLUB, .contestComboMoves = {COMBO_STARTER_BONEMERANG, COMBO_STARTER_BONE_RUSH, COMBO_STARTER_SHADOW_BONE}, @@ -3324,9 +3364,9 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .category = DAMAGE_CATEGORY_SPECIAL, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_BURN, - .chance = 10, + .chance = B_UPDATED_MOVE_DATA >= GEN_2 ? 10 : 30, }), - .contestEffect = CONTEST_EFFECT_HIGHLY_APPEALING, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_BETTER_WHEN_AUDIENCE_EXCITED : CONTEST_EFFECT_HIGHLY_APPEALING, .contestCategory = CONTEST_CATEGORY_BEAUTY, .contestComboStarterId = 0, .contestComboMoves = {COMBO_STARTER_SUNNY_DAY}, @@ -3355,7 +3395,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .chance = 20, }), #endif - .contestEffect = CONTEST_EFFECT_BETTER_IF_LAST, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_HIGHLY_APPEALING : CONTEST_EFFECT_BETTER_IF_LAST, .contestCategory = CONTEST_CATEGORY_TOUGH, .contestComboStarterId = 0, .contestComboMoves = {COMBO_STARTER_RAIN_DANCE}, @@ -3431,12 +3471,14 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .sleepTalkBanned = TRUE, .instructBanned = TRUE, .argument.twoTurnAttack = { .stringId = STRINGID_PKMNLOWEREDHEAD }, - .additionalEffects = ADDITIONAL_EFFECTS({ - .moveEffect = MOVE_EFFECT_DEF_PLUS_1, - .self = TRUE, - .onChargeTurnOnly = TRUE, - }), - .contestEffect = CONTEST_EFFECT_BADLY_STARTLE_FRONT_MON, + #if B_UPDATED_MOVE_DATA >= GEN_2 + .additionalEffects = ADDITIONAL_EFFECTS({ + .moveEffect = MOVE_EFFECT_DEF_PLUS_1, + .self = TRUE, + .onChargeTurnOnly = TRUE, + }), + #endif + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_AFFECTED_BY_PREV_APPEAL : CONTEST_EFFECT_BADLY_STARTLE_FRONT_MON, .contestCategory = CONTEST_CATEGORY_TOUGH, .contestComboStarterId = 0, .contestComboMoves = {0}, @@ -3458,7 +3500,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .target = MOVE_TARGET_SELECTED, .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, - .contestEffect = CONTEST_EFFECT_STARTLE_MON_WITH_JUDGES_ATTENTION, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_QUALITY_DEPENDS_ON_TIMING : CONTEST_EFFECT_STARTLE_MON_WITH_JUDGES_ATTENTION, .contestCategory = CONTEST_CATEGORY_COOL, .contestComboStarterId = 0, .contestComboMoves = {0}, @@ -3482,9 +3524,9 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .makesContact = TRUE, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_SPD_MINUS_1, - .chance = 10, + .chance = B_UPDATED_MOVE_DATA >= GEN_2 ? 10 : 33, }), - .contestEffect = CONTEST_EFFECT_STARTLE_PREV_MON, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_WORSEN_CONDITION_OF_PREV_MONS : CONTEST_EFFECT_STARTLE_PREV_MON, .contestCategory = CONTEST_CATEGORY_TOUGH, .contestComboStarterId = 0, .contestComboMoves = {0}, @@ -3509,9 +3551,9 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .ignoresProtect = TRUE, .mirrorMoveBanned = TRUE, .snatchAffected = TRUE, - .contestEffect = CONTEST_EFFECT_IMPROVE_CONDITION_PREVENT_NERVOUSNESS, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_AVOID_STARTLE : CONTEST_EFFECT_IMPROVE_CONDITION_PREVENT_NERVOUSNESS, .contestCategory = CONTEST_CATEGORY_CUTE, - .contestComboStarterId = 0, + .contestComboStarterId = COMBO_STARTER_AMNESIA, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_Amnesia, .validApprenticeMove = TRUE, @@ -3532,8 +3574,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .priority = 0, .category = DAMAGE_CATEGORY_STATUS, .zMove = { .effect = Z_EFFECT_EVSN_UP_1 }, - .magicCoatAffected = B_UPDATED_MOVE_FLAGS >= GEN_5, - .contestEffect = CONTEST_EFFECT_DONT_EXCITE_AUDIENCE, + .magicCoatAffected = B_UPDATED_MOVE_FLAGS >= GEN_4, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_REPETITION_NOT_BORING : CONTEST_EFFECT_DONT_EXCITE_AUDIENCE, .contestCategory = CONTEST_CATEGORY_SMART, .contestComboStarterId = COMBO_STARTER_KINESIS, .contestComboMoves = {COMBO_STARTER_CONFUSION, COMBO_STARTER_PSYCHIC}, @@ -3549,7 +3591,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .effect = EFFECT_SOFTBOILED, .power = 0, .type = TYPE_NORMAL, - .accuracy = 100, + .accuracy = 0, .pp = B_UPDATED_MOVE_DATA >= GEN_9 ? 5 : 10, .target = MOVE_TARGET_USER, .priority = 0, @@ -3559,8 +3601,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .ignoresProtect = TRUE, .mirrorMoveBanned = TRUE, .snatchAffected = TRUE, - .contestEffect = CONTEST_EFFECT_HIGHLY_APPEALING, - .contestCategory = CONTEST_CATEGORY_BEAUTY, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_BETTER_IF_FIRST : CONTEST_EFFECT_HIGHLY_APPEALING, + .contestCategory = C_UPDATED_MOVE_CATEGORIES >= GEN_6 ? CONTEST_CATEGORY_CUTE : CONTEST_CATEGORY_BEAUTY, .contestComboStarterId = COMBO_STARTER_SOFT_BOILED, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_SoftBoiled, @@ -3620,9 +3662,9 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .argument = { .nonVolatileStatus = MOVE_EFFECT_PARALYSIS }, .zMove = { .effect = Z_EFFECT_SPDEF_UP_1 }, .magicCoatAffected = TRUE, - .contestEffect = CONTEST_EFFECT_BADLY_STARTLE_PREV_MONS, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_BETTER_IF_SAME_TYPE : CONTEST_EFFECT_BADLY_STARTLE_PREV_MONS, .contestCategory = CONTEST_CATEGORY_TOUGH, - .contestComboStarterId = 0, + .contestComboStarterId = COMBO_STARTER_GLARE, .contestComboMoves = {COMBO_STARTER_LEER}, .battleAnimScript = gBattleAnimMove_Glare, .validApprenticeMove = TRUE, @@ -3643,11 +3685,10 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .priority = 0, .category = DAMAGE_CATEGORY_SPECIAL, .healingMove = B_HEAL_BLOCKING >= GEN_6, - .ignoresSubstitute = B_UPDATED_MOVE_FLAGS >= GEN_5, .contestEffect = CONTEST_EFFECT_STARTLE_PREV_MONS, .contestCategory = CONTEST_CATEGORY_SMART, .contestComboStarterId = 0, - .contestComboMoves = {COMBO_STARTER_CALM_MIND, COMBO_STARTER_HYPNOSIS}, + .contestComboMoves = {COMBO_STARTER_CALM_MIND, COMBO_STARTER_HYPNOSIS, COMBO_STARTER_LOVELY_KISS, COMBO_STARTER_SPORE, COMBO_STARTER_SING, COMBO_STARTER_YAWN, COMBO_STARTER_DARK_VOID, COMBO_STARTER_GRASS_WHISTLE, COMBO_STARTER_SLEEP_POWDER}, .battleAnimScript = gBattleAnimMove_DreamEater, .validApprenticeMove = TRUE, }, @@ -3660,7 +3701,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = "从而让对手陷入中毒状态。"), #if B_UPDATED_MOVE_DATA >= GEN_6 .accuracy = 90, - #elif B_UPDATED_MOVE_DATA >= GEN_5 + #elif B_UPDATED_MOVE_DATA == GEN_5 .accuracy = 80, #else .accuracy = 55, @@ -3675,9 +3716,9 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .argument = { .nonVolatileStatus = MOVE_EFFECT_POISON }, .zMove = { .effect = Z_EFFECT_DEF_UP_1 }, .magicCoatAffected = TRUE, - .contestEffect = CONTEST_EFFECT_WORSEN_CONDITION_OF_PREV_MONS, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_SHIFT_JUDGE_ATTENTION : CONTEST_EFFECT_WORSEN_CONDITION_OF_PREV_MONS, .contestCategory = CONTEST_CATEGORY_SMART, - .contestComboStarterId = 0, + .contestComboStarterId = COMBO_STARTER_POISON_GAS, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_PoisonGas, }, @@ -3697,8 +3738,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, .ballisticMove = TRUE, - .contestEffect = CONTEST_EFFECT_BETTER_IF_SAME_TYPE, - .contestCategory = CONTEST_CATEGORY_TOUGH, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_QUALITY_DEPENDS_ON_TIMING : CONTEST_EFFECT_BETTER_IF_SAME_TYPE, + .contestCategory = C_UPDATED_MOVE_CATEGORIES >= GEN_6 ? CONTEST_CATEGORY_CUTE : CONTEST_CATEGORY_TOUGH, .contestComboStarterId = 0, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_Barrage, @@ -3722,7 +3763,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .makesContact = TRUE, .ignoresKingsRock = (B_UPDATED_MOVE_FLAGS == GEN_3 || B_UPDATED_MOVE_FLAGS == GEN_4), .healingMove = B_HEAL_BLOCKING >= GEN_6, - .contestEffect = CONTEST_EFFECT_STARTLE_PREV_MON, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_APPEAL_AS_GOOD_AS_PREV_ONE : CONTEST_EFFECT_STARTLE_PREV_MON, .contestCategory = CONTEST_CATEGORY_SMART, .contestComboStarterId = 0, .contestComboMoves = {0}, @@ -3746,9 +3787,9 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .argument = { .nonVolatileStatus = MOVE_EFFECT_SLEEP }, .zMove = { .effect = Z_EFFECT_SPD_UP_1 }, .magicCoatAffected = TRUE, - .contestEffect = CONTEST_EFFECT_BADLY_STARTLE_PREV_MONS, + .contestEffect = CONTEST_EFFECT_BADLY_STARTLE_PREV_MONS, //C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_QUICKLY_GROW_BORED : .contestCategory = CONTEST_CATEGORY_BEAUTY, - .contestComboStarterId = 0, + .contestComboStarterId = COMBO_STARTER_LOVELY_KISS, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_LovelyKiss, .validApprenticeMove = TRUE, @@ -3802,13 +3843,14 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .category = DAMAGE_CATEGORY_STATUS, .zMove = { .effect = Z_EFFECT_RECOVER_HP }, .ignoresProtect = TRUE, + .ignoresSubstitute = B_UPDATED_MOVE_FLAGS < GEN_5, .mirrorMoveBanned = TRUE, .mimicBanned = TRUE, .metronomeBanned = B_UPDATED_MOVE_FLAGS >= GEN_5, - .copycatBanned = TRUE, + .copycatBanned = B_UPDATED_MOVE_FLAGS >= GEN_5, .instructBanned = TRUE, .encoreBanned = TRUE, - .assistBanned = TRUE, + .assistBanned = B_UPDATED_MOVE_FLAGS >= GEN_5, .contestEffect = CONTEST_EFFECT_REPETITION_NOT_BORING, .contestCategory = CONTEST_CATEGORY_SMART, .contestComboStarterId = 0, @@ -3833,9 +3875,9 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .category = DAMAGE_CATEGORY_SPECIAL, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_SPD_MINUS_1, - .chance = 10, + .chance = B_UPDATED_MOVE_DATA >= GEN_2 ? 10 : 33, }), - .contestEffect = CONTEST_EFFECT_STARTLE_PREV_MONS, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_HIGHLY_APPEALING : CONTEST_EFFECT_STARTLE_PREV_MONS, .contestCategory = CONTEST_CATEGORY_CUTE, .contestComboStarterId = 0, .contestComboMoves = {COMBO_STARTER_RAIN_DANCE}, @@ -3858,12 +3900,14 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .category = DAMAGE_CATEGORY_PHYSICAL, .makesContact = TRUE, .punchingMove = TRUE, - .additionalEffects = ADDITIONAL_EFFECTS({ - .moveEffect = MOVE_EFFECT_CONFUSION, - .chance = 20, - }), - .contestEffect = CONTEST_EFFECT_BADLY_STARTLE_FRONT_MON, - .contestCategory = CONTEST_CATEGORY_COOL, + #if B_UPDATED_MOVE_DATA >= GEN_2 + .additionalEffects = ADDITIONAL_EFFECTS({ + .moveEffect = MOVE_EFFECT_CONFUSION, + .chance = 20, + }), + #endif + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_SHIFT_JUDGE_ATTENTION : CONTEST_EFFECT_BADLY_STARTLE_FRONT_MON, + .contestCategory = C_UPDATED_MOVE_CATEGORIES >= GEN_6 ? CONTEST_CATEGORY_CUTE : CONTEST_CATEGORY_COOL, .contestComboStarterId = 0, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_DizzyPunch, @@ -3890,7 +3934,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .powderMove = TRUE, .contestEffect = CONTEST_EFFECT_BADLY_STARTLE_PREV_MONS, .contestCategory = CONTEST_CATEGORY_BEAUTY, - .contestComboStarterId = 0, + .contestComboStarterId = COMBO_STARTER_SPORE, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_Spore, .validApprenticeMove = TRUE, @@ -3934,7 +3978,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .target = MOVE_TARGET_SELECTED, .priority = 0, .category = DAMAGE_CATEGORY_SPECIAL, - .contestEffect = CONTEST_EFFECT_BADLY_STARTLE_MONS_WITH_GOOD_APPEALS, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_QUALITY_DEPENDS_ON_TIMING : CONTEST_EFFECT_BADLY_STARTLE_MONS_WITH_GOOD_APPEALS, .contestCategory = CONTEST_CATEGORY_SMART, .contestComboStarterId = 0, .contestComboMoves = {COMBO_STARTER_CALM_MIND}, @@ -3961,7 +4005,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .ignoresProtect = TRUE, .mirrorMoveBanned = TRUE, .gravityBanned = TRUE, - .contestEffect = CONTEST_EFFECT_BETTER_IF_LAST, + .contestEffect = CONTEST_EFFECT_BETTER_IF_LAST, //C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_QUICKLY_GROW_BORED : .contestCategory = CONTEST_CATEGORY_CUTE, .contestComboStarterId = 0, .contestComboMoves = {0}, @@ -3986,7 +4030,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .snatchAffected = TRUE, .ignoresProtect = TRUE, .mirrorMoveBanned = TRUE, - .contestEffect = CONTEST_EFFECT_IMPROVE_CONDITION_PREVENT_NERVOUSNESS, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_AVOID_STARTLE : CONTEST_EFFECT_IMPROVE_CONDITION_PREVENT_NERVOUSNESS, .contestCategory = CONTEST_CATEGORY_TOUGH, .contestComboStarterId = 0, .contestComboMoves = {0}, @@ -4004,13 +4048,13 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .power = B_UPDATED_MOVE_DATA >= GEN_6 ? 100 : 90, .type = TYPE_WATER, .accuracy = B_UPDATED_MOVE_DATA >= GEN_5 ? 90 : 85, - .criticalHitStage = 1, + .criticalHitStage = B_UPDATED_MOVE_DATA >= GEN_3 ? 1 : 2, .pp = 10, .target = MOVE_TARGET_SELECTED, .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, .makesContact = TRUE, - .contestEffect = CONTEST_EFFECT_AFFECTED_BY_PREV_APPEAL, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_REPETITION_NOT_BORING : CONTEST_EFFECT_AFFECTED_BY_PREV_APPEAL, .contestCategory = CONTEST_CATEGORY_TOUGH, .contestComboStarterId = 0, .contestComboMoves = {COMBO_STARTER_RAIN_DANCE, COMBO_STARTER_SWORDS_DANCE}, @@ -4025,7 +4069,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = "引发大爆炸攻击周围所有的\n" "宝可梦。使用后会陷入昏厥。"), .effect = EFFECT_EXPLOSION, - .power = 250, + .power = B_UPDATED_MOVE_DATA >= GEN_2 ? 250 : 170, .type = TYPE_NORMAL, .accuracy = 100, .pp = 5, @@ -4037,7 +4081,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .contestEffect = CONTEST_EFFECT_GREAT_APPEAL_BUT_NO_MORE_MOVES, .contestCategory = CONTEST_CATEGORY_BEAUTY, .contestComboStarterId = 0, - .contestComboMoves = {0}, + .contestComboMoves = {COMBO_STARTER_MEAN_LOOK, COMBO_STARTER_BLOCK}, .battleAnimScript = gBattleAnimMove_Explosion, .validApprenticeMove = TRUE, }, @@ -4057,7 +4101,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, .makesContact = TRUE, - .contestEffect = CONTEST_EFFECT_STARTLE_MON_WITH_JUDGES_ATTENTION, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_QUALITY_DEPENDS_ON_TIMING : CONTEST_EFFECT_STARTLE_MON_WITH_JUDGES_ATTENTION, .contestCategory = CONTEST_CATEGORY_TOUGH, .contestComboStarterId = 0, .contestComboMoves = {COMBO_STARTER_SCRATCH}, @@ -4079,7 +4123,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, .strikeCount = 2, - .contestEffect = CONTEST_EFFECT_HIGHLY_APPEALING, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_STARTLE_MONS_SAME_TYPE_APPEAL : CONTEST_EFFECT_HIGHLY_APPEALING, .contestCategory = CONTEST_CATEGORY_TOUGH, .contestComboStarterId = COMBO_STARTER_BONEMERANG, .contestComboMoves = {COMBO_STARTER_BONE_CLUB, COMBO_STARTER_BONE_RUSH, COMBO_STARTER_SHADOW_BONE}, @@ -4106,7 +4150,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .ignoresProtect = TRUE, .mirrorMoveBanned = TRUE, .healingMove = TRUE, - .contestEffect = CONTEST_EFFECT_AVOID_STARTLE_ONCE, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_AVOID_STARTLE : CONTEST_EFFECT_AVOID_STARTLE_ONCE, .contestCategory = CONTEST_CATEGORY_CUTE, .contestComboStarterId = COMBO_STARTER_REST, .contestComboMoves = {COMBO_STARTER_BELLY_DRUM, COMBO_STARTER_CHARM, COMBO_STARTER_YAWN}, @@ -4128,11 +4172,13 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .target = MOVE_TARGET_BOTH, .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, - .additionalEffects = ADDITIONAL_EFFECTS({ - .moveEffect = MOVE_EFFECT_FLINCH, - .chance = 30, - }), - .contestEffect = CONTEST_EFFECT_BADLY_STARTLE_PREV_MONS, + #if B_UPDATED_MOVE_DATA >= GEN_2 + .additionalEffects = ADDITIONAL_EFFECTS({ + .moveEffect = MOVE_EFFECT_FLINCH, + .chance = 30, + }), + #endif + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_STARTLE_PREV_MONS : CONTEST_EFFECT_BADLY_STARTLE_PREV_MONS, .contestCategory = CONTEST_CATEGORY_TOUGH, .contestComboStarterId = 0, .contestComboMoves = {COMBO_STARTER_ROCK_THROW}, @@ -4160,7 +4206,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .moveEffect = MOVE_EFFECT_FLINCH, .chance = 10, }), - .contestEffect = CONTEST_EFFECT_BADLY_STARTLE_FRONT_MON, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_REPETITION_NOT_BORING : CONTEST_EFFECT_BADLY_STARTLE_FRONT_MON, .contestCategory = CONTEST_CATEGORY_COOL, .contestComboStarterId = 0, .contestComboMoves = {0}, @@ -4234,11 +4280,13 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .target = MOVE_TARGET_SELECTED, .priority = 0, .category = DAMAGE_CATEGORY_SPECIAL, - .additionalEffects = ADDITIONAL_EFFECTS({ - .moveEffect = MOVE_EFFECT_TRI_ATTACK, - .chance = 20, - }), - .contestEffect = CONTEST_EFFECT_STARTLE_PREV_MONS, + #if B_UPDATED_MOVE_DATA >= GEN_2 + .additionalEffects = ADDITIONAL_EFFECTS({ + .moveEffect = MOVE_EFFECT_TRI_ATTACK, + .chance = 20, + }), + #endif + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_QUALITY_DEPENDS_ON_TIMING : CONTEST_EFFECT_STARTLE_PREV_MONS, .contestCategory = CONTEST_CATEGORY_BEAUTY, .contestComboStarterId = 0, .contestComboMoves = {COMBO_STARTER_LOCK_ON}, @@ -4281,14 +4329,14 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .power = 70, .type = TYPE_NORMAL, .accuracy = 100, - .criticalHitStage = 1, + .criticalHitStage = B_UPDATED_MOVE_DATA >= GEN_3 ? 1 : 2, .pp = 20, .target = MOVE_TARGET_SELECTED, .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, .makesContact = TRUE, .slicingMove = TRUE, - .contestEffect = CONTEST_EFFECT_AFFECTED_BY_PREV_APPEAL, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_HIGHLY_APPEALING : CONTEST_EFFECT_AFFECTED_BY_PREV_APPEAL, .contestCategory = CONTEST_CATEGORY_COOL, .contestComboStarterId = 0, .contestComboMoves = {COMBO_STARTER_SCRATCH, COMBO_STARTER_SWORDS_DANCE}, @@ -4316,7 +4364,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .mirrorMoveBanned = TRUE, .skyBattleBanned = TRUE, .contestEffect = CONTEST_EFFECT_AVOID_STARTLE_ONCE, - .contestCategory = CONTEST_CATEGORY_SMART, + .contestCategory = C_UPDATED_MOVE_CATEGORIES >= GEN_6 ? CONTEST_CATEGORY_CUTE : CONTEST_CATEGORY_SMART, .contestComboStarterId = 0, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_Substitute, @@ -4332,19 +4380,24 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = #if B_UPDATED_MOVE_DATA >= GEN_4 .effect = EFFECT_STRUGGLE, .accuracy = 0, - .mirrorMoveBanned = TRUE, + .pp = 1, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_RECOIL_HP_25, .self = TRUE, }), + #elif B_UPDATED_MOVE_DATA >= GEN_2 + .effect = EFFECT_RECOIL, + .accuracy = 100, + .pp = 1, + .argument = { .recoilPercentage = 25 }, #else .effect = EFFECT_RECOIL, .accuracy = 100, - .argument = { .recoilPercentage = 25 }, + .pp = 10, + .argument = { .recoilPercentage = 50 }, #endif .power = 50, .type = TYPE_NORMAL, - .pp = 1, .target = MOVE_TARGET_SELECTED, .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, @@ -4358,8 +4411,11 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .encoreBanned = TRUE, .assistBanned = TRUE, .sketchBanned = TRUE, + .mirrorMoveBanned = B_UPDATED_MOVE_FLAGS >= GEN_4, .battleAnimScript = gBattleAnimMove_Struggle, .validApprenticeMove = TRUE, + .contestEffect = CONTEST_EFFECT_HIGHLY_APPEALING, + .contestCategory = C_UPDATED_MOVE_CATEGORIES >= GEN_6 ? CONTEST_CATEGORY_COOL : CONTEST_CATEGORY_TOUGH, }, [MOVE_SKETCH] = @@ -4378,7 +4434,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .category = DAMAGE_CATEGORY_STATUS, .zMove = { .effect = Z_EFFECT_ALL_STATS_UP_1 }, .ignoresProtect = TRUE, - .ignoresSubstitute = TRUE, + .ignoresSubstitute = B_UPDATED_MOVE_FLAGS >= GEN_5, .mirrorMoveBanned = TRUE, .mimicBanned = TRUE, .metronomeBanned = TRUE, @@ -4412,7 +4468,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .category = DAMAGE_CATEGORY_PHYSICAL, .makesContact = TRUE, .strikeCount = 3, - .contestEffect = CONTEST_EFFECT_HIGHLY_APPEALING, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_REPETITION_NOT_BORING : CONTEST_EFFECT_HIGHLY_APPEALING, .contestCategory = CONTEST_CATEGORY_COOL, .contestComboStarterId = 0, .contestComboMoves = {COMBO_STARTER_FOCUS_ENERGY}, @@ -4440,7 +4496,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .metronomeBanned = TRUE, .copycatBanned = TRUE, .assistBanned = TRUE, - .contestEffect = CONTEST_EFFECT_APPEAL_AS_GOOD_AS_PREV_ONES, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_APPEAL_AS_GOOD_AS_PREV_ONE : CONTEST_EFFECT_APPEAL_AS_GOOD_AS_PREV_ONES, .contestCategory = CONTEST_CATEGORY_TOUGH, .contestComboStarterId = 0, .contestComboMoves = {0}, @@ -4463,7 +4519,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .priority = 0, .category = DAMAGE_CATEGORY_STATUS, .zMove = { .effect = Z_EFFECT_DEF_UP_1 }, - .ignoresProtect = (B_UPDATED_MOVE_FLAGS >= GEN_6) || (B_UPDATED_MOVE_FLAGS <= GEN_3), + .ignoresProtect = (B_UPDATED_MOVE_FLAGS >= GEN_6) || (B_UPDATED_MOVE_FLAGS < GEN_3), .magicCoatAffected = TRUE, .contestEffect = CONTEST_EFFECT_MAKE_FOLLOWING_MONS_NERVOUS, .contestCategory = CONTEST_CATEGORY_SMART, @@ -4488,7 +4544,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .priority = 0, .category = DAMAGE_CATEGORY_STATUS, .zMove = { .effect = Z_EFFECT_SPATK_UP_1 }, - .contestEffect = CONTEST_EFFECT_DONT_EXCITE_AUDIENCE, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_NEXT_APPEAL_EARLIER : CONTEST_EFFECT_DONT_EXCITE_AUDIENCE, .contestCategory = CONTEST_CATEGORY_SMART, .contestComboStarterId = COMBO_STARTER_MIND_READER, .contestComboMoves = {0}, @@ -4511,11 +4567,11 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .priority = 0, .category = DAMAGE_CATEGORY_STATUS, .zMove = { .effect = Z_EFFECT_SPATK_UP_1 }, - .ignoresProtect = B_UPDATED_MOVE_FLAGS <= GEN_3, + .ignoresProtect = B_UPDATED_MOVE_FLAGS < GEN_3, .contestEffect = CONTEST_EFFECT_BADLY_STARTLE_PREV_MONS, .contestCategory = CONTEST_CATEGORY_SMART, .contestComboStarterId = 0, - .contestComboMoves = {0}, + .contestComboMoves = {COMBO_STARTER_LOVELY_KISS, COMBO_STARTER_SPORE, COMBO_STARTER_SING, COMBO_STARTER_YAWN, COMBO_STARTER_HYPNOSIS, COMBO_STARTER_DARK_VOID, COMBO_STARTER_GRASS_WHISTLE, COMBO_STARTER_SLEEP_POWDER}, .battleAnimScript = gBattleAnimMove_Nightmare, .validApprenticeMove = TRUE, }, @@ -4540,7 +4596,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .moveEffect = MOVE_EFFECT_BURN, .chance = 10, }), - .contestEffect = CONTEST_EFFECT_HIGHLY_APPEALING, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_AFFECTED_BY_PREV_APPEAL : CONTEST_EFFECT_HIGHLY_APPEALING, .contestCategory = CONTEST_CATEGORY_BEAUTY, .contestComboStarterId = 0, .contestComboMoves = {COMBO_STARTER_SUNNY_DAY}, @@ -4568,7 +4624,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .moveEffect = MOVE_EFFECT_FLINCH, .chance = 30, }), - .contestEffect = CONTEST_EFFECT_HIGHLY_APPEALING, + .contestEffect = CONTEST_EFFECT_HIGHLY_APPEALING, //C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_QUICKLY_GROW_BORED : .contestCategory = CONTEST_CATEGORY_CUTE, .contestComboStarterId = 0, .contestComboMoves = {COMBO_STARTER_REST}, @@ -4592,7 +4648,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .category = DAMAGE_CATEGORY_STATUS, .zMove = { .effect = Z_EFFECT_CURSE }, .ignoresProtect = TRUE, - .ignoresSubstitute = TRUE, + .ignoresSubstitute = B_UPDATED_MOVE_FLAGS >= GEN_5, .mirrorMoveBanned = TRUE, .contestEffect = CONTEST_EFFECT_NEXT_APPEAL_LATER, .contestCategory = CONTEST_CATEGORY_TOUGH, @@ -4640,8 +4696,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .priority = 0, .category = DAMAGE_CATEGORY_STATUS, .zMove = { .effect = Z_EFFECT_RECOVER_HP }, - .ignoresProtect = B_UPDATED_MOVE_FLAGS >= GEN_5, - .ignoresSubstitute = TRUE, + .ignoresProtect = B_UPDATED_MOVE_FLAGS >= GEN_3, + .ignoresSubstitute = B_UPDATED_MOVE_FLAGS >= GEN_5, .mirrorMoveBanned = TRUE, .contestEffect = CONTEST_EFFECT_BETTER_IF_SAME_TYPE, .contestCategory = CONTEST_CATEGORY_BEAUTY, @@ -4661,13 +4717,13 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .power = 100, .type = TYPE_FLYING, .accuracy = 95, - .criticalHitStage = 1, + .criticalHitStage = B_UPDATED_MOVE_DATA >= GEN_3 ? 1 : 2, .pp = 5, .target = MOVE_TARGET_SELECTED, .priority = 0, .category = DAMAGE_CATEGORY_SPECIAL, .windMove = TRUE, - .contestEffect = CONTEST_EFFECT_AFFECTED_BY_PREV_APPEAL, + .contestEffect = CONTEST_EFFECT_AFFECTED_BY_PREV_APPEAL, //C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_EXCITES_AUDIENCE_MORE_IF_LAST : .contestCategory = CONTEST_CATEGORY_COOL, .contestComboStarterId = 0, .contestComboMoves = {0}, @@ -4715,7 +4771,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, .makesContact = TRUE, - .contestEffect = CONTEST_EFFECT_BETTER_IF_LAST, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_BETTER_WHEN_LATER : CONTEST_EFFECT_BETTER_IF_LAST, .contestCategory = CONTEST_CATEGORY_COOL, .contestComboStarterId = 0, .contestComboMoves = {COMBO_STARTER_ENDURE}, @@ -4740,10 +4796,10 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .zMove = { .effect = Z_EFFECT_RECOVER_HP }, .magicCoatAffected = B_UPDATED_MOVE_FLAGS >= GEN_5, .ignoresSubstitute = TRUE, - .contestEffect = CONTEST_EFFECT_BETTER_WHEN_LATER, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_BADLY_STARTLE_MONS_WITH_GOOD_APPEALS : CONTEST_EFFECT_BETTER_WHEN_LATER, .contestCategory = CONTEST_CATEGORY_TOUGH, .contestComboStarterId = 0, - .contestComboMoves = {COMBO_STARTER_CURSE}, + .contestComboMoves = {COMBO_STARTER_CURSE, COMBO_STARTER_ENCORE, COMBO_STARTER_TAUNT, COMBO_STARTER_TORMENT}, .battleAnimScript = gBattleAnimMove_Spite, .validApprenticeMove = TRUE, }, @@ -4783,14 +4839,20 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .accuracy = 0, .pp = 10, .target = MOVE_TARGET_USER, - .priority = B_UPDATED_MOVE_DATA >= GEN_5 ? 4 : 3, + #if B_UPDATED_MOVE_DATA >= GEN_5 + .priority = 4, + #elif B_UPDATED_MOVE_DATA >= GEN_3 + .priority = 3, + #else + .priority = 2, + #endif .category = DAMAGE_CATEGORY_STATUS, .argument = { .protectMethod = PROTECT_NORMAL }, .zMove = { .effect = Z_EFFECT_RESET_STATS }, .metronomeBanned = TRUE, .copycatBanned = TRUE, .assistBanned = TRUE, - .contestEffect = CONTEST_EFFECT_AVOID_STARTLE, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_AVOID_STARTLE_ONCE : CONTEST_EFFECT_AVOID_STARTLE, .contestCategory = CONTEST_CATEGORY_CUTE, .contestComboStarterId = 0, .contestComboMoves = {COMBO_STARTER_HARDEN}, @@ -4838,7 +4900,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .category = DAMAGE_CATEGORY_STATUS, .zMove = { .effect = Z_EFFECT_SPD_UP_1 }, .magicCoatAffected = TRUE, - .contestEffect = CONTEST_EFFECT_STARTLE_MON_WITH_JUDGES_ATTENTION, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_WORSEN_CONDITION_OF_PREV_MONS : CONTEST_EFFECT_STARTLE_MON_WITH_JUDGES_ATTENTION, .contestCategory = CONTEST_CATEGORY_TOUGH, .contestComboStarterId = COMBO_STARTER_SCARY_FACE, .contestComboMoves = {COMBO_STARTER_LEER, COMBO_STARTER_RAGE}, @@ -4911,7 +4973,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .snatchAffected = TRUE, .ignoresProtect = TRUE, .mirrorMoveBanned = TRUE, - .contestEffect = CONTEST_EFFECT_IMPROVE_CONDITION_PREVENT_NERVOUSNESS, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_USER_MORE_EASILY_STARTLED : CONTEST_EFFECT_IMPROVE_CONDITION_PREVENT_NERVOUSNESS, .contestCategory = CONTEST_CATEGORY_CUTE, .contestComboStarterId = COMBO_STARTER_BELLY_DRUM, .contestComboMoves = {0}, @@ -4964,7 +5026,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .moveEffect = MOVE_EFFECT_ACC_MINUS_1, .chance = 100, }), - .contestEffect = CONTEST_EFFECT_STARTLE_MON_WITH_JUDGES_ATTENTION, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_WORSEN_CONDITION_OF_PREV_MONS : CONTEST_EFFECT_STARTLE_MON_WITH_JUDGES_ATTENTION, .contestCategory = CONTEST_CATEGORY_CUTE, .contestComboStarterId = COMBO_STARTER_MUD_SLAP, .contestComboMoves = {COMBO_STARTER_MUD_SPORT, COMBO_STARTER_SAND_ATTACK, COMBO_STARTER_SANDSTORM}, @@ -4991,7 +5053,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .moveEffect = MOVE_EFFECT_ACC_MINUS_1, .chance = 50, }), - .contestEffect = CONTEST_EFFECT_STARTLE_MON_WITH_JUDGES_ATTENTION, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_REPETITION_NOT_BORING : CONTEST_EFFECT_STARTLE_MON_WITH_JUDGES_ATTENTION, .contestCategory = CONTEST_CATEGORY_TOUGH, .contestComboStarterId = 0, .contestComboMoves = {COMBO_STARTER_LOCK_ON, COMBO_STARTER_RAIN_DANCE}, @@ -5021,7 +5083,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .skyBattleBanned = TRUE, .contestEffect = CONTEST_EFFECT_MAKE_FOLLOWING_MONS_NERVOUS, .contestCategory = CONTEST_CATEGORY_SMART, - .contestComboStarterId = 0, + .contestComboStarterId = COMBO_STARTER_SPIKES, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_Spikes, .validApprenticeMove = TRUE, @@ -5046,7 +5108,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .moveEffect = MOVE_EFFECT_PARALYSIS, .chance = 100, }), - .contestEffect = CONTEST_EFFECT_HIGHLY_APPEALING, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_BADLY_STARTLE_MONS_WITH_GOOD_APPEALS : CONTEST_EFFECT_HIGHLY_APPEALING, .contestCategory = CONTEST_CATEGORY_COOL, .contestComboStarterId = 0, .contestComboMoves = {COMBO_STARTER_CHARGE, COMBO_STARTER_LOCK_ON}, @@ -5071,7 +5133,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .zMove = { .effect = Z_EFFECT_BOOST_CRITS }, .magicCoatAffected = B_UPDATED_MOVE_FLAGS >= GEN_5, .ignoresSubstitute = TRUE, - .contestEffect = CONTEST_EFFECT_WORSEN_CONDITION_OF_PREV_MONS, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_STARTLE_MONS_SAME_TYPE_APPEAL : CONTEST_EFFECT_WORSEN_CONDITION_OF_PREV_MONS, .contestCategory = CONTEST_CATEGORY_SMART, .contestComboStarterId = 0, .contestComboMoves = {0}, @@ -5100,10 +5162,10 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .metronomeBanned = TRUE, .copycatBanned = TRUE, .assistBanned = TRUE, - .contestEffect = CONTEST_EFFECT_GREAT_APPEAL_BUT_NO_MORE_MOVES, + .contestEffect = CONTEST_EFFECT_GREAT_APPEAL_BUT_NO_MORE_MOVES, //C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_QUICKLY_GROW_BORED : .contestCategory = CONTEST_CATEGORY_SMART, .contestComboStarterId = 0, - .contestComboMoves = {COMBO_STARTER_CURSE, COMBO_STARTER_ENDURE, COMBO_STARTER_MEAN_LOOK}, + .contestComboMoves = {COMBO_STARTER_CURSE, COMBO_STARTER_ENDURE, COMBO_STARTER_MEAN_LOOK, COMBO_STARTER_ENCORE, COMBO_STARTER_TAUNT, COMBO_STARTER_TORMENT}, .battleAnimScript = gBattleAnimMove_DestinyBond, .validApprenticeMove = TRUE, }, @@ -5124,13 +5186,13 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .category = DAMAGE_CATEGORY_STATUS, .zMove = { .effect = Z_EFFECT_RESET_STATS }, .ignoresProtect = TRUE, - .ignoresSubstitute = B_UPDATED_MOVE_FLAGS >= GEN_6, + .ignoresSubstitute = TRUE, .mirrorMoveBanned = TRUE, .soundMove = TRUE, - .contestEffect = CONTEST_EFFECT_BADLY_STARTLE_MONS_WITH_GOOD_APPEALS, + .contestEffect = CONTEST_EFFECT_BADLY_STARTLE_MONS_WITH_GOOD_APPEALS, //C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_QUICKLY_GROW_BORED : .contestCategory = CONTEST_CATEGORY_BEAUTY, .contestComboStarterId = 0, - .contestComboMoves = {COMBO_STARTER_MEAN_LOOK, COMBO_STARTER_SING}, + .contestComboMoves = {COMBO_STARTER_MEAN_LOOK, COMBO_STARTER_SING, COMBO_STARTER_BLOCK}, .battleAnimScript = gBattleAnimMove_PerishSong, .validApprenticeMove = TRUE, }, @@ -5172,7 +5234,13 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .accuracy = 0, .pp = 5, .target = MOVE_TARGET_USER, - .priority = B_UPDATED_MOVE_DATA >= GEN_5 ? 4 : 3, + #if B_UPDATED_MOVE_DATA >= GEN_5 + .priority = 4, + #elif B_UPDATED_MOVE_DATA >= GEN_3 + .priority = 3, + #else + .priority = 2, + #endif .category = DAMAGE_CATEGORY_STATUS, .argument = { .protectMethod = PROTECT_NORMAL }, .zMove = { .effect = Z_EFFECT_EVSN_UP_1 }, @@ -5181,7 +5249,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .metronomeBanned = TRUE, .copycatBanned = TRUE, .assistBanned = TRUE, - .contestEffect = CONTEST_EFFECT_AVOID_STARTLE_ONCE, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_AVOID_STARTLE : CONTEST_EFFECT_AVOID_STARTLE_ONCE, .contestCategory = CONTEST_CATEGORY_COOL, .contestComboStarterId = 0, .contestComboMoves = {COMBO_STARTER_TAUNT}, @@ -5203,7 +5271,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .target = MOVE_TARGET_SELECTED, .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, - .contestEffect = CONTEST_EFFECT_HIGHLY_APPEALING, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_QUALITY_DEPENDS_ON_TIMING : CONTEST_EFFECT_HIGHLY_APPEALING, .contestCategory = CONTEST_CATEGORY_TOUGH, .contestComboStarterId = COMBO_STARTER_BONE_RUSH, .contestComboMoves = {COMBO_STARTER_BONE_CLUB, COMBO_STARTER_BONEMERANG, COMBO_STARTER_FOCUS_ENERGY, COMBO_STARTER_SHADOW_BONE}, @@ -5225,7 +5293,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .priority = 0, .category = DAMAGE_CATEGORY_STATUS, .zMove = { .effect = Z_EFFECT_SPD_UP_1 }, - .contestEffect = CONTEST_EFFECT_DONT_EXCITE_AUDIENCE, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_NEXT_APPEAL_EARLIER : CONTEST_EFFECT_DONT_EXCITE_AUDIENCE, .contestCategory = CONTEST_CATEGORY_SMART, .contestComboStarterId = COMBO_STARTER_LOCK_ON, .contestComboMoves = {0}, @@ -5253,7 +5321,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .moveEffect = MOVE_EFFECT_THRASH, .self = TRUE, }), - .contestEffect = CONTEST_EFFECT_JAMS_OTHERS_BUT_MISS_ONE_TURN, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_USER_MORE_EASILY_STARTLED : CONTEST_EFFECT_JAMS_OTHERS_BUT_MISS_ONE_TURN, .contestCategory = CONTEST_CATEGORY_COOL, .contestComboStarterId = 0, .contestComboMoves = {0}, @@ -5279,7 +5347,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .ignoresProtect = TRUE, .mirrorMoveBanned = TRUE, .windMove = TRUE, - .contestEffect = CONTEST_EFFECT_SCRAMBLE_NEXT_TURN_ORDER, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_BADLY_STARTLE_MONS_WITH_GOOD_APPEALS : CONTEST_EFFECT_SCRAMBLE_NEXT_TURN_ORDER, .contestCategory = CONTEST_CATEGORY_TOUGH, .contestComboStarterId = COMBO_STARTER_SANDSTORM, .contestComboMoves = {0}, @@ -5304,7 +5372,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .argument = { .absorbPercentage = 50 }, .ignoresKingsRock = (B_UPDATED_MOVE_FLAGS == GEN_3 || B_UPDATED_MOVE_FLAGS == GEN_4), .healingMove = B_HEAL_BLOCKING >= GEN_6, - .contestEffect = CONTEST_EFFECT_STARTLE_MON_WITH_JUDGES_ATTENTION, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_BADLY_STARTLE_FRONT_MON : CONTEST_EFFECT_STARTLE_MON_WITH_JUDGES_ATTENTION, .contestCategory = CONTEST_CATEGORY_SMART, .contestComboStarterId = 0, .contestComboMoves = {COMBO_STARTER_GROWTH}, @@ -5324,7 +5392,13 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .accuracy = 0, .pp = 10, .target = MOVE_TARGET_USER, - .priority = B_UPDATED_MOVE_DATA >= GEN_5 ? 4 : 3, + #if B_UPDATED_MOVE_DATA >= GEN_5 + .priority = 4, + #elif B_UPDATED_MOVE_DATA >= GEN_3 + .priority = 3, + #else + .priority = 2, + #endif .category = DAMAGE_CATEGORY_STATUS, .zMove = { .effect = Z_EFFECT_RESET_STATS }, .ignoresProtect = TRUE, @@ -5332,7 +5406,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .metronomeBanned = TRUE, .copycatBanned = TRUE, .assistBanned = TRUE, - .contestEffect = CONTEST_EFFECT_AVOID_STARTLE_ONCE, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_NEXT_APPEAL_LATER : CONTEST_EFFECT_AVOID_STARTLE_ONCE, .contestCategory = CONTEST_CATEGORY_TOUGH, .contestComboStarterId = COMBO_STARTER_ENDURE, .contestComboMoves = {0}, @@ -5356,7 +5430,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .category = DAMAGE_CATEGORY_STATUS, .zMove = { .effect = Z_EFFECT_DEF_UP_1 }, .magicCoatAffected = TRUE, - .contestEffect = CONTEST_EFFECT_STARTLE_MONS_SAME_TYPE_APPEAL, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_STARTLE_MON_WITH_JUDGES_ATTENTION : CONTEST_EFFECT_STARTLE_MONS_SAME_TYPE_APPEAL, .contestCategory = CONTEST_CATEGORY_CUTE, .contestComboStarterId = COMBO_STARTER_CHARM, .contestComboMoves = {0}, @@ -5381,8 +5455,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .makesContact = TRUE, .instructBanned = TRUE, .parentalBondBanned = TRUE, - .contestEffect = CONTEST_EFFECT_DONT_EXCITE_AUDIENCE, - .contestCategory = CONTEST_CATEGORY_TOUGH, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_REPETITION_NOT_BORING : CONTEST_EFFECT_DONT_EXCITE_AUDIENCE, + .contestCategory = C_UPDATED_MOVE_CATEGORIES >= GEN_6 ? CONTEST_CATEGORY_CUTE : CONTEST_CATEGORY_TOUGH, .contestComboStarterId = 0, .contestComboMoves = {COMBO_STARTER_DEFENSE_CURL, COMBO_STARTER_HARDEN}, .battleAnimScript = gBattleAnimMove_Rollout, @@ -5402,7 +5476,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, .makesContact = TRUE, - .contestEffect = CONTEST_EFFECT_BADLY_STARTLE_PREV_MONS, + .contestEffect = CONTEST_EFFECT_BADLY_STARTLE_PREV_MONS, //C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_QUICKLY_GROW_BORED : .contestCategory = CONTEST_CATEGORY_COOL, .contestComboStarterId = 0, .contestComboMoves = {COMBO_STARTER_SWORDS_DANCE}, @@ -5425,8 +5499,9 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .priority = 0, .category = DAMAGE_CATEGORY_STATUS, .zMove = { .effect = Z_EFFECT_RESET_STATS }, + //.ignoresSubstitute = TRUE, In Gen4+, the attack raise will no longer bypass Substitute. However, this is tricky to code .magicCoatAffected = TRUE, - .contestEffect = CONTEST_EFFECT_BETTER_IF_FIRST, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_WORSEN_CONDITION_OF_PREV_MONS : CONTEST_EFFECT_BETTER_IF_FIRST, .contestCategory = CONTEST_CATEGORY_CUTE, .contestComboStarterId = 0, .contestComboMoves = {0}, @@ -5452,7 +5527,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .snatchAffected = TRUE, .ignoresProtect = TRUE, .mirrorMoveBanned = TRUE, - .contestEffect = CONTEST_EFFECT_BETTER_IF_SAME_TYPE, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_BETTER_IF_FIRST : CONTEST_EFFECT_BETTER_IF_SAME_TYPE, .contestCategory = CONTEST_CATEGORY_CUTE, .contestComboStarterId = 0, .contestComboMoves = {0}, @@ -5479,7 +5554,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .moveEffect = MOVE_EFFECT_PARALYSIS, .chance = 30, }), - .contestEffect = CONTEST_EFFECT_BADLY_STARTLE_FRONT_MON, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_HIGHLY_APPEALING : CONTEST_EFFECT_BADLY_STARTLE_FRONT_MON, .contestCategory = CONTEST_CATEGORY_COOL, .contestComboStarterId = 0, .contestComboMoves = {COMBO_STARTER_CHARGE}, @@ -5494,7 +5569,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = "连续击中,威力就会提高。"), #if B_UPDATED_MOVE_DATA >= GEN_6 .power = 40, - #elif B_UPDATED_MOVE_DATA >= GEN_5 + #elif B_UPDATED_MOVE_DATA == GEN_5 .power = 20, #else .power = 10, @@ -5531,12 +5606,13 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, .makesContact = TRUE, + .ignoresKingsRock = B_UPDATED_MOVE_FLAGS < GEN_3, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_DEF_PLUS_1, .self = TRUE, .chance = 10, }), - .contestEffect = CONTEST_EFFECT_BETTER_IF_SAME_TYPE, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_AFFECTED_BY_PREV_APPEAL : CONTEST_EFFECT_BETTER_IF_SAME_TYPE, .contestCategory = CONTEST_CATEGORY_COOL, .contestComboStarterId = 0, .contestComboMoves = {0}, @@ -5559,7 +5635,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .priority = 0, .category = DAMAGE_CATEGORY_STATUS, .zMove = { .effect = Z_EFFECT_SPDEF_UP_1 }, - .ignoresProtect = (B_UPDATED_MOVE_FLAGS >= GEN_6) || (B_UPDATED_MOVE_FLAGS <= GEN_3), + .ignoresProtect = (B_UPDATED_MOVE_FLAGS >= GEN_6) || (B_UPDATED_MOVE_FLAGS < GEN_3), .magicCoatAffected = TRUE, .contestEffect = CONTEST_EFFECT_MAKE_FOLLOWING_MONS_NERVOUS, .contestCategory = CONTEST_CATEGORY_BEAUTY, @@ -5618,7 +5694,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .mimicBanned = TRUE, .encoreBanned = TRUE, .assistBanned = TRUE, - .contestEffect = CONTEST_EFFECT_REPETITION_NOT_BORING, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_QUALITY_DEPENDS_ON_TIMING : CONTEST_EFFECT_REPETITION_NOT_BORING, .contestCategory = CONTEST_CATEGORY_CUTE, .contestComboStarterId = 0, .contestComboMoves = {COMBO_STARTER_REST}, @@ -5645,8 +5721,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .ignoresProtect = TRUE, .ignoresSubstitute = TRUE, .mirrorMoveBanned = TRUE, - .soundMove = B_UPDATED_MOVE_FLAGS != GEN_5, - .contestEffect = CONTEST_EFFECT_BETTER_IF_LAST, + .soundMove = TRUE, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_AVOID_STARTLE : CONTEST_EFFECT_BETTER_IF_LAST, .contestCategory = CONTEST_CATEGORY_BEAUTY, .contestComboStarterId = COMBO_STARTER_HEAL_BELL, .contestComboMoves = {COMBO_STARTER_LUCKY_CHANT}, @@ -5669,7 +5745,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, .makesContact = TRUE, - .contestEffect = CONTEST_EFFECT_EXCITE_AUDIENCE_IN_ANY_CONTEST, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_HIGHLY_APPEALING : CONTEST_EFFECT_EXCITE_AUDIENCE_IN_ANY_CONTEST, .contestCategory = CONTEST_CATEGORY_CUTE, .contestComboStarterId = 0, .contestComboMoves = {0}, @@ -5695,7 +5771,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .contestEffect = CONTEST_EFFECT_REPETITION_NOT_BORING, .contestCategory = CONTEST_CATEGORY_CUTE, .contestComboStarterId = 0, - .contestComboMoves = {0}, + .contestComboMoves = {COMBO_STARTER_CELEBRATE, COMBO_STARTER_COVET, COMBO_STARTER_HAPPY_HOUR, COMBO_STARTER_WISH}, .battleAnimScript = gBattleAnimMove_Present, .validApprenticeMove = TRUE, }, @@ -5715,7 +5791,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, .makesContact = TRUE, - .contestEffect = CONTEST_EFFECT_EXCITE_AUDIENCE_IN_ANY_CONTEST, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_STARTLE_PREV_MON : CONTEST_EFFECT_EXCITE_AUDIENCE_IN_ANY_CONTEST, .contestCategory = CONTEST_CATEGORY_CUTE, .contestComboStarterId = 0, .contestComboMoves = {0}, @@ -5741,7 +5817,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .snatchAffected = TRUE, .ignoresProtect = TRUE, .mirrorMoveBanned = TRUE, - .contestEffect = CONTEST_EFFECT_AVOID_STARTLE, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_AVOID_STARTLE_ONCE : CONTEST_EFFECT_AVOID_STARTLE, .contestCategory = CONTEST_CATEGORY_BEAUTY, .contestComboStarterId = 0, .contestComboMoves = {0}, @@ -5758,13 +5834,13 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .effect = EFFECT_PAIN_SPLIT, .power = 0, .type = TYPE_NORMAL, - .accuracy = 0, + .accuracy = B_UPDATED_MOVE_DATA >= GEN_3 ? 0 : 100, .pp = 20, .target = MOVE_TARGET_SELECTED, .priority = 0, .category = DAMAGE_CATEGORY_STATUS, .zMove = { .effect = Z_EFFECT_DEF_UP_1 }, - .contestEffect = CONTEST_EFFECT_BADLY_STARTLE_FRONT_MON, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_APPEAL_AS_GOOD_AS_PREV_ONES : CONTEST_EFFECT_BADLY_STARTLE_FRONT_MON, .contestCategory = CONTEST_CATEGORY_SMART, .contestComboStarterId = 0, .contestComboMoves = {COMBO_STARTER_ENDURE}, @@ -5791,7 +5867,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .moveEffect = MOVE_EFFECT_BURN, .chance = 50, }), - .contestEffect = CONTEST_EFFECT_HIGHLY_APPEALING, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_BETTER_IF_LAST : CONTEST_EFFECT_HIGHLY_APPEALING, .contestCategory = CONTEST_CATEGORY_BEAUTY, .contestComboStarterId = 0, .contestComboMoves = {COMBO_STARTER_SUNNY_DAY}, @@ -5865,7 +5941,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, .makesContact = TRUE, - .contestEffect = CONTEST_EFFECT_BETTER_IF_SAME_TYPE, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_REPETITION_NOT_BORING : CONTEST_EFFECT_BETTER_IF_SAME_TYPE, .contestCategory = CONTEST_CATEGORY_COOL, .contestComboStarterId = 0, .contestComboMoves = {0}, @@ -5892,7 +5968,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .moveEffect = MOVE_EFFECT_PARALYSIS, .chance = 30, }), - .contestEffect = CONTEST_EFFECT_BADLY_STARTLE_PREV_MONS, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_STARTLE_PREV_MON : CONTEST_EFFECT_BADLY_STARTLE_PREV_MONS, .contestCategory = CONTEST_CATEGORY_COOL, .contestComboStarterId = COMBO_STARTER_DRAGON_BREATH, .contestComboMoves = {COMBO_STARTER_DRAGON_DANCE, COMBO_STARTER_DRAGON_RAGE, COMBO_STARTER_DRAGON_RUSH, COMBO_STARTER_DRAGON_TAIL}, @@ -5917,10 +5993,10 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .zMove = { .effect = Z_EFFECT_RESET_STATS }, .ignoresProtect = TRUE, .mirrorMoveBanned = TRUE, - .contestEffect = CONTEST_EFFECT_MAKE_FOLLOWING_MONS_NERVOUS, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_BETTER_WITH_GOOD_CONDITION : CONTEST_EFFECT_MAKE_FOLLOWING_MONS_NERVOUS, .contestCategory = CONTEST_CATEGORY_CUTE, .contestComboStarterId = 0, - .contestComboMoves = {0}, + .contestComboMoves = {COMBO_STARTER_AGILITY, COMBO_STARTER_AMNESIA, COMBO_STARTER_HONE_CLAWS, COMBO_STARTER_CALM_MIND, COMBO_STARTER_NASTY_PLOT, COMBO_STARTER_ROCK_POLISH}, .battleAnimScript = gBattleAnimMove_BatonPass, .validApprenticeMove = TRUE, }, @@ -5945,7 +6021,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .ignoresSubstitute = TRUE, .contestEffect = CONTEST_EFFECT_MAKE_FOLLOWING_MONS_NERVOUS, .contestCategory = CONTEST_CATEGORY_CUTE, - .contestComboStarterId = 0, + .contestComboStarterId = COMBO_STARTER_ENCORE, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_Encore, .validApprenticeMove = TRUE, @@ -5967,7 +6043,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .category = DAMAGE_CATEGORY_PHYSICAL, .makesContact = TRUE, .ignoresKingsRock = (B_UPDATED_MOVE_FLAGS == GEN_3 || B_UPDATED_MOVE_FLAGS == GEN_4), - .contestEffect = CONTEST_EFFECT_BADLY_STARTLE_MONS_WITH_GOOD_APPEALS, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_STARTLE_MONS_SAME_TYPE_APPEAL : CONTEST_EFFECT_BADLY_STARTLE_MONS_WITH_GOOD_APPEALS, .contestCategory = CONTEST_CATEGORY_SMART, .contestComboStarterId = 0, .contestComboMoves = {0}, @@ -5999,7 +6075,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = } #endif ), - .contestEffect = CONTEST_EFFECT_AVOID_STARTLE_ONCE, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_BETTER_WHEN_AUDIENCE_EXCITED : CONTEST_EFFECT_AVOID_STARTLE_ONCE, .contestCategory = CONTEST_CATEGORY_COOL, .contestComboStarterId = 0, .contestComboMoves = {0}, @@ -6023,7 +6099,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .category = DAMAGE_CATEGORY_STATUS, .zMove = { .effect = Z_EFFECT_ACC_UP_1 }, .magicCoatAffected = TRUE, - .contestEffect = CONTEST_EFFECT_BADLY_STARTLE_PREV_MONS, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_AVOID_STARTLE_ONCE : CONTEST_EFFECT_BADLY_STARTLE_PREV_MONS, .contestCategory = CONTEST_CATEGORY_CUTE, .contestComboStarterId = COMBO_STARTER_SWEET_SCENT, .contestComboMoves = {0}, @@ -6050,7 +6126,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .moveEffect = MOVE_EFFECT_DEF_MINUS_1, .chance = 30, }), - .contestEffect = CONTEST_EFFECT_BADLY_STARTLE_FRONT_MON, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_HIGHLY_APPEALING : CONTEST_EFFECT_BADLY_STARTLE_FRONT_MON, .contestCategory = CONTEST_CATEGORY_COOL, .contestComboStarterId = 0, .contestComboMoves = {0}, @@ -6101,10 +6177,10 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .priority = -1, .category = DAMAGE_CATEGORY_PHYSICAL, .makesContact = TRUE, - .contestEffect = CONTEST_EFFECT_NEXT_APPEAL_LATER, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_BETTER_IF_LAST : CONTEST_EFFECT_NEXT_APPEAL_LATER, .contestCategory = CONTEST_CATEGORY_COOL, .contestComboStarterId = 0, - .contestComboMoves = {COMBO_STARTER_FAKE_OUT}, + .contestComboMoves = {COMBO_STARTER_FAKE_OUT, COMBO_STARTER_ENTRAINMENT, COMBO_STARTER_PLAY_NICE}, .battleAnimScript = gBattleAnimMove_VitalThrow, .validApprenticeMove = TRUE, }, @@ -6222,7 +6298,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .power = 100, .type = TYPE_FIGHTING, .accuracy = 80, - .criticalHitStage = 1, + .criticalHitStage = B_UPDATED_MOVE_DATA >= GEN_3 ? 1 : 2, .pp = 5, .target = MOVE_TARGET_SELECTED, .priority = 0, @@ -6250,13 +6326,14 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .target = MOVE_TARGET_BOTH, .priority = 0, .category = DAMAGE_CATEGORY_SPECIAL, + .ignoresKingsRock = B_UPDATED_MOVE_FLAGS < GEN_3, .damagesAirborneDoubleDamage = TRUE, .windMove = TRUE, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_FLINCH, .chance = 20, }), - .contestEffect = CONTEST_EFFECT_SCRAMBLE_NEXT_TURN_ORDER, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_HIGHLY_APPEALING : CONTEST_EFFECT_SCRAMBLE_NEXT_TURN_ORDER, .contestCategory = CONTEST_CATEGORY_COOL, .contestComboStarterId = 0, .contestComboMoves = {0}, @@ -6281,7 +6358,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .ignoresProtect = TRUE, .mirrorMoveBanned = TRUE, .contestEffect = CONTEST_EFFECT_BETTER_WHEN_AUDIENCE_EXCITED, - .contestCategory = CONTEST_CATEGORY_TOUGH, + .contestCategory = C_UPDATED_MOVE_CATEGORIES >= GEN_6 ? CONTEST_CATEGORY_BEAUTY : CONTEST_CATEGORY_TOUGH, .contestComboStarterId = COMBO_STARTER_RAIN_DANCE, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_RainDance, @@ -6359,14 +6436,15 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .target = MOVE_TARGET_DEPENDS, .priority = -5, .category = DAMAGE_CATEGORY_SPECIAL, + .ignoresProtect = B_UPDATED_MOVE_FLAGS < GEN_5, .mirrorMoveBanned = B_UPDATED_MOVE_FLAGS >= GEN_4, .meFirstBanned = TRUE, .metronomeBanned = TRUE, .assistBanned = TRUE, - .contestEffect = CONTEST_EFFECT_AVOID_STARTLE_ONCE, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_BETTER_IF_LAST : CONTEST_EFFECT_AVOID_STARTLE_ONCE, .contestCategory = CONTEST_CATEGORY_BEAUTY, .contestComboStarterId = 0, - .contestComboMoves = {COMBO_STARTER_TAUNT}, + .contestComboMoves = {COMBO_STARTER_TAUNT, COMBO_STARTER_ENCORE, COMBO_STARTER_TORMENT}, .battleAnimScript = gBattleAnimMove_MirrorCoat, .validApprenticeMove = TRUE, }, @@ -6468,7 +6546,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .moveEffect = MOVE_EFFECT_SP_DEF_MINUS_1, .chance = 20, }), - .contestEffect = CONTEST_EFFECT_SHIFT_JUDGE_ATTENTION, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_HIGHLY_APPEALING : CONTEST_EFFECT_SHIFT_JUDGE_ATTENTION, .contestCategory = CONTEST_CATEGORY_SMART, .contestComboStarterId = 0, .contestComboMoves = {0}, @@ -6484,7 +6562,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = "向对手发送一团念力攻击。"), #if B_UPDATED_MOVE_DATA >= GEN_6 .power = 120, - #elif B_UPDATED_MOVE_DATA >= GEN_5 + #elif B_UPDATED_MOVE_DATA == GEN_5 .power = 100, #else .power = 80, @@ -6498,7 +6576,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .category = DAMAGE_CATEGORY_SPECIAL, .ignoresProtect = TRUE, .mirrorMoveBanned = TRUE, - .contestEffect = CONTEST_EFFECT_DONT_EXCITE_AUDIENCE, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_BETTER_IF_SAME_TYPE : CONTEST_EFFECT_DONT_EXCITE_AUDIENCE, .contestCategory = CONTEST_CATEGORY_SMART, .contestComboStarterId = 0, .contestComboMoves = {COMBO_STARTER_CALM_MIND, COMBO_STARTER_CONFUSION, COMBO_STARTER_KINESIS, COMBO_STARTER_PSYCHIC}, @@ -6525,7 +6603,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .moveEffect = MOVE_EFFECT_DEF_MINUS_1, .chance = 50, }), - .contestEffect = CONTEST_EFFECT_BETTER_WITH_GOOD_CONDITION, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_HIGHLY_APPEALING : CONTEST_EFFECT_BETTER_WITH_GOOD_CONDITION, .contestCategory = CONTEST_CATEGORY_TOUGH, .contestComboStarterId = 0, .contestComboMoves = {0}, @@ -6547,6 +6625,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .target = MOVE_TARGET_SELECTED, .priority = 0, .category = DAMAGE_CATEGORY_SPECIAL, + .ignoresKingsRock = B_UPDATED_MOVE_FLAGS < GEN_3, .damagesUnderwater = TRUE, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_WRAP, @@ -6574,7 +6653,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .target = MOVE_TARGET_SELECTED, .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, - .contestEffect = CONTEST_EFFECT_BADLY_STARTLE_MONS_WITH_GOOD_APPEALS, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_BETTER_WITH_GOOD_CONDITION : CONTEST_EFFECT_BADLY_STARTLE_MONS_WITH_GOOD_APPEALS, .contestCategory = CONTEST_CATEGORY_SMART, .contestComboStarterId = 0, .contestComboMoves = {0}, @@ -6601,7 +6680,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .moveEffect = MOVE_EFFECT_FLINCH, .chance = 100, }), - .contestEffect = CONTEST_EFFECT_STARTLE_MONS_SAME_TYPE_APPEAL, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_STARTLE_PREV_MON : CONTEST_EFFECT_STARTLE_MONS_SAME_TYPE_APPEAL, .contestCategory = CONTEST_CATEGORY_CUTE, .contestComboStarterId = COMBO_STARTER_FAKE_OUT, .contestComboMoves = {0}, @@ -6631,7 +6710,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .moveEffect = MOVE_EFFECT_UPROAR, .self = TRUE, }), - .contestEffect = CONTEST_EFFECT_SCRAMBLE_NEXT_TURN_ORDER, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_STARTLE_MON_WITH_JUDGES_ATTENTION : CONTEST_EFFECT_SCRAMBLE_NEXT_TURN_ORDER, .contestCategory = CONTEST_CATEGORY_CUTE, .contestComboStarterId = 0, .contestComboMoves = {0}, @@ -6657,7 +6736,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .snatchAffected = TRUE, .ignoresProtect = TRUE, .mirrorMoveBanned = TRUE, - .contestEffect = CONTEST_EFFECT_AVOID_STARTLE_ONCE, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_IMPROVE_CONDITION_PREVENT_NERVOUSNESS : CONTEST_EFFECT_AVOID_STARTLE_ONCE, .contestCategory = CONTEST_CATEGORY_TOUGH, .contestComboStarterId = COMBO_STARTER_STOCKPILE, .contestComboMoves = {0}, @@ -6672,7 +6751,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = "将积蓄的力量撞向对手攻击。\n" "积蓄得越多,威力越大。"), .effect = EFFECT_SPIT_UP, - .power = B_UPDATED_MOVE_DATA >= GEN_4 ? 1 : 100, + .power = 1, .type = TYPE_NORMAL, .accuracy = 100, .pp = 10, @@ -6680,7 +6759,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .priority = 0, .category = DAMAGE_CATEGORY_SPECIAL, .mirrorMoveBanned = TRUE, - .contestEffect = CONTEST_EFFECT_HIGHLY_APPEALING, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_BETTER_WITH_GOOD_CONDITION : CONTEST_EFFECT_HIGHLY_APPEALING, .contestCategory = CONTEST_CATEGORY_TOUGH, .contestComboStarterId = 0, .contestComboMoves = {COMBO_STARTER_STOCKPILE}, @@ -6707,7 +6786,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .snatchAffected = TRUE, .ignoresProtect = TRUE, .mirrorMoveBanned = TRUE, - .contestEffect = CONTEST_EFFECT_IMPROVE_CONDITION_PREVENT_NERVOUSNESS, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_AVOID_STARTLE_ONCE : CONTEST_EFFECT_IMPROVE_CONDITION_PREVENT_NERVOUSNESS, .contestCategory = CONTEST_CATEGORY_TOUGH, .contestComboStarterId = 0, .contestComboMoves = {COMBO_STARTER_STOCKPILE}, @@ -6734,7 +6813,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .moveEffect = MOVE_EFFECT_BURN, .chance = 10, }), - .contestEffect = CONTEST_EFFECT_HIGHLY_APPEALING, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_STARTLE_PREV_MONS : CONTEST_EFFECT_HIGHLY_APPEALING, .contestCategory = CONTEST_CATEGORY_BEAUTY, .contestComboStarterId = 0, .contestComboMoves = {COMBO_STARTER_SUNNY_DAY}, @@ -6759,7 +6838,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .zMove = { .effect = Z_EFFECT_SPD_UP_1 }, .ignoresProtect = TRUE, .mirrorMoveBanned = TRUE, - .contestEffect = CONTEST_EFFECT_BADLY_STARTLE_PREV_MONS, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_BADLY_STARTLE_MONS_WITH_GOOD_APPEALS : CONTEST_EFFECT_BADLY_STARTLE_PREV_MONS, .contestCategory = CONTEST_CATEGORY_BEAUTY, .contestComboStarterId = COMBO_STARTER_HAIL, .contestComboMoves = {0}, @@ -6785,7 +6864,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .magicCoatAffected = B_UPDATED_MOVE_FLAGS >= GEN_5, .contestEffect = CONTEST_EFFECT_MAKE_FOLLOWING_MONS_NERVOUS, .contestCategory = CONTEST_CATEGORY_TOUGH, - .contestComboStarterId = 0, + .contestComboStarterId = COMBO_STARTER_TORMENT, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_Torment, .validApprenticeMove = TRUE, @@ -6832,9 +6911,9 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .argument = { .nonVolatileStatus = MOVE_EFFECT_BURN }, .zMove = { .effect = Z_EFFECT_ATK_UP_1 }, .magicCoatAffected = TRUE, - .contestEffect = CONTEST_EFFECT_BADLY_STARTLE_FRONT_MON, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_SHIFT_JUDGE_ATTENTION : CONTEST_EFFECT_BADLY_STARTLE_FRONT_MON, .contestCategory = CONTEST_CATEGORY_BEAUTY, - .contestComboStarterId = 0, + .contestComboStarterId = COMBO_STARTER_WILL_O_WISP, .contestComboMoves = {COMBO_STARTER_SUNNY_DAY}, .battleAnimScript = gBattleAnimMove_WillOWisp, .validApprenticeMove = TRUE, @@ -6849,7 +6928,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .effect = EFFECT_MEMENTO, .power = 0, .type = TYPE_DARK, - .accuracy = 100, + .accuracy = B_UPDATED_MOVE_DATA >= GEN_4 ? 100 : 0, .pp = 10, .target = MOVE_TARGET_SELECTED, .priority = 0, @@ -6858,7 +6937,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .contestEffect = CONTEST_EFFECT_GREAT_APPEAL_BUT_NO_MORE_MOVES, .contestCategory = CONTEST_CATEGORY_TOUGH, .contestComboStarterId = 0, - .contestComboMoves = {0}, + .contestComboMoves = {COMBO_STARTER_MEAN_LOOK, COMBO_STARTER_BLOCK}, .battleAnimScript = gBattleAnimMove_Memento, .validApprenticeMove = TRUE, }, @@ -6909,7 +6988,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .copycatBanned = TRUE, .instructBanned = TRUE, .assistBanned = TRUE, - .contestEffect = CONTEST_EFFECT_NEXT_APPEAL_LATER, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_BETTER_IF_LAST : CONTEST_EFFECT_NEXT_APPEAL_LATER, .contestCategory = CONTEST_CATEGORY_TOUGH, .contestComboStarterId = 0, .contestComboMoves = {COMBO_STARTER_FOCUS_ENERGY}, @@ -6936,10 +7015,10 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_REMOVE_STATUS, }), - .contestEffect = CONTEST_EFFECT_STARTLE_PREV_MON, - .contestCategory = CONTEST_CATEGORY_SMART, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_AFFECTED_BY_PREV_APPEAL : CONTEST_EFFECT_STARTLE_PREV_MON, + .contestCategory = C_UPDATED_MOVE_CATEGORIES >= GEN_6 ? CONTEST_CATEGORY_TOUGH : CONTEST_CATEGORY_SMART, .contestComboStarterId = 0, - .contestComboMoves = {0}, + .contestComboMoves = {COMBO_STARTER_FORCE_PALM, COMBO_STARTER_THUNDER_WAVE, COMBO_STARTER_GLARE}, .battleAnimScript = gBattleAnimMove_SmellingSalts, .validApprenticeMove = TRUE, }, @@ -6953,7 +7032,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .effect = EFFECT_FOLLOW_ME, .power = 0, .type = TYPE_NORMAL, - .accuracy = 100, + .accuracy = 0, .pp = 20, .target = MOVE_TARGET_USER, .priority = B_UPDATED_MOVE_DATA >= GEN_6 ? 2 : 3, @@ -6986,12 +7065,12 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .target = MOVE_TARGET_DEPENDS, .priority = 0, .category = DAMAGE_CATEGORY_STATUS, - .metronomeBanned = B_UPDATED_MOVE_FLAGS >= GEN_4, + .metronomeBanned = B_UPDATED_MOVE_FLAGS >= GEN_5, .copycatBanned = TRUE, .sleepTalkBanned = TRUE, .instructBanned = TRUE, .encoreBanned = TRUE, - .assistBanned = TRUE, + .assistBanned = B_UPDATED_MOVE_FLAGS >= GEN_6, .mimicBanned = TRUE, .contestEffect = CONTEST_EFFECT_BETTER_WHEN_AUDIENCE_EXCITED, .contestCategory = CONTEST_CATEGORY_BEAUTY, @@ -7010,7 +7089,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .effect = EFFECT_CHARGE, .power = 0, .type = TYPE_ELECTRIC, - .accuracy = 100, + .accuracy = 0, .pp = 20, .target = MOVE_TARGET_USER, .priority = 0, @@ -7019,7 +7098,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .snatchAffected = TRUE, .ignoresProtect = TRUE, .mirrorMoveBanned = TRUE, - .contestEffect = CONTEST_EFFECT_BETTER_IF_SAME_TYPE, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_IMPROVE_CONDITION_PREVENT_NERVOUSNESS : CONTEST_EFFECT_BETTER_IF_SAME_TYPE, .contestCategory = CONTEST_CATEGORY_SMART, .contestComboStarterId = COMBO_STARTER_CHARGE, .contestComboMoves = {0}, @@ -7044,7 +7123,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .zMove = { .effect = Z_EFFECT_ATK_UP_1 }, .ignoresSubstitute = TRUE, .magicCoatAffected = B_UPDATED_MOVE_FLAGS >= GEN_5, - .contestEffect = CONTEST_EFFECT_MAKE_FOLLOWING_MONS_NERVOUS, + .mirrorMoveBanned = B_UPDATED_MOVE_FLAGS < GEN_4, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_STARTLE_MON_WITH_JUDGES_ATTENTION : CONTEST_EFFECT_MAKE_FOLLOWING_MONS_NERVOUS, .contestCategory = CONTEST_CATEGORY_SMART, .contestComboStarterId = COMBO_STARTER_TAUNT, .contestComboMoves = {0}, @@ -7061,7 +7141,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .effect = EFFECT_HELPING_HAND, .power = 0, .type = TYPE_NORMAL, - .accuracy = 100, + .accuracy = 0, .pp = 20, .target = B_UPDATED_MOVE_DATA >= GEN_4 ? MOVE_TARGET_ALLY : MOVE_TARGET_USER, .priority = 5, @@ -7073,7 +7153,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .metronomeBanned = TRUE, .copycatBanned = TRUE, .assistBanned = TRUE, - .contestEffect = CONTEST_EFFECT_MAKE_FOLLOWING_MONS_NERVOUS, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_HIGHLY_APPEALING : CONTEST_EFFECT_MAKE_FOLLOWING_MONS_NERVOUS, .contestCategory = CONTEST_CATEGORY_SMART, .contestComboStarterId = 0, .contestComboMoves = {0}, @@ -7099,7 +7179,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .metronomeBanned = TRUE, .copycatBanned = TRUE, .assistBanned = TRUE, - .contestEffect = CONTEST_EFFECT_BETTER_IF_SAME_TYPE, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_STARTLE_MONS_SAME_TYPE_APPEAL : CONTEST_EFFECT_BETTER_IF_SAME_TYPE, .contestCategory = CONTEST_CATEGORY_SMART, .contestComboStarterId = 0, .contestComboMoves = {0}, @@ -7152,9 +7232,9 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .snatchAffected = B_UPDATED_MOVE_FLAGS >= GEN_5, .ignoresProtect = TRUE, .mirrorMoveBanned = TRUE, - .contestEffect = CONTEST_EFFECT_DONT_EXCITE_AUDIENCE, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_BETTER_IF_LAST : CONTEST_EFFECT_DONT_EXCITE_AUDIENCE, .contestCategory = CONTEST_CATEGORY_CUTE, - .contestComboStarterId = 0, + .contestComboStarterId = COMBO_STARTER_WISH, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_Wish, .validApprenticeMove = TRUE, @@ -7169,7 +7249,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .effect = EFFECT_ASSIST, .power = 0, .type = TYPE_NORMAL, - .accuracy = 100, + .accuracy = 0, .pp = 20, .target = MOVE_TARGET_DEPENDS, .priority = 0, @@ -7200,7 +7280,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .effect = EFFECT_INGRAIN, .power = 0, .type = TYPE_GRASS, - .accuracy = 100, + .accuracy = 0, .pp = 20, .target = MOVE_TARGET_USER, .priority = 0, @@ -7210,7 +7290,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .ignoresProtect = TRUE, .mirrorMoveBanned = TRUE, .skyBattleBanned = TRUE, - .contestEffect = CONTEST_EFFECT_AVOID_STARTLE, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_IMPROVE_CONDITION_PREVENT_NERVOUSNESS : CONTEST_EFFECT_AVOID_STARTLE, .contestCategory = CONTEST_CATEGORY_SMART, .contestComboStarterId = 0, .contestComboMoves = {0}, @@ -7254,7 +7334,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .effect = EFFECT_MAGIC_COAT, .power = 0, .type = TYPE_PSYCHIC, - .accuracy = 100, + .accuracy = 0, .pp = 15, .target = MOVE_TARGET_DEPENDS, .priority = 4, @@ -7262,7 +7342,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .zMove = { .effect = Z_EFFECT_SPDEF_UP_2 }, .ignoresProtect = TRUE, .mirrorMoveBanned = TRUE, - .contestEffect = CONTEST_EFFECT_AVOID_STARTLE, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_BETTER_IF_LAST : CONTEST_EFFECT_AVOID_STARTLE, .contestCategory = CONTEST_CATEGORY_BEAUTY, .contestComboStarterId = 0, .contestComboMoves = {0}, @@ -7279,7 +7359,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .effect = EFFECT_RECYCLE, .power = 0, .type = TYPE_NORMAL, - .accuracy = 100, + .accuracy = 0, .pp = 10, .target = MOVE_TARGET_USER, .priority = 0, @@ -7288,7 +7368,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .snatchAffected = B_UPDATED_MOVE_FLAGS >= GEN_5, .ignoresProtect = TRUE, .mirrorMoveBanned = TRUE, - .contestEffect = CONTEST_EFFECT_REPETITION_NOT_BORING, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_APPEAL_AS_GOOD_AS_PREV_ONE : CONTEST_EFFECT_REPETITION_NOT_BORING, .contestCategory = CONTEST_CATEGORY_SMART, .contestComboStarterId = 0, .contestComboMoves = {0}, @@ -7309,7 +7389,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .priority = -4, .category = DAMAGE_CATEGORY_PHYSICAL, .makesContact = TRUE, - .contestEffect = CONTEST_EFFECT_NEXT_APPEAL_LATER, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_BETTER_IF_LAST : CONTEST_EFFECT_NEXT_APPEAL_LATER, .contestCategory = CONTEST_CATEGORY_TOUGH, .contestComboStarterId = COMBO_STARTER_REVENGE, .contestComboMoves = {COMBO_STARTER_PAYBACK}, @@ -7332,7 +7412,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, .makesContact = TRUE, - .contestEffect = CONTEST_EFFECT_BADLY_STARTLE_FRONT_MON, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_HIGHLY_APPEALING : CONTEST_EFFECT_BADLY_STARTLE_FRONT_MON, .contestCategory = CONTEST_CATEGORY_COOL, .contestComboStarterId = 0, .contestComboMoves = {COMBO_STARTER_FOCUS_ENERGY}, @@ -7380,7 +7460,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, .makesContact = TRUE, - .contestEffect = CONTEST_EFFECT_BADLY_STARTLE_FRONT_MON, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_STARTLE_PREV_MON : CONTEST_EFFECT_BADLY_STARTLE_FRONT_MON, .contestCategory = CONTEST_CATEGORY_SMART, .contestComboStarterId = 0, .contestComboMoves = {COMBO_STARTER_FAKE_OUT}, @@ -7426,7 +7506,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .target = MOVE_TARGET_BOTH, .priority = 0, .category = DAMAGE_CATEGORY_SPECIAL, - .contestEffect = CONTEST_EFFECT_BETTER_WHEN_LATER, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_USER_MORE_EASILY_STARTLED : CONTEST_EFFECT_BETTER_WHEN_LATER, .contestCategory = CONTEST_CATEGORY_BEAUTY, .contestComboStarterId = 0, .contestComboMoves = {COMBO_STARTER_EARTHQUAKE, COMBO_STARTER_ENDURE, COMBO_STARTER_SUNNY_DAY}, @@ -7467,7 +7547,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .effect = EFFECT_IMPRISON, .power = 0, .type = TYPE_PSYCHIC, - .accuracy = 100, + .accuracy = 0, .pp = 10, .target = MOVE_TARGET_USER, .priority = 0, @@ -7478,7 +7558,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .ignoresSubstitute = TRUE, .mirrorMoveBanned = TRUE, .forcePressure = TRUE, - .contestEffect = CONTEST_EFFECT_WORSEN_CONDITION_OF_PREV_MONS, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_DONT_EXCITE_AUDIENCE : CONTEST_EFFECT_WORSEN_CONDITION_OF_PREV_MONS, .contestCategory = CONTEST_CATEGORY_SMART, .contestComboStarterId = 0, .contestComboMoves = {0}, @@ -7495,7 +7575,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .effect = EFFECT_REFRESH, .power = 0, .type = TYPE_NORMAL, - .accuracy = 100, + .accuracy = 0, .pp = 20, .target = MOVE_TARGET_USER, .priority = 0, @@ -7504,7 +7584,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .snatchAffected = TRUE, .ignoresProtect = TRUE, .mirrorMoveBanned = TRUE, - .contestEffect = CONTEST_EFFECT_IMPROVE_CONDITION_PREVENT_NERVOUSNESS, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_AVOID_STARTLE_ONCE : CONTEST_EFFECT_IMPROVE_CONDITION_PREVENT_NERVOUSNESS, .contestCategory = CONTEST_CATEGORY_CUTE, .contestComboStarterId = 0, .contestComboMoves = {COMBO_STARTER_SING, COMBO_STARTER_WATER_SPORT}, @@ -7521,7 +7601,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .effect = EFFECT_GRUDGE, .power = 0, .type = TYPE_GHOST, - .accuracy = 100, + .accuracy = 0, .pp = 5, .target = MOVE_TARGET_USER, .priority = 0, @@ -7530,10 +7610,10 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .ignoresProtect = TRUE, .ignoresSubstitute = TRUE, .mirrorMoveBanned = TRUE, - .contestEffect = CONTEST_EFFECT_BETTER_WHEN_LATER, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_JAMS_OTHERS_BUT_MISS_ONE_TURN : CONTEST_EFFECT_BETTER_WHEN_LATER, .contestCategory = CONTEST_CATEGORY_TOUGH, .contestComboStarterId = 0, - .contestComboMoves = {COMBO_STARTER_CURSE}, + .contestComboMoves = {COMBO_STARTER_CURSE, COMBO_STARTER_ENCORE, COMBO_STARTER_TAUNT, COMBO_STARTER_TORMENT}, .battleAnimScript = gBattleAnimMove_Grudge, .validApprenticeMove = TRUE, }, @@ -7547,7 +7627,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .effect = EFFECT_SNATCH, .power = 0, .type = TYPE_DARK, - .accuracy = 100, + .accuracy = 0, .pp = 10, .target = MOVE_TARGET_DEPENDS, .priority = 4, @@ -7558,7 +7638,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .metronomeBanned = TRUE, .copycatBanned = TRUE, .assistBanned = TRUE, - .contestEffect = CONTEST_EFFECT_BADLY_STARTLE_MONS_WITH_GOOD_APPEALS, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_APPEAL_AS_GOOD_AS_PREV_ONE : CONTEST_EFFECT_BADLY_STARTLE_MONS_WITH_GOOD_APPEALS, .contestCategory = CONTEST_CATEGORY_SMART, .contestComboStarterId = 0, .contestComboMoves = {0}, @@ -7609,7 +7689,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .makesContact = TRUE, .sleepTalkBanned = TRUE, .instructBanned = TRUE, - .assistBanned = TRUE, + .assistBanned = B_UPDATED_MOVE_FLAGS >= GEN_6, .skyBattleBanned = TRUE, .argument.twoTurnAttack = { .stringId = STRINGID_PKMNHIDUNDERWATER, .status = STATE_UNDERWATER }, .contestEffect = CONTEST_EFFECT_AVOID_STARTLE_ONCE, @@ -7635,7 +7715,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, .makesContact = TRUE, - .contestEffect = CONTEST_EFFECT_STARTLE_MON_WITH_JUDGES_ATTENTION, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_QUALITY_DEPENDS_ON_TIMING : CONTEST_EFFECT_STARTLE_MON_WITH_JUDGES_ATTENTION, .contestCategory = CONTEST_CATEGORY_TOUGH, .contestComboStarterId = 0, .contestComboMoves = {COMBO_STARTER_FAKE_OUT, COMBO_STARTER_FOCUS_ENERGY}, @@ -7651,7 +7731,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .effect = EFFECT_CAMOUFLAGE, .power = 0, .type = TYPE_NORMAL, - .accuracy = 100, + .accuracy = 0, .pp = 20, .target = MOVE_TARGET_USER, .priority = 0, @@ -7660,7 +7740,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .snatchAffected = TRUE, .ignoresProtect = TRUE, .mirrorMoveBanned = TRUE, - .contestEffect = CONTEST_EFFECT_AFFECTED_BY_PREV_APPEAL, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_APPEAL_AS_GOOD_AS_PREV_ONES : CONTEST_EFFECT_AFFECTED_BY_PREV_APPEAL, .contestCategory = CONTEST_CATEGORY_SMART, .contestComboStarterId = 0, .contestComboMoves = {0}, @@ -7712,7 +7792,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .moveEffect = MOVE_EFFECT_SP_DEF_MINUS_1, .chance = 50, }), - .contestEffect = CONTEST_EFFECT_STARTLE_PREV_MON, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_STARTLE_MONS_SAME_TYPE_APPEAL : CONTEST_EFFECT_STARTLE_PREV_MON, .contestCategory = CONTEST_CATEGORY_SMART, .contestComboStarterId = 0, .contestComboMoves = {COMBO_STARTER_CALM_MIND}, @@ -7739,7 +7819,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .moveEffect = MOVE_EFFECT_SP_ATK_MINUS_1, .chance = 50, }), - .contestEffect = CONTEST_EFFECT_BADLY_STARTLE_FRONT_MON, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_BADLY_STARTLE_MONS_WITH_GOOD_APPEALS : CONTEST_EFFECT_BADLY_STARTLE_FRONT_MON, .contestCategory = CONTEST_CATEGORY_SMART, .contestComboStarterId = 0, .contestComboMoves = {COMBO_STARTER_CALM_MIND}, @@ -7807,7 +7887,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .power = 85, .type = TYPE_FIRE, .accuracy = 90, - .criticalHitStage = 1, + .criticalHitStage = B_UPDATED_MOVE_DATA >= GEN_3 ? 1 : 2, .pp = 10, .target = MOVE_TARGET_SELECTED, .priority = 0, @@ -7817,10 +7897,10 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .moveEffect = MOVE_EFFECT_BURN, .chance = 10, }), - .contestEffect = CONTEST_EFFECT_HIGHLY_APPEALING, - .contestCategory = CONTEST_CATEGORY_BEAUTY, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_REPETITION_NOT_BORING : CONTEST_EFFECT_HIGHLY_APPEALING, + .contestCategory = C_UPDATED_MOVE_CATEGORIES >= GEN_6 ? CONTEST_CATEGORY_COOL : CONTEST_CATEGORY_BEAUTY, .contestComboStarterId = 0, - .contestComboMoves = {COMBO_STARTER_SUNNY_DAY}, + .contestComboMoves = {COMBO_STARTER_SUNNY_DAY, COMBO_STARTER_FOCUS_ENERGY}, .battleAnimScript = gBattleAnimMove_BlazeKick, .validApprenticeMove = TRUE, }, @@ -7834,7 +7914,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .effect = EFFECT_MUD_SPORT, .power = 0, .type = TYPE_GROUND, - .accuracy = 100, + .accuracy = 0, .pp = 15, .target = MOVE_TARGET_ALL_BATTLERS, .priority = 0, @@ -7843,7 +7923,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .ignoresProtect = TRUE, .mirrorMoveBanned = TRUE, .skyBattleBanned = TRUE, - .contestEffect = CONTEST_EFFECT_HIGHLY_APPEALING, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_EXCITE_AUDIENCE_IN_ANY_CONTEST : CONTEST_EFFECT_HIGHLY_APPEALING, .contestCategory = CONTEST_CATEGORY_CUTE, .contestComboStarterId = COMBO_STARTER_MUD_SPORT, .contestComboMoves = {COMBO_STARTER_MUD_SLAP, COMBO_STARTER_SANDSTORM, COMBO_STARTER_WATER_SPORT}, @@ -7872,7 +7952,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .contestEffect = CONTEST_EFFECT_DONT_EXCITE_AUDIENCE, .contestCategory = CONTEST_CATEGORY_BEAUTY, .contestComboStarterId = 0, - .contestComboMoves = {COMBO_STARTER_HAIL}, + .contestComboMoves = {COMBO_STARTER_HAIL, COMBO_STARTER_DEFENSE_CURL}, .battleAnimScript = gBattleAnimMove_IceBall, }, @@ -7896,7 +7976,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .moveEffect = MOVE_EFFECT_FLINCH, .chance = 30, }), - .contestEffect = CONTEST_EFFECT_BADLY_STARTLE_FRONT_MON, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_HIGHLY_APPEALING : CONTEST_EFFECT_BADLY_STARTLE_FRONT_MON, .contestCategory = CONTEST_CATEGORY_SMART, .contestComboStarterId = 0, .contestComboMoves = {0}, @@ -7913,7 +7993,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .effect = EFFECT_RESTORE_HP, .power = 0, .type = TYPE_NORMAL, - .accuracy = 100, + .accuracy = 0, .pp = B_UPDATED_MOVE_DATA >= GEN_9 ? 5 : 10, .target = MOVE_TARGET_USER, .priority = 0, @@ -7923,7 +8003,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .snatchAffected = TRUE, .ignoresProtect = TRUE, .mirrorMoveBanned = TRUE, - .contestEffect = CONTEST_EFFECT_BETTER_WHEN_LATER, + .contestEffect = CONTEST_EFFECT_BETTER_WHEN_LATER, //C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_QUICKLY_GROW_BORED : .contestCategory = CONTEST_CATEGORY_CUTE, .contestComboStarterId = 0, .contestComboMoves = {0}, @@ -7947,7 +8027,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .category = DAMAGE_CATEGORY_SPECIAL, .soundMove = TRUE, .ignoresSubstitute = B_UPDATED_MOVE_FLAGS >= GEN_6, - .contestEffect = CONTEST_EFFECT_BADLY_STARTLE_PREV_MONS, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_STARTLE_PREV_MONS : CONTEST_EFFECT_BADLY_STARTLE_PREV_MONS, .contestCategory = CONTEST_CATEGORY_COOL, .contestComboStarterId = 0, .contestComboMoves = {0}, @@ -7975,7 +8055,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .moveEffect = MOVE_EFFECT_TOXIC, .chance = B_UPDATED_MOVE_DATA >= GEN_6 ? 50 : 30, }), - .contestEffect = CONTEST_EFFECT_WORSEN_CONDITION_OF_PREV_MONS, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_HIGHLY_APPEALING : CONTEST_EFFECT_WORSEN_CONDITION_OF_PREV_MONS, .contestCategory = CONTEST_CATEGORY_SMART, .contestComboStarterId = 0, .contestComboMoves = {0}, @@ -8082,7 +8162,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .self = TRUE, .chance = 20, }), - .contestEffect = CONTEST_EFFECT_BETTER_IF_SAME_TYPE, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_REPETITION_NOT_BORING : CONTEST_EFFECT_BETTER_IF_SAME_TYPE, .contestCategory = CONTEST_CATEGORY_COOL, .contestComboStarterId = 0, .contestComboMoves = {0}, @@ -8111,7 +8191,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .chance = 30, }), .contestEffect = CONTEST_EFFECT_STARTLE_PREV_MON, - .contestCategory = CONTEST_CATEGORY_SMART, + .contestCategory = C_UPDATED_MOVE_CATEGORIES >= GEN_6 ? CONTEST_CATEGORY_CUTE : CONTEST_CATEGORY_SMART, .contestComboStarterId = 0, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_Astonish, @@ -8134,8 +8214,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .category = DAMAGE_CATEGORY_SPECIAL, .zMove = { .powerOverride = 160 }, .ballisticMove = TRUE, - .contestEffect = CONTEST_EFFECT_HIGHLY_APPEALING, - .contestCategory = CONTEST_CATEGORY_SMART, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_REPETITION_NOT_BORING : CONTEST_EFFECT_HIGHLY_APPEALING, + .contestCategory = C_UPDATED_MOVE_CATEGORIES >= GEN_6 ? CONTEST_CATEGORY_BEAUTY : CONTEST_CATEGORY_SMART, .contestComboStarterId = 0, .contestComboMoves = {COMBO_STARTER_HAIL, COMBO_STARTER_RAIN_DANCE, COMBO_STARTER_SANDSTORM, COMBO_STARTER_SUNNY_DAY}, .battleAnimScript = gBattleAnimMove_WeatherBall, @@ -8159,8 +8239,9 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .zMove = { .effect = Z_EFFECT_RECOVER_HP }, .snatchAffected = TRUE, .ignoresProtect = TRUE, + .ignoresSubstitute = B_UPDATED_MOVE_FLAGS < GEN_6, .mirrorMoveBanned = TRUE, - .contestEffect = CONTEST_EFFECT_BETTER_IF_LAST, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_AVOID_STARTLE : CONTEST_EFFECT_BETTER_IF_LAST, .contestCategory = CONTEST_CATEGORY_SMART, .contestComboStarterId = 0, .contestComboMoves = {0}, @@ -8184,8 +8265,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .category = DAMAGE_CATEGORY_STATUS, .zMove = { .effect = Z_EFFECT_SPATK_UP_1 }, .magicCoatAffected = TRUE, - .contestEffect = CONTEST_EFFECT_BETTER_IF_LAST, - .contestCategory = CONTEST_CATEGORY_SMART, + .contestEffect = CONTEST_EFFECT_BETTER_IF_LAST, //C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_QUICKLY_GROW_BORED : + .contestCategory = C_UPDATED_MOVE_CATEGORIES >= GEN_6 ? CONTEST_CATEGORY_CUTE : CONTEST_CATEGORY_SMART, .contestComboStarterId = 0, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_FakeTears, @@ -8202,14 +8283,14 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .power = B_UPDATED_MOVE_DATA >= GEN_6 ? 60 : 55, .type = TYPE_FLYING, .accuracy = 95, - .criticalHitStage = 1, + .criticalHitStage = B_UPDATED_MOVE_DATA >= GEN_3 ? 1 : 2, .pp = 25, .target = MOVE_TARGET_BOTH, .priority = 0, .category = DAMAGE_CATEGORY_SPECIAL, .windMove = TRUE, .slicingMove = TRUE, - .contestEffect = CONTEST_EFFECT_STARTLE_MONS_SAME_TYPE_APPEAL, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_HIGHLY_APPEALING : CONTEST_EFFECT_STARTLE_MONS_SAME_TYPE_APPEAL, .contestCategory = CONTEST_CATEGORY_COOL, .contestComboStarterId = 0, .contestComboMoves = {0}, @@ -8261,7 +8342,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .zMove = { .effect = Z_EFFECT_ATK_UP_1 }, .ignoresSubstitute = TRUE, .magicCoatAffected = B_UPDATED_MOVE_FLAGS >= GEN_5, - .contestEffect = CONTEST_EFFECT_WORSEN_CONDITION_OF_PREV_MONS, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_AVOID_STARTLE_ONCE : CONTEST_EFFECT_WORSEN_CONDITION_OF_PREV_MONS, .contestCategory = CONTEST_CATEGORY_SMART, .contestComboStarterId = 0, .contestComboMoves = {0}, @@ -8287,7 +8368,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .moveEffect = MOVE_EFFECT_SPD_MINUS_1, .chance = 100, }), - .contestEffect = CONTEST_EFFECT_DONT_EXCITE_AUDIENCE, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_SHIFT_JUDGE_ATTENTION : CONTEST_EFFECT_DONT_EXCITE_AUDIENCE, .contestCategory = CONTEST_CATEGORY_SMART, .contestComboStarterId = 0, .contestComboMoves = {COMBO_STARTER_ROCK_THROW}, @@ -8368,9 +8449,9 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .ignoresSubstitute = B_UPDATED_MOVE_FLAGS >= GEN_6, .magicCoatAffected = TRUE, .soundMove = TRUE, - .contestEffect = CONTEST_EFFECT_BADLY_STARTLE_PREV_MONS, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_AVOID_STARTLE_ONCE : CONTEST_EFFECT_BADLY_STARTLE_PREV_MONS, .contestCategory = CONTEST_CATEGORY_SMART, - .contestComboStarterId = 0, + .contestComboStarterId = COMBO_STARTER_GRASS_WHISTLE, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_GrassWhistle, .validApprenticeMove = TRUE, @@ -8391,6 +8472,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .priority = 0, .category = DAMAGE_CATEGORY_STATUS, .zMove = { .effect = Z_EFFECT_DEF_UP_1 }, + .ignoresSubstitute = B_UPDATED_MOVE_FLAGS < GEN_4, .magicCoatAffected = TRUE, .contestEffect = CONTEST_EFFECT_WORSEN_CONDITION_OF_PREV_MONS, .contestCategory = CONTEST_CATEGORY_CUTE, @@ -8419,7 +8501,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .ignoresProtect = TRUE, .mirrorMoveBanned = TRUE, .contestEffect = CONTEST_EFFECT_IMPROVE_CONDITION_PREVENT_NERVOUSNESS, - .contestCategory = CONTEST_CATEGORY_COOL, + .contestCategory = C_UPDATED_MOVE_CATEGORIES >= GEN_6 ? CONTEST_CATEGORY_BEAUTY : CONTEST_CATEGORY_COOL, .contestComboStarterId = 0, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_CosmicPower, @@ -8440,7 +8522,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .target = MOVE_TARGET_BOTH, .priority = 0, .category = DAMAGE_CATEGORY_SPECIAL, - .contestEffect = CONTEST_EFFECT_BETTER_WHEN_LATER, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_USER_MORE_EASILY_STARTLED : CONTEST_EFFECT_BETTER_WHEN_LATER, .contestCategory = CONTEST_CATEGORY_BEAUTY, .contestComboStarterId = 0, .contestComboMoves = {COMBO_STARTER_RAIN_DANCE}, @@ -8466,7 +8548,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .moveEffect = MOVE_EFFECT_CONFUSION, .chance = 10, }), - .contestEffect = CONTEST_EFFECT_SCRAMBLE_NEXT_TURN_ORDER, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_SHIFT_JUDGE_ATTENTION : CONTEST_EFFECT_SCRAMBLE_NEXT_TURN_ORDER, .contestCategory = CONTEST_CATEGORY_BEAUTY, .contestComboStarterId = 0, .contestComboMoves = {0}, @@ -8517,7 +8599,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .moveEffect = MOVE_EFFECT_FLINCH, .chance = 10, }), - .contestEffect = CONTEST_EFFECT_BADLY_STARTLE_FRONT_MON, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_STARTLE_MONS_SAME_TYPE_APPEAL : CONTEST_EFFECT_BADLY_STARTLE_FRONT_MON, .contestCategory = CONTEST_CATEGORY_COOL, .contestComboStarterId = 0, .contestComboMoves = {0}, @@ -8617,7 +8699,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .moveEffect = MOVE_EFFECT_ACC_MINUS_1, .chance = 30, }), - .contestEffect = CONTEST_EFFECT_STARTLE_MON_WITH_JUDGES_ATTENTION, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_STARTLE_PREV_MONS : CONTEST_EFFECT_STARTLE_MON_WITH_JUDGES_ATTENTION, .contestCategory = CONTEST_CATEGORY_TOUGH, .contestComboStarterId = 0, .contestComboMoves = {COMBO_STARTER_RAIN_DANCE}, @@ -8640,10 +8722,10 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, .ballisticMove = TRUE, - .contestEffect = CONTEST_EFFECT_BADLY_STARTLE_MONS_WITH_GOOD_APPEALS, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_QUALITY_DEPENDS_ON_TIMING : CONTEST_EFFECT_BADLY_STARTLE_MONS_WITH_GOOD_APPEALS, .contestCategory = CONTEST_CATEGORY_COOL, .contestComboStarterId = 0, - .contestComboMoves = {COMBO_STARTER_GROWTH}, + .contestComboMoves = {COMBO_STARTER_GROWTH, COMBO_STARTER_ROTOTILLER}, .battleAnimScript = gBattleAnimMove_BulletSeed, }, @@ -8685,7 +8767,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .target = MOVE_TARGET_SELECTED, .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, - .contestEffect = CONTEST_EFFECT_STARTLE_MONS_SAME_TYPE_APPEAL, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_QUALITY_DEPENDS_ON_TIMING : CONTEST_EFFECT_STARTLE_MONS_SAME_TYPE_APPEAL, .contestCategory = CONTEST_CATEGORY_BEAUTY, .contestComboStarterId = 0, .contestComboMoves = {0}, @@ -8733,11 +8815,11 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .priority = 0, .category = DAMAGE_CATEGORY_STATUS, .zMove = { .effect = Z_EFFECT_DEF_UP_1 }, - .ignoresProtect = (B_UPDATED_MOVE_FLAGS >= GEN_6) || (B_UPDATED_MOVE_FLAGS <= GEN_3), + .ignoresProtect = B_UPDATED_MOVE_FLAGS >= GEN_6, .magicCoatAffected = TRUE, .contestEffect = CONTEST_EFFECT_MAKE_FOLLOWING_MONS_NERVOUS, .contestCategory = CONTEST_CATEGORY_CUTE, - .contestComboStarterId = 0, + .contestComboStarterId = COMBO_STARTER_BLOCK, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_Block, .validApprenticeMove = TRUE, @@ -8762,7 +8844,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .ignoresProtect = TRUE, .mirrorMoveBanned = TRUE, .soundMove = B_UPDATED_MOVE_FLAGS >= GEN_8, - .contestEffect = CONTEST_EFFECT_IMPROVE_CONDITION_PREVENT_NERVOUSNESS, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_BETTER_IF_LAST : CONTEST_EFFECT_IMPROVE_CONDITION_PREVENT_NERVOUSNESS, .contestCategory = CONTEST_CATEGORY_COOL, .contestComboStarterId = 0, .contestComboMoves = {0}, @@ -8785,7 +8867,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, .makesContact = TRUE, - .contestEffect = CONTEST_EFFECT_STARTLE_MONS_SAME_TYPE_APPEAL, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_HIGHLY_APPEALING : CONTEST_EFFECT_STARTLE_MONS_SAME_TYPE_APPEAL, .contestCategory = CONTEST_CATEGORY_COOL, .contestComboStarterId = 0, .contestComboMoves = {COMBO_STARTER_DRAGON_BREATH, COMBO_STARTER_DRAGON_DANCE, COMBO_STARTER_DRAGON_RAGE, COMBO_STARTER_DRAGON_RUSH, COMBO_STARTER_DRAGON_TAIL}, @@ -8839,7 +8921,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .ignoresProtect = TRUE, .mirrorMoveBanned = TRUE, .contestEffect = CONTEST_EFFECT_IMPROVE_CONDITION_PREVENT_NERVOUSNESS, - .contestCategory = CONTEST_CATEGORY_BEAUTY, + .contestCategory = C_UPDATED_MOVE_CATEGORIES >= GEN_6 ? CONTEST_CATEGORY_COOL : CONTEST_CATEGORY_BEAUTY, .contestComboStarterId = 0, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_BulkUp, @@ -8864,7 +8946,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .gravityBanned = TRUE, .sleepTalkBanned = TRUE, .instructBanned = TRUE, - .assistBanned = TRUE, + .assistBanned = B_UPDATED_MOVE_FLAGS >= GEN_6, .argument.twoTurnAttack = { .stringId = STRINGID_PKMNSPRANGUP, .status = STATE_ON_AIR }, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_PARALYSIS, @@ -8896,7 +8978,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .moveEffect = MOVE_EFFECT_SPD_MINUS_1, .chance = 100, }), - .contestEffect = CONTEST_EFFECT_BADLY_STARTLE_PREV_MONS, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_HIGHLY_APPEALING : CONTEST_EFFECT_BADLY_STARTLE_PREV_MONS, .contestCategory = CONTEST_CATEGORY_TOUGH, .contestComboStarterId = 0, .contestComboMoves = {COMBO_STARTER_SANDSTORM}, @@ -8913,7 +8995,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .power = 50, .type = TYPE_POISON, .accuracy = 100, - .criticalHitStage = 1, + .criticalHitStage = B_UPDATED_MOVE_DATA >= GEN_3 ? 1 : 2, .pp = 25, .target = MOVE_TARGET_SELECTED, .priority = 0, @@ -8926,7 +9008,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .contestEffect = CONTEST_EFFECT_WORSEN_CONDITION_OF_PREV_MONS, .contestCategory = CONTEST_CATEGORY_SMART, .contestComboStarterId = 0, - .contestComboMoves = {0}, + .contestComboMoves = {COMBO_STARTER_FOCUS_ENERGY}, .battleAnimScript = gBattleAnimMove_PoisonTail, .validApprenticeMove = TRUE, }, @@ -8952,7 +9034,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .assistBanned = TRUE, .contestEffect = CONTEST_EFFECT_APPEAL_AS_GOOD_AS_PREV_ONES, .contestCategory = CONTEST_CATEGORY_CUTE, - .contestComboStarterId = 0, + .contestComboStarterId = COMBO_STARTER_COVET, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_Covet, .validApprenticeMove = TRUE, @@ -8982,7 +9064,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = #endif .contestEffect = CONTEST_EFFECT_USER_MORE_EASILY_STARTLED, .contestCategory = CONTEST_CATEGORY_COOL, - .contestComboStarterId = 0, + .contestComboStarterId = COMBO_STARTER_CHARGE, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_VoltTackle, .validApprenticeMove = TRUE, @@ -9019,7 +9101,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .effect = EFFECT_WATER_SPORT, .power = 0, .type = TYPE_WATER, - .accuracy = 100, + .accuracy = 0, .pp = 15, .target = MOVE_TARGET_ALL_BATTLERS, .priority = 0, @@ -9028,7 +9110,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .ignoresProtect = TRUE, .mirrorMoveBanned = TRUE, .skyBattleBanned = TRUE, - .contestEffect = CONTEST_EFFECT_HIGHLY_APPEALING, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_EXCITE_AUDIENCE_IN_ANY_CONTEST : CONTEST_EFFECT_HIGHLY_APPEALING, .contestCategory = CONTEST_CATEGORY_CUTE, .contestComboStarterId = COMBO_STARTER_WATER_SPORT, .contestComboMoves = {COMBO_STARTER_MUD_SPORT, COMBO_STARTER_RAIN_DANCE}, @@ -9054,7 +9136,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .snatchAffected = TRUE, .ignoresProtect = TRUE, .mirrorMoveBanned = TRUE, - .contestEffect = CONTEST_EFFECT_AVOID_STARTLE_ONCE, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_IMPROVE_CONDITION_PREVENT_NERVOUSNESS : CONTEST_EFFECT_AVOID_STARTLE_ONCE, .contestCategory = CONTEST_CATEGORY_SMART, .contestComboStarterId = COMBO_STARTER_CALM_MIND, .contestComboMoves = {0}, @@ -9072,14 +9154,14 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .power = B_UPDATED_MOVE_DATA >= GEN_4 ? 90 : 70, .type = TYPE_GRASS, .accuracy = 100, - .criticalHitStage = 1, + .criticalHitStage = B_UPDATED_MOVE_DATA >= GEN_3 ? 1 : 2, .pp = 15, .target = MOVE_TARGET_SELECTED, .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, .makesContact = TRUE, .slicingMove = TRUE, - .contestEffect = CONTEST_EFFECT_AFFECTED_BY_PREV_APPEAL, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_REPETITION_NOT_BORING : CONTEST_EFFECT_AFFECTED_BY_PREV_APPEAL, .contestCategory = CONTEST_CATEGORY_COOL, .contestComboStarterId = 0, .contestComboMoves = {0}, @@ -9129,7 +9211,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, .ballisticMove = B_UPDATED_MOVE_FLAGS >= GEN_6, - .contestEffect = CONTEST_EFFECT_BETTER_IF_SAME_TYPE, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_QUALITY_DEPENDS_ON_TIMING : CONTEST_EFFECT_BETTER_IF_SAME_TYPE, .contestCategory = CONTEST_CATEGORY_TOUGH, .contestComboStarterId = 0, .contestComboMoves = {0}, @@ -9177,7 +9259,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .moveEffect = MOVE_EFFECT_CONFUSION, .chance = 20, }), - .contestEffect = CONTEST_EFFECT_SCRAMBLE_NEXT_TURN_ORDER, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_SHIFT_JUDGE_ATTENTION : CONTEST_EFFECT_SCRAMBLE_NEXT_TURN_ORDER, .contestCategory = CONTEST_CATEGORY_BEAUTY, .contestComboStarterId = 0, .contestComboMoves = {COMBO_STARTER_RAIN_DANCE}, @@ -9201,8 +9283,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .category = DAMAGE_CATEGORY_SPECIAL, .ignoresProtect = TRUE, .mirrorMoveBanned = TRUE, - .contestEffect = CONTEST_EFFECT_DONT_EXCITE_AUDIENCE, - .contestCategory = CONTEST_CATEGORY_COOL, + .contestEffect = CONTEST_EFFECT_DONT_EXCITE_AUDIENCE, //C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_EXCITES_AUDIENCE_MORE_IF_LAST : + .contestCategory = C_UPDATED_MOVE_CATEGORIES >= GEN_6 ? CONTEST_CATEGORY_BEAUTY : CONTEST_CATEGORY_COOL, .contestComboStarterId = 0, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_DoomDesire, @@ -9254,8 +9336,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .snatchAffected = TRUE, .ignoresProtect = TRUE, .mirrorMoveBanned = TRUE, - .contestEffect = CONTEST_EFFECT_HIGHLY_APPEALING, - .contestCategory = CONTEST_CATEGORY_COOL, + .contestEffect = CONTEST_EFFECT_HIGHLY_APPEALING, //CONTEST_EFFECT_QUICKLY_GROW_BORED + .contestCategory = C_UPDATED_MOVE_CATEGORIES >= GEN_6 ? CONTEST_CATEGORY_SMART : CONTEST_CATEGORY_COOL, .contestComboStarterId = 0, .contestComboMoves = {COMBO_STARTER_BRAVE_BIRD}, .battleAnimScript = gBattleAnimMove_Roost, @@ -9279,8 +9361,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .ignoresProtect = TRUE, .mirrorMoveBanned = TRUE, .skyBattleBanned = TRUE, - .contestEffect = CONTEST_EFFECT_STARTLE_PREV_MONS, - .contestCategory = CONTEST_CATEGORY_BEAUTY, + .contestEffect = CONTEST_EFFECT_MAKE_FOLLOWING_MONS_NERVOUS, + .contestCategory = C_UPDATED_MOVE_CATEGORIES >= GEN_6 ? CONTEST_CATEGORY_SMART : CONTEST_CATEGORY_BEAUTY, .contestComboStarterId = 0, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_Gravity, @@ -9303,8 +9385,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .zMove = { .effect = Z_EFFECT_SPATK_UP_1 }, .ignoresSubstitute = TRUE, .magicCoatAffected = B_UPDATED_MOVE_FLAGS >= GEN_5, - .contestEffect = CONTEST_EFFECT_WORSEN_CONDITION_OF_PREV_MONS, - .contestCategory = CONTEST_CATEGORY_CUTE, + .contestEffect = CONTEST_EFFECT_BETTER_IF_FIRST, + .contestCategory = C_UPDATED_MOVE_CATEGORIES >= GEN_6 ? CONTEST_CATEGORY_SMART : CONTEST_CATEGORY_CUTE, .contestComboStarterId = 0, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_MiracleEye, @@ -9329,10 +9411,10 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_REMOVE_STATUS, }), - .contestEffect = CONTEST_EFFECT_STARTLE_PREV_MON, - .contestCategory = CONTEST_CATEGORY_SMART, + .contestEffect = CONTEST_EFFECT_APPEAL_AS_GOOD_AS_PREV_ONE, + .contestCategory = C_UPDATED_MOVE_CATEGORIES >= GEN_6 ? CONTEST_CATEGORY_TOUGH : CONTEST_CATEGORY_SMART, .contestComboStarterId = 0, - .contestComboMoves = {0}, + .contestComboMoves = {COMBO_STARTER_LOVELY_KISS, COMBO_STARTER_SPORE, COMBO_STARTER_ENTRAINMENT, COMBO_STARTER_PLAY_NICE, COMBO_STARTER_SING, COMBO_STARTER_YAWN, COMBO_STARTER_HYPNOSIS, COMBO_STARTER_DARK_VOID, COMBO_STARTER_GRASS_WHISTLE, COMBO_STARTER_SLEEP_POWDER}, .battleAnimScript = gBattleAnimMove_WakeUpSlap, }, @@ -9356,8 +9438,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .moveEffect = MOVE_EFFECT_SPD_MINUS_1, .self = TRUE, }), - .contestEffect = CONTEST_EFFECT_BADLY_STARTLE_PREV_MONS, - .contestCategory = CONTEST_CATEGORY_COOL, + .contestEffect = CONTEST_EFFECT_USER_MORE_EASILY_STARTLED, + .contestCategory = C_UPDATED_MOVE_CATEGORIES >= GEN_6 ? CONTEST_CATEGORY_TOUGH : CONTEST_CATEGORY_COOL, .contestComboStarterId = 0, .contestComboMoves = {COMBO_STARTER_FOCUS_ENERGY}, .battleAnimScript = gBattleAnimMove_HammerArm, @@ -9379,8 +9461,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .category = DAMAGE_CATEGORY_PHYSICAL, .makesContact = TRUE, .ballisticMove = TRUE, - .contestEffect = CONTEST_EFFECT_BETTER_IF_LAST, - .contestCategory = CONTEST_CATEGORY_BEAUTY, + .contestEffect = CONTEST_EFFECT_BETTER_WHEN_LATER, + .contestCategory = C_UPDATED_MOVE_CATEGORIES >= GEN_6 ? CONTEST_CATEGORY_COOL : CONTEST_CATEGORY_BEAUTY, .contestComboStarterId = 0, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_GyroBall, @@ -9403,7 +9485,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .ignoresProtect = TRUE, .mirrorMoveBanned = TRUE, .contestEffect = CONTEST_EFFECT_GREAT_APPEAL_BUT_NO_MORE_MOVES, - .contestCategory = CONTEST_CATEGORY_CUTE, + .contestCategory = C_UPDATED_MOVE_CATEGORIES >= GEN_6 ? CONTEST_CATEGORY_BEAUTY : CONTEST_CATEGORY_CUTE, .contestComboStarterId = 0, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_HealingWish, @@ -9423,8 +9505,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .target = MOVE_TARGET_SELECTED, .priority = 0, .category = DAMAGE_CATEGORY_SPECIAL, - .contestEffect = CONTEST_EFFECT_BETTER_IF_SAME_TYPE, - .contestCategory = CONTEST_CATEGORY_SMART, + .contestEffect = CONTEST_EFFECT_APPEAL_AS_GOOD_AS_PREV_ONE, + .contestCategory = C_UPDATED_MOVE_CATEGORIES >= GEN_6 ? CONTEST_CATEGORY_TOUGH : CONTEST_CATEGORY_SMART, .contestComboStarterId = 0, .contestComboMoves = {COMBO_STARTER_RAIN_DANCE}, .battleAnimScript = gBattleAnimMove_Brine, @@ -9444,8 +9526,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .target = MOVE_TARGET_SELECTED, .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, - .contestEffect = CONTEST_EFFECT_BETTER_WHEN_LATER, - .contestCategory = CONTEST_CATEGORY_COOL, + .contestEffect = CONTEST_EFFECT_BETTER_WHEN_AUDIENCE_EXCITED, + .contestCategory = C_UPDATED_MOVE_CATEGORIES >= GEN_6 ? CONTEST_CATEGORY_SMART : CONTEST_CATEGORY_COOL, .contestComboStarterId = 0, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_NaturalGift, @@ -9471,8 +9553,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_FEINT, }), - .contestEffect = CONTEST_EFFECT_WORSEN_CONDITION_OF_PREV_MONS, - .contestCategory = CONTEST_CATEGORY_BEAUTY, + .contestEffect = CONTEST_EFFECT_NEXT_APPEAL_EARLIER, + .contestCategory = C_UPDATED_MOVE_CATEGORIES >= GEN_6 ? CONTEST_CATEGORY_SMART : CONTEST_CATEGORY_BEAUTY, .contestComboStarterId = 0, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_Feint, @@ -9494,7 +9576,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_BUG_BITE, }), - .contestEffect = CONTEST_EFFECT_AFFECTED_BY_PREV_APPEAL, + .contestEffect = CONTEST_EFFECT_WORSEN_CONDITION_OF_PREV_MONS, .contestCategory = CONTEST_CATEGORY_CUTE, .contestComboStarterId = 0, .contestComboMoves = {0}, @@ -9521,7 +9603,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .ignoresProtect = TRUE, .mirrorMoveBanned = TRUE, .contestEffect = CONTEST_EFFECT_NEXT_APPEAL_EARLIER, - .contestCategory = CONTEST_CATEGORY_SMART, + .contestCategory = C_UPDATED_MOVE_CATEGORIES >= GEN_6 ? CONTEST_CATEGORY_COOL : CONTEST_CATEGORY_SMART, .contestComboStarterId = 0, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_Tailwind, @@ -9545,8 +9627,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .ignoresProtect = TRUE, .mirrorMoveBanned = TRUE, .snatchAffected = B_UPDATED_MOVE_FLAGS < GEN_5, - .contestEffect = CONTEST_EFFECT_IMPROVE_CONDITION_PREVENT_NERVOUSNESS, - .contestCategory = CONTEST_CATEGORY_COOL, + .contestEffect = CONTEST_EFFECT_QUALITY_DEPENDS_ON_TIMING, + .contestCategory = C_UPDATED_MOVE_CATEGORIES >= GEN_6 ? CONTEST_CATEGORY_TOUGH : CONTEST_CATEGORY_COOL, .contestComboStarterId = 0, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_Acupressure, @@ -9566,11 +9648,12 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .target = MOVE_TARGET_DEPENDS, .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, + .ignoresProtect = B_UPDATED_MOVE_FLAGS < GEN_5, .meFirstBanned = TRUE, - .contestEffect = CONTEST_EFFECT_AVOID_STARTLE_ONCE, - .contestCategory = CONTEST_CATEGORY_BEAUTY, + .contestEffect = CONTEST_EFFECT_BETTER_IF_LAST, + .contestCategory = C_UPDATED_MOVE_CATEGORIES >= GEN_6 ? CONTEST_CATEGORY_COOL : CONTEST_CATEGORY_BEAUTY, .contestComboStarterId = 0, - .contestComboMoves = {COMBO_STARTER_METAL_SOUND}, + .contestComboMoves = {COMBO_STARTER_METAL_SOUND, COMBO_STARTER_ENCORE, COMBO_STARTER_TAUNT, COMBO_STARTER_TORMENT}, .battleAnimScript = gBattleAnimMove_MetalBurst, }, @@ -9587,7 +9670,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, .makesContact = TRUE, - .contestEffect = CONTEST_EFFECT_AVOID_STARTLE, + .contestEffect = CONTEST_EFFECT_AVOID_STARTLE, //CONTEST_EFFECT_QUICKLY_GROW_BORED .contestCategory = CONTEST_CATEGORY_CUTE, .contestComboStarterId = 0, .contestComboMoves = {0}, @@ -9612,7 +9695,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .self = TRUE, }), .contestEffect = CONTEST_EFFECT_USER_MORE_EASILY_STARTLED, - .contestCategory = CONTEST_CATEGORY_SMART, + .contestCategory = C_UPDATED_MOVE_CATEGORIES >= GEN_6 ? CONTEST_CATEGORY_TOUGH : CONTEST_CATEGORY_SMART, .contestComboStarterId = 0, .contestComboMoves = {COMBO_STARTER_FOCUS_ENERGY, COMBO_STARTER_MIND_READER}, .battleAnimScript = gBattleAnimMove_CloseCombat, @@ -9633,8 +9716,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, .makesContact = TRUE, - .contestEffect = CONTEST_EFFECT_BADLY_STARTLE_MONS_WITH_GOOD_APPEALS, - .contestCategory = CONTEST_CATEGORY_COOL, + .contestEffect = CONTEST_EFFECT_BETTER_IF_LAST, + .contestCategory = C_UPDATED_MOVE_CATEGORIES >= GEN_6 ? CONTEST_CATEGORY_TOUGH : CONTEST_CATEGORY_COOL, .contestComboStarterId = COMBO_STARTER_PAYBACK, .contestComboMoves = {COMBO_STARTER_REVENGE}, .battleAnimScript = gBattleAnimMove_Payback, @@ -9655,8 +9738,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, .makesContact = TRUE, - .contestEffect = CONTEST_EFFECT_BETTER_IF_LAST, - .contestCategory = CONTEST_CATEGORY_BEAUTY, + .contestEffect = CONTEST_EFFECT_NEXT_APPEAL_LATER, + .contestCategory = C_UPDATED_MOVE_CATEGORIES >= GEN_6 ? CONTEST_CATEGORY_SMART : CONTEST_CATEGORY_BEAUTY, .contestComboStarterId = 0, .contestComboMoves = {COMBO_STARTER_PAYBACK, COMBO_STARTER_REVENGE}, .battleAnimScript = gBattleAnimMove_Assurance, @@ -9678,8 +9761,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .category = DAMAGE_CATEGORY_STATUS, .zMove = { .effect = Z_EFFECT_SPATK_UP_1 }, .magicCoatAffected = B_UPDATED_MOVE_FLAGS >= GEN_5, - .contestEffect = CONTEST_EFFECT_MAKE_FOLLOWING_MONS_NERVOUS, - .contestCategory = CONTEST_CATEGORY_CUTE, + .contestEffect = CONTEST_EFFECT_WORSEN_CONDITION_OF_PREV_MONS, + .contestCategory = C_UPDATED_MOVE_CATEGORIES >= GEN_6 ? CONTEST_CATEGORY_SMART : CONTEST_CATEGORY_CUTE, .contestComboStarterId = 0, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_Embargo, @@ -9700,10 +9783,10 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, .parentalBondBanned = TRUE, - .contestEffect = CONTEST_EFFECT_MAKE_FOLLOWING_MONS_NERVOUS, - .contestCategory = CONTEST_CATEGORY_TOUGH, + .contestEffect = CONTEST_EFFECT_WORSEN_CONDITION_OF_PREV_MONS, + .contestCategory = C_UPDATED_MOVE_CATEGORIES >= GEN_6 ? CONTEST_CATEGORY_CUTE : CONTEST_CATEGORY_TOUGH, .contestComboStarterId = 0, - .contestComboMoves = {0}, + .contestComboMoves = {COMBO_STARTER_CELEBRATE, COMBO_STARTER_COVET, COMBO_STARTER_HAPPY_HOUR, COMBO_STARTER_WISH}, .battleAnimScript = gBattleAnimMove_Fling, }, @@ -9722,8 +9805,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .priority = 0, .category = DAMAGE_CATEGORY_STATUS, .zMove = { .effect = Z_EFFECT_SPATK_UP_2 }, - .contestEffect = CONTEST_EFFECT_MAKE_FOLLOWING_MONS_NERVOUS, - .contestCategory = CONTEST_CATEGORY_COOL, + .contestEffect = CONTEST_EFFECT_BETTER_IF_LAST, + .contestCategory = C_UPDATED_MOVE_CATEGORIES >= GEN_6 ? CONTEST_CATEGORY_SMART : CONTEST_CATEGORY_COOL, .contestComboStarterId = 0, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_PsychoShift, @@ -9767,8 +9850,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .category = DAMAGE_CATEGORY_STATUS, .zMove = { .effect = Z_EFFECT_SPATK_UP_2 }, .magicCoatAffected = B_UPDATED_MOVE_FLAGS >= GEN_5, - .contestEffect = CONTEST_EFFECT_MAKE_FOLLOWING_MONS_NERVOUS, - .contestCategory = CONTEST_CATEGORY_CUTE, + .contestEffect = CONTEST_EFFECT_DONT_EXCITE_AUDIENCE, + .contestCategory = C_UPDATED_MOVE_CATEGORIES >= GEN_6 ? CONTEST_CATEGORY_SMART : CONTEST_CATEGORY_CUTE, .contestComboStarterId = 0, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_HealBlock, @@ -9787,8 +9870,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .priority = 0, .category = DAMAGE_CATEGORY_SPECIAL, .makesContact = TRUE, - .contestEffect = CONTEST_EFFECT_STARTLE_PREV_MON, - .contestCategory = CONTEST_CATEGORY_SMART, + .contestEffect = CONTEST_EFFECT_STARTLE_MON_WITH_JUDGES_ATTENTION, + .contestCategory = C_UPDATED_MOVE_CATEGORIES >= GEN_6 ? CONTEST_CATEGORY_TOUGH : CONTEST_CATEGORY_SMART, .contestComboStarterId = 0, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_WringOut, @@ -9812,8 +9895,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .snatchAffected = B_UPDATED_MOVE_FLAGS >= GEN_5, .ignoresProtect = TRUE, .mirrorMoveBanned = TRUE, - .contestEffect = CONTEST_EFFECT_SCRAMBLE_NEXT_TURN_ORDER, - .contestCategory = CONTEST_CATEGORY_COOL, + .contestEffect = CONTEST_EFFECT_BETTER_IF_SAME_TYPE, + .contestCategory = C_UPDATED_MOVE_CATEGORIES >= GEN_6 ? CONTEST_CATEGORY_SMART : CONTEST_CATEGORY_COOL, .contestComboStarterId = 0, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_PowerTrick, @@ -9835,8 +9918,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .category = DAMAGE_CATEGORY_STATUS, .zMove = { .effect = Z_EFFECT_SPD_UP_1 }, .magicCoatAffected = TRUE, - .contestEffect = CONTEST_EFFECT_STARTLE_MON_WITH_JUDGES_ATTENTION, - .contestCategory = CONTEST_CATEGORY_BEAUTY, + .contestEffect = CONTEST_EFFECT_WORSEN_CONDITION_OF_PREV_MONS, + .contestCategory = C_UPDATED_MOVE_CATEGORIES >= GEN_6 ? CONTEST_CATEGORY_TOUGH : CONTEST_CATEGORY_BEAUTY, .contestComboStarterId = 0, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_GastroAcid, @@ -9860,7 +9943,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .snatchAffected = B_UPDATED_MOVE_FLAGS >= GEN_5, .ignoresProtect = TRUE, .mirrorMoveBanned = TRUE, - .contestEffect = CONTEST_EFFECT_DONT_EXCITE_AUDIENCE, + .contestEffect = CONTEST_EFFECT_IMPROVE_CONDITION_PREVENT_NERVOUSNESS, .contestCategory = CONTEST_CATEGORY_CUTE, .contestComboStarterId = COMBO_STARTER_LUCKY_CHANT, .contestComboMoves = {COMBO_STARTER_HEAL_BELL}, @@ -9893,7 +9976,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .assistBanned = TRUE, .mimicBanned = TRUE, .contestEffect = CONTEST_EFFECT_NEXT_APPEAL_EARLIER, - .contestCategory = CONTEST_CATEGORY_CUTE, + .contestCategory = C_UPDATED_MOVE_CATEGORIES >= GEN_6 ? CONTEST_CATEGORY_SMART : CONTEST_CATEGORY_CUTE, .contestComboStarterId = 0, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_MeFirst, @@ -9924,7 +10007,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .assistBanned = TRUE, .mimicBanned = TRUE, .contestEffect = CONTEST_EFFECT_APPEAL_AS_GOOD_AS_PREV_ONE, - .contestCategory = CONTEST_CATEGORY_COOL, + .contestCategory = C_UPDATED_MOVE_CATEGORIES >= GEN_6 ? CONTEST_CATEGORY_CUTE : CONTEST_CATEGORY_COOL, .contestComboStarterId = 0, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_Copycat, @@ -9947,7 +10030,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .zMove = { .effect = Z_EFFECT_SPD_UP_1 }, .ignoresSubstitute = TRUE, .contestEffect = CONTEST_EFFECT_APPEAL_AS_GOOD_AS_PREV_ONES, - .contestCategory = CONTEST_CATEGORY_BEAUTY, + .contestCategory = C_UPDATED_MOVE_CATEGORIES >= GEN_6 ? CONTEST_CATEGORY_SMART : CONTEST_CATEGORY_BEAUTY, .contestComboStarterId = 0, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_PowerSwap, @@ -9969,8 +10052,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .category = DAMAGE_CATEGORY_STATUS, .zMove = { .effect = Z_EFFECT_SPD_UP_1 }, .ignoresSubstitute = TRUE, - .contestEffect = CONTEST_EFFECT_AVOID_STARTLE, - .contestCategory = CONTEST_CATEGORY_CUTE, + .contestEffect = CONTEST_EFFECT_APPEAL_AS_GOOD_AS_PREV_ONES, + .contestCategory = C_UPDATED_MOVE_CATEGORIES >= GEN_6 ? CONTEST_CATEGORY_SMART : CONTEST_CATEGORY_CUTE, .contestComboStarterId = 0, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_GuardSwap, @@ -9991,8 +10074,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, .makesContact = TRUE, - .contestEffect = CONTEST_EFFECT_BETTER_WHEN_LATER, - .contestCategory = CONTEST_CATEGORY_SMART, + .contestEffect = CONTEST_EFFECT_STARTLE_MON_WITH_JUDGES_ATTENTION, + .contestCategory = C_UPDATED_MOVE_CATEGORIES >= GEN_6 ? CONTEST_CATEGORY_COOL : CONTEST_CATEGORY_SMART, .contestComboStarterId = 0, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_Punishment, @@ -10013,7 +10096,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, .makesContact = TRUE, - .contestEffect = CONTEST_EFFECT_USER_MORE_EASILY_STARTLED, + .contestEffect = CONTEST_EFFECT_BETTER_WITH_GOOD_CONDITION, .contestCategory = CONTEST_CATEGORY_CUTE, .contestComboStarterId = 0, .contestComboMoves = {0}, @@ -10026,7 +10109,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .description = COMPOUND_STRING( "种植心神不宁的种子。\n" "使对手特性变成不眠。"), - .effect = EFFECT_WORRY_SEED, + .effect = EFFECT_OVERWRITE_ABILITY, .power = 0, .type = TYPE_GRASS, .accuracy = 100, @@ -10034,12 +10117,13 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .target = MOVE_TARGET_SELECTED, .priority = 0, .category = DAMAGE_CATEGORY_STATUS, + .argument = { .overwriteAbility = ABILITY_INSOMNIA }, .zMove = { .effect = Z_EFFECT_SPD_UP_1 }, .magicCoatAffected = TRUE, .contestEffect = CONTEST_EFFECT_MAKE_FOLLOWING_MONS_NERVOUS, - .contestCategory = CONTEST_CATEGORY_BEAUTY, + .contestCategory = C_UPDATED_MOVE_CATEGORIES >= GEN_6 ? CONTEST_CATEGORY_SMART : CONTEST_CATEGORY_BEAUTY, .contestComboStarterId = COMBO_STARTER_WORRY_SEED, - .contestComboMoves = {COMBO_STARTER_LEECH_SEED}, + .contestComboMoves = {COMBO_STARTER_LEECH_SEED, COMBO_STARTER_ROTOTILLER}, .battleAnimScript = gBattleAnimMove_WorrySeed, }, @@ -10085,7 +10169,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .skyBattleBanned = TRUE, .contestEffect = CONTEST_EFFECT_MAKE_FOLLOWING_MONS_NERVOUS, .contestCategory = CONTEST_CATEGORY_SMART, - .contestComboStarterId = 0, + .contestComboStarterId = COMBO_STARTER_TOXIC_SPIKES, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_ToxicSpikes, }, @@ -10107,7 +10191,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .zMove = { .effect = Z_EFFECT_BOOST_CRITS }, .ignoresSubstitute = TRUE, .contestEffect = CONTEST_EFFECT_APPEAL_AS_GOOD_AS_PREV_ONES, - .contestCategory = CONTEST_CATEGORY_COOL, + .contestCategory = C_UPDATED_MOVE_CATEGORIES >= GEN_6 ? CONTEST_CATEGORY_SMART : CONTEST_CATEGORY_COOL, .contestComboStarterId = 0, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_HeartSwap, @@ -10131,7 +10215,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .snatchAffected = B_UPDATED_MOVE_FLAGS >= GEN_5, .ignoresProtect = TRUE, .mirrorMoveBanned = TRUE, - .contestEffect = CONTEST_EFFECT_AVOID_STARTLE, + .contestEffect = CONTEST_EFFECT_IMPROVE_CONDITION_PREVENT_NERVOUSNESS, .contestCategory = CONTEST_CATEGORY_BEAUTY, .contestComboStarterId = 0, .contestComboMoves = {0}, @@ -10157,8 +10241,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .ignoresProtect = TRUE, .mirrorMoveBanned = TRUE, .gravityBanned = TRUE, - .contestEffect = CONTEST_EFFECT_AVOID_STARTLE, - .contestCategory = CONTEST_CATEGORY_CUTE, + .contestEffect = CONTEST_EFFECT_MAKE_FOLLOWING_MONS_NERVOUS, + .contestCategory = C_UPDATED_MOVE_CATEGORIES >= GEN_6 ? CONTEST_CATEGORY_SMART : CONTEST_CATEGORY_CUTE, .contestComboStarterId = 0, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_MagnetRise, @@ -10186,7 +10270,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .chance = 10, }), .contestEffect = CONTEST_EFFECT_USER_MORE_EASILY_STARTLED, - .contestCategory = CONTEST_CATEGORY_SMART, + .contestCategory = C_UPDATED_MOVE_CATEGORIES >= GEN_6 ? CONTEST_CATEGORY_COOL : CONTEST_CATEGORY_SMART, .contestComboStarterId = 0, .contestComboMoves = {COMBO_STARTER_SUNNY_DAY}, .battleAnimScript = gBattleAnimMove_FlareBlitz, @@ -10211,9 +10295,9 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .moveEffect = MOVE_EFFECT_PARALYSIS, .chance = 30, }), - .contestEffect = CONTEST_EFFECT_BADLY_STARTLE_FRONT_MON, + .contestEffect = CONTEST_EFFECT_HIGHLY_APPEALING, .contestCategory = CONTEST_CATEGORY_COOL, - .contestComboStarterId = 0, + .contestComboStarterId = COMBO_STARTER_FORCE_PALM, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_ForcePalm, }, @@ -10261,7 +10345,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .mirrorMoveBanned = TRUE, .contestEffect = CONTEST_EFFECT_NEXT_APPEAL_EARLIER, .contestCategory = CONTEST_CATEGORY_TOUGH, - .contestComboStarterId = 0, + .contestComboStarterId = COMBO_STARTER_ROCK_POLISH, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_RockPolish, }, @@ -10285,8 +10369,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .moveEffect = MOVE_EFFECT_POISON, .chance = 30, }), - .contestEffect = CONTEST_EFFECT_BADLY_STARTLE_FRONT_MON, - .contestCategory = CONTEST_CATEGORY_SMART, + .contestEffect = CONTEST_EFFECT_HIGHLY_APPEALING, + .contestCategory = C_UPDATED_MOVE_CATEGORIES >= GEN_6 ? CONTEST_CATEGORY_TOUGH : CONTEST_CATEGORY_SMART, .contestComboStarterId = 0, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_PoisonJab, @@ -10311,7 +10395,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .moveEffect = MOVE_EFFECT_FLINCH, .chance = 20, }), - .contestEffect = CONTEST_EFFECT_BETTER_IF_LAST, + .contestEffect = CONTEST_EFFECT_HIGHLY_APPEALING, .contestCategory = CONTEST_CATEGORY_COOL, .contestComboStarterId = 0, .contestComboMoves = {0}, @@ -10328,7 +10412,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .power = 70, .type = TYPE_DARK, .accuracy = 100, - .criticalHitStage = 1, + .criticalHitStage = B_UPDATED_MOVE_DATA >= GEN_3 ? 1 : 2, .pp = 15, .target = MOVE_TARGET_SELECTED, .priority = 0, @@ -10336,9 +10420,9 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .makesContact = TRUE, .slicingMove = TRUE, .contestEffect = CONTEST_EFFECT_AFFECTED_BY_PREV_APPEAL, - .contestCategory = CONTEST_CATEGORY_BEAUTY, + .contestCategory = C_UPDATED_MOVE_CATEGORIES >= GEN_6 ? CONTEST_CATEGORY_COOL : CONTEST_CATEGORY_BEAUTY, .contestComboStarterId = 0, - .contestComboMoves = {0}, + .contestComboMoves = {COMBO_STARTER_FOCUS_ENERGY}, .battleAnimScript = gBattleAnimMove_NightSlash, }, @@ -10358,7 +10442,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .category = DAMAGE_CATEGORY_PHYSICAL, .makesContact = TRUE, .contestEffect = CONTEST_EFFECT_HIGHLY_APPEALING, - .contestCategory = CONTEST_CATEGORY_CUTE, + .contestCategory = C_UPDATED_MOVE_CATEGORIES >= GEN_6 ? CONTEST_CATEGORY_BEAUTY : CONTEST_CATEGORY_CUTE, .contestComboStarterId = 0, .contestComboMoves = {COMBO_STARTER_RAIN_DANCE}, .battleAnimScript = gBattleAnimMove_AquaTail, @@ -10380,9 +10464,9 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .category = DAMAGE_CATEGORY_PHYSICAL, .ballisticMove = TRUE, .contestEffect = CONTEST_EFFECT_HIGHLY_APPEALING, - .contestCategory = CONTEST_CATEGORY_SMART, + .contestCategory = C_UPDATED_MOVE_CATEGORIES >= GEN_6 ? CONTEST_CATEGORY_TOUGH : CONTEST_CATEGORY_SMART, .contestComboStarterId = 0, - .contestComboMoves = {0}, + .contestComboMoves = {COMBO_STARTER_ROTOTILLER}, .battleAnimScript = gBattleAnimMove_SeedBomb, }, @@ -10405,7 +10489,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .moveEffect = MOVE_EFFECT_FLINCH, .chance = 30, }), - .contestEffect = CONTEST_EFFECT_STARTLE_MONS_SAME_TYPE_APPEAL, + .contestEffect = CONTEST_EFFECT_BADLY_STARTLE_FRONT_MON, .contestCategory = CONTEST_CATEGORY_COOL, .contestComboStarterId = 0, .contestComboMoves = {0}, @@ -10428,8 +10512,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .category = DAMAGE_CATEGORY_PHYSICAL, .makesContact = TRUE, .slicingMove = TRUE, - .contestEffect = CONTEST_EFFECT_HIGHLY_APPEALING, - .contestCategory = CONTEST_CATEGORY_BEAUTY, + .contestEffect = CONTEST_EFFECT_STARTLE_MONS_SAME_TYPE_APPEAL, + .contestCategory = C_UPDATED_MOVE_CATEGORIES >= GEN_6 ? CONTEST_CATEGORY_COOL : CONTEST_CATEGORY_BEAUTY, .contestComboStarterId = 0, .contestComboMoves = {COMBO_STARTER_SWORDS_DANCE}, .battleAnimScript = gBattleAnimMove_XScissor, @@ -10455,8 +10539,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .moveEffect = MOVE_EFFECT_SP_DEF_MINUS_1, .chance = 10, }), - .contestEffect = CONTEST_EFFECT_BADLY_STARTLE_PREV_MONS, - .contestCategory = CONTEST_CATEGORY_CUTE, + .contestEffect = CONTEST_EFFECT_BADLY_STARTLE_FRONT_MON, + .contestCategory = C_UPDATED_MOVE_CATEGORIES >= GEN_6 ? CONTEST_CATEGORY_BEAUTIFUL : CONTEST_CATEGORY_CUTE, .contestComboStarterId = 0, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_BugBuzz, @@ -10477,8 +10561,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .priority = 0, .category = DAMAGE_CATEGORY_SPECIAL, .pulseMove = TRUE, - .contestEffect = CONTEST_EFFECT_STARTLE_PREV_MONS, - .contestCategory = CONTEST_CATEGORY_SMART, + .contestEffect = CONTEST_EFFECT_HIGHLY_APPEALING, + .contestCategory = C_UPDATED_MOVE_CATEGORIES >= GEN_6 ? CONTEST_CATEGORY_BEAUTY : CONTEST_CATEGORY_SMART, .contestComboStarterId = 0, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_DragonPulse, @@ -10504,8 +10588,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .moveEffect = MOVE_EFFECT_FLINCH, .chance = 20, }), - .contestEffect = CONTEST_EFFECT_BETTER_IF_FIRST, - .contestCategory = CONTEST_CATEGORY_COOL, + .contestEffect = CONTEST_EFFECT_AFFECTED_BY_PREV_APPEAL, + .contestCategory = C_UPDATED_MOVE_CATEGORIES >= GEN_6 ? CONTEST_CATEGORY_TOUGH : CONTEST_CATEGORY_COOL, .contestComboStarterId = COMBO_STARTER_DRAGON_RUSH, .contestComboMoves = {COMBO_STARTER_DRAGON_BREATH, COMBO_STARTER_DRAGON_DANCE, COMBO_STARTER_DRAGON_RAGE, COMBO_STARTER_DRAGON_TAIL}, .battleAnimScript = gBattleAnimMove_DragonRush, @@ -10548,8 +10632,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .makesContact = TRUE, .punchingMove = TRUE, .healingMove = B_HEAL_BLOCKING >= GEN_6, - .contestEffect = CONTEST_EFFECT_STARTLE_MON_WITH_JUDGES_ATTENTION, - .contestCategory = CONTEST_CATEGORY_BEAUTY, + .contestEffect = CONTEST_EFFECT_APPEAL_AS_GOOD_AS_PREV_ONE, + .contestCategory = C_UPDATED_MOVE_CATEGORIES >= GEN_6 ? CONTEST_CATEGORY_TOUGH : CONTEST_CATEGORY_BEAUTY, .contestComboStarterId = 0, .contestComboMoves = {COMBO_STARTER_FOCUS_ENERGY}, .battleAnimScript = gBattleAnimMove_DrainPunch, @@ -10570,7 +10654,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .priority = 1, .category = DAMAGE_CATEGORY_SPECIAL, .contestEffect = CONTEST_EFFECT_NEXT_APPEAL_EARLIER, - .contestCategory = CONTEST_CATEGORY_SMART, + .contestCategory = C_UPDATED_MOVE_CATEGORIES >= GEN_6 ? CONTEST_CATEGORY_COOL : CONTEST_CATEGORY_SMART, .contestComboStarterId = 0, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_VacuumWave, @@ -10595,7 +10679,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .moveEffect = MOVE_EFFECT_SP_DEF_MINUS_1, .chance = 10, }), - .contestEffect = CONTEST_EFFECT_STARTLE_MON_WITH_JUDGES_ATTENTION, + .contestEffect = CONTEST_EFFECT_HIGHLY_APPEALING, .contestCategory = CONTEST_CATEGORY_COOL, .contestComboStarterId = 0, .contestComboMoves = {COMBO_STARTER_FOCUS_ENERGY}, @@ -10621,7 +10705,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .moveEffect = MOVE_EFFECT_SP_DEF_MINUS_1, .chance = 10, }), - .contestEffect = CONTEST_EFFECT_BADLY_STARTLE_PREV_MONS, + .contestEffect = CONTEST_EFFECT_HIGHLY_APPEALING, .contestCategory = CONTEST_CATEGORY_BEAUTY, .contestComboStarterId = 0, .contestComboMoves = {COMBO_STARTER_GROWTH}, @@ -10645,7 +10729,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .argument = { .recoilPercentage = 33 }, .makesContact = TRUE, .contestEffect = CONTEST_EFFECT_USER_MORE_EASILY_STARTLED, - .contestCategory = CONTEST_CATEGORY_CUTE, + .contestCategory = C_UPDATED_MOVE_CATEGORIES >= GEN_6 ? CONTEST_CATEGORY_COOL : CONTEST_CATEGORY_CUTE, .contestComboStarterId = COMBO_STARTER_BRAVE_BIRD, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_BraveBird, @@ -10670,8 +10754,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .moveEffect = MOVE_EFFECT_SP_DEF_MINUS_1, .chance = 10, }), - .contestEffect = CONTEST_EFFECT_BADLY_STARTLE_PREV_MONS, - .contestCategory = CONTEST_CATEGORY_SMART, + .contestEffect = CONTEST_EFFECT_HIGHLY_APPEALING, + .contestCategory = C_UPDATED_MOVE_CATEGORIES >= GEN_6 ? CONTEST_CATEGORY_BEAUTY : CONTEST_CATEGORY_SMART, .contestComboStarterId = 0, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_EarthPower, @@ -10695,8 +10779,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .metronomeBanned = TRUE, .copycatBanned = TRUE, .assistBanned = TRUE, - .contestEffect = CONTEST_EFFECT_SCRAMBLE_NEXT_TURN_ORDER, - .contestCategory = CONTEST_CATEGORY_COOL, + .contestEffect = CONTEST_EFFECT_STARTLE_MONS_SAME_TYPE_APPEAL, + .contestCategory = C_UPDATED_MOVE_CATEGORIES >= GEN_6 ? CONTEST_CATEGORY_SMART : CONTEST_CATEGORY_COOL, .contestComboStarterId = 0, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_Switcheroo, @@ -10720,7 +10804,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .self = TRUE, }), .contestEffect = CONTEST_EFFECT_JAMS_OTHERS_BUT_MISS_ONE_TURN, - .contestCategory = CONTEST_CATEGORY_BEAUTY, + .contestCategory = C_UPDATED_MOVE_CATEGORIES >= GEN_6 ? CONTEST_CATEGORY_TOUGH : CONTEST_CATEGORY_BEAUTY, .contestComboStarterId = 0, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_GigaImpact, @@ -10745,8 +10829,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .ignoresProtect = TRUE, .mirrorMoveBanned = TRUE, .contestEffect = CONTEST_EFFECT_IMPROVE_CONDITION_PREVENT_NERVOUSNESS, - .contestCategory = CONTEST_CATEGORY_CUTE, - .contestComboStarterId = 0, + .contestCategory = C_UPDATED_MOVE_CATEGORIES >= GEN_6 ? CONTEST_CATEGORY_SMART : CONTEST_CATEGORY_CUTE, + .contestComboStarterId = COMBO_STARTER_NASTY_PLOT, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_NastyPlot, }, @@ -10768,7 +10852,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .makesContact = TRUE, .punchingMove = TRUE, .contestEffect = CONTEST_EFFECT_NEXT_APPEAL_EARLIER, - .contestCategory = CONTEST_CATEGORY_SMART, + .contestCategory = C_UPDATED_MOVE_CATEGORIES >= GEN_6 ? CONTEST_CATEGORY_TOUGH : CONTEST_CATEGORY_SMART, .contestComboStarterId = 0, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_BulletPunch, @@ -10787,8 +10871,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .priority = -4, .category = DAMAGE_CATEGORY_PHYSICAL, .makesContact = TRUE, - .contestEffect = CONTEST_EFFECT_NEXT_APPEAL_LATER, - .contestCategory = CONTEST_CATEGORY_COOL, + .contestEffect = CONTEST_EFFECT_AFFECTED_BY_PREV_APPEAL, + .contestCategory = C_UPDATED_MOVE_CATEGORIES >= GEN_6 ? CONTEST_CATEGORY_BEAUTY : CONTEST_CATEGORY_COOL, .contestComboStarterId = 0, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_Avalanche, @@ -10825,16 +10909,16 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .power = 70, .type = TYPE_GHOST, .accuracy = 100, - .criticalHitStage = 1, + .criticalHitStage = B_UPDATED_MOVE_DATA >= GEN_3 ? 1 : 2, .pp = 15, .target = MOVE_TARGET_SELECTED, .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, .makesContact = TRUE, - .contestEffect = CONTEST_EFFECT_AFFECTED_BY_PREV_APPEAL, - .contestCategory = CONTEST_CATEGORY_CUTE, + .contestEffect = CONTEST_EFFECT_HIGHLY_APPEALING, + .contestCategory = C_UPDATED_MOVE_CATEGORIES >= GEN_6 ? CONTEST_CATEGORY_COOL : CONTEST_CATEGORY_CUTE, .contestComboStarterId = 0, - .contestComboMoves = {0}, + .contestComboMoves = {COMBO_STARTER_FOCUS_ENERGY}, .battleAnimScript = gBattleAnimMove_ShadowClaw, }, @@ -10863,7 +10947,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .chance = 10, }), .contestEffect = CONTEST_EFFECT_HIGHLY_APPEALING, - .contestCategory = CONTEST_CATEGORY_SMART, + .contestCategory = C_UPDATED_MOVE_CATEGORIES >= GEN_6 ? CONTEST_CATEGORY_COOL : CONTEST_CATEGORY_SMART, .contestComboStarterId = COMBO_STARTER_THUNDER_FANG, .contestComboMoves = {COMBO_STARTER_CHARGE, COMBO_STARTER_FIRE_FANG, COMBO_STARTER_ICE_FANG}, .battleAnimScript = gBattleAnimMove_ThunderFang, @@ -10925,7 +11009,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .chance = 10, }), .contestEffect = CONTEST_EFFECT_HIGHLY_APPEALING, - .contestCategory = CONTEST_CATEGORY_BEAUTY, + .contestCategory = C_UPDATED_MOVE_CATEGORIES >= GEN_6 ? CONTEST_CATEGORY_COOL : CONTEST_CATEGORY_BEAUTY, .contestComboStarterId = COMBO_STARTER_FIRE_FANG, .contestComboMoves = {COMBO_STARTER_ICE_FANG, COMBO_STARTER_THUNDER_FANG}, .battleAnimScript = gBattleAnimMove_FireFang, @@ -10972,8 +11056,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .moveEffect = MOVE_EFFECT_ACC_MINUS_1, .chance = 30, }), - .contestEffect = CONTEST_EFFECT_STARTLE_MON_WITH_JUDGES_ATTENTION, - .contestCategory = CONTEST_CATEGORY_SMART, + .contestEffect = CONTEST_EFFECT_STARTLE_PREV_MON, + .contestCategory = C_UPDATED_MOVE_CATEGORIES >= GEN_6 ? CONTEST_CATEGORY_CUTE : CONTEST_CATEGORY_SMART, .contestComboStarterId = 0, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_MudBomb, @@ -10989,13 +11073,13 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .power = 70, .type = TYPE_PSYCHIC, .accuracy = 100, - .criticalHitStage = 1, + .criticalHitStage = B_UPDATED_MOVE_DATA >= GEN_3 ? 1 : 2, .pp = 20, .target = MOVE_TARGET_SELECTED, .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, .slicingMove = TRUE, - .contestEffect = CONTEST_EFFECT_AFFECTED_BY_PREV_APPEAL, + .contestEffect = CONTEST_EFFECT_HIGHLY_APPEALING, .contestCategory = CONTEST_CATEGORY_COOL, .contestComboStarterId = 0, .contestComboMoves = {0}, @@ -11021,8 +11105,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .moveEffect = MOVE_EFFECT_FLINCH, .chance = 20, }), - .contestEffect = CONTEST_EFFECT_BADLY_STARTLE_FRONT_MON, - .contestCategory = CONTEST_CATEGORY_BEAUTY, + .contestEffect = CONTEST_EFFECT_HIGHLY_APPEALING, + .contestCategory = C_UPDATED_MOVE_CATEGORIES >= GEN_6 ? CONTEST_CATEGORY_SMART : CONTEST_CATEGORY_BEAUTY, .contestComboStarterId = 0, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_ZenHeadbutt, @@ -11046,8 +11130,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .moveEffect = MOVE_EFFECT_ACC_MINUS_1, .chance = 30, }), - .contestEffect = CONTEST_EFFECT_STARTLE_MON_WITH_JUDGES_ATTENTION, - .contestCategory = CONTEST_CATEGORY_CUTE, + .contestEffect = CONTEST_EFFECT_STARTLE_PREV_MON, + .contestCategory = C_UPDATED_MOVE_CATEGORIES >= GEN_6 ? CONTEST_CATEGORY_BEAUTY : CONTEST_CATEGORY_CUTE, .contestComboStarterId = 0, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_MirrorShot, @@ -11071,8 +11155,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .moveEffect = MOVE_EFFECT_SP_DEF_MINUS_1, .chance = 10, }), - .contestEffect = CONTEST_EFFECT_BADLY_STARTLE_PREV_MONS, - .contestCategory = CONTEST_CATEGORY_SMART, + .contestEffect = CONTEST_EFFECT_HIGHLY_APPEALING, + .contestCategory = C_UPDATED_MOVE_CATEGORIES >= GEN_6 ? CONTEST_CATEGORY_BEAUTY : CONTEST_CATEGORY_SMART, .contestComboStarterId = 0, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_FlashCannon, @@ -11097,7 +11181,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .moveEffect = MOVE_EFFECT_CONFUSION, .chance = 20, }), - .contestEffect = CONTEST_EFFECT_BETTER_WITH_GOOD_CONDITION, + .contestEffect = CONTEST_EFFECT_SHIFT_JUDGE_ATTENTION, .contestCategory = CONTEST_CATEGORY_COOL, .contestComboStarterId = 0, .contestComboMoves = {0}, @@ -11121,8 +11205,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .zMove = { .effect = Z_EFFECT_ACC_UP_1 }, //.ignoresSubstitute = TRUE, In Gen5+, the evasion drop will no longer bypass Substitute. However, this is tricky to code .magicCoatAffected = B_UPDATED_MOVE_FLAGS >= GEN_5, - .contestEffect = CONTEST_EFFECT_WORSEN_CONDITION_OF_PREV_MONS, - .contestCategory = CONTEST_CATEGORY_BEAUTY, + .contestEffect = CONTEST_EFFECT_BETTER_IF_FIRST, + .contestCategory = C_UPDATED_MOVE_CATEGORIES >= GEN_6 ? CONTEST_CATEGORY_COOL : CONTEST_CATEGORY_BEAUTY, .contestComboStarterId = 0, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_Defog, @@ -11144,8 +11228,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .category = DAMAGE_CATEGORY_STATUS, .zMove = { .effect = Z_EFFECT_ACC_UP_1 }, .ignoresProtect = TRUE, - .contestEffect = CONTEST_EFFECT_NEXT_APPEAL_LATER, - .contestCategory = CONTEST_CATEGORY_CUTE, + .contestEffect = CONTEST_EFFECT_SCRAMBLE_NEXT_TURN_ORDER, + .contestCategory = C_UPDATED_MOVE_CATEGORIES >= GEN_6 ? CONTEST_CATEGORY_SMART : CONTEST_CATEGORY_CUTE, .contestComboStarterId = 0, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_TrickRoom, @@ -11170,7 +11254,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .self = TRUE, }), .contestEffect = CONTEST_EFFECT_USER_MORE_EASILY_STARTLED, - .contestCategory = CONTEST_CATEGORY_SMART, + .contestCategory = C_UPDATED_MOVE_CATEGORIES >= GEN_6 ? CONTEST_CATEGORY_BEAUTY : CONTEST_CATEGORY_SMART, .contestComboStarterId = 0, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_DracoMeteor, @@ -11194,8 +11278,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .moveEffect = MOVE_EFFECT_PARALYSIS, .chance = 30, }), - .contestEffect = CONTEST_EFFECT_BADLY_STARTLE_PREV_MONS, - .contestCategory = CONTEST_CATEGORY_COOL, + .contestEffect = CONTEST_EFFECT_STARTLE_PREV_MONS, + .contestCategory = C_UPDATED_MOVE_CATEGORIES >= GEN_6 ? CONTEST_CATEGORY_BEAUTY : CONTEST_CATEGORY_COOL, .contestComboStarterId = 0, .contestComboMoves = {COMBO_STARTER_CHARGE}, .battleAnimScript = gBattleAnimMove_Discharge, @@ -11217,7 +11301,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .moveEffect = MOVE_EFFECT_BURN, .chance = 30, }), - .contestEffect = CONTEST_EFFECT_BADLY_STARTLE_PREV_MONS, + .contestEffect = CONTEST_EFFECT_STARTLE_PREV_MONS, .contestCategory = CONTEST_CATEGORY_TOUGH, .contestComboStarterId = 0, .contestComboMoves = {COMBO_STARTER_SUNNY_DAY}, @@ -11243,7 +11327,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .self = TRUE, }), .contestEffect = CONTEST_EFFECT_USER_MORE_EASILY_STARTLED, - .contestCategory = CONTEST_CATEGORY_CUTE, + .contestCategory = C_UPDATED_MOVE_CATEGORIES >= GEN_6 ? CONTEST_CATEGORY_BEAUTY : CONTEST_CATEGORY_CUTE, .contestComboStarterId = 0, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_LeafStorm, @@ -11264,8 +11348,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, .makesContact = TRUE, - .contestEffect = CONTEST_EFFECT_BETTER_IF_SAME_TYPE, - .contestCategory = CONTEST_CATEGORY_BEAUTY, + .contestEffect = CONTEST_EFFECT_BETTER_WHEN_AUDIENCE_EXCITED, + .contestCategory = C_UPDATED_MOVE_CATEGORIES >= GEN_6 ? CONTEST_CATEGORY_TOUGH : CONTEST_CATEGORY_BEAUTY, .contestComboStarterId = 0, .contestComboMoves = {COMBO_STARTER_GROWTH}, .battleAnimScript = gBattleAnimMove_PowerWhip, @@ -11305,7 +11389,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .power = 70, .type = TYPE_POISON, .accuracy = 100, - .criticalHitStage = 1, + .criticalHitStage = B_UPDATED_MOVE_DATA >= GEN_3 ? 1 : 2, .pp = 20, .target = MOVE_TARGET_SELECTED, .priority = 0, @@ -11316,7 +11400,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .moveEffect = MOVE_EFFECT_POISON, .chance = 10, }), - .contestEffect = CONTEST_EFFECT_HIGHLY_APPEALING, + .contestEffect = CONTEST_EFFECT_STARTLE_MONS_SAME_TYPE_APPEAL, .contestCategory = CONTEST_CATEGORY_COOL, .contestComboStarterId = 0, .contestComboMoves = {0}, @@ -11341,8 +11425,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .moveEffect = MOVE_EFFECT_POISON, .chance = 30, }), - .contestEffect = CONTEST_EFFECT_STARTLE_PREV_MONS, - .contestCategory = CONTEST_CATEGORY_COOL, + .contestEffect = CONTEST_EFFECT_BADLY_STARTLE_MONS_WITH_GOOD_APPEALS, + .contestCategory = C_UPDATED_MOVE_CATEGORIES >= GEN_6 ? CONTEST_CATEGORY_TOUGH : CONTEST_CATEGORY_COOL, .contestComboStarterId = 0, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_GunkShot, @@ -11367,7 +11451,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .moveEffect = MOVE_EFFECT_FLINCH, .chance = 30, }), - .contestEffect = CONTEST_EFFECT_BADLY_STARTLE_FRONT_MON, + .contestEffect = CONTEST_EFFECT_HIGHLY_APPEALING, .contestCategory = CONTEST_CATEGORY_TOUGH, .contestComboStarterId = 0, .contestComboMoves = {0}, @@ -11406,7 +11490,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .power = 100, .type = TYPE_ROCK, .accuracy = 80, - .criticalHitStage = 1, + .criticalHitStage = B_UPDATED_MOVE_DATA >= GEN_3 ? 1 : 2, .pp = 5, .target = MOVE_TARGET_SELECTED, .priority = 0, @@ -11414,7 +11498,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .contestEffect = CONTEST_EFFECT_AFFECTED_BY_PREV_APPEAL, .contestCategory = CONTEST_CATEGORY_TOUGH, .contestComboStarterId = 0, - .contestComboMoves = {0}, + .contestComboMoves = {COMBO_STARTER_FOCUS_ENERGY}, .battleAnimScript = gBattleAnimMove_StoneEdge, }, @@ -11434,8 +11518,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .category = DAMAGE_CATEGORY_STATUS, .zMove = { .effect = Z_EFFECT_SPDEF_UP_2 }, .magicCoatAffected = TRUE, - .contestEffect = CONTEST_EFFECT_DONT_EXCITE_AUDIENCE, - .contestCategory = CONTEST_CATEGORY_BEAUTY, + .contestEffect = CONTEST_EFFECT_DONT_EXCITE_AUDIENCE, //CONTEST_EFFECT_QUICKLY_GROW_BORED + .contestCategory = C_UPDATED_MOVE_CATEGORIES >= GEN_6 ? CONTEST_CATEGORY_CUTE : CONTEST_CATEGORY_BEAUTY, .contestComboStarterId = 0, .contestComboMoves = {COMBO_STARTER_CHARM}, .battleAnimScript = gBattleAnimMove_Captivate, @@ -11463,7 +11547,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .contestEffect = CONTEST_EFFECT_MAKE_FOLLOWING_MONS_NERVOUS, .contestCategory = CONTEST_CATEGORY_COOL, .contestComboStarterId = 0, - .contestComboMoves = {0}, + .contestComboMoves = {COMBO_STARTER_STEALTH_ROCK}, .battleAnimScript = gBattleAnimMove_StealthRock, }, @@ -11483,8 +11567,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .category = DAMAGE_CATEGORY_SPECIAL, .makesContact = TRUE, .skyBattleBanned = TRUE, - .contestEffect = CONTEST_EFFECT_BADLY_STARTLE_FRONT_MON, - .contestCategory = CONTEST_CATEGORY_SMART, + .contestEffect = CONTEST_EFFECT_BETTER_WHEN_LATER, + .contestCategory = C_UPDATED_MOVE_CATEGORIES >= GEN_6 ? CONTEST_CATEGORY_CUTE : CONTEST_CATEGORY_SMART, .contestComboStarterId = 0, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_GrassKnot, @@ -11517,14 +11601,14 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .moveEffect = MOVE_EFFECT_CONFUSION, #if B_UPDATED_MOVE_DATA >= GEN_6 .chance = 100, - #elif B_UPDATED_MOVE_DATA >= GEN_5 + #elif B_UPDATED_MOVE_DATA == GEN_5 .chance = 10, #else .chance = 31, #endif }), - .contestEffect = CONTEST_EFFECT_SCRAMBLE_NEXT_TURN_ORDER, - .contestCategory = CONTEST_CATEGORY_SMART, + .contestEffect = CONTEST_EFFECT_WORSEN_CONDITION_OF_PREV_MONS, + .contestCategory = C_UPDATED_MOVE_CATEGORIES >= GEN_6 ? CONTEST_CATEGORY_CUTE : CONTEST_CATEGORY_SMART, .contestComboStarterId = 0, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_Chatter, @@ -11545,8 +11629,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .priority = 0, .category = DAMAGE_CATEGORY_SPECIAL, .argument = { .holdEffect = HOLD_EFFECT_PLATE }, - .contestEffect = CONTEST_EFFECT_SCRAMBLE_NEXT_TURN_ORDER, - .contestCategory = CONTEST_CATEGORY_SMART, + .contestEffect = CONTEST_EFFECT_REPETITION_NOT_BORING, + .contestCategory = C_UPDATED_MOVE_CATEGORIES >= GEN_6 ? CONTEST_CATEGORY_BEAUTY : CONTEST_CATEGORY_SMART, .contestComboStarterId = 0, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_Judgment, @@ -11568,8 +11652,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_BUG_BITE, }), - .contestEffect = CONTEST_EFFECT_AFFECTED_BY_PREV_APPEAL, - .contestCategory = CONTEST_CATEGORY_TOUGH, + .contestEffect = CONTEST_EFFECT_WORSEN_CONDITION_OF_PREV_MONS, + .contestCategory = C_UPDATED_MOVE_CATEGORIES >= GEN_6 ? CONTEST_CATEGORY_CUTE : CONTEST_CATEGORY_TOUGH, .contestComboStarterId = 0, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_BugBite, @@ -11594,7 +11678,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .self = TRUE, .chance = 70, }), - .contestEffect = CONTEST_EFFECT_IMPROVE_CONDITION_PREVENT_NERVOUSNESS, + .contestEffect = CONTEST_EFFECT_BETTER_WITH_GOOD_CONDITION, .contestCategory = CONTEST_CATEGORY_BEAUTY, .contestComboStarterId = 0, .contestComboMoves = {COMBO_STARTER_CHARGE}, @@ -11640,7 +11724,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .category = DAMAGE_CATEGORY_PHYSICAL, .makesContact = TRUE, .contestEffect = CONTEST_EFFECT_NEXT_APPEAL_EARLIER, - .contestCategory = CONTEST_CATEGORY_BEAUTY, + .contestCategory = C_UPDATED_MOVE_CATEGORIES >= GEN_6 ? CONTEST_CATEGORY_COOL : CONTEST_CATEGORY_BEAUTY, .contestComboStarterId = 0, .contestComboMoves = {COMBO_STARTER_RAIN_DANCE}, .battleAnimScript = gBattleAnimMove_AquaJet, @@ -11656,12 +11740,12 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .power = 90, .type = TYPE_BUG, .accuracy = 100, - .criticalHitStage = 1, + .criticalHitStage = B_UPDATED_MOVE_DATA >= GEN_3 ? 1 : 2, .pp = 15, .target = MOVE_TARGET_SELECTED, .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, - .contestEffect = CONTEST_EFFECT_AFFECTED_BY_PREV_APPEAL, + .contestEffect = CONTEST_EFFECT_REPETITION_NOT_BORING, .contestCategory = CONTEST_CATEGORY_SMART, .contestComboStarterId = COMBO_STARTER_ATTACK_ORDER, .contestComboMoves = {COMBO_STARTER_DEFEND_ORDER, COMBO_STARTER_HEAL_ORDER}, @@ -11686,7 +11770,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .snatchAffected = TRUE, .ignoresProtect = TRUE, .mirrorMoveBanned = TRUE, - .contestEffect = CONTEST_EFFECT_AVOID_STARTLE, + .contestEffect = CONTEST_EFFECT_AVOID_STARTLE_ONCE, .contestCategory = CONTEST_CATEGORY_SMART, .contestComboStarterId = COMBO_STARTER_DEFEND_ORDER, .contestComboMoves = {COMBO_STARTER_ATTACK_ORDER, COMBO_STARTER_HEAL_ORDER}, @@ -11758,8 +11842,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .category = DAMAGE_CATEGORY_PHYSICAL, .makesContact = TRUE, .strikeCount = 2, - .contestEffect = CONTEST_EFFECT_REPETITION_NOT_BORING, - .contestCategory = CONTEST_CATEGORY_SMART, + .contestEffect = CONTEST_EFFECT_STARTLE_MONS_SAME_TYPE_APPEAL, + .contestCategory = C_UPDATED_MOVE_CATEGORIES >= GEN_6 ? CONTEST_CATEGORY_COOL : CONTEST_CATEGORY_SMART, .contestComboStarterId = 0, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_DoubleHit, @@ -11784,7 +11868,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .self = TRUE, }), .contestEffect = CONTEST_EFFECT_JAMS_OTHERS_BUT_MISS_ONE_TURN, - .contestCategory = CONTEST_CATEGORY_COOL, + .contestCategory = C_UPDATED_MOVE_CATEGORIES >= GEN_6 ? CONTEST_CATEGORY_BEAUTY : CONTEST_CATEGORY_COOL, .contestComboStarterId = 0, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_RoarOfTime, @@ -11800,13 +11884,13 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .power = 100, .type = TYPE_DRAGON, .accuracy = 95, - .criticalHitStage = 1, + .criticalHitStage = B_UPDATED_MOVE_DATA >= GEN_3 ? 1 : 2, .pp = 5, .target = MOVE_TARGET_SELECTED, .priority = 0, .category = DAMAGE_CATEGORY_SPECIAL, - .contestEffect = CONTEST_EFFECT_AFFECTED_BY_PREV_APPEAL, - .contestCategory = CONTEST_CATEGORY_TOUGH, + .contestEffect = CONTEST_EFFECT_USER_MORE_EASILY_STARTLED, + .contestCategory = C_UPDATED_MOVE_CATEGORIES >= GEN_6 ? CONTEST_CATEGORY_BEAUTY : CONTEST_CATEGORY_TOUGH, .contestComboStarterId = 0, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_SpacialRend, @@ -11816,7 +11900,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("新月舞"), .description = sHealingWishDescription, - .effect = EFFECT_HEALING_WISH, + .effect = EFFECT_LUNAR_DANCE, .power = 0, .type = TYPE_PSYCHIC, .accuracy = 0, @@ -11849,7 +11933,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, .makesContact = TRUE, - .contestEffect = CONTEST_EFFECT_BADLY_STARTLE_FRONT_MON, + .contestEffect = CONTEST_EFFECT_REPETITION_NOT_BORING, .contestCategory = CONTEST_CATEGORY_TOUGH, .contestComboStarterId = 0, .contestComboMoves = {0}, @@ -11899,9 +11983,9 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .zMove = { .effect = Z_EFFECT_RESET_STATS }, .magicCoatAffected = TRUE, .sketchBanned = (B_SKETCH_BANS >= GEN_9), - .contestEffect = CONTEST_EFFECT_DONT_EXCITE_AUDIENCE, + .contestEffect = CONTEST_EFFECT_MAKE_FOLLOWING_MONS_NERVOUS, .contestCategory = CONTEST_CATEGORY_SMART, - .contestComboStarterId = 0, + .contestComboStarterId = COMBO_STARTER_DARK_VOID, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_DarkVoid, }, @@ -11924,8 +12008,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .moveEffect = MOVE_EFFECT_SP_DEF_MINUS_2, .chance = 40, }), - .contestEffect = CONTEST_EFFECT_HIGHLY_APPEALING, - .contestCategory = CONTEST_CATEGORY_COOL, + .contestEffect = CONTEST_EFFECT_USER_MORE_EASILY_STARTLED, + .contestCategory = C_UPDATED_MOVE_CATEGORIES >= GEN_6 ? CONTEST_CATEGORY_BEAUTY : CONTEST_CATEGORY_COOL, .contestComboStarterId = 0, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_SeedFlare, @@ -11952,7 +12036,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .chance = 10, }), .contestEffect = CONTEST_EFFECT_IMPROVE_CONDITION_PREVENT_NERVOUSNESS, - .contestCategory = CONTEST_CATEGORY_SMART, + .contestCategory = C_UPDATED_MOVE_CATEGORIES >= GEN_6 ? CONTEST_CATEGORY_BEAUTY : CONTEST_CATEGORY_SMART, .contestComboStarterId = 0, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_OminousWind, @@ -11975,13 +12059,13 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .minimizeDoubleDamage = B_UPDATED_MOVE_FLAGS == GEN_6, .sleepTalkBanned = TRUE, .instructBanned = TRUE, - .assistBanned = TRUE, + .assistBanned = B_UPDATED_MOVE_FLAGS >= GEN_6, .argument.twoTurnAttack = { .stringId = STRINGID_VANISHEDINSTANTLY, .status = STATE_PHANTOM_FORCE }, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_FEINT, }), - .contestEffect = CONTEST_EFFECT_AVOID_STARTLE_ONCE, - .contestCategory = CONTEST_CATEGORY_SMART, + .contestEffect = CONTEST_EFFECT_AVOID_STARTLE, + .contestCategory = C_UPDATED_MOVE_CATEGORIES >= GEN_6 ? CONTEST_CATEGORY_COOL : CONTEST_CATEGORY_SMART, .contestComboStarterId = 0, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_ShadowForce, @@ -12006,8 +12090,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .ignoresProtect = TRUE, .mirrorMoveBanned = TRUE, .contestEffect = CONTEST_EFFECT_IMPROVE_CONDITION_PREVENT_NERVOUSNESS, - .contestCategory = CONTEST_CATEGORY_COOL, - .contestComboStarterId = 0, + .contestCategory = CONTEST_CATEGORY_CUTE, + .contestComboStarterId = COMBO_STARTER_HONE_CLAWS, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_HoneClaws, }, @@ -12055,7 +12139,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .category = DAMAGE_CATEGORY_STATUS, .zMove = { .effect = Z_EFFECT_SPD_UP_1 }, .mirrorMoveBanned = TRUE, - .contestEffect = CONTEST_EFFECT_AVOID_STARTLE, + .contestEffect = CONTEST_EFFECT_APPEAL_AS_GOOD_AS_PREV_ONES, .contestCategory = CONTEST_CATEGORY_SMART, .contestComboStarterId = 0, .contestComboMoves = {0}, @@ -12101,8 +12185,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .category = DAMAGE_CATEGORY_STATUS, .zMove = { .effect = Z_EFFECT_SPDEF_UP_1 }, .ignoresProtect = TRUE, - .contestEffect = CONTEST_EFFECT_BADLY_STARTLE_MONS_WITH_GOOD_APPEALS, - .contestCategory = CONTEST_CATEGORY_BEAUTY, + .contestEffect = CONTEST_EFFECT_SCRAMBLE_NEXT_TURN_ORDER, + .contestCategory = CONTEST_CATEGORY_SMART, .contestComboStarterId = 0, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_WonderRoom, @@ -12120,8 +12204,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .target = MOVE_TARGET_SELECTED, .priority = 0, .category = DAMAGE_CATEGORY_SPECIAL, - .contestEffect = CONTEST_EFFECT_BETTER_IF_SAME_TYPE, - .contestCategory = CONTEST_CATEGORY_SMART, + .contestEffect = CONTEST_EFFECT_BADLY_STARTLE_FRONT_MON, + .contestCategory = CONTEST_CATEGORY_BEAUTY, .contestComboStarterId = 0, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_Psyshock, @@ -12143,9 +12227,9 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .category = DAMAGE_CATEGORY_SPECIAL, .argument = { .status = STATUS1_PSN_ANY }, .contestEffect = CONTEST_EFFECT_BETTER_IF_SAME_TYPE, - .contestCategory = CONTEST_CATEGORY_TOUGH, + .contestCategory = CONTEST_CATEGORY_BEAUTY, .contestComboStarterId = 0, - .contestComboMoves = {COMBO_STARTER_TOXIC}, + .contestComboMoves = {COMBO_STARTER_TOXIC, COMBO_STARTER_POISON_GAS, COMBO_STARTER_POISON_POWDER, COMBO_STARTER_TOXIC_SPIKES}, .battleAnimScript = gBattleAnimMove_Venoshock, }, @@ -12167,8 +12251,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .snatchAffected = TRUE, .ignoresProtect = TRUE, .mirrorMoveBanned = TRUE, - .contestEffect = CONTEST_EFFECT_NEXT_APPEAL_EARLIER, - .contestCategory = CONTEST_CATEGORY_SMART, + .contestEffect = CONTEST_EFFECT_IMPROVE_CONDITION_PREVENT_NERVOUSNESS, + .contestCategory = CONTEST_CATEGORY_BEAUTY, .contestComboStarterId = 0, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_Autotomize, @@ -12196,7 +12280,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .copycatBanned = TRUE, .assistBanned = TRUE, .contestEffect = CONTEST_EFFECT_DONT_EXCITE_AUDIENCE, - .contestCategory = CONTEST_CATEGORY_BEAUTY, + .contestCategory = CONTEST_CATEGORY_SMART, .contestComboStarterId = 0, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_RagePowder, @@ -12219,7 +12303,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .zMove = { .effect = Z_EFFECT_SPATK_UP_1 }, .magicCoatAffected = TRUE, .gravityBanned = TRUE, - .contestEffect = CONTEST_EFFECT_SHIFT_JUDGE_ATTENTION, + .contestEffect = CONTEST_EFFECT_MAKE_FOLLOWING_MONS_NERVOUS, .contestCategory = CONTEST_CATEGORY_SMART, .contestComboStarterId = 0, .contestComboMoves = {0}, @@ -12242,7 +12326,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .category = DAMAGE_CATEGORY_STATUS, .zMove = { .effect = Z_EFFECT_SPDEF_UP_1 }, .ignoresProtect = TRUE, - .contestEffect = CONTEST_EFFECT_MAKE_FOLLOWING_MONS_NERVOUS, + .contestEffect = CONTEST_EFFECT_DONT_EXCITE_AUDIENCE, .contestCategory = CONTEST_CATEGORY_SMART, .contestComboStarterId = 0, .contestComboMoves = {0}, @@ -12265,10 +12349,10 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .category = DAMAGE_CATEGORY_PHYSICAL, .damagesAirborne = TRUE, .skyBattleBanned = TRUE, - .contestEffect = CONTEST_EFFECT_BADLY_STARTLE_FRONT_MON, + .contestEffect = CONTEST_EFFECT_STARTLE_MON_WITH_JUDGES_ATTENTION, .contestCategory = CONTEST_CATEGORY_TOUGH, .contestComboStarterId = 0, - .contestComboMoves = {0}, + .contestComboMoves = {COMBO_STARTER_ENTRAINMENT, COMBO_STARTER_PLAY_NICE}, .battleAnimScript = gBattleAnimMove_SmackDown, }, @@ -12286,10 +12370,10 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .category = DAMAGE_CATEGORY_PHYSICAL, .makesContact = TRUE, .alwaysCriticalHit = TRUE, - .contestEffect = CONTEST_EFFECT_AFFECTED_BY_PREV_APPEAL, - .contestCategory = CONTEST_CATEGORY_TOUGH, + .contestEffect = CONTEST_EFFECT_EXCITE_AUDIENCE_IN_ANY_CONTEST, + .contestCategory = CONTEST_CATEGORY_COOL, .contestComboStarterId = 0, - .contestComboMoves = {0}, + .contestComboMoves = {COMBO_STARTER_ENTRAINMENT, COMBO_STARTER_PLAY_NICE}, .battleAnimScript = gBattleAnimMove_StormThrow, }, @@ -12311,7 +12395,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .moveEffect = MOVE_EFFECT_FLAME_BURST, .self = TRUE, }), - .contestEffect = CONTEST_EFFECT_STARTLE_PREV_MONS, + .contestEffect = CONTEST_EFFECT_SHIFT_JUDGE_ATTENTION, .contestCategory = CONTEST_CATEGORY_BEAUTY, .contestComboStarterId = 0, .contestComboMoves = {0}, @@ -12336,7 +12420,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .moveEffect = MOVE_EFFECT_POISON, .chance = 10, }), - .contestEffect = CONTEST_EFFECT_BADLY_STARTLE_PREV_MONS, + .contestEffect = CONTEST_EFFECT_WORSEN_CONDITION_OF_PREV_MONS, .contestCategory = CONTEST_CATEGORY_TOUGH, .contestComboStarterId = 0, .contestComboMoves = {0}, @@ -12363,7 +12447,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .ignoresProtect = TRUE, .mirrorMoveBanned = TRUE, .contestEffect = CONTEST_EFFECT_IMPROVE_CONDITION_PREVENT_NERVOUSNESS, - .contestCategory = CONTEST_CATEGORY_SMART, + .contestCategory = CONTEST_CATEGORY_BEAUTY, .contestComboStarterId = 0, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_QuiverDance, @@ -12384,7 +12468,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .makesContact = TRUE, .minimizeDoubleDamage = B_UPDATED_MOVE_FLAGS >= GEN_7, .skyBattleBanned = TRUE, - .contestEffect = CONTEST_EFFECT_BADLY_STARTLE_FRONT_MON, + .contestEffect = CONTEST_EFFECT_BETTER_IF_LAST, .contestCategory = CONTEST_CATEGORY_TOUGH, .contestComboStarterId = 0, .contestComboMoves = {0}, @@ -12405,7 +12489,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .target = MOVE_TARGET_FOES_AND_ALLY, .priority = 0, .category = DAMAGE_CATEGORY_SPECIAL, - .contestEffect = CONTEST_EFFECT_STARTLE_MONS_SAME_TYPE_APPEAL, + .contestEffect = CONTEST_EFFECT_BETTER_IF_SAME_TYPE, .contestCategory = CONTEST_CATEGORY_SMART, .contestComboStarterId = 0, .contestComboMoves = {0}, @@ -12427,10 +12511,10 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .priority = 0, .category = DAMAGE_CATEGORY_SPECIAL, .ballisticMove = TRUE, - .contestEffect = CONTEST_EFFECT_BADLY_STARTLE_FRONT_MON, + .contestEffect = CONTEST_EFFECT_BADLY_STARTLE_FRONT_MON, //CONTEST_EFFECT_EXCITES_AUDIENCE_MORE_IF_FIRST .contestCategory = CONTEST_CATEGORY_COOL, .contestComboStarterId = 0, - .contestComboMoves = {0}, + .contestComboMoves = {COMBO_STARTER_AGILITY, COMBO_STARTER_CHARGE, COMBO_STARTER_ROCK_POLISH}, .battleAnimScript = gBattleAnimMove_ElectroBall, }, @@ -12451,10 +12535,10 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .argument = { .type = TYPE_WATER }, .zMove = { .effect = Z_EFFECT_SPATK_UP_1 }, .magicCoatAffected = TRUE, - .contestEffect = CONTEST_EFFECT_WORSEN_CONDITION_OF_PREV_MONS, - .contestCategory = CONTEST_CATEGORY_SMART, + .contestEffect = CONTEST_EFFECT_STARTLE_MON_WITH_JUDGES_ATTENTION, + .contestCategory = CONTEST_CATEGORY_CUTE, .contestComboStarterId = 0, - .contestComboMoves = {0}, + .contestComboMoves = {COMBO_STARTER_RAIN_DANCE}, .battleAnimScript = gBattleAnimMove_Soak, }, @@ -12478,8 +12562,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .self = TRUE, .chance = 100, }), - .contestEffect = CONTEST_EFFECT_IMPROVE_CONDITION_PREVENT_NERVOUSNESS, - .contestCategory = CONTEST_CATEGORY_BEAUTY, + .contestEffect = CONTEST_EFFECT_BETTER_WITH_GOOD_CONDITION, + .contestCategory = CONTEST_CATEGORY_COOL, .contestComboStarterId = 0, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_FlameCharge, @@ -12504,7 +12588,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .ignoresProtect = TRUE, .mirrorMoveBanned = TRUE, .contestEffect = CONTEST_EFFECT_IMPROVE_CONDITION_PREVENT_NERVOUSNESS, - .contestCategory = CONTEST_CATEGORY_SMART, + .contestCategory = CONTEST_CATEGORY_TOUGH, .contestComboStarterId = 0, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_Coil, @@ -12529,8 +12613,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .moveEffect = MOVE_EFFECT_SPD_MINUS_1, .chance = 100, }), - .contestEffect = CONTEST_EFFECT_BADLY_STARTLE_PREV_MONS, - .contestCategory = CONTEST_CATEGORY_TOUGH, + .contestEffect = CONTEST_EFFECT_STARTLE_PREV_MON, + .contestCategory = CONTEST_CATEGORY_SMART, .contestComboStarterId = 0, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_LowSweep, @@ -12555,8 +12639,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .moveEffect = MOVE_EFFECT_SP_DEF_MINUS_2, .chance = 100, }), - .contestEffect = CONTEST_EFFECT_STARTLE_PREV_MONS, - .contestCategory = CONTEST_CATEGORY_SMART, + .contestEffect = CONTEST_EFFECT_STARTLE_MONS_SAME_TYPE_APPEAL, + .contestCategory = CONTEST_CATEGORY_BEAUTY, .contestComboStarterId = 0, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_AcidSpray, @@ -12577,8 +12661,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, .makesContact = TRUE, - .contestEffect = CONTEST_EFFECT_BADLY_STARTLE_FRONT_MON, - .contestCategory = CONTEST_CATEGORY_COOL, + .contestEffect = CONTEST_EFFECT_APPEAL_AS_GOOD_AS_PREV_ONE, + .contestCategory = CONTEST_CATEGORY_SMART, .contestComboStarterId = 0, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_FoulPlay, @@ -12590,7 +12674,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .description = COMPOUND_STRING( "向对手发送谜之念波。接收\n" "到的对手特性会变为单纯。"), - .effect = EFFECT_SIMPLE_BEAM, + .effect = EFFECT_OVERWRITE_ABILITY, .power = 0, .type = TYPE_NORMAL, .accuracy = 100, @@ -12598,9 +12682,10 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .target = MOVE_TARGET_SELECTED, .priority = 0, .category = DAMAGE_CATEGORY_STATUS, + .argument = { .overwriteAbility = ABILITY_SIMPLE }, .zMove = { .effect = Z_EFFECT_SPATK_UP_1 }, .magicCoatAffected = TRUE, - .contestEffect = CONTEST_EFFECT_APPEAL_AS_GOOD_AS_PREV_ONES, + .contestEffect = CONTEST_EFFECT_WORSEN_CONDITION_OF_PREV_MONS, .contestCategory = CONTEST_CATEGORY_CUTE, .contestComboStarterId = 0, .contestComboMoves = {0}, @@ -12623,9 +12708,9 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .category = DAMAGE_CATEGORY_STATUS, .zMove = { .effect = Z_EFFECT_SPDEF_UP_1 }, .magicCoatAffected = TRUE, - .contestEffect = CONTEST_EFFECT_STARTLE_MON_WITH_JUDGES_ATTENTION, + .contestEffect = CONTEST_EFFECT_STARTLE_MONS_SAME_TYPE_APPEAL, .contestCategory = CONTEST_CATEGORY_CUTE, - .contestComboStarterId = 0, + .contestComboStarterId = COMBO_STARTER_ENTRAINMENT, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_Entrainment, }, @@ -12675,8 +12760,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_ROUND, }), - .contestEffect = CONTEST_EFFECT_REPETITION_NOT_BORING, - .contestCategory = CONTEST_CATEGORY_CUTE, + .contestEffect = CONTEST_EFFECT_BETTER_IF_SAME_TYPE, + .contestCategory = CONTEST_CATEGORY_BEAUTY, .contestComboStarterId = 0, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_Round, @@ -12699,7 +12784,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .ignoresSubstitute = B_UPDATED_MOVE_FLAGS >= GEN_6, .soundMove = TRUE, .contestEffect = CONTEST_EFFECT_REPETITION_NOT_BORING, - .contestCategory = CONTEST_CATEGORY_CUTE, + .contestCategory = CONTEST_CATEGORY_BEAUTY, .contestComboStarterId = 0, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_EchoedVoice, @@ -12719,7 +12804,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .category = DAMAGE_CATEGORY_PHYSICAL, .makesContact = TRUE, .ignoresTargetDefenseEvasionStages = TRUE, - .contestEffect = CONTEST_EFFECT_REPETITION_NOT_BORING, + .contestEffect = CONTEST_EFFECT_EXCITE_AUDIENCE_IN_ANY_CONTEST, .contestCategory = CONTEST_CATEGORY_TOUGH, .contestComboStarterId = 0, .contestComboMoves = {0}, @@ -12743,7 +12828,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_CLEAR_SMOG, }), - .contestEffect = CONTEST_EFFECT_WORSEN_CONDITION_OF_PREV_MONS, + .contestEffect = CONTEST_EFFECT_BETTER_IF_FIRST, .contestCategory = CONTEST_CATEGORY_BEAUTY, .contestComboStarterId = 0, .contestComboMoves = {0}, @@ -12764,10 +12849,10 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .target = MOVE_TARGET_SELECTED, .priority = 0, .category = DAMAGE_CATEGORY_SPECIAL, - .contestEffect = CONTEST_EFFECT_BETTER_WHEN_LATER, - .contestCategory = CONTEST_CATEGORY_COOL, + .contestEffect = CONTEST_EFFECT_BETTER_WITH_GOOD_CONDITION, + .contestCategory = CONTEST_CATEGORY_SMART, .contestComboStarterId = 0, - .contestComboMoves = {0}, + .contestComboMoves = {COMBO_STARTER_AMNESIA, COMBO_STARTER_HONE_CLAWS, COMBO_STARTER_CALM_MIND, COMBO_STARTER_NASTY_PLOT}, .battleAnimScript = gBattleAnimMove_StoredPower, }, @@ -12791,8 +12876,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .ignoresProtect = TRUE, .mirrorMoveBanned = TRUE, .metronomeBanned = TRUE, - .contestEffect = CONTEST_EFFECT_AVOID_STARTLE_ONCE, - .contestCategory = CONTEST_CATEGORY_TOUGH, + .contestEffect = CONTEST_EFFECT_BETTER_IF_FIRST, + .contestCategory = CONTEST_CATEGORY_COOL, .contestComboStarterId = 0, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_QuickGuard, @@ -12841,7 +12926,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .moveEffect = MOVE_EFFECT_BURN, .chance = 30, }), - .contestEffect = CONTEST_EFFECT_HIGHLY_APPEALING, + .contestEffect = CONTEST_EFFECT_MAKE_FOLLOWING_MONS_NERVOUS, .contestCategory = CONTEST_CATEGORY_TOUGH, .contestComboStarterId = COMBO_STARTER_SCALD, .contestComboMoves = {0}, @@ -12866,7 +12951,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .snatchAffected = TRUE, .ignoresProtect = TRUE, .mirrorMoveBanned = TRUE, - .contestEffect = CONTEST_EFFECT_USER_MORE_EASILY_STARTLED, + .contestEffect = CONTEST_EFFECT_BETTER_IF_LAST, .contestCategory = CONTEST_CATEGORY_TOUGH, .contestComboStarterId = 0, .contestComboMoves = {0}, @@ -12892,8 +12977,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .mirrorMoveBanned = TRUE, .healingMove = TRUE, .pulseMove = TRUE, - .contestEffect = CONTEST_EFFECT_HIGHLY_APPEALING, - .contestCategory = CONTEST_CATEGORY_SMART, + .contestEffect = CONTEST_EFFECT_EXCITE_AUDIENCE_IN_ANY_CONTEST, + .contestCategory = CONTEST_CATEGORY_BEAUTY, .contestComboStarterId = 0, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_HealPulse, @@ -12915,10 +13000,10 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .category = DAMAGE_CATEGORY_SPECIAL, .zMove = { .powerOverride = 160 }, .argument = { .status = STATUS1_ANY }, - .contestEffect = CONTEST_EFFECT_BETTER_IF_SAME_TYPE, + .contestEffect = CONTEST_EFFECT_STARTLE_MONS_SAME_TYPE_APPEAL, .contestCategory = CONTEST_CATEGORY_SMART, .contestComboStarterId = 0, - .contestComboMoves = {COMBO_STARTER_TOXIC}, + .contestComboMoves = {COMBO_STARTER_TOXIC, COMBO_STARTER_FORCE_PALM, COMBO_STARTER_THUNDER_WAVE, COMBO_STARTER_INFERNO, COMBO_STARTER_WILL_O_WISP, COMBO_STARTER_LOVELY_KISS, COMBO_STARTER_SPORE, COMBO_STARTER_SING, COMBO_STARTER_YAWN, COMBO_STARTER_HYPNOSIS, COMBO_STARTER_DARK_VOID, COMBO_STARTER_GRASS_WHISTLE, COMBO_STARTER_SLEEP_POWDER, COMBO_STARTER_POISON_GAS, COMBO_STARTER_POISON_POWDER, COMBO_STARTER_TOXIC_SPIKES, COMBO_STARTER_GLARE}, .battleAnimScript = gBattleAnimMove_Hex, }, @@ -12940,12 +13025,12 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .gravityBanned = TRUE, .sleepTalkBanned = TRUE, .instructBanned = TRUE, - .assistBanned = TRUE, + .assistBanned = B_UPDATED_MOVE_FLAGS >= GEN_6, .argument.twoTurnAttack = { .stringId = STRINGID_PKMNTOOKTARGETHIGH, .status = STATE_ON_AIR }, - .contestEffect = CONTEST_EFFECT_AVOID_STARTLE, - .contestCategory = CONTEST_CATEGORY_SMART, + .contestEffect = CONTEST_EFFECT_DONT_EXCITE_AUDIENCE, + .contestCategory = CONTEST_CATEGORY_TOUGH, .contestComboStarterId = 0, - .contestComboMoves = {0}, + .contestComboMoves = {COMBO_STARTER_ENTRAINMENT, COMBO_STARTER_PLAY_NICE}, .battleAnimScript = gBattleAnimMove_SkyDrop, }, @@ -12969,7 +13054,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .mirrorMoveBanned = TRUE, .contestEffect = CONTEST_EFFECT_IMPROVE_CONDITION_PREVENT_NERVOUSNESS, .contestCategory = CONTEST_CATEGORY_SMART, - .contestComboStarterId = 0, + .contestComboStarterId = COMBO_STARTER_SHIFT_GEAR, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_ShiftGear, }, @@ -12989,10 +13074,10 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .makesContact = TRUE, .copycatBanned = TRUE, .assistBanned = TRUE, - .contestEffect = CONTEST_EFFECT_SCRAMBLE_NEXT_TURN_ORDER, - .contestCategory = CONTEST_CATEGORY_TOUGH, + .contestEffect = CONTEST_EFFECT_NEXT_APPEAL_LATER, + .contestCategory = CONTEST_CATEGORY_COOL, .contestComboStarterId = 0, - .contestComboMoves = {0}, + .contestComboMoves = {COMBO_STARTER_ENTRAINMENT, COMBO_STARTER_PLAY_NICE}, .battleAnimScript = gBattleAnimMove_CircleThrow, }, @@ -13013,8 +13098,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_INCINERATE, }), - .contestEffect = CONTEST_EFFECT_WORSEN_CONDITION_OF_PREV_MONS, - .contestCategory = CONTEST_CATEGORY_BEAUTY, + .contestEffect = CONTEST_EFFECT_SHIFT_JUDGE_ATTENTION, + .contestCategory = CONTEST_CATEGORY_TOUGH, .contestComboStarterId = 0, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_Incinerate, @@ -13036,8 +13121,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .category = DAMAGE_CATEGORY_STATUS, .zMove = { .effect = Z_EFFECT_SPD_UP_1 }, .metronomeBanned = TRUE, - .contestEffect = CONTEST_EFFECT_NEXT_APPEAL_LATER, - .contestCategory = CONTEST_CATEGORY_COOL, + .contestEffect = CONTEST_EFFECT_NEXT_APPEAL_EARLIER, + .contestCategory = CONTEST_CATEGORY_SMART, .contestComboStarterId = 0, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_Quash, @@ -13058,7 +13143,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, .makesContact = TRUE, - .contestEffect = CONTEST_EFFECT_BETTER_IF_SAME_TYPE, + .contestEffect = CONTEST_EFFECT_BETTER_WITH_GOOD_CONDITION, .contestCategory = CONTEST_CATEGORY_COOL, .contestComboStarterId = 0, .contestComboMoves = {0}, @@ -13082,7 +13167,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .zMove = { .effect = Z_EFFECT_SPATK_UP_1 }, .ignoresSubstitute = TRUE, .mirrorMoveBanned = TRUE, - .contestEffect = CONTEST_EFFECT_AFFECTED_BY_PREV_APPEAL, + .contestEffect = CONTEST_EFFECT_BETTER_IF_SAME_TYPE, .contestCategory = CONTEST_CATEGORY_SMART, .contestComboStarterId = 0, .contestComboMoves = {0}, @@ -13104,8 +13189,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, .makesContact = TRUE, - .contestEffect = CONTEST_EFFECT_NEXT_APPEAL_LATER, - .contestCategory = CONTEST_CATEGORY_TOUGH, + .contestEffect = CONTEST_EFFECT_AFFECTED_BY_PREV_APPEAL, + .contestCategory = CONTEST_CATEGORY_COOL, .contestComboStarterId = 0, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_Retaliate, @@ -13154,10 +13239,10 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .metronomeBanned = TRUE, .copycatBanned = TRUE, .assistBanned = TRUE, - .contestEffect = CONTEST_EFFECT_MAKE_FOLLOWING_MONS_NERVOUS, + .contestEffect = CONTEST_EFFECT_BETTER_WHEN_AUDIENCE_EXCITED, .contestCategory = CONTEST_CATEGORY_CUTE, .contestComboStarterId = 0, - .contestComboMoves = {0}, + .contestComboMoves = {COMBO_STARTER_CELEBRATE, COMBO_STARTER_COVET, COMBO_STARTER_HAPPY_HOUR, COMBO_STARTER_WISH}, .battleAnimScript = gBattleAnimMove_Bestow, }, @@ -13179,9 +13264,9 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .moveEffect = MOVE_EFFECT_BURN, .chance = 100, }), - .contestEffect = CONTEST_EFFECT_HIGHLY_APPEALING, + .contestEffect = CONTEST_EFFECT_BADLY_STARTLE_FRONT_MON, .contestCategory = CONTEST_CATEGORY_BEAUTY, - .contestComboStarterId = 0, + .contestComboStarterId = COMBO_STARTER_INFERNO, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_Inferno, }, @@ -13201,8 +13286,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .priority = 0, .category = DAMAGE_CATEGORY_SPECIAL, .skyBattleBanned = TRUE, - .contestEffect = CONTEST_EFFECT_HIGHLY_APPEALING, - .contestCategory = CONTEST_CATEGORY_CUTE, + .contestEffect = CONTEST_EFFECT_EXCITE_AUDIENCE_IN_ANY_CONTEST, + .contestCategory = CONTEST_CATEGORY_BEAUTY, .contestComboStarterId = 0, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_WaterPledge, @@ -13223,7 +13308,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .priority = 0, .category = DAMAGE_CATEGORY_SPECIAL, .skyBattleBanned = TRUE, - .contestEffect = CONTEST_EFFECT_HIGHLY_APPEALING, + .contestEffect = CONTEST_EFFECT_EXCITE_AUDIENCE_IN_ANY_CONTEST, .contestCategory = CONTEST_CATEGORY_BEAUTY, .contestComboStarterId = 0, .contestComboMoves = {0}, @@ -13245,8 +13330,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .priority = 0, .category = DAMAGE_CATEGORY_SPECIAL, .skyBattleBanned = TRUE, - .contestEffect = CONTEST_EFFECT_HIGHLY_APPEALING, - .contestCategory = CONTEST_CATEGORY_SMART, + .contestEffect = CONTEST_EFFECT_EXCITE_AUDIENCE_IN_ANY_CONTEST, + .contestCategory = CONTEST_CATEGORY_BEAUTY, .contestComboStarterId = 0, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_GrassPledge, @@ -13264,9 +13349,9 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .target = MOVE_TARGET_SELECTED, .priority = 0, .category = DAMAGE_CATEGORY_SPECIAL, - .contestEffect = CONTEST_EFFECT_AVOID_STARTLE, + .contestEffect = CONTEST_EFFECT_AVOID_STARTLE, //CONTEST_EFFECT_QUICKLY_GROW_BORED .contestCategory = CONTEST_CATEGORY_COOL, - .contestComboStarterId = 0, + .contestComboStarterId = COMBO_STARTER_CHARGE, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_VoltSwitch, }, @@ -13289,8 +13374,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .moveEffect = MOVE_EFFECT_SP_ATK_MINUS_1, .chance = 100, }), - .contestEffect = CONTEST_EFFECT_BADLY_STARTLE_PREV_MONS, - .contestCategory = CONTEST_CATEGORY_TOUGH, + .contestEffect = CONTEST_EFFECT_BETTER_IF_LAST, + .contestCategory = CONTEST_CATEGORY_CUTE, .contestComboStarterId = 0, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_StruggleBug, @@ -13315,7 +13400,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .moveEffect = MOVE_EFFECT_SPD_MINUS_1, .chance = 100, }), - .contestEffect = CONTEST_EFFECT_BADLY_STARTLE_PREV_MONS, + .contestEffect = CONTEST_EFFECT_STARTLE_PREV_MONS, .contestCategory = CONTEST_CATEGORY_TOUGH, .contestComboStarterId = 0, .contestComboMoves = {0}, @@ -13335,7 +13420,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .priority = 0, .category = DAMAGE_CATEGORY_SPECIAL, .alwaysCriticalHit = TRUE, - .contestEffect = CONTEST_EFFECT_AFFECTED_BY_PREV_APPEAL, + .contestEffect = CONTEST_EFFECT_AFFECTED_BY_PREV_APPEAL, //CONTEST_EFFECT_QUICKLY_GROW_BORED .contestCategory = CONTEST_CATEGORY_BEAUTY, .contestComboStarterId = 0, .contestComboMoves = {0}, @@ -13357,10 +13442,10 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .makesContact = TRUE, .copycatBanned = TRUE, .assistBanned = TRUE, - .contestEffect = CONTEST_EFFECT_SCRAMBLE_NEXT_TURN_ORDER, - .contestCategory = CONTEST_CATEGORY_COOL, + .contestEffect = CONTEST_EFFECT_NEXT_APPEAL_LATER, + .contestCategory = CONTEST_CATEGORY_TOUGH, .contestComboStarterId = COMBO_STARTER_DRAGON_TAIL, - .contestComboMoves = {COMBO_STARTER_DRAGON_BREATH, COMBO_STARTER_DRAGON_DANCE, COMBO_STARTER_DRAGON_RAGE, COMBO_STARTER_DRAGON_RUSH}, + .contestComboMoves = {COMBO_STARTER_DRAGON_BREATH, COMBO_STARTER_DRAGON_DANCE, COMBO_STARTER_DRAGON_RAGE, COMBO_STARTER_DRAGON_RUSH, COMBO_STARTER_STEALTH_ROCK, COMBO_STARTER_SPIKES, COMBO_STARTER_TOXIC_SPIKES}, .battleAnimScript = gBattleAnimMove_DragonTail, }, @@ -13382,8 +13467,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .snatchAffected = TRUE, .ignoresProtect = TRUE, .mirrorMoveBanned = TRUE, - .contestEffect = CONTEST_EFFECT_IMPROVE_CONDITION_PREVENT_NERVOUSNESS, - .contestCategory = CONTEST_CATEGORY_BEAUTY, + .contestEffect = CONTEST_EFFECT_IMPROVE_CONDITION_PREVENT_NERVOUSNESS, //CONTEST_EFFECT_EXCITES_AUDIENCE_MORE_IF_FIRST + .contestCategory = CONTEST_CATEGORY_TOUGH, .contestComboStarterId = 0, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_WorkUp, @@ -13407,10 +13492,10 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .moveEffect = MOVE_EFFECT_SPD_MINUS_1, .chance = 100, }), - .contestEffect = CONTEST_EFFECT_BADLY_STARTLE_PREV_MONS, - .contestCategory = CONTEST_CATEGORY_SMART, + .contestEffect = CONTEST_EFFECT_STARTLE_MON_WITH_JUDGES_ATTENTION, + .contestCategory = CONTEST_CATEGORY_BEAUTY, .contestComboStarterId = 0, - .contestComboMoves = {0}, + .contestComboMoves = {COMBO_STARTER_STRING_SHOT}, .battleAnimScript = gBattleAnimMove_Electroweb, }, @@ -13431,7 +13516,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .argument = { .recoilPercentage = 25 }, .makesContact = TRUE, .contestEffect = CONTEST_EFFECT_USER_MORE_EASILY_STARTLED, - .contestCategory = CONTEST_CATEGORY_COOL, + .contestCategory = CONTEST_CATEGORY_TOUGH, .contestComboStarterId = 0, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_WildCharge, @@ -13447,7 +13532,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .power = 80, .type = TYPE_GROUND, .accuracy = 95, - .criticalHitStage = 1, + .criticalHitStage = B_UPDATED_MOVE_DATA >= GEN_3 ? 1 : 2, .pp = 10, .target = MOVE_TARGET_SELECTED, .priority = 0, @@ -13456,7 +13541,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .contestEffect = CONTEST_EFFECT_AFFECTED_BY_PREV_APPEAL, .contestCategory = CONTEST_CATEGORY_TOUGH, .contestComboStarterId = 0, - .contestComboMoves = {0}, + .contestComboMoves = {COMBO_STARTER_FOCUS_ENERGY}, .battleAnimScript = gBattleAnimMove_DrillRun, }, @@ -13476,7 +13561,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .category = DAMAGE_CATEGORY_PHYSICAL, .makesContact = TRUE, .strikeCount = 2, - .contestEffect = CONTEST_EFFECT_REPETITION_NOT_BORING, + .contestEffect = CONTEST_EFFECT_STARTLE_MONS_SAME_TYPE_APPEAL, .contestCategory = CONTEST_CATEGORY_TOUGH, .contestComboStarterId = 0, .contestComboMoves = {0}, @@ -13502,7 +13587,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .moveEffect = MOVE_EFFECT_FLINCH, .chance = 30, }), - .contestEffect = CONTEST_EFFECT_MAKE_FOLLOWING_MONS_NERVOUS, + .contestEffect = CONTEST_EFFECT_REPETITION_NOT_BORING, .contestCategory = CONTEST_CATEGORY_CUTE, .contestComboStarterId = 0, .contestComboMoves = {0}, @@ -13524,8 +13609,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .argument = { .absorbPercentage = 50 }, .makesContact = TRUE, .healingMove = B_HEAL_BLOCKING >= GEN_6, - .contestEffect = CONTEST_EFFECT_STARTLE_MON_WITH_JUDGES_ATTENTION, - .contestCategory = CONTEST_CATEGORY_SMART, + .contestEffect = CONTEST_EFFECT_APPEAL_AS_GOOD_AS_PREV_ONE, + .contestCategory = CONTEST_CATEGORY_TOUGH, .contestComboStarterId = 0, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_HornLeech, @@ -13546,8 +13631,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .makesContact = TRUE, .ignoresTargetDefenseEvasionStages = TRUE, .slicingMove = TRUE, - .contestEffect = CONTEST_EFFECT_BADLY_STARTLE_MONS_WITH_GOOD_APPEALS, - .contestCategory = CONTEST_CATEGORY_TOUGH, + .contestEffect = CONTEST_EFFECT_EXCITE_AUDIENCE_IN_ANY_CONTEST, + .contestCategory = CONTEST_CATEGORY_COOL, .contestComboStarterId = 0, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_SacredSword, @@ -13573,8 +13658,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .moveEffect = MOVE_EFFECT_DEF_MINUS_1, .chance = 50, }), - .contestEffect = CONTEST_EFFECT_HIGHLY_APPEALING, - .contestCategory = CONTEST_CATEGORY_CUTE, + .contestEffect = CONTEST_EFFECT_REPETITION_NOT_BORING, + .contestCategory = CONTEST_CATEGORY_COOL, .contestComboStarterId = 0, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_RazorShell, @@ -13594,8 +13679,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .category = DAMAGE_CATEGORY_PHYSICAL, .makesContact = TRUE, .minimizeDoubleDamage = B_UPDATED_MOVE_FLAGS >= GEN_6, - .contestEffect = CONTEST_EFFECT_BADLY_STARTLE_FRONT_MON, - .contestCategory = CONTEST_CATEGORY_BEAUTY, + .contestEffect = CONTEST_EFFECT_BETTER_IF_LAST, + .contestCategory = CONTEST_CATEGORY_TOUGH, .contestComboStarterId = 0, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_HeatCrash, @@ -13619,8 +13704,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .moveEffect = MOVE_EFFECT_ACC_MINUS_1, .chance = 50, }), - .contestEffect = CONTEST_EFFECT_STARTLE_MON_WITH_JUDGES_ATTENTION, - .contestCategory = CONTEST_CATEGORY_SMART, + .contestEffect = CONTEST_EFFECT_REPETITION_NOT_BORING, + .contestCategory = CONTEST_CATEGORY_COOL, .contestComboStarterId = 0, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_LeafTornado, @@ -13646,7 +13731,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .moveEffect = MOVE_EFFECT_FLINCH, .chance = 30, }), - .contestEffect = CONTEST_EFFECT_BADLY_STARTLE_FRONT_MON, + .contestEffect = CONTEST_EFFECT_REPETITION_NOT_BORING, .contestCategory = CONTEST_CATEGORY_TOUGH, .contestComboStarterId = 0, .contestComboMoves = {0}, @@ -13672,7 +13757,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .ignoresProtect = TRUE, .mirrorMoveBanned = TRUE, .contestEffect = CONTEST_EFFECT_AVOID_STARTLE, - .contestCategory = CONTEST_CATEGORY_SMART, + .contestCategory = CONTEST_CATEGORY_CUTE, .contestComboStarterId = 0, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_CottonGuard, @@ -13696,7 +13781,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .moveEffect = MOVE_EFFECT_ACC_MINUS_1, .chance = 40, }), - .contestEffect = CONTEST_EFFECT_STARTLE_MON_WITH_JUDGES_ATTENTION, + .contestEffect = CONTEST_EFFECT_REPETITION_NOT_BORING, .contestCategory = CONTEST_CATEGORY_COOL, .contestComboStarterId = 0, .contestComboMoves = {0}, @@ -13715,8 +13800,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .target = MOVE_TARGET_SELECTED, .priority = 0, .category = DAMAGE_CATEGORY_SPECIAL, - .contestEffect = CONTEST_EFFECT_BETTER_IF_SAME_TYPE, - .contestCategory = CONTEST_CATEGORY_SMART, + .contestEffect = CONTEST_EFFECT_REPETITION_NOT_BORING, + .contestCategory = CONTEST_CATEGORY_COOL, .contestComboStarterId = 0, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_Psystrike, @@ -13737,7 +13822,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, .makesContact = TRUE, - .contestEffect = CONTEST_EFFECT_BETTER_IF_SAME_TYPE, + .contestEffect = CONTEST_EFFECT_QUALITY_DEPENDS_ON_TIMING, .contestCategory = CONTEST_CATEGORY_CUTE, .contestComboStarterId = 0, .contestComboMoves = {0}, @@ -13766,10 +13851,10 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .moveEffect = MOVE_EFFECT_CONFUSION, .chance = 30, }), - .contestEffect = CONTEST_EFFECT_STARTLE_PREV_MONS, - .contestCategory = CONTEST_CATEGORY_COOL, + .contestEffect = CONTEST_EFFECT_BADLY_STARTLE_MONS_WITH_GOOD_APPEALS, + .contestCategory = CONTEST_CATEGORY_TOUGH, .contestComboStarterId = 0, - .contestComboMoves = {0}, + .contestComboMoves = {COMBO_STARTER_RAIN_DANCE}, .battleAnimScript = gBattleAnimMove_Hurricane, }, @@ -13813,10 +13898,10 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .zMove = { .powerOverride = 180 }, .makesContact = TRUE, .strikeCount = 2, - .contestEffect = CONTEST_EFFECT_REPETITION_NOT_BORING, - .contestCategory = CONTEST_CATEGORY_TOUGH, + .contestEffect = CONTEST_EFFECT_HIGHLY_APPEALING, + .contestCategory = CONTEST_CATEGORY_SMART, .contestComboStarterId = 0, - .contestComboMoves = {0}, + .contestComboMoves = {COMBO_STARTER_SHIFT_GEAR}, .battleAnimScript = gBattleAnimMove_GearGrind, }, @@ -13837,8 +13922,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .moveEffect = MOVE_EFFECT_BURN, .chance = 30, }), - .contestEffect = CONTEST_EFFECT_HIGHLY_APPEALING, - .contestCategory = CONTEST_CATEGORY_BEAUTY, + .contestEffect = CONTEST_EFFECT_REPETITION_NOT_BORING, + .contestCategory = CONTEST_CATEGORY_COOL, .contestComboStarterId = 0, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_SearingShot, @@ -13860,7 +13945,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .category = DAMAGE_CATEGORY_SPECIAL, .argument = { .holdEffect = HOLD_EFFECT_DRIVE }, .metronomeBanned = TRUE, - .contestEffect = CONTEST_EFFECT_EXCITE_AUDIENCE_IN_ANY_CONTEST, + .contestEffect = CONTEST_EFFECT_BETTER_WITH_GOOD_CONDITION, .contestCategory = CONTEST_CATEGORY_COOL, .contestComboStarterId = 0, .contestComboMoves = {0}, @@ -13889,8 +13974,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .moveEffect = MOVE_EFFECT_SLEEP, .chance = 10, }), - .contestEffect = CONTEST_EFFECT_BADLY_STARTLE_PREV_MONS, - .contestCategory = CONTEST_CATEGORY_SMART, + .contestEffect = CONTEST_EFFECT_MAKE_FOLLOWING_MONS_NERVOUS, + .contestCategory = CONTEST_CATEGORY_BEAUTIFUL, .contestComboStarterId = 0, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_RelicSong, @@ -13912,8 +13997,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .category = DAMAGE_CATEGORY_SPECIAL, .slicingMove = TRUE, .metronomeBanned = TRUE, - .contestEffect = CONTEST_EFFECT_BETTER_IF_SAME_TYPE, - .contestCategory = CONTEST_CATEGORY_SMART, + .contestEffect = CONTEST_EFFECT_REPETITION_NOT_BORING, + .contestCategory = CONTEST_CATEGORY_BEAUTIFUL, .contestComboStarterId = 0, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_SecretSword, @@ -13937,10 +14022,10 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .moveEffect = MOVE_EFFECT_SPD_MINUS_1, .chance = 100, }), - .contestEffect = CONTEST_EFFECT_STARTLE_PREV_MONS, + .contestEffect = CONTEST_EFFECT_DONT_EXCITE_AUDIENCE, .contestCategory = CONTEST_CATEGORY_BEAUTY, .contestComboStarterId = 0, - .contestComboMoves = {0}, + .contestComboMoves = {COMBO_STARTER_HAIL}, .battleAnimScript = gBattleAnimMove_Glaciate, }, @@ -13963,8 +14048,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .moveEffect = MOVE_EFFECT_PARALYSIS, .chance = 20, }), - .contestEffect = CONTEST_EFFECT_HIGHLY_APPEALING, - .contestCategory = CONTEST_CATEGORY_COOL, + .contestEffect = CONTEST_EFFECT_REPETITION_NOT_BORING, + .contestCategory = CONTEST_CATEGORY_BEAUTY, .contestComboStarterId = 0, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_BoltStrike, @@ -13988,7 +14073,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .moveEffect = MOVE_EFFECT_BURN, .chance = 20, }), - .contestEffect = CONTEST_EFFECT_HIGHLY_APPEALING, + .contestEffect = CONTEST_EFFECT_REPETITION_NOT_BORING, .contestCategory = CONTEST_CATEGORY_BEAUTY, .contestComboStarterId = 0, .contestComboMoves = {0}, @@ -14015,7 +14100,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .self = TRUE, .chance = 50, }), - .contestEffect = CONTEST_EFFECT_IMPROVE_CONDITION_PREVENT_NERVOUSNESS, + .contestEffect = CONTEST_EFFECT_BETTER_WITH_GOOD_CONDITION, .contestCategory = CONTEST_CATEGORY_BEAUTY, .contestComboStarterId = 0, .contestComboMoves = {0}, @@ -14044,7 +14129,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .moveEffect = MOVE_EFFECT_PARALYSIS, .chance = 30, }), - .contestEffect = CONTEST_EFFECT_STARTLE_PREV_MONS, + .contestEffect = CONTEST_EFFECT_AFFECTED_BY_PREV_APPEAL, .contestCategory = CONTEST_CATEGORY_BEAUTY, .contestComboStarterId = 0, .contestComboMoves = {0}, @@ -14101,8 +14186,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .moveEffect = MOVE_EFFECT_SP_ATK_MINUS_1, .chance = 100, }), - .contestEffect = CONTEST_EFFECT_BADLY_STARTLE_PREV_MONS, - .contestCategory = CONTEST_CATEGORY_COOL, + .contestEffect = CONTEST_EFFECT_BADLY_STARTLE_PREV_MONS, //CONTEST_EFFECT_QUICKLY_GROW_BORED + .contestCategory = CONTEST_CATEGORY_TOUGH, .contestComboStarterId = 0, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_Snarl, @@ -14126,10 +14211,10 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .moveEffect = MOVE_EFFECT_FLINCH, .chance = 30, }), - .contestEffect = CONTEST_EFFECT_STARTLE_PREV_MON, + .contestEffect = CONTEST_EFFECT_BETTER_IF_LAST, .contestCategory = CONTEST_CATEGORY_BEAUTY, .contestComboStarterId = 0, - .contestComboMoves = {0}, + .contestComboMoves = {COMBO_STARTER_HAIL}, .battleAnimScript = gBattleAnimMove_IcicleCrash, }, @@ -14176,7 +14261,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .priority = 0, .category = DAMAGE_CATEGORY_SPECIAL, .thawsUser = TRUE, - .contestEffect = CONTEST_EFFECT_USER_MORE_EASILY_STARTLED, + .contestEffect = CONTEST_EFFECT_BETTER_WHEN_LATER, .contestCategory = CONTEST_CATEGORY_BEAUTY, .contestComboStarterId = 0, .contestComboMoves = {0}, @@ -14197,7 +14282,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .target = MOVE_TARGET_SELECTED, .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, - .contestEffect = CONTEST_EFFECT_USER_MORE_EASILY_STARTLED, + .contestEffect = CONTEST_EFFECT_BETTER_WHEN_LATER, .contestCategory = CONTEST_CATEGORY_COOL, .contestComboStarterId = 0, .contestComboMoves = {0}, @@ -14224,8 +14309,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .minimizeDoubleDamage = TRUE, .gravityBanned = TRUE, .skyBattleBanned = TRUE, - .contestEffect = CONTEST_EFFECT_HIGHLY_APPEALING, - .contestCategory = CONTEST_CATEGORY_COOL, + .contestEffect = CONTEST_EFFECT_EXCITE_AUDIENCE_IN_ANY_CONTEST, + .contestCategory = CONTEST_CATEGORY_TOUGH, .contestComboStarterId = 0, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_FlyingPress, @@ -14254,7 +14339,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .copycatBanned = TRUE, .assistBanned = TRUE, .skyBattleBanned = TRUE, - .contestEffect = CONTEST_EFFECT_AVOID_STARTLE, + .contestEffect = CONTEST_EFFECT_STARTLE_PREV_MONS, .contestCategory = CONTEST_CATEGORY_COOL, .contestComboStarterId = 0, .contestComboMoves = {0}, @@ -14283,8 +14368,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .sleepTalkBanned = TRUE, .instructBanned = TRUE, .assistBanned = TRUE, - .contestEffect = CONTEST_EFFECT_HIGHLY_APPEALING, - .contestCategory = CONTEST_CATEGORY_SMART, + .contestEffect = CONTEST_EFFECT_BETTER_WITH_GOOD_CONDITION, + .contestCategory = CONTEST_CATEGORY_TOUGH, .contestComboStarterId = 0, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_Belch, @@ -14310,7 +14395,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .skyBattleBanned = TRUE, .contestEffect = CONTEST_EFFECT_IMPROVE_CONDITION_PREVENT_NERVOUSNESS, .contestCategory = CONTEST_CATEGORY_TOUGH, - .contestComboStarterId = 0, + .contestComboStarterId = COMBO_STARTER_ROTOTILLER, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_Rototiller, }, @@ -14334,10 +14419,10 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .mirrorMoveBanned = TRUE, .magicCoatAffected = TRUE, .skyBattleBanned = TRUE, - .contestEffect = CONTEST_EFFECT_MAKE_FOLLOWING_MONS_NERVOUS, - .contestCategory = CONTEST_CATEGORY_SMART, + .contestEffect = CONTEST_EFFECT_STARTLE_MON_WITH_JUDGES_ATTENTION, + .contestCategory = CONTEST_CATEGORY_TOUGH, .contestComboStarterId = 0, - .contestComboMoves = {0}, + .contestComboMoves = {COMBO_STARTER_STRING_SHOT}, .battleAnimScript = gBattleAnimMove_StickyWeb, }, @@ -14356,8 +14441,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, .makesContact = TRUE, - .contestEffect = CONTEST_EFFECT_BETTER_IF_LAST, - .contestCategory = CONTEST_CATEGORY_TOUGH, + .contestEffect = CONTEST_EFFECT_BETTER_WHEN_AUDIENCE_EXCITED, + .contestCategory = CONTEST_CATEGORY_COOL, .contestComboStarterId = 0, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_FellStinger, @@ -14377,7 +14462,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .category = DAMAGE_CATEGORY_PHYSICAL, .ignoresProtect = TRUE, .makesContact = TRUE, - .minimizeDoubleDamage = B_UPDATED_MOVE_FLAGS == GEN_6, + .minimizeDoubleDamage = B_UPDATED_MOVE_FLAGS < GEN_7, .sleepTalkBanned = TRUE, .instructBanned = TRUE, .assistBanned = TRUE, @@ -14385,8 +14470,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_FEINT, }), - .contestEffect = CONTEST_EFFECT_AVOID_STARTLE_ONCE, - .contestCategory = CONTEST_CATEGORY_SMART, + .contestEffect = CONTEST_EFFECT_AVOID_STARTLE, + .contestCategory = CONTEST_CATEGORY_COOL, .contestComboStarterId = 0, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_PhantomForce, @@ -14409,8 +14494,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .argument = { .type = TYPE_GHOST }, .zMove = { .effect = Z_EFFECT_ALL_STATS_UP_1 }, .magicCoatAffected = TRUE, - .contestEffect = CONTEST_EFFECT_WORSEN_CONDITION_OF_PREV_MONS, - .contestCategory = CONTEST_CATEGORY_SMART, + .contestEffect = CONTEST_EFFECT_STARTLE_MONS_SAME_TYPE_APPEAL, + .contestCategory = CONTEST_CATEGORY_CUTE, .contestComboStarterId = 0, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_TrickOrTreat, @@ -14434,8 +14519,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .ignoresSubstitute = B_UPDATED_MOVE_FLAGS >= GEN_6, .magicCoatAffected = TRUE, .soundMove = TRUE, - .contestEffect = CONTEST_EFFECT_BETTER_IF_LAST, - .contestCategory = CONTEST_CATEGORY_COOL, + .contestEffect = CONTEST_EFFECT_BETTER_IF_FIRST, + .contestCategory = CONTEST_CATEGORY_TOUGH, .contestComboStarterId = 0, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_NobleRoar, @@ -14458,7 +14543,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .zMove = { .effect = Z_EFFECT_SPATK_UP_1 }, .ignoresProtect = TRUE, .mirrorMoveBanned = TRUE, - .contestEffect = CONTEST_EFFECT_WORSEN_CONDITION_OF_PREV_MONS, + .contestEffect = CONTEST_EFFECT_DONT_EXCITE_AUDIENCE, .contestCategory = CONTEST_CATEGORY_BEAUTY, .contestComboStarterId = 0, .contestComboMoves = {0}, @@ -14481,10 +14566,10 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .category = DAMAGE_CATEGORY_SPECIAL, .argument = { .absorbPercentage = 50 }, .healingMove = B_HEAL_BLOCKING >= GEN_6, - .contestEffect = CONTEST_EFFECT_STARTLE_MON_WITH_JUDGES_ATTENTION, - .contestCategory = CONTEST_CATEGORY_BEAUTY, - .contestComboStarterId = 0, - .contestComboMoves = {0}, + .contestEffect = CONTEST_EFFECT_APPEAL_AS_GOOD_AS_PREV_ONES, + .contestCategory = CONTEST_CATEGORY_SMART, + .contestComboStarterId = COMBO_STARTER_PARABOLIC_CHARGE, + .contestComboMoves = {COMBO_STARTER_CHARGE}, .battleAnimScript = gBattleAnimMove_ParabolicCharge, }, @@ -14505,7 +14590,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .argument = { .type = TYPE_GRASS }, .zMove = { .effect = Z_EFFECT_ALL_STATS_UP_1 }, .magicCoatAffected = TRUE, - .contestEffect = CONTEST_EFFECT_WORSEN_CONDITION_OF_PREV_MONS, + .contestEffect = CONTEST_EFFECT_BADLY_STARTLE_MONS_WITH_GOOD_APPEALS, .contestCategory = CONTEST_CATEGORY_SMART, .contestComboStarterId = 0, .contestComboMoves = {0}, @@ -14527,7 +14612,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, .windMove = TRUE, - .contestEffect = CONTEST_EFFECT_AFFECTED_BY_PREV_APPEAL, + .contestEffect = CONTEST_EFFECT_STARTLE_PREV_MONS, .contestCategory = CONTEST_CATEGORY_BEAUTY, .contestComboStarterId = 0, .contestComboMoves = {0}, @@ -14553,7 +14638,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .moveEffect = MOVE_EFFECT_FREEZE_OR_FROSTBITE, .chance = 10, }), - .contestEffect = CONTEST_EFFECT_STARTLE_MONS_SAME_TYPE_APPEAL, + .contestEffect = CONTEST_EFFECT_REPETITION_NOT_BORING, .contestCategory = CONTEST_CATEGORY_BEAUTY, .contestComboStarterId = 0, .contestComboMoves = {0}, @@ -14601,8 +14686,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .magicCoatAffected = TRUE, .ignoresSubstitute = B_UPDATED_MOVE_FLAGS >= GEN_6, .soundMove = TRUE, - .contestEffect = CONTEST_EFFECT_AVOID_STARTLE, - .contestCategory = CONTEST_CATEGORY_TOUGH, + .contestEffect = CONTEST_EFFECT_AVOID_STARTLE, //CONTEST_EFFECT_EXCITES_AUDIENCE_MORE_IF_LAST + .contestCategory = CONTEST_CATEGORY_COOL, .contestComboStarterId = 0, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_PartingShot, @@ -14624,8 +14709,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .category = DAMAGE_CATEGORY_STATUS, .zMove = { .effect = Z_EFFECT_ATK_UP_1 }, .magicCoatAffected = TRUE, - .contestEffect = CONTEST_EFFECT_MAKE_FOLLOWING_MONS_NERVOUS, - .contestCategory = CONTEST_CATEGORY_CUTE, + .contestEffect = CONTEST_EFFECT_SCRAMBLE_NEXT_TURN_ORDER, + .contestCategory = CONTEST_CATEGORY_SMART, .contestComboStarterId = 0, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_TopsyTurvy, @@ -14646,7 +14731,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .argument = { .absorbPercentage = 75 }, .makesContact = TRUE, .healingMove = B_HEAL_BLOCKING >= GEN_6, - .contestEffect = CONTEST_EFFECT_STARTLE_MON_WITH_JUDGES_ATTENTION, + .contestEffect = CONTEST_EFFECT_APPEAL_AS_GOOD_AS_PREV_ONES, .contestCategory = CONTEST_CATEGORY_CUTE, .contestComboStarterId = 0, .contestComboMoves = {0}, @@ -14672,7 +14757,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .ignoresProtect = TRUE, .mirrorMoveBanned = TRUE, .metronomeBanned = TRUE, - .contestEffect = CONTEST_EFFECT_AVOID_STARTLE_ONCE, + .contestEffect = CONTEST_EFFECT_BETTER_IF_FIRST, .contestCategory = CONTEST_CATEGORY_SMART, .contestComboStarterId = 0, .contestComboMoves = {0}, @@ -14697,7 +14782,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .ignoresProtect = TRUE, .mirrorMoveBanned = TRUE, .contestEffect = CONTEST_EFFECT_AVOID_STARTLE, - .contestCategory = CONTEST_CATEGORY_CUTE, + .contestCategory = CONTEST_CATEGORY_BEAUTY, .contestComboStarterId = 0, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_FlowerShield, @@ -14721,8 +14806,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .ignoresProtect = TRUE, .mirrorMoveBanned = TRUE, .skyBattleBanned = TRUE, - .contestEffect = CONTEST_EFFECT_BETTER_WHEN_AUDIENCE_EXCITED, - .contestCategory = CONTEST_CATEGORY_SMART, + .contestEffect = CONTEST_EFFECT_BETTER_WHEN_AUDIENCE_EXCITED, //CONTEST_EFFECT_EXCITES_AUDIENCE_MORE_IF_FIRST + .contestCategory = CONTEST_CATEGORY_BEAUTY, .contestComboStarterId = COMBO_STARTER_GRASSY_TERRAIN, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_GrassyTerrain, @@ -14746,8 +14831,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .ignoresProtect = TRUE, .mirrorMoveBanned = TRUE, .skyBattleBanned = TRUE, - .contestEffect = CONTEST_EFFECT_BETTER_WHEN_AUDIENCE_EXCITED, - .contestCategory = CONTEST_CATEGORY_CUTE, + .contestEffect = CONTEST_EFFECT_BETTER_WHEN_AUDIENCE_EXCITED, //CONTEST_EFFECT_EXCITES_AUDIENCE_MORE_IF_FIRST + .contestCategory = CONTEST_CATEGORY_BEAUTY, .contestComboStarterId = COMBO_STARTER_MISTY_TERRAIN, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_MistyTerrain, @@ -14768,10 +14853,10 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .priority = 0, .category = DAMAGE_CATEGORY_STATUS, .zMove = { .effect = Z_EFFECT_SPATK_UP_1 }, - .contestEffect = CONTEST_EFFECT_BETTER_WHEN_AUDIENCE_EXCITED, - .contestCategory = CONTEST_CATEGORY_COOL, + .contestEffect = CONTEST_EFFECT_STARTLE_MONS_SAME_TYPE_APPEAL, + .contestCategory = CONTEST_CATEGORY_SMART, .contestComboStarterId = 0, - .contestComboMoves = {0}, + .contestComboMoves = {COMBO_STARTER_PARABOLIC_CHARGE}, .battleAnimScript = gBattleAnimMove_Electrify, }, @@ -14794,8 +14879,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .moveEffect = MOVE_EFFECT_ATK_MINUS_1, .chance = 10, }), - .contestEffect = CONTEST_EFFECT_HIGHLY_APPEALING, - .contestCategory = CONTEST_CATEGORY_TOUGH, + .contestEffect = CONTEST_EFFECT_WORSEN_CONDITION_OF_PREV_MONS, + .contestCategory = CONTEST_CATEGORY_CUTE, .contestComboStarterId = 0, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_PlayRough, @@ -14817,7 +14902,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .category = DAMAGE_CATEGORY_SPECIAL, .windMove = TRUE, .contestEffect = CONTEST_EFFECT_HIGHLY_APPEALING, - .contestCategory = CONTEST_CATEGORY_CUTE, + .contestCategory = CONTEST_CATEGORY_BEAUTY, .contestComboStarterId = 0, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_FairyWind, @@ -14841,8 +14926,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .moveEffect = MOVE_EFFECT_SP_ATK_MINUS_1, .chance = 30, }), - .contestEffect = CONTEST_EFFECT_HIGHLY_APPEALING, - .contestCategory = CONTEST_CATEGORY_CUTE, + .contestEffect = CONTEST_EFFECT_BADLY_STARTLE_FRONT_MON, + .contestCategory = CONTEST_CATEGORY_BEAUTY, .contestComboStarterId = 0, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_Moonblast, @@ -14864,8 +14949,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .category = DAMAGE_CATEGORY_SPECIAL, .ignoresSubstitute = B_UPDATED_MOVE_FLAGS >= GEN_6, .soundMove = TRUE, - .contestEffect = CONTEST_EFFECT_USER_MORE_EASILY_STARTLED, - .contestCategory = CONTEST_CATEGORY_COOL, + .contestEffect = CONTEST_EFFECT_JAMS_OTHERS_BUT_MISS_ONE_TURN, + .contestCategory = CONTEST_CATEGORY_TOUGH, .contestComboStarterId = 0, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_Boomburst, @@ -14888,8 +14973,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .zMove = { .effect = Z_EFFECT_DEF_UP_1 }, .ignoresProtect = TRUE, .ignoresSubstitute = TRUE, - .contestEffect = CONTEST_EFFECT_MAKE_FOLLOWING_MONS_NERVOUS, - .contestCategory = CONTEST_CATEGORY_CUTE, + .contestEffect = CONTEST_EFFECT_DONT_EXCITE_AUDIENCE, + .contestCategory = CONTEST_CATEGORY_SMART, .contestComboStarterId = 0, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_FairyLock, @@ -14918,7 +15003,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .instructBanned = TRUE, .assistBanned = TRUE, .contestEffect = CONTEST_EFFECT_AVOID_STARTLE, - .contestCategory = CONTEST_CATEGORY_TOUGH, + .contestCategory = CONTEST_CATEGORY_COOL, .contestComboStarterId = 0, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_KingsShield, @@ -14942,9 +15027,9 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .ignoresProtect = TRUE, .ignoresSubstitute = TRUE, .magicCoatAffected = TRUE, - .contestEffect = CONTEST_EFFECT_BETTER_IF_LAST, + .contestEffect = CONTEST_EFFECT_BETTER_WHEN_AUDIENCE_EXCITED, .contestCategory = CONTEST_CATEGORY_CUTE, - .contestComboStarterId = 0, + .contestComboStarterId = COMBO_STARTER_PLAY_NICE, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_PlayNice, }, @@ -14968,8 +15053,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .magicCoatAffected = TRUE, .ignoresSubstitute = B_UPDATED_MOVE_FLAGS >= GEN_6, .soundMove = TRUE, - .contestEffect = CONTEST_EFFECT_BETTER_IF_LAST, - .contestCategory = CONTEST_CATEGORY_SMART, + .contestEffect = CONTEST_EFFECT_WORSEN_CONDITION_OF_PREV_MONS, + .contestCategory = CONTEST_CATEGORY_CUTE, .contestComboStarterId = 0, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_Confide, @@ -14995,7 +15080,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .self = TRUE, .chance = 50, }), - .contestEffect = CONTEST_EFFECT_USER_MORE_EASILY_STARTLED, + .contestEffect = CONTEST_EFFECT_USER_MORE_EASILY_STARTLED, //CONTEST_EFFECT_EXCITES_AUDIENCE_MORE_IF_LAST .contestCategory = CONTEST_CATEGORY_BEAUTY, .contestComboStarterId = 0, .contestComboMoves = {0}, @@ -15022,8 +15107,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .moveEffect = MOVE_EFFECT_BURN, .chance = 30, }), - .contestEffect = CONTEST_EFFECT_HIGHLY_APPEALING, - .contestCategory = CONTEST_CATEGORY_TOUGH, + .contestEffect = CONTEST_EFFECT_HIGHLY_APPEALING, //CONTEST_EFFECT_EXCITES_AUDIENCE_MORE_IF_LAST + .contestCategory = CONTEST_CATEGORY_BEAUTY, .contestComboStarterId = 0, .contestComboMoves = {COMBO_STARTER_SCALD}, .battleAnimScript = gBattleAnimMove_SteamEruption, @@ -15047,7 +15132,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_FEINT, }), - .contestEffect = CONTEST_EFFECT_DONT_EXCITE_AUDIENCE, + .contestEffect = CONTEST_EFFECT_DONT_EXCITE_AUDIENCE, //CONTEST_EFFECT_EXCITES_AUDIENCE_MORE_IF_FIRST .contestCategory = CONTEST_CATEGORY_SMART, .contestComboStarterId = COMBO_STARTER_HYPERSPACE_HOLE, .contestComboMoves = {COMBO_STARTER_HYPERSPACE_FURY}, @@ -15068,8 +15153,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .target = MOVE_TARGET_SELECTED, .priority = 1, .category = B_UPDATED_MOVE_DATA >= GEN_7 ? DAMAGE_CATEGORY_SPECIAL : DAMAGE_CATEGORY_PHYSICAL, - .contestEffect = CONTEST_EFFECT_STARTLE_MONS_SAME_TYPE_APPEAL, - .contestCategory = CONTEST_CATEGORY_BEAUTY, + .contestEffect = CONTEST_EFFECT_NEXT_APPEAL_EARLIER, + .contestCategory = CONTEST_CATEGORY_COOL, .contestComboStarterId = 0, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_WaterShuriken, @@ -15093,7 +15178,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .moveEffect = MOVE_EFFECT_SP_ATK_MINUS_1, .chance = 100, }), - .contestEffect = CONTEST_EFFECT_BADLY_STARTLE_PREV_MONS, + .contestEffect = CONTEST_EFFECT_REPETITION_NOT_BORING, .contestCategory = CONTEST_CATEGORY_BEAUTY, .contestComboStarterId = 0, .contestComboMoves = {0}, @@ -15122,7 +15207,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .copycatBanned = TRUE, .assistBanned = TRUE, .contestEffect = CONTEST_EFFECT_AVOID_STARTLE, - .contestCategory = CONTEST_CATEGORY_SMART, + .contestCategory = CONTEST_CATEGORY_TOUGH, .contestComboStarterId = 0, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_SpikyShield, @@ -15146,8 +15231,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .ignoresProtect = TRUE, .ignoresSubstitute = TRUE, .mirrorMoveBanned = TRUE, - .contestEffect = CONTEST_EFFECT_HIGHLY_APPEALING, - .contestCategory = CONTEST_CATEGORY_CUTE, + .contestEffect = CONTEST_EFFECT_IMPROVE_CONDITION_PREVENT_NERVOUSNESS, + .contestCategory = CONTEST_CATEGORY_BEAUTIFUL, .contestComboStarterId = 0, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_AromaticMist, @@ -15169,8 +15254,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .category = DAMAGE_CATEGORY_STATUS, .zMove = { .effect = Z_EFFECT_SPDEF_UP_1 }, .magicCoatAffected = TRUE, - .contestEffect = CONTEST_EFFECT_STARTLE_MONS_SAME_TYPE_APPEAL, - .contestCategory = CONTEST_CATEGORY_COOL, + .contestEffect = CONTEST_EFFECT_BADLY_STARTLE_FRONT_MON, + .contestCategory = CONTEST_CATEGORY_SMART, .contestComboStarterId = 0, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_EerieImpulse, @@ -15195,7 +15280,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .contestEffect = CONTEST_EFFECT_WORSEN_CONDITION_OF_PREV_MONS, .contestCategory = CONTEST_CATEGORY_SMART, .contestComboStarterId = 0, - .contestComboMoves = {COMBO_STARTER_TOXIC}, + .contestComboMoves = {COMBO_STARTER_TOXIC, COMBO_STARTER_POISON_GAS, COMBO_STARTER_POISON_POWDER, COMBO_STARTER_TOXIC_SPIKES}, .battleAnimScript = gBattleAnimMove_VenomDrench, }, @@ -15216,7 +15301,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .zMove = { .effect = Z_EFFECT_SPDEF_UP_2 }, .powderMove = TRUE, .magicCoatAffected = TRUE, - .contestEffect = CONTEST_EFFECT_DONT_EXCITE_AUDIENCE, + .contestEffect = CONTEST_EFFECT_DONT_EXCITE_AUDIENCE, //CONTEST_EFFECT_QUICKLY_GROW_BORED .contestCategory = CONTEST_CATEGORY_SMART, .contestComboStarterId = 0, .contestComboMoves = {0}, @@ -15243,7 +15328,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .skyBattleBanned = TRUE, .argument.twoTurnAttack = { .stringId = STRINGID_PKNMABSORBINGPOWER }, .contestEffect = CONTEST_EFFECT_IMPROVE_CONDITION_PREVENT_NERVOUSNESS, - .contestCategory = CONTEST_CATEGORY_CUTE, + .contestCategory = CONTEST_CATEGORY_BEAUTIFUL, .contestComboStarterId = 0, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_Geomancy, @@ -15268,8 +15353,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .ignoresProtect = TRUE, .ignoresSubstitute = TRUE, .mirrorMoveBanned = TRUE, - .contestEffect = CONTEST_EFFECT_HIGHLY_APPEALING, - .contestCategory = CONTEST_CATEGORY_BEAUTY, + .contestEffect = CONTEST_EFFECT_IMPROVE_CONDITION_PREVENT_NERVOUSNESS, + .contestCategory = CONTEST_CATEGORY_SMART, .contestComboStarterId = 0, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_MagneticFlux, @@ -15292,9 +15377,9 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .zMove = { .effect = Z_EFFECT_ALL_STATS_UP_1 }, .ignoresProtect = TRUE, .mirrorMoveBanned = TRUE, - .contestEffect = CONTEST_EFFECT_BETTER_WHEN_AUDIENCE_EXCITED, - .contestCategory = CONTEST_CATEGORY_COOL, - .contestComboStarterId = 0, + .contestEffect = CONTEST_EFFECT_EXCITE_AUDIENCE_IN_ANY_CONTEST, + .contestCategory = CONTEST_CATEGORY_CUTE, + .contestComboStarterId = COMBO_STARTER_HAPPY_HOUR, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_HappyHour, }, @@ -15317,8 +15402,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .ignoresProtect = TRUE, .mirrorMoveBanned = TRUE, .skyBattleBanned = TRUE, - .contestEffect = CONTEST_EFFECT_BETTER_WHEN_AUDIENCE_EXCITED, - .contestCategory = CONTEST_CATEGORY_BEAUTY, + .contestEffect = CONTEST_EFFECT_BETTER_WHEN_AUDIENCE_EXCITED, //CONTEST_EFFECT_EXCITES_AUDIENCE_MORE_IF_FIRST + .contestCategory = CONTEST_CATEGORY_SMART, .contestComboStarterId = COMBO_STARTER_ELECTRIC_TERRAIN, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_ElectricTerrain, @@ -15338,8 +15423,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .target = MOVE_TARGET_BOTH, .priority = 0, .category = DAMAGE_CATEGORY_SPECIAL, - .contestEffect = CONTEST_EFFECT_AFFECTED_BY_PREV_APPEAL, - .contestCategory = CONTEST_CATEGORY_CUTE, + .contestEffect = CONTEST_EFFECT_HIGHLY_APPEALING, + .contestCategory = CONTEST_CATEGORY_BEAUTY, .contestComboStarterId = 0, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_DazzlingGleam, @@ -15368,9 +15453,9 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .sleepTalkBanned = TRUE, .instructBanned = TRUE, .assistBanned = TRUE, - .contestEffect = CONTEST_EFFECT_BETTER_IF_FIRST, + .contestEffect = CONTEST_EFFECT_EXCITE_AUDIENCE_IN_ANY_CONTEST, .contestCategory = CONTEST_CATEGORY_CUTE, - .contestComboStarterId = 0, + .contestComboStarterId = COMBO_STARTER_CELEBRATE, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_Celebrate, }, @@ -15447,10 +15532,10 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .moveEffect = MOVE_EFFECT_PARALYSIS, .chance = 100, }), - .contestEffect = CONTEST_EFFECT_BADLY_STARTLE_MONS_WITH_GOOD_APPEALS, + .contestEffect = CONTEST_EFFECT_STARTLE_MONS_SAME_TYPE_APPEAL, .contestCategory = CONTEST_CATEGORY_CUTE, .contestComboStarterId = 0, - .contestComboMoves = {0}, + .contestComboMoves = {COMBO_STARTER_CHARGE}, .battleAnimScript = gBattleAnimMove_Nuzzle, }, @@ -15467,8 +15552,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, .makesContact = TRUE, - .contestEffect = CONTEST_EFFECT_BADLY_STARTLE_PREV_MONS, - .contestCategory = CONTEST_CATEGORY_CUTE, + .contestEffect = CONTEST_EFFECT_BADLY_STARTLE_PREV_MONS, //CONTEST_EFFECT_QUICKLY_GROW_BORED + .contestCategory = CONTEST_CATEGORY_COOL, .contestComboStarterId = 0, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_HoldBack, @@ -15494,7 +15579,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .multistring.wrapped = B_MSG_WRAPPED_INFESTATION, }), .contestEffect = CONTEST_EFFECT_DONT_EXCITE_AUDIENCE, - .contestCategory = CONTEST_CATEGORY_SMART, + .contestCategory = CONTEST_CATEGORY_CUTE, .contestComboStarterId = 0, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_Infestation, @@ -15521,7 +15606,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .self = TRUE, .chance = 100, }), - .contestEffect = CONTEST_EFFECT_BETTER_IF_SAME_TYPE, + .contestEffect = CONTEST_EFFECT_BETTER_WITH_GOOD_CONDITION, .contestCategory = CONTEST_CATEGORY_TOUGH, .contestComboStarterId = 0, .contestComboMoves = {0}, @@ -15542,7 +15627,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .category = DAMAGE_CATEGORY_SPECIAL, .argument = { .absorbPercentage = 75 }, .healingMove = B_HEAL_BLOCKING >= GEN_6, - .contestEffect = CONTEST_EFFECT_STARTLE_MON_WITH_JUDGES_ATTENTION, + .contestEffect = CONTEST_EFFECT_APPEAL_AS_GOOD_AS_PREV_ONES, .contestCategory = CONTEST_CATEGORY_COOL, .contestComboStarterId = 0, .contestComboMoves = {0}, @@ -15567,8 +15652,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .ignoreTypeIfFlyingAndUngrounded = TRUE, .metronomeBanned = TRUE, .skyBattleBanned = TRUE, - .contestEffect = CONTEST_EFFECT_HIGHLY_APPEALING, - .contestCategory = CONTEST_CATEGORY_TOUGH, + .contestEffect = CONTEST_EFFECT_STARTLE_MONS_SAME_TYPE_APPEAL, + .contestCategory = CONTEST_CATEGORY_BEAUTIFUL, .contestComboStarterId = COMBO_STARTER_THOUSAND_ARROWS, .contestComboMoves = {COMBO_STARTER_THOUSAND_WAVES}, .battleAnimScript = gBattleAnimMove_ThousandArrows, @@ -15593,7 +15678,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_PREVENT_ESCAPE, }), - .contestEffect = CONTEST_EFFECT_BADLY_STARTLE_MONS_WITH_GOOD_APPEALS, + .contestEffect = CONTEST_EFFECT_WORSEN_CONDITION_OF_PREV_MONS, .contestCategory = CONTEST_CATEGORY_TOUGH, .contestComboStarterId = COMBO_STARTER_THOUSAND_WAVES, .contestComboMoves = {COMBO_STARTER_THOUSAND_ARROWS}, @@ -15615,8 +15700,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, .skyBattleBanned = TRUE, - .contestEffect = CONTEST_EFFECT_BADLY_STARTLE_PREV_MONS, - .contestCategory = CONTEST_CATEGORY_TOUGH, + .contestEffect = CONTEST_EFFECT_STARTLE_PREV_MONS, + .contestCategory = CONTEST_CATEGORY_BEAUTY, .contestComboStarterId = 0, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_LandsWrath, @@ -15638,6 +15723,10 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .category = DAMAGE_CATEGORY_SPECIAL, .argument = { .recoilPercentage = 50 }, .metronomeBanned = TRUE, + .contestEffect = CONTEST_EFFECT_USER_MORE_EASILY_STARTLED, + .contestCategory = CONTEST_CATEGORY_BEAUTY, + .contestComboStarterId = 0, + .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_LightOfRuin, }, @@ -15657,7 +15746,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .category = DAMAGE_CATEGORY_SPECIAL, .pulseMove = TRUE, .metronomeBanned = TRUE, - .contestEffect = CONTEST_EFFECT_BETTER_IF_FIRST, + .contestEffect = CONTEST_EFFECT_BETTER_IF_FIRST, //CONTEST_EFFECT_EXCITES_AUDIENCE_MORE_IF_FIRST .contestCategory = CONTEST_CATEGORY_BEAUTY, .contestComboStarterId = 0, .contestComboMoves = {0}, @@ -15679,8 +15768,9 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, .metronomeBanned = TRUE, - .contestEffect = CONTEST_EFFECT_BETTER_IF_LAST, - .contestCategory = CONTEST_CATEGORY_CUTE, + .skyBattleBanned = TRUE, + .contestEffect = CONTEST_EFFECT_BETTER_IF_LAST, //CONTEST_EFFECT_EXCITES_AUDIENCE_MORE_IF_LAST + .contestCategory = CONTEST_CATEGORY_COOL, .contestComboStarterId = 0, .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_PrecipiceBlades, @@ -15732,7 +15822,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .moveEffect = MOVE_EFFECT_DEF_MINUS_1, .self = TRUE, }), - .contestEffect = CONTEST_EFFECT_HIGHLY_APPEALING, + .contestEffect = CONTEST_EFFECT_HIGHLY_APPEALING, //CONTEST_EFFECT_EXCITES_AUDIENCE_MORE_IF_FIRST .contestCategory = CONTEST_CATEGORY_TOUGH, .contestComboStarterId = COMBO_STARTER_HYPERSPACE_FURY, .contestComboMoves = {COMBO_STARTER_HYPERSPACE_HOLE}, @@ -15912,7 +16002,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .moveEffect = MOVE_EFFECT_SPD_MINUS_1, .self = TRUE, }), - .contestEffect = CONTEST_EFFECT_BADLY_STARTLE_PREV_MONS, + .contestEffect = CONTEST_EFFECT_USER_MORE_EASILY_STARTLED, .contestCategory = CONTEST_CATEGORY_BEAUTY, .contestComboStarterId = 0, .contestComboMoves = {COMBO_STARTER_HAIL}, @@ -15938,7 +16028,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .mirrorMoveBanned = TRUE, .healingMove = TRUE, .magicCoatAffected = TRUE, - .contestEffect = CONTEST_EFFECT_QUALITY_DEPENDS_ON_TIMING, + .contestEffect = CONTEST_EFFECT_EXCITE_AUDIENCE_IN_ANY_CONTEST, .contestCategory = CONTEST_CATEGORY_CUTE, .contestComboStarterId = 0, .contestComboMoves = {0}, @@ -16229,6 +16319,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .zMove = { .effect = Z_EFFECT_SPATK_UP_1 }, .ignoresProtect = TRUE, .mirrorMoveBanned = TRUE, + .skyBattleBanned = TRUE, .contestEffect = CONTEST_EFFECT_BETTER_WHEN_AUDIENCE_EXCITED, .contestCategory = CONTEST_CATEGORY_SMART, .contestComboStarterId = COMBO_STARTER_PSYCHIC_TERRAIN, @@ -16303,7 +16394,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, .makesContact = TRUE, - .contestEffect = CONTEST_EFFECT_BETTER_WHEN_LATER, + .contestEffect = CONTEST_EFFECT_BETTER_WITH_GOOD_CONDITION, .contestCategory = CONTEST_CATEGORY_TOUGH, .contestComboStarterId = 0, .contestComboMoves = {0}, @@ -17432,7 +17523,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .power = 80, .type = TYPE_WATER, .accuracy = 100, - .criticalHitStage = 1, + .criticalHitStage = B_UPDATED_MOVE_DATA >= GEN_3 ? 1 : 2, .pp = 15, .target = MOVE_TARGET_SELECTED, .priority = 0, @@ -17557,7 +17648,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .argument = { .type = TYPE_PSYCHIC }, .magicCoatAffected = TRUE, .powderMove = TRUE, - .contestEffect = CONTEST_EFFECT_WORSEN_CONDITION_OF_PREV_MONS, + .contestEffect = CONTEST_EFFECT_STARTLE_MON_WITH_JUDGES_ATTENTION, .contestCategory = CONTEST_CATEGORY_CUTE, .contestComboStarterId = 0, .contestComboMoves = {0}, @@ -18466,7 +18557,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .priority = 0, .category = DAMAGE_CATEGORY_SPECIAL, .pulseMove = TRUE, - .contestEffect = CONTEST_EFFECT_HIGHLY_APPEALING, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_REPETITION_NOT_BORING : CONTEST_EFFECT_HIGHLY_APPEALING, .contestCategory = CONTEST_CATEGORY_CUTE, .contestComboStarterId = 0, .contestComboMoves = {COMBO_STARTER_ELECTRIC_TERRAIN, COMBO_STARTER_MISTY_TERRAIN, COMBO_STARTER_GRASSY_TERRAIN, COMBO_STARTER_PSYCHIC_TERRAIN}, @@ -18826,7 +18917,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .priority = 0, .category = DAMAGE_CATEGORY_SPECIAL, .metronomeBanned = TRUE, - .contestEffect = CONTEST_EFFECT_BETTER_WHEN_LATER, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_USER_MORE_EASILY_STARTLED : CONTEST_EFFECT_BETTER_WHEN_LATER, .contestCategory = CONTEST_CATEGORY_COOL, .contestComboStarterId = 0, .contestComboMoves = {0}, @@ -19135,6 +19226,9 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .moveEffect = MOVE_EFFECT_THRASH, .self = TRUE, }), + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_USER_MORE_EASILY_STARTLED : CONTEST_EFFECT_JAMS_OTHERS_BUT_MISS_ONE_TURN, + .contestComboStarterId = 0, + .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_RagingFury, }, @@ -19155,6 +19249,9 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .argument = { .recoilPercentage = 33 }, .makesContact = TRUE, .skyBattleBanned = B_EXTRAPOLATED_MOVE_FLAGS, + .contestEffect = CONTEST_EFFECT_USER_MORE_EASILY_STARTLED, + .contestComboStarterId = 0, + .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_WaveCrash, }, @@ -19214,6 +19311,9 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .snatchAffected = TRUE, .ignoresProtect = TRUE, .mirrorMoveBanned = TRUE, + .contestEffect = CONTEST_EFFECT_IMPROVE_CONDITION_PREVENT_NERVOUSNESS, + .contestComboStarterId = 0, + .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_VictoryDance, }, @@ -19237,6 +19337,9 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .moveEffect = MOVE_EFFECT_DEF_SPDEF_DOWN, .self = TRUE, }), + .contestEffect = CONTEST_EFFECT_USER_MORE_EASILY_STARTLED, + .contestComboStarterId = 0, + .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_HeadlongRush, }, @@ -19272,7 +19375,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .power = B_UPDATED_MOVE_DATA >= GEN_9 ? 80 : 75, .type = TYPE_PSYCHIC, .accuracy = B_UPDATED_MOVE_DATA >= GEN_9 ? 100 : 90, - .criticalHitStage = 1, + .criticalHitStage = B_UPDATED_MOVE_DATA >= GEN_3 ? 1 : 2, .pp = 10, .target = MOVE_TARGET_SELECTED, .priority = 0, @@ -19337,7 +19440,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .type = TYPE_FIGHTING, .accuracy = 100, .pp = B_UPDATED_MOVE_DATA >= GEN_9 ? 10 : 15, - .criticalHitStage = 1, + .criticalHitStage = B_UPDATED_MOVE_DATA >= GEN_3 ? 1 : 2, .target = MOVE_TARGET_SELECTED, .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, @@ -19651,6 +19754,9 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .makesContact = TRUE, .punchingMove = TRUE, .metronomeBanned = TRUE, + .contestEffect = CONTEST_EFFECT_NEXT_APPEAL_EARLIER, + .contestComboStarterId = 0, + .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_JetPunch, }, @@ -20027,6 +20133,9 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .category = DAMAGE_CATEGORY_SPECIAL, .argument = { .damagePercentage = 50 }, .metronomeBanned = TRUE, + .contestEffect = CONTEST_EFFECT_BADLY_STARTLE_MONS_WITH_GOOD_APPEALS, + .contestComboStarterId = 0, + .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_Ruination, }, @@ -20148,6 +20257,10 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .ignoresProtect = TRUE, .mirrorMoveBanned = TRUE, .metronomeBanned = TRUE, + .contestEffect = C_UPDATED_MOVE_EFFECTS >= GEN_6 ? CONTEST_EFFECT_BADLY_STARTLE_MONS_WITH_GOOD_APPEALS : CONTEST_EFFECT_BADLY_STARTLE_PREV_MONS, + .contestCategory = CONTEST_CATEGORY_BEAUTY, + .contestComboStarterId = 0, + .contestComboMoves = {0}, .battleAnimScript = (B_PREFERRED_ICE_WEATHER == B_ICE_WEATHER_HAIL) ? gBattleAnimMove_Hail : gBattleAnimMove_Snowscape, }, @@ -20195,6 +20308,9 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .self = TRUE, .chance = 100, }), + .contestEffect = CONTEST_EFFECT_BETTER_WITH_GOOD_CONDITION, + .contestComboStarterId = 0, + .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_Trailblaze, }, @@ -20217,6 +20333,9 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .moveEffect = MOVE_EFFECT_ATK_MINUS_1, .chance = 100, }), + .contestEffect = CONTEST_EFFECT_BETTER_IF_LAST, + .contestComboStarterId = 0, + .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_ChillingWater, }, @@ -20298,6 +20417,9 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .moveEffect = MOVE_EFFECT_DEF_SPDEF_DOWN, .self = TRUE, }), + .contestEffect = CONTEST_EFFECT_USER_MORE_EASILY_STARTLED, + .contestComboStarterId = 0, + .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_ArmorCannon, }, @@ -20381,6 +20503,9 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .makesContact = TRUE, .meFirstBanned = TRUE, .metronomeBanned = TRUE, + .contestEffect = CONTEST_EFFECT_BETTER_IF_LAST, + .contestComboStarterId = 0, + .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_Comeuppance, }, @@ -20394,7 +20519,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .power = 70, .type = TYPE_WATER, .accuracy = 100, - .criticalHitStage = 1, + .criticalHitStage = B_UPDATED_MOVE_DATA >= GEN_3 ? 1 : 2, .pp = 20, .target = MOVE_TARGET_SELECTED, .priority = 0, @@ -20672,7 +20797,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .type = TYPE_GRASS, .accuracy = 100, .pp = 10, - .criticalHitStage = 1, + .criticalHitStage = B_UPDATED_MOVE_DATA >= GEN_3 ? 1 : 2, .target = MOVE_TARGET_SELECTED, .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, @@ -20778,6 +20903,9 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .target = MOVE_TARGET_SELECTED, .priority = 1, .category = DAMAGE_CATEGORY_SPECIAL, + .contestEffect = CONTEST_EFFECT_BETTER_IF_FIRST, + .contestComboStarterId = 0, + .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_Thunderclap, }, @@ -20867,7 +20995,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .priority = 0, .category = DAMAGE_CATEGORY_SPECIAL, .soundMove = TRUE, - .ignoresSubstitute = TRUE, + .ignoresSubstitute = B_UPDATED_MOVE_FLAGS >= GEN_6, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_CONFUSION, .onlyIfTargetRaisedStats = TRUE, @@ -20910,6 +21038,9 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .category = DAMAGE_CATEGORY_PHYSICAL, .makesContact = TRUE, .minimizeDoubleDamage = TRUE, + .contestEffect = CONTEST_EFFECT_USER_MORE_EASILY_STARTLED, + .contestComboStarterId = 0, + .contestComboMoves = {0}, .battleAnimScript = gBattleAnimMove_SupercellSlam, }, @@ -20928,7 +21059,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .priority = 0, .category = DAMAGE_CATEGORY_SPECIAL, .soundMove = TRUE, - .ignoresSubstitute = TRUE, + .ignoresSubstitute = B_UPDATED_MOVE_FLAGS >= GEN_6, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_PSYCHIC_NOISE, .chance = 100, @@ -21360,7 +21491,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .description = COMPOUND_STRING( "梦幻以Z力量全力攻击对手,\n" "脚下会变成精神场地。"), - .effect = EFFECT_HIT_SET_TERRAIN, + .effect = EFFECT_HIT, .power = 185, .type = TYPE_PSYCHIC, .accuracy = 0, @@ -21368,8 +21499,11 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .target = MOVE_TARGET_SELECTED, .priority = 0, .category = DAMAGE_CATEGORY_SPECIAL, - .argument = { .moveProperty = STATUS_FIELD_PSYCHIC_TERRAIN }, .battleAnimScript = gBattleAnimMove_GenesisSupernova, + .additionalEffects = ADDITIONAL_EFFECTS({ + .moveEffect = MOVE_EFFECT_PSYCHIC_TERRAIN, + .chance = 100, + }), }, [MOVE_SINISTER_ARROW_RAID] = { @@ -21401,6 +21535,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .target = MOVE_TARGET_SELECTED, .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, + .minimizeDoubleDamage = TRUE, .battleAnimScript = gBattleAnimMove_MaliciousMoonsault, }, [MOVE_OCEANIC_OPERETTA] = diff --git a/src/data/object_events/object_event_graphics.h b/src/data/object_events/object_event_graphics.h index e3d2c674ad..424d4224f3 100755 --- a/src/data/object_events/object_event_graphics.h +++ b/src/data/object_events/object_event_graphics.h @@ -465,3 +465,5 @@ const u16 gObjectEventPal_StrangeBall[] = INCBIN_U16("graphics/object_events/pic const u32 gFieldEffectObjectPic_CaveDust[] = INCBIN_U32("graphics/field_effects/pics/cave_dust.4bpp"); const u16 gFieldEffectObjectPalette_CaveDust[] = INCBIN_U16("graphics/field_effects/palettes/cave_dust.gbapal"); + +const u32 gObjectEventPic_ApricornTree[] = INCBIN_U32("graphics/object_events/pics/misc/apricorn_tree.4bpp"); diff --git a/src/data/object_events/object_event_graphics_info.h b/src/data/object_events/object_event_graphics_info.h index 91b3ab2c9d..5b1c891eb4 100755 --- a/src/data/object_events/object_event_graphics_info.h +++ b/src/data/object_events/object_event_graphics_info.h @@ -4690,3 +4690,22 @@ const struct ObjectEventGraphicsInfo gObjectEventGraphicsInfo_BallLight = { .images = gFieldEffectObjectPicTable_BallLight, .affineAnims = gDummySpriteAffineAnimTable, }; + +const struct ObjectEventGraphicsInfo gObjectEventGraphicsInfo_ApricornTree = { + .tileTag = TAG_NONE, + .paletteTag = OBJ_EVENT_PAL_TAG_NPC_3, + .reflectionPaletteTag = OBJ_EVENT_PAL_TAG_NONE, + .size = 128, + .width = 16, + .height = 16, + .paletteSlot = PALSLOT_NPC_3, + .shadowSize = SHADOW_SIZE_S, + .inanimate = TRUE, + .compressed = FALSE, + .tracks = TRACKS_NONE, + .oam = &gObjectEventBaseOam_16x16, + .subspriteTables = sOamTables_16x16, + .anims = sAnimTable_Inanimate, + .images = sPicTable_ApricornTree, + .affineAnims = gDummySpriteAffineAnimTable, +}; 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 117187739b..a239bce993 100755 --- a/src/data/object_events/object_event_graphics_info_pointers.h +++ b/src/data/object_events/object_event_graphics_info_pointers.h @@ -248,6 +248,7 @@ extern const struct ObjectEventGraphicsInfo gObjectEventGraphicsInfo_Storyteller extern const struct ObjectEventGraphicsInfo gObjectEventGraphicsInfo_Giddy; extern const struct ObjectEventGraphicsInfo gObjectEventGraphicsInfo_UnusedMauvilleOldMan1; extern const struct ObjectEventGraphicsInfo gObjectEventGraphicsInfo_UnusedMauvilleOldMan2; +extern const struct ObjectEventGraphicsInfo gObjectEventGraphicsInfo_ApricornTree; const struct ObjectEventGraphicsInfo *const gObjectEventGraphicsInfoPointers[NUM_OBJ_EVENT_GFX] = { [OBJ_EVENT_GFX_BRENDAN_NORMAL] = &gObjectEventGraphicsInfo_BrendanNormal, @@ -492,6 +493,7 @@ const struct ObjectEventGraphicsInfo *const gObjectEventGraphicsInfoPointers[NUM [OBJ_EVENT_GFX_POKE_BALL] = &gObjectEventGraphicsInfo_PokeBall, [OBJ_EVENT_GFX_OW_MON] = &gObjectEventGraphicsInfo_Follower, [OBJ_EVENT_GFX_LIGHT_SPRITE] = &gObjectEventGraphicsInfo_BallLight, + [OBJ_EVENT_GFX_APRICORN_TREE] = &gObjectEventGraphicsInfo_ApricornTree, }; const struct ObjectEventGraphicsInfo *const gMauvilleOldManGraphicsInfoPointers[] = { diff --git a/src/data/object_events/object_event_pic_tables.h b/src/data/object_events/object_event_pic_tables.h index c1f8fd6f1c..06d353b44d 100755 --- a/src/data/object_events/object_event_pic_tables.h +++ b/src/data/object_events/object_event_pic_tables.h @@ -1356,3 +1356,7 @@ static const struct SpriteFrameImage sPicTable_KirliaOld[] = { static const struct SpriteFrameImage sPicTable_RubySapphireMay[] = { overworld_ascending_frames(gObjectEventPic_RubySapphireMayNormal, 2, 4), }; + +static const struct SpriteFrameImage sPicTable_ApricornTree[] = { + overworld_frame(gObjectEventPic_ApricornTree, 2, 2, 0), +}; diff --git a/src/data/party_menu.h b/src/data/party_menu.h index f87354a502..81ff1463d1 100644 --- a/src/data/party_menu.h +++ b/src/data/party_menu.h @@ -118,6 +118,7 @@ static const u8 sFontColorTable[][3] = {TEXT_COLOR_WHITE, TEXT_COLOR_DARK_GRAY, TEXT_COLOR_LIGHT_GRAY}, // Selection actions {TEXT_COLOR_WHITE, TEXT_COLOR_BLUE, TEXT_COLOR_LIGHT_BLUE}, // Field moves {TEXT_COLOR_TRANSPARENT, TEXT_COLOR_WHITE, TEXT_COLOR_DARK_GRAY}, // Unused + {TEXT_COLOR_WHITE, TEXT_COLOR_RED, TEXT_COLOR_LIGHT_RED}, // Move relearner }; static const struct WindowTemplate sSinglePartyMenuWindowTemplate[] = @@ -717,6 +718,11 @@ struct [MENU_TRADE1] = {sText_Trade4, CursorCb_Trade1}, [MENU_TRADE2] = {sText_Trade4, CursorCb_Trade2}, [MENU_TOSS] = {gMenuText_Toss, CursorCb_Toss}, + [MENU_LEVEL_UP_MOVES] = {COMPOUND_STRING("升级招式"), CursorCb_ChangeLevelUpMoves}, + [MENU_EGG_MOVES] = {COMPOUND_STRING("蛋招式"), CursorCb_ChangeEggMoves}, + [MENU_TM_MOVES] = {COMPOUND_STRING("学习器招式"), CursorCb_ChangeTMMoves}, + [MENU_TUTOR_MOVES] = {COMPOUND_STRING("教授招式"), CursorCb_ChangeTutorMoves}, + [MENU_SUB_MOVES] = {COMPOUND_STRING("学习招式"), CursorCb_LearnMovesSubMenu}, [MENU_CATALOG_BULB] = {COMPOUND_STRING("灯泡"), CursorCb_CatalogBulb}, [MENU_CATALOG_OVEN] = {COMPOUND_STRING("微波炉"), CursorCb_CatalogOven}, [MENU_CATALOG_WASHING] = {COMPOUND_STRING("洗衣机"), CursorCb_CatalogWashing}, diff --git a/src/data/pokemon/form_change_tables.h b/src/data/pokemon/form_change_tables.h index fd443458c7..54584c5796 100644 --- a/src/data/pokemon/form_change_tables.h +++ b/src/data/pokemon/form_change_tables.h @@ -73,6 +73,15 @@ static const struct FormChange sPikachuFormChangeTable[] = }; #endif //P_FAMILY_PIKACHU +#if P_FAMILY_CLEFAIRY +static const struct FormChange sClefableFormChangeTable[] = { +#if P_GEN_9_MEGA_EVOLUTIONS + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_CLEFABLE_MEGA, ITEM_CLEFABLITE}, +#endif + {FORM_CHANGE_TERMINATOR}, +}; +#endif //P_FAMILY_CLEFAIRY + #if P_FAMILY_MEOWTH static const struct FormChange sMeowthFormChangeTable[] = { @@ -102,6 +111,15 @@ static const struct FormChange sMachampFormChangeTable[] = }; #endif //P_FAMILY_MACHOP +#if P_FAMILY_BELLSPROUT +static const struct FormChange sVictreebelFormChangeTable[] = { +#if P_GEN_9_MEGA_EVOLUTIONS + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_VICTREEBEL_MEGA, ITEM_VICTREEBELITE}, +#endif + {FORM_CHANGE_TERMINATOR}, +}; +#endif //P_FAMILY_BELLSPROUT + #if P_FAMILY_SLOWPOKE static const struct FormChange sSlowbroFormChangeTable[] = { #if P_MEGA_EVOLUTIONS @@ -153,6 +171,15 @@ static const struct FormChange sKangaskhanFormChangeTable[] = { }; #endif //P_FAMILY_KANGASKHAN +#if P_FAMILY_STARYU +static const struct FormChange sStarmieFormChangeTable[] = { +#if P_GEN_9_MEGA_EVOLUTIONS + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_STARMIE_MEGA, ITEM_STARMINITE}, +#endif + {FORM_CHANGE_TERMINATOR}, +}; +#endif //P_FAMILY_STARYU + #if P_FAMILY_SCYTHER #if P_GEN_2_CROSS_EVOS static const struct FormChange sScizorFormChangeTable[] = { @@ -218,6 +245,15 @@ static const struct FormChange sSnorlaxFormChangeTable[] = { }; #endif //P_FAMILY_SNORLAX +#if P_FAMILY_DRATINI +static const struct FormChange sDragoniteFormChangeTable[] = { +#if P_GEN_9_MEGA_EVOLUTIONS + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_DRAGONITE_MEGA, ITEM_DRAGONINITE}, +#endif + {FORM_CHANGE_TERMINATOR}, +}; +#endif //P_FAMILY_DRATINI + #if P_FAMILY_MEWTWO static const struct FormChange sMewtwoFormChangeTable[] = { #if P_MEGA_EVOLUTIONS @@ -228,6 +264,24 @@ static const struct FormChange sMewtwoFormChangeTable[] = { }; #endif //P_FAMILY_MEWTWO +#if P_FAMILY_CHIKORITA +static const struct FormChange sMeganiumFormChangeTable[] = { +#if P_GEN_9_MEGA_EVOLUTIONS + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_MEGANIUM_MEGA, ITEM_MEGANIUMITE}, +#endif + {FORM_CHANGE_TERMINATOR}, +}; +#endif //P_FAMILY_CHIKORITA + +#if P_FAMILY_TOTODILE +static const struct FormChange sFeraligatrFormChangeTable[] = { +#if P_GEN_9_MEGA_EVOLUTIONS + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_FERALIGATR_MEGA, ITEM_FERALIGITE}, +#endif + {FORM_CHANGE_TERMINATOR}, +}; +#endif //P_FAMILY_TOTODILE + #if P_FAMILY_MAREEP static const struct FormChange sAmpharosFormChangeTable[] = { #if P_MEGA_EVOLUTIONS @@ -246,6 +300,15 @@ static const struct FormChange sHeracrossFormChangeTable[] = { }; #endif //P_FAMILY_HERACROSS +#if P_FAMILY_SKARMORY +static const struct FormChange sSkarmoryFormChangeTable[] = { +#if P_GEN_9_MEGA_EVOLUTIONS + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_SKARMORY_MEGA, ITEM_SKARMORITE}, +#endif + {FORM_CHANGE_TERMINATOR}, +}; +#endif //P_FAMILY_SKARMORY + #if P_FAMILY_HOUNDOUR static const struct FormChange sHoundoomFormChangeTable[] = { #if P_MEGA_EVOLUTIONS @@ -406,6 +469,13 @@ static const struct FormChange sGlalieFormChangeTable[] = { #endif {FORM_CHANGE_TERMINATOR}, }; + +static const struct FormChange sFroslassFormChangeTable[] = { +#if P_GEN_9_MEGA_EVOLUTIONS + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_FROSLASS_MEGA, ITEM_FROSLASSITE}, +#endif + {FORM_CHANGE_TERMINATOR}, +}; #endif //P_FAMILY_SNORUNT #if P_FAMILY_CASTFORM @@ -690,6 +760,24 @@ static const struct FormChange sArceusFormChangeTable[] = { }; #endif //P_FAMILY_ARCEUS +#if P_FAMILY_TEPIG +static const struct FormChange sEmboarFormChangeTable[] = { +#if P_GEN_9_MEGA_EVOLUTIONS + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_EMBOAR_MEGA, ITEM_EMBOARITE}, +#endif + {FORM_CHANGE_TERMINATOR}, +}; +#endif //P_FAMILY_TEPIG + +#if P_FAMILY_DRILBUR +static const struct FormChange sExcadrillFormChangeTable[] = { +#if P_GEN_9_MEGA_EVOLUTIONS + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_EXCADRILL_MEGA, ITEM_EXCADRITE}, +#endif + {FORM_CHANGE_TERMINATOR}, +}; +#endif //P_FAMILY_DRILBUR + #if P_FAMILY_AUDINO static const struct FormChange sAudinoFormChangeTable[] = { #if P_MEGA_EVOLUTIONS @@ -699,6 +787,15 @@ static const struct FormChange sAudinoFormChangeTable[] = { }; #endif //P_FAMILY_AUDINO +#if P_FAMILY_VENIPEDE +static const struct FormChange sScolipedeFormChangeTable[] = { +#if P_GEN_9_MEGA_EVOLUTIONS + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_SCOLIPEDE_MEGA, ITEM_SCOLIPITE}, +#endif + {FORM_CHANGE_TERMINATOR}, +}; +#endif //P_FAMILY_VENIPEDE + #if P_FAMILY_DARUMAKA static const struct FormChange sDarmanitanFormChangeTable[] = { {FORM_CHANGE_BATTLE_HP_PERCENT, SPECIES_DARMANITAN_STANDARD, ABILITY_ZEN_MODE, HP_HIGHER_THAN, 50}, @@ -719,6 +816,15 @@ static const struct FormChange sDarmanitanGalarFormChangeTable[] = { #endif //P_GALARIAN_FORMS #endif //P_FAMILY_DARUMAKA +#if P_FAMILY_SCRAGGY +static const struct FormChange sScraftyFormChangeTable[] = { +#if P_GEN_9_MEGA_EVOLUTIONS + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_SCRAFTY_MEGA, ITEM_SCRAFTINITE}, +#endif + {FORM_CHANGE_TERMINATOR}, +}; +#endif //P_FAMILY_SCRAGGY + #if P_FAMILY_TRUBBISH static const struct FormChange sGarbodorFormChangeTable[] = { @@ -729,6 +835,24 @@ static const struct FormChange sGarbodorFormChangeTable[] = }; #endif //P_FAMILY_TRUBBISH +#if P_FAMILY_TYNAMO +static const struct FormChange sEelektrossFormChangeTable[] = { +#if P_GEN_9_MEGA_EVOLUTIONS + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_EELEKTROSS_MEGA, ITEM_EELEKTROSSITE}, +#endif + {FORM_CHANGE_TERMINATOR}, +}; +#endif //P_FAMILY_TYNAMO + +#if P_FAMILY_LITWICK +static const struct FormChange sChandelureFormChangeTable[] = { +#if P_GEN_9_MEGA_EVOLUTIONS + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_CHANDELURE_MEGA, ITEM_CHANDELURITE}, +#endif + {FORM_CHANGE_TERMINATOR}, +}; +#endif //P_FAMILY_LITWICK + #if P_FAMILY_TORNADUS static const struct FormChange sTornadusFormChangeTable[] = { {FORM_CHANGE_ITEM_USE, SPECIES_TORNADUS_THERIAN, ITEM_REVEAL_GLASS}, @@ -790,7 +914,32 @@ static const struct FormChange sGenesectFormChangeTable[] = { }; #endif //P_FAMILY_GENESECT +#if P_FAMILY_CHESPIN +static const struct FormChange sChesnaughtFormChangeTable[] = { +#if P_GEN_9_MEGA_EVOLUTIONS + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_CHESNAUGHT_MEGA, ITEM_CHESNAUGHTITE}, +#endif + {FORM_CHANGE_TERMINATOR}, +}; +#endif //P_FAMILY_CHESPIN + +#if P_FAMILY_FENNEKIN +static const struct FormChange sDelphoxFormChangeTable[] = { +#if P_GEN_9_MEGA_EVOLUTIONS + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_DELPHOX_MEGA, ITEM_DELPHOXITE}, +#endif + {FORM_CHANGE_TERMINATOR}, +}; +#endif //P_FAMILY_FENNEKIN + #if P_FAMILY_FROAKIE +static const struct FormChange sGreninjaFormChangeTable[] = { +#if P_GEN_9_MEGA_EVOLUTIONS + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_GRENINJA_MEGA, ITEM_GRENINJITE}, +#endif + {FORM_CHANGE_TERMINATOR}, +}; + static const struct FormChange sGreninjaBattleBondFormChangeTable[] = { {FORM_CHANGE_FAINT, SPECIES_GRENINJA_BATTLE_BOND}, {FORM_CHANGE_END_BATTLE, SPECIES_GRENINJA_BATTLE_BOND}, @@ -798,6 +947,24 @@ static const struct FormChange sGreninjaBattleBondFormChangeTable[] = { }; #endif //P_FAMILY_FROAKIE +#if P_FAMILY_LITLEO +static const struct FormChange sPyroarFormChangeTable[] = { +#if P_GEN_9_MEGA_EVOLUTIONS + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_PYROAR_MEGA, ITEM_PYROARITE}, +#endif + {FORM_CHANGE_TERMINATOR}, +}; +#endif //P_FAMILY_LITLEO + +#if P_FAMILY_FLABEBE +static const struct FormChange sFloetteEternalFormChangeTable[] = { +#if P_GEN_9_MEGA_EVOLUTIONS + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_FLOETTE_MEGA, ITEM_FLOETTITE}, +#endif + {FORM_CHANGE_TERMINATOR}, +}; +#endif //P_FAMILY_FLABEBE + #if P_FAMILY_FURFROU static const struct FormChange sFurfrouFormChangeTable[] = { {FORM_CHANGE_WITHDRAW, SPECIES_FURFROU_NATURAL}, @@ -818,6 +985,42 @@ static const struct FormChange sAegislashFormChangeTable[] = { }; #endif //P_FAMILY_HONEDGE +#if P_FAMILY_INKAY +static const struct FormChange sMalamarFormChangeTable[] = { +#if P_GEN_9_MEGA_EVOLUTIONS + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_MALAMAR_MEGA, ITEM_MALAMARITE}, +#endif + {FORM_CHANGE_TERMINATOR}, +}; +#endif //P_FAMILY_INKAY + +#if P_FAMILY_BINACLE +static const struct FormChange sBarbaracleFormChangeTable[] = { +#if P_GEN_9_MEGA_EVOLUTIONS + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_BARBARACLE_MEGA, ITEM_BARBARACITE}, +#endif + {FORM_CHANGE_TERMINATOR}, +}; +#endif //P_FAMILY_BINACLE + +#if P_FAMILY_SKRELP +static const struct FormChange sDragalgeFormChangeTable[] = { +#if P_GEN_9_MEGA_EVOLUTIONS + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_DRAGALGE_MEGA, ITEM_DRAGALGITE}, +#endif + {FORM_CHANGE_TERMINATOR}, +}; +#endif //P_FAMILY_SKRELP + +#if P_FAMILY_HAWLUCHA +static const struct FormChange sHawluchaFormChangeTable[] = { +#if P_GEN_9_MEGA_EVOLUTIONS + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_HAWLUCHA_MEGA, ITEM_HAWLUCHANITE}, +#endif + {FORM_CHANGE_TERMINATOR}, +}; +#endif //P_FAMILY_HAWLUCHA + #if P_FAMILY_XERNEAS static const struct FormChange sXerneasFormChangeTable[] = { {FORM_CHANGE_BEGIN_BATTLE, SPECIES_XERNEAS_ACTIVE}, @@ -856,6 +1059,9 @@ static const struct FormChange sZygarde10PowerConstructFormChangeTable[] = { static const struct FormChange sZygardeCompleteFormChangeTable[] = { {FORM_CHANGE_FAINT}, {FORM_CHANGE_END_BATTLE}, +#if P_GEN_9_MEGA_EVOLUTIONS + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_ZYGARDE_MEGA, ITEM_ZYGARDITE}, +#endif {FORM_CHANGE_TERMINATOR}, }; #endif //P_FAMILY_ZYGARDE @@ -1003,6 +1209,15 @@ static const struct FormChange sMimikyuTotemFormChangeTable[] = { }; #endif //P_FAMILY_MIMIKYU +#if P_FAMILY_DRAMPA +static const struct FormChange sDrampaFormChangeTable[] = { +#if P_GEN_9_MEGA_EVOLUTIONS + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_DRAMPA_MEGA, ITEM_DRAMPANITE}, +#endif + {FORM_CHANGE_TERMINATOR}, +}; +#endif //P_FAMILY_DRAMPA + #if P_FAMILY_NECROZMA static const struct Fusion sNecrozmaFusionTable[] = { {1, ITEM_N_SOLARIZER, SPECIES_NECROZMA, SPECIES_SOLGALEO, SPECIES_NECROZMA_DUSK_MANE, MOVE_SUNSTEEL_STRIKE, FORGET_EXTRA_MOVES}, @@ -1202,8 +1417,18 @@ static const struct FormChange sAlcremieFormChangeTable[] = }; #endif //P_FAMILY_MILCERY +#if P_FAMILY_FALINKS +static const struct FormChange sFalinksFormChangeTable[] = { +#if P_GEN_9_MEGA_EVOLUTIONS + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_FALINKS_MEGA, ITEM_FALINKSITE}, +#endif + {FORM_CHANGE_TERMINATOR}, +}; +#endif //P_FAMILY_FALINKS + #if P_FAMILY_EISCUE static const struct FormChange sEiscueFormChangeTable[] = { + {FORM_CHANGE_BATTLE_WEATHER, SPECIES_EISCUE_ICE, B_WEATHER_HAIL | B_WEATHER_SNOW, ABILITY_ICE_FACE}, {FORM_CHANGE_FAINT, SPECIES_EISCUE_ICE}, {FORM_CHANGE_END_BATTLE, SPECIES_EISCUE_ICE}, {FORM_CHANGE_TERMINATOR}, diff --git a/src/data/pokemon/form_species_tables.h b/src/data/pokemon/form_species_tables.h index 53ee47f933..ab703bc2d0 100644 --- a/src/data/pokemon/form_species_tables.h +++ b/src/data/pokemon/form_species_tables.h @@ -150,6 +150,16 @@ static const u16 sSandslashFormSpeciesIdTable[] = { }; #endif //P_FAMILY_SANDSHREW +#if P_FAMILY_CLEFAIRY +static const u16 sClefableFormSpeciesIdTable[] = { + SPECIES_CLEFABLE, +#if P_GEN_9_MEGA_EVOLUTIONS + SPECIES_CLEFABLE_MEGA, +#endif + FORM_SPECIES_END, +}; +#endif //P_FAMILY_CLEFAIRY + #if P_FAMILY_VULPIX static const u16 sVulpixFormSpeciesIdTable[] = { SPECIES_VULPIX, @@ -248,6 +258,16 @@ static const u16 sMachampFormSpeciesIdTable[] = { }; #endif //P_FAMILY_MACHOP +#if P_FAMILY_BELLSPROUT +static const u16 sVictreebelFormSpeciesIdTable[] = { + SPECIES_VICTREEBEL, +#if P_GEN_9_MEGA_EVOLUTIONS + SPECIES_VICTREEBEL_MEGA, +#endif + FORM_SPECIES_END, +}; +#endif //P_FAMILY_BELLSPROUT + #if P_FAMILY_GEODUDE static const u16 sGeodudeFormSpeciesIdTable[] = { SPECIES_GEODUDE, @@ -445,6 +465,16 @@ static const u16 sKangaskhanFormSpeciesIdTable[] = { }; #endif //P_FAMILY_KANGASKHAN +#if P_FAMILY_STARYU +static const u16 sStarmieFormSpeciesIdTable[] = { + SPECIES_STARMIE, +#if P_GEN_9_MEGA_EVOLUTIONS + SPECIES_STARMIE_MEGA, +#endif + FORM_SPECIES_END, +}; +#endif //P_FAMILY_STARYU + #if P_FAMILY_MR_MIME static const u16 sMrMimeFormSpeciesIdTable[] = { SPECIES_MR_MIME, @@ -570,6 +600,16 @@ static const u16 sMoltresFormSpeciesIdTable[] = { }; #endif //P_FAMILY_MOLTRES +#if P_FAMILY_DRATINI +static const u16 sDragoniteFormSpeciesIdTable[] = { + SPECIES_DRAGONITE, +#if P_GEN_9_MEGA_EVOLUTIONS + SPECIES_DRAGONITE_MEGA, +#endif + FORM_SPECIES_END, +}; +#endif //P_FAMILY_DRATINI + #if P_FAMILY_MEWTWO static const u16 sMewtwoFormSpeciesIdTable[] = { SPECIES_MEWTWO, @@ -581,6 +621,16 @@ static const u16 sMewtwoFormSpeciesIdTable[] = { }; #endif //P_FAMILY_MEWTWO +#if P_FAMILY_CHIKORITA +static const u16 sMeganiumFormSpeciesIdTable[] = { + SPECIES_MEGANIUM, +#if P_GEN_9_MEGA_EVOLUTIONS + SPECIES_MEGANIUM_MEGA, +#endif + FORM_SPECIES_END, +}; +#endif //P_FAMILY_CHIKORITA + #if P_FAMILY_CYNDAQUIL static const u16 sTyphlosionFormSpeciesIdTable[] = { SPECIES_TYPHLOSION, @@ -591,6 +641,16 @@ static const u16 sTyphlosionFormSpeciesIdTable[] = { }; #endif //P_FAMILY_CYNDAQUIL +#if P_FAMILY_TOTODILE +static const u16 sFeraligatrFormSpeciesIdTable[] = { + SPECIES_FERALIGATR, +#if P_GEN_9_MEGA_EVOLUTIONS + SPECIES_FERALIGATR_MEGA, +#endif + FORM_SPECIES_END, +}; +#endif //P_FAMILY_TOTODILE + #if P_FAMILY_MAREEP static const u16 sAmpharosFormSpeciesIdTable[] = { SPECIES_AMPHAROS, @@ -701,6 +761,16 @@ static const u16 sCorsolaFormSpeciesIdTable[] = { }; #endif //P_FAMILY_CORSOLA +#if P_FAMILY_SKARMORY +static const u16 sSkarmoryFormSpeciesIdTable[] = { + SPECIES_SKARMORY, +#if P_GEN_9_MEGA_EVOLUTIONS + SPECIES_SKARMORY_MEGA, +#endif + FORM_SPECIES_END, +}; +#endif //P_FAMILY_SKARMORY + #if P_FAMILY_HOUNDOUR static const u16 sHoundoomFormSpeciesIdTable[] = { SPECIES_HOUNDOOM, @@ -907,6 +977,14 @@ static const u16 sGlalieFormSpeciesIdTable[] = { #endif FORM_SPECIES_END, }; + +static const u16 sFroslassFormSpeciesIdTable[] = { + SPECIES_FROSLASS, +#if P_GEN_9_MEGA_EVOLUTIONS + SPECIES_FROSLASS_MEGA, +#endif + FORM_SPECIES_END, +}; #endif //P_FAMILY_SNORUNT #if P_FAMILY_BAGON @@ -1142,6 +1220,16 @@ static const u16 sArceusFormSpeciesIdTable[] = { }; #endif //P_FAMILY_ARCEUS +#if P_FAMILY_TEPIG +static const u16 sEmboarFormSpeciesIdTable[] = { + SPECIES_EMBOAR, +#if P_GEN_9_MEGA_EVOLUTIONS + SPECIES_EMBOAR_MEGA, +#endif + FORM_SPECIES_END, +}; +#endif //P_FAMILY_TEPIG + #if P_FAMILY_OSHAWOTT static const u16 sSamurottFormSpeciesIdTable[] = { SPECIES_SAMUROTT, @@ -1152,6 +1240,16 @@ static const u16 sSamurottFormSpeciesIdTable[] = { }; #endif //P_FAMILY_OSHAWOTT +#if P_FAMILY_DRILBUR +static const u16 sExcadrillFormSpeciesIdTable[] = { + SPECIES_EXCADRILL, +#if P_GEN_9_MEGA_EVOLUTIONS + SPECIES_EXCADRILL_MEGA, +#endif + FORM_SPECIES_END, +}; +#endif //P_FAMILY_DRILBUR + #if P_FAMILY_AUDINO static const u16 sAudinoFormSpeciesIdTable[] = { SPECIES_AUDINO, @@ -1162,6 +1260,16 @@ static const u16 sAudinoFormSpeciesIdTable[] = { }; #endif //P_FAMILY_AUDINO +#if P_FAMILY_VENIPEDE +static const u16 sScolipedeFormSpeciesIdTable[] = { + SPECIES_SCOLIPEDE, +#if P_GEN_9_MEGA_EVOLUTIONS + SPECIES_SCOLIPEDE_MEGA, +#endif + FORM_SPECIES_END, +}; +#endif //P_FAMILY_VENIPEDE + #if P_FAMILY_PETILIL static const u16 sLilligantFormSpeciesIdTable[] = { SPECIES_LILLIGANT, @@ -1207,6 +1315,16 @@ static const u16 sDarmanitanFormSpeciesIdTable[] = { }; #endif //P_FAMILY_DARUMAKA +#if P_FAMILY_SCRAGGY +static const u16 sScraftyFormSpeciesIdTable[] = { + SPECIES_SCRAFTY, +#if P_GEN_9_MEGA_EVOLUTIONS + SPECIES_SCRAFTY_MEGA, +#endif + FORM_SPECIES_END, +}; +#endif //P_FAMILY_SCRAGGY + #if P_FAMILY_YAMASK static const u16 sYamaskFormSpeciesIdTable[] = { SPECIES_YAMASK, @@ -1263,6 +1381,26 @@ static const u16 sSawsbuckFormSpeciesIdTable[] = { }; #endif //P_FAMILY_DEERLING +#if P_FAMILY_TYNAMO +static const u16 sEelektrossFormSpeciesIdTable[] = { + SPECIES_EELEKTROSS, +#if P_GEN_9_MEGA_EVOLUTIONS + SPECIES_EELEKTROSS_MEGA, +#endif + FORM_SPECIES_END, +}; +#endif //P_FAMILY_TYNAMO + +#if P_FAMILY_LITWICK +static const u16 sChandelureFormSpeciesIdTable[] = { + SPECIES_CHANDELURE, +#if P_GEN_9_MEGA_EVOLUTIONS + SPECIES_CHANDELURE_MEGA, +#endif + FORM_SPECIES_END, +}; +#endif //P_FAMILY_LITWICK + #if P_FAMILY_STUNFISK static const u16 sStunfiskFormSpeciesIdTable[] = { SPECIES_STUNFISK, @@ -1343,11 +1481,34 @@ static const u16 sGenesectFormSpeciesIdTable[] = { }; #endif //P_FAMILY_GENESECT +#if P_FAMILY_CHESPIN +static const u16 sChesnaughtFormSpeciesIdTable[] = { + SPECIES_CHESNAUGHT, +#if P_GEN_9_MEGA_EVOLUTIONS + SPECIES_CHESNAUGHT_MEGA, +#endif + FORM_SPECIES_END, +}; +#endif //P_FAMILY_CHESPIN + +#if P_FAMILY_FENNEKIN +static const u16 sDelphoxFormSpeciesIdTable[] = { + SPECIES_DELPHOX, +#if P_GEN_9_MEGA_EVOLUTIONS + SPECIES_DELPHOX_MEGA, +#endif + FORM_SPECIES_END, +}; +#endif //P_FAMILY_FENNEKIN + #if P_FAMILY_FROAKIE static const u16 sGreninjaFormSpeciesIdTable[] = { SPECIES_GRENINJA, SPECIES_GRENINJA_BATTLE_BOND, SPECIES_GRENINJA_ASH, +#if P_GEN_9_MEGA_EVOLUTIONS + SPECIES_GRENINJA_MEGA, +#endif FORM_SPECIES_END, }; #endif //P_FAMILY_FROAKIE @@ -1426,6 +1587,16 @@ static const u16 sVivillonFormSpeciesIdTable[] = { }; #endif //P_FAMILY_SCATTERBUG +#if P_FAMILY_LITLEO +static const u16 sPyroarFormSpeciesIdTable[] = { + SPECIES_PYROAR, +#if P_GEN_9_MEGA_EVOLUTIONS + SPECIES_PYROAR_MEGA, +#endif + FORM_SPECIES_END, +}; +#endif //P_FAMILY_LITLEO + #if P_FAMILY_FLABEBE static const u16 sFlabebeFormSpeciesIdTable[] = { SPECIES_FLABEBE_RED, @@ -1443,6 +1614,9 @@ static const u16 sFloetteFormSpeciesIdTable[] = { SPECIES_FLOETTE_BLUE, SPECIES_FLOETTE_WHITE, SPECIES_FLOETTE_ETERNAL, +#if P_GEN_9_MEGA_EVOLUTIONS + SPECIES_FLOETTE_MEGA, +#endif FORM_SPECIES_END, }; @@ -1488,6 +1662,46 @@ static const u16 sAegislashFormSpeciesIdTable[] = { }; #endif //P_FAMILY_HONEDGE +#if P_FAMILY_INKAY +static const u16 sMalamarFormSpeciesIdTable[] = { + SPECIES_MALAMAR, +#if P_GEN_9_MEGA_EVOLUTIONS + SPECIES_MALAMAR_MEGA, +#endif + FORM_SPECIES_END, +}; +#endif //P_FAMILY_INKAY + +#if P_FAMILY_BINACLE +static const u16 sBarbaracleFormSpeciesIdTable[] = { + SPECIES_BARBARACLE, +#if P_GEN_9_MEGA_EVOLUTIONS + SPECIES_BARBARACLE_MEGA, +#endif + FORM_SPECIES_END, +}; +#endif //P_FAMILY_BINACLE + +#if P_FAMILY_SKRELP +static const u16 sDragalgeFormSpeciesIdTable[] = { + SPECIES_DRAGALGE, +#if P_GEN_9_MEGA_EVOLUTIONS + SPECIES_DRAGALGE_MEGA, +#endif + FORM_SPECIES_END, +}; +#endif //P_FAMILY_SKRELP + +#if P_FAMILY_HAWLUCHA +static const u16 sHawluchaFormSpeciesIdTable[] = { + SPECIES_HAWLUCHA, +#if P_GEN_9_MEGA_EVOLUTIONS + SPECIES_HAWLUCHA_MEGA, +#endif + FORM_SPECIES_END, +}; +#endif //P_FAMILY_HAWLUCHA + #if P_FAMILY_GOOMY static const u16 sSliggooFormSpeciesIdTable[] = { SPECIES_SLIGGOO, @@ -1549,6 +1763,9 @@ static const u16 sZygardeFormSpeciesIdTable[] = { SPECIES_ZYGARDE_10_POWER_CONSTRUCT, SPECIES_ZYGARDE_50_POWER_CONSTRUCT, SPECIES_ZYGARDE_COMPLETE, +#if P_GEN_9_MEGA_EVOLUTIONS + SPECIES_ZYGARDE_MEGA, +#endif FORM_SPECIES_END, }; #endif //P_FAMILY_ZYGARDE @@ -1724,6 +1941,16 @@ static const u16 sMimikyuFormSpeciesIdTable[] = { }; #endif //P_FAMILY_MIMIKYU +#if P_FAMILY_DRAMPA +static const u16 sDrampaFormSpeciesIdTable[] = { + SPECIES_DRAMPA, +#if P_GEN_9_MEGA_EVOLUTIONS + SPECIES_DRAMPA_MEGA, +#endif + FORM_SPECIES_END, +}; +#endif //P_FAMILY_DRAMPA + #if P_FAMILY_JANGMO_O static const u16 sKommoOFormSpeciesIdTable[] = { SPECIES_KOMMO_O, @@ -1999,6 +2226,16 @@ static const u16 sAlcremieFormSpeciesIdTable[] = { }; #endif //P_FAMILY_MILCERY +#if P_FAMILY_FALINKS +static const u16 sFalinksFormSpeciesIdTable[] = { + SPECIES_FALINKS, +#if P_GEN_9_MEGA_EVOLUTIONS + SPECIES_FALINKS_MEGA, +#endif + FORM_SPECIES_END, +}; +#endif //P_FAMILY_FALINKS + #if P_FAMILY_EISCUE static const u16 sEiscueFormSpeciesIdTable[] = { SPECIES_EISCUE_ICE, diff --git a/src/data/pokemon/species_info/gen_1_families.h b/src/data/pokemon/species_info/gen_1_families.h index e99cc277a8..8139b90ed8 100644 --- a/src/data/pokemon/species_info/gen_1_families.h +++ b/src/data/pokemon/species_info/gen_1_families.h @@ -2914,8 +2914,8 @@ const struct SpeciesInfo gSpeciesInfoGen1[] = .teachableLearnset = sPikachuTeachableLearnset, .formSpeciesIdTable = sPikachuFormSpeciesIdTable, .formChangeTable = sPikachuFormChangeTable, - .evolutions = EVOLUTION({EVO_ITEM, ITEM_THUNDER_STONE, SPECIES_RAICHU}, - {EVO_NONE, 0, SPECIES_RAICHU_ALOLA}), + .evolutions = EVOLUTION({EVO_ITEM, ITEM_THUNDER_STONE, SPECIES_RAICHU, CONDITIONS({IF_NOT_REGION, REGION_ALOLA})}, + {EVO_ITEM, ITEM_THUNDER_STONE, SPECIES_RAICHU_ALOLA, CONDITIONS({IF_REGION, REGION_ALOLA})}), }, #if P_COSPLAY_PIKACHU_FORMS @@ -4941,7 +4941,96 @@ const struct SpeciesInfo gSpeciesInfoGen1[] = ) .levelUpLearnset = sClefableLevelUpLearnset, .teachableLearnset = sClefableTeachableLearnset, + .formSpeciesIdTable = sClefableFormSpeciesIdTable, + .formChangeTable = sClefableFormChangeTable, }, + +#if P_GEN_9_MEGA_EVOLUTIONS + [SPECIES_CLEFABLE_MEGA] = + { + .baseHP = 95, + .baseAttack = 80, + .baseDefense = 93, + .baseSpeed = 70, + .baseSpAttack = 135, + .baseSpDefense = 110, + .types = MON_TYPES(TYPE_FAIRY, TYPE_FLYING), + .catchRate = 25, + #if P_UPDATED_EXP_YIELDS >= GEN_8 + .expYield = 242, + #elif P_UPDATED_EXP_YIELDS >= GEN_7 + .expYield = 217, + #elif P_UPDATED_EXP_YIELDS >= GEN_5 + .expYield = 213, + #else + .expYield = 129, + #endif + .evYield_HP = 3, + .itemRare = ITEM_MOON_STONE, + .genderRatio = PERCENT_FEMALE(75), + .eggCycles = 10, + .friendship = 140, + .growthRate = GROWTH_FAST, + .eggGroups = MON_EGG_GROUPS(EGG_GROUP_FAIRY), + #if P_UPDATED_ABILITIES >= GEN_4 + .abilities = { ABILITY_CUTE_CHARM, ABILITY_MAGIC_GUARD, ABILITY_UNAWARE }, + #else + .abilities = { ABILITY_CUTE_CHARM, ABILITY_NONE, ABILITY_UNAWARE }, + #endif + .bodyColor = BODY_COLOR_PINK, + .speciesName = _("Clefable"), + .cryId = CRY_CLEFABLE, // CRY_CLEFABLE_MEGA, + .natDexNum = NATIONAL_DEX_CLEFABLE, + .categoryName = _("Fairy"), + .height = 17, + .weight = 423, + .description = COMPOUND_STRING( + "It flies by using the power of\n" + "moonlight to control gravity within\n" + "a radius of over 32 feet around it."), + .frontPic = gMonFrontPic_CircledQuestionMark, + .frontPicSize = MON_COORDS_SIZE(40, 40), + .frontPicYOffset = 12, + .frontAnimFrames = sAnims_TwoFramePlaceHolder, + .frontAnimId = ANIM_V_SQUISH_AND_BOUNCE, + .backPic = gMonBackPic_CircledQuestionMark, + .backPicSize = MON_COORDS_SIZE(40, 40), + .backPicYOffset = 12, + .backAnimId = BACK_ANIM_NONE, + .palette = gMonPalette_CircledQuestionMark, + .shinyPalette = gMonShinyPalette_CircledQuestionMark, + .iconSprite = gMonIcon_QuestionMark, + .iconPalIndex = 0, + .pokemonJumpType = PKMN_JUMP_TYPE_NONE, + FOOTPRINT(QuestionMark) + SHADOW(-1, 0, SHADOW_SIZE_M) + #if OW_BATTLE_ONLY_FORMS + .overworldData = { + .tileTag = TAG_NONE, + .paletteTag = OBJ_EVENT_PAL_TAG_SUBSTITUTE, + .reflectionPaletteTag = OBJ_EVENT_PAL_TAG_NONE, + .size = 512, + .width = 32, + .height = 32, + .paletteSlot = PALSLOT_NPC_1, + .shadowSize = SHADOW_SIZE_M, + .inanimate = FALSE, + .compressed = COMP, + .tracks = TRACKS_FOOT, + .oam = &gObjectEventBaseOam_32x32, + .subspriteTables = sOamTables_32x32, + .anims = sAnimTable_Following, + .images = sPicTable_Substitute, + .affineAnims = gDummySpriteAffineAnimTable, + }, + #endif //OW_BATTLE_ONLY_FORMS + .isMegaEvolution = TRUE, + .levelUpLearnset = sClefableLevelUpLearnset, + .teachableLearnset = sClefableTeachableLearnset, + .formSpeciesIdTable = sClefableFormSpeciesIdTable, + .formChangeTable = sClefableFormChangeTable, + }, +#endif //P_GEN_9_MEGA_EVOLUTIONS #endif //P_FAMILY_CLEFAIRY #if P_FAMILY_VULPIX @@ -9005,7 +9094,92 @@ const struct SpeciesInfo gSpeciesInfoGen1[] = ) .levelUpLearnset = sVictreebelLevelUpLearnset, .teachableLearnset = sVictreebelTeachableLearnset, + .formSpeciesIdTable = sVictreebelFormSpeciesIdTable, + .formChangeTable = sVictreebelFormChangeTable, }, + +#if P_GEN_9_MEGA_EVOLUTIONS + [SPECIES_VICTREEBEL_MEGA] = + { + .baseHP = 80, + .baseAttack = 125, + .baseDefense = 85, + .baseSpeed = 70, + .baseSpAttack = 135, + .baseSpDefense = 95, + .types = MON_TYPES(TYPE_GRASS, TYPE_POISON), + .catchRate = 45, + #if P_UPDATED_EXP_YIELDS >= GEN_8 + .expYield = 245, + #elif P_UPDATED_EXP_YIELDS >= GEN_7 + .expYield = 221, + #elif P_UPDATED_EXP_YIELDS >= GEN_5 + .expYield = 216, + #else + .expYield = 191, + #endif + .evYield_Attack = 3, + .genderRatio = PERCENT_FEMALE(50), + .eggCycles = 20, + .friendship = STANDARD_FRIENDSHIP, + .growthRate = GROWTH_MEDIUM_SLOW, + .eggGroups = MON_EGG_GROUPS(EGG_GROUP_GRASS), + .abilities = { ABILITY_CHLOROPHYLL, ABILITY_NONE, ABILITY_GLUTTONY }, + .bodyColor = BODY_COLOR_GREEN, + .speciesName = _("Victreebel"), + .cryId = CRY_VICTREEBEL, // CRY_VICTREEBEL_MEGA, + .natDexNum = NATIONAL_DEX_VICTREEBEL, + .categoryName = _("Flycatcher"), + .height = 45, + .weight = 1255, + .description = COMPOUND_STRING( + "The volume of this Pokémon's acid\n" + "has increased due to Mega Evolution,\n" + "filling its mouth. If not careful,\n" + "the acid will overflow and spill out."), + .frontPic = gMonFrontPic_CircledQuestionMark, + .frontPicSize = MON_COORDS_SIZE(40, 40), + .frontPicYOffset = 12, + .frontAnimFrames = sAnims_TwoFramePlaceHolder, + .frontAnimId = ANIM_V_SQUISH_AND_BOUNCE, + .backPic = gMonBackPic_CircledQuestionMark, + .backPicSize = MON_COORDS_SIZE(40, 40), + .backPicYOffset = 12, + .backAnimId = BACK_ANIM_NONE, + .palette = gMonPalette_CircledQuestionMark, + .shinyPalette = gMonShinyPalette_CircledQuestionMark, + .iconSprite = gMonIcon_QuestionMark, + .iconPalIndex = 0, + .pokemonJumpType = PKMN_JUMP_TYPE_NONE, + FOOTPRINT(QuestionMark) + SHADOW(-1, 0, SHADOW_SIZE_M) + #if OW_BATTLE_ONLY_FORMS + .overworldData = { + .tileTag = TAG_NONE, + .paletteTag = OBJ_EVENT_PAL_TAG_SUBSTITUTE, + .reflectionPaletteTag = OBJ_EVENT_PAL_TAG_NONE, + .size = 512, + .width = 32, + .height = 32, + .paletteSlot = PALSLOT_NPC_1, + .shadowSize = SHADOW_SIZE_M, + .inanimate = FALSE, + .compressed = COMP, + .tracks = TRACKS_FOOT, + .oam = &gObjectEventBaseOam_32x32, + .subspriteTables = sOamTables_32x32, + .anims = sAnimTable_Following, + .images = sPicTable_Substitute, + .affineAnims = gDummySpriteAffineAnimTable, + }, + #endif //OW_BATTLE_ONLY_FORMS + .isMegaEvolution = TRUE, + .levelUpLearnset = sVictreebelLevelUpLearnset, + .teachableLearnset = sVictreebelTeachableLearnset, + .formSpeciesIdTable = sVictreebelFormSpeciesIdTable, + .formChangeTable = sVictreebelFormChangeTable, + }, +#endif //P_GEN_9_MEGA_EVOLUTIONS #endif //P_FAMILY_BELLSPROUT #if P_FAMILY_TENTACOOL @@ -12842,8 +13016,8 @@ const struct SpeciesInfo gSpeciesInfoGen1[] = .levelUpLearnset = sExeggcuteLevelUpLearnset, .teachableLearnset = sExeggcuteTeachableLearnset, .eggMoveLearnset = sExeggcuteEggMoveLearnset, - .evolutions = EVOLUTION({EVO_ITEM, ITEM_LEAF_STONE, SPECIES_EXEGGUTOR}, - {EVO_NONE, 0, SPECIES_EXEGGUTOR_ALOLA}), + .evolutions = EVOLUTION({EVO_ITEM, ITEM_LEAF_STONE, SPECIES_EXEGGUTOR, CONDITIONS({IF_NOT_REGION, REGION_ALOLA})}, + {EVO_ITEM, ITEM_LEAF_STONE, SPECIES_EXEGGUTOR_ALOLA, CONDITIONS({IF_REGION, REGION_ALOLA})}), }, #if P_UPDATED_EXP_YIELDS >= GEN_7 @@ -13066,8 +13240,8 @@ const struct SpeciesInfo gSpeciesInfoGen1[] = .levelUpLearnset = sCuboneLevelUpLearnset, .teachableLearnset = sCuboneTeachableLearnset, .eggMoveLearnset = sCuboneEggMoveLearnset, - .evolutions = EVOLUTION({EVO_LEVEL, 28, SPECIES_MAROWAK}, - {EVO_NONE, 0, SPECIES_MAROWAK_ALOLA}, + .evolutions = EVOLUTION({EVO_LEVEL, 28, SPECIES_MAROWAK, CONDITIONS({IF_NOT_REGION, REGION_ALOLA})}, + {EVO_LEVEL, 28, SPECIES_MAROWAK_ALOLA, CONDITIONS({IF_REGION, REGION_ALOLA}, {IF_TIME, TIME_NIGHT})}, {EVO_NONE, 0, SPECIES_MAROWAK_ALOLA_TOTEM}), }, @@ -13791,8 +13965,8 @@ const struct SpeciesInfo gSpeciesInfoGen1[] = .levelUpLearnset = sKoffingLevelUpLearnset, .teachableLearnset = sKoffingTeachableLearnset, .eggMoveLearnset = sKoffingEggMoveLearnset, - .evolutions = EVOLUTION({EVO_LEVEL, 35, SPECIES_WEEZING}, - {EVO_NONE, 0, SPECIES_WEEZING_GALAR}), + .evolutions = EVOLUTION({EVO_LEVEL, 35, SPECIES_WEEZING, CONDITIONS({IF_NOT_REGION, REGION_GALAR})}, + {EVO_LEVEL, 35, SPECIES_WEEZING_GALAR, CONDITIONS({IF_REGION, REGION_GALAR})}), }, [SPECIES_WEEZING] = @@ -15256,7 +15430,86 @@ const struct SpeciesInfo gSpeciesInfoGen1[] = ) .levelUpLearnset = sStarmieLevelUpLearnset, .teachableLearnset = sStarmieTeachableLearnset, + .formSpeciesIdTable = sStarmieFormSpeciesIdTable, + .formChangeTable = sStarmieFormChangeTable, }, + +#if P_GEN_9_MEGA_EVOLUTIONS + [SPECIES_STARMIE_MEGA] = + { + .baseHP = 60, + .baseAttack = 140, + .baseDefense = 105, + .baseSpeed = 120, + .baseSpAttack = 130, + .baseSpDefense = 105, + .types = MON_TYPES(TYPE_WATER, TYPE_PSYCHIC), + .catchRate = 60, + .expYield = (P_UPDATED_EXP_YIELDS >= GEN_5) ? 182 : 207, + .evYield_Speed = 2, + .itemCommon = ITEM_STARDUST, + .itemRare = ITEM_STAR_PIECE, + .genderRatio = MON_GENDERLESS, + .eggCycles = 20, + .friendship = STANDARD_FRIENDSHIP, + .growthRate = GROWTH_SLOW, + .eggGroups = MON_EGG_GROUPS(EGG_GROUP_WATER_3), + .abilities = { ABILITY_ILLUMINATE, ABILITY_NATURAL_CURE, ABILITY_ANALYTIC }, + .bodyColor = BODY_COLOR_PURPLE, + .speciesName = _("Starmie"), + .cryId = CRY_STARMIE, // CRY_STARMIE_MEGA, + .natDexNum = NATIONAL_DEX_STARMIE, + .categoryName = _("Mysterious"), + .height = 23, + .weight = 800, + .description = COMPOUND_STRING( + "Its movements have become more\n" + "humanlike. Whether it's simply\n" + "trying to communicate or wants to\n" + "supplant humanity is unclear."), + .frontPic = gMonFrontPic_CircledQuestionMark, + .frontPicSize = MON_COORDS_SIZE(40, 40), + .frontPicYOffset = 12, + .frontAnimFrames = sAnims_TwoFramePlaceHolder, + .frontAnimId = ANIM_V_SQUISH_AND_BOUNCE, + .backPic = gMonBackPic_CircledQuestionMark, + .backPicSize = MON_COORDS_SIZE(40, 40), + .backPicYOffset = 12, + .backAnimId = BACK_ANIM_NONE, + .palette = gMonPalette_CircledQuestionMark, + .shinyPalette = gMonShinyPalette_CircledQuestionMark, + .iconSprite = gMonIcon_QuestionMark, + .iconPalIndex = 0, + .pokemonJumpType = PKMN_JUMP_TYPE_NONE, + FOOTPRINT(QuestionMark) + SHADOW(-1, 0, SHADOW_SIZE_M) + #if OW_BATTLE_ONLY_FORMS + .overworldData = { + .tileTag = TAG_NONE, + .paletteTag = OBJ_EVENT_PAL_TAG_SUBSTITUTE, + .reflectionPaletteTag = OBJ_EVENT_PAL_TAG_NONE, + .size = 512, + .width = 32, + .height = 32, + .paletteSlot = PALSLOT_NPC_1, + .shadowSize = SHADOW_SIZE_M, + .inanimate = FALSE, + .compressed = COMP, + .tracks = TRACKS_FOOT, + .oam = &gObjectEventBaseOam_32x32, + .subspriteTables = sOamTables_32x32, + .anims = sAnimTable_Following, + .images = sPicTable_Substitute, + .affineAnims = gDummySpriteAffineAnimTable, + }, + #endif //OW_BATTLE_ONLY_FORMS + .isMegaEvolution = TRUE, + .levelUpLearnset = sStarmieLevelUpLearnset, + .teachableLearnset = sStarmieTeachableLearnset, + .formSpeciesIdTable = sStarmieFormSpeciesIdTable, + .formChangeTable = sStarmieFormChangeTable, + }, +#endif //P_GEN_9_MEGA_EVOLUTIONS #endif //P_FAMILY_STARYU #if P_FAMILY_MR_MIME @@ -15336,8 +15589,8 @@ const struct SpeciesInfo gSpeciesInfoGen1[] = .levelUpLearnset = sMimeJrLevelUpLearnset, .teachableLearnset = sMimeJrTeachableLearnset, .eggMoveLearnset = sMimeJrEggMoveLearnset, - .evolutions = EVOLUTION({EVO_LEVEL, 0, SPECIES_MR_MIME, CONDITIONS({IF_KNOWS_MOVE, MOVE_MIMIC})}, - {EVO_NONE, 0, SPECIES_MR_MIME_GALAR}), + .evolutions = EVOLUTION({EVO_LEVEL, 0, SPECIES_MR_MIME, CONDITIONS({IF_KNOWS_MOVE, MOVE_MIMIC}, {IF_NOT_REGION, REGION_GALAR})}, + {EVO_LEVEL, 0, SPECIES_MR_MIME_GALAR, CONDITIONS({IF_KNOWS_MOVE, MOVE_MIMIC}, {IF_REGION, REGION_GALAR})}), }, #endif //P_GEN_4_CROSS_EVOS @@ -19645,7 +19898,91 @@ const struct SpeciesInfo gSpeciesInfoGen1[] = ) .levelUpLearnset = sDragoniteLevelUpLearnset, .teachableLearnset = sDragoniteTeachableLearnset, + .formSpeciesIdTable = sDragoniteFormSpeciesIdTable, + .formChangeTable = sDragoniteFormChangeTable, }, + +#if P_GEN_9_MEGA_EVOLUTIONS + [SPECIES_DRAGONITE_MEGA] = + { + .baseHP = 91, + .baseAttack = 124, + .baseDefense = 115, + .baseSpeed = 100, + .baseSpAttack = 145, + .baseSpDefense = 125, + .types = MON_TYPES(TYPE_DRAGON, TYPE_FLYING), + .catchRate = 45, + #if P_UPDATED_EXP_YIELDS >= GEN_8 + .expYield = 300, + #elif P_UPDATED_EXP_YIELDS >= GEN_5 + .expYield = 270, + #else + .expYield = 218, + #endif + .evYield_Attack = 3, + .itemRare = ITEM_DRAGON_SCALE, + .genderRatio = PERCENT_FEMALE(50), + .eggCycles = 40, + .friendship = 35, + .growthRate = GROWTH_SLOW, + .eggGroups = MON_EGG_GROUPS(EGG_GROUP_WATER_1, EGG_GROUP_DRAGON), + .abilities = { ABILITY_INNER_FOCUS, ABILITY_NONE, ABILITY_MULTISCALE }, + .bodyColor = BODY_COLOR_BROWN, + .speciesName = _("Dragonite"), + .cryId = CRY_DRAGONITE, // CRY_DRAGONITE_MEGA, + .natDexNum = NATIONAL_DEX_DRAGONITE, + .categoryName = _("Dragon"), + .height = 22, + .weight = 2900, + .description = COMPOUND_STRING( + "Mega Evolution has excessively\n" + "powered up this Pokémon's feelings\n" + "of kindness. It finishes off its\n" + "opponents with mercy in its heart."), + .frontPic = gMonFrontPic_CircledQuestionMark, + .frontPicSize = MON_COORDS_SIZE(40, 40), + .frontPicYOffset = 12, + .frontAnimFrames = sAnims_TwoFramePlaceHolder, + .frontAnimId = ANIM_V_SQUISH_AND_BOUNCE, + .backPic = gMonBackPic_CircledQuestionMark, + .backPicSize = MON_COORDS_SIZE(40, 40), + .backPicYOffset = 12, + .backAnimId = BACK_ANIM_NONE, + .palette = gMonPalette_CircledQuestionMark, + .shinyPalette = gMonShinyPalette_CircledQuestionMark, + .iconSprite = gMonIcon_QuestionMark, + .iconPalIndex = 0, + .pokemonJumpType = PKMN_JUMP_TYPE_NONE, + FOOTPRINT(QuestionMark) + SHADOW(-1, 0, SHADOW_SIZE_M) + #if OW_BATTLE_ONLY_FORMS + .overworldData = { + .tileTag = TAG_NONE, + .paletteTag = OBJ_EVENT_PAL_TAG_SUBSTITUTE, + .reflectionPaletteTag = OBJ_EVENT_PAL_TAG_NONE, + .size = 512, + .width = 32, + .height = 32, + .paletteSlot = PALSLOT_NPC_1, + .shadowSize = SHADOW_SIZE_M, + .inanimate = FALSE, + .compressed = COMP, + .tracks = TRACKS_FOOT, + .oam = &gObjectEventBaseOam_32x32, + .subspriteTables = sOamTables_32x32, + .anims = sAnimTable_Following, + .images = sPicTable_Substitute, + .affineAnims = gDummySpriteAffineAnimTable, + }, + #endif //OW_BATTLE_ONLY_FORMS + .isMegaEvolution = TRUE, + .levelUpLearnset = sDragoniteLevelUpLearnset, + .teachableLearnset = sDragoniteTeachableLearnset, + .formSpeciesIdTable = sDragoniteFormSpeciesIdTable, + .formChangeTable = sDragoniteFormChangeTable, + }, +#endif //P_GEN_9_MEGA_EVOLUTIONS #endif //P_FAMILY_DRATINI #if P_FAMILY_MEWTWO diff --git a/src/data/pokemon/species_info/gen_2_families.h b/src/data/pokemon/species_info/gen_2_families.h index 6b851d6dc9..a2694db5a8 100644 --- a/src/data/pokemon/species_info/gen_2_families.h +++ b/src/data/pokemon/species_info/gen_2_families.h @@ -221,7 +221,91 @@ const struct SpeciesInfo gSpeciesInfoGen2[] = ) .levelUpLearnset = sMeganiumLevelUpLearnset, .teachableLearnset = sMeganiumTeachableLearnset, + .formSpeciesIdTable = sMeganiumFormSpeciesIdTable, + .formChangeTable = sMeganiumFormChangeTable, }, + +#if P_GEN_9_MEGA_EVOLUTIONS + [SPECIES_MEGANIUM_MEGA] = + { + .baseHP = 80, + .baseAttack = 92, + .baseDefense = 115, + .baseSpeed = 80, + .baseSpAttack = 143, + .baseSpDefense = 115, + .types = MON_TYPES(TYPE_GRASS, TYPE_FAIRY), + .catchRate = 45, + #if P_UPDATED_EXP_YIELDS >= GEN_8 + .expYield = 263, + #elif P_UPDATED_EXP_YIELDS >= GEN_5 + .expYield = 236, + #else + .expYield = 208, + #endif + .evYield_Defense = 1, + .evYield_SpDefense = 2, + .genderRatio = PERCENT_FEMALE(12.5), + .eggCycles = 20, + .friendship = STANDARD_FRIENDSHIP, + .growthRate = GROWTH_MEDIUM_SLOW, + .eggGroups = MON_EGG_GROUPS(EGG_GROUP_MONSTER, EGG_GROUP_GRASS), + .abilities = { ABILITY_OVERGROW, ABILITY_NONE, ABILITY_LEAF_GUARD }, + .bodyColor = BODY_COLOR_GREEN, + .speciesName = _("Meganium"), + .cryId = CRY_MEGANIUM, // CRY_MEGANIUM_MEGA, + .natDexNum = NATIONAL_DEX_MEGANIUM, + .categoryName = _("Herb"), + .height = 24, + .weight = 2010, + .description = COMPOUND_STRING( + "This Pokémon can fire a tremendously\n" + "powerful Solar Beam from its four\n" + "flowers. Another name for this is\n" + "Mega Sol Cannon."), + .frontPic = gMonFrontPic_CircledQuestionMark, + .frontPicSize = MON_COORDS_SIZE(40, 40), + .frontPicYOffset = 12, + .frontAnimFrames = sAnims_TwoFramePlaceHolder, + .frontAnimId = ANIM_V_SQUISH_AND_BOUNCE, + .backPic = gMonBackPic_CircledQuestionMark, + .backPicSize = MON_COORDS_SIZE(40, 40), + .backPicYOffset = 12, + .backAnimId = BACK_ANIM_NONE, + .palette = gMonPalette_CircledQuestionMark, + .shinyPalette = gMonShinyPalette_CircledQuestionMark, + .iconSprite = gMonIcon_QuestionMark, + .iconPalIndex = 0, + .pokemonJumpType = PKMN_JUMP_TYPE_NONE, + FOOTPRINT(QuestionMark) + SHADOW(-1, 0, SHADOW_SIZE_M) + #if OW_BATTLE_ONLY_FORMS + .overworldData = { + .tileTag = TAG_NONE, + .paletteTag = OBJ_EVENT_PAL_TAG_SUBSTITUTE, + .reflectionPaletteTag = OBJ_EVENT_PAL_TAG_NONE, + .size = 512, + .width = 32, + .height = 32, + .paletteSlot = PALSLOT_NPC_1, + .shadowSize = SHADOW_SIZE_M, + .inanimate = FALSE, + .compressed = COMP, + .tracks = TRACKS_FOOT, + .oam = &gObjectEventBaseOam_32x32, + .subspriteTables = sOamTables_32x32, + .anims = sAnimTable_Following, + .images = sPicTable_Substitute, + .affineAnims = gDummySpriteAffineAnimTable, + }, + #endif //OW_BATTLE_ONLY_FORMS + .isMegaEvolution = TRUE, + .levelUpLearnset = sMeganiumLevelUpLearnset, + .teachableLearnset = sMeganiumTeachableLearnset, + .formSpeciesIdTable = sMeganiumFormSpeciesIdTable, + .formChangeTable = sMeganiumFormChangeTable, + }, +#endif //P_GEN_9_MEGA_EVOLUTIONS #endif //P_FAMILY_CHIKORITA #if P_FAMILY_CYNDAQUIL @@ -357,8 +441,8 @@ const struct SpeciesInfo gSpeciesInfoGen2[] = ) .levelUpLearnset = sQuilavaLevelUpLearnset, .teachableLearnset = sQuilavaTeachableLearnset, - .evolutions = EVOLUTION({EVO_LEVEL, 36, SPECIES_TYPHLOSION}, - {EVO_NONE, 0, SPECIES_TYPHLOSION_HISUI}), + .evolutions = EVOLUTION({EVO_LEVEL, 36, SPECIES_TYPHLOSION, CONDITIONS({IF_NOT_REGION, REGION_HISUI})}, + {EVO_LEVEL, 36, SPECIES_TYPHLOSION_HISUI, CONDITIONS({IF_REGION, REGION_HISUI})}), }, #if P_UPDATED_EXP_YIELDS >= GEN_8 @@ -714,7 +798,91 @@ const struct SpeciesInfo gSpeciesInfoGen2[] = ) .levelUpLearnset = sFeraligatrLevelUpLearnset, .teachableLearnset = sFeraligatrTeachableLearnset, + .formSpeciesIdTable = sFeraligatrFormSpeciesIdTable, + .formChangeTable = sFeraligatrFormChangeTable, }, + +#if P_GEN_9_MEGA_EVOLUTIONS + [SPECIES_FERALIGATR_MEGA] = + { + .baseHP = 85, + .baseAttack = 160, + .baseDefense = 125, + .baseSpeed = 78, + .baseSpAttack = 89, + .baseSpDefense = 93, + .types = MON_TYPES(TYPE_WATER, TYPE_DRAGON), + .catchRate = 45, + #if P_UPDATED_EXP_YIELDS >= GEN_8 + .expYield = 265, + #elif P_UPDATED_EXP_YIELDS >= GEN_5 + .expYield = 239, + #else + .expYield = 210, + #endif + .evYield_Attack = 2, + .evYield_Defense = 1, + .genderRatio = PERCENT_FEMALE(12.5), + .eggCycles = 20, + .friendship = STANDARD_FRIENDSHIP, + .growthRate = GROWTH_MEDIUM_SLOW, + .eggGroups = MON_EGG_GROUPS(EGG_GROUP_MONSTER, EGG_GROUP_WATER_1), + .abilities = { ABILITY_TORRENT, ABILITY_NONE, ABILITY_SHEER_FORCE }, + .bodyColor = BODY_COLOR_BLUE, + .speciesName = _("Feraligatr"), + .cryId = CRY_FERALIGATR, // CRY_FERALIGATR_MEGA, + .natDexNum = NATIONAL_DEX_FERALIGATR, + .categoryName = _("Double Jaw"), + .height = 23, + .weight = 1088, + .description = COMPOUND_STRING( + "With its arms and hoodlike fin, this\n" + "Pokémon forms a gigantic set of jaws\n" + "with a bite 10 times as powerful\n" + "as Mega Feraligatr's actual jaws."), + .frontPic = gMonFrontPic_CircledQuestionMark, + .frontPicSize = MON_COORDS_SIZE(40, 40), + .frontPicYOffset = 12, + .frontAnimFrames = sAnims_TwoFramePlaceHolder, + .frontAnimId = ANIM_V_SQUISH_AND_BOUNCE, + .backPic = gMonBackPic_CircledQuestionMark, + .backPicSize = MON_COORDS_SIZE(40, 40), + .backPicYOffset = 12, + .backAnimId = BACK_ANIM_NONE, + .palette = gMonPalette_CircledQuestionMark, + .shinyPalette = gMonShinyPalette_CircledQuestionMark, + .iconSprite = gMonIcon_QuestionMark, + .iconPalIndex = 0, + .pokemonJumpType = PKMN_JUMP_TYPE_NONE, + FOOTPRINT(QuestionMark) + SHADOW(-1, 0, SHADOW_SIZE_M) + #if OW_BATTLE_ONLY_FORMS + .overworldData = { + .tileTag = TAG_NONE, + .paletteTag = OBJ_EVENT_PAL_TAG_SUBSTITUTE, + .reflectionPaletteTag = OBJ_EVENT_PAL_TAG_NONE, + .size = 512, + .width = 32, + .height = 32, + .paletteSlot = PALSLOT_NPC_1, + .shadowSize = SHADOW_SIZE_M, + .inanimate = FALSE, + .compressed = COMP, + .tracks = TRACKS_FOOT, + .oam = &gObjectEventBaseOam_32x32, + .subspriteTables = sOamTables_32x32, + .anims = sAnimTable_Following, + .images = sPicTable_Substitute, + .affineAnims = gDummySpriteAffineAnimTable, + }, + #endif //OW_BATTLE_ONLY_FORMS + .isMegaEvolution = TRUE, + .levelUpLearnset = sFeraligatrLevelUpLearnset, + .teachableLearnset = sFeraligatrTeachableLearnset, + .formSpeciesIdTable = sFeraligatrFormSpeciesIdTable, + .formChangeTable = sFeraligatrFormChangeTable, + }, +#endif //P_GEN_9_MEGA_EVOLUTIONS #endif //P_FAMILY_TOTODILE #if P_FAMILY_SENTRET @@ -5819,7 +5987,7 @@ const struct SpeciesInfo gSpeciesInfoGen2[] = .levelUpLearnset = sUrsaringLevelUpLearnset, .teachableLearnset = sUrsaringTeachableLearnset, #if P_GEN_8_CROSS_EVOS - .evolutions = EVOLUTION({EVO_ITEM, ITEM_PEAT_BLOCK, SPECIES_URSALUNA, CONDITIONS({IF_TIME, TIME_NIGHT})}, + .evolutions = EVOLUTION({EVO_ITEM, ITEM_PEAT_BLOCK, SPECIES_URSALUNA, CONDITIONS({IF_REGION, REGION_HISUI}, {IF_TIME, TIME_NIGHT})}, {EVO_NONE, 0, SPECIES_URSALUNA_BLOODMOON}), #endif }, @@ -6993,7 +7161,85 @@ const struct SpeciesInfo gSpeciesInfoGen2[] = .levelUpLearnset = sSkarmoryLevelUpLearnset, .teachableLearnset = sSkarmoryTeachableLearnset, .eggMoveLearnset = sSkarmoryEggMoveLearnset, + .formSpeciesIdTable = sSkarmoryFormSpeciesIdTable, + .formChangeTable = sSkarmoryFormChangeTable, }, + +#if P_GEN_9_MEGA_EVOLUTIONS + [SPECIES_SKARMORY_MEGA] = + { + .baseHP = 65, + .baseAttack = 140, + .baseDefense = 110, + .baseSpeed = 110, + .baseSpAttack = 40, + .baseSpDefense = 100, + .types = MON_TYPES(TYPE_STEEL, TYPE_FLYING), + .catchRate = 25, + .expYield = (P_UPDATED_EXP_YIELDS >= GEN_5) ? 163 : 168, + .evYield_Defense = 2, + .itemRare = ITEM_METAL_COAT, + .genderRatio = PERCENT_FEMALE(50), + .eggCycles = 25, + .friendship = STANDARD_FRIENDSHIP, + .growthRate = GROWTH_SLOW, + .eggGroups = MON_EGG_GROUPS(EGG_GROUP_FLYING), + .abilities = { ABILITY_KEEN_EYE, ABILITY_STURDY, ABILITY_WEAK_ARMOR }, + .bodyColor = BODY_COLOR_GRAY, + .speciesName = _("Skarmory"), + .cryId = CRY_SKARMORY, // CRY_SKARMORY_MEGA, + .natDexNum = NATIONAL_DEX_SKARMORY, + .categoryName = _("Armor Bird"), + .height = 17, + .weight = 404, + .description = COMPOUND_STRING( + "Due to the effects of Mega Evolution,\n" + "its pincers have taken a more\n" + "diabolical form, ripping anything\n" + "they pierce to shreds."), + .frontPic = gMonFrontPic_CircledQuestionMark, + .frontPicSize = MON_COORDS_SIZE(40, 40), + .frontPicYOffset = 12, + .frontAnimFrames = sAnims_TwoFramePlaceHolder, + .frontAnimId = ANIM_V_SQUISH_AND_BOUNCE, + .backPic = gMonBackPic_CircledQuestionMark, + .backPicSize = MON_COORDS_SIZE(40, 40), + .backPicYOffset = 12, + .backAnimId = BACK_ANIM_NONE, + .palette = gMonPalette_CircledQuestionMark, + .shinyPalette = gMonShinyPalette_CircledQuestionMark, + .iconSprite = gMonIcon_QuestionMark, + .iconPalIndex = 0, + .pokemonJumpType = PKMN_JUMP_TYPE_NONE, + FOOTPRINT(QuestionMark) + SHADOW(-1, 0, SHADOW_SIZE_M) + #if OW_BATTLE_ONLY_FORMS + .overworldData = { + .tileTag = TAG_NONE, + .paletteTag = OBJ_EVENT_PAL_TAG_SUBSTITUTE, + .reflectionPaletteTag = OBJ_EVENT_PAL_TAG_NONE, + .size = 512, + .width = 32, + .height = 32, + .paletteSlot = PALSLOT_NPC_1, + .shadowSize = SHADOW_SIZE_M, + .inanimate = FALSE, + .compressed = COMP, + .tracks = TRACKS_FOOT, + .oam = &gObjectEventBaseOam_32x32, + .subspriteTables = sOamTables_32x32, + .anims = sAnimTable_Following, + .images = sPicTable_Substitute, + .affineAnims = gDummySpriteAffineAnimTable, + }, + #endif //OW_BATTLE_ONLY_FORMS + .isMegaEvolution = TRUE, + .levelUpLearnset = sSkarmoryLevelUpLearnset, + .teachableLearnset = sSkarmoryTeachableLearnset, + .formSpeciesIdTable = sSkarmoryFormSpeciesIdTable, + .formChangeTable = sSkarmoryFormChangeTable, + }, +#endif //P_GEN_9_MEGA_EVOLUTIONS #endif //P_FAMILY_SKARMORY #if P_FAMILY_HOUNDOUR diff --git a/src/data/pokemon/species_info/gen_3_families.h b/src/data/pokemon/species_info/gen_3_families.h index 0a1fbaa426..dac2847511 100644 --- a/src/data/pokemon/species_info/gen_3_families.h +++ b/src/data/pokemon/species_info/gen_3_families.h @@ -7111,13 +7111,17 @@ const struct SpeciesInfo gSpeciesInfoGen3[] = .frontPic = gMonFrontPic_Spinda, .frontPicSize = MON_COORDS_SIZE(48, 64), .frontPicYOffset = 8, - .frontAnimFrames = ANIM_FRAMES( - ANIMCMD_FRAME(0, 17), - ANIMCMD_FRAME(1, 23), - ANIMCMD_FRAME(0, 17), - ANIMCMD_FRAME(1, 23), - ANIMCMD_FRAME(0, 13), - ), + #if !P_GBA_STYLE_SPECIES_GFX + .frontAnimFrames = ANIM_FRAMES( + ANIMCMD_FRAME(0, 17), + ANIMCMD_FRAME(1, 23), + ANIMCMD_FRAME(0, 17), + ANIMCMD_FRAME(1, 23), + ANIMCMD_FRAME(0, 13), + ), + #else + .frontAnimFrames = sAnims_SingleFramePlaceHolder, + #endif .frontAnimId = P_GBA_STYLE_SPECIES_GFX ? ANIM_H_JUMPS : ANIM_CIRCLE_INTO_BG, .backPic = gMonBackPic_Spinda, .backPicSize = MON_COORDS_SIZE(56, 56), @@ -9028,13 +9032,17 @@ const struct SpeciesInfo gSpeciesInfoGen3[] = .frontPic = gMonFrontPic_CastformNormal, .frontPicSize = MON_COORDS_SIZE(24, 32), .frontPicYOffset = 17, - .frontAnimFrames = ANIM_FRAMES( - ANIMCMD_FRAME(0, 12), - ANIMCMD_FRAME(1, 24), - ANIMCMD_FRAME(0, 24), - ANIMCMD_FRAME(1, 24), - ANIMCMD_FRAME(0, 24), - ), + #if !P_GBA_STYLE_SPECIES_GFX + .frontAnimFrames = ANIM_FRAMES( + ANIMCMD_FRAME(0, 12), + ANIMCMD_FRAME(1, 24), + ANIMCMD_FRAME(0, 24), + ANIMCMD_FRAME(1, 24), + ANIMCMD_FRAME(0, 24), + ), + #else + .frontAnimFrames = sAnims_SingleFramePlaceHolder, + #endif .frontAnimId = ANIM_H_SLIDE_WOBBLE, .enemyMonElevation = 16, .backPic = gMonBackPic_CastformNormal, @@ -9102,21 +9110,25 @@ const struct SpeciesInfo gSpeciesInfoGen3[] = .frontPic = gMonFrontPic_CastformSunny, .frontPicSize = MON_COORDS_SIZE(40, 48), .frontPicYOffset = 9, - .frontAnimFrames = ANIM_FRAMES( - ANIMCMD_FRAME(0, 12), - ANIMCMD_FRAME(1, 12), - ANIMCMD_FRAME(0, 12), - ANIMCMD_FRAME(1, 12), - ANIMCMD_FRAME(0, 12), - ANIMCMD_FRAME(1, 12), - ANIMCMD_FRAME(0, 12), - ), - .frontAnimId = ANIM_GROW_VIBRATE, + #if !P_GBA_STYLE_SPECIES_GFX + .frontAnimFrames = ANIM_FRAMES( + ANIMCMD_FRAME(0, 12), + ANIMCMD_FRAME(1, 12), + ANIMCMD_FRAME(0, 12), + ANIMCMD_FRAME(1, 12), + ANIMCMD_FRAME(0, 12), + ANIMCMD_FRAME(1, 12), + ANIMCMD_FRAME(0, 12), + ), + #else + .frontAnimFrames = sAnims_SingleFramePlaceHolder, + #endif + .frontAnimId = P_GBA_STYLE_SPECIES_GFX ? ANIM_H_SLIDE_WOBBLE : ANIM_GROW_VIBRATE, .enemyMonElevation = 5, .backPic = gMonBackPic_CastformSunny, .backPicSize = MON_COORDS_SIZE(56, 64), .backPicYOffset = 0, - .backAnimId = BACK_ANIM_SHAKE_GLOW_RED, + .backAnimId = P_GBA_STYLE_SPECIES_GFX ? BACK_ANIM_CONVEX_DOUBLE_ARC : BACK_ANIM_SHAKE_GLOW_RED, .palette = gMonPalette_CastformSunny, .shinyPalette = gMonShinyPalette_CastformSunny, .iconSprite = gMonIcon_CastformSunny, @@ -9178,19 +9190,23 @@ const struct SpeciesInfo gSpeciesInfoGen3[] = .frontPic = gMonFrontPic_CastformRainy, .frontPicSize = MON_COORDS_SIZE(32, 48), .frontPicYOffset = 9, - .frontAnimFrames = ANIM_FRAMES( - ANIMCMD_FRAME(0, 22), - ANIMCMD_FRAME(1, 22), - ANIMCMD_FRAME(0, 22), - ANIMCMD_FRAME(1, 22), - ANIMCMD_FRAME(0, 11), - ), - .frontAnimId = ANIM_SWING_CONVEX_FAST, + #if !P_GBA_STYLE_SPECIES_GFX + .frontAnimFrames = ANIM_FRAMES( + ANIMCMD_FRAME(0, 22), + ANIMCMD_FRAME(1, 22), + ANIMCMD_FRAME(0, 22), + ANIMCMD_FRAME(1, 22), + ANIMCMD_FRAME(0, 11), + ), + #else + .frontAnimFrames = sAnims_SingleFramePlaceHolder, + #endif + .frontAnimId = P_GBA_STYLE_SPECIES_GFX ? ANIM_H_SLIDE_WOBBLE : ANIM_SWING_CONVEX_FAST, .enemyMonElevation = 5, .backPic = gMonBackPic_CastformRainy, .backPicSize = MON_COORDS_SIZE(40, 64), .backPicYOffset = 0, - .backAnimId = BACK_ANIM_SHRINK_GROW_VIBRATE, + .backAnimId = P_GBA_STYLE_SPECIES_GFX ? BACK_ANIM_CONVEX_DOUBLE_ARC : BACK_ANIM_SHRINK_GROW_VIBRATE, .palette = gMonPalette_CastformRainy, .shinyPalette = gMonShinyPalette_CastformRainy, .iconSprite = gMonIcon_CastformRainy, @@ -9252,19 +9268,23 @@ const struct SpeciesInfo gSpeciesInfoGen3[] = .frontPic = gMonFrontPic_CastformSnowy, .frontPicSize = MON_COORDS_SIZE(40, 56), .frontPicYOffset = 8, - .frontAnimFrames = ANIM_FRAMES( - ANIMCMD_FRAME(0, 5), - ANIMCMD_FRAME(1, 12), - ANIMCMD_FRAME(0, 12), - ANIMCMD_FRAME(1, 29), - ANIMCMD_FRAME(0, 12), - ), - .frontAnimId = ANIM_V_STRETCH, + #if !P_GBA_STYLE_SPECIES_GFX + .frontAnimFrames = ANIM_FRAMES( + ANIMCMD_FRAME(0, 5), + ANIMCMD_FRAME(1, 12), + ANIMCMD_FRAME(0, 12), + ANIMCMD_FRAME(1, 29), + ANIMCMD_FRAME(0, 12), + ), + #else + .frontAnimFrames = sAnims_SingleFramePlaceHolder, + #endif + .frontAnimId = P_GBA_STYLE_SPECIES_GFX ? ANIM_H_SLIDE_WOBBLE : ANIM_V_STRETCH, .enemyMonElevation = 5, .backPic = gMonBackPic_CastformSnowy, .backPicSize = MON_COORDS_SIZE(56, 64), .backPicYOffset = 0, - .backAnimId = BACK_ANIM_TRIANGLE_DOWN, + .backAnimId = P_GBA_STYLE_SPECIES_GFX ? BACK_ANIM_CONVEX_DOUBLE_ARC : BACK_ANIM_TRIANGLE_DOWN, .palette = gMonPalette_CastformSnowy, .shinyPalette = gMonShinyPalette_CastformSnowy, .iconSprite = gMonIcon_CastformSnowy, @@ -10516,7 +10536,84 @@ const struct SpeciesInfo gSpeciesInfoGen3[] = ) .levelUpLearnset = sFroslassLevelUpLearnset, .teachableLearnset = sFroslassTeachableLearnset, + .formSpeciesIdTable = sFroslassFormSpeciesIdTable, + .formChangeTable = sFroslassFormChangeTable, }, + +#if P_GEN_9_MEGA_EVOLUTIONS + [SPECIES_FROSLASS_MEGA] = + { + .baseHP = 70, + .baseAttack = 80, + .baseDefense = 70, + .baseSpeed = 120, + .baseSpAttack = 140, + .baseSpDefense = 100, + .types = MON_TYPES(TYPE_ICE, TYPE_GHOST), + .catchRate = 75, + .expYield = (P_UPDATED_EXP_YIELDS >= GEN_5) ? 168 : 187, + .evYield_Speed = 2, + .genderRatio = MON_FEMALE, + .eggCycles = 20, + .friendship = STANDARD_FRIENDSHIP, + .growthRate = GROWTH_MEDIUM_FAST, + .eggGroups = MON_EGG_GROUPS(EGG_GROUP_FAIRY, EGG_GROUP_MINERAL), + .abilities = { ABILITY_SNOW_CLOAK, ABILITY_NONE, ABILITY_CURSED_BODY }, + .bodyColor = BODY_COLOR_WHITE, + .speciesName = _("Froslass"), + .cryId = CRY_FROSLASS, // CRY_FROSLASS_MEGA, + .natDexNum = NATIONAL_DEX_FROSLASS, + .categoryName = _("Snow Land"), + .height = 26, + .weight = 296, + .description = COMPOUND_STRING( + "This Pokémon can use eerie cold\n" + "air imbued with ghost energy to\n" + "freeze even insubstantial things,\n" + "such as flames or the wind."), + .frontPic = gMonFrontPic_CircledQuestionMark, + .frontPicSize = MON_COORDS_SIZE(40, 40), + .frontPicYOffset = 12, + .frontAnimFrames = sAnims_TwoFramePlaceHolder, + .frontAnimId = ANIM_V_SQUISH_AND_BOUNCE, + .backPic = gMonBackPic_CircledQuestionMark, + .backPicSize = MON_COORDS_SIZE(40, 40), + .backPicYOffset = 12, + .backAnimId = BACK_ANIM_NONE, + .palette = gMonPalette_CircledQuestionMark, + .shinyPalette = gMonShinyPalette_CircledQuestionMark, + .iconSprite = gMonIcon_QuestionMark, + .iconPalIndex = 0, + .pokemonJumpType = PKMN_JUMP_TYPE_NONE, + FOOTPRINT(QuestionMark) + SHADOW(-1, 0, SHADOW_SIZE_M) + #if OW_BATTLE_ONLY_FORMS + .overworldData = { + .tileTag = TAG_NONE, + .paletteTag = OBJ_EVENT_PAL_TAG_SUBSTITUTE, + .reflectionPaletteTag = OBJ_EVENT_PAL_TAG_NONE, + .size = 512, + .width = 32, + .height = 32, + .paletteSlot = PALSLOT_NPC_1, + .shadowSize = SHADOW_SIZE_M, + .inanimate = FALSE, + .compressed = COMP, + .tracks = TRACKS_FOOT, + .oam = &gObjectEventBaseOam_32x32, + .subspriteTables = sOamTables_32x32, + .anims = sAnimTable_Following, + .images = sPicTable_Substitute, + .affineAnims = gDummySpriteAffineAnimTable, + }, + #endif //OW_BATTLE_ONLY_FORMS + .isMegaEvolution = TRUE, + .levelUpLearnset = sFroslassLevelUpLearnset, + .teachableLearnset = sFroslassTeachableLearnset, + .formSpeciesIdTable = sFroslassFormSpeciesIdTable, + .formChangeTable = sFroslassFormChangeTable, + }, +#endif //P_GEN_9_MEGA_EVOLUTIONS #endif //P_GEN_4_CROSS_EVOS #endif //P_FAMILY_SNORUNT @@ -12833,15 +12930,20 @@ const struct SpeciesInfo gSpeciesInfoGen3[] = .trainerOffset = 2, .frontPic = gMonFrontPic_DeoxysNormal, .frontPicSize = MON_COORDS_SIZE(64, 64), - .frontPicYOffset = 0, - .frontAnimFrames = ANIM_FRAMES( - ANIMCMD_FRAME(0, 16), - ANIMCMD_FRAME(1, 16), - ANIMCMD_FRAME(0, 26), - ANIMCMD_FRAME(1, 16), - ANIMCMD_FRAME(0, 16), - ), - .frontAnimId = ANIM_GROW_VIBRATE, + .frontPicYOffset = P_GBA_STYLE_SPECIES_GFX ? 1 : 0, + #if !P_GBA_STYLE_SPECIES_GFX + .frontAnimFrames = ANIM_FRAMES( + ANIMCMD_FRAME(0, 16), + ANIMCMD_FRAME(1, 16), + ANIMCMD_FRAME(0, 26), + ANIMCMD_FRAME(1, 16), + ANIMCMD_FRAME(0, 16), + ), + #else + .frontAnimFrames = sAnims_SingleFramePlaceHolder, + #endif + .frontAnimId = P_GBA_STYLE_SPECIES_GFX ? ANIM_H_PIVOT : ANIM_GROW_VIBRATE, + .enemyMonElevation = P_GBA_STYLE_SPECIES_GFX ? 8 : 0, .backPic = gMonBackPic_DeoxysNormal, .backPicSize = MON_COORDS_SIZE(64, 56), .backPicYOffset = P_GBA_STYLE_SPECIES_GFX ? 2 : 6, @@ -12904,19 +13006,24 @@ const struct SpeciesInfo gSpeciesInfoGen3[] = .trainerOffset = 2, .frontPic = gMonFrontPic_DeoxysAttack, .frontPicSize = MON_COORDS_SIZE(64, 64), - .frontPicYOffset = 0, - .frontAnimFrames = ANIM_FRAMES( - ANIMCMD_FRAME(0, 16), - ANIMCMD_FRAME(1, 16), - ANIMCMD_FRAME(0, 26), - ANIMCMD_FRAME(1, 16), - ANIMCMD_FRAME(0, 16), - ), - .frontAnimId = ANIM_GROW_VIBRATE, + .frontPicYOffset = P_GBA_STYLE_SPECIES_GFX ? 1 : 0, + #if !P_GBA_STYLE_SPECIES_GFX + .frontAnimFrames = ANIM_FRAMES( + ANIMCMD_FRAME(0, 16), + ANIMCMD_FRAME(1, 16), + ANIMCMD_FRAME(0, 26), + ANIMCMD_FRAME(1, 16), + ANIMCMD_FRAME(0, 16), + ), + #else + .frontAnimFrames = sAnims_SingleFramePlaceHolder, + #endif + .frontAnimId = P_GBA_STYLE_SPECIES_GFX ? ANIM_H_PIVOT : ANIM_GROW_VIBRATE, + .enemyMonElevation = P_GBA_STYLE_SPECIES_GFX ? 8 : 0, .backPic = gMonBackPic_DeoxysAttack, - .backPicSize = MON_COORDS_SIZE(64, 64), - .backPicYOffset = 1, - .backAnimId = BACK_ANIM_TRIANGLE_DOWN, + .backPicSize = P_GBA_STYLE_SPECIES_GFX ? MON_COORDS_SIZE(64, 56) : MON_COORDS_SIZE(64, 64), + .backPicYOffset = P_GBA_STYLE_SPECIES_GFX ? 7 : 1, + .backAnimId = P_GBA_STYLE_SPECIES_GFX ? BACK_ANIM_SHRINK_GROW_VIBRATE : BACK_ANIM_TRIANGLE_DOWN, .palette = gMonPalette_DeoxysAttack, .shinyPalette = gMonShinyPalette_DeoxysAttack, .iconSprite = gMonIcon_DeoxysAttack, @@ -12973,20 +13080,25 @@ const struct SpeciesInfo gSpeciesInfoGen3[] = .trainerScale = 290, .trainerOffset = 2, .frontPic = gMonFrontPic_DeoxysDefense, - .frontPicSize = MON_COORDS_SIZE(56, 64), - .frontPicYOffset = 0, - .frontAnimFrames = ANIM_FRAMES( - ANIMCMD_FRAME(0, 16), - ANIMCMD_FRAME(1, 16), - ANIMCMD_FRAME(0, 26), - ANIMCMD_FRAME(1, 16), - ANIMCMD_FRAME(0, 16), - ), - .frontAnimId = ANIM_GROW_VIBRATE, + .frontPicSize = P_GBA_STYLE_SPECIES_GFX ? MON_COORDS_SIZE(64, 64) : MON_COORDS_SIZE(56, 64), + .frontPicYOffset = P_GBA_STYLE_SPECIES_GFX ? 1 : 0, + #if !P_GBA_STYLE_SPECIES_GFX + .frontAnimFrames = ANIM_FRAMES( + ANIMCMD_FRAME(0, 16), + ANIMCMD_FRAME(1, 16), + ANIMCMD_FRAME(0, 26), + ANIMCMD_FRAME(1, 16), + ANIMCMD_FRAME(0, 16), + ), + #else + .frontAnimFrames = sAnims_SingleFramePlaceHolder, + #endif + .frontAnimId = P_GBA_STYLE_SPECIES_GFX ? ANIM_H_PIVOT : ANIM_GROW_VIBRATE, + .enemyMonElevation = P_GBA_STYLE_SPECIES_GFX ? 8 : 0, .backPic = gMonBackPic_DeoxysDefense, .backPicSize = MON_COORDS_SIZE(64, 56), - .backPicYOffset = 8, - .backAnimId = BACK_ANIM_TRIANGLE_DOWN, + .backPicYOffset = P_GBA_STYLE_SPECIES_GFX ? 7 : 8, + .backAnimId = P_GBA_STYLE_SPECIES_GFX ? BACK_ANIM_SHRINK_GROW_VIBRATE : BACK_ANIM_TRIANGLE_DOWN, .palette = gMonPalette_DeoxysDefense, .shinyPalette = gMonShinyPalette_DeoxysDefense, .iconSprite = gMonIcon_DeoxysDefense, @@ -13046,18 +13158,23 @@ const struct SpeciesInfo gSpeciesInfoGen3[] = .frontPic = gMonFrontPic_DeoxysSpeed, .frontPicSize = MON_COORDS_SIZE(64, 64), .frontPicYOffset = 1, - .frontAnimFrames = ANIM_FRAMES( - ANIMCMD_FRAME(0, 16), - ANIMCMD_FRAME(1, 16), - ANIMCMD_FRAME(0, 26), - ANIMCMD_FRAME(1, 16), - ANIMCMD_FRAME(0, 16), - ), - .frontAnimId = ANIM_GROW_VIBRATE, + #if !P_GBA_STYLE_SPECIES_GFX + .frontAnimFrames = ANIM_FRAMES( + ANIMCMD_FRAME(0, 16), + ANIMCMD_FRAME(1, 16), + ANIMCMD_FRAME(0, 26), + ANIMCMD_FRAME(1, 16), + ANIMCMD_FRAME(0, 16), + ), + #else + .frontAnimFrames = sAnims_SingleFramePlaceHolder, + #endif + .frontAnimId = P_GBA_STYLE_SPECIES_GFX ? ANIM_H_PIVOT : ANIM_GROW_VIBRATE, + .enemyMonElevation = P_GBA_STYLE_SPECIES_GFX ? 8 : 0, .backPic = gMonBackPic_DeoxysSpeed, - .backPicSize = MON_COORDS_SIZE(64, 64), - .backPicYOffset = 0, - .backAnimId = BACK_ANIM_TRIANGLE_DOWN, + .backPicSize = P_GBA_STYLE_SPECIES_GFX ? MON_COORDS_SIZE(64, 48) : MON_COORDS_SIZE(64, 64), + .backPicYOffset = P_GBA_STYLE_SPECIES_GFX ? 9 : 0, + .backAnimId = P_GBA_STYLE_SPECIES_GFX ? BACK_ANIM_SHRINK_GROW_VIBRATE : BACK_ANIM_TRIANGLE_DOWN, .palette = gMonPalette_DeoxysSpeed, .shinyPalette = gMonShinyPalette_DeoxysSpeed, .iconSprite = gMonIcon_DeoxysSpeed, diff --git a/src/data/pokemon/species_info/gen_5_families.h b/src/data/pokemon/species_info/gen_5_families.h index b43a51b52f..c34a08c9ce 100644 --- a/src/data/pokemon/species_info/gen_5_families.h +++ b/src/data/pokemon/species_info/gen_5_families.h @@ -503,7 +503,85 @@ const struct SpeciesInfo gSpeciesInfoGen5[] = ) .levelUpLearnset = sEmboarLevelUpLearnset, .teachableLearnset = sEmboarTeachableLearnset, + .formSpeciesIdTable = sEmboarFormSpeciesIdTable, + .formChangeTable = sEmboarFormChangeTable, }, + +#if P_GEN_9_MEGA_EVOLUTIONS + [SPECIES_EMBOAR_MEGA] = + { + .baseHP = 110, + .baseAttack = 148, + .baseDefense = 75, + .baseSpeed = 75, + .baseSpAttack = 110, + .baseSpDefense = 110, + .types = MON_TYPES(TYPE_FIRE, TYPE_FIGHTING), + .catchRate = 45, + .expYield = (P_UPDATED_EXP_YIELDS >= GEN_8) ? 264 : 238, + .evYield_Attack = 3, + .genderRatio = PERCENT_FEMALE(12.5), + .eggCycles = 20, + .friendship = STANDARD_FRIENDSHIP, + .growthRate = GROWTH_MEDIUM_SLOW, + .eggGroups = MON_EGG_GROUPS(EGG_GROUP_FIELD), + .abilities = { ABILITY_BLAZE, ABILITY_NONE, ABILITY_RECKLESS }, + .bodyColor = BODY_COLOR_RED, + .noFlip = TRUE, + .speciesName = _("Emboar"), + .cryId = CRY_EMBOAR, // CRY_EMBOAR_MEGA, + .natDexNum = NATIONAL_DEX_EMBOAR, + .categoryName = _("Fire Pig"), + .height = 18, + .weight = 1803, + .description = COMPOUND_STRING( + "Brandishing a blazing flame\n" + "shaped like a serpentine spear,\n" + "it rushes in to save its\n" + "imperiled allies."), + .frontPic = gMonFrontPic_CircledQuestionMark, + .frontPicSize = MON_COORDS_SIZE(40, 40), + .frontPicYOffset = 12, + .frontAnimFrames = sAnims_TwoFramePlaceHolder, + .frontAnimId = ANIM_V_SQUISH_AND_BOUNCE, + .backPic = gMonBackPic_CircledQuestionMark, + .backPicSize = MON_COORDS_SIZE(40, 40), + .backPicYOffset = 12, + .backAnimId = BACK_ANIM_NONE, + .palette = gMonPalette_CircledQuestionMark, + .shinyPalette = gMonShinyPalette_CircledQuestionMark, + .iconSprite = gMonIcon_QuestionMark, + .iconPalIndex = 0, + .pokemonJumpType = PKMN_JUMP_TYPE_NONE, + FOOTPRINT(QuestionMark) + SHADOW(-1, 0, SHADOW_SIZE_M) + #if OW_BATTLE_ONLY_FORMS + .overworldData = { + .tileTag = TAG_NONE, + .paletteTag = OBJ_EVENT_PAL_TAG_SUBSTITUTE, + .reflectionPaletteTag = OBJ_EVENT_PAL_TAG_NONE, + .size = 512, + .width = 32, + .height = 32, + .paletteSlot = PALSLOT_NPC_1, + .shadowSize = SHADOW_SIZE_M, + .inanimate = FALSE, + .compressed = COMP, + .tracks = TRACKS_FOOT, + .oam = &gObjectEventBaseOam_32x32, + .subspriteTables = sOamTables_32x32, + .anims = sAnimTable_Following, + .images = sPicTable_Substitute, + .affineAnims = gDummySpriteAffineAnimTable, + }, + #endif //OW_BATTLE_ONLY_FORMS + .isMegaEvolution = TRUE, + .levelUpLearnset = sEmboarLevelUpLearnset, + .teachableLearnset = sEmboarTeachableLearnset, + .formSpeciesIdTable = sEmboarFormSpeciesIdTable, + .formChangeTable = sEmboarFormChangeTable, + }, +#endif //P_GEN_9_MEGA_EVOLUTIONS #endif //P_FAMILY_TEPIG #if P_FAMILY_OSHAWOTT @@ -645,8 +723,8 @@ const struct SpeciesInfo gSpeciesInfoGen5[] = ) .levelUpLearnset = sDewottLevelUpLearnset, .teachableLearnset = sDewottTeachableLearnset, - .evolutions = EVOLUTION({EVO_LEVEL, 36, SPECIES_SAMUROTT}, - {EVO_NONE, 0, SPECIES_SAMUROTT_HISUI}), + .evolutions = EVOLUTION({EVO_LEVEL, 36, SPECIES_SAMUROTT, CONDITIONS({IF_NOT_REGION, REGION_HISUI})}, + {EVO_LEVEL, 36, SPECIES_SAMUROTT_HISUI, CONDITIONS({IF_REGION, REGION_HISUI})}), }, [SPECIES_SAMUROTT] = @@ -2724,7 +2802,85 @@ const struct SpeciesInfo gSpeciesInfoGen5[] = ) .levelUpLearnset = sExcadrillLevelUpLearnset, .teachableLearnset = sExcadrillTeachableLearnset, + .formSpeciesIdTable = sExcadrillFormSpeciesIdTable, + .formChangeTable = sExcadrillFormChangeTable, }, + +#if P_GEN_9_MEGA_EVOLUTIONS + [SPECIES_EXCADRILL_MEGA] = + { + .baseHP = 110, + .baseAttack = 165, + .baseDefense = 100, + .baseSpeed = 103, + .baseSpAttack = 65, + .baseSpDefense = 65, + .types = MON_TYPES(TYPE_GROUND, TYPE_STEEL), + .catchRate = 60, + .expYield = 178, + .evYield_Attack = 2, + .genderRatio = PERCENT_FEMALE(50), + .eggCycles = 20, + .friendship = STANDARD_FRIENDSHIP, + .growthRate = GROWTH_MEDIUM_FAST, + .eggGroups = MON_EGG_GROUPS(EGG_GROUP_FIELD), + .abilities = { ABILITY_SAND_RUSH, ABILITY_SAND_FORCE, ABILITY_MOLD_BREAKER }, + .bodyColor = BODY_COLOR_GRAY, + .noFlip = TRUE, + .speciesName = _("Excadrill"), + .cryId = CRY_EXCADRILL, // CRY_EXCADRILL_MEGA, + .natDexNum = NATIONAL_DEX_EXCADRILL, + .categoryName = _("Subterrene"), + .height = 9, + .weight = 600, + .description = COMPOUND_STRING( + "If this Pokémon brings its arms and\n" + "head together to form a streamlined\n" + "shape and spins at high speeds,\n" + "it can destroy anything."), + .frontPic = gMonFrontPic_CircledQuestionMark, + .frontPicSize = MON_COORDS_SIZE(40, 40), + .frontPicYOffset = 12, + .frontAnimFrames = sAnims_TwoFramePlaceHolder, + .frontAnimId = ANIM_V_SQUISH_AND_BOUNCE, + .backPic = gMonBackPic_CircledQuestionMark, + .backPicSize = MON_COORDS_SIZE(40, 40), + .backPicYOffset = 12, + .backAnimId = BACK_ANIM_NONE, + .palette = gMonPalette_CircledQuestionMark, + .shinyPalette = gMonShinyPalette_CircledQuestionMark, + .iconSprite = gMonIcon_QuestionMark, + .iconPalIndex = 0, + .pokemonJumpType = PKMN_JUMP_TYPE_NONE, + FOOTPRINT(QuestionMark) + SHADOW(-1, 0, SHADOW_SIZE_M) + #if OW_BATTLE_ONLY_FORMS + .overworldData = { + .tileTag = TAG_NONE, + .paletteTag = OBJ_EVENT_PAL_TAG_SUBSTITUTE, + .reflectionPaletteTag = OBJ_EVENT_PAL_TAG_NONE, + .size = 512, + .width = 32, + .height = 32, + .paletteSlot = PALSLOT_NPC_1, + .shadowSize = SHADOW_SIZE_M, + .inanimate = FALSE, + .compressed = COMP, + .tracks = TRACKS_FOOT, + .oam = &gObjectEventBaseOam_32x32, + .subspriteTables = sOamTables_32x32, + .anims = sAnimTable_Following, + .images = sPicTable_Substitute, + .affineAnims = gDummySpriteAffineAnimTable, + }, + #endif //OW_BATTLE_ONLY_FORMS + .isMegaEvolution = TRUE, + .levelUpLearnset = sExcadrillLevelUpLearnset, + .teachableLearnset = sExcadrillTeachableLearnset, + .formSpeciesIdTable = sExcadrillFormSpeciesIdTable, + .formChangeTable = sExcadrillFormChangeTable, + }, +#endif //P_GEN_9_MEGA_EVOLUTIONS #endif //P_FAMILY_DRILBUR #if P_FAMILY_AUDINO @@ -3870,7 +4026,90 @@ const struct SpeciesInfo gSpeciesInfoGen5[] = ) .levelUpLearnset = sScolipedeLevelUpLearnset, .teachableLearnset = sScolipedeTeachableLearnset, + .formSpeciesIdTable = sScolipedeFormSpeciesIdTable, + .formChangeTable = sScolipedeFormChangeTable, }, + +#if P_GEN_9_MEGA_EVOLUTIONS + [SPECIES_SCOLIPEDE_MEGA] = + { + .baseHP = 60, + .baseAttack = 140, + .baseDefense = 149, + .baseSpeed = 62, + .baseSpAttack = 75, + .baseSpDefense = 99, + .types = MON_TYPES(TYPE_BUG, TYPE_POISON), + .catchRate = 45, + #if P_UPDATED_EXP_YIELDS >= GEN_8 + .expYield = 243, + #elif P_UPDATED_EXP_YIELDS >= GEN_7 + .expYield = 218, + #else + .expYield = 214, + #endif + .evYield_Speed = 3, + .itemRare = ITEM_POISON_BARB, + .genderRatio = PERCENT_FEMALE(50), + .eggCycles = 20, + .friendship = STANDARD_FRIENDSHIP, + .growthRate = GROWTH_MEDIUM_SLOW, + .eggGroups = MON_EGG_GROUPS(EGG_GROUP_BUG), + .abilities = { ABILITY_POISON_POINT, ABILITY_SWARM, ABILITY_SPEED_BOOST }, + .bodyColor = BODY_COLOR_RED, + .speciesName = _("Scolipede"), + .cryId = CRY_SCOLIPEDE, // CRY_SCOLIPEDE_MEGA, + .natDexNum = NATIONAL_DEX_SCOLIPEDE, + .categoryName = _("Megapede"), + .height = 32, + .weight = 2305, + .description = COMPOUND_STRING( + "Its deadly venom gives off a faint\n" + "glow. The venom affects Scolipede's\n" + "mind, honing its viciousness."), + .frontPic = gMonFrontPic_CircledQuestionMark, + .frontPicSize = MON_COORDS_SIZE(40, 40), + .frontPicYOffset = 12, + .frontAnimFrames = sAnims_TwoFramePlaceHolder, + .frontAnimId = ANIM_V_SQUISH_AND_BOUNCE, + .backPic = gMonBackPic_CircledQuestionMark, + .backPicSize = MON_COORDS_SIZE(40, 40), + .backPicYOffset = 12, + .backAnimId = BACK_ANIM_NONE, + .palette = gMonPalette_CircledQuestionMark, + .shinyPalette = gMonShinyPalette_CircledQuestionMark, + .iconSprite = gMonIcon_QuestionMark, + .iconPalIndex = 0, + .pokemonJumpType = PKMN_JUMP_TYPE_NONE, + FOOTPRINT(QuestionMark) + SHADOW(-1, 0, SHADOW_SIZE_M) + #if OW_BATTLE_ONLY_FORMS + .overworldData = { + .tileTag = TAG_NONE, + .paletteTag = OBJ_EVENT_PAL_TAG_SUBSTITUTE, + .reflectionPaletteTag = OBJ_EVENT_PAL_TAG_NONE, + .size = 512, + .width = 32, + .height = 32, + .paletteSlot = PALSLOT_NPC_1, + .shadowSize = SHADOW_SIZE_M, + .inanimate = FALSE, + .compressed = COMP, + .tracks = TRACKS_FOOT, + .oam = &gObjectEventBaseOam_32x32, + .subspriteTables = sOamTables_32x32, + .anims = sAnimTable_Following, + .images = sPicTable_Substitute, + .affineAnims = gDummySpriteAffineAnimTable, + }, + #endif //OW_BATTLE_ONLY_FORMS + .isMegaEvolution = TRUE, + .levelUpLearnset = sScolipedeLevelUpLearnset, + .teachableLearnset = sScolipedeTeachableLearnset, + .formSpeciesIdTable = sScolipedeFormSpeciesIdTable, + .formChangeTable = sScolipedeFormChangeTable, + }, +#endif //P_GEN_9_MEGA_EVOLUTIONS #endif //P_FAMILY_VENIPEDE #if P_FAMILY_COTTONEE @@ -4093,8 +4332,8 @@ const struct SpeciesInfo gSpeciesInfoGen5[] = .levelUpLearnset = sPetililLevelUpLearnset, .teachableLearnset = sPetililTeachableLearnset, .eggMoveLearnset = sPetililEggMoveLearnset, - .evolutions = EVOLUTION({EVO_ITEM, ITEM_SUN_STONE, SPECIES_LILLIGANT}, - {EVO_NONE, 0, SPECIES_LILLIGANT_HISUI}), + .evolutions = EVOLUTION({EVO_ITEM, ITEM_SUN_STONE, SPECIES_LILLIGANT, CONDITIONS({IF_NOT_REGION, REGION_HISUI})}, + {EVO_ITEM, ITEM_SUN_STONE, SPECIES_LILLIGANT_HISUI, CONDITIONS({IF_REGION, REGION_HISUI})}), }, [SPECIES_LILLIGANT] = @@ -5521,7 +5760,86 @@ const struct SpeciesInfo gSpeciesInfoGen5[] = ) .levelUpLearnset = sScraftyLevelUpLearnset, .teachableLearnset = sScraftyTeachableLearnset, + .formSpeciesIdTable = sScraftyFormSpeciesIdTable, + .formChangeTable = sScraftyFormChangeTable, }, + +#if P_GEN_9_MEGA_EVOLUTIONS + [SPECIES_SCRAFTY_MEGA] = + { + .baseHP = 65, + .baseAttack = 130, + .baseDefense = 135, + .baseSpeed = 68, + .baseSpAttack = 55, + .baseSpDefense = 135, + .types = MON_TYPES(TYPE_DARK, TYPE_FIGHTING), + .catchRate = 90, + .expYield = 171, + .evYield_Defense = 1, + .evYield_SpDefense = 1, + .itemRare = ITEM_SHED_SHELL, + .genderRatio = PERCENT_FEMALE(50), + .eggCycles = 15, + .friendship = STANDARD_FRIENDSHIP, + .growthRate = GROWTH_MEDIUM_FAST, + .eggGroups = MON_EGG_GROUPS(EGG_GROUP_FIELD, EGG_GROUP_DRAGON), + .abilities = { ABILITY_SHED_SKIN, ABILITY_MOXIE, ABILITY_INTIMIDATE }, + .bodyColor = BODY_COLOR_RED, + .speciesName = _("Scrafty"), + .cryId = CRY_SCRAFTY, + .natDexNum = NATIONAL_DEX_SCRAFTY, + .categoryName = _("Hoodlum"), + .height = 11, + .weight = 310, + .description = COMPOUND_STRING( + "Mega Evolution has caused Scrafty's\n" + "shed skin to turn white, growing\n" + "tough and supple. Of course, this\n" + "Pokémon is still as feisty as ever."), + .frontPic = gMonFrontPic_CircledQuestionMark, + .frontPicSize = MON_COORDS_SIZE(40, 40), + .frontPicYOffset = 12, + .frontAnimFrames = sAnims_TwoFramePlaceHolder, + .frontAnimId = ANIM_V_SQUISH_AND_BOUNCE, + .backPic = gMonBackPic_CircledQuestionMark, + .backPicSize = MON_COORDS_SIZE(40, 40), + .backPicYOffset = 12, + .backAnimId = BACK_ANIM_NONE, + .palette = gMonPalette_CircledQuestionMark, + .shinyPalette = gMonShinyPalette_CircledQuestionMark, + .iconSprite = gMonIcon_QuestionMark, + .iconPalIndex = 0, + .pokemonJumpType = PKMN_JUMP_TYPE_NONE, + FOOTPRINT(QuestionMark) + SHADOW(-1, 0, SHADOW_SIZE_M) + #if OW_BATTLE_ONLY_FORMS + .overworldData = { + .tileTag = TAG_NONE, + .paletteTag = OBJ_EVENT_PAL_TAG_SUBSTITUTE, + .reflectionPaletteTag = OBJ_EVENT_PAL_TAG_NONE, + .size = 512, + .width = 32, + .height = 32, + .paletteSlot = PALSLOT_NPC_1, + .shadowSize = SHADOW_SIZE_M, + .inanimate = FALSE, + .compressed = COMP, + .tracks = TRACKS_FOOT, + .oam = &gObjectEventBaseOam_32x32, + .subspriteTables = sOamTables_32x32, + .anims = sAnimTable_Following, + .images = sPicTable_Substitute, + .affineAnims = gDummySpriteAffineAnimTable, + }, + #endif //OW_BATTLE_ONLY_FORMS + .isMegaEvolution = TRUE, + .levelUpLearnset = sScraftyLevelUpLearnset, + .teachableLearnset = sScraftyTeachableLearnset, + .formSpeciesIdTable = sScraftyFormSpeciesIdTable, + .formChangeTable = sScraftyFormChangeTable, + }, +#endif //P_GEN_9_MEGA_EVOLUTIONS #endif //P_FAMILY_SCRAGGY #if P_FAMILY_SIGILYPH @@ -9383,7 +9701,84 @@ const struct SpeciesInfo gSpeciesInfoGen5[] = ) .levelUpLearnset = sEelektrossLevelUpLearnset, .teachableLearnset = sEelektrossTeachableLearnset, + .formSpeciesIdTable = sEelektrossFormSpeciesIdTable, + .formChangeTable = sEelektrossFormChangeTable, }, + +#if P_GEN_9_MEGA_EVOLUTIONS + [SPECIES_EELEKTROSS_MEGA] = + { + .baseHP = 85, + .baseAttack = 145, + .baseDefense = 80, + .baseSpeed = 80, + .baseSpAttack = 135, + .baseSpDefense = 90, + .types = MON_TYPES(TYPE_ELECTRIC), + .catchRate = 30, + .expYield = (P_UPDATED_EXP_YIELDS >= GEN_8) ? 258 : 232, + .evYield_Attack = 3, + .genderRatio = PERCENT_FEMALE(50), + .eggCycles = 20, + .friendship = STANDARD_FRIENDSHIP, + .growthRate = GROWTH_SLOW, + .eggGroups = MON_EGG_GROUPS(EGG_GROUP_AMORPHOUS), + .abilities = { ABILITY_LEVITATE, ABILITY_NONE, ABILITY_NONE }, + .bodyColor = BODY_COLOR_BLUE, + .speciesName = _("Eelektross"), + .cryId = CRY_EELEKTROSS, // CRY_EELEKTROSS_MEGA, + .natDexNum = NATIONAL_DEX_EELEKTROSS, + .categoryName = _("EleFish"), + .height = 30, + .weight = 1800, + .description = COMPOUND_STRING( + "It now generates 10 times the\n" + "electricity it did before Mega\n" + "Evolving. It discharges this energy\n" + "from its false Eelektrik made of mucus."), + .frontPic = gMonFrontPic_CircledQuestionMark, + .frontPicSize = MON_COORDS_SIZE(40, 40), + .frontPicYOffset = 12, + .frontAnimFrames = sAnims_TwoFramePlaceHolder, + .frontAnimId = ANIM_V_SQUISH_AND_BOUNCE, + .backPic = gMonBackPic_CircledQuestionMark, + .backPicSize = MON_COORDS_SIZE(40, 40), + .backPicYOffset = 12, + .backAnimId = BACK_ANIM_NONE, + .palette = gMonPalette_CircledQuestionMark, + .shinyPalette = gMonShinyPalette_CircledQuestionMark, + .iconSprite = gMonIcon_QuestionMark, + .iconPalIndex = 0, + .pokemonJumpType = PKMN_JUMP_TYPE_NONE, + FOOTPRINT(QuestionMark) + SHADOW(-1, 0, SHADOW_SIZE_M) + #if OW_BATTLE_ONLY_FORMS + .overworldData = { + .tileTag = TAG_NONE, + .paletteTag = OBJ_EVENT_PAL_TAG_SUBSTITUTE, + .reflectionPaletteTag = OBJ_EVENT_PAL_TAG_NONE, + .size = 512, + .width = 32, + .height = 32, + .paletteSlot = PALSLOT_NPC_1, + .shadowSize = SHADOW_SIZE_M, + .inanimate = FALSE, + .compressed = COMP, + .tracks = TRACKS_FOOT, + .oam = &gObjectEventBaseOam_32x32, + .subspriteTables = sOamTables_32x32, + .anims = sAnimTable_Following, + .images = sPicTable_Substitute, + .affineAnims = gDummySpriteAffineAnimTable, + }, + #endif //OW_BATTLE_ONLY_FORMS + .isMegaEvolution = TRUE, + .levelUpLearnset = sEelektrossLevelUpLearnset, + .teachableLearnset = sEelektrossTeachableLearnset, + .formSpeciesIdTable = sEelektrossFormSpeciesIdTable, + .formChangeTable = sEelektrossFormChangeTable, + }, +#endif //P_GEN_9_MEGA_EVOLUTIONS #endif //P_FAMILY_TYNAMO #if P_FAMILY_ELGYEM @@ -9740,7 +10135,84 @@ const struct SpeciesInfo gSpeciesInfoGen5[] = ) .levelUpLearnset = sChandelureLevelUpLearnset, .teachableLearnset = sChandelureTeachableLearnset, + .formSpeciesIdTable = sChandelureFormSpeciesIdTable, + .formChangeTable = sChandelureFormChangeTable, }, + +#if P_GEN_9_MEGA_EVOLUTIONS + [SPECIES_CHANDELURE_MEGA] = + { + .baseHP = 60, + .baseAttack = 75, + .baseDefense = 110, + .baseSpeed = 90, + .baseSpAttack = 175, + .baseSpDefense = 110, + .types = MON_TYPES(TYPE_GHOST, TYPE_FIRE), + .catchRate = 45, + .expYield = (P_UPDATED_EXP_YIELDS >= GEN_8) ? 260 : 234, + .evYield_SpAttack = 3, + .genderRatio = PERCENT_FEMALE(50), + .eggCycles = 20, + .friendship = STANDARD_FRIENDSHIP, + .growthRate = GROWTH_MEDIUM_SLOW, + .eggGroups = MON_EGG_GROUPS(EGG_GROUP_AMORPHOUS), + .abilities = { ABILITY_FLASH_FIRE, ABILITY_FLAME_BODY, ABILITY_INFILTRATOR }, + .bodyColor = BODY_COLOR_BLACK, + .speciesName = _("Chandelure"), + .cryId = CRY_CHANDELURE, // CRY_CHANDELURE_MEGA, + .natDexNum = NATIONAL_DEX_CHANDELURE, + .categoryName = _("Luring"), + .height = 25, + .weight = 696, + .description = COMPOUND_STRING( + "One of its eyes is a window linking\n" + "our world with the afterlife.\n" + "This Pokémon draws in hatred and\n" + "converts it into power."), + .frontPic = gMonFrontPic_CircledQuestionMark, + .frontPicSize = MON_COORDS_SIZE(40, 40), + .frontPicYOffset = 12, + .frontAnimFrames = sAnims_TwoFramePlaceHolder, + .frontAnimId = ANIM_V_SQUISH_AND_BOUNCE, + .backPic = gMonBackPic_CircledQuestionMark, + .backPicSize = MON_COORDS_SIZE(40, 40), + .backPicYOffset = 12, + .backAnimId = BACK_ANIM_NONE, + .palette = gMonPalette_CircledQuestionMark, + .shinyPalette = gMonShinyPalette_CircledQuestionMark, + .iconSprite = gMonIcon_QuestionMark, + .iconPalIndex = 0, + .pokemonJumpType = PKMN_JUMP_TYPE_NONE, + FOOTPRINT(QuestionMark) + SHADOW(-1, 0, SHADOW_SIZE_M) + #if OW_BATTLE_ONLY_FORMS + .overworldData = { + .tileTag = TAG_NONE, + .paletteTag = OBJ_EVENT_PAL_TAG_SUBSTITUTE, + .reflectionPaletteTag = OBJ_EVENT_PAL_TAG_NONE, + .size = 512, + .width = 32, + .height = 32, + .paletteSlot = PALSLOT_NPC_1, + .shadowSize = SHADOW_SIZE_M, + .inanimate = FALSE, + .compressed = COMP, + .tracks = TRACKS_FOOT, + .oam = &gObjectEventBaseOam_32x32, + .subspriteTables = sOamTables_32x32, + .anims = sAnimTable_Following, + .images = sPicTable_Substitute, + .affineAnims = gDummySpriteAffineAnimTable, + }, + #endif //OW_BATTLE_ONLY_FORMS + .isMegaEvolution = TRUE, + .levelUpLearnset = sChandelureLevelUpLearnset, + .teachableLearnset = sChandelureTeachableLearnset, + .formSpeciesIdTable = sChandelureFormSpeciesIdTable, + .formChangeTable = sChandelureFormChangeTable, + }, +#endif //P_GEN_9_MEGA_EVOLUTIONS #endif //P_FAMILY_LITWICK #if P_FAMILY_AXEW @@ -11128,8 +11600,8 @@ const struct SpeciesInfo gSpeciesInfoGen5[] = ) .levelUpLearnset = sRuffletLevelUpLearnset, .teachableLearnset = sRuffletTeachableLearnset, - .evolutions = EVOLUTION({EVO_LEVEL, 54, SPECIES_BRAVIARY}, - {EVO_NONE, 0, SPECIES_BRAVIARY_HISUI}), + .evolutions = EVOLUTION({EVO_LEVEL, 54, SPECIES_BRAVIARY, CONDITIONS({IF_NOT_REGION, REGION_HISUI})}, + {EVO_LEVEL, 54, SPECIES_BRAVIARY_HISUI, CONDITIONS({IF_REGION, REGION_HISUI})}), }, [SPECIES_BRAVIARY] = diff --git a/src/data/pokemon/species_info/gen_6_families.h b/src/data/pokemon/species_info/gen_6_families.h index c027f0b454..905d982bf6 100644 --- a/src/data/pokemon/species_info/gen_6_families.h +++ b/src/data/pokemon/species_info/gen_6_families.h @@ -206,7 +206,83 @@ const struct SpeciesInfo gSpeciesInfoGen6[] = ) .levelUpLearnset = sChesnaughtLevelUpLearnset, .teachableLearnset = sChesnaughtTeachableLearnset, + .formSpeciesIdTable = sChesnaughtFormSpeciesIdTable, + .formChangeTable = sChesnaughtFormChangeTable, }, + +#if P_GEN_9_MEGA_EVOLUTIONS + [SPECIES_CHESNAUGHT_MEGA] = + { + .baseHP = 88, + .baseAttack = 137, + .baseDefense = 172, + .baseSpeed = 44, + .baseSpAttack = 74, + .baseSpDefense = 115, + .types = MON_TYPES(TYPE_GRASS, TYPE_FIGHTING), + .catchRate = 45, + .expYield = (P_UPDATED_EXP_YIELDS >= GEN_8) ? 265 : 239, + .evYield_Defense = 3, + .genderRatio = PERCENT_FEMALE(12.5), + .eggCycles = 20, + .friendship = STANDARD_FRIENDSHIP, + .growthRate = GROWTH_MEDIUM_SLOW, + .eggGroups = MON_EGG_GROUPS(EGG_GROUP_FIELD), + .abilities = { ABILITY_OVERGROW, ABILITY_NONE, ABILITY_BULLETPROOF }, + .bodyColor = BODY_COLOR_GREEN, + .speciesName = _("Chesnaught"), + .cryId = CRY_CHESNAUGHT, + .natDexNum = NATIONAL_DEX_CHESNAUGHT, + .categoryName = _("Spiny Armor"), + .height = 16, + .weight = 900, + .description = COMPOUND_STRING( + "It has fortified armor and a\n" + "will to defend at all costs.\n" + "Both are absurdly strong."), + .frontPic = gMonFrontPic_CircledQuestionMark, + .frontPicSize = MON_COORDS_SIZE(40, 40), + .frontPicYOffset = 12, + .frontAnimFrames = sAnims_TwoFramePlaceHolder, + .frontAnimId = ANIM_V_SQUISH_AND_BOUNCE, + .backPic = gMonBackPic_CircledQuestionMark, + .backPicSize = MON_COORDS_SIZE(40, 40), + .backPicYOffset = 12, + .backAnimId = BACK_ANIM_NONE, + .palette = gMonPalette_CircledQuestionMark, + .shinyPalette = gMonShinyPalette_CircledQuestionMark, + .iconSprite = gMonIcon_QuestionMark, + .iconPalIndex = 0, + .pokemonJumpType = PKMN_JUMP_TYPE_NONE, + FOOTPRINT(QuestionMark) + SHADOW(-1, 0, SHADOW_SIZE_M) + #if OW_BATTLE_ONLY_FORMS + .overworldData = { + .tileTag = TAG_NONE, + .paletteTag = OBJ_EVENT_PAL_TAG_SUBSTITUTE, + .reflectionPaletteTag = OBJ_EVENT_PAL_TAG_NONE, + .size = 512, + .width = 32, + .height = 32, + .paletteSlot = PALSLOT_NPC_1, + .shadowSize = SHADOW_SIZE_M, + .inanimate = FALSE, + .compressed = COMP, + .tracks = TRACKS_FOOT, + .oam = &gObjectEventBaseOam_32x32, + .subspriteTables = sOamTables_32x32, + .anims = sAnimTable_Following, + .images = sPicTable_Substitute, + .affineAnims = gDummySpriteAffineAnimTable, + }, + #endif //OW_BATTLE_ONLY_FORMS + .isMegaEvolution = TRUE, + .levelUpLearnset = sChesnaughtLevelUpLearnset, + .teachableLearnset = sChesnaughtTeachableLearnset, + .formSpeciesIdTable = sChesnaughtFormSpeciesIdTable, + .formChangeTable = sChesnaughtFormChangeTable, + }, +#endif //P_GEN_9_MEGA_EVOLUTIONS #endif //P_FAMILY_CHESPIN #if P_FAMILY_FENNEKIN @@ -417,7 +493,84 @@ const struct SpeciesInfo gSpeciesInfoGen6[] = ) .levelUpLearnset = sDelphoxLevelUpLearnset, .teachableLearnset = sDelphoxTeachableLearnset, + .formSpeciesIdTable = sDelphoxFormSpeciesIdTable, + .formChangeTable = sDelphoxFormChangeTable, }, + +#if P_GEN_9_MEGA_EVOLUTIONS + [SPECIES_DELPHOX_MEGA] = + { + .baseHP = 75, + .baseAttack = 69, + .baseDefense = 72, + .baseSpeed = 134, + .baseSpAttack = 159, + .baseSpDefense = 125, + .types = MON_TYPES(TYPE_FIRE, TYPE_PSYCHIC), + .catchRate = 45, + .expYield = (P_UPDATED_EXP_YIELDS >= GEN_8) ? 267 : 240, + .evYield_SpAttack = 3, + .genderRatio = PERCENT_FEMALE(12.5), + .eggCycles = 20, + .friendship = STANDARD_FRIENDSHIP, + .growthRate = GROWTH_MEDIUM_SLOW, + .eggGroups = MON_EGG_GROUPS(EGG_GROUP_FIELD), + .abilities = { ABILITY_BLAZE, ABILITY_NONE, ABILITY_MAGICIAN }, + .bodyColor = BODY_COLOR_RED, + .speciesName = _("Delphox"), + .cryId = CRY_DELPHOX, // CRY_DELPHOX_MEGA, + .natDexNum = NATIONAL_DEX_DELPHOX, + .categoryName = _("Fox"), + .height = 15, + .weight = 390, + .description = COMPOUND_STRING( + "It wields flaming branches to\n" + "dazzle its opponents before\n" + "incinerating them with a\n" + "huge fireball."), + .frontPic = gMonFrontPic_CircledQuestionMark, + .frontPicSize = MON_COORDS_SIZE(40, 40), + .frontPicYOffset = 12, + .frontAnimFrames = sAnims_TwoFramePlaceHolder, + .frontAnimId = ANIM_V_SQUISH_AND_BOUNCE, + .backPic = gMonBackPic_CircledQuestionMark, + .backPicSize = MON_COORDS_SIZE(40, 40), + .backPicYOffset = 12, + .backAnimId = BACK_ANIM_NONE, + .palette = gMonPalette_CircledQuestionMark, + .shinyPalette = gMonShinyPalette_CircledQuestionMark, + .iconSprite = gMonIcon_QuestionMark, + .iconPalIndex = 0, + .pokemonJumpType = PKMN_JUMP_TYPE_NONE, + FOOTPRINT(QuestionMark) + SHADOW(-1, 0, SHADOW_SIZE_M) + #if OW_BATTLE_ONLY_FORMS + .overworldData = { + .tileTag = TAG_NONE, + .paletteTag = OBJ_EVENT_PAL_TAG_SUBSTITUTE, + .reflectionPaletteTag = OBJ_EVENT_PAL_TAG_NONE, + .size = 512, + .width = 32, + .height = 32, + .paletteSlot = PALSLOT_NPC_1, + .shadowSize = SHADOW_SIZE_M, + .inanimate = FALSE, + .compressed = COMP, + .tracks = TRACKS_FOOT, + .oam = &gObjectEventBaseOam_32x32, + .subspriteTables = sOamTables_32x32, + .anims = sAnimTable_Following, + .images = sPicTable_Substitute, + .affineAnims = gDummySpriteAffineAnimTable, + }, + #endif //OW_BATTLE_ONLY_FORMS + .isMegaEvolution = TRUE, + .levelUpLearnset = sDelphoxLevelUpLearnset, + .teachableLearnset = sDelphoxTeachableLearnset, + .formSpeciesIdTable = sDelphoxFormSpeciesIdTable, + .formChangeTable = sDelphoxFormChangeTable, + }, +#endif //P_GEN_9_MEGA_EVOLUTIONS #endif //P_FAMILY_FENNEKIN #if P_FAMILY_FROAKIE @@ -618,6 +771,7 @@ const struct SpeciesInfo gSpeciesInfoGen6[] = .levelUpLearnset = sGreninjaLevelUpLearnset, .teachableLearnset = sGreninjaTeachableLearnset, .formSpeciesIdTable = sGreninjaFormSpeciesIdTable, + .formChangeTable = sGreninjaFormChangeTable, }, [SPECIES_GRENINJA_BATTLE_BOND] = @@ -751,6 +905,82 @@ const struct SpeciesInfo gSpeciesInfoGen6[] = .formSpeciesIdTable = sGreninjaFormSpeciesIdTable, .formChangeTable = sGreninjaBattleBondFormChangeTable, }, + +#if P_GEN_9_MEGA_EVOLUTIONS + [SPECIES_GRENINJA_MEGA] = + { + .baseHP = 72, + .baseAttack = 125, + .baseDefense = 77, + .baseSpeed = 142, + .baseSpAttack = 133, + .baseSpDefense = 81, + .types = MON_TYPES(TYPE_WATER, TYPE_DARK), + .catchRate = 45, + .expYield = (P_UPDATED_EXP_YIELDS >= GEN_8) ? 265 : 239, + .evYield_Speed = 3, + .genderRatio = PERCENT_FEMALE(12.5), + .eggCycles = 20, + .friendship = STANDARD_FRIENDSHIP, + .growthRate = GROWTH_MEDIUM_SLOW, + .eggGroups = MON_EGG_GROUPS(EGG_GROUP_WATER_1), + .abilities = { ABILITY_TORRENT, ABILITY_NONE, ABILITY_PROTEAN }, + .bodyColor = BODY_COLOR_BLUE, + .noFlip = TRUE, + .speciesName = _("Greninja"), + .cryId = CRY_GRENINJA, // CRY_GRENINJA_MEGA, + .natDexNum = NATIONAL_DEX_GRENINJA, + .categoryName = _("Ninja"), + .height = 15, + .weight = 400, + .description = COMPOUND_STRING( + "This Pokémon spins a giant\n" + "shuriken at high speed to make it\n" + "float, then clings to it upside\n" + "down to catch opponents unawares."), + .frontPic = gMonFrontPic_CircledQuestionMark, + .frontPicSize = MON_COORDS_SIZE(40, 40), + .frontPicYOffset = 12, + .frontAnimFrames = sAnims_TwoFramePlaceHolder, + .frontAnimId = ANIM_V_SQUISH_AND_BOUNCE, + .backPic = gMonBackPic_CircledQuestionMark, + .backPicSize = MON_COORDS_SIZE(40, 40), + .backPicYOffset = 12, + .backAnimId = BACK_ANIM_NONE, + .palette = gMonPalette_CircledQuestionMark, + .shinyPalette = gMonShinyPalette_CircledQuestionMark, + .iconSprite = gMonIcon_QuestionMark, + .iconPalIndex = 0, + .pokemonJumpType = PKMN_JUMP_TYPE_NONE, + FOOTPRINT(QuestionMark) + SHADOW(-1, 0, SHADOW_SIZE_M) + #if OW_BATTLE_ONLY_FORMS + .overworldData = { + .tileTag = TAG_NONE, + .paletteTag = OBJ_EVENT_PAL_TAG_SUBSTITUTE, + .reflectionPaletteTag = OBJ_EVENT_PAL_TAG_NONE, + .size = 512, + .width = 32, + .height = 32, + .paletteSlot = PALSLOT_NPC_1, + .shadowSize = SHADOW_SIZE_M, + .inanimate = FALSE, + .compressed = COMP, + .tracks = TRACKS_FOOT, + .oam = &gObjectEventBaseOam_32x32, + .subspriteTables = sOamTables_32x32, + .anims = sAnimTable_Following, + .images = sPicTable_Substitute, + .affineAnims = gDummySpriteAffineAnimTable, + }, + #endif //OW_BATTLE_ONLY_FORMS + .isMegaEvolution = TRUE, + .levelUpLearnset = sGreninjaLevelUpLearnset, + .teachableLearnset = sGreninjaTeachableLearnset, + .formSpeciesIdTable = sGreninjaFormSpeciesIdTable, + .formChangeTable = sGreninjaFormChangeTable, + }, +#endif //P_GEN_9_MEGA_EVOLUTIONS #endif //P_FAMILY_FROAKIE #if P_FAMILY_BUNNELBY @@ -1636,7 +1866,84 @@ const struct SpeciesInfo gSpeciesInfoGen6[] = ) .levelUpLearnset = sPyroarLevelUpLearnset, .teachableLearnset = sPyroarTeachableLearnset, + .formSpeciesIdTable = sPyroarFormSpeciesIdTable, + .formChangeTable = sPyroarFormChangeTable, }, + +#if P_GEN_9_MEGA_EVOLUTIONS + [SPECIES_PYROAR_MEGA] = + { + .baseHP = 86, + .baseAttack = 88, + .baseDefense = 92, + .baseSpeed = 126, + .baseSpAttack = 129, + .baseSpDefense = 86, + .types = MON_TYPES(TYPE_FIRE, TYPE_NORMAL), + .catchRate = 65, + .expYield = 177, + .evYield_SpAttack = 2, + .genderRatio = PERCENT_FEMALE(87.5), + .eggCycles = 20, + .friendship = STANDARD_FRIENDSHIP, + .growthRate = GROWTH_MEDIUM_SLOW, + .eggGroups = MON_EGG_GROUPS(EGG_GROUP_FIELD), + .abilities = { ABILITY_RIVALRY, ABILITY_UNNERVE, ABILITY_MOXIE }, + .bodyColor = BODY_COLOR_BROWN, + .speciesName = _("Pyroar"), + .cryId = CRY_PYROAR, // CRY_PYROAR_MEGA, + .natDexNum = NATIONAL_DEX_PYROAR, + .categoryName = _("Royal"), + .height = 15, + .weight = 933, + .description = COMPOUND_STRING( + "This Pokémon spews flames hotter\n" + "than 18,000 degrees Fahrenheit.\n" + "It swings around its grand, blazing\n" + "mane as it protects its allies."), + .frontPic = gMonFrontPic_CircledQuestionMark, + .frontPicSize = MON_COORDS_SIZE(40, 40), + .frontPicYOffset = 12, + .frontAnimFrames = sAnims_TwoFramePlaceHolder, + .frontAnimId = ANIM_V_SQUISH_AND_BOUNCE, + .backPic = gMonBackPic_CircledQuestionMark, + .backPicSize = MON_COORDS_SIZE(40, 40), + .backPicYOffset = 12, + .backAnimId = BACK_ANIM_NONE, + .palette = gMonPalette_CircledQuestionMark, + .shinyPalette = gMonShinyPalette_CircledQuestionMark, + .iconSprite = gMonIcon_QuestionMark, + .iconPalIndex = 0, + .pokemonJumpType = PKMN_JUMP_TYPE_NONE, + FOOTPRINT(QuestionMark) + SHADOW(-1, 0, SHADOW_SIZE_M) + #if OW_BATTLE_ONLY_FORMS + .overworldData = { + .tileTag = TAG_NONE, + .paletteTag = OBJ_EVENT_PAL_TAG_SUBSTITUTE, + .reflectionPaletteTag = OBJ_EVENT_PAL_TAG_NONE, + .size = 512, + .width = 32, + .height = 32, + .paletteSlot = PALSLOT_NPC_1, + .shadowSize = SHADOW_SIZE_M, + .inanimate = FALSE, + .compressed = COMP, + .tracks = TRACKS_FOOT, + .oam = &gObjectEventBaseOam_32x32, + .subspriteTables = sOamTables_32x32, + .anims = sAnimTable_Following, + .images = sPicTable_Substitute, + .affineAnims = gDummySpriteAffineAnimTable, + }, + #endif //OW_BATTLE_ONLY_FORMS + .isMegaEvolution = TRUE, + .levelUpLearnset = sPyroarLevelUpLearnset, + .teachableLearnset = sPyroarTeachableLearnset, + .formSpeciesIdTable = sPyroarFormSpeciesIdTable, + .formChangeTable = sPyroarFormChangeTable, + }, +#endif //P_GEN_9_MEGA_EVOLUTIONS #endif //P_FAMILY_LITLEO #if P_FAMILY_FLABEBE @@ -1866,6 +2173,7 @@ const struct SpeciesInfo gSpeciesInfoGen6[] = .backPicYOffset = 2, .levelUpLearnset = sFloetteEternalLevelUpLearnset, .teachableLearnset = sFloetteEternalTeachableLearnset, + .formChangeTable = sFloetteEternalFormChangeTable, }, #define FLORGES_MISC_INFO(Form, iconPal) \ @@ -1964,6 +2272,81 @@ const struct SpeciesInfo gSpeciesInfoGen6[] = "由白花装饰的个体也能与各种\n" "不同的颜色同步波长,激发力量。"), }, + +#if P_GEN_9_MEGA_EVOLUTIONS + [SPECIES_FLOETTE_MEGA] = + { + .baseHP = 74, + .baseAttack = 85, + .baseDefense = 87, + .baseSpeed = 102, + .baseSpAttack = 155, + .baseSpDefense = 148, + .types = MON_TYPES(TYPE_FAIRY), + .catchRate = 120, + .expYield = 1, + .evYield_SpDefense = 2, + .genderRatio = MON_FEMALE, + .eggCycles = 20, + .friendship = STANDARD_FRIENDSHIP, + .growthRate = GROWTH_MEDIUM_FAST, + .eggGroups = MON_EGG_GROUPS(EGG_GROUP_NO_EGGS_DISCOVERED), + .abilities = { ABILITY_FLOWER_VEIL, ABILITY_NONE, ABILITY_SYMBIOSIS }, + .bodyColor = BODY_COLOR_WHITE, + .speciesName = _("Floette"), + .cryId = CRY_FLOETTE_ETERNAL, // CRY_FLOETTE_MEGA, + .natDexNum = NATIONAL_DEX_FLOETTE, + .categoryName = _("Single Bloom"), + // height + // weight + .description = COMPOUND_STRING( + "The Eternal Flower has absorbed\n" + "all the energy from Mega\n" + "Evolution. The flower now attacks\n" + "enemies on its own."), + .frontPic = gMonFrontPic_CircledQuestionMark, + .frontPicSize = MON_COORDS_SIZE(40, 40), + .frontPicYOffset = 12, + .frontAnimFrames = sAnims_TwoFramePlaceHolder, + .frontAnimId = ANIM_V_SQUISH_AND_BOUNCE, + .backPic = gMonBackPic_CircledQuestionMark, + .backPicSize = MON_COORDS_SIZE(40, 40), + .backPicYOffset = 12, + .backAnimId = BACK_ANIM_NONE, + .palette = gMonPalette_CircledQuestionMark, + .shinyPalette = gMonShinyPalette_CircledQuestionMark, + .iconSprite = gMonIcon_QuestionMark, + .iconPalIndex = 0, + .pokemonJumpType = PKMN_JUMP_TYPE_NONE, + FOOTPRINT(QuestionMark) + SHADOW(-1, 0, SHADOW_SIZE_M) + #if OW_BATTLE_ONLY_FORMS + .overworldData = { + .tileTag = TAG_NONE, + .paletteTag = OBJ_EVENT_PAL_TAG_SUBSTITUTE, + .reflectionPaletteTag = OBJ_EVENT_PAL_TAG_NONE, + .size = 512, + .width = 32, + .height = 32, + .paletteSlot = PALSLOT_NPC_1, + .shadowSize = SHADOW_SIZE_M, + .inanimate = FALSE, + .compressed = COMP, + .tracks = TRACKS_FOOT, + .oam = &gObjectEventBaseOam_32x32, + .subspriteTables = sOamTables_32x32, + .anims = sAnimTable_Following, + .images = sPicTable_Substitute, + .affineAnims = gDummySpriteAffineAnimTable, + }, + #endif //OW_BATTLE_ONLY_FORMS + .isMegaEvolution = TRUE, + .levelUpLearnset = sFloetteEternalLevelUpLearnset, + .teachableLearnset = sFloetteEternalTeachableLearnset, + .formSpeciesIdTable = sFloetteFormSpeciesIdTable, + .formChangeTable = sFloetteEternalFormChangeTable, + }, +#endif //P_GEN_9_MEGA_EVOLUTIONS #endif //P_FAMILY_FLABEBE #if P_FAMILY_SKIDDO @@ -3221,7 +3604,84 @@ const struct SpeciesInfo gSpeciesInfoGen6[] = ) .levelUpLearnset = sMalamarLevelUpLearnset, .teachableLearnset = sMalamarTeachableLearnset, + .formSpeciesIdTable = sMalamarFormSpeciesIdTable, + .formChangeTable = sMalamarFormChangeTable, }, + +#if P_GEN_9_MEGA_EVOLUTIONS + [SPECIES_MALAMAR_MEGA] = + { + .baseHP = 86, + .baseAttack = 102, + .baseDefense = 88, + .baseSpeed = 88, + .baseSpAttack = 98, + .baseSpDefense = 120, + .types = MON_TYPES(TYPE_DARK, TYPE_PSYCHIC), + .catchRate = 80, + .expYield = 169, + .evYield_Attack = 2, + .genderRatio = PERCENT_FEMALE(50), + .eggCycles = 20, + .friendship = STANDARD_FRIENDSHIP, + .growthRate = GROWTH_MEDIUM_FAST, + .eggGroups = MON_EGG_GROUPS(EGG_GROUP_WATER_1, EGG_GROUP_WATER_2), + .abilities = { ABILITY_CONTRARY, ABILITY_SUCTION_CUPS, ABILITY_INFILTRATOR }, + .bodyColor = BODY_COLOR_BLUE, + .speciesName = _("Malamar"), + .cryId = CRY_MALAMAR, // CRY_MALAMAR_MEGA, + .natDexNum = NATIONAL_DEX_MALAMAR, + .categoryName = _("Overturning"), + .height = 29, + .weight = 698, + .description = COMPOUND_STRING( + "It uses its colorful lights to\n" + "overwrite the personality and\n" + "memories of others-and to\n" + "control them."), + .frontPic = gMonFrontPic_CircledQuestionMark, + .frontPicSize = MON_COORDS_SIZE(40, 40), + .frontPicYOffset = 12, + .frontAnimFrames = sAnims_TwoFramePlaceHolder, + .frontAnimId = ANIM_V_SQUISH_AND_BOUNCE, + .backPic = gMonBackPic_CircledQuestionMark, + .backPicSize = MON_COORDS_SIZE(40, 40), + .backPicYOffset = 12, + .backAnimId = BACK_ANIM_NONE, + .palette = gMonPalette_CircledQuestionMark, + .shinyPalette = gMonShinyPalette_CircledQuestionMark, + .iconSprite = gMonIcon_QuestionMark, + .iconPalIndex = 0, + .pokemonJumpType = PKMN_JUMP_TYPE_NONE, + FOOTPRINT(QuestionMark) + SHADOW(-1, 0, SHADOW_SIZE_M) + #if OW_BATTLE_ONLY_FORMS + .overworldData = { + .tileTag = TAG_NONE, + .paletteTag = OBJ_EVENT_PAL_TAG_SUBSTITUTE, + .reflectionPaletteTag = OBJ_EVENT_PAL_TAG_NONE, + .size = 512, + .width = 32, + .height = 32, + .paletteSlot = PALSLOT_NPC_1, + .shadowSize = SHADOW_SIZE_M, + .inanimate = FALSE, + .compressed = COMP, + .tracks = TRACKS_FOOT, + .oam = &gObjectEventBaseOam_32x32, + .subspriteTables = sOamTables_32x32, + .anims = sAnimTable_Following, + .images = sPicTable_Substitute, + .affineAnims = gDummySpriteAffineAnimTable, + }, + #endif //OW_BATTLE_ONLY_FORMS + .isMegaEvolution = TRUE, + .levelUpLearnset = sMalamarLevelUpLearnset, + .teachableLearnset = sMalamarTeachableLearnset, + .formSpeciesIdTable = sMalamarFormSpeciesIdTable, + .formChangeTable = sMalamarFormChangeTable, + }, +#endif //P_GEN_9_MEGA_EVOLUTIONS #endif //P_FAMILY_INKAY #if P_FAMILY_BINACLE @@ -3360,7 +3820,84 @@ const struct SpeciesInfo gSpeciesInfoGen6[] = ) .levelUpLearnset = sBarbaracleLevelUpLearnset, .teachableLearnset = sBarbaracleTeachableLearnset, + .formSpeciesIdTable = sBarbaracleFormSpeciesIdTable, + .formChangeTable = sBarbaracleFormChangeTable, }, + +#if P_GEN_9_MEGA_EVOLUTIONS + [SPECIES_BARBARACLE_MEGA] = + { + .baseHP = 72, + .baseAttack = 140, + .baseDefense = 130, + .baseSpeed = 88, + .baseSpAttack = 64, + .baseSpDefense = 106, + .types = MON_TYPES(TYPE_ROCK, TYPE_FIGHTING), + .catchRate = 45, + .expYield = 175, + .evYield_Attack = 2, + .genderRatio = PERCENT_FEMALE(50), + .eggCycles = 20, + .friendship = STANDARD_FRIENDSHIP, + .growthRate = GROWTH_MEDIUM_FAST, + .eggGroups = MON_EGG_GROUPS(EGG_GROUP_WATER_3), + .abilities = { ABILITY_TOUGH_CLAWS, ABILITY_SNIPER, ABILITY_PICKPOCKET }, + .bodyColor = BODY_COLOR_BROWN, + .noFlip = TRUE, + .speciesName = _("Barbaracle"), + .cryId = CRY_BARBARACLE, // CRY_BARBARACLE_MEGA, + .natDexNum = NATIONAL_DEX_BARBARACLE, + .categoryName = _("Collective"), + .height = 22, + .weight = 1000, + .description = COMPOUND_STRING( + "It uses its many arms to toy\n" + "with its opponents. This\n" + "keeps the head extremely busy."), + .frontPic = gMonFrontPic_CircledQuestionMark, + .frontPicSize = MON_COORDS_SIZE(40, 40), + .frontPicYOffset = 12, + .frontAnimFrames = sAnims_TwoFramePlaceHolder, + .frontAnimId = ANIM_V_SQUISH_AND_BOUNCE, + .backPic = gMonBackPic_CircledQuestionMark, + .backPicSize = MON_COORDS_SIZE(40, 40), + .backPicYOffset = 12, + .backAnimId = BACK_ANIM_NONE, + .palette = gMonPalette_CircledQuestionMark, + .shinyPalette = gMonShinyPalette_CircledQuestionMark, + .iconSprite = gMonIcon_QuestionMark, + .iconPalIndex = 0, + .pokemonJumpType = PKMN_JUMP_TYPE_NONE, + FOOTPRINT(QuestionMark) + SHADOW(-1, 0, SHADOW_SIZE_M) + #if OW_BATTLE_ONLY_FORMS + .overworldData = { + .tileTag = TAG_NONE, + .paletteTag = OBJ_EVENT_PAL_TAG_SUBSTITUTE, + .reflectionPaletteTag = OBJ_EVENT_PAL_TAG_NONE, + .size = 512, + .width = 32, + .height = 32, + .paletteSlot = PALSLOT_NPC_1, + .shadowSize = SHADOW_SIZE_M, + .inanimate = FALSE, + .compressed = COMP, + .tracks = TRACKS_FOOT, + .oam = &gObjectEventBaseOam_32x32, + .subspriteTables = sOamTables_32x32, + .anims = sAnimTable_Following, + .images = sPicTable_Substitute, + .affineAnims = gDummySpriteAffineAnimTable, + }, + #endif //OW_BATTLE_ONLY_FORMS + .isMegaEvolution = TRUE, + .levelUpLearnset = sBarbaracleLevelUpLearnset, + .teachableLearnset = sBarbaracleTeachableLearnset, + .formSpeciesIdTable = sBarbaracleFormSpeciesIdTable, + .formChangeTable = sBarbaracleFormChangeTable, + }, +#endif //P_GEN_9_MEGA_EVOLUTIONS #endif //P_FAMILY_BINACLE #if P_FAMILY_SKRELP @@ -3502,7 +4039,84 @@ const struct SpeciesInfo gSpeciesInfoGen6[] = ) .levelUpLearnset = sDragalgeLevelUpLearnset, .teachableLearnset = sDragalgeTeachableLearnset, + .formSpeciesIdTable = sDragalgeFormSpeciesIdTable, + .formChangeTable = sDragalgeFormChangeTable, }, + +#if P_GEN_9_MEGA_EVOLUTIONS + [SPECIES_DRAGALGE_MEGA] = + { + .baseHP = 65, + .baseAttack = 85, + .baseDefense = 105, + .baseSpeed = 44, + .baseSpAttack = 132, + .baseSpDefense = 163, + .types = MON_TYPES(TYPE_POISON, TYPE_DRAGON), + .catchRate = 55, + .expYield = 173, + .evYield_SpDefense = 2, + .genderRatio = PERCENT_FEMALE(50), + .eggCycles = 20, + .friendship = STANDARD_FRIENDSHIP, + .growthRate = GROWTH_MEDIUM_FAST, + .eggGroups = MON_EGG_GROUPS(EGG_GROUP_WATER_1, EGG_GROUP_DRAGON), + .abilities = { ABILITY_POISON_POINT, ABILITY_POISON_TOUCH, ABILITY_ADAPTABILITY }, + .bodyColor = BODY_COLOR_BROWN, + .speciesName = _("Dragalge"), + .cryId = CRY_DRAGALGE, // CRY_DRAGALGE_MEGA, + .natDexNum = NATIONAL_DEX_DRAGALGE, + .categoryName = _("Mock Kelp"), + .height = 21, + .weight = 1003, + .description = COMPOUND_STRING( + "It spits a liquid that causes the\n" + "regenerative power of cells to run\n" + "wild. The liquid is deadly poison\n" + "to everything other than itself."), + .frontPic = gMonFrontPic_CircledQuestionMark, + .frontPicSize = MON_COORDS_SIZE(40, 40), + .frontPicYOffset = 12, + .frontAnimFrames = sAnims_TwoFramePlaceHolder, + .frontAnimId = ANIM_V_SQUISH_AND_BOUNCE, + .backPic = gMonBackPic_CircledQuestionMark, + .backPicSize = MON_COORDS_SIZE(40, 40), + .backPicYOffset = 12, + .backAnimId = BACK_ANIM_NONE, + .palette = gMonPalette_CircledQuestionMark, + .shinyPalette = gMonShinyPalette_CircledQuestionMark, + .iconSprite = gMonIcon_QuestionMark, + .iconPalIndex = 0, + .pokemonJumpType = PKMN_JUMP_TYPE_NONE, + FOOTPRINT(QuestionMark) + SHADOW(-1, 0, SHADOW_SIZE_M) + #if OW_BATTLE_ONLY_FORMS + .overworldData = { + .tileTag = TAG_NONE, + .paletteTag = OBJ_EVENT_PAL_TAG_SUBSTITUTE, + .reflectionPaletteTag = OBJ_EVENT_PAL_TAG_NONE, + .size = 512, + .width = 32, + .height = 32, + .paletteSlot = PALSLOT_NPC_1, + .shadowSize = SHADOW_SIZE_M, + .inanimate = FALSE, + .compressed = COMP, + .tracks = TRACKS_FOOT, + .oam = &gObjectEventBaseOam_32x32, + .subspriteTables = sOamTables_32x32, + .anims = sAnimTable_Following, + .images = sPicTable_Substitute, + .affineAnims = gDummySpriteAffineAnimTable, + }, + #endif //OW_BATTLE_ONLY_FORMS + .isMegaEvolution = TRUE, + .levelUpLearnset = sDragalgeLevelUpLearnset, + .teachableLearnset = sDragalgeTeachableLearnset, + .formSpeciesIdTable = sDragalgeFormSpeciesIdTable, + .formChangeTable = sDragalgeFormChangeTable, + }, +#endif //P_GEN_9_MEGA_EVOLUTIONS #endif //P_FAMILY_SKRELP #if P_FAMILY_CLAUNCHER @@ -4131,7 +4745,84 @@ const struct SpeciesInfo gSpeciesInfoGen6[] = .levelUpLearnset = sHawluchaLevelUpLearnset, .teachableLearnset = sHawluchaTeachableLearnset, .eggMoveLearnset = sHawluchaEggMoveLearnset, + .formSpeciesIdTable = sHawluchaFormSpeciesIdTable, + .formChangeTable = sHawluchaFormChangeTable, }, + +#if P_GEN_9_MEGA_EVOLUTIONS + [SPECIES_HAWLUCHA_MEGA] = + { + .baseHP = 78, + .baseAttack = 137, + .baseDefense = 100, + .baseSpeed = 118, + .baseSpAttack = 74, + .baseSpDefense = 93, + .types = MON_TYPES(TYPE_FIGHTING, TYPE_FLYING), + .catchRate = 100, + .expYield = 175, + .evYield_Attack = 2, + .itemRare = ITEM_KINGS_ROCK, + .genderRatio = PERCENT_FEMALE(50), + .eggCycles = 20, + .friendship = STANDARD_FRIENDSHIP, + .growthRate = GROWTH_MEDIUM_FAST, + .eggGroups = MON_EGG_GROUPS(EGG_GROUP_FLYING, EGG_GROUP_HUMAN_LIKE), + .abilities = { ABILITY_LIMBER, ABILITY_UNBURDEN, ABILITY_MOLD_BREAKER }, + .bodyColor = BODY_COLOR_GREEN, + .speciesName = _("Hawlucha"), + .cryId = CRY_HAWLUCHA, // CRY_HAWLUCHA_MEGA, + .natDexNum = NATIONAL_DEX_HAWLUCHA, + .categoryName = _("Wrestling"), + .height = 10, + .weight = 250, + .description = COMPOUND_STRING( + "Mega Evolution has pumped up all\n" + "its muscles. Hawlucha flexes to\n" + "show off its strength."), + .frontPic = gMonFrontPic_CircledQuestionMark, + .frontPicSize = MON_COORDS_SIZE(40, 40), + .frontPicYOffset = 12, + .frontAnimFrames = sAnims_TwoFramePlaceHolder, + .frontAnimId = ANIM_V_SQUISH_AND_BOUNCE, + .backPic = gMonBackPic_CircledQuestionMark, + .backPicSize = MON_COORDS_SIZE(40, 40), + .backPicYOffset = 12, + .backAnimId = BACK_ANIM_NONE, + .palette = gMonPalette_CircledQuestionMark, + .shinyPalette = gMonShinyPalette_CircledQuestionMark, + .iconSprite = gMonIcon_QuestionMark, + .iconPalIndex = 0, + .pokemonJumpType = PKMN_JUMP_TYPE_NONE, + FOOTPRINT(QuestionMark) + SHADOW(-1, 0, SHADOW_SIZE_M) + #if OW_BATTLE_ONLY_FORMS + .overworldData = { + .tileTag = TAG_NONE, + .paletteTag = OBJ_EVENT_PAL_TAG_SUBSTITUTE, + .reflectionPaletteTag = OBJ_EVENT_PAL_TAG_NONE, + .size = 512, + .width = 32, + .height = 32, + .paletteSlot = PALSLOT_NPC_1, + .shadowSize = SHADOW_SIZE_M, + .inanimate = FALSE, + .compressed = COMP, + .tracks = TRACKS_FOOT, + .oam = &gObjectEventBaseOam_32x32, + .subspriteTables = sOamTables_32x32, + .anims = sAnimTable_Following, + .images = sPicTable_Substitute, + .affineAnims = gDummySpriteAffineAnimTable, + }, + #endif //OW_BATTLE_ONLY_FORMS + .isMegaEvolution = TRUE, + .levelUpLearnset = sHawluchaLevelUpLearnset, + .teachableLearnset = sHawluchaTeachableLearnset, + .formSpeciesIdTable = sHawluchaFormSpeciesIdTable, + .formChangeTable = sHawluchaFormChangeTable, + }, +#endif //P_GEN_9_MEGA_EVOLUTIONS #endif //P_FAMILY_HAWLUCHA #if P_FAMILY_DEDENNE @@ -4346,8 +5037,8 @@ const struct SpeciesInfo gSpeciesInfoGen6[] = .levelUpLearnset = sGoomyLevelUpLearnset, .teachableLearnset = sGoomyTeachableLearnset, .eggMoveLearnset = sGoomyEggMoveLearnset, - .evolutions = EVOLUTION({EVO_LEVEL, 40, SPECIES_SLIGGOO}, - {EVO_NONE, 0, SPECIES_SLIGGOO_HISUI}), + .evolutions = EVOLUTION({EVO_LEVEL, 40, SPECIES_SLIGGOO, CONDITIONS({IF_NOT_REGION, REGION_HISUI})}, + {EVO_LEVEL, 40, SPECIES_SLIGGOO_HISUI, CONDITIONS({IF_REGION, REGION_HISUI})}), }, [SPECIES_SLIGGOO] = @@ -5433,8 +6124,8 @@ const struct SpeciesInfo gSpeciesInfoGen6[] = .levelUpLearnset = sBergmiteLevelUpLearnset, .teachableLearnset = sBergmiteTeachableLearnset, .eggMoveLearnset = sBergmiteEggMoveLearnset, - .evolutions = EVOLUTION({EVO_LEVEL, 37, SPECIES_AVALUGG}, - {EVO_NONE, 0, SPECIES_AVALUGG_HISUI}), + .evolutions = EVOLUTION({EVO_LEVEL, 37, SPECIES_AVALUGG, CONDITIONS({IF_NOT_REGION, REGION_HISUI})}, + {EVO_LEVEL, 37, SPECIES_AVALUGG_HISUI, CONDITIONS({IF_REGION, REGION_HISUI})}), }, [SPECIES_AVALUGG] = @@ -6252,6 +6943,82 @@ const struct SpeciesInfo gSpeciesInfoGen6[] = .formSpeciesIdTable = sZygardeFormSpeciesIdTable, .formChangeTable = sZygardeCompleteFormChangeTable, }, + +#if P_GEN_9_MEGA_EVOLUTIONS + [SPECIES_ZYGARDE_MEGA] = + { + .baseHP = 216, + .baseAttack = 70, + .baseDefense = 91, + .baseSpeed = 100, + .baseSpAttack = 216, + .baseSpDefense = 85, + .types = MON_TYPES(TYPE_DRAGON, TYPE_GROUND), + .catchRate = 3, + .expYield = (P_UPDATED_EXP_YIELDS >= GEN_8) ? 354 : 319, + .evYield_HP = 3, + .genderRatio = MON_GENDERLESS, + .eggCycles = 120, + .friendship = 0, + .growthRate = GROWTH_SLOW, + .eggGroups = MON_EGG_GROUPS(EGG_GROUP_NO_EGGS_DISCOVERED), + .abilities = { ABILITY_AURA_BREAK, ABILITY_NONE, ABILITY_NONE }, + .bodyColor = BODY_COLOR_BLACK, + .noFlip = TRUE, + .speciesName = _("Zygarde"), + .cryId = CRY_ZYGARDE_COMPLETE, // CRY_ZYGARDE_MEGA, + .natDexNum = NATIONAL_DEX_ZYGARDE, + .categoryName = _("Order"), + .height = 77, + .weight = 6100, + .description = COMPOUND_STRING( + "In response to people's emotions\n" + "during an unprecedented crisis,\n" + "Zygarde Mega Evolves and calms the\n" + "situation with its unmatched power."), + .frontPic = gMonFrontPic_CircledQuestionMark, + .frontPicSize = MON_COORDS_SIZE(40, 40), + .frontPicYOffset = 12, + .frontAnimFrames = sAnims_TwoFramePlaceHolder, + .frontAnimId = ANIM_V_SQUISH_AND_BOUNCE, + .backPic = gMonBackPic_CircledQuestionMark, + .backPicSize = MON_COORDS_SIZE(40, 40), + .backPicYOffset = 12, + .backAnimId = BACK_ANIM_NONE, + .palette = gMonPalette_CircledQuestionMark, + .shinyPalette = gMonShinyPalette_CircledQuestionMark, + .iconSprite = gMonIcon_QuestionMark, + .iconPalIndex = 0, + .pokemonJumpType = PKMN_JUMP_TYPE_NONE, + FOOTPRINT(QuestionMark) + SHADOW(-1, 0, SHADOW_SIZE_M) + #if OW_BATTLE_ONLY_FORMS + .overworldData = { + .tileTag = TAG_NONE, + .paletteTag = OBJ_EVENT_PAL_TAG_SUBSTITUTE, + .reflectionPaletteTag = OBJ_EVENT_PAL_TAG_NONE, + .size = 512, + .width = 32, + .height = 32, + .paletteSlot = PALSLOT_NPC_1, + .shadowSize = SHADOW_SIZE_M, + .inanimate = FALSE, + .compressed = COMP, + .tracks = TRACKS_FOOT, + .oam = &gObjectEventBaseOam_32x32, + .subspriteTables = sOamTables_32x32, + .anims = sAnimTable_Following, + .images = sPicTable_Substitute, + .affineAnims = gDummySpriteAffineAnimTable, + }, + #endif //OW_BATTLE_ONLY_FORMS + .isMegaEvolution = TRUE, + .levelUpLearnset = sZygardeLevelUpLearnset, + .teachableLearnset = sZygardeTeachableLearnset, + .formSpeciesIdTable = sZygardeFormSpeciesIdTable, + .formChangeTable = sZygardeCompleteFormChangeTable, + }, +#endif //P_GEN_9_MEGA_EVOLUTIONS #endif //P_FAMILY_ZYGARDE #if P_FAMILY_DIANCIE diff --git a/src/data/pokemon/species_info/gen_7_families.h b/src/data/pokemon/species_info/gen_7_families.h index 0dad14a3cb..8c11d7d90d 100644 --- a/src/data/pokemon/species_info/gen_7_families.h +++ b/src/data/pokemon/species_info/gen_7_families.h @@ -135,8 +135,8 @@ const struct SpeciesInfo gSpeciesInfoGen7[] = ) .levelUpLearnset = sDartrixLevelUpLearnset, .teachableLearnset = sDartrixTeachableLearnset, - .evolutions = EVOLUTION({EVO_LEVEL, 34, SPECIES_DECIDUEYE}, - {EVO_NONE, 0, SPECIES_DECIDUEYE_HISUI}), + .evolutions = EVOLUTION({EVO_LEVEL, 34, SPECIES_DECIDUEYE, CONDITIONS({IF_NOT_REGION, REGION_HISUI})}, + {EVO_LEVEL, 36, SPECIES_DECIDUEYE_HISUI, CONDITIONS({IF_REGION, REGION_HISUI})}), }, [SPECIES_DECIDUEYE] = @@ -5141,7 +5141,85 @@ const struct SpeciesInfo gSpeciesInfoGen7[] = .levelUpLearnset = sDrampaLevelUpLearnset, .teachableLearnset = sDrampaTeachableLearnset, .eggMoveLearnset = sDrampaEggMoveLearnset, + .formSpeciesIdTable = sDrampaFormSpeciesIdTable, + .formChangeTable = sDrampaFormChangeTable, }, + +#if P_GEN_9_MEGA_EVOLUTIONS + [SPECIES_DRAMPA_MEGA] = + { + .baseHP = 78, + .baseAttack = 85, + .baseDefense = 110, + .baseSpeed = 36, + .baseSpAttack = 160, + .baseSpDefense = 116, + .types = MON_TYPES(TYPE_NORMAL, TYPE_DRAGON), + .catchRate = 70, + .expYield = 170, + .evYield_SpAttack = 2, + .itemRare = ITEM_PERSIM_BERRY, + .genderRatio = PERCENT_FEMALE(50), + .eggCycles = 20, + .friendship = STANDARD_FRIENDSHIP, + .growthRate = GROWTH_MEDIUM_FAST, + .eggGroups = MON_EGG_GROUPS(EGG_GROUP_MONSTER, EGG_GROUP_DRAGON), + .abilities = { ABILITY_BERSERK, ABILITY_SAP_SIPPER, ABILITY_CLOUD_NINE }, + .bodyColor = BODY_COLOR_WHITE, + .speciesName = _("Drampa"), + .cryId = CRY_DRAMPA, // CRY_DRAMPA_MEGA, + .natDexNum = NATIONAL_DEX_DRAMPA, + .categoryName = _("Imposing"), + .height = 3, + .weight = 2405, + .description = COMPOUND_STRING( + "Drampa's cells have been\n" + "invigorated, allowing it to regain\n" + "its youth. It manipulates the\n" + "atmosphere to summon storms."), + .frontPic = gMonFrontPic_CircledQuestionMark, + .frontPicSize = MON_COORDS_SIZE(40, 40), + .frontPicYOffset = 12, + .frontAnimFrames = sAnims_TwoFramePlaceHolder, + .frontAnimId = ANIM_V_SQUISH_AND_BOUNCE, + .backPic = gMonBackPic_CircledQuestionMark, + .backPicSize = MON_COORDS_SIZE(40, 40), + .backPicYOffset = 12, + .backAnimId = BACK_ANIM_NONE, + .palette = gMonPalette_CircledQuestionMark, + .shinyPalette = gMonShinyPalette_CircledQuestionMark, + .iconSprite = gMonIcon_QuestionMark, + .iconPalIndex = 0, + .pokemonJumpType = PKMN_JUMP_TYPE_NONE, + FOOTPRINT(QuestionMark) + SHADOW(-1, 0, SHADOW_SIZE_M) + #if OW_BATTLE_ONLY_FORMS + .overworldData = { + .tileTag = TAG_NONE, + .paletteTag = OBJ_EVENT_PAL_TAG_SUBSTITUTE, + .reflectionPaletteTag = OBJ_EVENT_PAL_TAG_NONE, + .size = 512, + .width = 32, + .height = 32, + .paletteSlot = PALSLOT_NPC_1, + .shadowSize = SHADOW_SIZE_M, + .inanimate = FALSE, + .compressed = COMP, + .tracks = TRACKS_FOOT, + .oam = &gObjectEventBaseOam_32x32, + .subspriteTables = sOamTables_32x32, + .anims = sAnimTable_Following, + .images = sPicTable_Substitute, + .affineAnims = gDummySpriteAffineAnimTable, + }, + #endif //OW_BATTLE_ONLY_FORMS + .isMegaEvolution = TRUE, + .levelUpLearnset = sDrampaLevelUpLearnset, + .teachableLearnset = sDrampaTeachableLearnset, + .formSpeciesIdTable = sDrampaFormSpeciesIdTable, + .formChangeTable = sDrampaFormChangeTable, + }, +#endif //P_GEN_9_MEGA_EVOLUTIONS #endif //P_FAMILY_DRAMPA #if P_FAMILY_DHELMISE diff --git a/src/data/pokemon/species_info/gen_8_families.h b/src/data/pokemon/species_info/gen_8_families.h index 59e79a697c..aa5c235c88 100644 --- a/src/data/pokemon/species_info/gen_8_families.h +++ b/src/data/pokemon/species_info/gen_8_families.h @@ -5180,7 +5180,85 @@ const struct SpeciesInfo gSpeciesInfoGen8[] = ) .levelUpLearnset = sFalinksLevelUpLearnset, .teachableLearnset = sFalinksTeachableLearnset, + .formSpeciesIdTable = sFalinksFormSpeciesIdTable, + .formChangeTable = sFalinksFormChangeTable, }, + +#if P_GEN_9_MEGA_EVOLUTIONS + [SPECIES_FALINKS_MEGA] = + { + .baseHP = 65, + .baseAttack = 135, + .baseDefense = 135, + .baseSpeed = 100, + .baseSpAttack = 70, + .baseSpDefense = 65, + .types = MON_TYPES(TYPE_FIGHTING), + .catchRate = 45, + .expYield = 165, + .evYield_Attack = 2, + .evYield_SpDefense = 1, + .genderRatio = MON_GENDERLESS, + .eggCycles = 25, + .friendship = STANDARD_FRIENDSHIP, + .growthRate = GROWTH_MEDIUM_FAST, + .eggGroups = MON_EGG_GROUPS(EGG_GROUP_FAIRY, EGG_GROUP_MINERAL), + .abilities = { ABILITY_BATTLE_ARMOR, ABILITY_NONE, ABILITY_DEFIANT }, + .bodyColor = BODY_COLOR_YELLOW, + .speciesName = _("Falinks"), + .cryId = CRY_FALINKS, + .natDexNum = NATIONAL_DEX_FALINKS, + .categoryName = _("Formation"), + .height = 16, + .weight = 990, + .description = COMPOUND_STRING( + "Mega Falinks has taken on the\n" + "ultimate battle formation, which\n" + "can be achieved only if the troopers\n" + "and brass have the strongest of bonds."), + .frontPic = gMonFrontPic_CircledQuestionMark, + .frontPicSize = MON_COORDS_SIZE(40, 40), + .frontPicYOffset = 12, + .frontAnimFrames = sAnims_TwoFramePlaceHolder, + .frontAnimId = ANIM_V_SQUISH_AND_BOUNCE, + .backPic = gMonBackPic_CircledQuestionMark, + .backPicSize = MON_COORDS_SIZE(40, 40), + .backPicYOffset = 12, + .backAnimId = BACK_ANIM_NONE, + .palette = gMonPalette_CircledQuestionMark, + .shinyPalette = gMonShinyPalette_CircledQuestionMark, + .iconSprite = gMonIcon_QuestionMark, + .iconPalIndex = 0, + .pokemonJumpType = PKMN_JUMP_TYPE_NONE, + FOOTPRINT(QuestionMark) + SHADOW(-1, 0, SHADOW_SIZE_M) + #if OW_BATTLE_ONLY_FORMS + .overworldData = { + .tileTag = TAG_NONE, + .paletteTag = OBJ_EVENT_PAL_TAG_SUBSTITUTE, + .reflectionPaletteTag = OBJ_EVENT_PAL_TAG_NONE, + .size = 512, + .width = 32, + .height = 32, + .paletteSlot = PALSLOT_NPC_1, + .shadowSize = SHADOW_SIZE_M, + .inanimate = FALSE, + .compressed = COMP, + .tracks = TRACKS_FOOT, + .oam = &gObjectEventBaseOam_32x32, + .subspriteTables = sOamTables_32x32, + .anims = sAnimTable_Following, + .images = sPicTable_Substitute, + .affineAnims = gDummySpriteAffineAnimTable, + }, + #endif //OW_BATTLE_ONLY_FORMS + .isMegaEvolution = TRUE, + .levelUpLearnset = sFalinksLevelUpLearnset, + .teachableLearnset = sFalinksTeachableLearnset, + .formSpeciesIdTable = sFalinksFormSpeciesIdTable, + .formChangeTable = sFalinksFormChangeTable, + }, +#endif //P_GEN_9_MEGA_EVOLUTIONS #endif //P_FAMILY_FALINKS #if P_FAMILY_PINCURCHIN diff --git a/src/data/pokemon/teachable_learnsets.h b/src/data/pokemon/teachable_learnsets.h index 8b400f5675..970cde222a 100644 --- a/src/data/pokemon/teachable_learnsets.h +++ b/src/data/pokemon/teachable_learnsets.h @@ -909,8 +909,10 @@ static const u16 sArbokTeachableLearnset[] = { static const u16 sPichuTeachableLearnset[] = { MOVE_ATTRACT, MOVE_BODY_SLAM, + MOVE_BRICK_BREAK, MOVE_COUNTER, MOVE_DEFENSE_CURL, + MOVE_DIG, MOVE_DOUBLE_EDGE, MOVE_DOUBLE_TEAM, MOVE_ENDURE, @@ -1501,6 +1503,7 @@ static const u16 sNidokingTeachableLearnset[] = { #if P_GEN_2_CROSS_EVOS static const u16 sCleffaTeachableLearnset[] = { MOVE_ATTRACT, + MOVE_BLIZZARD, MOVE_BODY_SLAM, MOVE_CALM_MIND, MOVE_COUNTER, @@ -1514,6 +1517,7 @@ static const u16 sCleffaTeachableLearnset[] = { MOVE_FIRE_BLAST, MOVE_FLAMETHROWER, MOVE_FLASH, + MOVE_ICE_BEAM, MOVE_ICY_WIND, MOVE_IRON_TAIL, MOVE_LIGHT_SCREEN, @@ -1539,6 +1543,8 @@ static const u16 sCleffaTeachableLearnset[] = { MOVE_SUNNY_DAY, MOVE_SWAGGER, MOVE_SWIFT, + MOVE_THUNDER, + MOVE_THUNDERBOLT, MOVE_THUNDER_WAVE, MOVE_TOXIC, MOVE_WATER_PULSE, @@ -4113,6 +4119,7 @@ static const u16 sSlowbroGalarTeachableLearnset[] = { MOVE_ENDURE, MOVE_FACADE, MOVE_FIRE_BLAST, + MOVE_FIRE_PUNCH, MOVE_FLAMETHROWER, MOVE_HAIL, MOVE_HYPER_BEAM, @@ -4139,6 +4146,7 @@ static const u16 sSlowbroGalarTeachableLearnset[] = { MOVE_SUNNY_DAY, MOVE_SURF, MOVE_SWIFT, + MOVE_THUNDER_PUNCH, MOVE_THUNDER_WAVE, MOVE_TOXIC, MOVE_WATERFALL, @@ -6401,6 +6409,7 @@ static const u16 sStaryuTeachableLearnset[] = { MOVE_REFLECT, MOVE_REST, MOVE_ROLLOUT, + MOVE_SAFEGUARD, MOVE_SLEEP_TALK, MOVE_SNORE, MOVE_SURF, @@ -6418,6 +6427,7 @@ static const u16 sStaryuTeachableLearnset[] = { static const u16 sStarmieTeachableLearnset[] = { MOVE_ATTRACT, MOVE_BLIZZARD, + MOVE_BULK_UP, MOVE_DIVE, MOVE_DOUBLE_EDGE, MOVE_DOUBLE_TEAM, @@ -6437,6 +6447,7 @@ static const u16 sStarmieTeachableLearnset[] = { MOVE_REFLECT, MOVE_REST, MOVE_ROLLOUT, + MOVE_SAFEGUARD, MOVE_SKILL_SWAP, MOVE_SLEEP_TALK, MOVE_SNORE, @@ -7073,6 +7084,7 @@ static const u16 sMagmortarTeachableLearnset[] = { #if P_FAMILY_PINSIR static const u16 sPinsirTeachableLearnset[] = { + MOVE_AERIAL_ACE, MOVE_ATTRACT, MOVE_BODY_SLAM, MOVE_BRICK_BREAK, @@ -7373,6 +7385,7 @@ static const u16 sVaporeonTeachableLearnset[] = { MOVE_SURF, MOVE_SWAGGER, MOVE_SWIFT, + MOVE_TAUNT, MOVE_TOXIC, MOVE_WATERFALL, MOVE_WATER_PULSE, @@ -7442,6 +7455,8 @@ static const u16 sFlareonTeachableLearnset[] = { MOVE_SUNNY_DAY, MOVE_SWAGGER, MOVE_SWIFT, + MOVE_SWORDS_DANCE, + MOVE_TAUNT, MOVE_TOXIC, MOVE_UNAVAILABLE, }; @@ -7471,6 +7486,7 @@ static const u16 sEspeonTeachableLearnset[] = { MOVE_REST, MOVE_ROAR, MOVE_ROCK_SMASH, + MOVE_SAFEGUARD, MOVE_SHADOW_BALL, MOVE_SKILL_SWAP, MOVE_SLEEP_TALK, @@ -7556,6 +7572,7 @@ static const u16 sLeafeonTeachableLearnset[] = { MOVE_SWAGGER, MOVE_SWIFT, MOVE_SWORDS_DANCE, + MOVE_TAUNT, MOVE_TOXIC, MOVE_UNAVAILABLE, }; @@ -7588,6 +7605,7 @@ static const u16 sGlaceonTeachableLearnset[] = { MOVE_SUNNY_DAY, MOVE_SWAGGER, MOVE_SWIFT, + MOVE_TAUNT, MOVE_TOXIC, MOVE_WATER_PULSE, MOVE_UNAVAILABLE, @@ -7626,6 +7644,7 @@ static const u16 sSylveonTeachableLearnset[] = { MOVE_SUNNY_DAY, MOVE_SWAGGER, MOVE_SWIFT, + MOVE_TAUNT, MOVE_TOXIC, MOVE_UNAVAILABLE, }; @@ -14445,6 +14464,7 @@ static const u16 sSableyeTeachableLearnset[] = { MOVE_REST, MOVE_ROCK_SMASH, MOVE_ROCK_TOMB, + MOVE_SAFEGUARD, MOVE_SEISMIC_TOSS, MOVE_SHADOW_BALL, MOVE_SHOCK_WAVE, @@ -14974,6 +14994,7 @@ static const u16 sIllumiseTeachableLearnset[] = { #if P_GEN_4_CROSS_EVOS static const u16 sBudewTeachableLearnset[] = { MOVE_ATTRACT, + MOVE_BODY_SLAM, MOVE_BULLET_SEED, MOVE_CUT, MOVE_DOUBLE_TEAM, @@ -16512,6 +16533,7 @@ static const u16 sShuppetTeachableLearnset[] = { MOVE_SNORE, MOVE_SUNNY_DAY, MOVE_SWAGGER, + MOVE_SWORDS_DANCE, MOVE_TAUNT, MOVE_THIEF, MOVE_THUNDER, @@ -19381,6 +19403,7 @@ static const u16 sBunearyTeachableLearnset[] = { MOVE_DIG, MOVE_DOUBLE_EDGE, MOVE_DOUBLE_TEAM, + MOVE_DYNAMIC_PUNCH, MOVE_ENDURE, MOVE_FACADE, MOVE_FIRE_PUNCH, @@ -19419,6 +19442,7 @@ static const u16 sLopunnyTeachableLearnset[] = { MOVE_DIG, MOVE_DOUBLE_EDGE, MOVE_DOUBLE_TEAM, + MOVE_DYNAMIC_PUNCH, MOVE_ENDURE, MOVE_FACADE, MOVE_FIRE_PUNCH, @@ -19444,6 +19468,7 @@ static const u16 sLopunnyTeachableLearnset[] = { MOVE_SUNNY_DAY, MOVE_SWAGGER, MOVE_SWIFT, + MOVE_SWORDS_DANCE, MOVE_THUNDER, MOVE_THUNDERBOLT, MOVE_THUNDER_PUNCH, @@ -19778,6 +19803,7 @@ static const u16 sGabiteTeachableLearnset[] = { MOVE_AERIAL_ACE, MOVE_ATTRACT, MOVE_BODY_SLAM, + MOVE_BRICK_BREAK, MOVE_CUT, MOVE_DIG, MOVE_DOUBLE_EDGE, @@ -21372,6 +21398,7 @@ static const u16 sPatratTeachableLearnset[] = { MOVE_CUT, MOVE_DIG, MOVE_DOUBLE_TEAM, + MOVE_ENDURE, MOVE_FACADE, MOVE_IRON_TAIL, MOVE_PROTECT, @@ -21394,8 +21421,10 @@ static const u16 sWatchogTeachableLearnset[] = { MOVE_BULLET_SEED, MOVE_CUT, MOVE_DIG, + MOVE_DOUBLE_EDGE, MOVE_DOUBLE_TEAM, MOVE_DREAM_EATER, + MOVE_ENDURE, MOVE_FACADE, MOVE_FIRE_PUNCH, MOVE_FLAMETHROWER, @@ -21417,6 +21446,7 @@ static const u16 sWatchogTeachableLearnset[] = { MOVE_STRENGTH, MOVE_SUNNY_DAY, MOVE_SWAGGER, + MOVE_SWIFT, MOVE_SWORDS_DANCE, MOVE_THUNDER, MOVE_THUNDERBOLT, @@ -21576,10 +21606,12 @@ static const u16 sLiepardTeachableLearnset[] = { #if P_FAMILY_PANSAGE static const u16 sPansageTeachableLearnset[] = { MOVE_ATTRACT, + MOVE_BRICK_BREAK, MOVE_BULLET_SEED, MOVE_CUT, MOVE_DIG, MOVE_DOUBLE_TEAM, + MOVE_ENDURE, MOVE_FACADE, MOVE_FLASH, MOVE_FOCUS_PUNCH, @@ -21587,6 +21619,7 @@ static const u16 sPansageTeachableLearnset[] = { MOVE_IRON_TAIL, MOVE_PROTECT, MOVE_REST, + MOVE_ROCK_SLIDE, MOVE_ROCK_SMASH, MOVE_ROCK_TOMB, MOVE_SLEEP_TALK, @@ -21594,6 +21627,7 @@ static const u16 sPansageTeachableLearnset[] = { MOVE_SOLAR_BEAM, MOVE_SUNNY_DAY, MOVE_SWAGGER, + MOVE_SWIFT, MOVE_TAUNT, MOVE_THIEF, MOVE_TORMENT, @@ -21608,6 +21642,7 @@ static const u16 sSimisageTeachableLearnset[] = { MOVE_CUT, MOVE_DIG, MOVE_DOUBLE_TEAM, + MOVE_ENDURE, MOVE_FACADE, MOVE_FLASH, MOVE_FOCUS_PUNCH, @@ -21624,6 +21659,7 @@ static const u16 sSimisageTeachableLearnset[] = { MOVE_SOLAR_BEAM, MOVE_SUNNY_DAY, MOVE_SWAGGER, + MOVE_SWIFT, MOVE_TAUNT, MOVE_THIEF, MOVE_TORMENT, @@ -21635,9 +21671,11 @@ static const u16 sSimisageTeachableLearnset[] = { #if P_FAMILY_PANSEAR static const u16 sPansearTeachableLearnset[] = { MOVE_ATTRACT, + MOVE_BRICK_BREAK, MOVE_CUT, MOVE_DIG, MOVE_DOUBLE_TEAM, + MOVE_ENDURE, MOVE_FACADE, MOVE_FIRE_BLAST, MOVE_FIRE_PUNCH, @@ -21647,6 +21685,7 @@ static const u16 sPansearTeachableLearnset[] = { MOVE_OVERHEAT, MOVE_PROTECT, MOVE_REST, + MOVE_ROCK_SLIDE, MOVE_ROCK_SMASH, MOVE_ROCK_TOMB, MOVE_SLEEP_TALK, @@ -21654,6 +21693,7 @@ static const u16 sPansearTeachableLearnset[] = { MOVE_SOLAR_BEAM, MOVE_SUNNY_DAY, MOVE_SWAGGER, + MOVE_SWIFT, MOVE_TAUNT, MOVE_THIEF, MOVE_TORMENT, @@ -21667,6 +21707,7 @@ static const u16 sSimisearTeachableLearnset[] = { MOVE_CUT, MOVE_DIG, MOVE_DOUBLE_TEAM, + MOVE_ENDURE, MOVE_FACADE, MOVE_FIRE_BLAST, MOVE_FIRE_PUNCH, @@ -21685,6 +21726,7 @@ static const u16 sSimisearTeachableLearnset[] = { MOVE_SOLAR_BEAM, MOVE_SUNNY_DAY, MOVE_SWAGGER, + MOVE_SWIFT, MOVE_TAUNT, MOVE_THIEF, MOVE_TORMENT, @@ -21697,10 +21739,12 @@ static const u16 sSimisearTeachableLearnset[] = { static const u16 sPanpourTeachableLearnset[] = { MOVE_ATTRACT, MOVE_BLIZZARD, + MOVE_BRICK_BREAK, MOVE_CUT, MOVE_DIG, MOVE_DIVE, MOVE_DOUBLE_TEAM, + MOVE_ENDURE, MOVE_FACADE, MOVE_FOCUS_PUNCH, MOVE_HAIL, @@ -21711,12 +21755,14 @@ static const u16 sPanpourTeachableLearnset[] = { MOVE_PROTECT, MOVE_RAIN_DANCE, MOVE_REST, + MOVE_ROCK_SLIDE, MOVE_ROCK_SMASH, MOVE_ROCK_TOMB, MOVE_SLEEP_TALK, MOVE_SNORE, MOVE_SURF, MOVE_SWAGGER, + MOVE_SWIFT, MOVE_TAUNT, MOVE_THIEF, MOVE_TORMENT, @@ -21734,6 +21780,7 @@ static const u16 sSimipourTeachableLearnset[] = { MOVE_DIG, MOVE_DIVE, MOVE_DOUBLE_TEAM, + MOVE_ENDURE, MOVE_FACADE, MOVE_FOCUS_PUNCH, MOVE_HAIL, @@ -21752,6 +21799,7 @@ static const u16 sSimipourTeachableLearnset[] = { MOVE_SNORE, MOVE_SURF, MOVE_SWAGGER, + MOVE_SWIFT, MOVE_TAUNT, MOVE_THIEF, MOVE_TORMENT, @@ -22558,6 +22606,7 @@ static const u16 sVenipedeTeachableLearnset[] = { MOVE_PROTECT, MOVE_REST, MOVE_ROCK_SMASH, + MOVE_ROCK_TOMB, MOVE_ROLLOUT, MOVE_SLEEP_TALK, MOVE_SLUDGE_BOMB, @@ -22580,6 +22629,7 @@ static const u16 sWhirlipedeTeachableLearnset[] = { MOVE_PROTECT, MOVE_REST, MOVE_ROCK_SMASH, + MOVE_ROCK_TOMB, MOVE_ROLLOUT, MOVE_SLEEP_TALK, MOVE_SLUDGE_BOMB, @@ -22823,6 +22873,7 @@ static const u16 sBasculegionTeachableLearnset[] = { #if P_FAMILY_SANDILE static const u16 sSandileTeachableLearnset[] = { + MOVE_AERIAL_ACE, MOVE_ATTRACT, MOVE_BODY_SLAM, MOVE_BRICK_BREAK, @@ -22831,6 +22882,7 @@ static const u16 sSandileTeachableLearnset[] = { MOVE_DIG, MOVE_DOUBLE_EDGE, MOVE_DOUBLE_TEAM, + MOVE_DRAGON_CLAW, MOVE_EARTHQUAKE, MOVE_ENDURE, MOVE_FACADE, @@ -23166,6 +23218,7 @@ static const u16 sScraggyTeachableLearnset[] = { MOVE_DOUBLE_EDGE, MOVE_DOUBLE_TEAM, MOVE_DRAGON_CLAW, + MOVE_DYNAMIC_PUNCH, MOVE_ENDURE, MOVE_FACADE, MOVE_FIRE_PUNCH, @@ -23206,6 +23259,7 @@ static const u16 sScraftyTeachableLearnset[] = { MOVE_DOUBLE_EDGE, MOVE_DOUBLE_TEAM, MOVE_DRAGON_CLAW, + MOVE_DYNAMIC_PUNCH, MOVE_ENDURE, MOVE_FACADE, MOVE_FIRE_PUNCH, @@ -23513,6 +23567,7 @@ static const u16 sArcheopsTeachableLearnset[] = { #if P_FAMILY_TRUBBISH static const u16 sTrubbishTeachableLearnset[] = { MOVE_ATTRACT, + MOVE_BULLET_SEED, MOVE_DOUBLE_TEAM, MOVE_ENDURE, MOVE_EXPLOSION, @@ -23535,6 +23590,7 @@ static const u16 sTrubbishTeachableLearnset[] = { static const u16 sGarbodorTeachableLearnset[] = { MOVE_ATTRACT, MOVE_BODY_SLAM, + MOVE_BULLET_SEED, MOVE_DOUBLE_TEAM, MOVE_ENDURE, MOVE_EXPLOSION, @@ -24568,6 +24624,7 @@ static const u16 sKlinklangTeachableLearnset[] = { #if P_FAMILY_TYNAMO static const u16 sTynamoTeachableLearnset[] = { + MOVE_PROTECT, MOVE_THUNDER_WAVE, MOVE_UNAVAILABLE, }; @@ -24633,6 +24690,7 @@ static const u16 sEelektrossTeachableLearnset[] = { MOVE_THUNDER_PUNCH, MOVE_THUNDER_WAVE, MOVE_TOXIC, + MOVE_WATERFALL, MOVE_UNAVAILABLE, }; #endif //P_FAMILY_TYNAMO @@ -25106,6 +25164,7 @@ static const u16 sStunfiskGalarTeachableLearnset[] = { MOVE_SNORE, MOVE_SURF, MOVE_THUNDER_WAVE, + MOVE_TOXIC, MOVE_UNAVAILABLE, }; #endif //P_GALARIAN_FORMS @@ -26523,6 +26582,7 @@ static const u16 sFrogadierTeachableLearnset[] = { MOVE_AERIAL_ACE, MOVE_ATTRACT, MOVE_BLIZZARD, + MOVE_BRICK_BREAK, MOVE_COUNTER, MOVE_CUT, MOVE_DIG, @@ -26762,6 +26822,7 @@ static const u16 sTalonflameTeachableLearnset[] = { #if P_FAMILY_SCATTERBUG static const u16 sScatterbugTeachableLearnset[] = { + MOVE_PROTECT, MOVE_UNAVAILABLE, }; @@ -26926,6 +26987,7 @@ static const u16 sFloetteEternalTeachableLearnset[] = { MOVE_FACADE, MOVE_FLASH, MOVE_GIGA_DRAIN, + MOVE_HYPER_BEAM, MOVE_LIGHT_SCREEN, MOVE_METRONOME, MOVE_PROTECT, @@ -27099,6 +27161,7 @@ static const u16 sPangoroTeachableLearnset[] = { MOVE_FACADE, MOVE_FIRE_PUNCH, MOVE_FOCUS_PUNCH, + MOVE_GIGA_DRAIN, MOVE_HYPER_BEAM, MOVE_ICE_PUNCH, MOVE_MEGA_KICK, @@ -27133,9 +27196,12 @@ static const u16 sPangoroTeachableLearnset[] = { static const u16 sFurfrouTeachableLearnset[] = { MOVE_ATTRACT, MOVE_DIG, + MOVE_DOUBLE_EDGE, MOVE_DOUBLE_TEAM, + MOVE_ENDURE, MOVE_FACADE, MOVE_FLASH, + MOVE_HYPER_BEAM, MOVE_IRON_TAIL, MOVE_PROTECT, MOVE_RAIN_DANCE, @@ -27217,6 +27283,7 @@ static const u16 sMeowsticMTeachableLearnset[] = { MOVE_SUNNY_DAY, MOVE_SWAGGER, MOVE_SWIFT, + MOVE_TAUNT, MOVE_THUNDERBOLT, MOVE_THUNDER_WAVE, MOVE_TORMENT, @@ -27257,6 +27324,7 @@ static const u16 sMeowsticFTeachableLearnset[] = { MOVE_THUNDER_WAVE, MOVE_TORMENT, MOVE_TOXIC, + MOVE_WATER_PULSE, MOVE_UNAVAILABLE, }; #endif //P_FAMILY_ESPURR @@ -27417,6 +27485,7 @@ static const u16 sSwirlixTeachableLearnset[] = { MOVE_SUNNY_DAY, MOVE_SURF, MOVE_SWAGGER, + MOVE_SWORDS_DANCE, MOVE_THIEF, MOVE_THUNDERBOLT, MOVE_TOXIC, @@ -27446,6 +27515,7 @@ static const u16 sSlurpuffTeachableLearnset[] = { MOVE_SUNNY_DAY, MOVE_SURF, MOVE_SWAGGER, + MOVE_SWORDS_DANCE, MOVE_THIEF, MOVE_THUNDER, MOVE_THUNDERBOLT, @@ -27491,6 +27561,7 @@ static const u16 sInkayTeachableLearnset[] = { static const u16 sMalamarTeachableLearnset[] = { MOVE_AERIAL_ACE, MOVE_ATTRACT, + MOVE_BULK_UP, MOVE_CALM_MIND, MOVE_CUT, MOVE_DOUBLE_TEAM, @@ -27558,6 +27629,7 @@ static const u16 sBinacleTeachableLearnset[] = { MOVE_THIEF, MOVE_TORMENT, MOVE_TOXIC, + MOVE_WATERFALL, MOVE_WATER_PULSE, MOVE_UNAVAILABLE, }; @@ -27600,6 +27672,7 @@ static const u16 sBarbaracleTeachableLearnset[] = { MOVE_THIEF, MOVE_TORMENT, MOVE_TOXIC, + MOVE_WATERFALL, MOVE_WATER_PULSE, MOVE_UNAVAILABLE, }; @@ -28061,6 +28134,7 @@ static const u16 sGoomyTeachableLearnset[] = { MOVE_SLUDGE_BOMB, MOVE_SNORE, MOVE_SUNNY_DAY, + MOVE_SURF, MOVE_SWAGGER, MOVE_THUNDERBOLT, MOVE_TOXIC, @@ -28087,6 +28161,7 @@ static const u16 sSliggooTeachableLearnset[] = { MOVE_SLUDGE_BOMB, MOVE_SNORE, MOVE_SUNNY_DAY, + MOVE_SURF, MOVE_SWAGGER, MOVE_THUNDER, MOVE_THUNDERBOLT, @@ -28109,6 +28184,7 @@ static const u16 sGoodraTeachableLearnset[] = { MOVE_FIRE_PUNCH, MOVE_FLAMETHROWER, MOVE_FOCUS_PUNCH, + MOVE_GIGA_DRAIN, MOVE_HAIL, MOVE_HYPER_BEAM, MOVE_ICE_BEAM, @@ -28154,8 +28230,10 @@ static const u16 sSliggooHisuiTeachableLearnset[] = { MOVE_SLEEP_TALK, MOVE_SLUDGE_BOMB, MOVE_SUNNY_DAY, + MOVE_SURF, MOVE_THUNDER, MOVE_THUNDERBOLT, + MOVE_TOXIC, MOVE_WATER_PULSE, MOVE_UNAVAILABLE, }; @@ -28188,6 +28266,7 @@ static const u16 sGoodraHisuiTeachableLearnset[] = { MOVE_THUNDER, MOVE_THUNDERBOLT, MOVE_THUNDER_PUNCH, + MOVE_TOXIC, MOVE_WATER_PULSE, MOVE_UNAVAILABLE, }; @@ -28441,6 +28520,7 @@ static const u16 sAvaluggHisuiTeachableLearnset[] = { MOVE_ROCK_TOMB, MOVE_SANDSTORM, MOVE_SLEEP_TALK, + MOVE_SURF, MOVE_WATER_PULSE, MOVE_UNAVAILABLE, }; @@ -30524,6 +30604,7 @@ static const u16 sBruxishTeachableLearnset[] = { static const u16 sDrampaTeachableLearnset[] = { MOVE_ATTRACT, MOVE_BLIZZARD, + MOVE_BODY_SLAM, MOVE_CALM_MIND, MOVE_DOUBLE_TEAM, MOVE_DRAGON_CLAW, diff --git a/src/data/region_map/region_map_sections.json b/src/data/region_map/region_map_sections.json index cb5d5125b9..f14469c5b1 100644 --- a/src/data/region_map/region_map_sections.json +++ b/src/data/region_map/region_map_sections.json @@ -531,7 +531,6 @@ { "id": "MAPSEC_AQUA_HIDEOUT_OLD", "name": "{AQUA}基地", - "name_clone": true, "x": 19, "y": 3, "width": 1, @@ -698,12 +697,7 @@ "height": 1 }, { - "id": "MAPSEC_DYNAMIC", - "name": " ", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "id": "MAPSEC_DYNAMIC" }, { "id": "MAPSEC_PALLET_TOWN", @@ -795,21 +789,11 @@ }, { "id": "MAPSEC_ROUTE_4_POKECENTER", - "name": "4号道路", - "name_clone": true, - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "4号道路" }, { "id": "MAPSEC_ROUTE_10_POKECENTER", - "name": "10号道路", - "name_clone": true, - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "10号道路" }, { "id": "MAPSEC_ROUTE_1", @@ -1045,12 +1029,7 @@ }, { "id": "MAPSEC_UNDERGROUND_PATH_2", - "name": "地下通道", - "name_clone": true, - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "地下通道" }, { "id": "MAPSEC_DIGLETTS_CAVE", @@ -1062,12 +1041,7 @@ }, { "id": "MAPSEC_KANTO_VICTORY_ROAD", - "name": "冠军之路", - "name_clone": true, - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "冠军之路" }, { "id": "MAPSEC_ROCKET_HIDEOUT", @@ -1095,12 +1069,7 @@ }, { "id": "MAPSEC_KANTO_SAFARI_ZONE", - "name": "狩猎地带", - "name_clone": true, - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "狩猎地带" }, { "id": "MAPSEC_POKEMON_LEAGUE", @@ -1440,12 +1409,7 @@ }, { "id": "MAPSEC_TRAINER_TOWER_2", - "name": "训练家塔", - "name_clone": true, - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "训练家塔" }, { "id": "MAPSEC_DOTTED_HOLE", diff --git a/src/data/region_map/region_map_sections.json.txt b/src/data/region_map/region_map_sections.json.txt index ae0626243a..5c532a050a 100644 --- a/src/data/region_map/region_map_sections.json.txt +++ b/src/data/region_map/region_map_sections.json.txt @@ -2,19 +2,6 @@ #ifndef GUARD_DATA_REGION_MAP_REGION_MAP_ENTRIES_H #define GUARD_DATA_REGION_MAP_REGION_MAP_ENTRIES_H -## for map_section in map_sections -{% if existsIn(map_section, "name") and isEmptyString(getVar(map_section.name)) and not existsIn(map_section, "name_clone") %}{{ setVar(map_section.name, map_section.id) }}{% endif %} -## endfor - -## for map_section in map_sections -{% if existsIn(map_section, "name") %} -static const u8 sMapName_{{ map_section.id }}[] = _("{{ map_section.name }}"); -{% if existsIn(map_section, "name_clone") %} -static const u8 sMapName_{{ map_section.id }}_Clone[] = _("{{ map_section.name }}"); -{% endif %} -{% endif %} -## endfor - const struct RegionMapLocation gRegionMapEntries[] = { ## for map_section in map_sections [{{ map_section.id }}] = { @@ -39,7 +26,7 @@ const struct RegionMapLocation gRegionMapEntries[] = { .height = 1, {% endif %} {% if existsIn(map_section, "name") %} - .name = sMapName_{{ map_section.id }}{% if existsIn(map_section, "name_clone") %}_Clone{% endif %}, + .name = COMPOUND_STRING("{{ map_section.name }}"), {% else %} .name = (const u8[])_(""), {% endif %} diff --git a/src/data/speaker_names.h b/src/data/speaker_names.h new file mode 100644 index 0000000000..27ac3df290 --- /dev/null +++ b/src/data/speaker_names.h @@ -0,0 +1,5 @@ +const u8 *const gSpeakerNamesTable[SP_NAME_COUNT] = +{ + [SP_NAME_MOM] = COMPOUND_STRING("妈妈"), + [SP_NAME_PLAYER] = COMPOUND_STRING("{PLAYER}"), +}; diff --git a/src/data/trainers.party b/src/data/trainers.party index 6671c30170..ca5d68e588 100644 --- a/src/data/trainers.party +++ b/src/data/trainers.party @@ -1,16875 +1,16875 @@ -/* -Trainers and their parties defined with Competetive Syntax. -Compatible with Pokemon Showdown exports. -https://github.com/smogon/pokemon-showdown/blob/master/sim/TEAMS.md - -A trainer specification starts with "=== TRAINER_XXXX ===" -and includes everything until the next line that starts with "===" -or the file ends. -A blank line is required between the trainer and their Pokemon -and between their Pokemon. -TRAINER_XXXX is how the trainer is referred to within code. - -Fields with description and/or example of usage -Required fields for trainers: - - Name - - Pic -Optional (but still recommended) fields for trainers: - - Class (if not specified, PkMn Trainer will be used) - - Gender (Male/Female, affects random gender weights of party if not specified) - - Music - - Items (Some Item / Another Item / Third Item) - (Can also be specified with ITEM_SOME_ITEM) - - Battle Type (Singles / Doubles, defaults to Singles) - - AI (Ai Flag / Another Flag / Third Flag / ... - see "constants/battle_ai.h" for all flags) - - Mugshot (enable Mugshots during battle transition - set to one of Purple, Green, Pink, Blue or Yellow) - - Starting Status (see include/constants/battle.h for values) - -Pokemon are then specified using the Showdown Export format. -If a field is not specified, it will use it's default value. - -Required fields for Pokemon: - - Species (Either as SPECIES_ABRA or Abra) - This line also specifies Gender, Nickname and Held item. - Alfred (Abra) (M) @ Eviolite - Roberta (SPECIES_ABRA) (F) @ ITEM_CHOICE_SPECS - Both lines are valid. Gender (M) or (F) must use a capital letter. - Nickname length is limited to 10 characters using standard letters. - With narrow font it's increased to 12. Longer strings will be silently shortened. - -Optional fields for Pokemon: - - Level (Number between 1 and 100, defaults to 100) - - Ability (Ability Name or ABILITY_ABILITY_NAME) - - IVs (0 HP / 1 Atk / 2 Def / 3 SpA / 4 SpD / 5 Spe, defaults to all 31) - (Order does not matter) - - EVs (252 HP / 128 Spe / 48 Def, defaults to all 0, is not capped at 512 total) - (Order does not matter) - - Ball (Poke Ball or ITEM_POKE_BALL, defaults to Poke Ball) - - Happiness (Number between 1 and 255) - - Nature (Rash or NATURE_RASH, defaults to Hardy) - - Shiny (Yes/No, defaults to No) - - Dynamax Level (Number between 0 and 10, default 10, also sets "shouldDynamax" to True) - - Gigantamax (Yes/No, sets to Gigantamax factor) - (doesn't do anything to Pokemon without a Gigantamax form, also sets "shouldDynamax" to True) - - Tera Type (Set to a Type, either Fire or TYPE_FIRE, also sets "shouldTerastal" to True) -Moves are defined with a - (dash) followed by a single space, then the move name. -Either "- Tackle" or "- MOVE_TACKLE" works. One move per line. -Moves have to be the last lines of a Pokemon. -If no moves are specified, the Pokemon will use the last 4 moves it learns -through levelup at its level. - -Default IVs and Level can be changed in the "main" function of tools/trainerproc/main.c - -This file is processed with a custom preprocessor. -*/ - -/* -Comments can be added as C comment blocks -// cannot be used as comments -*/ - -/*Comments can also be on a single line*/ - - -=== TRAINER_NONE === -Name: -Class: Pkmn Trainer 1 -Pic: Hiker -Gender: Male -Music: Male -Double Battle: No - -=== TRAINER_SAWYER_1 === -Name: 雅彦 -Class: Hiker -Pic: Hiker -Gender: Male -Music: Hiker -Double Battle: No -AI: Basic Trainer - -Geodude -Level: 21 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_GRUNT_AQUA_HIDEOUT_1 === -Name: 手下 -Class: Team Aqua -Pic: Aqua Grunt M -Gender: Male -Music: Aqua -Double Battle: No -AI: Check Bad Move - -Poochyena -Level: 32 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_GRUNT_AQUA_HIDEOUT_2 === -Name: 手下 -Class: Team Aqua -Pic: Aqua Grunt M -Gender: Male -Music: Aqua -Double Battle: No -AI: Check Bad Move - -Zubat -Level: 31 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Carvanha -Level: 31 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_GRUNT_AQUA_HIDEOUT_3 === -Name: 手下 -Class: Team Aqua -Pic: Aqua Grunt M -Gender: Male -Music: Aqua -Double Battle: No -AI: Check Bad Move - -Zubat -Level: 32 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_GRUNT_AQUA_HIDEOUT_4 === -Name: 手下 -Class: Team Aqua -Pic: Aqua Grunt M -Gender: Male -Music: Aqua -Double Battle: No -AI: Check Bad Move - -Carvanha -Level: 32 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_GRUNT_SEAFLOOR_CAVERN_1 === -Name: 手下 -Class: Team Aqua -Pic: Aqua Grunt M -Gender: Male -Music: Aqua -Double Battle: No -AI: Check Bad Move - -Poochyena -Level: 36 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_GRUNT_SEAFLOOR_CAVERN_2 === -Name: 手下 -Class: Team Aqua -Pic: Aqua Grunt M -Gender: Male -Music: Aqua -Double Battle: No -AI: Check Bad Move - -Carvanha -Level: 36 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_GRUNT_SEAFLOOR_CAVERN_3 === -Name: 手下 -Class: Team Aqua -Pic: Aqua Grunt M -Gender: Male -Music: Aqua -Double Battle: No -AI: Check Bad Move - -Zubat -Level: 36 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_GABRIELLE_1 === -Name: 福美 -Class: Pkmn Breeder -Pic: Pokemon Breeder F -Gender: Female -Music: Female -Double Battle: No -AI: Check Bad Move - -Skitty -Level: 26 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Poochyena -Level: 26 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Zigzagoon -Level: 26 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Lotad -Level: 26 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Seedot -Level: 26 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Taillow -Level: 26 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_GRUNT_PETALBURG_WOODS === -Name: 手下 -Class: Team Aqua -Pic: Aqua Grunt M -Gender: Male -Music: Aqua -Double Battle: No -AI: Check Bad Move - -Poochyena -Level: 9 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_MARCEL === -Name: 节夫 -Class: Cooltrainer -Pic: Cooltrainer M -Gender: Male -Music: Cool -Items: Hyper Potion -Double Battle: No -AI: Basic Trainer - -Manectric -Level: 29 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -Shiftry -Level: 29 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -=== TRAINER_ALBERTO === -Name: 洋介 -Class: Bird Keeper -Pic: Bird Keeper -Gender: Male -Music: Cool -Double Battle: No -AI: Check Bad Move - -Pelipper -Level: 30 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Xatu -Level: 30 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_ED === -Name: 杰 -Class: Collector -Pic: Collector -Gender: Male -Music: Suspicious -Double Battle: No -AI: Check Bad Move - -Zangoose -Level: 30 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Seviper -Level: 30 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_GRUNT_SEAFLOOR_CAVERN_4 === -Name: 手下 -Class: Team Aqua -Pic: Aqua Grunt F -Gender: Female -Music: Aqua -Double Battle: No -AI: Check Bad Move - -Carvanha -Level: 36 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_DECLAN === -Name: 一平 -Class: Swimmer M -Pic: Swimmer M -Gender: Male -Music: Swimmer -Double Battle: No -AI: Check Bad Move - -Gyarados -Level: 34 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_GRUNT_RUSTURF_TUNNEL === -Name: 手下 -Class: Team Aqua -Pic: Aqua Grunt M -Gender: Male -Music: Aqua -Double Battle: No -AI: Check Bad Move - -Poochyena -Level: 11 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_GRUNT_WEATHER_INST_1 === -Name: 手下 -Class: Team Aqua -Pic: Aqua Grunt M -Gender: Male -Music: Aqua -Double Battle: No -AI: Check Bad Move - -Zubat -Level: 27 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Poochyena -Level: 27 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_GRUNT_WEATHER_INST_2 === -Name: 手下 -Class: Team Aqua -Pic: Aqua Grunt M -Gender: Male -Music: Aqua -Double Battle: No -AI: Check Bad Move - -Poochyena -Level: 27 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Carvanha -Level: 27 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_GRUNT_WEATHER_INST_3 === -Name: 手下 -Class: Team Aqua -Pic: Aqua Grunt M -Gender: Male -Music: Aqua -Double Battle: No -AI: Check Bad Move - -Poochyena -Level: 26 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Zubat -Level: 26 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Carvanha -Level: 26 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_GRUNT_MUSEUM_1 === -Name: 手下 -Class: Team Aqua -Pic: Aqua Grunt M -Gender: Male -Music: Aqua -Double Battle: No -AI: Check Bad Move - -Carvanha -Level: 15 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_GRUNT_MUSEUM_2 === -Name: 手下 -Class: Team Aqua -Pic: Aqua Grunt M -Gender: Male -Music: Aqua -Double Battle: No -AI: Check Bad Move - -Zubat -Level: 14 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Carvanha -Level: 14 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_GRUNT_SPACE_CENTER_1 === -Name: 手下 -Class: Team Magma -Pic: Magma Grunt M -Gender: Male -Music: Magma -Double Battle: No -AI: Check Bad Move - -Numel -Level: 32 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_GRUNT_MT_PYRE_1 === -Name: 手下 -Class: Team Aqua -Pic: Aqua Grunt M -Gender: Male -Music: Aqua -Double Battle: No -AI: Check Bad Move - -Zubat -Level: 32 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_GRUNT_MT_PYRE_2 === -Name: 手下 -Class: Team Aqua -Pic: Aqua Grunt M -Gender: Male -Music: Aqua -Double Battle: No -AI: Check Bad Move - -Carvanha -Level: 32 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_GRUNT_MT_PYRE_3 === -Name: 手下 -Class: Team Aqua -Pic: Aqua Grunt M -Gender: Male -Music: Aqua -Double Battle: No -AI: Check Bad Move - -Poochyena -Level: 30 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Carvanha -Level: 30 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_GRUNT_WEATHER_INST_4 === -Name: 手下 -Class: Team Aqua -Pic: Aqua Grunt F -Gender: Female -Music: Aqua -Double Battle: No -AI: Check Bad Move - -Carvanha -Level: 28 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_GRUNT_AQUA_HIDEOUT_5 === -Name: 手下 -Class: Team Aqua -Pic: Aqua Grunt F -Gender: Female -Music: Aqua -Double Battle: No -AI: Check Bad Move - -Carvanha -Level: 32 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_GRUNT_AQUA_HIDEOUT_6 === -Name: 手下 -Class: Team Aqua -Pic: Aqua Grunt F -Gender: Female -Music: Aqua -Double Battle: No -AI: Check Bad Move - -Zubat -Level: 32 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_FREDRICK === -Name: 寿茂 -Class: Expert -Pic: Expert M -Gender: Male -Music: Intense -Double Battle: No -AI: Basic Trainer - -Makuhita -Level: 30 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -Machoke -Level: 30 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -=== TRAINER_MATT === -Name: 阿潮 -Class: Aqua Admin -Pic: Aqua Admin M -Gender: Male -Music: Aqua -Items: Super Potion -Double Battle: No -AI: Basic Trainer - -Mightyena -Level: 34 -IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe - -Golbat -Level: 34 -IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe - -=== TRAINER_ZANDER === -Name: 良治 -Class: Black Belt -Pic: Black Belt -Gender: Male -Music: Intense -Double Battle: No -AI: Check Bad Move - -Hariyama -Level: 31 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_SHELLY_WEATHER_INSTITUTE === -Name: 阿泉 -Class: Aqua Admin -Pic: Aqua Admin F -Gender: Female -Music: Aqua -Double Battle: No -AI: Basic Trainer - -Carvanha -Level: 28 -IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe - -Mightyena -Level: 28 -IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe - -=== TRAINER_SHELLY_SEAFLOOR_CAVERN === -Name: 阿泉 -Class: Aqua Admin -Pic: Aqua Admin F -Gender: Female -Music: Aqua -Double Battle: No -AI: Basic Trainer - -Sharpedo -Level: 37 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -Mightyena -Level: 37 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -=== TRAINER_ARCHIE === -Name: 水梧桐 -Class: Aqua Leader -Pic: Aqua Leader Archie -Gender: Male -Music: Aqua -Items: Super Potion / Super Potion -Double Battle: No -AI: Basic Trainer - -Mightyena -Level: 41 -IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe - -Crobat -Level: 41 -IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe - -Sharpedo -Level: 43 -IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe - -=== TRAINER_LEAH === -Name: 绘美 -Class: Hex Maniac -Pic: Hex Maniac -Gender: Female -Music: Suspicious -Double Battle: No -AI: Check Bad Move - -Spoink -Level: 31 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_DAISY === -Name: 美鸟 -Class: Aroma Lady -Pic: Aroma Lady -Gender: Female -Music: Female -Double Battle: No -AI: Check Bad Move - -Shroomish -Level: 14 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Roselia -Level: 14 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_ROSE_1 === -Name: 弥生 -Class: Aroma Lady -Pic: Aroma Lady -Gender: Female -Music: Female -Double Battle: No -AI: Check Bad Move - -Roselia -Level: 14 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Shroomish -Level: 14 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Roselia -Level: 14 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_FELIX === -Name: 幸次郎 -Class: Cooltrainer -Pic: Cooltrainer M -Gender: Male -Music: Cool -Items: Full Restore -Double Battle: No -AI: Basic Trainer - -Medicham -Level: 43 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe -- Psychic - -Claydol -Level: 43 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe -- Skill Swap -- Earthquake - -=== TRAINER_VIOLET === -Name: 千鹤 -Class: Aroma Lady -Pic: Aroma Lady -Gender: Female -Music: Female -Double Battle: No -AI: Check Bad Move - -Roselia -Level: 26 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Gloom -Level: 26 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_ROSE_2 === -Name: 弥生 -Class: Aroma Lady -Pic: Aroma Lady -Gender: Female -Music: Female -Double Battle: No -AI: Check Bad Move - -Shroomish -Level: 26 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe - -Roselia -Level: 26 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe - -=== TRAINER_ROSE_3 === -Name: 弥生 -Class: Aroma Lady -Pic: Aroma Lady -Gender: Female -Music: Female -Double Battle: No -AI: Check Bad Move - -Shroomish -Level: 28 -IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe - -Gloom -Level: 28 -IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe - -Roselia -Level: 28 -IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe - -=== TRAINER_ROSE_4 === -Name: 弥生 -Class: Aroma Lady -Pic: Aroma Lady -Gender: Female -Music: Female -Double Battle: No -AI: Check Bad Move - -Shroomish -Level: 31 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe - -Gloom -Level: 31 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe - -Roselia -Level: 31 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe - -=== TRAINER_ROSE_5 === -Name: 弥生 -Class: Aroma Lady -Pic: Aroma Lady -Gender: Female -Music: Female -Double Battle: No -AI: Check Bad Move - -Breloom -Level: 34 -IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe - -Gloom -Level: 34 -IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe - -Roselia -Level: 34 -IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe - -=== TRAINER_DUSTY_1 === -Name: 伸夫 -Class: Ruin Maniac -Pic: Ruin Maniac -Gender: Male -Music: Hiker -Double Battle: No -AI: Check Bad Move - -Sandslash -Level: 23 -IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe -- Dig -- Slash -- Sand Attack -- Poison Sting - -=== TRAINER_CHIP === -Name: 圭一 -Class: Ruin Maniac -Pic: Ruin Maniac -Gender: Male -Music: Hiker -Double Battle: No -AI: Check Bad Move - -Baltoy -Level: 27 -IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe -- Psybeam -- Self Destruct -- Sandstorm -- Ancient Power - -Sandshrew -Level: 27 -IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe -- Dig -- Slash -- Sand Attack -- Poison Sting - -Sandslash -Level: 27 -IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe -- Dig -- Slash -- Sand Attack -- Poison Sting - -=== TRAINER_FOSTER === -Name: 秋人 -Class: Ruin Maniac -Pic: Ruin Maniac -Gender: Male -Music: Hiker -Double Battle: No -AI: Check Bad Move - -Sandshrew -Level: 25 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe -- Dig -- Slash -- Sand Attack -- Poison Sting - -Sandslash -Level: 25 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe -- Dig -- Slash -- Sand Attack -- Poison Sting - -=== TRAINER_DUSTY_2 === -Name: 伸夫 -Class: Ruin Maniac -Pic: Ruin Maniac -Gender: Male -Music: Hiker -Double Battle: No -AI: Check Bad Move - -Sandslash -Level: 27 -IVs: 7 HP / 7 Atk / 7 Def / 7 SpA / 7 SpD / 7 Spe -- Dig -- Slash -- Sand Attack -- Poison Sting - -=== TRAINER_DUSTY_3 === -Name: 伸夫 -Class: Ruin Maniac -Pic: Ruin Maniac -Gender: Male -Music: Hiker -Double Battle: No -AI: Check Bad Move - -Sandslash -Level: 30 -IVs: 8 HP / 8 Atk / 8 Def / 8 SpA / 8 SpD / 8 Spe -- Dig -- Slash -- Sand Attack -- Poison Sting - -=== TRAINER_DUSTY_4 === -Name: 伸夫 -Class: Ruin Maniac -Pic: Ruin Maniac -Gender: Male -Music: Hiker -Double Battle: No -AI: Check Bad Move - -Sandslash -Level: 33 -IVs: 9 HP / 9 Atk / 9 Def / 9 SpA / 9 SpD / 9 Spe -- Dig -- Slash -- Sand Attack -- Poison Sting - -=== TRAINER_DUSTY_5 === -Name: 伸夫 -Class: Ruin Maniac -Pic: Ruin Maniac -Gender: Male -Music: Hiker -Double Battle: No -AI: Check Bad Move - -Sandslash -Level: 36 -IVs: 10 HP / 10 Atk / 10 Def / 10 SpA / 10 SpD / 10 Spe -- Dig -- Slash -- Sand Attack -- Poison Sting - -=== TRAINER_GABBY_AND_TY_1 === -Name: 玛莉和达伊 -Class: Interviewer -Pic: Interviewer -Gender: Male -Music: Interviewer -Double Battle: Yes -AI: Check Bad Move - -Magnemite -Level: 17 -IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe - -Whismur -Level: 17 -IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe - -=== TRAINER_GABBY_AND_TY_2 === -Name: 玛莉和达伊 -Class: Interviewer -Pic: Interviewer -Gender: Male -Music: Interviewer -Double Battle: Yes -AI: Check Bad Move - -Magnemite -Level: 27 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -Loudred -Level: 27 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -=== TRAINER_GABBY_AND_TY_3 === -Name: 玛莉和达伊 -Class: Interviewer -Pic: Interviewer -Gender: Male -Music: Interviewer -Double Battle: Yes -AI: Check Bad Move - -Magneton -Level: 30 -IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe - -Loudred -Level: 30 -IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe - -=== TRAINER_GABBY_AND_TY_4 === -Name: 玛莉和达伊 -Class: Interviewer -Pic: Interviewer -Gender: Male -Music: Interviewer -Double Battle: Yes -AI: Check Bad Move - -Magneton -Level: 33 -IVs: 24 HP / 24 Atk / 24 Def / 24 SpA / 24 SpD / 24 Spe - -Loudred -Level: 33 -IVs: 24 HP / 24 Atk / 24 Def / 24 SpA / 24 SpD / 24 Spe - -=== TRAINER_GABBY_AND_TY_5 === -Name: 玛莉和达伊 -Class: Interviewer -Pic: Interviewer -Gender: Male -Music: Interviewer -Double Battle: Yes -AI: Check Bad Move - -Magneton -Level: 36 -IVs: 30 HP / 30 Atk / 30 Def / 30 SpA / 30 SpD / 30 Spe - -Loudred -Level: 36 -IVs: 30 HP / 30 Atk / 30 Def / 30 SpA / 30 SpD / 30 Spe - -=== TRAINER_GABBY_AND_TY_6 === -Name: 玛莉和达伊 -Class: Interviewer -Pic: Interviewer -Gender: Male -Music: Interviewer -Double Battle: Yes -AI: Check Bad Move - -Magneton -Level: 39 -IVs: 30 HP / 30 Atk / 30 Def / 30 SpA / 30 SpD / 30 Spe -- Sonic Boom -- Thunder Wave -- Metal Sound -- Thunderbolt - -Exploud -Level: 39 -IVs: 30 HP / 30 Atk / 30 Def / 30 SpA / 30 SpD / 30 Spe -- Astonish -- Stomp -- Supersonic -- Hyper Voice - -=== TRAINER_LOLA_1 === -Name: 亚由美 -Class: Tuber F -Pic: Tuber F -Gender: Female -Music: Girl -Double Battle: No -AI: Check Bad Move - -Azurill -Level: 12 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe - -Azurill -Level: 12 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe - -=== TRAINER_AUSTINA === -Name: 博美 -Class: Tuber F -Pic: Tuber F -Gender: Female -Music: Girl -Double Battle: No -AI: Check Bad Move - -Marill -Level: 26 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_GWEN === -Name: 小望 -Class: Tuber F -Pic: Tuber F -Gender: Female -Music: Girl -Double Battle: No -AI: Check Bad Move - -Marill -Level: 26 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_LOLA_2 === -Name: 亚由美 -Class: Tuber F -Pic: Tuber F -Gender: Female -Music: Girl -Double Battle: No -AI: Check Bad Move - -Marill -Level: 26 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe - -Marill -Level: 26 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe - -=== TRAINER_LOLA_3 === -Name: 亚由美 -Class: Tuber F -Pic: Tuber F -Gender: Female -Music: Girl -Double Battle: No -AI: Check Bad Move - -Marill -Level: 29 -IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe - -Marill -Level: 29 -IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe - -=== TRAINER_LOLA_4 === -Name: 亚由美 -Class: Tuber F -Pic: Tuber F -Gender: Female -Music: Girl -Double Battle: No -AI: Check Bad Move - -Marill -Level: 32 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe - -Marill -Level: 32 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe - -=== TRAINER_LOLA_5 === -Name: 亚由美 -Class: Tuber F -Pic: Tuber F -Gender: Female -Music: Girl -Double Battle: No -AI: Check Bad Move - -Azumarill -Level: 35 -IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe - -Azumarill -Level: 35 -IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe - -=== TRAINER_RICKY_1 === -Name: 裕太 -Class: Tuber M -Pic: Tuber M -Gender: Male -Music: Girl -Double Battle: No -AI: Check Bad Move - -Zigzagoon -Level: 13 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe -- Sand Attack -- Headbutt -- Tail Whip -- Surf - -=== TRAINER_SIMON === -Name: 安信 -Class: Tuber M -Pic: Tuber M -Gender: Male -Music: Girl -Double Battle: No -AI: Check Bad Move - -Azurill -Level: 12 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Marill -Level: 12 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_CHARLIE === -Name: 学武 -Class: Tuber M -Pic: Tuber M -Gender: Male -Music: Girl -Double Battle: No -AI: Check Bad Move - -Marill -Level: 26 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_RICKY_2 === -Name: 裕太 -Class: Tuber M -Pic: Tuber M -Gender: Male -Music: Girl -Double Battle: No -AI: Check Bad Move - -Linoone -Level: 27 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe -- Sand Attack -- Pin Missile -- Tail Whip -- Surf - -=== TRAINER_RICKY_3 === -Name: 裕太 -Class: Tuber M -Pic: Tuber M -Gender: Male -Music: Girl -Double Battle: No -AI: Check Bad Move - -Linoone -Level: 30 -IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe -- Sand Attack -- Pin Missile -- Tail Whip -- Surf - -=== TRAINER_RICKY_4 === -Name: 裕太 -Class: Tuber M -Pic: Tuber M -Gender: Male -Music: Girl -Double Battle: No -AI: Check Bad Move - -Linoone -Level: 33 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe -- Sand Attack -- Pin Missile -- Tail Whip -- Surf - -=== TRAINER_RICKY_5 === -Name: 裕太 -Class: Tuber M -Pic: Tuber M -Gender: Male -Music: Girl -Double Battle: No -AI: Check Bad Move - -Linoone -Level: 36 -IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe -- Sand Attack -- Pin Missile -- Tail Whip -- Surf - -=== TRAINER_RANDALL === -Name: 俊树 -Class: Cooltrainer -Pic: Cooltrainer M -Gender: Male -Music: Cool -Items: Hyper Potion -Double Battle: No -AI: Basic Trainer - -Swellow -Level: 26 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Quick Attack -- Agility -- Wing Attack - -=== TRAINER_PARKER === -Name: 秀树 -Class: Cooltrainer -Pic: Cooltrainer M -Gender: Male -Music: Cool -Items: Hyper Potion -Double Battle: No -AI: Basic Trainer - -Spinda -Level: 26 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Teeter Dance -- Dizzy Punch -- Focus Punch - -=== TRAINER_GEORGE === -Name: 数马 -Class: Cooltrainer -Pic: Cooltrainer M -Gender: Male -Music: Cool -Items: Hyper Potion -Double Battle: No -AI: Basic Trainer - -Slakoth @ Sitrus Berry -Level: 26 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Slack Off -- Counter -- Shadow Ball - -=== TRAINER_BERKE === -Name: 直树 -Class: Cooltrainer -Pic: Cooltrainer M -Gender: Male -Music: Cool -Items: Hyper Potion -Double Battle: No -AI: Basic Trainer - -Vigoroth -Level: 26 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Focus Energy -- Slash - -=== TRAINER_BRAXTON === -Name: 义雄 -Class: Cooltrainer -Pic: Cooltrainer M -Gender: Male -Music: Cool -Items: Hyper Potion -Double Battle: No -AI: Basic Trainer - -Swellow -Level: 28 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe -- Focus Energy -- Quick Attack -- Wing Attack -- Endeavor - -Trapinch -Level: 28 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe -- Bite -- Dig -- Feint Attack -- Sand Tomb - -Wailmer -Level: 28 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe -- Rollout -- Whirlpool -- Astonish -- Water Pulse - -Magneton -Level: 28 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe -- Thunderbolt -- Supersonic -- Thunder Wave -- Sonic Boom - -Shiftry -Level: 28 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe -- Giga Drain -- Feint Attack -- Double Team -- Swagger - -=== TRAINER_VINCENT === -Name: 祐翔 -Class: Cooltrainer -Pic: Cooltrainer M -Gender: Male -Music: Cool -Items: Full Restore -Double Battle: No -AI: Basic Trainer - -Sableye -Level: 44 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -Medicham -Level: 44 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -Sharpedo -Level: 44 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -=== TRAINER_LEROY === -Name: 诚 -Class: Cooltrainer -Pic: Cooltrainer M -Gender: Male -Music: Cool -Items: Full Restore -Double Battle: No -AI: Basic Trainer - -Mawile -Level: 46 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -Starmie -Level: 46 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -=== TRAINER_WILTON_1 === -Name: 裕介 -Class: Cooltrainer -Pic: Cooltrainer M -Gender: Male -Music: Cool -Items: Super Potion -Double Battle: No -AI: Basic Trainer - -Electrike -Level: 17 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -Wailmer -Level: 17 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -Makuhita -Level: 17 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -=== TRAINER_EDGAR === -Name: 光辉 -Class: Cooltrainer -Pic: Cooltrainer M -Gender: Male -Music: Cool -Items: Full Restore -Double Battle: No -AI: Basic Trainer - -Cacturne -Level: 43 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -Pelipper -Level: 43 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -=== TRAINER_ALBERT === -Name: 胜 -Class: Cooltrainer -Pic: Cooltrainer M -Gender: Male -Music: Cool -Items: Full Restore -Double Battle: No -AI: Basic Trainer - -Magneton -Level: 43 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -Muk -Level: 43 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -=== TRAINER_SAMUEL === -Name: 拓也 -Class: Cooltrainer -Pic: Cooltrainer M -Gender: Male -Music: Cool -Items: Full Restore -Double Battle: No -AI: Basic Trainer - -Swellow -Level: 42 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -Mawile -Level: 42 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -Kadabra -Level: 42 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -=== TRAINER_VITO === -Name: 良平 -Class: Cooltrainer -Pic: Cooltrainer M -Gender: Male -Music: Cool -Items: Full Restore -Double Battle: No -AI: Basic Trainer - -Dodrio -Level: 42 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -Kadabra -Level: 42 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -Electrode -Level: 42 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -Shiftry -Level: 42 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -=== TRAINER_OWEN === -Name: 翔 -Class: Cooltrainer -Pic: Cooltrainer M -Gender: Male -Music: Cool -Items: Full Restore -Double Battle: No -AI: Basic Trainer - -Kecleon -Level: 42 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -Graveler -Level: 42 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -Wailord -Level: 42 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -=== TRAINER_WILTON_2 === -Name: 裕介 -Class: Cooltrainer -Pic: Cooltrainer M -Gender: Male -Music: Cool -Items: Hyper Potion -Double Battle: No -AI: Basic Trainer - -Electrike -Level: 26 -IVs: 13 HP / 13 Atk / 13 Def / 13 SpA / 13 SpD / 13 Spe - -Wailmer -Level: 26 -IVs: 13 HP / 13 Atk / 13 Def / 13 SpA / 13 SpD / 13 Spe - -Makuhita -Level: 26 -IVs: 13 HP / 13 Atk / 13 Def / 13 SpA / 13 SpD / 13 Spe - -=== TRAINER_WILTON_3 === -Name: 裕介 -Class: Cooltrainer -Pic: Cooltrainer M -Gender: Male -Music: Cool -Items: Hyper Potion -Double Battle: No -AI: Basic Trainer - -Manectric -Level: 29 -IVs: 14 HP / 14 Atk / 14 Def / 14 SpA / 14 SpD / 14 Spe - -Wailmer -Level: 29 -IVs: 14 HP / 14 Atk / 14 Def / 14 SpA / 14 SpD / 14 Spe - -Makuhita -Level: 29 -IVs: 14 HP / 14 Atk / 14 Def / 14 SpA / 14 SpD / 14 Spe - -=== TRAINER_WILTON_4 === -Name: 裕介 -Class: Cooltrainer -Pic: Cooltrainer M -Gender: Male -Music: Cool -Items: Full Restore -Double Battle: No -AI: Basic Trainer - -Manectric -Level: 32 -IVs: 15 HP / 15 Atk / 15 Def / 15 SpA / 15 SpD / 15 Spe - -Wailmer -Level: 32 -IVs: 15 HP / 15 Atk / 15 Def / 15 SpA / 15 SpD / 15 Spe - -Makuhita -Level: 32 -IVs: 15 HP / 15 Atk / 15 Def / 15 SpA / 15 SpD / 15 Spe - -=== TRAINER_WILTON_5 === -Name: 裕介 -Class: Cooltrainer -Pic: Cooltrainer M -Gender: Male -Music: Cool -Items: Full Restore -Double Battle: No -AI: Basic Trainer - -Manectric -Level: 35 -IVs: 17 HP / 17 Atk / 17 Def / 17 SpA / 17 SpD / 17 Spe - -Wailmer -Level: 35 -IVs: 17 HP / 17 Atk / 17 Def / 17 SpA / 17 SpD / 17 Spe - -Hariyama -Level: 35 -IVs: 17 HP / 17 Atk / 17 Def / 17 SpA / 17 SpD / 17 Spe - -=== TRAINER_WARREN === -Name: 礼司 -Class: Cooltrainer -Pic: Cooltrainer M -Gender: Male -Music: Cool -Items: Full Restore -Double Battle: No -AI: Basic Trainer - -Graveler -Level: 33 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -Ludicolo -Level: 33 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -=== TRAINER_MARY === -Name: 绫香 -Class: Cooltrainer -Pic: Cooltrainer F -Gender: Female -Music: Cool -Items: Hyper Potion -Double Battle: No -AI: Basic Trainer - -Delcatty -Level: 26 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Feint Attack -- Shock Wave - -=== TRAINER_ALEXIA === -Name: 海晴 -Class: Cooltrainer -Pic: Cooltrainer F -Gender: Female -Music: Cool -Items: Hyper Potion -Double Battle: No -AI: Basic Trainer - -Wigglytuff -Level: 26 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Defense Curl -- Double Edge -- Shadow Ball - -=== TRAINER_JODY === -Name: 沙织 -Class: Cooltrainer -Pic: Cooltrainer F -Gender: Female -Music: Cool -Items: Hyper Potion -Double Battle: No -AI: Check Bad Move / Try To Faint / Force Setup First Turn - -Zangoose -Level: 26 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Swords Dance -- Slash - -=== TRAINER_WENDY === -Name: 刹那 -Class: Cooltrainer -Pic: Cooltrainer F -Gender: Female -Music: Cool -Items: Full Restore -Double Battle: No -AI: Check Bad Move / Try To Faint / Force Setup First Turn - -Mawile -Level: 29 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe -- Baton Pass -- Feint Attack -- Fake Tears -- Bite - -Roselia -Level: 29 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe -- Mega Drain -- Magical Leaf -- Grass Whistle -- Leech Seed - -Pelipper -Level: 29 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe -- Fly -- Water Gun -- Mist -- Protect - -=== TRAINER_KEIRA === -Name: 安娜 -Class: Cooltrainer -Pic: Cooltrainer F -Gender: Female -Music: Cool -Items: Full Restore -Double Battle: No -AI: Check Bad Move / Try To Faint / Force Setup First Turn - -Lairon -Level: 45 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -Manectric -Level: 45 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -=== TRAINER_BROOKE_1 === -Name: 真理亚 -Class: Cooltrainer -Pic: Cooltrainer F -Gender: Female -Music: Cool -Items: Super Potion -Double Battle: No -AI: Basic Trainer - -Wingull -Level: 17 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -Numel -Level: 17 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -Roselia -Level: 17 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -=== TRAINER_JENNIFER === -Name: 弥生子 -Class: Cooltrainer -Pic: Cooltrainer F -Gender: Female -Music: Cool -Items: Full Restore -Double Battle: No -AI: Basic Trainer - -Sableye -Level: 30 -IVs: 24 HP / 24 Atk / 24 Def / 24 SpA / 24 SpD / 24 Spe - -=== TRAINER_HOPE === -Name: 爱理 -Class: Cooltrainer -Pic: Cooltrainer F -Gender: Female -Music: Cool -Items: Full Restore -Double Battle: No -AI: Basic Trainer - -Roselia -Level: 45 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -=== TRAINER_SHANNON === -Name: 绘理子 -Class: Cooltrainer -Pic: Cooltrainer F -Gender: Female -Music: Cool -Items: Full Restore -Double Battle: No -AI: Basic Trainer - -Claydol -Level: 45 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -=== TRAINER_MICHELLE === -Name: 和美 -Class: Cooltrainer -Pic: Cooltrainer F -Gender: Female -Music: Cool -Items: Full Restore -Double Battle: No -AI: Basic Trainer - -Torkoal -Level: 42 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -Medicham -Level: 42 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -Ludicolo -Level: 42 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -=== TRAINER_CAROLINE === -Name: 绯月 -Class: Cooltrainer -Pic: Cooltrainer F -Gender: Female -Music: Cool -Items: Full Restore -Double Battle: No -AI: Basic Trainer - -Skarmory -Level: 43 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -Sableye -Level: 43 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -=== TRAINER_JULIE === -Name: 琴美 -Class: Cooltrainer -Pic: Cooltrainer F -Gender: Female -Music: Cool -Items: Full Restore -Double Battle: No -AI: Basic Trainer - -Sandslash -Level: 42 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -Ninetales -Level: 42 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -Tropius -Level: 42 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -=== TRAINER_BROOKE_2 === -Name: 真理亚 -Class: Cooltrainer -Pic: Cooltrainer F -Gender: Female -Music: Cool -Items: Hyper Potion -Double Battle: No -AI: Basic Trainer - -Wingull -Level: 26 -IVs: 13 HP / 13 Atk / 13 Def / 13 SpA / 13 SpD / 13 Spe - -Numel -Level: 26 -IVs: 13 HP / 13 Atk / 13 Def / 13 SpA / 13 SpD / 13 Spe - -Roselia -Level: 26 -IVs: 13 HP / 13 Atk / 13 Def / 13 SpA / 13 SpD / 13 Spe - -=== TRAINER_BROOKE_3 === -Name: 真理亚 -Class: Cooltrainer -Pic: Cooltrainer F -Gender: Female -Music: Cool -Items: Hyper Potion -Double Battle: No -AI: Basic Trainer - -Pelipper -Level: 29 -IVs: 14 HP / 14 Atk / 14 Def / 14 SpA / 14 SpD / 14 Spe - -Numel -Level: 29 -IVs: 14 HP / 14 Atk / 14 Def / 14 SpA / 14 SpD / 14 Spe - -Roselia -Level: 29 -IVs: 14 HP / 14 Atk / 14 Def / 14 SpA / 14 SpD / 14 Spe - -=== TRAINER_BROOKE_4 === -Name: 真理亚 -Class: Cooltrainer -Pic: Cooltrainer F -Gender: Female -Music: Cool -Items: Full Restore -Double Battle: No -AI: Basic Trainer - -Pelipper -Level: 32 -IVs: 15 HP / 15 Atk / 15 Def / 15 SpA / 15 SpD / 15 Spe - -Numel -Level: 32 -IVs: 15 HP / 15 Atk / 15 Def / 15 SpA / 15 SpD / 15 Spe - -Roselia -Level: 32 -IVs: 15 HP / 15 Atk / 15 Def / 15 SpA / 15 SpD / 15 Spe - -=== TRAINER_BROOKE_5 === -Name: 真理亚 -Class: Cooltrainer -Pic: Cooltrainer F -Gender: Female -Music: Cool -Items: Full Restore -Double Battle: No -AI: Basic Trainer - -Pelipper -Level: 34 -IVs: 17 HP / 17 Atk / 17 Def / 17 SpA / 17 SpD / 17 Spe - -Camerupt -Level: 34 -IVs: 17 HP / 17 Atk / 17 Def / 17 SpA / 17 SpD / 17 Spe - -Roselia -Level: 34 -IVs: 17 HP / 17 Atk / 17 Def / 17 SpA / 17 SpD / 17 Spe - -=== TRAINER_PATRICIA === -Name: 采音 -Class: Hex Maniac -Pic: Hex Maniac -Gender: Female -Music: Suspicious -Double Battle: No -AI: Check Bad Move - -Banette -Level: 41 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Lunatone -Level: 41 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_KINDRA === -Name: 祥子 -Class: Hex Maniac -Pic: Hex Maniac -Gender: Female -Music: Suspicious -Double Battle: No -AI: Check Bad Move - -Duskull -Level: 30 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Shuppet -Level: 30 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_TAMMY === -Name: 命 -Class: Hex Maniac -Pic: Hex Maniac -Gender: Female -Music: Suspicious -Double Battle: No -AI: Check Bad Move - -Duskull -Level: 29 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Shuppet -Level: 29 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_VALERIE_1 === -Name: 穗乃佳 -Class: Hex Maniac -Pic: Hex Maniac -Gender: Female -Music: Suspicious -Double Battle: No -AI: Check Bad Move - -Sableye -Level: 32 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_TASHA === -Name: 穗多琉 -Class: Hex Maniac -Pic: Hex Maniac -Gender: Female -Music: Suspicious -Double Battle: No -AI: Check Bad Move - -Shuppet -Level: 32 -IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe - -=== TRAINER_VALERIE_2 === -Name: 穗乃佳 -Class: Hex Maniac -Pic: Hex Maniac -Gender: Female -Music: Suspicious -Double Battle: No -AI: Check Bad Move - -Sableye -Level: 31 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe - -Spoink -Level: 31 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe - -=== TRAINER_VALERIE_3 === -Name: 穗乃佳 -Class: Hex Maniac -Pic: Hex Maniac -Gender: Female -Music: Suspicious -Double Battle: No -AI: Check Bad Move - -Spoink -Level: 35 -IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe - -Sableye -Level: 35 -IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe - -=== TRAINER_VALERIE_4 === -Name: 穗乃佳 -Class: Hex Maniac -Pic: Hex Maniac -Gender: Female -Music: Suspicious -Double Battle: No -AI: Check Bad Move - -Spoink -Level: 40 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe - -Sableye -Level: 40 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe - -=== TRAINER_VALERIE_5 === -Name: 穗乃佳 -Class: Hex Maniac -Pic: Hex Maniac -Gender: Female -Music: Suspicious -Double Battle: No -AI: Check Bad Move - -Duskull -Level: 42 -IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe - -Sableye -Level: 42 -IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe - -Grumpig -Level: 42 -IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe - -=== TRAINER_CINDY_1 === -Name: 丽华 -Class: Lady -Pic: Lady -Gender: Female -Music: Female -Items: Full Restore -Double Battle: No -AI: Check Bad Move - -Zigzagoon @ Nugget -Level: 7 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_DAPHNE === -Name: 咏歌 -Class: Lady -Pic: Lady -Gender: Female -Music: Female -Items: Full Restore -Double Battle: No -AI: Check Bad Move - -Luvdisc @ Nugget -Level: 39 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe -- Attract -- Sweet Kiss -- Flail -- Water Pulse - -Luvdisc @ Nugget -Level: 39 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe -- Attract -- Safeguard -- Take Down -- Water Pulse - -=== TRAINER_GRUNT_SPACE_CENTER_2 === -Name: 手下 -Class: Team Magma -Pic: Magma Grunt M -Gender: Male -Music: Magma -Double Battle: No -AI: Check Bad Move - -Mightyena -Level: 26 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Mightyena -Level: 28 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Numel -Level: 30 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_CINDY_2 === -Name: 丽华 -Class: Lady -Pic: Lady -Gender: Female -Music: Female -Items: Full Restore -Double Battle: No -AI: Check Bad Move - -Zigzagoon @ Nugget -Level: 11 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe -- Tackle -- Tail Whip - -=== TRAINER_BRIANNA === -Name: 诗织 -Class: Lady -Pic: Lady -Gender: Female -Music: Female -Items: Full Restore -Double Battle: No -AI: Check Bad Move - -Seaking @ Nugget -Level: 40 -IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe - -=== TRAINER_NAOMI === -Name: 小百合 -Class: Lady -Pic: Lady -Gender: Female -Music: Female -Items: Full Restore -Double Battle: No -AI: Check Bad Move - -Roselia @ Nugget -Level: 45 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -=== TRAINER_CINDY_3 === -Name: 丽华 -Class: Lady -Pic: Lady -Gender: Female -Music: Female -Items: Full Restore -Double Battle: No -AI: Check Bad Move - -Linoone @ Nugget -Level: 27 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe - -=== TRAINER_CINDY_4 === -Name: 丽华 -Class: Lady -Pic: Lady -Gender: Female -Music: Female -Items: Full Restore -Double Battle: No -AI: Check Bad Move - -Linoone @ Nugget -Level: 30 -IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe - -=== TRAINER_CINDY_5 === -Name: 丽华 -Class: Lady -Pic: Lady -Gender: Female -Music: Female -Items: Full Restore -Double Battle: No -AI: Check Bad Move - -Linoone @ Nugget -Level: 33 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe - -=== TRAINER_CINDY_6 === -Name: 丽华 -Class: Lady -Pic: Lady -Gender: Female -Music: Female -Items: Full Restore -Double Battle: No -AI: Check Bad Move - -Linoone @ Nugget -Level: 36 -IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe -- Fury Swipes -- Mud Sport -- Odor Sleuth -- Sand Attack - -=== TRAINER_MELISSA === -Name: 惠美 -Class: Beauty -Pic: Beauty -Gender: Female -Music: Female -Double Battle: No -AI: Check Bad Move - -Marill -Level: 21 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_SHEILA === -Name: 国美 -Class: Beauty -Pic: Beauty -Gender: Female -Music: Female -Double Battle: No -AI: Check Bad Move - -Shroomish -Level: 21 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_SHIRLEY === -Name: 朝美 -Class: Beauty -Pic: Beauty -Gender: Female -Music: Female -Double Battle: No -AI: Check Bad Move - -Numel -Level: 21 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_JESSICA_1 === -Name: 依子 -Class: Beauty -Pic: Beauty -Gender: Female -Music: Female -Double Battle: No -AI: Check Bad Move - -Kecleon -Level: 29 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe -- Bind -- Lick -- Fury Swipes -- Feint Attack - -Seviper -Level: 29 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe -- Poison Tail -- Screech -- Glare -- Crunch - -=== TRAINER_CONNIE === -Name: 眉子 -Class: Beauty -Pic: Beauty -Gender: Female -Music: Female -Double Battle: No -AI: Check Bad Move - -Goldeen -Level: 40 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -=== TRAINER_BRIDGET === -Name: 清子 -Class: Beauty -Pic: Beauty -Gender: Female -Music: Female -Double Battle: No -AI: Check Bad Move - -Azumarill -Level: 40 -IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe - -=== TRAINER_OLIVIA === -Name: 直子 -Class: Beauty -Pic: Beauty -Gender: Female -Music: Female -Double Battle: No -AI: Check Bad Move - -Clamperl -Level: 35 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe -- Iron Defense -- Whirlpool -- Rain Dance -- Water Pulse - -Corphish -Level: 37 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe -- Taunt -- Crabhammer -- Water Pulse - -Lombre -Level: 39 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe -- Uproar -- Fury Swipes -- Fake Out -- Water Pulse - -=== TRAINER_TIFFANY === -Name: 春子 -Class: Beauty -Pic: Beauty -Gender: Female -Music: Female -Double Battle: No -AI: Check Bad Move - -Carvanha -Level: 39 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -Sharpedo -Level: 39 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -=== TRAINER_JESSICA_2 === -Name: 依子 -Class: Beauty -Pic: Beauty -Gender: Female -Music: Female -Double Battle: No -AI: Check Bad Move - -Kecleon -Level: 35 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe -- Bind -- Lick -- Fury Swipes -- Feint Attack - -Seviper -Level: 35 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe -- Poison Tail -- Screech -- Glare -- Crunch - -=== TRAINER_JESSICA_3 === -Name: 依子 -Class: Beauty -Pic: Beauty -Gender: Female -Music: Female -Double Battle: No -AI: Check Bad Move - -Kecleon -Level: 38 -IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe -- Bind -- Lick -- Fury Swipes -- Feint Attack - -Seviper -Level: 38 -IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe -- Poison Tail -- Screech -- Glare -- Crunch - -=== TRAINER_JESSICA_4 === -Name: 依子 -Class: Beauty -Pic: Beauty -Gender: Female -Music: Female -Double Battle: No -AI: Check Bad Move - -Kecleon -Level: 41 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe -- Bind -- Lick -- Fury Swipes -- Feint Attack - -Seviper -Level: 41 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe -- Poison Tail -- Screech -- Glare -- Crunch - -=== TRAINER_JESSICA_5 === -Name: 依子 -Class: Beauty -Pic: Beauty -Gender: Female -Music: Female -Double Battle: No -AI: Check Bad Move - -Kecleon -Level: 44 -IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe -- Bind -- Lick -- Fury Swipes -- Feint Attack - -Seviper -Level: 44 -IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe -- Poison Tail -- Screech -- Glare -- Crunch - -=== TRAINER_WINSTON_1 === -Name: 小贡 -Class: Rich Boy -Pic: Rich Boy -Gender: Male -Music: Rich -Items: Full Restore -Double Battle: No -AI: Check Bad Move - -Zigzagoon @ Nugget -Level: 7 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_MOLLIE === -Name: 奈江 -Class: Expert -Pic: Expert F -Gender: Female -Music: Intense -Double Battle: No -AI: Check Bad Move - -Whiscash -Level: 33 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Meditite -Level: 33 -IVs: 24 HP / 24 Atk / 24 Def / 24 SpA / 24 SpD / 24 Spe - -=== TRAINER_GARRET === -Name: 祥一 -Class: Rich Boy -Pic: Rich Boy -Gender: Male -Music: Rich -Items: Full Restore -Double Battle: No -AI: Check Bad Move - -Azumarill @ Nugget -Level: 45 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_WINSTON_2 === -Name: 小贡 -Class: Rich Boy -Pic: Rich Boy -Gender: Male -Music: Rich -Items: Full Restore -Double Battle: No -AI: Check Bad Move - -Linoone @ Nugget -Level: 27 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_WINSTON_3 === -Name: 小贡 -Class: Rich Boy -Pic: Rich Boy -Gender: Male -Music: Rich -Items: Full Restore -Double Battle: No -AI: Check Bad Move - -Linoone @ Nugget -Level: 30 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_WINSTON_4 === -Name: 小贡 -Class: Rich Boy -Pic: Rich Boy -Gender: Male -Music: Rich -Items: Full Restore -Double Battle: No -AI: Check Bad Move - -Linoone @ Nugget -Level: 33 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_WINSTON_5 === -Name: 小贡 -Class: Rich Boy -Pic: Rich Boy -Gender: Male -Music: Rich -Items: Full Restore -Double Battle: No -AI: Check Bad Move - -Linoone @ Nugget -Level: 36 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe -- Fury Swipes -- Mud Sport -- Odor Sleuth -- Sand Attack - -=== TRAINER_STEVE_1 === -Name: 俊夫 -Class: Pokemaniac -Pic: Pokemaniac -Gender: Male -Music: Suspicious -Double Battle: No -AI: Check Bad Move - -Aron -Level: 19 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_THALIA_1 === -Name: 睫 -Class: Beauty -Pic: Beauty -Gender: Female -Music: Female -Double Battle: No -AI: Check Bad Move - -Wailmer -Level: 25 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Horsea -Level: 25 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_MARK === -Name: 基文 -Class: Pokemaniac -Pic: Pokemaniac -Gender: Male -Music: Suspicious -Double Battle: No -AI: Check Bad Move - -Rhyhorn -Level: 31 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_GRUNT_MT_CHIMNEY_1 === -Name: 手下 -Class: Team Magma -Pic: Magma Grunt F -Gender: Female -Music: Magma -Double Battle: No -AI: Check Bad Move - -Numel -Level: 20 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_STEVE_2 === -Name: 俊夫 -Class: Pokemaniac -Pic: Pokemaniac -Gender: Male -Music: Suspicious -Double Battle: No -AI: Check Bad Move - -Lairon -Level: 27 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe - -=== TRAINER_STEVE_3 === -Name: 俊夫 -Class: Pokemaniac -Pic: Pokemaniac -Gender: Male -Music: Suspicious -Double Battle: No -AI: Check Bad Move - -Lairon -Level: 29 -IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe - -Rhyhorn -Level: 29 -IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe - -=== TRAINER_STEVE_4 === -Name: 俊夫 -Class: Pokemaniac -Pic: Pokemaniac -Gender: Male -Music: Suspicious -Double Battle: No -AI: Check Bad Move - -Lairon -Level: 32 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe - -Rhyhorn -Level: 32 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe - -=== TRAINER_STEVE_5 === -Name: 俊夫 -Class: Pokemaniac -Pic: Pokemaniac -Gender: Male -Music: Suspicious -Double Battle: No -AI: Check Bad Move - -Aggron -Level: 35 -IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe - -Rhydon -Level: 35 -IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe - -=== TRAINER_LUIS === -Name: 洋平 -Class: Swimmer M -Pic: Swimmer M -Gender: Male -Music: Swimmer -Double Battle: No -AI: Check Bad Move - -Carvanha -Level: 26 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_DOMINIK === -Name: 弘道 -Class: Swimmer M -Pic: Swimmer M -Gender: Male -Music: Swimmer -Double Battle: No -AI: Check Bad Move - -Tentacool -Level: 26 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_DOUGLAS === -Name: 辰夫 -Class: Swimmer M -Pic: Swimmer M -Gender: Male -Music: Swimmer -Double Battle: No -AI: Check Bad Move - -Tentacool -Level: 24 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe - -Tentacool -Level: 24 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe - -=== TRAINER_DARRIN === -Name: 照幸 -Class: Swimmer M -Pic: Swimmer M -Gender: Male -Music: Swimmer -Double Battle: No -AI: Check Bad Move - -Tentacool -Level: 24 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe - -Wingull -Level: 24 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe - -Tentacool -Level: 24 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe - -=== TRAINER_TONY_1 === -Name: 英一 -Class: Swimmer M -Pic: Swimmer M -Gender: Male -Music: Swimmer -Double Battle: No -AI: Check Bad Move - -Carvanha -Level: 26 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_JEROME === -Name: 森男 -Class: Swimmer M -Pic: Swimmer M -Gender: Male -Music: Swimmer -Double Battle: No -AI: Check Bad Move - -Tentacruel -Level: 26 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_MATTHEW === -Name: 国彦 -Class: Swimmer M -Pic: Swimmer M -Gender: Male -Music: Swimmer -Double Battle: No -AI: Check Bad Move - -Carvanha -Level: 26 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_DAVID === -Name: 健一 -Class: Swimmer M -Pic: Swimmer M -Gender: Male -Music: Swimmer -Double Battle: No -AI: Check Bad Move - -Tentacool -Level: 25 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Carvanha -Level: 25 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_SPENCER === -Name: 稔洋 -Class: Swimmer M -Pic: Swimmer M -Gender: Male -Music: Swimmer -Double Battle: No -AI: Check Bad Move - -Tentacool -Level: 33 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Wingull -Level: 33 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_ROLAND === -Name: 正稔 -Class: Swimmer M -Pic: Swimmer M -Gender: Male -Music: Swimmer -Double Battle: No -AI: Check Bad Move - -Carvanha -Level: 34 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_NOLEN === -Name: 信夫 -Class: Swimmer M -Pic: Swimmer M -Gender: Male -Music: Swimmer -Double Battle: No -AI: Check Bad Move - -Tentacruel -Level: 34 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_STAN === -Name: 圭史 -Class: Swimmer M -Pic: Swimmer M -Gender: Male -Music: Swimmer -Double Battle: No -AI: Check Bad Move - -Horsea -Level: 34 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_BARRY === -Name: 学人 -Class: Swimmer M -Pic: Swimmer M -Gender: Male -Music: Swimmer -Double Battle: No -AI: Check Bad Move - -Gyarados -Level: 34 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_DEAN === -Name: 烈日 -Class: Swimmer M -Pic: Swimmer M -Gender: Male -Music: Swimmer -Double Battle: No -AI: Check Bad Move - -Carvanha -Level: 31 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Wingull -Level: 31 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Carvanha -Level: 31 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_RODNEY === -Name: 正洋 -Class: Swimmer M -Pic: Swimmer M -Gender: Male -Music: Swimmer -Double Battle: No -AI: Check Bad Move - -Gyarados -Level: 34 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_RICHARD === -Name: 春树 -Class: Swimmer M -Pic: Swimmer M -Gender: Male -Music: Swimmer -Double Battle: No -AI: Check Bad Move - -Pelipper -Level: 34 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_HERMAN === -Name: 大辅 -Class: Swimmer M -Pic: Swimmer M -Gender: Male -Music: Swimmer -Double Battle: No -AI: Check Bad Move - -Wingull -Level: 33 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Tentacruel -Level: 33 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_SANTIAGO === -Name: 慎二 -Class: Swimmer M -Pic: Swimmer M -Gender: Male -Music: Swimmer -Double Battle: No -AI: Check Bad Move - -Tentacruel -Level: 33 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Wailmer -Level: 33 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_GILBERT === -Name: 豪 -Class: Swimmer M -Pic: Swimmer M -Gender: Male -Music: Swimmer -Double Battle: No -AI: Check Bad Move - -Sharpedo -Level: 34 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_FRANKLIN === -Name: 茂雄 -Class: Swimmer M -Pic: Swimmer M -Gender: Male -Music: Swimmer -Double Battle: No -AI: Check Bad Move - -Sealeo -Level: 34 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_KEVIN === -Name: 勉 -Class: Swimmer M -Pic: Swimmer M -Gender: Male -Music: Swimmer -Double Battle: No -AI: Check Bad Move - -Spheal -Level: 34 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_JACK === -Name: 秀典 -Class: Swimmer M -Pic: Swimmer M -Gender: Male -Music: Swimmer -Double Battle: No -AI: Check Bad Move - -Gyarados -Level: 34 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_DUDLEY === -Name: 德雄 -Class: Swimmer M -Pic: Swimmer M -Gender: Male -Music: Swimmer -Double Battle: No -AI: Check Bad Move - -Tentacool -Level: 33 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Wingull -Level: 33 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Tentacruel -Level: 33 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_CHAD === -Name: 克之 -Class: Swimmer M -Pic: Swimmer M -Gender: Male -Music: Swimmer -Double Battle: No -AI: Check Bad Move - -Tentacool -Level: 33 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Wailmer -Level: 33 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_TONY_2 === -Name: 英一 -Class: Swimmer M -Pic: Swimmer M -Gender: Male -Music: Swimmer -Double Battle: No -AI: Check Bad Move - -Sharpedo -Level: 30 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe - -=== TRAINER_TONY_3 === -Name: 英一 -Class: Swimmer M -Pic: Swimmer M -Gender: Male -Music: Swimmer -Double Battle: No -AI: Check Bad Move - -Sharpedo -Level: 33 -IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe - -=== TRAINER_TONY_4 === -Name: 英一 -Class: Swimmer M -Pic: Swimmer M -Gender: Male -Music: Swimmer -Double Battle: No -AI: Check Bad Move - -Staryu -Level: 34 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe - -Sharpedo -Level: 36 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe - -=== TRAINER_TONY_5 === -Name: 英一 -Class: Swimmer M -Pic: Swimmer M -Gender: Male -Music: Swimmer -Double Battle: No -AI: Check Bad Move - -Starmie -Level: 37 -IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe - -Sharpedo -Level: 39 -IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe - -=== TRAINER_TAKAO === -Name: 大庆 -Class: Black Belt -Pic: Black Belt -Gender: Male -Music: Intense -Double Battle: No -AI: Check Bad Move - -Machop -Level: 13 -IVs: 15 HP / 15 Atk / 15 Def / 15 SpA / 15 SpD / 15 Spe - -=== TRAINER_HITOSHI === -Name: 岩冈 -Class: Black Belt -Pic: Black Belt -Gender: Male -Music: Intense -Double Battle: No -AI: Check Bad Move - -Machop -Level: 32 -IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe - -Machoke -Level: 32 -IVs: 24 HP / 24 Atk / 24 Def / 24 SpA / 24 SpD / 24 Spe - -=== TRAINER_KIYO === -Name: 拓马 -Class: Black Belt -Pic: Black Belt -Gender: Male -Music: Intense -Double Battle: No -AI: Check Bad Move - -Hariyama -Level: 34 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -=== TRAINER_KOICHI === -Name: 武德 -Class: Black Belt -Pic: Black Belt -Gender: Male -Music: Intense -Double Battle: No -AI: Check Bad Move - -Machop -Level: 24 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -Machoke -Level: 28 -IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe - -=== TRAINER_NOB_1 === -Name: 吾郎 -Class: Black Belt -Pic: Black Belt -Gender: Male -Music: Intense -Double Battle: No -AI: Check Bad Move - -Machop -Level: 19 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -=== TRAINER_NOB_2 === -Name: 吾郎 -Class: Black Belt -Pic: Black Belt -Gender: Male -Music: Intense -Double Battle: No -AI: Check Bad Move - -Machoke -Level: 27 -IVs: 13 HP / 13 Atk / 13 Def / 13 SpA / 13 SpD / 13 Spe - -=== TRAINER_NOB_3 === -Name: 吾郎 -Class: Black Belt -Pic: Black Belt -Gender: Male -Music: Intense -Double Battle: No -AI: Check Bad Move - -Machop -Level: 29 -IVs: 14 HP / 14 Atk / 14 Def / 14 SpA / 14 SpD / 14 Spe - -Machoke -Level: 29 -IVs: 14 HP / 14 Atk / 14 Def / 14 SpA / 14 SpD / 14 Spe - -=== TRAINER_NOB_4 === -Name: 吾郎 -Class: Black Belt -Pic: Black Belt -Gender: Male -Music: Intense -Double Battle: No -AI: Check Bad Move - -Machop -Level: 31 -IVs: 15 HP / 15 Atk / 15 Def / 15 SpA / 15 SpD / 15 Spe - -Machoke -Level: 31 -IVs: 15 HP / 15 Atk / 15 Def / 15 SpA / 15 SpD / 15 Spe - -Machoke -Level: 31 -IVs: 15 HP / 15 Atk / 15 Def / 15 SpA / 15 SpD / 15 Spe - -=== TRAINER_NOB_5 === -Name: 吾郎 -Class: Black Belt -Pic: Black Belt -Gender: Male -Music: Intense -Double Battle: No -AI: Check Bad Move - -Machop -Level: 33 -IVs: 17 HP / 17 Atk / 17 Def / 17 SpA / 17 SpD / 17 Spe - -Machoke -Level: 33 -IVs: 17 HP / 17 Atk / 17 Def / 17 SpA / 17 SpD / 17 Spe - -Machoke -Level: 33 -IVs: 17 HP / 17 Atk / 17 Def / 17 SpA / 17 SpD / 17 Spe - -Machamp @ Black Belt -Level: 33 -IVs: 17 HP / 17 Atk / 17 Def / 17 SpA / 17 SpD / 17 Spe - -=== TRAINER_YUJI === -Name: 和嗣 -Class: Black Belt -Pic: Black Belt -Gender: Male -Music: Intense -Double Battle: No -AI: Check Bad Move - -Makuhita -Level: 26 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -Machoke -Level: 26 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -=== TRAINER_DAISUKE === -Name: 正 -Class: Black Belt -Pic: Black Belt -Gender: Male -Music: Intense -Double Battle: No -AI: Check Bad Move - -Machop -Level: 19 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -=== TRAINER_ATSUSHI === -Name: 哲久 -Class: Black Belt -Pic: Black Belt -Gender: Male -Music: Intense -Double Battle: No -AI: Check Bad Move - -Hariyama -Level: 32 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -=== TRAINER_KIRK === -Name: 乔治 -Class: Guitarist -Pic: Guitarist -Gender: Male -Music: Intense -Double Battle: No -AI: Check Bad Move - -Electrike -Level: 17 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe -- Quick Attack -- Thunder Wave -- Spark -- Leer - -Voltorb -Level: 17 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe -- Charge -- Shock Wave -- Screech - -=== TRAINER_GRUNT_AQUA_HIDEOUT_7 === -Name: 手下 -Class: Team Aqua -Pic: Aqua Grunt F -Gender: Female -Music: Aqua -Double Battle: No -AI: Check Bad Move - -Poochyena -Level: 31 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Zubat -Level: 31 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_GRUNT_AQUA_HIDEOUT_8 === -Name: 手下 -Class: Team Aqua -Pic: Aqua Grunt M -Gender: Male -Music: Aqua -Double Battle: No -AI: Check Bad Move - -Carvanha -Level: 32 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_SHAWN === -Name: 麦克 -Class: Guitarist -Pic: Guitarist -Gender: Male -Music: Intense -Double Battle: No -AI: Check Bad Move - -Voltorb -Level: 17 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -Magnemite -Level: 17 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -=== TRAINER_FERNANDO_1 === -Name: 乔 -Class: Guitarist -Pic: Guitarist -Gender: Male -Music: Intense -Double Battle: No -AI: Check Bad Move - -Electrike -Level: 30 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Loudred -Level: 30 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_DALTON_1 === -Name: 泰瑞 -Class: Guitarist -Pic: Guitarist -Gender: Male -Music: Intense -Double Battle: No -AI: Check Bad Move - -Magnemite -Level: 15 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Whismur -Level: 15 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_DALTON_2 === -Name: 泰瑞 -Class: Guitarist -Pic: Guitarist -Gender: Male -Music: Intense -Double Battle: No -AI: Check Bad Move - -Magnemite -Level: 25 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe - -Whismur -Level: 25 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe - -Magnemite -Level: 25 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe - -=== TRAINER_DALTON_3 === -Name: 泰瑞 -Class: Guitarist -Pic: Guitarist -Gender: Male -Music: Intense -Double Battle: No -AI: Check Bad Move - -Magnemite -Level: 28 -IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe - -Loudred -Level: 28 -IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe - -Magnemite -Level: 28 -IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe - -=== TRAINER_DALTON_4 === -Name: 泰瑞 -Class: Guitarist -Pic: Guitarist -Gender: Male -Music: Intense -Double Battle: No -AI: Check Bad Move - -Magneton -Level: 31 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe - -Loudred -Level: 31 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe - -Magneton -Level: 31 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe - -=== TRAINER_DALTON_5 === -Name: 泰瑞 -Class: Guitarist -Pic: Guitarist -Gender: Male -Music: Intense -Double Battle: No -AI: Check Bad Move - -Magneton -Level: 34 -IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe - -Exploud -Level: 34 -IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe - -Magneton -Level: 34 -IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe - -=== TRAINER_COLE === -Name: 小明 -Class: Kindler -Pic: Kindler -Gender: Male -Music: Hiker -Double Battle: No -AI: Check Bad Move - -Numel -Level: 23 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -=== TRAINER_JEFF === -Name: 光太 -Class: Kindler -Pic: Kindler -Gender: Male -Music: Hiker -Double Battle: No -AI: Check Bad Move - -Slugma -Level: 22 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -Slugma -Level: 22 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -=== TRAINER_AXLE === -Name: 阿保 -Class: Kindler -Pic: Kindler -Gender: Male -Music: Hiker -Double Battle: No -AI: Check Bad Move - -Numel -Level: 23 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -=== TRAINER_JACE === -Name: 顺次 -Class: Kindler -Pic: Kindler -Gender: Male -Music: Hiker -Double Battle: No -AI: Check Bad Move - -Slugma -Level: 23 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -=== TRAINER_KEEGAN === -Name: 晴隆 -Class: Kindler -Pic: Kindler -Gender: Male -Music: Hiker -Double Battle: No -AI: Check Bad Move - -Slugma -Level: 23 -IVs: 14 HP / 14 Atk / 14 Def / 14 SpA / 14 SpD / 14 Spe - -=== TRAINER_BERNIE_1 === -Name: 信彦 -Class: Kindler -Pic: Kindler -Gender: Male -Music: Hiker -Double Battle: No -AI: Check Bad Move - -Slugma -Level: 18 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Wingull -Level: 18 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_BERNIE_2 === -Name: 信彦 -Class: Kindler -Pic: Kindler -Gender: Male -Music: Hiker -Double Battle: No -AI: Check Bad Move - -Slugma -Level: 26 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe - -Wingull -Level: 26 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe - -=== TRAINER_BERNIE_3 === -Name: 信彦 -Class: Kindler -Pic: Kindler -Gender: Male -Music: Hiker -Double Battle: No -AI: Check Bad Move - -Slugma -Level: 29 -IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe - -Pelipper -Level: 29 -IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe - -=== TRAINER_BERNIE_4 === -Name: 信彦 -Class: Kindler -Pic: Kindler -Gender: Male -Music: Hiker -Double Battle: No -AI: Check Bad Move - -Slugma -Level: 32 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe - -Pelipper -Level: 32 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe - -=== TRAINER_BERNIE_5 === -Name: 信彦 -Class: Kindler -Pic: Kindler -Gender: Male -Music: Hiker -Double Battle: No -AI: Check Bad Move - -Magcargo -Level: 35 -IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe - -Pelipper -Level: 35 -IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe - -=== TRAINER_DREW === -Name: 典弘 -Class: Camper -Pic: Camper -Gender: Male -Music: Male -Double Battle: No -AI: Check Bad Move - -Sandshrew -Level: 23 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe -- Dig -- Sand Attack -- Poison Sting -- Slash - -=== TRAINER_BEAU === -Name: 和之 -Class: Camper -Pic: Camper -Gender: Male -Music: Male -Double Battle: No -AI: Check Bad Move - -Baltoy -Level: 21 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe -- Rapid Spin -- Mud Slap -- Psybeam -- Rock Tomb - -Sandshrew -Level: 21 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe -- Poison Sting -- Sand Attack -- Scratch -- Dig - -Baltoy -Level: 21 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe -- Rapid Spin -- Mud Slap -- Psybeam -- Rock Tomb - -=== TRAINER_LARRY === -Name: 清文 -Class: Camper -Pic: Camper -Gender: Male -Music: Male -Double Battle: No -AI: Check Bad Move - -Nuzleaf -Level: 18 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_SHANE === -Name: 智弘 -Class: Camper -Pic: Camper -Gender: Male -Music: Male -Double Battle: No -AI: Check Bad Move - -Sandshrew -Level: 18 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Nuzleaf -Level: 18 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_JUSTIN === -Name: 正道 -Class: Camper -Pic: Camper -Gender: Male -Music: Male -Double Battle: No -AI: Check Bad Move - -Kecleon -Level: 24 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_ETHAN_1 === -Name: 义晴 -Class: Camper -Pic: Camper -Gender: Male -Music: Male -Double Battle: No -AI: Check Bad Move - -Zigzagoon -Level: 20 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Taillow -Level: 20 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_AUTUMN === -Name: 奈津子 -Class: Picnicker -Pic: Picnicker -Gender: Female -Music: Girl -Double Battle: No -AI: Check Bad Move - -Shroomish -Level: 21 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_TRAVIS === -Name: 良也 -Class: Camper -Pic: Camper -Gender: Male -Music: Male -Double Battle: No -AI: Check Bad Move - -Sandshrew -Level: 18 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_ETHAN_2 === -Name: 义晴 -Class: Camper -Pic: Camper -Gender: Male -Music: Male -Double Battle: No -AI: Check Bad Move - -Zigzagoon -Level: 26 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe - -Taillow -Level: 26 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe - -=== TRAINER_ETHAN_3 === -Name: 义晴 -Class: Camper -Pic: Camper -Gender: Male -Music: Male -Double Battle: No -AI: Check Bad Move - -Linoone -Level: 29 -IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe - -Swellow -Level: 29 -IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe - -=== TRAINER_ETHAN_4 === -Name: 义晴 -Class: Camper -Pic: Camper -Gender: Male -Music: Male -Double Battle: No -AI: Check Bad Move - -Sandshrew -Level: 31 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe - -Swellow -Level: 31 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe - -Linoone -Level: 31 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe - -=== TRAINER_ETHAN_5 === -Name: 义晴 -Class: Camper -Pic: Camper -Gender: Male -Music: Male -Double Battle: No -AI: Check Bad Move - -Swellow -Level: 34 -IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe - -Sandslash -Level: 34 -IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe - -Linoone -Level: 34 -IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe - -=== TRAINER_BRENT === -Name: 洋一 -Class: Bug Maniac -Pic: Bug Maniac -Gender: Male -Music: Suspicious -Double Battle: No -AI: Check Bad Move - -Surskit -Level: 26 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -=== TRAINER_DONALD === -Name: 苍介 -Class: Bug Maniac -Pic: Bug Maniac -Gender: Male -Music: Suspicious -Double Battle: No -AI: Check Bad Move - -Wurmple -Level: 24 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -Silcoon -Level: 24 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -Beautifly -Level: 24 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -=== TRAINER_TAYLOR === -Name: 生海 -Class: Bug Maniac -Pic: Bug Maniac -Gender: Male -Music: Suspicious -Double Battle: No -AI: Check Bad Move - -Wurmple -Level: 27 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -Cascoon -Level: 27 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -Dustox -Level: 27 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -=== TRAINER_JEFFREY_1 === -Name: 干雄 -Class: Bug Maniac -Pic: Bug Maniac -Gender: Male -Music: Suspicious -Double Battle: No -AI: Check Bad Move - -Surskit -Level: 27 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Surskit -Level: 27 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Surskit -Level: 27 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_DEREK === -Name: 良明 -Class: Bug Maniac -Pic: Bug Maniac -Gender: Male -Music: Suspicious -Double Battle: No -AI: Check Bad Move - -Dustox -Level: 16 -IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe - -Beautifly -Level: 16 -IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe - -=== TRAINER_JEFFREY_2 === -Name: 干雄 -Class: Bug Maniac -Pic: Bug Maniac -Gender: Male -Music: Suspicious -Double Battle: No -AI: Check Bad Move - -Surskit -Level: 31 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe - -Surskit -Level: 31 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe - -Surskit -Level: 31 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe - -=== TRAINER_JEFFREY_3 === -Name: 干雄 -Class: Bug Maniac -Pic: Bug Maniac -Gender: Male -Music: Suspicious -Double Battle: No -AI: Check Bad Move - -Surskit -Level: 34 -IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe - -Surskit -Level: 34 -IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe - -Masquerain -Level: 34 -IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe - -=== TRAINER_JEFFREY_4 === -Name: 干雄 -Class: Bug Maniac -Pic: Bug Maniac -Gender: Male -Music: Suspicious -Double Battle: No -AI: Check Bad Move - -Surskit -Level: 36 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe - -Wurmple -Level: 36 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe - -Surskit -Level: 36 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe - -Masquerain -Level: 36 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe - -=== TRAINER_JEFFREY_5 === -Name: 干雄 -Class: Bug Maniac -Pic: Bug Maniac -Gender: Male -Music: Suspicious -Double Battle: No -AI: Check Bad Move - -Surskit -Level: 38 -IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe - -Dustox -Level: 38 -IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe - -Surskit -Level: 38 -IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe - -Masquerain @ Silver Powder -Level: 38 -IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe - -Beautifly -Level: 38 -IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe - -=== TRAINER_EDWARD === -Name: 明人 -Class: Psychic -Pic: Psychic M -Gender: Male -Music: Intense -Double Battle: No -AI: Check Bad Move - -Abra -Level: 15 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe -- Hidden Power - -=== TRAINER_PRESTON === -Name: 宏 -Class: Psychic -Pic: Psychic M -Gender: Male -Music: Intense -Double Battle: No -AI: Check Bad Move - -Kirlia -Level: 36 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -=== TRAINER_VIRGIL === -Name: 祐也 -Class: Psychic -Pic: Psychic M -Gender: Male -Music: Intense -Double Battle: No -AI: Check Bad Move - -Ralts -Level: 36 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -=== TRAINER_BLAKE === -Name: 聪 -Class: Psychic -Pic: Psychic M -Gender: Male -Music: Intense -Double Battle: No -AI: Check Bad Move - -Girafarig -Level: 36 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -=== TRAINER_WILLIAM === -Name: 彻也 -Class: Psychic -Pic: Psychic M -Gender: Male -Music: Intense -Double Battle: No -AI: Check Bad Move - -Ralts -Level: 26 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Ralts -Level: 26 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Kirlia -Level: 26 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_JOSHUA === -Name: 修一 -Class: Psychic -Pic: Psychic M -Gender: Male -Music: Intense -Double Battle: No -AI: Check Bad Move - -Kadabra -Level: 41 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Solrock -Level: 41 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_CAMERON_1 === -Name: 薰 -Class: Psychic -Pic: Psychic M -Gender: Male -Music: Intense -Double Battle: No -AI: Check Bad Move - -Solrock -Level: 31 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_CAMERON_2 === -Name: 薰 -Class: Psychic -Pic: Psychic M -Gender: Male -Music: Intense -Double Battle: No -AI: Check Bad Move - -Kadabra -Level: 33 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe - -Solrock -Level: 33 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe - -=== TRAINER_CAMERON_3 === -Name: 薰 -Class: Psychic -Pic: Psychic M -Gender: Male -Music: Intense -Double Battle: No -AI: Check Bad Move - -Kadabra -Level: 38 -IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe - -Solrock -Level: 38 -IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe - -=== TRAINER_CAMERON_4 === -Name: 薰 -Class: Psychic -Pic: Psychic M -Gender: Male -Music: Intense -Double Battle: No -AI: Check Bad Move - -Kadabra -Level: 41 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe - -Solrock -Level: 41 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe - -=== TRAINER_CAMERON_5 === -Name: 薰 -Class: Psychic -Pic: Psychic M -Gender: Male -Music: Intense -Double Battle: No -AI: Check Bad Move - -Solrock -Level: 45 -IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe - -Alakazam -Level: 45 -IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe - -=== TRAINER_JACLYN === -Name: 玛俐可 -Class: Psychic -Pic: Psychic F -Gender: Female -Music: Intense -Double Battle: No -AI: Check Bad Move - -Abra -Level: 16 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe -- Hidden Power - -=== TRAINER_HANNAH === -Name: 飞鸟 -Class: Psychic -Pic: Psychic F -Gender: Female -Music: Intense -Double Battle: No -AI: Check Bad Move - -Kirlia -Level: 36 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -=== TRAINER_SAMANTHA === -Name: 未来 -Class: Psychic -Pic: Psychic F -Gender: Female -Music: Intense -Double Battle: No -AI: Check Bad Move - -Xatu -Level: 36 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -=== TRAINER_MAURA === -Name: 光 -Class: Psychic -Pic: Psychic F -Gender: Female -Music: Intense -Double Battle: No -AI: Check Bad Move - -Kadabra -Level: 36 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -=== TRAINER_KAYLA === -Name: 织江 -Class: Psychic -Pic: Psychic F -Gender: Female -Music: Intense -Double Battle: No -AI: Check Bad Move - -Wobbuffet -Level: 26 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Natu -Level: 26 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Kadabra -Level: 26 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_ALEXIS === -Name: 奈奈子 -Class: Psychic -Pic: Psychic F -Gender: Female -Music: Intense -Double Battle: No -AI: Check Bad Move - -Kirlia -Level: 41 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Xatu -Level: 41 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_JACKI_1 === -Name: 志保美 -Class: Psychic -Pic: Psychic F -Gender: Female -Music: Intense -Double Battle: No -AI: Check Bad Move - -Kadabra -Level: 30 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Lunatone -Level: 30 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_JACKI_2 === -Name: 志保美 -Class: Psychic -Pic: Psychic F -Gender: Female -Music: Intense -Double Battle: No -AI: Check Bad Move - -Kadabra -Level: 34 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe - -Lunatone -Level: 34 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe - -=== TRAINER_JACKI_3 === -Name: 志保美 -Class: Psychic -Pic: Psychic F -Gender: Female -Music: Intense -Double Battle: No -AI: Check Bad Move - -Kadabra -Level: 37 -IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe - -Lunatone -Level: 37 -IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe - -=== TRAINER_JACKI_4 === -Name: 志保美 -Class: Psychic -Pic: Psychic F -Gender: Female -Music: Intense -Double Battle: No -AI: Check Bad Move - -Kadabra -Level: 40 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe - -Lunatone -Level: 40 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe - -=== TRAINER_JACKI_5 === -Name: 志保美 -Class: Psychic -Pic: Psychic F -Gender: Female -Music: Intense -Double Battle: No -AI: Check Bad Move - -Lunatone -Level: 43 -IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe - -Alakazam -Level: 43 -IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe - -=== TRAINER_WALTER_1 === -Name: 罗伯特 -Class: Gentleman -Pic: Gentleman -Gender: Male -Music: Rich -Double Battle: No -AI: Check Bad Move - -Manectric -Level: 29 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_MICAH === -Name: 奥尔森 -Class: Gentleman -Pic: Gentleman -Gender: Male -Music: Rich -Double Battle: No -AI: Check Bad Move - -Manectric -Level: 44 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Manectric -Level: 44 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_THOMAS === -Name: 史考特 -Class: Gentleman -Pic: Gentleman -Gender: Male -Music: Rich -Double Battle: No -AI: Check Bad Move - -Zangoose -Level: 45 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_WALTER_2 === -Name: 罗伯特 -Class: Gentleman -Pic: Gentleman -Gender: Male -Music: Rich -Double Battle: No -AI: Check Bad Move - -Manectric -Level: 34 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe - -=== TRAINER_WALTER_3 === -Name: 罗伯特 -Class: Gentleman -Pic: Gentleman -Gender: Male -Music: Rich -Double Battle: No -AI: Check Bad Move - -Linoone -Level: 36 -IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe -- Headbutt -- Sand Attack -- Odor Sleuth -- Fury Swipes - -Manectric -Level: 36 -IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe -- Quick Attack -- Spark -- Odor Sleuth -- Roar - -=== TRAINER_WALTER_4 === -Name: 罗伯特 -Class: Gentleman -Pic: Gentleman -Gender: Male -Music: Rich -Double Battle: No -AI: Check Bad Move - -Linoone -Level: 39 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe -- Headbutt -- Sand Attack -- Odor Sleuth -- Fury Swipes - -Manectric -Level: 39 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe -- Quick Attack -- Spark -- Odor Sleuth - -=== TRAINER_WALTER_5 === -Name: 罗伯特 -Class: Gentleman -Pic: Gentleman -Gender: Male -Music: Rich -Double Battle: No -AI: Check Bad Move - -Linoone -Level: 41 -IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe -- Headbutt -- Sand Attack -- Odor Sleuth -- Fury Swipes - -Golduck -Level: 41 -IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe -- Fury Swipes -- Disable -- Confusion -- Psych Up - -Manectric -Level: 41 -IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe -- Quick Attack -- Spark -- Odor Sleuth -- Roar - -=== TRAINER_SIDNEY === -Name: 花月 -Class: Elite Four -Pic: Elite Four Sidney -Gender: Male -Music: Elite Four -Items: Full Restore / Full Restore -Double Battle: No -AI: Basic Trainer / Force Setup First Turn -Mugshot: Purple - -Mightyena -Level: 46 -IVs: 30 HP / 30 Atk / 30 Def / 30 SpA / 30 SpD / 30 Spe -- Roar -- Double Edge -- Sand Attack -- Crunch - -Shiftry -Level: 48 -IVs: 30 HP / 30 Atk / 30 Def / 30 SpA / 30 SpD / 30 Spe -- Torment -- Double Team -- Swagger -- Extrasensory - -Cacturne -Level: 46 -IVs: 30 HP / 30 Atk / 30 Def / 30 SpA / 30 SpD / 30 Spe -- Leech Seed -- Feint Attack -- Needle Arm -- Cotton Spore - -Crawdaunt -Level: 48 -IVs: 30 HP / 30 Atk / 30 Def / 30 SpA / 30 SpD / 30 Spe -- Surf -- Swords Dance -- Strength -- Facade - -Absol @ Sitrus Berry -Level: 49 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Aerial Ace -- Rock Slide -- Swords Dance -- Slash - -=== TRAINER_PHOEBE === -Name: 芙蓉 -Class: Elite Four -Pic: Elite Four Phoebe -Gender: Female -Music: Elite Four -Items: Full Restore / Full Restore -Double Battle: No -AI: Basic Trainer -Mugshot: Green - -Dusclops -Level: 48 -IVs: 30 HP / 30 Atk / 30 Def / 30 SpA / 30 SpD / 30 Spe -- Shadow Punch -- Confuse Ray -- Curse -- Protect - -Banette -Level: 49 -IVs: 30 HP / 30 Atk / 30 Def / 30 SpA / 30 SpD / 30 Spe -- Shadow Ball -- Grudge -- Will O Wisp -- Feint Attack - -Sableye -Level: 50 -IVs: 30 HP / 30 Atk / 30 Def / 30 SpA / 30 SpD / 30 Spe -- Shadow Ball -- Double Team -- Night Shade -- Feint Attack - -Banette -Level: 49 -IVs: 30 HP / 30 Atk / 30 Def / 30 SpA / 30 SpD / 30 Spe -- Shadow Ball -- Psychic -- Thunderbolt -- Facade - -Dusclops @ Sitrus Berry -Level: 51 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Shadow Ball -- Ice Beam -- Rock Slide -- Earthquake - -=== TRAINER_GLACIA === -Name: 波妮 -Class: Elite Four -Pic: Elite Four Glacia -Gender: Female -Music: Elite Four -Items: Full Restore / Full Restore -Double Battle: No -AI: Basic Trainer -Mugshot: Pink - -Sealeo -Level: 50 -IVs: 30 HP / 30 Atk / 30 Def / 30 SpA / 30 SpD / 30 Spe -- Encore -- Body Slam -- Hail -- Ice Ball - -Glalie -Level: 50 -IVs: 30 HP / 30 Atk / 30 Def / 30 SpA / 30 SpD / 30 Spe -- Light Screen -- Crunch -- Icy Wind -- Ice Beam - -Sealeo -Level: 52 -IVs: 30 HP / 30 Atk / 30 Def / 30 SpA / 30 SpD / 30 Spe -- Attract -- Double Edge -- Hail -- Blizzard - -Glalie -Level: 52 -IVs: 30 HP / 30 Atk / 30 Def / 30 SpA / 30 SpD / 30 Spe -- Shadow Ball -- Explosion -- Hail -- Ice Beam - -Walrein @ Sitrus Berry -Level: 53 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Surf -- Body Slam -- Ice Beam -- Sheer Cold - -=== TRAINER_DRAKE === -Name: 源治 -Class: Elite Four -Pic: Elite Four Drake -Gender: Male -Music: Elite Four -Items: Full Restore / Full Restore -Double Battle: No -AI: Basic Trainer -Mugshot: Blue - -Shelgon -Level: 52 -IVs: 30 HP / 30 Atk / 30 Def / 30 SpA / 30 SpD / 30 Spe -- Rock Tomb -- Dragon Claw -- Protect -- Double Edge - -Altaria -Level: 54 -IVs: 30 HP / 30 Atk / 30 Def / 30 SpA / 30 SpD / 30 Spe -- Double Edge -- Dragon Breath -- Dragon Dance -- Aerial Ace - -Kingdra -Level: 53 -IVs: 30 HP / 30 Atk / 30 Def / 30 SpA / 30 SpD / 30 Spe -- Smokescreen -- Dragon Dance -- Surf -- Body Slam - -Flygon -Level: 53 -IVs: 30 HP / 30 Atk / 30 Def / 30 SpA / 30 SpD / 30 Spe -- Flamethrower -- Crunch -- Dragon Breath -- Earthquake - -Salamence @ Sitrus Berry -Level: 55 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Flamethrower -- Dragon Claw -- Rock Slide -- Crunch - -=== TRAINER_ROXANNE_1 === -Name: 杜娟 -Class: Leader -Pic: Leader Roxanne -Gender: Female -Music: Female -Items: Potion / Potion -Double Battle: No -AI: Basic Trainer - -Geodude -Level: 12 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe -- Tackle -- Defense Curl -- Rock Throw -- Rock Tomb - -Geodude -Level: 12 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe -- Tackle -- Defense Curl -- Rock Throw -- Rock Tomb - -Nosepass @ Oran Berry -Level: 15 -IVs: 24 HP / 24 Atk / 24 Def / 24 SpA / 24 SpD / 24 Spe -- Block -- Harden -- Tackle -- Rock Tomb - -=== TRAINER_BRAWLY_1 === -Name: 藤树 -Class: Leader -Pic: Leader Brawly -Gender: Male -Music: Male -Items: Super Potion / Super Potion -Double Battle: No -AI: Basic Trainer - -Machop -Level: 16 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe -- Karate Chop -- Low Kick -- Seismic Toss -- Bulk Up - -Meditite -Level: 16 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe -- Focus Punch -- Light Screen -- Reflect -- Bulk Up - -Makuhita @ Sitrus Berry -Level: 19 -IVs: 24 HP / 24 Atk / 24 Def / 24 SpA / 24 SpD / 24 Spe -- Arm Thrust -- Vital Throw -- Reversal -- Bulk Up - -=== TRAINER_WATTSON_1 === -Name: 铁旋 -Class: Leader -Pic: Leader Wattson -Gender: Male -Music: Male -Items: Super Potion / Super Potion -Double Battle: No -AI: Basic Trainer - -Voltorb -Level: 20 -IVs: 24 HP / 24 Atk / 24 Def / 24 SpA / 24 SpD / 24 Spe -- Rollout -- Spark -- Self Destruct -- Shock Wave - -Electrike -Level: 20 -IVs: 24 HP / 24 Atk / 24 Def / 24 SpA / 24 SpD / 24 Spe -- Shock Wave -- Leer -- Quick Attack -- Howl - -Magneton -Level: 22 -IVs: 26 HP / 26 Atk / 26 Def / 26 SpA / 26 SpD / 26 Spe -- Supersonic -- Shock Wave -- Thunder Wave -- Sonic Boom - -Manectric @ Sitrus Berry -Level: 24 -IVs: 30 HP / 30 Atk / 30 Def / 30 SpA / 30 SpD / 30 Spe -- Quick Attack -- Thunder Wave -- Shock Wave -- Howl - -=== TRAINER_FLANNERY_1 === -Name: 亚莎 -Class: Leader -Pic: Leader Flannery -Gender: Female -Music: Female -Items: Hyper Potion / Hyper Potion -Double Battle: No -AI: Basic Trainer - -Numel -Level: 24 -IVs: 24 HP / 24 Atk / 24 Def / 24 SpA / 24 SpD / 24 Spe -- Overheat -- Take Down -- Magnitude -- Sunny Day - -Slugma -Level: 24 -IVs: 24 HP / 24 Atk / 24 Def / 24 SpA / 24 SpD / 24 Spe -- Overheat -- Smog -- Light Screen -- Sunny Day - -Camerupt -Level: 26 -IVs: 30 HP / 30 Atk / 30 Def / 30 SpA / 30 SpD / 30 Spe -- Overheat -- Tackle -- Sunny Day -- Attract - -Torkoal @ White Herb -Level: 29 -IVs: 30 HP / 30 Atk / 30 Def / 30 SpA / 30 SpD / 30 Spe -- Overheat -- Sunny Day -- Body Slam -- Attract - -=== TRAINER_NORMAN_1 === -Name: 千里 -Class: Leader -Pic: Leader Norman -Gender: Male -Music: Male -Items: Hyper Potion / Hyper Potion -Double Battle: No -AI: Basic Trainer - -Spinda -Level: 27 -IVs: 24 HP / 24 Atk / 24 Def / 24 SpA / 24 SpD / 24 Spe -- Teeter Dance -- Psybeam -- Facade -- Encore - -Vigoroth -Level: 27 -IVs: 24 HP / 24 Atk / 24 Def / 24 SpA / 24 SpD / 24 Spe -- Slash -- Facade -- Encore -- Feint Attack - -Linoone -Level: 29 -IVs: 24 HP / 24 Atk / 24 Def / 24 SpA / 24 SpD / 24 Spe -- Slash -- Belly Drum -- Facade -- Headbutt - -Slaking @ Sitrus Berry -Level: 31 -IVs: 30 HP / 30 Atk / 30 Def / 30 SpA / 30 SpD / 30 Spe -- Counter -- Yawn -- Facade -- Feint Attack - -=== TRAINER_WINONA_1 === -Name: 娜琪 -Class: Leader -Pic: Leader Winona -Gender: Female -Music: Female -Items: Hyper Potion / Hyper Potion -Double Battle: No -AI: Basic Trainer / Risky - -Swablu -Level: 29 -IVs: 25 HP / 25 Atk / 25 Def / 25 SpA / 25 SpD / 25 Spe -- Perish Song -- Mirror Move -- Safeguard -- Aerial Ace - -Tropius -Level: 29 -IVs: 25 HP / 25 Atk / 25 Def / 25 SpA / 25 SpD / 25 Spe -- Sunny Day -- Aerial Ace -- Solar Beam -- Synthesis - -Pelipper -Level: 30 -IVs: 25 HP / 25 Atk / 25 Def / 25 SpA / 25 SpD / 25 Spe -- Water Gun -- Supersonic -- Protect -- Aerial Ace - -Skarmory -Level: 31 -IVs: 26 HP / 26 Atk / 26 Def / 26 SpA / 26 SpD / 26 Spe -- Sand Attack -- Fury Attack -- Steel Wing -- Aerial Ace - -Altaria @ Oran Berry -Level: 33 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Earthquake -- Dragon Breath -- Dragon Dance -- Aerial Ace - -=== TRAINER_TATE_AND_LIZA_1 === -Name: 小枫与小南 -Class: Leader -Pic: Leader Tate And Liza -Gender: Male -Music: Female -Items: Hyper Potion / Hyper Potion / Hyper Potion / Hyper Potion -Double Battle: Yes -AI: Basic Trainer - -Claydol -Level: 41 -IVs: 30 HP / 30 Atk / 30 Def / 30 SpA / 30 SpD / 30 Spe -- Earthquake -- Ancient Power -- Psychic -- Light Screen - -Xatu -Level: 41 -IVs: 30 HP / 30 Atk / 30 Def / 30 SpA / 30 SpD / 30 Spe -- Psychic -- Sunny Day -- Confuse Ray -- Calm Mind - -Lunatone @ Sitrus Berry -Level: 42 -IVs: 30 HP / 30 Atk / 30 Def / 30 SpA / 30 SpD / 30 Spe -- Light Screen -- Psychic -- Hypnosis -- Calm Mind - -Solrock @ Sitrus Berry -Level: 42 -IVs: 30 HP / 30 Atk / 30 Def / 30 SpA / 30 SpD / 30 Spe -- Sunny Day -- Solar Beam -- Psychic -- Flamethrower - -=== TRAINER_JUAN_1 === -Name: 亚当 -Class: Leader -Pic: Leader Juan -Gender: Male -Music: Male -Items: Hyper Potion / Hyper Potion -Double Battle: No -AI: Basic Trainer - -Luvdisc -Level: 41 -IVs: 24 HP / 24 Atk / 24 Def / 24 SpA / 24 SpD / 24 Spe -- Water Pulse -- Attract -- Sweet Kiss -- Flail - -Whiscash -Level: 41 -IVs: 24 HP / 24 Atk / 24 Def / 24 SpA / 24 SpD / 24 Spe -- Rain Dance -- Water Pulse -- Amnesia -- Earthquake - -Sealeo -Level: 43 -IVs: 24 HP / 24 Atk / 24 Def / 24 SpA / 24 SpD / 24 Spe -- Encore -- Body Slam -- Aurora Beam -- Water Pulse - -Crawdaunt -Level: 43 -IVs: 24 HP / 24 Atk / 24 Def / 24 SpA / 24 SpD / 24 Spe -- Water Pulse -- Crabhammer -- Taunt -- Leer - -Kingdra @ Chesto Berry -Level: 46 -IVs: 30 HP / 30 Atk / 30 Def / 30 SpA / 30 SpD / 30 Spe -- Water Pulse -- Double Team -- Ice Beam -- Rest - -=== TRAINER_JERRY_1 === -Name: 秀夫 -Class: School Kid -Pic: School Kid M -Gender: Male -Music: Male -Double Battle: No -AI: Check Bad Move - -Ralts -Level: 9 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe - -=== TRAINER_TED === -Name: 信久 -Class: School Kid -Pic: School Kid M -Gender: Male -Music: Male -Double Battle: No -AI: Check Bad Move - -Ralts -Level: 17 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe - -=== TRAINER_PAUL === -Name: 胜俊 -Class: School Kid -Pic: School Kid M -Gender: Male -Music: Male -Double Battle: No -AI: Check Bad Move - -Numel -Level: 15 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe - -Oddish -Level: 15 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe - -Wingull -Level: 15 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe - -=== TRAINER_JERRY_2 === -Name: 秀夫 -Class: School Kid -Pic: School Kid M -Gender: Male -Music: Male -Double Battle: No -AI: Check Bad Move - -Ralts -Level: 26 -IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe - -Meditite -Level: 26 -IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe - -=== TRAINER_JERRY_3 === -Name: 秀夫 -Class: School Kid -Pic: School Kid M -Gender: Male -Music: Male -Double Battle: No -AI: Check Bad Move - -Kirlia -Level: 29 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe - -Meditite -Level: 29 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe - -=== TRAINER_JERRY_4 === -Name: 秀夫 -Class: School Kid -Pic: School Kid M -Gender: Male -Music: Male -Double Battle: No -AI: Check Bad Move - -Kirlia -Level: 32 -IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe - -Medicham -Level: 32 -IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe - -=== TRAINER_JERRY_5 === -Name: 秀夫 -Class: School Kid -Pic: School Kid M -Gender: Male -Music: Male -Double Battle: No -AI: Check Bad Move - -Kirlia -Level: 34 -IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe - -Banette -Level: 34 -IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe - -Medicham -Level: 34 -IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe - -=== TRAINER_KAREN_1 === -Name: 初音 -Class: School Kid -Pic: School Kid F -Gender: Female -Music: Girl -Double Battle: No -AI: Check Bad Move - -Shroomish -Level: 9 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe - -=== TRAINER_GEORGIA === -Name: 美贵江 -Class: School Kid -Pic: School Kid F -Gender: Female -Music: Girl -Double Battle: No -AI: Check Bad Move - -Shroomish -Level: 16 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe - -Beautifly -Level: 16 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe - -=== TRAINER_KAREN_2 === -Name: 初音 -Class: School Kid -Pic: School Kid F -Gender: Female -Music: Girl -Double Battle: No -AI: Check Bad Move - -Shroomish -Level: 26 -IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe - -Whismur -Level: 26 -IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe - -=== TRAINER_KAREN_3 === -Name: 初音 -Class: School Kid -Pic: School Kid F -Gender: Female -Music: Girl -Double Battle: No -AI: Check Bad Move - -Shroomish -Level: 29 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe - -Loudred -Level: 29 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe - -=== TRAINER_KAREN_4 === -Name: 初音 -Class: School Kid -Pic: School Kid F -Gender: Female -Music: Girl -Double Battle: No -AI: Check Bad Move - -Breloom -Level: 32 -IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe - -Loudred -Level: 32 -IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe - -=== TRAINER_KAREN_5 === -Name: 初音 -Class: School Kid -Pic: School Kid F -Gender: Female -Music: Girl -Double Battle: No -AI: Check Bad Move - -Breloom -Level: 35 -IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe - -Exploud -Level: 35 -IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe - -=== TRAINER_KATE_AND_JOY === -Name: 真奈和由依 -Class: Sr And Jr -Pic: Sr And Jr -Gender: Male -Music: Twins -Double Battle: Yes -AI: Check Bad Move - -Spinda -Level: 30 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe -- Hypnosis -- Psybeam -- Dizzy Punch -- Teeter Dance - -Slaking -Level: 32 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe -- Focus Punch -- Yawn -- Slack Off -- Feint Attack - -=== TRAINER_ANNA_AND_MEG_1 === -Name: 美穗和里子 -Class: Sr And Jr -Pic: Sr And Jr -Gender: Male -Music: Twins -Double Battle: Yes -AI: Check Bad Move - -Zigzagoon -Level: 15 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe -- Growl -- Tail Whip -- Headbutt -- Odor Sleuth - -Makuhita -Level: 17 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe -- Tackle -- Focus Energy -- Arm Thrust - -=== TRAINER_ANNA_AND_MEG_2 === -Name: 美穗和里子 -Class: Sr And Jr -Pic: Sr And Jr -Gender: Male -Music: Twins -Double Battle: Yes -AI: Check Bad Move - -Zigzagoon -Level: 28 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe -- Growl -- Tail Whip -- Headbutt -- Odor Sleuth - -Makuhita -Level: 30 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe -- Tackle -- Focus Energy -- Arm Thrust - -=== TRAINER_ANNA_AND_MEG_3 === -Name: 美穗和里子 -Class: Sr And Jr -Pic: Sr And Jr -Gender: Male -Music: Twins -Double Battle: Yes -AI: Check Bad Move - -Zigzagoon -Level: 31 -IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe -- Growl -- Tail Whip -- Headbutt -- Odor Sleuth - -Makuhita -Level: 33 -IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe -- Tackle -- Focus Energy -- Arm Thrust - -=== TRAINER_ANNA_AND_MEG_4 === -Name: 美穗和里子 -Class: Sr And Jr -Pic: Sr And Jr -Gender: Male -Music: Twins -Double Battle: Yes -AI: Check Bad Move - -Linoone -Level: 34 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe -- Growl -- Tail Whip -- Headbutt -- Odor Sleuth - -Makuhita -Level: 36 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe -- Tackle -- Focus Energy -- Arm Thrust - -=== TRAINER_ANNA_AND_MEG_5 === -Name: 美穗和里子 -Class: Sr And Jr -Pic: Sr And Jr -Gender: Male -Music: Twins -Double Battle: Yes -AI: Check Bad Move - -Linoone -Level: 36 -IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe -- Growl -- Tail Whip -- Headbutt -- Odor Sleuth - -Hariyama -Level: 38 -IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe -- Tackle -- Focus Energy -- Arm Thrust - -=== TRAINER_VICTOR === -Name: 晴彦 -Class: Winstrate -Pic: Pokefan M -Gender: Male -Music: Twins -Double Battle: No -AI: Check Bad Move - -Taillow @ Oran Berry -Level: 16 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe - -Zigzagoon @ Oran Berry -Level: 16 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe - -=== TRAINER_MIGUEL_1 === -Name: 光晴 -Class: Pokefan -Pic: Pokefan M -Gender: Male -Music: Twins -Double Battle: No -AI: Check Bad Move - -Skitty @ Oran Berry -Level: 15 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_COLTON === -Name: 尚志 -Class: Pokefan -Pic: Pokefan M -Gender: Male -Music: Twins -Double Battle: No -AI: Check Bad Move - -Skitty @ Oran Berry -Level: 22 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe -- Assist -- Charm -- Feint Attack -- Heal Bell - -Skitty @ Oran Berry -Level: 36 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe -- Assist -- Charm -- Feint Attack -- Heal Bell - -Skitty @ Oran Berry -Level: 40 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe -- Assist -- Charm -- Feint Attack -- Heal Bell - -Skitty @ Oran Berry -Level: 12 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe -- Assist -- Charm -- Feint Attack -- Heal Bell - -Skitty @ Oran Berry -Level: 30 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe -- Assist -- Charm -- Feint Attack -- Heal Bell - -Delcatty @ Oran Berry -Level: 42 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe -- Assist -- Charm -- Feint Attack -- Heal Bell - -=== TRAINER_MIGUEL_2 === -Name: 光晴 -Class: Pokefan -Pic: Pokefan M -Gender: Male -Music: Twins -Double Battle: No -AI: Check Bad Move - -Skitty @ Oran Berry -Level: 29 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_MIGUEL_3 === -Name: 光晴 -Class: Pokefan -Pic: Pokefan M -Gender: Male -Music: Twins -Double Battle: No -AI: Check Bad Move - -Skitty @ Oran Berry -Level: 32 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_MIGUEL_4 === -Name: 光晴 -Class: Pokefan -Pic: Pokefan M -Gender: Male -Music: Twins -Double Battle: No -AI: Check Bad Move - -Delcatty @ Oran Berry -Level: 35 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_MIGUEL_5 === -Name: 光晴 -Class: Pokefan -Pic: Pokefan M -Gender: Male -Music: Twins -Double Battle: No -AI: Check Bad Move - -Delcatty @ Sitrus Berry -Level: 38 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_VICTORIA === -Name: 安江 -Class: Winstrate -Pic: Pokefan F -Gender: Female -Music: Twins -Double Battle: No -AI: Check Bad Move / Try To Faint - -Roselia @ Oran Berry -Level: 17 -IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe - -=== TRAINER_VANESSA === -Name: 今朝子 -Class: Pokefan -Pic: Pokefan F -Gender: Female -Music: Twins -Double Battle: No -AI: Check Bad Move - -Pikachu @ Oran Berry -Level: 30 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_BETHANY === -Name: 汀子 -Class: Pokefan -Pic: Pokefan F -Gender: Female -Music: Twins -Double Battle: No -AI: Check Bad Move - -Azurill @ Oran Berry -Level: 35 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -Marill @ Oran Berry -Level: 37 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -Azumarill @ Oran Berry -Level: 39 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -=== TRAINER_ISABEL_1 === -Name: 雅子 -Class: Pokefan -Pic: Pokefan F -Gender: Female -Music: Twins -Double Battle: No -AI: Check Bad Move - -Plusle @ Oran Berry -Level: 14 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Minun @ Oran Berry -Level: 14 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_ISABEL_2 === -Name: 雅子 -Class: Pokefan -Pic: Pokefan F -Gender: Female -Music: Twins -Double Battle: No -AI: Check Bad Move - -Plusle @ Oran Berry -Level: 26 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe - -Minun @ Oran Berry -Level: 26 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe - -=== TRAINER_ISABEL_3 === -Name: 雅子 -Class: Pokefan -Pic: Pokefan F -Gender: Female -Music: Twins -Double Battle: No -AI: Check Bad Move - -Plusle @ Oran Berry -Level: 29 -IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe - -Minun @ Oran Berry -Level: 29 -IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe - -=== TRAINER_ISABEL_4 === -Name: 雅子 -Class: Pokefan -Pic: Pokefan F -Gender: Female -Music: Twins -Double Battle: No -AI: Check Bad Move - -Plusle @ Oran Berry -Level: 32 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe - -Minun @ Oran Berry -Level: 32 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe - -=== TRAINER_ISABEL_5 === -Name: 雅子 -Class: Pokefan -Pic: Pokefan F -Gender: Female -Music: Twins -Double Battle: No -AI: Check Bad Move - -Plusle @ Sitrus Berry -Level: 35 -IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe - -Minun @ Sitrus Berry -Level: 35 -IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe - -=== TRAINER_TIMOTHY_1 === -Name: 文翔 -Class: Expert -Pic: Expert M -Gender: Male -Music: Intense -Double Battle: No -AI: Basic Trainer - -Hariyama -Level: 27 -IVs: 24 HP / 24 Atk / 24 Def / 24 SpA / 24 SpD / 24 Spe - -=== TRAINER_TIMOTHY_2 === -Name: 文翔 -Class: Expert -Pic: Expert M -Gender: Male -Music: Intense -Double Battle: No -AI: Basic Trainer - -Hariyama -Level: 33 -IVs: 25 HP / 25 Atk / 25 Def / 25 SpA / 25 SpD / 25 Spe -- Arm Thrust -- Knock Off -- Sand Attack -- Dig - -=== TRAINER_TIMOTHY_3 === -Name: 文翔 -Class: Expert -Pic: Expert M -Gender: Male -Music: Intense -Double Battle: No -AI: Basic Trainer - -Hariyama -Level: 36 -IVs: 26 HP / 26 Atk / 26 Def / 26 SpA / 26 SpD / 26 Spe -- Arm Thrust -- Knock Off -- Sand Attack -- Dig - -=== TRAINER_TIMOTHY_4 === -Name: 文翔 -Class: Expert -Pic: Expert M -Gender: Male -Music: Intense -Double Battle: No -AI: Basic Trainer - -Hariyama -Level: 39 -IVs: 27 HP / 27 Atk / 27 Def / 27 SpA / 27 SpD / 27 Spe -- Arm Thrust -- Belly Drum -- Sand Attack -- Dig - -=== TRAINER_TIMOTHY_5 === -Name: 文翔 -Class: Expert -Pic: Expert M -Gender: Male -Music: Intense -Double Battle: No -AI: Basic Trainer - -Hariyama -Level: 42 -IVs: 29 HP / 29 Atk / 29 Def / 29 SpA / 29 SpD / 29 Spe -- Arm Thrust -- Belly Drum -- Sand Attack -- Dig - -=== TRAINER_VICKY === -Name: 光代 -Class: Winstrate -Pic: Expert F -Gender: Female -Music: Intense -Double Battle: No -AI: Basic Trainer - -Meditite -Level: 18 -IVs: 24 HP / 24 Atk / 24 Def / 24 SpA / 24 SpD / 24 Spe -- High Jump Kick -- Meditate -- Confusion -- Detect - -=== TRAINER_SHELBY_1 === -Name: 宫子 -Class: Expert -Pic: Expert F -Gender: Female -Music: Intense -Double Battle: No -AI: Basic Trainer - -Meditite -Level: 21 -IVs: 24 HP / 24 Atk / 24 Def / 24 SpA / 24 SpD / 24 Spe - -Makuhita -Level: 21 -IVs: 24 HP / 24 Atk / 24 Def / 24 SpA / 24 SpD / 24 Spe - -=== TRAINER_SHELBY_2 === -Name: 宫子 -Class: Expert -Pic: Expert F -Gender: Female -Music: Intense -Double Battle: No -AI: Basic Trainer - -Meditite -Level: 30 -IVs: 25 HP / 25 Atk / 25 Def / 25 SpA / 25 SpD / 25 Spe - -Makuhita -Level: 30 -IVs: 25 HP / 25 Atk / 25 Def / 25 SpA / 25 SpD / 25 Spe - -=== TRAINER_SHELBY_3 === -Name: 宫子 -Class: Expert -Pic: Expert F -Gender: Female -Music: Intense -Double Battle: No -AI: Basic Trainer - -Medicham -Level: 33 -IVs: 26 HP / 26 Atk / 26 Def / 26 SpA / 26 SpD / 26 Spe - -Hariyama -Level: 33 -IVs: 26 HP / 26 Atk / 26 Def / 26 SpA / 26 SpD / 26 Spe - -=== TRAINER_SHELBY_4 === -Name: 宫子 -Class: Expert -Pic: Expert F -Gender: Female -Music: Intense -Double Battle: No -AI: Basic Trainer - -Medicham -Level: 36 -IVs: 27 HP / 27 Atk / 27 Def / 27 SpA / 27 SpD / 27 Spe - -Hariyama -Level: 36 -IVs: 27 HP / 27 Atk / 27 Def / 27 SpA / 27 SpD / 27 Spe - -=== TRAINER_SHELBY_5 === -Name: 宫子 -Class: Expert -Pic: Expert F -Gender: Female -Music: Intense -Double Battle: No -AI: Basic Trainer - -Medicham -Level: 39 -IVs: 29 HP / 29 Atk / 29 Def / 29 SpA / 29 SpD / 29 Spe - -Hariyama -Level: 39 -IVs: 29 HP / 29 Atk / 29 Def / 29 SpA / 29 SpD / 29 Spe - -=== TRAINER_CALVIN_1 === -Name: 和树 -Class: Youngster -Pic: Youngster -Gender: Male -Music: Male -Double Battle: No -AI: Check Bad Move - -Poochyena -Level: 5 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_BILLY === -Name: 庆太 -Class: Youngster -Pic: Youngster -Gender: Male -Music: Male -Double Battle: No -AI: Check Bad Move - -Zigzagoon -Level: 5 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Seedot -Level: 7 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_JOSH === -Name: 太郎 -Class: Youngster -Pic: Youngster -Gender: Male -Music: Male -Double Battle: No -AI: Check Bad Move - -Geodude -Level: 10 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe -- Tackle - -=== TRAINER_TOMMY === -Name: 克雄 -Class: Youngster -Pic: Youngster -Gender: Male -Music: Male -Double Battle: No -AI: Check Bad Move - -Geodude -Level: 8 -IVs: 13 HP / 13 Atk / 13 Def / 13 SpA / 13 SpD / 13 Spe - -Geodude -Level: 8 -IVs: 14 HP / 14 Atk / 14 Def / 14 SpA / 14 SpD / 14 Spe - -=== TRAINER_JOEY === -Name: 武雄 -Class: Youngster -Pic: Youngster -Gender: Male -Music: Male -Double Battle: No -AI: Check Bad Move - -Machop -Level: 9 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_BEN === -Name: 弘人 -Class: Youngster -Pic: Youngster -Gender: Male -Music: Male -Double Battle: No -AI: Check Bad Move - -Zigzagoon -Level: 17 -IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe -- Headbutt -- Sand Attack -- Growl -- Thunderbolt - -Gulpin -Level: 17 -IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe -- Amnesia -- Sludge -- Yawn -- Pound - -=== TRAINER_QUINCY === -Name: 忠俊 -Class: Cooltrainer -Pic: Cooltrainer M -Gender: Male -Music: Cool -Items: Full Restore -Double Battle: No -AI: Basic Trainer - -Slaking -Level: 43 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe -- Attract -- Ice Beam -- Thunderbolt -- Flamethrower - -Dusclops -Level: 43 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe -- Skill Swap -- Protect -- Will O Wisp -- Toxic - -=== TRAINER_KATELYNN === -Name: 铃香 -Class: Cooltrainer -Pic: Cooltrainer F -Gender: Female -Music: Cool -Items: Full Restore -Double Battle: No -AI: Basic Trainer - -Gardevoir -Level: 43 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe -- Skill Swap -- Psychic -- Thunderbolt -- Calm Mind - -Slaking -Level: 43 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe -- Earthquake -- Shadow Ball -- Aerial Ace -- Brick Break - -=== TRAINER_JAYLEN === -Name: 雅之 -Class: Youngster -Pic: Youngster -Gender: Male -Music: Male -Double Battle: No -AI: Check Bad Move - -Trapinch -Level: 19 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_DILLON === -Name: 义人 -Class: Youngster -Pic: Youngster -Gender: Male -Music: Male -Double Battle: No -AI: Check Bad Move - -Aron -Level: 19 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_CALVIN_2 === -Name: 和树 -Class: Youngster -Pic: Youngster -Gender: Male -Music: Male -Double Battle: No -AI: Check Bad Move - -Mightyena -Level: 27 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe - -=== TRAINER_CALVIN_3 === -Name: 和树 -Class: Youngster -Pic: Youngster -Gender: Male -Music: Male -Double Battle: No -AI: Check Bad Move - -Swellow -Level: 28 -IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe - -Mightyena -Level: 30 -IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe - -=== TRAINER_CALVIN_4 === -Name: 和树 -Class: Youngster -Pic: Youngster -Gender: Male -Music: Male -Double Battle: No -AI: Check Bad Move - -Swellow -Level: 31 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe - -Linoone -Level: 29 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe - -Mightyena -Level: 33 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe - -=== TRAINER_CALVIN_5 === -Name: 和树 -Class: Youngster -Pic: Youngster -Gender: Male -Music: Male -Double Battle: No -AI: Check Bad Move - -Swellow -Level: 34 -IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe - -Linoone -Level: 32 -IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe - -Mightyena -Level: 36 -IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe - -=== TRAINER_EDDIE === -Name: 康幸 -Class: Youngster -Pic: Youngster -Gender: Male -Music: Male -Double Battle: No -AI: Check Bad Move - -Zigzagoon -Level: 14 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Zigzagoon -Level: 16 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_ALLEN === -Name: 勇 -Class: Youngster -Pic: Youngster -Gender: Male -Music: Male -Double Battle: No -AI: Check Bad Move - -Zigzagoon -Level: 4 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Taillow -Level: 3 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_TIMMY === -Name: 真悟 -Class: Youngster -Pic: Youngster -Gender: Male -Music: Male -Double Battle: No -AI: Check Bad Move - -Aron -Level: 15 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Electrike -Level: 13 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_WALLACE === -Name: 米可利 -Class: Champion -Pic: Champion Wallace -Gender: Male -Music: Male -Items: Full Restore / Full Restore / Full Restore / Full Restore -Double Battle: No -AI: Basic Trainer -Mugshot: Yellow - -Wailord -Level: 57 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Rain Dance -- Water Spout -- Double Edge -- Blizzard - -Tentacruel -Level: 55 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Toxic -- Hydro Pump -- Sludge Bomb -- Ice Beam - -Ludicolo -Level: 56 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Giga Drain -- Surf -- Leech Seed -- Double Team - -Whiscash -Level: 56 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Earthquake -- Surf -- Amnesia -- Hyper Beam - -Gyarados -Level: 56 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Dragon Dance -- Earthquake -- Hyper Beam -- Surf - -Milotic @ Sitrus Berry -Level: 58 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Recover -- Surf -- Ice Beam -- Toxic - -=== TRAINER_ANDREW === -Name: 胜典 -Class: Fisherman -Pic: Fisherman -Gender: Male -Music: Hiker -Double Battle: No -AI: Check Bad Move - -Magikarp -Level: 5 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Tentacool -Level: 10 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Magikarp -Level: 15 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_IVAN === -Name: 佳孝 -Class: Fisherman -Pic: Fisherman -Gender: Male -Music: Hiker -Double Battle: No -AI: Check Bad Move - -Magikarp -Level: 5 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Magikarp -Level: 6 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Magikarp -Level: 7 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_CLAUDE === -Name: 秀之 -Class: Fisherman -Pic: Fisherman -Gender: Male -Music: Hiker -Double Battle: No -AI: Check Bad Move - -Magikarp -Level: 16 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Goldeen -Level: 17 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Barboach -Level: 18 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_ELLIOT_1 === -Name: 明彦 -Class: Fisherman -Pic: Fisherman -Gender: Male -Music: Hiker -Double Battle: No -AI: Check Bad Move - -Magikarp -Level: 10 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Tentacool -Level: 7 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Magikarp -Level: 10 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_NED === -Name: 友和 -Class: Fisherman -Pic: Fisherman -Gender: Male -Music: Hiker -Double Battle: No -AI: Check Bad Move - -Tentacool -Level: 11 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe - -=== TRAINER_DALE === -Name: 贵文 -Class: Fisherman -Pic: Fisherman -Gender: Male -Music: Hiker -Double Battle: No -AI: Check Bad Move - -Tentacool -Level: 11 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Wailmer -Level: 14 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Tentacool -Level: 11 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Wailmer -Level: 14 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_NOLAN === -Name: 孝则 -Class: Fisherman -Pic: Fisherman -Gender: Male -Music: Hiker -Double Battle: No -AI: Check Bad Move - -Barboach -Level: 19 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_BARNY === -Name: 和彦 -Class: Fisherman -Pic: Fisherman -Gender: Male -Music: Hiker -Double Battle: No -AI: Check Bad Move - -Tentacool -Level: 25 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Carvanha -Level: 25 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_WADE === -Name: 绩 -Class: Fisherman -Pic: Fisherman -Gender: Male -Music: Hiker -Double Battle: No -AI: Check Bad Move - -Tentacool -Level: 16 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_CARTER === -Name: 高弘 -Class: Fisherman -Pic: Fisherman -Gender: Male -Music: Hiker -Double Battle: No -AI: Check Bad Move - -Wailmer -Level: 25 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe - -Tentacruel -Level: 25 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe - -=== TRAINER_ELLIOT_2 === -Name: 明彦 -Class: Fisherman -Pic: Fisherman -Gender: Male -Music: Hiker -Double Battle: No -AI: Check Bad Move - -Tentacool -Level: 24 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe - -Gyarados -Level: 27 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe - -Gyarados -Level: 27 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe - -=== TRAINER_ELLIOT_3 === -Name: 明彦 -Class: Fisherman -Pic: Fisherman -Gender: Male -Music: Hiker -Double Battle: No -AI: Check Bad Move - -Gyarados -Level: 29 -IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe - -Carvanha -Level: 26 -IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe - -Tentacool -Level: 26 -IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe - -Gyarados -Level: 29 -IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe - -=== TRAINER_ELLIOT_4 === -Name: 明彦 -Class: Fisherman -Pic: Fisherman -Gender: Male -Music: Hiker -Double Battle: No -AI: Check Bad Move - -Gyarados -Level: 31 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe - -Carvanha -Level: 30 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe - -Tentacruel -Level: 30 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe - -Gyarados -Level: 31 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe - -=== TRAINER_ELLIOT_5 === -Name: 明彦 -Class: Fisherman -Pic: Fisherman -Gender: Male -Music: Hiker -Double Battle: No -AI: Check Bad Move / Try To Faint - -Gyarados -Level: 33 -IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe - -Sharpedo -Level: 33 -IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe - -Gyarados -Level: 33 -IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe - -Tentacruel -Level: 35 -IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe - -=== TRAINER_RONALD === -Name: 和雄 -Class: Fisherman -Pic: Fisherman -Gender: Male -Music: Hiker -Double Battle: No -AI: Check Bad Move - -Magikarp -Level: 19 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Gyarados -Level: 21 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Gyarados -Level: 23 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Gyarados -Level: 26 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Gyarados -Level: 30 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Gyarados -Level: 35 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_JACOB === -Name: 进 -Class: Triathlete -Pic: Cycling Triathlete M -Gender: Male -Music: Male -Double Battle: No -AI: Check Bad Move - -Voltorb -Level: 6 -IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe - -Voltorb -Level: 6 -IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe - -Magnemite -Level: 14 -IVs: 24 HP / 24 Atk / 24 Def / 24 SpA / 24 SpD / 24 Spe - -=== TRAINER_ANTHONY === -Name: 俊介 -Class: Triathlete -Pic: Cycling Triathlete M -Gender: Male -Music: Male -Double Battle: No -AI: Check Bad Move - -Magnemite -Level: 14 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Magnemite -Level: 14 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_BENJAMIN_1 === -Name: 英明 -Class: Triathlete -Pic: Cycling Triathlete M -Gender: Male -Music: Male -Double Battle: No -AI: Check Bad Move - -Magnemite -Level: 16 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_BENJAMIN_2 === -Name: 英明 -Class: Triathlete -Pic: Cycling Triathlete M -Gender: Male -Music: Male -Double Battle: No -AI: Check Bad Move - -Magnemite -Level: 30 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe - -=== TRAINER_BENJAMIN_3 === -Name: 英明 -Class: Triathlete -Pic: Cycling Triathlete M -Gender: Male -Music: Male -Double Battle: No -AI: Check Bad Move - -Magnemite -Level: 33 -IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe - -=== TRAINER_BENJAMIN_4 === -Name: 英明 -Class: Triathlete -Pic: Cycling Triathlete M -Gender: Male -Music: Male -Double Battle: No -AI: Check Bad Move - -Magneton -Level: 36 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe - -=== TRAINER_BENJAMIN_5 === -Name: 英明 -Class: Triathlete -Pic: Cycling Triathlete M -Gender: Male -Music: Male -Double Battle: No -AI: Check Bad Move - -Magneton -Level: 39 -IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe - -=== TRAINER_ABIGAIL_1 === -Name: 翔子 -Class: Triathlete -Pic: Cycling Triathlete F -Gender: Female -Music: Female -Double Battle: No -AI: Check Bad Move - -Magnemite -Level: 16 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_JASMINE === -Name: 秀美 -Class: Triathlete -Pic: Cycling Triathlete F -Gender: Female -Music: Female -Double Battle: No -AI: Check Bad Move - -Magnemite -Level: 14 -IVs: 9 HP / 9 Atk / 9 Def / 9 SpA / 9 SpD / 9 Spe - -Magnemite -Level: 14 -IVs: 9 HP / 9 Atk / 9 Def / 9 SpA / 9 SpD / 9 Spe - -Voltorb -Level: 6 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_ABIGAIL_2 === -Name: 翔子 -Class: Triathlete -Pic: Cycling Triathlete F -Gender: Female -Music: Female -Double Battle: No -AI: Check Bad Move - -Magnemite -Level: 28 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe - -=== TRAINER_ABIGAIL_3 === -Name: 翔子 -Class: Triathlete -Pic: Cycling Triathlete F -Gender: Female -Music: Female -Double Battle: No -AI: Check Bad Move - -Magnemite -Level: 31 -IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe - -=== TRAINER_ABIGAIL_4 === -Name: 翔子 -Class: Triathlete -Pic: Cycling Triathlete F -Gender: Female -Music: Female -Double Battle: No -AI: Check Bad Move - -Magneton -Level: 34 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe - -=== TRAINER_ABIGAIL_5 === -Name: 翔子 -Class: Triathlete -Pic: Cycling Triathlete F -Gender: Female -Music: Female -Double Battle: No -AI: Check Bad Move - -Magneton -Level: 37 -IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe - -=== TRAINER_DYLAN_1 === -Name: 阿毅 -Class: Triathlete -Pic: Running Triathlete M -Gender: Male -Music: Male -Double Battle: No -AI: Check Bad Move - -Doduo -Level: 17 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_DYLAN_2 === -Name: 阿毅 -Class: Triathlete -Pic: Running Triathlete M -Gender: Male -Music: Male -Double Battle: No -AI: Check Bad Move - -Doduo -Level: 28 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe - -=== TRAINER_DYLAN_3 === -Name: 阿毅 -Class: Triathlete -Pic: Running Triathlete M -Gender: Male -Music: Male -Double Battle: No -AI: Check Bad Move - -Doduo -Level: 31 -IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe - -=== TRAINER_DYLAN_4 === -Name: 阿毅 -Class: Triathlete -Pic: Running Triathlete M -Gender: Male -Music: Male -Double Battle: No -AI: Check Bad Move - -Dodrio -Level: 34 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe - -=== TRAINER_DYLAN_5 === -Name: 阿毅 -Class: Triathlete -Pic: Running Triathlete M -Gender: Male -Music: Male -Double Battle: No -AI: Check Bad Move - -Dodrio -Level: 37 -IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe - -=== TRAINER_MARIA_1 === -Name: 佐枝子 -Class: Triathlete -Pic: Running Triathlete F -Gender: Female -Music: Female -Double Battle: No -AI: Check Bad Move - -Doduo -Level: 17 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_MARIA_2 === -Name: 佐枝子 -Class: Triathlete -Pic: Running Triathlete F -Gender: Female -Music: Female -Double Battle: No -AI: Check Bad Move - -Doduo -Level: 28 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe - -=== TRAINER_MARIA_3 === -Name: 佐枝子 -Class: Triathlete -Pic: Running Triathlete F -Gender: Female -Music: Female -Double Battle: No -AI: Check Bad Move - -Doduo -Level: 31 -IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe - -=== TRAINER_MARIA_4 === -Name: 佐枝子 -Class: Triathlete -Pic: Running Triathlete F -Gender: Female -Music: Female -Double Battle: No -AI: Check Bad Move - -Dodrio -Level: 34 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe - -=== TRAINER_MARIA_5 === -Name: 佐枝子 -Class: Triathlete -Pic: Running Triathlete F -Gender: Female -Music: Female -Double Battle: No -AI: Check Bad Move - -Dodrio -Level: 37 -IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe - -=== TRAINER_CAMDEN === -Name: 茂治 -Class: Triathlete -Pic: Swimming Triathlete M -Gender: Male -Music: Swimmer -Double Battle: No -AI: Check Bad Move - -Staryu -Level: 33 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Staryu -Level: 33 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_DEMETRIUS === -Name: 文武 -Class: Youngster -Pic: Youngster -Gender: Male -Music: Male -Double Battle: No -AI: Check Bad Move - -Zigzagoon -Level: 25 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Electrike -Level: 25 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_ISAIAH_1 === -Name: 英辅 -Class: Triathlete -Pic: Swimming Triathlete M -Gender: Male -Music: Swimmer -Double Battle: No -AI: Check Bad Move - -Staryu -Level: 35 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_PABLO_1 === -Name: 靖宏 -Class: Triathlete -Pic: Swimming Triathlete M -Gender: Male -Music: Swimmer -Double Battle: No -AI: Check Bad Move - -Staryu -Level: 33 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Staryu -Level: 33 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_CHASE === -Name: 正吾 -Class: Triathlete -Pic: Swimming Triathlete M -Gender: Male -Music: Swimmer -Double Battle: No -AI: Check Bad Move - -Wingull -Level: 26 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Staryu -Level: 34 -IVs: 9 HP / 9 Atk / 9 Def / 9 SpA / 9 SpD / 9 Spe - -=== TRAINER_ISAIAH_2 === -Name: 英辅 -Class: Triathlete -Pic: Swimming Triathlete M -Gender: Male -Music: Swimmer -Double Battle: No -AI: Check Bad Move - -Staryu -Level: 39 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe - -=== TRAINER_ISAIAH_3 === -Name: 英辅 -Class: Triathlete -Pic: Swimming Triathlete M -Gender: Male -Music: Swimmer -Double Battle: No -AI: Check Bad Move - -Staryu -Level: 42 -IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe - -=== TRAINER_ISAIAH_4 === -Name: 英辅 -Class: Triathlete -Pic: Swimming Triathlete M -Gender: Male -Music: Swimmer -Double Battle: No -AI: Check Bad Move - -Starmie -Level: 45 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe - -=== TRAINER_ISAIAH_5 === -Name: 英辅 -Class: Triathlete -Pic: Swimming Triathlete M -Gender: Male -Music: Swimmer -Double Battle: No -AI: Check Bad Move - -Starmie -Level: 48 -IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe - -=== TRAINER_ISOBEL === -Name: 绢江 -Class: Triathlete -Pic: Swimming Triathlete F -Gender: Female -Music: Swimmer -Double Battle: No -AI: Check Bad Move - -Staryu -Level: 34 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_DONNY === -Name: 由鹤 -Class: Triathlete -Pic: Swimming Triathlete F -Gender: Female -Music: Swimmer -Double Battle: No -AI: Check Bad Move - -Wingull -Level: 26 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Staryu -Level: 34 -IVs: 19 HP / 19 Atk / 19 Def / 19 SpA / 19 SpD / 19 Spe - -=== TRAINER_TALIA === -Name: 美佳子 -Class: Triathlete -Pic: Swimming Triathlete F -Gender: Female -Music: Swimmer -Double Battle: No -AI: Check Bad Move - -Staryu -Level: 34 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_KATELYN_1 === -Name: 夏美 -Class: Triathlete -Pic: Swimming Triathlete F -Gender: Female -Music: Swimmer -Double Battle: No -AI: Check Bad Move - -Staryu -Level: 35 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_ALLISON === -Name: 千慧 -Class: Triathlete -Pic: Swimming Triathlete F -Gender: Female -Music: Swimmer -Double Battle: No -AI: Check Bad Move - -Wingull -Level: 27 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Staryu -Level: 33 -IVs: 29 HP / 29 Atk / 29 Def / 29 SpA / 29 SpD / 29 Spe - -=== TRAINER_KATELYN_2 === -Name: 夏美 -Class: Triathlete -Pic: Swimming Triathlete F -Gender: Female -Music: Swimmer -Double Battle: No -AI: Check Bad Move - -Staryu -Level: 39 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe - -=== TRAINER_KATELYN_3 === -Name: 夏美 -Class: Triathlete -Pic: Swimming Triathlete F -Gender: Female -Music: Swimmer -Double Battle: No -AI: Check Bad Move - -Staryu -Level: 42 -IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe - -=== TRAINER_KATELYN_4 === -Name: 夏美 -Class: Triathlete -Pic: Swimming Triathlete F -Gender: Female -Music: Swimmer -Double Battle: No -AI: Check Bad Move - -Starmie -Level: 45 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe - -=== TRAINER_KATELYN_5 === -Name: 夏美 -Class: Triathlete -Pic: Swimming Triathlete F -Gender: Female -Music: Swimmer -Double Battle: No -AI: Check Bad Move - -Starmie -Level: 48 -IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe - -=== TRAINER_NICOLAS_1 === -Name: 武 -Class: Dragon Tamer -Pic: Dragon Tamer -Gender: Male -Music: Intense -Double Battle: No -AI: Check Bad Move - -Altaria -Level: 37 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -Altaria -Level: 37 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -=== TRAINER_NICOLAS_2 === -Name: 武 -Class: Dragon Tamer -Pic: Dragon Tamer -Gender: Male -Music: Intense -Double Battle: No -AI: Check Bad Move - -Altaria -Level: 41 -IVs: 13 HP / 13 Atk / 13 Def / 13 SpA / 13 SpD / 13 Spe - -Altaria -Level: 41 -IVs: 13 HP / 13 Atk / 13 Def / 13 SpA / 13 SpD / 13 Spe - -=== TRAINER_NICOLAS_3 === -Name: 武 -Class: Dragon Tamer -Pic: Dragon Tamer -Gender: Male -Music: Intense -Double Battle: No -AI: Check Bad Move - -Altaria -Level: 44 -IVs: 14 HP / 14 Atk / 14 Def / 14 SpA / 14 SpD / 14 Spe - -Altaria -Level: 44 -IVs: 14 HP / 14 Atk / 14 Def / 14 SpA / 14 SpD / 14 Spe - -=== TRAINER_NICOLAS_4 === -Name: 武 -Class: Dragon Tamer -Pic: Dragon Tamer -Gender: Male -Music: Intense -Double Battle: No -AI: Check Bad Move - -Bagon -Level: 46 -IVs: 15 HP / 15 Atk / 15 Def / 15 SpA / 15 SpD / 15 Spe - -Altaria -Level: 46 -IVs: 15 HP / 15 Atk / 15 Def / 15 SpA / 15 SpD / 15 Spe - -Altaria -Level: 46 -IVs: 15 HP / 15 Atk / 15 Def / 15 SpA / 15 SpD / 15 Spe - -=== TRAINER_NICOLAS_5 === -Name: 武 -Class: Dragon Tamer -Pic: Dragon Tamer -Gender: Male -Music: Intense -Double Battle: No -AI: Check Bad Move - -Altaria -Level: 49 -IVs: 17 HP / 17 Atk / 17 Def / 17 SpA / 17 SpD / 17 Spe - -Altaria -Level: 49 -IVs: 17 HP / 17 Atk / 17 Def / 17 SpA / 17 SpD / 17 Spe - -Shelgon @ Dragon Fang -Level: 49 -IVs: 17 HP / 17 Atk / 17 Def / 17 SpA / 17 SpD / 17 Spe - -=== TRAINER_AARON === -Name: 龙马 -Class: Dragon Tamer -Pic: Dragon Tamer -Gender: Male -Music: Intense -Double Battle: No -AI: Check Bad Move - -Bagon -Level: 34 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Dragon Breath -- Headbutt -- Focus Energy -- Ember - -=== TRAINER_PERRY === -Name: 清彦 -Class: Bird Keeper -Pic: Bird Keeper -Gender: Male -Music: Cool -Double Battle: No -AI: Check Bad Move - -Wingull -Level: 26 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_HUGH === -Name: 拓海 -Class: Bird Keeper -Pic: Bird Keeper -Gender: Male -Music: Cool -Double Battle: No -AI: Check Bad Move - -Wingull -Level: 25 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Tropius -Level: 25 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_PHIL === -Name: 骏平 -Class: Bird Keeper -Pic: Bird Keeper -Gender: Male -Music: Cool -Double Battle: No -AI: Check Bad Move - -Swellow -Level: 26 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_JARED === -Name: 英治 -Class: Bird Keeper -Pic: Bird Keeper -Gender: Male -Music: Cool -Double Battle: No -AI: Check Bad Move - -Doduo -Level: 27 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -Skarmory -Level: 27 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -Tropius -Level: 27 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -=== TRAINER_HUMBERTO === -Name: 光明 -Class: Bird Keeper -Pic: Bird Keeper -Gender: Male -Music: Cool -Double Battle: No -AI: Check Bad Move - -Skarmory -Level: 30 -IVs: 30 HP / 30 Atk / 30 Def / 30 SpA / 30 SpD / 30 Spe - -=== TRAINER_PRESLEY === -Name: 直宏 -Class: Bird Keeper -Pic: Bird Keeper -Gender: Male -Music: Cool -Double Battle: No -AI: Check Bad Move - -Tropius -Level: 33 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Xatu -Level: 33 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_EDWARDO === -Name: 上田 -Class: Bird Keeper -Pic: Bird Keeper -Gender: Male -Music: Cool -Double Battle: No -AI: Check Bad Move - -Doduo -Level: 29 -IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe - -Pelipper -Level: 29 -IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe - -=== TRAINER_COLIN === -Name: 森一 -Class: Bird Keeper -Pic: Bird Keeper -Gender: Male -Music: Cool -Double Battle: No -AI: Check Bad Move - -Wingull -Level: 28 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Natu -Level: 28 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_ROBERT_1 === -Name: 阿翼 -Class: Bird Keeper -Pic: Bird Keeper -Gender: Male -Music: Cool -Double Battle: No -AI: Check Bad Move - -Swablu -Level: 29 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_BENNY === -Name: 彰正 -Class: Bird Keeper -Pic: Bird Keeper -Gender: Male -Music: Cool -Double Battle: No -AI: Check Bad Move - -Swellow -Level: 36 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Pelipper -Level: 36 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Xatu -Level: 36 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_CHESTER === -Name: 大使 -Class: Bird Keeper -Pic: Bird Keeper -Gender: Male -Music: Cool -Double Battle: No -AI: Check Bad Move - -Taillow -Level: 25 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Swellow -Level: 25 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_ROBERT_2 === -Name: 阿翼 -Class: Bird Keeper -Pic: Bird Keeper -Gender: Male -Music: Cool -Double Battle: No -AI: Check Bad Move - -Natu -Level: 32 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe - -Swablu -Level: 32 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe - -=== TRAINER_ROBERT_3 === -Name: 阿翼 -Class: Bird Keeper -Pic: Bird Keeper -Gender: Male -Music: Cool -Double Battle: No -AI: Check Bad Move - -Natu -Level: 35 -IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe - -Altaria -Level: 35 -IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe - -=== TRAINER_ROBERT_4 === -Name: 阿翼 -Class: Bird Keeper -Pic: Bird Keeper -Gender: Male -Music: Cool -Double Battle: No -AI: Check Bad Move - -Natu -Level: 38 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe - -Altaria -Level: 38 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe - -=== TRAINER_ROBERT_5 === -Name: 阿翼 -Class: Bird Keeper -Pic: Bird Keeper -Gender: Male -Music: Cool -Double Battle: No -AI: Check Bad Move - -Altaria -Level: 41 -IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe - -Xatu -Level: 41 -IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe - -=== TRAINER_ALEX === -Name: 正嗣 -Class: Bird Keeper -Pic: Bird Keeper -Gender: Male -Music: Cool -Double Battle: No -AI: Check Bad Move - -Natu -Level: 33 -IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe - -Swellow -Level: 33 -IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe - -=== TRAINER_BECK === -Name: 俊明 -Class: Bird Keeper -Pic: Bird Keeper -Gender: Male -Music: Cool -Double Battle: No -AI: Check Bad Move - -Tropius -Level: 34 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_YASU === -Name: 广宣 -Class: Ninja Boy -Pic: Ninja Boy -Gender: Male -Music: Suspicious -Double Battle: No -AI: Check Bad Move / Try To Faint - -Ninjask -Level: 26 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_TAKASHI === -Name: 四郎 -Class: Ninja Boy -Pic: Ninja Boy -Gender: Male -Music: Suspicious -Double Battle: No -AI: Check Bad Move / Try To Faint - -Ninjask -Level: 25 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Koffing -Level: 25 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_DIANNE === -Name: 心 -Class: Cooltrainer -Pic: Cooltrainer F -Gender: Female -Music: Cool -Items: Full Restore -Double Battle: No - -Claydol -Level: 43 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe -- Skill Swap -- Earthquake - -Lanturn -Level: 43 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe -- Thunderbolt -- Earthquake - -=== TRAINER_JANI === -Name: 麻美 -Class: Tuber F -Pic: Tuber F -Gender: Female -Music: Girl -Double Battle: No - -Marill -Level: 26 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_LAO_1 === -Name: 金次 -Class: Ninja Boy -Pic: Ninja Boy -Gender: Male -Music: Suspicious -Double Battle: No - -Koffing -Level: 17 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe -- Poison Gas -- Tackle -- Smog -- Self Destruct - -Koffing -Level: 17 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe -- Poison Gas -- Tackle -- Smog -- Self Destruct - -Koffing -Level: 17 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe -- Poison Gas -- Tackle -- Sludge -- Self Destruct - -=== TRAINER_LUNG === -Name: 村正 -Class: Ninja Boy -Pic: Ninja Boy -Gender: Male -Music: Suspicious -Double Battle: No - -Koffing -Level: 18 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Ninjask -Level: 18 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_LAO_2 === -Name: 金次 -Class: Ninja Boy -Pic: Ninja Boy -Gender: Male -Music: Suspicious -Double Battle: No - -Koffing -Level: 24 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe -- Poison Gas -- Tackle -- Sludge -- Self Destruct - -Koffing -Level: 24 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe -- Poison Gas -- Tackle -- Sludge - -Koffing -Level: 24 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe -- Poison Gas -- Tackle -- Sludge -- Self Destruct - -Koffing -Level: 26 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe -- Tackle -- Sludge - -=== TRAINER_LAO_3 === -Name: 金次 -Class: Ninja Boy -Pic: Ninja Boy -Gender: Male -Music: Suspicious -Double Battle: No - -Koffing -Level: 27 -IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe -- Poison Gas -- Tackle -- Sludge -- Self Destruct - -Koffing -Level: 27 -IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe -- Poison Gas -- Tackle -- Sludge -- Self Destruct - -Koffing -Level: 27 -IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe -- Poison Gas -- Tackle -- Sludge - -Koffing -Level: 29 -IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe -- Tackle -- Sludge - -=== TRAINER_LAO_4 === -Name: 金次 -Class: Ninja Boy -Pic: Ninja Boy -Gender: Male -Music: Suspicious -Double Battle: No - -Koffing -Level: 30 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe -- Poison Gas -- Tackle -- Sludge - -Koffing -Level: 30 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe -- Poison Gas -- Tackle -- Sludge - -Koffing -Level: 30 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe -- Poison Gas -- Tackle -- Sludge - -Koffing -Level: 32 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe -- Tackle -- Sludge - -=== TRAINER_LAO_5 === -Name: 金次 -Class: Ninja Boy -Pic: Ninja Boy -Gender: Male -Music: Suspicious -Double Battle: No - -Koffing -Level: 33 -IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe -- Poison Gas -- Tackle -- Sludge - -Koffing -Level: 33 -IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe -- Poison Gas -- Tackle -- Sludge -- Self Destruct - -Koffing -Level: 33 -IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe -- Poison Gas -- Tackle -- Sludge -- Self Destruct - -Weezing @ Smoke Ball -Level: 35 -IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe -- Tackle -- Sludge - -=== TRAINER_JOCELYN === -Name: 小忍 -Class: Battle Girl -Pic: Battle Girl -Gender: Female -Music: Intense -Double Battle: No -AI: Check Bad Move - -Meditite -Level: 13 -IVs: 15 HP / 15 Atk / 15 Def / 15 SpA / 15 SpD / 15 Spe - -=== TRAINER_LAURA === -Name: 美里 -Class: Battle Girl -Pic: Battle Girl -Gender: Female -Music: Intense -Double Battle: No -AI: Check Bad Move - -Meditite -Level: 13 -IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe - -=== TRAINER_CYNDY_1 === -Name: 由梨香 -Class: Battle Girl -Pic: Battle Girl -Gender: Female -Music: Intense -Double Battle: No -AI: Check Bad Move - -Meditite -Level: 18 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -Makuhita -Level: 18 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -=== TRAINER_CORA === -Name: 风华 -Class: Battle Girl -Pic: Battle Girl -Gender: Female -Music: Intense -Double Battle: No -AI: Check Bad Move - -Meditite -Level: 27 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -=== TRAINER_PAULA === -Name: 雏 -Class: Battle Girl -Pic: Battle Girl -Gender: Female -Music: Intense -Double Battle: No -AI: Check Bad Move - -Breloom -Level: 27 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -=== TRAINER_CYNDY_2 === -Name: 由梨香 -Class: Battle Girl -Pic: Battle Girl -Gender: Female -Music: Intense -Double Battle: No -AI: Check Bad Move - -Meditite -Level: 26 -IVs: 13 HP / 13 Atk / 13 Def / 13 SpA / 13 SpD / 13 Spe - -Makuhita -Level: 26 -IVs: 13 HP / 13 Atk / 13 Def / 13 SpA / 13 SpD / 13 Spe - -=== TRAINER_CYNDY_3 === -Name: 由梨香 -Class: Battle Girl -Pic: Battle Girl -Gender: Female -Music: Intense -Double Battle: No -AI: Check Bad Move - -Meditite -Level: 29 -IVs: 14 HP / 14 Atk / 14 Def / 14 SpA / 14 SpD / 14 Spe - -Makuhita -Level: 29 -IVs: 14 HP / 14 Atk / 14 Def / 14 SpA / 14 SpD / 14 Spe - -=== TRAINER_CYNDY_4 === -Name: 由梨香 -Class: Battle Girl -Pic: Battle Girl -Gender: Female -Music: Intense -Double Battle: No -AI: Check Bad Move - -Medicham -Level: 32 -IVs: 15 HP / 15 Atk / 15 Def / 15 SpA / 15 SpD / 15 Spe - -Hariyama -Level: 32 -IVs: 15 HP / 15 Atk / 15 Def / 15 SpA / 15 SpD / 15 Spe - -=== TRAINER_CYNDY_5 === -Name: 由梨香 -Class: Battle Girl -Pic: Battle Girl -Gender: Female -Music: Intense -Double Battle: No -AI: Check Bad Move - -Medicham -Level: 35 -IVs: 17 HP / 17 Atk / 17 Def / 17 SpA / 17 SpD / 17 Spe - -Hariyama -Level: 35 -IVs: 17 HP / 17 Atk / 17 Def / 17 SpA / 17 SpD / 17 Spe - -=== TRAINER_MADELINE_1 === -Name: 圆香 -Class: Parasol Lady -Pic: Parasol Lady -Gender: Female -Music: Female -Double Battle: No -AI: Check Bad Move - -Numel -Level: 19 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe -- Ember -- Tackle -- Magnitude -- Sunny Day - -=== TRAINER_CLARISSA === -Name: 美华 -Class: Parasol Lady -Pic: Parasol Lady -Gender: Female -Music: Female -Double Battle: No -AI: Check Bad Move - -Roselia -Level: 28 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Wailmer -Level: 28 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_ANGELICA === -Name: 浮江 -Class: Parasol Lady -Pic: Parasol Lady -Gender: Female -Music: Female -Double Battle: No -AI: Check Bad Move - -Castform -Level: 30 -IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe -- Rain Dance -- Weather Ball -- Thunder -- Water Pulse - -=== TRAINER_MADELINE_2 === -Name: 圆香 -Class: Parasol Lady -Pic: Parasol Lady -Gender: Female -Music: Female -Double Battle: No -AI: Check Bad Move - -Numel -Level: 29 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe -- Ember -- Tackle -- Magnitude -- Sunny Day - -=== TRAINER_MADELINE_3 === -Name: 圆香 -Class: Parasol Lady -Pic: Parasol Lady -Gender: Female -Music: Female -Double Battle: No -AI: Check Bad Move - -Numel -Level: 32 -IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe -- Ember -- Take Down -- Magnitude -- Sunny Day - -=== TRAINER_MADELINE_4 === -Name: 圆香 -Class: Parasol Lady -Pic: Parasol Lady -Gender: Female -Music: Female -Double Battle: No -AI: Check Bad Move - -Roselia -Level: 34 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe -- Leech Seed -- Mega Drain -- Grass Whistle -- Sunny Day - -Numel -Level: 34 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe -- Flamethrower -- Take Down -- Magnitude -- Sunny Day - -=== TRAINER_MADELINE_5 === -Name: 圆香 -Class: Parasol Lady -Pic: Parasol Lady -Gender: Female -Music: Female -Double Battle: No -AI: Check Bad Move - -Roselia -Level: 37 -IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe -- Leech Seed -- Giga Drain -- Solar Beam -- Sunny Day - -Camerupt -Level: 37 -IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe -- Flamethrower -- Take Down -- Earthquake -- Sunny Day - -=== TRAINER_BEVERLY === -Name: 夏树 -Class: Swimmer F -Pic: Swimmer F -Gender: Female -Music: Swimmer -Double Battle: No -AI: Check Bad Move - -Wingull -Level: 25 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Wailmer -Level: 25 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_IMANI === -Name: 真由佳 -Class: Swimmer F -Pic: Swimmer F -Gender: Female -Music: Swimmer -Double Battle: No -AI: Check Bad Move - -Marill -Level: 26 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_KYLA === -Name: 水羽 -Class: Swimmer F -Pic: Swimmer F -Gender: Female -Music: Swimmer -Double Battle: No -AI: Check Bad Move - -Wailmer -Level: 26 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_DENISE === -Name: 雅美 -Class: Swimmer F -Pic: Swimmer F -Gender: Female -Music: Swimmer -Double Battle: No -AI: Check Bad Move - -Wingull -Level: 25 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Goldeen -Level: 25 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_BETH === -Name: 纪香 -Class: Swimmer F -Pic: Swimmer F -Gender: Female -Music: Swimmer -Double Battle: No -AI: Check Bad Move - -Goldeen -Level: 26 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_TARA === -Name: 千寻 -Class: Swimmer F -Pic: Swimmer F -Gender: Female -Music: Swimmer -Double Battle: No -AI: Check Bad Move - -Horsea -Level: 25 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Marill -Level: 25 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_MISSY === -Name: 久美子 -Class: Swimmer F -Pic: Swimmer F -Gender: Female -Music: Swimmer -Double Battle: No -AI: Check Bad Move - -Goldeen -Level: 26 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_ALICE === -Name: 悦子 -Class: Swimmer F -Pic: Swimmer F -Gender: Female -Music: Swimmer -Double Battle: No -AI: Check Bad Move - -Goldeen -Level: 24 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Wingull -Level: 24 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Goldeen -Level: 24 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_JENNY_1 === -Name: 小渚 -Class: Swimmer F -Pic: Swimmer F -Gender: Female -Music: Swimmer -Double Battle: No -AI: Check Bad Move - -Wailmer -Level: 34 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_GRACE === -Name: 秋江 -Class: Swimmer F -Pic: Swimmer F -Gender: Female -Music: Swimmer -Double Battle: No -AI: Check Bad Move - -Marill -Level: 34 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_TANYA === -Name: 惠子 -Class: Swimmer F -Pic: Swimmer F -Gender: Female -Music: Swimmer -Double Battle: No -AI: Check Bad Move - -Luvdisc -Level: 34 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_SHARON === -Name: 彩华 -Class: Swimmer F -Pic: Swimmer F -Gender: Female -Music: Swimmer -Double Battle: No -AI: Check Bad Move - -Seaking -Level: 34 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_NIKKI === -Name: 静江 -Class: Swimmer F -Pic: Swimmer F -Gender: Female -Music: Swimmer -Double Battle: No -AI: Check Bad Move - -Marill -Level: 33 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Spheal -Level: 33 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_BRENDA === -Name: 辉美 -Class: Swimmer F -Pic: Swimmer F -Gender: Female -Music: Swimmer -Double Battle: No -AI: Check Bad Move - -Goldeen -Level: 34 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_KATIE === -Name: 富美江 -Class: Swimmer F -Pic: Swimmer F -Gender: Female -Music: Swimmer -Double Battle: No -AI: Check Bad Move - -Goldeen -Level: 33 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Spheal -Level: 33 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_SUSIE === -Name: 美咲 -Class: Swimmer F -Pic: Swimmer F -Gender: Female -Music: Swimmer -Double Battle: No -AI: Check Bad Move - -Luvdisc -Level: 34 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_KARA === -Name: 鞠绘 -Class: Swimmer F -Pic: Swimmer F -Gender: Female -Music: Swimmer -Double Battle: No -AI: Check Bad Move - -Seaking -Level: 34 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_DANA === -Name: 美雪 -Class: Swimmer F -Pic: Swimmer F -Gender: Female -Music: Swimmer -Double Battle: No -AI: Check Bad Move - -Azumarill -Level: 34 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_SIENNA === -Name: 郁子 -Class: Swimmer F -Pic: Swimmer F -Gender: Female -Music: Swimmer -Double Battle: No -AI: Check Bad Move - -Luvdisc -Level: 33 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Luvdisc -Level: 33 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_DEBRA === -Name: 里佳子 -Class: Swimmer F -Pic: Swimmer F -Gender: Female -Music: Swimmer -Double Battle: No -AI: Check Bad Move - -Seaking -Level: 34 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_LINDA === -Name: 春美 -Class: Swimmer F -Pic: Swimmer F -Gender: Female -Music: Swimmer -Double Battle: No -AI: Check Bad Move - -Horsea -Level: 33 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Seadra -Level: 33 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_KAYLEE === -Name: 多可 -Class: Swimmer F -Pic: Swimmer F -Gender: Female -Music: Swimmer -Double Battle: No -AI: Check Bad Move - -Lanturn -Level: 34 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Pelipper -Level: 34 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_LAUREL === -Name: 园子 -Class: Swimmer F -Pic: Swimmer F -Gender: Female -Music: Swimmer -Double Battle: No -AI: Check Bad Move - -Luvdisc -Level: 33 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Luvdisc -Level: 33 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_CARLEE === -Name: 国子 -Class: Swimmer F -Pic: Swimmer F -Gender: Female -Music: Swimmer -Double Battle: No -AI: Check Bad Move - -Seaking -Level: 35 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_JENNY_2 === -Name: 小渚 -Class: Swimmer F -Pic: Swimmer F -Gender: Female -Music: Swimmer -Double Battle: No -AI: Check Bad Move - -Wailmer -Level: 38 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_JENNY_3 === -Name: 小渚 -Class: Swimmer F -Pic: Swimmer F -Gender: Female -Music: Swimmer -Double Battle: No -AI: Check Bad Move - -Wailmer -Level: 41 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_JENNY_4 === -Name: 小渚 -Class: Swimmer F -Pic: Swimmer F -Gender: Female -Music: Swimmer -Double Battle: No -AI: Check Bad Move - -Staryu -Level: 43 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Wailmer -Level: 43 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_JENNY_5 === -Name: 小渚 -Class: Swimmer F -Pic: Swimmer F -Gender: Female -Music: Swimmer -Double Battle: No -AI: Check Bad Move - -Luvdisc -Level: 45 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Wailmer -Level: 45 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Starmie -Level: 45 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_HEIDI === -Name: 千佳子 -Class: Picnicker -Pic: Picnicker -Gender: Female -Music: Girl -Double Battle: No -AI: Check Bad Move - -Sandshrew -Level: 22 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe -- Dig -- Sand Attack -- Poison Sting -- Slash - -Baltoy -Level: 22 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe -- Rapid Spin -- Mud Slap -- Psybeam -- Rock Tomb - -=== TRAINER_BECKY === -Name: 爱弥 -Class: Picnicker -Pic: Picnicker -Gender: Female -Music: Girl -Double Battle: No -AI: Check Bad Move - -Sandshrew -Level: 22 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe -- Sand Attack -- Poison Sting -- Slash -- Dig - -Marill -Level: 22 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe -- Rollout -- Bubble Beam -- Tail Whip -- Defense Curl - -=== TRAINER_CAROL === -Name: 裕子 -Class: Picnicker -Pic: Picnicker -Gender: Female -Music: Girl -Double Battle: No -AI: Check Bad Move - -Taillow -Level: 17 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Lombre -Level: 17 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_NANCY === -Name: 皋月 -Class: Picnicker -Pic: Picnicker -Gender: Female -Music: Girl -Double Battle: No -AI: Check Bad Move - -Marill -Level: 18 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Lombre -Level: 18 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_MARTHA === -Name: 朋子 -Class: Picnicker -Pic: Picnicker -Gender: Female -Music: Girl -Double Battle: No -AI: Check Bad Move - -Skitty -Level: 23 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Swablu -Level: 23 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_DIANA_1 === -Name: 梢 -Class: Picnicker -Pic: Picnicker -Gender: Female -Music: Girl -Double Battle: No -AI: Check Bad Move - -Shroomish -Level: 19 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Oddish -Level: 19 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Swablu -Level: 19 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_CEDRIC === -Name: 义清 -Class: Psychic -Pic: Psychic M -Gender: Male -Music: Intense -Double Battle: No -AI: Check Bad Move - -Wobbuffet -Level: 32 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe -- Destiny Bond -- Safeguard -- Counter -- Mirror Coat - -=== TRAINER_IRENE === -Name: 水木 -Class: Picnicker -Pic: Picnicker -Gender: Female -Music: Girl -Double Battle: No -AI: Check Bad Move - -Shroomish -Level: 17 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Marill -Level: 17 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_DIANA_2 === -Name: 梢 -Class: Picnicker -Pic: Picnicker -Gender: Female -Music: Girl -Double Battle: No -AI: Check Bad Move - -Shroomish -Level: 25 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe - -Gloom -Level: 25 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe - -Swablu -Level: 25 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe - -=== TRAINER_DIANA_3 === -Name: 梢 -Class: Picnicker -Pic: Picnicker -Gender: Female -Music: Girl -Double Battle: No -AI: Check Bad Move - -Breloom -Level: 28 -IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe - -Gloom -Level: 28 -IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe - -Swablu -Level: 28 -IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe - -=== TRAINER_DIANA_4 === -Name: 梢 -Class: Picnicker -Pic: Picnicker -Gender: Female -Music: Girl -Double Battle: No -AI: Check Bad Move - -Breloom -Level: 31 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe - -Gloom -Level: 31 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe - -Swablu -Level: 31 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe - -=== TRAINER_DIANA_5 === -Name: 梢 -Class: Picnicker -Pic: Picnicker -Gender: Female -Music: Girl -Double Battle: No -AI: Check Bad Move - -Breloom -Level: 40 -IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe - -Vileplume -Level: 40 -IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe - -Altaria -Level: 40 -IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe - -=== TRAINER_AMY_AND_LIV_1 === -Name: 久美和留美 -Class: Twins -Pic: Twins -Gender: Male -Music: Twins -Double Battle: Yes -AI: Check Bad Move - -Plusle -Level: 15 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Minun -Level: 15 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_AMY_AND_LIV_2 === -Name: 久美和留美 -Class: Twins -Pic: Twins -Gender: Male -Music: Twins -Double Battle: Yes -AI: Check Bad Move - -Plusle -Level: 27 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe - -Minun -Level: 27 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe - -=== TRAINER_GINA_AND_MIA_1 === -Name: 奈绪和美绪 -Class: Twins -Pic: Twins -Gender: Male -Music: Twins -Double Battle: Yes -AI: Check Bad Move - -Seedot -Level: 6 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Lotad -Level: 6 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_MIU_AND_YUKI === -Name: 美雨和雪 -Class: Twins -Pic: Twins -Gender: Male -Music: Twins -Double Battle: Yes -AI: Check Bad Move - -Beautifly -Level: 26 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Dustox -Level: 26 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_AMY_AND_LIV_3 === -Name: 久美和留美 -Class: Twins -Pic: Twins -Gender: Male -Music: Twins -Double Battle: Yes -AI: Check Bad Move - -Plusle -Level: 9 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Minun -Level: 9 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_GINA_AND_MIA_2 === -Name: 奈绪和美绪 -Class: Twins -Pic: Twins -Gender: Male -Music: Twins -Double Battle: Yes -AI: Check Bad Move - -Duskull -Level: 10 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe -- Night Shade -- Disable - -Shroomish -Level: 10 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe -- Absorb -- Leech Seed - -=== TRAINER_AMY_AND_LIV_4 === -Name: 久美和留美 -Class: Twins -Pic: Twins -Gender: Male -Music: Twins -Double Battle: Yes -AI: Check Bad Move - -Plusle -Level: 30 -IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe - -Minun -Level: 30 -IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe - -=== TRAINER_AMY_AND_LIV_5 === -Name: 久美和留美 -Class: Twins -Pic: Twins -Gender: Male -Music: Twins -Double Battle: Yes -AI: Check Bad Move - -Plusle -Level: 33 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe -- Spark -- Charge -- Fake Tears -- Helping Hand - -Minun -Level: 33 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe -- Spark -- Charge -- Charm -- Helping Hand - -=== TRAINER_AMY_AND_LIV_6 === -Name: 久美和留美 -Class: Twins -Pic: Twins -Gender: Male -Music: Twins -Double Battle: Yes -AI: Check Bad Move - -Plusle -Level: 36 -IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe -- Thunder -- Charge -- Fake Tears -- Helping Hand - -Minun -Level: 36 -IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe -- Thunder -- Charge -- Charm -- Helping Hand - -=== TRAINER_HUEY === -Name: 达郎 -Class: Sailor -Pic: Sailor -Gender: Male -Music: Male -Double Battle: No -AI: Check Bad Move - -Wingull -Level: 12 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe - -Machop -Level: 12 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe - -=== TRAINER_EDMOND === -Name: 克哉 -Class: Sailor -Pic: Sailor -Gender: Male -Music: Male -Double Battle: No -AI: Check Bad Move - -Wingull -Level: 13 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_ERNEST_1 === -Name: 次郎 -Class: Sailor -Pic: Sailor -Gender: Male -Music: Male -Double Battle: No -AI: Check Bad Move - -Wingull -Level: 33 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Machoke -Level: 33 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_DWAYNE === -Name: 龙彦 -Class: Sailor -Pic: Sailor -Gender: Male -Music: Male -Double Battle: No -AI: Check Bad Move - -Wingull -Level: 11 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Machop -Level: 11 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Tentacool -Level: 11 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_PHILLIP === -Name: 勇作 -Class: Sailor -Pic: Sailor -Gender: Male -Music: Male -Double Battle: No -AI: Check Bad Move - -Tentacruel -Level: 44 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Machoke -Level: 44 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_LEONARD === -Name: 大树 -Class: Sailor -Pic: Sailor -Gender: Male -Music: Male -Double Battle: No -AI: Check Bad Move - -Machop -Level: 43 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Pelipper -Level: 43 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Machoke -Level: 43 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_DUNCAN === -Name: 豪史 -Class: Sailor -Pic: Sailor -Gender: Male -Music: Male -Double Battle: No -AI: Check Bad Move - -Spheal -Level: 25 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Machoke -Level: 25 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_ERNEST_2 === -Name: 次郎 -Class: Sailor -Pic: Sailor -Gender: Male -Music: Male -Double Battle: No -AI: Check Bad Move - -Wingull -Level: 36 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe - -Tentacool -Level: 36 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe - -Machoke -Level: 36 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe - -=== TRAINER_ERNEST_3 === -Name: 次郎 -Class: Sailor -Pic: Sailor -Gender: Male -Music: Male -Double Battle: No -AI: Check Bad Move - -Pelipper -Level: 39 -IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe - -Tentacool -Level: 39 -IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe - -Machoke -Level: 39 -IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe - -=== TRAINER_ERNEST_4 === -Name: 次郎 -Class: Sailor -Pic: Sailor -Gender: Male -Music: Male -Double Battle: No -AI: Check Bad Move - -Pelipper -Level: 42 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe - -Tentacool -Level: 42 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe - -Machoke -Level: 42 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe - -=== TRAINER_ERNEST_5 === -Name: 次郎 -Class: Sailor -Pic: Sailor -Gender: Male -Music: Male -Double Battle: No -AI: Check Bad Move - -Pelipper -Level: 45 -IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe - -Machoke -Level: 45 -IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe - -Tentacruel -Level: 45 -IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe - -=== TRAINER_ELI === -Name: 辉义 -Class: Hiker -Pic: Hiker -Gender: Male -Music: Hiker -Double Battle: No -AI: Check Bad Move - -Numel -Level: 23 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -=== TRAINER_ANNIKA === -Name: 峰子 -Class: Pokefan -Pic: Pokefan F -Gender: Female -Music: Twins -Double Battle: No -AI: Check Bad Move - -Feebas @ Oran Berry -Level: 39 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe -- Flail -- Water Pulse -- Return -- Attract - -Feebas @ Oran Berry -Level: 39 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe -- Flail -- Water Pulse -- Return -- Attract - -=== TRAINER_JAZMYN === -Name: 美羽 -Class: Cooltrainer 2 -Pic: Cooltrainer F -Gender: Female -Music: Cool -Items: Hyper Potion -Double Battle: No -AI: Basic Trainer - -Absol -Level: 27 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_JONAS === -Name: 伸介 -Class: Ninja Boy -Pic: Ninja Boy -Gender: Male -Music: Suspicious -Double Battle: No -AI: Basic Trainer - -Koffing -Level: 31 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe -- Toxic -- Thunder -- Self Destruct -- Sludge Bomb - -=== TRAINER_KAYLEY === -Name: 薰子 -Class: Parasol Lady -Pic: Parasol Lady -Gender: Female -Music: Female -Double Battle: No -AI: Check Bad Move - -Castform -Level: 31 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe -- Sunny Day -- Weather Ball -- Flamethrower -- Solar Beam - -=== TRAINER_AURON === -Name: 一圭 -Class: Expert -Pic: Expert M -Gender: Male -Music: Intense -Double Battle: No -AI: Check Bad Move - -Manectric -Level: 33 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Machamp -Level: 33 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_KELVIN === -Name: 直也 -Class: Sailor -Pic: Sailor -Gender: Male -Music: Male -Double Battle: No -AI: Check Bad Move - -Machoke -Level: 33 -IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe - -Spheal -Level: 33 -IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe - -=== TRAINER_MARLEY === -Name: 律子 -Class: Cooltrainer -Pic: Cooltrainer F -Gender: Female -Music: Cool -Items: Hyper Potion -Double Battle: No -AI: Basic Trainer - -Manectric -Level: 34 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Bite -- Roar -- Thunder Wave -- Thunderbolt - -=== TRAINER_REYNA === -Name: 珠希 -Class: Battle Girl -Pic: Battle Girl -Gender: Female -Music: Intense -Double Battle: No -AI: Check Bad Move - -Meditite -Level: 33 -IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe - -Hariyama -Level: 33 -IVs: 24 HP / 24 Atk / 24 Def / 24 SpA / 24 SpD / 24 Spe - -=== TRAINER_HUDSON === -Name: 纯也 -Class: Sailor -Pic: Sailor -Gender: Male -Music: Male -Double Battle: No -AI: Check Bad Move - -Wailmer -Level: 34 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_CONOR === -Name: 茂良 -Class: Expert -Pic: Expert M -Gender: Male -Music: Intense -Double Battle: No -AI: Check Bad Move - -Chinchou -Level: 33 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Hariyama -Level: 33 -IVs: 24 HP / 24 Atk / 24 Def / 24 SpA / 24 SpD / 24 Spe - -=== TRAINER_EDWIN_1 === -Name: 元树 -Class: Collector -Pic: Collector -Gender: Male -Music: Suspicious -Double Battle: No -AI: Check Bad Move - -Lombre -Level: 14 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Nuzleaf -Level: 14 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_HECTOR === -Name: 俊宣 -Class: Collector -Pic: Collector -Gender: Male -Music: Suspicious -Double Battle: No -AI: Check Bad Move - -Zangoose -Level: 18 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Seviper -Level: 18 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_TABITHA_MOSSDEEP === -Name: 火村 -Class: Magma Admin -Pic: Magma Admin -Gender: Male -Music: Magma -Double Battle: No -AI: Check Bad Move - -Camerupt -Level: 36 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -Mightyena -Level: 38 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -Golbat -Level: 40 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -=== TRAINER_EDWIN_2 === -Name: 元树 -Class: Collector -Pic: Collector -Gender: Male -Music: Suspicious -Double Battle: No -AI: Check Bad Move - -Lombre -Level: 26 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Nuzleaf -Level: 26 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_EDWIN_3 === -Name: 元树 -Class: Collector -Pic: Collector -Gender: Male -Music: Suspicious -Double Battle: No -AI: Check Bad Move - -Lombre -Level: 29 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Nuzleaf -Level: 29 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_EDWIN_4 === -Name: 元树 -Class: Collector -Pic: Collector -Gender: Male -Music: Suspicious -Double Battle: No -AI: Check Bad Move - -Lombre -Level: 32 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Nuzleaf -Level: 32 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_EDWIN_5 === -Name: 元树 -Class: Collector -Pic: Collector -Gender: Male -Music: Suspicious -Double Battle: No -AI: Check Bad Move - -Ludicolo -Level: 35 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Shiftry -Level: 35 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_WALLY_VR_1 === -Name: 满充 -Class: Rival -Pic: Wally -Gender: Male -Music: Male -Items: Full Restore / Full Restore -Double Battle: No -AI: Basic Trainer - -Altaria -Level: 44 -IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe -- Aerial Ace -- Safeguard -- Dragon Breath -- Dragon Dance - -Delcatty -Level: 43 -IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe -- Sing -- Assist -- Charm -- Feint Attack - -Roselia -Level: 44 -IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe -- Magical Leaf -- Leech Seed -- Giga Drain -- Toxic - -Magneton -Level: 41 -IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe -- Supersonic -- Thunderbolt -- Tri Attack -- Screech - -Gardevoir -Level: 45 -IVs: 30 HP / 30 Atk / 30 Def / 30 SpA / 30 SpD / 30 Spe -- Double Team -- Calm Mind -- Psychic -- Future Sight - -=== TRAINER_BRENDAN_ROUTE_103_MUDKIP === -Name: 小悠 -Class: Rival -Pic: Brendan -Gender: Male -Music: Male -Double Battle: No -AI: Basic Trainer - -Treecko -Level: 5 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_BRENDAN_ROUTE_110_MUDKIP === -Name: 小悠 -Class: Rival -Pic: Brendan -Gender: Male -Music: Male -Double Battle: No -AI: Basic Trainer - -Slugma -Level: 18 -IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe - -Wingull -Level: 18 -IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe - -Grovyle -Level: 20 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -=== TRAINER_BRENDAN_ROUTE_119_MUDKIP === -Name: 小悠 -Class: Rival -Pic: Brendan -Gender: Male -Music: Male -Double Battle: No -AI: Basic Trainer - -Slugma -Level: 29 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -Pelipper -Level: 29 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -Grovyle -Level: 31 -IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe - -=== TRAINER_BRENDAN_ROUTE_103_TREECKO === -Name: 小悠 -Class: Rival -Pic: Brendan -Gender: Male -Music: Male -Double Battle: No -AI: Check Bad Move / Try To Faint / Force Setup First Turn - -Torchic -Level: 5 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_BRENDAN_ROUTE_110_TREECKO === -Name: 小悠 -Class: Rival -Pic: Brendan -Gender: Male -Music: Male -Double Battle: No -AI: Basic Trainer - -Wingull -Level: 18 -IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe - -Lombre -Level: 18 -IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe - -Combusken -Level: 20 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -=== TRAINER_BRENDAN_ROUTE_119_TREECKO === -Name: 小悠 -Class: Rival -Pic: Brendan -Gender: Male -Music: Male -Double Battle: No -AI: Basic Trainer - -Pelipper -Level: 29 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -Lombre -Level: 29 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -Combusken -Level: 31 -IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe - -=== TRAINER_BRENDAN_ROUTE_103_TORCHIC === -Name: 小悠 -Class: Rival -Pic: Brendan -Gender: Male -Music: Male -Double Battle: No -AI: Basic Trainer - -Mudkip -Level: 5 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_BRENDAN_ROUTE_110_TORCHIC === -Name: 小悠 -Class: Rival -Pic: Brendan -Gender: Male -Music: Male -Double Battle: No -AI: Basic Trainer - -Lombre -Level: 18 -IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe - -Slugma -Level: 18 -IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe - -Marshtomp -Level: 20 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -=== TRAINER_BRENDAN_ROUTE_119_TORCHIC === -Name: 小悠 -Class: Rival -Pic: Brendan -Gender: Male -Music: Male -Double Battle: No -AI: Basic Trainer - -Lombre -Level: 29 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -Slugma -Level: 29 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -Marshtomp -Level: 31 -IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe - -=== TRAINER_MAY_ROUTE_103_MUDKIP === -Name: 小遥 -Class: Rival -Pic: May -Gender: Female -Music: Female -Double Battle: No -AI: Basic Trainer - -Treecko -Level: 5 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_MAY_ROUTE_110_MUDKIP === -Name: 小遥 -Class: Rival -Pic: May -Gender: Female -Music: Female -Double Battle: No -AI: Basic Trainer - -Wingull -Level: 18 -IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe - -Slugma -Level: 18 -IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe - -Grovyle -Level: 20 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -=== TRAINER_MAY_ROUTE_119_MUDKIP === -Name: 小遥 -Class: Rival -Pic: May -Gender: Female -Music: Female -Double Battle: No -AI: Basic Trainer - -Slugma -Level: 29 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -Lombre -Level: 29 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -Grovyle -Level: 31 -IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe - -=== TRAINER_MAY_ROUTE_103_TREECKO === -Name: 小遥 -Class: Rival -Pic: May -Gender: Female -Music: Female -Double Battle: No -AI: Basic Trainer - -Torchic -Level: 5 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_MAY_ROUTE_110_TREECKO === -Name: 小遥 -Class: Rival -Pic: May -Gender: Female -Music: Female -Double Battle: No -AI: Basic Trainer - -Wingull -Level: 18 -IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe - -Lombre -Level: 18 -IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe - -Combusken -Level: 20 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -=== TRAINER_MAY_ROUTE_119_TREECKO === -Name: 小遥 -Class: Rival -Pic: May -Gender: Female -Music: Female -Double Battle: No -AI: Basic Trainer - -Pelipper -Level: 29 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -Lombre -Level: 29 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -Combusken -Level: 31 -IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe - -=== TRAINER_MAY_ROUTE_103_TORCHIC === -Name: 小遥 -Class: Rival -Pic: May -Gender: Female -Music: Female -Double Battle: No -AI: Basic Trainer - -Mudkip -Level: 5 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_MAY_ROUTE_110_TORCHIC === -Name: 小遥 -Class: Rival -Pic: May -Gender: Female -Music: Female -Double Battle: No -AI: Basic Trainer - -Lombre -Level: 18 -IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe - -Slugma -Level: 18 -IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe - -Marshtomp -Level: 20 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -=== TRAINER_MAY_ROUTE_119_TORCHIC === -Name: 小遥 -Class: Rival -Pic: May -Gender: Female -Music: Female -Double Battle: No -AI: Basic Trainer - -Lombre -Level: 29 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -Slugma -Level: 29 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -Marshtomp -Level: 31 -IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe - -=== TRAINER_ISAAC_1 === -Name: 诚儿 -Class: Pkmn Breeder -Pic: Pokemon Breeder M -Gender: Male -Music: Male -Double Battle: No -AI: Check Bad Move - -Whismur -Level: 11 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Zigzagoon -Level: 11 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Aron -Level: 11 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Poochyena -Level: 11 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Taillow -Level: 11 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Makuhita -Level: 11 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_DAVIS === -Name: 喜朗 -Class: Bug Catcher -Pic: Bug Catcher -Gender: Male -Music: Male -Double Battle: No -AI: Check Bad Move - -Pinsir -Level: 27 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_MITCHELL === -Name: 铁平 -Class: Cooltrainer -Pic: Cooltrainer M -Gender: Male -Music: Cool -Double Battle: No -AI: Basic Trainer - -Lunatone -Level: 43 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe -- Explosion -- Reflect -- Light Screen -- Psychic - -Solrock -Level: 43 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe -- Explosion -- Reflect -- Light Screen -- Shadow Ball - -=== TRAINER_ISAAC_2 === -Name: 诚儿 -Class: Pkmn Breeder -Pic: Pokemon Breeder M -Gender: Male -Music: Male -Double Battle: No -AI: Check Bad Move - -Loudred -Level: 22 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe - -Linoone -Level: 22 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe - -Aron -Level: 22 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe - -Mightyena -Level: 22 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe - -Swellow -Level: 22 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe - -Makuhita -Level: 22 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe - -=== TRAINER_ISAAC_3 === -Name: 诚儿 -Class: Pkmn Breeder -Pic: Pokemon Breeder M -Gender: Male -Music: Male -Double Battle: No -AI: Check Bad Move - -Loudred -Level: 25 -IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe - -Linoone -Level: 25 -IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe - -Aron -Level: 25 -IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe - -Mightyena -Level: 25 -IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe - -Swellow -Level: 25 -IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe - -Hariyama -Level: 25 -IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe - -=== TRAINER_ISAAC_4 === -Name: 诚儿 -Class: Pkmn Breeder -Pic: Pokemon Breeder M -Gender: Male -Music: Male -Double Battle: No -AI: Check Bad Move - -Loudred -Level: 28 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe - -Linoone -Level: 28 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe - -Aron -Level: 28 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe - -Mightyena -Level: 28 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe - -Swellow -Level: 28 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe - -Hariyama -Level: 28 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe - -=== TRAINER_ISAAC_5 === -Name: 诚儿 -Class: Pkmn Breeder -Pic: Pokemon Breeder M -Gender: Male -Music: Male -Double Battle: No -AI: Check Bad Move - -Loudred -Level: 31 -IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe - -Linoone -Level: 31 -IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe - -Lairon -Level: 31 -IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe - -Mightyena -Level: 31 -IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe - -Swellow -Level: 31 -IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe - -Hariyama -Level: 31 -IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe - -=== TRAINER_LYDIA_1 === -Name: 郁惠 -Class: Pkmn Breeder -Pic: Pokemon Breeder F -Gender: Female -Music: Female -Double Battle: No -AI: Check Bad Move - -Wingull -Level: 11 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Shroomish -Level: 11 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Marill -Level: 11 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Roselia -Level: 11 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Skitty -Level: 11 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Goldeen -Level: 11 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_HALLE === -Name: 广惠 -Class: Cooltrainer -Pic: Cooltrainer F -Gender: Female -Music: Cool -Items: Full Restore -Double Battle: No -AI: Basic Trainer - -Sableye -Level: 43 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Absol -Level: 43 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_GARRISON === -Name: 恒安 -Class: Ruin Maniac -Pic: Ruin Maniac -Gender: Male -Music: Hiker -Double Battle: No -AI: Check Bad Move - -Sandslash -Level: 26 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_LYDIA_2 === -Name: 郁惠 -Class: Pkmn Breeder -Pic: Pokemon Breeder F -Gender: Female -Music: Female -Double Battle: No -AI: Check Bad Move - -Wingull -Level: 22 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe - -Shroomish -Level: 22 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe - -Marill -Level: 22 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe - -Roselia -Level: 22 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe - -Skitty -Level: 22 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe - -Goldeen -Level: 22 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe - -=== TRAINER_LYDIA_3 === -Name: 郁惠 -Class: Pkmn Breeder -Pic: Pokemon Breeder F -Gender: Female -Music: Female -Double Battle: No -AI: Check Bad Move - -Pelipper -Level: 25 -IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe - -Breloom -Level: 25 -IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe - -Marill -Level: 25 -IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe - -Roselia -Level: 25 -IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe - -Delcatty -Level: 25 -IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe - -Goldeen -Level: 25 -IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe - -=== TRAINER_LYDIA_4 === -Name: 郁惠 -Class: Pkmn Breeder -Pic: Pokemon Breeder F -Gender: Female -Music: Female -Double Battle: No -AI: Check Bad Move - -Pelipper -Level: 28 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe - -Breloom -Level: 28 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe - -Marill -Level: 28 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe - -Roselia -Level: 28 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe - -Delcatty -Level: 28 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe - -Goldeen -Level: 28 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe - -=== TRAINER_LYDIA_5 === -Name: 郁惠 -Class: Pkmn Breeder -Pic: Pokemon Breeder F -Gender: Female -Music: Female -Double Battle: No -AI: Check Bad Move - -Pelipper -Level: 31 -IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe - -Breloom -Level: 31 -IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe - -Azumarill -Level: 31 -IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe - -Roselia -Level: 31 -IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe - -Delcatty -Level: 31 -IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe - -Seaking -Level: 31 -IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe - -=== TRAINER_JACKSON_1 === -Name: 阿守 -Class: Pkmn Ranger -Pic: Pokemon Ranger M -Gender: Male -Music: Cool -Items: Full Restore -Double Battle: No -AI: Basic Trainer - -Breloom -Level: 27 -IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe - -=== TRAINER_LORENZO === -Name: 淳一 -Class: Pkmn Ranger -Pic: Pokemon Ranger M -Gender: Male -Music: Cool -Items: Full Restore -Double Battle: No -AI: Basic Trainer - -Seedot -Level: 28 -IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe - -Nuzleaf -Level: 28 -IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe - -Lombre -Level: 28 -IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe - -=== TRAINER_SEBASTIAN === -Name: 圭介 -Class: Pkmn Ranger -Pic: Pokemon Ranger M -Gender: Male -Music: Cool -Items: Full Restore -Double Battle: No -AI: Basic Trainer - -Cacturne -Level: 39 -IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe - -=== TRAINER_JACKSON_2 === -Name: 阿守 -Class: Pkmn Ranger -Pic: Pokemon Ranger M -Gender: Male -Music: Cool -Items: Full Restore -Double Battle: No -AI: Check Bad Move / Try To Faint / Force Setup First Turn - -Breloom -Level: 31 -IVs: 7 HP / 7 Atk / 7 Def / 7 SpA / 7 SpD / 7 Spe - -=== TRAINER_JACKSON_3 === -Name: 阿守 -Class: Pkmn Ranger -Pic: Pokemon Ranger M -Gender: Male -Music: Cool -Items: Full Restore -Double Battle: No -AI: Basic Trainer - -Breloom -Level: 34 -IVs: 8 HP / 8 Atk / 8 Def / 8 SpA / 8 SpD / 8 Spe - -=== TRAINER_JACKSON_4 === -Name: 阿守 -Class: Pkmn Ranger -Pic: Pokemon Ranger M -Gender: Male -Music: Cool -Items: Full Restore -Double Battle: No -AI: Check Bad Move / Try To Faint / Force Setup First Turn - -Breloom -Level: 37 -IVs: 9 HP / 9 Atk / 9 Def / 9 SpA / 9 SpD / 9 Spe - -=== TRAINER_JACKSON_5 === -Name: 阿守 -Class: Pkmn Ranger -Pic: Pokemon Ranger M -Gender: Male -Music: Cool -Items: Full Restore -Double Battle: No -AI: Basic Trainer - -Kecleon -Level: 39 -IVs: 10 HP / 10 Atk / 10 Def / 10 SpA / 10 SpD / 10 Spe - -Breloom -Level: 39 -IVs: 10 HP / 10 Atk / 10 Def / 10 SpA / 10 SpD / 10 Spe - -=== TRAINER_CATHERINE_1 === -Name: 真奈美 -Class: Pkmn Ranger -Pic: Pokemon Ranger F -Gender: Female -Music: Cool -Items: Full Restore -Double Battle: No -AI: Check Bad Move / Try To Faint / Force Setup First Turn - -Gloom -Level: 26 -IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe - -Roselia -Level: 26 -IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe - -=== TRAINER_JENNA === -Name: 芹奈 -Class: Pkmn Ranger -Pic: Pokemon Ranger F -Gender: Female -Music: Cool -Items: Full Restore -Double Battle: No -AI: Check Bad Move / Try To Faint / Force Setup First Turn - -Lotad -Level: 28 -IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe - -Lombre -Level: 28 -IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe - -Nuzleaf -Level: 28 -IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe - -=== TRAINER_SOPHIA === -Name: 千秋 -Class: Pkmn Ranger -Pic: Pokemon Ranger F -Gender: Female -Music: Cool -Items: Full Restore -Double Battle: No -AI: Basic Trainer - -Swablu -Level: 38 -IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe - -Roselia -Level: 38 -IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe - -=== TRAINER_CATHERINE_2 === -Name: 真奈美 -Class: Pkmn Ranger -Pic: Pokemon Ranger F -Gender: Female -Music: Cool -Items: Full Restore -Double Battle: No -AI: Check Bad Move / Try To Faint / Force Setup First Turn - -Gloom -Level: 30 -IVs: 7 HP / 7 Atk / 7 Def / 7 SpA / 7 SpD / 7 Spe - -Roselia -Level: 30 -IVs: 7 HP / 7 Atk / 7 Def / 7 SpA / 7 SpD / 7 Spe - -=== TRAINER_CATHERINE_3 === -Name: 真奈美 -Class: Pkmn Ranger -Pic: Pokemon Ranger F -Gender: Female -Music: Cool -Items: Full Restore -Double Battle: No -AI: Basic Trainer - -Gloom -Level: 33 -IVs: 8 HP / 8 Atk / 8 Def / 8 SpA / 8 SpD / 8 Spe - -Roselia -Level: 33 -IVs: 8 HP / 8 Atk / 8 Def / 8 SpA / 8 SpD / 8 Spe - -=== TRAINER_CATHERINE_4 === -Name: 真奈美 -Class: Pkmn Ranger -Pic: Pokemon Ranger F -Gender: Female -Music: Cool -Items: Full Restore -Double Battle: No -AI: Check Bad Move / Try To Faint / Force Setup First Turn - -Gloom -Level: 36 -IVs: 9 HP / 9 Atk / 9 Def / 9 SpA / 9 SpD / 9 Spe - -Roselia -Level: 36 -IVs: 9 HP / 9 Atk / 9 Def / 9 SpA / 9 SpD / 9 Spe - -=== TRAINER_CATHERINE_5 === -Name: 真奈美 -Class: Pkmn Ranger -Pic: Pokemon Ranger F -Gender: Female -Music: Cool -Items: Full Restore -Double Battle: No -AI: Basic Trainer - -Bellossom -Level: 39 -IVs: 10 HP / 10 Atk / 10 Def / 10 SpA / 10 SpD / 10 Spe - -Roselia -Level: 39 -IVs: 10 HP / 10 Atk / 10 Def / 10 SpA / 10 SpD / 10 Spe - -=== TRAINER_JULIO === -Name: 光雄 -Class: Triathlete -Pic: Cycling Triathlete M -Gender: Male -Music: Male -Double Battle: No -AI: Check Bad Move - -Magnemite -Level: 21 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_GRUNT_SEAFLOOR_CAVERN_5 === -Name: 手下 -Class: Team Aqua -Pic: Aqua Grunt M -Gender: Male -Music: Aqua -Double Battle: No -AI: Check Bad Move - -Mightyena -Level: 35 -IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe - -Golbat -Level: 35 -IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe - -=== TRAINER_GRUNT_UNUSED === -Name: 手下 -Class: Team Magma -Pic: Aqua Grunt F -Gender: Female -Music: Aqua -Double Battle: No -AI: Check Bad Move - -Wailmer -Level: 31 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Zubat -Level: 31 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_GRUNT_MT_PYRE_4 === -Name: 手下 -Class: Team Aqua -Pic: Aqua Grunt F -Gender: Female -Music: Aqua -Double Battle: No -AI: Check Bad Move - -Wailmer -Level: 30 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Zubat -Level: 30 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_GRUNT_JAGGED_PASS === -Name: 手下 -Class: Team Magma -Pic: Magma Grunt M -Gender: Male -Music: Magma -Double Battle: No -AI: Check Bad Move - -Poochyena -Level: 22 -IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe - -Numel -Level: 22 -IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe - -=== TRAINER_MARC === -Name: 宗太郎 -Class: Hiker -Pic: Hiker -Gender: Male -Music: Hiker -Double Battle: No -AI: Check Bad Move - -Geodude -Level: 8 -IVs: 14 HP / 14 Atk / 14 Def / 14 SpA / 14 SpD / 14 Spe - -Geodude -Level: 8 -IVs: 15 HP / 15 Atk / 15 Def / 15 SpA / 15 SpD / 15 Spe - -=== TRAINER_BRENDEN === -Name: 和正 -Class: Sailor -Pic: Sailor -Gender: Male -Music: Male -Double Battle: No -AI: Check Bad Move - -Machop -Level: 13 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -=== TRAINER_LILITH === -Name: 安昙 -Class: Battle Girl -Pic: Battle Girl -Gender: Female -Music: Intense -Double Battle: No -AI: Check Bad Move - -Meditite -Level: 13 -IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe - -=== TRAINER_CRISTIAN === -Name: 俊英 -Class: Black Belt -Pic: Black Belt -Gender: Male -Music: Intense -Double Battle: No -AI: Check Bad Move - -Makuhita -Level: 13 -IVs: 24 HP / 24 Atk / 24 Def / 24 SpA / 24 SpD / 24 Spe - -=== TRAINER_SYLVIA === -Name: 朝代 -Class: Hex Maniac -Pic: Hex Maniac -Gender: Female -Music: Suspicious -Double Battle: No -AI: Check Bad Move - -Meditite -Level: 36 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -=== TRAINER_LEONARDO === -Name: 和成 -Class: Swimmer M -Pic: Swimmer M -Gender: Male -Music: Swimmer -Double Battle: No -AI: Check Bad Move - -Carvanha -Level: 34 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_ATHENA === -Name: 江美里 -Class: Cooltrainer -Pic: Cooltrainer F -Gender: Female -Music: Cool -Items: Hyper Potion -Double Battle: No -AI: Basic Trainer - -Manectric -Level: 32 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe -- Thunder -- Thunder Wave -- Quick Attack - -Linoone -Level: 32 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe -- Surf -- Thief - -=== TRAINER_HARRISON === -Name: 正明 -Class: Swimmer M -Pic: Swimmer M -Gender: Male -Music: Swimmer -Double Battle: No -AI: Check Bad Move - -Tentacruel -Level: 35 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_GRUNT_MT_CHIMNEY_2 === -Name: 手下 -Class: Team Magma -Pic: Magma Grunt M -Gender: Male -Music: Magma -Double Battle: No -AI: Check Bad Move - -Zubat -Level: 20 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_CLARENCE === -Name: 义文 -Class: Swimmer M -Pic: Swimmer M -Gender: Male -Music: Swimmer -Double Battle: No -AI: Check Bad Move - -Sharpedo -Level: 34 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_TERRY === -Name: 无名氏 -Class: Psychic -Pic: Psychic F -Gender: Female -Music: Intense -Double Battle: No -AI: Check Bad Move - -Girafarig -Level: 37 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_NATE === -Name: 东尼 -Class: Gentleman -Pic: Gentleman -Gender: Male -Music: Rich -Double Battle: No -AI: Check Bad Move - -Spoink -Level: 36 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -=== TRAINER_KATHLEEN === -Name: 幸代 -Class: Hex Maniac -Pic: Hex Maniac -Gender: Female -Music: Suspicious -Double Battle: No -AI: Check Bad Move - -Kadabra -Level: 36 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -=== TRAINER_CLIFFORD === -Name: 史蒂夫 -Class: Gentleman -Pic: Gentleman -Gender: Male -Music: Rich -Double Battle: No -AI: Check Bad Move - -Girafarig -Level: 36 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_NICHOLAS === -Name: 行世 -Class: Psychic -Pic: Psychic M -Gender: Male -Music: Intense -Double Battle: No -AI: Check Bad Move - -Wobbuffet -Level: 36 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_GRUNT_SPACE_CENTER_3 === -Name: 手下 -Class: Team Magma -Pic: Magma Grunt F -Gender: Female -Music: Magma -Double Battle: No -AI: Check Bad Move - -Zubat -Level: 31 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Poochyena -Level: 31 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_GRUNT_SPACE_CENTER_4 === -Name: 手下 -Class: Team Magma -Pic: Magma Grunt M -Gender: Male -Music: Magma -Double Battle: No -AI: Check Bad Move - -Baltoy -Level: 32 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_GRUNT_SPACE_CENTER_5 === -Name: 手下 -Class: Team Magma -Pic: Magma Grunt M -Gender: Male -Music: Magma -Double Battle: No -AI: Check Bad Move - -Zubat -Level: 32 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_GRUNT_SPACE_CENTER_6 === -Name: 手下 -Class: Team Magma -Pic: Magma Grunt M -Gender: Male -Music: Magma -Double Battle: No -AI: Check Bad Move - -Mightyena -Level: 32 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_GRUNT_SPACE_CENTER_7 === -Name: 手下 -Class: Team Magma -Pic: Magma Grunt M -Gender: Male -Music: Magma -Double Battle: No -AI: Check Bad Move - -Baltoy -Level: 32 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_MACEY === -Name: 总子 -Class: Psychic -Pic: Psychic F -Gender: Female -Music: Intense -Double Battle: No -AI: Check Bad Move - -Natu -Level: 36 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_BRENDAN_RUSTBORO_TREECKO === -Name: 小悠 -Class: Rival -Pic: Brendan -Gender: Male -Music: Male -Double Battle: No -AI: Check Bad Move - -Lotad -Level: 13 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe - -Torchic -Level: 15 -IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe - -=== TRAINER_BRENDAN_RUSTBORO_MUDKIP === -Name: 小悠 -Class: Rival -Pic: Brendan -Gender: Male -Music: Male -Double Battle: No -AI: Check Bad Move - -Wingull -Level: 13 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe - -Treecko -Level: 15 -IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe - -=== TRAINER_PAXTON === -Name: 刚藏 -Class: Expert -Pic: Expert M -Gender: Male -Music: Intense -Double Battle: No -AI: Basic Trainer - -Swellow -Level: 33 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Breloom -Level: 33 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_ISABELLA === -Name: 和晴 -Class: Triathlete -Pic: Swimming Triathlete F -Gender: Female -Music: Swimmer -Double Battle: No -AI: Check Bad Move - -Staryu -Level: 34 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_GRUNT_WEATHER_INST_5 === -Name: 手下 -Class: Team Aqua -Pic: Aqua Grunt F -Gender: Female -Music: Aqua -Double Battle: No -AI: Check Bad Move - -Zubat -Level: 27 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Poochyena -Level: 27 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_TABITHA_MT_CHIMNEY === -Name: 火村 -Class: Magma Admin -Pic: Magma Admin -Gender: Male -Music: Magma -Double Battle: No -AI: Basic Trainer - -Numel -Level: 18 -IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe - -Poochyena -Level: 20 -IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe - -Numel -Level: 22 -IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe - -Zubat -Level: 22 -IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe - -=== TRAINER_JONATHAN === -Name: 凉介 -Class: Cooltrainer -Pic: Cooltrainer M -Gender: Male -Music: Cool -Items: Hyper Potion -Double Battle: No -AI: Check Bad Move / Try To Faint / Force Setup First Turn - -Kecleon -Level: 33 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Loudred -Level: 33 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_BRENDAN_RUSTBORO_TORCHIC === -Name: 小悠 -Class: Rival -Pic: Brendan -Gender: Male -Music: Male -Double Battle: No -AI: Basic Trainer - -Slugma -Level: 13 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe - -Mudkip -Level: 15 -IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe - -=== TRAINER_MAY_RUSTBORO_MUDKIP === -Name: 小遥 -Class: Rival -Pic: May -Gender: Female -Music: Female -Double Battle: No -AI: Check Bad Move / Try To Faint / Force Setup First Turn - -Wingull -Level: 13 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe - -Treecko -Level: 15 -IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe - -=== TRAINER_MAXIE_MAGMA_HIDEOUT === -Name: 赤焰松 -Class: Magma Leader -Pic: Magma Leader Maxie -Gender: Male -Music: Magma -Items: Super Potion / Super Potion -Double Battle: No -AI: Basic Trainer - -Mightyena -Level: 37 -IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe - -Crobat -Level: 38 -IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe - -Camerupt -Level: 39 -IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe - -=== TRAINER_MAXIE_MT_CHIMNEY === -Name: 赤焰松 -Class: Magma Leader -Pic: Magma Leader Maxie -Gender: Male -Music: Magma -Items: Super Potion / Super Potion -Double Battle: No -AI: Basic Trainer - -Mightyena -Level: 24 -IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe - -Zubat -Level: 24 -IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe - -Camerupt -Level: 25 -IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe - -=== TRAINER_TIANA === -Name: 千佳 -Class: Lass -Pic: Lass -Gender: Female -Music: Female -Double Battle: No -AI: Check Bad Move - -Zigzagoon -Level: 4 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Shroomish -Level: 4 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_HALEY_1 === -Name: 真希 -Class: Lass -Pic: Lass -Gender: Female -Music: Female -Double Battle: No -AI: Check Bad Move - -Lotad -Level: 6 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Shroomish -Level: 6 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_JANICE === -Name: 真理 -Class: Lass -Pic: Lass -Gender: Female -Music: Female -Double Battle: No -AI: Check Bad Move - -Marill -Level: 9 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_VIVI === -Name: 小秋 -Class: Winstrate -Pic: Lass -Gender: Female -Music: Female -Double Battle: No -AI: Basic Trainer - -Marill -Level: 15 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -Shroomish -Level: 15 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -Numel -Level: 15 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -=== TRAINER_HALEY_2 === -Name: 真希 -Class: Lass -Pic: Lass -Gender: Female -Music: Female -Double Battle: No -AI: Check Bad Move - -Lombre -Level: 26 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe - -Shroomish -Level: 26 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe - -=== TRAINER_HALEY_3 === -Name: 真希 -Class: Lass -Pic: Lass -Gender: Female -Music: Female -Double Battle: No -AI: Check Bad Move - -Lombre -Level: 29 -IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe - -Breloom -Level: 29 -IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe - -=== TRAINER_HALEY_4 === -Name: 真希 -Class: Lass -Pic: Lass -Gender: Female -Music: Female -Double Battle: No -AI: Check Bad Move - -Lombre -Level: 32 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe - -Breloom -Level: 32 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe - -=== TRAINER_HALEY_5 === -Name: 真希 -Class: Lass -Pic: Lass -Gender: Female -Music: Female -Double Battle: No -AI: Check Bad Move - -Swellow -Level: 34 -IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe - -Lombre -Level: 34 -IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe - -Breloom -Level: 34 -IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe - -=== TRAINER_SALLY === -Name: 美奈 -Class: Lass -Pic: Lass -Gender: Female -Music: Female -Double Battle: No -AI: Check Bad Move - -Oddish -Level: 16 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_ROBIN === -Name: 诗帆 -Class: Lass -Pic: Lass -Gender: Female -Music: Female -Double Battle: No -AI: Check Bad Move - -Skitty -Level: 14 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Shroomish -Level: 14 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Marill -Level: 14 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_ANDREA === -Name: 美纪 -Class: Lass -Pic: Lass -Gender: Female -Music: Female -Double Battle: No -AI: Check Bad Move - -Luvdisc -Level: 40 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -=== TRAINER_CRISSY === -Name: 梅 -Class: Lass -Pic: Lass -Gender: Female -Music: Female -Double Battle: No -AI: Check Bad Move - -Goldeen -Level: 39 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -Wailmer -Level: 39 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -=== TRAINER_RICK === -Name: 真一 -Class: Bug Catcher -Pic: Bug Catcher -Gender: Male -Music: Male -Double Battle: No -AI: Check Bad Move - -Wurmple -Level: 4 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Wurmple -Level: 4 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_LYLE === -Name: 不二雄 -Class: Bug Catcher -Pic: Bug Catcher -Gender: Male -Music: Male -Double Battle: No -AI: Check Bad Move - -Wurmple -Level: 3 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Wurmple -Level: 3 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Wurmple -Level: 3 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Wurmple -Level: 3 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_JOSE === -Name: 智德 -Class: Bug Catcher -Pic: Bug Catcher -Gender: Male -Music: Male -Double Battle: No -AI: Check Bad Move - -Wurmple -Level: 8 -IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe - -Nincada -Level: 8 -IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe - -=== TRAINER_DOUG === -Name: 修 -Class: Bug Catcher -Pic: Bug Catcher -Gender: Male -Music: Male -Double Battle: No -AI: Check Bad Move - -Nincada -Level: 28 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Ninjask -Level: 28 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_GREG === -Name: 浩之 -Class: Bug Catcher -Pic: Bug Catcher -Gender: Male -Music: Male -Double Battle: No -AI: Check Bad Move - -Volbeat -Level: 25 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Illumise -Level: 25 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_KENT === -Name: 友道 -Class: Bug Catcher -Pic: Bug Catcher -Gender: Male -Music: Male -Double Battle: No -AI: Check Bad Move - -Ninjask -Level: 25 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_JAMES_1 === -Name: 三树也 -Class: Bug Catcher -Pic: Bug Catcher -Gender: Male -Music: Male -Double Battle: No -AI: Check Bad Move - -Nincada -Level: 6 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Nincada -Level: 6 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_JAMES_2 === -Name: 三树也 -Class: Bug Catcher -Pic: Bug Catcher -Gender: Male -Music: Male -Double Battle: No -AI: Check Bad Move - -Ninjask -Level: 27 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe - -=== TRAINER_JAMES_3 === -Name: 三树也 -Class: Bug Catcher -Pic: Bug Catcher -Gender: Male -Music: Male -Double Battle: No -AI: Check Bad Move - -Dustox -Level: 29 -IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe - -Ninjask -Level: 29 -IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe - -=== TRAINER_JAMES_4 === -Name: 三树也 -Class: Bug Catcher -Pic: Bug Catcher -Gender: Male -Music: Male -Double Battle: No -AI: Check Bad Move - -Surskit -Level: 31 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe - -Dustox -Level: 31 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe - -Ninjask -Level: 31 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe - -=== TRAINER_JAMES_5 === -Name: 三树也 -Class: Bug Catcher -Pic: Bug Catcher -Gender: Male -Music: Male -Double Battle: No -AI: Check Bad Move - -Surskit -Level: 33 -IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe - -Ninjask -Level: 33 -IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe - -Dustox -Level: 33 -IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe - -Ninjask -Level: 33 -IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe - -=== TRAINER_BRICE === -Name: 晴信 -Class: Hiker -Pic: Hiker -Gender: Male -Music: Hiker -Double Battle: No -AI: Check Bad Move - -Numel -Level: 17 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Machop -Level: 17 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_TRENT_1 === -Name: 健作 -Class: Hiker -Pic: Hiker -Gender: Male -Music: Hiker -Double Battle: No -AI: Check Bad Move - -Geodude -Level: 16 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Geodude -Level: 17 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Geodude -Level: 16 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_LENNY === -Name: 胜人 -Class: Hiker -Pic: Hiker -Gender: Male -Music: Hiker -Double Battle: No -AI: Check Bad Move - -Geodude -Level: 18 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Machop -Level: 18 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_LUCAS_1 === -Name: 三郎 -Class: Hiker -Pic: Hiker -Gender: Male -Music: Hiker -Double Battle: No -AI: Check Bad Move - -Geodude -Level: 18 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Numel -Level: 18 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_ALAN === -Name: 正典 -Class: Hiker -Pic: Hiker -Gender: Male -Music: Hiker -Double Battle: No -AI: Check Bad Move - -Geodude -Level: 22 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Nosepass -Level: 22 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Graveler -Level: 22 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_CLARK === -Name: 和德 -Class: Hiker -Pic: Hiker -Gender: Male -Music: Hiker -Double Battle: No -AI: Check Bad Move - -Geodude -Level: 8 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_ERIC === -Name: 大地 -Class: Hiker -Pic: Hiker -Gender: Male -Music: Hiker -Double Battle: No -AI: Check Bad Move - -Geodude -Level: 20 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Baltoy -Level: 20 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_LUCAS_2 === -Name: 三郎 -Class: Hiker -Pic: Hiker -Gender: Male -Music: Hiker -Double Battle: No -AI: Check Bad Move - -Wailmer -Level: 9 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe -- Splash -- Water Gun - -=== TRAINER_MIKE_1 === -Name: 登 -Class: Hiker -Pic: Hiker -Gender: Male -Music: Hiker -Double Battle: No -AI: Check Bad Move - -Pelipper -Level: 10 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe -- Gust -- Growl - -Poochyena -Level: 10 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe -- Bite -- Scary Face - -=== TRAINER_MIKE_2 === -Name: 登 -Class: Hiker -Pic: Hiker -Gender: Male -Music: Hiker -Double Battle: No -AI: Check Bad Move - -Geodude -Level: 16 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Geodude -Level: 16 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Machop -Level: 16 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_TRENT_2 === -Name: 健作 -Class: Hiker -Pic: Hiker -Gender: Male -Music: Hiker -Double Battle: No -AI: Check Bad Move - -Geodude -Level: 24 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe - -Geodude -Level: 24 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe - -Geodude -Level: 24 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe - -Graveler -Level: 24 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe - -=== TRAINER_TRENT_3 === -Name: 健作 -Class: Hiker -Pic: Hiker -Gender: Male -Music: Hiker -Double Battle: No -AI: Check Bad Move - -Geodude -Level: 27 -IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe - -Geodude -Level: 27 -IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe - -Graveler -Level: 27 -IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe - -Graveler -Level: 27 -IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe - -=== TRAINER_TRENT_4 === -Name: 健作 -Class: Hiker -Pic: Hiker -Gender: Male -Music: Hiker -Double Battle: No -AI: Check Bad Move - -Geodude -Level: 30 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe - -Graveler -Level: 30 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe - -Graveler -Level: 30 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe - -Graveler -Level: 30 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe - -=== TRAINER_TRENT_5 === -Name: 健作 -Class: Hiker -Pic: Hiker -Gender: Male -Music: Hiker -Double Battle: No -AI: Check Bad Move - -Graveler -Level: 33 -IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe - -Graveler -Level: 33 -IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe - -Graveler -Level: 33 -IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe - -Golem -Level: 33 -IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe - -=== TRAINER_DEZ_AND_LUKE === -Name: 真子和辉 -Class: Young Couple -Pic: Young Couple -Gender: Male -Music: Girl -Double Battle: Yes -AI: Check Bad Move - -Delcatty -Level: 31 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Manectric -Level: 31 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_LEA_AND_JED === -Name: 佳穗和阿新 -Class: Young Couple -Pic: Young Couple -Gender: Male -Music: Girl -Double Battle: Yes -AI: Check Bad Move - -Luvdisc -Level: 45 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Luvdisc -Level: 45 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_KIRA_AND_DAN_1 === -Name: 夏和文 -Class: Young Couple -Pic: Young Couple -Gender: Male -Music: Girl -Double Battle: Yes -AI: Check Bad Move - -Volbeat -Level: 25 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Illumise -Level: 25 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_KIRA_AND_DAN_2 === -Name: 夏和文 -Class: Young Couple -Pic: Young Couple -Gender: Male -Music: Girl -Double Battle: Yes -AI: Check Bad Move - -Volbeat -Level: 30 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe - -Illumise -Level: 30 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe - -=== TRAINER_KIRA_AND_DAN_3 === -Name: 夏和文 -Class: Young Couple -Pic: Young Couple -Gender: Male -Music: Girl -Double Battle: Yes -AI: Check Bad Move - -Volbeat -Level: 33 -IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe - -Illumise -Level: 33 -IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe - -=== TRAINER_KIRA_AND_DAN_4 === -Name: 夏和文 -Class: Young Couple -Pic: Young Couple -Gender: Male -Music: Girl -Double Battle: Yes -AI: Check Bad Move - -Volbeat -Level: 36 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe - -Illumise -Level: 36 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe - -=== TRAINER_KIRA_AND_DAN_5 === -Name: 夏和文 -Class: Young Couple -Pic: Young Couple -Gender: Male -Music: Girl -Double Battle: Yes -AI: Check Bad Move - -Volbeat -Level: 39 -IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe - -Illumise -Level: 39 -IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe - -=== TRAINER_JOHANNA === -Name: 敦子 -Class: Beauty -Pic: Beauty -Gender: Female -Music: Female -Double Battle: No -AI: Check Bad Move - -Goldeen -Level: 13 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_GERALD === -Name: 卓郎 -Class: Cooltrainer -Pic: Cooltrainer M -Gender: Male -Music: Cool -Items: Hyper Potion -Double Battle: No -AI: Basic Trainer - -Kecleon -Level: 23 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe -- Flamethrower -- Fury Swipes -- Feint Attack -- Bind - -=== TRAINER_VIVIAN === -Name: 真琴 -Class: Battle Girl -Pic: Battle Girl -Gender: Female -Music: Intense -Double Battle: No -AI: Check Bad Move - -Meditite -Level: 17 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe -- Bide -- Detect -- Confusion -- Thunder Punch - -Meditite -Level: 17 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe -- Thunder Punch -- Detect -- Confusion -- Meditate - -=== TRAINER_DANIELLE === -Name: 知美 -Class: Battle Girl -Pic: Battle Girl -Gender: Female -Music: Intense -Double Battle: No -AI: Check Bad Move - -Meditite -Level: 23 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe -- Bide -- Detect -- Confusion -- Fire Punch - -=== TRAINER_HIDEO === -Name: 克治 -Class: Ninja Boy -Pic: Ninja Boy -Gender: Male -Music: Suspicious -Double Battle: No -AI: Check Bad Move / Try To Faint - -Koffing -Level: 25 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe -- Tackle -- Self Destruct -- Sludge -- Smokescreen - -Koffing -Level: 25 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe -- Tackle -- Poison Gas -- Sludge -- Smokescreen - -=== TRAINER_KEIGO === -Name: 哲司 -Class: Ninja Boy -Pic: Ninja Boy -Gender: Male -Music: Suspicious -Double Battle: No -AI: Check Bad Move / Try To Faint - -Koffing -Level: 28 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe -- Poison Gas -- Self Destruct -- Sludge -- Smokescreen - -Ninjask -Level: 28 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe -- Sand Attack -- Double Team -- Fury Cutter -- Swords Dance - -=== TRAINER_RILEY === -Name: 忠弘 -Class: Ninja Boy -Pic: Ninja Boy -Gender: Male -Music: Suspicious -Double Battle: No -AI: Check Bad Move / Try To Faint - -Nincada -Level: 28 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe -- Leech Life -- Fury Swipes -- Mind Reader -- Dig - -Koffing -Level: 28 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe -- Tackle -- Self Destruct -- Sludge -- Smokescreen - -=== TRAINER_FLINT === -Name: 辉夫 -Class: Camper -Pic: Camper -Gender: Male -Music: Male -Double Battle: No -AI: Check Bad Move - -Swellow -Level: 29 -IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe - -Xatu -Level: 29 -IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe - -=== TRAINER_ASHLEY === -Name: 耳子 -Class: Picnicker -Pic: Picnicker -Gender: Female -Music: Girl -Double Battle: No -AI: Check Bad Move - -Swablu -Level: 27 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -Swablu -Level: 27 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -Swablu -Level: 27 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -=== TRAINER_WALLY_MAUVILLE === -Name: 满充 -Class: Rival -Pic: Wally -Gender: Male -Music: Male -Double Battle: No -AI: Basic Trainer - -Ralts -Level: 16 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe - -=== TRAINER_WALLY_VR_2 === -Name: 满充 -Class: Rival -Pic: Wally -Gender: Male -Music: Male -Items: Full Restore / Full Restore -Double Battle: No -AI: Basic Trainer - -Altaria -Level: 47 -IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe -- Aerial Ace -- Safeguard -- Dragon Breath -- Dragon Dance - -Delcatty -Level: 46 -IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe -- Sing -- Assist -- Charm -- Feint Attack - -Roselia -Level: 47 -IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe -- Magical Leaf -- Leech Seed -- Giga Drain -- Toxic - -Magneton -Level: 44 -IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe -- Supersonic -- Thunderbolt -- Tri Attack -- Screech - -Gardevoir -Level: 48 -IVs: 30 HP / 30 Atk / 30 Def / 30 SpA / 30 SpD / 30 Spe -- Double Team -- Calm Mind -- Psychic -- Future Sight - -=== TRAINER_WALLY_VR_3 === -Name: 满充 -Class: Rival -Pic: Wally -Gender: Male -Music: Male -Items: Full Restore / Full Restore -Double Battle: No -AI: Basic Trainer - -Altaria -Level: 50 -IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe -- Aerial Ace -- Safeguard -- Dragon Breath -- Dragon Dance - -Delcatty -Level: 49 -IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe -- Sing -- Assist -- Charm -- Feint Attack - -Roselia -Level: 50 -IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe -- Magical Leaf -- Leech Seed -- Giga Drain -- Toxic - -Magneton -Level: 47 -IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe -- Supersonic -- Thunderbolt -- Tri Attack -- Screech - -Gardevoir -Level: 51 -IVs: 30 HP / 30 Atk / 30 Def / 30 SpA / 30 SpD / 30 Spe -- Double Team -- Calm Mind -- Psychic -- Future Sight - -=== TRAINER_WALLY_VR_4 === -Name: 满充 -Class: Rival -Pic: Wally -Gender: Male -Music: Male -Items: Full Restore / Full Restore -Double Battle: No -AI: Basic Trainer - -Altaria -Level: 53 -IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe -- Aerial Ace -- Safeguard -- Dragon Breath -- Dragon Dance - -Delcatty -Level: 52 -IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe -- Sing -- Assist -- Charm -- Feint Attack - -Roselia -Level: 53 -IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe -- Magical Leaf -- Leech Seed -- Giga Drain -- Toxic - -Magneton -Level: 50 -IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe -- Supersonic -- Thunderbolt -- Tri Attack -- Screech - -Gardevoir -Level: 54 -IVs: 30 HP / 30 Atk / 30 Def / 30 SpA / 30 SpD / 30 Spe -- Double Team -- Calm Mind -- Psychic -- Future Sight - -=== TRAINER_WALLY_VR_5 === -Name: 满充 -Class: Rival -Pic: Wally -Gender: Male -Music: Male -Items: Full Restore / Full Restore -Double Battle: No -AI: Basic Trainer - -Altaria -Level: 56 -IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe -- Aerial Ace -- Safeguard -- Dragon Breath -- Dragon Dance - -Delcatty -Level: 55 -IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe -- Sing -- Assist -- Charm -- Feint Attack - -Roselia -Level: 56 -IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe -- Magical Leaf -- Leech Seed -- Giga Drain -- Toxic - -Magneton -Level: 53 -IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe -- Supersonic -- Thunderbolt -- Tri Attack -- Screech - -Gardevoir -Level: 57 -IVs: 30 HP / 30 Atk / 30 Def / 30 SpA / 30 SpD / 30 Spe -- Double Team -- Calm Mind -- Psychic -- Future Sight - -=== TRAINER_BRENDAN_LILYCOVE_MUDKIP === -Name: 小悠 -Class: Rival -Pic: Brendan -Gender: Male -Music: Male -Double Battle: No -AI: Basic Trainer - -Tropius -Level: 31 -IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe - -Slugma -Level: 32 -IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe - -Pelipper -Level: 32 -IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe - -Grovyle -Level: 34 -IVs: 24 HP / 24 Atk / 24 Def / 24 SpA / 24 SpD / 24 Spe - -=== TRAINER_BRENDAN_LILYCOVE_TREECKO === -Name: 小悠 -Class: Rival -Pic: Brendan -Gender: Male -Music: Male -Double Battle: No -AI: Basic Trainer - -Tropius -Level: 31 -IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe - -Pelipper -Level: 32 -IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe - -Ludicolo -Level: 32 -IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe - -Combusken -Level: 34 -IVs: 24 HP / 24 Atk / 24 Def / 24 SpA / 24 SpD / 24 Spe - -=== TRAINER_BRENDAN_LILYCOVE_TORCHIC === -Name: 小悠 -Class: Rival -Pic: Brendan -Gender: Male -Music: Male -Double Battle: No -AI: Basic Trainer - -Tropius -Level: 31 -IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe - -Ludicolo -Level: 32 -IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe - -Slugma -Level: 32 -IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe - -Marshtomp -Level: 34 -IVs: 24 HP / 24 Atk / 24 Def / 24 SpA / 24 SpD / 24 Spe - -=== TRAINER_MAY_LILYCOVE_MUDKIP === -Name: 小遥 -Class: Rival -Pic: May -Gender: Female -Music: Female -Double Battle: No -AI: Basic Trainer - -Tropius -Level: 31 -IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe - -Slugma -Level: 32 -IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe - -Pelipper -Level: 32 -IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe - -Grovyle -Level: 34 -IVs: 24 HP / 24 Atk / 24 Def / 24 SpA / 24 SpD / 24 Spe - -=== TRAINER_MAY_LILYCOVE_TREECKO === -Name: 小遥 -Class: Rival -Pic: May -Gender: Female -Music: Female -Double Battle: No -AI: Basic Trainer - -Tropius -Level: 31 -IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe - -Pelipper -Level: 32 -IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe - -Ludicolo -Level: 32 -IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe - -Combusken -Level: 34 -IVs: 24 HP / 24 Atk / 24 Def / 24 SpA / 24 SpD / 24 Spe - -=== TRAINER_MAY_LILYCOVE_TORCHIC === -Name: 小遥 -Class: Rival -Pic: May -Gender: Female -Music: Female -Double Battle: No -AI: Basic Trainer - -Tropius -Level: 31 -IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe - -Ludicolo -Level: 32 -IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe - -Slugma -Level: 32 -IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe - -Marshtomp -Level: 34 -IVs: 24 HP / 24 Atk / 24 Def / 24 SpA / 24 SpD / 24 Spe - -=== TRAINER_JONAH === -Name: 善德 -Class: Fisherman -Pic: Fisherman -Gender: Male -Music: Hiker -Double Battle: No -AI: Check Bad Move - -Wailmer -Level: 30 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Tentacool -Level: 31 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Sharpedo -Level: 32 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_HENRY === -Name: 健太郎 -Class: Fisherman -Pic: Fisherman -Gender: Male -Music: Hiker -Double Battle: No -AI: Check Bad Move - -Carvanha -Level: 31 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Tentacruel -Level: 34 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_ROGER === -Name: 智彦 -Class: Fisherman -Pic: Fisherman -Gender: Male -Music: Hiker -Double Battle: No -AI: Check Bad Move - -Magikarp -Level: 15 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Magikarp -Level: 25 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Gyarados -Level: 35 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_ALEXA === -Name: 明香 -Class: Cooltrainer -Pic: Cooltrainer F -Gender: Female -Music: Cool -Items: Full Restore -Double Battle: No -AI: Basic Trainer - -Gloom -Level: 34 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -Azumarill -Level: 34 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -=== TRAINER_RUBEN === -Name: 驯 -Class: Cooltrainer -Pic: Cooltrainer M -Gender: Male -Music: Cool -Items: Hyper Potion -Double Battle: No -AI: Basic Trainer - -Shiftry -Level: 34 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -Nosepass -Level: 34 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -=== TRAINER_KOJI_1 === -Name: 铁郎 -Class: Black Belt -Pic: Black Belt -Gender: Male -Music: Intense -Double Battle: No -AI: Check Bad Move - -Machoke -Level: 34 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_WAYNE === -Name: 孝作 -Class: Fisherman -Pic: Fisherman -Gender: Male -Music: Hiker -Double Battle: No -AI: Check Bad Move - -Tentacool -Level: 31 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Tentacool -Level: 31 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Wailmer -Level: 36 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_AIDAN === -Name: 郁夫 -Class: Bird Keeper -Pic: Bird Keeper -Gender: Male -Music: Cool -Double Battle: No -AI: Check Bad Move - -Swellow -Level: 32 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Skarmory -Level: 32 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_REED === -Name: 明夫 -Class: Swimmer M -Pic: Swimmer M -Gender: Male -Music: Swimmer -Double Battle: No -AI: Check Bad Move - -Spheal -Level: 33 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Sharpedo -Level: 33 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_TISHA === -Name: 由佳理 -Class: Swimmer F -Pic: Swimmer F -Gender: Female -Music: Swimmer -Double Battle: No -AI: Check Bad Move - -Chinchou -Level: 34 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_TORI_AND_TIA === -Name: 奈奈和宁宁 -Class: Twins -Pic: Twins -Gender: Male -Music: Twins -Double Battle: Yes -AI: Check Bad Move - -Spinda -Level: 19 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Spinda -Level: 19 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_KIM_AND_IRIS === -Name: 真穗和奈穗 -Class: Sr And Jr -Pic: Sr And Jr -Gender: Male -Music: Twins -Double Battle: Yes -AI: Check Bad Move - -Swablu -Level: 32 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe -- Sing -- Fury Attack -- Safeguard -- Aerial Ace - -Numel -Level: 35 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe -- Flamethrower -- Take Down -- Rest -- Earthquake - -=== TRAINER_TYRA_AND_IVY === -Name: 佳代和依代 -Class: Sr And Jr -Pic: Sr And Jr -Gender: Male -Music: Twins -Double Battle: Yes -AI: Check Bad Move - -Roselia -Level: 18 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe -- Growth -- Stun Spore -- Mega Drain -- Leech Seed - -Graveler -Level: 20 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe -- Defense Curl -- Rollout -- Mud Sport -- Rock Throw - -=== TRAINER_MEL_AND_PAUL === -Name: 志木和理树 -Class: Young Couple -Pic: Young Couple -Gender: Male -Music: Girl -Double Battle: Yes -AI: Check Bad Move - -Dustox -Level: 27 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe -- Gust -- Psybeam -- Toxic -- Protect - -Beautifly -Level: 27 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe -- Gust -- Mega Drain -- Attract -- Stun Spore - -=== TRAINER_JOHN_AND_JAY_1 === -Name: 源和初 -Class: Old Couple -Pic: Old Couple -Gender: Male -Music: Intense -Double Battle: Yes -AI: Basic Trainer - -Medicham -Level: 39 -IVs: 24 HP / 24 Atk / 24 Def / 24 SpA / 24 SpD / 24 Spe -- Psychic -- Fire Punch -- Psych Up -- Protect - -Hariyama -Level: 39 -IVs: 24 HP / 24 Atk / 24 Def / 24 SpA / 24 SpD / 24 Spe -- Focus Punch -- Rock Tomb -- Rest -- Belly Drum - -=== TRAINER_JOHN_AND_JAY_2 === -Name: 源和初 -Class: Old Couple -Pic: Old Couple -Gender: Male -Music: Intense -Double Battle: Yes -AI: Basic Trainer - -Medicham -Level: 43 -IVs: 25 HP / 25 Atk / 25 Def / 25 SpA / 25 SpD / 25 Spe -- Psychic -- Fire Punch -- Psych Up -- Protect - -Hariyama -Level: 43 -IVs: 25 HP / 25 Atk / 25 Def / 25 SpA / 25 SpD / 25 Spe -- Focus Punch -- Rock Tomb -- Rest -- Belly Drum - -=== TRAINER_JOHN_AND_JAY_3 === -Name: 源和初 -Class: Old Couple -Pic: Old Couple -Gender: Male -Music: Intense -Double Battle: Yes -AI: Basic Trainer - -Medicham -Level: 46 -IVs: 26 HP / 26 Atk / 26 Def / 26 SpA / 26 SpD / 26 Spe -- Psychic -- Fire Punch -- Psych Up -- Protect - -Hariyama -Level: 46 -IVs: 26 HP / 26 Atk / 26 Def / 26 SpA / 26 SpD / 26 Spe -- Focus Punch -- Rock Tomb -- Rest -- Belly Drum - -=== TRAINER_JOHN_AND_JAY_4 === -Name: 源和初 -Class: Old Couple -Pic: Old Couple -Gender: Male -Music: Intense -Double Battle: Yes -AI: Check Bad Move / Try To Faint / Force Setup First Turn - -Medicham -Level: 49 -IVs: 27 HP / 27 Atk / 27 Def / 27 SpA / 27 SpD / 27 Spe -- Psychic -- Fire Punch -- Psych Up -- Protect - -Hariyama -Level: 49 -IVs: 27 HP / 27 Atk / 27 Def / 27 SpA / 27 SpD / 27 Spe -- Focus Punch -- Rock Tomb -- Rest -- Belly Drum - -=== TRAINER_JOHN_AND_JAY_5 === -Name: 源和初 -Class: Old Couple -Pic: Old Couple -Gender: Male -Music: Intense -Double Battle: Yes -AI: Basic Trainer - -Medicham -Level: 52 -IVs: 29 HP / 29 Atk / 29 Def / 29 SpA / 29 SpD / 29 Spe -- Psychic -- Fire Punch -- Psych Up -- Protect - -Hariyama -Level: 52 -IVs: 29 HP / 29 Atk / 29 Def / 29 SpA / 29 SpD / 29 Spe -- Focus Punch -- Rock Tomb -- Rest -- Belly Drum - -=== TRAINER_RELI_AND_IAN === -Name: 胜和亚美 -Class: Sis And Bro -Pic: Sis And Bro -Gender: Male -Music: Swimmer -Double Battle: Yes -AI: Check Bad Move - -Azumarill -Level: 35 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Wingull -Level: 33 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_LILA_AND_ROY_1 === -Name: 小勇和佳子 -Class: Sis And Bro -Pic: Sis And Bro -Gender: Male -Music: Swimmer -Double Battle: Yes -AI: Check Bad Move - -Chinchou -Level: 34 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Carvanha -Level: 33 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_LILA_AND_ROY_2 === -Name: 小勇和佳子 -Class: Sis And Bro -Pic: Sis And Bro -Gender: Male -Music: Swimmer -Double Battle: Yes -AI: Check Bad Move - -Chinchou -Level: 42 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Carvanha -Level: 40 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_LILA_AND_ROY_3 === -Name: 小勇和佳子 -Class: Sis And Bro -Pic: Sis And Bro -Gender: Male -Music: Swimmer -Double Battle: Yes -AI: Check Bad Move - -Lanturn -Level: 45 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Carvanha -Level: 43 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_LILA_AND_ROY_4 === -Name: 小勇和佳子 -Class: Sis And Bro -Pic: Sis And Bro -Gender: Male -Music: Swimmer -Double Battle: Yes -AI: Check Bad Move - -Lanturn -Level: 48 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Sharpedo -Level: 46 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_LILA_AND_ROY_5 === -Name: 小勇和佳子 -Class: Sis And Bro -Pic: Sis And Bro -Gender: Male -Music: Swimmer -Double Battle: Yes -AI: Check Bad Move - -Lanturn -Level: 51 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Sharpedo -Level: 49 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_LISA_AND_RAY === -Name: 真和由美 -Class: Sis And Bro -Pic: Sis And Bro -Gender: Male -Music: Swimmer -Double Battle: Yes -AI: Check Bad Move - -Goldeen -Level: 27 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Tentacool -Level: 25 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_CHRIS === -Name: 正志 -Class: Fisherman -Pic: Fisherman -Gender: Male -Music: Hiker -Double Battle: No -AI: Check Bad Move - -Magikarp -Level: 29 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Tentacool -Level: 20 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Feebas -Level: 26 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Carvanha -Level: 23 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_DAWSON === -Name: 希望 -Class: Rich Boy -Pic: Rich Boy -Gender: Male -Music: Rich -Double Battle: No -AI: Check Bad Move - -Zigzagoon @ Nugget -Level: 8 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Poochyena -Level: 8 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_SARAH === -Name: 樱子 -Class: Lady -Pic: Lady -Gender: Female -Music: Female -Items: Full Restore -Double Battle: No -AI: Check Bad Move - -Lotad -Level: 8 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Zigzagoon @ Nugget -Level: 8 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_DARIAN === -Name: 健吉 -Class: Fisherman -Pic: Fisherman -Gender: Male -Music: Hiker -Double Battle: No -AI: Check Bad Move - -Magikarp -Level: 9 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_HAILEY === -Name: 小华 -Class: Tuber F -Pic: Tuber F -Gender: Female -Music: Girl -Double Battle: No -AI: Check Bad Move - -Marill -Level: 13 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_CHANDLER === -Name: 大辅 -Class: Tuber M -Pic: Tuber M -Gender: Male -Music: Girl -Double Battle: No -AI: Check Bad Move - -Tentacool -Level: 12 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Tentacool -Level: 12 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_KALEB === -Name: 雅贵 -Class: Pokefan -Pic: Pokefan M -Gender: Male -Music: Twins -Double Battle: No -AI: Check Bad Move - -Minun @ Oran Berry -Level: 14 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Plusle @ Oran Berry -Level: 14 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_JOSEPH === -Name: 保罗 -Class: Guitarist -Pic: Guitarist -Gender: Male -Music: Intense -Double Battle: No -AI: Check Bad Move - -Electrike -Level: 14 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Voltorb -Level: 14 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_ALYSSA === -Name: 冴美 -Class: Triathlete -Pic: Cycling Triathlete F -Gender: Female -Music: Female -Double Battle: No -AI: Check Bad Move - -Magnemite -Level: 15 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_MARCOS === -Name: 埃力克 -Class: Guitarist -Pic: Guitarist -Gender: Male -Music: Intense -Double Battle: No -AI: Check Bad Move - -Voltorb -Level: 15 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -=== TRAINER_RHETT === -Name: 茂森 -Class: Black Belt -Pic: Black Belt -Gender: Male -Music: Intense -Double Battle: No -AI: Check Bad Move - -Makuhita -Level: 15 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -=== TRAINER_TYRON === -Name: 俊文 -Class: Camper -Pic: Camper -Gender: Male -Music: Male -Double Battle: No -AI: Check Bad Move - -Sandshrew -Level: 19 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_CELINA === -Name: 和香子 -Class: Aroma Lady -Pic: Aroma Lady -Gender: Female -Music: Female -Double Battle: No -AI: Check Bad Move - -Roselia -Level: 18 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_BIANCA === -Name: 伊织 -Class: Picnicker -Pic: Picnicker -Gender: Female -Music: Girl -Double Battle: No -AI: Check Bad Move - -Shroomish -Level: 18 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_HAYDEN === -Name: 国明 -Class: Kindler -Pic: Kindler -Gender: Male -Music: Hiker -Double Battle: No -AI: Check Bad Move - -Numel -Level: 18 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_SOPHIE === -Name: 长闲 -Class: Picnicker -Pic: Picnicker -Gender: Female -Music: Girl -Double Battle: No -AI: Check Bad Move - -Marill -Level: 17 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Lombre -Level: 19 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_COBY === -Name: 和高 -Class: Bird Keeper -Pic: Bird Keeper -Gender: Male -Music: Cool -Double Battle: No -AI: Check Bad Move - -Skarmory -Level: 17 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Swellow -Level: 19 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_LAWRENCE === -Name: 勇吾 -Class: Camper -Pic: Camper -Gender: Male -Music: Male -Double Battle: No -AI: Check Bad Move - -Baltoy -Level: 18 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Sandshrew -Level: 18 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_WYATT === -Name: 道夫 -Class: Pokemaniac -Pic: Pokemaniac -Gender: Male -Music: Suspicious -Double Battle: No -AI: Check Bad Move - -Aron -Level: 18 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Aron -Level: 18 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_ANGELINA === -Name: 茉莉 -Class: Picnicker -Pic: Picnicker -Gender: Female -Music: Girl -Double Battle: No -AI: Check Bad Move - -Lombre -Level: 18 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Marill -Level: 18 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_KAI === -Name: 宏光 -Class: Fisherman -Pic: Fisherman -Gender: Male -Music: Hiker -Double Battle: No -AI: Check Bad Move - -Barboach -Level: 19 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_CHARLOTTE === -Name: 美波 -Class: Picnicker -Pic: Picnicker -Gender: Female -Music: Girl -Double Battle: No -AI: Check Bad Move - -Nuzleaf -Level: 19 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_DEANDRE === -Name: 雅也 -Class: Youngster -Pic: Youngster -Gender: Male -Music: Male -Double Battle: No -AI: Check Bad Move - -Zigzagoon -Level: 14 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Aron -Level: 14 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Electrike -Level: 14 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_GRUNT_MAGMA_HIDEOUT_1 === -Name: 手下 -Class: Team Magma -Pic: Magma Grunt M -Gender: Male -Music: Magma -Double Battle: No -AI: Check Bad Move - -Zubat -Level: 29 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_GRUNT_MAGMA_HIDEOUT_2 === -Name: 手下 -Class: Team Magma -Pic: Magma Grunt M -Gender: Male -Music: Magma -Double Battle: No -AI: Check Bad Move - -Poochyena -Level: 29 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_GRUNT_MAGMA_HIDEOUT_3 === -Name: 手下 -Class: Team Magma -Pic: Magma Grunt M -Gender: Male -Music: Magma -Double Battle: No -AI: Check Bad Move - -Numel -Level: 29 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_GRUNT_MAGMA_HIDEOUT_4 === -Name: 手下 -Class: Team Magma -Pic: Magma Grunt M -Gender: Male -Music: Magma -Double Battle: No -AI: Check Bad Move - -Baltoy -Level: 28 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Zubat -Level: 28 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_GRUNT_MAGMA_HIDEOUT_5 === -Name: 手下 -Class: Team Magma -Pic: Magma Grunt M -Gender: Male -Music: Magma -Double Battle: No -AI: Check Bad Move - -Baltoy -Level: 28 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Numel -Level: 28 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_GRUNT_MAGMA_HIDEOUT_6 === -Name: 手下 -Class: Team Magma -Pic: Magma Grunt M -Gender: Male -Music: Magma -Double Battle: No -AI: Check Bad Move - -Mightyena -Level: 29 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_GRUNT_MAGMA_HIDEOUT_7 === -Name: 手下 -Class: Team Magma -Pic: Magma Grunt M -Gender: Male -Music: Magma -Double Battle: No -AI: Check Bad Move - -Zubat -Level: 29 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_GRUNT_MAGMA_HIDEOUT_8 === -Name: 手下 -Class: Team Magma -Pic: Magma Grunt M -Gender: Male -Music: Magma -Double Battle: No -AI: Check Bad Move - -Poochyena -Level: 29 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_GRUNT_MAGMA_HIDEOUT_9 === -Name: 手下 -Class: Team Magma -Pic: Magma Grunt M -Gender: Male -Music: Magma -Double Battle: No -AI: Check Bad Move - -Zubat -Level: 29 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_GRUNT_MAGMA_HIDEOUT_10 === -Name: 手下 -Class: Team Magma -Pic: Magma Grunt M -Gender: Male -Music: Magma -Double Battle: No -AI: Check Bad Move - -Mightyena -Level: 29 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_GRUNT_MAGMA_HIDEOUT_11 === -Name: 手下 -Class: Team Magma -Pic: Magma Grunt M -Gender: Male -Music: Magma -Double Battle: No -AI: Check Bad Move - -Baltoy -Level: 29 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_GRUNT_MAGMA_HIDEOUT_12 === -Name: 手下 -Class: Team Magma -Pic: Magma Grunt M -Gender: Male -Music: Magma -Double Battle: No -AI: Check Bad Move - -Numel -Level: 29 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_GRUNT_MAGMA_HIDEOUT_13 === -Name: 手下 -Class: Team Magma -Pic: Magma Grunt M -Gender: Male -Music: Magma -Double Battle: No -AI: Check Bad Move - -Zubat -Level: 29 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_GRUNT_MAGMA_HIDEOUT_14 === -Name: 手下 -Class: Team Magma -Pic: Magma Grunt F -Gender: Female -Music: Magma -Double Battle: No -AI: Check Bad Move - -Mightyena -Level: 29 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_GRUNT_MAGMA_HIDEOUT_15 === -Name: 手下 -Class: Team Magma -Pic: Magma Grunt F -Gender: Female -Music: Magma -Double Battle: No -AI: Check Bad Move - -Numel -Level: 29 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_GRUNT_MAGMA_HIDEOUT_16 === -Name: 手下 -Class: Team Magma -Pic: Magma Grunt F -Gender: Female -Music: Magma -Double Battle: No -AI: Check Bad Move - -Baltoy -Level: 29 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_TABITHA_MAGMA_HIDEOUT === -Name: 火村 -Class: Magma Admin -Pic: Magma Admin -Gender: Male -Music: Magma -Double Battle: No -AI: Check Bad Move - -Numel -Level: 26 -IVs: 9 HP / 9 Atk / 9 Def / 9 SpA / 9 SpD / 9 Spe - -Mightyena -Level: 28 -IVs: 9 HP / 9 Atk / 9 Def / 9 SpA / 9 SpD / 9 Spe - -Zubat -Level: 30 -IVs: 9 HP / 9 Atk / 9 Def / 9 SpA / 9 SpD / 9 Spe - -Camerupt -Level: 33 -IVs: 9 HP / 9 Atk / 9 Def / 9 SpA / 9 SpD / 9 Spe - -=== TRAINER_DARCY === -Name: 成美 -Class: Cooltrainer -Pic: Cooltrainer F -Gender: Female -Music: Cool -Items: Hyper Potion -Double Battle: No -AI: Basic Trainer - -Pelipper -Level: 33 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Camerupt -Level: 33 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_MAXIE_MOSSDEEP === -Name: 赤焰松 -Class: Magma Leader -Pic: Magma Leader Maxie -Gender: Male -Music: Magma -Double Battle: No -AI: Basic Trainer - -Mightyena -Level: 42 -IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe - -Crobat -Level: 43 -IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe - -Camerupt -Level: 44 -IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe - -=== TRAINER_PETE === -Name: 秀彦 -Class: Swimmer M -Pic: Swimmer M -Gender: Male -Music: Swimmer -Double Battle: No -AI: Check Bad Move - -Tentacool -Level: 15 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_ISABELLE === -Name: 由美子 -Class: Swimmer F -Pic: Swimmer F -Gender: Female -Music: Swimmer -Double Battle: No -AI: Check Bad Move - -Marill -Level: 15 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_ANDRES_1 === -Name: 大次郎 -Class: Ruin Maniac -Pic: Ruin Maniac -Gender: Male -Music: Hiker -Double Battle: No -AI: Check Bad Move - -Sandshrew -Level: 25 -IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe - -Sandshrew -Level: 25 -IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe - -=== TRAINER_JOSUE === -Name: 康文 -Class: Bird Keeper -Pic: Bird Keeper -Gender: Male -Music: Cool -Double Battle: No -AI: Check Bad Move - -Taillow -Level: 25 -IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe - -Wingull -Level: 25 -IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe - -=== TRAINER_CAMRON === -Name: 国男 -Class: Triathlete -Pic: Swimming Triathlete M -Gender: Male -Music: Swimmer -Double Battle: No -AI: Check Bad Move - -Staryu -Level: 26 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_CORY_1 === -Name: 典孝 -Class: Sailor -Pic: Sailor -Gender: Male -Music: Male -Double Battle: No -AI: Check Bad Move - -Wingull -Level: 24 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Machop -Level: 24 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Tentacool -Level: 24 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_CAROLINA === -Name: 圣华 -Class: Cooltrainer -Pic: Cooltrainer F -Gender: Female -Music: Cool -Items: Hyper Potion -Double Battle: No -AI: Basic Trainer - -Manectric -Level: 24 -IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe - -Swellow -Level: 24 -IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe - -Manectric -Level: 24 -IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe - -=== TRAINER_ELIJAH === -Name: 俊隆 -Class: Bird Keeper -Pic: Bird Keeper -Gender: Male -Music: Cool -Double Battle: No -AI: Check Bad Move - -Skarmory -Level: 25 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Skarmory -Level: 25 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_CELIA === -Name: 亚希子 -Class: Picnicker -Pic: Picnicker -Gender: Female -Music: Girl -Double Battle: No -AI: Check Bad Move - -Marill -Level: 22 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Lombre -Level: 22 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_BRYAN === -Name: 博敏 -Class: Ruin Maniac -Pic: Ruin Maniac -Gender: Male -Music: Hiker -Double Battle: No -AI: Check Bad Move - -Sandshrew -Level: 22 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Sandslash -Level: 22 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_BRANDEN === -Name: 康范 -Class: Camper -Pic: Camper -Gender: Male -Music: Male -Double Battle: No -AI: Check Bad Move - -Taillow -Level: 22 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Nuzleaf -Level: 22 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_BRYANT === -Name: 敦夫 -Class: Kindler -Pic: Kindler -Gender: Male -Music: Hiker -Double Battle: No -AI: Check Bad Move - -Numel -Level: 18 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Slugma -Level: 18 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_SHAYLA === -Name: 妙子 -Class: Aroma Lady -Pic: Aroma Lady -Gender: Female -Music: Female -Double Battle: No -AI: Check Bad Move - -Shroomish -Level: 18 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Roselia -Level: 18 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_KYRA === -Name: 凛子 -Class: Triathlete -Pic: Running Triathlete F -Gender: Female -Music: Female -Double Battle: No -AI: Check Bad Move - -Doduo -Level: 26 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Dodrio -Level: 26 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_JAIDEN === -Name: 勇藏 -Class: Ninja Boy -Pic: Ninja Boy -Gender: Male -Music: Suspicious -Double Battle: No -AI: Check Bad Move - -Ninjask -Level: 26 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Gulpin -Level: 26 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_ALIX === -Name: 诗乃 -Class: Psychic -Pic: Psychic F -Gender: Female -Music: Intense -Double Battle: No -AI: Check Bad Move - -Kadabra -Level: 26 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Kirlia -Level: 26 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_HELENE === -Name: 千岁 -Class: Battle Girl -Pic: Battle Girl -Gender: Female -Music: Intense -Double Battle: No -AI: Check Bad Move - -Meditite -Level: 26 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Makuhita -Level: 26 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_MARLENE === -Name: 璃音 -Class: Psychic -Pic: Psychic F -Gender: Female -Music: Intense -Double Battle: No -AI: Check Bad Move - -Meditite -Level: 18 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Spoink -Level: 18 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_DEVAN === -Name: 通泰 -Class: Hiker -Pic: Hiker -Gender: Male -Music: Hiker -Double Battle: No -AI: Check Bad Move - -Geodude -Level: 8 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Geodude -Level: 8 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_JOHNSON === -Name: 有利 -Class: Youngster -Pic: Youngster -Gender: Male -Music: Male -Double Battle: No -AI: Check Bad Move - -Shroomish -Level: 8 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Lotad -Level: 8 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_MELINA === -Name: 素子 -Class: Triathlete -Pic: Running Triathlete F -Gender: Female -Music: Female -Double Battle: No -AI: Check Bad Move - -Doduo -Level: 17 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_BRANDI === -Name: 圣夏 -Class: Psychic -Pic: Psychic F -Gender: Female -Music: Intense -Double Battle: No -AI: Check Bad Move - -Ralts -Level: 17 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_AISHA === -Name: 诗茉 -Class: Battle Girl -Pic: Battle Girl -Gender: Female -Music: Intense -Double Battle: No -AI: Check Bad Move - -Meditite -Level: 17 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_MAKAYLA === -Name: 铃 -Class: Expert -Pic: Expert F -Gender: Female -Music: Intense -Items: Hyper Potion -Double Battle: No -AI: Basic Trainer - -Roselia -Level: 33 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Medicham -Level: 33 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_FABIAN === -Name: 吉米 -Class: Guitarist -Pic: Guitarist -Gender: Male -Music: Intense -Double Battle: No -AI: Check Bad Move - -Manectric -Level: 26 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_DAYTON === -Name: 淳宏 -Class: Kindler -Pic: Kindler -Gender: Male -Music: Hiker -Double Battle: No -AI: Check Bad Move - -Slugma -Level: 25 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Numel -Level: 25 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_RACHEL === -Name: 观月 -Class: Parasol Lady -Pic: Parasol Lady -Gender: Female -Music: Female -Double Battle: No -AI: Check Bad Move - -Goldeen -Level: 26 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_LEONEL === -Name: 和宏 -Class: Cooltrainer -Pic: Cooltrainer M -Gender: Male -Music: Cool -Items: Hyper Potion -Double Battle: No -AI: Basic Trainer - -Manectric -Level: 30 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe -- Thunder -- Quick Attack -- Thunder Wave - -=== TRAINER_CALLIE === -Name: 风子 -Class: Battle Girl -Pic: Battle Girl -Gender: Female -Music: Intense -Double Battle: No -AI: Check Bad Move - -Meditite -Level: 28 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Makuhita -Level: 28 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_CALE === -Name: 健介 -Class: Bug Maniac -Pic: Bug Maniac -Gender: Male -Music: Suspicious -Double Battle: No -AI: Check Bad Move - -Dustox -Level: 29 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Beautifly -Level: 29 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_MYLES === -Name: 康夫 -Class: Pkmn Breeder -Pic: Pokemon Breeder M -Gender: Male -Music: Male -Double Battle: No -AI: Check Bad Move - -Makuhita -Level: 25 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe - -Wingull -Level: 25 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe - -Tropius -Level: 25 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe - -Zigzagoon -Level: 25 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe - -Electrike -Level: 25 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe - -Numel -Level: 25 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe - -=== TRAINER_PAT === -Name: 春衣 -Class: Pkmn Breeder -Pic: Pokemon Breeder F -Gender: Female -Music: Female -Double Battle: No -AI: Check Bad Move - -Poochyena -Level: 25 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe - -Shroomish -Level: 25 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe - -Electrike -Level: 25 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe - -Marill -Level: 25 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe - -Sandshrew -Level: 25 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe - -Gulpin -Level: 25 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe - -=== TRAINER_CRISTIN_1 === -Name: 登纪子 -Class: Cooltrainer -Pic: Cooltrainer F -Gender: Female -Music: Cool -Items: Hyper Potion -Double Battle: No -AI: Basic Trainer - -Loudred -Level: 29 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -Vigoroth -Level: 29 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -=== TRAINER_MAY_RUSTBORO_TREECKO === -Name: 小遥 -Class: Rival -Pic: May -Gender: Female -Music: Female -Double Battle: No -AI: Basic Trainer - -Lotad -Level: 13 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe - -Torchic -Level: 15 -IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe - -=== TRAINER_MAY_RUSTBORO_TORCHIC === -Name: 小遥 -Class: Rival -Pic: May -Gender: Female -Music: Female -Double Battle: No -AI: Basic Trainer - -Torkoal -Level: 13 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe - -Mudkip -Level: 15 -IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe - -=== TRAINER_ROXANNE_2 === -Name: 杜娟 -Class: Leader -Pic: Leader Roxanne -Gender: Female -Music: Female -Items: Full Restore / Full Restore / Full Restore -Double Battle: Yes -AI: Basic Trainer - -Golem -Level: 32 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Protect -- Rollout -- Magnitude -- Explosion - -Kabuto @ Sitrus Berry -Level: 35 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Swords Dance -- Ice Beam -- Surf -- Rock Slide - -Onix -Level: 35 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Iron Tail -- Explosion -- Roar -- Rock Slide - -Nosepass @ Sitrus Berry -Level: 37 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Double Team -- Explosion -- Protect -- Rock Slide - -=== TRAINER_ROXANNE_3 === -Name: 杜娟 -Class: Leader -Pic: Leader Roxanne -Gender: Female -Music: Female -Items: Full Restore / Full Restore / Full Restore -Double Battle: Yes -AI: Basic Trainer - -Omanyte -Level: 37 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Protect -- Ice Beam -- Rock Slide -- Surf - -Golem -Level: 37 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Protect -- Rollout -- Magnitude -- Explosion - -Kabutops @ Sitrus Berry -Level: 40 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Swords Dance -- Ice Beam -- Surf -- Rock Slide - -Onix -Level: 40 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Iron Tail -- Explosion -- Roar -- Rock Slide - -Nosepass @ Sitrus Berry -Level: 42 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Double Team -- Explosion -- Protect -- Rock Slide - -=== TRAINER_ROXANNE_4 === -Name: 杜娟 -Class: Leader -Pic: Leader Roxanne -Gender: Female -Music: Female -Items: Full Restore / Full Restore / Full Restore -Double Battle: Yes -AI: Basic Trainer - -Omastar -Level: 42 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Protect -- Ice Beam -- Rock Slide -- Surf - -Golem -Level: 42 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Protect -- Rollout -- Earthquake -- Explosion - -Kabutops @ Sitrus Berry -Level: 45 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Swords Dance -- Ice Beam -- Surf -- Rock Slide - -Onix -Level: 45 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Iron Tail -- Explosion -- Roar -- Rock Slide - -Nosepass @ Sitrus Berry -Level: 47 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Double Team -- Explosion -- Protect -- Rock Slide - -=== TRAINER_ROXANNE_5 === -Name: 杜娟 -Class: Leader -Pic: Leader Roxanne -Gender: Female -Music: Female -Items: Full Restore / Full Restore / Full Restore -Double Battle: Yes -AI: Basic Trainer - -Aerodactyl -Level: 47 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Rock Slide -- Hyper Beam -- Supersonic -- Protect - -Golem -Level: 47 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Focus Punch -- Rollout -- Earthquake -- Explosion - -Omastar -Level: 47 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Protect -- Ice Beam -- Rock Slide -- Surf - -Kabutops @ Sitrus Berry -Level: 50 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Swords Dance -- Ice Beam -- Surf -- Rock Slide - -Steelix -Level: 50 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Iron Tail -- Explosion -- Roar -- Rock Slide - -Nosepass @ Sitrus Berry -Level: 52 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Double Team -- Explosion -- Protect -- Rock Slide - -=== TRAINER_BRAWLY_2 === -Name: 藤树 -Class: Leader -Pic: Leader Brawly -Gender: Male -Music: Male -Items: Full Restore / Full Restore / Full Restore -Double Battle: Yes -AI: Basic Trainer - -Machamp @ Sitrus Berry -Level: 33 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Karate Chop -- Rock Slide -- Focus Punch -- Bulk Up - -Meditite -Level: 33 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Psychic -- Light Screen -- Reflect -- Focus Punch - -Hitmontop -Level: 35 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Pursuit -- Counter -- Protect -- Triple Kick - -Hariyama @ Sitrus Berry -Level: 37 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Fake Out -- Focus Punch -- Belly Drum -- Earthquake - -=== TRAINER_BRAWLY_3 === -Name: 藤树 -Class: Leader -Pic: Leader Brawly -Gender: Male -Music: Male -Items: Full Restore / Full Restore / Full Restore -Double Battle: Yes -AI: Basic Trainer - -Machamp @ Sitrus Berry -Level: 38 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Karate Chop -- Rock Slide -- Focus Punch -- Bulk Up - -Medicham -Level: 38 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Psychic -- Light Screen -- Reflect -- Focus Punch - -Hitmontop -Level: 40 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Pursuit -- Counter -- Protect -- Triple Kick - -Hariyama @ Sitrus Berry -Level: 42 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Fake Out -- Focus Punch -- Belly Drum -- Earthquake - -=== TRAINER_BRAWLY_4 === -Name: 藤树 -Class: Leader -Pic: Leader Brawly -Gender: Male -Music: Male -Items: Full Restore / Full Restore / Full Restore -Double Battle: Yes -AI: Basic Trainer - -Hitmonchan -Level: 40 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Sky Uppercut -- Protect -- Fire Punch -- Ice Punch - -Machamp @ Sitrus Berry -Level: 43 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Karate Chop -- Rock Slide -- Focus Punch -- Bulk Up - -Medicham -Level: 43 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Focus Punch -- Light Screen -- Reflect -- Psychic - -Hitmontop -Level: 45 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Pursuit -- Counter -- Protect -- Triple Kick - -Hariyama @ Sitrus Berry -Level: 47 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Fake Out -- Focus Punch -- Belly Drum -- Earthquake - -=== TRAINER_BRAWLY_5 === -Name: 藤树 -Class: Leader -Pic: Leader Brawly -Gender: Male -Music: Male -Items: Full Restore / Full Restore / Full Restore -Double Battle: Yes -AI: Basic Trainer - -Hitmonlee -Level: 46 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Mega Kick -- Focus Punch -- Earthquake -- Bulk Up - -Hitmonchan -Level: 46 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Sky Uppercut -- Protect -- Fire Punch -- Ice Punch - -Machamp @ Sitrus Berry -Level: 48 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Cross Chop -- Rock Slide -- Focus Punch -- Bulk Up - -Medicham -Level: 48 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Focus Punch -- Light Screen -- Reflect -- Psychic - -Hitmontop -Level: 50 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Pursuit -- Counter -- Protect -- Triple Kick - -Hariyama @ Sitrus Berry -Level: 52 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Fake Out -- Focus Punch -- Belly Drum -- Earthquake - -=== TRAINER_WATTSON_2 === -Name: 铁旋 -Class: Leader -Pic: Leader Wattson -Gender: Male -Music: Male -Items: Full Restore / Full Restore / Full Restore -Double Battle: Yes -AI: Basic Trainer - -Mareep -Level: 36 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Thunder -- Protect -- Thunder Wave -- Light Screen - -Electrode -Level: 36 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Rollout -- Thunder -- Explosion -- Rain Dance - -Magneton @ Sitrus Berry -Level: 38 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Supersonic -- Protect -- Thunder -- Rain Dance - -Manectric @ Sitrus Berry -Level: 40 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Bite -- Thunder Wave -- Thunder -- Protect - -=== TRAINER_WATTSON_3 === -Name: 铁旋 -Class: Leader -Pic: Leader Wattson -Gender: Male -Music: Male -Items: Full Restore / Full Restore / Full Restore -Double Battle: Yes -AI: Basic Trainer - -Pikachu -Level: 39 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Thunder -- Slam -- Rain Dance -- Shock Wave - -Flaaffy -Level: 41 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Thunder -- Protect -- Thunder Wave -- Light Screen - -Electrode -Level: 41 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Rollout -- Thunder -- Explosion -- Rain Dance - -Magneton @ Sitrus Berry -Level: 43 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Supersonic -- Protect -- Thunder -- Rain Dance - -Manectric @ Sitrus Berry -Level: 45 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Bite -- Thunder Wave -- Thunder -- Protect - -=== TRAINER_WATTSON_4 === -Name: 铁旋 -Class: Leader -Pic: Leader Wattson -Gender: Male -Music: Male -Items: Full Restore / Full Restore / Full Restore -Double Battle: Yes -AI: Basic Trainer - -Raichu -Level: 44 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Thunder -- Slam -- Rain Dance -- Protect - -Ampharos -Level: 46 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Thunder -- Protect -- Thunder Wave -- Light Screen - -Electrode -Level: 46 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Rollout -- Thunder -- Explosion -- Rain Dance - -Magneton @ Sitrus Berry -Level: 48 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Supersonic -- Protect -- Thunder -- Rain Dance - -Manectric @ Sitrus Berry -Level: 50 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Bite -- Thunder Wave -- Thunder -- Protect - -=== TRAINER_WATTSON_5 === -Name: 铁旋 -Class: Leader -Pic: Leader Wattson -Gender: Male -Music: Male -Items: Full Restore / Full Restore / Full Restore -Double Battle: Yes -AI: Basic Trainer - -Electabuzz -Level: 50 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Swift -- Focus Punch -- Thunder Punch -- Light Screen - -Raichu -Level: 51 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Thunder -- Slam -- Rain Dance -- Protect - -Ampharos -Level: 51 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Thunder -- Protect -- Thunder Wave -- Light Screen - -Electrode -Level: 53 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Rollout -- Thunder -- Explosion -- Rain Dance - -Magneton @ Sitrus Berry -Level: 53 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Supersonic -- Protect -- Thunder -- Rain Dance - -Manectric @ Sitrus Berry -Level: 55 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Bite -- Thunder Wave -- Thunder -- Protect - -=== TRAINER_FLANNERY_2 === -Name: 亚莎 -Class: Leader -Pic: Leader Flannery -Gender: Female -Music: Female -Items: Full Restore / Full Restore / Full Restore -Double Battle: Yes -AI: Basic Trainer - -Magcargo @ White Herb -Level: 38 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Overheat -- Attract -- Light Screen -- Rock Slide - -Ponyta -Level: 36 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Flamethrower -- Attract -- Solar Beam -- Bounce - -Camerupt @ White Herb -Level: 38 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Overheat -- Sunny Day -- Earthquake -- Attract - -Torkoal @ White Herb -Level: 40 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Overheat -- Sunny Day -- Explosion -- Attract - -=== TRAINER_FLANNERY_3 === -Name: 亚莎 -Class: Leader -Pic: Leader Flannery -Gender: Female -Music: Female -Items: Full Restore / Full Restore / Full Restore -Double Battle: Yes -AI: Basic Trainer - -Growlithe -Level: 41 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Helping Hand -- Flamethrower -- Roar -- Sunny Day - -Magcargo @ White Herb -Level: 43 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Overheat -- Attract -- Light Screen -- Rock Slide - -Ponyta -Level: 41 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Flamethrower -- Attract -- Solar Beam -- Bounce - -Camerupt @ White Herb -Level: 43 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Overheat -- Sunny Day -- Earthquake -- Attract - -Torkoal @ White Herb -Level: 45 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Overheat -- Sunny Day -- Explosion -- Attract - -=== TRAINER_FLANNERY_4 === -Name: 亚莎 -Class: Leader -Pic: Leader Flannery -Gender: Female -Music: Female -Items: Full Restore / Full Restore / Full Restore -Double Battle: Yes -AI: Basic Trainer - -Houndour -Level: 46 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Roar -- Solar Beam -- Taunt -- Sunny Day - -Growlithe -Level: 46 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Helping Hand -- Flamethrower -- Sunny Day -- Roar - -Magcargo @ White Herb -Level: 48 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Overheat -- Attract -- Light Screen -- Rock Slide - -Rapidash -Level: 46 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Flamethrower -- Attract -- Solar Beam -- Bounce - -Camerupt @ White Herb -Level: 48 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Overheat -- Sunny Day -- Earthquake -- Attract - -Torkoal @ White Herb -Level: 50 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Overheat -- Sunny Day -- Explosion -- Attract - -=== TRAINER_FLANNERY_5 === -Name: 亚莎 -Class: Leader -Pic: Leader Flannery -Gender: Female -Music: Female -Items: Full Restore / Full Restore / Full Restore -Double Battle: Yes -AI: Basic Trainer - -Arcanine -Level: 51 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Helping Hand -- Flamethrower -- Sunny Day -- Roar - -Magcargo @ White Herb -Level: 53 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Overheat -- Attract -- Light Screen -- Rock Slide - -Houndoom -Level: 51 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Roar -- Solar Beam -- Taunt -- Sunny Day - -Rapidash -Level: 51 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Flamethrower -- Attract -- Solar Beam -- Bounce - -Camerupt @ White Herb -Level: 53 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Overheat -- Sunny Day -- Earthquake -- Attract - -Torkoal @ White Herb -Level: 55 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Overheat -- Sunny Day -- Explosion -- Attract - -=== TRAINER_NORMAN_2 === -Name: 千里 -Class: Leader -Pic: Leader Norman -Gender: Male -Music: Male -Items: Full Restore / Full Restore / Full Restore -Double Battle: Yes -AI: Basic Trainer - -Chansey -Level: 42 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Light Screen -- Sing -- Skill Swap -- Focus Punch - -Slaking @ Sitrus Berry -Level: 42 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Blizzard -- Shadow Ball -- Double Edge -- Fire Blast - -Spinda -Level: 43 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Teeter Dance -- Skill Swap -- Facade -- Hypnosis - -Slaking @ Sitrus Berry -Level: 45 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Hyper Beam -- Flamethrower -- Thunderbolt -- Shadow Ball - -=== TRAINER_NORMAN_3 === -Name: 千里 -Class: Leader -Pic: Leader Norman -Gender: Male -Music: Male -Items: Full Restore / Full Restore / Full Restore -Double Battle: Yes -AI: Basic Trainer - -Slaking @ Sitrus Berry -Level: 47 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Blizzard -- Shadow Ball -- Double Edge -- Fire Blast - -Chansey -Level: 47 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Light Screen -- Sing -- Skill Swap -- Focus Punch - -Kangaskhan -Level: 45 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Fake Out -- Dizzy Punch -- Endure -- Reversal - -Spinda -Level: 48 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Teeter Dance -- Skill Swap -- Facade -- Hypnosis - -Slaking @ Sitrus Berry -Level: 50 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Hyper Beam -- Flamethrower -- Thunderbolt -- Shadow Ball - -=== TRAINER_NORMAN_4 === -Name: 千里 -Class: Leader -Pic: Leader Norman -Gender: Male -Music: Male -Items: Full Restore / Full Restore / Full Restore -Double Battle: Yes -AI: Basic Trainer - -Slaking @ Sitrus Berry -Level: 52 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Blizzard -- Shadow Ball -- Double Edge -- Fire Blast - -Blissey -Level: 52 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Light Screen -- Sing -- Skill Swap -- Focus Punch - -Kangaskhan -Level: 50 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Fake Out -- Dizzy Punch -- Endure -- Reversal - -Spinda -Level: 53 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Teeter Dance -- Skill Swap -- Facade -- Hypnosis - -Slaking @ Sitrus Berry -Level: 55 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Hyper Beam -- Flamethrower -- Thunderbolt -- Shadow Ball - -=== TRAINER_NORMAN_5 === -Name: 千里 -Class: Leader -Pic: Leader Norman -Gender: Male -Music: Male -Items: Full Restore / Full Restore / Full Restore -Double Battle: Yes -AI: Basic Trainer - -Slaking @ Sitrus Berry -Level: 57 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Blizzard -- Shadow Ball -- Double Edge -- Fire Blast - -Blissey -Level: 57 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Protect -- Sing -- Skill Swap -- Focus Punch - -Kangaskhan -Level: 55 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Fake Out -- Dizzy Punch -- Endure -- Reversal - -Tauros -Level: 57 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Take Down -- Protect -- Fire Blast -- Earthquake - -Spinda -Level: 58 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Teeter Dance -- Skill Swap -- Facade -- Hypnosis - -Slaking @ Sitrus Berry -Level: 60 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Hyper Beam -- Flamethrower -- Thunderbolt -- Shadow Ball - -=== TRAINER_WINONA_2 === -Name: 娜琪 -Class: Leader -Pic: Leader Winona -Gender: Female -Music: Female -Items: Full Restore / Full Restore / Full Restore -Double Battle: Yes -AI: Basic Trainer / Risky - -Dratini @ Sitrus Berry -Level: 40 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Thunder Wave -- Thunderbolt -- Protect -- Ice Beam - -Tropius -Level: 38 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Sunny Day -- Aerial Ace -- Solar Beam -- Earthquake - -Pelipper -Level: 41 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Surf -- Supersonic -- Protect -- Aerial Ace - -Skarmory -Level: 43 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Whirlwind -- Spikes -- Steel Wing -- Aerial Ace - -Altaria @ Chesto Berry -Level: 45 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Aerial Ace -- Rest -- Dragon Dance -- Earthquake - -=== TRAINER_WINONA_3 === -Name: 娜琪 -Class: Leader -Pic: Leader Winona -Gender: Female -Music: Female -Items: Full Restore / Full Restore / Full Restore -Double Battle: Yes -AI: Basic Trainer / Risky - -Hoothoot -Level: 43 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Hypnosis -- Psychic -- Reflect -- Dream Eater - -Tropius -Level: 43 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Sunny Day -- Aerial Ace -- Solar Beam -- Earthquake - -Dragonair @ Sitrus Berry -Level: 45 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Thunder Wave -- Thunderbolt -- Protect -- Ice Beam - -Pelipper -Level: 46 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Surf -- Supersonic -- Protect -- Aerial Ace - -Skarmory -Level: 48 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Whirlwind -- Spikes -- Steel Wing -- Aerial Ace - -Altaria @ Chesto Berry -Level: 50 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Aerial Ace -- Rest -- Dragon Dance -- Earthquake - -=== TRAINER_WINONA_4 === -Name: 娜琪 -Class: Leader -Pic: Leader Winona -Gender: Female -Music: Female -Items: Full Restore / Full Restore / Full Restore -Double Battle: Yes -AI: Basic Trainer / Risky - -Noctowl -Level: 48 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Hypnosis -- Psychic -- Reflect -- Dream Eater - -Tropius -Level: 49 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Sunny Day -- Aerial Ace -- Solar Beam -- Earthquake - -Dragonair @ Sitrus Berry -Level: 50 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Thunder Wave -- Thunderbolt -- Protect -- Ice Beam - -Pelipper -Level: 51 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Surf -- Supersonic -- Protect -- Aerial Ace - -Skarmory -Level: 53 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Whirlwind -- Spikes -- Steel Wing -- Aerial Ace - -Altaria @ Chesto Berry -Level: 55 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Aerial Ace -- Rest -- Dragon Dance -- Earthquake - -=== TRAINER_WINONA_5 === -Name: 娜琪 -Class: Leader -Pic: Leader Winona -Gender: Female -Music: Female -Items: Full Restore / Full Restore / Full Restore -Double Battle: Yes -AI: Basic Trainer / Risky - -Noctowl -Level: 53 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Hypnosis -- Psychic -- Reflect -- Dream Eater - -Tropius -Level: 54 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Sunny Day -- Aerial Ace -- Solar Beam -- Earthquake - -Pelipper -Level: 55 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Surf -- Supersonic -- Protect -- Aerial Ace - -Dragonite @ Sitrus Berry -Level: 55 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Hyper Beam -- Thunderbolt -- Earthquake -- Ice Beam - -Skarmory -Level: 58 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Whirlwind -- Spikes -- Steel Wing -- Aerial Ace - -Altaria @ Chesto Berry -Level: 60 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Sky Attack -- Rest -- Dragon Dance -- Earthquake - -=== TRAINER_TATE_AND_LIZA_2 === -Name: 小枫与小南 -Class: Leader -Pic: Leader Tate And Liza -Gender: Male -Music: Female -Items: Full Restore / Full Restore / Full Restore -Double Battle: Yes -AI: Basic Trainer - -Slowpoke -Level: 48 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Yawn -- Psychic -- Calm Mind -- Protect - -Claydol -Level: 49 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Earthquake -- Ancient Power -- Psychic -- Light Screen - -Xatu @ Chesto Berry -Level: 49 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Psychic -- Rest -- Confuse Ray -- Calm Mind - -Lunatone @ Chesto Berry -Level: 50 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Earthquake -- Psychic -- Rest -- Calm Mind - -Solrock @ Sitrus Berry -Level: 50 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Sunny Day -- Solar Beam -- Psychic -- Flamethrower - -=== TRAINER_TATE_AND_LIZA_3 === -Name: 小枫与小南 -Class: Leader -Pic: Leader Tate And Liza -Gender: Male -Music: Female -Items: Full Restore / Full Restore / Full Restore -Double Battle: Yes -AI: Basic Trainer - -Drowzee -Level: 53 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Hypnosis -- Dream Eater -- Headbutt -- Protect - -Slowpoke -Level: 53 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Yawn -- Psychic -- Calm Mind -- Protect - -Claydol -Level: 54 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Earthquake -- Explosion -- Psychic -- Light Screen - -Xatu @ Chesto Berry -Level: 54 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Psychic -- Rest -- Confuse Ray -- Calm Mind - -Lunatone @ Chesto Berry -Level: 55 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Earthquake -- Psychic -- Rest -- Calm Mind - -Solrock @ Sitrus Berry -Level: 55 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Sunny Day -- Solar Beam -- Psychic -- Flamethrower - -=== TRAINER_TATE_AND_LIZA_4 === -Name: 小枫与小南 -Class: Leader -Pic: Leader Tate And Liza -Gender: Male -Music: Female -Items: Full Restore / Full Restore / Full Restore -Double Battle: Yes -AI: Basic Trainer - -Hypno -Level: 58 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Hypnosis -- Dream Eater -- Headbutt -- Protect - -Claydol -Level: 59 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Earthquake -- Explosion -- Psychic -- Light Screen - -Slowpoke -Level: 58 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Yawn -- Psychic -- Calm Mind -- Protect - -Xatu @ Chesto Berry -Level: 59 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Psychic -- Rest -- Confuse Ray -- Calm Mind - -Lunatone @ Chesto Berry -Level: 60 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Earthquake -- Psychic -- Rest -- Calm Mind - -Solrock @ Sitrus Berry -Level: 60 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Sunny Day -- Solar Beam -- Psychic -- Flamethrower - -=== TRAINER_TATE_AND_LIZA_5 === -Name: 小枫与小南 -Class: Leader -Pic: Leader Tate And Liza -Gender: Male -Music: Female -Items: Full Restore / Full Restore / Full Restore -Double Battle: Yes -AI: Basic Trainer - -Hypno -Level: 63 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Hypnosis -- Dream Eater -- Headbutt -- Protect - -Claydol -Level: 64 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Earthquake -- Explosion -- Psychic -- Light Screen - -Slowking -Level: 63 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Yawn -- Psychic -- Calm Mind -- Protect - -Xatu @ Chesto Berry -Level: 64 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Psychic -- Rest -- Confuse Ray -- Calm Mind - -Lunatone @ Chesto Berry -Level: 65 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Earthquake -- Psychic -- Rest -- Calm Mind - -Solrock @ Sitrus Berry -Level: 65 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Sunny Day -- Solar Beam -- Psychic -- Flamethrower - -=== TRAINER_JUAN_2 === -Name: 亚当 -Class: Leader -Pic: Leader Juan -Gender: Male -Music: Male -Items: Full Restore / Full Restore / Full Restore -Double Battle: Yes -AI: Basic Trainer - -Poliwag -Level: 46 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Hypnosis -- Rain Dance -- Protect -- Hydro Pump - -Whiscash -Level: 46 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Rain Dance -- Water Pulse -- Double Team -- Fissure - -Walrein -Level: 48 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Water Pulse -- Body Slam -- Protect -- Ice Beam - -Crawdaunt @ Chesto Berry -Level: 48 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Rest -- Crabhammer -- Taunt -- Double Team - -Kingdra @ Chesto Berry -Level: 51 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Water Pulse -- Double Team -- Ice Beam -- Rest - -=== TRAINER_JUAN_3 === -Name: 亚当 -Class: Leader -Pic: Leader Juan -Gender: Male -Music: Male -Items: Full Restore / Full Restore / Full Restore -Double Battle: Yes -AI: Basic Trainer - -Poliwhirl -Level: 50 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Hypnosis -- Rain Dance -- Protect -- Hydro Pump - -Whiscash -Level: 51 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Rain Dance -- Water Pulse -- Double Team -- Fissure - -Walrein -Level: 53 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Water Pulse -- Body Slam -- Protect -- Ice Beam - -Crawdaunt @ Chesto Berry -Level: 53 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Rest -- Guillotine -- Taunt -- Double Team - -Kingdra @ Chesto Berry -Level: 56 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Water Pulse -- Double Team -- Ice Beam -- Rest - -=== TRAINER_JUAN_4 === -Name: 亚当 -Class: Leader -Pic: Leader Juan -Gender: Male -Music: Male -Items: Full Restore / Full Restore / Full Restore -Double Battle: Yes -AI: Basic Trainer - -Lapras -Level: 56 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Hydro Pump -- Perish Song -- Ice Beam -- Confuse Ray - -Whiscash -Level: 58 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Rain Dance -- Water Pulse -- Double Team -- Fissure - -Poliwhirl -Level: 56 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Hypnosis -- Rain Dance -- Protect -- Hydro Pump - -Walrein -Level: 58 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Water Pulse -- Body Slam -- Protect -- Ice Beam - -Crawdaunt @ Chesto Berry -Level: 58 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Rest -- Guillotine -- Taunt -- Double Team - -Kingdra @ Chesto Berry -Level: 61 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Water Pulse -- Double Team -- Ice Beam -- Rest - -=== TRAINER_JUAN_5 === -Name: 亚当 -Class: Leader -Pic: Leader Juan -Gender: Male -Music: Male -Items: Full Restore / Full Restore / Full Restore -Double Battle: Yes -AI: Basic Trainer - -Lapras -Level: 61 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Hydro Pump -- Perish Song -- Ice Beam -- Confuse Ray - -Whiscash -Level: 63 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Rain Dance -- Water Pulse -- Double Team -- Fissure - -Politoed -Level: 61 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Hypnosis -- Rain Dance -- Hydro Pump -- Perish Song - -Walrein -Level: 63 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Water Pulse -- Body Slam -- Protect -- Sheer Cold - -Crawdaunt @ Chesto Berry -Level: 63 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Rest -- Guillotine -- Taunt -- Double Team - -Kingdra @ Chesto Berry -Level: 66 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Water Pulse -- Double Team -- Ice Beam -- Rest - -=== TRAINER_ANGELO === -Name: 基宏 -Class: Bug Maniac -Pic: Bug Maniac -Gender: Male -Music: Suspicious -Double Battle: No -AI: Basic Trainer - -Illumise -Level: 17 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe -- Shock Wave -- Quick Attack -- Charm - -Volbeat -Level: 17 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe -- Shock Wave -- Quick Attack -- Confuse Ray - -=== TRAINER_DARIUS === -Name: 诚一 -Class: Bird Keeper -Pic: Bird Keeper -Gender: Male -Music: Cool -Double Battle: No -AI: Basic Trainer - -Tropius -Level: 30 -IVs: 24 HP / 24 Atk / 24 Def / 24 SpA / 24 SpD / 24 Spe - -=== TRAINER_STEVEN === -Name: 大吾 -Class: Rival -Pic: Steven -Gender: Male -Music: Male -Items: Full Restore / Full Restore / Full Restore / Full Restore -Double Battle: No -AI: Basic Trainer - -Skarmory -Level: 77 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Toxic -- Aerial Ace -- Spikes -- Steel Wing - -Claydol -Level: 75 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Reflect -- Light Screen -- Ancient Power -- Earthquake - -Aggron -Level: 76 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Thunder -- Earthquake -- Solar Beam -- Dragon Claw - -Cradily -Level: 76 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Giga Drain -- Ancient Power -- Ingrain -- Confuse Ray - -Armaldo -Level: 76 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Water Pulse -- Ancient Power -- Aerial Ace -- Slash - -Metagross @ Sitrus Berry -Level: 78 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -- Earthquake -- Psychic -- Meteor Mash -- Shadow Ball - -=== TRAINER_ANABEL === -Name: 莉拉 -Class: Salon Maiden -Pic: Salon Maiden Anabel -Gender: Female -Music: Male -Double Battle: No -AI: Basic Trainer - -Beldum -Level: 5 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_TUCKER === -Name: 石南 -Class: Dome Ace -Pic: Dome Ace Tucker -Gender: Male -Music: Male -Double Battle: No -AI: Basic Trainer - -Beldum -Level: 5 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_SPENSER === -Name: 郁金 -Class: Palace Maven -Pic: Palace Maven Spenser -Gender: Male -Music: Male -Double Battle: No -AI: Basic Trainer - -Beldum -Level: 5 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_GRETA === -Name: 黄瓜香 -Class: Arena Tycoon -Pic: Arena Tycoon Greta -Gender: Female -Music: Male -Double Battle: No -AI: Basic Trainer - -Beldum -Level: 5 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_NOLAND === -Name: 达拉 -Class: Factory Head -Pic: Factory Head Noland -Gender: Male -Music: Male -Double Battle: No -AI: Basic Trainer - -Beldum -Level: 5 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_LUCY === -Name: 小蓟 -Class: Pike Queen -Pic: Pike Queen Lucy -Gender: Female -Music: Male -Double Battle: No -AI: Basic Trainer - -Beldum -Level: 5 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_BRANDON === -Name: 神代 -Class: Pyramid King -Pic: Pyramid King Brandon -Gender: Male -Music: Male -Double Battle: No -AI: Basic Trainer - -Beldum -Level: 5 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_ANDRES_2 === -Name: 大次郎 -Class: Ruin Maniac -Pic: Ruin Maniac -Gender: Male -Music: Hiker -Double Battle: No -AI: Check Bad Move - -Sandshrew -Level: 31 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe - -Sandshrew -Level: 31 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe - -=== TRAINER_ANDRES_3 === -Name: 大次郎 -Class: Ruin Maniac -Pic: Ruin Maniac -Gender: Male -Music: Hiker -Double Battle: No -AI: Check Bad Move - -Nosepass -Level: 33 -IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe - -Sandshrew -Level: 33 -IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe - -Sandshrew -Level: 33 -IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe - -=== TRAINER_ANDRES_4 === -Name: 大次郎 -Class: Ruin Maniac -Pic: Ruin Maniac -Gender: Male -Music: Hiker -Double Battle: No -AI: Check Bad Move - -Nosepass -Level: 35 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe - -Sandshrew -Level: 35 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe - -Sandshrew -Level: 35 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe - -=== TRAINER_ANDRES_5 === -Name: 大次郎 -Class: Ruin Maniac -Pic: Ruin Maniac -Gender: Male -Music: Hiker -Double Battle: No -AI: Check Bad Move - -Nosepass -Level: 37 -IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe - -Sandslash -Level: 37 -IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe - -Sandslash -Level: 37 -IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe - -=== TRAINER_CORY_2 === -Name: 典孝 -Class: Sailor -Pic: Sailor -Gender: Male -Music: Male -Double Battle: No -AI: Check Bad Move - -Wingull -Level: 30 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe - -Machop -Level: 30 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe - -Tentacool -Level: 30 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe - -=== TRAINER_CORY_3 === -Name: 典孝 -Class: Sailor -Pic: Sailor -Gender: Male -Music: Male -Double Battle: No -AI: Check Bad Move - -Pelipper -Level: 32 -IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe - -Machop -Level: 32 -IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe - -Tentacool -Level: 32 -IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe - -=== TRAINER_CORY_4 === -Name: 典孝 -Class: Sailor -Pic: Sailor -Gender: Male -Music: Male -Double Battle: No -AI: Check Bad Move - -Pelipper -Level: 34 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe - -Machop -Level: 34 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe - -Tentacruel -Level: 34 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe - -=== TRAINER_CORY_5 === -Name: 典孝 -Class: Sailor -Pic: Sailor -Gender: Male -Music: Male -Double Battle: No -AI: Check Bad Move - -Pelipper -Level: 36 -IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe - -Machoke -Level: 36 -IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe - -Tentacruel -Level: 36 -IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe - -=== TRAINER_PABLO_2 === -Name: 靖宏 -Class: Triathlete -Pic: Swimming Triathlete M -Gender: Male -Music: Swimmer -Double Battle: No -AI: Check Bad Move - -Staryu -Level: 37 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe - -Staryu -Level: 37 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe - -=== TRAINER_PABLO_3 === -Name: 靖宏 -Class: Triathlete -Pic: Swimming Triathlete M -Gender: Male -Music: Swimmer -Double Battle: No -AI: Check Bad Move - -Wingull -Level: 39 -IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe - -Staryu -Level: 39 -IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe - -Staryu -Level: 39 -IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe - -=== TRAINER_PABLO_4 === -Name: 靖宏 -Class: Triathlete -Pic: Swimming Triathlete M -Gender: Male -Music: Swimmer -Double Battle: No -AI: Check Bad Move - -Pelipper -Level: 41 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe - -Staryu -Level: 41 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe - -Staryu -Level: 41 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe - -=== TRAINER_PABLO_5 === -Name: 靖宏 -Class: Triathlete -Pic: Swimming Triathlete M -Gender: Male -Music: Swimmer -Double Battle: No -AI: Check Bad Move - -Pelipper -Level: 43 -IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe - -Starmie -Level: 43 -IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe - -Starmie -Level: 43 -IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe - -=== TRAINER_KOJI_2 === -Name: 铁郎 -Class: Black Belt -Pic: Black Belt -Gender: Male -Music: Intense -Double Battle: No -AI: Check Bad Move - -Machoke -Level: 37 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe - -Machoke -Level: 37 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe - -=== TRAINER_KOJI_3 === -Name: 铁郎 -Class: Black Belt -Pic: Black Belt -Gender: Male -Music: Intense -Double Battle: No -AI: Check Bad Move - -Makuhita -Level: 39 -IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe - -Machoke -Level: 39 -IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe - -Machoke -Level: 39 -IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe - -=== TRAINER_KOJI_4 === -Name: 铁郎 -Class: Black Belt -Pic: Black Belt -Gender: Male -Music: Intense -Double Battle: No -AI: Check Bad Move - -Hariyama -Level: 41 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe - -Machoke -Level: 41 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe - -Machoke -Level: 41 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe - -=== TRAINER_KOJI_5 === -Name: 铁郎 -Class: Black Belt -Pic: Black Belt -Gender: Male -Music: Intense -Double Battle: No -AI: Check Bad Move - -Hariyama -Level: 43 -IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe - -Machamp -Level: 43 -IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe - -Machamp -Level: 43 -IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe - -=== TRAINER_CRISTIN_2 === -Name: 登纪子 -Class: Cooltrainer -Pic: Cooltrainer F -Gender: Female -Music: Cool -Items: Hyper Potion -Double Battle: No -AI: Basic Trainer - -Loudred -Level: 35 -IVs: 13 HP / 13 Atk / 13 Def / 13 SpA / 13 SpD / 13 Spe - -Vigoroth -Level: 35 -IVs: 13 HP / 13 Atk / 13 Def / 13 SpA / 13 SpD / 13 Spe - -=== TRAINER_CRISTIN_3 === -Name: 登纪子 -Class: Cooltrainer -Pic: Cooltrainer F -Gender: Female -Music: Cool -Items: Hyper Potion -Double Battle: No -AI: Basic Trainer - -Spinda -Level: 37 -IVs: 14 HP / 14 Atk / 14 Def / 14 SpA / 14 SpD / 14 Spe - -Loudred -Level: 37 -IVs: 14 HP / 14 Atk / 14 Def / 14 SpA / 14 SpD / 14 Spe - -Vigoroth -Level: 37 -IVs: 14 HP / 14 Atk / 14 Def / 14 SpA / 14 SpD / 14 Spe - -=== TRAINER_CRISTIN_4 === -Name: 登纪子 -Class: Cooltrainer -Pic: Cooltrainer F -Gender: Female -Music: Cool -Items: Hyper Potion -Double Battle: No -AI: Basic Trainer - -Spinda -Level: 39 -IVs: 15 HP / 15 Atk / 15 Def / 15 SpA / 15 SpD / 15 Spe - -Loudred -Level: 39 -IVs: 15 HP / 15 Atk / 15 Def / 15 SpA / 15 SpD / 15 Spe - -Vigoroth -Level: 39 -IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe - -=== TRAINER_CRISTIN_5 === -Name: 登纪子 -Class: Cooltrainer -Pic: Cooltrainer F -Gender: Female -Music: Cool -Items: Hyper Potion -Double Battle: No -AI: Basic Trainer - -Spinda -Level: 41 -IVs: 17 HP / 17 Atk / 17 Def / 17 SpA / 17 SpD / 17 Spe - -Exploud -Level: 41 -IVs: 17 HP / 17 Atk / 17 Def / 17 SpA / 17 SpD / 17 Spe - -Slaking -Level: 41 -IVs: 17 HP / 17 Atk / 17 Def / 17 SpA / 17 SpD / 17 Spe - -=== TRAINER_FERNANDO_2 === -Name: 乔 -Class: Guitarist -Pic: Guitarist -Gender: Male -Music: Intense -Double Battle: No -AI: Check Bad Move - -Electrike -Level: 35 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe - -Electrike -Level: 35 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe - -Loudred -Level: 35 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe - -=== TRAINER_FERNANDO_3 === -Name: 乔 -Class: Guitarist -Pic: Guitarist -Gender: Male -Music: Intense -Double Battle: No -AI: Check Bad Move - -Electrike -Level: 37 -IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe - -Manectric -Level: 37 -IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe - -Loudred -Level: 37 -IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe - -=== TRAINER_FERNANDO_4 === -Name: 乔 -Class: Guitarist -Pic: Guitarist -Gender: Male -Music: Intense -Double Battle: No -AI: Check Bad Move - -Manectric -Level: 39 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe - -Manectric -Level: 39 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe - -Loudred -Level: 39 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe - -=== TRAINER_FERNANDO_5 === -Name: 乔 -Class: Guitarist -Pic: Guitarist -Gender: Male -Music: Intense -Double Battle: No -AI: Check Bad Move - -Manectric -Level: 41 -IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe - -Manectric -Level: 41 -IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe - -Exploud -Level: 41 -IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe - -=== TRAINER_SAWYER_2 === -Name: 雅彦 -Class: Hiker -Pic: Hiker -Gender: Male -Music: Hiker -Double Battle: No -AI: Basic Trainer - -Geodude -Level: 26 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe - -Numel -Level: 26 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe - -=== TRAINER_SAWYER_3 === -Name: 雅彦 -Class: Hiker -Pic: Hiker -Gender: Male -Music: Hiker -Double Battle: No -AI: Basic Trainer - -Machop -Level: 28 -IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe - -Numel -Level: 28 -IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe - -Graveler -Level: 28 -IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe - -=== TRAINER_SAWYER_4 === -Name: 雅彦 -Class: Hiker -Pic: Hiker -Gender: Male -Music: Hiker -Double Battle: No -AI: Basic Trainer - -Machop -Level: 30 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe - -Numel -Level: 30 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe - -Graveler -Level: 30 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe - -=== TRAINER_SAWYER_5 === -Name: 雅彦 -Class: Hiker -Pic: Hiker -Gender: Male -Music: Hiker -Double Battle: No -AI: Basic Trainer - -Machoke -Level: 33 -IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe - -Camerupt -Level: 33 -IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe - -Golem -Level: 33 -IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe - -=== TRAINER_GABRIELLE_2 === -Name: 福美 -Class: Pkmn Breeder -Pic: Pokemon Breeder F -Gender: Female -Music: Female -Double Battle: No -AI: Check Bad Move - -Skitty -Level: 31 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe - -Mightyena -Level: 31 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe - -Zigzagoon -Level: 31 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe - -Lotad -Level: 31 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe - -Seedot -Level: 31 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe - -Taillow -Level: 31 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe - -=== TRAINER_GABRIELLE_3 === -Name: 福美 -Class: Pkmn Breeder -Pic: Pokemon Breeder F -Gender: Female -Music: Female -Double Battle: No -AI: Check Bad Move - -Skitty -Level: 33 -IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe - -Mightyena -Level: 33 -IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe - -Linoone -Level: 33 -IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe - -Lombre -Level: 33 -IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe - -Nuzleaf -Level: 33 -IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe - -Taillow -Level: 33 -IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe - -=== TRAINER_GABRIELLE_4 === -Name: 福美 -Class: Pkmn Breeder -Pic: Pokemon Breeder F -Gender: Female -Music: Female -Double Battle: No -AI: Check Bad Move - -Delcatty -Level: 35 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe - -Mightyena -Level: 35 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe - -Linoone -Level: 35 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe - -Lombre -Level: 35 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe - -Nuzleaf -Level: 35 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe - -Swellow -Level: 35 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe - -=== TRAINER_GABRIELLE_5 === -Name: 福美 -Class: Pkmn Breeder -Pic: Pokemon Breeder F -Gender: Female -Music: Female -Double Battle: No -AI: Check Bad Move - -Delcatty -Level: 37 -IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe - -Mightyena -Level: 37 -IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe - -Linoone -Level: 37 -IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe - -Ludicolo -Level: 37 -IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe - -Shiftry -Level: 37 -IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe - -Swellow -Level: 37 -IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe - -=== TRAINER_THALIA_2 === -Name: 睫 -Class: Beauty -Pic: Beauty -Gender: Female -Music: Female -Double Battle: No -AI: Check Bad Move - -Wailmer -Level: 34 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe - -Horsea -Level: 34 -IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe - -=== TRAINER_THALIA_3 === -Name: 睫 -Class: Beauty -Pic: Beauty -Gender: Female -Music: Female -Double Battle: No -AI: Check Bad Move - -Luvdisc -Level: 36 -IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe - -Wailmer -Level: 36 -IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe - -Seadra -Level: 36 -IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe - -=== TRAINER_THALIA_4 === -Name: 睫 -Class: Beauty -Pic: Beauty -Gender: Female -Music: Female -Double Battle: No -AI: Check Bad Move - -Luvdisc -Level: 38 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe - -Wailmer -Level: 38 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe - -Seadra -Level: 38 -IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe - -=== TRAINER_THALIA_5 === -Name: 睫 -Class: Beauty -Pic: Beauty -Gender: Female -Music: Female -Double Battle: No -AI: Check Bad Move - -Luvdisc -Level: 40 -IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe - -Wailord -Level: 40 -IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe - -Kingdra -Level: 40 -IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe - -=== TRAINER_MARIELA === -Name: 未羽 -Class: Psychic -Pic: Psychic F -Gender: Female -Music: Intense -Double Battle: No - -Chimecho -Level: 41 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_ALVARO === -Name: 信也 -Class: Psychic -Pic: Psychic M -Gender: Male -Music: Intense -Double Battle: No - -Banette -Level: 41 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Kadabra -Level: 41 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_EVERETT === -Name: 道格 -Class: Gentleman -Pic: Gentleman -Gender: Male -Music: Rich -Double Battle: No - -Wobbuffet -Level: 41 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_RED === -Name: 赤红 -Class: Rival -Pic: Red -Gender: Male -Music: Male -Double Battle: No - -Charmander -Level: 5 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_LEAF === -Name: 叶子 -Class: Rival -Pic: Leaf -Gender: Female -Music: Male -Double Battle: No - -Bulbasaur -Level: 5 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_BRENDAN_PLACEHOLDER === -Name: 小悠 -Class: RS Protag -Pic: RS Brendan -Gender: Male -Music: Male -Double Battle: No - -Groudon -Level: 5 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== TRAINER_MAY_PLACEHOLDER === -Name: 小遥 -Class: RS Protag -Pic: RS May -Gender: Female -Music: Male -Double Battle: No - -Kyogre -Level: 5 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe +/* +Trainers and their parties defined with Competetive Syntax. +Compatible with Pokemon Showdown exports. +https://github.com/smogon/pokemon-showdown/blob/master/sim/TEAMS.md + +A trainer specification starts with "=== TRAINER_XXXX ===" +and includes everything until the next line that starts with "===" +or the file ends. +A blank line is required between the trainer and their Pokemon +and between their Pokemon. +TRAINER_XXXX is how the trainer is referred to within code. + +Fields with description and/or example of usage +Required fields for trainers: + - Name + - Pic +Optional (but still recommended) fields for trainers: + - Class (if not specified, PkMn Trainer will be used) + - Gender (Male/Female, affects random gender weights of party if not specified) + - Music + - Items (Some Item / Another Item / Third Item) + (Can also be specified with ITEM_SOME_ITEM) + - Battle Type (Singles / Doubles, defaults to Singles) + - AI (Ai Flag / Another Flag / Third Flag / ... + see "constants/battle_ai.h" for all flags) + - Mugshot (enable Mugshots during battle transition + set to one of Purple, Green, Pink, Blue or Yellow) + - Starting Status (see include/constants/battle.h for values) + +Pokemon are then specified using the Showdown Export format. +If a field is not specified, it will use it's default value. + +Required fields for Pokemon: + - Species (Either as SPECIES_ABRA or Abra) + This line also specifies Gender, Nickname and Held item. + Alfred (Abra) (M) @ Eviolite + Roberta (SPECIES_ABRA) (F) @ ITEM_CHOICE_SPECS + Both lines are valid. Gender (M) or (F) must use a capital letter. + Nickname length is limited to 10 characters using standard letters. + With narrow font it's increased to 12. Longer strings will be silently shortened. + +Optional fields for Pokemon: + - Level (Number between 1 and 100, defaults to 100) + - Ability (Ability Name or ABILITY_ABILITY_NAME) + - IVs (0 HP / 1 Atk / 2 Def / 3 SpA / 4 SpD / 5 Spe, defaults to all 31) + (Order does not matter) + - EVs (252 HP / 128 Spe / 48 Def, defaults to all 0, is not capped at 512 total) + (Order does not matter) + - Ball (Poke Ball or ITEM_POKE_BALL, defaults to Poke Ball) + - Happiness (Number between 1 and 255) + - Nature (Rash or NATURE_RASH, defaults to Hardy) + - Shiny (Yes/No, defaults to No) + - Dynamax Level (Number between 0 and 10, default 10, also sets "shouldDynamax" to True) + - Gigantamax (Yes/No, sets to Gigantamax factor) + (doesn't do anything to Pokemon without a Gigantamax form, also sets "shouldDynamax" to True) + - Tera Type (Set to a Type, either Fire or TYPE_FIRE, also sets "shouldTerastal" to True) +Moves are defined with a - (dash) followed by a single space, then the move name. +Either "- Tackle" or "- MOVE_TACKLE" works. One move per line. +Moves have to be the last lines of a Pokemon. +If no moves are specified, the Pokemon will use the last 4 moves it learns +through levelup at its level. + +Default IVs and Level can be changed in the "main" function of tools/trainerproc/main.c + +This file is processed with a custom preprocessor. +*/ + +/* +Comments can be added as C comment blocks +// cannot be used as comments +*/ + +/*Comments can also be on a single line*/ + + +=== TRAINER_NONE === +Name: +Class: Pkmn Trainer 1 +Pic: Hiker +Gender: Male +Music: Male +Double Battle: No + +=== TRAINER_SAWYER_1 === +Name: 雅彦 +Class: Hiker +Pic: Hiker +Gender: Male +Music: Hiker +Double Battle: No +AI: Basic Trainer + +Geodude +Level: 21 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_GRUNT_AQUA_HIDEOUT_1 === +Name: 手下 +Class: Team Aqua +Pic: Aqua Grunt M +Gender: Male +Music: Aqua +Double Battle: No +AI: Check Bad Move + +Poochyena +Level: 32 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_GRUNT_AQUA_HIDEOUT_2 === +Name: 手下 +Class: Team Aqua +Pic: Aqua Grunt M +Gender: Male +Music: Aqua +Double Battle: No +AI: Check Bad Move + +Zubat +Level: 31 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Carvanha +Level: 31 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_GRUNT_AQUA_HIDEOUT_3 === +Name: 手下 +Class: Team Aqua +Pic: Aqua Grunt M +Gender: Male +Music: Aqua +Double Battle: No +AI: Check Bad Move + +Zubat +Level: 32 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_GRUNT_AQUA_HIDEOUT_4 === +Name: 手下 +Class: Team Aqua +Pic: Aqua Grunt M +Gender: Male +Music: Aqua +Double Battle: No +AI: Check Bad Move + +Carvanha +Level: 32 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_GRUNT_SEAFLOOR_CAVERN_1 === +Name: 手下 +Class: Team Aqua +Pic: Aqua Grunt M +Gender: Male +Music: Aqua +Double Battle: No +AI: Check Bad Move + +Poochyena +Level: 36 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_GRUNT_SEAFLOOR_CAVERN_2 === +Name: 手下 +Class: Team Aqua +Pic: Aqua Grunt M +Gender: Male +Music: Aqua +Double Battle: No +AI: Check Bad Move + +Carvanha +Level: 36 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_GRUNT_SEAFLOOR_CAVERN_3 === +Name: 手下 +Class: Team Aqua +Pic: Aqua Grunt M +Gender: Male +Music: Aqua +Double Battle: No +AI: Check Bad Move + +Zubat +Level: 36 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_GABRIELLE_1 === +Name: 福美 +Class: Pkmn Breeder +Pic: Pokemon Breeder F +Gender: Female +Music: Female +Double Battle: No +AI: Check Bad Move + +Skitty +Level: 26 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Poochyena +Level: 26 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Zigzagoon +Level: 26 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Lotad +Level: 26 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Seedot +Level: 26 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Taillow +Level: 26 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_GRUNT_PETALBURG_WOODS === +Name: 手下 +Class: Team Aqua +Pic: Aqua Grunt M +Gender: Male +Music: Aqua +Double Battle: No +AI: Check Bad Move + +Poochyena +Level: 9 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_MARCEL === +Name: 节夫 +Class: Cooltrainer +Pic: Cooltrainer M +Gender: Male +Music: Cool +Items: Hyper Potion +Double Battle: No +AI: Basic Trainer + +Manectric +Level: 29 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +Shiftry +Level: 29 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +=== TRAINER_ALBERTO === +Name: 洋介 +Class: Bird Keeper +Pic: Bird Keeper +Gender: Male +Music: Cool +Double Battle: No +AI: Check Bad Move + +Pelipper +Level: 30 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Xatu +Level: 30 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_ED === +Name: 杰 +Class: Collector +Pic: Collector +Gender: Male +Music: Suspicious +Double Battle: No +AI: Check Bad Move + +Zangoose +Level: 30 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Seviper +Level: 30 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_GRUNT_SEAFLOOR_CAVERN_4 === +Name: 手下 +Class: Team Aqua +Pic: Aqua Grunt F +Gender: Female +Music: Aqua +Double Battle: No +AI: Check Bad Move + +Carvanha +Level: 36 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_DECLAN === +Name: 一平 +Class: Swimmer M +Pic: Swimmer M +Gender: Male +Music: Swimmer +Double Battle: No +AI: Check Bad Move + +Gyarados +Level: 34 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_GRUNT_RUSTURF_TUNNEL === +Name: 手下 +Class: Team Aqua +Pic: Aqua Grunt M +Gender: Male +Music: Aqua +Double Battle: No +AI: Check Bad Move + +Poochyena +Level: 11 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_GRUNT_WEATHER_INST_1 === +Name: 手下 +Class: Team Aqua +Pic: Aqua Grunt M +Gender: Male +Music: Aqua +Double Battle: No +AI: Check Bad Move + +Zubat +Level: 27 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Poochyena +Level: 27 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_GRUNT_WEATHER_INST_2 === +Name: 手下 +Class: Team Aqua +Pic: Aqua Grunt M +Gender: Male +Music: Aqua +Double Battle: No +AI: Check Bad Move + +Poochyena +Level: 27 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Carvanha +Level: 27 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_GRUNT_WEATHER_INST_3 === +Name: 手下 +Class: Team Aqua +Pic: Aqua Grunt M +Gender: Male +Music: Aqua +Double Battle: No +AI: Check Bad Move + +Poochyena +Level: 26 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Zubat +Level: 26 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Carvanha +Level: 26 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_GRUNT_MUSEUM_1 === +Name: 手下 +Class: Team Aqua +Pic: Aqua Grunt M +Gender: Male +Music: Aqua +Double Battle: No +AI: Check Bad Move + +Carvanha +Level: 15 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_GRUNT_MUSEUM_2 === +Name: 手下 +Class: Team Aqua +Pic: Aqua Grunt M +Gender: Male +Music: Aqua +Double Battle: No +AI: Check Bad Move + +Zubat +Level: 14 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Carvanha +Level: 14 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_GRUNT_SPACE_CENTER_1 === +Name: 手下 +Class: Team Magma +Pic: Magma Grunt M +Gender: Male +Music: Magma +Double Battle: No +AI: Check Bad Move + +Numel +Level: 32 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_GRUNT_MT_PYRE_1 === +Name: 手下 +Class: Team Aqua +Pic: Aqua Grunt M +Gender: Male +Music: Aqua +Double Battle: No +AI: Check Bad Move + +Zubat +Level: 32 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_GRUNT_MT_PYRE_2 === +Name: 手下 +Class: Team Aqua +Pic: Aqua Grunt M +Gender: Male +Music: Aqua +Double Battle: No +AI: Check Bad Move + +Carvanha +Level: 32 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_GRUNT_MT_PYRE_3 === +Name: 手下 +Class: Team Aqua +Pic: Aqua Grunt M +Gender: Male +Music: Aqua +Double Battle: No +AI: Check Bad Move + +Poochyena +Level: 30 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Carvanha +Level: 30 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_GRUNT_WEATHER_INST_4 === +Name: 手下 +Class: Team Aqua +Pic: Aqua Grunt F +Gender: Female +Music: Aqua +Double Battle: No +AI: Check Bad Move + +Carvanha +Level: 28 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_GRUNT_AQUA_HIDEOUT_5 === +Name: 手下 +Class: Team Aqua +Pic: Aqua Grunt F +Gender: Female +Music: Aqua +Double Battle: No +AI: Check Bad Move + +Carvanha +Level: 32 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_GRUNT_AQUA_HIDEOUT_6 === +Name: 手下 +Class: Team Aqua +Pic: Aqua Grunt F +Gender: Female +Music: Aqua +Double Battle: No +AI: Check Bad Move + +Zubat +Level: 32 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_FREDRICK === +Name: 寿茂 +Class: Expert +Pic: Expert M +Gender: Male +Music: Intense +Double Battle: No +AI: Basic Trainer + +Makuhita +Level: 30 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +Machoke +Level: 30 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +=== TRAINER_MATT === +Name: 阿潮 +Class: Aqua Admin +Pic: Aqua Admin M +Gender: Male +Music: Aqua +Items: Super Potion +Double Battle: No +AI: Basic Trainer + +Mightyena +Level: 34 +IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe + +Golbat +Level: 34 +IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe + +=== TRAINER_ZANDER === +Name: 良治 +Class: Black Belt +Pic: Black Belt +Gender: Male +Music: Intense +Double Battle: No +AI: Check Bad Move + +Hariyama +Level: 31 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_SHELLY_WEATHER_INSTITUTE === +Name: 阿泉 +Class: Aqua Admin +Pic: Aqua Admin F +Gender: Female +Music: Aqua +Double Battle: No +AI: Basic Trainer + +Carvanha +Level: 28 +IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe + +Mightyena +Level: 28 +IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe + +=== TRAINER_SHELLY_SEAFLOOR_CAVERN === +Name: 阿泉 +Class: Aqua Admin +Pic: Aqua Admin F +Gender: Female +Music: Aqua +Double Battle: No +AI: Basic Trainer + +Sharpedo +Level: 37 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +Mightyena +Level: 37 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +=== TRAINER_ARCHIE === +Name: 水梧桐 +Class: Aqua Leader +Pic: Aqua Leader Archie +Gender: Male +Music: Aqua +Items: Super Potion / Super Potion +Double Battle: No +AI: Basic Trainer + +Mightyena +Level: 41 +IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe + +Crobat +Level: 41 +IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe + +Sharpedo +Level: 43 +IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe + +=== TRAINER_LEAH === +Name: 绘美 +Class: Hex Maniac +Pic: Hex Maniac +Gender: Female +Music: Suspicious +Double Battle: No +AI: Check Bad Move + +Spoink +Level: 31 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_DAISY === +Name: 美鸟 +Class: Aroma Lady +Pic: Aroma Lady +Gender: Female +Music: Female +Double Battle: No +AI: Check Bad Move + +Shroomish +Level: 14 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Roselia +Level: 14 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_ROSE_1 === +Name: 弥生 +Class: Aroma Lady +Pic: Aroma Lady +Gender: Female +Music: Female +Double Battle: No +AI: Check Bad Move + +Roselia +Level: 14 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Shroomish +Level: 14 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Roselia +Level: 14 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_FELIX === +Name: 幸次郎 +Class: Cooltrainer +Pic: Cooltrainer M +Gender: Male +Music: Cool +Items: Full Restore +Double Battle: No +AI: Basic Trainer + +Medicham +Level: 43 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe +- Psychic + +Claydol +Level: 43 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe +- Skill Swap +- Earthquake + +=== TRAINER_VIOLET === +Name: 千鹤 +Class: Aroma Lady +Pic: Aroma Lady +Gender: Female +Music: Female +Double Battle: No +AI: Check Bad Move + +Roselia +Level: 26 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Gloom +Level: 26 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_ROSE_2 === +Name: 弥生 +Class: Aroma Lady +Pic: Aroma Lady +Gender: Female +Music: Female +Double Battle: No +AI: Check Bad Move + +Shroomish +Level: 26 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe + +Roselia +Level: 26 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe + +=== TRAINER_ROSE_3 === +Name: 弥生 +Class: Aroma Lady +Pic: Aroma Lady +Gender: Female +Music: Female +Double Battle: No +AI: Check Bad Move + +Shroomish +Level: 28 +IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe + +Gloom +Level: 28 +IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe + +Roselia +Level: 28 +IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe + +=== TRAINER_ROSE_4 === +Name: 弥生 +Class: Aroma Lady +Pic: Aroma Lady +Gender: Female +Music: Female +Double Battle: No +AI: Check Bad Move + +Shroomish +Level: 31 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe + +Gloom +Level: 31 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe + +Roselia +Level: 31 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe + +=== TRAINER_ROSE_5 === +Name: 弥生 +Class: Aroma Lady +Pic: Aroma Lady +Gender: Female +Music: Female +Double Battle: No +AI: Check Bad Move + +Breloom +Level: 34 +IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe + +Gloom +Level: 34 +IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe + +Roselia +Level: 34 +IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe + +=== TRAINER_DUSTY_1 === +Name: 伸夫 +Class: Ruin Maniac +Pic: Ruin Maniac +Gender: Male +Music: Hiker +Double Battle: No +AI: Check Bad Move + +Sandslash +Level: 23 +IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe +- Dig +- Slash +- Sand Attack +- Poison Sting + +=== TRAINER_CHIP === +Name: 圭一 +Class: Ruin Maniac +Pic: Ruin Maniac +Gender: Male +Music: Hiker +Double Battle: No +AI: Check Bad Move + +Baltoy +Level: 27 +IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe +- Psybeam +- Self Destruct +- Sandstorm +- Ancient Power + +Sandshrew +Level: 27 +IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe +- Dig +- Slash +- Sand Attack +- Poison Sting + +Sandslash +Level: 27 +IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe +- Dig +- Slash +- Sand Attack +- Poison Sting + +=== TRAINER_FOSTER === +Name: 秋人 +Class: Ruin Maniac +Pic: Ruin Maniac +Gender: Male +Music: Hiker +Double Battle: No +AI: Check Bad Move + +Sandshrew +Level: 25 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe +- Dig +- Slash +- Sand Attack +- Poison Sting + +Sandslash +Level: 25 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe +- Dig +- Slash +- Sand Attack +- Poison Sting + +=== TRAINER_DUSTY_2 === +Name: 伸夫 +Class: Ruin Maniac +Pic: Ruin Maniac +Gender: Male +Music: Hiker +Double Battle: No +AI: Check Bad Move + +Sandslash +Level: 27 +IVs: 7 HP / 7 Atk / 7 Def / 7 SpA / 7 SpD / 7 Spe +- Dig +- Slash +- Sand Attack +- Poison Sting + +=== TRAINER_DUSTY_3 === +Name: 伸夫 +Class: Ruin Maniac +Pic: Ruin Maniac +Gender: Male +Music: Hiker +Double Battle: No +AI: Check Bad Move + +Sandslash +Level: 30 +IVs: 8 HP / 8 Atk / 8 Def / 8 SpA / 8 SpD / 8 Spe +- Dig +- Slash +- Sand Attack +- Poison Sting + +=== TRAINER_DUSTY_4 === +Name: 伸夫 +Class: Ruin Maniac +Pic: Ruin Maniac +Gender: Male +Music: Hiker +Double Battle: No +AI: Check Bad Move + +Sandslash +Level: 33 +IVs: 9 HP / 9 Atk / 9 Def / 9 SpA / 9 SpD / 9 Spe +- Dig +- Slash +- Sand Attack +- Poison Sting + +=== TRAINER_DUSTY_5 === +Name: 伸夫 +Class: Ruin Maniac +Pic: Ruin Maniac +Gender: Male +Music: Hiker +Double Battle: No +AI: Check Bad Move + +Sandslash +Level: 36 +IVs: 10 HP / 10 Atk / 10 Def / 10 SpA / 10 SpD / 10 Spe +- Dig +- Slash +- Sand Attack +- Poison Sting + +=== TRAINER_GABBY_AND_TY_1 === +Name: 玛莉和达伊 +Class: Interviewer +Pic: Interviewer +Gender: Male +Music: Interviewer +Double Battle: Yes +AI: Check Bad Move + +Magnemite +Level: 17 +IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe + +Whismur +Level: 17 +IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe + +=== TRAINER_GABBY_AND_TY_2 === +Name: 玛莉和达伊 +Class: Interviewer +Pic: Interviewer +Gender: Male +Music: Interviewer +Double Battle: Yes +AI: Check Bad Move + +Magnemite +Level: 27 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +Loudred +Level: 27 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +=== TRAINER_GABBY_AND_TY_3 === +Name: 玛莉和达伊 +Class: Interviewer +Pic: Interviewer +Gender: Male +Music: Interviewer +Double Battle: Yes +AI: Check Bad Move + +Magneton +Level: 30 +IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe + +Loudred +Level: 30 +IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe + +=== TRAINER_GABBY_AND_TY_4 === +Name: 玛莉和达伊 +Class: Interviewer +Pic: Interviewer +Gender: Male +Music: Interviewer +Double Battle: Yes +AI: Check Bad Move + +Magneton +Level: 33 +IVs: 24 HP / 24 Atk / 24 Def / 24 SpA / 24 SpD / 24 Spe + +Loudred +Level: 33 +IVs: 24 HP / 24 Atk / 24 Def / 24 SpA / 24 SpD / 24 Spe + +=== TRAINER_GABBY_AND_TY_5 === +Name: 玛莉和达伊 +Class: Interviewer +Pic: Interviewer +Gender: Male +Music: Interviewer +Double Battle: Yes +AI: Check Bad Move + +Magneton +Level: 36 +IVs: 30 HP / 30 Atk / 30 Def / 30 SpA / 30 SpD / 30 Spe + +Loudred +Level: 36 +IVs: 30 HP / 30 Atk / 30 Def / 30 SpA / 30 SpD / 30 Spe + +=== TRAINER_GABBY_AND_TY_6 === +Name: 玛莉和达伊 +Class: Interviewer +Pic: Interviewer +Gender: Male +Music: Interviewer +Double Battle: Yes +AI: Check Bad Move + +Magneton +Level: 39 +IVs: 30 HP / 30 Atk / 30 Def / 30 SpA / 30 SpD / 30 Spe +- Sonic Boom +- Thunder Wave +- Metal Sound +- Thunderbolt + +Exploud +Level: 39 +IVs: 30 HP / 30 Atk / 30 Def / 30 SpA / 30 SpD / 30 Spe +- Astonish +- Stomp +- Supersonic +- Hyper Voice + +=== TRAINER_LOLA_1 === +Name: 亚由美 +Class: Tuber F +Pic: Tuber F +Gender: Female +Music: Girl +Double Battle: No +AI: Check Bad Move + +Azurill +Level: 12 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe + +Azurill +Level: 12 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe + +=== TRAINER_AUSTINA === +Name: 博美 +Class: Tuber F +Pic: Tuber F +Gender: Female +Music: Girl +Double Battle: No +AI: Check Bad Move + +Marill +Level: 26 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_GWEN === +Name: 小望 +Class: Tuber F +Pic: Tuber F +Gender: Female +Music: Girl +Double Battle: No +AI: Check Bad Move + +Marill +Level: 26 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_LOLA_2 === +Name: 亚由美 +Class: Tuber F +Pic: Tuber F +Gender: Female +Music: Girl +Double Battle: No +AI: Check Bad Move + +Marill +Level: 26 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe + +Marill +Level: 26 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe + +=== TRAINER_LOLA_3 === +Name: 亚由美 +Class: Tuber F +Pic: Tuber F +Gender: Female +Music: Girl +Double Battle: No +AI: Check Bad Move + +Marill +Level: 29 +IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe + +Marill +Level: 29 +IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe + +=== TRAINER_LOLA_4 === +Name: 亚由美 +Class: Tuber F +Pic: Tuber F +Gender: Female +Music: Girl +Double Battle: No +AI: Check Bad Move + +Marill +Level: 32 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe + +Marill +Level: 32 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe + +=== TRAINER_LOLA_5 === +Name: 亚由美 +Class: Tuber F +Pic: Tuber F +Gender: Female +Music: Girl +Double Battle: No +AI: Check Bad Move + +Azumarill +Level: 35 +IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe + +Azumarill +Level: 35 +IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe + +=== TRAINER_RICKY_1 === +Name: 裕太 +Class: Tuber M +Pic: Tuber M +Gender: Male +Music: Girl +Double Battle: No +AI: Check Bad Move + +Zigzagoon +Level: 13 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe +- Sand Attack +- Headbutt +- Tail Whip +- Surf + +=== TRAINER_SIMON === +Name: 安信 +Class: Tuber M +Pic: Tuber M +Gender: Male +Music: Girl +Double Battle: No +AI: Check Bad Move + +Azurill +Level: 12 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Marill +Level: 12 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_CHARLIE === +Name: 学武 +Class: Tuber M +Pic: Tuber M +Gender: Male +Music: Girl +Double Battle: No +AI: Check Bad Move + +Marill +Level: 26 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_RICKY_2 === +Name: 裕太 +Class: Tuber M +Pic: Tuber M +Gender: Male +Music: Girl +Double Battle: No +AI: Check Bad Move + +Linoone +Level: 27 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe +- Sand Attack +- Pin Missile +- Tail Whip +- Surf + +=== TRAINER_RICKY_3 === +Name: 裕太 +Class: Tuber M +Pic: Tuber M +Gender: Male +Music: Girl +Double Battle: No +AI: Check Bad Move + +Linoone +Level: 30 +IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe +- Sand Attack +- Pin Missile +- Tail Whip +- Surf + +=== TRAINER_RICKY_4 === +Name: 裕太 +Class: Tuber M +Pic: Tuber M +Gender: Male +Music: Girl +Double Battle: No +AI: Check Bad Move + +Linoone +Level: 33 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe +- Sand Attack +- Pin Missile +- Tail Whip +- Surf + +=== TRAINER_RICKY_5 === +Name: 裕太 +Class: Tuber M +Pic: Tuber M +Gender: Male +Music: Girl +Double Battle: No +AI: Check Bad Move + +Linoone +Level: 36 +IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe +- Sand Attack +- Pin Missile +- Tail Whip +- Surf + +=== TRAINER_RANDALL === +Name: 俊树 +Class: Cooltrainer +Pic: Cooltrainer M +Gender: Male +Music: Cool +Items: Hyper Potion +Double Battle: No +AI: Basic Trainer + +Swellow +Level: 26 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Quick Attack +- Agility +- Wing Attack + +=== TRAINER_PARKER === +Name: 秀树 +Class: Cooltrainer +Pic: Cooltrainer M +Gender: Male +Music: Cool +Items: Hyper Potion +Double Battle: No +AI: Basic Trainer + +Spinda +Level: 26 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Teeter Dance +- Dizzy Punch +- Focus Punch + +=== TRAINER_GEORGE === +Name: 数马 +Class: Cooltrainer +Pic: Cooltrainer M +Gender: Male +Music: Cool +Items: Hyper Potion +Double Battle: No +AI: Basic Trainer + +Slakoth @ Sitrus Berry +Level: 26 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Slack Off +- Counter +- Shadow Ball + +=== TRAINER_BERKE === +Name: 直树 +Class: Cooltrainer +Pic: Cooltrainer M +Gender: Male +Music: Cool +Items: Hyper Potion +Double Battle: No +AI: Basic Trainer + +Vigoroth +Level: 26 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Focus Energy +- Slash + +=== TRAINER_BRAXTON === +Name: 义雄 +Class: Cooltrainer +Pic: Cooltrainer M +Gender: Male +Music: Cool +Items: Hyper Potion +Double Battle: No +AI: Basic Trainer + +Swellow +Level: 28 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe +- Focus Energy +- Quick Attack +- Wing Attack +- Endeavor + +Trapinch +Level: 28 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe +- Bite +- Dig +- Feint Attack +- Sand Tomb + +Wailmer +Level: 28 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe +- Rollout +- Whirlpool +- Astonish +- Water Pulse + +Magneton +Level: 28 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe +- Thunderbolt +- Supersonic +- Thunder Wave +- Sonic Boom + +Shiftry +Level: 28 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe +- Giga Drain +- Feint Attack +- Double Team +- Swagger + +=== TRAINER_VINCENT === +Name: 祐翔 +Class: Cooltrainer +Pic: Cooltrainer M +Gender: Male +Music: Cool +Items: Full Restore +Double Battle: No +AI: Basic Trainer + +Sableye +Level: 44 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +Medicham +Level: 44 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +Sharpedo +Level: 44 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +=== TRAINER_LEROY === +Name: 诚 +Class: Cooltrainer +Pic: Cooltrainer M +Gender: Male +Music: Cool +Items: Full Restore +Double Battle: No +AI: Basic Trainer + +Mawile +Level: 46 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +Starmie +Level: 46 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +=== TRAINER_WILTON_1 === +Name: 裕介 +Class: Cooltrainer +Pic: Cooltrainer M +Gender: Male +Music: Cool +Items: Super Potion +Double Battle: No +AI: Basic Trainer + +Electrike +Level: 17 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +Wailmer +Level: 17 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +Makuhita +Level: 17 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +=== TRAINER_EDGAR === +Name: 光辉 +Class: Cooltrainer +Pic: Cooltrainer M +Gender: Male +Music: Cool +Items: Full Restore +Double Battle: No +AI: Basic Trainer + +Cacturne +Level: 43 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +Pelipper +Level: 43 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +=== TRAINER_ALBERT === +Name: 胜 +Class: Cooltrainer +Pic: Cooltrainer M +Gender: Male +Music: Cool +Items: Full Restore +Double Battle: No +AI: Basic Trainer + +Magneton +Level: 43 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +Muk +Level: 43 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +=== TRAINER_SAMUEL === +Name: 拓也 +Class: Cooltrainer +Pic: Cooltrainer M +Gender: Male +Music: Cool +Items: Full Restore +Double Battle: No +AI: Basic Trainer + +Swellow +Level: 42 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +Mawile +Level: 42 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +Kadabra +Level: 42 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +=== TRAINER_VITO === +Name: 良平 +Class: Cooltrainer +Pic: Cooltrainer M +Gender: Male +Music: Cool +Items: Full Restore +Double Battle: No +AI: Basic Trainer + +Dodrio +Level: 42 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +Kadabra +Level: 42 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +Electrode +Level: 42 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +Shiftry +Level: 42 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +=== TRAINER_OWEN === +Name: 翔 +Class: Cooltrainer +Pic: Cooltrainer M +Gender: Male +Music: Cool +Items: Full Restore +Double Battle: No +AI: Basic Trainer + +Kecleon +Level: 42 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +Graveler +Level: 42 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +Wailord +Level: 42 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +=== TRAINER_WILTON_2 === +Name: 裕介 +Class: Cooltrainer +Pic: Cooltrainer M +Gender: Male +Music: Cool +Items: Hyper Potion +Double Battle: No +AI: Basic Trainer + +Electrike +Level: 26 +IVs: 13 HP / 13 Atk / 13 Def / 13 SpA / 13 SpD / 13 Spe + +Wailmer +Level: 26 +IVs: 13 HP / 13 Atk / 13 Def / 13 SpA / 13 SpD / 13 Spe + +Makuhita +Level: 26 +IVs: 13 HP / 13 Atk / 13 Def / 13 SpA / 13 SpD / 13 Spe + +=== TRAINER_WILTON_3 === +Name: 裕介 +Class: Cooltrainer +Pic: Cooltrainer M +Gender: Male +Music: Cool +Items: Hyper Potion +Double Battle: No +AI: Basic Trainer + +Manectric +Level: 29 +IVs: 14 HP / 14 Atk / 14 Def / 14 SpA / 14 SpD / 14 Spe + +Wailmer +Level: 29 +IVs: 14 HP / 14 Atk / 14 Def / 14 SpA / 14 SpD / 14 Spe + +Makuhita +Level: 29 +IVs: 14 HP / 14 Atk / 14 Def / 14 SpA / 14 SpD / 14 Spe + +=== TRAINER_WILTON_4 === +Name: 裕介 +Class: Cooltrainer +Pic: Cooltrainer M +Gender: Male +Music: Cool +Items: Full Restore +Double Battle: No +AI: Basic Trainer + +Manectric +Level: 32 +IVs: 15 HP / 15 Atk / 15 Def / 15 SpA / 15 SpD / 15 Spe + +Wailmer +Level: 32 +IVs: 15 HP / 15 Atk / 15 Def / 15 SpA / 15 SpD / 15 Spe + +Makuhita +Level: 32 +IVs: 15 HP / 15 Atk / 15 Def / 15 SpA / 15 SpD / 15 Spe + +=== TRAINER_WILTON_5 === +Name: 裕介 +Class: Cooltrainer +Pic: Cooltrainer M +Gender: Male +Music: Cool +Items: Full Restore +Double Battle: No +AI: Basic Trainer + +Manectric +Level: 35 +IVs: 17 HP / 17 Atk / 17 Def / 17 SpA / 17 SpD / 17 Spe + +Wailmer +Level: 35 +IVs: 17 HP / 17 Atk / 17 Def / 17 SpA / 17 SpD / 17 Spe + +Hariyama +Level: 35 +IVs: 17 HP / 17 Atk / 17 Def / 17 SpA / 17 SpD / 17 Spe + +=== TRAINER_WARREN === +Name: 礼司 +Class: Cooltrainer +Pic: Cooltrainer M +Gender: Male +Music: Cool +Items: Full Restore +Double Battle: No +AI: Basic Trainer + +Graveler +Level: 33 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +Ludicolo +Level: 33 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +=== TRAINER_MARY === +Name: 绫香 +Class: Cooltrainer +Pic: Cooltrainer F +Gender: Female +Music: Cool +Items: Hyper Potion +Double Battle: No +AI: Basic Trainer + +Delcatty +Level: 26 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Feint Attack +- Shock Wave + +=== TRAINER_ALEXIA === +Name: 海晴 +Class: Cooltrainer +Pic: Cooltrainer F +Gender: Female +Music: Cool +Items: Hyper Potion +Double Battle: No +AI: Basic Trainer + +Wigglytuff +Level: 26 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Defense Curl +- Double Edge +- Shadow Ball + +=== TRAINER_JODY === +Name: 沙织 +Class: Cooltrainer +Pic: Cooltrainer F +Gender: Female +Music: Cool +Items: Hyper Potion +Double Battle: No +AI: Check Bad Move / Try To Faint / Force Setup First Turn + +Zangoose +Level: 26 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Swords Dance +- Slash + +=== TRAINER_WENDY === +Name: 刹那 +Class: Cooltrainer +Pic: Cooltrainer F +Gender: Female +Music: Cool +Items: Full Restore +Double Battle: No +AI: Check Bad Move / Try To Faint / Force Setup First Turn + +Mawile +Level: 29 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe +- Baton Pass +- Feint Attack +- Fake Tears +- Bite + +Roselia +Level: 29 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe +- Mega Drain +- Magical Leaf +- Grass Whistle +- Leech Seed + +Pelipper +Level: 29 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe +- Fly +- Water Gun +- Mist +- Protect + +=== TRAINER_KEIRA === +Name: 安娜 +Class: Cooltrainer +Pic: Cooltrainer F +Gender: Female +Music: Cool +Items: Full Restore +Double Battle: No +AI: Check Bad Move / Try To Faint / Force Setup First Turn + +Lairon +Level: 45 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +Manectric +Level: 45 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +=== TRAINER_BROOKE_1 === +Name: 真理亚 +Class: Cooltrainer +Pic: Cooltrainer F +Gender: Female +Music: Cool +Items: Super Potion +Double Battle: No +AI: Basic Trainer + +Wingull +Level: 17 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +Numel +Level: 17 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +Roselia +Level: 17 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +=== TRAINER_JENNIFER === +Name: 弥生子 +Class: Cooltrainer +Pic: Cooltrainer F +Gender: Female +Music: Cool +Items: Full Restore +Double Battle: No +AI: Basic Trainer + +Sableye +Level: 30 +IVs: 24 HP / 24 Atk / 24 Def / 24 SpA / 24 SpD / 24 Spe + +=== TRAINER_HOPE === +Name: 爱理 +Class: Cooltrainer +Pic: Cooltrainer F +Gender: Female +Music: Cool +Items: Full Restore +Double Battle: No +AI: Basic Trainer + +Roselia +Level: 45 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +=== TRAINER_SHANNON === +Name: 绘理子 +Class: Cooltrainer +Pic: Cooltrainer F +Gender: Female +Music: Cool +Items: Full Restore +Double Battle: No +AI: Basic Trainer + +Claydol +Level: 45 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +=== TRAINER_MICHELLE === +Name: 和美 +Class: Cooltrainer +Pic: Cooltrainer F +Gender: Female +Music: Cool +Items: Full Restore +Double Battle: No +AI: Basic Trainer + +Torkoal +Level: 42 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +Medicham +Level: 42 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +Ludicolo +Level: 42 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +=== TRAINER_CAROLINE === +Name: 绯月 +Class: Cooltrainer +Pic: Cooltrainer F +Gender: Female +Music: Cool +Items: Full Restore +Double Battle: No +AI: Basic Trainer + +Skarmory +Level: 43 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +Sableye +Level: 43 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +=== TRAINER_JULIE === +Name: 琴美 +Class: Cooltrainer +Pic: Cooltrainer F +Gender: Female +Music: Cool +Items: Full Restore +Double Battle: No +AI: Basic Trainer + +Sandslash +Level: 42 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +Ninetales +Level: 42 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +Tropius +Level: 42 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +=== TRAINER_BROOKE_2 === +Name: 真理亚 +Class: Cooltrainer +Pic: Cooltrainer F +Gender: Female +Music: Cool +Items: Hyper Potion +Double Battle: No +AI: Basic Trainer + +Wingull +Level: 26 +IVs: 13 HP / 13 Atk / 13 Def / 13 SpA / 13 SpD / 13 Spe + +Numel +Level: 26 +IVs: 13 HP / 13 Atk / 13 Def / 13 SpA / 13 SpD / 13 Spe + +Roselia +Level: 26 +IVs: 13 HP / 13 Atk / 13 Def / 13 SpA / 13 SpD / 13 Spe + +=== TRAINER_BROOKE_3 === +Name: 真理亚 +Class: Cooltrainer +Pic: Cooltrainer F +Gender: Female +Music: Cool +Items: Hyper Potion +Double Battle: No +AI: Basic Trainer + +Pelipper +Level: 29 +IVs: 14 HP / 14 Atk / 14 Def / 14 SpA / 14 SpD / 14 Spe + +Numel +Level: 29 +IVs: 14 HP / 14 Atk / 14 Def / 14 SpA / 14 SpD / 14 Spe + +Roselia +Level: 29 +IVs: 14 HP / 14 Atk / 14 Def / 14 SpA / 14 SpD / 14 Spe + +=== TRAINER_BROOKE_4 === +Name: 真理亚 +Class: Cooltrainer +Pic: Cooltrainer F +Gender: Female +Music: Cool +Items: Full Restore +Double Battle: No +AI: Basic Trainer + +Pelipper +Level: 32 +IVs: 15 HP / 15 Atk / 15 Def / 15 SpA / 15 SpD / 15 Spe + +Numel +Level: 32 +IVs: 15 HP / 15 Atk / 15 Def / 15 SpA / 15 SpD / 15 Spe + +Roselia +Level: 32 +IVs: 15 HP / 15 Atk / 15 Def / 15 SpA / 15 SpD / 15 Spe + +=== TRAINER_BROOKE_5 === +Name: 真理亚 +Class: Cooltrainer +Pic: Cooltrainer F +Gender: Female +Music: Cool +Items: Full Restore +Double Battle: No +AI: Basic Trainer + +Pelipper +Level: 34 +IVs: 17 HP / 17 Atk / 17 Def / 17 SpA / 17 SpD / 17 Spe + +Camerupt +Level: 34 +IVs: 17 HP / 17 Atk / 17 Def / 17 SpA / 17 SpD / 17 Spe + +Roselia +Level: 34 +IVs: 17 HP / 17 Atk / 17 Def / 17 SpA / 17 SpD / 17 Spe + +=== TRAINER_PATRICIA === +Name: 采音 +Class: Hex Maniac +Pic: Hex Maniac +Gender: Female +Music: Suspicious +Double Battle: No +AI: Check Bad Move + +Banette +Level: 41 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Lunatone +Level: 41 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_KINDRA === +Name: 祥子 +Class: Hex Maniac +Pic: Hex Maniac +Gender: Female +Music: Suspicious +Double Battle: No +AI: Check Bad Move + +Duskull +Level: 30 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Shuppet +Level: 30 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_TAMMY === +Name: 命 +Class: Hex Maniac +Pic: Hex Maniac +Gender: Female +Music: Suspicious +Double Battle: No +AI: Check Bad Move + +Duskull +Level: 29 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Shuppet +Level: 29 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_VALERIE_1 === +Name: 穗乃佳 +Class: Hex Maniac +Pic: Hex Maniac +Gender: Female +Music: Suspicious +Double Battle: No +AI: Check Bad Move + +Sableye +Level: 32 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_TASHA === +Name: 穗多琉 +Class: Hex Maniac +Pic: Hex Maniac +Gender: Female +Music: Suspicious +Double Battle: No +AI: Check Bad Move + +Shuppet +Level: 32 +IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe + +=== TRAINER_VALERIE_2 === +Name: 穗乃佳 +Class: Hex Maniac +Pic: Hex Maniac +Gender: Female +Music: Suspicious +Double Battle: No +AI: Check Bad Move + +Sableye +Level: 31 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe + +Spoink +Level: 31 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe + +=== TRAINER_VALERIE_3 === +Name: 穗乃佳 +Class: Hex Maniac +Pic: Hex Maniac +Gender: Female +Music: Suspicious +Double Battle: No +AI: Check Bad Move + +Spoink +Level: 35 +IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe + +Sableye +Level: 35 +IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe + +=== TRAINER_VALERIE_4 === +Name: 穗乃佳 +Class: Hex Maniac +Pic: Hex Maniac +Gender: Female +Music: Suspicious +Double Battle: No +AI: Check Bad Move + +Spoink +Level: 40 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe + +Sableye +Level: 40 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe + +=== TRAINER_VALERIE_5 === +Name: 穗乃佳 +Class: Hex Maniac +Pic: Hex Maniac +Gender: Female +Music: Suspicious +Double Battle: No +AI: Check Bad Move + +Duskull +Level: 42 +IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe + +Sableye +Level: 42 +IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe + +Grumpig +Level: 42 +IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe + +=== TRAINER_CINDY_1 === +Name: 丽华 +Class: Lady +Pic: Lady +Gender: Female +Music: Female +Items: Full Restore +Double Battle: No +AI: Check Bad Move + +Zigzagoon @ Nugget +Level: 7 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_DAPHNE === +Name: 咏歌 +Class: Lady +Pic: Lady +Gender: Female +Music: Female +Items: Full Restore +Double Battle: No +AI: Check Bad Move + +Luvdisc @ Nugget +Level: 39 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe +- Attract +- Sweet Kiss +- Flail +- Water Pulse + +Luvdisc @ Nugget +Level: 39 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe +- Attract +- Safeguard +- Take Down +- Water Pulse + +=== TRAINER_GRUNT_SPACE_CENTER_2 === +Name: 手下 +Class: Team Magma +Pic: Magma Grunt M +Gender: Male +Music: Magma +Double Battle: No +AI: Check Bad Move + +Mightyena +Level: 26 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Mightyena +Level: 28 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Numel +Level: 30 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_CINDY_2 === +Name: 丽华 +Class: Lady +Pic: Lady +Gender: Female +Music: Female +Items: Full Restore +Double Battle: No +AI: Check Bad Move + +Zigzagoon @ Nugget +Level: 11 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe +- Tackle +- Tail Whip + +=== TRAINER_BRIANNA === +Name: 诗织 +Class: Lady +Pic: Lady +Gender: Female +Music: Female +Items: Full Restore +Double Battle: No +AI: Check Bad Move + +Seaking @ Nugget +Level: 40 +IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe + +=== TRAINER_NAOMI === +Name: 小百合 +Class: Lady +Pic: Lady +Gender: Female +Music: Female +Items: Full Restore +Double Battle: No +AI: Check Bad Move + +Roselia @ Nugget +Level: 45 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +=== TRAINER_CINDY_3 === +Name: 丽华 +Class: Lady +Pic: Lady +Gender: Female +Music: Female +Items: Full Restore +Double Battle: No +AI: Check Bad Move + +Linoone @ Nugget +Level: 27 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe + +=== TRAINER_CINDY_4 === +Name: 丽华 +Class: Lady +Pic: Lady +Gender: Female +Music: Female +Items: Full Restore +Double Battle: No +AI: Check Bad Move + +Linoone @ Nugget +Level: 30 +IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe + +=== TRAINER_CINDY_5 === +Name: 丽华 +Class: Lady +Pic: Lady +Gender: Female +Music: Female +Items: Full Restore +Double Battle: No +AI: Check Bad Move + +Linoone @ Nugget +Level: 33 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe + +=== TRAINER_CINDY_6 === +Name: 丽华 +Class: Lady +Pic: Lady +Gender: Female +Music: Female +Items: Full Restore +Double Battle: No +AI: Check Bad Move + +Linoone @ Nugget +Level: 36 +IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe +- Fury Swipes +- Mud Sport +- Odor Sleuth +- Sand Attack + +=== TRAINER_MELISSA === +Name: 惠美 +Class: Beauty +Pic: Beauty +Gender: Female +Music: Female +Double Battle: No +AI: Check Bad Move + +Marill +Level: 21 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_SHEILA === +Name: 国美 +Class: Beauty +Pic: Beauty +Gender: Female +Music: Female +Double Battle: No +AI: Check Bad Move + +Shroomish +Level: 21 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_SHIRLEY === +Name: 朝美 +Class: Beauty +Pic: Beauty +Gender: Female +Music: Female +Double Battle: No +AI: Check Bad Move + +Numel +Level: 21 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_JESSICA_1 === +Name: 依子 +Class: Beauty +Pic: Beauty +Gender: Female +Music: Female +Double Battle: No +AI: Check Bad Move + +Kecleon +Level: 29 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe +- Bind +- Lick +- Fury Swipes +- Feint Attack + +Seviper +Level: 29 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe +- Poison Tail +- Screech +- Glare +- Crunch + +=== TRAINER_CONNIE === +Name: 眉子 +Class: Beauty +Pic: Beauty +Gender: Female +Music: Female +Double Battle: No +AI: Check Bad Move + +Goldeen +Level: 40 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +=== TRAINER_BRIDGET === +Name: 清子 +Class: Beauty +Pic: Beauty +Gender: Female +Music: Female +Double Battle: No +AI: Check Bad Move + +Azumarill +Level: 40 +IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe + +=== TRAINER_OLIVIA === +Name: 直子 +Class: Beauty +Pic: Beauty +Gender: Female +Music: Female +Double Battle: No +AI: Check Bad Move + +Clamperl +Level: 35 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe +- Iron Defense +- Whirlpool +- Rain Dance +- Water Pulse + +Corphish +Level: 37 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe +- Taunt +- Crabhammer +- Water Pulse + +Lombre +Level: 39 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe +- Uproar +- Fury Swipes +- Fake Out +- Water Pulse + +=== TRAINER_TIFFANY === +Name: 春子 +Class: Beauty +Pic: Beauty +Gender: Female +Music: Female +Double Battle: No +AI: Check Bad Move + +Carvanha +Level: 39 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +Sharpedo +Level: 39 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +=== TRAINER_JESSICA_2 === +Name: 依子 +Class: Beauty +Pic: Beauty +Gender: Female +Music: Female +Double Battle: No +AI: Check Bad Move + +Kecleon +Level: 35 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe +- Bind +- Lick +- Fury Swipes +- Feint Attack + +Seviper +Level: 35 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe +- Poison Tail +- Screech +- Glare +- Crunch + +=== TRAINER_JESSICA_3 === +Name: 依子 +Class: Beauty +Pic: Beauty +Gender: Female +Music: Female +Double Battle: No +AI: Check Bad Move + +Kecleon +Level: 38 +IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe +- Bind +- Lick +- Fury Swipes +- Feint Attack + +Seviper +Level: 38 +IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe +- Poison Tail +- Screech +- Glare +- Crunch + +=== TRAINER_JESSICA_4 === +Name: 依子 +Class: Beauty +Pic: Beauty +Gender: Female +Music: Female +Double Battle: No +AI: Check Bad Move + +Kecleon +Level: 41 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe +- Bind +- Lick +- Fury Swipes +- Feint Attack + +Seviper +Level: 41 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe +- Poison Tail +- Screech +- Glare +- Crunch + +=== TRAINER_JESSICA_5 === +Name: 依子 +Class: Beauty +Pic: Beauty +Gender: Female +Music: Female +Double Battle: No +AI: Check Bad Move + +Kecleon +Level: 44 +IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe +- Bind +- Lick +- Fury Swipes +- Feint Attack + +Seviper +Level: 44 +IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe +- Poison Tail +- Screech +- Glare +- Crunch + +=== TRAINER_WINSTON_1 === +Name: 小贡 +Class: Rich Boy +Pic: Rich Boy +Gender: Male +Music: Rich +Items: Full Restore +Double Battle: No +AI: Check Bad Move + +Zigzagoon @ Nugget +Level: 7 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_MOLLIE === +Name: 奈江 +Class: Expert +Pic: Expert F +Gender: Female +Music: Intense +Double Battle: No +AI: Check Bad Move + +Whiscash +Level: 33 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Meditite +Level: 33 +IVs: 24 HP / 24 Atk / 24 Def / 24 SpA / 24 SpD / 24 Spe + +=== TRAINER_GARRET === +Name: 祥一 +Class: Rich Boy +Pic: Rich Boy +Gender: Male +Music: Rich +Items: Full Restore +Double Battle: No +AI: Check Bad Move + +Azumarill @ Nugget +Level: 45 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_WINSTON_2 === +Name: 小贡 +Class: Rich Boy +Pic: Rich Boy +Gender: Male +Music: Rich +Items: Full Restore +Double Battle: No +AI: Check Bad Move + +Linoone @ Nugget +Level: 27 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_WINSTON_3 === +Name: 小贡 +Class: Rich Boy +Pic: Rich Boy +Gender: Male +Music: Rich +Items: Full Restore +Double Battle: No +AI: Check Bad Move + +Linoone @ Nugget +Level: 30 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_WINSTON_4 === +Name: 小贡 +Class: Rich Boy +Pic: Rich Boy +Gender: Male +Music: Rich +Items: Full Restore +Double Battle: No +AI: Check Bad Move + +Linoone @ Nugget +Level: 33 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_WINSTON_5 === +Name: 小贡 +Class: Rich Boy +Pic: Rich Boy +Gender: Male +Music: Rich +Items: Full Restore +Double Battle: No +AI: Check Bad Move + +Linoone @ Nugget +Level: 36 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe +- Fury Swipes +- Mud Sport +- Odor Sleuth +- Sand Attack + +=== TRAINER_STEVE_1 === +Name: 俊夫 +Class: Pokemaniac +Pic: Pokemaniac +Gender: Male +Music: Suspicious +Double Battle: No +AI: Check Bad Move + +Aron +Level: 19 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_THALIA_1 === +Name: 睫 +Class: Beauty +Pic: Beauty +Gender: Female +Music: Female +Double Battle: No +AI: Check Bad Move + +Wailmer +Level: 25 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Horsea +Level: 25 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_MARK === +Name: 基文 +Class: Pokemaniac +Pic: Pokemaniac +Gender: Male +Music: Suspicious +Double Battle: No +AI: Check Bad Move + +Rhyhorn +Level: 31 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_GRUNT_MT_CHIMNEY_1 === +Name: 手下 +Class: Team Magma +Pic: Magma Grunt F +Gender: Female +Music: Magma +Double Battle: No +AI: Check Bad Move + +Numel +Level: 20 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_STEVE_2 === +Name: 俊夫 +Class: Pokemaniac +Pic: Pokemaniac +Gender: Male +Music: Suspicious +Double Battle: No +AI: Check Bad Move + +Lairon +Level: 27 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe + +=== TRAINER_STEVE_3 === +Name: 俊夫 +Class: Pokemaniac +Pic: Pokemaniac +Gender: Male +Music: Suspicious +Double Battle: No +AI: Check Bad Move + +Lairon +Level: 29 +IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe + +Rhyhorn +Level: 29 +IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe + +=== TRAINER_STEVE_4 === +Name: 俊夫 +Class: Pokemaniac +Pic: Pokemaniac +Gender: Male +Music: Suspicious +Double Battle: No +AI: Check Bad Move + +Lairon +Level: 32 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe + +Rhyhorn +Level: 32 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe + +=== TRAINER_STEVE_5 === +Name: 俊夫 +Class: Pokemaniac +Pic: Pokemaniac +Gender: Male +Music: Suspicious +Double Battle: No +AI: Check Bad Move + +Aggron +Level: 35 +IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe + +Rhydon +Level: 35 +IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe + +=== TRAINER_LUIS === +Name: 洋平 +Class: Swimmer M +Pic: Swimmer M +Gender: Male +Music: Swimmer +Double Battle: No +AI: Check Bad Move + +Carvanha +Level: 26 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_DOMINIK === +Name: 弘道 +Class: Swimmer M +Pic: Swimmer M +Gender: Male +Music: Swimmer +Double Battle: No +AI: Check Bad Move + +Tentacool +Level: 26 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_DOUGLAS === +Name: 辰夫 +Class: Swimmer M +Pic: Swimmer M +Gender: Male +Music: Swimmer +Double Battle: No +AI: Check Bad Move + +Tentacool +Level: 24 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe + +Tentacool +Level: 24 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe + +=== TRAINER_DARRIN === +Name: 照幸 +Class: Swimmer M +Pic: Swimmer M +Gender: Male +Music: Swimmer +Double Battle: No +AI: Check Bad Move + +Tentacool +Level: 24 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe + +Wingull +Level: 24 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe + +Tentacool +Level: 24 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe + +=== TRAINER_TONY_1 === +Name: 英一 +Class: Swimmer M +Pic: Swimmer M +Gender: Male +Music: Swimmer +Double Battle: No +AI: Check Bad Move + +Carvanha +Level: 26 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_JEROME === +Name: 森男 +Class: Swimmer M +Pic: Swimmer M +Gender: Male +Music: Swimmer +Double Battle: No +AI: Check Bad Move + +Tentacruel +Level: 26 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_MATTHEW === +Name: 国彦 +Class: Swimmer M +Pic: Swimmer M +Gender: Male +Music: Swimmer +Double Battle: No +AI: Check Bad Move + +Carvanha +Level: 26 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_DAVID === +Name: 健一 +Class: Swimmer M +Pic: Swimmer M +Gender: Male +Music: Swimmer +Double Battle: No +AI: Check Bad Move + +Tentacool +Level: 25 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Carvanha +Level: 25 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_SPENCER === +Name: 稔洋 +Class: Swimmer M +Pic: Swimmer M +Gender: Male +Music: Swimmer +Double Battle: No +AI: Check Bad Move + +Tentacool +Level: 33 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Wingull +Level: 33 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_ROLAND === +Name: 正稔 +Class: Swimmer M +Pic: Swimmer M +Gender: Male +Music: Swimmer +Double Battle: No +AI: Check Bad Move + +Carvanha +Level: 34 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_NOLEN === +Name: 信夫 +Class: Swimmer M +Pic: Swimmer M +Gender: Male +Music: Swimmer +Double Battle: No +AI: Check Bad Move + +Tentacruel +Level: 34 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_STAN === +Name: 圭史 +Class: Swimmer M +Pic: Swimmer M +Gender: Male +Music: Swimmer +Double Battle: No +AI: Check Bad Move + +Horsea +Level: 34 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_BARRY === +Name: 学人 +Class: Swimmer M +Pic: Swimmer M +Gender: Male +Music: Swimmer +Double Battle: No +AI: Check Bad Move + +Gyarados +Level: 34 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_DEAN === +Name: 烈日 +Class: Swimmer M +Pic: Swimmer M +Gender: Male +Music: Swimmer +Double Battle: No +AI: Check Bad Move + +Carvanha +Level: 31 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Wingull +Level: 31 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Carvanha +Level: 31 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_RODNEY === +Name: 正洋 +Class: Swimmer M +Pic: Swimmer M +Gender: Male +Music: Swimmer +Double Battle: No +AI: Check Bad Move + +Gyarados +Level: 34 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_RICHARD === +Name: 春树 +Class: Swimmer M +Pic: Swimmer M +Gender: Male +Music: Swimmer +Double Battle: No +AI: Check Bad Move + +Pelipper +Level: 34 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_HERMAN === +Name: 大辅 +Class: Swimmer M +Pic: Swimmer M +Gender: Male +Music: Swimmer +Double Battle: No +AI: Check Bad Move + +Wingull +Level: 33 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Tentacruel +Level: 33 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_SANTIAGO === +Name: 慎二 +Class: Swimmer M +Pic: Swimmer M +Gender: Male +Music: Swimmer +Double Battle: No +AI: Check Bad Move + +Tentacruel +Level: 33 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Wailmer +Level: 33 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_GILBERT === +Name: 豪 +Class: Swimmer M +Pic: Swimmer M +Gender: Male +Music: Swimmer +Double Battle: No +AI: Check Bad Move + +Sharpedo +Level: 34 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_FRANKLIN === +Name: 茂雄 +Class: Swimmer M +Pic: Swimmer M +Gender: Male +Music: Swimmer +Double Battle: No +AI: Check Bad Move + +Sealeo +Level: 34 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_KEVIN === +Name: 勉 +Class: Swimmer M +Pic: Swimmer M +Gender: Male +Music: Swimmer +Double Battle: No +AI: Check Bad Move + +Spheal +Level: 34 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_JACK === +Name: 秀典 +Class: Swimmer M +Pic: Swimmer M +Gender: Male +Music: Swimmer +Double Battle: No +AI: Check Bad Move + +Gyarados +Level: 34 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_DUDLEY === +Name: 德雄 +Class: Swimmer M +Pic: Swimmer M +Gender: Male +Music: Swimmer +Double Battle: No +AI: Check Bad Move + +Tentacool +Level: 33 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Wingull +Level: 33 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Tentacruel +Level: 33 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_CHAD === +Name: 克之 +Class: Swimmer M +Pic: Swimmer M +Gender: Male +Music: Swimmer +Double Battle: No +AI: Check Bad Move + +Tentacool +Level: 33 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Wailmer +Level: 33 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_TONY_2 === +Name: 英一 +Class: Swimmer M +Pic: Swimmer M +Gender: Male +Music: Swimmer +Double Battle: No +AI: Check Bad Move + +Sharpedo +Level: 30 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe + +=== TRAINER_TONY_3 === +Name: 英一 +Class: Swimmer M +Pic: Swimmer M +Gender: Male +Music: Swimmer +Double Battle: No +AI: Check Bad Move + +Sharpedo +Level: 33 +IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe + +=== TRAINER_TONY_4 === +Name: 英一 +Class: Swimmer M +Pic: Swimmer M +Gender: Male +Music: Swimmer +Double Battle: No +AI: Check Bad Move + +Staryu +Level: 34 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe + +Sharpedo +Level: 36 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe + +=== TRAINER_TONY_5 === +Name: 英一 +Class: Swimmer M +Pic: Swimmer M +Gender: Male +Music: Swimmer +Double Battle: No +AI: Check Bad Move + +Starmie +Level: 37 +IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe + +Sharpedo +Level: 39 +IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe + +=== TRAINER_TAKAO === +Name: 大庆 +Class: Black Belt +Pic: Black Belt +Gender: Male +Music: Intense +Double Battle: No +AI: Check Bad Move + +Machop +Level: 13 +IVs: 15 HP / 15 Atk / 15 Def / 15 SpA / 15 SpD / 15 Spe + +=== TRAINER_HITOSHI === +Name: 岩冈 +Class: Black Belt +Pic: Black Belt +Gender: Male +Music: Intense +Double Battle: No +AI: Check Bad Move + +Machop +Level: 32 +IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe + +Machoke +Level: 32 +IVs: 24 HP / 24 Atk / 24 Def / 24 SpA / 24 SpD / 24 Spe + +=== TRAINER_KIYO === +Name: 拓马 +Class: Black Belt +Pic: Black Belt +Gender: Male +Music: Intense +Double Battle: No +AI: Check Bad Move + +Hariyama +Level: 34 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +=== TRAINER_KOICHI === +Name: 武德 +Class: Black Belt +Pic: Black Belt +Gender: Male +Music: Intense +Double Battle: No +AI: Check Bad Move + +Machop +Level: 24 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +Machoke +Level: 28 +IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe + +=== TRAINER_NOB_1 === +Name: 吾郎 +Class: Black Belt +Pic: Black Belt +Gender: Male +Music: Intense +Double Battle: No +AI: Check Bad Move + +Machop +Level: 19 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +=== TRAINER_NOB_2 === +Name: 吾郎 +Class: Black Belt +Pic: Black Belt +Gender: Male +Music: Intense +Double Battle: No +AI: Check Bad Move + +Machoke +Level: 27 +IVs: 13 HP / 13 Atk / 13 Def / 13 SpA / 13 SpD / 13 Spe + +=== TRAINER_NOB_3 === +Name: 吾郎 +Class: Black Belt +Pic: Black Belt +Gender: Male +Music: Intense +Double Battle: No +AI: Check Bad Move + +Machop +Level: 29 +IVs: 14 HP / 14 Atk / 14 Def / 14 SpA / 14 SpD / 14 Spe + +Machoke +Level: 29 +IVs: 14 HP / 14 Atk / 14 Def / 14 SpA / 14 SpD / 14 Spe + +=== TRAINER_NOB_4 === +Name: 吾郎 +Class: Black Belt +Pic: Black Belt +Gender: Male +Music: Intense +Double Battle: No +AI: Check Bad Move + +Machop +Level: 31 +IVs: 15 HP / 15 Atk / 15 Def / 15 SpA / 15 SpD / 15 Spe + +Machoke +Level: 31 +IVs: 15 HP / 15 Atk / 15 Def / 15 SpA / 15 SpD / 15 Spe + +Machoke +Level: 31 +IVs: 15 HP / 15 Atk / 15 Def / 15 SpA / 15 SpD / 15 Spe + +=== TRAINER_NOB_5 === +Name: 吾郎 +Class: Black Belt +Pic: Black Belt +Gender: Male +Music: Intense +Double Battle: No +AI: Check Bad Move + +Machop +Level: 33 +IVs: 17 HP / 17 Atk / 17 Def / 17 SpA / 17 SpD / 17 Spe + +Machoke +Level: 33 +IVs: 17 HP / 17 Atk / 17 Def / 17 SpA / 17 SpD / 17 Spe + +Machoke +Level: 33 +IVs: 17 HP / 17 Atk / 17 Def / 17 SpA / 17 SpD / 17 Spe + +Machamp @ Black Belt +Level: 33 +IVs: 17 HP / 17 Atk / 17 Def / 17 SpA / 17 SpD / 17 Spe + +=== TRAINER_YUJI === +Name: 和嗣 +Class: Black Belt +Pic: Black Belt +Gender: Male +Music: Intense +Double Battle: No +AI: Check Bad Move + +Makuhita +Level: 26 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +Machoke +Level: 26 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +=== TRAINER_DAISUKE === +Name: 正 +Class: Black Belt +Pic: Black Belt +Gender: Male +Music: Intense +Double Battle: No +AI: Check Bad Move + +Machop +Level: 19 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +=== TRAINER_ATSUSHI === +Name: 哲久 +Class: Black Belt +Pic: Black Belt +Gender: Male +Music: Intense +Double Battle: No +AI: Check Bad Move + +Hariyama +Level: 32 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +=== TRAINER_KIRK === +Name: 乔治 +Class: Guitarist +Pic: Guitarist +Gender: Male +Music: Intense +Double Battle: No +AI: Check Bad Move + +Electrike +Level: 17 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe +- Quick Attack +- Thunder Wave +- Spark +- Leer + +Voltorb +Level: 17 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe +- Charge +- Shock Wave +- Screech + +=== TRAINER_GRUNT_AQUA_HIDEOUT_7 === +Name: 手下 +Class: Team Aqua +Pic: Aqua Grunt F +Gender: Female +Music: Aqua +Double Battle: No +AI: Check Bad Move + +Poochyena +Level: 31 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Zubat +Level: 31 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_GRUNT_AQUA_HIDEOUT_8 === +Name: 手下 +Class: Team Aqua +Pic: Aqua Grunt M +Gender: Male +Music: Aqua +Double Battle: No +AI: Check Bad Move + +Carvanha +Level: 32 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_SHAWN === +Name: 麦克 +Class: Guitarist +Pic: Guitarist +Gender: Male +Music: Intense +Double Battle: No +AI: Check Bad Move + +Voltorb +Level: 17 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +Magnemite +Level: 17 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +=== TRAINER_FERNANDO_1 === +Name: 乔 +Class: Guitarist +Pic: Guitarist +Gender: Male +Music: Intense +Double Battle: No +AI: Check Bad Move + +Electrike +Level: 30 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Loudred +Level: 30 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_DALTON_1 === +Name: 泰瑞 +Class: Guitarist +Pic: Guitarist +Gender: Male +Music: Intense +Double Battle: No +AI: Check Bad Move + +Magnemite +Level: 15 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Whismur +Level: 15 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_DALTON_2 === +Name: 泰瑞 +Class: Guitarist +Pic: Guitarist +Gender: Male +Music: Intense +Double Battle: No +AI: Check Bad Move + +Magnemite +Level: 25 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe + +Whismur +Level: 25 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe + +Magnemite +Level: 25 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe + +=== TRAINER_DALTON_3 === +Name: 泰瑞 +Class: Guitarist +Pic: Guitarist +Gender: Male +Music: Intense +Double Battle: No +AI: Check Bad Move + +Magnemite +Level: 28 +IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe + +Loudred +Level: 28 +IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe + +Magnemite +Level: 28 +IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe + +=== TRAINER_DALTON_4 === +Name: 泰瑞 +Class: Guitarist +Pic: Guitarist +Gender: Male +Music: Intense +Double Battle: No +AI: Check Bad Move + +Magneton +Level: 31 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe + +Loudred +Level: 31 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe + +Magneton +Level: 31 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe + +=== TRAINER_DALTON_5 === +Name: 泰瑞 +Class: Guitarist +Pic: Guitarist +Gender: Male +Music: Intense +Double Battle: No +AI: Check Bad Move + +Magneton +Level: 34 +IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe + +Exploud +Level: 34 +IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe + +Magneton +Level: 34 +IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe + +=== TRAINER_COLE === +Name: 小明 +Class: Kindler +Pic: Kindler +Gender: Male +Music: Hiker +Double Battle: No +AI: Check Bad Move + +Numel +Level: 23 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +=== TRAINER_JEFF === +Name: 光太 +Class: Kindler +Pic: Kindler +Gender: Male +Music: Hiker +Double Battle: No +AI: Check Bad Move + +Slugma +Level: 22 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +Slugma +Level: 22 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +=== TRAINER_AXLE === +Name: 阿保 +Class: Kindler +Pic: Kindler +Gender: Male +Music: Hiker +Double Battle: No +AI: Check Bad Move + +Numel +Level: 23 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +=== TRAINER_JACE === +Name: 顺次 +Class: Kindler +Pic: Kindler +Gender: Male +Music: Hiker +Double Battle: No +AI: Check Bad Move + +Slugma +Level: 23 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +=== TRAINER_KEEGAN === +Name: 晴隆 +Class: Kindler +Pic: Kindler +Gender: Male +Music: Hiker +Double Battle: No +AI: Check Bad Move + +Slugma +Level: 23 +IVs: 14 HP / 14 Atk / 14 Def / 14 SpA / 14 SpD / 14 Spe + +=== TRAINER_BERNIE_1 === +Name: 信彦 +Class: Kindler +Pic: Kindler +Gender: Male +Music: Hiker +Double Battle: No +AI: Check Bad Move + +Slugma +Level: 18 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Wingull +Level: 18 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_BERNIE_2 === +Name: 信彦 +Class: Kindler +Pic: Kindler +Gender: Male +Music: Hiker +Double Battle: No +AI: Check Bad Move + +Slugma +Level: 26 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe + +Wingull +Level: 26 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe + +=== TRAINER_BERNIE_3 === +Name: 信彦 +Class: Kindler +Pic: Kindler +Gender: Male +Music: Hiker +Double Battle: No +AI: Check Bad Move + +Slugma +Level: 29 +IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe + +Pelipper +Level: 29 +IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe + +=== TRAINER_BERNIE_4 === +Name: 信彦 +Class: Kindler +Pic: Kindler +Gender: Male +Music: Hiker +Double Battle: No +AI: Check Bad Move + +Slugma +Level: 32 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe + +Pelipper +Level: 32 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe + +=== TRAINER_BERNIE_5 === +Name: 信彦 +Class: Kindler +Pic: Kindler +Gender: Male +Music: Hiker +Double Battle: No +AI: Check Bad Move + +Magcargo +Level: 35 +IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe + +Pelipper +Level: 35 +IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe + +=== TRAINER_DREW === +Name: 典弘 +Class: Camper +Pic: Camper +Gender: Male +Music: Male +Double Battle: No +AI: Check Bad Move + +Sandshrew +Level: 23 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe +- Dig +- Sand Attack +- Poison Sting +- Slash + +=== TRAINER_BEAU === +Name: 和之 +Class: Camper +Pic: Camper +Gender: Male +Music: Male +Double Battle: No +AI: Check Bad Move + +Baltoy +Level: 21 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe +- Rapid Spin +- Mud Slap +- Psybeam +- Rock Tomb + +Sandshrew +Level: 21 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe +- Poison Sting +- Sand Attack +- Scratch +- Dig + +Baltoy +Level: 21 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe +- Rapid Spin +- Mud Slap +- Psybeam +- Rock Tomb + +=== TRAINER_LARRY === +Name: 清文 +Class: Camper +Pic: Camper +Gender: Male +Music: Male +Double Battle: No +AI: Check Bad Move + +Nuzleaf +Level: 18 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_SHANE === +Name: 智弘 +Class: Camper +Pic: Camper +Gender: Male +Music: Male +Double Battle: No +AI: Check Bad Move + +Sandshrew +Level: 18 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Nuzleaf +Level: 18 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_JUSTIN === +Name: 正道 +Class: Camper +Pic: Camper +Gender: Male +Music: Male +Double Battle: No +AI: Check Bad Move + +Kecleon +Level: 24 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_ETHAN_1 === +Name: 义晴 +Class: Camper +Pic: Camper +Gender: Male +Music: Male +Double Battle: No +AI: Check Bad Move + +Zigzagoon +Level: 20 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Taillow +Level: 20 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_AUTUMN === +Name: 奈津子 +Class: Picnicker +Pic: Picnicker +Gender: Female +Music: Girl +Double Battle: No +AI: Check Bad Move + +Shroomish +Level: 21 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_TRAVIS === +Name: 良也 +Class: Camper +Pic: Camper +Gender: Male +Music: Male +Double Battle: No +AI: Check Bad Move + +Sandshrew +Level: 18 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_ETHAN_2 === +Name: 义晴 +Class: Camper +Pic: Camper +Gender: Male +Music: Male +Double Battle: No +AI: Check Bad Move + +Zigzagoon +Level: 26 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe + +Taillow +Level: 26 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe + +=== TRAINER_ETHAN_3 === +Name: 义晴 +Class: Camper +Pic: Camper +Gender: Male +Music: Male +Double Battle: No +AI: Check Bad Move + +Linoone +Level: 29 +IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe + +Swellow +Level: 29 +IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe + +=== TRAINER_ETHAN_4 === +Name: 义晴 +Class: Camper +Pic: Camper +Gender: Male +Music: Male +Double Battle: No +AI: Check Bad Move + +Sandshrew +Level: 31 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe + +Swellow +Level: 31 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe + +Linoone +Level: 31 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe + +=== TRAINER_ETHAN_5 === +Name: 义晴 +Class: Camper +Pic: Camper +Gender: Male +Music: Male +Double Battle: No +AI: Check Bad Move + +Swellow +Level: 34 +IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe + +Sandslash +Level: 34 +IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe + +Linoone +Level: 34 +IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe + +=== TRAINER_BRENT === +Name: 洋一 +Class: Bug Maniac +Pic: Bug Maniac +Gender: Male +Music: Suspicious +Double Battle: No +AI: Check Bad Move + +Surskit +Level: 26 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +=== TRAINER_DONALD === +Name: 苍介 +Class: Bug Maniac +Pic: Bug Maniac +Gender: Male +Music: Suspicious +Double Battle: No +AI: Check Bad Move + +Wurmple +Level: 24 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +Silcoon +Level: 24 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +Beautifly +Level: 24 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +=== TRAINER_TAYLOR === +Name: 生海 +Class: Bug Maniac +Pic: Bug Maniac +Gender: Male +Music: Suspicious +Double Battle: No +AI: Check Bad Move + +Wurmple +Level: 27 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +Cascoon +Level: 27 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +Dustox +Level: 27 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +=== TRAINER_JEFFREY_1 === +Name: 干雄 +Class: Bug Maniac +Pic: Bug Maniac +Gender: Male +Music: Suspicious +Double Battle: No +AI: Check Bad Move + +Surskit +Level: 27 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Surskit +Level: 27 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Surskit +Level: 27 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_DEREK === +Name: 良明 +Class: Bug Maniac +Pic: Bug Maniac +Gender: Male +Music: Suspicious +Double Battle: No +AI: Check Bad Move + +Dustox +Level: 16 +IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe + +Beautifly +Level: 16 +IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe + +=== TRAINER_JEFFREY_2 === +Name: 干雄 +Class: Bug Maniac +Pic: Bug Maniac +Gender: Male +Music: Suspicious +Double Battle: No +AI: Check Bad Move + +Surskit +Level: 31 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe + +Surskit +Level: 31 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe + +Surskit +Level: 31 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe + +=== TRAINER_JEFFREY_3 === +Name: 干雄 +Class: Bug Maniac +Pic: Bug Maniac +Gender: Male +Music: Suspicious +Double Battle: No +AI: Check Bad Move + +Surskit +Level: 34 +IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe + +Surskit +Level: 34 +IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe + +Masquerain +Level: 34 +IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe + +=== TRAINER_JEFFREY_4 === +Name: 干雄 +Class: Bug Maniac +Pic: Bug Maniac +Gender: Male +Music: Suspicious +Double Battle: No +AI: Check Bad Move + +Surskit +Level: 36 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe + +Wurmple +Level: 36 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe + +Surskit +Level: 36 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe + +Masquerain +Level: 36 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe + +=== TRAINER_JEFFREY_5 === +Name: 干雄 +Class: Bug Maniac +Pic: Bug Maniac +Gender: Male +Music: Suspicious +Double Battle: No +AI: Check Bad Move + +Surskit +Level: 38 +IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe + +Dustox +Level: 38 +IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe + +Surskit +Level: 38 +IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe + +Masquerain @ Silver Powder +Level: 38 +IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe + +Beautifly +Level: 38 +IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe + +=== TRAINER_EDWARD === +Name: 明人 +Class: Psychic +Pic: Psychic M +Gender: Male +Music: Intense +Double Battle: No +AI: Check Bad Move + +Abra +Level: 15 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe +- Hidden Power + +=== TRAINER_PRESTON === +Name: 宏 +Class: Psychic +Pic: Psychic M +Gender: Male +Music: Intense +Double Battle: No +AI: Check Bad Move + +Kirlia +Level: 36 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +=== TRAINER_VIRGIL === +Name: 祐也 +Class: Psychic +Pic: Psychic M +Gender: Male +Music: Intense +Double Battle: No +AI: Check Bad Move + +Ralts +Level: 36 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +=== TRAINER_BLAKE === +Name: 聪 +Class: Psychic +Pic: Psychic M +Gender: Male +Music: Intense +Double Battle: No +AI: Check Bad Move + +Girafarig +Level: 36 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +=== TRAINER_WILLIAM === +Name: 彻也 +Class: Psychic +Pic: Psychic M +Gender: Male +Music: Intense +Double Battle: No +AI: Check Bad Move + +Ralts +Level: 26 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Ralts +Level: 26 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Kirlia +Level: 26 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_JOSHUA === +Name: 修一 +Class: Psychic +Pic: Psychic M +Gender: Male +Music: Intense +Double Battle: No +AI: Check Bad Move + +Kadabra +Level: 41 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Solrock +Level: 41 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_CAMERON_1 === +Name: 薰 +Class: Psychic +Pic: Psychic M +Gender: Male +Music: Intense +Double Battle: No +AI: Check Bad Move + +Solrock +Level: 31 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_CAMERON_2 === +Name: 薰 +Class: Psychic +Pic: Psychic M +Gender: Male +Music: Intense +Double Battle: No +AI: Check Bad Move + +Kadabra +Level: 33 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe + +Solrock +Level: 33 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe + +=== TRAINER_CAMERON_3 === +Name: 薰 +Class: Psychic +Pic: Psychic M +Gender: Male +Music: Intense +Double Battle: No +AI: Check Bad Move + +Kadabra +Level: 38 +IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe + +Solrock +Level: 38 +IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe + +=== TRAINER_CAMERON_4 === +Name: 薰 +Class: Psychic +Pic: Psychic M +Gender: Male +Music: Intense +Double Battle: No +AI: Check Bad Move + +Kadabra +Level: 41 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe + +Solrock +Level: 41 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe + +=== TRAINER_CAMERON_5 === +Name: 薰 +Class: Psychic +Pic: Psychic M +Gender: Male +Music: Intense +Double Battle: No +AI: Check Bad Move + +Solrock +Level: 45 +IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe + +Alakazam +Level: 45 +IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe + +=== TRAINER_JACLYN === +Name: 玛俐可 +Class: Psychic +Pic: Psychic F +Gender: Female +Music: Intense +Double Battle: No +AI: Check Bad Move + +Abra +Level: 16 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe +- Hidden Power + +=== TRAINER_HANNAH === +Name: 飞鸟 +Class: Psychic +Pic: Psychic F +Gender: Female +Music: Intense +Double Battle: No +AI: Check Bad Move + +Kirlia +Level: 36 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +=== TRAINER_SAMANTHA === +Name: 未来 +Class: Psychic +Pic: Psychic F +Gender: Female +Music: Intense +Double Battle: No +AI: Check Bad Move + +Xatu +Level: 36 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +=== TRAINER_MAURA === +Name: 光 +Class: Psychic +Pic: Psychic F +Gender: Female +Music: Intense +Double Battle: No +AI: Check Bad Move + +Kadabra +Level: 36 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +=== TRAINER_KAYLA === +Name: 织江 +Class: Psychic +Pic: Psychic F +Gender: Female +Music: Intense +Double Battle: No +AI: Check Bad Move + +Wobbuffet +Level: 26 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Natu +Level: 26 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Kadabra +Level: 26 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_ALEXIS === +Name: 奈奈子 +Class: Psychic +Pic: Psychic F +Gender: Female +Music: Intense +Double Battle: No +AI: Check Bad Move + +Kirlia +Level: 41 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Xatu +Level: 41 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_JACKI_1 === +Name: 志保美 +Class: Psychic +Pic: Psychic F +Gender: Female +Music: Intense +Double Battle: No +AI: Check Bad Move + +Kadabra +Level: 30 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Lunatone +Level: 30 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_JACKI_2 === +Name: 志保美 +Class: Psychic +Pic: Psychic F +Gender: Female +Music: Intense +Double Battle: No +AI: Check Bad Move + +Kadabra +Level: 34 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe + +Lunatone +Level: 34 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe + +=== TRAINER_JACKI_3 === +Name: 志保美 +Class: Psychic +Pic: Psychic F +Gender: Female +Music: Intense +Double Battle: No +AI: Check Bad Move + +Kadabra +Level: 37 +IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe + +Lunatone +Level: 37 +IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe + +=== TRAINER_JACKI_4 === +Name: 志保美 +Class: Psychic +Pic: Psychic F +Gender: Female +Music: Intense +Double Battle: No +AI: Check Bad Move + +Kadabra +Level: 40 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe + +Lunatone +Level: 40 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe + +=== TRAINER_JACKI_5 === +Name: 志保美 +Class: Psychic +Pic: Psychic F +Gender: Female +Music: Intense +Double Battle: No +AI: Check Bad Move + +Lunatone +Level: 43 +IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe + +Alakazam +Level: 43 +IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe + +=== TRAINER_WALTER_1 === +Name: 罗伯特 +Class: Gentleman +Pic: Gentleman +Gender: Male +Music: Rich +Double Battle: No +AI: Check Bad Move + +Manectric +Level: 29 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_MICAH === +Name: 奥尔森 +Class: Gentleman +Pic: Gentleman +Gender: Male +Music: Rich +Double Battle: No +AI: Check Bad Move + +Manectric +Level: 44 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Manectric +Level: 44 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_THOMAS === +Name: 史考特 +Class: Gentleman +Pic: Gentleman +Gender: Male +Music: Rich +Double Battle: No +AI: Check Bad Move + +Zangoose +Level: 45 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_WALTER_2 === +Name: 罗伯特 +Class: Gentleman +Pic: Gentleman +Gender: Male +Music: Rich +Double Battle: No +AI: Check Bad Move + +Manectric +Level: 34 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe + +=== TRAINER_WALTER_3 === +Name: 罗伯特 +Class: Gentleman +Pic: Gentleman +Gender: Male +Music: Rich +Double Battle: No +AI: Check Bad Move + +Linoone +Level: 36 +IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe +- Headbutt +- Sand Attack +- Odor Sleuth +- Fury Swipes + +Manectric +Level: 36 +IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe +- Quick Attack +- Spark +- Odor Sleuth +- Roar + +=== TRAINER_WALTER_4 === +Name: 罗伯特 +Class: Gentleman +Pic: Gentleman +Gender: Male +Music: Rich +Double Battle: No +AI: Check Bad Move + +Linoone +Level: 39 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe +- Headbutt +- Sand Attack +- Odor Sleuth +- Fury Swipes + +Manectric +Level: 39 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe +- Quick Attack +- Spark +- Odor Sleuth + +=== TRAINER_WALTER_5 === +Name: 罗伯特 +Class: Gentleman +Pic: Gentleman +Gender: Male +Music: Rich +Double Battle: No +AI: Check Bad Move + +Linoone +Level: 41 +IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe +- Headbutt +- Sand Attack +- Odor Sleuth +- Fury Swipes + +Golduck +Level: 41 +IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe +- Fury Swipes +- Disable +- Confusion +- Psych Up + +Manectric +Level: 41 +IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe +- Quick Attack +- Spark +- Odor Sleuth +- Roar + +=== TRAINER_SIDNEY === +Name: 花月 +Class: Elite Four +Pic: Elite Four Sidney +Gender: Male +Music: Elite Four +Items: Full Restore / Full Restore +Double Battle: No +AI: Basic Trainer / Force Setup First Turn +Mugshot: Purple + +Mightyena +Level: 46 +IVs: 30 HP / 30 Atk / 30 Def / 30 SpA / 30 SpD / 30 Spe +- Roar +- Double Edge +- Sand Attack +- Crunch + +Shiftry +Level: 48 +IVs: 30 HP / 30 Atk / 30 Def / 30 SpA / 30 SpD / 30 Spe +- Torment +- Double Team +- Swagger +- Extrasensory + +Cacturne +Level: 46 +IVs: 30 HP / 30 Atk / 30 Def / 30 SpA / 30 SpD / 30 Spe +- Leech Seed +- Feint Attack +- Needle Arm +- Cotton Spore + +Crawdaunt +Level: 48 +IVs: 30 HP / 30 Atk / 30 Def / 30 SpA / 30 SpD / 30 Spe +- Surf +- Swords Dance +- Strength +- Facade + +Absol @ Sitrus Berry +Level: 49 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Aerial Ace +- Rock Slide +- Swords Dance +- Slash + +=== TRAINER_PHOEBE === +Name: 芙蓉 +Class: Elite Four +Pic: Elite Four Phoebe +Gender: Female +Music: Elite Four +Items: Full Restore / Full Restore +Double Battle: No +AI: Basic Trainer +Mugshot: Green + +Dusclops +Level: 48 +IVs: 30 HP / 30 Atk / 30 Def / 30 SpA / 30 SpD / 30 Spe +- Shadow Punch +- Confuse Ray +- Curse +- Protect + +Banette +Level: 49 +IVs: 30 HP / 30 Atk / 30 Def / 30 SpA / 30 SpD / 30 Spe +- Shadow Ball +- Grudge +- Will O Wisp +- Feint Attack + +Sableye +Level: 50 +IVs: 30 HP / 30 Atk / 30 Def / 30 SpA / 30 SpD / 30 Spe +- Shadow Ball +- Double Team +- Night Shade +- Feint Attack + +Banette +Level: 49 +IVs: 30 HP / 30 Atk / 30 Def / 30 SpA / 30 SpD / 30 Spe +- Shadow Ball +- Psychic +- Thunderbolt +- Facade + +Dusclops @ Sitrus Berry +Level: 51 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Shadow Ball +- Ice Beam +- Rock Slide +- Earthquake + +=== TRAINER_GLACIA === +Name: 波妮 +Class: Elite Four +Pic: Elite Four Glacia +Gender: Female +Music: Elite Four +Items: Full Restore / Full Restore +Double Battle: No +AI: Basic Trainer +Mugshot: Pink + +Sealeo +Level: 50 +IVs: 30 HP / 30 Atk / 30 Def / 30 SpA / 30 SpD / 30 Spe +- Encore +- Body Slam +- Hail +- Ice Ball + +Glalie +Level: 50 +IVs: 30 HP / 30 Atk / 30 Def / 30 SpA / 30 SpD / 30 Spe +- Light Screen +- Crunch +- Icy Wind +- Ice Beam + +Sealeo +Level: 52 +IVs: 30 HP / 30 Atk / 30 Def / 30 SpA / 30 SpD / 30 Spe +- Attract +- Double Edge +- Hail +- Blizzard + +Glalie +Level: 52 +IVs: 30 HP / 30 Atk / 30 Def / 30 SpA / 30 SpD / 30 Spe +- Shadow Ball +- Explosion +- Hail +- Ice Beam + +Walrein @ Sitrus Berry +Level: 53 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Surf +- Body Slam +- Ice Beam +- Sheer Cold + +=== TRAINER_DRAKE === +Name: 源治 +Class: Elite Four +Pic: Elite Four Drake +Gender: Male +Music: Elite Four +Items: Full Restore / Full Restore +Double Battle: No +AI: Basic Trainer +Mugshot: Blue + +Shelgon +Level: 52 +IVs: 30 HP / 30 Atk / 30 Def / 30 SpA / 30 SpD / 30 Spe +- Rock Tomb +- Dragon Claw +- Protect +- Double Edge + +Altaria +Level: 54 +IVs: 30 HP / 30 Atk / 30 Def / 30 SpA / 30 SpD / 30 Spe +- Double Edge +- Dragon Breath +- Dragon Dance +- Aerial Ace + +Kingdra +Level: 53 +IVs: 30 HP / 30 Atk / 30 Def / 30 SpA / 30 SpD / 30 Spe +- Smokescreen +- Dragon Dance +- Surf +- Body Slam + +Flygon +Level: 53 +IVs: 30 HP / 30 Atk / 30 Def / 30 SpA / 30 SpD / 30 Spe +- Flamethrower +- Crunch +- Dragon Breath +- Earthquake + +Salamence @ Sitrus Berry +Level: 55 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Flamethrower +- Dragon Claw +- Rock Slide +- Crunch + +=== TRAINER_ROXANNE_1 === +Name: 杜娟 +Class: Leader +Pic: Leader Roxanne +Gender: Female +Music: Female +Items: Potion / Potion +Double Battle: No +AI: Basic Trainer + +Geodude +Level: 12 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe +- Tackle +- Defense Curl +- Rock Throw +- Rock Tomb + +Geodude +Level: 12 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe +- Tackle +- Defense Curl +- Rock Throw +- Rock Tomb + +Nosepass @ Oran Berry +Level: 15 +IVs: 24 HP / 24 Atk / 24 Def / 24 SpA / 24 SpD / 24 Spe +- Block +- Harden +- Tackle +- Rock Tomb + +=== TRAINER_BRAWLY_1 === +Name: 藤树 +Class: Leader +Pic: Leader Brawly +Gender: Male +Music: Male +Items: Super Potion / Super Potion +Double Battle: No +AI: Basic Trainer + +Machop +Level: 16 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe +- Karate Chop +- Low Kick +- Seismic Toss +- Bulk Up + +Meditite +Level: 16 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe +- Focus Punch +- Light Screen +- Reflect +- Bulk Up + +Makuhita @ Sitrus Berry +Level: 19 +IVs: 24 HP / 24 Atk / 24 Def / 24 SpA / 24 SpD / 24 Spe +- Arm Thrust +- Vital Throw +- Reversal +- Bulk Up + +=== TRAINER_WATTSON_1 === +Name: 铁旋 +Class: Leader +Pic: Leader Wattson +Gender: Male +Music: Male +Items: Super Potion / Super Potion +Double Battle: No +AI: Basic Trainer + +Voltorb +Level: 20 +IVs: 24 HP / 24 Atk / 24 Def / 24 SpA / 24 SpD / 24 Spe +- Rollout +- Spark +- Self Destruct +- Shock Wave + +Electrike +Level: 20 +IVs: 24 HP / 24 Atk / 24 Def / 24 SpA / 24 SpD / 24 Spe +- Shock Wave +- Leer +- Quick Attack +- Howl + +Magneton +Level: 22 +IVs: 26 HP / 26 Atk / 26 Def / 26 SpA / 26 SpD / 26 Spe +- Supersonic +- Shock Wave +- Thunder Wave +- Sonic Boom + +Manectric @ Sitrus Berry +Level: 24 +IVs: 30 HP / 30 Atk / 30 Def / 30 SpA / 30 SpD / 30 Spe +- Quick Attack +- Thunder Wave +- Shock Wave +- Howl + +=== TRAINER_FLANNERY_1 === +Name: 亚莎 +Class: Leader +Pic: Leader Flannery +Gender: Female +Music: Female +Items: Hyper Potion / Hyper Potion +Double Battle: No +AI: Basic Trainer + +Numel +Level: 24 +IVs: 24 HP / 24 Atk / 24 Def / 24 SpA / 24 SpD / 24 Spe +- Overheat +- Take Down +- Magnitude +- Sunny Day + +Slugma +Level: 24 +IVs: 24 HP / 24 Atk / 24 Def / 24 SpA / 24 SpD / 24 Spe +- Overheat +- Smog +- Light Screen +- Sunny Day + +Camerupt +Level: 26 +IVs: 30 HP / 30 Atk / 30 Def / 30 SpA / 30 SpD / 30 Spe +- Overheat +- Tackle +- Sunny Day +- Attract + +Torkoal @ White Herb +Level: 29 +IVs: 30 HP / 30 Atk / 30 Def / 30 SpA / 30 SpD / 30 Spe +- Overheat +- Sunny Day +- Body Slam +- Attract + +=== TRAINER_NORMAN_1 === +Name: 千里 +Class: Leader +Pic: Leader Norman +Gender: Male +Music: Male +Items: Hyper Potion / Hyper Potion +Double Battle: No +AI: Basic Trainer + +Spinda +Level: 27 +IVs: 24 HP / 24 Atk / 24 Def / 24 SpA / 24 SpD / 24 Spe +- Teeter Dance +- Psybeam +- Facade +- Encore + +Vigoroth +Level: 27 +IVs: 24 HP / 24 Atk / 24 Def / 24 SpA / 24 SpD / 24 Spe +- Slash +- Facade +- Encore +- Feint Attack + +Linoone +Level: 29 +IVs: 24 HP / 24 Atk / 24 Def / 24 SpA / 24 SpD / 24 Spe +- Slash +- Belly Drum +- Facade +- Headbutt + +Slaking @ Sitrus Berry +Level: 31 +IVs: 30 HP / 30 Atk / 30 Def / 30 SpA / 30 SpD / 30 Spe +- Counter +- Yawn +- Facade +- Feint Attack + +=== TRAINER_WINONA_1 === +Name: 娜琪 +Class: Leader +Pic: Leader Winona +Gender: Female +Music: Female +Items: Hyper Potion / Hyper Potion +Double Battle: No +AI: Basic Trainer / Risky + +Swablu +Level: 29 +IVs: 25 HP / 25 Atk / 25 Def / 25 SpA / 25 SpD / 25 Spe +- Perish Song +- Mirror Move +- Safeguard +- Aerial Ace + +Tropius +Level: 29 +IVs: 25 HP / 25 Atk / 25 Def / 25 SpA / 25 SpD / 25 Spe +- Sunny Day +- Aerial Ace +- Solar Beam +- Synthesis + +Pelipper +Level: 30 +IVs: 25 HP / 25 Atk / 25 Def / 25 SpA / 25 SpD / 25 Spe +- Water Gun +- Supersonic +- Protect +- Aerial Ace + +Skarmory +Level: 31 +IVs: 26 HP / 26 Atk / 26 Def / 26 SpA / 26 SpD / 26 Spe +- Sand Attack +- Fury Attack +- Steel Wing +- Aerial Ace + +Altaria @ Oran Berry +Level: 33 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Earthquake +- Dragon Breath +- Dragon Dance +- Aerial Ace + +=== TRAINER_TATE_AND_LIZA_1 === +Name: 小枫与小南 +Class: Leader +Pic: Leader Tate And Liza +Gender: Male +Music: Female +Items: Hyper Potion / Hyper Potion / Hyper Potion / Hyper Potion +Double Battle: Yes +AI: Basic Trainer + +Claydol +Level: 41 +IVs: 30 HP / 30 Atk / 30 Def / 30 SpA / 30 SpD / 30 Spe +- Earthquake +- Ancient Power +- Psychic +- Light Screen + +Xatu +Level: 41 +IVs: 30 HP / 30 Atk / 30 Def / 30 SpA / 30 SpD / 30 Spe +- Psychic +- Sunny Day +- Confuse Ray +- Calm Mind + +Lunatone @ Sitrus Berry +Level: 42 +IVs: 30 HP / 30 Atk / 30 Def / 30 SpA / 30 SpD / 30 Spe +- Light Screen +- Psychic +- Hypnosis +- Calm Mind + +Solrock @ Sitrus Berry +Level: 42 +IVs: 30 HP / 30 Atk / 30 Def / 30 SpA / 30 SpD / 30 Spe +- Sunny Day +- Solar Beam +- Psychic +- Flamethrower + +=== TRAINER_JUAN_1 === +Name: 亚当 +Class: Leader +Pic: Leader Juan +Gender: Male +Music: Male +Items: Hyper Potion / Hyper Potion +Double Battle: No +AI: Basic Trainer + +Luvdisc +Level: 41 +IVs: 24 HP / 24 Atk / 24 Def / 24 SpA / 24 SpD / 24 Spe +- Water Pulse +- Attract +- Sweet Kiss +- Flail + +Whiscash +Level: 41 +IVs: 24 HP / 24 Atk / 24 Def / 24 SpA / 24 SpD / 24 Spe +- Rain Dance +- Water Pulse +- Amnesia +- Earthquake + +Sealeo +Level: 43 +IVs: 24 HP / 24 Atk / 24 Def / 24 SpA / 24 SpD / 24 Spe +- Encore +- Body Slam +- Aurora Beam +- Water Pulse + +Crawdaunt +Level: 43 +IVs: 24 HP / 24 Atk / 24 Def / 24 SpA / 24 SpD / 24 Spe +- Water Pulse +- Crabhammer +- Taunt +- Leer + +Kingdra @ Chesto Berry +Level: 46 +IVs: 30 HP / 30 Atk / 30 Def / 30 SpA / 30 SpD / 30 Spe +- Water Pulse +- Double Team +- Ice Beam +- Rest + +=== TRAINER_JERRY_1 === +Name: 秀夫 +Class: School Kid +Pic: School Kid M +Gender: Male +Music: Male +Double Battle: No +AI: Check Bad Move + +Ralts +Level: 9 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe + +=== TRAINER_TED === +Name: 信久 +Class: School Kid +Pic: School Kid M +Gender: Male +Music: Male +Double Battle: No +AI: Check Bad Move + +Ralts +Level: 17 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe + +=== TRAINER_PAUL === +Name: 胜俊 +Class: School Kid +Pic: School Kid M +Gender: Male +Music: Male +Double Battle: No +AI: Check Bad Move + +Numel +Level: 15 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe + +Oddish +Level: 15 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe + +Wingull +Level: 15 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe + +=== TRAINER_JERRY_2 === +Name: 秀夫 +Class: School Kid +Pic: School Kid M +Gender: Male +Music: Male +Double Battle: No +AI: Check Bad Move + +Ralts +Level: 26 +IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe + +Meditite +Level: 26 +IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe + +=== TRAINER_JERRY_3 === +Name: 秀夫 +Class: School Kid +Pic: School Kid M +Gender: Male +Music: Male +Double Battle: No +AI: Check Bad Move + +Kirlia +Level: 29 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe + +Meditite +Level: 29 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe + +=== TRAINER_JERRY_4 === +Name: 秀夫 +Class: School Kid +Pic: School Kid M +Gender: Male +Music: Male +Double Battle: No +AI: Check Bad Move + +Kirlia +Level: 32 +IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe + +Medicham +Level: 32 +IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe + +=== TRAINER_JERRY_5 === +Name: 秀夫 +Class: School Kid +Pic: School Kid M +Gender: Male +Music: Male +Double Battle: No +AI: Check Bad Move + +Kirlia +Level: 34 +IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe + +Banette +Level: 34 +IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe + +Medicham +Level: 34 +IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe + +=== TRAINER_KAREN_1 === +Name: 初音 +Class: School Kid +Pic: School Kid F +Gender: Female +Music: Girl +Double Battle: No +AI: Check Bad Move + +Shroomish +Level: 9 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe + +=== TRAINER_GEORGIA === +Name: 美贵江 +Class: School Kid +Pic: School Kid F +Gender: Female +Music: Girl +Double Battle: No +AI: Check Bad Move + +Shroomish +Level: 16 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe + +Beautifly +Level: 16 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe + +=== TRAINER_KAREN_2 === +Name: 初音 +Class: School Kid +Pic: School Kid F +Gender: Female +Music: Girl +Double Battle: No +AI: Check Bad Move + +Shroomish +Level: 26 +IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe + +Whismur +Level: 26 +IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe + +=== TRAINER_KAREN_3 === +Name: 初音 +Class: School Kid +Pic: School Kid F +Gender: Female +Music: Girl +Double Battle: No +AI: Check Bad Move + +Shroomish +Level: 29 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe + +Loudred +Level: 29 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe + +=== TRAINER_KAREN_4 === +Name: 初音 +Class: School Kid +Pic: School Kid F +Gender: Female +Music: Girl +Double Battle: No +AI: Check Bad Move + +Breloom +Level: 32 +IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe + +Loudred +Level: 32 +IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe + +=== TRAINER_KAREN_5 === +Name: 初音 +Class: School Kid +Pic: School Kid F +Gender: Female +Music: Girl +Double Battle: No +AI: Check Bad Move + +Breloom +Level: 35 +IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe + +Exploud +Level: 35 +IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe + +=== TRAINER_KATE_AND_JOY === +Name: 真奈和由依 +Class: Sr And Jr +Pic: Sr And Jr +Gender: Male +Music: Twins +Double Battle: Yes +AI: Check Bad Move + +Spinda +Level: 30 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe +- Hypnosis +- Psybeam +- Dizzy Punch +- Teeter Dance + +Slaking +Level: 32 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe +- Focus Punch +- Yawn +- Slack Off +- Feint Attack + +=== TRAINER_ANNA_AND_MEG_1 === +Name: 美穗和里子 +Class: Sr And Jr +Pic: Sr And Jr +Gender: Male +Music: Twins +Double Battle: Yes +AI: Check Bad Move + +Zigzagoon +Level: 15 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe +- Growl +- Tail Whip +- Headbutt +- Odor Sleuth + +Makuhita +Level: 17 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe +- Tackle +- Focus Energy +- Arm Thrust + +=== TRAINER_ANNA_AND_MEG_2 === +Name: 美穗和里子 +Class: Sr And Jr +Pic: Sr And Jr +Gender: Male +Music: Twins +Double Battle: Yes +AI: Check Bad Move + +Zigzagoon +Level: 28 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe +- Growl +- Tail Whip +- Headbutt +- Odor Sleuth + +Makuhita +Level: 30 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe +- Tackle +- Focus Energy +- Arm Thrust + +=== TRAINER_ANNA_AND_MEG_3 === +Name: 美穗和里子 +Class: Sr And Jr +Pic: Sr And Jr +Gender: Male +Music: Twins +Double Battle: Yes +AI: Check Bad Move + +Zigzagoon +Level: 31 +IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe +- Growl +- Tail Whip +- Headbutt +- Odor Sleuth + +Makuhita +Level: 33 +IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe +- Tackle +- Focus Energy +- Arm Thrust + +=== TRAINER_ANNA_AND_MEG_4 === +Name: 美穗和里子 +Class: Sr And Jr +Pic: Sr And Jr +Gender: Male +Music: Twins +Double Battle: Yes +AI: Check Bad Move + +Linoone +Level: 34 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe +- Growl +- Tail Whip +- Headbutt +- Odor Sleuth + +Makuhita +Level: 36 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe +- Tackle +- Focus Energy +- Arm Thrust + +=== TRAINER_ANNA_AND_MEG_5 === +Name: 美穗和里子 +Class: Sr And Jr +Pic: Sr And Jr +Gender: Male +Music: Twins +Double Battle: Yes +AI: Check Bad Move + +Linoone +Level: 36 +IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe +- Growl +- Tail Whip +- Headbutt +- Odor Sleuth + +Hariyama +Level: 38 +IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe +- Tackle +- Focus Energy +- Arm Thrust + +=== TRAINER_VICTOR === +Name: 晴彦 +Class: Winstrate +Pic: Pokefan M +Gender: Male +Music: Twins +Double Battle: No +AI: Check Bad Move + +Taillow @ Oran Berry +Level: 16 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe + +Zigzagoon @ Oran Berry +Level: 16 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe + +=== TRAINER_MIGUEL_1 === +Name: 光晴 +Class: Pokefan +Pic: Pokefan M +Gender: Male +Music: Twins +Double Battle: No +AI: Check Bad Move + +Skitty @ Oran Berry +Level: 15 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_COLTON === +Name: 尚志 +Class: Pokefan +Pic: Pokefan M +Gender: Male +Music: Twins +Double Battle: No +AI: Check Bad Move + +Skitty @ Oran Berry +Level: 22 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe +- Assist +- Charm +- Feint Attack +- Heal Bell + +Skitty @ Oran Berry +Level: 36 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe +- Assist +- Charm +- Feint Attack +- Heal Bell + +Skitty @ Oran Berry +Level: 40 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe +- Assist +- Charm +- Feint Attack +- Heal Bell + +Skitty @ Oran Berry +Level: 12 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe +- Assist +- Charm +- Feint Attack +- Heal Bell + +Skitty @ Oran Berry +Level: 30 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe +- Assist +- Charm +- Feint Attack +- Heal Bell + +Delcatty @ Oran Berry +Level: 42 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe +- Assist +- Charm +- Feint Attack +- Heal Bell + +=== TRAINER_MIGUEL_2 === +Name: 光晴 +Class: Pokefan +Pic: Pokefan M +Gender: Male +Music: Twins +Double Battle: No +AI: Check Bad Move + +Skitty @ Oran Berry +Level: 29 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_MIGUEL_3 === +Name: 光晴 +Class: Pokefan +Pic: Pokefan M +Gender: Male +Music: Twins +Double Battle: No +AI: Check Bad Move + +Skitty @ Oran Berry +Level: 32 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_MIGUEL_4 === +Name: 光晴 +Class: Pokefan +Pic: Pokefan M +Gender: Male +Music: Twins +Double Battle: No +AI: Check Bad Move + +Delcatty @ Oran Berry +Level: 35 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_MIGUEL_5 === +Name: 光晴 +Class: Pokefan +Pic: Pokefan M +Gender: Male +Music: Twins +Double Battle: No +AI: Check Bad Move + +Delcatty @ Sitrus Berry +Level: 38 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_VICTORIA === +Name: 安江 +Class: Winstrate +Pic: Pokefan F +Gender: Female +Music: Twins +Double Battle: No +AI: Check Bad Move / Try To Faint + +Roselia @ Oran Berry +Level: 17 +IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe + +=== TRAINER_VANESSA === +Name: 今朝子 +Class: Pokefan +Pic: Pokefan F +Gender: Female +Music: Twins +Double Battle: No +AI: Check Bad Move + +Pikachu @ Oran Berry +Level: 30 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_BETHANY === +Name: 汀子 +Class: Pokefan +Pic: Pokefan F +Gender: Female +Music: Twins +Double Battle: No +AI: Check Bad Move + +Azurill @ Oran Berry +Level: 35 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +Marill @ Oran Berry +Level: 37 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +Azumarill @ Oran Berry +Level: 39 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +=== TRAINER_ISABEL_1 === +Name: 雅子 +Class: Pokefan +Pic: Pokefan F +Gender: Female +Music: Twins +Double Battle: No +AI: Check Bad Move + +Plusle @ Oran Berry +Level: 14 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Minun @ Oran Berry +Level: 14 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_ISABEL_2 === +Name: 雅子 +Class: Pokefan +Pic: Pokefan F +Gender: Female +Music: Twins +Double Battle: No +AI: Check Bad Move + +Plusle @ Oran Berry +Level: 26 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe + +Minun @ Oran Berry +Level: 26 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe + +=== TRAINER_ISABEL_3 === +Name: 雅子 +Class: Pokefan +Pic: Pokefan F +Gender: Female +Music: Twins +Double Battle: No +AI: Check Bad Move + +Plusle @ Oran Berry +Level: 29 +IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe + +Minun @ Oran Berry +Level: 29 +IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe + +=== TRAINER_ISABEL_4 === +Name: 雅子 +Class: Pokefan +Pic: Pokefan F +Gender: Female +Music: Twins +Double Battle: No +AI: Check Bad Move + +Plusle @ Oran Berry +Level: 32 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe + +Minun @ Oran Berry +Level: 32 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe + +=== TRAINER_ISABEL_5 === +Name: 雅子 +Class: Pokefan +Pic: Pokefan F +Gender: Female +Music: Twins +Double Battle: No +AI: Check Bad Move + +Plusle @ Sitrus Berry +Level: 35 +IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe + +Minun @ Sitrus Berry +Level: 35 +IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe + +=== TRAINER_TIMOTHY_1 === +Name: 文翔 +Class: Expert +Pic: Expert M +Gender: Male +Music: Intense +Double Battle: No +AI: Basic Trainer + +Hariyama +Level: 27 +IVs: 24 HP / 24 Atk / 24 Def / 24 SpA / 24 SpD / 24 Spe + +=== TRAINER_TIMOTHY_2 === +Name: 文翔 +Class: Expert +Pic: Expert M +Gender: Male +Music: Intense +Double Battle: No +AI: Basic Trainer + +Hariyama +Level: 33 +IVs: 25 HP / 25 Atk / 25 Def / 25 SpA / 25 SpD / 25 Spe +- Arm Thrust +- Knock Off +- Sand Attack +- Dig + +=== TRAINER_TIMOTHY_3 === +Name: 文翔 +Class: Expert +Pic: Expert M +Gender: Male +Music: Intense +Double Battle: No +AI: Basic Trainer + +Hariyama +Level: 36 +IVs: 26 HP / 26 Atk / 26 Def / 26 SpA / 26 SpD / 26 Spe +- Arm Thrust +- Knock Off +- Sand Attack +- Dig + +=== TRAINER_TIMOTHY_4 === +Name: 文翔 +Class: Expert +Pic: Expert M +Gender: Male +Music: Intense +Double Battle: No +AI: Basic Trainer + +Hariyama +Level: 39 +IVs: 27 HP / 27 Atk / 27 Def / 27 SpA / 27 SpD / 27 Spe +- Arm Thrust +- Belly Drum +- Sand Attack +- Dig + +=== TRAINER_TIMOTHY_5 === +Name: 文翔 +Class: Expert +Pic: Expert M +Gender: Male +Music: Intense +Double Battle: No +AI: Basic Trainer + +Hariyama +Level: 42 +IVs: 29 HP / 29 Atk / 29 Def / 29 SpA / 29 SpD / 29 Spe +- Arm Thrust +- Belly Drum +- Sand Attack +- Dig + +=== TRAINER_VICKY === +Name: 光代 +Class: Winstrate +Pic: Expert F +Gender: Female +Music: Intense +Double Battle: No +AI: Basic Trainer + +Meditite +Level: 18 +IVs: 24 HP / 24 Atk / 24 Def / 24 SpA / 24 SpD / 24 Spe +- High Jump Kick +- Meditate +- Confusion +- Detect + +=== TRAINER_SHELBY_1 === +Name: 宫子 +Class: Expert +Pic: Expert F +Gender: Female +Music: Intense +Double Battle: No +AI: Basic Trainer + +Meditite +Level: 21 +IVs: 24 HP / 24 Atk / 24 Def / 24 SpA / 24 SpD / 24 Spe + +Makuhita +Level: 21 +IVs: 24 HP / 24 Atk / 24 Def / 24 SpA / 24 SpD / 24 Spe + +=== TRAINER_SHELBY_2 === +Name: 宫子 +Class: Expert +Pic: Expert F +Gender: Female +Music: Intense +Double Battle: No +AI: Basic Trainer + +Meditite +Level: 30 +IVs: 25 HP / 25 Atk / 25 Def / 25 SpA / 25 SpD / 25 Spe + +Makuhita +Level: 30 +IVs: 25 HP / 25 Atk / 25 Def / 25 SpA / 25 SpD / 25 Spe + +=== TRAINER_SHELBY_3 === +Name: 宫子 +Class: Expert +Pic: Expert F +Gender: Female +Music: Intense +Double Battle: No +AI: Basic Trainer + +Medicham +Level: 33 +IVs: 26 HP / 26 Atk / 26 Def / 26 SpA / 26 SpD / 26 Spe + +Hariyama +Level: 33 +IVs: 26 HP / 26 Atk / 26 Def / 26 SpA / 26 SpD / 26 Spe + +=== TRAINER_SHELBY_4 === +Name: 宫子 +Class: Expert +Pic: Expert F +Gender: Female +Music: Intense +Double Battle: No +AI: Basic Trainer + +Medicham +Level: 36 +IVs: 27 HP / 27 Atk / 27 Def / 27 SpA / 27 SpD / 27 Spe + +Hariyama +Level: 36 +IVs: 27 HP / 27 Atk / 27 Def / 27 SpA / 27 SpD / 27 Spe + +=== TRAINER_SHELBY_5 === +Name: 宫子 +Class: Expert +Pic: Expert F +Gender: Female +Music: Intense +Double Battle: No +AI: Basic Trainer + +Medicham +Level: 39 +IVs: 29 HP / 29 Atk / 29 Def / 29 SpA / 29 SpD / 29 Spe + +Hariyama +Level: 39 +IVs: 29 HP / 29 Atk / 29 Def / 29 SpA / 29 SpD / 29 Spe + +=== TRAINER_CALVIN_1 === +Name: 和树 +Class: Youngster +Pic: Youngster +Gender: Male +Music: Male +Double Battle: No +AI: Check Bad Move + +Poochyena +Level: 5 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_BILLY === +Name: 庆太 +Class: Youngster +Pic: Youngster +Gender: Male +Music: Male +Double Battle: No +AI: Check Bad Move + +Zigzagoon +Level: 5 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Seedot +Level: 7 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_JOSH === +Name: 太郎 +Class: Youngster +Pic: Youngster +Gender: Male +Music: Male +Double Battle: No +AI: Check Bad Move + +Geodude +Level: 10 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe +- Tackle + +=== TRAINER_TOMMY === +Name: 克雄 +Class: Youngster +Pic: Youngster +Gender: Male +Music: Male +Double Battle: No +AI: Check Bad Move + +Geodude +Level: 8 +IVs: 13 HP / 13 Atk / 13 Def / 13 SpA / 13 SpD / 13 Spe + +Geodude +Level: 8 +IVs: 14 HP / 14 Atk / 14 Def / 14 SpA / 14 SpD / 14 Spe + +=== TRAINER_JOEY === +Name: 武雄 +Class: Youngster +Pic: Youngster +Gender: Male +Music: Male +Double Battle: No +AI: Check Bad Move + +Machop +Level: 9 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_BEN === +Name: 弘人 +Class: Youngster +Pic: Youngster +Gender: Male +Music: Male +Double Battle: No +AI: Check Bad Move + +Zigzagoon +Level: 17 +IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe +- Headbutt +- Sand Attack +- Growl +- Thunderbolt + +Gulpin +Level: 17 +IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe +- Amnesia +- Sludge +- Yawn +- Pound + +=== TRAINER_QUINCY === +Name: 忠俊 +Class: Cooltrainer +Pic: Cooltrainer M +Gender: Male +Music: Cool +Items: Full Restore +Double Battle: No +AI: Basic Trainer + +Slaking +Level: 43 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe +- Attract +- Ice Beam +- Thunderbolt +- Flamethrower + +Dusclops +Level: 43 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe +- Skill Swap +- Protect +- Will O Wisp +- Toxic + +=== TRAINER_KATELYNN === +Name: 铃香 +Class: Cooltrainer +Pic: Cooltrainer F +Gender: Female +Music: Cool +Items: Full Restore +Double Battle: No +AI: Basic Trainer + +Gardevoir +Level: 43 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe +- Skill Swap +- Psychic +- Thunderbolt +- Calm Mind + +Slaking +Level: 43 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe +- Earthquake +- Shadow Ball +- Aerial Ace +- Brick Break + +=== TRAINER_JAYLEN === +Name: 雅之 +Class: Youngster +Pic: Youngster +Gender: Male +Music: Male +Double Battle: No +AI: Check Bad Move + +Trapinch +Level: 19 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_DILLON === +Name: 义人 +Class: Youngster +Pic: Youngster +Gender: Male +Music: Male +Double Battle: No +AI: Check Bad Move + +Aron +Level: 19 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_CALVIN_2 === +Name: 和树 +Class: Youngster +Pic: Youngster +Gender: Male +Music: Male +Double Battle: No +AI: Check Bad Move + +Mightyena +Level: 27 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe + +=== TRAINER_CALVIN_3 === +Name: 和树 +Class: Youngster +Pic: Youngster +Gender: Male +Music: Male +Double Battle: No +AI: Check Bad Move + +Swellow +Level: 28 +IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe + +Mightyena +Level: 30 +IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe + +=== TRAINER_CALVIN_4 === +Name: 和树 +Class: Youngster +Pic: Youngster +Gender: Male +Music: Male +Double Battle: No +AI: Check Bad Move + +Swellow +Level: 31 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe + +Linoone +Level: 29 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe + +Mightyena +Level: 33 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe + +=== TRAINER_CALVIN_5 === +Name: 和树 +Class: Youngster +Pic: Youngster +Gender: Male +Music: Male +Double Battle: No +AI: Check Bad Move + +Swellow +Level: 34 +IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe + +Linoone +Level: 32 +IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe + +Mightyena +Level: 36 +IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe + +=== TRAINER_EDDIE === +Name: 康幸 +Class: Youngster +Pic: Youngster +Gender: Male +Music: Male +Double Battle: No +AI: Check Bad Move + +Zigzagoon +Level: 14 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Zigzagoon +Level: 16 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_ALLEN === +Name: 勇 +Class: Youngster +Pic: Youngster +Gender: Male +Music: Male +Double Battle: No +AI: Check Bad Move + +Zigzagoon +Level: 4 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Taillow +Level: 3 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_TIMMY === +Name: 真悟 +Class: Youngster +Pic: Youngster +Gender: Male +Music: Male +Double Battle: No +AI: Check Bad Move + +Aron +Level: 15 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Electrike +Level: 13 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_WALLACE === +Name: 米可利 +Class: Champion +Pic: Champion Wallace +Gender: Male +Music: Male +Items: Full Restore / Full Restore / Full Restore / Full Restore +Double Battle: No +AI: Basic Trainer +Mugshot: Yellow + +Wailord +Level: 57 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Rain Dance +- Water Spout +- Double Edge +- Blizzard + +Tentacruel +Level: 55 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Toxic +- Hydro Pump +- Sludge Bomb +- Ice Beam + +Ludicolo +Level: 56 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Giga Drain +- Surf +- Leech Seed +- Double Team + +Whiscash +Level: 56 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Earthquake +- Surf +- Amnesia +- Hyper Beam + +Gyarados +Level: 56 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Dragon Dance +- Earthquake +- Hyper Beam +- Surf + +Milotic @ Sitrus Berry +Level: 58 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Recover +- Surf +- Ice Beam +- Toxic + +=== TRAINER_ANDREW === +Name: 胜典 +Class: Fisherman +Pic: Fisherman +Gender: Male +Music: Hiker +Double Battle: No +AI: Check Bad Move + +Magikarp +Level: 5 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Tentacool +Level: 10 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Magikarp +Level: 15 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_IVAN === +Name: 佳孝 +Class: Fisherman +Pic: Fisherman +Gender: Male +Music: Hiker +Double Battle: No +AI: Check Bad Move + +Magikarp +Level: 5 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Magikarp +Level: 6 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Magikarp +Level: 7 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_CLAUDE === +Name: 秀之 +Class: Fisherman +Pic: Fisherman +Gender: Male +Music: Hiker +Double Battle: No +AI: Check Bad Move + +Magikarp +Level: 16 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Goldeen +Level: 17 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Barboach +Level: 18 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_ELLIOT_1 === +Name: 明彦 +Class: Fisherman +Pic: Fisherman +Gender: Male +Music: Hiker +Double Battle: No +AI: Check Bad Move + +Magikarp +Level: 10 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Tentacool +Level: 7 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Magikarp +Level: 10 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_NED === +Name: 友和 +Class: Fisherman +Pic: Fisherman +Gender: Male +Music: Hiker +Double Battle: No +AI: Check Bad Move + +Tentacool +Level: 11 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe + +=== TRAINER_DALE === +Name: 贵文 +Class: Fisherman +Pic: Fisherman +Gender: Male +Music: Hiker +Double Battle: No +AI: Check Bad Move + +Tentacool +Level: 11 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Wailmer +Level: 14 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Tentacool +Level: 11 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Wailmer +Level: 14 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_NOLAN === +Name: 孝则 +Class: Fisherman +Pic: Fisherman +Gender: Male +Music: Hiker +Double Battle: No +AI: Check Bad Move + +Barboach +Level: 19 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_BARNY === +Name: 和彦 +Class: Fisherman +Pic: Fisherman +Gender: Male +Music: Hiker +Double Battle: No +AI: Check Bad Move + +Tentacool +Level: 25 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Carvanha +Level: 25 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_WADE === +Name: 绩 +Class: Fisherman +Pic: Fisherman +Gender: Male +Music: Hiker +Double Battle: No +AI: Check Bad Move + +Tentacool +Level: 16 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_CARTER === +Name: 高弘 +Class: Fisherman +Pic: Fisherman +Gender: Male +Music: Hiker +Double Battle: No +AI: Check Bad Move + +Wailmer +Level: 25 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe + +Tentacruel +Level: 25 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe + +=== TRAINER_ELLIOT_2 === +Name: 明彦 +Class: Fisherman +Pic: Fisherman +Gender: Male +Music: Hiker +Double Battle: No +AI: Check Bad Move + +Tentacool +Level: 24 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe + +Gyarados +Level: 27 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe + +Gyarados +Level: 27 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe + +=== TRAINER_ELLIOT_3 === +Name: 明彦 +Class: Fisherman +Pic: Fisherman +Gender: Male +Music: Hiker +Double Battle: No +AI: Check Bad Move + +Gyarados +Level: 29 +IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe + +Carvanha +Level: 26 +IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe + +Tentacool +Level: 26 +IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe + +Gyarados +Level: 29 +IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe + +=== TRAINER_ELLIOT_4 === +Name: 明彦 +Class: Fisherman +Pic: Fisherman +Gender: Male +Music: Hiker +Double Battle: No +AI: Check Bad Move + +Gyarados +Level: 31 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe + +Carvanha +Level: 30 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe + +Tentacruel +Level: 30 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe + +Gyarados +Level: 31 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe + +=== TRAINER_ELLIOT_5 === +Name: 明彦 +Class: Fisherman +Pic: Fisherman +Gender: Male +Music: Hiker +Double Battle: No +AI: Check Bad Move / Try To Faint + +Gyarados +Level: 33 +IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe + +Sharpedo +Level: 33 +IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe + +Gyarados +Level: 33 +IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe + +Tentacruel +Level: 35 +IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe + +=== TRAINER_RONALD === +Name: 和雄 +Class: Fisherman +Pic: Fisherman +Gender: Male +Music: Hiker +Double Battle: No +AI: Check Bad Move + +Magikarp +Level: 19 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Gyarados +Level: 21 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Gyarados +Level: 23 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Gyarados +Level: 26 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Gyarados +Level: 30 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Gyarados +Level: 35 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_JACOB === +Name: 进 +Class: Triathlete +Pic: Cycling Triathlete M +Gender: Male +Music: Male +Double Battle: No +AI: Check Bad Move + +Voltorb +Level: 6 +IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe + +Voltorb +Level: 6 +IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe + +Magnemite +Level: 14 +IVs: 24 HP / 24 Atk / 24 Def / 24 SpA / 24 SpD / 24 Spe + +=== TRAINER_ANTHONY === +Name: 俊介 +Class: Triathlete +Pic: Cycling Triathlete M +Gender: Male +Music: Male +Double Battle: No +AI: Check Bad Move + +Magnemite +Level: 14 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Magnemite +Level: 14 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_BENJAMIN_1 === +Name: 英明 +Class: Triathlete +Pic: Cycling Triathlete M +Gender: Male +Music: Male +Double Battle: No +AI: Check Bad Move + +Magnemite +Level: 16 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_BENJAMIN_2 === +Name: 英明 +Class: Triathlete +Pic: Cycling Triathlete M +Gender: Male +Music: Male +Double Battle: No +AI: Check Bad Move + +Magnemite +Level: 30 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe + +=== TRAINER_BENJAMIN_3 === +Name: 英明 +Class: Triathlete +Pic: Cycling Triathlete M +Gender: Male +Music: Male +Double Battle: No +AI: Check Bad Move + +Magnemite +Level: 33 +IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe + +=== TRAINER_BENJAMIN_4 === +Name: 英明 +Class: Triathlete +Pic: Cycling Triathlete M +Gender: Male +Music: Male +Double Battle: No +AI: Check Bad Move + +Magneton +Level: 36 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe + +=== TRAINER_BENJAMIN_5 === +Name: 英明 +Class: Triathlete +Pic: Cycling Triathlete M +Gender: Male +Music: Male +Double Battle: No +AI: Check Bad Move + +Magneton +Level: 39 +IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe + +=== TRAINER_ABIGAIL_1 === +Name: 翔子 +Class: Triathlete +Pic: Cycling Triathlete F +Gender: Female +Music: Female +Double Battle: No +AI: Check Bad Move + +Magnemite +Level: 16 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_JASMINE === +Name: 秀美 +Class: Triathlete +Pic: Cycling Triathlete F +Gender: Female +Music: Female +Double Battle: No +AI: Check Bad Move + +Magnemite +Level: 14 +IVs: 9 HP / 9 Atk / 9 Def / 9 SpA / 9 SpD / 9 Spe + +Magnemite +Level: 14 +IVs: 9 HP / 9 Atk / 9 Def / 9 SpA / 9 SpD / 9 Spe + +Voltorb +Level: 6 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_ABIGAIL_2 === +Name: 翔子 +Class: Triathlete +Pic: Cycling Triathlete F +Gender: Female +Music: Female +Double Battle: No +AI: Check Bad Move + +Magnemite +Level: 28 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe + +=== TRAINER_ABIGAIL_3 === +Name: 翔子 +Class: Triathlete +Pic: Cycling Triathlete F +Gender: Female +Music: Female +Double Battle: No +AI: Check Bad Move + +Magnemite +Level: 31 +IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe + +=== TRAINER_ABIGAIL_4 === +Name: 翔子 +Class: Triathlete +Pic: Cycling Triathlete F +Gender: Female +Music: Female +Double Battle: No +AI: Check Bad Move + +Magneton +Level: 34 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe + +=== TRAINER_ABIGAIL_5 === +Name: 翔子 +Class: Triathlete +Pic: Cycling Triathlete F +Gender: Female +Music: Female +Double Battle: No +AI: Check Bad Move + +Magneton +Level: 37 +IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe + +=== TRAINER_DYLAN_1 === +Name: 阿毅 +Class: Triathlete +Pic: Running Triathlete M +Gender: Male +Music: Male +Double Battle: No +AI: Check Bad Move + +Doduo +Level: 17 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_DYLAN_2 === +Name: 阿毅 +Class: Triathlete +Pic: Running Triathlete M +Gender: Male +Music: Male +Double Battle: No +AI: Check Bad Move + +Doduo +Level: 28 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe + +=== TRAINER_DYLAN_3 === +Name: 阿毅 +Class: Triathlete +Pic: Running Triathlete M +Gender: Male +Music: Male +Double Battle: No +AI: Check Bad Move + +Doduo +Level: 31 +IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe + +=== TRAINER_DYLAN_4 === +Name: 阿毅 +Class: Triathlete +Pic: Running Triathlete M +Gender: Male +Music: Male +Double Battle: No +AI: Check Bad Move + +Dodrio +Level: 34 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe + +=== TRAINER_DYLAN_5 === +Name: 阿毅 +Class: Triathlete +Pic: Running Triathlete M +Gender: Male +Music: Male +Double Battle: No +AI: Check Bad Move + +Dodrio +Level: 37 +IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe + +=== TRAINER_MARIA_1 === +Name: 佐枝子 +Class: Triathlete +Pic: Running Triathlete F +Gender: Female +Music: Female +Double Battle: No +AI: Check Bad Move + +Doduo +Level: 17 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_MARIA_2 === +Name: 佐枝子 +Class: Triathlete +Pic: Running Triathlete F +Gender: Female +Music: Female +Double Battle: No +AI: Check Bad Move + +Doduo +Level: 28 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe + +=== TRAINER_MARIA_3 === +Name: 佐枝子 +Class: Triathlete +Pic: Running Triathlete F +Gender: Female +Music: Female +Double Battle: No +AI: Check Bad Move + +Doduo +Level: 31 +IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe + +=== TRAINER_MARIA_4 === +Name: 佐枝子 +Class: Triathlete +Pic: Running Triathlete F +Gender: Female +Music: Female +Double Battle: No +AI: Check Bad Move + +Dodrio +Level: 34 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe + +=== TRAINER_MARIA_5 === +Name: 佐枝子 +Class: Triathlete +Pic: Running Triathlete F +Gender: Female +Music: Female +Double Battle: No +AI: Check Bad Move + +Dodrio +Level: 37 +IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe + +=== TRAINER_CAMDEN === +Name: 茂治 +Class: Triathlete +Pic: Swimming Triathlete M +Gender: Male +Music: Swimmer +Double Battle: No +AI: Check Bad Move + +Staryu +Level: 33 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Staryu +Level: 33 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_DEMETRIUS === +Name: 文武 +Class: Youngster +Pic: Youngster +Gender: Male +Music: Male +Double Battle: No +AI: Check Bad Move + +Zigzagoon +Level: 25 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Electrike +Level: 25 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_ISAIAH_1 === +Name: 英辅 +Class: Triathlete +Pic: Swimming Triathlete M +Gender: Male +Music: Swimmer +Double Battle: No +AI: Check Bad Move + +Staryu +Level: 35 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_PABLO_1 === +Name: 靖宏 +Class: Triathlete +Pic: Swimming Triathlete M +Gender: Male +Music: Swimmer +Double Battle: No +AI: Check Bad Move + +Staryu +Level: 33 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Staryu +Level: 33 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_CHASE === +Name: 正吾 +Class: Triathlete +Pic: Swimming Triathlete M +Gender: Male +Music: Swimmer +Double Battle: No +AI: Check Bad Move + +Wingull +Level: 26 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Staryu +Level: 34 +IVs: 9 HP / 9 Atk / 9 Def / 9 SpA / 9 SpD / 9 Spe + +=== TRAINER_ISAIAH_2 === +Name: 英辅 +Class: Triathlete +Pic: Swimming Triathlete M +Gender: Male +Music: Swimmer +Double Battle: No +AI: Check Bad Move + +Staryu +Level: 39 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe + +=== TRAINER_ISAIAH_3 === +Name: 英辅 +Class: Triathlete +Pic: Swimming Triathlete M +Gender: Male +Music: Swimmer +Double Battle: No +AI: Check Bad Move + +Staryu +Level: 42 +IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe + +=== TRAINER_ISAIAH_4 === +Name: 英辅 +Class: Triathlete +Pic: Swimming Triathlete M +Gender: Male +Music: Swimmer +Double Battle: No +AI: Check Bad Move + +Starmie +Level: 45 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe + +=== TRAINER_ISAIAH_5 === +Name: 英辅 +Class: Triathlete +Pic: Swimming Triathlete M +Gender: Male +Music: Swimmer +Double Battle: No +AI: Check Bad Move + +Starmie +Level: 48 +IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe + +=== TRAINER_ISOBEL === +Name: 绢江 +Class: Triathlete +Pic: Swimming Triathlete F +Gender: Female +Music: Swimmer +Double Battle: No +AI: Check Bad Move + +Staryu +Level: 34 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_DONNY === +Name: 由鹤 +Class: Triathlete +Pic: Swimming Triathlete F +Gender: Female +Music: Swimmer +Double Battle: No +AI: Check Bad Move + +Wingull +Level: 26 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Staryu +Level: 34 +IVs: 19 HP / 19 Atk / 19 Def / 19 SpA / 19 SpD / 19 Spe + +=== TRAINER_TALIA === +Name: 美佳子 +Class: Triathlete +Pic: Swimming Triathlete F +Gender: Female +Music: Swimmer +Double Battle: No +AI: Check Bad Move + +Staryu +Level: 34 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_KATELYN_1 === +Name: 夏美 +Class: Triathlete +Pic: Swimming Triathlete F +Gender: Female +Music: Swimmer +Double Battle: No +AI: Check Bad Move + +Staryu +Level: 35 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_ALLISON === +Name: 千慧 +Class: Triathlete +Pic: Swimming Triathlete F +Gender: Female +Music: Swimmer +Double Battle: No +AI: Check Bad Move + +Wingull +Level: 27 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Staryu +Level: 33 +IVs: 29 HP / 29 Atk / 29 Def / 29 SpA / 29 SpD / 29 Spe + +=== TRAINER_KATELYN_2 === +Name: 夏美 +Class: Triathlete +Pic: Swimming Triathlete F +Gender: Female +Music: Swimmer +Double Battle: No +AI: Check Bad Move + +Staryu +Level: 39 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe + +=== TRAINER_KATELYN_3 === +Name: 夏美 +Class: Triathlete +Pic: Swimming Triathlete F +Gender: Female +Music: Swimmer +Double Battle: No +AI: Check Bad Move + +Staryu +Level: 42 +IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe + +=== TRAINER_KATELYN_4 === +Name: 夏美 +Class: Triathlete +Pic: Swimming Triathlete F +Gender: Female +Music: Swimmer +Double Battle: No +AI: Check Bad Move + +Starmie +Level: 45 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe + +=== TRAINER_KATELYN_5 === +Name: 夏美 +Class: Triathlete +Pic: Swimming Triathlete F +Gender: Female +Music: Swimmer +Double Battle: No +AI: Check Bad Move + +Starmie +Level: 48 +IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe + +=== TRAINER_NICOLAS_1 === +Name: 武 +Class: Dragon Tamer +Pic: Dragon Tamer +Gender: Male +Music: Intense +Double Battle: No +AI: Check Bad Move + +Altaria +Level: 37 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +Altaria +Level: 37 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +=== TRAINER_NICOLAS_2 === +Name: 武 +Class: Dragon Tamer +Pic: Dragon Tamer +Gender: Male +Music: Intense +Double Battle: No +AI: Check Bad Move + +Altaria +Level: 41 +IVs: 13 HP / 13 Atk / 13 Def / 13 SpA / 13 SpD / 13 Spe + +Altaria +Level: 41 +IVs: 13 HP / 13 Atk / 13 Def / 13 SpA / 13 SpD / 13 Spe + +=== TRAINER_NICOLAS_3 === +Name: 武 +Class: Dragon Tamer +Pic: Dragon Tamer +Gender: Male +Music: Intense +Double Battle: No +AI: Check Bad Move + +Altaria +Level: 44 +IVs: 14 HP / 14 Atk / 14 Def / 14 SpA / 14 SpD / 14 Spe + +Altaria +Level: 44 +IVs: 14 HP / 14 Atk / 14 Def / 14 SpA / 14 SpD / 14 Spe + +=== TRAINER_NICOLAS_4 === +Name: 武 +Class: Dragon Tamer +Pic: Dragon Tamer +Gender: Male +Music: Intense +Double Battle: No +AI: Check Bad Move + +Bagon +Level: 46 +IVs: 15 HP / 15 Atk / 15 Def / 15 SpA / 15 SpD / 15 Spe + +Altaria +Level: 46 +IVs: 15 HP / 15 Atk / 15 Def / 15 SpA / 15 SpD / 15 Spe + +Altaria +Level: 46 +IVs: 15 HP / 15 Atk / 15 Def / 15 SpA / 15 SpD / 15 Spe + +=== TRAINER_NICOLAS_5 === +Name: 武 +Class: Dragon Tamer +Pic: Dragon Tamer +Gender: Male +Music: Intense +Double Battle: No +AI: Check Bad Move + +Altaria +Level: 49 +IVs: 17 HP / 17 Atk / 17 Def / 17 SpA / 17 SpD / 17 Spe + +Altaria +Level: 49 +IVs: 17 HP / 17 Atk / 17 Def / 17 SpA / 17 SpD / 17 Spe + +Shelgon @ Dragon Fang +Level: 49 +IVs: 17 HP / 17 Atk / 17 Def / 17 SpA / 17 SpD / 17 Spe + +=== TRAINER_AARON === +Name: 龙马 +Class: Dragon Tamer +Pic: Dragon Tamer +Gender: Male +Music: Intense +Double Battle: No +AI: Check Bad Move + +Bagon +Level: 34 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Dragon Breath +- Headbutt +- Focus Energy +- Ember + +=== TRAINER_PERRY === +Name: 清彦 +Class: Bird Keeper +Pic: Bird Keeper +Gender: Male +Music: Cool +Double Battle: No +AI: Check Bad Move + +Wingull +Level: 26 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_HUGH === +Name: 拓海 +Class: Bird Keeper +Pic: Bird Keeper +Gender: Male +Music: Cool +Double Battle: No +AI: Check Bad Move + +Wingull +Level: 25 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Tropius +Level: 25 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_PHIL === +Name: 骏平 +Class: Bird Keeper +Pic: Bird Keeper +Gender: Male +Music: Cool +Double Battle: No +AI: Check Bad Move + +Swellow +Level: 26 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_JARED === +Name: 英治 +Class: Bird Keeper +Pic: Bird Keeper +Gender: Male +Music: Cool +Double Battle: No +AI: Check Bad Move + +Doduo +Level: 27 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +Skarmory +Level: 27 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +Tropius +Level: 27 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +=== TRAINER_HUMBERTO === +Name: 光明 +Class: Bird Keeper +Pic: Bird Keeper +Gender: Male +Music: Cool +Double Battle: No +AI: Check Bad Move + +Skarmory +Level: 30 +IVs: 30 HP / 30 Atk / 30 Def / 30 SpA / 30 SpD / 30 Spe + +=== TRAINER_PRESLEY === +Name: 直宏 +Class: Bird Keeper +Pic: Bird Keeper +Gender: Male +Music: Cool +Double Battle: No +AI: Check Bad Move + +Tropius +Level: 33 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Xatu +Level: 33 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_EDWARDO === +Name: 上田 +Class: Bird Keeper +Pic: Bird Keeper +Gender: Male +Music: Cool +Double Battle: No +AI: Check Bad Move + +Doduo +Level: 29 +IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe + +Pelipper +Level: 29 +IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe + +=== TRAINER_COLIN === +Name: 森一 +Class: Bird Keeper +Pic: Bird Keeper +Gender: Male +Music: Cool +Double Battle: No +AI: Check Bad Move + +Wingull +Level: 28 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Natu +Level: 28 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_ROBERT_1 === +Name: 阿翼 +Class: Bird Keeper +Pic: Bird Keeper +Gender: Male +Music: Cool +Double Battle: No +AI: Check Bad Move + +Swablu +Level: 29 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_BENNY === +Name: 彰正 +Class: Bird Keeper +Pic: Bird Keeper +Gender: Male +Music: Cool +Double Battle: No +AI: Check Bad Move + +Swellow +Level: 36 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Pelipper +Level: 36 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Xatu +Level: 36 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_CHESTER === +Name: 大使 +Class: Bird Keeper +Pic: Bird Keeper +Gender: Male +Music: Cool +Double Battle: No +AI: Check Bad Move + +Taillow +Level: 25 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Swellow +Level: 25 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_ROBERT_2 === +Name: 阿翼 +Class: Bird Keeper +Pic: Bird Keeper +Gender: Male +Music: Cool +Double Battle: No +AI: Check Bad Move + +Natu +Level: 32 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe + +Swablu +Level: 32 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe + +=== TRAINER_ROBERT_3 === +Name: 阿翼 +Class: Bird Keeper +Pic: Bird Keeper +Gender: Male +Music: Cool +Double Battle: No +AI: Check Bad Move + +Natu +Level: 35 +IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe + +Altaria +Level: 35 +IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe + +=== TRAINER_ROBERT_4 === +Name: 阿翼 +Class: Bird Keeper +Pic: Bird Keeper +Gender: Male +Music: Cool +Double Battle: No +AI: Check Bad Move + +Natu +Level: 38 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe + +Altaria +Level: 38 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe + +=== TRAINER_ROBERT_5 === +Name: 阿翼 +Class: Bird Keeper +Pic: Bird Keeper +Gender: Male +Music: Cool +Double Battle: No +AI: Check Bad Move + +Altaria +Level: 41 +IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe + +Xatu +Level: 41 +IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe + +=== TRAINER_ALEX === +Name: 正嗣 +Class: Bird Keeper +Pic: Bird Keeper +Gender: Male +Music: Cool +Double Battle: No +AI: Check Bad Move + +Natu +Level: 33 +IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe + +Swellow +Level: 33 +IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe + +=== TRAINER_BECK === +Name: 俊明 +Class: Bird Keeper +Pic: Bird Keeper +Gender: Male +Music: Cool +Double Battle: No +AI: Check Bad Move + +Tropius +Level: 34 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_YASU === +Name: 广宣 +Class: Ninja Boy +Pic: Ninja Boy +Gender: Male +Music: Suspicious +Double Battle: No +AI: Check Bad Move / Try To Faint + +Ninjask +Level: 26 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_TAKASHI === +Name: 四郎 +Class: Ninja Boy +Pic: Ninja Boy +Gender: Male +Music: Suspicious +Double Battle: No +AI: Check Bad Move / Try To Faint + +Ninjask +Level: 25 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Koffing +Level: 25 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_DIANNE === +Name: 心 +Class: Cooltrainer +Pic: Cooltrainer F +Gender: Female +Music: Cool +Items: Full Restore +Double Battle: No + +Claydol +Level: 43 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe +- Skill Swap +- Earthquake + +Lanturn +Level: 43 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe +- Thunderbolt +- Earthquake + +=== TRAINER_JANI === +Name: 麻美 +Class: Tuber F +Pic: Tuber F +Gender: Female +Music: Girl +Double Battle: No + +Marill +Level: 26 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_LAO_1 === +Name: 金次 +Class: Ninja Boy +Pic: Ninja Boy +Gender: Male +Music: Suspicious +Double Battle: No + +Koffing +Level: 17 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe +- Poison Gas +- Tackle +- Smog +- Self Destruct + +Koffing +Level: 17 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe +- Poison Gas +- Tackle +- Smog +- Self Destruct + +Koffing +Level: 17 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe +- Poison Gas +- Tackle +- Sludge +- Self Destruct + +=== TRAINER_LUNG === +Name: 村正 +Class: Ninja Boy +Pic: Ninja Boy +Gender: Male +Music: Suspicious +Double Battle: No + +Koffing +Level: 18 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Ninjask +Level: 18 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_LAO_2 === +Name: 金次 +Class: Ninja Boy +Pic: Ninja Boy +Gender: Male +Music: Suspicious +Double Battle: No + +Koffing +Level: 24 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe +- Poison Gas +- Tackle +- Sludge +- Self Destruct + +Koffing +Level: 24 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe +- Poison Gas +- Tackle +- Sludge + +Koffing +Level: 24 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe +- Poison Gas +- Tackle +- Sludge +- Self Destruct + +Koffing +Level: 26 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe +- Tackle +- Sludge + +=== TRAINER_LAO_3 === +Name: 金次 +Class: Ninja Boy +Pic: Ninja Boy +Gender: Male +Music: Suspicious +Double Battle: No + +Koffing +Level: 27 +IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe +- Poison Gas +- Tackle +- Sludge +- Self Destruct + +Koffing +Level: 27 +IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe +- Poison Gas +- Tackle +- Sludge +- Self Destruct + +Koffing +Level: 27 +IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe +- Poison Gas +- Tackle +- Sludge + +Koffing +Level: 29 +IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe +- Tackle +- Sludge + +=== TRAINER_LAO_4 === +Name: 金次 +Class: Ninja Boy +Pic: Ninja Boy +Gender: Male +Music: Suspicious +Double Battle: No + +Koffing +Level: 30 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe +- Poison Gas +- Tackle +- Sludge + +Koffing +Level: 30 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe +- Poison Gas +- Tackle +- Sludge + +Koffing +Level: 30 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe +- Poison Gas +- Tackle +- Sludge + +Koffing +Level: 32 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe +- Tackle +- Sludge + +=== TRAINER_LAO_5 === +Name: 金次 +Class: Ninja Boy +Pic: Ninja Boy +Gender: Male +Music: Suspicious +Double Battle: No + +Koffing +Level: 33 +IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe +- Poison Gas +- Tackle +- Sludge + +Koffing +Level: 33 +IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe +- Poison Gas +- Tackle +- Sludge +- Self Destruct + +Koffing +Level: 33 +IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe +- Poison Gas +- Tackle +- Sludge +- Self Destruct + +Weezing @ Smoke Ball +Level: 35 +IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe +- Tackle +- Sludge + +=== TRAINER_JOCELYN === +Name: 小忍 +Class: Battle Girl +Pic: Battle Girl +Gender: Female +Music: Intense +Double Battle: No +AI: Check Bad Move + +Meditite +Level: 13 +IVs: 15 HP / 15 Atk / 15 Def / 15 SpA / 15 SpD / 15 Spe + +=== TRAINER_LAURA === +Name: 美里 +Class: Battle Girl +Pic: Battle Girl +Gender: Female +Music: Intense +Double Battle: No +AI: Check Bad Move + +Meditite +Level: 13 +IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe + +=== TRAINER_CYNDY_1 === +Name: 由梨香 +Class: Battle Girl +Pic: Battle Girl +Gender: Female +Music: Intense +Double Battle: No +AI: Check Bad Move + +Meditite +Level: 18 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +Makuhita +Level: 18 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +=== TRAINER_CORA === +Name: 风华 +Class: Battle Girl +Pic: Battle Girl +Gender: Female +Music: Intense +Double Battle: No +AI: Check Bad Move + +Meditite +Level: 27 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +=== TRAINER_PAULA === +Name: 雏 +Class: Battle Girl +Pic: Battle Girl +Gender: Female +Music: Intense +Double Battle: No +AI: Check Bad Move + +Breloom +Level: 27 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +=== TRAINER_CYNDY_2 === +Name: 由梨香 +Class: Battle Girl +Pic: Battle Girl +Gender: Female +Music: Intense +Double Battle: No +AI: Check Bad Move + +Meditite +Level: 26 +IVs: 13 HP / 13 Atk / 13 Def / 13 SpA / 13 SpD / 13 Spe + +Makuhita +Level: 26 +IVs: 13 HP / 13 Atk / 13 Def / 13 SpA / 13 SpD / 13 Spe + +=== TRAINER_CYNDY_3 === +Name: 由梨香 +Class: Battle Girl +Pic: Battle Girl +Gender: Female +Music: Intense +Double Battle: No +AI: Check Bad Move + +Meditite +Level: 29 +IVs: 14 HP / 14 Atk / 14 Def / 14 SpA / 14 SpD / 14 Spe + +Makuhita +Level: 29 +IVs: 14 HP / 14 Atk / 14 Def / 14 SpA / 14 SpD / 14 Spe + +=== TRAINER_CYNDY_4 === +Name: 由梨香 +Class: Battle Girl +Pic: Battle Girl +Gender: Female +Music: Intense +Double Battle: No +AI: Check Bad Move + +Medicham +Level: 32 +IVs: 15 HP / 15 Atk / 15 Def / 15 SpA / 15 SpD / 15 Spe + +Hariyama +Level: 32 +IVs: 15 HP / 15 Atk / 15 Def / 15 SpA / 15 SpD / 15 Spe + +=== TRAINER_CYNDY_5 === +Name: 由梨香 +Class: Battle Girl +Pic: Battle Girl +Gender: Female +Music: Intense +Double Battle: No +AI: Check Bad Move + +Medicham +Level: 35 +IVs: 17 HP / 17 Atk / 17 Def / 17 SpA / 17 SpD / 17 Spe + +Hariyama +Level: 35 +IVs: 17 HP / 17 Atk / 17 Def / 17 SpA / 17 SpD / 17 Spe + +=== TRAINER_MADELINE_1 === +Name: 圆香 +Class: Parasol Lady +Pic: Parasol Lady +Gender: Female +Music: Female +Double Battle: No +AI: Check Bad Move + +Numel +Level: 19 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe +- Ember +- Tackle +- Magnitude +- Sunny Day + +=== TRAINER_CLARISSA === +Name: 美华 +Class: Parasol Lady +Pic: Parasol Lady +Gender: Female +Music: Female +Double Battle: No +AI: Check Bad Move + +Roselia +Level: 28 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Wailmer +Level: 28 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_ANGELICA === +Name: 浮江 +Class: Parasol Lady +Pic: Parasol Lady +Gender: Female +Music: Female +Double Battle: No +AI: Check Bad Move + +Castform +Level: 30 +IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe +- Rain Dance +- Weather Ball +- Thunder +- Water Pulse + +=== TRAINER_MADELINE_2 === +Name: 圆香 +Class: Parasol Lady +Pic: Parasol Lady +Gender: Female +Music: Female +Double Battle: No +AI: Check Bad Move + +Numel +Level: 29 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe +- Ember +- Tackle +- Magnitude +- Sunny Day + +=== TRAINER_MADELINE_3 === +Name: 圆香 +Class: Parasol Lady +Pic: Parasol Lady +Gender: Female +Music: Female +Double Battle: No +AI: Check Bad Move + +Numel +Level: 32 +IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe +- Ember +- Take Down +- Magnitude +- Sunny Day + +=== TRAINER_MADELINE_4 === +Name: 圆香 +Class: Parasol Lady +Pic: Parasol Lady +Gender: Female +Music: Female +Double Battle: No +AI: Check Bad Move + +Roselia +Level: 34 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe +- Leech Seed +- Mega Drain +- Grass Whistle +- Sunny Day + +Numel +Level: 34 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe +- Flamethrower +- Take Down +- Magnitude +- Sunny Day + +=== TRAINER_MADELINE_5 === +Name: 圆香 +Class: Parasol Lady +Pic: Parasol Lady +Gender: Female +Music: Female +Double Battle: No +AI: Check Bad Move + +Roselia +Level: 37 +IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe +- Leech Seed +- Giga Drain +- Solar Beam +- Sunny Day + +Camerupt +Level: 37 +IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe +- Flamethrower +- Take Down +- Earthquake +- Sunny Day + +=== TRAINER_BEVERLY === +Name: 夏树 +Class: Swimmer F +Pic: Swimmer F +Gender: Female +Music: Swimmer +Double Battle: No +AI: Check Bad Move + +Wingull +Level: 25 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Wailmer +Level: 25 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_IMANI === +Name: 真由佳 +Class: Swimmer F +Pic: Swimmer F +Gender: Female +Music: Swimmer +Double Battle: No +AI: Check Bad Move + +Marill +Level: 26 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_KYLA === +Name: 水羽 +Class: Swimmer F +Pic: Swimmer F +Gender: Female +Music: Swimmer +Double Battle: No +AI: Check Bad Move + +Wailmer +Level: 26 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_DENISE === +Name: 雅美 +Class: Swimmer F +Pic: Swimmer F +Gender: Female +Music: Swimmer +Double Battle: No +AI: Check Bad Move + +Wingull +Level: 25 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Goldeen +Level: 25 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_BETH === +Name: 纪香 +Class: Swimmer F +Pic: Swimmer F +Gender: Female +Music: Swimmer +Double Battle: No +AI: Check Bad Move + +Goldeen +Level: 26 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_TARA === +Name: 千寻 +Class: Swimmer F +Pic: Swimmer F +Gender: Female +Music: Swimmer +Double Battle: No +AI: Check Bad Move + +Horsea +Level: 25 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Marill +Level: 25 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_MISSY === +Name: 久美子 +Class: Swimmer F +Pic: Swimmer F +Gender: Female +Music: Swimmer +Double Battle: No +AI: Check Bad Move + +Goldeen +Level: 26 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_ALICE === +Name: 悦子 +Class: Swimmer F +Pic: Swimmer F +Gender: Female +Music: Swimmer +Double Battle: No +AI: Check Bad Move + +Goldeen +Level: 24 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Wingull +Level: 24 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Goldeen +Level: 24 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_JENNY_1 === +Name: 小渚 +Class: Swimmer F +Pic: Swimmer F +Gender: Female +Music: Swimmer +Double Battle: No +AI: Check Bad Move + +Wailmer +Level: 34 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_GRACE === +Name: 秋江 +Class: Swimmer F +Pic: Swimmer F +Gender: Female +Music: Swimmer +Double Battle: No +AI: Check Bad Move + +Marill +Level: 34 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_TANYA === +Name: 惠子 +Class: Swimmer F +Pic: Swimmer F +Gender: Female +Music: Swimmer +Double Battle: No +AI: Check Bad Move + +Luvdisc +Level: 34 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_SHARON === +Name: 彩华 +Class: Swimmer F +Pic: Swimmer F +Gender: Female +Music: Swimmer +Double Battle: No +AI: Check Bad Move + +Seaking +Level: 34 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_NIKKI === +Name: 静江 +Class: Swimmer F +Pic: Swimmer F +Gender: Female +Music: Swimmer +Double Battle: No +AI: Check Bad Move + +Marill +Level: 33 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Spheal +Level: 33 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_BRENDA === +Name: 辉美 +Class: Swimmer F +Pic: Swimmer F +Gender: Female +Music: Swimmer +Double Battle: No +AI: Check Bad Move + +Goldeen +Level: 34 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_KATIE === +Name: 富美江 +Class: Swimmer F +Pic: Swimmer F +Gender: Female +Music: Swimmer +Double Battle: No +AI: Check Bad Move + +Goldeen +Level: 33 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Spheal +Level: 33 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_SUSIE === +Name: 美咲 +Class: Swimmer F +Pic: Swimmer F +Gender: Female +Music: Swimmer +Double Battle: No +AI: Check Bad Move + +Luvdisc +Level: 34 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_KARA === +Name: 鞠绘 +Class: Swimmer F +Pic: Swimmer F +Gender: Female +Music: Swimmer +Double Battle: No +AI: Check Bad Move + +Seaking +Level: 34 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_DANA === +Name: 美雪 +Class: Swimmer F +Pic: Swimmer F +Gender: Female +Music: Swimmer +Double Battle: No +AI: Check Bad Move + +Azumarill +Level: 34 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_SIENNA === +Name: 郁子 +Class: Swimmer F +Pic: Swimmer F +Gender: Female +Music: Swimmer +Double Battle: No +AI: Check Bad Move + +Luvdisc +Level: 33 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Luvdisc +Level: 33 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_DEBRA === +Name: 里佳子 +Class: Swimmer F +Pic: Swimmer F +Gender: Female +Music: Swimmer +Double Battle: No +AI: Check Bad Move + +Seaking +Level: 34 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_LINDA === +Name: 春美 +Class: Swimmer F +Pic: Swimmer F +Gender: Female +Music: Swimmer +Double Battle: No +AI: Check Bad Move + +Horsea +Level: 33 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Seadra +Level: 33 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_KAYLEE === +Name: 多可 +Class: Swimmer F +Pic: Swimmer F +Gender: Female +Music: Swimmer +Double Battle: No +AI: Check Bad Move + +Lanturn +Level: 34 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Pelipper +Level: 34 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_LAUREL === +Name: 园子 +Class: Swimmer F +Pic: Swimmer F +Gender: Female +Music: Swimmer +Double Battle: No +AI: Check Bad Move + +Luvdisc +Level: 33 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Luvdisc +Level: 33 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_CARLEE === +Name: 国子 +Class: Swimmer F +Pic: Swimmer F +Gender: Female +Music: Swimmer +Double Battle: No +AI: Check Bad Move + +Seaking +Level: 35 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_JENNY_2 === +Name: 小渚 +Class: Swimmer F +Pic: Swimmer F +Gender: Female +Music: Swimmer +Double Battle: No +AI: Check Bad Move + +Wailmer +Level: 38 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_JENNY_3 === +Name: 小渚 +Class: Swimmer F +Pic: Swimmer F +Gender: Female +Music: Swimmer +Double Battle: No +AI: Check Bad Move + +Wailmer +Level: 41 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_JENNY_4 === +Name: 小渚 +Class: Swimmer F +Pic: Swimmer F +Gender: Female +Music: Swimmer +Double Battle: No +AI: Check Bad Move + +Staryu +Level: 43 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Wailmer +Level: 43 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_JENNY_5 === +Name: 小渚 +Class: Swimmer F +Pic: Swimmer F +Gender: Female +Music: Swimmer +Double Battle: No +AI: Check Bad Move + +Luvdisc +Level: 45 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Wailmer +Level: 45 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Starmie +Level: 45 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_HEIDI === +Name: 千佳子 +Class: Picnicker +Pic: Picnicker +Gender: Female +Music: Girl +Double Battle: No +AI: Check Bad Move + +Sandshrew +Level: 22 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe +- Dig +- Sand Attack +- Poison Sting +- Slash + +Baltoy +Level: 22 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe +- Rapid Spin +- Mud Slap +- Psybeam +- Rock Tomb + +=== TRAINER_BECKY === +Name: 爱弥 +Class: Picnicker +Pic: Picnicker +Gender: Female +Music: Girl +Double Battle: No +AI: Check Bad Move + +Sandshrew +Level: 22 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe +- Sand Attack +- Poison Sting +- Slash +- Dig + +Marill +Level: 22 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe +- Rollout +- Bubble Beam +- Tail Whip +- Defense Curl + +=== TRAINER_CAROL === +Name: 裕子 +Class: Picnicker +Pic: Picnicker +Gender: Female +Music: Girl +Double Battle: No +AI: Check Bad Move + +Taillow +Level: 17 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Lombre +Level: 17 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_NANCY === +Name: 皋月 +Class: Picnicker +Pic: Picnicker +Gender: Female +Music: Girl +Double Battle: No +AI: Check Bad Move + +Marill +Level: 18 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Lombre +Level: 18 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_MARTHA === +Name: 朋子 +Class: Picnicker +Pic: Picnicker +Gender: Female +Music: Girl +Double Battle: No +AI: Check Bad Move + +Skitty +Level: 23 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Swablu +Level: 23 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_DIANA_1 === +Name: 梢 +Class: Picnicker +Pic: Picnicker +Gender: Female +Music: Girl +Double Battle: No +AI: Check Bad Move + +Shroomish +Level: 19 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Oddish +Level: 19 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Swablu +Level: 19 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_CEDRIC === +Name: 义清 +Class: Psychic +Pic: Psychic M +Gender: Male +Music: Intense +Double Battle: No +AI: Check Bad Move + +Wobbuffet +Level: 32 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe +- Destiny Bond +- Safeguard +- Counter +- Mirror Coat + +=== TRAINER_IRENE === +Name: 水木 +Class: Picnicker +Pic: Picnicker +Gender: Female +Music: Girl +Double Battle: No +AI: Check Bad Move + +Shroomish +Level: 17 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Marill +Level: 17 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_DIANA_2 === +Name: 梢 +Class: Picnicker +Pic: Picnicker +Gender: Female +Music: Girl +Double Battle: No +AI: Check Bad Move + +Shroomish +Level: 25 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe + +Gloom +Level: 25 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe + +Swablu +Level: 25 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe + +=== TRAINER_DIANA_3 === +Name: 梢 +Class: Picnicker +Pic: Picnicker +Gender: Female +Music: Girl +Double Battle: No +AI: Check Bad Move + +Breloom +Level: 28 +IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe + +Gloom +Level: 28 +IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe + +Swablu +Level: 28 +IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe + +=== TRAINER_DIANA_4 === +Name: 梢 +Class: Picnicker +Pic: Picnicker +Gender: Female +Music: Girl +Double Battle: No +AI: Check Bad Move + +Breloom +Level: 31 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe + +Gloom +Level: 31 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe + +Swablu +Level: 31 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe + +=== TRAINER_DIANA_5 === +Name: 梢 +Class: Picnicker +Pic: Picnicker +Gender: Female +Music: Girl +Double Battle: No +AI: Check Bad Move + +Breloom +Level: 40 +IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe + +Vileplume +Level: 40 +IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe + +Altaria +Level: 40 +IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe + +=== TRAINER_AMY_AND_LIV_1 === +Name: 久美和留美 +Class: Twins +Pic: Twins +Gender: Male +Music: Twins +Double Battle: Yes +AI: Check Bad Move + +Plusle +Level: 15 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Minun +Level: 15 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_AMY_AND_LIV_2 === +Name: 久美和留美 +Class: Twins +Pic: Twins +Gender: Male +Music: Twins +Double Battle: Yes +AI: Check Bad Move + +Plusle +Level: 27 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe + +Minun +Level: 27 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe + +=== TRAINER_GINA_AND_MIA_1 === +Name: 奈绪和美绪 +Class: Twins +Pic: Twins +Gender: Male +Music: Twins +Double Battle: Yes +AI: Check Bad Move + +Seedot +Level: 6 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Lotad +Level: 6 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_MIU_AND_YUKI === +Name: 美雨和雪 +Class: Twins +Pic: Twins +Gender: Male +Music: Twins +Double Battle: Yes +AI: Check Bad Move + +Beautifly +Level: 26 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Dustox +Level: 26 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_AMY_AND_LIV_3 === +Name: 久美和留美 +Class: Twins +Pic: Twins +Gender: Male +Music: Twins +Double Battle: Yes +AI: Check Bad Move + +Plusle +Level: 9 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Minun +Level: 9 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_GINA_AND_MIA_2 === +Name: 奈绪和美绪 +Class: Twins +Pic: Twins +Gender: Male +Music: Twins +Double Battle: Yes +AI: Check Bad Move + +Duskull +Level: 10 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe +- Night Shade +- Disable + +Shroomish +Level: 10 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe +- Absorb +- Leech Seed + +=== TRAINER_AMY_AND_LIV_4 === +Name: 久美和留美 +Class: Twins +Pic: Twins +Gender: Male +Music: Twins +Double Battle: Yes +AI: Check Bad Move + +Plusle +Level: 30 +IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe + +Minun +Level: 30 +IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe + +=== TRAINER_AMY_AND_LIV_5 === +Name: 久美和留美 +Class: Twins +Pic: Twins +Gender: Male +Music: Twins +Double Battle: Yes +AI: Check Bad Move + +Plusle +Level: 33 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe +- Spark +- Charge +- Fake Tears +- Helping Hand + +Minun +Level: 33 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe +- Spark +- Charge +- Charm +- Helping Hand + +=== TRAINER_AMY_AND_LIV_6 === +Name: 久美和留美 +Class: Twins +Pic: Twins +Gender: Male +Music: Twins +Double Battle: Yes +AI: Check Bad Move + +Plusle +Level: 36 +IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe +- Thunder +- Charge +- Fake Tears +- Helping Hand + +Minun +Level: 36 +IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe +- Thunder +- Charge +- Charm +- Helping Hand + +=== TRAINER_HUEY === +Name: 达郎 +Class: Sailor +Pic: Sailor +Gender: Male +Music: Male +Double Battle: No +AI: Check Bad Move + +Wingull +Level: 12 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe + +Machop +Level: 12 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe + +=== TRAINER_EDMOND === +Name: 克哉 +Class: Sailor +Pic: Sailor +Gender: Male +Music: Male +Double Battle: No +AI: Check Bad Move + +Wingull +Level: 13 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_ERNEST_1 === +Name: 次郎 +Class: Sailor +Pic: Sailor +Gender: Male +Music: Male +Double Battle: No +AI: Check Bad Move + +Wingull +Level: 33 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Machoke +Level: 33 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_DWAYNE === +Name: 龙彦 +Class: Sailor +Pic: Sailor +Gender: Male +Music: Male +Double Battle: No +AI: Check Bad Move + +Wingull +Level: 11 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Machop +Level: 11 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Tentacool +Level: 11 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_PHILLIP === +Name: 勇作 +Class: Sailor +Pic: Sailor +Gender: Male +Music: Male +Double Battle: No +AI: Check Bad Move + +Tentacruel +Level: 44 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Machoke +Level: 44 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_LEONARD === +Name: 大树 +Class: Sailor +Pic: Sailor +Gender: Male +Music: Male +Double Battle: No +AI: Check Bad Move + +Machop +Level: 43 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Pelipper +Level: 43 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Machoke +Level: 43 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_DUNCAN === +Name: 豪史 +Class: Sailor +Pic: Sailor +Gender: Male +Music: Male +Double Battle: No +AI: Check Bad Move + +Spheal +Level: 25 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Machoke +Level: 25 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_ERNEST_2 === +Name: 次郎 +Class: Sailor +Pic: Sailor +Gender: Male +Music: Male +Double Battle: No +AI: Check Bad Move + +Wingull +Level: 36 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe + +Tentacool +Level: 36 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe + +Machoke +Level: 36 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe + +=== TRAINER_ERNEST_3 === +Name: 次郎 +Class: Sailor +Pic: Sailor +Gender: Male +Music: Male +Double Battle: No +AI: Check Bad Move + +Pelipper +Level: 39 +IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe + +Tentacool +Level: 39 +IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe + +Machoke +Level: 39 +IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe + +=== TRAINER_ERNEST_4 === +Name: 次郎 +Class: Sailor +Pic: Sailor +Gender: Male +Music: Male +Double Battle: No +AI: Check Bad Move + +Pelipper +Level: 42 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe + +Tentacool +Level: 42 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe + +Machoke +Level: 42 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe + +=== TRAINER_ERNEST_5 === +Name: 次郎 +Class: Sailor +Pic: Sailor +Gender: Male +Music: Male +Double Battle: No +AI: Check Bad Move + +Pelipper +Level: 45 +IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe + +Machoke +Level: 45 +IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe + +Tentacruel +Level: 45 +IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe + +=== TRAINER_ELI === +Name: 辉义 +Class: Hiker +Pic: Hiker +Gender: Male +Music: Hiker +Double Battle: No +AI: Check Bad Move + +Numel +Level: 23 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +=== TRAINER_ANNIKA === +Name: 峰子 +Class: Pokefan +Pic: Pokefan F +Gender: Female +Music: Twins +Double Battle: No +AI: Check Bad Move + +Feebas @ Oran Berry +Level: 39 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe +- Flail +- Water Pulse +- Return +- Attract + +Feebas @ Oran Berry +Level: 39 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe +- Flail +- Water Pulse +- Return +- Attract + +=== TRAINER_JAZMYN === +Name: 美羽 +Class: Cooltrainer 2 +Pic: Cooltrainer F +Gender: Female +Music: Cool +Items: Hyper Potion +Double Battle: No +AI: Basic Trainer + +Absol +Level: 27 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_JONAS === +Name: 伸介 +Class: Ninja Boy +Pic: Ninja Boy +Gender: Male +Music: Suspicious +Double Battle: No +AI: Basic Trainer + +Koffing +Level: 31 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe +- Toxic +- Thunder +- Self Destruct +- Sludge Bomb + +=== TRAINER_KAYLEY === +Name: 薰子 +Class: Parasol Lady +Pic: Parasol Lady +Gender: Female +Music: Female +Double Battle: No +AI: Check Bad Move + +Castform +Level: 31 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe +- Sunny Day +- Weather Ball +- Flamethrower +- Solar Beam + +=== TRAINER_AURON === +Name: 一圭 +Class: Expert +Pic: Expert M +Gender: Male +Music: Intense +Double Battle: No +AI: Check Bad Move + +Manectric +Level: 33 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Machamp +Level: 33 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_KELVIN === +Name: 直也 +Class: Sailor +Pic: Sailor +Gender: Male +Music: Male +Double Battle: No +AI: Check Bad Move + +Machoke +Level: 33 +IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe + +Spheal +Level: 33 +IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe + +=== TRAINER_MARLEY === +Name: 律子 +Class: Cooltrainer +Pic: Cooltrainer F +Gender: Female +Music: Cool +Items: Hyper Potion +Double Battle: No +AI: Basic Trainer + +Manectric +Level: 34 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Bite +- Roar +- Thunder Wave +- Thunderbolt + +=== TRAINER_REYNA === +Name: 珠希 +Class: Battle Girl +Pic: Battle Girl +Gender: Female +Music: Intense +Double Battle: No +AI: Check Bad Move + +Meditite +Level: 33 +IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe + +Hariyama +Level: 33 +IVs: 24 HP / 24 Atk / 24 Def / 24 SpA / 24 SpD / 24 Spe + +=== TRAINER_HUDSON === +Name: 纯也 +Class: Sailor +Pic: Sailor +Gender: Male +Music: Male +Double Battle: No +AI: Check Bad Move + +Wailmer +Level: 34 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_CONOR === +Name: 茂良 +Class: Expert +Pic: Expert M +Gender: Male +Music: Intense +Double Battle: No +AI: Check Bad Move + +Chinchou +Level: 33 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Hariyama +Level: 33 +IVs: 24 HP / 24 Atk / 24 Def / 24 SpA / 24 SpD / 24 Spe + +=== TRAINER_EDWIN_1 === +Name: 元树 +Class: Collector +Pic: Collector +Gender: Male +Music: Suspicious +Double Battle: No +AI: Check Bad Move + +Lombre +Level: 14 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Nuzleaf +Level: 14 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_HECTOR === +Name: 俊宣 +Class: Collector +Pic: Collector +Gender: Male +Music: Suspicious +Double Battle: No +AI: Check Bad Move + +Zangoose +Level: 18 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Seviper +Level: 18 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_TABITHA_MOSSDEEP === +Name: 火村 +Class: Magma Admin +Pic: Magma Admin +Gender: Male +Music: Magma +Double Battle: No +AI: Check Bad Move + +Camerupt +Level: 36 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +Mightyena +Level: 38 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +Golbat +Level: 40 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +=== TRAINER_EDWIN_2 === +Name: 元树 +Class: Collector +Pic: Collector +Gender: Male +Music: Suspicious +Double Battle: No +AI: Check Bad Move + +Lombre +Level: 26 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Nuzleaf +Level: 26 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_EDWIN_3 === +Name: 元树 +Class: Collector +Pic: Collector +Gender: Male +Music: Suspicious +Double Battle: No +AI: Check Bad Move + +Lombre +Level: 29 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Nuzleaf +Level: 29 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_EDWIN_4 === +Name: 元树 +Class: Collector +Pic: Collector +Gender: Male +Music: Suspicious +Double Battle: No +AI: Check Bad Move + +Lombre +Level: 32 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Nuzleaf +Level: 32 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_EDWIN_5 === +Name: 元树 +Class: Collector +Pic: Collector +Gender: Male +Music: Suspicious +Double Battle: No +AI: Check Bad Move + +Ludicolo +Level: 35 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Shiftry +Level: 35 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_WALLY_VR_1 === +Name: 满充 +Class: Rival +Pic: Wally +Gender: Male +Music: Male +Items: Full Restore / Full Restore +Double Battle: No +AI: Basic Trainer + +Altaria +Level: 44 +IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe +- Aerial Ace +- Safeguard +- Dragon Breath +- Dragon Dance + +Delcatty +Level: 43 +IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe +- Sing +- Assist +- Charm +- Feint Attack + +Roselia +Level: 44 +IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe +- Magical Leaf +- Leech Seed +- Giga Drain +- Toxic + +Magneton +Level: 41 +IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe +- Supersonic +- Thunderbolt +- Tri Attack +- Screech + +Gardevoir +Level: 45 +IVs: 30 HP / 30 Atk / 30 Def / 30 SpA / 30 SpD / 30 Spe +- Double Team +- Calm Mind +- Psychic +- Future Sight + +=== TRAINER_BRENDAN_ROUTE_103_MUDKIP === +Name: 小悠 +Class: Rival +Pic: Brendan +Gender: Male +Music: Male +Double Battle: No +AI: Basic Trainer + +Treecko +Level: 5 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_BRENDAN_ROUTE_110_MUDKIP === +Name: 小悠 +Class: Rival +Pic: Brendan +Gender: Male +Music: Male +Double Battle: No +AI: Basic Trainer + +Slugma +Level: 18 +IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe + +Wingull +Level: 18 +IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe + +Grovyle +Level: 20 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +=== TRAINER_BRENDAN_ROUTE_119_MUDKIP === +Name: 小悠 +Class: Rival +Pic: Brendan +Gender: Male +Music: Male +Double Battle: No +AI: Basic Trainer + +Slugma +Level: 29 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +Pelipper +Level: 29 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +Grovyle +Level: 31 +IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe + +=== TRAINER_BRENDAN_ROUTE_103_TREECKO === +Name: 小悠 +Class: Rival +Pic: Brendan +Gender: Male +Music: Male +Double Battle: No +AI: Check Bad Move / Try To Faint / Force Setup First Turn + +Torchic +Level: 5 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_BRENDAN_ROUTE_110_TREECKO === +Name: 小悠 +Class: Rival +Pic: Brendan +Gender: Male +Music: Male +Double Battle: No +AI: Basic Trainer + +Wingull +Level: 18 +IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe + +Lombre +Level: 18 +IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe + +Combusken +Level: 20 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +=== TRAINER_BRENDAN_ROUTE_119_TREECKO === +Name: 小悠 +Class: Rival +Pic: Brendan +Gender: Male +Music: Male +Double Battle: No +AI: Basic Trainer + +Pelipper +Level: 29 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +Lombre +Level: 29 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +Combusken +Level: 31 +IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe + +=== TRAINER_BRENDAN_ROUTE_103_TORCHIC === +Name: 小悠 +Class: Rival +Pic: Brendan +Gender: Male +Music: Male +Double Battle: No +AI: Basic Trainer + +Mudkip +Level: 5 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_BRENDAN_ROUTE_110_TORCHIC === +Name: 小悠 +Class: Rival +Pic: Brendan +Gender: Male +Music: Male +Double Battle: No +AI: Basic Trainer + +Lombre +Level: 18 +IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe + +Slugma +Level: 18 +IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe + +Marshtomp +Level: 20 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +=== TRAINER_BRENDAN_ROUTE_119_TORCHIC === +Name: 小悠 +Class: Rival +Pic: Brendan +Gender: Male +Music: Male +Double Battle: No +AI: Basic Trainer + +Lombre +Level: 29 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +Slugma +Level: 29 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +Marshtomp +Level: 31 +IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe + +=== TRAINER_MAY_ROUTE_103_MUDKIP === +Name: 小遥 +Class: Rival +Pic: May +Gender: Female +Music: Female +Double Battle: No +AI: Basic Trainer + +Treecko +Level: 5 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_MAY_ROUTE_110_MUDKIP === +Name: 小遥 +Class: Rival +Pic: May +Gender: Female +Music: Female +Double Battle: No +AI: Basic Trainer + +Wingull +Level: 18 +IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe + +Slugma +Level: 18 +IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe + +Grovyle +Level: 20 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +=== TRAINER_MAY_ROUTE_119_MUDKIP === +Name: 小遥 +Class: Rival +Pic: May +Gender: Female +Music: Female +Double Battle: No +AI: Basic Trainer + +Slugma +Level: 29 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +Lombre +Level: 29 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +Grovyle +Level: 31 +IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe + +=== TRAINER_MAY_ROUTE_103_TREECKO === +Name: 小遥 +Class: Rival +Pic: May +Gender: Female +Music: Female +Double Battle: No +AI: Basic Trainer + +Torchic +Level: 5 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_MAY_ROUTE_110_TREECKO === +Name: 小遥 +Class: Rival +Pic: May +Gender: Female +Music: Female +Double Battle: No +AI: Basic Trainer + +Wingull +Level: 18 +IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe + +Lombre +Level: 18 +IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe + +Combusken +Level: 20 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +=== TRAINER_MAY_ROUTE_119_TREECKO === +Name: 小遥 +Class: Rival +Pic: May +Gender: Female +Music: Female +Double Battle: No +AI: Basic Trainer + +Pelipper +Level: 29 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +Lombre +Level: 29 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +Combusken +Level: 31 +IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe + +=== TRAINER_MAY_ROUTE_103_TORCHIC === +Name: 小遥 +Class: Rival +Pic: May +Gender: Female +Music: Female +Double Battle: No +AI: Basic Trainer + +Mudkip +Level: 5 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_MAY_ROUTE_110_TORCHIC === +Name: 小遥 +Class: Rival +Pic: May +Gender: Female +Music: Female +Double Battle: No +AI: Basic Trainer + +Lombre +Level: 18 +IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe + +Slugma +Level: 18 +IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe + +Marshtomp +Level: 20 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +=== TRAINER_MAY_ROUTE_119_TORCHIC === +Name: 小遥 +Class: Rival +Pic: May +Gender: Female +Music: Female +Double Battle: No +AI: Basic Trainer + +Lombre +Level: 29 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +Slugma +Level: 29 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +Marshtomp +Level: 31 +IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe + +=== TRAINER_ISAAC_1 === +Name: 诚儿 +Class: Pkmn Breeder +Pic: Pokemon Breeder M +Gender: Male +Music: Male +Double Battle: No +AI: Check Bad Move + +Whismur +Level: 11 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Zigzagoon +Level: 11 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Aron +Level: 11 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Poochyena +Level: 11 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Taillow +Level: 11 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Makuhita +Level: 11 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_DAVIS === +Name: 喜朗 +Class: Bug Catcher +Pic: Bug Catcher +Gender: Male +Music: Male +Double Battle: No +AI: Check Bad Move + +Pinsir +Level: 27 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_MITCHELL === +Name: 铁平 +Class: Cooltrainer +Pic: Cooltrainer M +Gender: Male +Music: Cool +Double Battle: No +AI: Basic Trainer + +Lunatone +Level: 43 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe +- Explosion +- Reflect +- Light Screen +- Psychic + +Solrock +Level: 43 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe +- Explosion +- Reflect +- Light Screen +- Shadow Ball + +=== TRAINER_ISAAC_2 === +Name: 诚儿 +Class: Pkmn Breeder +Pic: Pokemon Breeder M +Gender: Male +Music: Male +Double Battle: No +AI: Check Bad Move + +Loudred +Level: 22 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe + +Linoone +Level: 22 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe + +Aron +Level: 22 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe + +Mightyena +Level: 22 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe + +Swellow +Level: 22 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe + +Makuhita +Level: 22 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe + +=== TRAINER_ISAAC_3 === +Name: 诚儿 +Class: Pkmn Breeder +Pic: Pokemon Breeder M +Gender: Male +Music: Male +Double Battle: No +AI: Check Bad Move + +Loudred +Level: 25 +IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe + +Linoone +Level: 25 +IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe + +Aron +Level: 25 +IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe + +Mightyena +Level: 25 +IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe + +Swellow +Level: 25 +IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe + +Hariyama +Level: 25 +IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe + +=== TRAINER_ISAAC_4 === +Name: 诚儿 +Class: Pkmn Breeder +Pic: Pokemon Breeder M +Gender: Male +Music: Male +Double Battle: No +AI: Check Bad Move + +Loudred +Level: 28 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe + +Linoone +Level: 28 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe + +Aron +Level: 28 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe + +Mightyena +Level: 28 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe + +Swellow +Level: 28 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe + +Hariyama +Level: 28 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe + +=== TRAINER_ISAAC_5 === +Name: 诚儿 +Class: Pkmn Breeder +Pic: Pokemon Breeder M +Gender: Male +Music: Male +Double Battle: No +AI: Check Bad Move + +Loudred +Level: 31 +IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe + +Linoone +Level: 31 +IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe + +Lairon +Level: 31 +IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe + +Mightyena +Level: 31 +IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe + +Swellow +Level: 31 +IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe + +Hariyama +Level: 31 +IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe + +=== TRAINER_LYDIA_1 === +Name: 郁惠 +Class: Pkmn Breeder +Pic: Pokemon Breeder F +Gender: Female +Music: Female +Double Battle: No +AI: Check Bad Move + +Wingull +Level: 11 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Shroomish +Level: 11 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Marill +Level: 11 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Roselia +Level: 11 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Skitty +Level: 11 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Goldeen +Level: 11 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_HALLE === +Name: 广惠 +Class: Cooltrainer +Pic: Cooltrainer F +Gender: Female +Music: Cool +Items: Full Restore +Double Battle: No +AI: Basic Trainer + +Sableye +Level: 43 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Absol +Level: 43 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_GARRISON === +Name: 恒安 +Class: Ruin Maniac +Pic: Ruin Maniac +Gender: Male +Music: Hiker +Double Battle: No +AI: Check Bad Move + +Sandslash +Level: 26 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_LYDIA_2 === +Name: 郁惠 +Class: Pkmn Breeder +Pic: Pokemon Breeder F +Gender: Female +Music: Female +Double Battle: No +AI: Check Bad Move + +Wingull +Level: 22 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe + +Shroomish +Level: 22 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe + +Marill +Level: 22 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe + +Roselia +Level: 22 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe + +Skitty +Level: 22 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe + +Goldeen +Level: 22 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe + +=== TRAINER_LYDIA_3 === +Name: 郁惠 +Class: Pkmn Breeder +Pic: Pokemon Breeder F +Gender: Female +Music: Female +Double Battle: No +AI: Check Bad Move + +Pelipper +Level: 25 +IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe + +Breloom +Level: 25 +IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe + +Marill +Level: 25 +IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe + +Roselia +Level: 25 +IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe + +Delcatty +Level: 25 +IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe + +Goldeen +Level: 25 +IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe + +=== TRAINER_LYDIA_4 === +Name: 郁惠 +Class: Pkmn Breeder +Pic: Pokemon Breeder F +Gender: Female +Music: Female +Double Battle: No +AI: Check Bad Move + +Pelipper +Level: 28 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe + +Breloom +Level: 28 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe + +Marill +Level: 28 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe + +Roselia +Level: 28 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe + +Delcatty +Level: 28 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe + +Goldeen +Level: 28 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe + +=== TRAINER_LYDIA_5 === +Name: 郁惠 +Class: Pkmn Breeder +Pic: Pokemon Breeder F +Gender: Female +Music: Female +Double Battle: No +AI: Check Bad Move + +Pelipper +Level: 31 +IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe + +Breloom +Level: 31 +IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe + +Azumarill +Level: 31 +IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe + +Roselia +Level: 31 +IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe + +Delcatty +Level: 31 +IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe + +Seaking +Level: 31 +IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe + +=== TRAINER_JACKSON_1 === +Name: 阿守 +Class: Pkmn Ranger +Pic: Pokemon Ranger M +Gender: Male +Music: Cool +Items: Full Restore +Double Battle: No +AI: Basic Trainer + +Breloom +Level: 27 +IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe + +=== TRAINER_LORENZO === +Name: 淳一 +Class: Pkmn Ranger +Pic: Pokemon Ranger M +Gender: Male +Music: Cool +Items: Full Restore +Double Battle: No +AI: Basic Trainer + +Seedot +Level: 28 +IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe + +Nuzleaf +Level: 28 +IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe + +Lombre +Level: 28 +IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe + +=== TRAINER_SEBASTIAN === +Name: 圭介 +Class: Pkmn Ranger +Pic: Pokemon Ranger M +Gender: Male +Music: Cool +Items: Full Restore +Double Battle: No +AI: Basic Trainer + +Cacturne +Level: 39 +IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe + +=== TRAINER_JACKSON_2 === +Name: 阿守 +Class: Pkmn Ranger +Pic: Pokemon Ranger M +Gender: Male +Music: Cool +Items: Full Restore +Double Battle: No +AI: Check Bad Move / Try To Faint / Force Setup First Turn + +Breloom +Level: 31 +IVs: 7 HP / 7 Atk / 7 Def / 7 SpA / 7 SpD / 7 Spe + +=== TRAINER_JACKSON_3 === +Name: 阿守 +Class: Pkmn Ranger +Pic: Pokemon Ranger M +Gender: Male +Music: Cool +Items: Full Restore +Double Battle: No +AI: Basic Trainer + +Breloom +Level: 34 +IVs: 8 HP / 8 Atk / 8 Def / 8 SpA / 8 SpD / 8 Spe + +=== TRAINER_JACKSON_4 === +Name: 阿守 +Class: Pkmn Ranger +Pic: Pokemon Ranger M +Gender: Male +Music: Cool +Items: Full Restore +Double Battle: No +AI: Check Bad Move / Try To Faint / Force Setup First Turn + +Breloom +Level: 37 +IVs: 9 HP / 9 Atk / 9 Def / 9 SpA / 9 SpD / 9 Spe + +=== TRAINER_JACKSON_5 === +Name: 阿守 +Class: Pkmn Ranger +Pic: Pokemon Ranger M +Gender: Male +Music: Cool +Items: Full Restore +Double Battle: No +AI: Basic Trainer + +Kecleon +Level: 39 +IVs: 10 HP / 10 Atk / 10 Def / 10 SpA / 10 SpD / 10 Spe + +Breloom +Level: 39 +IVs: 10 HP / 10 Atk / 10 Def / 10 SpA / 10 SpD / 10 Spe + +=== TRAINER_CATHERINE_1 === +Name: 真奈美 +Class: Pkmn Ranger +Pic: Pokemon Ranger F +Gender: Female +Music: Cool +Items: Full Restore +Double Battle: No +AI: Check Bad Move / Try To Faint / Force Setup First Turn + +Gloom +Level: 26 +IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe + +Roselia +Level: 26 +IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe + +=== TRAINER_JENNA === +Name: 芹奈 +Class: Pkmn Ranger +Pic: Pokemon Ranger F +Gender: Female +Music: Cool +Items: Full Restore +Double Battle: No +AI: Check Bad Move / Try To Faint / Force Setup First Turn + +Lotad +Level: 28 +IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe + +Lombre +Level: 28 +IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe + +Nuzleaf +Level: 28 +IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe + +=== TRAINER_SOPHIA === +Name: 千秋 +Class: Pkmn Ranger +Pic: Pokemon Ranger F +Gender: Female +Music: Cool +Items: Full Restore +Double Battle: No +AI: Basic Trainer + +Swablu +Level: 38 +IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe + +Roselia +Level: 38 +IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe + +=== TRAINER_CATHERINE_2 === +Name: 真奈美 +Class: Pkmn Ranger +Pic: Pokemon Ranger F +Gender: Female +Music: Cool +Items: Full Restore +Double Battle: No +AI: Check Bad Move / Try To Faint / Force Setup First Turn + +Gloom +Level: 30 +IVs: 7 HP / 7 Atk / 7 Def / 7 SpA / 7 SpD / 7 Spe + +Roselia +Level: 30 +IVs: 7 HP / 7 Atk / 7 Def / 7 SpA / 7 SpD / 7 Spe + +=== TRAINER_CATHERINE_3 === +Name: 真奈美 +Class: Pkmn Ranger +Pic: Pokemon Ranger F +Gender: Female +Music: Cool +Items: Full Restore +Double Battle: No +AI: Basic Trainer + +Gloom +Level: 33 +IVs: 8 HP / 8 Atk / 8 Def / 8 SpA / 8 SpD / 8 Spe + +Roselia +Level: 33 +IVs: 8 HP / 8 Atk / 8 Def / 8 SpA / 8 SpD / 8 Spe + +=== TRAINER_CATHERINE_4 === +Name: 真奈美 +Class: Pkmn Ranger +Pic: Pokemon Ranger F +Gender: Female +Music: Cool +Items: Full Restore +Double Battle: No +AI: Check Bad Move / Try To Faint / Force Setup First Turn + +Gloom +Level: 36 +IVs: 9 HP / 9 Atk / 9 Def / 9 SpA / 9 SpD / 9 Spe + +Roselia +Level: 36 +IVs: 9 HP / 9 Atk / 9 Def / 9 SpA / 9 SpD / 9 Spe + +=== TRAINER_CATHERINE_5 === +Name: 真奈美 +Class: Pkmn Ranger +Pic: Pokemon Ranger F +Gender: Female +Music: Cool +Items: Full Restore +Double Battle: No +AI: Basic Trainer + +Bellossom +Level: 39 +IVs: 10 HP / 10 Atk / 10 Def / 10 SpA / 10 SpD / 10 Spe + +Roselia +Level: 39 +IVs: 10 HP / 10 Atk / 10 Def / 10 SpA / 10 SpD / 10 Spe + +=== TRAINER_JULIO === +Name: 光雄 +Class: Triathlete +Pic: Cycling Triathlete M +Gender: Male +Music: Male +Double Battle: No +AI: Check Bad Move + +Magnemite +Level: 21 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_GRUNT_SEAFLOOR_CAVERN_5 === +Name: 手下 +Class: Team Aqua +Pic: Aqua Grunt M +Gender: Male +Music: Aqua +Double Battle: No +AI: Check Bad Move + +Mightyena +Level: 35 +IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe + +Golbat +Level: 35 +IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe + +=== TRAINER_GRUNT_UNUSED === +Name: 手下 +Class: Team Magma +Pic: Aqua Grunt F +Gender: Female +Music: Aqua +Double Battle: No +AI: Check Bad Move + +Wailmer +Level: 31 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Zubat +Level: 31 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_GRUNT_MT_PYRE_4 === +Name: 手下 +Class: Team Aqua +Pic: Aqua Grunt F +Gender: Female +Music: Aqua +Double Battle: No +AI: Check Bad Move + +Wailmer +Level: 30 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Zubat +Level: 30 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_GRUNT_JAGGED_PASS === +Name: 手下 +Class: Team Magma +Pic: Magma Grunt M +Gender: Male +Music: Magma +Double Battle: No +AI: Check Bad Move + +Poochyena +Level: 22 +IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe + +Numel +Level: 22 +IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe + +=== TRAINER_MARC === +Name: 宗太郎 +Class: Hiker +Pic: Hiker +Gender: Male +Music: Hiker +Double Battle: No +AI: Check Bad Move + +Geodude +Level: 8 +IVs: 14 HP / 14 Atk / 14 Def / 14 SpA / 14 SpD / 14 Spe + +Geodude +Level: 8 +IVs: 15 HP / 15 Atk / 15 Def / 15 SpA / 15 SpD / 15 Spe + +=== TRAINER_BRENDEN === +Name: 和正 +Class: Sailor +Pic: Sailor +Gender: Male +Music: Male +Double Battle: No +AI: Check Bad Move + +Machop +Level: 13 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +=== TRAINER_LILITH === +Name: 安昙 +Class: Battle Girl +Pic: Battle Girl +Gender: Female +Music: Intense +Double Battle: No +AI: Check Bad Move + +Meditite +Level: 13 +IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe + +=== TRAINER_CRISTIAN === +Name: 俊英 +Class: Black Belt +Pic: Black Belt +Gender: Male +Music: Intense +Double Battle: No +AI: Check Bad Move + +Makuhita +Level: 13 +IVs: 24 HP / 24 Atk / 24 Def / 24 SpA / 24 SpD / 24 Spe + +=== TRAINER_SYLVIA === +Name: 朝代 +Class: Hex Maniac +Pic: Hex Maniac +Gender: Female +Music: Suspicious +Double Battle: No +AI: Check Bad Move + +Meditite +Level: 36 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +=== TRAINER_LEONARDO === +Name: 和成 +Class: Swimmer M +Pic: Swimmer M +Gender: Male +Music: Swimmer +Double Battle: No +AI: Check Bad Move + +Carvanha +Level: 34 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_ATHENA === +Name: 江美里 +Class: Cooltrainer +Pic: Cooltrainer F +Gender: Female +Music: Cool +Items: Hyper Potion +Double Battle: No +AI: Basic Trainer + +Manectric +Level: 32 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe +- Thunder +- Thunder Wave +- Quick Attack + +Linoone +Level: 32 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe +- Surf +- Thief + +=== TRAINER_HARRISON === +Name: 正明 +Class: Swimmer M +Pic: Swimmer M +Gender: Male +Music: Swimmer +Double Battle: No +AI: Check Bad Move + +Tentacruel +Level: 35 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_GRUNT_MT_CHIMNEY_2 === +Name: 手下 +Class: Team Magma +Pic: Magma Grunt M +Gender: Male +Music: Magma +Double Battle: No +AI: Check Bad Move + +Zubat +Level: 20 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_CLARENCE === +Name: 义文 +Class: Swimmer M +Pic: Swimmer M +Gender: Male +Music: Swimmer +Double Battle: No +AI: Check Bad Move + +Sharpedo +Level: 34 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_TERRY === +Name: 无名氏 +Class: Psychic +Pic: Psychic F +Gender: Female +Music: Intense +Double Battle: No +AI: Check Bad Move + +Girafarig +Level: 37 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_NATE === +Name: 东尼 +Class: Gentleman +Pic: Gentleman +Gender: Male +Music: Rich +Double Battle: No +AI: Check Bad Move + +Spoink +Level: 36 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +=== TRAINER_KATHLEEN === +Name: 幸代 +Class: Hex Maniac +Pic: Hex Maniac +Gender: Female +Music: Suspicious +Double Battle: No +AI: Check Bad Move + +Kadabra +Level: 36 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +=== TRAINER_CLIFFORD === +Name: 史蒂夫 +Class: Gentleman +Pic: Gentleman +Gender: Male +Music: Rich +Double Battle: No +AI: Check Bad Move + +Girafarig +Level: 36 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_NICHOLAS === +Name: 行世 +Class: Psychic +Pic: Psychic M +Gender: Male +Music: Intense +Double Battle: No +AI: Check Bad Move + +Wobbuffet +Level: 36 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_GRUNT_SPACE_CENTER_3 === +Name: 手下 +Class: Team Magma +Pic: Magma Grunt F +Gender: Female +Music: Magma +Double Battle: No +AI: Check Bad Move + +Zubat +Level: 31 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Poochyena +Level: 31 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_GRUNT_SPACE_CENTER_4 === +Name: 手下 +Class: Team Magma +Pic: Magma Grunt M +Gender: Male +Music: Magma +Double Battle: No +AI: Check Bad Move + +Baltoy +Level: 32 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_GRUNT_SPACE_CENTER_5 === +Name: 手下 +Class: Team Magma +Pic: Magma Grunt M +Gender: Male +Music: Magma +Double Battle: No +AI: Check Bad Move + +Zubat +Level: 32 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_GRUNT_SPACE_CENTER_6 === +Name: 手下 +Class: Team Magma +Pic: Magma Grunt M +Gender: Male +Music: Magma +Double Battle: No +AI: Check Bad Move + +Mightyena +Level: 32 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_GRUNT_SPACE_CENTER_7 === +Name: 手下 +Class: Team Magma +Pic: Magma Grunt M +Gender: Male +Music: Magma +Double Battle: No +AI: Check Bad Move + +Baltoy +Level: 32 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_MACEY === +Name: 总子 +Class: Psychic +Pic: Psychic F +Gender: Female +Music: Intense +Double Battle: No +AI: Check Bad Move + +Natu +Level: 36 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_BRENDAN_RUSTBORO_TREECKO === +Name: 小悠 +Class: Rival +Pic: Brendan +Gender: Male +Music: Male +Double Battle: No +AI: Check Bad Move + +Lotad +Level: 13 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe + +Torchic +Level: 15 +IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe + +=== TRAINER_BRENDAN_RUSTBORO_MUDKIP === +Name: 小悠 +Class: Rival +Pic: Brendan +Gender: Male +Music: Male +Double Battle: No +AI: Check Bad Move + +Wingull +Level: 13 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe + +Treecko +Level: 15 +IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe + +=== TRAINER_PAXTON === +Name: 刚藏 +Class: Expert +Pic: Expert M +Gender: Male +Music: Intense +Double Battle: No +AI: Basic Trainer + +Swellow +Level: 33 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Breloom +Level: 33 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_ISABELLA === +Name: 和晴 +Class: Triathlete +Pic: Swimming Triathlete F +Gender: Female +Music: Swimmer +Double Battle: No +AI: Check Bad Move + +Staryu +Level: 34 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_GRUNT_WEATHER_INST_5 === +Name: 手下 +Class: Team Aqua +Pic: Aqua Grunt F +Gender: Female +Music: Aqua +Double Battle: No +AI: Check Bad Move + +Zubat +Level: 27 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Poochyena +Level: 27 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_TABITHA_MT_CHIMNEY === +Name: 火村 +Class: Magma Admin +Pic: Magma Admin +Gender: Male +Music: Magma +Double Battle: No +AI: Basic Trainer + +Numel +Level: 18 +IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe + +Poochyena +Level: 20 +IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe + +Numel +Level: 22 +IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe + +Zubat +Level: 22 +IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe + +=== TRAINER_JONATHAN === +Name: 凉介 +Class: Cooltrainer +Pic: Cooltrainer M +Gender: Male +Music: Cool +Items: Hyper Potion +Double Battle: No +AI: Check Bad Move / Try To Faint / Force Setup First Turn + +Kecleon +Level: 33 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Loudred +Level: 33 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_BRENDAN_RUSTBORO_TORCHIC === +Name: 小悠 +Class: Rival +Pic: Brendan +Gender: Male +Music: Male +Double Battle: No +AI: Basic Trainer + +Slugma +Level: 13 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe + +Mudkip +Level: 15 +IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe + +=== TRAINER_MAY_RUSTBORO_MUDKIP === +Name: 小遥 +Class: Rival +Pic: May +Gender: Female +Music: Female +Double Battle: No +AI: Check Bad Move / Try To Faint / Force Setup First Turn + +Wingull +Level: 13 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe + +Treecko +Level: 15 +IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe + +=== TRAINER_MAXIE_MAGMA_HIDEOUT === +Name: 赤焰松 +Class: Magma Leader +Pic: Magma Leader Maxie +Gender: Male +Music: Magma +Items: Super Potion / Super Potion +Double Battle: No +AI: Basic Trainer + +Mightyena +Level: 37 +IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe + +Crobat +Level: 38 +IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe + +Camerupt +Level: 39 +IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe + +=== TRAINER_MAXIE_MT_CHIMNEY === +Name: 赤焰松 +Class: Magma Leader +Pic: Magma Leader Maxie +Gender: Male +Music: Magma +Items: Super Potion / Super Potion +Double Battle: No +AI: Basic Trainer + +Mightyena +Level: 24 +IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe + +Zubat +Level: 24 +IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe + +Camerupt +Level: 25 +IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe + +=== TRAINER_TIANA === +Name: 千佳 +Class: Lass +Pic: Lass +Gender: Female +Music: Female +Double Battle: No +AI: Check Bad Move + +Zigzagoon +Level: 4 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Shroomish +Level: 4 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_HALEY_1 === +Name: 真希 +Class: Lass +Pic: Lass +Gender: Female +Music: Female +Double Battle: No +AI: Check Bad Move + +Lotad +Level: 6 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Shroomish +Level: 6 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_JANICE === +Name: 真理 +Class: Lass +Pic: Lass +Gender: Female +Music: Female +Double Battle: No +AI: Check Bad Move + +Marill +Level: 9 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_VIVI === +Name: 小秋 +Class: Winstrate +Pic: Lass +Gender: Female +Music: Female +Double Battle: No +AI: Basic Trainer + +Marill +Level: 15 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +Shroomish +Level: 15 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +Numel +Level: 15 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +=== TRAINER_HALEY_2 === +Name: 真希 +Class: Lass +Pic: Lass +Gender: Female +Music: Female +Double Battle: No +AI: Check Bad Move + +Lombre +Level: 26 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe + +Shroomish +Level: 26 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe + +=== TRAINER_HALEY_3 === +Name: 真希 +Class: Lass +Pic: Lass +Gender: Female +Music: Female +Double Battle: No +AI: Check Bad Move + +Lombre +Level: 29 +IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe + +Breloom +Level: 29 +IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe + +=== TRAINER_HALEY_4 === +Name: 真希 +Class: Lass +Pic: Lass +Gender: Female +Music: Female +Double Battle: No +AI: Check Bad Move + +Lombre +Level: 32 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe + +Breloom +Level: 32 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe + +=== TRAINER_HALEY_5 === +Name: 真希 +Class: Lass +Pic: Lass +Gender: Female +Music: Female +Double Battle: No +AI: Check Bad Move + +Swellow +Level: 34 +IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe + +Lombre +Level: 34 +IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe + +Breloom +Level: 34 +IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe + +=== TRAINER_SALLY === +Name: 美奈 +Class: Lass +Pic: Lass +Gender: Female +Music: Female +Double Battle: No +AI: Check Bad Move + +Oddish +Level: 16 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_ROBIN === +Name: 诗帆 +Class: Lass +Pic: Lass +Gender: Female +Music: Female +Double Battle: No +AI: Check Bad Move + +Skitty +Level: 14 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Shroomish +Level: 14 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Marill +Level: 14 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_ANDREA === +Name: 美纪 +Class: Lass +Pic: Lass +Gender: Female +Music: Female +Double Battle: No +AI: Check Bad Move + +Luvdisc +Level: 40 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +=== TRAINER_CRISSY === +Name: 梅 +Class: Lass +Pic: Lass +Gender: Female +Music: Female +Double Battle: No +AI: Check Bad Move + +Goldeen +Level: 39 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +Wailmer +Level: 39 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +=== TRAINER_RICK === +Name: 真一 +Class: Bug Catcher +Pic: Bug Catcher +Gender: Male +Music: Male +Double Battle: No +AI: Check Bad Move + +Wurmple +Level: 4 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Wurmple +Level: 4 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_LYLE === +Name: 不二雄 +Class: Bug Catcher +Pic: Bug Catcher +Gender: Male +Music: Male +Double Battle: No +AI: Check Bad Move + +Wurmple +Level: 3 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Wurmple +Level: 3 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Wurmple +Level: 3 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Wurmple +Level: 3 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_JOSE === +Name: 智德 +Class: Bug Catcher +Pic: Bug Catcher +Gender: Male +Music: Male +Double Battle: No +AI: Check Bad Move + +Wurmple +Level: 8 +IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe + +Nincada +Level: 8 +IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe + +=== TRAINER_DOUG === +Name: 修 +Class: Bug Catcher +Pic: Bug Catcher +Gender: Male +Music: Male +Double Battle: No +AI: Check Bad Move + +Nincada +Level: 28 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Ninjask +Level: 28 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_GREG === +Name: 浩之 +Class: Bug Catcher +Pic: Bug Catcher +Gender: Male +Music: Male +Double Battle: No +AI: Check Bad Move + +Volbeat +Level: 25 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Illumise +Level: 25 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_KENT === +Name: 友道 +Class: Bug Catcher +Pic: Bug Catcher +Gender: Male +Music: Male +Double Battle: No +AI: Check Bad Move + +Ninjask +Level: 25 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_JAMES_1 === +Name: 三树也 +Class: Bug Catcher +Pic: Bug Catcher +Gender: Male +Music: Male +Double Battle: No +AI: Check Bad Move + +Nincada +Level: 6 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Nincada +Level: 6 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_JAMES_2 === +Name: 三树也 +Class: Bug Catcher +Pic: Bug Catcher +Gender: Male +Music: Male +Double Battle: No +AI: Check Bad Move + +Ninjask +Level: 27 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe + +=== TRAINER_JAMES_3 === +Name: 三树也 +Class: Bug Catcher +Pic: Bug Catcher +Gender: Male +Music: Male +Double Battle: No +AI: Check Bad Move + +Dustox +Level: 29 +IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe + +Ninjask +Level: 29 +IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe + +=== TRAINER_JAMES_4 === +Name: 三树也 +Class: Bug Catcher +Pic: Bug Catcher +Gender: Male +Music: Male +Double Battle: No +AI: Check Bad Move + +Surskit +Level: 31 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe + +Dustox +Level: 31 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe + +Ninjask +Level: 31 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe + +=== TRAINER_JAMES_5 === +Name: 三树也 +Class: Bug Catcher +Pic: Bug Catcher +Gender: Male +Music: Male +Double Battle: No +AI: Check Bad Move + +Surskit +Level: 33 +IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe + +Ninjask +Level: 33 +IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe + +Dustox +Level: 33 +IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe + +Ninjask +Level: 33 +IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe + +=== TRAINER_BRICE === +Name: 晴信 +Class: Hiker +Pic: Hiker +Gender: Male +Music: Hiker +Double Battle: No +AI: Check Bad Move + +Numel +Level: 17 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Machop +Level: 17 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_TRENT_1 === +Name: 健作 +Class: Hiker +Pic: Hiker +Gender: Male +Music: Hiker +Double Battle: No +AI: Check Bad Move + +Geodude +Level: 16 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Geodude +Level: 17 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Geodude +Level: 16 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_LENNY === +Name: 胜人 +Class: Hiker +Pic: Hiker +Gender: Male +Music: Hiker +Double Battle: No +AI: Check Bad Move + +Geodude +Level: 18 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Machop +Level: 18 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_LUCAS_1 === +Name: 三郎 +Class: Hiker +Pic: Hiker +Gender: Male +Music: Hiker +Double Battle: No +AI: Check Bad Move + +Geodude +Level: 18 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Numel +Level: 18 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_ALAN === +Name: 正典 +Class: Hiker +Pic: Hiker +Gender: Male +Music: Hiker +Double Battle: No +AI: Check Bad Move + +Geodude +Level: 22 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Nosepass +Level: 22 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Graveler +Level: 22 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_CLARK === +Name: 和德 +Class: Hiker +Pic: Hiker +Gender: Male +Music: Hiker +Double Battle: No +AI: Check Bad Move + +Geodude +Level: 8 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_ERIC === +Name: 大地 +Class: Hiker +Pic: Hiker +Gender: Male +Music: Hiker +Double Battle: No +AI: Check Bad Move + +Geodude +Level: 20 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Baltoy +Level: 20 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_LUCAS_2 === +Name: 三郎 +Class: Hiker +Pic: Hiker +Gender: Male +Music: Hiker +Double Battle: No +AI: Check Bad Move + +Wailmer +Level: 9 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe +- Splash +- Water Gun + +=== TRAINER_MIKE_1 === +Name: 登 +Class: Hiker +Pic: Hiker +Gender: Male +Music: Hiker +Double Battle: No +AI: Check Bad Move + +Pelipper +Level: 10 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe +- Gust +- Growl + +Poochyena +Level: 10 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe +- Bite +- Scary Face + +=== TRAINER_MIKE_2 === +Name: 登 +Class: Hiker +Pic: Hiker +Gender: Male +Music: Hiker +Double Battle: No +AI: Check Bad Move + +Geodude +Level: 16 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Geodude +Level: 16 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Machop +Level: 16 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_TRENT_2 === +Name: 健作 +Class: Hiker +Pic: Hiker +Gender: Male +Music: Hiker +Double Battle: No +AI: Check Bad Move + +Geodude +Level: 24 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe + +Geodude +Level: 24 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe + +Geodude +Level: 24 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe + +Graveler +Level: 24 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe + +=== TRAINER_TRENT_3 === +Name: 健作 +Class: Hiker +Pic: Hiker +Gender: Male +Music: Hiker +Double Battle: No +AI: Check Bad Move + +Geodude +Level: 27 +IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe + +Geodude +Level: 27 +IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe + +Graveler +Level: 27 +IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe + +Graveler +Level: 27 +IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe + +=== TRAINER_TRENT_4 === +Name: 健作 +Class: Hiker +Pic: Hiker +Gender: Male +Music: Hiker +Double Battle: No +AI: Check Bad Move + +Geodude +Level: 30 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe + +Graveler +Level: 30 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe + +Graveler +Level: 30 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe + +Graveler +Level: 30 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe + +=== TRAINER_TRENT_5 === +Name: 健作 +Class: Hiker +Pic: Hiker +Gender: Male +Music: Hiker +Double Battle: No +AI: Check Bad Move + +Graveler +Level: 33 +IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe + +Graveler +Level: 33 +IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe + +Graveler +Level: 33 +IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe + +Golem +Level: 33 +IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe + +=== TRAINER_DEZ_AND_LUKE === +Name: 真子和辉 +Class: Young Couple +Pic: Young Couple +Gender: Male +Music: Girl +Double Battle: Yes +AI: Check Bad Move + +Delcatty +Level: 31 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Manectric +Level: 31 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_LEA_AND_JED === +Name: 佳穗和阿新 +Class: Young Couple +Pic: Young Couple +Gender: Male +Music: Girl +Double Battle: Yes +AI: Check Bad Move + +Luvdisc +Level: 45 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Luvdisc +Level: 45 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_KIRA_AND_DAN_1 === +Name: 夏和文 +Class: Young Couple +Pic: Young Couple +Gender: Male +Music: Girl +Double Battle: Yes +AI: Check Bad Move + +Volbeat +Level: 25 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Illumise +Level: 25 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_KIRA_AND_DAN_2 === +Name: 夏和文 +Class: Young Couple +Pic: Young Couple +Gender: Male +Music: Girl +Double Battle: Yes +AI: Check Bad Move + +Volbeat +Level: 30 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe + +Illumise +Level: 30 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe + +=== TRAINER_KIRA_AND_DAN_3 === +Name: 夏和文 +Class: Young Couple +Pic: Young Couple +Gender: Male +Music: Girl +Double Battle: Yes +AI: Check Bad Move + +Volbeat +Level: 33 +IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe + +Illumise +Level: 33 +IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe + +=== TRAINER_KIRA_AND_DAN_4 === +Name: 夏和文 +Class: Young Couple +Pic: Young Couple +Gender: Male +Music: Girl +Double Battle: Yes +AI: Check Bad Move + +Volbeat +Level: 36 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe + +Illumise +Level: 36 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe + +=== TRAINER_KIRA_AND_DAN_5 === +Name: 夏和文 +Class: Young Couple +Pic: Young Couple +Gender: Male +Music: Girl +Double Battle: Yes +AI: Check Bad Move + +Volbeat +Level: 39 +IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe + +Illumise +Level: 39 +IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe + +=== TRAINER_JOHANNA === +Name: 敦子 +Class: Beauty +Pic: Beauty +Gender: Female +Music: Female +Double Battle: No +AI: Check Bad Move + +Goldeen +Level: 13 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_GERALD === +Name: 卓郎 +Class: Cooltrainer +Pic: Cooltrainer M +Gender: Male +Music: Cool +Items: Hyper Potion +Double Battle: No +AI: Basic Trainer + +Kecleon +Level: 23 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe +- Flamethrower +- Fury Swipes +- Feint Attack +- Bind + +=== TRAINER_VIVIAN === +Name: 真琴 +Class: Battle Girl +Pic: Battle Girl +Gender: Female +Music: Intense +Double Battle: No +AI: Check Bad Move + +Meditite +Level: 17 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe +- Bide +- Detect +- Confusion +- Thunder Punch + +Meditite +Level: 17 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe +- Thunder Punch +- Detect +- Confusion +- Meditate + +=== TRAINER_DANIELLE === +Name: 知美 +Class: Battle Girl +Pic: Battle Girl +Gender: Female +Music: Intense +Double Battle: No +AI: Check Bad Move + +Meditite +Level: 23 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe +- Bide +- Detect +- Confusion +- Fire Punch + +=== TRAINER_HIDEO === +Name: 克治 +Class: Ninja Boy +Pic: Ninja Boy +Gender: Male +Music: Suspicious +Double Battle: No +AI: Check Bad Move / Try To Faint + +Koffing +Level: 25 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe +- Tackle +- Self Destruct +- Sludge +- Smokescreen + +Koffing +Level: 25 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe +- Tackle +- Poison Gas +- Sludge +- Smokescreen + +=== TRAINER_KEIGO === +Name: 哲司 +Class: Ninja Boy +Pic: Ninja Boy +Gender: Male +Music: Suspicious +Double Battle: No +AI: Check Bad Move / Try To Faint + +Koffing +Level: 28 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe +- Poison Gas +- Self Destruct +- Sludge +- Smokescreen + +Ninjask +Level: 28 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe +- Sand Attack +- Double Team +- Fury Cutter +- Swords Dance + +=== TRAINER_RILEY === +Name: 忠弘 +Class: Ninja Boy +Pic: Ninja Boy +Gender: Male +Music: Suspicious +Double Battle: No +AI: Check Bad Move / Try To Faint + +Nincada +Level: 28 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe +- Leech Life +- Fury Swipes +- Mind Reader +- Dig + +Koffing +Level: 28 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe +- Tackle +- Self Destruct +- Sludge +- Smokescreen + +=== TRAINER_FLINT === +Name: 辉夫 +Class: Camper +Pic: Camper +Gender: Male +Music: Male +Double Battle: No +AI: Check Bad Move + +Swellow +Level: 29 +IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe + +Xatu +Level: 29 +IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe + +=== TRAINER_ASHLEY === +Name: 耳子 +Class: Picnicker +Pic: Picnicker +Gender: Female +Music: Girl +Double Battle: No +AI: Check Bad Move + +Swablu +Level: 27 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +Swablu +Level: 27 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +Swablu +Level: 27 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +=== TRAINER_WALLY_MAUVILLE === +Name: 满充 +Class: Rival +Pic: Wally +Gender: Male +Music: Male +Double Battle: No +AI: Basic Trainer + +Ralts +Level: 16 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe + +=== TRAINER_WALLY_VR_2 === +Name: 满充 +Class: Rival +Pic: Wally +Gender: Male +Music: Male +Items: Full Restore / Full Restore +Double Battle: No +AI: Basic Trainer + +Altaria +Level: 47 +IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe +- Aerial Ace +- Safeguard +- Dragon Breath +- Dragon Dance + +Delcatty +Level: 46 +IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe +- Sing +- Assist +- Charm +- Feint Attack + +Roselia +Level: 47 +IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe +- Magical Leaf +- Leech Seed +- Giga Drain +- Toxic + +Magneton +Level: 44 +IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe +- Supersonic +- Thunderbolt +- Tri Attack +- Screech + +Gardevoir +Level: 48 +IVs: 30 HP / 30 Atk / 30 Def / 30 SpA / 30 SpD / 30 Spe +- Double Team +- Calm Mind +- Psychic +- Future Sight + +=== TRAINER_WALLY_VR_3 === +Name: 满充 +Class: Rival +Pic: Wally +Gender: Male +Music: Male +Items: Full Restore / Full Restore +Double Battle: No +AI: Basic Trainer + +Altaria +Level: 50 +IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe +- Aerial Ace +- Safeguard +- Dragon Breath +- Dragon Dance + +Delcatty +Level: 49 +IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe +- Sing +- Assist +- Charm +- Feint Attack + +Roselia +Level: 50 +IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe +- Magical Leaf +- Leech Seed +- Giga Drain +- Toxic + +Magneton +Level: 47 +IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe +- Supersonic +- Thunderbolt +- Tri Attack +- Screech + +Gardevoir +Level: 51 +IVs: 30 HP / 30 Atk / 30 Def / 30 SpA / 30 SpD / 30 Spe +- Double Team +- Calm Mind +- Psychic +- Future Sight + +=== TRAINER_WALLY_VR_4 === +Name: 满充 +Class: Rival +Pic: Wally +Gender: Male +Music: Male +Items: Full Restore / Full Restore +Double Battle: No +AI: Basic Trainer + +Altaria +Level: 53 +IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe +- Aerial Ace +- Safeguard +- Dragon Breath +- Dragon Dance + +Delcatty +Level: 52 +IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe +- Sing +- Assist +- Charm +- Feint Attack + +Roselia +Level: 53 +IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe +- Magical Leaf +- Leech Seed +- Giga Drain +- Toxic + +Magneton +Level: 50 +IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe +- Supersonic +- Thunderbolt +- Tri Attack +- Screech + +Gardevoir +Level: 54 +IVs: 30 HP / 30 Atk / 30 Def / 30 SpA / 30 SpD / 30 Spe +- Double Team +- Calm Mind +- Psychic +- Future Sight + +=== TRAINER_WALLY_VR_5 === +Name: 满充 +Class: Rival +Pic: Wally +Gender: Male +Music: Male +Items: Full Restore / Full Restore +Double Battle: No +AI: Basic Trainer + +Altaria +Level: 56 +IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe +- Aerial Ace +- Safeguard +- Dragon Breath +- Dragon Dance + +Delcatty +Level: 55 +IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe +- Sing +- Assist +- Charm +- Feint Attack + +Roselia +Level: 56 +IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe +- Magical Leaf +- Leech Seed +- Giga Drain +- Toxic + +Magneton +Level: 53 +IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe +- Supersonic +- Thunderbolt +- Tri Attack +- Screech + +Gardevoir +Level: 57 +IVs: 30 HP / 30 Atk / 30 Def / 30 SpA / 30 SpD / 30 Spe +- Double Team +- Calm Mind +- Psychic +- Future Sight + +=== TRAINER_BRENDAN_LILYCOVE_MUDKIP === +Name: 小悠 +Class: Rival +Pic: Brendan +Gender: Male +Music: Male +Double Battle: No +AI: Basic Trainer + +Tropius +Level: 31 +IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe + +Slugma +Level: 32 +IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe + +Pelipper +Level: 32 +IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe + +Grovyle +Level: 34 +IVs: 24 HP / 24 Atk / 24 Def / 24 SpA / 24 SpD / 24 Spe + +=== TRAINER_BRENDAN_LILYCOVE_TREECKO === +Name: 小悠 +Class: Rival +Pic: Brendan +Gender: Male +Music: Male +Double Battle: No +AI: Basic Trainer + +Tropius +Level: 31 +IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe + +Pelipper +Level: 32 +IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe + +Ludicolo +Level: 32 +IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe + +Combusken +Level: 34 +IVs: 24 HP / 24 Atk / 24 Def / 24 SpA / 24 SpD / 24 Spe + +=== TRAINER_BRENDAN_LILYCOVE_TORCHIC === +Name: 小悠 +Class: Rival +Pic: Brendan +Gender: Male +Music: Male +Double Battle: No +AI: Basic Trainer + +Tropius +Level: 31 +IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe + +Ludicolo +Level: 32 +IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe + +Slugma +Level: 32 +IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe + +Marshtomp +Level: 34 +IVs: 24 HP / 24 Atk / 24 Def / 24 SpA / 24 SpD / 24 Spe + +=== TRAINER_MAY_LILYCOVE_MUDKIP === +Name: 小遥 +Class: Rival +Pic: May +Gender: Female +Music: Female +Double Battle: No +AI: Basic Trainer + +Tropius +Level: 31 +IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe + +Slugma +Level: 32 +IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe + +Pelipper +Level: 32 +IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe + +Grovyle +Level: 34 +IVs: 24 HP / 24 Atk / 24 Def / 24 SpA / 24 SpD / 24 Spe + +=== TRAINER_MAY_LILYCOVE_TREECKO === +Name: 小遥 +Class: Rival +Pic: May +Gender: Female +Music: Female +Double Battle: No +AI: Basic Trainer + +Tropius +Level: 31 +IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe + +Pelipper +Level: 32 +IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe + +Ludicolo +Level: 32 +IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe + +Combusken +Level: 34 +IVs: 24 HP / 24 Atk / 24 Def / 24 SpA / 24 SpD / 24 Spe + +=== TRAINER_MAY_LILYCOVE_TORCHIC === +Name: 小遥 +Class: Rival +Pic: May +Gender: Female +Music: Female +Double Battle: No +AI: Basic Trainer + +Tropius +Level: 31 +IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe + +Ludicolo +Level: 32 +IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe + +Slugma +Level: 32 +IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe + +Marshtomp +Level: 34 +IVs: 24 HP / 24 Atk / 24 Def / 24 SpA / 24 SpD / 24 Spe + +=== TRAINER_JONAH === +Name: 善德 +Class: Fisherman +Pic: Fisherman +Gender: Male +Music: Hiker +Double Battle: No +AI: Check Bad Move + +Wailmer +Level: 30 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Tentacool +Level: 31 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Sharpedo +Level: 32 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_HENRY === +Name: 健太郎 +Class: Fisherman +Pic: Fisherman +Gender: Male +Music: Hiker +Double Battle: No +AI: Check Bad Move + +Carvanha +Level: 31 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Tentacruel +Level: 34 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_ROGER === +Name: 智彦 +Class: Fisherman +Pic: Fisherman +Gender: Male +Music: Hiker +Double Battle: No +AI: Check Bad Move + +Magikarp +Level: 15 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Magikarp +Level: 25 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Gyarados +Level: 35 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_ALEXA === +Name: 明香 +Class: Cooltrainer +Pic: Cooltrainer F +Gender: Female +Music: Cool +Items: Full Restore +Double Battle: No +AI: Basic Trainer + +Gloom +Level: 34 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +Azumarill +Level: 34 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +=== TRAINER_RUBEN === +Name: 驯 +Class: Cooltrainer +Pic: Cooltrainer M +Gender: Male +Music: Cool +Items: Hyper Potion +Double Battle: No +AI: Basic Trainer + +Shiftry +Level: 34 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +Nosepass +Level: 34 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +=== TRAINER_KOJI_1 === +Name: 铁郎 +Class: Black Belt +Pic: Black Belt +Gender: Male +Music: Intense +Double Battle: No +AI: Check Bad Move + +Machoke +Level: 34 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_WAYNE === +Name: 孝作 +Class: Fisherman +Pic: Fisherman +Gender: Male +Music: Hiker +Double Battle: No +AI: Check Bad Move + +Tentacool +Level: 31 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Tentacool +Level: 31 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Wailmer +Level: 36 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_AIDAN === +Name: 郁夫 +Class: Bird Keeper +Pic: Bird Keeper +Gender: Male +Music: Cool +Double Battle: No +AI: Check Bad Move + +Swellow +Level: 32 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Skarmory +Level: 32 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_REED === +Name: 明夫 +Class: Swimmer M +Pic: Swimmer M +Gender: Male +Music: Swimmer +Double Battle: No +AI: Check Bad Move + +Spheal +Level: 33 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Sharpedo +Level: 33 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_TISHA === +Name: 由佳理 +Class: Swimmer F +Pic: Swimmer F +Gender: Female +Music: Swimmer +Double Battle: No +AI: Check Bad Move + +Chinchou +Level: 34 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_TORI_AND_TIA === +Name: 奈奈和宁宁 +Class: Twins +Pic: Twins +Gender: Male +Music: Twins +Double Battle: Yes +AI: Check Bad Move + +Spinda +Level: 19 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Spinda +Level: 19 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_KIM_AND_IRIS === +Name: 真穗和奈穗 +Class: Sr And Jr +Pic: Sr And Jr +Gender: Male +Music: Twins +Double Battle: Yes +AI: Check Bad Move + +Swablu +Level: 32 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe +- Sing +- Fury Attack +- Safeguard +- Aerial Ace + +Numel +Level: 35 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe +- Flamethrower +- Take Down +- Rest +- Earthquake + +=== TRAINER_TYRA_AND_IVY === +Name: 佳代和依代 +Class: Sr And Jr +Pic: Sr And Jr +Gender: Male +Music: Twins +Double Battle: Yes +AI: Check Bad Move + +Roselia +Level: 18 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe +- Growth +- Stun Spore +- Mega Drain +- Leech Seed + +Graveler +Level: 20 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe +- Defense Curl +- Rollout +- Mud Sport +- Rock Throw + +=== TRAINER_MEL_AND_PAUL === +Name: 志木和理树 +Class: Young Couple +Pic: Young Couple +Gender: Male +Music: Girl +Double Battle: Yes +AI: Check Bad Move + +Dustox +Level: 27 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe +- Gust +- Psybeam +- Toxic +- Protect + +Beautifly +Level: 27 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe +- Gust +- Mega Drain +- Attract +- Stun Spore + +=== TRAINER_JOHN_AND_JAY_1 === +Name: 源和初 +Class: Old Couple +Pic: Old Couple +Gender: Male +Music: Intense +Double Battle: Yes +AI: Basic Trainer + +Medicham +Level: 39 +IVs: 24 HP / 24 Atk / 24 Def / 24 SpA / 24 SpD / 24 Spe +- Psychic +- Fire Punch +- Psych Up +- Protect + +Hariyama +Level: 39 +IVs: 24 HP / 24 Atk / 24 Def / 24 SpA / 24 SpD / 24 Spe +- Focus Punch +- Rock Tomb +- Rest +- Belly Drum + +=== TRAINER_JOHN_AND_JAY_2 === +Name: 源和初 +Class: Old Couple +Pic: Old Couple +Gender: Male +Music: Intense +Double Battle: Yes +AI: Basic Trainer + +Medicham +Level: 43 +IVs: 25 HP / 25 Atk / 25 Def / 25 SpA / 25 SpD / 25 Spe +- Psychic +- Fire Punch +- Psych Up +- Protect + +Hariyama +Level: 43 +IVs: 25 HP / 25 Atk / 25 Def / 25 SpA / 25 SpD / 25 Spe +- Focus Punch +- Rock Tomb +- Rest +- Belly Drum + +=== TRAINER_JOHN_AND_JAY_3 === +Name: 源和初 +Class: Old Couple +Pic: Old Couple +Gender: Male +Music: Intense +Double Battle: Yes +AI: Basic Trainer + +Medicham +Level: 46 +IVs: 26 HP / 26 Atk / 26 Def / 26 SpA / 26 SpD / 26 Spe +- Psychic +- Fire Punch +- Psych Up +- Protect + +Hariyama +Level: 46 +IVs: 26 HP / 26 Atk / 26 Def / 26 SpA / 26 SpD / 26 Spe +- Focus Punch +- Rock Tomb +- Rest +- Belly Drum + +=== TRAINER_JOHN_AND_JAY_4 === +Name: 源和初 +Class: Old Couple +Pic: Old Couple +Gender: Male +Music: Intense +Double Battle: Yes +AI: Check Bad Move / Try To Faint / Force Setup First Turn + +Medicham +Level: 49 +IVs: 27 HP / 27 Atk / 27 Def / 27 SpA / 27 SpD / 27 Spe +- Psychic +- Fire Punch +- Psych Up +- Protect + +Hariyama +Level: 49 +IVs: 27 HP / 27 Atk / 27 Def / 27 SpA / 27 SpD / 27 Spe +- Focus Punch +- Rock Tomb +- Rest +- Belly Drum + +=== TRAINER_JOHN_AND_JAY_5 === +Name: 源和初 +Class: Old Couple +Pic: Old Couple +Gender: Male +Music: Intense +Double Battle: Yes +AI: Basic Trainer + +Medicham +Level: 52 +IVs: 29 HP / 29 Atk / 29 Def / 29 SpA / 29 SpD / 29 Spe +- Psychic +- Fire Punch +- Psych Up +- Protect + +Hariyama +Level: 52 +IVs: 29 HP / 29 Atk / 29 Def / 29 SpA / 29 SpD / 29 Spe +- Focus Punch +- Rock Tomb +- Rest +- Belly Drum + +=== TRAINER_RELI_AND_IAN === +Name: 胜和亚美 +Class: Sis And Bro +Pic: Sis And Bro +Gender: Male +Music: Swimmer +Double Battle: Yes +AI: Check Bad Move + +Azumarill +Level: 35 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Wingull +Level: 33 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_LILA_AND_ROY_1 === +Name: 小勇和佳子 +Class: Sis And Bro +Pic: Sis And Bro +Gender: Male +Music: Swimmer +Double Battle: Yes +AI: Check Bad Move + +Chinchou +Level: 34 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Carvanha +Level: 33 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_LILA_AND_ROY_2 === +Name: 小勇和佳子 +Class: Sis And Bro +Pic: Sis And Bro +Gender: Male +Music: Swimmer +Double Battle: Yes +AI: Check Bad Move + +Chinchou +Level: 42 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Carvanha +Level: 40 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_LILA_AND_ROY_3 === +Name: 小勇和佳子 +Class: Sis And Bro +Pic: Sis And Bro +Gender: Male +Music: Swimmer +Double Battle: Yes +AI: Check Bad Move + +Lanturn +Level: 45 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Carvanha +Level: 43 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_LILA_AND_ROY_4 === +Name: 小勇和佳子 +Class: Sis And Bro +Pic: Sis And Bro +Gender: Male +Music: Swimmer +Double Battle: Yes +AI: Check Bad Move + +Lanturn +Level: 48 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Sharpedo +Level: 46 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_LILA_AND_ROY_5 === +Name: 小勇和佳子 +Class: Sis And Bro +Pic: Sis And Bro +Gender: Male +Music: Swimmer +Double Battle: Yes +AI: Check Bad Move + +Lanturn +Level: 51 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Sharpedo +Level: 49 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_LISA_AND_RAY === +Name: 真和由美 +Class: Sis And Bro +Pic: Sis And Bro +Gender: Male +Music: Swimmer +Double Battle: Yes +AI: Check Bad Move + +Goldeen +Level: 27 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Tentacool +Level: 25 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_CHRIS === +Name: 正志 +Class: Fisherman +Pic: Fisherman +Gender: Male +Music: Hiker +Double Battle: No +AI: Check Bad Move + +Magikarp +Level: 29 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Tentacool +Level: 20 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Feebas +Level: 26 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Carvanha +Level: 23 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_DAWSON === +Name: 希望 +Class: Rich Boy +Pic: Rich Boy +Gender: Male +Music: Rich +Double Battle: No +AI: Check Bad Move + +Zigzagoon @ Nugget +Level: 8 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Poochyena +Level: 8 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_SARAH === +Name: 樱子 +Class: Lady +Pic: Lady +Gender: Female +Music: Female +Items: Full Restore +Double Battle: No +AI: Check Bad Move + +Lotad +Level: 8 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Zigzagoon @ Nugget +Level: 8 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_DARIAN === +Name: 健吉 +Class: Fisherman +Pic: Fisherman +Gender: Male +Music: Hiker +Double Battle: No +AI: Check Bad Move + +Magikarp +Level: 9 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_HAILEY === +Name: 小华 +Class: Tuber F +Pic: Tuber F +Gender: Female +Music: Girl +Double Battle: No +AI: Check Bad Move + +Marill +Level: 13 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_CHANDLER === +Name: 大辅 +Class: Tuber M +Pic: Tuber M +Gender: Male +Music: Girl +Double Battle: No +AI: Check Bad Move + +Tentacool +Level: 12 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Tentacool +Level: 12 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_KALEB === +Name: 雅贵 +Class: Pokefan +Pic: Pokefan M +Gender: Male +Music: Twins +Double Battle: No +AI: Check Bad Move + +Minun @ Oran Berry +Level: 14 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Plusle @ Oran Berry +Level: 14 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_JOSEPH === +Name: 保罗 +Class: Guitarist +Pic: Guitarist +Gender: Male +Music: Intense +Double Battle: No +AI: Check Bad Move + +Electrike +Level: 14 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Voltorb +Level: 14 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_ALYSSA === +Name: 冴美 +Class: Triathlete +Pic: Cycling Triathlete F +Gender: Female +Music: Female +Double Battle: No +AI: Check Bad Move + +Magnemite +Level: 15 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_MARCOS === +Name: 埃力克 +Class: Guitarist +Pic: Guitarist +Gender: Male +Music: Intense +Double Battle: No +AI: Check Bad Move + +Voltorb +Level: 15 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +=== TRAINER_RHETT === +Name: 茂森 +Class: Black Belt +Pic: Black Belt +Gender: Male +Music: Intense +Double Battle: No +AI: Check Bad Move + +Makuhita +Level: 15 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +=== TRAINER_TYRON === +Name: 俊文 +Class: Camper +Pic: Camper +Gender: Male +Music: Male +Double Battle: No +AI: Check Bad Move + +Sandshrew +Level: 19 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_CELINA === +Name: 和香子 +Class: Aroma Lady +Pic: Aroma Lady +Gender: Female +Music: Female +Double Battle: No +AI: Check Bad Move + +Roselia +Level: 18 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_BIANCA === +Name: 伊织 +Class: Picnicker +Pic: Picnicker +Gender: Female +Music: Girl +Double Battle: No +AI: Check Bad Move + +Shroomish +Level: 18 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_HAYDEN === +Name: 国明 +Class: Kindler +Pic: Kindler +Gender: Male +Music: Hiker +Double Battle: No +AI: Check Bad Move + +Numel +Level: 18 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_SOPHIE === +Name: 长闲 +Class: Picnicker +Pic: Picnicker +Gender: Female +Music: Girl +Double Battle: No +AI: Check Bad Move + +Marill +Level: 17 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Lombre +Level: 19 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_COBY === +Name: 和高 +Class: Bird Keeper +Pic: Bird Keeper +Gender: Male +Music: Cool +Double Battle: No +AI: Check Bad Move + +Skarmory +Level: 17 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Swellow +Level: 19 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_LAWRENCE === +Name: 勇吾 +Class: Camper +Pic: Camper +Gender: Male +Music: Male +Double Battle: No +AI: Check Bad Move + +Baltoy +Level: 18 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Sandshrew +Level: 18 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_WYATT === +Name: 道夫 +Class: Pokemaniac +Pic: Pokemaniac +Gender: Male +Music: Suspicious +Double Battle: No +AI: Check Bad Move + +Aron +Level: 18 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Aron +Level: 18 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_ANGELINA === +Name: 茉莉 +Class: Picnicker +Pic: Picnicker +Gender: Female +Music: Girl +Double Battle: No +AI: Check Bad Move + +Lombre +Level: 18 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Marill +Level: 18 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_KAI === +Name: 宏光 +Class: Fisherman +Pic: Fisherman +Gender: Male +Music: Hiker +Double Battle: No +AI: Check Bad Move + +Barboach +Level: 19 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_CHARLOTTE === +Name: 美波 +Class: Picnicker +Pic: Picnicker +Gender: Female +Music: Girl +Double Battle: No +AI: Check Bad Move + +Nuzleaf +Level: 19 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_DEANDRE === +Name: 雅也 +Class: Youngster +Pic: Youngster +Gender: Male +Music: Male +Double Battle: No +AI: Check Bad Move + +Zigzagoon +Level: 14 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Aron +Level: 14 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Electrike +Level: 14 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_GRUNT_MAGMA_HIDEOUT_1 === +Name: 手下 +Class: Team Magma +Pic: Magma Grunt M +Gender: Male +Music: Magma +Double Battle: No +AI: Check Bad Move + +Zubat +Level: 29 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_GRUNT_MAGMA_HIDEOUT_2 === +Name: 手下 +Class: Team Magma +Pic: Magma Grunt M +Gender: Male +Music: Magma +Double Battle: No +AI: Check Bad Move + +Poochyena +Level: 29 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_GRUNT_MAGMA_HIDEOUT_3 === +Name: 手下 +Class: Team Magma +Pic: Magma Grunt M +Gender: Male +Music: Magma +Double Battle: No +AI: Check Bad Move + +Numel +Level: 29 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_GRUNT_MAGMA_HIDEOUT_4 === +Name: 手下 +Class: Team Magma +Pic: Magma Grunt M +Gender: Male +Music: Magma +Double Battle: No +AI: Check Bad Move + +Baltoy +Level: 28 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Zubat +Level: 28 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_GRUNT_MAGMA_HIDEOUT_5 === +Name: 手下 +Class: Team Magma +Pic: Magma Grunt M +Gender: Male +Music: Magma +Double Battle: No +AI: Check Bad Move + +Baltoy +Level: 28 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Numel +Level: 28 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_GRUNT_MAGMA_HIDEOUT_6 === +Name: 手下 +Class: Team Magma +Pic: Magma Grunt M +Gender: Male +Music: Magma +Double Battle: No +AI: Check Bad Move + +Mightyena +Level: 29 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_GRUNT_MAGMA_HIDEOUT_7 === +Name: 手下 +Class: Team Magma +Pic: Magma Grunt M +Gender: Male +Music: Magma +Double Battle: No +AI: Check Bad Move + +Zubat +Level: 29 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_GRUNT_MAGMA_HIDEOUT_8 === +Name: 手下 +Class: Team Magma +Pic: Magma Grunt M +Gender: Male +Music: Magma +Double Battle: No +AI: Check Bad Move + +Poochyena +Level: 29 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_GRUNT_MAGMA_HIDEOUT_9 === +Name: 手下 +Class: Team Magma +Pic: Magma Grunt M +Gender: Male +Music: Magma +Double Battle: No +AI: Check Bad Move + +Zubat +Level: 29 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_GRUNT_MAGMA_HIDEOUT_10 === +Name: 手下 +Class: Team Magma +Pic: Magma Grunt M +Gender: Male +Music: Magma +Double Battle: No +AI: Check Bad Move + +Mightyena +Level: 29 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_GRUNT_MAGMA_HIDEOUT_11 === +Name: 手下 +Class: Team Magma +Pic: Magma Grunt M +Gender: Male +Music: Magma +Double Battle: No +AI: Check Bad Move + +Baltoy +Level: 29 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_GRUNT_MAGMA_HIDEOUT_12 === +Name: 手下 +Class: Team Magma +Pic: Magma Grunt M +Gender: Male +Music: Magma +Double Battle: No +AI: Check Bad Move + +Numel +Level: 29 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_GRUNT_MAGMA_HIDEOUT_13 === +Name: 手下 +Class: Team Magma +Pic: Magma Grunt M +Gender: Male +Music: Magma +Double Battle: No +AI: Check Bad Move + +Zubat +Level: 29 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_GRUNT_MAGMA_HIDEOUT_14 === +Name: 手下 +Class: Team Magma +Pic: Magma Grunt F +Gender: Female +Music: Magma +Double Battle: No +AI: Check Bad Move + +Mightyena +Level: 29 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_GRUNT_MAGMA_HIDEOUT_15 === +Name: 手下 +Class: Team Magma +Pic: Magma Grunt F +Gender: Female +Music: Magma +Double Battle: No +AI: Check Bad Move + +Numel +Level: 29 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_GRUNT_MAGMA_HIDEOUT_16 === +Name: 手下 +Class: Team Magma +Pic: Magma Grunt F +Gender: Female +Music: Magma +Double Battle: No +AI: Check Bad Move + +Baltoy +Level: 29 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_TABITHA_MAGMA_HIDEOUT === +Name: 火村 +Class: Magma Admin +Pic: Magma Admin +Gender: Male +Music: Magma +Double Battle: No +AI: Check Bad Move + +Numel +Level: 26 +IVs: 9 HP / 9 Atk / 9 Def / 9 SpA / 9 SpD / 9 Spe + +Mightyena +Level: 28 +IVs: 9 HP / 9 Atk / 9 Def / 9 SpA / 9 SpD / 9 Spe + +Zubat +Level: 30 +IVs: 9 HP / 9 Atk / 9 Def / 9 SpA / 9 SpD / 9 Spe + +Camerupt +Level: 33 +IVs: 9 HP / 9 Atk / 9 Def / 9 SpA / 9 SpD / 9 Spe + +=== TRAINER_DARCY === +Name: 成美 +Class: Cooltrainer +Pic: Cooltrainer F +Gender: Female +Music: Cool +Items: Hyper Potion +Double Battle: No +AI: Basic Trainer + +Pelipper +Level: 33 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Camerupt +Level: 33 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_MAXIE_MOSSDEEP === +Name: 赤焰松 +Class: Magma Leader +Pic: Magma Leader Maxie +Gender: Male +Music: Magma +Double Battle: No +AI: Basic Trainer + +Mightyena +Level: 42 +IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe + +Crobat +Level: 43 +IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe + +Camerupt +Level: 44 +IVs: 18 HP / 18 Atk / 18 Def / 18 SpA / 18 SpD / 18 Spe + +=== TRAINER_PETE === +Name: 秀彦 +Class: Swimmer M +Pic: Swimmer M +Gender: Male +Music: Swimmer +Double Battle: No +AI: Check Bad Move + +Tentacool +Level: 15 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_ISABELLE === +Name: 由美子 +Class: Swimmer F +Pic: Swimmer F +Gender: Female +Music: Swimmer +Double Battle: No +AI: Check Bad Move + +Marill +Level: 15 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_ANDRES_1 === +Name: 大次郎 +Class: Ruin Maniac +Pic: Ruin Maniac +Gender: Male +Music: Hiker +Double Battle: No +AI: Check Bad Move + +Sandshrew +Level: 25 +IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe + +Sandshrew +Level: 25 +IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe + +=== TRAINER_JOSUE === +Name: 康文 +Class: Bird Keeper +Pic: Bird Keeper +Gender: Male +Music: Cool +Double Battle: No +AI: Check Bad Move + +Taillow +Level: 25 +IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe + +Wingull +Level: 25 +IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe + +=== TRAINER_CAMRON === +Name: 国男 +Class: Triathlete +Pic: Swimming Triathlete M +Gender: Male +Music: Swimmer +Double Battle: No +AI: Check Bad Move + +Staryu +Level: 26 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_CORY_1 === +Name: 典孝 +Class: Sailor +Pic: Sailor +Gender: Male +Music: Male +Double Battle: No +AI: Check Bad Move + +Wingull +Level: 24 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Machop +Level: 24 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Tentacool +Level: 24 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_CAROLINA === +Name: 圣华 +Class: Cooltrainer +Pic: Cooltrainer F +Gender: Female +Music: Cool +Items: Hyper Potion +Double Battle: No +AI: Basic Trainer + +Manectric +Level: 24 +IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe + +Swellow +Level: 24 +IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe + +Manectric +Level: 24 +IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe + +=== TRAINER_ELIJAH === +Name: 俊隆 +Class: Bird Keeper +Pic: Bird Keeper +Gender: Male +Music: Cool +Double Battle: No +AI: Check Bad Move + +Skarmory +Level: 25 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Skarmory +Level: 25 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_CELIA === +Name: 亚希子 +Class: Picnicker +Pic: Picnicker +Gender: Female +Music: Girl +Double Battle: No +AI: Check Bad Move + +Marill +Level: 22 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Lombre +Level: 22 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_BRYAN === +Name: 博敏 +Class: Ruin Maniac +Pic: Ruin Maniac +Gender: Male +Music: Hiker +Double Battle: No +AI: Check Bad Move + +Sandshrew +Level: 22 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Sandslash +Level: 22 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_BRANDEN === +Name: 康范 +Class: Camper +Pic: Camper +Gender: Male +Music: Male +Double Battle: No +AI: Check Bad Move + +Taillow +Level: 22 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Nuzleaf +Level: 22 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_BRYANT === +Name: 敦夫 +Class: Kindler +Pic: Kindler +Gender: Male +Music: Hiker +Double Battle: No +AI: Check Bad Move + +Numel +Level: 18 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Slugma +Level: 18 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_SHAYLA === +Name: 妙子 +Class: Aroma Lady +Pic: Aroma Lady +Gender: Female +Music: Female +Double Battle: No +AI: Check Bad Move + +Shroomish +Level: 18 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Roselia +Level: 18 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_KYRA === +Name: 凛子 +Class: Triathlete +Pic: Running Triathlete F +Gender: Female +Music: Female +Double Battle: No +AI: Check Bad Move + +Doduo +Level: 26 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Dodrio +Level: 26 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_JAIDEN === +Name: 勇藏 +Class: Ninja Boy +Pic: Ninja Boy +Gender: Male +Music: Suspicious +Double Battle: No +AI: Check Bad Move + +Ninjask +Level: 26 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Gulpin +Level: 26 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_ALIX === +Name: 诗乃 +Class: Psychic +Pic: Psychic F +Gender: Female +Music: Intense +Double Battle: No +AI: Check Bad Move + +Kadabra +Level: 26 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Kirlia +Level: 26 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_HELENE === +Name: 千岁 +Class: Battle Girl +Pic: Battle Girl +Gender: Female +Music: Intense +Double Battle: No +AI: Check Bad Move + +Meditite +Level: 26 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Makuhita +Level: 26 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_MARLENE === +Name: 璃音 +Class: Psychic +Pic: Psychic F +Gender: Female +Music: Intense +Double Battle: No +AI: Check Bad Move + +Meditite +Level: 18 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Spoink +Level: 18 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_DEVAN === +Name: 通泰 +Class: Hiker +Pic: Hiker +Gender: Male +Music: Hiker +Double Battle: No +AI: Check Bad Move + +Geodude +Level: 8 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Geodude +Level: 8 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_JOHNSON === +Name: 有利 +Class: Youngster +Pic: Youngster +Gender: Male +Music: Male +Double Battle: No +AI: Check Bad Move + +Shroomish +Level: 8 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Lotad +Level: 8 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_MELINA === +Name: 素子 +Class: Triathlete +Pic: Running Triathlete F +Gender: Female +Music: Female +Double Battle: No +AI: Check Bad Move + +Doduo +Level: 17 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_BRANDI === +Name: 圣夏 +Class: Psychic +Pic: Psychic F +Gender: Female +Music: Intense +Double Battle: No +AI: Check Bad Move + +Ralts +Level: 17 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_AISHA === +Name: 诗茉 +Class: Battle Girl +Pic: Battle Girl +Gender: Female +Music: Intense +Double Battle: No +AI: Check Bad Move + +Meditite +Level: 17 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_MAKAYLA === +Name: 铃 +Class: Expert +Pic: Expert F +Gender: Female +Music: Intense +Items: Hyper Potion +Double Battle: No +AI: Basic Trainer + +Roselia +Level: 33 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Medicham +Level: 33 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_FABIAN === +Name: 吉米 +Class: Guitarist +Pic: Guitarist +Gender: Male +Music: Intense +Double Battle: No +AI: Check Bad Move + +Manectric +Level: 26 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_DAYTON === +Name: 淳宏 +Class: Kindler +Pic: Kindler +Gender: Male +Music: Hiker +Double Battle: No +AI: Check Bad Move + +Slugma +Level: 25 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Numel +Level: 25 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_RACHEL === +Name: 观月 +Class: Parasol Lady +Pic: Parasol Lady +Gender: Female +Music: Female +Double Battle: No +AI: Check Bad Move + +Goldeen +Level: 26 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_LEONEL === +Name: 和宏 +Class: Cooltrainer +Pic: Cooltrainer M +Gender: Male +Music: Cool +Items: Hyper Potion +Double Battle: No +AI: Basic Trainer + +Manectric +Level: 30 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe +- Thunder +- Quick Attack +- Thunder Wave + +=== TRAINER_CALLIE === +Name: 风子 +Class: Battle Girl +Pic: Battle Girl +Gender: Female +Music: Intense +Double Battle: No +AI: Check Bad Move + +Meditite +Level: 28 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Makuhita +Level: 28 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_CALE === +Name: 健介 +Class: Bug Maniac +Pic: Bug Maniac +Gender: Male +Music: Suspicious +Double Battle: No +AI: Check Bad Move + +Dustox +Level: 29 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Beautifly +Level: 29 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_MYLES === +Name: 康夫 +Class: Pkmn Breeder +Pic: Pokemon Breeder M +Gender: Male +Music: Male +Double Battle: No +AI: Check Bad Move + +Makuhita +Level: 25 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe + +Wingull +Level: 25 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe + +Tropius +Level: 25 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe + +Zigzagoon +Level: 25 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe + +Electrike +Level: 25 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe + +Numel +Level: 25 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe + +=== TRAINER_PAT === +Name: 春衣 +Class: Pkmn Breeder +Pic: Pokemon Breeder F +Gender: Female +Music: Female +Double Battle: No +AI: Check Bad Move + +Poochyena +Level: 25 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe + +Shroomish +Level: 25 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe + +Electrike +Level: 25 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe + +Marill +Level: 25 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe + +Sandshrew +Level: 25 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe + +Gulpin +Level: 25 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe + +=== TRAINER_CRISTIN_1 === +Name: 登纪子 +Class: Cooltrainer +Pic: Cooltrainer F +Gender: Female +Music: Cool +Items: Hyper Potion +Double Battle: No +AI: Basic Trainer + +Loudred +Level: 29 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +Vigoroth +Level: 29 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +=== TRAINER_MAY_RUSTBORO_TREECKO === +Name: 小遥 +Class: Rival +Pic: May +Gender: Female +Music: Female +Double Battle: No +AI: Basic Trainer + +Lotad +Level: 13 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe + +Torchic +Level: 15 +IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe + +=== TRAINER_MAY_RUSTBORO_TORCHIC === +Name: 小遥 +Class: Rival +Pic: May +Gender: Female +Music: Female +Double Battle: No +AI: Basic Trainer + +Torkoal +Level: 13 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe + +Mudkip +Level: 15 +IVs: 6 HP / 6 Atk / 6 Def / 6 SpA / 6 SpD / 6 Spe + +=== TRAINER_ROXANNE_2 === +Name: 杜娟 +Class: Leader +Pic: Leader Roxanne +Gender: Female +Music: Female +Items: Full Restore / Full Restore / Full Restore +Double Battle: Yes +AI: Basic Trainer + +Golem +Level: 32 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Protect +- Rollout +- Magnitude +- Explosion + +Kabuto @ Sitrus Berry +Level: 35 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Swords Dance +- Ice Beam +- Surf +- Rock Slide + +Onix +Level: 35 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Iron Tail +- Explosion +- Roar +- Rock Slide + +Nosepass @ Sitrus Berry +Level: 37 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Double Team +- Explosion +- Protect +- Rock Slide + +=== TRAINER_ROXANNE_3 === +Name: 杜娟 +Class: Leader +Pic: Leader Roxanne +Gender: Female +Music: Female +Items: Full Restore / Full Restore / Full Restore +Double Battle: Yes +AI: Basic Trainer + +Omanyte +Level: 37 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Protect +- Ice Beam +- Rock Slide +- Surf + +Golem +Level: 37 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Protect +- Rollout +- Magnitude +- Explosion + +Kabutops @ Sitrus Berry +Level: 40 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Swords Dance +- Ice Beam +- Surf +- Rock Slide + +Onix +Level: 40 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Iron Tail +- Explosion +- Roar +- Rock Slide + +Nosepass @ Sitrus Berry +Level: 42 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Double Team +- Explosion +- Protect +- Rock Slide + +=== TRAINER_ROXANNE_4 === +Name: 杜娟 +Class: Leader +Pic: Leader Roxanne +Gender: Female +Music: Female +Items: Full Restore / Full Restore / Full Restore +Double Battle: Yes +AI: Basic Trainer + +Omastar +Level: 42 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Protect +- Ice Beam +- Rock Slide +- Surf + +Golem +Level: 42 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Protect +- Rollout +- Earthquake +- Explosion + +Kabutops @ Sitrus Berry +Level: 45 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Swords Dance +- Ice Beam +- Surf +- Rock Slide + +Onix +Level: 45 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Iron Tail +- Explosion +- Roar +- Rock Slide + +Nosepass @ Sitrus Berry +Level: 47 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Double Team +- Explosion +- Protect +- Rock Slide + +=== TRAINER_ROXANNE_5 === +Name: 杜娟 +Class: Leader +Pic: Leader Roxanne +Gender: Female +Music: Female +Items: Full Restore / Full Restore / Full Restore +Double Battle: Yes +AI: Basic Trainer + +Aerodactyl +Level: 47 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Rock Slide +- Hyper Beam +- Supersonic +- Protect + +Golem +Level: 47 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Focus Punch +- Rollout +- Earthquake +- Explosion + +Omastar +Level: 47 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Protect +- Ice Beam +- Rock Slide +- Surf + +Kabutops @ Sitrus Berry +Level: 50 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Swords Dance +- Ice Beam +- Surf +- Rock Slide + +Steelix +Level: 50 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Iron Tail +- Explosion +- Roar +- Rock Slide + +Nosepass @ Sitrus Berry +Level: 52 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Double Team +- Explosion +- Protect +- Rock Slide + +=== TRAINER_BRAWLY_2 === +Name: 藤树 +Class: Leader +Pic: Leader Brawly +Gender: Male +Music: Male +Items: Full Restore / Full Restore / Full Restore +Double Battle: Yes +AI: Basic Trainer + +Machamp @ Sitrus Berry +Level: 33 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Karate Chop +- Rock Slide +- Focus Punch +- Bulk Up + +Meditite +Level: 33 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Psychic +- Light Screen +- Reflect +- Focus Punch + +Hitmontop +Level: 35 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Pursuit +- Counter +- Protect +- Triple Kick + +Hariyama @ Sitrus Berry +Level: 37 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Fake Out +- Focus Punch +- Belly Drum +- Earthquake + +=== TRAINER_BRAWLY_3 === +Name: 藤树 +Class: Leader +Pic: Leader Brawly +Gender: Male +Music: Male +Items: Full Restore / Full Restore / Full Restore +Double Battle: Yes +AI: Basic Trainer + +Machamp @ Sitrus Berry +Level: 38 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Karate Chop +- Rock Slide +- Focus Punch +- Bulk Up + +Medicham +Level: 38 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Psychic +- Light Screen +- Reflect +- Focus Punch + +Hitmontop +Level: 40 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Pursuit +- Counter +- Protect +- Triple Kick + +Hariyama @ Sitrus Berry +Level: 42 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Fake Out +- Focus Punch +- Belly Drum +- Earthquake + +=== TRAINER_BRAWLY_4 === +Name: 藤树 +Class: Leader +Pic: Leader Brawly +Gender: Male +Music: Male +Items: Full Restore / Full Restore / Full Restore +Double Battle: Yes +AI: Basic Trainer + +Hitmonchan +Level: 40 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Sky Uppercut +- Protect +- Fire Punch +- Ice Punch + +Machamp @ Sitrus Berry +Level: 43 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Karate Chop +- Rock Slide +- Focus Punch +- Bulk Up + +Medicham +Level: 43 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Focus Punch +- Light Screen +- Reflect +- Psychic + +Hitmontop +Level: 45 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Pursuit +- Counter +- Protect +- Triple Kick + +Hariyama @ Sitrus Berry +Level: 47 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Fake Out +- Focus Punch +- Belly Drum +- Earthquake + +=== TRAINER_BRAWLY_5 === +Name: 藤树 +Class: Leader +Pic: Leader Brawly +Gender: Male +Music: Male +Items: Full Restore / Full Restore / Full Restore +Double Battle: Yes +AI: Basic Trainer + +Hitmonlee +Level: 46 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Mega Kick +- Focus Punch +- Earthquake +- Bulk Up + +Hitmonchan +Level: 46 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Sky Uppercut +- Protect +- Fire Punch +- Ice Punch + +Machamp @ Sitrus Berry +Level: 48 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Cross Chop +- Rock Slide +- Focus Punch +- Bulk Up + +Medicham +Level: 48 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Focus Punch +- Light Screen +- Reflect +- Psychic + +Hitmontop +Level: 50 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Pursuit +- Counter +- Protect +- Triple Kick + +Hariyama @ Sitrus Berry +Level: 52 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Fake Out +- Focus Punch +- Belly Drum +- Earthquake + +=== TRAINER_WATTSON_2 === +Name: 铁旋 +Class: Leader +Pic: Leader Wattson +Gender: Male +Music: Male +Items: Full Restore / Full Restore / Full Restore +Double Battle: Yes +AI: Basic Trainer + +Mareep +Level: 36 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Thunder +- Protect +- Thunder Wave +- Light Screen + +Electrode +Level: 36 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Rollout +- Thunder +- Explosion +- Rain Dance + +Magneton @ Sitrus Berry +Level: 38 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Supersonic +- Protect +- Thunder +- Rain Dance + +Manectric @ Sitrus Berry +Level: 40 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Bite +- Thunder Wave +- Thunder +- Protect + +=== TRAINER_WATTSON_3 === +Name: 铁旋 +Class: Leader +Pic: Leader Wattson +Gender: Male +Music: Male +Items: Full Restore / Full Restore / Full Restore +Double Battle: Yes +AI: Basic Trainer + +Pikachu +Level: 39 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Thunder +- Slam +- Rain Dance +- Shock Wave + +Flaaffy +Level: 41 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Thunder +- Protect +- Thunder Wave +- Light Screen + +Electrode +Level: 41 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Rollout +- Thunder +- Explosion +- Rain Dance + +Magneton @ Sitrus Berry +Level: 43 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Supersonic +- Protect +- Thunder +- Rain Dance + +Manectric @ Sitrus Berry +Level: 45 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Bite +- Thunder Wave +- Thunder +- Protect + +=== TRAINER_WATTSON_4 === +Name: 铁旋 +Class: Leader +Pic: Leader Wattson +Gender: Male +Music: Male +Items: Full Restore / Full Restore / Full Restore +Double Battle: Yes +AI: Basic Trainer + +Raichu +Level: 44 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Thunder +- Slam +- Rain Dance +- Protect + +Ampharos +Level: 46 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Thunder +- Protect +- Thunder Wave +- Light Screen + +Electrode +Level: 46 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Rollout +- Thunder +- Explosion +- Rain Dance + +Magneton @ Sitrus Berry +Level: 48 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Supersonic +- Protect +- Thunder +- Rain Dance + +Manectric @ Sitrus Berry +Level: 50 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Bite +- Thunder Wave +- Thunder +- Protect + +=== TRAINER_WATTSON_5 === +Name: 铁旋 +Class: Leader +Pic: Leader Wattson +Gender: Male +Music: Male +Items: Full Restore / Full Restore / Full Restore +Double Battle: Yes +AI: Basic Trainer + +Electabuzz +Level: 50 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Swift +- Focus Punch +- Thunder Punch +- Light Screen + +Raichu +Level: 51 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Thunder +- Slam +- Rain Dance +- Protect + +Ampharos +Level: 51 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Thunder +- Protect +- Thunder Wave +- Light Screen + +Electrode +Level: 53 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Rollout +- Thunder +- Explosion +- Rain Dance + +Magneton @ Sitrus Berry +Level: 53 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Supersonic +- Protect +- Thunder +- Rain Dance + +Manectric @ Sitrus Berry +Level: 55 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Bite +- Thunder Wave +- Thunder +- Protect + +=== TRAINER_FLANNERY_2 === +Name: 亚莎 +Class: Leader +Pic: Leader Flannery +Gender: Female +Music: Female +Items: Full Restore / Full Restore / Full Restore +Double Battle: Yes +AI: Basic Trainer + +Magcargo @ White Herb +Level: 38 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Overheat +- Attract +- Light Screen +- Rock Slide + +Ponyta +Level: 36 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Flamethrower +- Attract +- Solar Beam +- Bounce + +Camerupt @ White Herb +Level: 38 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Overheat +- Sunny Day +- Earthquake +- Attract + +Torkoal @ White Herb +Level: 40 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Overheat +- Sunny Day +- Explosion +- Attract + +=== TRAINER_FLANNERY_3 === +Name: 亚莎 +Class: Leader +Pic: Leader Flannery +Gender: Female +Music: Female +Items: Full Restore / Full Restore / Full Restore +Double Battle: Yes +AI: Basic Trainer + +Growlithe +Level: 41 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Helping Hand +- Flamethrower +- Roar +- Sunny Day + +Magcargo @ White Herb +Level: 43 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Overheat +- Attract +- Light Screen +- Rock Slide + +Ponyta +Level: 41 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Flamethrower +- Attract +- Solar Beam +- Bounce + +Camerupt @ White Herb +Level: 43 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Overheat +- Sunny Day +- Earthquake +- Attract + +Torkoal @ White Herb +Level: 45 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Overheat +- Sunny Day +- Explosion +- Attract + +=== TRAINER_FLANNERY_4 === +Name: 亚莎 +Class: Leader +Pic: Leader Flannery +Gender: Female +Music: Female +Items: Full Restore / Full Restore / Full Restore +Double Battle: Yes +AI: Basic Trainer + +Houndour +Level: 46 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Roar +- Solar Beam +- Taunt +- Sunny Day + +Growlithe +Level: 46 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Helping Hand +- Flamethrower +- Sunny Day +- Roar + +Magcargo @ White Herb +Level: 48 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Overheat +- Attract +- Light Screen +- Rock Slide + +Rapidash +Level: 46 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Flamethrower +- Attract +- Solar Beam +- Bounce + +Camerupt @ White Herb +Level: 48 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Overheat +- Sunny Day +- Earthquake +- Attract + +Torkoal @ White Herb +Level: 50 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Overheat +- Sunny Day +- Explosion +- Attract + +=== TRAINER_FLANNERY_5 === +Name: 亚莎 +Class: Leader +Pic: Leader Flannery +Gender: Female +Music: Female +Items: Full Restore / Full Restore / Full Restore +Double Battle: Yes +AI: Basic Trainer + +Arcanine +Level: 51 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Helping Hand +- Flamethrower +- Sunny Day +- Roar + +Magcargo @ White Herb +Level: 53 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Overheat +- Attract +- Light Screen +- Rock Slide + +Houndoom +Level: 51 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Roar +- Solar Beam +- Taunt +- Sunny Day + +Rapidash +Level: 51 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Flamethrower +- Attract +- Solar Beam +- Bounce + +Camerupt @ White Herb +Level: 53 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Overheat +- Sunny Day +- Earthquake +- Attract + +Torkoal @ White Herb +Level: 55 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Overheat +- Sunny Day +- Explosion +- Attract + +=== TRAINER_NORMAN_2 === +Name: 千里 +Class: Leader +Pic: Leader Norman +Gender: Male +Music: Male +Items: Full Restore / Full Restore / Full Restore +Double Battle: Yes +AI: Basic Trainer + +Chansey +Level: 42 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Light Screen +- Sing +- Skill Swap +- Focus Punch + +Slaking @ Sitrus Berry +Level: 42 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Blizzard +- Shadow Ball +- Double Edge +- Fire Blast + +Spinda +Level: 43 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Teeter Dance +- Skill Swap +- Facade +- Hypnosis + +Slaking @ Sitrus Berry +Level: 45 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Hyper Beam +- Flamethrower +- Thunderbolt +- Shadow Ball + +=== TRAINER_NORMAN_3 === +Name: 千里 +Class: Leader +Pic: Leader Norman +Gender: Male +Music: Male +Items: Full Restore / Full Restore / Full Restore +Double Battle: Yes +AI: Basic Trainer + +Slaking @ Sitrus Berry +Level: 47 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Blizzard +- Shadow Ball +- Double Edge +- Fire Blast + +Chansey +Level: 47 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Light Screen +- Sing +- Skill Swap +- Focus Punch + +Kangaskhan +Level: 45 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Fake Out +- Dizzy Punch +- Endure +- Reversal + +Spinda +Level: 48 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Teeter Dance +- Skill Swap +- Facade +- Hypnosis + +Slaking @ Sitrus Berry +Level: 50 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Hyper Beam +- Flamethrower +- Thunderbolt +- Shadow Ball + +=== TRAINER_NORMAN_4 === +Name: 千里 +Class: Leader +Pic: Leader Norman +Gender: Male +Music: Male +Items: Full Restore / Full Restore / Full Restore +Double Battle: Yes +AI: Basic Trainer + +Slaking @ Sitrus Berry +Level: 52 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Blizzard +- Shadow Ball +- Double Edge +- Fire Blast + +Blissey +Level: 52 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Light Screen +- Sing +- Skill Swap +- Focus Punch + +Kangaskhan +Level: 50 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Fake Out +- Dizzy Punch +- Endure +- Reversal + +Spinda +Level: 53 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Teeter Dance +- Skill Swap +- Facade +- Hypnosis + +Slaking @ Sitrus Berry +Level: 55 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Hyper Beam +- Flamethrower +- Thunderbolt +- Shadow Ball + +=== TRAINER_NORMAN_5 === +Name: 千里 +Class: Leader +Pic: Leader Norman +Gender: Male +Music: Male +Items: Full Restore / Full Restore / Full Restore +Double Battle: Yes +AI: Basic Trainer + +Slaking @ Sitrus Berry +Level: 57 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Blizzard +- Shadow Ball +- Double Edge +- Fire Blast + +Blissey +Level: 57 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Protect +- Sing +- Skill Swap +- Focus Punch + +Kangaskhan +Level: 55 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Fake Out +- Dizzy Punch +- Endure +- Reversal + +Tauros +Level: 57 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Take Down +- Protect +- Fire Blast +- Earthquake + +Spinda +Level: 58 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Teeter Dance +- Skill Swap +- Facade +- Hypnosis + +Slaking @ Sitrus Berry +Level: 60 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Hyper Beam +- Flamethrower +- Thunderbolt +- Shadow Ball + +=== TRAINER_WINONA_2 === +Name: 娜琪 +Class: Leader +Pic: Leader Winona +Gender: Female +Music: Female +Items: Full Restore / Full Restore / Full Restore +Double Battle: Yes +AI: Basic Trainer / Risky + +Dratini @ Sitrus Berry +Level: 40 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Thunder Wave +- Thunderbolt +- Protect +- Ice Beam + +Tropius +Level: 38 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Sunny Day +- Aerial Ace +- Solar Beam +- Earthquake + +Pelipper +Level: 41 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Surf +- Supersonic +- Protect +- Aerial Ace + +Skarmory +Level: 43 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Whirlwind +- Spikes +- Steel Wing +- Aerial Ace + +Altaria @ Chesto Berry +Level: 45 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Aerial Ace +- Rest +- Dragon Dance +- Earthquake + +=== TRAINER_WINONA_3 === +Name: 娜琪 +Class: Leader +Pic: Leader Winona +Gender: Female +Music: Female +Items: Full Restore / Full Restore / Full Restore +Double Battle: Yes +AI: Basic Trainer / Risky + +Hoothoot +Level: 43 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Hypnosis +- Psychic +- Reflect +- Dream Eater + +Tropius +Level: 43 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Sunny Day +- Aerial Ace +- Solar Beam +- Earthquake + +Dragonair @ Sitrus Berry +Level: 45 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Thunder Wave +- Thunderbolt +- Protect +- Ice Beam + +Pelipper +Level: 46 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Surf +- Supersonic +- Protect +- Aerial Ace + +Skarmory +Level: 48 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Whirlwind +- Spikes +- Steel Wing +- Aerial Ace + +Altaria @ Chesto Berry +Level: 50 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Aerial Ace +- Rest +- Dragon Dance +- Earthquake + +=== TRAINER_WINONA_4 === +Name: 娜琪 +Class: Leader +Pic: Leader Winona +Gender: Female +Music: Female +Items: Full Restore / Full Restore / Full Restore +Double Battle: Yes +AI: Basic Trainer / Risky + +Noctowl +Level: 48 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Hypnosis +- Psychic +- Reflect +- Dream Eater + +Tropius +Level: 49 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Sunny Day +- Aerial Ace +- Solar Beam +- Earthquake + +Dragonair @ Sitrus Berry +Level: 50 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Thunder Wave +- Thunderbolt +- Protect +- Ice Beam + +Pelipper +Level: 51 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Surf +- Supersonic +- Protect +- Aerial Ace + +Skarmory +Level: 53 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Whirlwind +- Spikes +- Steel Wing +- Aerial Ace + +Altaria @ Chesto Berry +Level: 55 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Aerial Ace +- Rest +- Dragon Dance +- Earthquake + +=== TRAINER_WINONA_5 === +Name: 娜琪 +Class: Leader +Pic: Leader Winona +Gender: Female +Music: Female +Items: Full Restore / Full Restore / Full Restore +Double Battle: Yes +AI: Basic Trainer / Risky + +Noctowl +Level: 53 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Hypnosis +- Psychic +- Reflect +- Dream Eater + +Tropius +Level: 54 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Sunny Day +- Aerial Ace +- Solar Beam +- Earthquake + +Pelipper +Level: 55 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Surf +- Supersonic +- Protect +- Aerial Ace + +Dragonite @ Sitrus Berry +Level: 55 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Hyper Beam +- Thunderbolt +- Earthquake +- Ice Beam + +Skarmory +Level: 58 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Whirlwind +- Spikes +- Steel Wing +- Aerial Ace + +Altaria @ Chesto Berry +Level: 60 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Sky Attack +- Rest +- Dragon Dance +- Earthquake + +=== TRAINER_TATE_AND_LIZA_2 === +Name: 小枫与小南 +Class: Leader +Pic: Leader Tate And Liza +Gender: Male +Music: Female +Items: Full Restore / Full Restore / Full Restore +Double Battle: Yes +AI: Basic Trainer + +Slowpoke +Level: 48 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Yawn +- Psychic +- Calm Mind +- Protect + +Claydol +Level: 49 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Earthquake +- Ancient Power +- Psychic +- Light Screen + +Xatu @ Chesto Berry +Level: 49 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Psychic +- Rest +- Confuse Ray +- Calm Mind + +Lunatone @ Chesto Berry +Level: 50 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Earthquake +- Psychic +- Rest +- Calm Mind + +Solrock @ Sitrus Berry +Level: 50 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Sunny Day +- Solar Beam +- Psychic +- Flamethrower + +=== TRAINER_TATE_AND_LIZA_3 === +Name: 小枫与小南 +Class: Leader +Pic: Leader Tate And Liza +Gender: Male +Music: Female +Items: Full Restore / Full Restore / Full Restore +Double Battle: Yes +AI: Basic Trainer + +Drowzee +Level: 53 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Hypnosis +- Dream Eater +- Headbutt +- Protect + +Slowpoke +Level: 53 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Yawn +- Psychic +- Calm Mind +- Protect + +Claydol +Level: 54 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Earthquake +- Explosion +- Psychic +- Light Screen + +Xatu @ Chesto Berry +Level: 54 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Psychic +- Rest +- Confuse Ray +- Calm Mind + +Lunatone @ Chesto Berry +Level: 55 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Earthquake +- Psychic +- Rest +- Calm Mind + +Solrock @ Sitrus Berry +Level: 55 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Sunny Day +- Solar Beam +- Psychic +- Flamethrower + +=== TRAINER_TATE_AND_LIZA_4 === +Name: 小枫与小南 +Class: Leader +Pic: Leader Tate And Liza +Gender: Male +Music: Female +Items: Full Restore / Full Restore / Full Restore +Double Battle: Yes +AI: Basic Trainer + +Hypno +Level: 58 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Hypnosis +- Dream Eater +- Headbutt +- Protect + +Claydol +Level: 59 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Earthquake +- Explosion +- Psychic +- Light Screen + +Slowpoke +Level: 58 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Yawn +- Psychic +- Calm Mind +- Protect + +Xatu @ Chesto Berry +Level: 59 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Psychic +- Rest +- Confuse Ray +- Calm Mind + +Lunatone @ Chesto Berry +Level: 60 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Earthquake +- Psychic +- Rest +- Calm Mind + +Solrock @ Sitrus Berry +Level: 60 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Sunny Day +- Solar Beam +- Psychic +- Flamethrower + +=== TRAINER_TATE_AND_LIZA_5 === +Name: 小枫与小南 +Class: Leader +Pic: Leader Tate And Liza +Gender: Male +Music: Female +Items: Full Restore / Full Restore / Full Restore +Double Battle: Yes +AI: Basic Trainer + +Hypno +Level: 63 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Hypnosis +- Dream Eater +- Headbutt +- Protect + +Claydol +Level: 64 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Earthquake +- Explosion +- Psychic +- Light Screen + +Slowking +Level: 63 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Yawn +- Psychic +- Calm Mind +- Protect + +Xatu @ Chesto Berry +Level: 64 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Psychic +- Rest +- Confuse Ray +- Calm Mind + +Lunatone @ Chesto Berry +Level: 65 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Earthquake +- Psychic +- Rest +- Calm Mind + +Solrock @ Sitrus Berry +Level: 65 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Sunny Day +- Solar Beam +- Psychic +- Flamethrower + +=== TRAINER_JUAN_2 === +Name: 亚当 +Class: Leader +Pic: Leader Juan +Gender: Male +Music: Male +Items: Full Restore / Full Restore / Full Restore +Double Battle: Yes +AI: Basic Trainer + +Poliwag +Level: 46 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Hypnosis +- Rain Dance +- Protect +- Hydro Pump + +Whiscash +Level: 46 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Rain Dance +- Water Pulse +- Double Team +- Fissure + +Walrein +Level: 48 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Water Pulse +- Body Slam +- Protect +- Ice Beam + +Crawdaunt @ Chesto Berry +Level: 48 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Rest +- Crabhammer +- Taunt +- Double Team + +Kingdra @ Chesto Berry +Level: 51 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Water Pulse +- Double Team +- Ice Beam +- Rest + +=== TRAINER_JUAN_3 === +Name: 亚当 +Class: Leader +Pic: Leader Juan +Gender: Male +Music: Male +Items: Full Restore / Full Restore / Full Restore +Double Battle: Yes +AI: Basic Trainer + +Poliwhirl +Level: 50 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Hypnosis +- Rain Dance +- Protect +- Hydro Pump + +Whiscash +Level: 51 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Rain Dance +- Water Pulse +- Double Team +- Fissure + +Walrein +Level: 53 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Water Pulse +- Body Slam +- Protect +- Ice Beam + +Crawdaunt @ Chesto Berry +Level: 53 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Rest +- Guillotine +- Taunt +- Double Team + +Kingdra @ Chesto Berry +Level: 56 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Water Pulse +- Double Team +- Ice Beam +- Rest + +=== TRAINER_JUAN_4 === +Name: 亚当 +Class: Leader +Pic: Leader Juan +Gender: Male +Music: Male +Items: Full Restore / Full Restore / Full Restore +Double Battle: Yes +AI: Basic Trainer + +Lapras +Level: 56 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Hydro Pump +- Perish Song +- Ice Beam +- Confuse Ray + +Whiscash +Level: 58 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Rain Dance +- Water Pulse +- Double Team +- Fissure + +Poliwhirl +Level: 56 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Hypnosis +- Rain Dance +- Protect +- Hydro Pump + +Walrein +Level: 58 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Water Pulse +- Body Slam +- Protect +- Ice Beam + +Crawdaunt @ Chesto Berry +Level: 58 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Rest +- Guillotine +- Taunt +- Double Team + +Kingdra @ Chesto Berry +Level: 61 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Water Pulse +- Double Team +- Ice Beam +- Rest + +=== TRAINER_JUAN_5 === +Name: 亚当 +Class: Leader +Pic: Leader Juan +Gender: Male +Music: Male +Items: Full Restore / Full Restore / Full Restore +Double Battle: Yes +AI: Basic Trainer + +Lapras +Level: 61 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Hydro Pump +- Perish Song +- Ice Beam +- Confuse Ray + +Whiscash +Level: 63 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Rain Dance +- Water Pulse +- Double Team +- Fissure + +Politoed +Level: 61 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Hypnosis +- Rain Dance +- Hydro Pump +- Perish Song + +Walrein +Level: 63 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Water Pulse +- Body Slam +- Protect +- Sheer Cold + +Crawdaunt @ Chesto Berry +Level: 63 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Rest +- Guillotine +- Taunt +- Double Team + +Kingdra @ Chesto Berry +Level: 66 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Water Pulse +- Double Team +- Ice Beam +- Rest + +=== TRAINER_ANGELO === +Name: 基宏 +Class: Bug Maniac +Pic: Bug Maniac +Gender: Male +Music: Suspicious +Double Battle: No +AI: Basic Trainer + +Illumise +Level: 17 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe +- Shock Wave +- Quick Attack +- Charm + +Volbeat +Level: 17 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe +- Shock Wave +- Quick Attack +- Confuse Ray + +=== TRAINER_DARIUS === +Name: 诚一 +Class: Bird Keeper +Pic: Bird Keeper +Gender: Male +Music: Cool +Double Battle: No +AI: Basic Trainer + +Tropius +Level: 30 +IVs: 24 HP / 24 Atk / 24 Def / 24 SpA / 24 SpD / 24 Spe + +=== TRAINER_STEVEN === +Name: 大吾 +Class: Rival +Pic: Steven +Gender: Male +Music: Male +Items: Full Restore / Full Restore / Full Restore / Full Restore +Double Battle: No +AI: Basic Trainer + +Skarmory +Level: 77 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Toxic +- Aerial Ace +- Spikes +- Steel Wing + +Claydol +Level: 75 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Reflect +- Light Screen +- Ancient Power +- Earthquake + +Aggron +Level: 76 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Thunder +- Earthquake +- Solar Beam +- Dragon Claw + +Cradily +Level: 76 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Giga Drain +- Ancient Power +- Ingrain +- Confuse Ray + +Armaldo +Level: 76 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Water Pulse +- Ancient Power +- Aerial Ace +- Slash + +Metagross @ Sitrus Berry +Level: 78 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +- Earthquake +- Psychic +- Meteor Mash +- Shadow Ball + +=== TRAINER_ANABEL === +Name: 莉拉 +Class: Salon Maiden +Pic: Salon Maiden Anabel +Gender: Female +Music: Male +Double Battle: No +AI: Basic Trainer + +Beldum +Level: 5 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_TUCKER === +Name: 石南 +Class: Dome Ace +Pic: Dome Ace Tucker +Gender: Male +Music: Male +Double Battle: No +AI: Basic Trainer + +Beldum +Level: 5 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_SPENSER === +Name: 郁金 +Class: Palace Maven +Pic: Palace Maven Spenser +Gender: Male +Music: Male +Double Battle: No +AI: Basic Trainer + +Beldum +Level: 5 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_GRETA === +Name: 黄瓜香 +Class: Arena Tycoon +Pic: Arena Tycoon Greta +Gender: Female +Music: Male +Double Battle: No +AI: Basic Trainer + +Beldum +Level: 5 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_NOLAND === +Name: 达拉 +Class: Factory Head +Pic: Factory Head Noland +Gender: Male +Music: Male +Double Battle: No +AI: Basic Trainer + +Beldum +Level: 5 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_LUCY === +Name: 小蓟 +Class: Pike Queen +Pic: Pike Queen Lucy +Gender: Female +Music: Male +Double Battle: No +AI: Basic Trainer + +Beldum +Level: 5 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_BRANDON === +Name: 神代 +Class: Pyramid King +Pic: Pyramid King Brandon +Gender: Male +Music: Male +Double Battle: No +AI: Basic Trainer + +Beldum +Level: 5 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_ANDRES_2 === +Name: 大次郎 +Class: Ruin Maniac +Pic: Ruin Maniac +Gender: Male +Music: Hiker +Double Battle: No +AI: Check Bad Move + +Sandshrew +Level: 31 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe + +Sandshrew +Level: 31 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe + +=== TRAINER_ANDRES_3 === +Name: 大次郎 +Class: Ruin Maniac +Pic: Ruin Maniac +Gender: Male +Music: Hiker +Double Battle: No +AI: Check Bad Move + +Nosepass +Level: 33 +IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe + +Sandshrew +Level: 33 +IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe + +Sandshrew +Level: 33 +IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe + +=== TRAINER_ANDRES_4 === +Name: 大次郎 +Class: Ruin Maniac +Pic: Ruin Maniac +Gender: Male +Music: Hiker +Double Battle: No +AI: Check Bad Move + +Nosepass +Level: 35 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe + +Sandshrew +Level: 35 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe + +Sandshrew +Level: 35 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe + +=== TRAINER_ANDRES_5 === +Name: 大次郎 +Class: Ruin Maniac +Pic: Ruin Maniac +Gender: Male +Music: Hiker +Double Battle: No +AI: Check Bad Move + +Nosepass +Level: 37 +IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe + +Sandslash +Level: 37 +IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe + +Sandslash +Level: 37 +IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe + +=== TRAINER_CORY_2 === +Name: 典孝 +Class: Sailor +Pic: Sailor +Gender: Male +Music: Male +Double Battle: No +AI: Check Bad Move + +Wingull +Level: 30 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe + +Machop +Level: 30 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe + +Tentacool +Level: 30 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe + +=== TRAINER_CORY_3 === +Name: 典孝 +Class: Sailor +Pic: Sailor +Gender: Male +Music: Male +Double Battle: No +AI: Check Bad Move + +Pelipper +Level: 32 +IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe + +Machop +Level: 32 +IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe + +Tentacool +Level: 32 +IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe + +=== TRAINER_CORY_4 === +Name: 典孝 +Class: Sailor +Pic: Sailor +Gender: Male +Music: Male +Double Battle: No +AI: Check Bad Move + +Pelipper +Level: 34 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe + +Machop +Level: 34 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe + +Tentacruel +Level: 34 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe + +=== TRAINER_CORY_5 === +Name: 典孝 +Class: Sailor +Pic: Sailor +Gender: Male +Music: Male +Double Battle: No +AI: Check Bad Move + +Pelipper +Level: 36 +IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe + +Machoke +Level: 36 +IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe + +Tentacruel +Level: 36 +IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe + +=== TRAINER_PABLO_2 === +Name: 靖宏 +Class: Triathlete +Pic: Swimming Triathlete M +Gender: Male +Music: Swimmer +Double Battle: No +AI: Check Bad Move + +Staryu +Level: 37 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe + +Staryu +Level: 37 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe + +=== TRAINER_PABLO_3 === +Name: 靖宏 +Class: Triathlete +Pic: Swimming Triathlete M +Gender: Male +Music: Swimmer +Double Battle: No +AI: Check Bad Move + +Wingull +Level: 39 +IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe + +Staryu +Level: 39 +IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe + +Staryu +Level: 39 +IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe + +=== TRAINER_PABLO_4 === +Name: 靖宏 +Class: Triathlete +Pic: Swimming Triathlete M +Gender: Male +Music: Swimmer +Double Battle: No +AI: Check Bad Move + +Pelipper +Level: 41 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe + +Staryu +Level: 41 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe + +Staryu +Level: 41 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe + +=== TRAINER_PABLO_5 === +Name: 靖宏 +Class: Triathlete +Pic: Swimming Triathlete M +Gender: Male +Music: Swimmer +Double Battle: No +AI: Check Bad Move + +Pelipper +Level: 43 +IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe + +Starmie +Level: 43 +IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe + +Starmie +Level: 43 +IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe + +=== TRAINER_KOJI_2 === +Name: 铁郎 +Class: Black Belt +Pic: Black Belt +Gender: Male +Music: Intense +Double Battle: No +AI: Check Bad Move + +Machoke +Level: 37 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe + +Machoke +Level: 37 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe + +=== TRAINER_KOJI_3 === +Name: 铁郎 +Class: Black Belt +Pic: Black Belt +Gender: Male +Music: Intense +Double Battle: No +AI: Check Bad Move + +Makuhita +Level: 39 +IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe + +Machoke +Level: 39 +IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe + +Machoke +Level: 39 +IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe + +=== TRAINER_KOJI_4 === +Name: 铁郎 +Class: Black Belt +Pic: Black Belt +Gender: Male +Music: Intense +Double Battle: No +AI: Check Bad Move + +Hariyama +Level: 41 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe + +Machoke +Level: 41 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe + +Machoke +Level: 41 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe + +=== TRAINER_KOJI_5 === +Name: 铁郎 +Class: Black Belt +Pic: Black Belt +Gender: Male +Music: Intense +Double Battle: No +AI: Check Bad Move + +Hariyama +Level: 43 +IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe + +Machamp +Level: 43 +IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe + +Machamp +Level: 43 +IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe + +=== TRAINER_CRISTIN_2 === +Name: 登纪子 +Class: Cooltrainer +Pic: Cooltrainer F +Gender: Female +Music: Cool +Items: Hyper Potion +Double Battle: No +AI: Basic Trainer + +Loudred +Level: 35 +IVs: 13 HP / 13 Atk / 13 Def / 13 SpA / 13 SpD / 13 Spe + +Vigoroth +Level: 35 +IVs: 13 HP / 13 Atk / 13 Def / 13 SpA / 13 SpD / 13 Spe + +=== TRAINER_CRISTIN_3 === +Name: 登纪子 +Class: Cooltrainer +Pic: Cooltrainer F +Gender: Female +Music: Cool +Items: Hyper Potion +Double Battle: No +AI: Basic Trainer + +Spinda +Level: 37 +IVs: 14 HP / 14 Atk / 14 Def / 14 SpA / 14 SpD / 14 Spe + +Loudred +Level: 37 +IVs: 14 HP / 14 Atk / 14 Def / 14 SpA / 14 SpD / 14 Spe + +Vigoroth +Level: 37 +IVs: 14 HP / 14 Atk / 14 Def / 14 SpA / 14 SpD / 14 Spe + +=== TRAINER_CRISTIN_4 === +Name: 登纪子 +Class: Cooltrainer +Pic: Cooltrainer F +Gender: Female +Music: Cool +Items: Hyper Potion +Double Battle: No +AI: Basic Trainer + +Spinda +Level: 39 +IVs: 15 HP / 15 Atk / 15 Def / 15 SpA / 15 SpD / 15 Spe + +Loudred +Level: 39 +IVs: 15 HP / 15 Atk / 15 Def / 15 SpA / 15 SpD / 15 Spe + +Vigoroth +Level: 39 +IVs: 12 HP / 12 Atk / 12 Def / 12 SpA / 12 SpD / 12 Spe + +=== TRAINER_CRISTIN_5 === +Name: 登纪子 +Class: Cooltrainer +Pic: Cooltrainer F +Gender: Female +Music: Cool +Items: Hyper Potion +Double Battle: No +AI: Basic Trainer + +Spinda +Level: 41 +IVs: 17 HP / 17 Atk / 17 Def / 17 SpA / 17 SpD / 17 Spe + +Exploud +Level: 41 +IVs: 17 HP / 17 Atk / 17 Def / 17 SpA / 17 SpD / 17 Spe + +Slaking +Level: 41 +IVs: 17 HP / 17 Atk / 17 Def / 17 SpA / 17 SpD / 17 Spe + +=== TRAINER_FERNANDO_2 === +Name: 乔 +Class: Guitarist +Pic: Guitarist +Gender: Male +Music: Intense +Double Battle: No +AI: Check Bad Move + +Electrike +Level: 35 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe + +Electrike +Level: 35 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe + +Loudred +Level: 35 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe + +=== TRAINER_FERNANDO_3 === +Name: 乔 +Class: Guitarist +Pic: Guitarist +Gender: Male +Music: Intense +Double Battle: No +AI: Check Bad Move + +Electrike +Level: 37 +IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe + +Manectric +Level: 37 +IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe + +Loudred +Level: 37 +IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe + +=== TRAINER_FERNANDO_4 === +Name: 乔 +Class: Guitarist +Pic: Guitarist +Gender: Male +Music: Intense +Double Battle: No +AI: Check Bad Move + +Manectric +Level: 39 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe + +Manectric +Level: 39 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe + +Loudred +Level: 39 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe + +=== TRAINER_FERNANDO_5 === +Name: 乔 +Class: Guitarist +Pic: Guitarist +Gender: Male +Music: Intense +Double Battle: No +AI: Check Bad Move + +Manectric +Level: 41 +IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe + +Manectric +Level: 41 +IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe + +Exploud +Level: 41 +IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe + +=== TRAINER_SAWYER_2 === +Name: 雅彦 +Class: Hiker +Pic: Hiker +Gender: Male +Music: Hiker +Double Battle: No +AI: Basic Trainer + +Geodude +Level: 26 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe + +Numel +Level: 26 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe + +=== TRAINER_SAWYER_3 === +Name: 雅彦 +Class: Hiker +Pic: Hiker +Gender: Male +Music: Hiker +Double Battle: No +AI: Basic Trainer + +Machop +Level: 28 +IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe + +Numel +Level: 28 +IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe + +Graveler +Level: 28 +IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe + +=== TRAINER_SAWYER_4 === +Name: 雅彦 +Class: Hiker +Pic: Hiker +Gender: Male +Music: Hiker +Double Battle: No +AI: Basic Trainer + +Machop +Level: 30 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe + +Numel +Level: 30 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe + +Graveler +Level: 30 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe + +=== TRAINER_SAWYER_5 === +Name: 雅彦 +Class: Hiker +Pic: Hiker +Gender: Male +Music: Hiker +Double Battle: No +AI: Basic Trainer + +Machoke +Level: 33 +IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe + +Camerupt +Level: 33 +IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe + +Golem +Level: 33 +IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe + +=== TRAINER_GABRIELLE_2 === +Name: 福美 +Class: Pkmn Breeder +Pic: Pokemon Breeder F +Gender: Female +Music: Female +Double Battle: No +AI: Check Bad Move + +Skitty +Level: 31 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe + +Mightyena +Level: 31 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe + +Zigzagoon +Level: 31 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe + +Lotad +Level: 31 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe + +Seedot +Level: 31 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe + +Taillow +Level: 31 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe + +=== TRAINER_GABRIELLE_3 === +Name: 福美 +Class: Pkmn Breeder +Pic: Pokemon Breeder F +Gender: Female +Music: Female +Double Battle: No +AI: Check Bad Move + +Skitty +Level: 33 +IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe + +Mightyena +Level: 33 +IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe + +Linoone +Level: 33 +IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe + +Lombre +Level: 33 +IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe + +Nuzleaf +Level: 33 +IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe + +Taillow +Level: 33 +IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe + +=== TRAINER_GABRIELLE_4 === +Name: 福美 +Class: Pkmn Breeder +Pic: Pokemon Breeder F +Gender: Female +Music: Female +Double Battle: No +AI: Check Bad Move + +Delcatty +Level: 35 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe + +Mightyena +Level: 35 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe + +Linoone +Level: 35 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe + +Lombre +Level: 35 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe + +Nuzleaf +Level: 35 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe + +Swellow +Level: 35 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe + +=== TRAINER_GABRIELLE_5 === +Name: 福美 +Class: Pkmn Breeder +Pic: Pokemon Breeder F +Gender: Female +Music: Female +Double Battle: No +AI: Check Bad Move + +Delcatty +Level: 37 +IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe + +Mightyena +Level: 37 +IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe + +Linoone +Level: 37 +IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe + +Ludicolo +Level: 37 +IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe + +Shiftry +Level: 37 +IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe + +Swellow +Level: 37 +IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe + +=== TRAINER_THALIA_2 === +Name: 睫 +Class: Beauty +Pic: Beauty +Gender: Female +Music: Female +Double Battle: No +AI: Check Bad Move + +Wailmer +Level: 34 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe + +Horsea +Level: 34 +IVs: 1 HP / 1 Atk / 1 Def / 1 SpA / 1 SpD / 1 Spe + +=== TRAINER_THALIA_3 === +Name: 睫 +Class: Beauty +Pic: Beauty +Gender: Female +Music: Female +Double Battle: No +AI: Check Bad Move + +Luvdisc +Level: 36 +IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe + +Wailmer +Level: 36 +IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe + +Seadra +Level: 36 +IVs: 2 HP / 2 Atk / 2 Def / 2 SpA / 2 SpD / 2 Spe + +=== TRAINER_THALIA_4 === +Name: 睫 +Class: Beauty +Pic: Beauty +Gender: Female +Music: Female +Double Battle: No +AI: Check Bad Move + +Luvdisc +Level: 38 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe + +Wailmer +Level: 38 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe + +Seadra +Level: 38 +IVs: 3 HP / 3 Atk / 3 Def / 3 SpA / 3 SpD / 3 Spe + +=== TRAINER_THALIA_5 === +Name: 睫 +Class: Beauty +Pic: Beauty +Gender: Female +Music: Female +Double Battle: No +AI: Check Bad Move + +Luvdisc +Level: 40 +IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe + +Wailord +Level: 40 +IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe + +Kingdra +Level: 40 +IVs: 4 HP / 4 Atk / 4 Def / 4 SpA / 4 SpD / 4 Spe + +=== TRAINER_MARIELA === +Name: 未羽 +Class: Psychic +Pic: Psychic F +Gender: Female +Music: Intense +Double Battle: No + +Chimecho +Level: 41 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_ALVARO === +Name: 信也 +Class: Psychic +Pic: Psychic M +Gender: Male +Music: Intense +Double Battle: No + +Banette +Level: 41 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Kadabra +Level: 41 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_EVERETT === +Name: 道格 +Class: Gentleman +Pic: Gentleman +Gender: Male +Music: Rich +Double Battle: No + +Wobbuffet +Level: 41 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_RED === +Name: 赤红 +Class: Rival +Pic: Red +Gender: Male +Music: Male +Double Battle: No + +Charmander +Level: 5 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_LEAF === +Name: 叶子 +Class: Rival +Pic: Leaf +Gender: Female +Music: Male +Double Battle: No + +Bulbasaur +Level: 5 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_BRENDAN_PLACEHOLDER === +Name: 小悠 +Class: RS Protag +Pic: RS Brendan +Gender: Male +Music: Male +Double Battle: No + +Groudon +Level: 5 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== TRAINER_MAY_PLACEHOLDER === +Name: 小遥 +Class: RS Protag +Pic: RS May +Gender: Female +Music: Male +Double Battle: No + +Kyogre +Level: 5 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe diff --git a/src/data/wild_encounters.json b/src/data/wild_encounters.json index 0b30c0f65b..053c4c095f 100755 --- a/src/data/wild_encounters.json +++ b/src/data/wild_encounters.json @@ -7,30 +7,71 @@ { "type": "land_mons", "encounter_rates": [ - 20, 20, 10, 10, 10, 10, 5, 5, 4, 4, 1, 1 + 20, + 20, + 10, + 10, + 10, + 10, + 5, + 5, + 4, + 4, + 1, + 1 ] }, { "type": "water_mons", "encounter_rates": [ - 60, 30, 5, 4, 1 + 60, + 30, + 5, + 4, + 1 ] }, { "type": "rock_smash_mons", "encounter_rates": [ - 60, 30, 5, 4, 1 + 60, + 30, + 5, + 4, + 1 ] }, { "type": "fishing_mons", "encounter_rates": [ - 70, 30, 60, 20, 20, 40, 40, 15, 4, 1 + 70, + 30, + 60, + 20, + 20, + 40, + 40, + 15, + 4, + 1 ], "groups": { - "old_rod": [0, 1], - "good_rod": [2, 3, 4], - "super_rod": [5, 6, 7, 8, 9] + "old_rod": [ + 0, + 1 + ], + "good_rod": [ + 2, + 3, + 4 + ], + "super_rod": [ + 5, + 6, + 7, + 8, + 9 + ] } } ], diff --git a/src/daycare.c b/src/daycare.c index 2dec8a81f1..439c0db3d6 100644 --- a/src/daycare.c +++ b/src/daycare.c @@ -24,7 +24,6 @@ #include "regions.h" #include "constants/form_change_types.h" #include "constants/items.h" -#include "constants/hold_effects.h" #include "constants/moves.h" #include "constants/region_map_sections.h" @@ -505,6 +504,8 @@ static u16 GetEggSpecies(u16 species) found = FALSE; for (j = 1; j < NUM_SPECIES; j++) { + if (!IsSpeciesEnabled(j)) + continue; const struct Evolution *evolutions = GetSpeciesEvolutions(j); if (evolutions == NULL) continue; @@ -741,10 +742,10 @@ static void InheritPokeball(struct Pokemon *egg, struct BoxPokemon *father, stru static void InheritAbility(struct Pokemon *egg, struct BoxPokemon *father, struct BoxPokemon *mother) { - u16 fatherAbility = GetBoxMonData(father, MON_DATA_ABILITY_NUM); - u16 motherAbility = GetBoxMonData(mother, MON_DATA_ABILITY_NUM); + enum Ability fatherAbility = GetBoxMonData(father, MON_DATA_ABILITY_NUM); + enum Ability motherAbility = GetBoxMonData(mother, MON_DATA_ABILITY_NUM); u16 motherSpecies = GetBoxMonData(mother, MON_DATA_SPECIES); - u16 inheritAbility = motherAbility; + enum Ability inheritAbility = motherAbility; if (motherSpecies == SPECIES_DITTO) { diff --git a/src/debug.c b/src/debug.c index f01d560a36..c9a0f8a022 100644 --- a/src/debug.c +++ b/src/debug.c @@ -29,6 +29,7 @@ #include "international_string_util.h" #include "item.h" #include "item_icon.h" +#include "item_use.h" #include "list_menu.h" #include "m4a.h" #include "main.h" @@ -106,8 +107,8 @@ enum FlagsVarsDebugMenu DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_COLLISION, DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_ENCOUNTER, DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_TRAINER_SEE, - DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_BAG_USE, DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_CATCHING, + DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_BAG_USE, }; enum DebugBattleType @@ -237,6 +238,8 @@ static void Debug_DestroyMenu(u8 taskId); static void DebugAction_Cancel(u8 taskId); static void DebugAction_DestroyExtraWindow(u8 taskId); static void Debug_RefreshListMenu(u8 taskId); +static u8 DebugNativeStep_CreateDebugWindow(void); +static void DebugNativeStep_CloseDebugWindow(u8 taskId); static void DebugAction_OpenSubMenu(u8 taskId, const struct DebugMenuOption *items); static void DebugAction_OpenSubMenuFlagsVars(u8 taskId, const struct DebugMenuOption *items); @@ -342,12 +345,15 @@ static void DebugAction_Player_Id(u8 taskId); extern const u8 Debug_FlagsNotSetOverworldConfigMessage[]; extern const u8 Debug_FlagsNotSetBattleConfigMessage[]; +extern const u8 Debug_VarsNotSetBattleConfigMessage[]; extern const u8 Debug_FlagsAndVarNotSetBattleConfigMessage[]; extern const u8 Debug_EventScript_FontTest[]; extern const u8 Debug_EventScript_CheckEVs[]; extern const u8 Debug_EventScript_CheckIVs[]; extern const u8 Debug_EventScript_InflictStatus1[]; extern const u8 Debug_EventScript_SetHiddenNature[]; +extern const u8 Debug_EventScript_SetAbility[]; +extern const u8 Debug_EventScript_SetFriendship[]; extern const u8 Debug_EventScript_Script_1[]; extern const u8 Debug_EventScript_Script_2[]; extern const u8 Debug_EventScript_Script_3[]; @@ -380,7 +386,7 @@ extern const u8 Debug_EventScript_FakeRTCNotEnabled[]; extern const u8 Debug_BerryPestsDisabled[]; extern const u8 Debug_BerryWeedsDisabled[]; -extern const u8 FallarborTown_MoveRelearnersHouse_EventScript_ChooseMon[]; +extern const u8 Common_EventScript_MoveRelearner[]; #include "data/map_group_count.h" @@ -571,11 +577,13 @@ static const struct DebugMenuOption sDebugMenu_Actions_PCBag[] = static const struct DebugMenuOption sDebugMenu_Actions_Party[] = { - { COMPOUND_STRING("回忆技能"), DebugAction_ExecuteScript, FallarborTown_MoveRelearnersHouse_EventScript_ChooseMon }, + { COMPOUND_STRING("回忆技能"), DebugAction_ExecuteScript, Common_EventScript_MoveRelearner }, { COMPOUND_STRING("孵化宝可梦蛋"), DebugAction_ExecuteScript, Debug_HatchAnEgg }, { COMPOUND_STRING("回复同行宝可梦"), DebugAction_Party_HealParty }, { COMPOUND_STRING("造成异常状态1"), DebugAction_ExecuteScript, Debug_EventScript_InflictStatus1 }, { COMPOUND_STRING("设置隐藏特性"), DebugAction_ExecuteScript, Debug_EventScript_SetHiddenNature }, + { COMPOUND_STRING("设置亲密度"), DebugAction_ExecuteScript, Debug_EventScript_SetFriendship }, + { COMPOUND_STRING("设置特性"), DebugAction_ExecuteScript, Debug_EventScript_SetAbility }, { COMPOUND_STRING("确认努力值"), DebugAction_ExecuteScript, Debug_EventScript_CheckEVs }, { COMPOUND_STRING("确认个体值"), DebugAction_ExecuteScript, Debug_EventScript_CheckIVs }, { COMPOUND_STRING("清空同行宝可梦"), DebugAction_Party_ClearParty }, @@ -639,23 +647,30 @@ static const struct DebugMenuOption sDebugMenu_Actions_Flags[] = [DEBUG_FLAGVAR_MENU_ITEM_VARS] = { COMPOUND_STRING("设定某个变量…"), DebugAction_FlagsVars_Vars }, [DEBUG_FLAGVAR_MENU_ITEM_DEXFLAGS_ALL] = { COMPOUND_STRING("图鉴标志全部设定"), DebugAction_FlagsVars_PokedexFlags_All }, [DEBUG_FLAGVAR_MENU_ITEM_DEXFLAGS_RESET] = { COMPOUND_STRING("图鉴标志全部重置"), DebugAction_FlagsVars_PokedexFlags_Reset }, - [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_POKEDEX] = { COMPOUND_STRING("Toggle {STR_VAR_1}图鉴"), DebugAction_ToggleFlag, DebugAction_FlagsVars_SwitchDex }, - [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_NATDEX] = { COMPOUND_STRING("Toggle {STR_VAR_1}全国图鉴"), DebugAction_ToggleFlag, DebugAction_FlagsVars_SwitchNatDex }, - [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_POKENAV] = { COMPOUND_STRING("Toggle {STR_VAR_1}导航器"), DebugAction_ToggleFlag, DebugAction_FlagsVars_SwitchPokeNav }, - [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_MATCH_CALL] = { COMPOUND_STRING("Toggle {STR_VAR_1}对战寻呼"), DebugAction_ToggleFlag, DebugAction_FlagsVars_SwitchMatchCall }, - [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_RUN_SHOES] = { COMPOUND_STRING("Toggle {STR_VAR_1}跑步鞋"), DebugAction_ToggleFlag, DebugAction_FlagsVars_RunningShoes }, - [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_LOCATIONS] = { COMPOUND_STRING("Toggle {STR_VAR_1}飞翔标志"), DebugAction_ToggleFlag, DebugAction_FlagsVars_ToggleFlyFlags }, - [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_BADGES_ALL] = { COMPOUND_STRING("Toggle {STR_VAR_1}全部徽章"), DebugAction_ToggleFlag, DebugAction_FlagsVars_ToggleBadgeFlags }, - [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_GAME_CLEAR] = { COMPOUND_STRING("Toggle {STR_VAR_1}通关游戏"), DebugAction_ToggleFlag, DebugAction_FlagsVars_ToggleGameClear }, - [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_FRONTIER_PASS] = { COMPOUND_STRING("Toggle {STR_VAR_1}开拓通行证"), DebugAction_ToggleFlag, DebugAction_FlagsVars_ToggleFrontierPass }, - [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_COLLISION] = { COMPOUND_STRING("Toggle {STR_VAR_1}无视地形阻碍"), DebugAction_ToggleFlag, DebugAction_FlagsVars_CollisionOnOff }, - [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_ENCOUNTER] = { COMPOUND_STRING("Toggle {STR_VAR_1}不再遭遇宝可梦"), DebugAction_ToggleFlag, DebugAction_FlagsVars_EncounterOnOff }, - [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_TRAINER_SEE] = { COMPOUND_STRING("Toggle {STR_VAR_1}对训练家隐身"), DebugAction_ToggleFlag, DebugAction_FlagsVars_TrainerSeeOnOff }, - [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_BAG_USE] = { COMPOUND_STRING("Toggle {STR_VAR_1}无法打开包包"), DebugAction_ToggleFlag, DebugAction_FlagsVars_BagUseOnOff }, - [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_CATCHING] = { COMPOUND_STRING("Toggle {STR_VAR_1}无法捕捉宝可梦"), DebugAction_ToggleFlag, DebugAction_FlagsVars_CatchingOnOff }, + [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_POKEDEX] = { COMPOUND_STRING("开关{STR_VAR_1}图鉴"), DebugAction_ToggleFlag, DebugAction_FlagsVars_SwitchDex }, + [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_NATDEX] = { COMPOUND_STRING("开关{STR_VAR_1}全国图鉴"), DebugAction_ToggleFlag, DebugAction_FlagsVars_SwitchNatDex }, + [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_POKENAV] = { COMPOUND_STRING("开关{STR_VAR_1}导航器"), DebugAction_ToggleFlag, DebugAction_FlagsVars_SwitchPokeNav }, + [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_MATCH_CALL] = { COMPOUND_STRING("开关{STR_VAR_1}对战寻呼"), DebugAction_ToggleFlag, DebugAction_FlagsVars_SwitchMatchCall }, + [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_RUN_SHOES] = { COMPOUND_STRING("开关{STR_VAR_1}跑步鞋"), DebugAction_ToggleFlag, DebugAction_FlagsVars_RunningShoes }, + [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_LOCATIONS] = { COMPOUND_STRING("开关{STR_VAR_1}飞翔标志"), DebugAction_ToggleFlag, DebugAction_FlagsVars_ToggleFlyFlags }, + [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_BADGES_ALL] = { COMPOUND_STRING("开关{STR_VAR_1}全部徽章"), DebugAction_ToggleFlag, DebugAction_FlagsVars_ToggleBadgeFlags }, + [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_GAME_CLEAR] = { COMPOUND_STRING("开关{STR_VAR_1}通关游戏"), DebugAction_ToggleFlag, DebugAction_FlagsVars_ToggleGameClear }, + [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_FRONTIER_PASS] = { COMPOUND_STRING("开关{STR_VAR_1}开拓通行证"), DebugAction_ToggleFlag, DebugAction_FlagsVars_ToggleFrontierPass }, + [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_COLLISION] = { COMPOUND_STRING("开关{STR_VAR_1}无视地形阻碍"), DebugAction_ToggleFlag, DebugAction_FlagsVars_CollisionOnOff }, + [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_ENCOUNTER] = { COMPOUND_STRING("开关{STR_VAR_1}不再遭遇宝可梦"), DebugAction_ToggleFlag, DebugAction_FlagsVars_EncounterOnOff }, + [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_TRAINER_SEE] = { COMPOUND_STRING("开关{STR_VAR_1}对训练家隐身"), DebugAction_ToggleFlag, DebugAction_FlagsVars_TrainerSeeOnOff }, + [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_CATCHING] = { COMPOUND_STRING("开关{STR_VAR_1}无法捕捉宝可梦"), DebugAction_ToggleFlag, DebugAction_FlagsVars_CatchingOnOff }, + [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_BAG_USE] = { COMPOUND_STRING("开关{STR_VAR_1}无法打开包包"), DebugAction_ToggleFlag, DebugAction_FlagsVars_BagUseOnOff }, { NULL } }; +static const u8 *const sDebugMenu_Actions_BagUse_Options[] = +{ + COMPOUND_STRING("无法打开包包: {STR_VAR_1}未启用"), + COMPOUND_STRING("无法打开包包: {STR_VAR_1}仅对战时"), + COMPOUND_STRING("无法打开包包: {STR_VAR_1}启用"), +}; + static const struct DebugMenuOption sDebugMenu_Actions_Main[] = { { COMPOUND_STRING("常用功能…"), DebugAction_OpenSubMenu, sDebugMenu_Actions_Utilities, }, @@ -932,6 +947,30 @@ static void DebugAction_DestroyExtraWindow(u8 taskId) UnfreezeObjectEvents(); } +static u8 DebugNativeStep_CreateDebugWindow(void) +{ + u8 windowId; + + LockPlayerFieldControls(); + FreezeObjectEvents(); + HideMapNamePopUpWindow(); + LoadMessageBoxAndBorderGfx(); + windowId = AddWindow(&sDebugMenuWindowTemplateExtra); + DrawStdWindowFrame(windowId, FALSE); + CopyWindowToVram(windowId, COPYWIN_FULL); + + return windowId; +} + +static void DebugNativeStep_CloseDebugWindow(u8 taskId) +{ + ClearStdWindowAndFrame(gTasks[taskId].tSubWindowId, TRUE); + RemoveWindow(gTasks[taskId].tSubWindowId); + DestroyTask(taskId); + UnfreezeObjectEvents(); + UnlockPlayerFieldControls(); +} + static const u16 sLocationFlags[] = { FLAG_VISITED_LITTLEROOT_TOWN, @@ -956,7 +995,7 @@ static const u16 sLocationFlags[] = static u8 Debug_CheckToggleFlags(u8 id) { - u8 result = FALSE; + bool32 result = FALSE; switch (id) { @@ -1018,16 +1057,14 @@ static u8 Debug_CheckToggleFlags(u8 id) result = FlagGet(OW_FLAG_NO_TRAINER_SEE); break; #endif - #if B_FLAG_NO_BAG_USE != 0 - case DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_BAG_USE: - result = FlagGet(B_FLAG_NO_BAG_USE); - break; - #endif #if B_FLAG_NO_CATCHING != 0 case DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_CATCHING: result = FlagGet(B_FLAG_NO_CATCHING); break; #endif + case DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_BAG_USE: + result = VarGet(B_VAR_NO_BAG_USE); + break; default: result = 0xFF; break; @@ -1054,7 +1091,10 @@ static u8 Debug_GenerateListMenuNames(void) if (sDebugMenuListData->listId == 1) { flagResult = Debug_CheckToggleFlags(i); - name = sDebugMenu_Actions_Flags[i].text; + if (i == DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_BAG_USE) + name = sDebugMenu_Actions_BagUse_Options[flagResult]; + else + name = sDebugMenu_Actions_Flags[i].text; } if (flagResult == 0xFF) @@ -2006,14 +2046,11 @@ static void DebugAction_FlagsVars_TrainerSeeOnOff(u8 taskId) static void DebugAction_FlagsVars_BagUseOnOff(u8 taskId) { -#if B_FLAG_NO_BAG_USE == 0 - Debug_DestroyMenu_Full_Script(taskId, Debug_FlagsNotSetBattleConfigMessage); +#if B_VAR_NO_BAG_USE < VARS_START || B_VAR_NO_BAG_USE > VARS_END + Debug_DestroyMenu_Full_Script(taskId, Debug_VarsNotSetBattleConfigMessage); #else - if (FlagGet(B_FLAG_NO_BAG_USE)) - PlaySE(SE_PC_OFF); - else - PlaySE(SE_PC_LOGIN); - FlagToggle(B_FLAG_NO_BAG_USE); + PlaySE(SE_SELECT); + VarSet(B_VAR_NO_BAG_USE, (VarGet(B_VAR_NO_BAG_USE) + 1) % 3); #endif } @@ -2040,6 +2077,17 @@ static void Debug_Display_ItemInfo(u32 itemId, u32 digit, u8 windowId) { StringCopy(gStringVar2, gText_DigitIndicator[digit]); u8* end = CopyItemName(itemId, gStringVar1); + u16 moveId = ItemIdToBattleMoveId(itemId); + if (moveId != MOVE_NONE) + { + end = StringCopy(end, gText_Space); + end = StringCopy(end, GetMoveName(moveId)); + } + else if (CheckIfItemIsTMHMOrEvolutionStone(itemId) == 1) + { + end = StringCopy(end, COMPOUND_STRING(" None")); + } + WrapFontIdToFit(gStringVar1, end, DEBUG_MENU_FONT, WindowWidthPx(windowId)); StringCopyPadded(gStringVar1, gStringVar1, CHAR_SPACE, 15); ConvertIntToDecimalStringN(gStringVar3, itemId, STR_CONV_MODE_LEADING_ZEROS, DEBUG_NUMBER_DIGITS_ITEMS); @@ -2386,7 +2434,7 @@ static void DebugAction_Give_Pokemon_SelectShiny(u8 taskId) } } -static void Debug_Display_Ability(u32 abilityId, u32 digit, u8 windowId)//(u32 natureId, u32 digit, u8 windowId) +static void Debug_Display_Ability(enum Ability abilityId, u32 digit, u8 windowId)//(u32 natureId, u32 digit, u8 windowId) { StringCopy(gStringVar2, gText_DigitIndicator[digit]); ConvertIntToDecimalStringN(gStringVar3, abilityId, STR_CONV_MODE_LEADING_ZEROS, 2); @@ -2425,7 +2473,7 @@ static void DebugAction_Give_Pokemon_SelectNature(u8 taskId) gTasks[taskId].tInput = 0; gTasks[taskId].tDigit = 0; - u32 abilityId = GetAbilityBySpecies(sDebugMonData->species, 0); + enum Ability abilityId = GetAbilityBySpecies(sDebugMonData->species, 0); Debug_Display_Ability(abilityId, gTasks[taskId].tDigit, gTasks[taskId].tSubWindowId); gTasks[taskId].func = DebugAction_Give_Pokemon_SelectAbility; @@ -2474,7 +2522,7 @@ static void DebugAction_Give_Pokemon_SelectAbility(u8 taskId) { i++; } - u32 abilityId = GetAbilityBySpecies(sDebugMonData->species, gTasks[taskId].tInput - i); + enum Ability abilityId = GetAbilityBySpecies(sDebugMonData->species, gTasks[taskId].tInput - i); Debug_Display_Ability(abilityId, gTasks[taskId].tDigit, gTasks[taskId].tSubWindowId); } @@ -3005,6 +3053,9 @@ static void DebugAction_Give_MaxMoney(u8 taskId) static void DebugAction_Give_MaxCoins(u8 taskId) { SetCoins(MAX_COINS); + + if (!CheckBagHasItem(ITEM_COIN_CASE, 1)) + AddBagItem(ITEM_COIN_CASE, 1); } static void DebugAction_Give_MaxBattlePoints(u8 taskId) @@ -3387,11 +3438,6 @@ static void DebugAction_DestroyFollowerNPC(u8 taskId) #undef tCurrentSong -#undef tMenuTaskId -#undef tWindowId -#undef tSubWindowId -#undef tInput -#undef tDigit #define SOUND_LIST_BGM \ X(MUS_LITTLEROOT_TEST) \ @@ -4015,6 +4061,81 @@ static void DebugAction_Party_HealParty(u8 taskId) Debug_DestroyMenu_Full(taskId); } +void DebugNative_GetAbilityNames(void) +{ + u32 species = GetMonData(&gPlayerParty[gSpecialVar_0x8004], MON_DATA_SPECIES); + StringCopy(gStringVar1, gAbilitiesInfo[GetAbilityBySpecies(species, 0)].name); + StringCopy(gStringVar2, gAbilitiesInfo[GetAbilityBySpecies(species, 1)].name); + StringCopy(gStringVar3, gAbilitiesInfo[GetAbilityBySpecies(species, 2)].name); +} + +#define tPartyId data[5] +#define tFriendship data[6] + +static void Debug_Display_FriendshipInfo(s32 oldFriendship, s32 newFriendship, u32 digit, u8 windowId) +{ + ConvertIntToDecimalStringN(gStringVar1, oldFriendship, STR_CONV_MODE_LEADING_ZEROS, 3); + ConvertIntToDecimalStringN(gStringVar2, newFriendship, STR_CONV_MODE_LEADING_ZEROS, 3); + StringCopy(gStringVar3, gText_DigitIndicator[digit]); + StringExpandPlaceholders(gStringVar4, COMPOUND_STRING("Friendship:\n{STR_VAR_1} {RIGHT_ARROW} {STR_VAR_2}\n\n{STR_VAR_3}")); + AddTextPrinterParameterized(windowId, DEBUG_MENU_FONT, gStringVar4, 0, 0, 0, NULL); +} + +static void DebugNativeStep_Party_SetFriendshipSelect(u8 taskId) +{ + if (JOY_NEW(A_BUTTON)) + { + PlaySE(SE_SELECT); + gTasks[taskId].tFriendship = gTasks[taskId].tInput; + SetMonData(&gPlayerParty[gTasks[taskId].tPartyId], MON_DATA_FRIENDSHIP, &gTasks[taskId].tInput); + } + else if (JOY_NEW(B_BUTTON)) + { + PlaySE(SE_SELECT); + DebugNativeStep_CloseDebugWindow(taskId); + return; + } + + Debug_HandleInput_Numeric(taskId, 0, 255, 3); + + if (JOY_NEW(DPAD_ANY) || JOY_NEW(A_BUTTON)) + Debug_Display_FriendshipInfo(gTasks[taskId].tFriendship, gTasks[taskId].tInput, gTasks[taskId].tDigit, gTasks[taskId].tSubWindowId); +} + +static void DebugNativeStep_Party_SetFriendshipMain(u8 taskId) +{ + u8 windowId = DebugNativeStep_CreateDebugWindow(); + u32 friendship = GetMonData(&gPlayerParty[gTasks[taskId].tPartyId], MON_DATA_FRIENDSHIP); + + // Display initial flag + Debug_Display_FriendshipInfo(friendship, friendship, 0, windowId); + + gTasks[taskId].func = DebugNativeStep_Party_SetFriendshipSelect; + gTasks[taskId].tSubWindowId = windowId; + gTasks[taskId].tFriendship = friendship; + gTasks[taskId].tInput = friendship; + gTasks[taskId].tDigit = 0; + gTasks[taskId].tPartyId = 0; +} + +void DebugNative_Party_SetFriendship(void) +{ + if (gSpecialVar_0x8004 < PARTY_SIZE) + { + u32 taskId = CreateTask(DebugNativeStep_Party_SetFriendshipMain, 1); + gTasks[taskId].tPartyId = gSpecialVar_0x8004; + } +} + +#undef tPartyId +#undef tFriendship + +#undef tMenuTaskId +#undef tWindowId +#undef tSubWindowId +#undef tInput +#undef tDigit + static void DebugAction_Party_ClearParty(u8 taskId) { ZeroPlayerPartyMons(); diff --git a/src/dexnav.c b/src/dexnav.c index 1fcb87ce53..7b0099727f 100644 --- a/src/dexnav.c +++ b/src/dexnav.c @@ -932,8 +932,8 @@ static void DexNavUpdateDirectionArrow(void) { u16 tileX = sDexNavSearchDataPtr->tileX; u16 tileY = sDexNavSearchDataPtr->tileY; - u16 playerX = gSaveBlock1Ptr->pos.x + 7; - u16 playerY = gSaveBlock1Ptr->pos.y + 7; + u16 playerX = gSaveBlock1Ptr->pos.x + MAP_OFFSET; + u16 playerY = gSaveBlock1Ptr->pos.y + MAP_OFFSET; u16 deltaX = abs(tileX - playerX); u16 deltaY = abs(tileY - playerY); const u8 *str; @@ -2123,7 +2123,7 @@ static void PrintCurrentSpeciesInfo(void) { u16 species = DexNavGetSpecies(); enum NationalDexOrder dexNum = SpeciesToNationalPokedexNum(species); - u8 type1, type2; + enum Type type1, type2; if (!GetSetPokedexFlag(dexNum, FLAG_GET_SEEN)) species = SPECIES_NONE; diff --git a/src/egg_hatch.c b/src/egg_hatch.c index 6f858c8f8d..2c632ee578 100644 --- a/src/egg_hatch.c +++ b/src/egg_hatch.c @@ -931,7 +931,7 @@ u8 GetEggCyclesToSubtract(void) { if (!GetMonData(&gPlayerParty[i], MON_DATA_SANITY_IS_EGG)) { - u16 ability = GetMonAbility(&gPlayerParty[i]); + enum Ability ability = GetMonAbility(&gPlayerParty[i]); if (ability == ABILITY_MAGMA_ARMOR || ability == ABILITY_FLAME_BODY || ability == ABILITY_STEAM_ENGINE) diff --git a/src/event_object_movement.c b/src/event_object_movement.c index 8fdd7057b4..848289aec7 100644 --- a/src/event_object_movement.c +++ b/src/event_object_movement.c @@ -5502,7 +5502,7 @@ static bool32 TryStartFollowerTransformEffect(struct ObjectEvent *objectEvent, s { u32 multi; struct Pokemon *mon; - u32 ability; + enum Ability ability; if (DoesSpeciesHaveFormChangeMethod(OW_SPECIES(objectEvent), FORM_CHANGE_OVERWORLD_WEATHER) && OW_SPECIES(objectEvent) != (multi = GetOverworldWeatherSpecies(OW_SPECIES(objectEvent)))) { @@ -11536,3 +11536,8 @@ bool8 MovementAction_SurfStillRight_Step1(struct ObjectEvent *objectEvent, struc } return FALSE; } + +u8 GetObjectEventApricornTreeId(u8 objectEventId) +{ + return gObjectEvents[objectEventId].trainerRange_berryTreeId; +} diff --git a/src/field_effect.c b/src/field_effect.c index 45b4d61d17..174c071ae4 100644 --- a/src/field_effect.c +++ b/src/field_effect.c @@ -19,6 +19,7 @@ #include "mirage_tower.h" #include "menu.h" #include "metatile_behavior.h" +#include "oras_dowse.h" #include "overworld.h" #include "palette.h" #include "party_menu.h" @@ -1679,6 +1680,7 @@ void StartEscalatorWarp(u8 metatileBehavior, u8 priority) { gTasks[taskId].tGoingUp = TRUE; } + EndORASDowsing(); } static void Task_EscalatorWarpOut(u8 taskId) @@ -2065,6 +2067,7 @@ static bool8 DiveFieldEffect_TryWarp(struct Task *task) void StartLavaridgeGymB1FWarp(u8 priority) { + EndORASDowsing(); CreateTask(Task_LavaridgeGymB1FWarp, priority); } @@ -2273,6 +2276,7 @@ void SpriteCB_AshLaunch(struct Sprite *sprite) void StartLavaridgeGym1FWarp(u8 priority) { + EndORASDowsing(); CreateTask(Task_LavaridgeGym1FWarp, priority); } @@ -2395,6 +2399,7 @@ void StartEscapeRopeFieldEffect(void) LockPlayerFieldControls(); FreezeObjectEvents(); HideFollowerForFieldEffect(); // hide follower before warping + EndORASDowsing(); CreateTask(Task_EscapeRopeWarpOut, 80); } @@ -2589,6 +2594,7 @@ static void TeleportWarpOutFieldEffect_Init(struct Task *task) LockPlayerFieldControls(); FreezeObjectEvents(); CameraObjectFreeze(); + EndORASDowsing(); task->data[15] = GetPlayerFacingDirection(); task->tState++; } diff --git a/src/field_effect_helpers.c b/src/field_effect_helpers.c index 2e9e1a8510..f5f62a2367 100755 --- a/src/field_effect_helpers.c +++ b/src/field_effect_helpers.c @@ -35,8 +35,8 @@ static void UpdateFeetInFlowingWaterFieldEffect(struct Sprite *); static void UpdateAshFieldEffect_Wait(struct Sprite *); static void UpdateAshFieldEffect_Show(struct Sprite *); static void UpdateAshFieldEffect_End(struct Sprite *); -static void SynchroniseSurfAnim(struct ObjectEvent *, struct Sprite *); -static void SynchroniseSurfPosition(struct ObjectEvent *, struct Sprite *); +static void SynchronizeSurfAnim(struct ObjectEvent *, struct Sprite *); +static void SynchronizeSurfPosition(struct ObjectEvent *, struct Sprite *); static void UpdateBobbingEffect(struct ObjectEvent *, struct Sprite *, struct Sprite *); static void SpriteCB_UnderwaterSurfBlob(struct Sprite *); static u32 ShowDisguiseFieldEffect(u8, u8, u8); @@ -1248,13 +1248,13 @@ void UpdateSurfBlobFieldEffect(struct Sprite *sprite) { struct ObjectEvent *playerObj = &gObjectEvents[sprite->sPlayerObjId]; struct Sprite *playerSprite = &gSprites[playerObj->spriteId]; - SynchroniseSurfAnim(playerObj, sprite); - SynchroniseSurfPosition(playerObj, sprite); + SynchronizeSurfAnim(playerObj, sprite); + SynchronizeSurfPosition(playerObj, sprite); UpdateBobbingEffect(playerObj, playerSprite, sprite); sprite->oam.priority = playerSprite->oam.priority; } -static void SynchroniseSurfAnim(struct ObjectEvent *playerObj, struct Sprite *sprite) +static void SynchronizeSurfAnim(struct ObjectEvent *playerObj, struct Sprite *sprite) { // Indexes into sAnimTable_SurfBlob u8 surfBlobDirectionAnims[] = { @@ -1273,7 +1273,7 @@ static void SynchroniseSurfAnim(struct ObjectEvent *playerObj, struct Sprite *sp StartSpriteAnimIfDifferent(sprite, surfBlobDirectionAnims[playerObj->movementDirection]); } -void SynchroniseSurfPosition(struct ObjectEvent *playerObj, struct Sprite *sprite) +void SynchronizeSurfPosition(struct ObjectEvent *playerObj, struct Sprite *sprite) { u8 i; s16 x = playerObj->currentCoords.x; @@ -1903,4 +1903,3 @@ static void UpdateGrassFieldEffectSubpriority(struct Sprite *sprite, u8 elevatio } } } - diff --git a/src/field_message_box.c b/src/field_message_box.c index a87745f76c..6cac521853 100755 --- a/src/field_message_box.c +++ b/src/field_message_box.c @@ -7,6 +7,7 @@ #include "field_message_box.h" #include "text_window.h" #include "script.h" +#include "field_name_box.h" static EWRAM_DATA u8 sFieldMessageBoxMode = 0; EWRAM_DATA u8 gWalkAwayFromSignpostTimer = 0; @@ -39,9 +40,14 @@ static void Task_DrawFieldMessage(u8 taskId) task->tState++; break; case 1: + { + u32 nameboxWinId = GetNameboxWindowId(); DrawDialogueFrame(0, TRUE); + if (nameboxWinId != WINDOW_NONE) + DrawNamebox(nameboxWinId, NAME_BOX_BASE_TILE_NUM - NAME_BOX_BASE_TILES_TOTAL, TRUE); task->tState++; break; + } case 2: if (RunTextPrintersAndIsPrinter0Active() != TRUE) { @@ -123,6 +129,7 @@ bool8 ShowFieldMessageFromBuffer(void) static void ExpandStringAndStartDrawFieldMessage(const u8 *str, bool32 allowSkippingDelayWithButtonPress) { + TrySpawnNamebox(NAME_BOX_BASE_TILE_NUM); StringExpandPlaceholders(gStringVar4, str); AddTextPrinterForMessage(allowSkippingDelayWithButtonPress); CreateTask_DrawFieldMessage(); @@ -138,6 +145,7 @@ void HideFieldMessageBox(void) { DestroyTask_DrawFieldMessage(); ClearDialogWindowAndFrame(0, TRUE); + DestroyNamebox(); sFieldMessageBoxMode = FIELD_MESSAGE_BOX_HIDDEN; } diff --git a/src/field_name_box.c b/src/field_name_box.c new file mode 100644 index 0000000000..4c51f89d85 --- /dev/null +++ b/src/field_name_box.c @@ -0,0 +1,201 @@ +#include "global.h" +#include "main.h" +#include "menu.h" +#include "bg.h" +#include "window.h" +#include "text.h" +#include "string_util.h" +#include "international_string_util.h" +#include "script_menu.h" +#include "field_message_box.h" +#include "graphics.h" +#include "script.h" +#include "field_name_box.h" +#include "event_data.h" +#include "match_call.h" +#include "malloc.h" +#include "constants/speaker_names.h" +#include "data/speaker_names.h" + +static EWRAM_INIT u8 sNameboxWindowId = WINDOW_NONE; +EWRAM_DATA const u8 *gSpeakerName = NULL; + +static const u32 sNameBoxDefaultGfx[] = INCBIN_U32("graphics/text_window/name_box.4bpp"); +static const u32 sNameBoxPokenavGfx[] = INCBIN_U32("graphics/pokenav/name_box.4bpp"); + +static void WindowFunc_DrawNamebox(u32, u32, u32, u32, u32, u32, u32); +static void WindowFunc_ClearNamebox(u8, u8, u8, u8, u8, u8); + +void TrySpawnNamebox(u32 tileNum) +{ + u8 *strbuf = AllocZeroed(32 * sizeof(u8)); + if ((OW_FLAG_SUPPRESS_NAME_BOX != 0 && FlagGet(OW_FLAG_SUPPRESS_NAME_BOX)) || gSpeakerName == NULL || !strbuf) + { + // Re-check again in case anything but !strbuf is TRUE. + if (strbuf) + Free(strbuf); + + DestroyNamebox(); + return; + } + + StringExpandPlaceholders(strbuf, gSpeakerName); + + u32 fontId = FONT_SMALL; + u32 winWidth = OW_NAME_BOX_DEFAULT_WIDTH; + + if (OW_NAME_BOX_USE_DYNAMIC_WIDTH) + { + winWidth = ConvertPixelWidthToTileWidth(GetStringWidth(fontId, strbuf, -1)); + if (winWidth > OW_NAME_BOX_DEFAULT_WIDTH) + winWidth = OW_NAME_BOX_DEFAULT_WIDTH; + } + + if (sNameboxWindowId != WINDOW_NONE) + { + DestroyNamebox(); + RedrawDialogueFrame(); + } + + bool32 matchCall = IsMatchCallTaskActive(); + + struct WindowTemplate template = + { + .bg = 0, + .tilemapLeft = 2, + .tilemapTop = 13, + .width = winWidth, + .height = OW_NAME_BOX_DEFAULT_HEIGHT, + .paletteNum = matchCall ? 14 : DLG_WINDOW_PALETTE_NUM, + .baseBlock = tileNum, + }; + + sNameboxWindowId = AddWindow(&template); + FillNamebox(); + + u8 colors[3] = {TEXT_COLOR_TRANSPARENT, OW_NAME_BOX_FOREGROUND_COLOR, OW_NAME_BOX_SHADOW_COLOR}; + u8 bakColors[3]; + int strX = GetStringCenterAlignXOffset(fontId, strbuf, (winWidth * 8)); + if (matchCall) + { + colors[1] = 1; + colors[2] = 0; + } + + SaveTextColors(&bakColors[0], &bakColors[1], &bakColors[2]); + AddTextPrinterParameterized3(sNameboxWindowId, fontId, strX, 0, colors, 0, strbuf); + RestoreTextColors(&bakColors[0], &bakColors[1], &bakColors[2]); + PutWindowTilemap(sNameboxWindowId); + Free(strbuf); +} + +u32 GetNameboxWindowId(void) +{ + return sNameboxWindowId; +} + +void ResetNameboxData(void) +{ + sNameboxWindowId = WINDOW_NONE; + gSpeakerName = NULL; +} + +void DestroyNamebox(void) +{ + if (sNameboxWindowId == WINDOW_NONE) + return; + + ClearNamebox(sNameboxWindowId, TRUE); + ClearWindowTilemap(sNameboxWindowId); + RemoveWindow(sNameboxWindowId); + sNameboxWindowId = WINDOW_NONE; + gSpeakerName = NULL; +} + +u32 GetNameboxWidth(void) +{ + return gWindows[sNameboxWindowId].window.width; +} + +static const u32 *GetNameboxGraphics(void) +{ + if (IsMatchCallTaskActive()) + return sNameBoxPokenavGfx; + else + return sNameBoxDefaultGfx; +} + +void FillNamebox(void) +{ + u32 winSize = GetNameboxWidth(); + const u32 *gfx = GetNameboxGraphics(); + + for (u32 i = 0; i < winSize; i++) + { + #define TILE(x) (8 * x) + CopyToWindowPixelBuffer(sNameboxWindowId, &gfx[TILE(1)], TILE_SIZE_4BPP, i); + CopyToWindowPixelBuffer(sNameboxWindowId, &gfx[TILE(4)], TILE_SIZE_4BPP, i + winSize); + #undef TILE + } +} + +void DrawNamebox(u32 windowId, u32 tileNum, bool32 copyToVram) +{ + // manual instead of using CallWindowFunction for extra tileNum param + struct WindowTemplate *w = &gWindows[windowId].window; + u32 size = TILE_OFFSET_4BPP(NAME_BOX_BASE_TILES_TOTAL); + + LoadBgTiles(GetWindowAttribute(sNameboxWindowId, WINDOW_BG), GetNameboxGraphics(), size, tileNum); + WindowFunc_DrawNamebox(w->bg, w->tilemapLeft, w->tilemapTop, w->width, w->height, w->paletteNum, tileNum); + PutWindowTilemap(windowId); + if (copyToVram == TRUE) + CopyWindowToVram(windowId, COPYWIN_FULL); +} + +void ClearNamebox(u32 windowId, bool32 copyToVram) +{ + CallWindowFunction(windowId, WindowFunc_ClearNamebox); + ClearWindowTilemap(windowId); + if (copyToVram == TRUE) + CopyWindowToVram(windowId, COPYWIN_FULL); +} + +static void WindowFunc_DrawNamebox(u32 bg, u32 L, u32 T, u32 w, u32 h, u32 p, u32 tileNum) +{ + // left-most + FillBgTilemapBufferRect(bg, tileNum, L - 1, T, 1, 1, p); + FillBgTilemapBufferRect(bg, tileNum + 3, L - 1, T + 1, 1, 1, p); + + // right-most + FillBgTilemapBufferRect(bg, tileNum + 2, L + w, T, 1, 1, p); + FillBgTilemapBufferRect(bg, tileNum + 5, L + w, T + 1, 1, 1, p); +} + +static void WindowFunc_ClearNamebox(u8 bg, u8 L, u8 T, u8 w, u8 h, u8 p) +{ + FillBgTilemapBufferRect(bg, 0, L - 1, T, w + 2, h, 0); // palette doesn't matter +} + +void SetSpeaker(struct ScriptContext *ctx) +{ + u32 arg = ScriptReadWord(ctx); + const u8 *speaker = NULL; + + if (arg < SP_NAME_COUNT) + speaker = gSpeakerNamesTable[arg]; + else if (arg >= ROM_START && arg < ROM_END) + speaker = (const u8 *)arg; + + gSpeakerName = speaker; +} + +// useful for other context e.g. match call +void TrySpawnAndShowNamebox(const u8 *speaker, u32 tileNum) +{ + gSpeakerName = speaker; + TrySpawnNamebox(tileNum); + if (sNameboxWindowId != WINDOW_NONE) + DrawNamebox(sNameboxWindowId, tileNum - NAME_BOX_BASE_TILES_TOTAL, TRUE); + else // either NULL or SP_NAME_NONE + RedrawDialogueFrame(); +} diff --git a/src/field_player_avatar.c b/src/field_player_avatar.c index aaf28a6dea..a46f292517 100644 --- a/src/field_player_avatar.c +++ b/src/field_player_avatar.c @@ -12,6 +12,7 @@ #include "follower_npc.h" #include "menu.h" #include "metatile_behavior.h" +#include "oras_dowse.h" #include "overworld.h" #include "party_menu.h" #include "random.h" @@ -146,40 +147,6 @@ static void CreateStopSurfingTask(u8); static void Task_StopSurfingInit(u8); static void Task_WaitStopSurfing(u8); -static void Task_Fishing(u8); -static bool32 Fishing_Init(struct Task *); -static bool32 Fishing_GetRodOut(struct Task *); -static bool32 Fishing_WaitBeforeDots(struct Task *); -static bool32 Fishing_InitDots(struct Task *); -static bool32 Fishing_ShowDots(struct Task *); -static bool32 Fishing_CheckForBite(struct Task *); -static bool32 Fishing_GotBite(struct Task *); -static bool32 Fishing_ChangeMinigame(struct Task *); -static bool32 Fishing_WaitForA(struct Task *); -static bool32 Fishing_APressNoMinigame(struct Task *); -static bool32 Fishing_CheckMoreDots(struct Task *); -static bool32 Fishing_MonOnHook(struct Task *); -static bool32 Fishing_StartEncounter(struct Task *); -static bool32 Fishing_NotEvenNibble(struct Task *); -static bool32 Fishing_GotAway(struct Task *); -static bool32 Fishing_NoMon(struct Task *); -static bool32 Fishing_PutRodAway(struct Task *); -static bool32 Fishing_EndNoMon(struct Task *); -static void AlignFishingAnimationFrames(void); -static bool32 DoesFishingMinigameAllowCancel(void); -static bool32 Fishing_DoesFirstMonInPartyHaveSuctionCupsOrStickyHold(void); -static bool32 Fishing_RollForBite(u32, bool32); -static u32 CalculateFishingBiteOdds(u32, bool32); -static u32 CalculateFishingFollowerBoost(void); -static u32 CalculateFishingProximityBoost(u32 odds); -static void GetCoordinatesAroundBobber(s16[], s16[][AXIS_COUNT], u32); -static u32 CountQualifyingTiles(s16[][AXIS_COUNT], s16 player[], u8 facingDirection, struct ObjectEvent *objectEvent, bool32 isTileLand[]); -static bool32 CheckTileQualification(s16 tile[], s16 player[], u32 facingDirection, struct ObjectEvent* objectEvent, bool32 isTileLand[], u32 direction); -static u32 CountLandTiles(bool32 isTileLand[]); -static bool32 IsPlayerHere(s16, s16, s16, s16); -static bool32 IsMetatileBlocking(s16, s16, u32); -static bool32 IsMetatileLand(s16, s16, u32); - static u8 TrySpinPlayerForWarp(struct ObjectEvent *, s16 *); static bool8 (*const sForcedMovementTestFuncs[NUM_FORCED_MOVEMENTS])(u8) = @@ -382,7 +349,7 @@ void PlayerStep(u8 direction, u16 newKeys, u16 heldKeys) DoPlayerAvatarTransition(); if (TryDoMetatileBehaviorForcedMovement() == 0) { - if (GetFollowerNPCData(FNPC_DATA_FORCED_MOVEMENT) != FALSE) + if (GetFollowerNPCData(FNPC_DATA_FORCED_MOVEMENT) != FNPC_FORCED_NONE) { gPlayerAvatar.preventStep = TRUE; CreateTask(Task_MoveNPCFollowerAfterForcedMovement, 1); @@ -397,6 +364,8 @@ void PlayerStep(u8 direction, u16 newKeys, u16 heldKeys) } } +#define sCounter data[3] + static bool8 TryInterruptObjectEventSpecialAnim(struct ObjectEvent *playerObjEvent, u8 direction) { if (ObjectEventIsMovementOverridden(playerObjEvent) @@ -405,6 +374,8 @@ static bool8 TryInterruptObjectEventSpecialAnim(struct ObjectEvent *playerObjEve u8 heldMovementActionId = ObjectEventGetHeldMovementActionId(playerObjEvent); if (heldMovementActionId > MOVEMENT_ACTION_WALK_FAST_RIGHT && heldMovementActionId < MOVEMENT_ACTION_WALK_IN_PLACE_NORMAL_DOWN) { + struct ObjectEvent *playerObj = &gObjectEvents[gPlayerAvatar.objectEventId]; + if (direction == DIR_NONE) { return TRUE; @@ -412,12 +383,21 @@ static bool8 TryInterruptObjectEventSpecialAnim(struct ObjectEvent *playerObjEve if (playerObjEvent->movementDirection != direction) { + if (I_ORAS_DOWSING_FLAG != 0 && FlagGet(I_ORAS_DOWSING_FLAG)) + gSprites[playerObj->fieldEffectSpriteId].sCounter = 0; + ObjectEventClearHeldMovement(playerObjEvent); return FALSE; } if (CheckForPlayerAvatarStaticCollision(direction) == COLLISION_NONE) { + if (I_ORAS_DOWSING_FLAG != 0 && FlagGet(I_ORAS_DOWSING_FLAG)) + { + gSprites[playerObj->fieldEffectSpriteId].sCounter = 0; + gSprites[playerObj->fieldEffectSpriteId].y2 = 0; + } + ObjectEventClearHeldMovement(playerObjEvent); return FALSE; } @@ -429,6 +409,8 @@ static bool8 TryInterruptObjectEventSpecialAnim(struct ObjectEvent *playerObjEve return FALSE; } +#undef sCounter + static void npc_clear_strange_bits(struct ObjectEvent *objEvent) { objEvent->inanimate = FALSE; @@ -519,7 +501,7 @@ static bool8 DoForcedMovement(u8 direction, void (*moveFunc)(u8)) { if (collision == COLLISION_LEDGE_JUMP) { - SetFollowerNPCData(FNPC_DATA_FORCED_MOVEMENT, FALSE); + SetFollowerNPCData(FNPC_DATA_FORCED_MOVEMENT, FNPC_FORCED_NONE); PlayerJumpLedge(direction); } @@ -530,8 +512,8 @@ static bool8 DoForcedMovement(u8 direction, void (*moveFunc)(u8)) } else { - if (PlayerHasFollowerNPC()) - SetFollowerNPCData(FNPC_DATA_FORCED_MOVEMENT, TRUE); + if (PlayerHasFollowerNPC() && GetFollowerNPCData(FNPC_DATA_FORCED_MOVEMENT) != FNPC_FORCED_STAY) + SetFollowerNPCData(FNPC_DATA_FORCED_MOVEMENT, FNPC_FORCED_FOLLOW); playerAvatar->runningState = MOVING; moveFunc(direction); @@ -858,8 +840,12 @@ static void PlayerNotOnBikeMoving(u8 direction, u16 heldKeys) return; } - if (!(gPlayerAvatar.flags & PLAYER_AVATAR_FLAG_UNDERWATER) && (heldKeys & B_BUTTON) && FlagGet(FLAG_SYS_B_DASH) - && IsRunningDisallowed(gObjectEvents[gPlayerAvatar.objectEventId].currentMetatileBehavior) == 0 && !FollowerNPCComingThroughDoor()) + if (!(gPlayerAvatar.flags & PLAYER_AVATAR_FLAG_UNDERWATER) + && (heldKeys & B_BUTTON) + && FlagGet(FLAG_SYS_B_DASH) + && IsRunningDisallowed(gObjectEvents[gPlayerAvatar.objectEventId].currentMetatileBehavior) == 0 + && !FollowerNPCComingThroughDoor() + && (I_ORAS_DOWSING_FLAG == 0 || (I_ORAS_DOWSING_FLAG != 0 && !FlagGet(I_ORAS_DOWSING_FLAG)))) { if (ObjectMovingOnRockStairs(&gObjectEvents[gPlayerAvatar.objectEventId], direction)) PlayerRunSlow(direction); @@ -1660,12 +1646,14 @@ void SetPlayerInvisibility(bool8 invisible) void SetPlayerAvatarFieldMove(void) { + EndORASDowsing(); ObjectEventSetGraphicsId(&gObjectEvents[gPlayerAvatar.objectEventId], GetPlayerAvatarGraphicsIdByStateId(PLAYER_AVATAR_STATE_FIELD_MOVE)); StartSpriteAnim(&gSprites[gPlayerAvatar.spriteId], ANIM_FIELD_MOVE); } -static void SetPlayerAvatarFishing(u8 direction) +void SetPlayerAvatarFishing(u8 direction) { + EndORASDowsing(); ObjectEventSetGraphicsId(&gObjectEvents[gPlayerAvatar.objectEventId], GetPlayerAvatarGraphicsIdByStateId(PLAYER_AVATAR_STATE_FISHING)); StartSpriteAnim(&gSprites[gPlayerAvatar.spriteId], GetFishingDirectionAnimNum(direction)); } @@ -1679,6 +1667,7 @@ void PlayerUseAcroBikeOnBumpySlope(u8 direction) void SetPlayerAvatarWatering(u8 direction) { + EndORASDowsing(); ObjectEventSetGraphicsId(&gObjectEvents[gPlayerAvatar.objectEventId], GetPlayerAvatarGraphicsIdByStateId(PLAYER_AVATAR_STATE_WATERING)); StartSpriteAnim(&gSprites[gPlayerAvatar.spriteId], GetFaceDirectionAnimNum(direction)); } @@ -1934,644 +1923,6 @@ static void Task_WaitStopSurfing(u8 taskId) } } -#define tStep data[0] -#define tFrameCounter data[1] -#define tNumDots data[2] -#define tDotsRequired data[3] -#define tRoundsPlayed data[12] -#define tMinRoundsRequired data[13] -#define tPlayerGfxId data[14] -#define tFishingRod data[15] - -#define FISHING_PROXIMITY_BOOST 4 -#define FISHING_STICKY_BOOST 36 - -#if I_FISHING_BITE_ODDS >= GEN_4 - #define FISHING_OLD_ROD_ODDS 75 - #define FISHING_GOOD_ROD_ODDS 50 - #define FISHING_SUPER_ROD_ODDS 25 -#elif I_FISHING_BITE_ODDS >= GEN_3 - #define FISHING_OLD_ROD_ODDS 50 - #define FISHING_GOOD_ROD_ODDS 50 - #define FISHING_SUPER_ROD_ODDS 50 -#else - #define FISHING_OLD_ROD_ODDS 0 - #define FISHING_GOOD_ROD_ODDS 33 - #define FISHING_SUPER_ROD_ODDS 50 -#endif - -enum -{ - FISHING_INIT, - FISHING_GET_ROD_OUT, - FISHING_WAIT_BEFORE_DOTS, - FISHING_INIT_DOTS, - FISHING_SHOW_DOTS, - FISHING_CHECK_FOR_BITE, - FISHING_GOT_BITE, - FISHING_CHANGE_MINIGAME, - FISHING_WAIT_FOR_A, - FISHING_A_PRESS_NO_MINIGAME, - FISHING_CHECK_MORE_DOTS, - FISHING_MON_ON_HOOK, - FISHING_START_ENCOUNTER, - FISHING_NOT_EVEN_NIBBLE, - FISHING_GOT_AWAY, - FISHING_NO_MON, - FISHING_PUT_ROD_AWAY, - FISHING_END_NO_MON, -}; - -static bool32 (*const sFishingStateFuncs[])(struct Task *) = -{ - [FISHING_INIT] = Fishing_Init, - [FISHING_GET_ROD_OUT] = Fishing_GetRodOut, - [FISHING_WAIT_BEFORE_DOTS] = Fishing_WaitBeforeDots, - [FISHING_INIT_DOTS] = Fishing_InitDots, - [FISHING_SHOW_DOTS] = Fishing_ShowDots, - [FISHING_CHECK_FOR_BITE] = Fishing_CheckForBite, - [FISHING_GOT_BITE] = Fishing_GotBite, - [FISHING_CHANGE_MINIGAME] = Fishing_ChangeMinigame, - [FISHING_WAIT_FOR_A] = Fishing_WaitForA, - [FISHING_A_PRESS_NO_MINIGAME] = Fishing_APressNoMinigame, - [FISHING_CHECK_MORE_DOTS] = Fishing_CheckMoreDots, - [FISHING_MON_ON_HOOK] = Fishing_MonOnHook, - [FISHING_START_ENCOUNTER] = Fishing_StartEncounter, - [FISHING_NOT_EVEN_NIBBLE] = Fishing_NotEvenNibble, - [FISHING_GOT_AWAY] = Fishing_GotAway, - [FISHING_NO_MON] = Fishing_NoMon, - [FISHING_PUT_ROD_AWAY] = Fishing_PutRodAway, - [FISHING_END_NO_MON] = Fishing_EndNoMon, -}; - -void StartFishing(u8 rod) -{ - u8 taskId = CreateTask(Task_Fishing, 0xFF); - - gTasks[taskId].tFishingRod = rod; - Task_Fishing(taskId); -} - -static void Task_Fishing(u8 taskId) -{ - while (sFishingStateFuncs[gTasks[taskId].tStep](&gTasks[taskId])) - ; -} - -static bool32 Fishing_Init(struct Task *task) -{ - LockPlayerFieldControls(); - gPlayerAvatar.preventStep = TRUE; - task->tStep = FISHING_GET_ROD_OUT; - return FALSE; -} - -static bool32 Fishing_GetRodOut(struct Task *task) -{ - struct ObjectEvent *playerObjEvent; - const s16 minRounds1[] = { - [OLD_ROD] = 1, - [GOOD_ROD] = 1, - [SUPER_ROD] = 1 - }; - const s16 minRounds2[] = { - [OLD_ROD] = 1, - [GOOD_ROD] = 3, - [SUPER_ROD] = 6 - }; - - task->tRoundsPlayed = 0; - task->tMinRoundsRequired = minRounds1[task->tFishingRod] + (Random() % minRounds2[task->tFishingRod]); - task->tPlayerGfxId = gObjectEvents[gPlayerAvatar.objectEventId].graphicsId; - playerObjEvent = &gObjectEvents[gPlayerAvatar.objectEventId]; - ObjectEventClearHeldMovementIfActive(playerObjEvent); - playerObjEvent->enableAnim = TRUE; - SetPlayerAvatarFishing(playerObjEvent->facingDirection); - task->tStep = FISHING_WAIT_BEFORE_DOTS; - return FALSE; -} - -static bool32 Fishing_WaitBeforeDots(struct Task *task) -{ - AlignFishingAnimationFrames(); - - // Wait one second - task->tFrameCounter++; - if (task->tFrameCounter >= 60) - task->tStep = FISHING_INIT_DOTS; - return FALSE; -} - -static bool32 Fishing_InitDots(struct Task *task) -{ - u32 randVal; - - LoadMessageBoxAndFrameGfx(0, TRUE); - task->tStep = FISHING_SHOW_DOTS; - task->tFrameCounter = 0; - task->tNumDots = 0; - randVal = Random(); - randVal %= 10; - task->tDotsRequired = randVal + 1; - if (task->tRoundsPlayed == 0) - task->tDotsRequired = randVal + 4; - if (task->tDotsRequired >= 10) - task->tDotsRequired = 10; - return TRUE; -} - -static bool32 Fishing_ShowDots(struct Task *task) -{ - const u8 dot[] = _("·"); - - AlignFishingAnimationFrames(); - task->tFrameCounter++; - if (JOY_NEW(A_BUTTON)) - { - if (!DoesFishingMinigameAllowCancel()) - return FALSE; - - task->tStep = FISHING_NOT_EVEN_NIBBLE; - if (task->tRoundsPlayed != 0) - task->tStep = FISHING_GOT_AWAY; - return TRUE; - } - else - { - if (task->tFrameCounter >= 20) - { - task->tFrameCounter = 0; - if (task->tNumDots >= task->tDotsRequired) - { - task->tStep = FISHING_CHECK_FOR_BITE; - if (task->tRoundsPlayed != 0) - task->tStep = FISHING_GOT_BITE; - task->tRoundsPlayed++; - } - else - { - AddTextPrinterParameterized(0, FONT_NORMAL, dot, task->tNumDots * 8, 1, 0, NULL); - task->tNumDots++; - } - } - return FALSE; - } -} - -static bool32 Fishing_CheckForBite(struct Task *task) -{ - bool32 bite, firstMonHasSuctionOrSticky; - - AlignFishingAnimationFrames(); - task->tStep = FISHING_GOT_BITE; - bite = FALSE; - - if (!DoesCurrentMapHaveFishingMons()) - { - task->tStep = FISHING_NOT_EVEN_NIBBLE; - return TRUE; - } - - firstMonHasSuctionOrSticky = Fishing_DoesFirstMonInPartyHaveSuctionCupsOrStickyHold(); - - if(firstMonHasSuctionOrSticky) - bite = Fishing_RollForBite(task->tFishingRod, firstMonHasSuctionOrSticky); - - if (!bite) - bite = Fishing_RollForBite(task->tFishingRod, FALSE); - - if (!bite) - task->tStep = FISHING_NOT_EVEN_NIBBLE; - - if (bite) - StartSpriteAnim(&gSprites[gPlayerAvatar.spriteId], GetFishingBiteDirectionAnimNum(GetPlayerFacingDirection())); - - return TRUE; -} - -static bool32 Fishing_GotBite(struct Task *task) -{ - AlignFishingAnimationFrames(); - AddTextPrinterParameterized(0, FONT_NORMAL, gText_OhABite, 0, 17, 0, NULL); - task->tStep = FISHING_CHANGE_MINIGAME; - task->tFrameCounter = 0; - return FALSE; -} - -static bool32 Fishing_ChangeMinigame(struct Task *task) -{ - switch (I_FISHING_MINIGAME) - { - case GEN_1: - case GEN_2: - task->tStep = FISHING_A_PRESS_NO_MINIGAME; - break; - case GEN_3: - default: - task->tStep = FISHING_WAIT_FOR_A; - break; - } - return TRUE; -} - -// We have a bite. Now, wait for the player to press A, or the timer to expire. -static bool32 Fishing_WaitForA(struct Task *task) -{ - const s16 reelTimeouts[3] = { - [OLD_ROD] = 36, - [GOOD_ROD] = 33, - [SUPER_ROD] = 30 - }; - - AlignFishingAnimationFrames(); - task->tFrameCounter++; - if (task->tFrameCounter >= reelTimeouts[task->tFishingRod]) - task->tStep = FISHING_GOT_AWAY; - else if (JOY_NEW(A_BUTTON)) - task->tStep = FISHING_CHECK_MORE_DOTS; - return FALSE; -} - -static bool32 Fishing_APressNoMinigame(struct Task *task) -{ - AlignFishingAnimationFrames(); - if (JOY_NEW(A_BUTTON)) - task->tStep = FISHING_MON_ON_HOOK; - return FALSE; -} - -// Determine if we're going to play the dot game again -static bool32 Fishing_CheckMoreDots(struct Task *task) -{ - const s16 moreDotsChance[][2] = - { - [OLD_ROD] = {0, 0}, - [GOOD_ROD] = {40, 10}, - [SUPER_ROD] = {70, 30} - }; - - AlignFishingAnimationFrames(); - task->tStep = FISHING_MON_ON_HOOK; - if (task->tRoundsPlayed < task->tMinRoundsRequired) - { - task->tStep = FISHING_INIT_DOTS; - } - else if (task->tRoundsPlayed < 2) - { - // probability of having to play another round - s16 probability = Random() % 100; - - if (moreDotsChance[task->tFishingRod][task->tRoundsPlayed] > probability) - task->tStep = FISHING_INIT_DOTS; - } - return FALSE; -} - -static bool32 Fishing_MonOnHook(struct Task *task) -{ - AlignFishingAnimationFrames(); - FillWindowPixelBuffer(0, PIXEL_FILL(1)); - AddTextPrinterParameterized2(0, FONT_NORMAL, gText_PokemonOnHook, 1, 0, TEXT_COLOR_DARK_GRAY, TEXT_COLOR_WHITE, TEXT_COLOR_LIGHT_GRAY); - task->tStep = FISHING_START_ENCOUNTER; - task->tFrameCounter = 0; - return FALSE; -} - -static bool32 Fishing_StartEncounter(struct Task *task) -{ - if (task->tFrameCounter == 0) - AlignFishingAnimationFrames(); - - RunTextPrinters(); - - if (task->tFrameCounter == 0) - { - if (!IsTextPrinterActive(0)) - { - struct ObjectEvent *playerObjEvent = &gObjectEvents[gPlayerAvatar.objectEventId]; - - ObjectEventSetGraphicsId(playerObjEvent, task->tPlayerGfxId); - ObjectEventTurn(playerObjEvent, playerObjEvent->movementDirection); - if (gPlayerAvatar.flags & PLAYER_AVATAR_FLAG_SURFING) - SetSurfBlob_PlayerOffset(gObjectEvents[gPlayerAvatar.objectEventId].fieldEffectSpriteId, FALSE, 0); - gSprites[gPlayerAvatar.spriteId].x2 = 0; - gSprites[gPlayerAvatar.spriteId].y2 = 0; - ClearDialogWindowAndFrame(0, TRUE); - task->tFrameCounter++; - return FALSE; - } - } - - if (task->tFrameCounter != 0) - { - gPlayerAvatar.preventStep = FALSE; - UnlockPlayerFieldControls(); - FishingWildEncounter(task->tFishingRod); - RecordFishingAttemptForTV(TRUE); - DestroyTask(FindTaskIdByFunc(Task_Fishing)); - } - return FALSE; -} - -static bool32 Fishing_NotEvenNibble(struct Task *task) -{ - gChainFishingDexNavStreak = 0; - AlignFishingAnimationFrames(); - StartSpriteAnim(&gSprites[gPlayerAvatar.spriteId], GetFishingNoCatchDirectionAnimNum(GetPlayerFacingDirection())); - FillWindowPixelBuffer(0, PIXEL_FILL(1)); - AddTextPrinterParameterized2(0, FONT_NORMAL, gText_NotEvenANibble, 1, 0, TEXT_COLOR_DARK_GRAY, TEXT_COLOR_WHITE, TEXT_COLOR_LIGHT_GRAY); - task->tStep = FISHING_NO_MON; - return TRUE; -} - -static bool32 Fishing_GotAway(struct Task *task) -{ - gChainFishingDexNavStreak = 0; - AlignFishingAnimationFrames(); - StartSpriteAnim(&gSprites[gPlayerAvatar.spriteId], GetFishingNoCatchDirectionAnimNum(GetPlayerFacingDirection())); - FillWindowPixelBuffer(0, PIXEL_FILL(1)); - AddTextPrinterParameterized2(0, FONT_NORMAL, gText_ItGotAway, 1, 0, TEXT_COLOR_DARK_GRAY, TEXT_COLOR_WHITE, TEXT_COLOR_LIGHT_GRAY); - task->tStep = FISHING_NO_MON; - return TRUE; -} - -static bool32 Fishing_NoMon(struct Task *task) -{ - AlignFishingAnimationFrames(); - task->tStep = FISHING_PUT_ROD_AWAY; - return FALSE; -} - -static bool32 Fishing_PutRodAway(struct Task *task) -{ - AlignFishingAnimationFrames(); - if (gSprites[gPlayerAvatar.spriteId].animEnded) - { - struct ObjectEvent *playerObjEvent = &gObjectEvents[gPlayerAvatar.objectEventId]; - - ObjectEventSetGraphicsId(playerObjEvent, task->tPlayerGfxId); - ObjectEventTurn(playerObjEvent, playerObjEvent->movementDirection); - if (gPlayerAvatar.flags & PLAYER_AVATAR_FLAG_SURFING) - SetSurfBlob_PlayerOffset(gObjectEvents[gPlayerAvatar.objectEventId].fieldEffectSpriteId, FALSE, 0); - gSprites[gPlayerAvatar.spriteId].x2 = 0; - gSprites[gPlayerAvatar.spriteId].y2 = 0; - task->tStep = FISHING_END_NO_MON; - } - return FALSE; -} - -static bool32 Fishing_EndNoMon(struct Task *task) -{ - RunTextPrinters(); - if (!IsTextPrinterActive(0)) - { - gPlayerAvatar.preventStep = FALSE; - UnlockPlayerFieldControls(); - UnfreezeObjectEvents(); - ClearDialogWindowAndFrame(0, TRUE); - RecordFishingAttemptForTV(FALSE); - DestroyTask(FindTaskIdByFunc(Task_Fishing)); - } - return FALSE; -} - -static bool32 DoesFishingMinigameAllowCancel(void) -{ - switch(I_FISHING_MINIGAME) - { - case GEN_1: - case GEN_2: - return FALSE; - case GEN_3: - default: - return TRUE; - } -} - -static bool32 Fishing_DoesFirstMonInPartyHaveSuctionCupsOrStickyHold(void) -{ - u32 ability; - - if (GetMonData(&gPlayerParty[0], MON_DATA_SANITY_IS_EGG)) - return FALSE; - - ability = GetMonAbility(&gPlayerParty[0]); - - return (ability == ABILITY_SUCTION_CUPS || ability == ABILITY_STICKY_HOLD); -} - -static bool32 Fishing_RollForBite(u32 rod, bool32 isStickyHold) -{ - return ((Random() % 100) > CalculateFishingBiteOdds(rod, isStickyHold)); -} - -static u32 CalculateFishingBiteOdds(u32 rod, bool32 isStickyHold) -{ - u32 odds; - - if (rod == OLD_ROD) - odds = FISHING_OLD_ROD_ODDS; - if (rod == GOOD_ROD) - odds = FISHING_GOOD_ROD_ODDS; - if (rod == SUPER_ROD) - odds = FISHING_SUPER_ROD_ODDS; - - odds -= CalculateFishingFollowerBoost(); - - if (isStickyHold) - { - if (I_FISHING_STICKY_BOOST >= GEN_4) - odds -= (100 - odds); - else - odds -= FISHING_STICKY_BOOST; - } - - odds -= CalculateFishingProximityBoost(odds); - - return odds; -} - -static u32 CalculateFishingFollowerBoost() -{ - u32 friendship; - struct Pokemon *mon = GetFirstLiveMon(); - - if (!I_FISHING_FOLLOWER_BOOST || !mon) - return 0; - - friendship = GetMonData(mon, MON_DATA_FRIENDSHIP); - if (friendship >= 250) - return 50; - else if (friendship >= 200) - return 40; - else if (friendship >= 150) - return 30; - else if (friendship >= 100) - return 20; - else - return 0; -} - -static u32 CalculateFishingProximityBoost(u32 odds) -{ - s16 player[AXIS_COUNT], bobber[AXIS_COUNT]; - s16 surroundingTile[CARDINAL_DIRECTION_COUNT][AXIS_COUNT] = {{0, 0}}; - bool32 isTileLand[CARDINAL_DIRECTION_COUNT] = {FALSE}; - u32 facingDirection, numQualifyingTile = 0; - struct ObjectEvent *objectEvent; - - if (!I_FISHING_PROXIMITY) - return 0; - - objectEvent = &gObjectEvents[gPlayerAvatar.objectEventId]; - - player[AXIS_X] = objectEvent->currentCoords.x; - player[AXIS_Y] = objectEvent->currentCoords.y; - bobber[AXIS_X] = objectEvent->currentCoords.x; - bobber[AXIS_Y] = objectEvent->currentCoords.y; - - facingDirection = GetPlayerFacingDirection(); - MoveCoords(facingDirection, &bobber[AXIS_X], &bobber[AXIS_Y]); - - GetCoordinatesAroundBobber(bobber, surroundingTile, facingDirection); - numQualifyingTile = CountQualifyingTiles(surroundingTile, player, facingDirection, objectEvent, isTileLand); - - numQualifyingTile += CountLandTiles(isTileLand); - - return (numQualifyingTile == 3) ? odds : (numQualifyingTile * FISHING_PROXIMITY_BOOST); -} - -static void GetCoordinatesAroundBobber(s16 bobber[], s16 surroundingTile[][AXIS_COUNT], u32 facingDirection) -{ - u32 direction; - - for (direction = DIR_SOUTH; direction < CARDINAL_DIRECTION_COUNT; direction++) - { - surroundingTile[direction][AXIS_X] = bobber[AXIS_X]; - surroundingTile[direction][AXIS_Y] = bobber[AXIS_Y]; - MoveCoords(direction, &surroundingTile[direction][AXIS_X], &surroundingTile[direction][AXIS_Y]); - } -} - -static u32 CountQualifyingTiles(s16 surroundingTile[][AXIS_COUNT], s16 player[], u8 facingDirection, struct ObjectEvent *objectEvent, bool32 isTileLand[]) -{ - u32 numQualifyingTile = 0; - s16 tile[AXIS_COUNT]; - u8 direction = DIR_SOUTH; - - for (direction = DIR_SOUTH; direction < CARDINAL_DIRECTION_COUNT; direction++) - { - tile[AXIS_X] = surroundingTile[direction][AXIS_X]; - tile[AXIS_Y] = surroundingTile[direction][AXIS_Y]; - - if (!CheckTileQualification(tile, player, facingDirection, objectEvent, isTileLand, direction)) - continue; - - numQualifyingTile++; - } - return numQualifyingTile; -} - -static bool32 CheckTileQualification(s16 tile[], s16 player[], u32 facingDirection, struct ObjectEvent* objectEvent, bool32 isTileLand[], u32 direction) -{ - u32 collison = GetCollisionAtCoords(objectEvent, tile[AXIS_X], tile[AXIS_Y], facingDirection); - - if (IsPlayerHere(tile[AXIS_X], tile[AXIS_Y], player[AXIS_X], player[AXIS_Y])) - return FALSE; - else if (IsMetatileBlocking(tile[AXIS_X], tile[AXIS_Y], collison)) - return TRUE; - else if (MetatileBehavior_IsSurfableFishableWater(MapGridGetMetatileBehaviorAt(tile[AXIS_X], tile[AXIS_Y]))) - return FALSE; - else if (IsMetatileLand(tile[AXIS_X], tile[AXIS_Y], collison)) - isTileLand[direction] = TRUE; - - return FALSE; -} - -static u32 CountLandTiles(bool32 isTileLand[]) -{ - u32 direction, numQualifyingTile = 0; - - for (direction = DIR_SOUTH; direction < CARDINAL_DIRECTION_COUNT; direction++) - if (isTileLand[direction]) - numQualifyingTile++; - - return (numQualifyingTile < 2) ? 0 : numQualifyingTile; -} - -static bool32 IsPlayerHere(s16 x, s16 y, s16 playerX, s16 playerY) -{ - return ((x == playerX) && (y == playerY)); -} - -static bool32 IsMetatileBlocking(s16 x, s16 y, u32 collison) -{ - switch(collison) - { - case COLLISION_NONE: - case COLLISION_STOP_SURFING: - case COLLISION_ELEVATION_MISMATCH: - return FALSE; - default: - return TRUE; - case COLLISION_OBJECT_EVENT: - return (gObjectEvents[GetObjectEventIdByXY(x,y)].inanimate); - } - return TRUE; -} - -static bool32 IsMetatileLand(s16 x, s16 y, u32 collison) -{ - switch(collison) - { - case COLLISION_NONE: - case COLLISION_STOP_SURFING: - case COLLISION_ELEVATION_MISMATCH: - return TRUE; - default: - return FALSE; - } -} - -#undef tStep -#undef tFrameCounter -#undef tFishingRod - -static void AlignFishingAnimationFrames(void) -{ - struct Sprite *playerSprite = &gSprites[gPlayerAvatar.spriteId]; - u8 animCmdIndex; - u8 animType; - - AnimateSprite(playerSprite); - playerSprite->x2 = 0; - playerSprite->y2 = 0; - animCmdIndex = playerSprite->animCmdIndex; - if (playerSprite->anims[playerSprite->animNum][animCmdIndex].type == -1) - { - animCmdIndex--; - } - else - { - playerSprite->animDelayCounter++; - if (playerSprite->anims[playerSprite->animNum][animCmdIndex].type == -1) - animCmdIndex--; - } - animType = playerSprite->anims[playerSprite->animNum][animCmdIndex].type; - if (animType == 1 || animType == 2 || animType == 3) - { - playerSprite->x2 = 8; - if (GetPlayerFacingDirection() == 3) - playerSprite->x2 = -8; - } - if (animType == 5) - playerSprite->y2 = -8; - if (animType == 10 || animType == 11) - playerSprite->y2 = 8; - if (gPlayerAvatar.flags & PLAYER_AVATAR_FLAG_SURFING) - SetSurfBlob_PlayerOffset(gObjectEvents[gPlayerAvatar.objectEventId].fieldEffectSpriteId, TRUE, playerSprite->y2); -} - void SetSpinStartFacingDir(u8 direction) { sSpinStartFacingDir = direction; diff --git a/src/field_screen_effect.c b/src/field_screen_effect.c index 74d2008ac9..2a3a5993d8 100644 --- a/src/field_screen_effect.c +++ b/src/field_screen_effect.c @@ -24,6 +24,7 @@ #include "mirage_tower.h" #include "metatile_behavior.h" #include "palette.h" +#include "oras_dowse.h" #include "overworld.h" #include "scanline_effect.h" #include "script.h" @@ -684,6 +685,7 @@ void Task_WarpAndLoadMap(u8 taskId) case 0: FreezeObjectEvents(); LockPlayerFieldControls(); + EndORASDowsing(); task->tState++; break; case 1: @@ -745,6 +747,7 @@ void Task_DoDoorWarp(u8 taskId) ObjectEventSetHeldMovement(followerObject, MOVEMENT_ACTION_ENTER_POKEBALL); } task->tDoorTask = FieldAnimateDoorOpen(*x, *y - 1); + EndORASDowsing(); task->tState = DOORWARP_START_WALK_UP; break; case DOORWARP_START_WALK_UP: diff --git a/src/field_special_scene.c b/src/field_special_scene.c index ccb15f02b4..6c66b50f8b 100644 --- a/src/field_special_scene.c +++ b/src/field_special_scene.c @@ -34,7 +34,7 @@ #define BOX3_Y_OFFSET 0 // porthole states -enum +enum PortholeState { INIT_PORTHOLE, IDLE_CHECK, @@ -300,7 +300,7 @@ void Task_HandlePorthole(u8 taskId) u16 *cruiseState = GetVarPointer(VAR_SS_TIDAL_STATE); struct WarpData *location = &gSaveBlock1Ptr->location; - switch (data[0]) + switch ((enum PortholeState)data[0]) { case INIT_PORTHOLE: // finish fading before making porthole finish. if (!gPaletteFade.active) diff --git a/src/field_specials.c b/src/field_specials.c index 716503b55c..8ac07cc693 100644 --- a/src/field_specials.c +++ b/src/field_specials.c @@ -123,14 +123,14 @@ static void Task_MoveElevator(u8); static void MoveElevatorWindowLights(u16, bool8); static void Task_MoveElevatorWindowLights(u8); static void Task_ShowScrollableMultichoice(u8); -static void FillFrontierExchangeCornerWindowAndItemIcon(u16, u16); -static void ShowBattleFrontierTutorWindow(u8, u16); +static void FillFrontierExchangeCornerWindowAndItemIcon(enum ScrollMulti, u16); +static void ShowBattleFrontierTutorWindow(enum ScrollMulti, u16); static void InitScrollableMultichoice(void); static void ScrollableMultichoice_ProcessInput(u8); static void ScrollableMultichoice_UpdateScrollArrows(u8); static void ScrollableMultichoice_MoveCursor(s32, bool8, struct ListMenu *); -static void HideFrontierExchangeCornerItemIcon(u16, u16); -static void ShowBattleFrontierTutorMoveDescription(u8, u16); +static void HideFrontierExchangeCornerItemIcon(enum ScrollMulti, u16); +static void ShowBattleFrontierTutorMoveDescription(enum ScrollMulti, u16); static void CloseScrollableMultichoice(u8); static void ScrollableMultichoice_RemoveScrollArrows(u8); static void Task_ScrollableMultichoice_WaitReturnToList(u8); @@ -315,10 +315,11 @@ bool32 CountSSTidalStep(u16 delta) return TRUE; } -u8 GetSSTidalLocation(s8 *mapGroup, s8 *mapNum, s16 *x, s16 *y) +enum SSTidalLocation GetSSTidalLocation(s8 *mapGroup, s8 *mapNum, s16 *x, s16 *y) { u16 *varCruiseStepCount = GetVarPointer(VAR_CRUISE_STEP_COUNT); - switch (*GetVarPointer(VAR_SS_TIDAL_STATE)) + + switch ((enum SSTidalState)(*GetVarPointer(VAR_SS_TIDAL_STATE))) { case SS_TIDAL_BOARD_SLATEPORT: case SS_TIDAL_LAND_SLATEPORT: @@ -1782,7 +1783,7 @@ static const u16 sElevatorWindowTiles_Descending[ELEVATOR_WINDOW_HEIGHT][ELEVATO void SetDeptStoreFloor(void) { - u8 deptStoreFloor; + enum DeptStoreFloorNumber deptStoreFloor; switch (gSaveBlock1Ptr->dynamicWarp.mapNum) { case MAP_NUM(MAP_LILYCOVE_CITY_DEPARTMENT_STORE_1F): @@ -2295,7 +2296,7 @@ void ShowScrollableMultichoice(void) struct Task *task = &gTasks[taskId]; task->tScrollMultiId = gSpecialVar_0x8004; - switch (gSpecialVar_0x8004) + switch ((enum ScrollMulti)gSpecialVar_0x8004) { case SCROLL_MULTI_NONE: task->tMaxItemsOnScreen = 1; @@ -2990,7 +2991,7 @@ void CloseFrontierExchangeCornerItemIconWindow(void) RemoveWindow(sFrontierExchangeCorner_ItemIconWindowId); } -static void FillFrontierExchangeCornerWindowAndItemIcon(u16 menu, u16 selection) +static void FillFrontierExchangeCornerWindowAndItemIcon(enum ScrollMulti menu, u16 selection) { #include "data/battle_frontier/battle_frontier_exchange_corner.h" @@ -3033,6 +3034,8 @@ static void FillFrontierExchangeCornerWindowAndItemIcon(u16 menu, u16 selection) AddTextPrinterParameterized2(0, FONT_NORMAL, sFrontierExchangeCorner_HoldItemsDescriptions[selection], 0, NULL, TEXT_COLOR_DARK_GRAY, TEXT_COLOR_WHITE, TEXT_COLOR_LIGHT_GRAY); ShowFrontierExchangeCornerItemIcon(sFrontierExchangeCorner_HoldItems[selection]); break; + default: + break; } } } @@ -3051,7 +3054,7 @@ static void ShowFrontierExchangeCornerItemIcon(u16 item) } } -static void HideFrontierExchangeCornerItemIcon(u16 menu, u16 unused) +static void HideFrontierExchangeCornerItemIcon(enum ScrollMulti menu, u16 unused) { if (sScrollableMultichoice_ItemSpriteId != MAX_SPRITES) { @@ -3064,6 +3067,8 @@ static void HideFrontierExchangeCornerItemIcon(u16 menu, u16 unused) // This makes sure deleting the icon will not clear palettes in use by object events FieldEffectFreeGraphicsResources(&gSprites[sScrollableMultichoice_ItemSpriteId]); break; + default: + break; } sScrollableMultichoice_ItemSpriteId = MAX_SPRITES; } @@ -3074,7 +3079,7 @@ void BufferBattleFrontierTutorMoveName(void) StringCopy(gStringVar1, GetMoveName(gSpecialVar_0x8005)); } -static void ShowBattleFrontierTutorWindow(u8 menu, u16 selection) +static void ShowBattleFrontierTutorWindow(enum ScrollMulti menu, u16 selection) { static const struct WindowTemplate sBattleFrontierTutor_WindowTemplate = { @@ -3098,7 +3103,7 @@ static void ShowBattleFrontierTutorWindow(u8 menu, u16 selection) } } -static void ShowBattleFrontierTutorMoveDescription(u8 menu, u16 selection) +static void ShowBattleFrontierTutorMoveDescription(enum ScrollMulti menu, u16 selection) { static const u8 *const sBattleFrontier_TutorMoveDescriptions1[] = { @@ -4308,8 +4313,8 @@ void GetObjectPosition(u16* xPointer, u16* yPointer, u32 localId, u32 useTemplat objectId = GetObjectEventIdByLocalId(localId); objEvent = &gObjectEvents[objectId]; - *xPointer = objEvent->currentCoords.x - 7; - *yPointer = objEvent->currentCoords.y - 7; + *xPointer = objEvent->currentCoords.x - MAP_OFFSET; + *yPointer = objEvent->currentCoords.y - MAP_OFFSET; } bool32 CheckObjectAtXY(u32 x, u32 y) @@ -4351,6 +4356,7 @@ void UseBlankMessageToCancelPokemonPic(void) void EnterCode(void) { + StringCopy(gStringVar2, COMPOUND_STRING("")); DoNamingScreen(NAMING_SCREEN_CODE, gStringVar2, 0, 0, 0, CB2_ReturnToFieldContinueScript); } @@ -4369,3 +4375,9 @@ void SetHiddenNature(void) SetMonData(&gPlayerParty[gSpecialVar_0x8004], MON_DATA_HIDDEN_NATURE, &hiddenNature); CalculateMonStats(&gPlayerParty[gSpecialVar_0x8004]); } + +void SetAbility(void) +{ + u32 ability = gSpecialVar_Result; + SetMonData(&gPlayerParty[gSpecialVar_0x8004], MON_DATA_ABILITY_NUM, &ability); +} diff --git a/src/fishing.c b/src/fishing.c new file mode 100644 index 0000000000..7730351abb --- /dev/null +++ b/src/fishing.c @@ -0,0 +1,650 @@ +#include "global.h" +#include "main.h" +#include "event_object_movement.h" +#include "fieldmap.h" +#include "field_effect_helpers.h" +#include "field_player_avatar.h" +#include "menu.h" +#include "metatile_behavior.h" +#include "random.h" +#include "script.h" +#include "strings.h" +#include "task.h" +#include "text.h" +#include "tv.h" +#include "wild_encounter.h" +#include "config/fishing.h" + +static void Task_Fishing(u8); +static bool32 Fishing_Init(struct Task *); +static bool32 Fishing_GetRodOut(struct Task *); +static bool32 Fishing_WaitBeforeDots(struct Task *); +static bool32 Fishing_InitDots(struct Task *); +static bool32 Fishing_ShowDots(struct Task *); +static bool32 Fishing_CheckForBite(struct Task *); +static bool32 Fishing_GotBite(struct Task *); +static bool32 Fishing_ChangeMinigame(struct Task *); +static bool32 Fishing_WaitForA(struct Task *); +static bool32 Fishing_APressNoMinigame(struct Task *); +static bool32 Fishing_CheckMoreDots(struct Task *); +static bool32 Fishing_MonOnHook(struct Task *); +static bool32 Fishing_StartEncounter(struct Task *); +static bool32 Fishing_NotEvenNibble(struct Task *); +static bool32 Fishing_GotAway(struct Task *); +static bool32 Fishing_NoMon(struct Task *); +static bool32 Fishing_PutRodAway(struct Task *); +static bool32 Fishing_EndNoMon(struct Task *); +static void AlignFishingAnimationFrames(void); +static bool32 DoesFishingMinigameAllowCancel(void); +static bool32 Fishing_DoesFirstMonInPartyHaveSuctionCupsOrStickyHold(void); +static bool32 Fishing_RollForBite(u32, bool32); +static u32 CalculateFishingBiteOdds(u32, bool32); +static u32 CalculateFishingFollowerBoost(void); +static u32 CalculateFishingProximityBoost(void); +static u32 CalculateFishingTimeOfDayBoost(void); + +#define FISHING_PROXIMITY_BOOST 20 //Active if config I_FISHING_PROXIMITY is TRUE +#define FISHING_TIME_OF_DAY_BOOST 20 //Active if config I_FISHING_TIME_OF_DAY_BOOST is TRUE +#define FISHING_GEN3_STICKY_CHANCE 85 //Active if config I_FISHING_STICKY_BOOST is set to GEN_3 or lower + +#if I_FISHING_BITE_ODDS >= GEN_4 + #define FISHING_OLD_ROD_ODDS 25 + #define FISHING_GOOD_ROD_ODDS 50 + #define FISHING_SUPER_ROD_ODDS 75 +#elif I_FISHING_BITE_ODDS >= GEN_3 + #define FISHING_OLD_ROD_ODDS 50 + #define FISHING_GOOD_ROD_ODDS 50 + #define FISHING_SUPER_ROD_ODDS 50 +#else + #define FISHING_OLD_ROD_ODDS 100 + #define FISHING_GOOD_ROD_ODDS 33 + #define FISHING_SUPER_ROD_ODDS 50 +#endif + +struct FriendshipHookChanceBoost +{ + u8 threshold; + u8 bonus; +}; + +//Needs to be defined in descending order and end with the 0 friendship boost +//Active if config I_FISHING_FOLLOWER_BOOST is TRUE +static const struct FriendshipHookChanceBoost sFriendshipHookChanceBoostArray[] = +{ + {.threshold = 250, .bonus = 50}, + {.threshold = 200, .bonus = 40}, + {.threshold = 150, .bonus = 30}, + {.threshold = 100, .bonus = 20}, + {.threshold = 0, .bonus = 0}, +}; + +#define FISHING_CHAIN_SHINY_STREAK_MAX 20 + +enum +{ + FISHING_INIT, + FISHING_GET_ROD_OUT, + FISHING_WAIT_BEFORE_DOTS, + FISHING_INIT_DOTS, + FISHING_SHOW_DOTS, + FISHING_CHECK_FOR_BITE, + FISHING_GOT_BITE, + FISHING_CHANGE_MINIGAME, + FISHING_WAIT_FOR_A, + FISHING_A_PRESS_NO_MINIGAME, + FISHING_CHECK_MORE_DOTS, + FISHING_MON_ON_HOOK, + FISHING_START_ENCOUNTER, + FISHING_NOT_EVEN_NIBBLE, + FISHING_GOT_AWAY, + FISHING_NO_MON, + FISHING_PUT_ROD_AWAY, + FISHING_END_NO_MON, +}; + +static bool32 (*const sFishingStateFuncs[])(struct Task *) = +{ + [FISHING_INIT] = Fishing_Init, + [FISHING_GET_ROD_OUT] = Fishing_GetRodOut, + [FISHING_WAIT_BEFORE_DOTS] = Fishing_WaitBeforeDots, + [FISHING_INIT_DOTS] = Fishing_InitDots, + [FISHING_SHOW_DOTS] = Fishing_ShowDots, + [FISHING_CHECK_FOR_BITE] = Fishing_CheckForBite, + [FISHING_GOT_BITE] = Fishing_GotBite, + [FISHING_CHANGE_MINIGAME] = Fishing_ChangeMinigame, + [FISHING_WAIT_FOR_A] = Fishing_WaitForA, + [FISHING_A_PRESS_NO_MINIGAME] = Fishing_APressNoMinigame, + [FISHING_CHECK_MORE_DOTS] = Fishing_CheckMoreDots, + [FISHING_MON_ON_HOOK] = Fishing_MonOnHook, + [FISHING_START_ENCOUNTER] = Fishing_StartEncounter, + [FISHING_NOT_EVEN_NIBBLE] = Fishing_NotEvenNibble, + [FISHING_GOT_AWAY] = Fishing_GotAway, + [FISHING_NO_MON] = Fishing_NoMon, + [FISHING_PUT_ROD_AWAY] = Fishing_PutRodAway, + [FISHING_END_NO_MON] = Fishing_EndNoMon, +}; + +#define tStep data[0] +#define tFrameCounter data[1] +#define tNumDots data[2] +#define tDotsRequired data[3] +#define tRoundsPlayed data[12] +#define tMinRoundsRequired data[13] +#define tPlayerGfxId data[14] +#define tFishingRod data[15] + +void StartFishing(u8 rod) +{ + u8 taskId = CreateTask(Task_Fishing, 0xFF); + + gTasks[taskId].tFishingRod = rod; + Task_Fishing(taskId); +} + +static void Task_Fishing(u8 taskId) +{ + while (sFishingStateFuncs[gTasks[taskId].tStep](&gTasks[taskId])) + ; +} + +static bool32 Fishing_Init(struct Task *task) +{ + LockPlayerFieldControls(); + gPlayerAvatar.preventStep = TRUE; + task->tStep = FISHING_GET_ROD_OUT; + return FALSE; +} + +static bool32 Fishing_GetRodOut(struct Task *task) +{ + struct ObjectEvent *playerObjEvent; + const s16 minRounds1[] = { + [OLD_ROD] = 1, + [GOOD_ROD] = 1, + [SUPER_ROD] = 1 + }; + const s16 minRounds2[] = { + [OLD_ROD] = 1, + [GOOD_ROD] = 3, + [SUPER_ROD] = 6 + }; + + task->tRoundsPlayed = 0; + task->tMinRoundsRequired = minRounds1[task->tFishingRod] + (Random() % minRounds2[task->tFishingRod]); + task->tPlayerGfxId = gObjectEvents[gPlayerAvatar.objectEventId].graphicsId; + playerObjEvent = &gObjectEvents[gPlayerAvatar.objectEventId]; + ObjectEventClearHeldMovementIfActive(playerObjEvent); + playerObjEvent->enableAnim = TRUE; + SetPlayerAvatarFishing(playerObjEvent->facingDirection); + task->tStep = FISHING_WAIT_BEFORE_DOTS; + return FALSE; +} + +static bool32 Fishing_WaitBeforeDots(struct Task *task) +{ + AlignFishingAnimationFrames(); + + // Wait one second + task->tFrameCounter++; + if (task->tFrameCounter >= 60) + task->tStep = FISHING_INIT_DOTS; + return FALSE; +} + +static bool32 Fishing_InitDots(struct Task *task) +{ + u32 randVal; + + LoadMessageBoxAndFrameGfx(0, TRUE); + task->tStep = FISHING_SHOW_DOTS; + task->tFrameCounter = 0; + task->tNumDots = 0; + randVal = Random(); + randVal %= 10; + task->tDotsRequired = randVal + 1; + if (task->tRoundsPlayed == 0) + task->tDotsRequired = randVal + 4; + if (task->tDotsRequired >= 10) + task->tDotsRequired = 10; + return TRUE; +} + +static bool32 Fishing_ShowDots(struct Task *task) +{ + const u8 dot[] = _("·"); + + AlignFishingAnimationFrames(); + task->tFrameCounter++; + if (JOY_NEW(A_BUTTON)) + { + if (!DoesFishingMinigameAllowCancel()) + return FALSE; + + task->tStep = FISHING_NOT_EVEN_NIBBLE; + if (task->tRoundsPlayed != 0) + task->tStep = FISHING_GOT_AWAY; + return TRUE; + } + else + { + if (task->tFrameCounter >= 20) + { + task->tFrameCounter = 0; + if (task->tNumDots >= task->tDotsRequired) + { + task->tStep = FISHING_CHECK_FOR_BITE; + if (task->tRoundsPlayed != 0) + task->tStep = FISHING_GOT_BITE; + task->tRoundsPlayed++; + } + else + { + AddTextPrinterParameterized(0, FONT_NORMAL, dot, task->tNumDots * 8, 1, 0, NULL); + task->tNumDots++; + } + } + return FALSE; + } +} + +static bool32 Fishing_CheckForBite(struct Task *task) +{ + bool32 bite, firstMonHasSuctionOrSticky; + + AlignFishingAnimationFrames(); + task->tStep = FISHING_GOT_BITE; + bite = FALSE; + + if (!DoesCurrentMapHaveFishingMons()) + { + task->tStep = FISHING_NOT_EVEN_NIBBLE; + return TRUE; + } + + firstMonHasSuctionOrSticky = Fishing_DoesFirstMonInPartyHaveSuctionCupsOrStickyHold(); + + if(firstMonHasSuctionOrSticky && I_FISHING_STICKY_BOOST < GEN_4) + bite = RandomPercentage(RNG_FISHING_GEN3_STICKY, FISHING_GEN3_STICKY_CHANCE); + + if (!bite) + bite = Fishing_RollForBite(task->tFishingRod, firstMonHasSuctionOrSticky); + + if (!bite) + task->tStep = FISHING_NOT_EVEN_NIBBLE; + + if (bite) + StartSpriteAnim(&gSprites[gPlayerAvatar.spriteId], GetFishingBiteDirectionAnimNum(GetPlayerFacingDirection())); + + return TRUE; +} + +static bool32 Fishing_GotBite(struct Task *task) +{ + AlignFishingAnimationFrames(); + AddTextPrinterParameterized(0, FONT_NORMAL, gText_OhABite, 0, 17, 0, NULL); + task->tStep = FISHING_CHANGE_MINIGAME; + task->tFrameCounter = 0; + return FALSE; +} + +static bool32 Fishing_ChangeMinigame(struct Task *task) +{ + switch (I_FISHING_MINIGAME) + { + case GEN_1: + case GEN_2: + task->tStep = FISHING_A_PRESS_NO_MINIGAME; + break; + case GEN_3: + default: + task->tStep = FISHING_WAIT_FOR_A; + break; + } + return TRUE; +} + +// We have a bite. Now, wait for the player to press A, or the timer to expire. +static bool32 Fishing_WaitForA(struct Task *task) +{ + const s16 reelTimeouts[3] = { + [OLD_ROD] = 36, + [GOOD_ROD] = 33, + [SUPER_ROD] = 30 + }; + + AlignFishingAnimationFrames(); + task->tFrameCounter++; + if (task->tFrameCounter >= reelTimeouts[task->tFishingRod]) + task->tStep = FISHING_GOT_AWAY; + else if (JOY_NEW(A_BUTTON)) + task->tStep = FISHING_CHECK_MORE_DOTS; + return FALSE; +} + +static bool32 Fishing_APressNoMinigame(struct Task *task) +{ + AlignFishingAnimationFrames(); + if (JOY_NEW(A_BUTTON)) + task->tStep = FISHING_MON_ON_HOOK; + return FALSE; +} + +// Determine if we're going to play the dot game again +static bool32 Fishing_CheckMoreDots(struct Task *task) +{ + const s16 moreDotsChance[][2] = + { + [OLD_ROD] = {0, 0}, + [GOOD_ROD] = {40, 10}, + [SUPER_ROD] = {70, 30} + }; + + AlignFishingAnimationFrames(); + task->tStep = FISHING_MON_ON_HOOK; + if (task->tRoundsPlayed < task->tMinRoundsRequired) + { + task->tStep = FISHING_INIT_DOTS; + } + else if (task->tRoundsPlayed < 2) + { + // probability of having to play another round + s16 probability = Random() % 100; + + if (moreDotsChance[task->tFishingRod][task->tRoundsPlayed] > probability) + task->tStep = FISHING_INIT_DOTS; + } + return FALSE; +} + +static bool32 Fishing_MonOnHook(struct Task *task) +{ + AlignFishingAnimationFrames(); + FillWindowPixelBuffer(0, PIXEL_FILL(1)); + AddTextPrinterParameterized2(0, FONT_NORMAL, gText_PokemonOnHook, 1, 0, TEXT_COLOR_DARK_GRAY, TEXT_COLOR_WHITE, TEXT_COLOR_LIGHT_GRAY); + task->tStep = FISHING_START_ENCOUNTER; + task->tFrameCounter = 0; + return FALSE; +} + +static bool32 Fishing_StartEncounter(struct Task *task) +{ + if (task->tFrameCounter == 0) + AlignFishingAnimationFrames(); + + RunTextPrinters(); + + if (task->tFrameCounter == 0) + { + if (!IsTextPrinterActive(0)) + { + struct ObjectEvent *playerObjEvent = &gObjectEvents[gPlayerAvatar.objectEventId]; + + ObjectEventSetGraphicsId(playerObjEvent, task->tPlayerGfxId); + ObjectEventTurn(playerObjEvent, playerObjEvent->movementDirection); + if (gPlayerAvatar.flags & PLAYER_AVATAR_FLAG_SURFING) + SetSurfBlob_PlayerOffset(gObjectEvents[gPlayerAvatar.objectEventId].fieldEffectSpriteId, FALSE, 0); + gSprites[gPlayerAvatar.spriteId].x2 = 0; + gSprites[gPlayerAvatar.spriteId].y2 = 0; + ClearDialogWindowAndFrame(0, TRUE); + task->tFrameCounter++; + return FALSE; + } + } + + if (task->tFrameCounter != 0) + { + gPlayerAvatar.preventStep = FALSE; + UnlockPlayerFieldControls(); + FishingWildEncounter(task->tFishingRod); + RecordFishingAttemptForTV(TRUE); + DestroyTask(FindTaskIdByFunc(Task_Fishing)); + } + return FALSE; +} + +static bool32 Fishing_NotEvenNibble(struct Task *task) +{ + gChainFishingDexNavStreak = 0; + AlignFishingAnimationFrames(); + StartSpriteAnim(&gSprites[gPlayerAvatar.spriteId], GetFishingNoCatchDirectionAnimNum(GetPlayerFacingDirection())); + FillWindowPixelBuffer(0, PIXEL_FILL(1)); + AddTextPrinterParameterized2(0, FONT_NORMAL, gText_NotEvenANibble, 1, 0, TEXT_COLOR_DARK_GRAY, TEXT_COLOR_WHITE, TEXT_COLOR_LIGHT_GRAY); + task->tStep = FISHING_NO_MON; + return TRUE; +} + +static bool32 Fishing_GotAway(struct Task *task) +{ + gChainFishingDexNavStreak = 0; + AlignFishingAnimationFrames(); + StartSpriteAnim(&gSprites[gPlayerAvatar.spriteId], GetFishingNoCatchDirectionAnimNum(GetPlayerFacingDirection())); + FillWindowPixelBuffer(0, PIXEL_FILL(1)); + AddTextPrinterParameterized2(0, FONT_NORMAL, gText_ItGotAway, 1, 0, TEXT_COLOR_DARK_GRAY, TEXT_COLOR_WHITE, TEXT_COLOR_LIGHT_GRAY); + task->tStep = FISHING_NO_MON; + return TRUE; +} + +static bool32 Fishing_NoMon(struct Task *task) +{ + AlignFishingAnimationFrames(); + task->tStep = FISHING_PUT_ROD_AWAY; + return FALSE; +} + +static bool32 Fishing_PutRodAway(struct Task *task) +{ + AlignFishingAnimationFrames(); + if (gSprites[gPlayerAvatar.spriteId].animEnded) + { + struct ObjectEvent *playerObjEvent = &gObjectEvents[gPlayerAvatar.objectEventId]; + + ObjectEventSetGraphicsId(playerObjEvent, task->tPlayerGfxId); + ObjectEventTurn(playerObjEvent, playerObjEvent->movementDirection); + if (gPlayerAvatar.flags & PLAYER_AVATAR_FLAG_SURFING) + SetSurfBlob_PlayerOffset(gObjectEvents[gPlayerAvatar.objectEventId].fieldEffectSpriteId, FALSE, 0); + gSprites[gPlayerAvatar.spriteId].x2 = 0; + gSprites[gPlayerAvatar.spriteId].y2 = 0; + task->tStep = FISHING_END_NO_MON; + } + return FALSE; +} + +static bool32 Fishing_EndNoMon(struct Task *task) +{ + RunTextPrinters(); + if (!IsTextPrinterActive(0)) + { + gPlayerAvatar.preventStep = FALSE; + UnlockPlayerFieldControls(); + UnfreezeObjectEvents(); + ClearDialogWindowAndFrame(0, TRUE); + RecordFishingAttemptForTV(FALSE); + DestroyTask(FindTaskIdByFunc(Task_Fishing)); + } + return FALSE; +} + +static bool32 DoesFishingMinigameAllowCancel(void) +{ + switch(I_FISHING_MINIGAME) + { + case GEN_1: + case GEN_2: + return FALSE; + case GEN_3: + default: + return TRUE; + } +} + +static bool32 Fishing_DoesFirstMonInPartyHaveSuctionCupsOrStickyHold(void) +{ + enum Ability ability; + + if (GetMonData(&gPlayerParty[0], MON_DATA_SANITY_IS_EGG)) + return FALSE; + + ability = GetMonAbility(&gPlayerParty[0]); + + return (ability == ABILITY_SUCTION_CUPS || ability == ABILITY_STICKY_HOLD); +} + +static bool32 Fishing_RollForBite(u32 rod, bool32 isStickyHold) +{ + return ((RandomUniform(RNG_FISHING_BITE, 1, 100)) <= CalculateFishingBiteOdds(rod, isStickyHold)); +} + +static u32 CalculateFishingBiteOdds(u32 rod, bool32 isStickyHold) +{ + u32 odds; + + if (rod == OLD_ROD) + odds = FISHING_OLD_ROD_ODDS; + if (rod == GOOD_ROD) + odds = FISHING_GOOD_ROD_ODDS; + if (rod == SUPER_ROD) + odds = FISHING_SUPER_ROD_ODDS; + + odds += CalculateFishingFollowerBoost(); + odds += CalculateFishingProximityBoost(); + odds += CalculateFishingTimeOfDayBoost(); + + if (isStickyHold && I_FISHING_STICKY_BOOST >= GEN_4) + odds *= 2; + + odds = min(100, odds); + DebugPrintf("Fishing odds: %d", odds); + return odds; +} + +static u32 CalculateFishingFollowerBoost() +{ + u32 friendship; + struct Pokemon *mon = GetFirstLiveMon(); + + if (!I_FISHING_FOLLOWER_BOOST || !mon) + return 0; + + friendship = GetMonData(mon, MON_DATA_FRIENDSHIP); + for (u32 i = 0;; i++) + { + if (friendship >= sFriendshipHookChanceBoostArray[i].threshold) + return sFriendshipHookChanceBoostArray[i].bonus; + } +} + +static u32 CalculateFishingProximityBoost() +{ + s16 bobber_x, bobber_y, tile_x, tile_y; + u32 direction, facingDirection, numQualifyingTile = 0; + struct ObjectEvent *objectEvent; + + if (!I_FISHING_PROXIMITY) + return 0; + + objectEvent = &gObjectEvents[gPlayerAvatar.objectEventId]; + + bobber_x = objectEvent->currentCoords.x; + bobber_y = objectEvent->currentCoords.y; + + facingDirection = GetPlayerFacingDirection(); + MoveCoords(facingDirection, &bobber_x, &bobber_y); + + numQualifyingTile = 0; + for (direction = DIR_SOUTH; direction < CARDINAL_DIRECTION_COUNT; direction++) + { + tile_x = bobber_x; + tile_y = bobber_y; + MoveCoords(direction, &tile_x, &tile_y); + if (tile_x == objectEvent->currentCoords.x && tile_y == objectEvent->currentCoords.y) + continue; + if (!MetatileBehavior_IsSurfableFishableWater(MapGridGetMetatileBehaviorAt(tile_x, tile_y))) + numQualifyingTile++; + else if (MapGridGetCollisionAt(tile_x, tile_y)) + numQualifyingTile++; + else if (GetMapBorderIdAt(tile_x, tile_y) == -1) + numQualifyingTile++; + } + + return (numQualifyingTile * FISHING_PROXIMITY_BOOST); +} + +static u32 CalculateFishingTimeOfDayBoost() +{ + if (!I_FISHING_TIME_OF_DAY_BOOST) + return 0; + + enum TimeOfDay timeOfDay = GetTimeOfDay(); + if (timeOfDay == TIME_MORNING || timeOfDay == TIME_EVENING) + return FISHING_TIME_OF_DAY_BOOST; + return 0; +} + +#undef tStep +#undef tFrameCounter +#undef tNumDots +#undef tDotsRequired +#undef tRoundsPlayed +#undef tMinRoundsRequired +#undef tPlayerGfxId +#undef tFishingRod + +static void AlignFishingAnimationFrames(void) +{ + struct Sprite *playerSprite = &gSprites[gPlayerAvatar.spriteId]; + u8 animCmdIndex; + u8 animType; + + AnimateSprite(playerSprite); + playerSprite->x2 = 0; + playerSprite->y2 = 0; + animCmdIndex = playerSprite->animCmdIndex; + if (playerSprite->anims[playerSprite->animNum][animCmdIndex].type == -1) + { + animCmdIndex--; + } + else + { + playerSprite->animDelayCounter++; + if (playerSprite->anims[playerSprite->animNum][animCmdIndex].type == -1) + animCmdIndex--; + } + animType = playerSprite->anims[playerSprite->animNum][animCmdIndex].type; + if (animType == 1 || animType == 2 || animType == 3) + { + playerSprite->x2 = 8; + if (GetPlayerFacingDirection() == 3) + playerSprite->x2 = -8; + } + if (animType == 5) + playerSprite->y2 = -8; + if (animType == 10 || animType == 11) + playerSprite->y2 = 8; + if (gPlayerAvatar.flags & PLAYER_AVATAR_FLAG_SURFING) + SetSurfBlob_PlayerOffset(gObjectEvents[gPlayerAvatar.objectEventId].fieldEffectSpriteId, TRUE, playerSprite->y2); +} + +void UpdateChainFishingStreak() +{ + if (!I_FISHING_CHAIN) + return; + + if (gChainFishingDexNavStreak == MAX_u8) + return; + + gChainFishingDexNavStreak++; +} + +u32 CalculateChainFishingShinyRolls(void) +{ + if (!I_FISHING_CHAIN || !gIsFishingEncounter) + return 0; + u32 a = 2 * min(gChainFishingDexNavStreak, FISHING_CHAIN_SHINY_STREAK_MAX); + DebugPrintf("Total Shiny Rolls %d", a); + return a; +} + +bool32 ShouldUseFishingEnvironmentInBattle() +{ + return (I_FISHING_ENVIRONMENT >= GEN_4 && gIsFishingEncounter); +} \ No newline at end of file diff --git a/src/fldeff_cut.c b/src/fldeff_cut.c index 4344186a54..a5f45ab29e 100644 --- a/src/fldeff_cut.c +++ b/src/fldeff_cut.c @@ -140,7 +140,7 @@ bool32 SetUpFieldMove_Cut(void) s16 x, y; u8 i, j; u8 tileBehavior; - u16 userAbility; + enum Ability userAbility; bool8 cutTiles[CUT_NORMAL_AREA]; bool8 ret; diff --git a/src/follower_helper.c b/src/follower_helper.c index c4352b09c8..ce1fe51ec4 100644 --- a/src/follower_helper.c +++ b/src/follower_helper.c @@ -74,7 +74,7 @@ static const u8* const sDayTexts[] = {sCondMsg43, sCondMsg44, NULL}; static const u8 sCondMsg45[] = _("你的宝可梦正呆呆地\n凝望着夜空!"); static const u8 sCondMsg46[] = _("你的宝可梦正开心地\n凝视着美丽的星空!"); static const u8* const sNightTexts[] = {sCondMsg45, sCondMsg46, NULL}; -static const u8 sCondMsg50[] = _("{STR_VAR_1} is disturbed by the\nabnormal weather!"); +static const u8 sCondMsg50[] = _("{STR_VAR_1}正受到\n异常天气的困扰!"); // See the struct definition in follower_helper.h for more info const struct FollowerMsgInfoExtended gFollowerConditionalMessages[COND_MSG_COUNT] = diff --git a/src/follower_npc.c b/src/follower_npc.c index 1833d555ab..2cca3186b3 100644 --- a/src/follower_npc.c +++ b/src/follower_npc.c @@ -4,6 +4,7 @@ #include "battle.h" #include "battle_setup.h" #include "battle_tower.h" +#include "bike.h" #include "event_data.h" #include "event_object_movement.h" #include "event_scripts.h" @@ -52,6 +53,8 @@ static void TurnNPCIntoFollower(u32 localId, u32 followerFlags, u32 setScript, c static u32 GetFollowerNPCSprite(void); static bool32 FollowerNPCHasRunningFrames(void); static bool32 IsStateMovement(u32 state); +static u32 GetNewPlayerMovementDirection(u32 state); +static bool32 IsPlayerForcedOntoSameTile(u8 metatileBehavior, u8 direction); static u32 GetPlayerFaceToDoorDirection(struct ObjectEvent *player, struct ObjectEvent *follower); static u32 ReturnFollowerNPCDelayedState(u32 direction); static void TryUpdateFollowerNPCSpriteUnderwater(void); @@ -351,6 +354,115 @@ static bool32 IsStateMovement(u32 state) return TRUE; } +// Because we want the NPC follower's movements to happen simultaneously with the player's, +// we need to set the follower's movement before the player object's movementDirection parameter gets set. +// This function allows us to determine the player's new movement direction before it gets set. +static u32 GetNewPlayerMovementDirection(u32 state) +{ + switch (state) + { + case MOVEMENT_ACTION_WALK_SLOW_DOWN: + case MOVEMENT_ACTION_WALK_NORMAL_DOWN: + case MOVEMENT_ACTION_WALK_FAST_DOWN: + case MOVEMENT_ACTION_WALK_FASTER_DOWN: + case MOVEMENT_ACTION_PLAYER_RUN_DOWN: + case MOVEMENT_ACTION_ACRO_WHEELIE_HOP_DOWN: + case MOVEMENT_ACTION_ACRO_WHEELIE_JUMP_DOWN: + case MOVEMENT_ACTION_ACRO_POP_WHEELIE_MOVE_DOWN: + case MOVEMENT_ACTION_ACRO_WHEELIE_MOVE_DOWN: + case MOVEMENT_ACTION_ACRO_END_WHEELIE_MOVE_DOWN: + case MOVEMENT_ACTION_RIDE_WATER_CURRENT_DOWN: + case MOVEMENT_ACTION_JUMP_DOWN: + return DIR_SOUTH; + case MOVEMENT_ACTION_WALK_SLOW_UP: + case MOVEMENT_ACTION_WALK_NORMAL_UP: + case MOVEMENT_ACTION_WALK_FAST_UP: + case MOVEMENT_ACTION_WALK_FASTER_UP: + case MOVEMENT_ACTION_PLAYER_RUN_UP: + case MOVEMENT_ACTION_ACRO_WHEELIE_HOP_UP: + case MOVEMENT_ACTION_ACRO_WHEELIE_JUMP_UP: + case MOVEMENT_ACTION_ACRO_POP_WHEELIE_MOVE_UP: + case MOVEMENT_ACTION_ACRO_WHEELIE_MOVE_UP: + case MOVEMENT_ACTION_ACRO_END_WHEELIE_MOVE_UP: + case MOVEMENT_ACTION_RIDE_WATER_CURRENT_UP: + case MOVEMENT_ACTION_JUMP_UP: + return DIR_NORTH; + case MOVEMENT_ACTION_WALK_SLOW_LEFT: + case MOVEMENT_ACTION_WALK_NORMAL_LEFT: + case MOVEMENT_ACTION_WALK_FAST_LEFT: + case MOVEMENT_ACTION_WALK_FASTER_LEFT: + case MOVEMENT_ACTION_PLAYER_RUN_LEFT: + case MOVEMENT_ACTION_ACRO_WHEELIE_HOP_LEFT: + case MOVEMENT_ACTION_ACRO_WHEELIE_JUMP_LEFT: + case MOVEMENT_ACTION_ACRO_POP_WHEELIE_MOVE_LEFT: + case MOVEMENT_ACTION_ACRO_WHEELIE_MOVE_LEFT: + case MOVEMENT_ACTION_ACRO_END_WHEELIE_MOVE_LEFT: + case MOVEMENT_ACTION_RIDE_WATER_CURRENT_LEFT: + case MOVEMENT_ACTION_JUMP_LEFT: + return DIR_WEST; + case MOVEMENT_ACTION_WALK_SLOW_RIGHT: + case MOVEMENT_ACTION_WALK_NORMAL_RIGHT: + case MOVEMENT_ACTION_WALK_FAST_RIGHT: + case MOVEMENT_ACTION_WALK_FASTER_RIGHT: + case MOVEMENT_ACTION_PLAYER_RUN_RIGHT: + case MOVEMENT_ACTION_ACRO_WHEELIE_HOP_RIGHT: + case MOVEMENT_ACTION_ACRO_WHEELIE_JUMP_RIGHT: + case MOVEMENT_ACTION_ACRO_POP_WHEELIE_MOVE_RIGHT: + case MOVEMENT_ACTION_ACRO_WHEELIE_MOVE_RIGHT: + case MOVEMENT_ACTION_ACRO_END_WHEELIE_MOVE_RIGHT: + case MOVEMENT_ACTION_RIDE_WATER_CURRENT_RIGHT: + case MOVEMENT_ACTION_JUMP_RIGHT: + return DIR_EAST; + default: + return DIR_NONE; + } +} + +static bool32 IsPlayerForcedOntoSameTile(u8 metatileBehavior, u8 direction) +{ + u8 oppositeDirection = DIR_NONE; + + switch (metatileBehavior) + { + case MB_WALK_EAST: + case MB_SLIDE_EAST: + case MB_EASTWARD_CURRENT: + oppositeDirection = DIR_WEST; + break; + case MB_WALK_WEST: + case MB_SLIDE_WEST: + case MB_WESTWARD_CURRENT: + oppositeDirection = DIR_EAST; + break; + case MB_WALK_NORTH: + case MB_SLIDE_NORTH: + case MB_NORTHWARD_CURRENT: + oppositeDirection = DIR_SOUTH; + break; + case MB_WALK_SOUTH: + case MB_SLIDE_SOUTH: + case MB_SOUTHWARD_CURRENT: + case MB_MUDDY_SLOPE: + case MB_WATERFALL: + oppositeDirection = DIR_NORTH; + break; + default: + return FALSE; + } + + if (oppositeDirection == direction) + return TRUE; + + return FALSE; +} + +void GetXYCoordsPlayerMovementDest(u32 direction, s16 *x, s16 *y) +{ + *x = gObjectEvents[gPlayerAvatar.objectEventId].currentCoords.x; + *y = gObjectEvents[gPlayerAvatar.objectEventId].currentCoords.y; + MoveCoords(direction, x, y); +} + static u32 GetPlayerFaceToDoorDirection(struct ObjectEvent *player, struct ObjectEvent *follower) { s32 delta_x = player->currentCoords.x - follower->currentCoords.x; @@ -760,6 +872,9 @@ u32 DetermineFollowerNPCState(struct ObjectEvent *follower, u32 state, u32 direc u32 nextBehavior; u32 noSpecialAnimFrames = (GetFollowerNPCSprite() == GetFollowerNPCData(FNPC_DATA_GFX_ID)); u32 delayedState = GetFollowerNPCData(FNPC_DATA_DELAYED_STATE); + s16 playerDestX, playerDestY; + u32 playerMoveDirection = GetNewPlayerMovementDirection(state); + u32 newPlayerMB; MoveCoords(direction, &followerX, &followerY); nextBehavior = MapGridGetMetatileBehaviorAt(followerX, followerY); @@ -769,6 +884,24 @@ u32 DetermineFollowerNPCState(struct ObjectEvent *follower, u32 state, u32 direc if (!IsStateMovement(state) && delayedState) return MOVEMENT_ACTION_NONE; + // Follower won't move if player is forced back onto the same tile. + if (GetFollowerNPCData(FNPC_DATA_FORCED_MOVEMENT) == FNPC_FORCED_STAY) + return MOVEMENT_ACTION_NONE; + + GetXYCoordsPlayerMovementDest(playerMoveDirection, &playerDestX, &playerDestY); + newPlayerMB = MapGridGetMetatileBehaviorAt(playerDestX, playerDestY); + + if (IsPlayerForcedOntoSameTile(newPlayerMB, playerMoveDirection) + && !(gPlayerAvatar.flags & PLAYER_AVATAR_FLAG_MACH_BIKE && playerMoveDirection == DIR_NORTH && newPlayerMB == MB_MUDDY_SLOPE && GetPlayerSpeed() >= PLAYER_SPEED_FAST)) + { + SetFollowerNPCData(FNPC_DATA_FORCED_MOVEMENT, FNPC_FORCED_STAY); + SetFollowerNPCData(FNPC_DATA_DELAYED_STATE, 0); + if (gPlayerAvatar.flags & PLAYER_AVATAR_FLAG_ON_FOOT) + ObjectEventSetHeldMovement(follower, GetFaceDirectionAnimNum(follower->facingDirection)); + + return MOVEMENT_INVALID; + } + if (IsStateMovement(state) && delayedState) { // Lock face direction for Acro side jump. @@ -1592,25 +1725,40 @@ void Task_MoveNPCFollowerAfterForcedMovement(u8 taskId) struct ObjectEvent *follower = &gObjectEvents[GetFollowerNPCObjectId()]; struct ObjectEvent *player = &gObjectEvents[gPlayerAvatar.objectEventId]; - // The NPC will take an extra step and be on the same tile as the player. - if (gTasks[taskId].tState == NPC_INTO_PLAYER && ObjectEventClearHeldMovementIfFinished(player) != 0 && ObjectEventClearHeldMovementIfFinished(follower) != 0) + // If follower moved during player's forced momvements. + if (GetFollowerNPCData(FNPC_DATA_FORCED_MOVEMENT) == FNPC_FORCED_FOLLOW) { - if (follower->currentMetatileBehavior == MB_MUDDY_SLOPE) - follower->facingDirectionLocked = TRUE; + // The NPC will take an extra step and be on the same tile as the player. + if (gTasks[taskId].tState == NPC_INTO_PLAYER && ObjectEventClearHeldMovementIfFinished(player) != 0 && ObjectEventClearHeldMovementIfFinished(follower) != 0) + { + if (follower->currentMetatileBehavior == MB_MUDDY_SLOPE) + follower->facingDirectionLocked = TRUE; - ObjectEventSetHeldMovement(follower, GetWalkFastMovementAction(DetermineFollowerNPCDirection(player, follower))); - gTasks[taskId].tState = ENABLE_PLAYER_STEP; - return; + ObjectEventSetHeldMovement(follower, GetWalkFastMovementAction(DetermineFollowerNPCDirection(player, follower))); + gTasks[taskId].tState = ENABLE_PLAYER_STEP; + return; + } + // Hide the NPC until the player takes a step. Reallow player input. + else if (gTasks[taskId].tState == ENABLE_PLAYER_STEP && ObjectEventClearHeldMovementIfFinished(follower) != 0) + { + follower->facingDirectionLocked = FALSE; + HideNPCFollower(); + SetFollowerNPCData(FNPC_DATA_WARP_END, FNPC_WARP_REAPPEAR); + SetFollowerNPCData(FNPC_DATA_FORCED_MOVEMENT, FNPC_FORCED_NONE); + gPlayerAvatar.preventStep = FALSE; + DestroyTask(taskId); + } } - // Hide the NPC until the player takes a step. Reallow player input. - else if (gTasks[taskId].tState == ENABLE_PLAYER_STEP && ObjectEventClearHeldMovementIfFinished(follower) != 0) + // If player was forced back onto the same tile. + else if (GetFollowerNPCData(FNPC_DATA_FORCED_MOVEMENT) == FNPC_FORCED_STAY) { - follower->facingDirectionLocked = FALSE; - HideNPCFollower(); - SetFollowerNPCData(FNPC_DATA_WARP_END, FNPC_WARP_REAPPEAR); - SetFollowerNPCData(FNPC_DATA_FORCED_MOVEMENT, FALSE); - gPlayerAvatar.preventStep = FALSE; - DestroyTask(taskId); + if (ObjectEventClearHeldMovementIfFinished(player) != 0) + { + SetFollowerNPCData(FNPC_DATA_FORCED_MOVEMENT, FNPC_FORCED_NONE); + SetFollowerNPCData(FNPC_DATA_DELAYED_STATE, 0); + gPlayerAvatar.preventStep = FALSE; + DestroyTask(taskId); + } } } diff --git a/src/frontier_util.c b/src/frontier_util.c index 8b6de020a0..578c5386f8 100644 --- a/src/frontier_util.c +++ b/src/frontier_util.c @@ -38,6 +38,7 @@ #include "constants/items.h" #include "constants/event_objects.h" #include "party_menu.h" +#include "list_menu.h" struct FrontierBrainMon { @@ -93,6 +94,9 @@ static void ShowArenaResultsWindow(void); static void ShowPyramidResultsWindow(void); static void ShowLinkContestResultsWindow(void); static void CopyFrontierBrainText(bool8 playerWonText); +static u16 *MakeCaughtBannesSpeciesList(u32 totalBannedSpecies); +static void PrintBannedSpeciesName(u8 windowId, u32 itemId, u8 y); +static void Task_BannedSpeciesWindowInput(u8 taskId); // 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) @@ -784,6 +788,58 @@ static const u8 *const sHallFacilityToRecordsText[] = [RANKING_HALL_TOWER_LINK] = gText_FrontierFacilityWinStreak, }; + +#define BANNED_SPECIES_SHOWN 6 + +static const struct ListMenuTemplate sCaughtBannedSpeciesListTemplate = +{ + .items = NULL, + .isDynamic = TRUE, + .moveCursorFunc = ListMenuDefaultCursorMoveFunc, + .itemPrintFunc = PrintBannedSpeciesName, + .maxShowed = BANNED_SPECIES_SHOWN, + .header_X = 0, + .item_X = 8, + .cursor_X = 0, + .upText_Y = 1, + .cursorPal = 2, + .fillValue = 1, + .cursorShadowPal = 3, + .lettersSpacing = 1, + .itemVerticalPadding = 0, + .scrollMultiple = LIST_NO_MULTIPLE_SCROLL, + .fontId = FONT_NORMAL, + .cursorKind = 0 +}; + +static const struct WindowTemplate sBannedSpeciesWindowTemplateMain = +{ + .bg = 0, + .tilemapLeft = 1, + .tilemapTop = 1, + .width = 12, + .height = 2 * BANNED_SPECIES_SHOWN, + .paletteNum = 15, + .baseBlock = 1, +}; + +#define TAG_LIST_ARROWS 5425 + +static const struct ScrollArrowsTemplate sCaughtBannedSpeciesScrollArrowsTemplate = +{ + .firstArrowType = SCROLL_ARROW_UP, + .firstX = 56, + .firstY = 8, + .secondArrowType = SCROLL_ARROW_DOWN, + .secondX = 56, + .secondY = 104, + .fullyUpThreshold = 0, + .fullyDownThreshold = 0, + .tileTag = TAG_LIST_ARROWS, + .palTag = TAG_LIST_ARROWS, + .palNum = 0, +}; + // code void CallFrontierUtilFunc(void) { @@ -1943,21 +1999,18 @@ static void CheckBattleTypeFlag(void) gSpecialVar_Result = FALSE; } -#define SPECIES_PER_LINE 3 - static void AppendCaughtBannedMonSpeciesName(u16 species, u8 count, s32 numBannedMonsCaught) { - if (numBannedMonsCaught == count) + if (count == 1) + ; + else if (numBannedMonsCaught == count) StringAppend(gStringVar1, gText_SpaceAndSpace); else if (numBannedMonsCaught > count) StringAppend(gStringVar1, gText_CommaSpace); - if ((count % SPECIES_PER_LINE) == 0) - { - if (count == SPECIES_PER_LINE) - StringAppend(gStringVar1, gText_NewLine); - else - StringAppend(gStringVar1, gText_LineBreak); - } + if (count == 3) + StringAppend(gStringVar1, gText_NewLine2); + else if (count == 6) + StringAppend(gStringVar1, gText_LineBreak); StringAppend(gStringVar1, GetSpeciesName(species)); } @@ -2053,37 +2106,60 @@ static void CheckPartyIneligibility(void) if (numEligibleMons < toChoose) { - u32 i; + u32 i, j; u32 baseSpecies = 0; u32 totalCaughtBanned = 0; - u32 caughtBanned[100] = {0}; + u32 totalPartyBanned = 0; + u32 partyBanned[PARTY_SIZE] = {0}; for (i = 0; i < NUM_SPECIES; i++) { - if (totalCaughtBanned >= ARRAY_COUNT(caughtBanned)) - break; baseSpecies = GET_BASE_SPECIES_ID(i); - if (baseSpecies == i) + if (baseSpecies == i && gSpeciesInfo[baseSpecies].isFrontierBanned) { - if (gSpeciesInfo[baseSpecies].isFrontierBanned) + if (GetSetPokedexFlag(SpeciesToNationalPokedexNum(baseSpecies), FLAG_GET_CAUGHT)) + totalCaughtBanned++; + } + } + + for (i = 0; i < PARTY_SIZE; i++) + { + u16 species = GetMonData(&gPlayerParty[i], MON_DATA_SPECIES_OR_EGG); + if (species == SPECIES_EGG || species == SPECIES_NONE) + continue; + if (gSpeciesInfo[GET_BASE_SPECIES_ID(species)].isFrontierBanned) + { + bool32 addToList = TRUE; + for (j = 0; j < totalPartyBanned; j++) + if (partyBanned[j] == species) + addToList = FALSE; + if (addToList) { - if (GetSetPokedexFlag(SpeciesToNationalPokedexNum(baseSpecies), FLAG_GET_CAUGHT)) - { - caughtBanned[totalCaughtBanned] = baseSpecies; - totalCaughtBanned++; - } + partyBanned[totalPartyBanned] = species; + totalPartyBanned++; } } } + gStringVar1[0] = EOS; gSpecialVar_0x8004 = TRUE; - for (i = 0; i < totalCaughtBanned; i++) - AppendCaughtBannedMonSpeciesName(caughtBanned[i], i+1, totalCaughtBanned); - - if (totalCaughtBanned <= 2) - StringAppend(gStringVar1, gText_NewLine); - else if (totalCaughtBanned % SPECIES_PER_LINE == SPECIES_PER_LINE - 1) - StringAppend(gStringVar1, gText_LineBreak); + if (totalCaughtBanned == 0) + { + StringAppend(gStringVar1, gText_FrontierFacilityAreInelegible); + } + else + { + ConvertIntToDecimalStringN(gStringVar2, totalCaughtBanned, STR_CONV_MODE_LEFT_ALIGN, 3); + StringExpandPlaceholders(gStringVar4, gText_FrontierFacilityTotalCaughtSpeciesBanned); + StringAppend(gStringVar1, gStringVar4); + } + if (totalPartyBanned > 0) + { + StringAppend(gStringVar1, gText_FrontierFacilityIncluding); + for (i = 0; i < totalPartyBanned; i++) + AppendCaughtBannedMonSpeciesName(partyBanned[i], i+1, totalPartyBanned); + } + gSpecialVar_0x8005 = totalCaughtBanned; } else { @@ -2093,8 +2169,6 @@ static void CheckPartyIneligibility(void) #undef numEligibleMons } -#undef SPECIES_PER_LINE - static void ValidateVisitingTrainer(void) { ValidateEReaderTrainer(); @@ -2640,3 +2714,98 @@ void ClearEnemyPartyAfterChallenge() ZeroEnemyPartyMons(); } } + +#define tWindowId data[0] +#define tMenuTaskId data[1] +#define tArrowTaskId data[2] +#define tScrollOffset data[3] +#define tListPointerElemId 4 + +static u16 *MakeCaughtBannesSpeciesList(u32 totalBannedSpecies) +{ + u32 count = 0; + u16 *list = AllocZeroed(sizeof(u16) * totalBannedSpecies); + for (u32 i = 0; i < NUM_SPECIES; i++) + { + u32 baseSpecies = GET_BASE_SPECIES_ID(i); + if (baseSpecies == i && gSpeciesInfo[baseSpecies].isFrontierBanned) + { + if (GetSetPokedexFlag(SpeciesToNationalPokedexNum(baseSpecies), FLAG_GET_CAUGHT)) + { + list[count] = i; + count++; + } + } + } + return list; +} + +static void PrintBannedSpeciesName(u8 windowId, u32 itemId, u8 y) +{ + u8 colors[3] = { + sCaughtBannedSpeciesListTemplate.fillValue, + sCaughtBannedSpeciesListTemplate.cursorPal, + sCaughtBannedSpeciesListTemplate.cursorShadowPal + }; + u16 *list = (u16 *) GetWordTaskArg(gSpecialVar_0x8006, tListPointerElemId); + AddTextPrinterParameterized4(windowId, + sCaughtBannedSpeciesListTemplate.fontId, + sCaughtBannedSpeciesListTemplate.item_X, y, + sCaughtBannedSpeciesListTemplate.lettersSpacing, 0, colors, TEXT_SKIP_DRAW, + GetSpeciesName(list[itemId])); +} + +void ShowBattleFrontierCaughtBannedSpecies(void) +{ + u8 windowId; + struct ListMenuTemplate listTemplate = sCaughtBannedSpeciesListTemplate; + u32 totalCaughtBanned = gSpecialVar_0x8005; + listTemplate.totalItems = totalCaughtBanned; + + // create window + LoadMessageBoxAndBorderGfx(); + windowId = AddWindow(&sBannedSpeciesWindowTemplateMain); + DrawStdWindowFrame(windowId, FALSE); + listTemplate.windowId = windowId; + + u16 *listItems = MakeCaughtBannesSpeciesList(totalCaughtBanned); + u32 inputTaskId = CreateTask(Task_BannedSpeciesWindowInput, 3); + gTasks[inputTaskId].tWindowId = windowId; + gSpecialVar_0x8006 = inputTaskId; + SetWordTaskArg(inputTaskId, tListPointerElemId, (u32)listItems); + u32 menuTaskId = ListMenuInit(&listTemplate, 0, 0); + gTasks[inputTaskId].tMenuTaskId = menuTaskId; + gTasks[inputTaskId].tArrowTaskId = TASK_NONE; + if (listTemplate.totalItems > listTemplate.maxShowed) + { + gTempScrollArrowTemplate = sCaughtBannedSpeciesScrollArrowsTemplate; + gTempScrollArrowTemplate.fullyDownThreshold = listTemplate.totalItems - listTemplate.maxShowed; + gTasks[inputTaskId].tArrowTaskId = AddScrollIndicatorArrowPair(&gTempScrollArrowTemplate, (u16 *)&gTasks[inputTaskId].tScrollOffset); + } + + // draw everything + CopyWindowToVram(windowId, COPYWIN_FULL); +} + +static void Task_BannedSpeciesWindowInput(u8 taskId) +{ + ListMenu_ProcessInput(gTasks[taskId].tMenuTaskId); + ListMenuGetScrollAndRow(gTasks[taskId].tMenuTaskId, (u16 *)&gTasks[taskId].tScrollOffset, NULL); + if (JOY_NEW(B_BUTTON)) + { + ScriptContext_Enable(); + if (gTasks[taskId].tArrowTaskId < TASK_NONE) + RemoveScrollIndicatorArrowPair(gTasks[taskId].tArrowTaskId); + Free((struct ListItem *)(GetWordTaskArg(taskId, tListPointerElemId))); + DestroyListMenuTask(gTasks[taskId].tMenuTaskId, NULL, NULL); + ClearStdWindowAndFrame(gTasks[taskId].tWindowId, TRUE); + RemoveWindow(gTasks[taskId].tWindowId); + DestroyTask(taskId); + } +} + +#undef tWindowId +#undef tMenuTaskId +#undef tArrowTaskId +#undef tScrollOffset +#undef tListPointerElemId diff --git a/src/generational_changes.c b/src/generational_changes.c index 1ad29aa675..a02b6ce944 100644 --- a/src/generational_changes.c +++ b/src/generational_changes.c @@ -3,17 +3,113 @@ #include "malloc.h" #include "constants/generational_changes.h" -#if TESTING -EWRAM_DATA u8 *gGenerationalChangesTestOverride = NULL; +#define UNPACK_CONFIG_GEN_CHANGES2(_name, _field, ...) ._field = B_##_name, +const struct GenChanges sConfigChanges = +{ + CONFIG_DEFINITIONS(UNPACK_CONFIG_GEN_CHANGES2) + /* Expands to: + .critChance = B_CRIT_CHANCE, + .critMultiplier = B_CRIT_MULTIPLIER, + */ +}; + +#if TESTING +EWRAM_DATA struct GenChanges *gConfigChangesTestOverride = NULL; +#define UNPACK_CONFIG_OVERRIDE_GETTERS(_name, _field, ...) case CONFIG_##_name: return gConfigChangesTestOverride->_field; +#define UNPACK_CONFIG_GETTERS(_name, _field, ...) case CONFIG_##_name: return sConfigChanges._field; +#define UNPACK_CONFIG_CLAMPER(_name, _field, _typeMaxValue, ...) case CONFIG_##_name: clampedValue = min(GET_CONFIG_MAXIMUM(_typeMaxValue), newValue); break; +#define UNPACK_CONFIG_SETTERS(_name, _field, _typeMaxValue, ...) case CONFIG_##_name: gConfigChangesTestOverride->_field = clampedValue; break; + +#else + +#define UNPACK_CONFIG_OVERRIDE_GETTERS(_name, _field, ...) case CONFIG_##_name: return sConfigChanges._field; +#define UNPACK_CONFIG_GETTERS(_name, _field, ...) case CONFIG_##_name: return sConfigChanges._field; +#define UNPACK_CONFIG_CLAMPER(_name, _field, ...) case CONFIG_##_name: return 0; +#define UNPACK_CONFIG_SETTERS(_name, _field, ...) case CONFIG_##_name: return; +#endif + +// Gets the value of a volatile status flag for a certain battler +// Primarily used for the debug menu and scripts. Outside of it explicit references are preferred +u32 GetConfig(enum ConfigTag _genConfig) +{ +#if TESTING + if (gConfigChangesTestOverride == NULL) + { + switch (_genConfig) + { + CONFIG_DEFINITIONS(UNPACK_CONFIG_GETTERS) + /* Expands to: + case CONFIG_CRIT_CHANCE: + return gConfigChangesTestOverride->critChance; + */ + default: + return 0; + } + } + else +#endif + { + switch (_genConfig) + { + CONFIG_DEFINITIONS(UNPACK_CONFIG_OVERRIDE_GETTERS) + /* Expands to: + case CONFIG_CRIT_CHANCE: + return sConfigChanges.critChance; + */ + default: // Invalid config tag + return 0; + } + } +} + +#if TESTING +u32 GetClampedValue(enum ConfigTag _genConfig, u32 newValue) +{ + u32 clampedValue = 0; + switch(_genConfig) + { + CONFIG_DEFINITIONS(UNPACK_CONFIG_CLAMPER) + default: + return 0; + } + return clampedValue; +} +#endif + +void SetConfig(enum ConfigTag _genConfig, u32 _value) +{ +#if TESTING + // Clamping is done here instead of the switch due to an internal compiler error! + u32 clampedValue = GetClampedValue(_genConfig, _value); + switch (_genConfig) + { + CONFIG_DEFINITIONS(UNPACK_CONFIG_SETTERS) + /* Expands to: + #if TESTING + case CONFIG_CRIT_CHANCE: + gConfigChangesTestOverride->critChance = clampedValue; + break; + #else + case CONFIG_CRIT_CHANCE: + return; + #endif + */ + default: // Invalid config tag + return; + } +#endif +} + +#if TESTING void TestInitConfigData(void) { - gGenerationalChangesTestOverride = Alloc(sizeof(sGenerationalChanges)); - memcpy(gGenerationalChangesTestOverride, sGenerationalChanges, sizeof(sGenerationalChanges)); + gConfigChangesTestOverride = Alloc(sizeof(sConfigChanges)); + memcpy(gConfigChangesTestOverride, &sConfigChanges, sizeof(sConfigChanges)); } void TestFreeConfigData(void) { - TRY_FREE_AND_SET_NULL(gGenerationalChangesTestOverride) + TRY_FREE_AND_SET_NULL(gConfigChangesTestOverride) } #endif diff --git a/src/international_string_util.c b/src/international_string_util.c index feba03c97f..b5a904c773 100644 --- a/src/international_string_util.c +++ b/src/international_string_util.c @@ -220,7 +220,7 @@ void FillWindowTilesByRow(int windowId, int columnStart, int rowStart, int numFi fillSize = numFillTiles * TILE_SIZE_4BPP; windowRowSize = window->window.width * TILE_SIZE_4BPP; - windowTileData = window->tileData + (rowStart * windowRowSize) + (columnStart * TILE_SIZE_4BPP); + windowTileData = (u8 *)window->tileData + (rowStart * windowRowSize) + (columnStart * TILE_SIZE_4BPP); if (numRows > 0) { for (i = numRows; i != 0; i--) diff --git a/src/item.c b/src/item.c index 908e2814be..9a631f559c 100644 --- a/src/item.c +++ b/src/item.c @@ -413,6 +413,13 @@ bool32 RemoveBagItem(u16 itemId, u16 count) return BagPocket_RemoveItem(&gBagPockets[GetItemPocket(itemId)], itemId, count); } +// Unsafe function: Only use with functions that already check the slot and count are valid +void RemoveBagItemFromSlot(struct BagPocket *pocket, u16 slotId, u16 count) +{ + struct ItemSlot itemSlot = BagPocket_GetSlotData(pocket, slotId); + BagPocket_SetSlotItemIdAndCount(pocket, slotId, itemSlot.itemId, itemSlot.quantity - count); +} + static u8 NONNULL BagPocket_CountUsedItemSlots(struct BagPocket *pocket) { u8 usedSlots = 0; @@ -814,7 +821,7 @@ const u8 *GetItemEffect(u32 itemId) return gItemsInfo[SanitizeItemId(itemId)].effect; } -u32 GetItemHoldEffect(u32 itemId) +enum HoldEffect GetItemHoldEffect(u32 itemId) { return gItemsInfo[SanitizeItemId(itemId)].holdEffect; } @@ -937,7 +944,7 @@ u32 GetItemSellPrice(u32 itemId) return GetItemPrice(itemId) / ITEM_SELL_FACTOR; } -bool32 IsHoldEffectChoice(enum ItemHoldEffect holdEffect) +bool32 IsHoldEffectChoice(enum HoldEffect holdEffect) { return holdEffect == HOLD_EFFECT_CHOICE_BAND || holdEffect == HOLD_EFFECT_CHOICE_SCARF diff --git a/src/item_menu.c b/src/item_menu.c index f999b31480..8b7aa84cc1 100755 --- a/src/item_menu.c +++ b/src/item_menu.c @@ -170,6 +170,7 @@ static void PrintThereIsNoPokemon(u8); static void Task_ChooseHowManyToToss(u8); static void AskTossItems(u8); static void Task_RemoveItemFromBag(u8); +static void Task_TossItemFromBag(u8 taskId); static void ItemMenu_Cancel(u8); static void HandleErrorMessage(u8); static void PrintItemCantBeHeld(u8); @@ -1958,11 +1959,34 @@ static void ConfirmToss(u8 taskId) StringExpandPlaceholders(gStringVar4, gText_ThrewAwayVar2Var1s); FillWindowPixelBuffer(WIN_DESCRIPTION, PIXEL_FILL(0)); BagMenu_Print(WIN_DESCRIPTION, FONT_NORMAL, gStringVar4, 3, 1, 0, 0, 0, COLORID_NORMAL); - gTasks[taskId].func = Task_RemoveItemFromBag; + if (CurrentBattlePyramidLocation() != PYRAMID_LOCATION_NONE || FlagGet(FLAG_STORING_ITEMS_IN_PYRAMID_BAG) == TRUE) + gTasks[taskId].func = Task_RemoveItemFromBag; + else + gTasks[taskId].func = Task_TossItemFromBag; +} + +static void Task_TossItemFromBag(u8 taskId) +{ + s16 *data = gTasks[taskId].data; + u16 *scrollPos = &gBagPosition.scrollPosition[gBagPosition.pocket]; + u16 *cursorPos = &gBagPosition.cursorPosition[gBagPosition.pocket]; + + if (JOY_NEW(A_BUTTON | B_BUTTON)) + { + PlaySE(SE_SELECT); + RemoveBagItemFromSlot(&gBagPockets[gBagPosition.pocket], *scrollPos + *cursorPos, tItemCount); + DestroyListMenuTask(tListTaskId, scrollPos, cursorPos); + UpdatePocketItemList(gBagPosition.pocket); + UpdatePocketListPosition(gBagPosition.pocket); + LoadBagItemListBuffers(gBagPosition.pocket); + tListTaskId = ListMenuInit(&gMultiuseListMenuTemplate, *scrollPos, *cursorPos); + ScheduleBgCopyTilemapToVram(0); + ReturnToItemList(taskId); + } } // Remove selected item(s) from the bag and update list -// For when items are tossed or deposited +// For when items are deposited static void Task_RemoveItemFromBag(u8 taskId) { s16 *data = gTasks[taskId].data; diff --git a/src/item_use.c b/src/item_use.c index 9fc4176949..49c40e4c7e 100644 --- a/src/item_use.c +++ b/src/item_use.c @@ -18,6 +18,7 @@ #include "field_player_avatar.h" #include "field_screen_effect.h" #include "field_weather.h" +#include "fishing.h" #include "fldeff.h" #include "follower_npc.h" #include "item.h" @@ -28,6 +29,7 @@ #include "menu.h" #include "menu_helpers.h" #include "metatile_behavior.h" +#include "oras_dowse.h" #include "overworld.h" #include "palette.h" #include "party_menu.h" @@ -54,8 +56,6 @@ static void Task_UseItemfinder(u8); static void Task_CloseItemfinderMessage(u8); static void Task_HiddenItemNearby(u8); static void Task_StandingOnHiddenItem(u8); -static bool8 ItemfinderCheckForHiddenItems(const struct MapEvents *, u8); -static u8 GetDirectionToHiddenItem(s16, s16); static void PlayerFaceHiddenItem(u8); static void CheckForHiddenItemsInMapConnection(u8); static void Task_OpenRegisteredPokeblockCase(u8); @@ -367,10 +367,20 @@ void ItemUseOutOfBattle_Itemfinder(u8 var) static void ItemUseOnFieldCB_Itemfinder(u8 taskId) { - if (ItemfinderCheckForHiddenItems(gMapHeader.events, taskId) == TRUE) - gTasks[taskId].func = Task_UseItemfinder; + if (I_ORAS_DOWSING_FLAG != 0) + { + if (!TestPlayerAvatarFlags(PLAYER_AVATAR_FLAG_SURFING) && !TestPlayerAvatarFlags(PLAYER_AVATAR_FLAG_UNDERWATER)) + gTasks[taskId].func = Task_UseORASDowsingMachine; + else + DisplayItemMessageOnField(taskId, gText_DadsAdvice, Task_CloseItemfinderMessage); + } else - DisplayItemMessageOnField(taskId, sText_ItemFinderNothing, Task_CloseItemfinderMessage); + { + if (ItemfinderCheckForHiddenItems(gMapHeader.events, taskId) == TRUE) + gTasks[taskId].func = Task_UseItemfinder; + else + DisplayItemMessageOnField(taskId, sText_ItemFinderNothing, Task_CloseItemfinderMessage); + } } // Define itemfinder task data @@ -426,12 +436,15 @@ static void Task_CloseItemfinderMessage(u8 taskId) DestroyTask(taskId); } -static bool8 ItemfinderCheckForHiddenItems(const struct MapEvents *events, u8 taskId) +bool8 ItemfinderCheckForHiddenItems(const struct MapEvents *events, u8 taskId) { int itemX, itemY; s16 playerX, playerY, i, distanceX, distanceY; PlayerGetDestCoords(&playerX, &playerY); - gTasks[taskId].tItemFound = FALSE; + if (I_ORAS_DOWSING_FLAG != 0) + gSprites[gObjectEvents[gPlayerAvatar.objectEventId].fieldEffectSpriteId].tItemFound = FALSE; + else + gTasks[taskId].tItemFound = FALSE; for (i = 0; i < events->bgEventCount; i++) { @@ -451,7 +464,7 @@ static bool8 ItemfinderCheckForHiddenItems(const struct MapEvents *events, u8 ta } CheckForHiddenItemsInMapConnection(taskId); - if (gTasks[taskId].tItemFound == TRUE) + if (gTasks[taskId].tItemFound == TRUE || gSprites[gObjectEvents[gPlayerAvatar.objectEventId].fieldEffectSpriteId].tItemFound) return TRUE; else return FALSE; @@ -550,6 +563,8 @@ static void SetDistanceOfClosestHiddenItem(u8 taskId, s16 itemDistanceX, s16 ite { s16 *data = gTasks[taskId].data; s16 oldItemAbsX, oldItemAbsY, newItemAbsX, newItemAbsY; + if (I_ORAS_DOWSING_FLAG != 0) + data = gSprites[gObjectEvents[gPlayerAvatar.objectEventId].fieldEffectSpriteId].data; if (tItemFound == FALSE) { @@ -606,7 +621,7 @@ static void SetDistanceOfClosestHiddenItem(u8 taskId, s16 itemDistanceX, s16 ite } } -static u8 GetDirectionToHiddenItem(s16 itemDistanceX, s16 itemDistanceY) +u8 GetDirectionToHiddenItem(s16 itemDistanceX, s16 itemDistanceY) { s16 absX, absY; @@ -1133,7 +1148,7 @@ static u32 GetBallThrowableState(void) return BALL_THROW_UNABLE_NO_ROOM; else if (B_SEMI_INVULNERABLE_CATCH >= GEN_4 && IsSemiInvulnerable(GetCatchingBattler(), CHECK_ALL)) return BALL_THROW_UNABLE_SEMI_INVULNERABLE; - else if (FlagGet(B_FLAG_NO_CATCHING)) + else if (FlagGet(B_FLAG_NO_CATCHING) || !IsAllowedToUseBag()) return BALL_THROW_UNABLE_DISABLED_FLAG; return BALL_THROW_ABLE; diff --git a/src/landmark.c b/src/landmark.c index 3ea57ec60a..aa975e9691 100644 --- a/src/landmark.c +++ b/src/landmark.c @@ -15,90 +15,50 @@ struct LandmarkList const struct Landmark *const *landmarks; }; -static const u8 LandmarkName_FlowerShop[] = _("花店"); -static const u8 LandmarkName_PetalburgWoods[] = _("橙华森林"); -static const u8 LandmarkName_MrBrineysCottage[] = _("哈奇老人的小屋"); -static const u8 LandmarkName_AbandonedShip[] = _("弃船"); -static const u8 LandmarkName_SeashoreHouse[] = _("大海之家"); -static const u8 LandmarkName_SlateportBeach[] = _("凯那海滩"); -static const u8 LandmarkName_CyclingRoad[] = _("自行车道"); -static const u8 LandmarkName_NewMauville[] = _("新紫堇"); -static const u8 LandmarkName_TrickHouse[] = _("戏法屋"); -static const u8 LandmarkName_OldLadysRestShop[] = _("简康奶奶的家"); -static const u8 LandmarkName_Desert[] = _("沙漠"); -static const u8 LandmarkName_WinstrateFamily[] = _("连胜家族"); -static const u8 LandmarkName_CableCar[] = _("缆车"); -static const u8 LandmarkName_GlassWorkshop[] = _("琉璃工坊"); -static const u8 LandmarkName_WeatherInstitute[] = _("天气研究所"); -static const u8 LandmarkName_MeteorFalls[] = _("流星瀑布"); -static const u8 LandmarkName_TunnelersRestHouse[] = _("隧道工人休息屋"); -static const u8 LandmarkName_RusturfTunnel[] = _("卡绿隧道"); -static const u8 LandmarkName_PokemonDayCare[] = _("宝可梦培育屋"); -static const u8 LandmarkName_SafariZoneEntrance[] = _("狩猎地带入口"); -static const u8 LandmarkName_MtPyre[] = _("送神山"); -static const u8 LandmarkName_ShoalCave[] = _("浅滩洞穴"); -static const u8 LandmarkName_SeafloorCavern[] = _("海底洞窟"); -static const u8 LandmarkName_GraniteCave[] = _("石之洞窟"); -static const u8 LandmarkName_OceanCurrent[] = _("洋流"); -static const u8 LandmarkName_LanettesHouse[] = _("真由美的家"); -static const u8 LandmarkName_FieryPath[] = _("烈焰小径"); -static const u8 LandmarkName_JaggedPass[] = _("凹凸山道"); -static const u8 LandmarkName_SkyPillar[] = _("天空之柱"); -static const u8 LandmarkName_BerryMastersHouse[] = _("树果名人的家"); -static const u8 LandmarkName_IslandCave[] = _("小岛洞穴"); -static const u8 LandmarkName_DesertRuins[] = _("沙漠遗迹"); -static const u8 LandmarkName_ScorchedSlab[] = _("天旱石窟"); -static const u8 LandmarkName_AncientTomb[] = _("古代坟墓"); -static const u8 LandmarkName_SealedChamber[] = _("布告石室"); -static const u8 LandmarkName_FossilManiacsHouse[] = _("化石迷的家"); -static const u8 LandmarkName_HuntersHouse[] = _("寻宝者的小屋"); -static const u8 LandmarkName_MagmaHideout[] = _("熔岩队基地"); -static const u8 LandmarkName_MirageTower[] = _("幻影之塔"); -static const u8 LandmarkName_AlteringCave[] = _("变化洞窟"); -static const u8 LandmarkName_DesertUnderpass[] = _("沙漠的地下道"); -static const u8 LandmarkName_TrainerHill[] = _("训练家之丘"); +static const u8 LandmarkName_MagmaHideout[] = _("熔岩队基地"); //Unused + +static const struct Landmark Landmark_FlowerShop = {COMPOUND_STRING("花店"), FLAG_LANDMARK_FLOWER_SHOP}; +static const struct Landmark Landmark_PetalburgWoods = {COMPOUND_STRING("橙华森林"), -1}; +static const struct Landmark Landmark_MrBrineysCottage = {COMPOUND_STRING("哈奇老人的小屋"), FLAG_LANDMARK_MR_BRINEY_HOUSE}; +static const struct Landmark Landmark_AbandonedShip = {COMPOUND_STRING("弃船"), FLAG_LANDMARK_ABANDONED_SHIP}; +static const struct Landmark Landmark_SeashoreHouse = {COMPOUND_STRING("大海之家"), FLAG_LANDMARK_SEASHORE_HOUSE}; +static const struct Landmark Landmark_SlateportBeach = {COMPOUND_STRING("凯那海滩"), -1}; +static const struct Landmark Landmark_CyclingRoad = {COMPOUND_STRING("自行车道"), -1}; +static const struct Landmark Landmark_NewMauville = {COMPOUND_STRING("新紫堇"), FLAG_LANDMARK_NEW_MAUVILLE}; +static const struct Landmark Landmark_TrickHouse = {COMPOUND_STRING("戏法屋"), FLAG_LANDMARK_TRICK_HOUSE}; +static const struct Landmark Landmark_OldLadysRestShop = {COMPOUND_STRING("简康奶奶的家"), FLAG_LANDMARK_OLD_LADY_REST_SHOP}; +static const struct Landmark Landmark_Desert = {COMPOUND_STRING("沙漠"), -1}; +static const struct Landmark Landmark_WinstrateFamily = {COMPOUND_STRING("连胜家族"), FLAG_LANDMARK_WINSTRATE_FAMILY}; +static const struct Landmark Landmark_CableCar = {COMPOUND_STRING("缆车"), -1}; +static const struct Landmark Landmark_GlassWorkshop = {COMPOUND_STRING("琉璃工坊"), FLAG_LANDMARK_GLASS_WORKSHOP}; +static const struct Landmark Landmark_WeatherInstitute = {COMPOUND_STRING("天气研究所"), -1}; +static const struct Landmark Landmark_MeteorFalls = {COMPOUND_STRING("流星瀑布"), -1}; +static const struct Landmark Landmark_TunnelersRestHouse = {COMPOUND_STRING("隧道工人休息屋"), FLAG_LANDMARK_TUNNELERS_REST_HOUSE}; +static const struct Landmark Landmark_RusturfTunnel = {COMPOUND_STRING("卡绿隧道"), -1}; +static const struct Landmark Landmark_PokemonDayCare = {COMPOUND_STRING("宝可梦培育屋"), FLAG_LANDMARK_POKEMON_DAYCARE}; +static const struct Landmark Landmark_SafariZoneEntrance = {COMPOUND_STRING("狩猎地带入口"), -1}; +static const struct Landmark Landmark_MtPyre = {COMPOUND_STRING("送神山"), -1}; +static const struct Landmark Landmark_ShoalCave = {COMPOUND_STRING("浅滩洞穴"), -1}; +static const struct Landmark Landmark_SeafloorCavern = {COMPOUND_STRING("海底洞窟"), FLAG_LANDMARK_SEAFLOOR_CAVERN}; +static const struct Landmark Landmark_GraniteCave = {COMPOUND_STRING("石之洞窟"), -1}; +static const struct Landmark Landmark_OceanCurrent = {COMPOUND_STRING("洋流"), -1}; +static const struct Landmark Landmark_LanettesHouse = {COMPOUND_STRING("真由美的家"), FLAG_LANDMARK_LANETTES_HOUSE}; +static const struct Landmark Landmark_FieryPath = {COMPOUND_STRING("烈焰小径"), FLAG_LANDMARK_FIERY_PATH}; +static const struct Landmark Landmark_JaggedPass = {COMPOUND_STRING("凹凸山道"), -1}; +static const struct Landmark Landmark_BerryMastersHouse = {COMPOUND_STRING("树果名人的家"), FLAG_LANDMARK_BERRY_MASTERS_HOUSE}; +static const struct Landmark Landmark_IslandCave = {COMPOUND_STRING("小岛洞穴"), FLAG_LANDMARK_ISLAND_CAVE}; +static const struct Landmark Landmark_DesertRuins = {COMPOUND_STRING("沙漠遗迹"), FLAG_LANDMARK_DESERT_RUINS}; +static const struct Landmark Landmark_ScorchedSlab = {COMPOUND_STRING("天旱石窟"), FLAG_LANDMARK_SCORCHED_SLAB}; +static const struct Landmark Landmark_AncientTomb = {COMPOUND_STRING("古代坟墓"), FLAG_LANDMARK_ANCIENT_TOMB}; +static const struct Landmark Landmark_SealedChamber = {COMPOUND_STRING("布告石室"), FLAG_LANDMARK_SEALED_CHAMBER}; +static const struct Landmark Landmark_FossilManiacsHouse = {COMPOUND_STRING("化石迷的家"), FLAG_LANDMARK_FOSSIL_MANIACS_HOUSE}; +static const struct Landmark Landmark_HuntersHouse = {COMPOUND_STRING("寻宝者的小屋"), FLAG_LANDMARK_HUNTERS_HOUSE}; +static const struct Landmark Landmark_SkyPillar = {COMPOUND_STRING("天空之柱"), FLAG_LANDMARK_SKY_PILLAR}; +static const struct Landmark Landmark_MirageTower = {COMPOUND_STRING("幻影之塔"), FLAG_LANDMARK_MIRAGE_TOWER}; +static const struct Landmark Landmark_AlteringCave = {COMPOUND_STRING("变化洞窟"), FLAG_LANDMARK_ALTERING_CAVE}; +static const struct Landmark Landmark_DesertUnderpass = {COMPOUND_STRING("沙漠的地下道"), FLAG_LANDMARK_DESERT_UNDERPASS}; +static const struct Landmark Landmark_TrainerHill = {COMPOUND_STRING("训练家之丘"), FLAG_LANDMARK_TRAINER_HILL}; -static const struct Landmark Landmark_FlowerShop = {LandmarkName_FlowerShop, FLAG_LANDMARK_FLOWER_SHOP}; -static const struct Landmark Landmark_PetalburgWoods = {LandmarkName_PetalburgWoods, -1}; -static const struct Landmark Landmark_MrBrineysCottage = {LandmarkName_MrBrineysCottage, FLAG_LANDMARK_MR_BRINEY_HOUSE}; -static const struct Landmark Landmark_AbandonedShip = {LandmarkName_AbandonedShip, FLAG_LANDMARK_ABANDONED_SHIP}; -static const struct Landmark Landmark_SeashoreHouse = {LandmarkName_SeashoreHouse, FLAG_LANDMARK_SEASHORE_HOUSE}; -static const struct Landmark Landmark_SlateportBeach = {LandmarkName_SlateportBeach, -1}; -static const struct Landmark Landmark_CyclingRoad = {LandmarkName_CyclingRoad, -1}; -static const struct Landmark Landmark_NewMauville = {LandmarkName_NewMauville, FLAG_LANDMARK_NEW_MAUVILLE}; -static const struct Landmark Landmark_TrickHouse = {LandmarkName_TrickHouse, FLAG_LANDMARK_TRICK_HOUSE}; -static const struct Landmark Landmark_OldLadysRestShop = {LandmarkName_OldLadysRestShop, FLAG_LANDMARK_OLD_LADY_REST_SHOP}; -static const struct Landmark Landmark_Desert = {LandmarkName_Desert, -1}; -static const struct Landmark Landmark_WinstrateFamily = {LandmarkName_WinstrateFamily, FLAG_LANDMARK_WINSTRATE_FAMILY}; -static const struct Landmark Landmark_CableCar = {LandmarkName_CableCar, -1}; -static const struct Landmark Landmark_GlassWorkshop = {LandmarkName_GlassWorkshop, FLAG_LANDMARK_GLASS_WORKSHOP}; -static const struct Landmark Landmark_WeatherInstitute = {LandmarkName_WeatherInstitute, -1}; -static const struct Landmark Landmark_MeteorFalls = {LandmarkName_MeteorFalls, -1}; -static const struct Landmark Landmark_TunnelersRestHouse = {LandmarkName_TunnelersRestHouse, FLAG_LANDMARK_TUNNELERS_REST_HOUSE}; -static const struct Landmark Landmark_RusturfTunnel = {LandmarkName_RusturfTunnel, -1}; -static const struct Landmark Landmark_PokemonDayCare = {LandmarkName_PokemonDayCare, FLAG_LANDMARK_POKEMON_DAYCARE}; -static const struct Landmark Landmark_SafariZoneEntrance = {LandmarkName_SafariZoneEntrance, -1}; -static const struct Landmark Landmark_MtPyre = {LandmarkName_MtPyre, -1}; -static const struct Landmark Landmark_ShoalCave = {LandmarkName_ShoalCave, -1}; -static const struct Landmark Landmark_SeafloorCavern = {LandmarkName_SeafloorCavern, FLAG_LANDMARK_SEAFLOOR_CAVERN}; -static const struct Landmark Landmark_GraniteCave = {LandmarkName_GraniteCave, -1}; -static const struct Landmark Landmark_OceanCurrent = {LandmarkName_OceanCurrent, -1}; -static const struct Landmark Landmark_LanettesHouse = {LandmarkName_LanettesHouse, FLAG_LANDMARK_LANETTES_HOUSE}; -static const struct Landmark Landmark_FieryPath = {LandmarkName_FieryPath, FLAG_LANDMARK_FIERY_PATH}; -static const struct Landmark Landmark_JaggedPass = {LandmarkName_JaggedPass, -1}; -static const struct Landmark Landmark_BerryMastersHouse = {LandmarkName_BerryMastersHouse, FLAG_LANDMARK_BERRY_MASTERS_HOUSE}; -static const struct Landmark Landmark_IslandCave = {LandmarkName_IslandCave, FLAG_LANDMARK_ISLAND_CAVE}; -static const struct Landmark Landmark_DesertRuins = {LandmarkName_DesertRuins, FLAG_LANDMARK_DESERT_RUINS}; -static const struct Landmark Landmark_ScorchedSlab = {LandmarkName_ScorchedSlab, FLAG_LANDMARK_SCORCHED_SLAB}; -static const struct Landmark Landmark_AncientTomb = {LandmarkName_AncientTomb, FLAG_LANDMARK_ANCIENT_TOMB}; -static const struct Landmark Landmark_SealedChamber = {LandmarkName_SealedChamber, FLAG_LANDMARK_SEALED_CHAMBER}; -static const struct Landmark Landmark_FossilManiacsHouse = {LandmarkName_FossilManiacsHouse, FLAG_LANDMARK_FOSSIL_MANIACS_HOUSE}; -static const struct Landmark Landmark_HuntersHouse = {LandmarkName_HuntersHouse, FLAG_LANDMARK_HUNTERS_HOUSE}; -static const struct Landmark Landmark_SkyPillar = {LandmarkName_SkyPillar, FLAG_LANDMARK_SKY_PILLAR}; -static const struct Landmark Landmark_MirageTower = {LandmarkName_MirageTower, FLAG_LANDMARK_MIRAGE_TOWER}; -static const struct Landmark Landmark_AlteringCave = {LandmarkName_AlteringCave, FLAG_LANDMARK_ALTERING_CAVE}; -static const struct Landmark Landmark_DesertUnderpass = {LandmarkName_DesertUnderpass, FLAG_LANDMARK_DESERT_UNDERPASS}; -static const struct Landmark Landmark_TrainerHill = {LandmarkName_TrainerHill, FLAG_LANDMARK_TRAINER_HILL}; static const struct Landmark *const Landmarks_Route103_2[] = { diff --git a/src/list_menu.c b/src/list_menu.c index 124d39ba43..1a129e9f20 100644 --- a/src/list_menu.c +++ b/src/list_menu.c @@ -13,6 +13,10 @@ #include "sound.h" #include "constants/songs.h" +// GF cast Task data to ListMenu in many places, which effectively puts +// an upper bound on sizeof(struct ListMenu). +STATIC_ASSERT(sizeof(struct ListMenu) <= sizeof(((struct Task *)NULL)->data), ListMenuTooLargeForTaskData); + // Cursors after this point are created using a sprite with their own task. // This allows them to have idle animations. Cursors prior to this are simply printed text. #define CURSOR_OBJECT_START CURSOR_RED_OUTLINE @@ -392,7 +396,10 @@ s32 ListMenu_ProcessInput(u8 listTaskId) if (JOY_NEW(A_BUTTON)) { - return list->template.items[list->scrollOffset + list->selectedRow].id; + if (list->template.isDynamic) + return list->scrollOffset + list->selectedRow; + else + return list->template.items[list->scrollOffset + list->selectedRow].id; } else if (JOY_NEW(B_BUTTON)) { @@ -612,7 +619,6 @@ static void ListMenuPrintEntries(struct ListMenu *list, u16 startIndex, u16 yOff s32 i; u8 x, y; u8 yMultiplier = GetFontAttribute(list->template.fontId, FONTATTR_MAX_LETTER_HEIGHT) + list->template.itemVerticalPadding; - for (i = 0; i < count; i++) { if (list->template.items[startIndex].id != LIST_HEADER) @@ -621,10 +627,16 @@ static void ListMenuPrintEntries(struct ListMenu *list, u16 startIndex, u16 yOff x = list->template.header_X; y = (yOffset + i) * yMultiplier + list->template.upText_Y; - if (list->template.itemPrintFunc != NULL) - list->template.itemPrintFunc(list->template.windowId, list->template.items[startIndex].id, y); - - ListMenuPrint(list, list->template.items[startIndex].name, x, y); + if (list->template.isDynamic) + { + list->template.itemPrintFunc(list->template.windowId, startIndex, y); + } + else + { + if (list->template.itemPrintFunc != NULL) + list->template.itemPrintFunc(list->template.windowId, list->template.items[startIndex].id, y); + ListMenuPrint(list, list->template.items[startIndex].name, x, y); + } startIndex++; } } @@ -711,7 +723,7 @@ static u8 ListMenuUpdateSelectedRowIndexAndScrollOffset(struct ListMenu *list, b while (selectedRow != 0) { selectedRow--; - if (list->template.items[scrollOffset + selectedRow].id != LIST_HEADER) + if (list->template.isDynamic || list->template.items[scrollOffset + selectedRow].id != LIST_HEADER) { list->selectedRow = selectedRow; return 1; @@ -725,7 +737,7 @@ static u8 ListMenuUpdateSelectedRowIndexAndScrollOffset(struct ListMenu *list, b while (selectedRow > newRow) { selectedRow--; - if (list->template.items[scrollOffset + selectedRow].id != LIST_HEADER) + if (list->template.isDynamic || list->template.items[scrollOffset + selectedRow].id != LIST_HEADER) { list->selectedRow = selectedRow; return 1; @@ -747,7 +759,7 @@ static u8 ListMenuUpdateSelectedRowIndexAndScrollOffset(struct ListMenu *list, b while (selectedRow < list->template.maxShowed - 1) { selectedRow++; - if (list->template.items[scrollOffset + selectedRow].id != LIST_HEADER) + if (list->template.isDynamic || list->template.items[scrollOffset + selectedRow].id != LIST_HEADER) { list->selectedRow = selectedRow; return 1; @@ -761,7 +773,7 @@ static u8 ListMenuUpdateSelectedRowIndexAndScrollOffset(struct ListMenu *list, b while (selectedRow < newRow) { selectedRow++; - if (list->template.items[scrollOffset + selectedRow].id != LIST_HEADER) + if (list->template.isDynamic || list->template.items[scrollOffset + selectedRow].id != LIST_HEADER) { list->selectedRow = selectedRow; return 1; @@ -825,16 +837,26 @@ bool8 ListMenuChangeSelectionFull(struct ListMenu *list, bool32 updateCursor, bo oldSelectedRow = list->selectedRow; cursorCount = 0; selectionChange = 0; + for (i = 0; i < count; i++) { - do + if (list->template.isDynamic) { u8 ret = ListMenuUpdateSelectedRowIndexAndScrollOffset(list, movingDown); selectionChange |= ret; - if (ret != 2) - break; cursorCount++; - } while (list->template.items[list->scrollOffset + list->selectedRow].id == LIST_HEADER); + } + else + { + do + { + u8 ret = ListMenuUpdateSelectedRowIndexAndScrollOffset(list, movingDown); + selectionChange |= ret; + if (ret != 2) + break; + cursorCount++; + } while (list->template.items[list->scrollOffset + list->selectedRow].id == LIST_HEADER); + } } if (updateCursor) diff --git a/src/main.c b/src/main.c index 3fd080c75b..7abc47265e 100644 --- a/src/main.c +++ b/src/main.c @@ -116,7 +116,7 @@ void AgbMain(void) gSoftResetDisabled = FALSE; if (gFlashMemoryPresent != TRUE) - SetMainCallback2((SAVE_TYPE_ERROR_SCREEN) ? CB2_FlashNotDetectedScreen : NULL); + SetMainCallback2(CB2_FlashNotDetectedScreen); gLinkTransferringData = FALSE; diff --git a/src/match_call.c b/src/match_call.c index 9c2022524b..e8782cf60e 100644 --- a/src/match_call.c +++ b/src/match_call.c @@ -27,6 +27,7 @@ #include "task.h" #include "wild_encounter.h" #include "window.h" +#include "field_name_box.h" #include "constants/abilities.h" #include "constants/battle_frontier.h" #include "constants/event_objects.h" @@ -1321,9 +1322,11 @@ static bool32 MatchCall_PrintIntro(u8 taskId) { FillWindowPixelBuffer(tWindowId, PIXEL_FILL(8)); - // Ready the message + // Ready the message (and the speaker's name if possible) if (!sMatchCallState.triggeredFromScript) SelectMatchCallMessage(sMatchCallState.trainerId, gStringVar4); + + TrySpawnAndShowNamebox(gSpeakerName, NAME_BOX_BASE_TILE_NUM); InitMatchCallTextPrinter(tWindowId, gStringVar4); return TRUE; } @@ -1348,9 +1351,9 @@ static bool32 MatchCall_PrintMessage(u8 taskId) static bool32 MatchCall_SlideWindowOut(u8 taskId) { s16 *data = gTasks[taskId].data; - if (ChangeBgY(0, 0x600, BG_COORD_SUB) <= -0x2000) + if (ChangeBgY(0, 0x600, BG_COORD_SUB) <= -0x4000) { - FillBgTilemapBufferRect_Palette0(0, 0, 0, 14, 30, 6); + FillBgTilemapBufferRect_Palette0(0, 0, 0, 12, 30, 8); DestroyTask(tIconTaskId); RemoveWindow(tWindowId); CopyBgTilemapBufferToVram(0); @@ -1404,6 +1407,31 @@ static void DrawMatchCallTextBoxBorder_Internal(u32 windowId, u32 tileOffset, u3 FillBgTilemapBufferRect_Palette0(bg, ((paletteId << 12) & 0xF000) | (tileNum + 7), x + width, y + height, 1, 1); } +static u8 GetMatchCallWindowId(void) +{ + if (!IsMatchCallTaskActive()) + return WINDOW_NONE; + + u32 taskId = FindTaskIdByFunc(ExecuteMatchCall); + return gTasks[taskId].tWindowId; +} + +// redraw only the top-half +void RedrawMatchCallTextBoxBorder(void) +{ + u32 windowId = GetMatchCallWindowId(); + u32 bg = GetWindowAttribute(windowId, WINDOW_BG); + u32 x = GetWindowAttribute(windowId, WINDOW_TILEMAP_LEFT); + u32 y = GetWindowAttribute(windowId, WINDOW_TILEMAP_TOP); + u32 width = GetWindowAttribute(windowId, WINDOW_WIDTH); + u32 tileNum = TILE_MC_WINDOW + GetBgAttribute(bg, BG_ATTR_BASETILE); + u32 paletteId = 14; + + FillBgTilemapBufferRect_Palette0(bg, ((paletteId << 12) & 0xF000) | (tileNum + 0), x - 1, y - 1, 1, 1); + FillBgTilemapBufferRect_Palette0(bg, ((paletteId << 12) & 0xF000) | (tileNum + 1), x, y - 1, width, 1); + FillBgTilemapBufferRect_Palette0(bg, ((paletteId << 12) & 0xF000) | (tileNum + 2), x + width, y - 1, 1, 1); +} + static void InitMatchCallTextPrinter(int windowId, const u8 *str) { struct TextPrinterTemplate printerTemplate; diff --git a/src/menu.c b/src/menu.c index 59cdb160e4..d30b6ec44e 100644 --- a/src/menu.c +++ b/src/menu.c @@ -1,14 +1,16 @@ #include "global.h" -#include "malloc.h" #include "bg.h" #include "blit.h" #include "decompress.h" #include "dma3.h" #include "event_data.h" +#include "field_name_box.h" #include "field_weather.h" #include "graphics.h" #include "main.h" +#include "malloc.h" #include "map_name_popup.h" +#include "match_call.h" #include "menu.h" #include "menu_helpers.h" #include "palette.h" @@ -22,7 +24,6 @@ #include "task.h" #include "text_window.h" #include "window.h" -#include "config/overworld.h" #include "constants/songs.h" struct MenuInfoIcon @@ -75,13 +76,6 @@ static EWRAM_DATA void *sTempTileDataBuffer[0x20] = {NULL}; const u16 gStandardMenuPalette[] = INCBIN_U16("graphics/interface/std_menu.gbapal"); -static const u8 sTextSpeedFrameDelays[] = -{ - [OPTIONS_TEXT_SPEED_SLOW] = 8, - [OPTIONS_TEXT_SPEED_MID] = 4, - [OPTIONS_TEXT_SPEED_FAST] = 1 -}; - static const struct WindowTemplate sStandardTextBox_WindowTemplates[] = { { @@ -145,6 +139,7 @@ static const struct MenuInfoIcon sMenuInfoIcons[] = void InitStandardTextBoxWindows(void) { + ResetNameboxData(); InitWindows(sStandardTextBox_WindowTemplates); sStartMenuWindowId = WINDOW_NONE; sMapNamePopupWindowId = WINDOW_NONE; @@ -194,13 +189,6 @@ u16 AddTextPrinterParameterized2(u8 windowId, u8 fontId, const u8 *str, u8 speed } void AddTextPrinterForMessage(bool8 allowSkippingDelayWithButtonPress) -{ - void (*callback)(struct TextPrinterTemplate *, u16) = NULL; - gTextFlags.canABSpeedUpPrint = allowSkippingDelayWithButtonPress; - AddTextPrinterParameterized2(0, FONT_NORMAL, gStringVar4, GetPlayerTextSpeedDelay(), callback, TEXT_COLOR_DARK_GRAY, TEXT_COLOR_WHITE, TEXT_COLOR_LIGHT_GRAY); -} - -void AddTextPrinterForMessage_2(bool8 allowSkippingDelayWithButtonPress) { gTextFlags.canABSpeedUpPrint = allowSkippingDelayWithButtonPress; AddTextPrinterParameterized2(0, FONT_NORMAL, gStringVar4, GetPlayerTextSpeedDelay(), NULL, TEXT_COLOR_DARK_GRAY, TEXT_COLOR_WHITE, TEXT_COLOR_LIGHT_GRAY); @@ -341,6 +329,53 @@ void DrawDialogueFrame(u8 windowId, bool8 copyToVram) CopyWindowToVram(windowId, COPYWIN_FULL); } +static void WindowFunc_RedrawDialogueFrame(u8 bg, u8 tilemapLeft, u8 tilemapTop, u8 width, u8 height, u8 paletteNum) +{ + FillBgTilemapBufferRect(bg, + DLG_WINDOW_BASE_TILE_NUM + 1, + tilemapLeft - 2, + tilemapTop - 1, + 1, + 1, + DLG_WINDOW_PALETTE_NUM); + FillBgTilemapBufferRect(bg, + DLG_WINDOW_BASE_TILE_NUM + 3, + tilemapLeft - 1, + tilemapTop - 1, + 1, + 1, + DLG_WINDOW_PALETTE_NUM); + FillBgTilemapBufferRect(bg, + DLG_WINDOW_BASE_TILE_NUM + 4, + tilemapLeft, + tilemapTop - 1, + width - 1, + 1, + DLG_WINDOW_PALETTE_NUM); + FillBgTilemapBufferRect(bg, + DLG_WINDOW_BASE_TILE_NUM + 5, + tilemapLeft + width - 1, + tilemapTop - 1, + 1, + 1, + DLG_WINDOW_PALETTE_NUM); + FillBgTilemapBufferRect(bg, + DLG_WINDOW_BASE_TILE_NUM + 6, + tilemapLeft + width, + tilemapTop - 1, + 1, + 1, + DLG_WINDOW_PALETTE_NUM); +} + +void RedrawDialogueFrame(void) +{ + if (IsMatchCallTaskActive()) + RedrawMatchCallTextBoxBorder(); + else + CallWindowFunction(0, WindowFunc_RedrawDialogueFrame); +} + void DrawStdWindowFrame(u8 windowId, bool8 copyToVram) { CallWindowFunction(windowId, WindowFunc_DrawStandardFrame); @@ -370,8 +405,6 @@ void ClearStdWindowAndFrame(u8 windowId, bool8 copyToVram) static void WindowFunc_DrawStandardFrame(u8 bg, u8 tilemapLeft, u8 tilemapTop, u8 width, u8 height, u8 paletteNum) { - int i; - FillBgTilemapBufferRect(bg, STD_WINDOW_BASE_TILE_NUM + 0, tilemapLeft - 1, @@ -393,25 +426,20 @@ static void WindowFunc_DrawStandardFrame(u8 bg, u8 tilemapLeft, u8 tilemapTop, u 1, 1, STD_WINDOW_PALETTE_NUM); - - for (i = tilemapTop; i < tilemapTop + height; i++) - { - FillBgTilemapBufferRect(bg, - STD_WINDOW_BASE_TILE_NUM + 3, - tilemapLeft - 1, - i, - 1, - 1, - STD_WINDOW_PALETTE_NUM); - FillBgTilemapBufferRect(bg, - STD_WINDOW_BASE_TILE_NUM + 5, - tilemapLeft + width, - i, - 1, - 1, - STD_WINDOW_PALETTE_NUM); - } - + FillBgTilemapBufferRect(bg, + STD_WINDOW_BASE_TILE_NUM + 3, + tilemapLeft - 1, + tilemapTop, + 1, + height, + STD_WINDOW_PALETTE_NUM); + FillBgTilemapBufferRect(bg, + STD_WINDOW_BASE_TILE_NUM + 5, + tilemapLeft + width, + tilemapTop, + 1, + height, + STD_WINDOW_PALETTE_NUM); FillBgTilemapBufferRect(bg, STD_WINDOW_BASE_TILE_NUM + 6, tilemapLeft - 1, @@ -590,22 +618,6 @@ void DisplayYesNoMenuWithDefault(u8 initialCursorPos) CreateYesNoMenu(&sYesNo_WindowTemplates, STD_WINDOW_BASE_TILE_NUM, STD_WINDOW_PALETTE_NUM, initialCursorPos); } -u32 GetPlayerTextSpeed(void) -{ - if (gTextFlags.forceMidTextSpeed) - return OPTIONS_TEXT_SPEED_MID; - return gSaveBlock2Ptr->optionsTextSpeed; -} - -u8 GetPlayerTextSpeedDelay(void) -{ - u32 speed; - if (gSaveBlock2Ptr->optionsTextSpeed > OPTIONS_TEXT_SPEED_FAST) - gSaveBlock2Ptr->optionsTextSpeed = OPTIONS_TEXT_SPEED_MID; - speed = GetPlayerTextSpeed(); - return sTextSpeedFrameDelays[speed]; -} - u8 AddStartMenuWindow(u8 numActions) { if (sStartMenuWindowId == WINDOW_NONE) diff --git a/src/menu_specialized.c b/src/menu_specialized.c index df4233fd14..33f26a5b90 100644 --- a/src/menu_specialized.c +++ b/src/menu_specialized.c @@ -1,9 +1,11 @@ #include "global.h" #include "malloc.h" #include "battle_main.h" +#include "contest.h" #include "contest_effect.h" #include "data.h" #include "decompress.h" +#include "event_data.h" #include "gpu_regs.h" #include "graphics.h" #include "menu.h" @@ -836,10 +838,10 @@ static void MoveRelearnerMenuLoadContestMoveDescription(u32 chosenMove) return; } - str = gContestMoveTypeTextPointers[GetMoveContestCategory(chosenMove)]; + str = gContestCategoryInfo[GetMoveContestCategory(chosenMove)].name; AddTextPrinterParameterized(RELEARNERWIN_DESC_CONTEST, FONT_NORMAL, str, 4, 25, TEXT_SKIP_DRAW, NULL); - str = gContestEffectDescriptionPointers[GetMoveContestEffect(chosenMove)]; + str = gContestEffects[GetMoveContestEffect(chosenMove)].description; AddTextPrinterParameterized(RELEARNERWIN_DESC_CONTEST, FONT_NARROW, str, 0, 65, TEXT_SKIP_DRAW, NULL); CopyWindowToVram(RELEARNERWIN_DESC_CONTEST, COPYWIN_GFX); diff --git a/src/metatile_behavior.c b/src/metatile_behavior.c index 687b98ca27..115a0d4c7b 100644 --- a/src/metatile_behavior.c +++ b/src/metatile_behavior.c @@ -331,7 +331,7 @@ bool8 MetatileBehavior_IsSouthArrowWarp(u8 metatileBehavior) bool8 UNUSED Unref_MetatileBehavior_IsArrowWarp(u8 metatileBehavior) { - u8 isArrowWarp = FALSE; + bool32 isArrowWarp = FALSE; if (MetatileBehavior_IsEastArrowWarp(metatileBehavior) || MetatileBehavior_IsWestArrowWarp(metatileBehavior) diff --git a/src/move_relearner.c b/src/move_relearner.c index ee700beb44..9aafbb4b59 100644 --- a/src/move_relearner.c +++ b/src/move_relearner.c @@ -9,6 +9,7 @@ #include "event_data.h" #include "field_screen_effect.h" #include "gpu_regs.h" +#include "item.h" #include "move_relearner.h" #include "list_menu.h" #include "malloc.h" @@ -134,7 +135,8 @@ #define MENU_STATE_CONFIRM_DELETE_OLD_MOVE 18 #define MENU_STATE_PRINT_WHICH_MOVE_PROMPT 19 #define MENU_STATE_SHOW_MOVE_SUMMARY_SCREEN 20 -// States 21, 22, and 23 are skipped. +#define MENU_STATE_RETURN_TO_PARTY_MENU 21 +// States 22 and 23 are skipped. #define MENU_STATE_PRINT_STOP_TEACHING 24 #define MENU_STATE_WAIT_FOR_STOP_TEACHING 25 #define MENU_STATE_CONFIRM_STOP_TEACHING 26 @@ -183,7 +185,8 @@ static EWRAM_DATA struct { bool8 showContestInfo; } sMoveRelearnerMenuState = {0}; -EWRAM_DATA u8 gOriginSummaryScreenPage = 0; // indicates summary screen page that the move relearner was opened from (if opened from PSS) +EWRAM_DATA enum MoveRelearnerStates gMoveRelearnerState = MOVE_RELEARNER_LEVEL_UP_MOVES; +EWRAM_DATA enum RelearnMode gRelearnMode = RELEARN_MODE_NONE; static const u16 sUI_Pal[] = INCBIN_U16("graphics/interface/ui_learn_move.gbapal"); @@ -402,11 +405,28 @@ void CB2_InitLearnMove(void) SetVBlankCallback(VBlankCB_MoveRelearner); InitMoveRelearnerBackgroundLayers(); - InitMoveRelearnerWindows(gOriginSummaryScreenPage == PSS_PAGE_CONTEST_MOVES); + InitMoveRelearnerWindows(gRelearnMode == RELEARN_MODE_PSS_PAGE_CONTEST_MOVES); sMoveRelearnerMenuState.listOffset = 0; sMoveRelearnerMenuState.listRow = 0; - sMoveRelearnerMenuState.showContestInfo = gOriginSummaryScreenPage == PSS_PAGE_CONTEST_MOVES; + sMoveRelearnerMenuState.showContestInfo = gRelearnMode == RELEARN_MODE_PSS_PAGE_CONTEST_MOVES; + + switch (gMoveRelearnerState) + { + case MOVE_RELEARNER_EGG_MOVES: + StringCopy(gStringVar3, MoveRelearner_Text_EggMoveLWR); + break; + case MOVE_RELEARNER_TM_MOVES: + StringCopy(gStringVar3, MoveRelearner_Text_TMMoveLWR); + break; + case MOVE_RELEARNER_TUTOR_MOVES: + StringCopy(gStringVar3, MoveRelearner_Text_TutorMoveLWR); + break; + case MOVE_RELEARNER_LEVEL_UP_MOVES: + default: + StringCopy(gStringVar3, MoveRelearner_Text_LevelUpMoveLWR); + break; + } CreateLearnableMovesList(); @@ -474,6 +494,18 @@ static void PrintMessageWithPlaceholders(const u8 *src) MoveRelearnerPrintMessage(gStringVar4); } +// If reusable TMs is off, remove the TM from the bag +static void RemoveRelearnerTMFromBag(u16 move) +{ + u16 item = GetTMHMItemIdFromMoveId(move); + + if (!I_REUSABLE_TMS && !P_ENABLE_ALL_TM_MOVES + && gMoveRelearnerState == MOVE_RELEARNER_TM_MOVES && GetItemTMHMIndex(item) <= NUM_TECHNICAL_MACHINES) + { + RemoveBagItem(item, 1); + } +} + // See the state machine doc at the top of the file. static void DoMoveRelearnerMain(void) { @@ -482,14 +514,14 @@ static void DoMoveRelearnerMain(void) case MENU_STATE_FADE_TO_BLACK: sMoveRelearnerStruct->state++; HideHeartSpritesAndShowTeachMoveText(FALSE); - if (gOriginSummaryScreenPage == PSS_PAGE_CONTEST_MOVES) + if (gRelearnMode == RELEARN_MODE_PSS_PAGE_CONTEST_MOVES) MoveRelearnerShowHideHearts(GetCurrentSelectedMove()); BeginNormalPaletteFade(PALETTES_ALL, 0, 16, 0, RGB_BLACK); break; case MENU_STATE_WAIT_FOR_FADE: if (!gPaletteFade.active) { - if (gOriginSummaryScreenPage == PSS_PAGE_CONTEST_MOVES) + if (gRelearnMode == RELEARN_MODE_PSS_PAGE_CONTEST_MOVES) sMoveRelearnerStruct->state = MENU_STATE_IDLE_CONTEST_MODE; else sMoveRelearnerStruct->state = MENU_STATE_IDLE_BATTLE_MODE; @@ -499,7 +531,6 @@ static void DoMoveRelearnerMain(void) sMoveRelearnerStruct->state++; break; case MENU_STATE_SETUP_BATTLE_MODE: - HideHeartSpritesAndShowTeachMoveText(FALSE); sMoveRelearnerStruct->state++; AddScrollArrows(); @@ -684,10 +715,11 @@ static void DoMoveRelearnerMain(void) FreeMoveRelearnerResources(); } break; - case 21: - if (!MoveRelearnerRunTextPrinters()) + case MENU_STATE_RETURN_TO_PARTY_MENU: + if (!gPaletteFade.active) { - sMoveRelearnerStruct->state = MENU_STATE_FADE_AND_RETURN; + FreeMoveRelearnerResources(); + SetMainCallback2(CB2_ReturnToPartyMenuFromSummaryScreen); } break; case 22: @@ -695,26 +727,28 @@ static void DoMoveRelearnerMain(void) break; case MENU_STATE_FADE_AND_RETURN: BeginNormalPaletteFade(PALETTES_ALL, 0, 0, 16, RGB_BLACK); - sMoveRelearnerStruct->state++; + if (gRelearnMode == RELEARN_MODE_PARTY_MENU) + sMoveRelearnerStruct->state = MENU_STATE_RETURN_TO_PARTY_MENU; + else + sMoveRelearnerStruct->state++; break; case MENU_STATE_RETURN_TO_FIELD: if (!gPaletteFade.active) { if (gInitialSummaryScreenCallback != NULL) { - switch (gOriginSummaryScreenPage) + switch (gRelearnMode) { - case PSS_PAGE_BATTLE_MOVES: + case RELEARN_MODE_PSS_PAGE_BATTLE_MOVES: ShowPokemonSummaryScreen(SUMMARY_MODE_RELEARNER_BATTLE, gPlayerParty, sMoveRelearnerStruct->partyMon, gPlayerPartyCount - 1, gInitialSummaryScreenCallback); break; - case PSS_PAGE_CONTEST_MOVES: + case RELEARN_MODE_PSS_PAGE_CONTEST_MOVES: ShowPokemonSummaryScreen(SUMMARY_MODE_RELEARNER_CONTEST, gPlayerParty, sMoveRelearnerStruct->partyMon, gPlayerPartyCount - 1, gInitialSummaryScreenCallback); break; default: ShowPokemonSummaryScreen(SUMMARY_MODE_NORMAL, gPlayerParty, sMoveRelearnerStruct->partyMon, gPlayerPartyCount - 1, gInitialSummaryScreenCallback); break; } - gOriginSummaryScreenPage = 0; } else { @@ -722,6 +756,7 @@ static void DoMoveRelearnerMain(void) } FreeMoveRelearnerResources(); + gRelearnMode = RELEARN_MODE_NONE; } break; case MENU_STATE_FADE_FROM_SUMMARY_SCREEN: @@ -754,7 +789,8 @@ static void DoMoveRelearnerMain(void) RemoveMonPPBonus(&gPlayerParty[sMoveRelearnerStruct->partyMon], sMoveRelearnerStruct->moveSlot); SetMonMoveSlot(&gPlayerParty[sMoveRelearnerStruct->partyMon], GetCurrentSelectedMove(), sMoveRelearnerStruct->moveSlot); u8 newPP = GetMonData(&gPlayerParty[sMoveRelearnerStruct->partyMon], MON_DATA_PP1 + sMoveRelearnerStruct->moveSlot); - if (!P_SUMMARY_MOVE_RELEARNER_FULL_PP && gOriginSummaryScreenPage != 0 && originalPP < newPP) + if (!P_SUMMARY_MOVE_RELEARNER_FULL_PP + && (gRelearnMode == RELEARN_MODE_PSS_PAGE_BATTLE_MOVES || gRelearnMode == RELEARN_MODE_PSS_PAGE_BATTLE_MOVES) && originalPP < newPP) SetMonData(&gPlayerParty[sMoveRelearnerStruct->partyMon], MON_DATA_PP1 + sMoveRelearnerStruct->moveSlot, &originalPP); StringCopy(gStringVar2, GetMoveName(GetCurrentSelectedMove())); PrintMessageWithPlaceholders(gText_MoveRelearnerAndPoof); @@ -775,6 +811,7 @@ static void DoMoveRelearnerMain(void) if (!MoveRelearnerRunTextPrinters()) { PlayFanfare(MUS_LEVEL_UP); + RemoveRelearnerTMFromBag(GetCurrentSelectedMove()); sMoveRelearnerStruct->state = MENU_STATE_WAIT_FOR_FANFARE; } break; @@ -953,7 +990,22 @@ static void CreateLearnableMovesList(void) s32 i; u8 nickname[POKEMON_NAME_LENGTH + 1]; - sMoveRelearnerStruct->numMenuChoices = GetMoveRelearnerMoves(&gPlayerParty[sMoveRelearnerStruct->partyMon], sMoveRelearnerStruct->movesToLearn); + switch (gMoveRelearnerState) + { + case MOVE_RELEARNER_EGG_MOVES: + sMoveRelearnerStruct->numMenuChoices = GetRelearnerEggMoves(&gPlayerParty[sMoveRelearnerStruct->partyMon], sMoveRelearnerStruct->movesToLearn); + break; + case MOVE_RELEARNER_TM_MOVES: + sMoveRelearnerStruct->numMenuChoices = GetRelearnerTMMoves(&gPlayerParty[sMoveRelearnerStruct->partyMon], sMoveRelearnerStruct->movesToLearn); + break; + case MOVE_RELEARNER_TUTOR_MOVES: + sMoveRelearnerStruct->numMenuChoices = GetRelearnerTutorMoves(&gPlayerParty[sMoveRelearnerStruct->partyMon], sMoveRelearnerStruct->movesToLearn); + break; + case MOVE_RELEARNER_LEVEL_UP_MOVES: + default: + sMoveRelearnerStruct->numMenuChoices = GetRelearnerLevelUpMoves(&gPlayerParty[sMoveRelearnerStruct->partyMon], sMoveRelearnerStruct->movesToLearn); + break; + } for (i = 0; i < sMoveRelearnerStruct->numMenuChoices; i++) { diff --git a/src/option_menu.c b/src/option_menu.c index fda3a24c47..715990fef7 100644 --- a/src/option_menu.c +++ b/src/option_menu.c @@ -72,19 +72,35 @@ static void DrawBgWindowFrames(void); EWRAM_DATA static bool8 sArrowPressed = FALSE; +static const u8 gText_Option[] = _("游戏设定"); +static const u8 gText_TextSpeedSlow[] = _("{COLOR GREEN}{SHADOW LIGHT_GREEN}慢"); +static const u8 gText_TextSpeedMid[] = _("{COLOR GREEN}{SHADOW LIGHT_GREEN}中"); +static const u8 gText_TextSpeedFast[] = _("{COLOR GREEN}{SHADOW LIGHT_GREEN}快"); +static const u8 gText_BattleSceneOn[] = _("{COLOR GREEN}{SHADOW LIGHT_GREEN}开"); +static const u8 gText_BattleSceneOff[] = _("{COLOR GREEN}{SHADOW LIGHT_GREEN}关"); +static const u8 gText_BattleStyleShift[] = _("{COLOR GREEN}{SHADOW LIGHT_GREEN}接力制"); +static const u8 gText_BattleStyleSet[] = _("{COLOR GREEN}{SHADOW LIGHT_GREEN}淘汰制"); +static const u8 gText_SoundMono[] = _("{COLOR GREEN}{SHADOW LIGHT_GREEN}单声道"); +static const u8 gText_SoundStereo[] = _("{COLOR GREEN}{SHADOW LIGHT_GREEN}立体声"); +static const u8 gText_FrameType[] = _("{COLOR GREEN}{SHADOW LIGHT_GREEN}类型"); +static const u8 gText_FrameTypeNumber[] = _("{COLOR GREEN}{SHADOW LIGHT_GREEN}"); +static const u8 gText_ButtonTypeNormal[] = _("{COLOR GREEN}{SHADOW LIGHT_GREEN}一般"); +static const u8 gText_ButtonTypeLR[] = _("{COLOR GREEN}{SHADOW LIGHT_GREEN}LR"); +static const u8 gText_ButtonTypeLEqualsA[] = _("{COLOR GREEN}{SHADOW LIGHT_GREEN}L同A"); + static const u16 sOptionMenuText_Pal[] = INCBIN_U16("graphics/interface/option_menu_text.gbapal"); // note: this is only used in the Japanese release static const u8 sEqualSignGfx[] = INCBIN_U8("graphics/interface/option_menu_equals_sign.4bpp"); static const u8 *const sOptionMenuItemsNames[MENUITEM_COUNT] = { - [MENUITEM_TEXTSPEED] = gText_TextSpeed, - [MENUITEM_BATTLESCENE] = gText_BattleScene, - [MENUITEM_BATTLESTYLE] = gText_BattleStyle, - [MENUITEM_SOUND] = gText_Sound, - [MENUITEM_BUTTONMODE] = gText_ButtonMode, - [MENUITEM_FRAMETYPE] = gText_Frame, - [MENUITEM_CANCEL] = gText_OptionMenuCancel, + [MENUITEM_TEXTSPEED] = COMPOUND_STRING("文字速度"), + [MENUITEM_BATTLESCENE] = COMPOUND_STRING("战斗动画"), + [MENUITEM_BATTLESTYLE] = COMPOUND_STRING("对战方式"), + [MENUITEM_SOUND] = COMPOUND_STRING("声音"), + [MENUITEM_BUTTONMODE] = COMPOUND_STRING("按键模式"), + [MENUITEM_FRAMETYPE] = COMPOUND_STRING("边框类型"), + [MENUITEM_CANCEL] = COMPOUND_STRING("取消"), }; static const struct WindowTemplate sOptionMenuWinTemplates[] = diff --git a/src/oras_dowse.c b/src/oras_dowse.c new file mode 100644 index 0000000000..237c456187 --- /dev/null +++ b/src/oras_dowse.c @@ -0,0 +1,562 @@ +#include "global.h" +#include "oras_dowse.h" +#include "bike.h" +#include "event_data.h" +#include "event_object_lock.h" +#include "event_object_movement.h" +#include "field_effect.h" +#include "field_effect_helpers.h" +#include "field_player_avatar.h" +#include "fldeff.h" +#include "item_use.h" +#include "palette.h" +#include "script.h" +#include "sound.h" +#include "task.h" +#include "constants/field_effects.h" +#include "constants/songs.h" +#include "constants/rgb.h" + +static void StartORASDowseFieldEffect(void); +static void UpdateORASDowsingFieldEffect(struct Sprite *sprite); +static void ChangeDowsingColor(u8 direction, struct Sprite *sprite); +static void ClearDowsingColor(struct Sprite *sprite); +static void PlayDowseSound(u32 dowseState); + +const u32 gFieldEffectObjectPic_ORASDowsingBrendan[] = INCBIN_U32("graphics/field_effects/pics/oras_dowsing_brendan.4bpp"); +const u32 gFieldEffectObjectPic_ORASDowsingMay[] = INCBIN_U32("graphics/field_effects/pics/oras_dowsing_may.4bpp"); +const u16 gFieldEffectPal_ORASDowsing[] = INCBIN_U16("graphics/field_effects/palettes/oras_dowsing.gbapal"); + +static const struct SpriteFrameImage sPicTable_ORASDowsingBrendan[] = { + overworld_ascending_frames(gFieldEffectObjectPic_ORASDowsingBrendan, 2, 4), +}; + +static const struct SpriteFrameImage sPicTable_ORASDowsingMay[] = { + overworld_ascending_frames(gFieldEffectObjectPic_ORASDowsingMay, 2, 4), +}; + +static const union AnimCmd sAnim_FaceSouth[] = +{ + ANIMCMD_FRAME(0, 16), + ANIMCMD_JUMP(0), +}; + +static const union AnimCmd sAnim_FaceNorth[] = +{ + ANIMCMD_FRAME(1, 16), + ANIMCMD_JUMP(0), +}; + +static const union AnimCmd sAnim_FaceWest[] = +{ + ANIMCMD_FRAME(2, 16), + ANIMCMD_JUMP(0), +}; + +static const union AnimCmd sAnim_FaceEast[] = +{ + ANIMCMD_FRAME(2, 16, .hFlip = TRUE), + ANIMCMD_JUMP(0), +}; + +static const union AnimCmd sAnim_ORASDowseWiggleSouthSlow[] = +{ + ANIMCMD_FRAME(0, 32), + ANIMCMD_FRAME(0, 32), + ANIMCMD_FRAME(4, 32), + ANIMCMD_FRAME(4, 32), + ANIMCMD_JUMP(0), +}; + +static const union AnimCmd sAnim_ORASDowseWiggleNorthSlow[] = +{ + ANIMCMD_FRAME(1, 32), + ANIMCMD_FRAME(1, 32), + ANIMCMD_FRAME(6, 32), + ANIMCMD_FRAME(6, 32), + ANIMCMD_JUMP(0), +}; + +static const union AnimCmd sAnim_ORASDowseWiggleWestSlow[] = +{ + ANIMCMD_FRAME(2, 32), + ANIMCMD_FRAME(2, 32), + ANIMCMD_FRAME(8, 32), + ANIMCMD_FRAME(8, 32), + ANIMCMD_JUMP(0), +}; + +static const union AnimCmd sAnim_ORASDowseWiggleEastSlow[] = +{ + ANIMCMD_FRAME(2, 32, .hFlip = TRUE), + ANIMCMD_FRAME(2, 32, .hFlip = TRUE), + ANIMCMD_FRAME(8, 32, .hFlip = TRUE), + ANIMCMD_FRAME(8, 32, .hFlip = TRUE), + ANIMCMD_JUMP(0), +}; + +static const union AnimCmd sAnim_ORASDowseWiggleSouth[] = +{ + ANIMCMD_FRAME(0, 32), + ANIMCMD_FRAME(3, 32), + ANIMCMD_FRAME(0, 32), + ANIMCMD_FRAME(4, 32), + ANIMCMD_JUMP(0), +}; + +static const union AnimCmd sAnim_ORASDowseWiggleNorth[] = +{ + ANIMCMD_FRAME(1, 32), + ANIMCMD_FRAME(5, 32), + ANIMCMD_FRAME(1, 32), + ANIMCMD_FRAME(6, 32), + ANIMCMD_JUMP(0), +}; + +static const union AnimCmd sAnim_ORASDowseWiggleWest[] = +{ + ANIMCMD_FRAME(2, 32), + ANIMCMD_FRAME(7, 32), + ANIMCMD_FRAME(2, 32), + ANIMCMD_FRAME(8, 32), + ANIMCMD_JUMP(0), +}; + +static const union AnimCmd sAnim_ORASDowseWiggleEast[] = +{ + ANIMCMD_FRAME(2, 32, .hFlip = TRUE), + ANIMCMD_FRAME(7, 32, .hFlip = TRUE), + ANIMCMD_FRAME(2, 32, .hFlip = TRUE), + ANIMCMD_FRAME(8, 32, .hFlip = TRUE), + ANIMCMD_JUMP(0), +}; + +static const union AnimCmd sAnim_ORASDowseWiggleSouthFast[] = +{ + ANIMCMD_FRAME(0, 16), + ANIMCMD_FRAME(3, 16), + ANIMCMD_FRAME(0, 16), + ANIMCMD_FRAME(4, 16), + ANIMCMD_JUMP(0), +}; + +static const union AnimCmd sAnim_ORASDowseWiggleNorthFast[] = +{ + ANIMCMD_FRAME(1, 16), + ANIMCMD_FRAME(5, 16), + ANIMCMD_FRAME(1, 16), + ANIMCMD_FRAME(6, 16), + ANIMCMD_JUMP(0), +}; + +static const union AnimCmd sAnim_ORASDowseWiggleWestFast[] = +{ + ANIMCMD_FRAME(2, 16), + ANIMCMD_FRAME(7, 16), + ANIMCMD_FRAME(2, 16), + ANIMCMD_FRAME(8, 16), + ANIMCMD_JUMP(0), +}; + +static const union AnimCmd sAnim_ORASDowseWiggleEastFast[] = +{ + ANIMCMD_FRAME(2, 16, .hFlip = TRUE), + ANIMCMD_FRAME(7, 16, .hFlip = TRUE), + ANIMCMD_FRAME(2, 16, .hFlip = TRUE), + ANIMCMD_FRAME(8, 16, .hFlip = TRUE), + ANIMCMD_JUMP(0), +}; + +static const union AnimCmd sAnim_ORASDowseWiggleSouthFaster[] = +{ + ANIMCMD_FRAME(0, 8), + ANIMCMD_FRAME(3, 8), + ANIMCMD_FRAME(0, 8), + ANIMCMD_FRAME(4, 8), + ANIMCMD_JUMP(0), +}; + +static const union AnimCmd sAnim_ORASDowseWiggleNorthFaster[] = +{ + ANIMCMD_FRAME(1, 8), + ANIMCMD_FRAME(5, 8), + ANIMCMD_FRAME(1, 8), + ANIMCMD_FRAME(6, 8), + ANIMCMD_JUMP(0), +}; + +static const union AnimCmd sAnim_ORASDowseWiggleWestFaster[] = +{ + ANIMCMD_FRAME(2, 8), + ANIMCMD_FRAME(7, 8), + ANIMCMD_FRAME(2, 8), + ANIMCMD_FRAME(8, 8), + ANIMCMD_JUMP(0), +}; + +static const union AnimCmd sAnim_ORASDowseWiggleEastFaster[] = +{ + ANIMCMD_FRAME(2, 8, .hFlip = TRUE), + ANIMCMD_FRAME(7, 8, .hFlip = TRUE), + ANIMCMD_FRAME(2, 8, .hFlip = TRUE), + ANIMCMD_FRAME(8, 8, .hFlip = TRUE), + ANIMCMD_JUMP(0), +}; + +static const union AnimCmd *const sAnimTable_ORASDowsing[] = +{ + [ANIM_STD_FACE_SOUTH] = sAnim_FaceSouth, + [ANIM_STD_FACE_NORTH] = sAnim_FaceNorth, + [ANIM_STD_FACE_WEST] = sAnim_FaceWest, + [ANIM_STD_FACE_EAST] = sAnim_FaceEast, + [ANIM_ORAS_DOWSE_WIGGLE_SOUTH_SLOW] = sAnim_ORASDowseWiggleSouthSlow, + [ANIM_ORAS_DOWSE_WIGGLE_NORTH_SLOW] = sAnim_ORASDowseWiggleNorthSlow, + [ANIM_ORAS_DOWSE_WIGGLE_WEST_SLOW] = sAnim_ORASDowseWiggleWestSlow, + [ANIM_ORAS_DOWSE_WIGGLE_EAST_SLOW] = sAnim_ORASDowseWiggleEastSlow, + [ANIM_ORAS_DOWSE_WIGGLE_SOUTH] = sAnim_ORASDowseWiggleSouth, + [ANIM_ORAS_DOWSE_WIGGLE_NORTH] = sAnim_ORASDowseWiggleNorth, + [ANIM_ORAS_DOWSE_WIGGLE_WEST] = sAnim_ORASDowseWiggleWest, + [ANIM_ORAS_DOWSE_WIGGLE_EAST] = sAnim_ORASDowseWiggleEast, + [ANIM_ORAS_DOWSE_WIGGLE_SOUTH_FAST] = sAnim_ORASDowseWiggleSouthFast, + [ANIM_ORAS_DOWSE_WIGGLE_NORTH_FAST] = sAnim_ORASDowseWiggleNorthFast, + [ANIM_ORAS_DOWSE_WIGGLE_WEST_FAST] = sAnim_ORASDowseWiggleWestFast, + [ANIM_ORAS_DOWSE_WIGGLE_EAST_FAST] = sAnim_ORASDowseWiggleEastFast, + [ANIM_ORAS_DOWSE_WIGGLE_SOUTH_FASTER] = sAnim_ORASDowseWiggleSouthFaster, + [ANIM_ORAS_DOWSE_WIGGLE_NORTH_FASTER] = sAnim_ORASDowseWiggleNorthFaster, + [ANIM_ORAS_DOWSE_WIGGLE_WEST_FASTER] = sAnim_ORASDowseWiggleWestFaster, + [ANIM_ORAS_DOWSE_WIGGLE_EAST_FASTER] = sAnim_ORASDowseWiggleEastFaster, +}; + +static const struct OamData gObjectEventOam_ORASDowse = { + .shape = SPRITE_SHAPE(16x32), + .size = SPRITE_SIZE(16x32), + .priority = 2 +}; + +const struct SpriteTemplate gFieldEffectObjectTemplate_ORASDowsingBrendan = { + .tileTag = TAG_NONE, + .paletteTag = FLDEFF_PAL_TAG_ORAS_DOWSE, + .oam = &gObjectEventOam_ORASDowse, + .anims = sAnimTable_ORASDowsing, + .images = sPicTable_ORASDowsingBrendan, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = UpdateORASDowsingFieldEffect, +}; + +const struct SpriteTemplate gFieldEffectObjectTemplate_ORASDowsingMay = { + .tileTag = TAG_NONE, + .paletteTag = FLDEFF_PAL_TAG_ORAS_DOWSE, + .oam = &gObjectEventOam_ORASDowse, + .anims = sAnimTable_ORASDowsing, + .images = sPicTable_ORASDowsingMay, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = UpdateORASDowsingFieldEffect, +}; + +void Task_UseORASDowsingMachine(u8 taskId) +{ + if (FlagGet(I_ORAS_DOWSING_FLAG)) + { + EndORASDowsing(); + } + else + { + if (TestPlayerAvatarFlags(PLAYER_AVATAR_FLAG_BIKE)) + GetOnOffBike(0); + + StartORASDowseFieldEffect(); + } + ScriptUnfreezeObjectEvents(); + UnlockPlayerFieldControls(); + DestroyTask(taskId); +} + +static void StartORASDowseFieldEffect(void) +{ + struct ObjectEvent *playerObj = &gObjectEvents[gPlayerAvatar.objectEventId]; + + gFieldEffectArguments[0] = playerObj->currentCoords.x; + gFieldEffectArguments[1] = playerObj->currentCoords.y; + FieldEffectStart(FLDEFF_ORAS_DOWSE); +} + +void ResumeORASDowseFieldEffect(void) +{ + if (I_ORAS_DOWSING_FLAG != 0 && FlagGet(I_ORAS_DOWSING_FLAG)) + StartORASDowseFieldEffect(); +} + +static const struct SpritePalette gSpritePalette_ORASDowsing = {gFieldEffectPal_ORASDowsing, FLDEFF_PAL_TAG_ORAS_DOWSE}; + +// Sprite data for ORAS Dowsing Machine +#define tItemDistanceX data[0] +#define tItemDistanceY data[1] +#define sItemFound data[2] +#define sCounter data[3] +#define sSoundTimer data[4] +#define sDowseState data[5] +#define sPrevDowseState data[6] +#define sMoveActive data[7] + +#define fPlayerX gFieldEffectArguments[0] +#define fPlayerY gFieldEffectArguments[1] + +// Create the ORAS Dowsing Machine sprite. +u32 FldEff_ORASDowsing(void) +{ + struct ObjectEvent *playerObj = &gObjectEvents[gPlayerAvatar.objectEventId]; + u32 spriteId; + u32 palNum; + + FlagSet(I_ORAS_DOWSING_FLAG); + SetSpritePosToOffsetMapCoords((s16 *)&fPlayerX, (s16 *)&fPlayerY, 8, 0); + if (gPlayerAvatar.gender == MALE) + spriteId = CreateSpriteAtEnd(gFieldEffectObjectTemplatePointers[FLDEFFOBJ_ORAS_DOWSE_BRENDAN], fPlayerX, fPlayerY, 1); + else + spriteId = CreateSpriteAtEnd(gFieldEffectObjectTemplatePointers[FLDEFFOBJ_ORAS_DOWSE_MAY], fPlayerX, fPlayerY, 1); + + if (spriteId != MAX_SPRITES) + { + struct Sprite *sprite = &gSprites[spriteId]; + sprite->coordOffsetEnabled = TRUE; + palNum = LoadSpritePalette(&gSpritePalette_ORASDowsing); + if (palNum != 0xFF) + sprite->oam.paletteNum = palNum; + else + sprite->oam.paletteNum = LoadPlayerObjectEventPalette(gSaveBlock2Ptr->playerGender); + + playerObj->fieldEffectSpriteId = spriteId; + sprite->sDowseState = ORASD_WIGGLE_NONE; + UpdateDowseState(sprite); + } + FieldEffectActiveListRemove(FLDEFF_ORAS_DOWSE); + return spriteId; +} + +// Callback for ORAS Dowsing Machine sprite. +static void UpdateORASDowsingFieldEffect(struct Sprite *sprite) +{ + struct ObjectEvent *playerObj = &gObjectEvents[gPlayerAvatar.objectEventId]; + struct Sprite *playerSprite = &gSprites[playerObj->spriteId]; + + if (!FlagGet(I_ORAS_DOWSING_FLAG)) + { + DestroySpriteAndFreeResources(sprite); + return; + } + + sprite->x = playerSprite->x; + sprite->y = playerSprite->y; + sprite->x2 = playerSprite->x2; + sprite->y2 = playerSprite->y2; + + if (playerSprite->anims[playerSprite->animNum][playerSprite->animCmdIndex].frame.imageValue > 2) + sprite->y2++; + + if (playerObj->previousMovementDirection != playerObj->movementDirection) + UpdateDowsingAnimDirection(sprite, playerObj); + + if (playerObj->movementActionId != MOVEMENT_ACTION_NONE) + { + if (playerObj->heldMovementFinished == FALSE) + { + if (sprite->sCounter == 0) + { + sprite->sMoveActive = TRUE; + sprite->sCounter++; + } + } + else if (playerObj->heldMovementFinished == TRUE && sprite->sMoveActive) + { + sprite->sMoveActive = FALSE; + sprite->sCounter = 0; + UpdateDowseState(sprite); + } + } + + if (I_ORAS_DOWSING_SOUNDS && sprite->sDowseState == ORASD_WIGGLE_FASTER && playerObj->heldMovementFinished != FALSE) + { + if (++sprite->sSoundTimer == 70) + { + PlaySE(SE_ITEMFINDER); + sprite->sSoundTimer = 0; + } + } + sprite->oam.priority = playerSprite->oam.priority; +} + +static const u8 sClockwiseDirections[] = {DIR_NORTH, DIR_EAST, DIR_SOUTH, DIR_WEST}; + +void UpdateDowseState(struct Sprite *sprite) +{ + struct ObjectEvent *playerObj = &gObjectEvents[gPlayerAvatar.objectEventId]; + + sprite->tItemDistanceX = 0; + sprite->tItemDistanceY = 0; + sprite->sPrevDowseState = sprite->sDowseState; + if (ItemfinderCheckForHiddenItems(gMapHeader.events, TASK_NONE) == TRUE) + { + s8 distX = sprite->tItemDistanceX; + s8 distY = sprite->tItemDistanceY; + u8 directionToItem = CARDINAL_DIRECTION_COUNT; + u8 playerDirToItem = GetDirectionToHiddenItem(distX, distY); + if (playerDirToItem != DIR_NONE) + directionToItem = sClockwiseDirections[GetDirectionToHiddenItem(distX, distY) - 1]; + + if (distX < 0) + distX *= -1; + + if (distY < 0) + distY *= -1; + + // If the player is facing the item's direction. + if (directionToItem == playerObj->movementDirection) + { + ChangeDowsingColor(directionToItem, sprite); + } + // If x and y distances are equal, make sure item can bee seen from both facing directions. + else if (distX == distY && distX != 0) + { + if ((directionToItem == DIR_NORTH || directionToItem == DIR_SOUTH) && sprite->tItemDistanceX > 0 && playerObj->movementDirection == DIR_EAST) + ChangeDowsingColor(DIR_EAST, sprite); + else if ((directionToItem == DIR_NORTH || directionToItem == DIR_SOUTH) && sprite->tItemDistanceX < 0 && playerObj->movementDirection == DIR_WEST) + ChangeDowsingColor(DIR_WEST, sprite); + else + ClearDowsingColor(sprite); + } + else + { + ClearDowsingColor(sprite); + } + } + else + { + ClearDowsingColor(sprite); + } + UpdateDowsingAnimDirection(sprite, playerObj); +} + +static void ChangeDowsingColor(u8 direction, struct Sprite *sprite) +{ + s16 distance; + u16 color = I_ORAS_DOWSING_COLOR_NONE; + + if (direction == DIR_NORTH || direction == DIR_SOUTH) + distance = sprite->tItemDistanceY; + else + distance = sprite->tItemDistanceX; + + // Absolute value. + if (distance < 0) + distance *= -1; + + switch (distance) + { + case 1: + if (sprite->tItemDistanceX == 0 || sprite->tItemDistanceY == 0) + { + color = I_ORAS_DOWSING_COLOR_FASTER; + sprite->sDowseState = ORASD_WIGGLE_FASTER; + break; + } + case 2: + color = I_ORAS_DOWSING_COLOR_FAST; + sprite->sDowseState = ORASD_WIGGLE_FAST; + break; + case 3: + case 4: + color = I_ORAS_DOWSING_COLOR_NORMAL; + sprite->sDowseState = ORASD_WIGGLE_NORMAL; + break; + case 5: + case 6: + case 7: + color = I_ORAS_DOWSING_COLOR_SLOW; + sprite->sDowseState = ORASD_WIGGLE_SLOW; + break; + } + + if (I_ORAS_DOWSING_SOUNDS && sprite->sDowseState != sprite->sPrevDowseState) + { + sprite->sSoundTimer = 0; + PlayDowseSound(sprite->sDowseState); + } + + FillPalette(color, (OBJ_PLTT_ID(IndexOfSpritePaletteTag(FLDEFF_PAL_TAG_ORAS_DOWSE)) + I_ORAS_DOWSING_COLOR_PAL), PLTT_SIZEOF(1)); + UpdateSpritePaletteWithTime(IndexOfSpritePaletteTag(FLDEFF_PAL_TAG_ORAS_DOWSE)); +} + +static void ClearDowsingColor(struct Sprite *sprite) +{ + sprite->sDowseState = ORASD_WIGGLE_NONE; + FillPalette(I_ORAS_DOWSING_COLOR_NONE, (OBJ_PLTT_ID(IndexOfSpritePaletteTag(FLDEFF_PAL_TAG_ORAS_DOWSE)) + I_ORAS_DOWSING_COLOR_PAL), PLTT_SIZEOF(1)); + UpdateSpritePaletteWithTime(IndexOfSpritePaletteTag(FLDEFF_PAL_TAG_ORAS_DOWSE)); +} + +static void PlayDowseSound(u32 dowseState) +{ + switch (dowseState) + { + case ORASD_WIGGLE_SLOW: + PlaySE(SE_CONTEST_ICON_CLEAR); + return; + case ORASD_WIGGLE_NORMAL: + PlaySE(SE_PIN); + return; + case ORASD_WIGGLE_FAST: + PlaySE(SE_SUCCESS); + return; + case ORASD_WIGGLE_FASTER: + PlaySE(SE_ITEMFINDER); + return; + } +} + +void UpdateDowsingAnimDirection(struct Sprite *sprite, struct ObjectEvent *playerObj) +{ + u32 anim = (playerObj->facingDirection - 1); + + switch (sprite->sDowseState) + { + case ORASD_WIGGLE_SLOW: + anim += 4; + break; + case ORASD_WIGGLE_NORMAL: + anim += 8; + break; + case ORASD_WIGGLE_FAST: + anim += 12; + break; + case ORASD_WIGGLE_FASTER: + anim += 16; + break; + } + + // Don't completely restart anim if wiggling didn't stop. + if (sprite->sPrevDowseState != ORASD_WIGGLE_NONE && sprite->sDowseState != ORASD_WIGGLE_NONE) + SetAndStartSpriteAnim(sprite, anim, sprite->animCmdIndex); + else + StartSpriteAnimIfDifferent(sprite, anim); +} + +void EndORASDowsing(void) +{ + if (I_ORAS_DOWSING_FLAG != 0 && FlagGet(I_ORAS_DOWSING_FLAG)) + FlagClear(I_ORAS_DOWSING_FLAG); +} + +void Script_ClearDowsingColor(void) +{ + if (I_ORAS_DOWSING_FLAG != 0 && FlagGet(I_ORAS_DOWSING_FLAG)) + { + struct Sprite *sprite = &gSprites[gObjectEvents[gPlayerAvatar.objectEventId].fieldEffectSpriteId]; + ClearDowsingColor(sprite); + UpdateDowsingAnimDirection(sprite, &gObjectEvents[gPlayerAvatar.objectEventId]); + } +} + +void Script_UpdateDowseState(void) +{ + if (I_ORAS_DOWSING_FLAG != 0 && FlagGet(I_ORAS_DOWSING_FLAG)) + UpdateDowseState(&gSprites[gObjectEvents[gPlayerAvatar.objectEventId].fieldEffectSpriteId]); +} diff --git a/src/overworld.c b/src/overworld.c index e70cae880d..5f16de1f2e 100644 --- a/src/overworld.c +++ b/src/overworld.c @@ -43,6 +43,7 @@ #include "mirage_tower.h" #include "money.h" #include "new_game.h" +#include "oras_dowse.h" #include "palette.h" #include "play_time.h" #include "random.h" @@ -429,10 +430,13 @@ void Overworld_ResetBattleFlagsAndVars(void) VarSet(B_VAR_WILD_AI_FLAGS,0); #endif + #if B_VAR_NO_BAG_USE != 0 + VarSet(B_VAR_NO_BAG_USE, 0); + #endif + FlagClear(B_FLAG_INVERSE_BATTLE); FlagClear(B_FLAG_FORCE_DOUBLE_WILD); FlagClear(B_SMART_WILD_AI_FLAG); - FlagClear(B_FLAG_NO_BAG_USE); FlagClear(B_FLAG_NO_CATCHING); FlagClear(B_FLAG_NO_RUNNING); FlagClear(B_FLAG_DYNAMAX_BATTLE); @@ -856,8 +860,8 @@ void LoadMapFromCameraTransition(u8 mapGroup, u8 mapNum) TryUpdateRandomTrainerRematches(mapGroup, mapNum); #endif //FREE_MATCH_CALL -if (I_VS_SEEKER_CHARGING != 0) - MapResetTrainerRematches(mapGroup, mapNum); + if (I_VS_SEEKER_CHARGING != 0) + MapResetTrainerRematches(mapGroup, mapNum); DoTimeBasedEvents(); SetSavedWeatherFromCurrMapHeader(); @@ -922,8 +926,8 @@ static void LoadMapFromWarp(bool32 a1) TryUpdateRandomTrainerRematches(gSaveBlock1Ptr->location.mapGroup, gSaveBlock1Ptr->location.mapNum); #endif //FREE_MATCH_CALL -if (I_VS_SEEKER_CHARGING != 0) - MapResetTrainerRematches(gSaveBlock1Ptr->location.mapGroup, gSaveBlock1Ptr->location.mapNum); + if (I_VS_SEEKER_CHARGING != 0) + MapResetTrainerRematches(gSaveBlock1Ptr->location.mapGroup, gSaveBlock1Ptr->location.mapNum); if (a1 != TRUE) DoTimeBasedEvents(); @@ -1621,7 +1625,7 @@ void UpdateTimeOfDay(void) #undef DEFAULT_WEIGHT // Whether a map type is naturally lit/outside -bool32 MapHasNaturalLight(u8 mapType) +bool32 MapHasNaturalLight(enum MapType mapType) { return (OW_ENABLE_DNS && (mapType == MAP_TYPE_TOWN @@ -2237,6 +2241,7 @@ static bool32 ReturnToFieldLocal(u8 *state) InitViewGraphics(); TryLoadTrainerHillEReaderPalette(); FollowerNPC_BindToSurfBlobOnReloadScreen(); + ResumeORASDowseFieldEffect(); (*state)++; break; case 2: diff --git a/src/party_menu.c b/src/party_menu.c index 5e3bd4629e..f93fc6b39a 100644 --- a/src/party_menu.c +++ b/src/party_menu.c @@ -43,6 +43,7 @@ #include "menu_helpers.h" #include "menu_specialized.h" #include "metatile_behavior.h" +#include "move_relearner.h" #include "overworld.h" #include "palette.h" #include "party_menu.h" @@ -99,6 +100,11 @@ enum { MENU_REGISTER, MENU_TRADE1, MENU_TRADE2, + MENU_LEVEL_UP_MOVES, + MENU_EGG_MOVES, + MENU_TM_MOVES, + MENU_TUTOR_MOVES, + MENU_SUB_MOVES, MENU_TOSS, MENU_CATALOG_BULB, MENU_CATALOG_OVEN, @@ -126,6 +132,7 @@ enum { ACTIONS_REGISTER, ACTIONS_TRADE, ACTIONS_SPIN_TRADE, + ACTIONS_MOVES_SUB, ACTIONS_TAKEITEM_TOSS, ACTIONS_ROTOM_CATALOG, ACTIONS_ZYGARDE_CUBE, @@ -335,13 +342,13 @@ static void Task_CancelParticipationYesNo(u8); static void Task_HandleCancelParticipationYesNoInput(u8); static bool8 ShouldUseChooseMonText(void); static void SetPartyMonFieldSelectionActions(struct Pokemon *, u8); +static void SetPartyMonLearnMoveSelectionActions(struct Pokemon*, u8); static u8 GetPartyMenuActionsTypeInBattle(struct Pokemon *); static u8 GetPartySlotEntryStatus(s8); static void Task_UpdateHeldItemSprite(u8); static void Task_HandleSelectionMenuInput(u8); static void CB2_ShowPokemonSummaryScreen(void); static void UpdatePartyToBattleOrder(void); -static void CB2_ReturnToPartyMenuFromSummaryScreen(void); static void SlidePartyMenuBoxOneStep(u8); static void Task_SlideSelectedSlotsOffscreen(u8); static void SwitchPartyMon(void); @@ -478,6 +485,11 @@ static void CursorCb_Trade1(u8); static void CursorCb_Trade2(u8); static void CursorCb_Toss(u8); static void CursorCb_FieldMove(u8); +static void CursorCb_ChangeLevelUpMoves(u8); +static void CursorCb_ChangeEggMoves(u8); +static void CursorCb_ChangeTMMoves(u8); +static void CursorCb_ChangeTutorMoves(u8); +static void CursorCb_LearnMovesSubMenu(u8); static void CursorCb_CatalogBulb(u8); static void CursorCb_CatalogOven(u8); static void CursorCb_CatalogWashing(u8); @@ -1081,10 +1093,27 @@ static void DisplayPartyPokemonDataForContest(u8 slot) static void DisplayPartyPokemonDataForRelearner(u8 slot) { - if (GetNumberOfRelearnableMoves(&gPlayerParty[slot]) == 0) - DisplayPartyPokemonDescriptionData(slot, PARTYBOX_DESC_NOT_ABLE_2); - else - DisplayPartyPokemonDescriptionData(slot, PARTYBOX_DESC_ABLE_2); + struct Pokemon *mon = &gPlayerParty[slot]; + bool32 hasMoves = FALSE; + + switch (gMoveRelearnerState) + { + case MOVE_RELEARNER_EGG_MOVES: + hasMoves = HasRelearnerEggMoves(mon); + break; + case MOVE_RELEARNER_TM_MOVES: + hasMoves = HasRelearnerTMMoves(mon); + break; + case MOVE_RELEARNER_TUTOR_MOVES: + hasMoves = HasRelearnerTutorMoves(mon); + break; + default: + hasMoves = HasRelearnerLevelUpMoves(mon); + break; + } + + u32 desc = (hasMoves ? PARTYBOX_DESC_ABLE_2 : PARTYBOX_DESC_NOT_ABLE_2); + DisplayPartyPokemonDescriptionData(slot, desc); } static void DisplayPartyPokemonDataForWirelessMinigame(u8 slot) @@ -2771,7 +2800,13 @@ static u8 DisplaySelectionWindow(u8 windowType) for (i = 0; i < sPartyMenuInternal->numActions; i++) { const u8 *text; - u8 fontColorsId = (sPartyMenuInternal->actions[i] >= MENU_FIELD_MOVES) ? 4 : 3; + u8 fontColorsId = 3; + + if (sPartyMenuInternal->actions[i] >= MENU_FIELD_MOVES) + fontColorsId = 4; + if (sPartyMenuInternal->actions[i] >= MENU_LEVEL_UP_MOVES && sPartyMenuInternal->actions[i] <= MENU_SUB_MOVES) + fontColorsId = 6; + if (sPartyMenuInternal->actions[i] >= MENU_FIELD_MOVES) text = GetMoveName(FieldMove_GetMoveId(sPartyMenuInternal->actions[i] - MENU_FIELD_MOVES)); else @@ -2819,6 +2854,11 @@ static void SetPartyMonSelectionActions(struct Pokemon *mons, u8 slotId, u8 acti { SetPartyMonFieldSelectionActions(mons, slotId); } + else if (action == ACTIONS_MOVES_SUB && P_PARTY_MOVE_RELEARNER) + { + sPartyMenuInternal->numActions = 0; + SetPartyMonLearnMoveSelectionActions(mons, slotId); + } else { sPartyMenuInternal->numActions = sPartyMenuActionCounts[action]; @@ -2834,6 +2874,12 @@ static void SetPartyMonFieldSelectionActions(struct Pokemon *mons, u8 slotId) sPartyMenuInternal->numActions = 0; AppendToList(sPartyMenuInternal->actions, &sPartyMenuInternal->numActions, MENU_SUMMARY); + if (P_PARTY_MOVE_RELEARNER + && (GetMonData(&mons[slotId], MON_DATA_SPECIES) + && (HasRelearnerLevelUpMoves(&mons[slotId]) || HasRelearnerEggMoves(&mons[slotId]) + || HasRelearnerTMMoves(&mons[slotId]) || HasRelearnerTutorMoves(&mons[slotId])))) + AppendToList(sPartyMenuInternal->actions, &sPartyMenuInternal->numActions, MENU_SUB_MOVES); + // Add field moves to action list for (i = 0; i < MAX_MON_MOVES; i++) { @@ -2859,6 +2905,32 @@ static void SetPartyMonFieldSelectionActions(struct Pokemon *mons, u8 slotId) AppendToList(sPartyMenuInternal->actions, &sPartyMenuInternal->numActions, MENU_CANCEL1); } +static void SetPartyMonLearnMoveSelectionActions(struct Pokemon *mons, u8 slotId) +{ + if (GetMonData(&mons[slotId], MON_DATA_SPECIES) != SPECIES_NONE && HasRelearnerLevelUpMoves(&mons[slotId])) + AppendToList(sPartyMenuInternal->actions, &sPartyMenuInternal->numActions, MENU_LEVEL_UP_MOVES); + + if (P_ENABLE_MOVE_RELEARNERS || (P_FLAG_EGG_MOVES != 0 && FlagGet(P_FLAG_EGG_MOVES))) + { + if (GetMonData(&mons[slotId], MON_DATA_SPECIES) != SPECIES_NONE && HasRelearnerEggMoves(&mons[slotId])) + AppendToList(sPartyMenuInternal->actions, &sPartyMenuInternal->numActions, MENU_EGG_MOVES); + } + + if (P_ENABLE_MOVE_RELEARNERS || P_TM_MOVES_RELEARNER) + { + if (GetMonData(&mons[slotId], MON_DATA_SPECIES) != SPECIES_NONE && HasRelearnerTMMoves(&mons[slotId])) + AppendToList(sPartyMenuInternal->actions, &sPartyMenuInternal->numActions, MENU_TM_MOVES); + } + + if (P_ENABLE_MOVE_RELEARNERS || (P_FLAG_TUTOR_MOVES != 0 && FlagGet(P_FLAG_TUTOR_MOVES))) + { + if (GetMonData(&mons[slotId], MON_DATA_SPECIES) != SPECIES_NONE && HasRelearnerTutorMoves(&mons[slotId])) + AppendToList(sPartyMenuInternal->actions, &sPartyMenuInternal->numActions, MENU_TUTOR_MOVES); + } + + AppendToList(sPartyMenuInternal->actions, &sPartyMenuInternal->numActions, MENU_CANCEL1); +} + static u8 GetPartyMenuActionsType(struct Pokemon *mon) { u32 actionType; @@ -3010,13 +3082,17 @@ static void CB2_ShowPokemonSummaryScreen(void) UpdatePartyToBattleOrder(); ShowPokemonSummaryScreen(SUMMARY_MODE_LOCK_MOVES, gPlayerParty, gPartyMenu.slotId, gPlayerPartyCount - 1, CB2_ReturnToPartyMenuFromSummaryScreen); } + else if (gPartyMenu.menuType == PARTY_MENU_TYPE_CHOOSE_HALF) + { + ShowPokemonSummaryScreen(SUMMARY_MODE_LOCK_MOVES, gPlayerParty, gPartyMenu.slotId, gPlayerPartyCount - 1, CB2_ReturnToPartyMenuFromSummaryScreen); + } else { ShowPokemonSummaryScreen(SUMMARY_MODE_NORMAL, gPlayerParty, gPartyMenu.slotId, gPlayerPartyCount - 1, CB2_ReturnToPartyMenuFromSummaryScreen); } } -static void CB2_ReturnToPartyMenuFromSummaryScreen(void) +void CB2_ReturnToPartyMenuFromSummaryScreen(void) { gPaletteFade.bufferTransferDisabled = TRUE; gPartyMenu.slotId = gLastViewedMonIndex; @@ -7508,19 +7584,12 @@ static void BufferBattlePartyOrderBySide(u8 *partyBattleOrder, u8 flankId, u8 ba { u8 partyIndexes[PARTY_SIZE]; int i, j; - u8 leftBattler; - u8 rightBattler; + u8 leftBattler; if (IsOnPlayerSide(battler)) - { leftBattler = GetBattlerAtPosition(B_POSITION_PLAYER_LEFT); - rightBattler = GetBattlerAtPosition(B_POSITION_PLAYER_RIGHT); - } else - { leftBattler = GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT); - rightBattler = GetBattlerAtPosition(B_POSITION_OPPONENT_RIGHT); - } if (IsMultiBattle() == TRUE) { @@ -7553,6 +7622,12 @@ static void BufferBattlePartyOrderBySide(u8 *partyBattleOrder, u8 flankId, u8 ba } else { + u8 rightBattler; + if (IsOnPlayerSide(battler)) + rightBattler = GetBattlerAtPosition(B_POSITION_PLAYER_RIGHT); + else + rightBattler = GetBattlerAtPosition(B_POSITION_OPPONENT_RIGHT); + j = 2; partyIndexes[0] = gBattlerPartyIndexes[leftBattler]; partyIndexes[1] = gBattlerPartyIndexes[rightBattler]; @@ -7865,6 +7940,7 @@ static void Task_ChoosePartyMon(u8 taskId) void ChooseMonForMoveRelearner(void) { + gRelearnMode = RELEARN_MODE_SCRIPT; LockPlayerFieldControls(); FadeScreen(FADE_TO_BLACK, 0); CreateTask(Task_ChooseMonForMoveRelearner, 10); @@ -7884,9 +7960,27 @@ static void CB2_ChooseMonForMoveRelearner(void) { gSpecialVar_0x8004 = GetCursorSelectionMonId(); if (gSpecialVar_0x8004 >= PARTY_SIZE) + { gSpecialVar_0x8004 = PARTY_NOTHING_CHOSEN; + } else - gSpecialVar_0x8005 = GetNumberOfRelearnableMoves(&gPlayerParty[gSpecialVar_0x8004]); + { + switch(gMoveRelearnerState) + { + case MOVE_RELEARNER_EGG_MOVES: + gSpecialVar_0x8005 = HasRelearnerEggMoves(&gPlayerParty[gSpecialVar_0x8004]); + break; + case MOVE_RELEARNER_TM_MOVES: + gSpecialVar_0x8005 = HasRelearnerTMMoves(&gPlayerParty[gSpecialVar_0x8004]); + break; + case MOVE_RELEARNER_TUTOR_MOVES: + gSpecialVar_0x8005 = HasRelearnerTutorMoves(&gPlayerParty[gSpecialVar_0x8004]); + break; + default: + gSpecialVar_0x8005 = HasRelearnerLevelUpMoves(&gPlayerParty[gSpecialVar_0x8004]); + break; + } + } gFieldCallback2 = CB2_FadeFromPartyMenu; SetMainCallback2(CB2_ReturnToField); } @@ -8016,6 +8110,62 @@ void IsLastMonThatKnowsSurf(void) } } +static void CursorCb_ChangeLevelUpMoves(u8 taskId) +{ + PlaySE(SE_SELECT); + gMoveRelearnerState = MOVE_RELEARNER_LEVEL_UP_MOVES; + gRelearnMode = RELEARN_MODE_PARTY_MENU; + gLastViewedMonIndex = gPartyMenu.slotId; + gSpecialVar_0x8004 = gLastViewedMonIndex; + TeachMoveRelearnerMove(); + Task_ClosePartyMenu(taskId); +} + +static void CursorCb_ChangeEggMoves(u8 taskId) +{ + PlaySE(SE_SELECT); + gMoveRelearnerState = MOVE_RELEARNER_EGG_MOVES; + gRelearnMode = RELEARN_MODE_PARTY_MENU; + gLastViewedMonIndex = gPartyMenu.slotId; + gSpecialVar_0x8004 = gLastViewedMonIndex; + TeachMoveRelearnerMove(); + Task_ClosePartyMenu(taskId); +} + +static void CursorCb_ChangeTMMoves(u8 taskId) +{ + PlaySE(SE_SELECT); + gMoveRelearnerState = MOVE_RELEARNER_TM_MOVES; + gRelearnMode = RELEARN_MODE_PARTY_MENU; + gLastViewedMonIndex = gPartyMenu.slotId; + gSpecialVar_0x8004 = gLastViewedMonIndex; + TeachMoveRelearnerMove(); + Task_ClosePartyMenu(taskId); +} + +static void CursorCb_ChangeTutorMoves(u8 taskId) +{ + PlaySE(SE_SELECT); + gMoveRelearnerState = MOVE_RELEARNER_TUTOR_MOVES; + gRelearnMode = RELEARN_MODE_PARTY_MENU; + gLastViewedMonIndex = gPartyMenu.slotId; + gSpecialVar_0x8004 = gLastViewedMonIndex; + TeachMoveRelearnerMove(); + Task_ClosePartyMenu(taskId); +} + +static void CursorCb_LearnMovesSubMenu(u8 taskId) +{ + PlaySE(SE_SELECT); + PartyMenuRemoveWindow(&sPartyMenuInternal->windowId[0]); + PartyMenuRemoveWindow(&sPartyMenuInternal->windowId[1]); + SetPartyMonSelectionActions(gPlayerParty, gPartyMenu.slotId, ACTIONS_MOVES_SUB); + DisplaySelectionWindow(SELECTWINDOW_ACTIONS); + DisplayPartyMenuStdMessage(PARTY_MSG_DO_WHAT_WITH_MON); + gTasks[taskId].data[0] = 0xFF; + gTasks[taskId].func = Task_HandleSelectionMenuInput; +} + void CursorCb_MoveItemCallback(u8 taskId) { u16 item1, item2; diff --git a/src/pokedex.c b/src/pokedex.c index 3c5fce0474..da0cc30061 100644 --- a/src/pokedex.c +++ b/src/pokedex.c @@ -1426,7 +1426,7 @@ static const u8 sOrderOptions[] = ORDER_SMALLEST, }; -static const u8 sDexSearchTypeIds[NUMBER_OF_MON_TYPES] = +static const enum Type sDexSearchTypeIds[NUMBER_OF_MON_TYPES] = { TYPE_NONE, TYPE_NORMAL, @@ -4959,12 +4959,12 @@ static u16 CreateSizeScreenTrainerPic(u16 species, s16 x, s16 y, s8 paletteSlot) return CreateTrainerPicSprite(species, TRUE, x, y, paletteSlot, TAG_NONE); } -static int DoPokedexSearch(u8 dexMode, u8 order, u8 abcGroup, enum BodyColor bodyColor, u8 type1, u8 type2) +static int DoPokedexSearch(u8 dexMode, u8 order, u8 abcGroup, enum BodyColor bodyColor, enum Type type1, enum Type type2) { u16 species; u16 i; u16 resultsCount; - u8 types[2]; + enum Type types[2]; CreatePokedexList(dexMode, order); @@ -5371,8 +5371,8 @@ static void Task_StartPokedexSearch(u8 taskId) u8 order = GetSearchModeSelection(taskId, SEARCH_ORDER); u8 abcGroup = GetSearchModeSelection(taskId, SEARCH_NAME); enum BodyColor bodyColor = GetSearchModeSelection(taskId, SEARCH_COLOR); - u8 type1 = GetSearchModeSelection(taskId, SEARCH_TYPE_LEFT); - u8 type2 = GetSearchModeSelection(taskId, SEARCH_TYPE_RIGHT); + enum Type type1 = GetSearchModeSelection(taskId, SEARCH_TYPE_LEFT); + enum Type type2 = GetSearchModeSelection(taskId, SEARCH_TYPE_RIGHT); DoPokedexSearch(dexMode, order, abcGroup, bodyColor, type1, type2); gTasks[taskId].func = Task_WaitAndCompleteSearch; diff --git a/src/pokedex_area_screen.c b/src/pokedex_area_screen.c index 8d2f0b8c50..82312a9539 100644 --- a/src/pokedex_area_screen.c +++ b/src/pokedex_area_screen.c @@ -248,7 +248,7 @@ static const struct WindowTemplate sTimeOfDayWindowLabelTemplates[] = .baseBlock = 0x16C }, - [DEX_AREA_LABEL_AREA_UNKNOWN] = + [DEX_AREA_LABEL_AREA_UNKNOWN] = { .bg = LABEL_WINDOW_BG, .tilemapLeft = 12, diff --git a/src/pokedex_cry_screen.c b/src/pokedex_cry_screen.c index b567aac391..810a8dae6a 100644 --- a/src/pokedex_cry_screen.c +++ b/src/pokedex_cry_screen.c @@ -228,7 +228,7 @@ static const struct SpritePalette sCryMeterNeedleSpritePalettes[] = bool8 LoadCryWaveformWindow(struct CryScreenWindow *window, u8 windowId) { u8 i; - u8 finished = FALSE; + bool32 finished = FALSE; switch (gDexCryScreenState) { diff --git a/src/pokedex_plus_hgss.c b/src/pokedex_plus_hgss.c index 607ced5f47..ff7f14759c 100644 --- a/src/pokedex_plus_hgss.c +++ b/src/pokedex_plus_hgss.c @@ -2,6 +2,7 @@ #include "battle_main.h" #include "battle_util.h" #include "bg.h" +#include "contest.h" #include "contest_effect.h" #include "data.h" #include "daycare.h" @@ -362,9 +363,9 @@ struct PokemonStats u8 eggCycles; u16 expYield; u8 friendship; - u16 ability0; - u16 ability1; - u16 abilityHidden; + enum Ability ability0; + enum Ability ability1; + enum Ability abilityHidden; }; struct EvoScreenData @@ -1915,7 +1916,7 @@ static const u8 sOrderOptions[] = ORDER_SMALLEST, }; -static const u8 sDexSearchTypeIds[NUMBER_OF_MON_TYPES] = +static const enum Type sDexSearchTypeIds[NUMBER_OF_MON_TYPES] = { TYPE_NONE, TYPE_NORMAL, @@ -4342,14 +4343,7 @@ static void SetSpriteInvisibility(u8 spriteArrayId, bool8 invisible) { gSprites[sPokedexView->typeIconSpriteIds[spriteArrayId]].invisible = invisible; } -static const u8 sContestCategoryToOamPaletteNum[CONTEST_CATEGORIES_COUNT] = -{ - [CONTEST_CATEGORY_COOL] = 13, - [CONTEST_CATEGORY_BEAUTY] = 14, - [CONTEST_CATEGORY_CUTE] = 14, - [CONTEST_CATEGORY_SMART] = 15, - [CONTEST_CATEGORY_TOUGH] = 13, -}; + static void SetTypeIconPosAndPal(u8 typeId, u8 x, u8 y, u8 spriteArrayId) { struct Sprite *sprite; @@ -4359,14 +4353,14 @@ static void SetTypeIconPosAndPal(u8 typeId, u8 x, u8 y, u8 spriteArrayId) if (typeId < NUMBER_OF_MON_TYPES) sprite->oam.paletteNum = gTypesInfo[typeId].palette + TYPE_INFO_PALETTE_NUM_OFFSET; else - sprite->oam.paletteNum = sContestCategoryToOamPaletteNum[typeId - NUMBER_OF_MON_TYPES] + TYPE_INFO_PALETTE_NUM_OFFSET; + sprite->oam.paletteNum = gContestCategoryInfo[typeId - NUMBER_OF_MON_TYPES].palette + TYPE_INFO_PALETTE_NUM_OFFSET; sprite->x = x + 16; sprite->y = y + 8; SetSpriteInvisibility(spriteArrayId, FALSE); } static void PrintCurrentSpeciesTypeInfo(u8 newEntry, u16 species) { - u8 type1, type2; + enum Type type1, type2; if (!newEntry) { @@ -4870,7 +4864,6 @@ static void Task_LoadStatsScreen(u8 taskId) sPokedexView->typeIconSpriteIds[1] = 0xFF; CreateTypeIconSprites(); sPokedexView->categoryIconSpriteId = 0xFF; - LoadPalette(gMoveTypes_Pal, 0x1D0, 0x60); LoadCompressedSpriteSheet(&gSpriteSheet_CategoryIcons); LoadSpritePalette(&gSpritePal_CategoryIcons); gMain.state++; @@ -5304,7 +5297,7 @@ static void PrintStatsScreen_Moves_Description(u8 taskId) } else { - StringCopy(gStringVar4, gContestEffectDescriptionPointers[GetMoveContestEffect(move)]); + StringCopy(gStringVar4, gContestEffects[GetMoveContestEffect(move)].description); PrintStatsScreenTextSmall(WIN_STATS_MOVES_DESCRIPTION, gStringVar4, moves_x, moves_y); } } @@ -5905,9 +5898,9 @@ static void PrintStatsScreen_Abilities(u8 taskId) { u8 abilities_x = 5; u8 abilities_y = 3; - u16 ability0; - u16 ability1; - u16 abilityHidden; + enum Ability ability0; + enum Ability ability1; + enum Ability abilityHidden; //Abilitie(s) @@ -6663,7 +6656,8 @@ static void PrintEvolutionTargetSpeciesAndMethod(u8 taskId, u16 species, u8 dept StringAppend(gStringVar4, COMPOUND_STRING(", ")); } - switch((enum EvolutionConditions)evolutions[i].params[j].condition) + enum EvolutionConditions condition = evolutions[i].params[j].condition; + switch(condition) { // Gen 2 case IF_GENDER: @@ -6720,10 +6714,10 @@ static void PrintEvolutionTargetSpeciesAndMethod(u8 taskId, u16 species, u8 dept case IF_PID_UPPER_MODULO_10_EQ: case IF_PID_UPPER_MODULO_10_LT: arg = evolutions[i].params[j].arg1; - if ((enum EvolutionConditions)evolutions[i].params[j].condition == IF_PID_UPPER_MODULO_10_GT + if (condition == IF_PID_UPPER_MODULO_10_GT && arg < 10 && arg >= 0) arg = 9 - arg; - else if ((enum EvolutionConditions)evolutions[i].params[j].condition == IF_PID_UPPER_MODULO_10_EQ + else if (condition == IF_PID_UPPER_MODULO_10_EQ && arg < 10 && arg >= 0) arg = 1; ConvertIntToDecimalStringN(gStringVar2, arg * 10, STR_CONV_MODE_LEFT_ALIGN, 3); @@ -6785,6 +6779,33 @@ static void PrintEvolutionTargetSpeciesAndMethod(u8 taskId, u16 species, u8 dept StringAppend(gStringVar4, gTypesInfo[evolutions[i].params[j].arg1].name); StringAppend(gStringVar4, COMPOUND_STRING("招式")); break; + case IF_REGION: + case IF_NOT_REGION: + { + if (condition == IF_REGION) + StringAppend(gStringVar4, COMPOUND_STRING("in ")); + else if (condition == IF_NOT_REGION) + StringAppend(gStringVar4, COMPOUND_STRING("out of ")); + + switch ((enum Region)evolutions[i].params[j].arg1) + { + case REGION_NONE: + case REGIONS_COUNT: + StringAppend(gStringVar4, COMPOUND_STRING("???")); + break; + case REGION_KANTO: StringAppend(gStringVar4, COMPOUND_STRING("Kanto")); break; + case REGION_JOHTO: StringAppend(gStringVar4, COMPOUND_STRING("Johto")); break; + case REGION_HOENN: StringAppend(gStringVar4, COMPOUND_STRING("Hoenn")); break; + case REGION_SINNOH: StringAppend(gStringVar4, COMPOUND_STRING("Sinnoh")); break; + case REGION_UNOVA: StringAppend(gStringVar4, COMPOUND_STRING("Unova")); break; + case REGION_KALOS: StringAppend(gStringVar4, COMPOUND_STRING("Kalos")); break; + case REGION_ALOLA: StringAppend(gStringVar4, COMPOUND_STRING("Alola")); break; + case REGION_GALAR: StringAppend(gStringVar4, COMPOUND_STRING("Galar")); break; + case REGION_HISUI: StringAppend(gStringVar4, COMPOUND_STRING("Hisui")); break; + case REGION_PALDEA: StringAppend(gStringVar4, COMPOUND_STRING("Paldea")); break; + } + break; + } // Gen 8 case IF_NATURE: StringCopy(gStringVar2, gNaturesInfo[evolutions[i].params[j].arg1].name); @@ -6837,10 +6858,10 @@ static void PrintEvolutionTargetSpeciesAndMethod(u8 taskId, u16 species, u8 dept case IF_PID_MODULO_100_EQ: case IF_PID_MODULO_100_LT: arg = evolutions[i].params[j].arg1; - if ((enum EvolutionConditions)evolutions[i].params[j].condition == IF_PID_MODULO_100_GT + if (condition == IF_PID_MODULO_100_GT && arg < 100 && arg >= 0) arg = 99 - arg; - else if ((enum EvolutionConditions)evolutions[i].params[j].condition == IF_PID_MODULO_100_EQ + else if (condition == IF_PID_MODULO_100_EQ && arg < 100 && arg >= 0) arg = 1; ConvertIntToDecimalStringN(gStringVar2, arg, STR_CONV_MODE_LEFT_ALIGN, 3); @@ -7851,12 +7872,12 @@ static void Task_ClosePokedexFromSearchResultsStartMenu(u8 taskId) //* Search code * //* * //************************************ -static int DoPokedexSearch(u8 dexMode, u8 order, u8 abcGroup, enum BodyColor bodyColor, u8 type1, u8 type2) +static int DoPokedexSearch(u8 dexMode, u8 order, u8 abcGroup, enum BodyColor bodyColor, enum Type type1, enum Type type2) { u16 species; u16 i; u16 resultsCount; - u8 types[2]; + enum Type types[2]; CreatePokedexList(dexMode, order); @@ -8268,8 +8289,8 @@ static void Task_StartPokedexSearch(u8 taskId) u8 order = GetSearchModeSelection(taskId, SEARCH_ORDER); u8 abcGroup = GetSearchModeSelection(taskId, SEARCH_NAME); enum BodyColor bodyColor = GetSearchModeSelection(taskId, SEARCH_COLOR); - u8 type1 = GetSearchModeSelection(taskId, SEARCH_TYPE_LEFT); - u8 type2 = GetSearchModeSelection(taskId, SEARCH_TYPE_RIGHT); + enum Type type1 = GetSearchModeSelection(taskId, SEARCH_TYPE_LEFT); + enum Type type2 = GetSearchModeSelection(taskId, SEARCH_TYPE_RIGHT); DoPokedexSearch(dexMode, order, abcGroup, bodyColor, type1, type2); gTasks[taskId].func = Task_WaitAndCompleteSearch; diff --git a/src/pokemon.c b/src/pokemon.c index 72b8832052..68775003e0 100644 --- a/src/pokemon.c +++ b/src/pokemon.c @@ -12,6 +12,7 @@ #include "battle_tower.h" #include "battle_z_move.h" #include "data.h" +#include "daycare.h" #include "dexnav.h" #include "event_data.h" #include "event_object_movement.h" @@ -19,12 +20,14 @@ #include "field_player_avatar.h" #include "field_specials.h" #include "field_weather.h" +#include "fishing.h" #include "follower_npc.h" #include "graphics.h" #include "item.h" #include "caps.h" #include "link.h" #include "main.h" +#include "move_relearner.h" #include "overworld.h" #include "m4a.h" #include "party_menu.h" @@ -37,6 +40,7 @@ #include "pokemon_storage_system.h" #include "random.h" #include "recorded_battle.h" +#include "regions.h" #include "rtc.h" #include "sound.h" #include "string_util.h" @@ -55,7 +59,6 @@ #include "constants/cries.h" #include "constants/event_objects.h" #include "constants/form_change_types.h" -#include "constants/hold_effects.h" #include "constants/item_effects.h" #include "constants/items.h" #include "constants/layouts.h" @@ -65,7 +68,6 @@ #include "constants/trainers.h" #include "constants/union_room.h" #include "constants/weather.h" -#include "wild_encounter.h" #define FRIENDSHIP_EVO_THRESHOLD ((P_FRIENDSHIP_EVO_THRESHOLD >= GEN_8) ? 160 : 220) @@ -852,7 +854,7 @@ static const u8 sGetMonDataEVConstants[] = }; // For stat-raising items -static const u8 sStatsToRaise[] = +static const enum Stat sStatsToRaise[] = { STAT_ATK, STAT_ATK, STAT_DEF, STAT_SPEED, STAT_SPATK, STAT_SPDEF, STAT_ACC }; @@ -1042,8 +1044,8 @@ void CreateBoxMon(struct BoxPokemon *boxMon, u16 species, u8 level, u8 fixedIV, u32 value; u16 checksum; u8 i; - u8 availableIVs[NUM_STATS]; - u8 selectedIvs[NUM_STATS]; + enum Stat availableIVs[NUM_STATS]; + enum Stat selectedIvs[NUM_STATS]; bool32 isShiny; ZeroBoxMonData(boxMon); @@ -1089,8 +1091,7 @@ void CreateBoxMon(struct BoxPokemon *boxMon, u16 species, u8 level, u8 fixedIV, totalRerolls += I_SHINY_CHARM_ADDITIONAL_ROLLS; if (LURE_STEP_COUNT != 0) totalRerolls += 1; - if (I_FISHING_CHAIN && gIsFishingEncounter) - totalRerolls += CalculateChainFishingShinyRolls(); + totalRerolls += CalculateChainFishingShinyRolls(); if (gDexNavSpecies) totalRerolls += CalculateDexNavShinyRolls(); @@ -1129,7 +1130,7 @@ void CreateBoxMon(struct BoxPokemon *boxMon, u16 species, u8 level, u8 fixedIV, SetBoxMonData(boxMon, MON_DATA_POKEBALL, &value); SetBoxMonData(boxMon, MON_DATA_OT_GENDER, &gSaveBlock2Ptr->playerGender); - u32 teraType = (boxMon->personality & 0x1) == 0 ? GetSpeciesType(species, 0) : GetSpeciesType(species, 1); + enum Type teraType = (boxMon->personality & 0x1) == 0 ? GetSpeciesType(species, 0) : GetSpeciesType(species, 1); SetBoxMonData(boxMon, MON_DATA_TERA_TYPE, &teraType); if (fixedIV < USE_RANDOM_IVS) @@ -1201,6 +1202,8 @@ void CreateBoxMon(struct BoxPokemon *boxMon, u16 species, u8 level, u8 fixedIV, case STAT_SPDEF: SetBoxMonData(boxMon, MON_DATA_SPDEF_IV, &iv); break; + default: + break; } } } @@ -2739,7 +2742,7 @@ u32 GetBoxMonData3(struct BoxPokemon *boxMon, s32 field, u8 *data) } else if (substruct0->teraType == TYPE_NONE) // Tera Type hasn't been modified so we can just use the personality { - const u8 *types = gSpeciesInfo[substruct0->species].types; + const enum Type *types = gSpeciesInfo[substruct0->species].types; retVal = (boxMon->personality & 0x1) == 0 ? types[0] : types[1]; } else @@ -2843,7 +2846,7 @@ u32 GetBoxMonData2(struct BoxPokemon *boxMon, s32 field) #define SET16(lhs) (lhs) = data[0] + (data[1] << 8) #define SET32(lhs) (lhs) = data[0] + (data[1] << 8) + (data[2] << 16) + (data[3] << 24) // -// Prefer SET_BY_WIDTH for fields whose types might be extended (e.g. +// Prefer SET_BY_WIDTH for fields whose types might be extended (e.g. // anything whose typedef is in gametypes.h). // #define SET_BY_WIDTH(lhs) \ @@ -3409,7 +3412,7 @@ u8 GetMonsStateToDoubles_2(void) return (aliveCount > 1) ? PLAYER_HAS_TWO_USABLE_MONS : PLAYER_HAS_ONE_USABLE_MON; } -u16 GetAbilityBySpecies(u16 species, u8 abilityNum) +enum Ability GetAbilityBySpecies(u16 species, u8 abilityNum) { int i; @@ -3434,7 +3437,7 @@ u16 GetAbilityBySpecies(u16 species, u8 abilityNum) return gLastUsedAbility; } -u16 GetMonAbility(struct Pokemon *mon) +enum Ability GetMonAbility(struct Pokemon *mon) { u16 species = GetMonData(mon, MON_DATA_SPECIES, NULL); u8 abilityNum = GetMonData(mon, MON_DATA_ABILITY_NUM, NULL); @@ -3545,12 +3548,12 @@ u32 GetSpeciesWeight(u16 species) return gSpeciesInfo[SanitizeSpeciesId(species)].weight; } -u32 GetSpeciesType(u16 species, u8 slot) +enum Type GetSpeciesType(u16 species, u8 slot) { return gSpeciesInfo[SanitizeSpeciesId(species)].types[slot]; } -u32 GetSpeciesAbility(u16 species, u8 slot) +enum Ability GetSpeciesAbility(u16 species, u8 slot) { return gSpeciesInfo[SanitizeSpeciesId(species)].abilities[slot]; } @@ -3741,17 +3744,7 @@ bool8 ExecuteTableBasedItemEffect(struct Pokemon *mon, u16 item, u8 partyIndex, { \ friendshipChange = itemEffect[itemEffectParam]; \ friendship = GetMonData(mon, MON_DATA_FRIENDSHIP, NULL); \ - if (friendshipChange > 0 && holdEffect == HOLD_EFFECT_FRIENDSHIP_UP) \ - friendship += 150 * friendshipChange / 100; \ - else \ - friendship += friendshipChange; \ - if (friendshipChange > 0) \ - { \ - if (GetMonData(mon, MON_DATA_POKEBALL, NULL) == ITEM_LUXURY_BALL) \ - friendship++; \ - if (GetMonData(mon, MON_DATA_MET_LOCATION, NULL) == GetCurrentRegionMapSectionId()) \ - friendship++; \ - } \ + friendship += CalculateFriendshipBonuses(mon,friendshipChange,holdEffect); \ if (friendship < 0) \ friendship = 0; \ if (friendship > MAX_FRIENDSHIP) \ @@ -3782,9 +3775,9 @@ bool8 PokemonUseItemEffects(struct Pokemon *mon, u16 item, u8 partyIndex, u8 mov u8 itemEffectParam = ITEM_EFFECT_ARG_START; u32 temp1, temp2; s8 friendshipChange = 0; - u8 holdEffect; + enum HoldEffect holdEffect; u8 battler = MAX_BATTLERS_COUNT; - u32 friendshipOnly = FALSE; + bool32 friendshipOnly = FALSE; u16 heldItem; u8 effectFlags; s8 evChange; @@ -4368,7 +4361,7 @@ u8 GetItemEffectParamOffset(u32 battler, u16 itemId, u8 effectByte, u8 effectBit return offset; } -static void BufferStatRoseMessage(s32 statIdx) +static void BufferStatRoseMessage(enum Stat statIdx) { gBattlerTarget = gBattlerInMenuId; StringCopy(gBattleTextBuff1, gStatNamesTable[sStatsToRaise[statIdx]]); @@ -4482,7 +4475,7 @@ bool32 DoesMonMeetAdditionalConditions(struct Pokemon *mon, const struct Evoluti u32 removeBagItemCount = 0; u32 evolutionTracker = GetMonData(mon, MON_DATA_EVOLUTION_TRACKER, 0); u32 partnerSpecies, partnerHeldItem; - enum ItemHoldEffect partnerHoldEffect; + enum HoldEffect partnerHoldEffect; if (tradePartner != NULL) { @@ -4509,7 +4502,7 @@ bool32 DoesMonMeetAdditionalConditions(struct Pokemon *mon, const struct Evoluti for (i = 0; params != NULL && params[i].condition != CONDITIONS_END; i++) { enum EvolutionConditions condition = params[i].condition; - u32 currentCondition = FALSE; + bool32 currentCondition = FALSE; switch(condition) { @@ -4761,6 +4754,14 @@ bool32 DoesMonMeetAdditionalConditions(struct Pokemon *mon, const struct Evoluti *canStopEvo = FALSE; } break; + case IF_REGION: + if (GetCurrentRegion() == params[i].arg1) + currentCondition = TRUE; + break; + case IF_NOT_REGION: + if (GetCurrentRegion() != params[i].arg1) + currentCondition = TRUE; + break; case CONDITIONS_END: break; } @@ -4792,7 +4793,7 @@ u32 GetEvolutionTargetSpecies(struct Pokemon *mon, enum EvolutionMode mode, u16 u32 species = GetMonData(mon, MON_DATA_SPECIES, 0); u32 heldItem = GetMonData(mon, MON_DATA_HELD_ITEM, 0); u32 level = GetMonData(mon, MON_DATA_LEVEL, 0); - u32 holdEffect; + enum HoldEffect holdEffect; const struct Evolution *evolutions = GetSpeciesEvolutions(species); if (evolutions == NULL) @@ -5235,7 +5236,7 @@ u8 GetTrainerEncounterMusicId(u16 trainerOpponentId) return gTrainers[difficulty][sanitizedTrainerId].encounterMusic_gender & (F_TRAINER_FEMALE - 1); } -u16 ModifyStatByNature(u8 nature, u16 stat, u8 statIndex) +u16 ModifyStatByNature(u8 nature, u16 stat, enum Stat statIndex) { // Don't modify HP, Accuracy, or Evasion by nature if (statIndex <= STAT_HP || statIndex > NUM_NATURE_STATS || gNaturesInfo[nature].statUp == gNaturesInfo[nature].statDown) @@ -5251,7 +5252,7 @@ u16 ModifyStatByNature(u8 nature, u16 stat, u8 statIndex) void AdjustFriendship(struct Pokemon *mon, u8 event) { u16 species, heldItem; - u8 holdEffect; + enum HoldEffect holdEffect; s8 mod; if (ShouldSkipFriendshipChange()) @@ -5279,7 +5280,7 @@ void AdjustFriendship(struct Pokemon *mon, u8 event) if (species && species != SPECIES_EGG) { u8 friendshipLevel = 0; - s16 friendship = GetMonData(mon, MON_DATA_FRIENDSHIP, 0); + s32 friendship = GetMonData(mon, MON_DATA_FRIENDSHIP, 0); enum TrainerClassID opponentTrainerClass = GetTrainerClassFromId(TRAINER_BATTLE_PARAM.opponentA); if (friendship > 99) @@ -5305,18 +5306,7 @@ void AdjustFriendship(struct Pokemon *mon, u8 event) } mod = sFriendshipEventModifiers[event][friendshipLevel]; - if (mod > 0 && holdEffect == HOLD_EFFECT_FRIENDSHIP_UP) - // 50% increase, rounding down - mod = (150 * mod) / 100; - - friendship += mod; - if (mod > 0) - { - if (GetMonData(mon, MON_DATA_POKEBALL, NULL) == ITEM_LUXURY_BALL) - friendship++; - if (GetMonData(mon, MON_DATA_MET_LOCATION, NULL) == GetCurrentRegionMapSectionId()) - friendship++; - } + friendship += CalculateFriendshipBonuses(mon,mod,holdEffect); if (friendship < 0) friendship = 0; @@ -5327,14 +5317,36 @@ void AdjustFriendship(struct Pokemon *mon, u8 event) } } +u8 CalculateFriendshipBonuses(struct Pokemon *mon, u32 modifier, enum HoldEffect itemHoldEffect) +{ + u32 bonus = 0; + + if ((modifier > 0) && (itemHoldEffect == HOLD_EFFECT_FRIENDSHIP_UP)) + bonus += 150 * modifier / 100; + else + bonus += modifier; + + if (modifier == 0) + return bonus; + + if (GetMonData(mon, MON_DATA_POKEBALL, NULL) == ITEM_LUXURY_BALL) + bonus += ITEM_FRIENDSHIP_LUXURY_BONUS; + + if (GetMonData(mon, MON_DATA_MET_LOCATION, NULL) == GetCurrentRegionMapSectionId()) + bonus += ITEM_FRIENDSHIP_MAPSEC_BONUS; + + return bonus; +} + void MonGainEVs(struct Pokemon *mon, u16 defeatedSpecies) { u8 evs[NUM_STATS]; u16 evIncrease = 0; u16 totalEVs = 0; u16 heldItem; - u8 holdEffect; - int i, multiplier; + enum HoldEffect holdEffect; + enum Stat i; + int multiplier; u8 stat; u8 bonus; u32 currentEVCap = GetCurrentEVCap(); @@ -5413,6 +5425,8 @@ void MonGainEVs(struct Pokemon *mon, u16 defeatedSpecies) else evIncrease = gSpeciesInfo[defeatedSpecies].evYield_SpDefense * multiplier; break; + default: + break; } if (holdEffect == HOLD_EFFECT_MACHO_BRACE) @@ -5697,46 +5711,380 @@ u8 CanLearnTeachableMove(u16 species, u16 move) } } -u8 GetMoveRelearnerMoves(struct Pokemon *mon, u16 *moves) +static void QuickSortMoves(u16 *moves, s32 left, s32 right) { - u16 learnedMoves[4]; - u8 numMoves = 0; - u16 species = GetMonData(mon, MON_DATA_SPECIES, 0); - u8 level = GetMonData(mon, MON_DATA_LEVEL, 0); - const struct LevelUpMove *learnset = GetSpeciesLevelUpLearnset(species); - int i, j, k; + if (left >= right) + return; - for (i = 0; i < MAX_MON_MOVES; i++) - learnedMoves[i] = GetMonData(mon, MON_DATA_MOVE1 + i, 0); + u16 pivot = moves[(left + right) / 2]; + s32 i = left, j = right; - for (i = 0; i < MAX_LEVEL_UP_MOVES; i++) + while (i <= j) { - u16 moveLevel; + while (moves[i] != MOVE_NONE && StringCompare(GetMoveName(moves[i]), GetMoveName(pivot)) < 0) + i++; + while (moves[j] != MOVE_NONE && StringCompare(GetMoveName(moves[j]), GetMoveName(pivot)) > 0) + j--; - if (learnset[i].move == LEVEL_UP_MOVE_END) - break; - - moveLevel = learnset[i].level; - - if (moveLevel <= level) + if (i <= j) { - for (j = 0; j < MAX_MON_MOVES && learnedMoves[j] != learnset[i].move; j++) - ; - - if (j == MAX_MON_MOVES) - { - for (k = 0; k < numMoves && moves[k] != learnset[i].move; k++) - ; - - if (k == numMoves) - moves[numMoves++] = learnset[i].move; - } + u16 temp = moves[i]; + moves[i] = moves[j]; + moves[j] = temp; + i++; + j--; } } + QuickSortMoves(moves, left, j); + QuickSortMoves(moves, i, right); +} + +static void SortMovesAlphabetically(u16 *moves, u32 numMoves) +{ + if (numMoves > 1) + QuickSortMoves(moves, 0, numMoves - 1); +} + +u32 GetRelearnerLevelUpMoves(struct Pokemon *mon, u16 *moves) +{ + u16 learnedMoves[MAX_MON_MOVES] = {0}; + u32 numMoves = 0; + u32 species = GetMonData(mon, MON_DATA_SPECIES, 0); + u32 level = (P_ENABLE_ALL_LEVEL_UP_MOVES ? MAX_LEVEL : GetMonData(mon, MON_DATA_LEVEL, 0)); + + for (u32 i = 0; i < MAX_MON_MOVES; i++) + learnedMoves[i] = GetMonData(mon, MON_DATA_MOVE1 + i, 0); + + do + { + const struct LevelUpMove *learnset = GetSpeciesLevelUpLearnset(species); + + for (u32 i = 0; i < MAX_LEVEL_UP_MOVES && learnset[i].move != LEVEL_UP_MOVE_END; i++) + { + if (learnset[i].level > level) + break; + + u32 j; + for (j = 0; j < MAX_MON_MOVES; j++) + { + if (learnedMoves[j] == learnset[i].move) + break; + } + if (j < MAX_MON_MOVES) + continue; + + for (j = 0; j < numMoves; j++) + { + if (moves[j] == learnset[i].move) + break; + } + if (j < numMoves) + continue; + + moves[numMoves++] = learnset[i].move; + } + + species = (P_PRE_EVO_MOVES ? GetSpeciesPreEvolution(species) : SPECIES_NONE); + } while (species != SPECIES_NONE); + + if (P_SORT_MOVES) + SortMovesAlphabetically(moves, numMoves); + return numMoves; } +u32 GetRelearnerEggMoves(struct Pokemon *mon, u16 *moves) +{ + if (!FlagGet(P_FLAG_EGG_MOVES) && !P_ENABLE_MOVE_RELEARNERS) + return 0; + + u32 learnedMoves[MAX_MON_MOVES] = {0}; + u32 numMoves = 0; + u32 species = GetMonData(mon, MON_DATA_SPECIES); + + while (GetSpeciesPreEvolution(species) != SPECIES_NONE) + species = GetSpeciesPreEvolution(species); + const u16 *eggMoves = GetSpeciesEggMoves(species); + + if (eggMoves == sNoneEggMoveLearnset) + return numMoves; + + for (u32 i = 0; i < MAX_MON_MOVES; i++) + learnedMoves[i] = GetMonData(mon, MON_DATA_MOVE1 + i, 0); + + for (u32 i = 0; eggMoves[i] != MOVE_UNAVAILABLE; i++) + { + u32 j; + for (j = 0; j < MAX_MON_MOVES; j++) + { + if (learnedMoves[j] == eggMoves[i]) + break; + } + if (j < MAX_MON_MOVES) + continue; + + for (j = 0; j < numMoves; j++) + { + if (moves[j] == eggMoves[i]) + break; + } + if (j < numMoves) + continue; + + moves[numMoves++] = eggMoves[i]; + } + + if (P_SORT_MOVES) + SortMovesAlphabetically(moves, numMoves); + + return numMoves; +} + +u32 GetRelearnerTMMoves(struct Pokemon *mon, u16 *moves) +{ + if (!P_TM_MOVES_RELEARNER) + return 0; + + u32 learnedMoves[MAX_MON_MOVES] = {0}; + u32 numMoves = 0; + u32 species = GetMonData(mon, MON_DATA_SPECIES); + u16 allMoves[NUM_ALL_MACHINES]; + u32 totalMoveCount = 0; + + for (u32 i = 0; i < NUM_ALL_MACHINES; i++) + { + enum TMHMItemId item = GetTMHMItemId(i + 1); + u32 move = GetTMHMMoveId(i + 1); + + if (move == MOVE_NONE) + continue; + + if ((P_ENABLE_ALL_TM_MOVES || CheckBagHasItem(item, 1)) && CanLearnTeachableMove(species, move) && move != MOVE_NONE) + allMoves[totalMoveCount++] = move; + } + + for (u32 i = 0; i < MAX_MON_MOVES; i++) + learnedMoves[i] = GetMonData(mon, MON_DATA_MOVE1 + i, 0); + + for (u32 i = 0; i < totalMoveCount; i++) + { + u32 j; + for (j = 0; j < MAX_MON_MOVES; j++) + { + if (learnedMoves[j] == allMoves[i]) + break; + } + if (j < MAX_MON_MOVES) + continue; + + for (j = 0; j < numMoves; j++) + { + if (moves[j] == allMoves[i]) + break; + } + if (j < numMoves) + continue; + + moves[numMoves++] = allMoves[i]; + } + + if (P_SORT_MOVES) + SortMovesAlphabetically(moves, numMoves); + + return numMoves; +} + +u32 GetRelearnerTutorMoves(struct Pokemon *mon, u16 *moves) +{ + if (!FlagGet(P_FLAG_TUTOR_MOVES) && !P_ENABLE_MOVE_RELEARNERS) + return 0; + +#if P_TUTOR_MOVES_ARRAY + u16 learnedMoves[MAX_MON_MOVES] = {0}; + u32 numMoves = 0; + u32 species = GetMonData(mon, MON_DATA_SPECIES, 0); + + for (u32 i = 0; i < MAX_MON_MOVES; i++) + learnedMoves[i] = GetMonData(mon, MON_DATA_MOVE1 + i, 0); + + for (u32 i = 0; gTutorMoves[i] != MOVE_UNAVAILABLE; i++) + { + u32 move = gTutorMoves[i]; + + if (!CanLearnTeachableMove(species, move)) + continue; + + u32 j; + for (j = 0; j < MAX_MON_MOVES; j++) + { + if (learnedMoves[j] == move) + break; + } + if (j < MAX_MON_MOVES) + continue; + + for (j = 0; j < numMoves; j++) + { + if (moves[j] == move) + break; + } + if (j < numMoves) + continue; + + moves[numMoves++] = move; + } + + if (P_SORT_MOVES) + SortMovesAlphabetically(moves, numMoves); + + return numMoves; +#else + return 0; +#endif // P_TUTOR_MOVES_ARRAY +} + +static inline bool32 DoesMonHaveMove(const u16 *moves, u16 move) +{ + for (u32 i = 0; i < MAX_MON_MOVES; i++) + { + if (moves[i] == move) + return TRUE; + } + return FALSE; +} + +bool32 HasRelearnerLevelUpMoves(struct Pokemon *mon) +{ + u32 species = GetMonData(mon, MON_DATA_SPECIES_OR_EGG, 0); + + if (species == SPECIES_EGG) + return FALSE; + + u16 learnedMoves[MAX_MON_MOVES]; + + for (u32 i = 0; i < MAX_MON_MOVES; i++) + learnedMoves[i] = GetMonData(mon, MON_DATA_MOVE1 + i, 0); + + u32 level = (P_ENABLE_ALL_LEVEL_UP_MOVES ? MAX_LEVEL : GetMonData(mon, MON_DATA_LEVEL, 0)); + + do + { + const struct LevelUpMove *learnset = GetSpeciesLevelUpLearnset(species); + + for (u32 i = 0; i < MAX_LEVEL_UP_MOVES && learnset[i].move != LEVEL_UP_MOVE_END; i++) + { + if (learnset[i].level > level) + break; + + if (!DoesMonHaveMove(learnedMoves, learnset[i].move)) + return TRUE; + } + + species = (P_PRE_EVO_MOVES ? GetSpeciesPreEvolution(species) : SPECIES_NONE); + + } while (species != SPECIES_NONE); + + return FALSE; +} + +bool32 HasRelearnerEggMoves(struct Pokemon *mon) +{ + if (!FlagGet(P_FLAG_EGG_MOVES) && !P_ENABLE_MOVE_RELEARNERS) + return FALSE; + + u32 species = GetMonData(mon, MON_DATA_SPECIES_OR_EGG, 0); + + if (species == SPECIES_EGG) + return FALSE; + + u16 learnedMoves[MAX_MON_MOVES]; + + for (u32 i = 0; i < MAX_MON_MOVES; i++) + learnedMoves[i] = GetMonData(mon, MON_DATA_MOVE1 + i, 0); + + while (GetSpeciesPreEvolution(species) != SPECIES_NONE) + species = GetSpeciesPreEvolution(species); + + const u16 *eggMoves = GetSpeciesEggMoves(species); + if (eggMoves == sNoneEggMoveLearnset) + return FALSE; + + for (u32 i = 0; eggMoves[i] != MOVE_UNAVAILABLE; i++) + { + if (!DoesMonHaveMove(learnedMoves, eggMoves[i])) + return TRUE; + } + + return FALSE; +} + +bool32 HasRelearnerTMMoves(struct Pokemon *mon) +{ + if (!P_TM_MOVES_RELEARNER) + return FALSE; + + u32 species = GetMonData(mon, MON_DATA_SPECIES_OR_EGG, 0); + + if (species == SPECIES_EGG) + return FALSE; + + u16 learnedMoves[MAX_MON_MOVES]; + + for (u32 i = 0; i < MAX_MON_MOVES; i++) + learnedMoves[i] = GetMonData(mon, MON_DATA_MOVE1 + i, 0); + + for (u32 i = 0; i < NUM_ALL_MACHINES; i++) + { + enum TMHMItemId item = GetTMHMItemId(i + 1); + u32 move = GetTMHMMoveId(i + 1); + + if (move == MOVE_NONE) + continue; + + if (!P_ENABLE_ALL_TM_MOVES && !CheckBagHasItem(item, 1)) + continue; + + if (!CanLearnTeachableMove(species, move)) + continue; + + if (!DoesMonHaveMove(learnedMoves, move)) + return TRUE; + } + + return FALSE; +} + +bool32 HasRelearnerTutorMoves(struct Pokemon *mon) +{ + if (!FlagGet(P_FLAG_TUTOR_MOVES) && !P_ENABLE_MOVE_RELEARNERS) + return FALSE; + +#if P_TUTOR_MOVES_ARRAY + u32 species = GetMonData(mon, MON_DATA_SPECIES_OR_EGG, 0); + + if (species == SPECIES_EGG) + return FALSE; + + u16 learnedMoves[MAX_MON_MOVES]; + + for (u32 i = 0; i < MAX_MON_MOVES; i++) + learnedMoves[i] = GetMonData(mon, MON_DATA_MOVE1 + i, 0); + + for (u32 i = 0; gTutorMoves[i] != MOVE_UNAVAILABLE; i++) + { + u32 move = gTutorMoves[i]; + + if (!CanLearnTeachableMove(species, move)) + continue; + + if (!DoesMonHaveMove(learnedMoves, move)) + return TRUE; + } +#endif + return FALSE; +} + u8 GetLevelUpMovesBySpecies(u16 species, u16 *moves) { u8 numMoves = 0; @@ -5749,50 +6097,6 @@ u8 GetLevelUpMovesBySpecies(u16 species, u16 *moves) return numMoves; } -u8 GetNumberOfRelearnableMoves(struct Pokemon *mon) -{ - u16 learnedMoves[MAX_MON_MOVES]; - u16 moves[MAX_LEVEL_UP_MOVES]; - u8 numMoves = 0; - u16 species = GetMonData(mon, MON_DATA_SPECIES_OR_EGG, 0); - u8 level = GetMonData(mon, MON_DATA_LEVEL, 0); - const struct LevelUpMove *learnset = GetSpeciesLevelUpLearnset(species); - int i, j, k; - - if (species == SPECIES_EGG) - return 0; - - for (i = 0; i < MAX_MON_MOVES; i++) - learnedMoves[i] = GetMonData(mon, MON_DATA_MOVE1 + i, 0); - - for (i = 0; i < MAX_LEVEL_UP_MOVES; i++) - { - u16 moveLevel; - - if (learnset[i].move == LEVEL_UP_MOVE_END) - break; - - moveLevel = learnset[i].level; - - if (moveLevel <= level) - { - for (j = 0; j < MAX_MON_MOVES && learnedMoves[j] != learnset[i].move; j++) - ; - - if (j == MAX_MON_MOVES) - { - for (k = 0; k < numMoves && moves[k] != learnset[i].move; k++) - ; - - if (k == numMoves) - moves[numMoves++] = learnset[i].move; - } - } - } - - return numMoves; -} - u16 SpeciesToPokedexNum(u16 species) { if (IsNationalPokedexEnabled()) @@ -6090,7 +6394,7 @@ static s32 GetWildMonTableIdInAlteringCave(u16 species) static inline bool32 CanFirstMonBoostHeldItemRarity(void) { - u32 ability; + enum Ability ability; if (GetMonData(&gPlayerParty[0], MON_DATA_SANITY_IS_EGG)) return FALSE; @@ -6630,7 +6934,7 @@ u32 GetFormChangeTargetSpeciesBoxMon(struct BoxPokemon *boxMon, enum FormChanges u32 targetSpecies = species; const struct FormChange *formChanges = GetSpeciesFormChanges(species); u16 heldItem; - u32 ability; + enum Ability ability; if (formChanges != NULL) { @@ -6896,7 +7200,7 @@ bool32 SpeciesHasGenderDifferences(u16 species) return FALSE; } -bool32 TryFormChange(u32 monId, u32 side, enum FormChanges method) +bool32 TryFormChange(u32 monId, enum BattleSide side, enum FormChanges method) { struct Pokemon *party = (side == B_SIDE_PLAYER) ? gPlayerParty : gEnemyParty; @@ -7014,7 +7318,7 @@ void UpdateMonPersonality(struct BoxPokemon *boxMon, u32 personality) bool32 isShiny = GetBoxMonData(boxMon, MON_DATA_IS_SHINY, NULL); u32 hiddenNature = GetBoxMonData(boxMon, MON_DATA_HIDDEN_NATURE, NULL); - u32 teraType = GetBoxMonData(boxMon, MON_DATA_TERA_TYPE, NULL); + enum Type teraType = GetBoxMonData(boxMon, MON_DATA_TERA_TYPE, NULL); old = *boxMon; old0 = &(GetSubstruct(&old, old.personality, SUBSTRUCT_TYPE_0)->type0); @@ -7129,9 +7433,9 @@ void UpdateDaysPassedSinceFormChange(u16 days) } } -u32 CheckDynamicMoveType(struct Pokemon *mon, u32 move, u32 battler, enum MonState state) +enum Type CheckDynamicMoveType(struct Pokemon *mon, u32 move, u32 battler, enum MonState state) { - u32 moveType = GetDynamicMoveType(mon, move, battler, state); + enum Type moveType = GetDynamicMoveType(mon, move, battler, state); if (moveType != TYPE_NONE) return moveType; return GetMoveType(move); @@ -7211,7 +7515,7 @@ bool32 IsSpeciesForeignRegionalForm(u32 species, u32 currentRegion) return FALSE; } -u32 GetTeraTypeFromPersonality(struct Pokemon *mon) +enum Type GetTeraTypeFromPersonality(struct Pokemon *mon) { const u8 *types = gSpeciesInfo[GetMonData(mon, MON_DATA_SPECIES)].types; return (GetMonData(mon, MON_DATA_PERSONALITY) & 0x1) == 0 ? types[0] : types[1]; @@ -7232,7 +7536,7 @@ void SavePlayerPartyMon(u32 index, struct Pokemon *mon) gSaveBlock1Ptr->playerParty[index] = *mon; } -u32 IsSpeciesOfType(u32 species, u32 type) +bool32 IsSpeciesOfType(u32 species, enum Type type) { if (gSpeciesInfo[species].types[0] == type || gSpeciesInfo[species].types[1] == type) diff --git a/src/pokemon_summary_screen.c b/src/pokemon_summary_screen.c index cf2d2e14b4..56d9cd0943 100644 --- a/src/pokemon_summary_screen.c +++ b/src/pokemon_summary_screen.c @@ -44,7 +44,6 @@ #include "tv.h" #include "window.h" #include "constants/battle_move_effects.h" -#include "constants/hold_effects.h" #include "constants/items.h" #include "constants/moves.h" #include "constants/party_menu.h" @@ -164,7 +163,7 @@ static EWRAM_DATA struct PokemonSummaryScreenData u8 sanity; // 0x35 u8 OTName[17]; // 0x36 u32 OTID; // 0x48 - u8 teraType; + enum Type teraType; u8 mintNature; } summary; u16 bgTilemapBuffers[PSS_PAGE_COUNT][2][0x400]; @@ -182,7 +181,7 @@ static EWRAM_DATA struct PokemonSummaryScreenData u8 secondMoveIndex; bool8 lockMovesFlag; // This is used to prevent the player from changing position of moves in a battle or when trading. u8 bgDisplayOrder; // Determines the order page backgrounds are loaded while scrolling between them - u8 relearnableMovesNum; + bool8 hasRelearnableMoves; u8 windowIds[8]; u8 spriteIds[SPRITE_ARR_ID_COUNT]; bool8 handleDeoxys; @@ -552,12 +551,12 @@ static const struct WindowTemplate sSummaryTemplate[] = }, [PSS_LABEL_WINDOW_PROMPT_RELEARN] = { .bg = 0, - .tilemapLeft = 22, + .tilemapLeft = 18, .tilemapTop = 2, - .width = 8, + .width = 11, .height = 2, .paletteNum = 15, - .baseBlock = 387, + .baseBlock = 800, }, [PSS_LABEL_WINDOW_PORTRAIT_DEX_NUMBER] = { .bg = 0, @@ -977,14 +976,7 @@ const struct SpriteTemplate gSpriteTemplate_MoveTypes = .affineAnims = gDummySpriteAffineAnimTable, .callback = SpriteCallbackDummy }; -static const u8 sContestCategoryToOamPaletteNum[CONTEST_CATEGORIES_COUNT] = -{ - [CONTEST_CATEGORY_COOL] = 13, - [CONTEST_CATEGORY_BEAUTY] = 14, - [CONTEST_CATEGORY_CUTE] = 14, - [CONTEST_CATEGORY_SMART] = 15, - [CONTEST_CATEGORY_TOUGH] = 13, -}; + static const struct OamData sOamData_MoveSelector = { .y = 0, @@ -1232,6 +1224,9 @@ void ShowPokemonSummaryScreen(u8 mode, void *mons, u8 monIndex, u8 maxMonIndex, if (gMonSpritesGfxPtr == NULL) CreateMonSpritesGfxManager(MON_SPR_GFX_MANAGER_A, MON_SPR_GFX_MODE_NORMAL); + if (ShouldShowMoveRelearner()) + TryUpdateRelearnType(TRY_SET_UPDATE); + SetMainCallback2(CB2_InitSummaryScreen); } @@ -1544,7 +1539,6 @@ static bool8 ExtractMonDataToSummaryStruct(struct Pokemon *mon) sum->ribbonCount = GetMonData(mon, MON_DATA_RIBBON_COUNT); sum->teraType = GetMonData(mon, MON_DATA_TERA_TYPE); sum->isShiny = GetMonData(mon, MON_DATA_IS_SHINY); - sMonSummaryScreen->relearnableMovesNum = P_SUMMARY_SCREEN_MOVE_RELEARNER ? GetNumberOfRelearnableMoves(mon) : 0; return TRUE; } sMonSummaryScreen->switchCounter++; @@ -1704,11 +1698,11 @@ static void Task_HandleInput(u8 taskId) { ChangeSummaryPokemon(taskId, 1); } - else if ((JOY_NEW(DPAD_LEFT)) || GetLRKeysPressed() == MENU_L_PRESSED) + else if (JOY_NEW(DPAD_LEFT)) { ChangePage(taskId, -1); } - else if ((JOY_NEW(DPAD_RIGHT)) || GetLRKeysPressed() == MENU_R_PRESSED) + else if (JOY_NEW(DPAD_RIGHT)) { ChangePage(taskId, 1); } @@ -1756,7 +1750,7 @@ static void Task_HandleInput(u8 taskId) { sMonSummaryScreen->callback = CB2_InitLearnMove; gSpecialVar_0x8004 = sMonSummaryScreen->curMonIndex; - gOriginSummaryScreenPage = sMonSummaryScreen->currPageIndex; + gRelearnMode = sMonSummaryScreen->currPageIndex; StopPokemonAnimations(); PlaySE(SE_SELECT); BeginCloseSummaryScreen(taskId); @@ -1768,6 +1762,24 @@ static void Task_HandleInput(u8 taskId) PlaySE(SE_SELECT); CloseSummaryScreen(taskId); } + else if (JOY_NEW(R_BUTTON)) // R means increase. Level -> Egg -> TM -> Tutor + { + if (P_SUMMARY_SCREEN_MOVE_RELEARNER && (sMonSummaryScreen->currPageIndex == PSS_PAGE_BATTLE_MOVES || sMonSummaryScreen->currPageIndex == PSS_PAGE_CONTEST_MOVES) && !gMain.inBattle) + { + TryUpdateRelearnType(TRY_INCREMENT); + PlaySE(SE_SELECT); + ShowRelearnPrompt(); + } + } + else if (JOY_NEW(L_BUTTON)) // L means decrease. Level <- Egg <- TM <- Tutor + { + if (P_SUMMARY_SCREEN_MOVE_RELEARNER && (sMonSummaryScreen->currPageIndex == PSS_PAGE_BATTLE_MOVES || sMonSummaryScreen->currPageIndex == PSS_PAGE_CONTEST_MOVES) && !gMain.inBattle) + { + TryUpdateRelearnType(TRY_DECREMENT); + PlaySE(SE_SELECT); + ShowRelearnPrompt(); + } + } } } @@ -1890,6 +1902,115 @@ void ExtractMonSkillEvData(struct Pokemon *mon, struct PokeSummary *sum) sum->speed = GetMonData(mon, MON_DATA_SPEED_EV); } +bool32 HasAnyRelearnableMoves(enum MoveRelearnerStates state) +{ + struct Pokemon *mon = &sMonSummaryScreen->currentMon; + + switch (state) + { + case MOVE_RELEARNER_EGG_MOVES: + return HasRelearnerEggMoves(mon); + case MOVE_RELEARNER_TM_MOVES: + return HasRelearnerTMMoves(mon); + case MOVE_RELEARNER_TUTOR_MOVES: + return HasRelearnerTutorMoves(mon); + case MOVE_RELEARNER_LEVEL_UP_MOVES: + return HasRelearnerLevelUpMoves(mon); + default: + return FALSE; + } +} + +bool32 NoMovesAvailableToRelearn(void) +{ + u32 zeroCounter = 0; + for (enum MoveRelearnerStates state = MOVE_RELEARNER_LEVEL_UP_MOVES; state < MOVE_RELEARNER_COUNT; state++) + { + if (!HasAnyRelearnableMoves(state)) + zeroCounter++; + } + + return zeroCounter == MOVE_RELEARNER_COUNT; +} + +bool32 CheckRelearnerStateFlag(enum MoveRelearnerStates state) +{ + if (P_ENABLE_MOVE_RELEARNERS) + return TRUE; + + switch (state) + { + case MOVE_RELEARNER_LEVEL_UP_MOVES: + return TRUE; + case MOVE_RELEARNER_EGG_MOVES: + return FlagGet(P_FLAG_EGG_MOVES); + case MOVE_RELEARNER_TM_MOVES: + return P_TM_MOVES_RELEARNER; + case MOVE_RELEARNER_TUTOR_MOVES: + return FlagGet(P_FLAG_TUTOR_MOVES); + default: + return FALSE; + } +} + +void TryUpdateRelearnType(enum IncrDecrUpdateValues delta) +{ + bool32 hasRelearnableMoves = FALSE; + u32 zeroCounter = 0; + enum MoveRelearnerStates state = gMoveRelearnerState; + + // just in case everything is off, default to level up moves + if ((!P_ENABLE_MOVE_RELEARNERS + && !P_TM_MOVES_RELEARNER + && !FlagGet(P_FLAG_EGG_MOVES) + && !FlagGet(P_FLAG_TUTOR_MOVES))) + { + sMonSummaryScreen->hasRelearnableMoves = HasAnyRelearnableMoves(MOVE_RELEARNER_LEVEL_UP_MOVES); + return; + } + + do + { + switch (delta) + { + default: + case TRY_SET_UPDATE: + hasRelearnableMoves = HasAnyRelearnableMoves(gMoveRelearnerState); + if (!hasRelearnableMoves) + { + delta = TRY_INCREMENT; + continue; + } + else + { + sMonSummaryScreen->hasRelearnableMoves = hasRelearnableMoves; + return; + } + // should never reach this, but just in case + break; + case TRY_INCREMENT: + state = state >= MOVE_RELEARNER_TUTOR_MOVES ? MOVE_RELEARNER_LEVEL_UP_MOVES : state + 1; + break; + case TRY_DECREMENT: + state = state == MOVE_RELEARNER_LEVEL_UP_MOVES ? MOVE_RELEARNER_TUTOR_MOVES : state - 1; + break; + } + + if (!CheckRelearnerStateFlag(state)) + continue; + + hasRelearnableMoves = HasAnyRelearnableMoves(state); + if (hasRelearnableMoves) + { + gMoveRelearnerState = state; + sMonSummaryScreen->hasRelearnableMoves = hasRelearnableMoves; + return; + } + zeroCounter++; + + } while (zeroCounter <= MOVE_RELEARNER_COUNT && !hasRelearnableMoves); +} + static void ChangeSummaryPokemon(u8 taskId, s8 delta) { s8 monId; @@ -1961,27 +2082,32 @@ static void Task_ChangeSummaryMon(u8 taskId) sMonSummaryScreen->switchCounter = 0; break; case 4: + if (ExtractMonDataToSummaryStruct(&sMonSummaryScreen->currentMon) == FALSE) + return; + if (P_SUMMARY_SCREEN_RENAME && sMonSummaryScreen->currPageIndex == PSS_PAGE_INFO) ShowUtilityPrompt(SUMMARY_MODE_NORMAL); + if (ShouldShowIvEvPrompt() && sMonSummaryScreen->currPageIndex == PSS_PAGE_SKILLS) { sMonSummaryScreen->skillsPageMode = SUMMARY_SKILLS_MODE_STATS; ChangeStatLabel(SUMMARY_SKILLS_MODE_STATS); } - if (ExtractMonDataToSummaryStruct(&sMonSummaryScreen->currentMon) == FALSE) + + if (P_SUMMARY_SCREEN_MOVE_RELEARNER + && (sMonSummaryScreen->currPageIndex == PSS_PAGE_BATTLE_MOVES + || sMonSummaryScreen->currPageIndex == PSS_PAGE_CONTEST_MOVES)) { - return; + gMoveRelearnerState = MOVE_RELEARNER_LEVEL_UP_MOVES; + TryUpdateRelearnType(TRY_SET_UPDATE); + if (ShouldShowMoveRelearner()) + ShowRelearnPrompt(); + else + ClearWindowTilemap(PSS_LABEL_WINDOW_PROMPT_RELEARN); } else { - if (P_SUMMARY_SCREEN_MOVE_RELEARNER - && (sMonSummaryScreen->currPageIndex == PSS_PAGE_BATTLE_MOVES || sMonSummaryScreen->currPageIndex == PSS_PAGE_CONTEST_MOVES)) - { - if (ShouldShowMoveRelearner()) - PutWindowTilemap(PSS_LABEL_WINDOW_PROMPT_RELEARN); - else - ClearWindowTilemap(PSS_LABEL_WINDOW_PROMPT_RELEARN); - } + ClearWindowTilemap(PSS_LABEL_WINDOW_PROMPT_RELEARN); } break; case 5: @@ -2097,6 +2223,7 @@ static void ChangePage(u8 taskId, s8 delta) { struct PokeSummary *summary = &sMonSummaryScreen->summary; s16 *data = gTasks[taskId].data; + u32 currPageIndex; if (summary->isEgg) return; @@ -2107,17 +2234,17 @@ static void ChangePage(u8 taskId, s8 delta) PlaySE(SE_SELECT); ClearPageWindowTilemaps(sMonSummaryScreen->currPageIndex); - sMonSummaryScreen->currPageIndex += delta; + currPageIndex = sMonSummaryScreen->currPageIndex += delta; data[0] = 0; if (delta == 1) SetTaskFuncWithFollowupFunc(taskId, PssScrollRight, gTasks[taskId].func); else SetTaskFuncWithFollowupFunc(taskId, PssScrollLeft, gTasks[taskId].func); - CreateTextPrinterTask(sMonSummaryScreen->currPageIndex); + CreateTextPrinterTask(currPageIndex); HidePageSpecificSprites(); - if (sMonSummaryScreen->currPageIndex == PSS_PAGE_SKILLS - || (sMonSummaryScreen->currPageIndex + delta) == PSS_PAGE_SKILLS) + if (currPageIndex == PSS_PAGE_SKILLS + || (currPageIndex + delta) == PSS_PAGE_SKILLS) { struct Pokemon *mon = &sMonSummaryScreen->currentMon; @@ -2133,6 +2260,19 @@ static void ChangePage(u8 taskId, s8 delta) { ShowUtilityPrompt(SUMMARY_MODE_NORMAL); } + + // acts like a quick reset + if (currPageIndex == PSS_PAGE_SKILLS) + { + gMoveRelearnerState = MOVE_RELEARNER_LEVEL_UP_MOVES; + TryUpdateRelearnType(TRY_SET_UPDATE); + } + + // to prevent nothing showing + if (currPageIndex >= PSS_PAGE_BATTLE_MOVES && !sMonSummaryScreen->hasRelearnableMoves) + TryUpdateRelearnType(TRY_SET_UPDATE); + else + ClearWindowTilemap(PSS_LABEL_WINDOW_PROMPT_RELEARN); } static void PssScrollRight(u8 taskId) // Scroll right @@ -2176,6 +2316,7 @@ static void PssScrollRightEnd(u8 taskId) // display right SetTypeIcons(); TryDrawExperienceProgressBar(); SwitchTaskToFollowupFunc(taskId); + ShowRelearnPrompt(); } static void PssScrollLeft(u8 taskId) // Scroll left @@ -2228,6 +2369,7 @@ static void PssScrollLeftEnd(u8 taskId) // display left SetTypeIcons(); TryDrawExperienceProgressBar(); SwitchTaskToFollowupFunc(taskId); + ShowRelearnPrompt(); } static void TryDrawExperienceProgressBar(void) @@ -3239,7 +3381,13 @@ static void PrintPageNamesAndStats(void) PrintTextOnWindow(PSS_LABEL_WINDOW_MOVES_POWER_ACC, gText_Accuracy2, 0, 17, 0, 1); PrintTextOnWindow(PSS_LABEL_WINDOW_MOVES_APPEAL_JAM, gText_Appeal, 0, 1, 0, 1); PrintTextOnWindow(PSS_LABEL_WINDOW_MOVES_APPEAL_JAM, gText_Jam, 0, 17, 0, 1); - PrintTextOnWindowWithFont(PSS_LABEL_WINDOW_PROMPT_RELEARN, gText_Relearn, 13, 4, 0, 0, FONT_SMALL); + + if (sMonSummaryScreen->currPageIndex == PSS_PAGE_BATTLE_MOVES + || sMonSummaryScreen->currPageIndex == PSS_PAGE_CONTEST_MOVES) + { + TryUpdateRelearnType(TRY_SET_UPDATE); + ShowRelearnPrompt(); + } } static void PutPageWindowTilemaps(u8 page) @@ -3315,6 +3463,7 @@ static void ClearPageWindowTilemaps(u8 page) if (InBattleFactory() == TRUE || InSlateportBattleTent() == TRUE) ClearWindowTilemap(PSS_LABEL_WINDOW_POKEMON_INFO_RENTAL); ClearWindowTilemap(PSS_LABEL_WINDOW_POKEMON_INFO_TYPE); + ClearWindowTilemap(PSS_LABEL_WINDOW_PROMPT_RELEARN); break; case PSS_PAGE_SKILLS: ClearWindowTilemap(PSS_LABEL_WINDOW_POKEMON_SKILLS_STATS_LEFT); @@ -3322,6 +3471,7 @@ static void ClearPageWindowTilemaps(u8 page) ClearWindowTilemap(PSS_LABEL_WINDOW_POKEMON_SKILLS_EXP); if (ShouldShowIvEvPrompt()) ClearPageWindowTilemaps(PSS_LABEL_WINDOW_PROMPT_UTILITY); + ClearWindowTilemap(PSS_LABEL_WINDOW_PROMPT_RELEARN); break; case PSS_PAGE_BATTLE_MOVES: if (sMonSummaryScreen->mode == SUMMARY_MODE_SELECT_MOVE) @@ -3332,11 +3482,8 @@ static void ClearPageWindowTilemaps(u8 page) gSprites[sMonSummaryScreen->categoryIconSpriteId].invisible = TRUE; } } - else - { - if (ShouldShowMoveRelearner()) - ClearWindowTilemap(PSS_LABEL_WINDOW_PROMPT_RELEARN); - } + + ClearWindowTilemap(PSS_LABEL_WINDOW_PROMPT_RELEARN); break; case PSS_PAGE_CONTEST_MOVES: if (sMonSummaryScreen->mode == SUMMARY_MODE_SELECT_MOVE) @@ -3344,11 +3491,8 @@ static void ClearPageWindowTilemaps(u8 page) if (sMonSummaryScreen->newMove != MOVE_NONE || sMonSummaryScreen->firstMoveIndex != MAX_MON_MOVES) ClearWindowTilemap(PSS_LABEL_WINDOW_MOVES_APPEAL_JAM); } - else - { - if (ShouldShowMoveRelearner()) - ClearWindowTilemap(PSS_LABEL_WINDOW_PROMPT_RELEARN); - } + + ClearWindowTilemap(PSS_LABEL_WINDOW_PROMPT_RELEARN); break; } @@ -3474,13 +3618,13 @@ static void PrintMonOTID(void) static void PrintMonAbilityName(void) { - u16 ability = GetAbilityBySpecies(sMonSummaryScreen->summary.species, sMonSummaryScreen->summary.abilityNum); + enum Ability ability = GetAbilityBySpecies(sMonSummaryScreen->summary.species, sMonSummaryScreen->summary.abilityNum); PrintTextOnWindow(AddWindowFromTemplateList(sPageInfoTemplate, PSS_DATA_WINDOW_INFO_ABILITY), gAbilitiesInfo[ability].name, 0, 1, 0, 1); } static void PrintMonAbilityDescription(void) { - u16 ability = GetAbilityBySpecies(sMonSummaryScreen->summary.species, sMonSummaryScreen->summary.abilityNum); + enum Ability ability = GetAbilityBySpecies(sMonSummaryScreen->summary.species, sMonSummaryScreen->summary.abilityNum); PrintTextOnWindow(AddWindowFromTemplateList(sPageInfoTemplate, PSS_DATA_WINDOW_INFO_ABILITY), gAbilitiesInfo[ability].description, 0, 17, 0, 0); } @@ -3766,7 +3910,7 @@ static void PrintRibbonCount(void) PrintTextOnWindow(AddWindowFromTemplateList(sPageSkillsTemplate, PSS_DATA_WINDOW_SKILLS_RIBBON_COUNT), text, x, 1, 0, 0); } -static void BufferStat(u8 *dst, u8 statIndex, u32 stat, u32 strId, u32 n) +static void BufferStat(u8 *dst, enum Stat statIndex, u32 stat, u32 strId, u32 n) { static const u8 sTextNatureDown[] = _("{COLOR}{08}"); static const u8 sTextNatureUp[] = _("{COLOR}{05}"); @@ -4109,7 +4253,7 @@ static void PrintContestMoveDescription(u8 moveSlot) if (move != MOVE_NONE) { u8 windowId = AddWindowFromTemplateList(sPageMovesTemplate, PSS_DATA_WINDOW_MOVE_DESCRIPTION); - PrintTextOnWindow(windowId, gContestEffectDescriptionPointers[GetMoveContestEffect(move)], 6, 1, 0, 0); + PrintTextOnWindow(windowId, gContestEffects[GetMoveContestEffect(move)].description, 6, 1, 0, 0); } } @@ -4128,7 +4272,7 @@ static void PrintMoveDetails(u16 move) } else { - PrintTextOnWindow(windowId, gContestEffectDescriptionPointers[GetMoveContestEffect(move)], 6, 1, 0, 0); + PrintTextOnWindow(windowId, gContestEffects[GetMoveContestEffect(move)].description, 6, 1, 0, 0); } PutWindowTilemap(windowId); } @@ -4261,14 +4405,14 @@ static void CreateMoveTypeIcons(void) } } -void SetTypeSpritePosAndPal(u8 typeId, u8 x, u8 y, u8 spriteArrayId) +void SetTypeSpritePosAndPal(enum Type typeId, u8 x, u8 y, u8 spriteArrayId) { struct Sprite *sprite = &gSprites[sMonSummaryScreen->spriteIds[spriteArrayId]]; StartSpriteAnim(sprite, typeId); if (typeId < NUMBER_OF_MON_TYPES) sprite->oam.paletteNum = gTypesInfo[typeId].palette; else - sprite->oam.paletteNum = sContestCategoryToOamPaletteNum[typeId - NUMBER_OF_MON_TYPES]; + sprite->oam.paletteNum = gContestCategoryInfo[typeId - NUMBER_OF_MON_TYPES].palette; sprite->x = x + 16; sprite->y = y + 8; SetSpriteInvisibility(spriteArrayId, FALSE); @@ -4306,7 +4450,7 @@ static void SetMoveTypeIcons(void) u32 i; struct PokeSummary *summary = &sMonSummaryScreen->summary; struct Pokemon *mon = &sMonSummaryScreen->currentMon; - u32 type; + enum Type type; for (i = 0; i < MAX_MON_MOVES; i++) { @@ -4343,7 +4487,7 @@ static void SetContestMoveTypeIcons(void) static void SetNewMoveTypeIcon(void) { - u32 type = GetMoveType(sMonSummaryScreen->newMove); + enum Type type = GetMoveType(sMonSummaryScreen->newMove); struct Pokemon *mon = &sMonSummaryScreen->currentMon; if (P_SHOW_DYNAMIC_TYPES) @@ -4660,9 +4804,10 @@ static inline bool32 ShouldShowMoveRelearner(void) && !sMonSummaryScreen->isBoxMon && sMonSummaryScreen->mode != SUMMARY_MODE_BOX && sMonSummaryScreen->mode != SUMMARY_MODE_BOX_CURSOR - && sMonSummaryScreen->relearnableMovesNum > 0 + && sMonSummaryScreen->hasRelearnableMoves && !InBattleFactory() - && !InSlateportBattleTent()); + && !InSlateportBattleTent() + && !NoMovesAvailableToRelearn()); } static inline bool32 ShouldShowRename(void) @@ -4683,7 +4828,7 @@ static inline bool32 ShouldShowIvEvPrompt(void) if (P_SUMMARY_SCREEN_IV_EV_BOX_ONLY) { return (P_SUMMARY_SCREEN_IV_EV_INFO || FlagGet(P_FLAG_SUMMARY_SCREEN_IV_EV_INFO)) - && (sMonSummaryScreen->mode == SUMMARY_MODE_BOX|| sMonSummaryScreen->mode == SUMMARY_MODE_BOX_CURSOR); + && (sMonSummaryScreen->mode == SUMMARY_MODE_BOX || sMonSummaryScreen->mode == SUMMARY_MODE_BOX_CURSOR); } else if (!P_SUMMARY_SCREEN_IV_EV_BOX_ONLY) { @@ -4758,6 +4903,49 @@ static inline void ShowUtilityPrompt(s16 mode) PrintTextOnWindow(PSS_LABEL_WINDOW_PROMPT_UTILITY, promptText, stringXPos, 1, 0, 0); } +void ShowRelearnPrompt(void) +{ + u32 currPage = sMonSummaryScreen->currPageIndex; + + if (!ShouldShowMoveRelearner() || !(currPage >= PSS_PAGE_BATTLE_MOVES)) + { + ClearWindowTilemap(PSS_LABEL_WINDOW_PROMPT_RELEARN); + return; + } + + if (!HasAnyRelearnableMoves(gMoveRelearnerState)) + return; + + const u8* relearnText; + + int relearnTextXPos; + + switch (gMoveRelearnerState) + { + case MOVE_RELEARNER_LEVEL_UP_MOVES: + relearnText = gText_Relearn_LevelUp; + break; + case MOVE_RELEARNER_EGG_MOVES: + relearnText = gText_Relearn_Egg; + break; + case MOVE_RELEARNER_TM_MOVES: + relearnText = gText_Relearn_TM; + break; + case MOVE_RELEARNER_TUTOR_MOVES: + relearnText = gText_Relearn_Tutor; + break; + default: + relearnText = gText_Relearn; + break; + } + + relearnTextXPos = GetStringRightAlignXOffset(FONT_NORMAL, relearnText, 0); + + FillWindowPixelBuffer(PSS_LABEL_WINDOW_PROMPT_RELEARN, PIXEL_FILL(0)); + PutWindowTilemap(PSS_LABEL_WINDOW_PROMPT_RELEARN); + PrintTextOnWindowWithFont(PSS_LABEL_WINDOW_PROMPT_RELEARN, relearnText, relearnTextXPos, 4, 0, 0, FONT_SMALL); +} + static void CB2_ReturnToSummaryScreenFromNamingScreen(void) { SetMonData(&gPlayerParty[gSpecialVar_0x8004], MON_DATA_NICKNAME, gStringVar2); diff --git a/src/recorded_battle.c b/src/recorded_battle.c index 500a83e888..5b61a8b4dd 100644 --- a/src/recorded_battle.c +++ b/src/recorded_battle.c @@ -49,7 +49,7 @@ EWRAM_DATA static u8 sFrontierPassFlag = 0; EWRAM_DATA static u8 sBattleScene = 0; EWRAM_DATA static u8 sTextSpeed = 0; EWRAM_DATA static u32 sBattleFlags = 0; -EWRAM_DATA static u64 sAI_Scripts = 0; +EWRAM_DATA static u64 sAI_Scripts[MAX_BATTLERS_COUNT] = {0}; EWRAM_DATA static struct Pokemon sSavedPlayerParty[PARTY_SIZE] = {0}; EWRAM_DATA static struct Pokemon sSavedOpponentParty[PARTY_SIZE] = {0}; EWRAM_DATA static u16 sPlayerMonMoves[MAX_BATTLERS_COUNT / 2][MAX_MON_MOVES] = {0}; @@ -87,7 +87,7 @@ void RecordedBattle_Init(u8 mode) for (j = 0; j < BATTLER_RECORD_SIZE; j++) sBattleRecords[i][j] = 0xFF; sBattleFlags = gBattleTypeFlags; - sAI_Scripts = gAiThinkingStruct->aiFlags[B_POSITION_OPPONENT_LEFT]; + sAI_Scripts[i] = gAiThinkingStruct->aiFlags[i]; } } } @@ -312,6 +312,7 @@ bool32 MoveRecordedBattleToSaveData(void) battleSave->playersLanguage[i] = sPlayers[i].language; battleSave->playersBattlers[i] = sPlayers[i].battler; battleSave->playersTrainerId[i] = sPlayers[i].trainerId; + battleSave->AI_scripts[i] = sAI_Scripts[i]; } battleSave->rngSeed = gRecordedBattleRngSeed; @@ -358,7 +359,6 @@ bool32 MoveRecordedBattleToSaveData(void) battleSave->frontierBrainSymbol = sFrontierBrainSymbol; battleSave->battleScene = gSaveBlock2Ptr->optionsBattleSceneOff; battleSave->textSpeed = gSaveBlock2Ptr->optionsTextSpeed; - battleSave->AI_scripts = sAI_Scripts; if (TRAINER_BATTLE_PARAM.opponentA >= TRAINER_RECORD_MIXING_FRIEND && TRAINER_BATTLE_PARAM.opponentA < TRAINER_RECORD_MIXING_APPRENTICE) { @@ -523,6 +523,7 @@ void SetVariablesForRecordedBattle(struct RecordedBattleSave *src) gLinkPlayers[i].language = src->playersLanguage[i]; gLinkPlayers[i].id = src->playersBattlers[i]; gLinkPlayers[i].trainerId = src->playersTrainerId[i]; + sAI_Scripts[i] = src->AI_scripts[i]; if (var) ConvertInternationalString(gLinkPlayers[i].name, gLinkPlayers[i].language); @@ -539,7 +540,6 @@ void SetVariablesForRecordedBattle(struct RecordedBattleSave *src) sFrontierBrainSymbol = src->frontierBrainSymbol; sBattleScene = src->battleScene; sTextSpeed = src->textSpeed; - sAI_Scripts = src->AI_scripts; for (i = 0; i < PLAYER_NAME_LENGTH + 1; i++) sRecordMixFriendName[i] = src->recordMixFriendName[i]; @@ -779,16 +779,16 @@ void RecordedBattle_CheckMovesetChanges(u8 mode) SetMonData(mon, MON_DATA_PP_BONUSES, &ppBonusSet); } - gChosenMoveByBattler[battler] = gBattleMons[battler].moves[gBattleStruct->chosenMovePositions[battler]]; + gChosenMoveByBattler[battler] = GetChosenMoveFromPosition(battler); } } } } } -u64 GetAiScriptsInRecordedBattle(void) +u64 GetAiScriptsInRecordedBattle(u32 battler) { - return sAI_Scripts; + return sAI_Scripts[battler]; } // Used to determine when the player is allowed to press B to end a recorded battle's playback diff --git a/src/rom_header_rhh.c b/src/rom_header_rhh.c index 9a97948e8a..3a88a2c413 100644 --- a/src/rom_header_rhh.c +++ b/src/rom_header_rhh.c @@ -21,7 +21,7 @@ struct RHHRomHeader /*0x0A*/ u16 movesCount; /*0x0C*/ u16 numSpecies; /*0x0E*/ u16 abilitiesCount; - /*0x10*/ const struct Ability *abilities; + /*0x10*/ const struct AbilityInfo *abilities; /*0x14*/ u16 itemsCount; /*0x16*/ u8 itemNameLength; /*0x17*/ u8 padding; diff --git a/src/rtc.c b/src/rtc.c index fb2518f210..555c86b87e 100644 --- a/src/rtc.c +++ b/src/rtc.c @@ -334,7 +334,8 @@ enum TimeOfDay GetTimeOfDay(void) enum TimeOfDay GetTimeOfDayForDex(void) { - return OW_TIME_OF_DAY_ENCOUNTERS ? GetTimeOfDay() : TIME_OF_DAY_DEFAULT; + enum TimeOfDay timeOfDay = OW_TIME_OF_DAY_ENCOUNTERS ? GetTimeOfDay() : TIME_OF_DAY_DEFAULT; + return GenConfigTimeOfDay(timeOfDay); } void RtcInitLocalTimeOffset(s32 hour, s32 minute) @@ -456,12 +457,24 @@ enum Weekday GetDayOfWeek(void) return dateTime.dayOfWeek; } +enum TimeOfDay GenConfigTimeOfDay(enum TimeOfDay timeOfDay) +{ + if ((((timeOfDay == TIME_MORNING || timeOfDay == TIME_EVENING) && OW_TIMES_OF_DAY == GEN_3) + || (timeOfDay == TIME_EVENING && OW_TIMES_OF_DAY == GEN_4)) + && timeOfDay < TIME_LAST) + timeOfDay++; + + return timeOfDay; +} + enum TimeOfDay TryIncrementTimeOfDay(enum TimeOfDay timeOfDay) { - return timeOfDay == TIME_NIGHT ? TIME_MORNING : timeOfDay + 1; + timeOfDay = timeOfDay == TIME_LAST ? TIME_FIRST : timeOfDay + 1; + return GenConfigTimeOfDay(timeOfDay); } enum TimeOfDay TryDecrementTimeOfDay(enum TimeOfDay timeOfDay) { - return timeOfDay == TIME_MORNING ? TIME_NIGHT : timeOfDay - 1; + timeOfDay = timeOfDay == TIME_FIRST ? TIME_LAST : timeOfDay - 1; + return GenConfigTimeOfDay(timeOfDay); } diff --git a/src/save.c b/src/save.c index 5d17cea210..ff7cef5989 100644 --- a/src/save.c +++ b/src/save.c @@ -855,7 +855,7 @@ bool8 WriteSaveBlock2(void) // It returns TRUE when finished. bool8 WriteSaveBlock1Sector(void) { - u8 finished = FALSE; + bool32 finished = FALSE; u16 sectorId = ++gIncrementalSectorId; // Because WriteSaveBlock2 will have been called prior, this will be SECTOR_ID_SAVEBLOCK1_START if (sectorId <= SECTOR_ID_SAVEBLOCK1_END) { diff --git a/src/scrcmd.c b/src/scrcmd.c index 54edd76c61..cf1fb1ab67 100644 --- a/src/scrcmd.c +++ b/src/scrcmd.c @@ -34,6 +34,7 @@ #include "menu.h" #include "money.h" #include "move.h" +#include "move_relearner.h" #include "mystery_event_script.h" #include "palette.h" #include "party_menu.h" @@ -3085,8 +3086,8 @@ bool8 ScrCmd_getobjectxy(struct ScriptContext *ctx) bool8 ScrCmd_checkobjectat(struct ScriptContext *ctx) { - u32 x = VarGet(ScriptReadHalfword(ctx)) + 7; - u32 y = VarGet(ScriptReadHalfword(ctx)) + 7; + u32 x = VarGet(ScriptReadHalfword(ctx)) + MAP_OFFSET; + u32 y = VarGet(ScriptReadHalfword(ctx)) + MAP_OFFSET; u32 varId = ScriptReadHalfword(ctx); Script_RequestEffects(SCREFF_V1); @@ -3255,3 +3256,38 @@ void Script_EndTrainerCanSeeIf(struct ScriptContext *ctx) if (ctx->breakOnTrainerBattle && sScriptConditionTable[condition][ctx->comparisonResult] == 1) StopScript(ctx); } + +bool8 ScrCmd_setmoverelearnerstate(struct ScriptContext *ctx) +{ + enum MoveRelearnerStates state = VarGet(ScriptReadHalfword(ctx)); + + Script_RequestEffects(SCREFF_V1); + + gMoveRelearnerState = state; + return FALSE; +} + +bool8 ScrCmd_getmoverelearnerstate(struct ScriptContext *ctx) +{ + u32 varId = ScriptReadHalfword(ctx); + + Script_RequestEffects(SCREFF_V1); + Script_RequestWriteVar(varId); + + u16 *varPointer = GetVarPointer(varId); + *varPointer = gMoveRelearnerState; + return FALSE; +} + +bool8 ScrCmd_istmrelearneractive(struct ScriptContext *ctx) +{ + const u8 *ptr = (const u8 *)ScriptReadWord(ctx); + + Script_RequestEffects(SCREFF_V1); + + if ((P_TM_MOVES_RELEARNER || P_ENABLE_MOVE_RELEARNERS) + && (P_ENABLE_ALL_TM_MOVES || IsBagPocketNonEmpty(POCKET_TM_HM))) + ScriptCall(ctx, ptr); + + return FALSE; +} diff --git a/src/script_pokemon_util.c b/src/script_pokemon_util.c index d4fba87859..ae503d1016 100644 --- a/src/script_pokemon_util.c +++ b/src/script_pokemon_util.c @@ -319,7 +319,7 @@ void CheckTeraType(struct ScriptContext *ctx) void SetTeraType(struct ScriptContext *ctx) { - u32 type = ScriptReadByte(ctx); + enum Type type = ScriptReadByte(ctx); u32 partyIndex = VarGet(ScriptReadHalfword(ctx)); Script_RequestEffects(SCREFF_V1 | SCREFF_SAVE); @@ -332,7 +332,7 @@ void SetTeraType(struct ScriptContext *ctx) * if side/slot are assigned, it will create the mon at the assigned party location * if slot == PARTY_SIZE, it will give the mon to first available party or storage slot */ -static u32 ScriptGiveMonParameterized(u8 side, u8 slot, u16 species, u8 level, u16 item, enum PokeBall ball, u8 nature, u8 abilityNum, u8 gender, u8 *evs, u8 *ivs, u16 *moves, enum ShinyMode shinyMode, bool8 gmaxFactor, u8 teraType, u8 dmaxLevel) +static u32 ScriptGiveMonParameterized(u8 side, u8 slot, u16 species, u8 level, u16 item, enum PokeBall ball, u8 nature, u8 abilityNum, u8 gender, u8 *evs, u8 *ivs, u16 *moves, enum ShinyMode shinyMode, bool8 gmaxFactor, enum Type teraType, u8 dmaxLevel) { enum NationalDexOrder nationalDexNum; int sentToPc; @@ -518,8 +518,8 @@ void ScrCmd_createmon(struct ScriptContext *ctx) // Perfect IV calculation u32 i; - u8 availableIVs[NUM_STATS]; - u8 selectedIvs[NUM_STATS]; + enum Stat availableIVs[NUM_STATS]; + enum Stat selectedIvs[NUM_STATS]; if (gSpeciesInfo[species].perfectIVCount != 0) { // Initialize a list of IV indices. @@ -543,6 +543,7 @@ void ScrCmd_createmon(struct ScriptContext *ctx) case STAT_SPEED: speedIv = MAX_PER_STAT_IVS; break; case STAT_SPATK: spAtkIv = MAX_PER_STAT_IVS; break; case STAT_SPDEF: spDefIv = MAX_PER_STAT_IVS; break; + default: break; } } } @@ -558,7 +559,7 @@ void ScrCmd_createmon(struct ScriptContext *ctx) u16 move4 = PARSE_FLAG(20, MOVE_NONE); enum ShinyMode shinyMode = PARSE_FLAG(21, SHINY_MODE_RANDOM); bool8 gmaxFactor = PARSE_FLAG(22, FALSE); - u8 teraType = PARSE_FLAG(23, NUMBER_OF_MON_TYPES); + enum Type teraType = PARSE_FLAG(23, NUMBER_OF_MON_TYPES); u8 dmaxLevel = PARSE_FLAG(24, 0); u8 evs[NUM_STATS] = {hpEv, atkEv, defEv, speedEv, spAtkEv, spDefEv}; diff --git a/src/start_menu.c b/src/start_menu.c index b51d0592d8..073cd88481 100644 --- a/src/start_menu.c +++ b/src/start_menu.c @@ -957,7 +957,7 @@ static void ShowSaveMessage(const u8 *message, u8 (*saveCallback)(void)) { StringExpandPlaceholders(gStringVar4, message); LoadMessageBoxAndFrameGfx(0, TRUE); - AddTextPrinterForMessage_2(TRUE); + AddTextPrinterForMessage(TRUE); sSavingComplete = TRUE; sSaveDialogCallback = saveCallback; } diff --git a/src/string_util.c b/src/string_util.c index fd4a0861ee..fe8b6fa592 100644 --- a/src/string_util.c +++ b/src/string_util.c @@ -706,6 +706,7 @@ u8 GetExtCtrlCodeLength(u8 code) [EXT_CTRL_CODE_ENG] = 1, [EXT_CTRL_CODE_PAUSE_MUSIC] = 1, [EXT_CTRL_CODE_RESUME_MUSIC] = 1, + [EXT_CTRL_CODE_SPEAKER] = 1, }; u8 length = 0; diff --git a/src/strings.c b/src/strings.c index 41b128d1da..bb3c656d3f 100644 --- a/src/strings.c +++ b/src/strings.c @@ -972,6 +972,9 @@ ALIGNED(4) const u8 gText_FrontierFacilityRoomsCleared[] = _("通过房间:{ST ALIGNED(4) const u8 gText_FrontierFacilityKOsStreak[] = _("连续击败:{STR_VAR_2}"); ALIGNED(4) const u8 gText_FrontierFacilityFloorsCleared[] = _("通过楼层:{STR_VAR_2}"); ALIGNED(4) const u8 gText_123Dot[][3] = {_("1."), _("2."), _("3.")}; +const u8 gText_FrontierFacilityTotalCaughtSpeciesBanned[] = _("和{STR_VAR_2}种\n您捕捉的宝可梦无法参加"); +const u8 gText_FrontierFacilityIncluding[] = _("!\p其中包括"); +const u8 gText_FrontierFacilityAreInelegible[] = _("无法参加"); const u8 gText_SavingDontTurnOff2[] = _("正在写入记录……\n请勿切断电源。"); const u8 gText_BlenderMaxSpeedRecord[] = _("树果混合器\n最快纪录!"); @@ -984,28 +987,6 @@ const u8 gText_CommErrorEllipsis[] = _("发生连接错误……"); const u8 gText_MoveCloserToLinkPartner[] = _("请靠近你的联机朋友,\n避免朋友之间的障碍物。"); const u8 gText_ABtnRegistrationCounter[] = _("A键:登记柜台"); const u8 gText_ABtnTitleScreen[] = _("A键:标题画面"); -const u8 gText_Option[] = _("游戏设定"); -const u8 gText_TextSpeed[] = _("文字速度"); -const u8 gText_BattleScene[] = _("战斗动画"); -const u8 gText_BattleStyle[] = _("对战方式"); -const u8 gText_Sound[] = _("声音"); -const u8 gText_Frame[] = _("边框类型"); -const u8 gText_OptionMenuCancel[] = _("取消"); -const u8 gText_ButtonMode[] = _("按键模式"); -const u8 gText_TextSpeedSlow[] = _("{COLOR GREEN}{SHADOW LIGHT_GREEN}慢"); -const u8 gText_TextSpeedMid[] = _("{COLOR GREEN}{SHADOW LIGHT_GREEN}中"); -const u8 gText_TextSpeedFast[] = _("{COLOR GREEN}{SHADOW LIGHT_GREEN}快"); -const u8 gText_BattleSceneOn[] = _("{COLOR GREEN}{SHADOW LIGHT_GREEN}开"); -const u8 gText_BattleSceneOff[] = _("{COLOR GREEN}{SHADOW LIGHT_GREEN}关"); -const u8 gText_BattleStyleShift[] = _("{COLOR GREEN}{SHADOW LIGHT_GREEN}接力制"); -const u8 gText_BattleStyleSet[] = _("{COLOR GREEN}{SHADOW LIGHT_GREEN}淘汰制"); -const u8 gText_SoundMono[] = _("{COLOR GREEN}{SHADOW LIGHT_GREEN}单声道"); -const u8 gText_SoundStereo[] = _("{COLOR GREEN}{SHADOW LIGHT_GREEN}立体声"); -const u8 gText_FrameType[] = _("{COLOR GREEN}{SHADOW LIGHT_GREEN}类型"); -const u8 gText_FrameTypeNumber[] = _("{COLOR GREEN}{SHADOW LIGHT_GREEN}"); -const u8 gText_ButtonTypeNormal[] = _("{COLOR GREEN}{SHADOW LIGHT_GREEN}一般"); -const u8 gText_ButtonTypeLR[] = _("{COLOR GREEN}{SHADOW LIGHT_GREEN}LR"); -const u8 gText_ButtonTypeLEqualsA[] = _("{COLOR GREEN}{SHADOW LIGHT_GREEN}L同A"); const u8 gText_NumPlayerLink[] = _("{STR_VAR_1}P连接"); const u8 gText_BronzeCard[] = _("青铜"); const u8 gText_CopperCard[] = _("紫铜"); @@ -1237,7 +1218,7 @@ const u8 gText_TrainerHill1F[] = _("1F"); const u8 gText_TrainerHill2F[] = _("2F"); const u8 gText_TrainerHill3F[] = _("3F"); const u8 gText_TrainerHill4F[] = _("4F"); -const u8 gText_TeachWhichMoveToPkmn[] = _("要让{STR_VAR_1}学习哪个招式呢?"); +const u8 gText_TeachWhichMoveToPkmn[] = _("要让{STR_VAR_1}学习哪个{STR_VAR_3}呢?"); const u8 gText_MoveRelearnerTeachMoveConfirm[] = _("要学习{STR_VAR_2}吗?"); const u8 gText_MoveRelearnerPkmnLearnedMove[] = _("{STR_VAR_1}学会了\n{STR_VAR_2}!"); const u8 gText_MoveRelearnerPkmnTryingToLearnMove[] = _("{STR_VAR_1}想要学习\n{STR_VAR_2}……\p为了学习{STR_VAR_2},\n要忘记其他的招式吗?"); @@ -1298,7 +1279,11 @@ const u8 gText_BasePointsResetToZero[] = _("{STR_VAR_1}的\n基础点数消失 const u8 gText_AM[] = _("AM"); const u8 gText_PM[] = _("PM"); const u8 gText_Relearn[] = _("{START_BUTTON} 回忆"); // future note: don't decap this, because it mimics the summary screen BG graphics which will not get decapped +const u8 gText_Relearn_LevelUp[] = _("{START_BUTTON}回忆升级招式"); +const u8 gText_Relearn_Egg[] = _("{START_BUTTON}回忆蛋招式"); +const u8 gText_Relearn_TM[] = _("{START_BUTTON}回忆学习器招式"); +const u8 gText_Relearn_Tutor[] = _("{START_BUTTON}回忆教授招式"); const u8 gText_Rename[] = _("更改昵称"); const u8 gText_CannotSendMonToBoxHM[] = _("无法将那只宝可梦送回盒子,\n因为它学会了秘传招式。{PAUSE_UNTIL_PRESS}"); const u8 gText_CannotSendMonToBoxActive[] = _("无法将正在战斗的宝可梦\n送回盒子。{PAUSE_UNTIL_PRESS}"); -const u8 gText_CannotSendMonToBoxPartner[] = _("无法将其他人的宝可梦\n送回盒子。{PAUSE_UNTIL_PRESS}"); \ No newline at end of file +const u8 gText_CannotSendMonToBoxPartner[] = _("无法将其他人的宝可梦\n送回盒子。{PAUSE_UNTIL_PRESS}"); diff --git a/src/text.c b/src/text.c index e5169fb33d..25b3082ab6 100644 --- a/src/text.c +++ b/src/text.c @@ -1,18 +1,25 @@ #include "global.h" #include "battle.h" -#include "main.h" +#include "blit.h" +#include "dynamic_placeholder_text_util.h" +#include "event_data.h" +#include "field_name_box.h" +#include "fonts.h" #include "m4a.h" +#include "main.h" +#include "menu.h" #include "palette.h" #include "sound.h" -#include "constants/songs.h" #include "string_util.h" -#include "window.h" #include "text.h" #include "blit.h" #include "menu.h" #include "dynamic_placeholder_text_util.h" #include "fonts.h" #include "chinese_text.h" +#include "window.h" +#include "constants/songs.h" +#include "constants/speaker_names.h" static u16 RenderText(struct TextPrinter *); static u32 RenderFont(struct TextPrinter *); @@ -86,11 +93,6 @@ static const u8 sDarkDownArrowTiles[] = INCBIN_U8("graphics/fonts/down_arrow_alt static const u8 sUnusedFRLGBlankedDownArrow[] = INCBIN_U8("graphics/fonts/unused_frlg_blanked_down_arrow.4bpp"); static const u8 sUnusedFRLGDownArrow[] = INCBIN_U8("graphics/fonts/unused_frlg_down_arrow.4bpp"); static const u8 sDownArrowYCoords[] = { 0, 1, 2, 1 }; -static const u8 sWindowVerticalScrollSpeeds[] = { - [OPTIONS_TEXT_SPEED_SLOW] = 1, - [OPTIONS_TEXT_SPEED_MID] = 2, - [OPTIONS_TEXT_SPEED_FAST] = 4, -}; static const struct GlyphWidthFunc sGlyphWidthFuncs[] = { @@ -295,6 +297,31 @@ static const u8 sMenuCursorDimensions[][2] = [FONT_SHORT_NARROWER] = { 8, 14 }, }; +// these three arrays are most for readability, ie instead of returning a magic number 8 +static const u8 sTextSpeedFrameDelays[] = +{ + [OPTIONS_TEXT_SPEED_SLOW] = 8, + [OPTIONS_TEXT_SPEED_MID] = 4, + [OPTIONS_TEXT_SPEED_FAST] = 1, + [OPTIONS_TEXT_SPEED_INSTANT] = 1, +}; + +static const u8 sTextSpeedModifiers[] = +{ + [OPTIONS_TEXT_SPEED_SLOW] = TEXT_SPEED_SLOW_MODIFIER, + [OPTIONS_TEXT_SPEED_MID] = TEXT_SPEED_MEDIUM_MODIFIER, + [OPTIONS_TEXT_SPEED_FAST] = TEXT_SPEED_FAST_MODIFIER, + [OPTIONS_TEXT_SPEED_INSTANT] = TEXT_SPEED_INSTANT_MODIFIER, +}; + +static const u8 sTextScrollSpeeds[] = +{ + [OPTIONS_TEXT_SPEED_SLOW] = 1, + [OPTIONS_TEXT_SPEED_MID] = 2, + [OPTIONS_TEXT_SPEED_FAST] = 4, + [OPTIONS_TEXT_SPEED_INSTANT] = 6, +}; + static const u16 sFontBoldJapaneseGlyphs[] = INCBIN_U16("graphics/fonts/bold.hwjpnfont"); static void SetFontsPointer(const struct FontInfo *fonts) @@ -302,6 +329,40 @@ static void SetFontsPointer(const struct FontInfo *fonts) gFonts = fonts; } +u32 GetPlayerTextSpeed(void) +{ + if (gTextFlags.forceMidTextSpeed) + return OPTIONS_TEXT_SPEED_MID; + + if (gSaveBlock2Ptr->optionsTextSpeed > OPTIONS_TEXT_SPEED_INSTANT) + gSaveBlock2Ptr->optionsTextSpeed = OPTIONS_TEXT_SPEED_FAST; + + if (FlagGet(FLAG_TEXT_SPEED_INSTANT) || TEXT_SPEED_INSTANT) + return OPTIONS_TEXT_SPEED_INSTANT; + + return gSaveBlock2Ptr->optionsTextSpeed; +} + +u32 GetPlayerTextSpeedDelay(void) +{ + return sTextSpeedFrameDelays[GetPlayerTextSpeed()]; +} + +u32 GetPlayerTextSpeedModifier(void) +{ + return sTextSpeedModifiers[GetPlayerTextSpeed()]; +} + +u32 GetPlayerTextScrollSpeed(void) +{ + return sTextScrollSpeeds[GetPlayerTextSpeed()]; +} + +bool32 IsPlayerTextSpeedInstant(void) +{ + return GetPlayerTextSpeed() == OPTIONS_TEXT_SPEED_INSTANT; +} + void DeactivateAllTextPrinters(void) { int printer; @@ -379,30 +440,53 @@ bool32 AddTextPrinter(struct TextPrinterTemplate *printerTemplate, u8 speed, voi void RunTextPrinters(void) { - int i; + bool32 isInstantText = IsPlayerTextSpeedInstant(); + u32 textRepeats = GetPlayerTextSpeedModifier(); - if (!gDisableTextPrinters) + if (gDisableTextPrinters) + return; + + do { - for (i = 0; i < WINDOWS_MAX; ++i) + u32 numEmpty = 0; + for (u32 windowId = 0; windowId < WINDOWS_MAX; windowId++) { - if (sTextPrinters[i].active) + if (sTextPrinters[windowId].active) { - u16 renderCmd = RenderFont(&sTextPrinters[i]); - switch (renderCmd) + for (u32 repeat = 0; repeat < textRepeats; repeat++) { - case RENDER_PRINT: - CopyWindowToVram(sTextPrinters[i].printerTemplate.windowId, COPYWIN_GFX); - case RENDER_UPDATE: - if (sTextPrinters[i].callback != NULL) - sTextPrinters[i].callback(&sTextPrinters[i].printerTemplate, renderCmd); - break; - case RENDER_FINISH: - sTextPrinters[i].active = FALSE; - break; + u32 renderState = RenderFont(&sTextPrinters[windowId]); + switch (renderState) + { + case RENDER_PRINT: + CopyWindowToVram(sTextPrinters[windowId].printerTemplate.windowId, COPYWIN_GFX); + if (sTextPrinters[windowId].callback != NULL) + sTextPrinters[windowId].callback(&sTextPrinters[windowId].printerTemplate, renderState); + break; + case RENDER_UPDATE: + if (sTextPrinters[windowId].callback != NULL) + sTextPrinters[windowId].callback(&sTextPrinters[windowId].printerTemplate, renderState); + isInstantText = FALSE; + break; + case RENDER_FINISH: + sTextPrinters[windowId].active = FALSE; + isInstantText = FALSE; + break; + } + + if (!sTextPrinters[windowId].active) + break; } } + else + { + numEmpty++; + } } - } + + if (numEmpty == WINDOWS_MAX) + return; + } while (isInstantText); } bool32 IsTextPrinterActive(u8 id) @@ -428,6 +512,13 @@ void GenerateFontHalfRowLookupTable(u8 fgColor, u8 bgColor, u8 shadowColor) u16 *current = sFontHalfRowLookupTable; + if (fgColor == sLastTextFgColor + && bgColor == sLastTextBgColor + && shadowColor == sLastTextShadowColor) + { + return; + } + sLastTextBgColor = bgColor; sLastTextFgColor = fgColor; sLastTextShadowColor = shadowColor; @@ -630,27 +721,35 @@ static u8 UNUSED GetLastTextColor(u8 colorType) } } -inline static void GLYPH_COPY(u8 *windowTiles, u32 widthOffset, u32 j, u32 i, u32 *glyphPixels, s32 width, s32 height) +inline static void GLYPH_COPY(u8 *windowTiles, u32 widthOffset, u32 x0, u32 y0, u32 *glyphPixels, s32 width, s32 height) { - u32 xAdd, yAdd, pixelData, bits, toOrr, dummyX; - u8 *dst; + if (width <= 0) + return; - xAdd = j + width; - yAdd = i + height; - dummyX = j; - for (; i < yAdd; i++) + u32 widthMask = (1 << (width * 4)) - 1; + + u32 shift0 = (x0 % 8) * 4, shift8 = 32 - shift0; + + u32 *alignedWindowTilesX = (u32 *)(windowTiles + ((x0 / 8) * TILE_SIZE_4BPP)); + + u32 y1 = y0 + height; + for (u32 y = y0; y < y1; y++) { - pixelData = *glyphPixels++; - for (j = dummyX; j < xAdd; j++) - { - if ((toOrr = pixelData & 0xF)) - { - dst = windowTiles + ((j / 8) * 32) + ((j % 8) / 2) + ((i / 8) * widthOffset) + ((i % 8) * 4); - bits = ((j & 1) * 4); - *dst = (toOrr << bits) | (*dst & (0xF0 >> bits)); - } - pixelData >>= 4; - } + u32 pixels = *glyphPixels++ & widthMask; + + u32 mask = pixels; + mask = mask | (mask >> 2); + mask = mask | (mask >> 1); + mask = mask & 0x11111111; + mask = mask * 0xF; + + u32 pixels0 = pixels << shift0, pixels8 = pixels >> shift8; + u32 mask0 = mask << shift0, mask8 = mask >> shift8; + + u32 *alignedWindowTiles = (u32 *)((u8 *)alignedWindowTilesX + ((y / 8) * widthOffset) + ((y % 8) * 4)); + + alignedWindowTiles[0] = (alignedWindowTiles[0] & ~mask0) | pixels0; + alignedWindowTiles[8] = (alignedWindowTiles[8] & ~mask8) | pixels8; } } @@ -889,7 +988,7 @@ void TextPrinterInitDownArrowCounters(struct TextPrinter *textPrinter) else { subStruct->downArrowYPosIdx = 0; - subStruct->downArrowDelay = 0; + subStruct->utilityCounter = 0; } } @@ -900,9 +999,9 @@ void TextPrinterDrawDownArrow(struct TextPrinter *textPrinter) if (gTextFlags.autoScroll == 0) { - if (subStruct->downArrowDelay != 0) + if (subStruct->utilityCounter != 0) { - subStruct->downArrowDelay--; + subStruct->utilityCounter--; } else { @@ -938,7 +1037,7 @@ void TextPrinterDrawDownArrow(struct TextPrinter *textPrinter) 16); CopyWindowToVram(textPrinter->printerTemplate.windowId, COPYWIN_GFX); - subStruct->downArrowDelay = 8; + subStruct->utilityCounter = 8 * GetPlayerTextSpeedModifier(); subStruct->downArrowYPosIdx++; } } @@ -1042,7 +1141,7 @@ void DrawDownArrow(u8 windowId, u16 x, u16 y, u8 bgColor, bool32 drawArrow, u8 * BlitBitmapRectToWindow(windowId, arrowTiles, 0, sDownArrowYCoords[*yCoordIndex & 3], 8, 16, x, y - 2, 8, 16); CopyWindowToVram(windowId, COPYWIN_GFX); - *counter = 8; + *counter = 8 * GetPlayerTextSpeedModifier(); ++*yCoordIndex; } } @@ -1058,7 +1157,7 @@ static u16 RenderText(struct TextPrinter *textPrinter) switch (textPrinter->state) { case RENDER_STATE_HANDLE_CHAR: - if (JOY_HELD(A_BUTTON | B_BUTTON) && subStruct->hasPrintBeenSpedUp) + if ((JOY_HELD(A_BUTTON | B_BUTTON) && subStruct->hasPrintBeenSpedUp) || IsPlayerTextSpeedInstant()) textPrinter->delayCounter = 0; if (textPrinter->delayCounter && textPrinter->textSpeed) @@ -1214,6 +1313,13 @@ static u16 RenderText(struct TextPrinter *textPrinter) case EXT_CTRL_CODE_ENG: textPrinter->japanese = FALSE; return RENDER_REPEAT; + case EXT_CTRL_CODE_SPEAKER: + { + enum SpeakerNames name = *textPrinter->printerTemplate.currentChar++; + TrySpawnAndShowNamebox(gSpeakerNamesTable[name], NAME_BOX_BASE_TILE_NUM); + + return RENDER_REPEAT; + } } break; case CHAR_PROMPT_CLEAR: @@ -1322,6 +1428,7 @@ static u16 RenderText(struct TextPrinter *textPrinter) case RENDER_STATE_SCROLL_START: if (TextPrinterWaitWithDownArrow(textPrinter)) { + subStruct->utilityCounter = 0; TextPrinterClearDownArrow(textPrinter); textPrinter->scrollDistance = gFonts[textPrinter->printerTemplate.fontId].maxLetterHeight + textPrinter->printerTemplate.lineSpacing; textPrinter->printerTemplate.currentX = textPrinter->printerTemplate.x; @@ -1331,18 +1438,31 @@ static u16 RenderText(struct TextPrinter *textPrinter) case RENDER_STATE_SCROLL: if (textPrinter->scrollDistance) { - int scrollSpeed = GetPlayerTextSpeed(); - int speed = sWindowVerticalScrollSpeeds[scrollSpeed]; - if (textPrinter->scrollDistance < speed) + u32 scrollSpeed = GetPlayerTextScrollSpeed(); + u32 speedModifier = GetPlayerTextSpeedModifier(); + + if (subStruct->utilityCounter != 0) + { + subStruct->utilityCounter--; + return RENDER_UPDATE; + } + + if (textPrinter->scrollDistance < scrollSpeed) { ScrollWindow(textPrinter->printerTemplate.windowId, 0, textPrinter->scrollDistance, PIXEL_FILL(textPrinter->printerTemplate.bgColor)); textPrinter->scrollDistance = 0; } else { - ScrollWindow(textPrinter->printerTemplate.windowId, 0, speed, PIXEL_FILL(textPrinter->printerTemplate.bgColor)); - textPrinter->scrollDistance -= speed; + ScrollWindow(textPrinter->printerTemplate.windowId, 0, scrollSpeed, PIXEL_FILL(textPrinter->printerTemplate.bgColor)); + textPrinter->scrollDistance -= scrollSpeed; } + + if (speedModifier > 1) + subStruct->utilityCounter = speedModifier; + else + subStruct->utilityCounter = 0; + CopyWindowToVram(textPrinter->printerTemplate.windowId, COPYWIN_GFX); } else @@ -1417,6 +1537,7 @@ static u32 UNUSED GetStringWidthFixedWidthFont(const u8 *str, u8 fontId, u8 lett case EXT_CTRL_CODE_SKIP: case EXT_CTRL_CODE_CLEAR_TO: case EXT_CTRL_CODE_MIN_LETTER_SPACING: + case EXT_CTRL_CODE_SPEAKER: ++strPos; break; case EXT_CTRL_CODE_RESET_FONT: @@ -1565,6 +1686,7 @@ s32 GetStringWidth(u8 fontId, const u8 *str, s16 letterSpacing) case EXT_CTRL_CODE_ESCAPE: case EXT_CTRL_CODE_SHIFT_RIGHT: case EXT_CTRL_CODE_SHIFT_DOWN: + case EXT_CTRL_CODE_SPEAKER: ++str; break; case EXT_CTRL_CODE_FONT: @@ -1742,6 +1864,7 @@ u8 RenderTextHandleBold(u8 *pixels, u8 fontId, u8 *str) case EXT_CTRL_CODE_SKIP: case EXT_CTRL_CODE_CLEAR_TO: case EXT_CTRL_CODE_MIN_LETTER_SPACING: + case EXT_CTRL_CODE_SPEAKER: ++strPos; break; case EXT_CTRL_CODE_RESET_FONT: diff --git a/src/trade.c b/src/trade.c index 2a0d920a91..01cd6f15ca 100644 --- a/src/trade.c +++ b/src/trade.c @@ -138,7 +138,7 @@ enum { #define NUM_CHOOSE_PKMN_SPRITES (1 + GFXTAG_CHOOSE_PKMN_EMPTY_3 - GFXTAG_CHOOSE_PKMN_L) // Values for signaling to/from the link partner -enum { +enum SignalStatus { STATUS_NONE, STATUS_READY, STATUS_CANCEL, @@ -2482,7 +2482,7 @@ s32 GetGameProgressForLinkTrade(void) return TRADE_BOTH_PLAYERS_READY; } -int GetUnionRoomTradeMessageId(struct RfuGameCompatibilityData player, struct RfuGameCompatibilityData partner, u16 playerSpecies2, u16 partnerSpecies, u8 requestedType, u16 playerSpecies, bool8 isModernFatefulEncounter) +int GetUnionRoomTradeMessageId(struct RfuGameCompatibilityData player, struct RfuGameCompatibilityData partner, u16 playerSpecies2, u16 partnerSpecies, enum Type requestedType, u16 playerSpecies, bool8 isModernFatefulEncounter) { bool8 playerHasNationalDex = player.hasNationalDex; bool8 playerCanLinkNationally = player.canLinkNationally; diff --git a/src/trainer_pools.c b/src/trainer_pools.c index ec38c7a01f..6f0e57fdb2 100644 --- a/src/trainer_pools.c +++ b/src/trainer_pools.c @@ -1,5 +1,6 @@ #include "global.h" #include "data.h" +#include "item.h" #include "malloc.h" #include "pokemon.h" #include "random.h" @@ -227,6 +228,10 @@ static u32 PickMonFromPool(const struct Trainer *trainer, u8 *poolIndexArray, u3 poolIndexArray[currIndex] = POOL_SLOT_DISABLED; } } + if (rules->megaStoneClause && gItemsInfo[currentItem].sortType == ITEM_TYPE_MEGA_STONE && gItemsInfo[chosenItem].sortType == ITEM_TYPE_MEGA_STONE) + poolIndexArray[currIndex] = POOL_SLOT_DISABLED; + if (rules->zCrystalClause && gItemsInfo[currentItem].sortType == ITEM_TYPE_Z_CRYSTAL && gItemsInfo[chosenItem].sortType == ITEM_TYPE_Z_CRYSTAL) + poolIndexArray[currIndex] = POOL_SLOT_DISABLED; } } return monIndex; diff --git a/src/trainer_see.c b/src/trainer_see.c index 348ec14c2d..bf66f66e2e 100644 --- a/src/trainer_see.c +++ b/src/trainer_see.c @@ -361,6 +361,8 @@ static const struct SpriteTemplate sSpriteTemplate_Emote = bool8 CheckForTrainersWantingBattle(void) { u8 i; + u8 trainerObjects[OBJECT_EVENTS_COUNT] = {0}; + u8 trainerObjectsCount = 0; if (FlagGet(OW_FLAG_NO_TRAINER_SEE)) return FALSE; @@ -368,17 +370,34 @@ bool8 CheckForTrainersWantingBattle(void) gNoOfApproachingTrainers = 0; gApproachingTrainerId = 0; + // Adds trainers wanting to battle to array for (i = 0; i < OBJECT_EVENTS_COUNT; i++) - { - u8 numTrainers; - + { if (!gObjectEvents[i].active) continue; if (gObjectEvents[i].trainerType != TRAINER_TYPE_NORMAL && gObjectEvents[i].trainerType != TRAINER_TYPE_SEE_ALL_DIRECTIONS && gObjectEvents[i].trainerType != TRAINER_TYPE_BURIED) continue; + trainerObjects[trainerObjectsCount++] = i; + } - numTrainers = CheckTrainer(i); - if (numTrainers == 0xFF) // non-trainerbatle script + // Sorts array by localId + for (i = 1; i <= trainerObjectsCount; i++) + { + u8 x = trainerObjects[i]; + u8 j = i; + while (j > 0 && gObjectEvents[trainerObjects[j-1]].localId > gObjectEvents[x].localId) + { + trainerObjects[j] = trainerObjects[j-1]; + j--; + } + trainerObjects[j] = x; + } + + for (i = 0; i <= trainerObjectsCount; i++) + { + u8 numTrainers; + numTrainers = CheckTrainer(trainerObjects[i]); + if (numTrainers == 0xFF) // non-trainerbattle script { u32 objectEventId = gApproachingTrainers[gNoOfApproachingTrainers - 1].objectEventId; gApproachingTrainers[gNoOfApproachingTrainers - 1].trainerScriptPtr = GetObjectEventScriptPointerByObjectEventId(objectEventId); @@ -522,6 +541,9 @@ static u8 GetTrainerApproachDistance(struct ObjectEvent *trainerObj) PlayerGetDestCoords(&x, &y); if (trainerObj->trainerType == TRAINER_TYPE_NORMAL) // can only see in one direction { + // Disable trainer approach while moving diagonally (usually moving on sideway stairs) + if (trainerObj->facingDirection > DIR_EAST) + return 0; approachDistance = sDirectionalApproachDistanceFuncs[trainerObj->facingDirection - 1](trainerObj, trainerObj->trainerRange_berryTreeId, x, y); return CheckPathBetweenTrainerAndPlayer(trainerObj, approachDistance, trainerObj->facingDirection); } diff --git a/src/trainer_slide.c b/src/trainer_slide.c index 3b94894a79..080c1d4bbc 100644 --- a/src/trainer_slide.c +++ b/src/trainer_slide.c @@ -312,7 +312,7 @@ static bool32 IsSlideInitalizedOrPlayed(enum TrainerSlideType slideId) return FALSE; } -void TryInitializeFirstSTABMoveTrainerSlide(u32 battlerDef, u32 battlerAtk, u32 moveType) +void TryInitializeFirstSTABMoveTrainerSlide(u32 battlerDef, u32 battlerAtk, enum Type moveType) { enum TrainerSlideType slideId = TRAINER_SLIDE_PLAYER_LANDS_FIRST_STAB_MOVE; diff --git a/src/type_icons.c b/src/type_icons.c index ba13f86027..237c2c9a4f 100644 --- a/src/type_icons.c +++ b/src/type_icons.c @@ -14,18 +14,18 @@ static void LoadTypeIconsPerBattler(u32, u32); static bool32 UseDoubleBattleCoords(u32); -static u32 GetMonPublicType(u32, u32); +static enum Type GetMonPublicType(u32, u32); static bool32 ShouldHideUncaughtType(u32 species); static bool32 ShouldHideUnseenType(u32 species); -static u32 GetMonDefensiveTeraType(struct Pokemon *, struct Pokemon*, u32, u32, u32, u32); -static u32 IsIllusionActiveAndTypeUnchanged(struct Pokemon*, u32, u32); +static enum Type GetMonDefensiveTeraType(struct Pokemon *, struct Pokemon*, u32, u32, u32, u32); +static bool32 IsIllusionActiveAndTypeUnchanged(struct Pokemon*, u32, u32); -static void CreateSpriteFromType(u32, bool32, u32[], u32, u32); -static bool32 ShouldSkipSecondType(u32[], u32); +static void CreateSpriteFromType(u32, bool32, enum Type[], u32, u32); +static bool32 ShouldSkipSecondType(enum Type[], 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 CreateSpriteAndSetTypeSpriteAttributes(enum Type, u32 x, u32 y, u32, u32, bool32); +static bool32 ShouldFlipTypeIcon(bool32, u32, enum Type); static void SpriteCB_TypeIcon(struct Sprite*); static void DestroyTypeIcon(struct Sprite*); @@ -266,7 +266,8 @@ static void LoadTypeSpritesAndPalettes(void) static void LoadTypeIconsPerBattler(u32 battler, u32 position) { - u32 typeNum, types[2]; + u32 typeNum; + enum Type types[2]; u32 battlerId = GetBattlerAtPosition(position); bool32 useDoubleBattleCoords = UseDoubleBattleCoords(battlerId); @@ -294,11 +295,11 @@ static bool32 UseDoubleBattleCoords(u32 position) return TRUE; } -static u32 GetMonPublicType(u32 battlerId, u32 typeNum) +static enum Type GetMonPublicType(u32 battlerId, u32 typeNum) { - struct Pokemon* mon = GetBattlerMon(battlerId); + struct Pokemon *mon = GetBattlerMon(battlerId); u32 monSpecies = GetMonData(mon,MON_DATA_SPECIES,NULL); - struct Pokemon* monIllusion; + struct Pokemon *monIllusion; u32 illusionSpecies; if (ShouldHideUncaughtType(monSpecies) || ShouldHideUnseenType(monSpecies)) @@ -338,9 +339,9 @@ static bool32 ShouldHideUnseenType(u32 species) return TRUE; } -static u32 GetMonDefensiveTeraType(struct Pokemon * mon, struct Pokemon* monIllusion, u32 battlerId, u32 typeNum, u32 illusionSpecies, u32 monSpecies) +static enum Type GetMonDefensiveTeraType(struct Pokemon *mon, struct Pokemon *monIllusion, u32 battlerId, u32 typeNum, u32 illusionSpecies, u32 monSpecies) { - u32 teraType = GetBattlerTeraType(battlerId); + enum Type teraType = GetBattlerTeraType(battlerId); u32 targetSpecies; if (teraType != TYPE_STELLAR) @@ -351,7 +352,7 @@ static u32 GetMonDefensiveTeraType(struct Pokemon * mon, struct Pokemon* monIllu return GetSpeciesType(targetSpecies, typeNum); } -static u32 IsIllusionActiveAndTypeUnchanged(struct Pokemon* monIllusion, u32 monSpecies, u32 battlerId) +static bool32 IsIllusionActiveAndTypeUnchanged(struct Pokemon *monIllusion, u32 monSpecies, u32 battlerId) { u32 typeNum; @@ -365,7 +366,7 @@ static u32 IsIllusionActiveAndTypeUnchanged(struct Pokemon* monIllusion, u32 mon return TRUE; } -static void CreateSpriteFromType(u32 position, bool32 useDoubleBattleCoords, u32 types[], u32 typeNum, u32 battler) +static void CreateSpriteFromType(u32 position, bool32 useDoubleBattleCoords, enum Type types[], u32 typeNum, u32 battler) { s32 x = 0, y = 0; @@ -377,7 +378,7 @@ static void CreateSpriteFromType(u32 position, bool32 useDoubleBattleCoords, u32 CreateSpriteAndSetTypeSpriteAttributes(types[typeNum], x, y, position, battler, useDoubleBattleCoords); } -static bool32 ShouldSkipSecondType(u32 types[], u32 typeNum) +static bool32 ShouldSkipSecondType(enum Type types[], u32 typeNum) { if (!typeNum) return FALSE; @@ -394,7 +395,7 @@ static void SetTypeIconXY(s32* x, s32* y, u32 position, bool32 useDoubleBattleCo *y = sTypeIconPositions[position][useDoubleBattleCoords].y + (11 * typeNum); } -static void CreateSpriteAndSetTypeSpriteAttributes(u32 type, u32 x, u32 y, u32 position, u32 battler, bool32 useDoubleBattleCoords) +static void CreateSpriteAndSetTypeSpriteAttributes(enum Type 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; @@ -413,9 +414,9 @@ static void CreateSpriteAndSetTypeSpriteAttributes(u32 type, u32 x, u32 y, u32 p StartSpriteAnim(sprite, type); } -static bool32 ShouldFlipTypeIcon(bool32 useDoubleBattleCoords, u32 position, u32 typeId) +static bool32 ShouldFlipTypeIcon(bool32 useDoubleBattleCoords, u32 position, enum Type typeId) { - bool32 side = (useDoubleBattleCoords) ? B_SIDE_OPPONENT : B_SIDE_PLAYER; + enum BattleSide side = (useDoubleBattleCoords) ? B_SIDE_OPPONENT : B_SIDE_PLAYER; if (GetBattlerSide(GetBattlerAtPosition(position)) != side) return FALSE; @@ -423,7 +424,7 @@ static bool32 ShouldFlipTypeIcon(bool32 useDoubleBattleCoords, u32 position, u32 return !gTypesInfo[typeId].isSpecialCaseType; } -static void SpriteCB_TypeIcon(struct Sprite* sprite) +static void SpriteCB_TypeIcon(struct Sprite *sprite) { u32 position = sprite->tMonPosition; u32 battlerId = sprite->tBattlerId; @@ -487,7 +488,7 @@ static void FreeAllTypeIconResources(void) } } -static void (* const sShowTypesControllerFuncs[])(u32 battler) = +static void (*const sShowTypesControllerFuncs[])(u32 battler) = { PlayerHandleChooseMove, HandleChooseMoveAfterDma3, @@ -562,7 +563,7 @@ static s32 GetTypeIconSlideMovement(bool32 useDoubleBattleCoords, u32 position, static s32 GetTypeIconBounceMovement(s32 originalY, u32 position) { - struct Sprite* healthbox = &gSprites[gHealthboxSpriteIds[GetBattlerAtPosition(position)]]; + struct Sprite *healthbox = &gSprites[gHealthboxSpriteIds[GetBattlerAtPosition(position)]]; return originalY + healthbox->y2; } diff --git a/src/union_room.c b/src/union_room.c index 135cf3e982..368becd0a2 100644 --- a/src/union_room.c +++ b/src/union_room.c @@ -205,7 +205,7 @@ static EWRAM_DATA union } sWirelessLinkMain = {}; EWRAM_DATA struct RfuGameCompatibilityData gRfuPartnerCompatibilityData = {}; EWRAM_DATA u16 gUnionRoomOfferedSpecies = 0; -EWRAM_DATA u8 gUnionRoomRequestedMonType = 0; +EWRAM_DATA enum Type gUnionRoomRequestedMonType = 0; static EWRAM_DATA struct UnionRoomTrade sUnionRoomTrade = {}; static struct WirelessLink_Leader *sLeader; @@ -270,7 +270,7 @@ static void GetURoomActivityRejectMsg(u8 *, s32, u32); static u32 ConvPartnerUnameAndGetWhetherMetAlready(struct RfuPlayer *); static void GetURoomActivityStartMsg(u8 *, u8); static void UR_ClearBg0(void); -static s32 IsRequestedTradeInPlayerParty(u32, u32); +static s32 IsRequestedTradeInPlayerParty(enum Type, u32); static bool32 UR_PrintFieldMessage(const u8 *); static s32 GetChatLeaderActionRequestMessage(u8 *, u32, u16 *, struct WirelessLink_URoom *); static void Task_InitUnionRoom(u8 taskId); @@ -3612,7 +3612,7 @@ static bool8 PrintOnTextbox(u8 *textState, const u8 *str) LoadMessageBoxAndBorderGfx(); DrawDialogueFrame(0, TRUE); StringExpandPlaceholders(gStringVar4, str); - AddTextPrinterForMessage_2(TRUE); + AddTextPrinterForMessage(TRUE); (*textState)++; break; case 1: @@ -4104,7 +4104,7 @@ static void TradeBoardPrintItemInfo(u8 windowId, u8 y, struct RfuGameData *data, { u8 levelStr[4]; u16 species = data->tradeSpecies; - u8 type = data->tradeType; + enum Type type = data->tradeType; u8 level = data->tradeLevel; PrintUnionRoomText(windowId, FONT_NORMAL, playerName, 8, y, colorIdx); @@ -4174,7 +4174,7 @@ static s32 GetUnionRoomPlayerGender(s32 playerIdx, struct RfuPlayerList *list) return list->players[playerIdx].rfu.data.playerGender; } -static s32 IsRequestedTradeInPlayerParty(u32 type, u32 species) +static s32 IsRequestedTradeInPlayerParty(enum Type type, u32 species) { s32 i; diff --git a/src/vs_seeker.c b/src/vs_seeker.c index d9e4497421..48bdbc2abb 100644 --- a/src/vs_seeker.c +++ b/src/vs_seeker.c @@ -15,6 +15,7 @@ #include "battle_setup.h" #include "random.h" #include "field_player_avatar.h" +#include "fieldmap.h" #include "vs_seeker.h" #include "menu.h" #include "string_util.h" @@ -390,8 +391,8 @@ static void GatherNearbyTrainerInfo(void) sVsSeeker->trainerInfo[vsSeekerObjectIdx].localId = templates[objectEventIdx].localId; TryGetObjectEventIdByLocalIdAndMap(templates[objectEventIdx].localId, gSaveBlock1Ptr->location.mapNum, gSaveBlock1Ptr->location.mapGroup, &objectEventId); sVsSeeker->trainerInfo[vsSeekerObjectIdx].objectEventId = objectEventId; - sVsSeeker->trainerInfo[vsSeekerObjectIdx].xCoord = gObjectEvents[objectEventId].currentCoords.x - 7; - sVsSeeker->trainerInfo[vsSeekerObjectIdx].yCoord = gObjectEvents[objectEventId].currentCoords.y - 7; + sVsSeeker->trainerInfo[vsSeekerObjectIdx].xCoord = gObjectEvents[objectEventId].currentCoords.x - MAP_OFFSET; + sVsSeeker->trainerInfo[vsSeekerObjectIdx].yCoord = gObjectEvents[objectEventId].currentCoords.y - MAP_OFFSET; sVsSeeker->trainerInfo[vsSeekerObjectIdx].graphicsId = templates[objectEventIdx].graphicsId; vsSeekerObjectIdx++; } @@ -766,8 +767,8 @@ static bool8 IsTrainerVisibleOnScreen(struct VsSeekerTrainerInfo * trainerInfo) s16 y; PlayerGetDestCoords(&x, &y); - x -= 7; - y -= 7; + x -= MAP_OFFSET; + y -= MAP_OFFSET; if ( x - 7 <= trainerInfo->xCoord && x + 7 >= trainerInfo->xCoord diff --git a/src/wallclock.c b/src/wallclock.c index bca008ac24..6bc87513dd 100644 --- a/src/wallclock.c +++ b/src/wallclock.c @@ -61,9 +61,9 @@ enum { }; enum { - MOVE_NONE, - MOVE_BACKWARD, - MOVE_FORWARD, + CLOCK_MOVE_NONE, + CLOCK_MOVE_BACKWARD, + CLOCK_MOVE_FORWARD, }; enum { @@ -806,15 +806,15 @@ static void Task_SetClock_HandleInput(u8 taskId) } else { - gTasks[taskId].tMoveDir = MOVE_NONE; + gTasks[taskId].tMoveDir = CLOCK_MOVE_NONE; if (JOY_HELD(DPAD_LEFT)) - gTasks[taskId].tMoveDir = MOVE_BACKWARD; + gTasks[taskId].tMoveDir = CLOCK_MOVE_BACKWARD; if (JOY_HELD(DPAD_RIGHT)) - gTasks[taskId].tMoveDir = MOVE_FORWARD; + gTasks[taskId].tMoveDir = CLOCK_MOVE_FORWARD; - if (gTasks[taskId].tMoveDir != MOVE_NONE) + if (gTasks[taskId].tMoveDir != CLOCK_MOVE_NONE) { if (gTasks[taskId].tMoveSpeed < 0xFF) gTasks[taskId].tMoveSpeed++; @@ -916,13 +916,13 @@ static u16 CalcNewMinHandAngle(u16 angle, u8 direction, u8 speed) u8 delta = CalcMinHandDelta(speed); switch (direction) { - case MOVE_BACKWARD: + case CLOCK_MOVE_BACKWARD: if (angle) angle -= delta; else angle = 360 - delta; break; - case MOVE_FORWARD: + case CLOCK_MOVE_FORWARD: if (angle < 360 - delta) angle += delta; else @@ -936,7 +936,7 @@ static bool32 AdvanceClock(u8 taskId, u8 direction) { switch (direction) { - case MOVE_BACKWARD: + case CLOCK_MOVE_BACKWARD: if (gTasks[taskId].tMinutes > 0) { gTasks[taskId].tMinutes--; @@ -953,7 +953,7 @@ static bool32 AdvanceClock(u8 taskId, u8 direction) UpdateClockPeriod(taskId, direction); } break; - case MOVE_FORWARD: + case CLOCK_MOVE_FORWARD: if (gTasks[taskId].tMinutes < 59) { gTasks[taskId].tMinutes++; @@ -979,7 +979,7 @@ static void UpdateClockPeriod(u8 taskId, u8 direction) u8 hours = gTasks[taskId].tHours; switch (direction) { - case MOVE_BACKWARD: + case CLOCK_MOVE_BACKWARD: switch (hours) { case 11: @@ -990,7 +990,7 @@ static void UpdateClockPeriod(u8 taskId, u8 direction) break; } break; - case MOVE_FORWARD: + case CLOCK_MOVE_FORWARD: switch (hours) { case 0: diff --git a/src/wild_encounter.c b/src/wild_encounter.c index 5d8e22c11b..4c81fa371c 100644 --- a/src/wild_encounter.c +++ b/src/wild_encounter.c @@ -4,6 +4,7 @@ #include "battle_pyramid.h" #include "event_data.h" #include "fieldmap.h" +#include "fishing.h" #include "follower_npc.h" #include "random.h" #include "field_player_avatar.h" @@ -46,15 +47,14 @@ extern const u8 EventScript_SprayWoreOff[]; static u16 FeebasRandom(void); static void FeebasSeedRng(u16 seed); -static void UpdateChainFishingStreak(); static bool8 IsWildLevelAllowedByRepel(u8 level); static void ApplyFluteEncounterRateMod(u32 *encRate); static void ApplyCleanseTagEncounterRateMod(u32 *encRate); static u8 GetMaxLevelOfSpeciesInWildTable(const struct WildPokemon *wildMon, u16 species, enum WildPokemonArea area); #ifdef BUGFIX -static bool8 TryGetAbilityInfluencedWildMonIndex(const struct WildPokemon *wildMon, u8 type, u16 ability, u8 *monIndex, u32 size); +static bool8 TryGetAbilityInfluencedWildMonIndex(const struct WildPokemon *wildMon, enum Type type, enum Ability ability, u8 *monIndex, u32 size); #else -static bool8 TryGetAbilityInfluencedWildMonIndex(const struct WildPokemon *wildMon, u8 type, u16 ability, u8 *monIndex); +static bool8 TryGetAbilityInfluencedWildMonIndex(const struct WildPokemon *wildMon, enum Type type, enum Ability ability, u8 *monIndex); #endif static bool8 IsAbilityAllowingEncounter(u8 level); @@ -353,7 +353,7 @@ static u8 ChooseWildMonLevel(const struct WildPokemon *wildPokemon, u8 wildMonIn // check ability for max level mon if (!GetMonData(&gPlayerParty[0], MON_DATA_SANITY_IS_EGG)) { - u16 ability = GetMonAbility(&gPlayerParty[0]); + enum Ability ability = GetMonAbility(&gPlayerParty[0]); if (ability == ABILITY_HUSTLE || ability == ABILITY_VITAL_SPIRIT || ability == ABILITY_PRESSURE) { if (Random() % 2 == 0) @@ -415,36 +415,32 @@ enum TimeOfDay GetTimeOfDayForEncounters(u32 headerId, enum WildPokemonArea area return TIME_OF_DAY_DEFAULT; if (InBattlePike() || CurrentBattlePyramidLocation() != PYRAMID_LOCATION_NONE) - { return OW_TIME_OF_DAY_FALLBACK; - } - else + + switch (area) { - switch (area) - { - default: - case WILD_AREA_LAND: - wildMonInfo = gWildMonHeaders[headerId].encounterTypes[timeOfDay].landMonsInfo; - break; - case WILD_AREA_WATER: - wildMonInfo = gWildMonHeaders[headerId].encounterTypes[timeOfDay].waterMonsInfo; - break; - case WILD_AREA_ROCKS: - wildMonInfo = gWildMonHeaders[headerId].encounterTypes[timeOfDay].rockSmashMonsInfo; - break; - case WILD_AREA_FISHING: - wildMonInfo = gWildMonHeaders[headerId].encounterTypes[timeOfDay].fishingMonsInfo; - break; - case WILD_AREA_HIDDEN: - wildMonInfo = gWildMonHeaders[headerId].encounterTypes[timeOfDay].hiddenMonsInfo; - break; - } + default: + case WILD_AREA_LAND: + wildMonInfo = gWildMonHeaders[headerId].encounterTypes[timeOfDay].landMonsInfo; + break; + case WILD_AREA_WATER: + wildMonInfo = gWildMonHeaders[headerId].encounterTypes[timeOfDay].waterMonsInfo; + break; + case WILD_AREA_ROCKS: + wildMonInfo = gWildMonHeaders[headerId].encounterTypes[timeOfDay].rockSmashMonsInfo; + break; + case WILD_AREA_FISHING: + wildMonInfo = gWildMonHeaders[headerId].encounterTypes[timeOfDay].fishingMonsInfo; + break; + case WILD_AREA_HIDDEN: + wildMonInfo = gWildMonHeaders[headerId].encounterTypes[timeOfDay].hiddenMonsInfo; + break; } if (wildMonInfo == NULL && !OW_TIME_OF_DAY_DISABLE_FALLBACK) return OW_TIME_OF_DAY_FALLBACK; else - return timeOfDay; + return GenConfigTimeOfDay(timeOfDay); } u8 PickWildMonNature(void) @@ -637,7 +633,7 @@ static bool8 WildEncounterCheck(u32 encounterRate, bool8 ignoreAbility) encounterRate *= 2; if (!ignoreAbility && !GetMonData(&gPlayerParty[0], MON_DATA_SANITY_IS_EGG)) { - u32 ability = GetMonAbility(&gPlayerParty[0]); + enum Ability ability = GetMonAbility(&gPlayerParty[0]); if (ability == ABILITY_STENCH && gMapHeader.mapLayoutId == LAYOUT_BATTLE_FRONTIER_BATTLE_PYRAMID_FLOOR) encounterRate = encounterRate * 3 / 4; @@ -967,22 +963,6 @@ bool8 DoesCurrentMapHaveFishingMons(void) return FALSE; } -u32 CalculateChainFishingShinyRolls(void) -{ - return (2 * min(gChainFishingDexNavStreak, FISHING_CHAIN_SHINY_STREAK_MAX)); -} - -static void UpdateChainFishingStreak() -{ - if (!I_FISHING_CHAIN) - return; - - if (gChainFishingDexNavStreak >= FISHING_CHAIN_LENGTH_MAX) - return; - - gChainFishingDexNavStreak++; -} - void FishingWildEncounter(u8 rod) { u16 species; @@ -1126,7 +1106,7 @@ static bool8 IsWildLevelAllowedByRepel(u8 wildLevel) static bool8 IsAbilityAllowingEncounter(u8 level) { - u16 ability; + enum Ability ability; if (GetMonData(&gPlayerParty[0], MON_DATA_SANITY_IS_EGG)) return TRUE; @@ -1142,7 +1122,7 @@ static bool8 IsAbilityAllowingEncounter(u8 level) return TRUE; } -static bool8 TryGetRandomWildMonIndexByType(const struct WildPokemon *wildMon, u8 type, u8 numMon, u8 *monIndex) +static bool8 TryGetRandomWildMonIndexByType(const struct WildPokemon *wildMon, enum Type type, u8 numMon, u8 *monIndex) { u8 validIndexes[numMon]; // variable length array, an interesting feature u8 i, validMonCount; @@ -1196,9 +1176,9 @@ static u8 GetMaxLevelOfSpeciesInWildTable(const struct WildPokemon *wildMon, u16 } #ifdef BUGFIX -static bool8 TryGetAbilityInfluencedWildMonIndex(const struct WildPokemon *wildMon, u8 type, u16 ability, u8 *monIndex, u32 size) +static bool8 TryGetAbilityInfluencedWildMonIndex(const struct WildPokemon *wildMon, enum Type type, enum Ability ability, u8 *monIndex, u32 size) #else -static bool8 TryGetAbilityInfluencedWildMonIndex(const struct WildPokemon *wildMon, u8 type, u16 ability, u8 *monIndex) +static bool8 TryGetAbilityInfluencedWildMonIndex(const struct WildPokemon *wildMon, enum Type type, enum Ability ability, u8 *monIndex) #endif { if (GetMonData(&gPlayerParty[0], MON_DATA_SANITY_IS_EGG)) diff --git a/test/battle/ability/adaptability.c b/test/battle/ability/adaptability.c index 4c1c8439b7..876dac212c 100644 --- a/test/battle/ability/adaptability.c +++ b/test/battle/ability/adaptability.c @@ -3,7 +3,7 @@ SINGLE_BATTLE_TEST("Adaptability increases same-type attack bonus from x1.5 to x2", s16 damage) { - u32 ability; + enum Ability ability; PARAMETRIZE { ability = ABILITY_HYPER_CUTTER; } PARAMETRIZE { ability = ABILITY_ADAPTABILITY; } GIVEN { diff --git a/test/battle/ability/aerilate.c b/test/battle/ability/aerilate.c index c122496d51..b6ae57bd50 100644 --- a/test/battle/ability/aerilate.c +++ b/test/battle/ability/aerilate.c @@ -54,7 +54,7 @@ SINGLE_BATTLE_TEST("Aerilate boosts power of affected moves by 20% (Gen7+) or 30 PARAMETRIZE { move = MOVE_SKILL_SWAP; genConfig = GEN_6; } GIVEN { - WITH_CONFIG(GEN_CONFIG_ATE_MULTIPLIER, genConfig); + WITH_CONFIG(CONFIG_ATE_MULTIPLIER, genConfig); ASSUME(GetMoveType(MOVE_TACKLE) == TYPE_NORMAL); ASSUME(GetMoveEffect(MOVE_SKILL_SWAP) == EFFECT_SKILL_SWAP); PLAYER(SPECIES_WOBBUFFET); diff --git a/test/battle/ability/analytic.c b/test/battle/ability/analytic.c index 5e50c24d59..da2b8e28a6 100644 --- a/test/battle/ability/analytic.c +++ b/test/battle/ability/analytic.c @@ -20,9 +20,59 @@ SINGLE_BATTLE_TEST("Analytic increases the power of moves by 30% if it's the las } } +DOUBLE_BATTLE_TEST("Analytic activates correctly with empty slot after fainting", s16 damage) +{ + u32 speed; + + PARAMETRIZE { speed = 50; } + PARAMETRIZE { speed = 5; } + + GIVEN { + PLAYER(SPECIES_MAGNEMITE) { Ability(ABILITY_ANALYTIC); Speed(speed); } + PLAYER(SPECIES_WYNAUT) { HP(1); Speed(1); } + OPPONENT(SPECIES_WOBBUFFET) { Speed(20); } + OPPONENT(SPECIES_WYNAUT) { Speed(10); } + } WHEN { + TURN { MOVE(opponentLeft, MOVE_SCRATCH, target: playerRight); } + TURN { + MOVE(opponentRight, MOVE_CELEBRATE); + MOVE(playerLeft, MOVE_SCRATCH, target: opponentLeft); + } + } SCENE { + HP_BAR(opponentLeft, captureDamage: &results[i].damage); + } FINALLY { + EXPECT_MUL_EQ(results[0].damage, Q_4_12(1.3), results[1].damage); + } +} + +DOUBLE_BATTLE_TEST("Analytic does not activate when not moving last with empty slot", s16 damage) +{ + u32 speed; + + PARAMETRIZE { speed = 50; } + PARAMETRIZE { speed = 15; } + + GIVEN { + PLAYER(SPECIES_MAGNEMITE) { Ability(ABILITY_ANALYTIC); Speed(speed); } + PLAYER(SPECIES_WYNAUT) { HP(1); Speed(1); } + OPPONENT(SPECIES_WOBBUFFET) { Speed(20); } + OPPONENT(SPECIES_WYNAUT) { Speed(10); } + } WHEN { + TURN { MOVE(opponentLeft, MOVE_SCRATCH, target: playerRight); } + TURN { + MOVE(opponentLeft, MOVE_CELEBRATE); + MOVE(opponentRight, MOVE_CELEBRATE); + MOVE(playerLeft, MOVE_SCRATCH, target: opponentLeft); + } + } SCENE { + HP_BAR(opponentLeft, captureDamage: &results[i].damage); + } FINALLY { + EXPECT_EQ(results[0].damage, results[1].damage); + } +} + 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"); diff --git a/test/battle/ability/anger_shell.c b/test/battle/ability/anger_shell.c index 875088c945..6c9064ee0d 100644 --- a/test/battle/ability/anger_shell.c +++ b/test/battle/ability/anger_shell.c @@ -93,3 +93,23 @@ SINGLE_BATTLE_TEST("Anger Shell activates after all hits from a multi-hit move") EXPECT_EQ(player->statStages[STAT_SPEED], DEFAULT_STAT_STAGE + 1); } } + +SINGLE_BATTLE_TEST("Anger Shell does not activate if move is boosted by Sheer Force") +{ + u16 maxHp = 500; + GIVEN { + PLAYER(SPECIES_KLAWF) { Ability(ABILITY_ANGER_SHELL); MaxHP(maxHp); HP(maxHp / 2 + 1); } + OPPONENT(SPECIES_NIDOKING) { Ability(ABILITY_SHEER_FORCE); } + } WHEN { + TURN { MOVE(opponent, MOVE_EMBER); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_EMBER, opponent); + NOT ABILITY_POPUP(player, ABILITY_ANGER_SHELL); + } THEN { + EXPECT_EQ(player->statStages[STAT_DEF], DEFAULT_STAT_STAGE); + EXPECT_EQ(player->statStages[STAT_SPDEF], DEFAULT_STAT_STAGE); + EXPECT_EQ(player->statStages[STAT_ATK], DEFAULT_STAT_STAGE); + EXPECT_EQ(player->statStages[STAT_SPATK], DEFAULT_STAT_STAGE); + EXPECT_EQ(player->statStages[STAT_SPEED], DEFAULT_STAT_STAGE); + } +} diff --git a/test/battle/ability/anticipation.c b/test/battle/ability/anticipation.c index a4a3bef77f..ee5b602a13 100644 --- a/test/battle/ability/anticipation.c +++ b/test/battle/ability/anticipation.c @@ -100,7 +100,8 @@ SINGLE_BATTLE_TEST("Anticipation doesn't consider Gravity into their effectivene SINGLE_BATTLE_TEST("Anticipation counts Counter, Metal Burst or Mirror Coat as attacking moves of their types (Gen5+)") { - u32 move, species, typeAtk, typeDef; + u32 move, species; + enum Type typeAtk, typeDef; PARAMETRIZE { move = MOVE_COUNTER; species = SPECIES_RATICATE; typeAtk = TYPE_FIGHTING; typeDef = TYPE_NORMAL; } PARAMETRIZE { move = MOVE_METAL_BURST; species = SPECIES_ROGGENROLA; typeAtk = TYPE_STEEL; typeDef = TYPE_ROCK; } PARAMETRIZE { move = MOVE_MIRROR_COAT; species = SPECIES_NIDORINO; typeAtk = TYPE_PSYCHIC; typeDef = TYPE_POISON; } diff --git a/test/battle/ability/aura_break.c b/test/battle/ability/aura_break.c index 10c248c87d..c023869c78 100644 --- a/test/battle/ability/aura_break.c +++ b/test/battle/ability/aura_break.c @@ -62,54 +62,3 @@ DOUBLE_BATTLE_TEST("Aura Break inverts Dark Aura's effect") EXPECT_MUL_EQ(damage[0], UQ_4_12(0.75), damage[2]); } } - -DOUBLE_BATTLE_TEST("Aura Break ignores Mold Breaker abilities") -{ - s16 damage[6]; - u32 species = SPECIES_WOBBUFFET, ability = ABILITY_NONE; - - PARAMETRIZE { species = SPECIES_WOBBUFFET, ability = ABILITY_SHADOW_TAG; } - PARAMETRIZE { species = SPECIES_CRANIDOS, ability = ABILITY_MOLD_BREAKER; } - PARAMETRIZE { species = SPECIES_ZEKROM, ability = ABILITY_TERAVOLT; } - PARAMETRIZE { species = SPECIES_RESHIRAM, ability = ABILITY_TURBOBLAZE; } - - GIVEN { - PLAYER(species) { Ability(ability); Level(50); } - PLAYER(SPECIES_WOBBUFFET); - PLAYER(SPECIES_YVELTAL) { Ability(ABILITY_DARK_AURA); } - PLAYER(SPECIES_XERNEAS) { Ability(ABILITY_FAIRY_AURA); } - OPPONENT(SPECIES_WOBBUFFET); - OPPONENT(SPECIES_WOBBUFFET); - OPPONENT(SPECIES_ZYGARDE_50) { Ability(ABILITY_AURA_BREAK); } - } WHEN { - TURN { MOVE(playerLeft, MOVE_BITE, target: opponentLeft); } - TURN { MOVE(playerLeft, MOVE_PLAY_ROUGH, target: opponentLeft); } - TURN { MOVE(playerLeft, MOVE_BITE, target: opponentLeft); SWITCH(playerRight, 2); } - TURN { MOVE(playerLeft, MOVE_PLAY_ROUGH, target: opponentLeft); SWITCH(playerRight, 3); } - TURN { MOVE(playerLeft, MOVE_BITE, target: opponentLeft); SWITCH(playerRight, 2); SWITCH(opponentRight, 2); } - TURN { MOVE(playerLeft, MOVE_PLAY_ROUGH, target: opponentLeft); SWITCH(playerRight, 3); } - } SCENE { - ANIMATION(ANIM_TYPE_MOVE, MOVE_BITE, playerLeft); - HP_BAR(opponentLeft, captureDamage: &damage[0]); - - ANIMATION(ANIM_TYPE_MOVE, MOVE_PLAY_ROUGH, playerLeft); - HP_BAR(opponentLeft, captureDamage: &damage[1]); - - ANIMATION(ANIM_TYPE_MOVE, MOVE_BITE, playerLeft); - HP_BAR(opponentLeft, captureDamage: &damage[2]); - - ANIMATION(ANIM_TYPE_MOVE, MOVE_PLAY_ROUGH, playerLeft); - HP_BAR(opponentLeft, captureDamage: &damage[3]); - - ANIMATION(ANIM_TYPE_MOVE, MOVE_BITE, playerLeft); - HP_BAR(opponentLeft, captureDamage: &damage[4]); - - ANIMATION(ANIM_TYPE_MOVE, MOVE_PLAY_ROUGH, playerLeft); - HP_BAR(opponentLeft, captureDamage: &damage[5]); - } THEN { - EXPECT_MUL_EQ(damage[0], UQ_4_12(1.33), damage[2]); - EXPECT_MUL_EQ(damage[0], UQ_4_12(0.75), damage[4]); - EXPECT_MUL_EQ(damage[1], UQ_4_12(1.33), damage[3]); - EXPECT_MUL_EQ(damage[1], UQ_4_12(0.75), damage[5]); - } -} diff --git a/test/battle/ability/battle_armor.c b/test/battle/ability/battle_armor.c index b5e28c5a0d..abf7396f60 100644 --- a/test/battle/ability/battle_armor.c +++ b/test/battle/ability/battle_armor.c @@ -4,7 +4,7 @@ SINGLE_BATTLE_TEST("Battle Armor and Shell Armor block critical hits") { u32 species; - u32 ability; + enum Ability ability; PARAMETRIZE { species = SPECIES_KINGLER; ability = ABILITY_SHELL_ARMOR; } PARAMETRIZE { species = SPECIES_ARMALDO; ability = ABILITY_BATTLE_ARMOR; } diff --git a/test/battle/ability/battle_bond.c b/test/battle/ability/battle_bond.c index d268536964..95787429b1 100644 --- a/test/battle/ability/battle_bond.c +++ b/test/battle/ability/battle_bond.c @@ -17,7 +17,7 @@ SINGLE_BATTLE_TEST("Battle Bond transforms player's Greninja - Singles") PARAMETRIZE {monsCountPlayer = 2; monsCountOpponent = 2; } GIVEN { - WITH_CONFIG(GEN_CONFIG_BATTLE_BOND, GEN_8); + WITH_CONFIG(CONFIG_BATTLE_BOND, GEN_8); PLAYER(SPECIES_GRENINJA_BATTLE_BOND); if (monsCountPlayer == 2) { PLAYER(SPECIES_WOBBUFFET); @@ -65,7 +65,7 @@ SINGLE_BATTLE_TEST("Battle Bond transforms opponent's Greninja - Singles") PARAMETRIZE {monsCountPlayer = 2; monsCountOpponent = 2; } GIVEN { - WITH_CONFIG(GEN_CONFIG_BATTLE_BOND, GEN_8); + WITH_CONFIG(CONFIG_BATTLE_BOND, GEN_8); OPPONENT(SPECIES_GRENINJA_BATTLE_BOND); if (monsCountOpponent == 2) { OPPONENT(SPECIES_WOBBUFFET); @@ -113,7 +113,7 @@ DOUBLE_BATTLE_TEST("Battle Bond transforms player's Greninja when fainting its A PARAMETRIZE {monsCountPlayer = 3; monsCountOpponent = 3; } GIVEN { - WITH_CONFIG(GEN_CONFIG_BATTLE_BOND, GEN_8); + WITH_CONFIG(CONFIG_BATTLE_BOND, GEN_8); PLAYER(SPECIES_GRENINJA_BATTLE_BOND); PLAYER(SPECIES_WOBBUFFET) { HP(1); } if (monsCountPlayer == 3) { @@ -145,7 +145,7 @@ DOUBLE_BATTLE_TEST("Battle Bond transforms player's Greninja when fainting its A SINGLE_BATTLE_TEST("Battle Bond increases Atk, SpAtk and Speed by 1 stage (Gen9+)") { GIVEN { - WITH_CONFIG(GEN_CONFIG_BATTLE_BOND, GEN_9); + WITH_CONFIG(CONFIG_BATTLE_BOND, GEN_9); PLAYER(SPECIES_GRENINJA_BATTLE_BOND) { Ability(ABILITY_BATTLE_BOND); } OPPONENT(SPECIES_WOBBUFFET) { HP(1); } OPPONENT(SPECIES_WOBBUFFET); @@ -166,7 +166,7 @@ SINGLE_BATTLE_TEST("Battle Bond increases Atk, SpAtk and Speed by 1 stage (Gen9+ SINGLE_BATTLE_TEST("Battle Bond increases a Stat even if only one can be increased (Gen9+)") { GIVEN { - WITH_CONFIG(GEN_CONFIG_BATTLE_BOND, GEN_9); + WITH_CONFIG(CONFIG_BATTLE_BOND, GEN_9); PLAYER(SPECIES_GRENINJA_BATTLE_BOND) { Ability(ABILITY_BATTLE_BOND); } OPPONENT(SPECIES_WOBBUFFET) { HP(1); } OPPONENT(SPECIES_WOBBUFFET); diff --git a/test/battle/ability/beads_of_ruin.c b/test/battle/ability/beads_of_ruin.c index 37240d2d68..86172459ab 100644 --- a/test/battle/ability/beads_of_ruin.c +++ b/test/battle/ability/beads_of_ruin.c @@ -4,6 +4,7 @@ ASSUMPTIONS { ASSUME(GetMoveCategory(MOVE_WATER_GUN) == DAMAGE_CATEGORY_SPECIAL); + ASSUME(GetMoveCategory(MOVE_ROUND) == DAMAGE_CATEGORY_SPECIAL); ASSUME(GetMoveEffect(MOVE_ROLE_PLAY) == EFFECT_ROLE_PLAY); } @@ -74,4 +75,117 @@ SINGLE_BATTLE_TEST("Beads of Ruin's message displays correctly after all battler } } -TO_DO_BATTLE_TEST("Beads of Ruin reduce Defense if Wonder Room is active"); +DOUBLE_BATTLE_TEST("Beads of Ruin increases damage taken by physical moves in Wonder Room", s16 damage) +{ + bool32 useWonderRoom; + u32 move; + + PARAMETRIZE { useWonderRoom = FALSE; move = MOVE_SCRATCH; } + PARAMETRIZE { useWonderRoom = FALSE; move = MOVE_ROUND; } + PARAMETRIZE { useWonderRoom = TRUE; move = MOVE_SCRATCH; } + PARAMETRIZE { useWonderRoom = TRUE; move = MOVE_ROUND; } + + GIVEN { + ASSUME(GetMoveEffect(MOVE_WONDER_ROOM) == EFFECT_WONDER_ROOM); + ASSUME(GetMoveCategory(MOVE_SCRATCH) == DAMAGE_CATEGORY_PHYSICAL); + ASSUME(GetMoveEffect(MOVE_ROUND) != EFFECT_PSYSHOCK); + PLAYER(SPECIES_CHI_YU) { Ability(ABILITY_BEADS_OF_RUIN); } + PLAYER(SPECIES_WYNAUT); + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + if (useWonderRoom) + TURN { MOVE(opponentLeft, MOVE_WONDER_ROOM); MOVE(playerRight, move, target: opponentLeft); } + else + TURN { MOVE(playerRight, move, target: opponentLeft); } + } SCENE { + ABILITY_POPUP(playerLeft, ABILITY_BEADS_OF_RUIN); + MESSAGE("Chi-Yu's Beads of Ruin weakened the Sp. Def of all surrounding Pokémon!"); + ANIMATION(ANIM_TYPE_MOVE, move, playerRight); + HP_BAR(opponentLeft, captureDamage: &results[i].damage); + } FINALLY { + EXPECT_GT(results[2].damage, results[0].damage); // In Wonder Room, physical move deals more damage + EXPECT_LT(results[3].damage, results[1].damage); // In Wonder Room, special move deals less damage + } +} + +SINGLE_BATTLE_TEST("Beads of Ruin doesn't activate when dragged out by Mold Breaker attacker") +{ + u32 ability; + + PARAMETRIZE { ability = ABILITY_MOLD_BREAKER; } + PARAMETRIZE { ability = ABILITY_SAND_RUSH; } + + GIVEN { + ASSUME(GetMoveEffect(MOVE_DRAGON_TAIL) == EFFECT_HIT_SWITCH_TARGET); + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_CHI_YU) { Ability(ABILITY_BEADS_OF_RUIN); } + OPPONENT(SPECIES_EXCADRILL) { Ability(ability); } + } WHEN { + TURN { MOVE(opponent, MOVE_DRAGON_TAIL); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_DRAGON_TAIL, opponent); + if (ability == ABILITY_MOLD_BREAKER) + { + NONE_OF { + ABILITY_POPUP(player, ABILITY_BEADS_OF_RUIN); + MESSAGE("Chi-Yu's Beads of Ruin weakened the Sp. Def of all surrounding Pokémon!"); + } + } + else + { + ABILITY_POPUP(player, ABILITY_BEADS_OF_RUIN); + MESSAGE("Chi-Yu's Beads of Ruin weakened the Sp. Def of all surrounding Pokémon!"); + } + } +} + +DOUBLE_BATTLE_TEST("Beads of Ruin's Sp. Def reduction is not ignored by Mold Breaker", s16 damage) +{ + u32 ability; + + PARAMETRIZE { ability = ABILITY_MOLD_BREAKER; } + PARAMETRIZE { ability = ABILITY_SAND_RUSH; } + + GIVEN { + PLAYER(SPECIES_CHI_YU) { Ability(ABILITY_BEADS_OF_RUIN); } + PLAYER(SPECIES_WYNAUT); + OPPONENT(SPECIES_EXCADRILL) { Ability(ability); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponentLeft, MOVE_ROUND, target: playerRight); } + } SCENE { + ABILITY_POPUP(playerLeft, ABILITY_BEADS_OF_RUIN); + MESSAGE("Chi-Yu's Beads of Ruin weakened the Sp. Def of all surrounding Pokémon!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_ROUND, opponentLeft); + HP_BAR(playerRight, captureDamage: &results[i].damage); + } FINALLY { + EXPECT_EQ(results[0].damage, results[1].damage); + } +} + +DOUBLE_BATTLE_TEST("Beads of Ruin's Sp. Def reduction is ignored by Gastro Acid", s16 damage) +{ + u32 move; + + PARAMETRIZE { move = MOVE_GASTRO_ACID; } + PARAMETRIZE { move = MOVE_CELEBRATE; } + + GIVEN { + ASSUME(GetMoveEffect(MOVE_GASTRO_ACID) == EFFECT_GASTRO_ACID); + PLAYER(SPECIES_CHI_YU) { Ability(ABILITY_BEADS_OF_RUIN); } + PLAYER(SPECIES_WYNAUT); + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponentRight, move, target: playerLeft); MOVE(opponentLeft, MOVE_ROUND, target: playerRight); } + } SCENE { + ABILITY_POPUP(playerLeft, ABILITY_BEADS_OF_RUIN); + MESSAGE("Chi-Yu's Beads of Ruin weakened the Sp. Def of all surrounding Pokémon!"); + ANIMATION(ANIM_TYPE_MOVE, move, opponentRight); + ANIMATION(ANIM_TYPE_MOVE, MOVE_ROUND, opponentLeft); + HP_BAR(playerRight, captureDamage: &results[i].damage); + } FINALLY { + EXPECT_LT(results[0].damage, results[1].damage); + } +} diff --git a/test/battle/ability/berserk.c b/test/battle/ability/berserk.c index 80e418e3c5..fe356bc671 100644 --- a/test/battle/ability/berserk.c +++ b/test/battle/ability/berserk.c @@ -73,3 +73,64 @@ SINGLE_BATTLE_TEST("Berserk activates after all hits from a multi-hit move") EXPECT_EQ(player->statStages[STAT_SPATK], DEFAULT_STAT_STAGE + 1); } } + +SINGLE_BATTLE_TEST("Berserk does not activate if move is boosted by Sheer Force") +{ + u16 maxHp = 500; + GIVEN { + PLAYER(SPECIES_DRAMPA) { Ability(ABILITY_BERSERK); MaxHP(maxHp); HP(maxHp / 2 + 1); } + OPPONENT(SPECIES_NIDOKING) { Ability(ABILITY_SHEER_FORCE); } + } WHEN { + TURN { MOVE(opponent, MOVE_EMBER); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_EMBER, opponent); + NOT ABILITY_POPUP(player, ABILITY_BERSERK); + } THEN { + EXPECT_EQ(player->statStages[STAT_DEF], DEFAULT_STAT_STAGE); + EXPECT_EQ(player->statStages[STAT_SPDEF], DEFAULT_STAT_STAGE); + EXPECT_EQ(player->statStages[STAT_ATK], DEFAULT_STAT_STAGE); + EXPECT_EQ(player->statStages[STAT_SPATK], DEFAULT_STAT_STAGE); + EXPECT_EQ(player->statStages[STAT_SPEED], DEFAULT_STAT_STAGE); + } +} + +SINGLE_BATTLE_TEST("Berserk will not activate if the last multi hit move activates a restore berry") +{ + u32 j; + GIVEN { + ASSUME(GetMoveEffect(MOVE_DOUBLE_SLAP) == EFFECT_MULTI_HIT); + PLAYER(SPECIES_DRAMPA) { Ability(ABILITY_BERSERK); Item(ITEM_SITRUS_BERRY); MaxHP(100); HP(90); } + OPPONENT(SPECIES_SHELLDER) { Ability(ABILITY_SKILL_LINK); } // Always hits 5 times. + } WHEN { + TURN { MOVE(opponent, MOVE_DOUBLE_SLAP); } + } SCENE { + for (j = 0; j < 4; j++) { + ANIMATION(ANIM_TYPE_MOVE, MOVE_DOUBLE_SLAP, opponent); + NOT ABILITY_POPUP(player, ABILITY_BERSERK); + } + ANIMATION(ANIM_TYPE_MOVE, MOVE_DOUBLE_SLAP, opponent); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player); + NOT ABILITY_POPUP(player, ABILITY_BERSERK); + + } THEN { + EXPECT_EQ(player->statStages[STAT_SPATK], DEFAULT_STAT_STAGE); + } +} + +SINGLE_BATTLE_TEST("Berserk activates before the hp can be restored on non multi hit moves") +{ + u16 maxHp = 500; + GIVEN { + ASSUME(!IsBattleMoveStatus(MOVE_SCRATCH)); + PLAYER(SPECIES_DRAMPA) { Ability(ABILITY_BERSERK); Item(ITEM_SITRUS_BERRY); MaxHP(maxHp); HP(maxHp / 2 + 1); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_SCRATCH); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SCRATCH, opponent); + ABILITY_POPUP(player, ABILITY_BERSERK); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player); + } THEN { + EXPECT_EQ(player->statStages[STAT_SPATK], DEFAULT_STAT_STAGE + 1); + } +} diff --git a/test/battle/ability/clear_body.c b/test/battle/ability/clear_body.c index 46185791a3..f5b9573fe0 100644 --- a/test/battle/ability/clear_body.c +++ b/test/battle/ability/clear_body.c @@ -5,7 +5,8 @@ SINGLE_BATTLE_TEST("Clear Body, Full Metal Body, and White Smoke prevent intimid { s16 turnOneHit; s16 turnTwoHit; - u32 species, ability; + u32 species; + enum Ability ability; PARAMETRIZE{ species = SPECIES_METANG; ability = ABILITY_CLEAR_BODY; } PARAMETRIZE{ species = SPECIES_SOLGALEO; ability = ABILITY_FULL_METAL_BODY; } @@ -40,7 +41,8 @@ SINGLE_BATTLE_TEST("Clear Body, Full Metal Body, and White Smoke prevent intimid SINGLE_BATTLE_TEST("Clear Body, Full Metal Body, and White Smoke prevent stat stage reduction from moves") { u16 move = MOVE_NONE; - u32 j, species = SPECIES_NONE, ability = ABILITY_NONE; + u32 j, species = SPECIES_NONE; + enum Ability ability = ABILITY_NONE; static const u16 statReductionMoves[] = { MOVE_GROWL, MOVE_LEER, @@ -86,7 +88,8 @@ SINGLE_BATTLE_TEST("Clear Body, Full Metal Body, and White Smoke prevent stat st SINGLE_BATTLE_TEST("Clear Body, Full Metal Body, and White Smoke prevent Sticky Web effect on switchin") { - u32 species, ability; + u32 species; + enum Ability ability; PARAMETRIZE{ species = SPECIES_METANG; ability = ABILITY_CLEAR_BODY; } PARAMETRIZE{ species = SPECIES_SOLGALEO; ability = ABILITY_FULL_METAL_BODY; } PARAMETRIZE{ species = SPECIES_TORKOAL; ability = ABILITY_WHITE_SMOKE; } @@ -114,7 +117,8 @@ SINGLE_BATTLE_TEST("Clear Body, Full Metal Body, and White Smoke prevent Sticky SINGLE_BATTLE_TEST("Clear Body, Full Metal Body, and White Smoke don't prevent stat stage reduction from moves used by the user") { - u32 species, ability; + u32 species; + enum Ability ability; PARAMETRIZE{ species = SPECIES_METANG; ability = ABILITY_CLEAR_BODY; } PARAMETRIZE{ species = SPECIES_SOLGALEO; ability = ABILITY_FULL_METAL_BODY; } PARAMETRIZE{ species = SPECIES_TORKOAL; ability = ABILITY_WHITE_SMOKE; } @@ -137,8 +141,9 @@ SINGLE_BATTLE_TEST("Clear Body, Full Metal Body, and White Smoke don't prevent s SINGLE_BATTLE_TEST("Mold Breaker, Teravolt, and Turboblaze ignore Clear Body and White Smoke, but not Full Metal Body") { - u32 j, k, species = SPECIES_NONE, ability = ABILITY_NONE; - u16 breakerAbility = ABILITY_NONE; + u32 j, k, species = SPECIES_NONE; + enum Ability ability = ABILITY_NONE; + enum Ability breakerAbility = ABILITY_NONE; u16 move = ABILITY_NONE; static const u16 breakerAbilities[] = { ABILITY_MOLD_BREAKER, @@ -197,7 +202,8 @@ SINGLE_BATTLE_TEST("Mold Breaker, Teravolt, and Turboblaze ignore Clear Body and SINGLE_BATTLE_TEST("Clear Body, Full Metal Body, and White Smoke don't prevent Speed reduction from Iron Ball") { - u32 j, species = SPECIES_NONE, ability = ABILITY_NONE; + u32 j, species = SPECIES_NONE; + enum Ability ability = ABILITY_NONE; u16 heldItem = ITEM_NONE; static const u16 heldItems[] = { ITEM_NONE, @@ -239,7 +245,8 @@ SINGLE_BATTLE_TEST("Clear Body, Full Metal Body, and White Smoke don't prevent S SINGLE_BATTLE_TEST("Clear Body, Full Metal Body, and White Smoke don't prevent Speed reduction from paralysis") { - u32 species, ability; + u32 species; + enum Ability ability; PARAMETRIZE{ species = SPECIES_METANG; ability = ABILITY_CLEAR_BODY; } PARAMETRIZE{ species = SPECIES_SOLGALEO; ability = ABILITY_FULL_METAL_BODY; } @@ -276,7 +283,8 @@ SINGLE_BATTLE_TEST("Clear Body, Full Metal Body, and White Smoke don't prevent S SINGLE_BATTLE_TEST("Clear Body, Full Metal Body, and White Smoke don't prevent Attack reduction from burn", s16 damage) { bool32 burned = FALSE; - u32 species, ability; + u32 species; + enum Ability ability; PARAMETRIZE{ species = SPECIES_METANG; ability = ABILITY_CLEAR_BODY; burned = FALSE; } PARAMETRIZE{ species = SPECIES_METANG; ability = ABILITY_CLEAR_BODY; burned = TRUE; } PARAMETRIZE{ species = SPECIES_SOLGALEO; ability = ABILITY_FULL_METAL_BODY; burned = FALSE; } @@ -299,7 +307,8 @@ SINGLE_BATTLE_TEST("Clear Body, Full Metal Body, and White Smoke don't prevent A SINGLE_BATTLE_TEST("Clear Body, Full Metal Body, and White Smoke don't prevent receiving negative stat changes from Baton Pass") { - u32 species, ability; + u32 species; + enum Ability ability; PARAMETRIZE{ species = SPECIES_METANG; ability = ABILITY_CLEAR_BODY; } PARAMETRIZE{ species = SPECIES_SOLGALEO; ability = ABILITY_FULL_METAL_BODY; } @@ -329,7 +338,8 @@ SINGLE_BATTLE_TEST("Clear Body, Full Metal Body, and White Smoke don't prevent r SINGLE_BATTLE_TEST("Clear Body, Full Metal Body, and White Smoke don't prevent Topsy-Turvy") { - u32 species, ability; + u32 species; + enum Ability ability; PARAMETRIZE{ species = SPECIES_METANG; ability = ABILITY_CLEAR_BODY; } PARAMETRIZE{ species = SPECIES_SOLGALEO; ability = ABILITY_FULL_METAL_BODY; } @@ -370,7 +380,8 @@ SINGLE_BATTLE_TEST("Clear Body, Full Metal Body, and White Smoke don't prevent T SINGLE_BATTLE_TEST("Clear Body, Full Metal Body, and White Smoke don't prevent Spectral Thief from resetting positive stat changes") { - u32 species, ability; + u32 species; + enum Ability ability; PARAMETRIZE{ species = SPECIES_METANG; ability = ABILITY_CLEAR_BODY; } PARAMETRIZE{ species = SPECIES_SOLGALEO; ability = ABILITY_FULL_METAL_BODY; } @@ -417,7 +428,7 @@ SINGLE_BATTLE_TEST("Clear Body, Full Metal Body, and White Smoke protect from Pr { u32 move = MOVE_NONE; u32 species = SPECIES_NONE; - u32 ability = ABILITY_NONE; + enum Ability ability = ABILITY_NONE; static const u32 moves[] = { MOVE_SPIKY_SHIELD, diff --git a/test/battle/ability/cloud_nine.c b/test/battle/ability/cloud_nine.c index 613ea86e0a..a4eddd1e1c 100644 --- a/test/battle/ability/cloud_nine.c +++ b/test/battle/ability/cloud_nine.c @@ -3,7 +3,8 @@ SINGLE_BATTLE_TEST("Cloud Nine/Air Lock prevent basic weather effects, but without them disappearing - Sandstorm") { - u32 species = 0, ability = 0; + u32 species = 0; + enum Ability ability = 0; PARAMETRIZE { species = SPECIES_PSYDUCK; ability = ABILITY_CLOUD_NINE; } PARAMETRIZE { species = SPECIES_RAYQUAZA; ability = ABILITY_AIR_LOCK; } GIVEN { diff --git a/test/battle/ability/color_change.c b/test/battle/ability/color_change.c index 6ea5d9537b..49eaa3e916 100644 --- a/test/battle/ability/color_change.c +++ b/test/battle/ability/color_change.c @@ -173,3 +173,16 @@ SINGLE_BATTLE_TEST("Color Change does not change the type to Normal when a Pokem } } } + +SINGLE_BATTLE_TEST("Color Change does not activate if move is boosted by Sheer Force") +{ + GIVEN { + PLAYER(SPECIES_KECLEON) { Ability(ABILITY_COLOR_CHANGE); } + OPPONENT(SPECIES_NIDOKING) { Ability(ABILITY_SHEER_FORCE); } + } WHEN { + TURN { MOVE(opponent, MOVE_EMBER); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_EMBER, opponent); + NOT ABILITY_POPUP(player, ABILITY_COLOR_CHANGE); + } +} diff --git a/test/battle/ability/competitive.c b/test/battle/ability/competitive.c index 96472fa2c9..28cd0198ab 100644 --- a/test/battle/ability/competitive.c +++ b/test/battle/ability/competitive.c @@ -140,7 +140,7 @@ SINGLE_BATTLE_TEST("Competitive activates after Sticky Web lowers Speed") SINGLE_BATTLE_TEST("Competitive doesn't activate after Sticky Web lowers Speed if Court Changed (gen8)") { GIVEN { - WITH_CONFIG(GEN_CONFIG_DEFIANT_STICKY_WEB, GEN_8); + WITH_CONFIG(CONFIG_DEFIANT_STICKY_WEB, GEN_8); PLAYER(SPECIES_WOBBUFFET); PLAYER(SPECIES_IGGLYBUFF) { Ability(ABILITY_COMPETITIVE); } OPPONENT(SPECIES_WOBBUFFET); @@ -167,7 +167,7 @@ SINGLE_BATTLE_TEST("Competitive doesn't activate after Sticky Web lowers Speed i SINGLE_BATTLE_TEST("Competitive correctly activates after Sticky Web lowers Speed if Court Changed (Gen8)") { GIVEN { - WITH_CONFIG(GEN_CONFIG_DEFIANT_STICKY_WEB, GEN_8); + WITH_CONFIG(CONFIG_DEFIANT_STICKY_WEB, GEN_8); PLAYER(SPECIES_WOBBUFFET); PLAYER(SPECIES_IGGLYBUFF) { Ability(ABILITY_COMPETITIVE); } OPPONENT(SPECIES_WOBBUFFET); diff --git a/test/battle/ability/contrary.c b/test/battle/ability/contrary.c index 850ca60734..ef5b4c6c7d 100644 --- a/test/battle/ability/contrary.c +++ b/test/battle/ability/contrary.c @@ -8,7 +8,7 @@ ASSUMPTIONS SINGLE_BATTLE_TEST("Contrary raises Attack when Intimidated in a single battle", s16 damage) { - u32 ability; + enum Ability ability; PARAMETRIZE { ability = ABILITY_CONTRARY; } PARAMETRIZE { ability = ABILITY_TANGLED_FEET; } GIVEN { @@ -35,7 +35,7 @@ SINGLE_BATTLE_TEST("Contrary raises Attack when Intimidated in a single battle", DOUBLE_BATTLE_TEST("Contrary raises Attack when Intimidated in a double battle", s16 damageLeft, s16 damageRight) { - u32 abilityLeft, abilityRight; + enum Ability abilityLeft, abilityRight; PARAMETRIZE { abilityLeft = ABILITY_CONTRARY; abilityRight = ABILITY_CONTRARY; } PARAMETRIZE { abilityLeft = ABILITY_TANGLED_FEET; abilityRight = ABILITY_TANGLED_FEET; } @@ -78,7 +78,7 @@ DOUBLE_BATTLE_TEST("Contrary raises Attack when Intimidated in a double battle", SINGLE_BATTLE_TEST("Contrary raises stats after using a move which would normally lower them: Overheat", s16 damageBefore, s16 damageAfter) { - u32 ability; + enum Ability ability; PARAMETRIZE { ability = ABILITY_CONTRARY; } PARAMETRIZE { ability = ABILITY_TANGLED_FEET; } GIVEN { @@ -122,7 +122,7 @@ SINGLE_BATTLE_TEST("Contrary raises stats after using a move which would normall SINGLE_BATTLE_TEST("Contrary lowers a stat after using a move which would normally raise it: Swords Dance", s16 damageBefore, s16 damageAfter) { - u32 ability; + enum Ability ability; PARAMETRIZE { ability = ABILITY_CONTRARY; } PARAMETRIZE { ability = ABILITY_TANGLED_FEET; } GIVEN { @@ -159,7 +159,7 @@ SINGLE_BATTLE_TEST("Contrary lowers a stat after using a move which would normal SINGLE_BATTLE_TEST("Contrary raises a stat after using a move which would normally lower it: Growl", s16 damage) { - u32 ability; + enum Ability ability; PARAMETRIZE { ability = ABILITY_CONTRARY; } PARAMETRIZE { ability = ABILITY_TANGLED_FEET; } GIVEN { @@ -190,7 +190,7 @@ SINGLE_BATTLE_TEST("Contrary raises a stat after using a move which would normal SINGLE_BATTLE_TEST("Contrary lowers a stat after using a move which would normally raise it: Belly Drum", s16 damageBefore, s16 damageAfter) { - u32 ability; + enum Ability ability; PARAMETRIZE { ability = ABILITY_CONTRARY; } PARAMETRIZE { ability = ABILITY_TANGLED_FEET; } GIVEN { diff --git a/test/battle/ability/costar.c b/test/battle/ability/costar.c index 3d041a8d53..bc06ac26a7 100644 --- a/test/battle/ability/costar.c +++ b/test/battle/ability/costar.c @@ -25,8 +25,99 @@ DOUBLE_BATTLE_TEST("Costar copies an ally's stat stages upon entering battle") } } +DOUBLE_BATTLE_TEST("Costar copies an ally's Dragon Cheer critical hit boost") +{ + PASSES_RANDOMLY(1, 8, RNG_CRITICAL_HIT); + GIVEN { + ASSUME(gMovesInfo[MOVE_DRAGON_CHEER].effect == EFFECT_DRAGON_CHEER); + ASSUME(gMovesInfo[MOVE_TACKLE].criticalHitStage == 0); + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_WYNAUT); + PLAYER(SPECIES_FLAMIGO) { Ability(ABILITY_COSTAR); } + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(playerRight, MOVE_DRAGON_CHEER, target: playerLeft); MOVE(playerLeft, MOVE_CELEBRATE); } + TURN { SWITCH(playerRight, 2); } + TURN { MOVE(playerRight, MOVE_TACKLE, target: opponentLeft); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_DRAGON_CHEER, playerRight); + ABILITY_POPUP(playerRight, ABILITY_COSTAR); + ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, playerRight); + MESSAGE("A critical hit!"); + } +} + +DOUBLE_BATTLE_TEST("Costar copies an ally's lowered stat stages") +{ + GIVEN { + ASSUME(gMovesInfo[MOVE_GROWL].effect == EFFECT_ATTACK_DOWN); + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_WYNAUT); + PLAYER(SPECIES_FLAMIGO) { Ability(ABILITY_COSTAR); } + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponentLeft, MOVE_GROWL); MOVE(opponentRight, MOVE_CELEBRATE); } + TURN { SWITCH(playerRight, 2); MOVE(playerLeft, MOVE_CELEBRATE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_GROWL, opponentLeft); + ABILITY_POPUP(playerRight, ABILITY_COSTAR); + } THEN { + EXPECT_EQ(playerLeft->statStages[STAT_ATK], DEFAULT_STAT_STAGE - 1); + EXPECT_EQ(playerRight->statStages[STAT_ATK], DEFAULT_STAT_STAGE - 1); + } +} + +DOUBLE_BATTLE_TEST("Costar copies an ally's Focus Energy critical hit boost") +{ + PASSES_RANDOMLY(1, 2, RNG_CRITICAL_HIT); + GIVEN { + ASSUME(gMovesInfo[MOVE_FOCUS_ENERGY].effect == EFFECT_FOCUS_ENERGY); + ASSUME(gMovesInfo[MOVE_TACKLE].criticalHitStage == 0); + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_WYNAUT); + PLAYER(SPECIES_FLAMIGO) { Ability(ABILITY_COSTAR); } + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(playerLeft, MOVE_SWORDS_DANCE); MOVE(playerRight, MOVE_CELEBRATE); } + TURN { MOVE(playerLeft, MOVE_FOCUS_ENERGY); MOVE(playerRight, MOVE_CELEBRATE); } + TURN { SWITCH(playerRight, 2); } + TURN { MOVE(playerRight, MOVE_TACKLE, target: opponentLeft); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SWORDS_DANCE, playerLeft); + ANIMATION(ANIM_TYPE_MOVE, MOVE_FOCUS_ENERGY, playerLeft); + ABILITY_POPUP(playerRight, ABILITY_COSTAR); + ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, playerRight); + MESSAGE("A critical hit!"); + } +} + +DOUBLE_BATTLE_TEST("Costar copies an ally's Dragon Cheer critical hit boost") +{ + PASSES_RANDOMLY(1, 8, RNG_CRITICAL_HIT); + GIVEN { + ASSUME(gMovesInfo[MOVE_DRAGON_CHEER].effect == EFFECT_DRAGON_CHEER); + ASSUME(gMovesInfo[MOVE_TACKLE].criticalHitStage == 0); + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_WYNAUT); + PLAYER(SPECIES_FLAMIGO) { Ability(ABILITY_COSTAR); } + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(playerRight, MOVE_DRAGON_CHEER, target: playerLeft); MOVE(playerLeft, MOVE_SWORDS_DANCE); } + TURN { SWITCH(playerRight, 2); MOVE(playerLeft, MOVE_CELEBRATE); } + TURN { MOVE(playerRight, MOVE_TACKLE, target: opponentLeft); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_DRAGON_CHEER, playerRight); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SWORDS_DANCE, playerLeft); + ABILITY_POPUP(playerRight, ABILITY_COSTAR); + ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, playerRight); + MESSAGE("A critical hit!"); + } +} + // Copy from Ruin ability tests TO_DO_BATTLE_TEST("Costar's message displays correctly after all battlers fainted - Player"); TO_DO_BATTLE_TEST("Costar's message displays correctly after all battlers fainted - Opponent"); - -TO_DO_BATTLE_TEST("Costar can copy an ally's critical hit ratio"); diff --git a/test/battle/ability/curious_medicine.c b/test/battle/ability/curious_medicine.c index 3844170eb0..7c3e200c7a 100644 --- a/test/battle/ability/curious_medicine.c +++ b/test/battle/ability/curious_medicine.c @@ -3,7 +3,7 @@ DOUBLE_BATTLE_TEST("Curious Medicine resets ally's stat stages upon entering battle") { - u32 ability; + enum Ability ability; PARAMETRIZE { ability = ABILITY_CURIOUS_MEDICINE; } PARAMETRIZE { ability = ABILITY_OWN_TEMPO; } diff --git a/test/battle/ability/damp.c b/test/battle/ability/damp.c index 030e698d8e..816588f497 100644 --- a/test/battle/ability/damp.c +++ b/test/battle/ability/damp.c @@ -1,7 +1,7 @@ #include "global.h" #include "test/battle.h" -SINGLE_BATTLE_TEST("Damp prevents explosion-like moves from enemies") +SINGLE_BATTLE_TEST("Damp prevents Explosion-like moves from enemies") { u32 move; PARAMETRIZE { move = MOVE_EXPLOSION; } @@ -19,7 +19,7 @@ SINGLE_BATTLE_TEST("Damp prevents explosion-like moves from enemies") } } -DOUBLE_BATTLE_TEST("Damp prevents explosion-like moves from enemies in a double battle") +DOUBLE_BATTLE_TEST("Damp prevents Explosion-like moves from enemies in a double battle") { u32 move; PARAMETRIZE { move = MOVE_EXPLOSION; } @@ -39,7 +39,7 @@ DOUBLE_BATTLE_TEST("Damp prevents explosion-like moves from enemies in a double } } -SINGLE_BATTLE_TEST("Damp prevents explosion-like moves from self") +SINGLE_BATTLE_TEST("Damp prevents Explosion-like moves from self") { u32 move; PARAMETRIZE { move = MOVE_EXPLOSION; } @@ -72,3 +72,5 @@ SINGLE_BATTLE_TEST("Damp prevents damage from Aftermath") NONE_OF { HP_BAR(player); } } } + +//TO_DO_BATTLE_TEST("Damp affects non-adjacent Pokémon (triples)") diff --git a/test/battle/ability/dancer.c b/test/battle/ability/dancer.c index b456d9d79a..2fb870ea51 100644 --- a/test/battle/ability/dancer.c +++ b/test/battle/ability/dancer.c @@ -79,6 +79,9 @@ DOUBLE_BATTLE_TEST("Dancer triggers from slowest to fastest") } } +TO_DO_BATTLE_TEST("Dancer triggers from slowest to fastest during Trick Room") +TO_DO_BATTLE_TEST("Dancer triggering ignores Lagging Tail") + SINGLE_BATTLE_TEST("Dancer doesn't trigger if the original user flinches") { GIVEN { @@ -146,6 +149,27 @@ SINGLE_BATTLE_TEST("Dancer-called attacks have their type updated") } } +SINGLE_BATTLE_TEST("Dancer-called attacks do not trigger Life Orb if target is immune") +{ + GIVEN { + ASSUME(IsDanceMove(MOVE_REVELATION_DANCE)); + ASSUME(GetMoveEffect(MOVE_REVELATION_DANCE) == EFFECT_REVELATION_DANCE); + ASSUME(GetMoveEffect(MOVE_ROOST) == EFFECT_ROOST); + ASSUME(GetItemHoldEffect(ITEM_LIFE_ORB) == HOLD_EFFECT_LIFE_ORB); + ASSUME(GetSpeciesType(SPECIES_ORICORIO_POM_POM, 0) == TYPE_ELECTRIC || GetSpeciesType(SPECIES_ORICORIO_POM_POM, 1) == TYPE_ELECTRIC); + PLAYER(SPECIES_RAICHU) { Ability(ABILITY_LIGHTNING_ROD); } + OPPONENT(SPECIES_ORICORIO_POM_POM) { Ability(ABILITY_DANCER); Item(ITEM_LIFE_ORB); } + } WHEN { + TURN { MOVE(opponent, MOVE_ROOST); MOVE(player, MOVE_REVELATION_DANCE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_REVELATION_DANCE, player); + ABILITY_POPUP(opponent, ABILITY_DANCER); + NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_REVELATION_DANCE, opponent); + ABILITY_POPUP(player, ABILITY_LIGHTNING_ROD); + NOT HP_BAR(opponent); + } +} + DOUBLE_BATTLE_TEST("Dancer doesn't trigger on a snatched move") { GIVEN { @@ -170,6 +194,9 @@ DOUBLE_BATTLE_TEST("Dancer doesn't trigger on a snatched move") } } +TO_DO_BATTLE_TEST("Dancer-called moves can be snatched") +TO_DO_BATTLE_TEST("Dancer-called moves can be reflected by Magic Bounce/Coat") + DOUBLE_BATTLE_TEST("Dancer triggers on Instructed dance moves") { GIVEN { @@ -225,6 +252,9 @@ DOUBLE_BATTLE_TEST("Dancer-called move doesn't update move to be Instructed") } } +TO_DO_BATTLE_TEST("Dancer-called moves doesn't update move to be called by Mimick") +TO_DO_BATTLE_TEST("Dancer-called moves doesn't update move to be called by Mirror Move") + DOUBLE_BATTLE_TEST("Dancer doesn't call a move that didn't execute due to Powder") { GIVEN { @@ -247,7 +277,6 @@ DOUBLE_BATTLE_TEST("Dancer doesn't call a move that didn't execute due to Powder } } - DOUBLE_BATTLE_TEST("Dancer still activates after Red Card") { GIVEN { @@ -334,3 +363,16 @@ DOUBLE_BATTLE_TEST("Dancer correctly restores move targets") HP_BAR(playerRight); } } + +TO_DO_BATTLE_TEST("Dancer-called damaging moves are considered for Counter/Mirror Coat/Metal Burst") + +TO_DO_BATTLE_TEST("Dancer copies a status Z-Move's base move without gaining an additional Z-Power effect") +TO_DO_BATTLE_TEST("Dancer user may hit itself in confusion instead of copying a move if it's confused") +TO_DO_BATTLE_TEST("Dancer tries to copy a move but fails if it's being forced into a different move - Rampage move") // Test with Petal Dance, Thrash +TO_DO_BATTLE_TEST("Dancer tries to copy a move but fails if it's being forced into a different move - Rollout") +TO_DO_BATTLE_TEST("Dancer tries to copy a move but fails if it's being forced into a different move - Choice items") +TO_DO_BATTLE_TEST("Dancer tries to copy a move but fails if it's being forced into a different move - Encore") +TO_DO_BATTLE_TEST("Dancer tries to copy a status move but fails if it's under Taunt's effect") +TO_DO_BATTLE_TEST("Dancer can still copy status moves if the user is holding an Assault Vest") +TO_DO_BATTLE_TEST("Dancer copies Lunar Dance after the original user faints, but before the replacement is sent out") +TO_DO_BATTLE_TEST("Dancer doesn't activate Feather Dance if it was reflected by Magic Bounce/Coat") diff --git a/test/battle/ability/dauntless_shield.c b/test/battle/ability/dauntless_shield.c index 6fed2f0b5c..91d5ceb4fc 100644 --- a/test/battle/ability/dauntless_shield.c +++ b/test/battle/ability/dauntless_shield.c @@ -20,7 +20,7 @@ SINGLE_BATTLE_TEST("Dauntless Shield raises Defense by one stage") SINGLE_BATTLE_TEST("Dauntless Shield raises Defense by one stage every time it switches in (Gen8)") { GIVEN { - WITH_CONFIG(GEN_DAUNTLESS_SHIELD, GEN_8); + WITH_CONFIG(CONFIG_DAUNTLESS_SHIELD, GEN_8); PLAYER(SPECIES_WOBBUFFET); OPPONENT(SPECIES_ZAMAZENTA) { Ability(ABILITY_DAUNTLESS_SHIELD); } OPPONENT(SPECIES_WYNAUT); @@ -42,7 +42,7 @@ SINGLE_BATTLE_TEST("Dauntless Shield raises Defense by one stage every time it s SINGLE_BATTLE_TEST("Dauntless Shield raises Defense by one stage only once per battle (Gen 9+)") { GIVEN { - WITH_CONFIG(GEN_DAUNTLESS_SHIELD, GEN_9); + WITH_CONFIG(CONFIG_DAUNTLESS_SHIELD, GEN_9); PLAYER(SPECIES_WOBBUFFET); OPPONENT(SPECIES_ZAMAZENTA) { Ability(ABILITY_DAUNTLESS_SHIELD); } OPPONENT(SPECIES_WYNAUT); diff --git a/test/battle/ability/dazzling.c b/test/battle/ability/dazzling.c index 7541b8a566..e5dd6bb37d 100644 --- a/test/battle/ability/dazzling.c +++ b/test/battle/ability/dazzling.c @@ -1,7 +1,6 @@ #include "global.h" #include "test/battle.h" - ASSUMPTIONS { ASSUME(GetMovePriority(MOVE_QUICK_ATTACK) > 0); @@ -9,7 +8,8 @@ ASSUMPTIONS DOUBLE_BATTLE_TEST("Dazzling, Queenly Majesty and Armor Tail protect the user from priority moves") { - u32 species, ability; + u32 species; + enum Ability ability; PARAMETRIZE { species = SPECIES_BRUXISH; ability = ABILITY_DAZZLING; } PARAMETRIZE { species = SPECIES_FARIGIRAF; ability = ABILITY_ARMOR_TAIL; } @@ -31,7 +31,8 @@ DOUBLE_BATTLE_TEST("Dazzling, Queenly Majesty and Armor Tail protect the user fr DOUBLE_BATTLE_TEST("Dazzling, Queenly Majesty and Armor Tail protect users partner from priority moves") { - u32 species, ability; + u32 species; + enum Ability ability; PARAMETRIZE { species = SPECIES_BRUXISH; ability = ABILITY_DAZZLING; } PARAMETRIZE { species = SPECIES_FARIGIRAF; ability = ABILITY_ARMOR_TAIL; } @@ -53,7 +54,8 @@ DOUBLE_BATTLE_TEST("Dazzling, Queenly Majesty and Armor Tail protect users partn DOUBLE_BATTLE_TEST("Dazzling, Queenly Majesty and Armor Tail don't protect the user from negative priority") { - u32 species, ability; + u32 species; + enum Ability ability; PARAMETRIZE { species = SPECIES_BRUXISH; ability = ABILITY_DAZZLING; } PARAMETRIZE { species = SPECIES_FARIGIRAF; ability = ABILITY_ARMOR_TAIL; } @@ -74,7 +76,8 @@ DOUBLE_BATTLE_TEST("Dazzling, Queenly Majesty and Armor Tail don't protect the u SINGLE_BATTLE_TEST("Dazzling, Queenly Majesty and Armor Tail protect from all multi hit hits with one activation") { - u32 species, ability; + u32 species; + enum Ability ability; PARAMETRIZE { species = SPECIES_BRUXISH; ability = ABILITY_DAZZLING; } PARAMETRIZE { species = SPECIES_FARIGIRAF; ability = ABILITY_ARMOR_TAIL; } @@ -96,3 +99,36 @@ SINGLE_BATTLE_TEST("Dazzling, Queenly Majesty and Armor Tail protect from all mu } } } + +SINGLE_BATTLE_TEST("Dazzling, Queenly Majesty and Armor Tail prevent Protean activation") +{ + u32 species, ability; + + PARAMETRIZE { species = SPECIES_BRUXISH; ability = ABILITY_DAZZLING; } + PARAMETRIZE { species = SPECIES_FARIGIRAF; ability = ABILITY_ARMOR_TAIL; } + PARAMETRIZE { species = SPECIES_TSAREENA; ability = ABILITY_QUEENLY_MAJESTY; } + + GIVEN { + PLAYER(SPECIES_KECLEON) { Ability(ABILITY_PROTEAN); } + OPPONENT(species) { Ability(ability); } + } WHEN { + TURN { MOVE(player, MOVE_WATER_SHURIKEN); } + } SCENE { + NONE_OF { + ANIMATION(ANIM_TYPE_MOVE, MOVE_WATER_SHURIKEN, player); + ABILITY_POPUP(player, ABILITY_PROTEAN); + } + ABILITY_POPUP(opponent, ability); + } +} + +// Listed on Bulbapedia as "Moves that target all Pokémon (except Perish Song, Flower Shield, and Rototiller)," +// Despite the fact that there's only 2 remaining moves from that list, being Haze and Teatime +TO_DO_BATTLE_TEST("Dazzling, Queenly Majesty and Armor Tail do not block Haze") +TO_DO_BATTLE_TEST("Dazzling, Queenly Majesty and Armor Tail do not block Teatime") + +TO_DO_BATTLE_TEST("Dazzling, Queenly Majesty and Armor Tail do not block a move's Z-Status effect") // Z-Baby-Doll eyes increases Def but doesn't reduce Atk +TO_DO_BATTLE_TEST("Mold Breaker ignores Dazzling, Queenly Majesty and Armor Tail") +TO_DO_BATTLE_TEST("Instruct-called moves keep their priority, which is considered for Dazzling, Queenly Majesty and Armor Tail") + +TO_DO_BATTLE_TEST(" Dazzling, Queenly Majesty and Armor Tail do not block high-priority moves called by other moves") // Metronome, Assist, Nature Power, etc. diff --git a/test/battle/ability/defiant.c b/test/battle/ability/defiant.c index 3102980378..21c1e40a43 100644 --- a/test/battle/ability/defiant.c +++ b/test/battle/ability/defiant.c @@ -3,7 +3,7 @@ DOUBLE_BATTLE_TEST("Defiant sharply raises player's Attack after Intimidate") { - u32 abilityLeft, abilityRight; + enum Ability abilityLeft, abilityRight; PARAMETRIZE { abilityLeft = ABILITY_VITAL_SPIRIT; abilityRight = ABILITY_VITAL_SPIRIT; } PARAMETRIZE { abilityLeft = ABILITY_VITAL_SPIRIT; abilityRight = ABILITY_DEFIANT; } @@ -61,7 +61,7 @@ DOUBLE_BATTLE_TEST("Defiant sharply raises player's Attack after Intimidate") // Same as above, but for opponent. DOUBLE_BATTLE_TEST("Defiant sharply raises opponent's Attack after Intimidate") { - u32 abilityLeft, abilityRight; + enum Ability abilityLeft, abilityRight; PARAMETRIZE { abilityLeft = ABILITY_VITAL_SPIRIT; abilityRight = ABILITY_VITAL_SPIRIT; } PARAMETRIZE { abilityLeft = ABILITY_VITAL_SPIRIT; abilityRight = ABILITY_DEFIANT; } @@ -142,7 +142,7 @@ SINGLE_BATTLE_TEST("Defiant activates after Sticky Web lowers Speed") SINGLE_BATTLE_TEST("Defiant doesn't activate after Sticky Web lowers Speed if Court Changed (Gen8)") { GIVEN { - WITH_CONFIG(GEN_CONFIG_DEFIANT_STICKY_WEB, GEN_8); + WITH_CONFIG(CONFIG_DEFIANT_STICKY_WEB, GEN_8); ASSUME(GetMoveEffect(MOVE_GROWL) == EFFECT_ATTACK_DOWN); ASSUME(GetMoveEffect(MOVE_STICKY_WEB) == EFFECT_STICKY_WEB); ASSUME(GetMoveEffect(MOVE_COURT_CHANGE) == EFFECT_COURT_CHANGE); @@ -179,7 +179,7 @@ SINGLE_BATTLE_TEST("Defiant doesn't activate after Sticky Web lowers Speed if Co SINGLE_BATTLE_TEST("Defiant activates after Sticky Web lowers Speed if Court Changed (Gen9)") { GIVEN { - WITH_CONFIG(GEN_CONFIG_DEFIANT_STICKY_WEB, GEN_9); + WITH_CONFIG(CONFIG_DEFIANT_STICKY_WEB, GEN_9); ASSUME(GetMoveEffect(MOVE_GROWL) == EFFECT_ATTACK_DOWN); ASSUME(GetMoveEffect(MOVE_STICKY_WEB) == EFFECT_STICKY_WEB); ASSUME(GetMoveEffect(MOVE_COURT_CHANGE) == EFFECT_COURT_CHANGE); diff --git a/test/battle/ability/delta_stream.c b/test/battle/ability/delta_stream.c index 5b4081cb1e..a2202d64c0 100644 --- a/test/battle/ability/delta_stream.c +++ b/test/battle/ability/delta_stream.c @@ -1,4 +1,9 @@ #include "global.h" #include "test/battle.h" -TO_DO_BATTLE_TEST("TODO: Write Delta Stream (Ability) test titles") +// Effects of strong winds are handled in test/battle/weather/strong_winds.c + +//TO_DO_BATTLE_TEST("Delta Stream doesn't activate if is sent-out in a rotated-out position (Rotation)") +//TO_DO_BATTLE_TEST("Delta Stream doesn't activate if is rotated-in (Rotation)") +TO_DO_BATTLE_TEST("Delta Stream doesn't activate if there's already strong winds") +TO_DO_BATTLE_TEST("Strong winds continue as long as there's a Pokémon with Delta Stream on the field") // Doesn't need to be the original mon diff --git a/test/battle/ability/desolate_land.c b/test/battle/ability/desolate_land.c index b7cc02d47e..d9f1e3924a 100644 --- a/test/battle/ability/desolate_land.c +++ b/test/battle/ability/desolate_land.c @@ -98,3 +98,15 @@ SINGLE_BATTLE_TEST("Desolate Land is removed immediately if user faints") MESSAGE("The extremely harsh sunlight faded!"); } } + +TO_DO_BATTLE_TEST("Desolate Land makes Sunny Day fail") +TO_DO_BATTLE_TEST("Desolate Land makes Rain Dance fail") +TO_DO_BATTLE_TEST("Desolate Land makes Sandstorm fail") +TO_DO_BATTLE_TEST("Desolate Land makes Hail fail") +TO_DO_BATTLE_TEST("Desolate Land makes Snowscape fail") // Extrapolation +TO_DO_BATTLE_TEST("Desolate Land makes Drought fail to activate") +TO_DO_BATTLE_TEST("Desolate Land makes Drizzle fail to activate") +TO_DO_BATTLE_TEST("Desolate Land makes Sand Stream fail to activate") +TO_DO_BATTLE_TEST("Desolate Land makes Snow Warning fail to activate") +TO_DO_BATTLE_TEST("Desolate Land can be replaced by Delta Stream") +TO_DO_BATTLE_TEST("Desolate Land can be replaced by Primordial Sea") diff --git a/test/battle/ability/disguise.c b/test/battle/ability/disguise.c index 0d73fdf9ae..d77f94c1db 100644 --- a/test/battle/ability/disguise.c +++ b/test/battle/ability/disguise.c @@ -9,7 +9,7 @@ ASSUMPTIONS SINGLE_BATTLE_TEST("Disguised Mimikyu doesn't lose 1/8 of its max HP upon changing to its busted form (Gen7)") { GIVEN { - WITH_CONFIG(GEN_CONFIG_DISGUISE_HP_LOSS, GEN_7); + WITH_CONFIG(CONFIG_DISGUISE_HP_LOSS, GEN_7); PLAYER(SPECIES_MIMIKYU_DISGUISED) { Ability(ABILITY_DISGUISE); } OPPONENT(SPECIES_WOBBUFFET); } WHEN { @@ -29,7 +29,7 @@ SINGLE_BATTLE_TEST("Disguised Mimikyu will lose 1/8 of its max HP upon changing s16 disguiseDamage; GIVEN { - WITH_CONFIG(GEN_CONFIG_DISGUISE_HP_LOSS, GEN_8); + WITH_CONFIG(CONFIG_DISGUISE_HP_LOSS, GEN_8); PLAYER(SPECIES_MIMIKYU_DISGUISED) { Ability(ABILITY_DISGUISE); } OPPONENT(SPECIES_WOBBUFFET); } WHEN { @@ -85,7 +85,7 @@ SINGLE_BATTLE_TEST("Disguised Mimikyu's Air Balloon will pop upon changing to it } } -SINGLE_BATTLE_TEST("Disguised Mimikyu takes damage from secondary damage without breaking the disguise") +SINGLE_BATTLE_TEST("Disguised Mimikyu takes damage from secondary damage without breaking the disguise - Stealth Rock") { GIVEN { ASSUME(GetMoveEffect(MOVE_STEALTH_ROCK) == EFFECT_STEALTH_ROCK); @@ -104,6 +104,8 @@ SINGLE_BATTLE_TEST("Disguised Mimikyu takes damage from secondary damage without } } +TO_DO_BATTLE_TEST("Disguised Mimikyu takes damage from secondary damage without breaking the disguise - Weather") + SINGLE_BATTLE_TEST("Disguised Mimikyu takes damage from Rocky Helmet without breaking the disguise") { GIVEN { diff --git a/test/battle/ability/download.c b/test/battle/ability/download.c index 7219e32329..f275b7c262 100644 --- a/test/battle/ability/download.c +++ b/test/battle/ability/download.c @@ -9,7 +9,7 @@ ASSUMPTIONS SINGLE_BATTLE_TEST("Download raises Attack if player has lower Def than Sp. Def", s16 damage) { - u32 ability; + enum Ability ability; PARAMETRIZE { ability = ABILITY_TRACE; } PARAMETRIZE { ability = ABILITY_DOWNLOAD; } GIVEN { @@ -32,7 +32,7 @@ SINGLE_BATTLE_TEST("Download raises Attack if player has lower Def than Sp. Def" SINGLE_BATTLE_TEST("Download raises Sp.Attack if enemy has lower Sp. Def than Def", s16 damage) { - u32 ability; + enum Ability ability; PARAMETRIZE { ability = ABILITY_TRACE; } PARAMETRIZE { ability = ABILITY_DOWNLOAD; } GIVEN { @@ -55,7 +55,7 @@ SINGLE_BATTLE_TEST("Download raises Sp.Attack if enemy has lower Sp. Def than De SINGLE_BATTLE_TEST("Download doesn't activate if target hasn't been sent out yet", s16 damagePhysical, s16 damageSpecial) { - u32 ability; + enum Ability ability; PARAMETRIZE { ability = ABILITY_TRACE; } PARAMETRIZE { ability = ABILITY_DOWNLOAD; } @@ -97,7 +97,7 @@ SINGLE_BATTLE_TEST("Download doesn't activate if target hasn't been sent out yet DOUBLE_BATTLE_TEST("Download raises Sp.Attack if enemies have lower total Sp. Def than Def", s16 damage) { - u32 ability; + enum Ability ability; PARAMETRIZE { ability = ABILITY_TRACE; } PARAMETRIZE { ability = ABILITY_DOWNLOAD; } GIVEN { diff --git a/test/battle/ability/dragons_maw.c b/test/battle/ability/dragons_maw.c index 64280cfb5a..950cb1db0f 100644 --- a/test/battle/ability/dragons_maw.c +++ b/test/battle/ability/dragons_maw.c @@ -4,7 +4,7 @@ SINGLE_BATTLE_TEST("Dragon's Maw increases Dragon-type move damage", s16 damage) { u32 move; - u16 ability; + enum Ability ability; PARAMETRIZE { move = MOVE_SCRATCH; ability = ABILITY_KLUTZ; } PARAMETRIZE { move = MOVE_SCRATCH; ability = ABILITY_DRAGONS_MAW; } diff --git a/test/battle/ability/drizzle.c b/test/battle/ability/drizzle.c index ce0fc9514b..fd56704830 100644 --- a/test/battle/ability/drizzle.c +++ b/test/battle/ability/drizzle.c @@ -3,7 +3,7 @@ SINGLE_BATTLE_TEST("Drizzle summons rain", s16 damage) { - u32 ability; + enum Ability ability; PARAMETRIZE { ability = ABILITY_DRIZZLE; } PARAMETRIZE { ability = ABILITY_DAMP; } diff --git a/test/battle/ability/drought.c b/test/battle/ability/drought.c index c28b0895b8..ba78643b50 100644 --- a/test/battle/ability/drought.c +++ b/test/battle/ability/drought.c @@ -4,7 +4,7 @@ SINGLE_BATTLE_TEST("Drought sets up sun for 5 turns (Gen6+)") { GIVEN { - WITH_CONFIG(GEN_CONFIG_ABILITY_WEATHER, GEN_6); + WITH_CONFIG(CONFIG_ABILITY_WEATHER, GEN_6); PLAYER(SPECIES_NINETALES) { Moves(MOVE_CELEBRATE); Ability(ABILITY_DROUGHT); } OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_CELEBRATE); } } WHEN { @@ -26,7 +26,7 @@ SINGLE_BATTLE_TEST("Drought sets up sun for 5 turns (Gen6+)") SINGLE_BATTLE_TEST("Drought sets up sun for 8 turns with Heat Rock (Gen6+)") { GIVEN { - WITH_CONFIG(GEN_CONFIG_ABILITY_WEATHER, GEN_6); + WITH_CONFIG(CONFIG_ABILITY_WEATHER, GEN_6); PLAYER(SPECIES_NINETALES) { Moves(MOVE_CELEBRATE); Ability(ABILITY_DROUGHT); Item(ITEM_HEAT_ROCK); } OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_CELEBRATE); } } WHEN { @@ -54,7 +54,7 @@ SINGLE_BATTLE_TEST("Drought sets up sun for 8 turns with Heat Rock (Gen6+)") SINGLE_BATTLE_TEST("Drought sets up permanent sun (Gen3-5)") { GIVEN { - WITH_CONFIG(GEN_CONFIG_ABILITY_WEATHER, GEN_3); + WITH_CONFIG(CONFIG_ABILITY_WEATHER, GEN_3); PLAYER(SPECIES_NINETALES) { Moves(MOVE_CELEBRATE); Ability(ABILITY_DROUGHT); } OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_CELEBRATE); } } WHEN { diff --git a/test/battle/ability/dry_skin.c b/test/battle/ability/dry_skin.c index 097251565f..aab5658618 100644 --- a/test/battle/ability/dry_skin.c +++ b/test/battle/ability/dry_skin.c @@ -35,7 +35,7 @@ TO_DO_BATTLE_TEST("Dry Skin doesn't heal in Rain if Cloud Nine/Air Lock is on th SINGLE_BATTLE_TEST("Dry Skin increases damage taken from Fire-type moves by 25%", s16 damage) { - u32 ability; + enum Ability ability; PARAMETRIZE { ability = ABILITY_EFFECT_SPORE; } PARAMETRIZE { ability = ABILITY_DRY_SKIN; } GIVEN { diff --git a/test/battle/ability/embody_aspect.c b/test/battle/ability/embody_aspect.c index fffc8cf423..e7ac53a9e8 100644 --- a/test/battle/ability/embody_aspect.c +++ b/test/battle/ability/embody_aspect.c @@ -4,7 +4,8 @@ SINGLE_BATTLE_TEST("Embody Aspect raises a stat depending on the users form by one stage") { - u16 species, ability; + u16 species; + enum Ability ability; PARAMETRIZE { species = SPECIES_OGERPON_TEAL_TERA; ability = ABILITY_EMBODY_ASPECT_TEAL_MASK; } PARAMETRIZE { species = SPECIES_OGERPON_HEARTHFLAME_TERA; ability = ABILITY_EMBODY_ASPECT_HEARTHFLAME_MASK; } diff --git a/test/battle/ability/emergency_exit.c b/test/battle/ability/emergency_exit.c index 1dcd0be21b..3592b91b01 100644 --- a/test/battle/ability/emergency_exit.c +++ b/test/battle/ability/emergency_exit.c @@ -81,6 +81,23 @@ SINGLE_BATTLE_TEST("Emergency Exit activates when taking residual damage and fal } } +SINGLE_BATTLE_TEST("Emergency Exit activates when healing from under 50% max-hp and taking residual damage to under 50% max-hp - Burn") +{ + // Might fail if users set healing higher than burn damage + GIVEN { + ASSUME(GetMoveEffect(MOVE_AQUA_RING) == EFFECT_AQUA_RING); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_GOLISOPOD) { Ability(ABILITY_EMERGENCY_EXIT); MaxHP(263); HP(130); Status1(STATUS1_BURN); }; + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_AQUA_RING); SEND_OUT(opponent, 1); } + } SCENE { + HP_BAR(opponent); + HP_BAR(opponent); + ABILITY_POPUP(opponent, ABILITY_EMERGENCY_EXIT); + } +} + SINGLE_BATTLE_TEST("Emergency Exit activates when taking residual damage and falling under 50% max-hp - Weather") { GIVEN { @@ -95,6 +112,24 @@ SINGLE_BATTLE_TEST("Emergency Exit activates when taking residual damage and fal } } +SINGLE_BATTLE_TEST("Emergency Exit activates when healing from under 50% max-hp and taking residual damage to under 50% max-hp - Sticky Barb") +{ + // Might fail if users set healing higher than sticky barb damage + GIVEN { + ASSUME(GetMoveEffect(MOVE_AQUA_RING) == EFFECT_AQUA_RING); + ASSUME(GetItemHoldEffect(ITEM_STICKY_BARB) == HOLD_EFFECT_STICKY_BARB); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_GOLISOPOD) { Ability(ABILITY_EMERGENCY_EXIT); MaxHP(263); HP(130); Item(ITEM_STICKY_BARB); }; + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_AQUA_RING); SEND_OUT(opponent, 1); } + } SCENE { + HP_BAR(opponent); + HP_BAR(opponent); + ABILITY_POPUP(opponent, ABILITY_EMERGENCY_EXIT); + } +} + SINGLE_BATTLE_TEST("Emergency Exit activates when taking residual damage and falling under 50% max-hp - Salt Cure") { GIVEN { diff --git a/test/battle/ability/filter.c b/test/battle/ability/filter.c index 69c0e96278..db3d353b79 100644 --- a/test/battle/ability/filter.c +++ b/test/battle/ability/filter.c @@ -3,7 +3,7 @@ SINGLE_BATTLE_TEST("Filter reduces damage to Super Effective moves by 0.75", s16 damage) { - u32 ability; + enum Ability ability; PARAMETRIZE { ability = ABILITY_SOUNDPROOF; } PARAMETRIZE { ability = ABILITY_FILTER; } GIVEN { diff --git a/test/battle/ability/flower_gift.c b/test/battle/ability/flower_gift.c index 29f5820191..30cc7926e5 100644 --- a/test/battle/ability/flower_gift.c +++ b/test/battle/ability/flower_gift.c @@ -65,7 +65,8 @@ SINGLE_BATTLE_TEST("Flower Gift transforms Cherrim back to normal when its abili SINGLE_BATTLE_TEST("Flower Gift transforms Cherrim back to normal under Cloud Nine/Air Lock") { - u32 species = 0, ability = 0; + u32 species = 0; + enum Ability ability = 0; PARAMETRIZE { species = SPECIES_PSYDUCK; ability = ABILITY_CLOUD_NINE; } PARAMETRIZE { species = SPECIES_RAYQUAZA; ability = ABILITY_AIR_LOCK; } GIVEN { diff --git a/test/battle/ability/fluffy.c b/test/battle/ability/fluffy.c index 6525c73212..68afbd8993 100644 --- a/test/battle/ability/fluffy.c +++ b/test/battle/ability/fluffy.c @@ -12,7 +12,7 @@ ASSUMPTIONS SINGLE_BATTLE_TEST("Fluffy halves damage taken from moves that make direct contact", s16 damage) { - u32 ability; + enum Ability ability; PARAMETRIZE { ability = ABILITY_KLUTZ; } PARAMETRIZE { ability = ABILITY_FLUFFY; } GIVEN { @@ -30,7 +30,7 @@ SINGLE_BATTLE_TEST("Fluffy halves damage taken from moves that make direct conta SINGLE_BATTLE_TEST("Fluffy doubles damage taken from fire type moves", s16 damage) { - u32 ability; + enum Ability ability; PARAMETRIZE { ability = ABILITY_KLUTZ; } PARAMETRIZE { ability = ABILITY_FLUFFY; } GIVEN { @@ -48,7 +48,7 @@ SINGLE_BATTLE_TEST("Fluffy doubles damage taken from fire type moves", s16 damag SINGLE_BATTLE_TEST("Fluffy does not alter damage of fire-type moves that make direct contact", s16 damage) { - u32 ability; + enum Ability ability; PARAMETRIZE { ability = ABILITY_KLUTZ; } PARAMETRIZE { ability = ABILITY_FLUFFY; } GIVEN { @@ -66,7 +66,7 @@ SINGLE_BATTLE_TEST("Fluffy does not alter damage of fire-type moves that make di SINGLE_BATTLE_TEST("Fluffy halves damage taken from moves that make direct contact even if protected by Protective Pads", s16 damage) { - u32 ability; + enum Ability ability; PARAMETRIZE { ability = ABILITY_KLUTZ; } PARAMETRIZE { ability = ABILITY_FLUFFY; } GIVEN { @@ -84,7 +84,7 @@ SINGLE_BATTLE_TEST("Fluffy halves damage taken from moves that make direct conta SINGLE_BATTLE_TEST("Fluffy does not halve damage taken from moves that make direct contact but are ignored by Punching Glove", s16 damage) { - u32 ability; + enum Ability ability; PARAMETRIZE { ability = ABILITY_KLUTZ; } PARAMETRIZE { ability = ABILITY_FLUFFY; } GIVEN { diff --git a/test/battle/ability/forecast.c b/test/battle/ability/forecast.c index 418c8058d2..b6889620ab 100644 --- a/test/battle/ability/forecast.c +++ b/test/battle/ability/forecast.c @@ -157,7 +157,8 @@ DOUBLE_BATTLE_TEST("Forecast transforms all Castforms present in weather") SINGLE_BATTLE_TEST("Forecast transforms Castform in weather from an ability") { - u32 species, ability; + u32 species; + enum Ability ability; PARAMETRIZE { species = SPECIES_KYOGRE; ability = ABILITY_DRIZZLE; } PARAMETRIZE { species = SPECIES_GROUDON; ability = ABILITY_DROUGHT; } PARAMETRIZE { species = SPECIES_ABOMASNOW; ability = ABILITY_SNOW_WARNING; } @@ -183,13 +184,16 @@ SINGLE_BATTLE_TEST("Forecast transforms Castform in weather from an ability") case ABILITY_SNOW_WARNING: EXPECT_EQ(player->species, SPECIES_CASTFORM_SNOWY); break; + default: + break; } } } SINGLE_BATTLE_TEST("Forecast transforms Castform in primal weather") { - u32 species, item, ability; + u32 species, item; + enum Ability ability; PARAMETRIZE { species = SPECIES_KYOGRE; ability = ABILITY_PRIMORDIAL_SEA; item = ITEM_BLUE_ORB; } PARAMETRIZE { species = SPECIES_GROUDON; ability = ABILITY_DESOLATE_LAND; item = ITEM_RED_ORB; } GIVEN { @@ -212,6 +216,8 @@ SINGLE_BATTLE_TEST("Forecast transforms Castform in primal weather") case ABILITY_PRIMORDIAL_SEA: EXPECT_EQ(player->species, SPECIES_CASTFORM_RAINY); break; + default: + break; } } } @@ -266,7 +272,8 @@ SINGLE_BATTLE_TEST("Forecast transforms Castform back to normal when Sandstorm i SINGLE_BATTLE_TEST("Forecast transforms Castform back to normal under Cloud Nine/Air Lock") { - u32 species = 0, ability = 0; + u32 species = 0; + enum Ability ability = 0; PARAMETRIZE { species = SPECIES_PSYDUCK; ability = ABILITY_CLOUD_NINE; } PARAMETRIZE { species = SPECIES_RAYQUAZA; ability = ABILITY_AIR_LOCK; } GIVEN { @@ -400,7 +407,8 @@ SINGLE_BATTLE_TEST("Forecast transforms Castform back when it uses a move that f SINGLE_BATTLE_TEST("Forecast transforms Castform when Cloud Nine ability user leaves the field") { - u32 species = 0, ability = 0; + u32 species = 0; + enum Ability ability = 0; PARAMETRIZE { species = SPECIES_PSYDUCK; ability = ABILITY_CLOUD_NINE; } PARAMETRIZE { species = SPECIES_RAYQUAZA; ability = ABILITY_AIR_LOCK; } diff --git a/test/battle/ability/gale_wings.c b/test/battle/ability/gale_wings.c index df8f025326..be82da81d4 100644 --- a/test/battle/ability/gale_wings.c +++ b/test/battle/ability/gale_wings.c @@ -9,7 +9,7 @@ SINGLE_BATTLE_TEST("Gale Wings only grants priority at full HP (Gen 7+)") PARAMETRIZE { hp = 100; config = GEN_6; } PARAMETRIZE { hp = 99; config = GEN_6; } GIVEN { - WITH_CONFIG(GEN_CONFIG_GALE_WINGS, config); + WITH_CONFIG(CONFIG_GALE_WINGS, config); ASSUME(GetMoveType(MOVE_AERIAL_ACE) == TYPE_FLYING); PLAYER(SPECIES_TALONFLAME) { Ability(ABILITY_GALE_WINGS); HP(hp); MaxHP(100); Speed(1);} OPPONENT(SPECIES_WOBBUFFET) { Speed(100);}; diff --git a/test/battle/ability/galvanize.c b/test/battle/ability/galvanize.c index e6569aedaf..bbfa6c3cfb 100644 --- a/test/battle/ability/galvanize.c +++ b/test/battle/ability/galvanize.c @@ -44,14 +44,15 @@ SINGLE_BATTLE_TEST("Galvanize can not turn certain moves into Electric type move SINGLE_BATTLE_TEST("Galvanize boosts power of affected moves by 20% (Gen7+) or 30% (Gen1-6)", s16 damage) { - u32 ability, genConfig; + enum Ability ability; + u32 genConfig; PARAMETRIZE { ability = ABILITY_STURDY; genConfig = GEN_7; } PARAMETRIZE { ability = ABILITY_STURDY; genConfig = GEN_6; } PARAMETRIZE { ability = ABILITY_GALVANIZE; genConfig = GEN_7; } PARAMETRIZE { ability = ABILITY_GALVANIZE; genConfig = GEN_6; } GIVEN { - WITH_CONFIG(GEN_CONFIG_ATE_MULTIPLIER, genConfig); + WITH_CONFIG(CONFIG_ATE_MULTIPLIER, genConfig); PLAYER(SPECIES_GEODUDE_ALOLA) { Ability(ability); Moves(MOVE_TACKLE); } OPPONENT(SPECIES_WOBBUFFET); } WHEN { @@ -68,7 +69,8 @@ SINGLE_BATTLE_TEST("Galvanize boosts power of affected moves by 20% (Gen7+) or 3 SINGLE_BATTLE_TEST("Galvanize doesn't affect Weather Ball's type", s16 damage) { - u16 move, ability; + u16 move; + enum Ability ability; PARAMETRIZE { move = MOVE_CELEBRATE; ability = ABILITY_STURDY; } PARAMETRIZE { move = MOVE_SUNNY_DAY; ability = ABILITY_STURDY; } PARAMETRIZE { move = MOVE_CELEBRATE; ability = ABILITY_GALVANIZE; } @@ -96,7 +98,7 @@ SINGLE_BATTLE_TEST("Galvanize doesn't affect Weather Ball's type", s16 damage) SINGLE_BATTLE_TEST("Galvanize doesn't affect Natural Gift's type") { - u16 ability; + enum Ability ability; PARAMETRIZE { ability = ABILITY_STURDY; } PARAMETRIZE { ability = ABILITY_GALVANIZE; } GIVEN { diff --git a/test/battle/ability/grim_neigh.c b/test/battle/ability/grim_neigh.c index 69d60db93e..bb212e589b 100644 --- a/test/battle/ability/grim_neigh.c +++ b/test/battle/ability/grim_neigh.c @@ -3,7 +3,8 @@ 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; + u32 species = 0, abilityPopUp = 0; + enum Ability ability = 0; PARAMETRIZE { species = SPECIES_SPECTRIER; ability = ABILITY_GRIM_NEIGH; abilityPopUp = ABILITY_GRIM_NEIGH; } PARAMETRIZE { species = SPECIES_CALYREX_SHADOW; ability = ABILITY_AS_ONE_SHADOW_RIDER; abilityPopUp = ABILITY_GRIM_NEIGH; } GIVEN { @@ -33,7 +34,8 @@ DOUBLE_BATTLE_TEST("Grim Neigh raises Sp. Attack by one stage after directly cau 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; + u32 species = 0, abilityPopUp = 0; + enum Ability ability = 0; PARAMETRIZE { species = SPECIES_SPECTRIER; ability = ABILITY_GRIM_NEIGH; abilityPopUp = ABILITY_GRIM_NEIGH; } PARAMETRIZE { species = SPECIES_CALYREX_SHADOW; ability = ABILITY_AS_ONE_SHADOW_RIDER; abilityPopUp = ABILITY_GRIM_NEIGH; } GIVEN { @@ -70,7 +72,8 @@ DOUBLE_BATTLE_TEST("Grim Neigh does not trigger if Pokemon faint to indirect dam 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; + u32 species = 0, abilityPopUp = 0; + enum Ability ability = 0; PARAMETRIZE { species = SPECIES_SPECTRIER; ability = ABILITY_GRIM_NEIGH; abilityPopUp = ABILITY_GRIM_NEIGH; } PARAMETRIZE { species = SPECIES_CALYREX_SHADOW; ability = ABILITY_AS_ONE_SHADOW_RIDER; abilityPopUp = ABILITY_GRIM_NEIGH; } diff --git a/test/battle/ability/guard_dog.c b/test/battle/ability/guard_dog.c index 4327140d68..b8ebbafbad 100644 --- a/test/battle/ability/guard_dog.c +++ b/test/battle/ability/guard_dog.c @@ -3,7 +3,7 @@ SINGLE_BATTLE_TEST("Guard Dog raises Attack when intimidated", s16 damage) { - u32 ability; + enum Ability ability; PARAMETRIZE { ability = ABILITY_INTIMIDATE; } PARAMETRIZE { ability = ABILITY_SHED_SKIN; } GIVEN { diff --git a/test/battle/ability/gulp_missile.c b/test/battle/ability/gulp_missile.c index fe1bc718fd..5a3266ff17 100644 --- a/test/battle/ability/gulp_missile.c +++ b/test/battle/ability/gulp_missile.c @@ -137,13 +137,14 @@ SINGLE_BATTLE_TEST("(Gulp Missile) triggers even if the user is fainted by oppos SINGLE_BATTLE_TEST("(Gulp Missile) Transformed Cramorant Gulping lowers defense but is prevented by stat reduction preventing abilities") { - u32 species, ability; + u32 species; + enum Ability ability; PARAMETRIZE { species = SPECIES_METAGROSS; ability = ABILITY_CLEAR_BODY; } PARAMETRIZE { species = SPECIES_CORVIKNIGHT; ability = ABILITY_MIRROR_ARMOR; } PARAMETRIZE { species = SPECIES_CHATOT; ability = ABILITY_BIG_PECKS; } GIVEN { PLAYER(SPECIES_CRAMORANT) { Ability(ABILITY_GULP_MISSILE); } - OPPONENT(species) { Ability(ability); } + OPPONENT(species) { Ability(ability); HP(9999); MaxHP(9999); } // In Gen 5 data, Surf would be enough to knock out Chatot } WHEN { TURN { MOVE(player, MOVE_SURF); MOVE(opponent, MOVE_SCRATCH); } } SCENE { @@ -163,7 +164,7 @@ SINGLE_BATTLE_TEST("(Gulp Missile) Transformed Cramorant Gulping lowers defense SINGLE_BATTLE_TEST("(Gulp Missile) Transformed Cramorant Gulping lowers defense and still triggers other effects after") { // Make sure attacker and target are correct after triggering the ability - u32 ability; + enum Ability ability; PARAMETRIZE { ability = ABILITY_INFILTRATOR; } PARAMETRIZE { ability = ABILITY_CLEAR_BODY; } GIVEN { diff --git a/test/battle/ability/ice_scales.c b/test/battle/ability/ice_scales.c index 0d49bb4996..ea96f64961 100644 --- a/test/battle/ability/ice_scales.c +++ b/test/battle/ability/ice_scales.c @@ -4,7 +4,7 @@ SINGLE_BATTLE_TEST("Ice Scales halves the damage from special moves", s16 damage) { u32 move; - u16 ability; + enum Ability ability; PARAMETRIZE { ability = ABILITY_SHIELD_DUST; move = MOVE_PSYCHIC; } PARAMETRIZE { ability = ABILITY_ICE_SCALES; move = MOVE_PSYCHIC; } PARAMETRIZE { ability = ABILITY_SHIELD_DUST; move = MOVE_PSYSHOCK; } diff --git a/test/battle/ability/illusion.c b/test/battle/ability/illusion.c index 56fad1b62e..efa80cdafe 100644 --- a/test/battle/ability/illusion.c +++ b/test/battle/ability/illusion.c @@ -102,7 +102,7 @@ SINGLE_BATTLE_TEST("Illusion breaks if affected by Gastro Acid") SINGLE_BATTLE_TEST("Illusion breaks if user loses Illusion due to Worry Seed") { GIVEN { - ASSUME(GetMoveEffect(MOVE_WORRY_SEED) == EFFECT_WORRY_SEED); + ASSUME(GetMoveEffect(MOVE_WORRY_SEED) == EFFECT_OVERWRITE_ABILITY); PLAYER(SPECIES_ZOROARK); PLAYER(SPECIES_WYNAUT); OPPONENT(SPECIES_WOBBUFFET); @@ -113,3 +113,20 @@ SINGLE_BATTLE_TEST("Illusion breaks if user loses Illusion due to Worry Seed") ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_ILLUSION_OFF, player); } } + +SINGLE_BATTLE_TEST("Illusion breaks when attacked behind a substitute") +{ + GIVEN { + PLAYER(SPECIES_DRAGAPULT) {Ability(ABILITY_INFILTRATOR); Speed(1);}; + OPPONENT(SPECIES_WOBBUFFET) {Speed(2);}; + OPPONENT(SPECIES_ZOROARK) {Speed(2);}; + OPPONENT(SPECIES_WYNAUT) {Speed(2);}; + } WHEN { + TURN { MOVE(player, MOVE_TACKLE); MOVE(opponent, MOVE_SHED_TAIL); SEND_OUT(opponent, 1);} + } SCENE { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_SWAP_FROM_SUBSTITUTE, opponent); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_ILLUSION_OFF, opponent); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_SWAP_TO_SUBSTITUTE, opponent); + MESSAGE("The opposing Zoroark's illusion wore off!"); + } +} diff --git a/test/battle/ability/immunity.c b/test/battle/ability/immunity.c index e18aef667c..9199638ad5 100644 --- a/test/battle/ability/immunity.c +++ b/test/battle/ability/immunity.c @@ -27,7 +27,7 @@ SINGLE_BATTLE_TEST("Immunity prevents Toxic bad poison") } SCENE { MESSAGE("Wobbuffet used Toxic!"); ABILITY_POPUP(opponent, ABILITY_IMMUNITY); - MESSAGE("The opposing Snorlax's Immunity prevents poisoning!"); + MESSAGE("It doesn't affect the opposing Snorlax…"); NOT STATUS_ICON(opponent, poison: TRUE); } } diff --git a/test/battle/ability/inner_focus.c b/test/battle/ability/inner_focus.c index 75c7c113d0..7280725e88 100644 --- a/test/battle/ability/inner_focus.c +++ b/test/battle/ability/inner_focus.c @@ -7,7 +7,7 @@ SINGLE_BATTLE_TEST("Inner Focus doesn't prevent intimidate (Gen3-7)") s16 turnTwoHit; GIVEN { - WITH_CONFIG(GEN_CONFIG_UPDATED_INTIMIDATE, GEN_7); + WITH_CONFIG(CONFIG_UPDATED_INTIMIDATE, GEN_7); PLAYER(SPECIES_EKANS) { Ability(ABILITY_SHED_SKIN); }; PLAYER(SPECIES_EKANS) { Ability(ABILITY_INTIMIDATE); }; OPPONENT(SPECIES_ZUBAT) { Ability(ABILITY_INNER_FOCUS); }; @@ -34,7 +34,7 @@ SINGLE_BATTLE_TEST("Inner Focus prevents intimidate (Gen8+)") s16 turnTwoHit; GIVEN { - WITH_CONFIG(GEN_CONFIG_UPDATED_INTIMIDATE, GEN_8); + WITH_CONFIG(CONFIG_UPDATED_INTIMIDATE, GEN_8); PLAYER(SPECIES_EKANS) { Ability(ABILITY_SHED_SKIN); }; PLAYER(SPECIES_EKANS) { Ability(ABILITY_INTIMIDATE); }; OPPONENT(SPECIES_ZUBAT) { Ability(ABILITY_INNER_FOCUS); }; diff --git a/test/battle/ability/intimidate.c b/test/battle/ability/intimidate.c index b0e4b19a19..0606938d45 100644 --- a/test/battle/ability/intimidate.c +++ b/test/battle/ability/intimidate.c @@ -8,7 +8,7 @@ ASSUMPTIONS SINGLE_BATTLE_TEST("Intimidate (opponent) lowers player's attack after switch out", s16 damage) { - u32 ability; + enum Ability ability; PARAMETRIZE { ability = ABILITY_INTIMIDATE; } PARAMETRIZE { ability = ABILITY_SHED_SKIN; } GIVEN { @@ -33,7 +33,7 @@ SINGLE_BATTLE_TEST("Intimidate (opponent) lowers player's attack after switch ou SINGLE_BATTLE_TEST("Intimidate (opponent) lowers player's attack after KO", s16 damage) { - u32 ability; + enum Ability ability; PARAMETRIZE { ability = ABILITY_INTIMIDATE; } PARAMETRIZE { ability = ABILITY_SHED_SKIN; } GIVEN { diff --git a/test/battle/ability/intrepid_sword.c b/test/battle/ability/intrepid_sword.c index a260e78d0d..1fc461ebcd 100644 --- a/test/battle/ability/intrepid_sword.c +++ b/test/battle/ability/intrepid_sword.c @@ -20,7 +20,7 @@ SINGLE_BATTLE_TEST("Intrepid Sword raises Attack by one stage") SINGLE_BATTLE_TEST("Intrepid Sword raises Attack by one stage every time it switches in (Gen8)") { GIVEN { - WITH_CONFIG(GEN_INTREPID_SWORD, GEN_8); + WITH_CONFIG(CONFIG_INTREPID_SWORD, GEN_8); PLAYER(SPECIES_WOBBUFFET); OPPONENT(SPECIES_ZACIAN) { Ability(ABILITY_INTREPID_SWORD); } OPPONENT(SPECIES_WYNAUT); @@ -42,7 +42,7 @@ SINGLE_BATTLE_TEST("Intrepid Sword raises Attack by one stage every time it swit SINGLE_BATTLE_TEST("Intrepid Sword raises Attack by one stage only once per battle (Gen9+)") { GIVEN { - WITH_CONFIG(GEN_INTREPID_SWORD, GEN_9); + WITH_CONFIG(CONFIG_INTREPID_SWORD, GEN_9); PLAYER(SPECIES_WOBBUFFET); OPPONENT(SPECIES_ZACIAN) { Ability(ABILITY_INTREPID_SWORD); } OPPONENT(SPECIES_WYNAUT); diff --git a/test/battle/ability/keen_eye.c b/test/battle/ability/keen_eye.c index ee10c446fb..7dbef04ee8 100644 --- a/test/battle/ability/keen_eye.c +++ b/test/battle/ability/keen_eye.c @@ -9,7 +9,7 @@ ASSUMPTIONS SINGLE_BATTLE_TEST("Keen Eye, Gen9+ Illuminate & Minds Eye prevent accuracy stage reduction from moves") { - u16 ability; + enum Ability ability; u32 species; PARAMETRIZE { species = SPECIES_HITMONCHAN; ability = ABILITY_KEEN_EYE; } @@ -18,7 +18,7 @@ SINGLE_BATTLE_TEST("Keen Eye, Gen9+ Illuminate & Minds Eye prevent accuracy stag PASSES_RANDOMLY(100, 100, RNG_ACCURACY); GIVEN { - WITH_CONFIG(GEN_ILLUMINATE_EFFECT, GEN_9); + WITH_CONFIG(CONFIG_ILLUMINATE_EFFECT, GEN_9); PLAYER(SPECIES_WOBBUFFET); OPPONENT(species) { Ability(ability); } } WHEN { @@ -38,7 +38,7 @@ SINGLE_BATTLE_TEST("Keen Eye, Gen9+ Illuminate & Minds Eye prevent accuracy stag SINGLE_BATTLE_TEST("Keen Eye, Gen9+ Illuminate & Minds Eye ignore target's evasion stat") { - u16 ability; + enum Ability ability; u32 species; PARAMETRIZE { species = SPECIES_HITMONCHAN; ability = ABILITY_KEEN_EYE; } @@ -47,7 +47,7 @@ SINGLE_BATTLE_TEST("Keen Eye, Gen9+ Illuminate & Minds Eye ignore target's evasi PASSES_RANDOMLY(100, 100, RNG_ACCURACY); GIVEN { - WITH_CONFIG(GEN_ILLUMINATE_EFFECT, GEN_9); + WITH_CONFIG(CONFIG_ILLUMINATE_EFFECT, GEN_9); ASSUME(GetMoveEffect(MOVE_DOUBLE_TEAM) == EFFECT_EVASION_UP); PLAYER(SPECIES_WOBBUFFET); OPPONENT(species) { Ability(ability); } @@ -62,7 +62,7 @@ SINGLE_BATTLE_TEST("Keen Eye, Gen9+ Illuminate & Minds Eye ignore target's evasi SINGLE_BATTLE_TEST("Keen Eye, Gen9+ Illuminate & Minds Eye are ignored by Mold Breaker abilities") { - u16 abilityPlayer = ABILITY_NONE, abilityOpponent = ABILITY_NONE; + enum Ability abilityPlayer = ABILITY_NONE, abilityOpponent = ABILITY_NONE; u16 speciesPlayer = SPECIES_NONE, speciesOpponent = SPECIES_NONE; u32 j; @@ -81,7 +81,7 @@ SINGLE_BATTLE_TEST("Keen Eye, Gen9+ Illuminate & Minds Eye are ignored by Mold B PASSES_RANDOMLY(GetMoveAccuracy(MOVE_SCRATCH) * 3 / 4, 100, RNG_ACCURACY); GIVEN { - WITH_CONFIG(GEN_ILLUMINATE_EFFECT, GEN_9); + WITH_CONFIG(CONFIG_ILLUMINATE_EFFECT, GEN_9); PLAYER(speciesPlayer) { Ability(abilityPlayer); } OPPONENT(speciesOpponent) { Ability(abilityOpponent); } } WHEN { @@ -96,7 +96,7 @@ SINGLE_BATTLE_TEST("Keen Eye, Gen9+ Illuminate & Minds Eye are ignored by Mold B SINGLE_BATTLE_TEST("Keen Eye, Gen9+ Illuminate & Minds Eye don't prevent Topsy-Turvy") { - u16 ability; + enum Ability ability; u32 species; PARAMETRIZE { species = SPECIES_HITMONCHAN; ability = ABILITY_KEEN_EYE; } @@ -104,7 +104,7 @@ SINGLE_BATTLE_TEST("Keen Eye, Gen9+ Illuminate & Minds Eye don't prevent Topsy-T PARAMETRIZE { species = SPECIES_URSALUNA_BLOODMOON; ability = ABILITY_MINDS_EYE; } GIVEN { - WITH_CONFIG(GEN_ILLUMINATE_EFFECT, GEN_9); + WITH_CONFIG(CONFIG_ILLUMINATE_EFFECT, GEN_9); ASSUME(GetMoveEffect(MOVE_HONE_CLAWS) == EFFECT_ATTACK_ACCURACY_UP); ASSUME(GetMoveEffect(MOVE_TOPSY_TURVY) == EFFECT_TOPSY_TURVY); PLAYER(SPECIES_WOBBUFFET); @@ -137,14 +137,14 @@ SINGLE_BATTLE_TEST("Keen Eye, Gen9+ Illuminate & Minds Eye don't prevent Topsy-T SINGLE_BATTLE_TEST("Keen Eye, Gen9+ Illuminate & Minds Eye don't prevent receiving negative Attack stage changes from Baton Pass") { - u16 ability; + enum Ability ability; u32 species; PARAMETRIZE { species = SPECIES_HITMONCHAN; ability = ABILITY_KEEN_EYE; } PARAMETRIZE { species = SPECIES_STARYU; ability = ABILITY_ILLUMINATE; } PARAMETRIZE { species = SPECIES_URSALUNA_BLOODMOON; ability = ABILITY_MINDS_EYE; } GIVEN { - WITH_CONFIG(GEN_ILLUMINATE_EFFECT, GEN_9); + WITH_CONFIG(CONFIG_ILLUMINATE_EFFECT, GEN_9); ASSUME(GetMoveEffect(MOVE_BATON_PASS) == EFFECT_BATON_PASS); PLAYER(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WOBBUFFET); @@ -170,14 +170,14 @@ SINGLE_BATTLE_TEST("Keen Eye, Gen9+ Illuminate & Minds Eye don't prevent receivi SINGLE_BATTLE_TEST("Keen Eye & Gen9+ Illuminate don't prevent Spectral Thief from resetting positive accuracy stage changes") { - u16 ability; + enum Ability ability; u32 species; PARAMETRIZE { species = SPECIES_HITMONCHAN; ability = ABILITY_KEEN_EYE; } PARAMETRIZE { species = SPECIES_STARYU; ability = ABILITY_ILLUMINATE; } GIVEN { - WITH_CONFIG(GEN_ILLUMINATE_EFFECT, GEN_9); + WITH_CONFIG(CONFIG_ILLUMINATE_EFFECT, GEN_9); ASSUME(GetMoveEffect(MOVE_HONE_CLAWS) == EFFECT_ATTACK_ACCURACY_UP); ASSUME(GetMoveEffect(MOVE_SPECTRAL_THIEF) == EFFECT_SPECTRAL_THIEF); PLAYER(SPECIES_WOBBUFFET); diff --git a/test/battle/ability/leaf_guard.c b/test/battle/ability/leaf_guard.c index 182f07787b..8efa7abdf3 100644 --- a/test/battle/ability/leaf_guard.c +++ b/test/battle/ability/leaf_guard.c @@ -121,7 +121,7 @@ SINGLE_BATTLE_TEST("Leaf Guard prevents Rest during sun (Gen 5+)") PARAMETRIZE { gen = GEN_4; } PARAMETRIZE { gen = GEN_5; } GIVEN { - WITH_CONFIG(GEN_CONFIG_LEAF_GUARD_PREVENTS_REST, gen); + WITH_CONFIG(CONFIG_LEAF_GUARD_PREVENTS_REST, gen); ASSUME(GetMoveEffect(MOVE_REST) == EFFECT_REST); PLAYER(SPECIES_LEAFEON) { Ability(ABILITY_LEAF_GUARD); HP(100); MaxHP(200); } OPPONENT(SPECIES_WOBBUFFET); @@ -151,7 +151,7 @@ SINGLE_BATTLE_TEST("Leaf Guard doesn't prevent Rest if Cloud Nine/Air Lock is on PARAMETRIZE { species = SPECIES_RAYQUAZA; ability = ABILITY_AIR_LOCK; } PARAMETRIZE { species = SPECIES_RAYQUAZA; ability = ABILITY_AIR_LOCK; } GIVEN { - WITH_CONFIG(GEN_CONFIG_LEAF_GUARD_PREVENTS_REST, GEN_5); + WITH_CONFIG(CONFIG_LEAF_GUARD_PREVENTS_REST, GEN_5); ASSUME(GetMoveEffect(MOVE_REST) == EFFECT_REST); PLAYER(SPECIES_LEAFEON) { Ability(ABILITY_LEAF_GUARD); HP(100); MaxHP(200); } OPPONENT(species) { Ability(ability); } diff --git a/test/battle/ability/levitate.c b/test/battle/ability/levitate.c index 348d347f3b..51ac0dca2c 100644 --- a/test/battle/ability/levitate.c +++ b/test/battle/ability/levitate.c @@ -92,7 +92,7 @@ DOUBLE_BATTLE_TEST("Levitate does not cause single remaining target to take high AI_SINGLE_BATTLE_TEST("Levitate is seen correctly by switch AI") { - u32 ability = ABILITY_NONE, item = ITEM_NONE; + enum Ability ability = ABILITY_NONE, item = ITEM_NONE; PARAMETRIZE { ability = ABILITY_OWN_TEMPO, item = ITEM_NONE ; } PARAMETRIZE { ability = ABILITY_MOLD_BREAKER, item = ITEM_NONE ; } diff --git a/test/battle/ability/lightning_rod.c b/test/battle/ability/lightning_rod.c index ab2f0d89a0..aec2e7fea4 100644 --- a/test/battle/ability/lightning_rod.c +++ b/test/battle/ability/lightning_rod.c @@ -28,6 +28,8 @@ SINGLE_BATTLE_TEST("Lightning Rod absorbs Electric-type moves and increases the HP_BAR(opponent); } ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponent); + } THEN { + EXPECT_EQ(gBattleHistory->abilities[1], ABILITY_LIGHTNING_ROD); // Check if the correct ability has been recorded } } diff --git a/test/battle/ability/limber.c b/test/battle/ability/limber.c index f89f9a1e74..fc4e398c1f 100644 --- a/test/battle/ability/limber.c +++ b/test/battle/ability/limber.c @@ -29,7 +29,7 @@ SINGLE_BATTLE_TEST("Limber prevents paralysis from Thunder Wave") } WHEN { TURN { MOVE(opponent, MOVE_THUNDER_WAVE); } } SCENE { - MESSAGE("Persian's Limber prevents paralysis!"); + MESSAGE("It doesn't affect Persian…"); NONE_OF { ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_PRZ, player); STATUS_ICON(player, paralysis: TRUE); diff --git a/test/battle/ability/liquid_ooze.c b/test/battle/ability/liquid_ooze.c index ca7c88ebdd..38b1428df1 100644 --- a/test/battle/ability/liquid_ooze.c +++ b/test/battle/ability/liquid_ooze.c @@ -113,7 +113,7 @@ SINGLE_BATTLE_TEST("Liquid Ooze causes Strength Sap users to lose HP instead of */ SINGLE_BATTLE_TEST("Liquid Ooze causes leech seed victim to faint before seeder") { - u16 ability; + enum Ability ability; PARAMETRIZE { ability = ABILITY_CLEAR_BODY; } PARAMETRIZE { ability = ABILITY_LIQUID_OOZE; } GIVEN { @@ -142,7 +142,7 @@ SINGLE_BATTLE_TEST("Liquid Ooze causes Dream Eater users to lose HP instead of h { s16 damage; GIVEN { - WITH_CONFIG(GEN_DREAM_EATER_LIQUID_OOZE, GEN_5); + WITH_CONFIG(CONFIG_DREAM_EATER_LIQUID_OOZE, GEN_5); ASSUME(GetMoveEffect(MOVE_SPORE) == EFFECT_NON_VOLATILE_STATUS); ASSUME(GetMoveNonVolatileStatus(MOVE_SPORE) == MOVE_EFFECT_SLEEP); ASSUME(GetMoveEffect(MOVE_DREAM_EATER) == EFFECT_DREAM_EATER); @@ -167,7 +167,7 @@ SINGLE_BATTLE_TEST("Liquid Ooze does not cause Dream Eater users to lose HP inst { s16 damage; GIVEN { - WITH_CONFIG(GEN_DREAM_EATER_LIQUID_OOZE, GEN_3); + WITH_CONFIG(CONFIG_DREAM_EATER_LIQUID_OOZE, GEN_3); ASSUME(GetMoveEffect(MOVE_SPORE) == EFFECT_NON_VOLATILE_STATUS); ASSUME(GetMoveNonVolatileStatus(MOVE_SPORE) == MOVE_EFFECT_SLEEP); ASSUME(GetMoveEffect(MOVE_DREAM_EATER) == EFFECT_DREAM_EATER); diff --git a/test/battle/ability/magic_bounce.c b/test/battle/ability/magic_bounce.c index 9ef36de4af..efc3173de6 100644 --- a/test/battle/ability/magic_bounce.c +++ b/test/battle/ability/magic_bounce.c @@ -42,7 +42,7 @@ SINGLE_BATTLE_TEST("Magic Bounce bounces back powder moves") SINGLE_BATTLE_TEST("Magic Bounce cannot bounce back powder moves against Grass Types") { GIVEN { - WITH_CONFIG(GEN_CONFIG_POWDER_GRASS, GEN_6); + WITH_CONFIG(CONFIG_POWDER_GRASS, GEN_6); ASSUME(IsPowderMove(MOVE_STUN_SPORE)); ASSUME(GetSpeciesType(SPECIES_ODDISH, 0) == TYPE_GRASS); PLAYER(SPECIES_ODDISH); diff --git a/test/battle/ability/mimicry.c b/test/battle/ability/mimicry.c index 67eab20575..5cdea7276f 100644 --- a/test/battle/ability/mimicry.c +++ b/test/battle/ability/mimicry.c @@ -13,7 +13,7 @@ SINGLE_BATTLE_TEST("Mimicry changes the battler's type based on Terrain") { u32 j; u32 terrainMove = MOVE_NONE; - u32 terrainType = TYPE_NONE; + enum Type terrainType = TYPE_NONE; for (j = 0; j < ARRAY_COUNT(terrainData); j++) PARAMETRIZE { terrainMove = terrainData[j][0]; terrainType = terrainData[j][1]; } diff --git a/test/battle/ability/minds_eye.c b/test/battle/ability/minds_eye.c index 0300c2e4d5..4ac339d899 100644 --- a/test/battle/ability/minds_eye.c +++ b/test/battle/ability/minds_eye.c @@ -44,7 +44,7 @@ SINGLE_BATTLE_TEST("Mind's Eye doesn't bypass a Ghost-type's Wonder Guard") AI_SINGLE_BATTLE_TEST("AI doesn't use accuracy-lowering moves if it knows that the foe has Mind's Eye") { - u32 abilityAI = ABILITY_NONE; + enum Ability abilityAI = ABILITY_NONE; PARAMETRIZE { abilityAI = ABILITY_SWIFT_SWIM; } PARAMETRIZE { abilityAI = ABILITY_MOLD_BREAKER; } @@ -60,7 +60,7 @@ AI_SINGLE_BATTLE_TEST("AI doesn't use accuracy-lowering moves if it knows that t if (abilityAI == ABILITY_MOLD_BREAKER) { SCORE_GT(opponent, MOVE_SAND_ATTACK, MOVE_CELEBRATE); } else { - SCORE_EQ(opponent, MOVE_SAND_ATTACK, MOVE_CELEBRATE); + SCORE_LT_VAL(opponent, MOVE_SAND_ATTACK, AI_SCORE_DEFAULT); } } } SCENE { diff --git a/test/battle/ability/mirror_armor.c b/test/battle/ability/mirror_armor.c index 7d027398f3..771df02699 100644 --- a/test/battle/ability/mirror_armor.c +++ b/test/battle/ability/mirror_armor.c @@ -5,12 +5,12 @@ SINGLE_BATTLE_TEST("Mirror Armor lowers a stat of the attacking Pokémon") { u16 move, statId; - PARAMETRIZE { move = MOVE_LEER; statId = STAT_DEF; } - PARAMETRIZE { move = MOVE_GROWL; statId = STAT_ATK; } + PARAMETRIZE { move = MOVE_LEER; statId = STAT_DEF; } + PARAMETRIZE { move = MOVE_GROWL; statId = STAT_ATK; } PARAMETRIZE { move = MOVE_SWEET_SCENT; statId = STAT_EVASION; } PARAMETRIZE { move = MOVE_SAND_ATTACK; statId = STAT_ACC; } - PARAMETRIZE { move = MOVE_CONFIDE; statId = STAT_SPATK; } - PARAMETRIZE { move = MOVE_FAKE_TEARS; statId = STAT_SPDEF; } + PARAMETRIZE { move = MOVE_CONFIDE; statId = STAT_SPATK; } + PARAMETRIZE { move = MOVE_FAKE_TEARS; statId = STAT_SPDEF; } GIVEN { PLAYER(SPECIES_CORVIKNIGHT) {Ability(ABILITY_MIRROR_ARMOR);} @@ -29,7 +29,11 @@ SINGLE_BATTLE_TEST("Mirror Armor lowers a stat of the attacking Pokémon") MESSAGE("The opposing Wynaut's Attack fell!"); break; case STAT_EVASION: - MESSAGE("The opposing Wynaut's evasiveness harshly fell!"); + if (GetMoveEffect(move) == EFFECT_EVASION_DOWN_2) { + MESSAGE("The opposing Wynaut's evasiveness harshly fell!"); + } else { + MESSAGE("The opposing Wynaut's evasiveness fell!"); + } break; case STAT_ACC: MESSAGE("The opposing Wynaut's accuracy fell!"); @@ -43,7 +47,7 @@ SINGLE_BATTLE_TEST("Mirror Armor lowers a stat of the attacking Pokémon") } } THEN { EXPECT_EQ(player->statStages[statId], DEFAULT_STAT_STAGE); - EXPECT_EQ(opponent->statStages[statId], (statId == STAT_SPDEF || statId == STAT_EVASION) ? DEFAULT_STAT_STAGE - 2 : DEFAULT_STAT_STAGE - 1); + EXPECT_EQ(opponent->statStages[statId], (statId == STAT_SPDEF || (statId == STAT_EVASION && GetMoveEffect(move) == EFFECT_EVASION_DOWN_2)) ? DEFAULT_STAT_STAGE - 2 : DEFAULT_STAT_STAGE - 1); } } diff --git a/test/battle/ability/moody.c b/test/battle/ability/moody.c index d52f6e9cee..739bee6d01 100644 --- a/test/battle/ability/moody.c +++ b/test/battle/ability/moody.c @@ -11,7 +11,7 @@ SINGLE_BATTLE_TEST("Moody randomly raises the user's Attack, Defense, Sp. Atk, S // HP is not included PASSES_RANDOMLY(1, statsNum - 1, RNG_MOODY_INCREASE); GIVEN { - WITH_CONFIG(GEN_CONFIG_MOODY_STATS, config); + WITH_CONFIG(CONFIG_MOODY_ACC_EVASION, config); PLAYER(SPECIES_OCTILLERY) { Ability(ABILITY_MOODY); } OPPONENT(SPECIES_WOBBUFFET); } WHEN { @@ -36,7 +36,7 @@ SINGLE_BATTLE_TEST("Moody randomly lowers the user's Attack, Defense, Sp. Atk, S // One stat becomes unavailable due to it already increasing PASSES_RANDOMLY(1, statsNum - 2, RNG_MOODY_DECREASE); GIVEN { - WITH_CONFIG(GEN_CONFIG_MOODY_STATS, config); + WITH_CONFIG(CONFIG_MOODY_ACC_EVASION, config); PLAYER(SPECIES_OCTILLERY) { Ability(ABILITY_MOODY); } OPPONENT(SPECIES_WOBBUFFET); } WHEN { @@ -60,7 +60,7 @@ SINGLE_BATTLE_TEST("Moody randomly raises the holder's Attack, Defense, Sp. Atk, PASSES_RANDOMLY(statsNum - 1, statsNum - 1, RNG_MOODY_DECREASE); GIVEN { - WITH_CONFIG(GEN_CONFIG_MOODY_STATS, config); + WITH_CONFIG(CONFIG_MOODY_ACC_EVASION, config); PLAYER(SPECIES_OCTILLERY) { Ability(ABILITY_MOODY); } OPPONENT(SPECIES_WOBBUFFET); } WHEN { diff --git a/test/battle/ability/moxie.c b/test/battle/ability/moxie.c index 1dda9f7926..01eb51b9e7 100644 --- a/test/battle/ability/moxie.c +++ b/test/battle/ability/moxie.c @@ -3,7 +3,8 @@ DOUBLE_BATTLE_TEST("Moxie/Chilling Neigh raises Attack by one stage after directly causing a Pokemon to faint") { - u32 species = 0, ability = 0, abilityPopUp = 0; + u32 species = 0, abilityPopUp = 0; + enum Ability ability = ABILITY_NONE; 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; ability = ABILITY_AS_ONE_ICE_RIDER; abilityPopUp = ABILITY_CHILLING_NEIGH; } @@ -36,7 +37,8 @@ DOUBLE_BATTLE_TEST("Moxie/Chilling Neigh raises Attack by one stage after direct 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; + u32 species = 0, abilityPopUp = 0; + enum Ability ability = ABILITY_NONE; 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; ability = ABILITY_AS_ONE_ICE_RIDER; abilityPopUp = ABILITY_CHILLING_NEIGH; } @@ -73,7 +75,8 @@ DOUBLE_BATTLE_TEST("Moxie/Chilling Neigh does not trigger if Pokemon faint to in SINGLE_BATTLE_TEST("Moxie/Chilling Neigh does not trigger when already at maximum Attack stage") { - u32 species = 0, ability = 0, abilityPopUp = 0; + u32 species = 0, abilityPopUp = 0; + enum Ability ability = ABILITY_NONE; 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; ability = ABILITY_AS_ONE_ICE_RIDER; abilityPopUp = ABILITY_CHILLING_NEIGH; } @@ -111,7 +114,8 @@ SINGLE_BATTLE_TEST("Moxie/Chilling Neigh does not trigger when already at maximu DOUBLE_BATTLE_TEST("Moxie/Chilling 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; + u32 species = 0, abilityPopUp = 0; + enum Ability ability = ABILITY_NONE; 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; ability = ABILITY_AS_ONE_ICE_RIDER; abilityPopUp = ABILITY_CHILLING_NEIGH; } diff --git a/test/battle/ability/mummy.c b/test/battle/ability/mummy.c index f03e453e5c..990fba7a0d 100644 --- a/test/battle/ability/mummy.c +++ b/test/battle/ability/mummy.c @@ -3,7 +3,8 @@ SINGLE_BATTLE_TEST("Mummy/Lingering Aroma replace the attacker's ability on contact") { - u32 move, ability, species; + u32 move, species; + enum Ability ability; PARAMETRIZE { move = MOVE_AQUA_JET; ability = ABILITY_MUMMY; species = SPECIES_YAMASK; } PARAMETRIZE { move = MOVE_WATER_GUN; ability = ABILITY_MUMMY; species = SPECIES_YAMASK;} @@ -37,7 +38,7 @@ SINGLE_BATTLE_TEST("Mummy/Lingering Aroma replace the attacker's ability on cont SINGLE_BATTLE_TEST("Mummy and Lingering Aroma don't replace each other") { - u32 ability1, species1, ability2, species2; + enum Ability ability1, species1, ability2, species2; PARAMETRIZE { ability1 = ability2 = ABILITY_MUMMY; species1 = species2 = SPECIES_YAMASK; } PARAMETRIZE { ability1 = ABILITY_MUMMY; species1 = SPECIES_YAMASK; ability2 = ABILITY_LINGERING_AROMA; species2 = SPECIES_OINKOLOGNE; } @@ -66,7 +67,8 @@ SINGLE_BATTLE_TEST("Mummy and Lingering Aroma don't replace each other") SINGLE_BATTLE_TEST("Mummy doesn't replace abilities that can't be suppressed") { - u32 species, ability; + u32 species; + enum Ability ability; PARAMETRIZE { species = SPECIES_ARCEUS; ability = ABILITY_MULTITYPE; } PARAMETRIZE { species = SPECIES_AEGISLASH; ability = ABILITY_STANCE_CHANGE; } diff --git a/test/battle/ability/neuroforce.c b/test/battle/ability/neuroforce.c index bd581b9b7d..32f3e91e56 100644 --- a/test/battle/ability/neuroforce.c +++ b/test/battle/ability/neuroforce.c @@ -4,7 +4,7 @@ SINGLE_BATTLE_TEST("Neuroforce increases the strength of super-effective moves by 25%", s16 damage) { u32 move; - u16 ability; + enum Ability ability; PARAMETRIZE { ability = ABILITY_NEUROFORCE; move = MOVE_SHADOW_BALL; } PARAMETRIZE { ability = ABILITY_KLUTZ; move = MOVE_SHADOW_BALL; } PARAMETRIZE { ability = ABILITY_NEUROFORCE; move = MOVE_SCRATCH; } diff --git a/test/battle/ability/neutralizing_gas.c b/test/battle/ability/neutralizing_gas.c index f83e928c4a..02f7323af2 100644 --- a/test/battle/ability/neutralizing_gas.c +++ b/test/battle/ability/neutralizing_gas.c @@ -83,7 +83,7 @@ DOUBLE_BATTLE_TEST("Neutralizing Gas ignores all battlers' ability effects") SINGLE_BATTLE_TEST("Neutralizing Gas ignores multipliers from attacker's ability", s16 damage) { - u32 ability; + enum Ability ability; PARAMETRIZE { ability = ABILITY_NEUTRALIZING_GAS; } PARAMETRIZE { ability = ABILITY_LEVITATE; } GIVEN { @@ -102,7 +102,7 @@ SINGLE_BATTLE_TEST("Neutralizing Gas ignores multipliers from attacker's ability SINGLE_BATTLE_TEST("Neutralizing Gas ignores multipliers from target's ability", s16 damage) { - u32 ability; + enum Ability ability; PARAMETRIZE { ability = ABILITY_NEUTRALIZING_GAS; } PARAMETRIZE { ability = ABILITY_LEVITATE; } GIVEN { @@ -122,7 +122,7 @@ SINGLE_BATTLE_TEST("Neutralizing Gas ignores multipliers from target's ability", DOUBLE_BATTLE_TEST("Neutralizing Gas ignores multipliers from target's ally's ability", s16 damage) { - u32 ability; + enum Ability ability; PARAMETRIZE { ability = ABILITY_NEUTRALIZING_GAS; } PARAMETRIZE { ability = ABILITY_LEVITATE; } GIVEN { @@ -142,7 +142,7 @@ DOUBLE_BATTLE_TEST("Neutralizing Gas ignores multipliers from target's ally's ab DOUBLE_BATTLE_TEST("Neutralizing Gas ignores multipliers from ally's ability", s16 damage) { - u32 ability; + enum Ability ability; PARAMETRIZE { ability = ABILITY_NEUTRALIZING_GAS; } PARAMETRIZE { ability = ABILITY_LEVITATE; } GIVEN { @@ -310,3 +310,88 @@ SINGLE_BATTLE_TEST("Neutralizing Gas exiting the field does not activate Imposte NOT ABILITY_POPUP(player, ABILITY_IMPOSTER); } } + +SINGLE_BATTLE_TEST("Neutralizing Gas exiting the field does not activate Air Lock/Cloud Nine but their effects are kept") +{ + u32 species, ability; + + PARAMETRIZE { species = SPECIES_GOLDUCK; ability = ABILITY_CLOUD_NINE; } + PARAMETRIZE { species = SPECIES_RAYQUAZA; ability = ABILITY_AIR_LOCK; } + + GIVEN { + ASSUME(GetMoveEffect(MOVE_RAIN_DANCE) == EFFECT_RAIN_DANCE); + PLAYER(SPECIES_WOBBUFFET); + PLAYER(species) { Ability(ability); } + OPPONENT(SPECIES_WEEZING) { Ability(ABILITY_NEUTRALIZING_GAS); } + OPPONENT(SPECIES_LUDICOLO) { Ability(ABILITY_RAIN_DISH); } + } WHEN { + TURN { SWITCH(player, 1); SWITCH(opponent, 1); } + TURN { MOVE(player, MOVE_RAIN_DANCE); } + } SCENE { + NOT ABILITY_POPUP(player, ABILITY_AIR_LOCK); + MESSAGE("The effects of the neutralizing gas wore off!"); + NOT ABILITY_POPUP(player, ABILITY_AIR_LOCK); + ANIMATION(ANIM_TYPE_MOVE, MOVE_RAIN_DANCE, player); + NOT ABILITY_POPUP(opponent, ABILITY_RAIN_DISH); + } +} + +SINGLE_BATTLE_TEST("Neutralizing Gas only displays exiting message for the last user leaving the field") +{ + GIVEN { + PLAYER(SPECIES_WEEZING) { Ability(ABILITY_NEUTRALIZING_GAS); } + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WEEZING) { Ability(ABILITY_NEUTRALIZING_GAS); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { SWITCH(player, 1); SWITCH(opponent, 1); } + } SCENE { + ABILITY_POPUP(player, ABILITY_NEUTRALIZING_GAS); + ABILITY_POPUP(opponent, ABILITY_NEUTRALIZING_GAS); + SEND_IN_MESSAGE("Wobbuffet"); + MESSAGE("The effects of the neutralizing gas wore off!"); + NOT MESSAGE("The effects of the neutralizing gas wore off!"); + } +} + +DOUBLE_BATTLE_TEST("Neutralizing Gas is active for the duration of a Spread Move even if Neutralizing Gas is no longer on the field") +{ + GIVEN { + ASSUME(GetMoveTarget(MOVE_ORIGIN_PULSE) == MOVE_TARGET_BOTH); + PLAYER(SPECIES_WEEZING) { HP(1); Ability(ABILITY_NEUTRALIZING_GAS); } + PLAYER(SPECIES_GOLEM) { Ability(ABILITY_STURDY); } + OPPONENT(SPECIES_BASCULEGION) { Ability(ABILITY_MOLD_BREAKER); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponentLeft, MOVE_ORIGIN_PULSE); } + } SCENE { + ABILITY_POPUP(playerLeft, ABILITY_NEUTRALIZING_GAS); + ANIMATION(ANIM_TYPE_MOVE, MOVE_ORIGIN_PULSE, opponentLeft); + HP_BAR(playerLeft); + HP_BAR(playerRight); + MESSAGE("Weezing fainted!"); + MESSAGE("Golem fainted!"); + NOT ABILITY_POPUP(playerRight, ABILITY_STURDY); + } +} + +DOUBLE_BATTLE_TEST("Neutralizing Gas is active until the last Dragon Darts hit even if Neutralizing Gas is no longer on the field") +{ + GIVEN { + ASSUME(GetMoveEffect(MOVE_DRAGON_DARTS) == EFFECT_DRAGON_DARTS); + PLAYER(SPECIES_WEEZING) { HP(1); Ability(ABILITY_NEUTRALIZING_GAS); } + PLAYER(SPECIES_GOLEM) { HP(2); MaxHP(2); Ability(ABILITY_STURDY); } + OPPONENT(SPECIES_BASCULEGION) { Ability(ABILITY_MOLD_BREAKER); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponentLeft, MOVE_DRAGON_DARTS, target: playerLeft); } + } SCENE { + ABILITY_POPUP(playerLeft, ABILITY_NEUTRALIZING_GAS); + ANIMATION(ANIM_TYPE_MOVE, MOVE_DRAGON_DARTS, opponentLeft); + HP_BAR(playerLeft); + MESSAGE("Weezing fainted!"); + HP_BAR(playerRight); + NOT MESSAGE("Golem fainted!"); + ABILITY_POPUP(playerRight, ABILITY_STURDY); + } +} diff --git a/test/battle/ability/normalize.c b/test/battle/ability/normalize.c index 23ecbee592..b50c46be09 100644 --- a/test/battle/ability/normalize.c +++ b/test/battle/ability/normalize.c @@ -11,7 +11,7 @@ ASSUMPTIONS SINGLE_BATTLE_TEST("Normalize turns a move into a Normal-type move") { - u16 ability; + enum Ability ability; PARAMETRIZE { ability = ABILITY_CUTE_CHARM; } PARAMETRIZE { ability = ABILITY_NORMALIZE; } GIVEN { @@ -36,7 +36,7 @@ SINGLE_BATTLE_TEST("Normalize turns a move into a Normal-type move") SINGLE_BATTLE_TEST("Normalize affects status moves") { - u16 ability; + enum Ability ability; PARAMETRIZE { ability = ABILITY_CUTE_CHARM; } PARAMETRIZE { ability = ABILITY_NORMALIZE; } GIVEN { @@ -62,7 +62,7 @@ SINGLE_BATTLE_TEST("Normalize affects status moves") SINGLE_BATTLE_TEST("Normalize still makes Freeze-Dry do super effective damage to Water-type Pokémon", s16 damage) { - u16 ability; + enum Ability ability; PARAMETRIZE { ability = ABILITY_CUTE_CHARM; } PARAMETRIZE { ability = ABILITY_NORMALIZE; } GIVEN { @@ -82,12 +82,12 @@ SINGLE_BATTLE_TEST("Normalize still makes Freeze-Dry do super effective damage t SINGLE_BATTLE_TEST("Normalize doesn't boost power of unaffected moves by 20% (< Gen7)", s16 damage) { - u32 ability; + enum Ability ability; PARAMETRIZE { ability = ABILITY_CUTE_CHARM; } PARAMETRIZE { ability = ABILITY_NORMALIZE; } GIVEN { - WITH_CONFIG(GEN_CONFIG_ATE_MULTIPLIER, GEN_6); + WITH_CONFIG(CONFIG_ATE_MULTIPLIER, GEN_6); PLAYER(SPECIES_DELCATTY) { Ability(ability); } OPPONENT(SPECIES_WOBBUFFET); } WHEN { @@ -101,12 +101,12 @@ SINGLE_BATTLE_TEST("Normalize doesn't boost power of unaffected moves by 20% (< SINGLE_BATTLE_TEST("Normalize boosts power of unaffected moves by 20% (Gen7+)", s16 damage) { - u32 ability; + enum Ability ability; PARAMETRIZE { ability = ABILITY_CUTE_CHARM; } PARAMETRIZE { ability = ABILITY_NORMALIZE; } GIVEN { - WITH_CONFIG(GEN_CONFIG_ATE_MULTIPLIER, GEN_7); + WITH_CONFIG(CONFIG_ATE_MULTIPLIER, GEN_7); PLAYER(SPECIES_DELCATTY) { Ability(ability); } OPPONENT(SPECIES_WOBBUFFET); } WHEN { @@ -120,12 +120,12 @@ SINGLE_BATTLE_TEST("Normalize boosts power of unaffected moves by 20% (Gen7+)", SINGLE_BATTLE_TEST("Normalize doesn't boost power of affected moves by 20% (< Gen7)", s16 damage) { - u32 ability; + enum Ability ability; PARAMETRIZE { ability = ABILITY_CUTE_CHARM; } PARAMETRIZE { ability = ABILITY_NORMALIZE; } GIVEN { - WITH_CONFIG(GEN_CONFIG_ATE_MULTIPLIER, GEN_6); + WITH_CONFIG(CONFIG_ATE_MULTIPLIER, GEN_6); PLAYER(SPECIES_SKITTY) { Ability(ability); Moves(MOVE_WATER_GUN); } OPPONENT(SPECIES_WOBBUFFET); } WHEN { @@ -139,12 +139,12 @@ SINGLE_BATTLE_TEST("Normalize doesn't boost power of affected moves by 20% (< Ge SINGLE_BATTLE_TEST("Normalize boosts power of affected moves by 20% (Gen7+)", s16 damage) { - u32 ability; + enum Ability ability; PARAMETRIZE { ability = ABILITY_CUTE_CHARM; } PARAMETRIZE { ability = ABILITY_NORMALIZE; } GIVEN { - WITH_CONFIG(GEN_CONFIG_ATE_MULTIPLIER, GEN_7); + WITH_CONFIG(CONFIG_ATE_MULTIPLIER, GEN_7); PLAYER(SPECIES_SKITTY) { Ability(ability); Moves(MOVE_WATER_GUN); } OPPONENT(SPECIES_WOBBUFFET); } WHEN { @@ -184,7 +184,8 @@ SINGLE_BATTLE_TEST("Normalize-affected moves become Electric-type under Ion Delu SINGLE_BATTLE_TEST("Normalize doesn't affect Weather Ball's type", s16 damage) { - u16 move, ability; + u16 move; + enum Ability ability; PARAMETRIZE { move = MOVE_CELEBRATE; ability = ABILITY_CUTE_CHARM; } PARAMETRIZE { move = MOVE_SUNNY_DAY; ability = ABILITY_CUTE_CHARM; } PARAMETRIZE { move = MOVE_CELEBRATE; ability = ABILITY_NORMALIZE; } @@ -212,7 +213,7 @@ SINGLE_BATTLE_TEST("Normalize doesn't affect Weather Ball's type", s16 damage) SINGLE_BATTLE_TEST("Normalize doesn't affect Natural Gift's type") { - u16 ability; + enum Ability ability; PARAMETRIZE { ability = ABILITY_CUTE_CHARM; } PARAMETRIZE { ability = ABILITY_NORMALIZE; } GIVEN { diff --git a/test/battle/ability/oblivious.c b/test/battle/ability/oblivious.c index c160ab423e..03f71d7f55 100644 --- a/test/battle/ability/oblivious.c +++ b/test/battle/ability/oblivious.c @@ -37,7 +37,7 @@ SINGLE_BATTLE_TEST("Oblivious prevents Taunt (Gen6+)") PARAMETRIZE { gen = GEN_5; } PARAMETRIZE { gen = GEN_6; } GIVEN { - WITH_CONFIG(GEN_CONFIG_OBLIVIOUS_TAUNT, gen); + WITH_CONFIG(CONFIG_OBLIVIOUS_TAUNT, gen); ASSUME(GetMoveEffect(MOVE_TAUNT) == EFFECT_TAUNT); PLAYER(SPECIES_SLOWPOKE) { Ability(ABILITY_OBLIVIOUS); } OPPONENT(SPECIES_WOBBUFFET); @@ -66,7 +66,7 @@ SINGLE_BATTLE_TEST("Oblivious prevents Taunt (Gen6+)") SINGLE_BATTLE_TEST("Oblivious doesn't prevent Intimidate (Gen3-7)") { GIVEN { - WITH_CONFIG(GEN_CONFIG_UPDATED_INTIMIDATE, GEN_7); + WITH_CONFIG(CONFIG_UPDATED_INTIMIDATE, GEN_7); PLAYER(SPECIES_SLOWPOKE) { Ability(ABILITY_OBLIVIOUS); } OPPONENT(SPECIES_WOBBUFFET); OPPONENT(SPECIES_EKANS) { Ability(ABILITY_INTIMIDATE); } @@ -86,7 +86,7 @@ SINGLE_BATTLE_TEST("Oblivious doesn't prevent Intimidate (Gen3-7)") SINGLE_BATTLE_TEST("Oblivious prevents Intimidate (Gen8+)") { GIVEN { - WITH_CONFIG(GEN_CONFIG_UPDATED_INTIMIDATE, GEN_8); + WITH_CONFIG(CONFIG_UPDATED_INTIMIDATE, GEN_8); PLAYER(SPECIES_SLOWPOKE) { Ability(ABILITY_OBLIVIOUS); } OPPONENT(SPECIES_WOBBUFFET); OPPONENT(SPECIES_EKANS) { Ability(ABILITY_INTIMIDATE); } diff --git a/test/battle/ability/opportunist.c b/test/battle/ability/opportunist.c index 3fac02b5b7..6e5b13dd31 100644 --- a/test/battle/ability/opportunist.c +++ b/test/battle/ability/opportunist.c @@ -8,7 +8,7 @@ ASSUMPTIONS SINGLE_BATTLE_TEST("Opportunist only copies foe's positive stat changes in a turn", s16 damage) { - u32 ability; + enum Ability ability; PARAMETRIZE { ability = ABILITY_FRISK; } PARAMETRIZE { ability = ABILITY_OPPORTUNIST; } GIVEN { @@ -42,7 +42,7 @@ SINGLE_BATTLE_TEST("Opportunist only copies foe's positive stat changes in a tur DOUBLE_BATTLE_TEST("Opportunist raises Attack only once when partner has Intimidate against Contrary foe in a double battle", s16 damageLeft, s16 damageRight) { - u32 abilityLeft, abilityRight; + enum Ability abilityLeft, abilityRight; PARAMETRIZE { abilityLeft = ABILITY_CONTRARY; abilityRight = ABILITY_CONTRARY; } PARAMETRIZE { abilityLeft = ABILITY_TANGLED_FEET; abilityRight = ABILITY_TANGLED_FEET; } @@ -294,3 +294,24 @@ SINGLE_BATTLE_TEST("Opportunist and Mirror Herb stack stat increases") EXPECT_EQ(opponent->statStages[STAT_SPDEF], DEFAULT_STAT_STAGE); } } + +DOUBLE_BATTLE_TEST("Opportunist and Mirror Herb resolve correctly") +{ + GIVEN { + PLAYER(SPECIES_ZACIAN) { Ability(ABILITY_INTREPID_SWORD); } + PLAYER(SPECIES_ESPATHRA) { Ability(ABILITY_OPPORTUNIST); } + OPPONENT(SPECIES_MEOWSCARADA) { Item(ITEM_MIRROR_HERB); } + OPPONENT(SPECIES_ESPATHRA) { Ability(ABILITY_OPPORTUNIST); Item(ITEM_MIRROR_HERB); } + } WHEN { + TURN { } + } SCENE { + ABILITY_POPUP(playerLeft, ABILITY_INTREPID_SWORD); + ABILITY_POPUP(opponentRight, ABILITY_OPPORTUNIST); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, opponentLeft); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, opponentRight); + } THEN { + EXPECT_EQ(playerLeft->statStages[STAT_ATK], DEFAULT_STAT_STAGE + 1); + EXPECT_EQ(opponentLeft->statStages[STAT_ATK], DEFAULT_STAT_STAGE + 1); + EXPECT_EQ(opponentRight->statStages[STAT_ATK], DEFAULT_STAT_STAGE + 2); + } +} diff --git a/test/battle/ability/overcoat.c b/test/battle/ability/overcoat.c index 5edda7c3d5..b0e8984bec 100644 --- a/test/battle/ability/overcoat.c +++ b/test/battle/ability/overcoat.c @@ -7,7 +7,7 @@ SINGLE_BATTLE_TEST("Overcoat blocks powder and spore moves (Gen6+)") PARAMETRIZE { gen = GEN_5; } PARAMETRIZE { gen = GEN_6; } GIVEN { - WITH_CONFIG(GEN_CONFIG_POWDER_OVERCOAT, gen); + WITH_CONFIG(CONFIG_POWDER_OVERCOAT, gen); ASSUME(IsPowderMove(MOVE_STUN_SPORE)); PLAYER(SPECIES_WYNAUT); OPPONENT(SPECIES_PINECO) { Ability(ABILITY_OVERCOAT); } @@ -77,7 +77,7 @@ SINGLE_BATTLE_TEST("Overcoat blocks Effect Spore's effect (Gen6+)") PARAMETRIZE { config = GEN_5; } PARAMETRIZE { config = GEN_6; } GIVEN { - WITH_CONFIG(GEN_CONFIG_POWDER_OVERCOAT, config); + WITH_CONFIG(CONFIG_POWDER_OVERCOAT, config); PLAYER(SPECIES_PINECO) {Ability(ABILITY_OVERCOAT);} OPPONENT(SPECIES_SHROOMISH) {Ability(ABILITY_EFFECT_SPORE);} } WHEN { diff --git a/test/battle/ability/own_tempo.c b/test/battle/ability/own_tempo.c index bbd709c57b..c2b9f4d6d9 100644 --- a/test/battle/ability/own_tempo.c +++ b/test/battle/ability/own_tempo.c @@ -4,7 +4,7 @@ SINGLE_BATTLE_TEST("Own Tempo doesn't prevent Intimidate (Gen3-7)") { GIVEN { - WITH_CONFIG(GEN_CONFIG_UPDATED_INTIMIDATE, GEN_7); + WITH_CONFIG(CONFIG_UPDATED_INTIMIDATE, GEN_7); ASSUME(GetMoveEffect(MOVE_CONFUSE_RAY) == EFFECT_CONFUSE); PLAYER(SPECIES_EKANS) { Ability(ABILITY_INTIMIDATE); }; OPPONENT(SPECIES_SLOWPOKE) { Ability(ABILITY_OWN_TEMPO); }; @@ -22,7 +22,7 @@ SINGLE_BATTLE_TEST("Own Tempo doesn't prevent Intimidate (Gen3-7)") SINGLE_BATTLE_TEST("Own Tempo prevents Intimidate but no other stat down changes (Gen8+)") { GIVEN { - WITH_CONFIG(GEN_CONFIG_UPDATED_INTIMIDATE, GEN_8); + WITH_CONFIG(CONFIG_UPDATED_INTIMIDATE, GEN_8); ASSUME(GetMoveEffect(MOVE_CONFUSE_RAY) == EFFECT_CONFUSE); PLAYER(SPECIES_EKANS) { Ability(ABILITY_INTIMIDATE); }; OPPONENT(SPECIES_SLOWPOKE) { Ability(ABILITY_OWN_TEMPO); }; diff --git a/test/battle/ability/parental_bond.c b/test/battle/ability/parental_bond.c index fc128dba64..824399379c 100644 --- a/test/battle/ability/parental_bond.c +++ b/test/battle/ability/parental_bond.c @@ -105,7 +105,9 @@ DOUBLE_BATTLE_TEST("Parental Bond does not convert multi-target moves into a two SINGLE_BATTLE_TEST("Parental Bond-converted moves only hit once on Lightning Rod/Storm Drain mons") { - u16 move, species, ability, type; + u16 move, species; + enum Type type; + enum Ability ability; PARAMETRIZE { move = MOVE_THUNDERBOLT; ability = ABILITY_LIGHTNING_ROD; species = SPECIES_RAICHU; type = TYPE_ELECTRIC; } PARAMETRIZE { move = MOVE_SURF; ability = ABILITY_STORM_DRAIN; species = SPECIES_LILEEP; type = TYPE_WATER; } GIVEN { @@ -139,7 +141,7 @@ SINGLE_BATTLE_TEST("Parental Bond has no affect on multi hit moves and they stil PASSES_RANDOMLY(passes, trials, RNG_HITS); GIVEN { - WITH_CONFIG(GEN_CONFIG_MULTI_HIT_CHANCE, genConfig); + WITH_CONFIG(CONFIG_MULTI_HIT_CHANCE, genConfig); ASSUME(GetMoveCategory(MOVE_COMET_PUNCH) != DAMAGE_CATEGORY_STATUS); ASSUME(GetMoveEffect(MOVE_COMET_PUNCH) == EFFECT_MULTI_HIT); PLAYER(SPECIES_KANGASKHAN) { Item(ITEM_KANGASKHANITE); } @@ -168,7 +170,7 @@ SINGLE_BATTLE_TEST("Parental Bond has no affect on multi hit moves and they stil PASSES_RANDOMLY(passes, trials, RNG_HITS); GIVEN { - WITH_CONFIG(GEN_CONFIG_MULTI_HIT_CHANCE, genConfig); + WITH_CONFIG(CONFIG_MULTI_HIT_CHANCE, genConfig); ASSUME(GetMoveCategory(MOVE_COMET_PUNCH) != DAMAGE_CATEGORY_STATUS); ASSUME(GetMoveEffect(MOVE_COMET_PUNCH) == EFFECT_MULTI_HIT); PLAYER(SPECIES_KANGASKHAN) { Item(ITEM_KANGASKHANITE); } @@ -198,7 +200,7 @@ SINGLE_BATTLE_TEST("Parental Bond has no affect on multi hit moves and they stil PASSES_RANDOMLY(passes, trials, RNG_HITS); GIVEN { - WITH_CONFIG(GEN_CONFIG_MULTI_HIT_CHANCE, genConfig); + WITH_CONFIG(CONFIG_MULTI_HIT_CHANCE, genConfig); ASSUME(GetMoveCategory(MOVE_COMET_PUNCH) != DAMAGE_CATEGORY_STATUS); ASSUME(GetMoveEffect(MOVE_COMET_PUNCH) == EFFECT_MULTI_HIT); PLAYER(SPECIES_KANGASKHAN) { Item(ITEM_KANGASKHANITE); } @@ -229,7 +231,7 @@ SINGLE_BATTLE_TEST("Parental Bond has no affect on multi hit moves and they stil PASSES_RANDOMLY(passes, trials, RNG_HITS); GIVEN { - WITH_CONFIG(GEN_CONFIG_MULTI_HIT_CHANCE, genConfig); + WITH_CONFIG(CONFIG_MULTI_HIT_CHANCE, genConfig); ASSUME(GetMoveCategory(MOVE_COMET_PUNCH) != DAMAGE_CATEGORY_STATUS); ASSUME(GetMoveEffect(MOVE_COMET_PUNCH) == EFFECT_MULTI_HIT); PLAYER(SPECIES_KANGASKHAN) { Item(ITEM_KANGASKHANITE); } diff --git a/test/battle/ability/pastel_veil.c b/test/battle/ability/pastel_veil.c index 1c0926ac80..11bf32bb9a 100644 --- a/test/battle/ability/pastel_veil.c +++ b/test/battle/ability/pastel_veil.c @@ -80,7 +80,7 @@ SINGLE_BATTLE_TEST("Pastel Veil prevents Toxic bad poison") } SCENE { MESSAGE("Wobbuffet used Toxic!"); ABILITY_POPUP(opponent, ABILITY_PASTEL_VEIL); - MESSAGE("The opposing Ponyta is protected by a pastel veil!"); + MESSAGE("It doesn't affect the opposing Ponyta…"); NOT STATUS_ICON(opponent, badPoison: TRUE); } } @@ -97,7 +97,7 @@ DOUBLE_BATTLE_TEST("Pastel Veil prevents Toxic bad poison on partner - right tar } SCENE { MESSAGE("Wobbuffet used Toxic!"); ABILITY_POPUP(opponentLeft, ABILITY_PASTEL_VEIL); - MESSAGE("The opposing Wynaut is protected by a pastel veil!"); + MESSAGE("It doesn't affect the opposing Wynaut…"); NOT STATUS_ICON(opponentRight, badPoison: TRUE); } } @@ -114,7 +114,7 @@ DOUBLE_BATTLE_TEST("Pastel Veil prevents Toxic bad poison on partner - left targ } SCENE { MESSAGE("Wobbuffet used Toxic!"); ABILITY_POPUP(opponentRight, ABILITY_PASTEL_VEIL); - MESSAGE("The opposing Wynaut is protected by a pastel veil!"); + MESSAGE("It doesn't affect the opposing Wynaut…"); NOT STATUS_ICON(opponentLeft, badPoison: TRUE); } } diff --git a/test/battle/ability/pickup.c b/test/battle/ability/pickup.c index cc9ae37e9d..bf74823361 100644 --- a/test/battle/ability/pickup.c +++ b/test/battle/ability/pickup.c @@ -26,7 +26,7 @@ SINGLE_BATTLE_TEST("Pickup grants an item used by another Pokémon") WILD_BATTLE_TEST("Pickup grants an item used by itself in wild battles (Gen9+)") { GIVEN { - WITH_CONFIG(GEN_PICKUP_WILD, GEN_9); + WITH_CONFIG(CONFIG_PICKUP_WILD, GEN_9); PLAYER(SPECIES_ZIGZAGOON) { Ability(ABILITY_PICKUP); MaxHP(100); HP(51); Item(ITEM_SITRUS_BERRY); } OPPONENT(SPECIES_WOBBUFFET); } WHEN { diff --git a/test/battle/ability/pixilate.c b/test/battle/ability/pixilate.c index 7e0d98f519..f6747b92d3 100644 --- a/test/battle/ability/pixilate.c +++ b/test/battle/ability/pixilate.c @@ -23,14 +23,15 @@ SINGLE_BATTLE_TEST("Pixilate turns a Normal-type move into a Fairy-type move") SINGLE_BATTLE_TEST("Pixilate boosts power of affected moves by 20% (Gen7+) or 30% (Gen1-6)", s16 damage) { - u32 ability, genConfig; + enum Ability ability; + u32 genConfig; PARAMETRIZE { ability = ABILITY_CUTE_CHARM; genConfig = GEN_7; } PARAMETRIZE { ability = ABILITY_CUTE_CHARM; genConfig = GEN_6; } PARAMETRIZE { ability = ABILITY_PIXILATE; genConfig = GEN_7; } PARAMETRIZE { ability = ABILITY_PIXILATE; genConfig = GEN_6; } GIVEN { - WITH_CONFIG(GEN_CONFIG_ATE_MULTIPLIER, genConfig); + WITH_CONFIG(CONFIG_ATE_MULTIPLIER, genConfig); PLAYER(SPECIES_SYLVEON) { Ability(ability); Moves(MOVE_TACKLE); } OPPONENT(SPECIES_WOBBUFFET); } WHEN { @@ -47,7 +48,8 @@ SINGLE_BATTLE_TEST("Pixilate boosts power of affected moves by 20% (Gen7+) or 30 SINGLE_BATTLE_TEST("Pixilate doesn't affect Weather Ball's type", s16 damage) { - u16 move, ability; + u16 move; + enum Ability ability; PARAMETRIZE { move = MOVE_CELEBRATE; ability = ABILITY_STURDY; } PARAMETRIZE { move = MOVE_SUNNY_DAY; ability = ABILITY_STURDY; } PARAMETRIZE { move = MOVE_CELEBRATE; ability = ABILITY_PIXILATE; } @@ -75,7 +77,7 @@ SINGLE_BATTLE_TEST("Pixilate doesn't affect Weather Ball's type", s16 damage) SINGLE_BATTLE_TEST("Pixilate doesn't affect Natural Gift's type") { - u16 ability; + enum Ability ability; PARAMETRIZE { ability = ABILITY_CUTE_CHARM; } PARAMETRIZE { ability = ABILITY_PIXILATE; } GIVEN { diff --git a/test/battle/ability/prankster.c b/test/battle/ability/prankster.c index e927c2d94f..7e170570cf 100644 --- a/test/battle/ability/prankster.c +++ b/test/battle/ability/prankster.c @@ -13,7 +13,7 @@ SINGLE_BATTLE_TEST("Prankster-affected moves don't affect Dark-type Pokémon (Ge PARAMETRIZE { gen = GEN_6; } PARAMETRIZE { gen = GEN_7; } GIVEN { - WITH_CONFIG(GEN_CONFIG_PRANKSTER_DARK_TYPES, gen); + WITH_CONFIG(CONFIG_PRANKSTER_DARK_TYPES, gen); PLAYER(SPECIES_UMBREON); OPPONENT(SPECIES_VOLBEAT) { Ability(ABILITY_PRANKSTER); } } WHEN { @@ -31,7 +31,7 @@ SINGLE_BATTLE_TEST("Prankster-affected moves don't affect Dark-type Pokémon (Ge SINGLE_BATTLE_TEST("Prankster-affected moves don't affect Dark-type Pokémon after they switch-in") { GIVEN { - WITH_CONFIG(GEN_CONFIG_PRANKSTER_DARK_TYPES, GEN_7); + WITH_CONFIG(CONFIG_PRANKSTER_DARK_TYPES, GEN_7); PLAYER(SPECIES_WOBBUFFET); PLAYER(SPECIES_UMBREON); OPPONENT(SPECIES_VOLBEAT) { Ability(ABILITY_PRANKSTER); } @@ -64,7 +64,7 @@ SINGLE_BATTLE_TEST("Prankster-affected moves called via Assist don't affect Dark PARAMETRIZE { gen = GEN_6; } PARAMETRIZE { gen = GEN_7; } GIVEN { - WITH_CONFIG(GEN_CONFIG_PRANKSTER_DARK_TYPES, gen); + WITH_CONFIG(CONFIG_PRANKSTER_DARK_TYPES, gen); PLAYER(SPECIES_UMBREON); OPPONENT(SPECIES_VOLBEAT) { Ability(ABILITY_PRANKSTER); } OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_CONFUSE_RAY); }; @@ -87,7 +87,7 @@ DOUBLE_BATTLE_TEST("Prankster-affected moves called via Instruct do not affect D PARAMETRIZE { gen = GEN_6; } PARAMETRIZE { gen = GEN_7; } GIVEN { - WITH_CONFIG(GEN_CONFIG_PRANKSTER_DARK_TYPES, gen); + WITH_CONFIG(CONFIG_PRANKSTER_DARK_TYPES, gen); PLAYER(SPECIES_VOLBEAT) { Speed(20); Ability(ABILITY_PRANKSTER); } PLAYER(SPECIES_WOBBUFFET) { Speed(10);} OPPONENT(SPECIES_UMBREON) { Speed(15); } @@ -197,13 +197,13 @@ SINGLE_BATTLE_TEST("Prankster-affected moves can still be bounced back by Dark-t SINGLE_BATTLE_TEST("Prankster-affected moves which are reflected by Magic Coat can affect Dark-type Pokémon, unless the Pokémon that bounced the move also has Prankster") { - u16 sableyeAbility; + enum Ability sableyeAbility; PARAMETRIZE { sableyeAbility = ABILITY_PRANKSTER; } PARAMETRIZE { sableyeAbility = ABILITY_KEEN_EYE; } GIVEN { - WITH_CONFIG(GEN_CONFIG_PRANKSTER_DARK_TYPES, GEN_7); + WITH_CONFIG(CONFIG_PRANKSTER_DARK_TYPES, GEN_7); PLAYER(SPECIES_SABLEYE) { Ability(sableyeAbility); } OPPONENT(SPECIES_MURKROW) { Ability(ABILITY_PRANKSTER); } } WHEN { diff --git a/test/battle/ability/primordial_sea.c b/test/battle/ability/primordial_sea.c index 39d350d3a0..f24219f263 100644 --- a/test/battle/ability/primordial_sea.c +++ b/test/battle/ability/primordial_sea.c @@ -64,3 +64,15 @@ SINGLE_BATTLE_TEST("Primordial Sea does not block a move if Pokémon is asleep a MESSAGE("The opposing Wobbuffet is fast asleep."); } } + +TO_DO_BATTLE_TEST("Primordial Sea makes Sunny Day fail") +TO_DO_BATTLE_TEST("Primordial Sea makes Rain Dance fail") +TO_DO_BATTLE_TEST("Primordial Sea makes Sandstorm fail") +TO_DO_BATTLE_TEST("Primordial Sea makes Hail fail") +TO_DO_BATTLE_TEST("Primordial Sea makes Snowscape fail") // Extrapolation +TO_DO_BATTLE_TEST("Primordial Sea makes Drought fail to activate") +TO_DO_BATTLE_TEST("Primordial Sea makes Drizzle fail to activate") +TO_DO_BATTLE_TEST("Primordial Sea makes Sand Stream fail to activate") +TO_DO_BATTLE_TEST("Primordial Sea makes Snow Warning fail to activate") +TO_DO_BATTLE_TEST("Primordial Sea can be replaced by Delta Stream") +TO_DO_BATTLE_TEST("Primordial Sea can be replaced by Desolate Land") diff --git a/test/battle/ability/prism_armor.c b/test/battle/ability/prism_armor.c index 69bdde0a0f..36fbc27f99 100644 --- a/test/battle/ability/prism_armor.c +++ b/test/battle/ability/prism_armor.c @@ -3,7 +3,7 @@ SINGLE_BATTLE_TEST("Prism Armor reduces damage to Super Effective moves by 0.75", s16 damage) { - u32 ability; + enum Ability ability; PARAMETRIZE { ability = ABILITY_NEUTRALIZING_GAS; } PARAMETRIZE { ability = ABILITY_LEVITATE; } GIVEN { diff --git a/test/battle/ability/protean.c b/test/battle/ability/protean.c index c41fa58cca..7ebec1ff6e 100644 --- a/test/battle/ability/protean.c +++ b/test/battle/ability/protean.c @@ -7,7 +7,7 @@ SINGLE_BATTLE_TEST("Protean/Libero changes the type of the user to the move used PARAMETRIZE { ability = ABILITY_PROTEAN; species = SPECIES_KECLEON; } PARAMETRIZE { ability = ABILITY_LIBERO; species = SPECIES_RABOOT; } GIVEN { - WITH_CONFIG(GEN_PROTEAN_LIBERO, GEN_6); + WITH_CONFIG(CONFIG_PROTEAN_LIBERO, GEN_6); PLAYER(SPECIES_REGIROCK); OPPONENT(species) { Ability(ability); } OPPONENT(SPECIES_WOBBUFFET); @@ -45,7 +45,7 @@ SINGLE_BATTLE_TEST("Protean/Libero changes the type of the user only once per sw PARAMETRIZE { ability = ABILITY_PROTEAN; species = SPECIES_KECLEON; } PARAMETRIZE { ability = ABILITY_LIBERO; species = SPECIES_RABOOT; } GIVEN { - WITH_CONFIG(GEN_PROTEAN_LIBERO, GEN_9); + WITH_CONFIG(CONFIG_PROTEAN_LIBERO, GEN_9); PLAYER(SPECIES_REGIROCK); OPPONENT(species) { Ability(ability); } OPPONENT(SPECIES_WOBBUFFET); diff --git a/test/battle/ability/protosynthesis.c b/test/battle/ability/protosynthesis.c index bad29b4c9a..a080e90a11 100644 --- a/test/battle/ability/protosynthesis.c +++ b/test/battle/ability/protosynthesis.c @@ -59,7 +59,7 @@ SINGLE_BATTLE_TEST("Protosynthesis ability pop up activates only once during the u16 turns; GIVEN { - WITH_CONFIG(GEN_CONFIG_ABILITY_WEATHER, GEN_6); + WITH_CONFIG(CONFIG_ABILITY_WEATHER, GEN_6); PLAYER(SPECIES_WALKING_WAKE) { Ability(ABILITY_PROTOSYNTHESIS); } OPPONENT(SPECIES_NINETALES) { Ability(ABILITY_DROUGHT); }; } WHEN { @@ -185,7 +185,8 @@ SINGLE_BATTLE_TEST("Protosynthesis activates even if the Pokémon is holding an SINGLE_BATTLE_TEST("Protosynthesis doesn't activate if Cloud Nine/Air Lock is on the field") { - u32 species, ability; + u32 species; + enum Ability ability; PARAMETRIZE { species = SPECIES_RAYQUAZA; ability = ABILITY_AIR_LOCK; } PARAMETRIZE { species = SPECIES_GOLDUCK; ability = ABILITY_CLOUD_NINE; } @@ -218,3 +219,95 @@ SINGLE_BATTLE_TEST("Protosynthesis activates after weather was reset") ABILITY_POPUP(player, ABILITY_PROTOSYNTHESIS); } } + +SINGLE_BATTLE_TEST("Protosynthesis accounts for Sticky Web when determining the boosted stat") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Speed(1); } + PLAYER(SPECIES_FLUTTER_MANE) { Ability(ABILITY_PROTOSYNTHESIS); Attack(50); Defense(50); SpAttack(150); SpDefense(140); Speed(180); } + OPPONENT(SPECIES_GALVANTULA) { Speed(60); } + OPPONENT(SPECIES_WOBBUFFET) { Speed(1); } + } WHEN { + TURN { MOVE(opponent, MOVE_STICKY_WEB); MOVE(player, MOVE_SUNNY_DAY); } + TURN { SWITCH(player, 1); MOVE(opponent, MOVE_SPLASH); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_STICKY_WEB, opponent); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SUNNY_DAY, player); + ABILITY_POPUP(player, ABILITY_PROTOSYNTHESIS); + MESSAGE("The harsh sunlight activated Flutter Mane's Protosynthesis!"); + MESSAGE("Flutter Mane's Sp. Atk was heightened!"); + } +} + +SINGLE_BATTLE_TEST("Protosynthesis keeps its initial boosted stat after Speed is lowered") +{ + s16 damage[2]; + + GIVEN { + PLAYER(SPECIES_FLUTTER_MANE) { Ability(ABILITY_PROTOSYNTHESIS); Attack(10); Defense(10); SpAttack(150); SpDefense(120); Speed(180); Moves(MOVE_ROUND); } + OPPONENT(SPECIES_NINETALES) { Ability(ABILITY_DROUGHT); Moves(MOVE_ICY_WIND, MOVE_CELEBRATE); Speed(100); } + } WHEN { + TURN { MOVE(player, MOVE_ROUND); MOVE(opponent, MOVE_ICY_WIND); } + TURN { MOVE(player, MOVE_ROUND); MOVE(opponent, MOVE_CELEBRATE); } + } SCENE { + ABILITY_POPUP(opponent, ABILITY_DROUGHT); + ABILITY_POPUP(player, ABILITY_PROTOSYNTHESIS); + ANIMATION(ANIM_TYPE_MOVE, MOVE_ROUND, player); + HP_BAR(opponent, captureDamage: &damage[0]); + ANIMATION(ANIM_TYPE_MOVE, MOVE_ICY_WIND, opponent); + ANIMATION(ANIM_TYPE_MOVE, MOVE_ROUND, player); + HP_BAR(opponent, captureDamage: &damage[1]); + } THEN { + EXPECT_EQ(damage[0], damage[1]); + } +} + +SINGLE_BATTLE_TEST("Protosynthesis recalculates the boosted stat after Neutralizing Gas leaves the field") +{ + GIVEN { + PLAYER(SPECIES_FLUTTER_MANE) { Ability(ABILITY_PROTOSYNTHESIS); Attack(10); Defense(10); SpAttack(150); SpDefense(120); Speed(180); } + OPPONENT(SPECIES_WEEZING) { Ability(ABILITY_NEUTRALIZING_GAS); Moves(MOVE_ICY_WIND); Speed(70); } + OPPONENT(SPECIES_WOBBUFFET) { Speed(1); } + } WHEN { + TURN { MOVE(player, MOVE_SUNNY_DAY); MOVE(opponent, MOVE_ICY_WIND); } + TURN { SWITCH(opponent, 1); } + } SCENE { + ABILITY_POPUP(opponent, ABILITY_NEUTRALIZING_GAS); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SUNNY_DAY, player); + NOT ABILITY_POPUP(player, ABILITY_PROTOSYNTHESIS); + ANIMATION(ANIM_TYPE_MOVE, MOVE_ICY_WIND, opponent); + MESSAGE("The effects of the neutralizing gas wore off!"); + ABILITY_POPUP(player, ABILITY_PROTOSYNTHESIS); + MESSAGE("The harsh sunlight activated Flutter Mane's Protosynthesis!"); + MESSAGE("Flutter Mane's Sp. Atk was heightened!"); + } +} + +SINGLE_BATTLE_TEST("Protosynthesis retains its boosted stat after Neutralizing Gas briefly suppresses it") +{ + s16 damage[2]; + + GIVEN { + PLAYER(SPECIES_FLUTTER_MANE) { Ability(ABILITY_PROTOSYNTHESIS); Attack(10); Defense(10); SpAttack(150); SpDefense(120); Speed(180); Moves(MOVE_SUNNY_DAY, MOVE_ROUND, MOVE_CELEBRATE); } + OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_CELEBRATE); Speed(1); } + OPPONENT(SPECIES_WEEZING) { Ability(ABILITY_NEUTRALIZING_GAS); Moves(MOVE_CELEBRATE); Speed(70); } + } WHEN { + TURN { MOVE(player, MOVE_SUNNY_DAY); MOVE(opponent, MOVE_CELEBRATE); } + TURN { MOVE(player, MOVE_ROUND); MOVE(opponent, MOVE_CELEBRATE); } + TURN { MOVE(player, MOVE_CELEBRATE); SWITCH(opponent, 1); } + TURN { MOVE(player, MOVE_CELEBRATE); SWITCH(opponent, 0); } + TURN { MOVE(player, MOVE_ROUND); MOVE(opponent, MOVE_CELEBRATE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SUNNY_DAY, player); + ABILITY_POPUP(player, ABILITY_PROTOSYNTHESIS); + ANIMATION(ANIM_TYPE_MOVE, MOVE_ROUND, player); + HP_BAR(opponent, captureDamage: &damage[0]); + ABILITY_POPUP(opponent, ABILITY_NEUTRALIZING_GAS); + MESSAGE("Neutralizing gas filled the area!"); + MESSAGE("The effects of the neutralizing gas wore off!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_ROUND, player); + HP_BAR(opponent, captureDamage: &damage[1]); + } THEN { + EXPECT_EQ(damage[0], damage[1]); + } +} diff --git a/test/battle/ability/purifying_salt.c b/test/battle/ability/purifying_salt.c index 23f097e8aa..80dc786117 100644 --- a/test/battle/ability/purifying_salt.c +++ b/test/battle/ability/purifying_salt.c @@ -3,7 +3,7 @@ SINGLE_BATTLE_TEST("Purifying Salt halves damage from Ghost-type moves", s16 damage) { - u16 ability; + enum Ability ability; PARAMETRIZE { ability = ABILITY_STURDY; } PARAMETRIZE { ability = ABILITY_PURIFYING_SALT; } GIVEN { @@ -21,7 +21,7 @@ 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; + enum Ability ability; PARAMETRIZE { ability = ABILITY_STURDY; } PARAMETRIZE { ability = ABILITY_PURIFYING_SALT; } GIVEN { diff --git a/test/battle/ability/quark_drive.c b/test/battle/ability/quark_drive.c index a9f6e65a4b..3523f7dca4 100644 --- a/test/battle/ability/quark_drive.c +++ b/test/battle/ability/quark_drive.c @@ -54,6 +54,59 @@ SINGLE_BATTLE_TEST("Quark Drive boosts either Attack or Special Attack, not both } } +SINGLE_BATTLE_TEST("Quark Drive keeps its initial boosted stat after Speed is lowered") +{ + s16 damage[2]; + + GIVEN { + PLAYER(SPECIES_IRON_MOTH) { Ability(ABILITY_QUARK_DRIVE); Attack(10); Defense(10); SpAttack(150); SpDefense(120); Speed(180); Moves(MOVE_ROUND, MOVE_CELEBRATE); } + OPPONENT(SPECIES_TAPU_KOKO) { Ability(ABILITY_ELECTRIC_SURGE); Moves(MOVE_CELEBRATE, MOVE_ICY_WIND); Speed(100); } + } WHEN { + TURN { MOVE(player, MOVE_ROUND); MOVE(opponent, MOVE_CELEBRATE); } + TURN { MOVE(player, MOVE_CELEBRATE); MOVE(opponent, MOVE_ICY_WIND); } + TURN { MOVE(player, MOVE_ROUND); MOVE(opponent, MOVE_CELEBRATE); } + } SCENE { + ABILITY_POPUP(opponent, ABILITY_ELECTRIC_SURGE); + ABILITY_POPUP(player, ABILITY_QUARK_DRIVE); + ANIMATION(ANIM_TYPE_MOVE, MOVE_ROUND, player); + HP_BAR(opponent, captureDamage: &damage[0]); + ANIMATION(ANIM_TYPE_MOVE, MOVE_ICY_WIND, opponent); + ANIMATION(ANIM_TYPE_MOVE, MOVE_ROUND, player); + HP_BAR(opponent, captureDamage: &damage[1]); + } THEN { + EXPECT_EQ(damage[0], damage[1]); + } +} + +SINGLE_BATTLE_TEST("Quark Drive retains its boosted stat after Neutralizing Gas briefly suppresses it") +{ + s16 damage[2]; + + GIVEN { + PLAYER(SPECIES_IRON_MOTH) { Ability(ABILITY_QUARK_DRIVE); Attack(10); Defense(10); SpAttack(150); SpDefense(120); Speed(180); Moves(MOVE_ELECTRIC_TERRAIN, MOVE_ROUND, MOVE_CELEBRATE); } + OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_CELEBRATE); Speed(1); } + OPPONENT(SPECIES_WEEZING) { Ability(ABILITY_NEUTRALIZING_GAS); Moves(MOVE_CELEBRATE); Speed(70); } + } WHEN { + TURN { MOVE(player, MOVE_ELECTRIC_TERRAIN); MOVE(opponent, MOVE_CELEBRATE); } + TURN { MOVE(player, MOVE_ROUND); MOVE(opponent, MOVE_CELEBRATE); } + TURN { MOVE(player, MOVE_CELEBRATE); SWITCH(opponent, 1); } + TURN { MOVE(player, MOVE_CELEBRATE); SWITCH(opponent, 0); } + TURN { MOVE(player, MOVE_ROUND); MOVE(opponent, MOVE_CELEBRATE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_ELECTRIC_TERRAIN, player); + ABILITY_POPUP(player, ABILITY_QUARK_DRIVE); + ANIMATION(ANIM_TYPE_MOVE, MOVE_ROUND, player); + HP_BAR(opponent, captureDamage: &damage[0]); + ABILITY_POPUP(opponent, ABILITY_NEUTRALIZING_GAS); + MESSAGE("Neutralizing gas filled the area!"); + MESSAGE("The effects of the neutralizing gas wore off!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_ROUND, player); + HP_BAR(opponent, captureDamage: &damage[1]); + } THEN { + EXPECT_EQ(damage[0], damage[1]); + } +} + SINGLE_BATTLE_TEST("Quark Drive ability pop up activates only once during the duration of electric terrain") { u16 turns; diff --git a/test/battle/ability/rattled.c b/test/battle/ability/rattled.c index a2cc61536e..e5e7b3b03e 100644 --- a/test/battle/ability/rattled.c +++ b/test/battle/ability/rattled.c @@ -55,7 +55,7 @@ SINGLE_BATTLE_TEST("Rattled boosts speed by 1 when hit by Bug, Dark or Ghost typ SINGLE_BATTLE_TEST("Rattled does not boost speed by 1 when affected by Intimidate (Gen5-7)") { GIVEN { - WITH_CONFIG(GEN_CONFIG_UPDATED_INTIMIDATE, GEN_7); + WITH_CONFIG(CONFIG_UPDATED_INTIMIDATE, GEN_7); PLAYER(SPECIES_GYARADOS) {Ability(ABILITY_INTIMIDATE); } OPPONENT(SPECIES_SUDOWOODO) {Ability(ABILITY_RATTLED); } } WHEN { @@ -75,7 +75,7 @@ SINGLE_BATTLE_TEST("Rattled does not boost speed by 1 when affected by Intimidat SINGLE_BATTLE_TEST("Rattled boosts speed by 1 when affected by Intimidate (Gen8+)") { GIVEN { - WITH_CONFIG(GEN_CONFIG_UPDATED_INTIMIDATE, GEN_8); + WITH_CONFIG(CONFIG_UPDATED_INTIMIDATE, GEN_8); PLAYER(SPECIES_GYARADOS) {Ability(ABILITY_INTIMIDATE); } OPPONENT(SPECIES_SUDOWOODO) {Ability(ABILITY_RATTLED); } } WHEN { diff --git a/test/battle/ability/refrigerate.c b/test/battle/ability/refrigerate.c index c5e7f5687a..0fc274c8e5 100644 --- a/test/battle/ability/refrigerate.c +++ b/test/battle/ability/refrigerate.c @@ -22,14 +22,15 @@ SINGLE_BATTLE_TEST("Refrigerate turns a Normal-type move into a Ice-type move") SINGLE_BATTLE_TEST("Refrigerate boosts power of affected moves by 20% (Gen7+) or 30% (Gen1-6)", s16 damage) { - u32 ability, genConfig; + enum Ability ability; + u32 genConfig; PARAMETRIZE { ability = ABILITY_SNOW_WARNING; genConfig = GEN_7; } PARAMETRIZE { ability = ABILITY_SNOW_WARNING; genConfig = GEN_6; } PARAMETRIZE { ability = ABILITY_REFRIGERATE; genConfig = GEN_7; } PARAMETRIZE { ability = ABILITY_REFRIGERATE; genConfig = GEN_6; } GIVEN { - WITH_CONFIG(GEN_CONFIG_ATE_MULTIPLIER, genConfig); + WITH_CONFIG(CONFIG_ATE_MULTIPLIER, genConfig); PLAYER(SPECIES_AMAURA) { Ability(ability); Moves(MOVE_TACKLE); } OPPONENT(SPECIES_WOBBUFFET); } WHEN { @@ -46,13 +47,14 @@ SINGLE_BATTLE_TEST("Refrigerate boosts power of affected moves by 20% (Gen7+) or SINGLE_BATTLE_TEST("Refrigerate doesn't affect Weather Ball's type", s16 damage) { - u16 move, ability; + u16 move; + enum Ability ability; PARAMETRIZE { move = MOVE_CELEBRATE; ability = ABILITY_SNOW_WARNING; } PARAMETRIZE { move = MOVE_SUNNY_DAY; ability = ABILITY_SNOW_WARNING; } PARAMETRIZE { move = MOVE_CELEBRATE; ability = ABILITY_REFRIGERATE; } PARAMETRIZE { move = MOVE_SUNNY_DAY; ability = ABILITY_REFRIGERATE; } GIVEN { - WITH_CONFIG(GEN_SNOW_WARNING, GEN_9); //To prevent capturing hail damage + WITH_CONFIG(CONFIG_SNOW_WARNING, GEN_9); //To prevent capturing hail damage ASSUME(GetMoveEffect(MOVE_WEATHER_BALL) == EFFECT_WEATHER_BALL); ASSUME(GetSpeciesType(SPECIES_PINSIR, 0) == TYPE_BUG); PLAYER(SPECIES_AMAURA) { Ability(ability); } @@ -74,7 +76,7 @@ SINGLE_BATTLE_TEST("Refrigerate doesn't affect Weather Ball's type", s16 damage) SINGLE_BATTLE_TEST("Refrigerate doesn't affect Natural Gift's type") { - u16 ability; + enum Ability ability; PARAMETRIZE { ability = ABILITY_SNOW_WARNING; } PARAMETRIZE { ability = ABILITY_REFRIGERATE; } GIVEN { diff --git a/test/battle/ability/rivalry.c b/test/battle/ability/rivalry.c index aef7361af5..fbb4ba4530 100644 --- a/test/battle/ability/rivalry.c +++ b/test/battle/ability/rivalry.c @@ -10,7 +10,8 @@ ASSUMPTIONS SINGLE_BATTLE_TEST("Rivalry increases power by x1.25 towards Pokémon of the same gender", s16 damage) { - u16 species, ability; + u16 species; + enum Ability ability; PARAMETRIZE { species = SPECIES_NIDOKING; ability = ABILITY_POISON_POINT; } PARAMETRIZE { species = SPECIES_NIDOKING; ability = ABILITY_RIVALRY; } PARAMETRIZE { species = SPECIES_NIDOQUEEN; ability = ABILITY_POISON_POINT; } @@ -32,7 +33,8 @@ SINGLE_BATTLE_TEST("Rivalry increases power by x1.25 towards Pokémon of the sam SINGLE_BATTLE_TEST("Rivalry decreases power by x0.75 towards Pokémon of different gender", s16 damage) { - u16 species1, species2, ability; + u16 species1, species2; + enum Ability ability; PARAMETRIZE { species1 = SPECIES_NIDOKING; species2 = SPECIES_NIDOQUEEN; ability = ABILITY_POISON_POINT; } PARAMETRIZE { species1 = SPECIES_NIDOKING; species2 = SPECIES_NIDOQUEEN; ability = ABILITY_RIVALRY; } PARAMETRIZE { species1 = SPECIES_NIDOQUEEN; species2 = SPECIES_NIDOKING; ability = ABILITY_POISON_POINT; } @@ -54,7 +56,8 @@ SINGLE_BATTLE_TEST("Rivalry decreases power by x0.75 towards Pokémon of differe SINGLE_BATTLE_TEST("Rivalry doesn't modify power if the attacker is genderless", s16 damage) { - u16 species, ability; + u16 species; + enum Ability ability; PARAMETRIZE { species = SPECIES_NIDOKING; ability = ABILITY_POISON_POINT; } PARAMETRIZE { species = SPECIES_NIDOKING; ability = ABILITY_RIVALRY; } PARAMETRIZE { species = SPECIES_NIDOQUEEN; ability = ABILITY_POISON_POINT; } @@ -78,7 +81,8 @@ SINGLE_BATTLE_TEST("Rivalry doesn't modify power if the attacker is genderless", SINGLE_BATTLE_TEST("Rivalry doesn't modify power if the target is genderless", s16 damage) { - u16 species, ability; + u16 species; + enum Ability ability; PARAMETRIZE { species = SPECIES_NIDOKING; ability = ABILITY_POISON_POINT; } PARAMETRIZE { species = SPECIES_NIDOKING; ability = ABILITY_RIVALRY; } PARAMETRIZE { species = SPECIES_NIDOQUEEN; ability = ABILITY_POISON_POINT; } diff --git a/test/battle/ability/rocky_payload.c b/test/battle/ability/rocky_payload.c index a185efb4f9..d688e5c87e 100644 --- a/test/battle/ability/rocky_payload.c +++ b/test/battle/ability/rocky_payload.c @@ -4,7 +4,7 @@ SINGLE_BATTLE_TEST("Rocky Payload increases Rock-type move damage", s16 damage) { u32 move; - u16 ability; + enum Ability ability; PARAMETRIZE { move = MOVE_SCRATCH; ability = ABILITY_BIG_PECKS; } PARAMETRIZE { move = MOVE_SCRATCH; ability = ABILITY_ROCKY_PAYLOAD; } diff --git a/test/battle/ability/sand_force.c b/test/battle/ability/sand_force.c index 7592c5afec..ba062f3fa3 100644 --- a/test/battle/ability/sand_force.c +++ b/test/battle/ability/sand_force.c @@ -3,8 +3,8 @@ SINGLE_BATTLE_TEST("Sand Force prevents damage from sandstorm") { - u32 type1 = GetSpeciesType(SPECIES_SHELLOS, 0); - u32 type2 = GetSpeciesType(SPECIES_SHELLOS, 1); + enum Type type1 = GetSpeciesType(SPECIES_SHELLOS, 0); + enum Type type2 = GetSpeciesType(SPECIES_SHELLOS, 1); GIVEN { ASSUME(type1 != TYPE_ROCK && type2 != TYPE_ROCK); ASSUME(type1 != TYPE_GROUND && type2 != TYPE_GROUND); diff --git a/test/battle/ability/sand_rush.c b/test/battle/ability/sand_rush.c index 4d557348e5..9d6ef98274 100644 --- a/test/battle/ability/sand_rush.c +++ b/test/battle/ability/sand_rush.c @@ -3,8 +3,8 @@ SINGLE_BATTLE_TEST("Sand Rush prevents damage from sandstorm") { - u32 type1 = GetSpeciesType(SPECIES_STOUTLAND, 0); - u32 type2 = GetSpeciesType(SPECIES_STOUTLAND, 1); + enum Type type1 = GetSpeciesType(SPECIES_STOUTLAND, 0); + enum Type type2 = GetSpeciesType(SPECIES_STOUTLAND, 1); GIVEN { ASSUME(type1 != TYPE_ROCK && type2 != TYPE_ROCK); ASSUME(type1 != TYPE_GROUND && type2 != TYPE_GROUND); diff --git a/test/battle/ability/scrappy.c b/test/battle/ability/scrappy.c index 9476f93926..045f7dbde9 100644 --- a/test/battle/ability/scrappy.c +++ b/test/battle/ability/scrappy.c @@ -7,7 +7,7 @@ SINGLE_BATTLE_TEST("Scrappy doesn't prevent Intimidate (Gen4-7)") s16 turnTwoHit; GIVEN { - WITH_CONFIG(GEN_CONFIG_UPDATED_INTIMIDATE, GEN_7); + WITH_CONFIG(CONFIG_UPDATED_INTIMIDATE, GEN_7); PLAYER(SPECIES_EKANS) { Ability(ABILITY_SHED_SKIN); }; PLAYER(SPECIES_EKANS) { Ability(ABILITY_INTIMIDATE); }; OPPONENT(SPECIES_KANGASKHAN) { Ability(ABILITY_SCRAPPY); }; @@ -35,7 +35,7 @@ SINGLE_BATTLE_TEST("Scrappy prevents Intimidate (Gen8+)") s16 turnTwoHit; GIVEN { - WITH_CONFIG(GEN_CONFIG_UPDATED_INTIMIDATE, GEN_8); + WITH_CONFIG(CONFIG_UPDATED_INTIMIDATE, GEN_8); PLAYER(SPECIES_EKANS) { Ability(ABILITY_SHED_SKIN); }; PLAYER(SPECIES_EKANS) { Ability(ABILITY_INTIMIDATE); }; OPPONENT(SPECIES_KANGASKHAN) { Ability(ABILITY_SCRAPPY); }; diff --git a/test/battle/ability/sharpness.c b/test/battle/ability/sharpness.c index 9b89614c36..f737bab72a 100644 --- a/test/battle/ability/sharpness.c +++ b/test/battle/ability/sharpness.c @@ -4,7 +4,7 @@ SINGLE_BATTLE_TEST("Sharpness increases the power of slicing moves by 50%", s16 damage) { u32 move; - u16 ability; + enum Ability ability; PARAMETRIZE { move = MOVE_AERIAL_ACE; ability = ABILITY_SHARPNESS; } PARAMETRIZE { move = MOVE_AERIAL_ACE; ability = ABILITY_STEADFAST; } PARAMETRIZE { move = MOVE_SCRATCH; ability = ABILITY_SHARPNESS; } diff --git a/test/battle/ability/sheer_force.c b/test/battle/ability/sheer_force.c index d14d53571d..abeee88ce7 100644 --- a/test/battle/ability/sheer_force.c +++ b/test/battle/ability/sheer_force.c @@ -8,7 +8,7 @@ ASSUMPTIONS SINGLE_BATTLE_TEST("Sheer Force doesn't boost Magnitude", s16 damage) { - u16 ability = 0; + enum Ability ability = 0; PARAMETRIZE { ability = ABILITY_SHEER_FORCE; } PARAMETRIZE { ability = ABILITY_ANGER_POINT; } GIVEN { @@ -25,7 +25,7 @@ SINGLE_BATTLE_TEST("Sheer Force doesn't boost Magnitude", s16 damage) } SINGLE_BATTLE_TEST("Sheer Force doesn't boost Eruption", s16 damage) { - u16 ability = 0; + enum Ability ability = 0; PARAMETRIZE { ability = ABILITY_SHEER_FORCE; } PARAMETRIZE { ability = ABILITY_ANGER_POINT; } GIVEN { @@ -42,7 +42,7 @@ SINGLE_BATTLE_TEST("Sheer Force doesn't boost Eruption", s16 damage) } SINGLE_BATTLE_TEST("Sheer Force doesn't boost Water Spout", s16 damage) { - u16 ability = 0; + enum Ability ability = 0; PARAMETRIZE { ability = ABILITY_SHEER_FORCE; } PARAMETRIZE { ability = ABILITY_ANGER_POINT; } GIVEN { @@ -59,14 +59,16 @@ SINGLE_BATTLE_TEST("Sheer Force doesn't boost Water Spout", s16 damage) } SINGLE_BATTLE_TEST("Sheer Force doesn't boost Present", s16 damage) { - u16 ability = 0; + enum Ability ability = 0; PARAMETRIZE { ability = ABILITY_SHEER_FORCE; } PARAMETRIZE { ability = ABILITY_ANGER_POINT; } GIVEN { PLAYER(SPECIES_TAUROS) { Ability(ability); } OPPONENT(SPECIES_WOBBUFFET); } WHEN { - TURN { MOVE(player, MOVE_PRESENT); } + //Test will fail if present heals because the hp change would be 0 + //so we want a damaging version of present + TURN { MOVE(player, MOVE_PRESENT, WITH_RNG(RNG_PRESENT, 1)); } } SCENE { HP_BAR(opponent, captureDamage: &results[i].damage); } FINALLY { @@ -76,7 +78,7 @@ SINGLE_BATTLE_TEST("Sheer Force doesn't boost Present", s16 damage) } SINGLE_BATTLE_TEST("Sheer Force doesn't boost Psywave", s16 damage) { - u16 ability = 0; + enum Ability ability = 0; PARAMETRIZE { ability = ABILITY_SHEER_FORCE; } PARAMETRIZE { ability = ABILITY_ANGER_POINT; } GIVEN { @@ -93,7 +95,7 @@ SINGLE_BATTLE_TEST("Sheer Force doesn't boost Psywave", s16 damage) } SINGLE_BATTLE_TEST("Sheer Force doesn't boost Round", s16 damage) { - u16 ability = 0; + enum Ability ability = 0; PARAMETRIZE { ability = ABILITY_SHEER_FORCE; } PARAMETRIZE { ability = ABILITY_ANGER_POINT; } GIVEN { @@ -110,7 +112,7 @@ SINGLE_BATTLE_TEST("Sheer Force doesn't boost Round", s16 damage) } SINGLE_BATTLE_TEST("Sheer Force doesn't boost Gyro Ball", s16 damage) { - u16 ability = 0; + enum Ability ability = 0; PARAMETRIZE { ability = ABILITY_SHEER_FORCE; } PARAMETRIZE { ability = ABILITY_ANGER_POINT; } GIVEN { @@ -127,7 +129,7 @@ SINGLE_BATTLE_TEST("Sheer Force doesn't boost Gyro Ball", s16 damage) } SINGLE_BATTLE_TEST("Sheer Force doesn't boost Electro Ball", s16 damage) { - u16 ability = 0; + enum Ability ability = 0; PARAMETRIZE { ability = ABILITY_SHEER_FORCE; } PARAMETRIZE { ability = ABILITY_ANGER_POINT; } GIVEN { @@ -144,7 +146,7 @@ SINGLE_BATTLE_TEST("Sheer Force doesn't boost Electro Ball", s16 damage) } SINGLE_BATTLE_TEST("Sheer Force doesn't boost Dragon Energy", s16 damage) { - u16 ability = 0; + enum Ability ability = 0; PARAMETRIZE { ability = ABILITY_SHEER_FORCE; } PARAMETRIZE { ability = ABILITY_ANGER_POINT; } GIVEN { @@ -161,7 +163,7 @@ SINGLE_BATTLE_TEST("Sheer Force doesn't boost Dragon Energy", s16 damage) } SINGLE_BATTLE_TEST("Sheer Force doesn't boost Belch", s16 damage) { - u16 ability = 0; + enum Ability ability = 0; PARAMETRIZE { ability = ABILITY_SHEER_FORCE; } PARAMETRIZE { ability = ABILITY_ANGER_POINT; } GIVEN { @@ -178,7 +180,7 @@ SINGLE_BATTLE_TEST("Sheer Force doesn't boost Belch", s16 damage) } SINGLE_BATTLE_TEST("Sheer Force doesn't boost Shell Trap", s16 damage) { - u16 ability = 0; + enum Ability ability = 0; PARAMETRIZE { ability = ABILITY_SHEER_FORCE; } PARAMETRIZE { ability = ABILITY_ANGER_POINT; } GIVEN { @@ -195,7 +197,7 @@ SINGLE_BATTLE_TEST("Sheer Force doesn't boost Shell Trap", s16 damage) } SINGLE_BATTLE_TEST("Sheer Force doesn't boost Burn Up", s16 damage) { - u16 ability = 0; + enum Ability ability = 0; PARAMETRIZE { ability = ABILITY_SHEER_FORCE; } PARAMETRIZE { ability = ABILITY_ZEN_MODE; } GIVEN { @@ -229,7 +231,7 @@ SINGLE_BATTLE_TEST("Sheer Force doesn't boost Double Shock", s16 damage) } SINGLE_BATTLE_TEST("Sheer Force doesn't boost Steel Roller", s16 damage) { - u16 ability = 0; + enum Ability ability = 0; PARAMETRIZE { ability = ABILITY_SHEER_FORCE; } PARAMETRIZE { ability = ABILITY_ANGER_POINT; } GIVEN { @@ -246,7 +248,7 @@ SINGLE_BATTLE_TEST("Sheer Force doesn't boost Steel Roller", s16 damage) } SINGLE_BATTLE_TEST("Sheer Force doesn't boost Synchronoise", s16 damage) { - u16 ability = 0; + enum Ability ability = 0; PARAMETRIZE { ability = ABILITY_SHEER_FORCE; } PARAMETRIZE { ability = ABILITY_ANGER_POINT; } GIVEN { @@ -297,7 +299,7 @@ SINGLE_BATTLE_TEST("Sheer Force doesn't boost Hyperspace Fury", s16 damage) } SINGLE_BATTLE_TEST("Sheer Force doesn't boost Bolt Beak", s16 damage) { - u16 ability = 0; + enum Ability ability = 0; PARAMETRIZE { ability = ABILITY_SHEER_FORCE; } PARAMETRIZE { ability = ABILITY_ANGER_POINT; } GIVEN { @@ -314,7 +316,7 @@ SINGLE_BATTLE_TEST("Sheer Force doesn't boost Bolt Beak", s16 damage) } SINGLE_BATTLE_TEST("Sheer Force doesn't boost Fishious Rend", s16 damage) { - u16 ability = 0; + enum Ability ability = 0; PARAMETRIZE { ability = ABILITY_SHEER_FORCE; } PARAMETRIZE { ability = ABILITY_ANGER_POINT; } GIVEN { @@ -331,7 +333,7 @@ SINGLE_BATTLE_TEST("Sheer Force doesn't boost Fishious Rend", s16 damage) } SINGLE_BATTLE_TEST("Sheer Force doesn't boost Comeuppance", s16 damage) { - u16 ability = 0; + enum Ability ability = 0; PARAMETRIZE { ability = ABILITY_SHEER_FORCE; } PARAMETRIZE { ability = ABILITY_ANGER_POINT; } GIVEN { @@ -348,7 +350,7 @@ SINGLE_BATTLE_TEST("Sheer Force doesn't boost Comeuppance", s16 damage) } SINGLE_BATTLE_TEST("Sheer Force doesn't boost Payback", s16 damage) { - u16 ability = 0; + enum Ability ability = 0; PARAMETRIZE { ability = ABILITY_SHEER_FORCE; } PARAMETRIZE { ability = ABILITY_ANGER_POINT; } GIVEN { @@ -1358,3 +1360,20 @@ DOUBLE_BATTLE_TEST("Sheer Force only boosts the damage of moves it's supposed to EXPECT_EQ(damage2, damage1); } } + +AI_SINGLE_BATTLE_TEST("AI sees Sheer Force skips additional effects") +{ + u16 ability, expectedMove, move; + + PARAMETRIZE { ability = ABILITY_ROUGH_SKIN; move = MOVE_KARATE_CHOP; expectedMove = MOVE_POWER_UP_PUNCH; } + PARAMETRIZE { ability = ABILITY_ROUGH_SKIN; move = MOVE_BRICK_BREAK; expectedMove = MOVE_POWER_UP_PUNCH; } + PARAMETRIZE { ability = ABILITY_SHEER_FORCE; move = MOVE_BRICK_BREAK; expectedMove = MOVE_BRICK_BREAK; } + + GIVEN { + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_DRUDDIGON) { Ability(ability); Moves(MOVE_POWER_UP_PUNCH, move); } + } WHEN { + TURN { EXPECT_MOVE(opponent, expectedMove); } + } +} diff --git a/test/battle/ability/snow_warning.c b/test/battle/ability/snow_warning.c index 171ad23b49..bffee14e49 100644 --- a/test/battle/ability/snow_warning.c +++ b/test/battle/ability/snow_warning.c @@ -4,7 +4,7 @@ SINGLE_BATTLE_TEST("Snow Warning summons hail (Gen4-8)") { GIVEN { - WITH_CONFIG(GEN_SNOW_WARNING, GEN_8); + WITH_CONFIG(CONFIG_SNOW_WARNING, GEN_8); PLAYER(SPECIES_ABOMASNOW) { Ability(ABILITY_SNOW_WARNING); } OPPONENT(SPECIES_WOBBUFFET); } WHEN { @@ -18,7 +18,7 @@ SINGLE_BATTLE_TEST("Snow Warning summons hail (Gen4-8)") SINGLE_BATTLE_TEST("Snow Warning summons snow (Gen9+)") { GIVEN { - WITH_CONFIG(GEN_SNOW_WARNING, GEN_9); + WITH_CONFIG(CONFIG_SNOW_WARNING, GEN_9); PLAYER(SPECIES_ABOMASNOW) { Ability(ABILITY_SNOW_WARNING); } OPPONENT(SPECIES_WOBBUFFET); } WHEN { diff --git a/test/battle/ability/solid_rock.c b/test/battle/ability/solid_rock.c index d15b87e236..d25fca6259 100644 --- a/test/battle/ability/solid_rock.c +++ b/test/battle/ability/solid_rock.c @@ -3,7 +3,7 @@ SINGLE_BATTLE_TEST("Solid Rock reduces damage to Super Effective moves by 0.75", s16 damage) { - u32 ability; + enum Ability ability; PARAMETRIZE { ability = ABILITY_STURDY; } PARAMETRIZE { ability = ABILITY_SOLID_ROCK; } GIVEN { diff --git a/test/battle/ability/stalwart.c b/test/battle/ability/stalwart.c index 22debe74cd..6bebe17cb6 100644 --- a/test/battle/ability/stalwart.c +++ b/test/battle/ability/stalwart.c @@ -20,7 +20,8 @@ DOUBLE_BATTLE_TEST("Stalwart ignores redirection from Follow-Me") DOUBLE_BATTLE_TEST("Stalwart stops Lightning Rod and Storm Drain from redirecting moves") { - u32 ability, species; + enum Ability ability; + u32 species; PARAMETRIZE { ability = ABILITY_STORM_DRAIN; species = SPECIES_LUMINEON; } PARAMETRIZE { ability = ABILITY_LIGHTNING_ROD; species = SPECIES_RAICHU; } GIVEN { diff --git a/test/battle/ability/stamina.c b/test/battle/ability/stamina.c index e9823b7068..39113fd15a 100644 --- a/test/battle/ability/stamina.c +++ b/test/battle/ability/stamina.c @@ -49,7 +49,7 @@ SINGLE_BATTLE_TEST("Stamina raises Defense by 1 when hit by a move") DOUBLE_BATTLE_TEST("Stamina activates correctly for every battler with the ability when hit by a multi target move") { - u16 abilityLeft, abilityRight; + enum Ability abilityLeft, abilityRight; PARAMETRIZE {abilityLeft = ABILITY_NONE, abilityRight = ABILITY_STAMINA; } PARAMETRIZE {abilityLeft = ABILITY_STAMINA, abilityRight = ABILITY_NONE; } diff --git a/test/battle/ability/steelworker.c b/test/battle/ability/steelworker.c index eaf36165f6..b4fa720cdc 100644 --- a/test/battle/ability/steelworker.c +++ b/test/battle/ability/steelworker.c @@ -4,7 +4,7 @@ SINGLE_BATTLE_TEST("Steelworker increases Steel-type move damage", s16 damage) { u32 move; - u16 ability; + enum Ability ability; PARAMETRIZE { move = MOVE_SCRATCH; ability = ABILITY_KLUTZ; } PARAMETRIZE { move = MOVE_SCRATCH; ability = ABILITY_STEELWORKER; } diff --git a/test/battle/ability/super_luck.c b/test/battle/ability/super_luck.c index 016ff3fae1..16dfc081a9 100644 --- a/test/battle/ability/super_luck.c +++ b/test/battle/ability/super_luck.c @@ -11,7 +11,7 @@ SINGLE_BATTLE_TEST("Super Luck increases the critical hit ratio by 1 stage") PASSES_RANDOMLY(passes, trials, RNG_CRITICAL_HIT); GIVEN { ASSUME(GetSpeciesBaseSpeed(SPECIES_TOGEPI) == 20); - WITH_CONFIG(GEN_CONFIG_CRIT_CHANCE, genConfig); + WITH_CONFIG(CONFIG_CRIT_CHANCE, genConfig); PLAYER(SPECIES_TOGEPI) { Ability(ABILITY_SUPER_LUCK); }; OPPONENT(SPECIES_WOBBUFFET); } WHEN { diff --git a/test/battle/ability/sword_of_ruin.c b/test/battle/ability/sword_of_ruin.c index 395cd3fd68..a891f7d5a7 100644 --- a/test/battle/ability/sword_of_ruin.c +++ b/test/battle/ability/sword_of_ruin.c @@ -73,3 +73,118 @@ SINGLE_BATTLE_TEST("Sword of Ruin's message displays correctly after all battler MESSAGE("The opposing Chien-Pao's Sword of Ruin weakened the Defense of all surrounding Pokémon!"); } } + +DOUBLE_BATTLE_TEST("Sword of Ruin increases damage taken by special moves in Wonder Room", s16 damage) +{ + bool32 useWonderRoom; + u32 move; + + PARAMETRIZE { useWonderRoom = FALSE; move = MOVE_SCRATCH; } + PARAMETRIZE { useWonderRoom = FALSE; move = MOVE_ROUND; } + PARAMETRIZE { useWonderRoom = TRUE; move = MOVE_SCRATCH; } + PARAMETRIZE { useWonderRoom = TRUE; move = MOVE_ROUND; } + + GIVEN { + ASSUME(GetMoveEffect(MOVE_WONDER_ROOM) == EFFECT_WONDER_ROOM); + ASSUME(GetMoveCategory(MOVE_ROUND) == DAMAGE_CATEGORY_SPECIAL); + ASSUME(GetMoveEffect(MOVE_ROUND) != EFFECT_PSYSHOCK); + PLAYER(SPECIES_CHIEN_PAO) { Ability(ABILITY_SWORD_OF_RUIN); } + PLAYER(SPECIES_WYNAUT); + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + if (useWonderRoom) + TURN { MOVE(opponentLeft, MOVE_WONDER_ROOM); MOVE(playerRight, move, target: opponentLeft); } + else + TURN { MOVE(playerRight, move, target: opponentLeft); } + } SCENE { + ABILITY_POPUP(playerLeft, ABILITY_SWORD_OF_RUIN); + MESSAGE("Chien-Pao's Sword of Ruin weakened the Defense of all surrounding Pokémon!"); + ANIMATION(ANIM_TYPE_MOVE, move, playerRight); + HP_BAR(opponentLeft, captureDamage: &results[i].damage); + } FINALLY { + EXPECT_LT(results[2].damage, results[0].damage); // In Wonder Room, physical move deals less damage + EXPECT_GT(results[3].damage, results[1].damage); // In Wonder Room, special move deals more damage + } +} + +SINGLE_BATTLE_TEST("Sword of Ruin doesn't activate when dragged out by Mold Breaker attacker") +{ + u32 ability; + + PARAMETRIZE { ability = ABILITY_MOLD_BREAKER; } + PARAMETRIZE { ability = ABILITY_SAND_RUSH; } + + GIVEN { + ASSUME(GetMoveEffect(MOVE_DRAGON_TAIL) == EFFECT_HIT_SWITCH_TARGET); + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_CHIEN_PAO) { Ability(ABILITY_SWORD_OF_RUIN); } + OPPONENT(SPECIES_EXCADRILL) { Ability(ability); } + } WHEN { + TURN { MOVE(opponent, MOVE_DRAGON_TAIL); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_DRAGON_TAIL, opponent); + if (ability == ABILITY_MOLD_BREAKER) + { + NONE_OF { + ABILITY_POPUP(player, ABILITY_SWORD_OF_RUIN); + MESSAGE("Chien-Pao's Sword of Ruin weakened the Defense of all surrounding Pokémon!"); + } + } + else + { + ABILITY_POPUP(player, ABILITY_SWORD_OF_RUIN); + MESSAGE("Chien-Pao's Sword of Ruin weakened the Defense of all surrounding Pokémon!"); + } + } +} + +DOUBLE_BATTLE_TEST("Sword of Ruin's Defense reduction is not ignored by Mold Breaker", s16 damage) +{ + u32 ability; + + PARAMETRIZE { ability = ABILITY_MOLD_BREAKER; } + PARAMETRIZE { ability = ABILITY_SAND_RUSH; } + + GIVEN { + PLAYER(SPECIES_CHIEN_PAO) { Ability(ABILITY_SWORD_OF_RUIN); } + PLAYER(SPECIES_WYNAUT); + OPPONENT(SPECIES_EXCADRILL) { Ability(ability); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponentLeft, MOVE_SCRATCH, target: playerRight); } + } SCENE { + ABILITY_POPUP(playerLeft, ABILITY_SWORD_OF_RUIN); + MESSAGE("Chien-Pao's Sword of Ruin weakened the Defense of all surrounding Pokémon!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SCRATCH, opponentLeft); + HP_BAR(playerRight, captureDamage: &results[i].damage); + } FINALLY { + EXPECT_EQ(results[0].damage, results[1].damage); + } +} + +DOUBLE_BATTLE_TEST("Sword of Ruin's Defense reduction is ignored by Gastro Acid", s16 damage) +{ + u32 move; + + PARAMETRIZE { move = MOVE_GASTRO_ACID; } + PARAMETRIZE { move = MOVE_CELEBRATE; } + + GIVEN { + ASSUME(GetMoveEffect(MOVE_GASTRO_ACID) == EFFECT_GASTRO_ACID); + PLAYER(SPECIES_CHIEN_PAO) { Ability(ABILITY_SWORD_OF_RUIN); } + PLAYER(SPECIES_WYNAUT); + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponentRight, move, target: playerLeft); MOVE(opponentLeft, MOVE_SCRATCH, target: playerRight); } + } SCENE { + ABILITY_POPUP(playerLeft, ABILITY_SWORD_OF_RUIN); + MESSAGE("Chien-Pao's Sword of Ruin weakened the Defense of all surrounding Pokémon!"); + ANIMATION(ANIM_TYPE_MOVE, move, opponentRight); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SCRATCH, opponentLeft); + HP_BAR(playerRight, captureDamage: &results[i].damage); + } FINALLY { + EXPECT_LT(results[0].damage, results[1].damage); + } +} diff --git a/test/battle/ability/symbiosis.c b/test/battle/ability/symbiosis.c index 932008d9d7..44e7c5f1bd 100644 --- a/test/battle/ability/symbiosis.c +++ b/test/battle/ability/symbiosis.c @@ -132,3 +132,49 @@ DOUBLE_BATTLE_TEST("Symbiosis transfers its item to an ally after it consumes a EXPECT_EQ(playerRight->item, ITEM_NONE); } } + +DOUBLE_BATTLE_TEST("Symbiosis transfers its item after Gem consumption and move execution (Gen7+)") +{ + GIVEN { + ASSUME(GetItemHoldEffect(ITEM_NORMAL_GEM) == HOLD_EFFECT_GEMS); + WITH_CONFIG(CONFIG_SYMBIOSIS_GEMS, GEN_7); + PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_NORMAL_GEM); } + PLAYER(SPECIES_ORANGURU) { Ability(ABILITY_SYMBIOSIS); Item(ITEM_TOXIC_ORB); } + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(playerLeft, MOVE_SCRATCH, target: opponentLeft); } + } SCENE { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, playerLeft); + MESSAGE("The Normal Gem strengthened Wobbuffet's power!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SCRATCH, playerLeft); + ABILITY_POPUP(playerRight, ABILITY_SYMBIOSIS); + STATUS_ICON(playerLeft, STATUS1_TOXIC_POISON); + } THEN { + EXPECT_EQ(playerLeft->item, ITEM_TOXIC_ORB); + EXPECT_EQ(playerRight->item, ITEM_NONE); + } +} + +DOUBLE_BATTLE_TEST("Symbiosis transfers its item after Gem consumption, but before move execution (Gen6)") +{ + GIVEN { + ASSUME(GetItemHoldEffect(ITEM_NORMAL_GEM) == HOLD_EFFECT_GEMS); + WITH_CONFIG(CONFIG_SYMBIOSIS_GEMS, GEN_6); + PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_NORMAL_GEM); } + PLAYER(SPECIES_ORANGURU) { Ability(ABILITY_SYMBIOSIS); Item(ITEM_TOXIC_ORB); } + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(playerLeft, MOVE_SCRATCH, target: opponentLeft); } + } SCENE { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, playerLeft); + MESSAGE("The Normal Gem strengthened Wobbuffet's power!"); + ABILITY_POPUP(playerRight, ABILITY_SYMBIOSIS); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SCRATCH, playerLeft); + STATUS_ICON(playerLeft, STATUS1_TOXIC_POISON); + } THEN { + EXPECT_EQ(playerLeft->item, ITEM_TOXIC_ORB); + EXPECT_EQ(playerRight->item, ITEM_NONE); + } +} diff --git a/test/battle/ability/synchronize.c b/test/battle/ability/synchronize.c index e150e2950e..8e92936e41 100644 --- a/test/battle/ability/synchronize.c +++ b/test/battle/ability/synchronize.c @@ -25,6 +25,7 @@ SINGLE_BATTLE_TEST("Synchronize will mirror back non volatile status back at opp SINGLE_BATTLE_TEST("Synchronize will still show up the ability pop up even if it fails") { GIVEN { + WITH_CONFIG(CONFIG_PARALYZE_ELECTRIC, GEN_6); ASSUME(MoveMakesContact(MOVE_TACKLE)); PLAYER(SPECIES_PIKACHU) { Ability(ABILITY_STATIC); } OPPONENT(SPECIES_ABRA) { Ability(ABILITY_SYNCHRONIZE); } diff --git a/test/battle/ability/tangling_hair.c b/test/battle/ability/tangling_hair.c index 849c83df64..fdae4de06d 100644 --- a/test/battle/ability/tangling_hair.c +++ b/test/battle/ability/tangling_hair.c @@ -97,3 +97,17 @@ SINGLE_BATTLE_TEST("Tangling Hair does not trigger on Clear Body") NOT ABILITY_POPUP(player, ABILITY_TANGLING_HAIR); } } + +SINGLE_BATTLE_TEST("Tangling Hair will trigger if move is boosted by Sheer Force") +{ + ASSUME(MoveIsAffectedBySheerForce(MOVE_POISON_JAB)); + GIVEN { + PLAYER(SPECIES_DUGTRIO) { Ability(ABILITY_TANGLING_HAIR); } + OPPONENT(SPECIES_NIDOKING) { Ability(ABILITY_SHEER_FORCE); }; + } WHEN { + TURN { MOVE(opponent, MOVE_POISON_JAB); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_POISON_JAB, opponent); + ABILITY_POPUP(player, ABILITY_TANGLING_HAIR); + } +} diff --git a/test/battle/ability/teraform_zero.c b/test/battle/ability/teraform_zero.c index 96186f2047..f6620d6625 100644 --- a/test/battle/ability/teraform_zero.c +++ b/test/battle/ability/teraform_zero.c @@ -39,11 +39,12 @@ DOUBLE_BATTLE_TEST("Teraform Zero can be supressed") SINGLE_BATTLE_TEST("Teraform Zero can be replaced") { GIVEN { - ASSUME(GetMoveEffect(MOVE_WORRY_SEED) == EFFECT_WORRY_SEED); + ASSUME(GetMoveEffect(MOVE_WORRY_SEED) == EFFECT_OVERWRITE_ABILITY); ASSUME(GetMoveEffect(MOVE_REST) == EFFECT_REST); PLAYER(SPECIES_TERAPAGOS); OPPONENT(SPECIES_WHIMSICOTT) { Ability(ABILITY_PRANKSTER); } } WHEN { + TURN { MOVE(opponent, MOVE_POUND); } TURN { MOVE(opponent, MOVE_WORRY_SEED); MOVE(player, MOVE_REST, gimmick: GIMMICK_TERA); } } SCENE { MESSAGE("The opposing Whimsicott used Worry Seed!"); diff --git a/test/battle/ability/trace.c b/test/battle/ability/trace.c index 6dbd9bda26..71d5035084 100644 --- a/test/battle/ability/trace.c +++ b/test/battle/ability/trace.c @@ -46,7 +46,7 @@ SINGLE_BATTLE_TEST("Trace copies opponents ability on switch-in even if opponent DOUBLE_BATTLE_TEST("Trace copies opponents ability randomly") { - u16 ability1, ability2; + enum Ability ability1, ability2; PARAMETRIZE { ability1 = ABILITY_SPEED_BOOST; ability2 = ABILITY_BLAZE;} PARAMETRIZE { ability1 = ABILITY_BLAZE; ability2 = ABILITY_SPEED_BOOST; } diff --git a/test/battle/ability/transistor.c b/test/battle/ability/transistor.c index 8b8f098d52..e57043a5c2 100644 --- a/test/battle/ability/transistor.c +++ b/test/battle/ability/transistor.c @@ -7,7 +7,7 @@ SINGLE_BATTLE_TEST("Transistor increases Electric-type attack / special attack", s16 damage) { u32 move; - u16 ability; + enum Ability ability; PARAMETRIZE { move = MOVE_SCRATCH; ability = ABILITY_KLUTZ; } PARAMETRIZE { move = MOVE_SCRATCH; ability = ABILITY_TRANSISTOR; } @@ -38,7 +38,7 @@ SINGLE_BATTLE_TEST("Transistor increases Electric-type attack / special attack", SINGLE_BATTLE_TEST("Transistor is blocked by neutralizing gas", s16 damage) { - u16 ability; + enum Ability ability; PARAMETRIZE { ability = ABILITY_NEUTRALIZING_GAS; } PARAMETRIZE { ability = ABILITY_LEVITATE; } diff --git a/test/battle/ability/unburden.c b/test/battle/ability/unburden.c index 0ddce0f227..4498bb4922 100644 --- a/test/battle/ability/unburden.c +++ b/test/battle/ability/unburden.c @@ -4,7 +4,7 @@ SINGLE_BATTLE_TEST("Unburden doubles speed once user uses item") { GIVEN { - ASSUME(GetItemHoldEffect(ITEM_GRASSY_SEED) == HOLD_EFFECT_SEEDS); + ASSUME(GetItemHoldEffect(ITEM_GRASSY_SEED) == HOLD_EFFECT_TERRAIN_SEED); ASSUME(GetMoveEffect(MOVE_U_TURN) == EFFECT_HIT_ESCAPE); PLAYER(SPECIES_DRIFBLIM) { Ability(ABILITY_UNBURDEN); Item(ITEM_GRASSY_SEED); Speed(5); } OPPONENT(SPECIES_WOBBUFFET) { Speed(7); } diff --git a/test/battle/ability/unnerve.c b/test/battle/ability/unnerve.c index 9a8972eb5c..a1eabbcf5a 100644 --- a/test/battle/ability/unnerve.c +++ b/test/battle/ability/unnerve.c @@ -5,7 +5,7 @@ SINGLE_BATTLE_TEST("Unnerve prevents opposing Pokémon from eating their own berries") { u16 mon; - u16 ability; + enum Ability ability; PARAMETRIZE { mon = SPECIES_JOLTIK, ability = ABILITY_UNNERVE; } PARAMETRIZE { mon = SPECIES_CALYREX_ICE, ability = ABILITY_AS_ONE_ICE_RIDER; } GIVEN { @@ -24,7 +24,7 @@ SINGLE_BATTLE_TEST("Unnerve prevents opposing Pokémon from eating their own ber SINGLE_BATTLE_TEST("Unnerve doesn't prevent opposing Pokémon from using Natural Gift") { u16 mon; - u16 ability; + enum Ability ability; PARAMETRIZE { mon = SPECIES_JOLTIK, ability = ABILITY_UNNERVE; } PARAMETRIZE { mon = SPECIES_CALYREX_ICE, ability = ABILITY_AS_ONE_ICE_RIDER; } GIVEN { @@ -42,7 +42,7 @@ SINGLE_BATTLE_TEST("Unnerve doesn't prevent opposing Pokémon from using Natural SINGLE_BATTLE_TEST("Unnerve prints the correct string (player)") { u16 mon; - u16 ability; + enum Ability ability; PARAMETRIZE { mon = SPECIES_JOLTIK, ability = ABILITY_UNNERVE; } PARAMETRIZE { mon = SPECIES_CALYREX_ICE, ability = ABILITY_AS_ONE_ICE_RIDER; } GIVEN { @@ -59,7 +59,7 @@ SINGLE_BATTLE_TEST("Unnerve prints the correct string (player)") SINGLE_BATTLE_TEST("Unnerve prints the correct string (opponent)") { u16 mon; - u16 ability; + enum Ability ability; PARAMETRIZE { mon = SPECIES_JOLTIK, ability = ABILITY_UNNERVE; } PARAMETRIZE { mon = SPECIES_CALYREX_ICE, ability = ABILITY_AS_ONE_ICE_RIDER; } GIVEN { @@ -76,7 +76,7 @@ SINGLE_BATTLE_TEST("Unnerve prints the correct string (opponent)") SINGLE_BATTLE_TEST("Unnerve activates only once per switch-in") { u16 mon; - u16 ability; + enum Ability ability; PARAMETRIZE { mon = SPECIES_JOLTIK, ability = ABILITY_UNNERVE; } PARAMETRIZE { mon = SPECIES_CALYREX_ICE, ability = ABILITY_AS_ONE_ICE_RIDER; } GIVEN { @@ -99,3 +99,28 @@ SINGLE_BATTLE_TEST("Unnerve activates only once per switch-in") } } + +DOUBLE_BATTLE_TEST("Unnerve stops applying on death but applies on revive") +{ + u16 mon; + u16 ability; + PARAMETRIZE { mon = SPECIES_JOLTIK, ability = ABILITY_UNNERVE;} + PARAMETRIZE { mon = SPECIES_CALYREX_ICE, ability = ABILITY_AS_ONE_ICE_RIDER; } + GIVEN { + ASSUME(gItemsInfo[ITEM_RAWST_BERRY].holdEffect == HOLD_EFFECT_CURE_BRN); + ASSUME(gItemsInfo[ITEM_REVIVE].battleUsage == EFFECT_ITEM_REVIVE); + PLAYER(SPECIES_WOBBUFFET); + PLAYER(mon) { Ability(ability); HP(1); } + OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_RAWST_BERRY); Status1(STATUS1_BURN); } + OPPONENT(SPECIES_WYNAUT) { Item(ITEM_RAWST_BERRY); } + } WHEN { + TURN { MOVE(opponentLeft, MOVE_SCRATCH, target: playerRight); } + TURN { USE_ITEM(playerLeft, ITEM_REVIVE, partyIndex: 1); SKIP_TURN(playerRight); MOVE(opponentLeft, MOVE_WILL_O_WISP, target: opponentRight); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SCRATCH, opponentLeft); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, opponentLeft); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_BRN, opponentRight); + NOT ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, opponentRight); + } + +} diff --git a/test/battle/ability/vessel_of_ruin.c b/test/battle/ability/vessel_of_ruin.c index 30c7520c36..1a075db8cf 100644 --- a/test/battle/ability/vessel_of_ruin.c +++ b/test/battle/ability/vessel_of_ruin.c @@ -73,3 +73,76 @@ SINGLE_BATTLE_TEST("Vessel of Ruin's message displays correctly after all battle MESSAGE("The opposing Ting-Lu's Vessel of Ruin weakened the Sp. Atk of all surrounding Pokémon!"); } } + +DOUBLE_BATTLE_TEST("Vessel of Ruin does not reduce Sp. Atk if Neutralizing Gas is on the field") +{ + s16 damage[2]; + + GIVEN { + PLAYER(SPECIES_WYNAUT); + PLAYER(SPECIES_TING_LU) { Ability(ABILITY_VESSEL_OF_RUIN); } + OPPONENT(SPECIES_WYNAUT); + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WEEZING) { Ability(ABILITY_NEUTRALIZING_GAS); } + } WHEN { + TURN { + MOVE(playerLeft, MOVE_WATER_GUN, target: opponentLeft); + } + TURN { + SWITCH(opponentRight, 2); + MOVE(playerLeft, MOVE_WATER_GUN, target: opponentLeft); + } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_WATER_GUN, playerLeft); + HP_BAR(opponentLeft, captureDamage: &damage[0]); + ANIMATION(ANIM_TYPE_MOVE, MOVE_WATER_GUN, playerLeft); + HP_BAR(opponentLeft, captureDamage: &damage[1]); + } THEN { + EXPECT_MUL_EQ(damage[0], Q_4_12(1.33), damage[1]); + } +} + +SINGLE_BATTLE_TEST("Vessel of Ruin is still active if removed by Mold Breaker + Entrainment") +{ + s16 damage[2]; + + GIVEN { + PLAYER(SPECIES_TING_LU) { Ability(ABILITY_VESSEL_OF_RUIN); } + OPPONENT(SPECIES_PINSIR) { Ability(ABILITY_MOLD_BREAKER); } + } WHEN { + TURN { MOVE(opponent, MOVE_WATER_GUN); } + TURN { MOVE(opponent, MOVE_ENTRAINMENT); } + TURN { MOVE(opponent, MOVE_WATER_GUN); } + } SCENE { + ABILITY_POPUP(player, ABILITY_VESSEL_OF_RUIN); + MESSAGE("Ting-Lu's Vessel of Ruin weakened the Sp. Atk of all surrounding Pokémon!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_WATER_GUN, opponent); + HP_BAR(player, captureDamage: &damage[0]); + ANIMATION(ANIM_TYPE_MOVE, MOVE_ENTRAINMENT, opponent); + ANIMATION(ANIM_TYPE_MOVE, MOVE_WATER_GUN, opponent); + HP_BAR(player, captureDamage: &damage[1]); + } THEN { + EXPECT_EQ(damage[0], damage[1]); + } +} + +DOUBLE_BATTLE_TEST("Vessel of Ruin is active if removed by Mold Breaker Entrainment and Sword of Ruin is active after obtaining it") +{ + GIVEN { + PLAYER(SPECIES_TING_LU) { Ability(ABILITY_VESSEL_OF_RUIN); } + PLAYER(SPECIES_CHIEN_PAO) { Ability(ABILITY_SWORD_OF_RUIN); } + OPPONENT(SPECIES_PINSIR) { Ability(ABILITY_MOLD_BREAKER); } + OPPONENT(SPECIES_WOBBUFFET) { Ability(ABILITY_TELEPATHY); } + } WHEN { + TURN { + MOVE(opponentLeft, MOVE_ENTRAINMENT, target: playerLeft); + MOVE(opponentRight, MOVE_SKILL_SWAP, target: playerLeft); + MOVE(playerRight, MOVE_SKILL_SWAP, target: playerLeft); + } + } THEN { + bool32 isVesselOfRuinActive = gBattleMons[B_POSITION_PLAYER_LEFT].volatiles.vesselOfRuin; + bool32 isSwordOfRuinActive = gBattleMons[B_POSITION_PLAYER_LEFT].volatiles.swordOfRuin; + EXPECT_EQ(isVesselOfRuinActive, TRUE); + EXPECT_EQ(isSwordOfRuinActive, TRUE); + } +} diff --git a/test/battle/ability/water_bubble.c b/test/battle/ability/water_bubble.c index d140dac040..1d1d3956d4 100644 --- a/test/battle/ability/water_bubble.c +++ b/test/battle/ability/water_bubble.c @@ -12,7 +12,7 @@ SINGLE_BATTLE_TEST("Water Bubble prevents burn from Will-o-Wisp") TURN { MOVE(opponent, MOVE_WILL_O_WISP); } } SCENE { ABILITY_POPUP(player, ABILITY_WATER_BUBBLE); - MESSAGE("Dewpider's Water Bubble prevents burns!"); + MESSAGE("It doesn't affect Dewpider…"); NONE_OF { ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_BRN, player); STATUS_ICON(player, burn: TRUE); diff --git a/test/battle/ability/water_compaction.c b/test/battle/ability/water_compaction.c index e4e32e2713..8e7751e376 100644 --- a/test/battle/ability/water_compaction.c +++ b/test/battle/ability/water_compaction.c @@ -43,7 +43,7 @@ SINGLE_BATTLE_TEST("Water Compaction raises Defense 2 stages on each hit of a mu SINGLE_BATTLE_TEST("Water Compaction does not affect damage taken from Water type moves", s16 damage) { - u16 ability; + enum Ability ability; PARAMETRIZE { ability = ABILITY_SAND_VEIL; } PARAMETRIZE { ability = ABILITY_WATER_COMPACTION; } GIVEN { diff --git a/test/battle/ability/weak_armor.c b/test/battle/ability/weak_armor.c index cae8383dde..b8a9337d67 100644 --- a/test/battle/ability/weak_armor.c +++ b/test/battle/ability/weak_armor.c @@ -18,7 +18,7 @@ SINGLE_BATTLE_TEST("Weak Armor lowers Defense by 1 and boosts Speed by 1 (Gen5-6 PARAMETRIZE { move = MOVE_GUST; gen = GEN_7; } GIVEN { - WITH_CONFIG(GEN_CONFIG_WEAK_ARMOR_SPEED, gen); + WITH_CONFIG(CONFIG_WEAK_ARMOR_SPEED, gen); PLAYER(SPECIES_SLUGMA) { Ability(ABILITY_WEAK_ARMOR); } OPPONENT(SPECIES_WOBBUFFET); } WHEN { @@ -29,14 +29,10 @@ SINGLE_BATTLE_TEST("Weak Armor lowers Defense by 1 and boosts Speed by 1 (Gen5-6 if (move == MOVE_SCRATCH) { ABILITY_POPUP(player, ABILITY_WEAK_ARMOR); ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); - MESSAGE("Slugma's Weak Armor lowered its Defense!"); - MESSAGE("Slugma's Weak Armor raised its Speed!"); } else { NONE_OF { ABILITY_POPUP(player, ABILITY_WEAK_ARMOR); ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); - MESSAGE("Slugma's Weak Armor lowered its Defense!"); - MESSAGE("Slugma's Weak Armor raised its Speed!"); } } } THEN { @@ -73,7 +69,7 @@ SINGLE_BATTLE_TEST("Weak Armor does not trigger when brought in by Dragon Tail a ABILITY_POPUP(player, ABILITY_WEAK_ARMOR); ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); MESSAGE("Slugma's Weak Armor lowered its Defense!"); - MESSAGE("Slugma's Weak Armor raised its Speed!"); + MESSAGE("Slugma's Weak Armor sharply raised its Speed!"); } } THEN { EXPECT_EQ(player->statStages[STAT_DEF], DEFAULT_STAT_STAGE); @@ -88,7 +84,7 @@ SINGLE_BATTLE_TEST("Weak Armor still boosts Speed if Defense can't go any lower" PARAMETRIZE { gen = GEN_6; } PARAMETRIZE { gen = GEN_7; } GIVEN { - WITH_CONFIG(GEN_CONFIG_WEAK_ARMOR_SPEED, gen); + WITH_CONFIG(CONFIG_WEAK_ARMOR_SPEED, gen); PLAYER(SPECIES_SLUGMA) { Ability(ABILITY_WEAK_ARMOR); } OPPONENT(SPECIES_WOBBUFFET); } WHEN { @@ -106,7 +102,11 @@ SINGLE_BATTLE_TEST("Weak Armor still boosts Speed if Defense can't go any lower" } MESSAGE("Slugma's Defense won't go any lower!"); ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); - MESSAGE("Slugma's Weak Armor raised its Speed!"); + if (gen == GEN_6) + MESSAGE("Slugma's Weak Armor raised its Speed!"); + else + MESSAGE("Slugma's Weak Armor sharply raised its Speed!"); + } THEN { EXPECT_EQ(player->statStages[STAT_DEF], MIN_STAT_STAGE); EXPECT_EQ(player->statStages[STAT_SPEED], DEFAULT_STAT_STAGE + (gen == GEN_7 ? 2 : 1)); @@ -131,7 +131,7 @@ SINGLE_BATTLE_TEST("Weak Armor still lowers Defense if Speed can't go any higher MESSAGE("Slugma's Weak Armor lowered its Defense!"); NONE_OF { ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); - MESSAGE("Slugma's Weak Armor raised its Speed!"); + MESSAGE("Slugma's Weak Armor sharply raised its Speed!"); } MESSAGE("Slugma's Speed won't go any higher!"); } THEN { @@ -144,7 +144,7 @@ SINGLE_BATTLE_TEST("Weak Armor doesn't interrupt multi hit moves if Defense can' { u32 j; GIVEN { - WITH_CONFIG(GEN_CONFIG_WEAK_ARMOR_SPEED, GEN_7); + WITH_CONFIG(CONFIG_WEAK_ARMOR_SPEED, GEN_7); PLAYER(SPECIES_MAGCARGO) { Ability(ABILITY_WEAK_ARMOR); Defense(999); } OPPONENT(SPECIES_CLOYSTER) { Ability(ABILITY_SKILL_LINK); } } WHEN { @@ -157,12 +157,12 @@ SINGLE_BATTLE_TEST("Weak Armor doesn't interrupt multi hit moves if Defense can' ANIMATION(ANIM_TYPE_MOVE, MOVE_FURY_SWIPES, opponent); ABILITY_POPUP(player, ABILITY_WEAK_ARMOR); MESSAGE("Magcargo's Weak Armor lowered its Defense!"); - MESSAGE("Magcargo's Weak Armor raised its Speed!"); + MESSAGE("Magcargo's Weak Armor sharply raised its Speed!"); } ANIMATION(ANIM_TYPE_MOVE, MOVE_FURY_SWIPES, opponent); ABILITY_POPUP(player, ABILITY_WEAK_ARMOR); MESSAGE("Magcargo's Defense won't go any lower!"); - MESSAGE("Magcargo's Weak Armor raised its Speed!"); + MESSAGE("Magcargo's Weak Armor sharply raised its Speed!"); for (j = 0; j < 2; j++) { ANIMATION(ANIM_TYPE_MOVE, MOVE_FURY_SWIPES, opponent); @@ -183,7 +183,7 @@ SINGLE_BATTLE_TEST("Weak Armor doesn't interrupt multi hit moves if Speed can't { u32 j; GIVEN { - WITH_CONFIG(GEN_CONFIG_WEAK_ARMOR_SPEED, GEN_7); + WITH_CONFIG(CONFIG_WEAK_ARMOR_SPEED, GEN_7); PLAYER(SPECIES_MAGCARGO) { Ability(ABILITY_WEAK_ARMOR); Defense(999); } OPPONENT(SPECIES_CLOYSTER) { Ability(ABILITY_SKILL_LINK); } } WHEN { @@ -194,7 +194,7 @@ SINGLE_BATTLE_TEST("Weak Armor doesn't interrupt multi hit moves if Speed can't ANIMATION(ANIM_TYPE_MOVE, MOVE_FURY_SWIPES, opponent); ABILITY_POPUP(player, ABILITY_WEAK_ARMOR); MESSAGE("Magcargo's Weak Armor lowered its Defense!"); - MESSAGE("Magcargo's Weak Armor raised its Speed!"); + MESSAGE("Magcargo's Weak Armor sharply raised its Speed!"); for (j = 0; j < 4; j++) { ANIMATION(ANIM_TYPE_MOVE, MOVE_FURY_SWIPES, opponent); diff --git a/test/battle/ability/wind_power.c b/test/battle/ability/wind_power.c index 279d51f623..c78df34190 100644 --- a/test/battle/ability/wind_power.c +++ b/test/battle/ability/wind_power.c @@ -3,9 +3,10 @@ ASSUMPTIONS { - ASSUME(!IsBattleMoveStatus(MOVE_THUNDERBOLT)); - ASSUME(GetMoveType(MOVE_THUNDERBOLT) == TYPE_ELECTRIC); + ASSUME(!IsBattleMoveStatus(MOVE_NUZZLE)); + ASSUME(GetMoveType(MOVE_NUZZLE) == TYPE_ELECTRIC); ASSUME(!IsBattleMoveStatus(MOVE_SCRATCH)); + ASSUME(!IsWindMove(MOVE_SCRATCH)); ASSUME(!IsBattleMoveStatus(MOVE_AIR_CUTTER)); ASSUME(GetMoveTarget(MOVE_AIR_CUTTER) == MOVE_TARGET_BOTH); ASSUME(IsWindMove(MOVE_AIR_CUTTER)); @@ -25,12 +26,12 @@ SINGLE_BATTLE_TEST("Wind Power sets up Charge for player when hit by a wind move GIVEN { PLAYER(SPECIES_WATTREL) { Ability(ABILITY_WIND_POWER); Speed(10); } - OPPONENT(SPECIES_WOBBUFFET) {Ability(ABILITY_LIMBER); Speed(5) ;} // Limber, so it doesn't get paralyzed. + OPPONENT(SPECIES_PERSIAN) {Ability(ABILITY_LIMBER); Speed(5) ;} // Limber, so it doesn't get paralyzed. } WHEN { - TURN { MOVE(player, MOVE_THUNDERBOLT), MOVE(opponent, move); } - TURN { MOVE(player, MOVE_THUNDERBOLT), MOVE(opponent, move); } + TURN { MOVE(player, MOVE_NUZZLE), MOVE(opponent, move); } + TURN { MOVE(player, MOVE_NUZZLE), MOVE(opponent, move); } } SCENE { - ANIMATION(ANIM_TYPE_MOVE, MOVE_THUNDERBOLT, player); + ANIMATION(ANIM_TYPE_MOVE, MOVE_NUZZLE, player); HP_BAR(opponent, captureDamage: &dmgBefore); ANIMATION(ANIM_TYPE_MOVE, move, opponent); @@ -40,7 +41,7 @@ SINGLE_BATTLE_TEST("Wind Power sets up Charge for player when hit by a wind move MESSAGE("Being hit by Air Cutter charged Wattrel with power!"); } - ANIMATION(ANIM_TYPE_MOVE, MOVE_THUNDERBOLT, player); + ANIMATION(ANIM_TYPE_MOVE, MOVE_NUZZLE, player); HP_BAR(opponent, captureDamage: &dmgAfter); ANIMATION(ANIM_TYPE_MOVE, move, opponent); @@ -69,13 +70,13 @@ SINGLE_BATTLE_TEST("Wind Power sets up Charge for opponent when hit by a wind mo PARAMETRIZE {move = MOVE_AIR_CUTTER; } GIVEN { - PLAYER(SPECIES_WOBBUFFET) {Ability(ABILITY_LIMBER); Speed(5) ;} // Limber, so it doesn't get paralyzed. + PLAYER(SPECIES_PERSIAN) {Ability(ABILITY_LIMBER); Speed(5) ;} // Limber, so it doesn't get paralyzed. OPPONENT(SPECIES_WATTREL) { Ability(ABILITY_WIND_POWER); Speed(10); } } WHEN { - TURN { MOVE(opponent, MOVE_THUNDERBOLT), MOVE(player, move); } - TURN { MOVE(opponent, MOVE_THUNDERBOLT), MOVE(player, move); } + TURN { MOVE(opponent, MOVE_NUZZLE), MOVE(player, move); } + TURN { MOVE(opponent, MOVE_NUZZLE), MOVE(player, move); } } SCENE { - ANIMATION(ANIM_TYPE_MOVE, MOVE_THUNDERBOLT, opponent); + ANIMATION(ANIM_TYPE_MOVE, MOVE_NUZZLE, opponent); HP_BAR(player, captureDamage: &dmgBefore); ANIMATION(ANIM_TYPE_MOVE, move, player); @@ -85,7 +86,7 @@ SINGLE_BATTLE_TEST("Wind Power sets up Charge for opponent when hit by a wind mo MESSAGE("Being hit by Air Cutter charged the opposing Wattrel with power!"); } - ANIMATION(ANIM_TYPE_MOVE, MOVE_THUNDERBOLT, opponent); + ANIMATION(ANIM_TYPE_MOVE, MOVE_NUZZLE, opponent); HP_BAR(player, captureDamage: &dmgAfter); ANIMATION(ANIM_TYPE_MOVE, move, player); @@ -105,9 +106,47 @@ SINGLE_BATTLE_TEST("Wind Power sets up Charge for opponent when hit by a wind mo } } +SINGLE_BATTLE_TEST("Wind Power sets up Charge for only one attack when hit by a wind move") +{ + s16 dmgCharged, dmgAfter; + u16 move; + + PARAMETRIZE {move = MOVE_SCRATCH; } + PARAMETRIZE {move = MOVE_AIR_CUTTER; } + + GIVEN { + PLAYER(SPECIES_WATTREL) { Ability(ABILITY_WIND_POWER); Speed(5); } + OPPONENT(SPECIES_PERSIAN) {Ability(ABILITY_LIMBER); Speed(10) ;} // Limber, so it doesn't get paralyzed. + } WHEN { + TURN { MOVE(opponent, move); MOVE(player, MOVE_NUZZLE); } + TURN { MOVE(player, MOVE_NUZZLE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, move, opponent); + HP_BAR(player); + if (move == MOVE_AIR_CUTTER) { + ABILITY_POPUP(player, ABILITY_WIND_POWER); + MESSAGE("Being hit by Air Cutter charged Wattrel with power!"); + } + + ANIMATION(ANIM_TYPE_MOVE, MOVE_NUZZLE, player); + HP_BAR(opponent, captureDamage: &dmgCharged); + + ANIMATION(ANIM_TYPE_MOVE, MOVE_NUZZLE, player); + HP_BAR(opponent, captureDamage: &dmgAfter); + } + THEN { + if (move == MOVE_AIR_CUTTER) { + EXPECT_MUL_EQ(dmgAfter, Q_4_12(2.0), dmgCharged); + } + else { + EXPECT_EQ(dmgAfter, dmgCharged); + } + } +} + DOUBLE_BATTLE_TEST("Wind Power activates correctly for every battler with the ability when hit by a 2/3 target move") { - u16 abilityLeft, abilityRight; + enum Ability abilityLeft, abilityRight; PARAMETRIZE {abilityLeft = ABILITY_NONE, abilityRight = ABILITY_WIND_POWER;} PARAMETRIZE {abilityLeft = ABILITY_WIND_POWER, abilityRight = ABILITY_NONE; } @@ -116,8 +155,8 @@ DOUBLE_BATTLE_TEST("Wind Power activates correctly for every battler with the ab GIVEN { PLAYER(SPECIES_WATTREL) { Ability(abilityLeft); Speed(10); } PLAYER(SPECIES_WATTREL) { Ability(abilityRight); Speed(5); } - OPPONENT(SPECIES_WOBBUFFET) { Ability(ABILITY_LIMBER); Speed(20); } - OPPONENT(SPECIES_WOBBUFFET) { Ability(ABILITY_LIMBER); Speed(15); } + OPPONENT(SPECIES_PERSIAN) { Ability(ABILITY_LIMBER); Speed(20); } + OPPONENT(SPECIES_PERSIAN) { Ability(ABILITY_LIMBER); Speed(15); } } WHEN { TURN { MOVE(opponentLeft, MOVE_AIR_CUTTER); MOVE(opponentRight, MOVE_AIR_CUTTER);} } SCENE { @@ -148,7 +187,7 @@ DOUBLE_BATTLE_TEST("Wind Power activates correctly for every battler with the ab DOUBLE_BATTLE_TEST("Wind Power activates correctly for every battler with the ability when hit by a 3 target move") { - u16 abilityLeft, abilityRight; + enum Ability abilityLeft, abilityRight; PARAMETRIZE {abilityLeft = ABILITY_NONE, abilityRight = ABILITY_WIND_POWER; } PARAMETRIZE {abilityLeft = ABILITY_WIND_POWER, abilityRight = ABILITY_NONE; } @@ -157,8 +196,8 @@ DOUBLE_BATTLE_TEST("Wind Power activates correctly for every battler with the ab GIVEN { PLAYER(SPECIES_WATTREL) { Ability(abilityLeft); Speed(10); } PLAYER(SPECIES_WATTREL) { Ability(abilityRight); Speed(5); } - OPPONENT(SPECIES_WOBBUFFET) { Ability(ABILITY_LIMBER); Speed(20); } - OPPONENT(SPECIES_WOBBUFFET) { Ability(ABILITY_LIMBER); Speed(15); } + OPPONENT(SPECIES_PERSIAN) { Ability(ABILITY_LIMBER); Speed(20); } + OPPONENT(SPECIES_PERSIAN) { Ability(ABILITY_LIMBER); Speed(15); } } WHEN { TURN { MOVE(opponentLeft, MOVE_PETAL_BLIZZARD);} } SCENE { diff --git a/test/battle/ability/zero_to_hero.c b/test/battle/ability/zero_to_hero.c index dcac9b8540..7df3f07702 100644 --- a/test/battle/ability/zero_to_hero.c +++ b/test/battle/ability/zero_to_hero.c @@ -84,8 +84,8 @@ SINGLE_BATTLE_TEST("Gastro Acid, Worry Seed, and Simple Beam fail if the target GIVEN { ASSUME(GetMoveEffect(MOVE_GASTRO_ACID) == EFFECT_GASTRO_ACID); - ASSUME(GetMoveEffect(MOVE_WORRY_SEED) == EFFECT_WORRY_SEED); - ASSUME(GetMoveEffect(MOVE_SIMPLE_BEAM) == EFFECT_SIMPLE_BEAM); + ASSUME(GetMoveEffect(MOVE_WORRY_SEED) == EFFECT_OVERWRITE_ABILITY); + ASSUME(GetMoveEffect(MOVE_SIMPLE_BEAM) == EFFECT_OVERWRITE_ABILITY); PLAYER(SPECIES_PALAFIN_ZERO) { Ability(ABILITY_ZERO_TO_HERO); } OPPONENT(SPECIES_WOBBUFFET); } WHEN { diff --git a/test/battle/ai/ai.c b/test/battle/ai/ai.c index 3e8f45717e..61100a9161 100644 --- a/test/battle/ai/ai.c +++ b/test/battle/ai/ai.c @@ -10,6 +10,7 @@ AI_SINGLE_BATTLE_TEST("AI prefers Bubble over Water Gun if it's slower") PARAMETRIZE { speedPlayer = 10; speedAi = 200; } GIVEN { + ASSUME(GetMovePower(MOVE_WATER_GUN) == GetMovePower(MOVE_BUBBLE)); AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT); PLAYER(SPECIES_SCIZOR) { Speed(speedPlayer); } OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_WATER_GUN, MOVE_BUBBLE); Speed(speedAi); } @@ -29,11 +30,12 @@ AI_SINGLE_BATTLE_TEST("AI prefers Bubble over Water Gun if it's slower") AI_SINGLE_BATTLE_TEST("AI prefers Water Gun over Bubble if it knows that foe has Contrary") { - u32 abilityAI; + enum Ability abilityAI; PARAMETRIZE { abilityAI = ABILITY_MOXIE; } PARAMETRIZE { abilityAI = ABILITY_MOLD_BREAKER; } // Mold Breaker ignores Contrary. GIVEN { + ASSUME(GetMovePower(MOVE_BUBBLE) == GetMovePower(MOVE_WATER_GUN)); AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT); PLAYER(SPECIES_SHUCKLE) { Ability(ABILITY_CONTRARY); } OPPONENT(SPECIES_PINSIR) { Moves(MOVE_WATER_GUN, MOVE_BUBBLE); Ability(abilityAI); } @@ -52,7 +54,8 @@ AI_SINGLE_BATTLE_TEST("AI prefers Water Gun over Bubble if it knows that foe has AI_SINGLE_BATTLE_TEST("AI prefers moves with better accuracy, but only if they both require the same number of hits to ko") { u16 move1 = MOVE_NONE, move2 = MOVE_NONE, move3 = MOVE_NONE, move4 = MOVE_NONE; - u16 hp, expectedMove, turns, abilityAtk, expectedMove2; + u16 hp, expectedMove, turns, expectedMove2; + enum Ability abilityAtk; abilityAtk = ABILITY_NONE; expectedMove2 = MOVE_NONE; @@ -136,7 +139,8 @@ AI_SINGLE_BATTLE_TEST("AI prefers moves which deal more damage instead of moves { u8 turns = 0; u16 move1 = MOVE_NONE, move2 = MOVE_NONE, move3 = MOVE_NONE, move4 = MOVE_NONE; - u16 expectedMove, abilityAtk, abilityDef; + u16 expectedMove; + enum Ability abilityAtk, abilityDef; abilityAtk = ABILITY_NONE; @@ -150,6 +154,7 @@ AI_SINGLE_BATTLE_TEST("AI prefers moves which deal more damage instead of moves ASSUME(GetMoveCategory(MOVE_SCALD) == DAMAGE_CATEGORY_SPECIAL); ASSUME(GetMoveCategory(MOVE_POISON_JAB) == DAMAGE_CATEGORY_PHYSICAL); ASSUME(GetMoveCategory(MOVE_WATER_GUN) == DAMAGE_CATEGORY_SPECIAL); + ASSUME(GetSpeciesBaseAttack(SPECIES_NIDOQUEEN) == 92); // Gen 5's 82 Base Attack causes the test to fail AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT); PLAYER(SPECIES_TYPHLOSION) { Ability(abilityDef); } PLAYER(SPECIES_WOBBUFFET); @@ -204,6 +209,9 @@ AI_SINGLE_BATTLE_TEST("AI prefers a weaker move over a one with a downside effec GIVEN { ASSUME(GetMoveCategory(MOVE_FLAMETHROWER) == DAMAGE_CATEGORY_SPECIAL); // Added because Typhlosion has to KO Wobbuffet ASSUME(GetMoveCategory(MOVE_OVERHEAT) == DAMAGE_CATEGORY_SPECIAL); // Added because Typhlosion has to KO Wobbuffet + // With Gen 5 data, it chooses Overheat instead + ASSUME(GetMovePower(MOVE_FLAMETHROWER) == 90); // In Gen 5, it's 95 + ASSUME(GetMovePower(MOVE_OVERHEAT) == 130); // In Gen 5, it's 140. AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT); PLAYER(SPECIES_WOBBUFFET) { HP(hp); } PLAYER(SPECIES_WOBBUFFET); @@ -258,7 +266,8 @@ AI_SINGLE_BATTLE_TEST("AI chooses the safest option to faint the target, taking { u16 move1 = MOVE_NONE, move2 = MOVE_NONE, move3 = MOVE_NONE, move4 = MOVE_NONE; u16 expectedMove, expectedMove2 = MOVE_NONE; - u16 abilityAtk = ABILITY_NONE, holdItemAtk = ITEM_NONE; + enum Ability abilityAtk = ABILITY_NONE; + u32 holdItemAtk = ITEM_NONE; // Psychic is not very effective, but always hits. Solarbeam requires a charging turn, Double Edge has recoil and Focus Blast can miss; PARAMETRIZE { abilityAtk = ABILITY_STURDY; move1 = MOVE_FOCUS_BLAST; move2 = MOVE_SOLAR_BEAM; move3 = MOVE_PSYCHIC; move4 = MOVE_DOUBLE_EDGE; expectedMove = MOVE_PSYCHIC; } @@ -295,7 +304,8 @@ AI_SINGLE_BATTLE_TEST("AI chooses the safest option to faint the target, taking { u16 move1 = MOVE_NONE, move2 = MOVE_NONE, move3 = MOVE_NONE, move4 = MOVE_NONE; u16 expectedMove, expectedMove2 = MOVE_NONE; - u16 abilityAtk = ABILITY_NONE, holdItemAtk = ITEM_NONE; + enum Ability abilityAtk = ABILITY_NONE; + u32 holdItemAtk = ITEM_NONE; // Fiery Dance and Skull Bash are chosen because user is holding Power Herb PARAMETRIZE { abilityAtk = ABILITY_STURDY; holdItemAtk = ITEM_POWER_HERB; move1 = MOVE_FOCUS_BLAST; move2 = MOVE_SKULL_BASH; move3 = MOVE_FIERY_DANCE; move4 = MOVE_DOUBLE_EDGE; @@ -322,7 +332,7 @@ AI_SINGLE_BATTLE_TEST("AI chooses the safest option to faint the target, taking AI_SINGLE_BATTLE_TEST("AI won't use Solar Beam if there is no Sun up or the user is not holding Power Herb") { - u16 abilityAtk = ABILITY_NONE; + enum Ability abilityAtk = ABILITY_NONE; u16 holdItemAtk = ITEM_NONE; PARAMETRIZE { abilityAtk = ABILITY_DROUGHT; } @@ -332,6 +342,7 @@ AI_SINGLE_BATTLE_TEST("AI won't use Solar Beam if there is no Sun up or the user GIVEN { ASSUME(GetMoveCategory(MOVE_SOLAR_BEAM) == DAMAGE_CATEGORY_SPECIAL); ASSUME(GetMoveCategory(MOVE_GRASS_PLEDGE) == DAMAGE_CATEGORY_SPECIAL); + ASSUME(GetMovePower(MOVE_GRASS_PLEDGE) == 80); // Gen 5's 50 power causes the test to fail AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT); PLAYER(SPECIES_WOBBUFFET) { HP(211); } PLAYER(SPECIES_WOBBUFFET); @@ -442,7 +453,7 @@ AI_SINGLE_BATTLE_TEST("First Impression is preferred on the first turn of the sp AI_SINGLE_BATTLE_TEST("First Impression is not chosen if it's blocked by certain abilities") { u16 species; - u16 ability; + enum Ability ability; PARAMETRIZE { species = SPECIES_BRUXISH; ability = ABILITY_DAZZLING; } PARAMETRIZE { species = SPECIES_FARIGIRAF; ability = ABILITY_ARMOR_TAIL; } @@ -509,7 +520,7 @@ AI_SINGLE_BATTLE_TEST("AI will choose Thunderbolt then Surf 2/3 times if the opp AI_SINGLE_BATTLE_TEST("AI will choose Scratch over Power-up Punch with Contrary") { - u32 ability; + enum Ability ability; PARAMETRIZE {ability = ABILITY_SUCTION_CUPS; } PARAMETRIZE {ability = ABILITY_CONTRARY; } @@ -535,7 +546,7 @@ AI_SINGLE_BATTLE_TEST("AI will choose Scratch over Power-up Punch with Contrary" AI_SINGLE_BATTLE_TEST("AI will choose Superpower over Outrage with Contrary") { - u32 ability; + enum Ability ability; PARAMETRIZE {ability = ABILITY_SUCTION_CUPS; } PARAMETRIZE {ability = ABILITY_CONTRARY; } @@ -561,7 +572,7 @@ AI_SINGLE_BATTLE_TEST("AI will choose Superpower over Outrage with Contrary") AI_SINGLE_BATTLE_TEST("AI calculates guaranteed criticals and detects critical immunity") { - u32 ability; + enum Ability ability; PARAMETRIZE { ability = ABILITY_SWIFT_SWIM; } PARAMETRIZE { ability = ABILITY_SHELL_ARMOR; } @@ -638,7 +649,8 @@ AI_SINGLE_BATTLE_TEST("AI uses a guaranteed KO move instead of the move with the AI_SINGLE_BATTLE_TEST("AI stays choice locked into moves in spite of the player's ability disabling them") { - u32 playerMon, ability, aiMove; + u32 playerMon, aiMove; + enum Ability ability; PARAMETRIZE { ability = ABILITY_DAZZLING; playerMon = SPECIES_BRUXISH; aiMove = MOVE_QUICK_ATTACK; } PARAMETRIZE { ability = ABILITY_QUEENLY_MAJESTY; playerMon = SPECIES_TSAREENA; aiMove = MOVE_QUICK_ATTACK; } PARAMETRIZE { ability = ABILITY_ARMOR_TAIL; playerMon = SPECIES_FARIGIRAF; aiMove = MOVE_QUICK_ATTACK; } @@ -687,6 +699,7 @@ AI_SINGLE_BATTLE_TEST("AI won't use thawing moves if target is frozen unless it PARAMETRIZE { status = STATUS1_FROSTBITE; aiMove = MOVE_EMBER; aiFlags = AI_FLAG_CHECK_BAD_MOVE; } GIVEN { + WITH_CONFIG(CONFIG_BURN_HIT_THAW, GEN_6); // In Gen 5, non-Fire burning moves didn't cause thawing ASSUME(GetMoveType(MOVE_EMBER) == TYPE_FIRE); ASSUME(GetMoveCategory(MOVE_TACKLE) == DAMAGE_CATEGORY_PHYSICAL); ASSUME(GetMoveCategory(MOVE_WATER_GUN) == DAMAGE_CATEGORY_SPECIAL); @@ -847,7 +860,7 @@ AI_DOUBLE_BATTLE_TEST("AI sees opposing drain ability") AI_SINGLE_BATTLE_TEST("AI will not set up Weather if it wont have any affect") { - u32 ability; + enum Ability ability; PARAMETRIZE { ability = ABILITY_CLOUD_NINE; } PARAMETRIZE { ability = ABILITY_DAMP; } @@ -928,6 +941,7 @@ AI_SINGLE_BATTLE_TEST("AI will see Magnitude damage") AI_SINGLE_BATTLE_TEST("AI will prefer resisted move over failing move") { GIVEN { + WITH_CONFIG(CONFIG_POWDER_GRASS, GEN_6); AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY); PLAYER(SPECIES_ROSELIA) { Moves(MOVE_ABSORB); }; OPPONENT(SPECIES_GLOOM) { Moves(MOVE_MEGA_DRAIN, MOVE_STUN_SPORE, MOVE_LEECH_SEED, MOVE_SYNTHESIS); } diff --git a/test/battle/ai/ai_calc_best_move_score.c b/test/battle/ai/ai_calc_best_move_score.c index cfad45a0aa..88525249dc 100644 --- a/test/battle/ai/ai_calc_best_move_score.c +++ b/test/battle/ai/ai_calc_best_move_score.c @@ -112,3 +112,24 @@ AI_SINGLE_BATTLE_TEST("AI will select Throat Chop if the sound move is the best TURN { EXPECT_MOVE(opponent, MOVE_THROAT_CHOP); MOVE(player, MOVE_HYPER_VOICE);} } } + +AI_SINGLE_BATTLE_TEST("HasMoveThatChangesKOThreshold - AI should not see self-targeted speed drops as preventing setup moves in 2hko cases") +{ + u16 move; + PARAMETRIZE { move = MOVE_EARTHQUAKE; } + PARAMETRIZE { move = MOVE_BULLDOZE; } + GIVEN { + ASSUME(MoveHasAdditionalEffectSelf(MOVE_HAMMER_ARM, MOVE_EFFECT_SPD_MINUS_1) == TRUE); + ASSUME(MoveHasAdditionalEffect(MOVE_BULLDOZE, MOVE_EFFECT_SPD_MINUS_1) == TRUE); + ASSUME(GetMoveEffect(MOVE_NASTY_PLOT) == EFFECT_SPECIAL_ATTACK_UP_2); + ASSUME(GetMovePower(MOVE_EARTHQUAKE) == 100); + ASSUME(GetMovePower(MOVE_HAMMER_ARM) == 100); + ASSUME(GetMovePower(MOVE_BULLDOZE) == 60); + ASSUME(GetMovePower(MOVE_AURA_SPHERE) == 80); + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY | AI_FLAG_SMART_SWITCHING | AI_FLAG_SMART_MON_CHOICES | AI_FLAG_OMNISCIENT); + PLAYER(SPECIES_RHYDON) { Level(100); Nature(NATURE_ADAMANT); Item(ITEM_EVIOLITE); Speed(1); Ability(ABILITY_LIGHTNING_ROD); Moves(MOVE_HAMMER_ARM, move); } + OPPONENT(SPECIES_GRIMMSNARL) { Level(100); Nature(NATURE_JOLLY); Ability(ABILITY_INFILTRATOR); Speed(2); HP(300); Moves(MOVE_NASTY_PLOT, MOVE_AURA_SPHERE); } + } WHEN { + TURN { MOVE(player, MOVE_HAMMER_ARM); EXPECT_MOVE(opponent, move == MOVE_EARTHQUAKE ? MOVE_NASTY_PLOT : MOVE_AURA_SPHERE); } + } +} diff --git a/test/battle/ai/ai_check_viability.c b/test/battle/ai/ai_check_viability.c index 4dff0e08ca..5ec4161a17 100644 --- a/test/battle/ai/ai_check_viability.c +++ b/test/battle/ai/ai_check_viability.c @@ -18,6 +18,7 @@ AI_SINGLE_BATTLE_TEST("AI sees increased base power of Facade") PARAMETRIZE { status1 = STATUS1_BURN; expectedMove = MOVE_FACADE; } GIVEN { + WITH_CONFIG(CONFIG_BURN_FACADE_DMG, GEN_6); ASSUME(GetMoveEffect(MOVE_FACADE) == EFFECT_FACADE); AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT); PLAYER(SPECIES_WOBBUFFET) { HP(60); } @@ -162,6 +163,7 @@ AI_SINGLE_BATTLE_TEST("AI can choose Counter or Mirror Coat if the predicted mov ASSUME(GetMoveEffect(MOVE_MIRROR_COAT) == EFFECT_MIRROR_COAT); ASSUME(GetMoveCategory(MOVE_STRENGTH) == DAMAGE_CATEGORY_PHYSICAL); ASSUME(GetMoveCategory(MOVE_POWER_GEM) == DAMAGE_CATEGORY_SPECIAL); + ASSUME(GetMovePower(MOVE_POWER_GEM) == 80); // Gen 5's 70 power causes the test to fail AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT); PLAYER(SPECIES_WOBBUFFET) { Speed(1); } OPPONENT(SPECIES_WOBBUFFET) { HP(102); Speed(100); Moves(opponentMove, MOVE_STRENGTH); } @@ -176,7 +178,7 @@ AI_SINGLE_BATTLE_TEST("AI can choose Counter or Mirror Coat if the predicted mov AI_SINGLE_BATTLE_TEST("AI chooses moves with secondary effect that have a 100% chance to trigger") { - u16 ability; + enum Ability ability; PARAMETRIZE { ability = ABILITY_NONE; } PARAMETRIZE { ability = ABILITY_SERENE_GRACE; } @@ -199,24 +201,24 @@ AI_DOUBLE_BATTLE_TEST("AI chooses moves that cure self or partner") { u32 status1_0, status1_1, partnerAbility, move; - PARAMETRIZE { status1_0 = STATUS1_NONE; status1_1 = STATUS1_NONE; + PARAMETRIZE { status1_0 = STATUS1_NONE; status1_1 = STATUS1_NONE; move = MOVE_HEAL_BELL; partnerAbility = ABILITY_SCRAPPY; } - PARAMETRIZE { status1_0 = STATUS1_TOXIC_POISON; status1_1 = STATUS1_NONE; + PARAMETRIZE { status1_0 = STATUS1_TOXIC_POISON; status1_1 = STATUS1_NONE; move = MOVE_HEAL_BELL; partnerAbility = ABILITY_SCRAPPY; } PARAMETRIZE { status1_0 = STATUS1_NONE; status1_1 = STATUS1_PARALYSIS; move = MOVE_HEAL_BELL; partnerAbility = ABILITY_SCRAPPY; } - PARAMETRIZE { status1_0 = STATUS1_NONE; status1_1 = STATUS1_PARALYSIS; + PARAMETRIZE { status1_0 = STATUS1_NONE; status1_1 = STATUS1_PARALYSIS; move = MOVE_HEAL_BELL; partnerAbility = ABILITY_SOUNDPROOF; } - PARAMETRIZE { status1_0 = STATUS1_NONE; status1_1 = STATUS1_NONE; + PARAMETRIZE { status1_0 = STATUS1_NONE; status1_1 = STATUS1_NONE; move = MOVE_REFRESH; partnerAbility = ABILITY_SCRAPPY; } - PARAMETRIZE { status1_0 = STATUS1_TOXIC_POISON; status1_1 = STATUS1_NONE; + PARAMETRIZE { status1_0 = STATUS1_TOXIC_POISON; status1_1 = STATUS1_NONE; move = MOVE_REFRESH; partnerAbility = ABILITY_SCRAPPY; } GIVEN { ASSUME(GetMoveEffect(MOVE_HEAL_BELL) == EFFECT_HEAL_BELL); - WITH_CONFIG(GEN_CONFIG_HEAL_BELL_SOUNDPROOF, GEN_8); + WITH_CONFIG(CONFIG_HEAL_BELL_SOUNDPROOF, GEN_8); AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT); PLAYER(SPECIES_WOBBUFFET); PLAYER(SPECIES_WOBBUFFET); @@ -230,9 +232,33 @@ AI_DOUBLE_BATTLE_TEST("AI chooses moves that cure self or partner") } } +AI_DOUBLE_BATTLE_TEST("AI uses Refresh only when curing status is worthwhile") +{ + u32 status1; + enum Ability ability; + u32 expectedMove; + + PARAMETRIZE { status1 = STATUS1_BURN; ability = ABILITY_GUTS; expectedMove = MOVE_ROCK_SLIDE; } + PARAMETRIZE { status1 = STATUS1_BURN; ability = ABILITY_PRESSURE; expectedMove = MOVE_REFRESH; } + PARAMETRIZE { status1 = STATUS1_TOXIC_POISON; ability = ABILITY_POISON_HEAL; expectedMove = MOVE_ROCK_SLIDE; } + PARAMETRIZE { status1 = STATUS1_TOXIC_POISON; ability = ABILITY_SCRAPPY; expectedMove = MOVE_REFRESH; } + + GIVEN { + ASSUME(GetMoveEffect(MOVE_REFRESH) == EFFECT_REFRESH); + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT); + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_REGIROCK) { Moves(MOVE_ROCK_SLIDE, MOVE_REFRESH); Status1(status1); Ability(ability); } + OPPONENT(SPECIES_EXPLOUD) { Moves(MOVE_CELEBRATE); } + } WHEN { + TURN { EXPECT_MOVE(opponentLeft, expectedMove); } + } +} + AI_SINGLE_BATTLE_TEST("AI chooses moves that cure inactive party members") { - u32 status, ability, config; + u32 status, config; + enum Ability ability; PARAMETRIZE { status = STATUS1_TOXIC_POISON; ability = ABILITY_SCRAPPY; } PARAMETRIZE { status = STATUS1_NONE; ability = ABILITY_SCRAPPY; } @@ -241,7 +267,7 @@ AI_SINGLE_BATTLE_TEST("AI chooses moves that cure inactive party members") GIVEN { ASSUME(GetMoveEffect(MOVE_HEAL_BELL) == EFFECT_HEAL_BELL); - WITH_CONFIG(GEN_CONFIG_HEAL_BELL_SOUNDPROOF, config); + WITH_CONFIG(CONFIG_HEAL_BELL_SOUNDPROOF, config); AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT); PLAYER(SPECIES_WOBBUFFET); OPPONENT(SPECIES_REGIROCK) { Moves(MOVE_BODY_PRESS, MOVE_HEAL_BELL); } @@ -312,7 +338,7 @@ AI_SINGLE_BATTLE_TEST("AI uses Worry Seed against Rest") AI_SINGLE_BATTLE_TEST("AI uses Simple Beam against Contrary Leaf Storm") { - u32 ability, move; + enum Ability ability, move; PARAMETRIZE { ability = ABILITY_CONTRARY; move = MOVE_LEAF_STORM; } PARAMETRIZE { ability = ABILITY_CONTRARY; move = MOVE_CHARGE_BEAM; } PARAMETRIZE { ability = ABILITY_OVERGROW; move = MOVE_CHARGE_BEAM; } @@ -391,3 +417,69 @@ AI_SINGLE_BATTLE_TEST("AI uses Wide Guard against Earthquake when opponent would TURN { MOVE(player, MOVE_EARTHQUAKE); EXPECT_MOVE(opponent, MOVE_WIDE_GUARD); } } } + +AI_SINGLE_BATTLE_TEST("AI sees Shield Dust immunity to additional effects") +{ + enum Ability ability; + PARAMETRIZE { ability = ABILITY_SHIELD_DUST; } + PARAMETRIZE { ability = ABILITY_TINTED_LENS; } + + GIVEN { + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_OMNISCIENT); + PLAYER(SPECIES_VENOMOTH) { Ability(ability); Moves(MOVE_CELEBRATE, MOVE_POUND); } + OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_CHILLING_WATER, MOVE_BRINE); } + } WHEN { + if (ability == ABILITY_SHIELD_DUST) + TURN { EXPECT_MOVE(opponent, MOVE_BRINE); } + else + TURN { EXPECT_MOVE(opponent, MOVE_CHILLING_WATER); } + } +} + +AI_DOUBLE_BATTLE_TEST("AI sees type-changing moves as the correct type") +{ + u32 species, fieldStatus, ability; + u64 aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT; + + PARAMETRIZE { fieldStatus = MOVE_RAIN_DANCE; species = SPECIES_PRIMARINA; ability = ABILITY_NONE; } + PARAMETRIZE { fieldStatus = MOVE_RAIN_DANCE; species = SPECIES_PRIMARINA; ability = ABILITY_LIQUID_VOICE; } + PARAMETRIZE { fieldStatus = MOVE_ELECTRIC_TERRAIN; species = SPECIES_GEODUDE_ALOLA; ability = ABILITY_GALVANIZE; } + PARAMETRIZE { aiFlags |= AI_FLAG_OMNISCIENT | AI_FLAG_SMART_SWITCHING | AI_FLAG_SMART_MON_CHOICES | AI_FLAG_PP_STALL_PREVENTION; + fieldStatus = MOVE_RAIN_DANCE; species = SPECIES_PRIMARINA; ability = ABILITY_NONE; } + PARAMETRIZE { aiFlags |= AI_FLAG_OMNISCIENT | AI_FLAG_SMART_SWITCHING | AI_FLAG_SMART_MON_CHOICES | AI_FLAG_PP_STALL_PREVENTION; + fieldStatus = MOVE_RAIN_DANCE; species = SPECIES_PRIMARINA; ability = ABILITY_LIQUID_VOICE; } + PARAMETRIZE { aiFlags |= AI_FLAG_OMNISCIENT | AI_FLAG_SMART_SWITCHING | AI_FLAG_SMART_MON_CHOICES | AI_FLAG_PP_STALL_PREVENTION; + fieldStatus = MOVE_ELECTRIC_TERRAIN; species = SPECIES_GEODUDE_ALOLA; ability = ABILITY_GALVANIZE; } + + GIVEN { + AI_FLAGS(aiFlags); + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET) { Moves(fieldStatus, MOVE_RETURN, MOVE_TAUNT); } + OPPONENT(species) { Ability(ability); Moves(MOVE_HYPER_VOICE); } + } WHEN { + if (ability != ABILITY_NONE) + TURN { EXPECT_MOVE(opponentLeft, fieldStatus); } + else + TURN { NOT_EXPECT_MOVE(opponentLeft, fieldStatus); } + } +} + +AI_SINGLE_BATTLE_TEST("AI uses Sparkling Aria to cure an enemy with Guts") +{ + u32 ability; + + PARAMETRIZE { ability = ABILITY_GUTS; } + PARAMETRIZE { ability = ABILITY_BULLETPROOF; } + + GIVEN { + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY | AI_FLAG_OMNISCIENT); + PLAYER(SPECIES_URSALUNA) { Ability(ability); Moves(MOVE_HEADLONG_RUSH, MOVE_CELEBRATE); Status1(STATUS1_BURN); } + OPPONENT(SPECIES_PRIMARINA) { Moves(MOVE_SPARKLING_ARIA, MOVE_SCALD); } + } WHEN { + if (ability == ABILITY_GUTS) + TURN { EXPECT_MOVE(opponent, MOVE_SPARKLING_ARIA); } + else + TURN { EXPECT_MOVE(opponent, MOVE_SCALD); } + } +} diff --git a/test/battle/ai/ai_choice.c b/test/battle/ai/ai_choice.c index d7ff7e021f..e8d3a8e42a 100644 --- a/test/battle/ai/ai_choice.c +++ b/test/battle/ai/ai_choice.c @@ -10,7 +10,8 @@ ASSUMPTIONS AI_SINGLE_BATTLE_TEST("Choiced Pokémon switch out after using a status move once") { - u32 j, ability = ABILITY_NONE, heldItem = ITEM_NONE; + u32 j, heldItem = ITEM_NONE; + enum Ability ability = ABILITY_NONE; static const u32 choiceItems[] = { ITEM_CHOICE_SPECS, @@ -46,7 +47,7 @@ AI_SINGLE_BATTLE_TEST("Choiced Pokémon switch out after using a status move onc AI_SINGLE_BATTLE_TEST("Choiced Pokémon only consider their own status moves when determining if they should switch") { - GIVEN + GIVEN { AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY | AI_FLAG_RISKY | AI_FLAG_SMART_SWITCHING | AI_FLAG_OMNISCIENT | AI_FLAG_SMART_MON_CHOICES); PLAYER(SPECIES_ZIGZAGOON) { Speed(4); Moves(MOVE_TAIL_WHIP, MOVE_SCRATCH); } @@ -61,7 +62,8 @@ AI_SINGLE_BATTLE_TEST("Choiced Pokémon only consider their own status moves whe AI_SINGLE_BATTLE_TEST("Choiced Pokémon won't use stat boosting moves") { // Moves defined by MOVE_TARGET_USER (with exceptions?) - u32 j, ability = ABILITY_NONE, heldItem = ITEM_NONE; + u32 j, heldItem = ITEM_NONE; + enum Ability ability = ABILITY_NONE; static const u32 choiceItems[] = { ITEM_CHOICE_SPECS, @@ -93,8 +95,8 @@ AI_SINGLE_BATTLE_TEST("Choiced Pokémon won't use stat boosting moves") AI_SINGLE_BATTLE_TEST("Choiced Pokémon won't use status move if they are the only party member") { - u32 j, ability = ABILITY_NONE, isAlive = 0, heldItem = ITEM_NONE; - + u32 j, isAlive = 0, heldItem = ITEM_NONE; + enum Ability ability = ABILITY_NONE; static const u32 choiceItems[] = { ITEM_CHOICE_SPECS, ITEM_CHOICE_BAND, @@ -128,8 +130,8 @@ AI_SINGLE_BATTLE_TEST("Choiced Pokémon won't use status move if they are the on AI_SINGLE_BATTLE_TEST("Choiced Pokémon won't use status move if they don't have a good switchin") { - u32 j, ability = ABILITY_NONE, move = MOVE_NONE, species = SPECIES_NONE, heldItem = ITEM_NONE; - + u32 j, move = MOVE_NONE, species = SPECIES_NONE, heldItem = ITEM_NONE; + enum Ability ability = ABILITY_NONE; static const u32 choiceItems[] = { ITEM_CHOICE_SPECS, ITEM_CHOICE_BAND, diff --git a/test/battle/ai/ai_doubles.c b/test/battle/ai/ai_doubles.c index add853b6d4..94fcfc8ef9 100644 --- a/test/battle/ai/ai_doubles.c +++ b/test/battle/ai/ai_doubles.c @@ -56,6 +56,88 @@ AI_DOUBLE_BATTLE_TEST("AI will not use Helping Hand if partner does not have any } } +AI_DOUBLE_BATTLE_TEST("AI skips Trick/Bestow when items are missing or target already holds one") +{ + u16 move = MOVE_NONE, atkItem = ITEM_NONE, targetItem = ITEM_NONE; + + PARAMETRIZE { move = MOVE_TRICK; atkItem = ITEM_NONE; targetItem = ITEM_NONE; } + PARAMETRIZE { move = MOVE_BESTOW; atkItem = ITEM_NONE; targetItem = ITEM_NONE; } + PARAMETRIZE { move = MOVE_BESTOW; atkItem = ITEM_ORAN_BERRY; targetItem = ITEM_LEFTOVERS; } + + GIVEN { + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT); + PLAYER(SPECIES_WOBBUFFET) { Item(targetItem); } + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET) { Moves(move, MOVE_SCRATCH); Item(atkItem); } + OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_TACKLE); } + } WHEN { + TURN { NOT_EXPECT_MOVE(opponentLeft, move); } + } +} + +AI_DOUBLE_BATTLE_TEST("AI skips Trick/Bestow with unexchangeable items") +{ + u16 move = MOVE_NONE, atkItem = ITEM_NONE, targetItem = ITEM_NONE; + + PARAMETRIZE { move = MOVE_TRICK; atkItem = ITEM_ORANGE_MAIL; targetItem = ITEM_NONE; } + PARAMETRIZE { move = MOVE_TRICK; atkItem = ITEM_ORAN_BERRY; targetItem = ITEM_ORANGE_MAIL; } + PARAMETRIZE { move = MOVE_BESTOW; atkItem = ITEM_ORANGE_MAIL; targetItem = ITEM_NONE; } + + GIVEN { + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT); + PLAYER(SPECIES_WOBBUFFET) { Item(targetItem); } + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET) { Moves(move, MOVE_SCRATCH); Item(atkItem); } + OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_TACKLE); } + } WHEN { + TURN { NOT_EXPECT_MOVE(opponentLeft, move); } + } +} + +AI_DOUBLE_BATTLE_TEST("AI skips Trick/Bestow around Sticky Hold") +{ + u16 move = MOVE_NONE, atkItem = ITEM_ORAN_BERRY, targetItem = ITEM_NONE; + enum Ability atkAbility = ABILITY_PRESSURE, targetAbility = ABILITY_PRESSURE; + + PARAMETRIZE { move = MOVE_TRICK; atkAbility = ABILITY_STICKY_HOLD; targetAbility = ABILITY_PRESSURE; targetItem = ITEM_LEFTOVERS; } + PARAMETRIZE { move = MOVE_TRICK; atkAbility = ABILITY_PRESSURE; targetAbility = ABILITY_STICKY_HOLD; targetItem = ITEM_LEFTOVERS; } + PARAMETRIZE { move = MOVE_BESTOW; atkAbility = ABILITY_STICKY_HOLD; targetAbility = ABILITY_PRESSURE; targetItem = ITEM_NONE; } + + GIVEN { + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT); + PLAYER(SPECIES_WOBBUFFET) { Ability(targetAbility); Item(targetItem); } + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET) { Ability(atkAbility); Item(atkItem); Moves(move, MOVE_SCRATCH); } + OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_TACKLE); } + } WHEN { + TURN { NOT_EXPECT_MOVE(opponentLeft, move); } + } +} + +AI_DOUBLE_BATTLE_TEST("AI skips Trick/Bestow if the target has a Substitute") +{ + ASSUME(GetMoveEffect(MOVE_SUBSTITUTE) == EFFECT_SUBSTITUTE); + + u16 move = MOVE_NONE, atkItem = ITEM_NONE, targetItem = ITEM_NONE; + + PARAMETRIZE { move = MOVE_TRICK; atkItem = ITEM_ORAN_BERRY; targetItem = ITEM_LEFTOVERS; } + PARAMETRIZE { move = MOVE_BESTOW; atkItem = ITEM_ORAN_BERRY; targetItem = ITEM_NONE; } + + GIVEN { + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT); + PLAYER(SPECIES_WOBBUFFET) { Moves(MOVE_SUBSTITUTE, MOVE_CELEBRATE); Item(targetItem); Speed(20); } + PLAYER(SPECIES_WOBBUFFET) { Moves(MOVE_CELEBRATE); Speed(20); } + OPPONENT(SPECIES_WOBBUFFET) { Moves(move, MOVE_SCRATCH); Item(atkItem); Speed(1); Attack(1); } + OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_CELEBRATE); Speed(1); } + } WHEN { + TURN { + MOVE(playerLeft, MOVE_SUBSTITUTE); + MOVE(playerRight, MOVE_CELEBRATE); + } + TURN { NOT_EXPECT_MOVE(opponentLeft, move); } + } +} + AI_DOUBLE_BATTLE_TEST("AI will not use a status move if partner already chose Helping Hand") { s32 j; @@ -69,13 +151,14 @@ AI_DOUBLE_BATTLE_TEST("AI will not use a status move if partner already chose He } GIVEN { - AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT); - PLAYER(SPECIES_WOBBUFFET); - PLAYER(SPECIES_WOBBUFFET); - OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_HELPING_HAND); } - OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_SCRATCH, statusMove); } + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_OMNISCIENT); + PLAYER(SPECIES_WOBBUFFET) { Moves(MOVE_CELEBRATE, MOVE_SCRATCH, statusMove, MOVE_WATER_GUN); } + PLAYER(SPECIES_WOBBUFFET) { Moves(MOVE_CELEBRATE, MOVE_SCRATCH, statusMove, MOVE_WATER_GUN); } + OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_HELPING_HAND, MOVE_EXPLOSION); } + OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_SCRATCH, statusMove, MOVE_WATER_GUN); } } WHEN { - TURN { NOT_EXPECT_MOVE(opponentRight, statusMove); + TURN { EXPECT_MOVE(opponentLeft, MOVE_HELPING_HAND); + NOT_EXPECT_MOVE(opponentRight, statusMove); SCORE_LT_VAL(opponentRight, statusMove, AI_SCORE_DEFAULT, target:playerLeft); SCORE_LT_VAL(opponentRight, statusMove, AI_SCORE_DEFAULT, target:playerRight); SCORE_LT_VAL(opponentRight, statusMove, AI_SCORE_DEFAULT, target:opponentLeft); @@ -138,6 +221,32 @@ AI_DOUBLE_BATTLE_TEST("AI won't use the same nondamaging move as its partner for } } +AI_DOUBLE_BATTLE_TEST("Heal Bell and Jungle Healing skip curing a partner that benefits from burn") +{ + u32 move; + + PARAMETRIZE { move = MOVE_HEAL_BELL; } + PARAMETRIZE { move = MOVE_JUNGLE_HEALING; } + + GIVEN { + ASSUME(GetMoveEffect(MOVE_HEAL_BELL) == EFFECT_HEAL_BELL); + ASSUME(GetMoveEffect(MOVE_JUNGLE_HEALING) == EFFECT_JUNGLE_HEALING); + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT); + PLAYER(SPECIES_WOBBUFFET) { Moves(MOVE_MEMENTO); Speed(1); } + PLAYER(SPECIES_WOBBUFFET) { Moves(MOVE_MEMENTO); Speed(1); } + OPPONENT(SPECIES_WOBBUFFET) { Moves(move, MOVE_SCRATCH); Speed(20); } + OPPONENT(SPECIES_WOBBUFFET) { Ability(ABILITY_GUTS); Moves(MOVE_TACKLE); Status1(STATUS1_BURN); MaxHP(200); HP(200); Speed(10); } + } WHEN { + TURN { + NOT_EXPECT_MOVE(opponentLeft, move); + EXPECT_MOVE(opponentLeft, MOVE_SCRATCH, target: playerLeft); + EXPECT_MOVE(opponentRight, MOVE_TACKLE, target: playerLeft); + MOVE(playerLeft, MOVE_MEMENTO); + MOVE(playerRight, MOVE_MEMENTO); + } + } +} + AI_DOUBLE_BATTLE_TEST("AI will not choose Earthquake if it damages the partner without a positive effect") { ASSUME(GetMoveTarget(MOVE_EARTHQUAKE) == MOVE_TARGET_FOES_AND_ALLY); @@ -185,7 +294,8 @@ AI_DOUBLE_BATTLE_TEST("AI will choose Bulldoze if it triggers its ally's ability ASSUME(GetMoveType(MOVE_BULLDOZE) == TYPE_GROUND); ASSUME(MoveHasAdditionalEffect(MOVE_BULLDOZE, MOVE_EFFECT_SPD_MINUS_1)); - u32 species, ability, currentHP; + u32 species, currentHP; + enum Ability ability; PARAMETRIZE { species = SPECIES_KINGAMBIT; ability = ABILITY_DEFIANT; currentHP = 400; } PARAMETRIZE { species = SPECIES_SHUCKLE; ability = ABILITY_CONTRARY; currentHP = 400; } @@ -212,7 +322,7 @@ AI_DOUBLE_BATTLE_TEST("AI will choose Beat Up on an ally with Justified if it wi ASSUME(GetMoveEffect(MOVE_BEAT_UP) == EFFECT_BEAT_UP); ASSUME(GetMoveType(MOVE_BEAT_UP) == TYPE_DARK); - u32 defAbility, atkAbility, currentHP; + enum Ability defAbility, atkAbility, currentHP; PARAMETRIZE { defAbility = ABILITY_FLASH_FIRE; atkAbility = ABILITY_SCRAPPY; currentHP = 400; } PARAMETRIZE { defAbility = ABILITY_JUSTIFIED; atkAbility = ABILITY_SCRAPPY; currentHP = 400; } @@ -336,7 +446,7 @@ AI_DOUBLE_BATTLE_TEST("AI will trigger its ally's Weakness Policy") } } -AI_DOUBLE_BATTLE_TEST("AI will only explode and kill everything on the field with Risky or Will Suicide") +AI_DOUBLE_BATTLE_TEST("AI will only explode and kill everything on the field with Risky or Will Suicide (doubles)") { ASSUME(GetMoveTarget(MOVE_EXPLOSION) == MOVE_TARGET_FOES_AND_ALLY); ASSUME(GetMoveEffect(MOVE_EXPLOSION) == EFFECT_EXPLOSION); @@ -361,6 +471,36 @@ AI_DOUBLE_BATTLE_TEST("AI will only explode and kill everything on the field wit } } +AI_DOUBLE_BATTLE_TEST("Battler 3 has Battler 1 AI flags set correctly (doubles)") +{ + ASSUME(GetMoveTarget(MOVE_EXPLOSION) == MOVE_TARGET_FOES_AND_ALLY); + ASSUME(GetMoveEffect(MOVE_EXPLOSION) == EFFECT_EXPLOSION); + + u32 aiFlags; + u32 battler; + + PARAMETRIZE { aiFlags = 0; battler = 1; } + PARAMETRIZE { aiFlags = 0; battler = 3; } + PARAMETRIZE { aiFlags = AI_FLAG_RISKY; battler = 3; } + PARAMETRIZE { aiFlags = AI_FLAG_RISKY; battler = 1; } + PARAMETRIZE { aiFlags = AI_FLAG_WILL_SUICIDE; battler = 1; } + PARAMETRIZE { aiFlags = AI_FLAG_WILL_SUICIDE; battler = 3; } + + GIVEN { + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT); + BATTLER_AI_FLAGS(battler, aiFlags); + PLAYER(SPECIES_WOBBUFFET) { HP(1); } + PLAYER(SPECIES_WOBBUFFET) { HP(1); } + OPPONENT(SPECIES_VOLTORB) { Moves(MOVE_EXPLOSION, MOVE_ELECTRO_BALL); HP(1); } + OPPONENT(SPECIES_ELECTRODE) { Moves(MOVE_EXPLOSION, MOVE_ELECTRO_BALL); HP(1); } + } WHEN { + if (aiFlags == 0 || battler == 3) + TURN { EXPECT_MOVE(opponentLeft, MOVE_ELECTRO_BALL, target: playerLeft); EXPECT_MOVE(opponentRight, MOVE_ELECTRO_BALL, target: playerLeft); } + else + TURN { EXPECT_MOVE(opponentLeft, MOVE_EXPLOSION, target: playerLeft); EXPECT_MOVE(opponentRight, MOVE_EXPLOSION); } + } +} + AI_DOUBLE_BATTLE_TEST("AI sees corresponding absorbing abilities on partners") { ASSUME(GetMoveTarget(MOVE_DISCHARGE) == MOVE_TARGET_FOES_AND_ALLY); @@ -372,7 +512,8 @@ AI_DOUBLE_BATTLE_TEST("AI sees corresponding absorbing abilities on partners") ASSUME(GetMoveTarget(MOVE_EARTHQUAKE) == MOVE_TARGET_FOES_AND_ALLY); ASSUME(GetMoveType(MOVE_EARTHQUAKE) == TYPE_GROUND); - u32 ability, move, species; + enum Ability ability; + u32 move, species; PARAMETRIZE { species = SPECIES_PSYDUCK; ability = ABILITY_CLOUD_NINE; move = MOVE_DISCHARGE; } PARAMETRIZE { species = SPECIES_PIKACHU; ability = ABILITY_LIGHTNING_ROD; move = MOVE_DISCHARGE; } @@ -409,7 +550,8 @@ AI_DOUBLE_BATTLE_TEST("AI treats an ally's redirection ability appropriately (ge ASSUME(GetMoveTarget(MOVE_SURF) == MOVE_TARGET_FOES_AND_ALLY); ASSUME(GetMoveType(MOVE_SURF) == TYPE_WATER); - u32 ability, move, species; + enum Ability ability; + u32 move, species; PARAMETRIZE { species = SPECIES_SEAKING; ability = ABILITY_LIGHTNING_ROD; move = MOVE_DISCHARGE; } PARAMETRIZE { species = SPECIES_SHELLOS; ability = ABILITY_STORM_DRAIN; move = MOVE_SURF; } @@ -433,7 +575,8 @@ AI_DOUBLE_BATTLE_TEST("AI treats an ally's redirection ability appropriately (ge ASSUME(GetMoveTarget(MOVE_SURF) == MOVE_TARGET_FOES_AND_ALLY); ASSUME(GetMoveType(MOVE_SURF) == TYPE_WATER); - u32 ability, move, species; + enum Ability ability; + u32 move, species; PARAMETRIZE { species = SPECIES_SEAKING; ability = ABILITY_LIGHTNING_ROD; move = MOVE_DISCHARGE; } PARAMETRIZE { species = SPECIES_SHELLOS; ability = ABILITY_STORM_DRAIN; move = MOVE_SURF; } @@ -452,7 +595,6 @@ AI_DOUBLE_BATTLE_TEST("AI treats an ally's redirection ability appropriately (ge AI_DOUBLE_BATTLE_TEST("AI recognizes Volt Absorb received from Trace") { - KNOWN_FAILING; // MGriffin's PR that switched two turn charging moves in AI tests broke this test, waiting on a fix GIVEN { AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT); PLAYER(SPECIES_MAGNETON); @@ -460,7 +602,7 @@ AI_DOUBLE_BATTLE_TEST("AI recognizes Volt Absorb received from Trace") OPPONENT(SPECIES_JOLTEON) { Ability(ABILITY_VOLT_ABSORB); Moves(MOVE_THUNDER_WAVE, MOVE_THUNDERSHOCK, MOVE_WATER_GUN); } OPPONENT(SPECIES_JOLTEON) { Ability(ABILITY_VOLT_ABSORB); Moves(MOVE_THUNDER_WAVE, MOVE_THUNDERSHOCK, MOVE_WATER_GUN); } } WHEN { - TURN { NOT_EXPECT_MOVE(opponentLeft, MOVE_THUNDERSHOCK); NOT_EXPECT_MOVE(opponentLeft, MOVE_THUNDER_WAVE); NOT_EXPECT_MOVE(opponentRight, MOVE_THUNDER_WAVE); } + TURN { NOT_EXPECT_MOVES(opponentLeft, MOVE_THUNDERSHOCK, MOVE_THUNDER_WAVE); NOT_EXPECT_MOVE(opponentRight, MOVE_THUNDER_WAVE); } } THEN { EXPECT(gAiLogicData->abilities[B_POSITION_PLAYER_RIGHT] == ABILITY_VOLT_ABSORB); } @@ -494,15 +636,15 @@ AI_DOUBLE_BATTLE_TEST("AI sets up weather for its ally") PARAMETRIZE { goodWeather = MOVE_HAIL; badWeather = MOVE_SUNNY_DAY; weatherTrigger = MOVE_BLIZZARD; } PARAMETRIZE { goodWeather = MOVE_SNOWSCAPE; badWeather = MOVE_SUNNY_DAY; weatherTrigger = MOVE_BLIZZARD; } PARAMETRIZE { goodWeather = MOVE_SANDSTORM; badWeather = MOVE_SUNNY_DAY; weatherTrigger = MOVE_SHORE_UP; } - PARAMETRIZE { aiFlags |= AI_FLAG_OMNISCIENT | AI_FLAG_SMART_SWITCHING | AI_FLAG_SMART_MON_CHOICES | AI_FLAG_PP_STALL_PREVENTION; + PARAMETRIZE { aiFlags |= AI_FLAG_OMNISCIENT | AI_FLAG_SMART_SWITCHING | AI_FLAG_SMART_MON_CHOICES | AI_FLAG_PP_STALL_PREVENTION; goodWeather = MOVE_SUNNY_DAY; badWeather = MOVE_RAIN_DANCE; weatherTrigger = MOVE_SOLAR_BEAM; } - PARAMETRIZE { aiFlags |= AI_FLAG_OMNISCIENT | AI_FLAG_SMART_SWITCHING | AI_FLAG_SMART_MON_CHOICES | AI_FLAG_PP_STALL_PREVENTION; + PARAMETRIZE { aiFlags |= AI_FLAG_OMNISCIENT | AI_FLAG_SMART_SWITCHING | AI_FLAG_SMART_MON_CHOICES | AI_FLAG_PP_STALL_PREVENTION; goodWeather = MOVE_RAIN_DANCE; badWeather = MOVE_SUNNY_DAY; weatherTrigger = MOVE_THUNDER; } - PARAMETRIZE { aiFlags |= AI_FLAG_OMNISCIENT | AI_FLAG_SMART_SWITCHING | AI_FLAG_SMART_MON_CHOICES | AI_FLAG_PP_STALL_PREVENTION; + PARAMETRIZE { aiFlags |= AI_FLAG_OMNISCIENT | AI_FLAG_SMART_SWITCHING | AI_FLAG_SMART_MON_CHOICES | AI_FLAG_PP_STALL_PREVENTION; goodWeather = MOVE_HAIL; badWeather = MOVE_SUNNY_DAY; weatherTrigger = MOVE_BLIZZARD; } - PARAMETRIZE { aiFlags |= AI_FLAG_OMNISCIENT | AI_FLAG_SMART_SWITCHING | AI_FLAG_SMART_MON_CHOICES | AI_FLAG_PP_STALL_PREVENTION; + PARAMETRIZE { aiFlags |= AI_FLAG_OMNISCIENT | AI_FLAG_SMART_SWITCHING | AI_FLAG_SMART_MON_CHOICES | AI_FLAG_PP_STALL_PREVENTION; goodWeather = MOVE_SNOWSCAPE; badWeather = MOVE_SUNNY_DAY; weatherTrigger = MOVE_BLIZZARD; } - PARAMETRIZE { aiFlags |= AI_FLAG_OMNISCIENT | AI_FLAG_SMART_SWITCHING | AI_FLAG_SMART_MON_CHOICES | AI_FLAG_PP_STALL_PREVENTION; + PARAMETRIZE { aiFlags |= AI_FLAG_OMNISCIENT | AI_FLAG_SMART_SWITCHING | AI_FLAG_SMART_MON_CHOICES | AI_FLAG_PP_STALL_PREVENTION; goodWeather = MOVE_SANDSTORM; badWeather = MOVE_SUNNY_DAY; weatherTrigger = MOVE_SHORE_UP; } GIVEN { @@ -525,13 +667,13 @@ AI_DOUBLE_BATTLE_TEST("AI sets up terrain for its ally") PARAMETRIZE { goodTerrain = MOVE_GRASSY_TERRAIN; badTerrain = MOVE_PSYCHIC_TERRAIN; terrainTrigger = MOVE_GRASSY_GLIDE; } PARAMETRIZE { goodTerrain = MOVE_MISTY_TERRAIN; badTerrain = MOVE_PSYCHIC_TERRAIN; terrainTrigger = MOVE_MISTY_EXPLOSION; } PARAMETRIZE { goodTerrain = MOVE_PSYCHIC_TERRAIN; badTerrain = MOVE_ELECTRIC_TERRAIN; terrainTrigger = MOVE_EXPANDING_FORCE; } - PARAMETRIZE { aiFlags |= AI_FLAG_OMNISCIENT | AI_FLAG_SMART_SWITCHING | AI_FLAG_SMART_MON_CHOICES | AI_FLAG_PP_STALL_PREVENTION; + PARAMETRIZE { aiFlags |= AI_FLAG_OMNISCIENT | AI_FLAG_SMART_SWITCHING | AI_FLAG_SMART_MON_CHOICES | AI_FLAG_PP_STALL_PREVENTION; goodTerrain = MOVE_ELECTRIC_TERRAIN; badTerrain = MOVE_PSYCHIC_TERRAIN; terrainTrigger = MOVE_RISING_VOLTAGE; } - PARAMETRIZE { aiFlags |= AI_FLAG_OMNISCIENT | AI_FLAG_SMART_SWITCHING | AI_FLAG_SMART_MON_CHOICES | AI_FLAG_PP_STALL_PREVENTION; + PARAMETRIZE { aiFlags |= AI_FLAG_OMNISCIENT | AI_FLAG_SMART_SWITCHING | AI_FLAG_SMART_MON_CHOICES | AI_FLAG_PP_STALL_PREVENTION; goodTerrain = MOVE_GRASSY_TERRAIN; badTerrain = MOVE_PSYCHIC_TERRAIN; terrainTrigger = MOVE_GRASSY_GLIDE; } - PARAMETRIZE { aiFlags |= AI_FLAG_OMNISCIENT | AI_FLAG_SMART_SWITCHING | AI_FLAG_SMART_MON_CHOICES | AI_FLAG_PP_STALL_PREVENTION; + PARAMETRIZE { aiFlags |= AI_FLAG_OMNISCIENT | AI_FLAG_SMART_SWITCHING | AI_FLAG_SMART_MON_CHOICES | AI_FLAG_PP_STALL_PREVENTION; goodTerrain = MOVE_MISTY_TERRAIN; badTerrain = MOVE_PSYCHIC_TERRAIN; terrainTrigger = MOVE_MISTY_EXPLOSION; } - PARAMETRIZE { aiFlags |= AI_FLAG_OMNISCIENT | AI_FLAG_SMART_SWITCHING | AI_FLAG_SMART_MON_CHOICES | AI_FLAG_PP_STALL_PREVENTION; + PARAMETRIZE { aiFlags |= AI_FLAG_OMNISCIENT | AI_FLAG_SMART_SWITCHING | AI_FLAG_SMART_MON_CHOICES | AI_FLAG_PP_STALL_PREVENTION; goodTerrain = MOVE_PSYCHIC_TERRAIN; badTerrain = MOVE_ELECTRIC_TERRAIN; terrainTrigger = MOVE_EXPANDING_FORCE; } GIVEN { @@ -555,6 +697,7 @@ AI_DOUBLE_BATTLE_TEST("AI uses After You to set up Trick Room") GIVEN { ASSUME(GetMoveEffect(MOVE_AFTER_YOU) == EFFECT_AFTER_YOU); ASSUME(GetMoveEffect(MOVE_TRICK_ROOM) == EFFECT_TRICK_ROOM); + ASSUME(IsHealingMove(MOVE_DRAINING_KISS)); // Doesn't have the Healing Move flag in Gen 5 AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY | AI_FLAG_DOUBLE_BATTLE); PLAYER(SPECIES_WOBBUFFET) { Speed(4); } PLAYER(SPECIES_WOBBUFFET) { Speed(4); } @@ -582,6 +725,7 @@ AI_DOUBLE_BATTLE_TEST("AI uses Trick Room intelligently") GIVEN { ASSUME(GetMoveEffect(MOVE_AFTER_YOU) == EFFECT_AFTER_YOU); ASSUME(GetMoveEffect(MOVE_TRICK_ROOM) == EFFECT_TRICK_ROOM); + ASSUME(IsHealingMove(MOVE_DRAINING_KISS)); // Doesn't have the Healing Move flag in Gen 5 AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY | AI_FLAG_DOUBLE_BATTLE); PLAYER(SPECIES_WOBBUFFET) { Speed(4); } PLAYER(SPECIES_WOBBUFFET) { Speed(speed); } @@ -611,7 +755,7 @@ AI_DOUBLE_BATTLE_TEST("AI uses Trick Room with both battlers on the turn it expi TURN { NOT_EXPECT_MOVE(opponentLeft, MOVE_TRICK_ROOM); NOT_EXPECT_MOVE(opponentRight, MOVE_TRICK_ROOM); } TURN { NOT_EXPECT_MOVE(opponentLeft, MOVE_TRICK_ROOM); NOT_EXPECT_MOVE(opponentRight, MOVE_TRICK_ROOM); } TURN { EXPECT_MOVE(opponentLeft, MOVE_TRICK_ROOM); EXPECT_MOVE(opponentRight, MOVE_TRICK_ROOM); } - } + } } AI_DOUBLE_BATTLE_TEST("AI uses Helping Hand if it's about to die") @@ -639,6 +783,7 @@ AI_DOUBLE_BATTLE_TEST("AI uses Helping Hand if it's about to die") AI_DOUBLE_BATTLE_TEST("AI uses Helping Hand if the ally does notably more damage") { + KNOWN_FAILING; // Failure was masked by test runner issues GIVEN { ASSUME(GetMoveEffect(MOVE_HELPING_HAND) == EFFECT_HELPING_HAND); AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY | AI_FLAG_OMNISCIENT); diff --git a/test/battle/ai/ai_flag_predict_switch.c b/test/battle/ai/ai_flag_predict_switch.c index 8530c49675..6f484b6378 100644 --- a/test/battle/ai/ai_flag_predict_switch.c +++ b/test/battle/ai/ai_flag_predict_switch.c @@ -59,7 +59,7 @@ AI_SINGLE_BATTLE_TEST("AI_FLAG_PREDICT_SWITCH: Considers ShouldSwitch and GetMos // Switching in trapper is an advanced feature of ShouldSwitch that requires GetMostSuitableMonToSwitchInto to also return a specific mon; this passing means the AI can use both in prediction PASSES_RANDOMLY(5, 10, RNG_AI_PREDICT_SWITCH); GIVEN { - WITH_CONFIG(GEN_CONFIG_POWDER_GRASS, GEN_6); + WITH_CONFIG(CONFIG_POWDER_GRASS, GEN_6); AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY | AI_FLAG_OMNISCIENT | AI_FLAG_SMART_SWITCHING | AI_FLAG_SMART_MON_CHOICES | AI_FLAG_PREDICT_SWITCH | AI_FLAG_PREDICT_INCOMING_MON); PLAYER(SPECIES_SKARMORY) { Moves(MOVE_SCRATCH); } PLAYER(SPECIES_DUGTRIO) { Ability(ABILITY_ARENA_TRAP); Moves(MOVE_ACROBATICS); } diff --git a/test/battle/ai/ai_multi.c b/test/battle/ai/ai_multi.c new file mode 100644 index 0000000000..b46573b4ca --- /dev/null +++ b/test/battle/ai/ai_multi.c @@ -0,0 +1,224 @@ +#include "global.h" +#include "test/battle.h" +#include "battle_ai_util.h" + +AI_MULTI_BATTLE_TEST("AI will only explode and kill everything on the field with Risky or Will Suicide (multi)") +{ + ASSUME(GetMoveTarget(MOVE_EXPLOSION) == MOVE_TARGET_FOES_AND_ALLY); + ASSUME(GetMoveEffect(MOVE_EXPLOSION) == EFFECT_EXPLOSION); + + u32 aiFlags; + u32 battler; + + PARAMETRIZE { aiFlags = 0; battler = 1; } + PARAMETRIZE { aiFlags = 0; battler = 3; } + PARAMETRIZE { aiFlags = AI_FLAG_RISKY; battler = 1; } + PARAMETRIZE { aiFlags = AI_FLAG_RISKY; battler = 3; } + PARAMETRIZE { aiFlags = AI_FLAG_WILL_SUICIDE; battler = 1; } + PARAMETRIZE { aiFlags = AI_FLAG_WILL_SUICIDE; battler = 3; } + + GIVEN { + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT); + BATTLER_AI_FLAGS(battler, aiFlags); + MULTI_PLAYER(SPECIES_WOBBUFFET) { HP(1); } + MULTI_PARTNER(SPECIES_WOBBUFFET) { HP(1); } + MULTI_OPPONENT_A(SPECIES_ELECTRODE) { Moves(MOVE_EXPLOSION, MOVE_ELECTRO_BALL); HP(1); } + MULTI_OPPONENT_B(SPECIES_VOLTORB) { Moves(MOVE_EXPLOSION, MOVE_ELECTRO_BALL); HP(1); } + } WHEN { + if (aiFlags == 0) + TURN { EXPECT_MOVE(opponentLeft, MOVE_ELECTRO_BALL, target: playerLeft); EXPECT_MOVE(opponentRight, MOVE_ELECTRO_BALL, target: playerLeft); } + else + TURN { EXPECT_MOVE(&gBattleMons[BATTLE_PARTNER(battler)], MOVE_ELECTRO_BALL, target: playerLeft); EXPECT_MOVE(&gBattleMons[battler], MOVE_EXPLOSION); } + } +} + +AI_ONE_VS_TWO_BATTLE_TEST("AI will only explode and kill everything on the field with Risky or Will Suicide (1v2)") +{ + ASSUME(GetMoveTarget(MOVE_EXPLOSION) == MOVE_TARGET_FOES_AND_ALLY); + ASSUME(GetMoveEffect(MOVE_EXPLOSION) == EFFECT_EXPLOSION); + + u32 aiFlags; + u32 battler; + + PARAMETRIZE { aiFlags = 0; battler = 1; } + PARAMETRIZE { aiFlags = 0; battler = 3; } + PARAMETRIZE { aiFlags = AI_FLAG_RISKY; battler = 3; } + PARAMETRIZE { aiFlags = AI_FLAG_RISKY; battler = 1; } + PARAMETRIZE { aiFlags = AI_FLAG_WILL_SUICIDE; battler = 1; } + PARAMETRIZE { aiFlags = AI_FLAG_WILL_SUICIDE; battler = 3; } + + GIVEN { + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT); + BATTLER_AI_FLAGS(battler, aiFlags); + MULTI_PLAYER(SPECIES_WOBBUFFET) { HP(1); } + MULTI_PLAYER(SPECIES_WOBBUFFET) { HP(1); } + MULTI_OPPONENT_A(SPECIES_ELECTRODE) { Moves(MOVE_EXPLOSION, MOVE_ELECTRO_BALL); HP(1); } + MULTI_OPPONENT_B(SPECIES_VOLTORB) { Moves(MOVE_EXPLOSION, MOVE_ELECTRO_BALL); HP(1); } + } WHEN { + if (aiFlags == 0) + TURN { EXPECT_MOVE(opponentLeft, MOVE_ELECTRO_BALL, target: playerLeft); EXPECT_MOVE(opponentRight, MOVE_ELECTRO_BALL, target: playerLeft); } + else + TURN { EXPECT_MOVE(&gBattleMons[BATTLE_PARTNER(battler)], MOVE_ELECTRO_BALL, target: playerLeft); EXPECT_MOVE(&gBattleMons[battler], MOVE_EXPLOSION); } + } +} + +// Used to test EXPECT_MOVE only on partner +AI_MULTI_BATTLE_TEST("AI partner makes sensible move selections in battle (multi)") +{ + GIVEN { + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT); + MULTI_PLAYER(SPECIES_HAUNTER); + MULTI_PLAYER(SPECIES_RATTATA); + // No moves to damage opponents. + MULTI_PARTNER(SPECIES_GENGAR) { Moves(MOVE_SHADOW_BALL, MOVE_AURA_SPHERE); } + MULTI_OPPONENT_A(SPECIES_RATTATA) { Moves(MOVE_CELEBRATE); HP(1); } + MULTI_OPPONENT_B(SPECIES_KANGASKHAN) { Moves(MOVE_CELEBRATE); } + + } WHEN { + TURN { MOVE(playerLeft, MOVE_AURA_SPHERE, target:opponentRight); EXPECT_MOVE(playerRight, MOVE_AURA_SPHERE, target:opponentLeft); }; + } +} + +// Used to test EXPECT_MOVE only on partner +AI_TWO_VS_ONE_BATTLE_TEST("AI partner makes sensible move selections in battle (2v1)") +{ + GIVEN { + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT); + MULTI_PLAYER(SPECIES_HAUNTER); + MULTI_PLAYER(SPECIES_RATTATA); + // No moves to damage opponents. + MULTI_PARTNER(SPECIES_GENGAR) { Moves(MOVE_SHADOW_BALL, MOVE_AURA_SPHERE); } + MULTI_OPPONENT_A(SPECIES_RATTATA) { Moves(MOVE_CELEBRATE); HP(1); } + MULTI_OPPONENT_A(SPECIES_KANGASKHAN) { Moves(MOVE_CELEBRATE); } + + } WHEN { + TURN { MOVE(playerLeft, MOVE_AURA_SPHERE, target:opponentRight); EXPECT_MOVE(playerRight, MOVE_AURA_SPHERE, target:opponentLeft); }; + } +} + +AI_TWO_VS_ONE_BATTLE_TEST("Battler 3 has Battler 1 AI flags set correctly (2v1)") +{ + ASSUME(GetMoveTarget(MOVE_EXPLOSION) == MOVE_TARGET_FOES_AND_ALLY); + ASSUME(GetMoveEffect(MOVE_EXPLOSION) == EFFECT_EXPLOSION); + + u32 aiFlags; + u32 battler; + + PARAMETRIZE { aiFlags = 0; battler = 1; } + PARAMETRIZE { aiFlags = 0; battler = 3; } + PARAMETRIZE { aiFlags = AI_FLAG_RISKY; battler = 1; } + PARAMETRIZE { aiFlags = AI_FLAG_RISKY; battler = 3; } + PARAMETRIZE { aiFlags = AI_FLAG_WILL_SUICIDE; battler = 1; } + PARAMETRIZE { aiFlags = AI_FLAG_WILL_SUICIDE; battler = 3; } + + GIVEN { + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT); + BATTLER_AI_FLAGS(battler, aiFlags); + MULTI_PLAYER(SPECIES_WOBBUFFET) { HP(1); } + MULTI_PARTNER(SPECIES_WOBBUFFET) { HP(1); } + MULTI_OPPONENT_A(SPECIES_VOLTORB) { Moves(MOVE_EXPLOSION, MOVE_ELECTRO_BALL); HP(1); } + MULTI_OPPONENT_A(SPECIES_ELECTRODE) { Moves(MOVE_EXPLOSION, MOVE_ELECTRO_BALL); HP(1); } + } WHEN { + if (aiFlags == 0 || battler == 3) + TURN { EXPECT_MOVE(opponentLeft, MOVE_ELECTRO_BALL, target: playerLeft); EXPECT_MOVE(opponentRight, MOVE_ELECTRO_BALL, target: playerLeft); } + else + TURN { EXPECT_MOVE(opponentLeft, MOVE_EXPLOSION, target: playerLeft); EXPECT_MOVE(opponentRight, MOVE_EXPLOSION); } + } +} + +AI_MULTI_BATTLE_TEST("Partner will not steal your pokemon when running out") +{ + + GIVEN { + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT); + MULTI_PLAYER(SPECIES_WOBBUFFET) { } + MULTI_PLAYER(SPECIES_WOBBUFFET) { } + MULTI_PLAYER(SPECIES_WOBBUFFET) { } + MULTI_PARTNER(SPECIES_WYNAUT) { Moves(MOVE_MEMENTO); } + MULTI_OPPONENT_A(SPECIES_WOBBUFFET) { Moves(MOVE_CELEBRATE); } + MULTI_OPPONENT_B(SPECIES_WOBBUFFET) { Moves(MOVE_CELEBRATE); } + } WHEN { + TURN {EXPECT_MOVE(playerRight, MOVE_MEMENTO, target:opponentLeft);} + TURN {} + } THEN { + EXPECT_EQ(gAbsentBattlerFlags, (1u << GetBattlerAtPosition(B_POSITION_PLAYER_RIGHT))); + } +} + +AI_MULTI_BATTLE_TEST("Partner will not steal your pokemon to delay using their ace") +{ + + GIVEN { + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT); + BATTLER_AI_FLAGS(B_POSITION_PLAYER_RIGHT, AI_FLAG_ACE_POKEMON); + MULTI_PLAYER(SPECIES_WOBBUFFET) { } + MULTI_PLAYER(SPECIES_WOBBUFFET) { } + MULTI_PLAYER(SPECIES_WOBBUFFET) { } + MULTI_PARTNER(SPECIES_WYNAUT) { Moves(MOVE_MEMENTO); } + MULTI_PARTNER(SPECIES_METAGROSS) { Moves(MOVE_CELEBRATE); } + MULTI_OPPONENT_A(SPECIES_WOBBUFFET) { Moves(MOVE_CELEBRATE); } + MULTI_OPPONENT_B(SPECIES_WOBBUFFET) { Moves(MOVE_CELEBRATE); } + } WHEN { + TURN {EXPECT_MOVE(playerRight, MOVE_MEMENTO, target:opponentLeft);} + TURN {} + } THEN { + EXPECT_EQ(SPECIES_METAGROSS, playerRight->species); + } +} + +AI_MULTI_BATTLE_TEST("AI opponents do not steal their partner pokemon in multi battle to delay using their ace") +{ + + GIVEN { + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT); + BATTLER_AI_FLAGS(B_POSITION_OPPONENT_LEFT, AI_FLAG_ACE_POKEMON); + MULTI_PLAYER(SPECIES_WOBBUFFET) { } + MULTI_PARTNER(SPECIES_WOBBUFFET) { } + MULTI_OPPONENT_A(SPECIES_WOBBUFFET) { Moves(MOVE_CELEBRATE); HP(1);} + MULTI_OPPONENT_A(SPECIES_VENUSAUR) { Moves(MOVE_GIGA_DRAIN); } + MULTI_OPPONENT_B(SPECIES_WYNAUT) { Moves(MOVE_CELEBRATE); } + } WHEN { + TURN {MOVE(playerLeft, MOVE_TACKLE, target: opponentLeft); } + TURN {MOVE(playerLeft, MOVE_TACKLE, target: opponentLeft); } + } THEN { + EXPECT_EQ(SPECIES_VENUSAUR, opponentLeft->species); + } +} + +AI_MULTI_BATTLE_TEST("AI opponents do not steal their partner pokemon in multi battle when forced out") +{ + u32 item, move; + PARAMETRIZE {item = ITEM_EJECT_BUTTON; move = MOVE_TACKLE;} + PARAMETRIZE {item = ITEM_EJECT_PACK; move = MOVE_TAIL_WHIP;} + PARAMETRIZE {item = ITEM_NONE; move = MOVE_ROAR;} + GIVEN { + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT); + BATTLER_AI_FLAGS(B_POSITION_OPPONENT_LEFT, AI_FLAG_ACE_POKEMON); + MULTI_PLAYER(SPECIES_WOBBUFFET) { } + MULTI_PARTNER(SPECIES_WOBBUFFET) { } + MULTI_OPPONENT_A(SPECIES_WOBBUFFET) { Moves(MOVE_CELEBRATE); Item(item);} + MULTI_OPPONENT_A(SPECIES_VENUSAUR) { Moves(MOVE_GIGA_DRAIN); } + MULTI_OPPONENT_B(SPECIES_WYNAUT) { Moves(MOVE_CELEBRATE); } + } WHEN { + TURN {MOVE(playerLeft, move, target: opponentLeft); } + } THEN { + EXPECT_EQ(SPECIES_VENUSAUR, opponentLeft->species); + } +} + +AI_MULTI_BATTLE_TEST("AI opponents do not steal their partner pokemon in multi battle when forced out 2") +{ + GIVEN { + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT); + BATTLER_AI_FLAGS(B_POSITION_OPPONENT_LEFT, AI_FLAG_ACE_POKEMON); + MULTI_PLAYER(SPECIES_WOBBUFFET) { } + MULTI_PARTNER(SPECIES_WOBBUFFET) { } + MULTI_OPPONENT_A(SPECIES_GOLISOPOD) { Moves(MOVE_CELEBRATE); HP(101); MaxHP(200); Ability(ABILITY_EMERGENCY_EXIT);} + MULTI_OPPONENT_A(SPECIES_VENUSAUR) { Moves(MOVE_GIGA_DRAIN); } + MULTI_OPPONENT_B(SPECIES_WYNAUT) { Moves(MOVE_CELEBRATE); } + } WHEN { + TURN {MOVE(playerLeft, MOVE_TACKLE, target: opponentLeft); } + } THEN { + EXPECT_EQ(SPECIES_VENUSAUR, opponentLeft->species); + } +} diff --git a/test/battle/ai/ai_smart_tera.c b/test/battle/ai/ai_smart_tera.c index 550ba7d2a1..7bed476b43 100644 --- a/test/battle/ai/ai_smart_tera.c +++ b/test/battle/ai/ai_smart_tera.c @@ -4,7 +4,6 @@ AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_TERA: AI will tera if it enables a ko") { - KNOWN_FAILING; // Tests don't currently give the AI the capability to tera, even with a tera type set. GIVEN { ASSUME(GetMovePower(MOVE_SEED_BOMB) == 80); ASSUME(GetMovePower(MOVE_AQUA_TAIL) == 90); @@ -14,9 +13,9 @@ AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_TERA: AI will tera if it enables a ko") OPPONENT(SPECIES_WOBBUFFET) { Speed(1); Moves(MOVE_AQUA_TAIL, MOVE_SEED_BOMB); TeraType(TYPE_GRASS); } OPPONENT(SPECIES_WOBBUFFET) { HP(1); Speed(100); TeraType(TYPE_FIRE); } } WHEN { - TURN { EXPECT_MOVE(opponent, MOVE_SEED_BOMB); } + TURN { EXPECT_MOVE(opponent, MOVE_SEED_BOMB, gimmick: GIMMICK_TERA); SEND_OUT(player, 1); } } SCENE { - MESSAGE("The opposing Wobbuffet terastilized into the Grass type!"); + MESSAGE("The opposing Wobbuffet terastallized into the Grass type!"); MESSAGE("Wobbuffet fainted!"); } } @@ -34,7 +33,7 @@ AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_TERA: AI will not tera if it gets outsped a } WHEN { TURN { } } SCENE { - NOT MESSAGE("The opposing Wobbuffet terastilized into the Grass type!"); + NOT MESSAGE("The opposing Wobbuffet terastallized into the Grass type!"); } } @@ -50,24 +49,23 @@ AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_TERA: AI will not tera if it gets ko'd by p } WHEN { TURN { } } SCENE { - NOT MESSAGE("The opposing Wobbuffet terastilized into the Grass type!"); + NOT MESSAGE("The opposing Wobbuffet terastallized into the Grass type!"); } } -// AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_TERA: AI might tera if it gets saved from a ko") -// { -// KNOWN_FAILING; // Tests don't currently give the AI the capability to tera, even with a tera type set. -// PASSES_RANDOMLY(90, 100, RNG_AI_CONSERVE_TERA); -// GIVEN { -// ASSUME(GetMovePower(MOVE_SEED_BOMB) == 80); -// AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_SMART_TERA | AI_FLAG_OMNISCIENT ); -// PLAYER(SPECIES_WOBBUFFET) { HP(47); Speed(100); Moves(MOVE_SEED_BOMB); } -// PLAYER(SPECIES_WOBBUFFET) { Speed(100); } -// OPPONENT(SPECIES_WOBBUFFET) { Speed(100); HP(30); Moves(MOVE_SEED_BOMB); TeraType(TYPE_FIRE); } -// OPPONENT(SPECIES_WOBBUFFET) { Speed(100); TeraType(TYPE_FIRE); } -// } WHEN { -// TURN { MOVE(player, MOVE_SEED_BOMB); } -// } SCENE { -// MESSAGE("The opposing Wobbuffet terastilized into the Fire type!"); -// } -// } \ No newline at end of file +AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_TERA: AI might tera if it gets saved from a ko") +{ + PASSES_RANDOMLY(90, 100, RNG_AI_CONSERVE_TERA); + GIVEN { + ASSUME(GetMovePower(MOVE_SEED_BOMB) == 80); + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_SMART_TERA | AI_FLAG_OMNISCIENT ); + PLAYER(SPECIES_WOBBUFFET) { HP(47); Speed(100); Moves(MOVE_SEED_BOMB); } + PLAYER(SPECIES_WOBBUFFET) { Speed(100); } + OPPONENT(SPECIES_WOBBUFFET) { Speed(100); HP(30); Moves(MOVE_SEED_BOMB); TeraType(TYPE_FIRE); } + OPPONENT(SPECIES_WOBBUFFET) { Speed(100); TeraType(TYPE_FIRE); } + } WHEN { + TURN { MOVE(player, MOVE_SEED_BOMB); } + } SCENE { + MESSAGE("The opposing Wobbuffet terastallized into the Fire type!"); + } +} diff --git a/test/battle/ai/ai_switching.c b/test/battle/ai/ai_switching.c index 14ea727f85..8c6c6ae623 100644 --- a/test/battle/ai/ai_switching.c +++ b/test/battle/ai/ai_switching.c @@ -53,7 +53,7 @@ AI_SINGLE_BATTLE_TEST("AI sees on-field player ability correctly and does not se OPPONENT(SPECIES_BOMBIRDIER) {Level(42); Moves(MOVE_ROCK_SLIDE); } OPPONENT(SPECIES_IRON_THORNS) {Level(43); Moves(MOVE_SUPERCELL_SLAM, MOVE_ICE_PUNCH); } } WHEN { - TURN { + TURN { MOVE(player, MOVE_VOLT_SWITCH); SEND_OUT(player, 1); EXPECT_MOVE(opponent, MOVE_SCRATCH); @@ -91,6 +91,250 @@ AI_DOUBLE_BATTLE_TEST("AI will not try to switch for the same Pokémon for 2 spo } } +// Used to test EXPECT_SWITCH only on partner +AI_MULTI_BATTLE_TEST("AI partner will not switch mid-turn into a player Pokémon (multi)") +{ + u32 flags; + + PARAMETRIZE {flags = AI_FLAG_SMART_SWITCHING; } + PARAMETRIZE {flags = 0; } + + PASSES_RANDOMLY(SHOULD_SWITCH_ALL_MOVES_BAD_PERCENTAGE, 100, RNG_AI_SWITCH_ALL_MOVES_BAD); + GIVEN { + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | flags); + MULTI_PLAYER(SPECIES_HAUNTER); + MULTI_PLAYER(SPECIES_RATTATA); + // No moves to damage opponents. + MULTI_PARTNER(SPECIES_GENGAR) { Moves(MOVE_SHADOW_BALL); } + MULTI_PARTNER(SPECIES_GASTLY) { Moves(MOVE_LICK); } + MULTI_PARTNER(SPECIES_RATICATE) { Moves(MOVE_HEADBUTT); } + MULTI_OPPONENT_A(SPECIES_RATTATA) { Moves(MOVE_CELEBRATE); } + MULTI_OPPONENT_B(SPECIES_KANGASKHAN) { Moves(MOVE_CELEBRATE); } + + } WHEN { + TURN { EXPECT_SWITCH(playerRight, 5); }; + } SCENE { + MESSAGE(AI_PARTNER_NAME " withdrew Gengar!"); + MESSAGE(AI_PARTNER_NAME " sent out Raticate!"); + NONE_OF { + MESSAGE(AI_PARTNER_NAME " withdrew Gengar!"); + MESSAGE(AI_PARTNER_NAME " sent out Rattata!"); + } + } +} + +// Used to test EXPECT_SWITCH only on partner +AI_TWO_VS_ONE_BATTLE_TEST("AI partner will not switch mid-turn into a player Pokémon (2v1)") +{ + u32 flags; + + PARAMETRIZE {flags = AI_FLAG_SMART_SWITCHING; } + PARAMETRIZE {flags = 0; } + + PASSES_RANDOMLY(SHOULD_SWITCH_ALL_MOVES_BAD_PERCENTAGE, 100, RNG_AI_SWITCH_ALL_MOVES_BAD); + GIVEN { + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | flags); + MULTI_PLAYER(SPECIES_HAUNTER); + MULTI_PLAYER(SPECIES_RATTATA); + // No moves to damage opponents. + MULTI_PARTNER(SPECIES_GENGAR) { Moves(MOVE_SHADOW_BALL); } + MULTI_PARTNER(SPECIES_GASTLY) { Moves(MOVE_LICK); } + MULTI_PARTNER(SPECIES_RATICATE) { Moves(MOVE_HEADBUTT); } + MULTI_OPPONENT_A(SPECIES_RATTATA) { Moves(MOVE_CELEBRATE); } + MULTI_OPPONENT_A(SPECIES_KANGASKHAN) { Moves(MOVE_CELEBRATE); } + + } WHEN { + TURN { EXPECT_SWITCH(playerRight, 5); }; + } SCENE { + MESSAGE(AI_PARTNER_NAME " withdrew Gengar!"); + MESSAGE(AI_PARTNER_NAME " sent out Raticate!"); + NONE_OF { + MESSAGE(AI_PARTNER_NAME " withdrew Gengar!"); + MESSAGE(AI_PARTNER_NAME " sent out Rattata!"); + } + } +} + +// Used to test EXPECT_SEND_OUT only on partner +AI_MULTI_BATTLE_TEST("AI partner will not switch into a player Pokémon after fainting (multi)") +{ + u32 flags; + + PARAMETRIZE {flags = AI_FLAG_SMART_SWITCHING; } + PARAMETRIZE {flags = 0; } + + PASSES_RANDOMLY(SHOULD_SWITCH_ALL_MOVES_BAD_PERCENTAGE, 100, RNG_AI_SWITCH_ALL_MOVES_BAD); + GIVEN { + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | flags); + MULTI_PLAYER(SPECIES_GENGAR); + MULTI_PLAYER(SPECIES_RATTATA); + // No moves to damage opponents. + MULTI_PARTNER(SPECIES_WOBBUFFET) { Status1(STATUS1_BURN); HP(1); } + MULTI_PARTNER(SPECIES_GASTLY); + MULTI_PARTNER(SPECIES_HAUNTER); + MULTI_OPPONENT_A(SPECIES_TRAPINCH) { Ability(ABILITY_ARENA_TRAP); Moves(MOVE_CELEBRATE); } + MULTI_OPPONENT_B(SPECIES_VIBRAVA) { Moves(MOVE_CELEBRATE); } + + } WHEN { + TURN { EXPECT_MOVE(playerRight, MOVE_CELEBRATE); EXPECT_SEND_OUT(playerRight, 5); }; + } SCENE { + MESSAGE(AI_PARTNER_NAME " sent out Haunter!"); + NONE_OF { + MESSAGE(AI_PARTNER_NAME " sent out Rattata!"); + } + } +} + +// Used to test EXPECT_SEND_OUT only on partner +AI_TWO_VS_ONE_BATTLE_TEST("AI partner will not switch into a player Pokémon after fainting (2v1)") +{ + u32 flags; + + PARAMETRIZE {flags = AI_FLAG_SMART_SWITCHING; } + PARAMETRIZE {flags = 0; } + + PASSES_RANDOMLY(SHOULD_SWITCH_ALL_MOVES_BAD_PERCENTAGE, 100, RNG_AI_SWITCH_ALL_MOVES_BAD); + GIVEN { + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | flags); + MULTI_PLAYER(SPECIES_GENGAR); + MULTI_PLAYER(SPECIES_RATTATA); + // No moves to damage opponents. + MULTI_PARTNER(SPECIES_WOBBUFFET) { Status1(STATUS1_BURN); HP(1); } + MULTI_PARTNER(SPECIES_GASTLY); + MULTI_PARTNER(SPECIES_HAUNTER); + MULTI_OPPONENT_A(SPECIES_TRAPINCH) { Ability(ABILITY_ARENA_TRAP); Moves(MOVE_CELEBRATE); } + MULTI_OPPONENT_A(SPECIES_VIBRAVA) { Moves(MOVE_CELEBRATE); } + + } WHEN { + TURN { EXPECT_MOVE(playerRight, MOVE_CELEBRATE); EXPECT_SEND_OUT(playerRight, 5); }; + } SCENE { + MESSAGE(AI_PARTNER_NAME " sent out Haunter!"); + NONE_OF { + MESSAGE(AI_PARTNER_NAME " sent out Rattata!"); + } + } +} + +// Used to test EXPECT_SWITCH, EXPECT_SEND_OUT, and EXPECT_MOVE on partner +AI_MULTI_BATTLE_TEST("AI partner will not switch into a player Pokémon (multi)") +{ + u32 flags; + + PARAMETRIZE {flags = AI_FLAG_SMART_SWITCHING; } + PARAMETRIZE {flags = 0; } + + PASSES_RANDOMLY(SHOULD_SWITCH_ALL_MOVES_BAD_PERCENTAGE, 100, RNG_AI_SWITCH_ALL_MOVES_BAD); + GIVEN { + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | flags); + MULTI_PLAYER(SPECIES_HAUNTER); + MULTI_PLAYER(SPECIES_RATTATA); + // No moves to damage opponents. + MULTI_PARTNER(SPECIES_GENGAR) { Moves(MOVE_SHADOW_BALL); } + MULTI_PARTNER(SPECIES_RATICATE) { Moves(MOVE_HEADBUTT); HP(1); } + MULTI_OPPONENT_A(SPECIES_RATTATA) { Moves(MOVE_CELEBRATE); } + MULTI_OPPONENT_B(SPECIES_KANGASKHAN) { Moves(MOVE_CELEBRATE); } + + } WHEN { + TURN { MOVE(playerLeft, MOVE_AURA_SPHERE, target:playerRight); EXPECT_SWITCH(playerRight, 4); EXPECT_SEND_OUT(playerRight, 3); }; + TURN { EXPECT_MOVE(playerRight, MOVE_SHADOW_BALL, target:opponentLeft); }; + } SCENE { + MESSAGE(AI_PARTNER_NAME " sent out Raticate!"); + NONE_OF { + MESSAGE(AI_PARTNER_NAME " sent out Rattata!"); + } + } +} + +// Used to test EXPECT_SWITCH, EXPECT_SEND_OUT, and EXPECT_MOVE on partner +AI_TWO_VS_ONE_BATTLE_TEST("AI partner will not switch into a player Pokémon (2v1)") +{ + u32 flags; + + PARAMETRIZE {flags = AI_FLAG_SMART_SWITCHING; } + PARAMETRIZE {flags = 0; } + + PASSES_RANDOMLY(SHOULD_SWITCH_ALL_MOVES_BAD_PERCENTAGE, 100, RNG_AI_SWITCH_ALL_MOVES_BAD); + GIVEN { + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | flags); + MULTI_PLAYER(SPECIES_HAUNTER); + MULTI_PLAYER(SPECIES_RATTATA); + // No moves to damage opponents. + MULTI_PARTNER(SPECIES_GENGAR) { Moves(MOVE_SHADOW_BALL); } + MULTI_PARTNER(SPECIES_RATICATE) { Moves(MOVE_HEADBUTT); HP(1); } + MULTI_OPPONENT_A(SPECIES_RATTATA) { Moves(MOVE_CELEBRATE); } + MULTI_OPPONENT_A(SPECIES_KANGASKHAN) { Moves(MOVE_CELEBRATE); } + + } WHEN { + TURN { MOVE(playerLeft, MOVE_AURA_SPHERE, target:playerRight); EXPECT_SWITCH(playerRight, 4); EXPECT_SEND_OUT(playerRight, 3); }; + TURN { EXPECT_MOVE(playerRight, MOVE_SHADOW_BALL, target:opponentLeft); }; + } SCENE { + MESSAGE(AI_PARTNER_NAME " sent out Raticate!"); + NONE_OF { + MESSAGE(AI_PARTNER_NAME " sent out Rattata!"); + } + } +} + +AI_TWO_VS_ONE_BATTLE_TEST("AI will not try to switch for the same pokemon for 2 spots in a 2v1 battle (all bad moves)") +{ + u32 flags; + + PARAMETRIZE {flags = AI_FLAG_SMART_SWITCHING; } + PARAMETRIZE {flags = 0; } + + PASSES_RANDOMLY(SHOULD_SWITCH_ALL_MOVES_BAD_PERCENTAGE, 100, RNG_AI_SWITCH_ALL_MOVES_BAD); + GIVEN { + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | flags); + MULTI_PLAYER(SPECIES_RATTATA); + MULTI_PLAYER(SPECIES_RATTATA); + MULTI_PARTNER(SPECIES_KANGASKHAN); + // No moves to damage player. + MULTI_OPPONENT_A(SPECIES_GENGAR) { Moves(MOVE_SHADOW_BALL); } + MULTI_OPPONENT_A(SPECIES_HAUNTER) { Moves(MOVE_SHADOW_BALL); } + MULTI_OPPONENT_A(SPECIES_GASTLY) { Moves(MOVE_LICK); } + MULTI_OPPONENT_A(SPECIES_RATICATE) { Moves(MOVE_HEADBUTT); } + } WHEN { + TURN { EXPECT_SWITCH(opponentLeft, 3); }; + } SCENE { + MESSAGE(AI_TRAINER_NAME " withdrew Gengar!"); + MESSAGE(AI_TRAINER_NAME " sent out Raticate!"); + NONE_OF { + MESSAGE(AI_TRAINER_NAME " withdrew Haunter!"); + MESSAGE(AI_TRAINER_NAME " sent out Raticate!"); + } + } +} + +AI_ONE_VS_TWO_BATTLE_TEST("AI will not switch into a partner Pokémon in a 1v2 battle (all bad moves)") +{ + u32 flags; + + PARAMETRIZE {flags = AI_FLAG_SMART_SWITCHING; } + PARAMETRIZE {flags = 0; } + + PASSES_RANDOMLY(SHOULD_SWITCH_ALL_MOVES_BAD_PERCENTAGE, 100, RNG_AI_SWITCH_ALL_MOVES_BAD); + GIVEN { + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | flags); + MULTI_PLAYER(SPECIES_RATTATA); + MULTI_PLAYER(SPECIES_KANGASKHAN); + // No moves to damage player. + MULTI_OPPONENT_A(SPECIES_HAUNTER) { Moves(MOVE_SHADOW_BALL); } + MULTI_OPPONENT_B(SPECIES_GENGAR) { Moves(MOVE_SHADOW_BALL); } + MULTI_OPPONENT_B(SPECIES_GASTLY) { Moves(MOVE_LICK); } + MULTI_OPPONENT_B(SPECIES_RATICATE) { Moves(MOVE_HEADBUTT); } + + } WHEN { + TURN { EXPECT_SWITCH(opponentRight, 5); }; + } SCENE { + MESSAGE(AI_TRAINER_2_NAME " withdrew Gengar!"); + MESSAGE(AI_TRAINER_2_NAME " sent out Raticate!"); + NONE_OF { + MESSAGE(AI_TRAINER_NAME " withdrew Haunter!"); + MESSAGE(AI_TRAINER_NAME " sent out Raticate!"); + } + } +} + AI_SINGLE_BATTLE_TEST("AI will switch out if it has no move that affects the player") { PASSES_RANDOMLY(SHOULD_SWITCH_ALL_MOVES_BAD_PERCENTAGE, 100, RNG_AI_SWITCH_ALL_MOVES_BAD); @@ -115,7 +359,7 @@ AI_SINGLE_BATTLE_TEST("When AI switches out due to having no move that affects t OPPONENT(SPECIES_ABRA) { Moves(MOVE_TACKLE); } OPPONENT(SPECIES_ABRA) { Moves(MOVE_TACKLE); } } WHEN { - TURN { MOVE(player, MOVE_SHADOW_BALL); EXPECT_SWITCH(opponent, 2); EXPECT_SEND_OUT(opponent, 4); } + TURN { MOVE(player, MOVE_SHADOW_BALL); EXPECT_SWITCH(opponent, 2); EXPECT_SEND_OUT(opponent, 0);} TURN { MOVE(player, MOVE_SHADOW_BALL); EXPECT_MOVE(opponent, MOVE_TACKLE); } } } @@ -161,7 +405,7 @@ AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_MON_CHOICES: Switch effect moves will send ASSUME(GetMoveEffect(MOVE_BATON_PASS) == EFFECT_BATON_PASS); ASSUME(GetMoveEffect(MOVE_CHILLY_RECEPTION) == EFFECT_CHILLY_RECEPTION); ASSUME(GetMoveEffect(MOVE_SHED_TAIL) == EFFECT_SHED_TAIL); - WITH_CONFIG(GEN_CONFIG_TELEPORT_BEHAVIOR, GEN_8); + WITH_CONFIG(CONFIG_TELEPORT_BEHAVIOR, GEN_8); AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_SMART_MON_CHOICES | AI_FLAG_ACE_POKEMON); PLAYER(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WOBBUFFET) { Moves(aiMove); } @@ -636,6 +880,7 @@ AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_SWITCHING: AI will switch out if it has bee GIVEN { ASSUME(GetMoveEffect(MOVE_TOXIC) == EFFECT_NON_VOLATILE_STATUS); ASSUME(GetMoveNonVolatileStatus(MOVE_TOXIC) == MOVE_EFFECT_TOXIC); + ASSUME(GetMovePower(MOVE_AURA_SPHERE) == 80); // Gen 5's 90 power causes too much damage AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_SMART_SWITCHING); PLAYER(SPECIES_ZIGZAGOON) { Moves(MOVE_SCRATCH, MOVE_CELEBRATE, MOVE_TOXIC, MOVE_AURA_SPHERE); } OPPONENT(SPECIES_ZIGZAGOON) { Moves(MOVE_SCRATCH); } @@ -770,15 +1015,15 @@ AI_DOUBLE_BATTLE_TEST("AI_FLAG_SMART_SWITCHING: AI will switch out if it has bee } } -AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_SWITCHING: AI will switch out if player's mon is semi-invulnerable and it has an absorber") +AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_SWITCHING: AI will switch out if player's mon is semi-invulnerable and it has a good switchin") { PASSES_RANDOMLY(SHOULD_SWITCH_FREE_TURN_PERCENTAGE, 100, RNG_AI_SWITCH_FREE_TURN); GIVEN { ASSUME(GetMoveType(MOVE_DIVE) == TYPE_WATER); - AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_SMART_SWITCHING); - PLAYER(SPECIES_LUVDISC) { Moves(MOVE_DIVE); } + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_SMART_SWITCHING | AI_FLAG_SMART_MON_CHOICES); + PLAYER(SPECIES_LUVDISC) { Level(1); Moves(MOVE_DIVE); } OPPONENT(SPECIES_ZIGZAGOON) { Moves(MOVE_SCRATCH); } - OPPONENT(SPECIES_MANTINE) { Moves(MOVE_SCRATCH); Ability(ABILITY_WATER_ABSORB); } + OPPONENT(SPECIES_PIKACHU) { Moves(MOVE_THUNDERBOLT); } } WHEN { TURN { MOVE(player, MOVE_DIVE) ; EXPECT_MOVE(opponent, MOVE_SCRATCH); } TURN { SKIP_TURN(player); EXPECT_SWITCH(opponent, 1); } @@ -832,7 +1077,7 @@ AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_SWITCHING: AI will switch out if player's m AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_SWITCHING: AI will switch out if player's mon is charging and it has a good switchin immunity (ability)") { - PASSES_RANDOMLY(SHOULD_SWITCH_FREE_TURN_PERCENTAGE, 100, RNG_AI_SWITCH_FREE_TURN); + PASSES_RANDOMLY(SHOULD_SWITCH_ABSORBS_MOVE_PERCENTAGE, 100, RNG_AI_SWITCH_ABSORBING); GIVEN { ASSUME(GetMoveType(MOVE_DIG) == TYPE_GROUND); AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_SMART_SWITCHING); @@ -847,7 +1092,8 @@ AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_SWITCHING: AI will switch out if player's m AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_SWITCHING: AI will switch out if it has an absorber") { - u32 aiMon; u32 move; u32 absorbingAbility; + u32 aiMon; u32 move; + enum Ability absorbingAbility; PARAMETRIZE { aiMon = SPECIES_NINETALES; absorbingAbility = ABILITY_FLASH_FIRE; move = MOVE_FLAMETHROWER;} PARAMETRIZE { aiMon = SPECIES_MANTINE; absorbingAbility = ABILITY_WATER_ABSORB; move = MOVE_SURF;} PARAMETRIZE { aiMon = SPECIES_TOXICROAK; absorbingAbility = ABILITY_DRY_SKIN; move = MOVE_SURF;} @@ -939,6 +1185,8 @@ AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_SWITCHING: AI will stay in if Encore'd into { GIVEN { ASSUME(GetMoveEffect(MOVE_ENCORE) == EFFECT_ENCORE); + ASSUME(GetSpeciesType(SPECIES_AZURILL, 0) == TYPE_NORMAL); + ASSUME(GetSpeciesType(SPECIES_AZURILL, 1) == TYPE_FAIRY); AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_SMART_SWITCHING); PLAYER(SPECIES_AZURILL) { Moves(MOVE_SCRATCH, MOVE_ENCORE); } OPPONENT(SPECIES_ODDISH) { Moves(MOVE_ACID); } @@ -950,6 +1198,22 @@ AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_SWITCHING: AI will stay in if Encore'd into } AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_SWITCHING: AI will switch out if Encore'd into neutral move with good switchin 50% of the time") +{ + PASSES_RANDOMLY(SHOULD_SWITCH_ENCORE_DAMAGE_PERCENTAGE, 100, RNG_AI_SWITCH_ENCORE); + GIVEN { + WITH_CONFIG(CONFIG_ENCORE_TARGET, GEN_3); + ASSUME(GetMoveEffect(MOVE_ENCORE) == EFFECT_ENCORE); + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_SMART_SWITCHING); + PLAYER(SPECIES_AZURILL) { Moves(MOVE_SCRATCH, MOVE_ENCORE); } + OPPONENT(SPECIES_ODDISH) { Moves(MOVE_SCRATCH); } + OPPONENT(SPECIES_ARON) { Moves(MOVE_METAL_CLAW); } + } WHEN { + TURN { EXPECT_MOVE(opponent, MOVE_SCRATCH); MOVE(player, MOVE_ENCORE); } + TURN { MOVE(player, MOVE_SCRATCH); EXPECT_SWITCH(opponent, 1); } + } +} + +AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_SWITCHING: AI will switch out if Encore'd into neutral move with good switchin 50% of the time (Gen 5+)") { PASSES_RANDOMLY(SHOULD_SWITCH_ENCORE_DAMAGE_PERCENTAGE, 100, RNG_AI_SWITCH_ENCORE); GIVEN { @@ -1055,7 +1319,7 @@ AI_SINGLE_BATTLE_TEST("Switch AI: AI will switch into mon with good type matchup AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_MON_CHOICES: AI correctly handles abilities when scoring moves") { GIVEN { - WITH_CONFIG(GEN_CONFIG_PRANKSTER_DARK_TYPES, GEN_7); + WITH_CONFIG(CONFIG_PRANKSTER_DARK_TYPES, GEN_7); ASSUME(GetSpeciesType(SPECIES_GRENINJA, 1) == TYPE_DARK); AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY | AI_FLAG_OMNISCIENT | AI_FLAG_SMART_MON_CHOICES); PLAYER(SPECIES_GRENINJA) { Moves(MOVE_WATER_GUN); } @@ -1308,7 +1572,7 @@ AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_MON_CHOICES: AI sees Echoed Voice damage co AI_SINGLE_BATTLE_TEST("AI_SMART_MON_CHOICES: AI sees its own weather setting ability when considering switchin candidates") { - u32 ability = ABILITY_NONE; + enum Ability ability = ABILITY_NONE; PARAMETRIZE { ability = ABILITY_WATER_ABSORB; } PARAMETRIZE { ability = ABILITY_DRIZZLE; } GIVEN { @@ -1328,6 +1592,8 @@ AI_SINGLE_BATTLE_TEST("AI_SMART_MON_CHOICES: AI sees its own weather setting abi AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_MON_CHOICES: AI will properly consider immunities when determining switchin type matchup") { GIVEN { + ASSUME(GetSpeciesType(SPECIES_WHIMSICOTT, 0) == TYPE_GRASS); + ASSUME(GetSpeciesType(SPECIES_WHIMSICOTT, 1) == TYPE_FAIRY); // Gen 5's pure Grass type makes the test fail AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_SMART_MON_CHOICES | AI_FLAG_OMNISCIENT); PLAYER(SPECIES_POLIWRATH) { Moves(MOVE_WATER_GUN, MOVE_KARATE_CHOP); } OPPONENT(SPECIES_ZIGZAGOON) { Level(1); Moves(MOVE_SCRATCH); } @@ -1438,3 +1704,23 @@ AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_MON_CHOICES: AI will consider choice-locked TURN { MOVE(player, MOVE_MIGHTY_CLEAVE); EXPECT_MOVE(opponent, MOVE_TACKLE); item == ITEM_NONE ? EXPECT_SEND_OUT(opponent, 1) : EXPECT_SEND_OUT(opponent, 2); } } } + +AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_MON_CHOICES: AI considers both meeting and exceeding KO thresholds correctly") +{ + u32 hp; + PARAMETRIZE { hp = 40; } + PARAMETRIZE { hp = 80; } + PARAMETRIZE { hp = 79; } + PARAMETRIZE { hp = 81; } + GIVEN { + ASSUME(GetMoveEffect(MOVE_DRAGON_RAGE) == EFFECT_FIXED_HP_DAMAGE); + ASSUME(GetMoveFixedHPDamage(MOVE_DRAGON_RAGE) == 40); + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY | AI_FLAG_SMART_SWITCHING | AI_FLAG_SMART_MON_CHOICES | AI_FLAG_OMNISCIENT); + PLAYER(SPECIES_ZIGZAGOON) { Speed(5); HP(hp); Moves(MOVE_PROTECT, MOVE_TACKLE); } + OPPONENT(SPECIES_ZIGZAGOON) { Speed(6); Moves(MOVE_EXPLOSION); } + OPPONENT(SPECIES_ZIGZAGOON) { Speed(6); Moves(MOVE_DRAGON_RAGE); } + OPPONENT(SPECIES_BELDUM) { Speed(4); Moves(MOVE_TACKLE); } + } WHEN { + TURN { MOVE(player, MOVE_PROTECT); EXPECT_MOVE(opponent, MOVE_EXPLOSION); hp > 80 ? EXPECT_SEND_OUT(opponent, 2) : EXPECT_SEND_OUT(opponent, 1); } + } +} diff --git a/test/battle/ai/can_use_all_moves.c b/test/battle/ai/can_use_all_moves.c index efae2b7544..d7ea827f39 100644 --- a/test/battle/ai/can_use_all_moves.c +++ b/test/battle/ai/can_use_all_moves.c @@ -314,8 +314,8 @@ AI_DOUBLE_BATTLE_TEST("AI can use all moves, 301-400") case EFFECT_COPYCAT: case EFFECT_LAST_RESORT: case EFFECT_AQUA_RING: - case EFFECT_GRAVITY: case EFFECT_HEALING_WISH: + case EFFECT_LUNAR_DANCE: //TODO: AI TESTS case EFFECT_RESTORE_HP: @@ -328,6 +328,7 @@ AI_DOUBLE_BATTLE_TEST("AI can use all moves, 301-400") case EFFECT_MAGNET_RISE: // tests exist elsewhere + case EFFECT_GRAVITY: case EFFECT_HEAL_BELL: case EFFECT_ATTACK_UP_USER_ALLY: @@ -383,6 +384,7 @@ AI_DOUBLE_BATTLE_TEST("AI can use all moves, 401-500") { //TODO: AI HANDLING case EFFECT_HEALING_WISH: + case EFFECT_LUNAR_DANCE: case EFFECT_WONDER_ROOM: case EFFECT_FOLLOW_ME: case EFFECT_MAGIC_ROOM: @@ -458,7 +460,6 @@ AI_DOUBLE_BATTLE_TEST("AI can use all moves, 501-600") case EFFECT_ION_DELUGE: case EFFECT_AROMATIC_MIST: case EFFECT_POWDER: - case EFFECT_FLOWER_SHIELD: case EFFECT_ELECTRIFY: //TODO: AI TESTS @@ -469,6 +470,7 @@ AI_DOUBLE_BATTLE_TEST("AI can use all moves, 501-600") case EFFECT_FAIRY_LOCK: // tests exist elsewhere + case EFFECT_FLOWER_SHIELD: case EFFECT_ROTOTILLER: case EFFECT_GRASSY_TERRAIN: case EFFECT_MISTY_TERRAIN: @@ -524,8 +526,6 @@ AI_DOUBLE_BATTLE_TEST("AI can use all moves, 601-700") switch (effect) { //TODO: AI HANDLING - case EFFECT_MAGNETIC_FLUX: - case EFFECT_GEAR_UP: case EFFECT_FAIL_IF_NOT_ARG_TYPE: case EFFECT_STUFF_CHEEKS: case EFFECT_NO_RETREAT: @@ -544,7 +544,9 @@ AI_DOUBLE_BATTLE_TEST("AI can use all moves, 601-700") case EFFECT_ELECTRIC_TERRAIN: case EFFECT_PSYCHIC_TERRAIN: case EFFECT_AURORA_VEIL: - + case EFFECT_GEAR_UP: + case EFFECT_MAGNETIC_FLUX: + // Skipped on purpose. case EFFECT_PROTECT: case EFFECT_NON_VOLATILE_STATUS: @@ -597,7 +599,6 @@ AI_DOUBLE_BATTLE_TEST("AI can use all moves, 701-800") { //TODO: AI HANDLING case EFFECT_CLANGOROUS_SOUL: - case EFFECT_LIFE_DEW: case EFFECT_POLTERGEIST: case EFFECT_COACHING: case EFFECT_REVIVAL_BLESSING: @@ -613,6 +614,7 @@ AI_DOUBLE_BATTLE_TEST("AI can use all moves, 701-800") // tests exist elsewhere case EFFECT_COURT_CHANGE: case EFFECT_DOODLE: + case EFFECT_LIFE_DEW: // Skipped on purpose. case EFFECT_PROTECT: diff --git a/test/battle/ai/check_bad_move.c b/test/battle/ai/check_bad_move.c index 776dcd7de2..c5a34f0df4 100644 --- a/test/battle/ai/check_bad_move.c +++ b/test/battle/ai/check_bad_move.c @@ -4,7 +4,8 @@ AI_SINGLE_BATTLE_TEST("AI will not try to lower opposing stats if target is protected by it's ability") { - u16 ability, species, move; + enum Ability ability; + u32 species, move; PARAMETRIZE { ability = ABILITY_SPEED_BOOST; species = SPECIES_TORCHIC; move = MOVE_SCARY_FACE; } PARAMETRIZE { ability = ABILITY_HYPER_CUTTER; species = SPECIES_KRABBY; move = MOVE_GROWL; } @@ -15,7 +16,7 @@ AI_SINGLE_BATTLE_TEST("AI will not try to lower opposing stats if target is prot PARAMETRIZE { ability = ABILITY_CLEAR_BODY; species = SPECIES_BELDUM; move = MOVE_NOBLE_ROAR; } GIVEN { - WITH_CONFIG(GEN_ILLUMINATE_EFFECT, GEN_9); + WITH_CONFIG(CONFIG_ILLUMINATE_EFFECT, GEN_9); AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_OMNISCIENT); PLAYER(species) { Ability(ability); } OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_TACKLE, move); } diff --git a/test/battle/ai/gimmick_dynamax.c b/test/battle/ai/gimmick_dynamax.c new file mode 100644 index 0000000000..99e6157c94 --- /dev/null +++ b/test/battle/ai/gimmick_dynamax.c @@ -0,0 +1,65 @@ +#include "global.h" +#include "test/battle.h" +#include "battle_ai_util.h" + +AI_SINGLE_BATTLE_TEST("AI uses Dynamax") +{ + GIVEN { + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_OMNISCIENT ); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_SCRATCH); DynamaxLevel(10); } + } WHEN { + TURN { EXPECT_MOVE(opponent, MOVE_SCRATCH, gimmick: GIMMICK_DYNAMAX); } + } +} + +AI_SINGLE_BATTLE_TEST("AI uses Dynamax -- Max Moves are scored based on max move effects, not base effects") +{ + KNOWN_FAILING; + GIVEN { + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_OMNISCIENT ); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_SCRATCH, MOVE_EXPLOSION); DynamaxLevel(10); } + } WHEN { + TURN { EXPECT_MOVE(opponent, MOVE_EXPLOSION, gimmick: GIMMICK_DYNAMAX); } + } +} + +AI_SINGLE_BATTLE_TEST("AI uses Dynamax -- AI does not dynamax before using a utility move") +{ + KNOWN_FAILING; + GIVEN { + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_OMNISCIENT ); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_FAKE_OUT); DynamaxLevel(10); } + } WHEN { + TURN { EXPECT_MOVE(opponent, MOVE_FAKE_OUT, gimmick: GIMMICK_NONE); } + } +} + +AI_TWO_VS_ONE_BATTLE_TEST("AI only Dynamaxes once per trainer in 2v1 multi battles") +{ + GIVEN { + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_OMNISCIENT); + MULTI_PLAYER(SPECIES_WOBBUFFET) { Moves(MOVE_SPLASH); } + MULTI_PARTNER(SPECIES_WOBBUFFET) { Moves(MOVE_SPLASH); } + MULTI_OPPONENT_A(SPECIES_WOBBUFFET) { Moves(MOVE_SPLASH); DynamaxLevel(10); } + MULTI_OPPONENT_A(SPECIES_WOBBUFFET) { Moves(MOVE_SPLASH); DynamaxLevel(10); } + } WHEN { + TURN { + MOVE(playerLeft, MOVE_SPLASH); + MOVE(playerRight, MOVE_SPLASH); + EXPECT_MOVE(opponentLeft, MOVE_SPLASH, gimmick: GIMMICK_DYNAMAX); + EXPECT_MOVE(opponentRight, MOVE_SPLASH, gimmick: GIMMICK_NONE); + } + TURN { + MOVE(playerLeft, MOVE_SPLASH); + MOVE(playerRight, MOVE_SPLASH); + EXPECT_MOVE(opponentLeft, MOVE_SPLASH, gimmick: GIMMICK_NONE); + EXPECT_MOVE(opponentRight, MOVE_SPLASH, gimmick: GIMMICK_NONE); + } + } +} + +// Copycatting an ally's Max Guard rendition of Trick Room was a notable strategy. +TO_DO_BATTLE_TEST("TODO: AI uses Dynamax -- AI uses Copycat against a Dynamaxed Pokemon intelligently") diff --git a/test/battle/ai/gimmick_mega.c b/test/battle/ai/gimmick_mega.c new file mode 100644 index 0000000000..ef94223122 --- /dev/null +++ b/test/battle/ai/gimmick_mega.c @@ -0,0 +1,19 @@ +#include "global.h" +#include "test/battle.h" +#include "battle_ai_util.h" + +AI_SINGLE_BATTLE_TEST("AI uses Mega Evolution") +{ + GIVEN { + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_OMNISCIENT ); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_VENUSAUR) { Item(ITEM_VENUSAURITE); Moves(MOVE_SLUDGE_BOMB); } + } WHEN { + TURN { EXPECT_MOVE(opponent, MOVE_SLUDGE_BOMB, gimmick: GIMMICK_MEGA); } + } SCENE { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_MEGA_EVOLUTION, opponent); + } THEN { + EXPECT_EQ(opponent->species, SPECIES_VENUSAUR_MEGA); + } +} + diff --git a/test/battle/ai/gimmick_z_move.c b/test/battle/ai/gimmick_z_move.c new file mode 100644 index 0000000000..fcc8d81658 --- /dev/null +++ b/test/battle/ai/gimmick_z_move.c @@ -0,0 +1,201 @@ +#include "global.h" +#include "test/battle.h" +#include "battle_ai_util.h" +#include "constants/battle_z_move_effects.h" + +AI_SINGLE_BATTLE_TEST("AI uses Z-moves.") +{ + GIVEN { + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_OMNISCIENT ); + ASSUME(GetMoveType(MOVE_QUICK_ATTACK) == TYPE_NORMAL); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_NORMALIUM_Z); Moves(MOVE_QUICK_ATTACK); } + } WHEN { + TURN { EXPECT_MOVE(opponent, MOVE_QUICK_ATTACK, gimmick: GIMMICK_Z_MOVE); } + } +} + +AI_SINGLE_BATTLE_TEST("AI does not use damaging Z-moves if the player would faint anyway.") +{ + u32 currentHP; + PARAMETRIZE { currentHP = 1; } + PARAMETRIZE { currentHP = 500; } + GIVEN { + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_OMNISCIENT ); + ASSUME(GetMoveType(MOVE_QUICK_ATTACK) == TYPE_NORMAL); + PLAYER(SPECIES_WOBBUFFET) { HP(currentHP); } + OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_NORMALIUM_Z); Moves(MOVE_QUICK_ATTACK); } + } WHEN { + if (currentHP != 1) + TURN { EXPECT_MOVE(opponent, MOVE_QUICK_ATTACK, gimmick: GIMMICK_Z_MOVE); } + else + TURN { EXPECT_MOVE(opponent, MOVE_QUICK_ATTACK, gimmick: GIMMICK_NONE); } + } +} +AI_SINGLE_BATTLE_TEST("AI uses Z-Moves -- Extreme Evoboost") +{ + GIVEN { + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_OMNISCIENT ); + ASSUME(GetMoveType(MOVE_QUICK_ATTACK) == TYPE_NORMAL); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_EEVEE) { Item(ITEM_EEVIUM_Z); Moves(MOVE_POUND, MOVE_LAST_RESORT); } + } WHEN { + TURN { EXPECT_MOVE(opponent, MOVE_LAST_RESORT, gimmick: GIMMICK_Z_MOVE); } + TURN { EXPECT_MOVE(opponent, MOVE_POUND, gimmick: GIMMICK_NONE); + SCORE_LT_VAL(opponent, MOVE_LAST_RESORT, AI_SCORE_DEFAULT); } + TURN { EXPECT_MOVE(opponent, MOVE_LAST_RESORT, gimmick: GIMMICK_NONE); } + } +} + +AI_SINGLE_BATTLE_TEST("AI uses Z-Moves -- 10,000,000 Volt Thunderbolt") +{ + GIVEN { + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_OMNISCIENT ); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_PIKACHU_PARTNER) { Item(ITEM_PIKASHUNIUM_Z); Moves(MOVE_THUNDERBOLT); } + } WHEN { + TURN { EXPECT_MOVE(opponent, MOVE_THUNDERBOLT, gimmick: GIMMICK_Z_MOVE); } + } +} +AI_SINGLE_BATTLE_TEST("AI uses Z-Moves -- Z-Conversion") +{ + enum Ability ability; + PARAMETRIZE { ability = ABILITY_NONE; } + PARAMETRIZE { ability = ABILITY_OPPORTUNIST; } + + GIVEN { + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_OMNISCIENT ); + ASSUME(GetMoveType(MOVE_CONVERSION) == TYPE_NORMAL); + PLAYER(SPECIES_WOBBUFFET) { Ability(ability); } + OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_NORMALIUM_Z); Ability(ABILITY_ADAPTABILITY); Moves(MOVE_THUNDERBOLT, MOVE_CONVERSION); } + } WHEN { + if (ability == ABILITY_OPPORTUNIST) + TURN { EXPECT_MOVE(opponent, MOVE_CONVERSION, gimmick: GIMMICK_NONE); } + else + TURN { EXPECT_MOVE(opponent, MOVE_CONVERSION, gimmick: GIMMICK_Z_MOVE); } + } +} + + +AI_SINGLE_BATTLE_TEST("AI uses Z-Moves -- Z-Destiny Bond is not used in singles") +{ + GIVEN { + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_OMNISCIENT ); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_GHOSTIUM_Z); Moves(MOVE_DESTINY_BOND); } + } WHEN { + TURN { EXPECT_MOVE(opponent, MOVE_DESTINY_BOND, gimmick: GIMMICK_NONE); } + } +} + +AI_DOUBLE_BATTLE_TEST("AI uses Z-Moves -- Z-Destiny Bond is used when about to die") +{ + u32 currentHP; + PARAMETRIZE { currentHP = 1; } + PARAMETRIZE { currentHP = 500; } + + GIVEN { + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_OMNISCIENT ); + PLAYER(SPECIES_WOBBUFFET) { Moves(MOVE_CELEBRATE, MOVE_POUND); } + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET) { HP(currentHP); Item(ITEM_GHOSTIUM_Z); Moves(MOVE_DESTINY_BOND); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + if (currentHP == 1) + TURN { EXPECT_MOVE(opponentLeft, MOVE_DESTINY_BOND, gimmick: GIMMICK_Z_MOVE); } + else + TURN { EXPECT_MOVE(opponentLeft, MOVE_DESTINY_BOND, gimmick: GIMMICK_NONE); } + } +} + +AI_SINGLE_BATTLE_TEST("AI uses Z-Moves -- Z-Detect") +{ + u32 move; + PARAMETRIZE { move = MOVE_THUNDERBOLT; } + PARAMETRIZE { move = MOVE_CLOSE_COMBAT; } + + GIVEN { + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_OMNISCIENT | AI_FLAG_PREDICT_MOVE ); + PLAYER(SPECIES_WOBBUFFET) { Moves(MOVE_CELEBRATE, MOVE_FAKE_OUT); } + OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_FIGHTINIUM_Z); Moves(MOVE_DETECT, move); } + } WHEN { + if (move == MOVE_CLOSE_COMBAT) + TURN { EXPECT_MOVE(opponent, MOVE_DETECT, gimmick: GIMMICK_NONE); } + else + TURN { EXPECT_MOVE(opponent, MOVE_DETECT, gimmick: GIMMICK_Z_MOVE); } + } +} + +AI_SINGLE_BATTLE_TEST("AI uses Z-Moves -- Z-Happy Hour") +{ + GIVEN { + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_OMNISCIENT ); + ASSUME(GetMoveType(MOVE_QUICK_ATTACK) == TYPE_NORMAL); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_NORMALIUM_Z); Moves(MOVE_POUND, MOVE_HAPPY_HOUR); } + } WHEN { + TURN { EXPECT_MOVE(opponent, MOVE_HAPPY_HOUR, gimmick: GIMMICK_Z_MOVE); + SCORE_GT_VAL(opponent, MOVE_HAPPY_HOUR, AI_SCORE_DEFAULT); } + TURN { EXPECT_MOVE(opponent, MOVE_POUND, gimmick: GIMMICK_NONE); + SCORE_EQ_VAL(opponent, MOVE_HAPPY_HOUR, 90); } + } +} + +TO_DO_BATTLE_TEST("TODO: AI uses Z-Moves -- Z-Haze") + +TO_DO_BATTLE_TEST("TODO: AI uses Z-Moves -- Z-Mirror Move") + +AI_SINGLE_BATTLE_TEST("AI uses Z-Moves -- Z-Nature Power") +{ + GIVEN { + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_OMNISCIENT | AI_FLAG_PREDICT_MOVE); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_NORMALIUM_Z); Moves(MOVE_NATURE_POWER, MOVE_HEADBUTT); } + } WHEN { + TURN { EXPECT_MOVE(opponent, MOVE_NATURE_POWER, gimmick: GIMMICK_Z_MOVE); } + } +} + +// Requires handling for Wish passing/Healing Wish/other ways to determine what pokemon to heal via switching into. +TO_DO_BATTLE_TEST("TODO: AI uses Z-Moves -- Z-Parting Shot") + +AI_SINGLE_BATTLE_TEST("AI uses Z-Moves -- Z-Splash") +{ + GIVEN { + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_OMNISCIENT ); + ASSUME(GetMoveType(MOVE_QUICK_ATTACK) == TYPE_NORMAL); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_NORMALIUM_Z); Moves(MOVE_POUND, MOVE_SPLASH); } + } WHEN { + TURN { EXPECT_MOVE(opponent, MOVE_SPLASH, gimmick: GIMMICK_Z_MOVE); + SCORE_GT_VAL(opponent, MOVE_SPLASH, AI_SCORE_DEFAULT); } + TURN { EXPECT_MOVE(opponent, MOVE_POUND, gimmick: GIMMICK_NONE); + SCORE_EQ_VAL(opponent, MOVE_SPLASH, 90); } + } +} + +TO_DO_BATTLE_TEST("TODO: AI uses Z-Moves -- Z-Tailwind") + +AI_SINGLE_BATTLE_TEST("AI uses Z-Moves -- Z-Transform") +{ + u32 currentHP, move; + PARAMETRIZE { currentHP = 1; move = MOVE_HEADBUTT; } + PARAMETRIZE { currentHP = 1; move = MOVE_THUNDERBOLT; } + PARAMETRIZE { currentHP = 500; move = MOVE_HEADBUTT; } + PARAMETRIZE { currentHP = 500; move = MOVE_THUNDERBOLT; } + + GIVEN { + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_OMNISCIENT ); + PLAYER(SPECIES_WOBBUFFET) { Moves(move, MOVE_CELEBRATE); } + OPPONENT(SPECIES_WOBBUFFET) { HP(currentHP); Item(ITEM_NORMALIUM_Z); Moves(MOVE_TRANSFORM); } + } WHEN { + if (currentHP == 1 || move == MOVE_THUNDERBOLT) + TURN { EXPECT_MOVE(opponent, MOVE_TRANSFORM, gimmick: GIMMICK_Z_MOVE); } + else + TURN { EXPECT_MOVE(opponent, MOVE_TRANSFORM, gimmick: GIMMICK_NONE); } + } +} + +TO_DO_BATTLE_TEST("TODO: AI uses Z-Moves -- Z-Trick Room") + + diff --git a/test/battle/badge_boost.c b/test/battle/badge_boost.c index eb8cecb240..b03168d476 100644 --- a/test/battle/badge_boost.c +++ b/test/battle/badge_boost.c @@ -16,7 +16,7 @@ WILD_BATTLE_TEST("Badge boost: B_FLAG_BADGE_BOOST_ATTACK boost Attack", s16 dmg) FlagSet(B_FLAG_BADGE_BOOST_ATTACK); else FlagClear(B_FLAG_BADGE_BOOST_ATTACK); - WITH_CONFIG(GEN_CONFIG_BADGE_BOOST, genConfig); + WITH_CONFIG(CONFIG_BADGE_BOOST, genConfig); PLAYER(SPECIES_WOBBUFFET) {} OPPONENT(SPECIES_WOBBUFFET) {} } WHEN { @@ -48,7 +48,7 @@ WILD_BATTLE_TEST("Badge boost: B_FLAG_BADGE_BOOST_SPATK boost Special Attack", s FlagSet(B_FLAG_BADGE_BOOST_SPATK); else FlagClear(B_FLAG_BADGE_BOOST_SPATK); - WITH_CONFIG(GEN_CONFIG_BADGE_BOOST, genConfig); + WITH_CONFIG(CONFIG_BADGE_BOOST, genConfig); PLAYER(SPECIES_WOBBUFFET) {} OPPONENT(SPECIES_WOBBUFFET) {} } WHEN { @@ -81,7 +81,7 @@ WILD_BATTLE_TEST("Badge boost: B_FLAG_BADGE_BOOST_DEFENSE boost Defense", s16 dm FlagSet(B_FLAG_BADGE_BOOST_DEFENSE); else FlagClear(B_FLAG_BADGE_BOOST_DEFENSE); - WITH_CONFIG(GEN_CONFIG_BADGE_BOOST, genConfig); + WITH_CONFIG(CONFIG_BADGE_BOOST, genConfig); PLAYER(SPECIES_WOBBUFFET) {} OPPONENT(SPECIES_WOBBUFFET) {} } WHEN { @@ -114,7 +114,7 @@ WILD_BATTLE_TEST("Badge boost: B_FLAG_BADGE_BOOST_SPDEF boost Special Defense", FlagSet(B_FLAG_BADGE_BOOST_SPDEF); else FlagClear(B_FLAG_BADGE_BOOST_SPDEF); - WITH_CONFIG(GEN_CONFIG_BADGE_BOOST, genConfig); + WITH_CONFIG(CONFIG_BADGE_BOOST, genConfig); PLAYER(SPECIES_WOBBUFFET) {} OPPONENT(SPECIES_WOBBUFFET) {} } WHEN { @@ -146,7 +146,7 @@ WILD_BATTLE_TEST("Badge boost: B_FLAG_BADGE_BOOST_SPEED boost Speed", s16 dmg) FlagSet(B_FLAG_BADGE_BOOST_SPEED); else FlagClear(B_FLAG_BADGE_BOOST_SPEED); - WITH_CONFIG(GEN_CONFIG_BADGE_BOOST, genConfig); + WITH_CONFIG(CONFIG_BADGE_BOOST, genConfig); PLAYER(SPECIES_WOBBUFFET) { Speed(100); HP(1); } OPPONENT(SPECIES_WOBBUFFET) { Speed(101); HP(1); } } WHEN { diff --git a/test/battle/crit_chance.c b/test/battle/crit_chance.c index 5a4dd8d653..8e1c9cf682 100644 --- a/test/battle/crit_chance.c +++ b/test/battle/crit_chance.c @@ -13,7 +13,7 @@ SINGLE_BATTLE_TEST("Critical hits without modifiers occur at different rates by PASSES_RANDOMLY(passes, trials, RNG_CRITICAL_HIT); GIVEN { - WITH_CONFIG(GEN_CONFIG_CRIT_CHANCE, genConfig); + WITH_CONFIG(CONFIG_CRIT_CHANCE, genConfig); ASSUME(GetSpeciesBaseSpeed(SPECIES_WOBBUFFET) == 33); PLAYER(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WOBBUFFET); @@ -35,7 +35,7 @@ SINGLE_BATTLE_TEST("Crit Chance: Raising critical hit rate to 3 guarantees a cri PARAMETRIZE { genConfig = j; passes = 1, trials = 1; } // 100% PASSES_RANDOMLY(passes, trials, RNG_CRITICAL_HIT); GIVEN { - WITH_CONFIG(GEN_CONFIG_CRIT_CHANCE, genConfig); + WITH_CONFIG(CONFIG_CRIT_CHANCE, genConfig); ASSUME(GetMoveCriticalHitStage(MOVE_SLASH) == 1); ASSUME(gItemsInfo[ITEM_SCOPE_LENS].holdEffect == HOLD_EFFECT_SCOPE_LENS); PLAYER(SPECIES_TOGEKISS) { Ability(ABILITY_SUPER_LUCK); Item(ITEM_SCOPE_LENS); }; diff --git a/test/battle/damage_formula.c b/test/battle/damage_formula.c index 4a7e4ec1ef..b62ed36ad9 100644 --- a/test/battle/damage_formula.c +++ b/test/battle/damage_formula.c @@ -41,7 +41,7 @@ SINGLE_BATTLE_TEST("Damage calculation matches Gen5+") } } -SINGLE_BATTLE_TEST("Damage calculation matches Gen5+ (Muscle Band, crit)") +SINGLE_BATTLE_TEST("Damage calculation matches Gen6+ (Muscle Band, crit)") { s16 dmg; s16 expectedDamage; @@ -62,6 +62,7 @@ SINGLE_BATTLE_TEST("Damage calculation matches Gen5+ (Muscle Band, crit)") PARAMETRIZE { expectedDamage = 276; } PARAMETRIZE { expectedDamage = 268; } GIVEN { + WITH_CONFIG(CONFIG_CRIT_MULTIPLIER, GEN_6); ASSUME(GetMoveCategory(MOVE_ICE_FANG) == DAMAGE_CATEGORY_PHYSICAL); PLAYER(SPECIES_GLACEON) { Level(75); Attack(123); Item(ITEM_MUSCLE_BAND); } OPPONENT(SPECIES_GARCHOMP) { Defense(163); } @@ -118,7 +119,7 @@ SINGLE_BATTLE_TEST("Damage calculation matches Gen5+ (Marshadow vs Mawile)") } } -DOUBLE_BATTLE_TEST("A spread move will do correct damage to the second mon if the first target faints from first hit of the spread move") +DOUBLE_BATTLE_TEST("A spread move will do correct damage to the second mon if the first target faints from first hit of the spread move (double battle)") { s16 damage[6]; GIVEN { @@ -152,6 +153,108 @@ DOUBLE_BATTLE_TEST("A spread move will do correct damage to the second mon if th } } +MULTI_BATTLE_TEST("A spread move will do correct damage to the second mon if the first target faints from first hit of the spread move (multibattle)") +{ + s16 damage[6]; + GIVEN { + MULTI_PLAYER(SPECIES_REGIROCK); + MULTI_PARTNER(SPECIES_REGIROCK); + MULTI_OPPONENT_A(SPECIES_WOBBUFFET) { HP(200); } + MULTI_OPPONENT_B(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(playerLeft, MOVE_ROCK_SLIDE); } + TURN { MOVE(playerLeft, MOVE_ROCK_SLIDE); MOVE(playerRight, MOVE_ROCK_SLIDE); } + TURN { MOVE(playerLeft, MOVE_ROCK_SLIDE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_ROCK_SLIDE, playerLeft); + HP_BAR(opponentLeft, captureDamage: &damage[0]); + HP_BAR(opponentRight, captureDamage: &damage[1]); + + ANIMATION(ANIM_TYPE_MOVE, MOVE_ROCK_SLIDE, playerLeft); + HP_BAR(opponentLeft, captureDamage: &damage[2]); + HP_BAR(opponentRight, captureDamage: &damage[3]); + + ANIMATION(ANIM_TYPE_MOVE, MOVE_ROCK_SLIDE, playerRight); + HP_BAR(opponentRight, captureDamage: &damage[4]); + + ANIMATION(ANIM_TYPE_MOVE, MOVE_ROCK_SLIDE, playerLeft); + HP_BAR(opponentRight, captureDamage: &damage[5]); + } THEN { + EXPECT_EQ(damage[0], damage[1]); + EXPECT_EQ(damage[1], damage[3]); + EXPECT_MUL_EQ(damage[5], UQ_4_12(0.75), damage[3]); + EXPECT_EQ(damage[4], damage[5]); + } +} + +TWO_VS_ONE_BATTLE_TEST("A spread move will do correct damage to the second mon if the first target faints from first hit of the spread move (2v1)") +{ + s16 damage[6]; + GIVEN { + MULTI_PLAYER(SPECIES_REGIROCK); + MULTI_PARTNER(SPECIES_REGIROCK); + MULTI_OPPONENT_A(SPECIES_WOBBUFFET) { HP(200); } + MULTI_OPPONENT_A(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(playerLeft, MOVE_ROCK_SLIDE); } + TURN { MOVE(playerLeft, MOVE_ROCK_SLIDE); MOVE(playerRight, MOVE_ROCK_SLIDE); } + TURN { MOVE(playerLeft, MOVE_ROCK_SLIDE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_ROCK_SLIDE, playerLeft); + HP_BAR(opponentLeft, captureDamage: &damage[0]); + HP_BAR(opponentRight, captureDamage: &damage[1]); + + ANIMATION(ANIM_TYPE_MOVE, MOVE_ROCK_SLIDE, playerLeft); + HP_BAR(opponentLeft, captureDamage: &damage[2]); + HP_BAR(opponentRight, captureDamage: &damage[3]); + + ANIMATION(ANIM_TYPE_MOVE, MOVE_ROCK_SLIDE, playerRight); + HP_BAR(opponentRight, captureDamage: &damage[4]); + + ANIMATION(ANIM_TYPE_MOVE, MOVE_ROCK_SLIDE, playerLeft); + HP_BAR(opponentRight, captureDamage: &damage[5]); + } THEN { + EXPECT_EQ(damage[0], damage[1]); + EXPECT_EQ(damage[1], damage[3]); + EXPECT_MUL_EQ(damage[5], UQ_4_12(0.75), damage[3]); + EXPECT_EQ(damage[4], damage[5]); + } +} + +ONE_VS_TWO_BATTLE_TEST("A spread move will do correct damage to the second mon if the first target faints from first hit of the spread move (1v2)") +{ + s16 damage[6]; + GIVEN { + MULTI_PLAYER(SPECIES_REGIROCK); + MULTI_PLAYER(SPECIES_REGIROCK); + MULTI_OPPONENT_A(SPECIES_WOBBUFFET) { HP(200); } + MULTI_OPPONENT_B(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(playerLeft, MOVE_ROCK_SLIDE); } + TURN { MOVE(playerLeft, MOVE_ROCK_SLIDE); MOVE(playerRight, MOVE_ROCK_SLIDE); } + TURN { MOVE(playerLeft, MOVE_ROCK_SLIDE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_ROCK_SLIDE, playerLeft); + HP_BAR(opponentLeft, captureDamage: &damage[0]); + HP_BAR(opponentRight, captureDamage: &damage[1]); + + ANIMATION(ANIM_TYPE_MOVE, MOVE_ROCK_SLIDE, playerLeft); + HP_BAR(opponentLeft, captureDamage: &damage[2]); + HP_BAR(opponentRight, captureDamage: &damage[3]); + + ANIMATION(ANIM_TYPE_MOVE, MOVE_ROCK_SLIDE, playerRight); + HP_BAR(opponentRight, captureDamage: &damage[4]); + + ANIMATION(ANIM_TYPE_MOVE, MOVE_ROCK_SLIDE, playerLeft); + HP_BAR(opponentRight, captureDamage: &damage[5]); + } THEN { + EXPECT_EQ(damage[0], damage[1]); + EXPECT_EQ(damage[1], damage[3]); + EXPECT_MUL_EQ(damage[5], UQ_4_12(0.75), damage[3]); + EXPECT_EQ(damage[4], damage[5]); + } +} + SINGLE_BATTLE_TEST("Punching Glove vs Muscle Band Damage calculation") { s16 dmgPlayer, dmgOpponent; @@ -281,7 +384,7 @@ DOUBLE_BATTLE_TEST("Transistor Damage calculation", s16 damage) } } GIVEN { - WITH_CONFIG(GEN_CONFIG_TRANSISTOR_BOOST, gen); + WITH_CONFIG(CONFIG_TRANSISTOR_BOOST, gen); ASSUME(GetMoveType(MOVE_WILD_CHARGE) == TYPE_ELECTRIC); ASSUME(GetMoveType(MOVE_THUNDER_SHOCK) == TYPE_ELECTRIC); ASSUME(GetMoveCategory(MOVE_WILD_CHARGE) == DAMAGE_CATEGORY_PHYSICAL); diff --git a/test/battle/end_turn_effects.c b/test/battle/end_turn_effects.c index 01c844f9b5..931f792efe 100644 --- a/test/battle/end_turn_effects.c +++ b/test/battle/end_turn_effects.c @@ -1,7 +1,7 @@ #include "global.h" #include "test/battle.h" -DOUBLE_BATTLE_TEST("End Turn Effects: First Event Block is executed correctly") +DOUBLE_BATTLE_TEST("End Turn Effects: First Event Block is executed correctly (double battle)") { s16 healed; s16 damage; @@ -53,3 +53,89 @@ DOUBLE_BATTLE_TEST("End Turn Effects: Effects are applied by Speed Order") HP_BAR(playerRight); } } + +MULTI_BATTLE_TEST("End Turn Effects: First Event Block is executed correctly (multibattle)") +{ + s16 healed; + s16 damage; + + GIVEN { + MULTI_PLAYER(SPECIES_WYNAUT) { HP(100); Speed(1); } + MULTI_PARTNER(SPECIES_EKANS) { HP(100); Ability(ABILITY_SHED_SKIN); Status1(STATUS1_BURN); Speed(2); } + MULTI_OPPONENT_A(SPECIES_WYNAUT) { HP(100); Item(ITEM_LEFTOVERS); Speed(3); } + MULTI_OPPONENT_B(SPECIES_WOBBUFFET) { HP(100); Item(ITEM_BLACK_SLUDGE); Speed(4); } + } WHEN { + TURN { MOVE(playerLeft, MOVE_GRASSY_TERRAIN); } + } SCENE { + MESSAGE("The opposing Wobbuffet is healed by the grassy terrain!"); + HP_BAR(opponentRight, captureDamage: &healed); + HP_BAR(opponentRight, captureDamage: &damage); + MESSAGE("The opposing Wobbuffet was hurt by the Black Sludge!"); + MESSAGE("The opposing Wynaut is healed by the grassy terrain!"); + MESSAGE("The opposing Wynaut restored a little HP using its Leftovers!"); + MESSAGE("Ekans is healed by the grassy terrain!"); + MESSAGE("Ekans's Shed Skin cured its burn problem!"); + MESSAGE("Wynaut is healed by the grassy terrain!"); + } THEN { + EXPECT_GT(0, healed); + EXPECT_GT(damage, 0); + } +} + + +TWO_VS_ONE_BATTLE_TEST("End Turn Effects: First Event Block is executed correctly (2v1)") +{ + s16 healed; + s16 damage; + + GIVEN { + MULTI_PLAYER(SPECIES_WYNAUT) { HP(100); Speed(1);} + MULTI_PARTNER(SPECIES_EKANS) { HP(100); Ability(ABILITY_SHED_SKIN); Status1(STATUS1_BURN); Speed(2); } + MULTI_OPPONENT_A(SPECIES_WYNAUT) { HP(100); Item(ITEM_LEFTOVERS); Speed(3); } + MULTI_OPPONENT_A(SPECIES_WOBBUFFET) { HP(100); Item(ITEM_BLACK_SLUDGE); Speed(4); } + } WHEN { + TURN { MOVE(playerLeft, MOVE_GRASSY_TERRAIN); } + } SCENE { + MESSAGE("The opposing Wobbuffet is healed by the grassy terrain!"); + HP_BAR(opponentRight, captureDamage: &healed); + HP_BAR(opponentRight, captureDamage: &damage); + MESSAGE("The opposing Wobbuffet was hurt by the Black Sludge!"); + MESSAGE("The opposing Wynaut is healed by the grassy terrain!"); + MESSAGE("The opposing Wynaut restored a little HP using its Leftovers!"); + MESSAGE("Ekans is healed by the grassy terrain!"); + MESSAGE("Ekans's Shed Skin cured its burn problem!"); + MESSAGE("Wynaut is healed by the grassy terrain!"); + } THEN { + EXPECT_GT(0, healed); + EXPECT_GT(damage, 0); + } +} + + +ONE_VS_TWO_BATTLE_TEST("End Turn Effects: First Event Block is executed correctly (1v2)") +{ + s16 healed; + s16 damage; + + GIVEN { + MULTI_PLAYER(SPECIES_WYNAUT) { HP(100); Speed(1);} + MULTI_PLAYER(SPECIES_EKANS) { HP(100); Ability(ABILITY_SHED_SKIN); Status1(STATUS1_BURN); Speed(2); } + MULTI_OPPONENT_A(SPECIES_WYNAUT) { HP(100); Item(ITEM_LEFTOVERS); Speed(3); } + MULTI_OPPONENT_B(SPECIES_WOBBUFFET) { HP(100); Item(ITEM_BLACK_SLUDGE); Speed(4); } + } WHEN { + TURN { MOVE(playerLeft, MOVE_GRASSY_TERRAIN); } + } SCENE { + MESSAGE("The opposing Wobbuffet is healed by the grassy terrain!"); + HP_BAR(opponentRight, captureDamage: &healed); + HP_BAR(opponentRight, captureDamage: &damage); + MESSAGE("The opposing Wobbuffet was hurt by the Black Sludge!"); + MESSAGE("The opposing Wynaut is healed by the grassy terrain!"); + MESSAGE("The opposing Wynaut restored a little HP using its Leftovers!"); + MESSAGE("Ekans is healed by the grassy terrain!"); + MESSAGE("Ekans's Shed Skin cured its burn problem!"); + MESSAGE("Wynaut is healed by the grassy terrain!"); + } THEN { + EXPECT_GT(0, healed); + EXPECT_GT(damage, 0); + } +} diff --git a/test/battle/exp.c b/test/battle/exp.c index 12c9c1e9bd..c22b7fa2f5 100644 --- a/test/battle/exp.c +++ b/test/battle/exp.c @@ -1,16 +1,17 @@ #include "global.h" #include "test/battle.h" -#if B_EXP_CATCH >= GEN_6 - -WILD_BATTLE_TEST("Pokemon gain exp after catching a Pokemon") +WILD_BATTLE_TEST("Pokemon gain experience after catching a Pokemon (Gen6+)") { u8 level = 0; + u32 config = 0; - PARAMETRIZE { level = 50; } - PARAMETRIZE { level = MAX_LEVEL; } + PARAMETRIZE { level = MAX_LEVEL; config = GEN_5; } + PARAMETRIZE { level = 50; config = GEN_5; } + PARAMETRIZE { level = 50; config = GEN_6; } GIVEN { + WITH_CONFIG(CONFIG_EXP_CATCH, config); PLAYER(SPECIES_WOBBUFFET) { Level(level); } OPPONENT(SPECIES_CATERPIE) { HP(1); } } WHEN { @@ -18,14 +19,14 @@ WILD_BATTLE_TEST("Pokemon gain exp after catching a Pokemon") } SCENE { MESSAGE("You used Ultra Ball!"); ANIMATION(ANIM_TYPE_SPECIAL, B_ANIM_BALL_THROW, player); - if (level != MAX_LEVEL) { + if (level != MAX_LEVEL && config >= GEN_6) { EXPERIENCE_BAR(player); + } else { + NOT EXPERIENCE_BAR(player); } } } -#endif // B_EXP_CATCH - WILD_BATTLE_TEST("Higher leveled Pokemon give more exp", s32 exp) { u8 level = 0; diff --git a/test/battle/form_change/mega_evolution.c b/test/battle/form_change/mega_evolution.c index 3e27a84608..af16b779b5 100644 --- a/test/battle/form_change/mega_evolution.c +++ b/test/battle/form_change/mega_evolution.c @@ -74,7 +74,7 @@ SINGLE_BATTLE_TEST("Rayquaza can Mega Evolve knowing Dragon Ascent") SINGLE_BATTLE_TEST("Mega Evolution doesn't affect turn order (Gen6)") { GIVEN { - WITH_CONFIG(GEN_CONFIG_MEGA_EVO_TURN_ORDER, GEN_6); + WITH_CONFIG(CONFIG_MEGA_EVO_TURN_ORDER, GEN_6); PLAYER(SPECIES_GARDEVOIR) { Item(ITEM_GARDEVOIRITE); } OPPONENT(SPECIES_WOBBUFFET) {} } WHEN { @@ -90,7 +90,7 @@ SINGLE_BATTLE_TEST("Mega Evolution doesn't affect turn order (Gen6)") SINGLE_BATTLE_TEST("Mega Evolution affects turn order (Gen7+)") { GIVEN { - WITH_CONFIG(GEN_CONFIG_MEGA_EVO_TURN_ORDER, GEN_7); + WITH_CONFIG(CONFIG_MEGA_EVO_TURN_ORDER, GEN_7); PLAYER(SPECIES_GARDEVOIR) { Item(ITEM_GARDEVOIRITE);} OPPONENT(SPECIES_WOBBUFFET) {} } WHEN { @@ -106,7 +106,7 @@ SINGLE_BATTLE_TEST("Mega Evolution affects turn order (Gen7+)") SINGLE_BATTLE_TEST("Abilities replaced by Mega Evolution do not affect turn order") { GIVEN { - WITH_CONFIG(GEN_CONFIG_MEGA_EVO_TURN_ORDER, GEN_7); + WITH_CONFIG(CONFIG_MEGA_EVO_TURN_ORDER, GEN_7); ASSUME(GetSpeciesAbility(SPECIES_SABLEYE_MEGA, 0) != ABILITY_STALL && GetSpeciesAbility(SPECIES_SABLEYE_MEGA, 1) != ABILITY_STALL); PLAYER(SPECIES_SABLEYE) { Item(ITEM_SABLENITE); Ability(ABILITY_STALL); Speed(105); } diff --git a/test/battle/form_change/ultra_burst.c b/test/battle/form_change/ultra_burst.c index 4b1bf6a8e3..183f61ec87 100644 --- a/test/battle/form_change/ultra_burst.c +++ b/test/battle/form_change/ultra_burst.c @@ -58,7 +58,7 @@ DOUBLE_BATTLE_TEST("Ultra Burst's order is determined by Speed - player faster") SINGLE_BATTLE_TEST("Ultra Burst affects turn order") { GIVEN { - WITH_CONFIG(GEN_CONFIG_MEGA_EVO_TURN_ORDER, GEN_7); + WITH_CONFIG(CONFIG_MEGA_EVO_TURN_ORDER, GEN_7); PLAYER(SPECIES_NECROZMA_DUSK_MANE) { Item(ITEM_ULTRANECROZIUM_Z);} OPPONENT(SPECIES_WOBBUFFET) {} } WHEN { diff --git a/test/battle/gimmick/dynamax.c b/test/battle/gimmick/dynamax.c index 0329ee903c..bf4abb86d5 100644 --- a/test/battle/gimmick/dynamax.c +++ b/test/battle/gimmick/dynamax.c @@ -239,8 +239,8 @@ SINGLE_BATTLE_TEST("Dynamax: Dynamaxed Pokemon are affected by Grudge") } SCENE { MESSAGE("The opposing Wobbuffet used Grudge!"); MESSAGE("Wobbuffet used Max Strike!"); - MESSAGE("Wobbuffet's Scratch lost all its PP due to the grudge!"); MESSAGE("The opposing Wobbuffet fainted!"); + MESSAGE("Wobbuffet's Scratch lost all its PP due to the grudge!"); } } @@ -423,7 +423,7 @@ SINGLE_BATTLE_TEST("Dynamax: Dynamaxed Pokemon that changes forms does not gain { u16 capturedHP, finalHP; GIVEN { - WITH_CONFIG(GEN_CONFIG_BATTLE_BOND, GEN_8); + WITH_CONFIG(CONFIG_BATTLE_BOND, GEN_8); PLAYER(SPECIES_GRENINJA_BATTLE_BOND) { Ability(ABILITY_BATTLE_BOND); HP(100); Speed(100); } OPPONENT(SPECIES_CATERPIE) { HP(1); Speed(1000); } OPPONENT(SPECIES_WOBBUFFET) { Speed(10); } @@ -860,7 +860,7 @@ SINGLE_BATTLE_TEST("Dynamax: Max Hailstorm sets up hail") MESSAGE("It started to hail!"); MESSAGE("The opposing Wobbuffet used Celebrate!"); ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HAIL_CONTINUES); -#endif +#endif } } @@ -913,7 +913,7 @@ SINGLE_BATTLE_TEST("Dynamax: Max Mindstorm sets up Psychic Terrain") } SCENE { MESSAGE("The opposing Wobbuffet used Extreme Speed!"); MESSAGE("Wobbuffet used Max Mindstorm!"); - MESSAGE("The opposing Wobbuffet cannot use Extreme Speed!"); + MESSAGE("Wobbuffet is protected by the Psychic Terrain!"); MESSAGE("Wobbuffet used Max Mindstorm!"); } } @@ -971,6 +971,7 @@ SINGLE_BATTLE_TEST("Dynamax: G-Max Stonesurge sets up Stealth Rocks") SINGLE_BATTLE_TEST("Dynamax: G-Max Steelsurge sets up sharp steel") { GIVEN { + WITH_CONFIG(CONFIG_DEFOG_EFFECT_CLEARING, GEN_6); ASSUME(MoveHasAdditionalEffect(MOVE_G_MAX_STEELSURGE, MOVE_EFFECT_STEELSURGE)); PLAYER(SPECIES_COPPERAJAH) { GigantamaxFactor(TRUE); } OPPONENT(SPECIES_WOBBUFFET); @@ -1464,7 +1465,7 @@ DOUBLE_BATTLE_TEST("Dynamax: G-Max Chi Strike boosts allies' crit chance by 1 st { u32 j; GIVEN { - WITH_CONFIG(GEN_CONFIG_CRIT_CHANCE, GEN_6); + WITH_CONFIG(CONFIG_CRIT_CHANCE, GEN_6); ASSUME(MoveHasAdditionalEffect(MOVE_G_MAX_CHI_STRIKE, MOVE_EFFECT_CRIT_PLUS_SIDE)); PLAYER(SPECIES_MACHAMP) { GigantamaxFactor(TRUE); } PLAYER(SPECIES_MACHOP); @@ -1608,7 +1609,8 @@ SINGLE_BATTLE_TEST("Dynamax: Max Attacks prints a message when hitting into Max SINGLE_BATTLE_TEST("Dynamax: Max Moves don't bypass absorbing abilities") { - u32 move, ability, species; + u32 move, species; + enum Ability ability; PARAMETRIZE { move = MOVE_SPARK; ability = ABILITY_VOLT_ABSORB; species = SPECIES_LANTURN; } PARAMETRIZE { move = MOVE_WATER_GUN; ability = ABILITY_WATER_ABSORB; species = SPECIES_LANTURN; } PARAMETRIZE { move = MOVE_EMBER; ability = ABILITY_FLASH_FIRE; species = SPECIES_HEATRAN; } @@ -1658,16 +1660,17 @@ SINGLE_BATTLE_TEST("Dynamax: Dynamax is reverted before switch out") } } -SINGLE_BATTLE_TEST("Dynamax: Destiny Bond fails if a dynamaxed battler is present on field") +SINGLE_BATTLE_TEST("Dynamax: max move against semi-invulnerable target prints the correct message") { GIVEN { - ASSUME(GetMoveEffect(MOVE_DESTINY_BOND) == EFFECT_DESTINY_BOND); - PLAYER(SPECIES_WOBBUFFET); - OPPONENT(SPECIES_WOBBUFFET); + PLAYER(SPECIES_WOBBUFFET) {Speed(1);}; + OPPONENT(SPECIES_WOBBUFFET) {Speed(2);}; } WHEN { - TURN { MOVE(opponent, MOVE_DESTINY_BOND); MOVE(player, MOVE_SCRATCH, gimmick: GIMMICK_DYNAMAX); } + TURN { MOVE(player, MOVE_SCRATCH, gimmick: GIMMICK_DYNAMAX); MOVE(opponent, MOVE_FLY); } } SCENE { - MESSAGE("The move was blocked by the power of Dynamax!"); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_DYNAMAX_GROWTH, player); + MESSAGE("Wobbuffet used Max Strike!"); + MESSAGE("The opposing Wobbuffet avoided the attack!"); } } diff --git a/test/battle/gimmick/terastal.c b/test/battle/gimmick/terastal.c index d238ea0d51..d78a68dc53 100644 --- a/test/battle/gimmick/terastal.c +++ b/test/battle/gimmick/terastal.c @@ -420,8 +420,8 @@ SINGLE_BATTLE_TEST("(TERA) Double Shock does not remove the user's Electric type TURN { MOVE(player, MOVE_DOUBLE_SHOCK); MOVE(opponent, MOVE_RECOVER); } TURN { MOVE(player, MOVE_DOUBLE_SHOCK, gimmick: GIMMICK_TERA); MOVE(opponent, MOVE_RECOVER); } TURN { MOVE(player, MOVE_DOUBLE_SHOCK); MOVE(opponent, MOVE_RECOVER); } - TURN { SWITCH(player, 1); MOVE(opponent, MOVE_RECOVER); } - TURN { SWITCH(player, 0); MOVE(opponent, MOVE_RECOVER); } + TURN { SWITCH(player, 1); } + TURN { SWITCH(player, 0); } TURN { MOVE(player, MOVE_DOUBLE_SHOCK); MOVE(opponent, MOVE_RECOVER); } TURN { MOVE(player, MOVE_DOUBLE_SHOCK); } } SCENE { @@ -826,7 +826,7 @@ SINGLE_BATTLE_TEST("(TERA) Pokemon with Tera forms change upon Terastallizing") SINGLE_BATTLE_TEST("(TERA) All type indicators function correctly") { - u32 type; + enum Type type; PARAMETRIZE { type = TYPE_NONE; } PARAMETRIZE { type = TYPE_NORMAL; } PARAMETRIZE { type = TYPE_FIGHTING; } @@ -858,7 +858,7 @@ SINGLE_BATTLE_TEST("(TERA) All type indicators function correctly") SINGLE_BATTLE_TEST("(TERA) All type indicators function correctly - Opponent") { - u32 type; + enum Type type; PARAMETRIZE { type = TYPE_NONE; } PARAMETRIZE { type = TYPE_NORMAL; } PARAMETRIZE { type = TYPE_FIGHTING; } diff --git a/test/battle/gimmick/zmove.c b/test/battle/gimmick/zmove.c index 1744fd151b..74f4ea3675 100644 --- a/test/battle/gimmick/zmove.c +++ b/test/battle/gimmick/zmove.c @@ -6,7 +6,7 @@ SINGLE_BATTLE_TEST("(Z-MOVE) Z-Moves do not retain priority") { GIVEN { - WITH_CONFIG(GEN_CONFIG_MEGA_EVO_TURN_ORDER, GEN_7); // TODO: Decouple this config from other gimmicks + WITH_CONFIG(CONFIG_MEGA_EVO_TURN_ORDER, GEN_7); // TODO: Decouple this config from other gimmicks ASSUME(GetMoveType(MOVE_QUICK_ATTACK) == TYPE_NORMAL); PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_NORMALIUM_Z); Speed(1); } OPPONENT(SPECIES_WOBBUFFET) { Speed(2); } @@ -115,10 +115,16 @@ SINGLE_BATTLE_TEST("(Z-MOVE) Z_EFFECT_ALL_STATS_UP raises all of a battler's sta } } -SINGLE_BATTLE_TEST("(Z-MOVE) Z_EFFECT_BOOST_CRITS raises a battler's critical hit ratio") +SINGLE_BATTLE_TEST("(Z-MOVE) Z_EFFECT_BOOST_CRITS raises a battler's critical hit ratio by 2 stages") { - PASSES_RANDOMLY(1, 2, RNG_CRITICAL_HIT); + u32 genConfig = 0, chance; + for (u32 j = GEN_1; j <= GEN_5; j++) + PARAMETRIZE { genConfig = j; chance = 4; } // 25% + for (u32 j = GEN_6; j <= GEN_9; j++) + PARAMETRIZE { genConfig = j; chance = 2; } // 50% + PASSES_RANDOMLY(1, chance, RNG_CRITICAL_HIT); GIVEN { + WITH_CONFIG(CONFIG_CRIT_CHANCE, genConfig); ASSUME(GetMoveType(MOVE_FORESIGHT) == TYPE_NORMAL); ASSUME(GetMoveZEffect(MOVE_FORESIGHT) == Z_EFFECT_BOOST_CRITS); PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_NORMALIUM_Z); } @@ -527,7 +533,7 @@ SINGLE_BATTLE_TEST("(Z-MOVE) 10,000,000 Volt Thunderbolt has an increased critic PARAMETRIZE { genConfig = j; chance = 2; } PASSES_RANDOMLY(1, chance, RNG_CRITICAL_HIT); GIVEN { - WITH_CONFIG(GEN_CONFIG_CRIT_CHANCE, genConfig); + WITH_CONFIG(CONFIG_CRIT_CHANCE, genConfig); ASSUME(GetMoveCriticalHitStage(MOVE_10_000_000_VOLT_THUNDERBOLT) == 2); ASSUME(GetSpeciesBaseSpeed(SPECIES_PIKACHU_PARTNER) == 90); PLAYER(SPECIES_PIKACHU_PARTNER) { Item(ITEM_PIKASHUNIUM_Z); } @@ -579,7 +585,7 @@ SINGLE_BATTLE_TEST("(Z-MOVE) Extreme Evoboost boosts all the user's stats by two SINGLE_BATTLE_TEST("(Z-MOVE) Genesis Supernova sets up psychic terrain") { GIVEN { - ASSUME(GetMoveEffect(MOVE_GENESIS_SUPERNOVA) == EFFECT_HIT_SET_TERRAIN); + ASSUME(MoveHasAdditionalEffect(MOVE_GENESIS_SUPERNOVA, MOVE_EFFECT_PSYCHIC_TERRAIN)); PLAYER(SPECIES_MEW) { Item(ITEM_MEWNIUM_Z); } OPPONENT(SPECIES_WOBBUFFET); } WHEN { @@ -589,7 +595,7 @@ SINGLE_BATTLE_TEST("(Z-MOVE) Genesis Supernova sets up psychic terrain") ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_ZMOVE_ACTIVATE, player); ANIMATION(ANIM_TYPE_MOVE, MOVE_GENESIS_SUPERNOVA, player); NOT { ANIMATION(ANIM_TYPE_MOVE, MOVE_QUICK_ATTACK, player); } - MESSAGE("Mew cannot use Quick Attack!"); + MESSAGE("The opposing Wobbuffet is protected by the Psychic Terrain!"); } } diff --git a/test/battle/hazards.c b/test/battle/hazards.c index 17ecb41f5c..ea0aef70e5 100644 --- a/test/battle/hazards.c +++ b/test/battle/hazards.c @@ -61,3 +61,113 @@ SINGLE_BATTLE_TEST("Hazards are applied correctly after a battler faints") MESSAGE("Pointed stones dug into Wynaut!"); } } + +SINGLE_BATTLE_TEST("Toxic Spikes can be removed after fainting to other hazards") +{ + KNOWN_FAILING; // tryfaintmon changes something that doesn't allow other switch-in effects on the battler + + GIVEN { + PLAYER(SPECIES_WYNAUT); + PLAYER(SPECIES_GRIMER) { HP(1); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_STEALTH_ROCK); } + TURN { MOVE(opponent, MOVE_TOXIC_SPIKES); } + TURN { MOVE(opponent, MOVE_STICKY_WEB); } + TURN { MOVE(opponent, MOVE_SPIKES); } + TURN { MOVE(opponent, MOVE_STEALTH_ROCK); SWITCH(player, 1); SEND_OUT(player, 0); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_STEALTH_ROCK, opponent); + ANIMATION(ANIM_TYPE_MOVE, MOVE_TOXIC_SPIKES, opponent); + ANIMATION(ANIM_TYPE_MOVE, MOVE_STICKY_WEB, opponent); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SPIKES, opponent); + MESSAGE("Pointed stones dug into Grimer!"); + MESSAGE("Grimer fainted!"); + MESSAGE("The poison spikes disappeared from the ground around your team!"); + NONE_OF { + MESSAGE("Grimer was caught in a sticky web!"); + MESSAGE("Grimer was hurt by the spikes!"); + } + } THEN { + EXPECT_EQ(gBattleStruct->hazardsQueue[0][0], HAZARDS_STEALTH_ROCK); + EXPECT_EQ(gBattleStruct->hazardsQueue[0][1], HAZARDS_STICKY_WEB); + EXPECT_EQ(gBattleStruct->hazardsQueue[0][2], HAZARDS_SPIKES); + EXPECT_EQ(gBattleStruct->hazardsQueue[0][3], HAZARDS_NONE); + EXPECT_EQ(gBattleStruct->hazardsQueue[0][4], HAZARDS_NONE); + EXPECT_EQ(gBattleStruct->hazardsQueue[0][5], HAZARDS_NONE); + } +} + +SINGLE_BATTLE_TEST("Hazards can trigger Emergency Exit and other hazards don't activate") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_GOLISOPOD) { HP(105); MaxHP(200); Ability(ABILITY_EMERGENCY_EXIT); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_STEALTH_ROCK); } + TURN { MOVE(opponent, MOVE_TOXIC_SPIKES); } + TURN { MOVE(opponent, MOVE_STICKY_WEB); } + TURN { MOVE(opponent, MOVE_SPIKES); } + TURN { MOVE(opponent, MOVE_STEALTH_ROCK); SWITCH(player, 1); SEND_OUT(player, 0); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_STEALTH_ROCK, opponent); + ANIMATION(ANIM_TYPE_MOVE, MOVE_TOXIC_SPIKES, opponent); + ANIMATION(ANIM_TYPE_MOVE, MOVE_STICKY_WEB, opponent); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SPIKES, opponent); + MESSAGE("Pointed stones dug into Golisopod!"); + ABILITY_POPUP(player, ABILITY_EMERGENCY_EXIT); + NONE_OF { + MESSAGE("Golisopod was poisoned!"); + MESSAGE("Golisopod was caught in a sticky web!"); + MESSAGE("Golisopod was hurt by the spikes!"); + } + MESSAGE("Pointed stones dug into Wobbuffet!"); + MESSAGE("Wobbuffet was poisoned!"); + MESSAGE("Wobbuffet was caught in a sticky web!"); + MESSAGE("Wobbuffet was hurt by the spikes!"); + NOT MESSAGE("Pointed stones dug into Wobbuffet!"); // Because the previous switch in effects instruction is still kept + } +} + +DOUBLE_BATTLE_TEST("Hazards can trigger Emergency Exit and hazards still activate for other battlers") +{ + GIVEN { + ASSUME(GetMoveEffect(MOVE_FINAL_GAMBIT) == EFFECT_FINAL_GAMBIT); + PLAYER(SPECIES_WOBBUFFET) { HP(1); } + PLAYER(SPECIES_WOBBUFFET) { HP(1); } + PLAYER(SPECIES_GOLISOPOD) { HP(105); MaxHP(200); Ability(ABILITY_EMERGENCY_EXIT); } + PLAYER(SPECIES_WYNAUT); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WYNAUT); + } WHEN { + TURN { MOVE(opponentLeft, MOVE_STEALTH_ROCK); MOVE(opponentRight, MOVE_TOXIC_SPIKES); } + TURN { MOVE(opponentLeft, MOVE_STICKY_WEB); MOVE(opponentRight, MOVE_SPIKES); } + TURN { MOVE(playerLeft, MOVE_FINAL_GAMBIT, target: opponentRight); + MOVE(playerRight, MOVE_FINAL_GAMBIT, target: opponentRight); + SEND_OUT(playerLeft, 2); + SEND_OUT(playerRight, 3); + SEND_OUT(playerLeft, 4); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_STEALTH_ROCK, opponentLeft); + ANIMATION(ANIM_TYPE_MOVE, MOVE_TOXIC_SPIKES, opponentRight); + ANIMATION(ANIM_TYPE_MOVE, MOVE_STICKY_WEB, opponentLeft); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SPIKES, opponentRight); + MESSAGE("Pointed stones dug into Golisopod!"); + ABILITY_POPUP(playerLeft, ABILITY_EMERGENCY_EXIT); + NONE_OF { + MESSAGE("Golisopod was poisoned!"); + MESSAGE("Golisopod was caught in a sticky web!"); + MESSAGE("Golisopod was hurt by the spikes!"); + } + MESSAGE("Pointed stones dug into Wobbuffet!"); + MESSAGE("Wobbuffet was poisoned!"); + MESSAGE("Wobbuffet was caught in a sticky web!"); + MESSAGE("Wobbuffet was hurt by the spikes!"); + MESSAGE("Pointed stones dug into Wynaut!"); + MESSAGE("Wynaut was poisoned!"); + MESSAGE("Wynaut was caught in a sticky web!"); + MESSAGE("Wynaut was hurt by the spikes!"); + } +} diff --git a/test/battle/hold_effect/absorb_bulb.c b/test/battle/hold_effect/absorb_bulb.c new file mode 100644 index 0000000000..63daaae02e --- /dev/null +++ b/test/battle/hold_effect/absorb_bulb.c @@ -0,0 +1,4 @@ +#include "global.h" +#include "test/battle.h" + +TO_DO_BATTLE_TEST("TODO: Write Absorb Bulb (Hold Effect) test titles") diff --git a/test/battle/hold_effect/adamant_orb.c b/test/battle/hold_effect/adamant_orb.c new file mode 100644 index 0000000000..3120e54335 --- /dev/null +++ b/test/battle/hold_effect/adamant_orb.c @@ -0,0 +1,4 @@ +#include "global.h" +#include "test/battle.h" + +TO_DO_BATTLE_TEST("TODO: Write Adamant Orb (Hold Effect) test titles") diff --git a/test/battle/hold_effect/adrenaline_orb.c b/test/battle/hold_effect/adrenaline_orb.c new file mode 100644 index 0000000000..595539203e --- /dev/null +++ b/test/battle/hold_effect/adrenaline_orb.c @@ -0,0 +1,4 @@ +#include "global.h" +#include "test/battle.h" + +TO_DO_BATTLE_TEST("TODO: Write Adrenaline Orb (Hold Effect) test titles") diff --git a/test/battle/hold_effect/assault_vest.c b/test/battle/hold_effect/assault_vest.c new file mode 100644 index 0000000000..815a9fddcf --- /dev/null +++ b/test/battle/hold_effect/assault_vest.c @@ -0,0 +1,4 @@ +#include "global.h" +#include "test/battle.h" + +TO_DO_BATTLE_TEST("TODO: Write Assault Vest (Hold Effect) test titles") diff --git a/test/battle/hold_effect/berserk_gene.c b/test/battle/hold_effect/berserk_gene.c index 5331f57849..c7b9ba0933 100644 --- a/test/battle/hold_effect/berserk_gene.c +++ b/test/battle/hold_effect/berserk_gene.c @@ -252,3 +252,54 @@ SINGLE_BATTLE_TEST("Berserk Gene does not cause an infinite loop") MESSAGE("Using Berserk Gene, the Attack of the opposing Wobbuffet sharply rose!"); } } + +SINGLE_BATTLE_TEST("Berserker Gene confusion can be healed with bag items") +{ + u16 item; + PARAMETRIZE { item = ITEM_FULL_HEAL; } + PARAMETRIZE { item = ITEM_HEAL_POWDER; } + PARAMETRIZE { item = ITEM_PEWTER_CRUNCHIES; } + PARAMETRIZE { item = ITEM_LAVA_COOKIE; } + PARAMETRIZE { item = ITEM_RAGE_CANDY_BAR; } + PARAMETRIZE { item = ITEM_OLD_GATEAU; } + PARAMETRIZE { item = ITEM_CASTELIACONE; } + PARAMETRIZE { item = ITEM_LUMIOSE_GALETTE; } + PARAMETRIZE { item = ITEM_SHALOUR_SABLE; } + PARAMETRIZE { item = ITEM_BIG_MALASADA; } + PARAMETRIZE { item = ITEM_JUBILIFE_MUFFIN; } + GIVEN { + ASSUME(gItemsInfo[item].battleUsage == EFFECT_ITEM_CURE_STATUS); + PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_BERSERK_GENE);}; + OPPONENT(SPECIES_GENGAR); + } WHEN { + TURN { USE_ITEM(player, item, partyIndex: 0); } + } SCENE { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_CONFUSION, player); + MESSAGE("Wobbuffet had its status healed!"); + } THEN { + EXPECT(player->volatiles.infiniteConfusion == 0); + } +} + +SINGLE_BATTLE_TEST("Berserker Gene confusion can be healed with used held items") +{ + u16 item; + PARAMETRIZE { item = ITEM_PERSIM_BERRY; } + PARAMETRIZE { item = ITEM_LUM_BERRY; } + + GIVEN { + ASSUME(gItemsInfo[ITEM_PERSIM_BERRY].holdEffect == HOLD_EFFECT_CURE_CONFUSION); + PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_BERSERK_GENE);}; + OPPONENT(SPECIES_WOBBUFFET) { Item(item);}; + } WHEN { + TURN { MOVE(player, MOVE_COVET, WITH_RNG(RNG_CONFUSION, FALSE)); } + TURN {} + } SCENE { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_CONFUSION, player); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player); + } THEN { + EXPECT(player->volatiles.infiniteConfusion == 0); + } +} diff --git a/test/battle/hold_effect/binding_band.c b/test/battle/hold_effect/binding_band.c new file mode 100644 index 0000000000..315ac7a7af --- /dev/null +++ b/test/battle/hold_effect/binding_band.c @@ -0,0 +1,4 @@ +#include "global.h" +#include "test/battle.h" + +TO_DO_BATTLE_TEST("TODO: Write Binding Band (Hold Effect) test titles") diff --git a/test/battle/hold_effect/black_sludge.c b/test/battle/hold_effect/black_sludge.c new file mode 100644 index 0000000000..9d7d845c58 --- /dev/null +++ b/test/battle/hold_effect/black_sludge.c @@ -0,0 +1,4 @@ +#include "global.h" +#include "test/battle.h" + +TO_DO_BATTLE_TEST("TODO: Write Black Sludge (Hold Effect) test titles") diff --git a/test/battle/hold_effect/booster_energy.c b/test/battle/hold_effect/booster_energy.c index a5113ef245..f98675a1e9 100644 --- a/test/battle/hold_effect/booster_energy.c +++ b/test/battle/hold_effect/booster_energy.c @@ -38,7 +38,7 @@ SINGLE_BATTLE_TEST("Booster Energy will activate Quark Drive after Electric Terr SINGLE_BATTLE_TEST("Booster Energy will activate Protosynthesis after harsh sunlight ends") { GIVEN { - WITH_CONFIG(GEN_CONFIG_ABILITY_WEATHER, GEN_6); + WITH_CONFIG(CONFIG_ABILITY_WEATHER, GEN_6); PLAYER(SPECIES_RAGING_BOLT) { Attack(100); Defense(100); Speed(100); SpAttack(110); SpDefense(100); Ability(ABILITY_PROTOSYNTHESIS); Item(ITEM_BOOSTER_ENERGY); } OPPONENT(SPECIES_TORKOAL) { Speed(100); Ability(ABILITY_DROUGHT); }; } WHEN { @@ -65,6 +65,29 @@ SINGLE_BATTLE_TEST("Booster Energy will activate Protosynthesis after harsh sunl } } +SINGLE_BATTLE_TEST("Booster Energy's Protosynthesis boost is preserved when weather changes") +{ + GIVEN { + PLAYER(SPECIES_RAGING_BOLT) { Attack(110); Defense(100); Speed(100); SpAttack(100); SpDefense(100); Ability(ABILITY_PROTOSYNTHESIS); Item(ITEM_BOOSTER_ENERGY); } + OPPONENT(SPECIES_WOBBUFFET) { Speed(50); Moves(MOVE_SUNNY_DAY, MOVE_CELEBRATE); } + } WHEN { + TURN { MOVE(opponent, MOVE_SUNNY_DAY); } + TURN { } + TURN { } + TURN { } + TURN { } + TURN { } + } SCENE { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player); + MESSAGE("Raging Bolt used its Booster Energy to activate Protosynthesis!"); + MESSAGE("Raging Bolt's Attack was heightened!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SUNNY_DAY, opponent); + MESSAGE("The sunlight faded."); + } THEN { + EXPECT(gDisableStructs[B_POSITION_PLAYER_LEFT].paradoxBoostedStat == STAT_ATK); + } +} + SINGLE_BATTLE_TEST("Booster Energy activates Protosynthesis and increases highest stat") { u32 attack, defense, speed, spAttack, spDefense; @@ -131,10 +154,33 @@ SINGLE_BATTLE_TEST("Booster Energy activates Quark Drive and increases highest s } } +SINGLE_BATTLE_TEST("Booster Energy's Quark Drive boost is preserved when terrain changes") +{ + GIVEN { + PLAYER(SPECIES_IRON_MOTH) { Attack(110); Defense(100); Speed(100); SpAttack(100); SpDefense(100); Ability(ABILITY_QUARK_DRIVE); Item(ITEM_BOOSTER_ENERGY); Moves(MOVE_CELEBRATE); } + OPPONENT(SPECIES_WOBBUFFET) { Speed(50); Moves(MOVE_GRASSY_TERRAIN, MOVE_CELEBRATE); } + } WHEN { + TURN { MOVE(opponent, MOVE_GRASSY_TERRAIN); } + TURN { } + TURN { } + TURN { } + TURN { } + TURN { } + } SCENE { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player); + MESSAGE("Iron Moth used its Booster Energy to activate Quark Drive!"); + MESSAGE("Iron Moth's Attack was heightened!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_GRASSY_TERRAIN, opponent); + MESSAGE("The grass disappeared from the battlefield."); + } THEN { + EXPECT(gDisableStructs[B_POSITION_PLAYER_LEFT].paradoxBoostedStat == STAT_ATK); + } +} + SINGLE_BATTLE_TEST("Booster Energy increases special attack by 30% if it is the highest stat", s16 damage) { u32 species; - u32 ability; + enum Ability ability; u32 item; PARAMETRIZE { species = SPECIES_RAGING_BOLT; ability = ABILITY_PROTOSYNTHESIS; item = ITEM_NONE; } @@ -160,7 +206,7 @@ SINGLE_BATTLE_TEST("Booster Energy increases special attack by 30% if it is the SINGLE_BATTLE_TEST("Booster Energy increases special defense by 30% if it is the highest stat", s16 damage) { u32 species; - u32 ability; + enum Ability ability; u32 item; PARAMETRIZE { species = SPECIES_RAGING_BOLT; ability = ABILITY_PROTOSYNTHESIS; item = ITEM_NONE; } diff --git a/test/battle/hold_effect/can_always_run.c b/test/battle/hold_effect/can_always_run.c new file mode 100644 index 0000000000..cb5fa5cfb5 --- /dev/null +++ b/test/battle/hold_effect/can_always_run.c @@ -0,0 +1,4 @@ +#include "global.h" +#include "test/battle.h" + +TO_DO_BATTLE_TEST("TODO: Write Smoke Ball (Hold Effect) test titles") diff --git a/test/battle/hold_effect/cell_battery.c b/test/battle/hold_effect/cell_battery.c new file mode 100644 index 0000000000..ed17597a1f --- /dev/null +++ b/test/battle/hold_effect/cell_battery.c @@ -0,0 +1,4 @@ +#include "global.h" +#include "test/battle.h" + +TO_DO_BATTLE_TEST("TODO: Write Cell Battery (Hold Effect) test titles") diff --git a/test/battle/hold_effect/choice_band.c b/test/battle/hold_effect/choice_band.c new file mode 100644 index 0000000000..f082befaf6 --- /dev/null +++ b/test/battle/hold_effect/choice_band.c @@ -0,0 +1,4 @@ +#include "global.h" +#include "test/battle.h" + +TO_DO_BATTLE_TEST("TODO: Write Choice Band (Hold Effect) test titles") diff --git a/test/battle/hold_effect/choice_scarf.c b/test/battle/hold_effect/choice_scarf.c new file mode 100644 index 0000000000..7eff5a8e0a --- /dev/null +++ b/test/battle/hold_effect/choice_scarf.c @@ -0,0 +1,4 @@ +#include "global.h" +#include "test/battle.h" + +TO_DO_BATTLE_TEST("TODO: Write Choice Scarf (Hold Effect) test titles") diff --git a/test/battle/hold_effect/choice_specs.c b/test/battle/hold_effect/choice_specs.c new file mode 100644 index 0000000000..7eff5a8e0a --- /dev/null +++ b/test/battle/hold_effect/choice_specs.c @@ -0,0 +1,4 @@ +#include "global.h" +#include "test/battle.h" + +TO_DO_BATTLE_TEST("TODO: Write Choice Scarf (Hold Effect) test titles") diff --git a/test/battle/hold_effect/confuse_bitter.c b/test/battle/hold_effect/confuse_bitter.c new file mode 100644 index 0000000000..f2faae1ec7 --- /dev/null +++ b/test/battle/hold_effect/confuse_bitter.c @@ -0,0 +1,4 @@ +#include "global.h" +#include "test/battle.h" + +TO_DO_BATTLE_TEST("TODO: Write Aguav Berry (Hold Effect) test titles") diff --git a/test/battle/hold_effect/confuse_dry.c b/test/battle/hold_effect/confuse_dry.c new file mode 100644 index 0000000000..bbd462f6b6 --- /dev/null +++ b/test/battle/hold_effect/confuse_dry.c @@ -0,0 +1,4 @@ +#include "global.h" +#include "test/battle.h" + +TO_DO_BATTLE_TEST("TODO: Write Wiki Berry (Hold Effect) test titles") diff --git a/test/battle/hold_effect/confuse_sour.c b/test/battle/hold_effect/confuse_sour.c new file mode 100644 index 0000000000..0d87fab14e --- /dev/null +++ b/test/battle/hold_effect/confuse_sour.c @@ -0,0 +1,4 @@ +#include "global.h" +#include "test/battle.h" + +TO_DO_BATTLE_TEST("TODO: Write Iapapa Berry (Hold Effect) test titles") diff --git a/test/battle/hold_effect/confuse_spicy.c b/test/battle/hold_effect/confuse_spicy.c new file mode 100644 index 0000000000..5270023478 --- /dev/null +++ b/test/battle/hold_effect/confuse_spicy.c @@ -0,0 +1,4 @@ +#include "global.h" +#include "test/battle.h" + +TO_DO_BATTLE_TEST("TODO: Write Figy Berry (Hold Effect) test titles") diff --git a/test/battle/hold_effect/confuse_sweet.c b/test/battle/hold_effect/confuse_sweet.c new file mode 100644 index 0000000000..46907373c1 --- /dev/null +++ b/test/battle/hold_effect/confuse_sweet.c @@ -0,0 +1,4 @@ +#include "global.h" +#include "test/battle.h" + +TO_DO_BATTLE_TEST("TODO: Write Mago Berry (Hold Effect) test titles") diff --git a/test/battle/hold_effect/critical_hit_up.c b/test/battle/hold_effect/critical_hit_up.c deleted file mode 100644 index 770505115b..0000000000 --- a/test/battle/hold_effect/critical_hit_up.c +++ /dev/null @@ -1,73 +0,0 @@ -#include "global.h" -#include "test/battle.h" - -ASSUMPTIONS -{ - ASSUME(gItemsInfo[ITEM_LANSAT_BERRY].holdEffect == HOLD_EFFECT_CRITICAL_UP); - ASSUME(GetMoveEffect(MOVE_DRAGON_RAGE) == EFFECT_FIXED_HP_DAMAGE); - ASSUME(GetMoveFixedHPDamage(MOVE_DRAGON_RAGE) == 40); -} - -SINGLE_BATTLE_TEST("Lansat Berry raises the holder's critical-hit-ratio by two stages when HP drops to 1/4 or below") -{ - u32 move; - - PARAMETRIZE { move = MOVE_SCRATCH; } - PARAMETRIZE { move = MOVE_DRAGON_RAGE; } - - GIVEN { - PLAYER(SPECIES_WOBBUFFET) { MaxHP(160); HP(80); Item(ITEM_LANSAT_BERRY); } - OPPONENT(SPECIES_WOBBUFFET); - } WHEN { - TURN { MOVE(opponent, move); } - } SCENE { - ANIMATION(ANIM_TYPE_MOVE, move, opponent); - if (move == MOVE_SCRATCH) { - NONE_OF { - ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player); - MESSAGE("Wobbuffet used the Lansat Berry to get pumped!"); - } - } else { - ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player); - MESSAGE("Wobbuffet used the Lansat Berry to get pumped!"); - } - } -} - -SINGLE_BATTLE_TEST("Lansat Berry raises the holder's critical-hit-ratio by two stages when HP drops to 1/2 or below") -{ - GIVEN { - PLAYER(SPECIES_BELLSPROUT) { MaxHP(80); HP(80); Ability(ABILITY_GLUTTONY); Item(ITEM_LANSAT_BERRY); } - OPPONENT(SPECIES_WOBBUFFET); - } WHEN { - TURN { MOVE(opponent, MOVE_DRAGON_RAGE); } - } SCENE { - ANIMATION(ANIM_TYPE_MOVE, MOVE_DRAGON_RAGE, opponent); - ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player); - MESSAGE("Bellsprout used the Lansat Berry to get pumped!"); - } -} - -SINGLE_BATTLE_TEST("Lansat Berry raises the holder's critical-hit-ratio by 2 stages") -{ - u32 genConfig = 0, chance; - for (u32 j = GEN_1; j <= GEN_5; j++) - PARAMETRIZE { genConfig = j; chance = 4; } // 25% - for (u32 j = GEN_6; j <= GEN_9; j++) - PARAMETRIZE { genConfig = j; chance = 2; } // 50% - PASSES_RANDOMLY(1, chance, RNG_CRITICAL_HIT); - GIVEN { - WITH_CONFIG(GEN_CONFIG_CRIT_CHANCE, genConfig); - ASSUME(GetMoveCriticalHitStage(MOVE_SCRATCH) == 0); - PLAYER(SPECIES_WOBBUFFET) { MaxHP(160); HP(80); Item(ITEM_LANSAT_BERRY); } - OPPONENT(SPECIES_WOBBUFFET); - } WHEN { - TURN { MOVE(opponent, MOVE_DRAGON_RAGE); MOVE(player, MOVE_SCRATCH); } - } SCENE { - ANIMATION(ANIM_TYPE_MOVE, MOVE_DRAGON_RAGE, opponent); - ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player); - MESSAGE("Wobbuffet used the Lansat Berry to get pumped!"); - ANIMATION(ANIM_TYPE_MOVE, MOVE_SCRATCH, player); - MESSAGE("A critical hit!"); - } -} diff --git a/test/battle/hold_effect/critical_up.c b/test/battle/hold_effect/critical_up.c new file mode 100644 index 0000000000..163d8f1c27 --- /dev/null +++ b/test/battle/hold_effect/critical_up.c @@ -0,0 +1,73 @@ +#include "global.h" +#include "test/battle.h" + +ASSUMPTIONS +{ + ASSUME(gItemsInfo[ITEM_LANSAT_BERRY].holdEffect == HOLD_EFFECT_CRITICAL_UP); + ASSUME(GetMoveEffect(MOVE_DRAGON_RAGE) == EFFECT_FIXED_HP_DAMAGE); + ASSUME(GetMoveFixedHPDamage(MOVE_DRAGON_RAGE) == 40); +} + +SINGLE_BATTLE_TEST("Lansat Berry raises the holder's critical-hit-ratio by two stages when HP drops to 1/4 or below") +{ + u32 move; + + PARAMETRIZE { move = MOVE_SCRATCH; } + PARAMETRIZE { move = MOVE_DRAGON_RAGE; } + + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { MaxHP(160); HP(80); Item(ITEM_LANSAT_BERRY); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, move); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, move, opponent); + if (move == MOVE_SCRATCH) { + NONE_OF { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player); + MESSAGE("Wobbuffet used the Lansat Berry to get pumped!"); + } + } else { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player); + MESSAGE("Wobbuffet used the Lansat Berry to get pumped!"); + } + } +} + +SINGLE_BATTLE_TEST("Lansat Berry raises the holder's critical-hit-ratio by two stages when HP drops to 1/2 or below") +{ + GIVEN { + PLAYER(SPECIES_BELLSPROUT) { MaxHP(80); HP(80); Ability(ABILITY_GLUTTONY); Item(ITEM_LANSAT_BERRY); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_DRAGON_RAGE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_DRAGON_RAGE, opponent); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player); + MESSAGE("Bellsprout used the Lansat Berry to get pumped!"); + } +} + +SINGLE_BATTLE_TEST("Lansat Berry raises the holder's critical-hit-ratio by 2 stages") +{ + u32 genConfig = 0, chance; + for (u32 j = GEN_1; j <= GEN_5; j++) + PARAMETRIZE { genConfig = j; chance = 4; } // 25% + for (u32 j = GEN_6; j <= GEN_9; j++) + PARAMETRIZE { genConfig = j; chance = 2; } // 50% + PASSES_RANDOMLY(1, chance, RNG_CRITICAL_HIT); + GIVEN { + WITH_CONFIG(CONFIG_CRIT_CHANCE, genConfig); + ASSUME(GetMoveCriticalHitStage(MOVE_SCRATCH) == 0); + PLAYER(SPECIES_WOBBUFFET) { MaxHP(160); HP(80); Item(ITEM_LANSAT_BERRY); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_DRAGON_RAGE); MOVE(player, MOVE_SCRATCH); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_DRAGON_RAGE, opponent); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player); + MESSAGE("Wobbuffet used the Lansat Berry to get pumped!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SCRATCH, player); + MESSAGE("A critical hit!"); + } +} diff --git a/test/battle/hold_effect/cure_brn.c b/test/battle/hold_effect/cure_brn.c new file mode 100644 index 0000000000..5c5971a759 --- /dev/null +++ b/test/battle/hold_effect/cure_brn.c @@ -0,0 +1,4 @@ +#include "global.h" +#include "test/battle.h" + + // Tests for Rawst Berry are handled in test/battle/hold_effect/cure_status.c diff --git a/test/battle/hold_effect/cure_confusion.c b/test/battle/hold_effect/cure_confusion.c new file mode 100644 index 0000000000..297d01113c --- /dev/null +++ b/test/battle/hold_effect/cure_confusion.c @@ -0,0 +1,4 @@ +#include "global.h" +#include "test/battle.h" + + // Tests for Persim Berry are handled in test/battle/hold_effect/cure_status.c diff --git a/test/battle/hold_effect/cure_frz.c b/test/battle/hold_effect/cure_frz.c new file mode 100644 index 0000000000..b70b0dd925 --- /dev/null +++ b/test/battle/hold_effect/cure_frz.c @@ -0,0 +1,4 @@ +#include "global.h" +#include "test/battle.h" + + // Tests for Aspear Berry are handled in test/battle/hold_effect/cure_status.c diff --git a/test/battle/hold_effect/cure_par.c b/test/battle/hold_effect/cure_par.c new file mode 100644 index 0000000000..07f771f7c9 --- /dev/null +++ b/test/battle/hold_effect/cure_par.c @@ -0,0 +1,4 @@ +#include "global.h" +#include "test/battle.h" + + // Tests for Cheri Berry are handled in test/battle/hold_effect/cure_status.c diff --git a/test/battle/hold_effect/cure_psn.c b/test/battle/hold_effect/cure_psn.c new file mode 100644 index 0000000000..3be395ac8b --- /dev/null +++ b/test/battle/hold_effect/cure_psn.c @@ -0,0 +1,4 @@ +#include "global.h" +#include "test/battle.h" + + // Tests for Pecha Berry are handled in test/battle/hold_effect/cure_status.c diff --git a/test/battle/hold_effect/cure_slp.c b/test/battle/hold_effect/cure_slp.c new file mode 100644 index 0000000000..aeb464c784 --- /dev/null +++ b/test/battle/hold_effect/cure_slp.c @@ -0,0 +1,4 @@ +#include "global.h" +#include "test/battle.h" + + // Tests for Chesto Berry are handled in test/battle/hold_effect/cure_status.c diff --git a/test/battle/hold_effect/cure_status.c b/test/battle/hold_effect/cure_status.c index 0fa0f7ba07..4a5d354a10 100644 --- a/test/battle/hold_effect/cure_status.c +++ b/test/battle/hold_effect/cure_status.c @@ -87,7 +87,7 @@ SINGLE_BATTLE_TEST("Aspear and Lum Berries cure freeze or frostbite") TURN { MOVE(player, MOVE_ICE_PUNCH); } } SCENE { ANIMATION(ANIM_TYPE_MOVE, MOVE_ICE_PUNCH, player); - ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_FRZ, opponent); + ANIMATION(ANIM_TYPE_STATUS, (B_USE_FROSTBITE ? B_ANIM_STATUS_FRB : B_ANIM_STATUS_FRZ), opponent); FREEZE_OR_FROSTBURN_STATUS(opponent, TRUE); ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, opponent); FREEZE_OR_FROSTBURN_STATUS(opponent, FALSE); @@ -293,3 +293,29 @@ DOUBLE_BATTLE_TEST("Lum Berry correctly cures all battlers if multiple fainted t EXPECT_EQ(opponentLeft->status1, STATUS1_NONE); } } + +SINGLE_BATTLE_TEST("Lum Berry properly cures a battler affected by a non-volatiles status and confusion") +{ + u32 status; + PARAMETRIZE { status = STATUS1_BURN;} + PARAMETRIZE { status = STATUS1_FREEZE;} + PARAMETRIZE { status = STATUS1_PARALYSIS;} + PARAMETRIZE { status = STATUS1_POISON;} + PARAMETRIZE { status = STATUS1_TOXIC_POISON;} + PARAMETRIZE { status = STATUS1_SLEEP;} + + GIVEN { + ASSUME(GetMoveEffect(MOVE_CONFUSE_RAY) == EFFECT_CONFUSE); + PLAYER(SPECIES_WOBBUFFET) { Status1(status); Speed(1);}; + OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_LUM_BERRY); Speed(2);}; + } WHEN { + TURN { MOVE(opponent, MOVE_CONFUSE_RAY); MOVE(player, MOVE_CELEBRATE, WITH_RNG(RNG_FROZEN, 0));} + TURN { MOVE(opponent, MOVE_SWITCHEROO);} + } SCENE { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player); + MESSAGE("Wobbuffet's Lum Berry normalized its status!"); + } THEN { + EXPECT_EQ(player->status1, STATUS1_NONE); + EXPECT(player->volatiles.confusionTurns == 0); + } +} diff --git a/test/battle/hold_effect/damp_rock.c b/test/battle/hold_effect/damp_rock.c new file mode 100644 index 0000000000..a41ea6719d --- /dev/null +++ b/test/battle/hold_effect/damp_rock.c @@ -0,0 +1,4 @@ +#include "global.h" +#include "test/battle.h" + +TO_DO_BATTLE_TEST("TODO: Write Damp Rock (Hold Effect) test titles") diff --git a/test/battle/hold_effect/deep_sea_scale.c b/test/battle/hold_effect/deep_sea_scale.c new file mode 100644 index 0000000000..991a7db5c5 --- /dev/null +++ b/test/battle/hold_effect/deep_sea_scale.c @@ -0,0 +1,4 @@ +#include "global.h" +#include "test/battle.h" + +TO_DO_BATTLE_TEST("TODO: Write Deep Sea Scale (Hold Effect) test titles") diff --git a/test/battle/hold_effect/deep_sea_tooth.c b/test/battle/hold_effect/deep_sea_tooth.c new file mode 100644 index 0000000000..54003e7185 --- /dev/null +++ b/test/battle/hold_effect/deep_sea_tooth.c @@ -0,0 +1,4 @@ +#include "global.h" +#include "test/battle.h" + +TO_DO_BATTLE_TEST("TODO: Write Deep Sea Tooth (Hold Effect) test titles") diff --git a/test/battle/hold_effect/destiny_knot.c b/test/battle/hold_effect/destiny_knot.c index b8097c6012..7c0fabff5d 100644 --- a/test/battle/hold_effect/destiny_knot.c +++ b/test/battle/hold_effect/destiny_knot.c @@ -64,3 +64,17 @@ SINGLE_BATTLE_TEST("Destiny Knot procs but fails if the target is oblivious") EXPECT(!player->volatiles.infatuation); } } + +SINGLE_BATTLE_TEST("Destiny Knot procs but fails if the target is already infatuated (cute charm)") +{ + GIVEN { + PLAYER(SPECIES_CLEFAIRY) { Gender(MON_MALE); Ability(ABILITY_CUTE_CHARM);} + OPPONENT(SPECIES_WOBBUFFET) { Gender(MON_FEMALE); Item(ITEM_DESTINY_KNOT); } + } WHEN { + TURN { MOVE(opponent, MOVE_ATTRACT);} + TURN { MOVE(opponent, MOVE_TACKLE);} + } SCENE { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, opponent); + MESSAGE("But it failed!"); + } +} diff --git a/test/battle/hold_effect/double_prize.c b/test/battle/hold_effect/double_prize.c new file mode 100644 index 0000000000..929a9aced3 --- /dev/null +++ b/test/battle/hold_effect/double_prize.c @@ -0,0 +1,4 @@ +#include "global.h" +#include "test/battle.h" + +TO_DO_BATTLE_TEST("TODO: Write Amulet Coin (Hold Effect) test titles") diff --git a/test/battle/hold_effect/drive.c b/test/battle/hold_effect/drive.c new file mode 100644 index 0000000000..e09ec3ba02 --- /dev/null +++ b/test/battle/hold_effect/drive.c @@ -0,0 +1,4 @@ +#include "global.h" +#include "test/battle.h" + +TO_DO_BATTLE_TEST("TODO: Write Douse, Shock, Burn and Chill Drive (Hold Effect) test titles") diff --git a/test/battle/hold_effect/evasion_up.c b/test/battle/hold_effect/evasion_up.c new file mode 100644 index 0000000000..3ed7b66be8 --- /dev/null +++ b/test/battle/hold_effect/evasion_up.c @@ -0,0 +1,4 @@ +#include "global.h" +#include "test/battle.h" + +TO_DO_BATTLE_TEST("TODO: Write Bright Powder (Hold Effect) test titles") diff --git a/test/battle/hold_effect/eviolite.c b/test/battle/hold_effect/eviolite.c new file mode 100644 index 0000000000..1aa0622e43 --- /dev/null +++ b/test/battle/hold_effect/eviolite.c @@ -0,0 +1,4 @@ +#include "global.h" +#include "test/battle.h" + +TO_DO_BATTLE_TEST("TODO: Write Eviolite (Hold Effect) test titles") diff --git a/test/battle/hold_effect/exp_share.c b/test/battle/hold_effect/exp_share.c new file mode 100644 index 0000000000..3f25ef7968 --- /dev/null +++ b/test/battle/hold_effect/exp_share.c @@ -0,0 +1,4 @@ +#include "global.h" +#include "test/battle.h" + +TO_DO_BATTLE_TEST("TODO: Write Exp. Share (Hold Effect) test titles") diff --git a/test/battle/hold_effect/expert_belt.c b/test/battle/hold_effect/expert_belt.c new file mode 100644 index 0000000000..6391046335 --- /dev/null +++ b/test/battle/hold_effect/expert_belt.c @@ -0,0 +1,4 @@ +#include "global.h" +#include "test/battle.h" + +TO_DO_BATTLE_TEST("TODO: Write Expert Belt (Hold Effect) test titles") diff --git a/test/battle/hold_effect/flame_orb.c b/test/battle/hold_effect/flame_orb.c new file mode 100644 index 0000000000..b715ab1a26 --- /dev/null +++ b/test/battle/hold_effect/flame_orb.c @@ -0,0 +1,4 @@ +#include "global.h" +#include "test/battle.h" + +TO_DO_BATTLE_TEST("TODO: Write Flame Orb (Hold Effect) test titles") diff --git a/test/battle/hold_effect/flinch.c b/test/battle/hold_effect/flinch.c new file mode 100644 index 0000000000..9d396391fc --- /dev/null +++ b/test/battle/hold_effect/flinch.c @@ -0,0 +1,36 @@ +#include "global.h" +#include "test/battle.h" + +ASSUMPTIONS +{ + ASSUME(gItemsInfo[ITEM_KINGS_ROCK].holdEffect == HOLD_EFFECT_FLINCH); +} + +SINGLE_BATTLE_TEST("Kings Rock holder will flinch the target 10% of the time") +{ + PASSES_RANDOMLY(10, 100, RNG_HOLD_EFFECT_FLINCH); + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_KINGS_ROCK); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_SCRATCH); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SCRATCH, player); + MESSAGE("The opposing Wobbuffet flinched and couldn't move!"); + } +} + +SINGLE_BATTLE_TEST("Kings Rock does not increase flinch chance of a move that has the flinch effect") +{ + PASSES_RANDOMLY(30, 100, RNG_SECONDARY_EFFECT); + GIVEN { + ASSUME(MoveHasAdditionalEffect(MOVE_HEADBUTT, MOVE_EFFECT_FLINCH)); + PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_KINGS_ROCK); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_HEADBUTT); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_HEADBUTT, player); + MESSAGE("The opposing Wobbuffet flinched and couldn't move!"); + } +} diff --git a/test/battle/hold_effect/float_stone.c b/test/battle/hold_effect/float_stone.c new file mode 100644 index 0000000000..f677c41369 --- /dev/null +++ b/test/battle/hold_effect/float_stone.c @@ -0,0 +1,4 @@ +#include "global.h" +#include "test/battle.h" + +TO_DO_BATTLE_TEST("TODO: Write Float Stone (Hold Effect) test titles") diff --git a/test/battle/hold_effect/focus_band.c b/test/battle/hold_effect/focus_band.c new file mode 100644 index 0000000000..0dddca16b9 --- /dev/null +++ b/test/battle/hold_effect/focus_band.c @@ -0,0 +1,4 @@ +#include "global.h" +#include "test/battle.h" + +TO_DO_BATTLE_TEST("TODO: Write Focus Band (Hold Effect) test titles") diff --git a/test/battle/hold_effect/focus_sash.c b/test/battle/hold_effect/focus_sash.c new file mode 100644 index 0000000000..a66da4ff29 --- /dev/null +++ b/test/battle/hold_effect/focus_sash.c @@ -0,0 +1,4 @@ +#include "global.h" +#include "test/battle.h" + +TO_DO_BATTLE_TEST("TODO: Write Focus Sash (Hold Effect) test titles") diff --git a/test/battle/hold_effect/friendship_up.c b/test/battle/hold_effect/friendship_up.c new file mode 100644 index 0000000000..9eb6408b0d --- /dev/null +++ b/test/battle/hold_effect/friendship_up.c @@ -0,0 +1,4 @@ +#include "global.h" +#include "test/battle.h" + +TO_DO_BATTLE_TEST("TODO: Write Soothe Bell (Hold Effect) test titles") diff --git a/test/battle/hold_effect/grip_claw.c b/test/battle/hold_effect/grip_claw.c new file mode 100644 index 0000000000..b334597bbc --- /dev/null +++ b/test/battle/hold_effect/grip_claw.c @@ -0,0 +1,4 @@ +#include "global.h" +#include "test/battle.h" + +TO_DO_BATTLE_TEST("TODO: Write Grip Claw (Hold Effect) test titles") diff --git a/test/battle/hold_effect/griseous_orb.c b/test/battle/hold_effect/griseous_orb.c new file mode 100644 index 0000000000..f904b5ec68 --- /dev/null +++ b/test/battle/hold_effect/griseous_orb.c @@ -0,0 +1,4 @@ +#include "global.h" +#include "test/battle.h" + +TO_DO_BATTLE_TEST("TODO: Write Griseous Orb (Hold Effect) test titles") diff --git a/test/battle/hold_effect/heat_rock.c b/test/battle/hold_effect/heat_rock.c new file mode 100644 index 0000000000..f297a89c8c --- /dev/null +++ b/test/battle/hold_effect/heat_rock.c @@ -0,0 +1,4 @@ +#include "global.h" +#include "test/battle.h" + +TO_DO_BATTLE_TEST("TODO: Write Heat Rock (Hold Effect) test titles") diff --git a/test/battle/hold_effect/heavy_duty_boots.c b/test/battle/hold_effect/heavy_duty_boots.c new file mode 100644 index 0000000000..060280cbc2 --- /dev/null +++ b/test/battle/hold_effect/heavy_duty_boots.c @@ -0,0 +1,4 @@ +#include "global.h" +#include "test/battle.h" + +TO_DO_BATTLE_TEST("TODO: Write Heavy Duty Boots (Hold Effect) test titles") diff --git a/test/battle/hold_effect/icy_rock.c b/test/battle/hold_effect/icy_rock.c new file mode 100644 index 0000000000..9ad50b807a --- /dev/null +++ b/test/battle/hold_effect/icy_rock.c @@ -0,0 +1,4 @@ +#include "global.h" +#include "test/battle.h" + +TO_DO_BATTLE_TEST("TODO: Write Icy Rock (Hold Effect) test titles") diff --git a/test/battle/hold_effect/kee_berry.c b/test/battle/hold_effect/kee_berry.c index c63da86841..d37a132be4 100644 --- a/test/battle/hold_effect/kee_berry.c +++ b/test/battle/hold_effect/kee_berry.c @@ -89,3 +89,19 @@ DOUBLE_BATTLE_TEST("Kee Berry doesn't trigger if partner was hit") EXPECT(opponentRight->item == ITEM_KEE_BERRY); } } + +SINGLE_BATTLE_TEST("Kee Berry doesn't trigger if the move was boosted by Sheer Force") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_KEE_BERRY); } + OPPONENT(SPECIES_NIDOKING) { Ability(ABILITY_SHEER_FORCE); } + } WHEN { + TURN { MOVE(opponent, MOVE_EMBER); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_EMBER, opponent); + HP_BAR(player); + NOT ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player); + } THEN { + EXPECT_EQ(player->statStages[STAT_DEF], DEFAULT_STAT_STAGE); + } +} \ No newline at end of file diff --git a/test/battle/hold_effect/leek.c b/test/battle/hold_effect/leek.c index 1775681d5f..025686485c 100644 --- a/test/battle/hold_effect/leek.c +++ b/test/battle/hold_effect/leek.c @@ -20,7 +20,7 @@ SINGLE_BATTLE_TEST("Leek increases critical hit ratio by 2 stages for the Farfet } PASSES_RANDOMLY(passes, trials, RNG_CRITICAL_HIT); GIVEN { - WITH_CONFIG(GEN_CONFIG_CRIT_CHANCE, genConfig); + WITH_CONFIG(CONFIG_CRIT_CHANCE, genConfig); ASSUME(GetSpeciesBaseSpeed(SPECIES_FARFETCHD) == 60); ASSUME(GetSpeciesBaseSpeed(SPECIES_FARFETCHD_GALAR) == 55); ASSUME(GetSpeciesBaseSpeed(SPECIES_SIRFETCHD) == 65); diff --git a/test/battle/hold_effect/life_orb.c b/test/battle/hold_effect/life_orb.c index e983537b83..7d99449bcb 100644 --- a/test/battle/hold_effect/life_orb.c +++ b/test/battle/hold_effect/life_orb.c @@ -1,6 +1,11 @@ #include "global.h" #include "test/battle.h" +ASSUMPTIONS +{ + ASSUME(gItemsInfo[ITEM_LIFE_ORB].holdEffect == HOLD_EFFECT_LIFE_ORB); +} + SINGLE_BATTLE_TEST("Life Orb activates when users attack is succesful") { GIVEN { diff --git a/test/battle/hold_effect/light_ball.c b/test/battle/hold_effect/light_ball.c new file mode 100644 index 0000000000..8c0d507b45 --- /dev/null +++ b/test/battle/hold_effect/light_ball.c @@ -0,0 +1,4 @@ +#include "global.h" +#include "test/battle.h" + +TO_DO_BATTLE_TEST("TODO: Write Light Ball (Hold Effect) test titles") diff --git a/test/battle/hold_effect/light_clay.c b/test/battle/hold_effect/light_clay.c new file mode 100644 index 0000000000..cb258ef885 --- /dev/null +++ b/test/battle/hold_effect/light_clay.c @@ -0,0 +1,4 @@ +#include "global.h" +#include "test/battle.h" + +TO_DO_BATTLE_TEST("TODO: Write Light Clay (Hold Effect) test titles") diff --git a/test/battle/hold_effect/loaded_dice.c b/test/battle/hold_effect/loaded_dice.c new file mode 100644 index 0000000000..f5c220818a --- /dev/null +++ b/test/battle/hold_effect/loaded_dice.c @@ -0,0 +1,4 @@ +#include "global.h" +#include "test/battle.h" + +TO_DO_BATTLE_TEST("TODO: Write Loaded Dice (Hold Effect) test titles") diff --git a/test/battle/hold_effect/luck_punch.c b/test/battle/hold_effect/luck_punch.c deleted file mode 100644 index 0bdae8134c..0000000000 --- a/test/battle/hold_effect/luck_punch.c +++ /dev/null @@ -1,25 +0,0 @@ -#include "global.h" -#include "test/battle.h" - -SINGLE_BATTLE_TEST("Lucky Punch increases critical hit ratio by 2 stages for Chansey") -{ - u32 genConfig, passes, trials; - PARAMETRIZE { genConfig = GEN_1; passes = 25; trials = 32; } // ~78.1% with Chansey's base speed - for (u32 j = GEN_2; j <= GEN_5; j++) - PARAMETRIZE { genConfig = j; passes = 1; trials = 4; } // 25% - for (u32 j = GEN_6; j <= GEN_9; j++) - PARAMETRIZE { genConfig = j; passes = 1; trials = 2; } // 50% - PASSES_RANDOMLY(passes, trials, RNG_CRITICAL_HIT); - GIVEN { - WITH_CONFIG(GEN_CONFIG_CRIT_CHANCE, genConfig); - ASSUME(gItemsInfo[ITEM_LUCKY_PUNCH].holdEffect == HOLD_EFFECT_LUCKY_PUNCH); - ASSUME(GetSpeciesBaseSpeed(SPECIES_CHANSEY) == 50); - PLAYER(SPECIES_WOBBUFFET); - OPPONENT(SPECIES_CHANSEY) { Item(ITEM_LUCKY_PUNCH); } - } WHEN { - TURN { MOVE(opponent, MOVE_SCRATCH); } - } SCENE { - ANIMATION(ANIM_TYPE_MOVE, MOVE_SCRATCH, opponent); - MESSAGE("A critical hit!"); - } -} diff --git a/test/battle/hold_effect/lucky_egg.c b/test/battle/hold_effect/lucky_egg.c new file mode 100644 index 0000000000..3016adeb43 --- /dev/null +++ b/test/battle/hold_effect/lucky_egg.c @@ -0,0 +1,4 @@ +#include "global.h" +#include "test/battle.h" + +TO_DO_BATTLE_TEST("TODO: Write Lucky Egg (Hold Effect) test titles") diff --git a/test/battle/hold_effect/lucky_punch.c b/test/battle/hold_effect/lucky_punch.c new file mode 100644 index 0000000000..bbc379d977 --- /dev/null +++ b/test/battle/hold_effect/lucky_punch.c @@ -0,0 +1,25 @@ +#include "global.h" +#include "test/battle.h" + +SINGLE_BATTLE_TEST("Lucky Punch increases critical hit ratio by 2 stages for Chansey") +{ + u32 genConfig, passes, trials; + PARAMETRIZE { genConfig = GEN_1; passes = 25; trials = 32; } // ~78.1% with Chansey's base speed + for (u32 j = GEN_2; j <= GEN_5; j++) + PARAMETRIZE { genConfig = j; passes = 1; trials = 4; } // 25% + for (u32 j = GEN_6; j <= GEN_9; j++) + PARAMETRIZE { genConfig = j; passes = 1; trials = 2; } // 50% + PASSES_RANDOMLY(passes, trials, RNG_CRITICAL_HIT); + GIVEN { + WITH_CONFIG(CONFIG_CRIT_CHANCE, genConfig); + ASSUME(gItemsInfo[ITEM_LUCKY_PUNCH].holdEffect == HOLD_EFFECT_LUCKY_PUNCH); + ASSUME(GetSpeciesBaseSpeed(SPECIES_CHANSEY) == 50); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_CHANSEY) { Item(ITEM_LUCKY_PUNCH); } + } WHEN { + TURN { MOVE(opponent, MOVE_SCRATCH); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SCRATCH, opponent); + MESSAGE("A critical hit!"); + } +} diff --git a/test/battle/hold_effect/luminous_moss.c b/test/battle/hold_effect/luminous_moss.c new file mode 100644 index 0000000000..c49bf04e03 --- /dev/null +++ b/test/battle/hold_effect/luminous_moss.c @@ -0,0 +1,4 @@ +#include "global.h" +#include "test/battle.h" + +TO_DO_BATTLE_TEST("TODO: Write Luminous Moss (Hold Effect) test titles") diff --git a/test/battle/hold_effect/lustrous_orb.c b/test/battle/hold_effect/lustrous_orb.c new file mode 100644 index 0000000000..e8bcdf3f31 --- /dev/null +++ b/test/battle/hold_effect/lustrous_orb.c @@ -0,0 +1,4 @@ +#include "global.h" +#include "test/battle.h" + +TO_DO_BATTLE_TEST("TODO: Write Lustrous Orb (Hold Effect) test titles") diff --git a/test/battle/hold_effect/macho_brace.c b/test/battle/hold_effect/macho_brace.c new file mode 100644 index 0000000000..2186a41f78 --- /dev/null +++ b/test/battle/hold_effect/macho_brace.c @@ -0,0 +1,4 @@ +#include "global.h" +#include "test/battle.h" + +TO_DO_BATTLE_TEST("TODO: Write Macho Brace (Hold Effect) test titles") diff --git a/test/battle/hold_effect/maranga_berry.c b/test/battle/hold_effect/maranga_berry.c index 22b72ba201..785e040ca4 100644 --- a/test/battle/hold_effect/maranga_berry.c +++ b/test/battle/hold_effect/maranga_berry.c @@ -89,3 +89,19 @@ DOUBLE_BATTLE_TEST("Maranga Berry doesn't trigger if partner was hit") EXPECT(opponentRight->item == ITEM_MARANGA_BERRY); } } + +SINGLE_BATTLE_TEST("Maranga Berry doesn't trigger if the move was boosted by Sheer Force") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_MARANGA_BERRY); } + OPPONENT(SPECIES_NIDOKING) { Ability(ABILITY_SHEER_FORCE); } + } WHEN { + TURN { MOVE(opponent, MOVE_FIRE_PUNCH); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_FIRE_PUNCH, opponent); + HP_BAR(player); + NOT ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player); + } THEN { + EXPECT_EQ(player->statStages[STAT_DEF], DEFAULT_STAT_STAGE); + } +} diff --git a/test/battle/hold_effect/mega_stone.c b/test/battle/hold_effect/mega_stone.c new file mode 100644 index 0000000000..a1100ed8ea --- /dev/null +++ b/test/battle/hold_effect/mega_stone.c @@ -0,0 +1,4 @@ +#include "global.h" +#include "test/battle.h" + +TO_DO_BATTLE_TEST("TODO: Write Mega Stone (Hold Effect) test titles") diff --git a/test/battle/hold_effect/memory.c b/test/battle/hold_effect/memory.c new file mode 100644 index 0000000000..290f534e4a --- /dev/null +++ b/test/battle/hold_effect/memory.c @@ -0,0 +1,4 @@ +#include "global.h" +#include "test/battle.h" + +TO_DO_BATTLE_TEST("TODO: Write Memories (Hold Effect) test titles") diff --git a/test/battle/hold_effect/mental_herb.c b/test/battle/hold_effect/mental_herb.c new file mode 100644 index 0000000000..7eeaba2ff7 --- /dev/null +++ b/test/battle/hold_effect/mental_herb.c @@ -0,0 +1,4 @@ +#include "global.h" +#include "test/battle.h" + +TO_DO_BATTLE_TEST("TODO: Write Mental Herb (Hold Effect) test titles") diff --git a/test/battle/hold_effect/metal_powder.c b/test/battle/hold_effect/metal_powder.c new file mode 100644 index 0000000000..2f716541a2 --- /dev/null +++ b/test/battle/hold_effect/metal_powder.c @@ -0,0 +1,4 @@ +#include "global.h" +#include "test/battle.h" + +TO_DO_BATTLE_TEST("TODO: Write Metal Powder (Hold Effect) test titles") diff --git a/test/battle/hold_effect/muscle_band.c b/test/battle/hold_effect/muscle_band.c new file mode 100644 index 0000000000..7bac7c9c87 --- /dev/null +++ b/test/battle/hold_effect/muscle_band.c @@ -0,0 +1,4 @@ +#include "global.h" +#include "test/battle.h" + +TO_DO_BATTLE_TEST("TODO: Write Muscle Band (Hold Effect) test titles") diff --git a/test/battle/hold_effect/plate.c b/test/battle/hold_effect/plate.c new file mode 100644 index 0000000000..92573659c7 --- /dev/null +++ b/test/battle/hold_effect/plate.c @@ -0,0 +1,4 @@ +#include "global.h" +#include "test/battle.h" + +TO_DO_BATTLE_TEST("TODO: Write Plates (Hold Effect) test titles") diff --git a/test/battle/hold_effect/power_herb.c b/test/battle/hold_effect/power_herb.c new file mode 100644 index 0000000000..c745851781 --- /dev/null +++ b/test/battle/hold_effect/power_herb.c @@ -0,0 +1,4 @@ +#include "global.h" +#include "test/battle.h" + +TO_DO_BATTLE_TEST("TODO: Write Power Herb (Hold Effect) test titles") diff --git a/test/battle/hold_effect/power_item.c b/test/battle/hold_effect/power_item.c new file mode 100644 index 0000000000..240d09a67f --- /dev/null +++ b/test/battle/hold_effect/power_item.c @@ -0,0 +1,4 @@ +#include "global.h" +#include "test/battle.h" + +TO_DO_BATTLE_TEST("TODO: Write Power Items (Hold Effect) test titles") diff --git a/test/battle/hold_effect/prevent_evolve.c b/test/battle/hold_effect/prevent_evolve.c new file mode 100644 index 0000000000..1043454368 --- /dev/null +++ b/test/battle/hold_effect/prevent_evolve.c @@ -0,0 +1,4 @@ +#include "global.h" +#include "test/battle.h" + +TO_DO_BATTLE_TEST("TODO: Write Everstone (Hold Effect) test titles") diff --git a/test/battle/hold_effect/primal_orb.c b/test/battle/hold_effect/primal_orb.c new file mode 100644 index 0000000000..42955a7365 --- /dev/null +++ b/test/battle/hold_effect/primal_orb.c @@ -0,0 +1,4 @@ +#include "global.h" +#include "test/battle.h" + +TO_DO_BATTLE_TEST("TODO: Write Red/Blue Orb (Hold Effect) test titles") diff --git a/test/battle/hold_effect/protective_pads.c b/test/battle/hold_effect/protective_pads.c index e04f30ac9b..6f8d068d06 100644 --- a/test/battle/hold_effect/protective_pads.c +++ b/test/battle/hold_effect/protective_pads.c @@ -9,7 +9,7 @@ ASSUMPTIONS SINGLE_BATTLE_TEST("Protective Pads protected moves still make direct contact", s16 damage) { - u32 ability; + enum Ability ability; PARAMETRIZE { ability = ABILITY_KLUTZ; } PARAMETRIZE { ability = ABILITY_FLUFFY; } GIVEN { diff --git a/test/battle/hold_effect/punching_glove.c b/test/battle/hold_effect/punching_glove.c new file mode 100644 index 0000000000..d8e05a9913 --- /dev/null +++ b/test/battle/hold_effect/punching_glove.c @@ -0,0 +1,4 @@ +#include "global.h" +#include "test/battle.h" + +TO_DO_BATTLE_TEST("TODO: Write Punching Glove (Hold Effect) test titles") diff --git a/test/battle/hold_effect/quick_powder.c b/test/battle/hold_effect/quick_powder.c new file mode 100644 index 0000000000..7e29687843 --- /dev/null +++ b/test/battle/hold_effect/quick_powder.c @@ -0,0 +1,4 @@ +#include "global.h" +#include "test/battle.h" + +TO_DO_BATTLE_TEST("TODO: Write Quick Powder (Hold Effect) test titles") diff --git a/test/battle/hold_effect/repel.c b/test/battle/hold_effect/repel.c new file mode 100644 index 0000000000..adfca5c483 --- /dev/null +++ b/test/battle/hold_effect/repel.c @@ -0,0 +1,4 @@ +#include "global.h" +#include "test/battle.h" + +TO_DO_BATTLE_TEST("TODO: Write Cleanse Tag (Hold Effect) test titles") diff --git a/test/battle/hold_effect/resist_berry.c b/test/battle/hold_effect/resist_berry.c new file mode 100644 index 0000000000..b13ca35665 --- /dev/null +++ b/test/battle/hold_effect/resist_berry.c @@ -0,0 +1,145 @@ +#include "global.h" +#include "test/battle.h" + +static const u16 sMoveItemTable[][4] = +{ + { TYPE_NORMAL, MOVE_SCRATCH, ITEM_CHILAN_BERRY, SPECIES_WOBBUFFET }, + { TYPE_FIGHTING, MOVE_KARATE_CHOP, ITEM_CHOPLE_BERRY, SPECIES_RAMPARDOS }, + { TYPE_FLYING, MOVE_WING_ATTACK, ITEM_COBA_BERRY, SPECIES_HARIYAMA }, + { TYPE_POISON, MOVE_POISON_STING, ITEM_KEBIA_BERRY, SPECIES_GOGOAT }, + { TYPE_GROUND, MOVE_MUD_SHOT, ITEM_SHUCA_BERRY, SPECIES_RAMPARDOS }, + { TYPE_ROCK, MOVE_ROCK_THROW, ITEM_CHARTI_BERRY, SPECIES_CORVISQUIRE }, + { TYPE_BUG, MOVE_BUG_BITE, ITEM_TANGA_BERRY, SPECIES_WOBBUFFET }, + { TYPE_GHOST, MOVE_SHADOW_PUNCH, ITEM_KASIB_BERRY, SPECIES_WOBBUFFET }, + { TYPE_STEEL, MOVE_METAL_CLAW, ITEM_BABIRI_BERRY, SPECIES_RAMPARDOS }, + { TYPE_FIRE, MOVE_EMBER, ITEM_OCCA_BERRY, SPECIES_GOGOAT }, + { TYPE_WATER, MOVE_WATER_GUN, ITEM_PASSHO_BERRY, SPECIES_RAMPARDOS }, + { TYPE_GRASS, MOVE_VINE_WHIP, ITEM_RINDO_BERRY, SPECIES_RAMPARDOS }, + { TYPE_ELECTRIC, MOVE_THUNDER_SHOCK, ITEM_WACAN_BERRY, SPECIES_CORVISQUIRE }, + { TYPE_PSYCHIC, MOVE_CONFUSION, ITEM_PAYAPA_BERRY, SPECIES_HARIYAMA }, + { TYPE_ICE, MOVE_AURORA_BEAM, ITEM_YACHE_BERRY, SPECIES_DRAGONAIR }, + { TYPE_DRAGON, MOVE_DRAGON_BREATH, ITEM_HABAN_BERRY, SPECIES_DRAGONAIR }, + { TYPE_DARK, MOVE_BITE, ITEM_COLBUR_BERRY, SPECIES_WOBBUFFET }, + { TYPE_FAIRY, MOVE_DISARMING_VOICE, ITEM_ROSELI_BERRY, SPECIES_DRAGONAIR }, +}; + +SINGLE_BATTLE_TEST("Weakness berries decrease the base power of moves by half", s16 damage) +{ + u32 move = 0, item = 0, defender = 0; + enum Type type = TYPE_NONE; + + for (u32 j = 0; j < ARRAY_COUNT(sMoveItemTable); j++) + { + PARAMETRIZE { type = sMoveItemTable[j][0]; move = sMoveItemTable[j][1]; defender = sMoveItemTable[j][3]; item = ITEM_NONE; } + PARAMETRIZE { type = sMoveItemTable[j][0]; move = sMoveItemTable[j][1]; defender = sMoveItemTable[j][3]; item = sMoveItemTable[j][2]; } + } + + GIVEN { + ASSUME(GetMovePower(move) > 0); + ASSUME(GetMoveType(move) == type); + ASSUME(GetSpeciesType(defender, 0) == GetSpeciesType(defender, 1)); + if (type != TYPE_NORMAL) { + ASSUME(gTypeEffectivenessTable[type][GetSpeciesType(defender, 0)] > UQ_4_12(1.0)); + } + if (item != ITEM_NONE) { + ASSUME(GetItemHoldEffect(item) == HOLD_EFFECT_RESIST_BERRY); + ASSUME(GetItemHoldEffectParam(item) == type); + } + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(defender) { Item(item); } + } WHEN { + TURN { MOVE(player, move); } + } SCENE { + if (1 == i % 2) { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, opponent); + } + HP_BAR(opponent, captureDamage: &results[i].damage); + } FINALLY { + for (u32 j = 0; j < ARRAY_COUNT(sMoveItemTable); j++) { + EXPECT_MUL_EQ(results[j*2].damage, Q_4_12(0.5), results[(j*2)+1].damage); + } + } +} + +SINGLE_BATTLE_TEST("Weakness berries do not activate unless a move is super effective", s16 damage) +{ + u32 move = 0, item = 0, defender = 0; + enum Type type = TYPE_NONE; + + for (u32 j = 0; j < ARRAY_COUNT(sMoveItemTable); j++) + { + if (TYPE_NORMAL == type) + { + // ITEM_CHILAN_BERRY activates without a weakness + } + else if (TYPE_FAIRY == type) + { + PARAMETRIZE { type = sMoveItemTable[j][0]; move = sMoveItemTable[j][1]; item = sMoveItemTable[j][2]; defender = SPECIES_WOBBUFFET; } + } + else + { + PARAMETRIZE { type = sMoveItemTable[j][0]; move = sMoveItemTable[j][1]; item = sMoveItemTable[j][2]; defender = SPECIES_SABLEYE; } + } + } + + GIVEN { + ASSUME(GetMovePower(move) > 0); + ASSUME(uq4_12_multiply(gTypeEffectivenessTable[type][GetSpeciesType(defender, 0)], + gTypeEffectivenessTable[type][GetSpeciesType(defender, 1)]) <= UQ_4_12(1.0)); + ASSUME(GetItemHoldEffect(item) == HOLD_EFFECT_RESIST_BERRY); + ASSUME(GetItemHoldEffectParam(item) == type); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(defender) { Item(item); } + } WHEN { + TURN { MOVE(player, move); } + } SCENE { + NOT ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, opponent); + } +} + +SINGLE_BATTLE_TEST("Weakness berries do not decrease the power of Struggle", s16 damage) +{ + u32 item = 0; + + PARAMETRIZE { item = ITEM_NONE; } + PARAMETRIZE { item = ITEM_CHILAN_BERRY; } + + GIVEN { + if (item != ITEM_NONE) { + ASSUME(GetItemHoldEffect(item) == HOLD_EFFECT_RESIST_BERRY); + ASSUME(GetItemHoldEffectParam(item) == TYPE_NORMAL); + } + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET) { Item(item); } + } WHEN { + TURN { MOVE(player, MOVE_STRUGGLE); } + } SCENE { + NONE_OF { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, opponent); + MESSAGE("The Chilan Berry weakened the damage to the opposing Wobbuffet!"); + } + ANIMATION(ANIM_TYPE_MOVE, MOVE_STRUGGLE, player); + HP_BAR(opponent, captureDamage: &results[i].damage); + } FINALLY { + EXPECT_EQ(results[0].damage, results[1].damage); + } +} + +SINGLE_BATTLE_TEST("Weakness berries do not activate if Disguise blocks the damage") +{ + GIVEN { + ASSUME(GetItemHoldEffect(ITEM_BABIRI_BERRY) == HOLD_EFFECT_RESIST_BERRY); + ASSUME(GetItemHoldEffectParam(ITEM_BABIRI_BERRY) == TYPE_STEEL); + ASSUME(GetMoveType(MOVE_METAL_CLAW) == TYPE_STEEL); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_MIMIKYU) { Item(ITEM_BABIRI_BERRY); Ability(ABILITY_DISGUISE); } + } WHEN { + TURN { MOVE(player, MOVE_METAL_CLAW); } + } SCENE { + NONE_OF { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, opponent); + MESSAGE("The Babiri Berry weakened the damage to the opposing Mimikyu!"); + } + ANIMATION(ANIM_TYPE_MOVE, MOVE_METAL_CLAW, player); + } +} diff --git a/test/battle/hold_effect/restore_hp.c b/test/battle/hold_effect/restore_hp.c index 9db149c023..ef96ead7e4 100644 --- a/test/battle/hold_effect/restore_hp.c +++ b/test/battle/hold_effect/restore_hp.c @@ -63,20 +63,3 @@ DOUBLE_BATTLE_TEST("Restore HP Item effects do not miss timing after a recoil mo ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, playerRight); } } - -#if B_HP_BERRIES <= GEN_3 -SINGLE_BATTLE_TEST("Restore HP Berry triggers only during the end turn") -{ - GIVEN { - PLAYER(SPECIES_WOBBUFFET); - OPPONENT(SPECIES_WYNAUT) { MaxHP(100); HP(51); Item(ITEM_ORAN_BERRY); } - } WHEN { - TURN { MOVE(player, MOVE_TACKLE); } - TURN {} - } SCENE { - ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, player); - ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponent); - ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, opponent); - } -} -#endif diff --git a/test/battle/hold_effect/restore_pct_hp.c b/test/battle/hold_effect/restore_pct_hp.c new file mode 100644 index 0000000000..ac0db59380 --- /dev/null +++ b/test/battle/hold_effect/restore_pct_hp.c @@ -0,0 +1,4 @@ +#include "global.h" +#include "test/battle.h" + + // Tests for Sitrus Berry are handled in test/battle/hold_effect/restore_hp.c diff --git a/test/battle/hold_effect/restore_stats.c b/test/battle/hold_effect/restore_stats.c deleted file mode 100644 index f2508c45ee..0000000000 --- a/test/battle/hold_effect/restore_stats.c +++ /dev/null @@ -1,236 +0,0 @@ -#include "global.h" -#include "test/battle.h" - -ASSUMPTIONS -{ - ASSUME(gItemsInfo[ITEM_WHITE_HERB].holdEffect == HOLD_EFFECT_WHITE_HERB); -} - -SINGLE_BATTLE_TEST("White Herb restores stats when they're lowered") -{ - GIVEN { - ASSUME(GetMoveEffect(MOVE_LEER) == EFFECT_DEFENSE_DOWN); - PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_WHITE_HERB); } - OPPONENT(SPECIES_WOBBUFFET); - } WHEN { - TURN { MOVE(opponent, MOVE_LEER); } - } SCENE { - ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); - ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player); - MESSAGE("Wobbuffet returned its stats to normal using its White Herb!"); - } THEN { - EXPECT(player->item == ITEM_NONE); - EXPECT(player->statStages[STAT_DEF] = DEFAULT_STAT_STAGE); - } -} - -SINGLE_BATTLE_TEST("White Herb restores stats after Attack was lowered by Intimidate in singles") -{ - GIVEN { - PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_WHITE_HERB); } - OPPONENT(SPECIES_ARBOK) { Ability(ABILITY_INTIMIDATE); } - } WHEN { - TURN { ; } - } SCENE { - ABILITY_POPUP(opponent, ABILITY_INTIMIDATE); - ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); - ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player); - MESSAGE("Wobbuffet returned its stats to normal using its White Herb!"); - } THEN { - EXPECT(player->item == ITEM_NONE); - EXPECT(player->statStages[STAT_DEF] = DEFAULT_STAT_STAGE); - } -} - -DOUBLE_BATTLE_TEST("White Herb restores stats after Attack was lowered by Intimidate in doubles") -{ - GIVEN { - OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_WHITE_HERB); } - OPPONENT(SPECIES_WYNAUT) { Item(ITEM_WHITE_HERB); } - PLAYER(SPECIES_ARBOK) { Ability(ABILITY_INTIMIDATE); } - PLAYER(SPECIES_WOBBUFFET); - } WHEN { - TURN { ; } - } SCENE { - ABILITY_POPUP(playerLeft, ABILITY_INTIMIDATE); - - ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponentLeft); - ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, opponentLeft); - MESSAGE("The opposing Wobbuffet returned its stats to normal using its White Herb!"); - - ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponentRight); - ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, opponentRight); - MESSAGE("The opposing Wynaut returned its stats to normal using its White Herb!"); - } THEN { - EXPECT(opponentLeft->item == ITEM_NONE); - EXPECT(opponentLeft->statStages[STAT_DEF] = DEFAULT_STAT_STAGE); - EXPECT(opponentRight->item == ITEM_NONE); - EXPECT(opponentRight->statStages[STAT_DEF] = DEFAULT_STAT_STAGE); - } -} - -SINGLE_BATTLE_TEST("White Herb restores stats after Attack was lowered by Intimidate while switching in") -{ - GIVEN { - PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_WHITE_HERB); } - OPPONENT(SPECIES_WOBBUFFET); - OPPONENT(SPECIES_ARBOK) { Ability(ABILITY_INTIMIDATE); } - } WHEN { - TURN { SWITCH(opponent, 1); MOVE(player, MOVE_CLOSE_COMBAT); } - } SCENE { - ABILITY_POPUP(opponent, ABILITY_INTIMIDATE); - ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); - ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player); - MESSAGE("Wobbuffet returned its stats to normal using its White Herb!"); - ANIMATION(ANIM_TYPE_MOVE, MOVE_CLOSE_COMBAT, player); - NONE_OF { - ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player); - MESSAGE("Wobbuffet returned its stats to normal using its White Herb!"); - } - } THEN { - EXPECT(player->item == ITEM_NONE); - EXPECT(player->statStages[STAT_DEF] = DEFAULT_STAT_STAGE - 1); - EXPECT(player->statStages[STAT_SPDEF] = DEFAULT_STAT_STAGE - 1); - } -} - -SINGLE_BATTLE_TEST("White Herb restores stats after all hits of a multi hit move happened") -{ - u16 species; - u16 ability; - - PARAMETRIZE { species = SPECIES_SLIGGOO_HISUI; ability = ABILITY_GOOEY; } - PARAMETRIZE { species = SPECIES_DUGTRIO_ALOLA; ability = ABILITY_TANGLING_HAIR; } - - GIVEN { - ASSUME(GetMoveStrikeCount(MOVE_DUAL_WINGBEAT) == 2); - PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_WHITE_HERB); } - OPPONENT(species) { Ability(ability); } - } WHEN { - TURN { MOVE(player, MOVE_DUAL_WINGBEAT); } - } SCENE { - ANIMATION(ANIM_TYPE_MOVE, MOVE_DUAL_WINGBEAT, player); - ABILITY_POPUP(opponent, ability); - ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); - MESSAGE("Wobbuffet's Speed fell!"); - ABILITY_POPUP(opponent, ability); - ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); - MESSAGE("Wobbuffet's Speed fell!"); - ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player); - MESSAGE("Wobbuffet returned its stats to normal using its White Herb!"); - } THEN { - EXPECT(player->item == ITEM_NONE); - EXPECT(player->statStages[STAT_SPEED] = DEFAULT_STAT_STAGE); - } -} - -SINGLE_BATTLE_TEST("White Herb wont have time to activate if it is knocked off or stolen by Thief") -{ - u16 move; - - PARAMETRIZE { move = MOVE_THIEF; } - PARAMETRIZE { move = MOVE_KNOCK_OFF; } - - GIVEN { - ASSUME(GetMoveEffect(MOVE_KNOCK_OFF) == EFFECT_KNOCK_OFF); - ASSUME(GetMoveEffect(MOVE_THIEF) == EFFECT_STEAL_ITEM); - PLAYER(SPECIES_SLUGMA) { Ability(ABILITY_WEAK_ARMOR); Item(ITEM_WHITE_HERB); } - OPPONENT(SPECIES_WOBBUFFET); - } WHEN { - TURN { MOVE(opponent, move); } - } SCENE { - ANIMATION(ANIM_TYPE_MOVE, move, opponent); - ABILITY_POPUP(player, ABILITY_WEAK_ARMOR); - ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); - MESSAGE("Slugma's Weak Armor lowered its Defense!"); - MESSAGE("Slugma's Weak Armor raised its Speed!"); - if (move == MOVE_KNOCK_OFF) { - MESSAGE("The opposing Wobbuffet knocked off Slugma's White Herb!"); - } else if (move == MOVE_THIEF) { - MESSAGE("The opposing Wobbuffet stole Slugma's White Herb!"); - } - NONE_OF { - ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player); - MESSAGE("Wobbuffet returned its stats to normal using its White Herb!"); - } - } THEN { - EXPECT(player->statStages[STAT_DEF] = DEFAULT_STAT_STAGE - 1); - EXPECT(player->statStages[STAT_SPEED] = DEFAULT_STAT_STAGE + 1); - } -} - -SINGLE_BATTLE_TEST("White Herb wont have time to activate if Magician steals it") -{ - GIVEN { - PLAYER(SPECIES_SLUGMA) { Ability(ABILITY_WEAK_ARMOR); Item(ITEM_WHITE_HERB); } - OPPONENT(SPECIES_FENNEKIN) { Ability(ABILITY_MAGICIAN); } - } WHEN { - TURN { MOVE(opponent, MOVE_SCRATCH); } - } SCENE { - ANIMATION(ANIM_TYPE_MOVE, MOVE_SCRATCH, opponent); - ABILITY_POPUP(player, ABILITY_WEAK_ARMOR); - ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); - MESSAGE("Slugma's Weak Armor lowered its Defense!"); - MESSAGE("Slugma's Weak Armor raised its Speed!"); - ABILITY_POPUP(opponent, ABILITY_MAGICIAN); - MESSAGE("The opposing Fennekin stole Slugma's White Herb!"); - NONE_OF { - ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player); - MESSAGE("Wobbuffet returned its stats to normal using its White Herb!"); - } - } THEN { - EXPECT(player->statStages[STAT_DEF] = DEFAULT_STAT_STAGE - 1); - EXPECT(player->statStages[STAT_SPEED] = DEFAULT_STAT_STAGE + 1); - } -} - -SINGLE_BATTLE_TEST("White Herb has correct interactions with Intimidate triggered Defiant and Competitive") -{ - u16 species; - u16 ability; - - PARAMETRIZE { species = SPECIES_IGGLYBUFF; ability = ABILITY_COMPETITIVE; } - PARAMETRIZE { species = SPECIES_MANKEY; ability = ABILITY_DEFIANT; } - - GIVEN { - PLAYER(species) { Ability(ability); Item(ITEM_WHITE_HERB); } - OPPONENT(SPECIES_ARBOK) { Ability(ABILITY_INTIMIDATE); } - } WHEN { - TURN { ; } - } SCENE { - ABILITY_POPUP(opponent, ABILITY_INTIMIDATE); - ABILITY_POPUP(player, ability); - ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); - // Defiant activates first, so White Herb doesn't have a chance to trigger. - if (ability == ABILITY_COMPETITIVE) { - ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player); - MESSAGE("Igglybuff returned its stats to normal using its White Herb!"); - } - } THEN { - if (ability == ABILITY_COMPETITIVE) { - EXPECT(player->item == ITEM_NONE); - EXPECT(player->statStages[STAT_ATK] = DEFAULT_STAT_STAGE); - EXPECT(player->statStages[STAT_SPATK] = DEFAULT_STAT_STAGE + 2); - } else { - EXPECT(player->statStages[STAT_ATK] = DEFAULT_STAT_STAGE + 1); - } - } -} - -DOUBLE_BATTLE_TEST("White Herb is correctly displayed") -{ - GIVEN { - PLAYER(SPECIES_WOBBUFFET); - PLAYER(SPECIES_WYNAUT) { Item(ITEM_WHITE_HERB); } - OPPONENT(SPECIES_WOBBUFFET); - OPPONENT(SPECIES_WYNAUT); - } WHEN { - TURN { MOVE(playerRight, MOVE_SUPERPOWER, target: opponentRight); } - } SCENE { - ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, playerRight); - MESSAGE("Wynaut returned its stats to normal using its White Herb!"); - } THEN { - EXPECT(playerLeft->item == ITEM_NONE); - EXPECT(playerLeft->statStages[STAT_DEF] = DEFAULT_STAT_STAGE); - } -} diff --git a/test/battle/hold_effect/ring_target.c b/test/battle/hold_effect/ring_target.c new file mode 100644 index 0000000000..1074bb0dc7 --- /dev/null +++ b/test/battle/hold_effect/ring_target.c @@ -0,0 +1,4 @@ +#include "global.h" +#include "test/battle.h" + +TO_DO_BATTLE_TEST("TODO: Write Ring Target (Hold Effect) test titles") diff --git a/test/battle/hold_effect/rocky_helmet.c b/test/battle/hold_effect/rocky_helmet.c new file mode 100644 index 0000000000..bc52f44b87 --- /dev/null +++ b/test/battle/hold_effect/rocky_helmet.c @@ -0,0 +1,25 @@ +#include "global.h" +#include "test/battle.h" + +ASSUMPTIONS +{ + ASSUME(GetItemHoldEffect(ITEM_ROCKY_HELMET) == HOLD_EFFECT_ROCKY_HELMET); + ASSUME(MoveMakesContact(MOVE_SCRATCH)); + ASSUME(MoveMakesContact(MOVE_SHADOW_SNEAK)); +} + +SINGLE_BATTLE_TEST("Rocky Helmet damages attacker even if damage is blocked by Disguise") +{ + GIVEN { + PLAYER(SPECIES_MIMIKYU) { Item(ITEM_ROCKY_HELMET); Ability(ABILITY_DISGUISE); }; + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_SHADOW_SNEAK); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SHADOW_SNEAK, opponent); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player); + HP_BAR(opponent); + } +} + +TO_DO_BATTLE_TEST("TODO: Write Rocky Helmet (Hold Effect) test titles") diff --git a/test/battle/hold_effect/safety_goggles.c b/test/battle/hold_effect/safety_goggles.c index 346e41fbfe..ec90b251b3 100644 --- a/test/battle/hold_effect/safety_goggles.c +++ b/test/battle/hold_effect/safety_goggles.c @@ -46,8 +46,10 @@ SINGLE_BATTLE_TEST("Safety Goggles blocks damage from Sandstorm") SINGLE_BATTLE_TEST("Safety Goggles blocks Effect Spore's effect") { + KNOWN_FAILING; PASSES_RANDOMLY(100, 100, RNG_EFFECT_SPORE); GIVEN { + WITH_CONFIG(CONFIG_POWDER_GRASS, GEN_5); // Setting it to Gen 6 causes it to pass ASSUME(MoveMakesContact(MOVE_SCRATCH)); PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_SAFETY_GOGGLES); } OPPONENT(SPECIES_BRELOOM) { Ability(ABILITY_EFFECT_SPORE); } diff --git a/test/battle/hold_effect/scope_lens.c b/test/battle/hold_effect/scope_lens.c index 06c9c4a0dc..2a073900a7 100644 --- a/test/battle/hold_effect/scope_lens.c +++ b/test/battle/hold_effect/scope_lens.c @@ -9,7 +9,7 @@ SINGLE_BATTLE_TEST("Scope Lens increases the critical hit ratio by 1 stage") PARAMETRIZE { genConfig = j; passes = 1; trials = 8; } // 12.5% PASSES_RANDOMLY(passes, trials, RNG_CRITICAL_HIT); GIVEN { - WITH_CONFIG(GEN_CONFIG_CRIT_CHANCE, genConfig); + WITH_CONFIG(CONFIG_CRIT_CHANCE, genConfig); ASSUME(gItemsInfo[ITEM_SCOPE_LENS].holdEffect == HOLD_EFFECT_SCOPE_LENS); ASSUME(GetSpeciesBaseSpeed(SPECIES_WOBBUFFET) == 33); PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_SCOPE_LENS); }; diff --git a/test/battle/hold_effect/seeds.c b/test/battle/hold_effect/seeds.c deleted file mode 100644 index 53cca3c211..0000000000 --- a/test/battle/hold_effect/seeds.c +++ /dev/null @@ -1,197 +0,0 @@ -#include "global.h" -#include "test/battle.h" - -ASSUMPTIONS -{ - ASSUME(gItemsInfo[ITEM_ELECTRIC_SEED].holdEffect == HOLD_EFFECT_SEEDS); - ASSUME(gItemsInfo[ITEM_ELECTRIC_SEED].holdEffectParam == HOLD_EFFECT_PARAM_ELECTRIC_TERRAIN); - ASSUME(gItemsInfo[ITEM_GRASSY_SEED].holdEffect == HOLD_EFFECT_SEEDS); - ASSUME(gItemsInfo[ITEM_GRASSY_SEED].holdEffectParam == HOLD_EFFECT_PARAM_GRASSY_TERRAIN); - ASSUME(gItemsInfo[ITEM_MISTY_SEED].holdEffect == HOLD_EFFECT_SEEDS); - ASSUME(gItemsInfo[ITEM_MISTY_SEED].holdEffectParam == HOLD_EFFECT_PARAM_MISTY_TERRAIN); - ASSUME(gItemsInfo[ITEM_PSYCHIC_SEED].holdEffect == HOLD_EFFECT_SEEDS); - ASSUME(gItemsInfo[ITEM_PSYCHIC_SEED].holdEffectParam == HOLD_EFFECT_PARAM_PSYCHIC_TERRAIN); - -} - -SINGLE_BATTLE_TEST("Electric Seed raises the holder's Defense on Electric Terrain") -{ - u32 ability, item; - PARAMETRIZE { ability = ABILITY_TELEPATHY; item = ITEM_NONE; } - PARAMETRIZE { ability = ABILITY_TELEPATHY; item = ITEM_ELECTRIC_SEED; } - PARAMETRIZE { ability = ABILITY_ELECTRIC_SURGE; item = ITEM_NONE; } - PARAMETRIZE { ability = ABILITY_ELECTRIC_SURGE; item = ITEM_ELECTRIC_SEED; } - GIVEN { - PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_ELECTRIC_SEED); } - PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_ELECTRIC_SEED); } - OPPONENT(SPECIES_TAPU_KOKO) { Ability(ability); Item(item); } - } WHEN { - if (ability == ABILITY_TELEPATHY) - TURN { MOVE(player, MOVE_ELECTRIC_TERRAIN); } - TURN { SWITCH(player, 1); } - } SCENE { - ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); - MESSAGE("Using Electric Seed, the Defense of Wobbuffet rose!"); - if (item == ITEM_ELECTRIC_SEED) { - ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); - MESSAGE("Using Electric Seed, the Defense of the opposing Tapu Koko rose!"); - } - SWITCH_OUT_MESSAGE("Wobbuffet"); - SEND_IN_MESSAGE("Wobbuffet"); - ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); - MESSAGE("Using Electric Seed, the Defense of Wobbuffet rose!"); - } THEN { - EXPECT_EQ(player->statStages[STAT_DEF], DEFAULT_STAT_STAGE + 1); - } -} - -SINGLE_BATTLE_TEST("Grassy Seed raises the holder's Defense on Grassy Terrain") -{ - u32 ability, item; - PARAMETRIZE { ability = ABILITY_TELEPATHY; item = ITEM_NONE; } - PARAMETRIZE { ability = ABILITY_TELEPATHY; item = ITEM_GRASSY_SEED; } - PARAMETRIZE { ability = ABILITY_GRASSY_SURGE; item = ITEM_NONE; } - PARAMETRIZE { ability = ABILITY_GRASSY_SURGE; item = ITEM_GRASSY_SEED; } - GIVEN { - PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_GRASSY_SEED); } - PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_GRASSY_SEED); } - OPPONENT(SPECIES_TAPU_BULU) { Ability(ability); Item(item); } - } WHEN { - if (ability == ABILITY_TELEPATHY) - TURN { MOVE(player, MOVE_GRASSY_TERRAIN); } - TURN { SWITCH(player, 1); } - } SCENE { - ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); - MESSAGE("Using Grassy Seed, the Defense of Wobbuffet rose!"); - if (item == ITEM_GRASSY_SEED) { - ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); - MESSAGE("Using Grassy Seed, the Defense of the opposing Tapu Bulu rose!"); - } - SWITCH_OUT_MESSAGE("Wobbuffet"); - SEND_IN_MESSAGE("Wobbuffet"); - ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); - MESSAGE("Using Grassy Seed, the Defense of Wobbuffet rose!"); - } THEN { - EXPECT_EQ(player->statStages[STAT_DEF], DEFAULT_STAT_STAGE + 1); - } -} - -SINGLE_BATTLE_TEST("Misty Seed raises the holder's Sp. Defense on Misty Terrain") -{ - u32 ability, item; - PARAMETRIZE { ability = ABILITY_TELEPATHY; item = ITEM_NONE; } - PARAMETRIZE { ability = ABILITY_TELEPATHY; item = ITEM_MISTY_SEED; } - PARAMETRIZE { ability = ABILITY_MISTY_SURGE; item = ITEM_NONE; } - PARAMETRIZE { ability = ABILITY_MISTY_SURGE; item = ITEM_MISTY_SEED; } - GIVEN { - PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_MISTY_SEED); } - PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_MISTY_SEED); } - OPPONENT(SPECIES_TAPU_FINI) { Ability(ability); Item(item); } - } WHEN { - if (ability == ABILITY_TELEPATHY) - TURN { MOVE(player, MOVE_MISTY_TERRAIN); } - TURN { SWITCH(player, 1); } - } SCENE { - ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); - MESSAGE("Using Misty Seed, the Sp. Def of Wobbuffet rose!"); - if (item == ITEM_MISTY_SEED) { - ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); - MESSAGE("Using Misty Seed, the Sp. Def of the opposing Tapu Fini rose!"); - } - SWITCH_OUT_MESSAGE("Wobbuffet"); - SEND_IN_MESSAGE("Wobbuffet"); - ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); - MESSAGE("Using Misty Seed, the Sp. Def of Wobbuffet rose!"); - } THEN { - EXPECT_EQ(player->statStages[STAT_SPDEF], DEFAULT_STAT_STAGE + 1); - } -} - -SINGLE_BATTLE_TEST("Psychic Seed raises the holder's Sp. Defense on Psychic Terrain") -{ - u32 ability, item; - PARAMETRIZE { ability = ABILITY_TELEPATHY; item = ITEM_NONE; } - PARAMETRIZE { ability = ABILITY_TELEPATHY; item = ITEM_PSYCHIC_SEED; } - PARAMETRIZE { ability = ABILITY_PSYCHIC_SURGE; item = ITEM_NONE; } - PARAMETRIZE { ability = ABILITY_PSYCHIC_SURGE; item = ITEM_PSYCHIC_SEED; } - GIVEN { - PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_PSYCHIC_SEED); } - PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_PSYCHIC_SEED); } - OPPONENT(SPECIES_TAPU_LELE) { Ability(ability); Item(item); } - } WHEN { - if (ability == ABILITY_TELEPATHY) - TURN { MOVE(player, MOVE_PSYCHIC_TERRAIN); } - TURN { SWITCH(player, 1); } - } SCENE { - ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); - MESSAGE("Using Psychic Seed, the Sp. Def of Wobbuffet rose!"); - if (item == ITEM_PSYCHIC_SEED) { - ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); - MESSAGE("Using Psychic Seed, the Sp. Def of the opposing Tapu Lele rose!"); - } - SWITCH_OUT_MESSAGE("Wobbuffet"); - SEND_IN_MESSAGE("Wobbuffet"); - ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); - MESSAGE("Using Psychic Seed, the Sp. Def of Wobbuffet rose!"); - } THEN { - EXPECT_EQ(player->statStages[STAT_SPDEF], DEFAULT_STAT_STAGE + 1); - } -} - -SINGLE_BATTLE_TEST("Seeds get consumed in Terrain even if holder is not affected by Terrain") -{ - u32 species, ability, item; - PARAMETRIZE { species = SPECIES_TAPU_KOKO; ability = ABILITY_ELECTRIC_SURGE; item = ITEM_ELECTRIC_SEED; } - PARAMETRIZE { species = SPECIES_TAPU_BULU; ability = ABILITY_GRASSY_SURGE; item = ITEM_GRASSY_SEED; } - PARAMETRIZE { species = SPECIES_TAPU_FINI; ability = ABILITY_MISTY_SURGE; item = ITEM_MISTY_SEED; } - PARAMETRIZE { species = SPECIES_TAPU_LELE; ability = ABILITY_PSYCHIC_SURGE; item = ITEM_PSYCHIC_SEED; } - GIVEN { - ASSUME(GetSpeciesType(SPECIES_PIDGEY, 0) == TYPE_FLYING || GetSpeciesType(SPECIES_PIDGEY, 1) == TYPE_FLYING); - PLAYER(SPECIES_PIDGEY) { Item(item); } - OPPONENT(species) { Ability(ability); } - } WHEN { - TURN { } - } SCENE { - ABILITY_POPUP(opponent, ability); - ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); - } THEN { - EXPECT_EQ(player->item, ITEM_NONE); - } -} - -SINGLE_BATTLE_TEST("Electric Seed is consumed on Electric Terrain before other abilities change the terrain") -{ - GIVEN { - PLAYER(SPECIES_TAPU_BULU) { Ability(ABILITY_GRASSY_SURGE); Item(ITEM_ELECTRIC_SEED); Speed(5); } - OPPONENT(SPECIES_TAPU_KOKO) { Ability(ABILITY_ELECTRIC_SURGE); Item(ITEM_ELECTRIC_SEED); Speed(10); } - } WHEN { - TURN { } - } SCENE { - ABILITY_POPUP(opponent, ABILITY_ELECTRIC_SURGE); - ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); - MESSAGE("Using Electric Seed, the Defense of the opposing Tapu Koko rose!"); - ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); - MESSAGE("Using Electric Seed, the Defense of Tapu Bulu rose!"); - ABILITY_POPUP(player, ABILITY_GRASSY_SURGE); - } -} - -SINGLE_BATTLE_TEST("Electric Seed doesn't activate on existing Electric Terrain before user's ability changes the terrain") -{ - GIVEN { - PLAYER(SPECIES_WOBBUFFET); - PLAYER(SPECIES_TAPU_BULU) { Ability(ABILITY_GRASSY_SURGE); Item(ITEM_ELECTRIC_SEED); } - OPPONENT(SPECIES_TAPU_KOKO) { Ability(ABILITY_ELECTRIC_SURGE); } - } WHEN { - TURN { SWITCH(player, 1); } - } SCENE { - ABILITY_POPUP(opponent, ABILITY_ELECTRIC_SURGE); - SWITCH_OUT_MESSAGE("Wobbuffet"); - SEND_IN_MESSAGE("Tapu Bulu"); - NONE_OF { - ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); - MESSAGE("Using Electric Seed, the Defense of Tapu Bulu rose!"); - } - ABILITY_POPUP(player, ABILITY_GRASSY_SURGE); - } -} diff --git a/test/battle/hold_effect/smooth_rock.c b/test/battle/hold_effect/smooth_rock.c new file mode 100644 index 0000000000..f782e12381 --- /dev/null +++ b/test/battle/hold_effect/smooth_rock.c @@ -0,0 +1,4 @@ +#include "global.h" +#include "test/battle.h" + +TO_DO_BATTLE_TEST("TODO: Write Smooth Rock (Hold Effect) test titles") diff --git a/test/battle/hold_effect/snowball.c b/test/battle/hold_effect/snowball.c new file mode 100644 index 0000000000..7037e1c59d --- /dev/null +++ b/test/battle/hold_effect/snowball.c @@ -0,0 +1,4 @@ +#include "global.h" +#include "test/battle.h" + +TO_DO_BATTLE_TEST("TODO: Write Snowball (Hold Effect) test titles") diff --git a/test/battle/hold_effect/soul_dew.c b/test/battle/hold_effect/soul_dew.c new file mode 100644 index 0000000000..b1ad8a9aa0 --- /dev/null +++ b/test/battle/hold_effect/soul_dew.c @@ -0,0 +1,4 @@ +#include "global.h" +#include "test/battle.h" + +TO_DO_BATTLE_TEST("TODO: Write Soul Dew (Hold Effect) test titles") diff --git a/test/battle/hold_effect/special_attack_up.c b/test/battle/hold_effect/sp_attack_up.c similarity index 100% rename from test/battle/hold_effect/special_attack_up.c rename to test/battle/hold_effect/sp_attack_up.c diff --git a/test/battle/hold_effect/special_defense_up.c b/test/battle/hold_effect/sp_defense_up.c similarity index 100% rename from test/battle/hold_effect/special_defense_up.c rename to test/battle/hold_effect/sp_defense_up.c diff --git a/test/battle/hold_effect/sticky_barb.c b/test/battle/hold_effect/sticky_barb.c new file mode 100644 index 0000000000..59c1e12270 --- /dev/null +++ b/test/battle/hold_effect/sticky_barb.c @@ -0,0 +1,51 @@ +#include "global.h" +#include "test/battle.h" + +ASSUMPTIONS +{ + ASSUME(GetItemHoldEffect(ITEM_STICKY_BARB) == HOLD_EFFECT_STICKY_BARB); +} + +SINGLE_BATTLE_TEST("Sticky Barb hurts its holder at the end of the turn") +{ + s16 damage; + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_STICKY_BARB); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { } + } SCENE { + HP_BAR(player, captureDamage: &damage); + } THEN { + EXPECT_EQ(damage, player->maxHP / 8); + } +} + +SINGLE_BATTLE_TEST("Sticky Barb gets transferred if its holder is hit by a contact move") +{ + u32 move; + PARAMETRIZE { move = MOVE_SCRATCH; } + PARAMETRIZE { move = MOVE_GROWL; } + PARAMETRIZE { move = MOVE_HYPER_VOICE; } + GIVEN { + ASSUME(MoveMakesContact(MOVE_SCRATCH)); + ASSUME(!MoveMakesContact(MOVE_GROWL)); + ASSUME(!MoveMakesContact(MOVE_HYPER_VOICE)); + PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_STICKY_BARB); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, move); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, move, opponent); + if (MoveMakesContact(move)) + { + MESSAGE("The Sticky Barb attached itself to the opposing Wobbuffet!"); + MESSAGE("The opposing Wobbuffet was hurt by the Sticky Barb!"); + } + else + { + NOT MESSAGE("The Sticky Barb attached itself to the opposing Wobbuffet!"); + MESSAGE("Wobbuffet was hurt by the Sticky Barb!"); + } + } +} diff --git a/test/battle/hold_effect/terrain_extender.c b/test/battle/hold_effect/terrain_extender.c new file mode 100644 index 0000000000..cce69d42aa --- /dev/null +++ b/test/battle/hold_effect/terrain_extender.c @@ -0,0 +1,4 @@ +#include "global.h" +#include "test/battle.h" + +TO_DO_BATTLE_TEST("TODO: Write Terrain Extender (Hold Effect) test titles") diff --git a/test/battle/hold_effect/terrain_seed.c b/test/battle/hold_effect/terrain_seed.c new file mode 100644 index 0000000000..b54dd54f5b --- /dev/null +++ b/test/battle/hold_effect/terrain_seed.c @@ -0,0 +1,202 @@ +#include "global.h" +#include "test/battle.h" + +ASSUMPTIONS +{ + ASSUME(gItemsInfo[ITEM_ELECTRIC_SEED].holdEffect == HOLD_EFFECT_TERRAIN_SEED); + ASSUME(gItemsInfo[ITEM_ELECTRIC_SEED].holdEffectParam == HOLD_EFFECT_PARAM_ELECTRIC_TERRAIN); + ASSUME(gItemsInfo[ITEM_GRASSY_SEED].holdEffect == HOLD_EFFECT_TERRAIN_SEED); + ASSUME(gItemsInfo[ITEM_GRASSY_SEED].holdEffectParam == HOLD_EFFECT_PARAM_GRASSY_TERRAIN); + ASSUME(gItemsInfo[ITEM_MISTY_SEED].holdEffect == HOLD_EFFECT_TERRAIN_SEED); + ASSUME(gItemsInfo[ITEM_MISTY_SEED].holdEffectParam == HOLD_EFFECT_PARAM_MISTY_TERRAIN); + ASSUME(gItemsInfo[ITEM_PSYCHIC_SEED].holdEffect == HOLD_EFFECT_TERRAIN_SEED); + ASSUME(gItemsInfo[ITEM_PSYCHIC_SEED].holdEffectParam == HOLD_EFFECT_PARAM_PSYCHIC_TERRAIN); + +} + +SINGLE_BATTLE_TEST("Electric Seed raises the holder's Defense on Electric Terrain") +{ + enum Ability ability; + u32 item; + PARAMETRIZE { ability = ABILITY_TELEPATHY; item = ITEM_NONE; } + PARAMETRIZE { ability = ABILITY_TELEPATHY; item = ITEM_ELECTRIC_SEED; } + PARAMETRIZE { ability = ABILITY_ELECTRIC_SURGE; item = ITEM_NONE; } + PARAMETRIZE { ability = ABILITY_ELECTRIC_SURGE; item = ITEM_ELECTRIC_SEED; } + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_ELECTRIC_SEED); } + PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_ELECTRIC_SEED); } + OPPONENT(SPECIES_TAPU_KOKO) { Ability(ability); Item(item); } + } WHEN { + if (ability == ABILITY_TELEPATHY) + TURN { MOVE(player, MOVE_ELECTRIC_TERRAIN); } + TURN { SWITCH(player, 1); } + } SCENE { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); + MESSAGE("Using Electric Seed, the Defense of Wobbuffet rose!"); + if (item == ITEM_ELECTRIC_SEED) { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); + MESSAGE("Using Electric Seed, the Defense of the opposing Tapu Koko rose!"); + } + SWITCH_OUT_MESSAGE("Wobbuffet"); + SEND_IN_MESSAGE("Wobbuffet"); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); + MESSAGE("Using Electric Seed, the Defense of Wobbuffet rose!"); + } THEN { + EXPECT_EQ(player->statStages[STAT_DEF], DEFAULT_STAT_STAGE + 1); + } +} + +SINGLE_BATTLE_TEST("Grassy Seed raises the holder's Defense on Grassy Terrain") +{ + enum Ability ability; + u32 item; + PARAMETRIZE { ability = ABILITY_TELEPATHY; item = ITEM_NONE; } + PARAMETRIZE { ability = ABILITY_TELEPATHY; item = ITEM_GRASSY_SEED; } + PARAMETRIZE { ability = ABILITY_GRASSY_SURGE; item = ITEM_NONE; } + PARAMETRIZE { ability = ABILITY_GRASSY_SURGE; item = ITEM_GRASSY_SEED; } + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_GRASSY_SEED); } + PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_GRASSY_SEED); } + OPPONENT(SPECIES_TAPU_BULU) { Ability(ability); Item(item); } + } WHEN { + if (ability == ABILITY_TELEPATHY) + TURN { MOVE(player, MOVE_GRASSY_TERRAIN); } + TURN { SWITCH(player, 1); } + } SCENE { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); + MESSAGE("Using Grassy Seed, the Defense of Wobbuffet rose!"); + if (item == ITEM_GRASSY_SEED) { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); + MESSAGE("Using Grassy Seed, the Defense of the opposing Tapu Bulu rose!"); + } + SWITCH_OUT_MESSAGE("Wobbuffet"); + SEND_IN_MESSAGE("Wobbuffet"); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); + MESSAGE("Using Grassy Seed, the Defense of Wobbuffet rose!"); + } THEN { + EXPECT_EQ(player->statStages[STAT_DEF], DEFAULT_STAT_STAGE + 1); + } +} + +SINGLE_BATTLE_TEST("Misty Seed raises the holder's Sp. Defense on Misty Terrain") +{ + enum Ability ability; + u32 item; + PARAMETRIZE { ability = ABILITY_TELEPATHY; item = ITEM_NONE; } + PARAMETRIZE { ability = ABILITY_TELEPATHY; item = ITEM_MISTY_SEED; } + PARAMETRIZE { ability = ABILITY_MISTY_SURGE; item = ITEM_NONE; } + PARAMETRIZE { ability = ABILITY_MISTY_SURGE; item = ITEM_MISTY_SEED; } + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_MISTY_SEED); } + PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_MISTY_SEED); } + OPPONENT(SPECIES_TAPU_FINI) { Ability(ability); Item(item); } + } WHEN { + if (ability == ABILITY_TELEPATHY) + TURN { MOVE(player, MOVE_MISTY_TERRAIN); } + TURN { SWITCH(player, 1); } + } SCENE { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); + MESSAGE("Using Misty Seed, the Sp. Def of Wobbuffet rose!"); + if (item == ITEM_MISTY_SEED) { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); + MESSAGE("Using Misty Seed, the Sp. Def of the opposing Tapu Fini rose!"); + } + SWITCH_OUT_MESSAGE("Wobbuffet"); + SEND_IN_MESSAGE("Wobbuffet"); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); + MESSAGE("Using Misty Seed, the Sp. Def of Wobbuffet rose!"); + } THEN { + EXPECT_EQ(player->statStages[STAT_SPDEF], DEFAULT_STAT_STAGE + 1); + } +} + +SINGLE_BATTLE_TEST("Psychic Seed raises the holder's Sp. Defense on Psychic Terrain") +{ + enum Ability ability; + u32 item; + PARAMETRIZE { ability = ABILITY_TELEPATHY; item = ITEM_NONE; } + PARAMETRIZE { ability = ABILITY_TELEPATHY; item = ITEM_PSYCHIC_SEED; } + PARAMETRIZE { ability = ABILITY_PSYCHIC_SURGE; item = ITEM_NONE; } + PARAMETRIZE { ability = ABILITY_PSYCHIC_SURGE; item = ITEM_PSYCHIC_SEED; } + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_PSYCHIC_SEED); } + PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_PSYCHIC_SEED); } + OPPONENT(SPECIES_TAPU_LELE) { Ability(ability); Item(item); } + } WHEN { + if (ability == ABILITY_TELEPATHY) + TURN { MOVE(player, MOVE_PSYCHIC_TERRAIN); } + TURN { SWITCH(player, 1); } + } SCENE { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); + MESSAGE("Using Psychic Seed, the Sp. Def of Wobbuffet rose!"); + if (item == ITEM_PSYCHIC_SEED) { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); + MESSAGE("Using Psychic Seed, the Sp. Def of the opposing Tapu Lele rose!"); + } + SWITCH_OUT_MESSAGE("Wobbuffet"); + SEND_IN_MESSAGE("Wobbuffet"); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); + MESSAGE("Using Psychic Seed, the Sp. Def of Wobbuffet rose!"); + } THEN { + EXPECT_EQ(player->statStages[STAT_SPDEF], DEFAULT_STAT_STAGE + 1); + } +} + +SINGLE_BATTLE_TEST("Seeds get consumed in Terrain even if holder is not affected by Terrain") +{ + u32 species, item; + enum Ability ability; + PARAMETRIZE { species = SPECIES_TAPU_KOKO; ability = ABILITY_ELECTRIC_SURGE; item = ITEM_ELECTRIC_SEED; } + PARAMETRIZE { species = SPECIES_TAPU_BULU; ability = ABILITY_GRASSY_SURGE; item = ITEM_GRASSY_SEED; } + PARAMETRIZE { species = SPECIES_TAPU_FINI; ability = ABILITY_MISTY_SURGE; item = ITEM_MISTY_SEED; } + PARAMETRIZE { species = SPECIES_TAPU_LELE; ability = ABILITY_PSYCHIC_SURGE; item = ITEM_PSYCHIC_SEED; } + GIVEN { + ASSUME(GetSpeciesType(SPECIES_PIDGEY, 0) == TYPE_FLYING || GetSpeciesType(SPECIES_PIDGEY, 1) == TYPE_FLYING); + PLAYER(SPECIES_PIDGEY) { Item(item); } + OPPONENT(species) { Ability(ability); } + } WHEN { + TURN { } + } SCENE { + ABILITY_POPUP(opponent, ability); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); + } THEN { + EXPECT_EQ(player->item, ITEM_NONE); + } +} + +SINGLE_BATTLE_TEST("Electric Seed is consumed on Electric Terrain before other abilities change the terrain") +{ + GIVEN { + PLAYER(SPECIES_TAPU_BULU) { Ability(ABILITY_GRASSY_SURGE); Item(ITEM_ELECTRIC_SEED); Speed(5); } + OPPONENT(SPECIES_TAPU_KOKO) { Ability(ABILITY_ELECTRIC_SURGE); Item(ITEM_ELECTRIC_SEED); Speed(10); } + } WHEN { + TURN { } + } SCENE { + ABILITY_POPUP(opponent, ABILITY_ELECTRIC_SURGE); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); + MESSAGE("Using Electric Seed, the Defense of the opposing Tapu Koko rose!"); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); + MESSAGE("Using Electric Seed, the Defense of Tapu Bulu rose!"); + ABILITY_POPUP(player, ABILITY_GRASSY_SURGE); + } +} + +SINGLE_BATTLE_TEST("Electric Seed doesn't activate on existing Electric Terrain before user's ability changes the terrain") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_TAPU_BULU) { Ability(ABILITY_GRASSY_SURGE); Item(ITEM_ELECTRIC_SEED); } + OPPONENT(SPECIES_TAPU_KOKO) { Ability(ABILITY_ELECTRIC_SURGE); } + } WHEN { + TURN { SWITCH(player, 1); } + } SCENE { + ABILITY_POPUP(opponent, ABILITY_ELECTRIC_SURGE); + SWITCH_OUT_MESSAGE("Wobbuffet"); + SEND_IN_MESSAGE("Tapu Bulu"); + NONE_OF { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); + MESSAGE("Using Electric Seed, the Defense of Tapu Bulu rose!"); + } + ABILITY_POPUP(player, ABILITY_GRASSY_SURGE); + } +} diff --git a/test/battle/hold_effect/thick_club.c b/test/battle/hold_effect/thick_club.c new file mode 100644 index 0000000000..9fe2040394 --- /dev/null +++ b/test/battle/hold_effect/thick_club.c @@ -0,0 +1,4 @@ +#include "global.h" +#include "test/battle.h" + +TO_DO_BATTLE_TEST("TODO: Write Thick Club (Hold Effect) test titles") diff --git a/test/battle/hold_effect/toxic_orb.c b/test/battle/hold_effect/toxic_orb.c new file mode 100644 index 0000000000..115259cd0c --- /dev/null +++ b/test/battle/hold_effect/toxic_orb.c @@ -0,0 +1,4 @@ +#include "global.h" +#include "test/battle.h" + +TO_DO_BATTLE_TEST("TODO: Write Toxic Orb (Hold Effect) test titles") diff --git a/test/battle/hold_effect/weakness_berry.c b/test/battle/hold_effect/weakness_berry.c deleted file mode 100644 index 17adb08aa3..0000000000 --- a/test/battle/hold_effect/weakness_berry.c +++ /dev/null @@ -1,124 +0,0 @@ -#include "global.h" -#include "test/battle.h" - -static const u16 sMoveItemTable[][4] = -{ - { TYPE_NORMAL, MOVE_SCRATCH, ITEM_CHILAN_BERRY, SPECIES_WOBBUFFET }, - { TYPE_FIGHTING, MOVE_KARATE_CHOP, ITEM_CHOPLE_BERRY, SPECIES_RAMPARDOS }, - { TYPE_FLYING, MOVE_WING_ATTACK, ITEM_COBA_BERRY, SPECIES_HARIYAMA }, - { TYPE_POISON, MOVE_POISON_STING, ITEM_KEBIA_BERRY, SPECIES_GOGOAT }, - { TYPE_GROUND, MOVE_MUD_SHOT, ITEM_SHUCA_BERRY, SPECIES_RAMPARDOS }, - { TYPE_ROCK, MOVE_ROCK_THROW, ITEM_CHARTI_BERRY, SPECIES_CORVISQUIRE }, - { TYPE_BUG, MOVE_BUG_BITE, ITEM_TANGA_BERRY, SPECIES_WOBBUFFET }, - { TYPE_GHOST, MOVE_SHADOW_PUNCH, ITEM_KASIB_BERRY, SPECIES_WOBBUFFET }, - { TYPE_STEEL, MOVE_METAL_CLAW, ITEM_BABIRI_BERRY, SPECIES_RAMPARDOS }, - { TYPE_FIRE, MOVE_EMBER, ITEM_OCCA_BERRY, SPECIES_GOGOAT }, - { TYPE_WATER, MOVE_WATER_GUN, ITEM_PASSHO_BERRY, SPECIES_RAMPARDOS }, - { TYPE_GRASS, MOVE_VINE_WHIP, ITEM_RINDO_BERRY, SPECIES_RAMPARDOS }, - { TYPE_ELECTRIC, MOVE_THUNDER_SHOCK, ITEM_WACAN_BERRY, SPECIES_CORVISQUIRE }, - { TYPE_PSYCHIC, MOVE_CONFUSION, ITEM_PAYAPA_BERRY, SPECIES_HARIYAMA }, - { TYPE_ICE, MOVE_AURORA_BEAM, ITEM_YACHE_BERRY, SPECIES_DRAGONAIR }, - { TYPE_DRAGON, MOVE_DRAGON_BREATH, ITEM_HABAN_BERRY, SPECIES_DRAGONAIR }, - { TYPE_DARK, MOVE_BITE, ITEM_COLBUR_BERRY, SPECIES_WOBBUFFET }, - { TYPE_FAIRY, MOVE_DISARMING_VOICE, ITEM_ROSELI_BERRY, SPECIES_DRAGONAIR }, -}; - -SINGLE_BATTLE_TEST("Weakness berries decrease the base power of moves by half", s16 damage) -{ - u32 move = 0, item = 0, type = 0, defender = 0; - - for (u32 j = 0; j < ARRAY_COUNT(sMoveItemTable); j++) - { - PARAMETRIZE { type = sMoveItemTable[j][0]; move = sMoveItemTable[j][1]; defender = sMoveItemTable[j][3]; item = ITEM_NONE; } - PARAMETRIZE { type = sMoveItemTable[j][0]; move = sMoveItemTable[j][1]; defender = sMoveItemTable[j][3]; item = sMoveItemTable[j][2]; } - } - - GIVEN { - ASSUME(GetMovePower(move) > 0); - ASSUME(GetMoveType(move) == type); - ASSUME(GetSpeciesType(defender, 0) == GetSpeciesType(defender, 1)); - if (type != TYPE_NORMAL) { - ASSUME(gTypeEffectivenessTable[type][GetSpeciesType(defender, 0)] > UQ_4_12(1.0)); - } - if (item != ITEM_NONE) { - ASSUME(GetItemHoldEffect(item) == HOLD_EFFECT_RESIST_BERRY); - ASSUME(GetItemHoldEffectParam(item) == type); - } - PLAYER(SPECIES_WOBBUFFET); - OPPONENT(defender) { Item(item); } - } WHEN { - TURN { MOVE(player, move); } - } SCENE { - if (1 == i % 2) { - ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, opponent); - } - HP_BAR(opponent, captureDamage: &results[i].damage); - } FINALLY { - for (u32 j = 0; j < ARRAY_COUNT(sMoveItemTable); j++) { - EXPECT_MUL_EQ(results[j*2].damage, Q_4_12(0.5), results[(j*2)+1].damage); - } - } -} - -SINGLE_BATTLE_TEST("Weakness berries do not activate unless a move is super effective", s16 damage) -{ - u32 move = 0, item = 0, type = 0, defender = 0; - - for (u32 j = 0; j < ARRAY_COUNT(sMoveItemTable); j++) - { - if (TYPE_NORMAL == type) - { - // ITEM_CHILAN_BERRY activates without a weakness - } - else if (TYPE_FAIRY == type) - { - PARAMETRIZE { type = sMoveItemTable[j][0]; move = sMoveItemTable[j][1]; item = sMoveItemTable[j][2]; defender = SPECIES_WOBBUFFET; } - } - else - { - PARAMETRIZE { type = sMoveItemTable[j][0]; move = sMoveItemTable[j][1]; item = sMoveItemTable[j][2]; defender = SPECIES_SABLEYE; } - } - } - - GIVEN { - ASSUME(GetMovePower(move) > 0); - ASSUME(uq4_12_multiply(gTypeEffectivenessTable[type][GetSpeciesType(defender, 0)], - gTypeEffectivenessTable[type][GetSpeciesType(defender, 1)]) <= UQ_4_12(1.0)); - ASSUME(GetItemHoldEffect(item) == HOLD_EFFECT_RESIST_BERRY); - ASSUME(GetItemHoldEffectParam(item) == type); - PLAYER(SPECIES_WOBBUFFET); - OPPONENT(defender) { Item(item); } - } WHEN { - TURN { MOVE(player, move); } - } SCENE { - NOT ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, opponent); - } -} - -SINGLE_BATTLE_TEST("Weakness berries do not decrease the power of Struggle", s16 damage) -{ - u32 item = 0; - - PARAMETRIZE { item = ITEM_NONE; } - PARAMETRIZE { item = ITEM_CHILAN_BERRY; } - - GIVEN { - if (item != ITEM_NONE) { - ASSUME(GetItemHoldEffect(item) == HOLD_EFFECT_RESIST_BERRY); - ASSUME(GetItemHoldEffectParam(item) == TYPE_NORMAL); - } - PLAYER(SPECIES_WOBBUFFET); - OPPONENT(SPECIES_WOBBUFFET) { Item(item); } - } WHEN { - TURN { MOVE(player, MOVE_STRUGGLE); } - } SCENE { - NONE_OF { - ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, opponent); - MESSAGE("The Chilan Berry weakened the damage to the opposing Wobbuffet!"); - } - ANIMATION(ANIM_TYPE_MOVE, MOVE_STRUGGLE, player); - HP_BAR(opponent, captureDamage: &results[i].damage); - } FINALLY { - EXPECT_EQ(results[0].damage, results[1].damage); - } -} diff --git a/test/battle/hold_effect/weakness_policy.c b/test/battle/hold_effect/weakness_policy.c new file mode 100644 index 0000000000..d080e9ad65 --- /dev/null +++ b/test/battle/hold_effect/weakness_policy.c @@ -0,0 +1,31 @@ +#include "global.h" +#include "test/battle.h" + +ASSUMPTIONS +{ + ASSUME(GetItemHoldEffect(ITEM_WEAKNESS_POLICY) == HOLD_EFFECT_WEAKNESS_POLICY); +} + +SINGLE_BATTLE_TEST("Weakness Policy does not activate if Disguise blocks the damage") +{ + u32 species; + + PARAMETRIZE { species = SPECIES_MIMIKYU_BUSTED; } + PARAMETRIZE { species = SPECIES_MIMIKYU_DISGUISED; } + + GIVEN { + ASSUME(GetMoveType(MOVE_METAL_CLAW) == TYPE_STEEL); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(species) { Item(ITEM_WEAKNESS_POLICY); Ability(ABILITY_DISGUISE); } + } WHEN { + TURN { MOVE(player, MOVE_METAL_CLAW); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_METAL_CLAW, player); + if (species == SPECIES_MIMIKYU_BUSTED) + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, opponent); + else + NOT ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, opponent); + } +} + +TO_DO_BATTLE_TEST("TODO: Write Weakness Policy (Hold Effect) test titles") diff --git a/test/battle/hold_effect/white_herb.c b/test/battle/hold_effect/white_herb.c new file mode 100644 index 0000000000..4a8f020023 --- /dev/null +++ b/test/battle/hold_effect/white_herb.c @@ -0,0 +1,236 @@ +#include "global.h" +#include "test/battle.h" + +ASSUMPTIONS +{ + ASSUME(gItemsInfo[ITEM_WHITE_HERB].holdEffect == HOLD_EFFECT_WHITE_HERB); +} + +SINGLE_BATTLE_TEST("White Herb restores stats when they're lowered") +{ + GIVEN { + ASSUME(GetMoveEffect(MOVE_LEER) == EFFECT_DEFENSE_DOWN); + PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_WHITE_HERB); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_LEER); } + } SCENE { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player); + MESSAGE("Wobbuffet returned its stats to normal using its White Herb!"); + } THEN { + EXPECT(player->item == ITEM_NONE); + EXPECT(player->statStages[STAT_DEF] = DEFAULT_STAT_STAGE); + } +} + +SINGLE_BATTLE_TEST("White Herb restores stats after Attack was lowered by Intimidate in singles") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_WHITE_HERB); } + OPPONENT(SPECIES_ARBOK) { Ability(ABILITY_INTIMIDATE); } + } WHEN { + TURN { ; } + } SCENE { + ABILITY_POPUP(opponent, ABILITY_INTIMIDATE); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player); + MESSAGE("Wobbuffet returned its stats to normal using its White Herb!"); + } THEN { + EXPECT(player->item == ITEM_NONE); + EXPECT(player->statStages[STAT_DEF] = DEFAULT_STAT_STAGE); + } +} + +DOUBLE_BATTLE_TEST("White Herb restores stats after Attack was lowered by Intimidate in doubles") +{ + GIVEN { + OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_WHITE_HERB); } + OPPONENT(SPECIES_WYNAUT) { Item(ITEM_WHITE_HERB); } + PLAYER(SPECIES_ARBOK) { Ability(ABILITY_INTIMIDATE); } + PLAYER(SPECIES_WOBBUFFET); + } WHEN { + TURN { ; } + } SCENE { + ABILITY_POPUP(playerLeft, ABILITY_INTIMIDATE); + + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponentLeft); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponentRight); + + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, opponentLeft); + MESSAGE("The opposing Wobbuffet returned its stats to normal using its White Herb!"); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, opponentRight); + MESSAGE("The opposing Wynaut returned its stats to normal using its White Herb!"); + } THEN { + EXPECT(opponentLeft->item == ITEM_NONE); + EXPECT(opponentLeft->statStages[STAT_DEF] = DEFAULT_STAT_STAGE); + EXPECT(opponentRight->item == ITEM_NONE); + EXPECT(opponentRight->statStages[STAT_DEF] = DEFAULT_STAT_STAGE); + } +} + +SINGLE_BATTLE_TEST("White Herb restores stats after Attack was lowered by Intimidate while switching in") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_WHITE_HERB); } + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_ARBOK) { Ability(ABILITY_INTIMIDATE); } + } WHEN { + TURN { SWITCH(opponent, 1); MOVE(player, MOVE_CLOSE_COMBAT); } + } SCENE { + ABILITY_POPUP(opponent, ABILITY_INTIMIDATE); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player); + MESSAGE("Wobbuffet returned its stats to normal using its White Herb!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_CLOSE_COMBAT, player); + NONE_OF { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player); + MESSAGE("Wobbuffet returned its stats to normal using its White Herb!"); + } + } THEN { + EXPECT(player->item == ITEM_NONE); + EXPECT(player->statStages[STAT_DEF] = DEFAULT_STAT_STAGE - 1); + EXPECT(player->statStages[STAT_SPDEF] = DEFAULT_STAT_STAGE - 1); + } +} + +SINGLE_BATTLE_TEST("White Herb restores stats after all hits of a multi hit move happened") +{ + u16 species; + enum Ability ability; + + PARAMETRIZE { species = SPECIES_SLIGGOO_HISUI; ability = ABILITY_GOOEY; } + PARAMETRIZE { species = SPECIES_DUGTRIO_ALOLA; ability = ABILITY_TANGLING_HAIR; } + + GIVEN { + ASSUME(GetMoveStrikeCount(MOVE_DUAL_WINGBEAT) == 2); + PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_WHITE_HERB); } + OPPONENT(species) { Ability(ability); } + } WHEN { + TURN { MOVE(player, MOVE_DUAL_WINGBEAT); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_DUAL_WINGBEAT, player); + ABILITY_POPUP(opponent, ability); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); + MESSAGE("Wobbuffet's Speed fell!"); + ABILITY_POPUP(opponent, ability); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); + MESSAGE("Wobbuffet's Speed fell!"); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player); + MESSAGE("Wobbuffet returned its stats to normal using its White Herb!"); + } THEN { + EXPECT(player->item == ITEM_NONE); + EXPECT(player->statStages[STAT_SPEED] = DEFAULT_STAT_STAGE); + } +} + +SINGLE_BATTLE_TEST("White Herb wont have time to activate if it is knocked off or stolen by Thief") +{ + u16 move; + + PARAMETRIZE { move = MOVE_THIEF; } + PARAMETRIZE { move = MOVE_KNOCK_OFF; } + + GIVEN { + ASSUME(GetMoveEffect(MOVE_KNOCK_OFF) == EFFECT_KNOCK_OFF); + ASSUME(GetMoveEffect(MOVE_THIEF) == EFFECT_STEAL_ITEM); + PLAYER(SPECIES_SLUGMA) { Ability(ABILITY_WEAK_ARMOR); Item(ITEM_WHITE_HERB); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, move); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, move, opponent); + ABILITY_POPUP(player, ABILITY_WEAK_ARMOR); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); + MESSAGE("Slugma's Weak Armor lowered its Defense!"); + MESSAGE("Slugma's Weak Armor sharply raised its Speed!"); + if (move == MOVE_KNOCK_OFF) { + MESSAGE("The opposing Wobbuffet knocked off Slugma's White Herb!"); + } else if (move == MOVE_THIEF) { + MESSAGE("The opposing Wobbuffet stole Slugma's White Herb!"); + } + NONE_OF { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player); + MESSAGE("Wobbuffet returned its stats to normal using its White Herb!"); + } + } THEN { + EXPECT(player->statStages[STAT_DEF] = DEFAULT_STAT_STAGE - 1); + EXPECT(player->statStages[STAT_SPEED] = DEFAULT_STAT_STAGE + 1); + } +} + +SINGLE_BATTLE_TEST("White Herb wont have time to activate if Magician steals it") +{ + GIVEN { + PLAYER(SPECIES_SLUGMA) { Ability(ABILITY_WEAK_ARMOR); Item(ITEM_WHITE_HERB); } + OPPONENT(SPECIES_FENNEKIN) { Ability(ABILITY_MAGICIAN); } + } WHEN { + TURN { MOVE(opponent, MOVE_SCRATCH); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SCRATCH, opponent); + ABILITY_POPUP(player, ABILITY_WEAK_ARMOR); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); + MESSAGE("Slugma's Weak Armor lowered its Defense!"); + MESSAGE("Slugma's Weak Armor sharply raised its Speed!"); + ABILITY_POPUP(opponent, ABILITY_MAGICIAN); + MESSAGE("The opposing Fennekin stole Slugma's White Herb!"); + NONE_OF { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player); + MESSAGE("Wobbuffet returned its stats to normal using its White Herb!"); + } + } THEN { + EXPECT(player->statStages[STAT_DEF] = DEFAULT_STAT_STAGE - 1); + EXPECT(player->statStages[STAT_SPEED] = DEFAULT_STAT_STAGE + 1); + } +} + +SINGLE_BATTLE_TEST("White Herb has correct interactions with Intimidate triggered Defiant and Competitive") +{ + u16 species; + enum Ability ability; + + PARAMETRIZE { species = SPECIES_IGGLYBUFF; ability = ABILITY_COMPETITIVE; } + PARAMETRIZE { species = SPECIES_MANKEY; ability = ABILITY_DEFIANT; } + + GIVEN { + PLAYER(species) { Ability(ability); Item(ITEM_WHITE_HERB); } + OPPONENT(SPECIES_ARBOK) { Ability(ABILITY_INTIMIDATE); } + } WHEN { + TURN { ; } + } SCENE { + ABILITY_POPUP(opponent, ABILITY_INTIMIDATE); + ABILITY_POPUP(player, ability); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); + // Defiant activates first, so White Herb doesn't have a chance to trigger. + if (ability == ABILITY_COMPETITIVE) { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player); + MESSAGE("Igglybuff returned its stats to normal using its White Herb!"); + } + } THEN { + if (ability == ABILITY_COMPETITIVE) { + EXPECT(player->item == ITEM_NONE); + EXPECT(player->statStages[STAT_ATK] = DEFAULT_STAT_STAGE); + EXPECT(player->statStages[STAT_SPATK] = DEFAULT_STAT_STAGE + 2); + } else { + EXPECT(player->statStages[STAT_ATK] = DEFAULT_STAT_STAGE + 1); + } + } +} + +DOUBLE_BATTLE_TEST("White Herb is correctly displayed") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_WYNAUT) { Item(ITEM_WHITE_HERB); } + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WYNAUT); + } WHEN { + TURN { MOVE(playerRight, MOVE_SUPERPOWER, target: opponentRight); } + } SCENE { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, playerRight); + MESSAGE("Wynaut returned its stats to normal using its White Herb!"); + } THEN { + EXPECT(playerLeft->item == ITEM_NONE); + EXPECT(playerLeft->statStages[STAT_DEF] = DEFAULT_STAT_STAGE); + } +} diff --git a/test/battle/hold_effect/wide_lens.c b/test/battle/hold_effect/wide_lens.c new file mode 100644 index 0000000000..bcf49f559c --- /dev/null +++ b/test/battle/hold_effect/wide_lens.c @@ -0,0 +1,4 @@ +#include "global.h" +#include "test/battle.h" + +TO_DO_BATTLE_TEST("TODO: Write Wide Lens (Hold Effect) test titles") diff --git a/test/battle/hold_effect/wise_glasses.c b/test/battle/hold_effect/wise_glasses.c new file mode 100644 index 0000000000..6df63c9171 --- /dev/null +++ b/test/battle/hold_effect/wise_glasses.c @@ -0,0 +1,4 @@ +#include "global.h" +#include "test/battle.h" + +TO_DO_BATTLE_TEST("TODO: Write Wise Glasses (Hold Effect) test titles") diff --git a/test/battle/hold_effect/z_crystal.c b/test/battle/hold_effect/z_crystal.c new file mode 100644 index 0000000000..3c38b538dd --- /dev/null +++ b/test/battle/hold_effect/z_crystal.c @@ -0,0 +1,4 @@ +#include "global.h" +#include "test/battle.h" + +// Tests for Z-Crystals handled in test/battle/gimmick/zmove.c diff --git a/test/battle/hold_effect/zoom_lens.c b/test/battle/hold_effect/zoom_lens.c new file mode 100644 index 0000000000..6eded0dcb2 --- /dev/null +++ b/test/battle/hold_effect/zoom_lens.c @@ -0,0 +1,4 @@ +#include "global.h" +#include "test/battle.h" + +TO_DO_BATTLE_TEST("TODO: Write Zoom Lens (Hold Effect) test titles") diff --git a/test/battle/item_effect/cure_status.c b/test/battle/item_effect/cure_status.c index 919b4539af..79490b48dc 100644 --- a/test/battle/item_effect/cure_status.c +++ b/test/battle/item_effect/cure_status.c @@ -31,6 +31,29 @@ SINGLE_BATTLE_TEST("Antidote heals a battler from being poisoned") } } +DOUBLE_BATTLE_TEST("Antidote heals a battler from being poisoned (doubles)") +{ + u32 index; + struct BattlePokemon *user = NULL; + struct BattlePokemon *target = NULL; + PARAMETRIZE { index = 0; user = playerRight; target = playerLeft;} + PARAMETRIZE { index = 1; user = playerLeft; target = playerRight;} + PARAMETRIZE { index = 0; user = playerLeft; target = playerLeft;} + PARAMETRIZE { index = 1; user = playerRight; target = playerRight; } + + GIVEN { + ASSUME(gItemsInfo[ITEM_ANTIDOTE].battleUsage == EFFECT_ITEM_CURE_STATUS); + PLAYER(SPECIES_WOBBUFFET) { Status1(STATUS1_POISON); } + PLAYER(SPECIES_WYNAUT) { } + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WYNAUT); + } WHEN { + TURN { USE_ITEM(user, ITEM_ANTIDOTE, partyIndex: index); } + } THEN { + EXPECT_EQ(target->status1, STATUS1_NONE); + } +} + SINGLE_BATTLE_TEST("Antidote heals a battler from being badly poisoned") { GIVEN { @@ -135,6 +158,43 @@ SINGLE_BATTLE_TEST("Full Heal heals a battler from any primary status") } } +DOUBLE_BATTLE_TEST("Full Heal heals a battler from any primary status (doubles)") +{ + u32 statusParameters[7] = + { + STATUS1_SLEEP, + STATUS1_POISON, + STATUS1_BURN, + STATUS1_FREEZE, + STATUS1_PARALYSIS, + STATUS1_TOXIC_POISON, + STATUS1_FROSTBITE + }; + + u16 status = 0; + u32 index = 0; + struct BattlePokemon *user = NULL; + struct BattlePokemon *target = NULL; + for (u32 j = 0; j < 7; j++) + { + PARAMETRIZE {status = statusParameters[j]; user = playerRight; target = playerLeft; index = 0;} + PARAMETRIZE {status = statusParameters[j]; user = playerLeft; target = playerRight; index = 1;} + PARAMETRIZE {status = statusParameters[j]; user = playerLeft; target = playerLeft; index = 0;} + PARAMETRIZE {status = statusParameters[j]; user = playerRight; target = playerRight; index = 1;} + } + GIVEN { + ASSUME(gItemsInfo[ITEM_FULL_HEAL].battleUsage == EFFECT_ITEM_CURE_STATUS); + PLAYER(SPECIES_WOBBUFFET) { Status1(status); } + PLAYER(SPECIES_WYNAUT); + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WYNAUT); + } WHEN { + TURN { USE_ITEM(user, ITEM_FULL_HEAL, partyIndex: index); } + } THEN { + EXPECT_EQ(target->status1, STATUS1_NONE); + } +} + SINGLE_BATTLE_TEST("Heal Powder heals a battler from any primary status") { u16 status; @@ -158,6 +218,43 @@ SINGLE_BATTLE_TEST("Heal Powder heals a battler from any primary status") } } +DOUBLE_BATTLE_TEST("Heal Powder heals a battler from any primary status (doubles)") +{ + u32 statusParameters[7] = + { + STATUS1_SLEEP, + STATUS1_POISON, + STATUS1_BURN, + STATUS1_FREEZE, + STATUS1_PARALYSIS, + STATUS1_TOXIC_POISON, + STATUS1_FROSTBITE + }; + + u16 status = 0; + u32 index = 0; + struct BattlePokemon *user = NULL; + struct BattlePokemon *target = NULL; + for (u32 j = 0; j < 7; j++) + { + PARAMETRIZE {status = statusParameters[j]; user = playerRight; target = playerLeft; index = 0;} + PARAMETRIZE {status = statusParameters[j]; user = playerLeft; target = playerRight; index = 1;} + PARAMETRIZE {status = statusParameters[j]; user = playerLeft; target = playerLeft; index = 0;} + PARAMETRIZE {status = statusParameters[j]; user = playerRight; target = playerRight; index = 1;} + } + GIVEN { + ASSUME(gItemsInfo[ITEM_HEAL_POWDER].battleUsage == EFFECT_ITEM_CURE_STATUS); + PLAYER(SPECIES_WOBBUFFET) { Status1(status); } + PLAYER(SPECIES_WYNAUT); + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WYNAUT); + } WHEN { + TURN { USE_ITEM(user, ITEM_HEAL_POWDER, partyIndex: index); } + } THEN { + EXPECT_EQ(target->status1, STATUS1_NONE); + } +} + SINGLE_BATTLE_TEST("Pewter Crunchies heals a battler from any primary status") { u16 status; diff --git a/test/battle/item_effect/dire_hit.c b/test/battle/item_effect/dire_hit.c index 10b9a28a60..27f62e7d07 100644 --- a/test/battle/item_effect/dire_hit.c +++ b/test/battle/item_effect/dire_hit.c @@ -10,7 +10,7 @@ SINGLE_BATTLE_TEST("Dire Hit increases a battler's critical hit chance by 2 stag PARAMETRIZE { genConfig = j; chance = 2; } // 50% PASSES_RANDOMLY(1, chance, RNG_CRITICAL_HIT); GIVEN { - WITH_CONFIG(GEN_CONFIG_CRIT_CHANCE, genConfig); + WITH_CONFIG(CONFIG_CRIT_CHANCE, genConfig); ASSUME(gItemsInfo[ITEM_DIRE_HIT].battleUsage == EFFECT_ITEM_SET_FOCUS_ENERGY); PLAYER(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WOBBUFFET); diff --git a/test/battle/item_effect/heal_and_cure_status.c b/test/battle/item_effect/heal_and_cure_status.c index 99507df3cd..d85f11b33d 100644 --- a/test/battle/item_effect/heal_and_cure_status.c +++ b/test/battle/item_effect/heal_and_cure_status.c @@ -43,8 +43,8 @@ SINGLE_BATTLE_TEST("Full Restore restores a party members HP and cures any prima PARAMETRIZE { status = STATUS1_SLEEP; } PARAMETRIZE { status = STATUS1_NONE; } GIVEN { - PLAYER(SPECIES_WOBBUFFET) { HP(1); MaxHP(300); Status1(status); } - PLAYER(SPECIES_WYNAUT) { HP(1); MaxHP(300); Status1(status); } + PLAYER(SPECIES_WOBBUFFET) { HP(100); MaxHP(300); Status1(status); } + PLAYER(SPECIES_WYNAUT) { HP(100); MaxHP(300); Status1(status); } OPPONENT(SPECIES_WOBBUFFET); } WHEN { TURN { USE_ITEM(player, ITEM_FULL_RESTORE, partyIndex: 1); } diff --git a/test/battle/item_effect/increase_stat.c b/test/battle/item_effect/increase_stat.c index b56f1a2b84..227a638c6a 100644 --- a/test/battle/item_effect/increase_stat.c +++ b/test/battle/item_effect/increase_stat.c @@ -1,4 +1,5 @@ #include "global.h" +#include "overworld.h" #include "test/battle.h" #include "constants/item_effects.h" @@ -262,12 +263,13 @@ SINGLE_BATTLE_TEST("Max Mushrooms raises battler's Speed stat", s16 damage) SINGLE_BATTLE_TEST("Using X items in battle raises Friendship", s16 damage) { u32 startingFriendship; - u8 metLocation = MAPSEC_NONE; + u8 metLocation = GetCurrentRegionMapSectionId() + 1; + PARAMETRIZE { startingFriendship = 0; } PARAMETRIZE { startingFriendship = X_ITEM_MAX_FRIENDSHIP; } GIVEN { PLAYER(SPECIES_WOBBUFFET) { Friendship(startingFriendship); }; - // Set met location to MAPSEC_NONE to avoid getting the friendship boost + // Set met location to currentMapSec + 1 to avoid getting the friendship boost // from being met in the current map section SetMonData(&PLAYER_PARTY[0], MON_DATA_MET_LOCATION, &metLocation); OPPONENT(SPECIES_WOBBUFFET); @@ -280,3 +282,25 @@ SINGLE_BATTLE_TEST("Using X items in battle raises Friendship", s16 damage) EXPECT_EQ(player->friendship, X_ITEM_FRIENDSHIP_INCREASE); } } + +SINGLE_BATTLE_TEST("Using X items in battle where Pokemon was met raises Friendship with a bonus", s16 damage) +{ + u32 startingFriendship; + u8 metLocation = GetCurrentRegionMapSectionId(); + + PARAMETRIZE { startingFriendship = 0; } + PARAMETRIZE { startingFriendship = X_ITEM_MAX_FRIENDSHIP; } + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Friendship(startingFriendship); }; + // Set met location to currentMapSec to get the friendship boost + SetMonData(&PLAYER_PARTY[0], MON_DATA_MET_LOCATION, &metLocation); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { USE_ITEM(player, ITEM_X_ACCURACY); MOVE(opponent, MOVE_CELEBRATE); } + } THEN { + if (startingFriendship == X_ITEM_MAX_FRIENDSHIP) + EXPECT_EQ(player->friendship, X_ITEM_MAX_FRIENDSHIP); + else + EXPECT_EQ(player->friendship, (ITEM_FRIENDSHIP_MAPSEC_BONUS + X_ITEM_FRIENDSHIP_INCREASE)); + } +} diff --git a/test/battle/item_effect/revive.c b/test/battle/item_effect/revive.c index 9ff693fc30..df866edf0e 100644 --- a/test/battle/item_effect/revive.c +++ b/test/battle/item_effect/revive.c @@ -99,4 +99,128 @@ DOUBLE_BATTLE_TEST("Revive works for a partner in a double battle") } } +DOUBLE_BATTLE_TEST("Revive can trigger switch-in abilities") +{ + GIVEN { + PLAYER(SPECIES_ARBOK) { Ability(ABILITY_INTIMIDATE); HP(1); } + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WYNAUT); + } WHEN { + TURN { MOVE(opponentLeft, MOVE_SCRATCH, target: playerLeft); } + TURN { USE_ITEM(playerRight, ITEM_REVIVE, partyIndex: 0); SKIP_TURN(playerLeft); } + } SCENE { + ABILITY_POPUP(playerLeft, ABILITY_INTIMIDATE); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponentLeft); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponentRight); + ABILITY_POPUP(playerLeft, ABILITY_INTIMIDATE); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponentLeft); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponentRight); + } THEN { + EXPECT_EQ(opponentLeft->statStages[STAT_ATK], DEFAULT_STAT_STAGE - 2); + EXPECT_EQ(opponentRight->statStages[STAT_ATK], DEFAULT_STAT_STAGE - 2); + } +} + +DOUBLE_BATTLE_TEST("Revive does reset abilities") +{ + GIVEN { + PLAYER(SPECIES_ARBOK) { Ability(ABILITY_INTIMIDATE); HP(1); } + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WYNAUT); + } WHEN { + TURN { MOVE(opponentRight, MOVE_WORRY_SEED, target: playerLeft); MOVE(opponentLeft, MOVE_SCRATCH, target: playerLeft); } + TURN { USE_ITEM(playerRight, ITEM_REVIVE, partyIndex: 0); SKIP_TURN(playerLeft); MOVE(opponentRight, MOVE_SPORE, target: playerLeft);} + } SCENE { + ABILITY_POPUP(playerLeft, ABILITY_INTIMIDATE); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponentLeft); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponentRight); + ABILITY_POPUP(playerLeft, ABILITY_INTIMIDATE); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponentLeft); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponentRight); + } THEN { + EXPECT_EQ(opponentLeft->statStages[STAT_ATK], DEFAULT_STAT_STAGE - 2); + EXPECT_EQ(opponentRight->statStages[STAT_ATK], DEFAULT_STAT_STAGE - 2); + } +} + +DOUBLE_BATTLE_TEST("Revive does not grant a mon its pre-death status condition") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_WYNAUT) { Status1(STATUS1_SLEEP); HP(1); } + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WYNAUT); + } WHEN { + TURN { MOVE(opponentLeft, MOVE_SCRATCH, target: playerRight); } + TURN { USE_ITEM(playerLeft, ITEM_REVIVE, partyIndex: 1); SKIP_TURN(playerRight); } + } THEN { + EXPECT_EQ(opponentRight->status1, 0); + } +} + +DOUBLE_BATTLE_TEST("Revive does not grant a mon its pre-death stat change") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_WYNAUT) { HP(1); } + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WYNAUT); + } WHEN { + TURN { MOVE(playerRight, MOVE_SWORDS_DANCE); MOVE(opponentLeft, MOVE_SCRATCH, target: playerRight); } + TURN { USE_ITEM(playerLeft, ITEM_REVIVE, partyIndex: 1); SKIP_TURN(playerRight); } + } THEN { + EXPECT_EQ(playerRight->statStages[STAT_ATK], DEFAULT_STAT_STAGE); + } +} + +DOUBLE_BATTLE_TEST("Revive does not grant a mon its pre-death types") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_WYNAUT) { HP(1); } + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_POOCHYENA); + } WHEN { + TURN { MOVE(playerRight, MOVE_REFLECT_TYPE, target: opponentRight); MOVE(opponentLeft, MOVE_PSYSHOCK, target: playerRight); MOVE(opponentRight, MOVE_SCRATCH, target: playerRight); } + TURN { USE_ITEM(playerLeft, ITEM_MAX_REVIVE, partyIndex: 1); SKIP_TURN(playerRight); MOVE(opponentLeft, MOVE_PSYCHIC, target: playerRight);} + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_REFLECT_TYPE, playerRight); + NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_PSYSHOCK, opponentLeft); + ANIMATION(ANIM_TYPE_MOVE, MOVE_PSYCHIC, opponentLeft); + } THEN { + EXPECT_LT(playerRight->hp, playerRight->maxHP); + } +} + +DOUBLE_BATTLE_TEST("Revive force revived pokemon to replace absent battler immediately", s16 damage) +{ + u32 ability; + + PARAMETRIZE { ability = ABILITY_INTIMIDATE; } + PARAMETRIZE { ability = ABILITY_SHED_SKIN; } + + GIVEN { + PLAYER(SPECIES_WYNAUT) { HP(1); } + PLAYER(SPECIES_WOBBUFFET) { }; + PLAYER(SPECIES_ARBOK) { Ability(ability); HP(0) ;} ; + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WYNAUT); + } WHEN { + TURN { MOVE(opponentLeft, MOVE_SCRATCH, target: playerLeft);} + TURN { USE_ITEM(playerRight, ITEM_REVIVE, partyIndex: 2); SKIP_TURN(playerLeft); MOVE(opponentRight, MOVE_SCRATCH, target: playerRight); } + } SCENE { + if (ability == ABILITY_INTIMIDATE) + { + ABILITY_POPUP(playerLeft, ABILITY_INTIMIDATE); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponentRight); + } + ANIMATION(ANIM_TYPE_MOVE, MOVE_SCRATCH, opponentRight); + HP_BAR(playerRight, captureDamage: &results[i].damage); + } FINALLY { + EXPECT_MUL_EQ(results[0].damage, Q_4_12(1.5), results[1].damage); + } +} + TO_DO_BATTLE_TEST("Revive won't restore a battler's HP if it hasn't fainted") diff --git a/test/battle/move.c b/test/battle/move.c index f69c7b2eb4..f77e61aaf8 100644 --- a/test/battle/move.c +++ b/test/battle/move.c @@ -142,7 +142,7 @@ SINGLE_BATTLE_TEST("Critical hits deal 100% (Gen 1-5) or 50% (Gen 6+) more damag PARAMETRIZE { criticalHit = TRUE; genConfig = GEN_5; } PARAMETRIZE { criticalHit = TRUE; genConfig = GEN_6; } GIVEN { - WITH_CONFIG(GEN_CONFIG_CRIT_MULTIPLIER, genConfig); + WITH_CONFIG(CONFIG_CRIT_MULTIPLIER, genConfig); PLAYER(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WOBBUFFET); } WHEN { @@ -212,6 +212,50 @@ DOUBLE_BATTLE_TEST("Moves fail if they target the partner but they faint before } } +MULTI_BATTLE_TEST("Ally switch fails when used by either side in a multibattle") +{ + GIVEN { + MULTI_PLAYER(SPECIES_WOBBUFFET); + MULTI_PARTNER(SPECIES_WOBBUFFET); + MULTI_OPPONENT_A(SPECIES_WOBBUFFET); + MULTI_OPPONENT_B(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(playerLeft, MOVE_ALLY_SWITCH); MOVE(playerRight, MOVE_ALLY_SWITCH); MOVE(opponentLeft, MOVE_ALLY_SWITCH); MOVE(opponentRight, MOVE_ALLY_SWITCH); } + } SCENE { + NONE_OF { ANIMATION(ANIM_TYPE_MOVE, MOVE_ALLY_SWITCH, playerLeft); ANIMATION(ANIM_TYPE_MOVE, MOVE_ALLY_SWITCH, playerRight); ANIMATION(ANIM_TYPE_MOVE, MOVE_ALLY_SWITCH, opponentLeft); ANIMATION(ANIM_TYPE_MOVE, MOVE_ALLY_SWITCH, opponentRight); } + } +} + +TWO_VS_ONE_BATTLE_TEST("Ally switch can only be used by the opponent in a 2v1 battle") +{ + GIVEN { + MULTI_PLAYER(SPECIES_WOBBUFFET); + MULTI_PARTNER(SPECIES_WOBBUFFET); + MULTI_OPPONENT_A(SPECIES_WOBBUFFET); + MULTI_OPPONENT_A(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(playerLeft, MOVE_ALLY_SWITCH); MOVE(playerRight, MOVE_ALLY_SWITCH); MOVE(opponentLeft, MOVE_ALLY_SWITCH); } + } SCENE { + { ANIMATION(ANIM_TYPE_MOVE, MOVE_ALLY_SWITCH, opponentLeft); } + NONE_OF { ANIMATION(ANIM_TYPE_MOVE, MOVE_ALLY_SWITCH, playerLeft); ANIMATION(ANIM_TYPE_MOVE, MOVE_ALLY_SWITCH, playerRight); } + } +} + +ONE_VS_TWO_BATTLE_TEST("Ally switch can only be used by the player in a 1v2 battle") +{ + GIVEN { + MULTI_PLAYER(SPECIES_WOBBUFFET); + MULTI_PLAYER(SPECIES_WOBBUFFET); + MULTI_OPPONENT_A(SPECIES_WOBBUFFET); + MULTI_OPPONENT_B(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(playerLeft, MOVE_ALLY_SWITCH); MOVE(opponentLeft, MOVE_ALLY_SWITCH); MOVE(opponentRight, MOVE_ALLY_SWITCH); } + } SCENE { + { ANIMATION(ANIM_TYPE_MOVE, MOVE_ALLY_SWITCH, playerLeft); } + NONE_OF { ANIMATION(ANIM_TYPE_MOVE, MOVE_ALLY_SWITCH, opponentLeft); ANIMATION(ANIM_TYPE_MOVE, MOVE_ALLY_SWITCH, opponentRight); } + } +} + DOUBLE_BATTLE_TEST("Moves do not fail if an alive partner is the target") { GIVEN { diff --git a/test/battle/move_animations/all_anims.c b/test/battle/move_animations/all_anims.c index e69eb59750..c30f1c3a13 100644 --- a/test/battle/move_animations/all_anims.c +++ b/test/battle/move_animations/all_anims.c @@ -9,7 +9,7 @@ #define ANIM_TEST_END_MOVE MOVES_COUNT-1 // Last move to test -static void ParametrizeMovesAndSpecies(u32 j, u32 *pMove, u32 *pSpecies) +static void ParametrizeMovesAndSpecies(u32 j, u32 *pMove, u32 *pSpecies, u32 variation) { enum BattleMoveEffects effect = GetMoveEffect(j); if (effect == EFFECT_DARK_VOID) // User needs to be Darkrai @@ -59,6 +59,75 @@ static void ParametrizeMovesAndSpecies(u32 j, u32 *pMove, u32 *pSpecies) } } +static u32 ParametrizeFriendship(u32 move, u32 variation) +{ + if (gMovesInfo[move].effect == EFFECT_FRUSTRATION + || gMovesInfo[move].effect == EFFECT_RETURN + ) + { + if (variation == 0) + return 1; + else if (variation == 1) + return 61; + else if (variation == 2) + return 101; + else if (variation == 3) + return 201; + } + return 0; +} + +static u32 GetParametrizedHP(u32 move, u32 variation) +{ + if (gMovesInfo[move].effect == EFFECT_POWER_BASED_ON_USER_HP && variation > 0) + { + if (variation == 1) + return 6000; + else if (variation == 2) + return 4000; + else if (variation == 3) + return 2000; + } + return 9997; +} + +static u32 GetParametrizedItem(u32 move, u32 variation) +{ + if ((move == MOVE_TECHNO_BLAST) && variation > 0) + { + if (variation == 1) + return ITEM_DOUSE_DRIVE; + else if (variation == 2) + return ITEM_SHOCK_DRIVE; + else if (variation == 3) + return ITEM_BURN_DRIVE; + else if (variation == 4) + return ITEM_CHILL_DRIVE; + } + return ITEM_ORAN_BERRY; +} + +static u32 GetParametrizedLevel(u32 move, u32 variation) +{ + if (gMovesInfo[move].effect == EFFECT_LEVEL_DAMAGE && variation > 0) + { + if (variation == 1) + return 50; + else if (variation == 2) + return 20; + } + return 100; +} + +static bool32 GetParametrizedShinyness(u32 move, u32 variation) +{ + if ((gMovesInfo[move].effect == EFFECT_DRAGON_DARTS && variation == 2) + || (move == MOVE_SYRUP_BOMB && variation == 1) + ) + return TRUE; + return FALSE; +} + static bool32 TargetHasToMove(u32 move) // Opponent needs to hit the player first { enum BattleMoveEffects effect = GetMoveEffect(move); @@ -83,6 +152,7 @@ static bool32 AttackerHasToSwitch(u32 move) // User needs to send out a differen || effect == EFFECT_BATON_PASS || effect == EFFECT_MEMENTO || effect == EFFECT_HEALING_WISH + || effect == EFFECT_LUNAR_DANCE || effect == EFFECT_HIT_ESCAPE || effect == EFFECT_FINAL_GAMBIT || effect == EFFECT_PARTING_SHOT @@ -108,7 +178,37 @@ static bool32 UserHasToGoFirst(u32 move) // Player needs to go first return FALSE; } -static void WhenSingles(u32 move, struct BattlePokemon *attacker, struct BattlePokemon *defender) +static u32 GetVariationsNumber(u32 move, bool8 isDouble) +{ + u32 variationsNumber; + + if (gMovesInfo[move].effect == EFFECT_WEATHER_BALL + || gMovesInfo[move].effect == EFFECT_TERRAIN_PULSE + || move == MOVE_TECHNO_BLAST) + variationsNumber = 5; + else if (gMovesInfo[move].effect == EFFECT_FRUSTRATION + || gMovesInfo[move].effect == EFFECT_RETURN + || gMovesInfo[move].effect == EFFECT_IVY_CUDGEL + || move == MOVE_WATER_SPOUT) //we don't use the effect because other moves with the water spout effect don't have animation variations + variationsNumber = 4; + else if (gMovesInfo[move].effect == EFFECT_SPIT_UP + || gMovesInfo[move].effect == EFFECT_SWALLOW + || gMovesInfo[move].effect == EFFECT_DRAGON_DARTS + || move == MOVE_SEISMIC_TOSS) + variationsNumber = 3; + else if (gMovesInfo[move].effect == EFFECT_CURSE + || gMovesInfo[move].effect == EFFECT_PRESENT + || gMovesInfo[move].effect == EFFECT_SHELL_SIDE_ARM + || gMovesInfo[move].effect == EFFECT_FICKLE_BEAM + || gMovesInfo[move].effect == EFFECT_MAGNITUDE + || (isDouble && gMovesInfo[move].effect == EFFECT_TERA_STARSTORM) + || move == MOVE_SYRUP_BOMB) + variationsNumber = 2; + else + variationsNumber = 1; + return variationsNumber; +} +static void WhenSingles(u32 move, struct BattlePokemon *attacker, struct BattlePokemon *defender, u32 variation) { enum BattleMoveEffects effect = GetMoveEffect(move); // Setup turn @@ -120,7 +220,10 @@ static void WhenSingles(u32 move, struct BattlePokemon *attacker, struct BattleP else if (effect == EFFECT_SPIT_UP || effect == EFFECT_SWALLOW) { // attacker needs to have used Stockpile - TURN { MOVE(attacker, MOVE_STOCKPILE); } + for (u32 i = 0; i <= variation; i++) + { + TURN { MOVE(attacker, MOVE_STOCKPILE); } + } } else if ((effect == EFFECT_DOUBLE_POWER_ON_ARG_STATUS && GetMoveEffectArg_Status(move) == STATUS1_PARALYSIS)) { // defender needs to be paralyzed @@ -162,6 +265,32 @@ static void WhenSingles(u32 move, struct BattlePokemon *attacker, struct BattleP { // Needs a terrain TURN { MOVE(attacker, MOVE_ELECTRIC_TERRAIN); } } + else if (gMovesInfo[move].effect == EFFECT_WEATHER_BALL && variation > 0) + { + if (variation == 1) + TURN { MOVE(attacker, MOVE_SUNNY_DAY); } + else if (variation == 2) + TURN { MOVE(attacker, MOVE_RAIN_DANCE); } + else if (variation == 3) + TURN { MOVE(attacker, MOVE_SANDSTORM); } + else + TURN { MOVE(attacker, MOVE_HAIL); } + } + else if (gMovesInfo[move].effect == EFFECT_TERRAIN_PULSE && variation > 0) + { + if (variation == 1) + TURN { MOVE(attacker, MOVE_ELECTRIC_TERRAIN); } + else if (variation == 2) + TURN { MOVE(attacker, MOVE_GRASSY_TERRAIN); } + else if (variation == 3) + TURN { MOVE(attacker, MOVE_PSYCHIC_TERRAIN); } + else if (variation == 4) + TURN { MOVE(attacker, MOVE_MISTY_TERRAIN); } + } + else if (gBattleMoveEffects[gMovesInfo[move].effect].twoTurnEffect) + { + TURN { MOVE(attacker, move); } + } // Effective turn TURN { if (TargetHasToMove(move)) @@ -203,12 +332,62 @@ static void WhenSingles(u32 move, struct BattlePokemon *attacker, struct BattleP { MOVE(attacker, move, target: attacker); } + else if (gBattleMoveEffects[gMovesInfo[move].effect].twoTurnEffect) + { + MOVE(defender, MOVE_HELPING_HAND); + SKIP_TURN(attacker); + } + else if (gMovesInfo[move].effect == EFFECT_PRESENT) + { + if (variation == 0) + MOVE(attacker, move, WITH_RNG(RNG_PRESENT, 1)); + else if (variation == 1) + MOVE(attacker, move, WITH_RNG(RNG_PRESENT, 254)); + } + else if (gMovesInfo[move].effect == EFFECT_MAGNITUDE) + { + if (variation == 0) + MOVE(attacker, move, WITH_RNG(RNG_MAGNITUDE, 50)); + else if (variation == 1) + MOVE(attacker, move, WITH_RNG(RNG_MAGNITUDE, 99)); + } + else if (gMovesInfo[move].effect == EFFECT_FICKLE_BEAM) + { + if (variation == 0) + MOVE(attacker, move, WITH_RNG(RNG_FICKLE_BEAM, FALSE)); + else if (variation == 1) + MOVE(attacker, move, WITH_RNG(RNG_FICKLE_BEAM, TRUE)); + } + else if (gMovesInfo[move].effect == EFFECT_SHELL_SIDE_ARM) + { + if (variation == 0) + MOVE(attacker, move, WITH_RNG(RNG_SHELL_SIDE_ARM, FALSE)); + else if (variation == 1) + MOVE(attacker, move, WITH_RNG(RNG_SHELL_SIDE_ARM, TRUE)); + } else { // All other moves MOVE(defender, MOVE_HELPING_HAND); // Helping Hand, so there's no anim on the defender's side. MOVE(attacker, move); } } + if (gMovesInfo[move].effect == EFFECT_WISH) + { + TURN {}; + } + else if (gMovesInfo[move].effect == EFFECT_FUTURE_SIGHT) + { + TURN {}; + TURN {}; + } + else if (gMovesInfo[move].effect == EFFECT_ROLLOUT) + { + TURN {MOVE(attacker, move);}; + TURN {MOVE(attacker, move);}; + TURN {MOVE(attacker, move);}; + TURN {MOVE(attacker, move);}; + TURN {MOVE(attacker, MOVE_HELPING_HAND);}; + } } static void SceneSingles(u32 move, struct BattlePokemon *mon) @@ -239,7 +418,7 @@ static void SceneSingles(u32 move, struct BattlePokemon *mon) } } -static void DoublesWhen(u32 move, struct BattlePokemon *attacker, struct BattlePokemon *target, struct BattlePokemon *ignore1, struct BattlePokemon *ignore2) +static void DoublesWhen(u32 move, struct BattlePokemon *attacker, struct BattlePokemon *target, struct BattlePokemon *ignore1, struct BattlePokemon *ignore2, u32 variation) { enum BattleMoveEffects effect = GetMoveEffect(move); // Setup turn @@ -251,7 +430,10 @@ static void DoublesWhen(u32 move, struct BattlePokemon *attacker, struct BattleP else if (effect == EFFECT_SPIT_UP || effect == EFFECT_SWALLOW) { // Player needs to have used Stockpile - TURN { MOVE(attacker, MOVE_STOCKPILE); } + for (u32 i = 0; i <= variation; i++) + { + TURN { MOVE(attacker, MOVE_STOCKPILE); } + } } else if ((effect == EFFECT_DOUBLE_POWER_ON_ARG_STATUS && GetMoveEffectArg_Status(move) == STATUS1_PARALYSIS)) { // Opponent needs to be paralyzed @@ -293,6 +475,32 @@ static void DoublesWhen(u32 move, struct BattlePokemon *attacker, struct BattleP { // Needs a terrain TURN { MOVE(attacker, MOVE_ELECTRIC_TERRAIN); } } + else if (gMovesInfo[move].effect == EFFECT_WEATHER_BALL && variation > 0) + { + if (variation == 1) + TURN { MOVE(attacker, MOVE_SUNNY_DAY); } + else if (variation == 2) + TURN { MOVE(attacker, MOVE_RAIN_DANCE); } + else if (variation == 3) + TURN { MOVE(attacker, MOVE_SANDSTORM); } + else + TURN { MOVE(attacker, MOVE_HAIL); } + } + else if (gMovesInfo[move].effect == EFFECT_TERRAIN_PULSE && variation > 0) + { + if (variation == 1) + TURN { MOVE(attacker, MOVE_ELECTRIC_TERRAIN); } + else if (variation == 2) + TURN { MOVE(attacker, MOVE_GRASSY_TERRAIN); } + else if (variation == 3) + TURN { MOVE(attacker, MOVE_PSYCHIC_TERRAIN); } + else if (variation == 4) + TURN { MOVE(attacker, MOVE_MISTY_TERRAIN); } + } + else if (gBattleMoveEffects[gMovesInfo[move].effect].twoTurnEffect) + { + TURN { MOVE(attacker, move, target: target); } + } // Effective turn TURN { if (TargetHasToMove(move)) @@ -337,6 +545,39 @@ static void DoublesWhen(u32 move, struct BattlePokemon *attacker, struct BattleP MOVE(attacker, move, target: target); MOVE(target, MOVE_QUICK_ATTACK, target: attacker); } + else if (gBattleMoveEffects[gMovesInfo[move].effect].twoTurnEffect) + { + MOVE(target, MOVE_LAST_RESORT, target: attacker); + SKIP_TURN(attacker); + } + else if (gMovesInfo[move].effect == EFFECT_PRESENT) + { + if (variation == 0) + MOVE(attacker, move, target: target, WITH_RNG(RNG_PRESENT, 1)); + else if (variation == 1) + MOVE(attacker, move, target: target, WITH_RNG(RNG_PRESENT, 254)); + } + else if (gMovesInfo[move].effect == EFFECT_MAGNITUDE) + { + if (variation == 0) + MOVE(attacker, move, WITH_RNG(RNG_MAGNITUDE, 50)); + else if (variation == 1) + MOVE(attacker, move, WITH_RNG(RNG_MAGNITUDE, 99)); + } + else if (gMovesInfo[move].effect == EFFECT_FICKLE_BEAM) + { + if (variation == 0) + MOVE(attacker, move, target: target, WITH_RNG(RNG_FICKLE_BEAM, FALSE)); + else if (variation == 1) + MOVE(attacker, move, target: target, WITH_RNG(RNG_FICKLE_BEAM, TRUE)); + } + else if (gMovesInfo[move].effect == EFFECT_SHELL_SIDE_ARM) + { + if (variation == 0) + MOVE(attacker, move, target: target, WITH_RNG(RNG_SHELL_SIDE_ARM, FALSE)); + else if (variation == 1) + MOVE(attacker, move, target: target, WITH_RNG(RNG_SHELL_SIDE_ARM, TRUE)); + } else { // All other moves MOVE(target, MOVE_LAST_RESORT, target: attacker); // Last Resort, so there's no anim on the opponent's side. @@ -349,6 +590,23 @@ static void DoublesWhen(u32 move, struct BattlePokemon *attacker, struct BattleP MOVE(ignore2, MOVE_CELEBRATE); } } + if (gMovesInfo[move].effect == EFFECT_WISH) + { + TURN {}; + } + else if (gMovesInfo[move].effect == EFFECT_FUTURE_SIGHT) + { + TURN {}; + TURN {}; + } + else if (gMovesInfo[move].effect == EFFECT_ROLLOUT) + { + TURN {MOVE(attacker, move, target: target);}; + TURN {MOVE(attacker, move, target: target);}; + TURN {MOVE(attacker, move, target: target);}; + TURN {MOVE(attacker, move, target: target);}; + TURN {MOVE(attacker, MOVE_LAST_RESORT, target: attacker);}; + } } static void DoublesScene(u32 move, struct BattlePokemon *attacker) @@ -380,18 +638,27 @@ static void DoublesScene(u32 move, struct BattlePokemon *attacker) SINGLE_BATTLE_TEST("Move Animations don't leak when used - Singles (player to opponent)") { u32 j = ANIM_TEST_START_MOVE, move = 0, species = 0; + u32 k = 0, variation = 0, variationsNumber; + u32 friendship = 0, tempFriendship; u32 tempMove, tempSpecies; FORCE_MOVE_ANIM(TRUE); for (; j <= ANIM_TEST_END_MOVE; j++) { - ParametrizeMovesAndSpecies(j, &tempMove, &tempSpecies); - PARAMETRIZE { move = tempMove; species = tempSpecies; } + variationsNumber = GetVariationsNumber(j, FALSE); + for (k = 0; k < variationsNumber; k++) { + ParametrizeMovesAndSpecies(j, &tempMove, &tempSpecies, k); + tempFriendship = ParametrizeFriendship(j, k); + PARAMETRIZE { move = tempMove; species = tempSpecies; variation = k; friendship = tempFriendship;} + } } GIVEN { PLAYER(species) { - HP(9997); MaxHP(9999); Item(ITEM_ORAN_BERRY); + Level(GetParametrizedLevel(move, variation)); + HP(GetParametrizedHP(move, variation)); MaxHP(9999); Item(GetParametrizedItem(move, variation)); if (species == SPECIES_WOBBUFFET) Gender(MON_FEMALE); if (GetMoveEffect(move) == EFFECT_LAST_RESORT) Moves(move, MOVE_POUND); if (species == SPECIES_KLINKLANG) Ability(ABILITY_PLUS); + if (friendship) Friendship(friendship); + if (GetParametrizedShinyness(move, variation)) Shiny(TRUE); } PLAYER(SPECIES_WOBBUFFET) { Gender(MON_MALE); MaxHP(9999); Moves(MOVE_POUND); @@ -404,7 +671,7 @@ SINGLE_BATTLE_TEST("Move Animations don't leak when used - Singles (player to op } OPPONENT(SPECIES_WOBBUFFET) { Gender(MON_FEMALE); HP(9998); MaxHP(9999); SpDefense(9999); Defense(9999); } } WHEN { - WhenSingles(move, player, opponent); + WhenSingles(move, player, opponent, variation); } SCENE { SceneSingles(move, player); } THEN { @@ -419,18 +686,27 @@ SINGLE_BATTLE_TEST("Move Animations don't leak when used - Singles (player to op SINGLE_BATTLE_TEST("Move Animations don't leak when used - Singles (opponent to player)") { u32 j = ANIM_TEST_START_MOVE, move = 0, species = 0; + u32 k = 0, variation = 0, variationsNumber; + u32 friendship = 0, tempFriendship; u32 tempMove, tempSpecies; FORCE_MOVE_ANIM(TRUE); for (; j <= ANIM_TEST_END_MOVE; j++) { - ParametrizeMovesAndSpecies(j, &tempMove, &tempSpecies); - PARAMETRIZE { move = tempMove; species = tempSpecies; } + variationsNumber = GetVariationsNumber(j, FALSE); + for (k = 0; k < variationsNumber; k++) { + ParametrizeMovesAndSpecies(j, &tempMove, &tempSpecies, k); + tempFriendship = ParametrizeFriendship(j, k); + PARAMETRIZE { move = tempMove; species = tempSpecies; variation = k; friendship = tempFriendship;} + } } GIVEN { OPPONENT(species) { - HP(9997); MaxHP(9999); Item(ITEM_ORAN_BERRY); + Level(GetParametrizedLevel(move, variation)); + HP(GetParametrizedHP(move, variation)); MaxHP(9999); Item(GetParametrizedItem(move, variation)); if (species == SPECIES_WOBBUFFET) Gender(MON_FEMALE); if (GetMoveEffect(move) == EFFECT_LAST_RESORT) Moves(move, MOVE_POUND); if (species == SPECIES_KLINKLANG) Ability(ABILITY_PLUS); + if (friendship) Friendship(friendship); + if (GetParametrizedShinyness(move, variation)) Shiny(TRUE); } OPPONENT(SPECIES_WOBBUFFET) { Gender(MON_MALE); MaxHP(9999); Moves(MOVE_POUND); @@ -443,7 +719,7 @@ SINGLE_BATTLE_TEST("Move Animations don't leak when used - Singles (opponent to } PLAYER(SPECIES_WOBBUFFET) { Gender(MON_FEMALE); HP(9998); MaxHP(9999); SpDefense(9999); Defense(9999); } } WHEN { - WhenSingles(move, opponent, player); + WhenSingles(move, opponent, player, variation); } SCENE { SceneSingles(move, opponent); } THEN { @@ -458,6 +734,8 @@ SINGLE_BATTLE_TEST("Move Animations don't leak when used - Singles (opponent to DOUBLE_BATTLE_TEST("Move Animations don't leak when used - Doubles (playerLeft to opponentLeft)") { u32 j = ANIM_TEST_START_MOVE, move = 0, species = 0; + u32 k = 0, variation = 0, variationsNumber; + u32 friendship = 0, tempFriendship; u32 tempMove, tempSpecies; FORCE_MOVE_ANIM(TRUE); struct BattlePokemon *attacker = playerLeft; @@ -465,25 +743,35 @@ DOUBLE_BATTLE_TEST("Move Animations don't leak when used - Doubles (playerLeft t struct BattlePokemon *ignore1 = playerRight; struct BattlePokemon *ignore2 = opponentRight; for (; j <= ANIM_TEST_END_MOVE; j++) { - ParametrizeMovesAndSpecies(j, &tempMove, &tempSpecies); - PARAMETRIZE { move = tempMove; species = tempSpecies; } + variationsNumber = GetVariationsNumber(j, TRUE); + for (k = 0; k < variationsNumber; k++) { + ParametrizeMovesAndSpecies(j, &tempMove, &tempSpecies, k); + tempFriendship = ParametrizeFriendship(j, k); + PARAMETRIZE { move = tempMove; species = tempSpecies; variation = k; friendship = tempFriendship;} + } } GIVEN { PLAYER(species) { - HP(9997); MaxHP(9999); Item(ITEM_ORAN_BERRY); + Level(GetParametrizedLevel(move, variation)); + HP(GetParametrizedHP(move, variation)); MaxHP(9999); Item(GetParametrizedItem(move, variation)); if (attacker == playerLeft) { if (species == SPECIES_WOBBUFFET) Gender(MON_FEMALE); if (GetMoveEffect(move) == EFFECT_LAST_RESORT) Moves(move, MOVE_POUND); if (species == SPECIES_KLINKLANG) Ability(ABILITY_PLUS); + if (friendship) Friendship(friendship); + if (GetParametrizedShinyness(move, variation)) Shiny(TRUE); } } PLAYER(species) { - HP(9997); MaxHP(9999); Item(ITEM_ORAN_BERRY); + Level(GetParametrizedLevel(move, variation)); + HP(GetParametrizedHP(move, variation)); MaxHP(9999); Item(GetParametrizedItem(move, variation)); if (attacker == playerRight) { if (species == SPECIES_WOBBUFFET) Gender(MON_FEMALE); if (GetMoveEffect(move) == EFFECT_LAST_RESORT) Moves(move, MOVE_POUND); if (species == SPECIES_KLINKLANG) Ability(ABILITY_PLUS); + if (friendship) Friendship(friendship); + if (GetParametrizedShinyness(move, variation)) Shiny(TRUE); } } PLAYER(SPECIES_WOBBUFFET) { @@ -502,7 +790,7 @@ DOUBLE_BATTLE_TEST("Move Animations don't leak when used - Doubles (playerLeft t } OPPONENT(SPECIES_WOBBUFFET) { Gender(MON_FEMALE); HP(9998); MaxHP(9999); SpDefense(9999); Defense(9999); } } WHEN { - DoublesWhen(move, attacker, target, ignore1, ignore2); + DoublesWhen(move, attacker, target, ignore1, ignore2, variation); } SCENE { DoublesScene(move, attacker); } THEN { @@ -517,6 +805,8 @@ DOUBLE_BATTLE_TEST("Move Animations don't leak when used - Doubles (playerLeft t DOUBLE_BATTLE_TEST("Move Animations don't leak when used - Doubles (opponentLeft to playerLeft)") { u32 j = ANIM_TEST_START_MOVE, move = 0, species = 0; + u32 k = 0, variation = 0, variationsNumber; + u32 friendship = 0, tempFriendship; u32 tempMove, tempSpecies; FORCE_MOVE_ANIM(TRUE); struct BattlePokemon *attacker = opponentLeft; @@ -524,24 +814,34 @@ DOUBLE_BATTLE_TEST("Move Animations don't leak when used - Doubles (opponentLeft struct BattlePokemon *ignore1 = opponentRight; struct BattlePokemon *ignore2 = playerRight; for (; j <= ANIM_TEST_END_MOVE; j++) { - ParametrizeMovesAndSpecies(j, &tempMove, &tempSpecies); - PARAMETRIZE { move = tempMove; species = tempSpecies; } + variationsNumber = GetVariationsNumber(j, TRUE); + for (k = 0; k < variationsNumber; k++) { + ParametrizeMovesAndSpecies(j, &tempMove, &tempSpecies, k); + tempFriendship = ParametrizeFriendship(j, k); + PARAMETRIZE { move = tempMove; species = tempSpecies; variation = k; friendship = tempFriendship;} + } } GIVEN { OPPONENT(species) { - HP(9997); MaxHP(9999); Item(ITEM_ORAN_BERRY); + Level(GetParametrizedLevel(move, variation)); + HP(GetParametrizedHP(move, variation)); MaxHP(9999); Item(GetParametrizedItem(move, variation)); if (attacker == opponentLeft) { if (species == SPECIES_WOBBUFFET) Gender(MON_FEMALE); if (GetMoveEffect(move) == EFFECT_LAST_RESORT) Moves(move, MOVE_POUND); if (species == SPECIES_KLINKLANG) Ability(ABILITY_PLUS); + if (friendship) Friendship(friendship); + if (GetParametrizedShinyness(move, variation)) Shiny(TRUE); } } OPPONENT(species) { - HP(9997); MaxHP(9999); Item(ITEM_ORAN_BERRY); + Level(GetParametrizedLevel(move, variation)); + HP(GetParametrizedHP(move, variation)); MaxHP(9999); Item(GetParametrizedItem(move, variation)); if (attacker == opponentRight) { if (species == SPECIES_WOBBUFFET) Gender(MON_FEMALE); if (GetMoveEffect(move) == EFFECT_LAST_RESORT) Moves(move, MOVE_POUND); if (species == SPECIES_KLINKLANG) Ability(ABILITY_PLUS); + if (friendship) Friendship(friendship); + if (GetParametrizedShinyness(move, variation)) Shiny(TRUE); } } OPPONENT(SPECIES_WOBBUFFET) { @@ -562,7 +862,7 @@ DOUBLE_BATTLE_TEST("Move Animations don't leak when used - Doubles (opponentLeft } PLAYER(SPECIES_WOBBUFFET) { Gender(MON_FEMALE); HP(9998); MaxHP(9999); SpDefense(9999); Defense(9999); } } WHEN { - DoublesWhen(move, attacker, target, ignore1, ignore2); + DoublesWhen(move, attacker, target, ignore1, ignore2, variation); } SCENE { DoublesScene(move, attacker); } THEN { @@ -577,6 +877,8 @@ DOUBLE_BATTLE_TEST("Move Animations don't leak when used - Doubles (opponentLeft DOUBLE_BATTLE_TEST("Move Animations don't leak when used - Doubles (playerLeft to opponentRight)") { u32 j = ANIM_TEST_START_MOVE, move = 0, species = 0; + u32 k = 0, variation = 0, variationsNumber; + u32 friendship = 0, tempFriendship; u32 tempMove, tempSpecies; FORCE_MOVE_ANIM(TRUE); struct BattlePokemon *attacker = playerLeft; @@ -584,24 +886,34 @@ DOUBLE_BATTLE_TEST("Move Animations don't leak when used - Doubles (playerLeft t struct BattlePokemon *ignore1 = playerRight; struct BattlePokemon *ignore2 = opponentLeft; for (; j <= ANIM_TEST_END_MOVE; j++) { - ParametrizeMovesAndSpecies(j, &tempMove, &tempSpecies); - PARAMETRIZE { move = tempMove; species = tempSpecies; } + variationsNumber = GetVariationsNumber(j, TRUE); + for (k = 0; k < variationsNumber; k++) { + ParametrizeMovesAndSpecies(j, &tempMove, &tempSpecies, k); + tempFriendship = ParametrizeFriendship(j, k); + PARAMETRIZE { move = tempMove; species = tempSpecies; variation = k; friendship = tempFriendship;} + } } GIVEN { PLAYER(species) { - HP(9997); MaxHP(9999); Item(ITEM_ORAN_BERRY); + Level(GetParametrizedLevel(move, variation)); + HP(GetParametrizedHP(move, variation)); MaxHP(9999); Item(GetParametrizedItem(move, variation)); if (attacker == playerLeft) { if (species == SPECIES_WOBBUFFET) Gender(MON_FEMALE); if (GetMoveEffect(move) == EFFECT_LAST_RESORT) Moves(move, MOVE_POUND); if (species == SPECIES_KLINKLANG) Ability(ABILITY_PLUS); + if (friendship) Friendship(friendship); + if (GetParametrizedShinyness(move, variation)) Shiny(TRUE); } } PLAYER(species) { - HP(9997); MaxHP(9999); Item(ITEM_ORAN_BERRY); + Level(GetParametrizedLevel(move, variation)); + HP(GetParametrizedHP(move, variation)); MaxHP(9999); Item(GetParametrizedItem(move, variation)); if (attacker == playerRight) { if (species == SPECIES_WOBBUFFET) Gender(MON_FEMALE); if (GetMoveEffect(move) == EFFECT_LAST_RESORT) Moves(move, MOVE_POUND); if (species == SPECIES_KLINKLANG) Ability(ABILITY_PLUS); + if (friendship) Friendship(friendship); + if (GetParametrizedShinyness(move, variation)) Shiny(TRUE); } } PLAYER(SPECIES_WOBBUFFET) { @@ -622,7 +934,7 @@ DOUBLE_BATTLE_TEST("Move Animations don't leak when used - Doubles (playerLeft t } OPPONENT(SPECIES_WOBBUFFET) { Gender(MON_FEMALE); HP(9998); MaxHP(9999); SpDefense(9999); Defense(9999); } } WHEN { - DoublesWhen(move, attacker, target, ignore1, ignore2); + DoublesWhen(move, attacker, target, ignore1, ignore2, variation); } SCENE { DoublesScene(move, attacker); } THEN { @@ -637,6 +949,8 @@ DOUBLE_BATTLE_TEST("Move Animations don't leak when used - Doubles (playerLeft t DOUBLE_BATTLE_TEST("Move Animations don't leak when used - Doubles (opponentRight to playerLeft)") { u32 j = ANIM_TEST_START_MOVE, move = 0, species = 0; + u32 k = 0, variation = 0, variationsNumber; + u32 friendship = 0, tempFriendship; u32 tempMove, tempSpecies; FORCE_MOVE_ANIM(TRUE); struct BattlePokemon *attacker = opponentRight; @@ -644,24 +958,34 @@ DOUBLE_BATTLE_TEST("Move Animations don't leak when used - Doubles (opponentRigh struct BattlePokemon *ignore1 = opponentLeft; struct BattlePokemon *ignore2 = playerRight; for (; j <= ANIM_TEST_END_MOVE; j++) { - ParametrizeMovesAndSpecies(j, &tempMove, &tempSpecies); - PARAMETRIZE { move = tempMove; species = tempSpecies; } + variationsNumber = GetVariationsNumber(j, TRUE); + for (k = 0; k < variationsNumber; k++) { + ParametrizeMovesAndSpecies(j, &tempMove, &tempSpecies, k); + tempFriendship = ParametrizeFriendship(j, k); + PARAMETRIZE { move = tempMove; species = tempSpecies; variation = k; friendship = tempFriendship;} + } } GIVEN { OPPONENT(species) { - HP(9997); MaxHP(9999); Item(ITEM_ORAN_BERRY); + Level(GetParametrizedLevel(move, variation)); + HP(GetParametrizedHP(move, variation)); MaxHP(9999); Item(GetParametrizedItem(move, variation)); if (attacker == opponentLeft) { if (species == SPECIES_WOBBUFFET) Gender(MON_FEMALE); if (GetMoveEffect(move) == EFFECT_LAST_RESORT) Moves(move, MOVE_POUND); if (species == SPECIES_KLINKLANG) Ability(ABILITY_PLUS); + if (friendship) Friendship(friendship); + if (GetParametrizedShinyness(move, variation)) Shiny(TRUE); } } OPPONENT(species) { - HP(9997); MaxHP(9999); Item(ITEM_ORAN_BERRY); + Level(GetParametrizedLevel(move, variation)); + HP(GetParametrizedHP(move, variation)); MaxHP(9999); Item(GetParametrizedItem(move, variation)); if (attacker == opponentRight) { if (species == SPECIES_WOBBUFFET) Gender(MON_FEMALE); if (GetMoveEffect(move) == EFFECT_LAST_RESORT) Moves(move, MOVE_POUND); if (species == SPECIES_KLINKLANG) Ability(ABILITY_PLUS); + if (friendship) Friendship(friendship); + if (GetParametrizedShinyness(move, variation)) Shiny(TRUE); } } OPPONENT(SPECIES_WOBBUFFET) { @@ -682,7 +1006,7 @@ DOUBLE_BATTLE_TEST("Move Animations don't leak when used - Doubles (opponentRigh } PLAYER(SPECIES_WOBBUFFET) { Gender(MON_FEMALE); HP(9998); MaxHP(9999); SpDefense(9999); Defense(9999); } } WHEN { - DoublesWhen(move, attacker, target, ignore1, ignore2); + DoublesWhen(move, attacker, target, ignore1, ignore2, variation); } SCENE { DoublesScene(move, attacker); } THEN { @@ -697,6 +1021,8 @@ DOUBLE_BATTLE_TEST("Move Animations don't leak when used - Doubles (opponentRigh DOUBLE_BATTLE_TEST("Move Animations don't leak when used - Doubles (playerRight to opponentLeft)") { u32 j = ANIM_TEST_START_MOVE, move = 0, species = 0; + u32 k = 0, variation = 0, variationsNumber; + u32 friendship = 0, tempFriendship; u32 tempMove, tempSpecies; FORCE_MOVE_ANIM(TRUE); struct BattlePokemon *attacker = playerRight; @@ -704,24 +1030,34 @@ DOUBLE_BATTLE_TEST("Move Animations don't leak when used - Doubles (playerRight struct BattlePokemon *ignore1 = playerLeft; struct BattlePokemon *ignore2 = opponentRight; for (; j <= ANIM_TEST_END_MOVE; j++) { - ParametrizeMovesAndSpecies(j, &tempMove, &tempSpecies); - PARAMETRIZE { move = tempMove; species = tempSpecies; } + variationsNumber = GetVariationsNumber(j, TRUE); + for (k = 0; k < variationsNumber; k++) { + ParametrizeMovesAndSpecies(j, &tempMove, &tempSpecies, k); + tempFriendship = ParametrizeFriendship(j, k); + PARAMETRIZE { move = tempMove; species = tempSpecies; variation = k; friendship = tempFriendship;} + } } GIVEN { PLAYER(species) { - HP(9997); MaxHP(9999); Item(ITEM_ORAN_BERRY); + Level(GetParametrizedLevel(move, variation)); + HP(GetParametrizedHP(move, variation)); MaxHP(9999); Item(GetParametrizedItem(move, variation)); if (attacker == playerLeft) { if (species == SPECIES_WOBBUFFET) Gender(MON_FEMALE); if (GetMoveEffect(move) == EFFECT_LAST_RESORT) Moves(move, MOVE_POUND); if (species == SPECIES_KLINKLANG) Ability(ABILITY_PLUS); + if (friendship) Friendship(friendship); + if (GetParametrizedShinyness(move, variation)) Shiny(TRUE); } } PLAYER(species) { - HP(9997); MaxHP(9999); Item(ITEM_ORAN_BERRY); + Level(GetParametrizedLevel(move, variation)); + HP(GetParametrizedHP(move, variation)); MaxHP(9999); Item(GetParametrizedItem(move, variation)); if (attacker == playerRight) { if (species == SPECIES_WOBBUFFET) Gender(MON_FEMALE); if (GetMoveEffect(move) == EFFECT_LAST_RESORT) Moves(move, MOVE_POUND); if (species == SPECIES_KLINKLANG) Ability(ABILITY_PLUS); + if (friendship) Friendship(friendship); + if (GetParametrizedShinyness(move, variation)) Shiny(TRUE); } } PLAYER(SPECIES_WOBBUFFET) { @@ -742,7 +1078,7 @@ DOUBLE_BATTLE_TEST("Move Animations don't leak when used - Doubles (playerRight } OPPONENT(SPECIES_WOBBUFFET) { Gender(MON_FEMALE); HP(9998); MaxHP(9999); SpDefense(9999); Defense(9999); } } WHEN { - DoublesWhen(move, attacker, target, ignore1, ignore2); + DoublesWhen(move, attacker, target, ignore1, ignore2, variation); } SCENE { DoublesScene(move, attacker); } THEN { @@ -757,6 +1093,8 @@ DOUBLE_BATTLE_TEST("Move Animations don't leak when used - Doubles (playerRight DOUBLE_BATTLE_TEST("Move Animations don't leak when used - Doubles (opponentLeft to playerRight)") { u32 j = ANIM_TEST_START_MOVE, move = 0, species = 0; + u32 k = 0, variation = 0, variationsNumber; + u32 friendship = 0, tempFriendship; u32 tempMove, tempSpecies; FORCE_MOVE_ANIM(TRUE); struct BattlePokemon *attacker = opponentLeft; @@ -764,24 +1102,34 @@ DOUBLE_BATTLE_TEST("Move Animations don't leak when used - Doubles (opponentLeft struct BattlePokemon *ignore1 = playerLeft; struct BattlePokemon *ignore2 = opponentRight; for (; j <= ANIM_TEST_END_MOVE; j++) { - ParametrizeMovesAndSpecies(j, &tempMove, &tempSpecies); - PARAMETRIZE { move = tempMove; species = tempSpecies; } + variationsNumber = GetVariationsNumber(j, TRUE); + for (k = 0; k < variationsNumber; k++) { + ParametrizeMovesAndSpecies(j, &tempMove, &tempSpecies, k); + tempFriendship = ParametrizeFriendship(j, k); + PARAMETRIZE { move = tempMove; species = tempSpecies; variation = k; friendship = tempFriendship;} + } } GIVEN { OPPONENT(species) { - HP(9997); MaxHP(9999); Item(ITEM_ORAN_BERRY); + Level(GetParametrizedLevel(move, variation)); + HP(GetParametrizedHP(move, variation)); MaxHP(9999); Item(GetParametrizedItem(move, variation)); if (attacker == opponentLeft) { if (species == SPECIES_WOBBUFFET) Gender(MON_FEMALE); if (GetMoveEffect(move) == EFFECT_LAST_RESORT) Moves(move, MOVE_POUND); if (species == SPECIES_KLINKLANG) Ability(ABILITY_PLUS); + if (friendship) Friendship(friendship); + if (GetParametrizedShinyness(move, variation)) Shiny(TRUE); } } OPPONENT(species) { - HP(9997); MaxHP(9999); Item(ITEM_ORAN_BERRY); + Level(GetParametrizedLevel(move, variation)); + HP(GetParametrizedHP(move, variation)); MaxHP(9999); Item(GetParametrizedItem(move, variation)); if (attacker == opponentRight) { if (species == SPECIES_WOBBUFFET) Gender(MON_FEMALE); if (GetMoveEffect(move) == EFFECT_LAST_RESORT) Moves(move, MOVE_POUND); if (species == SPECIES_KLINKLANG) Ability(ABILITY_PLUS); + if (friendship) Friendship(friendship); + if (GetParametrizedShinyness(move, variation)) Shiny(TRUE); } } OPPONENT(SPECIES_WOBBUFFET) { @@ -802,7 +1150,7 @@ DOUBLE_BATTLE_TEST("Move Animations don't leak when used - Doubles (opponentLeft } PLAYER(SPECIES_WOBBUFFET) { Gender(MON_FEMALE); HP(9998); MaxHP(9999); SpDefense(9999); Defense(9999); } } WHEN { - DoublesWhen(move, attacker, target, ignore1, ignore2); + DoublesWhen(move, attacker, target, ignore1, ignore2, variation); } SCENE { DoublesScene(move, attacker); } THEN { @@ -817,6 +1165,8 @@ DOUBLE_BATTLE_TEST("Move Animations don't leak when used - Doubles (opponentLeft DOUBLE_BATTLE_TEST("Move Animations don't leak when used - Doubles (playerRight to opponentRight)") { u32 j = ANIM_TEST_START_MOVE, move = 0, species = 0; + u32 k = 0, variation = 0, variationsNumber; + u32 friendship = 0, tempFriendship; u32 tempMove, tempSpecies; FORCE_MOVE_ANIM(TRUE); struct BattlePokemon *attacker = playerRight; @@ -824,24 +1174,34 @@ DOUBLE_BATTLE_TEST("Move Animations don't leak when used - Doubles (playerRight struct BattlePokemon *ignore1 = playerLeft; struct BattlePokemon *ignore2 = opponentLeft; for (; j <= ANIM_TEST_END_MOVE; j++) { - ParametrizeMovesAndSpecies(j, &tempMove, &tempSpecies); - PARAMETRIZE { move = tempMove; species = tempSpecies; } + variationsNumber = GetVariationsNumber(j, TRUE); + for (k = 0; k < variationsNumber; k++) { + ParametrizeMovesAndSpecies(j, &tempMove, &tempSpecies, k); + tempFriendship = ParametrizeFriendship(j, k); + PARAMETRIZE { move = tempMove; species = tempSpecies; variation = k; friendship = tempFriendship;} + } } GIVEN { PLAYER(species) { - HP(9997); MaxHP(9999); Item(ITEM_ORAN_BERRY); + Level(GetParametrizedLevel(move, variation)); + HP(GetParametrizedHP(move, variation)); MaxHP(9999); Item(GetParametrizedItem(move, variation)); if (attacker == playerLeft) { if (species == SPECIES_WOBBUFFET) Gender(MON_FEMALE); if (GetMoveEffect(move) == EFFECT_LAST_RESORT) Moves(move, MOVE_POUND); if (species == SPECIES_KLINKLANG) Ability(ABILITY_PLUS); + if (friendship) Friendship(friendship); + if (GetParametrizedShinyness(move, variation)) Shiny(TRUE); } } PLAYER(species) { - HP(9997); MaxHP(9999); Item(ITEM_ORAN_BERRY); + Level(GetParametrizedLevel(move, variation)); + HP(GetParametrizedHP(move, variation)); MaxHP(9999); Item(GetParametrizedItem(move, variation)); if (attacker == playerRight) { if (species == SPECIES_WOBBUFFET) Gender(MON_FEMALE); if (GetMoveEffect(move) == EFFECT_LAST_RESORT) Moves(move, MOVE_POUND); if (species == SPECIES_KLINKLANG) Ability(ABILITY_PLUS); + if (friendship) Friendship(friendship); + if (GetParametrizedShinyness(move, variation)) Shiny(TRUE); } } PLAYER(SPECIES_WOBBUFFET) { @@ -862,7 +1222,7 @@ DOUBLE_BATTLE_TEST("Move Animations don't leak when used - Doubles (playerRight } OPPONENT(SPECIES_WOBBUFFET) { Gender(MON_FEMALE); HP(9998); MaxHP(9999); SpDefense(9999); Defense(9999); } } WHEN { - DoublesWhen(move, attacker, target, ignore1, ignore2); + DoublesWhen(move, attacker, target, ignore1, ignore2, variation); } SCENE { DoublesScene(move, attacker); } THEN { @@ -877,6 +1237,8 @@ DOUBLE_BATTLE_TEST("Move Animations don't leak when used - Doubles (playerRight DOUBLE_BATTLE_TEST("Move Animations don't leak when used - Doubles (opponentRight to playerRight)") { u32 j = ANIM_TEST_START_MOVE, move = 0, species = 0; + u32 k = 0, variation = 0, variationsNumber; + u32 friendship = 0, tempFriendship; u32 tempMove, tempSpecies; FORCE_MOVE_ANIM(TRUE); struct BattlePokemon *attacker = opponentRight; @@ -884,24 +1246,34 @@ DOUBLE_BATTLE_TEST("Move Animations don't leak when used - Doubles (opponentRigh struct BattlePokemon *ignore1 = playerLeft; struct BattlePokemon *ignore2 = opponentLeft; for (; j <= ANIM_TEST_END_MOVE; j++) { - ParametrizeMovesAndSpecies(j, &tempMove, &tempSpecies); - PARAMETRIZE { move = tempMove; species = tempSpecies; } + variationsNumber = GetVariationsNumber(j, TRUE); + for (k = 0; k < variationsNumber; k++) { + ParametrizeMovesAndSpecies(j, &tempMove, &tempSpecies, k); + tempFriendship = ParametrizeFriendship(j, k); + PARAMETRIZE { move = tempMove; species = tempSpecies; variation = k; friendship = tempFriendship;} + } } GIVEN { OPPONENT(species) { - HP(9997); MaxHP(9999); Item(ITEM_ORAN_BERRY); + Level(GetParametrizedLevel(move, variation)); + HP(GetParametrizedHP(move, variation)); MaxHP(9999); Item(GetParametrizedItem(move, variation)); if (attacker == opponentLeft) { if (species == SPECIES_WOBBUFFET) Gender(MON_FEMALE); if (GetMoveEffect(move) == EFFECT_LAST_RESORT) Moves(move, MOVE_POUND); if (species == SPECIES_KLINKLANG) Ability(ABILITY_PLUS); + if (friendship) Friendship(friendship); + if (GetParametrizedShinyness(move, variation)) Shiny(TRUE); } } OPPONENT(species) { - HP(9997); MaxHP(9999); Item(ITEM_ORAN_BERRY); + Level(GetParametrizedLevel(move, variation)); + HP(GetParametrizedHP(move, variation)); MaxHP(9999); Item(GetParametrizedItem(move, variation)); if (attacker == opponentRight) { if (species == SPECIES_WOBBUFFET) Gender(MON_FEMALE); if (GetMoveEffect(move) == EFFECT_LAST_RESORT) Moves(move, MOVE_POUND); if (species == SPECIES_KLINKLANG) Ability(ABILITY_PLUS); + if (friendship) Friendship(friendship); + if (GetParametrizedShinyness(move, variation)) Shiny(TRUE); } } OPPONENT(SPECIES_WOBBUFFET) { @@ -922,7 +1294,7 @@ DOUBLE_BATTLE_TEST("Move Animations don't leak when used - Doubles (opponentRigh } PLAYER(SPECIES_WOBBUFFET) { Gender(MON_FEMALE); HP(9998); MaxHP(9999); SpDefense(9999); Defense(9999); } } WHEN { - DoublesWhen(move, attacker, target, ignore1, ignore2); + DoublesWhen(move, attacker, target, ignore1, ignore2, variation); } SCENE { DoublesScene(move, attacker); } THEN { @@ -945,7 +1317,7 @@ DOUBLE_BATTLE_TEST("Move Animations don't leak when used - Doubles (playerLeft t struct BattlePokemon *ignore1 = opponentRight; struct BattlePokemon *ignore2 = opponentLeft; for (; j <= ANIM_TEST_END_MOVE; j++) { - ParametrizeMovesAndSpecies(j, &tempMove, &tempSpecies); + ParametrizeMovesAndSpecies(j, &tempMove, &tempSpecies, 0); PARAMETRIZE { move = tempMove; species = tempSpecies; } } GIVEN { @@ -1004,7 +1376,7 @@ DOUBLE_BATTLE_TEST("Move Animations don't leak when used - Doubles (playerRight struct BattlePokemon *ignore1 = opponentRight; struct BattlePokemon *ignore2 = opponentLeft; for (; j <= ANIM_TEST_END_MOVE; j++) { - ParametrizeMovesAndSpecies(j, &tempMove, &tempSpecies); + ParametrizeMovesAndSpecies(j, &tempMove, &tempSpecies, 0); PARAMETRIZE { move = tempMove; species = tempSpecies; } } GIVEN { @@ -1063,7 +1435,7 @@ DOUBLE_BATTLE_TEST("Move Animations don't leak when used - Doubles (opponentleft struct BattlePokemon *ignore1 = playerLeft; struct BattlePokemon *ignore2 = playerRight; for (; j <= ANIM_TEST_END_MOVE; j++) { - ParametrizeMovesAndSpecies(j, &tempMove, &tempSpecies); + ParametrizeMovesAndSpecies(j, &tempMove, &tempSpecies, 0); PARAMETRIZE { move = tempMove; species = tempSpecies; } } GIVEN { @@ -1122,7 +1494,7 @@ DOUBLE_BATTLE_TEST("Move Animations don't leak when used - Doubles (opponentRigh struct BattlePokemon *ignore1 = playerLeft; struct BattlePokemon *ignore2 = playerRight; for (; j <= ANIM_TEST_END_MOVE; j++) { - ParametrizeMovesAndSpecies(j, &tempMove, &tempSpecies); + ParametrizeMovesAndSpecies(j, &tempMove, &tempSpecies, 0); PARAMETRIZE { move = tempMove; species = tempSpecies; } } GIVEN { @@ -1175,18 +1547,27 @@ DOUBLE_BATTLE_TEST("Move Animations don't leak when used - Doubles (opponentRigh SINGLE_BATTLE_TEST("Move Animations occur before their stat change animations - Singles (player to opponent)") { u32 j = ANIM_TEST_START_MOVE, move = 0, species = 0; + u32 k = 0, variation = 0, variationsNumber; + u32 friendship = 0, tempFriendship; u32 tempMove, tempSpecies; FORCE_MOVE_ANIM(TRUE); for (; j <= ANIM_TEST_END_MOVE; j++) { - ParametrizeMovesAndSpecies(j, &tempMove, &tempSpecies); - PARAMETRIZE { move = tempMove; species = tempSpecies; } + variationsNumber = GetVariationsNumber(j, FALSE); + for (k = 0; k < variationsNumber; k++) { + ParametrizeMovesAndSpecies(j, &tempMove, &tempSpecies, k); + tempFriendship = ParametrizeFriendship(j, k); + PARAMETRIZE { move = tempMove; species = tempSpecies; variation = k; friendship = tempFriendship;} + } } GIVEN { PLAYER(species) { - HP(9997); MaxHP(9999); Item(ITEM_ORAN_BERRY); + Level(GetParametrizedLevel(move, variation)); + HP(GetParametrizedHP(move, variation)); MaxHP(9999); Item(GetParametrizedItem(move, variation)); if (species == SPECIES_WOBBUFFET) Gender(MON_FEMALE); if (GetMoveEffect(move) == EFFECT_LAST_RESORT) Moves(move, MOVE_POUND); if (species == SPECIES_KLINKLANG) Ability(ABILITY_PLUS); + if (friendship) Friendship(friendship); + if (GetParametrizedShinyness(move, variation)) Shiny(TRUE); } PLAYER(SPECIES_WOBBUFFET) { Gender(MON_MALE); MaxHP(9999); Moves(MOVE_POUND); @@ -1199,7 +1580,7 @@ SINGLE_BATTLE_TEST("Move Animations occur before their stat change animations - } OPPONENT(SPECIES_WOBBUFFET) { Gender(MON_FEMALE); HP(9998); MaxHP(9999); SpDefense(9999); Defense(9999); } } WHEN { - WhenSingles(move, player, opponent); + WhenSingles(move, player, opponent, variation); } SCENE { if (!(GetMoveEffect(move) == EFFECT_RECYCLE || GetMoveEffect(move) == EFFECT_BELCH diff --git a/test/battle/move_effect/absorb.c b/test/battle/move_effect/absorb.c index d497bc3f04..922d16fa0c 100644 --- a/test/battle/move_effect/absorb.c +++ b/test/battle/move_effect/absorb.c @@ -118,3 +118,17 @@ SINGLE_BATTLE_TEST("Absorb does not drain any HP if user does 0 damage") NOT MESSAGE("The opposing Wobbuffet had its energy drained!"); } } + +SINGLE_BATTLE_TEST("Absorb does not drain any HP if the move is blocked by Disguise") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { HP(1); } + OPPONENT(SPECIES_MIMIKYU) { Ability(ABILITY_DISGUISE); } + } WHEN { + TURN { MOVE(player, MOVE_ABSORB); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_ABSORB, player); + } THEN { + EXPECT_EQ(player->hp, 1); + } +} diff --git a/test/battle/move_effect/after_you.c b/test/battle/move_effect/after_you.c index 9d0464f72a..91742f4595 100644 --- a/test/battle/move_effect/after_you.c +++ b/test/battle/move_effect/after_you.c @@ -89,7 +89,7 @@ DOUBLE_BATTLE_TEST("After You calculates correct turn order if only one Pokémon DOUBLE_BATTLE_TEST("After You fails if the turn order remains the same after After You (Gen5-7)") { GIVEN { - WITH_CONFIG(GEN_CONFIG_AFTER_YOU_TURN_ORDER, GEN_7); + WITH_CONFIG(CONFIG_AFTER_YOU_TURN_ORDER, GEN_7); PLAYER(SPECIES_WOBBUFFET) { Speed(4); } PLAYER(SPECIES_WYNAUT) { Speed(1); } OPPONENT(SPECIES_WOBBUFFET) { Speed(2); } @@ -114,7 +114,7 @@ DOUBLE_BATTLE_TEST("After You fails if the turn order remains the same after Aft DOUBLE_BATTLE_TEST("After You doesn't fail if the turn order remains the same after After You (Gen8+)") { GIVEN { - WITH_CONFIG(GEN_CONFIG_AFTER_YOU_TURN_ORDER, GEN_8); + WITH_CONFIG(CONFIG_AFTER_YOU_TURN_ORDER, GEN_8); PLAYER(SPECIES_WOBBUFFET) { Speed(4); } PLAYER(SPECIES_WYNAUT) { Speed(1); } OPPONENT(SPECIES_WOBBUFFET) { Speed(2); } diff --git a/test/battle/move_effect/ally_switch.c b/test/battle/move_effect/ally_switch.c index 8300c7b9c8..9b0117afe1 100644 --- a/test/battle/move_effect/ally_switch.c +++ b/test/battle/move_effect/ally_switch.c @@ -92,7 +92,7 @@ DOUBLE_BATTLE_TEST("Ally Switch does not redirect the target of Snipe Shot") DOUBLE_BATTLE_TEST("Ally Switch does not redirect moves done by Pokémon with Stalwart and Propeller Tail") { - u16 ability; + enum Ability ability; PARAMETRIZE { ability = ABILITY_STALWART; } PARAMETRIZE { ability = ABILITY_PROPELLER_TAIL; } PARAMETRIZE { ability = ABILITY_TELEPATHY; } @@ -188,7 +188,7 @@ DOUBLE_BATTLE_TEST("Ally Switch doesn't make self-targeting status moves fail") DOUBLE_BATTLE_TEST("Ally Switch doesn't increase the Protect-like moves counter (Gen5-8)") { GIVEN { - WITH_CONFIG(GEN_ALLY_SWITCH_FAIL_CHANCE, GEN_8); + WITH_CONFIG(CONFIG_ALLY_SWITCH_FAIL_CHANCE, GEN_8); PLAYER(SPECIES_WOBBUFFET); PLAYER(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WOBBUFFET); @@ -203,7 +203,7 @@ DOUBLE_BATTLE_TEST("Ally Switch doesn't increase the Protect-like moves counter DOUBLE_BATTLE_TEST("Ally Switch increases the Protect-like moves counter (Gen9+)") { GIVEN { - WITH_CONFIG(GEN_ALLY_SWITCH_FAIL_CHANCE, GEN_9); + WITH_CONFIG(CONFIG_ALLY_SWITCH_FAIL_CHANCE, GEN_9); PLAYER(SPECIES_WOBBUFFET); PLAYER(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WOBBUFFET); diff --git a/test/battle/move_effect/assurance.c b/test/battle/move_effect/assurance.c index 6eccb48f3f..488740ec8f 100644 --- a/test/battle/move_effect/assurance.c +++ b/test/battle/move_effect/assurance.c @@ -1,11 +1,10 @@ #include "global.h" #include "test/battle.h" -TO_DO_BATTLE_TEST("Assurance doubles in power if the target has been damaged in the same turn - Recoil"); -TO_DO_BATTLE_TEST("Assurance doubles in power if the target has been damaged in the same turn - Life Orb"); -TO_DO_BATTLE_TEST("Assurance doubles in power if the target has been damaged in the same turn - Crash"); -TO_DO_BATTLE_TEST("Assurance doubles in power if the target has been damaged in the same turn - Confusion"); -TO_DO_BATTLE_TEST("Assurance doubles in power if the target has been damaged in the same turn - Rocky Helmet"); +ASSUMPTIONS +{ + ASSUME(GetMoveEffect(MOVE_ASSURANCE) == EFFECT_ASSURANCE); +} DOUBLE_BATTLE_TEST("Assurance doubles in power if False Swipe connected but didn't do any damage") { @@ -33,3 +32,31 @@ DOUBLE_BATTLE_TEST("Assurance doubles in power if False Swipe connected but didn EXPECT_MUL_EQ(hits[0], Q_4_12(2.0), hits[1]); } } + +SINGLE_BATTLE_TEST("Assurance doubles in power if the target has been damaged in the same turn - Life Orb") +{ + s16 hits[2]; + + GIVEN { + ASSUME(gItemsInfo[ITEM_LIFE_ORB].holdEffect == HOLD_EFFECT_LIFE_ORB); + PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_LIFE_ORB); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_CELEBRATE); MOVE(opponent, MOVE_ASSURANCE); } + TURN { MOVE(player, MOVE_POUND); MOVE(opponent, MOVE_ASSURANCE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_ASSURANCE, opponent); + HP_BAR(player, captureDamage: &hits[0]); + ANIMATION(ANIM_TYPE_MOVE, MOVE_POUND, player); + MESSAGE("Wobbuffet was hurt by the Life Orb!"); + HP_BAR(player, captureDamage: &hits[1]); + } THEN { + EXPECT_MUL_EQ(hits[0], Q_4_12(2.0), hits[1]); + } +} + +TO_DO_BATTLE_TEST("Assurance doubles in power if the target has been damaged in the same turn - Recoil"); +TO_DO_BATTLE_TEST("Assurance doubles in power if the target has been damaged in the same turn - Crash"); +TO_DO_BATTLE_TEST("Assurance doubles in power if the target has been damaged in the same turn - Confusion"); +TO_DO_BATTLE_TEST("Assurance doubles in power if the target has been damaged in the same turn - Rocky Helmet"); + diff --git a/test/battle/move_effect/aurora_veil.c b/test/battle/move_effect/aurora_veil.c index b57c85df06..1b480ad1ed 100644 --- a/test/battle/move_effect/aurora_veil.c +++ b/test/battle/move_effect/aurora_veil.c @@ -25,6 +25,35 @@ SINGLE_BATTLE_TEST("Aurora Veil can only be used in Hail and Snow") } } +SINGLE_BATTLE_TEST("Aurora Veil will prevent Protean activation if it fails due to no Snow/Hail") +{ + GIVEN { + PLAYER(SPECIES_KECLEON) { Ability(ABILITY_PROTEAN); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_AURORA_VEIL); } + } SCENE { + MESSAGE("But it failed!"); + NOT ABILITY_POPUP(player, ABILITY_PROTEAN); + } +} + +SINGLE_BATTLE_TEST("Aurora Veil wont prevent Protean activation when it fails due to being set up already") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_KECLEON) { Ability(ABILITY_PROTEAN); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_SNOWSCAPE); MOVE(player, MOVE_AURORA_VEIL); } + TURN { SWITCH(player, 1); } + TURN { MOVE(player, MOVE_AURORA_VEIL); } + } SCENE { + ABILITY_POPUP(player, ABILITY_PROTEAN); + MESSAGE("But it failed!"); + } +} + TO_DO_BATTLE_TEST("Aurora Veil reduces damage done to the user by half in singles") TO_DO_BATTLE_TEST("Aurora Veil reduces damage done to the user by roughly a third in doubles") TO_DO_BATTLE_TEST("Aurora Veil's damage reduction is ignored by Critical Hits") diff --git a/test/battle/move_effect/baddy_bad.c b/test/battle/move_effect/baddy_bad.c deleted file mode 100644 index e2ee4a6d84..0000000000 --- a/test/battle/move_effect/baddy_bad.c +++ /dev/null @@ -1,6 +0,0 @@ -#include "global.h" -#include "test/battle.h" - -TO_DO_BATTLE_TEST("Baddy Bad sets up Reflect, reducing physical damage"); -TO_DO_BATTLE_TEST("Baddy Bad's Reflect lasts for 5 turns"); -TO_DO_BATTLE_TEST("Baddy Bad can still damage the target when Reflect is already set up"); diff --git a/test/battle/move_effect/beak_blast.c b/test/battle/move_effect/beak_blast.c index b879a198c8..6e94a908e5 100644 --- a/test/battle/move_effect/beak_blast.c +++ b/test/battle/move_effect/beak_blast.c @@ -86,7 +86,7 @@ SINGLE_BATTLE_TEST("Beak Blast burns only when contact moves are used") PLAYER(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WOBBUFFET); } WHEN { - TURN { MOVE(player, MOVE_BEAK_BLAST); MOVE(opponent, move); } + TURN { MOVE(opponent, move); MOVE(player, MOVE_BEAK_BLAST); } TURN {} } SCENE { ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_BEAK_BLAST_SETUP, player); @@ -115,11 +115,11 @@ SINGLE_BATTLE_TEST("Beak Blast burns only when contact moves are used") SINGLE_BATTLE_TEST("Beak Blast doesn't burn fire types") { GIVEN { - ASSUME(gSpeciesInfo[SPECIES_ARCANINE].types[0] == TYPE_FIRE || gSpeciesInfo[SPECIES_ARCANINE].types[1]); + ASSUME(gSpeciesInfo[SPECIES_ARCANINE].types[0] == TYPE_FIRE || gSpeciesInfo[SPECIES_ARCANINE].types[1] == TYPE_FIRE); PLAYER(SPECIES_ARCANINE); OPPONENT(SPECIES_WOBBUFFET); } WHEN { - TURN { MOVE(opponent, MOVE_BEAK_BLAST); MOVE(player, MOVE_SCRATCH); } + TURN { MOVE(player, MOVE_SCRATCH); MOVE(opponent, MOVE_BEAK_BLAST); } } SCENE { ANIMATION(ANIM_TYPE_MOVE, MOVE_SCRATCH, player); NOT STATUS_ICON(player, burn: TRUE); @@ -127,6 +127,20 @@ SINGLE_BATTLE_TEST("Beak Blast doesn't burn fire types") } } +SINGLE_BATTLE_TEST("Beak Blast doesn't burn after being used") +{ + GIVEN { + ASSUME(GetMovePriority(MOVE_COUNTER) < GetMovePriority(MOVE_BEAK_BLAST)); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_BEAK_BLAST); MOVE(player, MOVE_COUNTER); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_BEAK_BLAST, opponent); + NOT STATUS_ICON(player, burn: TRUE); + } +} + TO_DO_BATTLE_TEST("Beak Blast's charging message is shown regardless if it would've missed"); TO_DO_BATTLE_TEST("Beak Blast fails if it's forced by Encore after choosing a different move"); TO_DO_BATTLE_TEST("Bulletproof is immune to Beak Blast but not to the burn it causes"); diff --git a/test/battle/move_effect/beat_up.c b/test/battle/move_effect/beat_up.c index e584ccc0f9..719772c38c 100644 --- a/test/battle/move_effect/beat_up.c +++ b/test/battle/move_effect/beat_up.c @@ -1,10 +1,18 @@ #include "global.h" #include "test/battle.h" -// General +// TODO: Beat Up's strikes have each an independent chance of a critical hit +// Unconfirmed by Bulbapedia +// - Technician interacion + SINGLE_BATTLE_TEST("Beat Up hits the target for each non-fainted, non-statused member in the party") { + u32 gen; + PARAMETRIZE { gen = GEN_3; } + PARAMETRIZE { gen = GEN_5; } + GIVEN { + WITH_CONFIG(CONFIG_BEAT_UP, gen); PLAYER(SPECIES_WOBBUFFET); PLAYER(SPECIES_WYNAUT); PLAYER(SPECIES_PICHU) @@ -21,37 +29,367 @@ SINGLE_BATTLE_TEST("Beat Up hits the target for each non-fainted, non-statused m NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_BEAT_UP, player); MESSAGE("The Pokémon was hit 4 time(s)!"); } THEN { - EXPECT_EQ(gBattleStruct->beatUpSpecies[0], SPECIES_WOBBUFFET); - EXPECT_EQ(gBattleStruct->beatUpSpecies[1], SPECIES_WYNAUT); - EXPECT_EQ(gBattleStruct->beatUpSpecies[2], SPECIES_PICHU); - EXPECT_EQ(gBattleStruct->beatUpSpecies[3], SPECIES_RAICHU); + if (gen == GEN_5) { + EXPECT_EQ(gBattleStruct->beatUpSpecies[0], SPECIES_WOBBUFFET); + EXPECT_EQ(gBattleStruct->beatUpSpecies[1], SPECIES_WYNAUT); + EXPECT_EQ(gBattleStruct->beatUpSpecies[2], SPECIES_PICHU); + EXPECT_EQ(gBattleStruct->beatUpSpecies[3], SPECIES_RAICHU); + } + else { + EXPECT_EQ(gBattleStruct->beatUpSpecies[0], 0); + EXPECT_EQ(gBattleStruct->beatUpSpecies[1], 1); + EXPECT_EQ(gBattleStruct->beatUpSpecies[2], 2); + EXPECT_EQ(gBattleStruct->beatUpSpecies[3], 4); + } } } -TO_DO_BATTLE_TEST("Beat Up doesn't consider Comatose as a status") -TO_DO_BATTLE_TEST("Beat Up's strikes have each an independent chance of a critical hit"); +SINGLE_BATTLE_TEST("Beat Up doesn't consider Comatose as a status") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_KOMALA) { Ability(ABILITY_COMATOSE); } + PLAYER(SPECIES_WYNAUT) { HP(0); } + PLAYER(SPECIES_WYNAUT) { Status1(STATUS1_POISON); } + PLAYER(SPECIES_WYNAUT) { Status1(STATUS1_SLEEP); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_BEAT_UP); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_BEAT_UP, player); + ANIMATION(ANIM_TYPE_MOVE, MOVE_BEAT_UP, player); + NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_BEAT_UP, player); + MESSAGE("The Pokémon was hit 2 time(s)!"); + } +} -// B_BEAT_UP Gen2-4 -TO_DO_BATTLE_TEST("Beat Up lists each party member's name"); -TO_DO_BATTLE_TEST("Beat Up's damage is typeless"); -TO_DO_BATTLE_TEST("Beat Up's damage doesn't consider STAB"); -TO_DO_BATTLE_TEST("Beat Up's last strike-only can trigger King's Rock"); -TO_DO_BATTLE_TEST("Beat Up's base power is the same for each strike"); -TO_DO_BATTLE_TEST("Beat Up's damage is determined by each striking Pokémon's base attack and level and the target's defense"); -TO_DO_BATTLE_TEST("Beat Up ignores stat stage changes"); //eg. Swords Dance -TO_DO_BATTLE_TEST("Beat Up ignores Huge Power"); -TO_DO_BATTLE_TEST("Beat Up ignores Choice Band"); +SINGLE_BATTLE_TEST("Beat Up doesn't list party member's name (Gen5+)") +{ + GIVEN { + WITH_CONFIG(CONFIG_BEAT_UP, GEN_5); + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_WYNAUT); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_BEAT_UP); } + } SCENE { + NONE_OF { + MESSAGE("Wobbuffet's attack!"); + MESSAGE("Wynaut's attack!"); + } + MESSAGE("The Pokémon was hit 2 time(s)!"); + } +} -// B_BEAT_UP Gen5+ -TO_DO_BATTLE_TEST("Beat Up doesn't list party member's name"); -TO_DO_BATTLE_TEST("Beat Up's damage is Dark-typed"); -TO_DO_BATTLE_TEST("Beat Up's damage receives STAB"); -TO_DO_BATTLE_TEST("Beat Up's can trigger King's Rock on all strikes"); -TO_DO_BATTLE_TEST("Beat Up's base power is determined by each striking Pokémon"); -TO_DO_BATTLE_TEST("Beat Up's damage is determined by the user's attack and the target's defense"); -TO_DO_BATTLE_TEST("Beat Up's damage considers stat stage changes"); //eg. Swords Dance -TO_DO_BATTLE_TEST("Beat Up's damage considers Huge Power"); -TO_DO_BATTLE_TEST("Beat Up's damage considers Choice Band"); +SINGLE_BATTLE_TEST("Beat Up's damage is Dark-typed (Gen5+)", s16 damage) +{ + bool32 targetIsFairy; + PARAMETRIZE { targetIsFairy = FALSE; } + PARAMETRIZE { targetIsFairy = TRUE; } -// Unconfirmed by Bulbapedia -// - Technician interacion + ASSUME(GetMoveType(MOVE_BEAT_UP) == TYPE_DARK); + GIVEN { + WITH_CONFIG(CONFIG_BEAT_UP, GEN_5); + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_WYNAUT); + OPPONENT(targetIsFairy ? SPECIES_SYLVEON : SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_BEAT_UP); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_BEAT_UP, player); + HP_BAR(opponent, captureDamage: &results[i].damage); + } THEN { + if (targetIsFairy) + EXPECT_LT(results[i].damage, results[0].damage); + } +} + +SINGLE_BATTLE_TEST("Beat Up's base power is determined by each striking Pokémon (Gen5+)") +{ + s16 firstHit, secondHit; + + GIVEN { + WITH_CONFIG(CONFIG_BEAT_UP, GEN_5); + PLAYER(SPECIES_SHUCKLE); + PLAYER(SPECIES_DEOXYS_ATTACK); + PLAYER(SPECIES_WYNAUT) { HP(0); } + PLAYER(SPECIES_WYNAUT) { HP(0); } + PLAYER(SPECIES_WYNAUT) { HP(0); } + OPPONENT(SPECIES_BLISSEY); + } WHEN { + TURN { MOVE(player, MOVE_BEAT_UP); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_BEAT_UP, player); + HP_BAR(opponent, captureDamage: &firstHit); + ANIMATION(ANIM_TYPE_MOVE, MOVE_BEAT_UP, player); + HP_BAR(opponent, captureDamage: &secondHit); + } THEN { + EXPECT_LT(firstHit, secondHit); + } +} + +SINGLE_BATTLE_TEST("Beat Up's damage considers stat stage changes (Gen5+)", s16 damage) +{ + bool32 boosted; + PARAMETRIZE { boosted = FALSE; } + PARAMETRIZE { boosted = TRUE; } + + GIVEN { + WITH_CONFIG(CONFIG_BEAT_UP, GEN_5); + PLAYER(SPECIES_UMBREON); + PLAYER(SPECIES_WYNAUT); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { if (boosted) { MOVE(player, MOVE_SWORDS_DANCE); } else { MOVE(player, MOVE_CELEBRATE); } } + TURN { MOVE(player, MOVE_BEAT_UP); } + } SCENE { + if (boosted) + ANIMATION(ANIM_TYPE_MOVE, MOVE_SWORDS_DANCE, player); + ANIMATION(ANIM_TYPE_MOVE, MOVE_BEAT_UP, player); + HP_BAR(opponent, captureDamage: &results[i].damage); + } THEN { + if (boosted) + EXPECT_GT(results[i].damage, results[0].damage); + } +} + +SINGLE_BATTLE_TEST("Beat Up's damage considers Huge Power and Choice Band (Gen5+)", s16 damage) +{ + u16 ability; + u16 item; + + PARAMETRIZE { ability = ABILITY_THICK_FAT; item = ITEM_NONE; } + PARAMETRIZE { ability = ABILITY_HUGE_POWER; item = ITEM_NONE; } + PARAMETRIZE { ability = ABILITY_THICK_FAT; item = ITEM_CHOICE_BAND; } + + GIVEN { + WITH_CONFIG(CONFIG_BEAT_UP, GEN_5); + PLAYER(SPECIES_AZUMARILL) { Ability(ability); Item(item); Moves(MOVE_BEAT_UP); } + PLAYER(SPECIES_WYNAUT); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_BEAT_UP); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_BEAT_UP, player); + HP_BAR(opponent, captureDamage: &results[i].damage); + } THEN { + if (i == 1) + EXPECT_GT(results[i].damage, results[0].damage); + if (i == 2) + EXPECT_GT(results[i].damage, results[0].damage); + } +} + +SINGLE_BATTLE_TEST("Beat Up lists each party member's name") +{ + GIVEN { + WITH_CONFIG(CONFIG_BEAT_UP, GEN_3); + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_WYNAUT); + PLAYER(SPECIES_WYNAUT) { HP(0); } + PLAYER(SPECIES_WYNAUT) { Status1(STATUS1_POISON); } + PLAYER(SPECIES_PIKACHU); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_BEAT_UP); } + } SCENE { + MESSAGE("Wobbuffet's attack!"); + MESSAGE("Wynaut's attack!"); + NOT MESSAGE("Wynaut's attack!"); + MESSAGE("Pikachu's attack!"); + } +} + +SINGLE_BATTLE_TEST("Beat Up's damage is typeless", s16 damage) +{ + u16 defender = SPECIES_WOBBUFFET; + u16 type1, type2; + + PARAMETRIZE { defender = SPECIES_BLISSEY; } // Normal + PARAMETRIZE { defender = SPECIES_MACHAMP; } // Fighting + PARAMETRIZE { defender = SPECIES_TORNADUS; } // Flying + PARAMETRIZE { defender = SPECIES_GRIMER; } // Poison + PARAMETRIZE { defender = SPECIES_SANDSHREW; } // Ground + PARAMETRIZE { defender = SPECIES_NOSEPASS; } // Rock + PARAMETRIZE { defender = SPECIES_CATERPIE; } // Bug + PARAMETRIZE { defender = SPECIES_DUSKULL; } // Ghost + PARAMETRIZE { defender = SPECIES_REGISTEEL; } // Steel + PARAMETRIZE { defender = SPECIES_CHIMCHAR; } // Fire + PARAMETRIZE { defender = SPECIES_WARTORTLE; } // Water + PARAMETRIZE { defender = SPECIES_TANGELA; } // Grass + PARAMETRIZE { defender = SPECIES_PIKACHU; } // Electric + PARAMETRIZE { defender = SPECIES_ABRA; } // Psychic + PARAMETRIZE { defender = SPECIES_SNORUNT; } // Ice + PARAMETRIZE { defender = SPECIES_BAGON; } // Dragon + PARAMETRIZE { defender = SPECIES_UMBREON; } // Dark + PARAMETRIZE { defender = SPECIES_SYLVEON; } // Fairy + + GIVEN { + WITH_CONFIG(CONFIG_BEAT_UP, GEN_3); + type1 = GetSpeciesType(defender, 0); + type2 = GetSpeciesType(defender, 1); + ASSUME(type2 == type1 || type2 == TYPE_MYSTERY); // Ensure monotype targets + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(defender); + } WHEN { + TURN { MOVE(player, MOVE_BEAT_UP); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_BEAT_UP, player); + HP_BAR(opponent, captureDamage: &results[i].damage); + NONE_OF { + MESSAGE("It's super effective!"); + MESSAGE("It's not very effective..."); + MESSAGE("It doesn't affect"); + } + } THEN { + EXPECT_GT(results[i].damage, 0); + } +} + +SINGLE_BATTLE_TEST("Beat Up's damage doesn't consider STAB") +{ + s16 damage; + GIVEN { + WITH_CONFIG(CONFIG_BEAT_UP, GEN_3); + damage = 0; + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_WYNAUT) { HP(0); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_BEAT_UP); } + } SCENE { + HP_BAR(opponent, captureDamage: &damage); + } THEN { + // Raw damage: baseAtk 33 * basePower 1 * levelFactor ((100 * 2 / 5) + 2 = 42) = 1386 + // Divide by baseDef 58 -> 23 (floor); 23/50 + 2 = 2; + u16 expected = 2; + EXPECT_EQ(damage, expected); + } +} + +SINGLE_BATTLE_TEST("Beat Up's base power is the same for each strike") +{ + s16 firstHit, secondHit; + GIVEN { + WITH_CONFIG(CONFIG_BEAT_UP, GEN_3); + firstHit = 0; + secondHit = 0; + PLAYER(SPECIES_WYNAUT); + PLAYER(SPECIES_WYNAUT); + PLAYER(SPECIES_WYNAUT) { HP(0); } + PLAYER(SPECIES_WYNAUT) { HP(0); } + PLAYER(SPECIES_WYNAUT) { HP(0); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_BEAT_UP); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_BEAT_UP, player); + HP_BAR(opponent, captureDamage: &firstHit); + ANIMATION(ANIM_TYPE_MOVE, MOVE_BEAT_UP, player); + HP_BAR(opponent, captureDamage: &secondHit); + } THEN { + EXPECT_EQ(firstHit, secondHit); + } +} + +SINGLE_BATTLE_TEST("Beat Up's damage is determined by each striking Pokémon's base attack and level and the target's defense") +{ + s16 shuckleHit, deoxysHit; + GIVEN { + WITH_CONFIG(CONFIG_BEAT_UP, GEN_3); + shuckleHit = 0; + deoxysHit = 0; + PLAYER(SPECIES_SHUCKLE); + PLAYER(SPECIES_DEOXYS_ATTACK); + PLAYER(SPECIES_WYNAUT) { HP(0); } + PLAYER(SPECIES_WYNAUT) { HP(0); } + PLAYER(SPECIES_WYNAUT) { HP(0); } + OPPONENT(SPECIES_BLISSEY); + } WHEN { + TURN { MOVE(player, MOVE_BEAT_UP); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_BEAT_UP, player); + HP_BAR(opponent, captureDamage: &shuckleHit); + ANIMATION(ANIM_TYPE_MOVE, MOVE_BEAT_UP, player); + HP_BAR(opponent, captureDamage: &deoxysHit); + } THEN { + // Shuckle: baseAtk 10 * basePower 1 * levelFactor 42 = 420; / baseDef 10 -> 42; 42/50 + 2 = 2 + u16 shuckleDmg = 2; + // Deoxys-A: baseAtk 180 * basePower 1 * levelFactor 42 = 7560; / baseDef 10 -> 756; 756/50 + 2 = 17 + u16 deoxysDmg = 17; + EXPECT_EQ(shuckleHit, shuckleDmg); + EXPECT_EQ(deoxysHit, deoxysDmg); + EXPECT_LT(shuckleHit, deoxysHit); + } +} + +SINGLE_BATTLE_TEST("Beat Up ignores stat stage changes", s16 damage) +{ + bool32 boosted; + PARAMETRIZE { boosted = FALSE; } + PARAMETRIZE { boosted = TRUE; } + + GIVEN { + WITH_CONFIG(CONFIG_BEAT_UP, GEN_3); + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_WYNAUT); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { if (boosted) { MOVE(player, MOVE_SWORDS_DANCE); } else { MOVE(player, MOVE_CELEBRATE); } } + TURN { MOVE(player, MOVE_BEAT_UP); } + } SCENE { + if (boosted) + ANIMATION(ANIM_TYPE_MOVE, MOVE_SWORDS_DANCE, player); + ANIMATION(ANIM_TYPE_MOVE, MOVE_BEAT_UP, player); + HP_BAR(opponent, captureDamage: &results[i].damage); + } THEN { + if (boosted) + EXPECT_EQ(results[i].damage, results[0].damage); + } +} + +SINGLE_BATTLE_TEST("Beat Up ignores Huge Power", s16 damage) +{ + u16 ability; + + PARAMETRIZE { ability = ABILITY_THICK_FAT; } + PARAMETRIZE { ability = ABILITY_HUGE_POWER; } + + GIVEN { + WITH_CONFIG(CONFIG_BEAT_UP, GEN_3); + PLAYER(SPECIES_AZUMARILL) { Ability(ability); Moves(MOVE_BEAT_UP); } + PLAYER(SPECIES_WYNAUT); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_BEAT_UP); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_BEAT_UP, player); + HP_BAR(opponent, captureDamage: &results[i].damage); + } THEN { + if (ability == ABILITY_HUGE_POWER) + EXPECT_EQ(results[i].damage, results[0].damage); + } +} + +SINGLE_BATTLE_TEST("Beat Up ignores Choice Band", s16 damage) +{ + u16 item; + + PARAMETRIZE { item = ITEM_NONE; } + PARAMETRIZE { item = ITEM_CHOICE_BAND; } + + GIVEN { + WITH_CONFIG(CONFIG_BEAT_UP, GEN_3); + PLAYER(SPECIES_URSARING) { Item(item); Moves(MOVE_BEAT_UP); } + PLAYER(SPECIES_WYNAUT); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_BEAT_UP); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_BEAT_UP, player); + HP_BAR(opponent, captureDamage: &results[i].damage); + } THEN { + if (item == ITEM_CHOICE_BAND) + EXPECT_EQ(results[i].damage, results[0].damage); + } +} diff --git a/test/battle/move_effect/bestow.c b/test/battle/move_effect/bestow.c index 4ca86119b6..9d7bc9ca5c 100644 --- a/test/battle/move_effect/bestow.c +++ b/test/battle/move_effect/bestow.c @@ -92,6 +92,21 @@ SINGLE_BATTLE_TEST("Bestow fails if the user's held item is a Z-Crystal") } } +SINGLE_BATTLE_TEST("Bestow fails if the user has Sticky Hold") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Ability(ABILITY_STICKY_HOLD); Item(ITEM_SITRUS_BERRY); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_BESTOW); } + } SCENE { + MESSAGE("But it failed!"); + } THEN { + EXPECT(player->item == ITEM_SITRUS_BERRY); + EXPECT(opponent->item == ITEM_NONE); + } +} + SINGLE_BATTLE_TEST("Bestow fails if the target is behind a Substitute (Gen 6+)") { GIVEN { @@ -130,4 +145,3 @@ SINGLE_BATTLE_TEST("Bestow fails if the user's held item changes its form") EXPECT(opponent->item == ITEM_NONE); } } - diff --git a/test/battle/move_effect/celebrate.c b/test/battle/move_effect/celebrate.c new file mode 100644 index 0000000000..f5719f5718 --- /dev/null +++ b/test/battle/move_effect/celebrate.c @@ -0,0 +1,4 @@ +#include "global.h" +#include "test/battle.h" + +TO_DO_BATTLE_TEST("TODO: Write Celebrate (Move Effect) test titles") diff --git a/test/battle/move_effect/charge.c b/test/battle/move_effect/charge.c index 35f491254d..48b77d8bdc 100644 --- a/test/battle/move_effect/charge.c +++ b/test/battle/move_effect/charge.c @@ -75,7 +75,8 @@ SINGLE_BATTLE_TEST("Charge's effect is removed if the user fails using an Electr SINGLE_BATTLE_TEST("Charge's effect does not stack with Electromorphosis or Wind Power") { - u32 species, ability; + u32 species; + enum Ability ability; s16 damage[2]; PARAMETRIZE { species = SPECIES_WATTREL; ability = ABILITY_WIND_POWER; } @@ -130,7 +131,7 @@ SINGLE_BATTLE_TEST("Charge's effect is removed regardless if the next move is El } } -SINGLE_BATTLE_TEST("Charge will not expire if it flinches twice in a row") +SINGLE_BATTLE_TEST("Charge will expire if user flinches while using an electric move") { s16 damage[2]; GIVEN { @@ -150,9 +151,6 @@ SINGLE_BATTLE_TEST("Charge will not expire if it flinches twice in a row") ANIMATION(ANIM_TYPE_MOVE, MOVE_THUNDERBOLT, player); HP_BAR(opponent, captureDamage: &damage[1]); } THEN { - if (B_CHARGE < GEN_9) - EXPECT_EQ(damage[0], damage[1]); - else - EXPECT_MUL_EQ(damage[0], Q_4_12(2.0), damage[1]); + EXPECT_EQ(damage[0], damage[1]); } } diff --git a/test/battle/move_effect/clangorous_soul.c b/test/battle/move_effect/clangorous_soul.c index 17e57d7dd5..a1a7ffa42a 100644 --- a/test/battle/move_effect/clangorous_soul.c +++ b/test/battle/move_effect/clangorous_soul.c @@ -1,11 +1,52 @@ #include "global.h" #include "test/battle.h" -TO_DO_BATTLE_TEST("Clangorous Soul raises the user's Attack by 1 stage"); -TO_DO_BATTLE_TEST("Clangorous Soul raises the user's Defense by 1 stage"); -TO_DO_BATTLE_TEST("Clangorous Soul raises the user's Sp. Attack by 1 stage"); -TO_DO_BATTLE_TEST("Clangorous Soul raises the user's Sp. Defense by 1 stage"); -TO_DO_BATTLE_TEST("Clangorous Soul raises the user's Speed by 1 stage"); -TO_DO_BATTLE_TEST("Clangorous Soul cuts the user's HP by 1/3"); +SINGLE_BATTLE_TEST("Clangorous Soul cuts the user's HP by 1/3") +{ + s16 dmg; + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { HP(300); MaxHP(300); }; + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_CLANGOROUS_SOUL); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_CLANGOROUS_SOUL, player); + HP_BAR(player, captureDamage: &dmg); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); + } THEN { + EXPECT_EQ(gBattleMons[0].maxHP / 3, dmg); + } +} + +SINGLE_BATTLE_TEST("Clangorous Soul raises the user's Atk, Def, Sp. Atk. Sp. Def and Speed by 1 stage") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { HP(300); MaxHP(300); }; + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_CLANGOROUS_SOUL); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_CLANGOROUS_SOUL, player); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); + } THEN { + EXPECT_EQ(player->statStages[STAT_ATK], DEFAULT_STAT_STAGE + 1); + EXPECT_EQ(player->statStages[STAT_DEF], DEFAULT_STAT_STAGE + 1); + EXPECT_EQ(player->statStages[STAT_SPATK], DEFAULT_STAT_STAGE + 1); + EXPECT_EQ(player->statStages[STAT_SPDEF], DEFAULT_STAT_STAGE + 1); + EXPECT_EQ(player->statStages[STAT_SPEED], DEFAULT_STAT_STAGE + 1); + } +} + +SINGLE_BATTLE_TEST("Clangorous Soul fails if the user's HP is less or equal than 1/3") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { HP(100); MaxHP(300); }; + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_CLANGOROUS_SOUL); } + } SCENE { + NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_CLANGOROUS_SOUL, player); + } +} + TO_DO_BATTLE_TEST("Clangorous Soul fails if Attack, Defense, Sp. Attack, Sp. Defense and Speed are all maxed out"); -TO_DO_BATTLE_TEST("Clangorous Soul fails if the user's HP is less or equal than 1/3"); diff --git a/test/battle/move_effect/coaching.c b/test/battle/move_effect/coaching.c index 7245f8854b..642727de51 100644 --- a/test/battle/move_effect/coaching.c +++ b/test/battle/move_effect/coaching.c @@ -117,3 +117,23 @@ DOUBLE_BATTLE_TEST("Coaching fails if there's no ally") MESSAGE("But it failed!"); } } + +AI_DOUBLE_BATTLE_TEST("AI uses Coaching") +{ + u32 move; + PARAMETRIZE { move = MOVE_HEADBUTT; } + PARAMETRIZE { move = MOVE_DAZZLING_GLEAM; } + + GIVEN { + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_OMNISCIENT); + PLAYER(SPECIES_WOBBUFFET) { Moves(MOVE_POUND, MOVE_CELEBRATE); } + PLAYER(SPECIES_WOBBUFFET) { Moves(MOVE_POUND, MOVE_CELEBRATE); } + OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_COACHING, MOVE_POUND); } + OPPONENT(SPECIES_WOBBUFFET) { Moves(move); } + } WHEN { + if (move == MOVE_HEADBUTT) + TURN { EXPECT_MOVE(opponentLeft, MOVE_COACHING); } + else + TURN { NOT_EXPECT_MOVE(opponentLeft, MOVE_COACHING); } + } +} diff --git a/test/battle/move_effect/coil.c b/test/battle/move_effect/coil.c index ce9e8629a8..7d56702989 100644 --- a/test/battle/move_effect/coil.c +++ b/test/battle/move_effect/coil.c @@ -1,6 +1,24 @@ #include "global.h" #include "test/battle.h" -TO_DO_BATTLE_TEST("Coil raises the user's Attack by 1 stage"); -TO_DO_BATTLE_TEST("Coil raises the user's Defense by 1 stage"); -TO_DO_BATTLE_TEST("Coil raises the user's Accuracy by 1 stage"); +ASSUMPTIONS +{ + ASSUME(GetMoveEffect(MOVE_COIL) == EFFECT_COIL); +} + +SINGLE_BATTLE_TEST("Coil increases the user's Attack, Defense and Accuracy by 1 stage each") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_COIL); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_COIL, player); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); + } THEN { + EXPECT_EQ(player->statStages[STAT_ATK], DEFAULT_STAT_STAGE + 1); + EXPECT_EQ(player->statStages[STAT_DEF], DEFAULT_STAT_STAGE + 1); + EXPECT_EQ(player->statStages[STAT_ACC], DEFAULT_STAT_STAGE + 1); + } +} diff --git a/test/battle/move_effect/copycat.c b/test/battle/move_effect/copycat.c index da9e085ede..d834564b13 100644 --- a/test/battle/move_effect/copycat.c +++ b/test/battle/move_effect/copycat.c @@ -21,10 +21,31 @@ TO_DO_BATTLE_TEST("Copycat ignores the recharging turn of recharging moves (Gen TO_DO_BATTLE_TEST("Copycat can copy Bide on all turns"); TO_DO_BATTLE_TEST("Copycat copies moves called by other calling moves instead of the calling move (Gen 5+)"); +ASSUMPTIONS +{ + ASSUME(GetMoveEffect(MOVE_COPYCAT) == EFFECT_COPYCAT); +} + +SINGLE_BATTLE_TEST("Copycat deducts power points from itself, not the copied move") +{ + ASSUME(GetMovePP(MOVE_COPYCAT) == 20); + ASSUME(GetMovePP(MOVE_POUND) == 35); + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Moves(MOVE_COPYCAT); } + OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_POUND); } + } WHEN { + TURN { MOVE(opponent, MOVE_POUND); MOVE(player, MOVE_COPYCAT); } + } SCENE { + } THEN { + EXPECT_EQ(opponent->pp[0], 34); + EXPECT_EQ(player->pp[0], 19); + } +} + DOUBLE_BATTLE_TEST("(DYNAMAX) Dynamaxed Pokemon can have their base moves copied by Copycat") { GIVEN { - WITH_CONFIG(GEN_CONFIG_MEGA_EVO_TURN_ORDER, GEN_7); // TODO: Decouple this config from other gimmicks + WITH_CONFIG(CONFIG_MEGA_EVO_TURN_ORDER, GEN_7); // TODO: Decouple this config from other gimmicks PLAYER(SPECIES_WOBBUFFET); PLAYER(SPECIES_WYNAUT); OPPONENT(SPECIES_WOBBUFFET); diff --git a/test/battle/move_effect/counter.c b/test/battle/move_effect/counter.c index ece0ea9a9f..7fc9fb4b9f 100644 --- a/test/battle/move_effect/counter.c +++ b/test/battle/move_effect/counter.c @@ -129,7 +129,7 @@ DOUBLE_BATTLE_TEST("Counter respects Follow me") } } -DOUBLE_BATTLE_TEST("Counter fails if mon that damaged counter user is no longer on the field") +DOUBLE_BATTLE_TEST("Counter fails if mon that damaged Counter user is no longer on the field (Gen 1-4)") { GIVEN { PLAYER(SPECIES_WOBBUFFET); @@ -149,6 +149,24 @@ DOUBLE_BATTLE_TEST("Counter fails if mon that damaged counter user is no longer } } +SINGLE_BATTLE_TEST("Counter deals 1 damage when the attack received is blocked by Disguise") +{ + s16 counterDmg; + GIVEN { + ASSUME(GetMoveCategory(MOVE_SHADOW_SNEAK) == DAMAGE_CATEGORY_PHYSICAL); + PLAYER(SPECIES_MIMIKYU) { Ability(ABILITY_DISGUISE); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_SHADOW_SNEAK); MOVE(player, MOVE_COUNTER); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SHADOW_SNEAK, opponent); + ANIMATION(ANIM_TYPE_MOVE, MOVE_COUNTER, player); + HP_BAR(opponent, captureDamage: &counterDmg); + } THEN { + EXPECT_EQ(counterDmg, 1); + } +} + // Gen 1 TO_DO_BATTLE_TEST("Counter can only counter Normal and Fighting-type moves (Gen 1)"); TO_DO_BATTLE_TEST("Counter can hit ghost-type Pokémon (Gen 1)"); diff --git a/test/battle/move_effect/decorate.c b/test/battle/move_effect/decorate.c index 5eef9dc305..ac2bb6105b 100644 --- a/test/battle/move_effect/decorate.c +++ b/test/battle/move_effect/decorate.c @@ -1,5 +1,23 @@ #include "global.h" #include "test/battle.h" -TO_DO_BATTLE_TEST("Decorate raises the target's Attack by 2 stages"); -TO_DO_BATTLE_TEST("Decorate raises the target's Sp. Attack by 2 stages"); +ASSUMPTIONS +{ + ASSUME(GetMoveEffect(MOVE_DECORATE) == EFFECT_DECORATE); +} + +SINGLE_BATTLE_TEST("Decorate raises the target's Attack and Sp. Attack by 2 stages each") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_DECORATE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_DECORATE, player); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); + } THEN { + EXPECT_EQ(opponent->statStages[STAT_ATK], DEFAULT_STAT_STAGE + 2); + EXPECT_EQ(opponent->statStages[STAT_SPATK], DEFAULT_STAT_STAGE + 2); + } +} diff --git a/test/battle/move_effect/defog.c b/test/battle/move_effect/defog.c index 96b79438f1..f2fa558e13 100644 --- a/test/battle/move_effect/defog.c +++ b/test/battle/move_effect/defog.c @@ -31,28 +31,142 @@ SINGLE_BATTLE_TEST("Defog lowers evasiveness by 1 stage") ANIMATION(ANIM_TYPE_MOVE, MOVE_DEFOG, player); ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); MESSAGE("The opposing Wobbuffet's evasiveness fell!"); + } THEN { + EXPECT_EQ(opponent->statStages[STAT_EVASION], DEFAULT_STAT_STAGE - 1); } } -SINGLE_BATTLE_TEST("Defog does not lower evasiveness if target behind Substitute") +SINGLE_BATTLE_TEST("Defog fails if target has minimum evasion stat change") { GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET) {Ability(ABILITY_SIMPLE);}; + } WHEN { + TURN { MOVE(player, MOVE_DEFOG); } + TURN { MOVE(player, MOVE_DEFOG); } + TURN { MOVE(player, MOVE_DEFOG); } + TURN { MOVE(player, MOVE_DEFOG); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_DEFOG, player); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); + MESSAGE("The opposing Wobbuffet's evasiveness harshly fell!"); + MESSAGE("But it failed!"); + } THEN { + EXPECT_EQ(opponent->statStages[STAT_EVASION], DEFAULT_STAT_STAGE - 6); + } +} + +SINGLE_BATTLE_TEST("Defog lowers evasiveness of target behind Substitute (Gen4)") +{ + GIVEN { + WITH_CONFIG(CONFIG_DEFOG_EFFECT_CLEARING, GEN_4); PLAYER(SPECIES_WOBBUFFET) { Speed(4); } OPPONENT(SPECIES_WOBBUFFET) { Speed(5); } } WHEN { TURN { MOVE(opponent, MOVE_SUBSTITUTE); MOVE(player, MOVE_DEFOG); } } SCENE { MESSAGE("The opposing Wobbuffet used Substitute!"); - MESSAGE("But it failed!"); - NONE_OF { - ANIMATION(ANIM_TYPE_MOVE, MOVE_DEFOG, player); - ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); - MESSAGE("The opposing Wobbuffet's evasiveness fell!"); - } + NOT MESSAGE("But it failed!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_DEFOG, player); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); + MESSAGE("The opposing Wobbuffet's evasiveness fell!"); + } THEN { + EXPECT_EQ(opponent->statStages[STAT_EVASION], DEFAULT_STAT_STAGE - 1); + } +} + +SINGLE_BATTLE_TEST("Defog fails if target has minimum evasion stat change behind Substitute (Gen4)") +{ + GIVEN { + WITH_CONFIG(CONFIG_DEFOG_EFFECT_CLEARING, GEN_4); + PLAYER(SPECIES_WOBBUFFET) { Speed(4); } + OPPONENT(SPECIES_WOBBUFFET) { Speed(5); Ability(ABILITY_SIMPLE);} + } WHEN { + TURN { MOVE(opponent, MOVE_SUBSTITUTE); MOVE(player, MOVE_DEFOG); } + TURN { MOVE(player, MOVE_DEFOG); } + TURN { MOVE(player, MOVE_DEFOG); } + TURN { MOVE(player, MOVE_DEFOG); } + } SCENE { + MESSAGE("The opposing Wobbuffet used Substitute!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_DEFOG, player); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); + MESSAGE("The opposing Wobbuffet's evasiveness harshly fell!"); + MESSAGE("But it failed!"); + } THEN { + EXPECT_EQ(opponent->statStages[STAT_EVASION], DEFAULT_STAT_STAGE - 6); + } +} + +SINGLE_BATTLE_TEST("Defog does not lower evasiveness if target behind Substitute (Gen5+)") +{ + u32 move; + + PARAMETRIZE { move = MOVE_LIGHT_SCREEN; } + PARAMETRIZE { move = MOVE_CELEBRATE; } + + GIVEN { + WITH_CONFIG(CONFIG_DEFOG_EFFECT_CLEARING, GEN_5); + PLAYER(SPECIES_WOBBUFFET) { Speed(4); } + OPPONENT(SPECIES_WOBBUFFET) { Speed(5); } + } WHEN { + TURN { MOVE(opponent, move); } + TURN { MOVE(opponent, MOVE_SUBSTITUTE); MOVE(player, MOVE_DEFOG); } + } SCENE { + MESSAGE("The opposing Wobbuffet used Substitute!"); + if (move == MOVE_CELEBRATE) + { + MESSAGE("But it failed!"); + NONE_OF { + ANIMATION(ANIM_TYPE_MOVE, MOVE_DEFOG, player); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); + MESSAGE("The opposing Wobbuffet's evasiveness fell!"); + } + } + else + { + NONE_OF { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); + MESSAGE("The opposing Wobbuffet's evasiveness fell!"); + } + } + } THEN { + EXPECT_EQ(opponent->statStages[STAT_EVASION], DEFAULT_STAT_STAGE); + } +} + +DOUBLE_BATTLE_TEST("Defog doesn't remove Reflect or Light Screen from the user's side", s16 damagePhysical, s16 damageSpecial) +{ + u16 move; + + PARAMETRIZE { move = MOVE_DEFOG; } + PARAMETRIZE { move = MOVE_CELEBRATE; } + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Speed(4); } + PLAYER(SPECIES_WOBBUFFET) { Speed(3); } + OPPONENT(SPECIES_WOBBUFFET) { Speed(2); } + OPPONENT(SPECIES_WOBBUFFET) { Speed(1); } + } WHEN { + TURN { MOVE(playerLeft, MOVE_REFLECT); MOVE(playerRight, MOVE_LIGHT_SCREEN); } + TURN { MOVE(playerLeft, move, target: opponentLeft); } + TURN { MOVE(opponentLeft, MOVE_SCRATCH, target: playerLeft); MOVE(opponentRight, MOVE_GUST, target: playerRight); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_REFLECT, playerLeft); + ANIMATION(ANIM_TYPE_MOVE, MOVE_LIGHT_SCREEN, playerRight); + ANIMATION(ANIM_TYPE_MOVE, move, playerLeft); + NONE_OF { + MESSAGE("Your team's Reflect wore off!"); + MESSAGE("Your team's Light Screen wore off!"); + } + ANIMATION(ANIM_TYPE_MOVE, MOVE_SCRATCH, opponentLeft); + HP_BAR(playerLeft, captureDamage: &results[i].damagePhysical); + ANIMATION(ANIM_TYPE_MOVE, MOVE_GUST, opponentRight); + HP_BAR(playerRight, captureDamage: &results[i].damageSpecial); + } FINALLY { + EXPECT_EQ(results[1].damagePhysical, results[0].damagePhysical); + EXPECT_EQ(results[1].damageSpecial, results[0].damageSpecial); } } -TO_DO_BATTLE_TEST("Defog doesn't remove Reflect or Light Screen from the user's side"); DOUBLE_BATTLE_TEST("Defog removes Reflect and Light Screen from target's side", s16 damagePhysical, s16 damageSpecial) { u16 move; @@ -76,9 +190,9 @@ DOUBLE_BATTLE_TEST("Defog removes Reflect and Light Screen from target's side", MESSAGE("The opposing team's Reflect wore off!"); MESSAGE("The opposing team's Light Screen wore off!"); } - MESSAGE("Wobbuffet used Scratch!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SCRATCH, playerLeft); HP_BAR(opponentLeft, captureDamage: &results[i].damagePhysical); - MESSAGE("Wobbuffet used Gust!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_GUST, playerRight); HP_BAR(opponentRight, captureDamage: &results[i].damageSpecial); } FINALLY { EXPECT_MUL_EQ(results[1].damagePhysical, Q_4_12(1.5), results[0].damagePhysical); @@ -86,7 +200,38 @@ DOUBLE_BATTLE_TEST("Defog removes Reflect and Light Screen from target's side", } } -TO_DO_BATTLE_TEST("Defog doesn't remove Mist or Safeguard from the user's side"); +DOUBLE_BATTLE_TEST("Defog doesn't remove Mist or Safeguard from the user's side") +{ + u16 move; + + PARAMETRIZE { move = MOVE_DEFOG; } + PARAMETRIZE { move = MOVE_CELEBRATE; } + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Speed(4); } + PLAYER(SPECIES_WOBBUFFET) { Speed(3); } + OPPONENT(SPECIES_WOBBUFFET) { Speed(2); } + OPPONENT(SPECIES_WOBBUFFET) { Speed(1); } + } WHEN { + TURN { MOVE(playerLeft, MOVE_MIST); MOVE(playerRight, MOVE_SAFEGUARD); } + TURN { MOVE(playerLeft, move, target: opponentLeft); } + TURN { MOVE(opponentLeft, MOVE_SCREECH, target: playerLeft); MOVE(opponentRight, MOVE_TOXIC, target: playerRight); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_MIST, playerLeft); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SAFEGUARD, playerRight); + ANIMATION(ANIM_TYPE_MOVE, move, playerLeft); + NONE_OF { + MESSAGE("Your team's Mist wore off!"); + MESSAGE("Your team's Safeguard wore off!"); + } + MESSAGE("The opposing Wobbuffet used Screech!"); + MESSAGE("Wobbuffet is protected by the mist!"); + NOT ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerLeft); + MESSAGE("The opposing Wobbuffet used Toxic!"); + MESSAGE("Wobbuffet is protected by Safeguard!"); + NOT STATUS_ICON(playerRight, badPoison: TRUE); + } +} + DOUBLE_BATTLE_TEST("Defog removes Mist and Safeguard from target's side") { u16 move; @@ -114,8 +259,7 @@ DOUBLE_BATTLE_TEST("Defog removes Mist and Safeguard from target's side") if (move == MOVE_DEFOG) { ANIMATION(ANIM_TYPE_MOVE, MOVE_SCREECH, playerLeft); ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponentLeft); - } - else { + } else { MESSAGE("The opposing Wobbuffet is protected by the mist!"); NOT ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponentLeft); } @@ -123,23 +267,73 @@ DOUBLE_BATTLE_TEST("Defog removes Mist and Safeguard from target's side") if (move == MOVE_DEFOG) { ANIMATION(ANIM_TYPE_MOVE, MOVE_TOXIC, playerRight); STATUS_ICON(opponentRight, badPoison: TRUE); - } - else { + } else { MESSAGE("The opposing Wobbuffet is protected by Safeguard!"); NOT STATUS_ICON(opponentRight, badPoison: TRUE); } } } -TO_DO_BATTLE_TEST("Defog removes Stealth Rock and Sticky Web from target's side"); -TO_DO_BATTLE_TEST("Defog doesn't remove Stealth Rock or Sticky Web from user's side (Gen 4-5)"); +DOUBLE_BATTLE_TEST("Defog removes Stealth Rock and Sticky Web from target's side") +{ + u32 move; + + PARAMETRIZE { move = MOVE_CELEBRATE; } + PARAMETRIZE { move = MOVE_DEFOG; } + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Speed(4); } + PLAYER(SPECIES_WOBBUFFET) { Speed(3); } + PLAYER(SPECIES_WOBBUFFET) { Speed(3); } + OPPONENT(SPECIES_WOBBUFFET) { Speed(2); } + OPPONENT(SPECIES_WOBBUFFET) { Speed(1); } + } WHEN { + TURN { MOVE(opponentLeft, MOVE_STEALTH_ROCK); MOVE(opponentRight, MOVE_STICKY_WEB); } + TURN { MOVE(opponentLeft, move, target: playerLeft); } + TURN { SWITCH(playerLeft, 2); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_STEALTH_ROCK, opponentLeft); + ANIMATION(ANIM_TYPE_MOVE, MOVE_STICKY_WEB, opponentRight); + ANIMATION(ANIM_TYPE_MOVE, move, opponentLeft); + if (move == MOVE_DEFOG) { + MESSAGE("The sticky web has disappeared from the ground around your team!"); + MESSAGE("The pointed stones disappeared from around your team!"); + } + // Switch happens + SWITCH_OUT_MESSAGE("Wobbuffet"); + SEND_IN_MESSAGE("Wobbuffet"); + if (move != MOVE_DEFOG) { + HP_BAR(playerLeft); + MESSAGE("Pointed stones dug into Wobbuffet!"); + MESSAGE("Wobbuffet was caught in a sticky web!"); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerLeft); + MESSAGE("Wobbuffet's Speed fell!"); + } else { + NONE_OF { + HP_BAR(playerLeft); + MESSAGE("Pointed stones dug into Wobbuffet!"); + MESSAGE("Wobbuffet was caught in a sticky web!"); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerLeft); + MESSAGE("Wobbuffet's Speed fell!"); + } + } + } THEN { + if (move != MOVE_DEFOG) { + EXPECT_EQ(playerLeft->statStages[STAT_SPEED], DEFAULT_STAT_STAGE - 1); + } else { + EXPECT_EQ(playerLeft->statStages[STAT_SPEED], DEFAULT_STAT_STAGE); + } + } +} + DOUBLE_BATTLE_TEST("Defog removes Stealth Rock and Sticky Web from user's side (Gen 6+)") { - u16 move; + u32 move, config; - PARAMETRIZE { move = MOVE_DEFOG; } - PARAMETRIZE { move = MOVE_CELEBRATE; } + PARAMETRIZE { move = MOVE_CELEBRATE; config = GEN_5; } + PARAMETRIZE { move = MOVE_DEFOG; config = GEN_5; } + PARAMETRIZE { move = MOVE_DEFOG; config = GEN_6; } GIVEN { + WITH_CONFIG(CONFIG_DEFOG_EFFECT_CLEARING, config); PLAYER(SPECIES_WOBBUFFET) { Speed(4); } PLAYER(SPECIES_WOBBUFFET) { Speed(3); } PLAYER(SPECIES_WOBBUFFET) { Speed(3); } @@ -153,21 +347,20 @@ DOUBLE_BATTLE_TEST("Defog removes Stealth Rock and Sticky Web from user's side ( ANIMATION(ANIM_TYPE_MOVE, MOVE_STEALTH_ROCK, opponentLeft); ANIMATION(ANIM_TYPE_MOVE, MOVE_STICKY_WEB, opponentRight); ANIMATION(ANIM_TYPE_MOVE, move, playerLeft); - if (move == MOVE_DEFOG && B_DEFOG_EFFECT_CLEARING >= GEN_6) { + if (move == MOVE_DEFOG && config >= GEN_6) { MESSAGE("The sticky web has disappeared from the ground around your team!"); MESSAGE("The pointed stones disappeared from around your team!"); } // Switch happens SWITCH_OUT_MESSAGE("Wobbuffet"); SEND_IN_MESSAGE("Wobbuffet"); - if (move != MOVE_DEFOG || B_DEFOG_EFFECT_CLEARING <= GEN_5) { + if (move != MOVE_DEFOG || config <= GEN_5) { HP_BAR(playerLeft); MESSAGE("Pointed stones dug into Wobbuffet!"); MESSAGE("Wobbuffet was caught in a sticky web!"); ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerLeft); MESSAGE("Wobbuffet's Speed fell!"); - } - else { + } else { NONE_OF { HP_BAR(playerLeft); MESSAGE("Pointed stones dug into Wobbuffet!"); @@ -176,18 +369,55 @@ DOUBLE_BATTLE_TEST("Defog removes Stealth Rock and Sticky Web from user's side ( MESSAGE("Wobbuffet's Speed fell!"); } } + } THEN { + if (move != MOVE_DEFOG || config <= GEN_5) { + EXPECT_EQ(playerLeft->statStages[STAT_SPEED], DEFAULT_STAT_STAGE - 1); + } else { + EXPECT_EQ(playerLeft->statStages[STAT_SPEED], DEFAULT_STAT_STAGE); + } + } +} + +SINGLE_BATTLE_TEST("Defog removes Spikes from target's side") +{ + u32 move; + + PARAMETRIZE { move = MOVE_CELEBRATE; } + PARAMETRIZE { move = MOVE_DEFOG; } + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Speed(2); } + OPPONENT(SPECIES_WOBBUFFET) { Speed(5); } + OPPONENT(SPECIES_WOBBUFFET) { Speed(5); } + } WHEN { + TURN { MOVE(player, MOVE_SPIKES); } + TURN { MOVE(player, move); } + TURN { SWITCH(opponent, 1); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SPIKES, player); + ANIMATION(ANIM_TYPE_MOVE, move, player); + if (move == MOVE_DEFOG) { + MESSAGE("The spikes disappeared from the ground around the opposing team!"); + NONE_OF { + HP_BAR(opponent); + MESSAGE("The opposing Wobbuffet was hurt by the spikes!"); + } + } else { + NOT MESSAGE("The spikes disappeared from the ground around the opposing team!"); + HP_BAR(opponent); + MESSAGE("The opposing Wobbuffet was hurt by the spikes!"); + } } } -TO_DO_BATTLE_TEST("Defog removes Spikes from target's side"); -TO_DO_BATTLE_TEST("Defog doesn't remove Spikes from user's side (Gen 4-5)"); SINGLE_BATTLE_TEST("Defog removes Spikes from user's side (Gen 6+)") { - u16 move; + u32 move, config; - PARAMETRIZE { move = MOVE_DEFOG; } - PARAMETRIZE { move = MOVE_CELEBRATE; } + PARAMETRIZE { move = MOVE_CELEBRATE; config = GEN_5; } + PARAMETRIZE { move = MOVE_DEFOG; config = GEN_5; } + PARAMETRIZE { move = MOVE_DEFOG; config = GEN_6; } GIVEN { + WITH_CONFIG(CONFIG_DEFOG_EFFECT_CLEARING, config); PLAYER(SPECIES_WOBBUFFET) { Speed(2); } PLAYER(SPECIES_WOBBUFFET) { Speed(2); } OPPONENT(SPECIES_WOBBUFFET) { Speed(5); } @@ -197,16 +427,15 @@ SINGLE_BATTLE_TEST("Defog removes Spikes from user's side (Gen 6+)") } SCENE { ANIMATION(ANIM_TYPE_MOVE, MOVE_SPIKES, opponent); ANIMATION(ANIM_TYPE_MOVE, move, player); - if (move == MOVE_DEFOG && B_DEFOG_EFFECT_CLEARING >= GEN_6) + if (move == MOVE_DEFOG && config >= 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 || B_DEFOG_EFFECT_CLEARING <= GEN_5) { + if (move != MOVE_DEFOG || config <= GEN_5) { HP_BAR(player); MESSAGE("Wobbuffet was hurt by the spikes!"); - } - else { + } else { NONE_OF { HP_BAR(player); MESSAGE("Wobbuffet was hurt by the spikes!"); @@ -215,16 +444,20 @@ SINGLE_BATTLE_TEST("Defog removes Spikes from user's side (Gen 6+)") } } -TO_DO_BATTLE_TEST("Defog doesn't remove terrain (Gen 4-7)"); SINGLE_BATTLE_TEST("Defog removes terrain (Gen 8+)") { - u16 move; + u32 move, config; - PARAMETRIZE { move = MOVE_PSYCHIC_TERRAIN; } - PARAMETRIZE { move = MOVE_ELECTRIC_TERRAIN; } - PARAMETRIZE { move = MOVE_MISTY_TERRAIN; } - PARAMETRIZE { move = MOVE_GRASSY_TERRAIN; } + PARAMETRIZE { move = MOVE_PSYCHIC_TERRAIN; config = GEN_7; } + PARAMETRIZE { move = MOVE_ELECTRIC_TERRAIN; config = GEN_7; } + PARAMETRIZE { move = MOVE_MISTY_TERRAIN; config = GEN_7; } + PARAMETRIZE { move = MOVE_GRASSY_TERRAIN; config = GEN_7; } + PARAMETRIZE { move = MOVE_PSYCHIC_TERRAIN; config = GEN_8; } + PARAMETRIZE { move = MOVE_ELECTRIC_TERRAIN; config = GEN_8; } + PARAMETRIZE { move = MOVE_MISTY_TERRAIN; config = GEN_8; } + PARAMETRIZE { move = MOVE_GRASSY_TERRAIN; config = GEN_8; } GIVEN { + WITH_CONFIG(CONFIG_DEFOG_EFFECT_CLEARING, config); PLAYER(SPECIES_WOBBUFFET) { Speed(50); } OPPONENT(SPECIES_WOBBUFFET) { Speed(5); } } WHEN { @@ -232,7 +465,7 @@ SINGLE_BATTLE_TEST("Defog removes terrain (Gen 8+)") } SCENE { ANIMATION(ANIM_TYPE_MOVE, move, player); ANIMATION(ANIM_TYPE_MOVE, MOVE_DEFOG, opponent); - if (B_DEFOG_EFFECT_CLEARING >= GEN_8) { + if (config >= GEN_8) { if (move == MOVE_PSYCHIC_TERRAIN) { MESSAGE("The weirdness disappeared from the battlefield!"); } @@ -258,34 +491,32 @@ SINGLE_BATTLE_TEST("Defog removes terrain (Gen 8+)") } } -TO_DO_BATTLE_TEST("Defog removes Toxic Spikes from target's side"); -TO_DO_BATTLE_TEST("Defog doesn't remove Toxic Spikes from user's side (Gen 4-5)"); -SINGLE_BATTLE_TEST("Defog removes Toxic Spikes from user's side (Gen 6+)") +SINGLE_BATTLE_TEST("Defog removes Toxic Spikes from target's side") { - u16 move; + u32 move; - PARAMETRIZE { move = MOVE_DEFOG; } PARAMETRIZE { move = MOVE_CELEBRATE; } + PARAMETRIZE { move = MOVE_DEFOG; } GIVEN { PLAYER(SPECIES_WOBBUFFET) { Speed(5); } OPPONENT(SPECIES_WOBBUFFET) { Speed(2); } OPPONENT(SPECIES_WOBBUFFET) { Speed(2); } } WHEN { - TURN { MOVE(player, MOVE_TOXIC_SPIKES); MOVE(opponent, move); } + TURN { MOVE(player, MOVE_TOXIC_SPIKES); } + TURN { MOVE(player, move); } TURN { SWITCH(opponent, 1); } } SCENE { ANIMATION(ANIM_TYPE_MOVE, MOVE_TOXIC_SPIKES, player); - ANIMATION(ANIM_TYPE_MOVE, move, opponent); - if (move == MOVE_DEFOG && B_DEFOG_EFFECT_CLEARING >= GEN_6) + ANIMATION(ANIM_TYPE_MOVE, move, player); + if (move == MOVE_DEFOG) MESSAGE("The poison spikes disappeared from the ground around the opposing team!"); // Switch happens MESSAGE("2 sent out Wobbuffet!"); - if (move != MOVE_DEFOG || B_DEFOG_EFFECT_CLEARING <= GEN_5) { + if (move != MOVE_DEFOG) { MESSAGE("The opposing Wobbuffet was poisoned!"); ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_PSN, opponent); STATUS_ICON(opponent, poison: TRUE); - } - else { + } else { NONE_OF { MESSAGE("The opposing Wobbuffet was poisoned!"); ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_PSN, opponent); @@ -295,7 +526,83 @@ SINGLE_BATTLE_TEST("Defog removes Toxic Spikes from user's side (Gen 6+)") } } -TO_DO_BATTLE_TEST("Defog doesn't remove Aurora Veil from the user's side"); +SINGLE_BATTLE_TEST("Defog removes Toxic Spikes from user's side (Gen 6+)") +{ + u32 move, config; + + PARAMETRIZE { move = MOVE_CELEBRATE; config = GEN_5; } + PARAMETRIZE { move = MOVE_DEFOG; config = GEN_5; } + PARAMETRIZE { move = MOVE_DEFOG; config = GEN_6; } + GIVEN { + WITH_CONFIG(CONFIG_DEFOG_EFFECT_CLEARING, config); + PLAYER(SPECIES_WOBBUFFET) { Speed(5); } + OPPONENT(SPECIES_WOBBUFFET) { Speed(2); } + OPPONENT(SPECIES_WOBBUFFET) { Speed(2); } + } WHEN { + TURN { MOVE(player, MOVE_TOXIC_SPIKES); MOVE(opponent, move); } + TURN { SWITCH(opponent, 1); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_TOXIC_SPIKES, player); + ANIMATION(ANIM_TYPE_MOVE, move, opponent); + if (move == MOVE_DEFOG && config >= 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 || config <= GEN_5) { + MESSAGE("The opposing Wobbuffet was poisoned!"); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_PSN, opponent); + STATUS_ICON(opponent, poison: TRUE); + } else { + NONE_OF { + MESSAGE("The opposing Wobbuffet was poisoned!"); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_PSN, opponent); + STATUS_ICON(opponent, poison: TRUE); + } + } + } +} + +DOUBLE_BATTLE_TEST("Defog doesn't remove Aurora Veil from the user's side", s16 damagePhysical, s16 damageSpecial) +{ + u16 move; + + PARAMETRIZE { move = MOVE_DEFOG; } + PARAMETRIZE { move = MOVE_CELEBRATE; } + GIVEN { + ASSUME(GetMoveEffect(MOVE_HAIL) == EFFECT_HAIL); + ASSUME(GetSpeciesType(SPECIES_GLALIE, 0) == TYPE_ICE); + PLAYER(SPECIES_GLALIE) { Speed(4); } + PLAYER(SPECIES_GLALIE) { Speed(3); } + OPPONENT(SPECIES_GLALIE) { Speed(2); } + OPPONENT(SPECIES_GLALIE) { Speed(1); } + } WHEN { + TURN { MOVE(playerLeft, MOVE_HAIL); MOVE(playerRight, MOVE_AURORA_VEIL); } + TURN { MOVE(playerLeft, move, target: opponentLeft); } + TURN { MOVE(opponentLeft, MOVE_SCRATCH, target: playerLeft); MOVE(opponentRight, MOVE_GUST, target: playerRight); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_HAIL, playerLeft); + ANIMATION(ANIM_TYPE_MOVE, MOVE_AURORA_VEIL, playerRight); + ANIMATION(ANIM_TYPE_MOVE, move, playerLeft); + if (move == MOVE_DEFOG) { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponentLeft); + MESSAGE("The opposing Glalie's evasiveness fell!"); + } + NOT MESSAGE("Your team's Aurora Veil wore off!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SCRATCH, opponentLeft); + HP_BAR(playerLeft, captureDamage: &results[i].damagePhysical); + ANIMATION(ANIM_TYPE_MOVE, MOVE_GUST, opponentRight); + HP_BAR(playerRight, captureDamage: &results[i].damageSpecial); + } THEN { + if (move == MOVE_DEFOG) + EXPECT_EQ(opponentLeft->statStages[STAT_EVASION], DEFAULT_STAT_STAGE - 1); + else + EXPECT_EQ(opponentLeft->statStages[STAT_EVASION], DEFAULT_STAT_STAGE); + } FINALLY { + EXPECT_EQ(results[1].damagePhysical, results[0].damagePhysical); + EXPECT_EQ(results[1].damageSpecial, results[0].damageSpecial); + } +} + DOUBLE_BATTLE_TEST("Defog removes Aurora Veil from target's side", s16 damagePhysical, s16 damageSpecial) { u16 move; @@ -322,10 +629,15 @@ DOUBLE_BATTLE_TEST("Defog removes Aurora Veil from target's side", s16 damagePhy MESSAGE("Glalie's evasiveness fell!"); MESSAGE("Your team's Aurora Veil wore off!"); } - MESSAGE("The opposing Glalie used Scratch!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SCRATCH, opponentLeft); HP_BAR(playerLeft, captureDamage: &results[i].damagePhysical); - MESSAGE("The opposing Glalie used Gust!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_GUST, opponentRight); HP_BAR(playerRight, captureDamage: &results[i].damageSpecial); + } THEN { + if (move == MOVE_DEFOG) + EXPECT_EQ(playerLeft->statStages[STAT_EVASION], DEFAULT_STAT_STAGE - 1); + else + EXPECT_EQ(playerLeft->statStages[STAT_EVASION], DEFAULT_STAT_STAGE); } FINALLY { EXPECT_MUL_EQ(results[1].damagePhysical, Q_4_12(1.5), results[0].damagePhysical); EXPECT_MUL_EQ(results[1].damageSpecial, Q_4_12(1.5), results[0].damageSpecial); @@ -334,7 +646,11 @@ DOUBLE_BATTLE_TEST("Defog removes Aurora Veil from target's side", s16 damagePhy DOUBLE_BATTLE_TEST("Defog removes everything it can") { + u32 config; + PARAMETRIZE { config = GEN_5; } + PARAMETRIZE { config = GEN_6; } GIVEN { + WITH_CONFIG(CONFIG_DEFOG_EFFECT_CLEARING, config); ASSUME(GetMoveEffect(MOVE_HAIL) == EFFECT_HAIL); ASSUME(GetSpeciesType(SPECIES_GLALIE, 0) == TYPE_ICE); PLAYER(SPECIES_GLALIE) { Speed(4); } @@ -363,7 +679,7 @@ DOUBLE_BATTLE_TEST("Defog removes everything it can") MESSAGE("Your team's Aurora Veil wore off!"); MESSAGE("Your team's Safeguard wore off!"); - if (B_DEFOG_EFFECT_CLEARING >= GEN_6) { + if (config == GEN_6) { MESSAGE("The spikes disappeared from the ground around your team!"); MESSAGE("The sticky web has disappeared from the ground around your team!"); MESSAGE("The poison spikes disappeared from the ground around your team!"); @@ -376,25 +692,43 @@ DOUBLE_BATTLE_TEST("Defog removes everything it can") MESSAGE("The pointed stones disappeared from around the opposing team!"); } } THEN { - EXPECT_EQ(gBattleStruct->hazardsQueue[0][0], HAZARDS_NONE); - EXPECT_EQ(gBattleStruct->hazardsQueue[0][1], HAZARDS_NONE); - EXPECT_EQ(gBattleStruct->hazardsQueue[0][2], HAZARDS_NONE); - EXPECT_EQ(gBattleStruct->hazardsQueue[0][3], HAZARDS_NONE); + if (config == GEN_6) { + EXPECT_EQ(gBattleStruct->hazardsQueue[0][0], HAZARDS_NONE); + EXPECT_EQ(gBattleStruct->hazardsQueue[0][1], HAZARDS_NONE); + EXPECT_EQ(gBattleStruct->hazardsQueue[0][2], HAZARDS_NONE); + EXPECT_EQ(gBattleStruct->hazardsQueue[0][3], HAZARDS_NONE); + } else { + EXPECT_EQ(gBattleStruct->hazardsQueue[0][0], HAZARDS_STICKY_WEB); + EXPECT_EQ(gBattleStruct->hazardsQueue[0][1], HAZARDS_SPIKES); + EXPECT_EQ(gBattleStruct->hazardsQueue[0][2], HAZARDS_STEALTH_ROCK); + EXPECT_EQ(gBattleStruct->hazardsQueue[0][3], HAZARDS_TOXIC_SPIKES); + } EXPECT_EQ(gBattleStruct->hazardsQueue[0][4], HAZARDS_NONE); EXPECT_EQ(gBattleStruct->hazardsQueue[0][5], HAZARDS_NONE); - EXPECT_EQ(gBattleStruct->hazardsQueue[1][0], HAZARDS_NONE); - EXPECT_EQ(gBattleStruct->hazardsQueue[1][1], HAZARDS_NONE); - EXPECT_EQ(gBattleStruct->hazardsQueue[1][2], HAZARDS_NONE); - EXPECT_EQ(gBattleStruct->hazardsQueue[1][3], HAZARDS_NONE); + if (config == GEN_6) { + EXPECT_EQ(gBattleStruct->hazardsQueue[1][0], HAZARDS_NONE); + EXPECT_EQ(gBattleStruct->hazardsQueue[1][1], HAZARDS_NONE); + EXPECT_EQ(gBattleStruct->hazardsQueue[1][2], HAZARDS_NONE); + EXPECT_EQ(gBattleStruct->hazardsQueue[1][3], HAZARDS_NONE); + } else { + EXPECT_EQ(gBattleStruct->hazardsQueue[1][0], HAZARDS_STICKY_WEB); + EXPECT_EQ(gBattleStruct->hazardsQueue[1][1], HAZARDS_SPIKES); + EXPECT_EQ(gBattleStruct->hazardsQueue[1][2], HAZARDS_TOXIC_SPIKES); + EXPECT_EQ(gBattleStruct->hazardsQueue[1][3], HAZARDS_STEALTH_ROCK); + } EXPECT_EQ(gBattleStruct->hazardsQueue[1][4], HAZARDS_NONE); EXPECT_EQ(gBattleStruct->hazardsQueue[1][5], HAZARDS_NONE); } } -SINGLE_BATTLE_TEST("Defog is used on the correct side if opposing mon is behind a substitute with Screen up") +SINGLE_BATTLE_TEST("Defog is used on the correct side if opposing mon is behind a Substitute with Screen up") { + u32 config; + PARAMETRIZE { config = GEN_4; } + PARAMETRIZE { config = GEN_5; } GIVEN { + WITH_CONFIG(CONFIG_DEFOG_EFFECT_CLEARING, config); PLAYER(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WOBBUFFET); } WHEN { @@ -405,7 +739,11 @@ SINGLE_BATTLE_TEST("Defog is used on the correct side if opposing mon is behind ANIMATION(ANIM_TYPE_MOVE, MOVE_SUBSTITUTE, opponent); MESSAGE("Wobbuffet used Defog!"); ANIMATION(ANIM_TYPE_MOVE, MOVE_DEFOG, player); - MESSAGE("The opposing Wobbuffet's evasiveness fell!"); MESSAGE("The opposing team's Light Screen wore off!"); + } THEN { + if (config >= GEN_5) + EXPECT_EQ(opponent->statStages[STAT_EVASION], DEFAULT_STAT_STAGE); + else + EXPECT_EQ(opponent->statStages[STAT_EVASION], DEFAULT_STAT_STAGE - 1); } } diff --git a/test/battle/move_effect/destiny_bond.c b/test/battle/move_effect/destiny_bond.c index ddebc6bb1f..ff532fa0d7 100644 --- a/test/battle/move_effect/destiny_bond.c +++ b/test/battle/move_effect/destiny_bond.c @@ -10,12 +10,18 @@ SINGLE_BATTLE_TEST("Destiny Bond faints the opposing mon if it fainted from the { GIVEN { PLAYER(SPECIES_WOBBUFFET) { HP(1); } + PLAYER(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WOBBUFFET); } WHEN { - TURN { MOVE(player, MOVE_DESTINY_BOND); MOVE(opponent, MOVE_SCRATCH); } + TURN { + MOVE(player, MOVE_DESTINY_BOND); + MOVE(opponent, MOVE_SCRATCH); + SEND_OUT(player, 1); + } } SCENE { ANIMATION(ANIM_TYPE_MOVE, MOVE_DESTINY_BOND, player); ANIMATION(ANIM_TYPE_MOVE, MOVE_SCRATCH, opponent); + MESSAGE("Wobbuffet fainted!"); MESSAGE("Wobbuffet took its attacker down with it!"); MESSAGE("The opposing Wobbuffet fainted!"); } @@ -24,7 +30,7 @@ SINGLE_BATTLE_TEST("Destiny Bond faints the opposing mon if it fainted from the SINGLE_BATTLE_TEST("Destiny Bond doesn't fail if used sequentially (Gen2-6)") { GIVEN { - WITH_CONFIG(GEN_CONFIG_DESTINY_BOND_FAIL, GEN_6); + WITH_CONFIG(CONFIG_DESTINY_BOND_FAIL, GEN_6); PLAYER(SPECIES_ZIGZAGOON); OPPONENT(SPECIES_ZIGZAGOON); OPPONENT(SPECIES_ZIGZAGOON); @@ -42,7 +48,7 @@ SINGLE_BATTLE_TEST("Destiny Bond doesn't fail if used sequentially (Gen2-6)") SINGLE_BATTLE_TEST("Destiny Bond fails if used sequentially (Gen7+)") { GIVEN { - WITH_CONFIG(GEN_CONFIG_DESTINY_BOND_FAIL, GEN_7); + WITH_CONFIG(CONFIG_DESTINY_BOND_FAIL, GEN_7); PLAYER(SPECIES_ZIGZAGOON); OPPONENT(SPECIES_ZIGZAGOON); OPPONENT(SPECIES_ZIGZAGOON); @@ -60,7 +66,7 @@ SINGLE_BATTLE_TEST("Destiny Bond fails if used sequentially (Gen7+)") SINGLE_BATTLE_TEST("Destiny Bond does not fail if used repeatedly separated by other moves (Gen7+)") { GIVEN { - WITH_CONFIG(GEN_CONFIG_DESTINY_BOND_FAIL, GEN_7); + WITH_CONFIG(CONFIG_DESTINY_BOND_FAIL, GEN_7); PLAYER(SPECIES_ZIGZAGOON); OPPONENT(SPECIES_ZIGZAGOON); OPPONENT(SPECIES_ZIGZAGOON); @@ -79,7 +85,7 @@ SINGLE_BATTLE_TEST("Destiny Bond does not fail if used repeatedly separated by o SINGLE_BATTLE_TEST("Destiny Bond does not fail if used after failing (Gen7+)") { GIVEN { - WITH_CONFIG(GEN_CONFIG_DESTINY_BOND_FAIL, GEN_7); + WITH_CONFIG(CONFIG_DESTINY_BOND_FAIL, GEN_7); PLAYER(SPECIES_ZIGZAGOON); OPPONENT(SPECIES_ZIGZAGOON); OPPONENT(SPECIES_ZIGZAGOON); diff --git a/test/battle/move_effect/doodle.c b/test/battle/move_effect/doodle.c index af144ecee5..3484dac6a0 100644 --- a/test/battle/move_effect/doodle.c +++ b/test/battle/move_effect/doodle.c @@ -84,7 +84,8 @@ DOUBLE_BATTLE_TEST("Doodle fails if partner has a banned Ability") DOUBLE_BATTLE_TEST("Doodle fails if ally's ability can't be suppressed") { - u32 species, ability; + u32 species; + enum Ability ability; PARAMETRIZE { species = SPECIES_ARCEUS; ability = ABILITY_MULTITYPE; } PARAMETRIZE { species = SPECIES_DARMANITAN; ability = ABILITY_ZEN_MODE; } diff --git a/test/battle/move_effect/dragon_cheer.c b/test/battle/move_effect/dragon_cheer.c index a7fff9e7d5..01458bdc11 100644 --- a/test/battle/move_effect/dragon_cheer.c +++ b/test/battle/move_effect/dragon_cheer.c @@ -28,7 +28,7 @@ DOUBLE_BATTLE_TEST("Dragon Cheer increases critical hit ratio by 1 on non-Dragon } PASSES_RANDOMLY(1, chance, RNG_CRITICAL_HIT); GIVEN { - WITH_CONFIG(GEN_CONFIG_CRIT_CHANCE, genConfig); + WITH_CONFIG(CONFIG_CRIT_CHANCE, genConfig); ASSUME(GetMoveCriticalHitStage(MOVE_SCRATCH) == 0); PLAYER(SPECIES_WOBBUFFET); PLAYER(SPECIES_WOBBUFFET); @@ -62,7 +62,7 @@ DOUBLE_BATTLE_TEST("Dragon Cheer increases critical hit ratio by 2 on Dragon typ } PASSES_RANDOMLY(passes, trials, RNG_CRITICAL_HIT); GIVEN { - WITH_CONFIG(GEN_CONFIG_CRIT_CHANCE, genConfig); + WITH_CONFIG(CONFIG_CRIT_CHANCE, genConfig); ASSUME(GetMoveCriticalHitStage(MOVE_SCRATCH) == 0); ASSUME(GetSpeciesBaseSpeed(SPECIES_DRATINI) == 50); PLAYER(SPECIES_WOBBUFFET); diff --git a/test/battle/move_effect/dragon_dance.c b/test/battle/move_effect/dragon_dance.c index 52587cc098..0d0cb6a4bc 100644 --- a/test/battle/move_effect/dragon_dance.c +++ b/test/battle/move_effect/dragon_dance.c @@ -1,4 +1,23 @@ #include "global.h" #include "test/battle.h" -TO_DO_BATTLE_TEST("Dragon Dance increases Attack and Speed by one stage each"); +ASSUMPTIONS +{ + ASSUME(GetMoveEffect(MOVE_DRAGON_DANCE) == EFFECT_DRAGON_DANCE); +} + +SINGLE_BATTLE_TEST("Dragon Dance increases the user's Attack and Speed by 1 stage each") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_DRAGON_DANCE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_DRAGON_DANCE, player); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); + } THEN { + EXPECT_EQ(player->statStages[STAT_ATK], DEFAULT_STAT_STAGE + 1); + EXPECT_EQ(player->statStages[STAT_SPEED], DEFAULT_STAT_STAGE + 1); + } +} diff --git a/test/battle/move_effect/dragon_darts.c b/test/battle/move_effect/dragon_darts.c index 40a9177589..97694909fe 100644 --- a/test/battle/move_effect/dragon_darts.c +++ b/test/battle/move_effect/dragon_darts.c @@ -97,7 +97,7 @@ DOUBLE_BATTLE_TEST("Dragon Darts strikes an opponent twice if electrified and th { struct BattlePokemon *chosenTarget = NULL; struct BattlePokemon *finalTarget = NULL; - u32 abilityLeft, abilityRight; + enum Ability abilityLeft, abilityRight; PARAMETRIZE { chosenTarget = opponentLeft; finalTarget = opponentLeft; abilityLeft = ABILITY_WATER_ABSORB; abilityRight = ABILITY_VOLT_ABSORB; } PARAMETRIZE { chosenTarget = opponentRight; finalTarget = opponentLeft; abilityLeft = ABILITY_WATER_ABSORB; abilityRight = ABILITY_VOLT_ABSORB; } PARAMETRIZE { chosenTarget = opponentLeft; finalTarget = opponentRight; abilityLeft = ABILITY_VOLT_ABSORB; abilityRight = ABILITY_WATER_ABSORB; } @@ -123,7 +123,7 @@ DOUBLE_BATTLE_TEST("Dragon Darts strikes an opponent twice if electrified and th { struct BattlePokemon *chosenTarget = NULL; struct BattlePokemon *finalTarget = NULL; - u32 abilityLeft, abilityRight; + enum Ability abilityLeft, abilityRight; PARAMETRIZE { chosenTarget = opponentLeft; finalTarget = opponentLeft; abilityLeft = ABILITY_VITAL_SPIRIT; abilityRight = ABILITY_MOTOR_DRIVE; } PARAMETRIZE { chosenTarget = opponentRight; finalTarget = opponentLeft; abilityLeft = ABILITY_VITAL_SPIRIT; abilityRight = ABILITY_MOTOR_DRIVE; } PARAMETRIZE { chosenTarget = opponentLeft; finalTarget = opponentRight; abilityLeft = ABILITY_MOTOR_DRIVE; abilityRight = ABILITY_VITAL_SPIRIT; } diff --git a/test/battle/move_effect/dream_eater.c b/test/battle/move_effect/dream_eater.c index baefd2e4ff..183a513b79 100644 --- a/test/battle/move_effect/dream_eater.c +++ b/test/battle/move_effect/dream_eater.c @@ -96,6 +96,7 @@ SINGLE_BATTLE_TEST("Dream Eater works if the target is behind a Substitute (Gen { s16 damage; s16 healed; + KNOWN_FAILING; GIVEN { ASSUME(GetMoveEffect(MOVE_YAWN) == EFFECT_YAWN); ASSUME(GetMoveEffect(MOVE_SUBSTITUTE) == EFFECT_SUBSTITUTE); diff --git a/test/battle/move_effect/encore.c b/test/battle/move_effect/encore.c index 2c4ade2c88..094191f665 100644 --- a/test/battle/move_effect/encore.c +++ b/test/battle/move_effect/encore.c @@ -14,7 +14,7 @@ SINGLE_BATTLE_TEST("Encore forces consecutive move uses for 3 turns: Encore used PARAMETRIZE { encoreUser = opponent; encoreTarget = player; speedPlayer = 10; speedOpponent = 20; } PARAMETRIZE { encoreUser = player; encoreTarget = opponent; speedPlayer = 20; speedOpponent = 10; } GIVEN { - WITH_CONFIG(GEN_CONFIG_ENCORE_TARGET, GEN_3); + WITH_CONFIG(CONFIG_ENCORE_TARGET, GEN_3); PLAYER(SPECIES_WOBBUFFET) { Speed(speedPlayer); } OPPONENT(SPECIES_WOBBUFFET) { Speed(speedOpponent); } } WHEN { @@ -42,7 +42,7 @@ SINGLE_BATTLE_TEST("Encore forces consecutive move uses for 3 turns for player: PARAMETRIZE { encoreUser = opponent; encoreTarget = player; speedPlayer = 20; speedOpponent = 10; } PARAMETRIZE { encoreUser = player; encoreTarget = opponent; speedPlayer = 10; speedOpponent = 20; } GIVEN { - WITH_CONFIG(GEN_CONFIG_ENCORE_TARGET, GEN_3); + WITH_CONFIG(CONFIG_ENCORE_TARGET, GEN_3); PLAYER(SPECIES_WOBBUFFET) { Speed(speedPlayer); } OPPONENT(SPECIES_WOBBUFFET) { Speed(speedOpponent); } } WHEN { diff --git a/test/battle/move_effect/fail_if_not_arg_type.c b/test/battle/move_effect/fail_if_not_arg_type.c index c1371d393d..9714c15752 100644 --- a/test/battle/move_effect/fail_if_not_arg_type.c +++ b/test/battle/move_effect/fail_if_not_arg_type.c @@ -42,9 +42,8 @@ TO_DO_BATTLE_TEST("Burn Up doesn't thaw the user if it fails due to the user not SINGLE_BATTLE_TEST("Burn Up fails if the user has Protean/Libero and is not a Fire-type") { - KNOWN_FAILING; GIVEN { - WITH_CONFIG(GEN_PROTEAN_LIBERO, GEN_6); + WITH_CONFIG(CONFIG_PROTEAN_LIBERO, GEN_6); PLAYER(SPECIES_REGIROCK); OPPONENT(SPECIES_KECLEON) { Ability(ABILITY_PROTEAN); } OPPONENT(SPECIES_WOBBUFFET); @@ -52,7 +51,10 @@ SINGLE_BATTLE_TEST("Burn Up fails if the user has Protean/Libero and is not a Fi TURN { MOVE(opponent, MOVE_BURN_UP); } } SCENE { MESSAGE("The opposing Kecleon used Burn Up!"); - NONE_OF { ANIMATION(ANIM_TYPE_MOVE, MOVE_BURN_UP, player); } + NONE_OF { + ABILITY_POPUP(opponent, ABILITY_PROTEAN); + ANIMATION(ANIM_TYPE_MOVE, MOVE_BURN_UP, player); + } MESSAGE("But it failed!"); } } diff --git a/test/battle/move_effect/fell_stinger.c b/test/battle/move_effect/fell_stinger.c index a5112fe897..8d395080fe 100644 --- a/test/battle/move_effect/fell_stinger.c +++ b/test/battle/move_effect/fell_stinger.c @@ -9,7 +9,7 @@ SINGLE_BATTLE_TEST("Fell Stinger raises user's Attack by 2 stages (Gen6) or 3 st PARAMETRIZE { config = GEN_6; } GIVEN { - WITH_CONFIG(GEN_CONFIG_FELL_STINGER_STAT_RAISE, config); + WITH_CONFIG(CONFIG_FELL_STINGER_STAT_RAISE, config); PLAYER(SPECIES_WOBBUFFET) { Moves(MOVE_FELL_STINGER); } OPPONENT(SPECIES_WOBBUFFET) { HP(1); } OPPONENT(SPECIES_WOBBUFFET); diff --git a/test/battle/move_effect/fixed_damage_arg.c b/test/battle/move_effect/fixed_hp_damage.c similarity index 100% rename from test/battle/move_effect/fixed_damage_arg.c rename to test/battle/move_effect/fixed_hp_damage.c diff --git a/test/battle/move_effect/fixed_percent_damage.c b/test/battle/move_effect/fixed_percent_damage.c new file mode 100644 index 0000000000..408139b98e --- /dev/null +++ b/test/battle/move_effect/fixed_percent_damage.c @@ -0,0 +1,9 @@ +#include "global.h" +#include "test/battle.h" + +TO_DO_BATTLE_TEST("Super Fang does 50% damage to the target's current HP") +TO_DO_BATTLE_TEST("Super Fang always deals at least 1 HP of damage") +TO_DO_BATTLE_TEST("Super Fang is unaffected by type immunities (Gen 1)") +TO_DO_BATTLE_TEST("Super Fang doesn't hit Ghost-type Pokémon (Gen 2+)") + +TO_DO_BATTLE_TEST("Guardian of Alola does 75% damage to the target's current HP") diff --git a/test/battle/move_effect/flatter.c b/test/battle/move_effect/flatter.c index d9d05a98f2..ce798e555c 100644 --- a/test/battle/move_effect/flatter.c +++ b/test/battle/move_effect/flatter.c @@ -1,7 +1,27 @@ #include "global.h" #include "test/battle.h" -TO_DO_BATTLE_TEST("Flatter raises the target's Sp. Atk and confuses them") +ASSUMPTIONS +{ + ASSUME(GetMoveEffect(MOVE_FLATTER) == EFFECT_FLATTER); +} + +SINGLE_BATTLE_TEST("Flatter increases the target's Sp. Attack by 1 stage and confuses them") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_FLATTER); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_FLATTER, player); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); + } THEN { + EXPECT_EQ(opponent->statStages[STAT_SPATK], DEFAULT_STAT_STAGE + 1); + EXPECT(opponent->volatiles.confusionTurns > 0); + } +} + TO_DO_BATTLE_TEST("Flatter raises the target's Sp. Atk even if they're already confused") TO_DO_BATTLE_TEST("Flatter raises the target's Sp. Atk even when protected by Safeguard") TO_DO_BATTLE_TEST("Flatter raises the target's Sp. Atk even when protected Own Tempo") diff --git a/test/battle/move_effect/fling.c b/test/battle/move_effect/fling.c index 5435fbcafe..2046ebe638 100644 --- a/test/battle/move_effect/fling.c +++ b/test/battle/move_effect/fling.c @@ -58,7 +58,7 @@ SINGLE_BATTLE_TEST("Fling fails if Pokémon is under the effects of Embargo or M SINGLE_BATTLE_TEST("Fling fails for Pokémon with Klutz ability") { - u16 ability; + enum Ability ability; PARAMETRIZE {ability = ABILITY_KLUTZ; } PARAMETRIZE {ability = ABILITY_RUN_AWAY; } @@ -80,8 +80,35 @@ SINGLE_BATTLE_TEST("Fling fails for Pokémon with Klutz ability") } } -TO_DO_BATTLE_TEST("Fling fails if the item changes the Pokémon's form") -TO_DO_BATTLE_TEST("Fling works if the item changes a Pokémon's form but not the one holding it") //Eg. non-matching Mega Stones +SINGLE_BATTLE_TEST("Fling fails if the item changes the Pokémon's form") +{ + GIVEN { + PLAYER(SPECIES_GIRATINA_ORIGIN) { Item(ITEM_GRISEOUS_CORE); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_FLING); } + } SCENE { + MESSAGE("But it failed!"); + } THEN { + EXPECT(player->item == ITEM_GRISEOUS_CORE); + } +} + +SINGLE_BATTLE_TEST("Fling works if the item changes a Pokémon's form but not the one holding it") +{ + GIVEN { + PLAYER(SPECIES_VENUSAUR) { Item(ITEM_BLASTOISINITE); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_FLING); } + } SCENE { + NOT MESSAGE("But it failed!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_FLING, player); + HP_BAR(opponent); + } THEN { + EXPECT(player->item == ITEM_NONE); + } +} SINGLE_BATTLE_TEST("Fling's thrown item can be regained with Recycle") { @@ -153,6 +180,23 @@ SINGLE_BATTLE_TEST("Fling - Item is lost when target protects itself") } } +SINGLE_BATTLE_TEST("Fling - Item does not get blocked by Unnerve if it isn't a berry") +{ + GIVEN { + ASSUME(GetMoveEffect(MOVE_TAUNT) == EFFECT_TAUNT); + PLAYER(SPECIES_CALYREX) { Item(ITEM_MENTAL_HERB); Ability(ABILITY_UNNERVE); } + OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_ORAN_BERRY); } + } WHEN { + TURN { MOVE(player, MOVE_TAUNT); MOVE(opponent, MOVE_SCRATCH); } + TURN { MOVE(player, MOVE_FLING); MOVE(opponent, MOVE_SCRATCH); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_TAUNT, player); + ANIMATION(ANIM_TYPE_MOVE, MOVE_FLING, player); + HP_BAR(opponent); + MESSAGE("The opposing Wobbuffet's Taunt wore off!"); + } +} + SINGLE_BATTLE_TEST("Fling doesn't consume the item if Pokémon is asleep/frozen/paralyzed") { u32 status; @@ -461,4 +505,46 @@ SINGLE_BATTLE_TEST("Fling deals damage based on items fling power") } } -TO_DO_BATTLE_TEST("Fling deals damage based on a TM's move power") +SINGLE_BATTLE_TEST("Fling deals damage based on a TM's move power") +{ + s16 damage[2]; + + GIVEN { + ASSUME(GetMovePower(MOVE_EARTHQUAKE) == GetMovePower(MOVE_EGG_BOMB)); + ASSUME(!IsSpeciesOfType(SPECIES_WOBBUFFET, TYPE_DARK)); + PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_TM_EARTHQUAKE); } + OPPONENT(SPECIES_HIPPOWDON); + } WHEN { + TURN { MOVE(player, MOVE_FLING); } + TURN { MOVE(player, MOVE_EGG_BOMB); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_FLING, player); + HP_BAR(opponent, captureDamage: &damage[0]); + ANIMATION(ANIM_TYPE_MOVE, MOVE_EGG_BOMB, player); + HP_BAR(opponent, captureDamage: &damage[1]); + } THEN { + EXPECT_EQ(damage[0], damage[1]); + } +} + +SINGLE_BATTLE_TEST("Fling deals damage based on a TM's move power") +{ + s16 damage[2]; + + GIVEN { + ASSUME(GetMovePower(MOVE_EARTHQUAKE) == GetMovePower(MOVE_EGG_BOMB)); + ASSUME(!IsSpeciesOfType(SPECIES_WOBBUFFET, TYPE_DARK)); + PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_TM_EARTHQUAKE); } + OPPONENT(SPECIES_HIPPOWDON); + } WHEN { + TURN { MOVE(player, MOVE_FLING); } + TURN { MOVE(player, MOVE_EGG_BOMB); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_FLING, player); + HP_BAR(opponent, captureDamage: &damage[0]); + ANIMATION(ANIM_TYPE_MOVE, MOVE_EGG_BOMB, player); + HP_BAR(opponent, captureDamage: &damage[1]); + } THEN { + EXPECT_EQ(damage[0], damage[1]); + } +} diff --git a/test/battle/move_effect/flower_shield.c b/test/battle/move_effect/flower_shield.c index d690869fa3..4a72163855 100644 --- a/test/battle/move_effect/flower_shield.c +++ b/test/battle/move_effect/flower_shield.c @@ -71,3 +71,19 @@ DOUBLE_BATTLE_TEST("Flower Shield doesn't affect Grass-type Pokémon that are in } } } + +AI_DOUBLE_BATTLE_TEST("AI uses Flower Shield") +{ + GIVEN { + ASSUME(GetSpeciesType(SPECIES_TANGELA, 0) == TYPE_GRASS); + ASSUME(GetSpeciesType(SPECIES_WOBBUFFET, 0) != TYPE_GRASS); + ASSUME(GetSpeciesType(SPECIES_WOBBUFFET, 1) != TYPE_GRASS); + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_OMNISCIENT); + PLAYER(SPECIES_WOBBUFFET) { Moves(MOVE_POUND, MOVE_CELEBRATE); } + PLAYER(SPECIES_WOBBUFFET) { Moves(MOVE_POUND, MOVE_CELEBRATE); } + OPPONENT(SPECIES_TANGELA) { Moves(MOVE_FLOWER_SHIELD, MOVE_POUND); } + OPPONENT(SPECIES_TANGELA); + } WHEN { + TURN { EXPECT_MOVE(opponentLeft, MOVE_FLOWER_SHIELD); } + } +} diff --git a/test/battle/move_effect/focus_energy.c b/test/battle/move_effect/focus_energy.c index 17a08ba7f3..363e6bd563 100644 --- a/test/battle/move_effect/focus_energy.c +++ b/test/battle/move_effect/focus_energy.c @@ -23,8 +23,8 @@ SINGLE_BATTLE_TEST("Focus Energy increases the user's critical hit ratio by 1 st } PASSES_RANDOMLY(1, chance, RNG_CRITICAL_HIT); GIVEN { - WITH_CONFIG(GEN_CONFIG_CRIT_CHANCE, (genConfig == GEN_1)? GEN_2 : genConfig); - WITH_CONFIG(GEN_CONFIG_FOCUS_ENERGY_CRIT_RATIO, genConfig); + WITH_CONFIG(CONFIG_CRIT_CHANCE, (genConfig == GEN_1)? GEN_2 : genConfig); + WITH_CONFIG(CONFIG_FOCUS_ENERGY_CRIT_RATIO, genConfig); ASSUME(GetSpeciesBaseSpeed(SPECIES_WOBBUFFET) == 33); PLAYER(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WOBBUFFET); @@ -50,8 +50,8 @@ SINGLE_BATTLE_TEST("Focus Energy multiplies crit chance by 4 with gen 1 crit cha } PASSES_RANDOMLY(1, chance, RNG_CRITICAL_HIT); GIVEN { - WITH_CONFIG(GEN_CONFIG_CRIT_CHANCE, GEN_1); - WITH_CONFIG(GEN_CONFIG_FOCUS_ENERGY_CRIT_RATIO, genConfig); + WITH_CONFIG(CONFIG_CRIT_CHANCE, GEN_1); + WITH_CONFIG(CONFIG_FOCUS_ENERGY_CRIT_RATIO, genConfig); ASSUME(GetSpeciesBaseSpeed(SPECIES_WOBBUFFET) == 33); PLAYER(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WOBBUFFET); diff --git a/test/battle/move_effect/focus_punch.c b/test/battle/move_effect/focus_punch.c index 3f8f96d4c4..35f26ae9ee 100644 --- a/test/battle/move_effect/focus_punch.c +++ b/test/battle/move_effect/focus_punch.c @@ -118,6 +118,9 @@ AI_SINGLE_BATTLE_TEST("AI won't use status moves if the player's best attacking GIVEN { ASSUME(GetMoveEffect(MOVE_FOCUS_PUNCH) == EFFECT_FOCUS_PUNCH); ASSUME(GetMoveCategory(MOVE_SWORDS_DANCE) == DAMAGE_CATEGORY_STATUS); + // If Clefable is Normal-type, it will always use Play Rough. + ASSUME(GetSpeciesType(SPECIES_CLEFABLE, 0) == TYPE_FAIRY); + ASSUME(GetSpeciesType(SPECIES_CLEFABLE, 1) == TYPE_FAIRY); AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_OMNISCIENT); PLAYER(SPECIES_SNORLAX) { Moves(MOVE_FOCUS_PUNCH, MOVE_POUND); } OPPONENT(SPECIES_CLEFABLE) { Moves(MOVE_PLAY_ROUGH, MOVE_SWORDS_DANCE); } diff --git a/test/battle/move_effect/gastro_acid.c b/test/battle/move_effect/gastro_acid.c index 8cb0a7d4af..1bbc8c0d5b 100644 --- a/test/battle/move_effect/gastro_acid.c +++ b/test/battle/move_effect/gastro_acid.c @@ -8,7 +8,8 @@ ASSUMPTIONS SINGLE_BATTLE_TEST("Gastro Acid fails if target has a banned ability") { - u32 species, ability; + u32 species; + enum Ability ability; PARAMETRIZE { species = SPECIES_ARCEUS; ability = ABILITY_MULTITYPE; } PARAMETRIZE { species = SPECIES_AEGISLASH; ability = ABILITY_STANCE_CHANGE; } diff --git a/test/battle/move_effect/gear_up.c b/test/battle/move_effect/gear_up.c index 03aba9a395..8689d6d268 100644 --- a/test/battle/move_effect/gear_up.c +++ b/test/battle/move_effect/gear_up.c @@ -1,4 +1,17 @@ #include "global.h" #include "test/battle.h" -TO_DO_BATTLE_TEST("TODO: Write Gear Up (Move Effect) test titles") +TO_DO_BATTLE_TEST("Gear Up increases the Attack and Sp. Attack of the user and allies if they have Plus or Minus") + +AI_DOUBLE_BATTLE_TEST("AI uses Gear Up") +{ + GIVEN { + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_OMNISCIENT); + PLAYER(SPECIES_WOBBUFFET) { Moves(MOVE_POUND, MOVE_CELEBRATE); } + PLAYER(SPECIES_WOBBUFFET) { Moves(MOVE_POUND, MOVE_CELEBRATE); } + OPPONENT(SPECIES_KLINKLANG) { Ability(ABILITY_PLUS); Moves(MOVE_GEAR_UP, MOVE_WATER_GUN, MOVE_POUND); } + OPPONENT(SPECIES_KLINKLANG) { Ability(ABILITY_PLUS); Moves(MOVE_GEAR_UP, MOVE_WATER_GUN, MOVE_POUND); } + } WHEN { + TURN { EXPECT_MOVE(opponentLeft, MOVE_GEAR_UP); } + } +} diff --git a/test/battle/move_effect/geomancy.c b/test/battle/move_effect/geomancy.c index f5b113a452..934e5e2f0a 100644 --- a/test/battle/move_effect/geomancy.c +++ b/test/battle/move_effect/geomancy.c @@ -1,4 +1,6 @@ #include "global.h" #include "test/battle.h" -TO_DO_BATTLE_TEST("TODO: Write Geomancy (Move Effect) test titles") +TO_DO_BATTLE_TEST("Geomancy takes 2 turns to increase Sp. Atk, Sp. Def and Speed by 2 stages"); +TO_DO_BATTLE_TEST("Geomancy only takes 1 turn when holding Power Herb") +TO_DO_BATTLE_TEST("Geomancy fails on the second turn if the user falls for Taunt while charging") diff --git a/test/battle/move_effect/glaive_rush.c b/test/battle/move_effect/glaive_rush.c index faf1f96664..ff949a57cd 100644 --- a/test/battle/move_effect/glaive_rush.c +++ b/test/battle/move_effect/glaive_rush.c @@ -96,8 +96,8 @@ SINGLE_BATTLE_TEST("Glaive Rush doesn't affect the user if the effect is blocked { u32 species; - PARAMETRIZE { species = SPECIES_CLEFAIRY; } - PARAMETRIZE { species = SPECIES_SHELLOS; } // Closest mon in both Defense and Sp. Defense + PARAMETRIZE { species = SPECIES_FIDOUGH; } + PARAMETRIZE { species = SPECIES_MAGNEMITE; } // Closest mon in both Defense and Sp. Defense GIVEN { PLAYER(SPECIES_WOBBUFFET); @@ -105,7 +105,7 @@ SINGLE_BATTLE_TEST("Glaive Rush doesn't affect the user if the effect is blocked } WHEN { TURN { MOVE(player, MOVE_GLAIVE_RUSH); MOVE(opponent, MOVE_SCRATCH); } } SCENE { - if (species == SPECIES_CLEFAIRY) + if (species == SPECIES_FIDOUGH) NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_GLAIVE_RUSH, player); else ANIMATION(ANIM_TYPE_MOVE, MOVE_GLAIVE_RUSH, player); diff --git a/test/battle/move_effect/grassy_glide.c b/test/battle/move_effect/grassy_glide.c index 00219fb1dd..64e3300970 100644 --- a/test/battle/move_effect/grassy_glide.c +++ b/test/battle/move_effect/grassy_glide.c @@ -1,4 +1,5 @@ #include "global.h" #include "test/battle.h" -TO_DO_BATTLE_TEST("TODO: Write Grassy Glide (Move Effect) test titles") +TO_DO_BATTLE_TEST("Grassy Glide's priority increases by 1 when the user is affected by Grassy Terrain") +TO_DO_BATTLE_TEST("Dynamax: Grassy Glide's priority doesn't increase for the Max Move it becomes") diff --git a/test/battle/move_effect/grav_apple.c b/test/battle/move_effect/grav_apple.c index 7ce2dd26c7..f2c3099fdc 100644 --- a/test/battle/move_effect/grav_apple.c +++ b/test/battle/move_effect/grav_apple.c @@ -1,4 +1,5 @@ #include "global.h" #include "test/battle.h" -TO_DO_BATTLE_TEST("TODO: Write Grav Apple (Move Effect) test titles") +TO_DO_BATTLE_TEST("Grav Apple lowers the target's Defense by 1 stage") +TO_DO_BATTLE_TEST("Grav Apple's power increases by 50% under Gravity's effect") diff --git a/test/battle/move_effect/gravity.c b/test/battle/move_effect/gravity.c index baac7a53ea..001505bae0 100644 --- a/test/battle/move_effect/gravity.c +++ b/test/battle/move_effect/gravity.c @@ -6,7 +6,11 @@ ASSUMPTIONS ASSUME(GetMoveEffect(MOVE_GRAVITY) == EFFECT_GRAVITY); } -DOUBLE_BATTLE_TEST("Gravity cancels fly and sky drop if they are in the air") +TO_DO_BATTLE_TEST("Gravity causes certain moves to fail") // Fly, Jump Kick, High Jump Kick, Splash, Bounce, Magnet Rise, Telekinesis, Sky Drop, Flying Press, Floaty Fall +TO_DO_BATTLE_TEST("Gravity increases accuracy of all moves by 5/3 (~1.67)") +TO_DO_BATTLE_TEST("Gravity causes all battlers to become grounded") + +DOUBLE_BATTLE_TEST("Gravity cancels Fly and Sky Drop if they are in the air") { u8 visibility; GIVEN { @@ -45,3 +49,35 @@ DOUBLE_BATTLE_TEST("Gravity cancels fly and sky drop if they are in the air") EXPECT_EQ(gLastMoves[0], MOVE_GRAVITY); } } + +AI_DOUBLE_BATTLE_TEST("AI uses Gravity") +{ + u32 move, friendItem, foeItem; + u64 aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT; + + PARAMETRIZE { move = MOVE_THUNDER; friendItem = ITEM_NONE; foeItem = ITEM_NONE; } + PARAMETRIZE { move = MOVE_HEADBUTT; friendItem = ITEM_AIR_BALLOON; foeItem = ITEM_NONE; } + PARAMETRIZE { move = MOVE_HEADBUTT; friendItem = ITEM_AIR_BALLOON; foeItem = ITEM_AIR_BALLOON; } + PARAMETRIZE { move = MOVE_HEADBUTT; friendItem = ITEM_NONE; foeItem = ITEM_AIR_BALLOON; } + PARAMETRIZE { aiFlags |= AI_FLAG_OMNISCIENT | AI_FLAG_SMART_SWITCHING | AI_FLAG_SMART_MON_CHOICES | AI_FLAG_PP_STALL_PREVENTION; + move = MOVE_THUNDER; friendItem = ITEM_NONE; foeItem = ITEM_NONE; } + PARAMETRIZE { aiFlags |= AI_FLAG_OMNISCIENT | AI_FLAG_SMART_SWITCHING | AI_FLAG_SMART_MON_CHOICES | AI_FLAG_PP_STALL_PREVENTION; + move = MOVE_HEADBUTT; friendItem = ITEM_AIR_BALLOON; foeItem = ITEM_NONE; } + PARAMETRIZE { aiFlags |= AI_FLAG_OMNISCIENT | AI_FLAG_SMART_SWITCHING | AI_FLAG_SMART_MON_CHOICES | AI_FLAG_PP_STALL_PREVENTION; + move = MOVE_HEADBUTT; friendItem = ITEM_AIR_BALLOON; foeItem = ITEM_AIR_BALLOON; } + PARAMETRIZE { aiFlags |= AI_FLAG_OMNISCIENT | AI_FLAG_SMART_SWITCHING | AI_FLAG_SMART_MON_CHOICES | AI_FLAG_PP_STALL_PREVENTION; + move = MOVE_HEADBUTT; friendItem = ITEM_NONE; foeItem = ITEM_AIR_BALLOON; } + + GIVEN { + AI_FLAGS(aiFlags); + PLAYER(SPECIES_WOBBUFFET) { Item(foeItem); } + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_GRAVITY, MOVE_HEADBUTT, MOVE_TAUNT); } + OPPONENT(SPECIES_WOBBUFFET) { Moves(move, MOVE_EARTH_POWER); Item(friendItem); } + } WHEN { + if (move == MOVE_THUNDER || (foeItem == ITEM_AIR_BALLOON && friendItem != ITEM_AIR_BALLOON)) + TURN { EXPECT_MOVE(opponentLeft, MOVE_GRAVITY); } + else + TURN { NOT_EXPECT_MOVE(opponentLeft, MOVE_GRAVITY); } + } +} diff --git a/test/battle/move_effect/growth.c b/test/battle/move_effect/growth.c index 7b53f56cfc..a9dda9cfd5 100644 --- a/test/battle/move_effect/growth.c +++ b/test/battle/move_effect/growth.c @@ -1,4 +1,6 @@ #include "global.h" #include "test/battle.h" -TO_DO_BATTLE_TEST("TODO: Write Growth (Move Effect) test titles") +TO_DO_BATTLE_TEST("Growth increases Sp. Atk and Sp. Def by 1 stage (Gen 1)") // Equivalent to raising Special +TO_DO_BATTLE_TEST("Growth increases Sp. Atk by 1 stage (Gen 2-4)") +TO_DO_BATTLE_TEST("Growth increases Attack and Sp. Atk by 1 stage or 2 stages under Sun (Gen 5+)") diff --git a/test/battle/move_effect/grudge.c b/test/battle/move_effect/grudge.c index f0e0e53b6a..2b74a3b05a 100644 --- a/test/battle/move_effect/grudge.c +++ b/test/battle/move_effect/grudge.c @@ -1,4 +1,61 @@ #include "global.h" #include "test/battle.h" -TO_DO_BATTLE_TEST("TODO: Write Grudge (Move Effect) test titles") +SINGLE_BATTLE_TEST("Grudge depletes all PP of the move that fainted the target") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { HP(1); } + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_CELEBRATE, MOVE_SCRATCH, MOVE_POUND, MOVE_SURF); }; + } WHEN { + TURN { + MOVE(player, MOVE_GRUDGE); + MOVE(opponent, MOVE_SCRATCH); + SEND_OUT(player, 1); + } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_GRUDGE, player); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SCRATCH, opponent); + MESSAGE("Wobbuffet fainted!"); + } THEN { + EXPECT_GT(opponent->pp[0], 0); + EXPECT_EQ(opponent->pp[1], 0); + EXPECT_GT(opponent->pp[2], 0); + EXPECT_GT(opponent->pp[3], 0); + } +} + +SINGLE_BATTLE_TEST("Grudge does not deplete PP of a Z-Move") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { HP(1); } + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_NORMALIUM_Z); Moves(MOVE_CELEBRATE, MOVE_SCRATCH, MOVE_POUND, MOVE_SURF); }; + } WHEN { + TURN { + MOVE(player, MOVE_GRUDGE); + MOVE(opponent, MOVE_SCRATCH, gimmick: GIMMICK_Z_MOVE); + SEND_OUT(player, 1); + } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_GRUDGE, player); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_ZMOVE_ACTIVATE, opponent); + ANIMATION(ANIM_TYPE_MOVE, MOVE_BREAKNECK_BLITZ, opponent); + MESSAGE("Wobbuffet fainted!"); + } THEN { + EXPECT_GT(opponent->pp[0], 0); + EXPECT_GT(opponent->pp[1], 0); + EXPECT_GT(opponent->pp[2], 0); + EXPECT_GT(opponent->pp[3], 0); + } +} + +TO_DO_BATTLE_TEST("Grudge depletes all PP from a Max Move's base move") +TO_DO_BATTLE_TEST("Grudge does not activate for Struggle") +TO_DO_BATTLE_TEST("Grudge's effect disappears if the user takes a new turn - Move"); +TO_DO_BATTLE_TEST("Grudge's effect disappears if the user takes a new turn - Sleep"); +TO_DO_BATTLE_TEST("Grudge's effect disappears if the user takes a new turn - Paralysis"); +TO_DO_BATTLE_TEST("Grudge's effect disappears if the user takes a new turn - Flinching"); +TO_DO_BATTLE_TEST("Grudge's effect doesn't trigger on indirect damage - Sandstorm"); +TO_DO_BATTLE_TEST("Grudge's effect doesn't trigger on indirect damage - Leech Seed"); +TO_DO_BATTLE_TEST("Grudge's effect doesn't trigger on indirect damage - Future Sight"); diff --git a/test/battle/move_effect/guard_split.c b/test/battle/move_effect/guard_split.c index d7572c1431..15b14c59d2 100644 --- a/test/battle/move_effect/guard_split.c +++ b/test/battle/move_effect/guard_split.c @@ -20,3 +20,7 @@ SINGLE_BATTLE_TEST("Guard Split averages users and targets Def and Sp. Def stats EXPECT_EQ(player->spDefense, opponent->spDefense); } } + +TO_DO_BATTLE_TEST("Stat stages use Guard Split's altered stats") +TO_DO_BATTLE_TEST("Assault Vest uses Guard Split's altered stats") +TO_DO_BATTLE_TEST("Eviolite uses Guard Split's altered stats") diff --git a/test/battle/move_effect/guard_swap.c b/test/battle/move_effect/guard_swap.c index f0e0e53b6a..d4be4dbd93 100644 --- a/test/battle/move_effect/guard_swap.c +++ b/test/battle/move_effect/guard_swap.c @@ -1,4 +1,4 @@ #include "global.h" #include "test/battle.h" -TO_DO_BATTLE_TEST("TODO: Write Grudge (Move Effect) test titles") +TO_DO_BATTLE_TEST("Guard Swap switches the user's Defense and Sp. Def stat stages with the target") diff --git a/test/battle/move_effect/guardian_of_alola.c b/test/battle/move_effect/guardian_of_alola.c deleted file mode 100644 index fe33236363..0000000000 --- a/test/battle/move_effect/guardian_of_alola.c +++ /dev/null @@ -1,4 +0,0 @@ -#include "global.h" -#include "test/battle.h" - -TO_DO_BATTLE_TEST("TODO: Write Guardian of Alola (Move Effect) test titles") diff --git a/test/battle/move_effect/heal_bell.c b/test/battle/move_effect/heal_bell.c index b3f6af0c45..e2ca05206a 100644 --- a/test/battle/move_effect/heal_bell.c +++ b/test/battle/move_effect/heal_bell.c @@ -86,7 +86,8 @@ DOUBLE_BATTLE_TEST("Heal Bell/Aromatherapy cures the entire party of the user fr DOUBLE_BATTLE_TEST("Heal Bell does not cure Soundproof partners (Gen 4, Gen 6+)") { - u32 ability, config; + enum Ability ability; + u32 config; PARAMETRIZE { ability = ABILITY_SCRAPPY; config = GEN_4; } PARAMETRIZE { ability = ABILITY_SOUNDPROOF; config = GEN_4; } @@ -95,7 +96,7 @@ DOUBLE_BATTLE_TEST("Heal Bell does not cure Soundproof partners (Gen 4, Gen 6+)" GIVEN { ASSUME(IsSoundMove(MOVE_HEAL_BELL)); - WITH_CONFIG(GEN_CONFIG_HEAL_BELL_SOUNDPROOF, config); + WITH_CONFIG(CONFIG_HEAL_BELL_SOUNDPROOF, config); PLAYER(SPECIES_WOBBUFFET); PLAYER(SPECIES_EXPLOUD) { Ability(ability); Status1(STATUS1_POISON); } OPPONENT(SPECIES_WYNAUT); @@ -114,7 +115,8 @@ DOUBLE_BATTLE_TEST("Heal Bell does not cure Soundproof partners (Gen 4, Gen 6+)" SINGLE_BATTLE_TEST("Heal Bell cures inactive Soundproof Pokemon (Gen5+)") { - u32 config, ability; + u32 config; + enum Ability ability; PARAMETRIZE { config = GEN_4, ability = ABILITY_SCRAPPY; } PARAMETRIZE { config = GEN_4, ability = ABILITY_SOUNDPROOF; } @@ -122,7 +124,7 @@ SINGLE_BATTLE_TEST("Heal Bell cures inactive Soundproof Pokemon (Gen5+)") GIVEN { ASSUME(IsSoundMove(MOVE_HEAL_BELL)); - WITH_CONFIG(GEN_CONFIG_HEAL_BELL_SOUNDPROOF, config); + WITH_CONFIG(CONFIG_HEAL_BELL_SOUNDPROOF, config); PLAYER(SPECIES_WOBBUFFET) { Status1(STATUS1_POISON); } PLAYER(SPECIES_EXPLOUD) { Ability(ability); Status1(STATUS1_POISON); } OPPONENT(SPECIES_WYNAUT); @@ -150,7 +152,7 @@ SINGLE_BATTLE_TEST("Heal Bell cures a Soundproof user (Gen5, Gen8+)") PARAMETRIZE { config = GEN_8; } GIVEN { ASSUME(IsSoundMove(MOVE_HEAL_BELL)); - WITH_CONFIG(GEN_CONFIG_HEAL_BELL_SOUNDPROOF, config); + WITH_CONFIG(CONFIG_HEAL_BELL_SOUNDPROOF, config); PLAYER(SPECIES_EXPLOUD) { Ability(ABILITY_SOUNDPROOF); Status1(STATUS1_POISON); } OPPONENT(SPECIES_WYNAUT); } WHEN { @@ -164,3 +166,53 @@ SINGLE_BATTLE_TEST("Heal Bell cures a Soundproof user (Gen5, Gen8+)") } } } + +DOUBLE_BATTLE_TEST("Aromatherapy cure Soundproof battlers regardless of config") +{ + u32 ability, config; + + PARAMETRIZE { ability = ABILITY_SOUNDPROOF; config = GEN_4; } + PARAMETRIZE { ability = ABILITY_SOUNDPROOF; config = GEN_5; } + PARAMETRIZE { ability = ABILITY_SOUNDPROOF; config = GEN_6; } + PARAMETRIZE { ability = ABILITY_SOUNDPROOF; config = GEN_8; } + + GIVEN { + ASSUME(!IsSoundMove(MOVE_AROMATHERAPY)); + WITH_CONFIG(CONFIG_HEAL_BELL_SOUNDPROOF, config); + PLAYER(SPECIES_WOBBUFFET) { Ability(ability); Status1(STATUS1_POISON); }; + PLAYER(SPECIES_EXPLOUD) { Ability(ability); Status1(STATUS1_POISON); } + OPPONENT(SPECIES_WYNAUT); + OPPONENT(SPECIES_WYNAUT); + } WHEN { + TURN { MOVE(playerLeft, MOVE_AROMATHERAPY, target: playerLeft); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_AROMATHERAPY, playerLeft); + NONE_OF { + MESSAGE("Exploud was hurt by its poisoning!"); + MESSAGE("Wobbuffet was hurt by its poisoning!"); + } + } +} + +SINGLE_BATTLE_TEST("Aromatherapy cures inactive Soundproof Pokemon regardless of config") +{ + u32 config, ability; + + PARAMETRIZE { config = GEN_4, ability = ABILITY_SOUNDPROOF; } + PARAMETRIZE { config = GEN_5, ability = ABILITY_SOUNDPROOF; } + + GIVEN { + ASSUME(!IsSoundMove(MOVE_AROMATHERAPY)); + WITH_CONFIG(CONFIG_HEAL_BELL_SOUNDPROOF, config); + PLAYER(SPECIES_WOBBUFFET) { } + PLAYER(SPECIES_EXPLOUD) { Ability(ability); Status1(STATUS1_POISON); } + OPPONENT(SPECIES_WYNAUT); + } WHEN { + TURN { MOVE(player, MOVE_AROMATHERAPY, target: player); } + TURN { SWITCH(player, 1); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_AROMATHERAPY, player); + SEND_IN_MESSAGE("Exploud"); + NOT MESSAGE("Exploud was hurt by its poisoning!"); + } +} diff --git a/test/battle/move_effect/heal_pulse.c b/test/battle/move_effect/heal_pulse.c index 7c46cbf344..c383b72682 100644 --- a/test/battle/move_effect/heal_pulse.c +++ b/test/battle/move_effect/heal_pulse.c @@ -86,6 +86,7 @@ SINGLE_BATTLE_TEST("Heal Pulse is blocked by Substitute") SINGLE_BATTLE_TEST("Floral Healing heals the target by 2/3rd of it's maxHP if Grassy Terrain is on the field") { GIVEN { + ASSUME(GetMoveEffect(MOVE_FLORAL_HEALING) == EFFECT_HEAL_PULSE); ASSUME(GetMoveEffectArg_MoveProperty(MOVE_FLORAL_HEALING) == MOVE_EFFECT_FLORAL_HEALING); ASSUME(GetMoveEffect(MOVE_GRASSY_TERRAIN) == EFFECT_GRASSY_TERRAIN); PLAYER(SPECIES_WOBBUFFET) { MaxHP(100); HP(1); } diff --git a/test/battle/move_effect/healing_wish.c b/test/battle/move_effect/healing_wish.c index 31dfebb342..ca78fd049e 100644 --- a/test/battle/move_effect/healing_wish.c +++ b/test/battle/move_effect/healing_wish.c @@ -4,15 +4,19 @@ ASSUMPTIONS { ASSUME(GetMoveEffect(MOVE_HEALING_WISH) == EFFECT_HEALING_WISH); - ASSUME(GetMoveEffect(MOVE_LUNAR_DANCE) == EFFECT_HEALING_WISH); } -SINGLE_BATTLE_TEST("Healing Wish causes the user to faint and fully heals the replacement") +SINGLE_BATTLE_TEST("Healing Wish causes the user to faint and heals the replacement's HP and status (singles)") { GIVEN { - ASSUME(B_HEALING_WISH_SWITCH >= GEN_5); + WITH_CONFIG(CONFIG_HEALING_WISH_SWITCH, GEN_7); + ASSUME(GetMovePP(MOVE_SCRATCH) == 35); + ASSUME(GetMovePP(MOVE_WATER_GUN) == 25); + ASSUME(GetMovePP(MOVE_LEAFAGE) == 40); + ASSUME(GetMovePP(MOVE_EMBER) == 25); PLAYER(SPECIES_GARDEVOIR); - PLAYER(SPECIES_WYNAUT) { HP(1); MaxHP(100); Status1(STATUS1_POISON); } + PLAYER(SPECIES_WYNAUT) { HP(1); MaxHP(100); Status1(STATUS1_POISON); + MovesWithPP({MOVE_SCRATCH, 5}, {MOVE_WATER_GUN, 5}, {MOVE_LEAFAGE, 5}, {MOVE_EMBER, 0}); } OPPONENT(SPECIES_WOBBUFFET); } WHEN { TURN { MOVE(player, MOVE_HEALING_WISH); SEND_OUT(player, 1); } @@ -24,35 +28,56 @@ SINGLE_BATTLE_TEST("Healing Wish causes the user to faint and fully heals the re HP_BAR(player, hp: 100); STATUS_ICON(player, none: TRUE); MESSAGE("Wynaut regained health!"); + } THEN { + EXPECT_EQ(player->hp, 100); + EXPECT_EQ(player->status1, 0); + // PP not healed + EXPECT_EQ(player->pp[0], 5); + EXPECT_EQ(player->pp[1], 5); + EXPECT_EQ(player->pp[2], 5); + EXPECT_EQ(player->pp[3], 0); } } -DOUBLE_BATTLE_TEST("Lunar Dance causes the user to faint and fully heals the replacement in a double battle") +DOUBLE_BATTLE_TEST("Healing Wish causes the user to faint and heals the replacement's HP and status (doubles)") { GIVEN { - ASSUME(B_HEALING_WISH_SWITCH >= GEN_5); + WITH_CONFIG(CONFIG_HEALING_WISH_SWITCH, GEN_7); + ASSUME(GetMovePP(MOVE_SCRATCH) == 35); + ASSUME(GetMovePP(MOVE_WATER_GUN) == 25); + ASSUME(GetMovePP(MOVE_LEAFAGE) == 40); + ASSUME(GetMovePP(MOVE_EMBER) == 25); PLAYER(SPECIES_GARDEVOIR) { Speed(300); } PLAYER(SPECIES_WOBBUFFET) { Speed(50); } - PLAYER(SPECIES_WYNAUT) { HP(99); MaxHP(100); Status1(STATUS1_BURN); Speed(50); } + PLAYER(SPECIES_WYNAUT) { HP(1); MaxHP(100); Status1(STATUS1_BURN); Speed(50); + MovesWithPP({MOVE_SCRATCH, 5}, {MOVE_WATER_GUN, 5}, {MOVE_LEAFAGE, 5}, {MOVE_EMBER, 0}); } OPPONENT(SPECIES_WOBBUFFET) { Speed(50); } OPPONENT(SPECIES_WOBBUFFET) { Speed(50); } } WHEN { - TURN { MOVE(playerLeft, MOVE_LUNAR_DANCE); SEND_OUT(playerLeft, 2); } + TURN { MOVE(playerLeft, MOVE_HEALING_WISH); SEND_OUT(playerLeft, 2); } } SCENE { - ANIMATION(ANIM_TYPE_MOVE, MOVE_LUNAR_DANCE, playerLeft); + ANIMATION(ANIM_TYPE_MOVE, MOVE_HEALING_WISH, playerLeft); HP_BAR(playerLeft, hp: 0); MESSAGE("Gardevoir fainted!"); - MESSAGE("Wynaut became cloaked in mystical moonlight!"); + MESSAGE("The healing wish came true for Wynaut!"); HP_BAR(playerLeft, hp: 100); STATUS_ICON(playerLeft, none: TRUE); MESSAGE("Wynaut regained health!"); + } THEN { + EXPECT_EQ(playerLeft->hp, 100); + EXPECT_EQ(playerLeft->status1, 0); + // PP not healed + EXPECT_EQ(playerLeft->pp[0], 5); + EXPECT_EQ(playerLeft->pp[1], 5); + EXPECT_EQ(playerLeft->pp[2], 5); + EXPECT_EQ(playerLeft->pp[3], 0); } } SINGLE_BATTLE_TEST("Healing Wish effect activates even if the the switched Pokémon can't be healed (Gen4-7)") { GIVEN { - WITH_CONFIG(GEN_CONFIG_HEALING_WISH_SWITCH, GEN_7); + WITH_CONFIG(CONFIG_HEALING_WISH_SWITCH, GEN_7); PLAYER(SPECIES_GARDEVOIR) { Speed(300); } PLAYER(SPECIES_NINJASK) { Speed(400); } OPPONENT(SPECIES_WOBBUFFET) { Speed(50); } @@ -69,15 +94,21 @@ SINGLE_BATTLE_TEST("Healing Wish effect activates even if the the switched Poké SINGLE_BATTLE_TEST("Healing Wish effect activates only if the switched Pokémon can be healed (Gen8+)") { + u32 switchTo; + PARAMETRIZE { switchTo = 2; } + PARAMETRIZE { switchTo = 3; } + PARAMETRIZE { switchTo = 4; } GIVEN { - WITH_CONFIG(GEN_CONFIG_HEALING_WISH_SWITCH, GEN_8); + WITH_CONFIG(CONFIG_HEALING_WISH_SWITCH, GEN_8); PLAYER(SPECIES_GARDEVOIR) { Speed(300); } PLAYER(SPECIES_NINJASK) { Speed(400); } - PLAYER(SPECIES_WYNAUT) { HP(50); MaxHP(100); Status1(STATUS1_PARALYSIS); Speed(50); } + PLAYER(SPECIES_WYNAUT) { HP(50); MaxHP(100); Speed(50); } + PLAYER(SPECIES_WYNAUT) { Status1(STATUS1_PARALYSIS); Speed(50); } + PLAYER(SPECIES_WYNAUT) { MovesWithPP({MOVE_SCRATCH, 5}); Speed(50); } OPPONENT(SPECIES_WOBBUFFET) { Speed(50); } } WHEN { TURN { MOVE(player, MOVE_HEALING_WISH); SEND_OUT(player, 1); } - TURN { MOVE(player, MOVE_U_TURN); SEND_OUT(player, 2); } + TURN { MOVE(player, MOVE_U_TURN); SEND_OUT(player, switchTo); } } SCENE { ANIMATION(ANIM_TYPE_MOVE, MOVE_HEALING_WISH, player); HP_BAR(player, hp: 0); @@ -87,9 +118,27 @@ SINGLE_BATTLE_TEST("Healing Wish effect activates only if the switched Pokémon MESSAGE("Ninjask regained health!"); } ANIMATION(ANIM_TYPE_MOVE, MOVE_U_TURN, player); - MESSAGE("The healing wish came true for Wynaut!"); - HP_BAR(player, hp: 100); - STATUS_ICON(player, none: TRUE); - MESSAGE("Wynaut regained health!"); + if (switchTo == 2) { + MESSAGE("The healing wish came true for Wynaut!"); + HP_BAR(player, hp: 100); + MESSAGE("Wynaut regained health!"); + } else if (switchTo == 3) { + MESSAGE("The healing wish came true for Wynaut!"); + STATUS_ICON(player, none: TRUE); + MESSAGE("Wynaut regained health!"); + } else { + NONE_OF { + MESSAGE("The healing wish came true for Wynaut!"); + MESSAGE("Wynaut regained health!"); + } + } + } THEN { + if (switchTo == 2) { + EXPECT_EQ(player->hp, 100); + } else if (switchTo == 3) { + EXPECT_EQ(player->status1, 0); + } else if (switchTo == 4) { + EXPECT_EQ(player->pp[0], 5); // Did NOT heal PP + } } } diff --git a/test/battle/move_effect/hidden_power.c b/test/battle/move_effect/hidden_power.c index a04482eb29..9ac88e687f 100644 --- a/test/battle/move_effect/hidden_power.c +++ b/test/battle/move_effect/hidden_power.c @@ -31,7 +31,8 @@ ASSUMPTIONS // IV combinations sourced from https://www.smogon.com/forums/threads/hidden-power-iv-combinations.78083/ SINGLE_BATTLE_TEST("Hidden Power's type is determined by IVs") { - u32 type, j, foeType, foeSpecies, foeItem; + enum Type type, foeType, j; + u32 foeSpecies, foeItem; u32 hp, atk, def, spAtk, spDef, speed; bool32 hidden; diff --git a/test/battle/move_effect/hit_set_remove_terrain.c b/test/battle/move_effect/hit_set_remove_terrain.c deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/test/battle/move_effect/instruct.c b/test/battle/move_effect/instruct.c index 070b6ba31d..834546009f 100644 --- a/test/battle/move_effect/instruct.c +++ b/test/battle/move_effect/instruct.c @@ -6,6 +6,21 @@ ASSUMPTIONS ASSUME(GetMoveEffect(MOVE_INSTRUCT) == EFFECT_INSTRUCT); } +SINGLE_BATTLE_TEST("Instruct causes the target to use its last used move again") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Moves(MOVE_SCRATCH, MOVE_POUND, MOVE_SCRATCH, MOVE_CELEBRATE); } + OPPONENT(SPECIES_WYNAUT); + } WHEN { + TURN { MOVE(player, MOVE_SCRATCH); MOVE(opponent, MOVE_INSTRUCT); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SCRATCH, player); + ANIMATION(ANIM_TYPE_MOVE, MOVE_INSTRUCT, opponent); + MESSAGE("Wobbuffet followed the opposing Wynaut's instructions!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SCRATCH, player); + } +} + DOUBLE_BATTLE_TEST("Instruct fails if target hasn't made a move") { GIVEN { @@ -280,7 +295,7 @@ DOUBLE_BATTLE_TEST("Instructed move will be redirected by Rage Powder after inst PARAMETRIZE { moveTarget = opponentLeft; } PARAMETRIZE { moveTarget = opponentRight; } GIVEN { - WITH_CONFIG(GEN_CONFIG_POWDER_GRASS, GEN_6); + WITH_CONFIG(CONFIG_POWDER_GRASS, GEN_6); ASSUME(GetMoveEffect(MOVE_RAGE_POWDER) == EFFECT_FOLLOW_ME); ASSUME(IsPowderMove(MOVE_RAGE_POWDER) == TRUE); ASSUME(GetMoveEffect(MOVE_SOAK) == EFFECT_SOAK); diff --git a/test/battle/move_effect/ion_deluge.c b/test/battle/move_effect/ion_deluge.c index b806f9d8e1..4f74c6db72 100644 --- a/test/battle/move_effect/ion_deluge.c +++ b/test/battle/move_effect/ion_deluge.c @@ -27,7 +27,7 @@ WILD_BATTLE_TEST("Ion Deluge works the same way as always when used by a mon wit WILD_BATTLE_TEST("Ion Deluge works the same way as always when used by a mon with Lightning Rod / Motor Drive") { - u16 ability; + enum Ability ability; PARAMETRIZE { ability = ABILITY_LIGHTNING_ROD; } PARAMETRIZE { ability = ABILITY_MOTOR_DRIVE; } diff --git a/test/battle/move_effect/lash_out.c b/test/battle/move_effect/lash_out.c index 4ceb0c02a8..ed9465e915 100644 --- a/test/battle/move_effect/lash_out.c +++ b/test/battle/move_effect/lash_out.c @@ -118,7 +118,7 @@ SINGLE_BATTLE_TEST("Lash Out damage is boosted on turn 1 by switch in abilities" DOUBLE_BATTLE_TEST("Lash Out damage is boosted by Cotton Down activation in doubles") { s16 damage[2] = {0}; - u32 ability = ABILITY_NONE; + enum Ability ability = ABILITY_NONE; PARAMETRIZE { ability = ABILITY_REGENERATOR; } PARAMETRIZE { ability = ABILITY_COTTON_DOWN; } diff --git a/test/battle/move_effect/last_resort.c b/test/battle/move_effect/last_resort.c index c0b2380f27..089a723304 100644 --- a/test/battle/move_effect/last_resort.c +++ b/test/battle/move_effect/last_resort.c @@ -114,3 +114,43 @@ SINGLE_BATTLE_TEST("Last Resort works with Sleep Talk") HP_BAR(opponent); } } + +AI_SINGLE_BATTLE_TEST("AI uses Last Resort - 2 moves") +{ + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT); + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_LAST_RESORT, MOVE_SCRATCH); } + } WHEN { + TURN { NOT_EXPECT_MOVE(opponent, MOVE_LAST_RESORT); } + TURN { EXPECT_MOVE(opponent, MOVE_LAST_RESORT); } + } +} + +AI_SINGLE_BATTLE_TEST("AI uses Last Resort - 3 moves") +{ + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT); + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET) { MovesWithPP({MOVE_LAST_RESORT, 5}, {MOVE_QUICK_ATTACK, 1}, {MOVE_SCRATCH, 35}); } + } WHEN { + TURN { NOT_EXPECT_MOVE(opponent, MOVE_LAST_RESORT); } + TURN { NOT_EXPECT_MOVE(opponent, MOVE_LAST_RESORT); } + TURN { EXPECT_MOVE(opponent, MOVE_LAST_RESORT); } + } +} + +AI_SINGLE_BATTLE_TEST("AI uses Last Resort - 4 moves") +{ + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT); + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET) { MovesWithPP({MOVE_LAST_RESORT, 5}, {MOVE_QUICK_ATTACK, 1}, {MOVE_SCRATCH, 1}, {MOVE_GUST, 35}); } + } WHEN { + TURN { NOT_EXPECT_MOVE(opponent, MOVE_LAST_RESORT); } + TURN { NOT_EXPECT_MOVE(opponent, MOVE_LAST_RESORT); } + TURN { NOT_EXPECT_MOVE(opponent, MOVE_LAST_RESORT); } + TURN { EXPECT_MOVE(opponent, MOVE_LAST_RESORT); } + } +} + diff --git a/test/battle/move_effect/last_respects.c b/test/battle/move_effect/last_respects.c index 6ef4c73c2d..1e0ddaed28 100644 --- a/test/battle/move_effect/last_respects.c +++ b/test/battle/move_effect/last_respects.c @@ -13,7 +13,7 @@ SINGLE_BATTLE_TEST("Last Respects power is multiplied by the amount of fainted m PARAMETRIZE { faintCount = 1; } PARAMETRIZE { faintCount = 2; } GIVEN { - PLAYER(SPECIES_GOLEM); // Not Wobbuffet to omit type effectiveness + PLAYER(SPECIES_HITMONLEE); // Not Wobbuffet to omit type effectiveness PLAYER(SPECIES_GEODUDE); OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_LEPPA_BERRY); Moves(MOVE_RECYCLE, MOVE_NONE, MOVE_NONE, MOVE_NONE); } } WHEN { @@ -44,7 +44,7 @@ SINGLE_BATTLE_TEST("Last Respects power is multiplied by the amount of fainted m PARAMETRIZE { faintCount = 2; } GIVEN { PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_LEPPA_BERRY); Moves(MOVE_RECYCLE, MOVE_NONE, MOVE_NONE, MOVE_NONE); } - OPPONENT(SPECIES_GOLEM); // Not Wobbuffet to omit type effectiveness + OPPONENT(SPECIES_HITMONLEE); // Not Wobbuffet to omit type effectiveness OPPONENT(SPECIES_GEODUDE); } WHEN { for (j = 0; j < faintCount; j++) diff --git a/test/battle/move_effect/life_dew.c b/test/battle/move_effect/life_dew.c index 493c4c73e7..1969f3454c 100644 --- a/test/battle/move_effect/life_dew.c +++ b/test/battle/move_effect/life_dew.c @@ -84,3 +84,30 @@ DOUBLE_BATTLE_TEST("Life Dew only works on partner if user is at full hp") HP_BAR(playerRight); } } + +AI_SINGLE_BATTLE_TEST("AI uses Life Dew if it outheals your damage and outspeeds (singles)") +{ + PASSES_RANDOMLY(100, 100, RNG_AI_SHOULD_RECOVER); + GIVEN { + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_OMNISCIENT); + PLAYER(SPECIES_WOBBUFFET) { Speed(2); Moves(MOVE_TACKLE); } + OPPONENT(SPECIES_WOBBUFFET) { Speed(5); Moves(MOVE_SCALD, MOVE_LIFE_DEW); HP(1); } + } WHEN { + TURN { MOVE(player, MOVE_TACKLE); EXPECT_MOVE(opponent, MOVE_LIFE_DEW); } + } +} + +AI_DOUBLE_BATTLE_TEST("AI uses Life Dew if it outheals your damage and outspeeds (doubles)") +{ + PASSES_RANDOMLY(100, 100, RNG_AI_SHOULD_RECOVER); + GIVEN { + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_OMNISCIENT); + PLAYER(SPECIES_WOBBUFFET) { Speed(2); Moves(MOVE_TACKLE); } + PLAYER(SPECIES_WOBBUFFET) { Speed(2); Moves(MOVE_TACKLE); } + OPPONENT(SPECIES_WOBBUFFET) { Speed(5); Moves(MOVE_SCALD, MOVE_LIFE_DEW); HP(1); } + OPPONENT(SPECIES_WOBBUFFET) { Speed(5); Moves(MOVE_SCALD); HP(1); } + } WHEN { + TURN { MOVE(playerLeft, MOVE_TACKLE); MOVE(playerRight, MOVE_TACKLE); EXPECT_MOVE(opponentLeft, MOVE_LIFE_DEW); } + } +} + diff --git a/test/battle/move_effect/lunar_dance.c b/test/battle/move_effect/lunar_dance.c new file mode 100644 index 0000000000..4714516b1f --- /dev/null +++ b/test/battle/move_effect/lunar_dance.c @@ -0,0 +1,137 @@ +#include "global.h" +#include "test/battle.h" + +ASSUMPTIONS +{ + ASSUME(GetMoveEffect(MOVE_LUNAR_DANCE) == EFFECT_LUNAR_DANCE); +} + +SINGLE_BATTLE_TEST("Lunar Dance causes the user to faint and heals the replacement's HP, PP and status (singles)") +{ + GIVEN { + WITH_CONFIG(CONFIG_HEALING_WISH_SWITCH, GEN_7); + ASSUME(GetMovePP(MOVE_SCRATCH) == 35); + ASSUME(GetMovePP(MOVE_WATER_GUN) == 25); + ASSUME(GetMovePP(MOVE_LEAFAGE) == 40); + ASSUME(GetMovePP(MOVE_EMBER) == 25); + PLAYER(SPECIES_GARDEVOIR); + PLAYER(SPECIES_WYNAUT) { HP(1); MaxHP(100); Status1(STATUS1_POISON); + MovesWithPP({MOVE_SCRATCH, 5}, {MOVE_WATER_GUN, 5}, {MOVE_LEAFAGE, 5}, {MOVE_EMBER, 0}); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_LUNAR_DANCE); SEND_OUT(player, 1); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_LUNAR_DANCE, player); + HP_BAR(player, hp: 0); + MESSAGE("Gardevoir fainted!"); + MESSAGE("Wynaut became cloaked in mystical moonlight!"); + HP_BAR(player, hp: 100); + STATUS_ICON(player, none: TRUE); + MESSAGE("Wynaut regained health!"); + } THEN { + EXPECT_EQ(player->hp, 100); + EXPECT_EQ(player->status1, 0); + // PP not healed + EXPECT_EQ(player->pp[0], 35); + EXPECT_EQ(player->pp[1], 25); + EXPECT_EQ(player->pp[2], 40); + EXPECT_EQ(player->pp[3], 25); + } +} + +DOUBLE_BATTLE_TEST("Lunar Dance causes the user to faint and heals the replacement's HP, PP and status (doubles)") +{ + GIVEN { + WITH_CONFIG(CONFIG_HEALING_WISH_SWITCH, GEN_7); + ASSUME(GetMovePP(MOVE_SCRATCH) == 35); + ASSUME(GetMovePP(MOVE_WATER_GUN) == 25); + ASSUME(GetMovePP(MOVE_LEAFAGE) == 40); + ASSUME(GetMovePP(MOVE_EMBER) == 25); + PLAYER(SPECIES_GARDEVOIR) { Speed(300); } + PLAYER(SPECIES_WOBBUFFET) { Speed(50); } + PLAYER(SPECIES_WYNAUT) { HP(1); MaxHP(100); Status1(STATUS1_BURN); Speed(50); + MovesWithPP({MOVE_SCRATCH, 5}, {MOVE_WATER_GUN, 5}, {MOVE_LEAFAGE, 5}, {MOVE_EMBER, 0}); } + OPPONENT(SPECIES_WOBBUFFET) { Speed(50); } + OPPONENT(SPECIES_WOBBUFFET) { Speed(50); } + } WHEN { + TURN { MOVE(playerLeft, MOVE_LUNAR_DANCE); SEND_OUT(playerLeft, 2); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_LUNAR_DANCE, playerLeft); + HP_BAR(playerLeft, hp: 0); + MESSAGE("Gardevoir fainted!"); + MESSAGE("Wynaut became cloaked in mystical moonlight!"); + HP_BAR(playerLeft, hp: 100); + STATUS_ICON(playerLeft, none: TRUE); + MESSAGE("Wynaut regained health!"); + } THEN { + EXPECT_EQ(playerLeft->hp, 100); + EXPECT_EQ(playerLeft->status1, 0); + EXPECT_EQ(playerLeft->pp[0], 35); + EXPECT_EQ(playerLeft->pp[1], 25); + EXPECT_EQ(playerLeft->pp[2], 40); + EXPECT_EQ(playerLeft->pp[3], 25); + } +} + +SINGLE_BATTLE_TEST("Lunar Dance effect activates even if the the switched Pokémon can't be healed (Gen4-7)") +{ + GIVEN { + WITH_CONFIG(CONFIG_HEALING_WISH_SWITCH, GEN_7); + PLAYER(SPECIES_GARDEVOIR) { Speed(300); } + PLAYER(SPECIES_NINJASK) { Speed(400); } + OPPONENT(SPECIES_WOBBUFFET) { Speed(50); } + } WHEN { + TURN { MOVE(player, MOVE_LUNAR_DANCE); SEND_OUT(player, 1); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_LUNAR_DANCE, player); + HP_BAR(player, hp: 0); + MESSAGE("Gardevoir fainted!"); + MESSAGE("Ninjask became cloaked in mystical moonlight!"); + MESSAGE("Ninjask regained health!"); + } +} + +SINGLE_BATTLE_TEST("Lunar Dance effect activates only if the switched Pokémon can be healed (Gen8+)") +{ + u32 switchTo; + PARAMETRIZE { switchTo = 2; } + PARAMETRIZE { switchTo = 3; } + PARAMETRIZE { switchTo = 4; } + GIVEN { + ASSUME(GetMovePP(MOVE_SCRATCH) == 35); + WITH_CONFIG(CONFIG_HEALING_WISH_SWITCH, GEN_8); + PLAYER(SPECIES_GARDEVOIR) { Speed(300); } + PLAYER(SPECIES_NINJASK) { Speed(400); } + PLAYER(SPECIES_WYNAUT) { HP(50); MaxHP(100); Speed(50); } + PLAYER(SPECIES_WYNAUT) { Status1(STATUS1_PARALYSIS); Speed(50); } + PLAYER(SPECIES_WYNAUT) { MovesWithPP({MOVE_SCRATCH, 5}); Speed(50); } + OPPONENT(SPECIES_WOBBUFFET) { Speed(50); } + } WHEN { + TURN { MOVE(player, MOVE_LUNAR_DANCE); SEND_OUT(player, 1); } + TURN { MOVE(player, MOVE_U_TURN); SEND_OUT(player, switchTo); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_LUNAR_DANCE, player); + HP_BAR(player, hp: 0); + MESSAGE("Gardevoir fainted!"); + NONE_OF { + MESSAGE("Ninjask became cloaked in mystical moonlight!"); + MESSAGE("Ninjask regained health!"); + } + ANIMATION(ANIM_TYPE_MOVE, MOVE_U_TURN, player); + MESSAGE("Wynaut became cloaked in mystical moonlight!"); + if (switchTo == 2) { + HP_BAR(player, hp: 100); + } else if (switchTo == 3) { + STATUS_ICON(player, none: TRUE); + } + MESSAGE("Wynaut regained health!"); + } THEN { + if (switchTo == 2) { + EXPECT_EQ(player->hp, 100); + } else if (switchTo == 3) { + EXPECT_EQ(player->status1, 0); + } else if (switchTo == 4) { + EXPECT_EQ(player->pp[0], 35); + } + } +} diff --git a/test/battle/move_effect/magic_coat.c b/test/battle/move_effect/magic_coat.c index ca7b78883e..05e53b5e12 100644 --- a/test/battle/move_effect/magic_coat.c +++ b/test/battle/move_effect/magic_coat.c @@ -33,6 +33,42 @@ SINGLE_BATTLE_TEST("Magic Coat prints the correct message when bouncing back a m } } +SINGLE_BATTLE_TEST("Magic Coat fails if user moves last") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Speed(5); } + OPPONENT(SPECIES_WYNAUT) { Speed(10); } + } WHEN { + TURN { MOVE(opponent, MOVE_CELEBRATE); MOVE(player, MOVE_MAGIC_COAT); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponent); + NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_MAGIC_COAT, player); + } +} + +DOUBLE_BATTLE_TEST("Magic Coat fails when the only slower battler is a fainted ally") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Speed(5); } + PLAYER(SPECIES_WYNAUT) { HP(1); Speed(1); } + OPPONENT(SPECIES_WOBBUFFET) { Speed(20); } + OPPONENT(SPECIES_WYNAUT) { Speed(10); } + } WHEN { + TURN { MOVE(opponentLeft, MOVE_SCRATCH, target: playerRight); } + TURN { + MOVE(opponentLeft, MOVE_CELEBRATE); + MOVE(opponentRight, MOVE_CELEBRATE); + MOVE(playerLeft, MOVE_MAGIC_COAT); + } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SCRATCH, opponentLeft); + MESSAGE("Wynaut fainted!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponentLeft); + ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponentRight); + NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_MAGIC_COAT, playerLeft); + } +} + DOUBLE_BATTLE_TEST("Magic Coat reflects hazards regardless of the user's position") { struct BattlePokemon *coatUser = NULL; diff --git a/test/battle/move_effect/magic_room.c b/test/battle/move_effect/magic_room.c index cffd6034d7..02953f533d 100644 --- a/test/battle/move_effect/magic_room.c +++ b/test/battle/move_effect/magic_room.c @@ -36,4 +36,43 @@ DOUBLE_BATTLE_TEST("Magic Room prevents item hold effects") } } +SINGLE_BATTLE_TEST("Magic Room: An item that can activate will activate once Magic Room is over") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_WHITE_HERB); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_MAGIC_ROOM); MOVE(opponent, MOVE_GROWL); } + TURN {} + TURN {} + TURN {} + TURN {} + TURN {} + } SCENE { + // Turn 1 + ANIMATION(ANIM_TYPE_MOVE, MOVE_MAGIC_ROOM, player); + ANIMATION(ANIM_TYPE_MOVE, MOVE_GROWL, opponent); + // Turn 2 + ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, player); + ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponent); + // Turn 3 + ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, player); + ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponent); + // Turn 4 + ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, player); + ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponent); + // Turn 5 + ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, player); + ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponent); + + NONE_OF { + ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, player); + ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponent); + } + + MESSAGE("Magic Room wore off, and held items' effects returned to normal!"); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player); + } +} + TO_DO_BATTLE_TEST("TODO: Write Magic Room (Move Effect) test titles") diff --git a/test/battle/move_effect/magnetic_flux.c b/test/battle/move_effect/magnetic_flux.c index f574db0089..6a23d2082f 100644 --- a/test/battle/move_effect/magnetic_flux.c +++ b/test/battle/move_effect/magnetic_flux.c @@ -2,3 +2,16 @@ #include "test/battle.h" TO_DO_BATTLE_TEST("TODO: Write Magnetic Flux (Move Effect) test titles") + +AI_DOUBLE_BATTLE_TEST("AI uses Magnetic Flux") +{ + GIVEN { + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_OMNISCIENT); + PLAYER(SPECIES_WOBBUFFET) { Moves(MOVE_POUND, MOVE_CELEBRATE); } + PLAYER(SPECIES_WOBBUFFET) { Moves(MOVE_POUND, MOVE_CELEBRATE); } + OPPONENT(SPECIES_KLINK) { Ability(ABILITY_PLUS); Moves(MOVE_MAGNETIC_FLUX, MOVE_POUND); } + OPPONENT(SPECIES_KLINK) { Ability(ABILITY_PLUS); Moves(MOVE_MAGNETIC_FLUX, MOVE_POUND); } + } WHEN { + TURN { EXPECT_MOVE(opponentLeft, MOVE_MAGNETIC_FLUX); } + } +} diff --git a/test/battle/move_effect/max_move.c b/test/battle/move_effect/max_move.c index 41c2a4e32c..38924f1d33 100644 --- a/test/battle/move_effect/max_move.c +++ b/test/battle/move_effect/max_move.c @@ -1,4 +1,4 @@ #include "global.h" #include "test/battle.h" -TO_DO_BATTLE_TEST("TODO: Write Max Moves (Move Effect) test titles") +// Tested in the dynamax.c test file diff --git a/test/battle/move_effect/me_first.c b/test/battle/move_effect/me_first.c index f351c1a498..51f673ae5f 100644 --- a/test/battle/move_effect/me_first.c +++ b/test/battle/move_effect/me_first.c @@ -1,6 +1,11 @@ #include "global.h" #include "test/battle.h" +ASSUMPTIONS +{ + ASSUME(GetMoveEffect(MOVE_ME_FIRST) == EFFECT_ME_FIRST); +} + SINGLE_BATTLE_TEST("Me First copies the move from the target and increases it's power by 1.5", s16 damage) { u32 move; @@ -77,4 +82,21 @@ SINGLE_BATTLE_TEST("Me First can be selected if users holds Assault Vest") } } +SINGLE_BATTLE_TEST("Me Frist deducts power points from itself, not the copied move") +{ + ASSUME(GetMovePP(MOVE_ME_FIRST) == 20); + ASSUME(GetMovePP(MOVE_POUND) == 35); + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Speed(100); Moves(MOVE_ME_FIRST); } + OPPONENT(SPECIES_WOBBUFFET) { Speed(50); Moves(MOVE_POUND); } + } WHEN { + TURN { MOVE(player, MOVE_ME_FIRST); MOVE(opponent, MOVE_POUND); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_ME_FIRST, player); + } THEN { + EXPECT_EQ(opponent->pp[0], 34); + EXPECT_EQ(player->pp[0], 19); + } +} + // TO_DO_BATTLE_TEST: Not everything has been tested diff --git a/test/battle/move_effect/metronome.c b/test/battle/move_effect/metronome.c index 91865b05cf..7415594a64 100644 --- a/test/battle/move_effect/metronome.c +++ b/test/battle/move_effect/metronome.c @@ -25,7 +25,7 @@ SINGLE_BATTLE_TEST("Metronome picks a random move") SINGLE_BATTLE_TEST("Metronome's called powder move fails against Grass Types") { GIVEN { - WITH_CONFIG(GEN_CONFIG_POWDER_GRASS, GEN_6); + WITH_CONFIG(CONFIG_POWDER_GRASS, GEN_6); ASSUME(IsPowderMove(MOVE_POISON_POWDER)); ASSUME(GetSpeciesType(SPECIES_TANGELA, 0) == TYPE_GRASS); ASSUME(GetMoveEffect(MOVE_POISON_POWDER) == EFFECT_NON_VOLATILE_STATUS); diff --git a/test/battle/move_effect/minimize.c b/test/battle/move_effect/minimize.c index f0196936a5..b6730fca9b 100644 --- a/test/battle/move_effect/minimize.c +++ b/test/battle/move_effect/minimize.c @@ -1,4 +1,29 @@ #include "global.h" #include "test/battle.h" -TO_DO_BATTLE_TEST("TODO: Write Minimize (Move Effect) test titles") +ASSUMPTIONS +{ + ASSUME(GetMoveEffect(MOVE_MINIMIZE) == EFFECT_MINIMIZE); +} + +SINGLE_BATTLE_TEST("Minimize increases the user's Evasion by 2 stages (Gen5+) or 1 stage (Gen1-4)") +{ + u32 config; + PARAMETRIZE { config = GEN_4; } + PARAMETRIZE { config = GEN_5; } + + GIVEN { + WITH_CONFIG(CONFIG_MINIMIZE_EVASION, config); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_MINIMIZE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_MINIMIZE, player); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); + } THEN { + EXPECT_EQ(player->statStages[STAT_EVASION], DEFAULT_STAT_STAGE + (config >= GEN_5 ? 2 : 1)); + } +} + +// Minimize's flag tests are handled in tests/battle/move_flags/minimize_double_damage.c diff --git a/test/battle/move_effect/mirror_coat.c b/test/battle/move_effect/mirror_coat.c index 2a3d6ef250..6de1c03c29 100644 --- a/test/battle/move_effect/mirror_coat.c +++ b/test/battle/move_effect/mirror_coat.c @@ -1,4 +1,131 @@ #include "global.h" #include "test/battle.h" -TO_DO_BATTLE_TEST("TODO: Write Mirror Coat (Move Effect) test titles") +ASSUMPTIONS +{ + ASSUME(GetMoveEffect(MOVE_MIRROR_COAT) == EFFECT_MIRROR_COAT); + ASSUME(GetMoveCategory(MOVE_ROUND) == DAMAGE_CATEGORY_SPECIAL); +} + +SINGLE_BATTLE_TEST("Mirror Coat will do twice as much damage received from the opponent") +{ + s16 normalDmg; + s16 mirrorCoatDmg; + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_ROUND); MOVE(player, MOVE_MIRROR_COAT); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_ROUND, opponent); + HP_BAR(player, captureDamage: &normalDmg); + ANIMATION(ANIM_TYPE_MOVE, MOVE_MIRROR_COAT, player); + HP_BAR(opponent, captureDamage: &mirrorCoatDmg); + } THEN { + EXPECT_MUL_EQ(normalDmg, Q_4_12(2.0), mirrorCoatDmg); + } +} + +DOUBLE_BATTLE_TEST("Mirror Coat cannot affect ally Pokémon") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_WYNAUT); + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WYNAUT); + } WHEN { + TURN { + MOVE(playerLeft, MOVE_ROUND, target: playerRight); + MOVE(playerRight, MOVE_MIRROR_COAT, target: playerLeft); + } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_ROUND, playerLeft); + NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_MIRROR_COAT, playerRight); + } +} + +DOUBLE_BATTLE_TEST("Mirror Coat hits the last opponent that hit the user") +{ + s16 normalDmg; + s16 mirrorCoatDmg; + + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_WYNAUT); + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WYNAUT); + } WHEN { + TURN { + MOVE(opponentLeft, MOVE_ROUND, target: playerLeft); + MOVE(opponentRight, MOVE_ROUND, target: playerLeft); + MOVE(playerLeft, MOVE_MIRROR_COAT); + } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_ROUND, opponentLeft); + ANIMATION(ANIM_TYPE_MOVE, MOVE_ROUND, opponentRight); + HP_BAR(playerLeft, captureDamage: &normalDmg); + ANIMATION(ANIM_TYPE_MOVE, MOVE_MIRROR_COAT, playerLeft); + HP_BAR(opponentRight, captureDamage: &mirrorCoatDmg); + } THEN { + EXPECT_MUL_EQ(normalDmg, Q_4_12(2.0), mirrorCoatDmg); + } +} + +DOUBLE_BATTLE_TEST("Mirror Coat respects Follow Me") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_WYNAUT); + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WYNAUT); + } WHEN { + TURN { + MOVE(opponentRight, MOVE_FOLLOW_ME); + MOVE(opponentLeft, MOVE_ROUND, target: playerLeft); + MOVE(playerLeft, MOVE_MIRROR_COAT, target: opponentLeft); + } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_FOLLOW_ME, opponentRight); + ANIMATION(ANIM_TYPE_MOVE, MOVE_ROUND, opponentLeft); + ANIMATION(ANIM_TYPE_MOVE, MOVE_MIRROR_COAT, playerLeft); + HP_BAR(opponentRight); + } +} + +DOUBLE_BATTLE_TEST("Mirror Coat fails if mon that damaged Mirror Coat user is no longer on the field (Gen 1-4)") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_WYNAUT); + OPPONENT(SPECIES_WOBBUFFET) { HP(1); }; + OPPONENT(SPECIES_WYNAUT); + } WHEN { + TURN { + MOVE(opponentLeft, MOVE_ROUND, target: playerLeft); + MOVE(playerRight, MOVE_ROUND, target: opponentLeft); + MOVE(playerLeft, MOVE_MIRROR_COAT, target: opponentLeft); + } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_ROUND, opponentLeft); + ANIMATION(ANIM_TYPE_MOVE, MOVE_ROUND, playerRight); + NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_MIRROR_COAT, playerLeft); + } +} + +SINGLE_BATTLE_TEST("Mirror Coat deals 1 damage when the attack received is blocked by Disguise") +{ + s16 mirrorCoatDmg; + GIVEN { + ASSUME(GetMoveCategory(MOVE_HEX) == DAMAGE_CATEGORY_SPECIAL); + PLAYER(SPECIES_MIMIKYU) { Ability(ABILITY_DISGUISE); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_HEX); MOVE(player, MOVE_MIRROR_COAT); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_HEX, opponent); + ANIMATION(ANIM_TYPE_MOVE, MOVE_MIRROR_COAT, player); + HP_BAR(opponent, captureDamage: &mirrorCoatDmg); + } THEN { + EXPECT_EQ(mirrorCoatDmg, 1); + } +} diff --git a/test/battle/move_effect/mirror_move.c b/test/battle/move_effect/mirror_move.c index 2f3c65b827..c07dc6b84e 100644 --- a/test/battle/move_effect/mirror_move.c +++ b/test/battle/move_effect/mirror_move.c @@ -32,7 +32,7 @@ SINGLE_BATTLE_TEST("Mirror Move fails if no move was used before") TURN { MOVE(player, MOVE_MIRROR_MOVE); MOVE(opponent, MOVE_SCRATCH); } } SCENE { MESSAGE("Wobbuffet used Mirror Move!"); - MESSAGE("The Mirror Move failed!"); + MESSAGE("But it failed!"); ANIMATION(ANIM_TYPE_MOVE, MOVE_SCRATCH, opponent); HP_BAR(player); } @@ -41,7 +41,7 @@ SINGLE_BATTLE_TEST("Mirror Move fails if no move was used before") SINGLE_BATTLE_TEST("Mirror Move's called powder move fails against Grass Types") { GIVEN { - WITH_CONFIG(GEN_CONFIG_POWDER_GRASS, GEN_6); + WITH_CONFIG(CONFIG_POWDER_GRASS, GEN_6); ASSUME(IsPowderMove(MOVE_STUN_SPORE)); ASSUME(GetSpeciesType(SPECIES_ODDISH, 0) == TYPE_GRASS); ASSUME(GetMoveEffect(MOVE_STUN_SPORE) == EFFECT_NON_VOLATILE_STATUS); diff --git a/test/battle/move_effect/misty_explosion.c b/test/battle/move_effect/misty_explosion.c new file mode 100644 index 0000000000..b7e0ede902 --- /dev/null +++ b/test/battle/move_effect/misty_explosion.c @@ -0,0 +1,93 @@ +#include "global.h" +#include "test/battle.h" + +ASSUMPTIONS +{ + ASSUME(GetMoveEffect(MOVE_MISTY_EXPLOSION) == EFFECT_MISTY_EXPLOSION); +} + +TO_DO_BATTLE_TEST("Misty Explosion increases in power by 50% when affected by Misty Terrain") + +SINGLE_BATTLE_TEST("Misty Explosion causes the user to faint") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_MISTY_EXPLOSION); } + } SCENE { + HP_BAR(player, hp: 0); + ANIMATION(ANIM_TYPE_MOVE, MOVE_MISTY_EXPLOSION, player); + MESSAGE("Wobbuffet fainted!"); + } +} + +SINGLE_BATTLE_TEST("Misty Explosion causes the user & the target to faint") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET) { HP(1); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_MISTY_EXPLOSION); } + } SCENE { + HP_BAR(player, hp: 0); + ANIMATION(ANIM_TYPE_MOVE, MOVE_MISTY_EXPLOSION, player); + HP_BAR(opponent, hp: 0); + MESSAGE("The opposing Wobbuffet fainted!"); + MESSAGE("Wobbuffet fainted!"); + } +} + +SINGLE_BATTLE_TEST("Misty Explosion causes the user to faint even if it misses") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_MISTY_EXPLOSION, hit: FALSE); } + } SCENE { + HP_BAR(player, hp: 0); + ANIMATION(ANIM_TYPE_MOVE, MOVE_MISTY_EXPLOSION, player); + MESSAGE("Wobbuffet fainted!"); + } +} + +DOUBLE_BATTLE_TEST("Misty Explosion causes everyone to faint in a double battle") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_WYNAUT) { HP(1); } + OPPONENT(SPECIES_ABRA) { HP(1); } + OPPONENT(SPECIES_KADABRA) { HP(1); } + OPPONENT(SPECIES_KADABRA); + } WHEN { + TURN { MOVE(playerLeft, MOVE_MISTY_EXPLOSION); } + } SCENE { + HP_BAR(playerLeft, hp: 0); + ANIMATION(ANIM_TYPE_MOVE, MOVE_MISTY_EXPLOSION, playerLeft); + HP_BAR(opponentLeft, hp: 0); + HP_BAR(playerRight, hp: 0); + HP_BAR(opponentRight, hp: 0); + MESSAGE("The opposing Abra fainted!"); + MESSAGE("Wynaut fainted!"); + MESSAGE("The opposing Kadabra fainted!"); + MESSAGE("Wobbuffet fainted!"); + } +} + +SINGLE_BATTLE_TEST("Misty Explosion does not trigger Destiny Bond") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { HP(1); }; + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_DESTINY_BOND); MOVE(opponent, MOVE_MISTY_EXPLOSION);} + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_DESTINY_BOND, player); + HP_BAR(opponent); + ANIMATION(ANIM_TYPE_MOVE, MOVE_MISTY_EXPLOSION, opponent); + HP_BAR(player); + NOT HP_BAR(opponent); + } +} diff --git a/test/battle/move_effect/moonlight.c b/test/battle/move_effect/moonlight.c index 9804e4ba1e..428227b66c 100644 --- a/test/battle/move_effect/moonlight.c +++ b/test/battle/move_effect/moonlight.c @@ -9,7 +9,7 @@ ASSUMPTIONS SINGLE_BATTLE_TEST("Moonlight recovers 1/2 of the user's max HP (Gen3+)") { GIVEN { - WITH_CONFIG(GEN_CONFIG_TIME_OF_DAY_HEALING_MOVES, GEN_3); + WITH_CONFIG(CONFIG_TIME_OF_DAY_HEALING_MOVES, GEN_3); PLAYER(SPECIES_WOBBUFFET) { HP(1); MaxHP(200); } OPPONENT(SPECIES_WOBBUFFET); } WHEN { @@ -22,7 +22,7 @@ SINGLE_BATTLE_TEST("Moonlight recovers 1/2 of the user's max HP (Gen3+)") SINGLE_BATTLE_TEST("Moonlight recovers 2/3 of the user's max HP in Sunlight (Gen3+)") { GIVEN { - WITH_CONFIG(GEN_CONFIG_TIME_OF_DAY_HEALING_MOVES, GEN_3); + WITH_CONFIG(CONFIG_TIME_OF_DAY_HEALING_MOVES, GEN_3); PLAYER(SPECIES_WOBBUFFET) { HP(1); MaxHP(300); } OPPONENT(SPECIES_WOBBUFFET); } WHEN { @@ -40,7 +40,7 @@ SINGLE_BATTLE_TEST("Moonlight recovers 1/4 of the user's max HP in Rain, Sandsto PARAMETRIZE { move = MOVE_HAIL; } PARAMETRIZE { move = MOVE_SNOWSCAPE; } GIVEN { - WITH_CONFIG(GEN_CONFIG_TIME_OF_DAY_HEALING_MOVES, GEN_3); + WITH_CONFIG(CONFIG_TIME_OF_DAY_HEALING_MOVES, GEN_3); PLAYER(SPECIES_WOBBUFFET) { HP(1); MaxHP(400); } OPPONENT(SPECIES_WOBBUFFET); } WHEN { diff --git a/test/battle/move_effect/morning_sun.c b/test/battle/move_effect/morning_sun.c index eca9efd31f..10d69ae568 100644 --- a/test/battle/move_effect/morning_sun.c +++ b/test/battle/move_effect/morning_sun.c @@ -9,7 +9,7 @@ ASSUMPTIONS SINGLE_BATTLE_TEST("Morning Sun recovers 1/2 of the user's max HP (Gen3+)") { GIVEN { - WITH_CONFIG(GEN_CONFIG_TIME_OF_DAY_HEALING_MOVES, GEN_3); + WITH_CONFIG(CONFIG_TIME_OF_DAY_HEALING_MOVES, GEN_3); PLAYER(SPECIES_WOBBUFFET) { HP(1); MaxHP(200); } OPPONENT(SPECIES_WOBBUFFET); } WHEN { @@ -22,7 +22,7 @@ SINGLE_BATTLE_TEST("Morning Sun recovers 1/2 of the user's max HP (Gen3+)") SINGLE_BATTLE_TEST("Morning Sun recovers 2/3 of the user's max HP in Sunlight (Gen3+)") { GIVEN { - WITH_CONFIG(GEN_CONFIG_TIME_OF_DAY_HEALING_MOVES, GEN_3); + WITH_CONFIG(CONFIG_TIME_OF_DAY_HEALING_MOVES, GEN_3); PLAYER(SPECIES_WOBBUFFET) { HP(1); MaxHP(300); } OPPONENT(SPECIES_WOBBUFFET); } WHEN { @@ -40,7 +40,7 @@ SINGLE_BATTLE_TEST("Morning Sun recovers 1/4 of the user's max HP in Rain, Sands PARAMETRIZE { move = MOVE_HAIL; } PARAMETRIZE { move = MOVE_SNOWSCAPE; } GIVEN { - WITH_CONFIG(GEN_CONFIG_TIME_OF_DAY_HEALING_MOVES, GEN_3); + WITH_CONFIG(CONFIG_TIME_OF_DAY_HEALING_MOVES, GEN_3); PLAYER(SPECIES_WOBBUFFET) { HP(1); MaxHP(400); } OPPONENT(SPECIES_WOBBUFFET); } WHEN { diff --git a/test/battle/move_effect/multi_hit.c b/test/battle/move_effect/multi_hit.c index 291c78efdb..594094385b 100644 --- a/test/battle/move_effect/multi_hit.c +++ b/test/battle/move_effect/multi_hit.c @@ -33,7 +33,7 @@ SINGLE_BATTLE_TEST("Multi hit Moves hit twice 37.5/35% of the time") PASSES_RANDOMLY(passes, trials, RNG_HITS); GIVEN { - WITH_CONFIG(GEN_CONFIG_MULTI_HIT_CHANCE, genConfig); + WITH_CONFIG(CONFIG_MULTI_HIT_CHANCE, genConfig); PLAYER(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WOBBUFFET); } WHEN { @@ -53,7 +53,7 @@ SINGLE_BATTLE_TEST("Multi hit Moves hit thrice 37.5/35% of the time") PASSES_RANDOMLY(passes, trials, RNG_HITS); GIVEN { - WITH_CONFIG(GEN_CONFIG_MULTI_HIT_CHANCE, genConfig); + WITH_CONFIG(CONFIG_MULTI_HIT_CHANCE, genConfig); PLAYER(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WOBBUFFET); } WHEN { @@ -74,7 +74,7 @@ SINGLE_BATTLE_TEST("Multi hit Moves hit four times 12.5/15% of the time") PASSES_RANDOMLY(passes, trials, RNG_HITS); GIVEN { - WITH_CONFIG(GEN_CONFIG_MULTI_HIT_CHANCE, genConfig); + WITH_CONFIG(CONFIG_MULTI_HIT_CHANCE, genConfig); PLAYER(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WOBBUFFET); } WHEN { @@ -96,7 +96,7 @@ SINGLE_BATTLE_TEST("Multi hit Moves hit five times 12.5/15% of the time") PASSES_RANDOMLY(passes, trials, RNG_HITS); GIVEN { - WITH_CONFIG(GEN_CONFIG_MULTI_HIT_CHANCE, genConfig); + WITH_CONFIG(CONFIG_MULTI_HIT_CHANCE, genConfig); PLAYER(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WOBBUFFET); } WHEN { diff --git a/test/battle/move_effect/nature_power.c b/test/battle/move_effect/nature_power.c index 1e9692f88d..53aa68442d 100644 --- a/test/battle/move_effect/nature_power.c +++ b/test/battle/move_effect/nature_power.c @@ -1,4 +1,27 @@ #include "global.h" #include "test/battle.h" +#include "battle_environment.h" -TO_DO_BATTLE_TEST("TODO: Write Nature Power (Move Effect) test titles") +//TO_DO_BATTLE_TEST("TODO: Write Nature Power (Move Effect) test titles") + +SINGLE_BATTLE_TEST("Nature power plays a move correctly in any background") +{ + u32 environment = 0; + u32 move = MOVE_TRI_ATTACK; + for (u32 j = 0; j < BATTLE_ENVIRONMENT_COUNT; j++) + { + PARAMETRIZE {environment = i;} + } + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + Environment(environment); + if (gBattleEnvironmentInfo[environment].naturePower) + move = gBattleEnvironmentInfo[environment].naturePower; + } WHEN { + TURN { MOVE(player, MOVE_NATURE_POWER); } + } SCENE { + NOT MESSAGE("Nature Power turned into Nature Power!"); + ANIMATION(ANIM_TYPE_MOVE, move, player); + } +} diff --git a/test/battle/move_effect/no_retreat.c b/test/battle/move_effect/no_retreat.c index bf2a15dfbf..fa944ab776 100644 --- a/test/battle/move_effect/no_retreat.c +++ b/test/battle/move_effect/no_retreat.c @@ -2,3 +2,60 @@ #include "test/battle.h" TO_DO_BATTLE_TEST("TODO: Write No Retreat (Move Effect) test titles") + +SINGLE_BATTLE_TEST("No Retreat raises user's Atk/Def/Sp.Atk/Sp.Def/Speed unless No Retreat was already used by user") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_NO_RETREAT); } + TURN { MOVE(player, MOVE_NO_RETREAT); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_NO_RETREAT, player); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); + NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_NO_RETREAT, player); + } THEN { + EXPECT_EQ(player->statStages[STAT_ATK], DEFAULT_STAT_STAGE + 1); + EXPECT_EQ(player->statStages[STAT_DEF], DEFAULT_STAT_STAGE + 1); + EXPECT_EQ(player->statStages[STAT_SPATK], DEFAULT_STAT_STAGE + 1); + EXPECT_EQ(player->statStages[STAT_SPDEF], DEFAULT_STAT_STAGE + 1); + EXPECT_EQ(player->statStages[STAT_SPEED], DEFAULT_STAT_STAGE + 1); + bool32 escapePrevention = gBattleMons[0].volatiles.escapePrevention; + EXPECT_EQ(escapePrevention, TRUE); + } +} + +// Question: If No Retreat is used is the mon blocking the switch out changed? +SINGLE_BATTLE_TEST("No Retreat won't fail if user is prevented from escaping") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_MEAN_LOOK); MOVE(player, MOVE_NO_RETREAT); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_MEAN_LOOK, opponent); + ANIMATION(ANIM_TYPE_MOVE, MOVE_NO_RETREAT, player); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); + } +} + +SINGLE_BATTLE_TEST("No Retreat won't activate Protean if it fails due to already being used by the user") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_KECLEON) { Ability(ABILITY_PROTEAN); } + } WHEN { + TURN { MOVE(player, MOVE_NO_RETREAT); MOVE(opponent, MOVE_SKILL_SWAP); } + TURN { MOVE(player, MOVE_NO_RETREAT); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_NO_RETREAT, player); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SKILL_SWAP, opponent); + NONE_OF { + ANIMATION(ANIM_TYPE_MOVE, MOVE_NO_RETREAT, player); + ABILITY_POPUP(player, ABILITY_PROTEAN); + } + } +} diff --git a/test/battle/move_effect/noble_roar.c b/test/battle/move_effect/noble_roar.c index 4fd182b84d..f683619b4f 100644 --- a/test/battle/move_effect/noble_roar.c +++ b/test/battle/move_effect/noble_roar.c @@ -1,4 +1,23 @@ #include "global.h" #include "test/battle.h" -TO_DO_BATTLE_TEST("TODO: Write Noble Roar (Move Effect) test titles") +ASSUMPTIONS +{ + ASSUME(GetMoveEffect(MOVE_NOBLE_ROAR) == EFFECT_NOBLE_ROAR); +} + +SINGLE_BATTLE_TEST("Noble Roar reduces the target's Attack and Sp. Attack by 1 stage each") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_NOBLE_ROAR); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_NOBLE_ROAR, player); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); + } THEN { + EXPECT_EQ(opponent->statStages[STAT_ATK], DEFAULT_STAT_STAGE - 1); + EXPECT_EQ(opponent->statStages[STAT_SPATK], DEFAULT_STAT_STAGE - 1); + } +} diff --git a/test/battle/move_effect/octolock.c b/test/battle/move_effect/octolock.c index 74e0b0fc4c..b98c17908d 100644 --- a/test/battle/move_effect/octolock.c +++ b/test/battle/move_effect/octolock.c @@ -21,7 +21,7 @@ SINGLE_BATTLE_TEST("Octolock decreases Defense and Sp. Def by at the end of the SINGLE_BATTLE_TEST("Octolock reduction is prevented by Clear Body, White Smoke and Full Metal Body") { u32 species; - u32 ability; + enum Ability ability; PARAMETRIZE { species = SPECIES_BELDUM; ability = ABILITY_CLEAR_BODY; } PARAMETRIZE { species = SPECIES_TORKOAL; ability = ABILITY_WHITE_SMOKE; } diff --git a/test/battle/move_effect/overwrite_ability.c b/test/battle/move_effect/overwrite_ability.c new file mode 100644 index 0000000000..e4be2b0667 --- /dev/null +++ b/test/battle/move_effect/overwrite_ability.c @@ -0,0 +1,150 @@ +#include "global.h" +#include "test/battle.h" + +SINGLE_BATTLE_TEST("Simple Beam replaces target's ability with Simple") +{ + GIVEN { + ASSUME(GetMoveEffect(MOVE_SIMPLE_BEAM) == EFFECT_OVERWRITE_ABILITY); + ASSUME(GetMoveOverwriteAbility(MOVE_SIMPLE_BEAM) == ABILITY_SIMPLE); + PLAYER(SPECIES_WOBBUFFET) { Ability(ABILITY_TELEPATHY); } + OPPONENT(SPECIES_CHARMANDER) { Ability(ABILITY_BLAZE); } + }WHEN { + TURN { MOVE(player, MOVE_SIMPLE_BEAM); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SIMPLE_BEAM, player); + ABILITY_POPUP(opponent, ABILITY_BLAZE); + } THEN { + EXPECT_EQ(opponent->ability, ABILITY_SIMPLE); + } +} + +DOUBLE_BATTLE_TEST("Simple Beam fails if the target already has Simple") +{ + GIVEN { + ASSUME(GetMoveEffect(MOVE_SIMPLE_BEAM) == EFFECT_OVERWRITE_ABILITY); + ASSUME(GetMoveOverwriteAbility(MOVE_SIMPLE_BEAM) == ABILITY_SIMPLE); + PLAYER(SPECIES_WOBBUFFET) { Ability(ABILITY_TELEPATHY); } + PLAYER(SPECIES_CHARMANDER) { Ability(ABILITY_BLAZE); } + OPPONENT(SPECIES_BULBASAUR) { Ability(ABILITY_OVERGROW); } + OPPONENT(SPECIES_SQUIRTLE) { Ability(ABILITY_TORRENT); } + } WHEN { + TURN { MOVE(playerLeft, MOVE_SIMPLE_BEAM, target: opponentLeft); MOVE(playerRight, MOVE_SIMPLE_BEAM, target: opponentLeft); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SIMPLE_BEAM, playerLeft); + ABILITY_POPUP(opponentLeft, ABILITY_OVERGROW); + NONE_OF { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SIMPLE_BEAM, playerRight); + ABILITY_POPUP(opponentLeft, ABILITY_SIMPLE); + } + } THEN { + EXPECT_EQ(opponentLeft->ability, ABILITY_SIMPLE); + } +} + +SINGLE_BATTLE_TEST("Simple Beam fails if target has an ability that can't be overwritten") +{ + u32 species; + enum Ability ability; + + PARAMETRIZE { species = SPECIES_ARCEUS; ability = ABILITY_MULTITYPE; } + PARAMETRIZE { species = SPECIES_AEGISLASH; ability = ABILITY_STANCE_CHANGE; } + PARAMETRIZE { species = SPECIES_MINIOR; ability = ABILITY_SHIELDS_DOWN; } + PARAMETRIZE { species = SPECIES_WISHIWASHI; ability = ABILITY_SCHOOLING; } + PARAMETRIZE { species = SPECIES_MIMIKYU; ability = ABILITY_DISGUISE; } + PARAMETRIZE { species = SPECIES_GRENINJA_BATTLE_BOND; ability = ABILITY_BATTLE_BOND; } + PARAMETRIZE { species = SPECIES_ZYGARDE; ability = ABILITY_POWER_CONSTRUCT; } + PARAMETRIZE { species = SPECIES_KOMALA; ability = ABILITY_COMATOSE; } + PARAMETRIZE { species = SPECIES_SILVALLY; ability = ABILITY_RKS_SYSTEM; } + PARAMETRIZE { species = SPECIES_CRAMORANT; ability = ABILITY_GULP_MISSILE; } + PARAMETRIZE { species = SPECIES_EISCUE; ability = ABILITY_ICE_FACE; } + PARAMETRIZE { species = SPECIES_CALYREX_ICE; ability = ABILITY_AS_ONE_ICE_RIDER; } + PARAMETRIZE { species = SPECIES_CALYREX_SHADOW; ability = ABILITY_AS_ONE_SHADOW_RIDER; } + PARAMETRIZE { species = SPECIES_PALAFIN_ZERO; ability = ABILITY_ZERO_TO_HERO; } + PARAMETRIZE { species = SPECIES_TATSUGIRI; ability = ABILITY_COMMANDER; } + + GIVEN { + ASSUME(GetMoveEffect(MOVE_SIMPLE_BEAM) == EFFECT_OVERWRITE_ABILITY); + ASSUME(GetMoveOverwriteAbility(MOVE_SIMPLE_BEAM) == ABILITY_SIMPLE); + PLAYER(SPECIES_WOBBUFFET) { Ability(ABILITY_TELEPATHY); } + OPPONENT(species) { Ability(ability); } + } WHEN { + TURN { MOVE(player, MOVE_SIMPLE_BEAM); } + } SCENE { + NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_SIMPLE_BEAM, player); + MESSAGE("But it failed!"); + } +} + +SINGLE_BATTLE_TEST("Worry Seed replaces target's ability with Insomnia") +{ + GIVEN { + ASSUME(GetMoveEffect(MOVE_WORRY_SEED) == EFFECT_OVERWRITE_ABILITY); + ASSUME(GetMoveOverwriteAbility(MOVE_WORRY_SEED) == ABILITY_INSOMNIA); + PLAYER(SPECIES_WOBBUFFET) { Ability(ABILITY_TELEPATHY); } + OPPONENT(SPECIES_CHARMANDER) { Ability(ABILITY_BLAZE); } + }WHEN { + TURN { MOVE(player, MOVE_WORRY_SEED); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_WORRY_SEED, player); + ABILITY_POPUP(opponent, ABILITY_BLAZE); + } THEN { + EXPECT_EQ(opponent->ability, ABILITY_INSOMNIA); + } +} + +DOUBLE_BATTLE_TEST("Worry Seed fails if the target already has Insomnia") +{ + GIVEN { + ASSUME(GetMoveEffect(MOVE_WORRY_SEED) == EFFECT_OVERWRITE_ABILITY); + ASSUME(GetMoveOverwriteAbility(MOVE_WORRY_SEED) == ABILITY_INSOMNIA); + PLAYER(SPECIES_WOBBUFFET) { Ability(ABILITY_TELEPATHY); } + PLAYER(SPECIES_CHARMANDER) { Ability(ABILITY_BLAZE); } + OPPONENT(SPECIES_BULBASAUR) { Ability(ABILITY_OVERGROW); } + OPPONENT(SPECIES_SQUIRTLE) { Ability(ABILITY_TORRENT); } + } WHEN { + TURN { MOVE(playerLeft, MOVE_WORRY_SEED, target: opponentLeft); MOVE(playerRight, MOVE_WORRY_SEED, target: opponentLeft); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_WORRY_SEED, playerLeft); + ABILITY_POPUP(opponentLeft, ABILITY_OVERGROW); + NONE_OF { + ANIMATION(ANIM_TYPE_MOVE, MOVE_WORRY_SEED, playerRight); + ABILITY_POPUP(opponentLeft, ABILITY_INSOMNIA); + } + } THEN { + EXPECT_EQ(opponentLeft->ability, ABILITY_INSOMNIA); + } +} + +SINGLE_BATTLE_TEST("Worry Seed fails if target has an ability that can't be overwritten") +{ + u32 species; + enum Ability ability; + + PARAMETRIZE { species = SPECIES_ARCEUS; ability = ABILITY_MULTITYPE; } + PARAMETRIZE { species = SPECIES_AEGISLASH; ability = ABILITY_STANCE_CHANGE; } + PARAMETRIZE { species = SPECIES_MINIOR; ability = ABILITY_SHIELDS_DOWN; } + PARAMETRIZE { species = SPECIES_WISHIWASHI; ability = ABILITY_SCHOOLING; } + PARAMETRIZE { species = SPECIES_MIMIKYU; ability = ABILITY_DISGUISE; } + PARAMETRIZE { species = SPECIES_GRENINJA_BATTLE_BOND; ability = ABILITY_BATTLE_BOND; } + PARAMETRIZE { species = SPECIES_ZYGARDE; ability = ABILITY_POWER_CONSTRUCT; } + PARAMETRIZE { species = SPECIES_KOMALA; ability = ABILITY_COMATOSE; } + PARAMETRIZE { species = SPECIES_SILVALLY; ability = ABILITY_RKS_SYSTEM; } + PARAMETRIZE { species = SPECIES_CRAMORANT; ability = ABILITY_GULP_MISSILE; } + PARAMETRIZE { species = SPECIES_EISCUE; ability = ABILITY_ICE_FACE; } + PARAMETRIZE { species = SPECIES_CALYREX_ICE; ability = ABILITY_AS_ONE_ICE_RIDER; } + PARAMETRIZE { species = SPECIES_CALYREX_SHADOW; ability = ABILITY_AS_ONE_SHADOW_RIDER; } + PARAMETRIZE { species = SPECIES_PALAFIN_ZERO; ability = ABILITY_ZERO_TO_HERO; } + PARAMETRIZE { species = SPECIES_TATSUGIRI; ability = ABILITY_COMMANDER; } + + GIVEN { + ASSUME(GetMoveEffect(MOVE_WORRY_SEED) == EFFECT_OVERWRITE_ABILITY); + ASSUME(GetMoveOverwriteAbility(MOVE_WORRY_SEED) == ABILITY_INSOMNIA); + PLAYER(SPECIES_WOBBUFFET) { Ability(ABILITY_TELEPATHY); } + OPPONENT(species) { Ability(ability); } + } WHEN { + TURN { MOVE(player, MOVE_WORRY_SEED); } + } SCENE { + NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_WORRY_SEED, player); + MESSAGE("But it failed!"); + } +} diff --git a/test/battle/move_effect/powder.c b/test/battle/move_effect/powder.c index 0cfeeb0a8d..2bcfc58da8 100644 --- a/test/battle/move_effect/powder.c +++ b/test/battle/move_effect/powder.c @@ -83,7 +83,7 @@ SINGLE_BATTLE_TEST("Powder doesn't damage target if it has Magic Guard") SINGLE_BATTLE_TEST("Powder damages the target under heavy rain (Gen 6)") { GIVEN { - WITH_CONFIG(GEN_CONFIG_POWDER_RAIN, GEN_6); + WITH_CONFIG(CONFIG_POWDER_RAIN, GEN_6); PLAYER(SPECIES_KYOGRE_PRIMAL) { Ability(ABILITY_PRIMORDIAL_SEA); } OPPONENT(SPECIES_VIVILLON); } WHEN { @@ -100,7 +100,7 @@ SINGLE_BATTLE_TEST("Powder damages the target under heavy rain (Gen 6)") SINGLE_BATTLE_TEST("Powder doesn't damage target under heavy rain (Gen 7+)") { GIVEN { - WITH_CONFIG(GEN_CONFIG_POWDER_RAIN, GEN_7); + WITH_CONFIG(CONFIG_POWDER_RAIN, GEN_7); PLAYER(SPECIES_KYOGRE_PRIMAL) { Ability(ABILITY_PRIMORDIAL_SEA); } OPPONENT(SPECIES_VIVILLON); } WHEN { @@ -152,7 +152,7 @@ DOUBLE_BATTLE_TEST("Powder fails if target is already affected by Powder") SINGLE_BATTLE_TEST("Powder fails if the target is Grass type (Gen6+)") { GIVEN { - WITH_CONFIG(GEN_CONFIG_POWDER_GRASS, GEN_6); + WITH_CONFIG(CONFIG_POWDER_GRASS, GEN_6); ASSUME(GetSpeciesType(SPECIES_VENUSAUR, 0) == TYPE_GRASS || GetSpeciesType(SPECIES_VENUSAUR, 1) == TYPE_GRASS); PLAYER(SPECIES_VENUSAUR); OPPONENT(SPECIES_VIVILLON); @@ -168,7 +168,7 @@ SINGLE_BATTLE_TEST("Powder fails if the target is Grass type (Gen6+)") SINGLE_BATTLE_TEST("Powder fails if the target has Overcoat (Gen6+)") { GIVEN { - WITH_CONFIG(GEN_CONFIG_POWDER_OVERCOAT, GEN_6); + WITH_CONFIG(CONFIG_POWDER_OVERCOAT, GEN_6); PLAYER(SPECIES_FORRETRESS) { Ability(ABILITY_OVERCOAT); } OPPONENT(SPECIES_VIVILLON); } WHEN { diff --git a/test/battle/move_effect/protect.c b/test/battle/move_effect/protect.c index 97a09bd922..05b238fe0e 100644 --- a/test/battle/move_effect/protect.c +++ b/test/battle/move_effect/protect.c @@ -356,6 +356,42 @@ SINGLE_BATTLE_TEST("Protect: Multi-hit moves don't hit a protected target and fa } } +SINGLE_BATTLE_TEST("Protect fails if user moves last") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Speed(5); } + OPPONENT(SPECIES_WYNAUT) { Speed(10); } + } WHEN { + TURN { MOVE(opponent, MOVE_CELEBRATE); MOVE(player, MOVE_PROTECT); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponent); + NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_PROTECT, player); + } +} + +DOUBLE_BATTLE_TEST("Protect fails when the only slower battler is a fainted ally") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Speed(5); } + PLAYER(SPECIES_WYNAUT) { HP(1); Speed(1); } + OPPONENT(SPECIES_WOBBUFFET) { Speed(20); } + OPPONENT(SPECIES_WYNAUT) { Speed(10); } + } WHEN { + TURN { MOVE(opponentLeft, MOVE_SCRATCH, target: playerRight); } + TURN { + MOVE(opponentLeft, MOVE_CELEBRATE); + MOVE(opponentRight, MOVE_CELEBRATE); + MOVE(playerLeft, MOVE_PROTECT); + } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SCRATCH, opponentLeft); + MESSAGE("Wynaut fainted!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponentLeft); + ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponentRight); + NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_PROTECT, playerLeft); + } +} + DOUBLE_BATTLE_TEST("Protect: Wide Guard protects self and ally from multi-target moves") { u16 move = MOVE_NONE; @@ -398,12 +434,15 @@ DOUBLE_BATTLE_TEST("Protect: Wide Guard protects self and ally from multi-target } } -DOUBLE_BATTLE_TEST("Protect: Wide Guard can not fail on consecutive turns") +DOUBLE_BATTLE_TEST("Protect: Wide Guard can not fail on consecutive turns (Gen6+)") { - u8 turns; + u32 turns, config, passes; - PASSES_RANDOMLY(2, 2); + PARAMETRIZE { config = GEN_5; passes = 0; } + PARAMETRIZE { config = GEN_6; passes = 2; } + PASSES_RANDOMLY(passes, 2); GIVEN { + WITH_CONFIG(CONFIG_WIDE_GUARD, config); ASSUME(GetMoveTarget(MOVE_HYPER_VOICE) == MOVE_TARGET_BOTH); PLAYER(SPECIES_WOBBUFFET); PLAYER(SPECIES_WOBBUFFET); @@ -431,8 +470,8 @@ DOUBLE_BATTLE_TEST("Protect: Quick Guard protects self and ally from priority mo u16 move = MOVE_NONE; struct BattlePokemon *targetOpponent = NULL; - PARAMETRIZE { move = MOVE_SCRATCH; targetOpponent = opponentLeft; } - PARAMETRIZE { move = MOVE_SCRATCH; targetOpponent = opponentRight; } + PARAMETRIZE { move = MOVE_SCRATCH; targetOpponent = opponentLeft; } + PARAMETRIZE { move = MOVE_SCRATCH; targetOpponent = opponentRight; } PARAMETRIZE { move = MOVE_QUICK_ATTACK; targetOpponent = opponentLeft; } PARAMETRIZE { move = MOVE_QUICK_ATTACK; targetOpponent = opponentRight; } @@ -461,12 +500,15 @@ DOUBLE_BATTLE_TEST("Protect: Quick Guard protects self and ally from priority mo } } -DOUBLE_BATTLE_TEST("Protect: Quick Guard can not fail on consecutive turns") +DOUBLE_BATTLE_TEST("Protect: Quick Guard can not fail on consecutive turns (Gen6+)") { - u8 turns; + u32 turns, config, passes; - PASSES_RANDOMLY(2, 2); + PARAMETRIZE { config = GEN_5; passes = 0; } + PARAMETRIZE { config = GEN_6; passes = 2; } + PASSES_RANDOMLY(passes, 2); GIVEN { + WITH_CONFIG(CONFIG_QUICK_GUARD, config); ASSUME(GetMovePriority(MOVE_QUICK_ATTACK) == 1); PLAYER(SPECIES_WOBBUFFET); PLAYER(SPECIES_WOBBUFFET); diff --git a/test/battle/move_effect/psychic_terrain.c b/test/battle/move_effect/psychic_terrain.c index 51fdb236ef..36f4841ef1 100644 --- a/test/battle/move_effect/psychic_terrain.c +++ b/test/battle/move_effect/psychic_terrain.c @@ -11,7 +11,7 @@ SINGLE_BATTLE_TEST("Psychic Terrain protects grounded battlers from priority mov TURN { MOVE(player, MOVE_QUICK_ATTACK); MOVE(opponent, MOVE_QUICK_ATTACK); } } SCENE { MESSAGE("Claydol used Psychic Terrain!"); - MESSAGE("Claydol cannot use Quick Attack!"); + MESSAGE("The opposing Wobbuffet is protected by the Psychic Terrain!"); NOT { HP_BAR(opponent); } MESSAGE("The opposing Wobbuffet used Quick Attack!"); HP_BAR(player); @@ -41,7 +41,7 @@ SINGLE_BATTLE_TEST("Psychic Terrain increases power of Psychic-type moves by 30/ } } -SINGLE_BATTLE_TEST("Psychic Terrain doesn't block priority moves that target the user") +SINGLE_BATTLE_TEST("Psychic Terrain doesn't blocks priority moves that target the user") { GIVEN { PLAYER(SPECIES_SABLEYE) { Ability(ABILITY_PRANKSTER); HP(1); } @@ -120,7 +120,7 @@ SINGLE_BATTLE_TEST("Psychic Terrain doesn't block priority moves against semi-in PARAMETRIZE { move = MOVE_SOLAR_BEAM; shouldWork = FALSE;} PARAMETRIZE { move = MOVE_FLY; shouldWork = TRUE;} GIVEN { - WITH_CONFIG(GEN_CONFIG_TOXIC_NEVER_MISS, GEN_6); + WITH_CONFIG(CONFIG_TOXIC_NEVER_MISS, GEN_6); ASSUME(IsSpeciesOfType(SPECIES_SHROODLE, TYPE_POISON)); PLAYER(SPECIES_SHROODLE) { Ability(ABILITY_PRANKSTER); } OPPONENT(SPECIES_WOBBUFFET); @@ -176,3 +176,37 @@ SINGLE_BATTLE_TEST("Psychic Terrain lasts for 5 turns") MESSAGE("The weirdness disappeared from the battlefield!"); } } + +DOUBLE_BATTLE_TEST("Psychic Terrain protects grounded battlers from priority moves in doubles - Left") +{ + GIVEN { + PLAYER(SPECIES_CLAYDOL) { Ability(ABILITY_LEVITATE); } + PLAYER(SPECIES_TAPU_LELE) { Ability(ABILITY_PSYCHIC_SURGE); } + OPPONENT(SPECIES_VOLBEAT) { Ability(ABILITY_PRANKSTER); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponentLeft, MOVE_COTTON_SPORE); } + } SCENE { + ABILITY_POPUP(playerRight, ABILITY_PSYCHIC_SURGE); + ANIMATION(ANIM_TYPE_MOVE, MOVE_COTTON_SPORE, opponentLeft); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerLeft); + NOT ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerRight); + } +} + +DOUBLE_BATTLE_TEST("Psychic Terrain protects grounded battlers from priority moves in doubles - Right") +{ + GIVEN { + PLAYER(SPECIES_TAPU_LELE) { Ability(ABILITY_PSYCHIC_SURGE); } + PLAYER(SPECIES_CLAYDOL) { Ability(ABILITY_LEVITATE); } + OPPONENT(SPECIES_VOLBEAT) { Ability(ABILITY_PRANKSTER); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponentLeft, MOVE_COTTON_SPORE); } + } SCENE { + ABILITY_POPUP(playerLeft, ABILITY_PSYCHIC_SURGE); + ANIMATION(ANIM_TYPE_MOVE, MOVE_COTTON_SPORE, opponentLeft); + NOT ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerLeft); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerRight); + } +} diff --git a/test/battle/move_effect/purify.c b/test/battle/move_effect/purify.c index 5f1651e96f..425d0a99a9 100644 --- a/test/battle/move_effect/purify.c +++ b/test/battle/move_effect/purify.c @@ -22,5 +22,45 @@ AI_DOUBLE_BATTLE_TEST("AI uses Purify") } } +AI_SINGLE_BATTLE_TEST("AI uses Purify to heal an enemy with Guts") +{ + u32 ability; + + PARAMETRIZE { ability = ABILITY_GUTS; } + PARAMETRIZE { ability = ABILITY_BULLETPROOF; } + + GIVEN { + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY | AI_FLAG_OMNISCIENT); + PLAYER(SPECIES_URSALUNA) { Ability(ability); Moves(MOVE_HEADLONG_RUSH, MOVE_CELEBRATE); Status1(STATUS1_BURN); } + OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_HEADBUTT, MOVE_PURIFY); } + } WHEN { + if (ability == ABILITY_GUTS) + TURN { EXPECT_MOVE(opponent, MOVE_PURIFY); } + else + TURN { NOT_EXPECT_MOVE(opponent, MOVE_PURIFY); } + } +} + +AI_DOUBLE_BATTLE_TEST("AI does not use Purify to heal an ally with Guts") +{ + u32 ability; + + PARAMETRIZE { ability = ABILITY_GUTS; } + PARAMETRIZE { ability = ABILITY_BULLETPROOF; } + + GIVEN { + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY | AI_FLAG_OMNISCIENT); + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_HEADBUTT, MOVE_PURIFY); } + OPPONENT(SPECIES_URSALUNA) { Ability(ability); Moves(MOVE_HEADLONG_RUSH); Status1(STATUS1_BURN); } + } WHEN { + if (ability == ABILITY_GUTS) + TURN { NOT_EXPECT_MOVE(opponentLeft, MOVE_PURIFY); } + else + TURN { EXPECT_MOVE(opponentLeft, MOVE_PURIFY, target: opponentRight); } + } +} + TO_DO_BATTLE_TEST("TODO: Write Purify (Move Effect) test titles") TO_DO_BATTLE_TEST("Purify doesn't heal HP if the target has Comatose") diff --git a/test/battle/move_effect/pursuit.c b/test/battle/move_effect/pursuit.c index 27303d95ce..cc8c0a72b8 100644 --- a/test/battle/move_effect/pursuit.c +++ b/test/battle/move_effect/pursuit.c @@ -51,7 +51,7 @@ DOUBLE_BATTLE_TEST("Pursuit doesn't attack a foe using Teleport / Baton Pass to PARAMETRIZE { move = MOVE_TELEPORT; } PARAMETRIZE { move = MOVE_BATON_PASS; } GIVEN { - WITH_CONFIG(GEN_CONFIG_TELEPORT_BEHAVIOR, GEN_8); + WITH_CONFIG(CONFIG_TELEPORT_BEHAVIOR, GEN_8); ASSUME(GetMoveEffect(MOVE_QUASH) == EFFECT_QUASH); ASSUME(GetMoveEffect(MOVE_TELEPORT) == EFFECT_TELEPORT); ASSUME(GetMoveEffect(MOVE_BATON_PASS) == EFFECT_BATON_PASS); diff --git a/test/battle/move_effect/quash.c b/test/battle/move_effect/quash.c index a6032b43c4..0fc2fbd25d 100644 --- a/test/battle/move_effect/quash.c +++ b/test/battle/move_effect/quash.c @@ -26,7 +26,7 @@ DOUBLE_BATTLE_TEST("Quash-affected target will move last in the priority bracket DOUBLE_BATTLE_TEST("Quash is not affected by dynamic speed") { GIVEN { - WITH_CONFIG(GEN_CONFIG_RECALC_TURN_AFTER_ACTIONS, GEN_8); + WITH_CONFIG(CONFIG_RECALC_TURN_AFTER_ACTIONS, GEN_8); ASSUME(GetMoveEffect(MOVE_TAILWIND) == EFFECT_TAILWIND); PLAYER(SPECIES_VOLBEAT) { Speed(10); Ability(ABILITY_PRANKSTER); } PLAYER(SPECIES_WOBBUFFET) { Speed(30); } @@ -112,7 +112,7 @@ DOUBLE_BATTLE_TEST("Quash-affected targets move from fastest to slowest (Gen 8+) DOUBLE_BATTLE_TEST("Quash-affected mon that acted early via After You is not affected by dynamic speed") { GIVEN { - WITH_CONFIG(GEN_CONFIG_RECALC_TURN_AFTER_ACTIONS, GEN_8); + WITH_CONFIG(CONFIG_RECALC_TURN_AFTER_ACTIONS, GEN_8); ASSUME(GetMoveEffect(MOVE_TAILWIND) == EFFECT_TAILWIND); ASSUME(GetMoveEffect(MOVE_AFTER_YOU) == EFFECT_AFTER_YOU); PLAYER(SPECIES_VOLBEAT) { Speed(20); Ability(ABILITY_PRANKSTER); } diff --git a/test/battle/move_effect/quiver_dance.c b/test/battle/move_effect/quiver_dance.c index 5a7ff5b944..b317d39878 100644 --- a/test/battle/move_effect/quiver_dance.c +++ b/test/battle/move_effect/quiver_dance.c @@ -1,4 +1,24 @@ #include "global.h" #include "test/battle.h" -TO_DO_BATTLE_TEST("TODO: Write Quiver Dance (Move Effect) test titles") +ASSUMPTIONS +{ + ASSUME(GetMoveEffect(MOVE_QUIVER_DANCE) == EFFECT_QUIVER_DANCE); +} + +SINGLE_BATTLE_TEST("Quiver Dance increases the user's Sp. Attack, Sp. Defense and Speed by 1 stage each") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_QUIVER_DANCE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_QUIVER_DANCE, player); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); + } THEN { + EXPECT_EQ(player->statStages[STAT_SPATK], DEFAULT_STAT_STAGE + 1); + EXPECT_EQ(player->statStages[STAT_SPDEF], DEFAULT_STAT_STAGE + 1); + EXPECT_EQ(player->statStages[STAT_SPEED], DEFAULT_STAT_STAGE + 1); + } +} diff --git a/test/battle/move_effect/rage_fist.c b/test/battle/move_effect/rage_fist.c index a750893d11..7a0b6bc322 100644 --- a/test/battle/move_effect/rage_fist.c +++ b/test/battle/move_effect/rage_fist.c @@ -258,7 +258,7 @@ SINGLE_BATTLE_TEST("Rage Fist base power is increased if Disguise breaks (Gen7)" PARAMETRIZE { species = SPECIES_MIMIKYU_TOTEM_DISGUISED; } GIVEN { - WITH_CONFIG(GEN_CONFIG_DISGUISE_HP_LOSS, GEN_7); + WITH_CONFIG(CONFIG_DISGUISE_HP_LOSS, GEN_7); PLAYER(species) { Ability(ABILITY_DISGUISE); } OPPONENT(SPECIES_REGIROCK); } WHEN { @@ -285,7 +285,7 @@ SINGLE_BATTLE_TEST("Rage Fist base power is increased if Disguise breaks (Gen8+) PARAMETRIZE { species = SPECIES_MIMIKYU_TOTEM_DISGUISED; } GIVEN { - WITH_CONFIG(GEN_CONFIG_DISGUISE_HP_LOSS, GEN_8); + WITH_CONFIG(CONFIG_DISGUISE_HP_LOSS, GEN_8); PLAYER(species) { Ability(ABILITY_DISGUISE); } OPPONENT(SPECIES_REGIROCK); } WHEN { diff --git a/test/battle/move_effect/rain_always_hit.c b/test/battle/move_effect/rain_always_hit.c deleted file mode 100644 index 3bed952a37..0000000000 --- a/test/battle/move_effect/rain_always_hit.c +++ /dev/null @@ -1,4 +0,0 @@ -#include "global.h" -#include "test/battle.h" - -TO_DO_BATTLE_TEST("TODO: Write Bleakwind/Wildbolt/Sandsear Storm (Move Effect) test titles") diff --git a/test/battle/move_effect/recoil.c b/test/battle/move_effect/recoil.c new file mode 100644 index 0000000000..60bf17435a --- /dev/null +++ b/test/battle/move_effect/recoil.c @@ -0,0 +1,4 @@ +#include "global.h" +#include "test/battle.h" + +TO_DO_BATTLE_TEST("TODO: Write Take Down (Move Effect) test titles") diff --git a/test/battle/move_effect/recoil_hp_25.c b/test/battle/move_effect/recoil_hp_25.c deleted file mode 100644 index 9abb1bcfd0..0000000000 --- a/test/battle/move_effect/recoil_hp_25.c +++ /dev/null @@ -1,4 +0,0 @@ -#include "global.h" -#include "test/battle.h" - -TO_DO_BATTLE_TEST("TODO: Write Struggle (Move Effect) test titles") diff --git a/test/battle/move_effect/recoil_if_miss.c b/test/battle/move_effect/recoil_if_miss.c index a5dbfef178..7f62f2065e 100644 --- a/test/battle/move_effect/recoil_if_miss.c +++ b/test/battle/move_effect/recoil_if_miss.c @@ -41,7 +41,7 @@ SINGLE_BATTLE_TEST("Recoil if miss: Jump Kick has 50% recoil on protect") SINGLE_BATTLE_TEST("Recoil if miss: Jump Kick has no recoil if no target") { GIVEN { - ASSUME(B_HEALING_WISH_SWITCH >= GEN_5); + WITH_CONFIG(CONFIG_HEALING_WISH_SWITCH, GEN_5); PLAYER(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WYNAUT); @@ -134,7 +134,7 @@ SINGLE_BATTLE_TEST("Recoil if miss: Supercell Slam causes recoil if it is absorb SINGLE_BATTLE_TEST("Recoil if miss: Disguise doesn't prevent crash damage from Jump Kick into ghost types") { - u32 ability; + enum Ability ability; PARAMETRIZE { ability = ABILITY_EARLY_BIRD; } PARAMETRIZE { ability = ABILITY_SCRAPPY; } @@ -154,4 +154,3 @@ SINGLE_BATTLE_TEST("Recoil if miss: Disguise doesn't prevent crash damage from J } } } - diff --git a/test/battle/move_effect/revenge.c b/test/battle/move_effect/revenge.c index 980bca9e33..1b5c79d00a 100644 --- a/test/battle/move_effect/revenge.c +++ b/test/battle/move_effect/revenge.c @@ -1,4 +1,69 @@ #include "global.h" #include "test/battle.h" -TO_DO_BATTLE_TEST("TODO: Write Revenge (Move Effect) test titles") +ASSUMPTIONS +{ + ASSUME(GetMoveEffect(MOVE_REVENGE) == EFFECT_REVENGE); +} + +SINGLE_BATTLE_TEST("Revenge doubles in power if False Swipe connected but didn't do any damage") +{ + s16 hits[3]; + + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { HP(1); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_CELEBRATE); MOVE(player, MOVE_REVENGE); } + TURN { MOVE(opponent, MOVE_FALSE_SWIPE); MOVE(player, MOVE_REVENGE); } + TURN { MOVE(opponent, MOVE_CELEBRATE); MOVE(player, MOVE_REVENGE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_REVENGE, player); + HP_BAR(opponent, captureDamage: &hits[0]); + ANIMATION(ANIM_TYPE_MOVE, MOVE_FALSE_SWIPE, opponent); + ANIMATION(ANIM_TYPE_MOVE, MOVE_REVENGE, player); + HP_BAR(opponent, captureDamage: &hits[1]); + ANIMATION(ANIM_TYPE_MOVE, MOVE_REVENGE, player); + HP_BAR(opponent, captureDamage: &hits[2]); + } THEN { + EXPECT_MUL_EQ(hits[0], Q_4_12(2.0), hits[1]); + EXPECT_EQ(hits[0], hits[2]); + } +} + +DOUBLE_BATTLE_TEST("Revenge doesn't double in power if user was not hit by target in doubles") +{ + s16 hits[3]; + + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { + MOVE(opponentLeft, MOVE_REVENGE, target: playerRight); } + TURN { + MOVE(playerRight, MOVE_POUND, target: opponentRight); + MOVE(opponentLeft, MOVE_REVENGE, target: playerRight); + } + TURN { + MOVE(playerRight, MOVE_POUND, target: opponentLeft); + MOVE(opponentLeft, MOVE_REVENGE, target: playerRight); + } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_REVENGE, opponentLeft); + HP_BAR(playerRight, captureDamage: &hits[0]); + + ANIMATION(ANIM_TYPE_MOVE, MOVE_POUND, playerRight); + ANIMATION(ANIM_TYPE_MOVE, MOVE_REVENGE, opponentLeft); + HP_BAR(playerRight, captureDamage: &hits[1]); + + ANIMATION(ANIM_TYPE_MOVE, MOVE_POUND, playerRight); + ANIMATION(ANIM_TYPE_MOVE, MOVE_REVENGE, opponentLeft); + HP_BAR(playerRight, captureDamage: &hits[2]); + } THEN { + EXPECT_EQ(hits[0], hits[1]); + EXPECT_MUL_EQ(hits[1], Q_4_12(2.0), hits[2]); + } +} diff --git a/test/battle/move_effect/revival_blessing.c b/test/battle/move_effect/revival_blessing.c index f1a0ad74bc..eeb90d202d 100644 --- a/test/battle/move_effect/revival_blessing.c +++ b/test/battle/move_effect/revival_blessing.c @@ -49,29 +49,36 @@ SINGLE_BATTLE_TEST("Revival Blessing fails if no party members are fainted") } } -DOUBLE_BATTLE_TEST("Revival Blessing cannot revive a partner's party member") +// Can only be tested through AI test, else test fails due to trying to force illegal action +AI_MULTI_BATTLE_TEST("Revival Blessing cannot revive a partner's party member") { - KNOWN_FAILING; struct BattlePokemon *user = NULL; - gBattleTypeFlags |= BATTLE_TYPE_TWO_OPPONENTS; - PARAMETRIZE { user = opponentLeft; } - PARAMETRIZE { user = opponentRight; } + u32 move1, move2, move3; + PARAMETRIZE { user = opponentLeft, move1 = MOVE_REVIVAL_BLESSING, move2 = MOVE_CELEBRATE, move3 = MOVE_CELEBRATE; } + PARAMETRIZE { user = playerRight, move1 = MOVE_CELEBRATE, move2 = MOVE_REVIVAL_BLESSING, move3 = MOVE_CELEBRATE; } + PARAMETRIZE { user = opponentRight, move1 = MOVE_CELEBRATE, move2 = MOVE_CELEBRATE, move3 = MOVE_REVIVAL_BLESSING; } GIVEN { - ASSUME((gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS) != FALSE); - PLAYER(SPECIES_WOBBUFFET); - PLAYER(SPECIES_WOBBUFFET); - OPPONENT(SPECIES_WOBBUFFET); - OPPONENT(SPECIES_WOBBUFFET); - OPPONENT(SPECIES_WOBBUFFET); - OPPONENT(SPECIES_WYNAUT); - OPPONENT(SPECIES_WYNAUT) { HP(0); } - OPPONENT(SPECIES_WYNAUT); + MULTI_PLAYER(SPECIES_CLEFABLE); + MULTI_PLAYER(SPECIES_CLEFABLE) { HP(0); } + MULTI_PLAYER(SPECIES_CLEFABLE); + MULTI_PARTNER(SPECIES_CLEFAIRY) { Moves(move2); } + MULTI_PARTNER(SPECIES_CLEFAIRY); + MULTI_PARTNER(SPECIES_CLEFAIRY); + MULTI_OPPONENT_A(SPECIES_WOBBUFFET) { Moves(move1); } + MULTI_OPPONENT_A(SPECIES_WOBBUFFET); + MULTI_OPPONENT_A(SPECIES_WOBBUFFET); + MULTI_OPPONENT_B(SPECIES_WYNAUT) { Moves(move3); } + MULTI_OPPONENT_B(SPECIES_WYNAUT) { HP(0); } + MULTI_OPPONENT_B(SPECIES_WYNAUT); } WHEN { - TURN { MOVE(user, MOVE_REVIVAL_BLESSING, partyIndex:4); } + TURN { EXPECT_MOVE(playerRight, move2); } // EXPECT_MOVE makes battler2 AI-controlled } SCENE { if (user == opponentLeft) { MESSAGE("The opposing Wobbuffet used Revival Blessing!"); MESSAGE("But it failed!"); + } else if (user == playerRight) { + MESSAGE("Clefairy used Revival Blessing!"); + MESSAGE("But it failed!"); } else { MESSAGE("The opposing Wynaut used Revival Blessing!"); MESSAGE("Wynaut was revived and is ready to fight again!"); diff --git a/test/battle/move_effect/roar.c b/test/battle/move_effect/roar.c index 5b1230f253..5c46e0cdf4 100644 --- a/test/battle/move_effect/roar.c +++ b/test/battle/move_effect/roar.c @@ -20,6 +20,8 @@ SINGLE_BATTLE_TEST("Roar switches the target with a random non-fainted replaceme } SCENE { ANIMATION(ANIM_TYPE_MOVE, MOVE_ROAR, player); MESSAGE("The opposing Bulbasaur was dragged out!"); + } THEN { + EXPECT_EQ(gLastUsedMove, MOVE_ROAR); } } diff --git a/test/battle/move_effect/role_play.c b/test/battle/move_effect/role_play.c index 1a05f02d4a..ebd56bce2c 100644 --- a/test/battle/move_effect/role_play.c +++ b/test/battle/move_effect/role_play.c @@ -50,7 +50,8 @@ DOUBLE_BATTLE_TEST("Role Play copies target's current ability even if it changed SINGLE_BATTLE_TEST("Role Play and Doodle fail if target's ability can't be copied'") { - u32 species, ability; + u32 species; + enum Ability ability; PARAMETRIZE { species = SPECIES_SHEDINJA; ability = ABILITY_WONDER_GUARD; } PARAMETRIZE { species = SPECIES_CASTFORM; ability = ABILITY_FORECAST; } @@ -90,7 +91,8 @@ SINGLE_BATTLE_TEST("Role Play and Doodle fail if target's ability can't be copie SINGLE_BATTLE_TEST("Role Play fails if user's ability can't be suppressed") { - u32 species, ability; + u32 species; + enum Ability ability; PARAMETRIZE { species = SPECIES_ARCEUS; ability = ABILITY_MULTITYPE; } if (B_UPDATED_ABILITY_DATA >= GEN_7) diff --git a/test/battle/move_effect/sheer_cold.c b/test/battle/move_effect/sheer_cold.c index 77ecb55bf7..c0b076f448 100644 --- a/test/battle/move_effect/sheer_cold.c +++ b/test/battle/move_effect/sheer_cold.c @@ -9,7 +9,7 @@ ASSUMPTIONS SINGLE_BATTLE_TEST("Sheer Cold doesn't affect Ice-type Pokémon (Gen3-6)") { GIVEN { - WITH_CONFIG(GEN_CONFIG_SHEER_COLD_IMMUNITY, GEN_6); + WITH_CONFIG(CONFIG_SHEER_COLD_IMMUNITY, GEN_6); ASSUME(GetSpeciesType(SPECIES_GLALIE, 0) == TYPE_ICE); PLAYER(SPECIES_WYNAUT); OPPONENT(SPECIES_GLALIE); @@ -25,7 +25,7 @@ SINGLE_BATTLE_TEST("Sheer Cold doesn't affect Ice-type Pokémon (Gen3-6)") SINGLE_BATTLE_TEST("Sheer Cold doesn't affect Ice-type Pokémon (Gen7+)") { GIVEN { - WITH_CONFIG(GEN_CONFIG_SHEER_COLD_IMMUNITY, GEN_7); + WITH_CONFIG(CONFIG_SHEER_COLD_IMMUNITY, GEN_7); ASSUME(GetSpeciesType(SPECIES_GLALIE, 0) == TYPE_ICE); PLAYER(SPECIES_WYNAUT); OPPONENT(SPECIES_GLALIE); diff --git a/test/battle/move_effect/shift_gear.c b/test/battle/move_effect/shift_gear.c index 990e815cb3..a480eaa949 100644 --- a/test/battle/move_effect/shift_gear.c +++ b/test/battle/move_effect/shift_gear.c @@ -1,4 +1,23 @@ #include "global.h" #include "test/battle.h" -TO_DO_BATTLE_TEST("TODO: Write Shift Gear (Move Effect) test titles") +ASSUMPTIONS +{ + ASSUME(GetMoveEffect(MOVE_SHIFT_GEAR) == EFFECT_SHIFT_GEAR); +} + +SINGLE_BATTLE_TEST("Shift Gear increases the user's Speed by 2 stages and Attack by 1 stage") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_SHIFT_GEAR); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SHIFT_GEAR, player); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); + } THEN { + EXPECT_EQ(player->statStages[STAT_SPEED], DEFAULT_STAT_STAGE + 2); + EXPECT_EQ(player->statStages[STAT_ATK], DEFAULT_STAT_STAGE + 1); + } +} diff --git a/test/battle/move_effect/simple_beam.c b/test/battle/move_effect/simple_beam.c deleted file mode 100644 index 4250c8ce45..0000000000 --- a/test/battle/move_effect/simple_beam.c +++ /dev/null @@ -1,74 +0,0 @@ -#include "global.h" -#include "test/battle.h" - -ASSUMPTIONS -{ - ASSUME(GetMoveEffect(MOVE_SIMPLE_BEAM) == EFFECT_SIMPLE_BEAM); -} - -SINGLE_BATTLE_TEST("Simple Beam replaces target's ability with Simple") -{ - GIVEN { - PLAYER(SPECIES_WOBBUFFET) { Ability(ABILITY_TELEPATHY); } - OPPONENT(SPECIES_CHARMANDER) { Ability(ABILITY_BLAZE); } - }WHEN { - TURN { MOVE(player, MOVE_SIMPLE_BEAM); } - } SCENE { - ANIMATION(ANIM_TYPE_MOVE, MOVE_SIMPLE_BEAM, player); - ABILITY_POPUP(opponent, ABILITY_BLAZE); - } THEN { - EXPECT_EQ(opponent->ability, ABILITY_SIMPLE); - } -} - -DOUBLE_BATTLE_TEST("Simple Beam fails if the target already has Simple") -{ - GIVEN { - PLAYER(SPECIES_WOBBUFFET) { Ability(ABILITY_TELEPATHY); } - PLAYER(SPECIES_CHARMANDER) { Ability(ABILITY_BLAZE); } - OPPONENT(SPECIES_BULBASAUR) { Ability(ABILITY_OVERGROW); } - OPPONENT(SPECIES_SQUIRTLE) { Ability(ABILITY_TORRENT); } - } WHEN { - TURN { MOVE(playerLeft, MOVE_SIMPLE_BEAM, target: opponentLeft); MOVE(playerRight, MOVE_SIMPLE_BEAM, target: opponentLeft); } - } SCENE { - ANIMATION(ANIM_TYPE_MOVE, MOVE_SIMPLE_BEAM, playerLeft); - ABILITY_POPUP(opponentLeft, ABILITY_OVERGROW); - NONE_OF { - ANIMATION(ANIM_TYPE_MOVE, MOVE_SIMPLE_BEAM, playerRight); - ABILITY_POPUP(opponentLeft, ABILITY_SIMPLE); - } - } THEN { - EXPECT_EQ(opponentLeft->ability, ABILITY_SIMPLE); - } -} - -SINGLE_BATTLE_TEST("Simple Beam fails if target has an ability that can't be overwritten") -{ - u32 species, ability; - - PARAMETRIZE { species = SPECIES_ARCEUS; ability = ABILITY_MULTITYPE; } - PARAMETRIZE { species = SPECIES_AEGISLASH; ability = ABILITY_STANCE_CHANGE; } - PARAMETRIZE { species = SPECIES_MINIOR; ability = ABILITY_SHIELDS_DOWN; } - PARAMETRIZE { species = SPECIES_WISHIWASHI; ability = ABILITY_SCHOOLING; } - PARAMETRIZE { species = SPECIES_MIMIKYU; ability = ABILITY_DISGUISE; } - PARAMETRIZE { species = SPECIES_GRENINJA_BATTLE_BOND; ability = ABILITY_BATTLE_BOND; } - PARAMETRIZE { species = SPECIES_ZYGARDE; ability = ABILITY_POWER_CONSTRUCT; } - PARAMETRIZE { species = SPECIES_KOMALA; ability = ABILITY_COMATOSE; } - PARAMETRIZE { species = SPECIES_SILVALLY; ability = ABILITY_RKS_SYSTEM; } - PARAMETRIZE { species = SPECIES_CRAMORANT; ability = ABILITY_GULP_MISSILE; } - PARAMETRIZE { species = SPECIES_EISCUE; ability = ABILITY_ICE_FACE; } - PARAMETRIZE { species = SPECIES_CALYREX_ICE; ability = ABILITY_AS_ONE_ICE_RIDER; } - PARAMETRIZE { species = SPECIES_CALYREX_SHADOW; ability = ABILITY_AS_ONE_SHADOW_RIDER; } - PARAMETRIZE { species = SPECIES_PALAFIN_ZERO; ability = ABILITY_ZERO_TO_HERO; } - PARAMETRIZE { species = SPECIES_TATSUGIRI; ability = ABILITY_COMMANDER; } - - GIVEN { - PLAYER(SPECIES_WOBBUFFET) { Ability(ABILITY_TELEPATHY); } - OPPONENT(species) { Ability(ability); } - } WHEN { - TURN { MOVE(player, MOVE_SIMPLE_BEAM); } - } SCENE { - NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_SIMPLE_BEAM, player); - MESSAGE("But it failed!"); - } -} diff --git a/test/battle/move_effect/sketch.c b/test/battle/move_effect/sketch.c new file mode 100644 index 0000000000..e78aaa93af --- /dev/null +++ b/test/battle/move_effect/sketch.c @@ -0,0 +1,4 @@ +#include "global.h" +#include "test/battle.h" + +TO_DO_BATTLE_TEST("TODO: Write Sketch (Move Effect) test titles") diff --git a/test/battle/move_effect/skill_swap.c b/test/battle/move_effect/skill_swap.c index c3c2ca91f4..59b023f5fa 100644 --- a/test/battle/move_effect/skill_swap.c +++ b/test/battle/move_effect/skill_swap.c @@ -20,7 +20,7 @@ SINGLE_BATTLE_TEST("Skill Swap swaps user and target's abilities") } THEN { EXPECT_EQ(player->ability, ABILITY_BLAZE); EXPECT_EQ(opponent->ability, ABILITY_TELEPATHY); - } + } } DOUBLE_BATTLE_TEST("Skill Swap only swaps user's ability with target's ability") @@ -67,7 +67,8 @@ DOUBLE_BATTLE_TEST("Skill Swap doesn't display ability popups when swapping with SINGLE_BATTLE_TEST("Skill Swap fails if user or target has an ability that can't be swapped") { - u32 species, ability; + u32 species; + enum Ability ability; PARAMETRIZE { species = SPECIES_SHEDINJA; ability = ABILITY_WONDER_GUARD; } PARAMETRIZE { species = SPECIES_ARCEUS; ability = ABILITY_MULTITYPE; } diff --git a/test/battle/move_effect/sleep_talk.c b/test/battle/move_effect/sleep_talk.c index 1f53530c46..ace40150c5 100644 --- a/test/battle/move_effect/sleep_talk.c +++ b/test/battle/move_effect/sleep_talk.c @@ -146,3 +146,42 @@ DOUBLE_BATTLE_TEST("Sleep Talk calls move and that move may be redirected by Sto ABILITY_POPUP(opponentRight, ABILITY_STORM_DRAIN); } } + +SINGLE_BATTLE_TEST("Sleep Talk calls move and that move correctly ignores ability if it should") +{ + u32 species; + enum Ability ability; + + PARAMETRIZE { species = SPECIES_KINGLER; ability = ABILITY_SHELL_ARMOR; } + PARAMETRIZE { species = SPECIES_ARMALDO; ability = ABILITY_BATTLE_ARMOR; } + + GIVEN { + ASSUME(MoveIgnoresTargetAbility(MOVE_SUNSTEEL_STRIKE)); + PLAYER(SPECIES_WOBBUFFET) { Status1(STATUS1_SLEEP); Moves(MOVE_SLEEP_TALK, MOVE_SUNSTEEL_STRIKE); } + OPPONENT(species) { Ability(ability); } + } WHEN { + TURN { MOVE(player, MOVE_SLEEP_TALK, criticalHit: TRUE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SLEEP_TALK, player); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SUNSTEEL_STRIKE, player); + MESSAGE("A critical hit!"); + } +} + +SINGLE_BATTLE_TEST("Sleep Talk deducts power points from itself, not the called move") +{ + ASSUME(GetMovePP(MOVE_SLEEP_TALK) == 10); + ASSUME(GetMovePP(MOVE_POUND) == 35); + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Status1(STATUS1_SLEEP); Moves(MOVE_SLEEP_TALK, MOVE_POUND); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_SLEEP_TALK); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SLEEP_TALK, player); + ANIMATION(ANIM_TYPE_MOVE, MOVE_POUND, player); + } THEN { + EXPECT_EQ(player->pp[0], 9); + EXPECT_EQ(player->pp[1], 35); + } +} diff --git a/test/battle/move_effect/snatch.c b/test/battle/move_effect/snatch.c index f8e2891837..42fb79b2a0 100644 --- a/test/battle/move_effect/snatch.c +++ b/test/battle/move_effect/snatch.c @@ -1,4 +1,64 @@ #include "global.h" #include "test/battle.h" -TO_DO_BATTLE_TEST("TODO: Write Snatch (Move Effect) test titles") +ASSUMPTIONS +{ + ASSUME(GetMoveEffect(MOVE_SNATCH) == EFFECT_SNATCH); + ASSUME(MoveCanBeSnatched(MOVE_SWORDS_DANCE)); +} + +SINGLE_BATTLE_TEST("Snatch steals stat-boosting moves from the opponent") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Speed(10); } + OPPONENT(SPECIES_WYNAUT) { Speed(5); } + } WHEN { + TURN { MOVE(player, MOVE_SNATCH); MOVE(opponent, MOVE_SWORDS_DANCE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SNATCH, player); + NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_SWORDS_DANCE, opponent); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SWORDS_DANCE, player); + } THEN { + EXPECT_EQ(player->statStages[STAT_ATK], DEFAULT_STAT_STAGE + 2); + EXPECT_EQ(opponent->statStages[STAT_ATK], DEFAULT_STAT_STAGE); + } +} + +SINGLE_BATTLE_TEST("Snatch fails if user moves last") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Speed(5); } + OPPONENT(SPECIES_WYNAUT) { Speed(10); } + } WHEN { + TURN { MOVE(opponent, MOVE_CELEBRATE); MOVE(player, MOVE_SNATCH); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponent); + NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_SNATCH, player); + } +} + +DOUBLE_BATTLE_TEST("Snatch fails when the only slower battler is a fainted ally") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Speed(5); } + PLAYER(SPECIES_WYNAUT) { HP(1); Speed(1); } + OPPONENT(SPECIES_WOBBUFFET) { Speed(20); } + OPPONENT(SPECIES_WYNAUT) { Speed(10); } + } WHEN { + TURN { MOVE(opponentLeft, MOVE_SCRATCH, target: playerRight); } + TURN { + MOVE(opponentLeft, MOVE_CELEBRATE); + MOVE(opponentRight, MOVE_CELEBRATE); + MOVE(playerLeft, MOVE_SNATCH); + } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SCRATCH, opponentLeft); + MESSAGE("Wynaut fainted!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponentLeft); + ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponentRight); + NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_SNATCH, playerLeft); + } +} + +TO_DO_BATTLE_TEST("Snatch does not steal moves that cannot be snatched"); +TO_DO_BATTLE_TEST("Snatch can steal healing moves"); diff --git a/test/battle/move_effect/solar_beam.c b/test/battle/move_effect/solar_beam.c index 309d950c50..6113b5c4ac 100644 --- a/test/battle/move_effect/solar_beam.c +++ b/test/battle/move_effect/solar_beam.c @@ -9,7 +9,7 @@ ASSUMPTIONS SINGLE_BATTLE_TEST("Solar Beam does not need a charging turn if Sun is up") { - u32 ability; + enum Ability ability; PARAMETRIZE { ability = ABILITY_DROUGHT; } PARAMETRIZE { ability = ABILITY_WHITE_SMOKE; } diff --git a/test/battle/move_effect/special_attack_down_2.c b/test/battle/move_effect/special_attack_down_2.c index b62d4b52ac..7ea5204431 100644 --- a/test/battle/move_effect/special_attack_down_2.c +++ b/test/battle/move_effect/special_attack_down_2.c @@ -1,4 +1,22 @@ #include "global.h" #include "test/battle.h" -TO_DO_BATTLE_TEST("TODO: Write Eerie Impulse (Move Effect) test titles") +ASSUMPTIONS +{ + ASSUME(GetMoveEffect(MOVE_EERIE_IMPULSE) == EFFECT_SPECIAL_ATTACK_DOWN_2); +} + +SINGLE_BATTLE_TEST("Eerie Impulse reduces the target's Sp. Attack by 2 stages") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_EERIE_IMPULSE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_EERIE_IMPULSE, player); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); + } THEN { + EXPECT_EQ(opponent->statStages[STAT_SPATK], DEFAULT_STAT_STAGE - 2); + } +} diff --git a/test/battle/move_effect/special_attack_up_2.c b/test/battle/move_effect/special_attack_up_2.c index c4bf38d6aa..c87b3fea0b 100644 --- a/test/battle/move_effect/special_attack_up_2.c +++ b/test/battle/move_effect/special_attack_up_2.c @@ -1,4 +1,22 @@ #include "global.h" #include "test/battle.h" -TO_DO_BATTLE_TEST("TODO: Write Nasty Plot (Move Effect) test titles") +ASSUMPTIONS +{ + ASSUME(GetMoveEffect(MOVE_NASTY_PLOT) == EFFECT_SPECIAL_ATTACK_UP_2); +} + +SINGLE_BATTLE_TEST("Nasty Plot increases the user's Sp. Attack by 2 stages") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_NASTY_PLOT); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_NASTY_PLOT, player); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); + } THEN { + EXPECT_EQ(player->statStages[STAT_SPATK], DEFAULT_STAT_STAGE + 2); + } +} diff --git a/test/battle/move_effect/special_defense_down_2.c b/test/battle/move_effect/special_defense_down_2.c index 5fff5bdd7b..4740d3e5e2 100644 --- a/test/battle/move_effect/special_defense_down_2.c +++ b/test/battle/move_effect/special_defense_down_2.c @@ -1,4 +1,22 @@ #include "global.h" #include "test/battle.h" -TO_DO_BATTLE_TEST("TODO: Write Fake Tears/Metal Sound (Move Effect) test titles") +ASSUMPTIONS +{ + ASSUME(GetMoveEffect(MOVE_FAKE_TEARS) == EFFECT_SPECIAL_DEFENSE_DOWN_2); +} + +SINGLE_BATTLE_TEST("Fake Tears reduces the target's Sp. Defense by 2 stages") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_FAKE_TEARS); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_FAKE_TEARS, player); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); + } THEN { + EXPECT_EQ(opponent->statStages[STAT_SPDEF], DEFAULT_STAT_STAGE - 2); + } +} diff --git a/test/battle/move_effect/special_defense_up_2.c b/test/battle/move_effect/special_defense_up_2.c index 1685663452..9da91d8d07 100644 --- a/test/battle/move_effect/special_defense_up_2.c +++ b/test/battle/move_effect/special_defense_up_2.c @@ -1,4 +1,22 @@ #include "global.h" #include "test/battle.h" -TO_DO_BATTLE_TEST("TODO: Write Amnesia (Move Effect) test titles") +ASSUMPTIONS +{ + ASSUME(GetMoveEffect(MOVE_AMNESIA) == EFFECT_SPECIAL_DEFENSE_UP_2); +} + +SINGLE_BATTLE_TEST("Amnesia increases the user's Sp. Defense by 2 stages") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_AMNESIA); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_AMNESIA, player); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); + } THEN { + EXPECT_EQ(player->statStages[STAT_SPDEF], DEFAULT_STAT_STAGE + 2); + } +} diff --git a/test/battle/move_effect/speed_down.c b/test/battle/move_effect/speed_down.c index a3b5e26be8..88d62f2f38 100644 --- a/test/battle/move_effect/speed_down.c +++ b/test/battle/move_effect/speed_down.c @@ -3,13 +3,14 @@ DOUBLE_BATTLE_TEST("Speed Down: Cotton Spore does not fail if it is blocked by one target") { - u32 abilityOne, abilityTwo; + enum Ability abilityOne, abilityTwo; PARAMETRIZE { abilityOne = ABILITY_OVERCOAT; abilityTwo = ABILITY_SKILL_LINK; } PARAMETRIZE { abilityOne = ABILITY_SKILL_LINK; abilityTwo = ABILITY_OVERCOAT; } GIVEN { ASSUME(GetMoveEffect(MOVE_COTTON_SPORE) == EFFECT_SPEED_DOWN_2); + ASSUME(GetMoveTarget(MOVE_COTTON_SPORE) == MOVE_TARGET_BOTH); PLAYER(SPECIES_WOBBUFFET); PLAYER(SPECIES_WOBBUFFET); OPPONENT(SPECIES_SHELLDER) { Ability(abilityOne); } diff --git a/test/battle/move_effect/speed_down_2.c b/test/battle/move_effect/speed_down_2.c index e3b95e3fe9..2b350b6252 100644 --- a/test/battle/move_effect/speed_down_2.c +++ b/test/battle/move_effect/speed_down_2.c @@ -1,4 +1,22 @@ #include "global.h" #include "test/battle.h" -TO_DO_BATTLE_TEST("TODO: Write Scary Face/Cotton Spore (Move Effect) test titles") +ASSUMPTIONS +{ + ASSUME(GetMoveEffect(MOVE_SCARY_FACE) == EFFECT_SPEED_DOWN_2); +} + +SINGLE_BATTLE_TEST("Scary Face reduces the target's Speed by 2 stages") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_SCARY_FACE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SCARY_FACE, player); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); + } THEN { + EXPECT_EQ(opponent->statStages[STAT_SPEED], DEFAULT_STAT_STAGE - 2); + } +} diff --git a/test/battle/move_effect/speed_swap.c b/test/battle/move_effect/speed_swap.c index b5f9aaebaf..3405d510ca 100644 --- a/test/battle/move_effect/speed_swap.c +++ b/test/battle/move_effect/speed_swap.c @@ -24,12 +24,13 @@ SINGLE_BATTLE_TEST("Speed Swap swaps user and target's speed stats") } THEN { EXPECT_EQ(player->speed, 10); EXPECT_EQ(opponent->speed, 6); - } + } } SINGLE_BATTLE_TEST("Speed Swap doesn't swap user and target's speed modifiers") { - u32 species, ability, move; + u32 species, move; + enum Ability ability; PARAMETRIZE { species = SPECIES_WOBBUFFET; ability = ABILITY_TELEPATHY; move = MOVE_ROCK_POLISH; } // x2.0 PARAMETRIZE { species = SPECIES_PSYDUCK; ability = ABILITY_SWIFT_SWIM; move = MOVE_RAIN_DANCE; } // x2.0 GIVEN { @@ -54,5 +55,5 @@ SINGLE_BATTLE_TEST("Speed Swap doesn't swap user and target's speed modifiers") EXPECT_EQ(player->statStages[STAT_SPEED], DEFAULT_STAT_STAGE); EXPECT_EQ(opponent->statStages[STAT_SPEED], DEFAULT_STAT_STAGE + 2); } - } + } } diff --git a/test/battle/move_effect/speed_up_2.c b/test/battle/move_effect/speed_up_2.c index 7202555498..bba7fb88b1 100644 --- a/test/battle/move_effect/speed_up_2.c +++ b/test/battle/move_effect/speed_up_2.c @@ -1,4 +1,22 @@ #include "global.h" #include "test/battle.h" -TO_DO_BATTLE_TEST("TODO: Write Agility/Rock Polish (Move Effect) test titles") +ASSUMPTIONS +{ + ASSUME(GetMoveEffect(MOVE_AGILITY) == EFFECT_SPEED_UP_2); +} + +SINGLE_BATTLE_TEST("Agility increases the user's Speed by 2 stages") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_AGILITY); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_AGILITY, player); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); + } THEN { + EXPECT_EQ(player->statStages[STAT_SPEED], DEFAULT_STAT_STAGE + 2); + } +} diff --git a/test/battle/move_effect/spicy_extract.c b/test/battle/move_effect/spicy_extract.c index 7cf9eacb32..6dc2a77427 100644 --- a/test/battle/move_effect/spicy_extract.c +++ b/test/battle/move_effect/spicy_extract.c @@ -27,7 +27,7 @@ SINGLE_BATTLE_TEST("Spicy Extract raises target's Attack by 2 stages and lowers SINGLE_BATTLE_TEST("Spicy Extract is prevented by target's ability if it's Attack stat is maxed out") { - u16 ability; + enum Ability ability; PARAMETRIZE { ability = ABILITY_CLEAR_BODY; } PARAMETRIZE { ability = ABILITY_LIGHT_METAL; } @@ -189,7 +189,7 @@ AI_DOUBLE_BATTLE_TEST("Spicy Extract user will use it if partner holds Clear Amu AI_DOUBLE_BATTLE_TEST("Spicy Extract user will not choose the move if it does not benefit partner") { u32 species; - u32 ability; + enum Ability ability; PARAMETRIZE { species = SPECIES_GHOLDENGO; ability = ABILITY_GOOD_AS_GOLD; } PARAMETRIZE { species = SPECIES_SNIVY; ability = ABILITY_CONTRARY; } diff --git a/test/battle/move_effect_secondary/steal_item.c b/test/battle/move_effect/steal_item.c similarity index 85% rename from test/battle/move_effect_secondary/steal_item.c rename to test/battle/move_effect/steal_item.c index 79c293757f..1259cf4599 100644 --- a/test/battle/move_effect_secondary/steal_item.c +++ b/test/battle/move_effect/steal_item.c @@ -113,7 +113,7 @@ WILD_BATTLE_TEST("Thief and Covet steal target's held item and it's added to Bag PARAMETRIZE { move = MOVE_THIEF; } PARAMETRIZE { move = MOVE_COVET; } GIVEN { - WITH_CONFIG(GEN_STEAL_WILD_ITEMS, GEN_9); + WITH_CONFIG(CONFIG_STEAL_WILD_ITEMS, GEN_9); PLAYER(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_HYPER_POTION); } } WHEN { @@ -148,11 +148,12 @@ SINGLE_BATTLE_TEST("Thief and Covet can't steal target's held item if user faint } } -SINGLE_BATTLE_TEST("Thief and Covet: Berry activation happens before the item can be stolen") +SINGLE_BATTLE_TEST("Thief and Covet: Berries that activate on HP thresholds are stolen before they can activate") { u32 move; PARAMETRIZE { move = MOVE_THIEF; } PARAMETRIZE { move = MOVE_COVET; } + GIVEN { PLAYER(SPECIES_WYNAUT); OPPONENT(SPECIES_WOBBUFFET) { MaxHP(200); HP(101); Item(ITEM_ORAN_BERRY); } @@ -161,6 +162,25 @@ SINGLE_BATTLE_TEST("Thief and Covet: Berry activation happens before the item ca } SCENE { ANIMATION(ANIM_TYPE_MOVE, move, player); HP_BAR(opponent); + NOT ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, opponent); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_ITEM_STEAL, opponent); + } +} + +SINGLE_BATTLE_TEST("Thief and Covet: Berries that activate on a Status activate before the item can be stolen") +{ + u32 move; + PARAMETRIZE { move = MOVE_THIEF; } + PARAMETRIZE { move = MOVE_COVET; } + + GIVEN { + PLAYER(SPECIES_TOXICROAK) { Ability(ABILITY_POISON_TOUCH); } + OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_LUM_BERRY); } + } WHEN { + TURN { MOVE(player, move); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, move, player); + ABILITY_POPUP(player, ABILITY_POISON_TOUCH); ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, opponent); NOT ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_ITEM_STEAL, opponent); } diff --git a/test/battle/move_effect/stockpile.c b/test/battle/move_effect/stockpile.c index 907643a1bd..e18c97fc57 100644 --- a/test/battle/move_effect/stockpile.c +++ b/test/battle/move_effect/stockpile.c @@ -30,7 +30,7 @@ SINGLE_BATTLE_TEST("Stockpile's count can go up only to 3") MESSAGE("Wobbuffet stockpiled 3!"); NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_STOCKPILE, player); - MESSAGE("Wobbuffet can't stockpile any more!"); + MESSAGE("But it failed!"); } } @@ -49,9 +49,9 @@ SINGLE_BATTLE_TEST("Spit Up and Swallow don't work if used without Stockpile") } SCENE { NOT ANIMATION(ANIM_TYPE_MOVE, move, player); if (move == MOVE_SWALLOW) - MESSAGE("But it failed to swallow a thing!"); + MESSAGE("But it failed!"); else - MESSAGE("But it failed to spit up a thing!"); + MESSAGE("But it failed!"); ANIMATION(ANIM_TYPE_MOVE, MOVE_STOCKPILE, player); MESSAGE("Wobbuffet stockpiled 1!"); diff --git a/test/battle/move_effect/substitute.c b/test/battle/move_effect/substitute.c index e94767b660..ce174ec025 100644 --- a/test/battle/move_effect/substitute.c +++ b/test/battle/move_effect/substitute.c @@ -69,4 +69,111 @@ SINGLE_BATTLE_TEST("Substitute's HP cost doesn't trigger effects that trigger on } } +SINGLE_BATTLE_TEST("Substitute hits are detected by SUB_HIT") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_SUBSTITUTE); MOVE(opponent, MOVE_SCRATCH); } + } SCENE { + SUB_HIT(player); + } +} + +SINGLE_BATTLE_TEST("Substitute hits are detected by SUB_HIT, break TRUE") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Level(1); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_SUBSTITUTE); MOVE(opponent, MOVE_SCRATCH); } + } SCENE { + SUB_HIT(player, subBreak: TRUE); + } +} + +SINGLE_BATTLE_TEST("Substitute hits are detected by SUB_HIT, break FALSE") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Level(100); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_SUBSTITUTE); MOVE(opponent, MOVE_SCRATCH); } + } SCENE { + SUB_HIT(player, subBreak: FALSE); + } +} + +SINGLE_BATTLE_TEST("Substitute hits are detected by SUB_HIT, records damage") +{ + u16 damage; + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_SUBSTITUTE); MOVE(opponent, MOVE_SCRATCH); } + } SCENE { + SUB_HIT(player, captureDamage: &damage); + } THEN { + EXPECT_GT(damage, 0); + } +} + +SINGLE_BATTLE_TEST("Substitute hits are detected by SUB_HIT, records damage, break FALSE") +{ + u16 damage; + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_SUBSTITUTE); MOVE(opponent, MOVE_SCRATCH); } + } SCENE { + SUB_HIT(player, captureDamage: &damage, subBreak: FALSE); + } THEN { + EXPECT_GT(damage, 0); + } +} + +SINGLE_BATTLE_TEST("Substitute hits are detected by SUB_HIT, records damage, break TRUE") +{ + u16 damage; + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Level(1); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_SUBSTITUTE); MOVE(opponent, MOVE_SCRATCH); } + } SCENE { + SUB_HIT(player, captureDamage: &damage, subBreak: TRUE); + } THEN { + EXPECT_GT(damage, 0); + } +} + +SINGLE_BATTLE_TEST("Substitute hits are detected by SUB_HIT, break TRUE, failing") +{ + KNOWN_FAILING; // For testing purposes + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Level(100); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_SUBSTITUTE); MOVE(opponent, MOVE_SCRATCH); } + } SCENE { + SUB_HIT(player, subBreak: TRUE); + } +} + +SINGLE_BATTLE_TEST("Substitute hits are detected by SUB_HIT, break FALSE, failing") +{ + KNOWN_FAILING; // For testing purposes + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Level(1); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_SUBSTITUTE); MOVE(opponent, MOVE_SCRATCH); } + } SCENE { + SUB_HIT(player, subBreak: FALSE); + } +} + TO_DO_BATTLE_TEST("Baton Pass passes Substitutes"); diff --git a/test/battle/move_effect/super_fang.c b/test/battle/move_effect/super_fang.c deleted file mode 100644 index 33e162395d..0000000000 --- a/test/battle/move_effect/super_fang.c +++ /dev/null @@ -1,4 +0,0 @@ -#include "global.h" -#include "test/battle.h" - -TO_DO_BATTLE_TEST("TODO: Write Super Fang (Move Effect) test titles") diff --git a/test/battle/move_effect/swagger.c b/test/battle/move_effect/swagger.c index 3217e48903..fad4a39c5c 100644 --- a/test/battle/move_effect/swagger.c +++ b/test/battle/move_effect/swagger.c @@ -1,7 +1,27 @@ #include "global.h" #include "test/battle.h" -TO_DO_BATTLE_TEST("Swagger raises the target's Attack and confuses them") +ASSUMPTIONS +{ + ASSUME(GetMoveEffect(MOVE_SWAGGER) == EFFECT_SWAGGER); +} + +SINGLE_BATTLE_TEST("Swagger increases the target's Attack by 2 stages and confuses them") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_SWAGGER); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SWAGGER, player); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); + } THEN { + EXPECT_EQ(opponent->statStages[STAT_ATK], DEFAULT_STAT_STAGE + 2); + EXPECT(opponent->volatiles.confusionTurns > 0); + } +} + TO_DO_BATTLE_TEST("Swagger raises the target's Attack even if they're already confused") TO_DO_BATTLE_TEST("Swagger raises the target's Attack even when protected by Safeguard") TO_DO_BATTLE_TEST("Swagger raises the target's Attack even when protected Own Tempo") diff --git a/test/battle/move_effect/synthesis.c b/test/battle/move_effect/synthesis.c index 7afbb7f87d..a33b586927 100644 --- a/test/battle/move_effect/synthesis.c +++ b/test/battle/move_effect/synthesis.c @@ -9,7 +9,7 @@ ASSUMPTIONS SINGLE_BATTLE_TEST("Synthesis recovers 1/2 of the user's max HP (Gen3+)") { GIVEN { - WITH_CONFIG(GEN_CONFIG_TIME_OF_DAY_HEALING_MOVES, GEN_3); + WITH_CONFIG(CONFIG_TIME_OF_DAY_HEALING_MOVES, GEN_3); PLAYER(SPECIES_WOBBUFFET) { HP(1); MaxHP(200); } OPPONENT(SPECIES_WOBBUFFET); } WHEN { @@ -22,7 +22,7 @@ SINGLE_BATTLE_TEST("Synthesis recovers 1/2 of the user's max HP (Gen3+)") SINGLE_BATTLE_TEST("Synthesis recovers 2/3 of the user's max HP in Sunlight (Gen3+)") { GIVEN { - WITH_CONFIG(GEN_CONFIG_TIME_OF_DAY_HEALING_MOVES, GEN_3); + WITH_CONFIG(CONFIG_TIME_OF_DAY_HEALING_MOVES, GEN_3); PLAYER(SPECIES_WOBBUFFET) { HP(1); MaxHP(300); } OPPONENT(SPECIES_WOBBUFFET); } WHEN { @@ -40,7 +40,7 @@ SINGLE_BATTLE_TEST("Synthesis recovers 1/4 of the user's max HP in Rain, Sandsto PARAMETRIZE { move = MOVE_HAIL; } PARAMETRIZE { move = MOVE_SNOWSCAPE; } GIVEN { - WITH_CONFIG(GEN_CONFIG_TIME_OF_DAY_HEALING_MOVES, GEN_3); + WITH_CONFIG(CONFIG_TIME_OF_DAY_HEALING_MOVES, GEN_3); PLAYER(SPECIES_WOBBUFFET) { HP(1); MaxHP(400); } OPPONENT(SPECIES_WOBBUFFET); } WHEN { diff --git a/test/battle/move_effect/tailwind.c b/test/battle/move_effect/tailwind.c index 7968bc25ef..9ed101301d 100644 --- a/test/battle/move_effect/tailwind.c +++ b/test/battle/move_effect/tailwind.c @@ -39,7 +39,7 @@ SINGLE_BATTLE_TEST("Tailwind applies for 4 turns") DOUBLE_BATTLE_TEST("Tailwind doesn't affect the partner on the same turn it's used (Gen4-7)") { GIVEN { - WITH_CONFIG(GEN_CONFIG_RECALC_TURN_AFTER_ACTIONS, GEN_7); + WITH_CONFIG(CONFIG_RECALC_TURN_AFTER_ACTIONS, GEN_7); PLAYER(SPECIES_WOBBUFFET) { Speed(20); } PLAYER(SPECIES_WYNAUT) { Speed(10); } OPPONENT(SPECIES_WOBBUFFET) { Speed(15); } @@ -57,7 +57,7 @@ DOUBLE_BATTLE_TEST("Tailwind doesn't affect the partner on the same turn it's us DOUBLE_BATTLE_TEST("Tailwind affects the partner on the same turn it's used (Gen8+)") { GIVEN { - WITH_CONFIG(GEN_CONFIG_RECALC_TURN_AFTER_ACTIONS, GEN_8); + WITH_CONFIG(CONFIG_RECALC_TURN_AFTER_ACTIONS, GEN_8); PLAYER(SPECIES_WOBBUFFET) { Speed(20); } PLAYER(SPECIES_WYNAUT) { Speed(10); } OPPONENT(SPECIES_WOBBUFFET) { Speed(15); } diff --git a/test/battle/move_effect/teleport.c b/test/battle/move_effect/teleport.c index 83d2142e67..c3b5b53519 100644 --- a/test/battle/move_effect/teleport.c +++ b/test/battle/move_effect/teleport.c @@ -9,7 +9,7 @@ ASSUMPTIONS SINGLE_BATTLE_TEST("Teleport fails to switch out when there is no Pokémon to switch in (Gen 8+)") { GIVEN { - WITH_CONFIG(GEN_CONFIG_TELEPORT_BEHAVIOR, GEN_8); + WITH_CONFIG(CONFIG_TELEPORT_BEHAVIOR, GEN_8); PLAYER(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WOBBUFFET); } WHEN { @@ -22,7 +22,7 @@ SINGLE_BATTLE_TEST("Teleport fails to switch out when there is no Pokémon to sw SINGLE_BATTLE_TEST("Teleport fails to switch out the user when there no alive Pokémon left (Gen 8+)") { GIVEN { - WITH_CONFIG(GEN_CONFIG_TELEPORT_BEHAVIOR, GEN_8); + WITH_CONFIG(CONFIG_TELEPORT_BEHAVIOR, GEN_8); PLAYER(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WYNAUT) { HP(0); } @@ -36,7 +36,7 @@ SINGLE_BATTLE_TEST("Teleport fails to switch out the user when there no alive Po SINGLE_BATTLE_TEST("Teleport fails in Trainer Battles (Gen 1-7)") { GIVEN { - WITH_CONFIG(GEN_CONFIG_TELEPORT_BEHAVIOR, GEN_7); + WITH_CONFIG(CONFIG_TELEPORT_BEHAVIOR, GEN_7); PLAYER(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WYNAUT); @@ -55,7 +55,7 @@ SINGLE_BATTLE_TEST("Teleport fails in Trainer Battles (Gen 1-7)") SINGLE_BATTLE_TEST("Teleport forces the Pokémon to switch out in Trainer Battles (Gen 8+)") { GIVEN { - WITH_CONFIG(GEN_CONFIG_TELEPORT_BEHAVIOR, GEN_8); + WITH_CONFIG(CONFIG_TELEPORT_BEHAVIOR, GEN_8); PLAYER(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WYNAUT); @@ -70,7 +70,7 @@ SINGLE_BATTLE_TEST("Teleport forces the Pokémon to switch out in Trainer Battle SINGLE_BATTLE_TEST("Teleport does not fail if the user is trapped") { GIVEN { - WITH_CONFIG(GEN_CONFIG_TELEPORT_BEHAVIOR, GEN_8); + WITH_CONFIG(CONFIG_TELEPORT_BEHAVIOR, GEN_8); PLAYER(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WYNAUT); diff --git a/test/battle/move_effect/tera_blast.c b/test/battle/move_effect/tera_blast.c index 060e28802d..1e041dda97 100644 --- a/test/battle/move_effect/tera_blast.c +++ b/test/battle/move_effect/tera_blast.c @@ -24,7 +24,7 @@ SINGLE_BATTLE_TEST("Tera Blast changes from Normal-type to the user's Tera Type" SINGLE_BATTLE_TEST("Tera Blast has correct effectiveness for every Tera Type") { u32 species; - u32 type; + enum Type type; PARAMETRIZE { species = SPECIES_CHIKORITA; type = TYPE_FLYING; } PARAMETRIZE { species = SPECIES_CHIKORITA; type = TYPE_POISON; } diff --git a/test/battle/move_effect/tickle.c b/test/battle/move_effect/tickle.c index b5f5a56d69..3a878868fd 100644 --- a/test/battle/move_effect/tickle.c +++ b/test/battle/move_effect/tickle.c @@ -1,4 +1,23 @@ #include "global.h" #include "test/battle.h" -TO_DO_BATTLE_TEST("TODO: Write Tickle (Move Effect) test titles") +ASSUMPTIONS +{ + ASSUME(GetMoveEffect(MOVE_TICKLE) == EFFECT_TICKLE); +} + +SINGLE_BATTLE_TEST("Tickle reduces the target's Attack and Defense by 1 stage each") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_TICKLE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_TICKLE, player); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); + } THEN { + EXPECT_EQ(opponent->statStages[STAT_ATK], DEFAULT_STAT_STAGE - 1); + EXPECT_EQ(opponent->statStages[STAT_DEF], DEFAULT_STAT_STAGE - 1); + } +} diff --git a/test/battle/move_effect/toxic.c b/test/battle/move_effect/toxic.c index a8134f9c66..55e09b24eb 100644 --- a/test/battle/move_effect/toxic.c +++ b/test/battle/move_effect/toxic.c @@ -52,7 +52,7 @@ SINGLE_BATTLE_TEST("Toxic cannot miss if used by a Poison-type (Gen6+)") PARAMETRIZE { species = SPECIES_WOBBUFFET; hit = FALSE; gen = GEN_6; } PARAMETRIZE { species = SPECIES_NIDORAN_M; hit = TRUE; gen = GEN_6; } GIVEN { - WITH_CONFIG(GEN_CONFIG_TOXIC_NEVER_MISS, gen); + WITH_CONFIG(CONFIG_TOXIC_NEVER_MISS, gen); ASSUME(GetSpeciesType(SPECIES_NIDORAN_M, 0) == TYPE_POISON); PLAYER(species); OPPONENT(SPECIES_WOBBUFFET); @@ -75,7 +75,8 @@ SINGLE_BATTLE_TEST("Toxic cannot miss if used by a Poison-type (Gen6+)") AI_SINGLE_BATTLE_TEST("AI avoids toxic when it can not poison target") { - u32 species, ability; + u32 species; + enum Ability ability; PARAMETRIZE { species = SPECIES_SNORLAX; ability = ABILITY_IMMUNITY; } PARAMETRIZE { species = SPECIES_KOMALA; ability = ABILITY_COMATOSE; } diff --git a/test/battle/move_effect/trick.c b/test/battle/move_effect/trick.c index 3aa26af67a..b7a75cd188 100644 --- a/test/battle/move_effect/trick.c +++ b/test/battle/move_effect/trick.c @@ -1,4 +1,185 @@ #include "global.h" #include "test/battle.h" +#include "mail.h" -TO_DO_BATTLE_TEST("TODO: Write Trick (Move Effect) test titles") +SINGLE_BATTLE_TEST("Trick swaps held items") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_SITRUS_BERRY); } + OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_LUM_BERRY); } + } WHEN { + TURN { MOVE(player, MOVE_TRICK); } + } THEN { + EXPECT(player->item == ITEM_LUM_BERRY); + EXPECT(opponent->item == ITEM_SITRUS_BERRY); + } +} + +SINGLE_BATTLE_TEST("Trick succeeds if only the user has an item") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_SITRUS_BERRY); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_TRICK); } + } THEN { + EXPECT(player->item == ITEM_NONE); + EXPECT(opponent->item == ITEM_SITRUS_BERRY); + } +} + +SINGLE_BATTLE_TEST("Trick succeeds if only the target has an item") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_LUM_BERRY); } + } WHEN { + TURN { MOVE(player, MOVE_TRICK); } + } THEN { + EXPECT(player->item == ITEM_LUM_BERRY); + EXPECT(opponent->item == ITEM_NONE); + } +} + +SINGLE_BATTLE_TEST("Trick fails if both battlers have no held item") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_TRICK); } + } SCENE { + MESSAGE("But it failed!"); + } THEN { + EXPECT(player->item == ITEM_NONE); + EXPECT(opponent->item == ITEM_NONE); + } +} + +SINGLE_BATTLE_TEST("Trick fails if either item is Mail") +{ + u16 atkItem = ITEM_NONE, defItem = ITEM_NONE; + + ASSUME(ItemIsMail(ITEM_ORANGE_MAIL)); + PARAMETRIZE { atkItem = ITEM_ORANGE_MAIL; defItem = ITEM_NONE; } + PARAMETRIZE { atkItem = ITEM_ORAN_BERRY; defItem = ITEM_ORANGE_MAIL; } + + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Item(atkItem); } + OPPONENT(SPECIES_WOBBUFFET) { Item(defItem); } + } WHEN { + TURN { MOVE(player, MOVE_TRICK); } + } SCENE { + MESSAGE("But it failed!"); + } THEN { + EXPECT(player->item == atkItem); + EXPECT(opponent->item == defItem); + } +} + +SINGLE_BATTLE_TEST("Trick fails if either item is a Z-Crystal") +{ + u16 atkItem = ITEM_NONE, defItem = ITEM_NONE; + + ASSUME(GetItemHoldEffect(ITEM_FIGHTINIUM_Z) == HOLD_EFFECT_Z_CRYSTAL); + PARAMETRIZE { atkItem = ITEM_FIGHTINIUM_Z; defItem = ITEM_NONE; } + PARAMETRIZE { atkItem = ITEM_SITRUS_BERRY; defItem = ITEM_FIGHTINIUM_Z; } + + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Item(atkItem); } + OPPONENT(SPECIES_WOBBUFFET) { Item(defItem); } + } WHEN { + TURN { MOVE(player, MOVE_TRICK); } + } SCENE { + MESSAGE("But it failed!"); + } THEN { + EXPECT(player->item == atkItem); + EXPECT(opponent->item == defItem); + } +} + +SINGLE_BATTLE_TEST("Trick fails if either battler holds a Mega Stone") +{ + u16 atkItem = ITEM_NONE, defItem = ITEM_NONE; + u16 atkSpecies = SPECIES_WOBBUFFET, defSpecies = SPECIES_WOBBUFFET; + + PARAMETRIZE { atkSpecies = SPECIES_BLAZIKEN; atkItem = ITEM_BLAZIKENITE; defSpecies = SPECIES_WOBBUFFET; defItem = ITEM_SITRUS_BERRY; } + PARAMETRIZE { atkSpecies = SPECIES_WOBBUFFET; atkItem = ITEM_SITRUS_BERRY; defSpecies = SPECIES_BLAZIKEN; defItem = ITEM_BLAZIKENITE; } + + GIVEN { + PLAYER(atkSpecies) { Item(atkItem); } + OPPONENT(defSpecies) { Item(defItem); } + } WHEN { + TURN { MOVE(player, MOVE_TRICK); } + } SCENE { + MESSAGE("But it failed!"); + } THEN { + EXPECT(player->item == atkItem); + EXPECT(opponent->item == defItem); + } +} + +SINGLE_BATTLE_TEST("Trick fails if an item changes the holder's form") +{ + u16 atkItem = ITEM_NONE, defItem = ITEM_NONE; + + PARAMETRIZE { atkItem = ITEM_GRISEOUS_CORE; defItem = ITEM_SITRUS_BERRY; } + PARAMETRIZE { atkItem = ITEM_SITRUS_BERRY; defItem = ITEM_GRISEOUS_CORE; } + + GIVEN { + PLAYER(SPECIES_GIRATINA_ORIGIN) { Item(atkItem); } + OPPONENT(SPECIES_WOBBUFFET) { Item(defItem); } + } WHEN { + TURN { MOVE(player, MOVE_TRICK); } + } SCENE { + MESSAGE("But it failed!"); + } THEN { + EXPECT(player->item == atkItem); + EXPECT(opponent->item == defItem); + } +} + +SINGLE_BATTLE_TEST("Trick fails if the user has Sticky Hold") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Ability(ABILITY_STICKY_HOLD); Item(ITEM_SITRUS_BERRY); } + OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_LUM_BERRY); } + } WHEN { + TURN { MOVE(player, MOVE_TRICK); } + } SCENE { + MESSAGE("But it failed!"); + } THEN { + EXPECT(player->item == ITEM_SITRUS_BERRY); + EXPECT(opponent->item == ITEM_LUM_BERRY); + } +} + +SINGLE_BATTLE_TEST("Trick fails against Sticky Hold") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_SITRUS_BERRY); } + OPPONENT(SPECIES_WOBBUFFET) { Ability(ABILITY_STICKY_HOLD); Item(ITEM_LUM_BERRY); } + } WHEN { + TURN { MOVE(player, MOVE_TRICK); } + } SCENE { + MESSAGE("The opposing Wobbuffet's Sticky Hold made Trick ineffective!"); + } THEN { + EXPECT(player->item == ITEM_SITRUS_BERRY); + EXPECT(opponent->item == ITEM_LUM_BERRY); + } +} + +SINGLE_BATTLE_TEST("Trick fails if the target is behind a Substitute") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_SITRUS_BERRY); Speed(50); } + OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_LUM_BERRY); Speed(100); } + } WHEN { + TURN { MOVE(opponent, MOVE_SUBSTITUTE); MOVE(player, MOVE_TRICK); } + } SCENE { + MESSAGE("But it failed!"); + } THEN { + EXPECT(player->item == ITEM_SITRUS_BERRY); + EXPECT(opponent->item == ITEM_LUM_BERRY); + } +} diff --git a/test/battle/move_effect/upper_hand.c b/test/battle/move_effect/upper_hand.c index 36b35781e3..59d6057521 100644 --- a/test/battle/move_effect/upper_hand.c +++ b/test/battle/move_effect/upper_hand.c @@ -68,6 +68,7 @@ SINGLE_BATTLE_TEST("Upper Hand succeeds if the target's move is boosted in prior GIVEN { ASSUME(GetMoveCategory(MOVE_DRAINING_KISS) == DAMAGE_CATEGORY_SPECIAL); ASSUME(GetMovePriority(MOVE_DRAINING_KISS) == 0); + ASSUME(IsHealingMove(MOVE_DRAINING_KISS)); // Doesn't have the Healing Move flag in Gen 5 PLAYER(SPECIES_MIENSHAO) { Speed(10); } OPPONENT(SPECIES_COMFEY) { Speed(5); Ability(ABILITY_TRIAGE); } } WHEN { @@ -85,6 +86,7 @@ SINGLE_BATTLE_TEST("Upper Hand fails if the target moves first") GIVEN { ASSUME(GetMoveCategory(MOVE_DRAINING_KISS) == DAMAGE_CATEGORY_SPECIAL); ASSUME(GetMovePriority(MOVE_DRAINING_KISS) == 0); + ASSUME(IsHealingMove(MOVE_DRAINING_KISS)); // Doesn't have the Healing Move flag in Gen 5 PLAYER(SPECIES_MIENSHAO) { Speed(5); } OPPONENT(SPECIES_COMFEY) { Speed(10); Ability(ABILITY_TRIAGE); } } WHEN { @@ -154,3 +156,20 @@ DOUBLE_BATTLE_TEST("Upper Hand fails if the target has attempted to act even if NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_UPPER_HAND, playerLeft); } } + +SINGLE_BATTLE_TEST("Upper Hand failing will prevent Protean activation") +{ + GIVEN { + WITH_CONFIG(CONFIG_PROTEAN_LIBERO, GEN_6); + PLAYER(SPECIES_REGIROCK); + OPPONENT(SPECIES_KECLEON) { Ability(ABILITY_PROTEAN); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_UPPER_HAND); } + } SCENE { + NONE_OF { + ABILITY_POPUP(opponent, ABILITY_PROTEAN); + ANIMATION(ANIM_TYPE_MOVE, MOVE_UPPER_HAND, player); + } + } +} diff --git a/test/battle/move_effect/victory_dance.c b/test/battle/move_effect/victory_dance.c index cd1d892428..83fff322e3 100644 --- a/test/battle/move_effect/victory_dance.c +++ b/test/battle/move_effect/victory_dance.c @@ -1,4 +1,24 @@ #include "global.h" #include "test/battle.h" -TO_DO_BATTLE_TEST("TODO: Write Victory Dance (Move Effect) test titles") +ASSUMPTIONS +{ + ASSUME(GetMoveEffect(MOVE_VICTORY_DANCE) == EFFECT_VICTORY_DANCE); +} + +SINGLE_BATTLE_TEST("Victory Dance increases the user's Attack, Defense and Speed by 1 stage each") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_VICTORY_DANCE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_VICTORY_DANCE, player); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); + } THEN { + EXPECT_EQ(player->statStages[STAT_ATK], DEFAULT_STAT_STAGE + 1); + EXPECT_EQ(player->statStages[STAT_DEF], DEFAULT_STAT_STAGE + 1); + EXPECT_EQ(player->statStages[STAT_SPEED], DEFAULT_STAT_STAGE + 1); + } +} diff --git a/test/battle/move_effect/wish.c b/test/battle/move_effect/wish.c index 8fa3842123..a901ce0bbf 100644 --- a/test/battle/move_effect/wish.c +++ b/test/battle/move_effect/wish.c @@ -6,9 +6,13 @@ ASSUMPTIONS ASSUME(GetMoveEffect(MOVE_WISH) == EFFECT_WISH); } -SINGLE_BATTLE_TEST("Wish restores 50% of max player HP") +SINGLE_BATTLE_TEST("Wish restores 50% of the user's HP when not switching") { + u32 config; + PARAMETRIZE { config = GEN_4; } + PARAMETRIZE { config = GEN_5; } GIVEN { + WITH_CONFIG(CONFIG_WISH_HP_SOURCE, config); PLAYER(SPECIES_WYNAUT) { HP(50); MaxHP(100); } OPPONENT(SPECIES_WOBBUFFET); } WHEN { @@ -18,11 +22,51 @@ SINGLE_BATTLE_TEST("Wish restores 50% of max player HP") ANIMATION(ANIM_TYPE_MOVE, MOVE_WISH, player); ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, player); MESSAGE("Wynaut's wish came true!"); - HP_BAR(player, hp: 100); + HP_BAR(player, damage: -50); MESSAGE("Wynaut's HP was restored."); } } +SINGLE_BATTLE_TEST("Wish restores 50% of the user's HP when switching (Gen5+)") +{ + GIVEN { + WITH_CONFIG(CONFIG_WISH_HP_SOURCE, GEN_5); + PLAYER(SPECIES_WYNAUT) { HP(50); MaxHP(100); } + PLAYER(SPECIES_WOBBUFFET) { HP(100); MaxHP(200); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_WISH); } + TURN { SWITCH(player, 1); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_WISH, player); + SWITCH_OUT_MESSAGE("Wynaut"); + SEND_IN_MESSAGE("Wobbuffet"); + MESSAGE("Wynaut's wish came true!"); + HP_BAR(player, damage: -50); + MESSAGE("Wobbuffet's HP was restored."); + } +} + +SINGLE_BATTLE_TEST("Wish restores 50% of the recipient's HP when switching (Gen3-4)") +{ + GIVEN { + WITH_CONFIG(CONFIG_WISH_HP_SOURCE, GEN_4); + PLAYER(SPECIES_WYNAUT) { HP(50); MaxHP(100); } + PLAYER(SPECIES_WOBBUFFET) { HP(100); MaxHP(200); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_WISH); } + TURN { SWITCH(player, 1); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_WISH, player); + SWITCH_OUT_MESSAGE("Wynaut"); + SEND_IN_MESSAGE("Wobbuffet"); + MESSAGE("Wynaut's wish came true!"); + HP_BAR(player, damage: -100); + MESSAGE("Wobbuffet's HP was restored."); + } +} + SINGLE_BATTLE_TEST("Wish heals the user at the end of the next turn") { GIVEN { @@ -60,5 +104,3 @@ SINGLE_BATTLE_TEST("Wish is blocked by Heal Block") NOT HP_BAR(player); } } - -TO_DO_BATTLE_TEST("TODO: Write Wish (Move Effect) test titles") diff --git a/test/battle/move_effect/worry_seed.c b/test/battle/move_effect/worry_seed.c deleted file mode 100644 index c4b18b7cab..0000000000 --- a/test/battle/move_effect/worry_seed.c +++ /dev/null @@ -1,74 +0,0 @@ -#include "global.h" -#include "test/battle.h" - -ASSUMPTIONS -{ - ASSUME(GetMoveEffect(MOVE_WORRY_SEED) == EFFECT_WORRY_SEED); -} - -SINGLE_BATTLE_TEST("Worry Seed replaces target's ability with Insomnia") -{ - GIVEN { - PLAYER(SPECIES_WOBBUFFET) { Ability(ABILITY_TELEPATHY); } - OPPONENT(SPECIES_CHARMANDER) { Ability(ABILITY_BLAZE); } - }WHEN { - TURN { MOVE(player, MOVE_WORRY_SEED); } - } SCENE { - ANIMATION(ANIM_TYPE_MOVE, MOVE_WORRY_SEED, player); - ABILITY_POPUP(opponent, ABILITY_BLAZE); - } THEN { - EXPECT_EQ(opponent->ability, ABILITY_INSOMNIA); - } -} - -DOUBLE_BATTLE_TEST("Worry Seed fails if the target already has Insomnia") -{ - GIVEN { - PLAYER(SPECIES_WOBBUFFET) { Ability(ABILITY_TELEPATHY); } - PLAYER(SPECIES_CHARMANDER) { Ability(ABILITY_BLAZE); } - OPPONENT(SPECIES_BULBASAUR) { Ability(ABILITY_OVERGROW); } - OPPONENT(SPECIES_SQUIRTLE) { Ability(ABILITY_TORRENT); } - } WHEN { - TURN { MOVE(playerLeft, MOVE_WORRY_SEED, target: opponentLeft); MOVE(playerRight, MOVE_WORRY_SEED, target: opponentLeft); } - } SCENE { - ANIMATION(ANIM_TYPE_MOVE, MOVE_WORRY_SEED, playerLeft); - ABILITY_POPUP(opponentLeft, ABILITY_OVERGROW); - NONE_OF { - ANIMATION(ANIM_TYPE_MOVE, MOVE_WORRY_SEED, playerRight); - ABILITY_POPUP(opponentLeft, ABILITY_INSOMNIA); - } - } THEN { - EXPECT_EQ(opponentLeft->ability, ABILITY_INSOMNIA); - } -} - -SINGLE_BATTLE_TEST("Worry Seed fails if target has an ability that can't be overwritten") -{ - u32 species, ability; - - PARAMETRIZE { species = SPECIES_ARCEUS; ability = ABILITY_MULTITYPE; } - PARAMETRIZE { species = SPECIES_AEGISLASH; ability = ABILITY_STANCE_CHANGE; } - PARAMETRIZE { species = SPECIES_MINIOR; ability = ABILITY_SHIELDS_DOWN; } - PARAMETRIZE { species = SPECIES_WISHIWASHI; ability = ABILITY_SCHOOLING; } - PARAMETRIZE { species = SPECIES_MIMIKYU; ability = ABILITY_DISGUISE; } - PARAMETRIZE { species = SPECIES_GRENINJA_BATTLE_BOND; ability = ABILITY_BATTLE_BOND; } - PARAMETRIZE { species = SPECIES_ZYGARDE; ability = ABILITY_POWER_CONSTRUCT; } - PARAMETRIZE { species = SPECIES_KOMALA; ability = ABILITY_COMATOSE; } - PARAMETRIZE { species = SPECIES_SILVALLY; ability = ABILITY_RKS_SYSTEM; } - PARAMETRIZE { species = SPECIES_CRAMORANT; ability = ABILITY_GULP_MISSILE; } - PARAMETRIZE { species = SPECIES_EISCUE; ability = ABILITY_ICE_FACE; } - PARAMETRIZE { species = SPECIES_CALYREX_ICE; ability = ABILITY_AS_ONE_ICE_RIDER; } - PARAMETRIZE { species = SPECIES_CALYREX_SHADOW; ability = ABILITY_AS_ONE_SHADOW_RIDER; } - PARAMETRIZE { species = SPECIES_PALAFIN_ZERO; ability = ABILITY_ZERO_TO_HERO; } - PARAMETRIZE { species = SPECIES_TATSUGIRI; ability = ABILITY_COMMANDER; } - - GIVEN { - PLAYER(SPECIES_WOBBUFFET) { Ability(ABILITY_TELEPATHY); } - OPPONENT(species) { Ability(ability); } - } WHEN { - TURN { MOVE(player, MOVE_WORRY_SEED); } - } SCENE { - NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_WORRY_SEED, player); - MESSAGE("But it failed!"); - } -} diff --git a/test/battle/move_effect_secondary/dire_claw.c b/test/battle/move_effect_secondary/dire_claw.c index abd4563132..e45b8e3947 100644 --- a/test/battle/move_effect_secondary/dire_claw.c +++ b/test/battle/move_effect_secondary/dire_claw.c @@ -41,7 +41,7 @@ SINGLE_BATTLE_TEST("Dire Claw cannot poison/paralyze poison/electric types respe PARAMETRIZE { statusAnim = B_ANIM_STATUS_PRZ; rng = MOVE_EFFECT_PARALYSIS; species = SPECIES_RAICHU; } PARAMETRIZE { statusAnim = B_ANIM_STATUS_PSN; rng = MOVE_EFFECT_POISON; species = SPECIES_ARBOK; } GIVEN { - WITH_CONFIG(GEN_CONFIG_PARALYZE_ELECTRIC, GEN_6); + WITH_CONFIG(CONFIG_PARALYZE_ELECTRIC, GEN_6); PLAYER(SPECIES_WOBBUFFET); OPPONENT(species); } WHEN { @@ -64,15 +64,13 @@ SINGLE_BATTLE_TEST("Dire Claw cannot poison/paralyze poison/electric types respe SINGLE_BATTLE_TEST("Dire Claw cannot poison/paralyze/cause to fall asleep Pokémon with abilities preventing respective statuses") { u8 statusAnim; - u16 species, ability; + u16 species; + enum Ability ability; u32 rng; - if (B_REDIRECT_ABILITY_IMMUNITY >= GEN_5) - PARAMETRIZE { statusAnim = B_ANIM_STATUS_PRZ; rng = MOVE_EFFECT_PARALYSIS; species = SPECIES_RAICHU; ability = ABILITY_LIGHTNING_ROD; } - PARAMETRIZE { statusAnim = B_ANIM_STATUS_PRZ; rng = MOVE_EFFECT_PARALYSIS; species = SPECIES_JOLTEON; ability = ABILITY_VOLT_ABSORB; } - PARAMETRIZE { statusAnim = B_ANIM_STATUS_PRZ; rng = MOVE_EFFECT_PARALYSIS; species = SPECIES_ELECTIVIRE; ability = ABILITY_MOTOR_DRIVE; } - PARAMETRIZE { statusAnim = B_ANIM_STATUS_PSN; rng = MOVE_EFFECT_POISON; species = SPECIES_ZANGOOSE; ability = ABILITY_IMMUNITY; } - PARAMETRIZE { statusAnim = B_ANIM_STATUS_SLP; rng = MOVE_EFFECT_SLEEP; species = SPECIES_VIGOROTH; ability = ABILITY_VITAL_SPIRIT; } - PARAMETRIZE { statusAnim = B_ANIM_STATUS_SLP; rng = MOVE_EFFECT_SLEEP; species = SPECIES_HYPNO; ability = ABILITY_INSOMNIA; } + PARAMETRIZE { statusAnim = B_ANIM_STATUS_PRZ; rng = MOVE_EFFECT_PARALYSIS; species = SPECIES_PERSIAN; ability = ABILITY_LIMBER; } + PARAMETRIZE { statusAnim = B_ANIM_STATUS_PSN; rng = MOVE_EFFECT_POISON; species = SPECIES_ZANGOOSE; ability = ABILITY_IMMUNITY; } + PARAMETRIZE { statusAnim = B_ANIM_STATUS_SLP; rng = MOVE_EFFECT_SLEEP; species = SPECIES_VIGOROTH; ability = ABILITY_VITAL_SPIRIT; } + PARAMETRIZE { statusAnim = B_ANIM_STATUS_SLP; rng = MOVE_EFFECT_SLEEP; species = SPECIES_HYPNO; ability = ABILITY_INSOMNIA; } GIVEN { PLAYER(SPECIES_WOBBUFFET); diff --git a/test/battle/move_effect_secondary/flinch.c b/test/battle/move_effect_secondary/flinch.c index 517c87cba9..41c1910b4f 100644 --- a/test/battle/move_effect_secondary/flinch.c +++ b/test/battle/move_effect_secondary/flinch.c @@ -69,3 +69,17 @@ SINGLE_BATTLE_TEST("Protect always works when used after flinching") NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_HEADBUTT, opponent); } } + +SINGLE_BATTLE_TEST("Headbutt flinches 30% of the time") +{ + PASSES_RANDOMLY(30, 100, RNG_SECONDARY_EFFECT); + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_HEADBUTT); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_HEADBUTT, player); + MESSAGE("The opposing Wobbuffet flinched and couldn't move!"); + } +} diff --git a/test/battle/move_effect_secondary/freeze.c b/test/battle/move_effect_secondary/freeze.c index 01a4b31c06..352845766d 100644 --- a/test/battle/move_effect_secondary/freeze.c +++ b/test/battle/move_effect_secondary/freeze.c @@ -20,7 +20,7 @@ SINGLE_BATTLE_TEST("Powder Snow inflicts freeze") } SCENE { ANIMATION(ANIM_TYPE_MOVE, MOVE_POWDER_SNOW, player); HP_BAR(opponent); - ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_FRZ, opponent); + ANIMATION(ANIM_TYPE_STATUS, (B_USE_FROSTBITE ? B_ANIM_STATUS_FRB : B_ANIM_STATUS_FRZ), opponent); FREEZE_OR_FROSTBURN_STATUS(opponent, TRUE); } } @@ -85,11 +85,11 @@ SINGLE_BATTLE_TEST("Freezing Glare shouldn't freeze Psychic-types") ANIMATION(ANIM_TYPE_MOVE, MOVE_FREEZING_GLARE, player); HP_BAR(opponent); #if B_STATUS_TYPE_IMMUNITY > GEN_1 - ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_FRZ, opponent); + ANIMATION(ANIM_TYPE_STATUS, (B_USE_FROSTBITE ? B_ANIM_STATUS_FRB : B_ANIM_STATUS_FRZ), opponent); FREEZE_OR_FROSTBURN_STATUS(opponent, TRUE); #else NONE_OF { - ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_FRZ, opponent); + ANIMATION(ANIM_TYPE_STATUS, (B_USE_FROSTBITE ? B_ANIM_STATUS_FRB : B_ANIM_STATUS_FRZ), opponent); FREEZE_OR_FROSTBURN_STATUS(opponent, TRUE); } #endif diff --git a/test/battle/move_effect_secondary/order_up.c b/test/battle/move_effect_secondary/order_up.c index ec6f1c51b5..bfabd6e3e3 100644 --- a/test/battle/move_effect_secondary/order_up.c +++ b/test/battle/move_effect_secondary/order_up.c @@ -140,7 +140,7 @@ DOUBLE_BATTLE_TEST("Order Up is boosted by Sheer Force without removing the stat DOUBLE_BATTLE_TEST("Order Up is always boosted by Sheer Force", s16 damage) { u32 move; - u32 ability; + enum Ability ability; PARAMETRIZE(move = MOVE_CELEBRATE, ability = ABILITY_STORM_DRAIN); PARAMETRIZE(move = MOVE_ENTRAINMENT, ability = ABILITY_STORM_DRAIN); PARAMETRIZE(move = MOVE_ENTRAINMENT, ability = ABILITY_COMMANDER); diff --git a/test/battle/move_effect_secondary/paralysis.c b/test/battle/move_effect_secondary/paralysis.c index 723309f01a..121d7ac6e9 100644 --- a/test/battle/move_effect_secondary/paralysis.c +++ b/test/battle/move_effect_secondary/paralysis.c @@ -27,7 +27,7 @@ SINGLE_BATTLE_TEST("Thunder Shock cannot paralyze an Electric-type (Gen6+)") PARAMETRIZE { gen = GEN_5; } PARAMETRIZE { gen = GEN_6; } GIVEN { - WITH_CONFIG(GEN_CONFIG_PARALYZE_ELECTRIC, gen); + WITH_CONFIG(CONFIG_PARALYZE_ELECTRIC, gen); ASSUME(GetSpeciesType(SPECIES_PIKACHU, 0) == TYPE_ELECTRIC); PLAYER(SPECIES_WOBBUFFET); OPPONENT(SPECIES_PIKACHU); diff --git a/test/battle/move_effect_secondary/recoil_hp_25.c b/test/battle/move_effect_secondary/recoil_hp_25.c new file mode 100644 index 0000000000..834b55aace --- /dev/null +++ b/test/battle/move_effect_secondary/recoil_hp_25.c @@ -0,0 +1,4 @@ +#include "global.h" +#include "test/battle.h" + +TO_DO_BATTLE_TEST("TODO: Write Struggle (Secondary Move Effect) test titles") diff --git a/test/battle/move_effect_secondary/reflect.c b/test/battle/move_effect_secondary/reflect.c index 0b1dbf7fd3..d0ada07926 100644 --- a/test/battle/move_effect_secondary/reflect.c +++ b/test/battle/move_effect_secondary/reflect.c @@ -21,8 +21,7 @@ SINGLE_BATTLE_TEST("Baddy Bad sets up Reflect when it was succesful") MOVE(player, MOVE_BADDY_BAD, hit: moveSuccess); } } SCENE { - if (moveSuccess == TRUE) - { + if (moveSuccess == TRUE) { ANIMATION(ANIM_TYPE_MOVE, MOVE_BADDY_BAD, player); MESSAGE("Reflect made your team stronger against physical moves!"); } else { @@ -33,3 +32,5 @@ SINGLE_BATTLE_TEST("Baddy Bad sets up Reflect when it was succesful") } } } + +TO_DO_BATTLE_TEST("Baddy Bad can still damage the target when Reflect is already set up"); diff --git a/test/battle/move_effect_secondary/remove_status.c b/test/battle/move_effect_secondary/remove_status.c index 4e62ca55e9..f1219d7ed0 100644 --- a/test/battle/move_effect_secondary/remove_status.c +++ b/test/battle/move_effect_secondary/remove_status.c @@ -3,7 +3,7 @@ SINGLE_BATTLE_TEST("Smelling Salts does not cure paralyzed pokemons behind substitutes or get increased power") { - u32 ability; + enum Ability ability; PARAMETRIZE { ability = ABILITY_INNER_FOCUS; } PARAMETRIZE { ability = ABILITY_INFILTRATOR; } GIVEN { @@ -62,7 +62,7 @@ SINGLE_BATTLE_TEST("Smelling Salts get incread power vs. paralyzed targets") SINGLE_BATTLE_TEST("Wake-Up Slap does not cure paralyzed pokemons behind substitutes or get increased power") { - u32 ability; + enum Ability ability; PARAMETRIZE { ability = ABILITY_INNER_FOCUS; } PARAMETRIZE { ability = ABILITY_INFILTRATOR; } GIVEN { diff --git a/test/battle/move_effect_secondary/syrup_bomb.c b/test/battle/move_effect_secondary/syrup_bomb.c index 3bb52b6d70..4cf2172069 100644 --- a/test/battle/move_effect_secondary/syrup_bomb.c +++ b/test/battle/move_effect_secondary/syrup_bomb.c @@ -74,7 +74,7 @@ SINGLE_BATTLE_TEST("Syrup Bomb is prevented by Bulletproof") SINGLE_BATTLE_TEST("Sticky Syrup speed reduction is prevented by Clear Body, White Smoke or Full Metal Body") { u32 species; - u32 ability; + enum Ability ability; PARAMETRIZE { species = SPECIES_BELDUM; ability = ABILITY_CLEAR_BODY; } PARAMETRIZE { species = SPECIES_TORKOAL; ability = ABILITY_WHITE_SMOKE; } diff --git a/test/battle/move_effect_secondary/tri_attack.c b/test/battle/move_effect_secondary/tri_attack.c index 4ec90f6f92..308e3914fd 100644 --- a/test/battle/move_effect_secondary/tri_attack.c +++ b/test/battle/move_effect_secondary/tri_attack.c @@ -15,7 +15,7 @@ SINGLE_BATTLE_TEST("Tri Attack can inflict paralysis, burn or freeze") u8 statusAnim; PARAMETRIZE { statusAnim = B_ANIM_STATUS_PRZ; } PARAMETRIZE { statusAnim = B_ANIM_STATUS_BRN; } - PARAMETRIZE { statusAnim = B_ANIM_STATUS_FRZ; } + PARAMETRIZE { statusAnim = (B_USE_FROSTBITE ? B_ANIM_STATUS_FRB : B_ANIM_STATUS_FRZ); } PASSES_RANDOMLY(1, 3, RNG_TRI_ATTACK); GIVEN { PLAYER(SPECIES_WOBBUFFET); @@ -29,7 +29,7 @@ SINGLE_BATTLE_TEST("Tri Attack can inflict paralysis, burn or freeze") ANIMATION(ANIM_TYPE_STATUS, statusAnim, opponent); if (statusAnim == B_ANIM_STATUS_BRN) { STATUS_ICON(opponent, burn: TRUE); - } else if (statusAnim == B_ANIM_STATUS_FRZ) { + } else if (statusAnim == (B_USE_FROSTBITE ? B_ANIM_STATUS_FRB : B_ANIM_STATUS_FRZ)) { FREEZE_OR_FROSTBURN_STATUS(opponent, TRUE); } else if (statusAnim == B_ANIM_STATUS_PRZ) { STATUS_ICON(opponent, paralysis: TRUE); @@ -50,7 +50,7 @@ SINGLE_BATTLE_TEST("Tri Attack cannot paralyze/burn/freeze electric/fire/ice typ PARAMETRIZE { statusAnim = B_ANIM_STATUS_BRN; rng = MOVE_EFFECT_BURN; species = SPECIES_ARCANINE; } PARAMETRIZE { statusAnim = B_ANIM_STATUS_FRZ; rng = MOVE_EFFECT_FREEZE_OR_FROSTBITE; species = SPECIES_GLALIE; } GIVEN { - WITH_CONFIG(GEN_CONFIG_PARALYZE_ELECTRIC, GEN_6); + WITH_CONFIG(CONFIG_PARALYZE_ELECTRIC, GEN_6); PLAYER(SPECIES_WOBBUFFET); OPPONENT(species); } WHEN { @@ -79,7 +79,8 @@ SINGLE_BATTLE_TEST("Tri Attack cannot paralyze/burn/freeze Pokémon with abiliti #endif { u8 statusAnim; - u16 species, ability; + u16 species; + enum Ability ability; u32 rng; PARAMETRIZE { statusAnim = B_ANIM_STATUS_PRZ; rng = MOVE_EFFECT_PARALYSIS; species = SPECIES_PERSIAN; ability = ABILITY_LIMBER; } PARAMETRIZE { statusAnim = B_ANIM_STATUS_PRZ; rng = MOVE_EFFECT_PARALYSIS; species = SPECIES_KOMALA; ability = ABILITY_COMATOSE; } diff --git a/test/battle/move_effects_combined/flinch_status.c b/test/battle/move_effects_combined/flinch_status.c index 75c9461880..0d37170726 100644 --- a/test/battle/move_effects_combined/flinch_status.c +++ b/test/battle/move_effects_combined/flinch_status.c @@ -32,7 +32,7 @@ SINGLE_BATTLE_TEST("Thunder, Ice and Fire Fang inflict status 10% of the time") ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_PRZ, opponent); STATUS_ICON(opponent, paralysis: TRUE); } if (move == MOVE_ICE_FANG) { - ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_FRZ, opponent); + ANIMATION(ANIM_TYPE_STATUS, (B_USE_FROSTBITE ? B_ANIM_STATUS_FRB : B_ANIM_STATUS_FRZ), opponent); FREEZE_OR_FROSTBURN_STATUS(opponent, TRUE); } if (move == MOVE_FIRE_FANG) { ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_BRN, opponent); diff --git a/test/battle/move_effects_combined/triple_arrows.c b/test/battle/move_effects_combined/triple_arrows.c index 70414e51c4..f9e0e550b8 100644 --- a/test/battle/move_effects_combined/triple_arrows.c +++ b/test/battle/move_effects_combined/triple_arrows.c @@ -9,7 +9,7 @@ ASSUMPTIONS SINGLE_BATTLE_TEST("Triple Arrows may lower Defense by one stage") { - u32 ability; + enum Ability ability; u32 chance; PARAMETRIZE { ability = ABILITY_HUSTLE; chance = 50; } PARAMETRIZE { ability = ABILITY_SERENE_GRACE; chance = 100; } @@ -28,7 +28,7 @@ SINGLE_BATTLE_TEST("Triple Arrows may lower Defense by one stage") SINGLE_BATTLE_TEST("Triple Arrows makes the foe flinch 30% of the time") { - u32 ability; + enum Ability ability; u32 chance; PARAMETRIZE { ability = ABILITY_HUSTLE; chance = 30; } PARAMETRIZE { ability = ABILITY_SERENE_GRACE; chance = 60; } @@ -54,7 +54,7 @@ SINGLE_BATTLE_TEST("Triple Arrows has an increased critical hit ratio") } PASSES_RANDOMLY(passes, trials, RNG_CRITICAL_HIT); GIVEN { - WITH_CONFIG(GEN_CONFIG_CRIT_CHANCE, genConfig); + WITH_CONFIG(CONFIG_CRIT_CHANCE, genConfig); ASSUME(GetMoveCriticalHitStage(MOVE_TRIPLE_ARROWS) == 1); PLAYER(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WOBBUFFET); diff --git a/test/battle/move_flags/always_hits_in_rain.c b/test/battle/move_flags/always_hits_in_rain.c index c4c5b5138b..4703052716 100644 --- a/test/battle/move_flags/always_hits_in_rain.c +++ b/test/battle/move_flags/always_hits_in_rain.c @@ -1,15 +1,21 @@ #include "global.h" #include "test/battle.h" -SINGLE_BATTLE_TEST("Thunder bypasses accuracy checks in Rain") +SINGLE_BATTLE_TEST("Thunder and Bleakwind/Wildbolt/Sandsear Storm bypass accuracy checks in Rain") { + u32 move; + PARAMETRIZE { move = MOVE_THUNDER; } + PARAMETRIZE { move = MOVE_BLEAKWIND_STORM; } + PARAMETRIZE { move = MOVE_WILDBOLT_STORM; } + PARAMETRIZE { move = MOVE_SANDSEAR_STORM; } PASSES_RANDOMLY(100, 100, RNG_ACCURACY); GIVEN { - ASSUME(MoveAlwaysHitsInRain(MOVE_THUNDER) == TRUE); + ASSUME(GetMoveAccuracy(move) < 100 && GetMoveAccuracy(move) > 0); + ASSUME(MoveAlwaysHitsInRain(move) == TRUE); PLAYER(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WOBBUFFET); } WHEN { - TURN { MOVE(opponent, MOVE_RAIN_DANCE); MOVE(player, MOVE_THUNDER); } + TURN { MOVE(opponent, MOVE_RAIN_DANCE); MOVE(player, move); } } SCENE { NONE_OF { MESSAGE("Wobbuffet's attack missed!"); } } diff --git a/test/battle/move_flags/cant_use_twice.c b/test/battle/move_flags/cant_use_twice.c index 3ed751b95d..1945a2b198 100644 --- a/test/battle/move_flags/cant_use_twice.c +++ b/test/battle/move_flags/cant_use_twice.c @@ -32,7 +32,7 @@ SINGLE_BATTLE_TEST("Moves with the cantUseTwice flag strike again if fast encore PARAMETRIZE { move = MOVE_GIGATON_HAMMER; } PARAMETRIZE { move = MOVE_BLOOD_MOON; } GIVEN { - WITH_CONFIG(GEN_CONFIG_ENCORE_TARGET, GEN_3); + WITH_CONFIG(CONFIG_ENCORE_TARGET, GEN_3); ASSUME(GetMoveEffect(MOVE_ENCORE) == EFFECT_ENCORE); PLAYER(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WOBBUFFET); diff --git a/test/battle/move_flags/critical_hit_stage.c b/test/battle/move_flags/critical_hit_stage.c index d82b4334f3..0712d49ace 100644 --- a/test/battle/move_flags/critical_hit_stage.c +++ b/test/battle/move_flags/critical_hit_stage.c @@ -11,7 +11,7 @@ SINGLE_BATTLE_TEST("criticalHitStage set to 1 increases critical hits occur at a } PASSES_RANDOMLY(passes, trials, RNG_CRITICAL_HIT); GIVEN { - WITH_CONFIG(GEN_CONFIG_CRIT_CHANCE, genConfig); + WITH_CONFIG(CONFIG_CRIT_CHANCE, genConfig); ASSUME(GetMoveCriticalHitStage(MOVE_SLASH) == 1); ASSUME(GetSpeciesBaseSpeed(SPECIES_WOBBUFFET) == 33); PLAYER(SPECIES_WOBBUFFET); diff --git a/test/battle/move_flags/ignores_target_ability.c b/test/battle/move_flags/ignores_target_ability.c index 25e0f9a20f..4a533e7a08 100644 --- a/test/battle/move_flags/ignores_target_ability.c +++ b/test/battle/move_flags/ignores_target_ability.c @@ -10,7 +10,8 @@ ASSUMPTIONS SINGLE_BATTLE_TEST("ignoresTargetAbility moves do not ignore the attacker's own ability", s16 damage) { - u32 ability, move; + enum Ability ability; + u32 move; PARAMETRIZE { move = MOVE_SUNSTEEL_STRIKE; ability = ABILITY_MAGIC_GUARD; } PARAMETRIZE { move = MOVE_SUNSTEEL_STRIKE; ability = ABILITY_UNAWARE; } @@ -47,7 +48,8 @@ SINGLE_BATTLE_TEST("ignoresTargetAbility moves do not ignore the attacker's own SINGLE_BATTLE_TEST("ignoresTargetAbility moves do ignore target's abilities", s16 damage) { - u32 ability, move; + enum Ability ability; + u32 move; PARAMETRIZE { move = MOVE_SUNSTEEL_STRIKE; ability = ABILITY_INNER_FOCUS; } PARAMETRIZE { move = MOVE_SUNSTEEL_STRIKE; ability = ABILITY_MULTISCALE; } @@ -76,7 +78,7 @@ SINGLE_BATTLE_TEST("ignoresTargetAbility moves do ignore target's abilities", s1 SINGLE_BATTLE_TEST("ignoresTargetAbility allows Pokémon with Battle Armor and Shell Armor to receive critical hits") { u32 species; - u32 ability; + enum Ability ability; PARAMETRIZE { species = SPECIES_KINGLER; ability = ABILITY_SHELL_ARMOR; } PARAMETRIZE { species = SPECIES_ARMALDO; ability = ABILITY_BATTLE_ARMOR; } diff --git a/test/battle/move_flags/powder.c b/test/battle/move_flags/powder.c index 989cfb6426..bb109a252e 100644 --- a/test/battle/move_flags/powder.c +++ b/test/battle/move_flags/powder.c @@ -7,7 +7,7 @@ SINGLE_BATTLE_TEST("Powder moves are blocked by Grass-type Pokémon (Gen6+)") PARAMETRIZE { gen = GEN_5; } PARAMETRIZE { gen = GEN_6; } GIVEN { - WITH_CONFIG(GEN_CONFIG_POWDER_GRASS, gen); + WITH_CONFIG(CONFIG_POWDER_GRASS, gen); ASSUME(IsPowderMove(MOVE_STUN_SPORE)); ASSUME(GetSpeciesType(SPECIES_ODDISH, 0) == TYPE_GRASS); PLAYER(SPECIES_WYNAUT); diff --git a/test/battle/move_flags/recoil.c b/test/battle/move_flags/recoil.c index c2b2e21b86..7a71187c82 100644 --- a/test/battle/move_flags/recoil.c +++ b/test/battle/move_flags/recoil.c @@ -122,3 +122,18 @@ SINGLE_BATTLE_TEST("Recoil: The correct amount of recoil damage is dealt after t EXPECT_MUL_EQ(directDamage, UQ_4_12(0.25), recoilDamage); } } + +SINGLE_BATTLE_TEST("Recoil: No recoil is taken if the move is blocked by Disguise") +{ + GIVEN { + ASSUME(GetMoveRecoil(MOVE_FLARE_BLITZ) > 0); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_MIMIKYU) { Ability(ABILITY_DISGUISE); } + } WHEN { + TURN { MOVE(player, MOVE_FLARE_BLITZ); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_FLARE_BLITZ, player); + } THEN { + EXPECT_EQ(player->hp, player->maxHP); + } +} diff --git a/test/battle/sleep_clause.c b/test/battle/sleep_clause.c index 3b8999f668..085bd05fda 100644 --- a/test/battle/sleep_clause.c +++ b/test/battle/sleep_clause.c @@ -1035,7 +1035,7 @@ DOUBLE_BATTLE_TEST("Sleep Clause: Sleep clause is deactivated when a sleeping mo SINGLE_BATTLE_TEST("Sleep Clause: Sleep clause is deactivated when a sleeping mon is woken up by gaining the ability Insomnia / Vital Spirit") { - u32 ability; + enum Ability ability; PARAMETRIZE { ability = ABILITY_VITAL_SPIRIT; } PARAMETRIZE { ability = ABILITY_INSOMNIA; } GIVEN { @@ -1072,7 +1072,7 @@ SINGLE_BATTLE_TEST("Sleep Clause: Sleep clause is deactivated when a sleeping mo SINGLE_BATTLE_TEST("Sleep Clause: Sleep clause is deactivated when a sleeping mon is sent out, has Trace, and Traces Insomnia / Vital spirit") { - u32 ability; + enum Ability ability; PARAMETRIZE { ability = ABILITY_VITAL_SPIRIT; } PARAMETRIZE { ability = ABILITY_INSOMNIA; } @@ -1110,7 +1110,7 @@ SINGLE_BATTLE_TEST("Sleep Clause: Sleep clause is deactivated when a sleeping mo SINGLE_BATTLE_TEST("Sleep Clause: Sleep clause is deactivated when a sleeping mon is sent out and transforms into a mon with Insomnia / Vital spirit") { - u32 ability; + enum Ability ability; PARAMETRIZE { ability = ABILITY_VITAL_SPIRIT; } PARAMETRIZE { ability = ABILITY_INSOMNIA; } KNOWN_FAILING; // Sleep Clause parts work, but Imposter seems broken with battle messages / targeting. Issue #5565 https://github.com/rh-hideout/pokeemerald-expansion/issues/5565 @@ -1404,7 +1404,7 @@ DOUBLE_BATTLE_TEST("Sleep Clause: Waking up after Rest doesn't deactivate sleep SINGLE_BATTLE_TEST("Sleep Clause: Suppressing and then sleeping Vital Spirit / Insomnia and switching back in deactivates sleep clause") { - u32 ability; + enum Ability ability; PARAMETRIZE { ability = ABILITY_VITAL_SPIRIT; } PARAMETRIZE { ability = ABILITY_INSOMNIA; } GIVEN { @@ -1435,7 +1435,7 @@ SINGLE_BATTLE_TEST("Sleep Clause: Suppressing and then sleeping Vital Spirit / I SINGLE_BATTLE_TEST("Sleep Clause: Mold Breaker Pokémon sleeping Vital Spirit / Insomnia activates sleep clause") { - u32 ability; + enum Ability ability; PARAMETRIZE { ability = ABILITY_VITAL_SPIRIT; } PARAMETRIZE { ability = ABILITY_INSOMNIA; } GIVEN { @@ -1772,7 +1772,7 @@ DOUBLE_BATTLE_TEST("Sleep Clause: Sleep Clause does not prevent sleeping your pa DOUBLE_BATTLE_TEST("Sleep Clause: Sleep moves used after being Encore'd are prevented when sleep clause is active") { GIVEN { - WITH_CONFIG(GEN_CONFIG_ENCORE_TARGET, GEN_3); + WITH_CONFIG(CONFIG_ENCORE_TARGET, GEN_3); FLAG_SET(B_FLAG_SLEEP_CLAUSE); ASSUME(GetMoveEffect(MOVE_SPORE) == EFFECT_NON_VOLATILE_STATUS); ASSUME(GetMoveNonVolatileStatus(MOVE_SPORE) == MOVE_EFFECT_SLEEP); diff --git a/test/battle/status1/burn.c b/test/battle/status1/burn.c index 689338cce8..8ec9d05835 100644 --- a/test/battle/status1/burn.c +++ b/test/battle/status1/burn.c @@ -74,7 +74,8 @@ SINGLE_BATTLE_TEST("Will-O-Wisp can't burn a fire type") AI_SINGLE_BATTLE_TEST("AI avoids Will-o-Wisp when it can not burn target") { - u32 species, ability; + u32 species; + enum Ability ability; PARAMETRIZE { species = SPECIES_BUIZEL; ability = ABILITY_WATER_VEIL; } PARAMETRIZE { species = SPECIES_DEWPIDER; ability = ABILITY_WATER_BUBBLE; } diff --git a/test/battle/status1/frostbite.c b/test/battle/status1/frostbite.c index 35503b00a3..e221a0eae3 100644 --- a/test/battle/status1/frostbite.c +++ b/test/battle/status1/frostbite.c @@ -34,7 +34,7 @@ SINGLE_BATTLE_TEST("Frostbite deals 1/16th (Gen7+) or 1/8th damage to affected P TURN {} } SCENE { MESSAGE("The opposing Wobbuffet was hurt by its frostbite!"); - ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_FRZ, opponent); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_FRB, opponent); HP_BAR(opponent, captureDamage: &frostbiteDamage); } THEN { EXPECT_EQ(frostbiteDamage, opponent->maxHP / ((B_BURN_DAMAGE >= GEN_7) ? 16 : 8)); } } @@ -86,11 +86,11 @@ SINGLE_BATTLE_TEST("Frostbite is healed when the user uses a thawing move") HP_BAR(opponent); if (move == MOVE_EMBER) { MESSAGE("Wobbuffet was hurt by its frostbite!"); - ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_FRZ, player); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_FRB, player); } else { NONE_OF { MESSAGE("Wobbuffet was hurt by its frostbite!"); - ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_FRZ, player); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_FRB, player); } } } diff --git a/test/battle/status1/paralysis.c b/test/battle/status1/paralysis.c index 1354c6490b..fa78387af7 100644 --- a/test/battle/status1/paralysis.c +++ b/test/battle/status1/paralysis.c @@ -10,7 +10,7 @@ SINGLE_BATTLE_TEST("Paralysis reduces Speed by 50% (Gen 7+) or 75% (Gen 1-6)") PARAMETRIZE { playerSpeed = 98; playerFirst = FALSE; genConfig = GEN_7; } PARAMETRIZE { playerSpeed = 102; playerFirst = TRUE; genConfig = GEN_7; } GIVEN { - WITH_CONFIG(GEN_CONFIG_PARALYSIS_SPEED, genConfig); + WITH_CONFIG(CONFIG_PARALYSIS_SPEED, genConfig); PLAYER(SPECIES_WOBBUFFET) { Status1(STATUS1_PARALYSIS); Speed(playerSpeed); } OPPONENT(SPECIES_WOBBUFFET) { Speed(50); } } WHEN { @@ -47,7 +47,8 @@ SINGLE_BATTLE_TEST("Paralysis has a 25% chance of skipping the turn") AI_SINGLE_BATTLE_TEST("AI avoids Thunder Wave when it can not paralyse target") { - u32 species, ability; + u32 species; + enum Ability ability; PARAMETRIZE { species = SPECIES_HITMONLEE; ability = ABILITY_LIMBER; } PARAMETRIZE { species = SPECIES_KOMALA; ability = ABILITY_COMATOSE; } @@ -55,7 +56,7 @@ AI_SINGLE_BATTLE_TEST("AI avoids Thunder Wave when it can not paralyse target") PARAMETRIZE { species = SPECIES_PIKACHU; ability = ABILITY_STATIC; } GIVEN { - WITH_CONFIG(GEN_CONFIG_PARALYZE_ELECTRIC, GEN_6); + WITH_CONFIG(CONFIG_PARALYZE_ELECTRIC, GEN_6); AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_OMNISCIENT); PLAYER(species) { Ability(ability); } OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_CELEBRATE, MOVE_THUNDER_WAVE); } @@ -70,7 +71,7 @@ SINGLE_BATTLE_TEST("Thunder Wave doesn't affect Electric types (Gen6+)") PARAMETRIZE { gen = GEN_5; } PARAMETRIZE { gen = GEN_6; } GIVEN { - WITH_CONFIG(GEN_CONFIG_PARALYZE_ELECTRIC, gen); + WITH_CONFIG(CONFIG_PARALYZE_ELECTRIC, gen); ASSUME(GetSpeciesType(SPECIES_PIKACHU, 0) == TYPE_ELECTRIC); PLAYER(SPECIES_WOBBUFFET); OPPONENT(SPECIES_PIKACHU); diff --git a/test/battle/status1/sleep.c b/test/battle/status1/sleep.c index 7a9f60d5fe..5cb60668b9 100644 --- a/test/battle/status1/sleep.c +++ b/test/battle/status1/sleep.c @@ -25,7 +25,7 @@ SINGLE_BATTLE_TEST("Sleep prevents the battler from using a move") SINGLE_BATTLE_TEST("Sleep: Spore affects grass types (Gen1-5)") { GIVEN { - WITH_CONFIG(GEN_CONFIG_POWDER_GRASS, GEN_5); + WITH_CONFIG(CONFIG_POWDER_GRASS, GEN_5); ASSUME(IsPowderMove(MOVE_SPORE)); PLAYER(SPECIES_WOBBUFFET); OPPONENT(SPECIES_CHIKORITA); @@ -39,7 +39,7 @@ SINGLE_BATTLE_TEST("Sleep: Spore affects grass types (Gen1-5)") SINGLE_BATTLE_TEST("Sleep: Spore doesn't affect grass types (Gen6+)") { GIVEN { - WITH_CONFIG(GEN_CONFIG_POWDER_GRASS, GEN_6); + WITH_CONFIG(CONFIG_POWDER_GRASS, GEN_6); ASSUME(IsPowderMove(MOVE_SPORE)); PLAYER(SPECIES_WOBBUFFET); OPPONENT(SPECIES_CHIKORITA); @@ -52,7 +52,8 @@ SINGLE_BATTLE_TEST("Sleep: Spore doesn't affect grass types (Gen6+)") AI_SINGLE_BATTLE_TEST("AI avoids hypnosis when it can not put target to sleep") { - u32 species, ability; + u32 species; + enum Ability ability; PARAMETRIZE { species = SPECIES_HOOTHOOT; ability = ABILITY_INSOMNIA; } PARAMETRIZE { species = SPECIES_MANKEY; ability = ABILITY_VITAL_SPIRIT; } diff --git a/test/battle/switch_in_abilities.c b/test/battle/switch_in_abilities.c index c8a8c54dd3..4d125ddce8 100644 --- a/test/battle/switch_in_abilities.c +++ b/test/battle/switch_in_abilities.c @@ -126,3 +126,124 @@ DOUBLE_BATTLE_TEST("Switch-in abilities trigger in Speed Order after post-KO swi } } } + +MULTI_BATTLE_TEST("Switch-in abilities trigger in Speed Order after post-KO switch - multibattle") +{ + u32 spdPlayer1, spdPlayer2, spdOpponent1, spdOpponent2; + + PARAMETRIZE { spdPlayer1 = 5; spdPlayer2 = 4; spdOpponent1 = 3; spdOpponent2 = 2; } + PARAMETRIZE { spdPlayer1 = 2; spdPlayer2 = 3; spdOpponent1 = 4; spdOpponent2 = 5; } + PARAMETRIZE { spdPlayer1 = 4; spdPlayer2 = 3; spdOpponent1 = 5; spdOpponent2 = 2; } + + GIVEN { + MULTI_PLAYER(SPECIES_WOBBUFFET) { HP(1); Speed(1); } + MULTI_PLAYER(SPECIES_TYRANITAR) { Speed(spdPlayer1); Ability(ABILITY_SAND_STREAM); } + MULTI_PARTNER(SPECIES_WOBBUFFET) { HP(1); Speed(1); } + MULTI_PARTNER(SPECIES_GYARADOS) { Speed(spdPlayer2); Ability(ABILITY_INTIMIDATE); } + MULTI_OPPONENT_A(SPECIES_WOBBUFFET) { HP(1); Speed(1); } + MULTI_OPPONENT_A(SPECIES_WEEZING_GALAR) { Speed(spdOpponent1); Ability(ABILITY_MISTY_SURGE); } + MULTI_OPPONENT_B(SPECIES_WOBBUFFET) { HP(1); Speed(1); } + MULTI_OPPONENT_B(SPECIES_VULPIX_ALOLA) { Speed(spdOpponent2); Ability(ABILITY_SNOW_WARNING); } + } WHEN { + TURN { MOVE(playerLeft, MOVE_EXPLOSION); SEND_OUT(playerLeft, 1); SEND_OUT(opponentLeft, 1); SEND_OUT(playerRight, 4); SEND_OUT(opponentRight, 4); } + TURN { ; } + } SCENE { + MESSAGE("Wobbuffet used Explosion!"); + if (spdPlayer1 == 5) { + ABILITY_POPUP(playerLeft, ABILITY_SAND_STREAM); + ABILITY_POPUP(playerRight, ABILITY_INTIMIDATE); + ABILITY_POPUP(opponentLeft, ABILITY_MISTY_SURGE); + ABILITY_POPUP(opponentRight, ABILITY_SNOW_WARNING); + } else if (spdOpponent2 == 5) { + ABILITY_POPUP(opponentRight, ABILITY_SNOW_WARNING); + ABILITY_POPUP(opponentLeft, ABILITY_MISTY_SURGE); + ABILITY_POPUP(playerRight, ABILITY_INTIMIDATE); + ABILITY_POPUP(playerLeft, ABILITY_SAND_STREAM); + } else { + ABILITY_POPUP(opponentLeft, ABILITY_MISTY_SURGE); + ABILITY_POPUP(playerLeft, ABILITY_SAND_STREAM); + ABILITY_POPUP(playerRight, ABILITY_INTIMIDATE); + ABILITY_POPUP(opponentRight, ABILITY_SNOW_WARNING); + } + } +} + +TWO_VS_ONE_BATTLE_TEST("Switch-in abilities trigger in Speed Order after post-KO switch - 2v1") +{ + u32 spdPlayer1, spdPlayer2, spdOpponent1, spdOpponent2; + + PARAMETRIZE { spdPlayer1 = 5; spdPlayer2 = 4; spdOpponent1 = 3; spdOpponent2 = 2; } + PARAMETRIZE { spdPlayer1 = 2; spdPlayer2 = 3; spdOpponent1 = 4; spdOpponent2 = 5; } + PARAMETRIZE { spdPlayer1 = 4; spdPlayer2 = 3; spdOpponent1 = 5; spdOpponent2 = 2; } + + GIVEN { + MULTI_PLAYER(SPECIES_WOBBUFFET) { HP(1); Speed(1); } + MULTI_PLAYER(SPECIES_TYRANITAR) { Speed(spdPlayer1); Ability(ABILITY_SAND_STREAM); } + MULTI_PARTNER(SPECIES_WYNAUT) { HP(1); Speed(1); } + MULTI_PARTNER(SPECIES_GYARADOS) { Speed(spdPlayer2); Ability(ABILITY_INTIMIDATE); } + MULTI_OPPONENT_A(SPECIES_WOBBUFFET) { HP(1); Speed(1); } + MULTI_OPPONENT_A(SPECIES_WYNAUT) { HP(1); Speed(1); } + MULTI_OPPONENT_A(SPECIES_WEEZING_GALAR) { Speed(spdOpponent1); Ability(ABILITY_MISTY_SURGE); } + MULTI_OPPONENT_A(SPECIES_VULPIX_ALOLA) { Speed(spdOpponent2); Ability(ABILITY_SNOW_WARNING); } + } WHEN { + TURN { MOVE(playerLeft, MOVE_EXPLOSION); SEND_OUT(playerLeft, 1); SEND_OUT(opponentLeft, 2); SEND_OUT(playerRight, 4); SEND_OUT(opponentRight, 3); } + } SCENE { + MESSAGE("Wobbuffet used Explosion!"); + if (spdPlayer1 == 5) { + ABILITY_POPUP(playerLeft, ABILITY_SAND_STREAM); + ABILITY_POPUP(playerRight, ABILITY_INTIMIDATE); + ABILITY_POPUP(opponentLeft, ABILITY_MISTY_SURGE); + ABILITY_POPUP(opponentRight, ABILITY_SNOW_WARNING); + } else if (spdOpponent2 == 5) { + ABILITY_POPUP(opponentRight, ABILITY_SNOW_WARNING); + ABILITY_POPUP(opponentLeft, ABILITY_MISTY_SURGE); + ABILITY_POPUP(playerRight, ABILITY_INTIMIDATE); + ABILITY_POPUP(playerLeft, ABILITY_SAND_STREAM); + } else { + ABILITY_POPUP(opponentLeft, ABILITY_MISTY_SURGE); + ABILITY_POPUP(playerLeft, ABILITY_SAND_STREAM); + ABILITY_POPUP(playerRight, ABILITY_INTIMIDATE); + ABILITY_POPUP(opponentRight, ABILITY_SNOW_WARNING); + } + } +} + +ONE_VS_TWO_BATTLE_TEST("Switch-in abilities trigger in Speed Order after post-KO switch - 1v2") +{ + u32 spdPlayer1, spdPlayer2, spdOpponent1, spdOpponent2; + + PARAMETRIZE { spdPlayer1 = 5; spdPlayer2 = 4; spdOpponent1 = 3; spdOpponent2 = 2; } + PARAMETRIZE { spdPlayer1 = 2; spdPlayer2 = 3; spdOpponent1 = 4; spdOpponent2 = 5; } + PARAMETRIZE { spdPlayer1 = 4; spdPlayer2 = 3; spdOpponent1 = 5; spdOpponent2 = 2; } + + GIVEN { + MULTI_PLAYER(SPECIES_WOBBUFFET) { HP(1); Speed(1); } + MULTI_PLAYER(SPECIES_WYNAUT) { HP(1); Speed(1); } + MULTI_PLAYER(SPECIES_TYRANITAR) { Speed(spdPlayer1); Ability(ABILITY_SAND_STREAM); } + MULTI_PLAYER(SPECIES_GYARADOS) { Speed(spdPlayer2); Ability(ABILITY_INTIMIDATE); } + MULTI_OPPONENT_A(SPECIES_WOBBUFFET) { HP(1); Speed(1); } + MULTI_OPPONENT_A(SPECIES_WEEZING_GALAR) { Speed(spdOpponent1); Ability(ABILITY_MISTY_SURGE); } + MULTI_OPPONENT_B(SPECIES_WYNAUT) { HP(1); Speed(1); } + MULTI_OPPONENT_B(SPECIES_VULPIX_ALOLA) { Speed(spdOpponent2); Ability(ABILITY_SNOW_WARNING); } + } WHEN { + TURN { MOVE(playerLeft, MOVE_EXPLOSION); SEND_OUT(playerLeft, 2); SEND_OUT(opponentLeft, 1); SEND_OUT(playerRight, 3); SEND_OUT(opponentRight, 4); } + } SCENE { + MESSAGE("Wobbuffet used Explosion!"); + if (spdPlayer1 == 5) { + ABILITY_POPUP(playerLeft, ABILITY_SAND_STREAM); + ABILITY_POPUP(playerRight, ABILITY_INTIMIDATE); + ABILITY_POPUP(opponentLeft, ABILITY_MISTY_SURGE); + ABILITY_POPUP(opponentRight, ABILITY_SNOW_WARNING); + } else if (spdOpponent2 == 5) { + ABILITY_POPUP(opponentRight, ABILITY_SNOW_WARNING); + ABILITY_POPUP(opponentLeft, ABILITY_MISTY_SURGE); + ABILITY_POPUP(playerRight, ABILITY_INTIMIDATE); + ABILITY_POPUP(playerLeft, ABILITY_SAND_STREAM); + } else { + ABILITY_POPUP(opponentLeft, ABILITY_MISTY_SURGE); + ABILITY_POPUP(playerLeft, ABILITY_SAND_STREAM); + ABILITY_POPUP(playerRight, ABILITY_INTIMIDATE); + ABILITY_POPUP(opponentRight, ABILITY_SNOW_WARNING); + } + } +} diff --git a/test/battle/trainer_control.party b/test/battle/trainer_control.party index 67436cf782..dbb7ac88ab 100644 --- a/test/battle/trainer_control.party +++ b/test/battle/trainer_control.party @@ -1,241 +1,241 @@ -=== 0 === -Name: Test1 -Class: Pkmn Trainer 1 -Pic: Red -Gender: Male -Music: Male -Battle Type: Singles - -Bubbles (Wobbuffet) (F) @ Assault Vest -Hasty Nature -Level: 67 -Ability: Telepathy -IVs: 25 HP / 26 Atk / 27 Def / 29 SpA / 30 SpD / 28 Spe -EVs: 252 HP / 4 SpA / 252 Spe -Happiness: 42 -Shiny: Yes -Ball: Master Ball -Dynamax Level: 5 -- Air Slash -- Barrier -- Solar Beam -- Explosion - -Wobbuffet -Level: 5 -Ability: Shadow Tag -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -Wynaut -Level: 5 -IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe - -=== 1 === -Name: Test2 -Class: Pkmn Trainer 1 -Pic: Red -Gender: Male -Music: Male -Battle Type: Singles -Difficulty: Normal - -Mewtwo -Level: 5 - -=== 2 === -Name: Test2 -Class: Pkmn Trainer 1 -Pic: Red -Gender: Male -Music: Male -Battle Type: Singles -Difficulty: Normal - -Mewtwo -Level: 50 - -=== 2 === -Name: Test2 -Class: Pkmn Trainer 1 -Pic: Red -Gender: Male -Music: Male -Battle Type: Singles -Difficulty: Easy - -Metapod -Level: 1 - -=== 2 === -Name: Test2 -Class: Pkmn Trainer 1 -Pic: Red -Gender: Male -Music: Male -Battle Type: Singles -Difficulty: Hard - -Arceus -Level: 99 - -=== 3 === -Name: Test3 -Class: Pkmn Trainer 1 -Pic: Red -Gender: Male -Music: Male -Battle Type: Singles -Party Size: 1 - -Wynaut - -Wobbuffet - -Eevee - -Mew - -=== 4 === -Name: Test4 -Class: Pkmn Trainer 1 -Pic: Red -Gender: Male -Music: Male -Battle Type: Singles -Party Size: 3 - -Wynaut - -Wobbuffet -Tags: Lead - -Eevee -Tags: Ace - -Mew - -Oddish -Tags: Ace - -Aron -Tags: Lead - -=== 5 === -Name: Test5 -Class: Pkmn Trainer 1 -Pic: Red -Gender: Male -Music: Male -Battle Type: Doubles -Party Size: 3 -Pool Rules: Weather Doubles - -Wynaut -Tags: Lead - -Wobbuffet -Tags: Lead - -Vulpix -Tags: Lead / Weather Setter - -Bulbasaur -Tags: Lead / Weather Abuser - -Torkoal -Tags: Lead / Weather Setter - -Cherrim -Tags: Lead / Weather Abuser - -Mew -Tags: Lead - -Aron -Tags: Lead - -Oddish - -Eevee - -=== 6 === -Name: Test6 -Class: Pkmn Trainer 1 -Pic: Red -Gender: Male -Music: Male -Battle Type: Singles -Party Size: 2 -Pool Rules: Basic - -Wynaut -Tags: Lead - -Wobbuffet -Tags: Lead - -Eevee -Tags: Lead - -=== 7 === -Name: Test1 -Class: Pkmn Trainer 1 -Pic: Red -Gender: Male -Music: Male -Battle Type: Singles -Party Size: 2 -Pool Rules: Basic -Pool Prune: Test - -Wynaut - -Wobbuffet -Tags: Lead - -Eevee - -=== 8 === -Name: Test1 -Class: Pkmn Trainer 1 -Pic: Red -Gender: Male -Music: Male -Battle Type: Singles -Party Size: 2 -Pool Rules: Basic -Pool Pick Functions: Lowest - -Wynaut -Tags: Ace - -Wobbuffet - -Eevee -Tags: Lead - -=== 9 === -Name: Test9 -Class: Pkmn Trainer 1 -Pic: Red -Gender: Male -Music: Male -Double Battle: Yes -Party Size: 2 - -Wynaut - -Wobbuffet - -=== 10 === -Name: Test10 -Class: Pkmn Trainer 1 -Pic: Red -Gender: Male -Music: Male -Battle Type: Doubles -Party Size: 2 - -Wynaut - -Wobbuffet +=== 0 === +Name: Test1 +Class: Pkmn Trainer 1 +Pic: Red +Gender: Male +Music: Male +Battle Type: Singles + +Bubbles (Wobbuffet) (F) @ Assault Vest +Hasty Nature +Level: 67 +Ability: Telepathy +IVs: 25 HP / 26 Atk / 27 Def / 29 SpA / 30 SpD / 28 Spe +EVs: 252 HP / 4 SpA / 252 Spe +Happiness: 42 +Shiny: Yes +Ball: Master Ball +Dynamax Level: 5 +- Air Slash +- Barrier +- Solar Beam +- Explosion + +Wobbuffet +Level: 5 +Ability: Shadow Tag +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +Wynaut +Level: 5 +IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== 1 === +Name: Test2 +Class: Pkmn Trainer 1 +Pic: Red +Gender: Male +Music: Male +Battle Type: Singles +Difficulty: Normal + +Mewtwo +Level: 5 + +=== 2 === +Name: Test2 +Class: Pkmn Trainer 1 +Pic: Red +Gender: Male +Music: Male +Battle Type: Singles +Difficulty: Normal + +Mewtwo +Level: 50 + +=== 2 === +Name: Test2 +Class: Pkmn Trainer 1 +Pic: Red +Gender: Male +Music: Male +Battle Type: Singles +Difficulty: Easy + +Metapod +Level: 1 + +=== 2 === +Name: Test2 +Class: Pkmn Trainer 1 +Pic: Red +Gender: Male +Music: Male +Battle Type: Singles +Difficulty: Hard + +Arceus +Level: 99 + +=== 3 === +Name: Test3 +Class: Pkmn Trainer 1 +Pic: Red +Gender: Male +Music: Male +Battle Type: Singles +Party Size: 1 + +Wynaut + +Wobbuffet + +Eevee + +Mew + +=== 4 === +Name: Test4 +Class: Pkmn Trainer 1 +Pic: Red +Gender: Male +Music: Male +Battle Type: Singles +Party Size: 3 + +Wynaut + +Wobbuffet +Tags: Lead + +Eevee +Tags: Ace + +Mew + +Oddish +Tags: Ace + +Aron +Tags: Lead + +=== 5 === +Name: Test5 +Class: Pkmn Trainer 1 +Pic: Red +Gender: Male +Music: Male +Battle Type: Doubles +Party Size: 3 +Pool Rules: Weather Doubles + +Wynaut +Tags: Lead + +Wobbuffet +Tags: Lead + +Vulpix +Tags: Lead / Weather Setter + +Bulbasaur +Tags: Lead / Weather Abuser + +Torkoal +Tags: Lead / Weather Setter + +Cherrim +Tags: Lead / Weather Abuser + +Mew +Tags: Lead + +Aron +Tags: Lead + +Oddish + +Eevee + +=== 6 === +Name: Test6 +Class: Pkmn Trainer 1 +Pic: Red +Gender: Male +Music: Male +Battle Type: Singles +Party Size: 2 +Pool Rules: Basic + +Wynaut +Tags: Lead + +Wobbuffet +Tags: Lead + +Eevee +Tags: Lead + +=== 7 === +Name: Test1 +Class: Pkmn Trainer 1 +Pic: Red +Gender: Male +Music: Male +Battle Type: Singles +Party Size: 2 +Pool Rules: Basic +Pool Prune: Test + +Wynaut + +Wobbuffet +Tags: Lead + +Eevee + +=== 8 === +Name: Test1 +Class: Pkmn Trainer 1 +Pic: Red +Gender: Male +Music: Male +Battle Type: Singles +Party Size: 2 +Pool Rules: Basic +Pool Pick Functions: Lowest + +Wynaut +Tags: Ace + +Wobbuffet + +Eevee +Tags: Lead + +=== 9 === +Name: Test9 +Class: Pkmn Trainer 1 +Pic: Red +Gender: Male +Music: Male +Double Battle: Yes +Party Size: 2 + +Wynaut + +Wobbuffet + +=== 10 === +Name: Test10 +Class: Pkmn Trainer 1 +Pic: Red +Gender: Male +Music: Male +Battle Type: Doubles +Party Size: 2 + +Wynaut + +Wobbuffet diff --git a/test/battle/trainer_slides.c b/test/battle/trainer_slides.c index 012ae6e7e9..972e359f87 100644 --- a/test/battle/trainer_slides.c +++ b/test/battle/trainer_slides.c @@ -109,7 +109,7 @@ SINGLE_BATTLE_TEST("Trainer Slide: Enemy Mon Unaffected") { gBattleTestRunnerState->data.recordedBattle.opponentA = TRAINER_SLIDE_ENEMY_MON_UNAFFECTED; GIVEN { - WITH_CONFIG(GEN_CONFIG_SHEER_COLD_IMMUNITY, GEN_7); + WITH_CONFIG(CONFIG_SHEER_COLD_IMMUNITY, GEN_7); ASSUME(GetSpeciesType(SPECIES_GLALIE, 0) == TYPE_ICE); PLAYER(SPECIES_WYNAUT); OPPONENT(SPECIES_GLALIE); diff --git a/test/battle/volatiles/confusion.c b/test/battle/volatiles/confusion.c index 66ab924842..540abbd5a6 100644 --- a/test/battle/volatiles/confusion.c +++ b/test/battle/volatiles/confusion.c @@ -10,7 +10,7 @@ SINGLE_BATTLE_TEST("Confusion adds a 50/33% chance to hit self with 40 power") PARAMETRIZE { genConfig = GEN_7; pctChance = 33; } PASSES_RANDOMLY(pctChance, 100, RNG_CONFUSION); GIVEN { - WITH_CONFIG(GEN_CONFIG_CONFUSION_SELF_DMG_CHANCE, genConfig); + WITH_CONFIG(CONFIG_CONFUSION_SELF_DMG_CHANCE, genConfig); ASSUME(GetMovePower(MOVE_SCRATCH) == 40); PLAYER(SPECIES_WOBBUFFET) { Speed(1); }; OPPONENT(SPECIES_WOBBUFFET) { Speed(2); }; @@ -38,7 +38,7 @@ SINGLE_BATTLE_TEST("Confusion self hit does not consume Gems") PARAMETRIZE { genConfig = GEN_7; pctChance = 33; } PASSES_RANDOMLY(pctChance, 100, RNG_CONFUSION); GIVEN { - WITH_CONFIG(GEN_CONFIG_CONFUSION_SELF_DMG_CHANCE, genConfig); + WITH_CONFIG(CONFIG_CONFUSION_SELF_DMG_CHANCE, genConfig); PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_NORMAL_GEM); }; OPPONENT(SPECIES_WOBBUFFET); } WHEN { diff --git a/test/battle/weather/sandstorm.c b/test/battle/weather/sandstorm.c index 96a440a10e..78dc0ecdce 100644 --- a/test/battle/weather/sandstorm.c +++ b/test/battle/weather/sandstorm.c @@ -17,12 +17,14 @@ SINGLE_BATTLE_TEST("Sandstorm deals 1/16 damage per turn") } THEN { EXPECT_EQ(sandstormDamage, opponent->maxHP / 16); } } -SINGLE_BATTLE_TEST("Sandstorm multiplies the special defense of Rock-types by 1.5x", s16 damage) +SINGLE_BATTLE_TEST("Sandstorm multiplies the special defense of Rock-types by 1.5x (Gen4+)", s16 damage) { - u16 move; - PARAMETRIZE { move = MOVE_SANDSTORM; } - PARAMETRIZE { move = MOVE_CELEBRATE; } + u32 move, config; + PARAMETRIZE { move = MOVE_CELEBRATE; config = GEN_3; } + PARAMETRIZE { move = MOVE_SANDSTORM; config = GEN_3; } + PARAMETRIZE { move = MOVE_SANDSTORM; config = GEN_4; } GIVEN { + WITH_CONFIG(CONFIG_SANDSTORM_SPDEF_BOOST, config); ASSUME(GetMoveCategory(MOVE_SWIFT) == DAMAGE_CATEGORY_SPECIAL); PLAYER(SPECIES_WOBBUFFET) ; OPPONENT(SPECIES_NOSEPASS); @@ -32,7 +34,8 @@ SINGLE_BATTLE_TEST("Sandstorm multiplies the special defense of Rock-types by 1. } SCENE { HP_BAR(opponent, captureDamage: &results[i].damage); } FINALLY { - EXPECT_MUL_EQ(results[0].damage, Q_4_12(1.5), results[1].damage); + EXPECT_MUL_EQ(results[2].damage, Q_4_12(1.5), results[0].damage); + EXPECT_MUL_EQ(results[2].damage, Q_4_12(1.5), results[1].damage); } } @@ -97,8 +100,8 @@ SINGLE_BATTLE_TEST("Sandstorm damage rounds properly when maxHP < 16") SINGLE_BATTLE_TEST("Sandstorm doesn't do damage when weather is negated") { - u32 type1 = GetSpeciesType(SPECIES_STOUTLAND, 0); - u32 type2 = GetSpeciesType(SPECIES_STOUTLAND, 1); + enum Type type1 = GetSpeciesType(SPECIES_STOUTLAND, 0); + enum Type type2 = GetSpeciesType(SPECIES_STOUTLAND, 1); GIVEN { ASSUME(type1 != TYPE_ROCK && type2 != TYPE_ROCK); ASSUME(type1 != TYPE_GROUND && type2 != TYPE_GROUND); diff --git a/test/battle/weather/strong_winds.c b/test/battle/weather/strong_winds.c new file mode 100644 index 0000000000..26b0a51d0d --- /dev/null +++ b/test/battle/weather/strong_winds.c @@ -0,0 +1,17 @@ +#include "global.h" +#include "test/battle.h" + +TO_DO_BATTLE_TEST("Strong winds remove Flying-type weaknesses of all battlers") // Electric, Ice, Rock +TO_DO_BATTLE_TEST("Strong winds remove Flying-type weaknesses of all battlers - Inverse Battle") // Bug, Fighting, Grass +TO_DO_BATTLE_TEST("Strong winds don't affect Stealth Rock's damage") +TO_DO_BATTLE_TEST("Strong winds makes Sunny Day fail") +TO_DO_BATTLE_TEST("Strong winds makes Rain Dance fail") +TO_DO_BATTLE_TEST("Strong winds makes Sandstorm fail") +TO_DO_BATTLE_TEST("Strong winds makes Hail fail") +TO_DO_BATTLE_TEST("Strong winds makes Snowscape fail") // Extrapolation +TO_DO_BATTLE_TEST("Strong winds makes Drought fail to activate") +TO_DO_BATTLE_TEST("Strong winds makes Drizzle fail to activate") +TO_DO_BATTLE_TEST("Strong winds makes Sand Stream fail to activate") +TO_DO_BATTLE_TEST("Strong winds makes Snow Warning fail to activate") +TO_DO_BATTLE_TEST("Strong winds can be replaced by Desolate Land") +TO_DO_BATTLE_TEST("Strong winds can be replaced by Primordial Sea") diff --git a/test/daycare.c b/test/daycare.c index 1f142f1154..3792737030 100644 --- a/test/daycare.c +++ b/test/daycare.c @@ -51,7 +51,10 @@ TEST("(Daycare) Pokémon can breed with Ditto if they don't belong to the Ditto ZeroPlayerPartyMons(); for (j = 1; j < NUM_SPECIES; j++) - PARAMETRIZE { parentSpecies = j; } + { + if (IsSpeciesEnabled(j)) + PARAMETRIZE { parentSpecies = j; } + } VarSet(VAR_TEMP_C, parentSpecies); RUN_OVERWORLD_SCRIPT( givemon SPECIES_DITTO, 100; givemon VAR_TEMP_C, 100; diff --git a/test/pokemon.c b/test/pokemon.c index d6c0cb4d42..c902e56e45 100644 --- a/test/pokemon.c +++ b/test/pokemon.c @@ -5,6 +5,7 @@ #include "test/overworld_script.h" #include "test/test.h" #include "constants/characters.h" +#include "constants/move_relearner.h" TEST("Nature independent from Hidden Nature") { @@ -25,7 +26,8 @@ TEST("Nature independent from Hidden Nature") TEST("Terastallization type defaults to primary or secondary type") { - u32 i, teraType; + u32 i; + enum Type teraType; struct Pokemon mon; for (i = 0; i < 128; i++) PARAMETRIZE {} CreateMon(&mon, SPECIES_PIDGEY, 100, 0, FALSE, 0, OT_ID_PRESET, 0); @@ -36,7 +38,8 @@ TEST("Terastallization type defaults to primary or secondary type") TEST("Terastallization type can be set to any type except TYPE_NONE") { - u32 i, teraType; + u32 i; + enum Type teraType; struct Pokemon mon; for (i = 1; i < NUMBER_OF_MON_TYPES; i++) { @@ -49,7 +52,8 @@ TEST("Terastallization type can be set to any type except TYPE_NONE") TEST("Terastallization type is reset to the default types when setting Tera Type back to TYPE_NONE") { - u32 i, teraType, typeNone; + u32 i; + enum Type teraType, typeNone; struct Pokemon mon; for (i = 1; i < NUMBER_OF_MON_TYPES; i++) { diff --git a/test/species.c b/test/species.c index 06351f179e..c4d91e60e5 100644 --- a/test/species.c +++ b/test/species.c @@ -106,7 +106,7 @@ TEST("No species has two evolutions that use the evolution tracker") for (i = 0; i < NUM_SPECIES; i++) { - if (GetSpeciesEvolutions(i) != NULL) PARAMETRIZE { species = i; } + if (IsSpeciesEnabled(i) && GetSpeciesEvolutions(i) != NULL) PARAMETRIZE { species = i; } } evolutionTrackerEvolutions = 0; diff --git a/test/test_runner.c b/test/test_runner.c index ac4b20cd2c..ef12e8d5f1 100644 --- a/test/test_runner.c +++ b/test/test_runner.c @@ -10,6 +10,7 @@ #include "constants/characters.h" #include "test_runner.h" #include "test/test.h" +#include "test/battle.h" #define TIMEOUT_SECONDS 60 @@ -482,6 +483,7 @@ void Test_ExpectCrash(bool32 expectCrash) static void FunctionTest_SetUp(void *data) { (void)data; + ClearRiggedRng(); gFunctionTestRunnerState = AllocZeroed(sizeof(*gFunctionTestRunnerState)); SeedRng(0); } @@ -513,12 +515,84 @@ static bool32 FunctionTest_CheckProgress(void *data) return madeProgress; } +static u32 FunctionTest_RandomUniform(enum RandomTag tag, u32 lo, u32 hi, bool32 (*reject)(u32), void *caller) +{ + //rigged + for (u32 i = 0; i < RIGGED_RNG_COUNT; i++) + { + if (gFunctionTestRunnerState->rngList[i].tag == tag) + { + if (reject && reject(gFunctionTestRunnerState->rngList[i].value)) + Test_ExitWithResult(TEST_RESULT_INVALID, SourceLine(0), ":LWITH_RNG specified a rejected value (%d)", gFunctionTestRunnerState->rngList[i].value); + return gFunctionTestRunnerState->rngList[i].value; + } + } + //trials + /* + if (tag == STATE->rngTag) + return RandomUniformTrials(tag, lo, hi, reject); + */ + + //default + return RandomUniformDefaultValue(tag, lo, hi, reject, caller); +} + +static u32 FunctionTest_RandomWeightedArray(enum RandomTag tag, u32 sum, u32 n, const u8 *weights, void *caller) +{ + //rigged + for (u32 i = 0; i < RIGGED_RNG_COUNT; i++) + { + if (gFunctionTestRunnerState->rngList[i].tag == tag) + return gFunctionTestRunnerState->rngList[i].value; + } + + //trials + /* + if (tag == STATE->rngTag) + return RandomWeightedArrayTrials(tag, sum, n, weights); + */ + + //default + return RandomWeightedArrayDefaultValue(tag, n, weights, caller); +} + +static const void* FunctionTest_RandomElementArray(enum RandomTag tag, const void *array, size_t size, size_t count, void *caller) +{ + //rigged + for (u32 i = 0; i < RIGGED_RNG_COUNT; i++) + { + if (gFunctionTestRunnerState->rngList[i].tag == tag) + { + u32 element = 0; + for (u32 index = 0; index < count; index++) + { + memcpy(&element, (const u8 *)array + size * index, size); + if (element == gFunctionTestRunnerState->rngList[i].value) + return (const u8 *)array + size * index; + } + Test_ExitWithResult(TEST_RESULT_ERROR, SourceLine(0), ":L%s: RandomElement illegal value requested: %d", gTestRunnerState.test->filename, gFunctionTestRunnerState->rngList[i].value); + } + } + + //trials + /* + if (tag == STATE->rngTag) + return RandomElementTrials(tag, array, size, count); + */ + + //default + return RandomElementArrayDefaultValue(tag, array, size, count, caller); +} + const struct TestRunner gFunctionTestRunner = { .setUp = FunctionTest_SetUp, .run = FunctionTest_Run, .tearDown = FunctionTest_TearDown, .checkProgress = FunctionTest_CheckProgress, + .randomUniform = FunctionTest_RandomUniform, + .randomWeightedArray = FunctionTest_RandomWeightedArray, + .randomElementArray = FunctionTest_RandomElementArray, }; static void Assumptions_Run(void *data) @@ -826,3 +900,102 @@ u32 SourceLineOffset(u32 sourceLine) else return sourceLine - test->sourceLine; } + +u32 RandomUniform(enum RandomTag tag, u32 lo, u32 hi) +{ + void *caller = __builtin_extract_return_addr(__builtin_return_address(0)); + if (gTestRunnerState.test->runner->randomUniform) + return gTestRunnerState.test->runner->randomUniform(tag, lo, hi, NULL, caller); + else + return RandomUniformDefault(tag, lo, hi); +} + +u32 RandomUniformExcept(enum RandomTag tag, u32 lo, u32 hi, bool32 (*reject)(u32)) +{ + void *caller = __builtin_extract_return_addr(__builtin_return_address(0)); + if (gTestRunnerState.test->runner->randomUniform) + return gTestRunnerState.test->runner->randomUniform(tag, lo, hi, reject, caller); + else + return RandomUniformExceptDefault(tag, lo, hi, reject); +} + +u32 RandomWeightedArray(enum RandomTag tag, u32 sum, u32 n, const u8 *weights) +{ + void *caller = __builtin_extract_return_addr(__builtin_return_address(0)); + if (gTestRunnerState.test->runner->randomWeightedArray) + return gTestRunnerState.test->runner->randomWeightedArray(tag, sum, n, weights, caller); + else + return RandomWeightedArrayDefault(tag, sum, n, weights); +} + +const void *RandomElementArray(enum RandomTag tag, const void *array, size_t size, size_t count) +{ + void *caller = __builtin_extract_return_addr(__builtin_return_address(0)); + if (gTestRunnerState.test->runner->randomElementArray) + return gTestRunnerState.test->runner->randomElementArray(tag, array, size, count, caller); + else + return RandomElementArrayDefault(tag, array, size, count); +} + +u32 RandomUniformDefaultValue(enum RandomTag tag, u32 lo, u32 hi, bool32 (*reject)(u32), void *caller) +{ + u32 default_ = hi; + if (reject) + { + while (reject(default_)) + { + if (default_ == lo) + Test_ExitWithResult(TEST_RESULT_ERROR, SourceLine(0), ":LRandomUniformExcept called from %p with tag %d rejected all values", caller, tag); + default_--; + } + } + return default_; +} + +u32 RandomWeightedArrayDefaultValue(enum RandomTag tag, u32 n, const u8 *weights, void *caller) +{ + while (weights[n-1] == 0) + { + if (n == 1) + Test_ExitWithResult(TEST_RESULT_ERROR, SourceLine(0), ":LRandomWeightedArray called from %p with tag %d and all zero weights", caller, tag); + n--; + } + return n-1; +} + +const void *RandomElementArrayDefaultValue(enum RandomTag tag, const void *array, size_t size, size_t count, void *caller) +{ + return (const u8 *)array + size * (count - 1); +} + +void ClearRiggedRng(void) +{ + struct RiggedRNG zeroRng = {.tag = RNG_NONE, .value = 0}; + for (u32 i = 0; i < RIGGED_RNG_COUNT; i++) + memcpy(&gFunctionTestRunnerState->rngList[i], &zeroRng, sizeof(zeroRng)); +} + +void SetupRiggedRng(u32 sourceLine, enum RandomTag randomTag, u32 value) +{ + struct RiggedRNG rng = {.tag = randomTag, .value = value}; + u32 i; + for (i = 0; i < RIGGED_RNG_COUNT; i++) + { + if (gFunctionTestRunnerState->rngList[i].tag == randomTag) + { + memcpy(&gFunctionTestRunnerState->rngList[i], &rng, sizeof(rng)); + break; + } + else if (gFunctionTestRunnerState->rngList[i].tag > RNG_NONE) + { + continue; + } + else + { + memcpy(&gFunctionTestRunnerState->rngList[i], &rng, sizeof(rng)); + break; + } + } + if (i == RIGGED_RNG_COUNT) + Test_ExitWithResult(TEST_RESULT_FAIL, __LINE__, ":L%s:%d: Too many rigged RNGs to set up", gTestRunnerState.test->filename, sourceLine); +} diff --git a/test/test_runner_battle.c b/test/test_runner_battle.c index 395381d1d2..59e0126419 100644 --- a/test/test_runner_battle.c +++ b/test/test_runner_battle.c @@ -3,6 +3,7 @@ #include "battle_ai_util.h" #include "battle_anim.h" #include "battle_controllers.h" +#include "battle_setup.h" #include "battle_gimmick.h" #include "battle_z_move.h" #include "event_data.h" @@ -10,16 +11,19 @@ #include "item_menu.h" #include "main.h" #include "malloc.h" +#include "party_menu.h" #include "random.h" #include "test/battle.h" #include "window.h" #include "constants/characters.h" #include "constants/trainers.h" +#include "constants/abilities.h" #if defined(__INTELLISENSE__) #undef TestRunner_Battle_RecordAbilityPopUp #undef TestRunner_Battle_RecordAnimation #undef TestRunner_Battle_RecordHP +#undef TestRunner_Battle_RecordSubHit #undef TestRunner_Battle_RecordMessage #undef TestRunner_Battle_RecordStatus1 #undef TestRunner_Battle_AfterLastTurn @@ -75,7 +79,7 @@ NAKED static void InvokeSingleTestFunctionWithStack(void *results, u32 i, struct .pool"); } -NAKED static void InvokeDoubleTestFunctionWithStack(void *results, u32 i, struct BattlePokemon *playerLeft, struct BattlePokemon *opponentLeft, struct BattlePokemon *playerRight, struct BattlePokemon *opponentRight, SingleBattleTestFunction function, void *stack) +NAKED static void InvokeDoubleTestFunctionWithStack(void *results, u32 i, struct BattlePokemon *playerLeft, struct BattlePokemon *opponentLeft, struct BattlePokemon *playerRight, struct BattlePokemon *opponentRight, DoubleBattleTestFunction function, void *stack) { asm("push {r4-r7,lr}\n\ ldr r4, [sp, #28] @ function\n\ @@ -99,6 +103,78 @@ NAKED static void InvokeDoubleTestFunctionWithStack(void *results, u32 i, struct .pool"); } +NAKED static void InvokeMultiTestFunctionWithStack(void *results, u32 i, struct BattlePokemon *playerLeft, struct BattlePokemon *opponentLeft, struct BattlePokemon *playerRight, struct BattlePokemon *opponentRight, MultiBattleTestFunction function, void *stack) +{ + asm("push {r4-r7,lr}\n\ + ldr r4, [sp, #28] @ function\n\ + ldr r5, [sp, #32] @ stack\n\ + mov r6, sp\n\ + mov sp, r5\n\ + push {r6}\n\ + add r6, #20\n\ + ldmia r6, {r6, r7} @ playerRight, opponentRight\n\ + push {r6, r7}\n\ + ldr r6, =MultiRestoreSP + 1\n\ + mov lr, r6\n\ + bx r4\n\ + MultiRestoreSP:\n\ + add sp, #8\n\ + pop {r0}\n\ + mov sp, r0\n\ + pop {r4-r7}\n\ + pop {r0}\n\ + bx r0\n\ + .pool"); +} + +NAKED static void InvokeTwoVsOneTestFunctionWithStack(void *results, u32 i, struct BattlePokemon *playerLeft, struct BattlePokemon *opponentLeft, struct BattlePokemon *playerRight, struct BattlePokemon *opponentRight, TwoVsOneBattleTestFunction function, void *stack) +{ + asm("push {r4-r7,lr}\n\ + ldr r4, [sp, #28] @ function\n\ + ldr r5, [sp, #32] @ stack\n\ + mov r6, sp\n\ + mov sp, r5\n\ + push {r6}\n\ + add r6, #20\n\ + ldmia r6, {r6, r7} @ playerRight, opponentRight\n\ + push {r6, r7}\n\ + ldr r6, =TwoVsOneRestoreSP + 1\n\ + mov lr, r6\n\ + bx r4\n\ + TwoVsOneRestoreSP:\n\ + add sp, #8\n\ + pop {r0}\n\ + mov sp, r0\n\ + pop {r4-r7}\n\ + pop {r0}\n\ + bx r0\n\ + .pool"); +} + +NAKED static void InvokeOneVsTwoTestFunctionWithStack(void *results, u32 i, struct BattlePokemon *playerLeft, struct BattlePokemon *opponentLeft, struct BattlePokemon *playerRight, struct BattlePokemon *opponentRight, OneVsTwoBattleTestFunction function, void *stack) +{ + asm("push {r4-r7,lr}\n\ + ldr r4, [sp, #28] @ function\n\ + ldr r5, [sp, #32] @ stack\n\ + mov r6, sp\n\ + mov sp, r5\n\ + push {r6}\n\ + add r6, #20\n\ + ldmia r6, {r6, r7} @ playerRight, opponentRight\n\ + push {r6, r7}\n\ + ldr r6, =OneVsTwoRestoreSP + 1\n\ + mov lr, r6\n\ + bx r4\n\ + OneVsTwoRestoreSP:\n\ + add sp, #8\n\ + pop {r0}\n\ + mov sp, r0\n\ + pop {r4-r7}\n\ + pop {r0}\n\ + bx r0\n\ + .pool"); +} + // Calls test->function, but pointing its stack at DATA.stack so that // local variables are live after the function returns (and so can be // referenced by HP_BAR, or the next call, etc). @@ -117,7 +193,19 @@ static void InvokeTestFunction(const struct BattleTest *test) break; case BATTLE_TEST_DOUBLES: case BATTLE_TEST_AI_DOUBLES: - InvokeDoubleTestFunctionWithStack(STATE->results, STATE->runParameter, &gBattleMons[B_POSITION_PLAYER_LEFT], &gBattleMons[B_POSITION_OPPONENT_LEFT], &gBattleMons[B_POSITION_PLAYER_RIGHT], &gBattleMons[B_POSITION_OPPONENT_RIGHT], test->function.singles, &DATA.stack[BATTLE_TEST_STACK_SIZE]); + InvokeDoubleTestFunctionWithStack(STATE->results, STATE->runParameter, &gBattleMons[B_POSITION_PLAYER_LEFT], &gBattleMons[B_POSITION_OPPONENT_LEFT], &gBattleMons[B_POSITION_PLAYER_RIGHT], &gBattleMons[B_POSITION_OPPONENT_RIGHT], test->function.doubles, &DATA.stack[BATTLE_TEST_STACK_SIZE]); + break; + case BATTLE_TEST_MULTI: + case BATTLE_TEST_AI_MULTI: + InvokeMultiTestFunctionWithStack(STATE->results, STATE->runParameter, &gBattleMons[B_POSITION_PLAYER_LEFT], &gBattleMons[B_POSITION_OPPONENT_LEFT], &gBattleMons[B_POSITION_PLAYER_RIGHT], &gBattleMons[B_POSITION_OPPONENT_RIGHT], test->function.multi, &DATA.stack[BATTLE_TEST_STACK_SIZE]); + break; + case BATTLE_TEST_TWO_VS_ONE: + case BATTLE_TEST_AI_TWO_VS_ONE: + InvokeTwoVsOneTestFunctionWithStack(STATE->results, STATE->runParameter, &gBattleMons[B_POSITION_PLAYER_LEFT], &gBattleMons[B_POSITION_OPPONENT_LEFT], &gBattleMons[B_POSITION_PLAYER_RIGHT], &gBattleMons[B_POSITION_OPPONENT_RIGHT], test->function.two_vs_one, &DATA.stack[BATTLE_TEST_STACK_SIZE]); + break; + case BATTLE_TEST_ONE_VS_TWO: + case BATTLE_TEST_AI_ONE_VS_TWO: + InvokeOneVsTwoTestFunctionWithStack(STATE->results, STATE->runParameter, &gBattleMons[B_POSITION_PLAYER_LEFT], &gBattleMons[B_POSITION_OPPONENT_LEFT], &gBattleMons[B_POSITION_PLAYER_RIGHT], &gBattleMons[B_POSITION_OPPONENT_RIGHT], test->function.one_vs_two, &DATA.stack[BATTLE_TEST_STACK_SIZE]); break; } } @@ -134,6 +222,9 @@ static bool32 IsAITest(void) { case BATTLE_TEST_AI_SINGLES: case BATTLE_TEST_AI_DOUBLES: + case BATTLE_TEST_AI_MULTI: + case BATTLE_TEST_AI_TWO_VS_ONE: + case BATTLE_TEST_AI_ONE_VS_TWO: return TRUE; } return FALSE; @@ -178,6 +269,12 @@ static void BattleTest_SetUp(void *data) break; case BATTLE_TEST_DOUBLES: case BATTLE_TEST_AI_DOUBLES: + case BATTLE_TEST_MULTI: + case BATTLE_TEST_AI_MULTI: + case BATTLE_TEST_TWO_VS_ONE: + case BATTLE_TEST_AI_TWO_VS_ONE: + case BATTLE_TEST_ONE_VS_TWO: + case BATTLE_TEST_AI_ONE_VS_TWO: STATE->battlersCount = 4; break; } @@ -262,26 +359,97 @@ static void BattleTest_Run(void *data) { case BATTLE_TEST_WILD: DATA.recordedBattle.battleFlags = BATTLE_TYPE_IS_MASTER; + for (i = 0; i < STATE->battlersCount; i++) + DATA.currentMonIndexes[i] = i / 2; break; case BATTLE_TEST_AI_SINGLES: DATA.recordedBattle.battleFlags = BATTLE_TYPE_IS_MASTER | BATTLE_TYPE_TRAINER; DATA.recordedBattle.opponentA = TRAINER_LEAF; DATA.hasAI = TRUE; + for (i = 0; i < STATE->battlersCount; i++) + DATA.currentMonIndexes[i] = i / 2; break; case BATTLE_TEST_AI_DOUBLES: DATA.recordedBattle.battleFlags = BATTLE_TYPE_IS_MASTER | BATTLE_TYPE_TRAINER | BATTLE_TYPE_DOUBLE; DATA.recordedBattle.opponentA = TRAINER_LEAF; + DATA.recordedBattle.opponentB = TRAINER_NONE; + DATA.hasAI = TRUE; + for (i = 0; i < STATE->battlersCount; i++) + DATA.currentMonIndexes[i] = i / 2; + break; + case BATTLE_TEST_AI_MULTI: + DATA.recordedBattle.battleFlags = BATTLE_TYPE_IS_MASTER | BATTLE_TYPE_TRAINER | BATTLE_TYPE_INGAME_PARTNER | BATTLE_TYPE_MULTI | BATTLE_TYPE_TWO_OPPONENTS; + DATA.recordedBattle.partnerId = TRAINER_PARTNER(PARTNER_STEVEN); + DATA.recordedBattle.opponentA = TRAINER_LEAF; DATA.recordedBattle.opponentB = TRAINER_RED; DATA.hasAI = TRUE; + DATA.currentMonIndexes[0] = 0; // Player first mon + DATA.currentMonIndexes[1] = 0; // Opponent A first mon + DATA.currentMonIndexes[2] = 3; // Player partner first mon + DATA.currentMonIndexes[3] = 3; // Opponent B first mon + break; + case BATTLE_TEST_AI_TWO_VS_ONE: + DATA.recordedBattle.battleFlags = BATTLE_TYPE_IS_MASTER | BATTLE_TYPE_TRAINER | BATTLE_TYPE_INGAME_PARTNER | BATTLE_TYPE_MULTI; + DATA.recordedBattle.partnerId = TRAINER_PARTNER(PARTNER_STEVEN); + DATA.recordedBattle.opponentA = TRAINER_LEAF; + DATA.recordedBattle.opponentB = 0xFFFF; + DATA.currentMonIndexes[0] = 0; // Player first mon + DATA.currentMonIndexes[1] = 0; // Opponent first mon + DATA.currentMonIndexes[2] = 3; // Player partner first mon + DATA.currentMonIndexes[3] = 1; // Opponent second mon + DATA.hasAI = TRUE; + break; + case BATTLE_TEST_AI_ONE_VS_TWO: + DATA.recordedBattle.battleFlags = BATTLE_TYPE_IS_MASTER | BATTLE_TYPE_TRAINER | BATTLE_TYPE_DOUBLE | BATTLE_TYPE_TWO_OPPONENTS; + DATA.recordedBattle.opponentA = TRAINER_LEAF; + DATA.recordedBattle.opponentB = TRAINER_RED; + DATA.currentMonIndexes[0] = 0; // Player first mon + DATA.currentMonIndexes[1] = 0; // Opponent A first mon + DATA.currentMonIndexes[2] = 1; // Player second mon + DATA.currentMonIndexes[3] = 3; // Opponent B first mon + DATA.hasAI = TRUE; break; case BATTLE_TEST_SINGLES: DATA.recordedBattle.battleFlags = BATTLE_TYPE_IS_MASTER | BATTLE_TYPE_RECORDED_IS_MASTER | BATTLE_TYPE_RECORDED_LINK | BATTLE_TYPE_TRAINER; DATA.recordedBattle.opponentA = TRAINER_LINK_OPPONENT; + for (i = 0; i < STATE->battlersCount; i++) + DATA.currentMonIndexes[i] = i / 2; break; case BATTLE_TEST_DOUBLES: DATA.recordedBattle.battleFlags = BATTLE_TYPE_IS_MASTER | BATTLE_TYPE_RECORDED_IS_MASTER | BATTLE_TYPE_RECORDED_LINK | BATTLE_TYPE_TRAINER | BATTLE_TYPE_DOUBLE; DATA.recordedBattle.opponentA = TRAINER_LINK_OPPONENT; + DATA.recordedBattle.opponentB = TRAINER_NONE; + for (i = 0; i < STATE->battlersCount; i++) + DATA.currentMonIndexes[i] = i / 2; + break; + case BATTLE_TEST_MULTI: + DATA.recordedBattle.battleFlags = BATTLE_TYPE_IS_MASTER | BATTLE_TYPE_RECORDED_IS_MASTER | BATTLE_TYPE_RECORDED_LINK | BATTLE_TYPE_TRAINER | BATTLE_TYPE_INGAME_PARTNER | BATTLE_TYPE_MULTI | BATTLE_TYPE_TWO_OPPONENTS; + DATA.recordedBattle.partnerId = TRAINER_PARTNER(PARTNER_STEVEN); + DATA.recordedBattle.opponentA = TRAINER_LINK_OPPONENT; DATA.recordedBattle.opponentB = TRAINER_LINK_OPPONENT; + DATA.currentMonIndexes[0] = 0; // Player first mon + DATA.currentMonIndexes[1] = 0; // Opponent A first mon + DATA.currentMonIndexes[2] = 3; // Player partner first mon + DATA.currentMonIndexes[3] = 3; // Opponent B first mon + break; + case BATTLE_TEST_TWO_VS_ONE: + DATA.recordedBattle.battleFlags = BATTLE_TYPE_IS_MASTER | BATTLE_TYPE_RECORDED_IS_MASTER | BATTLE_TYPE_RECORDED_LINK | BATTLE_TYPE_TRAINER | BATTLE_TYPE_INGAME_PARTNER | BATTLE_TYPE_MULTI; + DATA.recordedBattle.partnerId = TRAINER_PARTNER(PARTNER_STEVEN); + DATA.recordedBattle.opponentA = TRAINER_LINK_OPPONENT; + DATA.recordedBattle.opponentB = 0xFFFF; + DATA.currentMonIndexes[0] = 0; // Player first mon + DATA.currentMonIndexes[1] = 0; // Opponent first mon + DATA.currentMonIndexes[2] = 3; // Player partner first mon + DATA.currentMonIndexes[3] = 1; // Opponent second mon + break; + case BATTLE_TEST_ONE_VS_TWO: + DATA.recordedBattle.battleFlags = BATTLE_TYPE_IS_MASTER | BATTLE_TYPE_RECORDED_IS_MASTER | BATTLE_TYPE_RECORDED_LINK | BATTLE_TYPE_TRAINER | BATTLE_TYPE_DOUBLE | BATTLE_TYPE_TWO_OPPONENTS; + DATA.recordedBattle.opponentA = TRAINER_LINK_OPPONENT; + DATA.recordedBattle.opponentB = TRAINER_LINK_OPPONENT; + DATA.currentMonIndexes[0] = 0; // Player first mon + DATA.currentMonIndexes[1] = 0; // Opponent A first mon + DATA.currentMonIndexes[2] = 1; // Player second mon + DATA.currentMonIndexes[3] = 3; // Opponent B first mon break; } @@ -293,9 +461,6 @@ static void BattleTest_Run(void *data) DATA.recordedBattle.playersBattlers[i] = i; } - for (i = 0; i < STATE->battlersCount; i++) - DATA.currentMonIndexes[i] = i / 2; - STATE->runRandomly = TRUE; STATE->runGiven = TRUE; STATE->runWhen = TRUE; @@ -325,10 +490,46 @@ static void BattleTest_Run(void *data) if (DATA.hasExplicitSpeeds) { - // TODO: If a battler is taking the default action maybe it - // should not require an explicit speed? - if (DATA.explicitSpeeds[B_SIDE_PLAYER] != (1 << DATA.playerPartySize) - 1 - || DATA.explicitSpeeds[B_SIDE_OPPONENT] != (1 << DATA.opponentPartySize) - 1) + u8 revisedPlayerExplicitSpeeds = 0; + u8 revisedPartnerExplicitSpeeds = 0; + u8 revisedOpponentAExplicitSpeeds = 0; + u8 revisedOpponentBExplicitSpeeds = 0; + + for (i = 0; i < 3; i++) + { + if(GetMonData(&DATA.recordedBattle.playerParty[i], MON_DATA_SPECIES, NULL) != SPECIES_NONE) + revisedPlayerExplicitSpeeds |= 1 << i; + } + for (i = 3; i < PARTY_SIZE; i++) + { + if(GetMonData(&DATA.recordedBattle.playerParty[i], MON_DATA_SPECIES, NULL) != SPECIES_NONE) + { + if(DATA.currentPosition == B_POSITION_PLAYER_LEFT) + revisedPlayerExplicitSpeeds |= 1 << i; + else + revisedPartnerExplicitSpeeds |= 1 << i; + } + } + + for (i = 0; i < 3; i++) + { + if(GetMonData(&DATA.recordedBattle.opponentParty[i], MON_DATA_SPECIES, NULL) != SPECIES_NONE) + revisedOpponentAExplicitSpeeds |= 1 << i; + } + for (i = 3; i < PARTY_SIZE; i++) + { + if(GetMonData(&DATA.recordedBattle.opponentParty[i], MON_DATA_SPECIES, NULL) != SPECIES_NONE) + { + if(DATA.currentPosition == B_POSITION_OPPONENT_LEFT) + revisedOpponentAExplicitSpeeds |= 1 << i; + else + revisedOpponentBExplicitSpeeds |= 1 << i; + } + } + + if (((DATA.explicitSpeeds[B_POSITION_PLAYER_LEFT] + DATA.explicitSpeeds[B_POSITION_PLAYER_RIGHT]) != (revisedPlayerExplicitSpeeds + revisedPartnerExplicitSpeeds) + || (DATA.explicitSpeeds[B_POSITION_OPPONENT_LEFT] + DATA.explicitSpeeds[B_POSITION_OPPONENT_RIGHT]) != (revisedOpponentAExplicitSpeeds + revisedOpponentBExplicitSpeeds))) + { Test_ExitWithResult(TEST_RESULT_INVALID, SourceLine(0), ":LSpeed required for all PLAYERs and OPPONENTs"); } @@ -354,96 +555,113 @@ static void BattleTest_Run(void *data) PrintTestName(); } -u32 RandomUniform(enum RandomTag tag, u32 lo, u32 hi) +u32 RandomUniformTrials(enum RandomTag tag, u32 lo, u32 hi, bool32 (*reject)(u32), void *caller) { - const struct BattlerTurn *turn = NULL; - - if (gCurrentTurnActionNumber < gBattlersCount) + STATE->didRunRandomly = TRUE; + if (STATE->trials == 1) { - u32 battlerId = gBattlerByTurnOrder[gCurrentTurnActionNumber]; - turn = &DATA.battleRecordTurns[gBattleResults.battleTurnCounter][battlerId]; - if (turn && turn->rng.tag == tag) - return turn->rng.value; - } - - if (tag == STATE->rngTag) - { - STATE->didRunRandomly = TRUE; - u32 n = hi - lo + 1; - if (STATE->trials == 1) + u32 n = 0, i; + if (reject) { - STATE->trials = n; - PrintTestName(); - } - else if (STATE->trials != n) - { - Test_ExitWithResult(TEST_RESULT_ERROR, SourceLine(0), ":LRandomUniform called from %p with tag %d and inconsistent trials %d and %d", __builtin_extract_return_addr(__builtin_return_address(0)), tag, STATE->trials, n); - } - STATE->trialRatio = Q_4_12(1) / STATE->trials; - return STATE->runTrial + lo; - } - - return hi; -} - -u32 RandomUniformExcept(enum RandomTag tag, u32 lo, u32 hi, bool32 (*reject)(u32)) -{ - const struct BattlerTurn *turn = NULL; - u32 default_; - - if (gCurrentTurnActionNumber < gBattlersCount) - { - u32 battlerId = gBattlerByTurnOrder[gCurrentTurnActionNumber]; - turn = &DATA.battleRecordTurns[gBattleResults.battleTurnCounter][battlerId]; - if (turn && turn->rng.tag == tag) - { - if (reject(turn->rng.value)) - Test_ExitWithResult(TEST_RESULT_INVALID, SourceLine(0), ":LWITH_RNG specified a rejected value (%d)", turn->rng.value); - return turn->rng.value; - } - } - - if (tag == STATE->rngTag) - { - STATE->didRunRandomly = TRUE; - if (STATE->trials == 1) - { - u32 n = 0, i; for (i = lo; i <= hi; i++) if (!reject(i)) n++; STATE->trials = n; - PrintTestName(); } - STATE->trialRatio = Q_4_12(1) / STATE->trials; - - while (reject(STATE->runTrial + lo + STATE->rngTrialOffset)) - { - if (STATE->runTrial + lo + STATE->rngTrialOffset > hi) - Test_ExitWithResult(TEST_RESULT_ERROR, SourceLine(0), ":LRandomUniformExcept called from %p with tag %d and inconsistent reject", __builtin_extract_return_addr(__builtin_return_address(0)), tag); - STATE->rngTrialOffset++; - } - - return STATE->runTrial + lo + STATE->rngTrialOffset; + else + STATE->trials = hi - lo + 1; + PrintTestName(); } + STATE->trialRatio = Q_4_12(1) / STATE->trials; - default_ = hi; - while (reject(default_)) + if (!reject) { - if (default_ == lo) - Test_ExitWithResult(TEST_RESULT_ERROR, SourceLine(0), ":LRandomUniformExcept called from %p with tag %d rejected all values", __builtin_extract_return_addr(__builtin_return_address(0)), tag); - default_--; + if (STATE->trials != (hi - lo + 1)) + Test_ExitWithResult(TEST_RESULT_ERROR, SourceLine(0), ":LRandomUniform called from %p with tag %d and inconsistent trials %d and %d", caller, tag, STATE->trials, hi - lo + 1); + return STATE->runTrial + lo; } - return default_; + + while (reject(STATE->runTrial + lo + STATE->rngTrialOffset)) + { + if (STATE->runTrial + lo + STATE->rngTrialOffset > hi) + Test_ExitWithResult(TEST_RESULT_ERROR, SourceLine(0), ":LRandomUniformExcept called from %p with tag %d and inconsistent reject", caller, tag); + STATE->rngTrialOffset++; + } + + return STATE->runTrial + lo + STATE->rngTrialOffset; + } -u32 RandomWeightedArray(enum RandomTag tag, u32 sum, u32 n, const u8 *weights) +u32 RandomWeightedArrayTrials(enum RandomTag tag, u32 sum, u32 n, const u8 *weights, void *caller) { + //Detect inconsistent sum + u32 weightSum = 0; + if (STATE->runTrial == 0) + { + for (u32 i = 0; i < n; i++) + weightSum += weights[i]; + if (weightSum != sum) + Test_ExitWithResult(TEST_RESULT_ERROR, SourceLine(0), ":LRandomWeighted called from %p has weights not matching its sum", caller); + } + + STATE->didRunRandomly = TRUE; + if (STATE->trials == 1) + { + STATE->trials = n; + PrintTestName(); + } + else if (STATE->trials != n) + { + Test_ExitWithResult(TEST_RESULT_ERROR, SourceLine(0), ":LRandomWeighted called from %p with tag %d and inconsistent trials %d and %d", caller, tag, STATE->trials, n); + } + + STATE->trialRatio = Q_4_12(weights[STATE->runTrial]) / sum; + return STATE->runTrial; +} + +const void *RandomElementArrayTrials(enum RandomTag tag, const void *array, size_t size, size_t count, void *caller) +{ + STATE->didRunRandomly = TRUE; + if (STATE->trials == 1) + { + STATE->trials = count; + PrintTestName(); + } + else if (STATE->trials != count) + { + Test_ExitWithResult(TEST_RESULT_ERROR, SourceLine(0), ":LRandomElement called from %p with tag %d and inconsistent trials %d and %d", caller, tag, STATE->trials, count); + } + STATE->trialRatio = Q_4_12(1) / count; + return (const u8 *)array + size * STATE->runTrial; +} + +static u32 BattleTest_RandomUniform(enum RandomTag tag, u32 lo, u32 hi, bool32 (*reject)(u32), void *caller) +{ + //rigged const struct BattlerTurn *turn = NULL; + if (gCurrentTurnActionNumber < gBattlersCount) + { + u32 battlerId = gBattlerByTurnOrder[gCurrentTurnActionNumber]; + turn = &DATA.battleRecordTurns[gBattleResults.battleTurnCounter][battlerId]; + if (turn && turn->rng.tag == tag) + { + if (reject && reject(turn->rng.value)) + Test_ExitWithResult(TEST_RESULT_INVALID, SourceLine(0), ":LWITH_RNG specified a rejected value (%d)", turn->rng.value); + return turn->rng.value; + } + } + //trials + if (tag && tag == STATE->rngTag) + return RandomUniformTrials(tag, lo, hi, reject, caller); - if (sum == 0) - Test_ExitWithResult(TEST_RESULT_ERROR, SourceLine(0), ":LRandomWeightedArray called with zero sum"); + //default + return RandomUniformDefaultValue(tag, lo, hi, reject, caller); +} +static u32 BattleTest_RandomWeightedArray(enum RandomTag tag, u32 sum, u32 n, const u8 *weights, void *caller) +{ + //rigged + const struct BattlerTurn *turn = NULL; if (gCurrentTurnActionNumber < gBattlersCount || tag == RNG_SHELL_SIDE_ARM) { u32 battlerId = gBattlerByTurnOrder[gCurrentTurnActionNumber]; @@ -452,23 +670,11 @@ u32 RandomWeightedArray(enum RandomTag tag, u32 sum, u32 n, const u8 *weights) return turn->rng.value; } - if (tag == STATE->rngTag) - { - STATE->didRunRandomly = TRUE; - if (STATE->trials == 1) - { - STATE->trials = n; - PrintTestName(); - } - else if (STATE->trials != n) - { - Test_ExitWithResult(TEST_RESULT_ERROR, SourceLine(0), ":LRandomWeighted called from %p with tag %d and inconsistent trials %d and %d", __builtin_extract_return_addr(__builtin_return_address(0)), tag, STATE->trials, n); - } - // TODO: Detect inconsistent sum. - STATE->trialRatio = Q_4_12(weights[STATE->runTrial]) / sum; - return STATE->runTrial; - } + //trials + if (tag && tag == STATE->rngTag) + return RandomWeightedArrayTrials(tag, sum, n, weights, caller); + //default switch (tag) { case RNG_ACCURACY: @@ -493,21 +699,14 @@ u32 RandomWeightedArray(enum RandomTag tag, u32 sum, u32 n, const u8 *weights) return TRUE; default: - while (weights[n-1] == 0) - { - if (n == 1) - Test_ExitWithResult(TEST_RESULT_ERROR, SourceLine(0), ":LRandomWeightedArray called from %p with tag %d and all zero weights", __builtin_extract_return_addr(__builtin_return_address(0)), tag); - n--; - } - return n-1; + return RandomWeightedArrayDefaultValue(tag, n, weights, caller); } } -const void *RandomElementArray(enum RandomTag tag, const void *array, size_t size, size_t count) +static const void *BattleTest_RandomElementArray(enum RandomTag tag, const void *array, size_t size, size_t count, void *caller) { + //rigged const struct BattlerTurn *turn = NULL; - u32 index = count-1; - if (gCurrentTurnActionNumber < gBattlersCount) { u32 battlerId = gBattlerByTurnOrder[gCurrentTurnActionNumber]; @@ -515,36 +714,26 @@ const void *RandomElementArray(enum RandomTag tag, const void *array, size_t siz if (turn && turn->rng.tag == tag) { u32 element = 0; - for (index = 0; index < count; index++) + for (u32 index = 0; index < count; index++) { memcpy(&element, (const u8 *)array + size * index, size); if (element == turn->rng.value) return (const u8 *)array + size * index; } - // TODO: Incorporate the line number. Test_ExitWithResult(TEST_RESULT_ERROR, SourceLine(0), ":L%s: RandomElement illegal value requested: %d", gTestRunnerState.test->filename, turn->rng.value); } } - if (tag == STATE->rngTag) - { - STATE->didRunRandomly = TRUE; - if (STATE->trials == 1) - { - STATE->trials = count; - PrintTestName(); - } - else if (STATE->trials != count) - { - Test_ExitWithResult(TEST_RESULT_ERROR, SourceLine(0), ":LRandomElement called from %p with tag %d and inconsistent trials %d and %d", __builtin_extract_return_addr(__builtin_return_address(0)), tag, STATE->trials, count); - } - STATE->trialRatio = Q_4_12(1) / count; - return (const u8 *)array + size * STATE->runTrial; - } - return (const u8 *)array + size * index; + + //trials + if (tag && tag == STATE->rngTag) + return RandomElementArrayTrials(tag, array, size, count, caller); + + //default + return RandomElementArrayDefaultValue(tag, array, size, count, caller); } -static s32 TryAbilityPopUp(s32 i, s32 n, u32 battlerId, u32 ability) +static s32 TryAbilityPopUp(s32 i, s32 n, u32 battlerId, enum Ability ability) { struct QueuedAbilityEvent *event; s32 iMax = i + n; @@ -562,7 +751,7 @@ static s32 TryAbilityPopUp(s32 i, s32 n, u32 battlerId, u32 ability) return -1; } -void TestRunner_Battle_RecordAbilityPopUp(u32 battlerId, u32 ability) +void TestRunner_Battle_RecordAbilityPopUp(u32 battlerId, enum Ability ability) { s32 queuedEvent; s32 match; @@ -758,11 +947,100 @@ void TestRunner_Battle_RecordHP(u32 battlerId, u32 oldHP, u32 newHP) } } +static s32 TrySubHit(s32 i, s32 n, u32 battlerId, u32 damage, bool32 broke) +{ + struct QueuedSubHitEvent *event; + s32 iMax = i + n; + for (; i < iMax; i++) + { + if (DATA.queuedEvents[i].type != QUEUED_SUB_HIT_EVENT) + continue; + + event = &DATA.queuedEvents[i].as.subHit; + + if (event->battlerId == battlerId) + { + if (event->checkBreak) + { + if (event->breakSub && !broke) + return -1; + else if (!event->breakSub && broke) + return -1; + } + + if (event->address <= 0xFFFF) + { + event->address = damage; + return i; + } + else + { + *(u16 *)(u32)(event->address) = damage; + return i; + } + } + } + return -1; +} + +void TestRunner_Battle_RecordSubHit(u32 battlerId, u32 damage, bool32 broke) +{ + s32 queuedEvent; + s32 match; + struct QueuedEvent *event; + + if (DATA.trial.queuedEvent == DATA.queuedEventsCount) + return; + + event = &DATA.queuedEvents[DATA.trial.queuedEvent]; + switch (event->groupType) + { + case QUEUE_GROUP_NONE: + case QUEUE_GROUP_ONE_OF: + if (TrySubHit(DATA.trial.queuedEvent, event->groupSize, battlerId, damage, broke) != -1) + DATA.trial.queuedEvent += event->groupSize; + break; + case QUEUE_GROUP_NONE_OF: + queuedEvent = DATA.trial.queuedEvent; + do + { + if ((match = TrySubHit(queuedEvent, event->groupSize, battlerId, damage, broke)) != -1) + { + const char *filename = gTestRunnerState.test->filename; + u32 line = SourceLine(DATA.queuedEvents[match].sourceLineOffset); + Test_ExitWithResult(TEST_RESULT_FAIL, line, ":L%s:%d: Matched SUB_HIT", filename, line); + } + + queuedEvent += event->groupSize; + if (queuedEvent == DATA.queuedEventsCount) + break; + + event = &DATA.queuedEvents[queuedEvent]; + if (event->groupType == QUEUE_GROUP_NONE_OF) + continue; + + if (TrySubHit(queuedEvent, event->groupSize, battlerId, damage, broke) != -1) + DATA.trial.queuedEvent = queuedEvent + event->groupSize; + } while (FALSE); + break; + } +} + static const char *const sBattleActionNames[] = { - [B_ACTION_USE_MOVE] = "MOVE", - [B_ACTION_USE_ITEM] = "USE_ITEM", - [B_ACTION_SWITCH] = "SWITCH", + [B_ACTION_USE_MOVE] = "招式", + [B_ACTION_USE_ITEM] = "道具", + [B_ACTION_SWITCH] = "替换", +}; + +static const char *const sGimmickIdentifiers[GIMMICKS_COUNT] = +{ + [GIMMICK_NONE] = "N/A", + [GIMMICK_MEGA] = "超级进化", + [GIMMICK_ULTRA_BURST] = "究极爆发", + [GIMMICK_Z_MOVE] = "Z招式", + [GIMMICK_DYNAMAX] = "极巨化", + [GIMMICK_TERA] = "太晶化", }; static u32 CountAiExpectMoves(struct ExpectedAIAction *expectedAction, u32 battlerId, bool32 printLog) @@ -780,7 +1058,7 @@ static u32 CountAiExpectMoves(struct ExpectedAIAction *expectedAction, u32 battl return countExpected; } -void TestRunner_Battle_CheckChosenMove(u32 battlerId, u32 moveId, u32 target) +void TestRunner_Battle_CheckChosenMove(u32 battlerId, u32 moveId, u32 target, enum Gimmick gimmick) { const char *filename = gTestRunnerState.test->filename; u32 id = DATA.trial.aiActionsPlayed[battlerId]; @@ -802,6 +1080,9 @@ void TestRunner_Battle_CheckChosenMove(u32 battlerId, u32 moveId, u32 target) if (expectedAction->explicitTarget && expectedAction->target != target) Test_ExitWithResult(TEST_RESULT_FAIL, SourceLine(0), ":L%s:%d: Expected target %s, got %s", filename, expectedAction->sourceLine, BattlerIdentifier(expectedAction->target), BattlerIdentifier(target)); + if (expectedAction->gimmick != GIMMICKS_COUNT && expectedAction->gimmick != gimmick) + Test_ExitWithResult(TEST_RESULT_FAIL, SourceLine(0), ":L%s:%d: Expected gimmick %s, got %s", filename, expectedAction->sourceLine, sGimmickIdentifiers[expectedAction->gimmick], sGimmickIdentifiers[gimmick]); + for (i = 0; i < MAX_MON_MOVES; i++) { if ((1u << i) & expectedAction->moveSlots) @@ -1304,6 +1585,7 @@ static const char *const sEventTypeMacros[] = [QUEUED_ABILITY_POPUP_EVENT] = "ABILITY_POPUP", [QUEUED_ANIMATION_EVENT] = "ANIMATION", [QUEUED_HP_EVENT] = "HP_BAR", + [QUEUED_SUB_HIT_EVENT] = "SUB_HIT", [QUEUED_EXP_EVENT] = "EXPERIENCE_BAR", [QUEUED_MESSAGE_EVENT] = "MESSAGE", [QUEUED_STATUS_EVENT] = "STATUS_ICON", @@ -1496,14 +1778,24 @@ void RNGSeed_(u32 sourceLine, rng_value_t seed) void AIFlags_(u32 sourceLine, u64 flags) { - INVALID_IF(!IsAITest(), "AI_FLAGS is usable only in AI_SINGLE_BATTLE_TEST & AI_DOUBLE_BATTLE_TEST"); - DATA.recordedBattle.AI_scripts = flags; + INVALID_IF(!IsAITest(), "AI_FLAGS is usable only in AI_SINGLE_BATTLE_TEST, AI_DOUBLE_BATTLE_TEST, AI_MULTI_BATTLE_TEST, and AI_TWO_VS_ONE_TEST"); + for (u32 i = 0; i < MAX_BATTLERS_COUNT; i++) + { + DATA.recordedBattle.AI_scripts[i] = flags; + } + DATA.hasAI = TRUE; +} + +void BattlerAIFlags_(u32 sourceLine, u32 battler, u64 flags) +{ + INVALID_IF(!IsAITest(), "AI_FLAGS is usable only in AI_SINGLE_BATTLE_TEST, AI_DOUBLE_BATTLE_TEST, AI_MULTI_BATTLE_TEST, and AI_TWO_VS_ONE_TEST"); + DATA.recordedBattle.AI_scripts[battler] |= flags; DATA.hasAI = TRUE; } void AILogScores(u32 sourceLine) { - INVALID_IF(!IsAITest(), "AI_LOG is usable only in AI_SINGLE_BATTLE_TEST & AI_DOUBLE_BATTLE_TEST"); + INVALID_IF(!IsAITest(), "AI_LOG is usable only in AI_SINGLE_BATTLE_TEST, AI_DOUBLE_BATTLE_TEST, AI_MULTI_BATTLE_TEST, and AI_TWO_VS_ONE_TEST"); DATA.logAI = TRUE; } @@ -1515,6 +1807,9 @@ const struct TestRunner gBattleTestRunner = .tearDown = BattleTest_TearDown, .checkProgress = BattleTest_CheckProgress, .handleExitWithResult = BattleTest_HandleExitWithResult, + .randomUniform = BattleTest_RandomUniform, + .randomWeightedArray = BattleTest_RandomWeightedArray, + .randomElementArray = BattleTest_RandomElementArray, }; void SetFlagForTest(u32 sourceLine, u16 flagId) @@ -1524,10 +1819,10 @@ void SetFlagForTest(u32 sourceLine, u16 flagId) FlagSet(flagId); } -void TestSetConfig(u32 sourceLine, enum GenConfigTag configTag, u32 value) +void TestSetConfig(u32 sourceLine, enum ConfigTag configTag, u32 value) { INVALID_IF(!STATE->runGiven, "WITH_CONFIG outside of GIVEN"); - SetGenConfig(configTag, value); + SetConfig(configTag, value); } void ClearFlagAfterTest(void) @@ -1539,14 +1834,14 @@ void ClearFlagAfterTest(void) } } -void OpenPokemon(u32 sourceLine, u32 side, u32 species) +void OpenPokemon(u32 sourceLine, enum BattlerPosition position, u32 species) { s32 i, data; u8 *partySize; struct Pokemon *party; INVALID_IF(species >= SPECIES_EGG, "Invalid species: %d", species); ASSUMPTION_FAIL_IF(!IsSpeciesEnabled(species), "Species disabled: %d", species); - if (side == B_SIDE_PLAYER) + if ((position & BIT_SIDE) == B_SIDE_PLAYER) { partySize = &DATA.playerPartySize; party = DATA.recordedBattle.playerParty; @@ -1557,13 +1852,67 @@ void OpenPokemon(u32 sourceLine, u32 side, u32 species) party = DATA.recordedBattle.opponentParty; } INVALID_IF(*partySize >= PARTY_SIZE, "Too many Pokemon in party"); - DATA.currentSide = side; + DATA.currentPosition = position; DATA.currentPartyIndex = *partySize; DATA.currentMon = &party[DATA.currentPartyIndex]; DATA.gender = 0xFF; // Male DATA.nature = NATURE_HARDY; (*partySize)++; + CreateMon(DATA.currentMon, species, 100, 0, TRUE, 0, OT_ID_PRESET, 0); + data = MOVE_NONE; + for (i = 0; i < MAX_MON_MOVES; i++) + SetMonData(DATA.currentMon, MON_DATA_MOVE1 + i, &data); + data = 0; + if (B_FRIENDSHIP_BOOST) + { + // This way, we avoid the boost affecting tests unless explicitly stated. + SetMonData(DATA.currentMon, MON_DATA_FRIENDSHIP, &data); + CalculateMonStats(DATA.currentMon); + } +} + +void OpenPokemonMulti(u32 sourceLine, enum BattlerPosition position, u32 species) +{ + + s32 i, data; + u8 *partySize; + struct Pokemon *party; + INVALID_IF(species >= SPECIES_EGG, "Invalid species: %d", species); + ASSUMPTION_FAIL_IF(!IsSpeciesEnabled(species), "Species disabled: %d", species); + if (position == B_POSITION_PLAYER_LEFT) // MULTI_PLAYER + { + partySize = &DATA.playerPartySize; + party = DATA.recordedBattle.playerParty; + } + else if (position == B_POSITION_PLAYER_RIGHT) // MULTI_PARTNER + { + partySize = &DATA.playerPartySize; + if ((*partySize == 0) || (*partySize == 1) || (*partySize == 2)) + *partySize = 3; + party = DATA.recordedBattle.playerParty; + } + else if (position == B_POSITION_OPPONENT_LEFT) // MULTI_OPPONENT_A + { + partySize = &DATA.opponentPartySize; + party = DATA.recordedBattle.opponentParty; + } + else // MULTI_OPPONENT_B + { + partySize = &DATA.opponentPartySize; + if ((*partySize == 0) || (*partySize == 1) || (*partySize == 2)) + *partySize = 3; + party = DATA.recordedBattle.opponentParty; + } + INVALID_IF(*partySize >= PARTY_SIZE, "Too many Pokemon in party"); + DATA.currentPosition = position; + DATA.currentPartyIndex = *partySize; + DATA.currentMon = &party[DATA.currentPartyIndex]; + DATA.gender = 0xFF; // Male + DATA.nature = NATURE_HARDY; + DATA.isShiny = FALSE; + (*partySize)++; + CreateMon(DATA.currentMon, species, 100, 0, TRUE, 0, OT_ID_PRESET, 0); // Reset move IDs, but force PP to be non-zero. This is a safeguard against test species that only learn 1 move having test moves with 0 PP for (i = 0; i < MAX_MON_MOVES; i++) @@ -1607,21 +1956,32 @@ void ClosePokemon(u32 sourceLine) { s32 i; u32 data; - INVALID_IF(DATA.hasExplicitSpeeds && !(DATA.explicitSpeeds[DATA.currentSide] & (1 << DATA.currentPartyIndex)), "Speed required"); + INVALID_IF(DATA.hasExplicitSpeeds && !(DATA.explicitSpeeds[DATA.currentPosition] & (1 << DATA.currentPartyIndex)), "Speed required"); for (i = 0; i < STATE->battlersCount; i++) { - if ((i & BIT_SIDE) == DATA.currentSide + if (i == DATA.currentPosition && DATA.currentMonIndexes[i] == DATA.currentPartyIndex) { INVALID_IF(GetMonData(DATA.currentMon, MON_DATA_HP) == 0, "Battlers cannot be fainted"); } } - data = FALSE; - SetMonData(DATA.currentMon, MON_DATA_IS_SHINY, &data); UpdateMonPersonality(&DATA.currentMon->box, GenerateNature(DATA.nature, DATA.gender % NUM_NATURES) | DATA.gender); + data = DATA.isShiny; + SetMonData(DATA.currentMon, MON_DATA_IS_SHINY, &data); DATA.currentMon = NULL; } +static void SetGimmick(u32 sourceLine, u32 side, u32 partyIndex, enum Gimmick gimmick) +{ + enum Gimmick currentGimmick = DATA.chosenGimmick[side][partyIndex]; + if (!((currentGimmick == GIMMICK_ULTRA_BURST && gimmick == GIMMICK_Z_MOVE) + || (currentGimmick == GIMMICK_Z_MOVE && gimmick == GIMMICK_ULTRA_BURST))) + { + INVALID_IF(currentGimmick != GIMMICK_NONE && currentGimmick != gimmick, "Cannot set %s because %s already set", sGimmickIdentifiers[gimmick], sGimmickIdentifiers[currentGimmick]); + } + DATA.chosenGimmick[side][partyIndex] = gimmick; +} + void Gender_(u32 sourceLine, u32 gender) { const struct SpeciesInfo *info; @@ -1650,7 +2010,7 @@ void Nature_(u32 sourceLine, u32 nature) DATA.nature = nature; } -void Ability_(u32 sourceLine, u32 ability) +void Ability_(u32 sourceLine, enum Ability ability) { s32 i; u32 species; @@ -1670,7 +2030,7 @@ void Ability_(u32 sourceLine, u32 ability) // Store forced ability to be set when the battle starts if invalid. if (i == NUM_ABILITY_SLOTS) { - DATA.forcedAbilities[DATA.currentSide][DATA.currentPartyIndex] = ability; + DATA.forcedAbilities[DATA.currentPosition][DATA.currentPartyIndex] = ability; } } @@ -1748,7 +2108,7 @@ void Speed_(u32 sourceLine, u32 speed) bool32 hyperTrainingFlag = TRUE; SetMonData(DATA.currentMon, MON_DATA_HYPER_TRAINED_SPEED, &hyperTrainingFlag); DATA.hasExplicitSpeeds = TRUE; - DATA.explicitSpeeds[DATA.currentSide] |= 1 << DATA.currentPartyIndex; + DATA.explicitSpeeds[DATA.currentPosition] |= 1 << DATA.currentPartyIndex; } void HPIV_(u32 sourceLine, u32 hpIV) @@ -1798,6 +2158,17 @@ void Item_(u32 sourceLine, u32 item) INVALID_IF(!DATA.currentMon, "Item outside of PLAYER/OPPONENT"); INVALID_IF(item >= ITEMS_COUNT, "Illegal item: %d", item); SetMonData(DATA.currentMon, MON_DATA_HELD_ITEM, &item); + switch (GetItemHoldEffect(item)) + { + case HOLD_EFFECT_MEGA_STONE: + SetGimmick(sourceLine, DATA.currentPosition, DATA.currentPartyIndex, GIMMICK_MEGA); + break; + case HOLD_EFFECT_Z_CRYSTAL: + SetGimmick(sourceLine, DATA.currentPosition, DATA.currentPartyIndex, GIMMICK_Z_MOVE); + break; + default: + break; + } } void Moves_(u32 sourceLine, u16 moves[MAX_MON_MOVES]) @@ -1813,7 +2184,7 @@ void Moves_(u32 sourceLine, u16 moves[MAX_MON_MOVES]) u32 pp = GetMovePP(moves[i]); SetMonData(DATA.currentMon, MON_DATA_PP1 + i, &pp); } - DATA.explicitMoves[DATA.currentSide] |= 1 << DATA.currentPartyIndex; + DATA.explicitMoves[DATA.currentPosition] |= 1 << DATA.currentPartyIndex; } void MovesWithPP_(u32 sourceLine, struct moveWithPP moveWithPP[MAX_MON_MOVES]) @@ -1828,7 +2199,7 @@ void MovesWithPP_(u32 sourceLine, struct moveWithPP moveWithPP[MAX_MON_MOVES]) SetMonData(DATA.currentMon, MON_DATA_MOVE1 + i, &moveWithPP[i].moveId); SetMonData(DATA.currentMon, MON_DATA_PP1 + i, &moveWithPP[i].pp); } - DATA.explicitMoves[DATA.currentSide] |= 1 << DATA.currentPartyIndex; + DATA.explicitMoves[DATA.currentPosition] |= 1 << DATA.currentPartyIndex; } void Friendship_(u32 sourceLine, u32 friendship) @@ -1854,18 +2225,21 @@ void DynamaxLevel_(u32 sourceLine, u32 dynamaxLevel) { INVALID_IF(!DATA.currentMon, "DynamaxLevel outside of PLAYER/OPPONENT"); SetMonData(DATA.currentMon, MON_DATA_DYNAMAX_LEVEL, &dynamaxLevel); + SetGimmick(sourceLine, DATA.currentPosition, DATA.currentPartyIndex, GIMMICK_DYNAMAX); } void GigantamaxFactor_(u32 sourceLine, bool32 gigantamaxFactor) { INVALID_IF(!DATA.currentMon, "GigantamaxFactor outside of PLAYER/OPPONENT"); SetMonData(DATA.currentMon, MON_DATA_GIGANTAMAX_FACTOR, &gigantamaxFactor); + SetGimmick(sourceLine, DATA.currentPosition, DATA.currentPartyIndex, GIMMICK_DYNAMAX); } -void TeraType_(u32 sourceLine, u32 teraType) +void TeraType_(u32 sourceLine, enum Type teraType) { INVALID_IF(!DATA.currentMon, "TeraType outside of PLAYER/OPPONENT"); SetMonData(DATA.currentMon, MON_DATA_TERA_TYPE, &teraType); + SetGimmick(sourceLine, DATA.currentPosition, DATA.currentPartyIndex, GIMMICK_TERA); } void Shadow_(u32 sourceLine, bool32 isShadow) @@ -1874,6 +2248,19 @@ void Shadow_(u32 sourceLine, bool32 isShadow) SetMonData(DATA.currentMon, MON_DATA_IS_SHADOW, &isShadow); } +void Shiny_(u32 sourceLine, bool32 isShiny) +{ + INVALID_IF(!DATA.currentMon, "Shiny outside of PLAYER/OPPONENT"); + DATA.isShiny = isShiny; +} + +void Environment_(u32 sourceLine, u32 environment) +{ + INVALID_IF(DATA.forcedEnvironment, "Environment is already set"); + INVALID_IF(environment >= BATTLE_ENVIRONMENT_COUNT, "Illegal environment: %d", environment); + DATA.forcedEnvironment = environment + 1; +} + static const char *const sBattlerIdentifiersSingles[] = { "player", @@ -1899,6 +2286,12 @@ static const char *BattlerIdentifier(s32 battlerId) return sBattlerIdentifiersSingles[battlerId]; case BATTLE_TEST_DOUBLES: case BATTLE_TEST_AI_DOUBLES: + case BATTLE_TEST_MULTI: + case BATTLE_TEST_AI_MULTI: + case BATTLE_TEST_TWO_VS_ONE: + case BATTLE_TEST_AI_TWO_VS_ONE: + case BATTLE_TEST_ONE_VS_TWO: + case BATTLE_TEST_AI_ONE_VS_TWO: return sBattlerIdentifiersDoubles[battlerId]; } return ""; @@ -2039,7 +2432,7 @@ void CloseTurn(u32 sourceLine) for (i = 0; i < STATE->battlersCount; i++) { if (!(DATA.actionBattlers & (1 << i))) - { + { // Multi test partner trainers want setting to RecordedPartner controller if no move set in this case. if (IsAITest() && (i & BIT_SIDE) == B_SIDE_OPPONENT) // If Move was not specified, allow any move used. SetAiActionToPass(sourceLine, i); else @@ -2053,7 +2446,7 @@ void CloseTurn(u32 sourceLine) static struct Pokemon *CurrentMon(s32 battlerId) { struct Pokemon *party; - if ((battlerId & BIT_SIDE) == B_SIDE_PLAYER) + if (battlerId == B_POSITION_PLAYER_LEFT || battlerId == B_POSITION_PLAYER_RIGHT) party = DATA.recordedBattle.playerParty; else party = DATA.recordedBattle.opponentParty; @@ -2129,7 +2522,7 @@ void MoveGetIdAndSlot(s32 battlerId, struct MoveContext *ctx, u32 *moveId, u32 * INVALID_IF(DATA.explicitMoves[battlerId & BIT_SIDE] & (1 << DATA.currentMonIndexes[battlerId]), "Missing explicit %S", GetMoveName(ctx->move)); SetMonData(mon, MON_DATA_MOVE1 + i, &ctx->move); u32 pp = GetMovePP(ctx->move); - SetMonData(DATA.currentMon, MON_DATA_PP1 + i, &pp); + SetMonData(mon, MON_DATA_PP1 + i, &pp); *moveSlot = i; *moveId = ctx->move; INVALID_IF(GetMovePP(ctx->move) == 0, "%S has 0 PP!", GetMoveName(ctx->move)); @@ -2152,7 +2545,7 @@ void MoveGetIdAndSlot(s32 battlerId, struct MoveContext *ctx, u32 *moveId, u32 * if (ctx->explicitGimmick && ctx->gimmick != GIMMICK_NONE) { u32 item = GetMonData(mon, MON_DATA_HELD_ITEM); - enum ItemHoldEffect holdEffect = GetItemHoldEffect(item); + enum HoldEffect holdEffect = GetItemHoldEffect(item); u32 species = GetMonData(mon, MON_DATA_SPECIES); u32 side = battlerId & BIT_SIDE; @@ -2167,11 +2560,7 @@ void MoveGetIdAndSlot(s32 battlerId, struct MoveContext *ctx, u32 *moveId, u32 * INVALID_IF(ctx->gimmick != GIMMICK_Z_MOVE && ctx->gimmick != GIMMICK_ULTRA_BURST && holdEffect == HOLD_EFFECT_Z_CRYSTAL, "Cannot use another gimmick while holding a Z-Crystal"); // Check multiple gimmick use. - INVALID_IF(DATA.chosenGimmick[side][DATA.currentMonIndexes[battlerId]] != GIMMICK_NONE - && !(DATA.chosenGimmick[side][DATA.currentMonIndexes[battlerId]] == GIMMICK_ULTRA_BURST - && ctx->gimmick == GIMMICK_Z_MOVE), "Cannot use multiple gimmicks on the same battler"); - - DATA.chosenGimmick[side][DATA.currentMonIndexes[battlerId]] = ctx->gimmick; + SetGimmick(sourceLine, side, DATA.currentMonIndexes[battlerId], ctx->gimmick); *moveSlot |= RET_GIMMICK; } } @@ -2295,17 +2684,18 @@ static void TryMarkExpectMove(u32 sourceLine, struct BattlePokemon *battler, str s32 target; INVALID_IF(DATA.turnState == TURN_CLOSED, "EXPECT_MOVE outside TURN"); - INVALID_IF(!IsAITest(), "EXPECT_MOVE is usable only in AI_SINGLE_BATTLE_TEST & AI_DOUBLE_BATTLE_TEST"); + INVALID_IF(!IsAITest(), "EXPECT_MOVE is usable only in AI_SINGLE_BATTLE_TEST, AI_DOUBLE_BATTLE_TEST, AI_MULTI_BATTLE_TEST, and AI_TWO_VS_ONE_TEST"); MoveGetIdAndSlot(battlerId, ctx, &moveId, &moveSlot, sourceLine); target = MoveGetTarget(battlerId, moveId, ctx, sourceLine); id = DATA.expectedAiActionIndex[battlerId]; DATA.expectedAiActions[battlerId][id].type = B_ACTION_USE_MOVE; - DATA.expectedAiActions[battlerId][id].moveSlots |= 1 << moveSlot; + DATA.expectedAiActions[battlerId][id].moveSlots |= 1 << (moveSlot & ~RET_GIMMICK); DATA.expectedAiActions[battlerId][id].target = target; DATA.expectedAiActions[battlerId][id].explicitTarget = ctx->explicitTarget; DATA.expectedAiActions[battlerId][id].sourceLine = sourceLine; DATA.expectedAiActions[battlerId][id].actionSet = TRUE; + DATA.expectedAiActions[battlerId][id].gimmick = ctx->explicitGimmick ? ctx->gimmick : GIMMICKS_COUNT; if (ctx->explicitNotExpected) DATA.expectedAiActions[battlerId][id].notMove = ctx->notExpected; @@ -2325,7 +2715,7 @@ void ExpectSendOut(u32 sourceLine, struct BattlePokemon *battler, u32 partyIndex s32 i, id; s32 battlerId = battler - gBattleMons; INVALID_IF(DATA.turnState == TURN_CLOSED, "EXPECT_SEND_OUT outside TURN"); - INVALID_IF(!IsAITest(), "EXPECT_SEND_OUT is usable only in AI_SINGLE_BATTLE_TEST & AI_DOUBLE_BATTLE_TEST"); + INVALID_IF(!IsAITest(), "EXPECT_SEND_OUT is usable only in AI_SINGLE_BATTLE_TEST, AI_DOUBLE_BATTLE_TEST, AI_MULTI_BATTLE_TEST, AI_TWO_VS_ONE_TEST, and AI_ONE_VS_TWO_TEST"); INVALID_IF(partyIndex >= ((battlerId & BIT_SIDE) == B_SIDE_PLAYER ? DATA.playerPartySize : DATA.opponentPartySize), "EXPECT_SEND_OUT to invalid party index"); for (i = 0; i < STATE->battlersCount; i++) { @@ -2333,8 +2723,9 @@ void ExpectSendOut(u32 sourceLine, struct BattlePokemon *battler, u32 partyIndex INVALID_IF(DATA.currentMonIndexes[i] == partyIndex, "EXPECT_SEND_OUT to battler"); } if (!(DATA.actionBattlers & (1 << battlerId))) - { - if (IsAITest() && (battlerId & BIT_SIDE) == B_SIDE_OPPONENT) // If Move was not specified, allow any move used. + { // Multi test partner trainers want setting to PlayerPartner controller even if no move set in this case. + if (IsAITest() && (((battlerId & BIT_SIDE) == B_SIDE_OPPONENT) // If Move was not specified, allow any move used. + || (IsMultibattleTest() && battlerId == B_POSITION_PLAYER_RIGHT))) SetAiActionToPass(sourceLine, battlerId); else Move(sourceLine, battler, (struct MoveContext) { move: MOVE_CELEBRATE, explicitMove: TRUE }); @@ -2377,7 +2768,7 @@ void Score(u32 sourceLine, struct BattlePokemon *battler, u32 cmp, bool32 toValu s32 battlerId = battler - gBattleMons; s32 turn = DATA.turns; - INVALID_IF(!IsAITest(), "SCORE_%s%s is usable only in AI_SINGLE_BATTLE_TEST & AI_DOUBLE_BATTLE_TEST", sCmpToStringTable[cmp], (toValue == TRUE) ? "_VAL" : ""); + INVALID_IF(!IsAITest(), "SCORE_%s%s is usable only in AI_SINGLE_BATTLE_TEST, AI_DOUBLE_BATTLE_TEST, AI_MULTI_BATTLE_TEST, & AI_TWO_VS_ONE_TEST", sCmpToStringTable[cmp], (toValue == TRUE) ? "_VAL" : ""); for (i = 0; i < MAX_AI_SCORE_COMPARISION_PER_TURN; i++) { @@ -2461,7 +2852,7 @@ void ExpectSwitch(u32 sourceLine, struct BattlePokemon *battler, u32 partyIndex) s32 i, id; s32 battlerId = battler - gBattleMons; INVALID_IF(DATA.turnState == TURN_CLOSED, "EXPECT_SWITCH outside TURN"); - INVALID_IF(!IsAITest(), "EXPECT_SWITCH is usable only in AI_SINGLE_BATTLE_TEST & AI_DOUBLE_BATTLE_TEST"); + INVALID_IF(!IsAITest(), "EXPECT_SWITCH is usable only in AI_SINGLE_BATTLE_TEST, AI_DOUBLE_BATTLE_TEST, AI_MULTI_BATTLE_TEST, AI_TWO_VS_ONE_TEST, and AI_ONE_VS_TWO_TEST"); INVALID_IF(DATA.actionBattlers & (1 << battlerId), "Multiple battler actions"); INVALID_IF(partyIndex >= ((battlerId & BIT_SIDE) == B_SIDE_PLAYER ? DATA.playerPartySize : DATA.opponentPartySize), "EXPECT_SWITCH to invalid party index"); @@ -2583,7 +2974,6 @@ void CloseQueueGroup(u32 sourceLine) void QueueAbility(u32 sourceLine, struct BattlePokemon *battler, struct AbilityEventContext ctx) { -#if B_ABILITY_POP_UP s32 battlerId = battler - gBattleMons; INVALID_IF(!STATE->runScene, "ABILITY_POPUP outside of SCENE"); if (DATA.queuedEventsCount == MAX_QUEUED_EVENTS) @@ -2598,7 +2988,6 @@ void QueueAbility(u32 sourceLine, struct BattlePokemon *battler, struct AbilityE .ability = ctx.ability, }}, }; -#endif } void QueueAnimation(u32 sourceLine, u32 type, u32 id, struct AnimationEventContext ctx) @@ -2687,6 +3076,46 @@ void QueueHP(u32 sourceLine, struct BattlePokemon *battler, struct HPEventContex }; } +void QueueSubHit(u32 sourceLine, struct BattlePokemon *battler, struct SubHitEventContext ctx) +{ + s32 battlerId = battler - gBattleMons; + bool32 breakSub = FALSE; + bool32 checkBreak = FALSE; + uintptr_t address; + + INVALID_IF(!STATE->runScene, "SUB_HIT outside of SCENE"); + if (DATA.queuedEventsCount == MAX_QUEUED_EVENTS) + Test_ExitWithResult(TEST_RESULT_ERROR, sourceLine, ":L%s:%d: SUB_HIT exceeds MAX_QUEUED_EVENTS", gTestRunnerState.test->filename, sourceLine); + + address = 0; + if (ctx.explicitCaptureDamage) + { + INVALID_IF(ctx.captureDamage == NULL, "captureDamage is NULL"); + *ctx.captureDamage = 0; + address = (uintptr_t)ctx.captureDamage; + } + + if (ctx.explicitSubBreak) + { + checkBreak = TRUE; + if (ctx.subBreak) + breakSub = TRUE; + } + + DATA.queuedEvents[DATA.queuedEventsCount++] = (struct QueuedEvent) { + .type = QUEUED_SUB_HIT_EVENT, + .sourceLineOffset = SourceLineOffset(sourceLine), + .groupType = QUEUE_GROUP_NONE, + .groupSize = 1, + .as = { .subHit = { + .battlerId = battlerId, + .checkBreak = checkBreak, + .breakSub = breakSub, + .address = address, + }}, + }; +} + void QueueExp(u32 sourceLine, struct BattlePokemon *battler, struct ExpEventContext ctx) { s32 battlerId = battler - gBattleMons; @@ -2795,6 +3224,11 @@ u32 TestRunner_Battle_GetForcedAbility(u32 side, u32 partyIndex) return DATA.forcedAbilities[side][partyIndex]; } +u32 TestRunner_Battle_GetForcedEnvironment(void) +{ + return DATA.forcedEnvironment; +} + u32 TestRunner_Battle_GetChosenGimmick(u32 side, u32 partyIndex) { return DATA.chosenGimmick[side][partyIndex]; diff --git a/test/text.c b/test/text.c index cb5b82ca46..05e9ca1ffd 100644 --- a/test/text.c +++ b/test/text.c @@ -499,7 +499,7 @@ TEST("Ability names fit on Pokemon Summary Screen") { u32 i; const u32 fontId = FONT_NORMAL, widthPx = 144; - u32 ability = ABILITY_NONE; + enum Ability ability = ABILITY_NONE; for (i = 1; i < ABILITIES_COUNT; i++) { PARAMETRIZE_LABEL("%S", gAbilitiesInfo[i].name) { ability = i; } @@ -511,7 +511,7 @@ TEST("Ability names fit on Ability Pop-Up") { u32 i; const u32 fontId = FONT_SMALL_NARROWER, widthPx = 76; - u32 ability = ABILITY_NONE; + enum Ability ability = ABILITY_NONE; for (i = 1; i < ABILITIES_COUNT; i++) { PARAMETRIZE_LABEL("%S", gAbilitiesInfo[i].name) { ability = i; } @@ -523,7 +523,7 @@ TEST("Ability descriptions fit on Pokemon Summary Screen") { u32 i; const u32 fontId = FONT_NORMAL, widthPx = 146; - u32 ability = ABILITY_NONE; + enum Ability ability = ABILITY_NONE; for (i = 1; i < ABILITIES_COUNT; i++) { PARAMETRIZE_LABEL("%S", gAbilitiesInfo[i].description) { ability = i; } @@ -535,7 +535,7 @@ TEST("Type names fit on Battle Screen") { u32 i; const u32 fontId = FONT_NARROWER, widthPx = 39; - u32 type = TYPE_NORMAL; + enum Type type = TYPE_NORMAL; for (i = 0; i < NUMBER_OF_MON_TYPES; i++) { PARAMETRIZE_LABEL("%S", gTypesInfo[i].name) { type = i; } @@ -547,7 +547,7 @@ TEST("Type names fit on Pokedex Search Screen") { u32 i; const u32 fontId = FONT_NARROWER, widthPx = 38; - u32 type = TYPE_NORMAL; + enum Type type = TYPE_NORMAL; for (i = 0; i < NUMBER_OF_MON_TYPES; i++) { PARAMETRIZE_LABEL("%S", gTypesInfo[i].name) { type = i; } @@ -570,9 +570,9 @@ TEST("Battle strings fit on the battle message window") s32 sixDigitNines = 999999; // 36 pixels. u8 nickname[POKEMON_NAME_LENGTH + 1] = _("MMMMMMMMMMMM"); // 72 pixels. u32 longMoveID = MOVE_NATURES_MADNESS; // 89 pixels. - u32 longAbilityID = ABILITY_SUPERSWEET_SYRUP; // 91 pixels. + enum Ability longAbilityID = ABILITY_SUPERSWEET_SYRUP; // 91 pixels. u32 longStatName = STAT_EVASION; // 40 pixels. - u32 longTypeName = TYPE_ELECTRIC; // 43 pixels. + enum Type longTypeName = TYPE_ELECTRIC; // 43 pixels. u32 longSpeciesName = SPECIES_SANDY_SHOCKS; // 47 pixels. u32 longItemName = ITEM_UNREMARKABLE_TEACUP; // 73 pixels. u8 boxName[9] = _("MMMMMMMM"); // 54 pixels. @@ -663,8 +663,6 @@ TEST("Battle strings fit on the battle message window") break; // Buffer Move name to B_BUFF1 case STRINGID_PKMNLEARNEDMOVE2: - case STRINGID_TEAMSTOPPEDWORKING: // Unused - case STRINGID_FOESTOPPEDWORKING: // Unused case STRINGID_PKMNHURTBY: case STRINGID_PKMNFREEDFROM: case STRINGID_PKMNMOVEWASDISABLED: @@ -715,8 +713,6 @@ TEST("Battle strings fit on the battle message window") case STRINGID_ATTACKERABILITYSTATRAISE: case STRINGID_TARGETABILITYSTATLOWER: case STRINGID_SCRIPTINGABILITYSTATRAISE: - case STRINGID_BATTLERABILITYRAISEDSTAT: - case STRINGID_ABILITYRAISEDSTATDRASTICALLY: case STRINGID_STATWASHEIGHTENED: StringCopy(gBattleTextBuff1, gStatNamesTable[longStatName]); break; @@ -758,7 +754,6 @@ TEST("Battle strings fit on the battle message window") case STRINGID_PKMNCURIOUSABOUTX: case STRINGID_PKMNENTHRALLEDBYX: case STRINGID_PKMNIGNOREDX: - case STRINGID_PREVENTEDFROMWORKING: case STRINGID_PKMNOBTAINEDX: case STRINGID_ABOUTTOUSEPOLTERGEIST: PREPARE_ITEM_BUFFER(gBattleTextBuff1, longItemName); diff --git a/tools/aif2pcm/.gitignore b/tools/aif2pcm/.gitignore deleted file mode 100644 index 31531797e7..0000000000 --- a/tools/aif2pcm/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -aif2pcm - diff --git a/tools/aif2pcm/Makefile b/tools/aif2pcm/Makefile deleted file mode 100644 index dd48a87597..0000000000 --- a/tools/aif2pcm/Makefile +++ /dev/null @@ -1,24 +0,0 @@ -CC ?= gcc - -CFLAGS = -Wall -Wextra -Wno-switch -Werror -std=c11 -O2 - -LIBS = -lm - -SRCS = main.c extended.c - -ifeq ($(OS),Windows_NT) -EXE := .exe -else -EXE := -endif - -.PHONY: all clean - -all: aif2pcm$(EXE) - @: - -aif2pcm$(EXE): $(SRCS) - $(CC) $(CFLAGS) $(SRCS) -o $@ $(LDFLAGS) $(LIBS) - -clean: - $(RM) aif2pcm aif2pcm.exe diff --git a/tools/aif2pcm/aif2pcm b/tools/aif2pcm/aif2pcm new file mode 100644 index 0000000000..5fdc78e161 Binary files /dev/null and b/tools/aif2pcm/aif2pcm differ diff --git a/tools/aif2pcm/extended.c b/tools/aif2pcm/extended.c deleted file mode 100644 index 94449164bd..0000000000 --- a/tools/aif2pcm/extended.c +++ /dev/null @@ -1,172 +0,0 @@ -/* $Id: extended.c,v 1.8 2006/12/23 11:17:49 toad32767 Exp $ */ -/*- - * Copyright (c) 2005, 2006 by Marco Trillo - * - * Permission is hereby granted, free of charge, to any - * person obtaining a copy of this software and associated - * documentation files (the "Software"), to deal in the - * Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the - * Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice - * shall be included in all copies or substantial portions of - * the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY - * KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE - * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS - * OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -#include -#include -#include - -/* - * Infinite & NAN values - * for non-IEEE systems - */ -#ifndef HUGE_VAL -#ifdef HUGE -#define INFINITE_VALUE HUGE -#define NAN_VALUE HUGE -#endif -#else -#define INFINITE_VALUE HUGE_VAL -#define NAN_VALUE HUGE_VAL -#endif - -/* - * IEEE 754 Extended Precision - * - * Implementation here is the 80-bit extended precision - * format of Motorola 68881, Motorola 68882 and Motorola - * 68040 FPUs, as well as Intel 80x87 FPUs. - * - * See: - * http://www.freescale.com/files/32bit/doc/fact_sheet/BR509.pdf - */ -/* - * Exponent range: [-16383,16383] - * Precision for mantissa: 64 bits with no hidden bit - * Bias: 16383 - */ - -/* - * Write IEEE Extended Precision Numbers - */ -void -ieee754_write_extended(double in, uint8_t* out) -{ - int sgn, exp, shift; - double fraction, t; - unsigned int lexp, hexp; - unsigned long low, high; - - if (in == 0.0) { - memset(out, 0, 10); - return; - } - if (in < 0.0) { - in = fabs(in); - sgn = 1; - } else - sgn = 0; - - fraction = frexp(in, &exp); - - if (exp == 0 || exp > 16384) { - if (exp > 16384) /* infinite value */ - low = high = 0; - else { - low = 0x80000000; - high = 0; - } - exp = 32767; - goto done; - } - fraction = ldexp(fraction, 32); - t = floor(fraction); - low = (unsigned long) t; - fraction -= t; - t = floor(ldexp(fraction, 32)); - high = (unsigned long) t; - - /* Convert exponents < -16382 to -16382 (then they will be - * stored as -16383) */ - if (exp < -16382) { - shift = 0 - exp - 16382; - high >>= shift; - high |= (low << (32 - shift)); - low >>= shift; - exp = -16382; - } - exp += 16383 - 1; /* bias */ - -done: - lexp = ((unsigned int) exp) >> 8; - hexp = ((unsigned int) exp) & 0xFF; - - /* big endian */ - out[0] = ((uint8_t) sgn) << 7; - out[0] |= (uint8_t) lexp; - out[1] = (uint8_t) hexp; - out[2] = (uint8_t) (low >> 24); - out[3] = (uint8_t) ((low >> 16) & 0xFF); - out[4] = (uint8_t) ((low >> 8) & 0xFF); - out[5] = (uint8_t) (low & 0xFF); - out[6] = (uint8_t) (high >> 24); - out[7] = (uint8_t) ((high >> 16) & 0xFF); - out[8] = (uint8_t) ((high >> 8) & 0xFF); - out[9] = (uint8_t) (high & 0xFF); - - return; -} - - -/* - * Read IEEE Extended Precision Numbers - */ -double -ieee754_read_extended(uint8_t* in) -{ - int sgn, exp; - unsigned long low, high; - double out; - - /* Extract the components from the big endian buffer */ - sgn = (int) (in[0] >> 7); - exp = ((int) (in[0] & 0x7F) << 8) | ((int) in[1]); - low = (((unsigned long) in[2]) << 24) - | (((unsigned long) in[3]) << 16) - | (((unsigned long) in[4]) << 8) | (unsigned long) in[5]; - high = (((unsigned long) in[6]) << 24) - | (((unsigned long) in[7]) << 16) - | (((unsigned long) in[8]) << 8) | (unsigned long) in[9]; - - if (exp == 0 && low == 0 && high == 0) - return (sgn ? -0.0 : 0.0); - - switch (exp) { - case 32767: - if (low == 0 && high == 0) - return (sgn ? -INFINITE_VALUE : INFINITE_VALUE); - else - return (sgn ? -NAN_VALUE : NAN_VALUE); - default: - exp -= 16383; /* unbias exponent */ - - } - - out = ldexp((double) low, -31 + exp); - out += ldexp((double) high, -63 + exp); - - return (sgn ? -out : out); -} diff --git a/tools/aif2pcm/main.c b/tools/aif2pcm/main.c deleted file mode 100644 index 0824b92da8..0000000000 --- a/tools/aif2pcm/main.c +++ /dev/null @@ -1,945 +0,0 @@ -// Copyright(c) 2016 huderlem -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -#include -#include -#include -#include -#include -#include - -/* extended.c */ -void ieee754_write_extended (double, uint8_t*); -double ieee754_read_extended (uint8_t*); - -#ifdef _MSC_VER - -#define FATAL_ERROR(format, ...) \ -do \ -{ \ - fprintf(stderr, format, __VA_ARGS__); \ - exit(1); \ -} while (0) - -#else - -#define FATAL_ERROR(format, ...) \ -do \ -{ \ - fprintf(stderr, format, ##__VA_ARGS__); \ - exit(1); \ -} while (0) - -#endif // _MSC_VER - -typedef struct { - unsigned long num_samples; - union { - uint8_t *samples8; - uint16_t *samples16; - }; - uint8_t midi_note; - uint8_t sample_size; - bool has_loop; - unsigned long loop_offset; - double sample_rate; - unsigned long real_num_samples; -} AifData; - -struct Bytes { - unsigned long length; - uint8_t *data; -}; - -struct Marker { - unsigned short id; - unsigned long position; - // don't care about the name -}; - -struct Bytes *read_bytearray(const char *filename) -{ - struct Bytes *bytes = malloc(sizeof(struct Bytes)); - FILE *f = fopen(filename, "rb"); - if (!f) - { - FATAL_ERROR("Failed to open '%s' for reading!\n", filename); - } - fseek(f, 0, SEEK_END); - bytes->length = ftell(f); - fseek(f, 0, SEEK_SET); - bytes->data = malloc(bytes->length); - unsigned long read = fread(bytes->data, bytes->length, 1, f); - fclose(f); - if (read <= 0) - { - FATAL_ERROR("Failed to read data from '%s'!\n", filename); - } - return bytes; -} - -void write_bytearray(const char *filename, struct Bytes *bytes) -{ - FILE *f = fopen(filename, "wb"); - if (!f) - { - FATAL_ERROR("Failed to open '%s' for writing!\n", filename); - } - fwrite(bytes->data, bytes->length, 1, f); - fclose(f); -} - -void free_bytearray(struct Bytes *bytes) -{ - free(bytes->data); - free(bytes); -} - -char *get_file_extension(char *filename) -{ - char *index = strrchr(filename, '.'); - if (!index || index == filename) - { - return NULL; - } - return index + 1; -} - -char *new_file_extension(char *filename, char *ext) -{ - char *index = strrchr(filename, '.'); - if (!index || index == filename) - { - index = filename + strlen(filename); - } - int length = index - filename; - char *new_filename = malloc(length + 1 + strlen(ext) + 1); - if (new_filename) - { - strcpy(new_filename, filename); - new_filename[length] = '.'; - strcpy(new_filename + length + 1, ext); - } - return new_filename; -} - -void read_aif(struct Bytes *aif, AifData *aif_data) -{ - aif_data->has_loop = false; - aif_data->num_samples = 0; - - unsigned long pos = 0; - char chunk_name[5]; chunk_name[4] = '\0'; - char chunk_type[5]; chunk_type[4] = '\0'; - - // Check for FORM Chunk - memcpy(chunk_name, &aif->data[pos], 4); - pos += 4; - if (strcmp(chunk_name, "FORM") != 0) - { - FATAL_ERROR("Input .aif file has invalid header Chunk '%s'!\n", chunk_name); - } - - // Read size of whole file. - unsigned long whole_chunk_size = aif->data[pos++] << 24; - whole_chunk_size |= (aif->data[pos++] << 16); - whole_chunk_size |= (aif->data[pos++] << 8); - whole_chunk_size |= (uint8_t)aif->data[pos++]; - - unsigned long expected_whole_chunk_size = aif->length - 8; - if (whole_chunk_size != expected_whole_chunk_size) - { - FATAL_ERROR("FORM Chunk ckSize '%lu' doesn't match actual size '%lu'!\n", whole_chunk_size, expected_whole_chunk_size); - } - - // Check for AIFF Form Type - memcpy(chunk_type, &aif->data[pos], 4); - pos += 4; - if (strcmp(chunk_type, "AIFF") != 0) - { - FATAL_ERROR("FORM Type is '%s', but it must be AIFF!", chunk_type); - } - - struct Marker *markers = NULL; - unsigned short num_markers = 0, loop_start = 0, loop_end = 0; - unsigned long num_sample_frames = 0; - - // Read all the Chunks to populate the AifData struct. - while ((pos + 8) < aif->length) - { - // Read Chunk id - memcpy(chunk_name, &aif->data[pos], 4); - pos += 4; - - unsigned long chunk_size = (aif->data[pos++] << 24); - chunk_size |= (aif->data[pos++] << 16); - chunk_size |= (aif->data[pos++] << 8); - chunk_size |= aif->data[pos++]; - - if ((pos + chunk_size) > aif->length) - { - FATAL_ERROR("%s chunk at 0x%lx reached end of file before finishing\n", chunk_name, pos); - } - - if (strcmp(chunk_name, "COMM") == 0) - { - short num_channels = (aif->data[pos++] << 8); - num_channels |= (uint8_t)aif->data[pos++]; - if (num_channels != 1) - { - FATAL_ERROR("numChannels (%d) in the COMM Chunk must be 1!\n", num_channels); - } - - num_sample_frames = (aif->data[pos++] << 24); - num_sample_frames |= (aif->data[pos++] << 16); - num_sample_frames |= (aif->data[pos++] << 8); - num_sample_frames |= (uint8_t)aif->data[pos++]; - - aif_data->sample_size = (aif->data[pos++] << 8); - aif_data->sample_size |= (uint8_t)aif->data[pos++]; - if (aif_data->sample_size != 8 && aif_data->sample_size != 16) - { - FATAL_ERROR("sampleSize (%d) in the COMM Chunk must be 8 or 16!\n", aif_data->sample_size); - } - - double sample_rate = ieee754_read_extended((uint8_t*)(aif->data + pos)); - pos += 10; - - aif_data->sample_rate = sample_rate; - - if (aif_data->num_samples == 0) - { - aif_data->num_samples = num_sample_frames; - } - } - else if (strcmp(chunk_name, "MARK") == 0) - { - num_markers = (aif->data[pos++] << 8); - num_markers |= (uint8_t)aif->data[pos++]; - - if (markers) - { - FATAL_ERROR("More than one MARK Chunk in file!\n"); - } - - markers = calloc(num_markers, sizeof(struct Marker)); - - // Read each marker. - for (int i = 0; i < num_markers; i++) - { - unsigned short marker_id = (aif->data[pos++] << 8); - marker_id |= (uint8_t)aif->data[pos++]; - - unsigned long marker_position = (aif->data[pos++] << 24); - marker_position |= (aif->data[pos++] << 16); - marker_position |= (aif->data[pos++] << 8); - marker_position |= (uint8_t)aif->data[pos++]; - - // Marker name is a Pascal-style string. - uint8_t marker_name_size = aif->data[pos++]; - // We don't actually need the marker name for anything anymore. - /*char *marker_name = (char *)malloc((marker_name_size + 1) * sizeof(char)); - memcpy(marker_name, &aif->data[pos], marker_name_size); - marker_name[marker_name_size] = '\0';*/ - pos += marker_name_size + !(marker_name_size & 1); - - markers[i].id = marker_id; - markers[i].position = marker_position; - } - } - else if (strcmp(chunk_name, "INST") == 0) - { - uint8_t midi_note = (uint8_t)aif->data[pos++]; - - aif_data->midi_note = midi_note; - - // Skip over data we don't need. - pos += 7; - - unsigned short loop_type = (aif->data[pos++] << 8); - loop_type |= (uint8_t)aif->data[pos++]; - - if (loop_type) - { - loop_start = (aif->data[pos++] << 8); - loop_start |= (uint8_t)aif->data[pos++]; - - loop_end = (aif->data[pos++] << 8); - loop_end |= (uint8_t)aif->data[pos++]; - } - else - { - // Skip NoLooping sustain loop. - pos += 4; - } - - // Skip release loop, we don't need it. - pos += 6; - } - else if (strcmp(chunk_name, "SSND") == 0) - { - // Skip offset and blockSize - pos += 8; - - unsigned long num_samples = chunk_size - 8; - if (aif_data->sample_size == 8) - { - uint8_t *sample_data = (uint8_t *)malloc(num_samples * sizeof(uint8_t)); - memcpy(sample_data, &aif->data[pos], num_samples); - - aif_data->samples8 = sample_data; - aif_data->real_num_samples = num_samples; - } - else - { - uint16_t *sample_data = (uint16_t *)malloc(num_samples * sizeof(uint16_t)); - uint16_t *sample_data_swapped = (uint16_t *)malloc(num_samples * sizeof(uint16_t)); - memcpy(sample_data, &aif->data[pos], num_samples); - for (long unsigned i = 0; i < num_samples; i++) - { - sample_data_swapped[i] = __builtin_bswap16(sample_data[i]); - } - - aif_data->samples16 = sample_data_swapped; - aif_data->real_num_samples = num_samples; - free(sample_data); - } - pos += chunk_size - 8; - } - else - { - // Skip over unsupported chunks. - pos += chunk_size; - } - } - - if (markers) - { - // Resolve loop points. - struct Marker *cur_marker = markers; - - // Grab loop start point. - for (int i = 0; i < num_markers; i++, cur_marker++) - { - if (cur_marker->id == loop_start) - { - aif_data->loop_offset = cur_marker->position; - aif_data->has_loop = true; - break; - } - } - - cur_marker = markers; - - // Grab loop end point. - for (int i = 0; i < num_markers; i++, cur_marker++) - { - if (cur_marker->id == loop_end) - { - if (cur_marker->position < aif_data->loop_offset) { - aif_data->loop_offset = cur_marker->position; - aif_data->has_loop = true; - } - aif_data->num_samples = cur_marker->position; - break; - } - } - - free(markers); - } -} - -// This is a table of deltas between sample values in compressed PCM data. -const int gDeltaEncodingTable[] = { - 0, 1, 4, 9, 16, 25, 36, 49, - -64, -49, -36, -25, -16, -9, -4, -1, -}; - -#define POSITIVE_DELTAS_START 0 -#define POSITIVE_DELTAS_END 8 - -#define NEGATIVE_DELTAS_START 8 -#define NEGATIVE_DELTAS_END 16 - -struct Bytes *delta_decompress(struct Bytes *delta, unsigned int expected_length) -{ - struct Bytes *pcm = malloc(sizeof(struct Bytes)); - pcm->length = expected_length; - pcm->data = malloc(pcm->length + 0x40); - - uint8_t hi, lo; - unsigned int i = 0; - unsigned int j = 0; - int k; - int8_t base; - while (i < delta->length) - { - base = (int8_t)delta->data[i++]; - pcm->data[j++] = (uint8_t)base; - if (i >= delta->length) - { - break; - } - if (j >= pcm->length) - { - break; - } - lo = delta->data[i] & 0xf; - base += gDeltaEncodingTable[lo]; - pcm->data[j++] = base; - i++; - if (i >= delta->length) - { - break; - } - if (j >= pcm->length) - { - break; - } - for (k = 0; k < 31; k++) - { - hi = (delta->data[i] >> 4) & 0xf; - base += gDeltaEncodingTable[hi]; - pcm->data[j++] = base; - if (j >= pcm->length) - { - break; - } - lo = delta->data[i] & 0xf; - base += gDeltaEncodingTable[lo]; - pcm->data[j++] = base; - i++; - if (i >= delta->length) - { - break; - } - if (j >= pcm->length) - { - break; - } - } - if (j >= pcm->length) - { - break; - } - } - - pcm->length = j; - return pcm; -} - -#define U8_TO_S8(value) ((value) < 128 ? (value) : (value) - 256) -#define ABS(value) ((value) >= 0 ? (value) : -(value)) - -int get_delta_index(uint8_t sample, uint8_t prev_sample) -{ - int best_error = INT_MAX; - int best_index = -1; - int delta_table_start_index; - int delta_table_end_index; - int sample_signed = U8_TO_S8(sample); - int prev_sample_signed = U8_TO_S8(prev_sample); - - // if we're going up (or equal), only choose positive deltas - if (prev_sample_signed <= sample_signed) { - delta_table_start_index = POSITIVE_DELTAS_START; - delta_table_end_index = POSITIVE_DELTAS_END; - } else { - delta_table_start_index = NEGATIVE_DELTAS_START; - delta_table_end_index = NEGATIVE_DELTAS_END; - } - - for (int i = delta_table_start_index; i < delta_table_end_index; i++) - { - uint8_t new_sample = prev_sample + gDeltaEncodingTable[i]; - int new_sample_signed = U8_TO_S8(new_sample); - int error = ABS(new_sample_signed - sample_signed); - - if (error < best_error) - { - best_error = error; - best_index = i; - } - } - - return best_index; -} - -struct Bytes *delta_compress(struct Bytes *pcm) -{ - struct Bytes *delta = malloc(sizeof(struct Bytes)); - // estimate the length so we can malloc - int num_blocks = pcm->length / 64; - delta->length = num_blocks * 33; - - int extra = pcm->length % 64; - if (extra) - { - delta->length += 1; - extra -= 1; - } - if (extra) - { - delta->length += 1; - extra -= 1; - } - if (extra) - { - delta->length += (extra + 1) / 2; - } - - delta->data = malloc(delta->length + 33); - - unsigned int i = 0; - unsigned int j = 0; - int k; - uint8_t base; - int delta_index; - - while (i < pcm->length) - { - base = pcm->data[i++]; - delta->data[j++] = base; - - if (i >= pcm->length) - { - break; - } - delta_index = get_delta_index(pcm->data[i++], base); - base += gDeltaEncodingTable[delta_index]; - delta->data[j++] = delta_index; - - for (k = 0; k < 31; k++) - { - if (i >= pcm->length) - { - break; - } - delta_index = get_delta_index(pcm->data[i++], base); - base += gDeltaEncodingTable[delta_index]; - delta->data[j] = (delta_index << 4); - - if (i >= pcm->length) - { - break; - } - delta_index = get_delta_index(pcm->data[i++], base); - base += gDeltaEncodingTable[delta_index]; - delta->data[j++] |= delta_index; - } - } - - delta->length = j; - - return delta; -} - -#define STORE_U32_LE(dest, value) \ -do { \ - *(dest) = (value) & 0xff; \ - *((dest) + 1) = ((value) >> 8) & 0xff; \ - *((dest) + 2) = ((value) >> 16) & 0xff; \ - *((dest) + 3) = ((value) >> 24) & 0xff; \ -} while (0) - -#define LOAD_U32_LE(var, src) \ -do { \ - (var) = *(src); \ - (var) |= (*((src) + 1) << 8); \ - (var) |= (*((src) + 2) << 16); \ - (var) |= (*((src) + 3) << 24); \ -} while (0) - -// Reads an .aif file and produces a .pcm file containing an array of 8-bit samples. -void aif2pcm(const char *aif_filename, const char *pcm_filename, bool compress) -{ - struct Bytes *aif = read_bytearray(aif_filename); - AifData aif_data = {0}; - read_aif(aif, &aif_data); - - // Convert 16-bit to 8-bit if necessary - if (aif_data.sample_size == 16) - { - aif_data.real_num_samples /= 2; - uint8_t *converted_samples = malloc(aif_data.real_num_samples * sizeof(uint8_t)); - for (unsigned long i = 0; i < aif_data.real_num_samples; i++) - { - converted_samples[i] = aif_data.samples16[i] >> 8; - } - free(aif_data.samples16); - aif_data.samples8 = converted_samples; - } - - int header_size = 0x10; - struct Bytes *pcm; - struct Bytes output = {0,0}; - - if (compress) - { - struct Bytes *input = malloc(sizeof(struct Bytes)); - input->data = aif_data.samples8; - input->length = aif_data.real_num_samples; - pcm = delta_compress(input); - free(input); - } - else - { - pcm = malloc(sizeof(struct Bytes)); - pcm->data = aif_data.samples8; - pcm->length = aif_data.real_num_samples; - } - output.length = header_size + pcm->length; - output.data = malloc(output.length); - - uint32_t pitch_adjust = (uint32_t)(aif_data.sample_rate * 1024); - uint32_t loop_offset = (uint32_t)(aif_data.loop_offset); - uint32_t adjusted_num_samples = (uint32_t)(aif_data.num_samples - 1); - uint32_t flags = 0; - if (aif_data.has_loop) flags |= 0x40000000; - if (compress) flags |= 1; - STORE_U32_LE(output.data + 0, flags); - STORE_U32_LE(output.data + 4, pitch_adjust); - STORE_U32_LE(output.data + 8, loop_offset); - STORE_U32_LE(output.data + 12, adjusted_num_samples); - memcpy(&output.data[header_size], pcm->data, pcm->length); - write_bytearray(pcm_filename, &output); - - free(aif->data); - free(aif); - free(pcm); - free(output.data); - free(aif_data.samples8); -} - -// Reads a .pcm file containing an array of 8-bit samples and produces an .aif file. -// See http://www-mmsp.ece.mcgill.ca/documents/audioformats/aiff/Docs/AIFF-1.3.pdf for .aif file specification. -void pcm2aif(const char *pcm_filename, const char *aif_filename, uint32_t base_note) -{ - struct Bytes *pcm = read_bytearray(pcm_filename); - - AifData *aif_data = malloc(sizeof(AifData)); - - uint32_t flags; - LOAD_U32_LE(flags, pcm->data + 0); - aif_data->has_loop = flags & 0x40000000; - bool compressed = flags & 1; - - uint32_t pitch_adjust; - LOAD_U32_LE(pitch_adjust, pcm->data + 4); - aif_data->sample_rate = pitch_adjust / 1024.0; - - LOAD_U32_LE(aif_data->loop_offset, pcm->data + 8); - LOAD_U32_LE(aif_data->num_samples, pcm->data + 12); - aif_data->num_samples += 1; - - if (compressed) - { - struct Bytes *delta = pcm; - uint8_t *pcm_data = pcm->data; - delta->length -= 0x10; - delta->data += 0x10; - pcm = delta_decompress(delta, aif_data->num_samples); - free(pcm_data); - free(delta); - } - else - { - pcm->length -= 0x10; - pcm->data += 0x10; - } - - aif_data->samples8 = malloc(pcm->length); - memcpy(aif_data->samples8, pcm->data, pcm->length); - - struct Bytes *aif = malloc(sizeof(struct Bytes)); - aif->length = 54 + 60 + pcm->length; - aif->data = malloc(aif->length); - - long pos = 0; - - // First, write the FORM header chunk. - // FORM Chunk ckID - aif->data[pos++] = 'F'; - aif->data[pos++] = 'O'; - aif->data[pos++] = 'R'; - aif->data[pos++] = 'M'; - - // FORM Chunk ckSize - unsigned long form_size = pos; - unsigned long data_size = aif->length - 8; - aif->data[pos++] = ((data_size >> 24) & 0xFF); - aif->data[pos++] = ((data_size >> 16) & 0xFF); - aif->data[pos++] = ((data_size >> 8) & 0xFF); - aif->data[pos++] = (data_size & 0xFF); - - // FORM Chunk formType - aif->data[pos++] = 'A'; - aif->data[pos++] = 'I'; - aif->data[pos++] = 'F'; - aif->data[pos++] = 'F'; - - // Next, write the Common Chunk - // Common Chunk ckID - aif->data[pos++] = 'C'; - aif->data[pos++] = 'O'; - aif->data[pos++] = 'M'; - aif->data[pos++] = 'M'; - - // Common Chunk ckSize - aif->data[pos++] = 0; - aif->data[pos++] = 0; - aif->data[pos++] = 0; - aif->data[pos++] = 18; - - // Common Chunk numChannels - aif->data[pos++] = 0; - aif->data[pos++] = 1; // 1 channel - - // Common Chunk numSampleFrames - aif->data[pos++] = ((aif_data->num_samples >> 24) & 0xFF); - aif->data[pos++] = ((aif_data->num_samples >> 16) & 0xFF); - aif->data[pos++] = ((aif_data->num_samples >> 8) & 0xFF); - aif->data[pos++] = (aif_data->num_samples & 0xFF); - - // Common Chunk sampleSize - aif->data[pos++] = 0; - aif->data[pos++] = 8; // 8 bits per sample - - // Common Chunk sampleRate - //double sample_rate = pitch_adjust / 1024.0; - uint8_t sample_rate_buffer[10]; - ieee754_write_extended(aif_data->sample_rate, sample_rate_buffer); - for (int i = 0; i < 10; i++) - { - aif->data[pos++] = sample_rate_buffer[i]; - } - - if (aif_data->has_loop) - { - - // Marker Chunk ckID - aif->data[pos++] = 'M'; - aif->data[pos++] = 'A'; - aif->data[pos++] = 'R'; - aif->data[pos++] = 'K'; - - // Marker Chunk ckSize - aif->data[pos++] = 0; - aif->data[pos++] = 0; - aif->data[pos++] = 0; - aif->data[pos++] = 12 + (aif_data->has_loop ? 12 : 0); - - // Marker Chunk numMarkers - aif->data[pos++] = 0; - aif->data[pos++] = (aif_data->has_loop ? 2 : 1); - - // Marker loop start - aif->data[pos++] = 0; - aif->data[pos++] = 1; // id = 1 - - long loop_start = aif_data->loop_offset; - aif->data[pos++] = ((loop_start >> 24) & 0xFF); - aif->data[pos++] = ((loop_start >> 16) & 0xFF); - aif->data[pos++] = ((loop_start >> 8) & 0xFF); - aif->data[pos++] = (loop_start & 0xFF); // position - - aif->data[pos++] = 5; // pascal-style string length - aif->data[pos++] = 'S'; - aif->data[pos++] = 'T'; - aif->data[pos++] = 'A'; - aif->data[pos++] = 'R'; - aif->data[pos++] = 'T'; // markerName - - // Marker loop end - aif->data[pos++] = 0; - aif->data[pos++] = (aif_data->has_loop ? 2 : 1); // id = 2 - - long loop_end = aif_data->num_samples; - aif->data[pos++] = ((loop_end >> 24) & 0xFF); - aif->data[pos++] = ((loop_end >> 16) & 0xFF); - aif->data[pos++] = ((loop_end >> 8) & 0xFF); - aif->data[pos++] = (loop_end & 0xFF); // position - - aif->data[pos++] = 3; // pascal-style string length - aif->data[pos++] = 'E'; - aif->data[pos++] = 'N'; - aif->data[pos++] = 'D'; - } - - // Instrument Chunk ckID - aif->data[pos++] = 'I'; - aif->data[pos++] = 'N'; - aif->data[pos++] = 'S'; - aif->data[pos++] = 'T'; - - // Instrument Chunk ckSize - aif->data[pos++] = 0; - aif->data[pos++] = 0; - aif->data[pos++] = 0; - aif->data[pos++] = 20; - - aif->data[pos++] = base_note; // baseNote - aif->data[pos++] = 0; // detune - aif->data[pos++] = 0; // lowNote - aif->data[pos++] = 127; // highNote - aif->data[pos++] = 1; // lowVelocity - aif->data[pos++] = 127; // highVelocity - aif->data[pos++] = 0; // gain (hi) - aif->data[pos++] = 0; // gain (lo) - - // Instrument Chunk sustainLoop - aif->data[pos++] = 0; - aif->data[pos++] = 1; // playMode = ForwardLooping - - aif->data[pos++] = 0; - aif->data[pos++] = 1; // beginLoop marker id - - aif->data[pos++] = 0; - aif->data[pos++] = 2; // endLoop marker id - - // Instrument Chunk releaseLoop - aif->data[pos++] = 0; - aif->data[pos++] = 1; // playMode = ForwardLooping - - aif->data[pos++] = 0; - aif->data[pos++] = 1; // beginLoop marker id - - aif->data[pos++] = 0; - aif->data[pos++] = 2; // endLoop marker id - - // Finally, write the Sound Data Chunk - // Sound Data Chunk ckID - aif->data[pos++] = 'S'; - aif->data[pos++] = 'S'; - aif->data[pos++] = 'N'; - aif->data[pos++] = 'D'; - - // Sound Data Chunk ckSize - unsigned long sound_data_size = pcm->length + 8; - aif->data[pos++] = ((sound_data_size >> 24) & 0xFF); - aif->data[pos++] = ((sound_data_size >> 16) & 0xFF); - aif->data[pos++] = ((sound_data_size >> 8) & 0xFF); - aif->data[pos++] = (sound_data_size & 0xFF); - - // Sound Data Chunk offset - aif->data[pos++] = 0; - aif->data[pos++] = 0; - aif->data[pos++] = 0; - aif->data[pos++] = 0; - - // Sound Data Chunk blockSize - aif->data[pos++] = 0; - aif->data[pos++] = 0; - aif->data[pos++] = 0; - aif->data[pos++] = 0; - - // Sound Data Chunk soundData - for (unsigned int i = 0; i < aif_data->loop_offset; i++) - { - aif->data[pos++] = aif_data->samples8[i]; - } - - int j = 0; - for (unsigned int i = aif_data->loop_offset; i < pcm->length; i++) - { - int pcm_index = aif_data->loop_offset + (j++ % (pcm->length - aif_data->loop_offset)); - aif->data[pos++] = aif_data->samples8[pcm_index]; - } - - aif->length = pos; - - // Go back and rewrite ckSize - data_size = aif->length - 8; - aif->data[form_size + 0] = ((data_size >> 24) & 0xFF); - aif->data[form_size + 1] = ((data_size >> 16) & 0xFF); - aif->data[form_size + 2] = ((data_size >> 8) & 0xFF); - aif->data[form_size + 3] = (data_size & 0xFF); - - write_bytearray(aif_filename, aif); - - free(aif->data); - free(aif); -} - -void usage(void) -{ - fprintf(stderr, "Usage: aif2pcm bin_file [aif_file]\n"); - fprintf(stderr, " aif2pcm aif_file [bin_file] [--compress]\n"); -} - -int main(int argc, char **argv) -{ - if (argc < 2) - { - usage(); - exit(1); - } - - char *input_file = argv[1]; - char *extension = get_file_extension(input_file); - char *output_file; - bool compressed = false; - - if (argc > 3) - { - for (int i = 3; i < argc; i++) - { - if (strcmp(argv[i], "--compress") == 0) - { - compressed = true; - } - } - } - - if (strcmp(extension, "aif") == 0 || strcmp(extension, "aiff") == 0) - { - if (argc >= 3) - { - output_file = argv[2]; - aif2pcm(input_file, output_file, compressed); - } - else - { - output_file = new_file_extension(input_file, "bin"); - aif2pcm(input_file, output_file, compressed); - free(output_file); - } - } - else if (strcmp(extension, "bin") == 0) - { - if (argc >= 3) - { - output_file = argv[2]; - pcm2aif(input_file, output_file, 60); - } - else - { - output_file = new_file_extension(input_file, "aif"); - pcm2aif(input_file, output_file, 60); - free(output_file); - } - } - else - { - FATAL_ERROR("Input file must be .aif or .bin: '%s'\n", input_file); - } - - return 0; -} diff --git a/tools/compresSmol/compressAlgo.cpp b/tools/compresSmol/compressAlgo.cpp index 261abcf24a..36d4cbfadd 100644 --- a/tools/compresSmol/compressAlgo.cpp +++ b/tools/compresSmol/compressAlgo.cpp @@ -970,7 +970,7 @@ void getUIntVecFromData(CompressedImage *pImage, std::vector *pOut } } } - if (currOffset != 0) + if (currOffset % 4 != 0) pOutput->push_back(currInt); } diff --git a/tools/learnset_helpers/make_teachables.py b/tools/learnset_helpers/make_teachables.py index 6f3b186b68..a0e94124f7 100644 --- a/tools/learnset_helpers/make_teachables.py +++ b/tools/learnset_helpers/make_teachables.py @@ -150,6 +150,7 @@ def create_tutor_moves_array(tutors: list[str]) -> None: header = dedent("""\ // DO NOT MODIFY THIS FILE! It is auto-generated by tools/learnset_helpers/make_teachables.py // Set the config P_TUTOR_MOVES_ARRAY in include/config/pokemon.h to TRUE to enable this array! + // Also need by tutor moves relearner! const u16 gTutorMoves[] = { """) diff --git a/tools/learnset_helpers/porymoves_files/za.json b/tools/learnset_helpers/porymoves_files/za.json new file mode 100644 index 0000000000..cda070084f --- /dev/null +++ b/tools/learnset_helpers/porymoves_files/za.json @@ -0,0 +1,19086 @@ +{ + "BULBASAUR": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_GROWL" + }, + { + "Level": "3", + "Move": "MOVE_VINE_WHIP" + }, + { + "Level": "6", + "Move": "MOVE_GROWTH" + }, + { + "Level": "9", + "Move": "MOVE_LEECH_SEED" + }, + { + "Level": "12", + "Move": "MOVE_RAZOR_LEAF" + }, + { + "Level": "15", + "Move": "MOVE_POISON_POWDER" + }, + { + "Level": "15", + "Move": "MOVE_SLEEP_POWDER" + }, + { + "Level": "25", + "Move": "MOVE_TAKE_DOWN" + }, + { + "Level": "30", + "Move": "MOVE_MAGICAL_LEAF" + }, + { + "Level": "35", + "Move": "MOVE_SYNTHESIS" + }, + { + "Level": "40", + "Move": "MOVE_AMNESIA" + }, + { + "Level": "42", + "Move": "MOVE_SLUDGE_WAVE" + }, + { + "Level": "45", + "Move": "MOVE_DOUBLE_EDGE" + }, + { + "Level": "55", + "Move": "MOVE_SOLAR_BEAM" + } + ], + "TMMoves": [ + "MOVE_BODY_SLAM", + "MOVE_BULLET_SEED", + "MOVE_ENDURE", + "MOVE_ENERGY_BALL", + "MOVE_GIGA_DRAIN", + "MOVE_LIGHT_SCREEN", + "MOVE_PROTECT", + "MOVE_SAFEGUARD", + "MOVE_SLUDGE_BOMB", + "MOVE_SUBSTITUTE", + "MOVE_SWORDS_DANCE", + "MOVE_TOXIC", + "MOVE_WORK_UP" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "IVYSAUR": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_GROWL" + }, + { + "Level": "3", + "Move": "MOVE_VINE_WHIP" + }, + { + "Level": "6", + "Move": "MOVE_GROWTH" + }, + { + "Level": "9", + "Move": "MOVE_LEECH_SEED" + }, + { + "Level": "12", + "Move": "MOVE_RAZOR_LEAF" + }, + { + "Level": "15", + "Move": "MOVE_POISON_POWDER" + }, + { + "Level": "15", + "Move": "MOVE_SLEEP_POWDER" + }, + { + "Level": "25", + "Move": "MOVE_TAKE_DOWN" + }, + { + "Level": "30", + "Move": "MOVE_MAGICAL_LEAF" + }, + { + "Level": "35", + "Move": "MOVE_SYNTHESIS" + }, + { + "Level": "40", + "Move": "MOVE_AMNESIA" + }, + { + "Level": "42", + "Move": "MOVE_SLUDGE_WAVE" + }, + { + "Level": "45", + "Move": "MOVE_DOUBLE_EDGE" + }, + { + "Level": "55", + "Move": "MOVE_SOLAR_BEAM" + } + ], + "TMMoves": [ + "MOVE_BODY_SLAM", + "MOVE_BULLET_SEED", + "MOVE_ENDURE", + "MOVE_ENERGY_BALL", + "MOVE_GIGA_DRAIN", + "MOVE_LIGHT_SCREEN", + "MOVE_PROTECT", + "MOVE_ROAR", + "MOVE_SAFEGUARD", + "MOVE_SLUDGE_BOMB", + "MOVE_SUBSTITUTE", + "MOVE_SWORDS_DANCE", + "MOVE_TOXIC", + "MOVE_WORK_UP" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "VENUSAUR": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_GROWL" + }, + { + "Level": "3", + "Move": "MOVE_VINE_WHIP" + }, + { + "Level": "6", + "Move": "MOVE_GROWTH" + }, + { + "Level": "9", + "Move": "MOVE_LEECH_SEED" + }, + { + "Level": "12", + "Move": "MOVE_RAZOR_LEAF" + }, + { + "Level": "15", + "Move": "MOVE_POISON_POWDER" + }, + { + "Level": "15", + "Move": "MOVE_SLEEP_POWDER" + }, + { + "Level": "25", + "Move": "MOVE_TAKE_DOWN" + }, + { + "Level": "30", + "Move": "MOVE_MAGICAL_LEAF" + }, + { + "Level": "35", + "Move": "MOVE_SYNTHESIS" + }, + { + "Level": "40", + "Move": "MOVE_AMNESIA" + }, + { + "Level": "42", + "Move": "MOVE_SLUDGE_WAVE" + }, + { + "Level": "45", + "Move": "MOVE_DOUBLE_EDGE" + }, + { + "Level": "55", + "Move": "MOVE_SOLAR_BEAM" + } + ], + "TMMoves": [ + "MOVE_BODY_SLAM", + "MOVE_BULLET_SEED", + "MOVE_EARTHQUAKE", + "MOVE_EARTH_POWER", + "MOVE_ENDURE", + "MOVE_ENERGY_BALL", + "MOVE_GIGA_DRAIN", + "MOVE_GIGA_IMPACT", + "MOVE_HYPER_BEAM", + "MOVE_LIGHT_SCREEN", + "MOVE_OUTRAGE", + "MOVE_PROTECT", + "MOVE_ROAR", + "MOVE_SAFEGUARD", + "MOVE_SLUDGE_BOMB", + "MOVE_SUBSTITUTE", + "MOVE_SWORDS_DANCE", + "MOVE_TOXIC", + "MOVE_WORK_UP" + ], + "TutorMoves": [ + "MOVE_POWER_WHIP" + ], + "EggMoves": [] + }, + "CHARMANDER": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_GROWL" + }, + { + "Level": "4", + "Move": "MOVE_EMBER" + }, + { + "Level": "8", + "Move": "MOVE_SMOKESCREEN" + }, + { + "Level": "12", + "Move": "MOVE_DRAGON_BREATH" + }, + { + "Level": "17", + "Move": "MOVE_FIRE_FANG" + }, + { + "Level": "20", + "Move": "MOVE_FIRE_SPIN" + }, + { + "Level": "24", + "Move": "MOVE_SLASH" + }, + { + "Level": "30", + "Move": "MOVE_FLAMETHROWER" + }, + { + "Level": "42", + "Move": "MOVE_DRAGON_RUSH" + }, + { + "Level": "54", + "Move": "MOVE_FLARE_BLITZ" + } + ], + "TMMoves": [ + "MOVE_BODY_SLAM", + "MOVE_BRICK_BREAK", + "MOVE_CRUNCH", + "MOVE_DIG", + "MOVE_DRAGON_CLAW", + "MOVE_DRAGON_PULSE", + "MOVE_ENDURE", + "MOVE_FIRE_BLAST", + "MOVE_FIRE_PUNCH", + "MOVE_FOCUS_BLAST", + "MOVE_HEAT_WAVE", + "MOVE_IRON_TAIL", + "MOVE_OUTRAGE", + "MOVE_OVERHEAT", + "MOVE_PROTECT", + "MOVE_ROAR", + "MOVE_ROCK_SLIDE", + "MOVE_ROCK_TOMB", + "MOVE_SHADOW_CLAW", + "MOVE_SUBSTITUTE", + "MOVE_SWIFT", + "MOVE_SWORDS_DANCE", + "MOVE_THUNDER_PUNCH", + "MOVE_WILL_O_WISP" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "CHARMELEON": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_GROWL" + }, + { + "Level": "4", + "Move": "MOVE_EMBER" + }, + { + "Level": "8", + "Move": "MOVE_SMOKESCREEN" + }, + { + "Level": "12", + "Move": "MOVE_DRAGON_BREATH" + }, + { + "Level": "17", + "Move": "MOVE_FIRE_FANG" + }, + { + "Level": "20", + "Move": "MOVE_FIRE_SPIN" + }, + { + "Level": "24", + "Move": "MOVE_SLASH" + }, + { + "Level": "30", + "Move": "MOVE_FLAMETHROWER" + }, + { + "Level": "42", + "Move": "MOVE_DRAGON_RUSH" + }, + { + "Level": "54", + "Move": "MOVE_FLARE_BLITZ" + } + ], + "TMMoves": [ + "MOVE_BODY_SLAM", + "MOVE_BRICK_BREAK", + "MOVE_CRUNCH", + "MOVE_DIG", + "MOVE_DRAGON_CLAW", + "MOVE_DRAGON_PULSE", + "MOVE_ENDURE", + "MOVE_FIRE_BLAST", + "MOVE_FIRE_PUNCH", + "MOVE_FOCUS_BLAST", + "MOVE_HEAT_WAVE", + "MOVE_IRON_TAIL", + "MOVE_OUTRAGE", + "MOVE_OVERHEAT", + "MOVE_PROTECT", + "MOVE_ROAR", + "MOVE_ROCK_SLIDE", + "MOVE_ROCK_TOMB", + "MOVE_SHADOW_CLAW", + "MOVE_SUBSTITUTE", + "MOVE_SWIFT", + "MOVE_SWORDS_DANCE", + "MOVE_THUNDER_PUNCH", + "MOVE_WILL_O_WISP" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "CHARIZARD": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_GROWL" + }, + { + "Level": "1", + "Move": "MOVE_DRAGON_CLAW" + }, + { + "Level": "4", + "Move": "MOVE_EMBER" + }, + { + "Level": "8", + "Move": "MOVE_SMOKESCREEN" + }, + { + "Level": "12", + "Move": "MOVE_DRAGON_BREATH" + }, + { + "Level": "17", + "Move": "MOVE_FIRE_FANG" + }, + { + "Level": "20", + "Move": "MOVE_FIRE_SPIN" + }, + { + "Level": "24", + "Move": "MOVE_SLASH" + }, + { + "Level": "30", + "Move": "MOVE_FLAMETHROWER" + }, + { + "Level": "42", + "Move": "MOVE_DRAGON_RUSH" + }, + { + "Level": "54", + "Move": "MOVE_FLARE_BLITZ" + } + ], + "TMMoves": [ + "MOVE_BODY_SLAM", + "MOVE_BRICK_BREAK", + "MOVE_CRUNCH", + "MOVE_DIG", + "MOVE_DOUBLE_EDGE", + "MOVE_DRAGON_PULSE", + "MOVE_EARTHQUAKE", + "MOVE_ENDURE", + "MOVE_FIRE_PUNCH", + "MOVE_FLY", + "MOVE_FOCUS_BLAST", + "MOVE_GIGA_IMPACT", + "MOVE_HEAT_WAVE", + "MOVE_HURRICANE", + "MOVE_HYPER_BEAM", + "MOVE_IRON_TAIL", + "MOVE_OUTRAGE", + "MOVE_OVERHEAT", + "MOVE_PROTECT", + "MOVE_ROAR", + "MOVE_ROCK_SLIDE", + "MOVE_ROCK_TOMB", + "MOVE_SHADOW_CLAW", + "MOVE_SOLAR_BEAM", + "MOVE_SUBSTITUTE", + "MOVE_SWIFT", + "MOVE_SWORDS_DANCE", + "MOVE_THUNDER_PUNCH", + "MOVE_WILL_O_WISP" + ], + "TutorMoves": [ + "MOVE_AIR_SLASH", + "MOVE_FIRE_BLAST" + ], + "EggMoves": [] + }, + "SQUIRTLE": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_TAIL_WHIP" + }, + { + "Level": "3", + "Move": "MOVE_WATER_GUN" + }, + { + "Level": "12", + "Move": "MOVE_BITE" + }, + { + "Level": "15", + "Move": "MOVE_BUBBLE_BEAM" + }, + { + "Level": "20", + "Move": "MOVE_ICY_WIND" + }, + { + "Level": "30", + "Move": "MOVE_AQUA_RING" + }, + { + "Level": "35", + "Move": "MOVE_AQUA_JET" + }, + { + "Level": "40", + "Move": "MOVE_IRON_DEFENSE" + }, + { + "Level": "45", + "Move": "MOVE_LIQUIDATION" + } + ], + "TMMoves": [ + "MOVE_AURA_SPHERE", + "MOVE_BLIZZARD", + "MOVE_BODY_SLAM", + "MOVE_BRICK_BREAK", + "MOVE_DIG", + "MOVE_DOUBLE_EDGE", + "MOVE_DRAGON_PULSE", + "MOVE_ENDURE", + "MOVE_FLIP_TURN", + "MOVE_HEADBUTT", + "MOVE_HYDRO_PUMP", + "MOVE_ICE_BEAM", + "MOVE_ICE_PUNCH", + "MOVE_IRON_HEAD", + "MOVE_IRON_TAIL", + "MOVE_MUD_SHOT", + "MOVE_PROTECT", + "MOVE_ROCK_TOMB", + "MOVE_SUBSTITUTE", + "MOVE_SURF", + "MOVE_WATERFALL", + "MOVE_WATER_PULSE", + "MOVE_WHIRLPOOL", + "MOVE_WORK_UP", + "MOVE_ZEN_HEADBUTT" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "WARTORTLE": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_TAIL_WHIP" + }, + { + "Level": "3", + "Move": "MOVE_WATER_GUN" + }, + { + "Level": "12", + "Move": "MOVE_BITE" + }, + { + "Level": "15", + "Move": "MOVE_BUBBLE_BEAM" + }, + { + "Level": "20", + "Move": "MOVE_ICY_WIND" + }, + { + "Level": "30", + "Move": "MOVE_AQUA_RING" + }, + { + "Level": "35", + "Move": "MOVE_AQUA_JET" + }, + { + "Level": "40", + "Move": "MOVE_IRON_DEFENSE" + }, + { + "Level": "45", + "Move": "MOVE_LIQUIDATION" + } + ], + "TMMoves": [ + "MOVE_AURA_SPHERE", + "MOVE_BLIZZARD", + "MOVE_BODY_SLAM", + "MOVE_BRICK_BREAK", + "MOVE_DIG", + "MOVE_DOUBLE_EDGE", + "MOVE_DRAGON_PULSE", + "MOVE_ENDURE", + "MOVE_FLIP_TURN", + "MOVE_HEADBUTT", + "MOVE_HYDRO_PUMP", + "MOVE_ICE_BEAM", + "MOVE_ICE_PUNCH", + "MOVE_IRON_HEAD", + "MOVE_IRON_TAIL", + "MOVE_MUD_SHOT", + "MOVE_PROTECT", + "MOVE_ROCK_TOMB", + "MOVE_SUBSTITUTE", + "MOVE_SURF", + "MOVE_WATERFALL", + "MOVE_WATER_PULSE", + "MOVE_WHIRLPOOL", + "MOVE_WORK_UP", + "MOVE_ZEN_HEADBUTT" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "BLASTOISE": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_TAIL_WHIP" + }, + { + "Level": "3", + "Move": "MOVE_WATER_GUN" + }, + { + "Level": "12", + "Move": "MOVE_BITE" + }, + { + "Level": "15", + "Move": "MOVE_BUBBLE_BEAM" + }, + { + "Level": "20", + "Move": "MOVE_ICY_WIND" + }, + { + "Level": "30", + "Move": "MOVE_AQUA_RING" + }, + { + "Level": "35", + "Move": "MOVE_AQUA_JET" + }, + { + "Level": "40", + "Move": "MOVE_IRON_DEFENSE" + }, + { + "Level": "45", + "Move": "MOVE_LIQUIDATION" + } + ], + "TMMoves": [ + "MOVE_AURA_SPHERE", + "MOVE_BLIZZARD", + "MOVE_BODY_SLAM", + "MOVE_BRICK_BREAK", + "MOVE_CRUNCH", + "MOVE_DARK_PULSE", + "MOVE_DIG", + "MOVE_DOUBLE_EDGE", + "MOVE_DRAGON_PULSE", + "MOVE_EARTHQUAKE", + "MOVE_ENDURE", + "MOVE_FLIP_TURN", + "MOVE_FOCUS_BLAST", + "MOVE_GIGA_IMPACT", + "MOVE_HEADBUTT", + "MOVE_HYPER_BEAM", + "MOVE_ICE_BEAM", + "MOVE_ICE_PUNCH", + "MOVE_IRON_HEAD", + "MOVE_IRON_TAIL", + "MOVE_MUD_SHOT", + "MOVE_OUTRAGE", + "MOVE_PROTECT", + "MOVE_ROAR", + "MOVE_ROCK_SLIDE", + "MOVE_ROCK_TOMB", + "MOVE_SUBSTITUTE", + "MOVE_SURF", + "MOVE_WATERFALL", + "MOVE_WATER_PULSE", + "MOVE_WHIRLPOOL", + "MOVE_WORK_UP", + "MOVE_ZEN_HEADBUTT" + ], + "TutorMoves": [ + "MOVE_FLASH_CANNON", + "MOVE_HYDRO_PUMP" + ], + "EggMoves": [] + }, + "WEEDLE": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_POISON_STING" + }, + { + "Level": "1", + "Move": "MOVE_STRING_SHOT" + } + ], + "TMMoves": [ + "MOVE_ELECTROWEB" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "KAKUNA": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_POISON_STING" + }, + { + "Level": "1", + "Move": "MOVE_STRING_SHOT" + }, + { + "Level": "7", + "Move": "MOVE_HARDEN" + } + ], + "TMMoves": [ + "MOVE_ELECTROWEB", + "MOVE_IRON_DEFENSE" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "BEEDRILL": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_POISON_STING" + }, + { + "Level": "1", + "Move": "MOVE_STRING_SHOT" + }, + { + "Level": "7", + "Move": "MOVE_HARDEN" + }, + { + "Level": "15", + "Move": "MOVE_FOCUS_ENERGY" + }, + { + "Level": "20", + "Move": "MOVE_BRUTAL_SWING" + }, + { + "Level": "25", + "Move": "MOVE_X_SCISSOR" + }, + { + "Level": "27", + "Move": "MOVE_BUG_BUZZ" + }, + { + "Level": "29", + "Move": "MOVE_TOXIC_SPIKES" + }, + { + "Level": "33", + "Move": "MOVE_LUNGE" + }, + { + "Level": "35", + "Move": "MOVE_POISON_JAB" + }, + { + "Level": "40", + "Move": "MOVE_DRILL_RUN" + } + ], + "TMMoves": [ + "MOVE_AERIAL_ACE", + "MOVE_AGILITY", + "MOVE_BRICK_BREAK", + "MOVE_ELECTROWEB", + "MOVE_ENDURE", + "MOVE_GIGA_DRAIN", + "MOVE_GIGA_IMPACT", + "MOVE_HYPER_BEAM", + "MOVE_IRON_DEFENSE", + "MOVE_OUTRAGE", + "MOVE_PROTECT", + "MOVE_ROCK_SMASH", + "MOVE_SLUDGE_BOMB", + "MOVE_SOLAR_BEAM", + "MOVE_SUBSTITUTE", + "MOVE_SWORDS_DANCE", + "MOVE_TOXIC", + "MOVE_U_TURN" + ], + "TutorMoves": [ + "MOVE_PIN_MISSILE" + ], + "EggMoves": [] + }, + "PIDGEY": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_GROWL" + }, + { + "Level": "9", + "Move": "MOVE_GUST" + }, + { + "Level": "13", + "Move": "MOVE_QUICK_ATTACK" + }, + { + "Level": "17", + "Move": "MOVE_TWISTER" + }, + { + "Level": "21", + "Move": "MOVE_WING_ATTACK" + }, + { + "Level": "25", + "Move": "MOVE_WHIRLWIND" + }, + { + "Level": "29", + "Move": "MOVE_AGILITY" + }, + { + "Level": "33", + "Move": "MOVE_AIR_SLASH" + }, + { + "Level": "40", + "Move": "MOVE_FEATHER_DANCE" + }, + { + "Level": "45", + "Move": "MOVE_HURRICANE" + }, + { + "Level": "50", + "Move": "MOVE_BRAVE_BIRD" + } + ], + "TMMoves": [ + "MOVE_AERIAL_ACE", + "MOVE_DOUBLE_TEAM", + "MOVE_ENDURE", + "MOVE_FLY", + "MOVE_HEADBUTT", + "MOVE_HEAT_WAVE", + "MOVE_PROTECT", + "MOVE_REFLECT", + "MOVE_SUBSTITUTE", + "MOVE_U_TURN", + "MOVE_WORK_UP" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "PIDGEOTTO": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_GROWL" + }, + { + "Level": "9", + "Move": "MOVE_GUST" + }, + { + "Level": "13", + "Move": "MOVE_QUICK_ATTACK" + }, + { + "Level": "17", + "Move": "MOVE_TWISTER" + }, + { + "Level": "21", + "Move": "MOVE_WING_ATTACK" + }, + { + "Level": "25", + "Move": "MOVE_WHIRLWIND" + }, + { + "Level": "29", + "Move": "MOVE_AGILITY" + }, + { + "Level": "33", + "Move": "MOVE_AIR_SLASH" + }, + { + "Level": "40", + "Move": "MOVE_FEATHER_DANCE" + }, + { + "Level": "45", + "Move": "MOVE_HURRICANE" + }, + { + "Level": "50", + "Move": "MOVE_BRAVE_BIRD" + } + ], + "TMMoves": [ + "MOVE_AERIAL_ACE", + "MOVE_DOUBLE_TEAM", + "MOVE_ENDURE", + "MOVE_FLY", + "MOVE_HEADBUTT", + "MOVE_HEAT_WAVE", + "MOVE_PROTECT", + "MOVE_REFLECT", + "MOVE_SUBSTITUTE", + "MOVE_U_TURN", + "MOVE_WORK_UP" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "PIDGEOT": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_GROWL" + }, + { + "Level": "9", + "Move": "MOVE_GUST" + }, + { + "Level": "13", + "Move": "MOVE_QUICK_ATTACK" + }, + { + "Level": "17", + "Move": "MOVE_TWISTER" + }, + { + "Level": "21", + "Move": "MOVE_WING_ATTACK" + }, + { + "Level": "25", + "Move": "MOVE_WHIRLWIND" + }, + { + "Level": "29", + "Move": "MOVE_AGILITY" + }, + { + "Level": "33", + "Move": "MOVE_AIR_SLASH" + }, + { + "Level": "40", + "Move": "MOVE_FEATHER_DANCE" + }, + { + "Level": "45", + "Move": "MOVE_HURRICANE" + }, + { + "Level": "50", + "Move": "MOVE_BRAVE_BIRD" + } + ], + "TMMoves": [ + "MOVE_AERIAL_ACE", + "MOVE_DOUBLE_TEAM", + "MOVE_ENDURE", + "MOVE_FLY", + "MOVE_GIGA_IMPACT", + "MOVE_HEADBUTT", + "MOVE_HEAT_WAVE", + "MOVE_HYPER_BEAM", + "MOVE_PROTECT", + "MOVE_REFLECT", + "MOVE_SUBSTITUTE", + "MOVE_U_TURN", + "MOVE_WORK_UP" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "EKANS": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_LEER" + }, + { + "Level": "4", + "Move": "MOVE_POISON_STING" + }, + { + "Level": "9", + "Move": "MOVE_BITE" + }, + { + "Level": "12", + "Move": "MOVE_GLARE" + }, + { + "Level": "15", + "Move": "MOVE_BRUTAL_SWING" + }, + { + "Level": "17", + "Move": "MOVE_SCREECH" + }, + { + "Level": "25", + "Move": "MOVE_TOXIC" + }, + { + "Level": "33", + "Move": "MOVE_LEECH_LIFE" + }, + { + "Level": "36", + "Move": "MOVE_POISON_JAB" + }, + { + "Level": "41", + "Move": "MOVE_HAZE" + }, + { + "Level": "49", + "Move": "MOVE_GUNK_SHOT" + } + ], + "TMMoves": [ + "MOVE_BODY_SLAM", + "MOVE_BULLDOZE", + "MOVE_DARK_PULSE", + "MOVE_DIG", + "MOVE_EARTHQUAKE", + "MOVE_ENDURE", + "MOVE_FIRE_FANG", + "MOVE_GIGA_DRAIN", + "MOVE_ICE_FANG", + "MOVE_IRON_TAIL", + "MOVE_KNOCK_OFF", + "MOVE_MUD_SHOT", + "MOVE_PROTECT", + "MOVE_ROCK_SLIDE", + "MOVE_ROCK_TOMB", + "MOVE_SLUDGE_BOMB", + "MOVE_SUBSTITUTE", + "MOVE_THUNDER_FANG" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "ARBOK": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_LEER" + }, + { + "Level": "4", + "Move": "MOVE_POISON_STING" + }, + { + "Level": "9", + "Move": "MOVE_BITE" + }, + { + "Level": "12", + "Move": "MOVE_GLARE" + }, + { + "Level": "15", + "Move": "MOVE_BRUTAL_SWING" + }, + { + "Level": "17", + "Move": "MOVE_SCREECH" + }, + { + "Level": "25", + "Move": "MOVE_TOXIC" + }, + { + "Level": "33", + "Move": "MOVE_LEECH_LIFE" + }, + { + "Level": "36", + "Move": "MOVE_POISON_JAB" + }, + { + "Level": "41", + "Move": "MOVE_HAZE" + }, + { + "Level": "49", + "Move": "MOVE_GUNK_SHOT" + } + ], + "TMMoves": [ + "MOVE_BODY_SLAM", + "MOVE_BULLDOZE", + "MOVE_DARK_PULSE", + "MOVE_DIG", + "MOVE_DOUBLE_EDGE", + "MOVE_EARTHQUAKE", + "MOVE_ENDURE", + "MOVE_FIRE_FANG", + "MOVE_GIGA_DRAIN", + "MOVE_GIGA_IMPACT", + "MOVE_HYPER_BEAM", + "MOVE_ICE_FANG", + "MOVE_IRON_TAIL", + "MOVE_KNOCK_OFF", + "MOVE_MUD_SHOT", + "MOVE_PROTECT", + "MOVE_ROCK_SLIDE", + "MOVE_ROCK_TOMB", + "MOVE_SLUDGE_BOMB", + "MOVE_SUBSTITUTE", + "MOVE_THUNDER_FANG" + ], + "TutorMoves": [ + "MOVE_CRUNCH" + ], + "EggMoves": [] + }, + "PIKACHU": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TAIL_WHIP" + }, + { + "Level": "1", + "Move": "MOVE_GROWL" + }, + { + "Level": "1", + "Move": "MOVE_THUNDER_SHOCK" + }, + { + "Level": "1", + "Move": "MOVE_QUICK_ATTACK" + }, + { + "Level": "4", + "Move": "MOVE_THUNDER_WAVE" + }, + { + "Level": "12", + "Move": "MOVE_NUZZLE" + }, + { + "Level": "16", + "Move": "MOVE_SPARK" + }, + { + "Level": "20", + "Move": "MOVE_CHARM" + }, + { + "Level": "25", + "Move": "MOVE_THUNDERBOLT" + }, + { + "Level": "30", + "Move": "MOVE_CHARGE" + }, + { + "Level": "35", + "Move": "MOVE_LIGHT_SCREEN" + }, + { + "Level": "40", + "Move": "MOVE_THUNDER" + }, + { + "Level": "99", + "Move": "MOVE_VOLT_TACKLE" + } + ], + "TMMoves": [ + "MOVE_AGILITY", + "MOVE_BODY_SLAM", + "MOVE_BRICK_BREAK", + "MOVE_DIG", + "MOVE_DISCHARGE", + "MOVE_DOUBLE_TEAM", + "MOVE_ELECTROWEB", + "MOVE_ENDURE", + "MOVE_IRON_TAIL", + "MOVE_NASTY_PLOT", + "MOVE_PLAY_ROUGH", + "MOVE_PROTECT", + "MOVE_REFLECT", + "MOVE_SUBSTITUTE", + "MOVE_SURF", + "MOVE_SWIFT", + "MOVE_THUNDER_PUNCH", + "MOVE_VOLT_SWITCH", + "MOVE_WILD_CHARGE" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "RAICHU": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TAIL_WHIP" + }, + { + "Level": "1", + "Move": "MOVE_GROWL" + }, + { + "Level": "1", + "Move": "MOVE_THUNDER_SHOCK" + }, + { + "Level": "1", + "Move": "MOVE_QUICK_ATTACK" + }, + { + "Level": "4", + "Move": "MOVE_THUNDER_WAVE" + }, + { + "Level": "12", + "Move": "MOVE_NUZZLE" + }, + { + "Level": "16", + "Move": "MOVE_SPARK" + }, + { + "Level": "20", + "Move": "MOVE_CHARM" + }, + { + "Level": "25", + "Move": "MOVE_THUNDERBOLT" + }, + { + "Level": "30", + "Move": "MOVE_CHARGE" + }, + { + "Level": "35", + "Move": "MOVE_LIGHT_SCREEN" + }, + { + "Level": "40", + "Move": "MOVE_THUNDER" + }, + { + "Level": "99", + "Move": "MOVE_VOLT_TACKLE" + } + ], + "TMMoves": [ + "MOVE_AGILITY", + "MOVE_BODY_SLAM", + "MOVE_BRICK_BREAK", + "MOVE_DIG", + "MOVE_DISCHARGE", + "MOVE_DOUBLE_TEAM", + "MOVE_ELECTROWEB", + "MOVE_ENDURE", + "MOVE_GIGA_IMPACT", + "MOVE_HYPER_BEAM", + "MOVE_IRON_TAIL", + "MOVE_NASTY_PLOT", + "MOVE_PLAY_ROUGH", + "MOVE_PROTECT", + "MOVE_REFLECT", + "MOVE_SUBSTITUTE", + "MOVE_SURF", + "MOVE_SWIFT", + "MOVE_VOLT_SWITCH", + "MOVE_WILD_CHARGE" + ], + "TutorMoves": [ + "MOVE_EERIE_IMPULSE", + "MOVE_THUNDER_PUNCH" + ], + "EggMoves": [] + }, + "RAICHU_ALOLA": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TAIL_WHIP" + }, + { + "Level": "1", + "Move": "MOVE_GROWL" + }, + { + "Level": "1", + "Move": "MOVE_THUNDER_SHOCK" + }, + { + "Level": "1", + "Move": "MOVE_QUICK_ATTACK" + }, + { + "Level": "4", + "Move": "MOVE_THUNDER_WAVE" + }, + { + "Level": "12", + "Move": "MOVE_NUZZLE" + }, + { + "Level": "16", + "Move": "MOVE_SPARK" + }, + { + "Level": "20", + "Move": "MOVE_CHARM" + }, + { + "Level": "25", + "Move": "MOVE_THUNDERBOLT" + }, + { + "Level": "30", + "Move": "MOVE_CHARGE" + }, + { + "Level": "35", + "Move": "MOVE_LIGHT_SCREEN" + }, + { + "Level": "40", + "Move": "MOVE_THUNDER" + }, + { + "Level": "99", + "Move": "MOVE_VOLT_TACKLE" + } + ], + "TMMoves": [ + "MOVE_AGILITY", + "MOVE_BODY_SLAM", + "MOVE_BRICK_BREAK", + "MOVE_CALM_MIND", + "MOVE_DIG", + "MOVE_DISCHARGE", + "MOVE_DOUBLE_TEAM", + "MOVE_ELECTROWEB", + "MOVE_ENDURE", + "MOVE_GIGA_IMPACT", + "MOVE_HYPER_BEAM", + "MOVE_IRON_TAIL", + "MOVE_NASTY_PLOT", + "MOVE_PLAY_ROUGH", + "MOVE_PROTECT", + "MOVE_PSYSHOCK", + "MOVE_REFLECT", + "MOVE_SUBSTITUTE", + "MOVE_SURF", + "MOVE_SWIFT", + "MOVE_THUNDER_PUNCH", + "MOVE_VOLT_SWITCH", + "MOVE_WILD_CHARGE" + ], + "TutorMoves": [ + "MOVE_EERIE_IMPULSE", + "MOVE_PSYCHIC" + ], + "EggMoves": [] + }, + "CLEFAIRY": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_SPLASH" + }, + { + "Level": "5", + "Move": "MOVE_FAIRY_WIND" + }, + { + "Level": "8", + "Move": "MOVE_DISARMING_VOICE" + }, + { + "Level": "13", + "Move": "MOVE_CHARM" + }, + { + "Level": "16", + "Move": "MOVE_DRAINING_KISS" + }, + { + "Level": "18", + "Move": "MOVE_MAGICAL_LEAF" + }, + { + "Level": "20", + "Move": "MOVE_METRONOME" + }, + { + "Level": "22", + "Move": "MOVE_BUBBLE_BEAM" + }, + { + "Level": "24", + "Move": "MOVE_MOONLIGHT" + }, + { + "Level": "28", + "Move": "MOVE_AMNESIA" + }, + { + "Level": "32", + "Move": "MOVE_DAZZLING_GLEAM" + }, + { + "Level": "42", + "Move": "MOVE_MYSTICAL_FIRE" + }, + { + "Level": "48", + "Move": "MOVE_MOONBLAST" + }, + { + "Level": "55", + "Move": "MOVE_DOUBLE_EDGE" + } + ], + "TMMoves": [ + "MOVE_BLIZZARD", + "MOVE_BODY_SLAM", + "MOVE_CALM_MIND", + "MOVE_DIG", + "MOVE_ENDURE", + "MOVE_FIRE_BLAST", + "MOVE_FIRE_PUNCH", + "MOVE_FLAMETHROWER", + "MOVE_HEADBUTT", + "MOVE_HEAL_BLOCK", + "MOVE_HYPER_VOICE", + "MOVE_ICE_BEAM", + "MOVE_ICE_PUNCH", + "MOVE_IRON_TAIL", + "MOVE_LIGHT_SCREEN", + "MOVE_PLAY_ROUGH", + "MOVE_PROTECT", + "MOVE_PSYCHIC", + "MOVE_PSYSHOCK", + "MOVE_REFLECT", + "MOVE_SAFEGUARD", + "MOVE_SHADOW_BALL", + "MOVE_SOLAR_BEAM", + "MOVE_STEALTH_ROCK", + "MOVE_SUBSTITUTE", + "MOVE_SWIFT", + "MOVE_THUNDER", + "MOVE_THUNDERBOLT", + "MOVE_THUNDER_PUNCH", + "MOVE_THUNDER_WAVE", + "MOVE_WORK_UP", + "MOVE_ZEN_HEADBUTT" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "CLEFABLE": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_SPLASH" + }, + { + "Level": "5", + "Move": "MOVE_FAIRY_WIND" + }, + { + "Level": "8", + "Move": "MOVE_DISARMING_VOICE" + }, + { + "Level": "13", + "Move": "MOVE_CHARM" + }, + { + "Level": "16", + "Move": "MOVE_DRAINING_KISS" + }, + { + "Level": "18", + "Move": "MOVE_MAGICAL_LEAF" + }, + { + "Level": "20", + "Move": "MOVE_METRONOME" + }, + { + "Level": "22", + "Move": "MOVE_BUBBLE_BEAM" + }, + { + "Level": "24", + "Move": "MOVE_MOONLIGHT" + }, + { + "Level": "28", + "Move": "MOVE_AMNESIA" + }, + { + "Level": "32", + "Move": "MOVE_DAZZLING_GLEAM" + }, + { + "Level": "42", + "Move": "MOVE_MYSTICAL_FIRE" + }, + { + "Level": "48", + "Move": "MOVE_MOONBLAST" + }, + { + "Level": "52", + "Move": "MOVE_AIR_SLASH" + }, + { + "Level": "55", + "Move": "MOVE_DOUBLE_EDGE" + } + ], + "TMMoves": [ + "MOVE_BLIZZARD", + "MOVE_BODY_SLAM", + "MOVE_CALM_MIND", + "MOVE_DIG", + "MOVE_ENDURE", + "MOVE_FIRE_BLAST", + "MOVE_FIRE_PUNCH", + "MOVE_FLAMETHROWER", + "MOVE_FOCUS_BLAST", + "MOVE_GIGA_IMPACT", + "MOVE_HEADBUTT", + "MOVE_HEAL_BLOCK", + "MOVE_HYPER_BEAM", + "MOVE_HYPER_VOICE", + "MOVE_ICE_BEAM", + "MOVE_ICE_PUNCH", + "MOVE_IRON_TAIL", + "MOVE_LIGHT_SCREEN", + "MOVE_PLAY_ROUGH", + "MOVE_PROTECT", + "MOVE_PSYCHIC", + "MOVE_PSYSHOCK", + "MOVE_REFLECT", + "MOVE_SAFEGUARD", + "MOVE_SHADOW_BALL", + "MOVE_SOLAR_BEAM", + "MOVE_STEALTH_ROCK", + "MOVE_SUBSTITUTE", + "MOVE_SWIFT", + "MOVE_THUNDER", + "MOVE_THUNDERBOLT", + "MOVE_THUNDER_PUNCH", + "MOVE_THUNDER_WAVE", + "MOVE_WORK_UP", + "MOVE_ZEN_HEADBUTT" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "ABRA": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TELEPORT" + } + ], + "TMMoves": [ + "MOVE_BODY_SLAM", + "MOVE_CALM_MIND", + "MOVE_DAZZLING_GLEAM", + "MOVE_DOUBLE_TEAM", + "MOVE_ENDURE", + "MOVE_ENERGY_BALL", + "MOVE_FIRE_PUNCH", + "MOVE_ICE_PUNCH", + "MOVE_IRON_TAIL", + "MOVE_LIGHT_SCREEN", + "MOVE_METRONOME", + "MOVE_PROTECT", + "MOVE_PSYCHIC", + "MOVE_REFLECT", + "MOVE_SAFEGUARD", + "MOVE_SHADOW_BALL", + "MOVE_SUBSTITUTE", + "MOVE_SWIFT", + "MOVE_TAUNT", + "MOVE_THUNDER_PUNCH", + "MOVE_THUNDER_WAVE", + "MOVE_ZEN_HEADBUTT" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "KADABRA": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_PSYBEAM" + }, + { + "Level": "1", + "Move": "MOVE_TELEPORT" + }, + { + "Level": "10", + "Move": "MOVE_REFLECT" + }, + { + "Level": "20", + "Move": "MOVE_PSYCHO_CUT" + }, + { + "Level": "25", + "Move": "MOVE_RECOVER" + }, + { + "Level": "30", + "Move": "MOVE_PSYSHOCK" + }, + { + "Level": "35", + "Move": "MOVE_PSYCHIC" + }, + { + "Level": "40", + "Move": "MOVE_SAFEGUARD" + }, + { + "Level": "45", + "Move": "MOVE_FUTURE_SIGHT" + }, + { + "Level": "50", + "Move": "MOVE_CALM_MIND" + } + ], + "TMMoves": [ + "MOVE_BODY_SLAM", + "MOVE_DAZZLING_GLEAM", + "MOVE_DOUBLE_TEAM", + "MOVE_ENDURE", + "MOVE_ENERGY_BALL", + "MOVE_FIRE_PUNCH", + "MOVE_ICE_PUNCH", + "MOVE_IRON_TAIL", + "MOVE_LIGHT_SCREEN", + "MOVE_METRONOME", + "MOVE_PROTECT", + "MOVE_SHADOW_BALL", + "MOVE_SUBSTITUTE", + "MOVE_SWIFT", + "MOVE_TAUNT", + "MOVE_THUNDER_PUNCH", + "MOVE_THUNDER_WAVE", + "MOVE_ZEN_HEADBUTT" + ], + "TutorMoves": [ + "MOVE_CONFUSION" + ], + "EggMoves": [] + }, + "ALAKAZAM": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_PSYBEAM" + }, + { + "Level": "1", + "Move": "MOVE_TELEPORT" + }, + { + "Level": "10", + "Move": "MOVE_REFLECT" + }, + { + "Level": "20", + "Move": "MOVE_PSYCHO_CUT" + }, + { + "Level": "25", + "Move": "MOVE_RECOVER" + }, + { + "Level": "30", + "Move": "MOVE_PSYSHOCK" + }, + { + "Level": "35", + "Move": "MOVE_PSYCHIC" + }, + { + "Level": "40", + "Move": "MOVE_SAFEGUARD" + }, + { + "Level": "45", + "Move": "MOVE_FUTURE_SIGHT" + }, + { + "Level": "50", + "Move": "MOVE_CALM_MIND" + } + ], + "TMMoves": [ + "MOVE_BODY_SLAM", + "MOVE_DAZZLING_GLEAM", + "MOVE_DOUBLE_TEAM", + "MOVE_ENDURE", + "MOVE_ENERGY_BALL", + "MOVE_FIRE_PUNCH", + "MOVE_FOCUS_BLAST", + "MOVE_HYPER_BEAM", + "MOVE_ICE_PUNCH", + "MOVE_IRON_TAIL", + "MOVE_LIGHT_SCREEN", + "MOVE_METRONOME", + "MOVE_NASTY_PLOT", + "MOVE_PROTECT", + "MOVE_SHADOW_BALL", + "MOVE_SUBSTITUTE", + "MOVE_SWIFT", + "MOVE_TAUNT", + "MOVE_THUNDER_PUNCH", + "MOVE_THUNDER_WAVE", + "MOVE_ZEN_HEADBUTT" + ], + "TutorMoves": [ + "MOVE_CONFUSION" + ], + "EggMoves": [] + }, + "MACHOP": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_LEER" + }, + { + "Level": "1", + "Move": "MOVE_ROCK_SMASH" + }, + { + "Level": "4", + "Move": "MOVE_FOCUS_ENERGY" + }, + { + "Level": "12", + "Move": "MOVE_POWER_UP_PUNCH" + }, + { + "Level": "14", + "Move": "MOVE_BRUTAL_SWING" + }, + { + "Level": "16", + "Move": "MOVE_BULLET_PUNCH" + }, + { + "Level": "18", + "Move": "MOVE_KNOCK_OFF" + }, + { + "Level": "20", + "Move": "MOVE_BULK_UP" + }, + { + "Level": "25", + "Move": "MOVE_BRICK_BREAK" + }, + { + "Level": "30", + "Move": "MOVE_BULLDOZE" + }, + { + "Level": "36", + "Move": "MOVE_DETECT" + }, + { + "Level": "44", + "Move": "MOVE_DOUBLE_EDGE" + }, + { + "Level": "54", + "Move": "MOVE_DYNAMIC_PUNCH" + } + ], + "TMMoves": [ + "MOVE_BODY_SLAM", + "MOVE_CLOSE_COMBAT", + "MOVE_DIG", + "MOVE_EARTHQUAKE", + "MOVE_ENDURE", + "MOVE_FIRE_BLAST", + "MOVE_FIRE_PUNCH", + "MOVE_FLAMETHROWER", + "MOVE_FOCUS_BLAST", + "MOVE_ICE_PUNCH", + "MOVE_LIGHT_SCREEN", + "MOVE_METRONOME", + "MOVE_POISON_JAB", + "MOVE_PROTECT", + "MOVE_ROCK_SLIDE", + "MOVE_ROCK_TOMB", + "MOVE_SUBSTITUTE", + "MOVE_THUNDER_PUNCH", + "MOVE_WORK_UP" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "MACHOKE": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_LEER" + }, + { + "Level": "1", + "Move": "MOVE_ROCK_SMASH" + }, + { + "Level": "4", + "Move": "MOVE_FOCUS_ENERGY" + }, + { + "Level": "12", + "Move": "MOVE_POWER_UP_PUNCH" + }, + { + "Level": "14", + "Move": "MOVE_BRUTAL_SWING" + }, + { + "Level": "16", + "Move": "MOVE_BULLET_PUNCH" + }, + { + "Level": "18", + "Move": "MOVE_KNOCK_OFF" + }, + { + "Level": "20", + "Move": "MOVE_BULK_UP" + }, + { + "Level": "25", + "Move": "MOVE_BRICK_BREAK" + }, + { + "Level": "30", + "Move": "MOVE_BULLDOZE" + }, + { + "Level": "36", + "Move": "MOVE_DETECT" + }, + { + "Level": "44", + "Move": "MOVE_DOUBLE_EDGE" + }, + { + "Level": "54", + "Move": "MOVE_DYNAMIC_PUNCH" + } + ], + "TMMoves": [ + "MOVE_BODY_SLAM", + "MOVE_CLOSE_COMBAT", + "MOVE_DIG", + "MOVE_EARTHQUAKE", + "MOVE_ENDURE", + "MOVE_FIRE_BLAST", + "MOVE_FIRE_PUNCH", + "MOVE_FLAMETHROWER", + "MOVE_FOCUS_BLAST", + "MOVE_ICE_PUNCH", + "MOVE_LIGHT_SCREEN", + "MOVE_METRONOME", + "MOVE_POISON_JAB", + "MOVE_PROTECT", + "MOVE_ROCK_SLIDE", + "MOVE_ROCK_TOMB", + "MOVE_SUBSTITUTE", + "MOVE_THUNDER_PUNCH", + "MOVE_WORK_UP" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "MACHAMP": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_LEER" + }, + { + "Level": "1", + "Move": "MOVE_ROCK_SMASH" + }, + { + "Level": "4", + "Move": "MOVE_FOCUS_ENERGY" + }, + { + "Level": "12", + "Move": "MOVE_POWER_UP_PUNCH" + }, + { + "Level": "14", + "Move": "MOVE_BRUTAL_SWING" + }, + { + "Level": "16", + "Move": "MOVE_BULLET_PUNCH" + }, + { + "Level": "18", + "Move": "MOVE_KNOCK_OFF" + }, + { + "Level": "20", + "Move": "MOVE_BULK_UP" + }, + { + "Level": "25", + "Move": "MOVE_BRICK_BREAK" + }, + { + "Level": "30", + "Move": "MOVE_BULLDOZE" + }, + { + "Level": "36", + "Move": "MOVE_DETECT" + }, + { + "Level": "40", + "Move": "MOVE_HEAVY_SLAM" + }, + { + "Level": "44", + "Move": "MOVE_DOUBLE_EDGE" + }, + { + "Level": "54", + "Move": "MOVE_DYNAMIC_PUNCH" + } + ], + "TMMoves": [ + "MOVE_BODY_SLAM", + "MOVE_CLOSE_COMBAT", + "MOVE_DIG", + "MOVE_EARTHQUAKE", + "MOVE_ENDURE", + "MOVE_FIRE_BLAST", + "MOVE_FIRE_PUNCH", + "MOVE_FLAMETHROWER", + "MOVE_FOCUS_BLAST", + "MOVE_GIGA_IMPACT", + "MOVE_HYPER_BEAM", + "MOVE_ICE_PUNCH", + "MOVE_LIGHT_SCREEN", + "MOVE_METRONOME", + "MOVE_POISON_JAB", + "MOVE_PROTECT", + "MOVE_ROCK_SLIDE", + "MOVE_ROCK_TOMB", + "MOVE_STONE_EDGE", + "MOVE_SUBSTITUTE", + "MOVE_THUNDER_PUNCH", + "MOVE_WORK_UP" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "BELLSPROUT": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_VINE_WHIP" + }, + { + "Level": "1", + "Move": "MOVE_GROWTH" + }, + { + "Level": "8", + "Move": "MOVE_INFESTATION" + }, + { + "Level": "10", + "Move": "MOVE_RAZOR_LEAF" + }, + { + "Level": "13", + "Move": "MOVE_SLEEP_POWDER" + }, + { + "Level": "15", + "Move": "MOVE_POISON_POWDER" + }, + { + "Level": "17", + "Move": "MOVE_STUN_SPORE" + }, + { + "Level": "19", + "Move": "MOVE_KNOCK_OFF" + }, + { + "Level": "23", + "Move": "MOVE_MAGICAL_LEAF" + }, + { + "Level": "26", + "Move": "MOVE_TOXIC_SPIKES" + }, + { + "Level": "30", + "Move": "MOVE_POISON_JAB" + }, + { + "Level": "33", + "Move": "MOVE_LEECH_LIFE" + }, + { + "Level": "40", + "Move": "MOVE_SLUDGE_WAVE" + }, + { + "Level": "44", + "Move": "MOVE_POWER_WHIP" + }, + { + "Level": "48", + "Move": "MOVE_LEAF_STORM" + } + ], + "TMMoves": [ + "MOVE_BULLET_SEED", + "MOVE_ENDURE", + "MOVE_ENERGY_BALL", + "MOVE_GIGA_DRAIN", + "MOVE_PROTECT", + "MOVE_REFLECT", + "MOVE_SOLAR_BEAM", + "MOVE_SUBSTITUTE", + "MOVE_SWORDS_DANCE", + "MOVE_TOXIC" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "WEEPINBELL": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_VINE_WHIP" + }, + { + "Level": "1", + "Move": "MOVE_GROWTH" + }, + { + "Level": "8", + "Move": "MOVE_INFESTATION" + }, + { + "Level": "10", + "Move": "MOVE_RAZOR_LEAF" + }, + { + "Level": "13", + "Move": "MOVE_SLEEP_POWDER" + }, + { + "Level": "15", + "Move": "MOVE_POISON_POWDER" + }, + { + "Level": "17", + "Move": "MOVE_STUN_SPORE" + }, + { + "Level": "19", + "Move": "MOVE_KNOCK_OFF" + }, + { + "Level": "23", + "Move": "MOVE_MAGICAL_LEAF" + }, + { + "Level": "26", + "Move": "MOVE_TOXIC_SPIKES" + }, + { + "Level": "30", + "Move": "MOVE_POISON_JAB" + }, + { + "Level": "33", + "Move": "MOVE_LEECH_LIFE" + }, + { + "Level": "40", + "Move": "MOVE_SLUDGE_WAVE" + }, + { + "Level": "44", + "Move": "MOVE_POWER_WHIP" + }, + { + "Level": "48", + "Move": "MOVE_LEAF_STORM" + } + ], + "TMMoves": [ + "MOVE_BULLET_SEED", + "MOVE_ENDURE", + "MOVE_ENERGY_BALL", + "MOVE_GIGA_DRAIN", + "MOVE_PROTECT", + "MOVE_REFLECT", + "MOVE_SOLAR_BEAM", + "MOVE_SUBSTITUTE", + "MOVE_SWORDS_DANCE", + "MOVE_TOXIC" + ], + "TutorMoves": [ + "MOVE_LUNGE" + ], + "EggMoves": [] + }, + "VICTREEBEL": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_VINE_WHIP" + }, + { + "Level": "1", + "Move": "MOVE_GROWTH" + }, + { + "Level": "1", + "Move": "MOVE_LUNGE" + }, + { + "Level": "8", + "Move": "MOVE_INFESTATION" + }, + { + "Level": "10", + "Move": "MOVE_RAZOR_LEAF" + }, + { + "Level": "13", + "Move": "MOVE_SLEEP_POWDER" + }, + { + "Level": "15", + "Move": "MOVE_POISON_POWDER" + }, + { + "Level": "17", + "Move": "MOVE_STUN_SPORE" + }, + { + "Level": "19", + "Move": "MOVE_KNOCK_OFF" + }, + { + "Level": "23", + "Move": "MOVE_MAGICAL_LEAF" + }, + { + "Level": "26", + "Move": "MOVE_TOXIC_SPIKES" + }, + { + "Level": "30", + "Move": "MOVE_POISON_JAB" + }, + { + "Level": "33", + "Move": "MOVE_LEECH_LIFE" + }, + { + "Level": "40", + "Move": "MOVE_SLUDGE_WAVE" + }, + { + "Level": "44", + "Move": "MOVE_POWER_WHIP" + }, + { + "Level": "48", + "Move": "MOVE_LEAF_STORM" + } + ], + "TMMoves": [ + "MOVE_BULLET_SEED", + "MOVE_ENDURE", + "MOVE_ENERGY_BALL", + "MOVE_GIGA_DRAIN", + "MOVE_GIGA_IMPACT", + "MOVE_HYPER_BEAM", + "MOVE_PROTECT", + "MOVE_REFLECT", + "MOVE_SOLAR_BEAM", + "MOVE_SUBSTITUTE", + "MOVE_SWORDS_DANCE", + "MOVE_TOXIC" + ], + "TutorMoves": [ + "MOVE_SLUDGE_BOMB" + ], + "EggMoves": [] + }, + "SLOWPOKE": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_CONFUSION" + }, + { + "Level": "1", + "Move": "MOVE_CURSE" + }, + { + "Level": "3", + "Move": "MOVE_GROWL" + }, + { + "Level": "6", + "Move": "MOVE_WATER_GUN" + }, + { + "Level": "14", + "Move": "MOVE_PSYBEAM" + }, + { + "Level": "18", + "Move": "MOVE_WATER_PULSE" + }, + { + "Level": "21", + "Move": "MOVE_HEADBUTT" + }, + { + "Level": "24", + "Move": "MOVE_ZEN_HEADBUTT" + }, + { + "Level": "27", + "Move": "MOVE_AMNESIA" + }, + { + "Level": "36", + "Move": "MOVE_SURF" + }, + { + "Level": "42", + "Move": "MOVE_PSYCHIC" + } + ], + "TMMoves": [ + "MOVE_BLIZZARD", + "MOVE_BODY_SLAM", + "MOVE_CALM_MIND", + "MOVE_DIG", + "MOVE_EARTHQUAKE", + "MOVE_ENDURE", + "MOVE_FIRE_BLAST", + "MOVE_FLAMETHROWER", + "MOVE_HYDRO_PUMP", + "MOVE_ICE_BEAM", + "MOVE_ICY_WIND", + "MOVE_IRON_TAIL", + "MOVE_LIGHT_SCREEN", + "MOVE_LIQUIDATION", + "MOVE_MUD_SHOT", + "MOVE_PROTECT", + "MOVE_PSYSHOCK", + "MOVE_SAFEGUARD", + "MOVE_SHADOW_BALL", + "MOVE_SUBSTITUTE", + "MOVE_SWIFT", + "MOVE_THUNDER_WAVE", + "MOVE_WATERFALL", + "MOVE_WHIRLPOOL" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "SLOWBRO": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_CONFUSION" + }, + { + "Level": "1", + "Move": "MOVE_CURSE" + }, + { + "Level": "3", + "Move": "MOVE_GROWL" + }, + { + "Level": "6", + "Move": "MOVE_WATER_GUN" + }, + { + "Level": "14", + "Move": "MOVE_PSYBEAM" + }, + { + "Level": "18", + "Move": "MOVE_WATER_PULSE" + }, + { + "Level": "21", + "Move": "MOVE_HEADBUTT" + }, + { + "Level": "24", + "Move": "MOVE_ZEN_HEADBUTT" + }, + { + "Level": "27", + "Move": "MOVE_AMNESIA" + }, + { + "Level": "36", + "Move": "MOVE_SURF" + }, + { + "Level": "42", + "Move": "MOVE_PSYCHIC" + }, + { + "Level": "45", + "Move": "MOVE_FUTURE_SIGHT" + } + ], + "TMMoves": [ + "MOVE_BLIZZARD", + "MOVE_BODY_SLAM", + "MOVE_CALM_MIND", + "MOVE_DIG", + "MOVE_EARTHQUAKE", + "MOVE_ENDURE", + "MOVE_FIRE_BLAST", + "MOVE_FLAMETHROWER", + "MOVE_FOCUS_BLAST", + "MOVE_GIGA_IMPACT", + "MOVE_HEAL_BLOCK", + "MOVE_HYDRO_PUMP", + "MOVE_HYPER_BEAM", + "MOVE_ICE_BEAM", + "MOVE_ICE_PUNCH", + "MOVE_ICY_WIND", + "MOVE_IRON_TAIL", + "MOVE_LIGHT_SCREEN", + "MOVE_LIQUIDATION", + "MOVE_METRONOME", + "MOVE_MUD_SHOT", + "MOVE_NASTY_PLOT", + "MOVE_POWER_GEM", + "MOVE_PROTECT", + "MOVE_PSYSHOCK", + "MOVE_SAFEGUARD", + "MOVE_SHADOW_BALL", + "MOVE_SUBSTITUTE", + "MOVE_SWIFT", + "MOVE_THUNDER_WAVE", + "MOVE_WATERFALL", + "MOVE_WHIRLPOOL" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "SLOWBRO_GALAR": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_CONFUSION" + }, + { + "Level": "1", + "Move": "MOVE_CURSE" + }, + { + "Level": "3", + "Move": "MOVE_GROWL" + }, + { + "Level": "6", + "Move": "MOVE_WATER_GUN" + }, + { + "Level": "14", + "Move": "MOVE_PSYBEAM" + }, + { + "Level": "18", + "Move": "MOVE_WATER_PULSE" + }, + { + "Level": "21", + "Move": "MOVE_HEADBUTT" + }, + { + "Level": "24", + "Move": "MOVE_ZEN_HEADBUTT" + }, + { + "Level": "27", + "Move": "MOVE_AMNESIA" + }, + { + "Level": "33", + "Move": "MOVE_POISON_JAB" + }, + { + "Level": "36", + "Move": "MOVE_SURF" + }, + { + "Level": "40", + "Move": "MOVE_SLUDGE_BOMB" + }, + { + "Level": "42", + "Move": "MOVE_PSYCHIC" + }, + { + "Level": "45", + "Move": "MOVE_FUTURE_SIGHT" + } + ], + "TMMoves": [ + "MOVE_BLIZZARD", + "MOVE_BODY_SLAM", + "MOVE_CALM_MIND", + "MOVE_DIG", + "MOVE_DOUBLE_EDGE", + "MOVE_EARTHQUAKE", + "MOVE_ENDURE", + "MOVE_FIRE_BLAST", + "MOVE_FIRE_PUNCH", + "MOVE_FLAMETHROWER", + "MOVE_FOCUS_BLAST", + "MOVE_GIGA_IMPACT", + "MOVE_GUNK_SHOT", + "MOVE_HEAL_BLOCK", + "MOVE_HYDRO_PUMP", + "MOVE_HYPER_BEAM", + "MOVE_ICE_BEAM", + "MOVE_ICY_WIND", + "MOVE_IRON_TAIL", + "MOVE_LIGHT_SCREEN", + "MOVE_LIQUIDATION", + "MOVE_METRONOME", + "MOVE_MUD_SHOT", + "MOVE_NASTY_PLOT", + "MOVE_PROTECT", + "MOVE_PSYSHOCK", + "MOVE_SAFEGUARD", + "MOVE_SHADOW_BALL", + "MOVE_SUBSTITUTE", + "MOVE_SWIFT", + "MOVE_THUNDER_PUNCH", + "MOVE_THUNDER_WAVE", + "MOVE_TOXIC", + "MOVE_TOXIC_SPIKES", + "MOVE_WATERFALL", + "MOVE_WHIRLPOOL" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "GASTLY": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_CONFUSE_RAY" + }, + { + "Level": "1", + "Move": "MOVE_LICK" + }, + { + "Level": "4", + "Move": "MOVE_HYPNOSIS" + }, + { + "Level": "8", + "Move": "MOVE_CONFUSION" + }, + { + "Level": "12", + "Move": "MOVE_SHADOW_SNEAK" + }, + { + "Level": "20", + "Move": "MOVE_CURSE" + }, + { + "Level": "24", + "Move": "MOVE_HAZE" + }, + { + "Level": "28", + "Move": "MOVE_ICY_WIND" + }, + { + "Level": "36", + "Move": "MOVE_DARK_PULSE" + }, + { + "Level": "40", + "Move": "MOVE_SHADOW_BALL" + }, + { + "Level": "50", + "Move": "MOVE_PERISH_SONG" + } + ], + "TMMoves": [ + "MOVE_DAZZLING_GLEAM", + "MOVE_ENDURE", + "MOVE_ENERGY_BALL", + "MOVE_GIGA_DRAIN", + "MOVE_GUNK_SHOT", + "MOVE_NASTY_PLOT", + "MOVE_POISON_JAB", + "MOVE_PROTECT", + "MOVE_PSYCHIC", + "MOVE_SELF_DESTRUCT", + "MOVE_SLUDGE_BOMB", + "MOVE_SUBSTITUTE", + "MOVE_TAUNT", + "MOVE_THUNDER", + "MOVE_THUNDERBOLT", + "MOVE_TOXIC", + "MOVE_WILL_O_WISP" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "HAUNTER": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_CONFUSE_RAY" + }, + { + "Level": "1", + "Move": "MOVE_LICK" + }, + { + "Level": "4", + "Move": "MOVE_HYPNOSIS" + }, + { + "Level": "8", + "Move": "MOVE_CONFUSION" + }, + { + "Level": "12", + "Move": "MOVE_SHADOW_SNEAK" + }, + { + "Level": "16", + "Move": "MOVE_SHADOW_CLAW" + }, + { + "Level": "20", + "Move": "MOVE_CURSE" + }, + { + "Level": "24", + "Move": "MOVE_HAZE" + }, + { + "Level": "28", + "Move": "MOVE_ICY_WIND" + }, + { + "Level": "36", + "Move": "MOVE_DARK_PULSE" + }, + { + "Level": "40", + "Move": "MOVE_SHADOW_BALL" + }, + { + "Level": "48", + "Move": "MOVE_SLUDGE_WAVE" + }, + { + "Level": "50", + "Move": "MOVE_PERISH_SONG" + }, + { + "Level": "55", + "Move": "MOVE_PHANTOM_FORCE" + } + ], + "TMMoves": [ + "MOVE_DAZZLING_GLEAM", + "MOVE_ENDURE", + "MOVE_ENERGY_BALL", + "MOVE_FIRE_PUNCH", + "MOVE_GIGA_DRAIN", + "MOVE_GUNK_SHOT", + "MOVE_ICE_PUNCH", + "MOVE_METRONOME", + "MOVE_NASTY_PLOT", + "MOVE_POISON_JAB", + "MOVE_PROTECT", + "MOVE_PSYCHIC", + "MOVE_SELF_DESTRUCT", + "MOVE_SLUDGE_BOMB", + "MOVE_SUBSTITUTE", + "MOVE_TAUNT", + "MOVE_THUNDER", + "MOVE_THUNDERBOLT", + "MOVE_THUNDER_PUNCH", + "MOVE_TOXIC", + "MOVE_TOXIC_SPIKES", + "MOVE_WILL_O_WISP" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "GENGAR": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_CONFUSE_RAY" + }, + { + "Level": "1", + "Move": "MOVE_LICK" + }, + { + "Level": "4", + "Move": "MOVE_HYPNOSIS" + }, + { + "Level": "8", + "Move": "MOVE_CONFUSION" + }, + { + "Level": "12", + "Move": "MOVE_SHADOW_SNEAK" + }, + { + "Level": "16", + "Move": "MOVE_SHADOW_CLAW" + }, + { + "Level": "20", + "Move": "MOVE_CURSE" + }, + { + "Level": "24", + "Move": "MOVE_HAZE" + }, + { + "Level": "28", + "Move": "MOVE_ICY_WIND" + }, + { + "Level": "36", + "Move": "MOVE_DARK_PULSE" + }, + { + "Level": "40", + "Move": "MOVE_SHADOW_BALL" + }, + { + "Level": "48", + "Move": "MOVE_SLUDGE_WAVE" + }, + { + "Level": "50", + "Move": "MOVE_PERISH_SONG" + }, + { + "Level": "55", + "Move": "MOVE_PHANTOM_FORCE" + } + ], + "TMMoves": [ + "MOVE_DAZZLING_GLEAM", + "MOVE_ENDURE", + "MOVE_ENERGY_BALL", + "MOVE_FIRE_PUNCH", + "MOVE_FOCUS_BLAST", + "MOVE_GIGA_DRAIN", + "MOVE_GIGA_IMPACT", + "MOVE_GUNK_SHOT", + "MOVE_HYPER_BEAM", + "MOVE_ICE_PUNCH", + "MOVE_METRONOME", + "MOVE_NASTY_PLOT", + "MOVE_POISON_JAB", + "MOVE_PROTECT", + "MOVE_PSYCHIC", + "MOVE_SELF_DESTRUCT", + "MOVE_SLUDGE_BOMB", + "MOVE_SUBSTITUTE", + "MOVE_TAUNT", + "MOVE_THUNDER", + "MOVE_THUNDERBOLT", + "MOVE_THUNDER_PUNCH", + "MOVE_THUNDER_WAVE", + "MOVE_TOXIC", + "MOVE_TOXIC_SPIKES", + "MOVE_WILL_O_WISP" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "ONIX": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_ROCK_THROW" + }, + { + "Level": "1", + "Move": "MOVE_HARDEN" + }, + { + "Level": "12", + "Move": "MOVE_DRAGON_BREATH" + }, + { + "Level": "16", + "Move": "MOVE_CURSE" + }, + { + "Level": "20", + "Move": "MOVE_ROCK_SLIDE" + }, + { + "Level": "22", + "Move": "MOVE_BREAKING_SWIPE" + }, + { + "Level": "24", + "Move": "MOVE_SCREECH" + }, + { + "Level": "28", + "Move": "MOVE_SAND_TOMB" + }, + { + "Level": "32", + "Move": "MOVE_STEALTH_ROCK" + }, + { + "Level": "44", + "Move": "MOVE_DIG" + }, + { + "Level": "48", + "Move": "MOVE_IRON_TAIL" + }, + { + "Level": "52", + "Move": "MOVE_STONE_EDGE" + }, + { + "Level": "56", + "Move": "MOVE_DOUBLE_EDGE" + }, + { + "Level": "62", + "Move": "MOVE_HEAD_SMASH" + } + ], + "TMMoves": [ + "MOVE_DRAGON_PULSE", + "MOVE_EARTHQUAKE", + "MOVE_ENDURE", + "MOVE_IRON_HEAD", + "MOVE_PROTECT", + "MOVE_ROCK_BLAST", + "MOVE_ROCK_TOMB", + "MOVE_SELF_DESTRUCT", + "MOVE_SUBSTITUTE", + "MOVE_TAUNT" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "KANGASKHAN": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_TAIL_WHIP" + }, + { + "Level": "4", + "Move": "MOVE_GROWL" + }, + { + "Level": "12", + "Move": "MOVE_BITE" + }, + { + "Level": "20", + "Move": "MOVE_FOCUS_ENERGY" + }, + { + "Level": "24", + "Move": "MOVE_HEADBUTT" + }, + { + "Level": "32", + "Move": "MOVE_TAKE_DOWN" + }, + { + "Level": "36", + "Move": "MOVE_CRUNCH" + }, + { + "Level": "40", + "Move": "MOVE_ENDURE" + }, + { + "Level": "48", + "Move": "MOVE_OUTRAGE" + }, + { + "Level": "54", + "Move": "MOVE_DYNAMIC_PUNCH" + } + ], + "TMMoves": [ + "MOVE_AERIAL_ACE", + "MOVE_BLIZZARD", + "MOVE_BODY_SLAM", + "MOVE_BRICK_BREAK", + "MOVE_BULLDOZE", + "MOVE_DIG", + "MOVE_DOUBLE_EDGE", + "MOVE_EARTHQUAKE", + "MOVE_FIRE_BLAST", + "MOVE_FIRE_PUNCH", + "MOVE_FLAMETHROWER", + "MOVE_FOCUS_BLAST", + "MOVE_GIGA_IMPACT", + "MOVE_HYDRO_PUMP", + "MOVE_HYPER_BEAM", + "MOVE_ICE_BEAM", + "MOVE_ICE_PUNCH", + "MOVE_IRON_TAIL", + "MOVE_POWER_UP_PUNCH", + "MOVE_PROTECT", + "MOVE_ROAR", + "MOVE_ROCK_SLIDE", + "MOVE_ROCK_TOMB", + "MOVE_SAFEGUARD", + "MOVE_SHADOW_BALL", + "MOVE_SHADOW_CLAW", + "MOVE_SOLAR_BEAM", + "MOVE_SUBSTITUTE", + "MOVE_SURF", + "MOVE_THUNDER", + "MOVE_THUNDERBOLT", + "MOVE_THUNDER_PUNCH", + "MOVE_WHIRLPOOL", + "MOVE_WORK_UP" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "STARYU": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_HARDEN" + }, + { + "Level": "4", + "Move": "MOVE_WATER_GUN" + }, + { + "Level": "8", + "Move": "MOVE_CONFUSE_RAY" + }, + { + "Level": "12", + "Move": "MOVE_AQUA_JET" + }, + { + "Level": "16", + "Move": "MOVE_SWIFT" + }, + { + "Level": "20", + "Move": "MOVE_BUBBLE_BEAM" + }, + { + "Level": "24", + "Move": "MOVE_PSYBEAM" + }, + { + "Level": "32", + "Move": "MOVE_LIGHT_SCREEN" + }, + { + "Level": "36", + "Move": "MOVE_POWER_GEM" + }, + { + "Level": "40", + "Move": "MOVE_PSYCHIC" + }, + { + "Level": "44", + "Move": "MOVE_SURF" + }, + { + "Level": "48", + "Move": "MOVE_RECOVER" + }, + { + "Level": "56", + "Move": "MOVE_HYDRO_PUMP" + } + ], + "TMMoves": [ + "MOVE_BLIZZARD", + "MOVE_DAZZLING_GLEAM", + "MOVE_ENDURE", + "MOVE_FLASH_CANNON", + "MOVE_FLIP_TURN", + "MOVE_ICE_BEAM", + "MOVE_ICY_WIND", + "MOVE_PROTECT", + "MOVE_REFLECT", + "MOVE_SAFEGUARD", + "MOVE_SELF_DESTRUCT", + "MOVE_SUBSTITUTE", + "MOVE_THUNDER", + "MOVE_THUNDERBOLT", + "MOVE_THUNDER_WAVE", + "MOVE_WATERFALL", + "MOVE_WATER_PULSE", + "MOVE_WHIRLPOOL" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "STARMIE": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_TAKE_DOWN" + }, + { + "Level": "1", + "Move": "MOVE_HARDEN" + }, + { + "Level": "4", + "Move": "MOVE_WATER_GUN" + }, + { + "Level": "8", + "Move": "MOVE_CONFUSE_RAY" + }, + { + "Level": "12", + "Move": "MOVE_AQUA_JET" + }, + { + "Level": "16", + "Move": "MOVE_SWIFT" + }, + { + "Level": "20", + "Move": "MOVE_BUBBLE_BEAM" + }, + { + "Level": "24", + "Move": "MOVE_PSYBEAM" + }, + { + "Level": "32", + "Move": "MOVE_LIGHT_SCREEN" + }, + { + "Level": "36", + "Move": "MOVE_POWER_GEM" + }, + { + "Level": "40", + "Move": "MOVE_PSYCHIC" + }, + { + "Level": "42", + "Move": "MOVE_LIQUIDATION" + }, + { + "Level": "44", + "Move": "MOVE_SURF" + }, + { + "Level": "48", + "Move": "MOVE_RECOVER" + }, + { + "Level": "56", + "Move": "MOVE_HYDRO_PUMP" + } + ], + "TMMoves": [ + "MOVE_AGILITY", + "MOVE_BLIZZARD", + "MOVE_BULK_UP", + "MOVE_DAZZLING_GLEAM", + "MOVE_DOUBLE_EDGE", + "MOVE_ENDURE", + "MOVE_FLASH_CANNON", + "MOVE_FLIP_TURN", + "MOVE_GIGA_IMPACT", + "MOVE_HEADBUTT", + "MOVE_HEAL_BLOCK", + "MOVE_HYPER_BEAM", + "MOVE_ICE_BEAM", + "MOVE_ICY_WIND", + "MOVE_PROTECT", + "MOVE_PSYSHOCK", + "MOVE_REFLECT", + "MOVE_SAFEGUARD", + "MOVE_SELF_DESTRUCT", + "MOVE_SUBSTITUTE", + "MOVE_THUNDER", + "MOVE_THUNDERBOLT", + "MOVE_THUNDER_WAVE", + "MOVE_WATERFALL", + "MOVE_WATER_PULSE", + "MOVE_WHIRLPOOL", + "MOVE_ZEN_HEADBUTT" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "SCYTHER": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_LEER" + }, + { + "Level": "1", + "Move": "MOVE_QUICK_ATTACK" + }, + { + "Level": "12", + "Move": "MOVE_WING_ATTACK" + }, + { + "Level": "16", + "Move": "MOVE_DOUBLE_TEAM" + }, + { + "Level": "20", + "Move": "MOVE_BRUTAL_SWING" + }, + { + "Level": "24", + "Move": "MOVE_SLASH" + }, + { + "Level": "28", + "Move": "MOVE_FOCUS_ENERGY" + }, + { + "Level": "32", + "Move": "MOVE_X_SCISSOR" + }, + { + "Level": "34", + "Move": "MOVE_BUG_BUZZ" + }, + { + "Level": "36", + "Move": "MOVE_AIR_SLASH" + }, + { + "Level": "42", + "Move": "MOVE_SWORDS_DANCE" + }, + { + "Level": "46", + "Move": "MOVE_LUNGE" + } + ], + "TMMoves": [ + "MOVE_AERIAL_ACE", + "MOVE_AGILITY", + "MOVE_BRICK_BREAK", + "MOVE_CLOSE_COMBAT", + "MOVE_DOUBLE_EDGE", + "MOVE_ENDURE", + "MOVE_GIGA_IMPACT", + "MOVE_HYPER_BEAM", + "MOVE_KNOCK_OFF", + "MOVE_LIGHT_SCREEN", + "MOVE_NIGHT_SLASH", + "MOVE_PROTECT", + "MOVE_SUBSTITUTE", + "MOVE_SWIFT", + "MOVE_U_TURN" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "PINSIR": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_HARDEN" + }, + { + "Level": "4", + "Move": "MOVE_FOCUS_ENERGY" + }, + { + "Level": "8", + "Move": "MOVE_ROCK_SMASH" + }, + { + "Level": "16", + "Move": "MOVE_BRUTAL_SWING" + }, + { + "Level": "20", + "Move": "MOVE_DETECT" + }, + { + "Level": "24", + "Move": "MOVE_TAKE_DOWN" + }, + { + "Level": "32", + "Move": "MOVE_X_SCISSOR" + }, + { + "Level": "36", + "Move": "MOVE_LUNGE" + }, + { + "Level": "40", + "Move": "MOVE_SWORDS_DANCE" + }, + { + "Level": "50", + "Move": "MOVE_CLOSE_COMBAT" + } + ], + "TMMoves": [ + "MOVE_AERIAL_ACE", + "MOVE_BRICK_BREAK", + "MOVE_BULK_UP", + "MOVE_DIG", + "MOVE_EARTHQUAKE", + "MOVE_ENDURE", + "MOVE_FOCUS_BLAST", + "MOVE_GIGA_IMPACT", + "MOVE_HYPER_BEAM", + "MOVE_IRON_DEFENSE", + "MOVE_OUTRAGE", + "MOVE_PROTECT", + "MOVE_ROCK_SLIDE", + "MOVE_ROCK_TOMB", + "MOVE_STEALTH_ROCK", + "MOVE_STONE_EDGE", + "MOVE_SUBSTITUTE" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "MAGIKARP": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_SPLASH" + }, + { + "Level": "15", + "Move": "MOVE_TACKLE" + } + ], + "TMMoves": [ + "MOVE_HYDRO_PUMP" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "GYARADOS": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_LEER" + }, + { + "Level": "1", + "Move": "MOVE_SPLASH" + }, + { + "Level": "1", + "Move": "MOVE_TWISTER" + }, + { + "Level": "24", + "Move": "MOVE_WATERFALL" + }, + { + "Level": "30", + "Move": "MOVE_CRUNCH" + }, + { + "Level": "33", + "Move": "MOVE_IRON_HEAD" + }, + { + "Level": "40", + "Move": "MOVE_BOUNCE" + }, + { + "Level": "44", + "Move": "MOVE_HURRICANE" + }, + { + "Level": "45", + "Move": "MOVE_DRAGON_RUSH" + }, + { + "Level": "50", + "Move": "MOVE_HYDRO_PUMP" + }, + { + "Level": "55", + "Move": "MOVE_HYPER_BEAM" + } + ], + "TMMoves": [ + "MOVE_BLIZZARD", + "MOVE_BODY_SLAM", + "MOVE_BULLDOZE", + "MOVE_DARK_PULSE", + "MOVE_DOUBLE_EDGE", + "MOVE_DRAGON_PULSE", + "MOVE_EARTHQUAKE", + "MOVE_ENDURE", + "MOVE_FIRE_BLAST", + "MOVE_FLAMETHROWER", + "MOVE_GIGA_IMPACT", + "MOVE_ICE_BEAM", + "MOVE_ICE_FANG", + "MOVE_ICY_WIND", + "MOVE_IRON_TAIL", + "MOVE_OUTRAGE", + "MOVE_PROTECT", + "MOVE_ROAR", + "MOVE_STONE_EDGE", + "MOVE_SUBSTITUTE", + "MOVE_SURF", + "MOVE_TAUNT", + "MOVE_THUNDER", + "MOVE_THUNDERBOLT", + "MOVE_THUNDER_WAVE", + "MOVE_WATER_PULSE" + ], + "TutorMoves": [ + "MOVE_BITE", + "MOVE_WATER_GUN", + "MOVE_WHIRLPOOL" + ], + "EggMoves": [] + }, + "EEVEE": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_TAIL_WHIP" + }, + { + "Level": "1", + "Move": "MOVE_GROWL" + }, + { + "Level": "10", + "Move": "MOVE_QUICK_ATTACK" + }, + { + "Level": "15", + "Move": "MOVE_DISARMING_VOICE" + }, + { + "Level": "20", + "Move": "MOVE_SWIFT" + }, + { + "Level": "25", + "Move": "MOVE_BITE" + }, + { + "Level": "30", + "Move": "MOVE_WISH" + }, + { + "Level": "40", + "Move": "MOVE_TAKE_DOWN" + }, + { + "Level": "45", + "Move": "MOVE_CHARM" + }, + { + "Level": "50", + "Move": "MOVE_DOUBLE_EDGE" + } + ], + "TMMoves": [ + "MOVE_BODY_SLAM", + "MOVE_CALM_MIND", + "MOVE_DIG", + "MOVE_ENDURE", + "MOVE_HYPER_VOICE", + "MOVE_IRON_TAIL", + "MOVE_PROTECT", + "MOVE_ROAR", + "MOVE_SHADOW_BALL", + "MOVE_SUBSTITUTE" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "VAPOREON": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_TAIL_WHIP" + }, + { + "Level": "1", + "Move": "MOVE_BITE" + }, + { + "Level": "1", + "Move": "MOVE_GROWL" + }, + { + "Level": "10", + "Move": "MOVE_QUICK_ATTACK" + }, + { + "Level": "15", + "Move": "MOVE_DISARMING_VOICE" + }, + { + "Level": "20", + "Move": "MOVE_BUBBLE_BEAM" + }, + { + "Level": "25", + "Move": "MOVE_HAZE" + }, + { + "Level": "30", + "Move": "MOVE_ICY_WIND" + }, + { + "Level": "35", + "Move": "MOVE_AQUA_RING" + }, + { + "Level": "40", + "Move": "MOVE_SURF" + }, + { + "Level": "45", + "Move": "MOVE_ACID_ARMOR" + }, + { + "Level": "50", + "Move": "MOVE_HYDRO_PUMP" + } + ], + "TMMoves": [ + "MOVE_BLIZZARD", + "MOVE_BODY_SLAM", + "MOVE_CALM_MIND", + "MOVE_DIG", + "MOVE_ENDURE", + "MOVE_FLIP_TURN", + "MOVE_GIGA_IMPACT", + "MOVE_HEADBUTT", + "MOVE_HYPER_BEAM", + "MOVE_HYPER_VOICE", + "MOVE_ICE_BEAM", + "MOVE_IRON_TAIL", + "MOVE_LIQUIDATION", + "MOVE_PROTECT", + "MOVE_ROAR", + "MOVE_SHADOW_BALL", + "MOVE_SUBSTITUTE", + "MOVE_TAUNT", + "MOVE_WATERFALL", + "MOVE_WATER_PULSE", + "MOVE_WHIRLPOOL" + ], + "TutorMoves": [ + "MOVE_CHARM", + "MOVE_DOUBLE_EDGE", + "MOVE_SWIFT", + "MOVE_TAKE_DOWN", + "MOVE_WATER_GUN", + "MOVE_WISH" + ], + "EggMoves": [] + }, + "JOLTEON": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_TAIL_WHIP" + }, + { + "Level": "1", + "Move": "MOVE_BITE" + }, + { + "Level": "1", + "Move": "MOVE_GROWL" + }, + { + "Level": "10", + "Move": "MOVE_QUICK_ATTACK" + }, + { + "Level": "15", + "Move": "MOVE_DISARMING_VOICE" + }, + { + "Level": "20", + "Move": "MOVE_THUNDER_WAVE" + }, + { + "Level": "25", + "Move": "MOVE_HEADBUTT" + }, + { + "Level": "30", + "Move": "MOVE_THUNDER_FANG" + }, + { + "Level": "35", + "Move": "MOVE_PIN_MISSILE" + }, + { + "Level": "40", + "Move": "MOVE_THUNDERBOLT" + }, + { + "Level": "45", + "Move": "MOVE_FAKE_TEARS" + }, + { + "Level": "50", + "Move": "MOVE_THUNDER" + } + ], + "TMMoves": [ + "MOVE_AGILITY", + "MOVE_BODY_SLAM", + "MOVE_CALM_MIND", + "MOVE_DIG", + "MOVE_DISCHARGE", + "MOVE_ELECTROWEB", + "MOVE_ENDURE", + "MOVE_GIGA_IMPACT", + "MOVE_HYPER_BEAM", + "MOVE_HYPER_VOICE", + "MOVE_IRON_TAIL", + "MOVE_LIGHT_SCREEN", + "MOVE_PROTECT", + "MOVE_ROAR", + "MOVE_SHADOW_BALL", + "MOVE_SUBSTITUTE", + "MOVE_VOLT_SWITCH", + "MOVE_WILD_CHARGE" + ], + "TutorMoves": [ + "MOVE_CHARM", + "MOVE_DOUBLE_EDGE", + "MOVE_EERIE_IMPULSE", + "MOVE_SWIFT", + "MOVE_TAKE_DOWN", + "MOVE_THUNDER_SHOCK", + "MOVE_WISH" + ], + "EggMoves": [] + }, + "FLAREON": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_TAIL_WHIP" + }, + { + "Level": "1", + "Move": "MOVE_BITE" + }, + { + "Level": "1", + "Move": "MOVE_GROWL" + }, + { + "Level": "10", + "Move": "MOVE_QUICK_ATTACK" + }, + { + "Level": "15", + "Move": "MOVE_DISARMING_VOICE" + }, + { + "Level": "20", + "Move": "MOVE_SMOKESCREEN" + }, + { + "Level": "25", + "Move": "MOVE_FLAME_WHEEL" + }, + { + "Level": "30", + "Move": "MOVE_FIRE_SPIN" + }, + { + "Level": "35", + "Move": "MOVE_FIRE_FANG" + }, + { + "Level": "40", + "Move": "MOVE_LAVA_PLUME" + }, + { + "Level": "50", + "Move": "MOVE_FLARE_BLITZ" + } + ], + "TMMoves": [ + "MOVE_BODY_SLAM", + "MOVE_CALM_MIND", + "MOVE_DIG", + "MOVE_ENDURE", + "MOVE_FIRE_BLAST", + "MOVE_FLAMETHROWER", + "MOVE_GIGA_IMPACT", + "MOVE_HEADBUTT", + "MOVE_HEAT_WAVE", + "MOVE_HYPER_BEAM", + "MOVE_HYPER_VOICE", + "MOVE_IRON_TAIL", + "MOVE_PROTECT", + "MOVE_ROAR", + "MOVE_SHADOW_BALL", + "MOVE_SUBSTITUTE", + "MOVE_SWORDS_DANCE", + "MOVE_TAUNT", + "MOVE_WILL_O_WISP" + ], + "TutorMoves": [ + "MOVE_CHARM", + "MOVE_DOUBLE_EDGE", + "MOVE_EMBER", + "MOVE_SWIFT", + "MOVE_TAKE_DOWN", + "MOVE_WISH" + ], + "EggMoves": [] + }, + "AERODACTYL": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_BITE" + }, + { + "Level": "1", + "Move": "MOVE_STEEL_WING" + }, + { + "Level": "5", + "Move": "MOVE_SUPERSONIC" + }, + { + "Level": "10", + "Move": "MOVE_WING_ATTACK" + }, + { + "Level": "15", + "Move": "MOVE_ROCK_BLAST" + }, + { + "Level": "20", + "Move": "MOVE_ROCK_SLIDE" + }, + { + "Level": "25", + "Move": "MOVE_ROAR" + }, + { + "Level": "30", + "Move": "MOVE_CRUNCH" + }, + { + "Level": "35", + "Move": "MOVE_IRON_HEAD" + }, + { + "Level": "40", + "Move": "MOVE_TAKE_DOWN" + }, + { + "Level": "45", + "Move": "MOVE_STONE_EDGE" + }, + { + "Level": "55", + "Move": "MOVE_HYPER_BEAM" + }, + { + "Level": "60", + "Move": "MOVE_GIGA_IMPACT" + } + ], + "TMMoves": [ + "MOVE_AGILITY", + "MOVE_DRAGON_CLAW", + "MOVE_DRAGON_PULSE", + "MOVE_EARTHQUAKE", + "MOVE_EARTH_POWER", + "MOVE_ENDURE", + "MOVE_FIRE_BLAST", + "MOVE_FIRE_FANG", + "MOVE_FLAMETHROWER", + "MOVE_FLY", + "MOVE_HEAT_WAVE", + "MOVE_HURRICANE", + "MOVE_ICE_FANG", + "MOVE_IRON_TAIL", + "MOVE_PROTECT", + "MOVE_ROCK_TOMB", + "MOVE_STEALTH_ROCK", + "MOVE_SUBSTITUTE", + "MOVE_SWIFT", + "MOVE_TAUNT", + "MOVE_THUNDER_FANG", + "MOVE_WHIRLWIND" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "DRATINI": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_LEER" + }, + { + "Level": "5", + "Move": "MOVE_TWISTER" + }, + { + "Level": "10", + "Move": "MOVE_THUNDER_WAVE" + }, + { + "Level": "15", + "Move": "MOVE_TAKE_DOWN" + }, + { + "Level": "20", + "Move": "MOVE_BREAKING_SWIPE" + }, + { + "Level": "25", + "Move": "MOVE_BRUTAL_SWING" + }, + { + "Level": "30", + "Move": "MOVE_DRAGON_RUSH" + }, + { + "Level": "40", + "Move": "MOVE_SAFEGUARD" + }, + { + "Level": "50", + "Move": "MOVE_EXTREME_SPEED" + }, + { + "Level": "55", + "Move": "MOVE_OUTRAGE" + }, + { + "Level": "60", + "Move": "MOVE_HYPER_BEAM" + } + ], + "TMMoves": [ + "MOVE_AGILITY", + "MOVE_BLIZZARD", + "MOVE_DRACO_METEOR", + "MOVE_DRAGON_PULSE", + "MOVE_ENDURE", + "MOVE_FIRE_BLAST", + "MOVE_FIRE_SPIN", + "MOVE_FLAMETHROWER", + "MOVE_GIGA_IMPACT", + "MOVE_HYDRO_PUMP", + "MOVE_ICE_BEAM", + "MOVE_IRON_HEAD", + "MOVE_LIGHT_SCREEN", + "MOVE_PROTECT", + "MOVE_SUBSTITUTE", + "MOVE_SURF", + "MOVE_SWIFT", + "MOVE_THUNDER", + "MOVE_THUNDERBOLT", + "MOVE_WATERFALL", + "MOVE_WATER_PULSE", + "MOVE_WHIRLPOOL" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "DRAGONAIR": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_LEER" + }, + { + "Level": "5", + "Move": "MOVE_TWISTER" + }, + { + "Level": "10", + "Move": "MOVE_THUNDER_WAVE" + }, + { + "Level": "15", + "Move": "MOVE_TAKE_DOWN" + }, + { + "Level": "20", + "Move": "MOVE_BREAKING_SWIPE" + }, + { + "Level": "25", + "Move": "MOVE_BRUTAL_SWING" + }, + { + "Level": "30", + "Move": "MOVE_DRAGON_RUSH" + }, + { + "Level": "40", + "Move": "MOVE_SAFEGUARD" + }, + { + "Level": "50", + "Move": "MOVE_EXTREME_SPEED" + }, + { + "Level": "55", + "Move": "MOVE_OUTRAGE" + }, + { + "Level": "60", + "Move": "MOVE_HYPER_BEAM" + } + ], + "TMMoves": [ + "MOVE_AGILITY", + "MOVE_BLIZZARD", + "MOVE_DRACO_METEOR", + "MOVE_DRAGON_PULSE", + "MOVE_ENDURE", + "MOVE_FIRE_BLAST", + "MOVE_FIRE_SPIN", + "MOVE_FLAMETHROWER", + "MOVE_GIGA_IMPACT", + "MOVE_HYDRO_PUMP", + "MOVE_ICE_BEAM", + "MOVE_IRON_HEAD", + "MOVE_LIGHT_SCREEN", + "MOVE_PROTECT", + "MOVE_SUBSTITUTE", + "MOVE_SURF", + "MOVE_SWIFT", + "MOVE_THUNDER", + "MOVE_THUNDERBOLT", + "MOVE_WATERFALL", + "MOVE_WATER_PULSE", + "MOVE_WHIRLPOOL" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "DRAGONITE": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_LEER" + }, + { + "Level": "1", + "Move": "MOVE_AIR_SLASH" + }, + { + "Level": "5", + "Move": "MOVE_TWISTER" + }, + { + "Level": "10", + "Move": "MOVE_THUNDER_WAVE" + }, + { + "Level": "15", + "Move": "MOVE_TAKE_DOWN" + }, + { + "Level": "20", + "Move": "MOVE_BREAKING_SWIPE" + }, + { + "Level": "25", + "Move": "MOVE_BRUTAL_SWING" + }, + { + "Level": "30", + "Move": "MOVE_DRAGON_RUSH" + }, + { + "Level": "40", + "Move": "MOVE_SAFEGUARD" + }, + { + "Level": "50", + "Move": "MOVE_EXTREME_SPEED" + }, + { + "Level": "55", + "Move": "MOVE_OUTRAGE" + }, + { + "Level": "60", + "Move": "MOVE_HYPER_BEAM" + } + ], + "TMMoves": [ + "MOVE_AERIAL_ACE", + "MOVE_AGILITY", + "MOVE_BLIZZARD", + "MOVE_BRICK_BREAK", + "MOVE_DRACO_METEOR", + "MOVE_DRAGON_CLAW", + "MOVE_DRAGON_PULSE", + "MOVE_EARTHQUAKE", + "MOVE_ENDURE", + "MOVE_FIRE_BLAST", + "MOVE_FIRE_SPIN", + "MOVE_FLAMETHROWER", + "MOVE_FLY", + "MOVE_FOCUS_BLAST", + "MOVE_GIGA_IMPACT", + "MOVE_HEAT_WAVE", + "MOVE_HYDRO_PUMP", + "MOVE_ICE_BEAM", + "MOVE_ICE_PUNCH", + "MOVE_IRON_HEAD", + "MOVE_LIGHT_SCREEN", + "MOVE_METRONOME", + "MOVE_PROTECT", + "MOVE_ROAR", + "MOVE_ROCK_SLIDE", + "MOVE_ROCK_TOMB", + "MOVE_STONE_EDGE", + "MOVE_SUBSTITUTE", + "MOVE_SURF", + "MOVE_SWIFT", + "MOVE_THUNDER", + "MOVE_THUNDERBOLT", + "MOVE_WATERFALL", + "MOVE_WATER_PULSE", + "MOVE_WHIRLPOOL", + "MOVE_WHIRLWIND" + ], + "TutorMoves": [ + "MOVE_FIRE_PUNCH", + "MOVE_HURRICANE", + "MOVE_THUNDER_PUNCH", + "MOVE_WING_ATTACK" + ], + "EggMoves": [] + }, + "MEWTWO": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_CONFUSION" + }, + { + "Level": "1", + "Move": "MOVE_SWIFT" + }, + { + "Level": "12", + "Move": "MOVE_PSYBEAM" + }, + { + "Level": "16", + "Move": "MOVE_PSYCHO_CUT" + }, + { + "Level": "24", + "Move": "MOVE_SAFEGUARD" + }, + { + "Level": "32", + "Move": "MOVE_AMNESIA" + }, + { + "Level": "40", + "Move": "MOVE_AURA_SPHERE" + }, + { + "Level": "48", + "Move": "MOVE_PSYCHIC" + }, + { + "Level": "64", + "Move": "MOVE_MIST" + }, + { + "Level": "72", + "Move": "MOVE_PSYSTRIKE" + }, + { + "Level": "80", + "Move": "MOVE_RECOVER" + }, + { + "Level": "88", + "Move": "MOVE_FUTURE_SIGHT" + } + ], + "TMMoves": [ + "MOVE_AERIAL_ACE", + "MOVE_AGILITY", + "MOVE_BLIZZARD", + "MOVE_BRICK_BREAK", + "MOVE_BULK_UP", + "MOVE_CALM_MIND", + "MOVE_DARK_PULSE", + "MOVE_DISCHARGE", + "MOVE_DOUBLE_EDGE", + "MOVE_EARTHQUAKE", + "MOVE_EARTH_POWER", + "MOVE_ENDURE", + "MOVE_ENERGY_BALL", + "MOVE_FIRE_BLAST", + "MOVE_FIRE_PUNCH", + "MOVE_FLAMETHROWER", + "MOVE_FOCUS_BLAST", + "MOVE_GIGA_IMPACT", + "MOVE_HEAL_BLOCK", + "MOVE_HURRICANE", + "MOVE_HYPER_BEAM", + "MOVE_ICE_BEAM", + "MOVE_ICE_PUNCH", + "MOVE_IRON_TAIL", + "MOVE_LIGHT_SCREEN", + "MOVE_METRONOME", + "MOVE_NASTY_PLOT", + "MOVE_POISON_JAB", + "MOVE_POWER_GEM", + "MOVE_PROTECT", + "MOVE_PSYSHOCK", + "MOVE_REFLECT", + "MOVE_ROCK_SLIDE", + "MOVE_ROCK_TOMB", + "MOVE_SELF_DESTRUCT", + "MOVE_SHADOW_BALL", + "MOVE_SOLAR_BEAM", + "MOVE_STONE_EDGE", + "MOVE_SUBSTITUTE", + "MOVE_TAKE_DOWN", + "MOVE_TAUNT", + "MOVE_THUNDER", + "MOVE_THUNDERBOLT", + "MOVE_THUNDER_PUNCH", + "MOVE_THUNDER_WAVE", + "MOVE_TOXIC", + "MOVE_WILL_O_WISP", + "MOVE_ZEN_HEADBUTT" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "CHIKORITA": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_TAIL_WHIP" + }, + { + "Level": "6", + "Move": "MOVE_LEAFAGE" + }, + { + "Level": "9", + "Move": "MOVE_DISARMING_VOICE" + }, + { + "Level": "12", + "Move": "MOVE_RAZOR_LEAF" + }, + { + "Level": "14", + "Move": "MOVE_LEECH_SEED" + }, + { + "Level": "22", + "Move": "MOVE_BODY_SLAM" + }, + { + "Level": "27", + "Move": "MOVE_REFLECT" + }, + { + "Level": "36", + "Move": "MOVE_SAFEGUARD" + }, + { + "Level": "40", + "Move": "MOVE_SYNTHESIS" + }, + { + "Level": "45", + "Move": "MOVE_SOLAR_BEAM" + }, + { + "Level": "50", + "Move": "MOVE_LIGHT_SCREEN" + }, + { + "Level": "56", + "Move": "MOVE_LEAF_STORM" + } + ], + "TMMoves": [ + "MOVE_BULLDOZE", + "MOVE_BULLET_SEED", + "MOVE_CURSE", + "MOVE_DAZZLING_GLEAM", + "MOVE_DOUBLE_EDGE", + "MOVE_DOUBLE_TEAM", + "MOVE_EARTH_POWER", + "MOVE_ENDURE", + "MOVE_ENERGY_BALL", + "MOVE_HEADBUTT", + "MOVE_IRON_TAIL", + "MOVE_KNOCK_OFF", + "MOVE_PROTECT", + "MOVE_SUBSTITUTE", + "MOVE_SWORDS_DANCE", + "MOVE_WORK_UP" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "BAYLEEF": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_TAIL_WHIP" + }, + { + "Level": "6", + "Move": "MOVE_LEAFAGE" + }, + { + "Level": "9", + "Move": "MOVE_DISARMING_VOICE" + }, + { + "Level": "12", + "Move": "MOVE_RAZOR_LEAF" + }, + { + "Level": "14", + "Move": "MOVE_LEECH_SEED" + }, + { + "Level": "22", + "Move": "MOVE_BODY_SLAM" + }, + { + "Level": "27", + "Move": "MOVE_REFLECT" + }, + { + "Level": "36", + "Move": "MOVE_SAFEGUARD" + }, + { + "Level": "40", + "Move": "MOVE_SYNTHESIS" + }, + { + "Level": "45", + "Move": "MOVE_SOLAR_BEAM" + }, + { + "Level": "50", + "Move": "MOVE_LIGHT_SCREEN" + }, + { + "Level": "56", + "Move": "MOVE_LEAF_STORM" + } + ], + "TMMoves": [ + "MOVE_BULLDOZE", + "MOVE_BULLET_SEED", + "MOVE_CURSE", + "MOVE_DAZZLING_GLEAM", + "MOVE_DOUBLE_EDGE", + "MOVE_DOUBLE_TEAM", + "MOVE_EARTH_POWER", + "MOVE_ENDURE", + "MOVE_ENERGY_BALL", + "MOVE_HEADBUTT", + "MOVE_IRON_TAIL", + "MOVE_KNOCK_OFF", + "MOVE_PROTECT", + "MOVE_ROCK_SMASH", + "MOVE_SUBSTITUTE", + "MOVE_SWORDS_DANCE", + "MOVE_WORK_UP" + ], + "TutorMoves": [ + "MOVE_GIGA_DRAIN" + ], + "EggMoves": [] + }, + "MEGANIUM": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_TAIL_WHIP" + }, + { + "Level": "6", + "Move": "MOVE_LEAFAGE" + }, + { + "Level": "9", + "Move": "MOVE_DISARMING_VOICE" + }, + { + "Level": "12", + "Move": "MOVE_RAZOR_LEAF" + }, + { + "Level": "14", + "Move": "MOVE_LEECH_SEED" + }, + { + "Level": "22", + "Move": "MOVE_BODY_SLAM" + }, + { + "Level": "27", + "Move": "MOVE_REFLECT" + }, + { + "Level": "36", + "Move": "MOVE_SAFEGUARD" + }, + { + "Level": "40", + "Move": "MOVE_SYNTHESIS" + }, + { + "Level": "45", + "Move": "MOVE_SOLAR_BEAM" + }, + { + "Level": "50", + "Move": "MOVE_LIGHT_SCREEN" + }, + { + "Level": "56", + "Move": "MOVE_LEAF_STORM" + } + ], + "TMMoves": [ + "MOVE_BULLDOZE", + "MOVE_BULLET_SEED", + "MOVE_CURSE", + "MOVE_DAZZLING_GLEAM", + "MOVE_DOUBLE_EDGE", + "MOVE_DOUBLE_TEAM", + "MOVE_EARTHQUAKE", + "MOVE_EARTH_POWER", + "MOVE_ENDURE", + "MOVE_ENERGY_BALL", + "MOVE_GIGA_IMPACT", + "MOVE_HEADBUTT", + "MOVE_HYPER_BEAM", + "MOVE_IRON_TAIL", + "MOVE_KNOCK_OFF", + "MOVE_OUTRAGE", + "MOVE_PROTECT", + "MOVE_ROCK_SMASH", + "MOVE_SUBSTITUTE", + "MOVE_SWORDS_DANCE", + "MOVE_WORK_UP" + ], + "TutorMoves": [ + "MOVE_GIGA_DRAIN", + "MOVE_LEAF_BLADE" + ], + "EggMoves": [] + }, + "TOTODILE": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_LEER" + }, + { + "Level": "6", + "Move": "MOVE_WATER_GUN" + }, + { + "Level": "10", + "Move": "MOVE_BITE" + }, + { + "Level": "15", + "Move": "MOVE_BUBBLE_BEAM" + }, + { + "Level": "21", + "Move": "MOVE_AQUA_JET" + }, + { + "Level": "26", + "Move": "MOVE_BREAKING_SWIPE" + }, + { + "Level": "35", + "Move": "MOVE_SCREECH" + }, + { + "Level": "40", + "Move": "MOVE_LIQUIDATION" + }, + { + "Level": "50", + "Move": "MOVE_HYDRO_PUMP" + }, + { + "Level": "56", + "Move": "MOVE_OUTRAGE" + } + ], + "TMMoves": [ + "MOVE_BLIZZARD", + "MOVE_BRICK_BREAK", + "MOVE_BULLDOZE", + "MOVE_CURSE", + "MOVE_DIG", + "MOVE_DOUBLE_TEAM", + "MOVE_DRAGON_CLAW", + "MOVE_ENDURE", + "MOVE_FLIP_TURN", + "MOVE_ICE_BEAM", + "MOVE_ICE_FANG", + "MOVE_ICY_WIND", + "MOVE_PROTECT", + "MOVE_ROCK_SLIDE", + "MOVE_ROCK_TOMB", + "MOVE_SUBSTITUTE", + "MOVE_SURF", + "MOVE_SWORDS_DANCE", + "MOVE_WATERFALL", + "MOVE_WATER_PULSE", + "MOVE_WHIRLPOOL", + "MOVE_WORK_UP" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "CROCONAW": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_LEER" + }, + { + "Level": "6", + "Move": "MOVE_WATER_GUN" + }, + { + "Level": "10", + "Move": "MOVE_BITE" + }, + { + "Level": "15", + "Move": "MOVE_BUBBLE_BEAM" + }, + { + "Level": "21", + "Move": "MOVE_AQUA_JET" + }, + { + "Level": "26", + "Move": "MOVE_BREAKING_SWIPE" + }, + { + "Level": "35", + "Move": "MOVE_SCREECH" + }, + { + "Level": "40", + "Move": "MOVE_LIQUIDATION" + }, + { + "Level": "50", + "Move": "MOVE_HYDRO_PUMP" + }, + { + "Level": "56", + "Move": "MOVE_OUTRAGE" + } + ], + "TMMoves": [ + "MOVE_BLIZZARD", + "MOVE_BRICK_BREAK", + "MOVE_BULLDOZE", + "MOVE_CURSE", + "MOVE_DIG", + "MOVE_DOUBLE_TEAM", + "MOVE_DRAGON_CLAW", + "MOVE_ENDURE", + "MOVE_FLIP_TURN", + "MOVE_ICE_BEAM", + "MOVE_ICE_FANG", + "MOVE_ICY_WIND", + "MOVE_PROTECT", + "MOVE_ROAR", + "MOVE_ROCK_SLIDE", + "MOVE_ROCK_SMASH", + "MOVE_ROCK_TOMB", + "MOVE_SUBSTITUTE", + "MOVE_SURF", + "MOVE_SWORDS_DANCE", + "MOVE_WATERFALL", + "MOVE_WATER_PULSE", + "MOVE_WHIRLPOOL", + "MOVE_WORK_UP" + ], + "TutorMoves": [ + "MOVE_SLASH" + ], + "EggMoves": [] + }, + "FERALIGATR": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_LEER" + }, + { + "Level": "1", + "Move": "MOVE_SLASH" + }, + { + "Level": "6", + "Move": "MOVE_WATER_GUN" + }, + { + "Level": "10", + "Move": "MOVE_BITE" + }, + { + "Level": "15", + "Move": "MOVE_BUBBLE_BEAM" + }, + { + "Level": "21", + "Move": "MOVE_AQUA_JET" + }, + { + "Level": "26", + "Move": "MOVE_BREAKING_SWIPE" + }, + { + "Level": "35", + "Move": "MOVE_SCREECH" + }, + { + "Level": "40", + "Move": "MOVE_LIQUIDATION" + }, + { + "Level": "50", + "Move": "MOVE_HYDRO_PUMP" + }, + { + "Level": "56", + "Move": "MOVE_OUTRAGE" + } + ], + "TMMoves": [ + "MOVE_AGILITY", + "MOVE_BLIZZARD", + "MOVE_BRICK_BREAK", + "MOVE_BULLDOZE", + "MOVE_CURSE", + "MOVE_DIG", + "MOVE_DOUBLE_EDGE", + "MOVE_DOUBLE_TEAM", + "MOVE_DRAGON_CLAW", + "MOVE_EARTHQUAKE", + "MOVE_ENDURE", + "MOVE_FLIP_TURN", + "MOVE_GIGA_IMPACT", + "MOVE_HYPER_BEAM", + "MOVE_ICE_BEAM", + "MOVE_ICE_FANG", + "MOVE_ICY_WIND", + "MOVE_PROTECT", + "MOVE_ROAR", + "MOVE_ROCK_SLIDE", + "MOVE_ROCK_SMASH", + "MOVE_ROCK_TOMB", + "MOVE_SUBSTITUTE", + "MOVE_SURF", + "MOVE_SWORDS_DANCE", + "MOVE_WATERFALL", + "MOVE_WATER_PULSE", + "MOVE_WHIRLPOOL", + "MOVE_WORK_UP" + ], + "TutorMoves": [ + "MOVE_CRUNCH" + ], + "EggMoves": [] + }, + "SPINARAK": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_POISON_STING" + }, + { + "Level": "1", + "Move": "MOVE_STRING_SHOT" + }, + { + "Level": "5", + "Move": "MOVE_ABSORB" + }, + { + "Level": "8", + "Move": "MOVE_INFESTATION" + }, + { + "Level": "12", + "Move": "MOVE_SHADOW_SNEAK" + }, + { + "Level": "16", + "Move": "MOVE_X_SCISSOR" + }, + { + "Level": "21", + "Move": "MOVE_SCREECH" + }, + { + "Level": "24", + "Move": "MOVE_STICKY_WEB" + }, + { + "Level": "27", + "Move": "MOVE_PIN_MISSILE" + }, + { + "Level": "30", + "Move": "MOVE_PSYCHIC" + }, + { + "Level": "33", + "Move": "MOVE_POISON_JAB" + }, + { + "Level": "35", + "Move": "MOVE_BUG_BUZZ" + }, + { + "Level": "37", + "Move": "MOVE_LEECH_LIFE" + }, + { + "Level": "40", + "Move": "MOVE_LUNGE" + }, + { + "Level": "44", + "Move": "MOVE_MEGAHORN" + } + ], + "TMMoves": [ + "MOVE_AGILITY", + "MOVE_BODY_SLAM", + "MOVE_DIG", + "MOVE_ELECTROWEB", + "MOVE_ENDURE", + "MOVE_GIGA_DRAIN", + "MOVE_HEADBUTT", + "MOVE_KNOCK_OFF", + "MOVE_PROTECT", + "MOVE_SLUDGE_BOMB", + "MOVE_SOLAR_BEAM", + "MOVE_SUBSTITUTE", + "MOVE_TOXIC", + "MOVE_TOXIC_SPIKES" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "ARIADOS": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_POISON_STING" + }, + { + "Level": "1", + "Move": "MOVE_STRING_SHOT" + }, + { + "Level": "1", + "Move": "MOVE_FOCUS_ENERGY" + }, + { + "Level": "5", + "Move": "MOVE_ABSORB" + }, + { + "Level": "8", + "Move": "MOVE_INFESTATION" + }, + { + "Level": "12", + "Move": "MOVE_SHADOW_SNEAK" + }, + { + "Level": "16", + "Move": "MOVE_X_SCISSOR" + }, + { + "Level": "21", + "Move": "MOVE_SCREECH" + }, + { + "Level": "24", + "Move": "MOVE_STICKY_WEB" + }, + { + "Level": "27", + "Move": "MOVE_PIN_MISSILE" + }, + { + "Level": "30", + "Move": "MOVE_PSYCHIC" + }, + { + "Level": "33", + "Move": "MOVE_POISON_JAB" + }, + { + "Level": "35", + "Move": "MOVE_BUG_BUZZ" + }, + { + "Level": "37", + "Move": "MOVE_LEECH_LIFE" + }, + { + "Level": "40", + "Move": "MOVE_LUNGE" + }, + { + "Level": "44", + "Move": "MOVE_MEGAHORN" + } + ], + "TMMoves": [ + "MOVE_AGILITY", + "MOVE_BODY_SLAM", + "MOVE_DIG", + "MOVE_ELECTROWEB", + "MOVE_ENDURE", + "MOVE_GIGA_DRAIN", + "MOVE_GIGA_IMPACT", + "MOVE_HEADBUTT", + "MOVE_HYPER_BEAM", + "MOVE_KNOCK_OFF", + "MOVE_PROTECT", + "MOVE_SLUDGE_BOMB", + "MOVE_SOLAR_BEAM", + "MOVE_SUBSTITUTE", + "MOVE_TOXIC", + "MOVE_TOXIC_SPIKES" + ], + "TutorMoves": [ + "MOVE_SWORDS_DANCE" + ], + "EggMoves": [] + }, + "PICHU": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TAIL_WHIP" + }, + { + "Level": "1", + "Move": "MOVE_GROWL" + }, + { + "Level": "1", + "Move": "MOVE_THUNDER_SHOCK" + }, + { + "Level": "1", + "Move": "MOVE_QUICK_ATTACK" + }, + { + "Level": "4", + "Move": "MOVE_THUNDER_WAVE" + }, + { + "Level": "12", + "Move": "MOVE_NUZZLE" + }, + { + "Level": "16", + "Move": "MOVE_SPARK" + }, + { + "Level": "20", + "Move": "MOVE_CHARM" + }, + { + "Level": "25", + "Move": "MOVE_THUNDERBOLT" + }, + { + "Level": "30", + "Move": "MOVE_CHARGE" + }, + { + "Level": "35", + "Move": "MOVE_LIGHT_SCREEN" + }, + { + "Level": "40", + "Move": "MOVE_THUNDER" + }, + { + "Level": "99", + "Move": "MOVE_VOLT_TACKLE" + } + ], + "TMMoves": [ + "MOVE_BODY_SLAM", + "MOVE_BRICK_BREAK", + "MOVE_DIG", + "MOVE_DISCHARGE", + "MOVE_DOUBLE_TEAM", + "MOVE_ELECTROWEB", + "MOVE_ENDURE", + "MOVE_IRON_TAIL", + "MOVE_NASTY_PLOT", + "MOVE_PLAY_ROUGH", + "MOVE_PROTECT", + "MOVE_REFLECT", + "MOVE_SUBSTITUTE", + "MOVE_SURF", + "MOVE_SWIFT", + "MOVE_THUNDER_PUNCH", + "MOVE_VOLT_SWITCH", + "MOVE_WILD_CHARGE" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "CLEFFA": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_SPLASH" + }, + { + "Level": "5", + "Move": "MOVE_FAIRY_WIND" + }, + { + "Level": "8", + "Move": "MOVE_DISARMING_VOICE" + }, + { + "Level": "13", + "Move": "MOVE_CHARM" + }, + { + "Level": "16", + "Move": "MOVE_DRAINING_KISS" + }, + { + "Level": "18", + "Move": "MOVE_MAGICAL_LEAF" + }, + { + "Level": "20", + "Move": "MOVE_METRONOME" + }, + { + "Level": "22", + "Move": "MOVE_BUBBLE_BEAM" + }, + { + "Level": "24", + "Move": "MOVE_MOONLIGHT" + }, + { + "Level": "28", + "Move": "MOVE_AMNESIA" + }, + { + "Level": "42", + "Move": "MOVE_MYSTICAL_FIRE" + }, + { + "Level": "48", + "Move": "MOVE_MOONBLAST" + }, + { + "Level": "55", + "Move": "MOVE_DOUBLE_EDGE" + } + ], + "TMMoves": [ + "MOVE_BLIZZARD", + "MOVE_BODY_SLAM", + "MOVE_CALM_MIND", + "MOVE_DAZZLING_GLEAM", + "MOVE_DIG", + "MOVE_ENDURE", + "MOVE_FIRE_BLAST", + "MOVE_FLAMETHROWER", + "MOVE_HEADBUTT", + "MOVE_HYPER_VOICE", + "MOVE_ICE_BEAM", + "MOVE_IRON_TAIL", + "MOVE_LIGHT_SCREEN", + "MOVE_PLAY_ROUGH", + "MOVE_PROTECT", + "MOVE_PSYCHIC", + "MOVE_PSYSHOCK", + "MOVE_REFLECT", + "MOVE_SAFEGUARD", + "MOVE_SHADOW_BALL", + "MOVE_SOLAR_BEAM", + "MOVE_STEALTH_ROCK", + "MOVE_SUBSTITUTE", + "MOVE_SWIFT", + "MOVE_THUNDER", + "MOVE_THUNDERBOLT", + "MOVE_THUNDER_WAVE", + "MOVE_WORK_UP", + "MOVE_ZEN_HEADBUTT" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "MAREEP": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_GROWL" + }, + { + "Level": "4", + "Move": "MOVE_THUNDER_SHOCK" + }, + { + "Level": "8", + "Move": "MOVE_THUNDER_WAVE" + }, + { + "Level": "15", + "Move": "MOVE_CHARGE" + }, + { + "Level": "17", + "Move": "MOVE_CONFUSE_RAY" + }, + { + "Level": "28", + "Move": "MOVE_COTTON_GUARD" + }, + { + "Level": "32", + "Move": "MOVE_POWER_GEM" + }, + { + "Level": "36", + "Move": "MOVE_THUNDERBOLT" + }, + { + "Level": "40", + "Move": "MOVE_LIGHT_SCREEN" + }, + { + "Level": "45", + "Move": "MOVE_THUNDER" + } + ], + "TMMoves": [ + "MOVE_BODY_SLAM", + "MOVE_DAZZLING_GLEAM", + "MOVE_DIG", + "MOVE_DISCHARGE", + "MOVE_ELECTROWEB", + "MOVE_ENDURE", + "MOVE_PROTECT", + "MOVE_REFLECT", + "MOVE_SUBSTITUTE", + "MOVE_SWIFT", + "MOVE_VOLT_SWITCH", + "MOVE_WILD_CHARGE" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "FLAAFFY": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_GROWL" + }, + { + "Level": "4", + "Move": "MOVE_THUNDER_SHOCK" + }, + { + "Level": "8", + "Move": "MOVE_THUNDER_WAVE" + }, + { + "Level": "15", + "Move": "MOVE_CHARGE" + }, + { + "Level": "17", + "Move": "MOVE_CONFUSE_RAY" + }, + { + "Level": "28", + "Move": "MOVE_COTTON_GUARD" + }, + { + "Level": "32", + "Move": "MOVE_POWER_GEM" + }, + { + "Level": "36", + "Move": "MOVE_THUNDERBOLT" + }, + { + "Level": "40", + "Move": "MOVE_LIGHT_SCREEN" + }, + { + "Level": "45", + "Move": "MOVE_THUNDER" + } + ], + "TMMoves": [ + "MOVE_AGILITY", + "MOVE_BODY_SLAM", + "MOVE_DAZZLING_GLEAM", + "MOVE_DIG", + "MOVE_DISCHARGE", + "MOVE_ELECTROWEB", + "MOVE_ENDURE", + "MOVE_FIRE_PUNCH", + "MOVE_ICE_PUNCH", + "MOVE_PROTECT", + "MOVE_REFLECT", + "MOVE_ROAR", + "MOVE_SUBSTITUTE", + "MOVE_SWIFT", + "MOVE_VOLT_SWITCH", + "MOVE_WILD_CHARGE" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "AMPHAROS": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_GROWL" + }, + { + "Level": "4", + "Move": "MOVE_THUNDER_SHOCK" + }, + { + "Level": "8", + "Move": "MOVE_THUNDER_WAVE" + }, + { + "Level": "15", + "Move": "MOVE_CHARGE" + }, + { + "Level": "17", + "Move": "MOVE_CONFUSE_RAY" + }, + { + "Level": "28", + "Move": "MOVE_COTTON_GUARD" + }, + { + "Level": "32", + "Move": "MOVE_POWER_GEM" + }, + { + "Level": "36", + "Move": "MOVE_THUNDERBOLT" + }, + { + "Level": "40", + "Move": "MOVE_LIGHT_SCREEN" + }, + { + "Level": "42", + "Move": "MOVE_BREAKING_SWIPE" + }, + { + "Level": "45", + "Move": "MOVE_THUNDER" + }, + { + "Level": "50", + "Move": "MOVE_ZAP_CANNON" + } + ], + "TMMoves": [ + "MOVE_AGILITY", + "MOVE_BODY_SLAM", + "MOVE_BRICK_BREAK", + "MOVE_DAZZLING_GLEAM", + "MOVE_DIG", + "MOVE_DISCHARGE", + "MOVE_DOUBLE_EDGE", + "MOVE_DRAGON_PULSE", + "MOVE_ELECTROWEB", + "MOVE_ENDURE", + "MOVE_FIRE_PUNCH", + "MOVE_FLASH_CANNON", + "MOVE_FOCUS_BLAST", + "MOVE_GIGA_IMPACT", + "MOVE_HYPER_BEAM", + "MOVE_ICE_PUNCH", + "MOVE_OUTRAGE", + "MOVE_PROTECT", + "MOVE_REFLECT", + "MOVE_ROAR", + "MOVE_SUBSTITUTE", + "MOVE_SWIFT", + "MOVE_VOLT_SWITCH", + "MOVE_WILD_CHARGE" + ], + "TutorMoves": [ + "MOVE_EERIE_IMPULSE", + "MOVE_THUNDER_PUNCH" + ], + "EggMoves": [] + }, + "ESPEON": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_TAIL_WHIP" + }, + { + "Level": "1", + "Move": "MOVE_BITE" + }, + { + "Level": "1", + "Move": "MOVE_GROWL" + }, + { + "Level": "10", + "Move": "MOVE_QUICK_ATTACK" + }, + { + "Level": "15", + "Move": "MOVE_DISARMING_VOICE" + }, + { + "Level": "25", + "Move": "MOVE_PSYBEAM" + }, + { + "Level": "30", + "Move": "MOVE_MORNING_SUN" + }, + { + "Level": "35", + "Move": "MOVE_HEAL_BLOCK" + }, + { + "Level": "40", + "Move": "MOVE_PSYCHIC" + }, + { + "Level": "45", + "Move": "MOVE_FAKE_TEARS" + }, + { + "Level": "55", + "Move": "MOVE_FUTURE_SIGHT" + } + ], + "TMMoves": [ + "MOVE_BODY_SLAM", + "MOVE_CALM_MIND", + "MOVE_DAZZLING_GLEAM", + "MOVE_DIG", + "MOVE_ENDURE", + "MOVE_GIGA_IMPACT", + "MOVE_HYPER_BEAM", + "MOVE_HYPER_VOICE", + "MOVE_IRON_TAIL", + "MOVE_LIGHT_SCREEN", + "MOVE_POWER_GEM", + "MOVE_PROTECT", + "MOVE_PSYSHOCK", + "MOVE_REFLECT", + "MOVE_ROAR", + "MOVE_SAFEGUARD", + "MOVE_SHADOW_BALL", + "MOVE_SUBSTITUTE", + "MOVE_THUNDER_WAVE" + ], + "TutorMoves": [ + "MOVE_CHARM", + "MOVE_CONFUSION", + "MOVE_DOUBLE_EDGE", + "MOVE_SWIFT", + "MOVE_TAKE_DOWN", + "MOVE_WISH" + ], + "EggMoves": [] + }, + "UMBREON": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_TAIL_WHIP" + }, + { + "Level": "1", + "Move": "MOVE_BITE" + }, + { + "Level": "1", + "Move": "MOVE_GROWL" + }, + { + "Level": "10", + "Move": "MOVE_QUICK_ATTACK" + }, + { + "Level": "15", + "Move": "MOVE_DISARMING_VOICE" + }, + { + "Level": "20", + "Move": "MOVE_CONFUSE_RAY" + }, + { + "Level": "30", + "Move": "MOVE_MOONLIGHT" + }, + { + "Level": "35", + "Move": "MOVE_KNOCK_OFF" + }, + { + "Level": "40", + "Move": "MOVE_DARK_PULSE" + }, + { + "Level": "45", + "Move": "MOVE_SCREECH" + }, + { + "Level": "50", + "Move": "MOVE_CRUNCH" + } + ], + "TMMoves": [ + "MOVE_BODY_SLAM", + "MOVE_CALM_MIND", + "MOVE_CURSE", + "MOVE_DIG", + "MOVE_ENDURE", + "MOVE_GIGA_IMPACT", + "MOVE_HYPER_BEAM", + "MOVE_HYPER_VOICE", + "MOVE_IRON_TAIL", + "MOVE_LIGHT_SCREEN", + "MOVE_PROTECT", + "MOVE_PSYCHIC", + "MOVE_REFLECT", + "MOVE_ROAR", + "MOVE_SHADOW_BALL", + "MOVE_SUBSTITUTE", + "MOVE_TAUNT", + "MOVE_THUNDER_WAVE", + "MOVE_TOXIC" + ], + "TutorMoves": [ + "MOVE_CHARM", + "MOVE_DOUBLE_EDGE", + "MOVE_SNARL", + "MOVE_SWIFT", + "MOVE_TAKE_DOWN", + "MOVE_WISH" + ], + "EggMoves": [] + }, + "SLOWKING": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_CURSE" + }, + { + "Level": "1", + "Move": "MOVE_POWER_GEM" + }, + { + "Level": "1", + "Move": "MOVE_NASTY_PLOT" + }, + { + "Level": "3", + "Move": "MOVE_GROWL" + }, + { + "Level": "6", + "Move": "MOVE_WATER_GUN" + }, + { + "Level": "14", + "Move": "MOVE_PSYBEAM" + }, + { + "Level": "18", + "Move": "MOVE_WATER_PULSE" + }, + { + "Level": "21", + "Move": "MOVE_HEADBUTT" + }, + { + "Level": "24", + "Move": "MOVE_ZEN_HEADBUTT" + }, + { + "Level": "27", + "Move": "MOVE_AMNESIA" + }, + { + "Level": "36", + "Move": "MOVE_SURF" + }, + { + "Level": "42", + "Move": "MOVE_PSYCHIC" + }, + { + "Level": "45", + "Move": "MOVE_FUTURE_SIGHT" + } + ], + "TMMoves": [ + "MOVE_BLIZZARD", + "MOVE_BODY_SLAM", + "MOVE_CALM_MIND", + "MOVE_DIG", + "MOVE_EARTHQUAKE", + "MOVE_ENDURE", + "MOVE_FIRE_BLAST", + "MOVE_FLAMETHROWER", + "MOVE_FOCUS_BLAST", + "MOVE_GIGA_IMPACT", + "MOVE_HEAL_BLOCK", + "MOVE_HYDRO_PUMP", + "MOVE_HYPER_BEAM", + "MOVE_ICE_BEAM", + "MOVE_ICE_PUNCH", + "MOVE_ICY_WIND", + "MOVE_IRON_TAIL", + "MOVE_LIGHT_SCREEN", + "MOVE_LIQUIDATION", + "MOVE_METRONOME", + "MOVE_MUD_SHOT", + "MOVE_PROTECT", + "MOVE_PSYSHOCK", + "MOVE_REFLECT", + "MOVE_SAFEGUARD", + "MOVE_SHADOW_BALL", + "MOVE_SUBSTITUTE", + "MOVE_SWIFT", + "MOVE_THUNDER_WAVE", + "MOVE_WATERFALL", + "MOVE_WHIRLPOOL" + ], + "TutorMoves": [ + "MOVE_CONFUSION" + ], + "EggMoves": [] + }, + "SLOWKING_GALAR": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_CURSE" + }, + { + "Level": "1", + "Move": "MOVE_POWER_GEM" + }, + { + "Level": "1", + "Move": "MOVE_NASTY_PLOT" + }, + { + "Level": "3", + "Move": "MOVE_GROWL" + }, + { + "Level": "6", + "Move": "MOVE_WATER_GUN" + }, + { + "Level": "14", + "Move": "MOVE_PSYBEAM" + }, + { + "Level": "18", + "Move": "MOVE_WATER_PULSE" + }, + { + "Level": "21", + "Move": "MOVE_HEADBUTT" + }, + { + "Level": "24", + "Move": "MOVE_ZEN_HEADBUTT" + }, + { + "Level": "27", + "Move": "MOVE_AMNESIA" + }, + { + "Level": "36", + "Move": "MOVE_SURF" + }, + { + "Level": "36", + "Move": "MOVE_SLUDGE_WAVE" + }, + { + "Level": "42", + "Move": "MOVE_PSYCHIC" + }, + { + "Level": "45", + "Move": "MOVE_FUTURE_SIGHT" + } + ], + "TMMoves": [ + "MOVE_BLIZZARD", + "MOVE_BODY_SLAM", + "MOVE_CALM_MIND", + "MOVE_DIG", + "MOVE_EARTHQUAKE", + "MOVE_ENDURE", + "MOVE_FIRE_BLAST", + "MOVE_FIRE_PUNCH", + "MOVE_FLAMETHROWER", + "MOVE_FOCUS_BLAST", + "MOVE_GIGA_IMPACT", + "MOVE_GUNK_SHOT", + "MOVE_HEAL_BLOCK", + "MOVE_HYDRO_PUMP", + "MOVE_HYPER_BEAM", + "MOVE_ICE_BEAM", + "MOVE_ICY_WIND", + "MOVE_IRON_TAIL", + "MOVE_LIGHT_SCREEN", + "MOVE_LIQUIDATION", + "MOVE_METRONOME", + "MOVE_MUD_SHOT", + "MOVE_POISON_JAB", + "MOVE_PROTECT", + "MOVE_PSYSHOCK", + "MOVE_SAFEGUARD", + "MOVE_SHADOW_BALL", + "MOVE_SLUDGE_BOMB", + "MOVE_SUBSTITUTE", + "MOVE_SWIFT", + "MOVE_TAUNT", + "MOVE_THUNDER_PUNCH", + "MOVE_THUNDER_WAVE", + "MOVE_TOXIC_SPIKES", + "MOVE_WATERFALL", + "MOVE_WHIRLPOOL" + ], + "TutorMoves": [ + "MOVE_CONFUSION", + "MOVE_TOXIC" + ], + "EggMoves": [] + }, + "STEELIX": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_ROCK_THROW" + }, + { + "Level": "1", + "Move": "MOVE_HARDEN" + }, + { + "Level": "1", + "Move": "MOVE_CRUNCH" + }, + { + "Level": "12", + "Move": "MOVE_DRAGON_BREATH" + }, + { + "Level": "16", + "Move": "MOVE_CURSE" + }, + { + "Level": "20", + "Move": "MOVE_ROCK_SLIDE" + }, + { + "Level": "22", + "Move": "MOVE_BREAKING_SWIPE" + }, + { + "Level": "24", + "Move": "MOVE_SCREECH" + }, + { + "Level": "28", + "Move": "MOVE_SAND_TOMB" + }, + { + "Level": "32", + "Move": "MOVE_STEALTH_ROCK" + }, + { + "Level": "36", + "Move": "MOVE_HEAVY_SLAM" + }, + { + "Level": "44", + "Move": "MOVE_DIG" + }, + { + "Level": "52", + "Move": "MOVE_STONE_EDGE" + }, + { + "Level": "56", + "Move": "MOVE_DOUBLE_EDGE" + }, + { + "Level": "62", + "Move": "MOVE_HEAD_SMASH" + } + ], + "TMMoves": [ + "MOVE_BODY_SLAM", + "MOVE_DARK_PULSE", + "MOVE_DRAGON_PULSE", + "MOVE_EARTHQUAKE", + "MOVE_EARTH_POWER", + "MOVE_ENDURE", + "MOVE_FIRE_FANG", + "MOVE_FLASH_CANNON", + "MOVE_GIGA_IMPACT", + "MOVE_HYPER_BEAM", + "MOVE_ICE_FANG", + "MOVE_IRON_DEFENSE", + "MOVE_IRON_HEAD", + "MOVE_PROTECT", + "MOVE_ROCK_BLAST", + "MOVE_ROCK_TOMB", + "MOVE_SELF_DESTRUCT", + "MOVE_SUBSTITUTE", + "MOVE_TAUNT", + "MOVE_THUNDER_FANG" + ], + "TutorMoves": [ + "MOVE_IRON_TAIL" + ], + "EggMoves": [] + }, + "SCIZOR": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_LEER" + }, + { + "Level": "1", + "Move": "MOVE_QUICK_ATTACK" + }, + { + "Level": "12", + "Move": "MOVE_WING_ATTACK" + }, + { + "Level": "16", + "Move": "MOVE_DOUBLE_TEAM" + }, + { + "Level": "18", + "Move": "MOVE_STEEL_WING" + }, + { + "Level": "20", + "Move": "MOVE_BRUTAL_SWING" + }, + { + "Level": "24", + "Move": "MOVE_SLASH" + }, + { + "Level": "28", + "Move": "MOVE_FOCUS_ENERGY" + }, + { + "Level": "32", + "Move": "MOVE_X_SCISSOR" + }, + { + "Level": "34", + "Move": "MOVE_BUG_BUZZ" + }, + { + "Level": "36", + "Move": "MOVE_AIR_SLASH" + }, + { + "Level": "40", + "Move": "MOVE_IRON_DEFENSE" + }, + { + "Level": "42", + "Move": "MOVE_SWORDS_DANCE" + }, + { + "Level": "46", + "Move": "MOVE_LUNGE" + }, + { + "Level": "48", + "Move": "MOVE_IRON_HEAD" + } + ], + "TMMoves": [ + "MOVE_AERIAL_ACE", + "MOVE_AGILITY", + "MOVE_BRICK_BREAK", + "MOVE_CLOSE_COMBAT", + "MOVE_CURSE", + "MOVE_DOUBLE_EDGE", + "MOVE_ENDURE", + "MOVE_FLASH_CANNON", + "MOVE_GIGA_IMPACT", + "MOVE_HYPER_BEAM", + "MOVE_KNOCK_OFF", + "MOVE_LIGHT_SCREEN", + "MOVE_NIGHT_SLASH", + "MOVE_PROTECT", + "MOVE_SAFEGUARD", + "MOVE_SUBSTITUTE", + "MOVE_SWIFT", + "MOVE_U_TURN" + ], + "TutorMoves": [ + "MOVE_BULLET_PUNCH" + ], + "EggMoves": [] + }, + "HERACROSS": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_LEER" + }, + { + "Level": "5", + "Move": "MOVE_ENDURE" + }, + { + "Level": "10", + "Move": "MOVE_PIN_MISSILE" + }, + { + "Level": "13", + "Move": "MOVE_DETECT" + }, + { + "Level": "15", + "Move": "MOVE_AERIAL_ACE" + }, + { + "Level": "20", + "Move": "MOVE_TAKE_DOWN" + }, + { + "Level": "24", + "Move": "MOVE_BRICK_BREAK" + }, + { + "Level": "28", + "Move": "MOVE_ROCK_BLAST" + }, + { + "Level": "30", + "Move": "MOVE_BUG_BUZZ" + }, + { + "Level": "32", + "Move": "MOVE_LUNGE" + }, + { + "Level": "38", + "Move": "MOVE_SWORDS_DANCE" + }, + { + "Level": "45", + "Move": "MOVE_MEGAHORN" + }, + { + "Level": "50", + "Move": "MOVE_CLOSE_COMBAT" + } + ], + "TMMoves": [ + "MOVE_BODY_SLAM", + "MOVE_BULK_UP", + "MOVE_BULLDOZE", + "MOVE_BULLET_SEED", + "MOVE_CURSE", + "MOVE_DIG", + "MOVE_EARTHQUAKE", + "MOVE_FOCUS_BLAST", + "MOVE_GIGA_IMPACT", + "MOVE_HEADBUTT", + "MOVE_HYPER_BEAM", + "MOVE_IRON_DEFENSE", + "MOVE_KNOCK_OFF", + "MOVE_MUD_SHOT", + "MOVE_NIGHT_SLASH", + "MOVE_OUTRAGE", + "MOVE_PROTECT", + "MOVE_ROCK_SLIDE", + "MOVE_ROCK_SMASH", + "MOVE_ROCK_TOMB", + "MOVE_SHADOW_CLAW", + "MOVE_SPIKES", + "MOVE_STONE_EDGE", + "MOVE_SUBSTITUTE", + "MOVE_WORK_UP" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "DELIBIRD": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_PECK" + }, + { + "Level": "15", + "Move": "MOVE_ICY_WIND" + }, + { + "Level": "18", + "Move": "MOVE_AERIAL_ACE" + }, + { + "Level": "25", + "Move": "MOVE_ICE_SHARD" + }, + { + "Level": "28", + "Move": "MOVE_AIR_SLASH" + }, + { + "Level": "32", + "Move": "MOVE_FEATHER_DANCE" + }, + { + "Level": "35", + "Move": "MOVE_ICE_PUNCH" + }, + { + "Level": "37", + "Move": "MOVE_FREEZE_DRY" + }, + { + "Level": "40", + "Move": "MOVE_BLIZZARD" + } + ], + "TMMoves": [ + "MOVE_AGILITY", + "MOVE_BODY_SLAM", + "MOVE_BRICK_BREAK", + "MOVE_ENDURE", + "MOVE_FLY", + "MOVE_GIGA_IMPACT", + "MOVE_GUNK_SHOT", + "MOVE_HYPER_BEAM", + "MOVE_ICE_BEAM", + "MOVE_PROTECT", + "MOVE_SPIKES", + "MOVE_SUBSTITUTE", + "MOVE_SWIFT", + "MOVE_WATER_PULSE" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "SKARMORY": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_LEER" + }, + { + "Level": "1", + "Move": "MOVE_PECK" + }, + { + "Level": "12", + "Move": "MOVE_METAL_CLAW" + }, + { + "Level": "16", + "Move": "MOVE_SAND_TOMB" + }, + { + "Level": "20", + "Move": "MOVE_WING_ATTACK" + }, + { + "Level": "24", + "Move": "MOVE_SLASH" + }, + { + "Level": "28", + "Move": "MOVE_STEEL_WING" + }, + { + "Level": "34", + "Move": "MOVE_NIGHT_SLASH" + }, + { + "Level": "38", + "Move": "MOVE_DRILL_RUN" + }, + { + "Level": "42", + "Move": "MOVE_METAL_SOUND" + }, + { + "Level": "46", + "Move": "MOVE_SPIKES" + }, + { + "Level": "50", + "Move": "MOVE_IRON_DEFENSE" + }, + { + "Level": "56", + "Move": "MOVE_BRAVE_BIRD" + } + ], + "TMMoves": [ + "MOVE_AERIAL_ACE", + "MOVE_AGILITY", + "MOVE_CURSE", + "MOVE_DARK_PULSE", + "MOVE_DOUBLE_TEAM", + "MOVE_ENDURE", + "MOVE_FLASH_CANNON", + "MOVE_FLY", + "MOVE_GIGA_IMPACT", + "MOVE_HURRICANE", + "MOVE_HYPER_BEAM", + "MOVE_IRON_HEAD", + "MOVE_PROTECT", + "MOVE_ROAR", + "MOVE_ROCK_SLIDE", + "MOVE_ROCK_TOMB", + "MOVE_STEALTH_ROCK", + "MOVE_SUBSTITUTE", + "MOVE_SWIFT", + "MOVE_SWORDS_DANCE", + "MOVE_TAUNT", + "MOVE_WHIRLWIND", + "MOVE_X_SCISSOR" + ], + "TutorMoves": [ + "MOVE_AIR_SLASH" + ], + "EggMoves": [] + }, + "HOUNDOUR": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_LEER" + }, + { + "Level": "1", + "Move": "MOVE_EMBER" + }, + { + "Level": "6", + "Move": "MOVE_TACKLE" + }, + { + "Level": "13", + "Move": "MOVE_ROAR" + }, + { + "Level": "16", + "Move": "MOVE_BITE" + }, + { + "Level": "24", + "Move": "MOVE_TAKE_DOWN" + }, + { + "Level": "28", + "Move": "MOVE_FIRE_FANG" + }, + { + "Level": "44", + "Move": "MOVE_FLAMETHROWER" + }, + { + "Level": "49", + "Move": "MOVE_CRUNCH" + }, + { + "Level": "52", + "Move": "MOVE_NASTY_PLOT" + } + ], + "TMMoves": [ + "MOVE_BODY_SLAM", + "MOVE_DARK_PULSE", + "MOVE_DOUBLE_EDGE", + "MOVE_ENDURE", + "MOVE_FIRE_BLAST", + "MOVE_FIRE_SPIN", + "MOVE_FLARE_BLITZ", + "MOVE_HEADBUTT", + "MOVE_HEAT_WAVE", + "MOVE_HYPER_VOICE", + "MOVE_MUD_SHOT", + "MOVE_OVERHEAT", + "MOVE_PROTECT", + "MOVE_SHADOW_BALL", + "MOVE_SLUDGE_BOMB", + "MOVE_SOLAR_BEAM", + "MOVE_SUBSTITUTE", + "MOVE_TAUNT", + "MOVE_WILL_O_WISP" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "HOUNDOOM": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_LEER" + }, + { + "Level": "1", + "Move": "MOVE_EMBER" + }, + { + "Level": "1", + "Move": "MOVE_NASTY_PLOT" + }, + { + "Level": "6", + "Move": "MOVE_TACKLE" + }, + { + "Level": "13", + "Move": "MOVE_ROAR" + }, + { + "Level": "16", + "Move": "MOVE_BITE" + }, + { + "Level": "21", + "Move": "MOVE_SNARL" + }, + { + "Level": "24", + "Move": "MOVE_TAKE_DOWN" + }, + { + "Level": "28", + "Move": "MOVE_FIRE_FANG" + }, + { + "Level": "34", + "Move": "MOVE_DARK_PULSE" + }, + { + "Level": "44", + "Move": "MOVE_FLAMETHROWER" + }, + { + "Level": "49", + "Move": "MOVE_CRUNCH" + }, + { + "Level": "55", + "Move": "MOVE_OVERHEAT" + } + ], + "TMMoves": [ + "MOVE_BODY_SLAM", + "MOVE_DOUBLE_EDGE", + "MOVE_ENDURE", + "MOVE_FIRE_BLAST", + "MOVE_FIRE_SPIN", + "MOVE_FLARE_BLITZ", + "MOVE_GIGA_IMPACT", + "MOVE_HEADBUTT", + "MOVE_HEAT_WAVE", + "MOVE_HYPER_BEAM", + "MOVE_HYPER_VOICE", + "MOVE_MUD_SHOT", + "MOVE_PROTECT", + "MOVE_SHADOW_BALL", + "MOVE_SLUDGE_BOMB", + "MOVE_SOLAR_BEAM", + "MOVE_SUBSTITUTE", + "MOVE_TAUNT", + "MOVE_THUNDER_FANG", + "MOVE_TOXIC", + "MOVE_WILL_O_WISP" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "LARVITAR": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_LEER" + }, + { + "Level": "3", + "Move": "MOVE_ROCK_THROW" + }, + { + "Level": "9", + "Move": "MOVE_BITE" + }, + { + "Level": "12", + "Move": "MOVE_SAND_TOMB" + }, + { + "Level": "15", + "Move": "MOVE_ROCK_SLIDE" + }, + { + "Level": "21", + "Move": "MOVE_SCREECH" + }, + { + "Level": "27", + "Move": "MOVE_CRUNCH" + }, + { + "Level": "33", + "Move": "MOVE_EARTHQUAKE" + }, + { + "Level": "37", + "Move": "MOVE_STONE_EDGE" + }, + { + "Level": "40", + "Move": "MOVE_ROCK_BLAST" + }, + { + "Level": "48", + "Move": "MOVE_HYPER_BEAM" + } + ], + "TMMoves": [ + "MOVE_BODY_SLAM", + "MOVE_BRICK_BREAK", + "MOVE_BULLDOZE", + "MOVE_CURSE", + "MOVE_DARK_PULSE", + "MOVE_DIG", + "MOVE_DOUBLE_EDGE", + "MOVE_EARTH_POWER", + "MOVE_ENDURE", + "MOVE_GIGA_IMPACT", + "MOVE_HEADBUTT", + "MOVE_IRON_DEFENSE", + "MOVE_IRON_HEAD", + "MOVE_MUD_SHOT", + "MOVE_OUTRAGE", + "MOVE_PROTECT", + "MOVE_ROCK_TOMB", + "MOVE_STEALTH_ROCK", + "MOVE_SUBSTITUTE", + "MOVE_TAUNT" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "PUPITAR": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_LEER" + }, + { + "Level": "3", + "Move": "MOVE_ROCK_THROW" + }, + { + "Level": "9", + "Move": "MOVE_BITE" + }, + { + "Level": "12", + "Move": "MOVE_SAND_TOMB" + }, + { + "Level": "15", + "Move": "MOVE_ROCK_SLIDE" + }, + { + "Level": "21", + "Move": "MOVE_SCREECH" + }, + { + "Level": "27", + "Move": "MOVE_CRUNCH" + }, + { + "Level": "33", + "Move": "MOVE_EARTHQUAKE" + }, + { + "Level": "37", + "Move": "MOVE_STONE_EDGE" + }, + { + "Level": "40", + "Move": "MOVE_ROCK_BLAST" + }, + { + "Level": "48", + "Move": "MOVE_HYPER_BEAM" + } + ], + "TMMoves": [ + "MOVE_AERIAL_ACE", + "MOVE_BODY_SLAM", + "MOVE_BRICK_BREAK", + "MOVE_BULLDOZE", + "MOVE_CURSE", + "MOVE_DARK_PULSE", + "MOVE_DIG", + "MOVE_DOUBLE_EDGE", + "MOVE_EARTH_POWER", + "MOVE_ENDURE", + "MOVE_GIGA_IMPACT", + "MOVE_HEADBUTT", + "MOVE_IRON_HEAD", + "MOVE_MUD_SHOT", + "MOVE_OUTRAGE", + "MOVE_PROTECT", + "MOVE_ROCK_TOMB", + "MOVE_STEALTH_ROCK", + "MOVE_SUBSTITUTE", + "MOVE_TAUNT" + ], + "TutorMoves": [ + "MOVE_IRON_DEFENSE" + ], + "EggMoves": [] + }, + "TYRANITAR": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_LEER" + }, + { + "Level": "3", + "Move": "MOVE_ROCK_THROW" + }, + { + "Level": "9", + "Move": "MOVE_BITE" + }, + { + "Level": "12", + "Move": "MOVE_SAND_TOMB" + }, + { + "Level": "15", + "Move": "MOVE_ROCK_SLIDE" + }, + { + "Level": "21", + "Move": "MOVE_SCREECH" + }, + { + "Level": "27", + "Move": "MOVE_CRUNCH" + }, + { + "Level": "33", + "Move": "MOVE_EARTHQUAKE" + }, + { + "Level": "37", + "Move": "MOVE_STONE_EDGE" + }, + { + "Level": "40", + "Move": "MOVE_ROCK_BLAST" + }, + { + "Level": "48", + "Move": "MOVE_HYPER_BEAM" + }, + { + "Level": "53", + "Move": "MOVE_HEAVY_SLAM" + }, + { + "Level": "56", + "Move": "MOVE_GIGA_IMPACT" + } + ], + "TMMoves": [ + "MOVE_AERIAL_ACE", + "MOVE_BLIZZARD", + "MOVE_BODY_SLAM", + "MOVE_BRICK_BREAK", + "MOVE_BULLDOZE", + "MOVE_CURSE", + "MOVE_DIG", + "MOVE_DOUBLE_EDGE", + "MOVE_DRAGON_CLAW", + "MOVE_DRAGON_PULSE", + "MOVE_EARTH_POWER", + "MOVE_ENDURE", + "MOVE_FIRE_BLAST", + "MOVE_FIRE_FANG", + "MOVE_FIRE_PUNCH", + "MOVE_FLAMETHROWER", + "MOVE_HEADBUTT", + "MOVE_HYDRO_PUMP", + "MOVE_ICE_BEAM", + "MOVE_ICE_FANG", + "MOVE_ICE_PUNCH", + "MOVE_IRON_HEAD", + "MOVE_KNOCK_OFF", + "MOVE_MUD_SHOT", + "MOVE_OUTRAGE", + "MOVE_POWER_GEM", + "MOVE_PROTECT", + "MOVE_ROAR", + "MOVE_ROCK_TOMB", + "MOVE_SHADOW_CLAW", + "MOVE_STEALTH_ROCK", + "MOVE_SUBSTITUTE", + "MOVE_TAUNT", + "MOVE_THUNDER", + "MOVE_THUNDERBOLT", + "MOVE_THUNDER_FANG", + "MOVE_THUNDER_PUNCH", + "MOVE_THUNDER_WAVE" + ], + "TutorMoves": [ + "MOVE_DARK_PULSE", + "MOVE_IRON_DEFENSE" + ], + "EggMoves": [] + }, + "RALTS": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_GROWL" + }, + { + "Level": "1", + "Move": "MOVE_DISARMING_VOICE" + }, + { + "Level": "6", + "Move": "MOVE_CONFUSION" + }, + { + "Level": "9", + "Move": "MOVE_HYPNOSIS" + }, + { + "Level": "12", + "Move": "MOVE_DRAINING_KISS" + }, + { + "Level": "15", + "Move": "MOVE_TELEPORT" + }, + { + "Level": "18", + "Move": "MOVE_PSYBEAM" + }, + { + "Level": "20", + "Move": "MOVE_MAGICAL_LEAF" + }, + { + "Level": "24", + "Move": "MOVE_CONFUSE_RAY" + }, + { + "Level": "28", + "Move": "MOVE_CHARM" + }, + { + "Level": "30", + "Move": "MOVE_DOUBLE_TEAM" + }, + { + "Level": "35", + "Move": "MOVE_CALM_MIND" + }, + { + "Level": "38", + "Move": "MOVE_PSYCHIC" + }, + { + "Level": "44", + "Move": "MOVE_MYSTICAL_FIRE" + }, + { + "Level": "58", + "Move": "MOVE_FUTURE_SIGHT" + } + ], + "TMMoves": [ + "MOVE_BODY_SLAM", + "MOVE_ENDURE", + "MOVE_FIRE_PUNCH", + "MOVE_HYPER_VOICE", + "MOVE_ICE_PUNCH", + "MOVE_ICY_WIND", + "MOVE_LIGHT_SCREEN", + "MOVE_METRONOME", + "MOVE_PROTECT", + "MOVE_PSYSHOCK", + "MOVE_REFLECT", + "MOVE_SHADOW_BALL", + "MOVE_SUBSTITUTE", + "MOVE_SWIFT", + "MOVE_TAUNT", + "MOVE_THUNDERBOLT", + "MOVE_THUNDER_PUNCH", + "MOVE_THUNDER_WAVE", + "MOVE_WILL_O_WISP", + "MOVE_ZEN_HEADBUTT" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "KIRLIA": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_GROWL" + }, + { + "Level": "1", + "Move": "MOVE_DISARMING_VOICE" + }, + { + "Level": "6", + "Move": "MOVE_CONFUSION" + }, + { + "Level": "9", + "Move": "MOVE_HYPNOSIS" + }, + { + "Level": "12", + "Move": "MOVE_DRAINING_KISS" + }, + { + "Level": "15", + "Move": "MOVE_TELEPORT" + }, + { + "Level": "18", + "Move": "MOVE_PSYBEAM" + }, + { + "Level": "20", + "Move": "MOVE_MAGICAL_LEAF" + }, + { + "Level": "24", + "Move": "MOVE_CONFUSE_RAY" + }, + { + "Level": "28", + "Move": "MOVE_CHARM" + }, + { + "Level": "30", + "Move": "MOVE_DOUBLE_TEAM" + }, + { + "Level": "35", + "Move": "MOVE_CALM_MIND" + }, + { + "Level": "38", + "Move": "MOVE_PSYCHIC" + }, + { + "Level": "44", + "Move": "MOVE_MYSTICAL_FIRE" + }, + { + "Level": "58", + "Move": "MOVE_FUTURE_SIGHT" + } + ], + "TMMoves": [ + "MOVE_BODY_SLAM", + "MOVE_ENDURE", + "MOVE_FIRE_PUNCH", + "MOVE_HYPER_BEAM", + "MOVE_HYPER_VOICE", + "MOVE_ICE_PUNCH", + "MOVE_ICY_WIND", + "MOVE_LIGHT_SCREEN", + "MOVE_METRONOME", + "MOVE_PROTECT", + "MOVE_PSYSHOCK", + "MOVE_REFLECT", + "MOVE_SHADOW_BALL", + "MOVE_SUBSTITUTE", + "MOVE_SWIFT", + "MOVE_TAUNT", + "MOVE_THUNDERBOLT", + "MOVE_THUNDER_PUNCH", + "MOVE_THUNDER_WAVE", + "MOVE_WILL_O_WISP", + "MOVE_ZEN_HEADBUTT" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "GARDEVOIR": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_GROWL" + }, + { + "Level": "1", + "Move": "MOVE_DISARMING_VOICE" + }, + { + "Level": "6", + "Move": "MOVE_CONFUSION" + }, + { + "Level": "9", + "Move": "MOVE_HYPNOSIS" + }, + { + "Level": "12", + "Move": "MOVE_DRAINING_KISS" + }, + { + "Level": "15", + "Move": "MOVE_TELEPORT" + }, + { + "Level": "18", + "Move": "MOVE_PSYBEAM" + }, + { + "Level": "20", + "Move": "MOVE_MAGICAL_LEAF" + }, + { + "Level": "24", + "Move": "MOVE_CONFUSE_RAY" + }, + { + "Level": "28", + "Move": "MOVE_CHARM" + }, + { + "Level": "30", + "Move": "MOVE_DOUBLE_TEAM" + }, + { + "Level": "32", + "Move": "MOVE_WISH" + }, + { + "Level": "35", + "Move": "MOVE_CALM_MIND" + }, + { + "Level": "38", + "Move": "MOVE_PSYCHIC" + }, + { + "Level": "44", + "Move": "MOVE_MYSTICAL_FIRE" + }, + { + "Level": "49", + "Move": "MOVE_MOONBLAST" + }, + { + "Level": "58", + "Move": "MOVE_FUTURE_SIGHT" + } + ], + "TMMoves": [ + "MOVE_AURA_SPHERE", + "MOVE_BODY_SLAM", + "MOVE_ENDURE", + "MOVE_ENERGY_BALL", + "MOVE_FIRE_PUNCH", + "MOVE_FOCUS_BLAST", + "MOVE_GIGA_IMPACT", + "MOVE_HYPER_BEAM", + "MOVE_HYPER_VOICE", + "MOVE_ICE_PUNCH", + "MOVE_ICY_WIND", + "MOVE_LIGHT_SCREEN", + "MOVE_METRONOME", + "MOVE_PROTECT", + "MOVE_PSYSHOCK", + "MOVE_REFLECT", + "MOVE_SAFEGUARD", + "MOVE_SHADOW_BALL", + "MOVE_SUBSTITUTE", + "MOVE_SWIFT", + "MOVE_TAUNT", + "MOVE_THUNDERBOLT", + "MOVE_THUNDER_PUNCH", + "MOVE_THUNDER_WAVE", + "MOVE_WILL_O_WISP", + "MOVE_ZEN_HEADBUTT" + ], + "TutorMoves": [ + "MOVE_DAZZLING_GLEAM" + ], + "EggMoves": [] + }, + "SABLEYE": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_LEER" + }, + { + "Level": "9", + "Move": "MOVE_SHADOW_SNEAK" + }, + { + "Level": "15", + "Move": "MOVE_TAKE_DOWN" + }, + { + "Level": "18", + "Move": "MOVE_DETECT" + }, + { + "Level": "20", + "Move": "MOVE_SHADOW_CLAW" + }, + { + "Level": "22", + "Move": "MOVE_CONFUSE_RAY" + }, + { + "Level": "25", + "Move": "MOVE_KNOCK_OFF" + }, + { + "Level": "28", + "Move": "MOVE_PSYBEAM" + }, + { + "Level": "33", + "Move": "MOVE_NIGHT_SLASH" + }, + { + "Level": "39", + "Move": "MOVE_POWER_GEM" + }, + { + "Level": "42", + "Move": "MOVE_ZEN_HEADBUTT" + }, + { + "Level": "45", + "Move": "MOVE_SHADOW_BALL" + }, + { + "Level": "50", + "Move": "MOVE_RECOVER" + }, + { + "Level": "53", + "Move": "MOVE_PARTING_SHOT" + }, + { + "Level": "56", + "Move": "MOVE_PHANTOM_FORCE" + } + ], + "TMMoves": [ + "MOVE_AERIAL_ACE", + "MOVE_BODY_SLAM", + "MOVE_BRICK_BREAK", + "MOVE_BULK_UP", + "MOVE_CALM_MIND", + "MOVE_DARK_PULSE", + "MOVE_DAZZLING_GLEAM", + "MOVE_DIG", + "MOVE_ENDURE", + "MOVE_ENERGY_BALL", + "MOVE_FIRE_PUNCH", + "MOVE_GIGA_DRAIN", + "MOVE_GIGA_IMPACT", + "MOVE_HEAL_BLOCK", + "MOVE_HYPER_BEAM", + "MOVE_ICE_PUNCH", + "MOVE_LIGHT_SCREEN", + "MOVE_METRONOME", + "MOVE_MUD_SHOT", + "MOVE_NASTY_PLOT", + "MOVE_POISON_JAB", + "MOVE_PROTECT", + "MOVE_PSYCHIC", + "MOVE_REFLECT", + "MOVE_ROCK_TOMB", + "MOVE_SAFEGUARD", + "MOVE_SUBSTITUTE", + "MOVE_TAUNT", + "MOVE_THUNDER_PUNCH", + "MOVE_THUNDER_WAVE", + "MOVE_WILL_O_WISP", + "MOVE_X_SCISSOR" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "MAWILE": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_BITE" + }, + { + "Level": "1", + "Move": "MOVE_FAIRY_WIND" + }, + { + "Level": "5", + "Move": "MOVE_FAKE_TEARS" + }, + { + "Level": "16", + "Move": "MOVE_KNOCK_OFF" + }, + { + "Level": "20", + "Move": "MOVE_CHARM" + }, + { + "Level": "22", + "Move": "MOVE_DRAINING_KISS" + }, + { + "Level": "24", + "Move": "MOVE_IRON_DEFENSE" + }, + { + "Level": "28", + "Move": "MOVE_CRUNCH" + }, + { + "Level": "36", + "Move": "MOVE_IRON_HEAD" + }, + { + "Level": "40", + "Move": "MOVE_TAUNT" + }, + { + "Level": "48", + "Move": "MOVE_PLAY_ROUGH" + }, + { + "Level": "55", + "Move": "MOVE_DYNAMIC_PUNCH" + } + ], + "TMMoves": [ + "MOVE_BODY_SLAM", + "MOVE_BRICK_BREAK", + "MOVE_DARK_PULSE", + "MOVE_DAZZLING_GLEAM", + "MOVE_DOUBLE_EDGE", + "MOVE_DOUBLE_TEAM", + "MOVE_ENDURE", + "MOVE_FIRE_BLAST", + "MOVE_FIRE_FANG", + "MOVE_FLAMETHROWER", + "MOVE_FLASH_CANNON", + "MOVE_FOCUS_BLAST", + "MOVE_GIGA_IMPACT", + "MOVE_HEADBUTT", + "MOVE_HYPER_BEAM", + "MOVE_ICE_BEAM", + "MOVE_ICE_FANG", + "MOVE_ICE_PUNCH", + "MOVE_POWER_UP_PUNCH", + "MOVE_PROTECT", + "MOVE_ROCK_SLIDE", + "MOVE_ROCK_SMASH", + "MOVE_ROCK_TOMB", + "MOVE_SHADOW_BALL", + "MOVE_SLUDGE_BOMB", + "MOVE_SOLAR_BEAM", + "MOVE_STEALTH_ROCK", + "MOVE_STONE_EDGE", + "MOVE_SUBSTITUTE", + "MOVE_SWORDS_DANCE", + "MOVE_THUNDER_FANG", + "MOVE_THUNDER_PUNCH" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "ARON": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_SCREECH" + }, + { + "Level": "1", + "Move": "MOVE_HARDEN" + }, + { + "Level": "4", + "Move": "MOVE_METAL_CLAW" + }, + { + "Level": "8", + "Move": "MOVE_ROCK_TOMB" + }, + { + "Level": "12", + "Move": "MOVE_ROAR" + }, + { + "Level": "16", + "Move": "MOVE_HEADBUTT" + }, + { + "Level": "20", + "Move": "MOVE_PROTECT" + }, + { + "Level": "24", + "Move": "MOVE_ROCK_SLIDE" + }, + { + "Level": "28", + "Move": "MOVE_IRON_HEAD" + }, + { + "Level": "33", + "Move": "MOVE_METAL_SOUND" + }, + { + "Level": "36", + "Move": "MOVE_TAKE_DOWN" + }, + { + "Level": "44", + "Move": "MOVE_IRON_TAIL" + }, + { + "Level": "48", + "Move": "MOVE_IRON_DEFENSE" + }, + { + "Level": "52", + "Move": "MOVE_HEAVY_SLAM" + }, + { + "Level": "56", + "Move": "MOVE_DOUBLE_EDGE" + }, + { + "Level": "66", + "Move": "MOVE_HEAD_SMASH" + } + ], + "TMMoves": [ + "MOVE_BODY_SLAM", + "MOVE_BULLDOZE", + "MOVE_DIG", + "MOVE_EARTHQUAKE", + "MOVE_EARTH_POWER", + "MOVE_ENDURE", + "MOVE_MUD_SHOT", + "MOVE_SHADOW_CLAW", + "MOVE_STEALTH_ROCK", + "MOVE_SUBSTITUTE" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "LAIRON": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_SCREECH" + }, + { + "Level": "1", + "Move": "MOVE_HARDEN" + }, + { + "Level": "4", + "Move": "MOVE_METAL_CLAW" + }, + { + "Level": "8", + "Move": "MOVE_ROCK_TOMB" + }, + { + "Level": "12", + "Move": "MOVE_ROAR" + }, + { + "Level": "16", + "Move": "MOVE_HEADBUTT" + }, + { + "Level": "20", + "Move": "MOVE_PROTECT" + }, + { + "Level": "24", + "Move": "MOVE_ROCK_SLIDE" + }, + { + "Level": "28", + "Move": "MOVE_IRON_HEAD" + }, + { + "Level": "33", + "Move": "MOVE_METAL_SOUND" + }, + { + "Level": "36", + "Move": "MOVE_TAKE_DOWN" + }, + { + "Level": "44", + "Move": "MOVE_IRON_TAIL" + }, + { + "Level": "48", + "Move": "MOVE_IRON_DEFENSE" + }, + { + "Level": "52", + "Move": "MOVE_HEAVY_SLAM" + }, + { + "Level": "56", + "Move": "MOVE_DOUBLE_EDGE" + }, + { + "Level": "66", + "Move": "MOVE_HEAD_SMASH" + } + ], + "TMMoves": [ + "MOVE_BODY_SLAM", + "MOVE_BULLDOZE", + "MOVE_DIG", + "MOVE_EARTHQUAKE", + "MOVE_EARTH_POWER", + "MOVE_ENDURE", + "MOVE_MUD_SHOT", + "MOVE_SHADOW_CLAW", + "MOVE_STEALTH_ROCK", + "MOVE_STONE_EDGE", + "MOVE_SUBSTITUTE" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "AGGRON": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_SCREECH" + }, + { + "Level": "1", + "Move": "MOVE_HARDEN" + }, + { + "Level": "4", + "Move": "MOVE_METAL_CLAW" + }, + { + "Level": "8", + "Move": "MOVE_ROCK_TOMB" + }, + { + "Level": "12", + "Move": "MOVE_ROAR" + }, + { + "Level": "16", + "Move": "MOVE_HEADBUTT" + }, + { + "Level": "20", + "Move": "MOVE_PROTECT" + }, + { + "Level": "24", + "Move": "MOVE_ROCK_SLIDE" + }, + { + "Level": "28", + "Move": "MOVE_IRON_HEAD" + }, + { + "Level": "33", + "Move": "MOVE_METAL_SOUND" + }, + { + "Level": "36", + "Move": "MOVE_TAKE_DOWN" + }, + { + "Level": "44", + "Move": "MOVE_IRON_TAIL" + }, + { + "Level": "48", + "Move": "MOVE_IRON_DEFENSE" + }, + { + "Level": "52", + "Move": "MOVE_HEAVY_SLAM" + }, + { + "Level": "56", + "Move": "MOVE_DOUBLE_EDGE" + }, + { + "Level": "66", + "Move": "MOVE_HEAD_SMASH" + } + ], + "TMMoves": [ + "MOVE_BLIZZARD", + "MOVE_BODY_SLAM", + "MOVE_BRICK_BREAK", + "MOVE_BULLDOZE", + "MOVE_CRUNCH", + "MOVE_DARK_PULSE", + "MOVE_DIG", + "MOVE_DRAGON_CLAW", + "MOVE_DRAGON_PULSE", + "MOVE_EARTHQUAKE", + "MOVE_EARTH_POWER", + "MOVE_ENDURE", + "MOVE_FIRE_BLAST", + "MOVE_FIRE_PUNCH", + "MOVE_FLAMETHROWER", + "MOVE_FOCUS_BLAST", + "MOVE_GIGA_IMPACT", + "MOVE_HYDRO_PUMP", + "MOVE_HYPER_BEAM", + "MOVE_ICE_BEAM", + "MOVE_ICE_PUNCH", + "MOVE_MUD_SHOT", + "MOVE_OUTRAGE", + "MOVE_SHADOW_CLAW", + "MOVE_SOLAR_BEAM", + "MOVE_STEALTH_ROCK", + "MOVE_STONE_EDGE", + "MOVE_SUBSTITUTE", + "MOVE_SURF", + "MOVE_THUNDER", + "MOVE_THUNDERBOLT", + "MOVE_THUNDER_PUNCH", + "MOVE_THUNDER_WAVE", + "MOVE_WHIRLPOOL" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "MEDITITE": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_CONFUSION" + }, + { + "Level": "1", + "Move": "MOVE_WORK_UP" + }, + { + "Level": "9", + "Move": "MOVE_DETECT" + }, + { + "Level": "12", + "Move": "MOVE_ENDURE" + }, + { + "Level": "14", + "Move": "MOVE_ROCK_SMASH" + }, + { + "Level": "16", + "Move": "MOVE_BULLET_PUNCH" + }, + { + "Level": "20", + "Move": "MOVE_PSYBEAM" + }, + { + "Level": "23", + "Move": "MOVE_CALM_MIND" + }, + { + "Level": "25", + "Move": "MOVE_ZEN_HEADBUTT" + }, + { + "Level": "30", + "Move": "MOVE_TAKE_DOWN" + }, + { + "Level": "41", + "Move": "MOVE_RECOVER" + }, + { + "Level": "52", + "Move": "MOVE_DYNAMIC_PUNCH" + } + ], + "TMMoves": [ + "MOVE_AERIAL_ACE", + "MOVE_BODY_SLAM", + "MOVE_BRICK_BREAK", + "MOVE_BULK_UP", + "MOVE_CLOSE_COMBAT", + "MOVE_FIRE_PUNCH", + "MOVE_FOCUS_BLAST", + "MOVE_ICE_PUNCH", + "MOVE_LIGHT_SCREEN", + "MOVE_METRONOME", + "MOVE_POISON_JAB", + "MOVE_POWER_UP_PUNCH", + "MOVE_PROTECT", + "MOVE_PSYCHIC", + "MOVE_PSYSHOCK", + "MOVE_REFLECT", + "MOVE_ROCK_SLIDE", + "MOVE_ROCK_TOMB", + "MOVE_SHADOW_BALL", + "MOVE_SUBSTITUTE", + "MOVE_SWIFT", + "MOVE_TAUNT", + "MOVE_THUNDER_PUNCH" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "MEDICHAM": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_CONFUSION" + }, + { + "Level": "1", + "Move": "MOVE_WORK_UP" + }, + { + "Level": "9", + "Move": "MOVE_DETECT" + }, + { + "Level": "12", + "Move": "MOVE_ENDURE" + }, + { + "Level": "14", + "Move": "MOVE_ROCK_SMASH" + }, + { + "Level": "16", + "Move": "MOVE_BULLET_PUNCH" + }, + { + "Level": "20", + "Move": "MOVE_PSYBEAM" + }, + { + "Level": "23", + "Move": "MOVE_CALM_MIND" + }, + { + "Level": "25", + "Move": "MOVE_ZEN_HEADBUTT" + }, + { + "Level": "30", + "Move": "MOVE_TAKE_DOWN" + }, + { + "Level": "34", + "Move": "MOVE_AGILITY" + }, + { + "Level": "41", + "Move": "MOVE_RECOVER" + }, + { + "Level": "52", + "Move": "MOVE_DYNAMIC_PUNCH" + } + ], + "TMMoves": [ + "MOVE_AERIAL_ACE", + "MOVE_BODY_SLAM", + "MOVE_BRICK_BREAK", + "MOVE_BULK_UP", + "MOVE_CLOSE_COMBAT", + "MOVE_FOCUS_BLAST", + "MOVE_GIGA_IMPACT", + "MOVE_HYPER_BEAM", + "MOVE_LIGHT_SCREEN", + "MOVE_METRONOME", + "MOVE_POISON_JAB", + "MOVE_POWER_UP_PUNCH", + "MOVE_PROTECT", + "MOVE_PSYCHIC", + "MOVE_PSYSHOCK", + "MOVE_REFLECT", + "MOVE_ROCK_SLIDE", + "MOVE_ROCK_TOMB", + "MOVE_SHADOW_BALL", + "MOVE_SUBSTITUTE", + "MOVE_SWIFT", + "MOVE_TAUNT" + ], + "TutorMoves": [ + "MOVE_FIRE_PUNCH", + "MOVE_ICE_PUNCH", + "MOVE_THUNDER_PUNCH" + ], + "EggMoves": [] + }, + "ELECTRIKE": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_LEER" + }, + { + "Level": "1", + "Move": "MOVE_QUICK_ATTACK" + }, + { + "Level": "8", + "Move": "MOVE_THUNDER_SHOCK" + }, + { + "Level": "12", + "Move": "MOVE_THUNDER_WAVE" + }, + { + "Level": "16", + "Move": "MOVE_SPARK" + }, + { + "Level": "20", + "Move": "MOVE_BITE" + }, + { + "Level": "22", + "Move": "MOVE_EERIE_IMPULSE" + }, + { + "Level": "24", + "Move": "MOVE_THUNDER_FANG" + }, + { + "Level": "28", + "Move": "MOVE_ROAR" + }, + { + "Level": "30", + "Move": "MOVE_SNARL" + }, + { + "Level": "36", + "Move": "MOVE_CHARGE" + }, + { + "Level": "40", + "Move": "MOVE_THUNDERBOLT" + }, + { + "Level": "44", + "Move": "MOVE_WILD_CHARGE" + }, + { + "Level": "50", + "Move": "MOVE_THUNDER" + } + ], + "TMMoves": [ + "MOVE_AGILITY", + "MOVE_BODY_SLAM", + "MOVE_CRUNCH", + "MOVE_CURSE", + "MOVE_DISCHARGE", + "MOVE_ENDURE", + "MOVE_FIRE_FANG", + "MOVE_FLAMETHROWER", + "MOVE_HEADBUTT", + "MOVE_ICE_FANG", + "MOVE_LIGHT_SCREEN", + "MOVE_PROTECT", + "MOVE_SUBSTITUTE", + "MOVE_SWIFT", + "MOVE_VOLT_SWITCH" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "MANECTRIC": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_LEER" + }, + { + "Level": "1", + "Move": "MOVE_QUICK_ATTACK" + }, + { + "Level": "1", + "Move": "MOVE_FIRE_FANG" + }, + { + "Level": "8", + "Move": "MOVE_THUNDER_SHOCK" + }, + { + "Level": "12", + "Move": "MOVE_THUNDER_WAVE" + }, + { + "Level": "16", + "Move": "MOVE_SPARK" + }, + { + "Level": "20", + "Move": "MOVE_BITE" + }, + { + "Level": "22", + "Move": "MOVE_EERIE_IMPULSE" + }, + { + "Level": "24", + "Move": "MOVE_THUNDER_FANG" + }, + { + "Level": "28", + "Move": "MOVE_ROAR" + }, + { + "Level": "30", + "Move": "MOVE_SNARL" + }, + { + "Level": "36", + "Move": "MOVE_CHARGE" + }, + { + "Level": "40", + "Move": "MOVE_THUNDERBOLT" + }, + { + "Level": "44", + "Move": "MOVE_WILD_CHARGE" + }, + { + "Level": "50", + "Move": "MOVE_THUNDER" + } + ], + "TMMoves": [ + "MOVE_AGILITY", + "MOVE_BODY_SLAM", + "MOVE_CRUNCH", + "MOVE_CURSE", + "MOVE_DISCHARGE", + "MOVE_ENDURE", + "MOVE_FLAMETHROWER", + "MOVE_GIGA_IMPACT", + "MOVE_HEADBUTT", + "MOVE_HYPER_BEAM", + "MOVE_HYPER_VOICE", + "MOVE_ICE_FANG", + "MOVE_LIGHT_SCREEN", + "MOVE_OVERHEAT", + "MOVE_PROTECT", + "MOVE_SUBSTITUTE", + "MOVE_SWIFT", + "MOVE_VOLT_SWITCH" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "ROSELIA": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_ABSORB" + }, + { + "Level": "1", + "Move": "MOVE_GROWTH" + }, + { + "Level": "1", + "Move": "MOVE_STUN_SPORE" + }, + { + "Level": "1", + "Move": "MOVE_CHARM" + }, + { + "Level": "5", + "Move": "MOVE_RAZOR_LEAF" + }, + { + "Level": "8", + "Move": "MOVE_PIN_MISSILE" + }, + { + "Level": "10", + "Move": "MOVE_LEECH_SEED" + }, + { + "Level": "15", + "Move": "MOVE_MAGICAL_LEAF" + }, + { + "Level": "18", + "Move": "MOVE_SLEEP_POWDER" + }, + { + "Level": "22", + "Move": "MOVE_TOXIC_SPIKES" + }, + { + "Level": "30", + "Move": "MOVE_GIGA_DRAIN" + }, + { + "Level": "33", + "Move": "MOVE_POISON_JAB" + }, + { + "Level": "37", + "Move": "MOVE_SYNTHESIS" + }, + { + "Level": "44", + "Move": "MOVE_TOXIC" + }, + { + "Level": "55", + "Move": "MOVE_LEAF_STORM" + } + ], + "TMMoves": [ + "MOVE_BODY_SLAM", + "MOVE_BULLET_SEED", + "MOVE_DAZZLING_GLEAM", + "MOVE_ENDURE", + "MOVE_ENERGY_BALL", + "MOVE_MUD_SHOT", + "MOVE_PROTECT", + "MOVE_SHADOW_BALL", + "MOVE_SLUDGE_BOMB", + "MOVE_SOLAR_BEAM", + "MOVE_SPIKES", + "MOVE_SUBSTITUTE", + "MOVE_SWIFT", + "MOVE_SWORDS_DANCE" + ], + "TutorMoves": [ + "MOVE_POISON_STING" + ], + "EggMoves": [] + }, + "CARVANHA": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_LEER" + }, + { + "Level": "1", + "Move": "MOVE_AQUA_JET" + }, + { + "Level": "8", + "Move": "MOVE_FOCUS_ENERGY" + }, + { + "Level": "16", + "Move": "MOVE_BITE" + }, + { + "Level": "20", + "Move": "MOVE_FLIP_TURN" + }, + { + "Level": "24", + "Move": "MOVE_SCREECH" + }, + { + "Level": "32", + "Move": "MOVE_CRUNCH" + }, + { + "Level": "40", + "Move": "MOVE_TAKE_DOWN" + }, + { + "Level": "44", + "Move": "MOVE_LIQUIDATION" + }, + { + "Level": "51", + "Move": "MOVE_BOUNCE" + }, + { + "Level": "54", + "Move": "MOVE_DOUBLE_EDGE" + } + ], + "TMMoves": [ + "MOVE_AGILITY", + "MOVE_BLIZZARD", + "MOVE_DARK_PULSE", + "MOVE_ENDURE", + "MOVE_HYDRO_PUMP", + "MOVE_ICE_BEAM", + "MOVE_ICE_FANG", + "MOVE_ICY_WIND", + "MOVE_PROTECT", + "MOVE_SUBSTITUTE", + "MOVE_SURF", + "MOVE_SWIFT", + "MOVE_TAUNT", + "MOVE_WATERFALL", + "MOVE_WHIRLPOOL", + "MOVE_ZEN_HEADBUTT" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "SHARPEDO": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_LEER" + }, + { + "Level": "1", + "Move": "MOVE_NIGHT_SLASH" + }, + { + "Level": "1", + "Move": "MOVE_AQUA_JET" + }, + { + "Level": "8", + "Move": "MOVE_FOCUS_ENERGY" + }, + { + "Level": "16", + "Move": "MOVE_BITE" + }, + { + "Level": "20", + "Move": "MOVE_FLIP_TURN" + }, + { + "Level": "24", + "Move": "MOVE_SCREECH" + }, + { + "Level": "32", + "Move": "MOVE_CRUNCH" + }, + { + "Level": "36", + "Move": "MOVE_AGILITY" + }, + { + "Level": "40", + "Move": "MOVE_TAKE_DOWN" + }, + { + "Level": "44", + "Move": "MOVE_LIQUIDATION" + }, + { + "Level": "51", + "Move": "MOVE_BOUNCE" + }, + { + "Level": "54", + "Move": "MOVE_DOUBLE_EDGE" + } + ], + "TMMoves": [ + "MOVE_BLIZZARD", + "MOVE_CLOSE_COMBAT", + "MOVE_DARK_PULSE", + "MOVE_EARTHQUAKE", + "MOVE_ENDURE", + "MOVE_GIGA_IMPACT", + "MOVE_HYDRO_PUMP", + "MOVE_HYPER_BEAM", + "MOVE_ICE_BEAM", + "MOVE_ICE_FANG", + "MOVE_ICY_WIND", + "MOVE_POISON_JAB", + "MOVE_PROTECT", + "MOVE_ROCK_TOMB", + "MOVE_SUBSTITUTE", + "MOVE_SURF", + "MOVE_SWIFT", + "MOVE_TAUNT", + "MOVE_WATERFALL", + "MOVE_WHIRLPOOL", + "MOVE_ZEN_HEADBUTT" + ], + "TutorMoves": [ + "MOVE_SLASH" + ], + "EggMoves": [] + }, + "NUMEL": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_GROWL" + }, + { + "Level": "5", + "Move": "MOVE_EMBER" + }, + { + "Level": "8", + "Move": "MOVE_FOCUS_ENERGY" + }, + { + "Level": "12", + "Move": "MOVE_BULLDOZE" + }, + { + "Level": "19", + "Move": "MOVE_AMNESIA" + }, + { + "Level": "22", + "Move": "MOVE_LAVA_PLUME" + }, + { + "Level": "26", + "Move": "MOVE_EARTH_POWER" + }, + { + "Level": "29", + "Move": "MOVE_CURSE" + }, + { + "Level": "31", + "Move": "MOVE_TAKE_DOWN" + }, + { + "Level": "40", + "Move": "MOVE_EARTHQUAKE" + }, + { + "Level": "46", + "Move": "MOVE_FLAMETHROWER" + }, + { + "Level": "51", + "Move": "MOVE_DOUBLE_EDGE" + }, + { + "Level": "55", + "Move": "MOVE_HEAT_CRASH" + } + ], + "TMMoves": [ + "MOVE_BODY_SLAM", + "MOVE_DIG", + "MOVE_ENDURE", + "MOVE_FIRE_BLAST", + "MOVE_FIRE_SPIN", + "MOVE_FLARE_BLITZ", + "MOVE_FLASH_CANNON", + "MOVE_HEADBUTT", + "MOVE_HEAT_WAVE", + "MOVE_IRON_HEAD", + "MOVE_OVERHEAT", + "MOVE_PROTECT", + "MOVE_ROAR", + "MOVE_ROCK_SLIDE", + "MOVE_ROCK_TOMB", + "MOVE_STEALTH_ROCK", + "MOVE_STONE_EDGE", + "MOVE_SUBSTITUTE", + "MOVE_WILL_O_WISP", + "MOVE_ZEN_HEADBUTT" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "CAMERUPT": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_GROWL" + }, + { + "Level": "5", + "Move": "MOVE_EMBER" + }, + { + "Level": "8", + "Move": "MOVE_FOCUS_ENERGY" + }, + { + "Level": "12", + "Move": "MOVE_BULLDOZE" + }, + { + "Level": "19", + "Move": "MOVE_AMNESIA" + }, + { + "Level": "22", + "Move": "MOVE_LAVA_PLUME" + }, + { + "Level": "26", + "Move": "MOVE_EARTH_POWER" + }, + { + "Level": "29", + "Move": "MOVE_CURSE" + }, + { + "Level": "31", + "Move": "MOVE_TAKE_DOWN" + }, + { + "Level": "40", + "Move": "MOVE_EARTHQUAKE" + }, + { + "Level": "46", + "Move": "MOVE_FLAMETHROWER" + }, + { + "Level": "51", + "Move": "MOVE_DOUBLE_EDGE" + }, + { + "Level": "55", + "Move": "MOVE_HEAT_CRASH" + } + ], + "TMMoves": [ + "MOVE_BODY_SLAM", + "MOVE_DIG", + "MOVE_ENDURE", + "MOVE_FIRE_BLAST", + "MOVE_FIRE_SPIN", + "MOVE_FLARE_BLITZ", + "MOVE_FLASH_CANNON", + "MOVE_GIGA_IMPACT", + "MOVE_HEADBUTT", + "MOVE_HEAT_WAVE", + "MOVE_HYPER_BEAM", + "MOVE_IRON_HEAD", + "MOVE_OVERHEAT", + "MOVE_PROTECT", + "MOVE_ROAR", + "MOVE_ROCK_TOMB", + "MOVE_SELF_DESTRUCT", + "MOVE_STEALTH_ROCK", + "MOVE_STONE_EDGE", + "MOVE_SUBSTITUTE", + "MOVE_WILL_O_WISP", + "MOVE_ZEN_HEADBUTT" + ], + "TutorMoves": [ + "MOVE_ROCK_SLIDE" + ], + "EggMoves": [] + }, + "SWABLU": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_GROWL" + }, + { + "Level": "1", + "Move": "MOVE_PECK" + }, + { + "Level": "4", + "Move": "MOVE_DISARMING_VOICE" + }, + { + "Level": "8", + "Move": "MOVE_MIST" + }, + { + "Level": "20", + "Move": "MOVE_DRAGON_BREATH" + }, + { + "Level": "24", + "Move": "MOVE_SAFEGUARD" + }, + { + "Level": "32", + "Move": "MOVE_COTTON_GUARD" + }, + { + "Level": "35", + "Move": "MOVE_TWISTER" + }, + { + "Level": "37", + "Move": "MOVE_TAKE_DOWN" + }, + { + "Level": "40", + "Move": "MOVE_MOONBLAST" + }, + { + "Level": "44", + "Move": "MOVE_FEATHER_DANCE" + }, + { + "Level": "50", + "Move": "MOVE_BRAVE_BIRD" + }, + { + "Level": "55", + "Move": "MOVE_DRAGON_RUSH" + }, + { + "Level": "60", + "Move": "MOVE_PERISH_SONG" + } + ], + "TMMoves": [ + "MOVE_AERIAL_ACE", + "MOVE_AGILITY", + "MOVE_BODY_SLAM", + "MOVE_DAZZLING_GLEAM", + "MOVE_DRAGON_PULSE", + "MOVE_ENDURE", + "MOVE_FLY", + "MOVE_HEAT_WAVE", + "MOVE_HURRICANE", + "MOVE_HYPER_VOICE", + "MOVE_ICE_BEAM", + "MOVE_OUTRAGE", + "MOVE_PLAY_ROUGH", + "MOVE_PROTECT", + "MOVE_SOLAR_BEAM", + "MOVE_SUBSTITUTE", + "MOVE_SWIFT" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "ALTARIA": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_GROWL" + }, + { + "Level": "1", + "Move": "MOVE_PECK" + }, + { + "Level": "4", + "Move": "MOVE_DISARMING_VOICE" + }, + { + "Level": "8", + "Move": "MOVE_MIST" + }, + { + "Level": "20", + "Move": "MOVE_DRAGON_BREATH" + }, + { + "Level": "24", + "Move": "MOVE_SAFEGUARD" + }, + { + "Level": "32", + "Move": "MOVE_COTTON_GUARD" + }, + { + "Level": "35", + "Move": "MOVE_TWISTER" + }, + { + "Level": "37", + "Move": "MOVE_TAKE_DOWN" + }, + { + "Level": "40", + "Move": "MOVE_MOONBLAST" + }, + { + "Level": "44", + "Move": "MOVE_FEATHER_DANCE" + }, + { + "Level": "50", + "Move": "MOVE_BRAVE_BIRD" + }, + { + "Level": "55", + "Move": "MOVE_DRAGON_RUSH" + }, + { + "Level": "60", + "Move": "MOVE_PERISH_SONG" + } + ], + "TMMoves": [ + "MOVE_AERIAL_ACE", + "MOVE_AGILITY", + "MOVE_BODY_SLAM", + "MOVE_BULLDOZE", + "MOVE_DAZZLING_GLEAM", + "MOVE_DRACO_METEOR", + "MOVE_DRAGON_CLAW", + "MOVE_EARTHQUAKE", + "MOVE_ENDURE", + "MOVE_FIRE_SPIN", + "MOVE_FLAMETHROWER", + "MOVE_FLY", + "MOVE_GIGA_IMPACT", + "MOVE_HEAT_WAVE", + "MOVE_HURRICANE", + "MOVE_HYPER_BEAM", + "MOVE_HYPER_VOICE", + "MOVE_ICE_BEAM", + "MOVE_OUTRAGE", + "MOVE_PLAY_ROUGH", + "MOVE_PROTECT", + "MOVE_ROAR", + "MOVE_SOLAR_BEAM", + "MOVE_SUBSTITUTE", + "MOVE_SWIFT", + "MOVE_WILL_O_WISP" + ], + "TutorMoves": [ + "MOVE_DRAGON_PULSE" + ], + "EggMoves": [] + }, + "SHUPPET": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_SCREECH" + }, + { + "Level": "1", + "Move": "MOVE_LICK" + }, + { + "Level": "8", + "Move": "MOVE_CONFUSE_RAY" + }, + { + "Level": "12", + "Move": "MOVE_KNOCK_OFF" + }, + { + "Level": "16", + "Move": "MOVE_WILL_O_WISP" + }, + { + "Level": "19", + "Move": "MOVE_SHADOW_SNEAK" + }, + { + "Level": "23", + "Move": "MOVE_SHADOW_CLAW" + }, + { + "Level": "26", + "Move": "MOVE_CURSE" + }, + { + "Level": "30", + "Move": "MOVE_SHADOW_BALL" + }, + { + "Level": "34", + "Move": "MOVE_SWORDS_DANCE" + }, + { + "Level": "42", + "Move": "MOVE_PHANTOM_FORCE" + }, + { + "Level": "48", + "Move": "MOVE_GUNK_SHOT" + } + ], + "TMMoves": [ + "MOVE_BODY_SLAM", + "MOVE_CALM_MIND", + "MOVE_DARK_PULSE", + "MOVE_DAZZLING_GLEAM", + "MOVE_ENDURE", + "MOVE_HEADBUTT", + "MOVE_METRONOME", + "MOVE_NASTY_PLOT", + "MOVE_PROTECT", + "MOVE_PSYCHIC", + "MOVE_SUBSTITUTE", + "MOVE_TAUNT", + "MOVE_THUNDER", + "MOVE_THUNDERBOLT", + "MOVE_THUNDER_WAVE", + "MOVE_ZEN_HEADBUTT" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "BANETTE": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_SCREECH" + }, + { + "Level": "1", + "Move": "MOVE_LICK" + }, + { + "Level": "1", + "Move": "MOVE_SLASH" + }, + { + "Level": "8", + "Move": "MOVE_CONFUSE_RAY" + }, + { + "Level": "12", + "Move": "MOVE_KNOCK_OFF" + }, + { + "Level": "16", + "Move": "MOVE_WILL_O_WISP" + }, + { + "Level": "19", + "Move": "MOVE_SHADOW_SNEAK" + }, + { + "Level": "23", + "Move": "MOVE_SHADOW_CLAW" + }, + { + "Level": "26", + "Move": "MOVE_CURSE" + }, + { + "Level": "30", + "Move": "MOVE_SHADOW_BALL" + }, + { + "Level": "34", + "Move": "MOVE_SWORDS_DANCE" + }, + { + "Level": "42", + "Move": "MOVE_PHANTOM_FORCE" + }, + { + "Level": "48", + "Move": "MOVE_GUNK_SHOT" + } + ], + "TMMoves": [ + "MOVE_BODY_SLAM", + "MOVE_CALM_MIND", + "MOVE_DARK_PULSE", + "MOVE_DAZZLING_GLEAM", + "MOVE_ENDURE", + "MOVE_GIGA_IMPACT", + "MOVE_HEADBUTT", + "MOVE_HEAL_BLOCK", + "MOVE_HYPER_BEAM", + "MOVE_METRONOME", + "MOVE_NASTY_PLOT", + "MOVE_PROTECT", + "MOVE_PSYCHIC", + "MOVE_SUBSTITUTE", + "MOVE_TAUNT", + "MOVE_THUNDER", + "MOVE_THUNDERBOLT", + "MOVE_THUNDER_WAVE", + "MOVE_ZEN_HEADBUTT" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "ABSOL": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_LEER" + }, + { + "Level": "1", + "Move": "MOVE_QUICK_ATTACK" + }, + { + "Level": "10", + "Move": "MOVE_KNOCK_OFF" + }, + { + "Level": "15", + "Move": "MOVE_DETECT" + }, + { + "Level": "20", + "Move": "MOVE_SWORDS_DANCE" + }, + { + "Level": "23", + "Move": "MOVE_SLASH" + }, + { + "Level": "27", + "Move": "MOVE_NIGHT_SLASH" + }, + { + "Level": "32", + "Move": "MOVE_DOUBLE_TEAM" + }, + { + "Level": "36", + "Move": "MOVE_TAUNT" + }, + { + "Level": "40", + "Move": "MOVE_SHADOW_CLAW" + }, + { + "Level": "43", + "Move": "MOVE_FOCUS_ENERGY" + }, + { + "Level": "46", + "Move": "MOVE_AIR_SLASH" + }, + { + "Level": "48", + "Move": "MOVE_FUTURE_SIGHT" + }, + { + "Level": "54", + "Move": "MOVE_PERISH_SONG" + } + ], + "TMMoves": [ + "MOVE_AERIAL_ACE", + "MOVE_BLIZZARD", + "MOVE_BODY_SLAM", + "MOVE_CALM_MIND", + "MOVE_CLOSE_COMBAT", + "MOVE_DARK_PULSE", + "MOVE_DOUBLE_EDGE", + "MOVE_ENDURE", + "MOVE_FIRE_BLAST", + "MOVE_FLAMETHROWER", + "MOVE_GIGA_IMPACT", + "MOVE_HYPER_BEAM", + "MOVE_ICE_BEAM", + "MOVE_PLAY_ROUGH", + "MOVE_PROTECT", + "MOVE_ROCK_SLIDE", + "MOVE_ROCK_TOMB", + "MOVE_SHADOW_BALL", + "MOVE_STONE_EDGE", + "MOVE_SUBSTITUTE", + "MOVE_SWIFT", + "MOVE_THUNDER", + "MOVE_THUNDERBOLT", + "MOVE_THUNDER_WAVE", + "MOVE_WILL_O_WISP", + "MOVE_X_SCISSOR", + "MOVE_ZEN_HEADBUTT" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "SNORUNT": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_HEADBUTT" + }, + { + "Level": "1", + "Move": "MOVE_LEER" + }, + { + "Level": "1", + "Move": "MOVE_BITE" + }, + { + "Level": "10", + "Move": "MOVE_ICE_SHARD" + }, + { + "Level": "15", + "Move": "MOVE_PROTECT" + }, + { + "Level": "20", + "Move": "MOVE_ICY_WIND" + }, + { + "Level": "25", + "Move": "MOVE_FAKE_TEARS" + }, + { + "Level": "30", + "Move": "MOVE_ICE_FANG" + }, + { + "Level": "35", + "Move": "MOVE_DOUBLE_TEAM" + }, + { + "Level": "40", + "Move": "MOVE_ICICLE_CRASH" + }, + { + "Level": "45", + "Move": "MOVE_CRUNCH" + }, + { + "Level": "50", + "Move": "MOVE_BLIZZARD" + } + ], + "TMMoves": [ + "MOVE_BODY_SLAM", + "MOVE_ENDURE", + "MOVE_ICE_BEAM", + "MOVE_LIGHT_SCREEN", + "MOVE_SHADOW_BALL", + "MOVE_SPIKES", + "MOVE_SUBSTITUTE", + "MOVE_WATER_PULSE" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "GLALIE": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_HEADBUTT" + }, + { + "Level": "1", + "Move": "MOVE_LEER" + }, + { + "Level": "1", + "Move": "MOVE_BITE" + }, + { + "Level": "10", + "Move": "MOVE_ICE_SHARD" + }, + { + "Level": "15", + "Move": "MOVE_PROTECT" + }, + { + "Level": "20", + "Move": "MOVE_ICY_WIND" + }, + { + "Level": "25", + "Move": "MOVE_FAKE_TEARS" + }, + { + "Level": "30", + "Move": "MOVE_ICE_FANG" + }, + { + "Level": "35", + "Move": "MOVE_DOUBLE_TEAM" + }, + { + "Level": "40", + "Move": "MOVE_ICICLE_CRASH" + }, + { + "Level": "45", + "Move": "MOVE_CRUNCH" + }, + { + "Level": "50", + "Move": "MOVE_BLIZZARD" + }, + { + "Level": "55", + "Move": "MOVE_EXPLOSION" + } + ], + "TMMoves": [ + "MOVE_BODY_SLAM", + "MOVE_DARK_PULSE", + "MOVE_EARTHQUAKE", + "MOVE_ENDURE", + "MOVE_GIGA_IMPACT", + "MOVE_HYPER_BEAM", + "MOVE_ICE_BEAM", + "MOVE_IRON_HEAD", + "MOVE_LIGHT_SCREEN", + "MOVE_SELF_DESTRUCT", + "MOVE_SHADOW_BALL", + "MOVE_SPIKES", + "MOVE_SUBSTITUTE", + "MOVE_WATER_PULSE" + ], + "TutorMoves": [ + "MOVE_FREEZE_DRY" + ], + "EggMoves": [] + }, + "BAGON": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_LEER" + }, + { + "Level": "1", + "Move": "MOVE_BITE" + }, + { + "Level": "1", + "Move": "MOVE_EMBER" + }, + { + "Level": "10", + "Move": "MOVE_DRAGON_BREATH" + }, + { + "Level": "15", + "Move": "MOVE_HEADBUTT" + }, + { + "Level": "25", + "Move": "MOVE_CRUNCH" + }, + { + "Level": "30", + "Move": "MOVE_DRAGON_CLAW" + }, + { + "Level": "35", + "Move": "MOVE_ZEN_HEADBUTT" + }, + { + "Level": "40", + "Move": "MOVE_FOCUS_ENERGY" + }, + { + "Level": "45", + "Move": "MOVE_FLAMETHROWER" + }, + { + "Level": "50", + "Move": "MOVE_OUTRAGE" + }, + { + "Level": "55", + "Move": "MOVE_DOUBLE_EDGE" + } + ], + "TMMoves": [ + "MOVE_BODY_SLAM", + "MOVE_BRICK_BREAK", + "MOVE_DRACO_METEOR", + "MOVE_DRAGON_PULSE", + "MOVE_ENDURE", + "MOVE_FIRE_BLAST", + "MOVE_FIRE_FANG", + "MOVE_FIRE_SPIN", + "MOVE_HYDRO_PUMP", + "MOVE_HYPER_VOICE", + "MOVE_IRON_DEFENSE", + "MOVE_IRON_HEAD", + "MOVE_PROTECT", + "MOVE_ROAR", + "MOVE_ROCK_SLIDE", + "MOVE_ROCK_TOMB", + "MOVE_SHADOW_CLAW", + "MOVE_SUBSTITUTE", + "MOVE_THUNDER_FANG" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "SHELGON": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_LEER" + }, + { + "Level": "1", + "Move": "MOVE_BITE" + }, + { + "Level": "1", + "Move": "MOVE_EMBER" + }, + { + "Level": "10", + "Move": "MOVE_DRAGON_BREATH" + }, + { + "Level": "15", + "Move": "MOVE_HEADBUTT" + }, + { + "Level": "25", + "Move": "MOVE_CRUNCH" + }, + { + "Level": "30", + "Move": "MOVE_DRAGON_CLAW" + }, + { + "Level": "35", + "Move": "MOVE_ZEN_HEADBUTT" + }, + { + "Level": "40", + "Move": "MOVE_FOCUS_ENERGY" + }, + { + "Level": "45", + "Move": "MOVE_FLAMETHROWER" + }, + { + "Level": "50", + "Move": "MOVE_OUTRAGE" + }, + { + "Level": "55", + "Move": "MOVE_DOUBLE_EDGE" + } + ], + "TMMoves": [ + "MOVE_BODY_SLAM", + "MOVE_BRICK_BREAK", + "MOVE_DRACO_METEOR", + "MOVE_DRAGON_PULSE", + "MOVE_ENDURE", + "MOVE_FIRE_BLAST", + "MOVE_FIRE_FANG", + "MOVE_FIRE_SPIN", + "MOVE_HYDRO_PUMP", + "MOVE_HYPER_VOICE", + "MOVE_IRON_DEFENSE", + "MOVE_IRON_HEAD", + "MOVE_ROAR", + "MOVE_ROCK_SLIDE", + "MOVE_ROCK_TOMB", + "MOVE_SHADOW_CLAW", + "MOVE_SUBSTITUTE", + "MOVE_THUNDER_FANG" + ], + "TutorMoves": [ + "MOVE_PROTECT" + ], + "EggMoves": [] + }, + "SALAMENCE": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_LEER" + }, + { + "Level": "1", + "Move": "MOVE_BITE" + }, + { + "Level": "1", + "Move": "MOVE_EMBER" + }, + { + "Level": "1", + "Move": "MOVE_PROTECT" + }, + { + "Level": "10", + "Move": "MOVE_DRAGON_BREATH" + }, + { + "Level": "15", + "Move": "MOVE_HEADBUTT" + }, + { + "Level": "25", + "Move": "MOVE_CRUNCH" + }, + { + "Level": "30", + "Move": "MOVE_DRAGON_CLAW" + }, + { + "Level": "35", + "Move": "MOVE_ZEN_HEADBUTT" + }, + { + "Level": "40", + "Move": "MOVE_FOCUS_ENERGY" + }, + { + "Level": "45", + "Move": "MOVE_FLAMETHROWER" + }, + { + "Level": "50", + "Move": "MOVE_OUTRAGE" + }, + { + "Level": "55", + "Move": "MOVE_DOUBLE_EDGE" + }, + { + "Level": "60", + "Move": "MOVE_AIR_SLASH" + } + ], + "TMMoves": [ + "MOVE_AERIAL_ACE", + "MOVE_BODY_SLAM", + "MOVE_BRICK_BREAK", + "MOVE_DRACO_METEOR", + "MOVE_DRAGON_PULSE", + "MOVE_EARTHQUAKE", + "MOVE_ENDURE", + "MOVE_FIRE_BLAST", + "MOVE_FIRE_FANG", + "MOVE_FIRE_SPIN", + "MOVE_GIGA_IMPACT", + "MOVE_HURRICANE", + "MOVE_HYDRO_PUMP", + "MOVE_HYPER_BEAM", + "MOVE_HYPER_VOICE", + "MOVE_IRON_DEFENSE", + "MOVE_IRON_HEAD", + "MOVE_ROAR", + "MOVE_ROCK_SLIDE", + "MOVE_ROCK_TOMB", + "MOVE_SHADOW_CLAW", + "MOVE_STONE_EDGE", + "MOVE_SUBSTITUTE", + "MOVE_SWIFT", + "MOVE_THUNDER_FANG" + ], + "TutorMoves": [ + "MOVE_FLY" + ], + "EggMoves": [] + }, + "BELDUM": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + } + ], + "TMMoves": [ + "MOVE_AGILITY", + "MOVE_HEADBUTT", + "MOVE_IRON_DEFENSE", + "MOVE_IRON_HEAD", + "MOVE_ZEN_HEADBUTT" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "METANG": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_BULLET_PUNCH" + }, + { + "Level": "6", + "Move": "MOVE_ZEN_HEADBUTT" + }, + { + "Level": "18", + "Move": "MOVE_FLASH_CANNON" + }, + { + "Level": "26", + "Move": "MOVE_TAKE_DOWN" + }, + { + "Level": "34", + "Move": "MOVE_PSYCHO_CUT" + }, + { + "Level": "42", + "Move": "MOVE_PSYCHIC" + }, + { + "Level": "50", + "Move": "MOVE_IRON_HEAD" + }, + { + "Level": "54", + "Move": "MOVE_IRON_DEFENSE" + }, + { + "Level": "58", + "Move": "MOVE_HYPER_BEAM" + } + ], + "TMMoves": [ + "MOVE_AGILITY", + "MOVE_BODY_SLAM", + "MOVE_BRICK_BREAK", + "MOVE_DOUBLE_EDGE", + "MOVE_EARTHQUAKE", + "MOVE_ENDURE", + "MOVE_HEADBUTT", + "MOVE_ICE_PUNCH", + "MOVE_LIGHT_SCREEN", + "MOVE_POWER_UP_PUNCH", + "MOVE_PROTECT", + "MOVE_PSYSHOCK", + "MOVE_REFLECT", + "MOVE_ROCK_SLIDE", + "MOVE_ROCK_TOMB", + "MOVE_SELF_DESTRUCT", + "MOVE_SHADOW_BALL", + "MOVE_SLUDGE_BOMB", + "MOVE_STEALTH_ROCK", + "MOVE_SUBSTITUTE", + "MOVE_SWIFT", + "MOVE_THUNDER_PUNCH" + ], + "TutorMoves": [ + "MOVE_CONFUSION", + "MOVE_METAL_CLAW" + ], + "EggMoves": [] + }, + "METAGROSS": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_CONFUSION" + }, + { + "Level": "1", + "Move": "MOVE_METAL_CLAW" + }, + { + "Level": "1", + "Move": "MOVE_BULLET_PUNCH" + }, + { + "Level": "6", + "Move": "MOVE_ZEN_HEADBUTT" + }, + { + "Level": "18", + "Move": "MOVE_FLASH_CANNON" + }, + { + "Level": "26", + "Move": "MOVE_TAKE_DOWN" + }, + { + "Level": "34", + "Move": "MOVE_PSYCHO_CUT" + }, + { + "Level": "42", + "Move": "MOVE_PSYCHIC" + }, + { + "Level": "46", + "Move": "MOVE_BRUTAL_SWING" + }, + { + "Level": "50", + "Move": "MOVE_IRON_HEAD" + }, + { + "Level": "54", + "Move": "MOVE_IRON_DEFENSE" + }, + { + "Level": "58", + "Move": "MOVE_HYPER_BEAM" + } + ], + "TMMoves": [ + "MOVE_AGILITY", + "MOVE_BODY_SLAM", + "MOVE_BRICK_BREAK", + "MOVE_DOUBLE_EDGE", + "MOVE_EARTHQUAKE", + "MOVE_ENDURE", + "MOVE_GIGA_IMPACT", + "MOVE_HEADBUTT", + "MOVE_ICE_PUNCH", + "MOVE_KNOCK_OFF", + "MOVE_LIGHT_SCREEN", + "MOVE_POWER_UP_PUNCH", + "MOVE_PROTECT", + "MOVE_PSYSHOCK", + "MOVE_REFLECT", + "MOVE_ROCK_SLIDE", + "MOVE_ROCK_TOMB", + "MOVE_SELF_DESTRUCT", + "MOVE_SHADOW_BALL", + "MOVE_SLUDGE_BOMB", + "MOVE_STEALTH_ROCK", + "MOVE_STONE_EDGE", + "MOVE_SUBSTITUTE", + "MOVE_SWIFT", + "MOVE_THUNDER_PUNCH" + ], + "TutorMoves": [ + "MOVE_EXPLOSION", + "MOVE_HEAVY_SLAM" + ], + "EggMoves": [] + }, + "BUDEW": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_ABSORB" + }, + { + "Level": "1", + "Move": "MOVE_GROWTH" + }, + { + "Level": "1", + "Move": "MOVE_STUN_SPORE" + }, + { + "Level": "1", + "Move": "MOVE_CHARM" + } + ], + "TMMoves": [ + "MOVE_BODY_SLAM", + "MOVE_BULLET_SEED", + "MOVE_DAZZLING_GLEAM", + "MOVE_ENDURE", + "MOVE_ENERGY_BALL", + "MOVE_MUD_SHOT", + "MOVE_PROTECT", + "MOVE_SHADOW_BALL", + "MOVE_SLUDGE_BOMB", + "MOVE_SOLAR_BEAM", + "MOVE_SPIKES", + "MOVE_SUBSTITUTE", + "MOVE_SWIFT", + "MOVE_SWORDS_DANCE" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "ROSERADE": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_ABSORB" + }, + { + "Level": "1", + "Move": "MOVE_GROWTH" + }, + { + "Level": "1", + "Move": "MOVE_STUN_SPORE" + }, + { + "Level": "1", + "Move": "MOVE_CHARM" + }, + { + "Level": "5", + "Move": "MOVE_RAZOR_LEAF" + }, + { + "Level": "8", + "Move": "MOVE_PIN_MISSILE" + }, + { + "Level": "10", + "Move": "MOVE_LEECH_SEED" + }, + { + "Level": "15", + "Move": "MOVE_MAGICAL_LEAF" + }, + { + "Level": "18", + "Move": "MOVE_SLEEP_POWDER" + }, + { + "Level": "22", + "Move": "MOVE_TOXIC_SPIKES" + }, + { + "Level": "30", + "Move": "MOVE_GIGA_DRAIN" + }, + { + "Level": "34", + "Move": "MOVE_POISON_JAB" + }, + { + "Level": "37", + "Move": "MOVE_SYNTHESIS" + }, + { + "Level": "44", + "Move": "MOVE_TOXIC" + }, + { + "Level": "55", + "Move": "MOVE_LEAF_STORM" + } + ], + "TMMoves": [ + "MOVE_BODY_SLAM", + "MOVE_BULLET_SEED", + "MOVE_DAZZLING_GLEAM", + "MOVE_ENDURE", + "MOVE_ENERGY_BALL", + "MOVE_GIGA_IMPACT", + "MOVE_HYPER_BEAM", + "MOVE_MUD_SHOT", + "MOVE_PROTECT", + "MOVE_SHADOW_BALL", + "MOVE_SLUDGE_BOMB", + "MOVE_SOLAR_BEAM", + "MOVE_SPIKES", + "MOVE_SUBSTITUTE", + "MOVE_SWIFT", + "MOVE_SWORDS_DANCE" + ], + "TutorMoves": [ + "MOVE_POISON_STING" + ], + "EggMoves": [] + }, + "BUNEARY": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_SPLASH" + }, + { + "Level": "14", + "Move": "MOVE_DRAINING_KISS" + }, + { + "Level": "16", + "Move": "MOVE_QUICK_ATTACK" + }, + { + "Level": "20", + "Move": "MOVE_AGILITY" + }, + { + "Level": "24", + "Move": "MOVE_CHARM" + }, + { + "Level": "28", + "Move": "MOVE_BRUTAL_SWING" + }, + { + "Level": "32", + "Move": "MOVE_HEADBUTT" + }, + { + "Level": "42", + "Move": "MOVE_COTTON_GUARD" + }, + { + "Level": "48", + "Move": "MOVE_BOUNCE" + }, + { + "Level": "52", + "Move": "MOVE_DYNAMIC_PUNCH" + } + ], + "TMMoves": [ + "MOVE_CLOSE_COMBAT", + "MOVE_DIG", + "MOVE_ENDURE", + "MOVE_FIRE_PUNCH", + "MOVE_HYPER_VOICE", + "MOVE_ICE_BEAM", + "MOVE_ICE_PUNCH", + "MOVE_IRON_TAIL", + "MOVE_PLAY_ROUGH", + "MOVE_POWER_UP_PUNCH", + "MOVE_PROTECT", + "MOVE_SHADOW_BALL", + "MOVE_SOLAR_BEAM", + "MOVE_SUBSTITUTE", + "MOVE_SWIFT", + "MOVE_THUNDERBOLT", + "MOVE_THUNDER_PUNCH", + "MOVE_THUNDER_WAVE", + "MOVE_WORK_UP" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "LOPUNNY": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_SPLASH" + }, + { + "Level": "6", + "Move": "MOVE_POWER_UP_PUNCH" + }, + { + "Level": "9", + "Move": "MOVE_MACH_PUNCH" + }, + { + "Level": "12", + "Move": "MOVE_DOUBLE_TEAM" + }, + { + "Level": "14", + "Move": "MOVE_DRAINING_KISS" + }, + { + "Level": "16", + "Move": "MOVE_QUICK_ATTACK" + }, + { + "Level": "20", + "Move": "MOVE_AGILITY" + }, + { + "Level": "24", + "Move": "MOVE_CHARM" + }, + { + "Level": "28", + "Move": "MOVE_BRUTAL_SWING" + }, + { + "Level": "32", + "Move": "MOVE_HEADBUTT" + }, + { + "Level": "36", + "Move": "MOVE_IRON_TAIL" + }, + { + "Level": "42", + "Move": "MOVE_COTTON_GUARD" + }, + { + "Level": "48", + "Move": "MOVE_BOUNCE" + }, + { + "Level": "52", + "Move": "MOVE_DYNAMIC_PUNCH" + } + ], + "TMMoves": [ + "MOVE_BLIZZARD", + "MOVE_CLOSE_COMBAT", + "MOVE_DIG", + "MOVE_ENDURE", + "MOVE_FIRE_PUNCH", + "MOVE_FOCUS_BLAST", + "MOVE_GIGA_IMPACT", + "MOVE_HYPER_BEAM", + "MOVE_HYPER_VOICE", + "MOVE_ICE_BEAM", + "MOVE_ICE_PUNCH", + "MOVE_PLAY_ROUGH", + "MOVE_PROTECT", + "MOVE_SHADOW_BALL", + "MOVE_SOLAR_BEAM", + "MOVE_SUBSTITUTE", + "MOVE_SWIFT", + "MOVE_SWORDS_DANCE", + "MOVE_THUNDER", + "MOVE_THUNDERBOLT", + "MOVE_THUNDER_PUNCH", + "MOVE_THUNDER_WAVE", + "MOVE_U_TURN", + "MOVE_WORK_UP" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "GIBLE": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_SAND_TOMB" + }, + { + "Level": "12", + "Move": "MOVE_DRAGON_BREATH" + }, + { + "Level": "18", + "Move": "MOVE_BULLDOZE" + }, + { + "Level": "25", + "Move": "MOVE_BITE" + }, + { + "Level": "30", + "Move": "MOVE_SLASH" + }, + { + "Level": "36", + "Move": "MOVE_DRAGON_CLAW" + }, + { + "Level": "42", + "Move": "MOVE_DIG" + }, + { + "Level": "54", + "Move": "MOVE_TAKE_DOWN" + }, + { + "Level": "60", + "Move": "MOVE_DRAGON_RUSH" + } + ], + "TMMoves": [ + "MOVE_BODY_SLAM", + "MOVE_DRACO_METEOR", + "MOVE_DRAGON_PULSE", + "MOVE_EARTHQUAKE", + "MOVE_EARTH_POWER", + "MOVE_ENDURE", + "MOVE_FIRE_BLAST", + "MOVE_FIRE_FANG", + "MOVE_FLAMETHROWER", + "MOVE_IRON_HEAD", + "MOVE_OUTRAGE", + "MOVE_PROTECT", + "MOVE_ROCK_SLIDE", + "MOVE_ROCK_TOMB", + "MOVE_SHADOW_CLAW", + "MOVE_STEALTH_ROCK", + "MOVE_STONE_EDGE", + "MOVE_SUBSTITUTE", + "MOVE_SWIFT", + "MOVE_SWORDS_DANCE", + "MOVE_THUNDER_FANG" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "GABITE": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_SAND_TOMB" + }, + { + "Level": "12", + "Move": "MOVE_DRAGON_BREATH" + }, + { + "Level": "18", + "Move": "MOVE_BULLDOZE" + }, + { + "Level": "25", + "Move": "MOVE_BITE" + }, + { + "Level": "30", + "Move": "MOVE_SLASH" + }, + { + "Level": "36", + "Move": "MOVE_DRAGON_CLAW" + }, + { + "Level": "42", + "Move": "MOVE_DIG" + }, + { + "Level": "54", + "Move": "MOVE_TAKE_DOWN" + }, + { + "Level": "60", + "Move": "MOVE_DRAGON_RUSH" + } + ], + "TMMoves": [ + "MOVE_AERIAL_ACE", + "MOVE_BODY_SLAM", + "MOVE_BRICK_BREAK", + "MOVE_CRUNCH", + "MOVE_DRACO_METEOR", + "MOVE_DRAGON_PULSE", + "MOVE_EARTHQUAKE", + "MOVE_EARTH_POWER", + "MOVE_ENDURE", + "MOVE_FIRE_BLAST", + "MOVE_FIRE_FANG", + "MOVE_FLAMETHROWER", + "MOVE_IRON_HEAD", + "MOVE_OUTRAGE", + "MOVE_POISON_JAB", + "MOVE_PROTECT", + "MOVE_ROCK_SLIDE", + "MOVE_ROCK_TOMB", + "MOVE_SHADOW_CLAW", + "MOVE_SPIKES", + "MOVE_STEALTH_ROCK", + "MOVE_STONE_EDGE", + "MOVE_SUBSTITUTE", + "MOVE_SWIFT", + "MOVE_SWORDS_DANCE", + "MOVE_THUNDER_FANG" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "GARCHOMP": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_SAND_TOMB" + }, + { + "Level": "12", + "Move": "MOVE_DRAGON_BREATH" + }, + { + "Level": "18", + "Move": "MOVE_BULLDOZE" + }, + { + "Level": "25", + "Move": "MOVE_BITE" + }, + { + "Level": "30", + "Move": "MOVE_SLASH" + }, + { + "Level": "36", + "Move": "MOVE_DRAGON_CLAW" + }, + { + "Level": "42", + "Move": "MOVE_DIG" + }, + { + "Level": "54", + "Move": "MOVE_TAKE_DOWN" + }, + { + "Level": "60", + "Move": "MOVE_DRAGON_RUSH" + } + ], + "TMMoves": [ + "MOVE_AERIAL_ACE", + "MOVE_BODY_SLAM", + "MOVE_BRICK_BREAK", + "MOVE_DRACO_METEOR", + "MOVE_DRAGON_PULSE", + "MOVE_EARTHQUAKE", + "MOVE_EARTH_POWER", + "MOVE_ENDURE", + "MOVE_FIRE_BLAST", + "MOVE_FIRE_FANG", + "MOVE_FLAMETHROWER", + "MOVE_GIGA_IMPACT", + "MOVE_HYPER_BEAM", + "MOVE_IRON_HEAD", + "MOVE_IRON_TAIL", + "MOVE_LIQUIDATION", + "MOVE_OUTRAGE", + "MOVE_POISON_JAB", + "MOVE_PROTECT", + "MOVE_ROCK_SLIDE", + "MOVE_ROCK_TOMB", + "MOVE_SHADOW_CLAW", + "MOVE_SPIKES", + "MOVE_STEALTH_ROCK", + "MOVE_STONE_EDGE", + "MOVE_SUBSTITUTE", + "MOVE_SURF", + "MOVE_SWIFT", + "MOVE_SWORDS_DANCE", + "MOVE_THUNDER_FANG" + ], + "TutorMoves": [ + "MOVE_CRUNCH" + ], + "EggMoves": [] + }, + "RIOLU": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_QUICK_ATTACK" + }, + { + "Level": "1", + "Move": "MOVE_ENDURE" + }, + { + "Level": "1", + "Move": "MOVE_BULLET_PUNCH" + }, + { + "Level": "8", + "Move": "MOVE_METAL_CLAW" + }, + { + "Level": "16", + "Move": "MOVE_WORK_UP" + }, + { + "Level": "20", + "Move": "MOVE_ROCK_SMASH" + }, + { + "Level": "24", + "Move": "MOVE_SCREECH" + }, + { + "Level": "24", + "Move": "MOVE_DETECT" + }, + { + "Level": "28", + "Move": "MOVE_BULLDOZE" + }, + { + "Level": "35", + "Move": "MOVE_SWORDS_DANCE" + } + ], + "TMMoves": [ + "MOVE_AERIAL_ACE", + "MOVE_AGILITY", + "MOVE_BRICK_BREAK", + "MOVE_BULK_UP", + "MOVE_CLOSE_COMBAT", + "MOVE_CRUNCH", + "MOVE_DIG", + "MOVE_EARTHQUAKE", + "MOVE_FOCUS_BLAST", + "MOVE_ICE_PUNCH", + "MOVE_NASTY_PLOT", + "MOVE_POISON_JAB", + "MOVE_PROTECT", + "MOVE_ROCK_SLIDE", + "MOVE_ROCK_TOMB", + "MOVE_SHADOW_CLAW", + "MOVE_SUBSTITUTE", + "MOVE_SWIFT", + "MOVE_THUNDER_PUNCH", + "MOVE_ZEN_HEADBUTT" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "LUCARIO": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_QUICK_ATTACK" + }, + { + "Level": "1", + "Move": "MOVE_PROTECT" + }, + { + "Level": "1", + "Move": "MOVE_ENDURE" + }, + { + "Level": "1", + "Move": "MOVE_BULLET_PUNCH" + }, + { + "Level": "8", + "Move": "MOVE_METAL_CLAW" + }, + { + "Level": "16", + "Move": "MOVE_WORK_UP" + }, + { + "Level": "20", + "Move": "MOVE_ROCK_SMASH" + }, + { + "Level": "24", + "Move": "MOVE_SCREECH" + }, + { + "Level": "25", + "Move": "MOVE_AURA_SPHERE" + }, + { + "Level": "28", + "Move": "MOVE_BULLDOZE" + }, + { + "Level": "32", + "Move": "MOVE_METAL_SOUND" + }, + { + "Level": "35", + "Move": "MOVE_SWORDS_DANCE" + }, + { + "Level": "38", + "Move": "MOVE_DRAGON_PULSE" + }, + { + "Level": "45", + "Move": "MOVE_EXTREME_SPEED" + }, + { + "Level": "54", + "Move": "MOVE_CLOSE_COMBAT" + } + ], + "TMMoves": [ + "MOVE_AERIAL_ACE", + "MOVE_AGILITY", + "MOVE_BRICK_BREAK", + "MOVE_BULK_UP", + "MOVE_CALM_MIND", + "MOVE_CRUNCH", + "MOVE_DARK_PULSE", + "MOVE_DIG", + "MOVE_EARTHQUAKE", + "MOVE_FLASH_CANNON", + "MOVE_FOCUS_BLAST", + "MOVE_GIGA_IMPACT", + "MOVE_HYPER_BEAM", + "MOVE_ICE_PUNCH", + "MOVE_IRON_DEFENSE", + "MOVE_IRON_TAIL", + "MOVE_METRONOME", + "MOVE_NASTY_PLOT", + "MOVE_POISON_JAB", + "MOVE_POWER_UP_PUNCH", + "MOVE_PSYCHIC", + "MOVE_ROAR", + "MOVE_ROCK_SLIDE", + "MOVE_ROCK_TOMB", + "MOVE_SHADOW_BALL", + "MOVE_SHADOW_CLAW", + "MOVE_STONE_EDGE", + "MOVE_SUBSTITUTE", + "MOVE_SWIFT", + "MOVE_THUNDER_PUNCH", + "MOVE_WATER_PULSE", + "MOVE_ZEN_HEADBUTT" + ], + "TutorMoves": [ + "MOVE_DETECT" + ], + "EggMoves": [] + }, + "HIPPOPOTAS": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "4", + "Move": "MOVE_BITE" + }, + { + "Level": "8", + "Move": "MOVE_CURSE" + }, + { + "Level": "12", + "Move": "MOVE_SAND_TOMB" + }, + { + "Level": "16", + "Move": "MOVE_DIG" + }, + { + "Level": "20", + "Move": "MOVE_CRUNCH" + }, + { + "Level": "24", + "Move": "MOVE_AMNESIA" + }, + { + "Level": "28", + "Move": "MOVE_TAKE_DOWN" + }, + { + "Level": "32", + "Move": "MOVE_ROAR" + }, + { + "Level": "40", + "Move": "MOVE_EARTHQUAKE" + }, + { + "Level": "44", + "Move": "MOVE_DOUBLE_EDGE" + } + ], + "TMMoves": [ + "MOVE_BODY_SLAM", + "MOVE_EARTH_POWER", + "MOVE_ENDURE", + "MOVE_FIRE_FANG", + "MOVE_ICE_FANG", + "MOVE_PROTECT", + "MOVE_ROCK_SLIDE", + "MOVE_ROCK_TOMB", + "MOVE_STEALTH_ROCK", + "MOVE_STONE_EDGE", + "MOVE_SUBSTITUTE", + "MOVE_THUNDER_FANG", + "MOVE_WHIRLWIND" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "HIPPOWDON": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_BITE" + }, + { + "Level": "12", + "Move": "MOVE_SAND_TOMB" + }, + { + "Level": "16", + "Move": "MOVE_DIG" + }, + { + "Level": "20", + "Move": "MOVE_CRUNCH" + }, + { + "Level": "24", + "Move": "MOVE_AMNESIA" + }, + { + "Level": "28", + "Move": "MOVE_TAKE_DOWN" + }, + { + "Level": "32", + "Move": "MOVE_ROAR" + }, + { + "Level": "36", + "Move": "MOVE_HEAVY_SLAM" + }, + { + "Level": "40", + "Move": "MOVE_EARTHQUAKE" + }, + { + "Level": "44", + "Move": "MOVE_DOUBLE_EDGE" + } + ], + "TMMoves": [ + "MOVE_BODY_SLAM", + "MOVE_CURSE", + "MOVE_EARTH_POWER", + "MOVE_ENDURE", + "MOVE_FIRE_FANG", + "MOVE_GIGA_IMPACT", + "MOVE_HYPER_BEAM", + "MOVE_HYPER_VOICE", + "MOVE_ICE_FANG", + "MOVE_IRON_HEAD", + "MOVE_PROTECT", + "MOVE_ROCK_SLIDE", + "MOVE_ROCK_TOMB", + "MOVE_STEALTH_ROCK", + "MOVE_STONE_EDGE", + "MOVE_SUBSTITUTE", + "MOVE_THUNDER_FANG", + "MOVE_WHIRLWIND" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "SNOVER": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_LEER" + }, + { + "Level": "1", + "Move": "MOVE_LEAFAGE" + }, + { + "Level": "10", + "Move": "MOVE_MIST" + }, + { + "Level": "15", + "Move": "MOVE_ICE_SHARD" + }, + { + "Level": "20", + "Move": "MOVE_RAZOR_LEAF" + }, + { + "Level": "25", + "Move": "MOVE_ICY_WIND" + }, + { + "Level": "30", + "Move": "MOVE_GROWTH" + }, + { + "Level": "35", + "Move": "MOVE_LEECH_SEED" + }, + { + "Level": "41", + "Move": "MOVE_WOOD_HAMMER" + }, + { + "Level": "45", + "Move": "MOVE_BLIZZARD" + }, + { + "Level": "53", + "Move": "MOVE_LEAF_STORM" + } + ], + "TMMoves": [ + "MOVE_BODY_SLAM", + "MOVE_BULLET_SEED", + "MOVE_ENDURE", + "MOVE_ENERGY_BALL", + "MOVE_GIGA_DRAIN", + "MOVE_ICE_BEAM", + "MOVE_ICE_PUNCH", + "MOVE_MAGICAL_LEAF", + "MOVE_PROTECT", + "MOVE_SOLAR_BEAM", + "MOVE_SUBSTITUTE", + "MOVE_SWORDS_DANCE", + "MOVE_WATER_PULSE" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "ABOMASNOW": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_LEER" + }, + { + "Level": "1", + "Move": "MOVE_LEAFAGE" + }, + { + "Level": "10", + "Move": "MOVE_MIST" + }, + { + "Level": "15", + "Move": "MOVE_ICE_SHARD" + }, + { + "Level": "20", + "Move": "MOVE_RAZOR_LEAF" + }, + { + "Level": "25", + "Move": "MOVE_ICY_WIND" + }, + { + "Level": "30", + "Move": "MOVE_GROWTH" + }, + { + "Level": "35", + "Move": "MOVE_LEECH_SEED" + }, + { + "Level": "41", + "Move": "MOVE_WOOD_HAMMER" + }, + { + "Level": "45", + "Move": "MOVE_BLIZZARD" + }, + { + "Level": "53", + "Move": "MOVE_LEAF_STORM" + } + ], + "TMMoves": [ + "MOVE_BODY_SLAM", + "MOVE_BRICK_BREAK", + "MOVE_BULLET_SEED", + "MOVE_CURSE", + "MOVE_DOUBLE_EDGE", + "MOVE_EARTHQUAKE", + "MOVE_EARTH_POWER", + "MOVE_ENDURE", + "MOVE_ENERGY_BALL", + "MOVE_FOCUS_BLAST", + "MOVE_GIGA_DRAIN", + "MOVE_GIGA_IMPACT", + "MOVE_HYPER_BEAM", + "MOVE_ICE_BEAM", + "MOVE_MAGICAL_LEAF", + "MOVE_OUTRAGE", + "MOVE_PROTECT", + "MOVE_ROCK_SLIDE", + "MOVE_ROCK_TOMB", + "MOVE_SOLAR_BEAM", + "MOVE_SUBSTITUTE", + "MOVE_SWORDS_DANCE", + "MOVE_WATER_PULSE" + ], + "TutorMoves": [ + "MOVE_ICE_PUNCH" + ], + "EggMoves": [] + }, + "LEAFEON": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_TAIL_WHIP" + }, + { + "Level": "1", + "Move": "MOVE_BITE" + }, + { + "Level": "1", + "Move": "MOVE_GROWL" + }, + { + "Level": "10", + "Move": "MOVE_QUICK_ATTACK" + }, + { + "Level": "15", + "Move": "MOVE_DISARMING_VOICE" + }, + { + "Level": "20", + "Move": "MOVE_LEECH_SEED" + }, + { + "Level": "25", + "Move": "MOVE_MAGICAL_LEAF" + }, + { + "Level": "30", + "Move": "MOVE_SYNTHESIS" + }, + { + "Level": "35", + "Move": "MOVE_LEAF_BLADE" + }, + { + "Level": "40", + "Move": "MOVE_GIGA_DRAIN" + }, + { + "Level": "45", + "Move": "MOVE_SWORDS_DANCE" + }, + { + "Level": "50", + "Move": "MOVE_LEAF_STORM" + } + ], + "TMMoves": [ + "MOVE_AERIAL_ACE", + "MOVE_BODY_SLAM", + "MOVE_BULLET_SEED", + "MOVE_CALM_MIND", + "MOVE_DIG", + "MOVE_ENDURE", + "MOVE_ENERGY_BALL", + "MOVE_GIGA_IMPACT", + "MOVE_HYPER_BEAM", + "MOVE_HYPER_VOICE", + "MOVE_IRON_TAIL", + "MOVE_PROTECT", + "MOVE_ROAR", + "MOVE_SHADOW_BALL", + "MOVE_SOLAR_BEAM", + "MOVE_SUBSTITUTE", + "MOVE_TAUNT", + "MOVE_X_SCISSOR" + ], + "TutorMoves": [ + "MOVE_CHARM", + "MOVE_DOUBLE_EDGE", + "MOVE_RAZOR_LEAF", + "MOVE_SWIFT", + "MOVE_TAKE_DOWN", + "MOVE_WISH" + ], + "EggMoves": [] + }, + "GLACEON": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_TAIL_WHIP" + }, + { + "Level": "1", + "Move": "MOVE_BITE" + }, + { + "Level": "1", + "Move": "MOVE_GROWL" + }, + { + "Level": "10", + "Move": "MOVE_QUICK_ATTACK" + }, + { + "Level": "15", + "Move": "MOVE_DISARMING_VOICE" + }, + { + "Level": "18", + "Move": "MOVE_MIST" + }, + { + "Level": "23", + "Move": "MOVE_ICE_SHARD" + }, + { + "Level": "27", + "Move": "MOVE_ICE_FANG" + }, + { + "Level": "36", + "Move": "MOVE_ICE_BEAM" + }, + { + "Level": "40", + "Move": "MOVE_FREEZE_DRY" + }, + { + "Level": "50", + "Move": "MOVE_BLIZZARD" + } + ], + "TMMoves": [ + "MOVE_BODY_SLAM", + "MOVE_CALM_MIND", + "MOVE_DIG", + "MOVE_ENDURE", + "MOVE_GIGA_IMPACT", + "MOVE_HYPER_BEAM", + "MOVE_HYPER_VOICE", + "MOVE_IRON_TAIL", + "MOVE_PROTECT", + "MOVE_ROAR", + "MOVE_SHADOW_BALL", + "MOVE_SUBSTITUTE", + "MOVE_TAUNT" + ], + "TutorMoves": [ + "MOVE_CHARM", + "MOVE_DOUBLE_EDGE", + "MOVE_ICY_WIND", + "MOVE_SWIFT", + "MOVE_TAKE_DOWN", + "MOVE_WISH" + ], + "EggMoves": [] + }, + "GALLADE": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_GROWL" + }, + { + "Level": "1", + "Move": "MOVE_PSYBEAM" + }, + { + "Level": "1", + "Move": "MOVE_HYPNOSIS" + }, + { + "Level": "1", + "Move": "MOVE_DISARMING_VOICE" + }, + { + "Level": "6", + "Move": "MOVE_CONFUSION" + }, + { + "Level": "15", + "Move": "MOVE_TELEPORT" + }, + { + "Level": "18", + "Move": "MOVE_AERIAL_ACE" + }, + { + "Level": "28", + "Move": "MOVE_PROTECT" + }, + { + "Level": "30", + "Move": "MOVE_DOUBLE_TEAM" + }, + { + "Level": "35", + "Move": "MOVE_SWORDS_DANCE" + }, + { + "Level": "42", + "Move": "MOVE_PSYCHO_CUT" + }, + { + "Level": "50", + "Move": "MOVE_LEAF_BLADE" + }, + { + "Level": "58", + "Move": "MOVE_CLOSE_COMBAT" + } + ], + "TMMoves": [ + "MOVE_AGILITY", + "MOVE_AURA_SPHERE", + "MOVE_BODY_SLAM", + "MOVE_BRICK_BREAK", + "MOVE_BULK_UP", + "MOVE_DAZZLING_GLEAM", + "MOVE_EARTHQUAKE", + "MOVE_ENDURE", + "MOVE_ENERGY_BALL", + "MOVE_FIRE_PUNCH", + "MOVE_GIGA_IMPACT", + "MOVE_HYPER_BEAM", + "MOVE_HYPER_VOICE", + "MOVE_ICE_PUNCH", + "MOVE_ICY_WIND", + "MOVE_KNOCK_OFF", + "MOVE_LIGHT_SCREEN", + "MOVE_METRONOME", + "MOVE_PSYSHOCK", + "MOVE_REFLECT", + "MOVE_ROCK_TOMB", + "MOVE_SAFEGUARD", + "MOVE_SHADOW_BALL", + "MOVE_SHADOW_CLAW", + "MOVE_STONE_EDGE", + "MOVE_SUBSTITUTE", + "MOVE_SWIFT", + "MOVE_TAUNT", + "MOVE_THUNDERBOLT", + "MOVE_THUNDER_PUNCH", + "MOVE_THUNDER_WAVE", + "MOVE_WILL_O_WISP", + "MOVE_X_SCISSOR", + "MOVE_ZEN_HEADBUTT" + ], + "TutorMoves": [ + "MOVE_CALM_MIND", + "MOVE_CHARM", + "MOVE_CONFUSE_RAY", + "MOVE_DRAINING_KISS", + "MOVE_FUTURE_SIGHT", + "MOVE_MAGICAL_LEAF", + "MOVE_MYSTICAL_FIRE", + "MOVE_NIGHT_SLASH", + "MOVE_PSYCHIC", + "MOVE_SLASH" + ], + "EggMoves": [] + }, + "FROSLASS": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_HEADBUTT" + }, + { + "Level": "1", + "Move": "MOVE_LEER" + }, + { + "Level": "1", + "Move": "MOVE_BITE" + }, + { + "Level": "1", + "Move": "MOVE_DOUBLE_TEAM" + }, + { + "Level": "10", + "Move": "MOVE_ICE_SHARD" + }, + { + "Level": "15", + "Move": "MOVE_CONFUSE_RAY" + }, + { + "Level": "20", + "Move": "MOVE_ICY_WIND" + }, + { + "Level": "25", + "Move": "MOVE_FAKE_TEARS" + }, + { + "Level": "30", + "Move": "MOVE_HAZE" + }, + { + "Level": "35", + "Move": "MOVE_ICE_BEAM" + }, + { + "Level": "40", + "Move": "MOVE_SHADOW_BALL" + }, + { + "Level": "45", + "Move": "MOVE_WILL_O_WISP" + }, + { + "Level": "50", + "Move": "MOVE_BLIZZARD" + }, + { + "Level": "55", + "Move": "MOVE_PHANTOM_FORCE" + }, + { + "Level": "60", + "Move": "MOVE_CURSE" + } + ], + "TMMoves": [ + "MOVE_BODY_SLAM", + "MOVE_ENDURE", + "MOVE_GIGA_IMPACT", + "MOVE_HEAL_BLOCK", + "MOVE_HYPER_BEAM", + "MOVE_ICE_PUNCH", + "MOVE_LIGHT_SCREEN", + "MOVE_NASTY_PLOT", + "MOVE_PSYCHIC", + "MOVE_REFLECT", + "MOVE_SPIKES", + "MOVE_SUBSTITUTE", + "MOVE_TAUNT", + "MOVE_THUNDER", + "MOVE_THUNDERBOLT", + "MOVE_THUNDER_WAVE", + "MOVE_WATER_PULSE" + ], + "TutorMoves": [ + "MOVE_CRUNCH", + "MOVE_DRAINING_KISS", + "MOVE_ICE_FANG", + "MOVE_ICICLE_CRASH", + "MOVE_PROTECT" + ], + "EggMoves": [] + }, + "TEPIG": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_TAIL_WHIP" + }, + { + "Level": "6", + "Move": "MOVE_EMBER" + }, + { + "Level": "10", + "Move": "MOVE_ROLLOUT" + }, + { + "Level": "13", + "Move": "MOVE_SMOKESCREEN" + }, + { + "Level": "15", + "Move": "MOVE_FLAME_WHEEL" + }, + { + "Level": "20", + "Move": "MOVE_FIRE_SPIN" + }, + { + "Level": "24", + "Move": "MOVE_FOCUS_ENERGY" + }, + { + "Level": "29", + "Move": "MOVE_FLAMETHROWER" + }, + { + "Level": "32", + "Move": "MOVE_TAKE_DOWN" + }, + { + "Level": "50", + "Move": "MOVE_FLARE_BLITZ" + }, + { + "Level": "56", + "Move": "MOVE_HEAD_SMASH" + } + ], + "TMMoves": [ + "MOVE_DIG", + "MOVE_DOUBLE_TEAM", + "MOVE_ENDURE", + "MOVE_FIRE_BLAST", + "MOVE_HEADBUTT", + "MOVE_HEAT_WAVE", + "MOVE_OVERHEAT", + "MOVE_PROTECT", + "MOVE_ROAR", + "MOVE_SUBSTITUTE", + "MOVE_TAUNT", + "MOVE_WILD_CHARGE", + "MOVE_WILL_O_WISP", + "MOVE_WORK_UP" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "PIGNITE": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_TAIL_WHIP" + }, + { + "Level": "6", + "Move": "MOVE_EMBER" + }, + { + "Level": "10", + "Move": "MOVE_ROLLOUT" + }, + { + "Level": "13", + "Move": "MOVE_SMOKESCREEN" + }, + { + "Level": "15", + "Move": "MOVE_FLAME_WHEEL" + }, + { + "Level": "20", + "Move": "MOVE_FIRE_SPIN" + }, + { + "Level": "24", + "Move": "MOVE_FOCUS_ENERGY" + }, + { + "Level": "29", + "Move": "MOVE_FLAMETHROWER" + }, + { + "Level": "32", + "Move": "MOVE_TAKE_DOWN" + }, + { + "Level": "36", + "Move": "MOVE_BULK_UP" + }, + { + "Level": "50", + "Move": "MOVE_FLARE_BLITZ" + }, + { + "Level": "56", + "Move": "MOVE_HEAD_SMASH" + } + ], + "TMMoves": [ + "MOVE_BRICK_BREAK", + "MOVE_DIG", + "MOVE_DOUBLE_EDGE", + "MOVE_DOUBLE_TEAM", + "MOVE_ENDURE", + "MOVE_FIRE_BLAST", + "MOVE_FIRE_PUNCH", + "MOVE_FOCUS_BLAST", + "MOVE_HEADBUTT", + "MOVE_HEAT_WAVE", + "MOVE_KNOCK_OFF", + "MOVE_OVERHEAT", + "MOVE_POISON_JAB", + "MOVE_PROTECT", + "MOVE_ROAR", + "MOVE_ROCK_SLIDE", + "MOVE_ROCK_SMASH", + "MOVE_ROCK_TOMB", + "MOVE_STONE_EDGE", + "MOVE_SUBSTITUTE", + "MOVE_TAUNT", + "MOVE_WILD_CHARGE", + "MOVE_WILL_O_WISP", + "MOVE_WORK_UP", + "MOVE_ZEN_HEADBUTT" + ], + "TutorMoves": [ + "MOVE_POWER_UP_PUNCH" + ], + "EggMoves": [] + }, + "EMBOAR": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_TAIL_WHIP" + }, + { + "Level": "6", + "Move": "MOVE_EMBER" + }, + { + "Level": "10", + "Move": "MOVE_ROLLOUT" + }, + { + "Level": "13", + "Move": "MOVE_SMOKESCREEN" + }, + { + "Level": "15", + "Move": "MOVE_FLAME_WHEEL" + }, + { + "Level": "20", + "Move": "MOVE_FIRE_SPIN" + }, + { + "Level": "24", + "Move": "MOVE_FOCUS_ENERGY" + }, + { + "Level": "29", + "Move": "MOVE_FLAMETHROWER" + }, + { + "Level": "32", + "Move": "MOVE_TAKE_DOWN" + }, + { + "Level": "36", + "Move": "MOVE_BULK_UP" + }, + { + "Level": "45", + "Move": "MOVE_CLOSE_COMBAT" + }, + { + "Level": "50", + "Move": "MOVE_FLARE_BLITZ" + }, + { + "Level": "56", + "Move": "MOVE_HEAD_SMASH" + } + ], + "TMMoves": [ + "MOVE_BRICK_BREAK", + "MOVE_CURSE", + "MOVE_DIG", + "MOVE_DOUBLE_EDGE", + "MOVE_DOUBLE_TEAM", + "MOVE_EARTHQUAKE", + "MOVE_ENDURE", + "MOVE_FIRE_BLAST", + "MOVE_FIRE_PUNCH", + "MOVE_FOCUS_BLAST", + "MOVE_GIGA_IMPACT", + "MOVE_HEADBUTT", + "MOVE_HEAT_WAVE", + "MOVE_HYPER_BEAM", + "MOVE_IRON_HEAD", + "MOVE_KNOCK_OFF", + "MOVE_OVERHEAT", + "MOVE_POISON_JAB", + "MOVE_PROTECT", + "MOVE_ROAR", + "MOVE_ROCK_SLIDE", + "MOVE_ROCK_SMASH", + "MOVE_ROCK_TOMB", + "MOVE_STONE_EDGE", + "MOVE_SUBSTITUTE", + "MOVE_TAUNT", + "MOVE_THUNDER_PUNCH", + "MOVE_WILD_CHARGE", + "MOVE_WILL_O_WISP", + "MOVE_WORK_UP", + "MOVE_ZEN_HEADBUTT" + ], + "TutorMoves": [ + "MOVE_HEAT_CRASH", + "MOVE_POWER_UP_PUNCH" + ], + "EggMoves": [] + }, + "PATRAT": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "3", + "Move": "MOVE_LEER" + }, + { + "Level": "6", + "Move": "MOVE_BITE" + }, + { + "Level": "11", + "Move": "MOVE_DETECT" + }, + { + "Level": "16", + "Move": "MOVE_CRUNCH" + }, + { + "Level": "18", + "Move": "MOVE_HYPNOSIS" + }, + { + "Level": "21", + "Move": "MOVE_SUPER_FANG" + }, + { + "Level": "26", + "Move": "MOVE_FOCUS_ENERGY" + }, + { + "Level": "28", + "Move": "MOVE_WORK_UP" + }, + { + "Level": "33", + "Move": "MOVE_NASTY_PLOT" + } + ], + "TMMoves": [ + "MOVE_BULLET_SEED", + "MOVE_DIG", + "MOVE_DOUBLE_TEAM", + "MOVE_ENDURE", + "MOVE_GUNK_SHOT", + "MOVE_MUD_SHOT", + "MOVE_PROTECT", + "MOVE_SHADOW_BALL", + "MOVE_SUBSTITUTE", + "MOVE_SWORDS_DANCE", + "MOVE_THUNDERBOLT", + "MOVE_TOXIC", + "MOVE_ZEN_HEADBUTT" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "WATCHOG": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "3", + "Move": "MOVE_LEER" + }, + { + "Level": "6", + "Move": "MOVE_BITE" + }, + { + "Level": "11", + "Move": "MOVE_DETECT" + }, + { + "Level": "16", + "Move": "MOVE_CRUNCH" + }, + { + "Level": "18", + "Move": "MOVE_HYPNOSIS" + }, + { + "Level": "21", + "Move": "MOVE_SUPER_FANG" + }, + { + "Level": "26", + "Move": "MOVE_FOCUS_ENERGY" + }, + { + "Level": "28", + "Move": "MOVE_WORK_UP" + }, + { + "Level": "33", + "Move": "MOVE_NASTY_PLOT" + }, + { + "Level": "40", + "Move": "MOVE_IRON_TAIL" + }, + { + "Level": "46", + "Move": "MOVE_TAKE_DOWN" + }, + { + "Level": "50", + "Move": "MOVE_DOUBLE_EDGE" + } + ], + "TMMoves": [ + "MOVE_BULLET_SEED", + "MOVE_DIG", + "MOVE_DOUBLE_TEAM", + "MOVE_ENDURE", + "MOVE_FIRE_PUNCH", + "MOVE_FLAMETHROWER", + "MOVE_GIGA_IMPACT", + "MOVE_GUNK_SHOT", + "MOVE_HYPER_BEAM", + "MOVE_ICE_PUNCH", + "MOVE_LIGHT_SCREEN", + "MOVE_MUD_SHOT", + "MOVE_POWER_UP_PUNCH", + "MOVE_PROTECT", + "MOVE_ROCK_SMASH", + "MOVE_SHADOW_BALL", + "MOVE_SUBSTITUTE", + "MOVE_SWIFT", + "MOVE_SWORDS_DANCE", + "MOVE_THUNDERBOLT", + "MOVE_THUNDER_PUNCH", + "MOVE_THUNDER_WAVE", + "MOVE_TOXIC", + "MOVE_ZEN_HEADBUTT" + ], + "TutorMoves": [ + "MOVE_CONFUSE_RAY" + ], + "EggMoves": [] + }, + "PANSAGE": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_LEECH_SEED" + }, + { + "Level": "1", + "Move": "MOVE_WORK_UP" + }, + { + "Level": "4", + "Move": "MOVE_LEER" + }, + { + "Level": "7", + "Move": "MOVE_LICK" + }, + { + "Level": "10", + "Move": "MOVE_VINE_WHIP" + }, + { + "Level": "16", + "Move": "MOVE_BULLET_SEED" + }, + { + "Level": "19", + "Move": "MOVE_BITE" + }, + { + "Level": "22", + "Move": "MOVE_MAGICAL_LEAF" + }, + { + "Level": "28", + "Move": "MOVE_HEADBUTT" + }, + { + "Level": "32", + "Move": "MOVE_LEAF_STORM" + }, + { + "Level": "36", + "Move": "MOVE_CRUNCH" + }, + { + "Level": "43", + "Move": "MOVE_FOCUS_BLAST" + } + ], + "TMMoves": [ + "MOVE_BRICK_BREAK", + "MOVE_DIG", + "MOVE_ENDURE", + "MOVE_ENERGY_BALL", + "MOVE_GIGA_DRAIN", + "MOVE_GUNK_SHOT", + "MOVE_IRON_TAIL", + "MOVE_MUD_SHOT", + "MOVE_NASTY_PLOT", + "MOVE_POWER_UP_PUNCH", + "MOVE_PROTECT", + "MOVE_ROCK_SLIDE", + "MOVE_ROCK_TOMB", + "MOVE_SHADOW_CLAW", + "MOVE_SOLAR_BEAM", + "MOVE_SUBSTITUTE", + "MOVE_SWIFT", + "MOVE_TAUNT", + "MOVE_TOXIC" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "SIMISAGE": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_LEECH_SEED" + }, + { + "Level": "1", + "Move": "MOVE_WORK_UP" + }, + { + "Level": "4", + "Move": "MOVE_LEER" + }, + { + "Level": "7", + "Move": "MOVE_LICK" + }, + { + "Level": "10", + "Move": "MOVE_VINE_WHIP" + }, + { + "Level": "16", + "Move": "MOVE_BULLET_SEED" + }, + { + "Level": "19", + "Move": "MOVE_BITE" + }, + { + "Level": "22", + "Move": "MOVE_MAGICAL_LEAF" + }, + { + "Level": "28", + "Move": "MOVE_HEADBUTT" + }, + { + "Level": "32", + "Move": "MOVE_LEAF_STORM" + }, + { + "Level": "36", + "Move": "MOVE_CRUNCH" + }, + { + "Level": "43", + "Move": "MOVE_FOCUS_BLAST" + } + ], + "TMMoves": [ + "MOVE_BRICK_BREAK", + "MOVE_DIG", + "MOVE_ENDURE", + "MOVE_ENERGY_BALL", + "MOVE_GIGA_DRAIN", + "MOVE_GIGA_IMPACT", + "MOVE_GUNK_SHOT", + "MOVE_HYPER_BEAM", + "MOVE_IRON_TAIL", + "MOVE_MUD_SHOT", + "MOVE_NASTY_PLOT", + "MOVE_POWER_UP_PUNCH", + "MOVE_PROTECT", + "MOVE_ROCK_SLIDE", + "MOVE_ROCK_TOMB", + "MOVE_SHADOW_CLAW", + "MOVE_SOLAR_BEAM", + "MOVE_SUBSTITUTE", + "MOVE_SWIFT", + "MOVE_TAUNT", + "MOVE_TOXIC" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "PANSEAR": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_FIRE_SPIN" + }, + { + "Level": "1", + "Move": "MOVE_WORK_UP" + }, + { + "Level": "4", + "Move": "MOVE_LEER" + }, + { + "Level": "7", + "Move": "MOVE_LICK" + }, + { + "Level": "10", + "Move": "MOVE_EMBER" + }, + { + "Level": "16", + "Move": "MOVE_FLAME_WHEEL" + }, + { + "Level": "19", + "Move": "MOVE_BITE" + }, + { + "Level": "25", + "Move": "MOVE_AMNESIA" + }, + { + "Level": "28", + "Move": "MOVE_HEADBUTT" + }, + { + "Level": "32", + "Move": "MOVE_FIRE_BLAST" + }, + { + "Level": "36", + "Move": "MOVE_CRUNCH" + }, + { + "Level": "43", + "Move": "MOVE_FOCUS_BLAST" + } + ], + "TMMoves": [ + "MOVE_BRICK_BREAK", + "MOVE_DIG", + "MOVE_ENDURE", + "MOVE_FIRE_PUNCH", + "MOVE_FLAMETHROWER", + "MOVE_FLARE_BLITZ", + "MOVE_GUNK_SHOT", + "MOVE_HEAT_WAVE", + "MOVE_IRON_TAIL", + "MOVE_MUD_SHOT", + "MOVE_NASTY_PLOT", + "MOVE_OVERHEAT", + "MOVE_POWER_UP_PUNCH", + "MOVE_PROTECT", + "MOVE_ROCK_SLIDE", + "MOVE_ROCK_TOMB", + "MOVE_SHADOW_CLAW", + "MOVE_SOLAR_BEAM", + "MOVE_SUBSTITUTE", + "MOVE_SWIFT", + "MOVE_TAUNT", + "MOVE_WILL_O_WISP" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "SIMISEAR": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_FIRE_SPIN" + }, + { + "Level": "1", + "Move": "MOVE_WORK_UP" + }, + { + "Level": "4", + "Move": "MOVE_LEER" + }, + { + "Level": "7", + "Move": "MOVE_LICK" + }, + { + "Level": "10", + "Move": "MOVE_EMBER" + }, + { + "Level": "16", + "Move": "MOVE_FLAME_WHEEL" + }, + { + "Level": "19", + "Move": "MOVE_BITE" + }, + { + "Level": "25", + "Move": "MOVE_AMNESIA" + }, + { + "Level": "28", + "Move": "MOVE_HEADBUTT" + }, + { + "Level": "32", + "Move": "MOVE_FIRE_BLAST" + }, + { + "Level": "36", + "Move": "MOVE_CRUNCH" + }, + { + "Level": "43", + "Move": "MOVE_FOCUS_BLAST" + } + ], + "TMMoves": [ + "MOVE_BRICK_BREAK", + "MOVE_DIG", + "MOVE_ENDURE", + "MOVE_FIRE_PUNCH", + "MOVE_FLAMETHROWER", + "MOVE_FLARE_BLITZ", + "MOVE_GIGA_IMPACT", + "MOVE_GUNK_SHOT", + "MOVE_HEAT_WAVE", + "MOVE_HYPER_BEAM", + "MOVE_IRON_TAIL", + "MOVE_MUD_SHOT", + "MOVE_NASTY_PLOT", + "MOVE_OVERHEAT", + "MOVE_POWER_UP_PUNCH", + "MOVE_PROTECT", + "MOVE_ROCK_SLIDE", + "MOVE_ROCK_TOMB", + "MOVE_SHADOW_CLAW", + "MOVE_SOLAR_BEAM", + "MOVE_SUBSTITUTE", + "MOVE_SWIFT", + "MOVE_TAUNT", + "MOVE_WILL_O_WISP" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "PANPOUR": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_AQUA_RING" + }, + { + "Level": "1", + "Move": "MOVE_WORK_UP" + }, + { + "Level": "4", + "Move": "MOVE_LEER" + }, + { + "Level": "7", + "Move": "MOVE_LICK" + }, + { + "Level": "10", + "Move": "MOVE_WATER_GUN" + }, + { + "Level": "16", + "Move": "MOVE_BUBBLE_BEAM" + }, + { + "Level": "19", + "Move": "MOVE_BITE" + }, + { + "Level": "25", + "Move": "MOVE_TAUNT" + }, + { + "Level": "28", + "Move": "MOVE_HEADBUTT" + }, + { + "Level": "32", + "Move": "MOVE_HYDRO_PUMP" + }, + { + "Level": "36", + "Move": "MOVE_CRUNCH" + }, + { + "Level": "43", + "Move": "MOVE_FOCUS_BLAST" + } + ], + "TMMoves": [ + "MOVE_BLIZZARD", + "MOVE_BRICK_BREAK", + "MOVE_DIG", + "MOVE_ENDURE", + "MOVE_FLIP_TURN", + "MOVE_GUNK_SHOT", + "MOVE_ICE_BEAM", + "MOVE_ICE_PUNCH", + "MOVE_ICY_WIND", + "MOVE_IRON_TAIL", + "MOVE_MUD_SHOT", + "MOVE_NASTY_PLOT", + "MOVE_POWER_UP_PUNCH", + "MOVE_PROTECT", + "MOVE_ROCK_SLIDE", + "MOVE_ROCK_TOMB", + "MOVE_SHADOW_CLAW", + "MOVE_SUBSTITUTE", + "MOVE_SURF", + "MOVE_SWIFT", + "MOVE_WATERFALL" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "SIMIPOUR": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_AQUA_RING" + }, + { + "Level": "1", + "Move": "MOVE_WORK_UP" + }, + { + "Level": "4", + "Move": "MOVE_LEER" + }, + { + "Level": "7", + "Move": "MOVE_LICK" + }, + { + "Level": "10", + "Move": "MOVE_WATER_GUN" + }, + { + "Level": "16", + "Move": "MOVE_BUBBLE_BEAM" + }, + { + "Level": "19", + "Move": "MOVE_BITE" + }, + { + "Level": "25", + "Move": "MOVE_TAUNT" + }, + { + "Level": "28", + "Move": "MOVE_HEADBUTT" + }, + { + "Level": "32", + "Move": "MOVE_HYDRO_PUMP" + }, + { + "Level": "36", + "Move": "MOVE_CRUNCH" + }, + { + "Level": "43", + "Move": "MOVE_FOCUS_BLAST" + } + ], + "TMMoves": [ + "MOVE_BLIZZARD", + "MOVE_BRICK_BREAK", + "MOVE_DIG", + "MOVE_ENDURE", + "MOVE_FLIP_TURN", + "MOVE_GIGA_IMPACT", + "MOVE_GUNK_SHOT", + "MOVE_HYPER_BEAM", + "MOVE_ICE_BEAM", + "MOVE_ICE_PUNCH", + "MOVE_ICY_WIND", + "MOVE_IRON_TAIL", + "MOVE_LIQUIDATION", + "MOVE_MUD_SHOT", + "MOVE_NASTY_PLOT", + "MOVE_POWER_UP_PUNCH", + "MOVE_PROTECT", + "MOVE_ROCK_SLIDE", + "MOVE_ROCK_TOMB", + "MOVE_SHADOW_CLAW", + "MOVE_SUBSTITUTE", + "MOVE_SURF", + "MOVE_SWIFT", + "MOVE_WATERFALL" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "DRILBUR": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_LEER" + }, + { + "Level": "1", + "Move": "MOVE_MUD_SHOT" + }, + { + "Level": "7", + "Move": "MOVE_METAL_CLAW" + }, + { + "Level": "13", + "Move": "MOVE_SAND_TOMB" + }, + { + "Level": "18", + "Move": "MOVE_BULLDOZE" + }, + { + "Level": "24", + "Move": "MOVE_SLASH" + }, + { + "Level": "28", + "Move": "MOVE_DIG" + }, + { + "Level": "32", + "Move": "MOVE_ROCK_SLIDE" + }, + { + "Level": "36", + "Move": "MOVE_SWORDS_DANCE" + }, + { + "Level": "40", + "Move": "MOVE_DRILL_RUN" + }, + { + "Level": "46", + "Move": "MOVE_EARTHQUAKE" + } + ], + "TMMoves": [ + "MOVE_AGILITY", + "MOVE_BRICK_BREAK", + "MOVE_DOUBLE_EDGE", + "MOVE_ENDURE", + "MOVE_IRON_DEFENSE", + "MOVE_POISON_JAB", + "MOVE_PROTECT", + "MOVE_ROCK_SMASH", + "MOVE_ROCK_TOMB", + "MOVE_SLUDGE_BOMB", + "MOVE_SUBSTITUTE", + "MOVE_X_SCISSOR" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "EXCADRILL": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_LEER" + }, + { + "Level": "1", + "Move": "MOVE_MUD_SHOT" + }, + { + "Level": "7", + "Move": "MOVE_METAL_CLAW" + }, + { + "Level": "13", + "Move": "MOVE_SAND_TOMB" + }, + { + "Level": "16", + "Move": "MOVE_ROCK_BLAST" + }, + { + "Level": "18", + "Move": "MOVE_BULLDOZE" + }, + { + "Level": "24", + "Move": "MOVE_SLASH" + }, + { + "Level": "26", + "Move": "MOVE_X_SCISSOR" + }, + { + "Level": "28", + "Move": "MOVE_DIG" + }, + { + "Level": "32", + "Move": "MOVE_ROCK_SLIDE" + }, + { + "Level": "36", + "Move": "MOVE_SWORDS_DANCE" + }, + { + "Level": "40", + "Move": "MOVE_DRILL_RUN" + }, + { + "Level": "46", + "Move": "MOVE_EARTHQUAKE" + }, + { + "Level": "50", + "Move": "MOVE_MEGAHORN" + } + ], + "TMMoves": [ + "MOVE_AGILITY", + "MOVE_BRICK_BREAK", + "MOVE_DOUBLE_EDGE", + "MOVE_EARTH_POWER", + "MOVE_ENDURE", + "MOVE_FOCUS_BLAST", + "MOVE_GIGA_IMPACT", + "MOVE_HYPER_BEAM", + "MOVE_IRON_DEFENSE", + "MOVE_IRON_HEAD", + "MOVE_POISON_JAB", + "MOVE_PROTECT", + "MOVE_ROCK_SMASH", + "MOVE_ROCK_TOMB", + "MOVE_SLUDGE_BOMB", + "MOVE_STEALTH_ROCK", + "MOVE_SUBSTITUTE" + ], + "TutorMoves": [ + "MOVE_METAL_SOUND" + ], + "EggMoves": [] + }, + "AUDINO": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_GROWL" + }, + { + "Level": "4", + "Move": "MOVE_DISARMING_VOICE" + }, + { + "Level": "8", + "Move": "MOVE_ICY_WIND" + }, + { + "Level": "16", + "Move": "MOVE_DRAINING_KISS" + }, + { + "Level": "20", + "Move": "MOVE_ZEN_HEADBUTT" + }, + { + "Level": "24", + "Move": "MOVE_AMNESIA" + }, + { + "Level": "32", + "Move": "MOVE_TAKE_DOWN" + }, + { + "Level": "36", + "Move": "MOVE_WISH" + }, + { + "Level": "40", + "Move": "MOVE_HYPER_VOICE" + }, + { + "Level": "48", + "Move": "MOVE_DOUBLE_EDGE" + } + ], + "TMMoves": [ + "MOVE_BLIZZARD", + "MOVE_BODY_SLAM", + "MOVE_CALM_MIND", + "MOVE_DAZZLING_GLEAM", + "MOVE_DIG", + "MOVE_ENDURE", + "MOVE_FIRE_BLAST", + "MOVE_FIRE_PUNCH", + "MOVE_FLAMETHROWER", + "MOVE_GIGA_IMPACT", + "MOVE_HYPER_BEAM", + "MOVE_ICE_BEAM", + "MOVE_ICE_PUNCH", + "MOVE_IRON_TAIL", + "MOVE_LIGHT_SCREEN", + "MOVE_POWER_UP_PUNCH", + "MOVE_PROTECT", + "MOVE_PSYCHIC", + "MOVE_PSYSHOCK", + "MOVE_REFLECT", + "MOVE_SAFEGUARD", + "MOVE_SHADOW_BALL", + "MOVE_SOLAR_BEAM", + "MOVE_SUBSTITUTE", + "MOVE_SURF", + "MOVE_THUNDER", + "MOVE_THUNDERBOLT", + "MOVE_THUNDER_PUNCH", + "MOVE_THUNDER_WAVE", + "MOVE_WILD_CHARGE", + "MOVE_WORK_UP" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "VENIPEDE": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_POISON_STING" + }, + { + "Level": "1", + "Move": "MOVE_LEER" + }, + { + "Level": "4", + "Move": "MOVE_ROLLOUT" + }, + { + "Level": "8", + "Move": "MOVE_PROTECT" + }, + { + "Level": "12", + "Move": "MOVE_INFESTATION" + }, + { + "Level": "16", + "Move": "MOVE_SCREECH" + }, + { + "Level": "20", + "Move": "MOVE_PIN_MISSILE" + }, + { + "Level": "24", + "Move": "MOVE_TAKE_DOWN" + }, + { + "Level": "28", + "Move": "MOVE_POISON_JAB" + }, + { + "Level": "36", + "Move": "MOVE_TOXIC" + }, + { + "Level": "48", + "Move": "MOVE_AGILITY" + }, + { + "Level": "52", + "Move": "MOVE_DOUBLE_EDGE" + } + ], + "TMMoves": [ + "MOVE_ENDURE", + "MOVE_IRON_DEFENSE", + "MOVE_ROCK_TOMB", + "MOVE_SLUDGE_BOMB", + "MOVE_SOLAR_BEAM", + "MOVE_SPIKES", + "MOVE_SUBSTITUTE", + "MOVE_TOXIC_SPIKES" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "WHIRLIPEDE": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_POISON_STING" + }, + { + "Level": "1", + "Move": "MOVE_LEER" + }, + { + "Level": "4", + "Move": "MOVE_ROLLOUT" + }, + { + "Level": "8", + "Move": "MOVE_PROTECT" + }, + { + "Level": "12", + "Move": "MOVE_INFESTATION" + }, + { + "Level": "16", + "Move": "MOVE_SCREECH" + }, + { + "Level": "20", + "Move": "MOVE_PIN_MISSILE" + }, + { + "Level": "24", + "Move": "MOVE_TAKE_DOWN" + }, + { + "Level": "28", + "Move": "MOVE_POISON_JAB" + }, + { + "Level": "36", + "Move": "MOVE_TOXIC" + }, + { + "Level": "48", + "Move": "MOVE_AGILITY" + }, + { + "Level": "52", + "Move": "MOVE_DOUBLE_EDGE" + } + ], + "TMMoves": [ + "MOVE_ENDURE", + "MOVE_IRON_DEFENSE", + "MOVE_ROCK_TOMB", + "MOVE_SLUDGE_BOMB", + "MOVE_SOLAR_BEAM", + "MOVE_SPIKES", + "MOVE_SUBSTITUTE", + "MOVE_TOXIC_SPIKES" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "SCOLIPEDE": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_POISON_STING" + }, + { + "Level": "1", + "Move": "MOVE_LEER" + }, + { + "Level": "1", + "Move": "MOVE_IRON_DEFENSE" + }, + { + "Level": "4", + "Move": "MOVE_ROLLOUT" + }, + { + "Level": "8", + "Move": "MOVE_PROTECT" + }, + { + "Level": "12", + "Move": "MOVE_INFESTATION" + }, + { + "Level": "16", + "Move": "MOVE_SCREECH" + }, + { + "Level": "20", + "Move": "MOVE_PIN_MISSILE" + }, + { + "Level": "24", + "Move": "MOVE_TAKE_DOWN" + }, + { + "Level": "28", + "Move": "MOVE_POISON_JAB" + }, + { + "Level": "36", + "Move": "MOVE_TOXIC" + }, + { + "Level": "40", + "Move": "MOVE_IRON_TAIL" + }, + { + "Level": "44", + "Move": "MOVE_X_SCISSOR" + }, + { + "Level": "48", + "Move": "MOVE_AGILITY" + }, + { + "Level": "52", + "Move": "MOVE_DOUBLE_EDGE" + }, + { + "Level": "56", + "Move": "MOVE_MEGAHORN" + } + ], + "TMMoves": [ + "MOVE_DIG", + "MOVE_EARTHQUAKE", + "MOVE_ENDURE", + "MOVE_GIGA_IMPACT", + "MOVE_GUNK_SHOT", + "MOVE_HYPER_BEAM", + "MOVE_ROCK_SLIDE", + "MOVE_ROCK_TOMB", + "MOVE_SLUDGE_BOMB", + "MOVE_SOLAR_BEAM", + "MOVE_SPIKES", + "MOVE_SUBSTITUTE", + "MOVE_SWORDS_DANCE", + "MOVE_TOXIC_SPIKES", + "MOVE_U_TURN" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "SANDILE": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_LEER" + }, + { + "Level": "9", + "Move": "MOVE_SAND_TOMB" + }, + { + "Level": "15", + "Move": "MOVE_BITE" + }, + { + "Level": "21", + "Move": "MOVE_DIG" + }, + { + "Level": "24", + "Move": "MOVE_TAKE_DOWN" + }, + { + "Level": "27", + "Move": "MOVE_CRUNCH" + }, + { + "Level": "36", + "Move": "MOVE_IRON_TAIL" + }, + { + "Level": "42", + "Move": "MOVE_EARTHQUAKE" + }, + { + "Level": "50", + "Move": "MOVE_DOUBLE_EDGE" + } + ], + "TMMoves": [ + "MOVE_AERIAL_ACE", + "MOVE_BODY_SLAM", + "MOVE_BRICK_BREAK", + "MOVE_BULLDOZE", + "MOVE_DARK_PULSE", + "MOVE_DRAGON_CLAW", + "MOVE_EARTH_POWER", + "MOVE_ENDURE", + "MOVE_FIRE_FANG", + "MOVE_PROTECT", + "MOVE_ROAR", + "MOVE_ROCK_SLIDE", + "MOVE_ROCK_TOMB", + "MOVE_SHADOW_CLAW", + "MOVE_SLUDGE_BOMB", + "MOVE_STEALTH_ROCK", + "MOVE_STONE_EDGE", + "MOVE_SUBSTITUTE", + "MOVE_TAUNT", + "MOVE_THUNDER_FANG" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "KROKOROK": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_LEER" + }, + { + "Level": "9", + "Move": "MOVE_SAND_TOMB" + }, + { + "Level": "15", + "Move": "MOVE_BITE" + }, + { + "Level": "21", + "Move": "MOVE_DIG" + }, + { + "Level": "24", + "Move": "MOVE_TAKE_DOWN" + }, + { + "Level": "27", + "Move": "MOVE_CRUNCH" + }, + { + "Level": "36", + "Move": "MOVE_IRON_TAIL" + }, + { + "Level": "42", + "Move": "MOVE_EARTHQUAKE" + }, + { + "Level": "50", + "Move": "MOVE_DOUBLE_EDGE" + } + ], + "TMMoves": [ + "MOVE_AERIAL_ACE", + "MOVE_BODY_SLAM", + "MOVE_BRICK_BREAK", + "MOVE_BULLDOZE", + "MOVE_CURSE", + "MOVE_DARK_PULSE", + "MOVE_DRAGON_CLAW", + "MOVE_EARTH_POWER", + "MOVE_ENDURE", + "MOVE_FIRE_FANG", + "MOVE_KNOCK_OFF", + "MOVE_PROTECT", + "MOVE_ROAR", + "MOVE_ROCK_SLIDE", + "MOVE_ROCK_TOMB", + "MOVE_SHADOW_CLAW", + "MOVE_SLUDGE_BOMB", + "MOVE_STEALTH_ROCK", + "MOVE_STONE_EDGE", + "MOVE_SUBSTITUTE", + "MOVE_TAUNT", + "MOVE_THUNDER_FANG" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "KROOKODILE": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_LEER" + }, + { + "Level": "9", + "Move": "MOVE_SAND_TOMB" + }, + { + "Level": "15", + "Move": "MOVE_BITE" + }, + { + "Level": "21", + "Move": "MOVE_DIG" + }, + { + "Level": "24", + "Move": "MOVE_TAKE_DOWN" + }, + { + "Level": "27", + "Move": "MOVE_CRUNCH" + }, + { + "Level": "36", + "Move": "MOVE_IRON_TAIL" + }, + { + "Level": "42", + "Move": "MOVE_EARTHQUAKE" + }, + { + "Level": "50", + "Move": "MOVE_DOUBLE_EDGE" + }, + { + "Level": "58", + "Move": "MOVE_OUTRAGE" + } + ], + "TMMoves": [ + "MOVE_AERIAL_ACE", + "MOVE_BODY_SLAM", + "MOVE_BRICK_BREAK", + "MOVE_BULK_UP", + "MOVE_BULLDOZE", + "MOVE_CLOSE_COMBAT", + "MOVE_CURSE", + "MOVE_DARK_PULSE", + "MOVE_DRAGON_CLAW", + "MOVE_EARTH_POWER", + "MOVE_ENDURE", + "MOVE_FIRE_FANG", + "MOVE_FOCUS_BLAST", + "MOVE_GIGA_IMPACT", + "MOVE_GUNK_SHOT", + "MOVE_HYPER_BEAM", + "MOVE_IRON_HEAD", + "MOVE_KNOCK_OFF", + "MOVE_PROTECT", + "MOVE_ROAR", + "MOVE_ROCK_SLIDE", + "MOVE_ROCK_TOMB", + "MOVE_SHADOW_CLAW", + "MOVE_SLUDGE_BOMB", + "MOVE_STEALTH_ROCK", + "MOVE_STONE_EDGE", + "MOVE_SUBSTITUTE", + "MOVE_TAUNT", + "MOVE_THUNDER_FANG" + ], + "TutorMoves": [ + "MOVE_BREAKING_SWIPE" + ], + "EggMoves": [] + }, + "SCRAGGY": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_LEER" + }, + { + "Level": "8", + "Move": "MOVE_HEADBUTT" + }, + { + "Level": "12", + "Move": "MOVE_POWER_UP_PUNCH" + }, + { + "Level": "16", + "Move": "MOVE_ROCK_TOMB" + }, + { + "Level": "20", + "Move": "MOVE_PROTECT" + }, + { + "Level": "26", + "Move": "MOVE_PARTING_SHOT" + }, + { + "Level": "32", + "Move": "MOVE_BRICK_BREAK" + }, + { + "Level": "35", + "Move": "MOVE_DETECT" + }, + { + "Level": "40", + "Move": "MOVE_CRUNCH" + }, + { + "Level": "44", + "Move": "MOVE_IRON_TAIL" + }, + { + "Level": "48", + "Move": "MOVE_DYNAMIC_PUNCH" + }, + { + "Level": "52", + "Move": "MOVE_HEAD_SMASH" + } + ], + "TMMoves": [ + "MOVE_BULK_UP", + "MOVE_CURSE", + "MOVE_DARK_PULSE", + "MOVE_DIG", + "MOVE_DRAGON_CLAW", + "MOVE_DRAGON_PULSE", + "MOVE_ENDURE", + "MOVE_FIRE_PUNCH", + "MOVE_FOCUS_BLAST", + "MOVE_ICE_PUNCH", + "MOVE_IRON_DEFENSE", + "MOVE_IRON_HEAD", + "MOVE_POISON_JAB", + "MOVE_ROAR", + "MOVE_ROCK_SLIDE", + "MOVE_SLUDGE_BOMB", + "MOVE_STONE_EDGE", + "MOVE_SUBSTITUTE", + "MOVE_TAUNT", + "MOVE_THUNDER_PUNCH", + "MOVE_WORK_UP", + "MOVE_ZEN_HEADBUTT" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "SCRAFTY": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_LEER" + }, + { + "Level": "8", + "Move": "MOVE_HEADBUTT" + }, + { + "Level": "12", + "Move": "MOVE_POWER_UP_PUNCH" + }, + { + "Level": "16", + "Move": "MOVE_ROCK_TOMB" + }, + { + "Level": "20", + "Move": "MOVE_PROTECT" + }, + { + "Level": "26", + "Move": "MOVE_PARTING_SHOT" + }, + { + "Level": "32", + "Move": "MOVE_BRICK_BREAK" + }, + { + "Level": "35", + "Move": "MOVE_DETECT" + }, + { + "Level": "40", + "Move": "MOVE_CRUNCH" + }, + { + "Level": "44", + "Move": "MOVE_IRON_TAIL" + }, + { + "Level": "48", + "Move": "MOVE_DYNAMIC_PUNCH" + }, + { + "Level": "52", + "Move": "MOVE_HEAD_SMASH" + } + ], + "TMMoves": [ + "MOVE_BULK_UP", + "MOVE_CLOSE_COMBAT", + "MOVE_CURSE", + "MOVE_DARK_PULSE", + "MOVE_DIG", + "MOVE_DOUBLE_EDGE", + "MOVE_DRAGON_CLAW", + "MOVE_DRAGON_PULSE", + "MOVE_ENDURE", + "MOVE_FIRE_PUNCH", + "MOVE_FOCUS_BLAST", + "MOVE_GIGA_IMPACT", + "MOVE_HYPER_BEAM", + "MOVE_ICE_PUNCH", + "MOVE_IRON_DEFENSE", + "MOVE_IRON_HEAD", + "MOVE_KNOCK_OFF", + "MOVE_METRONOME", + "MOVE_OUTRAGE", + "MOVE_POISON_JAB", + "MOVE_ROAR", + "MOVE_ROCK_SLIDE", + "MOVE_ROCK_SMASH", + "MOVE_SLUDGE_BOMB", + "MOVE_STONE_EDGE", + "MOVE_SUBSTITUTE", + "MOVE_SWORDS_DANCE", + "MOVE_TAUNT", + "MOVE_THUNDER_PUNCH", + "MOVE_WORK_UP", + "MOVE_ZEN_HEADBUTT" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "TRUBBISH": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_HEADBUTT" + }, + { + "Level": "1", + "Move": "MOVE_SMOKESCREEN" + }, + { + "Level": "9", + "Move": "MOVE_AMNESIA" + }, + { + "Level": "12", + "Move": "MOVE_ROLLOUT" + }, + { + "Level": "15", + "Move": "MOVE_TOXIC_SPIKES" + }, + { + "Level": "18", + "Move": "MOVE_BRUTAL_SWING" + }, + { + "Level": "20", + "Move": "MOVE_TAKE_DOWN" + }, + { + "Level": "24", + "Move": "MOVE_POISON_JAB" + }, + { + "Level": "27", + "Move": "MOVE_SLUDGE_BOMB" + }, + { + "Level": "30", + "Move": "MOVE_TOXIC" + }, + { + "Level": "34", + "Move": "MOVE_SELF_DESTRUCT" + }, + { + "Level": "39", + "Move": "MOVE_SLUDGE_WAVE" + }, + { + "Level": "44", + "Move": "MOVE_GUNK_SHOT" + }, + { + "Level": "53", + "Move": "MOVE_EXPLOSION" + } + ], + "TMMoves": [ + "MOVE_BULLET_SEED", + "MOVE_DARK_PULSE", + "MOVE_ENDURE", + "MOVE_GIGA_DRAIN", + "MOVE_MUD_SHOT", + "MOVE_PROTECT", + "MOVE_ROCK_BLAST", + "MOVE_SPIKES", + "MOVE_SUBSTITUTE" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "GARBODOR": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_HEADBUTT" + }, + { + "Level": "1", + "Move": "MOVE_SMOKESCREEN" + }, + { + "Level": "1", + "Move": "MOVE_METAL_CLAW" + }, + { + "Level": "9", + "Move": "MOVE_AMNESIA" + }, + { + "Level": "12", + "Move": "MOVE_ROLLOUT" + }, + { + "Level": "15", + "Move": "MOVE_TOXIC_SPIKES" + }, + { + "Level": "18", + "Move": "MOVE_BRUTAL_SWING" + }, + { + "Level": "20", + "Move": "MOVE_TAKE_DOWN" + }, + { + "Level": "24", + "Move": "MOVE_POISON_JAB" + }, + { + "Level": "27", + "Move": "MOVE_SLUDGE_BOMB" + }, + { + "Level": "30", + "Move": "MOVE_TOXIC" + }, + { + "Level": "34", + "Move": "MOVE_SELF_DESTRUCT" + }, + { + "Level": "39", + "Move": "MOVE_SLUDGE_WAVE" + }, + { + "Level": "44", + "Move": "MOVE_GUNK_SHOT" + }, + { + "Level": "53", + "Move": "MOVE_EXPLOSION" + } + ], + "TMMoves": [ + "MOVE_BODY_SLAM", + "MOVE_BULLET_SEED", + "MOVE_DARK_PULSE", + "MOVE_ENDURE", + "MOVE_FOCUS_BLAST", + "MOVE_GIGA_DRAIN", + "MOVE_GIGA_IMPACT", + "MOVE_HEAL_BLOCK", + "MOVE_HYPER_BEAM", + "MOVE_MUD_SHOT", + "MOVE_PROTECT", + "MOVE_PSYCHIC", + "MOVE_ROCK_BLAST", + "MOVE_SOLAR_BEAM", + "MOVE_SPIKES", + "MOVE_SUBSTITUTE", + "MOVE_THUNDERBOLT" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "VANILLITE": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_HARDEN" + }, + { + "Level": "4", + "Move": "MOVE_TAUNT" + }, + { + "Level": "8", + "Move": "MOVE_MIST" + }, + { + "Level": "12", + "Move": "MOVE_ICY_WIND" + }, + { + "Level": "20", + "Move": "MOVE_SELF_DESTRUCT" + }, + { + "Level": "24", + "Move": "MOVE_ICICLE_CRASH" + }, + { + "Level": "32", + "Move": "MOVE_ACID_ARMOR" + }, + { + "Level": "35", + "Move": "MOVE_ICE_BEAM" + }, + { + "Level": "46", + "Move": "MOVE_EXPLOSION" + }, + { + "Level": "58", + "Move": "MOVE_BLIZZARD" + } + ], + "TMMoves": [ + "MOVE_ENDURE", + "MOVE_FLASH_CANNON", + "MOVE_HYPER_VOICE", + "MOVE_IRON_DEFENSE", + "MOVE_LIGHT_SCREEN", + "MOVE_PROTECT", + "MOVE_SUBSTITUTE" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "VANILLISH": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_HARDEN" + }, + { + "Level": "4", + "Move": "MOVE_TAUNT" + }, + { + "Level": "8", + "Move": "MOVE_MIST" + }, + { + "Level": "12", + "Move": "MOVE_ICY_WIND" + }, + { + "Level": "20", + "Move": "MOVE_SELF_DESTRUCT" + }, + { + "Level": "24", + "Move": "MOVE_ICICLE_CRASH" + }, + { + "Level": "32", + "Move": "MOVE_ACID_ARMOR" + }, + { + "Level": "35", + "Move": "MOVE_ICE_BEAM" + }, + { + "Level": "46", + "Move": "MOVE_EXPLOSION" + }, + { + "Level": "58", + "Move": "MOVE_BLIZZARD" + } + ], + "TMMoves": [ + "MOVE_ENDURE", + "MOVE_FLASH_CANNON", + "MOVE_HYPER_VOICE", + "MOVE_IRON_DEFENSE", + "MOVE_LIGHT_SCREEN", + "MOVE_PROTECT", + "MOVE_SUBSTITUTE" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "VANILLUXE": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_HARDEN" + }, + { + "Level": "1", + "Move": "MOVE_FREEZE_DRY" + }, + { + "Level": "4", + "Move": "MOVE_TAUNT" + }, + { + "Level": "8", + "Move": "MOVE_MIST" + }, + { + "Level": "12", + "Move": "MOVE_ICY_WIND" + }, + { + "Level": "20", + "Move": "MOVE_SELF_DESTRUCT" + }, + { + "Level": "24", + "Move": "MOVE_ICICLE_CRASH" + }, + { + "Level": "32", + "Move": "MOVE_ACID_ARMOR" + }, + { + "Level": "35", + "Move": "MOVE_ICE_BEAM" + }, + { + "Level": "46", + "Move": "MOVE_EXPLOSION" + }, + { + "Level": "58", + "Move": "MOVE_BLIZZARD" + } + ], + "TMMoves": [ + "MOVE_ENDURE", + "MOVE_FLASH_CANNON", + "MOVE_GIGA_IMPACT", + "MOVE_HYPER_BEAM", + "MOVE_HYPER_VOICE", + "MOVE_IRON_DEFENSE", + "MOVE_LIGHT_SCREEN", + "MOVE_PROTECT", + "MOVE_SUBSTITUTE" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "EMOLGA": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TAIL_WHIP" + }, + { + "Level": "1", + "Move": "MOVE_NUZZLE" + }, + { + "Level": "5", + "Move": "MOVE_DOUBLE_TEAM" + }, + { + "Level": "7", + "Move": "MOVE_CHARM" + }, + { + "Level": "10", + "Move": "MOVE_QUICK_ATTACK" + }, + { + "Level": "15", + "Move": "MOVE_THUNDER_SHOCK" + }, + { + "Level": "20", + "Move": "MOVE_CHARGE" + }, + { + "Level": "22", + "Move": "MOVE_WING_ATTACK" + }, + { + "Level": "25", + "Move": "MOVE_EERIE_IMPULSE" + }, + { + "Level": "29", + "Move": "MOVE_SPARK" + }, + { + "Level": "35", + "Move": "MOVE_AIR_SLASH" + }, + { + "Level": "40", + "Move": "MOVE_VOLT_SWITCH" + }, + { + "Level": "44", + "Move": "MOVE_LIGHT_SCREEN" + }, + { + "Level": "52", + "Move": "MOVE_DISCHARGE" + } + ], + "TMMoves": [ + "MOVE_AGILITY", + "MOVE_ELECTROWEB", + "MOVE_ENDURE", + "MOVE_ENERGY_BALL", + "MOVE_IRON_TAIL", + "MOVE_PROTECT", + "MOVE_SOLAR_BEAM", + "MOVE_SUBSTITUTE", + "MOVE_SWIFT", + "MOVE_TAUNT", + "MOVE_THUNDER", + "MOVE_THUNDERBOLT", + "MOVE_THUNDER_WAVE", + "MOVE_U_TURN", + "MOVE_WILD_CHARGE" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "TYNAMO": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_THUNDER_WAVE" + }, + { + "Level": "1", + "Move": "MOVE_SPARK" + } + ], + "TMMoves": [ + "MOVE_PROTECT" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "EELEKTRIK": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_HEADBUTT" + }, + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_THUNDER_WAVE" + }, + { + "Level": "1", + "Move": "MOVE_SPARK" + }, + { + "Level": "18", + "Move": "MOVE_TAKE_DOWN" + }, + { + "Level": "29", + "Move": "MOVE_DISCHARGE" + }, + { + "Level": "33", + "Move": "MOVE_EERIE_IMPULSE" + }, + { + "Level": "39", + "Move": "MOVE_CHARGE" + }, + { + "Level": "44", + "Move": "MOVE_THUNDERBOLT" + }, + { + "Level": "46", + "Move": "MOVE_WILD_CHARGE" + }, + { + "Level": "48", + "Move": "MOVE_ZAP_CANNON" + }, + { + "Level": "50", + "Move": "MOVE_SUPER_FANG" + } + ], + "TMMoves": [ + "MOVE_BODY_SLAM", + "MOVE_ENDURE", + "MOVE_FLASH_CANNON", + "MOVE_GIGA_DRAIN", + "MOVE_LIGHT_SCREEN", + "MOVE_PROTECT", + "MOVE_SUBSTITUTE", + "MOVE_THUNDER", + "MOVE_THUNDER_FANG", + "MOVE_U_TURN", + "MOVE_VOLT_SWITCH" + ], + "TutorMoves": [ + "MOVE_CRUNCH" + ], + "EggMoves": [] + }, + "EELEKTROSS": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_HEADBUTT" + }, + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_SPARK" + }, + { + "Level": "1", + "Move": "MOVE_CRUNCH" + }, + { + "Level": "18", + "Move": "MOVE_TAKE_DOWN" + }, + { + "Level": "21", + "Move": "MOVE_CONFUSE_RAY" + }, + { + "Level": "29", + "Move": "MOVE_DISCHARGE" + }, + { + "Level": "33", + "Move": "MOVE_EERIE_IMPULSE" + }, + { + "Level": "36", + "Move": "MOVE_LIQUIDATION" + }, + { + "Level": "39", + "Move": "MOVE_CHARGE" + }, + { + "Level": "44", + "Move": "MOVE_THUNDERBOLT" + }, + { + "Level": "46", + "Move": "MOVE_WILD_CHARGE" + }, + { + "Level": "48", + "Move": "MOVE_ZAP_CANNON" + }, + { + "Level": "50", + "Move": "MOVE_SUPER_FANG" + } + ], + "TMMoves": [ + "MOVE_BODY_SLAM", + "MOVE_BULK_UP", + "MOVE_BULLDOZE", + "MOVE_CLOSE_COMBAT", + "MOVE_DRAGON_CLAW", + "MOVE_DRAGON_PULSE", + "MOVE_ELECTROWEB", + "MOVE_ENDURE", + "MOVE_FIRE_PUNCH", + "MOVE_FLAMETHROWER", + "MOVE_FLASH_CANNON", + "MOVE_GIGA_DRAIN", + "MOVE_GIGA_IMPACT", + "MOVE_HYPER_BEAM", + "MOVE_LIGHT_SCREEN", + "MOVE_OUTRAGE", + "MOVE_PROTECT", + "MOVE_ROCK_SLIDE", + "MOVE_ROCK_TOMB", + "MOVE_SUBSTITUTE", + "MOVE_THUNDER", + "MOVE_THUNDER_FANG", + "MOVE_THUNDER_PUNCH", + "MOVE_THUNDER_WAVE", + "MOVE_U_TURN", + "MOVE_VOLT_SWITCH", + "MOVE_WATERFALL", + "MOVE_ZEN_HEADBUTT" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "LITWICK": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_EMBER" + }, + { + "Level": "1", + "Move": "MOVE_SMOKESCREEN" + }, + { + "Level": "10", + "Move": "MOVE_HAZE" + }, + { + "Level": "12", + "Move": "MOVE_CONFUSE_RAY" + }, + { + "Level": "16", + "Move": "MOVE_ACID_ARMOR" + }, + { + "Level": "20", + "Move": "MOVE_WILL_O_WISP" + }, + { + "Level": "24", + "Move": "MOVE_FIRE_SPIN" + }, + { + "Level": "28", + "Move": "MOVE_FLAMETHROWER" + }, + { + "Level": "32", + "Move": "MOVE_SHADOW_BALL" + }, + { + "Level": "38", + "Move": "MOVE_FLAME_WHEEL" + }, + { + "Level": "44", + "Move": "MOVE_CURSE" + }, + { + "Level": "48", + "Move": "MOVE_HEAL_BLOCK" + }, + { + "Level": "52", + "Move": "MOVE_OVERHEAT" + } + ], + "TMMoves": [ + "MOVE_CALM_MIND", + "MOVE_DARK_PULSE", + "MOVE_DOUBLE_TEAM", + "MOVE_ENDURE", + "MOVE_ENERGY_BALL", + "MOVE_FIRE_BLAST", + "MOVE_HEAT_WAVE", + "MOVE_PROTECT", + "MOVE_PSYCHIC", + "MOVE_SAFEGUARD", + "MOVE_SOLAR_BEAM", + "MOVE_SUBSTITUTE", + "MOVE_TAUNT" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "LAMPENT": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_EMBER" + }, + { + "Level": "1", + "Move": "MOVE_SMOKESCREEN" + }, + { + "Level": "10", + "Move": "MOVE_HAZE" + }, + { + "Level": "12", + "Move": "MOVE_CONFUSE_RAY" + }, + { + "Level": "16", + "Move": "MOVE_ACID_ARMOR" + }, + { + "Level": "20", + "Move": "MOVE_WILL_O_WISP" + }, + { + "Level": "24", + "Move": "MOVE_FIRE_SPIN" + }, + { + "Level": "28", + "Move": "MOVE_FLAMETHROWER" + }, + { + "Level": "32", + "Move": "MOVE_SHADOW_BALL" + }, + { + "Level": "38", + "Move": "MOVE_FLAME_WHEEL" + }, + { + "Level": "44", + "Move": "MOVE_CURSE" + }, + { + "Level": "48", + "Move": "MOVE_HEAL_BLOCK" + }, + { + "Level": "52", + "Move": "MOVE_OVERHEAT" + } + ], + "TMMoves": [ + "MOVE_CALM_MIND", + "MOVE_DARK_PULSE", + "MOVE_DOUBLE_TEAM", + "MOVE_ENDURE", + "MOVE_ENERGY_BALL", + "MOVE_FIRE_BLAST", + "MOVE_HEAT_WAVE", + "MOVE_PROTECT", + "MOVE_PSYCHIC", + "MOVE_SAFEGUARD", + "MOVE_SOLAR_BEAM", + "MOVE_SUBSTITUTE", + "MOVE_TAUNT" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "CHANDELURE": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_EMBER" + }, + { + "Level": "1", + "Move": "MOVE_SMOKESCREEN" + }, + { + "Level": "10", + "Move": "MOVE_HAZE" + }, + { + "Level": "12", + "Move": "MOVE_CONFUSE_RAY" + }, + { + "Level": "16", + "Move": "MOVE_ACID_ARMOR" + }, + { + "Level": "20", + "Move": "MOVE_WILL_O_WISP" + }, + { + "Level": "24", + "Move": "MOVE_FIRE_SPIN" + }, + { + "Level": "28", + "Move": "MOVE_FLAMETHROWER" + }, + { + "Level": "32", + "Move": "MOVE_SHADOW_BALL" + }, + { + "Level": "38", + "Move": "MOVE_FLAME_WHEEL" + }, + { + "Level": "44", + "Move": "MOVE_CURSE" + }, + { + "Level": "48", + "Move": "MOVE_HEAL_BLOCK" + }, + { + "Level": "52", + "Move": "MOVE_OVERHEAT" + } + ], + "TMMoves": [ + "MOVE_CALM_MIND", + "MOVE_DARK_PULSE", + "MOVE_DOUBLE_TEAM", + "MOVE_ENDURE", + "MOVE_ENERGY_BALL", + "MOVE_FIRE_BLAST", + "MOVE_FLARE_BLITZ", + "MOVE_GIGA_IMPACT", + "MOVE_HEAT_WAVE", + "MOVE_HYPER_BEAM", + "MOVE_PROTECT", + "MOVE_PSYCHIC", + "MOVE_SAFEGUARD", + "MOVE_SOLAR_BEAM", + "MOVE_SUBSTITUTE", + "MOVE_TAUNT" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "STUNFISK": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_WATER_GUN" + }, + { + "Level": "1", + "Move": "MOVE_THUNDER_SHOCK" + }, + { + "Level": "5", + "Move": "MOVE_ENDURE" + }, + { + "Level": "10", + "Move": "MOVE_MUD_SHOT" + }, + { + "Level": "15", + "Move": "MOVE_ROCK_TOMB" + }, + { + "Level": "20", + "Move": "MOVE_CHARGE" + }, + { + "Level": "25", + "Move": "MOVE_SPARK" + }, + { + "Level": "30", + "Move": "MOVE_EARTHQUAKE" + }, + { + "Level": "35", + "Move": "MOVE_DISCHARGE" + }, + { + "Level": "40", + "Move": "MOVE_BOUNCE" + }, + { + "Level": "45", + "Move": "MOVE_EERIE_IMPULSE" + }, + { + "Level": "50", + "Move": "MOVE_SLUDGE_WAVE" + } + ], + "TMMoves": [ + "MOVE_BULLDOZE", + "MOVE_CURSE", + "MOVE_DIG", + "MOVE_EARTH_POWER", + "MOVE_ELECTROWEB", + "MOVE_PROTECT", + "MOVE_ROCK_SLIDE", + "MOVE_SLUDGE_BOMB", + "MOVE_STEALTH_ROCK", + "MOVE_STONE_EDGE", + "MOVE_SUBSTITUTE", + "MOVE_SURF", + "MOVE_THUNDER", + "MOVE_THUNDERBOLT", + "MOVE_THUNDER_WAVE" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "STUNFISK_GALAR": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_WATER_GUN" + }, + { + "Level": "1", + "Move": "MOVE_SCREECH" + }, + { + "Level": "1", + "Move": "MOVE_METAL_CLAW" + }, + { + "Level": "5", + "Move": "MOVE_ENDURE" + }, + { + "Level": "10", + "Move": "MOVE_MUD_SHOT" + }, + { + "Level": "15", + "Move": "MOVE_ROCK_TOMB" + }, + { + "Level": "20", + "Move": "MOVE_METAL_SOUND" + }, + { + "Level": "25", + "Move": "MOVE_IRON_DEFENSE" + }, + { + "Level": "30", + "Move": "MOVE_EARTHQUAKE" + }, + { + "Level": "35", + "Move": "MOVE_BOUNCE" + }, + { + "Level": "40", + "Move": "MOVE_SLUDGE_WAVE" + }, + { + "Level": "45", + "Move": "MOVE_CRUNCH" + }, + { + "Level": "50", + "Move": "MOVE_STEALTH_ROCK" + } + ], + "TMMoves": [ + "MOVE_BULLDOZE", + "MOVE_CURSE", + "MOVE_DIG", + "MOVE_EARTH_POWER", + "MOVE_FLASH_CANNON", + "MOVE_ICE_FANG", + "MOVE_PROTECT", + "MOVE_ROCK_SLIDE", + "MOVE_SLUDGE_BOMB", + "MOVE_STONE_EDGE", + "MOVE_SUBSTITUTE", + "MOVE_SURF", + "MOVE_THUNDER_WAVE", + "MOVE_TOXIC" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "CHESPIN": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_VINE_WHIP" + }, + { + "Level": "1", + "Move": "MOVE_GROWL" + }, + { + "Level": "5", + "Move": "MOVE_GROWTH" + }, + { + "Level": "8", + "Move": "MOVE_ROLLOUT" + }, + { + "Level": "11", + "Move": "MOVE_BITE" + }, + { + "Level": "15", + "Move": "MOVE_LEECH_SEED" + }, + { + "Level": "18", + "Move": "MOVE_PIN_MISSILE" + }, + { + "Level": "27", + "Move": "MOVE_TAKE_DOWN" + }, + { + "Level": "35", + "Move": "MOVE_BRICK_BREAK" + }, + { + "Level": "42", + "Move": "MOVE_BODY_SLAM" + }, + { + "Level": "48", + "Move": "MOVE_WOOD_HAMMER" + } + ], + "TMMoves": [ + "MOVE_AERIAL_ACE", + "MOVE_BULLDOZE", + "MOVE_BULLET_SEED", + "MOVE_CURSE", + "MOVE_DIG", + "MOVE_ENDURE", + "MOVE_ENERGY_BALL", + "MOVE_GIGA_DRAIN", + "MOVE_HEADBUTT", + "MOVE_IRON_HEAD", + "MOVE_MUD_SHOT", + "MOVE_POISON_JAB", + "MOVE_PROTECT", + "MOVE_REFLECT", + "MOVE_ROAR", + "MOVE_ROCK_SLIDE", + "MOVE_ROCK_TOMB", + "MOVE_SHADOW_CLAW", + "MOVE_SOLAR_BEAM", + "MOVE_SPIKES", + "MOVE_SUBSTITUTE", + "MOVE_SWIFT", + "MOVE_THUNDER_PUNCH", + "MOVE_ZEN_HEADBUTT" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "QUILLADIN": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_VINE_WHIP" + }, + { + "Level": "1", + "Move": "MOVE_GROWL" + }, + { + "Level": "5", + "Move": "MOVE_GROWTH" + }, + { + "Level": "8", + "Move": "MOVE_ROLLOUT" + }, + { + "Level": "11", + "Move": "MOVE_BITE" + }, + { + "Level": "15", + "Move": "MOVE_LEECH_SEED" + }, + { + "Level": "18", + "Move": "MOVE_PIN_MISSILE" + }, + { + "Level": "27", + "Move": "MOVE_TAKE_DOWN" + }, + { + "Level": "35", + "Move": "MOVE_BRICK_BREAK" + }, + { + "Level": "42", + "Move": "MOVE_BODY_SLAM" + }, + { + "Level": "48", + "Move": "MOVE_WOOD_HAMMER" + } + ], + "TMMoves": [ + "MOVE_AERIAL_ACE", + "MOVE_BULK_UP", + "MOVE_BULLDOZE", + "MOVE_BULLET_SEED", + "MOVE_CURSE", + "MOVE_DIG", + "MOVE_ENDURE", + "MOVE_ENERGY_BALL", + "MOVE_GIGA_DRAIN", + "MOVE_HEADBUTT", + "MOVE_IRON_HEAD", + "MOVE_MUD_SHOT", + "MOVE_POISON_JAB", + "MOVE_PROTECT", + "MOVE_REFLECT", + "MOVE_ROAR", + "MOVE_ROCK_SLIDE", + "MOVE_ROCK_SMASH", + "MOVE_ROCK_TOMB", + "MOVE_SHADOW_CLAW", + "MOVE_SOLAR_BEAM", + "MOVE_SPIKES", + "MOVE_SUBSTITUTE", + "MOVE_SWIFT", + "MOVE_THUNDER_PUNCH", + "MOVE_ZEN_HEADBUTT" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "CHESNAUGHT": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_VINE_WHIP" + }, + { + "Level": "1", + "Move": "MOVE_GROWL" + }, + { + "Level": "5", + "Move": "MOVE_GROWTH" + }, + { + "Level": "8", + "Move": "MOVE_ROLLOUT" + }, + { + "Level": "11", + "Move": "MOVE_BITE" + }, + { + "Level": "15", + "Move": "MOVE_LEECH_SEED" + }, + { + "Level": "18", + "Move": "MOVE_PIN_MISSILE" + }, + { + "Level": "27", + "Move": "MOVE_TAKE_DOWN" + }, + { + "Level": "35", + "Move": "MOVE_BRICK_BREAK" + }, + { + "Level": "38", + "Move": "MOVE_BULK_UP" + }, + { + "Level": "42", + "Move": "MOVE_BODY_SLAM" + }, + { + "Level": "45", + "Move": "MOVE_CLOSE_COMBAT" + }, + { + "Level": "48", + "Move": "MOVE_WOOD_HAMMER" + }, + { + "Level": "55", + "Move": "MOVE_GIGA_IMPACT" + } + ], + "TMMoves": [ + "MOVE_AERIAL_ACE", + "MOVE_BULLDOZE", + "MOVE_BULLET_SEED", + "MOVE_CRUNCH", + "MOVE_CURSE", + "MOVE_DIG", + "MOVE_DOUBLE_EDGE", + "MOVE_DRAGON_CLAW", + "MOVE_EARTHQUAKE", + "MOVE_ENDURE", + "MOVE_ENERGY_BALL", + "MOVE_GIGA_DRAIN", + "MOVE_HEADBUTT", + "MOVE_HYPER_BEAM", + "MOVE_IRON_DEFENSE", + "MOVE_IRON_HEAD", + "MOVE_KNOCK_OFF", + "MOVE_MUD_SHOT", + "MOVE_POISON_JAB", + "MOVE_PROTECT", + "MOVE_REFLECT", + "MOVE_ROAR", + "MOVE_ROCK_SLIDE", + "MOVE_ROCK_SMASH", + "MOVE_ROCK_TOMB", + "MOVE_SHADOW_CLAW", + "MOVE_SOLAR_BEAM", + "MOVE_SPIKES", + "MOVE_STONE_EDGE", + "MOVE_SUBSTITUTE", + "MOVE_SWIFT", + "MOVE_SWORDS_DANCE", + "MOVE_THUNDER_PUNCH", + "MOVE_ZEN_HEADBUTT" + ], + "TutorMoves": [ + "MOVE_SPIKY_SHIELD" + ], + "EggMoves": [] + }, + "FENNEKIN": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_TAIL_WHIP" + }, + { + "Level": "5", + "Move": "MOVE_EMBER" + }, + { + "Level": "14", + "Move": "MOVE_CHARM" + }, + { + "Level": "17", + "Move": "MOVE_PSYBEAM" + }, + { + "Level": "20", + "Move": "MOVE_FIRE_SPIN" + }, + { + "Level": "25", + "Move": "MOVE_LIGHT_SCREEN" + }, + { + "Level": "31", + "Move": "MOVE_PSYSHOCK" + }, + { + "Level": "35", + "Move": "MOVE_FLAMETHROWER" + }, + { + "Level": "38", + "Move": "MOVE_WILL_O_WISP" + }, + { + "Level": "41", + "Move": "MOVE_PSYCHIC" + }, + { + "Level": "54", + "Move": "MOVE_FIRE_BLAST" + } + ], + "TMMoves": [ + "MOVE_AGILITY", + "MOVE_CALM_MIND", + "MOVE_ENDURE", + "MOVE_FLARE_BLITZ", + "MOVE_OVERHEAT", + "MOVE_PROTECT", + "MOVE_SOLAR_BEAM", + "MOVE_SUBSTITUTE", + "MOVE_SWIFT" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "BRAIXEN": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_TAIL_WHIP" + }, + { + "Level": "5", + "Move": "MOVE_EMBER" + }, + { + "Level": "14", + "Move": "MOVE_CHARM" + }, + { + "Level": "17", + "Move": "MOVE_PSYBEAM" + }, + { + "Level": "20", + "Move": "MOVE_FIRE_SPIN" + }, + { + "Level": "25", + "Move": "MOVE_LIGHT_SCREEN" + }, + { + "Level": "31", + "Move": "MOVE_PSYSHOCK" + }, + { + "Level": "35", + "Move": "MOVE_FLAMETHROWER" + }, + { + "Level": "38", + "Move": "MOVE_WILL_O_WISP" + }, + { + "Level": "41", + "Move": "MOVE_PSYCHIC" + }, + { + "Level": "46", + "Move": "MOVE_AGILITY" + }, + { + "Level": "54", + "Move": "MOVE_FIRE_BLAST" + } + ], + "TMMoves": [ + "MOVE_CALM_MIND", + "MOVE_ENDURE", + "MOVE_FIRE_PUNCH", + "MOVE_FLARE_BLITZ", + "MOVE_HEAT_WAVE", + "MOVE_OVERHEAT", + "MOVE_PROTECT", + "MOVE_SOLAR_BEAM", + "MOVE_SUBSTITUTE", + "MOVE_SWIFT", + "MOVE_THUNDER_PUNCH" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "DELPHOX": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_TAIL_WHIP" + }, + { + "Level": "5", + "Move": "MOVE_EMBER" + }, + { + "Level": "14", + "Move": "MOVE_CHARM" + }, + { + "Level": "17", + "Move": "MOVE_PSYBEAM" + }, + { + "Level": "20", + "Move": "MOVE_FIRE_SPIN" + }, + { + "Level": "25", + "Move": "MOVE_LIGHT_SCREEN" + }, + { + "Level": "31", + "Move": "MOVE_PSYSHOCK" + }, + { + "Level": "35", + "Move": "MOVE_FLAMETHROWER" + }, + { + "Level": "38", + "Move": "MOVE_WILL_O_WISP" + }, + { + "Level": "41", + "Move": "MOVE_PSYCHIC" + }, + { + "Level": "46", + "Move": "MOVE_AGILITY" + }, + { + "Level": "54", + "Move": "MOVE_FIRE_BLAST" + } + ], + "TMMoves": [ + "MOVE_CALM_MIND", + "MOVE_DAZZLING_GLEAM", + "MOVE_DOUBLE_TEAM", + "MOVE_ENDURE", + "MOVE_FIRE_PUNCH", + "MOVE_FLARE_BLITZ", + "MOVE_FOCUS_BLAST", + "MOVE_HEAL_BLOCK", + "MOVE_HEAT_WAVE", + "MOVE_HYPER_BEAM", + "MOVE_HYPER_VOICE", + "MOVE_METRONOME", + "MOVE_NASTY_PLOT", + "MOVE_OVERHEAT", + "MOVE_PROTECT", + "MOVE_REFLECT", + "MOVE_SAFEGUARD", + "MOVE_SOLAR_BEAM", + "MOVE_SUBSTITUTE", + "MOVE_SWIFT", + "MOVE_THUNDER_PUNCH", + "MOVE_ZEN_HEADBUTT" + ], + "TutorMoves": [ + "MOVE_FUTURE_SIGHT", + "MOVE_MYSTICAL_FIRE", + "MOVE_SHADOW_BALL" + ], + "EggMoves": [] + }, + "FROAKIE": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_GROWL" + }, + { + "Level": "5", + "Move": "MOVE_WATER_GUN" + }, + { + "Level": "8", + "Move": "MOVE_QUICK_ATTACK" + }, + { + "Level": "10", + "Move": "MOVE_LICK" + }, + { + "Level": "14", + "Move": "MOVE_BUBBLE_BEAM" + }, + { + "Level": "18", + "Move": "MOVE_SMOKESCREEN" + }, + { + "Level": "35", + "Move": "MOVE_SUBSTITUTE" + }, + { + "Level": "38", + "Move": "MOVE_NIGHT_SLASH" + }, + { + "Level": "43", + "Move": "MOVE_BOUNCE" + }, + { + "Level": "51", + "Move": "MOVE_DOUBLE_TEAM" + }, + { + "Level": "57", + "Move": "MOVE_HYDRO_PUMP" + } + ], + "TMMoves": [ + "MOVE_AERIAL_ACE", + "MOVE_BLIZZARD", + "MOVE_DIG", + "MOVE_ENDURE", + "MOVE_ICE_BEAM", + "MOVE_ICY_WIND", + "MOVE_LIQUIDATION", + "MOVE_PROTECT", + "MOVE_ROCK_SLIDE", + "MOVE_ROCK_TOMB", + "MOVE_SPIKES", + "MOVE_SURF", + "MOVE_SWIFT", + "MOVE_TAUNT", + "MOVE_TOXIC_SPIKES", + "MOVE_U_TURN", + "MOVE_WATERFALL", + "MOVE_WATER_PULSE" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "FROGADIER": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_GROWL" + }, + { + "Level": "5", + "Move": "MOVE_WATER_GUN" + }, + { + "Level": "8", + "Move": "MOVE_QUICK_ATTACK" + }, + { + "Level": "10", + "Move": "MOVE_LICK" + }, + { + "Level": "14", + "Move": "MOVE_BUBBLE_BEAM" + }, + { + "Level": "18", + "Move": "MOVE_SMOKESCREEN" + }, + { + "Level": "23", + "Move": "MOVE_AERIAL_ACE" + }, + { + "Level": "28", + "Move": "MOVE_SHADOW_SNEAK" + }, + { + "Level": "35", + "Move": "MOVE_SUBSTITUTE" + }, + { + "Level": "38", + "Move": "MOVE_NIGHT_SLASH" + }, + { + "Level": "43", + "Move": "MOVE_BOUNCE" + }, + { + "Level": "51", + "Move": "MOVE_DOUBLE_TEAM" + }, + { + "Level": "57", + "Move": "MOVE_HYDRO_PUMP" + } + ], + "TMMoves": [ + "MOVE_BLIZZARD", + "MOVE_BRICK_BREAK", + "MOVE_DARK_PULSE", + "MOVE_DIG", + "MOVE_ENDURE", + "MOVE_FLIP_TURN", + "MOVE_GUNK_SHOT", + "MOVE_HEADBUTT", + "MOVE_ICE_BEAM", + "MOVE_ICE_PUNCH", + "MOVE_ICY_WIND", + "MOVE_LIQUIDATION", + "MOVE_NASTY_PLOT", + "MOVE_PROTECT", + "MOVE_ROCK_SLIDE", + "MOVE_ROCK_TOMB", + "MOVE_SPIKES", + "MOVE_SURF", + "MOVE_SWIFT", + "MOVE_SWORDS_DANCE", + "MOVE_TAUNT", + "MOVE_TOXIC_SPIKES", + "MOVE_U_TURN", + "MOVE_WATERFALL", + "MOVE_WATER_PULSE" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "GRENINJA": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_GROWL" + }, + { + "Level": "5", + "Move": "MOVE_WATER_GUN" + }, + { + "Level": "8", + "Move": "MOVE_QUICK_ATTACK" + }, + { + "Level": "10", + "Move": "MOVE_LICK" + }, + { + "Level": "14", + "Move": "MOVE_BUBBLE_BEAM" + }, + { + "Level": "18", + "Move": "MOVE_SMOKESCREEN" + }, + { + "Level": "23", + "Move": "MOVE_AERIAL_ACE" + }, + { + "Level": "28", + "Move": "MOVE_SHADOW_SNEAK" + }, + { + "Level": "35", + "Move": "MOVE_SUBSTITUTE" + }, + { + "Level": "38", + "Move": "MOVE_NIGHT_SLASH" + }, + { + "Level": "43", + "Move": "MOVE_BOUNCE" + }, + { + "Level": "51", + "Move": "MOVE_DOUBLE_TEAM" + }, + { + "Level": "57", + "Move": "MOVE_HYDRO_PUMP" + } + ], + "TMMoves": [ + "MOVE_BLIZZARD", + "MOVE_BRICK_BREAK", + "MOVE_DARK_PULSE", + "MOVE_DIG", + "MOVE_ENDURE", + "MOVE_FLIP_TURN", + "MOVE_GIGA_IMPACT", + "MOVE_GUNK_SHOT", + "MOVE_HEADBUTT", + "MOVE_HYPER_BEAM", + "MOVE_ICE_BEAM", + "MOVE_ICE_PUNCH", + "MOVE_ICY_WIND", + "MOVE_LIQUIDATION", + "MOVE_NASTY_PLOT", + "MOVE_PROTECT", + "MOVE_PSYSHOCK", + "MOVE_ROCK_SLIDE", + "MOVE_ROCK_TOMB", + "MOVE_SPIKES", + "MOVE_SURF", + "MOVE_SWIFT", + "MOVE_SWORDS_DANCE", + "MOVE_TAUNT", + "MOVE_TOXIC_SPIKES", + "MOVE_U_TURN", + "MOVE_WATERFALL", + "MOVE_WATER_PULSE" + ], + "TutorMoves": [ + "MOVE_WATER_SHURIKEN" + ], + "EggMoves": [] + }, + "BUNNELBY": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_LEER" + }, + { + "Level": "7", + "Move": "MOVE_MUD_SHOT" + }, + { + "Level": "14", + "Move": "MOVE_QUICK_ATTACK" + }, + { + "Level": "24", + "Move": "MOVE_BRUTAL_SWING" + }, + { + "Level": "28", + "Move": "MOVE_DIG" + }, + { + "Level": "32", + "Move": "MOVE_BOUNCE" + }, + { + "Level": "36", + "Move": "MOVE_TAKE_DOWN" + }, + { + "Level": "40", + "Move": "MOVE_SUPER_FANG" + }, + { + "Level": "44", + "Move": "MOVE_EARTHQUAKE" + } + ], + "TMMoves": [ + "MOVE_AGILITY", + "MOVE_BRICK_BREAK", + "MOVE_BULK_UP", + "MOVE_BULLDOZE", + "MOVE_EARTH_POWER", + "MOVE_ENDURE", + "MOVE_HEADBUTT", + "MOVE_IRON_HEAD", + "MOVE_PROTECT", + "MOVE_ROCK_SLIDE", + "MOVE_ROCK_SMASH", + "MOVE_ROCK_TOMB", + "MOVE_SLUDGE_BOMB", + "MOVE_SPIKES", + "MOVE_STONE_EDGE", + "MOVE_SUBSTITUTE", + "MOVE_SURF", + "MOVE_SWORDS_DANCE", + "MOVE_U_TURN", + "MOVE_WILD_CHARGE" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "DIGGERSBY": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_LEER" + }, + { + "Level": "7", + "Move": "MOVE_MUD_SHOT" + }, + { + "Level": "14", + "Move": "MOVE_QUICK_ATTACK" + }, + { + "Level": "24", + "Move": "MOVE_BRUTAL_SWING" + }, + { + "Level": "28", + "Move": "MOVE_DIG" + }, + { + "Level": "32", + "Move": "MOVE_BOUNCE" + }, + { + "Level": "36", + "Move": "MOVE_TAKE_DOWN" + }, + { + "Level": "40", + "Move": "MOVE_SUPER_FANG" + }, + { + "Level": "44", + "Move": "MOVE_EARTHQUAKE" + } + ], + "TMMoves": [ + "MOVE_AGILITY", + "MOVE_BODY_SLAM", + "MOVE_BRICK_BREAK", + "MOVE_BULK_UP", + "MOVE_EARTH_POWER", + "MOVE_ENDURE", + "MOVE_FIRE_PUNCH", + "MOVE_GIGA_IMPACT", + "MOVE_GUNK_SHOT", + "MOVE_HEADBUTT", + "MOVE_HYPER_BEAM", + "MOVE_ICE_PUNCH", + "MOVE_IRON_HEAD", + "MOVE_PROTECT", + "MOVE_ROCK_SLIDE", + "MOVE_ROCK_SMASH", + "MOVE_ROCK_TOMB", + "MOVE_SLUDGE_BOMB", + "MOVE_SPIKES", + "MOVE_STONE_EDGE", + "MOVE_SUBSTITUTE", + "MOVE_SURF", + "MOVE_SWORDS_DANCE", + "MOVE_THUNDER_PUNCH", + "MOVE_U_TURN", + "MOVE_WILD_CHARGE" + ], + "TutorMoves": [ + "MOVE_BULLDOZE" + ], + "EggMoves": [] + }, + "FLETCHLING": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_GROWL" + }, + { + "Level": "1", + "Move": "MOVE_PECK" + }, + { + "Level": "8", + "Move": "MOVE_QUICK_ATTACK" + }, + { + "Level": "12", + "Move": "MOVE_EMBER" + }, + { + "Level": "16", + "Move": "MOVE_FEATHER_DANCE" + }, + { + "Level": "20", + "Move": "MOVE_WHIRLWIND" + }, + { + "Level": "25", + "Move": "MOVE_FLAME_WHEEL" + }, + { + "Level": "30", + "Move": "MOVE_STEEL_WING" + }, + { + "Level": "35", + "Move": "MOVE_AIR_SLASH" + }, + { + "Level": "40", + "Move": "MOVE_AGILITY" + }, + { + "Level": "45", + "Move": "MOVE_FLARE_BLITZ" + } + ], + "TMMoves": [ + "MOVE_AERIAL_ACE", + "MOVE_DOUBLE_TEAM", + "MOVE_ENDURE", + "MOVE_FLY", + "MOVE_HEAT_WAVE", + "MOVE_HURRICANE", + "MOVE_OVERHEAT", + "MOVE_PROTECT", + "MOVE_SUBSTITUTE", + "MOVE_SWIFT", + "MOVE_SWORDS_DANCE", + "MOVE_U_TURN", + "MOVE_WILL_O_WISP" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "FLETCHINDER": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_GROWL" + }, + { + "Level": "1", + "Move": "MOVE_PECK" + }, + { + "Level": "8", + "Move": "MOVE_QUICK_ATTACK" + }, + { + "Level": "12", + "Move": "MOVE_EMBER" + }, + { + "Level": "16", + "Move": "MOVE_FEATHER_DANCE" + }, + { + "Level": "20", + "Move": "MOVE_WHIRLWIND" + }, + { + "Level": "25", + "Move": "MOVE_FLAME_WHEEL" + }, + { + "Level": "30", + "Move": "MOVE_STEEL_WING" + }, + { + "Level": "35", + "Move": "MOVE_AIR_SLASH" + }, + { + "Level": "40", + "Move": "MOVE_AGILITY" + }, + { + "Level": "45", + "Move": "MOVE_FLARE_BLITZ" + } + ], + "TMMoves": [ + "MOVE_AERIAL_ACE", + "MOVE_DOUBLE_EDGE", + "MOVE_DOUBLE_TEAM", + "MOVE_ENDURE", + "MOVE_FIRE_BLAST", + "MOVE_FIRE_SPIN", + "MOVE_FLAMETHROWER", + "MOVE_FLY", + "MOVE_HEAT_WAVE", + "MOVE_HURRICANE", + "MOVE_OVERHEAT", + "MOVE_PROTECT", + "MOVE_SUBSTITUTE", + "MOVE_SWIFT", + "MOVE_SWORDS_DANCE", + "MOVE_U_TURN", + "MOVE_WILL_O_WISP" + ], + "TutorMoves": [ + "MOVE_WING_ATTACK" + ], + "EggMoves": [] + }, + "TALONFLAME": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_WING_ATTACK" + }, + { + "Level": "1", + "Move": "MOVE_GROWL" + }, + { + "Level": "1", + "Move": "MOVE_PECK" + }, + { + "Level": "8", + "Move": "MOVE_QUICK_ATTACK" + }, + { + "Level": "12", + "Move": "MOVE_EMBER" + }, + { + "Level": "16", + "Move": "MOVE_FEATHER_DANCE" + }, + { + "Level": "20", + "Move": "MOVE_WHIRLWIND" + }, + { + "Level": "25", + "Move": "MOVE_FLAME_WHEEL" + }, + { + "Level": "30", + "Move": "MOVE_STEEL_WING" + }, + { + "Level": "35", + "Move": "MOVE_AIR_SLASH" + }, + { + "Level": "40", + "Move": "MOVE_AGILITY" + }, + { + "Level": "45", + "Move": "MOVE_FLARE_BLITZ" + } + ], + "TMMoves": [ + "MOVE_AERIAL_ACE", + "MOVE_BULK_UP", + "MOVE_DOUBLE_EDGE", + "MOVE_DOUBLE_TEAM", + "MOVE_ENDURE", + "MOVE_FIRE_BLAST", + "MOVE_FIRE_SPIN", + "MOVE_FLAMETHROWER", + "MOVE_FLY", + "MOVE_GIGA_IMPACT", + "MOVE_HEAT_WAVE", + "MOVE_HURRICANE", + "MOVE_HYPER_BEAM", + "MOVE_OVERHEAT", + "MOVE_PROTECT", + "MOVE_SOLAR_BEAM", + "MOVE_SUBSTITUTE", + "MOVE_SWIFT", + "MOVE_SWORDS_DANCE", + "MOVE_U_TURN", + "MOVE_WILL_O_WISP" + ], + "TutorMoves": [ + "MOVE_BRAVE_BIRD" + ], + "EggMoves": [] + }, + "SCATTERBUG": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_STRING_SHOT" + }, + { + "Level": "7", + "Move": "MOVE_STUN_SPORE" + } + ], + "TMMoves": [ + "MOVE_PROTECT" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "SPEWPA": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_POISON_POWDER" + }, + { + "Level": "1", + "Move": "MOVE_STRING_SHOT" + }, + { + "Level": "1", + "Move": "MOVE_HARDEN" + }, + { + "Level": "7", + "Move": "MOVE_STUN_SPORE" + }, + { + "Level": "10", + "Move": "MOVE_INFESTATION" + } + ], + "TMMoves": [ + "MOVE_IRON_DEFENSE" + ], + "TutorMoves": [ + "MOVE_PROTECT" + ], + "EggMoves": [] + }, + "VIVILLON": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_POISON_POWDER" + }, + { + "Level": "1", + "Move": "MOVE_STUN_SPORE" + }, + { + "Level": "1", + "Move": "MOVE_SLEEP_POWDER" + }, + { + "Level": "10", + "Move": "MOVE_INFESTATION" + }, + { + "Level": "12", + "Move": "MOVE_LIGHT_SCREEN" + }, + { + "Level": "15", + "Move": "MOVE_DRAINING_KISS" + }, + { + "Level": "17", + "Move": "MOVE_SUPERSONIC" + }, + { + "Level": "21", + "Move": "MOVE_PSYBEAM" + }, + { + "Level": "25", + "Move": "MOVE_U_TURN" + }, + { + "Level": "28", + "Move": "MOVE_AIR_SLASH" + }, + { + "Level": "35", + "Move": "MOVE_BUG_BUZZ" + }, + { + "Level": "40", + "Move": "MOVE_SAFEGUARD" + }, + { + "Level": "40", + "Move": "MOVE_HURRICANE" + }, + { + "Level": "45", + "Move": "MOVE_WHIRLWIND" + } + ], + "TMMoves": [ + "MOVE_DAZZLING_GLEAM", + "MOVE_ENDURE", + "MOVE_ENERGY_BALL", + "MOVE_GIGA_DRAIN", + "MOVE_GIGA_IMPACT", + "MOVE_HYPER_BEAM", + "MOVE_IRON_DEFENSE", + "MOVE_PSYCHIC", + "MOVE_SOLAR_BEAM", + "MOVE_SUBSTITUTE", + "MOVE_SWIFT" + ], + "TutorMoves": [ + "MOVE_GUST", + "MOVE_HARDEN", + "MOVE_PROTECT", + "MOVE_STRING_SHOT", + "MOVE_TACKLE" + ], + "EggMoves": [] + }, + "LITLEO": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_LEER" + }, + { + "Level": "5", + "Move": "MOVE_EMBER" + }, + { + "Level": "6", + "Move": "MOVE_ROAR" + }, + { + "Level": "8", + "Move": "MOVE_WORK_UP" + }, + { + "Level": "11", + "Move": "MOVE_HEADBUTT" + }, + { + "Level": "16", + "Move": "MOVE_SNARL" + }, + { + "Level": "20", + "Move": "MOVE_TAKE_DOWN" + }, + { + "Level": "23", + "Move": "MOVE_FIRE_FANG" + }, + { + "Level": "28", + "Move": "MOVE_EARTH_POWER" + }, + { + "Level": "32", + "Move": "MOVE_FLAMETHROWER" + }, + { + "Level": "36", + "Move": "MOVE_CRUNCH" + }, + { + "Level": "42", + "Move": "MOVE_HYPER_VOICE" + } + ], + "TMMoves": [ + "MOVE_BODY_SLAM", + "MOVE_DIG", + "MOVE_DOUBLE_EDGE", + "MOVE_ENDURE", + "MOVE_FIRE_BLAST", + "MOVE_FIRE_SPIN", + "MOVE_FLARE_BLITZ", + "MOVE_HEAT_WAVE", + "MOVE_OVERHEAT", + "MOVE_PROTECT", + "MOVE_SOLAR_BEAM", + "MOVE_SUBSTITUTE", + "MOVE_SWIFT", + "MOVE_TAUNT", + "MOVE_THUNDER_FANG", + "MOVE_WILD_CHARGE", + "MOVE_WILL_O_WISP" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "PYROAR": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_LEER" + }, + { + "Level": "1", + "Move": "MOVE_EMBER" + }, + { + "Level": "6", + "Move": "MOVE_ROAR" + }, + { + "Level": "8", + "Move": "MOVE_WORK_UP" + }, + { + "Level": "11", + "Move": "MOVE_HEADBUTT" + }, + { + "Level": "16", + "Move": "MOVE_SNARL" + }, + { + "Level": "20", + "Move": "MOVE_TAKE_DOWN" + }, + { + "Level": "23", + "Move": "MOVE_FIRE_FANG" + }, + { + "Level": "28", + "Move": "MOVE_EARTH_POWER" + }, + { + "Level": "32", + "Move": "MOVE_FLAMETHROWER" + }, + { + "Level": "36", + "Move": "MOVE_CRUNCH" + }, + { + "Level": "42", + "Move": "MOVE_HYPER_VOICE" + } + ], + "TMMoves": [ + "MOVE_BODY_SLAM", + "MOVE_DARK_PULSE", + "MOVE_DIG", + "MOVE_DOUBLE_EDGE", + "MOVE_ENDURE", + "MOVE_FIRE_BLAST", + "MOVE_FIRE_SPIN", + "MOVE_FLARE_BLITZ", + "MOVE_GIGA_IMPACT", + "MOVE_HEAT_WAVE", + "MOVE_PROTECT", + "MOVE_SOLAR_BEAM", + "MOVE_SUBSTITUTE", + "MOVE_SWIFT", + "MOVE_TAUNT", + "MOVE_THUNDER_FANG", + "MOVE_WILD_CHARGE", + "MOVE_WILL_O_WISP" + ], + "TutorMoves": [ + "MOVE_HYPER_BEAM", + "MOVE_OVERHEAT" + ], + "EggMoves": [] + }, + "FLAB\u00c9B\u00c9": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_VINE_WHIP" + }, + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "6", + "Move": "MOVE_FAIRY_WIND" + }, + { + "Level": "10", + "Move": "MOVE_SAFEGUARD" + }, + { + "Level": "15", + "Move": "MOVE_RAZOR_LEAF" + }, + { + "Level": "18", + "Move": "MOVE_DRAINING_KISS" + }, + { + "Level": "20", + "Move": "MOVE_WISH" + }, + { + "Level": "22", + "Move": "MOVE_MAGICAL_LEAF" + }, + { + "Level": "26", + "Move": "MOVE_CHARM" + }, + { + "Level": "33", + "Move": "MOVE_SYNTHESIS" + }, + { + "Level": "40", + "Move": "MOVE_ENERGY_BALL" + }, + { + "Level": "54", + "Move": "MOVE_SOLAR_BEAM" + } + ], + "TMMoves": [ + "MOVE_CALM_MIND", + "MOVE_DAZZLING_GLEAM", + "MOVE_DOUBLE_TEAM", + "MOVE_ENDURE", + "MOVE_GIGA_DRAIN", + "MOVE_LIGHT_SCREEN", + "MOVE_PROTECT", + "MOVE_PSYCHIC", + "MOVE_SUBSTITUTE", + "MOVE_SWIFT" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "FLOETTE": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_VINE_WHIP" + }, + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_FAIRY_WIND" + }, + { + "Level": "10", + "Move": "MOVE_SAFEGUARD" + }, + { + "Level": "15", + "Move": "MOVE_RAZOR_LEAF" + }, + { + "Level": "18", + "Move": "MOVE_DRAINING_KISS" + }, + { + "Level": "20", + "Move": "MOVE_WISH" + }, + { + "Level": "22", + "Move": "MOVE_MAGICAL_LEAF" + }, + { + "Level": "26", + "Move": "MOVE_CHARM" + }, + { + "Level": "33", + "Move": "MOVE_SYNTHESIS" + }, + { + "Level": "40", + "Move": "MOVE_ENERGY_BALL" + }, + { + "Level": "54", + "Move": "MOVE_SOLAR_BEAM" + } + ], + "TMMoves": [ + "MOVE_CALM_MIND", + "MOVE_DAZZLING_GLEAM", + "MOVE_DOUBLE_TEAM", + "MOVE_ENDURE", + "MOVE_GIGA_DRAIN", + "MOVE_LIGHT_SCREEN", + "MOVE_METRONOME", + "MOVE_PROTECT", + "MOVE_PSYCHIC", + "MOVE_SUBSTITUTE", + "MOVE_SWIFT" + ], + "TutorMoves": [ + "MOVE_MOONBLAST" + ], + "EggMoves": [] + }, + "FLOETTE_ETERNAL": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_VINE_WHIP" + }, + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_FAIRY_WIND" + }, + { + "Level": "10", + "Move": "MOVE_SAFEGUARD" + }, + { + "Level": "15", + "Move": "MOVE_RAZOR_LEAF" + }, + { + "Level": "18", + "Move": "MOVE_DRAINING_KISS" + }, + { + "Level": "20", + "Move": "MOVE_WISH" + }, + { + "Level": "22", + "Move": "MOVE_MAGICAL_LEAF" + }, + { + "Level": "26", + "Move": "MOVE_CHARM" + }, + { + "Level": "33", + "Move": "MOVE_SYNTHESIS" + }, + { + "Level": "40", + "Move": "MOVE_ENERGY_BALL" + }, + { + "Level": "50", + "Move": "MOVE_LIGHT_OF_RUIN" + }, + { + "Level": "54", + "Move": "MOVE_SOLAR_BEAM" + } + ], + "TMMoves": [ + "MOVE_CALM_MIND", + "MOVE_DAZZLING_GLEAM", + "MOVE_DOUBLE_TEAM", + "MOVE_ENDURE", + "MOVE_GIGA_DRAIN", + "MOVE_HYPER_BEAM", + "MOVE_LIGHT_SCREEN", + "MOVE_METRONOME", + "MOVE_PROTECT", + "MOVE_PSYCHIC", + "MOVE_SUBSTITUTE", + "MOVE_SWIFT" + ], + "TutorMoves": [ + "MOVE_MOONBLAST" + ], + "EggMoves": [] + }, + "FLORGES": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_VINE_WHIP" + }, + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_FAIRY_WIND" + }, + { + "Level": "1", + "Move": "MOVE_MOONBLAST" + }, + { + "Level": "10", + "Move": "MOVE_SAFEGUARD" + }, + { + "Level": "15", + "Move": "MOVE_RAZOR_LEAF" + }, + { + "Level": "18", + "Move": "MOVE_DRAINING_KISS" + }, + { + "Level": "20", + "Move": "MOVE_WISH" + }, + { + "Level": "22", + "Move": "MOVE_MAGICAL_LEAF" + }, + { + "Level": "26", + "Move": "MOVE_CHARM" + }, + { + "Level": "33", + "Move": "MOVE_SYNTHESIS" + }, + { + "Level": "40", + "Move": "MOVE_ENERGY_BALL" + }, + { + "Level": "54", + "Move": "MOVE_SOLAR_BEAM" + } + ], + "TMMoves": [ + "MOVE_CALM_MIND", + "MOVE_DAZZLING_GLEAM", + "MOVE_DOUBLE_TEAM", + "MOVE_ENDURE", + "MOVE_GIGA_DRAIN", + "MOVE_HYPER_BEAM", + "MOVE_LIGHT_SCREEN", + "MOVE_METRONOME", + "MOVE_PROTECT", + "MOVE_PSYCHIC", + "MOVE_SUBSTITUTE", + "MOVE_SWIFT" + ], + "TutorMoves": [ + "MOVE_DISARMING_VOICE" + ], + "EggMoves": [] + }, + "SKIDDO": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_GROWTH" + }, + { + "Level": "7", + "Move": "MOVE_VINE_WHIP" + }, + { + "Level": "9", + "Move": "MOVE_TAIL_WHIP" + }, + { + "Level": "12", + "Move": "MOVE_LEECH_SEED" + }, + { + "Level": "13", + "Move": "MOVE_RAZOR_LEAF" + }, + { + "Level": "16", + "Move": "MOVE_MUD_SHOT" + }, + { + "Level": "20", + "Move": "MOVE_SYNTHESIS" + }, + { + "Level": "22", + "Move": "MOVE_TAKE_DOWN" + }, + { + "Level": "26", + "Move": "MOVE_BULLDOZE" + }, + { + "Level": "34", + "Move": "MOVE_HORN_LEECH" + }, + { + "Level": "38", + "Move": "MOVE_BULK_UP" + }, + { + "Level": "42", + "Move": "MOVE_DOUBLE_EDGE" + }, + { + "Level": "45", + "Move": "MOVE_LEAF_BLADE" + }, + { + "Level": "50", + "Move": "MOVE_MEGAHORN" + } + ], + "TMMoves": [ + "MOVE_BODY_SLAM", + "MOVE_BRICK_BREAK", + "MOVE_BULLET_SEED", + "MOVE_DIG", + "MOVE_ENDURE", + "MOVE_ENERGY_BALL", + "MOVE_GIGA_DRAIN", + "MOVE_LEAF_STORM", + "MOVE_MAGICAL_LEAF", + "MOVE_PLAY_ROUGH", + "MOVE_PROTECT", + "MOVE_ROAR", + "MOVE_ROCK_SLIDE", + "MOVE_SOLAR_BEAM", + "MOVE_SUBSTITUTE", + "MOVE_SURF", + "MOVE_WILD_CHARGE", + "MOVE_ZEN_HEADBUTT" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "GOGOAT": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_GROWTH" + }, + { + "Level": "7", + "Move": "MOVE_VINE_WHIP" + }, + { + "Level": "9", + "Move": "MOVE_TAIL_WHIP" + }, + { + "Level": "12", + "Move": "MOVE_LEECH_SEED" + }, + { + "Level": "13", + "Move": "MOVE_RAZOR_LEAF" + }, + { + "Level": "16", + "Move": "MOVE_MUD_SHOT" + }, + { + "Level": "20", + "Move": "MOVE_SYNTHESIS" + }, + { + "Level": "22", + "Move": "MOVE_TAKE_DOWN" + }, + { + "Level": "26", + "Move": "MOVE_BULLDOZE" + }, + { + "Level": "34", + "Move": "MOVE_HORN_LEECH" + }, + { + "Level": "38", + "Move": "MOVE_BULK_UP" + }, + { + "Level": "42", + "Move": "MOVE_DOUBLE_EDGE" + }, + { + "Level": "45", + "Move": "MOVE_LEAF_BLADE" + }, + { + "Level": "50", + "Move": "MOVE_MEGAHORN" + }, + { + "Level": "55", + "Move": "MOVE_EARTHQUAKE" + } + ], + "TMMoves": [ + "MOVE_BODY_SLAM", + "MOVE_BRICK_BREAK", + "MOVE_BULLET_SEED", + "MOVE_DIG", + "MOVE_ENDURE", + "MOVE_ENERGY_BALL", + "MOVE_GIGA_DRAIN", + "MOVE_GIGA_IMPACT", + "MOVE_HYPER_BEAM", + "MOVE_LEAF_STORM", + "MOVE_MAGICAL_LEAF", + "MOVE_PLAY_ROUGH", + "MOVE_PROTECT", + "MOVE_ROAR", + "MOVE_ROCK_SLIDE", + "MOVE_SOLAR_BEAM", + "MOVE_SUBSTITUTE", + "MOVE_SURF", + "MOVE_WILD_CHARGE", + "MOVE_ZEN_HEADBUTT" + ], + "TutorMoves": [ + "MOVE_AERIAL_ACE" + ], + "EggMoves": [] + }, + "PANCHAM": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_LEER" + }, + { + "Level": "8", + "Move": "MOVE_TAUNT" + }, + { + "Level": "15", + "Move": "MOVE_BRICK_BREAK" + }, + { + "Level": "20", + "Move": "MOVE_WORK_UP" + }, + { + "Level": "24", + "Move": "MOVE_SLASH" + }, + { + "Level": "28", + "Move": "MOVE_DETECT" + }, + { + "Level": "30", + "Move": "MOVE_PARTING_SHOT" + }, + { + "Level": "34", + "Move": "MOVE_CRUNCH" + }, + { + "Level": "44", + "Move": "MOVE_BODY_SLAM" + } + ], + "TMMoves": [ + "MOVE_BULK_UP", + "MOVE_BULLDOZE", + "MOVE_DIG", + "MOVE_ENDURE", + "MOVE_FIRE_PUNCH", + "MOVE_HYPER_VOICE", + "MOVE_ICE_PUNCH", + "MOVE_PROTECT", + "MOVE_ROCK_SLIDE", + "MOVE_ROCK_TOMB", + "MOVE_SHADOW_CLAW", + "MOVE_SLUDGE_BOMB", + "MOVE_STONE_EDGE", + "MOVE_SUBSTITUTE", + "MOVE_SURF", + "MOVE_SWORDS_DANCE", + "MOVE_THUNDER_PUNCH" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "PANGORO": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_LEER" + }, + { + "Level": "1", + "Move": "MOVE_TAUNT" + }, + { + "Level": "1", + "Move": "MOVE_BULLET_PUNCH" + }, + { + "Level": "15", + "Move": "MOVE_BRICK_BREAK" + }, + { + "Level": "20", + "Move": "MOVE_WORK_UP" + }, + { + "Level": "24", + "Move": "MOVE_SLASH" + }, + { + "Level": "28", + "Move": "MOVE_DETECT" + }, + { + "Level": "30", + "Move": "MOVE_PARTING_SHOT" + }, + { + "Level": "34", + "Move": "MOVE_BRUTAL_SWING" + }, + { + "Level": "38", + "Move": "MOVE_CRUNCH" + }, + { + "Level": "44", + "Move": "MOVE_BODY_SLAM" + }, + { + "Level": "50", + "Move": "MOVE_OUTRAGE" + }, + { + "Level": "54", + "Move": "MOVE_FOCUS_ENERGY" + }, + { + "Level": "58", + "Move": "MOVE_CLOSE_COMBAT" + } + ], + "TMMoves": [ + "MOVE_BULK_UP", + "MOVE_BULLDOZE", + "MOVE_DARK_PULSE", + "MOVE_DIG", + "MOVE_DRAGON_CLAW", + "MOVE_EARTHQUAKE", + "MOVE_ENDURE", + "MOVE_FIRE_PUNCH", + "MOVE_FOCUS_BLAST", + "MOVE_GIGA_DRAIN", + "MOVE_GIGA_IMPACT", + "MOVE_GUNK_SHOT", + "MOVE_HYPER_BEAM", + "MOVE_HYPER_VOICE", + "MOVE_ICE_PUNCH", + "MOVE_IRON_HEAD", + "MOVE_KNOCK_OFF", + "MOVE_POISON_JAB", + "MOVE_POWER_UP_PUNCH", + "MOVE_PROTECT", + "MOVE_ROCK_SLIDE", + "MOVE_ROCK_SMASH", + "MOVE_ROCK_TOMB", + "MOVE_SHADOW_CLAW", + "MOVE_SLUDGE_BOMB", + "MOVE_STONE_EDGE", + "MOVE_SUBSTITUTE", + "MOVE_SURF", + "MOVE_SWORDS_DANCE", + "MOVE_THUNDER_PUNCH", + "MOVE_ZEN_HEADBUTT" + ], + "TutorMoves": [ + "MOVE_NIGHT_SLASH" + ], + "EggMoves": [] + }, + "FURFROU": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_HEADBUTT" + }, + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_GROWL" + }, + { + "Level": "8", + "Move": "MOVE_TAIL_WHIP" + }, + { + "Level": "13", + "Move": "MOVE_BITE" + }, + { + "Level": "16", + "Move": "MOVE_TAKE_DOWN" + }, + { + "Level": "20", + "Move": "MOVE_ROAR" + }, + { + "Level": "22", + "Move": "MOVE_COTTON_GUARD" + }, + { + "Level": "25", + "Move": "MOVE_CHARM" + }, + { + "Level": "28", + "Move": "MOVE_CRUNCH" + }, + { + "Level": "30", + "Move": "MOVE_SNARL" + }, + { + "Level": "36", + "Move": "MOVE_DOUBLE_EDGE" + }, + { + "Level": "43", + "Move": "MOVE_HYPER_VOICE" + } + ], + "TMMoves": [ + "MOVE_DARK_PULSE", + "MOVE_DIG", + "MOVE_DOUBLE_TEAM", + "MOVE_ENDURE", + "MOVE_FIRE_FANG", + "MOVE_GIGA_IMPACT", + "MOVE_HYPER_BEAM", + "MOVE_ICE_FANG", + "MOVE_IRON_TAIL", + "MOVE_PROTECT", + "MOVE_ROCK_SMASH", + "MOVE_SUBSTITUTE", + "MOVE_SURF", + "MOVE_THUNDER_FANG", + "MOVE_THUNDER_WAVE", + "MOVE_U_TURN", + "MOVE_WILD_CHARGE", + "MOVE_WORK_UP", + "MOVE_ZEN_HEADBUTT" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "ESPURR": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_LEER" + }, + { + "Level": "6", + "Move": "MOVE_DISARMING_VOICE" + }, + { + "Level": "9", + "Move": "MOVE_CONFUSION" + }, + { + "Level": "13", + "Move": "MOVE_FAKE_TEARS" + }, + { + "Level": "15", + "Move": "MOVE_SWIFT" + }, + { + "Level": "21", + "Move": "MOVE_PSYBEAM" + }, + { + "Level": "30", + "Move": "MOVE_LIGHT_SCREEN" + }, + { + "Level": "30", + "Move": "MOVE_REFLECT" + }, + { + "Level": "36", + "Move": "MOVE_PSYSHOCK" + } + ], + "TMMoves": [ + "MOVE_CALM_MIND", + "MOVE_DARK_PULSE", + "MOVE_ENDURE", + "MOVE_ENERGY_BALL", + "MOVE_NASTY_PLOT", + "MOVE_PLAY_ROUGH", + "MOVE_PROTECT", + "MOVE_PSYCHIC", + "MOVE_SAFEGUARD", + "MOVE_SHADOW_BALL", + "MOVE_SUBSTITUTE", + "MOVE_THUNDERBOLT", + "MOVE_THUNDER_WAVE", + "MOVE_WORK_UP", + "MOVE_ZEN_HEADBUTT" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "MEOWSTIC_M": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_LEER" + }, + { + "Level": "6", + "Move": "MOVE_DISARMING_VOICE" + }, + { + "Level": "9", + "Move": "MOVE_CONFUSION" + }, + { + "Level": "13", + "Move": "MOVE_FAKE_TEARS" + }, + { + "Level": "15", + "Move": "MOVE_SWIFT" + }, + { + "Level": "18", + "Move": "MOVE_CHARM" + }, + { + "Level": "21", + "Move": "MOVE_PSYBEAM" + }, + { + "Level": "30", + "Move": "MOVE_LIGHT_SCREEN" + }, + { + "Level": "30", + "Move": "MOVE_REFLECT" + }, + { + "Level": "36", + "Move": "MOVE_PSYSHOCK" + }, + { + "Level": "44", + "Move": "MOVE_PSYCHIC" + }, + { + "Level": "46", + "Move": "MOVE_HEAL_BLOCK" + }, + { + "Level": "50", + "Move": "MOVE_WISH" + } + ], + "TMMoves": [ + "MOVE_CALM_MIND", + "MOVE_DARK_PULSE", + "MOVE_DIG", + "MOVE_DOUBLE_TEAM", + "MOVE_ENDURE", + "MOVE_ENERGY_BALL", + "MOVE_GIGA_IMPACT", + "MOVE_HYPER_BEAM", + "MOVE_NASTY_PLOT", + "MOVE_PLAY_ROUGH", + "MOVE_PROTECT", + "MOVE_SAFEGUARD", + "MOVE_SHADOW_BALL", + "MOVE_SPIKES", + "MOVE_STEALTH_ROCK", + "MOVE_SUBSTITUTE", + "MOVE_TAUNT", + "MOVE_THUNDERBOLT", + "MOVE_THUNDER_WAVE", + "MOVE_TOXIC_SPIKES", + "MOVE_WORK_UP", + "MOVE_ZEN_HEADBUTT" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "MEOWSTIC_F": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_LEER" + }, + { + "Level": "1", + "Move": "MOVE_MAGICAL_LEAF" + }, + { + "Level": "1", + "Move": "MOVE_DISARMING_VOICE" + }, + { + "Level": "9", + "Move": "MOVE_CONFUSION" + }, + { + "Level": "13", + "Move": "MOVE_FAKE_TEARS" + }, + { + "Level": "15", + "Move": "MOVE_SWIFT" + }, + { + "Level": "21", + "Move": "MOVE_PSYBEAM" + }, + { + "Level": "24", + "Move": "MOVE_DARK_PULSE" + }, + { + "Level": "30", + "Move": "MOVE_LIGHT_SCREEN" + }, + { + "Level": "30", + "Move": "MOVE_REFLECT" + }, + { + "Level": "36", + "Move": "MOVE_PSYSHOCK" + }, + { + "Level": "40", + "Move": "MOVE_SHADOW_BALL" + }, + { + "Level": "44", + "Move": "MOVE_PSYCHIC" + }, + { + "Level": "50", + "Move": "MOVE_FUTURE_SIGHT" + } + ], + "TMMoves": [ + "MOVE_CALM_MIND", + "MOVE_DIG", + "MOVE_EARTH_POWER", + "MOVE_ENDURE", + "MOVE_ENERGY_BALL", + "MOVE_GIGA_IMPACT", + "MOVE_HYPER_BEAM", + "MOVE_NASTY_PLOT", + "MOVE_PLAY_ROUGH", + "MOVE_PROTECT", + "MOVE_SAFEGUARD", + "MOVE_SUBSTITUTE", + "MOVE_THUNDERBOLT", + "MOVE_THUNDER_WAVE", + "MOVE_WATER_PULSE", + "MOVE_WORK_UP", + "MOVE_ZEN_HEADBUTT" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "HONEDGE": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_SCREECH" + }, + { + "Level": "4", + "Move": "MOVE_SHADOW_SNEAK" + }, + { + "Level": "12", + "Move": "MOVE_AERIAL_ACE" + }, + { + "Level": "16", + "Move": "MOVE_METAL_SOUND" + }, + { + "Level": "20", + "Move": "MOVE_SLASH" + }, + { + "Level": "22", + "Move": "MOVE_PSYCHO_CUT" + }, + { + "Level": "24", + "Move": "MOVE_SHADOW_CLAW" + }, + { + "Level": "32", + "Move": "MOVE_IRON_DEFENSE" + }, + { + "Level": "38", + "Move": "MOVE_IRON_HEAD" + }, + { + "Level": "44", + "Move": "MOVE_SWORDS_DANCE" + } + ], + "TMMoves": [ + "MOVE_BRICK_BREAK", + "MOVE_CLOSE_COMBAT", + "MOVE_FLASH_CANNON", + "MOVE_HEADBUTT", + "MOVE_NIGHT_SLASH", + "MOVE_PROTECT", + "MOVE_REFLECT", + "MOVE_ROCK_SLIDE", + "MOVE_SUBSTITUTE" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "DOUBLADE": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_SCREECH" + }, + { + "Level": "4", + "Move": "MOVE_SHADOW_SNEAK" + }, + { + "Level": "12", + "Move": "MOVE_AERIAL_ACE" + }, + { + "Level": "16", + "Move": "MOVE_METAL_SOUND" + }, + { + "Level": "20", + "Move": "MOVE_SLASH" + }, + { + "Level": "22", + "Move": "MOVE_PSYCHO_CUT" + }, + { + "Level": "24", + "Move": "MOVE_SHADOW_CLAW" + }, + { + "Level": "32", + "Move": "MOVE_IRON_DEFENSE" + }, + { + "Level": "38", + "Move": "MOVE_IRON_HEAD" + }, + { + "Level": "44", + "Move": "MOVE_SWORDS_DANCE" + } + ], + "TMMoves": [ + "MOVE_BRICK_BREAK", + "MOVE_CLOSE_COMBAT", + "MOVE_ENDURE", + "MOVE_FLASH_CANNON", + "MOVE_HEADBUTT", + "MOVE_NIGHT_SLASH", + "MOVE_PROTECT", + "MOVE_REFLECT", + "MOVE_ROCK_SLIDE", + "MOVE_SUBSTITUTE", + "MOVE_ZEN_HEADBUTT" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "AEGISLASH": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_SCREECH" + }, + { + "Level": "4", + "Move": "MOVE_SHADOW_SNEAK" + }, + { + "Level": "12", + "Move": "MOVE_AERIAL_ACE" + }, + { + "Level": "16", + "Move": "MOVE_METAL_SOUND" + }, + { + "Level": "20", + "Move": "MOVE_SLASH" + }, + { + "Level": "22", + "Move": "MOVE_PSYCHO_CUT" + }, + { + "Level": "24", + "Move": "MOVE_SHADOW_CLAW" + }, + { + "Level": "32", + "Move": "MOVE_IRON_DEFENSE" + }, + { + "Level": "38", + "Move": "MOVE_IRON_HEAD" + }, + { + "Level": "44", + "Move": "MOVE_SWORDS_DANCE" + }, + { + "Level": "50", + "Move": "MOVE_HEAD_SMASH" + } + ], + "TMMoves": [ + "MOVE_BRICK_BREAK", + "MOVE_CLOSE_COMBAT", + "MOVE_ENDURE", + "MOVE_FLASH_CANNON", + "MOVE_GIGA_IMPACT", + "MOVE_HEADBUTT", + "MOVE_HYPER_BEAM", + "MOVE_NIGHT_SLASH", + "MOVE_PROTECT", + "MOVE_REFLECT", + "MOVE_ROCK_SLIDE", + "MOVE_SHADOW_BALL", + "MOVE_SUBSTITUTE", + "MOVE_ZEN_HEADBUTT" + ], + "TutorMoves": [ + "MOVE_KINGS_SHIELD" + ], + "EggMoves": [] + }, + "SPRITZEE": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_FAIRY_WIND" + }, + { + "Level": "8", + "Move": "MOVE_FAKE_TEARS" + }, + { + "Level": "10", + "Move": "MOVE_DISARMING_VOICE" + }, + { + "Level": "15", + "Move": "MOVE_DRAINING_KISS" + }, + { + "Level": "22", + "Move": "MOVE_WISH" + }, + { + "Level": "24", + "Move": "MOVE_PSYBEAM" + }, + { + "Level": "27", + "Move": "MOVE_DAZZLING_GLEAM" + }, + { + "Level": "30", + "Move": "MOVE_CHARM" + }, + { + "Level": "33", + "Move": "MOVE_CALM_MIND" + }, + { + "Level": "36", + "Move": "MOVE_MOONBLAST" + }, + { + "Level": "40", + "Move": "MOVE_PSYCHIC" + }, + { + "Level": "44", + "Move": "MOVE_HEAL_BLOCK" + }, + { + "Level": "48", + "Move": "MOVE_HYPNOSIS" + } + ], + "TMMoves": [ + "MOVE_ENDURE", + "MOVE_ENERGY_BALL", + "MOVE_FLASH_CANNON", + "MOVE_LIGHT_SCREEN", + "MOVE_NASTY_PLOT", + "MOVE_PROTECT", + "MOVE_REFLECT", + "MOVE_SUBSTITUTE", + "MOVE_THUNDERBOLT" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "AROMATISSE": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_FAIRY_WIND" + }, + { + "Level": "8", + "Move": "MOVE_FAKE_TEARS" + }, + { + "Level": "10", + "Move": "MOVE_DISARMING_VOICE" + }, + { + "Level": "15", + "Move": "MOVE_DRAINING_KISS" + }, + { + "Level": "22", + "Move": "MOVE_WISH" + }, + { + "Level": "24", + "Move": "MOVE_PSYBEAM" + }, + { + "Level": "27", + "Move": "MOVE_DAZZLING_GLEAM" + }, + { + "Level": "30", + "Move": "MOVE_CHARM" + }, + { + "Level": "33", + "Move": "MOVE_CALM_MIND" + }, + { + "Level": "36", + "Move": "MOVE_MOONBLAST" + }, + { + "Level": "40", + "Move": "MOVE_PSYCHIC" + }, + { + "Level": "44", + "Move": "MOVE_HEAL_BLOCK" + }, + { + "Level": "48", + "Move": "MOVE_HYPNOSIS" + } + ], + "TMMoves": [ + "MOVE_ENDURE", + "MOVE_ENERGY_BALL", + "MOVE_FLASH_CANNON", + "MOVE_GIGA_IMPACT", + "MOVE_HYPER_BEAM", + "MOVE_LIGHT_SCREEN", + "MOVE_METRONOME", + "MOVE_NASTY_PLOT", + "MOVE_PROTECT", + "MOVE_PSYSHOCK", + "MOVE_REFLECT", + "MOVE_SUBSTITUTE", + "MOVE_THUNDERBOLT" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "SWIRLIX": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_CHARM" + }, + { + "Level": "6", + "Move": "MOVE_FAIRY_WIND" + }, + { + "Level": "12", + "Move": "MOVE_DRAINING_KISS" + }, + { + "Level": "15", + "Move": "MOVE_FAKE_TEARS" + }, + { + "Level": "18", + "Move": "MOVE_AMNESIA" + }, + { + "Level": "21", + "Move": "MOVE_STRING_SHOT" + }, + { + "Level": "24", + "Move": "MOVE_COTTON_GUARD" + }, + { + "Level": "27", + "Move": "MOVE_ENERGY_BALL" + }, + { + "Level": "32", + "Move": "MOVE_WISH" + }, + { + "Level": "36", + "Move": "MOVE_PLAY_ROUGH" + }, + { + "Level": "40", + "Move": "MOVE_STICKY_WEB" + } + ], + "TMMoves": [ + "MOVE_CALM_MIND", + "MOVE_DAZZLING_GLEAM", + "MOVE_ENDURE", + "MOVE_FLAMETHROWER", + "MOVE_LIGHT_SCREEN", + "MOVE_PROTECT", + "MOVE_PSYCHIC", + "MOVE_SAFEGUARD", + "MOVE_SELF_DESTRUCT", + "MOVE_SUBSTITUTE", + "MOVE_SURF", + "MOVE_SWORDS_DANCE", + "MOVE_THUNDERBOLT" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "SLURPUFF": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_CHARM" + }, + { + "Level": "6", + "Move": "MOVE_FAIRY_WIND" + }, + { + "Level": "12", + "Move": "MOVE_DRAINING_KISS" + }, + { + "Level": "15", + "Move": "MOVE_FAKE_TEARS" + }, + { + "Level": "18", + "Move": "MOVE_AMNESIA" + }, + { + "Level": "21", + "Move": "MOVE_STRING_SHOT" + }, + { + "Level": "24", + "Move": "MOVE_COTTON_GUARD" + }, + { + "Level": "27", + "Move": "MOVE_ENERGY_BALL" + }, + { + "Level": "32", + "Move": "MOVE_WISH" + }, + { + "Level": "36", + "Move": "MOVE_PLAY_ROUGH" + }, + { + "Level": "40", + "Move": "MOVE_STICKY_WEB" + } + ], + "TMMoves": [ + "MOVE_CALM_MIND", + "MOVE_DAZZLING_GLEAM", + "MOVE_ENDURE", + "MOVE_FLAMETHROWER", + "MOVE_GIGA_IMPACT", + "MOVE_HYPER_BEAM", + "MOVE_LIGHT_SCREEN", + "MOVE_METRONOME", + "MOVE_PROTECT", + "MOVE_PSYCHIC", + "MOVE_SAFEGUARD", + "MOVE_SELF_DESTRUCT", + "MOVE_SUBSTITUTE", + "MOVE_SURF", + "MOVE_SWORDS_DANCE", + "MOVE_THUNDERBOLT" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "INKAY": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_PECK" + }, + { + "Level": "3", + "Move": "MOVE_HYPNOSIS" + }, + { + "Level": "6", + "Move": "MOVE_FAKE_TEARS" + }, + { + "Level": "14", + "Move": "MOVE_KNOCK_OFF" + }, + { + "Level": "15", + "Move": "MOVE_PSYBEAM" + }, + { + "Level": "21", + "Move": "MOVE_SLASH" + }, + { + "Level": "24", + "Move": "MOVE_NIGHT_SLASH" + }, + { + "Level": "33", + "Move": "MOVE_PSYCHO_CUT" + }, + { + "Level": "37", + "Move": "MOVE_PSYSHOCK" + }, + { + "Level": "42", + "Move": "MOVE_TOPSY_TURVY" + }, + { + "Level": "54", + "Move": "MOVE_CLOSE_COMBAT" + } + ], + "TMMoves": [ + "MOVE_CALM_MIND", + "MOVE_DARK_PULSE", + "MOVE_ENDURE", + "MOVE_FLAMETHROWER", + "MOVE_FUTURE_SIGHT", + "MOVE_HEADBUTT", + "MOVE_LIGHT_SCREEN", + "MOVE_LIQUIDATION", + "MOVE_NASTY_PLOT", + "MOVE_PROTECT", + "MOVE_PSYCHIC", + "MOVE_REFLECT", + "MOVE_ROCK_SLIDE", + "MOVE_SUBSTITUTE", + "MOVE_TAUNT", + "MOVE_THUNDERBOLT", + "MOVE_ZEN_HEADBUTT" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "MALAMAR": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_PECK" + }, + { + "Level": "3", + "Move": "MOVE_HYPNOSIS" + }, + { + "Level": "6", + "Move": "MOVE_FAKE_TEARS" + }, + { + "Level": "14", + "Move": "MOVE_KNOCK_OFF" + }, + { + "Level": "15", + "Move": "MOVE_PSYBEAM" + }, + { + "Level": "21", + "Move": "MOVE_SLASH" + }, + { + "Level": "24", + "Move": "MOVE_NIGHT_SLASH" + }, + { + "Level": "33", + "Move": "MOVE_PSYCHO_CUT" + }, + { + "Level": "37", + "Move": "MOVE_PSYSHOCK" + }, + { + "Level": "42", + "Move": "MOVE_TOPSY_TURVY" + }, + { + "Level": "54", + "Move": "MOVE_CLOSE_COMBAT" + } + ], + "TMMoves": [ + "MOVE_BULK_UP", + "MOVE_CALM_MIND", + "MOVE_DARK_PULSE", + "MOVE_DOUBLE_TEAM", + "MOVE_ENDURE", + "MOVE_FLAMETHROWER", + "MOVE_FUTURE_SIGHT", + "MOVE_GIGA_IMPACT", + "MOVE_HEADBUTT", + "MOVE_HEAL_BLOCK", + "MOVE_HYPER_BEAM", + "MOVE_LIGHT_SCREEN", + "MOVE_LIQUIDATION", + "MOVE_NASTY_PLOT", + "MOVE_POISON_JAB", + "MOVE_PROTECT", + "MOVE_PSYCHIC", + "MOVE_REFLECT", + "MOVE_ROCK_SLIDE", + "MOVE_STEALTH_ROCK", + "MOVE_SUBSTITUTE", + "MOVE_TAUNT", + "MOVE_THUNDERBOLT", + "MOVE_ZEN_HEADBUTT" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "BINACLE": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_WATER_GUN" + }, + { + "Level": "1", + "Move": "MOVE_SCREECH" + }, + { + "Level": "9", + "Move": "MOVE_INFESTATION" + }, + { + "Level": "12", + "Move": "MOVE_ROCK_THROW" + }, + { + "Level": "14", + "Move": "MOVE_BUBBLE_BEAM" + }, + { + "Level": "16", + "Move": "MOVE_ROCK_BLAST" + }, + { + "Level": "18", + "Move": "MOVE_BULLDOZE" + }, + { + "Level": "23", + "Move": "MOVE_SLASH" + }, + { + "Level": "35", + "Move": "MOVE_IRON_DEFENSE" + }, + { + "Level": "40", + "Move": "MOVE_NIGHT_SLASH" + }, + { + "Level": "45", + "Move": "MOVE_LIQUIDATION" + }, + { + "Level": "50", + "Move": "MOVE_STONE_EDGE" + } + ], + "TMMoves": [ + "MOVE_BLIZZARD", + "MOVE_BRICK_BREAK", + "MOVE_DIG", + "MOVE_EARTHQUAKE", + "MOVE_ENDURE", + "MOVE_ICE_BEAM", + "MOVE_MUD_SHOT", + "MOVE_POISON_JAB", + "MOVE_POWER_UP_PUNCH", + "MOVE_PROTECT", + "MOVE_ROCK_SLIDE", + "MOVE_ROCK_TOMB", + "MOVE_SAFEGUARD", + "MOVE_SHADOW_CLAW", + "MOVE_SLUDGE_BOMB", + "MOVE_STEALTH_ROCK", + "MOVE_SUBSTITUTE", + "MOVE_SURF", + "MOVE_SWORDS_DANCE", + "MOVE_TAUNT", + "MOVE_WATERFALL", + "MOVE_X_SCISSOR" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "BARBARACLE": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_WATER_GUN" + }, + { + "Level": "1", + "Move": "MOVE_SCREECH" + }, + { + "Level": "9", + "Move": "MOVE_INFESTATION" + }, + { + "Level": "12", + "Move": "MOVE_ROCK_THROW" + }, + { + "Level": "14", + "Move": "MOVE_BUBBLE_BEAM" + }, + { + "Level": "16", + "Move": "MOVE_ROCK_BLAST" + }, + { + "Level": "18", + "Move": "MOVE_BULLDOZE" + }, + { + "Level": "23", + "Move": "MOVE_SLASH" + }, + { + "Level": "35", + "Move": "MOVE_IRON_DEFENSE" + }, + { + "Level": "40", + "Move": "MOVE_NIGHT_SLASH" + }, + { + "Level": "43", + "Move": "MOVE_BRICK_BREAK" + }, + { + "Level": "45", + "Move": "MOVE_LIQUIDATION" + }, + { + "Level": "50", + "Move": "MOVE_STONE_EDGE" + }, + { + "Level": "54", + "Move": "MOVE_CLOSE_COMBAT" + } + ], + "TMMoves": [ + "MOVE_BLIZZARD", + "MOVE_BULK_UP", + "MOVE_DIG", + "MOVE_DRAGON_CLAW", + "MOVE_EARTHQUAKE", + "MOVE_ENDURE", + "MOVE_FOCUS_BLAST", + "MOVE_GIGA_IMPACT", + "MOVE_HYPER_BEAM", + "MOVE_ICE_BEAM", + "MOVE_MUD_SHOT", + "MOVE_POISON_JAB", + "MOVE_POWER_UP_PUNCH", + "MOVE_PROTECT", + "MOVE_ROCK_SLIDE", + "MOVE_ROCK_TOMB", + "MOVE_SAFEGUARD", + "MOVE_SHADOW_CLAW", + "MOVE_SLUDGE_BOMB", + "MOVE_STEALTH_ROCK", + "MOVE_SUBSTITUTE", + "MOVE_SURF", + "MOVE_SWORDS_DANCE", + "MOVE_TAUNT", + "MOVE_WATERFALL", + "MOVE_X_SCISSOR" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "SKRELP": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_WATER_GUN" + }, + { + "Level": "1", + "Move": "MOVE_SMOKESCREEN" + }, + { + "Level": "5", + "Move": "MOVE_TAIL_WHIP" + }, + { + "Level": "10", + "Move": "MOVE_MUD_SHOT" + }, + { + "Level": "15", + "Move": "MOVE_BUBBLE_BEAM" + }, + { + "Level": "22", + "Move": "MOVE_DOUBLE_TEAM" + }, + { + "Level": "25", + "Move": "MOVE_TOXIC" + }, + { + "Level": "30", + "Move": "MOVE_WATER_PULSE" + }, + { + "Level": "32", + "Move": "MOVE_POISON_JAB" + }, + { + "Level": "36", + "Move": "MOVE_DRAGON_PULSE" + }, + { + "Level": "40", + "Move": "MOVE_SLUDGE_BOMB" + }, + { + "Level": "46", + "Move": "MOVE_HYDRO_PUMP" + }, + { + "Level": "52", + "Move": "MOVE_SLUDGE_WAVE" + } + ], + "TMMoves": [ + "MOVE_ENDURE", + "MOVE_FLIP_TURN", + "MOVE_GUNK_SHOT", + "MOVE_LIQUIDATION", + "MOVE_OUTRAGE", + "MOVE_PLAY_ROUGH", + "MOVE_PROTECT", + "MOVE_SHADOW_BALL", + "MOVE_SUBSTITUTE", + "MOVE_SURF", + "MOVE_THUNDERBOLT", + "MOVE_TOXIC_SPIKES", + "MOVE_WATERFALL" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "DRAGALGE": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_WATER_GUN" + }, + { + "Level": "1", + "Move": "MOVE_SMOKESCREEN" + }, + { + "Level": "5", + "Move": "MOVE_TAIL_WHIP" + }, + { + "Level": "10", + "Move": "MOVE_MUD_SHOT" + }, + { + "Level": "15", + "Move": "MOVE_BUBBLE_BEAM" + }, + { + "Level": "22", + "Move": "MOVE_DOUBLE_TEAM" + }, + { + "Level": "25", + "Move": "MOVE_TOXIC" + }, + { + "Level": "30", + "Move": "MOVE_WATER_PULSE" + }, + { + "Level": "32", + "Move": "MOVE_POISON_JAB" + }, + { + "Level": "36", + "Move": "MOVE_DRAGON_PULSE" + }, + { + "Level": "40", + "Move": "MOVE_SLUDGE_BOMB" + }, + { + "Level": "46", + "Move": "MOVE_HYDRO_PUMP" + }, + { + "Level": "52", + "Move": "MOVE_SLUDGE_WAVE" + } + ], + "TMMoves": [ + "MOVE_DRACO_METEOR", + "MOVE_ENDURE", + "MOVE_FLIP_TURN", + "MOVE_FOCUS_BLAST", + "MOVE_GUNK_SHOT", + "MOVE_HYPER_BEAM", + "MOVE_LIQUIDATION", + "MOVE_OUTRAGE", + "MOVE_PLAY_ROUGH", + "MOVE_PROTECT", + "MOVE_SHADOW_BALL", + "MOVE_SUBSTITUTE", + "MOVE_SURF", + "MOVE_THUNDERBOLT", + "MOVE_TOXIC_SPIKES", + "MOVE_WATERFALL" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "CLAUNCHER": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_WATER_GUN" + }, + { + "Level": "1", + "Move": "MOVE_SPLASH" + }, + { + "Level": "10", + "Move": "MOVE_BUBBLE_BEAM" + }, + { + "Level": "13", + "Move": "MOVE_AQUA_JET" + }, + { + "Level": "16", + "Move": "MOVE_MUD_SHOT" + }, + { + "Level": "24", + "Move": "MOVE_WATER_PULSE" + }, + { + "Level": "30", + "Move": "MOVE_SWORDS_DANCE" + }, + { + "Level": "34", + "Move": "MOVE_AURA_SPHERE" + }, + { + "Level": "40", + "Move": "MOVE_DARK_PULSE" + }, + { + "Level": "45", + "Move": "MOVE_BOUNCE" + }, + { + "Level": "48", + "Move": "MOVE_DRAGON_PULSE" + }, + { + "Level": "52", + "Move": "MOVE_HYDRO_PUMP" + } + ], + "TMMoves": [ + "MOVE_BLIZZARD", + "MOVE_ENDURE", + "MOVE_FLASH_CANNON", + "MOVE_FLIP_TURN", + "MOVE_ICE_BEAM", + "MOVE_LIQUIDATION", + "MOVE_PROTECT", + "MOVE_ROCK_SLIDE", + "MOVE_SUBSTITUTE", + "MOVE_SURF", + "MOVE_U_TURN", + "MOVE_WATERFALL" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "CLAWITZER": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_WATER_GUN" + }, + { + "Level": "1", + "Move": "MOVE_SPLASH" + }, + { + "Level": "10", + "Move": "MOVE_BUBBLE_BEAM" + }, + { + "Level": "13", + "Move": "MOVE_AQUA_JET" + }, + { + "Level": "16", + "Move": "MOVE_MUD_SHOT" + }, + { + "Level": "24", + "Move": "MOVE_WATER_PULSE" + }, + { + "Level": "30", + "Move": "MOVE_SWORDS_DANCE" + }, + { + "Level": "34", + "Move": "MOVE_AURA_SPHERE" + }, + { + "Level": "40", + "Move": "MOVE_DARK_PULSE" + }, + { + "Level": "45", + "Move": "MOVE_BOUNCE" + }, + { + "Level": "48", + "Move": "MOVE_DRAGON_PULSE" + }, + { + "Level": "52", + "Move": "MOVE_HYDRO_PUMP" + }, + { + "Level": "55", + "Move": "MOVE_FOCUS_BLAST" + } + ], + "TMMoves": [ + "MOVE_BLIZZARD", + "MOVE_ENDURE", + "MOVE_FLASH_CANNON", + "MOVE_FLIP_TURN", + "MOVE_HYPER_BEAM", + "MOVE_ICE_BEAM", + "MOVE_LIQUIDATION", + "MOVE_PROTECT", + "MOVE_ROCK_SLIDE", + "MOVE_SHADOW_BALL", + "MOVE_SUBSTITUTE", + "MOVE_SURF", + "MOVE_U_TURN", + "MOVE_WATERFALL" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "HELIOPTILE": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TAIL_WHIP" + }, + { + "Level": "1", + "Move": "MOVE_THUNDER_SHOCK" + }, + { + "Level": "1", + "Move": "MOVE_THUNDER_WAVE" + }, + { + "Level": "12", + "Move": "MOVE_QUICK_ATTACK" + }, + { + "Level": "15", + "Move": "MOVE_SWIFT" + }, + { + "Level": "20", + "Move": "MOVE_PARABOLIC_CHARGE" + }, + { + "Level": "24", + "Move": "MOVE_BULLDOZE" + }, + { + "Level": "28", + "Move": "MOVE_VOLT_SWITCH" + }, + { + "Level": "30", + "Move": "MOVE_BREAKING_SWIPE" + }, + { + "Level": "32", + "Move": "MOVE_MORNING_SUN" + }, + { + "Level": "36", + "Move": "MOVE_THUNDERBOLT" + }, + { + "Level": "42", + "Move": "MOVE_CHARGE" + }, + { + "Level": "50", + "Move": "MOVE_THUNDER" + } + ], + "TMMoves": [ + "MOVE_AGILITY", + "MOVE_DARK_PULSE", + "MOVE_DIG", + "MOVE_DISCHARGE", + "MOVE_ELECTROWEB", + "MOVE_ENDURE", + "MOVE_LIGHT_SCREEN", + "MOVE_PROTECT", + "MOVE_ROCK_SLIDE", + "MOVE_ROCK_TOMB", + "MOVE_SUBSTITUTE", + "MOVE_SURF", + "MOVE_U_TURN", + "MOVE_WILD_CHARGE" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "HELIOLISK": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TAIL_WHIP" + }, + { + "Level": "1", + "Move": "MOVE_THUNDER_SHOCK" + }, + { + "Level": "1", + "Move": "MOVE_THUNDER_WAVE" + }, + { + "Level": "12", + "Move": "MOVE_QUICK_ATTACK" + }, + { + "Level": "15", + "Move": "MOVE_SWIFT" + }, + { + "Level": "20", + "Move": "MOVE_PARABOLIC_CHARGE" + }, + { + "Level": "24", + "Move": "MOVE_BULLDOZE" + }, + { + "Level": "28", + "Move": "MOVE_VOLT_SWITCH" + }, + { + "Level": "30", + "Move": "MOVE_BREAKING_SWIPE" + }, + { + "Level": "32", + "Move": "MOVE_MORNING_SUN" + }, + { + "Level": "36", + "Move": "MOVE_THUNDERBOLT" + }, + { + "Level": "42", + "Move": "MOVE_CHARGE" + }, + { + "Level": "50", + "Move": "MOVE_THUNDER" + } + ], + "TMMoves": [ + "MOVE_AGILITY", + "MOVE_DARK_PULSE", + "MOVE_DIG", + "MOVE_DISCHARGE", + "MOVE_DRAGON_PULSE", + "MOVE_ELECTROWEB", + "MOVE_ENDURE", + "MOVE_FIRE_PUNCH", + "MOVE_FOCUS_BLAST", + "MOVE_GIGA_IMPACT", + "MOVE_HYPER_BEAM", + "MOVE_HYPER_VOICE", + "MOVE_IRON_TAIL", + "MOVE_LIGHT_SCREEN", + "MOVE_PROTECT", + "MOVE_ROCK_SLIDE", + "MOVE_ROCK_TOMB", + "MOVE_SOLAR_BEAM", + "MOVE_SUBSTITUTE", + "MOVE_SURF", + "MOVE_THUNDER_PUNCH", + "MOVE_U_TURN", + "MOVE_WILD_CHARGE" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "TYRUNT": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_TAIL_WHIP" + }, + { + "Level": "4", + "Move": "MOVE_ROAR" + }, + { + "Level": "8", + "Move": "MOVE_ROCK_THROW" + }, + { + "Level": "12", + "Move": "MOVE_CHARM" + }, + { + "Level": "16", + "Move": "MOVE_BITE" + }, + { + "Level": "24", + "Move": "MOVE_ROCK_BLAST" + }, + { + "Level": "28", + "Move": "MOVE_ROCK_SLIDE" + }, + { + "Level": "32", + "Move": "MOVE_CRUNCH" + }, + { + "Level": "36", + "Move": "MOVE_DRAGON_CLAW" + }, + { + "Level": "44", + "Move": "MOVE_EARTHQUAKE" + } + ], + "TMMoves": [ + "MOVE_BODY_SLAM", + "MOVE_BRICK_BREAK", + "MOVE_BULLDOZE", + "MOVE_CLOSE_COMBAT", + "MOVE_DARK_PULSE", + "MOVE_DIG", + "MOVE_DRACO_METEOR", + "MOVE_DRAGON_PULSE", + "MOVE_EARTH_POWER", + "MOVE_ENDURE", + "MOVE_FIRE_FANG", + "MOVE_HYPER_VOICE", + "MOVE_ICE_FANG", + "MOVE_IRON_DEFENSE", + "MOVE_IRON_HEAD", + "MOVE_OUTRAGE", + "MOVE_PLAY_ROUGH", + "MOVE_PROTECT", + "MOVE_ROCK_TOMB", + "MOVE_STEALTH_ROCK", + "MOVE_STONE_EDGE", + "MOVE_SUBSTITUTE", + "MOVE_THUNDER_FANG", + "MOVE_ZEN_HEADBUTT" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "TYRANTRUM": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_TAIL_WHIP" + }, + { + "Level": "1", + "Move": "MOVE_BREAKING_SWIPE" + }, + { + "Level": "4", + "Move": "MOVE_ROAR" + }, + { + "Level": "8", + "Move": "MOVE_ROCK_THROW" + }, + { + "Level": "12", + "Move": "MOVE_CHARM" + }, + { + "Level": "16", + "Move": "MOVE_BITE" + }, + { + "Level": "24", + "Move": "MOVE_ROCK_BLAST" + }, + { + "Level": "28", + "Move": "MOVE_ROCK_SLIDE" + }, + { + "Level": "32", + "Move": "MOVE_CRUNCH" + }, + { + "Level": "36", + "Move": "MOVE_DRAGON_CLAW" + }, + { + "Level": "44", + "Move": "MOVE_EARTHQUAKE" + }, + { + "Level": "52", + "Move": "MOVE_GIGA_IMPACT" + }, + { + "Level": "58", + "Move": "MOVE_HEAD_SMASH" + } + ], + "TMMoves": [ + "MOVE_BODY_SLAM", + "MOVE_BRICK_BREAK", + "MOVE_BULLDOZE", + "MOVE_CLOSE_COMBAT", + "MOVE_DARK_PULSE", + "MOVE_DIG", + "MOVE_DRACO_METEOR", + "MOVE_DRAGON_PULSE", + "MOVE_EARTH_POWER", + "MOVE_ENDURE", + "MOVE_FIRE_FANG", + "MOVE_HYPER_BEAM", + "MOVE_HYPER_VOICE", + "MOVE_ICE_FANG", + "MOVE_IRON_DEFENSE", + "MOVE_IRON_HEAD", + "MOVE_IRON_TAIL", + "MOVE_OUTRAGE", + "MOVE_PLAY_ROUGH", + "MOVE_PROTECT", + "MOVE_ROCK_TOMB", + "MOVE_STEALTH_ROCK", + "MOVE_STONE_EDGE", + "MOVE_SUBSTITUTE", + "MOVE_THUNDER_FANG", + "MOVE_ZEN_HEADBUTT" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "AMAURA": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_GROWL" + }, + { + "Level": "10", + "Move": "MOVE_ROCK_THROW" + }, + { + "Level": "12", + "Move": "MOVE_ICY_WIND" + }, + { + "Level": "16", + "Move": "MOVE_TAKE_DOWN" + }, + { + "Level": "20", + "Move": "MOVE_MIST" + }, + { + "Level": "24", + "Move": "MOVE_ROCK_BLAST" + }, + { + "Level": "28", + "Move": "MOVE_THUNDER_WAVE" + }, + { + "Level": "36", + "Move": "MOVE_FREEZE_DRY" + }, + { + "Level": "40", + "Move": "MOVE_ICE_BEAM" + }, + { + "Level": "44", + "Move": "MOVE_LIGHT_SCREEN" + }, + { + "Level": "52", + "Move": "MOVE_BLIZZARD" + }, + { + "Level": "56", + "Move": "MOVE_HYPER_BEAM" + } + ], + "TMMoves": [ + "MOVE_BODY_SLAM", + "MOVE_BULLDOZE", + "MOVE_CALM_MIND", + "MOVE_DARK_PULSE", + "MOVE_EARTH_POWER", + "MOVE_ENDURE", + "MOVE_FLASH_CANNON", + "MOVE_HYPER_VOICE", + "MOVE_IRON_DEFENSE", + "MOVE_IRON_HEAD", + "MOVE_OUTRAGE", + "MOVE_PROTECT", + "MOVE_REFLECT", + "MOVE_ROCK_SLIDE", + "MOVE_ROCK_TOMB", + "MOVE_SAFEGUARD", + "MOVE_STEALTH_ROCK", + "MOVE_STONE_EDGE", + "MOVE_SUBSTITUTE", + "MOVE_THUNDERBOLT", + "MOVE_ZEN_HEADBUTT" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "AURORUS": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_GROWL" + }, + { + "Level": "10", + "Move": "MOVE_ROCK_THROW" + }, + { + "Level": "12", + "Move": "MOVE_ICY_WIND" + }, + { + "Level": "16", + "Move": "MOVE_TAKE_DOWN" + }, + { + "Level": "20", + "Move": "MOVE_MIST" + }, + { + "Level": "24", + "Move": "MOVE_ROCK_BLAST" + }, + { + "Level": "28", + "Move": "MOVE_THUNDER_WAVE" + }, + { + "Level": "36", + "Move": "MOVE_FREEZE_DRY" + }, + { + "Level": "40", + "Move": "MOVE_ICE_BEAM" + }, + { + "Level": "44", + "Move": "MOVE_LIGHT_SCREEN" + }, + { + "Level": "52", + "Move": "MOVE_BLIZZARD" + }, + { + "Level": "56", + "Move": "MOVE_HYPER_BEAM" + } + ], + "TMMoves": [ + "MOVE_BODY_SLAM", + "MOVE_BULLDOZE", + "MOVE_CALM_MIND", + "MOVE_DARK_PULSE", + "MOVE_EARTHQUAKE", + "MOVE_EARTH_POWER", + "MOVE_ENDURE", + "MOVE_FLASH_CANNON", + "MOVE_GIGA_IMPACT", + "MOVE_HYPER_VOICE", + "MOVE_IRON_DEFENSE", + "MOVE_IRON_HEAD", + "MOVE_IRON_TAIL", + "MOVE_OUTRAGE", + "MOVE_PROTECT", + "MOVE_PSYCHIC", + "MOVE_REFLECT", + "MOVE_ROCK_SLIDE", + "MOVE_ROCK_TOMB", + "MOVE_SAFEGUARD", + "MOVE_STEALTH_ROCK", + "MOVE_STONE_EDGE", + "MOVE_SUBSTITUTE", + "MOVE_THUNDER", + "MOVE_THUNDERBOLT", + "MOVE_ZEN_HEADBUTT" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "SYLVEON": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_TAIL_WHIP" + }, + { + "Level": "1", + "Move": "MOVE_BITE" + }, + { + "Level": "1", + "Move": "MOVE_GROWL" + }, + { + "Level": "10", + "Move": "MOVE_QUICK_ATTACK" + }, + { + "Level": "15", + "Move": "MOVE_DISARMING_VOICE" + }, + { + "Level": "25", + "Move": "MOVE_LIGHT_SCREEN" + }, + { + "Level": "30", + "Move": "MOVE_DRAINING_KISS" + }, + { + "Level": "35", + "Move": "MOVE_DAZZLING_GLEAM" + }, + { + "Level": "40", + "Move": "MOVE_HYPER_VOICE" + }, + { + "Level": "45", + "Move": "MOVE_FAKE_TEARS" + }, + { + "Level": "50", + "Move": "MOVE_MOONBLAST" + } + ], + "TMMoves": [ + "MOVE_BODY_SLAM", + "MOVE_CALM_MIND", + "MOVE_CURSE", + "MOVE_DIG", + "MOVE_ENDURE", + "MOVE_GIGA_IMPACT", + "MOVE_HYPER_BEAM", + "MOVE_IRON_TAIL", + "MOVE_PROTECT", + "MOVE_PSYCHIC", + "MOVE_PSYSHOCK", + "MOVE_REFLECT", + "MOVE_ROAR", + "MOVE_SHADOW_BALL", + "MOVE_SUBSTITUTE", + "MOVE_TAUNT" + ], + "TutorMoves": [ + "MOVE_CHARM", + "MOVE_DOUBLE_EDGE", + "MOVE_SWIFT", + "MOVE_TAKE_DOWN", + "MOVE_WISH" + ], + "EggMoves": [] + }, + "HAWLUCHA": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "4", + "Move": "MOVE_WING_ATTACK" + }, + { + "Level": "8", + "Move": "MOVE_DETECT" + }, + { + "Level": "12", + "Move": "MOVE_AERIAL_ACE" + }, + { + "Level": "20", + "Move": "MOVE_FEATHER_DANCE" + }, + { + "Level": "24", + "Move": "MOVE_BRICK_BREAK" + }, + { + "Level": "26", + "Move": "MOVE_LUNGE" + }, + { + "Level": "28", + "Move": "MOVE_BOUNCE" + }, + { + "Level": "32", + "Move": "MOVE_TAUNT" + }, + { + "Level": "36", + "Move": "MOVE_FLYING_PRESS" + }, + { + "Level": "40", + "Move": "MOVE_SWORDS_DANCE" + }, + { + "Level": "44", + "Move": "MOVE_AIR_SLASH" + }, + { + "Level": "52", + "Move": "MOVE_BRAVE_BIRD" + } + ], + "TMMoves": [ + "MOVE_AGILITY", + "MOVE_BODY_SLAM", + "MOVE_BULK_UP", + "MOVE_CLOSE_COMBAT", + "MOVE_DIG", + "MOVE_ENDURE", + "MOVE_FIRE_PUNCH", + "MOVE_FLY", + "MOVE_FOCUS_BLAST", + "MOVE_GIGA_IMPACT", + "MOVE_HYPER_BEAM", + "MOVE_IRON_HEAD", + "MOVE_POISON_JAB", + "MOVE_PROTECT", + "MOVE_ROCK_SLIDE", + "MOVE_ROCK_TOMB", + "MOVE_STONE_EDGE", + "MOVE_SUBSTITUTE", + "MOVE_SWIFT", + "MOVE_THUNDER_PUNCH", + "MOVE_U_TURN", + "MOVE_X_SCISSOR", + "MOVE_ZEN_HEADBUTT" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "DEDENNE": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_TAIL_WHIP" + }, + { + "Level": "1", + "Move": "MOVE_THUNDER_SHOCK" + }, + { + "Level": "1", + "Move": "MOVE_NUZZLE" + }, + { + "Level": "5", + "Move": "MOVE_CHARGE" + }, + { + "Level": "10", + "Move": "MOVE_CHARM" + }, + { + "Level": "15", + "Move": "MOVE_PARABOLIC_CHARGE" + }, + { + "Level": "20", + "Move": "MOVE_EERIE_IMPULSE" + }, + { + "Level": "25", + "Move": "MOVE_VOLT_SWITCH" + }, + { + "Level": "30", + "Move": "MOVE_PLAY_ROUGH" + }, + { + "Level": "35", + "Move": "MOVE_THUNDERBOLT" + }, + { + "Level": "40", + "Move": "MOVE_SUPER_FANG" + }, + { + "Level": "50", + "Move": "MOVE_THUNDER" + } + ], + "TMMoves": [ + "MOVE_AGILITY", + "MOVE_DAZZLING_GLEAM", + "MOVE_DIG", + "MOVE_DISCHARGE", + "MOVE_ENDURE", + "MOVE_GIGA_IMPACT", + "MOVE_HYPER_BEAM", + "MOVE_LIGHT_SCREEN", + "MOVE_PROTECT", + "MOVE_SUBSTITUTE", + "MOVE_SWIFT", + "MOVE_THUNDER_PUNCH", + "MOVE_THUNDER_WAVE", + "MOVE_U_TURN", + "MOVE_WILD_CHARGE" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "CARBINK": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_HARDEN" + }, + { + "Level": "12", + "Move": "MOVE_ROCK_THROW" + }, + { + "Level": "15", + "Move": "MOVE_TAKE_DOWN" + }, + { + "Level": "23", + "Move": "MOVE_DAZZLING_GLEAM" + }, + { + "Level": "25", + "Move": "MOVE_IRON_DEFENSE" + }, + { + "Level": "28", + "Move": "MOVE_POWER_GEM" + }, + { + "Level": "30", + "Move": "MOVE_LIGHT_SCREEN" + }, + { + "Level": "32", + "Move": "MOVE_FLASH_CANNON" + }, + { + "Level": "35", + "Move": "MOVE_ROCK_SLIDE" + }, + { + "Level": "38", + "Move": "MOVE_STEALTH_ROCK" + }, + { + "Level": "45", + "Move": "MOVE_MOONBLAST" + }, + { + "Level": "52", + "Move": "MOVE_STONE_EDGE" + } + ], + "TMMoves": [ + "MOVE_BODY_SLAM", + "MOVE_CALM_MIND", + "MOVE_DOUBLE_EDGE", + "MOVE_EARTH_POWER", + "MOVE_ENDURE", + "MOVE_GIGA_IMPACT", + "MOVE_HYPER_BEAM", + "MOVE_IRON_HEAD", + "MOVE_PROTECT", + "MOVE_PSYCHIC", + "MOVE_REFLECT", + "MOVE_ROCK_BLAST", + "MOVE_ROCK_TOMB", + "MOVE_SELF_DESTRUCT", + "MOVE_SPIKES", + "MOVE_SUBSTITUTE" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "GOOMY": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_ABSORB" + }, + { + "Level": "5", + "Move": "MOVE_WATER_GUN" + }, + { + "Level": "8", + "Move": "MOVE_CHARM" + }, + { + "Level": "10", + "Move": "MOVE_DRAGON_BREATH" + }, + { + "Level": "15", + "Move": "MOVE_PROTECT" + }, + { + "Level": "18", + "Move": "MOVE_MUD_SHOT" + }, + { + "Level": "25", + "Move": "MOVE_WATER_PULSE" + }, + { + "Level": "30", + "Move": "MOVE_DRAGON_PULSE" + }, + { + "Level": "35", + "Move": "MOVE_TAKE_DOWN" + }, + { + "Level": "41", + "Move": "MOVE_CURSE" + }, + { + "Level": "45", + "Move": "MOVE_BODY_SLAM" + }, + { + "Level": "56", + "Move": "MOVE_SURF" + } + ], + "TMMoves": [ + "MOVE_DRACO_METEOR", + "MOVE_ENDURE", + "MOVE_OUTRAGE", + "MOVE_ROCK_SLIDE", + "MOVE_SLUDGE_BOMB", + "MOVE_SUBSTITUTE", + "MOVE_THUNDERBOLT", + "MOVE_TOXIC" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "SLIGGOO": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_ABSORB" + }, + { + "Level": "1", + "Move": "MOVE_ACID_ARMOR" + }, + { + "Level": "5", + "Move": "MOVE_WATER_GUN" + }, + { + "Level": "8", + "Move": "MOVE_CHARM" + }, + { + "Level": "10", + "Move": "MOVE_DRAGON_BREATH" + }, + { + "Level": "15", + "Move": "MOVE_PROTECT" + }, + { + "Level": "18", + "Move": "MOVE_MUD_SHOT" + }, + { + "Level": "25", + "Move": "MOVE_WATER_PULSE" + }, + { + "Level": "30", + "Move": "MOVE_DRAGON_PULSE" + }, + { + "Level": "35", + "Move": "MOVE_TAKE_DOWN" + }, + { + "Level": "41", + "Move": "MOVE_CURSE" + }, + { + "Level": "45", + "Move": "MOVE_BODY_SLAM" + }, + { + "Level": "56", + "Move": "MOVE_SURF" + } + ], + "TMMoves": [ + "MOVE_BLIZZARD", + "MOVE_DRACO_METEOR", + "MOVE_ENDURE", + "MOVE_ICE_BEAM", + "MOVE_OUTRAGE", + "MOVE_ROCK_SLIDE", + "MOVE_SLUDGE_BOMB", + "MOVE_SUBSTITUTE", + "MOVE_THUNDER", + "MOVE_THUNDERBOLT", + "MOVE_TOXIC" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "SLIGGOO_HISUI": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_ABSORB" + }, + { + "Level": "1", + "Move": "MOVE_ACID_ARMOR" + }, + { + "Level": "5", + "Move": "MOVE_WATER_GUN" + }, + { + "Level": "8", + "Move": "MOVE_CHARM" + }, + { + "Level": "10", + "Move": "MOVE_DRAGON_BREATH" + }, + { + "Level": "15", + "Move": "MOVE_PROTECT" + }, + { + "Level": "18", + "Move": "MOVE_MUD_SHOT" + }, + { + "Level": "25", + "Move": "MOVE_WATER_PULSE" + }, + { + "Level": "30", + "Move": "MOVE_DRAGON_PULSE" + }, + { + "Level": "35", + "Move": "MOVE_TAKE_DOWN" + }, + { + "Level": "41", + "Move": "MOVE_CURSE" + }, + { + "Level": "45", + "Move": "MOVE_BODY_SLAM" + }, + { + "Level": "56", + "Move": "MOVE_SURF" + } + ], + "TMMoves": [ + "MOVE_BLIZZARD", + "MOVE_DRACO_METEOR", + "MOVE_ENDURE", + "MOVE_ICE_BEAM", + "MOVE_IRON_HEAD", + "MOVE_OUTRAGE", + "MOVE_ROCK_SLIDE", + "MOVE_ROCK_TOMB", + "MOVE_SLUDGE_BOMB", + "MOVE_SUBSTITUTE", + "MOVE_THUNDER", + "MOVE_THUNDERBOLT", + "MOVE_TOXIC" + ], + "TutorMoves": [ + "MOVE_IRON_DEFENSE" + ], + "EggMoves": [] + }, + "GOODRA": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_ABSORB" + }, + { + "Level": "1", + "Move": "MOVE_ACID_ARMOR" + }, + { + "Level": "1", + "Move": "MOVE_BREAKING_SWIPE" + }, + { + "Level": "5", + "Move": "MOVE_WATER_GUN" + }, + { + "Level": "8", + "Move": "MOVE_CHARM" + }, + { + "Level": "10", + "Move": "MOVE_DRAGON_BREATH" + }, + { + "Level": "15", + "Move": "MOVE_PROTECT" + }, + { + "Level": "18", + "Move": "MOVE_MUD_SHOT" + }, + { + "Level": "25", + "Move": "MOVE_WATER_PULSE" + }, + { + "Level": "30", + "Move": "MOVE_DRAGON_PULSE" + }, + { + "Level": "35", + "Move": "MOVE_TAKE_DOWN" + }, + { + "Level": "41", + "Move": "MOVE_CURSE" + }, + { + "Level": "45", + "Move": "MOVE_BODY_SLAM" + }, + { + "Level": "56", + "Move": "MOVE_SURF" + }, + { + "Level": "58", + "Move": "MOVE_POWER_WHIP" + } + ], + "TMMoves": [ + "MOVE_BLIZZARD", + "MOVE_BULLDOZE", + "MOVE_DRACO_METEOR", + "MOVE_DRAGON_CLAW", + "MOVE_EARTHQUAKE", + "MOVE_ENDURE", + "MOVE_FIRE_BLAST", + "MOVE_FIRE_PUNCH", + "MOVE_FLAMETHROWER", + "MOVE_FOCUS_BLAST", + "MOVE_GIGA_DRAIN", + "MOVE_GIGA_IMPACT", + "MOVE_HYDRO_PUMP", + "MOVE_HYPER_BEAM", + "MOVE_ICE_BEAM", + "MOVE_KNOCK_OFF", + "MOVE_OUTRAGE", + "MOVE_ROCK_SLIDE", + "MOVE_SLUDGE_BOMB", + "MOVE_SUBSTITUTE", + "MOVE_THUNDER", + "MOVE_THUNDERBOLT", + "MOVE_THUNDER_PUNCH", + "MOVE_TOXIC" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "GOODRA_HISUI": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_ABSORB" + }, + { + "Level": "1", + "Move": "MOVE_ACID_ARMOR" + }, + { + "Level": "1", + "Move": "MOVE_IRON_DEFENSE" + }, + { + "Level": "5", + "Move": "MOVE_WATER_GUN" + }, + { + "Level": "8", + "Move": "MOVE_CHARM" + }, + { + "Level": "10", + "Move": "MOVE_DRAGON_BREATH" + }, + { + "Level": "15", + "Move": "MOVE_PROTECT" + }, + { + "Level": "18", + "Move": "MOVE_MUD_SHOT" + }, + { + "Level": "25", + "Move": "MOVE_WATER_PULSE" + }, + { + "Level": "30", + "Move": "MOVE_DRAGON_PULSE" + }, + { + "Level": "35", + "Move": "MOVE_TAKE_DOWN" + }, + { + "Level": "41", + "Move": "MOVE_CURSE" + }, + { + "Level": "44", + "Move": "MOVE_IRON_TAIL" + }, + { + "Level": "45", + "Move": "MOVE_BODY_SLAM" + }, + { + "Level": "55", + "Move": "MOVE_HEAVY_SLAM" + }, + { + "Level": "56", + "Move": "MOVE_SURF" + }, + { + "Level": "58", + "Move": "MOVE_SLUDGE_WAVE" + } + ], + "TMMoves": [ + "MOVE_BLIZZARD", + "MOVE_BULLDOZE", + "MOVE_DRACO_METEOR", + "MOVE_DRAGON_CLAW", + "MOVE_EARTHQUAKE", + "MOVE_ENDURE", + "MOVE_FIRE_BLAST", + "MOVE_FIRE_PUNCH", + "MOVE_FLAMETHROWER", + "MOVE_FLASH_CANNON", + "MOVE_GIGA_IMPACT", + "MOVE_HYDRO_PUMP", + "MOVE_HYPER_BEAM", + "MOVE_ICE_BEAM", + "MOVE_IRON_HEAD", + "MOVE_KNOCK_OFF", + "MOVE_OUTRAGE", + "MOVE_ROCK_SLIDE", + "MOVE_ROCK_TOMB", + "MOVE_SLUDGE_BOMB", + "MOVE_SUBSTITUTE", + "MOVE_THUNDER", + "MOVE_THUNDERBOLT", + "MOVE_THUNDER_PUNCH", + "MOVE_TOXIC" + ], + "TutorMoves": [ + "MOVE_BREAKING_SWIPE" + ], + "EggMoves": [] + }, + "KLEFKI": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "8", + "Move": "MOVE_FAIRY_WIND" + }, + { + "Level": "13", + "Move": "MOVE_METAL_CLAW" + }, + { + "Level": "20", + "Move": "MOVE_METAL_SOUND" + }, + { + "Level": "24", + "Move": "MOVE_DRAINING_KISS" + }, + { + "Level": "36", + "Move": "MOVE_FLASH_CANNON" + }, + { + "Level": "40", + "Move": "MOVE_PLAY_ROUGH" + }, + { + "Level": "44", + "Move": "MOVE_DAZZLING_GLEAM" + }, + { + "Level": "52", + "Move": "MOVE_HEAL_BLOCK" + } + ], + "TMMoves": [ + "MOVE_CALM_MIND", + "MOVE_DOUBLE_TEAM", + "MOVE_ENDURE", + "MOVE_FUTURE_SIGHT", + "MOVE_GIGA_IMPACT", + "MOVE_HYPER_BEAM", + "MOVE_IRON_DEFENSE", + "MOVE_LIGHT_SCREEN", + "MOVE_PROTECT", + "MOVE_PSYCHIC", + "MOVE_PSYSHOCK", + "MOVE_REFLECT", + "MOVE_SPIKES", + "MOVE_SUBSTITUTE", + "MOVE_SWIFT", + "MOVE_THUNDER_WAVE" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "PHANTUMP": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "8", + "Move": "MOVE_LEECH_SEED" + }, + { + "Level": "12", + "Move": "MOVE_CONFUSE_RAY" + }, + { + "Level": "16", + "Move": "MOVE_WILL_O_WISP" + }, + { + "Level": "24", + "Move": "MOVE_GROWTH" + }, + { + "Level": "28", + "Move": "MOVE_HORN_LEECH" + }, + { + "Level": "32", + "Move": "MOVE_FORESTS_CURSE" + }, + { + "Level": "36", + "Move": "MOVE_PHANTOM_FORCE" + }, + { + "Level": "44", + "Move": "MOVE_WOOD_HAMMER" + }, + { + "Level": "50", + "Move": "MOVE_CURSE" + } + ], + "TMMoves": [ + "MOVE_DARK_PULSE", + "MOVE_DIG", + "MOVE_ENDURE", + "MOVE_ENERGY_BALL", + "MOVE_GIGA_DRAIN", + "MOVE_HEAL_BLOCK", + "MOVE_MAGICAL_LEAF", + "MOVE_POISON_JAB", + "MOVE_PROTECT", + "MOVE_PSYCHIC", + "MOVE_REFLECT", + "MOVE_ROCK_SLIDE", + "MOVE_SAFEGUARD", + "MOVE_SHADOW_BALL", + "MOVE_SHADOW_CLAW", + "MOVE_SOLAR_BEAM", + "MOVE_SUBSTITUTE" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "TREVENANT": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "8", + "Move": "MOVE_LEECH_SEED" + }, + { + "Level": "12", + "Move": "MOVE_CONFUSE_RAY" + }, + { + "Level": "16", + "Move": "MOVE_WILL_O_WISP" + }, + { + "Level": "24", + "Move": "MOVE_GROWTH" + }, + { + "Level": "28", + "Move": "MOVE_HORN_LEECH" + }, + { + "Level": "30", + "Move": "MOVE_SHADOW_CLAW" + }, + { + "Level": "32", + "Move": "MOVE_FORESTS_CURSE" + }, + { + "Level": "36", + "Move": "MOVE_PHANTOM_FORCE" + }, + { + "Level": "44", + "Move": "MOVE_WOOD_HAMMER" + }, + { + "Level": "50", + "Move": "MOVE_CURSE" + } + ], + "TMMoves": [ + "MOVE_CALM_MIND", + "MOVE_DARK_PULSE", + "MOVE_DIG", + "MOVE_EARTHQUAKE", + "MOVE_ENDURE", + "MOVE_ENERGY_BALL", + "MOVE_FOCUS_BLAST", + "MOVE_GIGA_DRAIN", + "MOVE_GIGA_IMPACT", + "MOVE_HEAL_BLOCK", + "MOVE_HYPER_BEAM", + "MOVE_MAGICAL_LEAF", + "MOVE_POISON_JAB", + "MOVE_PROTECT", + "MOVE_PSYCHIC", + "MOVE_REFLECT", + "MOVE_ROCK_SLIDE", + "MOVE_SAFEGUARD", + "MOVE_SHADOW_BALL", + "MOVE_SOLAR_BEAM", + "MOVE_SUBSTITUTE", + "MOVE_X_SCISSOR" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "PUMPKABOO": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_TRICK_OR_TREAT" + }, + { + "Level": "4", + "Move": "MOVE_SHADOW_SNEAK" + }, + { + "Level": "8", + "Move": "MOVE_CONFUSE_RAY" + }, + { + "Level": "12", + "Move": "MOVE_RAZOR_LEAF" + }, + { + "Level": "16", + "Move": "MOVE_LEECH_SEED" + }, + { + "Level": "20", + "Move": "MOVE_BULLET_SEED" + }, + { + "Level": "24", + "Move": "MOVE_BRUTAL_SWING" + }, + { + "Level": "27", + "Move": "MOVE_HYPNOSIS" + }, + { + "Level": "36", + "Move": "MOVE_SHADOW_BALL" + }, + { + "Level": "40", + "Move": "MOVE_MYSTICAL_FIRE" + }, + { + "Level": "46", + "Move": "MOVE_POWER_WHIP" + } + ], + "TMMoves": [ + "MOVE_CURSE", + "MOVE_DARK_PULSE", + "MOVE_ENDURE", + "MOVE_ENERGY_BALL", + "MOVE_FIRE_BLAST", + "MOVE_FIRE_SPIN", + "MOVE_FLAMETHROWER", + "MOVE_GIGA_DRAIN", + "MOVE_LIGHT_SCREEN", + "MOVE_PROTECT", + "MOVE_PSYCHIC", + "MOVE_ROCK_SLIDE", + "MOVE_SAFEGUARD", + "MOVE_SELF_DESTRUCT", + "MOVE_SLUDGE_BOMB", + "MOVE_SOLAR_BEAM", + "MOVE_SUBSTITUTE", + "MOVE_WILL_O_WISP" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "GOURGEIST": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_TRICK_OR_TREAT" + }, + { + "Level": "1", + "Move": "MOVE_MOONBLAST" + }, + { + "Level": "4", + "Move": "MOVE_SHADOW_SNEAK" + }, + { + "Level": "8", + "Move": "MOVE_CONFUSE_RAY" + }, + { + "Level": "12", + "Move": "MOVE_RAZOR_LEAF" + }, + { + "Level": "16", + "Move": "MOVE_LEECH_SEED" + }, + { + "Level": "20", + "Move": "MOVE_BULLET_SEED" + }, + { + "Level": "24", + "Move": "MOVE_BRUTAL_SWING" + }, + { + "Level": "27", + "Move": "MOVE_HYPNOSIS" + }, + { + "Level": "36", + "Move": "MOVE_SHADOW_BALL" + }, + { + "Level": "40", + "Move": "MOVE_MYSTICAL_FIRE" + }, + { + "Level": "44", + "Move": "MOVE_PHANTOM_FORCE" + }, + { + "Level": "46", + "Move": "MOVE_POWER_WHIP" + }, + { + "Level": "52", + "Move": "MOVE_EXPLOSION" + } + ], + "TMMoves": [ + "MOVE_CURSE", + "MOVE_DARK_PULSE", + "MOVE_ENDURE", + "MOVE_ENERGY_BALL", + "MOVE_FIRE_BLAST", + "MOVE_FIRE_SPIN", + "MOVE_FLAMETHROWER", + "MOVE_GIGA_DRAIN", + "MOVE_GIGA_IMPACT", + "MOVE_HYPER_BEAM", + "MOVE_LIGHT_SCREEN", + "MOVE_NASTY_PLOT", + "MOVE_PROTECT", + "MOVE_PSYCHIC", + "MOVE_ROCK_SLIDE", + "MOVE_SAFEGUARD", + "MOVE_SELF_DESTRUCT", + "MOVE_SHADOW_CLAW", + "MOVE_SLUDGE_BOMB", + "MOVE_SOLAR_BEAM", + "MOVE_SUBSTITUTE", + "MOVE_WILL_O_WISP" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "BERGMITE": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_HARDEN" + }, + { + "Level": "3", + "Move": "MOVE_TACKLE" + }, + { + "Level": "9", + "Move": "MOVE_CURSE" + }, + { + "Level": "12", + "Move": "MOVE_ICY_WIND" + }, + { + "Level": "15", + "Move": "MOVE_PROTECT" + }, + { + "Level": "21", + "Move": "MOVE_BITE" + }, + { + "Level": "24", + "Move": "MOVE_ICE_FANG" + }, + { + "Level": "27", + "Move": "MOVE_IRON_DEFENSE" + }, + { + "Level": "30", + "Move": "MOVE_RECOVER" + }, + { + "Level": "33", + "Move": "MOVE_CRUNCH" + }, + { + "Level": "36", + "Move": "MOVE_TAKE_DOWN" + }, + { + "Level": "42", + "Move": "MOVE_DOUBLE_EDGE" + }, + { + "Level": "54", + "Move": "MOVE_BLIZZARD" + } + ], + "TMMoves": [ + "MOVE_BODY_SLAM", + "MOVE_BULLDOZE", + "MOVE_ENDURE", + "MOVE_ICE_BEAM", + "MOVE_ROCK_SLIDE", + "MOVE_ROCK_TOMB", + "MOVE_STONE_EDGE", + "MOVE_SUBSTITUTE" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "AVALUGG": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_HARDEN" + }, + { + "Level": "1", + "Move": "MOVE_HEAVY_SLAM" + }, + { + "Level": "3", + "Move": "MOVE_TACKLE" + }, + { + "Level": "9", + "Move": "MOVE_CURSE" + }, + { + "Level": "12", + "Move": "MOVE_ICY_WIND" + }, + { + "Level": "15", + "Move": "MOVE_PROTECT" + }, + { + "Level": "21", + "Move": "MOVE_BITE" + }, + { + "Level": "24", + "Move": "MOVE_ICE_FANG" + }, + { + "Level": "27", + "Move": "MOVE_IRON_DEFENSE" + }, + { + "Level": "30", + "Move": "MOVE_RECOVER" + }, + { + "Level": "33", + "Move": "MOVE_CRUNCH" + }, + { + "Level": "36", + "Move": "MOVE_TAKE_DOWN" + }, + { + "Level": "39", + "Move": "MOVE_ICICLE_CRASH" + }, + { + "Level": "42", + "Move": "MOVE_DOUBLE_EDGE" + }, + { + "Level": "54", + "Move": "MOVE_BLIZZARD" + } + ], + "TMMoves": [ + "MOVE_BODY_SLAM", + "MOVE_BULLDOZE", + "MOVE_EARTHQUAKE", + "MOVE_ENDURE", + "MOVE_FLASH_CANNON", + "MOVE_GIGA_IMPACT", + "MOVE_HYDRO_PUMP", + "MOVE_HYPER_BEAM", + "MOVE_ICE_BEAM", + "MOVE_ROCK_SLIDE", + "MOVE_ROCK_TOMB", + "MOVE_STONE_EDGE", + "MOVE_SUBSTITUTE", + "MOVE_SURF" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "AVALUGG_HISUI": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_HARDEN" + }, + { + "Level": "1", + "Move": "MOVE_HEAVY_SLAM" + }, + { + "Level": "3", + "Move": "MOVE_TACKLE" + }, + { + "Level": "9", + "Move": "MOVE_CURSE" + }, + { + "Level": "12", + "Move": "MOVE_ICY_WIND" + }, + { + "Level": "15", + "Move": "MOVE_PROTECT" + }, + { + "Level": "21", + "Move": "MOVE_BITE" + }, + { + "Level": "24", + "Move": "MOVE_ICE_FANG" + }, + { + "Level": "27", + "Move": "MOVE_IRON_DEFENSE" + }, + { + "Level": "30", + "Move": "MOVE_RECOVER" + }, + { + "Level": "33", + "Move": "MOVE_CRUNCH" + }, + { + "Level": "36", + "Move": "MOVE_TAKE_DOWN" + }, + { + "Level": "39", + "Move": "MOVE_ROCK_BLAST" + }, + { + "Level": "42", + "Move": "MOVE_DOUBLE_EDGE" + }, + { + "Level": "46", + "Move": "MOVE_STONE_EDGE" + }, + { + "Level": "48", + "Move": "MOVE_IRON_HEAD" + }, + { + "Level": "54", + "Move": "MOVE_BLIZZARD" + } + ], + "TMMoves": [ + "MOVE_BODY_SLAM", + "MOVE_BULLDOZE", + "MOVE_DIG", + "MOVE_EARTHQUAKE", + "MOVE_ENDURE", + "MOVE_FLASH_CANNON", + "MOVE_GIGA_IMPACT", + "MOVE_HYDRO_PUMP", + "MOVE_HYPER_BEAM", + "MOVE_ICE_BEAM", + "MOVE_ROCK_SLIDE", + "MOVE_ROCK_TOMB", + "MOVE_STEALTH_ROCK", + "MOVE_SUBSTITUTE", + "MOVE_SURF" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "NOIBAT": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_ABSORB" + }, + { + "Level": "4", + "Move": "MOVE_GUST" + }, + { + "Level": "8", + "Move": "MOVE_SUPERSONIC" + }, + { + "Level": "12", + "Move": "MOVE_DOUBLE_TEAM" + }, + { + "Level": "16", + "Move": "MOVE_WING_ATTACK" + }, + { + "Level": "20", + "Move": "MOVE_BITE" + }, + { + "Level": "24", + "Move": "MOVE_LEECH_LIFE" + }, + { + "Level": "28", + "Move": "MOVE_WHIRLWIND" + }, + { + "Level": "32", + "Move": "MOVE_SUPER_FANG" + }, + { + "Level": "36", + "Move": "MOVE_AIR_SLASH" + }, + { + "Level": "40", + "Move": "MOVE_SCREECH" + }, + { + "Level": "44", + "Move": "MOVE_HURRICANE" + } + ], + "TMMoves": [ + "MOVE_AERIAL_ACE", + "MOVE_AGILITY", + "MOVE_BRICK_BREAK", + "MOVE_DARK_PULSE", + "MOVE_DRACO_METEOR", + "MOVE_DRAGON_CLAW", + "MOVE_DRAGON_PULSE", + "MOVE_ENDURE", + "MOVE_FLY", + "MOVE_HEAT_WAVE", + "MOVE_HYPER_VOICE", + "MOVE_OUTRAGE", + "MOVE_PROTECT", + "MOVE_PSYCHIC", + "MOVE_SHADOW_BALL", + "MOVE_SHADOW_CLAW", + "MOVE_SOLAR_BEAM", + "MOVE_SUBSTITUTE", + "MOVE_SWIFT", + "MOVE_TAUNT", + "MOVE_U_TURN", + "MOVE_WILD_CHARGE" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "NOIVERN": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_ABSORB" + }, + { + "Level": "1", + "Move": "MOVE_MOONLIGHT" + }, + { + "Level": "4", + "Move": "MOVE_GUST" + }, + { + "Level": "8", + "Move": "MOVE_SUPERSONIC" + }, + { + "Level": "12", + "Move": "MOVE_DOUBLE_TEAM" + }, + { + "Level": "16", + "Move": "MOVE_WING_ATTACK" + }, + { + "Level": "20", + "Move": "MOVE_BITE" + }, + { + "Level": "24", + "Move": "MOVE_LEECH_LIFE" + }, + { + "Level": "28", + "Move": "MOVE_WHIRLWIND" + }, + { + "Level": "32", + "Move": "MOVE_SUPER_FANG" + }, + { + "Level": "36", + "Move": "MOVE_AIR_SLASH" + }, + { + "Level": "40", + "Move": "MOVE_SCREECH" + }, + { + "Level": "44", + "Move": "MOVE_HURRICANE" + }, + { + "Level": "52", + "Move": "MOVE_BOOMBURST" + } + ], + "TMMoves": [ + "MOVE_AERIAL_ACE", + "MOVE_AGILITY", + "MOVE_BODY_SLAM", + "MOVE_BRICK_BREAK", + "MOVE_DARK_PULSE", + "MOVE_DRACO_METEOR", + "MOVE_DRAGON_CLAW", + "MOVE_ENDURE", + "MOVE_FLAMETHROWER", + "MOVE_FLY", + "MOVE_FOCUS_BLAST", + "MOVE_GIGA_IMPACT", + "MOVE_HEAT_WAVE", + "MOVE_HYPER_BEAM", + "MOVE_HYPER_VOICE", + "MOVE_IRON_TAIL", + "MOVE_OUTRAGE", + "MOVE_PROTECT", + "MOVE_PSYCHIC", + "MOVE_SHADOW_BALL", + "MOVE_SHADOW_CLAW", + "MOVE_SOLAR_BEAM", + "MOVE_SUBSTITUTE", + "MOVE_SWIFT", + "MOVE_TAUNT", + "MOVE_U_TURN", + "MOVE_WATER_PULSE", + "MOVE_WILD_CHARGE" + ], + "TutorMoves": [ + "MOVE_DRAGON_PULSE" + ], + "EggMoves": [] + }, + "XERNEAS": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "5", + "Move": "MOVE_LIGHT_SCREEN" + }, + { + "Level": "20", + "Move": "MOVE_NIGHT_SLASH" + }, + { + "Level": "35", + "Move": "MOVE_HORN_LEECH" + }, + { + "Level": "50", + "Move": "MOVE_TAKE_DOWN" + }, + { + "Level": "55", + "Move": "MOVE_GEOMANCY" + }, + { + "Level": "60", + "Move": "MOVE_MOONBLAST" + }, + { + "Level": "70", + "Move": "MOVE_MEGAHORN" + }, + { + "Level": "75", + "Move": "MOVE_CLOSE_COMBAT" + }, + { + "Level": "80", + "Move": "MOVE_OUTRAGE" + }, + { + "Level": "85", + "Move": "MOVE_GIGA_IMPACT" + } + ], + "TMMoves": [ + "MOVE_BODY_SLAM", + "MOVE_CALM_MIND", + "MOVE_DAZZLING_GLEAM", + "MOVE_ENDURE", + "MOVE_FLASH_CANNON", + "MOVE_FOCUS_BLAST", + "MOVE_HYPER_BEAM", + "MOVE_HYPER_VOICE", + "MOVE_PLAY_ROUGH", + "MOVE_PROTECT", + "MOVE_PSYCHIC", + "MOVE_PSYSHOCK", + "MOVE_REFLECT", + "MOVE_ROCK_SLIDE", + "MOVE_SUBSTITUTE", + "MOVE_SWIFT", + "MOVE_THUNDER", + "MOVE_THUNDERBOLT", + "MOVE_THUNDER_WAVE", + "MOVE_ZEN_HEADBUTT" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "YVELTAL": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_GUST" + }, + { + "Level": "1", + "Move": "MOVE_DOUBLE_TEAM" + }, + { + "Level": "5", + "Move": "MOVE_TAUNT" + }, + { + "Level": "10", + "Move": "MOVE_SNARL" + }, + { + "Level": "35", + "Move": "MOVE_AIR_SLASH" + }, + { + "Level": "40", + "Move": "MOVE_DARK_PULSE" + }, + { + "Level": "45", + "Move": "MOVE_PSYCHIC" + }, + { + "Level": "55", + "Move": "MOVE_OBLIVION_WING" + }, + { + "Level": "60", + "Move": "MOVE_PHANTOM_FORCE" + }, + { + "Level": "65", + "Move": "MOVE_DRAGON_RUSH" + }, + { + "Level": "70", + "Move": "MOVE_HURRICANE" + }, + { + "Level": "75", + "Move": "MOVE_FOCUS_BLAST" + }, + { + "Level": "85", + "Move": "MOVE_HYPER_BEAM" + } + ], + "TMMoves": [ + "MOVE_BODY_SLAM", + "MOVE_DRAGON_CLAW", + "MOVE_ENDURE", + "MOVE_FLY", + "MOVE_GIGA_IMPACT", + "MOVE_HEAL_BLOCK", + "MOVE_HEAT_WAVE", + "MOVE_HYPER_VOICE", + "MOVE_PROTECT", + "MOVE_ROCK_SLIDE", + "MOVE_SHADOW_BALL", + "MOVE_SHADOW_CLAW", + "MOVE_SUBSTITUTE", + "MOVE_SWIFT", + "MOVE_U_TURN", + "MOVE_ZEN_HEADBUTT" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "ZYGARDE": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_BITE" + }, + { + "Level": "1", + "Move": "MOVE_DRAGON_BREATH" + }, + { + "Level": "1", + "Move": "MOVE_BULLDOZE" + }, + { + "Level": "1", + "Move": "MOVE_THOUSAND_ARROWS" + }, + { + "Level": "1", + "Move": "MOVE_THOUSAND_WAVES" + }, + { + "Level": "1", + "Move": "MOVE_LANDS_WRATH" + }, + { + "Level": "1", + "Move": "MOVE_CORE_ENFORCER" + }, + { + "Level": "8", + "Move": "MOVE_HAZE" + }, + { + "Level": "16", + "Move": "MOVE_DIG" + }, + { + "Level": "24", + "Move": "MOVE_SAFEGUARD" + }, + { + "Level": "32", + "Move": "MOVE_CRUNCH" + }, + { + "Level": "40", + "Move": "MOVE_DRAGON_PULSE" + }, + { + "Level": "44", + "Move": "MOVE_BREAKING_SWIPE" + }, + { + "Level": "56", + "Move": "MOVE_GLARE" + }, + { + "Level": "60", + "Move": "MOVE_SLUDGE_WAVE" + }, + { + "Level": "70", + "Move": "MOVE_EXTREME_SPEED" + }, + { + "Level": "80", + "Move": "MOVE_EARTHQUAKE" + }, + { + "Level": "88", + "Move": "MOVE_OUTRAGE" + } + ], + "TMMoves": [ + "MOVE_BODY_SLAM", + "MOVE_BRICK_BREAK", + "MOVE_DRACO_METEOR", + "MOVE_EARTH_POWER", + "MOVE_ENDURE", + "MOVE_FOCUS_BLAST", + "MOVE_GIGA_IMPACT", + "MOVE_HYPER_BEAM", + "MOVE_HYPER_VOICE", + "MOVE_IRON_HEAD", + "MOVE_PROTECT", + "MOVE_ROCK_SLIDE", + "MOVE_STONE_EDGE", + "MOVE_SUBSTITUTE", + "MOVE_SWIFT", + "MOVE_ZEN_HEADBUTT" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "DIANCIE": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_ROCK_THROW" + }, + { + "Level": "1", + "Move": "MOVE_HARDEN" + }, + { + "Level": "1", + "Move": "MOVE_DIAMOND_STORM" + }, + { + "Level": "7", + "Move": "MOVE_AMNESIA" + }, + { + "Level": "14", + "Move": "MOVE_FAKE_TEARS" + }, + { + "Level": "21", + "Move": "MOVE_DRAINING_KISS" + }, + { + "Level": "33", + "Move": "MOVE_ROCK_SLIDE" + }, + { + "Level": "42", + "Move": "MOVE_LIGHT_SCREEN" + }, + { + "Level": "44", + "Move": "MOVE_POWER_GEM" + }, + { + "Level": "46", + "Move": "MOVE_STEALTH_ROCK" + }, + { + "Level": "50", + "Move": "MOVE_STONE_EDGE" + }, + { + "Level": "54", + "Move": "MOVE_MOONBLAST" + } + ], + "TMMoves": [ + "MOVE_BODY_SLAM", + "MOVE_CALM_MIND", + "MOVE_DAZZLING_GLEAM", + "MOVE_EARTH_POWER", + "MOVE_ENDURE", + "MOVE_FLASH_CANNON", + "MOVE_GIGA_IMPACT", + "MOVE_HYPER_BEAM", + "MOVE_IRON_DEFENSE", + "MOVE_METRONOME", + "MOVE_PLAY_ROUGH", + "MOVE_PROTECT", + "MOVE_PSYCHIC", + "MOVE_PSYSHOCK", + "MOVE_REFLECT", + "MOVE_ROCK_TOMB", + "MOVE_SAFEGUARD", + "MOVE_SPIKES", + "MOVE_SUBSTITUTE", + "MOVE_SWIFT" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "HOOPA_CONFINED": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_CONFUSION" + }, + { + "Level": "15", + "Move": "MOVE_LIGHT_SCREEN" + }, + { + "Level": "19", + "Move": "MOVE_PSYBEAM" + }, + { + "Level": "22", + "Move": "MOVE_KNOCK_OFF" + }, + { + "Level": "35", + "Move": "MOVE_PHANTOM_FORCE" + }, + { + "Level": "38", + "Move": "MOVE_ZEN_HEADBUTT" + }, + { + "Level": "42", + "Move": "MOVE_SHADOW_BALL" + }, + { + "Level": "45", + "Move": "MOVE_NASTY_PLOT" + }, + { + "Level": "52", + "Move": "MOVE_PSYCHIC" + }, + { + "Level": "60", + "Move": "MOVE_HYPERSPACE_HOLE" + } + ], + "TMMoves": [ + "MOVE_BRICK_BREAK", + "MOVE_CALM_MIND", + "MOVE_DARK_PULSE", + "MOVE_ENDURE", + "MOVE_ENERGY_BALL", + "MOVE_FIRE_PUNCH", + "MOVE_FOCUS_BLAST", + "MOVE_FUTURE_SIGHT", + "MOVE_GIGA_IMPACT", + "MOVE_GUNK_SHOT", + "MOVE_HEAL_BLOCK", + "MOVE_HYPER_BEAM", + "MOVE_ICE_PUNCH", + "MOVE_PROTECT", + "MOVE_PSYSHOCK", + "MOVE_REFLECT", + "MOVE_ROCK_TOMB", + "MOVE_SUBSTITUTE", + "MOVE_SWIFT", + "MOVE_TAKE_DOWN", + "MOVE_TAUNT", + "MOVE_THUNDERBOLT", + "MOVE_THUNDER_PUNCH", + "MOVE_THUNDER_WAVE" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "HOOPA_UNBOUND": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_CONFUSION" + }, + { + "Level": "15", + "Move": "MOVE_LIGHT_SCREEN" + }, + { + "Level": "19", + "Move": "MOVE_PSYBEAM" + }, + { + "Level": "22", + "Move": "MOVE_KNOCK_OFF" + }, + { + "Level": "35", + "Move": "MOVE_PHANTOM_FORCE" + }, + { + "Level": "38", + "Move": "MOVE_ZEN_HEADBUTT" + }, + { + "Level": "42", + "Move": "MOVE_SHADOW_BALL" + }, + { + "Level": "45", + "Move": "MOVE_NASTY_PLOT" + }, + { + "Level": "52", + "Move": "MOVE_PSYCHIC" + }, + { + "Level": "60", + "Move": "MOVE_HYPERSPACE_FURY" + } + ], + "TMMoves": [ + "MOVE_BRICK_BREAK", + "MOVE_CALM_MIND", + "MOVE_DARK_PULSE", + "MOVE_ENDURE", + "MOVE_ENERGY_BALL", + "MOVE_FIRE_PUNCH", + "MOVE_FOCUS_BLAST", + "MOVE_FUTURE_SIGHT", + "MOVE_GIGA_IMPACT", + "MOVE_GUNK_SHOT", + "MOVE_HEAL_BLOCK", + "MOVE_HYPER_BEAM", + "MOVE_ICE_PUNCH", + "MOVE_PROTECT", + "MOVE_PSYSHOCK", + "MOVE_REFLECT", + "MOVE_ROCK_TOMB", + "MOVE_SUBSTITUTE", + "MOVE_SWIFT", + "MOVE_TAKE_DOWN", + "MOVE_TAUNT", + "MOVE_THUNDERBOLT", + "MOVE_THUNDER_PUNCH", + "MOVE_THUNDER_WAVE" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "VOLCANION": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_WATER_GUN" + }, + { + "Level": "1", + "Move": "MOVE_FIRE_SPIN" + }, + { + "Level": "1", + "Move": "MOVE_STEAM_ERUPTION" + }, + { + "Level": "6", + "Move": "MOVE_LEER" + }, + { + "Level": "18", + "Move": "MOVE_MUD_SHOT" + }, + { + "Level": "24", + "Move": "MOVE_WATER_PULSE" + }, + { + "Level": "30", + "Move": "MOVE_HEAT_CRASH" + }, + { + "Level": "33", + "Move": "MOVE_TAKE_DOWN" + }, + { + "Level": "40", + "Move": "MOVE_MIST" + }, + { + "Level": "40", + "Move": "MOVE_HAZE" + }, + { + "Level": "42", + "Move": "MOVE_HEAVY_SLAM" + }, + { + "Level": "46", + "Move": "MOVE_HYDRO_PUMP" + }, + { + "Level": "50", + "Move": "MOVE_FLARE_BLITZ" + }, + { + "Level": "54", + "Move": "MOVE_OVERHEAT" + }, + { + "Level": "60", + "Move": "MOVE_EXPLOSION" + } + ], + "TMMoves": [ + "MOVE_BODY_SLAM", + "MOVE_BRICK_BREAK", + "MOVE_DIG", + "MOVE_EARTHQUAKE", + "MOVE_EARTH_POWER", + "MOVE_ENDURE", + "MOVE_FIRE_BLAST", + "MOVE_FIRE_FANG", + "MOVE_FLAMETHROWER", + "MOVE_FLASH_CANNON", + "MOVE_FOCUS_BLAST", + "MOVE_GIGA_IMPACT", + "MOVE_HEAT_WAVE", + "MOVE_HYPER_BEAM", + "MOVE_LIQUIDATION", + "MOVE_PROTECT", + "MOVE_ROAR", + "MOVE_ROCK_SLIDE", + "MOVE_ROCK_TOMB", + "MOVE_SELF_DESTRUCT", + "MOVE_SLUDGE_BOMB", + "MOVE_SOLAR_BEAM", + "MOVE_STONE_EDGE", + "MOVE_SUBSTITUTE", + "MOVE_TAUNT", + "MOVE_THUNDER_FANG", + "MOVE_WILD_CHARGE", + "MOVE_WILL_O_WISP" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "DRAMPA": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_LEER" + }, + { + "Level": "1", + "Move": "MOVE_TWISTER" + }, + { + "Level": "5", + "Move": "MOVE_PROTECT" + }, + { + "Level": "10", + "Move": "MOVE_GLARE" + }, + { + "Level": "15", + "Move": "MOVE_SAFEGUARD" + }, + { + "Level": "20", + "Move": "MOVE_DRAGON_BREATH" + }, + { + "Level": "25", + "Move": "MOVE_ICY_WIND" + }, + { + "Level": "28", + "Move": "MOVE_BODY_SLAM" + }, + { + "Level": "32", + "Move": "MOVE_AMNESIA" + }, + { + "Level": "35", + "Move": "MOVE_DRAGON_PULSE" + }, + { + "Level": "40", + "Move": "MOVE_LIGHT_SCREEN" + }, + { + "Level": "44", + "Move": "MOVE_FLY" + }, + { + "Level": "50", + "Move": "MOVE_HYPER_VOICE" + }, + { + "Level": "54", + "Move": "MOVE_OUTRAGE" + }, + { + "Level": "56", + "Move": "MOVE_DRAGON_RUSH" + } + ], + "TMMoves": [ + "MOVE_BLIZZARD", + "MOVE_CALM_MIND", + "MOVE_DRACO_METEOR", + "MOVE_DRAGON_CLAW", + "MOVE_EARTHQUAKE", + "MOVE_EARTH_POWER", + "MOVE_ENDURE", + "MOVE_ENERGY_BALL", + "MOVE_FIRE_BLAST", + "MOVE_FLAMETHROWER", + "MOVE_FOCUS_BLAST", + "MOVE_GIGA_IMPACT", + "MOVE_HEAT_WAVE", + "MOVE_HURRICANE", + "MOVE_HYDRO_PUMP", + "MOVE_HYPER_BEAM", + "MOVE_ICE_BEAM", + "MOVE_PLAY_ROUGH", + "MOVE_ROCK_SLIDE", + "MOVE_SHADOW_BALL", + "MOVE_SHADOW_CLAW", + "MOVE_SOLAR_BEAM", + "MOVE_SUBSTITUTE", + "MOVE_SURF", + "MOVE_SWIFT", + "MOVE_THUNDER", + "MOVE_THUNDERBOLT", + "MOVE_THUNDER_WAVE", + "MOVE_WHIRLWIND", + "MOVE_WORK_UP" + ], + "TutorMoves": [], + "EggMoves": [] + }, + "FALINKS": { + "LevelMoves": [ + { + "Level": "1", + "Move": "MOVE_TACKLE" + }, + { + "Level": "1", + "Move": "MOVE_PROTECT" + }, + { + "Level": "5", + "Move": "MOVE_ROCK_SMASH" + }, + { + "Level": "10", + "Move": "MOVE_FOCUS_ENERGY" + }, + { + "Level": "15", + "Move": "MOVE_HEADBUTT" + }, + { + "Level": "20", + "Move": "MOVE_BULK_UP" + }, + { + "Level": "25", + "Move": "MOVE_ENDURE" + }, + { + "Level": "32", + "Move": "MOVE_IRON_HEAD" + }, + { + "Level": "36", + "Move": "MOVE_BRICK_BREAK" + }, + { + "Level": "40", + "Move": "MOVE_NO_RETREAT" + }, + { + "Level": "43", + "Move": "MOVE_IRON_DEFENSE" + }, + { + "Level": "48", + "Move": "MOVE_CLOSE_COMBAT" + }, + { + "Level": "52", + "Move": "MOVE_MEGAHORN" + } + ], + "TMMoves": [ + "MOVE_AGILITY", + "MOVE_BODY_SLAM", + "MOVE_FOCUS_BLAST", + "MOVE_GIGA_IMPACT", + "MOVE_HYPER_BEAM", + "MOVE_KNOCK_OFF", + "MOVE_POISON_JAB", + "MOVE_ROCK_SLIDE", + "MOVE_ROCK_TOMB", + "MOVE_SUBSTITUTE", + "MOVE_SWORDS_DANCE", + "MOVE_ZEN_HEADBUTT" + ], + "TutorMoves": [], + "EggMoves": [] + } +} \ No newline at end of file diff --git a/tools/wav2agb/.gitignore b/tools/wav2agb/.gitignore new file mode 100644 index 0000000000..2715405656 --- /dev/null +++ b/tools/wav2agb/.gitignore @@ -0,0 +1,10 @@ +*.o +*.exe +*.s +*.gba +*.sdf + +wav2agb +Debug +Release +.vs diff --git a/tools/aif2pcm/LICENSE b/tools/wav2agb/LICENSE similarity index 75% rename from tools/aif2pcm/LICENSE rename to tools/wav2agb/LICENSE index ce51485925..d52bf8ee67 100644 --- a/tools/aif2pcm/LICENSE +++ b/tools/wav2agb/LICENSE @@ -1,20 +1,21 @@ -Copyright (c) 2016 huderlem -Copyright (c) 2005, 2006 by Marco Trillo - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. +The MIT License (MIT) + +Copyright (c) 2016 ipatix + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/tools/wav2agb/Makefile b/tools/wav2agb/Makefile new file mode 100644 index 0000000000..a121730e95 --- /dev/null +++ b/tools/wav2agb/Makefile @@ -0,0 +1,33 @@ +GIT_VERSION := $(shell git describe --abbrev=7 --dirty --always --tags) + +CXX = g++ +STRIP = strip +CXXFLAGS = -Wall -Wextra -Wconversion -std=c++17 -O2 -g -DGIT_VERSION=\"$(GIT_VERSION)\" +EXE := +ifeq ($(OS),Windows_NT) + EXE := .exe +endif +BINARY = wav2agb$(EXE) + +SRC_FILES = $(wildcard *.cpp) +OBJ_FILES = $(SRC_FILES:.cpp=.o) + +LDFLAGS := + +ifneq (,$(RELEASE)) + LDFLAGS += -static + CXXFLAGS += -flto +endif + +.PHONY: clean clean +all: $(BINARY) + +clean: + rm -f $(OBJ_FILES) $(BINARY) + +$(BINARY): $(OBJ_FILES) + $(CXX) $(CXXFLAGS) $(LDFLAGS) -o $@ $^ + if [ $(RELEASE)x != x ]; then strip -s $@; fi + +%.o: %.cpp + $(CXX) -c -o $@ $< $(CXXFLAGS) diff --git a/tools/wav2agb/README.md b/tools/wav2agb/README.md new file mode 100644 index 0000000000..86f2660231 --- /dev/null +++ b/tools/wav2agb/README.md @@ -0,0 +1,29 @@ +# wav2agb +"wav2agb" is a tool to convert standard .wav files to GBA compatible .s or .bin files. Intended to convert .wav files for the use with the mp2k/m4a sound driver. + +This copy has been slightly modified from [ipatix's original implementation](https://github.com/ipatix/wav2agb) in the following ways: +1. Support outputting `.bin` files with a command line option `-b, --binary`. (The original only supports outputting `.s` assembly files.) +2. Support reading an override "pitch" value from a custom `agbp` RIFF chunk. + - This is needed to properly match some samples, due to float-point rounding errors when attempting to infer the pitch/sample rate from the .wav file's sample rate. + - If the custom `agbp` chunk isn't present, it will simply use the .wav's sample rate to calculate this "pitch" value. +3. Optionally omits trailing padding from compressed output. + +Usage: +``` +Usage: wav2agb [options] [] + +Options: +-s, --symbol | symbol name for wave header (default: file name) +-l, --lookahead | DPCM compression lookahead 1..8 (default: 3) +-c, --compress | compress output with DPCM +-f, --fast-compress | compress output with DPCM fast +--no-pad | omit trailing padding in compressed output +-b, --binary | output raw binary instead of assembly +--loop-start | override loop start (integer) +--loop-end | override loop end (integer) +--tune | override tuning (float) +--key | override midi key (int) +--rate | override base samplerate (int) +``` + +Flag -c enables compression (only supported by Pokemon Games) diff --git a/tools/wav2agb/converter.cpp b/tools/wav2agb/converter.cpp new file mode 100644 index 0000000000..c96135c149 --- /dev/null +++ b/tools/wav2agb/converter.cpp @@ -0,0 +1,462 @@ +#include "converter.h" + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "wav_file.h" + +static void agb_out(std::ofstream& ofs, const char *msg, ...) { + char buf[256]; + va_list args; + va_start(args, msg); + vsnprintf(buf, sizeof(buf), msg, args); + va_end(args); + ofs << buf; +} + +static void data_write(std::ofstream& ofs, uint32_t& block_pos, int data, bool hex) { + if (block_pos++ == 0) { + if (hex) + agb_out(ofs, "\n .byte 0x%02X", data); + else + agb_out(ofs, "\n .byte %4d", data); + } else { + if (hex) + agb_out(ofs, ", 0x%02X", data); + else + agb_out(ofs, ", %4d", data); + } + block_pos %= 16; +} + +static void bin_write_u8(std::vector& data, uint8_t value) { + data.push_back(value); +} + +static void bin_write_u32_le(std::vector& data, uint32_t value) { + data.push_back(static_cast(value & 0xFF)); + data.push_back(static_cast((value >> 8) & 0xFF)); + data.push_back(static_cast((value >> 16) & 0xFF)); + data.push_back(static_cast((value >> 24) & 0xFF)); +} + +template +const T& clamp(const T& v, const T& lo, const T& hi) { + return (v < lo) ? lo : (hi < v) ? hi : v; +} + +static void convert_uncompressed(wav_file& wf, std::ofstream& ofs) +{ + int loop_sample = 0; + + uint32_t block_pos = 0; + + for (size_t i = 0; i < wf.loopEnd; i++) { + double ds; + wf.readData(i, &ds, 1); + // TODO apply dither noise + int s = clamp(static_cast(floor(ds * 128.0)), -128, 127); + + if (wf.loopEnabled && i == wf.loopStart) + loop_sample = s; + + data_write(ofs, block_pos, s, false); + } + + data_write(ofs, block_pos, loop_sample, false); +} + +static void convert_uncompressed_bin(wav_file& wf, std::vector& data) +{ + for (size_t i = 0; i < wf.loopEnd; i++) { + double ds; + wf.readData(i, &ds, 1); + // TODO apply dither noise + int s = clamp(static_cast(floor(ds * 128.0)), -128, 127); + + bin_write_u8(data, static_cast(s)); + } + + // Align to 4 bytes. + while (data.size() % 4 != 0) { + bin_write_u8(data, 0); + } +} + +static uint32_t wav_loop_start; +static bool wav_loop_start_override = false; +static uint32_t wav_loop_end; +static bool wav_loop_end_override = false; +static double wav_tune; +static bool wav_tune_override = false; +static uint8_t wav_key; +static bool wav_key_override = false; +static uint32_t wav_rate; +static bool wav_rate_override = false; + +static bool dpcm_verbose = false; +static bool dpcm_lookahead_fast = false; +static bool dpcm_include_padding = true; +static size_t dpcm_enc_lookahead = 3; +static const size_t DPCM_BLK_SIZE = 0x40; +static const std::vector dpcmLookupTable = { + 0, 1, 4, 9, 16, 25, 36, 49, -64, -49, -36, -25, -16, -9, -4, -1 +}; +static const std::vector dpcmIndexTable = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 +}; +static const std::vector> dpcmFastLookupTable = { + {8}, {8}, {8}, {8}, {8}, {8}, {8}, {8}, {8}, {8}, {8}, {8}, {8}, {8}, {8}, {8}, + {8}, {8}, {8}, {8}, {8}, {8}, {8}, {8}, {8}, {8}, {8}, {8}, {8}, {8}, {8}, {8}, + {8}, {8}, {8}, {8}, {8}, {8}, {8}, {8}, {8}, {8}, {8}, {8}, {8}, {8}, {8}, {8}, + {8}, {8}, {8}, {8}, {8}, {8}, {8}, {8}, {8}, {8}, {8}, {8}, {8}, {8}, {8}, {8}, + {8}, {8}, {8}, {8}, {8}, {8}, {8}, {8}, {8}, {8}, {8}, {8}, {8}, {8}, {8}, {8}, + {8}, {8}, {8}, {8}, {8}, {8}, {8}, {8}, {8}, {8}, {8}, {8}, {8}, {8}, {8}, {8}, + {8}, {8}, {8}, {8}, {8}, {8}, {8}, {8}, {8}, {8}, {8}, {8}, {8}, {8}, {8}, {8}, + {8}, {8}, {8}, {8}, {8}, {8}, {8}, {8}, {8}, {8}, {8}, {8}, {8}, {8}, {8}, {8}, + {8}, {8}, {8}, {8}, {8}, {8}, {8}, {8}, {8}, {8}, {8}, {8}, {8}, {8}, {8}, {8}, + {8}, {8}, {8}, {8}, {8}, {8}, {8}, {8}, {8}, {8}, {8}, {8}, {8}, {8}, {8}, {8}, + {8}, {8}, {8}, {8}, {8}, {8}, {8}, {8}, {8}, {8}, {8}, {8}, {8}, {8}, {8}, {8}, + {8}, {8}, {8}, {8}, {8}, {8}, {8}, {8}, {8}, {8}, {8}, {8}, {8}, {8}, {8}, {8}, + {8, 9}, {8, 9}, {8, 9}, {8, 9}, {8, 9}, {8, 9}, {8, 9}, {8, 9}, {8, 9}, {8, 9}, {8, 9}, {8, 9}, {8, 9}, {8, 9}, {9, 10}, {9, 10}, + {9, 10}, {9, 10}, {9, 10}, {9, 10}, {9, 10}, {9, 10}, {9, 10}, {9, 10}, {9, 10}, {9, 10}, {9, 10}, {10, 11}, {10, 11}, {10, 11}, {10, 11}, {10, 11}, + {10, 11}, {10, 11}, {10, 11}, {10, 11}, {10, 11}, {10, 11}, {11, 12}, {11, 12}, {11, 12}, {11, 12}, {11, 12}, {11, 12}, {11, 12}, {11, 12}, {11, 12}, {12, 13}, + {12, 13}, {12, 13}, {12, 13}, {12, 13}, {12, 13}, {12, 13}, {13, 14}, {13, 14}, {13, 14}, {13, 14}, {13, 14}, {14, 15}, {14, 15}, {14, 15}, {0, 15}, {0, 1, 15}, + {1, 0}, {1, 2}, {1, 2}, {2, 1}, {2, 3}, {2, 3}, {2, 3}, {2, 3}, {3, 2}, {3, 4}, {3, 4}, {3, 4}, {3, 4}, {3, 4}, {3, 4}, {4, 3}, + {4, 5}, {4, 5}, {4, 5}, {4, 5}, {4, 5}, {4, 5}, {4, 5}, {4, 5}, {5, 4}, {5, 6}, {5, 6}, {5, 6}, {5, 6}, {5, 6}, {5, 6}, {5, 6}, + {5, 6}, {5, 6}, {5, 6}, {6, 5}, {6, 7}, {6, 7}, {6, 7}, {6, 7}, {6, 7}, {6, 7}, {6, 7}, {6, 7}, {6, 7}, {6, 7}, {6, 7}, {6, 7}, + {7}, {7}, {7}, {7}, {7}, {7}, {7}, {7}, {7}, {7}, {7}, {7}, {7}, {7}, {7}, {7}, + {7}, {7}, {7}, {7}, {7}, {7}, {7}, {7}, {7}, {7}, {7}, {7}, {7}, {7}, {7}, {7}, + {7}, {7}, {7}, {7}, {7}, {7}, {7}, {7}, {7}, {7}, {7}, {7}, {7}, {7}, {7}, {7}, + {7}, {7}, {7}, {7}, {7}, {7}, {7}, {7}, {7}, {7}, {7}, {7}, {7}, {7}, {7}, {7}, + {7}, {7}, {7}, {7}, {7}, {7}, {7}, {7}, {7}, {7}, {7}, {7}, {7}, {7}, {7}, {7}, + {7}, {7}, {7}, {7}, {7}, {7}, {7}, {7}, {7}, {7}, {7}, {7}, {7}, {7}, {7}, {7}, + {7}, {7}, {7}, {7}, {7}, {7}, {7}, {7}, {7}, {7}, {7}, {7}, {7}, {7}, {7}, {7}, + {7}, {7}, {7}, {7}, {7}, {7}, {7}, {7}, {7}, {7}, {7}, {7}, {7}, {7}, {7}, {7}, + {7}, {7}, {7}, {7}, {7}, {7}, {7}, {7}, {7}, {7}, {7}, {7}, {7}, {7}, {7}, {7}, + {7}, {7}, {7}, {7}, {7}, {7}, {7}, {7}, {7}, {7}, {7}, {7}, {7}, {7}, {7}, {7}, + {7}, {7}, {7}, {7}, {7}, {7}, {7}, {7}, {7}, {7}, {7}, {7}, {7}, {7}, {7}, {7}, + {7}, {7}, {7}, {7}, {7}, {7}, {7}, {7}, {7}, {7}, {7}, {7}, {7}, {7}, {7}, {7}, + {7}, {7}, {7}, {7}, {7}, {7}, {7}, {7}, {7}, {7}, {7}, {7}, {7}, {7}, {7} +}; + +static int squared(int x) { return x * x; } + +static void dpcm_lookahead( + int& minimumError, size_t& minimumErrorIndex, + const double *sampleBuf, const size_t lookahead, const int prevLevel) +{ + if (lookahead == 0) { + minimumError = 0; + return; + } + + minimumError = std::numeric_limits::max(); + minimumErrorIndex = dpcmLookupTable.size(); + const int s = clamp(static_cast(floor(sampleBuf[0] * 128.0)), -128, 127); + const std::vector indexCandicateSet = dpcm_lookahead_fast? dpcmFastLookupTable[s - prevLevel + 255]: dpcmIndexTable; + + for (auto i : indexCandicateSet) { + int newLevel = prevLevel + dpcmLookupTable[i]; + + int recMinimumError; + size_t recMinimumErrorIndex; + + // TODO apply dither noise + int errorEstimation = squared(s - newLevel); + if (errorEstimation >= minimumError) + continue; + + dpcm_lookahead(recMinimumError, recMinimumErrorIndex, + sampleBuf + 1, lookahead - 1, newLevel); + + // TODO weigh the error squared + int error = squared(s - newLevel) + recMinimumError; + if (error < minimumError) { + if (newLevel <= 127 && newLevel >= -128) { + minimumError = error; + minimumErrorIndex = i; + } + } + } +} + +static double calculate_snr(const std::vector& uncompressedData, const std::vector& decompressedData) +{ + int sum_son = 0; + int sum_mum = 0; + + assert(uncompressedData.size() == decompressedData.size()); + + for (size_t i = 0; i < uncompressedData.size(); i++) { + const int s = clamp(static_cast(floor(uncompressedData[i] * 128.0)), -128, 127) + 128; + sum_son += s * s; + const int sub = decompressedData[i] + 128 - s; + sum_mum += sub * sub; + } + + if (sum_mum == 0) { + return 100; + } + + return 10 * std::log10((double)sum_son / sum_mum); +} + +template +static void convert_dpcm_impl(wav_file& wf, InitialSampleWriter writeInitialSample, CompressedDataWriter writeCompressedData) +{ + int minimumError; + size_t minimumErrorIndex; + + std::vector uncompressedData; + std::vector decompressedData; + + const auto startTime = std::chrono::high_resolution_clock::now(); + + for (size_t i = 0; i < wf.loopEnd; i += DPCM_BLK_SIZE) { + double ds[DPCM_BLK_SIZE]; + size_t samples_in_block = std::min(DPCM_BLK_SIZE, wf.loopEnd - i); + wf.readData(i, ds, samples_in_block); + // Pad remaining samples in block with zeros if needed + for (size_t j = samples_in_block; j < DPCM_BLK_SIZE; j++) { + ds[j] = 0.0; + } + if (dpcm_verbose) { + uncompressedData.insert(uncompressedData.end(), std::begin(ds), std::end(ds)); + } + // TODO apply dither noise + int s = clamp(static_cast(floor(ds[0] * 128.0)), -128, 127); + + writeInitialSample(s); + if (dpcm_verbose) { + decompressedData.push_back(s); + } + + size_t innerLoopCount = 1; + size_t samples_to_process = dpcm_include_padding ? DPCM_BLK_SIZE : samples_in_block; + uint8_t outData = 0; + size_t sampleBufReadLen; + + goto initial_loop_enter; + + do { + if (innerLoopCount >= samples_to_process) + break; + sampleBufReadLen = std::min(dpcm_enc_lookahead, DPCM_BLK_SIZE - innerLoopCount); + dpcm_lookahead( + minimumError, minimumErrorIndex, + &ds[innerLoopCount], sampleBufReadLen, s); + outData = static_cast((minimumErrorIndex & 0xF) << 4); + s += dpcmLookupTable[minimumErrorIndex]; + if (dpcm_verbose) { + decompressedData.push_back(s); + } + innerLoopCount += 1; +initial_loop_enter: + if (innerLoopCount >= samples_to_process) + break; + sampleBufReadLen = std::min(dpcm_enc_lookahead, DPCM_BLK_SIZE - innerLoopCount); + dpcm_lookahead( + minimumError, minimumErrorIndex, + &ds[innerLoopCount], sampleBufReadLen, s); + outData |= static_cast(minimumErrorIndex & 0xF); + s += dpcmLookupTable[minimumErrorIndex]; + innerLoopCount += 1; + if (dpcm_verbose) { + decompressedData.push_back(s); + } + writeCompressedData(outData); + } while (innerLoopCount < DPCM_BLK_SIZE); + } + + const auto endTime = std::chrono::high_resolution_clock::now(); + + if (dpcm_verbose) { + const auto dur = std::chrono::duration_cast(endTime - startTime); + const double durSecs = static_cast(dur.count()) / 1000000000.0; + printf("SNR: %.2fdB, run time: %.2fs\n", calculate_snr(uncompressedData, decompressedData), durSecs); + } +} + +static void convert_dpcm(wav_file& wf, std::ofstream& ofs) +{ + uint32_t block_pos = 0; + convert_dpcm_impl(wf, + [&](int s) { data_write(ofs, block_pos, s, false); }, + [&](uint8_t outData) { data_write(ofs, block_pos, outData, true); }); +} + +static void convert_dpcm_bin(wav_file& wf, std::vector& data) +{ + convert_dpcm_impl(wf, + [&](int s) { bin_write_u8(data, static_cast(s)); }, + [&](uint8_t outData) { bin_write_u8(data, outData); }); +} + +void enable_dpcm_verbose() +{ + dpcm_verbose = true; +} + +void enable_dpcm_lookahead_fast() +{ + dpcm_lookahead_fast = true; +} + +void disable_dpcm_padding() +{ + dpcm_include_padding = false; +} + +void set_dpcm_lookahead(size_t lookahead) +{ + dpcm_enc_lookahead = clamp(lookahead, 1, 8); +} + +void set_wav_loop_start(uint32_t start) +{ + wav_loop_start = start; + wav_loop_start_override = true; +} + +void set_wav_loop_end(uint32_t end) +{ + wav_loop_end = end; + wav_loop_end_override = true; +} + +void set_wav_tune(double tune) +{ + wav_tune = tune; + wav_tune_override = true; +} + +void set_wav_key(uint8_t key) +{ + wav_key = key; + wav_key_override = true; +} + +void set_wav_rate(uint32_t rate) +{ + wav_rate = rate; + wav_rate_override = true; +} + +void convert(const std::string& wav_file_str, const std::string& out_file_str, + const std::string& sym, cmp_type ct, out_type ot) +{ + wav_file wf(wav_file_str); + + // check command line overrides + if (wav_loop_start_override) { + wf.loopStart = std::min(wav_loop_start, wf.loopEnd); + wf.loopEnabled = true; + } + if (wav_loop_end_override) { + wf.loopEnd = std::min(wav_loop_end, wf.loopEnd); + } + if (wav_tune_override) { + wf.tuning = wav_tune; + } + if (wav_key_override) { + wf.midiKey = wav_key; + } + if (wav_rate_override) { + wf.sampleRate = wav_rate; + } + + uint8_t fmt; + if (ct == cmp_type::none) + fmt = 0; + else if (ct == cmp_type::dpcm) + fmt = 1; + else + throw std::runtime_error("convert: invalid compression type"); + + double pitch; + if (wf.midiKey == 60 && wf.tuning == 0.0) { + pitch = wf.sampleRate; + } else { + pitch = wf.sampleRate * pow(2.0, (60.0 - wf.midiKey) / 12.0 + wf.tuning / 1200.0); + } + + uint32_t pitch_value; + if (wf.agbPitch != 0) { + pitch_value = wf.agbPitch; + } else { + pitch_value = static_cast(pitch * 1024.0); + } + + if (ot == out_type::binary) { + // Binary output mode + std::vector bin_data; + + // Write header (16 bytes) + // Bytes 0-3: flags (format in bit 0, loop in bit 30) + uint32_t flags = fmt; + if (wf.loopEnabled) + flags |= 0x40000000; + bin_write_u32_le(bin_data, flags); + + // Bytes 4-7: pitch + bin_write_u32_le(bin_data, pitch_value); + + // Bytes 8-11: loop start + bin_write_u32_le(bin_data, wf.loopStart); + + // Bytes 12-15: loop end + // wf.loopEnd is the exclusive end position; binary format expects (end - 1) + bin_write_u32_le(bin_data, wf.loopEnd > 0 ? wf.loopEnd - 1 : 0); + + // Write sample data + if (ct == cmp_type::none) + convert_uncompressed_bin(wf, bin_data); + else if (ct == cmp_type::dpcm) + convert_dpcm_bin(wf, bin_data); + else + throw std::runtime_error("convert: invalid compression type"); + + // Write binary file + std::ofstream fout(out_file_str, std::ios::out | std::ios::binary); + if (!fout.is_open()) { + perror("ofstream"); + throw std::runtime_error("unable to open output file"); + } + fout.write(reinterpret_cast(bin_data.data()), bin_data.size()); + fout.close(); + } else { + // Assembly output mode + std::ofstream fout(out_file_str, std::ios::out); + if (!fout.is_open()) { + perror("ofstream"); + throw std::runtime_error("unable to open output file"); + } + + agb_out(fout, " .section .rodata\n"); + agb_out(fout, " .global %s\n", sym.c_str()); + agb_out(fout, " .align 2\n\n%s:\n\n", sym.c_str()); + + agb_out(fout, " .byte 0x%X, 0x0, 0x0, 0x%X\n", fmt, wf.loopEnabled ? 0x40 : 0x0); + agb_out(fout, " .word 0x%08X @ Mid-C ~%f\n", pitch_value, pitch); + agb_out(fout, " .word %u, %u\n", wf.loopStart, wf.loopEnd); + + if (ct == cmp_type::none) + convert_uncompressed(wf, fout); + else if (ct == cmp_type::dpcm) + convert_dpcm(wf, fout); + else + throw std::runtime_error("convert: invalid compression type"); + + agb_out(fout, "\n\n .end\n"); + fout.close(); + } +} diff --git a/tools/wav2agb/converter.h b/tools/wav2agb/converter.h new file mode 100644 index 0000000000..df59ebe2d1 --- /dev/null +++ b/tools/wav2agb/converter.h @@ -0,0 +1,26 @@ +#pragma once + +#include +#include +#include + +enum class cmp_type { + none, dpcm +}; + +enum class out_type { + assembly, binary +}; + +void enable_dpcm_verbose(); +void enable_dpcm_lookahead_fast(); +void disable_dpcm_padding(); +void set_dpcm_lookahead(size_t lookahead); +void set_wav_loop_start(uint32_t start); +void set_wav_loop_end(uint32_t end); +void set_wav_tune(double tune); +void set_wav_key(uint8_t key); +void set_wav_rate(uint32_t rate); + +void convert(const std::string&, const std::string&, + const std::string& sym, cmp_type ct, out_type ot); diff --git a/tools/wav2agb/test_fast_compress.sh b/tools/wav2agb/test_fast_compress.sh new file mode 100644 index 0000000000..3ef56b4d91 --- /dev/null +++ b/tools/wav2agb/test_fast_compress.sh @@ -0,0 +1,9 @@ +#!/bin/sh + +for l in $(seq 1 8) +do + echo lookahead="$l": + wav2agb "$1" -c -l "$l" --verbose + echo lookahead="$l" fast: + wav2agb "$1" -f -l "$l" --verbose +done diff --git a/tools/wav2agb/wav2agb.cpp b/tools/wav2agb/wav2agb.cpp new file mode 100644 index 0000000000..be018abad6 --- /dev/null +++ b/tools/wav2agb/wav2agb.cpp @@ -0,0 +1,213 @@ +#include +#include +#include +#include +#include + +#include + +#include "converter.h" + +static void usage() { + fprintf(stderr, "wav2agb\n"); + fprintf(stderr, "\n"); + fprintf(stderr, "Usage: wav2agb [options] []\n"); + fprintf(stderr, "\n"); + fprintf(stderr, "Options:\n"); + fprintf(stderr, "-s, --symbol | symbol name for wave header (default: file name)\n"); + fprintf(stderr, "-l, --lookahead | DPCM compression lookahead 1..8 (default: 3)\n"); + fprintf(stderr, "-c, --compress | compress output with DPCM\n"); + fprintf(stderr, "-f, --fast-compress | compress output with DPCM fast\n"); + fprintf(stderr, "--no-pad | omit trailing padding in compressed output\n"); + fprintf(stderr, "-b, --binary | output raw binary instead of assembly\n"); + fprintf(stderr, "--loop-start | override loop start (integer)\n"); + fprintf(stderr, "--loop-end | override loop end (integer)\n"); + fprintf(stderr, "--tune | override tuning (float)\n"); + fprintf(stderr, "--key | override midi key (int)\n"); + fprintf(stderr, "--rate | override base samplerate (int)\n"); + exit(1); +} + +static void version() { + printf("wav2agb v1.1 (c) 2019 ipatix\n"); + exit(0); +} + +static void die(const char *msg, ...) { + va_list args; + va_start(args, msg); + vfprintf(stderr, msg, args); + va_end(args); + exit(1); +} + +static void fix_str(std::string& str) { + // replaces all characters that are not alphanumerical + for (size_t i = 0; i < str.size(); i++) { + if (str[i] >= 'a' && str[i] <= 'z') + continue; + if (str[i] >= 'A' && str[i] <= 'Z') + continue; + if (str[i] >= '0' && str[i] <= '9' && i > 0) + continue; + str[i] = '_'; + } +} + +static char path_seperators[] = { + '/', +#ifdef _WIN32 + '\\', +#endif + '\0' +}; + +static std::string filename_without_ext(const std::string& str) { + size_t last_path_seperator = 0; + char *sep = path_seperators; + while (*sep) { + size_t pos = str.find_last_of(*sep); + if (pos != std::string::npos) + last_path_seperator = std::max(pos, last_path_seperator); + sep += 1; + } + size_t file_ext_dot_pos = str.find_last_of('.'); + if (file_ext_dot_pos == std::string::npos) + return std::string(str); + assert(file_ext_dot_pos != last_path_seperator); + if (file_ext_dot_pos > last_path_seperator) + return str.substr(0, file_ext_dot_pos); + return std::string(str); +} + +static std::string filename_without_dir(const std::string& str) { + size_t last_path_seperator = 0; + bool path_seperator_found = false; + char *sep = path_seperators; + while (*sep) { + size_t pos = str.find_last_of(*sep); + if (pos != std::string::npos) { + last_path_seperator = std::max(pos, last_path_seperator); + path_seperator_found = true; + } + sep += 1; + } + if (str.size() > 0 && path_seperator_found) { + return str.substr(last_path_seperator + 1); + } else { + return std::string(str); + } +} + +static cmp_type arg_compress = cmp_type::none; +static out_type arg_output_type = out_type::assembly; +static std::string arg_sym; +static bool arg_input_file_read = false; +static bool arg_output_file_read = false; +static std::string arg_input_file; +static std::string arg_output_file; + +int main(int argc, char *argv[]) { + try { + if (argc == 1) + usage(); + + for (int i = 1; i < argc; i++) { + std::string st(argv[i]); + if (st == "-s" || st == "--symbol") { + if (++i >= argc) + die("-s: missing symbol name\n"); + arg_sym = argv[i]; + fix_str(arg_sym); + } else if (st == "-c" || st == "--compress") { + arg_compress = cmp_type::dpcm; + } else if (st == "-f" || st == "--compress-fast") { + arg_compress = cmp_type::dpcm; + enable_dpcm_lookahead_fast(); + } else if (st == "--no-pad") { + disable_dpcm_padding(); + } else if (st == "-b" || st == "--binary") { + arg_output_type = out_type::binary; + } else if (st == "--verbose") { + enable_dpcm_verbose(); + } else if (st == "-l" || st == "--lookahead") { + if (++i >= argc) + die("-l: missing parameter"); + set_dpcm_lookahead(std::stoul(argv[i], nullptr, 10)); + } else if (st == "--version") { + version(); + } else if (st == "--loop-start") { + if (++i >= argc) + die("--loop-start: missing parameter"); + uint32_t start = static_cast(std::stoul(argv[i], nullptr, 10)); + set_wav_loop_start(start); + } else if (st == "--loop-end") { + if (++i >= argc) + die("--loop-end: missing parameter"); + uint32_t end = static_cast(std::stoul(argv[i], nullptr, 10)); + set_wav_loop_end(end); + } else if (st == "--tune") { + if (++i >= argc) + die("--tune: missing parameter"); + double tune = std::stod(argv[i], nullptr); + set_wav_tune(tune); + } else if (st == "--key") { + if (++i >= argc) + die("--key: missing parameter"); + int key = std::stoi(argv[i], nullptr, 10); + if (key < 0) key = 0; + if (key > 127) key = 127; + set_wav_key(static_cast(key)); + } else if (st == "--rate") { + if (++i >= argc) + die("--rate: missing parameter"); + uint32_t rate = static_cast(std::stoul(argv[i], nullptr, 10)); + set_wav_rate(rate); + } else { + if (st == "--") { + if (++i >= argc) + die("--: missing file name\n"); + } + if (!arg_input_file_read) { + arg_input_file = argv[i]; + if (arg_input_file.size() < 1) + die("empty input file name\n"); + arg_input_file_read = true; + } else if (!arg_output_file_read) { + arg_output_file = argv[i]; + if (arg_output_file.size() < 1) + die("empty output file name\n"); + arg_output_file_read = true; + } else { + die("Too many files specified\n"); + } + } + } + + // check arguments + if (!arg_input_file_read) { + die("No input file specified\n"); + } + + if (!arg_output_file_read) { + // create output file name if none is provided + if (arg_output_type == out_type::binary) { + arg_output_file = filename_without_ext(arg_input_file) + ".bin"; + } else { + arg_output_file = filename_without_ext(arg_input_file) + ".s"; + } + arg_output_file_read = true; + } + + if (arg_sym.size() == 0) { + arg_sym = filename_without_dir(filename_without_ext(arg_output_file)); + fix_str(arg_sym); + } + + convert(arg_input_file, arg_output_file, arg_sym, arg_compress, arg_output_type); + return 0; + } catch (const std::exception& e) { + fprintf(stderr, "std lib error:\n%s\n", e.what()); + } + return 1; +} diff --git a/tools/wav2agb/wav_file.cpp b/tools/wav2agb/wav_file.cpp new file mode 100644 index 0000000000..4b242c5c00 --- /dev/null +++ b/tools/wav2agb/wav_file.cpp @@ -0,0 +1,287 @@ +#include "wav_file.h" + +#include +#include +#include +#include + +static uint32_t read_u32(std::ifstream& ifs) +{ + uint8_t lenBytes[4]; + ifs.read(reinterpret_cast(lenBytes), sizeof(lenBytes)); + uint32_t retval = lenBytes[0] | (lenBytes[1] << 8) | (lenBytes[2] << 16) | (lenBytes[3] << 24); + return retval; +} + +//static uint16_t read_u16(std::ifstream& ifs) +//{ +// uint8_t lenBytes[2]; +// ifs.read(reinterpret_cast(lenBytes), sizeof(lenBytes)); +// uint16_t retval = uint16_t(lenBytes[0] | (lenBytes[1] << 8)); +// return retval; +//} + +static std::string read_str(std::ifstream& ifs, size_t len) +{ + std::vector buf(len); + ifs.read(buf.data(), buf.size()); + return std::string(buf.data(), buf.size()); +} + +static std::vector read_arr(std::ifstream& ifs, size_t len) +{ + std::vector buf(len); + ifs.read(reinterpret_cast(buf.data()), buf.size()); + return buf; +} + +static uint16_t arr_u16(const std::vector& arr, size_t pos) +{ + uint16_t val = uint16_t(arr.at(pos) | (arr.at(pos + 1) << 8)); + return val; +} + +static uint32_t arr_u32(const std::vector& arr, size_t pos) +{ + uint32_t val = uint32_t(arr.at(pos) | (arr.at(pos + 1) << 8) | + (arr.at(pos + 2) << 16) | (arr.at(pos + 3) << 24)); + return val; +} + +static const size_t loadChunkSize = 2048; + +uint32_t wav_file::fmt_size() const +{ + if (fmt == format_type::u8) + return 1; + else if (fmt == format_type::s16) + return 2; + else if (fmt == format_type::s24) + return 3; + else if (fmt == format_type::s32) + return 4; + else if (fmt == format_type::f32) + return 4; + else if (fmt == format_type::f64) + return 8; + else + throw std::runtime_error("INTERNAL ERROR: invalid format type"); +} + +wav_file::wav_file(const std::string& path) : loadBuffer(loadChunkSize) +{ + ifs.exceptions(std::ios::badbit | std::ios::eofbit); + ifs.open(path, std::ios::binary); + if (!ifs.good()) + throw std::runtime_error("failed to open file: " + path + ", reason: " + strerror(errno)); + if (!ifs.is_open()) + throw std::runtime_error("failed to open file: " + path + ", reason: " + strerror(errno)); + + ifs.seekg(0, ifs.end); + std::streampos len = ifs.tellg(); + ifs.seekg(0, ifs.beg); + + std::string chunkId = read_str(ifs, 4); + if (chunkId != "RIFF") + throw std::runtime_error("RIFF ID invalid"); + uint32_t mainChunkLen = read_u32(ifs); + if (mainChunkLen + 8 != len) + throw std::runtime_error("RIFF chunk len (=" + + std::to_string(mainChunkLen) + + ") doesn't match file len (=" + + std::to_string(len) + + ")"); + std::string riffType = read_str(ifs, 4); + if (riffType != "WAVE") + throw std::runtime_error("WAVE ID invalid"); + + bool dataChunkFound = false; + bool fmtChunkFound = false; + // search all chunks + std::streampos curPos; + while ((curPos = ifs.tellg()) + std::streampos(8) <= len) { + chunkId = read_str(ifs, 4); + uint32_t chunkLen = read_u32(ifs); + if (curPos + std::streampos(8) + std::streampos(chunkLen) > len) + throw std::runtime_error("ERROR: chunk goes beyond end of file: offset=" + std::to_string(curPos)); + + if (chunkId == "fmt ") { + fmtChunkFound = true; + std::vector fmtChunk = read_arr(ifs, chunkLen); + uint16_t fmtTag = arr_u16(fmtChunk, 0); + uint16_t numChannels = arr_u16(fmtChunk, 2); + if (numChannels != 1) + throw std::runtime_error("ERROR: input file is NOT mono"); + this->sampleRate = arr_u32(fmtChunk, 4); + uint16_t block_align = arr_u16(fmtChunk, 12); + uint16_t bits_per_sample = arr_u16(fmtChunk, 14); + if (fmtTag == 1) { + // integer + if (block_align == 1 && bits_per_sample == 8) + this->fmt = format_type::u8; + else if (block_align == 2 && bits_per_sample == 16) + this->fmt = format_type::s16; + else if (block_align == 3 && bits_per_sample == 24) + this->fmt = format_type::s24; + else if (block_align == 4 && bits_per_sample == 32) + this->fmt = format_type::s32; + else + throw std::runtime_error("ERROR: unsupported integer format combination"); + } else if (fmtTag == 3) { + // float + if (block_align == 4 && bits_per_sample == 32) + this->fmt = format_type::f32; + else if (block_align == 8 && bits_per_sample == 64) + this->fmt = format_type::f64; + else + throw std::runtime_error("ERROR: unsupported float format combination"); + } else { + throw std::runtime_error("ERROR: unsupported format code: " + std::to_string(fmtTag)); + } + } else if (chunkId == "data") { + dataChunkFound = true; + dataChunkPos = ifs.tellg(); + dataChunkEndPos = dataChunkPos + std::streampos(chunkLen); + ifs.seekg(chunkLen, ifs.cur); + } else if (chunkId == "smpl") { + std::vector smplChunk = read_arr(ifs, chunkLen); + uint32_t midiUnityNote = arr_u32(smplChunk, 12); + this->midiKey = static_cast(std::min(midiUnityNote, 127u)); + uint32_t midiPitchFraction = arr_u32(smplChunk, 16); + // the values below convert the uint32_t range to 0.0 to 100.0 range + this->tuning = static_cast(midiPitchFraction) / (4294967296.0 * 100.0); + uint32_t numLoops = arr_u32(smplChunk, 28); + if (numLoops > 1) + throw std::runtime_error("ERROR: too many loops in smpl chunk"); + if (numLoops == 1) { + uint32_t loopType = arr_u32(smplChunk, 36 + 4); + if (loopType != 0) + throw std::runtime_error("ERROR: loop type not supported: " + std::to_string(loopType)); + this->loopStart = arr_u32(smplChunk, 36 + 8); + // sampler chunks tell the last sample to be played (so including rather than excluding), thus +1 + this->loopEnd = arr_u32(smplChunk, 36 + 12) + 1; + this->loopEnabled = true; + } + } else if (chunkId == "agbp") { + // Custom chunk: exact GBA pitch value (sample_rate * 1024) + // This allows perfect round-trip conversion without period-based precision loss + std::vector agbpChunk = read_arr(ifs, chunkLen); + if (chunkLen >= 4) { + this->agbPitch = arr_u32(agbpChunk, 0); + } + } else { + //fprintf(stderr, "WARNING: ignoring unknown chunk type: <%s>\n", chunkId.c_str()); + ifs.seekg(chunkLen, ifs.cur); + } + + /* https://en.wikipedia.org/wiki/Resource_Interchange_File_Format#Explanation + * If chunk size is odd, skip the pad byte */ + if ((chunkLen % 2) == 1) + ifs.seekg(1, ifs.cur); + } + + if (!fmtChunkFound) + throw std::runtime_error("ERROR: fmt chunk not found"); + if (!dataChunkFound) + throw std::runtime_error("ERROR: data chunk not found"); + + uint32_t numSamples = static_cast(dataChunkEndPos - dataChunkPos) / fmt_size(); + this->loopEnd = std::min(this->loopEnd, numSamples); +} + +wav_file::~wav_file() +{ + ifs.close(); +} + +void wav_file::readData(size_t location, double *data, size_t len) +{ + while (len-- > 0) { + if (loadedChunk != location - (location % loadChunkSize)) { + loadedChunk = location - (location % loadChunkSize); + + std::streampos blockpos = this->dataChunkPos + std::streampos(loadedChunk * fmt_size()); + std::streampos endblockpos = this->dataChunkEndPos; + size_t actualChunkSize = std::min(loadChunkSize, static_cast(endblockpos - blockpos) / fmt_size()); + + if (actualChunkSize == 0) { + std::fill(loadBuffer.begin(), loadBuffer.end(), 0.0); + goto load_sample; + } + + ifs.seekg(blockpos, ifs.beg); + std::vector ld(actualChunkSize * fmt_size()); + ifs.read(reinterpret_cast(ld.data()), ld.size()); + + if (fmt == format_type::u8) { + for (size_t i = 0; i < actualChunkSize; i++) { + loadBuffer[i] = (double(ld[i]) - 128.0) / 128.0; + } + } else if (fmt == format_type::s16) { + for (size_t i = 0; i < actualChunkSize; i++) { + int32_t s = + (ld[i * fmt_size() + 0] << 0) | + (ld[i * fmt_size() + 1] << 8); + s <<= 16; + s >>= 16; + loadBuffer[i] = double(s) / 32768.0; + } + } else if (fmt == format_type::s24) { + for (size_t i = 0; i < actualChunkSize; i++) { + int32_t s = + (ld[i * fmt_size() + 0] << 0) | + (ld[i * fmt_size() + 1] << 8) | + (ld[i * fmt_size() + 2] << 16); + s <<= 8; + s >>= 8; + loadBuffer[i] = double(s) / 8388608.0; + } + } else if (fmt == format_type::s32) { + for (size_t i = 0; i < actualChunkSize; i++) { + int32_t s = + (ld[i * fmt_size() + 0] << 0) | + (ld[i * fmt_size() + 1] << 8) | + (ld[i * fmt_size() + 2] << 16) | + (ld[i * fmt_size() + 3] << 24); + loadBuffer[i] = double(s) / 2147483648.0; + } + } else if (fmt == format_type::f32) { + for (size_t i = 0; i < actualChunkSize; i++) { + union { + uint32_t s; + float f; + } u; + u.s = + (ld[i * fmt_size() + 0] << 0) | + (ld[i * fmt_size() + 1] << 8) | + (ld[i * fmt_size() + 2] << 16) | + (ld[i * fmt_size() + 3] << 24); + loadBuffer[i] = u.f; + } + } else if (fmt == format_type::f64) { + for (size_t i = 0; i < actualChunkSize; i++) { + union { + uint64_t s; + double d; + } u; + u.s = + (uint64_t(ld[i * fmt_size() + 0]) << 0) | + (uint64_t(ld[i * fmt_size() + 1]) << 8) | + (uint64_t(ld[i * fmt_size() + 2]) << 16) | + (uint64_t(ld[i * fmt_size() + 3]) << 24) | + (uint64_t(ld[i * fmt_size() + 4]) << 32) | + (uint64_t(ld[i * fmt_size() + 5]) << 40) | + (uint64_t(ld[i * fmt_size() + 6]) << 48) | + (uint64_t(ld[i * fmt_size() + 7]) << 56); + loadBuffer[i] = u.d; + } + } + for (size_t i = actualChunkSize; i < loadChunkSize; i++) { + loadBuffer[i] = 0.0; + } + } +load_sample: + *data++ = loadBuffer[location % loadChunkSize]; + location++; + } +} diff --git a/tools/wav2agb/wav_file.h b/tools/wav2agb/wav_file.h new file mode 100644 index 0000000000..b88da4eeb6 --- /dev/null +++ b/tools/wav2agb/wav_file.h @@ -0,0 +1,38 @@ +#pragma once + +#include +#include +#include +#include +#include + +#define WAV_INVALID_VAL 0xFFFFFFFFu + +class wav_file { +public: + wav_file(const std::string& path); + ~wav_file(); + + void readData(size_t location, double *data, size_t len); +private: + std::ifstream ifs; + std::streampos dataChunkPos; + std::streampos dataChunkEndPos; + size_t loadedChunk = WAV_INVALID_VAL; + + std::vector loadBuffer; + size_t loadBufferBlock = std::numeric_limits::max(); + enum class format_type { + u8, s16, s24, s32, + f32, f64, + } fmt; + uint32_t fmt_size() const; +public: + uint32_t loopStart = 0; // samples + uint32_t loopEnd = std::numeric_limits::max(); // samples + bool loopEnabled = false; + double tuning = 0.0; // cents + uint8_t midiKey = 60; + uint32_t sampleRate; + uint32_t agbPitch = 0; // optional: exact GBA pitch value from 'agbp' chunk (0 = not present) +}; diff --git a/tools/wild_encounters/wild_encounters_to_header.py b/tools/wild_encounters/wild_encounters_to_header.py index 375dda3ecf..2fca4623e7 100644 --- a/tools/wild_encounters/wild_encounters_to_header.py +++ b/tools/wild_encounters/wild_encounters_to_header.py @@ -1,720 +1,277 @@ import json import re -import os - -IS_ENABLED = False -DEXNAV_ENABLED = False - -# C string vars -define = "#define" -ENCOUNTER_CHANCE = "ENCOUNTER_CHANCE" -SLOT = "SLOT" -TOTAL = "TOTAL" -NULL = "NULL" -UNDEFINED = "UNDEFINED" -MAP_UNDEFINED = "MAP_UNDEFINED" - -# encounter group header types, filled out programmatically -MON_HEADERS = [] - -# mon encounter group types -fieldData = [] -fieldInfoStrings = [] -fieldStrings = [] - -# time of day encounter data -TIME_DEFAULT = "" -TIME_DEFAULT_LABEL = "TIME_OF_DAY_DEFAULT" -TIME_DEFAULT_INDEX = 0 -TIMES_OF_DAY_COUNT = TIME_DEFAULT_INDEX + 1 - -# struct building blocks -baseStruct = "const struct WildPokemon" -structLabel = "" -structMonType = "" -structTime = "" -structMap = "" - -structInfo = "Info" -structHeader = "Header" -structArrayAssign = "[] =" - -baseStructLabel = "" -baseStructContent = [] -infoStructString = "" -infoStructRate = 0 -infoStructContent = [] -headerStructLabel = "" -headerStructContent = {} -headerStructTable = {} -headerIndex = 0 - -# map header data variables -hLabel = "" -hForMaps = True -headersArray = [headerIndex] - -# debug output control -mainSwitch = True -printWarningAndInclude = mainSwitch -printEncounterHeaders = mainSwitch -printEncounterRateMacros = mainSwitch -printEncounterStructsInfoString = mainSwitch -printEncounterStructs = mainSwitch - - -class TimeOfDay(): - def __init__(self): - self.vals = [] - self.lvals = [] - self.fvals = [] - self.count = 0 - - def __len__(self): - return self.count - - # for debugging purposes - def __str__(self): - return str([self.vals, self.lvals, self.fvals, self.count]) - - def add(self, val): - self.vals.append(val) - self.lvals.append(val.lower()) - self.fvals.append(GetTimeLabelFromString(val).capitalize()) - self.count += 1 - - def indexOf(self, val): - tempArr = [self.vals, self.lvals, self.fvals] - - for tvals in tempArr: - i = 0 - for time in tvals: - if val in time: - return i - - i += 1 - # return -1 here so it returns a consistent type and can be checked against < 0 - return -1 - - -def ImportWildEncounterFile(): - # make sure we're in the right directory before anything else - if not os.path.exists("Makefile"): - print("Please run this script from the project's root folder.") - quit() - - global MON_HEADERS - - global TIME_OF_DAY - TIME_OF_DAY = SetupUserTimeEnum(TimeOfDay()) - - global IS_ENABLED - global TIMES_OF_DAY_COUNT - if IsConfigEnabled(): - IS_ENABLED = True - TIMES_OF_DAY_COUNT = len(TIME_OF_DAY) - - global DEXNAV_ENABLED - DEXNAV_ENABLED = IsDexnavEnabled() - - global fieldInfoStrings - global fieldStrings - global structLabel - global structMonType - global structTime - global structMap - global baseStructLabel - global baseStructContent - global infoStructString - global infoStructRate - global headerStructLabel - global headerStructContent - global hLabel - global headersArray - global encounterTotalCount - global encounterCount - global headerIndex - global fieldData - global tabStr - tabStr = " " - - wFile = open("src/data/wild_encounters.json") - wData = json.load(wFile) - - encounterTotalCount = [] - encounterCount = [] - groupCount = 0 - while groupCount < len(wData["wild_encounter_groups"]): - encounterTotalCount.append(0) - encounterCount.append(0) - groupCount += 1 - - for data in wData["wild_encounter_groups"]: - wEncounters = wData["wild_encounter_groups"][headerIndex]["encounters"] - headerSuffix = structHeader + "s" - - if data["label"]: - hLabel = wData["wild_encounter_groups"][headerIndex]["label"] - if headerSuffix in hLabel: - hLabel = hLabel[:len(hLabel) - len(headerSuffix)] - MON_HEADERS.append(hLabel) - - if data["for_maps"]: - hForMaps = wData["wild_encounter_groups"][headerIndex]["for_maps"] - - if headerIndex == 0: - wFields = wData["wild_encounter_groups"][headerIndex]["fields"] - fieldCounter = 0 - for field in wFields: - if not CheckFieldDataDupes(field["type"]): - AddFieldData(fieldCounter, field["type"], field["encounter_rates"]) - - if "groups" in field: - fieldData[fieldCounter]["groups"] = field["groups"] - - """ - hidden mons need a special bit of logic since they're not in the vanilla - wild_encounters.json file, but the code expects them to be there - """ - hidden_mons = "hidden_mons" - if (fieldCounter == len(wFields) - 1) and not CheckFieldDataDupes(hidden_mons): - hidden_dummy_rates = [1, 0] - AddFieldData(fieldCounter + 1, hidden_mons, hidden_dummy_rates) - - fieldCounter += 1 - - if printWarningAndInclude: - PrintGeneratedWarningText() - print('#include "rtc.h"') - print("\n") - - PrintEncounterRateMacros() - - for encounter in wEncounters: - if "map" in encounter: - structMap = encounter["map"] - else: - structMap = encounter["base_label"] - - structLabel = encounter["base_label"] - - if encounterTotalCount[headerIndex] != len(wEncounters): - encounterTotalCount[headerIndex] = len(wEncounters) - - encounterCount[headerIndex] += 1 - headersArray = [] - - structTime = TIME_DEFAULT_INDEX - if IS_ENABLED: - timeCounter = 0 - while timeCounter < TIMES_OF_DAY_COUNT: - tempfTime = f"_{TIME_OF_DAY.fvals[timeCounter]}" - tempTime = TIME_OF_DAY.vals[timeCounter] - if tempfTime in structLabel or tempTime in structLabel: - structTime = timeCounter - - timeCounter += 1 - - fieldCounter = 0 - fieldInfoStrings = [] - while fieldCounter < len(fieldData): - fieldInfoStrings.append("") - fieldStrings.append("") - fieldCounter += 1 - - fieldCounter = 0 - while fieldCounter < len(fieldData): - for areaTable in encounter: - if fieldData[fieldCounter]["name"] in areaTable: - structMonType = fieldData[fieldCounter]["pascalName"] - if f"_{TIME_OF_DAY.fvals[structTime]}" in structLabel: - fieldInfoStrings[fieldCounter] = f"{structLabel}_{structMonType}{structInfo}" - fieldStrings[fieldCounter] = f"{structLabel}_{structMonType}" - else: - fieldInfoStrings[fieldCounter] = f"{structLabel}_{TIME_OF_DAY.fvals[structTime]}_{structMonType}{structInfo}" - fieldStrings[fieldCounter] = f"{structLabel}_{TIME_OF_DAY.fvals[structTime]}_{structMonType}" - else: - structMonType = "" - continue - - baseStructContent = [] - for group in encounter[areaTable]: - if "mons" in group: - for mon in encounter[areaTable][group]: - baseStructContent.append(list(mon.values())) - - if "encounter_rate" in group: - infoStructRate = encounter[areaTable][group] - - baseStructLabel = f"{baseStruct} {fieldStrings[fieldCounter]}{structArrayAssign}" - if printEncounterStructs: - print() - print(baseStructLabel) - print("{") - PrintStructContent(baseStructContent) - print("};") - - if printEncounterStructsInfoString: - infoStructString = f"{baseStruct}{structInfo} {fieldInfoStrings[fieldCounter]} = {{ {infoStructRate}, {fieldStrings[fieldCounter]} }};" - print(infoStructString) - - fieldCounter += 1 - AssembleMonHeaderContent() - headerIndex += 1 - PrintWildMonHeadersContent() - - -def PrintStructContent(contentList): - for monList in contentList: - print(f"{tabStr}{{ {monList[0]}, {monList[1]}, {monList[2]} }},") - return - - -def GetStructLabelWithoutTime(label): - labelLength = len(label) - timeLength = 0 - - if not IS_ENABLED: - return label - - timeCounter = 0 - while timeCounter < TIMES_OF_DAY_COUNT: - tempTime = TIME_OF_DAY.fvals[timeCounter] - if tempTime in label: - timeLength = len(tempTime) - return label[:(labelLength - (timeLength + 1))] - - timeCounter += 1 - return label - - -def GetStructTimeWithoutLabel(label): - if not IS_ENABLED: - return TIME_DEFAULT_INDEX - - timeCounter = 0 - while timeCounter < TIMES_OF_DAY_COUNT: - tempTime = f"_{TIME_OF_DAY.fvals[timeCounter]}" - if tempTime in label: - return timeCounter - - timeCounter += 1 - return TIME_DEFAULT_INDEX - - -def AssembleMonHeaderContent(): - SetupMonInfoVars() - - tempHeaderLabel = GetWildMonHeadersLabel() - tempHeaderTimeIndex = GetStructTimeWithoutLabel(structLabel) - structLabelNoTime = GetStructLabelWithoutTime(structLabel) - - if tempHeaderLabel not in headerStructTable: - headerStructTable[tempHeaderLabel] = {} - headerStructTable[tempHeaderLabel]["groupNum"] = headerIndex - - if structLabelNoTime not in headerStructTable[tempHeaderLabel]: - headerStructTable[tempHeaderLabel][structLabelNoTime] = {} - headerStructTable[tempHeaderLabel][structLabelNoTime]["headerType"] = GetWildMonHeadersLabel() - headerStructTable[tempHeaderLabel][structLabelNoTime]["mapGroup"] = structMap - headerStructTable[tempHeaderLabel][structLabelNoTime]["mapNum"] = structMap - headerStructTable[tempHeaderLabel][structLabelNoTime]["encounterTotalCount"] = encounterTotalCount[headerIndex] - headerStructTable[tempHeaderLabel][structLabelNoTime]["encounter_types"] = [] - - timeCounter = 0 - while timeCounter < TIMES_OF_DAY_COUNT: - headerStructTable[tempHeaderLabel][structLabelNoTime]["encounter_types"].append([]) - timeCounter += 1 - - fieldCounter = 0 - while fieldCounter < len(fieldData): - headerStructTable[tempHeaderLabel][structLabelNoTime]["encounter_types"][tempHeaderTimeIndex].append(fieldInfoStrings[fieldCounter]) - fieldCounter += 1 - - -def SetupMonInfoVars(): - i = 0 - while i < len(fieldData): - fieldData[i]["infoStringBase"] = "." + fieldData[i]["snakeName"] + structInfo - if CheckEmpty(fieldInfoStrings[i]): - fieldInfoStrings[i] = NULL - else: - fieldInfoStrings[i] = "&" + fieldInfoStrings[i] - - i += 1 - - -def PrintWildMonHeadersContent(): - groupCount = 0 - for group in headerStructTable: - labelCount = 0 - for label in headerStructTable[group]: - if label != "groupNum": - if labelCount == 0: - PrintEncounterHeaders("\n") - PrintEncounterHeaders(headerStructTable[group][label]["headerType"]) - - PrintEncounterHeaders(tabStr + "{") - - for stat in headerStructTable[group][label]: - mapData = headerStructTable[group][label][stat] - - if stat == "mapGroup": - PrintEncounterHeaders(f"{TabStr(2)}.mapGroup = {GetMapGroupEnum(mapData)},") - elif stat == "mapNum": - PrintEncounterHeaders(f"{TabStr(2)}.mapNum = {GetMapGroupEnum(mapData, labelCount + 1)},") - - if type(headerStructTable[group][label][stat]) == list: - PrintEncounterHeaders(f"{TabStr(2)}.encounterTypes =") - PrintEncounterHeaders(TabStr(2) + "{") - - timeCounter = 0 - while timeCounter < TIMES_OF_DAY_COUNT: - monInfo = headerStructTable[group][label][stat][timeCounter] - PrintEncounterHeaders(f"{TabStr(3)}[{TIME_OF_DAY.vals[timeCounter]}] = ") - - infoIndex = 0 - while infoIndex < len(fieldData): - if infoIndex == 0: - PrintEncounterHeaders(TabStr(3) + "{") - - if len(monInfo) == 0: - PrintEncounterHeaders(f"{TabStr(4)}{GetIMonInfoStringFromIndex(infoIndex)} = NULL,") - else: - PrintEncounterHeaders(f"{TabStr(4)}{GetIMonInfoStringFromIndex(infoIndex)} = {monInfo[infoIndex]},") - - if infoIndex == len(fieldData) - 1: - PrintEncounterHeaders(TabStr(3) + "},") - - infoIndex += 1 - timeCounter += 1 - PrintEncounterHeaders(TabStr(2) + "},") - PrintEncounterHeaders(tabStr + "},") - labelCount += 1 - PrintEncounterHeaders(tabStr + "{") - PrintEncounterHeaders(f"{TabStr(2)}.mapGroup = {GetMapGroupEnum(MAP_UNDEFINED)},") - PrintEncounterHeaders(f"{TabStr(2)}.mapNum = {GetMapGroupEnum(MAP_UNDEFINED, labelCount + 1)},") - - nullCount = 0 - while nullCount < TIMES_OF_DAY_COUNT: - if nullCount == 0: - PrintEncounterHeaders(f"{TabStr(2)}.encounterTypes =") - PrintEncounterHeaders(TabStr(2)+ "{") - - PrintEncounterHeaders(f"{TabStr(3)}[{TIME_OF_DAY.vals[nullCount]}] = ") - - nullIndex = 0 - while nullIndex <= len(fieldData) - 1: - if nullIndex == 0: - PrintEncounterHeaders(TabStr(3) + "{") - - PrintEncounterHeaders(f"{TabStr(4)}{GetIMonInfoStringFromIndex(nullIndex)} = NULL,") - - if nullIndex == len(fieldData) - 1: - PrintEncounterHeaders(TabStr(3) + "},") - - nullIndex += 1 - nullCount += 1 - PrintEncounterHeaders(TabStr(2) + "},") - PrintEncounterHeaders(tabStr + "},") - groupCount += 1 - PrintEncounterHeaders("};") - - -def GetWildMonHeadersLabel(): - return f"{baseStruct}{structHeader} {MON_HEADERS[headerIndex]}{structHeader}s{structArrayAssign}" + "\n{" - - -def PrintEncounterHeaders(content): - if printEncounterHeaders: - print(content) - - -def PrintEncounterRateMacros(): - if not printEncounterRateMacros: - return - - fieldCounter = 0 - while fieldCounter < len(fieldData): - tempName = fieldData[fieldCounter]["name"].upper() - if "groups" not in fieldData[fieldCounter]: - rateCount = 0 - if fieldData[fieldCounter]["encounter_rates"]: - for percent in fieldData[fieldCounter]["encounter_rates"]: - if not DEXNAV_ENABLED and tempName == "HIDDEN_MONS": - break - - if rateCount == 0: - print(f"{define} {ENCOUNTER_CHANCE}_{tempName}_{SLOT}_{rateCount} {percent}") - else: - print( - f"{define} {ENCOUNTER_CHANCE}_{tempName}_{SLOT}_{rateCount} {ENCOUNTER_CHANCE}_{tempName}_{SLOT}_{rateCount - 1} + {percent}" - ) - - if rateCount + 1 == len(fieldData[fieldCounter]["encounter_rates"]): - print( - f"{define} {ENCOUNTER_CHANCE}_{tempName}_{TOTAL} ({ENCOUNTER_CHANCE}_{tempName}_{SLOT}_{rateCount})" - ) - - rateCount += 1 - else: - rates = fieldData[fieldCounter]["encounter_rates"] - groups = fieldData[fieldCounter]["groups"] - - for method in groups: - method_indices = groups[method] - if not method_indices: +class Config: + def __init__(self, config_file_name, rtc_constants_file_name, encounters_json_data): + self.times_of_day = None + self.mon_types = None + self.time_encounters = None + self.disable_time_fallback = None + self.time_fallback = None + + self.ParseTimeEnum(rtc_constants_file_name) + if self.times_of_day == None: + raise Exception(f"Failed to parse 'enum TimeOfDay' in '{rtc_constants_file_name}'") + + self.ParseMonTypes(encounters_json_data) + if self.mon_types == None: + raise Exception("No fields defined in 'wild_encounters.json'") + + with open(config_file_name, 'r') as config_file: + lines = config_file.readlines() + for line in lines: + self.ParseTimeConfig(line) + + if self.time_encounters == None: + raise Exception("OW_TIME_OF_DAY_ENCOUNTERS not defined.") + if self.disable_time_fallback == None: + raise Exception("OW_TIME_OF_DAY_DISABLE_FALLBACK not defined.") + if self.time_fallback == None: + raise Exception("OW_TIME_OF_DAY_FALLBACK not defined.") + + def ParseTimeEnum(self, rtc_constants_file_name): + with open(rtc_constants_file_name, 'r') as rtc_constants_file: + DEFAULT_TIME_PAT = re.compile(r"enum\s+TimeOfDay\s*\{(?P[\s*\w+,\=\d*]+)\s*\}\s*\;") + file = rtc_constants_file.read() + + m = DEFAULT_TIME_PAT.search(file) + if m: + txt = m.group('rtc_val') + values = re.findall(r'TIME_\w+', txt) + self.times_of_day = {} + for value in values: + self.times_of_day[value] = value.title().replace("Time_", "").replace("_", "") + + def ParseMonTypes(self, encounters_json_data): + for group in encounters_json_data["wild_encounter_groups"]: + if "fields" in group: + for field in group["fields"]: + field_type = field["type"] + if not self.mon_types: + self.mon_types = [] + self.mon_types.append(field_type) + + def ParseTimeConfig(self, line): + m = re.search(r'#define OW_TIME_OF_DAY_ENCOUNTERS\s+(\w+)', line) + if m: + self.time_encounters = m.group(1) == "TRUE" + + m = re.search(r'#define OW_TIME_OF_DAY_DISABLE_FALLBACK\s+(\w+)', line) + if m: + self.disable_time_fallback = m.group(1) == "TRUE" + + m = re.search(r'#define OW_TIME_OF_DAY_FALLBACK\s+(\w+)', line) + if m: + self.time_fallback = m.group(1) + + +class WildEncounterAssembler: + def __init__(self, output_file, json_data, config): + self.output_file = output_file + self.json_data = json_data + self.config = config + + def WriteLine(self, line="", indents = 0): + self.output_file.write(4 * indents * " " + line + "\n") + + def WriteHeader(self): + self.WriteLine("//") + self.WriteLine("// DO NOT MODIFY THIS FILE! It is auto-generated by tools/wild_encounters/wild_encounters_to_header.py") + self.WriteLine("//") + self.output_file.write("\n\n") + + def WriteMacro(self, macro, value): + self.output_file.write("#define " + macro + " " + value + "\n") + + def WriteMacros(self): + wild_encounter_groups = self.json_data["wild_encounter_groups"] + for wild_encounter_group in wild_encounter_groups: + if "fields" in wild_encounter_group: + fields = wild_encounter_group["fields"] + for field in fields: + field_type = field["type"] + macro_base = "ENCOUNTER_CHANCE_" + field_type.upper() + previous_group = None + previous_macro = None + encounter_rates = field["encounter_rates"] + + group_name_mapping = len(encounter_rates) * [""] + if "groups" in field: + groups = field["groups"] + for group_name, indices in groups.items(): + for index in indices: + group_name_mapping[index] = "_" + group_name.upper() + + for idx, rate in enumerate(encounter_rates): + macro_name = macro_base + group_name_mapping[idx] + "_SLOT_" + str(idx) + macro_value = str(rate) + if previous_group == group_name_mapping[idx]: + macro_value = "(" + previous_macro + " + " + macro_value + ")" + elif idx > 0: + macro_total_name = macro_base + group_name_mapping[idx - 1] + "_TOTAL" + self.WriteMacro(macro_total_name, "(" + previous_macro + ")") + self.WriteMacro(macro_name, macro_value) + previous_group = group_name_mapping[idx] + previous_macro = macro_name + if idx == len(encounter_rates) - 1: + macro_total_name = macro_base + group_name_mapping[idx] + "_TOTAL" + self.WriteMacro(macro_total_name, "(" + previous_macro + ")") + macro_total_name = macro_base + group_name_mapping[-1] + "_TOTAL" + self.WriteLine() + + def WriteMonInfos(self, name, mons, encounter_rate): + info_name = name + "Info" + self.WriteLine(f"const struct WildPokemon {name}[] =") + self.WriteLine("{") + for mon in mons: + species = mon["species"] + min_level = 2 if "min_level" not in mon else mon["min_level"] + max_level = 100 if "max_level" not in mon else mon["max_level"] + self.WriteLine(f"{{ {min_level}, {max_level}, {species} }},", 1) + + self.WriteLine("};") + self.WriteLine() + self.WriteLine(f"const struct WildPokemonInfo {info_name} = {{ {encounter_rate}, {name} }};") + self.WriteLine() + + def WriteTerminator(self): + self.WriteLine("{", 1) + self.WriteLine(".mapGroup = MAP_GROUP(MAP_UNDEFINED),", 2) + self.WriteLine(".mapNum = MAP_NUM(MAP_UNDEFINED),", 2) + self.WriteLine(".encounterTypes =", 2) + self.WriteLine("{", 2) + for time in self.config.times_of_day: + if not self.config.time_encounters and time != self.config.time_fallback: + continue + self.WriteLine(f"[{time}] =", 3) + self.WriteLine("{", 3) + for mon_type in self.config.mon_types: + member_name = mon_type.title().replace("_", "") + member_name = member_name[0].lower() + member_name[1:] + "Info" + self.WriteLine(f".{member_name} = NULL,", 4) + self.WriteLine("},", 3) + self.WriteLine("},", 2) + self.WriteLine("},", 1) + + def WritePokemonHeaders(self, headers): + label = headers["label"] + self.WriteLine(f"const struct WildPokemonHeader {label}[] =") + self.WriteLine("{") + for shared_label in headers["data"]: + self.WriteLine() + map_data = headers["data"][shared_label] + encounter_data = map_data + map_group = map_data["mapGroup"] + map_num = map_data["mapNum"] + version = "EMERALD" + if "FireRed" in shared_label: + version = "FIRERED" + elif "LeafGreen" in shared_label: + version = "LEAFGREEN" + + self.WriteLine(f"#ifdef {version}") + + self.WriteLine("{", 1) + self.WriteLine(f".mapGroup = {map_group},", 2) + self.WriteLine(f".mapNum = {map_num},", 2) + self.WriteLine(".encounterTypes =", 2) + self.WriteLine("{", 2) + for time in self.config.times_of_day: + if not self.config.time_encounters and time != self.config.time_fallback: continue + self.WriteLine(f"[{time}] =", 3) + self.WriteLine("{", 3) + for mon_type in self.config.mon_types: + member_name = mon_type.title().replace("_", "") + member_name = member_name[0].lower() + member_name[1:] + "Info" + value = "NULL" + if time in encounter_data and mon_type in encounter_data[time]: + value = encounter_data[time][mon_type] + if value != "NULL": + value = "&" + value + self.WriteLine(f".{member_name} = {value},", 4) - for i, methodPercentIndex in enumerate(method_indices): - if methodPercentIndex < 0 or methodPercentIndex >= len(rates): - print(f"#error Invalid fishing encounter rate index {methodPercentIndex} for {method.upper()}") + self.WriteLine("},", 3) + + self.WriteLine("},", 2) + self.WriteLine("},", 1) + self.WriteLine(f"#endif") + self.WriteTerminator() + self.WriteLine("};") + + + def WriteEncounters(self): + wild_encounter_groups = self.json_data["wild_encounter_groups"] + for wild_encounter_group in wild_encounter_groups: + headers = {} + headers["label"] = wild_encounter_group["label"] + headers["data"] = {} + for_maps = False + map_num_counter = 1 + if "for_maps" in wild_encounter_group: + for_maps = wild_encounter_group["for_maps"] + encounters = wild_encounter_group["encounters"] + + for map_encounters in encounters: + map_group = "0" + map_num = str(map_num_counter) + if for_maps: + map_name = map_encounters["map"] + map_group = f"MAP_GROUP({map_name})" + map_num = f"MAP_NUM({map_name})" + map_num_counter += 1 + base_label = map_encounters["base_label"] + shared_label = base_label + time = self.config.time_fallback + + for time_ident in self.config.times_of_day: + if self.config.times_of_day[time_ident] in base_label: + time = time_ident + shared_label = shared_label.replace('_' + self.config.times_of_day[time_ident], '') + + if shared_label not in headers["data"]: + headers["data"][shared_label] = {} + if time not in headers["data"][shared_label]: + headers["data"][shared_label][time] = {} + headers["data"][shared_label]["mapGroup"] = map_group + headers["data"][shared_label]["mapNum"] = map_num + + version = "EMERALD" + if "FireRed" in shared_label: + version = "FIRERED" + elif "LeafGreen" in shared_label: + version = "LEAFGREEN" + self.WriteLine(f"#ifdef {version}") + for mon_type in self.config.mon_types: + if mon_type not in map_encounters: + headers["data"][shared_label][mon_type] = "NULL" continue - rate_value = rates[methodPercentIndex] - if i == 0: - print(f"{define} {ENCOUNTER_CHANCE}_{tempName}_{method.upper()}_{SLOT}_{methodPercentIndex} {rate_value}") - else: - previous_method_index = method_indices[i - 1] - print(f"{define} {ENCOUNTER_CHANCE}_{tempName}_{method.upper()}_{SLOT}_{methodPercentIndex} {ENCOUNTER_CHANCE}_{tempName}_{method.upper()}_{SLOT}_{previous_method_index} + {rate_value}") + mons_entry = map_encounters[mon_type] + encounter_rate = mons_entry["encounter_rate"] + mons = mons_entry["mons"] - if i == len(method_indices) - 1: - print(f"{define} {ENCOUNTER_CHANCE}_{tempName}_{method.upper()}_{TOTAL} ({ENCOUNTER_CHANCE}_{tempName}_{method.upper()}_{SLOT}_{methodPercentIndex})") + mon_array_name = base_label + "_" + mon_type.title().replace("_", "") + self.WriteMonInfos(mon_array_name, mons, encounter_rate) + headers["data"][shared_label][time][mon_type] = mon_array_name + "Info" + self.WriteLine(f"#endif") - fieldCounter += 1 - print() + self.WritePokemonHeaders(headers) -def GetTimeLabelFromString(string): - time = "TIME" - time_ = "TIME_" - - if string == "TIMES_OF_DAY_COUNT": - return string - - if time_ in string.upper(): - return string[len(time_):len(string)] - elif time in string.upper(): - return string[len(time):len(string)] - return string - - -def GetIMonInfoStringFromIndex(index): - return fieldData[index]["infoStringBase"] - - -def GetMapGroupEnum(string, index = 0): - if "MAP_" in string and index == 0: - return "MAP_GROUP(" + string + ")" - elif "MAP_" in string and index != 0: - return "MAP_NUM(" + string + ")" - return index - - -""" -get copied lhea :^ ) -- next four functions copied almost verbatim from @lhearachel's python scripts in tools/learnset_helpers -""" -def PrintGeneratedWarningText(): - print("//") - print("// DO NOT MODIFY THIS FILE! It is auto-generated by tools/wild_encounters/wild_encounters_to_header.py") - print("//") - print("\n") - - -def IsConfigEnabled(): - CONFIG_ENABLED_PAT = re.compile(r"#define OW_TIME_OF_DAY_ENCOUNTERS\s+(?P[^ ]*)") - - with open("./include/config/overworld.h", "r") as overworld_config_file: - config_overworld = overworld_config_file.read() - config_setting = CONFIG_ENABLED_PAT.search(config_overworld) - return config_setting is not None and config_setting.group("cfg_val") in ("TRUE", "1") - - -def IsDexnavEnabled(): - CONFIG_ENABLED_PAT = re.compile(r"#define DEXNAV_ENABLED\s+(?P[^ ]*)") - - with open("./include/config/dexnav.h", "r") as overworld_config_file: - config_overworld = overworld_config_file.read() - config_setting = CONFIG_ENABLED_PAT.search(config_overworld) - return config_setting is not None and config_setting.group("cfg_val") in ("TRUE", "1") - - -def GetTimeEnum(): - DEFAULT_TIME_PAT = re.compile(r"enum\s+TimeOfDay\s*\{(?P[\s*\w+,\=\d*]+)\s*\}\s*\;") - - with open("./include/constants/rtc.h", "r") as rtc_include_file: - include_rtc = rtc_include_file.read() - include_enum = DEFAULT_TIME_PAT.search(include_rtc) - return include_enum.group("rtc_val") - - -def CheckEmpty(string): - return string == "" or string.isspace() or string == "\n" - - -def SetupUserTimeEnum(timeOfDay): - enum_string = GetTimeEnum() - enum_string = enum_string.split(",") - - # check for extra element from trailing comma - if CheckEmpty(enum_string[-1]): - enum_string.pop(-1) - - # we don't need the `TIMES_OF_DAY_COUNT` value, so - 1 from the value of len(enum_string) - strCount = 0 - while strCount < len(enum_string) - 1: - tempStr = enum_string[strCount].strip("\n ") - - """ - we need to ignore any value assignments, as the times will need to correspond - with the elements in the array. - """ - if "=" in tempStr: - tempStr = tempStr[0:tempStr.index("=")] - tempStr = tempStr.strip(" ") - - #double check we didn't catch any empty values - if not CheckEmpty(enum_string[strCount]): - timeOfDay.add(tempStr) - - strCount += 1 - return timeOfDay - - -def TabStr(amount): - return tabStr * amount - - -def GetPascalCase(string): - stringArray = string.split("_") - pascalString = "" - - for string in stringArray: - pascalString += string.capitalize() - return pascalString - - -def GetSnakeCase(string): - stringArray = string.split("_") - snakeString = "" - - i = 0 - for string in stringArray: - if i == 0: - snakeString += string - else: - snakeString += string.capitalize() - - i += 1 - return snakeString - - -def CheckFieldDataDupes(name): - for field in fieldData: - if field["name"] == name: - return True - return False - - -def AddFieldData(index, fieldType, fieldRates): - fieldData.append({}) - fieldData[index]["name"] = fieldType - fieldData[index]["pascalName"] = GetPascalCase(fieldType) - fieldData[index]["snakeName"] = GetSnakeCase(fieldType) - fieldData[index]["encounter_rates"] = fieldRates - +def ConvertToHeaderFile(json_data): + with open('src/data/wild_encounters.h', 'w') as output_file: + config = Config('include/config/overworld.h', 'include/constants/rtc.h', json_data) + assembler = WildEncounterAssembler(output_file, json_data, config) + assembler.WriteHeader() + assembler.WriteMacros() + assembler.WriteEncounters() def main(): - pass + with open('src/data/wild_encounters.json', 'r') as json_file: + json_data = json.load(json_file) + ConvertToHeaderFile(json_data) -if __name__ == "__main__": - ImportWildEncounterFile() - - -""" -!!!! EXAMPLE OUTPUT !!!! -- when OW_TIME_OF DAY_ENCOUNTERS is FALSE in configoverworld.h - -#define ENCOUNTER_CHANCE_LAND_MONS_SLOT_0 20 -#define ENCOUNTER_CHANCE_LAND_MONS_SLOT_1 ENCOUNTER_CHANCE_LAND_MONS_SLOT_0 + 20 -#define ENCOUNTER_CHANCE_LAND_MONS_SLOT_2 ENCOUNTER_CHANCE_LAND_MONS_SLOT_1 + 10 -#define ENCOUNTER_CHANCE_LAND_MONS_SLOT_3 ENCOUNTER_CHANCE_LAND_MONS_SLOT_2 + 10 -#define ENCOUNTER_CHANCE_LAND_MONS_SLOT_4 ENCOUNTER_CHANCE_LAND_MONS_SLOT_3 + 10 -#define ENCOUNTER_CHANCE_LAND_MONS_SLOT_5 ENCOUNTER_CHANCE_LAND_MONS_SLOT_4 + 10 -#define ENCOUNTER_CHANCE_LAND_MONS_SLOT_6 ENCOUNTER_CHANCE_LAND_MONS_SLOT_5 + 5 -#define ENCOUNTER_CHANCE_LAND_MONS_SLOT_7 ENCOUNTER_CHANCE_LAND_MONS_SLOT_6 + 5 -#define ENCOUNTER_CHANCE_LAND_MONS_SLOT_8 ENCOUNTER_CHANCE_LAND_MONS_SLOT_7 + 4 -#define ENCOUNTER_CHANCE_LAND_MONS_SLOT_9 ENCOUNTER_CHANCE_LAND_MONS_SLOT_8 + 4 -#define ENCOUNTER_CHANCE_LAND_MONS_SLOT_10 ENCOUNTER_CHANCE_LAND_MONS_SLOT_9 + 1 -#define ENCOUNTER_CHANCE_LAND_MONS_SLOT_11 ENCOUNTER_CHANCE_LAND_MONS_SLOT_10 + 1 -#define ENCOUNTER_CHANCE_LAND_MONS_TOTAL (ENCOUNTER_CHANCE_LAND_MONS_SLOT_11) -#define ENCOUNTER_CHANCE_WATER_MONS_SLOT_0 60 -#define ENCOUNTER_CHANCE_WATER_MONS_SLOT_1 ENCOUNTER_CHANCE_WATER_MONS_SLOT_0 + 30 -#define ENCOUNTER_CHANCE_WATER_MONS_SLOT_2 ENCOUNTER_CHANCE_WATER_MONS_SLOT_1 + 5 -#define ENCOUNTER_CHANCE_WATER_MONS_SLOT_3 ENCOUNTER_CHANCE_WATER_MONS_SLOT_2 + 4 -#define ENCOUNTER_CHANCE_WATER_MONS_SLOT_4 ENCOUNTER_CHANCE_WATER_MONS_SLOT_3 + 1 -#define ENCOUNTER_CHANCE_WATER_MONS_TOTAL (ENCOUNTER_CHANCE_WATER_MONS_SLOT_4) -#define ENCOUNTER_CHANCE_ROCK_SMASH_MONS_SLOT_0 60 -#define ENCOUNTER_CHANCE_ROCK_SMASH_MONS_SLOT_1 ENCOUNTER_CHANCE_ROCK_SMASH_MONS_SLOT_0 + 30 -#define ENCOUNTER_CHANCE_ROCK_SMASH_MONS_SLOT_2 ENCOUNTER_CHANCE_ROCK_SMASH_MONS_SLOT_1 + 5 -#define ENCOUNTER_CHANCE_ROCK_SMASH_MONS_SLOT_3 ENCOUNTER_CHANCE_ROCK_SMASH_MONS_SLOT_2 + 4 -#define ENCOUNTER_CHANCE_ROCK_SMASH_MONS_SLOT_4 ENCOUNTER_CHANCE_ROCK_SMASH_MONS_SLOT_3 + 1 -#define ENCOUNTER_CHANCE_ROCK_SMASH_MONS_TOTAL (ENCOUNTER_CHANCE_ROCK_SMASH_MONS_SLOT_4) -#define ENCOUNTER_CHANCE_FISHING_MONS_GOOD_ROD_SLOT_2 60 -#define ENCOUNTER_CHANCE_FISHING_MONS_GOOD_ROD_SLOT_3 ENCOUNTER_CHANCE_FISHING_MONS_GOOD_ROD_SLOT_2 + 20 -#define ENCOUNTER_CHANCE_FISHING_MONS_GOOD_ROD_SLOT_4 ENCOUNTER_CHANCE_FISHING_MONS_GOOD_ROD_SLOT_3 + 20 -#define ENCOUNTER_CHANCE_FISHING_MONS_GOOD_ROD_TOTAL (ENCOUNTER_CHANCE_FISHING_MONS_GOOD_ROD_SLOT_4) -#define ENCOUNTER_CHANCE_FISHING_MONS_OLD_ROD_SLOT_0 70 -#define ENCOUNTER_CHANCE_FISHING_MONS_OLD_ROD_SLOT_1 ENCOUNTER_CHANCE_FISHING_MONS_OLD_ROD_SLOT_0 + 30 -#define ENCOUNTER_CHANCE_FISHING_MONS_OLD_ROD_TOTAL (ENCOUNTER_CHANCE_FISHING_MONS_OLD_ROD_SLOT_1) -#define ENCOUNTER_CHANCE_FISHING_MONS_SUPER_ROD_SLOT_5 40 -#define ENCOUNTER_CHANCE_FISHING_MONS_SUPER_ROD_SLOT_6 ENCOUNTER_CHANCE_FISHING_MONS_SUPER_ROD_SLOT_5 + 40 -#define ENCOUNTER_CHANCE_FISHING_MONS_SUPER_ROD_SLOT_7 ENCOUNTER_CHANCE_FISHING_MONS_SUPER_ROD_SLOT_6 + 15 -#define ENCOUNTER_CHANCE_FISHING_MONS_SUPER_ROD_SLOT_8 ENCOUNTER_CHANCE_FISHING_MONS_SUPER_ROD_SLOT_7 + 4 -#define ENCOUNTER_CHANCE_FISHING_MONS_SUPER_ROD_SLOT_9 ENCOUNTER_CHANCE_FISHING_MONS_SUPER_ROD_SLOT_8 + 1 -#define ENCOUNTER_CHANCE_FISHING_MONS_SUPER_ROD_TOTAL (ENCOUNTER_CHANCE_FISHING_MONS_SUPER_ROD_SLOT_9) - -- if DEXNAV_ENABLED is TRUE -- these macros are 1 and 0, respectively if hidden_mons isn't in the encounter - rate list at the top of wild_encounters.json -#define ENCOUNTER_CHANCE_HIDDEN_MONS_SLOT_0 1 -#define ENCOUNTER_CHANCE_HIDDEN_MONS_SLOT_1 ENCOUNTER_CHANCE_HIDDEN_MONS_SLOT_0 + 0 -#define ENCOUNTER_CHANCE_HIDDEN_MONS_TOTAL (ENCOUNTER_CHANCE_HIDDEN_MONS_SLOT_1) - -const struct WildPokemon gRoute101_LandMons_Day[] = -{ - { 2, 2, SPECIES_WURMPLE }, - { 2, 2, SPECIES_POOCHYENA }, - { 2, 2, SPECIES_WURMPLE }, - { 3, 3, SPECIES_WURMPLE }, - { 3, 3, SPECIES_POOCHYENA }, - { 3, 3, SPECIES_POOCHYENA }, - { 3, 3, SPECIES_WURMPLE }, - { 3, 3, SPECIES_POOCHYENA }, - { 2, 2, SPECIES_ZIGZAGOON }, - { 2, 2, SPECIES_ZIGZAGOON }, - { 3, 3, SPECIES_ZIGZAGOON }, - { 3, 3, SPECIES_ZIGZAGOON }, -}; - -const struct WildPokemonInfo gRoute101_Day_LandMonsInfo= { 20, gRoute101_Day_LandMons }; -const struct WildPokemonHeader gWildMonHeaders[] = -{ - { - .mapGroup = MAP(ROUTE101), - .mapNum = MAP_NUM(ROUTE101), - .encounterTypes = - [OW_TIME_OF_DAY_DEFAULT] = - { - .landMonsInfo = &gRoute101_LandMonsInfo, - .waterMonsInfo = NULL, - .rockSmashMonsInfo = NULL, - .fishingMonsInfo = NULL, - .hiddenMonsInfo = NULL, - } - }, -} -""" +if __name__ == '__main__': + main()