Merge branch 'upcoming' into queue_switches

This commit is contained in:
PhallenTree 2026-03-21 18:05:44 +00:00 committed by GitHub
commit 0944439191
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
216 changed files with 9369 additions and 7809 deletions

View File

@ -7,69 +7,217 @@ on:
- upcoming
pull_request:
env:
GAME_REVISION: 0
GAME_LANGUAGE: ENGLISH
COMPARE: 0
UNUSED_ERROR: 1
DEPRECATED_ERROR: 1
jobs:
build:
build-emerald:
if: github.actor != 'allcontributors[bot]'
runs-on: ubuntu-latest
env:
GAME_REVISION: 0
GAME_LANGUAGE: ENGLISH
COMPARE: 0
UNUSED_ERROR: 1
DEPRECATED_ERROR: 1
steps:
- name: Checkout
uses: actions/checkout@v2
uses: actions/checkout@v4
- name: Install binutils
run: |
sudo apt update
sudo apt install -y binutils-arm-none-eabi gcc-arm-none-eabi libnewlib-arm-none-eabi libpng-dev python3
# build-essential and git are already installed
sudo apt-get update
sudo apt-get install -y binutils-arm-none-eabi gcc-arm-none-eabi libnewlib-arm-none-eabi libpng-dev python3
- name: Cache build tools
uses: actions/cache@v4
with:
path: |
tools/bin2c/bin2c
tools/gbafix/gbafix
tools/gbagfx/gbagfx
tools/jsonproc/jsonproc
tools/mapjson/mapjson
tools/mid2agb/mid2agb
tools/preproc/preproc
tools/ramscrgen/ramscrgen
tools/rsfont/rsfont
tools/scaninc/scaninc
tools/trainerproc/trainerproc
tools/compresSmol/compresSmol
tools/compresSmol/compresSmolTilemap
tools/wav2agb/wav2agb
key: tools-${{ runner.os }}-${{ hashFiles('tools/*/Makefile', 'tools/**/*.c', 'tools/**/*.cpp', 'tools/**/*.h') }}
- name: ROM (Emerald)
env:
COMPARE: 0
GAME_VERSION: EMERALD
run: make -j${nproc} -O all
run: make -j$(nproc) -O all
build-firered:
if: github.actor != 'allcontributors[bot]'
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install binutils
run: |
sudo apt-get update
sudo apt-get install -y binutils-arm-none-eabi gcc-arm-none-eabi libnewlib-arm-none-eabi libpng-dev python3
- name: Cache build tools
uses: actions/cache@v4
with:
path: |
tools/bin2c/bin2c
tools/gbafix/gbafix
tools/gbagfx/gbagfx
tools/jsonproc/jsonproc
tools/mapjson/mapjson
tools/mid2agb/mid2agb
tools/preproc/preproc
tools/ramscrgen/ramscrgen
tools/rsfont/rsfont
tools/scaninc/scaninc
tools/trainerproc/trainerproc
tools/compresSmol/compresSmol
tools/compresSmol/compresSmolTilemap
tools/wav2agb/wav2agb
key: tools-${{ runner.os }}-${{ hashFiles('tools/*/Makefile', 'tools/**/*.c', 'tools/**/*.cpp', 'tools/**/*.h') }}
- name: ROM (Firered)
env:
COMPARE: 0
run: make firered -j$(nproc) -O
build-leafgreen:
if: github.actor != 'allcontributors[bot]'
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install binutils
run: |
make firered -j${nproc} -O
sudo apt-get update
sudo apt-get install -y binutils-arm-none-eabi gcc-arm-none-eabi libnewlib-arm-none-eabi libpng-dev python3
- name: Cache build tools
uses: actions/cache@v4
with:
path: |
tools/bin2c/bin2c
tools/gbafix/gbafix
tools/gbagfx/gbagfx
tools/jsonproc/jsonproc
tools/mapjson/mapjson
tools/mid2agb/mid2agb
tools/preproc/preproc
tools/ramscrgen/ramscrgen
tools/rsfont/rsfont
tools/scaninc/scaninc
tools/trainerproc/trainerproc
tools/compresSmol/compresSmol
tools/compresSmol/compresSmolTilemap
tools/wav2agb/wav2agb
key: tools-${{ runner.os }}-${{ hashFiles('tools/*/Makefile', 'tools/**/*.c', 'tools/**/*.cpp', 'tools/**/*.h') }}
- name: ROM (Leafgreen)
env:
COMPARE: 0
run: make leafgreen -j$(nproc) -O
release:
if: github.actor != 'allcontributors[bot]'
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install binutils
run: |
make leafgreen -j${nproc} -O
sudo apt-get update
sudo apt-get install -y binutils-arm-none-eabi gcc-arm-none-eabi libnewlib-arm-none-eabi libpng-dev python3
- name: Cache build tools
uses: actions/cache@v4
with:
path: |
tools/bin2c/bin2c
tools/gbafix/gbafix
tools/gbagfx/gbagfx
tools/jsonproc/jsonproc
tools/mapjson/mapjson
tools/mid2agb/mid2agb
tools/preproc/preproc
tools/ramscrgen/ramscrgen
tools/rsfont/rsfont
tools/scaninc/scaninc
tools/trainerproc/trainerproc
tools/compresSmol/compresSmol
tools/compresSmol/compresSmolTilemap
tools/wav2agb/wav2agb
key: tools-${{ runner.os }}-${{ hashFiles('tools/*/Makefile', 'tools/**/*.c', 'tools/**/*.cpp', 'tools/**/*.h') }}
- name: Release
env:
GAME_VERSION: EMERALD
run: make -j$(nproc) release
test:
if: github.actor != 'allcontributors[bot]'
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install binutils
run: |
make tidy
make -j${nproc} release
# make tidy to purge previous build
sudo apt-get update
sudo apt-get install -y binutils-arm-none-eabi gcc-arm-none-eabi libnewlib-arm-none-eabi libpng-dev python3
- name: Cache build tools
uses: actions/cache@v4
with:
path: |
tools/bin2c/bin2c
tools/gbafix/gbafix
tools/gbagfx/gbagfx
tools/jsonproc/jsonproc
tools/mapjson/mapjson
tools/mid2agb/mid2agb
tools/preproc/preproc
tools/ramscrgen/ramscrgen
tools/rsfont/rsfont
tools/scaninc/scaninc
tools/trainerproc/trainerproc
tools/compresSmol/compresSmol
tools/compresSmol/compresSmolTilemap
tools/wav2agb/wav2agb
tools/patchelf/patchelf
tools/mgba-rom-test-hydra/mgba-rom-test-hydra
key: tools-check-${{ runner.os }}-${{ hashFiles('tools/*/Makefile', 'tools/**/*.c', 'tools/**/*.cpp', 'tools/**/*.h') }}
- name: Test
env:
GAME_VERSION: EMERALD
TEST: 1
run: |
make -j${nproc} check
run: make -j$(nproc) check
# Gate job: satisfies the "build" branch protection rule.
# Passes only when all parallel build/test jobs succeed.
build:
if: github.actor != 'allcontributors[bot]'
runs-on: ubuntu-latest
needs: [build-emerald, build-firered, build-leafgreen, release, test]
steps:
- name: All builds passed
run: echo "All builds and tests passed."
docs_validate:
if: github.actor != 'allcontributors[bot]'
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
uses: actions/checkout@v4
- name: Check that SUMMARY.md includes markdown doc files
run: |
.github/docs_validate/inclusive_summary.py
run: .github/docs_validate/inclusive_summary.py
allcontributors:
if: github.actor == 'allcontributors[bot]'
@ -78,4 +226,3 @@ jobs:
steps:
- name: Automatically pass for allcontributors
run: echo "CI automatically passes for allcontributors" && exit 0

View File

@ -529,7 +529,7 @@ ifneq ($(NODEP),1)
endif
$(DATA_ASM_BUILDDIR)/%.o: $(DATA_ASM_SUBDIR)/%.s
$(PREPROC) $< charmap.txt | $(CPP) $(CPPFLAGS) $(INCLUDE_SCANINC_ARGS) - | $(PREPROC) -ie $< charmap.txt | $(AS) $(ASFLAGS) -o $@
$(PREPROC) -s $< charmap.txt | $(CPP) $(CPPFLAGS) $(INCLUDE_SCANINC_ARGS) - | $(PREPROC) -ie $< charmap.txt | $(AS) $(ASFLAGS) -o $@
$(DATA_ASM_BUILDDIR)/%.d: $(DATA_ASM_SUBDIR)/%.s
$(SCANINC) -M $@ $(INCLUDE_SCANINC_ARGS) -I "" $<

File diff suppressed because it is too large Load Diff

View File

@ -15,7 +15,7 @@
#include "constants/game_stat.h"
#include "constants/trainers.h"
#include "constants/species.h"
#include "constants/generational_changes.h"
#include "constants/config_changes.h"
.include "asm/macros.inc"
.include "asm/macros/battle_script.inc"
.include "constants/constants.inc"
@ -156,9 +156,12 @@ BattleScript_EffectShedTail::
switchinevents
end
BattleScript_EffectPsychicNoise::
BattleScript_MoveEffectPsychicNoise::
savetarget
copybyte gBattlerTarget, gEffectBattler
printstring STRINGID_PKMNPREVENTEDFROMHEALING
waitmessage B_WAIT_TIME_LONG
restoretarget
return
BattleScript_EffectFilletAway::
@ -409,18 +412,18 @@ BattleScript_EffectRevivalBlessingSendOut:
switchinevents
goto BattleScript_MoveEnd
BattleScript_StealthRockActivates::
setstealthrock BattleScript_StealthRockActivatesRet
BattleScript_MoveEffectStealthRock::
setstealthrock BattleScript_MoveEffectStealthRockRet
printfromtable gDmgHazardsStringIds
waitmessage B_WAIT_TIME_LONG
BattleScript_StealthRockActivatesRet:
BattleScript_MoveEffectStealthRockRet:
return
BattleScript_SpikesActivates::
trysetspikes BattleScript_SpikesActivatesRet
BattleScript_MoveEffectSpikes::
trysetspikes BattleScript_MoveEffectSpikesRet
printfromtable gDmgHazardsStringIds
waitmessage B_WAIT_TIME_LONG
BattleScript_SpikesActivatesRet:
BattleScript_MoveEffectSpikesRet:
return
BattleScript_EffectTeatime::
@ -649,11 +652,6 @@ BattleScript_ButHoopaCantUseIt:
waitmessage B_WAIT_TIME_LONG
goto BattleScript_MoveEnd
BattleScript_HyperspaceFuryRemoveProtect::
printstring STRINGID_BROKETHROUGHPROTECTION
waitmessage B_WAIT_TIME_LONG
return
BattleScript_MoveEffectIonDeluge::
printstring STRINGID_IONDELUGEON
waitmessage B_WAIT_TIME_LONG
@ -665,18 +663,19 @@ BattleScript_MoveEffectHaze::
return
BattleScript_MoveEffectLeechSeed::
savetarget
copybyte gBattlerTarget, gEffectBattler
printstring STRINGID_PKMNSEEDED
waitmessage B_WAIT_TIME_LONG
goto BattleScript_MoveEnd
BattleScript_MoveEffectReflect::
printfromtable gReflectLightScreenSafeguardStringIds
waitmessage B_WAIT_TIME_LONG
restoretarget
return
BattleScript_MoveEffectLightScreen::
BattleScript_MoveEffectScreens::
saveattacker
copybyte gBattlerAttacker, gEffectBattler
printfromtable gReflectLightScreenSafeguardStringIds
waitmessage B_WAIT_TIME_LONG
restoreattacker
return
BattleScript_EffectStuffCheeks::
@ -899,6 +898,8 @@ BattleScript_MoveEffectBugBite::
return
BattleScript_MoveEffectCoreEnforcer::
savetarget
copybyte gBattlerTarget, gEffectBattler
setgastroacid BattleScript_CoreEnforcerRet
printstring STRINGID_PKMNSABILITYSUPPRESSED
waitmessage B_WAIT_TIME_LONG
@ -906,6 +907,7 @@ BattleScript_MoveEffectCoreEnforcer::
call BattleScript_TryRevertWeatherform
flushtextbox
BattleScript_CoreEnforcerRet:
restoretarget
return
BattleScript_EffectLaserFocus::
@ -1120,7 +1122,7 @@ BattleScript_EffectAcupressureTry:
goto BattleScript_MoveEnd
BattleScript_MoveEffectFeint::
printstring STRINGID_FELLFORFEINT
printfromtable gBrokeProtectionStringIds
waitmessage B_WAIT_TIME_LONG
return
@ -1246,9 +1248,9 @@ BattleScript_EffectAfterYou::
BattleScript_MoveEffectFlameBurst::
printstring STRINGID_BURSTINGFLAMESHIT
waitmessage B_WAIT_TIME_LONG
healthbarupdate BS_SCRIPTING, PASSIVE_HP_UPDATE
datahpupdate BS_SCRIPTING, PASSIVE_HP_UPDATE
tryfaintmon BS_SCRIPTING
healthbarupdate BS_EFFECT_BATTLER, PASSIVE_HP_UPDATE
datahpupdate BS_EFFECT_BATTLER, PASSIVE_HP_UPDATE
tryfaintmon BS_EFFECT_BATTLER
return
BattleScript_EffectPowerTrick::
@ -2124,7 +2126,7 @@ BattleScript_EffectGravityInternal:
setgravity BattleScript_ButItFailed
attackanimation
waitanimation
BattleScript_EffectGravitySuccess::
BattleScript_MoveEffectGravity::
printstring STRINGID_GRAVITYINTENSIFIED
waitmessage B_WAIT_TIME_LONG
savetarget
@ -2767,11 +2769,6 @@ BattleScript_PrintReflectLightScreenSafeguardString::
waitmessage B_WAIT_TIME_LONG
goto BattleScript_MoveEnd
BattleScript_MoveEffectAuroraVeil::
printfromtable gReflectLightScreenSafeguardStringIds
waitmessage B_WAIT_TIME_LONG
return
BattleScript_VoltAbsorbHeal:
copybyte gBattlerAbility, gBattlerTarget
tryhealquarterhealth BS_TARGET, BattleScript_MonMadeMoveUseless @ Check if max hp
@ -3012,8 +3009,11 @@ BattleScript_EffectDestinyBond::
goto BattleScript_MoveEnd
BattleScript_MoveEffectEerieSpell::
savetarget
copybyte gBattlerTarget, gEffectBattler
printstring STRINGID_PKMNREDUCEDPP
waitmessage B_WAIT_TIME_LONG
restoretarget
return
BattleScript_EffectSpite::
@ -3734,12 +3734,15 @@ BattleScript_BreakScreens::
return
BattleScript_StealStats::
savetarget
copybyte gBattlerTarget, gEffectBattler
playmoveanimation MOVE_SPECTRAL_THIEF
waitanimation
printstring STRINGID_SPECTRALTHIEFSTEAL
waitmessage B_WAIT_TIME_LONG
spectralthiefprintstats
flushtextbox
restoretarget
return
BattleScript_EffectYawn::
@ -3752,9 +3755,12 @@ BattleScript_EffectYawn::
waitmessage B_WAIT_TIME_LONG
goto BattleScript_MoveEnd
BattleScript_MoveEffectYawnSide::
BattleScript_MoveEffectYawnFoe::
savetarget
copybyte gBattlerTarget, gEffectBattler
printstring STRINGID_PKMNWASMADEDROWSY
waitmessage B_WAIT_TIME_LONG
restoretarget
return
BattleScript_PrintAbilityMadeIneffective::
@ -4538,7 +4544,7 @@ BattleScript_SafeguardProtected::
pause B_WAIT_TIME_SHORT
printstring STRINGID_PKMNUSEDSAFEGUARD
waitmessage B_WAIT_TIME_LONG
end2
goto BattleScript_MoveEnd
BattleScript_SafeguardEnds::
pause B_WAIT_TIME_SHORT
@ -5933,6 +5939,13 @@ BattleScript_MoveEffectConfusion::
waitmessage B_WAIT_TIME_LONG
return
BattleScript_MoveEffectRecoilHP25::
saveattacker
copybyte gBattlerAttacker, sBATTLER
call BattleScript_MoveEffectRecoil
restoreattacker
return
BattleScript_MoveEffectRecoil::
healthbarupdate BS_ATTACKER, PASSIVE_HP_UPDATE
datahpupdate BS_ATTACKER, PASSIVE_HP_UPDATE
@ -7821,21 +7834,21 @@ BattleScript_LowerSideStatsEnd:
restoretarget
return
BattleScript_EffectSetWeather::
BattleScript_MoveEffectSetWeather::
playanimation 0, B_ANIM_MAX_SET_WEATHER
printfromtable gMoveWeatherChangeStringIds
waitmessage B_WAIT_TIME_LONG
call BattleScript_ActivateWeatherAbilities
return
BattleScript_EffectSetTerrain::
BattleScript_MoveEffectSetTerrain::
printfromtable gTerrainStringIds
waitmessage B_WAIT_TIME_LONG
playanimation BS_ATTACKER, B_ANIM_RESTORE_BG
call BattleScript_ActivateTerrainEffects
return
BattleScript_DamageNonTypesStarts::
BattleScript_MoveEffectDamageNonTypes::
printfromtable gDamageNonTypesStartStringIds
waitmessage B_WAIT_TIME_LONG
return
@ -7847,15 +7860,20 @@ BattleScript_DamageNonTypesContinues::
hitanimation BS_ATTACKER
goto BattleScript_DoTurnDmg
BattleScript_EffectTryReducePP::
tryspiteppreduce BattleScript_MoveEnd
BattleScript_MoveEffectSpite::
savetarget
copybyte gBattlerTarget, gEffectBattler
tryspiteppreduce BattleScript_MoveEffectSpiteRet
printstring STRINGID_PKMNREDUCEDPP
waitmessage B_WAIT_TIME_LONG
BattleScript_MoveEffectSpiteRet:
restoretarget
return
BattleScript_EffectParalyzeSide::
savetarget
copybyte sBATTLER, gBattlerTarget
copybyte sBATTLER, gEffectBattler
copybyte gBattlerTarget, gEffectBattler
BattleScript_ParalyzeSideLoop:
jumpifabsent BS_TARGET, BattleScript_ParalyzeSideIncrement
trysetparalysis BattleScript_ParalyzeSideIncrement
@ -7868,7 +7886,8 @@ BattleScript_ParalyzeSideEnd:
BattleScript_EffectPoisonSide::
savetarget
copybyte sBATTLER, gBattlerTarget
copybyte sBATTLER, gEffectBattler
copybyte gBattlerTarget, gEffectBattler
BattleScript_PoisonSideLoop:
jumpifabsent BS_TARGET, BattleScript_PoisonSideIncrement
trysetpoison BattleScript_PoisonSideIncrement
@ -7881,7 +7900,8 @@ BattleScript_PoisonSideEnd:
BattleScript_EffectPoisonParalyzeSide::
savetarget
copybyte sBATTLER, gBattlerTarget
copybyte sBATTLER, gEffectBattler
copybyte gBattlerTarget, gEffectBattler
BattleScript_PoisonParalyzeSideLoop:
jumpifabsent BS_TARGET, BattleScript_PoisonParalyzeSideIncrement
trysetpoisonparalysis BattleScript_PoisonParalyzeSideIncrement
@ -7894,7 +7914,8 @@ BattleScript_PoisonParalyzeSideEnd:
BattleScript_EffectEffectSporeSide::
savetarget
copybyte sBATTLER, gBattlerTarget
copybyte sBATTLER, gEffectBattler
copybyte gBattlerTarget, gEffectBattler
BattleScript_EffectSporeSideLoop:
jumpifabsent BS_TARGET, BattleScript_EffectSporeSideIncrement
tryseteffectspore BattleScript_EffectSporeSideIncrement
@ -7907,11 +7928,12 @@ BattleScript_EffectSporeSideEnd:
BattleScript_EffectConfuseSide::
savetarget
copybyte sBATTLER, gBattlerTarget
copybyte sBATTLER, gEffectBattler
copybyte gBattlerTarget, gEffectBattler
BattleScript_ConfuseSideLoop:
jumpifabsent BS_TARGET, BattleScript_ConfuseSideIncrement
trysetconfusion BattleScript_ConfuseSideIncrement
volatileanimation BS_EFFECT_BATTLER, VOLATILE_CONFUSION
volatileanimation BS_TARGET, VOLATILE_CONFUSION
BattleScript_ConfuseSidePrintMessage:
printstring STRINGID_PKMNWASCONFUSED
waitmessage B_WAIT_TIME_LONG
@ -7929,11 +7951,12 @@ BattleScript_PrintCoinsScattered:
BattleScript_EffectInfatuateSide::
savetarget
copybyte sBATTLER, gBattlerTarget
copybyte sBATTLER, gEffectBattler
copybyte gBattlerTarget, gEffectBattler
BattleScript_InfatuateSideLoop:
jumpifabsent BS_TARGET, BattleScript_InfatuateSideIncrement
trysetinfatuation BattleScript_InfatuateSideIncrement
volatileanimation BS_EFFECT_BATTLER, VOLATILE_INFATUATION
volatileanimation BS_TARGET, VOLATILE_INFATUATION
BattleScript_InfatuateSidePrintMessage:
printstring STRINGID_PKMNFELLINLOVE
waitmessage B_WAIT_TIME_LONG
@ -7946,7 +7969,8 @@ BattleScript_InfatuateSideEnd:
BattleScript_EffectTormentSide::
savetarget
copybyte sBATTLER, gBattlerTarget
copybyte sBATTLER, gEffectBattler
copybyte gBattlerTarget, gEffectBattler
BattleScript_TormentSideLoop:
jumpifabsent BS_TARGET, BattleScript_TormentSideIncrement
trysettorment BattleScript_TormentSideIncrement
@ -7967,7 +7991,8 @@ BattleScript_TormentEnds::
BattleScript_EffectMeanLookSide::
savetarget
copybyte sBATTLER, gBattlerTarget
copybyte sBATTLER, gEffectBattler
copybyte gBattlerTarget, gEffectBattler
BattleScript_MeanLookSideLoop:
jumpifabsent BS_TARGET, BattleScript_MeanLookSideIncrement
trysetescapeprevention BattleScript_MeanLookSideIncrement
@ -7983,7 +8008,8 @@ BattleScript_MeanLookSideEnd:
BattleScript_EffectRaiseCritAlliesAnim::
savetarget
copybyte gBattlerTarget, gBattlerAttacker
copybyte sBATTLER, gEffectBattler
copybyte gBattlerTarget, gEffectBattler
BattleScript_RaiseCritAlliesLoop:
jumpifabsent BS_TARGET, BattleScript_RaiseCritAlliesIncrement
setstatchanger STAT_ATK, 0, FALSE @ for animation
@ -7991,7 +8017,7 @@ BattleScript_RaiseCritAlliesLoop:
printstring STRINGID_PKMNGETTINGPUMPED
waitmessage B_WAIT_TIME_LONG
BattleScript_RaiseCritAlliesIncrement:
jumpifbytenotequal gBattlerTarget, gBattlerAttacker, BattleScript_RaiseCritAlliesEnd
jumpifbytenotequal gBattlerTarget, sBATTLER, BattleScript_RaiseCritAlliesEnd
setallytonexttarget BattleScript_RaiseCritAlliesLoop
BattleScript_RaiseCritAlliesEnd:
restoretarget
@ -8000,7 +8026,8 @@ BattleScript_RaiseCritAlliesEnd:
BattleScript_EffectHealOneSixthAllies::
jumpifteamhealthy BattleScript_MoveEnd
savetarget
copybyte gBattlerTarget, gBattlerAttacker
copybyte sBATTLER, gEffectBattler
copybyte gBattlerTarget, gEffectBattler
BattleScript_HealOneSixthAlliesLoop:
jumpifabsent BS_TARGET, BattleScript_HealOneSixthAlliesIncrement
tryhealsixthhealth BattleScript_HealOneSixthAlliesIncrement
@ -8009,7 +8036,7 @@ BattleScript_HealOneSixthAlliesLoop:
printstring STRINGID_PKMNREGAINEDHEALTH
waitmessage B_WAIT_TIME_LONG
BattleScript_HealOneSixthAlliesIncrement:
jumpifbytenotequal gBattlerTarget, gBattlerAttacker, BattleScript_HealOneSixthAlliesEnd
jumpifbytenotequal gBattlerTarget, sBATTLER, BattleScript_HealOneSixthAlliesEnd
setallytonexttarget BattleScript_HealOneSixthAlliesLoop
BattleScript_HealOneSixthAlliesEnd:
restoretarget
@ -8017,7 +8044,8 @@ BattleScript_HealOneSixthAlliesEnd:
BattleScript_EffectRecycleBerriesAllies::
savetarget
copybyte gBattlerTarget, gBattlerAttacker
copybyte sBATTLER, gEffectBattler
copybyte gBattlerTarget, gEffectBattler
BattleScript_RecycleBerriesAlliesLoop:
jumpifabsent BS_TARGET, BattleScript_RecycleBerriesAlliesIncrement
tryrecycleberry BattleScript_RecycleBerriesAlliesIncrement
@ -8026,13 +8054,13 @@ BattleScript_RecycleBerriesAlliesLoop:
waitmessage B_WAIT_TIME_LONG
swapattackerwithtarget
BattleScript_RecycleBerriesAlliesIncrement:
jumpifbytenotequal gBattlerTarget, gBattlerAttacker, BattleScript_RecycleBerriesAlliesEnd
jumpifbytenotequal gBattlerTarget, sBATTLER, BattleScript_RecycleBerriesAlliesEnd
setallytonexttarget BattleScript_RecycleBerriesAlliesLoop
BattleScript_RecycleBerriesAlliesEnd:
restoretarget
return
BattleScript_EffectSteelsurge::
BattleScript_MoveEffectSteelsurge::
setsteelsurge BattleScript_MoveEnd
printfromtable gDmgHazardsStringIds
waitmessage B_WAIT_TIME_LONG

View File

@ -1062,7 +1062,7 @@ EventScript_AfterWhiteOutHeal::
lockall
msgbox gText_FirstShouldRestoreMonsHealth
call EventScript_PkmnCenterNurse_TakeAndHealPkmn
call_if_unset FLAG_DEFEATED_RUSTBORO_GYM, EventScript_AfterWhiteOutHealMsgPreRoxanne
call_if_unset FLAG_DEFEATED_RUSTBORO_GYM, EventScript_AfterWhiteOutHealMsgPreFirstBoss
call_if_set FLAG_DEFEATED_RUSTBORO_GYM, EventScript_AfterWhiteOutHealMsg
applymovement VAR_LAST_TALKED, Movement_PkmnCenterNurse_Bow
waitmovement 0
@ -1070,7 +1070,7 @@ EventScript_AfterWhiteOutHeal::
releaseall
end
EventScript_AfterWhiteOutHealMsgPreRoxanne::
EventScript_AfterWhiteOutHealMsgPreFirstBoss::
msgbox gText_MonsHealedShouldBuyPotions
return
@ -1080,6 +1080,7 @@ EventScript_AfterWhiteOutHealMsg::
EventScript_AfterWhiteOutMomHeal::
lockall
textcolor NPC_TEXT_COLOR_FEMALE
applymovement LOCALID_PLAYERS_HOUSE_1F_MOM, Common_Movement_WalkInPlaceFasterDown
waitmovement 0
msgbox gText_HadQuiteAnExperienceTakeRest
@ -1432,7 +1433,7 @@ gText_HadQuiteAnExperienceTakeRest::
gText_MomExplainHPGetPotions::
.string "MOM: Oh, good! You and your\n"
.string "POKéMON are looking great.\p"
.string "I just heard from PROF. BIRCH.\p"
.string "I just heard from {STR_VAR_1}.\p"
.string "He said that POKéMON's energy is\n"
.string "measured in HP.\p"
.string "If your POKéMON lose their HP,\n"

View File

@ -17,7 +17,7 @@
"connections": null,
"object_events": [
{
"local_id": "LOCALID_MOM",
"local_id": "LOCALID_PLAYERS_HOUSE_1F_MOM",
"type": "object",
"graphics_id": "OBJ_EVENT_GFX_MOM_FRLG",
"x": 8,

View File

@ -9,7 +9,7 @@ PalletTown_PlayersHouse_1F_EventScript_Mom::
call_if_eq VAR_RESULT, MALE, PalletTown_PlayersHouse_1F_EventScript_MomOakLookingForYouMale
call_if_eq VAR_RESULT, FEMALE, PalletTown_PlayersHouse_1F_EventScript_MomOakLookingForYouFemale
closemessage
applymovement LOCALID_MOM, Common_Movement_FaceOriginalDirection
applymovement LOCALID_PLAYERS_HOUSE_1F_MOM, Common_Movement_FaceOriginalDirection
waitmovement 0
release
end

View File

@ -1,3 +1,16 @@
EventScript_AfterWhiteOutHeal_Frlg::
lockall
textcolor NPC_TEXT_COLOR_FEMALE
msgbox gText_FirstShouldRestoreMonsHealth
call EventScript_PkmnCenterNurse_TakeAndHealPkmn_Frlg
call_if_unset FLAG_DEFEATED_BROCK, EventScript_AfterWhiteOutHealMsgPreFirstBoss
call_if_set FLAG_DEFEATED_BROCK, EventScript_AfterWhiteOutHealMsg
applymovement VAR_LAST_TALKED, Movement_Bow
waitmovement 0
fadedefaultbgm
releaseall
end
EventScript_PkmnCenterNurse_Frlg::
message Text_WelcomeWantToHealPkmn_Frlg
waitmessage

View File

@ -1,138 +1,253 @@
# Generation of struct Pokemon instances
This document describes the ways you generate an instance of struct Pokemon through script or through code.
These Pokemon can be given to your players, be used as enemy trainer pokemon or as static wild pokemon.
This document describes the ways you generate an instance of `struct Pokemon` through script or through code.
These Pokemon can be given to your players, be used as enemy trainer Pokemon or as static wild Pokemon.
## Through script (`givemon` and `createmon`)
### `createmon`
`createmon` is a script command that allows you to generate a pokemon with any of the properties you might want.
It has a lot of arguments in order to offer this flexibility.
`side`, `slot`, `species` and `level` are the required arguments
`side` determines if the pokemon will be created as a player pokemon or an enemy pokemon: 0 will put the pokemon in the player party and 1 in the enemy party
`slot` determines the slot in the player or enemy party the pokemon will occupy. `slot` goes from 0 to 5 but if `side` is 0 (player pokemon), setting the slot to 6 will instead give the pokemon to player automatically putting it in the first empty slot or sending it to the PC when the party is the full. (Setting `slot` to 6 when trying to create an enemy pokemon will result in the `createmon` command being ignored)
`species` and `level` refers to the species id and the level of the pokemon you want to generate
`item`, `ball`, `nature`, `abilityNum`, `gender`, `hpEv`, `atkEv`, `defEv`, `speedEv`, `spAtkEv`, `spDefEv`, `hpIv`, `atkIv`, `defIv`, `speedIv`, `spAtkIv`, `spDefIv`, `move1`, `move2`, `move3`, `move4`, `shinyMode`, `gmaxFactor`, `teraType`, `dmaxLevel` are the optional arguments. They are pretty explicit in what they refer to but let's describe what they default to when they are not present.
`item` refers to the item the mon is holding. If the argument is missing, the mon won't be holding anything
`ball` refers to the type of ball the pokemon comes out of. This defaults to a PokeBall and if you are generating a wildmon, this will be overwritten if the pokemon is captured
`nature`, and `gender` will default to random values
`abilityNum` will default to the value corresponding to the personality they will roll (in practice, it's random but it will have correlations with other if the pokemon parameters)
`hpEv`, `atkEv`, `defEv`, `speedEv`, `spAtkEv`, `spDefEv` will default to 0
`hpIv`, `atkIv`, `defIv`, `speedIv`, `spAtkIv`, `spDefIv` will default to `USE_RANDOM_IVS` which tell the game to roll a random IV value (between 0 and 31). If the generated species has a `perfectIVCount`, only the random values will be eligible to be perfected.
`move1`, `move2`, `move3`, `move4` will default to `MOVE_DEFAULT` which tells the game to fill the slot with the last level up move available
`shinyMode` will default to SHINY_MODE_RANDOM doing random roll(s) to check if the mon is shiny. (The other possibile values for shinyMode are SHINY_MODE_ALWAYS and SHINY_MODE_NEVER to force the pokemon to be shiny or not be shiny respectively)
`gmaxFactor` default to FALSE
`teraType` will default to the value corresponding to the personality they will roll (in practice, it's random but it will have correlations with other if the pokemon parameters)
`dmaxLevel` will deafult to 0
`createmon` is a script command that allows you to generate a Pokemon with any of the properties you might want. It has a lot of arguments in order to offer this flexibility.
#### Required Arguments
> **side, slot, species, level** are the required arguments.
- **side** determines if the Pokemon will be created as a player Pokemon or an enemy Pokemon:
- `0` will put the Pokemon in the player party
- `1` in the enemy party
- **slot** determines the slot in the player or enemy party the Pokemon will occupy.
- `slot` goes from `0` to `5`
- If `side` is `0` (player Pokemon), setting the slot to `6` will instead give the Pokemon to player automatically putting it in the first empty slot or sending it to the PC when the party is the full.
- Setting `slot` to `6` when trying to create an enemy Pokemon will result in the `createmon` command being ignored.
- **species** and **level** refer to the species id and the level of the Pokemon you want to generate.
#### Optional Arguments
> `item`, `ball`, `nature`, `abilityNum`, `gender`, `hpEv`, `atkEv`, `defEv`, `speedEv`, `spAtkEv`, `spDefEv`, `hpIv`, `atkIv`, `defIv`, `speedIv`, `spAtkIv`, `spDefIv`, `move1`, `move2`, `move3`, `move4`, `shinyMode`, `gmaxFactor`, `teraType`, `dmaxLevel`.
The purpose of these arguments is largely self-explanatory but we will briefly discuss what they default to when nothing is explicitly specified.
- **item** refers to the item the Pokemon is holding. If the argument is missing, the Pokemon wont be holding anything.
- **ball** refers to the type of ball the Pokemon comes out of. The expected type is `enum Pokeball` defaults to a `BALL_POKE`. If the Pokemon being generated is a Wild Pokemon this will be overwritten if the Pokemon is captured.
- **nature** and **gender** will default to random values.
- **abilityNum** will default to the value corresponding to the personality rolled (This is essentially random but it will be have correlations to the other parameters of the Pokemon).
- **EVs**
`hpEv, atkEv, defEv, speedEv, spAtkEv, spDefEv` will default to `0`.
- **IVs**
`hpIv, atkIv, defIv, speedIv, spAtkIv, spDefIv` will default to `USE_RANDOM_IVS` which tell the game to roll a random IV value (between `0` and `31`). If the generated species has a `perfectIVCount`, only the random values will be eligible to be perfected.
- **moves**
`move1, move2, move3, move4` will default to `MOVE_DEFAULT` which tells the game to fill the slot with the last level up move available.
- **shinyMode** will default to `SHINY_MODE_RANDOM` doing random roll(s) to check if the Pokemon is shiny.
- `SHINY_MODE_ALWAYS` forces the Pokemon to be shiny
- `SHINY_MODE_NEVER` forces the Pokemon to not be shiny
- **gmaxFactor** defaults to `FALSE`.
- **teraType** will default to the value corresponding to the personality they will roll (in practice, its random but it will have correlations with other if the Pokemon parameters).
- **dmaxLevel** will default to `0`.
---
### `givemon`
`givemon` uses the same arguments as `createmon` minus `side` and `slot`. This is because `givemon` is almost equivalent to `createmon 0 6 ...` and just gives the mon to the player after generating it. The exception being that `givemon` interacts with the abilities `Synchronize` and `Cute Charm` slightly differently than `createmon` when `nature` or `gender` are not explicitly set.
`givemon` uses the same arguments as `createmon` minus `side` and `slot`.
### `setwildbattle (species:req, level:req, item=ITEM_NONE, species2=SPECIES_NONE, level2=0, item2=ITEM_NONE)`
This is because `givemon` is almost equivalent to `createmon 0 6 ...` and just gives the Pokemon to the player after generating it.
The exception being that `givemon` interacts with the abilities `Synchronize` and `Cute Charm` somewhat differently than `createmon` when `nature` or `gender` are not explicitly set.
---
### `setwildbattle`
##### Arguments
> `species:req`, `level:req`, `item=ITEM_NONE`, `species2=SPECIES_NONE`, `level2=0`, `item2=ITEM_NONE`
`setwildbattle` is a much simpler way to generate a Wild Pokemon ready for the player to fight.
`setwildbattle` is a much simpler way to generate a wildmon ready for the player to fight.
It only takes 3 arguments (or 6 if you want to make it a double wild battle)
`species` and `level` refers to the species id and the level of the pokemon you want to generate
`item` refers to the item the mon is holding. If the argument is missing, the mon won't be holding anything
`species2`, `level2`, and `item2` are relate to the species, level and item of the second mon generated in case you want to make a double wild battle
The other properties will like IVs and personality will be set random just like for a regular wild battle
Mons generated with `setwildbattle` will always be considered static encounters (STATIC_WILDMON_ORIGIN) and will thus be eligible to be affected by Synchronize and Cute Charm
### Synchronize and Cute Charm
- `species` and `level` refer to the `species` and the `level` of the Pokemon you want to generate.
- `item` refers to the item the Pokemon is holding. If no argument is provided the Pokemon will not be holding an item.
- `species2`, `level2`, and `item2` determine the `species`, `level` and `held item` respectively of the second Pokemon generated in case you want to make a double wild battle
- The other properties like IVs and personality will be set randomly the same way as they are set in regular wild battles.
`nature` and `gender` also accept `NATURE_MAY_SYNCHRONIZE` and `MON_GENDER_MAY_CUTE_CHARM` respectively as arguments
`NATURE_RANDOM` and `MON_GENDER_RANDOM` always return a random nature/gender and never check for Synchronize or Cute Charm. If you want the generated mon to have a chance to receive the effcets of Synchronize or Cute Charm, you need to use `NATURE_MAY_SYNCHRONIZE` and `MON_GENDER_MAY_CUTE_CHARM` respectively for nature and gender.
When you use `NATURE_MAY_SYNCHRONIZE` or `MON_GENDER_MAY_CUTE_CHARM`, you are telling the game can check if the player has a pokemon with Synchronize or Cute Charm in the first slot of its party and roll a die to see if the nature or gender should be fixed based on the ability or rolled normally.
The mon generated also need to be of the right "origin" to be eligible for Synchronize or Cute Charm. We don't want to "synchronize" a mon belonging to a trainer or change the gender of a gift mon with Cute Charm. So if a mon is generated for the player side, it will be considered a "gift mon" (GIFTMON_ORIGIN) and if a mon is generated on the enemy side, it will be considered a static wild encounter (STATIC_WILDMON_ORIGIN).
`givemon` will default to use `NATURE_MAY_SYNCHRONIZE` and `MON_GENDER_MAY_CUTE_CHARM` because we assume you will use givemon to create "gift mons" but if you don't want it to apply in a specific script, you can explicitly use `NATURE_RANDOM` and `MON_GENDER_RANDOM` instead
`createmon` on the other hand default to `NATURE_RANDOM` and `MON_GENDER_RANDOM` so you need to explicitly use `NATURE_MAY_SYNCHRONIZE` or `MON_GENDER_MAY_CUTE_CHARM` for the generated mon to be considered a gift mon or a static wild encounter
Static encounters and Gift mons eligibility to Synchronize vary through generations in the official games so you can use the config `OW_SYNCHRONIZE_NATURE` to match your preference or you can check the `src/ow_synchronize.c` to modify the Synchronize and Cute Charm eligibility of different origins however you like
Pokemon generated with `setwildbattle` will always be considered static encounters (`STATIC_WILDMON_ORIGIN`) and will thus be eligible to be affected by Synchronize and Cute Charm
#### Synchronize and Cute Charm
`nature` and `gender` also accept `NATURE_MAY_SYNCHRONIZE` and `MON_GENDER_MAY_CUTE_CHARM` respectively as arguments.
`NATURE_RANDOM` and `MON_GENDER_RANDOM` always return a random nature/gender and never check for Synchronize or Cute Charm. If you want the generated Pokemon to have a chance to receive the effects of Synchronize or Cute Charm, you need to use `NATURE_MAY_SYNCHRONIZE` and `MON_GENDER_MAY_CUTE_CHARM` respectively for nature and gender.
When you use `NATURE_MAY_SYNCHRONIZE` or `MON_GENDER_MAY_CUTE_CHARM`, you are telling the game can check if the player has a Pokemon with Synchronize or Cute Charm in the first slot of its party and roll a die to see if the nature or gender should be fixed based on the ability or rolled normally.
The Pokemon generated also need to be of the right "origin" to be eligible for Synchronize or Cute Charm. We don't want to "synchronize" a Pokemon belonging to a trainer or change the gender of a gift Pokemon with Cute Charm. So if a Pokemon is generated for the player side, it will be considered a "gift Pokemon" (`GIFTMON_ORIGIN`) and if a Pokemon is generated on the enemy side, it will be considered a static wild encounter (`STATIC_WILDMON_ORIGIN`).
`givemon` will default to use `NATURE_MAY_SYNCHRONIZE` and `MON_GENDER_MAY_CUTE_CHARM` because we assume you will use `givemon` to create "gift Pokemon" but if you don't want it to apply in a specific script, you can explicitly use `NATURE_RANDOM` and `MON_GENDER_RANDOM` instead
`createmon` on the other hand default to `NATURE_RANDOM` and `MON_GENDER_RANDOM` so you need to explicitly use `NATURE_MAY_SYNCHRONIZE` or `MON_GENDER_MAY_CUTE_CHARM` for the generated Pokemon to be considered a gift Pokemon or a static wild encounter
Static encounters and Gift Pokemon eligibility to Synchronize vary through generations in the official games so you can use the config `OW_SYNCHRONIZE_NATURE` to match your preference or you can check the `src/ow_abilities.c` to modify the Synchronize and Cute Charm eligibility of different origins however you like
---
## Through Code
A lot of places in the game generate mons, when you start a wild encounter, when a trainer generates its party from the data in trainers.party or even when you call one of the script described in the previous section. So let's go through some of the most common functions.
Note: None of the functions described here allocate memory for the Pokemon struct, they all expect a pointer they will fill the data with.
There are several instances of Pokemon generation throughout the game:
- When you start a wild encounter,
- When a trainer generates its party from the data in `trainers.party`,
- Or when you call one of the scripts described in the previous section.
In this section we will go through some of the most common functions.
> NOTE: None of the functions described here allocate memory for the Pokemon struct, they all expect a pointer they will fill the data with.
It means they are usually called with `&gPlayerParty[index]` or `&gEnemyParty[index]` because these are places in memory reserved for Pokemon struct.
### The basics
### The Basics
To generate a mon ready for battle, you usually need to go through these steps:
- generate a personality value
- fill the generic mon structure based on species, level and personality
- set IVs and EVs
- (re-)compute stats (this step does not happen if you are generating a `struct boxPokemon` instead of `struct Pokemon`)
- set the moves
To generate a Pokemon ready for battle, you usually need to go through the following steps:
1. Generate a personality value
2. Fill the generic mon structure based on `species`, `level` and `personality`.
3. Set IVs and EVs.
4. (Re-)Compute stats (this step does not happen if you are generating a `struct BoxPokemon` instead of `struct Pokemon`).
5. set the moves.
### `GetMonPersonality`
`GetMonPersonality` is the easiest way to make a personality value. It takes 4 arguments `species`, `gender`, `nature` and `unownLetter` then it rolls random personality values until it finds one that match all the selected criteria.
For example, if you want a personality for Wally's male Ralts, you would write:
`personality = GetMonPersonality(SPECIES_RALTS, MON_MALE, NATURE_RANDOM, RANDOM_UNOWN_LETTER);`
and if you want a personality for a brave J Unown, you would write
`personality = GetMonPersonality(SPECIES_UNOWN, MON_GENDER_RANDOM, NATURE_BRAVE, 9);` (J is the 10th letter of alphabet but for unown A starts at 0 so B is 1 and J is 9)
As you can see, you can use either a specific value or a special value `MON_GENDER_RANDOM`, `NATURE_RANDOM` or `RANDOM_UNOWN_LETTER` to tell the function to return any pokemon matching the other properties. This means, writing:
`personality = GetMonPersonality(SPECIES_X, MON_GENDER_RANDOM, NATURE_RANDOM, RANDOM_UNOWN_LETTER);`
id equivalent to
`personality = Random32();`
which is why `Random32()` is used throughout to generate a personality value in certain circumstances
```c
personality = GetMonPersonality(SPECIES_RALTS, MON_MALE, NATURE_RANDOM, RANDOM_UNOWN_LETTER);
```
And if you want a personality for a brave J Unown, you would write:
```c
personality = GetMonPersonality(SPECIES_UNOWN, MON_GENDER_RANDOM, NATURE_BRAVE, 9);
// J is the 10th letter of alphabet but for Unown A starts at 0 so B is 1 and J is 9
```
As you can see, you can use either a specific value or a special value `MON_GENDER_RANDOM`, `NATURE_RANDOM` or `RANDOM_UNOWN_LETTER` to tell the function to return any Pokemon matching the other properties. This means, writing:
```
personality = GetMonPersonality(SPECIES_X, MON_GENDER_RANDOM, NATURE_RANDOM, RANDOM_UNOWN_LETTER);
```
is equivalent to `personality = Random32();` which is why `Random32()` is used throughout the codebase to generate fully random personality values.
---
### `CreateMon` and `CreateBoxMon`
`CreateMon` is the most basic function to create a generic Pokemon struct. It takes 5 arguments:
`mon` is a pointer to the mon struct you want to set the data for
`species` and `level` are fairly explicit
`personality` is the personality value you want to use to create your mon, it will determine a lot of your mon properties and will usually be a number that you generated by following the instructions from the previous section
`trainerID` is a special type of struct that explain how the function should set up the otId of the pokemon. Usually you will want to use one of these 3 macros for the argument:
`OTID_STRUCT_PLAYER_ID` which means the pokemon should the player otId (used for wildmon so they the get the player id when captured)
`OTID_STRUCT_PRESET(value)` which set a specific otId that you pick/write yourself
`OTID_STRUCT_RANDOM_NO_SHINY` which picks a random otId and forces the mon to not be shiny even if the random otId and chosen personality would have made the mon shiny. It is used by NPC trainers.
Both `CreateMon` and `CreateBoxMon` erase the pokemon data in the pointer before they add the new data so every value they don't set will be zero-ed in some way. This is why they are considered "base" functions.
The values set by `CreateMon` and `CreateBoxMon` are the gender, ability num, tera type and nature (based on personality); the met info (location, level and game), the original trainer name, gender and language (always set to the player even for enemy trainer mons), the starting xp (based on the xp required to reach the level the pokemon is at), the starting friendship (based on the species info) and the shinyness.
`CreateMon` and `CreateBoxMon` are very similar. In fact, the `CreateMon` function calls `CreateBoxMon` to generate the boxmon part of its structure but it also sets the level and a mail object (to an empty value)
- `mon` is a pointer to the Pokemon struct you want to set the data for
- `species` and `level` are self-explanatory.
- `personality` is the personality value you want to use to create your Pokemon, it will determine a lot of your Pokemon properties and will usually be a number that you generated by following the instructions from the previous section.
- `trainerID` is a special type of struct that explain how the function should set up the `otId` of the Pokemon. Usually you will want to use one of these 3 macros for the argument:
- `OTID_STRUCT_PLAYER_ID` which means the Pokemon will use the player `otId` (used by Wild Pokemon so they the get the player id when captured)
- `OTID_STRUCT_PRESET(value)` which set a specific `otId` that you pick/write yourself
- `OTID_STRUCT_RANDOM_NO_SHINY` which picks a random `otId` and forces the Pokemon to not be shiny even if the random `otId` and chosen `personality` would have made the Pokemon shiny. It is used by NPC trainers.
- Both `CreateMon` and `CreateBoxMon` erase the Pokemon data in the pointer before they add the new data so every value they don't set will be zero-ed in some way. This is why they are considered "base" functions.
The values set by `CreateMon` and `CreateBoxMon` are the `gender`, `ability num`, `tera type` and `nature` (based on personality); the `met info` (location, level and game), the `OT name` , `gender` and `language` (always set to the player even for enemy trainer Pokemon), the `starting xp` (based on the xp required to reach the level the Pokemon is at), the `starting friendship` (based on the species info) and the `shinyness`.
`CreateMon` and `CreateBoxMon` are very similar. In fact, the `CreateMon` function calls `CreateBoxMon` to generate the BoxPokemon part of its structure but it also sets the level and a mail object (to an empty value)
### Setting IVs and EVs
Usually, you will want to use `SetBoxMonIVs(mon->box, ivs)` to set the ivs of the pokemon you are generating. The reason is that not only can you quickly set all ivs of your mon to a single value: `SetBoxMonIVs(mon->box, 15)` will set all IVs to 15. You can also use the special argument `USE_RANDOM_IVS`. When used with `USE_RANDOM_IVS`, `SetBoxMonIvs` will not only pick a random value between 0 and 31 for each stat, it will also allocate some perfect iv if the species of the mon has a perfectIvCount set in the species data. For example if you are generating a legendary with a perfectIvCount of 3, using `SetBoxMonIVs(mon->box, USE_RANDOM_IVS)` will guarantee that at least 3 IVs are set to 31. This is done using the function `SetBoxMonPerfectIVs`, which can also be used elsewhere to assign a number of random perfect IVs.
#### IVs
Usually, you will want to use `SetBoxMonIVs(mon->box, ivs)` to set the IVs of the Pokemon being generated. The reason is that not only can you quickly set all ivs of your Pokemon to a single value.
For instance `SetBoxMonIVs(mon->box, 15)` will set all IVs to 15.
You can also use the special argument `USE_RANDOM_IVS`. When used with `USE_RANDOM_IVS`, `SetBoxMonIvs` will not only pick a random value between 0 and 31 for each stat, it will also allocate some perfect iv if the species of the Pokemon has a `perfectIvCount` set in the species data.
For example if you are generating a legendary with a `perfectIvCount` of 3, using `SetBoxMonIVs(mon->box, USE_RANDOM_IVS)` will guarantee that at least 3 IVs are set to 31. This is done using the function `SetBoxMonPerfectIVs`, which can also be used elsewhere to assign a number of random perfect IVs.
The other way to assign IV is to use `SetMonData`, for example:
`SetMonData(mon, MON_DATA_HP_IV, 15)`
with the stats being in order `MON_DATA_HP_IV`, `MON_DATA_ATK_IV`, `MON_DATA_DEF_IV`, `MON_DATA_SPEED_IV`, `MON_DATA_SPATK_IV` and `MON_DATA_SPDEF_IV`
```c
SetMonData(mon, MON_DATA_HP_IV, 15)
```
with the stats being in the order `MON_DATA_HP_IV`, `MON_DATA_ATK_IV`, `MON_DATA_DEF_IV`, `MON_DATA_SPEED_IV`, `MON_DATA_SPATK_IV` and `MON_DATA_SPDEF_IV`
You can also use a loop like this:
```c
for (i = 0; i < NUM_STATS; i++)
SetMonData(mon, MON_DATA_HP_IV + i, iv_array[i])
```
if you happen to have an array containing the values you want but be careful about the order if you use this method
EVs default to 0 when a mon is generated with `CreateMon` or `CreateBoxMon` so you may not need to anything if you want to keep it that way. If you want to change them, there are currently no utilities to set EVs at the moment so you will need to use the `SetMonData` method as well:
`SetMonData(mon, MON_DATA_HP_EV, 252)`
The stats have the same names as the IVs with I cheange into an E : `MON_DATA_HP_EV`, `MON_DATA_ATK_EV`, `MON_DATA_DEF_EV`, `MON_DATA_SPEED_EV`, `MON_DATA_SPATK_EV` and `MON_DATA_SPDEF_EV` so the loop method works here too
if you happen to have an array containing the values you want. However, you must be careful about the order of the stats if you use this method.
#### EVs
EVs default to `0` when a Pokemon is generated with `CreateMon` or `CreateBoxMon`. You will not need to anything if you want to keep it that way.
If you want to change them, there are currently no utilities to set EVs. Thus you will need to use the `SetMonData` method:
```c
SetMonData(mon, MON_DATA_HP_EV, 252)
```
The stats have the same names as the IVs with I change into an E : `MON_DATA_HP_EV`, `MON_DATA_ATK_EV`, `MON_DATA_DEF_EV`, `MON_DATA_SPEED_EV`, `MON_DATA_SPATK_EV` and `MON_DATA_SPDEF_EV` so the loop method works here as well.
```c
for (i = 0; i < NUM_STATS; i++)
SetMonData(mon, MON_DATA_HP_EV + i, ev_array[i])
```
Just be careful when setting IVs and EVs with SetMonData because they are no check to make sure the IV and EV values you are setting are valid and this may cause some issues.
Just be careful when setting IVs and EVs with `SetMonData` because there is no check to make sure the IV and EV values you are setting are valid and this may cause some issues.
### `CalculateMonStats`
After all the IVs and EVs have been set for your mon, it's important to run `CalculateMonStats(mon)`. The function only has one argument so it's pretty simple but don't forget this step or you may have some isseus
After all the IVs and EVs have been set for your Pokemon, it's important to run `CalculateMonStats(mon)`. The function only has one argument so it's pretty simple but don't forget this step or you may have some issues.
### Setting moves
To set a move in slot `slot`, you would need to write:
```c
enum Move move = MOVE_X;
u32 pp = GetMovePP(move);
SetMonData(mon, MON_DATA_MOVE1 + slot, &move);
SetMonData(mon, MON_DATA_PP1 + slot, &spp);
```
where slot can be between 0 and 3 to represent the 1st to 4th move
You can also call the function `GiveMonInitialMoveset(mon)` that will give your pokemon its last 4 level-up moves available similarly to the wild pokemon you might enciunter
You can also call the function `GiveMonInitialMoveset(mon)` that will give your Pokemon its last 4 level-up moves available similarly to the wild Pokemon you might encounter.
## Going from 1.14 to 1.15
When going from 1.14 to 1.15, Expansion deleted multiple functions related to mon generation that were not used in Expansion anymore.
When going from 1.14 to 1.15, Expansion deleted multiple functions related to Pokemon generation that were not used in Expansion anymore.
The following functions were deleted
```c
void CreateMonWithNature(struct Pokemon *mon, u16 species, u8 level, u8 fixedIV, u8 nature);
void CreateMonWithGenderNatureLetter(struct Pokemon *mon, u16 species, u8 level, u8 fixedIV, u8 gender, u8 nature, u8 unownLetter);
@ -140,14 +255,18 @@ void CreateMonWithIVsOTID(struct Pokemon *mon, u16 species, u8 level, u8 *ivs, u
void CreateMonWithEVSpread(struct Pokemon *mon, u16 species, u8 level, u8 fixedIV, u8 evSpread);
void CreateMonWithEVSpreadNatureOTID(struct Pokemon *mon, u16 species, u8 level, u8 nature, u8 fixedIV, u8 evSpread, u32 otId);
```
If you add custom code relying on those functions, I would advise to simple recode them using the methods described in the previous section. If you follow the steps, you should be able to rewrite a function with the same effect easily.
However the move to 1.15 also completely rewrote these two functions:
```c
void CreateMon(struct Pokemon *mon, u16 species, u8 level, u8 fixedIV, u8 hasFixedPersonality, u32 fixedPersonality, u8 otIdType, u32 fixedOtId);
void CreateBoxMon(struct BoxPokemon *boxMon, u16 species, u8 level, u8 fixedIV, u8 hasFixedPersonality, u32 fixedPersonality, u8 otIdType, u32 fixedOtId);
```
`CreateMon` and `CreateBoxMon` now have different arguments and do less things than their 1.14 counterparts. If you have code that used those functions, we recommend you use these legacy version of `CreateMon` and `CreateBoxMon`:
```c
void CreateMonLegacy(struct Pokemon *mon, u16 species, u8 level, u8 fixedIV, u8 hasFixedPersonality, u32 fixedPersonality, u8 otIdType, u32 fixedOtId)
{
@ -166,4 +285,5 @@ void CreateBoxMonLegacy(struct BoxPokemon *boxMon, u16 species, u8 level, u8 fix
GiveBoxMonInitialMoveset(boxMon);
}
```
These two legacy functions use the 1.15 functions to recreate the 1.14 versions of `CreateMon` and `CreateBoxMon` with the same arguments and the same effects. Add these two legacy functions to your code then change your custom code that was relying on 1.14 `CreateMon` or `CreateBoxMon` to use `CreateMonLegacy` or `CreateBoxMonLegacy` instead and everything should work the same as before

View File

@ -0,0 +1,19 @@
JASC-PAL
0100
16
180 180 180
49 49 49
74 74 98
200 243 230
176 227 212
156 210 194
144 200 184
136 189 173
122 177 161
104 160 144
123 123 148
123 123 123
98 98 123
255 255 255
239 251 248
82 82 82

View File

@ -2,18 +2,18 @@ JASC-PAL
0100
16
180 180 180
164 226 197
238 242 230
139 170 180
8 113 115
0 157 156
106 222 172
41 182 189
90 206 172
90 182 180
8 0 0
65 190 189
115 194 189
0 117 131
0 129 131
0 12 0
64 128 115
92 163 114
101 169 99
69 171 140
115 191 132
72 141 162
83 204 163
72 176 192
49 49 49
149 210 138
137 225 177
190 237 195
143 224 228
255 255 255
0 0 0

Binary file not shown.

Before

Width:  |  Height:  |  Size: 304 B

After

Width:  |  Height:  |  Size: 266 B

View File

@ -15,7 +15,7 @@ JASC-PAL
193 33 41
141 251 184
52 66 162
194 181 66
0 0 0
0 0 0
123 131 0
255 255 255

View File

@ -15,7 +15,7 @@ JASC-PAL
193 33 41
141 251 184
52 66 162
194 181 66
74 74 74
0 0 0
123 131 0
255 255 255

View File

@ -15,7 +15,7 @@ JASC-PAL
193 33 41
141 251 184
52 66 162
194 181 66
0 0 0
0 0 0
123 131 0
255 255 255

View File

@ -15,7 +15,7 @@ JASC-PAL
193 33 41
141 251 184
52 66 162
194 181 66
74 74 74
0 0 0
123 131 0
255 255 255

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@ -8,7 +8,7 @@ struct ApprenticeTrainer
u8 name[NUM_LANGUAGES - 1][PLAYER_NAME_LENGTH + 1]; // For all languages except the unused one.
u16 otId;
u8 facilityClass;
u16 species[APPRENTICE_SPECIES_COUNT];
enum Species species[APPRENTICE_SPECIES_COUNT];
u8 id;
u16 speechLost[EASY_CHAT_BATTLE_WORDS_COUNT];
};

View File

@ -23,7 +23,7 @@
#include "battle_dynamax.h"
#include "battle_terastal.h"
#include "battle_gimmick.h"
#include "generational_changes.h"
#include "config_changes.h"
#include "item.h"
#include "move.h"
#include "random.h" // for rng_value_t
@ -177,7 +177,7 @@ struct AI_SavedBattleMon
struct AiPartyMon
{
u16 species;
enum Species species;
enum Item item;
enum HoldEffect heldEffect;
enum Ability ability;
@ -202,6 +202,7 @@ struct SimulatedDamage
u16 minimum;
u16 median;
u16 maximum;
u16 random;
};
// Ai Data used when deciding which move to use, computed only once before each turn's start.
@ -235,7 +236,8 @@ struct AiLogicData
u32 shouldConsiderExplosion:1; // Determines whether AI should consider explosion moves this turn
u32 shouldSwitch:4; // Stores result of ShouldSwitch, which decides whether a mon should be switched out
u32 shouldConsiderFinalGambit:1; // Determines whether AI should consider Final Gambit this turn
u32 padding2:19;
u32 switchInCalc:1; // Indicates if we're doing switch in calcs, this is purely for Retaliate damage calcs
u32 padding2:18;
};
struct AiThinkingStruct
@ -304,16 +306,16 @@ struct BattleResults
u8 playerMonWasDamaged:1; // 0x5
u8 caughtMonBall:4; // 0x5
u8 shinyWildMon:1; // 0x5
u16 playerMon1Species; // 0x6
enum Species playerMon1Species; // 0x6
u8 playerMon1Name[POKEMON_NAME_LENGTH + 1]; // 0x8
u8 battleTurnCounter; // 0x13
u8 playerMon2Name[POKEMON_NAME_LENGTH + 1]; // 0x14
u8 pokeblockThrows; // 0x1F
u16 lastOpponentSpecies; // 0x20
enum Species lastOpponentSpecies; // 0x20
u16 lastUsedMovePlayer; // 0x22
u16 lastUsedMoveOpponent; // 0x24
u16 playerMon2Species; // 0x26
u16 caughtMonSpecies; // 0x28
enum Species playerMon2Species; // 0x26
enum Species caughtMonSpecies; // 0x28
u8 caughtMonNick[POKEMON_NAME_LENGTH + 1]; // 0x2A
u8 filler35; // 0x35
u8 catchAttempts[POKEBALL_COUNT]; // 0x36
@ -656,7 +658,7 @@ struct BattleStruct
u8 ballSpriteIds[2]; // item gfx, window gfx
u8 moveInfoSpriteId; // move info, window gfx
// When using a move which hits multiple opponents which is then bounced by a target, we need to make sure, the move hits both opponents, the one with bounce, and the one without.
u16 beatUpSpecies[PARTY_SIZE]; // Species for Gen5+ Beat Up, otherwise party indexes
enum Species beatUpSpecies[PARTY_SIZE]; // Species for Gen5+ Beat Up, otherwise party indexes
u8 attackerBeforeBounce:2;
u8 beatUpSlot:3;
u8 pledgeMove:1;
@ -680,7 +682,7 @@ struct BattleStruct
u16 additionalEffectsCounter:4; // A counter for the additionalEffects applied by the current move in Cmd_setadditionaleffects
u8 pursuitStoredSwitch; // Stored id for the Pursuit target's switch
s32 battlerExpReward;
u16 prevTurnSpecies[MAX_BATTLERS_COUNT]; // Stores species the AI has in play at start of turn
enum Species prevTurnSpecies[MAX_BATTLERS_COUNT]; // Stores species the AI has in play at start of turn
s16 passiveHpUpdate[MAX_BATTLERS_COUNT]; // non-move damage and healing
s16 moveDamage[MAX_BATTLERS_COUNT];
u16 moveResultFlags[MAX_BATTLERS_COUNT];
@ -846,7 +848,7 @@ struct BattleSpriteInfo
u16 behindSubstitute:1; // 0x4
u16 flag_x8:1; // 0x8
u16 hpNumbersNoBars:1; // 0x10
u16 transformSpecies;
enum Species transformSpecies;
};
struct BattleAnimationInfo

View File

@ -136,6 +136,8 @@ void SetAiLogicDataForTurn(struct AiLogicData *aiData);
void ResetDynamicAiFunctions(void);
void AI_TrySwitchOrUseItem(enum BattlerId battler);
void CalcBattlerAiMovesData(struct AiLogicData *aiData, enum BattlerId battlerAtk, enum BattlerId battlerDef, u32 weather, u32 fieldStatus);
void AIDebugTimerStart(void);
void AIDebugTimerEnd(void);
extern AiSwitchFunc gDynamicAiSwitchFunc;

View File

@ -27,6 +27,8 @@ enum ShouldSwitchScenario
SHOULD_SWITCH_NATURAL_CURE_WEAK_STATS_RAISED,
SHOULD_SWITCH_REGENERATOR,
SHOULD_SWITCH_REGENERATOR_STATS_RAISED,
SHOULD_SWITCH_INTIMIDATE,
SHOULD_SWITCH_INTIMIDATE_STATS_RAISED,
SHOULD_SWITCH_ENCORE_STATUS,
SHOULD_SWITCH_ENCORE_DAMAGE,
SHOULD_SWITCH_CHOICE_LOCKED,

View File

@ -7,19 +7,24 @@
// Roll boundaries used by AI when scoring. Doesn't affect actual damage dealt.
#define MAX_ROLL_PERCENTAGE DMG_ROLL_PERCENT_HI
#define MIN_ROLL_PERCENTAGE DMG_ROLL_PERCENT_LO
#define DMG_ROLL_PERCENTAGE ((MAX_ROLL_PERCENTAGE + MIN_ROLL_PERCENTAGE + 1) / 2) // Controls the damage roll the AI sees for the default roll. By default the 9th roll is seen
#define DMG_ROLL_PERCENTAGE ((MAX_ROLL_PERCENTAGE + MIN_ROLL_PERCENTAGE + 1) / 2) // Controls the damage roll the AI sees for the median roll. By default the 9th roll is seen
enum DamageRollType
{
DMG_ROLL_LOWEST,
DMG_ROLL_DEFAULT,
DMG_ROLL_MEDIAN,
DMG_ROLL_HIGHEST,
DMG_ROLL_RANDOM,
};
enum DamageCalcContext
{
AI_DEFENDING,
AI_ATTACKING,
AI_SWITCHIN_DEFENDING,
AI_SWITCHIN_ATTACKING,
AI_SHOULD_SETUP_DEFENDING,
AI_ATTACKING_PARTNER,
};
enum AiConsiderEndure
@ -96,7 +101,7 @@ void SetBattlerData(enum BattlerId battlerId);
void SetBattlerAiData(enum BattlerId battler, struct AiLogicData *aiData);
void RestoreBattlerData(enum BattlerId battlerId);
enum Move GetAIChosenMove(enum BattlerId battlerId);
u32 GetTotalBaseStat(u32 species);
u32 GetTotalBaseStat(enum Species species);
bool32 IsTruantMonVulnerable(enum BattlerId battlerAI, enum BattlerId opposingBattler);
bool32 AI_BattlerAtMaxHp(enum BattlerId battler);
u32 GetHealthPercentage(enum BattlerId battler);
@ -104,7 +109,7 @@ bool32 AI_CanBattlerEscape(enum BattlerId battler);
bool32 IsBattlerTrapped(enum BattlerId battlerAtk, enum BattlerId battlerDef);
s32 AI_WhoStrikesFirst(enum BattlerId battlerAI, enum BattlerId battler, enum Move aiMoveConsidered, enum Move playerMoveConsidered, enum ConsiderPriority considerPriority);
bool32 CanTargetFaintAi(enum BattlerId battlerDef, enum BattlerId battlerAtk);
u32 NoOfHitsForTargetToFaintBattler(enum BattlerId battlerDef, enum BattlerId battlerAtk, enum AiConsiderEndure considerEndure);
u32 NoOfHitsForTargetToFaintBattler(enum BattlerId battlerDef, enum BattlerId battlerAtk, enum DamageCalcContext calcContext, enum AiConsiderEndure considerEndure);
void GetBestDmgMovesFromBattler(enum BattlerId battlerAtk, enum BattlerId battlerDef, enum DamageCalcContext calcContext, enum Move *bestMoves);
u32 GetMoveIndex(enum BattlerId battler, enum Move move);
bool32 IsBestDmgMove(enum BattlerId battlerAtk, enum BattlerId battlerDef, enum DamageCalcContext calcContext, enum Move move);
@ -256,6 +261,7 @@ bool32 AI_IsBattlerAsleepOrComatose(enum BattlerId battlerId);
// ability logic
bool32 IsMoxieTypeAbility(enum Ability ability);
bool32 DoesAbilityRaiseStatsWhenLowered(enum Ability ability);
bool32 DoesIntimidateRaiseStats(enum Ability ability);
bool32 ShouldTriggerAbility(enum BattlerId battlerAtk, enum BattlerId battlerDef, enum Ability ability);
bool32 CanEffectChangeAbility(enum BattlerId battlerAtk, enum BattlerId battlerDef, enum Move move, struct AiLogicData *aiData);
void AbilityChangeScore(enum BattlerId battlerAtk, enum BattlerId battlerDef, enum Move move, s32 *score, struct AiLogicData *aiData);
@ -322,7 +328,6 @@ bool32 IsBattlerPredictedToSwitch(enum BattlerId battler);
enum Move GetIncomingMove(enum BattlerId battler, enum BattlerId opposingBattler, struct AiLogicData *aiData);
enum Move GetIncomingMoveSpeedCheck(enum BattlerId battler, enum BattlerId opposingBattler, struct AiLogicData *aiData);
bool32 AI_OpponentCanFaintAiWithMod(enum BattlerId battler, u32 healAmount);
void SetBattlerFieldStatusForSwitchin(enum BattlerId battler);
bool32 ShouldInstructPartner(enum BattlerId partner, enum Move move);
bool32 CanMoveBeBouncedBack(enum BattlerId battler, enum Move move);

View File

@ -76,7 +76,7 @@ extern s16 gBattleAnimArgs[ANIM_ARGS_COUNT];
extern u8 gAnimMoveTurn;
extern enum BattlerId gBattleAnimAttacker;
extern enum BattlerId gBattleAnimTarget;
extern u16 gAnimBattlerSpecies[MAX_BATTLERS_COUNT];
extern enum Species gAnimBattlerSpecies[MAX_BATTLERS_COUNT];
extern u8 gAnimCustomPanning;
extern u16 gAnimMoveIndex;
@ -168,7 +168,7 @@ u32 GetBattleMonSpritePalettesMask(u8 playerLeft, u8 playerRight, u8 opponentLef
u8 GetSpritePalIdxByBattler(enum BattlerId battler);
s16 CloneBattlerSpriteWithBlend(enum AnimBattler animBattler);
void DestroySpriteWithActiveSheet(struct Sprite *sprite);
u8 CreateInvisibleSpriteCopy(int battler, u8 spriteId, int species);
u8 CreateInvisibleSpriteCopy(enum BattlerId battler, u8 spriteId, enum Species species);
void AnimLoadCompressedBgTilemapHandleContest(struct BattleAnimBgData *data, const void *src, bool32 largeScreen);
void AnimLoadCompressedBgGfx(u32 bgId, const u32 *src, u32 tilesOffset);
void UpdateAnimBg3ScreenSize(bool8 largeScreenSize);
@ -191,7 +191,7 @@ void PrepareAffineAnimInTaskData(struct Task *task, u8 spriteId, const union Aff
bool8 RunAffineAnimFromTaskData(struct Task *task);
void AnimThrowProjectile(struct Sprite *sprite);
void GetBgDataForTransform(struct BattleAnimBgData *out, enum BattlerId battler);
u8 CreateAdditionalMonSpriteForMoveAnim(u16 species, bool8 isBackpic, u8 id, s16 x, s16 y, u8 subpriority, u32 personality, bool8 isShiny, enum BattlerId battler);
u8 CreateAdditionalMonSpriteForMoveAnim(enum Species species, bool32 isBackpic, u8 id, s16 x, s16 y, u8 subpriority, u32 personality, bool32 isShiny, enum BattlerId battler);
void ResetSpriteRotScale_PreserveAffine(struct Sprite *sprite);
void Trade_MoveSelectedMonToTarget(struct Sprite *sprite);
void DestroyAnimVisualTaskAndDisableBlend(u8 taskId);
@ -422,7 +422,7 @@ u8 SmokescreenImpact(s16 x, s16 y, bool8 persist);
u32 UnpackSelectedBattlePalettes(s16 selector);
u8 GetBattlerSpriteFinal_Y(enum BattlerId battler, u16 species, bool8 a3);
u8 GetBattlerSpriteFinal_Y(enum BattlerId battler, enum Species species, bool32 a3);
extern const struct OamData gOamData_AffineOff_ObjNormal_8x16;
extern const struct OamData gOamData_AffineNormal_ObjBlend_16x16;

View File

@ -220,7 +220,7 @@ struct ChooseMoveStruct
enum Move moves[MAX_MON_MOVES];
u8 currentPp[MAX_MON_MOVES];
u8 maxPp[MAX_MON_MOVES];
u16 species;
enum Species species;
enum Type monTypes[3];
struct ZMoveData zmove;
};

View File

@ -12,8 +12,8 @@ bool8 TryHandleLaunchBattleTableAnimation(u8 activeBattlerId, u8 attacker, u8 ta
void InitAndLaunchSpecialAnimation(enum BattlerId activeBattlerId, enum BattlerId attacker, enum BattlerId target, u8 tableId);
bool8 IsBattleSEPlaying(enum BattlerId battler);
void BattleLoadMonSpriteGfx(struct Pokemon *mon, enum BattlerId battler);
void DecompressGhostFrontPic(u32 battler);
void BattleGfxSfxDummy2(u16 species);
void DecompressGhostFrontPic(enum BattlerId battler);
void BattleGfxSfxDummy2(enum Species species);
void DecompressTrainerFrontPic(u16 frontPicId, enum BattlerId battler);
void DecompressTrainerBackPic(enum TrainerPicID backPicId, enum BattlerId battler);
void FreeTrainerFrontPicPalette(u16 frontPicId);
@ -36,7 +36,7 @@ void SetBattlerSpriteAffineMode(u8 affineMode);
void CreateEnemyShadowSprite(enum BattlerId battler);
void LoadAndCreateEnemyShadowSprites(void);
void SpriteCB_SetInvisible(struct Sprite *sprite);
void SetBattlerShadowSpriteCallback(enum BattlerId battler, u16 species);
void SetBattlerShadowSpriteCallback(enum BattlerId battler, enum Species species);
void HideBattlerShadowSprite(enum BattlerId battler);
void FillAroundBattleWindows(void);
void ClearTemporarySpeciesSpriteData(enum BattlerId battler, bool32 dontClearTransform, bool32 dontClearSubstitute);

View File

@ -9,8 +9,8 @@
// For displaying a multi battle partner's Pokémon in the party menu
struct MultiPartnerMenuPokemon
{
/*0x00*/ u16 species;
/*0x02*/ u16 heldItem;
/*0x00*/ enum Species species;
/*0x02*/ enum Item heldItem;
/*0x04*/ u8 nickname[POKEMON_NAME_LENGTH + 1];
/*0x0F*/ u8 level;
/*0x10*/ u16 hp;
@ -109,7 +109,7 @@ void SetTypeBeforeUsingMove(enum Move move, enum BattlerId battler);
bool32 IsWildMonSmart(void);
u8 CreateNPCTrainerPartyFromTrainer(struct Pokemon *party, const struct Trainer *trainer, bool32 firstTrainer, u32 battleTypeFlags);
void ModifyPersonalityForNature(u32 *personality, u32 newNature);
u32 GeneratePersonalityForGender(u32 gender, u32 species);
u32 GeneratePersonalityForGender(u32 gender, enum Species species);
void CustomTrainerPartyAssignMoves(struct Pokemon *mon, const struct TrainerMon *partyEntry);
bool32 CanPlayerForfeitNormalTrainerBattle(void);
bool32 DidPlayerForfeitNormalTrainerBattle(void);

View File

@ -159,6 +159,7 @@ extern const u8 BattleScript_MoveEffectToxic[];
extern const u8 BattleScript_MoveEffectPayDay[];
extern const u8 BattleScript_MoveEffectWrap[];
extern const u8 BattleScript_MoveEffectConfusion[];
extern const u8 BattleScript_MoveEffectRecoilHP25[];
extern const u8 BattleScript_MoveEffectRecoil[];
extern const u8 BattleScript_FaintAttackerForExplosion[];
extern const u8 BattleScript_MaxHp50Recoil[];
@ -410,7 +411,6 @@ extern const u8 BattleScript_MysteriousAirCurrentBlowsOn[];
extern const u8 BattleScript_AttackWeakenedByStrongWinds[];
extern const u8 BattleScript_BlockedByPrimalWeather[];
extern const u8 BattleScript_PrimalReversion[];
extern const u8 BattleScript_HyperspaceFuryRemoveProtect[];
extern const u8 BattleScript_SelectingNotAllowedMoveGorillaTactics[];
extern const u8 BattleScript_SelectingNotAllowedMoveGorillaTacticsInPalace[];
extern const u8 BattleScript_WanderingSpiritActivates[];
@ -456,12 +456,12 @@ extern const u8 BattleScript_DampPreventsAftermath[];
extern const u8 BattleScript_HealingWishActivates[];
extern const u8 BattleScript_LunarDanceActivates[];
extern const u8 BattleScript_ShellTrapSetUp[];
extern const u8 BattleScript_StealthRockActivates[];
extern const u8 BattleScript_MoveEffectStealthRock[];
extern const u8 BattleScript_CouldntFullyProtect[];
extern const u8 BattleScript_TargetAvoidsAttack[];
extern const u8 BattleScript_TargetAvoidsAttackConsumeFlingItem[];
extern const u8 BattleScript_MoveEffectStockpileWoreOff[];
extern const u8 BattleScript_SpikesActivates[];
extern const u8 BattleScript_MoveEffectSpikes[];
extern const u8 BattleScript_BerserkGeneRet[];
extern const u8 BattleScript_TargetFormChangeWithStringNoPopup[];
extern const u8 BattleScript_DefDown[];
@ -478,7 +478,7 @@ extern const u8 BattleScript_TheRainbowDisappeared[];
extern const u8 BattleScript_HurtByTheSeaOfFire[];
extern const u8 BattleScript_TheSeaOfFireDisappeared[];
extern const u8 BattleScript_TheSwampDisappeared[];
extern const u8 BattleScript_EffectPsychicNoise[];
extern const u8 BattleScript_MoveEffectPsychicNoise[];
extern const u8 BattleScript_AromaVeilProtectsRet[];
extern const u8 BattleScript_LowerAtkSpAtk[];
extern const u8 BattleScript_Terastallization[];
@ -536,16 +536,15 @@ extern const u8 BattleScript_EffectExtremeEvoboost[];
// max moves
extern const u8 BattleScript_EffectRaiseStatAllies[];
extern const u8 BattleScript_EffectLowerStatFoes[];
extern const u8 BattleScript_EffectSetWeather[];
extern const u8 BattleScript_EffectSetTerrain[];
extern const u8 BattleScript_EffectSteelsurge[];
extern const u8 BattleScript_DamageNonTypesStarts[];
extern const u8 BattleScript_MoveEffectSetWeather[];
extern const u8 BattleScript_MoveEffectSetTerrain[];
extern const u8 BattleScript_MoveEffectSteelsurge[];
extern const u8 BattleScript_MoveEffectDamageNonTypes[];
extern const u8 BattleScript_DamageNonTypesContinues[];
extern const u8 BattleScript_MoveEffectDefog[];
extern const u8 BattleScript_MoveEffectAuroraVeil[];
extern const u8 BattleScript_EffectGravitySuccess[];
extern const u8 BattleScript_MoveEffectYawnSide[];
extern const u8 BattleScript_EffectTryReducePP[];
extern const u8 BattleScript_MoveEffectGravity[];
extern const u8 BattleScript_MoveEffectYawnFoe[];
extern const u8 BattleScript_MoveEffectSpite[];
extern const u8 BattleScript_EffectParalyzeSide[];
extern const u8 BattleScript_EffectPoisonSide[];
extern const u8 BattleScript_EffectPoisonParalyzeSide[];
@ -775,8 +774,7 @@ extern const u8 BattleScript_EffectCoaching[];
extern const u8 BattleScript_EffectDecorate[];
extern const u8 BattleScript_EffectStruggle[];
extern const u8 BattleScript_EffectStuffCheeks[];
extern const u8 BattleScript_MoveEffectLightScreen[];
extern const u8 BattleScript_MoveEffectReflect[];
extern const u8 BattleScript_MoveEffectScreens[];
extern const u8 BattleScript_MoveEffectLeechSeed[];
extern const u8 BattleScript_MoveEffectHaze[];
extern const u8 BattleScript_MoveEffectIonDeluge[];

View File

@ -121,6 +121,8 @@ struct BattleContext
enum HoldEffect holdEffectAtk;
enum HoldEffect holdEffectDef;
u8 aiTurnOrder[MAX_BATTLERS_COUNT];
// Flags
u32 isCrit:1;
u32 randomFactor:1;
@ -166,7 +168,6 @@ enum SubCheck
};
void HandleAction_ThrowBall(void);
uq4_12_t CalcTypeEffectivenessMultiplierHelper(enum Move move, enum Type moveType, enum BattlerId battlerAtk, enum BattlerId battlerDef, enum Ability abilityAtk, enum Ability abilityDef, bool32 recordAbilities);
u32 GetCurrentBattleWeather(void);
bool32 EndOrContinueWeather(void);
enum DamageCategory GetReflectDamageMoveDamageCategory(enum BattlerId battler, enum Move move);
@ -212,7 +213,6 @@ void TryClearRageAndFuryCutter(void);
bool32 HasNoMonsToSwitch(enum BattlerId battler, u8 partyIdBattlerOn1, u8 partyIdBattlerOn2);
bool32 TryChangeBattleWeather(enum BattlerId battler, u32 battleWeatherId, enum Ability ability);
bool32 TryChangeBattleTerrain(enum BattlerId battler, u32 statusFlag);
bool32 CanAbilityBlockMove(enum BattlerId battlerAtk, enum BattlerId battlerDef, enum Ability abilityAtk, enum Ability abilityDef, u32 move, enum ResultOption option);
bool32 CanTargetBlockPranksterMove(struct BattleContext *ctx, s32 movePriority);
bool32 CanPsychicTerrainProtectTarget(struct BattleContext *ctx, s32 movePriority);
bool32 CanMoveBeBlockedByTarget(struct BattleContext *ctx, s32 movePriority);
@ -258,7 +258,7 @@ s32 CalculateMoveDamageVars(struct BattleContext *ctx);
s32 DoFixedDamageMoveCalc(struct BattleContext *ctx);
s32 ApplyModifiersAfterDmgRoll(struct BattleContext *ctx, s32 dmg);
uq4_12_t CalcTypeEffectivenessMultiplier(struct BattleContext *ctx);
uq4_12_t CalcPartyMonTypeEffectivenessMultiplier(enum Move move, u16 speciesDef, enum Ability abilityDef);
uq4_12_t CalcPartyMonTypeEffectivenessMultiplier(enum Move move, enum Species speciesDef, enum Ability abilityDef);
uq4_12_t GetTypeModifier(enum Type atkType, enum Type defType);
uq4_12_t GetOverworldTypeEffectiveness(struct Pokemon *mon, enum Type moveType);
void UpdateMoveResultFlags(uq4_12_t modifier, u16 *resultFlags);
@ -271,14 +271,14 @@ void ActivateUltraBurst(enum BattlerId battler);
bool32 IsBattlerMegaEvolved(enum BattlerId battler);
bool32 IsBattlerPrimalReverted(enum BattlerId battler);
bool32 IsBattlerUltraBursted(enum BattlerId battler);
u32 GetBattleFormChangeTargetSpecies(enum BattlerId battler, enum FormChanges method, enum Ability ability);
enum Species GetBattleFormChangeTargetSpecies(enum BattlerId battler, enum FormChanges method, enum Ability ability);
bool32 TryRevertPartyMonFormChange(u32 partyIndex);
bool32 TryBattleFormChange(enum BattlerId battler, enum FormChanges method, enum Ability ability);
bool32 DoBattlersShareType(enum BattlerId battler1, enum BattlerId battler2);
bool32 CanBattlerGetOrLoseItem(enum BattlerId fromBattler, enum BattlerId battler, enum Item itemId);
u32 GetBattlerVisualSpecies(enum BattlerId battler);
enum Species GetBattlerVisualSpecies(enum BattlerId battler);
bool32 TryClearIllusion(enum BattlerId battler, enum Ability ability);
u32 GetIllusionMonSpecies(enum BattlerId battler);
enum Species GetIllusionMonSpecies(enum BattlerId battler);
struct Pokemon *GetIllusionMonPtr(enum BattlerId battler);
void ClearIllusionMon(enum BattlerId battler);
u32 GetIllusionMonPartyId(struct Pokemon *party, struct Pokemon *mon, struct Pokemon *partnerMon, enum BattlerId battler);
@ -289,7 +289,7 @@ uq4_12_t GetBadgeBoostModifier(void);
enum DamageCategory GetBattleMoveCategory(enum Move move);
void SetDynamicMoveCategory(enum BattlerId battlerAtk, enum BattlerId battlerDef, enum Move move);
bool32 CanFling(enum BattlerId battlerAtk, enum Ability abilityAtk);
bool32 IsTelekinesisBannedSpecies(u16 species);
bool32 IsTelekinesisBannedSpecies(enum Species species);
bool32 IsHealBlockPreventingMove(enum BattlerId battler, enum Move move);
bool32 IsGravityPreventingMove(enum Move move);
bool32 IsBelchPreventingMove(enum BattlerId battler, enum Move move);
@ -422,6 +422,7 @@ bool32 CanUseMoveConsecutively(enum BattlerId battler);
void TryResetConsecutiveUseCounter(enum BattlerId battler);
void SetOrClearRageVolatile(void);
enum BattlerId GetTargetBySlot(enum BattlerId battlerAtk, enum BattlerId battlerDef);
bool32 IsNaturalEnemy(u32 speciesAttacker, u32 speciesTarget);
bool32 IsNaturalEnemy(enum Species speciesAttacker, enum Species speciesTarget);
enum Stat GetDownloadStat(enum BattlerId battler);
#endif // GUARD_BATTLE_UTIL_H

View File

@ -5,7 +5,7 @@
struct SignatureZMove
{
u16 species;
enum Species species;
enum Item item;
enum Move move;
enum Move zmove;
@ -18,7 +18,7 @@ void ActivateZMove(enum BattlerId battler);
bool32 IsViableZMove(enum BattlerId battler, enum Move move);
bool32 TryChangeZTrigger(enum BattlerId battler, u32 moveIndex);
enum Move GetTypeBasedZMove(enum Move move);
enum Move GetSignatureZMove(enum Move move, u32 species, enum Item item);
enum Move GetSignatureZMove(enum Move move, enum Species species, enum Item item);
bool32 MoveSelectionDisplayZMove(enum Move zmove, enum BattlerId battler);
void SetZEffect(void);
void AssignUsableZMoves(enum BattlerId battler, enum Move *moves);

View File

@ -46,6 +46,8 @@
#define SHOULD_SWITCH_NATURAL_CURE_WEAK_STATS_RAISED_PERCENTAGE 10
#define SHOULD_SWITCH_REGENERATOR_PERCENTAGE 50
#define SHOULD_SWITCH_REGENERATOR_STATS_RAISED_PERCENTAGE 20
#define SHOULD_SWITCH_INTIMIDATE_PERCENTAGE 25
#define SHOULD_SWITCH_INTIMIDATE_STATS_RAISED_PERCENTAGE 10
// AI switchin considerations
#define ALL_MOVES_BAD_STATUS_MOVES_BAD FALSE // If the AI has no moves that affect the target, ShouldSwitchIfAllMovesBad can prompt a switch. Enabling this config will ignore status moves that can affect the target when making this decision.
@ -84,6 +86,21 @@
#define AI_DAMAGES_THROUGH_BERRIES TRUE // AI will see through resist berries when considering a certain KO threshold for the purposes damage calcs; this is considered when comparing best moves to KO to still pick the actual OHKO if needed
#define AI_IGNORE_BERRY_KO_THRESHOLD 2 // KO threshold AI must meet in order to treat it berry though it doesn't exist (ie. 2 means "If the AI can 2HKO with berry resisted attack + not-berry resisted next attack, ignore berry resistence when calcing first attack"). Requires AI_DAMAGES_THROUGH_BERRIES
// AI damage calc roll considerations
#define AI_ROLL_MIN 1
#define AI_ROLL_MEDIAN 2
#define AI_ROLL_MAX 3
#define AI_ROLL_RANDOM 4
#define AI_ROLL_TYPE_COUNT 5
// Define which roll type to use in each context; overridden by AI_FLAG_RISKY and AI_FLAG_CONSERVATIVE
#define AI_ROLL_ATTACKING AI_ROLL_MAX
#define AI_ROLL_DEFENDING AI_ROLL_MEDIAN
#define AI_ROLL_SWITCHIN_ATTACKING AI_ROLL_MEDIAN
#define AI_ROLL_SWITCHIN_DEFENDING AI_ROLL_MEDIAN
#define AI_ROLL_SHOULD_SETUP_DEFENDING AI_ROLL_MAX
#define AI_ROLL_ATTACKING_PARTNER AI_ROLL_MAX
// AI prediction chances
#define PREDICT_SWITCH_CHANCE 50
#define PREDICT_MOVE_CHANCE 100

View File

@ -56,6 +56,7 @@
#define B_TAILWIND_TURNS GEN_LATEST // In Gen5+, Tailwind lasts 4 turns instead of 3.
#define B_SLEEP_TURNS GEN_LATEST // In Gen5+, sleep lasts for 2-4 turns instead of 2-5 turns.
#define B_TAUNT_TURNS GEN_LATEST // In Gen5+, Taunt lasts 3 turns if the user acts before the target, or 4 turns if the target acted before the user. In Gen3, taunt lasts 2 turns and in Gen 4, 3-5 turns.
#define B_ENCORE_TURNS GEN_LATEST // In Gen5+, Encore lasts 3 turns if the target hasn't yet moved this turn, or 4 turns if it has. In Gen4, it lasts 3-7 turns. In Gen2-3, 2-6 turns.
#define B_SPORT_TURNS GEN_LATEST // In Gen6+, Water/Mud Sport last 5 turns, even if the user switches out.
#define B_MEGA_EVO_TURN_ORDER GEN_LATEST // In Gen7, a Pokémon's Speed after Mega Evolution is used to determine turn order, not its Speed before.
#define B_RECALC_TURN_AFTER_ACTIONS GEN_LATEST // In Gen8+, switching/using a move affects the current turn's order of actions, better known as dynamic speed.

View File

@ -1,7 +1,7 @@
#ifndef GUARD_GENERATIONAL_CHANGES_H
#define GUARD_GENERATIONAL_CHANGES_H
#ifndef GUARD_CONFIG_CHANGES_H
#define GUARD_CONFIG_CHANGES_H
#include "constants/generational_changes.h"
#include "constants/config_changes.h"
#include "config/battle.h"
#include "config/pokerus.h"
#include "config/ai.h"
@ -30,4 +30,4 @@ void TestInitConfigData(void);
void TestFreeConfigData(void);
#endif
#endif // GUARD_GENERATIONAL_CHANGES_H
#endif // GUARD_CONFIG_CHANGES_H

View File

@ -4,8 +4,6 @@
#define PARTNER_NONE 0
#define PARTNER_STEVEN 1
#define PARTNER_DUMMY 2
#define PARTNER_COUNT 3
//Tests need PARTNER_COUNT to be at least 3 so we add a dummy partner
#define PARTNER_COUNT 2
#endif // GUARD_CONSTANTS_BATTLE_PARTNERS_H

View File

@ -822,6 +822,13 @@ enum ProtectLikeUsedStringID
B_MSG_PROTECTED_TEAM,
};
// gBrokeProtectionStringIds
enum BrokeProtectionStringID
{
B_MSG_FEINT,
B_MSG_HYPERSPACE_FURY,
};
// gRestUsedStringIds
enum RestUsedStringID
{
@ -920,7 +927,7 @@ enum SportsUsedStringID
// gCaughtMonStringIds
enum CaughtMonStringID
{
B_MSG_NO_MESSSAGE_SKIP,
B_MSG_NO_MESSAGE_SKIP,
// "Lanette's" should always follow "someone's"
B_MSG_SENT_SOMEONES_PC,
B_MSG_SENT_LANETTES_PC,

View File

@ -1,5 +1,5 @@
#ifndef GUARD_CONSTANTS_GENERATIONAL_CHANGES_H
#define GUARD_CONSTANTS_GENERATIONAL_CHANGES_H
#ifndef GUARD_CONSTANTS_CONFIG_CHANGES_H
#define GUARD_CONSTANTS_CONFIG_CHANGES_H
/* Config definitions */
#define BATTLE_CONFIG_DEFINITIONS(F) \
@ -55,6 +55,7 @@
F(B_TAILWIND_TURNS, tailwindTurns, (u32, GEN_COUNT - 1)) \
F(B_SLEEP_TURNS, sleepTurns, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
F(B_TAUNT_TURNS, tauntTurns, (u32, GEN_COUNT - 1)) \
F(B_ENCORE_TURNS, encoreTurns, (u32, GEN_COUNT - 1)) \
F(B_SPORT_TURNS, sportTurns, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
F(B_MEGA_EVO_TURN_ORDER, megaEvoTurnOrder, (u32, GEN_COUNT - 1)) \
F(B_RECALC_TURN_AFTER_ACTIONS, recalcTurnAfterActions, (u32, GEN_COUNT - 1)) \
@ -232,6 +233,7 @@
F(POKERUS_WEAK_VARIANT, pokerusWeakVariant, (u32, TRUE)) \
#define AI_CONFIG_DEFINITIONS(F) \
F(AI_ROLL_ATTACKING, aiRollAttacking, (u32, AI_ROLL_TYPE_COUNT - 1)) \
#define GET_CONFIG_MAXIMUM(_typeMaxValue, ...) INVOKE_WITH_B(GET_CONFIG_MAXIMUM_, _typeMaxValue)
#define GET_CONFIG_MAXIMUM_(_type, ...) FIRST(__VA_OPT__(FIRST(__VA_ARGS__),) MAX_BITS((sizeof(_type) * 8)))
@ -246,4 +248,4 @@ enum ConfigTag
CONFIG_COUNT
};
#endif // GUARD_CONSTANTS_GENERATIONAL_CHANGES_H
#endif // GUARD_CONSTANTS_CONFIG_CHANGES_H

View File

@ -6,6 +6,9 @@ enum DifficultyLevel
DIFFICULTY_EASY,
DIFFICULTY_NORMAL, //If you rename this, the word "Normal" in fprint_trainers must be replaced with the new difficulty name.
DIFFICULTY_HARD,
#if TESTING
DIFFICULTY_TEST,
#endif
DIFFICULTY_COUNT,
};

View File

@ -103,7 +103,6 @@ enum Language
#define MAX_REMATCH_ENTRIES 100 // only REMATCH_TABLE_ENTRIES (78) are used
#define NUM_CONTEST_WINNERS 13
#define UNION_ROOM_KB_ROW_COUNT 10
#define GIFT_RIBBONS_COUNT 11
#define SAVED_TRENDS_COUNT 5
#define PYRAMID_BAG_ITEMS_COUNT 10
#define ROAMER_COUNT 1 // Number of maximum concurrent active roamers

File diff suppressed because it is too large Load Diff

View File

@ -87,7 +87,7 @@ enum {
struct ContestPokemon
{
u16 species;
enum Species species;
u8 nickname[POKEMON_NAME_LENGTH + 1];
u8 trainerName[PLAYER_NAME_LENGTH + 1];
u8 trainerGfxId;
@ -124,8 +124,8 @@ struct ContestTempSave
struct ContestMoveAnimData
{
u16 species;
u16 targetSpecies;
enum Species species;
enum Species targetSpecies;
bool8 hasTargetAnim:1;
u8 isShiny:1;
u8 targetIsShiny:1;
@ -355,7 +355,7 @@ void SetContestants(enum ContestCategories contestType, u8 rank);
void SetLinkAIContestants(enum ContestCategories contestType, u8 rank, bool32 isPostgame);
u8 GetContestEntryEligibility(struct Pokemon *pkmn);
void CalculateRound1Points(enum ContestCategories contestCategory);
bool8 IsSpeciesNotUnown(u16 species);
bool8 IsSpeciesNotUnown(enum Species species);
bool8 Contest_IsMonsTurnDisabled(u8 contestant);
void SaveLinkContestResults(void);
void SortContestants(bool8 useRanking);

View File

@ -63,8 +63,8 @@ struct TrainerMon
const u8 *ev;
u32 iv;
enum Move moves[MAX_MON_MOVES];
u16 species;
u16 heldItem;
enum Species species;
enum Item heldItem;
enum Ability ability;
u8 lvl;
enum PokeBall ball:8;

View File

@ -2,6 +2,7 @@
#define GUARD_DAYCARE_H
#include "constants/daycare.h"
#include "constants/species.h"
struct RecordMixingDaycareMail
{
@ -21,10 +22,10 @@ void GetDaycareCost(void);
u8 GetNumLevelsGainedFromDaycare(void);
void TriggerPendingDaycareEgg(void);
void RejectEggFromDayCare(void);
void CreateEgg(struct Pokemon *mon, u16 species, bool8 setHotSpringsLocation);
void CreateEgg(struct Pokemon *mon, enum Species species, bool8 setHotSpringsLocation);
void GiveEggFromDaycare(void);
bool8 ShouldEggHatch(void);
u16 GetSelectedMonNicknameAndSpecies(void);
enum Species GetSelectedMonNicknameAndSpecies(void);
void GetDaycareMonNicknames(void);
u8 GetDaycareState(void);
u8 GetDaycareCompatibilityScore(struct DayCare *daycare);
@ -32,8 +33,8 @@ void SetDaycareCompatibilityString(void);
bool8 NameHasGenderSymbol(const u8 *name, u8 genderRatio);
void ShowDaycareLevelMenu(void);
void ChooseSendDaycareMon(void);
u8 GetEggMovesBySpecies(u16 species, u16 *eggMoves);
bool8 SpeciesCanLearnEggMove(u16 species, enum Move move);
u8 GetEggMovesBySpecies(enum Species species, u16 *eggMoves);
bool8 SpeciesCanLearnEggMove(enum Species species, enum Move move);
void StorePokemonInDaycare(struct Pokemon *mon, struct DaycareMon *daycareMon);
u8 GetEggMoves(struct Pokemon *pokemon, u16 *eggMoves);

View File

@ -76,11 +76,11 @@ bool8 LoadCompressedSpriteSheetUsingHeap(const struct CompressedSpriteSheet *src
void DecompressPicFromTable(const struct CompressedSpriteSheet *src, void *buffer);
void HandleLoadSpecialPokePic(bool32 isFrontPic, void *dest, s32 species, u32 personality);
void HandleLoadSpecialPokePicIsEgg(bool32 isFrontPic, void *dest, s32 species, u32 personality, bool32 isEgg);
void HandleLoadSpecialPokePic(bool32 isFrontPic, void *dest, enum Species species, u32 personality);
void HandleLoadSpecialPokePicIsEgg(bool32 isFrontPic, void *dest, enum Species species, u32 personality, bool32 isEgg);
void LoadSpecialPokePic(void *dest, s32 species, u32 personality, bool8 isFrontPic);
void LoadSpecialPokePicIsEgg(void *dest, s32 species, u32 personality, bool8 isFrontPic, bool32 isEgg);
void LoadSpecialPokePic(void *dest, enum Species species, u32 personality, bool8 isFrontPic);
void LoadSpecialPokePicIsEgg(void *dest, enum Species species, u32 personality, bool8 isFrontPic, bool32 isEgg);
u32 GetDecompressedDataSize(const u32 *ptr);
bool32 IsCompressedData(const u32 *ptr);

View File

@ -79,6 +79,6 @@ u32 CalculateDexNavShinyRolls(void);
void IncrementDexNavChain(void);
bool32 OnStep_DexNavSearch(void);
extern u16 gDexNavSpecies;
extern enum Species gDexNavSpecies;
#endif // GUARD_DEXNAV_H

View File

@ -146,7 +146,7 @@ void ClearObjectEventMovement(struct ObjectEvent *objectEvent, struct Sprite *sp
void ObjectEventClearHeldMovement(struct ObjectEvent *objectEvent);
void ObjectEventClearHeldMovementIfActive(struct ObjectEvent *objectEvent);
struct Pokemon *GetFirstLiveMon(void);
u16 GetOverworldWeatherSpecies(u16 species);
enum Species GetOverworldWeatherSpecies(enum Species species);
void UpdateFollowingPokemon(void);
void RemoveFollowingPokemon(void);
struct ObjectEvent *GetFollowerObject(void);
@ -263,7 +263,7 @@ bool8 IsBerryTreeSparkling(u8 localId, u8 mapNum, u8 mapGroup);
const struct ObjectEventTemplate *GetObjectEventTemplateByLocalIdAndMap(u8 localId, u8 mapNum, u8 mapGroup);
u8 TrySpawnObjectEventTemplate(const struct ObjectEventTemplate *objectEventTemplate, u8 mapNum, u8 mapGroup, s16 cameraX, s16 cameraY);
bool8 GetFollowerInfo(u32 *species, bool32 *shiny, bool32 *female);
const struct ObjectEventGraphicsInfo *SpeciesToGraphicsInfo(u32 species, bool32 shiny, bool32 female);
const struct ObjectEventGraphicsInfo *SpeciesToGraphicsInfo(enum Species species, bool32 shiny, bool32 female);
u16 GetObjectEventFlagIdByLocalIdAndMap(u8 localId, u8 mapNum, u8 mapGroup);
void CopyObjectGraphicsInfoToSpriteTemplate(u16 graphicsId, void (*callback)(struct Sprite *), struct SpriteTemplate *spriteTemplate, const struct SubspriteTable **subspriteTables);

View File

@ -630,6 +630,8 @@ extern const u8 EventScript_SelectWithoutRegisteredItem[];
extern const u8 EventScript_WhiteOut[];
extern const u8 EventScript_AfterWhiteOutMomHeal[];
extern const u8 EventScript_AfterWhiteOutHeal[];
extern const u8 EventScript_AfterWhiteOutHeal_Frlg[];
extern const u8 EventScript_AfterWhiteOutHealMsgPreFirstBoss[];
extern const u8 EventScript_ResetMrBriney[];
extern const u8 EventScript_DoLinkRoomExit[];
extern const u8 CableClub_EventScript_TooBusyToNotice[];

View File

@ -6,8 +6,8 @@ void LoadEvoSparkleSpriteAndPal(void);
u8 EvolutionSparkles_SpiralUpward(u16 palNum);
u8 EvolutionSparkles_ArcDown(void);
u8 EvolutionSparkles_CircleInward(void);
u8 EvolutionSparkles_SprayAndFlash(u16 species);
u8 EvolutionSparkles_SprayAndFlash_Trade(u16 species);
u8 EvolutionSparkles_SprayAndFlash(enum Species species);
u8 EvolutionSparkles_SprayAndFlash_Trade(enum Species species);
u8 CycleEvolutionMonSprite(u8 preEvoSpriteId, u8 postEvoSpriteId);
#endif // GUARD_EVOLUTION_GRAPHICS_H

View File

@ -1,9 +1,11 @@
#ifndef GUARD_EVOLUTION_SCENE_H
#define GUARD_EVOLUTION_SCENE_H
void BeginEvolutionScene(struct Pokemon *mon, u16 postEvoSpecies, bool8 canStopEvo, u8 partyId);
void EvolutionScene(struct Pokemon *mon, u16 postEvoSpecies, bool8 canStopEvo, u8 partyId);
void TradeEvolutionScene(struct Pokemon *mon, u16 postEvoSpecies, u8 preEvoSpriteId, u8 partyId);
#include "constants/species.h"
void BeginEvolutionScene(struct Pokemon *mon, enum Species postEvoSpecies, bool32 canStopEvo, u8 partyId);
void EvolutionScene(struct Pokemon *mon, enum Species postEvoSpecies, bool32 canStopEvo, u8 partyId);
void TradeEvolutionScene(struct Pokemon *mon, enum Species postEvoSpecies, u8 preEvoSpriteId, u8 partyId);
extern void (*gCB2_AfterEvolution)(void);

View File

@ -47,7 +47,7 @@ void SpriteCB_AshLaunch(struct Sprite *sprite);
void MultiplyPaletteRGBComponents(u16 i, u8 r, u8 g, u8 b);
void FreeResourcesAndDestroySprite(struct Sprite *sprite, u8 spriteId);
u8 CreateMonSprite_PicBox(u16 species, s16 x, s16 y, u8 subpriority);
u8 CreateMonSprite_PicBox(enum Species species, s16 x, s16 y, u8 subpriority);
void StartEscapeRopeFieldEffect(void);
void FieldEffectFreeGraphicsResources(struct Sprite *sprite);
bool8 IsRockClimbActive(void);

View File

@ -1,6 +1,8 @@
#ifndef GUARD_FIELD_SPECIALS_H
#define GUARD_FIELD_SPECIALS_H
#include "constants/species.h"
extern bool8 gBikeCyclingChallenge;
extern u8 gBikeCollisions;
extern u16 gScrollableMultichoice_ScrollOffset;
@ -35,7 +37,7 @@ void SetPCBoxToSendMon(u8 boxId);
void PreparePartyForSkyBattle(void);
void GetObjectPosition(u16*, u16*, u32, u32);
bool32 CheckObjectAtXY(u32, u32);
bool32 CheckPartyHasSpecies(u32);
bool32 CheckPartyHasSpecies(enum Species);
bool8 CutMoveRuinValleyCheck(void);
void CutMoveOpenDottedHoleDoor(void);

View File

@ -1,6 +1,8 @@
#ifndef GUARD_FRONTIER_UTIL_H
#define GUARD_FRONTIER_UTIL_H
#include "constants/species.h"
void CallFrontierUtilFunc(void);
u8 GetFrontierBrainStatus(void);
void CopyFrontierTrainerText(u8 whichText, u16 trainerId);
@ -18,7 +20,7 @@ void CopyFrontierBrainTrainerName(u8 *dst);
bool8 IsFrontierBrainFemale(void);
void SetFrontierBrainObjEventGfx_2(void);
void CreateFrontierBrainPokemon(void);
u16 GetFrontierBrainMonSpecies(u8 monId);
enum Species GetFrontierBrainMonSpecies(u8 monId);
void SetFrontierBrainObjEventGfx(u8 facility);
u16 GetFrontierBrainMonMove(u8 monId, u8 moveSlotId);
u8 GetFrontierBrainMonNature(u8 monId);

View File

@ -331,7 +331,7 @@ struct BerryCrush
struct ApprenticeMon
{
u16 species;
enum Species species;
enum Move moves[MAX_MON_MOVES];
enum Item item;
};
@ -356,8 +356,8 @@ struct Apprentice
struct BattleTowerPokemon
{
u16 species;
u16 heldItem;
enum Species species;
enum Item heldItem;
enum Move moves[MAX_MON_MOVES];
u8 level;
u8 ppBonuses;
@ -399,8 +399,8 @@ struct EmeraldBattleTowerRecord
struct BattleTowerInterview
{
u16 playerSpecies;
u16 opponentSpecies;
enum Species playerSpecies;
enum Species opponentSpecies;
u8 opponentName[PLAYER_NAME_LENGTH + 1];
u8 opponentMonNickname[VANILLA_POKEMON_NAME_LENGTH + 1];
u8 opponentLanguage;
@ -630,8 +630,8 @@ struct SecretBaseParty
{
u32 personality[PARTY_SIZE];
enum Move moves[PARTY_SIZE * MAX_MON_MOVES];
u16 species[PARTY_SIZE];
u16 heldItems[PARTY_SIZE];
enum Species species[PARTY_SIZE];
enum Item heldItems[PARTY_SIZE];
u8 levels[PARTY_SIZE];
u8 EVs[PARTY_SIZE];
};
@ -691,7 +691,7 @@ struct Roamer
{
/*0x00*/ u32 ivs;
/*0x04*/ u32 personality;
/*0x08*/ u16 species;
/*0x08*/ enum Species species;
/*0x0A*/ u16 hp;
/*0x0C*/ u8 level;
/*0x0D*/ u8 statusA;
@ -838,7 +838,7 @@ struct ContestWinner
{
u32 personality;
u32 trainerId;
u16 species;
enum Species species;
u8 contestCategory;
u8 monName[VANILLA_POKEMON_NAME_LENGTH + 1];
u8 trainerName[PLAYER_NAME_LENGTH + 1];
@ -852,7 +852,7 @@ struct Mail
/*0x00*/ u16 words[MAIL_WORDS_COUNT];
/*0x12*/ u8 playerName[PLAYER_NAME_LENGTH + 1];
/*0x1A*/ u8 trainerId[TRAINER_ID_LENGTH];
/*0x1E*/ u16 species;
/*0x1E*/ enum Species species;
/*0x20*/ enum Item itemId;
};
@ -998,7 +998,7 @@ struct WonderNews
struct WonderCard
{
u16 flagId; // Event flag (sReceivedGiftFlags) + WONDER_CARD_FLAG_OFFSET
u16 iconSpecies;
enum Species iconSpecies;
u32 idNumber;
u8 type:2; // CARD_TYPE_*
u8 bgType:4;
@ -1017,7 +1017,7 @@ struct WonderCardMetadata
u16 battlesWon;
u16 battlesLost;
u16 numTrades;
u16 iconSpecies;
enum Species iconSpecies;
u16 stampData[2][MAX_STAMP_CARD_STAMPS]; // First element is STAMP_SPECIES, second is STAMP_ID
};
@ -1144,7 +1144,7 @@ struct SaveBlock1
/*0x27CC*/ TVShow tvShows[TV_SHOWS_COUNT];
/*0x27CA*/ //u8 padding4[2];
/*0x2B50*/ PokeNews pokeNews[POKE_NEWS_COUNT];
/*0x2B90*/ u16 outbreakPokemonSpecies;
/*0x2B90*/ enum Species outbreakPokemonSpecies;
/*0x2B92*/ u8 outbreakLocationMapNum;
/*0x2B93*/ u8 outbreakLocationMapGroup;
/*0x2B94*/ u8 outbreakPokemonLevel;
@ -1169,7 +1169,8 @@ struct SaveBlock1
#if FREE_LINK_BATTLE_RECORDS == FALSE
/*0x3150*/ struct LinkBattleRecords linkBattleRecords;
#endif //FREE_LINK_BATTLE_RECORDS
/*0x31A8*/ u8 giftRibbons[GIFT_RIBBONS_COUNT];
/*0x31A8*/ u8 giftRibbons[NUM_GIFT_RIBBONS];
u8 padding[4];
/*0x31B3*/ struct ExternalEventData externalEventData;
/*0x31C7*/ struct ExternalEventFlags externalEventFlags;
/*0x31DC*/ struct Roamer roamer[ROAMER_COUNT];

View File

@ -32,7 +32,7 @@ typedef union // size = 0x24
struct {
/*0x00*/ u8 kind;
/*0x01*/ bool8 active;
/*0x02*/ u16 species;
/*0x02*/ enum Species species;
/*0x04*/ u16 words[6];
/*0x10*/ u8 playerName[PLAYER_NAME_LENGTH + 1];
/*0x18*/ u8 language;
@ -43,7 +43,7 @@ typedef union // size = 0x24
struct {
/*0x00*/ u8 kind;
/*0x01*/ bool8 active;
/*0x02*/ u16 species;
/*0x02*/ enum Species species;
/*0x04*/ u16 words[6];
/*0x10*/ u8 playerName[PLAYER_NAME_LENGTH + 1];
/*0x18*/ u8 language;
@ -54,7 +54,7 @@ typedef union // size = 0x24
struct {
/*0x00*/ u8 kind;
/*0x01*/ bool8 active;
/*0x02*/ u16 species;
/*0x02*/ enum Species species;
/*0x04*/ u8 friendshipHighNybble:4;
u8 questionAsked:4;
/*0x05*/ u8 playerName[PLAYER_NAME_LENGTH + 1];
@ -71,7 +71,7 @@ typedef union // size = 0x24
/*0x00*/ u8 kind;
/*0x01*/ bool8 active;
/*0x02*/ u16 words[2];
/*0x06*/ u16 species;
/*0x06*/ enum Species species;
/*0x08*/ u8 filler_08[3];
/*0x0B*/ u8 name[12];
/*0x17*/ u8 language;
@ -81,13 +81,13 @@ typedef union // size = 0x24
struct {
/*0x00*/ u8 kind;
/*0x01*/ bool8 active;
/*0x02*/ u16 species;
/*0x02*/ enum Species species;
/*0x04*/ u8 pokemonName[VANILLA_POKEMON_NAME_LENGTH + 1];
/*0x0F*/ u8 trainerName[PLAYER_NAME_LENGTH + 1];
/*0x17*/ u8 unused[3];
/*0x1A*/ u8 random;
/*0x1B*/ u8 random2;
/*0x1C*/ u16 randomSpecies;
/*0x1C*/ enum Species randomSpecies;
/*0x1E*/ u8 language;
/*0x1F*/ u8 pokemonNameLanguage;
} nameRaterShow;
@ -96,7 +96,7 @@ typedef union // size = 0x24
struct {
/*0x00*/ u8 kind;
/*0x01*/ bool8 active;
/*0x02*/ u16 species;
/*0x02*/ enum Species species;
/*0x04*/ u16 words[2];
/*0x08*/ u8 pokemonNickname[VANILLA_POKEMON_NAME_LENGTH + 1];
/*0x13*/ u8 contestCategory:3;
@ -114,9 +114,9 @@ typedef union // size = 0x24
/*0x00*/ u8 kind;
/*0x01*/ bool8 active;
/*0x02*/ u8 playerName[PLAYER_NAME_LENGTH + 1];
/*0x0A*/ u16 species;
/*0x0A*/ enum Species species;
/*0x0C*/ u8 opponentName[PLAYER_NAME_LENGTH + 1];
/*0x14*/ u16 defeatedSpecies;
/*0x14*/ enum Species defeatedSpecies;
/*0x16*/ u16 numFights;
/*0x18*/ u16 words[1];
/*0x1A*/ u8 btLevel;
@ -131,14 +131,14 @@ typedef union // size = 0x24
struct {
/*0x00*/ u8 kind;
/*0x01*/ bool8 active;
/*0x02*/ u16 losingSpecies;
/*0x02*/ enum Species losingSpecies;
/*0x04*/ u8 losingTrainerName[PLAYER_NAME_LENGTH + 1];
/*0x0C*/ u8 loserAppealFlag;
/*0x0D*/ u8 round1Placing;
/*0x0E*/ u8 round2Placing;
/*0x0F*/ u8 winnerAppealFlag;
/*0x10*/ enum Move move;
/*0x12*/ u16 winningSpecies;
/*0x12*/ enum Species winningSpecies;
/*0x14*/ u8 winningTrainerName[PLAYER_NAME_LENGTH + 1];
/*0x1C*/ u8 category;
/*0x1D*/ u8 winningTrainerLanguage;
@ -164,11 +164,11 @@ typedef union // size = 0x24
struct {
/*0x00*/ u8 kind;
/*0x01*/ bool8 active;
/*0x02*/ u16 speciesOpponent;
/*0x02*/ enum Species speciesOpponent;
/*0x04*/ u8 playerName[PLAYER_NAME_LENGTH + 1];
/*0x0C*/ u8 linkOpponentName[PLAYER_NAME_LENGTH + 1];
/*0x14*/ enum Move move;
/*0x16*/ u16 speciesPlayer;
/*0x16*/ enum Species speciesPlayer;
/*0x18*/ u8 battleType;
/*0x19*/ u8 language;
/*0x1A*/ u8 linkOpponentLanguage;
@ -211,7 +211,7 @@ typedef union // size = 0x24
/*0x03*/ u8 language2;
/*0x04*/ u8 nickname[VANILLA_POKEMON_NAME_LENGTH + 1];
/*0x0F*/ u8 ball;
/*0x10*/ u16 species;
/*0x10*/ enum Species species;
/*0x12*/ u8 nBallsUsed;
/*0x13*/ u8 playerName[PLAYER_NAME_LENGTH + 1];
/*0x1B*/ //u8 padding;
@ -237,8 +237,8 @@ typedef union // size = 0x24
/*0x01*/ bool8 active;
/*0x02*/ u8 language;
/*0x03*/ u8 filler_03[9];
/*0x0C*/ u16 species;
/*0x0E*/ u16 species2;
/*0x0C*/ enum Species species;
/*0x0E*/ enum Species species2;
/*0x10*/ u8 nBallsUsed;
/*0x11*/ u8 outcome;
/*0x12*/ mapsec_u8_t location;
@ -252,7 +252,7 @@ typedef union // size = 0x24
/*0x01*/ bool8 active;
/*0x02*/ u8 nBites;
/*0x03*/ u8 nFails;
/*0x04*/ u16 species;
/*0x04*/ enum Species species;
/*0x06*/ u8 language;
/*0x07*/ u8 filler_07[12];
/*0x13*/ u8 playerName[PLAYER_NAME_LENGTH + 1];
@ -266,7 +266,7 @@ typedef union // size = 0x24
/*0x02*/ u16 numPokeCaught;
/*0x04*/ u16 caughtPoke;
/*0x06*/ u16 steps;
/*0x08*/ u16 species;
/*0x08*/ enum Species species;
/*0x0A*/ mapsec_u8_t location;
/*0x0B*/ u8 language;
/*0x0C*/ u8 filler_0C[7];
@ -335,12 +335,12 @@ typedef union // size = 0x24
struct {
/*0x00*/ u8 kind;
/*0x01*/ bool8 active;
/*0x02*/ u16 lastOpponentSpecies;
/*0x02*/ enum Species lastOpponentSpecies;
/*0x04*/ mapsec_u8_t location;
/*0x05*/ u8 outcome;
/*0x06*/ u16 caughtMonBall;
/*0x08*/ u16 balls;
/*0x0A*/ u16 poke1Species;
/*0x0A*/ enum Species poke1Species;
/*0x0C*/ u16 lastUsedMove;
/*0x0E*/ u8 language;
/*0x0F*/ u8 filler_0f[4];
@ -355,7 +355,7 @@ typedef union // size = 0x24
/*0x02*/ u8 avgLevel;
/*0x03*/ u8 numDecorations;
/*0x04*/ u8 decorations[4];
/*0x08*/ u16 species;
/*0x08*/ enum Species species;
/*0x0A*/ enum Move move;
/*0x0C*/ u8 language;
/*0x0D*/ u8 filler_0d[6];
@ -380,8 +380,8 @@ typedef union // size = 0x24
/*0x00*/ u8 kind;
/*0x01*/ bool8 active;
/*0x02*/ enum Move move;
/*0x04*/ u16 foeSpecies;
/*0x06*/ u16 species;
/*0x04*/ enum Species foeSpecies;
/*0x06*/ enum Species species;
/*0x08*/ u16 otherMoves[3];
/*0x0E*/ u16 betterMove;
/*0x10*/ u8 nOtherMoves;
@ -421,10 +421,10 @@ typedef union // size = 0x24
/*0x00*/ u8 kind;
/*0x01*/ bool8 active;
/*0x02*/ u16 winStreak;
/*0x04*/ u16 species1;
/*0x06*/ u16 species2;
/*0x08*/ u16 species3;
/*0x0A*/ u16 species4;
/*0x04*/ enum Species species1;
/*0x06*/ enum Species species2;
/*0x08*/ enum Species species3;
/*0x0A*/ enum Species species4;
/*0x0C*/ u8 language;
/*0x0D*/ u8 facilityAndMode;
/*0x0E*/ u8 filler_0e[5];
@ -478,7 +478,7 @@ typedef union // size = 0x24
/*0x02*/ u8 unused1;
/*0x03*/ u8 unused3;
/*0x04*/ enum Move moves[MAX_MON_MOVES];
/*0x0C*/ u16 species;
/*0x0C*/ enum Species species;
/*0x0E*/ u16 unused2;
/*0x10*/ u8 locationMapNum;
/*0x11*/ u8 locationMapGroup;

View File

@ -1525,6 +1525,7 @@ extern const u16 gItemIconPalette_GhostTMHM[];
extern const u16 gItemIconPalette_DragonTMHM[];
extern const u16 gItemIconPalette_DarkTMHM[];
extern const u16 gItemIconPalette_SteelTMHM[];
extern const u16 gItemIconPalette_MysteryTMHM[];
extern const u16 gItemIconPalette_FairyTMHM[];
// Charms
extern const u32 gItemIcon_OvalCharm[];

View File

@ -13,7 +13,7 @@ int GetStringWidthDifference(int fontId, const u8 *str, int totalWidth, int lett
int GetMaxWidthInMenuTable(const struct MenuAction *actions, int numActions);
int GetMaxWidthInSubsetOfMenuTable(const struct MenuAction *actions, const u8 *actionIds, int numActions);
int Intl_GetListMenuWidth(const struct ListMenuTemplate *listMenu);
void CopyMonCategoryText(u16 species, u8 *dest);
void CopyMonCategoryText(enum Species species, u8 *dest);
u8 *GetStringClearToWidth(u8 *dest, int fontId, const u8 *str, int totalStringWidth);
void PadNameString(u8 *dest, u8 padChar);
void ConvertInternationalPlayerNameStripChar(u8 *str, u8 removeChar);

View File

@ -4,6 +4,7 @@
#include "librfu.h"
#include "link.h"
#include "AgbRfu_LinkManager.h"
#include "constants/species.h"
#define RFUCMD_MASK 0xFF00
@ -103,7 +104,7 @@ struct __attribute__((packed, aligned(2))) RfuGameData
{
struct RfuGameCompatibilityData compatibility;
u8 partnerInfo[RFU_CHILD_MAX];
u16 tradeSpecies;
enum Species tradeSpecies;
u8 activity:7;
u8 startedActivity:1;
u8 playerGender:1;
@ -294,7 +295,7 @@ void UpdateGameData_SetActivity(u8 activity, u32 partnerInfo, bool32 startedActi
void CreateTask_RfuReconnectWithParent(const u8 *name, u16 trainerId);
void SetHostRfuWonderFlags(bool32 hasNews, bool32 hasCard);
void ResetHostRfuGameData(void);
void SetTradeBoardRegisteredMonInfo(u32 type, u32 species, u32 level);
void SetTradeBoardRegisteredMonInfo(u32 type, enum Species species, u32 level);
void InitializeRfuLinkManager_EnterUnionRoom(void);
void TryConnectToUnionRoomParent(const u8 *name, struct RfuGameData *parent, u8 activity);
bool32 IsUnionRoomListenTaskActive(void);

View File

@ -24,7 +24,7 @@ void ClearAllMail(void);
void ClearMail(struct Mail *mail);
bool8 MonHasMail(struct Pokemon *mon);
u8 GiveMailToMonByItemId(struct Pokemon *mon, enum Item itemId);
u16 SpeciesToMailSpecies(u16 species, u32 personality);
u16 SpeciesToMailSpecies(enum Species species, u32 personality);
u16 MailSpeciesToSpecies(u16 mailSpecies, u16 *buffer);
u8 GiveMailToMon(struct Pokemon *mon, struct Mail *mail);
void TakeMailFromMon(struct Pokemon *mon);

View File

@ -1,7 +1,7 @@
#ifndef GUARD_MOVES_H
#define GUARD_MOVES_H
#include "generational_changes.h"
#include "config_changes.h"
#include "contest_effect.h"
#include "constants/battle.h"
#include "constants/battle_factory.h"
@ -164,7 +164,7 @@ struct MoveInfo
};
} twoTurnAttack;
struct {
u16 species;
enum Species species;
u16 power:9;
u16 numOfHits:7;
} speciesPowerOverride;

View File

@ -2,6 +2,7 @@
#define GUARD_NAMING_SCREEN_H
#include "main.h"
#include "constants/species.h"
enum {
NAMING_SCREEN_PLAYER,
@ -15,6 +16,6 @@ enum {
extern void BattleMainCB2(void);
void DoNamingScreen(u8 templateNum, u8 *destBuffer, u16 monSpecies, u16 monGender, u32 monPersonality, MainCallback returnCallback);
void DoNamingScreen(u8 templateNum, u8 *destBuffer, u16 monSpeciesOrPlayerGender, u16 monGender, u32 monPersonality, MainCallback returnCallback);
#endif // GUARD_NAMING_SCREEN_H

View File

@ -9,7 +9,7 @@ enum GeneratedMonOrigin
GIFTMON_ORIGIN
};
u32 GetSynchronizedNature(enum GeneratedMonOrigin origin, u32 species);
u32 GetSynchronizedGender(enum GeneratedMonOrigin origin, u32 species);
u32 GetSynchronizedNature(enum GeneratedMonOrigin origin, enum Species species);
u32 GetSynchronizedGender(enum GeneratedMonOrigin origin, enum Species species);
#endif // GUARD_OW_SYNCHRONIZE_H

View File

@ -26,7 +26,7 @@ extern const struct PokeBallSprite gPokeBalls[];
#define POKEBALL_PLAYER_SLIDEIN 0xFD
u8 DoPokeballSendOutAnimation(enum BattlerId battler, s16 pan, u8 kindOfThrow);
void CreatePokeballSpriteToReleaseMon(u8 monSpriteId, u8 monPalNum, u8 x, u8 y, u8 oamPriority, u8 subpriority, u8 delay, u32 fadePalettes, u16 species);
void CreatePokeballSpriteToReleaseMon(u8 monSpriteId, u8 monPalNum, u8 x, u8 y, u8 oamPriority, u8 subpriority, u8 delay, u32 fadePalettes, enum Species species);
u8 CreateTradePokeballSprite(u8 monSpriteId, u8 monPalNum, u8 x, u8 y, u8 oamPriority, u8 subPriority, u8 delay, u32 fadePalettes);
void StartHealthboxSlideIn(enum BattlerId battler);
void DoHitAnimHealthboxEffect(enum BattlerId battler);

View File

@ -9,10 +9,10 @@ u16 GetNationalPokedexCount(u8 caseID);
u32 GetRegionalPokedexCount(u8 caseID);
u16 GetHoennPokedexCount(u8 caseID);
u16 GetKantoPokedexCount(u8 caseID);
u8 DisplayCaughtMonDexPage(u16 species, bool32 isShiny, u32 personality);
u32 Pokedex_CreateCaughtMonSprite(u32 species, s32 x, s32 y);
u8 DisplayCaughtMonDexPage(enum Species species, bool32 isShiny, u32 personality);
u32 Pokedex_CreateCaughtMonSprite(enum Species species, s32 x, s32 y);
s8 GetSetPokedexFlag(enum NationalDexOrder nationalDexNo, u8 caseID);
void DrawFootprint(u8 windowId, u16 species);
void DrawFootprint(u8 windowId, enum Species species);
u16 CreateMonSpriteFromNationalDexNumber(enum NationalDexOrder nationalNum, s16 x, s16 y, u16 paletteSlot);
bool16 HasAllRegionalMons(void);
bool16 HasAllHoennMons(void);
@ -20,7 +20,7 @@ bool16 HasAllKantoMons(void);
void ResetPokedexScrollPositions(void);
bool16 HasAllMons(void);
void CB2_OpenPokedex(void);
void PrintMonMeasurements(u16 species, u32 owned);
void PrintMonMeasurements(enum Species species, u32 owned);
u8* ConvertMonHeightToString(u32 height);
u8* ConvertMonWeightToString(u32 weight);

View File

@ -11,7 +11,7 @@ enum PokedexAreaScreenState
DEX_UPDATE_AREA_SCREEN
};
void DisplayPokedexAreaScreen(u16 species, u8 *screenSwitchState, enum TimeOfDay timeOfDay, enum PokedexAreaScreenState areaState);
void ShowPokedexAreaScreen(u16 species, u8 *screenSwitchState);
void DisplayPokedexAreaScreen(enum Species species, u8 *screenSwitchState, enum TimeOfDay timeOfDay, enum PokedexAreaScreenState areaState);
void ShowPokedexAreaScreen(enum Species species, u8 *screenSwitchState);
#endif // GUARD_POKEDEX_AREA_SCREEN_H

View File

@ -14,7 +14,7 @@ extern u8 gDexCryScreenState;
bool8 LoadCryWaveformWindow(struct CryScreenWindow *window, u8 windowId);
void UpdateCryWaveformWindow(u8 windowId);
void CryScreenPlayButton(u16 species);
void CryScreenPlayButton(enum Species species);
bool8 LoadCryMeter(struct CryScreenWindow *window, u8 windowId);
void FreeCryScreen(void);

View File

@ -336,7 +336,7 @@ struct Volatiles
struct BattlePokemon
{
/*0x00*/ u16 species;
/*0x00*/ enum Species species;
/*0x02*/ u16 attack;
/*0x04*/ u16 defense;
/*0x06*/ u16 speed;
@ -383,7 +383,7 @@ struct Evolution
{
u16 method;
u16 param;
u16 targetSpecies;
enum Species targetSpecies;
const struct EvolutionParam *params;
};
@ -623,7 +623,7 @@ struct LevelUpMove
struct FormChange
{
u16 method;
u16 targetSpecies;
enum Species targetSpecies;
u16 param1;
u16 param2;
u16 param3;
@ -633,7 +633,7 @@ struct FormChange
struct FormChangeContext
{
enum FormChanges method:16;
u16 currentSpecies;
enum Species currentSpecies;
u16 partyItemUsed;
u16 multichoiceSelection;
u16 heldItem;
@ -730,16 +730,16 @@ void ZeroBoxMonData(struct BoxPokemon *boxMon);
void ZeroMonData(struct Pokemon *mon);
void ZeroPlayerPartyMons(void);
void ZeroEnemyPartyMons(void);
u32 GetMonPersonality(u16 species, u8 gender, u8 nature, u8 unownLetter);
void CreateMon(struct Pokemon *mon, u16 species, u8 level, u32 personality, struct OriginalTrainerId);
void CreateRandomMon(struct Pokemon *mon, u16 species, u8 level);
void CreateRandomMonWithIVs(struct Pokemon *mon, u16 species, u8 level, u8 fixedIv);
void CreateBoxMon(struct BoxPokemon *boxMon, u16 species, u8 level, u32 personality, struct OriginalTrainerId);
void CreateMonWithIVs(struct Pokemon *mon, u16 species, u8 level, u32 personality, struct OriginalTrainerId trainerId, u8 fixedIV);
u32 GetMonPersonality(enum Species species, u8 gender, u8 nature, u8 unownLetter);
void CreateMon(struct Pokemon *mon, enum Species species, u8 level, u32 personality, struct OriginalTrainerId);
void CreateRandomMon(struct Pokemon *mon, enum Species species, u8 level);
void CreateRandomMonWithIVs(struct Pokemon *mon, enum Species species, u8 level, u8 fixedIv);
void CreateBoxMon(struct BoxPokemon *boxMon, enum Species species, u8 level, u32 personality, struct OriginalTrainerId);
void CreateMonWithIVs(struct Pokemon *mon, enum Species species, u8 level, u32 personality, struct OriginalTrainerId trainerId, u8 fixedIV);
void SetBoxMonIVs(struct BoxPokemon *mon, u8 fixedIV);
void SetBoxMonPerfectIVs(struct BoxPokemon *mon, u32 numPerfect);
void CreateMaleMon(struct Pokemon *mon, u16 species, u8 level);
void CreateMonWithIVsPersonality(struct Pokemon *mon, u16 species, u8 level, u32 ivs, u32 personality);
void CreateMaleMon(struct Pokemon *mon, enum Species species, u8 level);
void CreateMonWithIVsPersonality(struct Pokemon *mon, enum Species species, u8 level, u32 ivs, u32 personality);
void CreateBattleTowerMon(struct Pokemon *mon, struct BattleTowerPokemon *src);
void CreateBattleTowerMon_HandleLevel(struct Pokemon *mon, struct BattleTowerPokemon *src, bool8 lvl50);
void CreateApprenticeMon(struct Pokemon *mon, const struct Apprentice *src, u8 monId);
@ -769,10 +769,10 @@ u8 CountAliveMonsInBattle(u8 caseId, enum BattlerId battler);
u8 GetDefaultMoveTarget(enum BattlerId battler);
u8 GetMonGender(struct Pokemon *mon);
u8 GetBoxMonGender(struct BoxPokemon *boxMon);
u8 GetGenderFromSpeciesAndPersonality(u16 species, u32 personality);
bool32 IsPersonalityFemale(u16 species, u32 personality);
u8 GetGenderFromSpeciesAndPersonality(enum Species species, u32 personality);
bool32 IsPersonalityFemale(enum Species species, u32 personality);
u32 GetUnownSpeciesId(u32 personality);
void SetMultiuseSpriteTemplateToPokemon(u16 speciesTag, enum BattlerPosition battlerPosition);
void SetMultiuseSpriteTemplateToPokemon(enum Species speciesTag, enum BattlerPosition battlerPosition);
void SetMultiuseSpriteTemplateToTrainerBack(enum TrainerPicID trainerPicId, enum BattlerPosition battlerPosition);
void SetMultiuseSpriteTemplateToTrainerFront(enum TrainerPicID trainerPicId, enum BattlerPosition battlerPosition);
@ -798,33 +798,33 @@ u8 CalculateEnemyPartyCount(void);
u8 CalculateEnemyPartyCountInSide(enum BattlerId battler);
u8 GetMonsStateToDoubles(void);
u8 GetMonsStateToDoubles_2(void);
enum Ability GetAbilityBySpecies(u16 species, u8 abilityNum);
enum Ability GetAbilityBySpecies(enum Species species, u8 abilityNum);
enum Ability GetMonAbility(struct Pokemon *mon);
void CreateSecretBaseEnemyParty(struct SecretBase *secretBaseRecord);
enum TrainerPicID GetSecretBaseTrainerPicIndex(void);
enum TrainerClassID GetSecretBaseTrainerClass(void);
bool8 IsPlayerPartyAndPokemonStorageFull(void);
bool8 IsPokemonStorageFull(void);
const u8 *GetSpeciesName(u16 species);
const u8 *GetSpeciesCategory(u16 species);
const u8 *GetSpeciesPokedexDescription(u16 species);
u32 GetSpeciesHeight(u16 species);
u32 GetSpeciesWeight(u16 species);
enum Type GetSpeciesType(u16 species, u8 slot);
enum Ability GetSpeciesAbility(u16 species, u8 slot);
u32 GetSpeciesBaseHP(u16 species);
u32 GetSpeciesBaseAttack(u16 species);
u32 GetSpeciesBaseDefense(u16 species);
u32 GetSpeciesBaseSpAttack(u16 species);
u32 GetSpeciesBaseSpDefense(u16 species);
u32 GetSpeciesBaseSpeed(u16 species);
u32 GetSpeciesBaseStat(u16 species, u32 statIndex);
const struct LevelUpMove *GetSpeciesLevelUpLearnset(u16 species);
const u16 *GetSpeciesTeachableLearnset(u16 species);
const u16 *GetSpeciesEggMoves(u16 species);
const struct Evolution *GetSpeciesEvolutions(u16 species);
const u16 *GetSpeciesFormTable(u16 species);
const struct FormChange *GetSpeciesFormChanges(u16 species);
const u8 *GetSpeciesName(enum Species species);
const u8 *GetSpeciesCategory(enum Species species);
const u8 *GetSpeciesPokedexDescription(enum Species species);
u32 GetSpeciesHeight(enum Species species);
u32 GetSpeciesWeight(enum Species species);
enum Type GetSpeciesType(enum Species species, u8 slot);
enum Ability GetSpeciesAbility(enum Species species, u8 slot);
u32 GetSpeciesBaseHP(enum Species species);
u32 GetSpeciesBaseAttack(enum Species species);
u32 GetSpeciesBaseDefense(enum Species species);
u32 GetSpeciesBaseSpAttack(enum Species species);
u32 GetSpeciesBaseSpDefense(enum Species species);
u32 GetSpeciesBaseSpeed(enum Species species);
u32 GetSpeciesBaseStat(enum Species species, u32 statIndex);
const struct LevelUpMove *GetSpeciesLevelUpLearnset(enum Species species);
const u16 *GetSpeciesTeachableLearnset(enum Species species);
const u16 *GetSpeciesEggMoves(enum Species species);
const struct Evolution *GetSpeciesEvolutions(enum Species species);
const u16 *GetSpeciesFormTable(enum Species species);
const struct FormChange *GetSpeciesFormChanges(enum Species species);
u8 CalculatePPWithBonus(enum Move move, u8 ppBonuses, u8 moveIndex);
void RemoveMonPPBonus(struct Pokemon *mon, u8 moveIndex);
void RemoveBoxMonPPBonus(struct BoxPokemon *mon, u8 moveIndex);
@ -838,23 +838,23 @@ u8 GetItemEffectParamOffset(enum BattlerId battler, enum Item itemId, u8 effectB
u8 *UseStatIncreaseItem(enum Item itemId);
u8 GetNature(struct Pokemon *mon);
u8 GetNatureFromPersonality(u32 personality);
u32 GetGMaxTargetSpecies(u32 species);
enum Species GetGMaxTargetSpecies(enum Species species);
bool32 DoesMonMeetAdditionalConditions(struct Pokemon *mon, const struct EvolutionParam *params, struct Pokemon *tradePartner, u32 partyId, bool32 *canStopEvo, enum EvoState evoState);
u32 GetEvolutionTargetSpecies(struct Pokemon *mon, enum EvolutionMode mode, u16 evolutionItem, struct Pokemon *tradePartner, bool32 *canStopEvo, enum EvoState evoState);
enum Species GetEvolutionTargetSpecies(struct Pokemon *mon, enum EvolutionMode mode, u16 evolutionItem, struct Pokemon *tradePartner, bool32 *canStopEvo, enum EvoState evoState);
bool8 IsMonPastEvolutionLevel(struct Pokemon *mon);
u16 NationalPokedexNumToSpecies(enum NationalDexOrder nationalNum);
enum Species NationalPokedexNumToSpecies(enum NationalDexOrder nationalNum);
u32 NationalToRegionalOrder(enum NationalDexOrder nationalNum);
enum KantoDexOrder NationalToKantoOrder(enum NationalDexOrder nationalNum);
enum HoennDexOrder NationalToHoennOrder(enum NationalDexOrder nationalNum);
enum NationalDexOrder SpeciesToNationalPokedexNum(u16 species);
u32 SpeciesToRegionalPokedexNum(u16 species);
enum KantoDexOrder SpeciesToKantoPokedexNum(u16 species);
enum HoennDexOrder SpeciesToHoennPokedexNum(u16 species);
enum NationalDexOrder SpeciesToNationalPokedexNum(enum Species species);
u32 SpeciesToRegionalPokedexNum(enum Species species);
enum KantoDexOrder SpeciesToKantoPokedexNum(enum Species species);
enum HoennDexOrder SpeciesToHoennPokedexNum(enum Species species);
enum NationalDexOrder RegionalToNationalOrder(u32 regionNum);
enum NationalDexOrder KantoToNationalOrder(enum KantoDexOrder kantoNum);
enum NationalDexOrder HoennToNationalOrder(enum HoennDexOrder hoennNum);
void DrawSpindaSpots(u32 personality, u8 *dest, bool32 isSecondFrame);
void EvolutionRenameMon(struct Pokemon *mon, u16 oldSpecies, u16 newSpecies);
void EvolutionRenameMon(struct Pokemon *mon, enum Species oldSpecies, enum Species newSpecies);
u8 GetPlayerFlankId(void);
u16 GetLinkTrainerFlankId(u8 linkPlayerId);
s32 GetBattlerMultiplayerId(u16 id);
@ -862,27 +862,27 @@ u8 GetTrainerEncounterMusicId(u16 trainerOpponentId);
u16 ModifyStatByNature(u8 nature, u16 stat, enum Stat statIndex);
void AdjustFriendship(struct Pokemon *mon, u8 event);
u8 CalculateFriendshipBonuses(struct Pokemon *mon, u32 modifier, enum HoldEffect itemHoldEffect);
void MonGainEVs(struct Pokemon *mon, u16 defeatedSpecies);
void MonGainEVs(struct Pokemon *mon, enum Species defeatedSpecies);
u16 GetMonEVCount(struct Pokemon *mon);
bool8 TryIncrementMonLevel(struct Pokemon *mon);
u8 CanLearnTeachableMove(u16 species, enum Move move);
u8 GetLevelUpMovesBySpecies(u16 species, u16 *moves);
u16 SpeciesToPokedexNum(u16 species);
bool32 IsSpeciesInRegionalDex(u16 species);
bool32 IsSpeciesInKantoDex(u16 species);
bool32 IsSpeciesInHoennDex(u16 species);
u8 CanLearnTeachableMove(enum Species species, enum Move move);
u8 GetLevelUpMovesBySpecies(enum Species species, u16 *moves);
u16 SpeciesToPokedexNum(enum Species species);
bool32 IsSpeciesInRegionalDex(enum Species species);
bool32 IsSpeciesInKantoDex(enum Species species);
bool32 IsSpeciesInHoennDex(enum Species species);
u16 GetBattleBGM(void);
void PlayBattleBGM(void);
void PlayMapChosenOrBattleBGM(u16 songId);
void CreateTask_PlayMapChosenOrBattleBGM(u16 songId);
const u16 *GetMonFrontSpritePal(struct Pokemon *mon);
const u16 *GetMonSpritePalFromSpeciesAndPersonality(u16 species, bool32 isShiny, u32 personality);
const u16 *GetMonSpritePalFromSpeciesAndPersonalityIsEgg(u16 species, bool32 isShiny, u32 personality, bool32 isEgg);
const u16 *GetMonSpritePalFromSpecies(u16 species, bool32 isShiny, bool32 isFemale);
const u16 *GetMonSpritePalFromSpeciesIsEgg(u16 species, bool32 isShiny, bool32 isFemale, bool32 isEgg);
const u16 *GetMonSpritePalFromSpeciesAndPersonality(enum Species species, bool32 isShiny, u32 personality);
const u16 *GetMonSpritePalFromSpeciesAndPersonalityIsEgg(enum Species species, bool32 isShiny, u32 personality, bool32 isEgg);
const u16 *GetMonSpritePalFromSpecies(enum Species species, bool32 isShiny, bool32 isFemale);
const u16 *GetMonSpritePalFromSpeciesIsEgg(enum Species species, bool32 isShiny, bool32 isFemale, bool32 isEgg);
bool32 IsMoveHM(enum Move move);
bool32 CannotForgetMove(enum Move move);
bool8 IsMonSpriteNotFlipped(u16 species);
bool8 IsMonSpriteNotFlipped(enum Species species);
s8 GetMonFlavorRelation(struct Pokemon *mon, enum Flavor flavor);
s8 GetFlavorRelationByPersonality(u32 personality, enum Flavor flavor);
bool8 IsTradedMon(struct Pokemon *mon);
@ -893,28 +893,28 @@ void SetMonPreventsSwitchingString(void);
void SetWildMonHeldItem(void);
bool8 IsMonShiny(struct Pokemon *mon);
const u8 *GetTrainerPartnerName(void);
void BattleAnimateFrontSprite(struct Sprite *sprite, u16 species, bool8 noCry, u8 panMode);
void DoMonFrontSpriteAnimation(struct Sprite *sprite, u16 species, bool8 noCry, u8 panModeAnimFlag);
void PokemonSummaryDoMonAnimation(struct Sprite *sprite, u16 species, bool8 oneFrame);
void BattleAnimateFrontSprite(struct Sprite *sprite, enum Species species, bool8 noCry, u8 panMode);
void DoMonFrontSpriteAnimation(struct Sprite *sprite, enum Species species, bool8 noCry, u8 panModeAnimFlag);
void PokemonSummaryDoMonAnimation(struct Sprite *sprite, enum Species species, bool8 oneFrame);
void StopPokemonAnimationDelayTask(void);
void BattleAnimateBackSprite(struct Sprite *sprite, u16 species);
void BattleAnimateBackSprite(struct Sprite *sprite, enum Species species);
u8 GetOpposingLinkMultiBattlerId(bool8 rightSide, u8 multiplayerId);
enum TrainerPicID FacilityClassToPicIndex(u16 facilityClass);
enum TrainerPicID PlayerGenderToFrontTrainerPicId(enum Gender playerGender);
void HandleSetPokedexFlag(enum NationalDexOrder nationalNum, u8 caseId, u32 personality);
void HandleSetPokedexFlagFromMon(struct Pokemon *mon, u32 caseId);
bool8 HasTwoFramesAnimation(u16 species);
bool8 HasTwoFramesAnimation(enum Species species);
struct MonSpritesGfxManager *CreateMonSpritesGfxManager(u8 managerId, u8 mode);
void DestroyMonSpritesGfxManager(u8 managerId);
u8 *MonSpritesGfxManager_GetSpritePtr(u8 managerId, u8 spriteNum);
u16 GetFormSpeciesId(u16 speciesId, u8 formId);
u16 GetFormSpeciesId(enum Species speciesId, u8 formId);
u8 GetFormIdFromFormSpeciesId(u16 formSpeciesId);
u32 GetFormChangeTargetSpecies_Internal(struct FormChangeContext ctx);
bool32 DoesSpeciesHaveFormChangeMethod(u16 species, enum FormChanges method);
enum Species GetFormChangeTargetSpecies_Internal(struct FormChangeContext ctx);
bool32 DoesSpeciesHaveFormChangeMethod(enum Species species, enum FormChanges method);
u16 MonTryLearningNewMoveEvolution(struct Pokemon *mon, bool8 firstMove);
void RemoveIVIndexFromList(u8 *ivs, u8 selectedIv);
void TrySpecialOverworldEvo(void);
bool32 SpeciesHasGenderDifferences(u16 species);
bool32 SpeciesHasGenderDifferences(enum Species species);
bool32 TryFormChange(struct Pokemon *mon, enum FormChanges method);
bool32 TryBoxMonFormChange(struct BoxPokemon *boxMon, enum FormChanges method);
void TryToSetBattleFormChangeMoves(struct Pokemon *mon, enum FormChanges method);
@ -922,27 +922,27 @@ u32 GetMonFriendshipScore(struct Pokemon *pokemon);
u32 GetMonAffectionHearts(struct Pokemon *pokemon);
void UpdateMonPersonality(struct BoxPokemon *boxMon, u32 personality);
u8 CalculatePartyCount(struct Pokemon *party);
u16 SanitizeSpeciesId(u16 species);
bool32 IsSpeciesEnabled(u16 species);
enum PokemonCry GetCryIdBySpecies(u16 species);
u16 GetSpeciesPreEvolution(u16 species);
u16 SanitizeSpeciesId(enum Species species);
bool32 IsSpeciesEnabled(enum Species species);
enum PokemonCry GetCryIdBySpecies(enum Species species);
u16 GetSpeciesPreEvolution(enum Species species);
void HealPokemon(struct Pokemon *mon);
void HealBoxPokemon(struct BoxPokemon *boxMon);
void UpdateDaysPassedSinceFormChange(u16 days);
void TrySetDayLimitToFormChange(struct Pokemon *mon);
enum Type CheckDynamicMoveType(struct Pokemon *mon, enum Move move, enum BattlerId battler, enum MonState state);
uq4_12_t GetDynamaxLevelHPMultiplier(u32 dynamaxLevel, bool32 inverseMultiplier);
u32 GetRegionalFormByRegion(u32 species, u32 region);
bool32 IsSpeciesForeignRegionalForm(u32 species, u32 currentRegion);
u32 GetRegionalFormByRegion(enum Species species, u32 region);
bool32 IsSpeciesForeignRegionalForm(enum Species species, u32 currentRegion);
enum Type GetTeraTypeFromPersonality(struct Pokemon *mon);
bool8 ShouldSkipFriendshipChange(void);
struct Pokemon *GetSavedPlayerPartyMon(u32 index);
u8 *GetSavedPlayerPartyCount(void);
void SavePlayerPartyMon(u32 index, struct Pokemon *mon);
bool32 IsSpeciesOfType(u32 species, enum Type type);
bool32 IsSpeciesOfType(enum Species species, enum Type type);
struct BoxPokemon *GetSelectedBoxMonFromPcOrParty(void);
u32 GiveScriptedMonToPlayer(struct Pokemon *mon, u8 slot);
void ChangePokemonNicknameWithCallback(void (*callback)(void));
bool32 HasShedinjaHPHandling(u32 species);
bool32 HasShedinjaHPHandling(enum Species species);
#endif // GUARD_POKEMON_H

View File

@ -193,7 +193,7 @@ enum AnimFunctionIDs
ANIM_COUNT,
};
enum BackAnim GetSpeciesBackAnimSet(u16 species);
enum BackAnim GetSpeciesBackAnimSet(enum Species species);
void LaunchAnimationTaskForFrontSprite(struct Sprite *sprite, enum AnimFunctionIDs frontAnimId);
void StartMonSummaryAnimation(struct Sprite *sprite, enum AnimFunctionIDs frontAnimId);
void LaunchAnimationTaskForBackSprite(struct Sprite *sprite, enum BackAnim backAnimSet);

View File

@ -3,31 +3,31 @@
extern const struct SpritePalette gMonIconPaletteTable[];
const u8 *GetMonIconTiles(u16 species, u32 personality);
const u8 *GetMonIconTilesIsEgg(u16 species, u32 personality, bool32 isEgg);
const u8 *GetMonIconTiles(enum Species species, u32 personality);
const u8 *GetMonIconTilesIsEgg(enum Species species, u32 personality, bool32 isEgg);
void TryLoadAllMonIconPalettesAtOffset(u16 offset);
u8 GetValidMonIconPalIndex(u16 species);
const u8 *GetMonIconPtr(u16 species, u32 personality);
const u8 *GetMonIconPtrIsEgg(u16 species, u32 personality, bool32 isEgg);
const u16 *GetValidMonIconPalettePtr(u16 species);
u16 GetIconSpecies(u16 species, u32 personality);
u8 GetValidMonIconPalIndex(enum Species species);
const u8 *GetMonIconPtr(enum Species species, u32 personality);
const u8 *GetMonIconPtrIsEgg(enum Species species, u32 personality, bool32 isEgg);
const u16 *GetValidMonIconPalettePtr(enum Species species);
enum Species GetIconSpecies(enum Species species, u32 personality);
u16 GetUnownLetterByPersonality(u32 personality);
u16 GetIconSpeciesNoPersonality(u16 species);
enum Species GetIconSpeciesNoPersonality(enum Species species);
void LoadMonIconPalettes(void);
void LoadMonIconPalette(u16 species);
void LoadMonIconPalette(enum Species species);
void FreeMonIconPalettes(void);
u8 CreateMonIconNoPersonality(u16 species, void (*callback)(struct Sprite *), s16 x, s16 y, u8 subpriority);
u8 CreateMonIconNoPersonalityIsEgg(u16 species, void (*callback)(struct Sprite *), s16 x, s16 y, u8 subpriority, bool32 isEgg);
void FreeMonIconPalette(u16 species);
u8 CreateMonIconNoPersonality(enum Species species, void (*callback)(struct Sprite *), s16 x, s16 y, u8 subpriority);
u8 CreateMonIconNoPersonalityIsEgg(enum Species species, void (*callback)(struct Sprite *), s16 x, s16 y, u8 subpriority, bool32 isEgg);
void FreeMonIconPalette(enum Species species);
void FreeAndDestroyMonIconSprite(struct Sprite *sprite);
u8 CreateMonIcon(u16 species, void (*callback)(struct Sprite *), s16 x, s16 y, u8 subpriority, u32 personality);
u8 CreateMonIconIsEgg(u16 species, void (*callback)(struct Sprite *), s16 x, s16 y, u8 subpriority, u32 personality, bool32 isEgg);
u8 CreateMonIcon(enum Species species, void (*callback)(struct Sprite *), s16 x, s16 y, u8 subpriority, u32 personality);
u8 CreateMonIconIsEgg(enum Species species, void (*callback)(struct Sprite *), s16 x, s16 y, u8 subpriority, u32 personality, bool32 isEgg);
u8 UpdateMonIconFrame(struct Sprite *sprite);
void LoadMonIconPalette(u16 species);
void LoadMonIconPalettePersonality(u16 species, u32 personality);
void LoadMonIconPalette(enum Species species);
void LoadMonIconPalettePersonality(enum Species species, u32 personality);
void SpriteCB_MonIcon(struct Sprite *sprite);
void SetPartyHPBarSprite(struct Sprite *sprite, u8 animNum);
u8 GetMonIconPaletteIndexFromSpecies(u16 species);
void SafeFreeMonIconPalette(u16 species);
u8 GetMonIconPaletteIndexFromSpecies(enum Species species);
void SafeFreeMonIconPalette(enum Species species);
#endif // GUARD_POKEMON_ICON_H

View File

@ -4,7 +4,7 @@
#include "main.h"
void StartPokemonJump(u16 partyId, MainCallback exitCallback);
bool32 IsSpeciesAllowedInPokemonJump(u16 species);
bool32 IsSpeciesAllowedInPokemonJump(enum Species species);
void IsPokemonJumpSpeciesInParty(void);
void ResetPokemonJumpRecords(void);
void ShowPokemonJumpRecords(void);

View File

@ -161,6 +161,7 @@ enum RandomTag
RNG_SHED_SKIN,
RNG_SLEEP_TURNS,
RNG_TAUNT_TURNS,
RNG_ENCORE_TURNS,
RNG_SPEED_TIE,
RNG_STATIC,
RNG_STENCH,
@ -187,6 +188,7 @@ enum RandomTag
RNG_AI_SWITCH_ABSORBING_STAY_IN,
RNG_AI_SWITCH_NATURAL_CURE,
RNG_AI_SWITCH_REGENERATOR,
RNG_AI_SWITCH_INTIMIDATE,
RNG_AI_SWITCH_ENCORE,
RNG_AI_SWITCH_CHOICE_LOCKED,
RNG_AI_SWITCH_STATS_LOWERED,
@ -243,6 +245,7 @@ enum RandomTag
RNG_FISHING_GEN3_STICKY,
RNG_WILD_MON_TARGET,
RNG_AI_FAKE_OUT_SAVE_ALLY,
RNG_AI_DMG_ROLL_RANDOM,
};
#define RandomWeighted(tag, ...) \

View File

@ -12,7 +12,7 @@ bool8 TryStartRoamerEncounter(void);
void UpdateRoamerHPStatus(struct Pokemon *mon);
void SetRoamerInactive(u32 roamerIndex);
void GetRoamerLocation(u32 roamerIndex, u8 *mapGroup, u8 *mapNum);
bool8 TryAddRoamer(u16 species, u8 level);
bool8 TryAddRoamer(enum Species species, u8 level);
void MoveAllRoamersToOtherLocationSets(void);
void MoveAllRoamers(void);

View File

@ -37,7 +37,7 @@ bool8 ScriptMenu_MultichoiceWithDefault(u8 left, u8 top, u8 multichoiceId, bool8
void DrawMultichoiceMenuInternal(u8 left, u8 top, u8 multichoiceId, bool8 ignoreBPress, u8 cursorPos, const struct MenuAction *actions, int count);
bool8 ScriptMenu_YesNo(u8 left, u8 top);
bool8 ScriptMenu_MultichoiceGrid(u8 left, u8 top, u8 multichoiceId, bool8 ignoreBPress, u8 columnCount);
bool8 ScriptMenu_ShowPokemonPic(u16 species, u8 x, u8 y);
bool8 ScriptMenu_ShowPokemonPic(enum Species species, u8 x, u8 y);
bool8 (*ScriptMenu_HidePokemonPic(void))(void);
int ConvertPixelWidthToTileWidth(int width);
u8 CreateWindowFromRect(u8 x, u8 y, u8 width, u8 height);

View File

@ -1,10 +1,10 @@
#ifndef GUARD_SCRIPT_POKEMON_UTIL_H
#define GUARD_SCRIPT_POKEMON_UTIL_H
u32 ScriptGiveMon(u16 species, u8 level, enum Item item);
u8 ScriptGiveEgg(u16 species);
void CreateScriptedWildMon(u16 species, u8 level, enum Item item);
void CreateScriptedDoubleWildMon(u16 species, u8 level, enum Item item, u16 species2, u8 level2, enum Item item2);
u32 ScriptGiveMon(enum Species species, u8 level, enum Item item);
u8 ScriptGiveEgg(enum Species species);
void CreateScriptedWildMon(enum Species species, u8 level, enum Item item);
void CreateScriptedDoubleWildMon(enum Species species, u8 level, enum Item item, enum Species species2, u8 level2, enum Item item2);
void ScriptSetMonMoveSlot(u8 monIndex, enum Move move, u8 slot);
void ReducePlayerPartyToSelectedMons(void);
void HealPlayerParty(void);

View File

@ -24,13 +24,13 @@ bool8 IsBGMPausedOrStopped(void);
void FadeInBGM(u8 speed);
void FadeOutBGM(u8 speed);
bool8 IsBGMStopped(void);
void PlayCry_Normal(u16 species, s8 pan);
void PlayCry_NormalNoDucking(u16 species, s8 pan, s8 volume, u8 priority);
void PlayCry_ByMode(u16 species, s8 pan, u8 mode);
void PlayCry_ReleaseDouble(u16 species, s8 pan, u8 mode);
void PlayCry_Script(u16 species, u8 mode);
void PlayCry_DuckNoRestore(u16 species, s8 pan, u8 mode);
void PlayCryInternal(u16 species, s8 pan, s8 volume, u8 priority, u8 mode);
void PlayCry_Normal(enum Species species, s8 pan);
void PlayCry_NormalNoDucking(enum Species species, s8 pan, s8 volume, u8 priority);
void PlayCry_ByMode(enum Species species, s8 pan, u8 mode);
void PlayCry_ReleaseDouble(enum Species species, s8 pan, u8 mode);
void PlayCry_Script(enum Species species, u8 mode);
void PlayCry_DuckNoRestore(enum Species species, s8 pan, u8 mode);
void PlayCryInternal(enum Species species, s8 pan, s8 volume, u8 priority, u8 mode);
bool8 IsCryFinished(void);
void StopCryAndClearCrySongs(void);
void StopCry(void);

View File

@ -550,7 +550,7 @@
#include "battle.h"
#include "battle_anim.h"
#include "data.h"
#include "generational_changes.h"
#include "config_changes.h"
#include "item.h"
#include "random.h"
#include "recorded_battle.h"
@ -1058,8 +1058,8 @@ void TieBreakScore(u32 sourceLine, enum RandomTag rngTag, enum ScoreTieResolutio
void TieBreakTarget(u32 sourceLine, enum TargetTieResolution targetTieRes, u32 value);
void ClearFlagAfterTest(void);
void ClearVarAfterTest(void);
void OpenPokemon(u32 sourceLine, enum BattleTrainer trainer, u32 species);
void OpenPokemonMulti(u32 sourceLine, enum BattleTrainer trainer, u32 species);
void OpenPokemon(u32 sourceLine, enum BattleTrainer trainer, enum Species species);
void OpenPokemonMulti(u32 sourceLine, enum BattleTrainer trainer, enum Species species);
void ClosePokemon(u32 sourceLine);
void RNGSeed_(u32 sourceLine, rng_value_t seed);

View File

@ -15,8 +15,8 @@ extern const struct WindowTemplate gTradeEvolutionSceneYesNoWindowTemplate;
s32 GetGameProgressForLinkTrade(void);
void CB2_StartCreateTradeMenu(void);
void CB2_LinkTrade(void);
int CanRegisterMonForTradingBoard(struct RfuGameCompatibilityData player, u16 species2, u16 species, bool8 isModernFatefulEncounter);
int GetUnionRoomTradeMessageId(struct RfuGameCompatibilityData player, struct RfuGameCompatibilityData partner, u16 playerSpecies2, u16 partnerSpecies, enum Type requestedType, u16 playerSpecies, bool8 isModernFatefulEncounter);
int CanRegisterMonForTradingBoard(struct RfuGameCompatibilityData player, enum Species species2, enum Species species, bool8 isModernFatefulEncounter);
int GetUnionRoomTradeMessageId(struct RfuGameCompatibilityData player, struct RfuGameCompatibilityData partner, enum Species playerSpecies2, enum Species partnerSpecies, enum Type requestedType, enum Species playerSpecies, bool8 isModernFatefulEncounter);
int CanSpinTradeMon(struct Pokemon *mon, u16 monIdx);
void InitTradeSequenceBgGpuRegs(void);
void LinkTradeDrawWindow(void);

View File

@ -2,6 +2,7 @@
#define GUARD_TRAINER_CARD_H
#include "constants/trainer_card.h"
#include "constants/species.h"
struct TrainerCard
{
@ -39,7 +40,7 @@ struct TrainerCard
/*0x4E*/ u8 monIconTint; // FRLG only
/*0x4F*/ u8 unionRoomClass;
/*0x50*/ u8 stickers[TRAINER_CARD_STICKER_TYPES]; // FRLG only
/*0x54*/ u16 monSpecies[PARTY_SIZE]; // FRLG only
/*0x54*/ enum Species monSpecies[PARTY_SIZE]; // FRLG only
// Note: Link players use linkHasAllFrontierSymbols, not the field below,
// which they use for a Wonder Card flag id instead (see CreateTrainerCardInBuffer)
/*0x60*/ bool16 hasAllFrontierSymbols;

View File

@ -8,8 +8,8 @@
#define F_MON_PIC_NO_AFFINE (1 << 7)
bool16 ResetAllPicSprites(void);
u16 CreateMonPicSprite_Affine(u16 species, bool8 isShiny, u32 personality, u8 flags, s16 x, s16 y, u8 paletteSlot, u16 paletteTag);
u16 CreateMonPicSprite(u16 species, bool8 isShiny, u32 personality, bool8 isFrontPic, s16 x, s16 y, u8 paletteSlot, u16 paletteTag);
u16 CreateMonPicSprite_Affine(enum Species species, bool8 isShiny, u32 personality, u8 flags, s16 x, s16 y, u8 paletteSlot, u16 paletteTag);
u16 CreateMonPicSprite(enum Species species, bool8 isShiny, u32 personality, bool8 isFrontPic, s16 x, s16 y, u8 paletteSlot, u16 paletteTag);
u16 FreeAndDestroyMonPicSprite(u16 spriteId);
u16 FreeAndDestroyMonPicSpriteNoPalette(u16 spriteId);
u16 CreateTrainerPicSprite(u16 species, bool8 isFrontPic, s16 x, s16 y, u8 paletteSlot, u16 paletteTag);
@ -17,6 +17,6 @@ u16 FreeAndDestroyTrainerPicSprite(u16 spriteId);
u16 CreateTrainerCardTrainerPicSprite(u16 species, bool8 isFrontPic, u16 destX, u16 destY, u8 paletteSlot, u8 windowId);
u16 PlayerGenderToFrontTrainerPicId_Debug(enum Gender gender, bool8 getClass);
void CopyTrainerBackspriteFramesToDest(enum TrainerPicID trainerPicId, u8 *dest);
u16 CreateTrainerCardMonIconSprite(u16 species, bool8 isShiny, u32 personality, bool8 isFrontPic, u16 destX, u16 destY, u8 paletteSlot, u8 windowId);
u16 CreateTrainerCardMonIconSprite(enum Species species, bool8 isShiny, u32 personality, bool8 isFrontPic, u16 destX, u16 destY, u8 paletteSlot, u8 windowId);
#endif // GUARD_TRAINER_POKEMON_SPRITES_H

View File

@ -1,11 +1,13 @@
#ifndef GUARD_TV_H
#define GUARD_TV_H
#include "constants/species.h"
extern u8 *const gTVStringVarPtrs[3];
void ClearTVShowData(void);
void TryPutBreakingNewsOnAir(void);
void TryPutBattleSeminarOnAir(u16 foeSpecies, u16 species, u8 moveIndex, const u16 *movePtr, u16 betterMove);
void TryPutBattleSeminarOnAir(enum Species foeSpecies, enum Species species, u8 moveIndex, const u16 *movePtr, enum Move betterMove);
void TryPutFrontierTVShowOnAir(u16 winStreak, u8 facilityAndMode);
void DoTVShow(void);
void DoTVShowInSearchOfTrainers(void);
@ -39,11 +41,11 @@ void IncrementDailyBerryBlender(void);
void SanitizeTVShowsForRuby(TVShow *shows);
void TryPutSafariFanClubOnAir(u8 monsCaught, u8 pokeblocksUsed);
bool8 Put3CheersForPokeblocksOnTheAir(const u8 *partnersName, enum Flavor flavor, u8 color, u8 sheen, u8 language);
void SetPokemonAnglerSpecies(u16 species);
void SetPokemonAnglerSpecies(enum Species species);
void UpdateTVShowsPerDay(u16 days);
void TryPutPokemonTodayOnAir(void);
void TryPutSecretBaseVisitOnAir(void);
void PutBattleUpdateOnTheAir(u8 opponentLinkPlayerId, enum Move move, u16 speciesPlayer, u16 speciesOpponent);
void PutBattleUpdateOnTheAir(u8 opponentLinkPlayerId, enum Move move, enum Species speciesPlayer, enum Species speciesOpponent);
void BravoTrainerPokemonProfile_BeforeInterview1(enum Move move);
void InterviewBefore(void);
void InterviewAfter(void);

View File

@ -138,9 +138,9 @@ struct UnionRoomTrade
u16 type;
u32 playerPersonality;
u8 offerPlayerId;
u16 playerSpecies;
enum Species playerSpecies;
u16 playerLevel;
u16 species;
enum Species species;
u16 level;
u32 personality;
};
@ -148,7 +148,7 @@ struct UnionRoomTrade
extern u8 gPlayerCurrActivity;
extern struct RfuGameCompatibilityData gRfuPartnerCompatibilityData;
extern u16 gUnionRoomOfferedSpecies;
extern enum Species gUnionRoomOfferedSpecies;
extern enum Type gUnionRoomRequestedMonType;
u8 CreateTask_CreateTradeMenu(void);

View File

@ -18,7 +18,7 @@ struct WildPokemon
{
u8 minLevel;
u8 maxLevel;
u16 species;
enum Species species;
};
struct WildPokemonInfo
@ -60,7 +60,7 @@ bool8 UpdateRepelCounter(void);
bool8 TryDoDoubleWildBattle(void);
bool8 StandardWildEncounter_Debug(void);
u32 CalculateChainFishingShinyRolls(void);
void CreateWildMon(u16 species, u8 level);
void CreateWildMon(enum Species species, u8 level);
u16 GetCurrentMapWildMonHeaderId(void);
u32 ChooseWildMonIndex_Land(void);
u32 ChooseWildMonIndex_Water(void);

View File

@ -314,7 +314,7 @@ static u16 GetRandomAlternateMove(u8 monId)
u8 i, j;
u8 id;
u8 numLearnsetMoves;
u16 species;
enum Species species;
const struct LevelUpMove *learnset;
bool32 needTMs = FALSE;
enum Move move = MOVE_NONE;
@ -434,7 +434,7 @@ static bool8 TrySetMove(u8 monId, enum Move move)
return TRUE;
}
static void GetLatestLearnedMoves(u16 species, u16 *moves)
static void GetLatestLearnedMoves(enum Species species, u16 *moves)
{
u8 i, j;
u8 level, numLearnsetMoves;
@ -564,7 +564,7 @@ static void CreateApprenticeMenu(u8 menu)
top = 6;
for (i = 0; i < MULTI_PARTY_SIZE; i++)
{
u16 species;
enum Species species;
u32 speciesTableId;
speciesTableId = APPRENTICE_SPECIES_ID(i);

View File

@ -142,6 +142,20 @@ static s32 (*const sBattleAiFuncTable[])(enum BattlerId, enum BattlerId, enum Mo
};
// Functions
void AIDebugTimerStart()
{
// Set delay timer to count how long it takes for AI to choose action/move
gBattleStruct->aiDelayTimer = gMain.vblankCounter1;
CycleCountStart();
}
void AIDebugTimerEnd()
{
// We add to existing to compound multiple calls
gBattleStruct->aiDelayFrames += gMain.vblankCounter1 - gBattleStruct->aiDelayTimer;
gBattleStruct->aiDelayCycles += CycleCountEnd();
}
void BattleAI_SetupAIData(u8 defaultScoreMoves, enum BattlerId battler)
{
u32 moveLimitations;
@ -290,8 +304,8 @@ void BattleAI_SetupFlags(void)
// The check is here because wild natural enemies are not symmetrical.
if (B_WILD_NATURAL_ENEMIES && IsDoubleBattle())
{
u32 speciesLeft = GetMonData(&gEnemyParty[0], MON_DATA_SPECIES);
u32 speciesRight = GetMonData(&gEnemyParty[1], MON_DATA_SPECIES);
enum Species speciesLeft = GetMonData(&gEnemyParty[0], MON_DATA_SPECIES);
enum Species speciesRight = GetMonData(&gEnemyParty[1], MON_DATA_SPECIES);
if (IsNaturalEnemy(speciesLeft, speciesRight))
gAiThinkingStruct->aiFlags[B_BATTLER_1] |= AI_FLAG_ATTACKS_PARTNER;
if (IsNaturalEnemy(speciesRight, speciesLeft))
@ -371,6 +385,9 @@ void ComputeBattlerDecisions(enum BattlerId battler)
gAiLogicData->aiCalcInProgress = TRUE;
if (DEBUG_AI_DELAY_TIMER)
AIDebugTimerStart();
// Setup battler and prediction data
BattleAI_SetupAIData(0xF, battler);
SetupAIPredictionData(battler, SWITCH_MID_BATTLE_OPTIONAL);
@ -390,6 +407,9 @@ void ComputeBattlerDecisions(enum BattlerId battler)
BattlerChooseNonMoveAction();
ModifySwitchAfterMoveScoring(battler);
if (DEBUG_AI_DELAY_TIMER)
AIDebugTimerEnd();
gAiLogicData->aiCalcInProgress = FALSE;
}
}
@ -710,8 +730,10 @@ void SetAiLogicDataForTurn(struct AiLogicData *aiData)
if (!(gBattleTypeFlags & BATTLE_TYPE_HAS_AI) && !IsWildMonSmart())
return;
// Set delay timer to count how long it takes for AI to choose action/move
gBattleStruct->aiDelayTimer = gMain.vblankCounter1;
gAiLogicData->aiCalcInProgress = TRUE;
if (DEBUG_AI_DELAY_TIMER)
AIDebugTimerStart();
aiData->weatherHasEffect = HasWeatherEffect();
weather = AI_GetWeather();
@ -719,9 +741,6 @@ void SetAiLogicDataForTurn(struct AiLogicData *aiData)
// get/assume all battler data and simulate AI damage
battlersCount = gBattlersCount;
gAiLogicData->aiCalcInProgress = TRUE;
if (DEBUG_AI_DELAY_TIMER)
CycleCountStart();
for (enum BattlerId battlerAtk = 0; battlerAtk < battlersCount; battlerAtk++)
{
if (!IsBattlerAlive(battlerAtk))
@ -752,15 +771,15 @@ void SetAiLogicDataForTurn(struct AiLogicData *aiData)
}
if (DEBUG_AI_DELAY_TIMER)
// We add to existing to compound multiple calls
gBattleStruct->aiDelayCycles += CycleCountEnd();
AIDebugTimerEnd();
gAiLogicData->aiCalcInProgress = FALSE;
}
enum Ability GetPartyMonAbility(struct Pokemon *mon)
{
// Doesn't have any special handling yet
u32 species = GetMonData(mon, MON_DATA_SPECIES);
enum Species species = GetMonData(mon, MON_DATA_SPECIES);
enum Ability ability = GetSpeciesAbility(species, GetMonData(mon, MON_DATA_ABILITY_NUM));
return ability;
}
@ -3203,8 +3222,8 @@ static s32 AI_DoubleBattle(enum BattlerId battlerAtk, enum BattlerId battlerDef,
bool32 hasTwoOpponents = HasTwoOpponents(battlerAtk);
bool32 hasPartner = HasPartner(battlerAtk);
u32 friendlyFireThreshold = GetFriendlyFireKOThreshold(battlerAtk);
u32 noOfHitsToKOPartner = GetNoOfHitsToKOBattler(battlerAtk, battlerAtkPartner, gAiThinkingStruct->movesetIndex, AI_ATTACKING, CONSIDER_ENDURE);
bool32 wouldPartnerFaint = hasPartner && CanIndexMoveFaintTarget(battlerAtk, battlerAtkPartner, gAiThinkingStruct->movesetIndex, AI_ATTACKING) && !partnerProtecting;
u32 noOfHitsToKOPartner = GetNoOfHitsToKOBattler(battlerAtk, battlerAtkPartner, gAiThinkingStruct->movesetIndex, AI_ATTACKING_PARTNER, CONSIDER_ENDURE);
bool32 wouldPartnerFaint = hasPartner && CanIndexMoveFaintTarget(battlerAtk, battlerAtkPartner, gAiThinkingStruct->movesetIndex, AI_ATTACKING_PARTNER) && !partnerProtecting;
bool32 isFriendlyFireOK = !wouldPartnerFaint && (noOfHitsToKOPartner == 0 || noOfHitsToKOPartner > friendlyFireThreshold);
// check what effect partner is using
@ -4104,7 +4123,7 @@ static enum MoveComparisonResult CompareMoveTwoTurnEffect(enum BattlerId battler
static inline bool32 ShouldUseSpreadDamageMove(enum BattlerId battlerAtk, enum Move move, u32 moveIndex, u32 hitsToFaintOpposingBattler)
{
enum BattlerId partnerBattler = BATTLE_PARTNER(battlerAtk);
u32 noOfHitsToFaintPartner = GetNoOfHitsToKOBattler(battlerAtk, partnerBattler, moveIndex, AI_ATTACKING, CONSIDER_ENDURE);
u32 noOfHitsToFaintPartner = GetNoOfHitsToKOBattler(battlerAtk, partnerBattler, moveIndex, AI_ATTACKING_PARTNER, CONSIDER_ENDURE);
u32 friendlyFireThreshold = GetFriendlyFireKOThreshold(battlerAtk);
return (HasPartnerIgnoreFlags(battlerAtk)
&& noOfHitsToFaintPartner != 0 // Immunity check

View File

@ -35,11 +35,20 @@ struct IncomingHealInfo
static bool32 CanUseSuperEffectiveMoveAgainstOpponents(enum BattlerId battler);
static bool32 FindMonWithFlagsAndSuperEffective(enum BattlerId battler, u16 flags, u32 moduloPercent);
static u32 GetSwitchinHazardsDamage(enum BattlerId battler);
static u32 GetSwitchinSingleUseItemHealing(enum BattlerId battler, enum BattlerId opposingBattler, s32 currentHP);
static bool32 AI_CanSwitchinAbilityTrapOpponent(enum Ability ability, enum BattlerId opposingBattler);
static u32 GetBattlerTypeMatchup(enum BattlerId opposingBattler, enum BattlerId battler);
static u32 GetSwitchinHitsToKO(s32 damageTaken, enum BattlerId battler, const struct IncomingHealInfo *healInfo, u32 originalHp);
static void GetIncomingHealInfo(enum BattlerId battler, struct IncomingHealInfo *healInfo);
static u32 GetWishHealAmountForBattler(enum BattlerId battler);
static void SetBattlerStatusForSwitchin(enum BattlerId battler);
static void SetBattlerStatStagesForSwitchin(enum BattlerId battler, enum BattlerId opposingBattler, u32 fieldStatus);
static void SetBattlerHPChangeForSwitch(enum BattlerId battler, enum BattlerId opposingBattler);
static void SetBattlerVolatilesForSwitchin(enum BattlerId battler, u32 weather, u32 fieldStatus);
bool32 IsSwitchinTSpikesAffected(enum BattlerId battler);
static bool32 IsOpponentPhysicalAttacker(enum BattlerId battler, enum BattlerId opposingBattler);
static bool32 CanIntimidateLowerOpponentAtk(enum BattlerId battler, enum BattlerId opposingBattler);
static bool32 ShouldSwitchIfIntimidateBenefit(enum BattlerId battler);
static void InitializeSwitchinCandidate(enum BattlerId switchinBattler, u32 monIndex, struct Pokemon *mon)
{
@ -48,17 +57,24 @@ static void InitializeSwitchinCandidate(enum BattlerId switchinBattler, u32 monI
// Setup switchin battler data
gAiThinkingStruct->saved[switchinBattler].saved = TRUE;
SetBattlerAiData(switchinBattler, gAiLogicData);
SetBattlerFieldStatusForSwitchin(switchinBattler);
u32 switchinWeather = AI_GetSwitchinWeather(switchinBattler);
u32 switchinFieldStatus = AI_GetSwitchinFieldStatus(switchinBattler);
SetBattlerVolatilesForSwitchin(switchinBattler, switchinWeather, switchinFieldStatus);
SetBattlerStatusForSwitchin(switchinBattler);
gBattlerPartyIndexes[switchinBattler] = monIndex;
gAiLogicData->switchInCalc = TRUE;
for (enum BattlerId battlerIndex = 0; battlerIndex < gBattlersCount; battlerIndex++)
{
if (switchinBattler == battlerIndex || !IsBattlerAlive(battlerIndex))
continue;
CalcBattlerAiMovesData(gAiLogicData, switchinBattler, battlerIndex, AI_GetSwitchinWeather(switchinBattler), AI_GetSwitchinFieldStatus(switchinBattler));
CalcBattlerAiMovesData(gAiLogicData, battlerIndex, switchinBattler, AI_GetSwitchinWeather(switchinBattler), AI_GetSwitchinFieldStatus(switchinBattler));
SetBattlerStatStagesForSwitchin(switchinBattler, battlerIndex, switchinFieldStatus);
SetBattlerHPChangeForSwitch(switchinBattler, battlerIndex);
CalcBattlerAiMovesData(gAiLogicData, switchinBattler, battlerIndex, switchinWeather, switchinFieldStatus);
CalcBattlerAiMovesData(gAiLogicData, battlerIndex, switchinBattler, switchinWeather, switchinFieldStatus);
}
gAiLogicData->switchInCalc = FALSE;
gBattlerPartyIndexes[switchinBattler] = storeCurrBattlerPartyIndex;
gAiThinkingStruct->saved[switchinBattler].saved = FALSE;
}
@ -173,6 +189,10 @@ u32 GetSwitchChance(enum ShouldSwitchScenario shouldSwitchScenario)
return SHOULD_SWITCH_REGENERATOR_PERCENTAGE;
case SHOULD_SWITCH_REGENERATOR_STATS_RAISED:
return SHOULD_SWITCH_REGENERATOR_STATS_RAISED_PERCENTAGE;
case SHOULD_SWITCH_INTIMIDATE:
return SHOULD_SWITCH_INTIMIDATE_PERCENTAGE;
case SHOULD_SWITCH_INTIMIDATE_STATS_RAISED:
return SHOULD_SWITCH_INTIMIDATE_STATS_RAISED_PERCENTAGE;
case SHOULD_SWITCH_ENCORE_STATUS:
return SHOULD_SWITCH_ENCORE_STATUS_PERCENTAGE;
case SHOULD_SWITCH_ENCORE_DAMAGE:
@ -218,6 +238,35 @@ static bool32 AreStatsRaised(enum BattlerId battler)
return (buffedStatsValue > STAY_IN_STATS_RAISED);
}
bool32 IsSwitchinTSpikesAffected(enum BattlerId battler)
{
enum Ability ability = gAiLogicData->abilities[battler];
enum HoldEffect heldItemEffect = gAiLogicData->holdEffects[battler];
enum BattlerId opposingBattler = GetOppositeBattler(battler);
bool32 ignoreItem = ((gFieldStatuses & STATUS_FIELD_MAGIC_ROOM) || ability == ABILITY_KLUTZ);
if (gBattleMons[battler].status1 & STATUS1_ANY)
return FALSE;
if (IS_BATTLER_ANY_TYPE(battler, TYPE_POISON, TYPE_STEEL))
return FALSE;
if (ability == ABILITY_IMMUNITY || IsAbilityOnSide(battler, ABILITY_PASTEL_VEIL))
return FALSE;
if ((heldItemEffect == HOLD_EFFECT_HEAVY_DUTY_BOOTS || heldItemEffect == HOLD_EFFECT_CURE_PSN || heldItemEffect == HOLD_EFFECT_CURE_STATUS) && !ignoreItem)
return FALSE;
if (!AI_IsBattlerGrounded(battler))
return FALSE;
if (IsMistyTerrainAffected(battler, ability, heldItemEffect, gFieldStatuses))
return FALSE;
if (IsLeafGuardProtected(battler, ability))
return FALSE;
if (IsShieldsDownProtected(battler, ability))
return FALSE;
if (IsFlowerVeilProtected(battler))
return FALSE;
if (IsSafeguardProtected(opposingBattler, battler, gAiLogicData->abilities[opposingBattler]))
return FALSE;
return TRUE;
}
static inline bool32 SetSwitchinAndSwitch(enum BattlerId battler, u32 switchinId)
{
gBattleStruct->AI_monToSwitchIntoId[battler] = switchinId;
@ -339,7 +388,7 @@ static bool32 ShouldSwitchIfHasBadOdds(enum BattlerId battler)
hasSuperEffectiveMove = TRUE;
// Check if can win 1v1
hitsToKOPlayer = GetNoOfHitsToKOBattler(battler, opposingBattler, moveIndex, AI_ATTACKING, CONSIDER_ENDURE);
hitsToKOPlayer = GetNoOfHitsToKOBattler(battler, opposingBattler, moveIndex, AI_SWITCHIN_ATTACKING, CONSIDER_ENDURE);
if (!canBattlerWin1v1 ) // Once we can win a 1v1 we don't need to track this, but want to run the rest of the function to keep the runtime the same regardless of when we find the winning move
{
isBattlerFirst = AI_IsFaster(battler, opposingBattler, aiMove, expectedMove, CONSIDER_PRIORITY);
@ -586,7 +635,7 @@ static bool32 FindMonThatAbsorbsOpponentsMove(enum BattlerId battler)
// Only check damage if it's a damaging move
if (!IsBattleMoveStatus(aiMove))
{
if (!AI_DoesChoiceEffectBlockMove(battler, aiMove) && AI_GetDamage(battler, opposingBattler, moveIndex, AI_ATTACKING, gAiLogicData) > gBattleMons[opposingBattler].hp)
if (!AI_DoesChoiceEffectBlockMove(battler, aiMove) && AI_GetDamage(battler, opposingBattler, moveIndex, AI_SWITCHIN_ATTACKING, gAiLogicData) > gBattleMons[opposingBattler].hp)
return FALSE;
}
}
@ -916,6 +965,103 @@ static bool32 GetHitEscapeTransformState(enum BattlerId battlerAtk, enum Move mo
return isFasterThanAll;
}
static bool32 IsOpponentPhysicalAttacker(enum BattlerId battler, enum BattlerId opposingBattler)
{
if (!IsBattlerAlive(opposingBattler))
return FALSE;
if (GetBestDmgFromBattler(opposingBattler, battler, AI_DEFENDING) > 0 && HasPhysicalBestMove(opposingBattler, battler, AI_DEFENDING))
return TRUE;
enum Move incomingMove = GetIncomingMove(battler, opposingBattler, gAiLogicData);
return incomingMove != MOVE_NONE
&& incomingMove != MOVE_UNAVAILABLE
&& GetBattleMoveCategory(incomingMove) == DAMAGE_CATEGORY_PHYSICAL;
}
static bool32 CanIntimidateLowerOpponentAtk(enum BattlerId battler, enum BattlerId opposingBattler)
{
enum Ability abilityDef = gAiLogicData->abilities[opposingBattler];
// If Attack is already at -2 or lower, repeated Intimidate cycles aren't worth it.
if (gBattleMons[opposingBattler].statStages[STAT_ATK] <= DEFAULT_STAT_STAGE - 2)
return FALSE;
if (gBattleMons[opposingBattler].volatiles.substitute)
return FALSE;
if (gAiLogicData->holdEffects[opposingBattler] == HOLD_EFFECT_CLEAR_AMULET)
return FALSE;
if (gSideStatuses[GetBattlerSide(opposingBattler)] & SIDE_STATUS_MIST)
return FALSE;
if (IS_BATTLER_OF_TYPE(opposingBattler, TYPE_GRASS) && AI_IsAbilityOnSide(opposingBattler, ABILITY_FLOWER_VEIL))
return FALSE;
switch (abilityDef)
{
case ABILITY_HYPER_CUTTER:
case ABILITY_CLEAR_BODY:
case ABILITY_FULL_METAL_BODY:
case ABILITY_WHITE_SMOKE:
return FALSE;
default:
break;
}
if (GetConfig(B_UPDATED_INTIMIDATE) >= GEN_8)
{
switch (abilityDef)
{
case ABILITY_INNER_FOCUS:
case ABILITY_SCRAPPY:
case ABILITY_OWN_TEMPO:
case ABILITY_OBLIVIOUS:
return FALSE;
default:
break;
}
}
return TRUE;
}
static bool32 ShouldSwitchIfIntimidateBenefit(enum BattlerId battler)
{
// Keep Intimidate cycling behavior restricted to smart-switching AI
if (!(gAiThinkingStruct->aiFlags[battler] & AI_FLAG_SMART_SWITCHING))
return FALSE;
enum BattlerId opposingBattler = GetOppositeBattler(battler);
enum BattlerId opposingPartner = BATTLE_PARTNER(opposingBattler);
bool32 hasValidTarget = FALSE;
if (IsBattlerAlive(opposingBattler))
{
enum Ability abilityDef = gAiLogicData->abilities[opposingBattler];
bool32 canLowerAtk = CanIntimidateLowerOpponentAtk(battler, opposingBattler);
if (canLowerAtk && (DoesIntimidateRaiseStats(abilityDef) || abilityDef == ABILITY_MIRROR_ARMOR))
return FALSE;
if (canLowerAtk && IsOpponentPhysicalAttacker(battler, opposingBattler))
hasValidTarget = TRUE;
}
if (IsDoubleBattle() && IsBattlerAlive(opposingPartner))
{
enum Ability abilityDef = gAiLogicData->abilities[opposingPartner];
bool32 canLowerAtk = CanIntimidateLowerOpponentAtk(battler, opposingPartner);
if (canLowerAtk && (DoesIntimidateRaiseStats(abilityDef) || abilityDef == ABILITY_MIRROR_ARMOR))
return FALSE;
if (canLowerAtk && IsOpponentPhysicalAttacker(battler, opposingPartner))
hasValidTarget = TRUE;
}
return hasValidTarget;
}
static bool32 ShouldSwitchIfAbilityBenefit(enum BattlerId battler)
{
bool32 hasStatRaised = AnyUsefulStatIsRaised(battler);
@ -953,20 +1099,21 @@ static bool32 ShouldSwitchIfAbilityBenefit(enum BattlerId battler)
return FALSE;
case ABILITY_INTIMIDATE:
// TODO: In ShouldSwitch cleanup, gate Intimidate cycling behind "stay in instead if the current mon wins the 1v1" to avoid duplicating Bad Odds logic here.
if (ShouldSwitchIfIntimidateBenefit(battler)
&& gAiLogicData->mostSuitableMonId[battler] != PARTY_SIZE
&& (hasStatRaised ? RandomPercentage(RNG_AI_SWITCH_INTIMIDATE, GetSwitchChance(SHOULD_SWITCH_INTIMIDATE_STATS_RAISED)) : RandomPercentage(RNG_AI_SWITCH_INTIMIDATE, GetSwitchChance(SHOULD_SWITCH_INTIMIDATE))))
break;
return FALSE;
case ABILITY_ZERO_TO_HERO:
{
enum Move hitEscapeMove = MOVE_NONE;
for (u32 moveIndex = 0; moveIndex < MAX_MON_MOVES; moveIndex++)
{
enum Move move = gBattleMons[battler].moves[moveIndex];
if (move != MOVE_NONE && GetMoveEffect(move) == EFFECT_HIT_ESCAPE)
{
hitEscapeMove = move;
break;
}
}
if (GetBattlerMoveIndexWithEffect(battler, EFFECT_HIT_ESCAPE) < MAX_MON_MOVES)
hitEscapeMove = gBattleMons[battler].moves[GetBattlerMoveIndexWithEffect(battler, EFFECT_HIT_ESCAPE)];
// Prefer to use a hit escape move if Palafin will move first and can hit
if (hitEscapeMove != MOVE_NONE && GetHitEscapeTransformState(battler, hitEscapeMove))
@ -1042,7 +1189,7 @@ static bool32 FindMonWithFlagsAndSuperEffective(enum BattlerId battler, u16 flag
for (u32 monIndex = firstId; monIndex < lastId; monIndex++)
{
u16 species;
enum Species species;
enum Ability monAbility;
uq4_12_t typeMultiplier;
u16 moveFlags = 0;
@ -1488,6 +1635,51 @@ bool32 IsSwitchinValid(enum BattlerId battler)
return TRUE;
}
static u32 GetSwitchinSingleUseItemHealing(enum BattlerId battler, enum BattlerId opposingBattler, s32 currentHP)
{
enum Item aiItem = gAiLogicData->items[battler];
u32 maxHP = gBattleMons[battler].maxHP;
s32 itemHeal = 0;
// Check if we're at a single use healing item threshold
if (currentHP <= 0
|| gAiLogicData->abilities[battler] == ABILITY_KLUTZ
|| (gAiLogicData->abilities[opposingBattler] == ABILITY_UNNERVE && GetItemPocket(aiItem) == POCKET_BERRIES))
return itemHeal;
switch (GetItemHoldEffect(aiItem))
{
case HOLD_EFFECT_RESTORE_HP:
if (currentHP < maxHP / 2)
itemHeal = GetItemHoldEffectParam(aiItem);
break;
case HOLD_EFFECT_RESTORE_PCT_HP:
if (currentHP < maxHP / 2)
{
itemHeal = maxHP / GetItemHoldEffectParam(aiItem);
if (itemHeal == 0)
itemHeal = 1;
}
break;
case HOLD_EFFECT_CONFUSE_SPICY:
case HOLD_EFFECT_CONFUSE_DRY:
case HOLD_EFFECT_CONFUSE_SWEET:
case HOLD_EFFECT_CONFUSE_BITTER:
case HOLD_EFFECT_CONFUSE_SOUR:
if (currentHP < maxHP / CONFUSE_BERRY_HP_FRACTION)
{
itemHeal = maxHP / GetItemHoldEffectParam(aiItem);
if (itemHeal == 0)
itemHeal = 1;
}
break;
default:
break;
}
return itemHeal;
}
// Gets hazard damage
static u32 GetSwitchinHazardsDamage(enum BattlerId battler)
{
@ -1681,7 +1873,6 @@ static u32 GetSwitchinRecurringDamage(enum BattlerId battler)
static u32 GetSwitchinStatusDamage(enum BattlerId battler)
{
u8 tSpikesLayers = gSideTimers[GetBattlerSide(battler)].toxicSpikesAmount;
enum HoldEffect heldItemEffect = gAiLogicData->holdEffects[battler];
u32 status = gBattleMons[battler].status1;
enum Ability ability = gAiLogicData->abilities[battler];
u32 maxHP = gBattleMons[battler].maxHP;
@ -1729,13 +1920,7 @@ static u32 GetSwitchinStatusDamage(enum BattlerId battler)
// Apply hypothetical poisoning from Toxic Spikes, which means the first turn of damage already added in GetSwitchinHazardsDamage
// Do this last to skip one iteration of Poison / Toxic damage, and start counting Toxic damage one turn later.
if (tSpikesLayers != 0 && (!IS_BATTLER_ANY_TYPE(battler, TYPE_POISON, TYPE_STEEL)
&& ability != ABILITY_IMMUNITY && ability != ABILITY_POISON_HEAL && ability != ABILITY_PASTEL_VEIL
&& status == 0
&& !(heldItemEffect == HOLD_EFFECT_HEAVY_DUTY_BOOTS
&& (((gFieldStatuses & STATUS_FIELD_MAGIC_ROOM) || ability == ABILITY_KLUTZ)))
&& heldItemEffect != HOLD_EFFECT_CURE_PSN && heldItemEffect != HOLD_EFFECT_CURE_STATUS
&& AI_IsBattlerGrounded(battler)))
if (tSpikesLayers != 0 && IsSwitchinTSpikesAffected(battler))
{
if (tSpikesLayers == 1)
{
@ -1777,7 +1962,7 @@ static u32 GetSwitchinHitsToKO(s32 damageTaken, enum BattlerId battler, const st
u32 statusDamage = GetSwitchinStatusDamage(battler);
u32 hitsToKO = 0;
u16 maxHP = gBattleMons[battler].maxHP, item = gAiLogicData->items[battler], heldItemEffect = GetItemHoldEffect(item);
u8 weatherDuration = gBattleStruct->weatherDuration, holdEffectParam = GetItemHoldEffectParam(item);
u8 weatherDuration = gBattleStruct->weatherDuration;
enum BattlerId opposingBattler = GetOppositeBattler(battler);
enum Ability opposingAbility = gAiLogicData->abilities[opposingBattler], ability = gAiLogicData->abilities[battler];
bool32 usedSingleUseHealingItem = FALSE, opponentCanBreakMold = IsMoldBreakerTypeAbility(opposingBattler, opposingAbility);
@ -1811,37 +1996,9 @@ static u32 GetSwitchinHitsToKO(s32 damageTaken, enum BattlerId battler, const st
currentHP = currentHP - weatherImpact;
// Check if we're at a single use healing item threshold
if (currentHP > 0 && gAiLogicData->abilities[battler] != ABILITY_KLUTZ && usedSingleUseHealingItem == FALSE
&& !(opposingAbility == ABILITY_UNNERVE && GetItemPocket(item) == POCKET_BERRIES))
if (usedSingleUseHealingItem == FALSE)
{
switch (heldItemEffect)
{
case HOLD_EFFECT_RESTORE_HP:
if (currentHP < maxHP / 2)
singleUseItemHeal = holdEffectParam;
break;
case HOLD_EFFECT_RESTORE_PCT_HP:
if (currentHP < maxHP / 2)
{
singleUseItemHeal = maxHP / holdEffectParam;
if (singleUseItemHeal == 0)
singleUseItemHeal = 1;
}
break;
case HOLD_EFFECT_CONFUSE_SPICY:
case HOLD_EFFECT_CONFUSE_DRY:
case HOLD_EFFECT_CONFUSE_SWEET:
case HOLD_EFFECT_CONFUSE_BITTER:
case HOLD_EFFECT_CONFUSE_SOUR:
if (currentHP < maxHP / CONFUSE_BERRY_HP_FRACTION)
{
singleUseItemHeal = maxHP / holdEffectParam;
if (singleUseItemHeal == 0)
singleUseItemHeal = 1;
}
break;
}
singleUseItemHeal = GetSwitchinSingleUseItemHealing(battler, opposingBattler, currentHP);
// If we used one, apply it without overcapping our maxHP
if (singleUseItemHeal > 0)
{
@ -1975,7 +2132,7 @@ static s32 GetMaxDamagePlayerCouldDealToSwitchin(enum BattlerId battler, enum Ba
playerMove = SMART_SWITCHING_OMNISCIENT ? gBattleMons[opposingBattler].moves[moveIndex] : playerMoves[moveIndex];
if (playerMove != MOVE_NONE && !IsBattleMoveStatus(playerMove) && GetMoveEffect(playerMove) != EFFECT_FOCUS_PUNCH && gBattleMons[opposingBattler].pp[moveIndex] > 0)
{
damageTaken = AI_GetDamage(opposingBattler, battler, moveIndex, AI_DEFENDING, gAiLogicData);
damageTaken = AI_GetDamage(opposingBattler, battler, moveIndex, AI_SWITCHIN_DEFENDING, gAiLogicData);
if (playerMove == gBattleStruct->choicedMove[opposingBattler]) // If player is choiced, only care about the choice locked move
{
*bestPlayerMove = playerMove;
@ -2006,7 +2163,7 @@ static s32 GetMaxPriorityDamagePlayerCouldDealToSwitchin(enum BattlerId battler,
if (GetBattleMovePriority(opposingBattler, gAiLogicData->abilities[opposingBattler], playerMove) > 0
&& playerMove != MOVE_NONE && !IsBattleMoveStatus(playerMove) && GetMoveEffect(playerMove) != EFFECT_FOCUS_PUNCH && gBattleMons[opposingBattler].pp[moveIndex] > 0)
{
damageTaken = AI_GetDamage(opposingBattler, battler, moveIndex, AI_DEFENDING, gAiLogicData);
damageTaken = AI_GetDamage(opposingBattler, battler, moveIndex, AI_SWITCHIN_DEFENDING, gAiLogicData);
if (playerMove == gBattleStruct->choicedMove[opposingBattler]) // If player is choiced, only care about the choice locked move
{
*bestPlayerPriorityMove = playerMove;
@ -2174,8 +2331,8 @@ static u32 GetBestMonIntegrated(struct Pokemon *party, int firstId, int lastId,
continue;
aiMove = gBattleMons[battler].moves[moveIndex];
damageDealt = AI_GetDamage(battler, opposingBattler, moveIndex, AI_ATTACKING, gAiLogicData);
hitsToKOPlayer = GetNoOfHitsToKOBattler(battler, opposingBattler, moveIndex, AI_ATTACKING, CONSIDER_ENDURE);
damageDealt = AI_GetDamage(battler, opposingBattler, moveIndex, AI_SWITCHIN_ATTACKING, gAiLogicData);
hitsToKOPlayer = GetNoOfHitsToKOBattler(battler, opposingBattler, moveIndex, AI_SWITCHIN_ATTACKING, CONSIDER_ENDURE);
// Offensive switchin decisions are based on which whether switchin moves first and whether it can win a 1v1
isSwitchinFirst = AI_IsFaster(battler, opposingBattler, aiMove, bestPlayerMove, CONSIDER_PRIORITY);
@ -2437,7 +2594,7 @@ static u32 GetBestMonVanilla(struct Pokemon *party, int firstId, int lastId, enu
// Best damage
if (aiMove != MOVE_NONE && !IsBattleMoveStatus(aiMove))
{
u32 aiDmg = AI_GetDamage(battler, opposingBattler, moveIndex, AI_ATTACKING, gAiLogicData);
u32 aiDmg = AI_GetDamage(battler, opposingBattler, moveIndex, AI_SWITCHIN_ATTACKING, gAiLogicData);
if (aiDmg > bestDamage)
{
bestDamage = aiDmg;
@ -2586,7 +2743,7 @@ u32 AI_SelectRevivalBlessingMon(enum BattlerId battler)
if (aiMove == MOVE_NONE || gBattleMons[battler].pp[moveIndex] == 0)
continue;
s32 damage = AI_GetDamage(battler, opposingBattler, moveIndex, AI_ATTACKING, gAiLogicData);
s32 damage = AI_GetDamage(battler, opposingBattler, moveIndex, AI_SWITCHIN_ATTACKING, gAiLogicData);
if (damage > bestDamage)
bestDamage = damage;
}
@ -2622,3 +2779,196 @@ u32 AI_SelectRevivalBlessingMon(enum BattlerId battler)
return bestMonId;
}
static void SetBattlerStatusForSwitchin(enum BattlerId battler)
{
u32 tSpikesLayers = gSideTimers[GetBattlerSide(battler)].toxicSpikesAmount;
if (tSpikesLayers != 0 && IsSwitchinTSpikesAffected(battler))
{
if (tSpikesLayers == 1)
gBattleMons[battler].status1 = STATUS1_POISON;
if (tSpikesLayers == 2)
{
gBattleMons[battler].status1 = STATUS1_TOXIC_POISON;
gBattleMons[battler].status1 += STATUS1_TOXIC_TURN(1);
}
}
}
static void SetBattlerStatStagesForSwitchin(enum BattlerId battler, enum BattlerId opposingBattler, u32 fieldStatus)
{
u32 aiAbility = gAiLogicData->abilities[battler];
enum Item aiItem = gAiLogicData->items[battler];
bool32 isStickyWebsAffected = (IsHazardOnSide(GetBattlerSide(battler), HAZARDS_STICKY_WEB) && IsBattlerAffectedByHazards(battler, GetItemHoldEffect(aiItem), FALSE) && IsBattlerGrounded(battler, gAiLogicData->abilities[battler], GetItemHoldEffect(aiItem)));
bool32 opponentStatDrop = FALSE;
// Ability stat changes
switch(aiAbility)
{
case ABILITY_INTREPID_SWORD:
gBattleMons[battler].statStages[STAT_ATK] += 1;
break;
case ABILITY_DAUNTLESS_SHIELD:
gBattleMons[battler].statStages[STAT_DEF] += 1;
break;
case ABILITY_SUPREME_OVERLORD:
break;
case ABILITY_DOWNLOAD:
gBattleMons[battler].statStages[GetDownloadStat(battler)] += 1;
break;
case ABILITY_INTIMIDATE:
if (CanLowerStat(battler, opposingBattler, gAiLogicData, STAT_ATK))
{
if (gAiLogicData->abilities[opposingBattler] == ABILITY_CONTRARY)
{
gBattleMons[opposingBattler].statStages[STAT_ATK] += 1;
}
else
{
opponentStatDrop = TRUE;
gBattleMons[opposingBattler].statStages[STAT_ATK] -= 1;
if (gAiLogicData->abilities[opposingBattler] == ABILITY_DEFIANT)
gBattleMons[opposingBattler].statStages[STAT_ATK] += 2;
if (gAiLogicData->abilities[opposingBattler] == ABILITY_COMPETITIVE)
gBattleMons[opposingBattler].statStages[STAT_SPATK] += 2;
}
}
break;
case ABILITY_SUPERSWEET_SYRUP:
if (CanLowerStat(battler, opposingBattler, gAiLogicData, STAT_EVASION))
{
if (gAiLogicData->abilities[opposingBattler] == ABILITY_CONTRARY)
{
gBattleMons[opposingBattler].statStages[STAT_EVASION] += 1;
}
else
{
opponentStatDrop = TRUE;
gBattleMons[opposingBattler].statStages[STAT_EVASION] -= 1;
if (gAiLogicData->abilities[opposingBattler] == ABILITY_DEFIANT)
gBattleMons[opposingBattler].statStages[STAT_ATK] += 2;
if (gAiLogicData->abilities[opposingBattler] == ABILITY_COMPETITIVE)
gBattleMons[opposingBattler].statStages[STAT_SPATK] += 2;
}
}
break;
case ABILITY_WIND_RIDER:
if (gSideStatuses[GetBattlerSide(battler)] & SIDE_STATUS_TAILWIND)
gBattleMons[battler].statStages[STAT_ATK] += 1;
break;
case ABILITY_DEFIANT:
if (isStickyWebsAffected)
gBattleMons[battler].statStages[STAT_ATK] += 2;
break;
case ABILITY_COMPETITIVE:
if (isStickyWebsAffected)
gBattleMons[battler].statStages[STAT_SPATK] += 2;
break;
case ABILITY_CONTRARY:
if (isStickyWebsAffected)
gBattleMons[battler].statStages[STAT_SPEED] += 1;
default:
break;
}
// Item stat changes
switch(GetItemHoldEffect(aiItem))
{
case HOLD_EFFECT_TERRAIN_SEED:
{
u32 seedParam = GetItemHoldEffectParam(aiItem);
if ((seedParam == HOLD_EFFECT_PARAM_ELECTRIC_TERRAIN && (fieldStatus & STATUS_FIELD_ELECTRIC_TERRAIN))
|| (seedParam == HOLD_EFFECT_PARAM_GRASSY_TERRAIN && (fieldStatus & STATUS_FIELD_GRASSY_TERRAIN))
|| (seedParam == HOLD_EFFECT_PARAM_MISTY_TERRAIN && (fieldStatus & STATUS_FIELD_MISTY_TERRAIN))
|| (seedParam == HOLD_EFFECT_PARAM_PSYCHIC_TERRAIN && (fieldStatus & STATUS_FIELD_PSYCHIC_TERRAIN)))
gBattleMons[battler].statStages[STAT_DEF] += 1;
break;
}
case HOLD_EFFECT_ATTACK_UP:
if (HasEnoughHpToEatBerry(battler, aiAbility, GetItemHoldEffectParam(aiItem), aiItem))
gBattleMons[battler].statStages[STAT_ATK] += 1;
break;
case HOLD_EFFECT_DEFENSE_UP:
if (HasEnoughHpToEatBerry(battler, aiAbility, GetItemHoldEffectParam(aiItem), aiItem))
gBattleMons[battler].statStages[STAT_DEF] += 1;
break;
case HOLD_EFFECT_SPEED_UP:
if (HasEnoughHpToEatBerry(battler, aiAbility, GetItemHoldEffectParam(aiItem), aiItem))
gBattleMons[battler].statStages[STAT_SPEED] += 1;
break;
case HOLD_EFFECT_SP_ATTACK_UP:
if (HasEnoughHpToEatBerry(battler, aiAbility, GetItemHoldEffectParam(aiItem), aiItem))
gBattleMons[battler].statStages[STAT_SPATK] += 1;
break;
case HOLD_EFFECT_SP_DEFENSE_UP:
if (HasEnoughHpToEatBerry(battler, aiAbility, GetItemHoldEffectParam(aiItem), aiItem))
gBattleMons[battler].statStages[STAT_SPDEF] += 1;
break;
case HOLD_EFFECT_ROOM_SERVICE:
if (gFieldStatuses & STATUS_FIELD_TRICK_ROOM)
gBattleMons[battler].statStages[STAT_SPEED] -= 1;
case HOLD_EFFECT_MIRROR_HERB:
if (opponentStatDrop && gAiLogicData->abilities[opposingBattler] == ABILITY_DEFIANT)
gBattleMons[battler].statStages[STAT_ATK] += 2;
if (opponentStatDrop && gAiLogicData->abilities[opposingBattler] == ABILITY_COMPETITIVE)
gBattleMons[battler].statStages[STAT_SPATK] += 2;
break;
default:
break;
}
// Hazard stat changes
if (isStickyWebsAffected && GetItemHoldEffect(aiItem) != HOLD_EFFECT_WHITE_HERB)
gBattleMons[battler].statStages[STAT_SPEED] -= 1;
}
static void SetBattlerHPChangeForSwitch(enum BattlerId battler, enum BattlerId opposingBattler)
{
s32 maxHP = gBattleMons[battler].maxHP;
s32 currentHP = gBattleMons[battler].hp - GetSwitchinHazardsDamage(battler);
s32 itemHeal = GetSwitchinSingleUseItemHealing(battler, opposingBattler, currentHP);
if (itemHeal > 0)
{
if ((currentHP + itemHeal) > maxHP)
currentHP = maxHP;
else
currentHP = currentHP + itemHeal;
}
gBattleMons[battler].hp = currentHP;
}
// Set potential field effect from ability for switch in
static void SetBattlerVolatilesForSwitchin(enum BattlerId battler, u32 weather, u32 fieldStatus)
{
enum Item aiItem = gAiLogicData->items[battler];
switch (gAiLogicData->abilities[battler])
{
case ABILITY_VESSEL_OF_RUIN:
gBattleMons[battler].volatiles.vesselOfRuin = TRUE;
break;
case ABILITY_SWORD_OF_RUIN:
gBattleMons[battler].volatiles.swordOfRuin = TRUE;
break;
case ABILITY_TABLETS_OF_RUIN:
gBattleMons[battler].volatiles.tabletsOfRuin = TRUE;
break;
case ABILITY_BEADS_OF_RUIN:
gBattleMons[battler].volatiles.beadsOfRuin = TRUE;
break;
case ABILITY_QUARK_DRIVE:
if ((fieldStatus & STATUS_FIELD_ELECTRIC_TERRAIN) || GetItemHoldEffect(aiItem) == HOLD_EFFECT_BOOSTER_ENERGY)
gBattleMons[battler].volatiles.boosterEnergyActivated = TRUE;
break;
case ABILITY_PROTOSYNTHESIS:
if (((weather & B_WEATHER_SUN) && HasWeatherEffect()) || GetItemHoldEffect(aiItem) == HOLD_EFFECT_BOOSTER_ENERGY)
gBattleMons[battler].volatiles.boosterEnergyActivated = TRUE;
break;
case ABILITY_WIND_POWER:
if (gSideStatuses[GetBattlerSide(battler)] & SIDE_STATUS_TAILWIND)
gBattleMons[battler].volatiles.chargeTimer = 2;
break;
default:
break;
}
}

View File

@ -23,6 +23,7 @@
#include "constants/moves.h"
#include "constants/items.h"
static void AI_SetBattlerTurnOrder(u8 *aiTurnOrder);
static u32 GetAIEffectGroup(enum BattleMoveEffects effect);
static u32 GetAIEffectGroupFromMove(enum BattlerId battler, enum Move move);
@ -90,6 +91,23 @@ enum MoveTarget AI_GetBattlerMoveTargetType(enum BattlerId battler, enum Move mo
return GetMoveTarget(move);
}
u32 AI_GetDefaultDamageRollForContext(enum BattlerId battlerAtk, enum BattlerId battlerDef, u32 moveIndex, struct AiLogicData *aiData, u32 aiRoll)
{
switch (aiRoll)
{
case AI_ROLL_MIN:
return aiData->simulatedDmg[battlerAtk][battlerDef][moveIndex].minimum;
case AI_ROLL_MEDIAN:
return aiData->simulatedDmg[battlerAtk][battlerDef][moveIndex].median;
case AI_ROLL_MAX:
return aiData->simulatedDmg[battlerAtk][battlerDef][moveIndex].maximum;
case AI_ROLL_RANDOM:
return aiData->simulatedDmg[battlerAtk][battlerDef][moveIndex].random;
default:
return aiData->simulatedDmg[battlerAtk][battlerDef][moveIndex].median; // Default assumes it deals median damage
}
}
u32 AI_GetDamage(enum BattlerId battlerAtk, enum BattlerId battlerDef, u32 moveIndex, enum DamageCalcContext calcContext, struct AiLogicData *aiData)
{
if (calcContext == AI_ATTACKING && BattlerHasAi(battlerAtk))
@ -98,7 +116,7 @@ u32 AI_GetDamage(enum BattlerId battlerAtk, enum BattlerId battlerDef, u32 moveI
return aiData->simulatedDmg[battlerAtk][battlerDef][moveIndex].maximum;
if ((gAiThinkingStruct->aiFlags[battlerAtk] & AI_FLAG_CONSERVATIVE) && !(gAiThinkingStruct->aiFlags[battlerAtk] & AI_FLAG_RISKY)) // Conservative assumes it deals min damage
return aiData->simulatedDmg[battlerAtk][battlerDef][moveIndex].minimum;
return aiData->simulatedDmg[battlerAtk][battlerDef][moveIndex].median; // Default assumes it deals median damage
return AI_GetDefaultDamageRollForContext(battlerAtk, battlerDef, moveIndex, aiData, GetConfig(AI_ROLL_ATTACKING));
}
else if (calcContext == AI_DEFENDING && BattlerHasAi(battlerDef))
{
@ -106,7 +124,39 @@ u32 AI_GetDamage(enum BattlerId battlerAtk, enum BattlerId battlerDef, u32 moveI
return aiData->simulatedDmg[battlerAtk][battlerDef][moveIndex].minimum;
if ((gAiThinkingStruct->aiFlags[battlerAtk] & AI_FLAG_CONSERVATIVE) && !(gAiThinkingStruct->aiFlags[battlerAtk] & AI_FLAG_RISKY)) // Conservative assumes it takes max damage
return aiData->simulatedDmg[battlerAtk][battlerDef][moveIndex].maximum;
return aiData->simulatedDmg[battlerAtk][battlerDef][moveIndex].median; // Default assumes it takes median damage
return AI_GetDefaultDamageRollForContext(battlerAtk, battlerDef, moveIndex, aiData, AI_ROLL_DEFENDING);
}
else if (calcContext == AI_SWITCHIN_ATTACKING && BattlerHasAi(battlerAtk))
{
if ((gAiThinkingStruct->aiFlags[battlerAtk] & AI_FLAG_RISKY) && !(gAiThinkingStruct->aiFlags[battlerAtk] & AI_FLAG_CONSERVATIVE)) // Risky assumes it deals max damage
return aiData->simulatedDmg[battlerAtk][battlerDef][moveIndex].maximum;
if ((gAiThinkingStruct->aiFlags[battlerAtk] & AI_FLAG_CONSERVATIVE) && !(gAiThinkingStruct->aiFlags[battlerAtk] & AI_FLAG_RISKY)) // Conservative assumes it deals min damage
return aiData->simulatedDmg[battlerAtk][battlerDef][moveIndex].minimum;
return AI_GetDefaultDamageRollForContext(battlerAtk, battlerDef, moveIndex, aiData, AI_ROLL_SWITCHIN_ATTACKING);
}
else if (calcContext == AI_SWITCHIN_DEFENDING && BattlerHasAi(battlerDef))
{
if ((gAiThinkingStruct->aiFlags[battlerAtk] & AI_FLAG_RISKY) && !(gAiThinkingStruct->aiFlags[battlerAtk] & AI_FLAG_CONSERVATIVE)) // Risky assumes it takes min damage
return aiData->simulatedDmg[battlerAtk][battlerDef][moveIndex].minimum;
if ((gAiThinkingStruct->aiFlags[battlerAtk] & AI_FLAG_CONSERVATIVE) && !(gAiThinkingStruct->aiFlags[battlerAtk] & AI_FLAG_RISKY)) // Conservative assumes it takes max damage
return aiData->simulatedDmg[battlerAtk][battlerDef][moveIndex].maximum;
return AI_GetDefaultDamageRollForContext(battlerAtk, battlerDef, moveIndex, aiData, AI_ROLL_SWITCHIN_DEFENDING);
}
else if (calcContext == AI_SHOULD_SETUP_DEFENDING && BattlerHasAi(battlerDef))
{
if ((gAiThinkingStruct->aiFlags[battlerAtk] & AI_FLAG_RISKY) && !(gAiThinkingStruct->aiFlags[battlerAtk] & AI_FLAG_CONSERVATIVE)) // Risky assumes it takes min damage
return aiData->simulatedDmg[battlerAtk][battlerDef][moveIndex].minimum;
if ((gAiThinkingStruct->aiFlags[battlerAtk] & AI_FLAG_CONSERVATIVE) && !(gAiThinkingStruct->aiFlags[battlerAtk] & AI_FLAG_RISKY)) // Conservative assumes it takes max damage
return aiData->simulatedDmg[battlerAtk][battlerDef][moveIndex].maximum;
return AI_GetDefaultDamageRollForContext(battlerAtk, battlerDef, moveIndex, aiData, AI_ROLL_SHOULD_SETUP_DEFENDING);
}
else if (calcContext == AI_ATTACKING_PARTNER && BattlerHasAi(battlerAtk))
{
if ((gAiThinkingStruct->aiFlags[battlerAtk] & AI_FLAG_RISKY) && !(gAiThinkingStruct->aiFlags[battlerAtk] & AI_FLAG_CONSERVATIVE)) // Risky assumes it deals max damage
return aiData->simulatedDmg[battlerAtk][battlerDef][moveIndex].maximum;
if ((gAiThinkingStruct->aiFlags[battlerAtk] & AI_FLAG_CONSERVATIVE) && !(gAiThinkingStruct->aiFlags[battlerAtk] & AI_FLAG_RISKY)) // Conservative assumes it deals min damage
return aiData->simulatedDmg[battlerAtk][battlerDef][moveIndex].minimum;
return AI_GetDefaultDamageRollForContext(battlerAtk, battlerDef, moveIndex, aiData, AI_ROLL_ATTACKING_PARTNER);
}
else
{
@ -298,7 +348,7 @@ bool32 ShouldRecordStatusMove(enum Move move)
return RandomPercentage(RNG_AI_ASSUME_ALL_STATUS, ASSUME_ALL_STATUS_ODDS) && IsBattleMoveStatus(move);
}
static bool32 ShouldFailForIllusion(u32 illusionSpecies, enum BattlerId battlerId)
static bool32 ShouldFailForIllusion(enum Species illusionSpecies, enum BattlerId battlerId)
{
u32 learnsetMoveIndex;
const struct LevelUpMove *learnset;
@ -338,7 +388,7 @@ void SetBattlerData(enum BattlerId battlerId)
{
if (!BattlerHasAi(battlerId) && gAiThinkingStruct->saved[battlerId].saved)
{
u32 species, illusionSpecies;
enum Species species, illusionSpecies;
enum BattleSide side = GetBattlerSide(battlerId);
// Simulate Illusion
@ -449,7 +499,7 @@ bool32 IsBattlerTrapped(enum BattlerId battlerAtk, enum BattlerId battlerDef)
return FALSE;
}
u32 GetTotalBaseStat(u32 species)
u32 GetTotalBaseStat(enum Species species)
{
return GetSpeciesBaseHP(species)
+ GetSpeciesBaseAttack(species)
@ -571,6 +621,14 @@ static inline s32 DmgRoll(s32 dmg)
return dmg;
}
static inline s32 RandomRollDmg(s32 dmg)
{
u32 randomRollPercentage = RandomUniform(RNG_AI_DMG_ROLL_RANDOM, MIN_ROLL_PERCENTAGE, MAX_ROLL_PERCENTAGE);
dmg *= randomRollPercentage;
dmg /= 100;
return dmg;
}
bool32 IsDamageMoveUnusable(struct BattleContext *ctx)
{
enum Ability battlerDefAbility;
@ -681,6 +739,8 @@ static inline s32 GetDamageByRollType(s32 dmg, enum DamageRollType rollType)
return LowestRollDmg(dmg);
else if (rollType == DMG_ROLL_HIGHEST)
return HighestRollDmg(dmg);
else if (rollType == DMG_ROLL_RANDOM)
return RandomRollDmg(dmg);
else
return DmgRoll(dmg);
}
@ -699,12 +759,13 @@ static inline void AI_RestoreBattlerTypes(enum BattlerId battlerAtk, enum Type *
gBattleMons[battlerAtk].types[2] = types[2];
}
static inline void CalcDynamicMoveDamage(struct BattleContext *ctx, u16 *medianDamage, u16 *minimumDamage, u16 *maximumDamage)
static inline void CalcDynamicMoveDamage(struct BattleContext *ctx, u16 *medianDamage, u16 *minimumDamage, u16 *maximumDamage, u16 *randomDamage)
{
enum BattleMoveEffects effect = GetMoveEffect(ctx->move);
u16 median = *medianDamage;
u16 minimum = *minimumDamage;
u16 maximum = *maximumDamage;
u16 random = *randomDamage;
u32 strikeCount = GetMoveStrikeCount(ctx->move);
@ -718,7 +779,7 @@ static inline void CalcDynamicMoveDamage(struct BattleContext *ctx, u16 *medianD
median = 0;
for (i = 0; i < partyCount; i++)
median += CalculateMoveDamage(ctx);
maximum = minimum = median;
maximum = minimum = median = random;
gBattleStruct->beatUpSlot = 0;
}
else if (strikeCount > 1 && effect != EFFECT_TRIPLE_KICK)
@ -726,6 +787,7 @@ static inline void CalcDynamicMoveDamage(struct BattleContext *ctx, u16 *medianD
median *= strikeCount;
minimum *= strikeCount;
maximum *= strikeCount;
random *= strikeCount;
}
else if (IsMultiHitMove(ctx->move))
{
@ -734,12 +796,14 @@ static inline void CalcDynamicMoveDamage(struct BattleContext *ctx, u16 *medianD
median *= GetMoveSpeciesPowerOverride_NumOfHits(ctx->move);
minimum *= GetMoveSpeciesPowerOverride_NumOfHits(ctx->move);
maximum *= GetMoveSpeciesPowerOverride_NumOfHits(ctx->move);
random *= GetMoveSpeciesPowerOverride_NumOfHits(ctx->move);
}
else if (ctx->abilityAtk == ABILITY_SKILL_LINK)
{
median *= 5;
minimum *= 5;
maximum *= 5;
random *= 5;
}
else if (ctx->holdEffectAtk == HOLD_EFFECT_LOADED_DICE)
{
@ -747,12 +811,14 @@ static inline void CalcDynamicMoveDamage(struct BattleContext *ctx, u16 *medianD
median /= 2;
minimum *= 4;
maximum *= 5;
random *= RandomUniform(RNG_AI_DMG_ROLL_RANDOM, 4, 5);
}
else
{
median *= 3;
minimum *= 2;
maximum *= 5;
random *= RandomUniform(RNG_AI_DMG_ROLL_RANDOM, 2, 5);
}
}
else if (ctx->abilityAtk == ABILITY_PARENTAL_BOND
@ -762,6 +828,7 @@ static inline void CalcDynamicMoveDamage(struct BattleContext *ctx, u16 *medianD
median += median / (B_PARENTAL_BOND_DMG >= GEN_7 ? 4 : 2);
minimum += minimum / (B_PARENTAL_BOND_DMG >= GEN_7 ? 4 : 2);
maximum += maximum / (B_PARENTAL_BOND_DMG >= GEN_7 ? 4 : 2);
random += random / (B_PARENTAL_BOND_DMG >= GEN_7 ? 4 : 2);
}
if (median == 0)
@ -770,10 +837,13 @@ static inline void CalcDynamicMoveDamage(struct BattleContext *ctx, u16 *medianD
minimum = 1;
if (maximum == 0)
maximum = 1;
if (random == 0)
random = 1;
*medianDamage = median;
*minimumDamage = minimum;
*maximumDamage = maximum;
*randomDamage = random;
}
static inline bool32 ShouldCalcCritDamage(struct BattleContext *ctx)
@ -889,6 +959,7 @@ struct SimulatedDamage AI_CalcDamage(enum Move move, enum BattlerId battlerAtk,
ctx.abilityDef = AI_GetMoldBreakerSanitizedAbility(battlerAtk, ctx.abilityAtk, aiData->abilities[battlerDef], ctx.holdEffectDef, move);
ctx.isCrit = ShouldCalcCritDamage(&ctx);
ctx.typeEffectivenessModifier = CalcTypeEffectivenessMultiplier(&ctx);
AI_SetBattlerTurnOrder(ctx.aiTurnOrder);
u32 movePower = GetMovePower(move);
@ -901,7 +972,7 @@ struct SimulatedDamage AI_CalcDamage(enum Move move, enum BattlerId battlerAtk,
s32 fixedDamage = DoFixedDamageMoveCalc(&ctx);
if (fixedDamage != INT32_MAX)
{
simDamage.minimum = simDamage.median = simDamage.maximum = fixedDamage;
simDamage.minimum = simDamage.median = simDamage.maximum = simDamage.random = fixedDamage;
}
else if (moveEffect == EFFECT_TRIPLE_KICK)
{
@ -914,11 +985,14 @@ struct SimulatedDamage AI_CalcDamage(enum Move move, enum BattlerId battlerAtk,
damageByRollType = GetDamageByRollType(oneTripleKickHit, DMG_ROLL_LOWEST);
simDamage.minimum += AI_ApplyModifiersAfterDmgRoll(&ctx, damageByRollType);
damageByRollType = GetDamageByRollType(oneTripleKickHit, DMG_ROLL_DEFAULT);
damageByRollType = GetDamageByRollType(oneTripleKickHit, DMG_ROLL_MEDIAN);
simDamage.median += AI_ApplyModifiersAfterDmgRoll(&ctx, damageByRollType);
damageByRollType = GetDamageByRollType(oneTripleKickHit, DMG_ROLL_HIGHEST);
simDamage.maximum += AI_ApplyModifiersAfterDmgRoll(&ctx, damageByRollType);
damageByRollType = GetDamageByRollType(oneTripleKickHit, DMG_ROLL_RANDOM);
simDamage.random += AI_ApplyModifiersAfterDmgRoll(&ctx, damageByRollType);
}
}
else
@ -928,15 +1002,18 @@ struct SimulatedDamage AI_CalcDamage(enum Move move, enum BattlerId battlerAtk,
simDamage.minimum = GetDamageByRollType(damage, DMG_ROLL_LOWEST);
simDamage.minimum = AI_ApplyModifiersAfterDmgRoll(&ctx, simDamage.minimum);
simDamage.median = GetDamageByRollType(damage, DMG_ROLL_DEFAULT);
simDamage.median = GetDamageByRollType(damage, DMG_ROLL_MEDIAN);
simDamage.median = AI_ApplyModifiersAfterDmgRoll(&ctx, simDamage.median);
simDamage.maximum = GetDamageByRollType(damage, DMG_ROLL_HIGHEST);
simDamage.maximum = AI_ApplyModifiersAfterDmgRoll(&ctx, simDamage.maximum);
simDamage.random = GetDamageByRollType(damage, DMG_ROLL_RANDOM);
simDamage.random = AI_ApplyModifiersAfterDmgRoll(&ctx, simDamage.random);
}
if (GetActiveGimmick(battlerAtk) != GIMMICK_Z_MOVE)
CalcDynamicMoveDamage(&ctx, &simDamage.median, &simDamage.minimum, &simDamage.maximum);
CalcDynamicMoveDamage(&ctx, &simDamage.median, &simDamage.minimum, &simDamage.maximum, &simDamage.random);
AI_RestoreBattlerTypes(battlerAtk, types);
}
@ -945,6 +1022,7 @@ struct SimulatedDamage AI_CalcDamage(enum Move move, enum BattlerId battlerAtk,
simDamage.minimum = 0;
simDamage.median = 0;
simDamage.maximum = 0;
simDamage.random = 0;
}
// convert multiper to AI_EFFECTIVENESS_xX
@ -1490,14 +1568,14 @@ bool32 CanTargetFaintAi(enum BattlerId battlerDef, enum BattlerId battlerAtk)
return FALSE;
}
u32 NoOfHitsForTargetToFaintBattler(enum BattlerId battlerDef, enum BattlerId battlerAtk, enum AiConsiderEndure considerEndure)
u32 NoOfHitsForTargetToFaintBattler(enum BattlerId battlerDef, enum BattlerId battlerAtk, enum DamageCalcContext calcContext, enum AiConsiderEndure considerEndure)
{
u32 currNumberOfHits;
u32 leastNumberOfHits = UNKNOWN_NO_OF_HITS;
for (u32 moveIndex = 0; moveIndex < MAX_MON_MOVES; moveIndex++)
{
currNumberOfHits = GetNoOfHitsToKOBattler(battlerDef, battlerAtk, moveIndex, AI_DEFENDING, considerEndure);
currNumberOfHits = GetNoOfHitsToKOBattler(battlerDef, battlerAtk, moveIndex, calcContext, considerEndure);
if (currNumberOfHits != 0)
{
if (currNumberOfHits < leastNumberOfHits)
@ -1544,7 +1622,7 @@ void GetBestDmgMovesFromBattler(enum BattlerId battlerAtk, enum BattlerId battle
{
for (u32 moveIndex = 0; moveIndex < MAX_MON_MOVES; moveIndex++)
{
if (CanIndexMoveFaintTarget(battlerAtk, battlerDef, moveIndex, AI_ATTACKING))
if (CanIndexMoveFaintTarget(battlerAtk, battlerDef, moveIndex, calcContext))
bestMoves[countBestMoves++] = moves[moveIndex];
}
}
@ -1590,7 +1668,7 @@ bool32 IsBestDmgMove(enum BattlerId battlerAtk, enum BattlerId battlerDef, enum
enum Move bestMoves[MAX_MON_MOVES] = {MOVE_NONE};
u32 index = GetMoveIndex(battlerAtk, move);
if (CanIndexMoveFaintTarget(battlerAtk, battlerDef, index, AI_ATTACKING))
if (CanIndexMoveFaintTarget(battlerAtk, battlerDef, index, calcContext))
return TRUE;
GetBestDmgMovesFromBattler(battlerAtk, battlerDef, calcContext, bestMoves);
@ -1873,6 +1951,7 @@ u32 AI_GetSwitchinWeather(enum BattlerId battler)
case ABILITY_DRIZZLE:
return B_WEATHER_RAIN_NORMAL;
case ABILITY_DROUGHT:
case ABILITY_ORICHALCUM_PULSE:
return B_WEATHER_SUN_NORMAL;
case ABILITY_SAND_STREAM:
return B_WEATHER_SANDSTORM;
@ -2460,7 +2539,7 @@ bool32 CanIndexMoveFaintTarget(enum BattlerId battlerAtk, enum BattlerId battler
enum Move *moves = gBattleMons[battlerAtk].moves;
if (IsDoubleBattle() && battlerDef == BATTLE_PARTNER(battlerAtk))
dmg = gAiLogicData->simulatedDmg[battlerAtk][battlerDef][moveIndex].maximum; // Attacking partner, be careful
dmg = AI_GetDamage(battlerAtk, battlerDef, moveIndex, AI_ATTACKING_PARTNER, gAiLogicData); // Attacking partner, be careful
else
dmg = AI_GetDamage(battlerAtk, battlerDef, moveIndex, calcContext, gAiLogicData);
@ -3945,7 +4024,7 @@ static inline bool32 RecoveryEnablesWinning1v1(enum BattlerId battlerAtk, enum B
{
if (!CanTargetFaintAi(battlerDef, battlerAtk)
&& GetBestDmgFromBattler(battlerDef, battlerAtk, AI_DEFENDING) < healAmount
&& NoOfHitsForTargetToFaintBattler(battlerDef, battlerAtk, CONSIDER_ENDURE) < NoOfHitsForTargetToFaintBattlerWithMod(battlerDef, battlerAtk, healAmount))
&& NoOfHitsForTargetToFaintBattler(battlerDef, battlerAtk, AI_DEFENDING, CONSIDER_ENDURE) < NoOfHitsForTargetToFaintBattlerWithMod(battlerDef, battlerAtk, healAmount))
return TRUE; // target can't faint attacker and is dealing less damage than we're healing
else if (!CanTargetFaintAi(battlerDef, battlerAtk) && gAiLogicData->hpPercents[battlerAtk] < ENABLE_RECOVERY_THRESHOLD && RandomPercentage(RNG_AI_SHOULD_RECOVER, SHOULD_RECOVER_CHANCE))
return TRUE; // target can't faint attacker at all, generally safe
@ -4531,28 +4610,6 @@ void FreeRestoreAiLogicData(struct AiLogicData *savedAiLogicData)
Free(savedAiLogicData);
}
// Set potential field effect from ability for switch in
void SetBattlerFieldStatusForSwitchin(enum BattlerId battler)
{
switch (gAiLogicData->abilities[battler])
{
case ABILITY_VESSEL_OF_RUIN:
gBattleMons[battler].volatiles.vesselOfRuin = TRUE;
break;
case ABILITY_SWORD_OF_RUIN:
gBattleMons[battler].volatiles.swordOfRuin = TRUE;
break;
case ABILITY_TABLETS_OF_RUIN:
gBattleMons[battler].volatiles.tabletsOfRuin = TRUE;
break;
case ABILITY_BEADS_OF_RUIN:
gBattleMons[battler].volatiles.beadsOfRuin = TRUE;
break;
default:
break;
}
}
// party logic
s32 CountUsablePartyMons(enum BattlerId battlerId)
{
@ -4829,7 +4886,7 @@ static u32 GetStagesOfStatChange(enum StatChange statChange)
static enum AIScore IncreaseStatUpScoreInternal(enum BattlerId battlerAtk, enum BattlerId battlerDef, enum StatChange statChange, bool32 considerContrary)
{
enum AIScore tempScore = NO_INCREASE;
u32 noOfHitsToFaint = NoOfHitsForTargetToFaintBattler(battlerDef, battlerAtk, DONT_CONSIDER_ENDURE);
u32 noOfHitsToFaint = NoOfHitsForTargetToFaintBattler(battlerDef, battlerAtk, AI_SHOULD_SETUP_DEFENDING, DONT_CONSIDER_ENDURE);
enum Move predictedMoveSpeedCheck = GetIncomingMoveSpeedCheck(battlerAtk, battlerDef, gAiLogicData);
bool32 aiIsFaster = AI_IsFaster(battlerAtk, battlerDef, MOVE_NONE, predictedMoveSpeedCheck, DONT_CONSIDER_PRIORITY); // Don't care about the priority of our setup move, care about outspeeding otherwise
bool32 shouldSetUp = ((noOfHitsToFaint >= 2 && aiIsFaster) || (noOfHitsToFaint >= 3 && !aiIsFaster) || noOfHitsToFaint == UNKNOWN_NO_OF_HITS);
@ -5877,8 +5934,9 @@ bool32 DoesIntimidateRaiseStats(enum Ability ability)
case ABILITY_CONTRARY:
case ABILITY_DEFIANT:
case ABILITY_GUARD_DOG:
case ABILITY_RATTLED:
return TRUE;
case ABILITY_RATTLED:
return GetConfig(B_UPDATED_INTIMIDATE) >= GEN_8;
default:
return FALSE;
}
@ -6443,3 +6501,23 @@ bool32 IsPartyMonPlannedToBeSwitchedInByPartner(u32 partyIndex, enum BattlerId b
return TRUE;
return FALSE;
}
static void AI_SetBattlerTurnOrder(u8 *aiTurnOrder)
{
for (u32 battler = 0; battler < gBattlersCount; battler++)
aiTurnOrder[battler] = battler;
for (u32 i = 0; i < gBattlersCount; i++)
{
for (u32 j = 0; j < gBattlersCount; j++)
{
if (AI_WhoStrikesFirst(aiTurnOrder[i], aiTurnOrder[j], MOVE_NONE, MOVE_NONE, DONT_CONSIDER_PRIORITY) == AI_IS_FASTER)
{
u32 temp = aiTurnOrder[i];
aiTurnOrder[i] = aiTurnOrder[j];
aiTurnOrder[j] = temp;
}
}
}
}

View File

@ -119,7 +119,7 @@ EWRAM_DATA static u8 sAnimBackgroundFadeState = 0;
EWRAM_DATA u16 gAnimMoveIndex = 0;
EWRAM_DATA enum BattlerId gBattleAnimAttacker = 0;
EWRAM_DATA enum BattlerId gBattleAnimTarget = 0;
EWRAM_DATA u16 gAnimBattlerSpecies[MAX_BATTLERS_COUNT] = {0};
EWRAM_DATA enum Species gAnimBattlerSpecies[MAX_BATTLERS_COUNT] = {SPECIES_NONE};
EWRAM_DATA u8 gAnimCustomPanning = 0;
EWRAM_DATA static bool8 sAnimHideHpBoxes = FALSE;

View File

@ -907,7 +907,7 @@ void AnimTask_MetallicShine(u8 taskId)
{
CMD_ARGS(permanent, useColor, color);
u16 species;
enum Species species;
u8 spriteId;
u8 newSpriteId;
u16 paletteNum;

View File

@ -3372,7 +3372,7 @@ void AnimTask_RolePlaySilhouette(u8 taskId)
{
bool8 isBackPic, isShiny;
u32 personality;
u16 species;
enum Species species;
s16 xOffset;
u32 priority;
u8 spriteId;
@ -5259,7 +5259,7 @@ void AnimTask_SnatchOpposingMonMove(u8 taskId)
{
u8 spriteId, spriteId2;
int personality;
u16 species;
enum Species species;
u8 subpriority;
bool8 isBackPic, isShiny;
s16 x;

View File

@ -79,7 +79,7 @@ static const struct SpriteSheet sSpriteSheets_MoveEffectMons[] =
u8 GetBattlerSpriteCoord(enum BattlerId battler, u8 coordType)
{
u8 retVal;
u16 species;
enum Species species;
struct Pokemon *mon, *illusionMon;
struct BattleSpriteInfo *spriteInfo;
@ -130,7 +130,7 @@ u8 GetBattlerSpriteCoord(enum BattlerId battler, u8 coordType)
return retVal;
}
u8 GetBattlerYDelta(enum BattlerId battler, u16 species)
u8 GetBattlerYDelta(enum BattlerId battler, enum Species species)
{
u32 personality;
struct BattleSpriteInfo *spriteInfo;
@ -168,7 +168,7 @@ u8 GetBattlerYDelta(enum BattlerId battler, u16 species)
return ret;
}
u8 GetBattlerElevation(enum BattlerId battler, u16 species)
u8 GetBattlerElevation(enum BattlerId battler, enum Species species)
{
u8 ret = 0;
if (!IsOnPlayerSide(battler))
@ -182,7 +182,7 @@ u8 GetBattlerElevation(enum BattlerId battler, u16 species)
return ret;
}
u8 GetBattlerSpriteFinal_Y(enum BattlerId battler, u16 species, bool8 a3)
u8 GetBattlerSpriteFinal_Y(enum BattlerId battler, enum Species species, bool32 a3)
{
u16 offset;
u8 y;
@ -209,7 +209,7 @@ u8 GetBattlerSpriteFinal_Y(enum BattlerId battler, u16 species, bool8 a3)
u8 GetBattlerSpriteCoord2(enum BattlerId battler, u8 coordType)
{
u16 species;
enum Species species;
struct BattleSpriteInfo *spriteInfo;
if (coordType == BATTLER_COORD_Y_PIC_OFFSET || coordType == BATTLER_COORD_Y_PIC_OFFSET_DEFAULT)
@ -257,7 +257,7 @@ u8 GetSubstituteSpriteDefault_Y(enum BattlerId battler)
u8 GetBattlerYCoordWithElevation(enum BattlerId battler)
{
u16 species;
enum Species species;
u8 y;
struct BattleSpriteInfo *spriteInfo;
@ -1870,7 +1870,7 @@ static u16 GetBattlerYDeltaFromSpriteId(u8 spriteId)
{
struct BattleSpriteInfo *spriteInfo;
enum BattlerId battler = gSprites[spriteId].data[0];
u16 species;
enum Species species;
u16 i;
for (i = 0; i < MAX_BATTLERS_COUNT; i++)
@ -2040,7 +2040,7 @@ u8 GetBattlerSpriteBGPriorityRank(enum BattlerId battler)
}
// Create Pokémon sprite to be used for a move animation effect (e.g. Role Play / Snatch)
u8 CreateAdditionalMonSpriteForMoveAnim(u16 species, bool8 isBackpic, u8 id, s16 x, s16 y, u8 subpriority, u32 personality, bool8 isShiny, enum BattlerId battler)
u8 CreateAdditionalMonSpriteForMoveAnim(enum Species species, bool32 isBackpic, u8 id, s16 x, s16 y, u8 subpriority, u32 personality, bool32 isShiny, enum BattlerId battler)
{
u8 spriteId;
u16 sheet = LoadSpriteSheet(&sSpriteSheets_MoveEffectMons[id]);
@ -2088,7 +2088,7 @@ void DestroySpriteAndFreeResources_(struct Sprite *sprite)
s16 GetBattlerSpriteCoordAttr(enum BattlerId battler, u8 attr)
{
u16 species;
enum Species species;
u32 personality;
int ret;
u8 size;
@ -2244,7 +2244,7 @@ void SetToPartnerPositions(enum BattlerId battler, bool8 respectMonPicOffsets, s
*y = returnY;
}
u8 CreateInvisibleSpriteCopy(int battler, u8 spriteId, int species)
u8 CreateInvisibleSpriteCopy(enum BattlerId battler, u8 spriteId, enum Species species)
{
u8 newSpriteId = CreateInvisibleSpriteWithCallback(SpriteCallbackDummy);
gSprites[newSpriteId] = gSprites[spriteId];

View File

@ -133,7 +133,7 @@ static void SoundTask_LoopSEAdjustPanning_Step(u8 taskId)
void SoundTask_PlayCryHighPitch(u8 taskId)
{
u16 species = 0;
enum Species species = 0;
s8 pan = BattleAnimAdjustPanning(SOUND_PAN_ATTACKER);
enum AnimBattler animBattler = gBattleAnimArgs[0];
if (IsContest())
@ -186,7 +186,7 @@ void SoundTask_PlayCryHighPitch(u8 taskId)
void SoundTask_PlayDoubleCry(u8 taskId)
{
u16 species = 0;
enum Species species = 0;
s8 pan = BattleAnimAdjustPanning(SOUND_PAN_ATTACKER);
enum AnimBattler animBattler = gBattleAnimArgs[0];
if (IsContest())
@ -252,7 +252,7 @@ void SoundTask_PlayDoubleCry(u8 taskId)
static void SoundTask_PlayDoubleCry_Step(u8 taskId)
{
u16 species = gTasks[taskId].data[1];
enum Species species = gTasks[taskId].data[1];
s8 pan = gTasks[taskId].data[2];
if (gTasks[taskId].data[9] < 2)
@ -295,7 +295,7 @@ void SoundTask_WaitForCry(u8 taskId)
void SoundTask_PlayNormalCry(u8 taskId)
{
u16 species = (GetIllusionMonSpecies(gBattleAnimAttacker) != SPECIES_NONE) ? GetIllusionMonSpecies(gBattleAnimAttacker) : gAnimBattlerSpecies[gBattleAnimAttacker];
enum Species species = (GetIllusionMonSpecies(gBattleAnimAttacker) != SPECIES_NONE) ? GetIllusionMonSpecies(gBattleAnimAttacker) : gAnimBattlerSpecies[gBattleAnimAttacker];
PlayCry_ByMode(species, BattleAnimAdjustPanning(SOUND_PAN_ATTACKER), CRY_MODE_NORMAL);
gTasks[taskId].func = SoundTask_WaitForCry;
}
@ -307,7 +307,7 @@ void SoundTask_PlayNormalCry(u8 taskId)
void SoundTask_PlayCryWithEcho(u8 taskId)
{
u16 species;
enum Species species;
s8 pan;
gTasks[taskId].tLastCry = gBattleAnimArgs[0];
@ -329,14 +329,14 @@ void SoundTask_PlayCryWithEcho(u8 taskId)
void SoundTask_PlayDynamaxCry(u8 taskId)
{
u16 species = (GetIllusionMonSpecies(gBattleAnimAttacker) != SPECIES_NONE) ? GetIllusionMonSpecies(gBattleAnimAttacker) : gAnimBattlerSpecies[gBattleAnimAttacker];
enum Species species = (GetIllusionMonSpecies(gBattleAnimAttacker) != SPECIES_NONE) ? GetIllusionMonSpecies(gBattleAnimAttacker) : gAnimBattlerSpecies[gBattleAnimAttacker];
PlayCry_ByMode(species, BattleAnimAdjustPanning(SOUND_PAN_ATTACKER), CRY_MODE_DYNAMAX);
gTasks[taskId].func = SoundTask_WaitForCry;
}
static void SoundTask_PlayCryWithEcho_Step(u8 taskId)
{
u16 species = gTasks[taskId].tSpecies;
enum Species species = gTasks[taskId].tSpecies;
s8 pan = gTasks[taskId].tPan;
// Note the cases are not in order of execution

View File

@ -19,7 +19,7 @@ struct AnimStatsChangeData
enum BattlerId battler2;
bool8 hidBattler2;
s16 data[8];
u16 species;
enum Species species;
};
static EWRAM_DATA struct AnimStatsChangeData *sAnimStatsChangeData = {0};
@ -248,7 +248,7 @@ static void AnimMonTrace(struct Sprite *sprite)
// Only used by Curse for non-Ghost mons
void AnimTask_DrawFallingWhiteLinesOnAttacker(u8 taskId)
{
u16 species;
enum Species species;
int spriteId, newSpriteId;
u16 var0;
u32 bg1Cnt;
@ -770,7 +770,7 @@ void AnimTask_SetAllNonAttackersInvisiblity(u8 taskId)
void StartMonScrollingBgMask(u8 taskId, int UNUSED unused, u16 scrollSpeed, enum BattlerId battler, bool8 includePartner, u8 numFadeSteps, u8 fadeStepDelay, u8 duration, const u32 *gfx, const u32 *tilemap, const u16 *palette)
{
u16 species;
enum Species species;
u8 spriteId, spriteId2;
u32 bg1Cnt;
struct BattleAnimBgData animBgData;

View File

@ -846,7 +846,7 @@ static void OakOldManHandlePlaySE(enum BattlerId battler)
static void OakOldManHandleFaintingCry(enum BattlerId battler)
{
u16 species = GetMonData(&gPlayerParty[gBattlerPartyIndexes[battler]], MON_DATA_SPECIES);
enum Species species = GetMonData(&gPlayerParty[gBattlerPartyIndexes[battler]], MON_DATA_SPECIES);
PlayCry_Normal(species, 25);
OakOldManBufferExecCompleted(battler);

View File

@ -1424,7 +1424,7 @@ static void Task_GiveExpToMon(u8 taskId)
if (GetBattlerCoordsIndex(battler) == BATTLE_COORDS_DOUBLES || monId != gBattlerPartyIndexes[battler]) // Give exp without moving the expbar.
{
struct Pokemon *mon = &gPlayerParty[monId];
u16 species = GetMonData(mon, MON_DATA_SPECIES);
enum Species species = GetMonData(mon, MON_DATA_SPECIES);
u8 level = GetMonData(mon, MON_DATA_LEVEL);
u32 currExp = GetMonData(mon, MON_DATA_EXP);
u32 nextLvlExp = gExperienceTables[gSpeciesInfo[species].growthRate][level + 1];
@ -1471,7 +1471,7 @@ static void Task_PrepareToGiveExpWithExpBar(u8 taskId)
enum BattlerId battler = gTasks[taskId].tExpTask_battler;
struct Pokemon *mon = &gPlayerParty[monIndex];
u8 level = GetMonData(mon, MON_DATA_LEVEL);
u16 species = GetMonData(mon, MON_DATA_SPECIES);
enum Species species = GetMonData(mon, MON_DATA_SPECIES);
u32 exp = GetMonData(mon, MON_DATA_EXP);
u32 currLvlExp = gExperienceTables[gSpeciesInfo[species].growthRate][level];
u32 expToNextLvl;
@ -1487,7 +1487,7 @@ static void Task_PrepareToGiveExpWithExpBar(u8 taskId)
static void Task_GiveExpWithExpBar(u8 taskId)
{
u32 level, expAfterGain;
u16 species;
enum Species species;
u32 oldMaxHP;
s32 currExp, expOnNextLvl, newExpPoints;
@ -1710,7 +1710,7 @@ static void MoveSelectionDisplayPpNumber(enum BattlerId battler)
static void MoveSelectionDisplayMoveType(enum BattlerId battler)
{
u8 *txtPtr, *end;
u32 speciesId = gBattleMons[battler].species;
enum Species speciesId = gBattleMons[battler].species;
struct ChooseMoveStruct *moveInfo = (struct ChooseMoveStruct *)(&gBattleResources->bufferA[battler][4]);
txtPtr = StringCopy(gDisplayedStringBattle, gText_MoveInterfaceType);
enum Move move = moveInfo->moves[gMoveSelectionCursor[battler]];
@ -2003,8 +2003,6 @@ static void HandleChooseActionAfterDma3(enum BattlerId battler)
gBattle_BG0_Y = DISPLAY_HEIGHT;
if (gBattleStruct->aiDelayTimer != 0)
{
gBattleStruct->aiDelayFrames = gMain.vblankCounter1 - gBattleStruct->aiDelayTimer;
gBattleStruct->aiDelayTimer = 0;
if (DEBUG_AI_DELAY_TIMER)
{
static const u8 sFramesText[] = _(" frames thinking\n");
@ -2017,6 +2015,8 @@ static void HandleChooseActionAfterDma3(enum BattlerId battler)
StringAppend(gDisplayedStringBattle, sCyclesText);
BattlePutTextOnWindow(gDisplayedStringBattle, B_WIN_ACTION_PROMPT);
}
gBattleStruct->aiDelayTimer = 0;
gBattleStruct->aiDelayFrames = 0;
}
gBattlerControllerFuncs[battler] = HandleInputChooseAction;
}

View File

@ -343,7 +343,7 @@ static void SafariHandleChoosePokemon(enum BattlerId battler)
// Player is not a pokemon, so it can't really faint in the Safari anyway.
static void SafariHandleFaintingCry(enum BattlerId battler)
{
u16 species = GetMonData(GetBattlerMon(battler), MON_DATA_SPECIES);
enum Species species = GetMonData(GetBattlerMon(battler), MON_DATA_SPECIES);
PlayCry_Normal(species, 25);
BtlController_Complete(battler);

View File

@ -358,7 +358,7 @@ static void WallyHandleChooseItem(enum BattlerId battler)
// Wally's Pokémon during the tutorial is never intended to faint, so that's probably why it's different here.
static void WallyHandleFaintingCry(enum BattlerId battler)
{
u16 species = GetMonData(GetBattlerMon(battler), MON_DATA_SPECIES);
enum Species species = GetMonData(GetBattlerMon(battler), MON_DATA_SPECIES);
PlayCry_Normal(species, 25);
BtlController_Complete(battler);

View File

@ -385,7 +385,7 @@ static void InitBtlControllersInternal(void)
bool32 IsValidForBattle(struct Pokemon *mon)
{
u32 species = GetMonData(mon, MON_DATA_SPECIES_OR_EGG);
enum Species species = GetMonData(mon, MON_DATA_SPECIES_OR_EGG);
return (species != SPECIES_NONE
&& species != SPECIES_EGG
&& GetMonData(mon, MON_DATA_HP) != 0
@ -394,7 +394,7 @@ bool32 IsValidForBattle(struct Pokemon *mon)
bool32 IsValidForBattleButDead(struct Pokemon *mon)
{
u32 species = GetMonData(mon, MON_DATA_SPECIES_OR_EGG);
enum Species species = GetMonData(mon, MON_DATA_SPECIES_OR_EGG);
return (species != SPECIES_NONE
&& species != SPECIES_EGG
&& GetMonData(mon, MON_DATA_IS_EGG) == FALSE);
@ -1993,7 +1993,7 @@ static bool8 ShouldDoSlideInAnim(enum BattlerId battler)
void StartSendOutAnim(enum BattlerId battler, bool32 dontClearTransform, bool32 dontClearSubstituteBit, bool32 doSlideIn)
{
u16 species;
enum Species species;
struct Pokemon *mon = GetBattlerMon(battler);
u32 sendoutType;
@ -2337,7 +2337,7 @@ void BtlController_HandleLoadMonSprite(enum BattlerId battler)
{
u32 y;
struct Pokemon *mon = GetBattlerMon(battler);
u16 species = GetBattlerVisualSpecies(battler);
enum Species species = GetBattlerVisualSpecies(battler);
if (gBattleTypeFlags & BATTLE_TYPE_GHOST && GetBattlerSide(battler) == B_SIDE_OPPONENT)
{
@ -3059,7 +3059,7 @@ static void AnimateMonAfterKnockout(enum BattlerId battler)
static void LaunchKOAnimation(enum BattlerId battlerId, u16 animId, bool32 isFront)
{
u32 species = GetBattlerVisualSpecies(battlerId);
enum Species species = GetBattlerVisualSpecies(battlerId);
u32 spriteId = gBattlerSpriteIds[battlerId];
gBattleStruct->battlerKOAnimsRunning++;
@ -3081,7 +3081,7 @@ static void LaunchKOAnimation(enum BattlerId battlerId, u16 animId, bool32 isFro
static u32 ReturnAnimIdForBattler(bool32 wasPlayerSideKnockedOut, u32 specificBattler)
{
u32 species = GetBattlerVisualSpecies(specificBattler);
enum Species species = GetBattlerVisualSpecies(specificBattler);
if (wasPlayerSideKnockedOut)
return gSpeciesInfo[species].frontAnimId;
else

View File

@ -1068,7 +1068,7 @@ static void Task_ShowAiParty(u8 taskId)
aiMons = gAiPartyData->mons[GetBattlerSide(data->aiBattlerId)];
for (i = 0; i < gAiPartyData->count[GetBattlerSide(data->aiBattlerId)]; i++)
{
u16 species = SPECIES_NONE; // Question mark
enum Species species = SPECIES_NONE; // Question mark
if (aiMons[i].wasSentInBattle && aiMons[i].species)
species = aiMons[i].species;
data->spriteIds.aiPartyIcons[i] = CreateMonIcon(species, SpriteCallbackDummy, (i * 41) + 15, 7, 1, 0);

View File

@ -1911,7 +1911,7 @@ static void InitDomeTrainers(void)
{
int i, j, k;
int monLevel;
int species[FRONTIER_PARTY_SIZE];
enum Species species[FRONTIER_PARTY_SIZE];
int monTypesBits, monTypesCount;
int trainerId;
int monId;
@ -1919,9 +1919,9 @@ static void InitDomeTrainers(void)
int *statValues;
u8 ivs = 0;
species[0] = 0;
species[1] = 0;
species[2] = 0;
species[0] = SPECIES_NONE;
species[1] = SPECIES_NONE;
species[2] = SPECIES_NONE;
rankingScores = AllocZeroed(sizeof(u16) * DOME_TOURNAMENT_TRAINERS_COUNT);
statValues = AllocZeroed(sizeof(int) * NUM_STATS);
@ -4017,7 +4017,7 @@ static bool32 IsDomeStatusMoveEffect(enum Move move)
static bool32 IsDomeRareMove(enum Move move)
{
u16 i, j;
u16 species = 0;
enum Species species = SPECIES_NONE;
for (i = 0; i < NUM_SPECIES; i++)
{
if (!IsSpeciesEnabled(i))
@ -5125,7 +5125,7 @@ static u16 GetWinningMove(int winnerTournamentId, int loserTournamentId, u8 roun
for (k = 0; k < FRONTIER_PARTY_SIZE; k++)
{
u32 personality = 0;
u32 targetSpecies = 0;
enum Species targetSpecies = SPECIES_NONE;
enum Ability targetAbility = ABILITY_NONE;
uq4_12_t typeMultiplier = 0;
do
@ -5724,7 +5724,7 @@ static void InitRandomTourneyTreeResults(void)
{
int i, j, k;
int monLevel;
int species[FRONTIER_PARTY_SIZE];
enum Species species[FRONTIER_PARTY_SIZE];
int monTypesBits;
int trainerId;
int monId;
@ -5735,9 +5735,9 @@ static void InitRandomTourneyTreeResults(void)
int *statValues;
u8 ivs = 0;
species[0] = 0;
species[1] = 0;
species[2] = 0;
species[0] = SPECIES_NONE;
species[1] = SPECIES_NONE;
species[2] = SPECIES_NONE;
if ((gSaveBlock2Ptr->frontier.domeLvlMode != -gSaveBlock2Ptr->frontier.domeBattleMode) && gSaveBlock2Ptr->frontier.challengeStatus != CHALLENGE_STATUS_SAVING)
return;
@ -5894,7 +5894,7 @@ static void DecideRoundWinners(u8 roundId)
int i;
int moveSlot, monId1, monId2;
int tournamentId1, tournamentId2;
int species;
enum Species species;
int points1 = 0, points2 = 0;
for (i = 0; i < DOME_TOURNAMENT_TRAINERS_COUNT; i++)

View File

@ -26,7 +26,7 @@ static enum MaxPowerTier GetMaxPowerTier(enum Move move);
struct GMaxMove
{
u16 species;
enum Species species;
enum Type moveType;
u16 gmaxMove;
};
@ -72,7 +72,7 @@ static const struct GMaxMove sGMaxMoveTable[] =
// Returns whether a battler can Dynamax.
bool32 CanDynamax(enum BattlerId battler)
{
u16 species = GetBattlerVisualSpecies(battler);
enum Species species = GetBattlerVisualSpecies(battler);
enum HoldEffect holdEffect = GetBattlerHoldEffectIgnoreNegation(battler);
// Prevents Zigzagoon from dynamaxing in vanilla.
@ -244,8 +244,8 @@ static enum Move GetTypeBasedMaxMove(enum BattlerId battler, enum Type type)
{
// Gigantamax check
u32 i;
u32 species = gBattleMons[battler].species;
u32 targetSpecies = species;
enum Species species = gBattleMons[battler].species;
enum Species targetSpecies = species;
enum Ability ability = GetBattlerAbility(battler);
if (!gSpeciesInfo[species].isGigantamax)

View File

@ -235,7 +235,7 @@ static void SetPerformedRentalSwap(void)
static void GenerateOpponentMons(void)
{
int i, j, k;
u16 species[FRONTIER_PARTY_SIZE];
enum Species species[FRONTIER_PARTY_SIZE];
u16 heldItems[FRONTIER_PARTY_SIZE];
int firstMonId = 0;
u16 trainerId = 0;
@ -390,8 +390,8 @@ static void GenerateInitialRentalMons(void)
u8 factoryBattleMode;
u8 rentalRank;
u16 monId;
u16 currSpecies;
u16 species[PARTY_SIZE];
enum Species currSpecies;
enum Species species[PARTY_SIZE];
u16 monIds[PARTY_SIZE];
u16 heldItems[PARTY_SIZE];
@ -490,7 +490,7 @@ static void GetOpponentMostCommonMonType(void)
typeCounts[i] = 0;
for (i = 0; i < FRONTIER_PARTY_SIZE; i++)
{
u32 species = gFacilityTrainerMons[gFrontierTempParty[i]].species;
enum Species species = gFacilityTrainerMons[gFrontierTempParty[i]].species;
typeCounts[GetSpeciesType(species, 0)]++;
if (GetSpeciesType(species, 0) != GetSpeciesType(species, 1))
typeCounts[GetSpeciesType(species, 1)]++;
@ -654,8 +654,8 @@ u8 GetFactoryMonFixedIV(u8 challengeNum, bool8 isLastBattle)
void FillFactoryBrainParty(void)
{
int i, j, k;
u16 species[FRONTIER_PARTY_SIZE];
u16 heldItems[FRONTIER_PARTY_SIZE];
enum Species species[FRONTIER_PARTY_SIZE];
enum Item heldItems[FRONTIER_PARTY_SIZE];
int monLevel;
u8 fixedIV;
u32 otId;

View File

@ -1831,7 +1831,7 @@ static void Select_PrintRentalPkmnString(void)
static void Select_PrintMonSpecies(void)
{
u16 species;
enum Species species;
u8 x;
u8 monId = sFactorySelectScreen->cursorPos;
@ -1948,7 +1948,7 @@ static u8 Select_OptionOthers(void)
static void Select_PrintMonCategory(void)
{
u16 species;
enum Species species;
u8 text[30];
u8 x;
u8 monId = sFactorySelectScreen->cursorPos;
@ -1968,7 +1968,7 @@ static void Select_CreateMonSprite(void)
{
u8 monId = sFactorySelectScreen->cursorPos;
struct Pokemon *mon = &sFactorySelectScreen->mons[monId].monData;
u16 species = GetMonData(mon, MON_DATA_SPECIES);
enum Species species = GetMonData(mon, MON_DATA_SPECIES);
u32 personality = GetMonData(mon, MON_DATA_PERSONALITY);
bool8 isShiny = GetMonData(mon, MON_DATA_IS_SHINY);
@ -1987,7 +1987,7 @@ static void Select_SetMonPicAnimating(bool8 animating)
static void Select_ReshowMonSprite(void)
{
struct Pokemon *mon;
u16 species;
enum Species species;
u32 personality;
bool8 isShiny;
@ -2017,7 +2017,7 @@ static void Select_CreateChosenMonsSprites(void)
if (sFactorySelectScreen->mons[j].selectedId == i + 1)
{
struct Pokemon *mon = &sFactorySelectScreen->mons[j].monData;
u16 species = GetMonData(mon, MON_DATA_SPECIES);
enum Species species = GetMonData(mon, MON_DATA_SPECIES);
u32 personality = GetMonData(mon, MON_DATA_PERSONALITY);
bool8 isShiny = GetMonData(mon, MON_DATA_IS_SHINY);
@ -2209,7 +2209,7 @@ static void Select_SetWinRegs(s16 mWin0H, s16 nWin0H, s16 mWin0V, s16 nWin0V)
static bool32 Select_AreSpeciesValid(u16 monId)
{
u8 i, j;
u32 species = gFacilityTrainerMons[monId].species;
enum Species species = gFacilityTrainerMons[monId].species;
u8 selectState = sFactorySelectScreen->selectingMonsState;
for (i = 1; i < selectState; i++)
@ -3728,7 +3728,7 @@ static void Swap_PrintPkmnSwap(void)
static void Swap_PrintMonSpecies(void)
{
u16 species;
enum Species species;
u8 x;
FillWindowPixelBuffer(SWAP_WIN_SPECIES, PIXEL_FILL(0));
@ -3828,7 +3828,7 @@ static void Swap_PrintOneActionString(u8 which)
// For printing the species name once its selected. Keep the current fade but don't keep fading in and out
static void Swap_PrintMonSpeciesAtFade(void)
{
u16 species;
enum Species species;
u8 x;
u16 pal[5];
@ -3862,7 +3862,7 @@ static void Swap_PrintMonSpeciesAtFade(void)
// Reprints the species name over the faded one after a transition
static void Swap_PrintMonSpeciesForTransition(void)
{
u16 species;
enum Species species;
u8 x;
LoadPalette(sSwapText_Pal, BG_PLTT_ID(PALNUM_FADE_TEXT), sizeof(sSwapText_Pal));
@ -3888,7 +3888,7 @@ static void Swap_PrintMonSpeciesForTransition(void)
static void Swap_PrintMonCategory(void)
{
u16 species;
enum Species species;
u8 text[30];
u8 x;
u8 monId = sFactorySwapScreen->cursorPos;
@ -4029,7 +4029,7 @@ static void OpenMonPic(u8 *spriteId, bool8 *animating, bool8 swapScreen)
static void Swap_ShowSummaryMonSprite(void)
{
struct Pokemon *mon;
u16 species;
enum Species species;
u32 personality;
bool8 isShiny;
@ -4113,7 +4113,7 @@ static void Swap_TaskCantHaveSameMons(u8 taskId)
static bool8 Swap_AlreadyHasSameSpecies(u8 monId)
{
u8 i;
u16 species = GetMonData(&gEnemyParty[monId], MON_DATA_SPECIES);
enum Species species = GetMonData(&gEnemyParty[monId], MON_DATA_SPECIES);
for (i = 0; i < FRONTIER_PARTY_SIZE; i++)
{
@ -4245,9 +4245,9 @@ static void Task_CloseMonPic(u8 taskId)
static void Swap_CreateMonSprite(void)
{
struct Pokemon *mon;
u16 species;
enum Species species;
u32 personality;
bool8 isShiny;
bool32 isShiny;
if (!sFactorySwapScreen->inEnemyScreen)
mon = &gPlayerParty[sFactorySwapScreen->cursorPos];

View File

@ -685,7 +685,7 @@ void BattleLoadMonSpriteGfx(struct Pokemon *mon, enum BattlerId battler)
}
}
void BattleGfxSfxDummy2(u16 species)
void BattleGfxSfxDummy2(enum Species species)
{
}
@ -1160,7 +1160,7 @@ void CreateEnemyShadowSprite(enum BattlerId battler)
{
if (B_ENEMY_MON_SHADOW_STYLE >= GEN_4 && P_GBA_STYLE_SPECIES_GFX == FALSE)
{
u16 species = GetBattlerVisualSpecies(battler);
enum Species species = GetBattlerVisualSpecies(battler);
u8 size = gSpeciesInfo[species].enemyShadowSize;
gBattleSpritesDataPtr->healthBoxesData[battler].shadowSpriteIdPrimary = CreateSprite(&gSpriteTemplate_EnemyShadow,
@ -1255,7 +1255,7 @@ void SpriteCB_EnemyShadow(struct Sprite *shadowSprite)
bool8 invisible = FALSE;
enum BattlerId battler = shadowSprite->tBattlerId;
struct Sprite *battlerSprite = &gSprites[gBattlerSpriteIds[battler]];
u16 transformSpecies = SanitizeSpeciesId(gBattleSpritesDataPtr->battlerData[battler].transformSpecies);
enum Species transformSpecies = SanitizeSpeciesId(gBattleSpritesDataPtr->battlerData[battler].transformSpecies);
if (!battlerSprite->inUse || !IsBattlerSpritePresent(battler))
{
@ -1283,7 +1283,7 @@ void SpriteCB_EnemyShadow(struct Sprite *shadowSprite)
}
else if (B_ENEMY_MON_SHADOW_STYLE >= GEN_4 && P_GBA_STYLE_SPECIES_GFX == FALSE)
{
u16 species = GetBattlerVisualSpecies(battler);
enum Species species = GetBattlerVisualSpecies(battler);
xOffset = gSpeciesInfo[species].enemyShadowXOffset + (shadowSprite->tSpriteSide == SPRITE_SIDE_LEFT ? -16 : 16);
yOffset = gSpeciesInfo[species].enemyShadowYOffset + 16;
size = gSpeciesInfo[species].enemyShadowSize;
@ -1310,7 +1310,7 @@ void SpriteCB_SetInvisible(struct Sprite *sprite)
sprite->invisible = TRUE;
}
void SetBattlerShadowSpriteCallback(enum BattlerId battler, u16 species)
void SetBattlerShadowSpriteCallback(enum BattlerId battler, enum Species species)
{
if (B_ENEMY_MON_SHADOW_STYLE >= GEN_4 && P_GBA_STYLE_SPECIES_GFX == FALSE)
{
@ -1458,7 +1458,7 @@ bool32 ShouldPlayNormalMonCry(struct Pokemon *mon)
return TRUE;
}
void DecompressGhostFrontPic(u32 battler)
void DecompressGhostFrontPic(enum BattlerId battler)
{
u16 palOffset;
enum BattlerPosition position = GetBattlerPosition(battler);

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