Merge branch 'battle_engine' of https://github.com/rh-hideout/pokeemerald-expansion into primalReversionTweaks

This commit is contained in:
LOuroboros 2021-11-30 20:39:58 -03:00
commit f2dd7bce99
69 changed files with 2437 additions and 739 deletions

View File

@ -1877,6 +1877,53 @@
.2byte \species
.4byte \ptr
.endm
.macro tryendneutralizinggas battler:req
various \battler, VARIOUS_TRY_END_NEUTRALIZING_GAS
.endm
.macro trytoapplymimicry battler:req, ptr:req
various \battler, VARIOUS_TRY_TO_APPLY_MIMICRY
.4byte \ptr
.endm
.macro trynoretreat battler:req, ptr:req
various \battler, VARIOUS_TRY_NO_RETREAT
.4byte \ptr
.endm
.macro trytarshot battler:req, ptr:req
various \battler, VARIOUS_TRY_TAR_SHOT
.4byte \ptr
.endm
.macro cantarshotwork battler:req, ptr:req
various \battler, VARIOUS_CAN_TAR_SHOT_WORK
.4byte \ptr
.endm
.macro checkpoltergeist battler:req, ptr:req
various \battler, VARIOUS_CHECK_POLTERGEIST
.4byte \ptr
.endm
.macro setoctolock battler:req, ptr:req
various \battler, VARIOUS_SET_OCTOLOCK
.4byte \ptr
.endm
.macro cutonethirdhpraisestats ptr:req
various BS_ATTACKER, VARIOUS_CUT_1_3_HP_RAISE_STATS
.4byte \ptr
.endm
.macro photongeysercheck
various BS_ATTACKER, VARIOUS_PHOTON_GEYSER_CHECK
.endm
.macro shellsidearmcheck
various BS_ATTACKER, VARIOUS_SHELL_SIDE_ARM_CHECK
.endm
@ helpful macros
.macro setstatchanger stat:req, stages:req, down:req

View File

@ -5,6 +5,7 @@
#include "constants/moves.h"
#include "constants/pokemon.h"
#include "constants/items.h"
#include "constants/battle_config.h"
.include "asm/macros.inc"
.include "asm/macros/battle_anim_script.inc"
.include "constants/constants.inc"
@ -1893,7 +1894,7 @@ Move_AURA_SPHERE:
monbg ANIM_ATK_PARTNER
monbgprio_28 ANIM_ATTACKER
setalpha 12, 8
call SetHighSpeedBg
call SetAuraSphereBG
playsewithpan SE_M_SKY_UPPERCUT, 0
delay 60
createsprite gAuraSphereBlast, ANIM_TARGET, 3, 0
@ -1908,6 +1909,10 @@ Move_AURA_SPHERE:
delay 1
end
SetAuraSphereBG:
fadetobg BG_AURA_SPHERE
goto SetHighSpeedBgFade
Move_ROCK_POLISH:
loadspritegfx ANIM_TAG_WHITE_STREAK
loadspritegfx ANIM_TAG_SPARKLE_3
@ -2378,7 +2383,7 @@ Move_FOCUS_BLAST:
monbg ANIM_ATK_PARTNER
monbgprio_28 ANIM_ATTACKER
setalpha 12, 8
call SetHighSpeedBg
call SetFocusBlastBG
createsprite gSuperpowerOrbSpriteTemplate, ANIM_TARGET, 2, 0
playsewithpan SE_M_MEGA_KICK, SOUND_PAN_ATTACKER
waitforvisualfinish
@ -2391,6 +2396,10 @@ Move_FOCUS_BLAST:
delay 1
end
SetFocusBlastBG:
fadetobg BG_FOCUS_BLAST
goto SetHighSpeedBgFade
Move_ENERGY_BALL:
loadspritegfx ANIM_TAG_ENERGY_BALL
monbg ANIM_TARGET
@ -2497,20 +2506,30 @@ Move_GIGA_IMPACT:
loadspritegfx ANIM_TAG_IMPACT
monbg ANIM_DEF_PARTNER
setalpha 12, 8
createvisualtask AnimTask_IsContest, 2
jumprettrue SetGigaImpactContestsBG
createvisualtask AnimTask_IsTargetPlayerSide, 2
jumpretfalse SetGigaImpactOpponentBG
goto SetGigaImpactPlayerBG
SetGigaImpactOpponentBG:
fadetobg BG_GIGA_IMPACT_OPPONENT
goto GigaImpactContinuity
SetGigaImpactPlayerBG:
fadetobg BG_GIGA_IMPACT_PLAYER
goto GigaImpactContinuity
SetGigaImpactContestsBG:
fadetobg BG_GIGA_IMPACT_CONTEST
goto GigaImpactContinuity
GigaImpactContinuity:
playsewithpan SE_M_TAKE_DOWN, SOUND_PAN_ATTACKER
createsprite gVerticalDipSpriteTemplate, ANIM_ATTACKER, 2, 6, 1, ANIM_ATTACKER
waitforvisualfinish
delay 11
createsprite gSlideMonToOffsetSpriteTemplate, ANIM_ATTACKER, 2, 0, 26, 0, 0, 5
delay 6
@monbg ANIM_DEF_PARTNER
@setalpha 12, 8
@createvisualtask AnimTask_WindUpLunge, 5, 7, 0, -18, 8, 23, 10, 40, 10
@delay 35
createsprite gComplexPaletteBlendSpriteTemplate, 2, 7, 31, 3, 1, 0, 10, 0, 0
waitbgfadeout
createsprite gBasicHitSplatSpriteTemplate, 4, 4, -10, 0, 1, 0
playsewithpan SE_M_MEGA_KICK2, SOUND_PAN_TARGET
call SetImpactBackground
delay 1
createsprite gSlideMonToOffsetSpriteTemplate 2, 5, 1, -16, 0, 0, 4
waitforvisualfinish
@ -2525,6 +2544,7 @@ Move_GIGA_IMPACT:
blendoff
restorebg
waitbgfadein
waitforvisualfinish
end
Move_NASTY_PLOT:
@ -3437,6 +3457,7 @@ Move_GUNK_SHOT:
monbg ANIM_DEF_PARTNER
monbgprio_28 ANIM_TARGET
setalpha 12, 8
call SetGunkShotBG
createvisualtask AnimTask_ShakeMon 5, 5, ANIM_ATTACKER, 0, 2, 40, 1
delay 6
panse_1B SE_M_HYDRO_PUMP, SOUND_PAN_ATTACKER, SOUND_PAN_TARGET, 2, 0
@ -3464,6 +3485,7 @@ Move_GUNK_SHOT:
call GunkShotImpact
call PoisonBubblesEffect
waitforvisualfinish
call UnsetHighSpeedBg
clearmonbg ANIM_DEF_PARTNER
blendoff
end
@ -3479,6 +3501,10 @@ GunkShotImpact:
createsprite gGunkShotImpactSpriteTemplate, 4, 4, 0, 15, 1, 1
createsprite gGunkShotImpactSpriteTemplate, 4, 4, 0, -15, 1, 1
return
SetGunkShotBG:
fadetobg BG_GUNK_SHOT
goto SetHighSpeedBgFade
Move_IRON_HEAD:
loadspritegfx ANIM_TAG_GUST
@ -7264,7 +7290,7 @@ Move_RELIC_SONG:
monbg ANIM_DEF_PARTNER
launchtask AnimTask_MusicNotesRainbowBlend 0x2 0x0
waitforvisualfinish
panse_1B 0x1DF, SOUND_PAN_ATTACKER, SOUND_PAN_TARGET, 0x2, 0x0 @ ???
createvisualtask SoundTask_PlayCryWithEcho, 2, ANIM_ATTACKER, 2
launchtask AnimTask_UproarDistortion 0x2 0x1 0x0
launchtemplate gUproarRingSpriteTemplate 0x3 0x6 0x0 0x0 0x0 0x0 0x1f 0x8
launchtemplate gJaggedMusicNoteSpriteTemplate 0x2 0x4 0x0 0x1d 0xfff4 0x0
@ -14012,7 +14038,50 @@ Move_METEOR_BEAM::
end @to do:
Move_SHELL_SIDE_ARM::
end @to do:
launchtask AnimTask_ShellSideArm 0x5 0x0
jumpargeq 0x0, TRUE, Move_SHELL_SIDE_ARM_PHYSICAL
jumpargeq 0x0, FALSE, Move_SHELL_SIDE_ARM_SPECIAL
Move_SHELL_SIDE_ARM_PHYSICAL: @ Modified Body Slam, placeholder
loadspritegfx ANIM_TAG_IMPACT
createvisualtask AnimTask_BlendParticle, 5, ANIM_TAG_IMPACT, 0, 6, 6, RGB_MAGENTA
monbg ANIM_DEF_PARTNER
setalpha 12, 8
playsewithpan SE_M_TAKE_DOWN, SOUND_PAN_ATTACKER
createsprite gVerticalDipSpriteTemplate, ANIM_ATTACKER, 2, 6, 1, ANIM_ATTACKER
waitforvisualfinish
delay 11
createsprite gSlideMonToOffsetSpriteTemplate, ANIM_ATTACKER, 2, 0, 26, 0, 0, 5
delay 6
createsprite gBasicHitSplatSpriteTemplate, ANIM_ATTACKER, 4, -10, 0, ANIM_TARGET, 0
loopsewithpan SE_M_MEGA_KICK2, SOUND_PAN_TARGET, 10, 2
delay 1
createsprite gSlideMonToOffsetSpriteTemplate, ANIM_ATTACKER, 2, 1, -28, 0, 0, 3
waitforvisualfinish
createvisualtask AnimTask_ShakeMonInPlace, 2, ANIM_TARGET, 4, 0, 12, 1
waitforvisualfinish
delay 10
createsprite gSlideMonToOriginalPosSpriteTemplate, ANIM_ATTACKER, 2, 0, 0, 6
delay 5
createsprite gSlideMonToOriginalPosSpriteTemplate, ANIM_ATTACKER, 2, 1, 0, 6
waitforvisualfinish
clearmonbg ANIM_DEF_PARTNER
blendoff
end
Move_SHELL_SIDE_ARM_SPECIAL: @ Modified Snipe Shot, placeholder
loadspritegfx ANIM_TAG_IMPACT_2
loadspritegfx ANIM_TAG_LEER
createvisualtask AnimTask_BlendParticle, 5, ANIM_TAG_IMPACT_2, 0, 6, 6, RGB_MAGENTA
createvisualtask AnimTask_BlendParticle, 5, ANIM_TAG_LEER, 0, 6, 6, RGB_MAGENTA
launchtemplate gLeerSpriteTemplate 0x82, 2 0x18 -12
playsewithpan SE_M_DETECT, SOUND_PAN_ATTACKER
waitforvisualfinish
delay 0x20
playsewithpan SE_M_GIGA_DRAIN, SOUND_PAN_TARGET
launchtemplate gSnipeShotBallTemplate 0x82, 3, 0 0 24,
waitforvisualfinish
launchtask AnimTask_ShakeMon2 2 5 1 4 0 8, 1
waitforvisualfinish
end
Move_MISTY_EXPLOSION::
end @to do:
@ -14024,7 +14093,87 @@ Move_RISING_VOLTAGE::
end @to do:
Move_TERRAIN_PULSE::
end @to do:
loadspritegfx ANIM_TAG_DRAGON_PULSE
monbg ANIM_TARGET
setalpha 12, 8
createsprite gSimplePaletteBlendSpriteTemplate, ANIM_ATTACKER, 2, 1, 1, 0, 7, RGB_BLACK
launchtask AnimTask_TerrainPulse 0x5 0x0
jumpargeq 0x0, TYPE_ELECTRIC, TerrainPulseElectric
jumpargeq 0x0, TYPE_GRASS, TerrainPulseGrass
jumpargeq 0x0, TYPE_FAIRY, TerrainPulseFairy
jumpargeq 0x0, TYPE_PSYCHIC, TerrainPulsePsychic
TerrainPulseNormal:
createvisualtask AnimTask_BlendParticle, 5, ANIM_TAG_DRAGON_PULSE, 0, 12, 12, RGB_WHITE
waitforvisualfinish
playsewithpan SE_M_PSYBEAM, SOUND_PAN_ATTACKER
createsoundtask SoundTask_LoopSEAdjustPanning, SE_M_PSYBEAM2, SOUND_PAN_ATTACKER, SOUND_PAN_TARGET, 3, 4, 0, 15
call DragonPulseParticle
call DragonPulseParticle
createvisualtask AnimTask_SwayMon, 5, 0, 2, 51200, 24, ANIM_TARGET
createvisualtask AnimTask_BlendColorCycle, 2, 4, 2, 2, 0, 12, RGB_WHITE
goto TerrainPulseEnd
TerrainPulseElectric:
createvisualtask AnimTask_BlendParticle, 5, ANIM_TAG_DRAGON_PULSE, 0, 12, 12, RGB(27, 27, 0)
waitforvisualfinish
playsewithpan SE_M_PSYBEAM, SOUND_PAN_ATTACKER
createsoundtask SoundTask_LoopSEAdjustPanning, SE_M_PSYBEAM2, SOUND_PAN_ATTACKER, SOUND_PAN_TARGET, 3, 4, 0, 15
call DragonPulseParticle
call DragonPulseParticle
createvisualtask AnimTask_SwayMon, 5, 0, 4, 51200, 24, ANIM_TARGET
createvisualtask AnimTask_BlendColorCycle, 2, 4, 2, 2, 0, 12, RGB(27, 27, 0)
goto TerrainPulseEnd
TerrainPulseGrass:
createvisualtask AnimTask_BlendParticle, 5, ANIM_TAG_DRAGON_PULSE, 0, 12, 12, RGB(11, 26, 11)
waitforvisualfinish
playsewithpan SE_M_PSYBEAM, SOUND_PAN_ATTACKER
createsoundtask SoundTask_LoopSEAdjustPanning, SE_M_PSYBEAM2, SOUND_PAN_ATTACKER, SOUND_PAN_TARGET, 3, 4, 0, 15
call DragonPulseParticle
call DragonPulseParticle
createvisualtask AnimTask_SwayMon, 5, 0, 4, 51200, 24, ANIM_TARGET
createvisualtask AnimTask_BlendColorCycle, 2, 4, 2, 2, 0, 12, RGB(11, 26, 11)
goto TerrainPulseEnd
TerrainPulseFairy:
createvisualtask AnimTask_BlendParticle, 5, ANIM_TAG_DRAGON_PULSE, 0, 12, 12, RGB(31, 24, 31)
waitforvisualfinish
playsewithpan SE_M_PSYBEAM, SOUND_PAN_ATTACKER
createsoundtask SoundTask_LoopSEAdjustPanning, SE_M_PSYBEAM2, SOUND_PAN_ATTACKER, SOUND_PAN_TARGET, 3, 4, 0, 15
call DragonPulseParticle
call DragonPulseParticle
createvisualtask AnimTask_SwayMon, 5, 0, 4, 51200, 24, ANIM_TARGET
createvisualtask AnimTask_BlendColorCycle, 2, 4, 2, 2, 0, 12, RGB(31, 24, 31)
goto TerrainPulseEnd
TerrainPulsePsychic:
createvisualtask AnimTask_BlendParticle, 5, ANIM_TAG_DRAGON_PULSE, 0, 12, 12, RGB(27, 0, 13)
waitforvisualfinish
playsewithpan SE_M_PSYBEAM, SOUND_PAN_ATTACKER
createsoundtask SoundTask_LoopSEAdjustPanning, SE_M_PSYBEAM2, SOUND_PAN_ATTACKER, SOUND_PAN_TARGET, 3, 4, 0, 15
call DragonPulseParticle
call DragonPulseParticle
createvisualtask AnimTask_SwayMon, 5, 0, 4, 51200, 24, ANIM_TARGET
createvisualtask AnimTask_BlendColorCycle, 2, 4, 2, 2, 0, 12, RGB(27, 0, 13)
goto TerrainPulseEnd
TerrainPulseEnd:
call DragonPulseParticle
call DragonPulseParticle
call DragonPulseParticle
call DragonPulseParticle
call DragonPulseParticle
call DragonPulseParticle
call DragonPulseParticle
call DragonPulseParticle
call DragonPulseParticle
waitforvisualfinish
delay 1
createsprite gSimplePaletteBlendSpriteTemplate, ANIM_ATTACKER, 2, 1, 1, 7, 0, RGB_BLACK
waitforvisualfinish
blendoff
clearmonbg ANIM_TARGET
end
Move_SKITTER_SMACK::
end @to do:
@ -23296,17 +23445,50 @@ Move_SKY_UPPERCUT:
end
Move_SECRET_POWER:
createvisualtask AnimTask_GetFieldTerrain, 5
jumpargeq 0, STATUS_FIELD_MISTY_TERRAIN, Move_FAIRY_WIND
jumpargeq 0, STATUS_FIELD_GRASSY_TERRAIN, Move_NEEDLE_ARM
jumpargeq 0, STATUS_FIELD_ELECTRIC_TERRAIN, Move_THUNDER_SHOCK
jumpargeq 0, STATUS_FIELD_PSYCHIC_TERRAIN, Move_CONFUSION
createvisualtask AnimTask_GetBattleTerrain, 5
jumpargeq 0, BATTLE_TERRAIN_GRASS, Move_NEEDLE_ARM
jumpargeq 0, BATTLE_TERRAIN_LONG_GRASS, Move_MAGICAL_LEAF
jumpargeq 0, BATTLE_TERRAIN_SAND, Move_MUD_SHOT
jumpargeq 0, BATTLE_TERRAIN_UNDERWATER, Move_WATERFALL
jumpargeq 0, BATTLE_TERRAIN_WATER, Move_SURF
jumpargeq 0, BATTLE_TERRAIN_POND, Move_BUBBLE_BEAM
jumpargeq 0, BATTLE_TERRAIN_MOUNTAIN, Move_ROCK_THROW
jumpargeq 0, BATTLE_TERRAIN_CAVE, Move_BITE
jumpargeq 0, BATTLE_TERRAIN_BUILDING, Move_STRENGTH
jumpargeq 0, BATTLE_TERRAIN_GRASS, Move_NEEDLE_ARM
jumpargeq 0, BATTLE_TERRAIN_LONG_GRASS, Move_MAGICAL_LEAF
jumpargeq 0, BATTLE_TERRAIN_SAND, Move_MUD_SHOT
jumpargeq 0, BATTLE_TERRAIN_UNDERWATER, Move_WATERFALL
jumpargeq 0, BATTLE_TERRAIN_WATER, Move_SURF
jumpargeq 0, BATTLE_TERRAIN_POND, Move_BUBBLE_BEAM
jumpargeq 0, BATTLE_TERRAIN_MOUNTAIN, Move_ROCK_THROW
jumpargeq 0, BATTLE_TERRAIN_CAVE, Move_BITE
jumpargeq 0, BATTLE_TERRAIN_BUILDING, Move_STRENGTH
jumpargeq 0, BATTLE_TERRAIN_SOARING, Move_GUST
jumpargeq 0, BATTLE_TERRAIN_SKY_PILLAR, Move_GUST
jumpargeq 0, BATTLE_TERRAIN_BURIAL_GROUND, Move_SHADOW_SNEAK
jumpargeq 0, BATTLE_TERRAIN_PUDDLE, Move_MUD_SHOT
jumpargeq 0, BATTLE_TERRAIN_MARSH, Move_MUD_SHOT
jumpargeq 0, BATTLE_TERRAIN_SWAMP, Move_MUD_SHOT
.if B_SECRET_POWER_ANIMATION >= GEN_7
jumpargeq 0, BATTLE_TERRAIN_SNOW, Move_ICE_SHARD
.else
jumpargeq 0, BATTLE_TERRAIN_SNOW, Move_AVALANCHE
.endif
jumpargeq 0, BATTLE_TERRAIN_ICE, Move_ICE_SHARD
jumpargeq 0, BATTLE_TERRAIN_VOLCANO, Move_INCINERATE
jumpargeq 0, BATTLE_TERRAIN_DISTORTION_WORLD, Move_POUND
jumpargeq 0, BATTLE_TERRAIN_SPACE, Move_SWIFT
jumpargeq 0, BATTLE_TERRAIN_ULTRA_SPACE, Move_PSYWAVE
.if B_SECRET_POWER_ANIMATION >= GEN_7
jumpargeq 0, BATTLE_TERRAIN_BUILDING, Move_SPIT_UP
goto Move_SPIT_UP
.elseif B_SECRET_POWER_ANIMATION == GEN_6
jumpargeq 0, BATTLE_TERRAIN_BUILDING, Move_BODY_SLAM
goto Move_BODY_SLAM
.elseif B_SECRET_POWER_ANIMATION == GEN_5 || B_SECRET_POWER_ANIMATION == GEN_4
jumpargeq 0, BATTLE_TERRAIN_BUILDING, Move_BODY_SLAM
goto Move_MUD_SLAP
.else
jumpargeq 0, BATTLE_TERRAIN_BUILDING, Move_STRENGTH
goto Move_SLAM
.endif
Move_TWISTER:
loadspritegfx ANIM_TAG_LEAF
@ -24023,6 +24205,7 @@ General_TurnTrap:
jumpargeq 0, TRAP_ANIM_WHIRLPOOL, Status_Whirlpool
jumpargeq 0, TRAP_ANIM_CLAMP, Status_Clamp
jumpargeq 0, TRAP_ANIM_SAND_TOMB, Status_SandTomb
jumpargeq 0, TRAP_ANIM_MAGMA_STORM, Status_MagmaStorm
jumpargeq 0, TRAP_ANIM_INFESTATION, Status_Infestation
goto Status_BindWrap
Status_BindWrap:
@ -24049,6 +24232,32 @@ Status_FireSpin:
stopsound
end
Status_MagmaStorm:
loadspritegfx ANIM_TAG_SMALL_EMBER
fadetobg BG_MAGMA_STORM
waitbgfadeout
createvisualtask AnimTask_MoveSeismicTossBg, 3
playsewithpan SE_M_SACRED_FIRE2, SOUND_PAN_TARGET
loopsewithpan SE_M_SACRED_FIRE2, SOUND_PAN_TARGET, 5, 8
createvisualtask AnimTask_SeismicTossBgAccelerateDownAtEnd, 3
createvisualtask AnimTask_ShakeMon, 5, ANIM_TARGET, 0, 2, 47, 1
createvisualtask AnimTask_BlendColorCycle, 2, 6, 4, 2, 2, 0, 12, RGB(22, 9, 7)
call FireSpinEffect
call FireSpinEffect
createvisualtask AnimTask_BlendColorCycle, 2, 6, 4, 2, 2, 0, 12, RGB(22, 9, 7)
call FireSpinEffect
call FireSpinEffect
createvisualtask AnimTask_BlendColorCycle, 2, 6, 4, 2, 2, 0, 12, RGB(22, 9, 7)
call FireSpinEffect
restorebg
waitbgfadeout
setarg 7, 0xFFF
waitbgfadein
stopsound
clearmonbg ANIM_DEF_PARTNER
blendoff
end
Status_Whirlpool:
loadspritegfx ANIM_TAG_WATER_ORB
monbg ANIM_DEF_PARTNER

View File

@ -367,7 +367,7 @@ gBattleScriptsForMoveEffects::
.4byte BattleScript_EffectGeomancy @ EFFECT_GEOMANCY
.4byte BattleScript_EffectFairyLock @ EFFECT_FAIRY_LOCK
.4byte BattleScript_EffectAllySwitch @ EFFECT_ALLY_SWITCH
.4byte BattleScript_EffectSleepHit @ EFFECT_SLEEP_HIT
.4byte BattleScript_EffectRelicSong @ EFFECT_RELIC_SONG
.4byte BattleScript_EffectAttackerDefenseDownHit @ EFFECT_ATTACKER_DEFENSE_DOWN_HIT
.4byte BattleScript_EffectHit @ EFFECT_BODY_PRESS
.4byte BattleScript_EffectEerieSpell @ EFFECT_EERIE_SPELL
@ -392,10 +392,164 @@ gBattleScriptsForMoveEffects::
.4byte BattleScript_EffectSparklySwirl @ EFFECT_SPARKLY_SWIRL
.4byte BattleScript_EffectPlasmaFists @ EFFECT_PLASMA_FISTS
.4byte BattleScript_EffectHyperspaceFury @ EFFECT_HYPERSPACE_FURY
.4byte BattleScript_EffectAuraWheel @ EFFECT_AURA_WHEEL
.4byte BattleScript_EffectPhotonGeyser @ EFFECT_PHOTON_GEYSER
.4byte BattleScript_EffectShellSideArm @ EFFECT_SHELL_SIDE_ARM
.4byte BattleScript_EffectHit @ EFFECT_TERRAIN_PULSE
.4byte BattleScript_EffectJawLock @ EFFECT_JAW_LOCK
.4byte BattleScript_EffectNoRetreat @ EFFECT_NO_RETREAT
.4byte BattleScript_EffectTarShot @ EFFECT_TAR_SHOT
.4byte BattleScript_EffectPoltergeist @ EFFECT_POLTERGEIST
.4byte BattleScript_EffectOctolock @ EFFECT_OCTOLOCK
.4byte BattleScript_EffectClangorousSoul @ EFFECT_CLANGOROUS_SOUL
.4byte BattleScript_EffectHit @ EFFECT_BOLT_BEAK
BattleScript_EffectShellSideArm:
shellsidearmcheck
setmoveeffect MOVE_EFFECT_POISON
goto BattleScript_EffectHit
BattleScript_EffectPhotonGeyser:
attackcanceler
accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE
attackstring
ppreduce
critcalc
damagecalc
adjustdamage
photongeysercheck
attackanimation
waitanimation
effectivenesssound
hitanimation BS_TARGET
waitstate
healthbarupdate BS_TARGET
datahpupdate BS_TARGET
critmessage
waitmessage B_WAIT_TIME_LONG
resultmessage
waitmessage B_WAIT_TIME_LONG
seteffectwithchance
tryfaintmon BS_TARGET, FALSE, NULL
goto BattleScript_MoveEnd
BattleScript_EffectAuraWheel: @ Aura Wheel can only be used by Morpeko
jumpifspecies BS_ATTACKER, SPECIES_MORPEKO, BattleScript_EffectSpeedUpHit
jumpifspecies BS_ATTACKER, SPECIES_MORPEKO_HANGRY, BattleScript_EffectSpeedUpHit
printstring STRINGID_BUTPOKEMONCANTUSETHEMOVE
waitmessage B_WAIT_TIME_LONG
goto BattleScript_MoveEnd
BattleScript_EffectClangorousSoul:
attackcanceler
attackstring
ppreduce
cutonethirdhpraisestats BattleScript_ButItFailed
orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_SKIP_DMG_TRACK | HITMARKER_PASSIVE_DAMAGE | HITMARKER_IGNORE_DISGUISE
attackanimation
waitanimation
healthbarupdate BS_ATTACKER
datahpupdate BS_ATTACKER
call BattleScript_AllStatsUp
goto BattleScript_MoveEnd
BattleScript_EffectOctolock:
attackcanceler
jumpifsubstituteblocks BattleScript_ButItFailedAtkStringPpReduce
accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE
attackstring
ppreduce
setoctolock BS_TARGET, BattleScript_ButItFailed
attackanimation
waitanimation
printstring STRINGID_CANTESCAPEBECAUSEOFCURRENTMOVE
waitmessage B_WAIT_TIME_LONG
goto BattleScript_MoveEnd
BattleScript_OctolockEndTurn::
setbyte sSTAT_ANIM_PLAYED, FALSE
jumpifstat BS_TARGET, CMP_GREATER_THAN, STAT_DEF, MIN_STAT_STAGE, BattleScript_OctolockLowerDef
jumpifstat BS_TARGET, CMP_GREATER_THAN, STAT_SPDEF, MIN_STAT_STAGE, BattleScript_OctolockTryLowerSpDef
goto BattleScript_OctolockEnd2
BattleScript_OctolockLowerDef:
jumpifability BS_TARGET, ABILITY_BIG_PECKS, BattleScript_OctolockTryLowerSpDef
playstatchangeanimation BS_ATTACKER, BIT_DEF | BIT_SPDEF, STAT_CHANGE_NEGATIVE
setbyte sSTAT_ANIM_PLAYED, TRUE
setstatchanger STAT_DEF, 1, TRUE
statbuffchange STAT_BUFF_ALLOW_PTR, BattleScript_OctolockTryLowerSpDef
jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_DECREASE, BattleScript_OctolockTryLowerSpDef
printfromtable gStatUpStringIds
waitmessage B_WAIT_TIME_LONG
BattleScript_OctolockTryLowerSpDef:
jumpifbyte CMP_EQUAL, sSTAT_ANIM_PLAYED, TRUE, BattleScript_OctolockSkipSpDefAnim
playstatchangeanimation BS_ATTACKER, BIT_SPDEF, STAT_CHANGE_NEGATIVE
BattleScript_OctolockSkipSpDefAnim:
setstatchanger STAT_SPDEF, 1, TRUE
statbuffchange STAT_BUFF_ALLOW_PTR, BattleScript_OctolockEnd2
jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_DECREASE, BattleScript_OctolockEnd2
printfromtable gStatUpStringIds
waitmessage B_WAIT_TIME_LONG
BattleScript_OctolockEnd2::
end2
BattleScript_EffectPoltergeist:
attackcanceler
attackstring
ppreduce
checkpoltergeist BS_TARGET, BattleScript_ButItFailed
printstring STRINGID_ABOUTTOUSEPOLTERGEIST
waitmessage B_WAIT_TIME_LONG
goto BattleScript_HitFromCritCalc
BattleScript_EffectTarShot:
attackcanceler
jumpifsubstituteblocks BattleScript_ButItFailedAtkStringPpReduce
accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE
cantarshotwork BS_TARGET, BattleScript_ButItFailedAtkStringPpReduce
attackstring
ppreduce
setstatchanger STAT_SPEED, 1, TRUE
attackanimation
waitanimation
statbuffchange STAT_BUFF_ALLOW_PTR, BattleScript_TryTarShot
setgraphicalstatchangevalues
playanimation BS_TARGET, B_ANIM_STATS_CHANGE, sB_ANIM_ARG1
printfromtable gStatDownStringIds
waitmessage B_WAIT_TIME_LONG
BattleScript_TryTarShot:
trytarshot BS_TARGET, BattleScript_MoveEnd
printstring STRINGID_PKMNBECAMEWEAKERTOFIRE
waitmessage B_WAIT_TIME_LONG
goto BattleScript_MoveEnd
BattleScript_EffectNoRetreat:
attackcanceler
accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE
attackstring
ppreduce
trynoretreat BS_TARGET, BattleScript_ButItFailed
attackanimation
waitanimation
call BattleScript_AllStatsUp
jumpifstatus2 BS_TARGET, STATUS2_ESCAPE_PREVENTION, BattleScript_MoveEnd
setmoveeffect MOVE_EFFECT_PREVENT_ESCAPE
seteffectprimary
printstring STRINGID_CANTESCAPEDUETOUSEDMOVE
waitmessage B_WAIT_TIME_LONG
goto BattleScript_MoveEnd
BattleScript_EffectJawLock:
setmoveeffect MOVE_EFFECT_TRAP_BOTH | MOVE_EFFECT_CERTAIN
goto BattleScript_EffectHit
BattleScript_BothCanNoLongerEscape::
printstring STRINGID_BOTHCANNOLONGERESCAPE
waitmessage B_WAIT_TIME_LONG
return
BattleScript_EffectHyperspaceFury:
jumpifspecies BS_ATTACKER, SPECIES_TREECKO, BattleScript_EffectHyperspaceFuryUnbound
jumpifspecies BS_ATTACKER, SPECIES_MUDKIP, BattleScript_ButHoopaCantUseIt
jumpifspecies BS_ATTACKER, SPECIES_HOOPA_UNBOUND, BattleScript_EffectHyperspaceFuryUnbound
jumpifspecies BS_ATTACKER, SPECIES_HOOPA, BattleScript_ButHoopaCantUseIt
printstring STRINGID_BUTPOKEMONCANTUSETHEMOVE
waitmessage B_WAIT_TIME_LONG
goto BattleScript_MoveEnd
@ -734,9 +888,30 @@ BattleScript_EffectAttackerDefenseDownHit:
setmoveeffect MOVE_EFFECT_DEF_MINUS_1 | MOVE_EFFECT_AFFECTS_USER | MOVE_EFFECT_CERTAIN
goto BattleScript_EffectHit
BattleScript_EffectSleepHit:
setmoveeffect MOVE_EFFECT_SLEEP
goto BattleScript_EffectHit
BattleScript_EffectRelicSong:
setmoveeffect MOVE_EFFECT_RELIC_SONG | MOVE_EFFECT_AFFECTS_USER | MOVE_EFFECT_CERTAIN
attackcanceler
accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE
attackstring
ppreduce
critcalc
damagecalc
adjustdamage
attackanimation
waitanimation
effectivenesssound
hitanimation BS_TARGET
waitstate
healthbarupdate BS_TARGET
datahpupdate BS_TARGET
critmessage
waitmessage B_WAIT_TIME_LONG
resultmessage
waitmessage B_WAIT_TIME_LONG
seteffectwithchance
argumentstatuseffect
tryfaintmon BS_TARGET, FALSE, NULL
goto BattleScript_MoveEnd
BattleScript_EffectAllySwitch:
attackcanceler
@ -1707,7 +1882,7 @@ BattleScript_EffectSoak:
attackanimation
waitanimation
trysoak BattleScript_ButItFailed
printstring STRINGID_TRANSFORMEDINTOWATERTYPE
printstring STRINGID_TARGETCHANGEDTYPE
waitmessage B_WAIT_TIME_LONG
goto BattleScript_MoveEnd
@ -1908,6 +2083,23 @@ BattleScript_EffectPsychicTerrain:
waitmessage B_WAIT_TIME_LONG
playanimation BS_SCRIPTING, B_ANIM_RESTORE_BG, NULL
call BattleScript_TerrainSeedLoop
jumpifabilitypresent ABILITY_MIMICRY, BattleScript_ApplyMimicry
goto BattleScript_MoveEnd
BattleScript_ApplyMimicry::
savetarget
setbyte gBattlerTarget, 0
BattleScript_MimicryLoopIter:
copybyte sBATTLER, gBattlerTarget
trytoapplymimicry BS_TARGET, BattleScript_MimicryLoop_NextBattler
copybyte gBattlerAbility, sBATTLER
call BattleScript_AbilityPopUp
printstring STRINGID_BATTLERTYPECHANGEDTO
waitmessage B_WAIT_TIME_LONG
BattleScript_MimicryLoop_NextBattler:
addbyte gBattlerTarget, 0x1
jumpifbytenotequal gBattlerTarget, gBattlersCount, BattleScript_MimicryLoopIter
restoretarget
goto BattleScript_MoveEnd
BattleScript_EffectTopsyTurvy:
@ -1995,6 +2187,7 @@ BattleScript_EffectSimpleBeam:
trytoclearprimalweather
printstring STRINGID_EMPTYSTRING3
waitmessage 1
tryendneutralizinggas BS_TARGET
goto BattleScript_MoveEnd
BattleScript_EffectSuckerPunch:
@ -2217,6 +2410,7 @@ BattleScript_EffectGastroAcid:
trytoclearprimalweather
printstring STRINGID_EMPTYSTRING3
waitmessage 1
tryendneutralizinggas BS_TARGET
goto BattleScript_MoveEnd
BattleScript_EffectToxicSpikes:
@ -6289,7 +6483,7 @@ BattleScript_AttackerItemStatRaise::
playanimation BS_ATTACKER, B_ANIM_STATS_CHANGE, sB_ANIM_ARG1
waitanimation
printstring STRINGID_USINGITEMSTATOFPKMNROSE
waitmessage 0x40
waitmessage B_WAIT_TIME_LONG
removeitem BS_ATTACKER
BattleScript_AttackerItemStatRaiseRet:
return
@ -6972,6 +7166,7 @@ BattleScript_AttackerFormChange::
call BattleScript_AbilityPopUp
printstring STRINGID_EMPTYSTRING3
waitmessage 1
BattleScript_AttackerFormChangeNoPopup::
handleformchange BS_ATTACKER, 0
handleformchange BS_ATTACKER, 1
playanimation BS_ATTACKER, B_ANIM_FORM_CHANGE, NULL
@ -6983,6 +7178,21 @@ BattleScript_AttackerFormChangeEnd3::
call BattleScript_AttackerFormChange
end3
BattleScript_AttackerFormChangeEnd3NoPopup::
call BattleScript_AttackerFormChangeNoPopup
BattleScript_AttackerFormChangeMoveEffect::
waitmessage 1
handleformchange BS_ATTACKER, 0
handleformchange BS_ATTACKER, 1
playanimation BS_ATTACKER, B_ANIM_FORM_CHANGE, NULL
waitanimation
copybyte sBATTLER, gBattlerAttacker
printstring STRINGID_PKMNTRANSFORMED
waitmessage B_WAIT_TIME_LONG
handleformchange BS_ATTACKER, 2
end3
BattleScript_BallFetch::
call BattleScript_AbilityPopUp
printstring STRINGID_FETCHEDPOKEBALL
@ -8006,6 +8216,12 @@ BattleScript_ColorChangeActivates::
waitmessage B_WAIT_TIME_LONG
return
BattleScript_MimicryActivatesEnd3::
call BattleScript_AbilityPopUp
printstring STRINGID_BATTLERTYPECHANGEDTO
waitmessage B_WAIT_TIME_LONG
end3
BattleScript_ProteanActivates::
call BattleScript_AbilityPopUp
printstring STRINGID_PKMNCHANGEDTYPE
@ -8168,6 +8384,12 @@ BattleScript_SwitchInAbilityMsg::
waitmessage B_WAIT_TIME_LONG
end3
BattleScript_SwitchInAbilityMsgRet::
call BattleScript_AbilityPopUp
printfromtable gSwitchInAbilityStringIds
waitmessage B_WAIT_TIME_LONG
return
BattleScript_ActivateAsOne::
call BattleScript_AbilityPopUp
printfromtable gSwitchInAbilityStringIds
@ -8931,7 +9153,7 @@ BattleScript_StickyBarbTransfer::
BattleScript_RedCardActivates::
playanimation BS_SCRIPTING, B_ANIM_HELD_ITEM_EFFECT, NULL
printstring STRINGID_REDCARDACTIVATE
waitmessage 0x40
waitmessage B_WAIT_TIME_LONG
swapattackerwithtarget
jumpifstatus3 BS_EFFECT_BATTLER, STATUS3_ROOTED, BattleScript_RedCardIngrain
jumpifability BS_EFFECT_BATTLER, ABILITY_SUCTION_CUPS, BattleScript_RedCardSuctionCups
@ -8942,13 +9164,13 @@ BattleScript_RedCardEnd:
return
BattleScript_RedCardIngrain:
printstring STRINGID_PKMNANCHOREDITSELF
waitmessage 0x40
waitmessage B_WAIT_TIME_LONG
removeitem BS_SCRIPTING
swapattackerwithtarget
return
BattleScript_RedCardSuctionCups:
printstring STRINGID_PKMNANCHORSITSELFWITH
waitmessage 0x40
waitmessage B_WAIT_TIME_LONG
removeitem BS_SCRIPTING
swapattackerwithtarget
return
@ -8957,7 +9179,7 @@ BattleScript_EjectButtonActivates::
makevisible BS_ATTACKER
playanimation BS_SCRIPTING, B_ANIM_HELD_ITEM_EFFECT, NULL
printstring STRINGID_EJECTBUTTONACTIVATE
waitmessage 0x40
waitmessage B_WAIT_TIME_LONG
removeitem BS_SCRIPTING
makeinvisible BS_SCRIPTING
openpartyscreen BS_SCRIPTING, BattleScript_EjectButtonEnd
@ -9021,3 +9243,19 @@ BattleScript_PastelVeilLoopIncrement:
goto BattleScript_PastelVeilEnd
BattleScript_PastelVeilEnd:
end3
sByteFour:
.byte MAX_BATTLERS_COUNT
BattleScript_NeutralizingGasExits::
savetarget
pause B_WAIT_TIME_SHORT
printstring STRINGID_NEUTRALIZINGGASOVER
waitmessage B_WAIT_TIME_LONG
setbyte gBattlerTarget, 0
BattleScript_NeutralizingGasExitsLoop:
switchinabilities BS_TARGET
addbyte gBattlerTarget, 1
jumpifbytenotequal gBattlerTarget, sByteFour, BattleScript_NeutralizingGasExitsLoop @ SOMEHOW, comparing to gBattlersCount is problematic.
restoretarget
return

View File

@ -1,19 +0,0 @@
JASC-PAL
0100
16
0 0 0
131 131 131
123 123 123
115 115 115
106 106 106
98 98 98
82 82 82
65 65 65
49 49 49
0 0 0
0 0 0
0 0 0
0 0 0
0 0 0
0 0 0
0 0 0

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.9 KiB

View File

@ -1,19 +0,0 @@
JASC-PAL
0100
16
0 0 0
255 214 0
255 197 0
255 173 0
255 165 0
148 90 222
255 107 0
255 132 0
255 148 0
255 156 41
0 0 0
0 90 0
0 0 0
0 0 0
0 0 0
0 0 0

View File

@ -2,14 +2,14 @@ JASC-PAL
0100
16
0 0 0
131 131 131
123 123 123
115 115 115
106 106 106
98 98 98
82 82 82
65 65 65
49 49 49
48 48 48
72 72 72
88 88 88
120 120 120
0 0 0
0 0 0
0 0 0
0 0 0
0 0 0
0 0 0
0 0 0

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

After

Width:  |  Height:  |  Size: 984 B

View File

@ -0,0 +1,19 @@
JASC-PAL
0100
16
0 0 0
240 136 184
232 104 168
136 8 40
248 24 104
216 32 96
224 72 136
160 0 48
216 0 64
200 40 88
192 0 56
176 32 128
176 24 72
152 16 56
200 48 80
216 56 160

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

@ -0,0 +1,3 @@
<EFBFBD>$<24>$<24>$<24>$<24>$<24>$<24>$<24>$<24>$<24> <20> <20> <20> <20> <20> <20> <20> <20> <20> <20> <20> <20> <20> <20> <20> D!E!F!G!H!I!@!<21>$<24>$<24>$<24>$<24>$<24>$<24>$<24>$<24>$<24> <20> <20> <20> <20> <20> <20> <20> <20> <20> <20> <20> <20> <20> <20> <20> њ ћ ќ § ў џ ђ Ј$Ї$І$Ѕ$Є$Ѓ$Ђ$Ё$ $  Ё Ђ Ѓ Є Ѕ І Ї Ј Љ Њ Ћ Ќ ­ Ў Џ
! ! ! !!!!И$З$Ж$Е$Д$Г$В$Б$А$А Б В Г Д Е Ж З И Й К Л М Н О П !!!!!!!Ш$Ч$Ц$Х$Ф$У$Т$С$Р$Р С Т У Ф Х Ц Ч Ш Щ Ъ Ы Ь Э Ю Я *!+!,!-!.!/!"!и$з$ж$е$д$г$в$б$а$а б в г д е ж з и й к л м н о п :!;!<!=!>!?!2!ш$ч$ц$х$ф$у$т$с$р$р с т у ф х ц ч ш щ ъ ы ь э ю я J!K!L!M!N!O!B!ш,ч,ц,х,ф,у,т,с,р,р(с(т(у(ф(х(ц(ч(ш(щ(ъ(ы(ь(э(ю(я(J)K)L)M)N)O)B)и,з,ж,е,д,г,в,б,а,а(б(в(г(д(е(ж(з(и(й(к(л(м(н(о(п(:);)<)=)>)?)2)Ш,Ч,Ц,Х,Ф,У,Т,С,Р,Р(С(Т(У(Ф(Х(Ц(Ч(Ш(Щ(Ъ(Ы(Ь(Э(Ю(Я(*)+),)-).)/)")И,З,Ж,Е,Д,Г,В,Б,А,А(Б(В(Г(Д(Е(Ж(З(И(Й(К(Л(М(Н(О(П()))))))Ј,Ї,І,Ѕ,Є,Ѓ,Ђ,Ё, , (Ё(Ђ(Ѓ(Є(Ѕ(І(Ї(Ј(Љ(Њ(Ћ(Ќ(­(Ў(Џ(
) ) ) ))))<29>,<2C>,<2C>,<2C>,<2C>,<2C>,<2C>,<2C>,<2C>,<2C>(<28>(<28>(<28>(<28>(<28>(<28>(<28>(<28>(<28>(<28>(<28>(<28>(<28>(<28>(<28>(њ(ћ(ќ(§(ў(џ(ђ(<28>,<2C>,<2C>,<2C>,<2C>,<2C>,<2C>,<2C>,<2C>,<2C>(<28>(<28>(<28>(<28>(<28>(<28>(<28>(<28>(<28>(<28>(<28>(<28>(<28>(<28>(<28>(D)E)F)G)H)I)@)

View File

@ -1,19 +0,0 @@
JASC-PAL
0100
16
41 49 49
106 139 189
246 131 180
255 0 255
255 16 98
238 98 164
230 65 131
222 0 57
222 24 90
205 41 74
205 32 82
189 0 49
172 16 65
156 0 41
148 16 49
131 8 32

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

View File

@ -1,19 +0,0 @@
JASC-PAL
0100
16
0 0 0
255 255 255
255 0 255
255 16 98
246 131 180
238 98 164
230 65 131
222 0 57
222 24 90
205 32 82
205 41 74
189 0 49
172 16 65
156 0 41
148 16 49
131 8 32

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

View File

@ -2,12 +2,12 @@ JASC-PAL
0100
16
0 0 0
164 156 24
156 148 24
197 189 32
172 164 32
115 106 16
0 0 0
248 248 144
224 224 120
200 200 96
176 176 72
152 152 48
120 120 16
0 0 0
0 0 0
0 0 0

View File

@ -1,3 +0,0 @@
@%I%H%G%F%E%D%<25>$<24>$<24>$<24>$<24>$<24>$<24>$<24>$<24>$<24>$<24>$<24>$<24>$<24>$<24>$<24>$<24> <20> <20> <20> <20> <20> <20> <20> <20> ђ$џ$ў$§$ќ$ћ$њ$<24>$<24>$<24>$<24>$<24>$<24>$<24>$<24>$<24>$<24>$<24>$<24>$<24>$<24>$<24>$<24>$<24> <20> <20> <20> <20> <20> <20> <20> <20> %%% % % %
%Џ$Ў$­$Ќ$Ћ$Њ$Љ$Ј$Ї$І$Ѕ$Є$Ѓ$Ђ$Ё$ $  Ё Ђ Ѓ Є Ѕ І Ї Ј %%%%%%%П$О$Н$М$Л$К$Й$И$З$Ж$Е$Д$Г$В$Б$А$А Б В Г Д Е Ж З И "%/%.%-%,%+%*%Я$Ю$Э$Ь$Ы$Ъ$Щ$Ш$Ч$Ц$Х$Ф$У$Т$С$Р$Р С Т У Ф Х Ц Ч Ш 2%?%>%=%<%;%:%п$о$н$м$л$к$й$и$з$ж$е$д$г$в$б$а$а б в г д е ж з и B%O%N%M%L%K%J%я$ю$э$ь$ы$ъ$щ$ш$ч$ц$х$ф$у$т$с$р$р с т у ф х ц ч ш B-O-N-M-L-K-J-я,ю,э,ь,ы,ъ,щ,ш,ч,ц,х,ф,у,т,с,р,р(с(т(у(ф(х(ц(ч(ш(2-?->-=-<-;-:-п,о,н,м,л,к,й,и,з,ж,е,д,г,в,б,а,а(б(в(г(д(е(ж(з(и("-/-.---,-+-*-Я,Ю,Э,Ь,Ы,Ъ,Щ,Ш,Ч,Ц,Х,Ф,У,Т,С,Р,Р(С(Т(У(Ф(Х(Ц(Ч(Ш(-------П,О,Н,М,Л,К,Й,И,З,Ж,Е,Д,Г,В,Б,А,А(Б(В(Г(Д(Е(Ж(З(И(--- - - -
-Џ,Ў,­,Ќ,Ћ,Њ,Љ,Ј,Ї,І,Ѕ,Є,Ѓ,Ђ,Ё, , (Ё(Ђ(Ѓ(Є(Ѕ(І(Ї(Ј(ђ,џ,ў,§,ќ,ћ,њ,<2C>,<2C>,<2C>,<2C>,<2C>,<2C>,<2C>,<2C>,<2C>,<2C>,<2C>,<2C>,<2C>,<2C>,<2C>,<2C>,<2C>(<28>(<28>(<28>(<28>(<28>(<28>(<28>(<28>(@-I-H-G-F-E-D-<2D>,<2C>,<2C>,<2C>,<2C>,<2C>,<2C>,<2C>,<2C>,<2C>,<2C>,<2C>,<2C>,<2C>,<2C>,<2C>,<2C>(<28>(<28>(<28>(<28>(<28>(<28>(<28>(<28>(

View File

@ -2,12 +2,12 @@ JASC-PAL
0100
16
0 0 0
106 123 139
90 106 139
123 139 164
123 139 197
65 74 115
0 0 0
152 184 248
128 160 240
104 136 216
80 112 192
56 88 168
24 56 136
0 0 0
0 0 0
0 0 0

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

@ -2,10 +2,10 @@ JASC-PAL
0100
16
0 0 0
131 205 230
123 180 213
115 156 205
115 139 164
128 200 232
120 176 216
112 152 200
112 136 160
0 0 0
0 0 0
0 0 0

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.0 KiB

After

Width:  |  Height:  |  Size: 814 B

View File

@ -2,12 +2,12 @@ JASC-PAL
0100
16
0 0 0
214 55 93
199 40 78
222 91 123
223 96 127
158 31 62
0 0 0
248 144 248
224 120 224
200 96 200
176 72 176
152 48 152
120 16 120
0 0 0
0 0 0
0 0 0

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

View File

@ -62,12 +62,13 @@ struct ResourceFlags
u32 flags[4];
};
#define RESOURCE_FLAG_FLASH_FIRE 0x1
#define RESOURCE_FLAG_ROOST 0x2
#define RESOURCE_FLAG_UNBURDEN 0x4
#define RESOURCE_FLAG_INTIMIDATED 0x8
#define RESOURCE_FLAG_TRACED 0x10
#define RESOURCE_FLAG_EMERGENCY_EXIT 0x20
#define RESOURCE_FLAG_FLASH_FIRE 0x1
#define RESOURCE_FLAG_ROOST 0x2
#define RESOURCE_FLAG_UNBURDEN 0x4
#define RESOURCE_FLAG_INTIMIDATED 0x8
#define RESOURCE_FLAG_TRACED 0x10
#define RESOURCE_FLAG_EMERGENCY_EXIT 0x20
#define RESOURCE_FLAG_NEUTRALIZING_GAS 0x40
struct DisableStruct
{
@ -112,6 +113,9 @@ struct DisableStruct
u8 throatChopTimer;
u8 usedMoves:4;
u8 wrapTurns;
u8 noRetreat:1;
u8 tarShot:1;
u8 octolock:1;
};
struct ProtectStruct
@ -181,6 +185,8 @@ struct SpecialStatus
u8 damagedMons:4; // Mons that have been damaged directly by using a move, includes substitute.
u8 dancerUsedMove:1;
u8 dancerOriginalTarget:3;
u8 announceNeutralizingGas:1; // See Cmd_switchineffects
u8 neutralizingGasRemoved:1; // See VARIOUS_TRY_END_NEUTRALIZING_GAS
s32 dmg;
s32 physicalDmg;
s32 specialDmg;
@ -222,10 +228,7 @@ struct FieldTimer
u8 wonderRoomTimer;
u8 magicRoomTimer;
u8 trickRoomTimer;
u8 grassyTerrainTimer;
u8 mistyTerrainTimer;
u8 electricTerrainTimer;
u8 psychicTerrainTimer;
u8 terrainTimer;
u8 gravityTimer;
u8 fairyLockTimer;
};
@ -236,7 +239,7 @@ struct WishFutureKnock
u8 futureSightAttacker[MAX_BATTLERS_COUNT];
u16 futureSightMove[MAX_BATTLERS_COUNT];
u8 wishCounter[MAX_BATTLERS_COUNT];
u8 wishMonId[MAX_BATTLERS_COUNT];
u8 wishPartyId[MAX_BATTLERS_COUNT];
u8 weatherDuration;
u8 knockedOffMons[2]; // Each battler is represented by a bit. The array entry is dependent on the battler's side.
};
@ -929,5 +932,6 @@ extern u8 gBattleControllerData[MAX_BATTLERS_COUNT];
extern bool8 gHasFetchedBall;
extern u8 gLastUsedBall;
extern u16 gLastThrownBall;
extern bool8 gSwapDamageCategory; // Photon Geyser, Shell Side Arm, Light That Burns the Sky
#endif // GUARD_BATTLE_H

View File

@ -1,9 +1,9 @@
#ifndef GUARD_BATTLE_AI_UTIL_H
#define GUARD_BATTLE_AI_UTIL_H
// for IsAiFaster
#define AI_CHECK_FASTER 0 // if_user_faster
#define AI_CHECK_SLOWER 1 // if_target_faster
// for AI_WhoStrikesFirst
#define AI_IS_FASTER 0
#define AI_IS_SLOWER 1
#define FOE(battler) ((battler ^ BIT_SIDE) & BIT_SIDE)
@ -21,12 +21,13 @@ void SaveBattlerData(u8 battlerId);
void SetBattlerData(u8 battlerId);
void RestoreBattlerData(u8 battlerId);
bool32 WillAIStrikeFirst(void);
u32 GetTotalBaseStat(u32 species);
bool32 IsTruantMonVulnerable(u32 battlerAI, u32 opposingBattler);
bool32 AtMaxHp(u8 battler);
u32 GetHealthPercentage(u8 battler);
bool32 IsBattlerTrapped(u8 battler, bool8 switching);
bool32 IsAiFaster(u8 battler);
u8 AI_WhoStrikesFirst(u8 battlerAI, u8 battler2);
bool32 CanTargetFaintAi(u8 battlerDef, u8 battlerAtk);
bool32 CanMoveFaintBattler(u16 move, u8 battlerDef, u8 battlerAtk, u8 nHits);
bool32 CanTargetFaintAiWithMod(u8 battlerDef, u8 battlerAtk, s32 hpMod, s32 dmgMod);
@ -35,7 +36,8 @@ u16 AI_GetHoldEffect(u32 battlerId);
u32 AI_GetMoveAccuracy(u8 battlerAtk, u8 battlerDef, u16 atkAbility, u16 defAbility, u8 atkHoldEffect, u8 defHoldEffect, u16 move);
bool32 DoesBattlerIgnoreAbilityChecks(u16 atkAbility, u16 move);
bool32 AI_WeatherHasEffect(void);
bool32 CanAttackerFaintTarget(u8 battlerAtk, u8 battlerDef, u8 index, u8 numHits);
bool32 CanAIFaintTarget(u8 battlerAtk, u8 battlerDef, u8 numHits);
bool32 CanIndexMoveFaintTarget(u8 battlerAtk, u8 battlerDef, u8 index, u8 numHits);
bool32 AI_IsTerrainAffected(u8 battlerId, u32 flags);
bool32 AI_IsBattlerGrounded(u8 battlerId);
bool32 HasDamagingMove(u8 battlerId);
@ -51,9 +53,13 @@ bool32 ShouldRecover(u8 battlerAtk, u8 battlerDef, u16 move, u8 healPercent);
bool32 ShouldSetScreen(u8 battlerAtk, u8 battlerDef, u16 moveEffect);
bool32 ShouldPivot(u8 battlerAtk, u8 battlerDef, u16 defAbility, u16 move, u8 moveIndex);
bool32 IsRecycleEncouragedItem(u16 item);
bool32 ShouldRestoreHpBerry(u8 battlerAtk, u16 item);
bool32 IsStatBoostingBerry(u16 item);
bool32 CanKnockOffItem(u8 battler, u16 item);
bool32 IsAbilityOfRating(u16 ability, s8 rating);
s8 GetAbilityRating(u16 ability);
bool32 AI_IsAbilityOnSide(u32 battlerId, u32 ability);
bool32 AI_MoveMakesContact(u32 ability, u32 holdEffect, u16 move);
// stat stage checks
bool32 AnyStatIsRaised(u8 battlerId);
@ -120,7 +126,6 @@ bool32 IsSemiInvulnerable(u8 battlerDef, u16 move);
// status checks
bool32 AI_CanBeBurned(u8 battler, u16 ability);
bool32 AI_CanBePoisoned(u8 battler, u16 ability);
bool32 AI_CanBeConfused(u8 battler, u16 ability);
bool32 AI_CanSleep(u8 battler, u16 ability);
bool32 IsBattlerIncapacitated(u8 battler, u16 ability);

View File

@ -310,6 +310,5 @@ extern const u8 gText_BattleTourney[];
extern const u16 gMissStringIds[];
extern const u16 gStatUpStringIds[];
extern const u16 gTrappingMoves[];
#endif // GUARD_BATTLE_MESSAGE_H

View File

@ -36,6 +36,7 @@ u32 IsAbilityStatusProtected(u32 battler);
bool32 TryResetBattlerStatChanges(u8 battler);
bool32 CanCamouflage(u8 battlerId);
u16 GetNaturePowerMove(void);
u16 GetSecretPowerMoveEffect(void);
void StealTargetItem(u8 battlerStealer, u8 battlerItem);
u8 GetCatchingBattler(void);

View File

@ -261,6 +261,7 @@ extern const u8 BattleScript_AttackerAbilityStatRaiseEnd3[];
extern const u8 BattleScript_PoisonHealActivates[];
extern const u8 BattleScript_BadDreamsActivates[];
extern const u8 BattleScript_SwitchInAbilityMsg[];
extern const u8 BattleScript_SwitchInAbilityMsgRet[];
extern const u8 BattleScript_ToxicSpikesPoisoned[];
extern const u8 BattleScript_ToxicSpikesAbsorbed[];
extern const u8 BattleScript_StickyWebOnSwitchIn[];
@ -407,5 +408,12 @@ extern const u8 BattleScript_WanderingSpiritActivates[];
extern const u8 BattleScript_MirrorArmorReflect[];
extern const u8 BattleScript_GooeyActivates[];
extern const u8 BattleScript_PastelVeilActivates[];
extern const u8 BattleScript_MimicryActivatesEnd3[];
extern const u8 BattleScript_ApplyMimicry[];
extern const u8 BattleScript_AttackerFormChangeEnd3NoPopup[];
extern const u8 BattleScript_AttackerFormChangeMoveEffect[];
extern const u8 BattleScript_BothCanNoLongerEscape[];
extern const u8 BattleScript_OctolockEndTurn[];
extern const u8 BattleScript_NeutralizingGasExits[];
#endif // GUARD_BATTLE_SCRIPTS_H

View File

@ -8,21 +8,23 @@
#define MOVE_LIMITATION_TAUNT (1 << 4)
#define MOVE_LIMITATION_IMPRISON (1 << 5)
#define ABILITYEFFECT_ON_SWITCHIN 0x0
#define ABILITYEFFECT_ENDTURN 0x1
#define ABILITYEFFECT_MOVES_BLOCK 0x2
#define ABILITYEFFECT_ABSORBING 0x3
#define ABILITYEFFECT_MOVE_END_ATTACKER 0x4
#define ABILITYEFFECT_MOVE_END 0x5
#define ABILITYEFFECT_IMMUNITY 0x6
#define ABILITYEFFECT_FORECAST 0x7
#define ABILITYEFFECT_SYNCHRONIZE 0x8
#define ABILITYEFFECT_ATK_SYNCHRONIZE 0x9
#define ABILITYEFFECT_INTIMIDATE1 0xA
#define ABILITYEFFECT_INTIMIDATE2 0xB
#define ABILITYEFFECT_TRACE1 0xC
#define ABILITYEFFECT_TRACE2 0xD
#define ABILITYEFFECT_MOVE_END_OTHER 0xE
#define ABILITYEFFECT_ON_SWITCHIN 0
#define ABILITYEFFECT_ENDTURN 1
#define ABILITYEFFECT_MOVES_BLOCK 2
#define ABILITYEFFECT_ABSORBING 3
#define ABILITYEFFECT_MOVE_END_ATTACKER 4
#define ABILITYEFFECT_MOVE_END 5
#define ABILITYEFFECT_IMMUNITY 6
#define ABILITYEFFECT_FORECAST 7
#define ABILITYEFFECT_SYNCHRONIZE 8
#define ABILITYEFFECT_ATK_SYNCHRONIZE 9
#define ABILITYEFFECT_INTIMIDATE1 10
#define ABILITYEFFECT_INTIMIDATE2 11
#define ABILITYEFFECT_TRACE1 12
#define ABILITYEFFECT_TRACE2 13
#define ABILITYEFFECT_MOVE_END_OTHER 14
#define ABILITYEFFECT_NEUTRALIZINGGAS 15
// Special cases
#define ABILITYEFFECT_SWITCH_IN_TERRAIN 0xFE
#define ABILITYEFFECT_SWITCH_IN_WEATHER 0xFF
@ -102,6 +104,7 @@ u32 IsAbilityOnOpposingSide(u32 battlerId, u32 ability);
u32 IsAbilityOnField(u32 ability);
u32 IsAbilityOnFieldExcept(u32 battlerId, u32 ability);
u32 IsAbilityPreventingEscape(u32 battlerId);
bool32 IsBattlerProtected(u8 battlerId, u16 move);
bool32 CanBattlerEscape(u32 battlerId); // no ability check
void BattleScriptExecute(const u8* BS_ptr);
void BattleScriptPushCursorAndCallback(const u8* BS_ptr);
@ -157,8 +160,11 @@ void DoBurmyFormChange(u32 monId);
bool32 BlocksPrankster(u16 move, u8 battlerPrankster, u8 battlerDef, bool32 checkTarget);
u16 GetUsedHeldItem(u8 battler);
bool32 IsBattlerWeatherAffected(u8 battlerId, u32 weatherFlags);
void TryToApplyMimicry(u8 battlerId, bool8 various);
void TryToRevertMimicry(void);
void RestoreBattlerOriginalTypes(u8 battlerId);
// ability checks
// Ability checks
bool32 IsRolePlayBannedAbilityAtk(u16 ability);
bool32 IsRolePlayBannedAbility(u16 ability);
bool32 IsSkillSwapBannedAbility(u16 ability);

View File

@ -358,22 +358,39 @@
#define MOVE_EFFECT_INCINERATE 0x44
#define MOVE_EFFECT_BUG_BITE 0x45
#define MOVE_EFFECT_RECOIL_HP_25 0x46
#define NUM_MOVE_EFFECTS 0x47
#define MOVE_EFFECT_RELIC_SONG 0x47
#define MOVE_EFFECT_TRAP_BOTH 0x48
#define NUM_MOVE_EFFECTS 0x49
#define MOVE_EFFECT_AFFECTS_USER 0x4000
#define MOVE_EFFECT_CERTAIN 0x8000
// Battle terrain defines for gBattleTerrain.
#define BATTLE_TERRAIN_GRASS 0
#define BATTLE_TERRAIN_LONG_GRASS 1
#define BATTLE_TERRAIN_SAND 2
#define BATTLE_TERRAIN_UNDERWATER 3
#define BATTLE_TERRAIN_WATER 4
#define BATTLE_TERRAIN_POND 5
#define BATTLE_TERRAIN_MOUNTAIN 6
#define BATTLE_TERRAIN_CAVE 7
#define BATTLE_TERRAIN_BUILDING 8
#define BATTLE_TERRAIN_PLAIN 9
#define BATTLE_TERRAIN_GRASS 0
#define BATTLE_TERRAIN_LONG_GRASS 1
#define BATTLE_TERRAIN_SAND 2
#define BATTLE_TERRAIN_UNDERWATER 3
#define BATTLE_TERRAIN_WATER 4
#define BATTLE_TERRAIN_POND 5
#define BATTLE_TERRAIN_MOUNTAIN 6
#define BATTLE_TERRAIN_CAVE 7
#define BATTLE_TERRAIN_BUILDING 8
#define BATTLE_TERRAIN_PLAIN 9
// New battle terrains are used for Secret Power but not fully implemented.
#define BATTLE_TERRAIN_SOARING 10
#define BATTLE_TERRAIN_SKY_PILLAR 11
#define BATTLE_TERRAIN_BURIAL_GROUND 12
#define BATTLE_TERRAIN_PUDDLE 13
#define BATTLE_TERRAIN_MARSH 14
#define BATTLE_TERRAIN_SWAMP 15
#define BATTLE_TERRAIN_SNOW 16
#define BATTLE_TERRAIN_ICE 17
#define BATTLE_TERRAIN_VOLCANO 18
#define BATTLE_TERRAIN_DISTORTION_WORLD 19
#define BATTLE_TERRAIN_SPACE 20
#define BATTLE_TERRAIN_ULTRA_SPACE 21
#define BATTLE_TERRAIN_COUNT 22
#define B_WAIT_TIME_LONG 64
#define B_WAIT_TIME_MED 48

View File

@ -565,7 +565,8 @@
#define TRAP_ANIM_WHIRLPOOL 2
#define TRAP_ANIM_CLAMP 3
#define TRAP_ANIM_SAND_TOMB 4
#define TRAP_ANIM_INFESTATION 5
#define TRAP_ANIM_MAGMA_STORM 5
#define TRAP_ANIM_INFESTATION 6
// Weather defines for battle animation scripts.
#define ANIM_WEATHER_NONE 0

View File

@ -47,6 +47,11 @@
#define SPECIES_GRENINJA_ASH 10017
#define SPECIES_HOOPA 0
#define SPECIES_HOOPA_UNBOUND 10018
#define SPECIES_MELOETTA 0
#define SPECIES_MELOETTA_PIROUETTE 10019
#define SPECIES_MORPEKO 0
#define SPECIES_MORPEKO_HANGRY 10020
#define SPECIES_SIRFETCHD 10021
#endif
// Items with peculiar battle effects.
@ -87,11 +92,13 @@
#define GEN_8 5
#endif
// Mega Evolution settings
#define B_MEGA_EVO_TURN_ORDER GEN_7 // In Gen7, a Pokémon's Speed after Mega Evolution is used to determine turn order, not its Speed before.
// Calculation settings
#define B_CRIT_CHANCE GEN_7 // Chances of a critical hit landing. See CalcCritChanceStage.
#define B_CRIT_MULTIPLIER GEN_7 // In Gen6+, critical hits multiply damage by 1.5 instead of 2.
#define B_PARALYSIS_SPEED GEN_7 // In Gen7+, Speed is decreased by 50% instead of 75%.
#define B_TERRAIN_TYPE_BOOST GEN_8 // In Gen8, damage is boosted by 30% instead of 50%.
#define B_CONFUSION_SELF_DMG_CHANCE GEN_7 // In Gen7+, confusion has a 33.3% of self-damage, instead of 50%.
#define B_MULTI_HIT_CHANCE GEN_7 // In Gen5+, multi-hit moves have different %. See Cmd_setmultihitcounter for values.
@ -111,6 +118,7 @@
#define B_PAYBACK_SWITCH_BOOST GEN_7 // In Gen5+, if the opponent switches out, Payback's damage will no longer be doubled.
#define B_HIDDEN_POWER_DMG GEN_7 // In Gen6+, Hidden Power's base power was set to always be 60. Before, it was determined by the mon's IVs.
#define B_ROUGH_SKIN_DMG GEN_7 // In Gen4+, Rough Skin contact damage is 1/8th of max HP instead of 1/16th. This will also affect Iron Barbs.
#define B_KNOCK_OFF_DMG GEN_8 // In Gen6+, Knock Off deals 50% more damage when knocking off an item
// Type settings
#define B_GHOSTS_ESCAPE GEN_7 // In Gen6+, abilities like Shadow Tag or moves like Mean Look fail on Ghost-type Pokémon. They can also escape any Wild Battle.
@ -149,6 +157,9 @@
#define B_MEMENTO_FAIL GEN_7 // In Gen4+, Memento fails if there is no target or if the target is protected or behind substitute. But not if Atk/Sp. Atk are at -6.
#define B_GLARE_GHOST GEN_7 // In Gen4+, Glare can hit Ghost-type Pokémon normally.
#define B_SKILL_SWAP GEN_7 // In Gen4+, Skill Swap triggers switch-in abilities after use.
#define B_BRICK_BREAK GEN_7 // In Gen4+, you can destroy your own side's screens. In Gen 5+, screens are not removed if the target is immune.
#define B_WISH_HP_SOURCE GEN_7 // In Gen5+, Wish heals half of the user's max HP instead of the target's.
#define B_RAMPAGE_CANCELLING GEN_7 // In Gen5+, a failed Thrash, etc, will cancel except on its last turn.
// Ability settings
#define B_ABILITY_WEATHER GEN_7 // In Gen6+, ability-induced weather lasts 5 turns. Before, it lasted until the battle ended or until it was changed by a move or a different weather-affecting ability.
@ -157,7 +168,8 @@
#define B_SHADOW_TAG_ESCAPE GEN_7 // In Gen4+, if both sides have a Pokémon with Shadow Tag, all battlers can escape. Before, neither side could escape this situation.
#define B_MOODY_ACC_EVASION GEN_8 // In Gen8, Moody CANNOT raise Accuracy and Evasion anymore.
#define B_FLASH_FIRE_FROZEN GEN_7 // In Gen5+, Flash Fire can trigger even when frozen, when it couldn't before.
#define B_SYNCHRONIZE_NATURE GEN_8 // In Gen8, if the Pokémon with Synchronize is leading the party, it's 100% guaranteed that wild Pokémon will have the same ability, as opposed to 50% previously.
#define B_SYNCHRONIZE_NATURE GEN_8 // In Gen8, if a Pokémon with Synchronize is leading the party, it's 100% guaranteed that wild Pokémon will have the same ability, as opposed to 50% previously.
#define B_SYNCHRONIZE_TOXIC GEN_8 // In Gen5+, if a Pokémon with Synchronize is badly poisoned, the opponent will also become badly poisoned. Previously, the opponent would become regular poisoned.
#define B_UPDATED_INTIMIDATE GEN_8 // In Gen8, Intimidate doesn't work on opponents with the Inner Focus, Scrappy, Own Tempo or Oblivious abilities.
// Item settings
@ -166,6 +178,19 @@
#define B_X_ITEMS_BUFF GEN_7 // In Gen7+, the X Items raise a stat by 2 stages instead of 1.
#define B_MENTAL_HERB GEN_5 // In Gen5+, the Mental Herb cures Infatuation, Taunt, Encore, Torment, Heal Block, and Disable
#define B_TRAINERS_KNOCK_OFF_ITEMS TRUE // If TRUE, trainers can steal/swap your items (non-berries are restored after battle). In vanilla games trainers cannot steal items.
#define B_SOUL_DEW_BOOST GEN_7 // In Gens3-6, Soul Dew boosts Lati@s' Sp. Atk and Sp. Def. In Gen7+ it boosts the power of their Psychic and Dragon type moves instead.
#define B_NET_BALL_MODIFIER GEN_7 // In Gen7+, Net Ball's catch multiplier is x5 instead of x3.
#define B_DIVE_BALL_MODIFIER GEN_7 // In Gen4+, Dive Ball's effectiveness increases by when Surfing or Fishing.
#define B_NEST_BALL_MODIFIER GEN_7 // Nest Ball's formula varies depending on the Gen. See Cmd_handleballthrow.
#define B_REPEAT_BALL_MODIFIER GEN_7 // In Gen7+, Repeat Ball's catch multiplier is x3.5 instead of x3.
#define B_TIMER_BALL_MODIFIER GEN_7 // In Gen5+, Timer Ball's effectiveness increases by x0.3 per turn instead of x0.1
#define B_DUSK_BALL_MODIFIER GEN_7 // In Gen7+, Dusk Ball's catch multiplier is x3 instead of x3.5.
#define B_QUICK_BALL_MODIFIER GEN_7 // In Gen5+, Quick Ball's catch multiplier is x5 instead of x4.
#define B_LURE_BALL_MODIFIER GEN_7 // In Gen7+, Lure Ball's catch multiplier is x5 instead of x3.
#define B_HEAVY_BALL_MODIFIER GEN_7 // In Gen7+, Heavy Ball's ranges change. See Cmd_handleballthrow.
#define B_DREAM_BALL_MODIFIER GEN_8 // In Gen8, Dream Ball's catch multiplier is x4 when the target is asleep or has the ability Comatose.
#define B_SERENE_GRACE_BOOST GEN_7 // In Gen5+, Serene Grace boosts the added flinch chance of King's Rock and Razor Fang.
#define B_LEEK_ALWAYS_CRIT GEN_7 // In Gen6+, if a Farfetch'd or Sirfetch'd holding a Leek use a move with increased Critical Hit ratio, it will always result in a Critical Hit.
// Flag settings
// To use the following features in scripting, replace the 0s with the flag ID you're assigning it to.
@ -178,26 +203,31 @@
// Eg: Replace with VAR_UNUSED_0x40F7 so you can use VAR_TERRAIN for that feature.
#define VAR_TERRAIN 0 // If this var has a value, assigning a STATUS_FIELD_xx_TERRAIN to it before battle causes the battle to start with that terrain active
// Terrain settings
#define B_TERRAIN_BG_CHANGE TRUE // If set to TRUE, terrain moves permanently change the default battle background until the effect fades.
#define B_THUNDERSTORM_TERRAIN TRUE // If TRUE, overworld Thunderstorm generates Rain and Electric Terrain as in Gen 8.
#define B_TERRAIN_TYPE_BOOST GEN_8 // In Gen8, damage is boosted by 30% instead of 50%.
#define B_SECRET_POWER_EFFECT GEN_7 // Secret Power's effects change depending on terrain and generation. See GetSecretPowerMoveEffect.
#define B_SECRET_POWER_ANIMATION GEN_7 // Secret Power's animations change depending on terrain and generation.
#define B_NATURE_POWER_MOVES GEN_8 // Nature Power calls different moves depending on terrain and generation. See sNaturePowerMoves.
#define B_CAMOUFLAGE_TYPES GEN_7 // Camouflage changes the user to different types depending on terrain and generation. See sTerrainToType.
// Interface settings
#define B_ABILITY_POP_UP TRUE // In Gen5+, the Pokémon abilities are displayed in a pop-up, when they activate in battle.
#define B_FAST_INTRO TRUE // If set to TRUE, battle intro texts print at the same time as animation of a Pokémon, as opposing to waiting for the animation to end.
#define B_SHOW_TARGETS TRUE // If set to TRUE, all available targets, for moves hitting 2 or 3 Pokémon, will be shown before selecting a move.
#define B_SHOW_SPLIT_ICON TRUE // If set to TRUE, it will show an icon in the summary showing the move's category split.
#define B_HIDE_HEALTHBOX_IN_ANIMS TRUE // If set to TRUE, hides healthboxes during move animations.
#define B_TERRAIN_BG_CHANGE TRUE // If set to TRUE, terrain moves permanently change the default battle background until the effect fades.
// Critical Capture
#define B_CRITICAL_CAPTURE TRUE // If set to TRUE, Critical Capture will be enabled.
#define B_CATCHING_CHARM_BOOST 20 // % boost in Critical Capture odds if player has the Catching Charm.
// Last Used Ball
#define B_LAST_USED_BALL TRUE // If TRUE, the "last used ball" feature from Gen 7 will be implemented
#define B_LAST_USED_BALL_BUTTON R_BUTTON // If last used ball is implemented, this button (or button combo) will trigger throwing the last used ball.
// Catching settings
#define B_SEMI_INVULNERABLE_CATCH GEN_7 // In Gen4+, you cannot throw a ball against a Pokemon that is in a semi-invulnerable state (dig/fly/etc)
#define B_CATCHING_CHARM_BOOST 20 // % boost in Critical Capture odds if player has the Catching Charm.
#define B_CRITICAL_CAPTURE TRUE // If set to TRUE, Critical Capture will be enabled.
#define B_LAST_USED_BALL TRUE // If TRUE, the "last used ball" feature from Gen 7 will be implemented
#define B_LAST_USED_BALL_BUTTON R_BUTTON // If last used ball is implemented, this button (or button combo) will trigger throwing the last used ball.
// Other
#define B_DOUBLE_WILD_CHANCE 0 // % chance of encountering two Pokémon in a Wild Encounter.
#define B_THUNDERSTORM_TERRAIN TRUE // If TRUE, overworld Thunderstorm generates Rain and Electric Terrain as in Gen 8.
#define B_SEMI_INVULNERABLE_CATCH GEN_7 // In Gen4+, you cannot throw a ball against a Pokemon that is in a semi-invulnerable state (dig/fly/etc)
// Animation Settings
#define B_NEW_SWORD_PARTICLE FALSE // If set to TRUE, it updates Swords Dance's particle.

View File

@ -350,7 +350,7 @@
#define EFFECT_GEOMANCY 344
#define EFFECT_FAIRY_LOCK 345
#define EFFECT_ALLY_SWITCH 346
#define EFFECT_SLEEP_HIT 347
#define EFFECT_RELIC_SONG 347
#define EFFECT_ATTACKER_DEFENSE_DOWN_HIT 348
#define EFFECT_BODY_PRESS 349
#define EFFECT_EERIE_SPELL 350
@ -375,7 +375,18 @@
#define EFFECT_SPARKLY_SWIRL 369
#define EFFECT_PLASMA_FISTS 370
#define EFFECT_HYPERSPACE_FURY 371
#define EFFECT_AURA_WHEEL 372
#define EFFECT_PHOTON_GEYSER 373
#define EFFECT_SHELL_SIDE_ARM 374
#define EFFECT_TERRAIN_PULSE 375
#define EFFECT_JAW_LOCK 376
#define EFFECT_NO_RETREAT 377
#define EFFECT_TAR_SHOT 378
#define EFFECT_POLTERGEIST 379
#define EFFECT_OCTOLOCK 380
#define EFFECT_CLANGOROUS_SOUL 381
#define EFFECT_BOLT_BEAK 382
#define NUM_BATTLE_MOVE_EFFECTS 372
#define NUM_BATTLE_MOVE_EFFECTS 383
#endif // GUARD_CONSTANTS_BATTLE_MOVE_EFFECTS_H

View File

@ -198,6 +198,16 @@
#define VARIOUS_JUMP_IF_WEATHER_AFFECTED 125
#define VARIOUS_JUMP_IF_LEAF_GUARD_PROTECTED 126
#define VARIOUS_SET_ATTACKER_STICKY_WEB_USER 127
#define VARIOUS_TRY_TO_APPLY_MIMICRY 128
#define VARIOUS_PHOTON_GEYSER_CHECK 129
#define VARIOUS_SHELL_SIDE_ARM_CHECK 130
#define VARIOUS_TRY_NO_RETREAT 131
#define VARIOUS_TRY_TAR_SHOT 132
#define VARIOUS_CAN_TAR_SHOT_WORK 133
#define VARIOUS_CHECK_POLTERGEIST 134
#define VARIOUS_SET_OCTOLOCK 135
#define VARIOUS_CUT_1_3_HP_RAISE_STATS 136
#define VARIOUS_TRY_END_NEUTRALIZING_GAS 137
// Cmd_manipulatedamage
#define DMG_CHANGE_SIGN 0
@ -216,6 +226,7 @@
// Cmd_statbuffchange
#define STAT_BUFF_ALLOW_PTR (1 << 0) // If set, allow use of jumpptr. Set in every use of statbuffchange
#define STAT_BUFF_NOT_PROTECT_AFFECTED (1 << 5)
#define STAT_BUFF_UPDATE_MOVE_EFFECT (1 << 6)
// stat change flags for Cmd_playstatchangeanimation
#define STAT_CHANGE_NEGATIVE (1 << 0)

View File

@ -410,7 +410,7 @@
#define STRINGID_PKMNTWISTEDDIMENSIONS 406
#define STRINGID_POINTEDSTONESFLOAT 407
#define STRINGID_CLOAKEDINMYSTICALMOONLIGHT 408
#define STRINGID_TRAPPERBYSWIRLINGMAGMA 409
#define STRINGID_TRAPPEDBYSWIRLINGMAGMA 409
#define STRINGID_VANISHEDINSTANTLY 410
#define STRINGID_PROTECTEDTEAM 411
#define STRINGID_SHAREDITSGUARD 412
@ -420,7 +420,7 @@
#define STRINGID_HURLEDINTOTHEAIR 416
#define STRINGID_HELDITEMSLOSEEFFECTS 417
#define STRINGID_FELLSTRAIGHTDOWN 418
#define STRINGID_TRANSFORMEDINTOWATERTYPE 419
#define STRINGID_TARGETCHANGEDTYPE 419
#define STRINGID_PKMNACQUIREDSIMPLE 420
#define STRINGID_EMPTYSTRING5 421
#define STRINGID_KINDOFFER 422
@ -601,8 +601,16 @@
#define STRINGID_SWAPPEDABILITIES 598
#define STRINGID_PASTELVEILPROTECTED 599
#define STRINGID_PASTELVEILENTERS 600
#define STRINGID_BATTLERTYPECHANGEDTO 601
#define STRINGID_BOTHCANNOLONGERESCAPE 602
#define STRINGID_CANTESCAPEDUETOUSEDMOVE 603
#define STRINGID_PKMNBECAMEWEAKERTOFIRE 604
#define STRINGID_ABOUTTOUSEPOLTERGEIST 605
#define STRINGID_CANTESCAPEBECAUSEOFCURRENTMOVE 606
#define STRINGID_NEUTRALIZINGGASENTERS 607
#define STRINGID_NEUTRALIZINGGASOVER 608
#define BATTLESTRINGS_COUNT 601
#define BATTLESTRINGS_COUNT 609
// The below IDs are all indexes into battle message tables,
// used to determine which of a set of messages to print.
@ -838,6 +846,7 @@
#define B_MSG_SWITCHIN_ASONE 13
#define B_MSG_SWITCHIN_CURIOUS_MEDICINE 14
#define B_MSG_SWITCHIN_PASTEL_VEIL 15
#define B_MSG_SWITCHIN_NEUTRALIZING_GAS 16
// gMentalHerbCureStringIds
#define B_MSG_MENTALHERBCURE_INFATUATION 0

View File

@ -62,12 +62,12 @@
#define HOLD_EFFECT_FIRE_POWER 58
#define HOLD_EFFECT_DRAGON_POWER 59
#define HOLD_EFFECT_NORMAL_POWER 60
#define HOLD_EFFECT_UP_GRADE 61
#define HOLD_EFFECT_UPGRADE 61
#define HOLD_EFFECT_SHELL_BELL 62
#define HOLD_EFFECT_LUCKY_PUNCH 63
#define HOLD_EFFECT_METAL_POWDER 64
#define HOLD_EFFECT_THICK_CLUB 65
#define HOLD_EFFECT_STICK 66
#define HOLD_EFFECT_LEEK 66
// Gen4 hold effects.
#define HOLD_EFFECT_CHOICE_SCARF 67

View File

@ -308,6 +308,7 @@
#define FLAG_DMG_UNGROUNDED_IGNORE_TYPE_IF_FLYING (1 << 24) // Makes a Ground type move do 1x damage to flying and levitating targets
#define FLAG_THAW_USER (1 << 25)
#define FLAG_HIT_IN_SUBSTITUTE (1 << 26) // Hyperspace Fury
#define FLAG_TWO_STRIKES (1 << 27) // A move with this flag will strike twice, and may apply its effect on each hit
// Split defines.
#define SPLIT_PHYSICAL 0x0

View File

@ -4937,11 +4937,13 @@ extern const u32 gBattleAnimBgImage_Hurricane[];
extern const u32 gBattleAnimBgPalette_Hurricane[];
extern const u32 gBattleAnimBgTilemap_Hurricane[];
extern const u32 gBattleAnimBgPalette_RockWrecker[];
extern const u32 gBattleAnimBgTilemap_GigaImpactPlayer[];
extern const u32 gBattleAnimBgTilemap_GigaImpactOpponent[];
extern const u32 gBattleAnimBgTilemap_GigaImpactContest[];
extern const u32 gBattleAnimBgImage_GigaImpact[];
extern const u32 gBattleAnimBgPalette_GigaImpact[];
extern const u32 gBattleAnimBgImage_SpacialRend[];
extern const u32 gBattleAnimBgPalette_SpacialRend[];
extern const u32 gBattleAnimBgTilemap_SpacialRendOpponent[];
extern const u32 gBattleAnimBgTilemap_SpacialRendPlayer[];
extern const u32 gBattleAnimBgImage_DarkVoid[];
extern const u32 gBattleAnimBgPalette_DarkVoid[];
extern const u32 gBattleAnimBgTilemap_DarkVoid[];
extern const u32 gBattleAnimBgPalette_Dark[];
@ -4961,7 +4963,6 @@ extern const u32 gBattleAnimBgPalette_Fissure[];
extern const u32 gBattleAnimBgPalette_Bug[];
extern const u32 gBattleAnimBgPalette_Solarbeam[];
extern const u32 gBattleAnimBgPalette_MagmaStorm[];
extern const u32 gBattleAnimBgPalette_GigaImpact[];
extern const u32 gBattleAnimBgPalette_TrickRoom[];
extern const u32 gBattleAnimBgTilemap_Dark[];
extern const u32 gBattleAnimBgTilemap_Ghost[];

View File

@ -30,6 +30,8 @@ struct WildPokemonHeader
};
extern const struct WildPokemonHeader gWildMonHeaders[];
extern bool8 gIsFishingEncounter;
extern bool8 gIsSurfingEncounter;
void DisableWildEncounters(bool8 disabled);
bool8 StandardWildEncounter(u16 currMetaTileBehavior, u16 previousMetaTileBehavior);

View File

@ -278,6 +278,7 @@ static u8 ChooseMoveOrAction_Singles(void)
return AI_CHOICE_WATCH;
gActiveBattler = sBattler_AI;
// If can switch.
if (CountUsablePartyMons(sBattler_AI) > 0
&& !IsAbilityPreventingEscape(sBattler_AI)
@ -318,7 +319,7 @@ static u8 ChooseMoveOrAction_Singles(void)
}
}
}
numOfBestMoves = 1;
currentMoveArray[0] = AI_THINKING_STRUCT->score[0];
consideredMoveArray[0] = 0;
@ -559,7 +560,7 @@ static s16 AI_CheckBadMove(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
}
// check off screen
if (IsSemiInvulnerable(battlerDef, move) && moveEffect != EFFECT_SEMI_INVULNERABLE && GetWhoStrikesFirst(battlerAtk, battlerDef, TRUE) != 1)
if (IsSemiInvulnerable(battlerDef, move) && moveEffect != EFFECT_SEMI_INVULNERABLE && AI_WhoStrikesFirst(battlerAtk, battlerDef) == AI_IS_FASTER)
RETURN_SCORE_MINUS(20); // if target off screen and we go first, don't use move
// check if negates type
@ -578,6 +579,21 @@ static s16 AI_CheckBadMove(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
{
switch (AI_DATA->defAbility)
{
case ABILITY_MAGIC_GUARD:
switch (moveEffect)
{
case EFFECT_POISON:
case EFFECT_WILL_O_WISP:
case EFFECT_TOXIC:
case EFFECT_LEECH_SEED:
score -= 5;
break;
case EFFECT_CURSE:
if (IS_BATTLER_OF_TYPE(battlerAtk, TYPE_GHOST)) // Don't use Curse if you're a ghost type vs a Magic Guard user, they'll take no damage.
score -= 5;
break;
}
break;
case ABILITY_VOLT_ABSORB:
case ABILITY_MOTOR_DRIVE:
case ABILITY_LIGHTNING_ROD:
@ -1243,7 +1259,7 @@ static s16 AI_CheckBadMove(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
&& (B_MENTAL_HERB >= GEN_5 && AI_DATA->defHoldEffect != HOLD_EFFECT_MENTAL_HERB)
&& !PartnerHasSameMoveEffectWithoutTarget(AI_DATA->battlerAtkPartner, move, AI_DATA->partnerMove))
{
if (GetWhoStrikesFirst(battlerAtk, battlerDef, TRUE) == 0) // attacker should go first
if (AI_WhoStrikesFirst(battlerAtk, battlerDef) == AI_IS_FASTER) // Attacker should go first
{
if (gLastMoves[battlerDef] == MOVE_NONE || gLastMoves[battlerDef] == 0xFFFF)
score -= 10; // no anticipated move to disable
@ -1263,7 +1279,7 @@ static s16 AI_CheckBadMove(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
&& (B_MENTAL_HERB >= GEN_5 && AI_DATA->defHoldEffect != HOLD_EFFECT_MENTAL_HERB)
&& !DoesPartnerHaveSameMoveEffect(AI_DATA->battlerAtkPartner, battlerDef, move, AI_DATA->partnerMove))
{
if (GetWhoStrikesFirst(battlerAtk, battlerDef, TRUE) == 0) // attacker should go first
if (AI_WhoStrikesFirst(battlerAtk, battlerDef) == AI_IS_FASTER) // Attacker should go first
{
if (gLastMoves[battlerDef] == MOVE_NONE || gLastMoves[battlerDef] == 0xFFFF)
score -= 10; // no anticipated move to encore
@ -1377,22 +1393,22 @@ static s16 AI_CheckBadMove(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
}
break;
case EFFECT_SANDSTORM:
if (gBattleWeather & WEATHER_SANDSTORM_ANY //TODO | WEATHER_PRIMAL_ANY)
if (gBattleWeather & (WEATHER_SANDSTORM_ANY | WEATHER_PRIMAL_ANY)
|| PartnerMoveEffectIsWeather(AI_DATA->battlerAtkPartner, AI_DATA->partnerMove))
score -= 8;
break;
case EFFECT_SUNNY_DAY:
if (gBattleWeather & WEATHER_SUN_ANY //TODO | WEATHER_PRIMAL_ANY)
if (gBattleWeather & (WEATHER_SUN_ANY | WEATHER_PRIMAL_ANY)
|| PartnerMoveEffectIsWeather(AI_DATA->battlerAtkPartner, AI_DATA->partnerMove))
score -= 8;
break;
case EFFECT_RAIN_DANCE:
if (gBattleWeather & WEATHER_RAIN_ANY //TODO | WEATHER_PRIMAL_ANY)
if (gBattleWeather & (WEATHER_RAIN_ANY | WEATHER_PRIMAL_ANY)
|| PartnerMoveEffectIsWeather(AI_DATA->battlerAtkPartner, AI_DATA->partnerMove))
score -= 8;
break;
case EFFECT_HAIL:
if (gBattleWeather & WEATHER_HAIL_ANY //TODO | WEATHER_PRIMAL_ANY)
if (gBattleWeather & (WEATHER_HAIL_ANY | WEATHER_PRIMAL_ANY)
|| PartnerMoveEffectIsWeather(AI_DATA->battlerAtkPartner, AI_DATA->partnerMove))
score -= 8;
break;
@ -1458,7 +1474,7 @@ static s16 AI_CheckBadMove(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
else if (move == MOVE_FAKE_OUT) // filter out first impression
{
if ((AI_DATA->atkHoldEffect == HOLD_EFFECT_CHOICE_BAND || AI_DATA->atkAbility == ABILITY_GORILLA_TACTICS)
&& (CountUsablePartyMons(battlerDef) > 0 || !CanAttackerFaintTarget(battlerAtk, battlerDef, AI_THINKING_STRUCT->movesetIndex, 0)))
&& (CountUsablePartyMons(battlerDef) > 0 || !CanIndexMoveFaintTarget(battlerAtk, battlerDef, AI_THINKING_STRUCT->movesetIndex, 0)))
{
if (CountUsablePartyMons(battlerAtk) == 0)
score -= 10; // Don't lock the attacker into Fake Out if they can't switch out afterwards.
@ -1699,12 +1715,12 @@ static s16 AI_CheckBadMove(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
if (AI_DATA->defAbility == ABILITY_WONDER_GUARD && effectiveness < AI_EFFECTIVENESS_x2)
score -= 10;
else if (AI_DATA->atkAbility != ABILITY_TRUANT
&& !CanAttackerFaintTarget(battlerAtk, battlerDef, AI_THINKING_STRUCT->movesetIndex, 0))
&& !CanIndexMoveFaintTarget(battlerAtk, battlerDef, AI_THINKING_STRUCT->movesetIndex, 0))
score -= 2;
break;
case EFFECT_SPITE:
case EFFECT_MIMIC:
if (GetWhoStrikesFirst(battlerAtk, battlerDef, TRUE) == 0) // attacker should go first
if (AI_WhoStrikesFirst(battlerAtk, battlerDef) == AI_IS_FASTER) // Attacker should go first
{
if (gLastMoves[battlerDef] == MOVE_NONE
|| gLastMoves[battlerDef] == 0xFFFF)
@ -1861,7 +1877,7 @@ static s16 AI_CheckBadMove(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
if (isDoubleBattle)
{
if (IsHazardMoveEffect(gBattleMoves[AI_DATA->partnerMove].effect) // partner is going to set up hazards
&& GetWhoStrikesFirst(AI_DATA->battlerAtkPartner, battlerAtk, FALSE)) // partner is going to set up before the potential Defog
&& AI_WhoStrikesFirst(AI_DATA->battlerAtkPartner, battlerAtk) == AI_IS_FASTER) // partner is going to set up before the potential Defog
{
score -= 10;
break; // Don't use Defog if partner is going to set up hazards
@ -1899,7 +1915,7 @@ static s16 AI_CheckBadMove(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
break;
case EFFECT_SEMI_INVULNERABLE:
if (predictedMove != MOVE_NONE
&& GetWhoStrikesFirst(battlerAtk, battlerDef, TRUE) == 1
&& AI_WhoStrikesFirst(battlerAtk, battlerDef) == AI_IS_SLOWER
&& gBattleMoves[predictedMove].effect == EFFECT_SEMI_INVULNERABLE)
score -= 10; // Don't Fly/dig/etc if opponent is going to fly/dig/etc after you
@ -2080,7 +2096,7 @@ static s16 AI_CheckBadMove(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
case EFFECT_ME_FIRST:
if (predictedMove != MOVE_NONE)
{
if (GetWhoStrikesFirst(battlerAtk, battlerDef, TRUE) == 1)
if (AI_WhoStrikesFirst(battlerAtk, battlerDef) == AI_IS_SLOWER)
score -= 10; // Target is predicted to go first, Me First will fail
else
return AI_CheckBadMove(battlerAtk, battlerDef, predictedMove, score);
@ -2267,7 +2283,7 @@ static s16 AI_CheckBadMove(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
}
break;
case EFFECT_ELECTRIFY:
if (GetWhoStrikesFirst(battlerAtk, battlerDef, TRUE) == 0
if (AI_WhoStrikesFirst(battlerAtk, battlerDef) == AI_IS_FASTER
//|| GetMoveTypeSpecial(battlerDef, predictedMove) == TYPE_ELECTRIC // Move will already be electric type
|| PartnerMoveIsSameAsAttacker(AI_DATA->battlerAtkPartner, battlerDef, move, AI_DATA->partnerMove))
score -= 10;
@ -2296,7 +2312,7 @@ static s16 AI_CheckBadMove(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
case EFFECT_INSTRUCT:
{
u16 instructedMove;
if (GetWhoStrikesFirst(battlerAtk, battlerDef, TRUE) == 1)
if (AI_WhoStrikesFirst(battlerAtk, battlerDef) == AI_IS_SLOWER)
instructedMove = predictedMove;
else
instructedMove = gLastMoves[battlerDef];
@ -2305,7 +2321,7 @@ static s16 AI_CheckBadMove(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
|| IsInstructBannedMove(instructedMove)
|| MoveRequiresRecharging(instructedMove)
|| MoveCallsOtherMove(instructedMove)
#ifdef ITEM_Z_RING
#ifdef ITEM_Z_POWER_RING
//|| (IsZMove(instructedMove))
#endif
|| (gLockedMoves[battlerDef] != 0 && gLockedMoves[battlerDef] != 0xFFFF)
@ -2336,21 +2352,21 @@ static s16 AI_CheckBadMove(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
break;
case EFFECT_QUASH:
if (!isDoubleBattle
|| GetWhoStrikesFirst(battlerAtk, battlerDef, TRUE) == 1
|| AI_WhoStrikesFirst(battlerAtk, battlerDef) == AI_IS_SLOWER
|| PartnerMoveIsSameAsAttacker(AI_DATA->battlerAtkPartner, battlerDef, move, AI_DATA->partnerMove))
score -= 10;
break;
case EFFECT_AFTER_YOU:
if (!IsTargetingPartner(battlerAtk, battlerDef)
|| !isDoubleBattle
|| GetWhoStrikesFirst(battlerAtk, battlerDef, TRUE) == 1
|| AI_WhoStrikesFirst(battlerAtk, battlerDef) == AI_IS_SLOWER
|| PartnerMoveIsSameAsAttacker(AI_DATA->battlerAtkPartner, battlerDef, move, AI_DATA->partnerMove))
score -= 10;
break;
case EFFECT_SUCKER_PUNCH:
if (predictedMove != MOVE_NONE)
{
if (IS_MOVE_STATUS(predictedMove) || GetWhoStrikesFirst(battlerAtk, battlerDef, TRUE) == 1) // opponent going first
if (IS_MOVE_STATUS(predictedMove) || AI_WhoStrikesFirst(battlerAtk, battlerDef) == AI_IS_SLOWER) // Opponent going first
score -= 10;
}
break;
@ -2398,11 +2414,11 @@ static s16 AI_CheckBadMove(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
score--;
break;
case EFFECT_VITAL_THROW:
if (IsAiFaster(AI_CHECK_FASTER) && GetHealthPercentage(battlerAtk) < 40)
if (WillAIStrikeFirst() && GetHealthPercentage(battlerAtk) < 40)
score--; // don't want to move last
break;
case EFFECT_FLAIL:
if (GetWhoStrikesFirst(battlerAtk, battlerDef, TRUE) == 1 // opponent should go first
if (AI_WhoStrikesFirst(battlerAtk, battlerDef) == AI_IS_SLOWER // Opponent should go first
|| GetHealthPercentage(battlerAtk) > 50)
score -= 4;
break;
@ -2450,10 +2466,10 @@ static s16 AI_TryToFaint(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
if (gBattleMoves[move].power == 0)
return score; // can't make anything faint with no power
if (CanAttackerFaintTarget(battlerAtk, battlerDef, AI_THINKING_STRUCT->movesetIndex, 0) && gBattleMoves[move].effect != EFFECT_EXPLOSION)
if (CanIndexMoveFaintTarget(battlerAtk, battlerDef, AI_THINKING_STRUCT->movesetIndex, 0) && gBattleMoves[move].effect != EFFECT_EXPLOSION)
{
// this move can faint the target
if (GetWhoStrikesFirst(battlerAtk, battlerDef, TRUE) == 0 || GetMovePriority(battlerAtk, move) > 0)
if (!WillAIStrikeFirst() || GetMovePriority(battlerAtk, move) > 0)
score += 4; // we go first or we're using priority move
else
score += 2;
@ -2501,7 +2517,7 @@ static s16 AI_TryToFaint(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
}
//AI_TryToFaint_CheckIfDanger
if (!IsAiFaster(AI_CHECK_FASTER) && CanTargetFaintAi(battlerDef, battlerAtk))
if (!WillAIStrikeFirst() && CanTargetFaintAi(battlerDef, battlerAtk))
{ // AI_TryToFaint_Danger
if (GetMoveDamageResult(move) != MOVE_POWER_BEST)
score--;
@ -2551,7 +2567,7 @@ static s16 AI_DoubleBattle(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
// Ally decided to use Frost Breath on us. we must have Anger Point as our ability
if (AI_DATA->atkAbility == ABILITY_ANGER_POINT)
{
if (GetWhoStrikesFirst(battlerAtk, battlerAtkPartner, TRUE) == 1) // partner moving first
if (AI_WhoStrikesFirst(battlerAtk, battlerAtkPartner) == AI_IS_SLOWER) // Partner moving first
{
// discourage raising our attack since it's about to be maxed out
if (IsAttackBoostMoveEffect(effect))
@ -2692,7 +2708,7 @@ static s16 AI_DoubleBattle(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
&& !IS_MOVE_STATUS(move)
&& HasMoveWithSplit(battlerAtkPartner, SPLIT_PHYSICAL)
&& BattlerStatCanRise(battlerAtkPartner, atkPartnerAbility, STAT_ATK)
&& !CanAttackerFaintTarget(battlerAtk, battlerAtkPartner, AI_THINKING_STRUCT->movesetIndex, 1))
&& !CanIndexMoveFaintTarget(battlerAtk, battlerAtkPartner, AI_THINKING_STRUCT->movesetIndex, 1))
{
RETURN_SCORE_PLUS(1);
}
@ -2701,7 +2717,7 @@ static s16 AI_DoubleBattle(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
if (!IS_MOVE_STATUS(move)
&& (moveType == TYPE_DARK || moveType == TYPE_GHOST || moveType == TYPE_BUG)
&& BattlerStatCanRise(battlerAtkPartner, atkPartnerAbility, STAT_SPEED)
&& !CanAttackerFaintTarget(battlerAtk, battlerAtkPartner, AI_THINKING_STRUCT->movesetIndex, 1))
&& !CanIndexMoveFaintTarget(battlerAtk, battlerAtkPartner, AI_THINKING_STRUCT->movesetIndex, 1))
{
RETURN_SCORE_PLUS(1);
}
@ -2767,7 +2783,7 @@ static s16 AI_DoubleBattle(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
&& !IS_MOVE_STATUS(move)
&& HasMoveWithSplit(battlerAtkPartner, SPLIT_PHYSICAL)
&& BattlerStatCanRise(battlerAtkPartner, atkPartnerAbility, STAT_ATK)
&& !CanAttackerFaintTarget(battlerAtk, battlerAtkPartner, AI_THINKING_STRUCT->movesetIndex, 0))
&& !CanIndexMoveFaintTarget(battlerAtk, battlerAtkPartner, AI_THINKING_STRUCT->movesetIndex, 0))
{
RETURN_SCORE_PLUS(1);
}
@ -2818,22 +2834,22 @@ static s16 AI_DoubleBattle(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
case EFFECT_INSTRUCT:
{
u16 instructedMove;
if (GetWhoStrikesFirst(battlerAtk, battlerAtkPartner, TRUE) == 0)
if (AI_WhoStrikesFirst(battlerAtk, battlerAtkPartner) == AI_IS_FASTER)
instructedMove = AI_DATA->partnerMove;
else
instructedMove = gLastMoves[battlerAtkPartner];
if (instructedMove != MOVE_NONE
&& !IS_MOVE_STATUS(instructedMove)
&& gBattleMoves[instructedMove].target & (MOVE_TARGET_BOTH | MOVE_TARGET_FOES_AND_ALLY)) //Use instruct on multi-target moves
&& gBattleMoves[instructedMove].target & (MOVE_TARGET_BOTH | MOVE_TARGET_FOES_AND_ALLY)) // Use instruct on multi-target moves
{
RETURN_SCORE_PLUS(1);
}
}
break;
case EFFECT_AFTER_YOU:
if (GetWhoStrikesFirst(battlerAtkPartner, FOE(battlerAtkPartner), TRUE) == 1 // opponent mon 1 goes before partner
|| GetWhoStrikesFirst(battlerAtkPartner, BATTLE_PARTNER(FOE(battlerAtkPartner)), TRUE) == 1) // opponent mon 2 goes before partner
if (AI_WhoStrikesFirst(battlerAtkPartner, FOE(battlerAtkPartner) == AI_IS_SLOWER) // Opponent mon 1 goes before partner
|| AI_WhoStrikesFirst(battlerAtkPartner, BATTLE_PARTNER(FOE(battlerAtkPartner)) == AI_IS_SLOWER)) // Opponent mon 2 goes before partner
{
if (gBattleMoves[AI_DATA->partnerMove].effect == EFFECT_COUNTER || gBattleMoves[AI_DATA->partnerMove].effect == EFFECT_MIRROR_COAT)
break; // These moves need to go last
@ -2859,7 +2875,9 @@ static s16 AI_DoubleBattle(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
case EFFECT_EARTHQUAKE:
case EFFECT_MAGNITUDE:
if (!IsBattlerGrounded(battlerAtkPartner)
|| (GetWhoStrikesFirst(battlerAtk, battlerAtkPartner, TRUE) == 1 && IsUngroundingEffect(gBattleMoves[AI_DATA->partnerMove].effect)))
|| (IsBattlerGrounded(battlerAtkPartner)
&& AI_WhoStrikesFirst(battlerAtk, battlerAtkPartner) == AI_IS_SLOWER
&& IsUngroundingEffect(gBattleMoves[AI_DATA->partnerMove].effect)))
score += 2;
else if (IS_BATTLER_OF_TYPE(battlerAtkPartner, TYPE_FIRE)
|| IS_BATTLER_OF_TYPE(battlerAtkPartner, TYPE_ELECTRIC)
@ -2910,9 +2928,9 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
// check already dead
if (!IsBattlerIncapacitated(battlerDef, AI_DATA->defAbility)
&& CanTargetFaintAi(battlerAtk, battlerDef)
&& GetWhoStrikesFirst(battlerAtk, battlerDef, TRUE) == 1) // opponent should go first
&& AI_WhoStrikesFirst(battlerAtk, battlerDef) == AI_IS_SLOWER) // Opponent should go first
{
if (atkPriority > 0)
if (atkPriority > 0)
score++;
else
score--;
@ -2949,38 +2967,26 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
}
}
// ability checks
// attacker ability checks
switch (AI_DATA->atkAbility)
{
case ABILITY_MOXIE:
case ABILITY_BEAST_BOOST:
if (GetWhoStrikesFirst(battlerAtk, battlerDef, TRUE) == 0) // attacker should go first
case ABILITY_CHILLING_NEIGH:
case ABILITY_GRIM_NEIGH:
case ABILITY_AS_ONE_ICE_RIDER:
case ABILITY_AS_ONE_SHADOW_RIDER:
if (AI_WhoStrikesFirst(battlerAtk, battlerDef) == AI_IS_FASTER) // Attacker should go first
{
if (CanAttackerFaintTarget(battlerAtk, battlerDef, AI_THINKING_STRUCT->movesetIndex, 0))
if (CanIndexMoveFaintTarget(battlerAtk, battlerDef, AI_THINKING_STRUCT->movesetIndex, 0))
score += 8; // prioritize killing target for stat boost
}
break;
case ABILITY_MAGIC_GUARD:
switch (moveEffect)
{
case EFFECT_POISON:
case EFFECT_WILL_O_WISP:
case EFFECT_TOXIC:
case EFFECT_LEECH_SEED:
score -= 5;
break;
case EFFECT_CURSE:
if (IS_BATTLER_OF_TYPE(battlerDef, TYPE_GHOST))
score -= 5;
break;
}
break;
} // ability checks
// move effect checks
switch (moveEffect)
{
case EFFECT_HIT:
break;
case EFFECT_SLEEP:
@ -3042,7 +3048,7 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
break;
case EFFECT_SPEED_UP:
case EFFECT_SPEED_UP_2:
if (IsAiFaster(AI_CHECK_SLOWER))
if (!WillAIStrikeFirst())
{
if (!AI_RandLessThan(70))
score += 3;
@ -3140,7 +3146,7 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
break;
case EFFECT_SPEED_DOWN:
case EFFECT_SPEED_DOWN_2:
if (IsAiFaster(AI_CHECK_FASTER))
if (WillAIStrikeFirst())
score -= 3;
else if (!AI_RandLessThan(70))
score += 2;
@ -3243,6 +3249,10 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
case EFFECT_MULTI_HIT:
case EFFECT_DOUBLE_HIT:
case EFFECT_TRIPLE_KICK:
if (AI_MoveMakesContact(AI_DATA->atkAbility, AI_DATA->atkHoldEffect, move)
&& AI_DATA->atkAbility != ABILITY_MAGIC_GUARD
&& AI_DATA->defHoldEffect == HOLD_EFFECT_ROCKY_HELMET)
score -= 2;
break;
case EFFECT_CONVERSION:
if (!IS_BATTLER_OF_TYPE(battlerAtk, gBattleMoves[gBattleMons[battlerAtk].moves[0]].type))
@ -3381,7 +3391,7 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
score += 2;
break;
case EFFECT_SPEED_DOWN_HIT:
if (IsAiFaster(AI_CHECK_FASTER))
if (WillAIStrikeFirst())
score -= 2;
else if (!AI_RandLessThan(70))
score++;
@ -3413,7 +3423,7 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
score++;
break;
case EFFECT_MIMIC:
if (GetWhoStrikesFirst(battlerAtk, battlerDef, TRUE) == 0)
if (AI_WhoStrikesFirst(battlerAtk, battlerDef) == AI_IS_FASTER)
{
if (gLastMoves[battlerDef] != MOVE_NONE && gLastMoves[battlerDef] != 0xFFFF)
return AI_CheckViability(battlerAtk, battlerDef, gLastMoves[battlerDef], score);
@ -3472,7 +3482,7 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
if (gDisableStructs[battlerDef].disableTimer == 0
&& (B_MENTAL_HERB >= GEN_5 && AI_DATA->defHoldEffect != HOLD_EFFECT_MENTAL_HERB)) // mental herb
{
if (GetWhoStrikesFirst(battlerAtk, battlerDef, TRUE) == 0) // AI goes first
if (AI_WhoStrikesFirst(battlerAtk, battlerDef) == AI_IS_FASTER) // AI goes first
{
if (gLastMoves[battlerDef] != MOVE_NONE
&& gLastMoves[battlerDef] != 0xFFFF)
@ -3522,11 +3532,11 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
score++;
break;
case EFFECT_SPEED_UP_HIT:
if (AI_DATA->atkAbility == ABILITY_SERENE_GRACE && AI_DATA->defAbility != ABILITY_CONTRARY && IsAiFaster(AI_CHECK_SLOWER))
if (AI_DATA->atkAbility == ABILITY_SERENE_GRACE && AI_DATA->defAbility != ABILITY_CONTRARY && !WillAIStrikeFirst())
score += 3;
break;
case EFFECT_DESTINY_BOND:
if (GetWhoStrikesFirst(battlerAtk, battlerDef, TRUE) == 0 && CanTargetFaintAi(battlerDef, battlerAtk))
if (AI_WhoStrikesFirst(battlerAtk, battlerDef) == AI_IS_FASTER && CanTargetFaintAi(battlerDef, battlerAtk))
score += 3;
break;
case EFFECT_SPITE:
@ -3772,9 +3782,9 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
case EFFECT_FELL_STINGER:
if (gBattleMons[battlerAtk].statStages[STAT_ATK] < MAX_STAT_STAGE
&& AI_DATA->atkAbility != ABILITY_CONTRARY
&& CanAttackerFaintTarget(battlerAtk, battlerDef, AI_THINKING_STRUCT->movesetIndex, 0))
&& CanIndexMoveFaintTarget(battlerAtk, battlerDef, AI_THINKING_STRUCT->movesetIndex, 0))
{
if (GetWhoStrikesFirst(battlerAtk, battlerDef, TRUE) == 0) // Attacker goes first
if (AI_WhoStrikesFirst(battlerAtk, battlerDef) == AI_IS_FASTER) // Attacker goes first
score += 9;
else
score += 3;
@ -3819,7 +3829,7 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
score++;
if (predictedMove != MOVE_NONE && !isDoubleBattle)
{
if (GetWhoStrikesFirst(battlerAtk, battlerDef, TRUE) == 0) // Attacker goes first
if (AI_WhoStrikesFirst(battlerAtk, battlerDef) == AI_IS_FASTER) // Attacker goes first
{
if (gBattleMoves[predictedMove].effect == EFFECT_EXPLOSION
|| gBattleMoves[predictedMove].effect == EFFECT_PROTECT)
@ -3886,7 +3896,7 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
break;
case EFFECT_ATTRACT:
if (!isDoubleBattle && BattlerWillFaintFromSecondaryDamage(battlerDef, AI_DATA->defAbility)
&& GetWhoStrikesFirst(battlerAtk, battlerDef, TRUE) == 1) // Target goes first
&& AI_WhoStrikesFirst(battlerAtk, battlerDef) == AI_IS_SLOWER) // Target goes first
break; // Don't use if the attract won't have a change to activate
if (gBattleMons[battlerDef].status1 & STATUS1_ANY
@ -3931,7 +3941,7 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
if (isDoubleBattle)
{
if (IsHazardMoveEffect(gBattleMoves[AI_DATA->partnerMove].effect) // Partner is going to set up hazards
&& GetWhoStrikesFirst(battlerAtk, AI_DATA->battlerAtkPartner, TRUE) == 1) // Partner going first
&& AI_WhoStrikesFirst(battlerAtk, AI_DATA->battlerAtkPartner) == AI_IS_SLOWER) // Partner going first
break; // Don't use Defog if partner is going to set up hazards
}
@ -3999,7 +4009,7 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
score += 2;
break;
case HOLD_EFFECT_TOXIC_ORB:
if (!ShouldPoisonSelf(battlerAtk, AI_DATA->atkAbility) && AI_CanBePoisoned(battlerDef, AI_DATA->defAbility))
if (!ShouldPoisonSelf(battlerAtk, AI_DATA->atkAbility))
score += 2;
break;
case HOLD_EFFECT_FLAME_ORB:
@ -4101,6 +4111,18 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
score++;
if (IsRecycleEncouragedItem(GetUsedHeldItem(battlerAtk)))
score++;
if (AI_DATA->atkAbility == ABILITY_RIPEN)
{
u16 item = GetUsedHeldItem(battlerAtk);
u16 toHeal = (ItemId_GetHoldEffectParam(item) == 10) ? 10 : gBattleMons[battlerAtk].maxHP / ItemId_GetHoldEffectParam(item);
if (IsStatBoostingBerry(item) && atkHpPercent > 60)
score++;
else if (ShouldRestoreHpBerry(battlerAtk, item) && !CanAIFaintTarget(battlerAtk, battlerDef, 0)
&& ((GetWhoStrikesFirst(battlerAtk, battlerDef, TRUE) == 0 && CanTargetFaintAiWithMod(battlerDef, battlerAtk, 0, 0))
|| !CanTargetFaintAiWithMod(battlerDef, battlerAtk, toHeal, 0)))
score++; // Recycle healing berry if we can't otherwise faint the target and the target wont kill us after we activate the berry
}
break;
case EFFECT_BRICK_BREAK:
if (gSideStatuses[GetBattlerSide(battlerDef)] & SIDE_STATUS_REFLECT)
@ -4305,7 +4327,7 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
if (!IsBattlerGrounded(battlerDef))
score += 3;
break;
case EFFECT_SLEEP_HIT: // Relic Song
case EFFECT_RELIC_SONG:
#if (defined SPECIES_MELOETTA && defined SPECIES_MELOETTA_PIROUETTE)
if (AI_DATA->atkSpecies == SPECIES_MELOETTA && gBattleMons[battlerDef].defense < gBattleMons[battlerDef].spDefense)
score += 3; // Change to pirouette if can do more damage
@ -4408,13 +4430,13 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
score++;
break;
case EFFECT_THROAT_CHOP:
if (predictedMove != MOVE_NONE && TestMoveFlags(predictedMove, FLAG_SOUND) && GetWhoStrikesFirst(battlerAtk, battlerDef, TRUE) == 0)
if (predictedMove != MOVE_NONE && TestMoveFlags(predictedMove, FLAG_SOUND) && AI_WhoStrikesFirst(battlerAtk, battlerDef) == AI_IS_FASTER)
score += 3; // Ai goes first and predicts the target will use a sound move
else if (TestMoveFlagsInMoveset(battlerDef, FLAG_SOUND))
score += 3;
break;
case EFFECT_HEAL_BLOCK:
if (GetWhoStrikesFirst(battlerAtk, battlerDef, TRUE) == 0 && predictedMove != MOVE_NONE && IsHealingMoveEffect(gBattleMoves[predictedMove].effect))
if (AI_WhoStrikesFirst(battlerAtk, battlerDef) == AI_IS_FASTER && predictedMove != MOVE_NONE && IsHealingMoveEffect(gBattleMoves[predictedMove].effect))
score += 3; // Try to cancel healing move
else if (HasHealingEffect(battlerDef) || AI_DATA->defHoldEffect == HOLD_EFFECT_LEFTOVERS
|| (AI_DATA->defHoldEffect == HOLD_EFFECT_BLACK_SLUDGE && IS_BATTLER_OF_TYPE(battlerDef, TYPE_POISON)))
@ -4450,7 +4472,7 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
break;
case EFFECT_QUASH:
if (isDoubleBattle
&& GetWhoStrikesFirst(AI_DATA->battlerAtkPartner, battlerDef, TRUE) == 1) // Attacker partner wouldn't go before target
&& AI_WhoStrikesFirst(AI_DATA->battlerAtkPartner, battlerDef) == AI_IS_SLOWER) // Attacker partner wouldn't go before target
score++;
break;
case EFFECT_TAILWIND:
@ -4472,8 +4494,8 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
if (IsBattlerGrounded(battlerAtk) && HasDamagingMoveOfType(battlerDef, TYPE_ELECTRIC)
&& !(AI_GetTypeEffectiveness(MOVE_EARTHQUAKE, battlerDef, battlerAtk) == AI_EFFECTIVENESS_x0)) // Doesn't resist ground move
{
if (GetWhoStrikesFirst(battlerAtk, battlerDef, TRUE) == 0) // Attacker goes first
{
if (AI_WhoStrikesFirst(battlerAtk, battlerDef) == AI_IS_FASTER) // Attacker goes first
{
if (gBattleMoves[predictedMove].type == TYPE_GROUND)
score += 3; // Cause the enemy's move to fail
break;
@ -4487,7 +4509,7 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
}
break;
case EFFECT_CAMOUFLAGE:
if (predictedMove != MOVE_NONE && GetWhoStrikesFirst(battlerAtk, battlerDef, TRUE) == 0 // Attacker goes first
if (predictedMove != MOVE_NONE && AI_WhoStrikesFirst(battlerAtk, battlerDef) == AI_IS_FASTER // Attacker goes first
&& !IS_MOVE_STATUS(move) && AI_GetTypeEffectiveness(predictedMove, battlerDef, battlerAtk) != AI_EFFECTIVENESS_x0)
score++;
break;
@ -4530,7 +4552,7 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
}
break;
case EFFECT_FLAIL:
if (GetWhoStrikesFirst(battlerAtk, battlerDef, TRUE) == 0) // Ai goes first
if (AI_WhoStrikesFirst(battlerAtk, battlerDef) == AI_IS_FASTER) // Ai goes first
{
if (GetHealthPercentage(battlerAtk) < 20)
score++;
@ -4572,7 +4594,7 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
score += 2;
break;
case EFFECT_ENDEAVOR:
if (GetWhoStrikesFirst(battlerAtk, battlerDef, TRUE) == 1) // Opponent faster
if (AI_WhoStrikesFirst(battlerAtk, battlerDef) == AI_IS_SLOWER) // Opponent faster
{
if (GetHealthPercentage(battlerAtk) < 40)
score++;
@ -4603,7 +4625,7 @@ static s16 AI_SetupFirstTurn(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
return score;
if (AI_THINKING_STRUCT->aiFlags & AI_FLAG_SMART_SWITCHING
&& GetWhoStrikesFirst(battlerAtk, battlerDef, TRUE) == 1
&& AI_WhoStrikesFirst(battlerAtk, battlerDef) == AI_IS_SLOWER
&& CanTargetFaintAi(battlerDef, battlerAtk)
&& GetMovePriority(battlerAtk, move) == 0)
{
@ -4923,7 +4945,7 @@ static s16 AI_HPAware(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
}
// consider target HP
if (CanAttackerFaintTarget(battlerAtk, battlerDef, AI_THINKING_STRUCT->movesetIndex, 0))
if (CanIndexMoveFaintTarget(battlerAtk, battlerDef, AI_THINKING_STRUCT->movesetIndex, 0))
{
score += 2;
}

View File

@ -12,12 +12,14 @@
#include "constants/item_effects.h"
#include "constants/items.h"
#include "constants/moves.h"
#include "constants/battle_ai.h"
// this file's functions
static bool8 HasSuperEffectiveMoveAgainstOpponents(bool8 noRng);
static bool8 FindMonWithFlagsAndSuperEffective(u16 flags, u8 moduloPercent);
static bool8 ShouldUseItem(void);
// Functions
void GetAIPartyIndexes(u32 battlerId, s32 *firstId, s32 *lastId)
{
if (BATTLE_TWO_VS_ONE_OPPONENT && (battlerId & BIT_SIDE) == B_SIDE_OPPONENT)
@ -82,7 +84,7 @@ static bool8 ShouldSwitchIfWonderGuard(void)
opposingPosition = BATTLE_OPPOSITE(GetBattlerPosition(gActiveBattler));
if (gBattleMons[GetBattlerAtPosition(opposingPosition)].ability != ABILITY_WONDER_GUARD)
if (GetBattlerAbility(GetBattlerAtPosition(opposingPosition)) != ABILITY_WONDER_GUARD)
return FALSE;
// Check if Pokemon has a super effective move.
@ -176,7 +178,7 @@ static bool8 FindMonThatAbsorbsOpponentsMove(void)
else
return FALSE;
if (gBattleMons[gActiveBattler].ability == absorbingTypeAbility)
if (AI_GetAbility(gActiveBattler) == absorbingTypeAbility)
return FALSE;
GetAIPartyIndexes(gActiveBattler, &firstId, &lastId);
@ -228,7 +230,7 @@ static bool8 ShouldSwitchIfNaturalCure(void)
{
if (!(gBattleMons[gActiveBattler].status1 & STATUS1_SLEEP))
return FALSE;
if (gBattleMons[gActiveBattler].ability != ABILITY_NATURAL_CURE)
if (AI_GetAbility(gActiveBattler) != ABILITY_NATURAL_CURE)
return FALSE;
if (gBattleMons[gActiveBattler].hp < gBattleMons[gActiveBattler].maxHP / 2)
return FALSE;
@ -407,7 +409,6 @@ static bool8 FindMonWithFlagsAndSuperEffective(u16 flags, u8 moduloPercent)
if (AI_GetTypeEffectiveness(move, gActiveBattler, battlerIn1) >= UQ_4_12(2.0) && Random() % moduloPercent == 0)
{
*(gBattleStruct->AI_monToSwitchIntoId + gActiveBattler) = i;
BtlController_EmitTwoReturnValues(1, B_ACTION_SWITCH, 0);
return TRUE;
}
}
@ -436,6 +437,7 @@ bool32 ShouldSwitch(void)
return FALSE;
availableToSwitch = 0;
if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE)
{
battlerIn1 = gActiveBattler;
@ -564,6 +566,7 @@ void AI_TrySwitchOrUseItem(void)
}
}
// AI has decided it shouldn't switch or use an item, so it will now choose a move to use
BtlController_EmitTwoReturnValues(1, B_ACTION_USE_MOVE, (gActiveBattler ^ BIT_SIDE) << 8);
}
@ -851,7 +854,8 @@ static bool8 ShouldUseItem(void)
break;
if (gBattleMons[gActiveBattler].hp == 0)
break;
if (gBattleMons[gActiveBattler].hp < gBattleMons[gActiveBattler].maxHP / 4 || gBattleMons[gActiveBattler].maxHP - gBattleMons[gActiveBattler].hp > itemEffects[paramOffset])
if (gBattleMons[gActiveBattler].hp < gBattleMons[gActiveBattler].maxHP / 4
|| gBattleMons[gActiveBattler].maxHP - gBattleMons[gActiveBattler].hp > itemEffects[paramOffset])
shouldUse = TRUE;
break;
case AI_ITEM_CURE_CONDITION:

View File

@ -439,6 +439,11 @@ static const u16 sOtherMoveCallingMoves[] =
};
// Functions
bool32 WillAIStrikeFirst(void)
{
return (AI_WhoStrikesFirst(sBattler_AI, gBattlerTarget) == AI_IS_FASTER);
}
bool32 AI_RandLessThan(u8 val)
{
if ((Random() % 0xFF) < val)
@ -632,7 +637,7 @@ bool32 IsTruantMonVulnerable(u32 battlerAI, u32 opposingBattler)
u32 move = gBattleResources->battleHistory->usedMoves[opposingBattler][i];
if (gBattleMoves[move].effect == EFFECT_PROTECT && move != MOVE_ENDURE)
return TRUE;
if (gBattleMoves[move].effect == EFFECT_SEMI_INVULNERABLE && GetWhoStrikesFirst(battlerAI, opposingBattler, TRUE) == 1)
if (gBattleMoves[move].effect == EFFECT_SEMI_INVULNERABLE && AI_WhoStrikesFirst(battlerAI, opposingBattler) == AI_IS_SLOWER)
return TRUE;
}
return FALSE;
@ -660,9 +665,9 @@ bool32 MovesWithSplitUnusable(u32 attacker, u32 target, u32 split)
for (i = 0; i < MAX_MON_MOVES; i++)
{
if (moves[i] != MOVE_NONE
&& moves[i] != 0xFFFF
&& GetBattleMoveSplit(moves[i]) == split
&& !(unusable & gBitTable[i]))
&& moves[i] != 0xFFFF
&& GetBattleMoveSplit(moves[i]) == split
&& !(unusable & gBitTable[i]))
{
SetTypeBeforeUsingMove(moves[i], attacker);
GET_MOVE_TYPE(moves[i], moveType);
@ -733,28 +738,45 @@ s32 AI_CalcDamage(u16 move, u8 battlerAtk, u8 battlerDef)
else
dmg = (critDmg + normalDmg * (critChance - 1)) / critChance;
// handle dynamic move damage
// Handle dynamic move damage
switch (gBattleMoves[move].effect)
{
case EFFECT_LEVEL_DAMAGE:
case EFFECT_PSYWAVE:
//psywave's expected damage is equal to the user's level
dmg = gBattleMons[battlerAtk].level;
dmg = gBattleMons[battlerAtk].level * (AI_DATA->atkAbility == ABILITY_PARENTAL_BOND ? 2 : 1);
break;
case EFFECT_DRAGON_RAGE:
dmg = 40;
dmg = 40 * (AI_DATA->atkAbility == ABILITY_PARENTAL_BOND ? 2 : 1);
break;
case EFFECT_SONICBOOM:
dmg = 20;
dmg = 20 * (AI_DATA->atkAbility == ABILITY_PARENTAL_BOND ? 2 : 1);
break;
//case EFFECT_METAL_BURST:
//case EFFECT_COUNTER:
default:
//do not add the random factor, it's an average case analysis
//dmg *= (100 - (Random() % 10)) / 100; // add random factor
case EFFECT_MULTI_HIT:
dmg *= (AI_DATA->atkAbility == ABILITY_SKILL_LINK ? 5 : 3);
break;
case EFFECT_TRIPLE_KICK:
dmg *= (AI_DATA->atkAbility == ABILITY_SKILL_LINK ? 6 : 5);
break;
case EFFECT_ENDEAVOR:
// If target has less HP than user, Endeavor does no damage
dmg = max(0, gBattleMons[battlerDef].hp - gBattleMons[battlerAtk].hp);
break;
case EFFECT_SUPER_FANG:
dmg = (AI_DATA->atkAbility == ABILITY_PARENTAL_BOND
? max(2, gBattleMons[battlerDef].hp * 3 / 4)
: max(1, gBattleMons[battlerDef].hp / 2));
break;
case EFFECT_FINAL_GAMBIT:
dmg = gBattleMons[battlerAtk].hp;
break;
}
// Handle other multi-strike moves
if (gBattleMoves[move].flags & FLAG_TWO_STRIKES)
dmg *= 2;
else if (move == MOVE_SURGING_STRIKES || (move == MOVE_WATER_SHURIKEN && gBattleMons[battlerAtk].species == SPECIES_GRENINJA_ASH))
dmg *= 3;
RestoreBattlerData(battlerAtk);
RestoreBattlerData(battlerDef);
@ -964,48 +986,43 @@ u8 AI_GetMoveEffectiveness(u16 move, u8 battlerAtk, u8 battlerDef)
return damageVar;
}
// AI_CHECK_FASTER: is user(ai) faster
// AI_CHECK_SLOWER: is target faster
bool32 IsAiFaster(u8 battler)
/* Checks to see if AI will move ahead of another battler
* Output:
* AI_IS_FASTER: is user(ai) faster
* AI_IS_SLOWER: is target faster
*/
u8 AI_WhoStrikesFirst(u8 battlerAI, u8 battler2)
{
u32 fasterAI = 0, fasterPlayer = 0, i;
s8 prioAI, prioPlayer;
s8 prioAI = 0;
s8 prioPlayer = 0;
// Check move priorities first.
prioAI = GetMovePriority(sBattler_AI, AI_THINKING_STRUCT->moveConsidered);
SaveBattlerData(gBattlerTarget);
SetBattlerData(gBattlerTarget);
prioAI = GetMovePriority(battlerAI, AI_THINKING_STRUCT->moveConsidered);
for (i = 0; i < MAX_MON_MOVES; i++)
{
if (gBattleMons[gBattlerTarget].moves[i] == 0 || gBattleMons[gBattlerTarget].moves[i] == 0xFFFF)
if (gBattleMons[battler2].moves[i] == 0 || gBattleMons[battler2].moves[i] == 0xFFFF)
continue;
prioPlayer = GetMovePriority(gBattlerTarget, gBattleMons[gBattlerTarget].moves[i]);
prioPlayer = GetMovePriority(battler2, gBattleMons[battler2].moves[i]);
if (prioAI > prioPlayer)
fasterAI++;
else if (prioPlayer > prioAI)
fasterPlayer++;
}
RestoreBattlerData(gBattlerTarget);
if (fasterAI > fasterPlayer)
{
if (battler == 0) // is user (ai) faster
return TRUE;
else
return FALSE;
return AI_IS_FASTER;
}
else if (fasterAI < fasterPlayer)
{
if (battler == 1) // is target (player) faster
return TRUE;
else
return FALSE;
return AI_IS_SLOWER;
}
else
{
// Priorities are the same(at least comparing to moves the AI is aware of), decide by speed.
if (GetWhoStrikesFirst(sBattler_AI, gBattlerTarget, TRUE) == battler)
if (GetWhoStrikesFirst(battlerAI, battler2, TRUE) == 0)
return TRUE;
else
return FALSE;
@ -1016,7 +1033,7 @@ bool32 IsAiFaster(u8 battler)
bool32 CanTargetFaintAi(u8 battlerDef, u8 battlerAtk)
{
s32 i, dmg;
u32 unusable = CheckMoveLimitations(battlerDef, 0, 0xFF & ~MOVE_LIMITATION_PP);
u32 unusable = CheckMoveLimitations(battlerDef, 0, 0xFF);
u16 *moves = gBattleResources->battleHistory->usedMoves[battlerDef];
for (i = 0; i < MAX_MON_MOVES; i++)
@ -1031,10 +1048,36 @@ bool32 CanTargetFaintAi(u8 battlerDef, u8 battlerAtk)
return FALSE;
}
// Check if AI mon has the means to faint the target with any of its moves.
// If numHits > 1, check if the target will be KO'ed by that number of hits (ignoring healing effects)
bool32 CanAIFaintTarget(u8 battlerAtk, u8 battlerDef, u8 numHits)
{
s32 i, dmg;
u32 moveLimitations = CheckMoveLimitations(battlerAtk, 0, 0xFF);
u16 *moves = gBattleMons[battlerAtk].moves;
for (i = 0; i < MAX_MON_MOVES; i++)
{
if (moves[i] != MOVE_NONE && moves[i] != 0xFFFF && !(moveLimitations & gBitTable[i]))
{
// Use the pre-calculated value in simulatedDmg instead of re-calculating it
dmg = AI_THINKING_STRUCT->simulatedDmg[battlerAtk][battlerDef][i];
if (numHits)
dmg *= numHits;
if (gBattleMons[battlerDef].hp <= dmg)
return TRUE;
}
}
return FALSE;
}
bool32 CanMoveFaintBattler(u16 move, u8 battlerDef, u8 battlerAtk, u8 nHits)
{
s32 i, dmg;
u32 unusable = CheckMoveLimitations(battlerDef, 0, 0xFF & ~MOVE_LIMITATION_PP);
u32 unusable = CheckMoveLimitations(battlerDef, 0, 0xFF);
if (move != MOVE_NONE && move != 0xFFFF && !(unusable & gBitTable[i]) && AI_CalcDamage(move, battlerDef, battlerAtk) >= gBattleMons[battlerAtk].hp)
return TRUE;
@ -1046,13 +1089,17 @@ bool32 CanMoveFaintBattler(u16 move, u8 battlerDef, u8 battlerAtk, u8 nHits)
bool32 CanTargetFaintAiWithMod(u8 battlerDef, u8 battlerAtk, s32 hpMod, s32 dmgMod)
{
u32 i;
u32 unusable = CheckMoveLimitations(battlerDef, 0, 0xFF & ~MOVE_LIMITATION_PP);
u32 unusable = CheckMoveLimitations(battlerDef, 0, 0xFF);
s32 dmg;
u16 *moves = gBattleResources->battleHistory->usedMoves[battlerDef];
u32 hpCheck = gBattleMons[battlerAtk].hp + hpMod;
if (hpCheck > gBattleMons[battlerAtk].maxHP)
hpCheck = gBattleMons[battlerAtk].maxHP;
for (i = 0; i < MAX_MON_MOVES; i++)
{
u32 dmg = AI_CalcDamage(moves[i], battlerDef, battlerAtk);
u32 hpCheck = gBattleMons[battlerAtk].hp + hpMod;
dmg = AI_THINKING_STRUCT->simulatedDmg[battlerAtk][battlerDef][i];
if (dmgMod)
dmg *= dmgMod;
@ -1065,34 +1112,48 @@ bool32 CanTargetFaintAiWithMod(u8 battlerDef, u8 battlerAtk, s32 hpMod, s32 dmgM
return FALSE;
}
bool32 AI_IsAbilityOnSide(u32 battlerId, u32 ability)
{
if (IsBattlerAlive(battlerId) && AI_GetAbility(battlerId) == ability)
return TRUE;
else if (IsBattlerAlive(BATTLE_PARTNER(battlerId)) && AI_GetAbility(BATTLE_PARTNER(battlerId)) == ability)
return TRUE;
else
return FALSE;
}
// does NOT include ability suppression checks
s32 AI_GetAbility(u32 battlerId)
{
u32 knownAbility = GetBattlerAbility(battlerId);
// The AI knows its own ability.
if (IsBattlerAIControlled(battlerId))
return gBattleMons[battlerId].ability;
return knownAbility;
// Check neutralizing gas, gastro acid
if (knownAbility == ABILITY_NONE)
return knownAbility;
if (BATTLE_HISTORY->abilities[battlerId] != ABILITY_NONE)
return BATTLE_HISTORY->abilities[battlerId];
// Abilities that prevent fleeing.
if (gBattleMons[battlerId].ability == ABILITY_SHADOW_TAG
|| gBattleMons[battlerId].ability == ABILITY_MAGNET_PULL
|| gBattleMons[battlerId].ability == ABILITY_ARENA_TRAP)
return gBattleMons[battlerId].ability;
// Abilities that prevent fleeing - treat as always known
if (knownAbility == ABILITY_SHADOW_TAG || knownAbility == ABILITY_MAGNET_PULL || knownAbility == ABILITY_ARENA_TRAP)
return knownAbility;
// Else, guess the ability
if (gBaseStats[gBattleMons[battlerId].species].abilities[0] != ABILITY_NONE)
{
if (gBaseStats[gBattleMons[battlerId].species].abilities[1] != ABILITY_NONE)
u16 abilityGuess = ABILITY_NONE;
while (abilityGuess == ABILITY_NONE)
{
// AI has no knowledge of opponent, so it guesses which ability.
return gBaseStats[gBattleMons[battlerId].species].abilities[Random() & 1];
}
else
{
return gBaseStats[gBattleMons[battlerId].species].abilities[0]; // It's definitely ability 1.
abilityGuess = gBaseStats[gBattleMons[battlerId].species].abilities[Random() % NUM_ABILITY_SLOTS];
}
return abilityGuess;
}
return ABILITY_NONE; // Unknown.
}
@ -1650,7 +1711,7 @@ u32 CountNegativeStatStages(u8 battlerId)
bool32 ShouldLowerAttack(u8 battlerAtk, u8 battlerDef, u16 defAbility)
{
if (IsAiFaster(AI_CHECK_FASTER) && CanAttackerFaintTarget(battlerAtk, battlerDef, AI_THINKING_STRUCT->movesetIndex, 0))
if (WillAIStrikeFirst() && (AI_THINKING_STRUCT->aiFlags & AI_FLAG_TRY_TO_FAINT) && CanAIFaintTarget(battlerAtk, battlerDef, 0))
return FALSE; // Don't bother lowering stats if can kill enemy.
if (gBattleMons[battlerDef].statStages[STAT_ATK] > 4
@ -1658,7 +1719,7 @@ bool32 ShouldLowerAttack(u8 battlerAtk, u8 battlerDef, u16 defAbility)
&& defAbility != ABILITY_CONTRARY
&& defAbility != ABILITY_CLEAR_BODY
&& defAbility != ABILITY_WHITE_SMOKE
//&& defAbility != ABILITY_FULL_METAL_BODY
&& defAbility != ABILITY_FULL_METAL_BODY
&& defAbility != ABILITY_HYPER_CUTTER)
return TRUE;
return FALSE;
@ -1666,7 +1727,7 @@ bool32 ShouldLowerAttack(u8 battlerAtk, u8 battlerDef, u16 defAbility)
bool32 ShouldLowerDefense(u8 battlerAtk, u8 battlerDef, u16 defAbility)
{
if (IsAiFaster(AI_CHECK_FASTER) && CanAttackerFaintTarget(battlerAtk, battlerDef, AI_THINKING_STRUCT->movesetIndex, 0))
if (WillAIStrikeFirst() && (AI_THINKING_STRUCT->aiFlags & AI_FLAG_TRY_TO_FAINT) && CanAIFaintTarget(battlerAtk, battlerDef, 0))
return FALSE; // Don't bother lowering stats if can kill enemy.
if (gBattleMons[battlerDef].statStages[STAT_DEF] > 4
@ -1674,7 +1735,7 @@ bool32 ShouldLowerDefense(u8 battlerAtk, u8 battlerDef, u16 defAbility)
&& defAbility != ABILITY_CONTRARY
&& defAbility != ABILITY_CLEAR_BODY
&& defAbility != ABILITY_WHITE_SMOKE
//&& defAbility != ABILITY_FULL_METAL_BODY
&& defAbility != ABILITY_FULL_METAL_BODY
&& defAbility != ABILITY_BIG_PECKS)
return TRUE;
return FALSE;
@ -1682,13 +1743,13 @@ bool32 ShouldLowerDefense(u8 battlerAtk, u8 battlerDef, u16 defAbility)
bool32 ShouldLowerSpeed(u8 battlerAtk, u8 battlerDef, u16 defAbility)
{
if (IsAiFaster(AI_CHECK_FASTER) && CanAttackerFaintTarget(battlerAtk, battlerDef, AI_THINKING_STRUCT->movesetIndex, 0))
if (WillAIStrikeFirst() && (AI_THINKING_STRUCT->aiFlags & AI_FLAG_TRY_TO_FAINT) && CanAIFaintTarget(battlerAtk, battlerDef, 0))
return FALSE; // Don't bother lowering stats if can kill enemy.
if (IsAiFaster(AI_CHECK_SLOWER)
if (!WillAIStrikeFirst()
&& defAbility != ABILITY_CONTRARY
&& defAbility != ABILITY_CLEAR_BODY
//&& defAbility != ABILITY_FULL_METAL_BODY
&& defAbility != ABILITY_FULL_METAL_BODY
&& defAbility != ABILITY_WHITE_SMOKE)
return TRUE;
return FALSE;
@ -1696,14 +1757,14 @@ bool32 ShouldLowerSpeed(u8 battlerAtk, u8 battlerDef, u16 defAbility)
bool32 ShouldLowerSpAtk(u8 battlerAtk, u8 battlerDef, u16 defAbility)
{
if (IsAiFaster(AI_CHECK_FASTER) && CanAttackerFaintTarget(battlerAtk, battlerDef, AI_THINKING_STRUCT->movesetIndex, 0))
if (WillAIStrikeFirst() && (AI_THINKING_STRUCT->aiFlags & AI_FLAG_TRY_TO_FAINT) && CanAIFaintTarget(battlerAtk, battlerDef, 0))
return FALSE; // Don't bother lowering stats if can kill enemy.
if (gBattleMons[battlerDef].statStages[STAT_SPATK] > 4
&& HasMoveWithSplit(battlerDef, SPLIT_SPECIAL)
&& defAbility != ABILITY_CONTRARY
&& defAbility != ABILITY_CLEAR_BODY
//&& defAbility != ABILITY_FULL_METAL_BODY
&& defAbility != ABILITY_FULL_METAL_BODY
&& defAbility != ABILITY_WHITE_SMOKE)
return TRUE;
return FALSE;
@ -1711,14 +1772,14 @@ bool32 ShouldLowerSpAtk(u8 battlerAtk, u8 battlerDef, u16 defAbility)
bool32 ShouldLowerSpDef(u8 battlerAtk, u8 battlerDef, u16 defAbility)
{
if (IsAiFaster(AI_CHECK_FASTER) && CanAttackerFaintTarget(battlerAtk, battlerDef, AI_THINKING_STRUCT->movesetIndex, 0))
if (WillAIStrikeFirst() && (AI_THINKING_STRUCT->aiFlags & AI_FLAG_TRY_TO_FAINT) && CanAIFaintTarget(battlerAtk, battlerDef, 0))
return FALSE; // Don't bother lowering stats if can kill enemy.
if (gBattleMons[battlerDef].statStages[STAT_SPDEF] > 4
&& HasMoveWithSplit(battlerAtk, SPLIT_SPECIAL)
&& defAbility != ABILITY_CONTRARY
&& defAbility != ABILITY_CLEAR_BODY
//&& defAbility != ABILITY_FULL_METAL_BODY
&& defAbility != ABILITY_FULL_METAL_BODY
&& defAbility != ABILITY_WHITE_SMOKE)
return TRUE;
return FALSE;
@ -1726,13 +1787,13 @@ bool32 ShouldLowerSpDef(u8 battlerAtk, u8 battlerDef, u16 defAbility)
bool32 ShouldLowerAccuracy(u8 battlerAtk, u8 battlerDef, u16 defAbility)
{
if (IsAiFaster(AI_CHECK_FASTER) && CanAttackerFaintTarget(battlerAtk, battlerDef, AI_THINKING_STRUCT->movesetIndex, 0))
if (WillAIStrikeFirst() && (AI_THINKING_STRUCT->aiFlags & AI_FLAG_TRY_TO_FAINT) && CanAIFaintTarget(battlerAtk, battlerDef, 0))
return FALSE; // Don't bother lowering stats if can kill enemy.
if (defAbility != ABILITY_CONTRARY
&& defAbility != ABILITY_CLEAR_BODY
&& defAbility != ABILITY_WHITE_SMOKE
//&& defAbility != ABILITY_FULL_METAL_BODY
&& defAbility != ABILITY_FULL_METAL_BODY
&& defAbility != ABILITY_KEEN_EYE)
return TRUE;
return FALSE;
@ -1740,19 +1801,19 @@ bool32 ShouldLowerAccuracy(u8 battlerAtk, u8 battlerDef, u16 defAbility)
bool32 ShouldLowerEvasion(u8 battlerAtk, u8 battlerDef, u16 defAbility)
{
if (IsAiFaster(AI_CHECK_FASTER) && CanAttackerFaintTarget(battlerAtk, battlerDef, AI_THINKING_STRUCT->movesetIndex, 0))
if (WillAIStrikeFirst() && (AI_THINKING_STRUCT->aiFlags & AI_FLAG_TRY_TO_FAINT) && CanAIFaintTarget(battlerAtk, battlerDef, 0))
return FALSE; // Don't bother lowering stats if can kill enemy.
if (gBattleMons[battlerDef].statStages[STAT_EVASION] > DEFAULT_STAT_STAGE
&& defAbility != ABILITY_CONTRARY
&& defAbility != ABILITY_CLEAR_BODY
//&& defAbility != ABILITY_FULL_METAL_BODY
&& defAbility != ABILITY_FULL_METAL_BODY
&& defAbility != ABILITY_WHITE_SMOKE)
return TRUE;
return FALSE;
}
bool32 CanAttackerFaintTarget(u8 battlerAtk, u8 battlerDef, u8 index, u8 numHits)
bool32 CanIndexMoveFaintTarget(u8 battlerAtk, u8 battlerDef, u8 index, u8 numHits)
{
s32 dmg = AI_THINKING_STRUCT->simulatedDmg[battlerAtk][battlerDef][index];
@ -2355,9 +2416,19 @@ static bool32 AnyUsefulStatIsRaised(u8 battler)
return FALSE;
}
struct Pokemon *GetPartyBattlerPartyData(u8 battlerId, u8 switchBattler)
{
struct Pokemon *mon;
if (GetBattlerSide(battlerId) == B_SIDE_PLAYER)
mon = &gPlayerParty[switchBattler];
else
mon = &gEnemyParty[switchBattler];
return mon;
}
static bool32 PartyBattlerShouldAvoidHazards(u8 currBattler, u8 switchBattler)
{
struct Pokemon *mon = GetBattlerPartyData(switchBattler);
struct Pokemon *mon = GetPartyBattlerPartyData(currBattler, switchBattler);
u16 ability = GetMonAbility(mon); // we know our own party data
u16 holdEffect = GetBattlerHoldEffect(GetMonData(mon, MON_DATA_HELD_ITEM), TRUE);
u32 flags = gSideStatuses[GetBattlerSide(currBattler)] & (SIDE_STATUS_SPIKES | SIDE_STATUS_STEALTH_ROCK | SIDE_STATUS_STICKY_WEB | SIDE_STATUS_TOXIC_SPIKES);
@ -2404,11 +2475,11 @@ bool32 ShouldPivot(u8 battlerAtk, u8 battlerDef, u16 defAbility, u16 move, u8 mo
/*if (IsPredictedToSwitch(battlerDef, battlerAtk) && !hasStatBoost)
return PIVOT; // Try pivoting so you can switch to a better matchup to counter your new opponent*/
if (GetWhoStrikesFirst(battlerAtk, battlerDef, TRUE) == 0) // Attacker goes first
if (AI_WhoStrikesFirst(battlerAtk, battlerDef) == AI_IS_FASTER) // Attacker goes first
{
if (!CanAttackerFaintTarget(battlerAtk, battlerDef, moveIndex, 0)) // Can't KO foe otherwise
if (!CanAIFaintTarget(battlerAtk, battlerDef, 0)) // Can't KO foe otherwise
{
if (CanAttackerFaintTarget(battlerAtk, battlerDef, moveIndex, 2))
if (CanAIFaintTarget(battlerAtk, battlerDef, 2))
{
// attacker can kill target in two hits (theoretically)
if (CanTargetFaintAi(battlerDef, battlerAtk))
@ -2473,7 +2544,7 @@ bool32 ShouldPivot(u8 battlerAtk, u8 battlerDef, u16 defAbility, u16 move, u8 mo
}
else if (CanTargetFaintAiWithMod(battlerDef, battlerAtk, 0, 2)) // Foe can 2HKO AI
{
if (CanAttackerFaintTarget(battlerAtk, battlerDef, moveIndex, 0))
if (CanAIFaintTarget(battlerAtk, battlerDef, 0))
{
if (!BattlerWillFaintFromSecondaryDamage(battlerAtk, AI_DATA->atkAbility))
return CAN_TRY_PIVOT; // Use this move to KO if you must
@ -2485,7 +2556,7 @@ bool32 ShouldPivot(u8 battlerAtk, u8 battlerDef, u16 defAbility, u16 move, u8 mo
}
else // Foe can 3HKO+ AI
{
if (CanAttackerFaintTarget(battlerAtk, battlerDef, moveIndex, 0))
if (CanAIFaintTarget(battlerAtk, battlerDef, 0))
{
if (!BattlerWillFaintFromSecondaryDamage(battlerAtk, AI_DATA->atkAbility) // This is the only move that can KO
&& !hasStatBoost) //You're not wasting a valuable stat boost
@ -2493,7 +2564,7 @@ bool32 ShouldPivot(u8 battlerAtk, u8 battlerDef, u16 defAbility, u16 move, u8 mo
return CAN_TRY_PIVOT;
}
}
else if (CanAttackerFaintTarget(battlerAtk, battlerDef, moveIndex, 2))
else if (CanAIFaintTarget(battlerAtk, battlerDef, 2))
{
// can knock out foe in 2 hits
if (IS_MOVE_STATUS(move) && (shouldSwitch //Damaging move
@ -2606,27 +2677,38 @@ bool32 AI_CanSleep(u8 battler, u16 ability)
bool32 AI_CanPutToSleep(u8 battlerAtk, u8 battlerDef, u16 defAbility, u16 move, u16 partnerMove)
{
if (!AI_CanSleep(battlerDef, defAbility)
|| AI_GetMoveEffectiveness(move, battlerAtk, battlerDef) == AI_EFFECTIVENESS_x0
|| DoesSubstituteBlockMove(battlerAtk, battlerDef, move)
|| PartnerMoveEffectIsStatusSameTarget(BATTLE_PARTNER(battlerAtk), battlerDef, partnerMove)) // shouldn't try to sleep mon that partner is trying to make sleep
return FALSE;
return TRUE;
}
bool32 AI_CanBePoisoned(u8 battler, u16 ability)
static bool32 AI_CanPoisonType(u8 battlerAttacker, u8 battlerTarget)
{
if (ability == ABILITY_IMMUNITY
|| IsAbilityOnSide(battler, ABILITY_PASTEL_VEIL)
|| gBattleMons[battler].status1 & STATUS1_ANY
|| IsAbilityStatusProtected(battler)
|| gSideStatuses[GetBattlerSide(battler)] & SIDE_STATUS_SAFEGUARD)
return ((AI_GetAbility(battlerAttacker) == ABILITY_CORROSION && gBattleMoves[gCurrentMove].split == SPLIT_STATUS)
|| !(IS_BATTLER_OF_TYPE(battlerTarget, TYPE_POISON) || IS_BATTLER_OF_TYPE(battlerTarget, TYPE_STEEL)));
}
static bool32 AI_CanBePoisoned(u8 battlerAtk, u8 battlerDef)
{
u16 ability = AI_GetAbility(battlerDef);
if (!(AI_CanPoisonType(battlerAtk, battlerDef))
|| gSideStatuses[GetBattlerSide(battlerDef)] & SIDE_STATUS_SAFEGUARD
|| gBattleMons[battlerDef].status1 & STATUS1_ANY
|| ability == ABILITY_IMMUNITY
|| ability == ABILITY_COMATOSE
|| AI_IsAbilityOnSide(battlerDef, ABILITY_PASTEL_VEIL)
|| gBattleMons[battlerDef].status1 & STATUS1_ANY
|| IsAbilityStatusProtected(battlerDef)
|| AI_IsTerrainAffected(battlerDef, STATUS_FIELD_MISTY_TERRAIN))
return FALSE;
return TRUE;
}
bool32 ShouldPoisonSelf(u8 battler, u16 ability)
{
if (AI_CanBePoisoned(battler, ability) && (
if (AI_CanBePoisoned(battler, battler) && (
ability == ABILITY_MARVEL_SCALE
|| ability == ABILITY_POISON_HEAL
|| ability == ABILITY_QUICK_FEET
@ -2641,7 +2723,7 @@ bool32 ShouldPoisonSelf(u8 battler, u16 ability)
bool32 AI_CanPoison(u8 battlerAtk, u8 battlerDef, u16 defAbility, u16 move, u16 partnerMove)
{
if (!AI_CanBePoisoned(battlerDef, defAbility)
if (!AI_CanBePoisoned(battlerAtk, battlerDef)
|| AI_GetMoveEffectiveness(move, battlerAtk, battlerDef) == AI_EFFECTIVENESS_x0
|| DoesSubstituteBlockMove(battlerAtk, battlerDef, move)
|| PartnerMoveEffectIsStatusSameTarget(BATTLE_PARTNER(battlerAtk), battlerDef, partnerMove))
@ -2654,7 +2736,7 @@ bool32 AI_CanPoison(u8 battlerAtk, u8 battlerDef, u16 defAbility, u16 move, u16
return TRUE;
}
static bool32 CanBeParayzed(u8 battler, u16 ability)
static bool32 AI_CanBeParalyzed(u8 battler, u16 ability)
{
if (ability == ABILITY_LIMBER
|| IS_BATTLER_OF_TYPE(battler, TYPE_ELECTRIC)
@ -2666,7 +2748,7 @@ static bool32 CanBeParayzed(u8 battler, u16 ability)
bool32 AI_CanParalyze(u8 battlerAtk, u8 battlerDef, u16 defAbility, u16 move, u16 partnerMove)
{
if (!CanBeParayzed(battlerDef, defAbility)
if (!AI_CanBeParalyzed(battlerDef, defAbility)
|| AI_GetMoveEffectiveness(move, battlerAtk, battlerDef) == AI_EFFECTIVENESS_x0
|| gSideStatuses[GetBattlerSide(battlerDef)] & SIDE_STATUS_SAFEGUARD
|| DoesSubstituteBlockMove(battlerAtk, battlerDef, move)
@ -2744,7 +2826,7 @@ bool32 AI_CanBeInfatuated(u8 battlerAtk, u8 battlerDef, u16 defAbility, u8 atkGe
|| atkGender == defGender
|| atkGender == MON_GENDERLESS
|| defGender == MON_GENDERLESS
|| IsAbilityOnSide(battlerDef, ABILITY_AROMA_VEIL))
|| AI_IsAbilityOnSide(battlerDef, ABILITY_AROMA_VEIL))
return FALSE;
return TRUE;
}
@ -2753,7 +2835,7 @@ u32 ShouldTryToFlinch(u8 battlerAtk, u8 battlerDef, u16 atkAbility, u16 defAbili
{
if (defAbility == ABILITY_INNER_FOCUS
|| DoesSubstituteBlockMove(battlerAtk, battlerDef, move)
|| GetWhoStrikesFirst(battlerAtk, battlerDef, TRUE) == 1) // opponent goes first
|| AI_WhoStrikesFirst(battlerAtk, battlerDef) == AI_IS_SLOWER) // Opponent goes first
{
return 0; // don't try to flinch
}
@ -2866,7 +2948,7 @@ bool32 ShouldUseRecoilMove(u8 battlerAtk, u8 battlerDef, u32 recoilDmg, u8 moveI
if (recoilDmg >= gBattleMons[battlerAtk].hp //Recoil kills attacker
&& CountUsablePartyMons(battlerDef) != 0) //Foe has more than 1 target left
{
if (recoilDmg >= gBattleMons[battlerDef].hp && !CanAttackerFaintTarget(battlerAtk, battlerDef, moveIndex, 0))
if (recoilDmg >= gBattleMons[battlerDef].hp && !CanAIFaintTarget(battlerAtk, battlerDef, 0))
return TRUE; //If it's the only KO move then just use it
else
return FALSE; //Not as good to use move if you'll faint and not win
@ -2877,7 +2959,7 @@ bool32 ShouldUseRecoilMove(u8 battlerAtk, u8 battlerDef, u32 recoilDmg, u8 moveI
bool32 ShouldAbsorb(u8 battlerAtk, u8 battlerDef, u16 move, s32 damage)
{
if (move == 0xFFFF || GetWhoStrikesFirst(battlerAtk, gBattlerTarget, TRUE) == 0)
if (move == 0xFFFF || AI_WhoStrikesFirst(battlerAtk, battlerDef) == AI_IS_FASTER)
{
// using item or user goes first
u8 healPercent = (gBattleMoves[move].argument == 0) ? 50 : gBattleMoves[move].argument;
@ -2904,7 +2986,7 @@ bool32 ShouldAbsorb(u8 battlerAtk, u8 battlerDef, u16 move, s32 damage)
bool32 ShouldRecover(u8 battlerAtk, u8 battlerDef, u16 move, u8 healPercent)
{
if (move == 0xFFFF || GetWhoStrikesFirst(battlerAtk, gBattlerTarget, TRUE) == 0)
if (move == 0xFFFF || AI_WhoStrikesFirst(battlerAtk, battlerDef) == AI_IS_FASTER)
{
// using item or user going first
s32 damage = AI_THINKING_STRUCT->simulatedDmg[battlerAtk][battlerDef][AI_THINKING_STRUCT->movesetIndex];
@ -3304,6 +3386,47 @@ static const u16 sRecycleEncouragedItems[] =
// TODO expand this
};
// Its assumed that the berry is strategically given, so no need to check benefits of the berry
bool32 IsStatBoostingBerry(u16 item)
{
switch (item)
{
case ITEM_LIECHI_BERRY:
case ITEM_GANLON_BERRY:
case ITEM_SALAC_BERRY:
case ITEM_PETAYA_BERRY:
case ITEM_APICOT_BERRY:
//case ITEM_LANSAT_BERRY:
case ITEM_STARF_BERRY:
#ifdef ITEM_EXPANSION
case ITEM_MICLE_BERRY:
#endif
return TRUE;
default:
return FALSE;
}
}
bool32 ShouldRestoreHpBerry(u8 battlerAtk, u16 item)
{
switch (item)
{
case ITEM_ORAN_BERRY:
if (gBattleMons[battlerAtk].maxHP <= 50)
return TRUE; // Only worth it in the early game
return FALSE;
case ITEM_SITRUS_BERRY:
case ITEM_FIGY_BERRY:
case ITEM_WIKI_BERRY:
case ITEM_MAGO_BERRY:
case ITEM_AGUAV_BERRY:
case ITEM_IAPAPA_BERRY:
return TRUE;
default:
return FALSE;
}
}
bool32 IsRecycleEncouragedItem(u16 item)
{
u32 i;
@ -3325,6 +3448,9 @@ void IncreaseStatUpScore(u8 battlerAtk, u8 battlerDef, u8 statId, s16 *score)
if (GetHealthPercentage(battlerAtk) < 80 && AI_RandLessThan(128))
return;
if ((AI_THINKING_STRUCT->aiFlags & AI_FLAG_TRY_TO_FAINT) && CanAIFaintTarget(battlerAtk, battlerDef, 0))
return; // Damaging moves would get a score boost from AI_TryToFaint or PreferStrongestMove so we don't consider them here
switch (statId)
{
@ -3350,7 +3476,7 @@ void IncreaseStatUpScore(u8 battlerAtk, u8 battlerDef, u8 statId, s16 *score)
}
break;
case STAT_SPEED:
if (IsAiFaster(AI_CHECK_SLOWER))
if (!WillAIStrikeFirst())
{
if (gBattleMons[battlerAtk].statStages[STAT_SPEED] < STAT_UP_2_STAGE)
*score += 2;
@ -3397,6 +3523,9 @@ void IncreaseStatUpScore(u8 battlerAtk, u8 battlerDef, u8 statId, s16 *score)
void IncreasePoisonScore(u8 battlerAtk, u8 battlerDef, u16 move, s16 *score)
{
if ((AI_THINKING_STRUCT->aiFlags & AI_FLAG_TRY_TO_FAINT) && CanAIFaintTarget(battlerAtk, battlerDef, 0))
return;
if (AI_CanPoison(battlerAtk, battlerDef, AI_DATA->defAbility, move, AI_DATA->partnerMove) && GetHealthPercentage(battlerDef) > 20)
{
if (!HasDamagingMove(battlerDef))
@ -3417,6 +3546,9 @@ void IncreasePoisonScore(u8 battlerAtk, u8 battlerDef, u16 move, s16 *score)
void IncreaseBurnScore(u8 battlerAtk, u8 battlerDef, u16 move, s16 *score)
{
if ((AI_THINKING_STRUCT->aiFlags & AI_FLAG_TRY_TO_FAINT) && CanAIFaintTarget(battlerAtk, battlerDef, 0))
return;
if (AI_CanBurn(battlerAtk, battlerDef, AI_DATA->defAbility, AI_DATA->battlerAtkPartner, move, AI_DATA->partnerMove))
{
(*score)++; // burning is good
@ -3433,6 +3565,9 @@ void IncreaseBurnScore(u8 battlerAtk, u8 battlerDef, u16 move, s16 *score)
void IncreaseParalyzeScore(u8 battlerAtk, u8 battlerDef, u16 move, s16 *score)
{
if ((AI_THINKING_STRUCT->aiFlags & AI_FLAG_TRY_TO_FAINT) && CanAIFaintTarget(battlerAtk, battlerDef, 0))
return;
if (AI_CanParalyze(battlerAtk, battlerDef, AI_DATA->defAbility, move, AI_DATA->partnerMove))
{
u8 atkSpeed = GetBattlerTotalSpeedStat(battlerAtk);
@ -3451,6 +3586,9 @@ void IncreaseParalyzeScore(u8 battlerAtk, u8 battlerDef, u16 move, s16 *score)
void IncreaseSleepScore(u8 battlerAtk, u8 battlerDef, u16 move, s16 *score)
{
if ((AI_THINKING_STRUCT->aiFlags & AI_FLAG_TRY_TO_FAINT) && CanAIFaintTarget(battlerAtk, battlerDef, 0))
return;
if (AI_CanPutToSleep(battlerAtk, battlerDef, AI_DATA->defAbility, move, AI_DATA->partnerMove))
*score += 2;
else
@ -3466,6 +3604,9 @@ void IncreaseSleepScore(u8 battlerAtk, u8 battlerDef, u16 move, s16 *score)
void IncreaseConfusionScore(u8 battlerAtk, u8 battlerDef, u16 move, s16 *score)
{
if ((AI_THINKING_STRUCT->aiFlags & AI_FLAG_TRY_TO_FAINT) && CanAIFaintTarget(battlerAtk, battlerDef, 0))
return;
if (AI_CanConfuse(battlerAtk, battlerDef, AI_DATA->defAbility, AI_DATA->battlerAtkPartner, move, AI_DATA->partnerMove)
&& AI_DATA->defHoldEffect != HOLD_EFFECT_CURE_CONFUSION
&& AI_DATA->defHoldEffect != HOLD_EFFECT_CURE_STATUS)
@ -3478,3 +3619,12 @@ void IncreaseConfusionScore(u8 battlerAtk, u8 battlerDef, u16 move, s16 *score)
*score += 2;
}
}
bool32 AI_MoveMakesContact(u32 ability, u32 holdEffect, u16 move)
{
if (TestMoveFlags(move, FLAG_MAKES_CONTACT)
&& ability != ABILITY_LONG_REACH
&& holdEffect != HOLD_EFFECT_PROTECTIVE_PADS)
return TRUE;
return FALSE;
}

View File

@ -2052,14 +2052,14 @@ const struct BattleAnimBackground gBattleAnimBackgroundTable[] =
[BG_SOLARBEAM_CONTESTS] = {gBattleAnimBgImage_Impact, gBattleAnimBgPalette_Solarbeam, gBattleAnimBgTilemap_ImpactContests},
//new bgs
[BG_MAGMA_STORM] = {gBattleAnimBgImage_InAir, gBattleAnimBgPalette_MagmaStorm, gBattleAnimBgTilemap_InAir},
[BG_GIGA_IMPACT_OPPONENT] = {gBattleAnimBgImage_Impact, gBattleAnimBgPalette_GigaImpact, gBattleAnimBgTilemap_ImpactOpponent},
[BG_GIGA_IMPACT_PLAYER] = {gBattleAnimBgImage_Impact, gBattleAnimBgPalette_GigaImpact, gBattleAnimBgTilemap_ImpactPlayer},
[BG_GIGA_IMPACT_CONTEST] = {gBattleAnimBgImage_Impact, gBattleAnimBgPalette_GigaImpact, gBattleAnimBgTilemap_ImpactContests},
[BG_GIGA_IMPACT_OPPONENT] = {gBattleAnimBgImage_GigaImpact, gBattleAnimBgPalette_GigaImpact, gBattleAnimBgTilemap_GigaImpactOpponent},
[BG_GIGA_IMPACT_PLAYER] = {gBattleAnimBgImage_GigaImpact, gBattleAnimBgPalette_GigaImpact, gBattleAnimBgTilemap_GigaImpactPlayer},
[BG_GIGA_IMPACT_CONTEST] = {gBattleAnimBgImage_GigaImpact, gBattleAnimBgPalette_GigaImpact, gBattleAnimBgTilemap_GigaImpactContest},
[BG_TRICK_ROOM] = {gBattleAnimBgImage_TrickRoom, gBattleAnimBgPalette_TrickRoom, gBattleAnimBgTilemap_TrickRoom},
[BG_ROCK_WRECKER] = {gBattleAnimBgImage_Hurricane, gBattleAnimBgPalette_RockWrecker, gBattleAnimBgTilemap_Hurricane},
[BG_SPACIAL_REND_ON_OPPONENT] = {gBattleAnimBgImage_SpacialRend, gBattleAnimBgPalette_SpacialRend, gBattleAnimBgTilemap_SpacialRendOpponent},
[BG_SPACIAL_REND_ON_PLAYER] = {gBattleAnimBgImage_SpacialRend, gBattleAnimBgPalette_SpacialRend, gBattleAnimBgTilemap_SpacialRendPlayer},
[BG_DARK_VOID] = {gBattleAnimBgImage_DarkVoid, gBattleAnimBgPalette_DarkVoid, gBattleAnimBgTilemap_DarkVoid},
[BG_SPACIAL_REND_ON_OPPONENT] = {gBattleAnimBgImage_SpacialRend, gBattleAnimBgPalette_SpacialRend, gBattleAnimBgTilemap_GigaImpactOpponent},
[BG_SPACIAL_REND_ON_PLAYER] = {gBattleAnimBgImage_SpacialRend, gBattleAnimBgPalette_SpacialRend, gBattleAnimBgTilemap_GigaImpactPlayer},
[BG_DARK_VOID] = {gBattleAnimBgImage_Waterfall, gBattleAnimBgPalette_DarkVoid, gBattleAnimBgTilemap_DarkVoid},
[BG_WATER] = {gBattleAnimBgImage_HydroPump, gBattleAnimBgPalette_HydroPump, gBattleAnimBgTilemap_HydroPump},
[BG_NIGHTMARE] = {gBattleAnimBgImage_Nightmare, gBattleAnimBgPalette_Nightmare, gBattleAnimBgTilemap_Nightmare},
[BG_LEAF_STORM] = {gBattleAnimBgImage_LeafStorm, gBattleAnimBgPalette_LeafStorm, gBattleAnimBgTilemap_LeafStorm},

View File

@ -5064,3 +5064,34 @@ void AnimTask_PrimalReversion(u8 taskId)
gBattleAnimArgs[0] = 0;
DestroyAnimVisualTask(taskId);
}
void AnimTask_ShellSideArm(u8 taskId)
{
if (gSwapDamageCategory)
gBattleAnimArgs[0] = TRUE;
else
gBattleAnimArgs[0] = FALSE;
DestroyAnimVisualTask(taskId);
}
void AnimTask_TerrainPulse(u8 taskId)
{
if (IsBattlerTerrainAffected(gBattleAnimAttacker, STATUS_FIELD_TERRAIN_ANY))
{
if (gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN)
gBattleAnimArgs[0] = TYPE_ELECTRIC;
else if (gFieldStatuses & STATUS_FIELD_GRASSY_TERRAIN)
gBattleAnimArgs[0] = TYPE_GRASS;
else if (gFieldStatuses & STATUS_FIELD_MISTY_TERRAIN)
gBattleAnimArgs[0] = TYPE_FAIRY;
else if (gFieldStatuses & STATUS_FIELD_PSYCHIC_TERRAIN)
gBattleAnimArgs[0] = TYPE_PSYCHIC;
else //failsafe
gBattleAnimArgs[0] = 0;
}
else
{
gBattleAnimArgs[0] = 0;
}
DestroyAnimVisualTask(taskId);
}

View File

@ -2496,6 +2496,8 @@ void AnimTask_GetTrappedMoveAnimId(u8 taskId)
gBattleAnimArgs[0] = TRAP_ANIM_CLAMP;
else if (gBattleSpritesDataPtr->animationData->animArg == MOVE_SAND_TOMB)
gBattleAnimArgs[0] = TRAP_ANIM_SAND_TOMB;
else if (gBattleSpritesDataPtr->animationData->animArg == MOVE_MAGMA_STORM)
gBattleAnimArgs[0] = TRAP_ANIM_MAGMA_STORM;
else if (gBattleSpritesDataPtr->animationData->animArg == MOVE_INFESTATION)
gBattleAnimArgs[0] = TRAP_ANIM_INFESTATION;
else

View File

@ -136,6 +136,7 @@ void AnimTask_SetCamouflageBlend(u8 taskId)
gBattleAnimArgs[4] = RGB(31, 31, 31);
break;
case BATTLE_TERRAIN_PLAIN:
default:
gBattleAnimArgs[4] = RGB(31, 31, 31);
break;
}
@ -904,6 +905,12 @@ void AnimTask_GetBattleTerrain(u8 taskId)
DestroyAnimVisualTask(taskId);
}
void AnimTask_GetFieldTerrain(u8 taskId)
{
gBattleAnimArgs[0] = gFieldStatuses & STATUS_FIELD_TERRAIN_ANY;
DestroyAnimVisualTask(taskId);
}
void AnimTask_AllocBackupPalBuffer(u8 taskId)
{
gMonSpritesGfxPtr->buffer = AllocZeroed(0x2000);

View File

@ -1545,7 +1545,7 @@ static void OpponentHandlePrintSelectionString(void)
static void OpponentHandleChooseAction(void)
{
AI_TrySwitchOrUseItem();
AI_TrySwitchOrUseItem(); // TODO consider move choice first
OpponentBufferExecCompleted();
}
@ -1565,12 +1565,12 @@ static void OpponentHandleChooseMove(void)
{
u8 chosenMoveId;
struct ChooseMoveStruct *moveInfo = (struct ChooseMoveStruct*)(&gBattleResources->bufferA[gActiveBattler][4]);
if (gBattleTypeFlags & (BATTLE_TYPE_TRAINER | BATTLE_TYPE_FIRST_BATTLE | BATTLE_TYPE_SAFARI | BATTLE_TYPE_ROAMER))
{
BattleAI_SetupAIData(0xF);
chosenMoveId = BattleAI_ChooseMoveOrAction();
switch (chosenMoveId)
{
case AI_CHOICE_WATCH:
@ -1594,15 +1594,18 @@ static void OpponentHandleChooseMove(void)
if (gAbsentBattlerFlags & gBitTable[gBattlerTarget])
gBattlerTarget = GetBattlerAtPosition(B_POSITION_PLAYER_RIGHT);
}
if (CanMegaEvolve(gActiveBattler)) // If opponent can mega evolve, do it.
// If opponent can mega evolve, do it.
if (CanMegaEvolve(gActiveBattler))
BtlController_EmitTwoReturnValues(1, 10, (chosenMoveId) | (RET_MEGA_EVOLUTION) | (gBattlerTarget << 8));
else
BtlController_EmitTwoReturnValues(1, 10, (chosenMoveId) | (gBattlerTarget << 8));
break;
}
OpponentBufferExecCompleted();
}
else
else // Wild pokemon - use random move
{
u16 move;
do

View File

@ -1539,6 +1539,7 @@ static void PlayerPartnerHandleChooseMove(void)
BtlController_EmitTwoReturnValues(1, 10, (chosenMoveId) | (RET_MEGA_EVOLUTION) | (gBattlerTarget << 8));
else
BtlController_EmitTwoReturnValues(1, 10, (chosenMoveId) | (gBattlerTarget << 8));
PlayerPartnerBufferExecCompleted();
}

View File

@ -1924,12 +1924,20 @@ static const u8 sText_HoldEffectPsychicPower[] = _("Psychic Power");
static const u8 sText_HoldEffectFirePower[] = _("Fire Power");
static const u8 sText_HoldEffectDragonPower[] = _("Dragon Power");
static const u8 sText_HoldEffectNormalPower[] = _("Normal Power");
static const u8 sText_HoldEffectUpGrade[] = _("Up Grade");
#ifdef ITEM_EXPANSION
static const u8 sText_HoldEffectUpgrade[] = _("Upgrade");
#else
static const u8 sText_HoldEffectUpgrade[] = _("Up Grade");
#endif
static const u8 sText_HoldEffectShellBell[] = _("Shell Bell");
static const u8 sText_HoldEffectLuckyPunch[] = _("Lucky Punch");
static const u8 sText_HoldEffectMetalPowder[] = _("Metal Powder");
static const u8 sText_HoldEffectThickClub[] = _("Thick Club");
static const u8 sText_HoldEffectStick[] = _("Stick");
#ifdef ITEM_EXPANSION
static const u8 sText_HoldEffectLeek[] = _("Leek");
#else
static const u8 sText_HoldEffectLeek[] = _("Stick");
#endif
static const u8 sText_HoldEffectChoiceScarf[] = _("Choice Scarf");
static const u8 sText_HoldEffectChoiceSpecs[] = _("Choice Specs");
static const u8 sText_HoldEffectDampRock[] = _("Damp Rock");
@ -2064,12 +2072,12 @@ static const u8 *const sHoldEffectNames[] =
[HOLD_EFFECT_FIRE_POWER] = sText_HoldEffectFirePower,
[HOLD_EFFECT_DRAGON_POWER] = sText_HoldEffectDragonPower,
[HOLD_EFFECT_NORMAL_POWER] = sText_HoldEffectNormalPower,
[HOLD_EFFECT_UP_GRADE] = sText_HoldEffectUpGrade,
[HOLD_EFFECT_UPGRADE] = sText_HoldEffectUpgrade,
[HOLD_EFFECT_SHELL_BELL] = sText_HoldEffectShellBell,
[HOLD_EFFECT_LUCKY_PUNCH] = sText_HoldEffectLuckyPunch,
[HOLD_EFFECT_METAL_POWDER] = sText_HoldEffectMetalPowder,
[HOLD_EFFECT_THICK_CLUB] = sText_HoldEffectThickClub,
[HOLD_EFFECT_STICK] = sText_HoldEffectStick,
[HOLD_EFFECT_LEEK] = sText_HoldEffectLeek,
[HOLD_EFFECT_CHOICE_SCARF] = sText_HoldEffectChoiceScarf,
[HOLD_EFFECT_CHOICE_SPECS] = sText_HoldEffectChoiceSpecs,
[HOLD_EFFECT_DAMP_ROCK] = sText_HoldEffectDampRock,

View File

@ -49,6 +49,7 @@
#include "trig.h"
#include "tv.h"
#include "util.h"
#include "wild_encounter.h"
#include "window.h"
#include "constants/abilities.h"
#include "constants/battle_config.h"
@ -103,6 +104,7 @@ static void RunTurnActionsFunctions(void);
static void SetActionsAndBattlersTurnOrder(void);
static void sub_803CDF8(void);
static bool8 AllAtActionConfirmed(void);
static void TryChangeTurnOrder(void);
static void CheckFocusPunch_ClearVarsBeforeTurnStarts(void);
static void CheckMegaEvolutionBeforeTurn(void);
static void CheckQuickClaw_CustapBerryActivation(void);
@ -232,6 +234,7 @@ EWRAM_DATA struct TotemBoost gTotemBoosts[MAX_BATTLERS_COUNT] = {0};
EWRAM_DATA bool8 gHasFetchedBall = FALSE;
EWRAM_DATA u8 gLastUsedBall = 0;
EWRAM_DATA u16 gLastThrownBall = 0;
EWRAM_DATA bool8 gSwapDamageCategory = FALSE; // Photon Geyser, Shell Side Arm, Light That Burns the Sky
// IWRAM common vars
void (*gPreBattleCallback1)(void);
@ -2941,6 +2944,8 @@ static void BattleStartClearSetData(void)
gBattleStruct->usedHeldItems[i][1] = 0;
gBattleStruct->itemStolen[i].originalItem = GetMonData(&gPlayerParty[i], MON_DATA_HELD_ITEM);
}
gSwapDamageCategory = FALSE; // Photon Geyser, Shell Side Arm, Light That Burns the Sky
}
void SwitchInClearSetData(void)
@ -3544,7 +3549,11 @@ static void TryDoEventsBeforeFirstTurn(void)
return;
}
}
// Check neutralizing gas
if (AbilityBattleEffects(ABILITYEFFECT_NEUTRALIZINGGAS, 0, 0, 0, 0) != 0)
return;
// Check all switch in abilities happening from the fastest mon to slowest.
while (gBattleStruct->switchInAbilitiesCounter < gBattlersCount)
{
@ -3883,7 +3892,7 @@ static void HandleTurnActionSelectionState(void)
gBattleMons[gActiveBattler].ppBonuses,
i);
}
BtlController_EmitChooseMove(0, (gBattleTypeFlags & BATTLE_TYPE_DOUBLE) != 0, FALSE, &moveInfo);
MarkBattlerForControllerExec(gActiveBattler);
}
@ -4680,10 +4689,37 @@ static void CheckMegaEvolutionBeforeTurn(void)
}
}
#if B_MEGA_EVO_TURN_ORDER <= GEN_6
gBattleMainFunc = CheckFocusPunch_ClearVarsBeforeTurnStarts;
gBattleStruct->focusPunchBattlerId = 0;
#else
gBattleMainFunc = TryChangeTurnOrder; // This will just do nothing if no mon has mega evolved
#endif
}
// In gen7, priority and speed are recalculated during the turn in which a pokemon mega evolves
static void TryChangeTurnOrder(void)
{
s32 i, j;
for (i = 0; i < gBattlersCount - 1; i++)
{
for (j = i + 1; j < gBattlersCount; j++)
{
u8 battler1 = gBattlerByTurnOrder[i];
u8 battler2 = gBattlerByTurnOrder[j];
if (gActionsByTurnOrder[i] == B_ACTION_USE_MOVE
&& gActionsByTurnOrder[j] == B_ACTION_USE_MOVE)
{
if (GetWhoStrikesFirst(battler1, battler2, FALSE))
SwapTurnOrder(i, j);
}
}
}
gBattleMainFunc = CheckFocusPunch_ClearVarsBeforeTurnStarts;
gBattleStruct->focusPunchBattlerId = 0;
}
static void CheckFocusPunch_ClearVarsBeforeTurnStarts(void)
{
u32 i;
@ -5018,6 +5054,8 @@ static void FreeResetData_ReturnToOvOrDoEvolutions(void)
{
if (!gPaletteFade.active)
{
gIsFishingEncounter = FALSE;
gIsSurfingEncounter = FALSE;
ResetSpriteData();
if (gLeveledUpInBattle && (gBattleOutcome == B_OUTCOME_WON || gBattleOutcome == B_OUTCOME_CAUGHT))
{
@ -5189,6 +5227,22 @@ void SetTypeBeforeUsingMove(u16 move, u8 battlerAtk)
if (ItemId_GetPocket(gBattleMons[battlerAtk].item) == POCKET_BERRIES)
gBattleStruct->dynamicMoveType = gNaturalGiftTable[ITEM_TO_BERRY(gBattleMons[battlerAtk].item)].type;
}
else if (gBattleMoves[move].effect == EFFECT_TERRAIN_PULSE)
{
if (IsBattlerTerrainAffected(battlerAtk, STATUS_FIELD_TERRAIN_ANY))
{
if (gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN)
gBattleStruct->dynamicMoveType = TYPE_ELECTRIC | 0x80;
else if (gFieldStatuses & STATUS_FIELD_GRASSY_TERRAIN)
gBattleStruct->dynamicMoveType = TYPE_GRASS | 0x80;
else if (gFieldStatuses & STATUS_FIELD_MISTY_TERRAIN)
gBattleStruct->dynamicMoveType = TYPE_FAIRY | 0x80;
else if (gFieldStatuses & STATUS_FIELD_PSYCHIC_TERRAIN)
gBattleStruct->dynamicMoveType = TYPE_PSYCHIC | 0x80;
else //failsafe
gBattleStruct->dynamicMoveType = TYPE_NORMAL | 0x80;
}
}
attackerAbility = GetBattlerAbility(battlerAtk);
GET_MOVE_TYPE(move, moveType);
@ -5229,6 +5283,10 @@ void SetTypeBeforeUsingMove(u16 move, u8 battlerAtk)
{
gBattleStruct->dynamicMoveType = 0x80 | TYPE_ELECTRIC;
}
else if (move == MOVE_AURA_WHEEL && gBattleMons[battlerAtk].species == SPECIES_MORPEKO_HANGRY)
{
gBattleStruct->dynamicMoveType = 0x80 | TYPE_DARK;
}
// Check if a gem should activate.
GET_MOVE_TYPE(move, moveType);

View File

@ -549,7 +549,7 @@ static const u8 sText_BecameNimble[] =_("{B_ATK_NAME_WITH_PREFIX} became nimble!
static const u8 sText_HurledIntoTheAir[] =_("{B_DEF_NAME_WITH_PREFIX} was hurled\ninto the air!");
static const u8 sText_HeldItemsLoseEffects[] =_("It created a bizarre area in which\nPokémon's held items lose their effects!");
static const u8 sText_FellStraightDown[] =_("{B_DEF_NAME_WITH_PREFIX} fell\nstraight down!");
static const u8 sText_TransformedIntoWaterType[] =_("{B_DEF_NAME_WITH_PREFIX} transformed\ninto the water type!");
static const u8 sText_TargetChangedType[] =_("{B_DEF_NAME_WITH_PREFIX} transformed\ninto the {B_BUFF1} type!");
static const u8 sText_PkmnAcquiredSimple[] =_("{B_DEF_NAME_WITH_PREFIX} acquired\nSimple!");
static const u8 sText_KindOffer[] =_("{B_DEF_NAME_WITH_PREFIX}\ntook the kind offer!");
static const u8 sText_ResetsTargetsStatLevels[] =_("{B_DEF_NAME_WITH_PREFIX}'s stat changes\nwere removed!");
@ -629,7 +629,7 @@ static const u8 sText_TerrainBecomesGrassy[] = _("Grass grew to cover\nthe battl
static const u8 sText_TerrainBecomesElectric[] = _("An electric current runs across\nthe battlefield!");
static const u8 sText_TerrainBecomesPsychic[] = _("The battlefield got weird!");
static const u8 sText_TargetElectrified[] = _("The {B_DEF_NAME_WITH_PREFIX}'s moves\nhave been electrified!");
static const u8 sText_AssaultVestDoesntAllow[] = _("The effects of the {B_LAST_ITEM} prevent status\nmoves from being used!\p");
static const u8 sText_AssaultVestDoesntAllow[] = _("{B_LAST_ITEM}'s effects prevent\nstatus moves from being used!\p");
static const u8 sText_GravityPreventsUsage[] = _("{B_ATK_NAME_WITH_PREFIX} can't use {B_CURRENT_MOVE}\nbecause of gravity!\p");
static const u8 sText_HealBlockPreventsUsage[] = _("{B_ATK_NAME_WITH_PREFIX} was\nprevented from healing!\p");
static const u8 sText_MegaEvoReacting[] = _("{B_ATK_NAME_WITH_PREFIX}'s {B_LAST_ITEM} is \nreacting to {B_ATK_TRAINER_NAME}'s Mega Ring!");
@ -727,9 +727,20 @@ static const u8 sText_AbilityAllowsOnlyMove[] = _("{B_ATK_ABILITY} allows the\nu
static const u8 sText_SwappedAbilities[] = _("{B_DEF_NAME_WITH_PREFIX} swapped Abilities\nwith its target!");
static const u8 sText_PastelVeilProtected[] = _("{B_DEF_NAME_WITH_PREFIX} is protected\nby a pastel veil!");
static const u8 sText_PastelVeilEnters[] = _("{B_DEF_NAME_WITH_PREFIX} was cured\nof its poisoning!");
static const u8 sText_BattlerTypeChangedTo[] = _("{B_BUFF1}'s type\nchanged to {B_BUFF2}!");
static const u8 sText_BothCanNoLongerEscape[] = _("Neither POKéMON can run away!");
static const u8 sText_CantEscapeDueToUsedMove[] = _("{B_ATK_NAME_WITH_PREFIX} can no longer escape\nbecause it used {B_CURRENT_MOVE}!");
static const u8 sText_PkmnBecameWeakerToFire[] = _("{B_DEF_NAME_WITH_PREFIX} became\nweaker to fire!");
static const u8 sText_PkmnAboutToBeAttackedByItsItem[] = _("{B_DEF_NAME_WITH_PREFIX} is about\nto be attacked by its {B_BUFF1}!");
static const u8 sText_CantEscapeBecauseOfCurrentMove[] = _("{B_DEF_NAME_WITH_PREFIX} can no longer escape\nbecause of {B_CURRENT_MOVE}!");
static const u8 sText_NeutralizingGasEnters[] = _("Neutralizing Gas filled the area!");
static const u8 sText_NeutralizingGasOver[] = _("The effects of Neutralizing\nGas wore off!");
const u8 *const gBattleStringsTable[BATTLESTRINGS_COUNT] =
{
[STRINGID_NEUTRALIZINGGASOVER - 12] = sText_NeutralizingGasOver,
[STRINGID_NEUTRALIZINGGASENTERS - 12] = sText_NeutralizingGasEnters,
[STRINGID_BATTLERTYPECHANGEDTO - 12] = sText_BattlerTypeChangedTo,
[STRINGID_PASTELVEILENTERS - 12] = sText_PastelVeilEnters,
[STRINGID_PASTELVEILPROTECTED -12] = sText_PastelVeilProtected,
[STRINGID_SWAPPEDABILITIES - 12] = sText_SwappedAbilities,
@ -1198,7 +1209,7 @@ const u8 *const gBattleStringsTable[BATTLESTRINGS_COUNT] =
[STRINGID_PKMNTWISTEDDIMENSIONS - 12] = sText_PkmnTwistedDimensions,
[STRINGID_POINTEDSTONESFLOAT - 12] = sText_PointedStonesFloat,
[STRINGID_CLOAKEDINMYSTICALMOONLIGHT - 12] = sText_CloakedInMysticalMoonlight,
[STRINGID_TRAPPERBYSWIRLINGMAGMA - 12] = sText_TrappedBySwirlingMagma,
[STRINGID_TRAPPEDBYSWIRLINGMAGMA - 12] = sText_TrappedBySwirlingMagma,
[STRINGID_VANISHEDINSTANTLY - 12] = sText_VanishedInstantly,
[STRINGID_PROTECTEDTEAM - 12] = sText_ProtectedTeam,
[STRINGID_SHAREDITSGUARD - 12] = sText_SharedItsGuard,
@ -1208,7 +1219,7 @@ const u8 *const gBattleStringsTable[BATTLESTRINGS_COUNT] =
[STRINGID_HURLEDINTOTHEAIR - 12] = sText_HurledIntoTheAir,
[STRINGID_HELDITEMSLOSEEFFECTS - 12] = sText_HeldItemsLoseEffects,
[STRINGID_FELLSTRAIGHTDOWN - 12] = sText_FellStraightDown,
[STRINGID_TRANSFORMEDINTOWATERTYPE - 12] = sText_TransformedIntoWaterType,
[STRINGID_TARGETCHANGEDTYPE - 12] = sText_TargetChangedType,
[STRINGID_PKMNACQUIREDSIMPLE - 12] = sText_PkmnAcquiredSimple,
[STRINGID_EMPTYSTRING5 - 12] = sText_EmptyString4,
[STRINGID_KINDOFFER - 12] = sText_KindOffer,
@ -1318,6 +1329,11 @@ const u8 *const gBattleStringsTable[BATTLESTRINGS_COUNT] =
[STRINGID_AURABREAKENTERS - 12] = sText_AuraBreakActivates,
[STRINGID_COMATOSEENTERS - 12] = sText_ComatoseActivates,
[STRINGID_SCREENCLEANERENTERS - 12] = sText_ScreenCleanerActivates,
[STRINGID_BOTHCANNOLONGERESCAPE - 12] = sText_BothCanNoLongerEscape,
[STRINGID_CANTESCAPEDUETOUSEDMOVE - 12] = sText_CantEscapeDueToUsedMove,
[STRINGID_PKMNBECAMEWEAKERTOFIRE - 12] = sText_PkmnBecameWeakerToFire,
[STRINGID_ABOUTTOUSEPOLTERGEIST - 12] = sText_PkmnAboutToBeAttackedByItsItem,
[STRINGID_CANTESCAPEBECAUSEOFCURRENTMOVE - 12] = sText_CantEscapeBecauseOfCurrentMove,
};
const u16 gMentalHerbCureStringIds[] =
@ -1380,6 +1396,7 @@ const u16 gSwitchInAbilityStringIds[] =
[B_MSG_SWITCHIN_ASONE] = STRINGID_ASONEENTERS,
[B_MSG_SWITCHIN_CURIOUS_MEDICINE] = STRINGID_CURIOUSMEDICINEENTERS,
[B_MSG_SWITCHIN_PASTEL_VEIL] = STRINGID_PASTELVEILENTERS,
[B_MSG_SWITCHIN_NEUTRALIZING_GAS] = STRINGID_NEUTRALIZINGGASENTERS,
};
const u16 gMissStringIds[] =
@ -1533,16 +1550,17 @@ const u16 gFirstTurnOfTwoStringIds[] =
[B_MSG_TURN1_FREEZE_SHOCK] = STRINGID_CLOAKEDINAFREEZINGLIGHT,
};
// Index copied from move's index in gTrappingMoves
// Index copied from move's index in sTrappingMoves
const u16 gWrappedStringIds[] =
{
STRINGID_PKMNSQUEEZEDBYBIND, // MOVE_BIND
STRINGID_PKMNWRAPPEDBY, // MOVE_WRAP
STRINGID_PKMNTRAPPEDINVORTEX, // MOVE_FIRE_SPIN
STRINGID_PKMNCLAMPED, // MOVE_CLAMP
STRINGID_PKMNTRAPPEDINVORTEX, // MOVE_WHIRLPOOL
STRINGID_PKMNTRAPPEDBYSANDTOMB,// MOVE_SAND_TOMB
STRINGID_INFESTATION, // MOVE_INFESTATION
STRINGID_PKMNSQUEEZEDBYBIND, // MOVE_BIND
STRINGID_PKMNWRAPPEDBY, // MOVE_WRAP
STRINGID_PKMNTRAPPEDINVORTEX, // MOVE_FIRE_SPIN
STRINGID_PKMNCLAMPED, // MOVE_CLAMP
STRINGID_PKMNTRAPPEDINVORTEX, // MOVE_WHIRLPOOL
STRINGID_PKMNTRAPPEDBYSANDTOMB, // MOVE_SAND_TOMB
STRINGID_TRAPPEDBYSWIRLINGMAGMA, // MOVE_MAGMA_STORM
STRINGID_INFESTATION, // MOVE_INFESTATION
};
const u16 gMistUsedStringIds[] =
@ -1753,11 +1771,6 @@ const u16 gCaughtMonStringIds[] =
[B_MSG_LANETTES_BOX_FULL] = STRINGID_PKMNBOXLANETTESPCFULL,
};
const u16 gTrappingMoves[] =
{
MOVE_BIND, MOVE_WRAP, MOVE_FIRE_SPIN, MOVE_CLAMP, MOVE_WHIRLPOOL, MOVE_SAND_TOMB, MOVE_INFESTATION, 0xFFFF
};
const u16 gRoomsStringIds[] =
{
STRINGID_PKMNTWISTEDDIMENSIONS, STRINGID_TRICKROOMENDS,

File diff suppressed because it is too large Load Diff

View File

@ -317,8 +317,8 @@ void HandleAction_UseMove(void)
else if ((gBattleTypeFlags & BATTLE_TYPE_DOUBLE)
&& gSideTimers[side].followmeTimer == 0
&& (gBattleMoves[gCurrentMove].power != 0 || gBattleMoves[gCurrentMove].target != MOVE_TARGET_USER)
&& ((gBattleMons[*(gBattleStruct->moveTarget + gBattlerAttacker)].ability != ABILITY_LIGHTNING_ROD && moveType == TYPE_ELECTRIC)
|| (gBattleMons[*(gBattleStruct->moveTarget + gBattlerAttacker)].ability != ABILITY_STORM_DRAIN && moveType == TYPE_WATER)))
&& ((GetBattlerAbility(*(gBattleStruct->moveTarget + gBattlerAttacker)) != ABILITY_LIGHTNING_ROD && moveType == TYPE_ELECTRIC)
|| (GetBattlerAbility(*(gBattleStruct->moveTarget + gBattlerAttacker)) != ABILITY_STORM_DRAIN && moveType == TYPE_WATER)))
{
side = GetBattlerSide(gBattlerAttacker);
for (gActiveBattler = 0; gActiveBattler < gBattlersCount; gActiveBattler++)
@ -387,9 +387,9 @@ void HandleAction_UseMove(void)
{
gActiveBattler = gBattlerByTurnOrder[var];
RecordAbilityBattle(gActiveBattler, gBattleMons[gActiveBattler].ability);
if (gBattleMons[gActiveBattler].ability == ABILITY_LIGHTNING_ROD)
if (GetBattlerAbility(gActiveBattler) == ABILITY_LIGHTNING_ROD)
gSpecialStatuses[gActiveBattler].lightningRodRedirected = TRUE;
else if (gBattleMons[gActiveBattler].ability == ABILITY_STORM_DRAIN)
else if (GetBattlerAbility(gActiveBattler) == ABILITY_STORM_DRAIN)
gSpecialStatuses[gActiveBattler].stormDrainRedirected = TRUE;
gBattlerTarget = gActiveBattler;
}
@ -627,7 +627,7 @@ bool8 TryRunFromBattle(u8 battler)
effect++;
}
#endif
else if (gBattleMons[battler].ability == ABILITY_RUN_AWAY)
else if (GetBattlerAbility(battler) == ABILITY_RUN_AWAY)
{
if (InBattlePyramid())
{
@ -1762,7 +1762,7 @@ u8 TrySetCantSelectMoveBattleScript(void)
limitations++;
}
}
else if (holdEffect == HOLD_EFFECT_ASSAULT_VEST && gBattleMoves[move].power == 0)
else if (holdEffect == HOLD_EFFECT_ASSAULT_VEST && gBattleMoves[move].power == 0 && move != MOVE_ME_FIRST)
{
gCurrentMove = move;
gLastUsedItem = gBattleMons[gActiveBattler].item;
@ -1834,7 +1834,7 @@ u8 CheckMoveLimitations(u8 battlerId, u8 unusableMoves, u8 check)
unusableMoves |= gBitTable[i];
else if (HOLD_EFFECT_CHOICE(holdEffect) && *choicedMove != 0 && *choicedMove != 0xFFFF && *choicedMove != gBattleMons[battlerId].moves[i])
unusableMoves |= gBitTable[i];
else if (holdEffect == HOLD_EFFECT_ASSAULT_VEST && gBattleMoves[gBattleMons[battlerId].moves[i]].power == 0)
else if (holdEffect == HOLD_EFFECT_ASSAULT_VEST && gBattleMoves[gBattleMons[battlerId].moves[i]].power == 0 && gBattleMons[battlerId].moves[i] != MOVE_ME_FIRST)
unusableMoves |= gBitTable[i];
else if (IsGravityPreventingMove(gBattleMons[battlerId].moves[i]))
unusableMoves |= gBitTable[i];
@ -1894,6 +1894,57 @@ u8 GetImprisonedMovesCount(u8 battlerId, u16 move)
return imprisonedMoves;
}
void RestoreBattlerOriginalTypes(u8 battlerId)
{
gBattleMons[battlerId].type1 = gBaseStats[gBattleMons[battlerId].species].type1;
gBattleMons[battlerId].type2 = gBaseStats[gBattleMons[battlerId].species].type2;
}
void TryToApplyMimicry(u8 battlerId, bool8 various)
{
u32 moveType, move;
GET_MOVE_TYPE(move, moveType);
switch (gFieldStatuses)
{
case STATUS_FIELD_ELECTRIC_TERRAIN:
moveType = TYPE_ELECTRIC;
break;
case STATUS_FIELD_MISTY_TERRAIN:
moveType = TYPE_FAIRY;
break;
case STATUS_FIELD_GRASSY_TERRAIN:
moveType = TYPE_GRASS;
break;
case STATUS_FIELD_PSYCHIC_TERRAIN:
moveType = TYPE_PSYCHIC;
break;
default:
moveType = 0;
break;
}
if (moveType != 0 && !IS_BATTLER_OF_TYPE(battlerId, moveType))
{
SET_BATTLER_TYPE(battlerId, moveType);
PREPARE_MON_NICK_WITH_PREFIX_BUFFER(gBattleTextBuff1, battlerId, gBattlerPartyIndexes[battlerId])
PREPARE_TYPE_BUFFER(gBattleTextBuff2, moveType);
if (!various)
BattleScriptPushCursorAndCallback(BattleScript_MimicryActivatesEnd3);
}
}
void TryToRevertMimicry(void)
{
s32 i;
for (i = 0; i < MAX_BATTLERS_COUNT; i++)
{
if (GetBattlerAbility(i) == ABILITY_MIMICRY)
RestoreBattlerOriginalTypes(i);
}
}
enum
{
ENDTURN_ORDER,
@ -2275,9 +2326,10 @@ u8 DoFieldEndTurnEffects(void)
break;
case ENDTURN_ELECTRIC_TERRAIN:
if (gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN
&& (!(gFieldStatuses & STATUS_FIELD_TERRAIN_PERMANENT) && --gFieldTimers.electricTerrainTimer == 0))
&& (!(gFieldStatuses & STATUS_FIELD_TERRAIN_PERMANENT) && --gFieldTimers.terrainTimer == 0))
{
gFieldStatuses &= ~(STATUS_FIELD_ELECTRIC_TERRAIN | STATUS_FIELD_TERRAIN_PERMANENT);
TryToRevertMimicry();
BattleScriptExecute(BattleScript_ElectricTerrainEnds);
effect++;
}
@ -2285,9 +2337,10 @@ u8 DoFieldEndTurnEffects(void)
break;
case ENDTURN_MISTY_TERRAIN:
if (gFieldStatuses & STATUS_FIELD_MISTY_TERRAIN
&& (!(gFieldStatuses & STATUS_FIELD_TERRAIN_PERMANENT) && --gFieldTimers.mistyTerrainTimer == 0))
&& (!(gFieldStatuses & STATUS_FIELD_TERRAIN_PERMANENT) && --gFieldTimers.terrainTimer == 0))
{
gFieldStatuses &= ~(STATUS_FIELD_MISTY_TERRAIN);
TryToRevertMimicry();
BattleScriptExecute(BattleScript_MistyTerrainEnds);
effect++;
}
@ -2297,9 +2350,11 @@ u8 DoFieldEndTurnEffects(void)
if (gFieldStatuses & STATUS_FIELD_GRASSY_TERRAIN)
{
if (!(gFieldStatuses & STATUS_FIELD_TERRAIN_PERMANENT)
&& (gFieldTimers.grassyTerrainTimer == 0 || --gFieldTimers.grassyTerrainTimer == 0))
&& (gFieldTimers.terrainTimer == 0 || --gFieldTimers.terrainTimer == 0))
{
gFieldStatuses &= ~(STATUS_FIELD_GRASSY_TERRAIN);
TryToRevertMimicry();
}
BattleScriptExecute(BattleScript_GrassyTerrainHeals);
effect++;
}
@ -2307,9 +2362,10 @@ u8 DoFieldEndTurnEffects(void)
break;
case ENDTURN_PSYCHIC_TERRAIN:
if (gFieldStatuses & STATUS_FIELD_PSYCHIC_TERRAIN
&& (!(gFieldStatuses & STATUS_FIELD_TERRAIN_PERMANENT) && --gFieldTimers.psychicTerrainTimer == 0))
&& (!(gFieldStatuses & STATUS_FIELD_TERRAIN_PERMANENT) && --gFieldTimers.terrainTimer == 0))
{
gFieldStatuses &= ~(STATUS_FIELD_PSYCHIC_TERRAIN);
TryToRevertMimicry();
BattleScriptExecute(BattleScript_PsychicTerrainEnds);
effect++;
}
@ -2382,6 +2438,7 @@ enum
ENDTURN_NIGHTMARES,
ENDTURN_CURSE,
ENDTURN_WRAP,
ENDTURN_OCTOLOCK,
ENDTURN_UPROAR,
ENDTURN_THRASH,
ENDTURN_FLINCH,
@ -2652,13 +2709,25 @@ u8 DoBattlerEndTurnEffects(void)
}
gBattleStruct->turnEffectsTracker++;
break;
case ENDTURN_OCTOLOCK:
if (gDisableStructs[gActiveBattler].octolock
&& !(GetBattlerAbility(gActiveBattler) == ABILITY_CLEAR_BODY
|| GetBattlerAbility(gActiveBattler) == ABILITY_FULL_METAL_BODY
|| GetBattlerAbility(gActiveBattler) == ABILITY_WHITE_SMOKE))
{
gBattlerTarget = gActiveBattler;
BattleScriptExecute(BattleScript_OctolockEndTurn);
effect++;
}
gBattleStruct->turnEffectsTracker++;
break;
case ENDTURN_UPROAR: // uproar
if (gBattleMons[gActiveBattler].status2 & STATUS2_UPROAR)
{
for (gBattlerAttacker = 0; gBattlerAttacker < gBattlersCount; gBattlerAttacker++)
{
if ((gBattleMons[gBattlerAttacker].status1 & STATUS1_SLEEP)
&& gBattleMons[gBattlerAttacker].ability != ABILITY_SOUNDPROOF)
&& GetBattlerAbility(gBattlerAttacker) != ABILITY_SOUNDPROOF)
{
gBattleMons[gBattlerAttacker].status1 &= ~(STATUS1_SLEEP);
gBattleMons[gBattlerAttacker].status2 &= ~(STATUS2_NIGHTMARE);
@ -2726,6 +2795,7 @@ u8 DoBattlerEndTurnEffects(void)
case ENDTURN_FLINCH: // reset flinch
gBattleMons[gActiveBattler].status2 &= ~(STATUS2_FLINCHED);
gBattleStruct->turnEffectsTracker++;
break;
case ENDTURN_DISABLE: // disable
if (gDisableStructs[gActiveBattler].disableTimer != 0)
{
@ -3242,7 +3312,7 @@ u8 AtkCanceller_UnableToUseMove(void)
gBattleStruct->atkCancellerTracker++;
break;
case CANCELLER_TRUANT: // truant
if (gBattleMons[gBattlerAttacker].ability == ABILITY_TRUANT && gDisableStructs[gBattlerAttacker].truantCounter)
if (GetBattlerAbility(gBattlerAttacker) == ABILITY_TRUANT && gDisableStructs[gBattlerAttacker].truantCounter)
{
CancelMultiTurnMoves(gBattlerAttacker);
gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE;
@ -3683,7 +3753,7 @@ u8 TryWeatherFormChange(u8 battler)
if (gBattleMons[battler].species == SPECIES_CASTFORM)
{
if (gBattleMons[battler].ability != ABILITY_FORECAST || gBattleMons[battler].hp == 0)
if (GetBattlerAbility(battler) != ABILITY_FORECAST || gBattleMons[battler].hp == 0)
{
ret = 0;
}
@ -3719,11 +3789,11 @@ u8 TryWeatherFormChange(u8 battler)
}
else if (gBattleMons[battler].species == SPECIES_CHERRIM)
{
if (gBattleMons[battler].ability != ABILITY_FLOWER_GIFT || gBattleMons[battler].hp == 0)
if (GetBattlerAbility(battler) != ABILITY_FLOWER_GIFT || gBattleMons[battler].hp == 0)
ret = 0;
else if (gBattleMonForms[battler] == 0 && weatherEffect && holdEffect != HOLD_EFFECT_UTILITY_UMBRELLA && gBattleWeather & WEATHER_SUN_ANY)
ret = 2;
else if (gBattleMonForms[battler] != 0 && (!weatherEffect || holdEffect != HOLD_EFFECT_UTILITY_UMBRELLA || !(gBattleWeather & WEATHER_SUN_ANY)))
else if (gBattleMonForms[battler] != 0 && (!weatherEffect || holdEffect == HOLD_EFFECT_UTILITY_UMBRELLA || !(gBattleWeather & WEATHER_SUN_ANY)))
ret = 1;
}
@ -3809,7 +3879,7 @@ static bool32 ShouldChangeFormHpBased(u32 battler)
for (i = 0; i < ARRAY_COUNT(forms); i++)
{
if (gBattleMons[battler].ability == forms[i][0])
if (GetBattlerAbility(battler) == forms[i][0])
{
if (gBattleMons[battler].species == forms[i][2]
&& gBattleMons[battler].hp > gBattleMons[battler].maxHP / forms[i][3])
@ -4282,28 +4352,28 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move
}
break;
case ABILITY_ELECTRIC_SURGE:
if (TryChangeBattleTerrain(battler, STATUS_FIELD_ELECTRIC_TERRAIN, &gFieldTimers.electricTerrainTimer))
if (TryChangeBattleTerrain(battler, STATUS_FIELD_ELECTRIC_TERRAIN, &gFieldTimers.terrainTimer))
{
BattleScriptPushCursorAndCallback(BattleScript_ElectricSurgeActivates);
effect++;
}
break;
case ABILITY_GRASSY_SURGE:
if (TryChangeBattleTerrain(battler, STATUS_FIELD_GRASSY_TERRAIN, &gFieldTimers.grassyTerrainTimer))
if (TryChangeBattleTerrain(battler, STATUS_FIELD_GRASSY_TERRAIN, &gFieldTimers.terrainTimer))
{
BattleScriptPushCursorAndCallback(BattleScript_GrassySurgeActivates);
effect++;
}
break;
case ABILITY_MISTY_SURGE:
if (TryChangeBattleTerrain(battler, STATUS_FIELD_MISTY_TERRAIN, &gFieldTimers.mistyTerrainTimer))
if (TryChangeBattleTerrain(battler, STATUS_FIELD_MISTY_TERRAIN, &gFieldTimers.terrainTimer))
{
BattleScriptPushCursorAndCallback(BattleScript_MistySurgeActivates);
effect++;
}
break;
case ABILITY_PSYCHIC_SURGE:
if (TryChangeBattleTerrain(battler, STATUS_FIELD_PSYCHIC_TERRAIN, &gFieldTimers.psychicTerrainTimer))
if (TryChangeBattleTerrain(battler, STATUS_FIELD_PSYCHIC_TERRAIN, &gFieldTimers.terrainTimer))
{
BattleScriptPushCursorAndCallback(BattleScript_PsychicSurgeActivates);
effect++;
@ -4390,6 +4460,13 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move
effect++;
}
break;
case ABILITY_MIMICRY:
if (gBattleMons[battler].hp != 0 && gFieldStatuses & STATUS_FIELD_TERRAIN_ANY)
{
TryToApplyMimicry(battler, FALSE);
effect++;
}
break;
}
break;
case ABILITYEFFECT_ENDTURN: // 1
@ -4572,6 +4649,22 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move
effect++;
}
break;
case ABILITY_HUNGER_SWITCH:
if (!(gBattleMons[battler].status2 & STATUS2_TRANSFORMED))
{
if (gBattleMons[battler].species == SPECIES_MORPEKO)
{
gBattleMons[battler].species = SPECIES_MORPEKO_HANGRY;
BattleScriptPushCursorAndCallback(BattleScript_AttackerFormChangeEnd3NoPopup);
}
else if (gBattleMons[battler].species == SPECIES_MORPEKO_HANGRY)
{
gBattleMons[battler].species = SPECIES_MORPEKO;
BattleScriptPushCursorAndCallback(BattleScript_AttackerFormChangeEnd3NoPopup);
}
effect++;
}
break;
}
}
break;
@ -4837,7 +4930,7 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move
if (!(gMoveResultFlags & MOVE_RESULT_NO_EFFECT)
&& IsBattlerAlive(gBattlerAttacker)
&& TARGET_TURN_DAMAGED
&& (gBattleMoves[move].flags & FLAG_MAKES_CONTACT))
&& (IsMoveMakingContact(move, gBattlerAttacker)))
{
switch (gBattleMons[gBattlerAttacker].ability)
{
@ -5056,7 +5149,7 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move
if (!(gMoveResultFlags & MOVE_RESULT_NO_EFFECT)
&& gBattleMons[gBattlerAttacker].hp != 0
&& !gProtectStructs[gBattlerAttacker].confusionSelfDmg
&& (gBattleMoves[move].flags & FLAG_MAKES_CONTACT)
&& (IsMoveMakingContact(move, gBattlerAttacker))
&& TARGET_TURN_DAMAGED
&& CanBeBurned(gBattlerAttacker)
&& (Random() % 3) == 0)
@ -5072,7 +5165,7 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move
if (!(gMoveResultFlags & MOVE_RESULT_NO_EFFECT)
&& gBattleMons[gBattlerAttacker].hp != 0
&& !gProtectStructs[gBattlerAttacker].confusionSelfDmg
&& (gBattleMoves[move].flags & FLAG_MAKES_CONTACT)
&& (IsMoveMakingContact(move, gBattlerAttacker))
&& TARGET_TURN_DAMAGED
&& gBattleMons[gBattlerTarget].hp != 0
&& (Random() % 3) == 0
@ -5148,7 +5241,7 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move
&& !gProtectStructs[gBattlerAttacker].confusionSelfDmg
&& TARGET_TURN_DAMAGED
&& IsBattlerAlive(battler)
&& (gBattleMoves[move].flags & FLAG_MAKES_CONTACT)
&& (IsMoveMakingContact(move, gBattlerAttacker))
&& !(gStatuses3[gBattlerAttacker] & STATUS3_PERISH_SONG))
{
if (!(gStatuses3[battler] & STATUS3_PERISH_SONG))
@ -5281,7 +5374,7 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move
case ABILITYEFFECT_IMMUNITY: // 5
for (battler = 0; battler < gBattlersCount; battler++)
{
switch (gBattleMons[battler].ability)
switch (GetBattlerAbility(battler))
{
case ABILITY_IMMUNITY:
if (gBattleMons[battler].status1 & (STATUS1_POISON | STATUS1_TOXIC_POISON | STATUS1_TOXIC_COUNTER))
@ -5371,7 +5464,7 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move
case ABILITYEFFECT_FORECAST: // 6
for (battler = 0; battler < gBattlersCount; battler++)
{
if (gBattleMons[battler].ability == ABILITY_FORECAST || gBattleMons[battler].ability == ABILITY_FLOWER_GIFT)
if (GetBattlerAbility(battler) == ABILITY_FORECAST || GetBattlerAbility(battler) == ABILITY_FLOWER_GIFT)
{
effect = TryWeatherFormChange(battler);
if (effect)
@ -5392,8 +5485,10 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move
if (!(gBattleMons[gBattlerAttacker].status1 & STATUS1_ANY))
{
gBattleStruct->synchronizeMoveEffect &= ~(MOVE_EFFECT_AFFECTS_USER | MOVE_EFFECT_CERTAIN);
if (gBattleStruct->synchronizeMoveEffect == MOVE_EFFECT_TOXIC)
gBattleStruct->synchronizeMoveEffect = MOVE_EFFECT_POISON;
#if B_SYNCHRONIZE_TOXIC < GEN_5
if (gBattleStruct->synchronizeMoveEffect == MOVE_EFFECT_TOXIC)
gBattleStruct->synchronizeMoveEffect = MOVE_EFFECT_POISON;
#endif
gBattleScripting.moveEffect = gBattleStruct->synchronizeMoveEffect + MOVE_EFFECT_AFFECTS_USER;
gBattleScripting.battler = gBattlerAbility = gBattlerTarget;
@ -5430,7 +5525,7 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move
case ABILITYEFFECT_INTIMIDATE2:
for (i = 0; i < gBattlersCount; i++)
{
if (gBattleMons[i].ability == ABILITY_INTIMIDATE && gBattleResources->flags->flags[i] & RESOURCE_FLAG_INTIMIDATED)
if (GetBattlerAbility(i) == ABILITY_INTIMIDATE && gBattleResources->flags->flags[i] & RESOURCE_FLAG_INTIMIDATED)
{
gLastUsedAbility = ABILITY_INTIMIDATE;
gBattleResources->flags->flags[i] &= ~(RESOURCE_FLAG_INTIMIDATED);
@ -5497,6 +5592,23 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move
}
}
break;
case ABILITYEFFECT_NEUTRALIZINGGAS:
// Prints message only. separate from ABILITYEFFECT_ON_SWITCHIN bc activates before entry hazards
for (i = 0; i < gBattlersCount; i++)
{
if (gBattleMons[i].ability == ABILITY_NEUTRALIZING_GAS && !(gBattleResources->flags->flags[i] & RESOURCE_FLAG_NEUTRALIZING_GAS))
{
gBattleResources->flags->flags[i] |= RESOURCE_FLAG_NEUTRALIZING_GAS;
gBattlerAbility = i;
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SWITCHIN_NEUTRALIZING_GAS;
BattleScriptPushCursorAndCallback(BattleScript_SwitchInAbilityMsg);
effect++;
}
if (effect)
break;
}
break;
}
if (effect && gLastUsedAbility != 0xFF)
@ -5507,11 +5619,51 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move
return effect;
}
bool32 IsNeutralizingGasBannedAbility(u32 ability)
{
switch (ability)
{
case ABILITY_MULTITYPE:
case ABILITY_ZEN_MODE:
case ABILITY_STANCE_CHANGE:
case ABILITY_POWER_CONSTRUCT:
case ABILITY_SCHOOLING:
case ABILITY_RKS_SYSTEM:
case ABILITY_SHIELDS_DOWN:
case ABILITY_COMATOSE:
case ABILITY_DISGUISE:
case ABILITY_GULP_MISSILE:
case ABILITY_ICE_FACE:
case ABILITY_AS_ONE_ICE_RIDER:
case ABILITY_AS_ONE_SHADOW_RIDER:
return TRUE;
default:
return FALSE;
}
}
bool32 IsNeutralizingGasOnField(void)
{
u32 i;
for (i = 0; i < gBattlersCount; i++)
{
if (IsBattlerAlive(i) && gBattleMons[i].ability == ABILITY_NEUTRALIZING_GAS && !(gStatuses3[i] & STATUS3_GASTRO_ACID))
return TRUE;
}
return FALSE;
}
u32 GetBattlerAbility(u8 battlerId)
{
if (gStatuses3[battlerId] & STATUS3_GASTRO_ACID)
return ABILITY_NONE;
else if ((((gBattleMons[gBattlerAttacker].ability == ABILITY_MOLD_BREAKER
if (IsNeutralizingGasOnField() && !IsNeutralizingGasBannedAbility(gBattleMons[battlerId].ability))
return ABILITY_NONE;
if ((((gBattleMons[gBattlerAttacker].ability == ABILITY_MOLD_BREAKER
|| gBattleMons[gBattlerAttacker].ability == ABILITY_TERAVOLT
|| gBattleMons[gBattlerAttacker].ability == ABILITY_TURBOBLAZE)
&& !(gStatuses3[gBattlerAttacker] & STATUS3_GASTRO_ACID))
@ -5521,8 +5673,8 @@ u32 GetBattlerAbility(u8 battlerId)
&& gActionsByTurnOrder[gBattlerByTurnOrder[gBattlerAttacker]] == B_ACTION_USE_MOVE
&& gCurrentTurnActionNumber < gBattlersCount)
return ABILITY_NONE;
else
return gBattleMons[battlerId].ability;
return gBattleMons[battlerId].ability;
}
u32 IsAbilityOnSide(u32 battlerId, u32 ability)
@ -5574,7 +5726,7 @@ u32 IsAbilityPreventingEscape(u32 battlerId)
return 0;
#endif
#if B_SHADOW_TAG_ESCAPE >= GEN_4
if ((id = IsAbilityOnOpposingSide(battlerId, ABILITY_SHADOW_TAG)) && gBattleMons[battlerId].ability != ABILITY_SHADOW_TAG)
if ((id = IsAbilityOnOpposingSide(battlerId, ABILITY_SHADOW_TAG)) && GetBattlerAbility(battlerId) != ABILITY_SHADOW_TAG)
#else
if (id = IsAbilityOnOpposingSide(battlerId, ABILITY_SHADOW_TAG))
#endif
@ -6766,6 +6918,10 @@ u8 ItemBattleEffects(u8 caseID, u8 battlerId, bool8 moveTurn)
switch (atkHoldEffect)
{
case HOLD_EFFECT_FLINCH:
#if B_SERENE_GRACE_BOOST >= GEN_5
if (GetBattlerAbility(gBattlerAttacker) == ABILITY_SERENE_GRACE)
atkHoldEffectParam *= 2;
#endif
if (gBattleMoveDamage != 0 // Need to have done damage
&& !(gMoveResultFlags & MOVE_RESULT_NO_EFFECT)
&& TARGET_TURN_DAMAGED
@ -7121,7 +7277,7 @@ u32 GetMoveTarget(u16 move, u8 setTarget)
targetBattler = SetRandomTarget(gBattlerAttacker);
if (gBattleMoves[move].type == TYPE_ELECTRIC
&& IsAbilityOnOpposingSide(gBattlerAttacker, ABILITY_LIGHTNING_ROD)
&& gBattleMons[targetBattler].ability != ABILITY_LIGHTNING_ROD)
&& GetBattlerAbility(targetBattler) != ABILITY_LIGHTNING_ROD)
{
targetBattler ^= BIT_FLANK;
RecordAbilityBattle(targetBattler, gBattleMons[targetBattler].ability);
@ -7129,7 +7285,7 @@ u32 GetMoveTarget(u16 move, u8 setTarget)
}
else if (gBattleMoves[move].type == TYPE_WATER
&& IsAbilityOnOpposingSide(gBattlerAttacker, ABILITY_STORM_DRAIN)
&& gBattleMons[targetBattler].ability != ABILITY_STORM_DRAIN)
&& GetBattlerAbility(targetBattler) != ABILITY_STORM_DRAIN)
{
targetBattler ^= BIT_FLANK;
RecordAbilityBattle(targetBattler, gBattleMons[targetBattler].ability);
@ -7307,7 +7463,7 @@ u32 GetBattlerHoldEffect(u8 battlerId, bool32 checkNegating)
return HOLD_EFFECT_NONE;
if (gFieldStatuses & STATUS_FIELD_MAGIC_ROOM)
return HOLD_EFFECT_NONE;
if (gBattleMons[battlerId].ability == ABILITY_KLUTZ && !(gStatuses3[battlerId] & STATUS3_GASTRO_ACID))
if (GetBattlerAbility(battlerId) == ABILITY_KLUTZ)
return HOLD_EFFECT_NONE;
}
@ -7332,15 +7488,73 @@ u32 GetBattlerHoldEffectParam(u8 battlerId)
bool32 IsMoveMakingContact(u16 move, u8 battlerAtk)
{
if (!(gBattleMoves[move].flags & FLAG_MAKES_CONTACT))
return FALSE;
{
if (gBattleMoves[move].effect == EFFECT_SHELL_SIDE_ARM && gSwapDamageCategory)
return TRUE;
else
return FALSE;
}
else if (GetBattlerAbility(battlerAtk) == ABILITY_LONG_REACH)
{
return FALSE;
}
else if (GetBattlerHoldEffect(battlerAtk, TRUE) == HOLD_EFFECT_PROTECTIVE_PADS)
{
return FALSE;
}
else
{
return TRUE;
}
}
bool32 IsBattlerProtected(u8 battlerId, u16 move)
{
// Decorate bypasses protect and detect, but not crafty shield
if (move == MOVE_DECORATE)
{
if (gSideStatuses[GetBattlerSide(battlerId)] & SIDE_STATUS_CRAFTY_SHIELD)
return TRUE;
else if (gProtectStructs[battlerId].protected)
return FALSE;
}
// Protective Pads doesn't stop Unseen Fist from bypassing Protect effects, so IsMoveMakingContact() isn't used here.
// This means extra logic is needed to handle Shell Side Arm.
if (GetBattlerAbility(gBattlerAttacker) == ABILITY_UNSEEN_FIST
&& (gBattleMoves[move].flags & FLAG_MAKES_CONTACT || (gBattleMoves[move].effect == EFFECT_SHELL_SIDE_ARM && gSwapDamageCategory)))
return FALSE;
else if (!(gBattleMoves[move].flags & FLAG_PROTECT_AFFECTED))
return FALSE;
else if (gBattleMoves[move].effect == MOVE_EFFECT_FEINT)
return FALSE;
else if (gProtectStructs[battlerId].protected)
return TRUE;
else if (gSideStatuses[GetBattlerSide(battlerId)] & SIDE_STATUS_WIDE_GUARD
&& gBattleMoves[move].target & (MOVE_TARGET_BOTH | MOVE_TARGET_FOES_AND_ALLY))
return TRUE;
else if (gProtectStructs[battlerId].banefulBunkered)
return TRUE;
else if (gProtectStructs[battlerId].obstructed && !IS_MOVE_STATUS(move))
return TRUE;
else if (gProtectStructs[battlerId].spikyShielded)
return TRUE;
else if (gProtectStructs[battlerId].kingsShielded && gBattleMoves[move].power != 0)
return TRUE;
else if (gSideStatuses[GetBattlerSide(battlerId)] & SIDE_STATUS_QUICK_GUARD
&& GetChosenMovePriority(gBattlerAttacker) > 0)
return TRUE;
else if (gSideStatuses[GetBattlerSide(battlerId)] & SIDE_STATUS_CRAFTY_SHIELD
&& IS_MOVE_STATUS(move))
return TRUE;
else if (gSideStatuses[GetBattlerSide(battlerId)] & SIDE_STATUS_MAT_BLOCK
&& !IS_MOVE_STATUS(move))
return TRUE;
else
return FALSE;
}
bool32 IsBattlerGrounded(u8 battlerId)
{
if (GetBattlerHoldEffect(battlerId, TRUE) == HOLD_EFFECT_IRON_BALL)
@ -7696,7 +7910,7 @@ static u16 CalcMoveBasePower(u16 move, u8 battlerAtk, u8 battlerDef)
if (weight >= ARRAY_COUNT(sHeatCrashPowerTable))
basePower = sHeatCrashPowerTable[ARRAY_COUNT(sHeatCrashPowerTable) - 1];
else
basePower = sHeatCrashPowerTable[i];
basePower = sHeatCrashPowerTable[weight];
break;
case EFFECT_PUNISHMENT:
basePower = 60 + (CountBattlerStatIncreases(battlerDef, FALSE) * 20);
@ -7731,6 +7945,10 @@ static u16 CalcMoveBasePower(u16 move, u8 battlerAtk, u8 battlerDef)
&& (gDisableStructs[battlerDef].isFirstTurn != 2 || B_PAYBACK_SWITCH_BOOST < GEN_5))
basePower *= 2;
break;
case EFFECT_BOLT_BEAK:
if (GetBattlerTurnOrderNum(battlerAtk) < GetBattlerTurnOrderNum(battlerDef))
basePower *= 2;
break;
case EFFECT_ROUND:
if (gChosenMoveByBattler[BATTLE_PARTNER(battlerAtk)] == MOVE_ROUND && !(gAbsentBattlerFlags & gBitTable[BATTLE_PARTNER(battlerAtk)]))
basePower *= 2;
@ -7773,6 +7991,11 @@ static u16 CalcMoveBasePower(u16 move, u8 battlerAtk, u8 battlerDef)
if (gFieldStatuses & STATUS_FIELD_GRAVITY)
MulModifier(&basePower, UQ_4_12(1.5));
break;
case EFFECT_TERRAIN_PULSE:
if ((gFieldStatuses & STATUS_FIELD_TERRAIN_ANY)
&& IsBattlerGrounded(gBattlerAttacker))
basePower *= 2;
break;
}
// move-specific base power changes
@ -7846,7 +8069,7 @@ static u32 CalcMoveBasePowerAfterModifiers(u16 move, u8 battlerAtk, u8 battlerDe
MulModifier(&modifier, UQ_4_12(1.3));
break;
case ABILITY_TOUGH_CLAWS:
if (gBattleMoves[move].flags & FLAG_MAKES_CONTACT)
if (IsMoveMakingContact(move, battlerAtk))
MulModifier(&modifier, UQ_4_12(1.3));
break;
case ABILITY_STRONG_JAW:
@ -7914,7 +8137,7 @@ static u32 CalcMoveBasePowerAfterModifiers(u16 move, u8 battlerAtk, u8 battlerDe
if (IsAbilityOnField(ABILITY_AURA_BREAK))
MulModifier(&modifier, UQ_4_12(0.75));
else
MulModifier(&modifier, UQ_4_12(1.25));
MulModifier(&modifier, UQ_4_12(1.33));
}
// attacker partner's abilities
@ -7996,7 +8219,11 @@ static u32 CalcMoveBasePowerAfterModifiers(u16 move, u8 battlerAtk, u8 battlerDe
MulModifier(&modifier, holdEffectModifier);
break;
case HOLD_EFFECT_SOUL_DEW:
if ((gBattleMons[battlerAtk].species == SPECIES_LATIAS || gBattleMons[battlerAtk].species == SPECIES_LATIOS) && !(gBattleTypeFlags & BATTLE_TYPE_FRONTIER))
#if B_SOUL_DEW_BOOST >= GEN_7
if ((gBattleMons[battlerAtk].species == SPECIES_LATIAS || gBattleMons[battlerAtk].species == SPECIES_LATIOS) && (moveType == TYPE_PSYCHIC || moveType == TYPE_DRAGON))
#else
if ((gBattleMons[battlerAtk].species == SPECIES_LATIAS || gBattleMons[battlerAtk].species == SPECIES_LATIOS) && !(gBattleTypeFlags & BATTLE_TYPE_FRONTIER) && IS_MOVE_SPECIAL(move))
#endif
MulModifier(&modifier, holdEffectModifier);
break;
case HOLD_EFFECT_GEMS:
@ -8071,8 +8298,11 @@ static u32 CalcMoveBasePowerAfterModifiers(u16 move, u8 battlerAtk, u8 battlerDe
MulModifier(&modifier, UQ_4_12(0.5));
break;
case EFFECT_KNOCK_OFF:
if (gBattleMons[battlerDef].item != ITEM_NONE && GetBattlerAbility(battlerDef) != ABILITY_STICKY_HOLD)
#if B_KNOCK_OFF_DMG >= GEN_6
if (gBattleMons[battlerDef].item != ITEM_NONE
&& CanBattlerGetOrLoseItem(battlerDef, gBattleMons[battlerDef].item))
MulModifier(&modifier, UQ_4_12(1.5));
#endif
break;
}
@ -8409,6 +8639,14 @@ static u32 CalcDefenseStat(u16 move, u8 battlerAtk, u8 battlerDef, u8 moveType,
if (!usesDefStat)
MulModifier(&modifier, UQ_4_12(1.5));
break;
#if B_SOUL_DEW_BOOST <= GEN_6
case HOLD_EFFECT_SOUL_DEW:
if ((gBattleMons[battlerDef].species == SPECIES_LATIAS || gBattleMons[battlerDef].species == SPECIES_LATIOS)
&& !(gBattleTypeFlags & BATTLE_TYPE_FRONTIER)
&& !usesDefStat)
MulModifier(&modifier, UQ_4_12(1.5));
break;
#endif
}
// sandstorm sp.def boost for rock types
@ -8479,7 +8717,9 @@ static u32 CalcFinalDmg(u32 dmg, u16 move, u8 battlerAtk, u8 battlerDef, u8 move
if (((gSideStatuses[defSide] & SIDE_STATUS_REFLECT && IS_MOVE_PHYSICAL(move))
|| (gSideStatuses[defSide] & SIDE_STATUS_LIGHTSCREEN && IS_MOVE_SPECIAL(move))
|| (gSideStatuses[defSide] & SIDE_STATUS_AURORA_VEIL))
&& abilityAtk != ABILITY_INFILTRATOR)
&& abilityAtk != ABILITY_INFILTRATOR
&& !(isCrit)
&& !gProtectStructs[gBattlerAttacker].confusionSelfDmg)
{
if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE)
MulModifier(&finalModifier, UQ_4_12(0.66));
@ -8648,9 +8888,8 @@ static void MulByTypeEffectiveness(u16 *modifier, u16 move, u8 moveType, u8 batt
mod = UQ_4_12(2.0);
if (moveType == TYPE_GROUND && defType == TYPE_FLYING && IsBattlerGrounded(battlerDef) && mod == UQ_4_12(0.0))
mod = UQ_4_12(1.0);
if (gProtectStructs[battlerDef].kingsShielded && gBattleMoves[move].effect != EFFECT_FEINT)
mod = UQ_4_12(1.0);
if (moveType == TYPE_FIRE && gDisableStructs[battlerDef].tarShot)
mod = UQ_4_12(2.0);
// WEATHER_STRONG_WINDS weakens Super Effective moves against Flying-type Pokémon
if (WEATHER_HAS_EFFECT && gBattleWeather & WEATHER_STRONG_WINDS)
@ -8875,9 +9114,9 @@ bool32 CanMegaEvolve(u8 battlerId)
struct MegaEvolutionData *mega = &(((struct ChooseMoveStruct*)(&gBattleResources->bufferA[gActiveBattler][4]))->mega);
#ifdef ITEM_EXPANSION
// Check if Player has a Mega Bracelet
// Check if Player has a Mega Ring
if ((GetBattlerPosition(battlerId) == B_POSITION_PLAYER_LEFT || (!(gBattleTypeFlags & BATTLE_TYPE_MULTI) && GetBattlerPosition(battlerId) == B_POSITION_PLAYER_RIGHT))
&& !CheckBagHasItem(ITEM_MEGA_BRACELET, 1))
&& !CheckBagHasItem(ITEM_MEGA_RING, 1))
return FALSE;
#endif
@ -8969,6 +9208,7 @@ void UndoFormChange(u32 monId, u32 side, bool32 isSwitchingOut)
// Changed Form ID Default Form ID Should change on switch
{SPECIES_MIMIKYU_BUSTED, SPECIES_MIMIKYU, FALSE},
{SPECIES_GRENINJA_ASH, SPECIES_GRENINJA_BATTLE_BOND, FALSE},
{SPECIES_MELOETTA_PIROUETTE, SPECIES_MELOETTA, FALSE},
{SPECIES_AEGISLASH_BLADE, SPECIES_AEGISLASH, TRUE},
{SPECIES_DARMANITAN_ZEN_MODE, SPECIES_DARMANITAN, TRUE},
{SPECIES_MINIOR, SPECIES_MINIOR_CORE_RED, TRUE},
@ -8981,6 +9221,7 @@ void UndoFormChange(u32 monId, u32 side, bool32 isSwitchingOut)
{SPECIES_WISHIWASHI_SCHOOL, SPECIES_WISHIWASHI, TRUE},
{SPECIES_CRAMORANT_GORGING, SPECIES_CRAMORANT, TRUE},
{SPECIES_CRAMORANT_GULPING, SPECIES_CRAMORANT, TRUE},
{SPECIES_MORPEKO_HANGRY, SPECIES_MORPEKO, TRUE},
};
currSpecies = GetMonData(&party[monId], MON_DATA_SPECIES, NULL);
@ -9126,7 +9367,9 @@ bool8 ShouldGetStatBadgeBoost(u16 badgeFlag, u8 battlerId)
u8 GetBattleMoveSplit(u32 moveId)
{
if (IS_MOVE_STATUS(moveId) || B_PHYSICAL_SPECIAL_SPLIT >= GEN_4)
if (gSwapDamageCategory) // Photon Geyser, Shell Side Arm, Light That Burns the Sky
return SPLIT_PHYSICAL;
else if (IS_MOVE_STATUS(moveId) || B_PHYSICAL_SPECIAL_SPLIT >= GEN_4)
return gBattleMoves[moveId].split;
else if (gBattleMoves[moveId].type < TYPE_MYSTERY)
return SPLIT_PHYSICAL;

View File

@ -142,7 +142,7 @@ u32 sub_805725C(u8 battlerId)
{
u32 toSub;
if (gBattleMons[battlerId].ability == ABILITY_EARLY_BIRD)
if (GetBattlerAbility(battlerId) == ABILITY_EARLY_BIRD)
toSub = 2;
else
toSub = 1;

View File

@ -378,7 +378,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] =
.secondaryEffectChance = 0,
.target = MOVE_TARGET_SELECTED,
.priority = 0,
.flags = FLAG_MAKES_CONTACT | FLAG_PROTECT_AFFECTED | FLAG_MIRROR_MOVE_AFFECTED | FLAG_KINGS_ROCK_AFFECTED,
.flags = FLAG_MAKES_CONTACT | FLAG_PROTECT_AFFECTED | FLAG_MIRROR_MOVE_AFFECTED | FLAG_KINGS_ROCK_AFFECTED | FLAG_TWO_STRIKES,
.split = SPLIT_PHYSICAL,
},
@ -649,7 +649,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] =
.secondaryEffectChance = 20,
.target = MOVE_TARGET_SELECTED,
.priority = 0,
.flags = FLAG_PROTECT_AFFECTED | FLAG_MIRROR_MOVE_AFFECTED | FLAG_SHEER_FORCE_BOOST,
.flags = FLAG_PROTECT_AFFECTED | FLAG_MIRROR_MOVE_AFFECTED | FLAG_SHEER_FORCE_BOOST | FLAG_TWO_STRIKES,
.split = SPLIT_PHYSICAL,
},
@ -2460,7 +2460,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] =
.secondaryEffectChance = 0,
.target = MOVE_TARGET_SELECTED,
.priority = 0,
.flags = FLAG_PROTECT_AFFECTED | FLAG_MIRROR_MOVE_AFFECTED | FLAG_KINGS_ROCK_AFFECTED,
.flags = FLAG_PROTECT_AFFECTED | FLAG_MIRROR_MOVE_AFFECTED | FLAG_KINGS_ROCK_AFFECTED | FLAG_TWO_STRIKES,
.split = SPLIT_PHYSICAL,
},
@ -7267,7 +7267,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] =
.secondaryEffectChance = 0,
.target = MOVE_TARGET_SELECTED,
.priority = 0,
.flags = FLAG_MAKES_CONTACT | FLAG_PROTECT_AFFECTED | FLAG_MIRROR_MOVE_AFFECTED | FLAG_KINGS_ROCK_AFFECTED,
.flags = FLAG_MAKES_CONTACT | FLAG_PROTECT_AFFECTED | FLAG_MIRROR_MOVE_AFFECTED | FLAG_KINGS_ROCK_AFFECTED | FLAG_TWO_STRIKES,
.split = SPLIT_PHYSICAL,
},
@ -8367,7 +8367,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] =
.secondaryEffectChance = 0,
.target = MOVE_TARGET_SELECTED,
.priority = 0,
.flags = FLAG_MAKES_CONTACT | FLAG_PROTECT_AFFECTED | FLAG_MIRROR_MOVE_AFFECTED | FLAG_KINGS_ROCK_AFFECTED,
.flags = FLAG_MAKES_CONTACT | FLAG_PROTECT_AFFECTED | FLAG_MIRROR_MOVE_AFFECTED | FLAG_KINGS_ROCK_AFFECTED | FLAG_TWO_STRIKES,
.split = SPLIT_PHYSICAL,
},
@ -8575,7 +8575,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] =
.secondaryEffectChance = 0,
.target = MOVE_TARGET_SELECTED,
.priority = 0,
.flags = FLAG_MAKES_CONTACT | FLAG_PROTECT_AFFECTED | FLAG_MIRROR_MOVE_AFFECTED | FLAG_KINGS_ROCK_AFFECTED,
.flags = FLAG_MAKES_CONTACT | FLAG_PROTECT_AFFECTED | FLAG_MIRROR_MOVE_AFFECTED | FLAG_KINGS_ROCK_AFFECTED | FLAG_TWO_STRIKES,
.split = SPLIT_PHYSICAL,
},
@ -8614,7 +8614,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] =
[MOVE_RELIC_SONG] =
{
.effect = EFFECT_SLEEP_HIT,
.effect = EFFECT_RELIC_SONG,
.power = 75,
.type = TYPE_NORMAL,
.accuracy = 100,
@ -8624,6 +8624,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] =
.priority = 0,
.flags = FLAG_PROTECT_AFFECTED | FLAG_MIRROR_MOVE_AFFECTED | FLAG_SOUND | FLAG_SHEER_FORCE_BOOST,
.split = SPLIT_SPECIAL,
.argument = STATUS1_SLEEP,
},
[MOVE_SECRET_SWORD] =
@ -10454,7 +10455,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] =
[MOVE_PHOTON_GEYSER] =
{
.effect = EFFECT_PLACEHOLDER, // Needs a custom move effect
.effect = EFFECT_PHOTON_GEYSER,
.power = 100,
.type = TYPE_PSYCHIC,
.accuracy = 100,
@ -10462,7 +10463,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] =
.secondaryEffectChance = 0,
.target = MOVE_TARGET_FOES_AND_ALLY,
.priority = 0,
.flags = FLAG_PROTECT_AFFECTED | FLAG_MIRROR_MOVE_AFFECTED | FLAG_KINGS_ROCK_AFFECTED,
.flags = FLAG_PROTECT_AFFECTED | FLAG_MIRROR_MOVE_AFFECTED | FLAG_KINGS_ROCK_AFFECTED | FLAG_TARGET_ABILITY_IGNORED,
.split = SPLIT_SPECIAL,
},
@ -10726,9 +10727,9 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] =
[MOVE_DOUBLE_IRON_BASH] =
{
#if B_UPDATED_MOVE_DATA >= GEN_8
.flags = FLAG_MAKES_CONTACT | FLAG_PROTECT_AFFECTED | FLAG_MIRROR_MOVE_AFFECTED | FLAG_IRON_FIST_BOOST | FLAG_SHEER_FORCE_BOOST,
.flags = FLAG_MAKES_CONTACT | FLAG_PROTECT_AFFECTED | FLAG_MIRROR_MOVE_AFFECTED | FLAG_IRON_FIST_BOOST | FLAG_SHEER_FORCE_BOOST | FLAG_TWO_STRIKES,
#else
.flags = FLAG_MAKES_CONTACT | FLAG_PROTECT_AFFECTED | FLAG_MIRROR_MOVE_AFFECTED | FLAG_DMG_MINIMIZE | FLAG_IRON_FIST_BOOST | FLAG_SHEER_FORCE_BOOST,
.flags = FLAG_MAKES_CONTACT | FLAG_PROTECT_AFFECTED | FLAG_MIRROR_MOVE_AFFECTED | FLAG_DMG_MINIMIZE | FLAG_IRON_FIST_BOOST | FLAG_SHEER_FORCE_BOOST | FLAG_TWO_STRIKES,
#endif
.effect = EFFECT_DOUBLE_IRON_BASH,
.power = 60,
@ -10771,7 +10772,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] =
[MOVE_JAW_LOCK] =
{
.effect = EFFECT_MEAN_LOOK,
.effect = EFFECT_JAW_LOCK,
.power = 80,
.type = TYPE_DARK,
.accuracy = 100,
@ -10799,7 +10800,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] =
[MOVE_NO_RETREAT] =
{
.effect = EFFECT_PLACEHOLDER, //TODO
.effect = EFFECT_NO_RETREAT,
.power = 0,
.type = TYPE_FIGHTING,
.accuracy = 0,
@ -10813,7 +10814,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] =
[MOVE_TAR_SHOT] =
{
.effect = EFFECT_SPEED_DOWN,
.effect = EFFECT_TAR_SHOT,
.power = 0,
.type = TYPE_ROCK,
.accuracy = 100,
@ -10827,7 +10828,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] =
[MOVE_MAGIC_POWDER] =
{
.effect = EFFECT_THIRD_TYPE,
.effect = EFFECT_SOAK,
.power = 0,
.type = TYPE_PSYCHIC,
.accuracy = 100,
@ -10850,7 +10851,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] =
.secondaryEffectChance = 0,
.target = MOVE_TARGET_SELECTED,
.priority = 0,
.flags = FLAG_PROTECT_AFFECTED | FLAG_MIRROR_MOVE_AFFECTED | FLAG_KINGS_ROCK_AFFECTED,
.flags = FLAG_PROTECT_AFFECTED | FLAG_MIRROR_MOVE_AFFECTED | FLAG_KINGS_ROCK_AFFECTED | FLAG_TWO_STRIKES,
.split = SPLIT_PHYSICAL,
},
@ -10870,7 +10871,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] =
[MOVE_OCTOLOCK] =
{
.effect = EFFECT_MEAN_LOOK,
.effect = EFFECT_OCTOLOCK,
.power = 0,
.type = TYPE_FIGHTING,
.accuracy = 100,
@ -10884,7 +10885,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] =
[MOVE_BOLT_BEAK] =
{
.effect = EFFECT_PLACEHOLDER, //TODO
.effect = EFFECT_BOLT_BEAK,
.power = 85,
.type = TYPE_ELECTRIC,
.accuracy = 100,
@ -10898,7 +10899,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] =
[MOVE_FISHIOUS_REND] =
{
.effect = EFFECT_PLACEHOLDER, //TODO. same as bolt beak
.effect = EFFECT_BOLT_BEAK,
.power = 85,
.type = TYPE_WATER,
.accuracy = 100,
@ -10926,7 +10927,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] =
[MOVE_CLANGOROUS_SOUL] =
{
.effect = EFFECT_PLACEHOLDER, //TODO
.effect = EFFECT_CLANGOROUS_SOUL,
.power = 0,
.type = TYPE_DRAGON,
.accuracy = 100,
@ -11038,7 +11039,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] =
[MOVE_AURA_WHEEL] =
{
.effect = EFFECT_SPEED_UP_HIT,
.effect = EFFECT_AURA_WHEEL,
.power = 110,
.type = TYPE_ELECTRIC,
.accuracy = 100,
@ -11290,12 +11291,12 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] =
[MOVE_SHELL_SIDE_ARM] =
{
.effect = EFFECT_PLACEHOLDER, //TODO
.effect = EFFECT_SHELL_SIDE_ARM,
.power = 90,
.type = TYPE_POISON,
.accuracy = 100,
.pp = 10,
.secondaryEffectChance = 0,
.secondaryEffectChance = 20,
.target = MOVE_TARGET_SELECTED,
.priority = 0,
.flags = FLAG_PROTECT_AFFECTED | FLAG_MIRROR_MOVE_AFFECTED | FLAG_KINGS_ROCK_AFFECTED | FLAG_SHEER_FORCE_BOOST,
@ -11346,7 +11347,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] =
[MOVE_TERRAIN_PULSE] =
{
.effect = EFFECT_PLACEHOLDER, //TODO
.effect = EFFECT_TERRAIN_PULSE,
.power = 50,
.type = TYPE_NORMAL,
.accuracy = 100,
@ -11402,7 +11403,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] =
[MOVE_POLTERGEIST] =
{
.effect = EFFECT_PLACEHOLDER, //TODO
.effect = EFFECT_POLTERGEIST,
.power = 110,
.type = TYPE_GHOST,
.accuracy = 90,
@ -11480,7 +11481,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] =
.secondaryEffectChance = 0,
.target = MOVE_TARGET_SELECTED,
.priority = 0,
.flags = FLAG_MAKES_CONTACT | FLAG_PROTECT_AFFECTED | FLAG_MIRROR_MOVE_AFFECTED | FLAG_KINGS_ROCK_AFFECTED,
.flags = FLAG_MAKES_CONTACT | FLAG_PROTECT_AFFECTED | FLAG_MIRROR_MOVE_AFFECTED | FLAG_KINGS_ROCK_AFFECTED | FLAG_TWO_STRIKES,
.split = SPLIT_PHYSICAL,
},

View File

@ -2680,7 +2680,7 @@ const struct Item gItems[] =
.name = _("UP-GRADE"),
.itemId = ITEM_UP_GRADE,
.price = 2100,
.holdEffect = HOLD_EFFECT_UP_GRADE,
.holdEffect = HOLD_EFFECT_UPGRADE,
.description = sUpGradeDesc,
.pocket = POCKET_ITEMS,
.type = ITEM_USE_BAG_MENU,
@ -2767,7 +2767,7 @@ const struct Item gItems[] =
.name = _("STICK"),
.itemId = ITEM_STICK,
.price = 200,
.holdEffect = HOLD_EFFECT_STICK,
.holdEffect = HOLD_EFFECT_LEEK,
.description = sStickDesc,
.pocket = POCKET_ITEMS,
.type = ITEM_USE_BAG_MENU,

View File

@ -2839,7 +2839,7 @@ static const u8 sMETEOR_BEAMDescription[] = _(
"Sp. Attack before attacking.");
static const u8 sSHELL_SIDE_ARMDescription[] = _(
"Uses higher of physical and\n"
"Deals better of physical and\n"
"special damage. May poison.");
static const u8 sMISTY_EXPLOSIONDescription[] = _(

View File

@ -1395,11 +1395,6 @@ const u32 gBattleAnimBgPalette_Solarbeam[] = INCBIN_U32("graphics/battle_anims/b
const u32 gBattleAnimBgPalette_MagmaStorm[] = INCBIN_U32("graphics/battle_anims/backgrounds/magma_storm.gbapal.lz");
//new battle bgs
const u32 gBattleAnimBgPalette_GigaImpact[] = INCBIN_U32("graphics/battle_anims/backgrounds/giga_impact.gbapal.lz");
//const u32 gBattleAnimBgImage_TrickRoom[] = INCBIN_U32("graphics/battle_anims/backgrounds/trick_room.4bpp.lz");
//const u32 gBattleAnimBgPalette_TrickRoom[] = INCBIN_U32("graphics/battle_anims/backgrounds/trick_room.gbapal.lz");
//const u32 gBattleAnimBgTilemap_TrickRoom[] = INCBIN_U32("graphics/battle_anims/backgrounds/trick_room_map.bin.lz");
const u32 gBattleAnimBgImage_Hurricane[] = INCBIN_U32("graphics/battle_anims/backgrounds/new/hurricane.4bpp.lz");
const u32 gBattleAnimBgPalette_Hurricane[] = INCBIN_U32("graphics/battle_anims/backgrounds/new/hurricane.gbapal.lz");
@ -1407,15 +1402,14 @@ const u32 gBattleAnimBgTilemap_Hurricane[] = INCBIN_U32("graphics/battle_anims/b
const u32 gBattleAnimBgPalette_RockWrecker[] = INCBIN_U32("graphics/battle_anims/backgrounds/new/rock_wrecker.gbapal.lz");
const u32 gBattleAnimBgTilemap_GigaImpactPlayer[] = INCBIN_U32("graphics/battle_anims/backgrounds/new/giga_impact_player.bin.lz");
const u32 gBattleAnimBgTilemap_GigaImpactOpponent[] = INCBIN_U32("graphics/battle_anims/backgrounds/new/giga_impact_opponent.bin.lz");
const u32 gBattleAnimBgTilemap_GigaImpactContest[] = INCBIN_U32("graphics/battle_anims/backgrounds/new/giga_impact_contest.bin.lz");
const u32 gBattleAnimBgImage_GigaImpact[] = INCBIN_U32("graphics/battle_anims/backgrounds/new/giga_impact.4bpp.lz");
const u32 gBattleAnimBgPalette_GigaImpact[] = INCBIN_U32("graphics/battle_anims/backgrounds/new/giga_impact.gbapal.lz");
const u32 gBattleAnimBgImage_SpacialRend[] = INCBIN_U32("graphics/battle_anims/backgrounds/new/spacial_rend.4bpp.lz");
const u32 gBattleAnimBgPalette_SpacialRend[] = INCBIN_U32("graphics/battle_anims/backgrounds/new/spacial_rend.gbapal.lz");
const u32 gBattleAnimBgTilemap_SpacialRendOpponent[] = INCBIN_U32("graphics/battle_anims/backgrounds/new/spacial_rend_opponent.bin.lz");
const u32 gBattleAnimBgTilemap_SpacialRendPlayer[] = INCBIN_U32("graphics/battle_anims/backgrounds/new/spacial_rend_player.bin.lz");
const u32 gBattleAnimBgImage_DarkVoid[] = INCBIN_U32("graphics/battle_anims/backgrounds/dark_void.4bpp.lz");
const u32 gBattleAnimBgPalette_DarkVoid[] = INCBIN_U32("graphics/battle_anims/backgrounds/dark_void.gbapal.lz");
const u32 gBattleAnimBgTilemap_DarkVoid[] = INCBIN_U32("graphics/battle_anims/backgrounds/dark_void.bin.lz");
const u32 gBattleAnimBgPalette_SludgeWave[] = INCBIN_U32("graphics/battle_anims/backgrounds/new/sludge_wave.gbapal.lz");
@ -1441,10 +1435,6 @@ const u32 gBattleAnimBgImage_ClangorousSoulblaze[] = INCBIN_U32("graphics/battle
const u32 gBattleAnimBgPalette_ClangorousSoulblaze[] = INCBIN_U32("graphics/battle_anims/backgrounds/new/clangorous_soulblaze.gbapal.lz");
const u32 gBattleAnimBgTilemap_ClangorousSoulblaze[] = INCBIN_U32("graphics/battle_anims/backgrounds/new/clangorous_soulblaze.bin.lz");
//const u32 gBattleAnimBgImage_DarkVoid[] = INCBIN_U32("graphics/battle_anims/backgrounds/new/dark_void.4bpp.lz");
//const u32 gBattleAnimBgPalette_DarkVoid[] = INCBIN_U32("graphics/battle_anims/backgrounds/new/dark_void.gbapal.lz");
//const u32 gBattleAnimBgTilemap_DarkVoid[] = INCBIN_U32("graphics/battle_anims/backgrounds/new/dark_void.bin.lz");
const u32 gBattleAnimBgPalette_DynamaxCannon[] = INCBIN_U32("graphics/battle_anims/backgrounds/new/dynamax_cannon.gbapal.lz");
const u32 gBattleAnimBgImage_ElectricTerrain[] = INCBIN_U32("graphics/battle_anims/backgrounds/new/electric_terrain.4bpp.lz");
@ -1463,14 +1453,6 @@ const u32 gBattleAnimBgTilemap_FocusBlast[] = INCBIN_U32("graphics/battle_anims/
const u32 gBattleAnimBgPalette_GarbageFalls[] = INCBIN_U32("graphics/battle_anims/backgrounds/new/garbage_falls.gbapal.lz");
const u32 gBattleAnimBgImage_GigaImpactOpponent[] = INCBIN_U32("graphics/battle_anims/backgrounds/new/giga_impact_opponent.4bpp.lz");
const u32 gBattleAnimBgPalette_GigaImpactOpponent[] = INCBIN_U32("graphics/battle_anims/backgrounds/new/giga_impact_opponent.gbapal.lz");
const u32 gBattleAnimBgTilemap_GigaImpactOpponent[] = INCBIN_U32("graphics/battle_anims/backgrounds/new/giga_impact_opponent.bin.lz");
const u32 gBattleAnimBgImage_GigaImpactPlayer[] = INCBIN_U32("graphics/battle_anims/backgrounds/new/giga_impact_player.4bpp.lz");
const u32 gBattleAnimBgPalette_GigaImpactPlayer[] = INCBIN_U32("graphics/battle_anims/backgrounds/new/giga_impact_player.gbapal.lz");
const u32 gBattleAnimBgTilemap_GigaImpactPlayer[] = INCBIN_U32("graphics/battle_anims/backgrounds/new/giga_impact_player.bin.lz");
const u32 gBattleAnimBgImage_GrassyTerrain[] = INCBIN_U32("graphics/battle_anims/backgrounds/new/grassy_terrain.4bpp.lz");
const u32 gBattleAnimBgPalette_GrassyTerrain[] = INCBIN_U32("graphics/battle_anims/backgrounds/new/grassy_terrain.gbapal.lz");
const u32 gBattleAnimBgTilemap_GrassyTerrain[] = INCBIN_U32("graphics/battle_anims/backgrounds/new/grassy_terrain.bin.lz");
@ -1497,8 +1479,6 @@ const u32 gBattleAnimBgImage_LeafStorm[] = INCBIN_U32("graphics/battle_anims/bac
const u32 gBattleAnimBgPalette_LeafStorm[] = INCBIN_U32("graphics/battle_anims/backgrounds/new/leaf_storm.gbapal.lz");
const u32 gBattleAnimBgTilemap_LeafStorm[] = INCBIN_U32("graphics/battle_anims/backgrounds/new/leaf_storm.bin.lz");
const u32 gBattleAnimBgPalette_MagicRoom[] = INCBIN_U32("graphics/battle_anims/backgrounds/new/magic_room.gbapal.lz");
const u32 gBattleAnimBgImage_MaliciousMoonsault[] = INCBIN_U32("graphics/battle_anims/backgrounds/new/malicious_moonsault.4bpp.lz");
const u32 gBattleAnimBgPalette_MaliciousMoonsault[] = INCBIN_U32("graphics/battle_anims/backgrounds/new/malicious_moonsault.gbapal.lz");
const u32 gBattleAnimBgTilemap_MaliciousMoonsault[] = INCBIN_U32("graphics/battle_anims/backgrounds/new/malicious_moonsault.bin.lz");
@ -1553,6 +1533,10 @@ const u32 gBattleAnimBgImage_TrickRoom[] = INCBIN_U32("graphics/battle_anims/bac
const u32 gBattleAnimBgPalette_TrickRoom[] = INCBIN_U32("graphics/battle_anims/backgrounds/new/trick_room.gbapal.lz");
const u32 gBattleAnimBgTilemap_TrickRoom[] = INCBIN_U32("graphics/battle_anims/backgrounds/new/trick_room.bin.lz");
const u32 gBattleAnimBgPalette_MagicRoom[] = INCBIN_U32("graphics/battle_anims/backgrounds/new/magic_room.gbapal.lz");
const u32 gBattleAnimBgPalette_WonderRoom[] = INCBIN_U32("graphics/battle_anims/backgrounds/new/wonder_room.gbapal.lz");
const u32 gBattleAnimBgImage_TwinkleTackle[] = INCBIN_U32("graphics/battle_anims/backgrounds/new/twinkle_tackle.4bpp.lz");
const u32 gBattleAnimBgPalette_TwinkleTackle[] = INCBIN_U32("graphics/battle_anims/backgrounds/new/twinkle_tackle.gbapal.lz");
const u32 gBattleAnimBgTilemap_TwinkleTackle[] = INCBIN_U32("graphics/battle_anims/backgrounds/new/twinkle_tackle.bin.lz");
@ -1565,7 +1549,8 @@ const u32 gBattleAnimBgImage_Waterfall[] = INCBIN_U32("graphics/battle_anims/bac
const u32 gBattleAnimBgPalette_Waterfall[] = INCBIN_U32("graphics/battle_anims/backgrounds/new/waterfall.gbapal.lz");
const u32 gBattleAnimBgTilemap_Waterfall[] = INCBIN_U32("graphics/battle_anims/backgrounds/new/waterfall.bin.lz");
const u32 gBattleAnimBgPalette_WonderRoom[] = INCBIN_U32("graphics/battle_anims/backgrounds/new/wonder_room.gbapal.lz");
const u32 gBattleAnimBgPalette_DarkVoid[] = INCBIN_U32("graphics/battle_anims/backgrounds/new/dark_void.gbapal.lz");
const u32 gBattleAnimBgTilemap_DarkVoid[] = INCBIN_U32("graphics/battle_anims/backgrounds/new/dark_void.bin.lz");
const u32 gBattleAnimBgImage_ZMoveActivate[] = INCBIN_U32("graphics/battle_anims/backgrounds/new/zmove_activate.4bpp.lz");
const u32 gBattleAnimBgPalette_ZMoveActivate[] = INCBIN_U32("graphics/battle_anims/backgrounds/new/zmove_activate.gbapal.lz");

View File

@ -41,6 +41,8 @@ static bool8 IsAbilityAllowingEncounter(u8 level);
// EWRAM vars
EWRAM_DATA static u8 sWildEncountersDisabled = 0;
EWRAM_DATA static u32 sFeebasRngValue = 0;
EWRAM_DATA bool8 gIsFishingEncounter = 0;
EWRAM_DATA bool8 gIsSurfingEncounter = 0;
#include "data/wild_encounters.h"
@ -652,6 +654,7 @@ bool8 StandardWildEncounter(u16 currMetaTileBehavior, u16 previousMetaTileBehavi
{
if (TryGenerateWildMon(gWildMonHeaders[headerId].waterMonsInfo, WILD_AREA_WATER, WILD_CHECK_REPEL | WILD_CHECK_KEEN_EYE) == TRUE)
{
gIsSurfingEncounter = TRUE;
if (TryDoDoubleWildBattle())
{
struct Pokemon mon1 = gEnemyParty[0];
@ -803,6 +806,7 @@ void FishingWildEncounter(u8 rod)
}
IncrementGameStat(GAME_STAT_FISHING_CAPTURES);
SetPokemonAnglerSpecies(species);
gIsFishingEncounter = TRUE;
BattleSetup_StartWildBattle();
}