merge w upcoming

This commit is contained in:
ghoulslash 2024-09-22 09:13:25 -04:00
commit b7246a018c
1223 changed files with 50202 additions and 30856 deletions

View File

@ -23,9 +23,10 @@ body:
label: Version
description: What version of pokeemerald-expansion are you using as a base?
options:
- 1.9.0 (Latest release)
- 1.9.1 (Latest release)
- master (default, unreleased bugfixes)
- upcoming (Edge)
- 1.9.0
- 1.8.6
- 1.8.5
- 1.8.4

View File

@ -23,9 +23,10 @@ body:
label: Version
description: What version of pokeemerald-expansion are you using as a base?
options:
- 1.9.0 (Latest release)
- 1.9.1 (Latest release)
- master (default, unreleased bugfixes)
- upcoming (Edge)
- 1.9.0
- 1.8.6
- 1.8.5
- 1.8.4

View File

@ -23,9 +23,10 @@ body:
label: Version
description: What version of pokeemerald-expansion are you using as a base?
options:
- 1.9.0 (Latest release)
- 1.9.1 (Latest release)
- master (default, unreleased bugfixes)
- upcoming (Edge)
- 1.9.0
- 1.8.6
- 1.8.5
- 1.8.4

View File

@ -15,19 +15,12 @@ jobs:
GAME_VERSION: EMERALD
GAME_REVISION: 0
GAME_LANGUAGE: ENGLISH
MODERN: 0
COMPARE: 0
UNUSED_ERROR: 1
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Checkout agbcc
uses: actions/checkout@v2
with:
path: agbcc
repository: pret/agbcc
- name: Install binutils
run: |
sudo apt update
@ -36,27 +29,13 @@ jobs:
# gcc-arm-none-eabi is only needed for the modern build
# as an alternative to dkP
- name: Install agbcc
run: |
./build.sh
./install.sh ../
working-directory: agbcc
- name: Agbcc
- name: ROM
env:
MODERN: 0
COMPARE: 0
run: make -j${nproc} -O all
- name: Modern
env:
MODERN: 1
COMPARE: 0
run: make -j${nproc} -O all
- name: Test
env:
MODERN: 1
TEST: 1
run: |
make -j${nproc} -O pokeemerald-test.elf

View File

@ -1,6 +1,7 @@
# Pokeemerald-Expansion Changelogs
## 1.9.x
- **[Version 1.9.1](docs/changelogs/1.9.x/1.9.1.md) - 🧹 Bugfix Release**
- **[Version 1.9.0](docs/changelogs/1.9.x/1.9.0.md) - ✨ Feature Release**
## 1.8.x

View File

@ -327,7 +327,7 @@ If this works, then proceed to [Installation](#installation). Otherwise, ask for
libpng is now installed.
Continue to [Installing pkg-config (macOS)](#installing-pkg-config-macos) if **pkg-config is not installed**. Otherwise, continue to [Installing devkitARM (macOS)](#installing-devkitarm-macos) if **devkitARM is not installed**.
If both pkg-config and devkitARM are already installed, go to [Choosing where to store pokeemerald Expansion (macOS)](#choosing-where-to-store-pokeemerald-expansion-macos).
### Installing pkg-config (macOS)
@ -541,7 +541,7 @@ If this works, then proceed to [Installation](#installation). Otherwise, ask for
> ```
> Where *\<folder where pokeemerald-expansion is to be stored>* is the path of the folder [where you chose to store pokeemerald Expansion](#Choosing-where-to-store-pokeemerald-expansion-WSL1). Then run the `git clone` command again.
</details>
Now you're ready to build pokeemerald Expansion.
## Build pokeemerald Expansion
@ -596,58 +596,6 @@ To build **pokeemerald.elf** with debug symbols under a modern toolchain:
```bash
make DINFO=1
```
Note that this is not necessary for a non-modern (agbcc) build since those are built with debug symbols by default.
### agbcc
<details>
<summary><i>Deprecated; installing agbcc is optional since 1.7.0</i>.</summary>
1. Install agbcc into pokeemerald-expansion. The commands to run depend on certain conditions. **You should only follow one of the listed instructions**:
- If agbcc has **not been built before** in the folder where you chose to store pokeemerald Expansion, run the following commands to build and install it into pokeemerald-expansion:
```bash
git clone https://github.com/pret/agbcc
cd agbcc
./build.sh
./install.sh ../pokeemerald-expansion
```
- **Otherwise**, if agbcc has been built before (e.g. if the git clone above fails), but was **last built on a different terminal** than the one currently used (only relevant to Windows, e.g. switching from msys2 to WSL1), then run the following commands to build and install it into pokeemerald-expansion:
```bash
cd agbcc
git clean -fX
./build.sh
./install.sh ../pokeemerald-expansion
```
- **Otherwise**, if agbcc has been built before on the same terminal, run the following commands to install agbcc into pokeemerald-expansion:
```bash
cd agbcc
./install.sh ../pokeemerald-expansion
```
<details>
<summary><i>Note...</i></summary>
> If building agbcc or pokeemerald results in an error, try deleting the agbcc folder and re-installing agbcc as if it has not been built before.
</details>
2. Once agbcc is installed, change directory back to the base directory where pokeemerald-expansion and agbcc are stored:
```bash
cd ..
```
3. To compile with agbcc:
```bash
make agbcc
```
</details>
# Useful additional tools

141
Makefile
View File

@ -25,10 +25,8 @@ AS := $(PREFIX)as
LD := $(PREFIX)ld
# note: the makefile must be set up so MODERNCC is never called
# if MODERN=0
MODERNCC := $(PREFIX)gcc
PATH_MODERNCC := PATH="$(PATH)" $(MODERNCC)
ARMCC := $(PREFIX)gcc
PATH_ARMCC := PATH="$(PATH)" $(ARMCC)
ifeq ($(OS),Windows_NT)
EXE := .exe
@ -40,45 +38,25 @@ TITLE := POKEMON EMER
GAME_CODE := BPEE
MAKER_CODE := 01
REVISION := 0
MODERN ?= 1
TEST ?= 0
ANALYZE ?= 0
UNUSED_ERROR ?= 0
ifeq (agbcc,$(MAKECMDGOALS))
MODERN := 0
endif
DEBUG ?= 0
ifeq (check,$(MAKECMDGOALS))
TEST := 1
endif
# use arm-none-eabi-cpp for macOS
# as macOS's default compiler is clang
# and clang's preprocessor will warn on \u
# when preprocessing asm files, expecting a unicode literal
# we can't unconditionally use arm-none-eabi-cpp
# as installations which install binutils-arm-none-eabi
# don't come with it
ifneq ($(MODERN),1)
ifeq ($(shell uname -s),Darwin)
CPP := $(PREFIX)cpp
else
CPP := $(CC) -E
endif
else
CPP := $(PREFIX)cpp
ifeq (debug,$(MAKECMDGOALS))
DEBUG := 1
endif
ROM_NAME := pokeemerald_agbcc.gba
CPP := $(PREFIX)cpp
ROM_NAME := pokeemerald.gba
ELF_NAME := $(ROM_NAME:.gba=.elf)
MAP_NAME := $(ROM_NAME:.gba=.map)
OBJ_DIR_NAME := build/emerald
MODERN_ROM_NAME := pokeemerald.gba
MODERN_ELF_NAME := $(MODERN_ROM_NAME:.gba=.elf)
MODERN_MAP_NAME := $(MODERN_ROM_NAME:.gba=.map)
MODERN_OBJ_DIR_NAME := build/modern
OBJ_DIR_NAME := build/modern
SHELL := bash -o pipefail
@ -86,14 +64,9 @@ ELF = $(ROM:.gba=.elf)
MAP = $(ROM:.gba=.map)
SYM = $(ROM:.gba=.sym)
TEST_OBJ_DIR_NAME_MODERN := build/modern-test
TEST_OBJ_DIR_NAME_AGBCC := build/test
TEST_OBJ_DIR_NAME := build/modern-test
DEBUG_OBJ_DIR_NAME := build/modern-debug
ifeq ($(MODERN),0)
TEST_OBJ_DIR_NAME := $(TEST_OBJ_DIR_NAME_AGBCC)
else
TEST_OBJ_DIR_NAME := $(TEST_OBJ_DIR_NAME_MODERN)
endif
TESTELF = $(ROM:.gba=-test.elf)
HEADLESSELF = $(ROM:.gba=-test-headless.elf)
@ -116,18 +89,11 @@ SONG_BUILDDIR = $(OBJ_DIR)/$(SONG_SUBDIR)
MID_BUILDDIR = $(OBJ_DIR)/$(MID_SUBDIR)
TEST_BUILDDIR = $(OBJ_DIR)/$(TEST_SUBDIR)
ASFLAGS := -mcpu=arm7tdmi --defsym MODERN=$(MODERN)
ASFLAGS := -mcpu=arm7tdmi --defsym MODERN=1
CC1 = $(shell $(PATH_ARMCC) --print-prog-name=cc1) -quiet
override CFLAGS += -mthumb -mthumb-interwork -mabi=apcs-gnu -mtune=arm7tdmi -march=armv4t -fno-toplevel-reorder -Wno-pointer-to-int-cast -std=gnu17 -Werror -Wall -Wno-strict-aliasing -Wno-attribute-alias -Woverride-init
ifeq ($(MODERN),0)
CC1 := tools/agbcc/bin/agbcc$(EXE)
override CFLAGS += -mthumb-interwork -Wimplicit -Wparentheses -Werror -O2 -fhex-asm -g
ROM := $(ROM_NAME)
OBJ_DIR := $(OBJ_DIR_NAME)
LIBPATH := -L ../../tools/agbcc/lib
LIB := $(LIBPATH) -lgcc -lc -L../../libagbsyscall -lagbsyscall
else
CC1 = $(shell $(PATH_MODERNCC) --print-prog-name=cc1) -quiet
override CFLAGS += -mthumb -mthumb-interwork -O2 -mabi=apcs-gnu -mtune=arm7tdmi -march=armv4t -fno-toplevel-reorder -Wno-pointer-to-int-cast -std=gnu17 -Werror -Wall -Wno-strict-aliasing -Wno-attribute-alias -Woverride-init
ifeq ($(ANALYZE),1)
override CFLAGS += -fanalyzer
endif
@ -137,10 +103,15 @@ ifneq ($(GITHUB_REPOSITORY_OWNER),rh-hideout)
override CFLAGS += -Wno-error=unused-variable -Wno-error=unused-const-variable -Wno-error=unused-parameter -Wno-error=unused-function -Wno-error=unused-but-set-parameter -Wno-error=unused-but-set-variable -Wno-error=unused-value -Wno-error=unused-local-typedefs
endif
endif
ROM := $(MODERN_ROM_NAME)
OBJ_DIR := $(MODERN_OBJ_DIR_NAME)
LIBPATH := -L "$(dir $(shell $(PATH_MODERNCC) -mthumb -print-file-name=libgcc.a))" -L "$(dir $(shell $(PATH_MODERNCC) -mthumb -print-file-name=libnosys.a))" -L "$(dir $(shell $(PATH_MODERNCC) -mthumb -print-file-name=libc.a))"
ROM := $(ROM_NAME)
OBJ_DIR := $(OBJ_DIR_NAME)
LIBPATH := -L "$(dir $(shell $(PATH_ARMCC) -mthumb -print-file-name=libgcc.a))" -L "$(dir $(shell $(PATH_ARMCC) -mthumb -print-file-name=libnosys.a))" -L "$(dir $(shell $(PATH_ARMCC) -mthumb -print-file-name=libc.a))"
LIB := $(LIBPATH) -lc -lnosys -lgcc -L../../libagbsyscall -lagbsyscall
ifeq ($(DEBUG),1)
override CFLAGS += -Og -g
else
override CFLAGS += -O2
endif
ifeq ($(TESTELF),$(MAKECMDGOALS))
@ -150,12 +121,13 @@ endif
ifeq ($(TEST),1)
OBJ_DIR := $(TEST_OBJ_DIR_NAME)
endif
CPPFLAGS := -iquote include -iquote $(GFLIB_SUBDIR) -Wno-trigraphs -DMODERN=$(MODERN) -DTESTING=$(TEST)
ifneq ($(MODERN),1)
CPPFLAGS += -I tools/agbcc/include -I tools/agbcc -nostdinc -undef
ifeq ($(DEBUG),1)
OBJ_DIR := $(DEBUG_OBJ_DIR_NAME)
endif
CPPFLAGS := -iquote include -iquote $(GFLIB_SUBDIR) -Wno-trigraphs -DMODERN=1 -DTESTING=$(TEST)
SHA1 := $(shell { command -v sha1sum || command -v shasum; } 2>/dev/null) -c
GFX := tools/gbagfx/gbagfx$(EXE)
AIF := tools/aif2pcm/aif2pcm$(EXE)
@ -191,7 +163,7 @@ MAKEFLAGS += --no-print-directory
# Secondary expansion is required for dependency variables in object rules.
.SECONDEXPANSION:
.PHONY: all rom clean compare tidy tools check-tools mostlyclean clean-tools clean-check-tools $(TOOLDIRS) $(CHECKTOOLDIRS) libagbsyscall agbcc modern tidymodern tidynonmodern check history
.PHONY: all rom clean compare tidy tools check-tools mostlyclean clean-tools clean-check-tools $(TOOLDIRS) $(CHECKTOOLDIRS) libagbsyscall agbcc modern tidymodern tidynonmodern check history debug
infoshell = $(foreach line, $(shell $1 | sed "s/ /__SPACE__/g"), $(info $(subst __SPACE__, ,$(line))))
@ -199,7 +171,7 @@ infoshell = $(foreach line, $(shell $1 | sed "s/ /__SPACE__/g"), $(info $(subst
# Disable dependency scanning for clean/tidy/tools
# Use a separate minimal makefile for speed
# Since we don't need to reload most of this makefile
ifeq (,$(filter-out all rom compare agbcc modern check libagbsyscall syms $(TESTELF),$(MAKECMDGOALS)))
ifeq (,$(filter-out all rom compare agbcc modern check libagbsyscall syms $(TESTELF) debug,$(MAKECMDGOALS)))
$(call infoshell, $(MAKE) -f make_tools.mk)
else
NODEP ?= 1
@ -291,7 +263,7 @@ clean-tools:
clean-check-tools:
@$(foreach tooldir,$(CHECKTOOLDIRS),$(MAKE) clean -C $(tooldir);)
mostlyclean: tidynonmodern tidymodern tidycheck
mostlyclean: tidynonmodern tidymodern tidycheck tidydebug
find sound -iname '*.bin' -exec rm {} +
rm -f $(MID_SUBDIR)/*.s
find . \( -iname '*.1bpp' -o -iname '*.4bpp' -o -iname '*.8bpp' -o -iname '*.gbapal' -o -iname '*.lz' -o -iname '*.rl' -o -iname '*.latfont' -o -iname '*.hwjpnfont' -o -iname '*.fwjpnfont' \) -exec rm {} +
@ -301,25 +273,18 @@ mostlyclean: tidynonmodern tidymodern tidycheck
rm -f $(AUTO_GEN_TARGETS)
@$(MAKE) clean -C libagbsyscall
tidy: tidynonmodern tidymodern tidycheck
tidy: tidymodern tidycheck tidydebug
tidynonmodern:
tidymodern:
rm -f $(ROM_NAME) $(ELF_NAME) $(MAP_NAME)
rm -rf $(OBJ_DIR_NAME)
tidymodern:
rm -f $(MODERN_ROM_NAME) $(MODERN_ELF_NAME) $(MODERN_MAP_NAME)
rm -rf $(MODERN_OBJ_DIR_NAME)
tidycheck:
rm -f $(TESTELF) $(HEADLESSELF)
rm -rf $(TEST_OBJ_DIR_NAME_MODERN)
rm -rf $(TEST_OBJ_DIR_NAME_AGBCC)
rm -rf $(TEST_OBJ_DIR_NAME)
ifneq ($(MODERN),0)
$(C_BUILDDIR)/berry_crush.o: override CFLAGS += -Wno-address-of-packed-member
endif
tidydebug:
rm -rf $(DEBUG_OBJ_DIR_NAME)
include graphics_file_rules.mk
include map_data_rules.mk
@ -346,35 +311,24 @@ sound/%.bin: sound/%.aif ; $(AIF) $< $@
COMPETITIVE_PARTY_SYNTAX := $(shell PATH="$(PATH)"; echo 'COMPETITIVE_PARTY_SYNTAX' | $(CPP) $(CPPFLAGS) -imacros include/global.h | tail -n1)
ifeq ($(COMPETITIVE_PARTY_SYNTAX),1)
%.h: %.party tools ; $(CPP) $(CPPFLAGS) -traditional-cpp - < $< | sed '/#[^p]/d' | $(TRAINERPROC) -o $@ -i $< -
%.h: %.party tools ; $(CPP) $(CPPFLAGS) -traditional-cpp - < $< | $(TRAINERPROC) -o $@ -i $< -
endif
ifeq ($(MODERN),0)
$(C_BUILDDIR)/libc.o: CC1 := tools/agbcc/bin/old_agbcc$(EXE)
$(C_BUILDDIR)/libc.o: CFLAGS := -O2
$(C_BUILDDIR)/siirtc.o: CFLAGS := -mthumb-interwork
$(C_BUILDDIR)/agb_flash.o: CFLAGS := -O -mthumb-interwork
$(C_BUILDDIR)/agb_flash_1m.o: CFLAGS := -O -mthumb-interwork
$(C_BUILDDIR)/agb_flash_mx.o: CFLAGS := -O -mthumb-interwork
$(C_BUILDDIR)/m4a.o: CC1 := tools/agbcc/bin/old_agbcc$(EXE)
$(C_BUILDDIR)/record_mixing.o: CFLAGS += -ffreestanding
$(C_BUILDDIR)/librfu_intr.o: CC1 := tools/agbcc/bin/agbcc_arm$(EXE)
$(C_BUILDDIR)/librfu_intr.o: CFLAGS := -O2 -mthumb-interwork -quiet
else
$(C_BUILDDIR)/berry_crush.o: override CFLAGS += -Wno-address-of-packed-member
$(C_BUILDDIR)/librfu_intr.o: CFLAGS := -mthumb-interwork -O2 -mabi=apcs-gnu -mtune=arm7tdmi -march=armv4t -fno-toplevel-reorder -Wno-pointer-to-int-cast
$(C_BUILDDIR)/pokedex_plus_hgss.o: CFLAGS := -mthumb -mthumb-interwork -O2 -mabi=apcs-gnu -mtune=arm7tdmi -march=armv4t -Wno-pointer-to-int-cast -std=gnu17 -Werror -Wall -Wno-strict-aliasing -Wno-attribute-alias -Woverride-init
# Annoyingly we can't turn this on just for src/data/trainers.h
$(C_BUILDDIR)/data.o: CFLAGS += -fno-show-column -fno-diagnostics-show-caret
endif
ifeq ($(DINFO),1)
override CFLAGS += -g
endif
ifeq ($(NOOPT),1)
override CFLAGS := $(filter-out -O1 -Og -O2,$(CFLAGS))
override CFLAGS += -O0
endif
# The dep rules have to be explicit or else missing files won't be reported.
# As a side effect, they're evaluated immediately instead of when the rule is invoked.
# It doesn't look like $(shell) can be deferred so there might not be a better way.
@ -488,13 +442,8 @@ $1: $2 $$(shell $(SCANINC) -I include -I tools/agbcc/include -I gflib $2)
endef
$(foreach src, $(TEST_SRCS), $(eval $(call TEST_DEP,$(patsubst $(TEST_SUBDIR)/%.c,$(TEST_BUILDDIR)/%.o,$(src)),$(src),$(patsubst $(TEST_SUBDIR)/%.c,%,$(src)))))
ifeq ($(MODERN),0)
LD_SCRIPT := ld_script.ld
LD_SCRIPT_DEPS := $(OBJ_DIR)/sym_bss.ld $(OBJ_DIR)/sym_common.ld $(OBJ_DIR)/sym_ewram.ld
else
LD_SCRIPT := ld_script_modern.ld
LD_SCRIPT_DEPS :=
endif
$(OBJ_DIR)/ld_script.ld: $(LD_SCRIPT) $(LD_SCRIPT_DEPS)
cd $(OBJ_DIR) && sed "s#tools/#../../tools/#g" ../../$(LD_SCRIPT) > ld_script.ld
@ -518,6 +467,8 @@ agbcc:
modern: all
debug: all
LD_SCRIPT_TEST := ld_script_test.ld
$(OBJ_DIR)/ld_script_test.ld: $(LD_SCRIPT_TEST) $(LD_SCRIPT_DEPS)
@ -541,7 +492,7 @@ check: $(TESTELF)
$(ROMTESTHYDRA) $(ROMTEST) $(OBJCOPY) $(HEADLESSELF)
libagbsyscall:
@$(MAKE) -C libagbsyscall TOOLCHAIN=$(TOOLCHAIN) MODERN=$(MODERN)
@$(MAKE) -C libagbsyscall TOOLCHAIN=$(TOOLCHAIN) MODERN=1
###################
### Symbol file ###

View File

@ -9,7 +9,7 @@ pokeemerald-expansion is a decomp hack base project based off pret's [pokeemeral
If you use pokeemerald-expansion in your hack, please add RHH (Rom Hacking Hideout) to your credits list. Optionally, you can list the version used, so it can help players know what features to expect.
You can phrase it as the following:
```
Based off RHH's pokeemerald-expansion 1.9.0 https://github.com/rh-hideout/pokeemerald-expansion/
Based off RHH's pokeemerald-expansion 1.9.1 https://github.com/rh-hideout/pokeemerald-expansion/
```
## What features are included?

View File

@ -507,9 +507,9 @@
.byte \battler
.endm
.macro trainerslidein battler:req
.macro trainerslidein position:req
.byte 0x53
.byte \battler
.byte \position
.endm
.macro playse song:req
@ -1670,14 +1670,66 @@
callnative BS_DamageToQuarterTargetHP
.endm
@ various command changed to more readable macros
.macro cancelmultiturnmoves battler:req
various \battler, VARIOUS_CANCEL_MULTI_TURN_MOVES
.macro ficklebeamdamagecalculation
callnative BS_FickleBeamDamageCalculation
.endm
.macro trytarshot failInstr:req
callnative BS_TryTarShot
.4byte \failInstr
.endm
.macro jumpifteainvulnerable battler:req, jumpInstr:req
callnative BS_TeatimeInvul
.byte \battler
.4byte \jumpInstr
.endm
.macro jumpifteanoberry failInstr:req
callnative BS_TeatimeTargets
.4byte \failInstr
.endm
.macro trywindriderpower battler:req, failInstr:req
callnative BS_TryWindRiderPower
.byte \battler
.4byte \failInstr
.endm
.macro activateweatherchangeabilities battler:req
callnative BS_ActivateWeatherChangeAbilities
.byte \battler
.endm
.macro activateterrainchangeabilities battler:req
callnative BS_ActivateTerrainChangeAbilities
.byte \battler
.endm
@ Stores Healing Wish effect.
.macro storehealingwish battler:req
various \battler, VARIOUS_STORE_HEALING_WISH
callnative BS_StoreHealingWish
.byte \battler
.endm
.macro hitswitchtargetfailed
callnative BS_HitSwitchTargetFailed
.endm
.macro tryrevivalblessing, failInstr:req
callnative BS_TryRevivalBlessing
.4byte \failInstr
.endm
.macro jumpifblockedbysoundproof battler:req, failInstr:req
callnative BS_JumpIfBlockedBySoundproof
.byte \battler
.4byte \failInstr
.endm
@ various command changed to more readable macros
.macro cancelmultiturnmoves battler:req
various \battler, VARIOUS_CANCEL_MULTI_TURN_MOVES
.endm
.macro setmagiccoattarget battler:req
@ -2206,11 +2258,6 @@
.4byte \failInstr
.endm
.macro trytarshot battler:req, failInstr:req
various \battler, VARIOUS_TRY_TAR_SHOT
.4byte \failInstr
.endm
.macro cantarshotwork battler:req, failInstr:req
various \battler, VARIOUS_CAN_TAR_SHOT_WORK
.4byte \failInstr
@ -2226,16 +2273,6 @@
.4byte \failInstr
.endm
.macro jumpifteanoberry jumpInstr:req
various BS_ATTACKER, VARIOUS_TEATIME_TARGETS
.4byte \jumpInstr
.endm
.macro jumpifteainvulnerable battler:req, jumpInstr:req
various \battler, VARIOUS_TEATIME_INVUL
.4byte \jumpInstr
.endm
.macro curecertainstatuses battler:req
various \battler, VARIOUS_CURE_CERTAIN_STATUSES
.endm
@ -2280,19 +2317,6 @@
.byte \stat
.endm
.macro trywindriderpower battler:req, failInstr:req
various \battler, VARIOUS_TRY_WIND_RIDER_POWER
.4byte \failInstr
.endm
.macro activateweatherchangeabilities battler:req
various \battler, VARIOUS_ACTIVATE_WEATHER_CHANGE_ABILITIES
.endm
.macro activateterrainchangeabilities battler:req
various \battler, VARIOUS_ACTIVATE_TERRAIN_CHANGE_ABILITIES
.endm
@ helpful macros
.macro setstatchanger stat:req, stages:req, down:req
setbyte sSTATCHANGER, \stat | \stages << 3 | \down << 7
@ -2487,15 +2511,6 @@
waitmessage B_WAIT_TIME_LONG
.endm
.macro hitswitchtargetfailed
various 0, VARIOUS_HIT_SWITCH_TARGET_FAILED
.endm
.macro tryrevivalblessing, jumpInstr:req
various 0, VARIOUS_TRY_REVIVAL_BLESSING
.4byte \jumpInstr
.endm
@ Will jump to script pointer if the specified battler has or has not fainted.
.macro jumpiffainted battler:req, value:req, ptr:req
getbattlerfainted \battler

View File

@ -1798,7 +1798,7 @@
.4byte \text
.endm
@ Equivalent to fadescreen but copies gPlttBufferUnfaded to gPaletteDecompressionBuffer on the fade out
@ Equivalent to fadescreen but copies gPlttBufferUnfaded to gDecompressionBuffer on the fade out
@ and the reverse on the fade in, in effect saving gPlttBufferUnfaded to restore it.
.macro fadescreenswapbuffers mode:req
.byte 0xdc
@ -2321,3 +2321,20 @@
.macro togglefakertc
callnative Script_ToggleFakeRtc
.endm
@ ============================ @
@ ITEM DESCRIPTION HEADER MACROS
@ Used with OW_SHOW_ITEM_DESCRIPTIONS config
.macro showitemdescription
callnative ScriptShowItemDescription
.byte 0
.endm
.macro showberrydescription
callnative ScriptShowItemDescription
.byte 1
.endm
.macro hideitemdescription
callnative ScriptHideItemDescription
.endm

View File

@ -45,6 +45,7 @@ SUPER_ER = 2C
LV = 34
'=' = 35
';' = 36
V_D_ARROW = 38
'¿' = 51
'¡' = 52
PK = 53

View File

@ -1 +0,0 @@
lman

View File

@ -1,10 +0,0 @@
gFlashTimeoutFlag
PollFlashStatus
WaitForFlashWrite
ProgramFlashSector
gFlash
ProgramFlashByte
gFlashNumRemainingBytes
EraseFlashChip
EraseFlashSector
gFlashMaxTime

View File

@ -1,3 +0,0 @@
gApprenticePartyMovesData
gApprenticeQuestionData
gApprenticeFunc

View File

@ -1,3 +0,0 @@
gMonShrinkDuration
gMonShrinkDelta
gMonShrinkDistance

View File

@ -1,3 +0,0 @@
gBattlerControllerFuncs
gBattleControllerData
gBattlerControllerEndFuncs

View File

@ -1 +0,0 @@
gFactorySelect_CurrentOptionFunc

View File

@ -1,7 +0,0 @@
gPreBattleCallback1
gBattleMainFunc
gBattleResults
gLeveledUpInBattle
gHealthboxSpriteIds
gMultiUsePlayerCursor
gNumberOfMovesToChoose

View File

@ -1 +0,0 @@
gFrontierTempParty

View File

@ -1 +0,0 @@
gInGameOpponentsNo

View File

@ -1 +0,0 @@
gWindowTileAutoAllocEnabled

View File

@ -1 +0,0 @@
gContestRngValue

View File

@ -1,4 +0,0 @@
gContestMonPixels
gImageProcessingContext
gContestPaintingWinner
gContestPaintingMonPalette

View File

@ -1 +0,0 @@
gEReaderData

View File

@ -1 +0,0 @@
gCB2_AfterEvolution

View File

@ -1,3 +0,0 @@
sPlayerToMewDeltaX
sPlayerToMewDeltaY
sMewDirectionCandidates

View File

@ -1,3 +0,0 @@
gFieldCamera
gTotalCameraPixelOffsetY
gTotalCameraPixelOffsetX

View File

@ -1 +0,0 @@
gSelectedObjectEvent

View File

@ -1 +0,0 @@
gScrollableMultichoice_ListMenuTemplate

View File

@ -1 +0,0 @@
gBackupMapLayout

View File

@ -1,10 +0,0 @@
gCanvasColumnStart
gCanvasPixels
gCanvasRowEnd
gCanvasHeight
gCanvasColumnEnd
gCanvasRowStart
gCanvasMonPersonality
gCanvasWidth
gCanvasPalette
gCanvasPaletteStart

View File

@ -1,2 +0,0 @@
gIntroFrameCounter
gMultibootProgramStruct

View File

@ -1,5 +0,0 @@
gRfuSlotStatusUNI
gRfuSlotStatusNI
gRfuLinkStatus
gRfuStatic
gRfuFixed

View File

@ -1 +0,0 @@
gRfuSIO32Id

View File

@ -1 +0,0 @@
gSTWIStatus

View File

@ -1,35 +0,0 @@
gLinkPartnersHeldKeys
gLinkDebugSeed
gLocalLinkPlayerBlock
gLinkErrorOccurred
gLinkDebugFlags
gLinkFiller1
gRemoteLinkPlayersNotReceived
gBlockReceivedStatus
gLinkFiller2
gLinkHeldKeys
gRecvCmds
gLinkStatus
gLinkDummy1
gLinkDummy2
gReadyToExitStandby
gReadyToCloseLink
gReadyCloseLinkType
gSuppressLinkErrorMessage
gWirelessCommType
gSavedLinkPlayerCount
gSendCmd
gSavedMultiplayerId
gReceivedRemoteLinkPlayers
gLinkTestBGInfo
gLinkCallback
gShouldAdvanceLinkState
gLinkTestBlockChecksums
gBlockRequestType
gLinkFiller3
gLinkFiller4
gLinkFiller5
gLastSendQueueCount
gLink
gLastRecvQueueCount
gLinkSavedIme

View File

@ -1,2 +0,0 @@
gRfuAPIBuffer
gRfu

View File

@ -1,2 +0,0 @@
gListMenuOverride
gMultiuseListMenuTemplate

View File

@ -1,4 +0,0 @@
gFlashMemoryPresent
gSaveBlock1Ptr
gSaveBlock2Ptr
gPokemonStoragePtr

View File

@ -1,12 +0,0 @@
gSoundInfo
gPokemonCrySongs
gPokemonCryMusicPlayers
gMPlayInfo_BGM
gMPlayJumpTable
gCgbChans
gMPlayInfo_SE1
gMPlayInfo_SE2
gPokemonCryTracks
gPokemonCrySong
gMPlayMemAccArea
gMPlayInfo_SE3

View File

@ -1,10 +0,0 @@
gKeyRepeatStartDelay
gLinkTransferringData
gMain
gKeyRepeatContinueDelay
gSoftResetDisabled
gIntrTable
gLinkVSyncDisabled
IntrMain_Buffer
gPcmDmaCounter
gAgbMainLoop_sp

View File

@ -1 +0,0 @@
gBardSong

View File

@ -1,8 +0,0 @@
gOverworldTilemapBuffer_Bg2
gOverworldTilemapBuffer_Bg1
gOverworldTilemapBuffer_Bg3
gHeldKeyCodeToSend
gFieldCallback
gFieldCallback2
gLocalLinkPlayerId
gFieldLinkPlayerCount

View File

@ -1 +0,0 @@
gItemUseCB

View File

@ -1,2 +0,0 @@
gUnusedPokedexU8
gPokedexVBlankCB

View File

@ -1 +0,0 @@
gDexCryScreenState

View File

@ -1,2 +0,0 @@
gRngValue
gRng2Value

View File

@ -1 +0,0 @@
gLocalTime

View File

@ -1,13 +0,0 @@
gLastWrittenSector
gLastSaveCounter
gLastKnownGoodSector
gDamagedSaveSectors
gSaveCounter
gReadWriteSector
gIncrementalSectorId
gSaveUnusedVar
gSaveFileStatus
gGameContinueCallback
gRamSaveSectorLocations
gSaveUnusedVar2
gSaveAttemptStatus

View File

@ -1 +0,0 @@
gDisableMusic

View File

@ -1,2 +0,0 @@
gOamMatrixAllocBitmap
gReservedSpritePaletteCount

View File

@ -1 +0,0 @@
gMenuCallback

View File

@ -1 +0,0 @@
gTasks

View File

@ -1,4 +0,0 @@
gFonts
gDisableTextPrinters
gCurGlyph
gTextFlags

View File

@ -1,5 +0,0 @@
gWhichTrainerToFaceAfterBattle
gPostBattleMovementScript
gApproachingTrainers
gNoOfApproachingTrainers
gTrainerApproachedPlayer

View File

@ -1,4 +0,0 @@
sCurTVShowSlot
sTV_SecretBaseVisitMovesTemp
sTV_DecorationsBuffer
sTV_SecretBaseVisitMonsTemp

View File

@ -1,2 +0,0 @@
gTransparentTileNumber
gWindowBgTilemapBuffers

File diff suppressed because it is too large Load Diff

View File

@ -30,6 +30,19 @@ BattleScript_DamageToQuarterTargetHP::
damagetoquartertargethp
goto BattleScript_HitFromAtkAnimation
BattleScript_EffectFickleBeam::
attackcanceler
attackstring
ppreduce
accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE
ficklebeamdamagecalculation
goto BattleScript_HitFromCritCalc
BattleScript_FickleBeamDoubled::
pause B_WAIT_TIME_SHORTEST
printstring STRINGID_FICKLEBEAMDOUBLED
waitmessage B_WAIT_TIME_LONG
goto BattleScript_HitFromCritCalc
BattleScript_Terastallization::
@ TODO: no string prints in S/V, but right now this helps with clarity
printstring STRINGID_PKMNSTORINGENERGY
@ -495,7 +508,7 @@ BattleScript_EffectAttackUpUserAlly_TryAlly:
BattleScript_EffectAttackUpUserAlly_End:
goto BattleScript_MoveEnd
BattleScript_EffectAttackUpUserAlly_TryAlly_:
jumpifability BS_ATTACKER_PARTNER, ABILITY_SOUNDPROOF, BattleScript_EffectAttackUpUserAlly_TryAllyBlocked
jumpifblockedbysoundproof BS_ATTACKER_PARTNER, BattleScript_EffectAttackUpUserAlly_TryAllyBlocked
setstatchanger STAT_ATK, 1, FALSE
statbuffchange STAT_CHANGE_ALLOW_PTR, BattleScript_EffectAttackUpUserAlly_End
jumpifbyte CMP_NOT_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_EffectAttackUpUserAlly_AllyAnim
@ -565,7 +578,7 @@ BattleScript_Teatimerod:
statbuffchange STAT_CHANGE_ALLOW_PTR, BattleScript_TeatimeBuffer
jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, 0x2, BattleScript_TeatimeBuffer
printfromtable gStatUpStringIds
waitmessage 0x40
waitmessage B_WAIT_TIME_LONG
moveendto MOVEEND_NEXT_TARGET
jumpifnexttargetvalid BattleScript_TeatimeLoop
moveendcase MOVEEND_CLEAR_BITS
@ -577,7 +590,7 @@ BattleScript_Teatimemotor:
statbuffchange STAT_CHANGE_ALLOW_PTR, BattleScript_TeatimeBuffer
jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, 0x2, BattleScript_TeatimeBuffer
printfromtable gStatUpStringIds
waitmessage 0x40
waitmessage B_WAIT_TIME_LONG
moveendto MOVEEND_NEXT_TARGET
jumpifnexttargetvalid BattleScript_TeatimeLoop
moveendcase MOVEEND_CLEAR_BITS
@ -865,6 +878,7 @@ BattleScript_OctlockTurnDmgEnd:
BattleScript_EffectPoltergeist::
attackcanceler
accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE
attackstring
ppreduce
checkpoltergeist BS_TARGET, BattleScript_ButItFailed
@ -888,7 +902,7 @@ BattleScript_EffectTarShot::
printfromtable gStatDownStringIds
waitmessage B_WAIT_TIME_LONG
BattleScript_TryTarShot:
trytarshot BS_TARGET, BattleScript_MoveEnd
trytarshot BattleScript_MoveEnd
printstring STRINGID_PKMNBECAMEWEAKERTOFIRE
waitmessage B_WAIT_TIME_LONG
goto BattleScript_MoveEnd
@ -914,19 +928,10 @@ BattleScript_BothCanNoLongerEscape::
return
BattleScript_EffectHyperspaceFury::
jumpifspecies BS_ATTACKER, SPECIES_HOOPA_UNBOUND, BattleScript_EffectHyperspaceFuryUnbound
jumpifspecies BS_ATTACKER, SPECIES_HOOPA_UNBOUND, BattleScript_EffectHit
jumpifspecies BS_ATTACKER, SPECIES_HOOPA_CONFINED, BattleScript_ButHoopaCantUseIt
goto BattleScript_PokemonCantUseTheMove
BattleScript_EffectHyperspaceFuryUnbound::
attackcanceler
accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE
attackstring
pause B_WAIT_TIME_LONG
ppreduce
seteffectprimary MOVE_EFFECT_FEINT
goto BattleScript_HitFromCritCalc
BattleScript_ButHoopaCantUseIt:
printstring STRINGID_BUTHOOPACANTUSEIT
waitmessage B_WAIT_TIME_LONG
@ -1752,6 +1757,8 @@ BattleScript_EffectInstruct::
tryinstruct BattleScript_ButItFailed
attackanimation
waitanimation
copybyte gBattlerAttacker, gBattlerTarget
copybyte gBattlerTarget, gEffectBattler
printstring STRINGID_USEDINSTRUCTEDMOVE
waitmessage B_WAIT_TIME_LONG
setbyte sB_ANIM_TURN, 0
@ -1831,7 +1838,7 @@ BattleScript_HitSwitchTargetForceRandomSwitchFailed:
goto BattleScript_MoveEnd
BattleScript_EffectToxicThread::
setstatchanger STAT_SPEED, 2, TRUE
setstatchanger STAT_SPEED, 1, TRUE
attackcanceler
jumpifsubstituteblocks BattleScript_FailedFromAtkString
jumpifstat BS_TARGET, CMP_NOT_EQUAL, STAT_SPEED, MIN_STAT_STAGE, BattleScript_ToxicThreadWorks
@ -4274,7 +4281,7 @@ BattleScript_EffectPerishSong::
waitmessage B_WAIT_TIME_LONG
setbyte gBattlerTarget, 0
BattleScript_PerishSongLoop::
jumpifability BS_TARGET, ABILITY_SOUNDPROOF, BattleScript_PerishSongBlocked
jumpifblockedbysoundproof BS_TARGET, BattleScript_PerishSongBlocked
jumpifpranksterblocked BS_TARGET, BattleScript_PerishSongNotAffected
BattleScript_PerishSongLoopIncrement::
addbyte gBattlerTarget, 1
@ -4717,6 +4724,9 @@ BattleScript_ButItFailed::
resultmessage
waitmessage B_WAIT_TIME_LONG
goto BattleScript_MoveEnd
BattleScript_RestoreAttackerButItFailed:
restoreattacker
goto BattleScript_ButItFailed
BattleScript_NotAffected::
pause B_WAIT_TIME_SHORT
@ -5596,13 +5606,13 @@ BattleScript_LocalTrainerBattleWon::
BattleScript_LocalTwoTrainersDefeated::
printstring STRINGID_TWOENEMIESDEFEATED
BattleScript_LocalBattleWonLoseTexts::
trainerslidein BS_ATTACKER
trainerslidein BS_OPPONENT1
waitstate
printstring STRINGID_TRAINER1LOSETEXT
jumpifnotbattletype BATTLE_TYPE_TWO_OPPONENTS, BattleScript_LocalBattleWonReward
trainerslideout B_POSITION_OPPONENT_LEFT
trainerslideout BS_OPPONENT1
waitstate
trainerslidein BS_FAINTED
trainerslidein BS_OPPONENT2
waitstate
printstring STRINGID_TRAINER2LOSETEXT
BattleScript_LocalBattleWonReward::
@ -5654,15 +5664,15 @@ BattleScript_LocalBattleLostPrintTrainersWinText::
waitstate
returnopponentmon2toball BS_ATTACKER
waitstate
trainerslidein BS_ATTACKER
trainerslidein BS_OPPONENT1
waitstate
printstring STRINGID_TRAINER1WINTEXT
jumpifbattletype BATTLE_TYPE_TOWER_LINK_MULTI, BattleScript_LocalBattleLostDoTrainer2WinText
jumpifnotbattletype BATTLE_TYPE_TWO_OPPONENTS, BattleScript_LocalBattleLostEnd_
BattleScript_LocalBattleLostDoTrainer2WinText::
trainerslideout B_POSITION_OPPONENT_LEFT
trainerslideout BS_OPPONENT1
waitstate
trainerslidein BS_FAINTED
trainerslidein BS_OPPONENT2
waitstate
printstring STRINGID_TRAINER2WINTEXT
BattleScript_LocalBattleLostEnd_::
@ -5673,12 +5683,12 @@ BattleScript_FrontierLinkBattleLost::
waitstate
returnopponentmon2toball BS_ATTACKER
waitstate
trainerslidein BS_ATTACKER
trainerslidein BS_OPPONENT1
waitstate
printstring STRINGID_TRAINER1WINTEXT
trainerslideout B_POSITION_OPPONENT_LEFT
trainerslideout BS_OPPONENT1
waitstate
trainerslidein BS_FAINTED
trainerslidein BS_OPPONENT2
waitstate
printstring STRINGID_TRAINER2WINTEXT
jumpifbattletype BATTLE_TYPE_RECORDED, BattleScript_FrontierLinkBattleLostEnd
@ -5701,12 +5711,12 @@ BattleScript_TowerLinkBattleWon::
playtrainerdefeatbgm BS_ATTACKER
printstring STRINGID_BATTLEEND
waitmessage B_WAIT_TIME_LONG
trainerslidein BS_ATTACKER
trainerslidein BS_OPPONENT1
waitstate
printstring STRINGID_TRAINER1LOSETEXT
trainerslideout B_POSITION_OPPONENT_LEFT
trainerslideout BS_OPPONENT1
waitstate
trainerslidein BS_FAINTED
trainerslidein BS_OPPONENT2
waitstate
printstring STRINGID_TRAINER2LOSETEXT
jumpifbattletype BATTLE_TYPE_RECORDED, BattleScript_TowerLinkBattleWonEnd
@ -5723,13 +5733,13 @@ BattleScript_FrontierTrainerBattleWon::
BattleScript_FrontierTrainerBattleWon_TwoDefeated:
printstring STRINGID_TWOENEMIESDEFEATED
BattleScript_FrontierTrainerBattleWon_LoseTexts:
trainerslidein BS_ATTACKER
trainerslidein BS_OPPONENT1
waitstate
printstring STRINGID_TRAINER1LOSETEXT
jumpifnotbattletype BATTLE_TYPE_TWO_OPPONENTS, BattleScript_TryPickUpItems
trainerslideout B_POSITION_OPPONENT_LEFT
trainerslideout BS_OPPONENT1
waitstate
trainerslidein BS_FAINTED
trainerslidein BS_OPPONENT2
waitstate
printstring STRINGID_TRAINER2LOSETEXT
BattleScript_TryPickUpItems:
@ -6356,6 +6366,7 @@ BattleScript_StickyWebOnSwitchInPrintStatMsg:
BattleScript_StickyWebOnSwitchInEnd:
restoretarget
restoreattacker
setbyte sSTICKY_WEB_STAT_DROP, 0
return
BattleScript_PerishSongTakesLife::
@ -6452,12 +6463,14 @@ BattleScript_SeedSowerActivates::
return
BattleScript_AngerShellActivates::
saveattacker
copybyte gBattlerAttacker, gBattlerTarget
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_ButItFailed
jumpifstat BS_TARGET, CMP_EQUAL, STAT_SPDEF, MIN_STAT_STAGE, BattleScript_RestoreAttackerButItFailed
BattleScript_AngerShellTryDef::
setbyte sSTAT_ANIM_PLAYED, FALSE
modifybattlerstatstage BS_ATTACKER, STAT_DEF, DECREASE, 1, BattleScript_AngerShellTrySpDef, ANIM_ON
@ -6471,6 +6484,7 @@ BattleScript_AngerShellTrySpAtk:
BattleScript_AngerShellTrySpeed:
modifybattlerstatstage BS_ATTACKER, STAT_SPEED, INCREASE, 1, BattleScript_AngerShellRet, ANIM_ON
BattleScript_AngerShellRet:
restoreattacker
return
BattleScript_WindPowerActivates::
@ -7135,7 +7149,7 @@ BattleScript_TargetFormChangeWithStringNoPopup::
BattleScript_BattlerFormChangeWithStringEnd3::
pause 5
call BattleScript_AbilityPopUp
call BattleScript_AbilityPopUpScripting
flushtextbox
handleformchange BS_SCRIPTING, 0
handleformchange BS_SCRIPTING, 1
@ -7739,6 +7753,15 @@ BattleScript_CheekPouchActivates::
copybyte gBattlerAttacker, sSAVED_BATTLER
return
BattleScript_PickupActivates::
pause 5
tryrecycleitem BattleScript_PickupActivatesEnd
call BattleScript_AbilityPopUp
printstring STRINGID_XFOUNDONEY
waitmessage B_WAIT_TIME_LONG
BattleScript_PickupActivatesEnd:
end3
BattleScript_HarvestActivates::
pause 5
tryrecycleitem BattleScript_HarvestActivatesEnd
@ -7986,7 +8009,7 @@ BattleScript_DeltaStreamActivates::
end3
BattleScript_ProtosynthesisActivates::
call BattleScript_AbilityPopUp
call BattleScript_AbilityPopUpScripting
printstring STRINGID_SUNLIGHTACTIVATEDABILITY
waitmessage B_WAIT_TIME_MED
printstring STRINGID_STATWASHEIGHTENED

View File

@ -45,7 +45,7 @@ BattleScript_UseItemMessage:
printfromtable gTrainerUsedItemStringIds
waitmessage B_WAIT_TIME_LONG
return
BattleScript_ItemRestoreHPRet:
bichalfword gMoveResultFlags, MOVE_RESULT_NO_EFFECT
orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE
@ -238,7 +238,7 @@ BattleScript_ActionWallyThrow:
waitmessage B_WAIT_TIME_LONG
returnatktoball
waitstate
trainerslidein BS_TARGET
trainerslidein BS_PLAYER1
waitstate
printstring STRINGID_YOUTHROWABALLNOWRIGHT
waitmessage B_WAIT_TIME_LONG
@ -246,10 +246,10 @@ BattleScript_ActionWallyThrow:
BattleScript_TrainerASlideMsgRet::
handletrainerslidemsg BS_SCRIPTING, 0
trainerslidein B_POSITION_OPPONENT_LEFT
trainerslidein BS_OPPONENT1
handletrainerslidemsg BS_SCRIPTING, 1
waitstate
trainerslideout B_POSITION_OPPONENT_LEFT
trainerslideout BS_OPPONENT1
waitstate
handletrainerslidemsg BS_SCRIPTING, 2
return
@ -260,10 +260,10 @@ BattleScript_TrainerASlideMsgEnd2::
BattleScript_TrainerBSlideMsgRet::
handletrainerslidemsg BS_SCRIPTING, 0
trainerslidein B_POSITION_OPPONENT_RIGHT
trainerslidein BS_OPPONENT2
handletrainerslidemsg BS_SCRIPTING, 1
waitstate
trainerslideout B_POSITION_OPPONENT_RIGHT
trainerslideout BS_OPPONENT2
waitstate
handletrainerslidemsg BS_SCRIPTING, 2
return

View File

@ -724,6 +724,11 @@ EventScript_BackupMrBrineyLocation::
.include "data/scripts/rival_graphics.inc"
.include "data/scripts/set_gym_trainers.inc"
EventScript_CancelMessageBox::
special UseBlankMessageToCancelPokemonPic
release
end
Common_EventScript_ShowBagIsFull::
msgbox gText_TooBadBagIsFull, MSGBOX_DEFAULT
release
@ -1103,7 +1108,6 @@ EventScript_VsSeekerChargingDone::
.include "data/text/contest_strings.inc"
.include "data/text/contest_link.inc"
.include "data/text/contest_painting.inc"
.include "data/text/trick_house_mechadolls.inc"
.include "data/scripts/tv.inc"
.include "data/text/tv.inc"
.include "data/scripts/interview.inc"
@ -1144,6 +1148,5 @@ EventScript_VsSeekerChargingDone::
.include "data/scripts/trainer_hill.inc"
.include "data/scripts/test_signpost.inc"
.include "data/scripts/follower.inc"
.include "data/text/frontier_brain.inc"
.include "data/text/save.inc"
.include "data/text/birch_speech.inc"

View File

@ -111,6 +111,7 @@ MtChimney_EventScript_LavaCookieLady::
msgbox MtChimney_Text_ThankYouDear, MSGBOX_DEFAULT
checkitemspace ITEM_LAVA_COOKIE
call_if_eq VAR_RESULT, TRUE, MtChimney_EventScript_RemoveMoney
.if OW_SHOW_ITEM_DESCRIPTIONS == OW_ITEM_DESCRIPTIONS_OFF
giveitem ITEM_LAVA_COOKIE
goto_if_eq VAR_RESULT, FALSE, MtChimney_EventScript_BagIsFull
hidemoneybox
@ -122,6 +123,19 @@ MtChimney_EventScript_BagIsFull::
hidemoneybox
release
end
.else
hidemoneybox
giveitem ITEM_LAVA_COOKIE
goto_if_eq VAR_RESULT, FALSE, MtChimney_EventScript_BagIsFull
release
end
MtChimney_EventScript_BagIsFull::
msgbox gText_TooBadBagIsFull, MSGBOX_DEFAULT
release
end
.endif @ OW_SHOW_ITEM_DESCRIPTIONS
MtChimney_EventScript_RemoveMoney::
removemoney 200

View File

@ -52,8 +52,13 @@ Route109_SeashoreHouse_EventScript_BuySodaPop::
msgbox Route109_SeashoreHouse_Text_HereYouGo, MSGBOX_DEFAULT
removemoney 300
updatemoneybox
.if OW_SHOW_ITEM_DESCRIPTIONS != OW_ITEM_DESCRIPTIONS_OFF
hidemoneybox
giveitem ITEM_SODA_POP
.else
giveitem ITEM_SODA_POP
hidemoneybox
.endif
release
end

View File

@ -176,6 +176,8 @@ BerryTree_EventScript_PickBerry::
special IncrementDailyPickedBerries
special ObjectEventInteractionRemoveBerryTree
message BerryTree_Text_PickedTheBerry
delay 10
showberrydescription
playfanfare MUS_OBTAIN_BERRY
waitmessage
waitfanfare
@ -183,6 +185,7 @@ BerryTree_EventScript_PickBerry::
message BerryTree_Text_PutAwayBerry
waitmessage
waitbuttonpress
hideitemdescription
release
end

View File

@ -1,4 +1,3 @@
.if DEBUG_OVERWORLD_MENU == TRUE
Debug_MessageEnd:
waitmessage
waitbuttonpress
@ -448,5 +447,3 @@ Debug_EventScript_EWRAMCounters::
Debug_EventScript_EWRAMCounters_Text::
.string "Follower Steps: {STR_VAR_1}.\n"
.string "Fishing Chain: {STR_VAR_2}.$"
.endif

View File

@ -2,6 +2,7 @@
.set AMOUNT, VAR_0x8001
Std_ObtainItem::
copyvar VAR_0x8006, ITEMID
additem ITEMID, AMOUNT
copyvar VAR_0x8007, VAR_RESULT
call EventScript_ObtainItemMessage
@ -58,8 +59,11 @@ EventScript_ObtainedItem::
EventScript_ObtainedItemMessage:
message gText_ObtainedTheItem
EventScript_ContinueObtainedItem:
delay 10
showitemdescription
waitfanfare
msgbox gText_PutItemInPocket, MSGBOX_DEFAULT
hideitemdescription
setvar VAR_RESULT, TRUE
return
@ -103,6 +107,7 @@ Std_FindItem::
lock
faceplayer
waitse
copyvar VAR_0x8006, ITEMID
copyvar VAR_0x8004, ITEMID
copyvar VAR_0x8005, AMOUNT
checkitemspace ITEMID, AMOUNT
@ -118,20 +123,25 @@ Std_FindItem::
EventScript_PickUpItem::
removeobject VAR_LAST_TALKED
additem VAR_0x8004, VAR_0x8005
copyvar VAR_0x8006 VAR_0x8004
specialvar VAR_RESULT, BufferTMHMMoveName
copyvar VAR_0x8008, VAR_RESULT
call_if_eq VAR_0x8008, TRUE, EventScript_FoundTMHM
call_if_eq VAR_0x8008, FALSE, EventScript_FoundItem
delay 10
showitemdescription
waitfanfare
waitmessage
bufferitemnameplural STR_VAR_2, VAR_0x8004, VAR_0x8005
pyramid_inchallenge
goto_if_eq VAR_RESULT, TRUE, EventScript_PutBattlePyramidItemInBag
msgbox gText_PutItemInPocket, MSGBOX_DEFAULT
hideitemdescription
return
EventScript_PutBattlePyramidItemInBag::
msgbox gText_PlayerPutItemInBag, MSGBOX_DEFAULT
hideitemdescription
return
EventScript_FoundTMHM::
@ -165,6 +175,7 @@ EventScript_NoRoomToPickUpItem::
EventScript_HiddenItemScript::
lockall
waitse
copyvar VAR_0x8006, VAR_0x8005
additem VAR_0x8005
copyvar VAR_0x8007, VAR_RESULT
bufferitemnameplural STR_VAR_2, VAR_0x8005, 1
@ -194,11 +205,14 @@ EventScript_FoundHiddenItem::
end
EventScript_PutHiddenItemInPocket::
delay 10
showitemdescription
waitmessage
waitfanfare
bufferitemnameplural STR_VAR_2, VAR_0x8004, 1
copyvar VAR_0x8004, VAR_0x8008
msgbox gText_PutItemInPocket, MSGBOX_DEFAULT
hideitemdescription
special TryPutTreasureInvestigatorsOnAir
special SetHiddenItemFlag
releaseall

View File

@ -554,3 +554,4 @@ gSpecials::
def_special Script_GetChosenMonDefensiveEVs
def_special Script_GetChosenMonOffensiveIVs
def_special Script_GetChosenMonDefensiveIVs
def_special UseBlankMessageToCancelPokemonPic

View File

@ -1,108 +0,0 @@
@ Battle Tower
gText_AnabelWonSilver::
.string "It's very disappointing…$"
gText_AnabelDefeatSilver::
.string "Okay, I understand…$"
gText_AnabelWonGold::
.string "I'm terribly sorry…$"
gText_AnabelDefeatGold::
.string "Thank you…$"
@ Battle Dome
gText_TuckerWonSilver::
.string "Ahahaha! Aren't you embarrassed?\n"
.string "Everyone's watching!$"
gText_TuckerDefeatSilver::
.string "Grr…\n"
.string "What the…$"
gText_TuckerWonGold::
.string "My DOME ACE title isn't just for show!$"
gText_TuckerDefeatGold::
.string "Ahahaha!\n"
.string "You're inspiring!$"
@ Battle Factory
gText_NolandWonSilver::
.string "Way to work!\n"
.string "That was a good lesson, eh?$"
gText_NolandDefeatSilver::
.string "Good job!\n"
.string "You know what you're doing!$"
gText_NolandWonGold::
.string "Hey, hey, hey!\n"
.string "You're finished already?$"
gText_NolandDefeatGold::
.string "What happened here?$"
@ Battle Pike
gText_LucyWonSilver::
.string "Humph…$"
gText_LucyDefeatSilver::
.string "Urk…$"
gText_LucyWonGold::
.string "Hah!$"
gText_LucyDefeatGold::
.string "Darn!$"
@ Battle Arena
gText_GretaWonSilver::
.string "Oh, come on!\n"
.string "You have to try harder than that!$"
gText_GretaDefeatSilver::
.string "No way!\n"
.string "Good job!$"
gText_GretaWonGold::
.string "Heheh!\n"
.string "What did you expect?$"
gText_GretaDefeatGold::
.string "Huh?\n"
.string "Are you serious?!$"
@ Battle Palace
gText_SpenserWonSilver::
.string "Your POKéMON are wimpy because\n"
.string "you're wimpy as a TRAINER!$"
gText_SpenserDefeatSilver::
.string "Ah…\n"
.string "Now this is something else…$"
gText_SpenserWonGold::
.string "Gwahahaha!\n"
.string "My brethren, we have nothing to fear!$"
gText_SpenserDefeatGold::
.string "Gwah!\n"
.string "Hahahaha!$"
@ Battle Pyramid
gText_BrandonWonSilver::
.string "Hey! What's wrong with you!\n"
.string "Let's see some effort! Get up!$"
gText_BrandonDefeatSilver::
.string "That's it! You've done great!\n"
.string "You've worked hard for this!$"
gText_BrandonWonGold::
.string "Hey! Don't you give up now!\n"
.string "Get up! Don't lose faith in yourself!$"
gText_BrandonDefeatGold::
.string "That's it! You've done it!\n"
.string "You kept working for this!$"

View File

@ -1,134 +0,0 @@
gTrickHouse_Mechadoll_Oddish::
.string "ODDISH$"
gTrickHouse_Mechadoll_Poochyena::
.string "POOCHYENA$"
gTrickHouse_Mechadoll_Taillow::
.string "TAILLOW$"
gTrickHouse_Mechadoll_Azurill::
.string "AZURILL$"
gTrickHouse_Mechadoll_Lotad::
.string "LOTAD$"
gTrickHouse_Mechadoll_Wingull::
.string "WINGULL$"
gTrickHouse_Mechadoll_Dustox::
.string "DUSTOX$"
gTrickHouse_Mechadoll_Zubat::
.string "ZUBAT$"
gTrickHouse_Mechadoll_Nincada::
.string "NINCADA$"
gTrickHouse_Mechadoll_Ralts::
.string "RALTS$"
gTrickHouse_Mechadoll_Zigzagoon::
.string "ZIGZAGOON$"
gTrickHouse_Mechadoll_Slakoth::
.string "SLAKOTH$"
gTrickHouse_Mechadoll_Poochyena2::
.string "POOCHYENA$"
gTrickHouse_Mechadoll_Shroomish::
.string "SHROOMISH$"
gTrickHouse_Mechadoll_Zigzagoon2::
.string "ZIGZAGOON$"
gTrickHouse_Mechadoll_Poochyena3::
.string "POOCHYENA$"
gTrickHouse_Mechadoll_Zubat2::
.string "ZUBAT$"
gTrickHouse_Mechadoll_Carvanha::
.string "CARVANHA$"
gTrickHouse_Mechadoll_BurnHeal::
.string "BURN HEAL$"
gTrickHouse_Mechadoll_HarborMail::
.string "HARBOR MAIL$"
gTrickHouse_Mechadoll_SamePrice::
.string "Same price$"
gTrickHouse_Mechadoll_60Yen::
.string "¥60$"
gTrickHouse_Mechadoll_55Yen::
.string "¥55$"
gTrickHouse_Mechadoll_Nothing::
.string "Nothing$"
gTrickHouse_Mechadoll_CostMore::
.string "They will cost more.$"
gTrickHouse_Mechadoll_CostLess::
.string "They will cost less.$"
gTrickHouse_Mechadoll_SamePrice2::
.string "Same price$"
gTrickHouse_Mechadoll_Male::
.string "Male$"
gTrickHouse_Mechadoll_Female::
.string "Female$"
gTrickHouse_Mechadoll_Neither::
.string "Neither$"
gTrickHouse_Mechadoll_ElderlyMen::
.string "Elderly men$"
gTrickHouse_Mechadoll_ElderlyLadies::
.string "Elderly ladies$"
gTrickHouse_Mechadoll_SameNumber::
.string "Same number$"
gTrickHouse_Mechadoll_None::
.string "None$"
gTrickHouse_Mechadoll_One::
.string "1$"
gTrickHouse_Mechadoll_Two::
.string "2$"
gTrickHouse_Mechadoll_Two2::
.string "2$"
gTrickHouse_Mechadoll_Three::
.string "3$"
gTrickHouse_Mechadoll_Four::
.string "4$"
gTrickHouse_Mechadoll_Six::
.string "6$"
gTrickHouse_Mechadoll_Seven::
.string "7$"
gTrickHouse_Mechadoll_Eight::
.string "8$"
gTrickHouse_Mechadoll_Six2::
.string "6$"
gTrickHouse_Mechadoll_Seven2::
.string "7$"
gTrickHouse_Mechadoll_Eight2::
.string "8$"

View File

@ -59,6 +59,6 @@ def rellocate_follower_graphics():
#os.popen('cp followers/' + name + '.png followers/' + name + '/follower.png')
#os.remove('followers/' + name + '.png')
#print(pth)
#subprocess.run(["tools/gbagfx/gbagfx " + name +".png " + name + "_normal.pal'" + str(count) + "'"])
#subprocess.run(["tools/gbagfx/gbagfx " + name +".png " + name + "_normal.pal'" + str(count) + "'"])
rellocate_follower_graphics()

View File

@ -3,7 +3,20 @@
- [README](./README.md)
- [Installation](./INSTALL.md)
- [Setting up WSL1 (Legacy Portion)](./legacy_WSL1_INSTALL.md)
- [Run documentation site locally](local_mdbook/index.md)
- [Ubuntu WSL1/WSL2](local_mdbook/ubuntu_WSL.md)
- [AI Flags](./ai_flags.md)
- [Tutorials]()
- [How to add new AI Flags](./ai_logic.md)
- [How to add new battle script commands/macros](./how_to_battle_script_command_macro.md)
- [How to add a new move](./how_to_new_move.md)
- [How to add a new trainer class](./how_to_trainer_class.md)
- [How to add a new Pokémon]()
- [v1.9.x](./how_to_new_pokemon_1_9_0.md)
- [v1.8.x](./how_to_new_pokemon_1_8_0.md)
- [v1.7.x](./how_to_new_pokemon_1_7_0.md)
- [v1.6.x](./how_to_new_pokemon_1_6_0.md)
- [How to use the Testing System](./how_to_testing_system.md)
- [Changelog](./CHANGELOG.md)
- [1.9.x]()
- [Version 1.9.0](changelogs/1.9.x/1.9.0.md)

View File

@ -21,14 +21,24 @@ AI: Check Bad Move / Try to Faint / Check Viability. The name of each flag is ju
* Sequence Switching
## `COMPETITIVE_PARTY_SYNTAX != TRUE` / Not Found
If you are not using competitive syntax parties, instead access the trainer data directly in [`src/data/trainers.h`](https://github.com/rh-hideout/pokeemerald-expansion/blob/master/src/data/trainers.h), and add flags like so, typed exactly the same as the flag names themselves:
If you are not using competitive syntax parties, instead access the trainer data directly in [`src/data/trainers.h`](https://github.com/rh-hideout/pokeemerald-expansion/blob/master/src/data/trainers.h), and add flags like so, typed exactly the same as the flag names themselves:
`.aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY`
# What AI Flags does pokeemerald-expansion have?
This section lists all of expansions AI Flags and briefly describes the effect they have on the AIs behaviour. In all cases, please check the corresponding function or surrounding code around their implementation for more details. Some of these functions are vanilla, some share a name with vanilla but have been modified to varying degrees, and some are completely new.
## Composite AI Flags
Expansion has two "composite" AI flags, `AI_FLAG_BASIC_TRAINER` and `AI_FLAG_SMART_TRAINER`. This means that these flags have no unique functionality themselves, and can instead be thought of as groups of other flags that are all enabled when this flag is enabled. The idea behind these flags is that if you don't care to manage the detailed behaviour of a particular trainer, you can use these as a baseline instead, and expansion will keep them updated for you.
`AI_FLAG_BASIC_TRAINER` is expansion's version of generic, normal AI behaviour. It includes `AI_FLAG_CHECK_BAD_MOVE` (don't use bad moves), `AI_FLAG_TRY_TO_FAINT` (faint the player where possible), and `AI_FLAG_CHECK_VIABILITY` (choose the most effective move to use in the current context). Trainers with this flag will still be smarter than they are in vanilla as there have been dramatic improvements made to move selection, but not incredibly so. Trainers with this flag should feel like normal trainers. In general we recommend these three flags be used in all cases, unless you specifically want a trainer who makes obvious mistakes in battle.
`AI_FLAG_SMART_TRAINER` is expansion's version of a "smart AI". It includes everything in `AI_FLAG_BASIC_TRAINER` along with `AI_FLAG_SMART_SWITCHING` (make smart decisions about when to switch), `AI_FLAG_SMART_MON_CHOICES` (make smart decisions about what mon to send in after a switch / KO), and `AI_FLAG_OMNISCIENT` (awareness of what moves, items, and abilities the player's mons have to better inform decisions). Expansion will keep this updated to represent the most objectively intelligent behaviour our flags are capable of producing.
Expansion has LOADS of flags, which will be covered in the rest of this guide. If you don't want to engage with detailed trainer AI tuning though, you can just use these two composite flags, and trust that expansion will keep their contents updated to always represent the most standard and the smartest behaviour we can.
## `AI_FLAG_CHECK_BAD_MOVE`
The AI will avoid using moves that are likely to fail in the current situation. This flag helps prevent the AI from making ineffective choices, such as using moves into immunities, into invulnerable states, or when the moves are otherwise hindered by abilities, terrain, or status conditions.
The AI will avoid using moves that are likely to fail in the current situation. This flag helps prevent the AI from making ineffective choices, such as using moves into immunities, into invulnerable states, or when the moves are otherwise hindered by abilities, terrain, or status conditions.
## `AI_FLAG_TRY_TO_FAINT`
AI will prioritize KOing the player if able rather than using status moves. Will prioritize using a move that can OHKO the player. If the player can KO the AIs mon and the AIs mon is slower, prioritize priority moves (this does not prevent the AI from switching out instead).
@ -42,8 +52,8 @@ This flag is divided into two components to calculate the best available move fo
This is different to `AI_FLAG_CHECK_BAD_MOVE` as it calculates how poor a move is and not whether it will fail or not.
## `AI_FLAG_SETUP_FIRST_TURN`
AI will prioritize using setup moves on the first turn. These include stat buffs, field effects, status moves, etc.
## `AI_FLAG_FORCE_SETUP_FIRST_TURN`
AI will prioritize using setup moves on the first turn at the expense of all else. These include stat buffs, field effects, status moves, etc. AI_FLAG_CHECK_VIABILITY will instead do this when the AI determines it makes sense.
This is just a flat increase without any consideration of whether it makes sense to use the move or not. For better move choice quality for those moves, `AI_FLAG_CHECK_VIABILITY` should be used.
@ -58,12 +68,12 @@ AI will generally behave more recklessly. This AI enables the following behaviou
* Prioritize Explosion moves
## `AI_FLAG_PREFER_STRONGEST_MOVE`
Adds score bonus to any move the AI has that either OHKOs or 2HKOs the player.
Adds score bonus to any move the AI has that either OHKOs or 2HKOs the player.
Keep in mind that this is a weaker form of `AI_FLAG_TRY_TO_FAINT` at scoring OHKOs as it does not take into account who is attacking first, it does however handle 2HKOs.
## `AI_FLAG_PREFER_BATON_PASS`
AI prefers raising its own stats if it has >= 60% HP, as well as Ingrain, Aqua Ring, and Protect. Prioritizes Baton Bass if the mon is rooted (Ingrain) or has the Aqua Ring effect, and doesnt if it has been Leech Seeded.
AI prefers raising its own stats if it has >= 60% HP, as well as Ingrain, Aqua Ring, and Protect. Prioritizes Baton Bass if the mon is rooted (Ingrain) or has the Aqua Ring effect, and doesnt if it has been Leech Seeded.
## `AI_FLAG_DOUBLE_BATTLE`
This flag is automatically set in double battles, and controls much of the doubles-specific scoring. Ill summarize some of its scoring as follows:
@ -83,7 +93,7 @@ With respect to the AIs mons, in doubles:
In both singles and doubles:
* Prioritizes not using moves that require the user fainting (Destiny Bond, Explosion etc.) and healing moves while on >= 70% HP.
* Prioritize not using moves that require the user fainting or losing significant HP (Belly Drum etc) while between 30% and 70% HP
* Prioritize not using setup moves (Light Screen etc.) and Bide while on <= 30% HP
* Prioritize not using setup moves (Light Screen etc.) and Bide while on <= 30% HP
With respect to the players mons:
* Prioritize not using many status moves (stat buffs, Poison, Pain Split) if the player has between 30% and 70% HP
@ -96,7 +106,7 @@ AI prioritizes setting up field effects (Trick Room, Rain Dance, etc.) and side
AI does not understand ability suppression (Mold Breaker etc., weather suppression (Air Lock etc.), redirection abilities (Lightningrod etc.) being temporarily removed due to move effects (Sky Drop etc.), or item suppression (Magic Room etc.) and will ignore them. This is a handicap flag.
## `AI_FLAG_WILL_SUICIDE`
AI prioritizes self destruction moves (Explosion, Memento).
AI prioritizes self destruction moves (Explosion, Memento).
## `AI_FLAG_PREFER_STATUS_MOVES`
AI gets a score bonus for status moves. This should be combined with `AI_FLAG_CHECK_BAD_MOVE` to prevent using only status moves.
@ -127,7 +137,7 @@ Affects when the AI chooses to switch. AI will make smarter decisions about when
Marks the last Pokemon in the party as the Ace Pokemon. It will not be used unless it is the last one remaining, or is forced to be switched in (Roar, U-Turn with 1 mon remaining, etc.)
## `AI_FLAG_OMNISCIENT`
AI has full knowledge of player moves, abilities, and hold items, and can use this knowledge when making decisions.
AI has full knowledge of player moves, abilities, and hold items, and can use this knowledge when making decisions.
## `AI_FLAG_SMART_MON_CHOICES`
Affects what the AI chooses to send out after a switch. AI will make smarter decisions when choosing which mon to send out mid-battle and after a KO, which are handled separately. Automatically included when `AI_FLAG_SMART_SWITCHING` is enabled.
@ -148,7 +158,7 @@ And will choose mons after a mid-battle switch prioritizing the following criter
* Has Baton Pass
## `AI_FLAG_CONSERVATIVE`
AI always assumes it will roll the lowest possible result when comparing damage in scoring.
AI always assumes it will roll the lowest possible result when comparing damage in scoring.
## `AI_FLAG_SEQUENCE_SWITCHING`
AI will always switch out after a KO in exactly party order as defined in the trainer data (ie. slot 1, then 2, then 3, etc.). The AI will never switch out mid-battle unless forced to (Roar etc.). If the AI uses a move that requires a switch where it makes a decision about what to send in (U-Turn etc.), it will always switch out into the lowest available party index.

31
docs/ai_logic.md Normal file
View File

@ -0,0 +1,31 @@
# How to add new AI Flags
The battle engine upgrade has rewritten the AI battle scripts to C functions to easily add new logic. This tutorial explains how to add a new AI logic flag.
## 1. Define your flag
Open `include/constants/battle_ai.h`. We have many unused flags, but you can add a new one after `AI_FLAG_SMART_SWITCHING` like so:
`#define AI_FLAG_SUPPORT (1 << 16)`
## 2. Make your new function
Open `src/battle_ai_main.c`. Search for the array `static s16 (*const sBattleAiFuncTable[])(u8, u8, u16, s16)`. We want to add our new function to this table. Since we have defined our flag as `(1 << 16)`, find the 16th entry in the table (identifiable by the initializer, `[16]`), and replace it with:
`[16] = AI_Support, // AI_FLAG_SUPPORT`
Define your function above the table as `static s16 AI_Support(u8 battlerAtk, u8 battlerDef, u16 move, s16 score);`
## Make your function do something
at the bottom of the file, add:
```c
static s16 AI_Support(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
{
// Add your logic here!
}
```
## Give your trainer the correct AI flag!
And that's it!

View File

@ -92,5 +92,5 @@
* Court Change by @DizzyEggg in https://github.com/rh-hideout/pokeemerald-expansion/pull/3160
* Item Effects
* Utility Umbrella, by @AsparagusEduardo in https://github.com/rh-hideout/pokeemerald-expansion/pull/2835
**Full Changelog**: https://github.com/rh-hideout/pokeemerald-expansion/compare/expansion/1.5.1...expansion/1.5.2

View File

@ -9,8 +9,8 @@
## CRITICAL FIX, please update to avoid the issues detailed down below:
- Fixed memory corruption when handling trigger sprites by @SBird1337 in https://github.com/rh-hideout/pokeemerald-expansion/pull/3238
- This had the posibility of manifesting in weird ways, like camera and music changes, NPC duplication and more. If you've had this issue in the past, we ***heavily*** recommend you update to this version of the expansion.
- Thank you @Bassoonian for helping us pinpointing the issue.
- Thank you @Bassoonian for helping us pinpointing the issue.
![image](https://github.com/rh-hideout/pokeemerald-expansion/assets/2904965/26b9b984-c5db-4dac-85f7-5fc4e95a32ce) ![image](https://github.com/rh-hideout/pokeemerald-expansion/assets/2904965/d490eb30-ce54-4b90-bb2e-79c2e9bb50ac)

View File

@ -41,7 +41,7 @@
* Clodsire
* Crocalor
* Dolliv
* Dudunsparce
* Dudunsparce
* Esparthra
### Fixed
* Multiple Pokémon graphical fixes by @katykat5099 in https://github.com/rh-hideout/pokeemerald-expansion/pull/3805

View File

@ -0,0 +1,140 @@
# Version 1.9.1
```md
## How to update
- If you haven't set up a remote, run the command `git remote add RHH https://github.com/rh-hideout/pokeemerald-expansion`.
- Once you have your remote set up, run the command `git pull RHH expansion/1.9.1`.
```
## 🌋 *REFACTORS* 🌋
* Removed `ENDTURN_RETALIATE` in [#5182](https://github.com/rh-hideout/pokeemerald-expansion/pull/5182)
* Removed `ENDTURN_WEATHER_FORM` and `allowedToChangeFormInWeather` in [#5171](https://github.com/rh-hideout/pokeemerald-expansion/pull/5171)
## 🧬 General 🧬
### Added
* Move Relearner UI now displays move category by @kittenchilly in [#5081](https://github.com/rh-hideout/pokeemerald-expansion/pull/5081)
### Fixed
* Fixes wrong padding field in `SpeciesInfo` struct by @AlexOn1ine in [#5139](https://github.com/rh-hideout/pokeemerald-expansion/pull/5139)
* Fixed specific tiles changing to PC tiles when using Box Link/Debug PC option by @cawtds in [#5141](https://github.com/rh-hideout/pokeemerald-expansion/pull/5141)
## 🐉 Pokémon 🐉
### Fixed
* Fixed stray transparent pixels in Urshifu sprites by @hedara90 in [#5071](https://github.com/rh-hideout/pokeemerald-expansion/pull/5071)
* Fixed `bufferspeciesname` not working for species IDs over 1023 by @SBird1337 in [#5088](https://github.com/rh-hideout/pokeemerald-expansion/pull/5088)
* Fixed overworld Pokémon breaking for species IDs above 1535 by @hedara90, @mrgriffin and
@SarnPoke in [#5179](https://github.com/rh-hideout/pokeemerald-expansion/pull/5179)
* Fixed overworld palettes for multiple species by @hedara90 in [#5107](https://github.com/rh-hideout/pokeemerald-expansion/pull/5107)
* Dialga Origin (Normal and Shiny)
* Palkia Origin (Normal and Shiny)
* Giratina Origin (shiny palette fixed by @hedara90 in [#5108](https://github.com/rh-hideout/pokeemerald-expansion/pull/5108))
* Xerneas Neutral/Active (Normal and Shiny)
* Enamorus Incarnate/Therian (Normal and Shiny)
* Fixed/added missing Pokémon sprites and palettes by @Cafeei in [#5126](https://github.com/rh-hideout/pokeemerald-expansion/pull/5126)
* Overworld:
* Shiny Sneasler, Morelul, Bounsweet, Bruxish, Guzzlord, Regieleki, Zacian, Zamazenta
* Hisuian Zorua sprite
* Shiny Summer Sawsbuck
* Shiny Galarian Yamask, Darumaka, Zigzagoon, Zapdos, Ponyta, Rapidash, Slowpoke, Farfetch'd, Weezing, Mr. Mime, Articuno, Moltres, Slowking, Stunfisk, Darmanitan
* Shiny Hisuian Sneasel, Qwilfish, Samurott,
* Battle sprites:
* Shiny Sneasler, Cursola, Pincurchin, Runerigus
* Shiny Galarian Yamask, Darumaka
* Fixed Unown Overworld follower sprites by Sarn by @hedara90 in [#5146](https://github.com/rh-hideout/pokeemerald-expansion/pull/5146)
## ⚔️ Battle General ⚔️
### Changed
* Set new animation particles by default to off by @AlexOn1ine in [#5161](https://github.com/rh-hideout/pokeemerald-expansion/pull/5161)
### Fixed
* Fixed speed ties by @mrgriffin in [#4780](https://github.com/rh-hideout/pokeemerald-expansion/pull/4780)
* Cleanup by @hedara90 in [#5092](https://github.com/rh-hideout/pokeemerald-expansion/pull/5092)
* Fixed Defiant/Competitive not working after the battler enters the field with a Court Changed Sticky Web on its side of the field by @PhallenTree in [#5093](https://github.com/rh-hideout/pokeemerald-expansion/pull/5093)
* Fixed `trainerproc` not properly parsing line markers, which caused erroring lines to be offset by @mrgriffin in [#5122](https://github.com/rh-hideout/pokeemerald-expansion/pull/5122)
* Fixed initial Zigzagoon battle being able to use a Gimmick by @AlexOn1ine in [#5129](https://github.com/rh-hideout/pokeemerald-expansion/pull/5129)
* Fixed incorrect rounding when `maxHP` is lower than 16 by @hedara90 in [#5183](https://github.com/rh-hideout/pokeemerald-expansion/pull/5183)
* This caused these Pokémon to not be hurt by Sandstorm/Hail.
* Fixes UB in `Cmd_averagestats` by @mrgriffin and @AlexOn1ine in [#5191](https://github.com/rh-hideout/pokeemerald-expansion/pull/5191)
## 🤹 Moves 🤹
### Added
* Added move animations for multiple moves by @TheTrueSadfish in [#5159](https://github.com/rh-hideout/pokeemerald-expansion/pull/5159)
* Spin Out, Mortal Spin, Fillet Away, Flower Trick, Make It Rain, Shed Tail, Hyper Drill, Twin Beam, Comeuppance, Blood Moon, Fickle Beam, Thunder Clap, Hard Press, Dragon Cheer, Malignant Chain.
* Purple chains by ogwon on Discord, beam by @TheTrueSadfish and livra on Discord.
### Changed
* Adjusted Raging Bull's animation to include Brick Break's wall break effect by @TheTrueSadfish in [#5159](https://github.com/rh-hideout/pokeemerald-expansion/pull/5159)
### Fixed
* Fixed non-grass Ivy Cudgel breaking battle UI by @hedara90 in [#5117](https://github.com/rh-hideout/pokeemerald-expansion/pull/5117)
* Fixes Stomping Tantrum effect not doubling power in certain situations by @AlexOn1ine in [#5140](https://github.com/rh-hideout/pokeemerald-expansion/pull/5140)
* Fixed Fickle Beam's description by @PhallenTree in [#5093](https://github.com/rh-hideout/pokeemerald-expansion/pull/5093)
* Fixed Revelation Dance interactions with Z-Move, Roost and typeless mons by @PhallenTree in [#5133](https://github.com/rh-hideout/pokeemerald-expansion/pull/5133)
* Fixes Poltergeist missing its accuracy check by @AlexOn1ine in [#5168](https://github.com/rh-hideout/pokeemerald-expansion/pull/5168)
* Fixed Fickle Beam not showing its message by @TheTrueSadfish in [#5159](https://github.com/rh-hideout/pokeemerald-expansion/pull/5159)
* Fixed Retaliate not working correctly if the party member fainted via passive damage during end of turn by @hedara90 in [#5182](https://github.com/rh-hideout/pokeemerald-expansion/pull/5182)
* Fixed Flame Burst's passive damage being based off current HP rather than Max HP by @hedara90 in [#5182](https://github.com/rh-hideout/pokeemerald-expansion/pull/5182)
* Fixed using Population Bomb with Loaded Dice printing garbage text by @kittenchilly in [#5195](https://github.com/rh-hideout/pokeemerald-expansion/pull/5195)
## 🎭 Abilities 🎭
### Added
* Added in-battle effect of Pickup by @PhallenTree in [#5170](https://github.com/rh-hideout/pokeemerald-expansion/pull/5170)
### Fixed
* Fixes Purifying Salt not halving damage for dynamic move types by @AlexOn1ine in [#5145](https://github.com/rh-hideout/pokeemerald-expansion/pull/5145)
* Fixed Dancer-called moves not changing their type based on the new user by @PhallenTree in [#5133](https://github.com/rh-hideout/pokeemerald-expansion/pull/5133)
* Fixed Ice Face not regenerating after switching in during Hail/Snow by @hedara90 in [#5171](https://github.com/rh-hideout/pokeemerald-expansion/pull/5171)
* Fixed Wind Rider not activating when switched in while Tailwind is active on the user's side of the field activation and tests by @PhallenTree in https://github.com/rh-hideout/pokeemerald-expansion/pull/5207
## 🧶 Items 🧶
### Added
* Added Dowsing Machine's expanded name by @kittenchilly in [#5134](https://github.com/rh-hideout/pokeemerald-expansion/pull/5134)
### Fixed
* Fixes Booster Energy not increasing speed by @AlexOn1ine in [#5167](https://github.com/rh-hideout/pokeemerald-expansion/pull/5167)
## 🤖 Battle AI 🤖
### Changed
* Adjusted AI calculation for Triple Kick Effect by @AlexOn1ine in [#5127](https://github.com/rh-hideout/pokeemerald-expansion/pull/5127)
### Fixed
* Fix Switch AI Bug: AI never switching out when it could be OHKO'd by @Pawkkie in [#5089](https://github.com/rh-hideout/pokeemerald-expansion/pull/5089)
* Adds missing AI checks for poltergeist by @AlexOn1ine in [#5189](https://github.com/rh-hideout/pokeemerald-expansion/pull/5189)
## 🧹 Other Cleanup 🧹
* `IsValidForBattle` function formatting by @AlexOn1ine in [#5085](https://github.com/rh-hideout/pokeemerald-expansion/pull/5085)
* Opportunist/Mirror Herb cleanup by @AlexOn1ine in [#5120](https://github.com/rh-hideout/pokeemerald-expansion/pull/5120)
* Cleanup by @AlexOn1ine in [#5158](https://github.com/rh-hideout/pokeemerald-expansion/pull/5158)
* Remove trailing whitespace (master) by @AsparagusEduardo in [#5174](https://github.com/rh-hideout/pokeemerald-expansion/pull/5174)
## 🧪 Test Runner 🧪
### Added
* Added missing Move Effect TODO tests - Volume C by @AsparagusEduardo in [#5094](https://github.com/rh-hideout/pokeemerald-expansion/pull/5094)
* Added multiple missing ability TODO tests by @AsparagusEduardo in [#5163](https://github.com/rh-hideout/pokeemerald-expansion/pull/5163)
* Added missing Guard/Power split tests by @mrgriffin and @AlexOn1ine in [#5191](https://github.com/rh-hideout/pokeemerald-expansion/pull/5191)
* Added missing Harvest and Pickup tests by @PhallenTree in [#5170](https://github.com/rh-hideout/pokeemerald-expansion/pull/5170)
* Added missing Round tests by @hedara90 in https://github.com/rh-hideout/pokeemerald-expansion/pull/5196
* Added missing Wind Rider tests by @PhallenTree in https://github.com/rh-hideout/pokeemerald-expansion/pull/5207
### Changed
* Fixed G-Max Replenish not considering Gen 5+ Pickup by @PhallenTree in [#5170](https://github.com/rh-hideout/pokeemerald-expansion/pull/5170)
### Fixed
* Fixed `RandomUniformExcept` not being exclusive on the higher boundary by @PhallenTree in [#5170](https://github.com/rh-hideout/pokeemerald-expansion/pull/5170)
## 📚 Documentation 📚
* Added guide to running documentation website locally by @AsparagusEduardo in [#5059](https://github.com/rh-hideout/pokeemerald-expansion/pull/5059)
* How to docs and fixes to be added to the mdbook documentation site by @anrichtait in [#5070](https://github.com/rh-hideout/pokeemerald-expansion/pull/5070)
* Improved 1.8 ⇒ 1.9 non-Competitive syntax migration instructions by @mrgriffin in [#5079](https://github.com/rh-hideout/pokeemerald-expansion/pull/5079)
## 📦 Branch Synchronisation 📦
### pret
* 5th of August in [#5098](https://github.com/rh-hideout/pokeemerald-expansion/pull/5098)
* Fixed bottom half of Mt. Pyre not being labeled in PokeNav by @fdeblasio in [pret#2018](https://github.com/pret/pokeemerald/pull/2018)
* 7th of August in [#5116](https://github.com/rh-hideout/pokeemerald-expansion/pull/5116)
* Changed type1 and type2 to be consistent by @pkmnsnfrn in [pret#2021](https://github.com/pret/pokeemerald/pull/2021)
* 14th of August in [#5165](https://github.com/rh-hideout/pokeemerald-expansion/pull/5165)
* Fix type for offset in MapConnection by @GriffinRichards in [pret#2011](https://github.com/pret/pokeemerald/pull/2011)
### Followers
* 7th of August in [#5110](https://github.com/rh-hideout/pokeemerald-expansion/pull/5110)
* Fixed expanded OW IDs by @pkmnsnfrn in [aarant#38](https://github.com/aarant/pokeemerald/pull/38)
* Fix two small text errors in follower dialogue by @Bassoonian in [aarant#39](https://github.com/aarant/pokeemerald/pull/39)
**Full Changelog**: https://github.com/rh-hideout/pokeemerald-expansion/compare/expansion/1.9.0...expansion/1.9.1
## New Contributors
* @TheTrueSadfish made their first contribution in https://github.com/rh-hideout/pokeemerald-expansion/pull/5159
<!--Last PR: 5196-->

View File

@ -122,7 +122,10 @@
### Fixed
* N/A
## 📦 Pret merges 📦
## 📦 Branch Synchronisation 📦
### pret's base pokeemerald
* N/A
### merrp/aarant's followers
* N/A

View File

@ -0,0 +1,51 @@
## How to add new Battle Script Commands/Macros
To preface this tutorial, the battle engine upgrade has exhausted all battle script command IDs, and instead uses the `various` command to effectively add new commands. This is preferential to creating a secondary battle script command table like is done in the CFRU.
In general, `gBattlescriptCurrInstr` tracks the current battle script position as a ROM address. Fortunately, we don't need to worry about ROM addresses when using the decomps, but it is important to understand because of how the `various` command is set up.
```
.macro various battler:req, param1:req
.byte 0x76
.byte \battler
.byte \param1
.endm
```
`various` is 3 bytes in size, so if we wanted to advance to the next battle script command, we would write `gBattlescriptCurrInstr += 3`. Coincidentally, this is found at the end of `Cmd_Various` in `src/battle_script_commands.c`.
Now, how might we add a custom various command case? Here are the steps. We will use `VARIOUS_SET_SIMPLE_BEAM` as an example.
### 1. Add a definition to `include/constants/battle_script_commands.h`.
For example, `#define VARIOUS_SET_SIMPLE_BEAM 39`
### 2. Create a macro in `asm/macros/battle_script.inc`. For example:
```c
.macro setabilitysimple battler:req, ptr:req
various \battler VARIOUS_SET_SIMPLE_BEAM
.4byte \ptr
.endm
```
### 3. Add your new various command ID to `Cmd_Various`. For example:
```c
case VARIOUS_SET_SIMPLE_BEAM:
if (IsEntrainmentTargetOrSimpleBeamBannedAbility(gBattleMons[gBattlerTarget].ability)
|| gBattleMons[gBattlerTarget].ability == ABILITY_SIMPLE)
{
gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 3);
}
else
{
gBattleMons[gBattlerTarget].ability = ABILITY_SIMPLE;
RecordAbilityBattle(gActiveBattler, ABILITY_SIMPLE);
gBattlescriptCurrInstr += 7;
}
return;
```
The macros' `battler` argument is the battler who will be affected/considered by your command. In our case, which battler we will try to give `ABILITY_SIMPLE`. Note that `gActiveBattler` is always set to this battler at the beginning of `Cmd_Various`.
The `ptr` argument is an extra argument that, in this case, provides a battle script to jump to in the event that we fail to set `ABILITY_SIMPLE`. We must add the `.4byte \ptr` inside our macro. So now when we want to advance to the next battle script command in our script, we must increment `gBattlescriptCurrInstr` by `7` because our overall macro is 3 bytes for the various command, and 4 bytes for the pointer. *IMPORTANT* the `return` at the end of the switch case is required because remember that `various` always defaults to `gBattlescriptCurrInstr += 3` at the very end of the function, so if we included `gBattlescriptCurrInstr += 7` with a `break`, we would end up effectively doing `gBattlescriptCurrInstr += 10`.
This behavior can be found under the `else` statement in the example above, corresponding to `ABILITY_SIMPLE` being correctly applied. If we are unable to set `ABILITY_SIMPLE`, however, notice the following `gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 3);`. This means we are jumping to the battle script provided by the pointer 3 bytes after our various command (which is the `ptr` argument described previously). We still must `return` or else we would actually jump to 3 bytes after the `ptr` battle script begins.

197
docs/how_to_new_move.md Normal file
View File

@ -0,0 +1,197 @@
*Full credits and thank you to CancerFairy for writing this guide!*
### Note: This guide was written for version 1.8.0. Most stuff still applies to 1.7.x versions and earlier, with the following exceptions:
- Battle and Contest move data are separated in `src/data/battle_moves.h` and `src/data/contest_moves.h`
- `additionalEffects` doesn't exist, instead being handled by a combination of `secondaryEffectChance` and unique `EFFECT_xxx`s.
- There's no `include/constants/battle_move_effects.h`, so data specific to certain effects is handled in other places.
- Move names are handled in `gMoveNames`.
# Adding/editing moves
This guide is here to give you a breakdown of how moves work, how to edit existing ones, and how to add your own.
## Contents:
1. [Key files and definitions](#key-files-and-definitions)
- [Header files](#header-files)
- [C files](#c-files)
- [Script files](#script-files)
2. [Editing a move](#editing-a-move)
3. [Adding a new move](#adding-a-new-move)
## Key files and definitions
Before beginning the process, it's important to familiarise yourself with the important files that control moves. There are three categories of files - header(.h) files, which contain static information about a move, .c files which contains functions in C that determine how the move behaves, and script files (.s or .inc) that actually "run" the move - i.e. determine the sequence of events you see on screen when you execute the move.
## Header files
### src/data/moves_info.h
This is the place where the bulk of move information is stored, including name, base power, typing, PP, contest information etc.
Let's look at an example:
```c
[MOVE_THUNDER_SHOCK] =
{
.name = HANDLE_EXPANDED_MOVE_NAME("ThunderShock", "Thunder Shock"),
.description = COMPOUND_STRING(
"An electrical attack that\n"
"may paralyze the foe."),
.effect = EFFECT_HIT,
.power = 40,
.type = TYPE_ELECTRIC,
.accuracy = 100,
.pp = 30,
.target = MOVE_TARGET_SELECTED,
.priority = 0,
.category = DAMAGE_CATEGORY_SPECIAL,
.sheerForceBoost = TRUE,
.additionalEffects = ADDITIONAL_EFFECTS({
.moveEffect = MOVE_EFFECT_PARALYSIS,
.chance = 10,
}),
.contestEffect = CONTEST_EFFECT_HIGHLY_APPEALING,
.contestCategory = CONTEST_CATEGORY_COOL,
.contestComboStarterId = 0,
.contestComboMoves = {COMBO_STARTER_CHARGE},
},
```
The `HANDLE_EXPANDED_MOVE_NAME` allows the usage of a name of extended character length, so long as the `B_EXPANDED_MOVE_NAMES` is set to `TRUE`, whereas by default it's limited in Gen 3 to 12 characters. Most of the fields here are obvious, but the two important ones for determining what a move actually *does* are `effect` and `additionalEffects`.
The `effect` represents how the move actually works when called in battle - it can be a two turn move, or a move that only works if the target is holding an item, for example. How each effect works is pretty much unique, but the way a move of a particular effect is executed is defined by a script [`data/battle_scripts_1.s`](#databattle_scripts_1s), and any *variable* characteristics such as typing or power are defined in either [`src/battle_script_commands.c`](#srcbattle_script_commandsc) or [`src/battle_util.c`](#srcbattle_utilc), depending on the effect. The vast majority of non-status moves are simply `EFFECT_HIT`, in that they deal damage and apply `additionalEffects` (if defined).
The `additionalEffects` field represents effects that are applied at the `setadditionaleffects` stage of the move script (for most moves, see `BattleScript_Hit_RetFromAtkAnimation`). These are effects that can be encapsulated by any of the `MOVE_EFFECT_X` defined in [`include/constants/battle.h`](#includeconstantsbattleh) and encoded under `SetMoveEffect` in [`src/battle_script_commands.c`](#srcbattle_script_commandsc). These can vary from applying a status, such as `MOVE_EFFECT_PARALYSIS`, or lowering/raising stats etc. The move effect could target the user by setting `self = TRUE`, such as Overheat lowering the user's own Sp. Atk. What's more, definining a `chance`, such as for Thunder Shock, not only limits the effect to applying only `chance`% of the time, but it also turns it into a *secondary effect.* This difference is important because secondary effects are nullified by Sheer Force (which in turn will boost the move's power) and they are blocked by Shield Dust. These two limitations do not apply to *primary effects* which do not a chance field defined and by definition will *always* happen when the move is executed.
### src/data/battle_move_effects.h
Effects are listed here along with the `battleScript` that governs each one. Said scripts are defined in [`data/battle_scripts_1.s`](#databattle_scripts_1s). The indices/names of the effects (e.g. `EFFECT_FIRST_TURN_ONLY`) are enums defined in [`include/constants/battle_move_effects.h`](#includeconstantsbattle_move_effectsh).
### include/battle_scripts.h
Contains references to scripts [`data/battle_scripts_1.s`](#databattle_scripts_1s), allowing them to be referenced in C. Any new scripts must be added here.
### include/constants/battle_move_effects.h
Simply an enum list of possible effects for moves. Any new effects would be added here, with a definition for them (including defining a script) would then also be added to [`src/data/battle_move_effects.h`](#srcdatabattle_move_effectsh).
### include/constants/battle_string_ids.h
All strings that can be printed in battle have an id that is defined here. The actual message itself would then be defined and assigned to this id in [`src/data/battle_message.c`](#srcbattle_messagec).
### include/constants/battle.h
A whole range of constants defining battle variables, such as statuses, weather, and move effects.
### include/constants/moves.h
Where moves are defined (and nothing else).
**Note:** When adding custom moves, you should add them between the moves from the latest generation and the z moves, then adjust `MOVES_COUNT` accordingly. Adding a move after `MOVES_COUNT` that is neither a Max Move or a Z Move will result in that move's name not being printed when it is used, instead a generic message will be printed.
## C files
### src/battle_script_commands.c
This is where a lot of the commands referred to in scripts are defined. For example, the `jumpifnotfirstturn` command above is defined by the function `Cmd_jumpifnotfirstturn` and you can see how it works in C. It's possible that any move editing or updating you have in mind can be done with existing commands, but if you wanted to add a new function that could be called in a script above, this is where you would define it.
### src/battle_util.c
This contains a lot of the "utility" functions used to determine things like a move's dynamic typing or power. It's also where damage calculation takes place, and a lot of that will naturally take a move's effect into account. For example, a move with the effect `EFFECT_SOLAR_BEAM` would have its damage halved in sandstorm. If you wanted to add a move with an effect which gave it variable BP or typing, this is the file you would encode that effect.
### src/battle_message.c
Contains string defines and functions that print messages during the battle. If you wish to add or edit a move's string, then this is where you would do so.
### src/battle_main.c
Contains more fundamental functions that control the flow of the battle. Functions here determine move order, dynamic typing, animations, priority, speed calculations and more.
## Script files
### 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:
```
BattleScript_EffectFirstTurnOnly::
attackcanceler
jumpifnotfirstturn BattleScript_FailedFromAtkString
goto BattleScript_EffectHit
```
`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.
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.
### asm/macros/battle_script.inc
The "link" between [`data/battle_scripts_1.s`](#databattle_scripts_1s) and [`src/battle_script_commands.c`](#srcbattle_script_commandsc). Each command is represented by a hex byte which represents its index in the `gBattleScriptingCommandsTable` array at the top of [`src/battle_script_commands.c`](#srcbattle_script_commandsc). However, this file also contains macros which perform combinations of other commands, or just calculations in assembly. In addition to commands, it is also possible to call functions in [`src/battle_script_commands.c`](#srcbattle_script_commandsc) using the `various` (now gradually being deprecated) and the `callnative` functionality. The `various` macros will point to a case under the `Cmd_various` function in [`src/battle_script_commands.c`](#srcbattle_script_commandsc), whereas `callnative` will let you directly call a function in [`src/battle_script_commands.c`](#srcbattle_script_commandsc) by name.
### data/battle_anim_scripts.s
This is the place where move animations are defined. The array at the top, `gBattleAnims_Moves`, is in move index order and determines which animation goes with which move.
## Editing a move
### Basic information
To edit a move's basic information, you need only edit the relevant fields in [`src/data/battle_moves.h`](#srcdatamoves_infoh). This will let you change a move's:
- name
- description
- power
- accuracy
- type
- category
- target
- pp
- recoil percentage
- flags
- Z-move effect (for status moves) or overwritting its calculated power (for damaging moves)
### Changing a move's main effect
To change the main effect of a move to an existing effect, you need only change its `effect` field to one of the options in [`src/data/battle_move_effects.h`](#srcdatabattle_move_effectsh). If you wish to keep the effect but simply modify how it works, you can modify how it plays out on screen by editing its entry in [`data/battle_scripts_1.s`](#databattle_scripts_1s) and any relevant functions in [`src/battle_script_commands.c`](#srcbattle_script_commandsc). To change how a move's dynamic power, accuracy and are calculated, then you need to modify the following functions:
- For power: `CalcMoveBasePowerAfterModifiers` in [`src/battle_util.c`](#srcbattle_utilc)
- For accuracy: `AccuracyCalcHelper` in [`src/battle_script_commands.c`](#srcbattle_script_commandsc)
- For type: `SetTypeBeforeUsingMove` in [`src/battle_main.c`](#srcbattle_mainc)
Note: A generic function for calculating category does not currently exist - Photon Geyser's script in [`data/battle_scripts_1.s`](#databattle_scripts_1s) uses a special `callnative` function `BS_SetPhotonGeyserCategory`.
### Changing a move's additional effects
If you look at the example [here](#srcdatamoves_infoh), you can see that Thunder Shock has an additional effects array that contains a single move effect `MOVE_EFFECT_PARALYSIS` with a 10% chance of applying. Thanks to this field, you can add and remove primary and secondary effects (so long as they are defined by a `MOVE_EFFECT`) to a move without having to change its effect or script. You can also make an effect apply to the attacker rather than the target (for, say, a stat boost) with `.self = TRUE` and you can set the probability to whatever you want with the `chance` field.
All additional effects with a defined chance (even 100%) are treated as "secondary effects". This means that they are nullified by Sheer Force, blocked by Shield Dust or the Covert Cloak, and have their chance modified by Serene Grace. Additional effects without a chance field (effectively setting it to 0) are treated as "primary effects", which means that they cannot be blocked by the aforementioned items and abilities and their chance to occur cannot be modified; they will *always* happen.
Each move can have up to 15 additional effects, allowing you to construct monstrosities like this:
```
[MOVE_POUND] =
{
.name = COMPOUND_STRING("Pound"),
.description = COMPOUND_STRING(
"Pounds the foe with\n"
"forelegs or tail."),
.effect = EFFECT_HIT,
.power = 40,
.type = TYPE_NORMAL,
.accuracy = 100,
.pp = 35,
.target = MOVE_TARGET_SELECTED,
.priority = 0,
.category = DAMAGE_CATEGORY_PHYSICAL,
.additionalEffects = ADDITIONAL_EFFECTS({
.moveEffect = MOVE_EFFECT_PARALYSIS,
.chance = 10,
},{
.moveEffect = MOVE_EFFECT_CONFUSION,
.chance = 100,
},{
.moveEffect = MOVE_EFFECT_FLINCH,
.chance = 30,
},{
.moveEffect = MOVE_EFFECT_ALL_STATS_UP,
.chance = 40,
.self = TRUE,
},{
.moveEffect = MOVE_EFFECT_RAPID_SPIN,
},{
.moveEffect = MOVE_EFFECT_DEF_MINUS_2,
.chance = 50,
}),
.makesContact = TRUE,
.ignoresKingsRock = B_UPDATED_MOVE_FLAGS == GEN_4,
.contestEffect = CONTEST_EFFECT_HIGHLY_APPEALING,
.contestCategory = CONTEST_CATEGORY_TOUGH,
.contestComboStarterId = COMBO_STARTER_POUND,
.contestComboMoves = {0}
},
```
**Note: at the moment, additional effects can only be used by damaging moves, not by status moves.**
## Adding a new move
To add a new move, you need to create an entry in three locations:
- a define in [`include/constants/moves.h`](#includeconstantsmovesh)
- an info entry in [`src/data/battle_moves.h`](#srcdatamoves_infoh)
- an animation entry in [data/battle_anim_scripts.s](#databattle_anim_scriptss)
And that's it! You can use an existing animation or effect for your move - or you can add your own, but I'll leave figuring that out to you.

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,578 @@
# How to use the Testing System
## Running Tests
To run all the tests use:
`make check -j`
To run specific tests, e.g. Spikes ones, use:
`make check TESTS="Spikes"`
To build a ROM (pokemerald-test.elf) that can be opened in mgba to view specific tests, e.g. Spikes ones, use:
`make pokeemerald-test.elf TESTS="Spikes"`
## How to Write Tests
Manually testing a battle mechanic often follows this pattern:
1. Create a party which can activate the mechanic.
2. Start a battle and play a few turns which activate the mechanic.
3. Look at the UI outputs to decide if the mechanic works.
Automated testing follows the same pattern:
1. Initialize the party in `GIVEN`.
2. Play the turns in `WHEN`.
3. Check the UI outputs in `SCENE`.
### Example 1
As a concrete example, to manually test `EFFECT_PARALYZE`, e.g. the
effect of Stun Spore you might:
1. Put a Wobbuffet that knows Stun Spore in your party.
2. Battle a wild Wobbuffet.
3. Use Stun Spore.
4. Check that the Wobbuffet is paralyzed.
This can be translated to an automated test as follows:
```
ASSUMPTIONS
{
ASSUME(gMovesInfo[MOVE_STUN_SPORE].effect == EFFECT_PARALYZE);
}
SINGLE_BATTLE_TEST("Stun Spore inflicts paralysis")
{
GIVEN {
PLAYER(SPECIES_WOBBUFFET); // 1.
OPPONENT(SPECIES_WOBBUFFET); // 2.
} WHEN {
TURN { MOVE(player, MOVE_STUN_SPORE); } // 3.
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_STUN_SPORE, player);
MESSAGE("Foe Wobbuffet is paralyzed! It may be unable to move!"); // 4
STATUS_ICON(opponent, paralysis: TRUE); // 4.
}
}
```
The `ASSUMPTIONS` block documents that Stun Spore has `EFFECT_PARALYZE`.
If Stun Spore did not have that effect it would cause the tests in the file to be skipped. We write our tests like this so that hackers can change the effects of moves without causing tests to fail.
`SINGLE_BATTLE_TEST` defines the name of the test. Related tests should start with the same prefix, e.g. Stun Spore tests should start with "Stun Spore", this allows just the Stun Spore-related tests to be run with:
`make check TESTS="Stun Spore"`
`GIVEN` initializes the parties, `PLAYER` and `OPPONENT` add a Pokémon to their respective parties. They can both accept a block which further customizes the Pokémon's stats, moves, item, ability, etc.
`WHEN` describes the turns, and `TURN` describes the choices made in a single turn. `MOVE` causes the player to use Stun Spore and adds the move to the Pokémon's moveset if an explicit Moves was not specified.
Pokémon that are not mentioned in a `TURN` use Celebrate.
The test runner rigs the RNG so that unless otherwise specified, moves always hit, never critical hit, always activate their secondary effects, and always roll the same damage modifier.
`SCENE` describes the player-visible output of the battle. In this case `ANIMATION` checks that the Stun Spore animation played, `MESSAGE` checks the paralysis message was shown, and `STATUS_ICON` checks that the opponent's HP bar shows a PRZ icon.
### Example 2
As a second example, to manually test that Stun Spore does not effect Grass-types you might:
1. Put a Wobbuffet that knows Stun Spore in your party.
2. Battle a wild Oddish.
3. Use Stun Spore.
4. Check that the move animation does not play.
5. Check that a "It doesn't affect Foe Oddish…" message is shown.
This can again be translated as follows:
```
SINGLE_BATTLE_TEST("Stun Spore does not affect Grass-types")
{
GIVEN {
ASSUME(gMovesInfo[MOVE_STUN_SPORE].powderMove);
ASSUME(gSpeciesInfo[SPECIES_ODDISH].types[0] == TYPE_GRASS);
PLAYER(SPECIES_ODDISH); // 1.
OPPONENT(SPECIES_ODDISH); // 2.
} WHEN {
TURN { MOVE(player, MOVE_STUN_SPORE); } // 3.
} SCENE {
NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_STUN_SPORE, player); // 4.
MESSAGE("It doesn't affect Foe Oddish…"); // 5.
}
}
```
The `ASSUME` commands are documenting the reasons why Stun Spore does not affect Oddish, namely that Stun Spore is a powder move, and Oddish is a Grass-type. These `ASSUME` statements function similarly to the ones in `ASSUMPTIONS` but apply only to the one test.
NOT inverts the meaning of a `SCENE` check, so applying it to `ANIMATION` requires that the Stun Spore animation does not play. `MESSAGE` checks that the message was shown.
The checks in `SCENE` are ordered, so together this says "The doesn't affect message is shown, and the Stun Spore animation does not play at any time before that". Normally you would only test one or the other, or even better, just `NOT STATUS_ICON(opponent, paralysis: TRUE);` to say that Oddish was not paralyzed without specifying the exact outputs which led to that.
### Example 3
As a final example, to test that Meditate works you might:
1. Put a Wobbuffet that knows Meditate and Tackle in your party.
2. Battle a wild Wobbuffet.
3. Use Tackle and note the amount the HP bar reduced.
4. Battle a wild Wobbuffet.
5. Use Meditate and that the stat change animation and message play.
6. Use Tackle and check that the HP bar reduced by more than in 3.
This can be translated to an automated test as follows:
```
SINGLE_BATTLE_TEST("Meditate raises Attack", s16 damage)
{
bool32 raiseAttack;
PARAMETRIZE { raiseAttack = FALSE; }
PARAMETRIZE { raiseAttack = TRUE; }
GIVEN {
ASSUME(gMovesInfo[MOVE_TACKLE].category == DAMAGE_CATEGORY_PHYSICAL);
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
if (raiseAttack) TURN { MOVE(player, MOVE_MEDITATE); } // 5.
TURN { MOVE(player, MOVE_TACKLE); } // 3 & 6.
} SCENE {
if (raiseAttack) {
ANIMATION(ANIM_TYPE_MOVE, MOVE_MEDITATE, player);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); // 5.
MESSAGE("Wobbuffet's attack rose!"); // 5.
}
ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, player);
HP_BAR(opponent, captureDamage: &results[i].damage); // 3 & 6.
} FINALLY {
EXPECT_MUL_EQ(results[0].damage, Q_4_12(1.5), results[1].damage); // 6.
}
}
```
`PARAMETRIZE` causes a test to run multiple times, once per `PARAMETRIZE` block (e.g. once with `raiseAttack = FALSE` and once with `raiseAttack = TRUE`).
The `HP_BAR` command's `captureDamage` causes the change in HP to be stored in a variable, and the variable chosen is `results[i].damage`.
`results[i]` contains all the variables defined at the end of `SINGLE_BATTLE_TEST`, `i` is the current `PARAMETRIZE` index.
`FINALLY` runs after the last parameter has finished, and uses `EXPECT_MUL_EQ` to check that the second battle deals 1.5× the damage of the first battle (with a small tolerance to account for rounding).
You might notice that all the tests check the outputs the player could see rather than the internal battle state. e.g. the Meditate test could have used `gBattleMons[B_POSITION_OPPONENT_LEFT].hp` instead of using `HP_BAR` to capture the damage. This is a deliberate choice, by checking what the player can observe the tests are more robust to refactoring, e.g. if `gBattleMons` got moved into `gBattleStruct` then any test that used it would need to be updated.
### Note on Overworld Tests
The overworld is not available, so it is only possible to test commands which don't affect the overworld itself, e.g. `givemon` can be tested because it only alters `gPlayerParty`, but `addobject` cannot because it affects object events (which aren't loaded).
## REFERENCE
### `ASSUME`
`ASSUME(cond)`
Causes the test to be skipped if `cond` is false. Used to document any prerequisites of the test, e.g. to test Burn reducing the Attack of a Pokémon we can observe the damage of a physical attack with and without the burn. To document that this test assumes the attack is physical we can use:
`ASSUME(gMovesInfo[MOVE_WHATEVER].category == DAMAGE_CATEGORY_PHYSICAL);`
### `ASSUMPTIONS`
```
ASSUMPTIONS
{
...
}
```
Should be placed immediately after any `#includes` and contain any `ASSUME` statements which should apply to the whole file, e.g. to test `EFFECT_POISON_HIT` we need to choose a move with that effect, if we chose to use Poison Sting in every test then the top of `move_effect_poison_hit.c` should be:
```
ASSUMPTIONS
{
ASSUME(gMovesInfo[MOVE_POISON_STING].effect == EFFECT_POISON_HIT);
}
```
### `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:
- 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...)`
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:
- 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
- apart from the `EXPECTED` commands, there's also a new `SCORE_` and `SCORE__VAL` commands
### `KNOWN_FAILING`
`KNOWN_FAILING;`
Marks a test as not passing due to a bug. If there is an issue number associated with the bug it should be included in a comment. If the test passes the developer will be notified to remove `KNOWN_FAILING`.
For example:
```
SINGLE_BATTLE_TEST("Jump Kick has no recoil if no target")
{
KNOWN_FAILING; // #2596.
...
}
```
### `PARAMETRIZE`
`PARAMETERIZE { parameter; }`
Runs a test multiple times. `i` will be set to which parameter is running, and `results` will contain an entry for each parameter, e.g.:
```
SINGLE_BATTLE_TEST("Blaze boosts Fire-type moves in a pinch", s16 damage)
{
u16 hp;
PARAMETRIZE { hp = 99; }
PARAMETRIZE { hp = 33; }
GIVEN {
ASSUME(gMovesInfo[MOVE_EMBER].type == TYPE_FIRE);
PLAYER(SPECIES_CHARMANDER) { Ability(ABILITY_BLAZE); MaxHP(99); HP(hp); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, MOVE_EMBER); }
} SCENE {
HP_BAR(opponent, captureDamage: &results[i].damage);
} FINALLY {
EXPECT(results[1].damage > results[0].damage);
}
}
```
### `PASSES_RANDOMLY`
`PASSES_RANDOMLY(successes, trials, [tag])`
Checks that the test passes successes/trials. If `tag` is provided, the test is run for each value that the tag can produce. For example, to check that Paralysis causes the turn to be skipped 25/100 times, we can write the following test that passes only if the Pokémon is fully paralyzed and specify that we expect it to pass 25/100 times when `RNG_PARALYSIS` varies:
```
SINGLE_BATTLE_TEST("Paralysis has a 25% chance of skipping the turn")
{
PASSES_RANDOMLY(25, 100, RNG_PARALYSIS);
GIVEN {
PLAYER(SPECIES_WOBBUFFET) { Status1(STATUS1_PARALYSIS); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, MOVE_CELEBRATE); }
} SCENE {
MESSAGE("Wobbuffet is paralyzed! It can't move!");
}
}
```
All `BattleRandom` calls involving tag will return the same number, so this cannot be used to have two moves independently hit or miss, for example.
If the tag is not provided, runs the test 50 times and computes an approximate pass ratio.
`PASSES_RANDOMLY(gMovesInfo[move].accuracy, 100);`
Note that this mode of PASSES_RANDOMLY makes the tests run very slowly and should be avoided where possible. If the mechanic you are testing is missing its tag, you should add it.
### `GIVEN`
```
Given {
...
}
```
Contains the initial state of the parties before the battle.
## `RNGSeed`
`RNGSeed(seed)`
Explicitly sets the RNG seed. Try to avoid using this because it is a very fragile tool.
Example:
```
GIVEN {
RNGSeed(0xC0DEIDEA);
...
}
```
### `FLAG_SET`
`FLAG_SET(flagId)`
Sets the specified flag. Can currently only set one flag at a time.
Cleared between parameters and at the end of the test.
Example:
```
GIVEN {
FLAG_SET(FLAG_SYS_EXAMPLE_FLAG);
...
}
```
### `PLAYER` and `OPPONENT`
`PLAYER(species)` and `OPPONENT(species`
Adds the species to the player's or opponent's party respectively.
The Pokémon can be further customized with the following functions:
- `Gender(MON_MALE | MON_FEMALE)`
- `Nature(nature)`
- `Ability(ability)`
- `Level(level)`
- `MaxHP(n)`, `HP(n)`, `Attack(n)`, `Defense(n)`, `SpAttack(n)`, `SpDefense(n)`, `Speed(n)`
- `Item(item)`
- `Moves(moves...)`
- `Friendship(friendship)`
- `Status1(status1)`
For example to create a level 42 Wobbuffet that is poisoned:
`PLAYER(SPECIES_WOBBUFFET) { Level(42); Status1(STATUS1_POISON); }`
**Note if Speed is specified for any Pokémon then it must be specified for all Pokémon.**
**Note if Moves is specified then MOVE will not automatically add moves to the moveset.**
### `AI_FLAGS`
`AI_FLAGS(flags)`
Specifies which AI flags are run during the test. Has use only for AI tests.
The most common combination is `AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT)` which is the general 'smart' AI.
### `WHEN`
```
...
} WHEN {
...
}
```
Contains the choices that battlers make during the battle.
### `TURN`
`TURN { ... }`
Groups the choices made by the battlers on a single turn. If Speeds have not been explicitly specified then the order of the `MOVE` commands in the `TURN` will be used to infer the Speeds of the Pokémon, e.g.:
```
// player's speed will be greater than opponent's speed.
TURN { MOVE(player, MOVE_SPLASH); MOVE(opponent, MOVE_SPLASH); }
// opponent's speed will be greater than player's speed.
TURN { MOVE(opponent, MOVE_SPLASH); MOVE(player, MOVE_SPLASH); }
```
The inference process is naive, if your test contains anything that modifies the speed of a battler you should specify them explicitly.
### `MOVE`
`MOVE(battler, move | moveSlot:, [megaEvolve:], [hit:], [criticalHit:], [target:], [allowed:], [WITH_RNG(tag, value])`
Used when the battler chooses Fight. Either the move ID (e.g. `MOVE_TACKLE` or move slot must be specified.
- `megaEvolve: TRUE` causes the battler to Mega Evolve if able
- `hit: FALSE` causes the move to miss
- `criticalHit: TRUE` causes the move to land a critical hit
- `target:` is used in double battles to choose the target (when necessary)
- `allowed: FALSE` is used to reject an illegal move e.g. a Disabled one
- `WITH_RNG` allows the move to specify an explicit outcome for an RNG tag
```
MOVE(playerLeft, MOVE_TACKLE, target: opponentRight);
```
If the battler does not have an explicit Moves specified the moveset will be populated based on the `MOVE`s it uses.
### `FORCED_MOVE`
`FORCED_MOVE(battler)`
Used when the battler chooses Fight and then their move is chosen for them, e.g. when affected by Encore.
```
FORCED_MOVE(player);
```
### `SWITCH`
`SWITCH(battler, partyIndex)`
Used when the battler chooses Switch.
```
SWITCH(player, 1);
```
### `SKIP_TURN`
`SKIP_TURN(battler)`
Used when the battler cannot choose an action, e.g. when locked into Thrash.
```
SKIP_TURN(player);
```
### `SEND_OUT`
`SEND_OUT(battler, partyIndex)`
Used when the battler chooses to switch to another Pokémon but not via Switch, e.g. after fainting or due to a U-turn.
```
SEND_OUT(player, 1);
```
### `USE_ITEM`
`USE_ITEM(battler, itemId, [partyIndex:], [move:])`
Used when the battler chooses to use an item from the Bag. The item ID (e.g. ITEM_POTION) must be specified, and party index and move slot if applicable, e.g:
```
USE_ITEM(player, ITEM_X_ATTACK);
USE_ITEM(player, ITEM_POTION, partyIndex: 0);
USE_ITEM(player, ITEM_LEPPA_BERRY, partyIndex: 0, move: MOVE_TACKLE);
```
### `SCENE`
```
...
} SCENE {
...
}
```
Contains an abridged description of the UI during the `THEN`. The order of the description must match too, e.g.
```
} SCENE {
// ABILITY_POPUP followed by a MESSAGE
ABILITY_POPUP(player, ABILITY_STURDY);
MESSAGE("Geodude was protected by Sturdy!");
}
```
### `ABILITY_POPUP`
`ABILITY_POPUP(battler, [ability])`
Causes the test to fail if the battler's ability pop-up is not shown.
If specified, ability is the ability shown in the pop-up.
```
ABILITY_POPUP(opponent, ABILITY_MOLD_BREAKER);
```
### `ANIMATION`
`ANIMATION(type, animId, [battler], [target:])`
Causes the test to fail if the animation does not play. A common use of this command is to check if a move was successful, e.g.:
```
ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, player);
```
`target` can only be specified for `ANIM_TYPE_MOVE`.
### `EXPERIENCE_BAR`
`EXPERIENCE_BAR(battler, [exp: | captureGainedExp:])`
If `exp:` is used, causes the test to fail if that amount of experience is not gained, e.g.:
```
EXPERIENCE_BAR(player, exp: 0);
```
If `captureGainedExp:` is used, causes the test to fail if the Experience bar does not change, and then writes that change to the pointer, e.g.:
```
u32 exp;
EXPERIENCE_BAR(player, captureGainedExp: &exp);
```
If none of the above are used, causes the test to fail if the Exp does not change at all.
**Please note that due to nature of tests, this command is only usable in `WILD_BATTLE_TEST` and will fail elsewhere.**
### `HP_BAR`
`HP_BAR(battler, [damage: | hp: | captureDamage: | captureHP:])`
If `hp:` or `damage:` are used, causes the test to fail if that amount of damage is not dealt, e.g.:
```
HP_BAR(player, hp: 0);
```
If `captureDamage:` or `captureHP:` are used, causes the test to fail if the HP bar does not change, and then writes that change to the
pointer, e.g.:
```
s16 damage;
HP_BAR(player, captureDamage: &damage);
```
If none of the above are used, causes the test to fail if the HP does not change at all.
### MESSAGE
`MESSAGE(pattern)`
Causes the test to fail if the message in pattern is not displayed.
Spaces in pattern match newlines (\n, \l, and \p) in the message.
Often used to check that a battler took its turn but it failed, e.g.:
```
MESSAGE("Wobbuffet used Dream Eater!");
MESSAGE("Foe Wobbuffet wasn't affected!");
```
### `STATUS_ICON`
`STATUS_ICON(battler, status1 | none: | sleep: | poison: | burn: | freeze: | paralysis:, badPoison:)`
Causes the test to fail if the battler's status is not changed to the specified status.
```
STATUS_ICON(player, badPoison: TRUE);
```
If the expected status icon is parametrized the corresponding `STATUS1` constant can be provided, e.g.:
```
u32 status1;
PARAMETRIZE { status1 = STATUS1_NONE; }
PARAMETRIZE { status1 = STATUS1_BURN; }
...
STATUS_ICON(player, status1);
```
### `NOT`
`NOT sceneCommand`
Causes the test to fail if the `SCENE` command succeeds before the following command succeeds.
```
// Our Wobbuffet does not Celebrate before the foe's.
NOT MESSAGE("Wobbuffet used Celebrate!");
MESSAGE("Foe Wobbuffet used Celebrate!");
```
**NOTE**: If this condition fails, the viewable ROM freezes at the NOT command.
**WARNING: `NOT` is an alias of `NONE_OF`, so it behaves surprisingly when applied to multiple commands wrapped in braces.**
### `ONE_OF`
```
ONE_OF {
...
}
```
Causes the test to fail unless one of the `SCENE` commands succeeds.
```
ONE_OF {
MESSAGE("Wobbuffet used Celebrate!");
MESSAGE("Wobbuffet is paralyzed! It can't move!");
}
```
### `NONE_OF`
```
NONE_OF {
...
}
```
Causes the test to fail if one of the `SCENE` commands succeeds before the command after the `NONE_OF` succeeds.
```
// Our Wobbuffet does not move before the foe's.
NONE_OF {
MESSAGE("Wobbuffet used Celebrate!");
MESSAGE("Wobbuffet is paralyzed! It can't move!");
}
MESSAGE("Foe Wobbuffet used Celebrate!");
```
### `PLAYER_PARTY`
Refer to the party members defined in `GIVEN`, e.g.:
```
s32 maxHP = GetMonData(&PLAYER_PARTY[0], MON_DATA_MAX_HP);
HP_BAR(player, damage: maxHP / 2);
```
### `OPPONENT_PARTY`
Refer to the party members defined in `GIVEN`, e.g.:
```
s32 maxHP = GetMonData(&OPPONENT_PARTY[0], MON_DATA_MAX_HP);
HP_BAR(opponent, damage: maxHP / 2);
```
### `THEN`
```
...
} THEN {
...
}
```
Contains code to run after the battle has finished. If the test is using `PARAMETRIZE` commands then `EXPECT` commands between the results should go here. Is also occasionally used to check the internal battle state when checking the behavior via a `SCENE` is too difficult, verbose, or error-prone.
### `FINALLY`
```
...
} FINALLY {
...
}
```
Contains checks to run after all `PARAMETERIZE` commands have run. Prefer to write your checks in `THEN` where possible, because a failure in `THEN` will be tagged with which parameter it corresponds to.
### `EXPECT`
`EXPECT(cond)`
Causes the test to fail if `cond` is false.
### `EXPECT_XX`
`EXPECT_EQ(a, b)`
`a == b`
`EXPECT_NE(a, b)`
`a != b`
`EXPECT_LT(a, b)`
`a < b`
`EXPECT_LE(a, b)`
`a <= b`
`EXPECT_GT(a, b)`
`a > b`
`EXPECT_GE(a, b)`
`a >= b`
Causes the test to fail if a and b compare incorrectly, e.g.
```
EXPECT_EQ(results[0].damage, results[1].damage);
```
### `EXPECT_MUL_EQ`
`EXPECT_MUL_EQ(a, m, b)`
Causes the test to fail if `a*m != b` (within a threshold), e.g.
```
// Expect results[0].damage * 1.5 == results[1].damage.
EXPECT_EQ(results[0].damage, Q_4_12(1.5), results[1].damage);
```
## Overworld Command Reference
### `OVERWORLD_SCRIPT`
`OVERWORLD_SCRIPT(instructions...)`
Returns a pointer to a compiled overworld script. Cannot be used to initialize global `const` data, although the pointer **IS** to `const` data.
Note that each script command must be followed by a ;, e.g.:
```
const u8 *myScript = OVERWORLD_SCRIPT(
random 2;
addvar VAR_RESULT, 1;
);
```
### `RUN_OVERWORLD_SCRIPT`
`RUN_OVERWORLD_SCRIPT(instructions...)`
Runs an overworld script in the immediate script context, which means that commands like `waitstate` are not supported.
```
RUN_OVERWORLD_SCRIPT(
setvar VAR_RESULT, 3;
);
EXPECT_EQ(GetVar(VAR_RESULT), 3);
```

View File

@ -0,0 +1,178 @@
# How to add a new trainer class
## Content
* [Quick Summary](#quick-summary)
* [The Graphics](#the-graphics)
* [1. Edit the sprites](#2-edit-the-sprites)
* [2. Register the sprites](#2-register-the-sprites)
* [3. The Animation](#2-the-animation)
* [4. Connecting pictures to the data](#2-connecting-pictures-to-the-data)
* [The Data](#the-data)
* [5. Defining the trainer class](#2-defining-the-trainer-class)
* [Usage](#usage)
## Quick Summary
(Page contains out of date information, [new instructions for Sprites here](https://github.com/rh-hideout/pokeemerald-expansion/pull/3597).)
If you've done this before and just need a quick lookup, here's what files you need:
1. GFX into [graphics/trainers/front_pics](https://github.com/rh-hideout/pokeemerald-expansion/blob/master/graphics/trainers/front_pics)
2. Palette into [graphics/trainers/palettes](https://github.com/rh-hideout/pokeemerald-expansion/blob/master/graphics/trainers/palettes)
3. Register sprites to [include/graphics.h](https://github.com/rh-hideout/pokeemerald-expansion/blob/master/include/graphics.h)
4. Point game to where graphic files are found: [src/data/graphics/trainers](https://github.com/rh-hideout/pokeemerald-expansion/blob/master/src/data/graphics/trainers.h)
5. Add animation to: [src/data/trainer_graphics/front_pic_anims.h](https://github.com/rh-hideout/pokeemerald-expansion/blob/master/src/data/trainer_graphics/front_pic_anims.h)
6. Add the trainer to all three structs in: [src/data/trainer_graphics/front_pic_table.h](https://github.com/rh-hideout/pokeemerald-expansion/blob/master/src/data/trainer_graphics/front_pic_table.h)
7. Add trainer to [include/constants/trainers.h](https://github.com/rh-hideout/pokeemerald-expansion/blob/master/include/constants/trainers.h)
## The Graphics
### 1. Edit the sprites
We will start with a graphic that we want to use for our new trainer class. Unlike with adding Pokémon, the trainer sprites aren't sorted in individual folders, but rather in one folder:
[graphics/trainers/front_pics](https://github.com/rh-hideout/pokeemerald-expansion/blob/master/graphics/trainers/front_pics)
**Remember to limit yourself to 16 colors including transparency in the first slot!**
Export the pallette and place into the same folder.
### 2. Register the sprites
Sadly, just putting the image files into the graphics folder is not enough. To use the sprites we have to register them, which is kind of tedious. First, create constants for the file paths.
Edit [include/graphics.h](https://github.com/rh-hideout/pokeemerald-expansion/blob/master/include/graphics.h):
```diff
extern const u32 gTrainerFrontPic_RubySapphireMay[];
+ extern const u32 gTrainerFrontPic_myTrainerClass[];
extern const u32 gTrainerPalette_Hiker[];
...
...
extern const u32 gTrainerPalette_RubySapphireMay[];
+ extern const u32 gTrainerPalette_myTrainerClass[];
extern const u8 gTrainerBackPic_Brendan[];
```
Now link the graphic files.
[src/data/graphics/trainers](https://github.com/rh-hideout/pokeemerald-expansion/blob/master/src/data/graphics/trainers.h):
```diff
const u32 gTrainerPalette_RubySapphireBrendan[] = INCBIN_U32("graphics/trainers/palettes/ruby_sapphire_brendan.gbapal.lz");
const u32 gTrainerFrontPic_RubySapphireMay[] = INCBIN_U32("graphics/trainers/front_pics/ruby_sapphire_may_front_pic.4bpp.lz");
const u32 gTrainerPalette_RubySapphireMay[] = INCBIN_U32("graphics/trainers/palettes/ruby_sapphire_may.gbapal.lz");
+ const u32 gTrainerFrontPic_Sheriff[] = INCBIN_U32("graphics/trainers/front_pics/myTrainerClass_front_pic.4bpp.lz");
+ const u32 gTrainerPalette_Sheriff[] = INCBIN_U32("graphics/trainers/palettes/myTrainerClass.gbapal.lz");
const u8 gTrainerBackPic_Brendan[] = INCBIN_U8("graphics/trainers/back_pics/brendan_back_pic.4
```
### 3. The Animation
Add the Animation of the trainer here:
[src/data/trainer_graphics/front_pic_anims.h](https://github.com/rh-hideout/pokeemerald-expansion/blob/master/src/data/trainer_graphics/front_pic_anims.h)
The trainers don't really move, but in theory they could, it's just that the animation defined for each trainer just shows one frame:
```diff
static const union AnimCmd *const sAnims_RubySapphireMay[] ={
sAnim_GeneralFrame0,
};
+ static const union AnimCmd *const sAnims_MyTrainerClass[] ={
+ sAnim_GeneralFrame0,
+ };
const union AnimCmd *const *const gTrainerFrontAnimsPtrTable[] =
{
[TRAINER_PIC_HIKER] = sAnims_Hiker,
[TRAINER_PIC_AQUA_GRUNT_M] = sAnims_AquaGruntM,
[TRAINER_PIC_POKEMON_BREEDER_F] = sAnims_PokemonBreederF,
...
...
[TRAINER_PIC_RS_BRENDAN] = sAnims_RubySapphireBrendan,
[TRAINER_PIC_RS_MAY] = sAnims_RubySapphireMay,
+ [TRAINER_PIC_MYTRAINERCLASS] = sAnims_MyTrainerClass,
};
```
### 4. Connecting the Pictures to the Data
The last few things we have to do is prepare the graphics for usage. In [src/data/trainer_graphics/front_pic_table.h](https://github.com/rh-hideout/pokeemerald-expansion/blob/master/src/data/trainer_graphics/front_pic_table.h) you'll find the structs, we need to add the trainer to all of these. You can just copy the last trainer type defined and edit it, but as far as I understand, these are what they do:
1. gTrainerFrontPicCoords: Pretty self explanatory. Coordinates like size and offset on the y-axis to position the sprite on screen.
2. gTrainerFrontPicTable: Connects the trainer type with the image we defined earlier.
3. gTrainerFrontPicPaletteTable: Connects the trainer type with the palette we defined earlier.
So, finally, it needs to look like this:
```diff
const struct MonCoords gTrainerFrontPicCoords[] =
{
[TRAINER_PIC_HIKER] = {.size = 8, .y_offset = 1},
[TRAINER_PIC_AQUA_GRUNT_M] = {.size = 8, .y_offset = 1},
...
...
[TRAINER_PIC_RS_BRENDAN] = {.size = 8, .y_offset = 1},
[TRAINER_PIC_RS_MAY] = {.size = 8, .y_offset = 1},
+ [TRAINER_PIC_MYTRAINERCLASS] = {.size = 8, .y_offset = 1},
};
#define TRAINER_SPRITE(trainerPic, sprite, size) [TRAINER_PIC_##trainerPic] = {sprite, size, TRAINER_PIC_##trainerPic}
const struct CompressedSpriteSheet gTrainerFrontPicTable[] =
{
TRAINER_SPRITE(HIKER, gTrainerFrontPic_Hiker, 0x800),
TRAINER_SPRITE(AQUA_GRUNT_M, gTrainerFrontPic_AquaGruntM, 0x800),
TRAINER_SPRITE(POKEMON_BREEDER_F, gTrainerFrontPic_PokemonBreederF, 0x800),
TRAINER_SPRITE(COOLTRAINER_M, gTrainerFrontPic_CoolTrainerM, 0x800),
...
...
TRAINER_SPRITE(RS_BRENDAN, gTrainerFrontPic_RubySapphireBrendan, 0x800),
TRAINER_SPRITE(RS_MAY, gTrainerFrontPic_RubySapphireMay, 0x800),
+ TRAINER_SPRITE(MYTRAINERCLASS, gTrainerFrontPic_MyTrainerClass, 0x800),
};
#define TRAINER_PAL(trainerPic, pal) [TRAINER_PIC_##trainerPic] = {pal, TRAINER_PIC_##trainerPic}
const struct CompressedSpritePalette gTrainerFrontPicPaletteTable[] =
{
TRAINER_PAL(HIKER, gTrainerPalette_Hiker),
TRAINER_PAL(AQUA_GRUNT_M, gTrainerPalette_AquaGruntM),
TRAINER_PAL(POKEMON_BREEDER_F, gTrainerPalette_PokemonBreederF),
...
...
TRAINER_PAL(RS_BRENDAN, gTrainerPalette_RubySapphireBrendan),
TRAINER_PAL(RS_MAY, gTrainerPalette_RubySapphireMay),
+ TRAINER_PAL(MYTRAINERCLASS, gTrainerPalette_MyTrainerClass),
};
```
### The Data
#### 5. Defining the trainer class
Finally, let's bring it all together by defining our new trainer class in [include/constants/trainers.h](https://github.com/rh-hideout/pokeemerald-expansion/blob/master/include/constants/trainers.h):
```diff
#define TRAINER_PIC_RS_MAY 92
+ #define TRAINER_PIC_MYTRAINERCLASS 93
#define TRAINER_BACK_PIC_BRENDAN 0
#define TRAINER_BACK_PIC_MAY 1
```
Remember to count the number next to the trainer class up by one!
## Usage
You can test your trainer type by going to [src/data/trainers](https://github.com/rh-hideout/pokeemerald-expansion/blob/master/src/data/trainers.h) and changing a trainer type. For example:
```diff
[TRAINER_BRENDAN_PLACEHOLDER] =
{
.partyFlags = 0,
.trainerClass = TRAINER_CLASS_RS_PROTAG,
.encounterMusic_gender = TRAINER_ENCOUNTER_MUSIC_MALE,
- .trainerPic = TRAINER_PIC_RS_BRENDAN,
+ .trainerPic = TRAINER_PIC_MYTRAINERCLASS,
.trainerName = _("BRENDAN"),
.items = {},
.doubleBattle = FALSE,
.aiFlags = 0,
.partySize = ARRAY_COUNT(sParty_BrendanLinkPlaceholder),
.party = {.NoItemDefaultMoves = sParty_BrendanLinkPlaceholder},
},
```

View File

@ -0,0 +1,2 @@
## Running documentation website locally
- [Ubuntu WSL1/WSL2](/docs/local_mdbook/ubuntu_WSL.md)

View File

@ -0,0 +1,51 @@
Note: For further information beyond this very basic guide, please visit mdBook's [official documentation](https://rust-lang.github.io/mdBook/).
## Running documentation website locally (Ubuntu WSL1/WSL2)
### Previous Requirements:
- Option 1: Install via Rust toolchain
- Install Rust toolchain if you don't have it via the `sudo apt install cargo` command.
- Install mdBook via the `cargo install mdbook` command. Once finished, this message will pop up, with {USER} being your Ubuntu
```
warning: be sure to add `/home/{USER}/.cargo/bin` to your PATH to be able to run the installed binaries
```
- Add `/home/{USER}/.cargo/bin` to your PATH (with {USER} being the Ubuntu username.)
- Run command `nano ~/.profile` to edit the file.
- Add the following lines, ***replacing {USER} with your Linux username.***
```diff
# set PATH so it includes user's private bin if it exists
if [ -d "$HOME/bin" ] ; then
PATH="$HOME/bin:$PATH"
fi
# set PATH so it includes user's private bin if it exists
if [ -d "$HOME/.local/bin" ] ; then
PATH="$HOME/.local/bin:$PATH"
fi
+# set PATH so it includes cargo bin if it exists
+if [ -d "/home/{USER}/.cargo/bin" ] ; then
+ PATH="/home/{USER}/.cargo/bin:$PATH"
+fi
```
- Run the `source ~/.profile` command to refresh the path in the current session.
- Option 2: Install downloaded binaries directly
- TODO: Add documentation of this process.
### Running the website
- Navigate to the `docs` folder on the repository.
- Run `mdbook serve`. Once started, you may now open the website on your browser by going to `http://127.0.0.1:3000`.
- Every change done to the `docs` folder will be reflected with an automatic refresh.
- To stop the server and go back to the terminal, press `Ctrl + C`.
### Modifying the website
- The navigation menu on the left is handled by `docs/SUMMARY.md`. Every file added needs to be added somewhere here in order to become visible, otherwise you'll get a 404 error.
- Any Markdown files (.md extension) added to the `docs/` directory will automatically be read by mdBook.
- To add Markdown files that are not in the `docs/` directory, you may create an empty `.md` file and add the following ***without the "----"***:
```md
{{ ----#include ../INSTALL.md}}`
```
This will include the `INSTALL.md` Markdown file from the root directory.
Once you're set up, you can now check your changes before pushing them to your repo! :D
We hope that this will make it easier for users to contribute to the documentation :)

300
docs/mmbn_style_names.md Normal file
View File

@ -0,0 +1,300 @@
# Megaman Battle Network Style Names
Prior to 1.10, names in expansion that were too long for the game's UIs were truncated to fit using the naming conventions from the [Megaman Battle Network](<https://www.therockmanexezone.com/wiki/The_Rockman_EXE_Zone_Wiki>) series.
These were removed as part of https://github.com/rh-hideout/pokeemerald-expansion/pull/5240. They are stored here for users that may want to refer back to them or restore them.
# Table
Attribute | MMBN | Official
-- | -- | --
Item | PewtrCrnches | Pewter Crunchies
Item | RageCandyBar | Rage Candy Bar
Item | LumioseGlete | Lumiose Galette
Item | ShalourSable | Shalour Sable
Item | HealthFeather | Health Feather
Item | MuscleFeather | Muscle Feather
Item | ResistFeather | Resist Feather
Item | GeniusFeather | Genius Feather
Item | CleverFeather | Clever Feather
Item | SwiftFeather | Swift Feather
Item | AbilityCapsle | Ability Capsule
Item | AbilityPatch | Ability Patch
Item | AbilityPatches | Ability Patches
Item | Exp.Candy XS | Exp. Candy XS
Item | Exp.Candies XS | Exp. Candies XS
Item | Exp.Candy S | Exp. Candy S
Item | Exp.Candies S | Exp. Candies S
Item | Exp.Candy M | Exp. Candy M
Item | Exp.Candies M | Exp. Candies M
Item | Exp.Candy L | Exp. Candy L
Item | Exp.Candies L | Exp. Candies L
Item | Exp.Candy XL | Exp. Candy XL
Item | Exp.Candies XL | Exp. Candies XL
Item | DynamaxCandy | Dynamax Candy
Item | DynamaxCandies | Dynamax Candies
Item | MaxMushrooms | Max Mushrooms
Item | GoldBottlCap | Gold Bottle Cap
Item | PrettyFeather | Pretty Feather
Item | StrngeSouvnr | Strange Souvenir
Item | FosslzedBird | Fossilized Bird
Item | FosslzedFish | Fossilized Fish
Item | FosslzedFishes | Fossilized Fishes
Item | FosslzedDrke | Fossilized Drake
Item | FosslzedDino | Fossilized Dino
Item | SurprseMulch | Surprise Mulch
Item | YellwApricorn | Yellow Apricorn
Item | GreenApricorn | Green Apricorn
Item | WhiteApricorn | White Apricorn
Item | BlackApricorn | Black Apricorn
Item | WishingPiece | Wishing Piece
Item | GalaricaTwig | Galarica Twig
Item | GalaricaCuff | Galarica Cuff
Item | GalrcaWreath | Galarica Wreath
Item | GalrcaWreathes | Galarica Wreathes
Item | StrwbrySweet | Strawberry Sweet
Item | ElectrcMemory | Electric Memory
Item | ElectrcMemories | Electric Memories
Item | FightngMemory | Fighting Memory
Item | FightngMemories | Fighting Memories
Item | PsychicMemory | Psychic Memory
Item | PsychicMemories | Psychic Memories
Item | RustedSword | Rusted Sword
Item | RustedShield | Rusted Shield
Item | CharizarditeX | Charizardite X
Item | CharizarditeY | Charizardite Y
Item | U-Necrozium Z | Ultranecrozium Z
Item | DeepSeaScale | Deep Sea Scale
Item | DeepSeaTooth | Deep Sea Tooth
Item | Never-MeltIce | Never-Melt Ice
Item | WeaknssPolicy | Weakness Policy
Item | WeaknssPolicies | Weakness Policies
Item | SafetyGoggles | Safety Goggles
Item | AdrenalineOrb | Adrenaline Orb
Item | TerainExtendr | Terrain Extender
Item | ProtectvePads | Protective Pads
Item | Heavy-DtyBts | Heavy-Duty Boots
Item | BlundrPolicy | Blunder Policy
Item | BlundrPolicies | Blunder Policies
Item | UtltyUmbrlla | Utility Umbrella
Item | CatchngCharm | Catching Charm
Item | RotomCatalog | Rotom Catalog
Item | ReinsOfUnity | Reins of Unity
Item | Dowsing MCHN | Dowsing Machine
Item | AbilityShield | Ability Shield
Item | PunchingGlove | Punching Glove
Item | AuspciousArmr | Auspicious Armor
Item | BoosterEnergy | Booster Energy
Item | BoosterEnergies | Booster Energies
Item | BigBmbooShoot | Big Bamboo Shoot
Item | GimighoulCoin | Gimmighoul Coin
Item | Leader'sCrest | Leader's Crest
Item | MaliciousArmr | Malicious Armor
Item | ScrllOfDrknss | Scroll of Darkness
Item | ScrllsOfDrknss | Scrolls of Darkness
Item | ScrollOfWatrs | Scroll of Waters
Item | ScrollsOfWatrs | Scrolls of Waters
Item | TinyBmbooShot | Tiny Bamboo Shoot
Item | Bug TeraShard | Bug Tera Shard
Item | DarkTeraShard | Dark Tera Shard
Item | DragnTeraShrd | Dragon Tera Shard
Item | EltrcTeraShrd | Electric Tera Shard
Item | FairyTeraShrd | Fairy Tera Shard
Item | FghtngTerShrd | Fighting Tera Shard
Item | FireTeraShard | Fire Tera Shard
Item | FlyngTeraShrd | Flying Tera Shard
Item | GhostTeraShrd | Ghost Tera Shard
Item | GrassTeraShrd | Grass Tera Shard
Item | GrondTeraShrd | Ground Tera Shard
Item | Ice TeraShard | Ice Tera Shard
Item | NormlTeraShrd | Normal Tera Shard
Item | PoisnTeraShrd | Poison Tera Shard
Item | PschcTeraShrd | Psychic Tera Shard
Item | RockTeraShard | Rock Tera Shard
Item | SteelTeraShrd | Steel Tera Shard
Item | WaterTeraShrd | Water Tera Shard
Item | AdamantCrystl | Adamant Crystal
Item | LustrousGlobe | Lustrous Globe
Item | BlackAugurite | Black Augurite
Item | UnrmkblTeacup | Unremarkable Teacup
Item | MstrpceTeacup | Masterpiece Teacup
Item | CornrstneMask | Cornerstone Mask
Item | WellsprngMask | Wellspring Mask
Item | HrthflameMask | Hearthflame Mask
Item | FrshStrtMochi | Fresh Start Mochi
Item | GlmmringCharm | Glimmering Charm
Item | StllrTeraShrd | Stellar Tera Shard
Item | JublifeMuffin | Jubilife Muffin
Item | AuxPowerguard | Aux Powerguard
Item | ChoiceDumplng | Choice Dumpling
Item | 2xSpicedRadsh | Twice-Spiced Radish
Move | ThunderPunch | Thunder Punch
Move | PoisonPowder | Poison Powder
Move | ThunderShock | Thunder Shock
Move | SelfDestruct | Self-Destruct
Move | HighJumpKick | High Jump Kick
Move | DynamicPunch | Dynamic Punch
Move | DragonBreath | Dragon Breath
Move | ExtremeSpeed | Extreme Speed
Move | AncientPower | Ancient Power
Move | SmellngSalts | Smelling Salts
Move | FeatherDance | Feather Dance
Move | GrassWhistle | Grass Whistle
Move | PhantomForce | Phantom Force
Move | TrickOrTreat | Trick-or-Treat
Move | ParabolcChrg | Parabolic Charge
Move | Forest'sCurs | Forest's Curse
Move | PetalBlizzrd | Petal Blizzard
Move | DisrmngVoice | Disarming Voice
Move | DrainingKiss | Draining Kiss
Move | CraftyShield | Crafty Shield
Move | FlowerShield | Flower Shield
Move | GrssyTerrain | Grassy Terrain
Move | MistyTerrain | Misty Terrain
Move | King'sShield | King's Shield
Move | DiamondStorm | Diamond Storm
Move | SteamErption | Steam Eruption
Move | HyprspceHole | Hyperspace Hole
Move | WatrShuriken | Water Shuriken
Move | MysticalFire | Mystical Fire
Move | AromaticMist | Aromatic Mist
Move | EerieImpulse | Eerie Impulse
Move | MagneticFlux | Magnetic Flux
Move | ElctrcTrrain | Electric Terrain
Move | DazzlngGleam | Dazzling Gleam
Move | BabyDollEyes | Baby-Doll Eyes
Move | PowerUpPunch | Power-Up Punch
Move | OblivionWing | Oblivion Wing
Move | ThousndArrws | Thousand Arrows
Move | ThousndWaves | Thousand Waves
Move | LightOfRuin | Light Of Ruin
Move | PrcipceBldes | Precipice Blades
Move | DragonAscent | Dragon Ascent
Move | HyprspceFury | Hyperspace Fury
Move | FrstImpressn | First Impression
Move | BanefulBunkr | Baneful Bunker
Move | SpiritShackl | Spirit Shackle
Move | DarkstLariat | Darkest Lariat
Move | SparklngAria | Sparkling Aria
Move | FloralHealng | Floral Healing
Move | HighHorsepwr | High Horsepower
Move | PsychcTrrain | Psychic Terrain
Move | RvlationDnce | Revelation Dance
Move | CoreEnforcer | Core Enforcer
Move | ClngngScales | Clanging Scales
Move | DragonHammer | Dragon Hammer
Move | PsychicFangs | Psychic Fangs
Move | StmpngTantrm | Stomping Tantrum
Move | PrsmaticLasr | Prismatic Laser
Move | SpectrlThief | Spectral Thief
Move | SnsteelStrke | Sunsteel Strike
Move | MoongestBeam | Moongeist Beam
Move | Natur'sMadns | Nature's Madness
Move | PhotonGeyser | Photon Geyser
Move | SplishySplsh | Splishy Splash
Move | BouncyBubble | Bouncy Bubble
Move | SparklySwirl | Sparkly Swirl
Move | VeeveeVolley | Veevee Volley
Move | DublIronBash | Double Iron Bash
Move | DynamxCannon | Dynamax Cannon
Move | FishiousRend | Fishious Rend
Move | ClngrousSoul | Clangorous Soul
Move | BehemthBlade | Behemoth Blade
Move | BehemothBash | Behemoth Bash
Move | BreakngSwipe | Breaking Swipe
Move | StrangeSteam | Strange Steam
Move | FalsSurrendr | False Surrender
Move | MeteorAssalt | Meteor Assault
Move | ExpandngForc | Expanding Force
Move | ShellSideArm | Shell Side Arm
Move | MstyExplsion | Misty Explosion
Move | RisngVoltage | Rising Voltage
Move | TerrainPulse | Terrain Pulse
Move | SkitterSmack | Skitter Smack
Move | BrningJelosy | Burning Jealousy
Move | CorrosiveGas | Corrosive Gas
Move | DualWingbeat | Dual Wingbeat
Move | ScorchngSnds | Scorching Sands
Move | JungleHealng | Jungle Healing
Move | SurgngStrkes | Surging Strikes
Move | DragonEnergy | Dragon Energy
Move | FreezngGlare | Freezing Glare
Move | ThnderusKick | Thunderous Kick
Move | GlacialLance | Glacial Lance
Move | AstrlBarrage | Astral Barrage
Move | PsyshieldBsh | Psyshield Bash
Move | SprngtdeStrm | Springtide Storm
Move | MystcalPower | Mystical Power
Move | MountainGale | Mountain Gale
Move | VictoryDance | Victory Dance
Move | HeadlongRush | Headlong Rush
Move | BitterMalice | Bitter Malice
Move | TripleArrows | Triple Arrows
Move | InfrnlParade | Infernal Parade
Move | CeaslessEdge | Ceaseless Edge
Move | BlekwndStorm | Bleakwind Storm
Move | WildbltStorm | Wildbolt Storm
Move | SndsearStorm | Sandsear Storm
Move | LunarBlessng | Lunar Blessing
Move | LastRespects | Last Respects
Move | SpicyExtract | Spicy Extract
Move | PoplatinBomb | Population Bomb
Move | RevivlBlesng | Revival Blessing
Move | KowtowCleave | Kowtow Cleave
Move | ColisinCours | Collision Course
Move | ElectroDrift | Electro Drift
Move | ChilReceptin | Chilly Reception
Move | ChillingWatr | Chilling Water
Move | GigatonHammr | Gigaton Hammer
Move | BlazngTorque | Blazing Torque
Move | WickedTorque | Wicked Torque
Move | NoxiusTorque | Noxious Torque
Move | CombatTorque | Combat Torque
Move | MagiclTorque | Magical Torque
Move | MatchaGotcha | Matcha Gotcha
Move | TeraStarstrm | Tera Starstorm
Move | BurnngBulwrk | Burning Bulwark
Move | MightyCleave | Mighty Cleave
Move | TachyonCuttr | Tachyon Cutter
Move | AllurngVoice | Alluring Voice
Move | SuprcellSlam | Supercell Slam
Move | PsychicNoise | Psychic Noise
Move | MalignntChan | Malignant Chain
Species | Dudunsprce | Dudunsparce
Species | Corvisquir | Corvisquire
Species | Corviknigh | Corviknight
Species | Barraskewd | Barraskewda
Species | Centiskorc | Centiskorch
Species | Polteageis | Polteageist
Species | Stonjourne | Stonjourner
Species | Meowscarad | Meowscarada
Species | Sqawkabily | Squawkabilly
Species | Kilowatrel | Kilowattrel
Species | Brmblghast | Brambleghast
Species | ScreamTail | Scream Tail
Species | BruteBonet | Brute Bonnet
Species | FluttrMane | Flutter Mane
Species | SlithrWing | Slither Wing
Species | SndyShocks | Sandy Shocks
Species | IronTreads | Iron Treads
Species | IronBundle | Iron Bundle
Species | IronJuguls | Iron Jugulis
Species | IronThorns | Iron Thorns
Species | RoarngMoon | Roaring Moon
Species | IronVliant | Iron Valiant
Species | WalkngWake | Walking Wake
Species | IronLeaves | Iron Leaves
Species | Ptchageist | Poltchageist
Species | Fezndipiti | Fezandipiti
Species | GouginFire | Gouging Fire
Species | RagingBolt | Raging Bolt
Species | IronBouldr | Iron Boulder
Species | Crabminabl | Crabominable
Species | Blacephaln | Blacephalon
Species | Bsculegion | Basculegion
Species | Flechinder | Fletchinder
Type | Fight | Fighting
Type | Electr | Electric
Type | Psychc | Psychic
Type | Stellr | Stellar

View File

@ -53,6 +53,7 @@
#define CHAR_EQUALS 0x35
#define CHAR_SEMICOLON 0x36
#define CHAR_BARD_WORD_DELIMIT 0x37 // Empty space to separate words in Bard's song
#define CHAR_V_D_ARROW 0x38
#define CHAR_INV_QUESTION_MARK 0x51
#define CHAR_INV_EXCL_MARK 0x52
#define CHAR_PK 0x53

View File

@ -52,7 +52,6 @@ static void SortSprites(u32 *spritePriorities, s32 n);
static u32 CreateSpriteAt(u32 index, const struct SpriteTemplate *template, s16 x, s16 y, u32 subpriority);
static void ResetOamMatrices(void);
static void ResetSprite(struct Sprite *sprite);
static void RequestSpriteFrameImageCopy(u16 index, u16 tileNum, const struct SpriteFrameImage *images);
static void ResetAllSprites(void);
static void BeginAnim(struct Sprite *sprite);
static void ContinueAnim(struct Sprite *sprite);
@ -75,7 +74,6 @@ static void AffineAnimCmd_end(u8 matrixNum, struct Sprite *sprite);
static void AffineAnimCmd_frame(u8 matrixNum, struct Sprite *sprite);
static void CopyOamMatrix(u8 destMatrixIndex, struct OamMatrix *srcMatrix);
static u8 GetSpriteMatrixNum(struct Sprite *sprite);
static void SetSpriteOamFlipBits(struct Sprite *sprite, u8 hFlip, u8 vFlip);
static void AffineAnimStateRestartAnim(u8 matrixNum);
static void AffineAnimStateStartAnim(u8 matrixNum, u8 animNum);
static void AffineAnimStateReset(u8 matrixNum);

View File

@ -331,5 +331,7 @@ u8 SpriteTileAllocBitmapOp(u16 bit, u8 op);
void ClearSpriteCopyRequests(void);
void ResetAffineAnimData(void);
u32 GetSpanPerImage(u32 shape, u32 size);
void RequestSpriteFrameImageCopy(u16 index, u16 tileNum, const struct SpriteFrameImage *images);
void SetSpriteOamFlipBits(struct Sprite *sprite, u8 hFlip, u8 vFlip);
#endif //GUARD_SPRITE_H

View File

@ -932,8 +932,9 @@ bool32 TextPrinterWaitAutoMode(struct TextPrinter *textPrinter)
{
struct TextPrinterSubStruct *subStruct = (struct TextPrinterSubStruct *)(&textPrinter->subStructFields);
if (subStruct->autoScrollDelay == 49)
if (subStruct->autoScrollDelay == NUM_FRAMES_AUTO_SCROLL_DELAY)
{
subStruct->autoScrollDelay = 0;
return TRUE;
}
else
@ -943,21 +944,29 @@ bool32 TextPrinterWaitAutoMode(struct TextPrinter *textPrinter)
}
}
void SetResultWithButtonPress(bool32 *result)
{
if (JOY_NEW(A_BUTTON | B_BUTTON))
{
*result = TRUE;
PlaySE(SE_SELECT);
}
}
bool32 TextPrinterWaitWithDownArrow(struct TextPrinter *textPrinter)
{
bool32 result = FALSE;
if (gTextFlags.autoScroll != 0)
if (gTextFlags.autoScroll != 0 || AUTO_SCROLL_TEXT)
{
result = TextPrinterWaitAutoMode(textPrinter);
if (AUTO_SCROLL_TEXT)
SetResultWithButtonPress(&result);
}
else
{
TextPrinterDrawDownArrow(textPrinter);
if (JOY_NEW(A_BUTTON | B_BUTTON))
{
result = TRUE;
PlaySE(SE_SELECT);
}
SetResultWithButtonPress(&result);
}
return result;
}
@ -965,17 +974,16 @@ bool32 TextPrinterWaitWithDownArrow(struct TextPrinter *textPrinter)
bool32 TextPrinterWait(struct TextPrinter *textPrinter)
{
bool32 result = FALSE;
if (gTextFlags.autoScroll != 0)
if (gTextFlags.autoScroll != 0 || AUTO_SCROLL_TEXT)
{
result = TextPrinterWaitAutoMode(textPrinter);
if (AUTO_SCROLL_TEXT)
SetResultWithButtonPress(&result);
}
else
{
if (JOY_NEW(A_BUTTON | B_BUTTON))
{
result = TRUE;
PlaySE(SE_SELECT);
}
SetResultWithButtonPress(&result);
}
return result;
}

View File

@ -0,0 +1,19 @@
JASC-PAL
0100
16
237 28 36
251 239 143
247 228 69
234 209 76
222 186 48
160 113 22
255 255 16
213 222 32
255 255 255
222 153 4
222 171 55
230 188 67
247 210 69
0 0 0
0 0 0
0 0 0

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -0,0 +1,19 @@
JASC-PAL
0100
16
237 28 36
185 255 175
142 243 140
56 177 78
78 214 109
48 126 26
44 177 68
65 206 48
8 248 0
24 189 2
90 189 77
97 210 101
137 226 120
0 0 0
0 0 0
0 0 0

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Some files were not shown because too many files have changed in this diff Show More