Merge branch 'master' of https://github.com/rh-hideout/pokeemerald-expansion into rh-hideout-master
This commit is contained in:
commit
af2b69f7e5
@ -633,6 +633,15 @@
|
||||
"contributions": [
|
||||
"design"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "ChrispyChris27",
|
||||
"name": "ChrispyChris27",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/173648816?v=4",
|
||||
"profile": "https://github.com/ChrispyChris27",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
}
|
||||
],
|
||||
"contributorsPerLine": 7,
|
||||
|
||||
@ -43,9 +43,10 @@ body:
|
||||
label: Version
|
||||
description: What version of pokeemerald-expansion are you using?
|
||||
options:
|
||||
- 1.14.2 (Latest release)
|
||||
- 1.14.3 (Latest release)
|
||||
- master (default, unreleased bugfixes)
|
||||
- upcoming (Edge)
|
||||
- 1.14.2
|
||||
- 1.14.1
|
||||
- 1.14.0
|
||||
- 1.13.4
|
||||
|
||||
@ -43,9 +43,10 @@ body:
|
||||
label: Version
|
||||
description: What version of pokeemerald-expansion are you using?
|
||||
options:
|
||||
- 1.14.2 (Latest release)
|
||||
- 1.14.3 (Latest release)
|
||||
- master (default, unreleased bugfixes)
|
||||
- upcoming (Edge)
|
||||
- 1.14.2
|
||||
- 1.14.1
|
||||
- 1.14.0
|
||||
- 1.13.4
|
||||
|
||||
3
.github/ISSUE_TEMPLATE/04_other_errors.yaml
vendored
3
.github/ISSUE_TEMPLATE/04_other_errors.yaml
vendored
@ -43,9 +43,10 @@ body:
|
||||
label: Version
|
||||
description: What version of pokeemerald-expansion are you using?
|
||||
options:
|
||||
- 1.14.2 (Latest release)
|
||||
- 1.14.3 (Latest release)
|
||||
- master (default, unreleased bugfixes)
|
||||
- upcoming (Edge)
|
||||
- 1.14.2
|
||||
- 1.14.1
|
||||
- 1.14.0
|
||||
- 1.13.4
|
||||
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@ -52,6 +52,7 @@ src/data/debug_trainers.h
|
||||
test/battle/trainer_control.h
|
||||
tools/compresSmol/compresSmol
|
||||
tools/compresSmol/compresSmolTilemap
|
||||
tools/aif2pcm/aif2pcm
|
||||
*.Identifier
|
||||
*.smol
|
||||
*.fastSmol
|
||||
|
||||
@ -91,6 +91,7 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
|
||||
<tr>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/SabataLunar"><img src="https://avatars.githubusercontent.com/u/26584469?v=4?s=100" width="100px;" alt="SabataLunar"/><br /><sub><b>SabataLunar</b></sub></a><br /><a href="#design-SabataLunar" title="Design">🎨</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/PacFire"><img src="https://avatars.githubusercontent.com/u/108960850?v=4?s=100" width="100px;" alt="PacFire"/><br /><sub><b>PacFire</b></sub></a><br /><a href="#design-PacFire" title="Design">🎨</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/ChrispyChris27"><img src="https://avatars.githubusercontent.com/u/173648816?v=4?s=100" width="100px;" alt="ChrispyChris27"/><br /><sub><b>ChrispyChris27</b></sub></a><br /><a href="https://github.com/rh-hideout/pokeemerald-expansion/commits?author=ChrispyChris27" title="Code">💻</a></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
<tfoot>
|
||||
|
||||
@ -17,7 +17,7 @@
|
||||
If you use **`pokeemerald-expansion`**, please credit **RHH (Rom Hacking Hideout)**. Optionally, include the version number for clarity.
|
||||
|
||||
```
|
||||
Based off RHH's pokeemerald-expansion 1.14.2 https://github.com/rh-hideout/pokeemerald-expansion/
|
||||
Based off RHH's pokeemerald-expansion 1.14.3 https://github.com/rh-hideout/pokeemerald-expansion/
|
||||
```
|
||||
|
||||
Please consider [crediting all contributors](CREDITS.md) involved in the project!
|
||||
|
||||
@ -10,7 +10,7 @@
|
||||
.2byte \tag
|
||||
.endm
|
||||
|
||||
.macro createsprite template:req, anim_battler:req, subpriority_offset:req, argv:vararg
|
||||
.macro createsprite template:req, anim_battler:req, subpriority_offset:req, argv:vararg
|
||||
.byte 0x02
|
||||
.4byte \template
|
||||
.if \anim_battler == ANIM_TARGET
|
||||
@ -351,3 +351,300 @@
|
||||
createvisualtask AnimTask_IsDoubleBattle, 0
|
||||
jumprettrue \ptr
|
||||
.endm
|
||||
|
||||
@ createsprite wrappers
|
||||
@ The arguments are based on the CMD_ARGS of the callback associated with the template.
|
||||
|
||||
.macro simple_palette_blend unused_anim_battler=ANIM_ATTACKER, unused_subpriority_offset=2, selector:req, delay:req, initial_blend_y:req, target_blend_y:req, color:req
|
||||
createsprite gSimplePaletteBlendSpriteTemplate, \unused_anim_battler, \unused_subpriority_offset, \selector, \delay, \initial_blend_y, \target_blend_y, \color
|
||||
.endm
|
||||
|
||||
.macro complex_palette_blend unused_anim_battler=ANIM_ATTACKER, unused_subpriority_offset=2, selector:req, delay:req, num_blends:req, color1:req, blend_y1:req, color2:req, blend_y2:req
|
||||
createsprite gComplexPaletteBlendSpriteTemplate, \unused_anim_battler, \unused_subpriority_offset, \selector, \delay, \num_blends, \color1, \blend_y1, \color2, \blend_y2
|
||||
.endm
|
||||
|
||||
.macro shake_mon_or_platform unused_anim_battler=ANIM_ATTACKER, unused_subpriority_offset=2, velocity:req, shake_timer:req, shake_duration:req, type:req, battler_selector
|
||||
.if \type == SHAKE_MON_X || \type == SHAKE_MON_Y
|
||||
.ifb \battler_selector
|
||||
.error "battler_selector required for SHAKE_MON_X or SHAKE_MON_Y"
|
||||
.endif
|
||||
.else
|
||||
.ifnb \battler_selector
|
||||
.warning "unused battler_selector in shake_mon_or_platform"
|
||||
.endif
|
||||
.endif
|
||||
.ifb \battler_selector
|
||||
createsprite gShakeMonOrPlatformSpriteTemplate, \unused_anim_battler, \unused_subpriority_offset, \velocity, \shake_timer, \shake_duration, \type
|
||||
.else
|
||||
createsprite gShakeMonOrPlatformSpriteTemplate, \unused_anim_battler, \unused_subpriority_offset, \velocity, \shake_timer, \shake_duration, \type, \battler_selector
|
||||
.endif
|
||||
.endm
|
||||
|
||||
.macro create_megahorn_horn_sprite anim_battler:req, subpriority_offset:req, x1:req, y1:req, x2:req, y2:req, duration:req
|
||||
createsprite gMegahornHornSpriteTemplate, \anim_battler, \subpriority_offset, \x1, \y1, \x2, \y2, \duration
|
||||
.endm
|
||||
|
||||
.macro create_leech_life_needle_sprite anim_battler:req, subpriority_offset:req, x:req, y:req, duration:req
|
||||
createsprite gLeechLifeNeedleSpriteTemplate, \anim_battler, \subpriority_offset, \x, \y, \duration
|
||||
.endm
|
||||
|
||||
.macro create_web_thread_sprite anim_battler:req, subpriority_offset:req, x:req, y:req, unk2:req, amplitude:req, targets_both:req
|
||||
createsprite gWebThreadSpriteTemplate, \anim_battler, \subpriority_offset, \x, \y, \unk2, \amplitude, \targets_both
|
||||
.endm
|
||||
|
||||
.macro create_string_wrap_sprite anim_battler:req, subpriority_offset:req, x:req, y:req
|
||||
createsprite gStringWrapSpriteTemplate, \anim_battler, \subpriority_offset, \x, \y
|
||||
.endm
|
||||
|
||||
.macro create_linear_stinger_sprite anim_battler:req, subpriority_offset:req, initial_x:req, initial_y:req, target_x:req, target_y:req, duration:req
|
||||
createsprite gLinearStingerSpriteTemplate, \anim_battler, \subpriority_offset, \initial_x, \initial_y, \target_x, \target_y, \duration
|
||||
.endm
|
||||
|
||||
.macro create_pin_missile_sprite anim_battler:req, subpriority_offset:req, initial_x:req, initial_y:req, target_x:req, target_y:req, duration:req, wave_amplitude:req
|
||||
createsprite gPinMissileSpriteTemplate, \anim_battler, \subpriority_offset, \initial_x, \initial_y, \target_x, \target_y, \duration, \wave_amplitude
|
||||
.endm
|
||||
|
||||
.macro create_tail_glow_orb_sprite anim_battler:req, subpriority_offset:req, relative_to:req
|
||||
createsprite gTailGlowOrbSpriteTemplate, \anim_battler, \subpriority_offset, \relative_to
|
||||
.endm
|
||||
|
||||
.macro create_sharp_teeth_sprite anim_battler:req, subpriority_offset:req, x:req, y:req, animation:req, x_velocity:req, y_velocity:req, half_duration:req
|
||||
createsprite gSharpTeethSpriteTemplate, \anim_battler, \subpriority_offset, \x, \y, \animation, 256 * \x_velocity, 256 * \y_velocity, \half_duration
|
||||
.endm
|
||||
|
||||
.macro create_clamp_jaw_sprite anim_battler:req, subpriority_offset:req, x:req, y:req, animation:req, x_velocity:req, y_velocity:req, half_duration:req
|
||||
createsprite gClampJawSpriteTemplate, \anim_battler, \subpriority_offset, \x, \y, \animation, 256 * \x_velocity, 256 * \y_velocity, \half_duration
|
||||
.endm
|
||||
|
||||
.macro create_tear_drop_sprite anim_battler:req, subpriority_offset:req, relative_to:req, type:req
|
||||
createsprite gTearDropSpriteTemplate, \anim_battler, \subpriority_offset, \relative_to, \type
|
||||
.endm
|
||||
|
||||
.macro create_claw_slash_sprite anim_battler:req, subpriority_offset:req, x:req, y:req, animation:req
|
||||
createsprite gClawSlashSpriteTemplate, \anim_battler, \subpriority_offset, \x, \y, \animation
|
||||
.endm
|
||||
|
||||
.macro create_outrage_flame_sprite anim_battler:req, subpriority_offset:req, x:req, y:req, duration:req, x_velocity:req, y_velocity:req, flicker_duration:req
|
||||
createsprite gOutrageFlameSpriteTemplate, \anim_battler, \subpriority_offset, \x, \y, \duration, 256 * \x_velocity, 256 * \y_velocity, \flicker_duration
|
||||
.endm
|
||||
|
||||
.macro create_dragon_breath_fire_sprite anim_battler:req, subpriority_offset:req, initial_x:req, initial_y:req, target_x:req, target_y:req, duration:req
|
||||
createsprite gDragonBreathFireSpriteTemplate, \anim_battler, \subpriority_offset, \initial_x, \initial_y, \target_x, \target_y, \duration
|
||||
.endm
|
||||
|
||||
.macro create_dragon_rage_fire_spit_sprite anim_battler:req, subpriority_offset:req, initial_x:req, initial_y:req, target_x:req, target_y:req, duration:req
|
||||
createsprite gDragonRageFireSpitSpriteTemplate, \anim_battler, \subpriority_offset, \initial_x, \initial_y, \target_x, \target_y, \duration
|
||||
.endm
|
||||
|
||||
.macro create_dragon_rage_fire_plume_sprite anim_battler:req, subpriority_offset:req, relative_to:req, x:req, y:req
|
||||
createsprite gDragonRageFirePlumeSpriteTemplate, \anim_battler, \subpriority_offset, \relative_to, \x, \y
|
||||
.endm
|
||||
|
||||
.macro create_dragon_dance_orb_sprite anim_battler:req, subpriority_offset:req, angle:req
|
||||
createsprite gDragonDanceOrbSpriteTemplate, \anim_battler, \subpriority_offset, 256 * \angle
|
||||
.endm
|
||||
|
||||
.macro create_overheat_flame_sprite anim_battler:req, subpriority_offset:req, speed:req, unk1:req, unk2:req, duration:req, y:req
|
||||
createsprite gOverheatFlameSpriteTemplate, \anim_battler, \subpriority_offset, \speed, \unk1, \unk2, \duration, \y
|
||||
.endm
|
||||
|
||||
.macro create_sleep_powder_particle_sprite anim_battler:req, subpriority_offset:req, x:req, y:req, duration:req, y_velocity:req, wave_amplitude:req, wave_speed:req
|
||||
createsprite gSleepPowderParticleSpriteTemplate, \anim_battler, \subpriority_offset, \x, \y, \duration, 256 * \y_velocity, \wave_amplitude, \wave_speed
|
||||
.endm
|
||||
|
||||
.macro create_stun_spore_particle_sprite anim_battler:req, subpriority_offset:req, x:req, y:req, duration:req, y_velocity:req, wave_amplitude:req, wave_speed:req
|
||||
createsprite gStunSporeParticleSpriteTemplate, \anim_battler, \subpriority_offset, \x, \y, \duration, 256 * \y_velocity, \wave_amplitude, \wave_speed
|
||||
.endm
|
||||
|
||||
.macro create_poison_powder_particle_sprite anim_battler:req, subpriority_offset:req, x:req, y:req, duration:req, y_velocity:req, wave_amplitude:req, wave_speed:req
|
||||
createsprite gPoisonPowderParticleSpriteTemplate, \anim_battler, \subpriority_offset, \x, \y, \duration, 256 * \y_velocity, \wave_amplitude, \wave_speed
|
||||
.endm
|
||||
|
||||
.macro create_power_absorption_orb_sprite anim_battler:req, subpriority_offset:req, x:req, y:req, duration:req
|
||||
createsprite gPowerAbsorptionOrbSpriteTemplate, \anim_battler, \subpriority_offset, \x, \y, \duration
|
||||
.endm
|
||||
|
||||
.macro create_stockpile_absorption_orb_sprite anim_battler:req, subpriority_offset:req, x:req, y:req, duration:req
|
||||
createsprite gStockpileAbsorptionOrbSpriteTemplate, \anim_battler, \subpriority_offset, \x, \y, \duration
|
||||
.endm
|
||||
|
||||
.macro create_solar_beam_big_orb_sprite anim_battler:req, subpriority_offset:req, x:req, y:req, duration:req, animation:req
|
||||
createsprite gSolarBeamBigOrbSpriteTemplate, \anim_battler, \subpriority_offset, \x, \y, \duration, \animation
|
||||
.endm
|
||||
|
||||
.macro create_absorption_orb_sprite anim_battler:req, subpriority_offset:req, x:req, y:req, wave_amplitude:req, wave_period:req
|
||||
createsprite gAbsorptionOrbSpriteTemplate, \anim_battler, \subpriority_offset, \x, \y, \wave_amplitude, \wave_period
|
||||
.endm
|
||||
|
||||
.macro create_hyper_beam_orb_sprite anim_battler:req, subpriority_offset:req
|
||||
createsprite gHyperBeamOrbSpriteTemplate, \anim_battler, \subpriority_offset
|
||||
.endm
|
||||
|
||||
.macro createleechseedsprite anim_battler:req, subpriority_offset:req, initial_x:req, initial_y:req, target_x:req, target_y:req, duration:req, wave_amplitude:req
|
||||
createsprite gLeechSeedSpriteTemplate, \anim_battler, \subpriority_offset, \initial_x, \initial_y, \target_x, \target_y, \duration, \wave_amplitude
|
||||
.endm
|
||||
|
||||
.macro create_spore_particle_sprite anim_battler:req, subpriority_offset:req, x:req, y:req, wave_offset:req, duration:req, blend:req
|
||||
createsprite gSporeParticleSpriteTemplate, \anim_battler, \subpriority_offset, \x, \y, \wave_offset, \duration, \blend
|
||||
.endm
|
||||
|
||||
.macro create_petal_dance_big_flower_sprite anim_battler:req, subpriority_offset:req, initial_x:req, initial_y:req, target_y:req, duration:req
|
||||
createsprite gPetalDanceBigFlowerSpriteTemplate, \anim_battler, \subpriority_offset, \initial_x, \initial_y, \target_y, \duration
|
||||
.endm
|
||||
|
||||
.macro create_petal_dance_small_flower_sprite anim_battler:req, subpriority_offset:req, initial_x:req, initial_y:req, target_y:req, duration:req
|
||||
createsprite gPetalDanceSmallFlowerSpriteTemplate, \anim_battler, \subpriority_offset, \initial_x, \initial_y, \target_y, \duration
|
||||
.endm
|
||||
|
||||
.macro create_razor_leaf_particle_sprite anim_battler:req, subpriority_offset:req, upward_delta_x:req, upward_delta_y:req, upward_duration:req
|
||||
createsprite gRazorLeafParticleSpriteTemplate, \anim_battler, \subpriority_offset, \upward_delta_x, \upward_delta_y, \upward_duration
|
||||
.endm
|
||||
|
||||
.macro create_razor_leaf_cutter_sprite anim_battler:req, subpriority_offset:req, initial_x:req, initial_y:req, target_x:req, target_y:req, duration:req, wave_amplitude:req, target_both:req
|
||||
createsprite gRazorLeafCutterSpriteTemplate, \anim_battler, \subpriority_offset, \initial_x, \initial_y, \target_x, \target_y, \duration, \wave_amplitude, \target_both
|
||||
.endm
|
||||
|
||||
.macro create_swift_star_sprite anim_battler:req, subpriority_offset:req, initial_x:req, initial_y:req, target_x:req, target_y:req, duration:req, wave_amplitude:req, target_both:req
|
||||
createsprite gSwiftStarSpriteTemplate, \anim_battler, \subpriority_offset, \initial_x, \initial_y, \target_x, \target_y, \duration, \wave_amplitude, \target_both
|
||||
.endm
|
||||
|
||||
.macro create_twister_leaf_sprite anim_battler:req, subpriority_offset:req, duration:req, distance_y:req, wave_period:req, wave_amplitude:req, speed_up_on_frame:req
|
||||
createsprite gTwisterLeafSpriteTemplate, \anim_battler, \subpriority_offset, \duration, \distance_y, \wave_period, \wave_amplitude, \speed_up_on_frame
|
||||
.endm
|
||||
|
||||
.macro create_constrict_binding_sprite anim_battler:req, subpriority_offset:req, initial_x:req, initial_y:req, affine_animation:req, squeezes:req
|
||||
createsprite gConstrictBindingSpriteTemplate, \anim_battler, \subpriority_offset, \initial_x, \initial_y, \affine_animation, \squeezes
|
||||
.endm
|
||||
|
||||
.macro create_mimic_orb_sprite anim_battler:req, subpriority_offset:req, initial_x:req, initial_y:req
|
||||
createsprite gMimicOrbSpriteTemplate, \anim_battler, \subpriority_offset, \initial_x, \initial_y
|
||||
.endm
|
||||
|
||||
.macro create_ingrain_root_sprite anim_battler:req, subpriority_offset:req, offset_x:req, offset_y:req, subpriority:req, animation:req, duration:req
|
||||
createsprite gIngrainRootSpriteTemplate, \anim_battler, \subpriority_offset, \offset_x, \offset_y, \subpriority - 30, \animation, \duration
|
||||
.endm
|
||||
|
||||
.macro create_frenzy_plant_root_sprite anim_battler:req, subpriority_offset:req, interpolate_percent:req, offset_x:req, offset_y:req, subpriority:req, animation:req, duration:req
|
||||
createsprite gFrenzyPlantRootSpriteTemplate, \anim_battler, \subpriority_offset, \interpolate_percent, \offset_x, \offset_y, \subpriority - 30, \animation, \duration
|
||||
.endm
|
||||
|
||||
.macro create_ingrain_orb_sprite anim_battler:req, subpriority_offset:req, initial_x:req, initial_y:req, velocity_x:req, wave_amplitude:req, duration:req
|
||||
createsprite gIngrainOrbSpriteTemplate, \anim_battler, \subpriority_offset, \initial_x, \initial_y, \velocity_x, \wave_amplitude, \duration
|
||||
.endm
|
||||
|
||||
.macro create_present_sprite anim_battler:req, subpriority_offset:req, initial_x:req, initial_y:req, unk2:req, unk3:req, unk4:req
|
||||
createsprite gPresentSpriteTemplate, \anim_battler, \subpriority_offset, \initial_x, \initial_y, \unk2, \unk3, \unk4
|
||||
.endm
|
||||
|
||||
.macro create_present_heal_particle_sprite anim_battler:req, subpriority_offset:req, initial_x:req, initial_y:req, velocity_y:req, unused3=1
|
||||
createsprite gPresentHealParticleSpriteTemplate, \anim_battler, \subpriority_offset, \initial_x, \initial_y, \velocity_y, \unused3
|
||||
.endm
|
||||
|
||||
.macro create_item_steal_sprite anim_battler:req, subpriority_offset:req, initial_x:req, initial_y:req, unk2, unk3, unk4
|
||||
createsprite gItemStealSpriteTemplate, \anim_battler, \subpriority_offset, \initial_x, \initial_y, \unk2, \unk3, \unk4
|
||||
.endm
|
||||
|
||||
.macro create_trick_bag_sprite anim_battler:req, subpriority_offset:req, initial_y:req, wave_offset:req
|
||||
createsprite gTrickBagSpriteTemplate, \anim_battler, \subpriority_offset, \initial_y, \wave_offset
|
||||
.endm
|
||||
|
||||
.macro create_confusion_duck_sprite anim_battler:req, subpriority_offset:req, x:req, y:req, wave_offset:req, wave_period:req, duration:req
|
||||
createsprite gConfusionDuckSpriteTemplate, \anim_battler, \subpriority_offset, \x, \y, \wave_offset, \wave_period, \duration
|
||||
.endm
|
||||
|
||||
.macro create_basic_hitsplat_sprite anim_battler:req, subpriority_offset:req, x:req, y:req, relative_to:req, animation:req
|
||||
createsprite gBasicHitSplatSpriteTemplate, \anim_battler, \subpriority_offset, \x, \y, \relative_to, \animation
|
||||
.endm
|
||||
|
||||
.macro create_persist_hitsplat_sprite anim_battler:req, subpriority_offset:req, x:req, y:req, relative_to:req, animation:req, duration:req
|
||||
createsprite gPersistHitSplatSpriteTemplate, \anim_battler, \subpriority_offset, \x, \y, \relative_to, \animation, \duration
|
||||
.endm
|
||||
|
||||
.macro create_handle_invert_hitsplat_sprite anim_battler:req, subpriority_offset:req, x:req, y:req, relative_to:req, animation:req
|
||||
createsprite gHandleInvertHitSplatSpriteTemplate, \anim_battler, \subpriority_offset, \x, \y, \relative_to, \animation
|
||||
.endm
|
||||
|
||||
.macro create_random_pos_hitsplat_sprite anim_battler:req, subpriority_offset:req, relative_to:req, animation
|
||||
.ifnb \animation
|
||||
createsprite gRandomPosHitSplatSpriteTemplate, \anim_battler, \subpriority_offset, \relative_to, \animation
|
||||
.else
|
||||
createsprite gRandomPosHitSplatSpriteTemplate, \anim_battler, \subpriority_offset, \relative_to, -1
|
||||
.endif
|
||||
.endm
|
||||
|
||||
.macro create_mon_edge_hitsplat_sprite anim_battler:req, subpriority_offset:req, relative_to:req, x:req, y:req, animation:req
|
||||
createsprite gMonEdgeHitSplatSpriteTemplate, \anim_battler, \subpriority_offset, \relative_to, \x, \y, \animation
|
||||
.endm
|
||||
|
||||
.macro create_cross_impact_sprite anim_battler:req, subpriority_offset:req, x:req, y:req, relative_to:req, duration:req
|
||||
createsprite gCrossImpactSpriteTemplate, \anim_battler, \subpriority_offset, \x, \y, \relative_to, \duration
|
||||
.endm
|
||||
|
||||
.macro create_flashing_hitsplat_sprite anim_battler:req, subpriority_offset:req, x:req, y:req, relative_to:req, animation:req
|
||||
createsprite gFlashingHitSplatSpriteTemplate, \anim_battler, \subpriority_offset, \x, \y, \relative_to, \animation
|
||||
.endm
|
||||
|
||||
@ createvisualtask wrappers
|
||||
@ The arguments are based on the CMD_ARGS of the task.
|
||||
|
||||
.macro metallic_shine priority=5, permanent:req, color
|
||||
.ifb \color
|
||||
createvisualtask AnimTask_MetallicShine, \priority, \permanent, FALSE, RGB_BLACK
|
||||
.else
|
||||
createvisualtask AnimTask_MetallicShine, \priority, \permanent, TRUE, \color
|
||||
.endif
|
||||
.endm
|
||||
|
||||
.macro set_grayscale_pal priority=5, battler:req
|
||||
createvisualtask AnimTask_SetGrayscaleOrOriginalPal, \priority, \battler, FALSE
|
||||
.endm
|
||||
|
||||
.macro set_original_pal priority=5, battler:req
|
||||
createvisualtask AnimTask_SetGrayscaleOrOriginalPal, \priority, \battler, TRUE
|
||||
.endm
|
||||
|
||||
.macro attacker_fade_to_invisible priority=2, step_delay:req
|
||||
createvisualtask AnimTask_AttackerFadeToInvisible, \priority, \step_delay
|
||||
.endm
|
||||
|
||||
.macro attacker_fade_from_invisible priority=2, step_delay:req
|
||||
createvisualtask AnimTask_AttackerFadeFromInvisible, \priority, \step_delay
|
||||
.endm
|
||||
|
||||
.macro shrink_target_copy priority=5, unk0:req, unk1:req
|
||||
createvisualtask AnimTask_ShrinkTargetCopy, \priority, \unk0, \unk1
|
||||
.endm
|
||||
|
||||
.macro create_leaf_blade_task priority=5
|
||||
createvisualtask AnimTask_LeafBlade, \priority
|
||||
.endm
|
||||
|
||||
.macro blend_color_cycle priority=2, selector:req, delay:req, num_blends:req, initial_blend_y:req, target_blend_y:req, color:req
|
||||
createvisualtask AnimTask_BlendColorCycle, \priority, \selector, \delay, \num_blends, \initial_blend_y, \target_blend_y, \color
|
||||
.endm
|
||||
|
||||
.macro blend_color_cycleexclude priority=2, unk0:req, delay:req, num_blends:req, initial_blend_y:req, target_blend_y:req, color:req
|
||||
createvisualtask AnimTask_BlendColorCycleExclude, \priority, \unk0, \delay, \num_blends, \initial_blend_y, \target_blend_y, \color
|
||||
.endm
|
||||
|
||||
.macro blend_color_cyclebytag priority=2, tag:req, delay:req, num_blends:req, initial_blend_y:req, target_blend_y:req, color:req
|
||||
createvisualtask AnimTask_BlendColorCycleByTag, \priority, \tag, \delay, \num_blends, \initial_blend_y, \target_blend_y, \color
|
||||
.endm
|
||||
|
||||
.macro flash_anim_tag_with_color priority=2, tag:req, delay:req, num_blends:req, color1:req, blend_y1:req, color2:req, blend_y2:req
|
||||
createvisualtask AnimTask_FlashAnimTagWithColor, \priority, \tag, \delay, \num_blends, \color1, \blend_y1, \color2, \blend_y2
|
||||
.endm
|
||||
|
||||
@ NOTE: This function is different on expansion compared to pret
|
||||
.macro invert_screen_color priority=2, scenery:req
|
||||
@ NOTE: These generate 0x000 or 0x101 to match, but the code checks for '& 0x100'.
|
||||
createvisualtask AnimTask_InvertScreenColor, \priority, \scenery
|
||||
.endm
|
||||
|
||||
.macro tint_palettes priority=2, scenery:req, attacker:req, target:req, duration:req, color:req
|
||||
createvisualtask AnimTask_TintPalettes, \priority, \scenery << 8, \attacker << 8, \target << 8, \duration, \color & 0x1F, (\color >> 5) & 0x1F, (\color >> 10) & 0x1F
|
||||
.endm
|
||||
|
||||
.macro shake_battle_platforms priority=2, x_offset:req, y_offset:req, shakes:req, delay:req
|
||||
createvisualtask AnimTask_ShakeBattlePlatforms, \priority, \x_offset, \y_offset, \shakes, \delay
|
||||
.endm
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -1185,7 +1185,7 @@ BattleScript_EffectPartingShotTrySpAtk:
|
||||
statbuffchange BS_TARGET, STAT_CHANGE_ALLOW_PTR, BattleScript_EffectPartingShotMaybeSwitch
|
||||
call BattleScript_EffectPartingShotMaybePrintStat
|
||||
BattleScript_EffectPartingShotMaybeSwitch:
|
||||
jumpifgenconfiglowerthan CONFIG_PARTING_SHOT_SWITCH, GEN_7, BattleScript_EffectPartingShotSwitch
|
||||
jumpifgenconfiglowerthan CONFIG_B_PARTING_SHOT_SWITCH, GEN_7, BattleScript_EffectPartingShotSwitch
|
||||
jumpifbyte CMP_NOT_EQUAL, sB_ANIM_TARGETS_HIT, 0, BattleScript_EffectPartingShotSwitch
|
||||
goto BattleScript_MoveEnd
|
||||
|
||||
@ -1534,7 +1534,7 @@ BattleScript_EffectHitEnemyHealAlly::
|
||||
BattleScript_EffectDefog::
|
||||
setstatchanger STAT_EVASION, 1, TRUE
|
||||
attackcanceler
|
||||
jumpifgenconfiglowerthan CONFIG_DEFOG_EFFECT_CLEARING, GEN_5, BattleScript_DefogAfterSubstituteCheck
|
||||
jumpifgenconfiglowerthan CONFIG_B_DEFOG_EFFECT_CLEARING, GEN_5, BattleScript_DefogAfterSubstituteCheck
|
||||
jumpifsubstituteblocks BattleScript_DefogIfCanClearHazards
|
||||
BattleScript_DefogAfterSubstituteCheck:
|
||||
jumpifstat BS_TARGET, CMP_NOT_EQUAL, STAT_EVASION, MIN_STAT_STAGE, BattleScript_DefogWorks
|
||||
@ -1542,7 +1542,7 @@ BattleScript_DefogIfCanClearHazards:
|
||||
trydefog FALSE, BattleScript_ButItFailed
|
||||
BattleScript_DefogWorks:
|
||||
accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE
|
||||
jumpifgenconfiglowerthan CONFIG_DEFOG_EFFECT_CLEARING, GEN_5, BattleScript_DefogWorksAfterSubstituteCheck
|
||||
jumpifgenconfiglowerthan CONFIG_B_DEFOG_EFFECT_CLEARING, GEN_5, BattleScript_DefogWorksAfterSubstituteCheck
|
||||
jumpifsubstituteblocks BattleScript_DefogTryHazardsWithAnim
|
||||
BattleScript_DefogWorksAfterSubstituteCheck:
|
||||
statbuffchange BS_TARGET, STAT_CHANGE_ALLOW_PTR | STAT_CHANGE_ONLY_CHECKING, BattleScript_DefogTryHazardsWithAnim
|
||||
@ -2071,7 +2071,7 @@ BattleScript_EffectHealingWish::
|
||||
setatkhptozero
|
||||
tryfaintmon BS_ATTACKER
|
||||
storehealingwish BS_ATTACKER
|
||||
jumpifgenconfiglowerthan CONFIG_HEALING_WISH_SWITCH, GEN_5, BattleScript_EffectHealingWishGen4
|
||||
jumpifgenconfiglowerthan CONFIG_B_HEALING_WISH_SWITCH, GEN_5, BattleScript_EffectHealingWishGen4
|
||||
BattleScript_EffectHealingWishEnd:
|
||||
moveendall
|
||||
end
|
||||
@ -2357,7 +2357,7 @@ BattleScript_TryTailwindAbilitiesLoop_WindPower:
|
||||
BattleScript_EffectMiracleEye::
|
||||
attackcanceler
|
||||
accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE
|
||||
jumpifgenconfiglowerthan CONFIG_MIRACLE_EYE_FAIL, GEN_5, BattleScript_MiracleEyeSet
|
||||
jumpifgenconfiglowerthan CONFIG_B_MIRACLE_EYE_FAIL, GEN_5, BattleScript_MiracleEyeSet
|
||||
jumpifvolatile BS_TARGET, VOLATILE_MIRACLE_EYE, BattleScript_ButItFailed
|
||||
BattleScript_MiracleEyeSet:
|
||||
setvolatile BS_TARGET, VOLATILE_MIRACLE_EYE
|
||||
@ -3380,7 +3380,7 @@ BattleScript_EffectMeanLook::
|
||||
accuracycheck BattleScript_ButItFailed, NO_ACC_CALC_CHECK_LOCK_ON
|
||||
jumpifvolatile BS_TARGET, VOLATILE_ESCAPE_PREVENTION, BattleScript_ButItFailed
|
||||
jumpifsubstituteblocks BattleScript_ButItFailed
|
||||
jumpifgenconfiglowerthan CONFIG_GHOSTS_ESCAPE, GEN_6, BattleScript_EffectMeanLookGen5
|
||||
jumpifgenconfiglowerthan CONFIG_B_GHOSTS_ESCAPE, GEN_6, BattleScript_EffectMeanLookGen5
|
||||
jumpiftype BS_TARGET, TYPE_GHOST, BattleScript_ButItFailed
|
||||
BattleScript_EffectMeanLookGen5:
|
||||
attackanimation
|
||||
@ -3393,6 +3393,7 @@ BattleScript_EffectMeanLookGen5:
|
||||
BattleScript_EffectNightmare::
|
||||
attackcanceler
|
||||
jumpifsubstituteblocks BattleScript_ButItFailed
|
||||
accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE
|
||||
jumpifvolatile BS_TARGET, VOLATILE_NIGHTMARE, BattleScript_ButItFailed
|
||||
jumpifstatus BS_TARGET, STATUS1_SLEEP, BattleScript_NightmareWorked
|
||||
jumpifability BS_TARGET, ABILITY_COMATOSE, BattleScript_NightmareWorked
|
||||
@ -3408,7 +3409,7 @@ BattleScript_NightmareWorked::
|
||||
BattleScript_EffectMinimize::
|
||||
attackcanceler
|
||||
setvolatile BS_ATTACKER, VOLATILE_MINIMIZE
|
||||
jumpifgenconfiglowerthan CONFIG_MINIMIZE_EVASION, GEN_5, BattleScript_EffectMinimizeGen4
|
||||
jumpifgenconfiglowerthan CONFIG_B_MINIMIZE_EVASION, GEN_5, BattleScript_EffectMinimizeGen4
|
||||
setstatchanger STAT_EVASION, 2, FALSE
|
||||
goto BattleScript_EffectStatUpAfterAtkCanceler
|
||||
BattleScript_EffectMinimizeGen4:
|
||||
@ -3482,8 +3483,8 @@ BattleScript_EffectSpikes::
|
||||
BattleScript_EffectForesight::
|
||||
attackcanceler
|
||||
accuracycheck BattleScript_ButItFailed, NO_ACC_CALC_CHECK_LOCK_ON
|
||||
jumpifgenconfiglowerthan CONFIG_FORESIGHT_FAIL, GEN_3, BattleScript_ForesightFailCheck
|
||||
jumpifgenconfiglowerthan CONFIG_FORESIGHT_FAIL, GEN_5, BattleScript_ForesightSet
|
||||
jumpifgenconfiglowerthan CONFIG_B_FORESIGHT_FAIL, GEN_3, BattleScript_ForesightFailCheck
|
||||
jumpifgenconfiglowerthan CONFIG_B_FORESIGHT_FAIL, GEN_5, BattleScript_ForesightSet
|
||||
BattleScript_ForesightFailCheck:
|
||||
jumpifvolatile BS_TARGET, VOLATILE_FORESIGHT, BattleScript_ButItFailed
|
||||
BattleScript_ForesightSet:
|
||||
@ -3767,6 +3768,7 @@ BattleScript_EffectBellyDrum::
|
||||
|
||||
BattleScript_EffectPsychUp::
|
||||
attackcanceler
|
||||
accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE
|
||||
copyfoestats
|
||||
attackanimation
|
||||
waitanimation
|
||||
@ -3793,7 +3795,7 @@ BattleScript_EffectFutureSight::
|
||||
goto BattleScript_MoveEnd
|
||||
|
||||
BattleScript_EffectTeleport::
|
||||
jumpifgenconfiglowerthan CONFIG_TELEPORT_BEHAVIOR, GEN_8, BattleScript_EffectTeleportGen7
|
||||
jumpifgenconfiglowerthan CONFIG_B_TELEPORT_BEHAVIOR, GEN_8, BattleScript_EffectTeleportGen7
|
||||
jumpifbattletype BATTLE_TYPE_TRAINER, BattleScript_EffectBatonPass
|
||||
jumpifside BS_ATTACKER, B_SIDE_PLAYER, BattleScript_EffectBatonPass
|
||||
goto BattleScript_DoEffectTeleport
|
||||
@ -3812,7 +3814,7 @@ BattleScript_DoEffectTeleport::
|
||||
goto BattleScript_MoveEnd
|
||||
|
||||
BattleScript_EffectBeatUp::
|
||||
jumpifgenconfiglowerthan CONFIG_BEAT_UP, GEN_5, BattleScript_EffectBeatUpGen3
|
||||
jumpifgenconfiglowerthan CONFIG_B_BEAT_UP, GEN_5, BattleScript_EffectBeatUpGen3
|
||||
goto BattleScript_EffectHit
|
||||
|
||||
BattleScript_EffectBeatUpGen3:
|
||||
@ -5972,7 +5974,7 @@ BattleScript_CudChewActivates::
|
||||
end2
|
||||
|
||||
BattleScript_ApplyDisguiseFormChangeHPLoss::
|
||||
jumpifgenconfiglowerthan CONFIG_DISGUISE_HP_LOSS, GEN_8, BattleScript_ApplyDisguiseFormChangeHPLossReturn
|
||||
jumpifgenconfiglowerthan CONFIG_B_DISGUISE_HP_LOSS, GEN_8, BattleScript_ApplyDisguiseFormChangeHPLossReturn
|
||||
healthbarupdate BS_SCRIPTING, PASSIVE_HP_UPDATE
|
||||
datahpupdate BS_SCRIPTING, PASSIVE_HP_UPDATE
|
||||
BattleScript_ApplyDisguiseFormChangeHPLossReturn:
|
||||
@ -7336,7 +7338,7 @@ BattleScript_WeakArmorDefPrintString:
|
||||
printstring STRINGID_TARGETABILITYSTATLOWER
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
BattleScript_WeakArmorActivatesSpeed:
|
||||
jumpifgenconfiglowerthan CONFIG_WEAK_ARMOR_SPEED, GEN_7, BattleScript_WeakArmorSetSpeedGen6
|
||||
jumpifgenconfiglowerthan CONFIG_B_WEAK_ARMOR_SPEED, GEN_7, BattleScript_WeakArmorSetSpeedGen6
|
||||
setstatchanger STAT_SPEED, 2, FALSE
|
||||
goto BattleScript_WeakArmorDoSpeed
|
||||
BattleScript_WeakArmorSetSpeedGen6:
|
||||
|
||||
@ -44,6 +44,7 @@
|
||||
- [Vs. Seeker](tutorials/vs_seeker.md)
|
||||
- [Changelog](./CHANGELOG.md)
|
||||
- [1.14.x]()
|
||||
- [Version 1.14.3](changelogs/1.14.x/1.14.3.md)
|
||||
- [Version 1.14.2](changelogs/1.14.x/1.14.2.md)
|
||||
- [Version 1.14.1](changelogs/1.14.x/1.14.1.md)
|
||||
- [Version 1.14.0](changelogs/1.14.x/1.14.0.md)
|
||||
|
||||
170
docs/changelogs/1.14.x/1.14.3.md
Normal file
170
docs/changelogs/1.14.x/1.14.3.md
Normal file
@ -0,0 +1,170 @@
|
||||
```md
|
||||
## How to update
|
||||
- If you haven't set up a remote, run the command `git remote add RHH https://github.com/rh-hideout/pokeemerald-expansion`.
|
||||
- Once you have your remote set up, run the command `git pull RHH expansion/1.14.3
|
||||
`.
|
||||
```
|
||||
|
||||
|
||||
## 🧬 General 🧬
|
||||
### Changed
|
||||
* Misc style and whitespace cleanup by @grintoul1 in [#8681](https://github.com/rh-hideout/pokeemerald-expansion/pull/8681)
|
||||
* Disable L button config (throw ball shortcut or move description) when there is overlap with L=A option by @FosterProgramming in [#8332](https://github.com/rh-hideout/pokeemerald-expansion/pull/8332)
|
||||
* Update CONTRIBUTING.md by @pkmnsnfrn in [#8879](https://github.com/rh-hideout/pokeemerald-expansion/pull/8879)
|
||||
* Deleted unnecessary files by @Bassoonian in [#8899](https://github.com/rh-hideout/pokeemerald-expansion/pull/8899)
|
||||
* Fix Metronome bans by @amiosi in [#8834](https://github.com/rh-hideout/pokeemerald-expansion/pull/8834)
|
||||
* Move CMD_ARGS to battle_script_commands by @hedara90 in [#8974](https://github.com/rh-hideout/pokeemerald-expansion/pull/8974)
|
||||
- `CMD_ARGS` for battle scripts now only exist in `src/battle_script_commands.c`
|
||||
* Pret merge (20th of January, 2026) by @hedara90 in [#8973](https://github.com/rh-hideout/pokeemerald-expansion/pull/8973)
|
||||
* Remove trailing whitespace - Master by @AsparagusEduardo in [#9011](https://github.com/rh-hideout/pokeemerald-expansion/pull/9011)
|
||||
* fix: updated rulings about big feature label by @pkmnsnfrn in [#9027](https://github.com/rh-hideout/pokeemerald-expansion/pull/9027)
|
||||
* Add aif2pcm to gitignore by @hedara90 in [#9077](https://github.com/rh-hideout/pokeemerald-expansion/pull/9077)
|
||||
|
||||
### Fixed
|
||||
* Add check to warn of a non-working config setup by @FosterProgramming in [#8686](https://github.com/rh-hideout/pokeemerald-expansion/pull/8686)
|
||||
* Various sprite visualizer fixes if configs disabled by @kittenchilly in [#8697](https://github.com/rh-hideout/pokeemerald-expansion/pull/8697)
|
||||
* Fix trade evo with partner by @FosterProgramming in [#8857](https://github.com/rh-hideout/pokeemerald-expansion/pull/8857)
|
||||
* Fixed Acc value shadow cut off when Accuracy = 100 by @montmoguri in [#8886](https://github.com/rh-hideout/pokeemerald-expansion/pull/8886)
|
||||
* Fix vivillon icy snow icon by @FosterProgramming in [#8970](https://github.com/rh-hideout/pokeemerald-expansion/pull/8970)
|
||||
* Fix premier ball wrong data size by @FosterProgramming in [#8979](https://github.com/rh-hideout/pokeemerald-expansion/pull/8979)
|
||||
* Fixes creation of certain overworld sprites in object_event_pic_tables_followers.h by @ChrispyChris27 in [#9065](https://github.com/rh-hideout/pokeemerald-expansion/pull/9065)
|
||||
|
||||
## 🗺️ Overworld 🗺️
|
||||
### Fixed
|
||||
* Fix teleport location by @cawtds in [#8941](https://github.com/rh-hideout/pokeemerald-expansion/pull/8941)
|
||||
* Fix substitute follower appearing with dead party by @FosterProgramming in [#9028](https://github.com/rh-hideout/pokeemerald-expansion/pull/9028)
|
||||
* Fix berry tree spawning with max yield when OW_BERRY_ALWAYS_WATERABLE is active by @FosterProgramming in [#8976](https://github.com/rh-hideout/pokeemerald-expansion/pull/8976)
|
||||
* Fix debug menu using female icon with male palette by @FosterProgramming in [#9092](https://github.com/rh-hideout/pokeemerald-expansion/pull/9092)
|
||||
|
||||
## 🐉 Pokémon 🐉
|
||||
### Changed
|
||||
* Miscellaneous species_info Changes by @amiosi in [#8462](https://github.com/rh-hideout/pokeemerald-expansion/pull/8462)
|
||||
|
||||
### Fixed
|
||||
* Fix in-battle form changes always reverting by @AsparagusEduardo in [#8810](https://github.com/rh-hideout/pokeemerald-expansion/pull/8810)
|
||||
* Fix typo in Salazzle form species ID table reference by @ostomachion in [#8904](https://github.com/rh-hideout/pokeemerald-expansion/pull/8904)
|
||||
* Mega Gardevoir should always be Fairy-type by @amiosi in [#8955](https://github.com/rh-hideout/pokeemerald-expansion/pull/8955)
|
||||
|
||||
## ⚔️ Battle General ⚔️
|
||||
### Changed
|
||||
* Add enum for battle script commands by @AlexOn1ine in [#8778](https://github.com/rh-hideout/pokeemerald-expansion/pull/8778)
|
||||
* Miscellaneous fixes to configs and other values by @amiosi in [#8662](https://github.com/rh-hideout/pokeemerald-expansion/pull/8662)
|
||||
* Updating IsNonVolatileStatusBlocked by @bassforte123 in [#8728](https://github.com/rh-hideout/pokeemerald-expansion/pull/8728)
|
||||
|
||||
### Fixed
|
||||
* Fix berry activation timing for Yawn sleep and Leech Seed damage by @moostoet in [#8776](https://github.com/rh-hideout/pokeemerald-expansion/pull/8776)
|
||||
- Fix Chesto/Sitrus berry activation timing for status and damage
|
||||
* Fix Cheek Pouch not activating for Bug Bite, Pluck, and Fling berry effects by @Cle-bit in [#8782](https://github.com/rh-hideout/pokeemerald-expansion/pull/8782)
|
||||
* Fix wrongly getting a battler position in the type effectiveness functions by @Bassoonian in [#8787](https://github.com/rh-hideout/pokeemerald-expansion/pull/8787)
|
||||
* fix crash damage implementation and incorrect memento generation by @amiosi in [#8804](https://github.com/rh-hideout/pokeemerald-expansion/pull/8804)
|
||||
* Fix Sticky Hold blocking user's own Trick or Bestow by @Cle-bit in [#8860](https://github.com/rh-hideout/pokeemerald-expansion/pull/8860)
|
||||
* Fixes Nightmare not affecting Comatose and adds various missing tests by @Cle-bit in [#8859](https://github.com/rh-hideout/pokeemerald-expansion/pull/8859)
|
||||
* Fix Protosynthesis/Quark Drive defensive boost calculation by @hedara90 in [#8875](https://github.com/rh-hideout/pokeemerald-expansion/pull/8875)
|
||||
* Fix wrong cases of DamageContext by @Bassoonian in [#8895](https://github.com/rh-hideout/pokeemerald-expansion/pull/8895)
|
||||
* Fix misaligned shadows of transformed mons when `B_ENEMY_MON_SHADOW_STYLE <= GEN_3` by @estellarc in [#8887](https://github.com/rh-hideout/pokeemerald-expansion/pull/8887)
|
||||
* fix ITEM_NONE being considered a form change item by DoesSpeciesUseHoldItemToChangeForm by @phexmiau in [#8915](https://github.com/rh-hideout/pokeemerald-expansion/pull/8915)
|
||||
* Fix Memento and Block regressions by @amiosi in [#8942](https://github.com/rh-hideout/pokeemerald-expansion/pull/8942)
|
||||
* Fixed several issues with Parting Shot by @Cle-bit in [#8928](https://github.com/rh-hideout/pokeemerald-expansion/pull/8928)
|
||||
* Align Crafty Shield with wiki and refine IsAllyProtectingFromMove by @Cle-bit in [#8990](https://github.com/rh-hideout/pokeemerald-expansion/pull/8990)
|
||||
* Fixes Hyperspace Fury not breaking protection by @PhallenTree in [#8999](https://github.com/rh-hideout/pokeemerald-expansion/pull/8999)
|
||||
* Fix Magnetic Flux target handling in singles by @Cle-bit in [#9007](https://github.com/rh-hideout/pokeemerald-expansion/pull/9007)
|
||||
* fix: IsDoubleBattle() return value by @khbsd in [#9012](https://github.com/rh-hideout/pokeemerald-expansion/pull/9012)
|
||||
* Remove player party shiny bit setting in CreateFrontierBrainPokemon by @grintoul1 in [#9022](https://github.com/rh-hideout/pokeemerald-expansion/pull/9022)
|
||||
* Fix Foresight/Miracle Eye repeated-use behavior by @Cle-bit in [#9025](https://github.com/rh-hideout/pokeemerald-expansion/pull/9025)
|
||||
* Fix Crafty Shield consecutive-use failure by @Cle-bit in [#9023](https://github.com/rh-hideout/pokeemerald-expansion/pull/9023)
|
||||
* Fixes Beak Blast burning attacker when charging 2 turn move by @PhallenTree in [#9026](https://github.com/rh-hideout/pokeemerald-expansion/pull/9026)
|
||||
* Fix Synchronoise typeless behavior in Gen7+ by @Cle-bit in [#9031](https://github.com/rh-hideout/pokeemerald-expansion/pull/9031)
|
||||
* Fix Psych Up wrong battler message and Gen 6+ crit ratio copying by @Cle-bit in [#9015](https://github.com/rh-hideout/pokeemerald-expansion/pull/9015)
|
||||
* Add accuracy check to BattleScript_EffectNightmare by @AlexOn1ine in [#9032](https://github.com/rh-hideout/pokeemerald-expansion/pull/9032)
|
||||
* Fixes to Commander and Emergency Exit by @AlexOn1ine in [#9040](https://github.com/rh-hideout/pokeemerald-expansion/pull/9040)
|
||||
* Fixes Fling being usable with reusable TMs by @PhallenTree in [#8906](https://github.com/rh-hideout/pokeemerald-expansion/pull/8906)
|
||||
* Fix Forewarn edge cases and random selection by @Cle-bit in [#9049](https://github.com/rh-hideout/pokeemerald-expansion/pull/9049)
|
||||
* Fix Pickpocket moveend target checks and Thief/Covet handoff by @Cle-bit in [#9037](https://github.com/rh-hideout/pokeemerald-expansion/pull/9037)
|
||||
* Fixes Infiltrator and adds config for Substitute interaction by @PhallenTree in [#9073](https://github.com/rh-hideout/pokeemerald-expansion/pull/9073)
|
||||
* Fix Tranformed mon changing forms when fainting by @AsparagusEduardo in [#9106](https://github.com/rh-hideout/pokeemerald-expansion/pull/9106)
|
||||
* Prevent Incinerate from burning items under Sticky Hold by @Cle-Bit in [#9068](https://github.com/rh-hideout/pokeemerald-expansion/pull/9068)
|
||||
|
||||
## 🤹 Moves 🤹
|
||||
### Changed
|
||||
* Corrected Stone Axe and Ceaseless Edge descriptions by @fdeblasio in [#9062](https://github.com/rh-hideout/pokeemerald-expansion/pull/9062)
|
||||
|
||||
### Fixed
|
||||
* Fix Hyper Beam animation by @hedara90 in [#8872](https://github.com/rh-hideout/pokeemerald-expansion/pull/8872)
|
||||
* Fixed instances of COMBO_STARTER_CHARGE used incorrectly by @fdeblasio in [#9034](https://github.com/rh-hideout/pokeemerald-expansion/pull/9034)
|
||||
|
||||
## 🧶 Items 🧶
|
||||
### Changed
|
||||
* Miscellaneous Item Changes by @amiosi in [#8461](https://github.com/rh-hideout/pokeemerald-expansion/pull/8461)
|
||||
* add the type boost value for gen 3 sea incense by @amiosi in [#8826](https://github.com/rh-hideout/pokeemerald-expansion/pull/8826)
|
||||
* Changes to Item icons and palettes by @amiosi in [#8614](https://github.com/rh-hideout/pokeemerald-expansion/pull/8614)
|
||||
|
||||
## 🤖 Battle AI 🤖
|
||||
### Fixed
|
||||
* Fix Sticky Hold blocking user's own Trick or Bestow by @Cle-bit in [#8860](https://github.com/rh-hideout/pokeemerald-expansion/pull/8860)
|
||||
* Fix AI absorber switching for edge cases by @Cle-bit in [#8964](https://github.com/rh-hideout/pokeemerald-expansion/pull/8964)
|
||||
* Fix the speed scoring of Tailwind for AI by @Cle-bit in [#8968](https://github.com/rh-hideout/pokeemerald-expansion/pull/8968)
|
||||
* Fix AI wakeup-turn detection to consider Early Bird by @Cle-bit in [#9053](https://github.com/rh-hideout/pokeemerald-expansion/pull/9053)
|
||||
|
||||
## 🧹 Other Cleanup 🧹
|
||||
* Misc style and whitespace cleanup by @grintoul1 in [#8681](https://github.com/rh-hideout/pokeemerald-expansion/pull/8681)
|
||||
* Disable L button config (throw ball shortcut or move description) when there is overlap with L=A option by @FosterProgramming in [#8332](https://github.com/rh-hideout/pokeemerald-expansion/pull/8332)
|
||||
* Various sprite visualizer fixes if configs disabled by @kittenchilly in [#8697](https://github.com/rh-hideout/pokeemerald-expansion/pull/8697)
|
||||
* Updating IsNonVolatileStatusBlocked by @bassforte123 in [#8728](https://github.com/rh-hideout/pokeemerald-expansion/pull/8728)
|
||||
* Deleted unnecessary files by @Bassoonian in [#8899](https://github.com/rh-hideout/pokeemerald-expansion/pull/8899)
|
||||
* Fix Metronome bans by @amiosi in [#8834](https://github.com/rh-hideout/pokeemerald-expansion/pull/8834)
|
||||
* Move CMD_ARGS to battle_script_commands by @hedara90 in [#8974](https://github.com/rh-hideout/pokeemerald-expansion/pull/8974)
|
||||
- `CMD_ARGS` for battle scripts now only exist in `src/battle_script_commands.c`
|
||||
* Remove trailing whitespace - Master by @AsparagusEduardo in [#9011](https://github.com/rh-hideout/pokeemerald-expansion/pull/9011)
|
||||
* Corrected Stone Axe and Ceaseless Edge descriptions by @fdeblasio in [#9062](https://github.com/rh-hideout/pokeemerald-expansion/pull/9062)
|
||||
* Add aif2pcm to gitignore by @hedara90 in [#9077](https://github.com/rh-hideout/pokeemerald-expansion/pull/9077)
|
||||
* Fixes Infiltrator test battler not using intended move by @PhallenTree in [#9096](https://github.com/rh-hideout/pokeemerald-expansion/pull/9096)
|
||||
|
||||
## 🧪 Test Runner 🧪
|
||||
### Changed
|
||||
* Add inverse battle type matchup test by @izrofid in [#8779](https://github.com/rh-hideout/pokeemerald-expansion/pull/8779)
|
||||
* `B_ABILITY_TRIGGER_CHANCE` config tests by @AsparagusEduardo in [#8594](https://github.com/rh-hideout/pokeemerald-expansion/pull/8594)
|
||||
* Support end-of-battle party data check in tests by @AsparagusEduardo in [#8831](https://github.com/rh-hideout/pokeemerald-expansion/pull/8831)
|
||||
- If you added tests that checks for party data (`gPlayerParty`), make sure that you're not using a species which changes form at the end of the battle, as its data could be overriten by the form change.
|
||||
* Only test if move name fits on the bag screen for moves names within a TM/HM by @estellarc in [#8882](https://github.com/rh-hideout/pokeemerald-expansion/pull/8882)
|
||||
* Added tests for fainting form changes by @AsparagusEduardo in [#8912](https://github.com/rh-hideout/pokeemerald-expansion/pull/8912)
|
||||
* Add tests for type-changing abilities by @Cle-bit in [#8794](https://github.com/rh-hideout/pokeemerald-expansion/pull/8794)
|
||||
* Fixes Infiltrator test battler not using intended move by @PhallenTree in [#9096](https://github.com/rh-hideout/pokeemerald-expansion/pull/9096)
|
||||
|
||||
### Fixed
|
||||
* Fix Sticky Hold blocking user's own Trick or Bestow by @Cle-bit in [#8860](https://github.com/rh-hideout/pokeemerald-expansion/pull/8860)
|
||||
* Fixes Nightmare not affecting Comatose and adds various missing tests by @Cle-bit in [#8859](https://github.com/rh-hideout/pokeemerald-expansion/pull/8859)
|
||||
* Fixes Hyperspace Fury not breaking protection by @PhallenTree in [#8999](https://github.com/rh-hideout/pokeemerald-expansion/pull/8999)
|
||||
* Fix Magnetic Flux target handling in singles by @Cle-bit in [#9007](https://github.com/rh-hideout/pokeemerald-expansion/pull/9007)
|
||||
* Fix Foresight/Miracle Eye repeated-use behavior by @Cle-bit in [#9025](https://github.com/rh-hideout/pokeemerald-expansion/pull/9025)
|
||||
* Fixes Beak Blast burning attacker when charging 2 turn move by @PhallenTree in [#9026](https://github.com/rh-hideout/pokeemerald-expansion/pull/9026)
|
||||
* Fix Psych Up wrong battler message and Gen 6+ crit ratio copying by @Cle-bit in [#9015](https://github.com/rh-hideout/pokeemerald-expansion/pull/9015)
|
||||
* Fix Pickpocket moveend target checks and Thief/Covet handoff by @Cle-bit in [#9037](https://github.com/rh-hideout/pokeemerald-expansion/pull/9037)
|
||||
|
||||
## 📚 Documentation 📚
|
||||
* Add enum for battle script commands by @AlexOn1ine in [#8778](https://github.com/rh-hideout/pokeemerald-expansion/pull/8778)
|
||||
* Port old list of credits to modern system by @Bassoonian in [#7887](https://github.com/rh-hideout/pokeemerald-expansion/pull/7887)
|
||||
* Miscellaneous fixes to configs and other values by @amiosi in [#8662](https://github.com/rh-hideout/pokeemerald-expansion/pull/8662)
|
||||
* Remove credits from code by @Bassoonian in [#8748](https://github.com/rh-hideout/pokeemerald-expansion/pull/8748)
|
||||
* Miscellaneous species_info Changes by @amiosi in [#8462](https://github.com/rh-hideout/pokeemerald-expansion/pull/8462)
|
||||
* Update CONTRIBUTING.md by @pkmnsnfrn in [#8879](https://github.com/rh-hideout/pokeemerald-expansion/pull/8879)
|
||||
* Amend "SS Item" category of scope doc by @Pawkkie in [#8966](https://github.com/rh-hideout/pokeemerald-expansion/pull/8966)
|
||||
* fix: updated rulings about big feature label by @pkmnsnfrn in [#9027](https://github.com/rh-hideout/pokeemerald-expansion/pull/9027)
|
||||
|
||||
## 👻 Sprites 👻
|
||||
### Changed
|
||||
* Changes to Item icons and palettes by @amiosi in [#8614](https://github.com/rh-hideout/pokeemerald-expansion/pull/8614)
|
||||
|
||||
### Fixed
|
||||
* Fix vivillon icy snow icon by @FosterProgramming in [#8970](https://github.com/rh-hideout/pokeemerald-expansion/pull/8970)
|
||||
* Fix premier ball wrong data size by @FosterProgramming in [#8979](https://github.com/rh-hideout/pokeemerald-expansion/pull/8979)
|
||||
* Fixes creation of certain overworld sprites in object_event_pic_tables_followers.h by @ChrispyChris27 in [#9065](https://github.com/rh-hideout/pokeemerald-expansion/pull/9065)
|
||||
|
||||
## New Contributors
|
||||
* @ostomachion made their first contribution in [#8904](https://github.com/rh-hideout/pokeemerald-expansion/pull/8904)
|
||||
* @ChrispyChris27 made their first contribution in [#9065](https://github.com/rh-hideout/pokeemerald-expansion/pull/9065)
|
||||
|
||||
**Full Changelog**: https://github.com/rh-hideout/pokeemerald-expansion/compare/expansion/1.14.2...expansion/1.14.3
|
||||
|
||||
|
||||
<!--Last PR: 9099-->
|
||||
<!--Used to keep track of the last PR merged in case new ones come in before the changelog is done.-->
|
||||
18
include/battle_anim_internal.h
Normal file
18
include/battle_anim_internal.h
Normal file
@ -0,0 +1,18 @@
|
||||
#ifndef GUARD_BATTLE_ANIM_INTERNAL_H
|
||||
#define GUARD_BATTLE_ANIM_INTERNAL_H
|
||||
|
||||
/* CMD_ARGS provides a way to locally name the members of gBattleAnimArgs.
|
||||
*
|
||||
* For example:
|
||||
* {
|
||||
* CMD_ARGS(x, y);
|
||||
* // cmd->x is gBattleAnimArgs[0] and cmd->y is gBattleAnimArgs[1]
|
||||
* } */
|
||||
#if MODERN
|
||||
#define CMD_ARGS(...) struct { s16 __VA_ARGS__; } *cmd = (void *)gBattleAnimArgs
|
||||
#else
|
||||
#define CMD_ARGS(...) struct CMD_ARGS { s16 __VA_ARGS__; }
|
||||
#define cmd ((struct CMD_ARGS *)gBattleAnimArgs)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@ -383,6 +383,7 @@ bool32 CanBeFrozen(u32 battlerAtk, u32 battlerDef, enum Ability abilityDef);
|
||||
bool32 CanGetFrostbite(u32 battlerAtk, u32 battlerDef, enum Ability abilityDef);
|
||||
bool32 CanSetNonVolatileStatus(u32 battlerAtk, u32 battlerDef, enum Ability abilityAtk, enum Ability abilityDef, enum MoveEffect secondaryMoveEffect, enum FunctionCallOption option);
|
||||
bool32 CanBeConfused(u32 battler);
|
||||
bool32 IsSafeguardProtected(u32 battlerAtk, u32 battlerDef, u32 abilityAtk);
|
||||
u32 GetBattlerAffectionHearts(u32 battler);
|
||||
void TryToRevertMimicryAndFlags(void);
|
||||
bool32 BattleArenaTurnEnd(void);
|
||||
|
||||
@ -90,6 +90,7 @@
|
||||
#define B_MINIMIZE_EVASION GEN_LATEST // In Gen5+, Minimize raises evasion by 2 stages instead of 1.
|
||||
#define B_GROWTH_STAT_RAISE GEN_LATEST // In Gen5+, Growth raises Attack in addition to Special Attack by 1 stage each. Under the effects of the sun, it raises them by 2 stages each instead.
|
||||
#define B_FOCUS_ENERGY_CRIT_RATIO GEN_LATEST // In Gen3+, Focus Energy increases critical hit ratio by 2 instead of 1.
|
||||
#define B_PSYCH_UP_CRIT_RATIO GEN_LATEST // In Gen6+, Psych Up also copies the target's critical hit ratio.
|
||||
|
||||
// Other move settings
|
||||
#define B_INCINERATE_GEMS GEN_LATEST // In Gen6+, Incinerate can destroy Gems.
|
||||
@ -171,6 +172,7 @@
|
||||
#define B_ATE_MULTIPLIER GEN_LATEST // In Gen7+, -ate abilities (Aerilate, Galvanize, Normalize, Pixilate, Refrigerate) multiply damage by 1.2. Otherwise, it's 1.3, except Normalize which has no multiplier.
|
||||
#define B_DEFIANT_STICKY_WEB GEN_LATEST // In Gen9+, Defiant activates on Sticky Web regardless of who set it up. In Gen8, Defiant does not activate on Sticky Web set up by an ally after Court Change swaps its side.
|
||||
#define B_POWDER_OVERCOAT GEN_LATEST // In Gen6+, Overcoat blocks powder and spore moves from affecting the user.
|
||||
#define B_INFILTRATOR_SUBSTITUTE GEN_LATEST // In Gen6+, Infiltrator bypasses Substitute when using a move, excluding Transform and Sky Drop.
|
||||
|
||||
// Item settings
|
||||
#define B_CONFUSE_BERRIES_HEAL GEN_LATEST // In Gens3-6, Figy and similar berries restore 1/8th of HP and trigger at half HP. In Gen7 they restore half HP, triggering at 25% HP. In Gen8 they heal 1/3rd of HP.
|
||||
|
||||
@ -697,4 +697,7 @@ enum SpeciesGfxChange
|
||||
// It's redundant with F_PAL_BATTLERS, because they're only ever used together to refer to all the battlers at once.
|
||||
#define F_PAL_BATTLERS_2 (1 << 7 | 1 << 8 | 1 << 9 | 1 << 10)
|
||||
|
||||
enum { SHAKE_BG_X, SHAKE_BG_Y, SHAKE_MON_X, SHAKE_MON_Y };
|
||||
enum { SHAKE_MON_ATTACKER, SHAKE_MON_TARGET, SHAKE_MON_BOTH };
|
||||
|
||||
#endif // GUARD_CONSTANTS_BATTLE_ANIM_H
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
#ifndef GUARD_CONSTANTS_EXPANSION_H
|
||||
#define GUARD_CONSTANTS_EXPANSION_H
|
||||
|
||||
// Last version: 1.14.2
|
||||
// Last version: 1.14.3
|
||||
#define EXPANSION_VERSION_MAJOR 1
|
||||
#define EXPANSION_VERSION_MINOR 14
|
||||
#define EXPANSION_VERSION_PATCH 3
|
||||
#define EXPANSION_VERSION_PATCH 4
|
||||
|
||||
// FALSE if this this version of Expansion is not a tagged commit, i.e.
|
||||
// it contains unreleased changes.
|
||||
|
||||
@ -4,200 +4,202 @@
|
||||
/* Config definitions */
|
||||
#define CONFIG_DEFINITIONS(F) \
|
||||
/* Calculation settings */ \
|
||||
F(CRIT_CHANCE, critChance, (u32, GEN_COUNT - 1)) \
|
||||
F(CRIT_MULTIPLIER, critMultiplier, (u32, GEN_COUNT - 1)) \
|
||||
F(PARALYSIS_SPEED, paralysisSpeed, (u32, GEN_COUNT - 1)) \
|
||||
F(CONFUSION_SELF_DMG_CHANCE, confusionSelfDmgChance, (u32, GEN_COUNT - 1)) \
|
||||
F(MULTI_HIT_CHANCE, multiHitChance, (u32, GEN_COUNT - 1)) \
|
||||
F(WHITEOUT_MONEY, whiteoutMoney, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(LIGHT_BALL_ATTACK_BOOST, lightBallAttackBoost, (u32, GEN_COUNT - 1)) \
|
||||
F(B_CRIT_CHANCE, critChance, (u32, GEN_COUNT - 1)) \
|
||||
F(B_CRIT_MULTIPLIER, critMultiplier, (u32, GEN_COUNT - 1)) \
|
||||
F(B_PARALYSIS_SPEED, paralysisSpeed, (u32, GEN_COUNT - 1)) \
|
||||
F(B_CONFUSION_SELF_DMG_CHANCE, confusionSelfDmgChance, (u32, GEN_COUNT - 1)) \
|
||||
F(B_MULTI_HIT_CHANCE, multiHitChance, (u32, GEN_COUNT - 1)) \
|
||||
F(B_WHITEOUT_MONEY, whiteoutMoney, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(B_LIGHT_BALL_ATTACK_BOOST, lightBallAttackBoost, (u32, GEN_COUNT - 1)) \
|
||||
/* Experience settings */ \
|
||||
F(EXP_CATCH, expCatch, (u32, GEN_COUNT - 1)) \
|
||||
F(TRAINER_EXP_MULTIPLIER, trainerExpMultiplier, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(SPLIT_EXP, splitExp, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(SCALED_EXP, scaledExp, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(UNEVOLVED_EXP_MULTIPLIER, unevolvedExpMultiplier, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(LEVEL_UP_NOTIFICATION, levelUpNotification, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(B_EXP_CATCH, expCatch, (u32, GEN_COUNT - 1)) \
|
||||
F(B_TRAINER_EXP_MULTIPLIER, trainerExpMultiplier, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(B_SPLIT_EXP, splitExp, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(B_SCALED_EXP, scaledExp, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(B_UNEVOLVED_EXP_MULTIPLIER, unevolvedExpMultiplier, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(B_LEVEL_UP_NOTIFICATION, levelUpNotification, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
/* Stat settings */ \
|
||||
F(BADGE_BOOST, badgeBoost, (u32, GEN_COUNT - 1)) \
|
||||
F(FRIENDSHIP_BOOST, friendshipBoost, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(MAX_LEVEL_EV_GAINS, maxLevelEvGains, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(RECALCULATE_STATS, recalculateStats, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(B_BADGE_BOOST, badgeBoost, (u32, GEN_COUNT - 1)) \
|
||||
F(B_FRIENDSHIP_BOOST, friendshipBoost, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(B_MAX_LEVEL_EV_GAINS, maxLevelEvGains, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(B_RECALCULATE_STATS, recalculateStats, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
/* Damage settings */ \
|
||||
F(BURN_DAMAGE, burnDamage, (u32, GEN_COUNT - 1)) \
|
||||
F(BURN_FACADE_DMG, burnFacadeDmg, (u32, GEN_COUNT - 1)) \
|
||||
F(BINDING_DAMAGE, bindingDamage, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(PSYWAVE_DMG, psywaveDmg, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(PAYBACK_SWITCH_BOOST, paybackSwitchBoost, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(HIDDEN_POWER_DMG, hiddenPowerDmg, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(ROUGH_SKIN_DMG, roughSkinDmg, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(KNOCK_OFF_DMG, knockOffDmg, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(SPORT_DMG_REDUCTION, sportDmgReduction, (u32, GEN_COUNT - 1)) \
|
||||
F(EXPLOSION_DEFENSE, explosionDefense, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(PARENTAL_BOND_DMG, parentalBondDmg, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(MULTIPLE_TARGETS_DMG, multipleTargetsDmg, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(B_BURN_DAMAGE, burnDamage, (u32, GEN_COUNT - 1)) \
|
||||
F(B_BURN_FACADE_DMG, burnFacadeDmg, (u32, GEN_COUNT - 1)) \
|
||||
F(B_BINDING_DAMAGE, bindingDamage, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(B_PSYWAVE_DMG, psywaveDmg, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(B_PAYBACK_SWITCH_BOOST, paybackSwitchBoost, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(B_HIDDEN_POWER_DMG, hiddenPowerDmg, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(B_ROUGH_SKIN_DMG, roughSkinDmg, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(B_KNOCK_OFF_DMG, knockOffDmg, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(B_SPORT_DMG_REDUCTION, sportDmgReduction, (u32, GEN_COUNT - 1)) \
|
||||
F(B_EXPLOSION_DEFENSE, explosionDefense, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(B_PARENTAL_BOND_DMG, parentalBondDmg, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(B_MULTIPLE_TARGETS_DMG, multipleTargetsDmg, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
/* Type settings */ \
|
||||
F(GHOSTS_ESCAPE, ghostsEscape, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(PARALYZE_ELECTRIC, paralyzeElectric, (u32, GEN_COUNT - 1)) \
|
||||
F(POWDER_GRASS, powderGrass, (u32, GEN_COUNT - 1)) \
|
||||
F(POWDER_OVERCOAT, powderOvercoat, (u32, GEN_COUNT - 1)) \
|
||||
F(UPDATED_TYPE_MATCHUPS, updatedTypeMatchups, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(PRANKSTER_DARK_TYPES, pranksterDarkTypes, (u32, GEN_COUNT - 1)) \
|
||||
F(SHEER_COLD_IMMUNITY, sheerColdImmunity, (u32, GEN_COUNT - 1)) \
|
||||
F(ROOST_PURE_FLYING, roostPureFlying, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(STATUS_TYPE_IMMUNITY, statusTypeImmunity, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(B_GHOSTS_ESCAPE, ghostsEscape, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(B_PARALYZE_ELECTRIC, paralyzeElectric, (u32, GEN_COUNT - 1)) \
|
||||
F(B_POWDER_GRASS, powderGrass, (u32, GEN_COUNT - 1)) \
|
||||
F(B_POWDER_OVERCOAT, powderOvercoat, (u32, GEN_COUNT - 1)) \
|
||||
F(B_UPDATED_TYPE_MATCHUPS, updatedTypeMatchups, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(B_PRANKSTER_DARK_TYPES, pranksterDarkTypes, (u32, GEN_COUNT - 1)) \
|
||||
F(B_SHEER_COLD_IMMUNITY, sheerColdImmunity, (u32, GEN_COUNT - 1)) \
|
||||
F(B_ROOST_PURE_FLYING, roostPureFlying, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(B_STATUS_TYPE_IMMUNITY, statusTypeImmunity, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
/* Turn settings */ \
|
||||
F(BINDING_TURNS, bindingTurns, (u32, GEN_COUNT - 1)) \
|
||||
F(UPROAR_TURNS, uproarTurns, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(UPROAR_IGNORE_SOUNDPROOF, uproarIgnoreSoundproof, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(DISABLE_TURNS, disableTurns, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(TAILWIND_TURNS, tailwindTurns, (u32, GEN_COUNT - 1)) \
|
||||
F(SLEEP_TURNS, sleepTurns, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(TAUNT_TURNS, tauntTurns, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(SPORT_TURNS, sportTurns, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(MEGA_EVO_TURN_ORDER, megaEvoTurnOrder, (u32, GEN_COUNT - 1)) \
|
||||
F(RECALC_TURN_AFTER_ACTIONS, recalcTurnAfterActions, (u32, GEN_COUNT - 1)) \
|
||||
F(FAINT_SWITCH_IN, faintSwitchIn, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(B_BINDING_TURNS, bindingTurns, (u32, GEN_COUNT - 1)) \
|
||||
F(B_UPROAR_TURNS, uproarTurns, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(B_UPROAR_IGNORE_SOUNDPROOF, uproarIgnoreSoundproof, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(B_DISABLE_TURNS, disableTurns, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(B_TAILWIND_TURNS, tailwindTurns, (u32, GEN_COUNT - 1)) \
|
||||
F(B_SLEEP_TURNS, sleepTurns, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(B_TAUNT_TURNS, tauntTurns, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(B_SPORT_TURNS, sportTurns, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(B_MEGA_EVO_TURN_ORDER, megaEvoTurnOrder, (u32, GEN_COUNT - 1)) \
|
||||
F(B_RECALC_TURN_AFTER_ACTIONS, recalcTurnAfterActions, (u32, GEN_COUNT - 1)) \
|
||||
F(B_FAINT_SWITCH_IN, faintSwitchIn, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
/* Move data settings */ \
|
||||
F(UPDATED_MOVE_DATA, updatedMoveData, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(UPDATED_MOVE_TYPES, updatedMoveTypes, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(UPDATED_MOVE_FLAGS, updatedMoveFlags, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(PHYSICAL_SPECIAL_SPLIT, physicalSpecialSplit, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(RECOIL_IF_MISS_DMG, recoilIfMissDmg, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(KLUTZ_FLING_INTERACTION, klutzFlingInteraction, (u32, GEN_COUNT - 1)) \
|
||||
F(UPDATED_CONVERSION, updatedConversion, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(UPDATED_CONVERSION_2, updatedConversion2, (u32, GEN_COUNT - 1)) \
|
||||
F(PP_REDUCED_BY_SPITE, ppReducedBySpite, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(EXTRAPOLATED_MOVE_FLAGS, extrapolatedMoveFlags, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(B_UPDATED_MOVE_DATA, updatedMoveData, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(B_UPDATED_MOVE_TYPES, updatedMoveTypes, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(B_UPDATED_MOVE_FLAGS, updatedMoveFlags, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(B_PHYSICAL_SPECIAL_SPLIT, physicalSpecialSplit, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(B_RECOIL_IF_MISS_DMG, recoilIfMissDmg, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(B_KLUTZ_FLING_INTERACTION, klutzFlingInteraction, (u32, GEN_COUNT - 1)) \
|
||||
F(B_UPDATED_CONVERSION, updatedConversion, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(B_UPDATED_CONVERSION_2, updatedConversion2, (u32, GEN_COUNT - 1)) \
|
||||
F(B_PP_REDUCED_BY_SPITE, ppReducedBySpite, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(B_EXTRAPOLATED_MOVE_FLAGS, extrapolatedMoveFlags, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
/* Ability data settings */ \
|
||||
F(UPDATED_ABILITY_DATA, updatedAbilityData, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(B_UPDATED_ABILITY_DATA, updatedAbilityData, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
/* Move accuracy settings */ \
|
||||
F(TOXIC_NEVER_MISS, toxicNeverMiss, (u32, GEN_COUNT - 1)) \
|
||||
F(MINIMIZE_DMG_ACC, minimizeDmgAcc, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(BLIZZARD_HAIL, blizzardHail, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(SHEER_COLD_ACC, sheerColdAcc, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(B_TOXIC_NEVER_MISS, toxicNeverMiss, (u32, GEN_COUNT - 1)) \
|
||||
F(B_MINIMIZE_DMG_ACC, minimizeDmgAcc, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(B_BLIZZARD_HAIL, blizzardHail, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(B_SHEER_COLD_ACC, sheerColdAcc, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
/* Move stat change settings */ \
|
||||
F(FELL_STINGER_STAT_RAISE, fellStingerStatRaise, (u32, GEN_COUNT - 1)) \
|
||||
F(KINGS_SHIELD_LOWER_ATK, kingsShieldLowerAtk, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(SPEED_BUFFING_RAPID_SPIN, speedBuffingRapidSpin, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(CHARGE_SPDEF_RAISE, chargeSpDefRaise, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(MINIMIZE_EVASION, minimizeEvasion, (u32, GEN_COUNT - 1)) \
|
||||
F(GROWTH_STAT_RAISE, growthStatRaise, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(FOCUS_ENERGY_CRIT_RATIO, focusEnergyCritRatio, (u32, GEN_COUNT - 1)) \
|
||||
F(B_FELL_STINGER_STAT_RAISE, fellStingerStatRaise, (u32, GEN_COUNT - 1)) \
|
||||
F(B_KINGS_SHIELD_LOWER_ATK, kingsShieldLowerAtk, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(B_SPEED_BUFFING_RAPID_SPIN, speedBuffingRapidSpin, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(B_CHARGE_SPDEF_RAISE, chargeSpDefRaise, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(B_MINIMIZE_EVASION, minimizeEvasion, (u32, GEN_COUNT - 1)) \
|
||||
F(B_GROWTH_STAT_RAISE, growthStatRaise, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(B_FOCUS_ENERGY_CRIT_RATIO, focusEnergyCritRatio, (u32, GEN_COUNT - 1)) \
|
||||
F(B_PSYCH_UP_CRIT_RATIO, psychUpCritRatio, (u32, GEN_COUNT - 1)) \
|
||||
/* Other move settings */ \
|
||||
F(INCINERATE_GEMS, incinerateGems, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(CAN_SPITE_FAIL, canSpiteFail, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(CRASH_IF_TARGET_IMMUNE, crashIfTargetImmune, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(MEMENTO_FAIL, mementoFail, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(PARTING_SHOT_SWITCH, partingShotSwitch, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(GLARE_GHOST, glareGhost, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(SKILL_SWAP, skillSwap, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(BRICK_BREAK, brickBreak, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(WISH_HP_SOURCE, wishHpSource, (u32, GEN_COUNT - 1)) \
|
||||
F(RAMPAGE_CANCELLING, rampageCancelling, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(HEAL_BLOCKING, healBlocking, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(ROOTED_GROUNDING, rootedGrounding, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(METRONOME_MOVES, metronomeMoves, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(TELEPORT_BEHAVIOR, teleportBehavior, (u32, GEN_COUNT - 1)) \
|
||||
F(BEAT_UP, beatUp, (u32, GEN_COUNT - 1)) \
|
||||
F(DARK_VOID_FAIL, darkVoidFail, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(BURN_HIT_THAW, burnHitThaw, (u32, GEN_COUNT - 1)) \
|
||||
F(HEALING_WISH_SWITCH, healingWishSwitch, (u32, GEN_COUNT - 1)) \
|
||||
F(DEFOG_EFFECT_CLEARING, defogEffectClearing, (u32, GEN_COUNT - 1)) \
|
||||
F(STOCKPILE_RAISES_DEFS, stockpileRaisesDefs, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(TRANSFORM_SHINY, transformShiny, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(TRANSFORM_FORM_CHANGES, transformFormChanges, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(WIDE_GUARD, wideGuard, (u32, GEN_COUNT - 1)) \
|
||||
F(QUICK_GUARD, quickGuard, (u32, GEN_COUNT - 1)) \
|
||||
F(IMPRISON, imprison, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(ALLY_SWITCH_FAIL_CHANCE, allySwitchFailChance, (u32, GEN_COUNT - 1)) \
|
||||
F(SKETCH_BANS, sketchBans, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(KNOCK_OFF_REMOVAL, knockOffRemoval, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(HEAL_BELL_SOUNDPROOF, healBellSoundproof, (u32, GEN_COUNT - 1)) \
|
||||
F(CHARGE, charge, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(POWDER_RAIN, powderRain, (u32, GEN_COUNT - 1)) \
|
||||
F(AFTER_YOU_TURN_ORDER, afterYouTurnOrder, (u32, GEN_COUNT - 1)) \
|
||||
F(QUASH_TURN_ORDER, quashTurnOrder, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(DESTINY_BOND_FAIL, destinyBondFail, (u32, GEN_COUNT - 1)) \
|
||||
F(FORESIGHT_FAIL, foresightFail, (u32, GEN_COUNT - 1)) \
|
||||
F(MIRACLE_EYE_FAIL, miracleEyeFail, (u32, GEN_COUNT - 1)) \
|
||||
F(PURSUIT_TARGET, pursuitTarget, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(SKIP_RECHARGE, skipRecharge, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(ENCORE_TARGET, encoreTarget, (u32, GEN_COUNT - 1)) \
|
||||
F(TIME_OF_DAY_HEALING_MOVES, timeOfDayHealingMoves, (u32, GEN_COUNT - 1)) \
|
||||
F(DREAM_EATER_LIQUID_OOZE, dreamEaterLiquidOoze, (u32, GEN_COUNT - 1)) \
|
||||
F(B_INCINERATE_GEMS, incinerateGems, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(B_CAN_SPITE_FAIL, canSpiteFail, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(B_CRASH_IF_TARGET_IMMUNE, crashIfTargetImmune, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(B_MEMENTO_FAIL, mementoFail, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(B_PARTING_SHOT_SWITCH, partingShotSwitch, (u32, GEN_COUNT - 1)) \
|
||||
F(B_GLARE_GHOST, glareGhost, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(B_SKILL_SWAP, skillSwap, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(B_BRICK_BREAK, brickBreak, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(B_WISH_HP_SOURCE, wishHpSource, (u32, GEN_COUNT - 1)) \
|
||||
F(B_RAMPAGE_CANCELLING, rampageCancelling, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(B_HEAL_BLOCKING, healBlocking, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(B_ROOTED_GROUNDING, rootedGrounding, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(B_METRONOME_MOVES, metronomeMoves, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(B_TELEPORT_BEHAVIOR, teleportBehavior, (u32, GEN_COUNT - 1)) \
|
||||
F(B_BEAT_UP, beatUp, (u32, GEN_COUNT - 1)) \
|
||||
F(B_DARK_VOID_FAIL, darkVoidFail, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(B_BURN_HIT_THAW, burnHitThaw, (u32, GEN_COUNT - 1)) \
|
||||
F(B_HEALING_WISH_SWITCH, healingWishSwitch, (u32, GEN_COUNT - 1)) \
|
||||
F(B_DEFOG_EFFECT_CLEARING, defogEffectClearing, (u32, GEN_COUNT - 1)) \
|
||||
F(B_STOCKPILE_RAISES_DEFS, stockpileRaisesDefs, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(B_TRANSFORM_SHINY, transformShiny, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(B_TRANSFORM_FORM_CHANGES, transformFormChanges, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(B_WIDE_GUARD, wideGuard, (u32, GEN_COUNT - 1)) \
|
||||
F(B_QUICK_GUARD, quickGuard, (u32, GEN_COUNT - 1)) \
|
||||
F(B_IMPRISON, imprison, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(B_ALLY_SWITCH_FAIL_CHANCE, allySwitchFailChance, (u32, GEN_COUNT - 1)) \
|
||||
F(B_SKETCH_BANS, sketchBans, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(B_KNOCK_OFF_REMOVAL, knockOffRemoval, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(B_HEAL_BELL_SOUNDPROOF, healBellSoundproof, (u32, GEN_COUNT - 1)) \
|
||||
F(B_CHARGE, charge, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(B_POWDER_RAIN, powderRain, (u32, GEN_COUNT - 1)) \
|
||||
F(B_AFTER_YOU_TURN_ORDER, afterYouTurnOrder, (u32, GEN_COUNT - 1)) \
|
||||
F(B_QUASH_TURN_ORDER, quashTurnOrder, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(B_DESTINY_BOND_FAIL, destinyBondFail, (u32, GEN_COUNT - 1)) \
|
||||
F(B_FORESIGHT_FAIL, foresightFail, (u32, GEN_COUNT - 1)) \
|
||||
F(B_MIRACLE_EYE_FAIL, miracleEyeFail, (u32, GEN_COUNT - 1)) \
|
||||
F(B_PURSUIT_TARGET, pursuitTarget, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(B_SKIP_RECHARGE, skipRecharge, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(B_ENCORE_TARGET, encoreTarget, (u32, GEN_COUNT - 1)) \
|
||||
F(B_TIME_OF_DAY_HEALING_MOVES, timeOfDayHealingMoves, (u32, GEN_COUNT - 1)) \
|
||||
F(B_DREAM_EATER_LIQUID_OOZE, dreamEaterLiquidOoze, (u32, GEN_COUNT - 1)) \
|
||||
/* Ability settings */ \
|
||||
F(GALE_WINGS, galeWings, (u32, GEN_COUNT - 1)) \
|
||||
F(STANCE_CHANGE_FAIL, stanceChangeFail, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(SHADOW_TAG_ESCAPE, shadowTagEscape, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(MOODY_ACC_EVASION, moodyAccEvasion, (u32, GEN_COUNT - 1)) \
|
||||
F(FLASH_FIRE_FROZEN, flashFireFrozen, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(SYNCHRONIZE_TOXIC, synchronizeToxic, (u32, GEN_COUNT - 1)) \
|
||||
F(UPDATED_INTIMIDATE, updatedIntimidate, (u32, GEN_COUNT - 1)) \
|
||||
F(OBLIVIOUS_TAUNT, obliviousTaunt, (u32, GEN_COUNT - 1)) \
|
||||
F(STURDY, sturdy, (u32, GEN_COUNT - 1)) \
|
||||
F(PLUS_MINUS_INTERACTION, plusMinusInteraction, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(WEATHER_FORMS, weatherForms, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(SYMBIOSIS_GEMS, symbiosisGems, (u32, GEN_COUNT - 1)) \
|
||||
F(ABSORBING_ABILITY_STRING, absorbingAbilityString, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(REDIRECT_ABILITY_IMMUNITY, redirectAbilityImmunity, (u32, GEN_COUNT - 1)) \
|
||||
F(REDIRECT_ABILITY_ALLIES, redirectAbilityAllies, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(LEAF_GUARD_PREVENTS_REST, leafGuardPreventsRest, (u32, GEN_COUNT - 1)) \
|
||||
F(TRANSISTOR_BOOST, transistorBoost, (u32, GEN_COUNT - 1)) \
|
||||
F(ILLUMINATE_EFFECT, illuminateEffect, (u32, GEN_COUNT - 1)) \
|
||||
F(WEAK_ARMOR_SPEED, weakArmorSpeed, (u32, GEN_COUNT - 1)) \
|
||||
F(PROTEAN_LIBERO, proteanLibero, (u32, GEN_COUNT - 1)) \
|
||||
F(INTREPID_SWORD, intrepidSword, (u32, GEN_COUNT - 1)) \
|
||||
F(DAUNTLESS_SHIELD, dauntlessShield, (u32, GEN_COUNT - 1)) \
|
||||
F(DISGUISE_HP_LOSS, disguiseHpLoss, (u32, GEN_COUNT - 1)) \
|
||||
F(ABILITY_TRIGGER_CHANCE, abilityTriggerChance, (u32, GEN_COUNT - 1)) \
|
||||
F(PICKUP_WILD, pickupWild, (u32, GEN_COUNT - 1)) \
|
||||
F(MAGIC_GUARD, magicGuard, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(BATTLE_BOND, battleBond, (u32, GEN_COUNT - 1)) \
|
||||
F(ATE_MULTIPLIER, ateMultiplier, (u32, GEN_COUNT - 1)) \
|
||||
F(DEFIANT_STICKY_WEB, defiantStickyWeb, (u32, GEN_COUNT - 1)) \
|
||||
F(B_GALE_WINGS, galeWings, (u32, GEN_COUNT - 1)) \
|
||||
F(B_STANCE_CHANGE_FAIL, stanceChangeFail, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(B_SHADOW_TAG_ESCAPE, shadowTagEscape, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(B_MOODY_ACC_EVASION, moodyAccEvasion, (u32, GEN_COUNT - 1)) \
|
||||
F(B_FLASH_FIRE_FROZEN, flashFireFrozen, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(B_SYNCHRONIZE_TOXIC, synchronizeToxic, (u32, GEN_COUNT - 1)) \
|
||||
F(B_UPDATED_INTIMIDATE, updatedIntimidate, (u32, GEN_COUNT - 1)) \
|
||||
F(B_OBLIVIOUS_TAUNT, obliviousTaunt, (u32, GEN_COUNT - 1)) \
|
||||
F(B_STURDY, sturdy, (u32, GEN_COUNT - 1)) \
|
||||
F(B_PLUS_MINUS_INTERACTION, plusMinusInteraction, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(B_WEATHER_FORMS, weatherForms, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(B_SYMBIOSIS_GEMS, symbiosisGems, (u32, GEN_COUNT - 1)) \
|
||||
F(B_ABSORBING_ABILITY_STRING, absorbingAbilityString, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(B_REDIRECT_ABILITY_IMMUNITY, redirectAbilityImmunity, (u32, GEN_COUNT - 1)) \
|
||||
F(B_REDIRECT_ABILITY_ALLIES, redirectAbilityAllies, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(B_LEAF_GUARD_PREVENTS_REST, leafGuardPreventsRest, (u32, GEN_COUNT - 1)) \
|
||||
F(B_TRANSISTOR_BOOST, transistorBoost, (u32, GEN_COUNT - 1)) \
|
||||
F(B_ILLUMINATE_EFFECT, illuminateEffect, (u32, GEN_COUNT - 1)) \
|
||||
F(B_WEAK_ARMOR_SPEED, weakArmorSpeed, (u32, GEN_COUNT - 1)) \
|
||||
F(B_PROTEAN_LIBERO, proteanLibero, (u32, GEN_COUNT - 1)) \
|
||||
F(B_INTREPID_SWORD, intrepidSword, (u32, GEN_COUNT - 1)) \
|
||||
F(B_DAUNTLESS_SHIELD, dauntlessShield, (u32, GEN_COUNT - 1)) \
|
||||
F(B_DISGUISE_HP_LOSS, disguiseHpLoss, (u32, GEN_COUNT - 1)) \
|
||||
F(B_ABILITY_TRIGGER_CHANCE, abilityTriggerChance, (u32, GEN_COUNT - 1)) \
|
||||
F(B_PICKUP_WILD, pickupWild, (u32, GEN_COUNT - 1)) \
|
||||
F(B_MAGIC_GUARD, magicGuard, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(B_BATTLE_BOND, battleBond, (u32, GEN_COUNT - 1)) \
|
||||
F(B_ATE_MULTIPLIER, ateMultiplier, (u32, GEN_COUNT - 1)) \
|
||||
F(B_DEFIANT_STICKY_WEB, defiantStickyWeb, (u32, GEN_COUNT - 1)) \
|
||||
F(B_INFILTRATOR_SUBSTITUTE, infiltratorSubstitute, (u32, GEN_COUNT - 1)) \
|
||||
/* Item settings */ \
|
||||
F(CONFUSE_BERRIES_HEAL, confuseBerriesHeal, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(X_ITEMS_BUFF, xItemsBuff, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(MENTAL_HERB, mentalHerb, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(TRAINERS_KNOCK_OFF_ITEMS, trainersKnockOffItems, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(RETURN_STOLEN_NPC_ITEMS, returnStolenNpcItems, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(STEAL_WILD_ITEMS, stealWildItems, (u32, GEN_COUNT - 1)) \
|
||||
F(RESTORE_HELD_BATTLE_ITEMS, restoreHeldBattleItems, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(SOUL_DEW_BOOST, soulDewBoost, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(NET_BALL_MODIFIER, netBallModifier, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(DIVE_BALL_MODIFIER, diveBallModifier, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(NEST_BALL_MODIFIER, nestBallModifier, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(REPEAT_BALL_MODIFIER, repeatBallModifier, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(TIMER_BALL_MODIFIER, timerBallModifier, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(DUSK_BALL_MODIFIER, duskBallModifier, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(QUICK_BALL_MODIFIER, quickBallModifier, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(LURE_BALL_MODIFIER, lureBallModifier, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(HEAVY_BALL_MODIFIER, heavyBallModifier, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(DREAM_BALL_MODIFIER, dreamBallModifier, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(SPORT_BALL_MODIFIER, sportBallModifier, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(SAFARI_BALL_MODIFIER, safariBallModifier, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(FRIEND_BALL_MODIFIER, friendBallModifier, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(SERENE_GRACE_BOOST, sereneGraceBoost, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(IRON_BALL, ironBall, (u32, GEN_COUNT - 1)) \
|
||||
F(B_CONFUSE_BERRIES_HEAL, confuseBerriesHeal, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(B_X_ITEMS_BUFF, xItemsBuff, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(B_MENTAL_HERB, mentalHerb, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(B_TRAINERS_KNOCK_OFF_ITEMS, trainersKnockOffItems, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(B_RETURN_STOLEN_NPC_ITEMS, returnStolenNpcItems, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(B_STEAL_WILD_ITEMS, stealWildItems, (u32, GEN_COUNT - 1)) \
|
||||
F(B_RESTORE_HELD_BATTLE_ITEMS, restoreHeldBattleItems, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(B_SOUL_DEW_BOOST, soulDewBoost, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(B_NET_BALL_MODIFIER, netBallModifier, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(B_DIVE_BALL_MODIFIER, diveBallModifier, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(B_NEST_BALL_MODIFIER, nestBallModifier, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(B_REPEAT_BALL_MODIFIER, repeatBallModifier, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(B_TIMER_BALL_MODIFIER, timerBallModifier, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(B_DUSK_BALL_MODIFIER, duskBallModifier, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(B_QUICK_BALL_MODIFIER, quickBallModifier, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(B_LURE_BALL_MODIFIER, lureBallModifier, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(B_HEAVY_BALL_MODIFIER, heavyBallModifier, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(B_DREAM_BALL_MODIFIER, dreamBallModifier, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(B_SPORT_BALL_MODIFIER, sportBallModifier, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(B_SAFARI_BALL_MODIFIER, safariBallModifier, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(B_FRIEND_BALL_MODIFIER, friendBallModifier, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(B_SERENE_GRACE_BOOST, sereneGraceBoost, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(B_IRON_BALL, ironBall, (u32, GEN_COUNT - 1)) \
|
||||
/* Weather settings */ \
|
||||
F(ABILITY_WEATHER, abilityWeather, (u32, GEN_COUNT - 1)) \
|
||||
F(SANDSTORM_SPDEF_BOOST, sandstormSpDefBoost, (u32, GEN_COUNT - 1)) \
|
||||
F(OVERWORLD_FOG, overworldFog, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(OVERWORLD_SNOW, overworldSnow, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(SNOW_WARNING, snowWarning, (u32, GEN_COUNT - 1)) \
|
||||
F(PREFERRED_ICE_WEATHER, preferredIceWeather, (u32, B_ICE_WEATHER_SNOW)) /* TODO: use in tests */ \
|
||||
F(B_ABILITY_WEATHER, abilityWeather, (u32, GEN_COUNT - 1)) \
|
||||
F(B_SANDSTORM_SPDEF_BOOST, sandstormSpDefBoost, (u32, GEN_COUNT - 1)) \
|
||||
F(B_OVERWORLD_FOG, overworldFog, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(B_OVERWORLD_SNOW, overworldSnow, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(B_SNOW_WARNING, snowWarning, (u32, GEN_COUNT - 1)) \
|
||||
F(B_PREFERRED_ICE_WEATHER, preferredIceWeather, (u32, B_ICE_WEATHER_SNOW)) /* TODO: use in tests */ \
|
||||
/* Terrain settings */ \
|
||||
F(TERRAIN_TYPE_BOOST, terrainTypeBoost, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(SECRET_POWER_EFFECT, secretPowerEffect, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(SECRET_POWER_ANIMATION, secretPowerAnimation, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(NATURE_POWER_MOVES, naturePowerMoves, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(CAMOUFLAGE_TYPES, camouflageTypes, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(B_TERRAIN_TYPE_BOOST, terrainTypeBoost, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(B_SECRET_POWER_EFFECT, secretPowerEffect, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(B_SECRET_POWER_ANIMATION, secretPowerAnimation, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(B_NATURE_POWER_MOVES, naturePowerMoves, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(B_CAMOUFLAGE_TYPES, camouflageTypes, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
/* Other settings */ \
|
||||
F(WILD_NATURAL_ENEMIES, wildNaturalEnemies, (u32, TRUE)) /* TODO: use in tests */ \
|
||||
F(AFFECTION_MECHANICS, affectionMechanics, (u32, TRUE)) /* TODO: use in tests */ \
|
||||
F(OBEDIENCE_MECHANICS, obedienceMechanics, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(USE_FROSTBITE, useFrostbite, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(B_WILD_NATURAL_ENEMIES, wildNaturalEnemies, (u32, TRUE)) /* TODO: use in tests */ \
|
||||
F(B_AFFECTION_MECHANICS, affectionMechanics, (u32, TRUE)) /* TODO: use in tests */ \
|
||||
F(B_OBEDIENCE_MECHANICS, obedienceMechanics, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(B_USE_FROSTBITE, useFrostbite, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
|
||||
|
||||
#define GET_CONFIG_MAXIMUM(_typeMaxValue, ...) INVOKE_WITH_B(GET_CONFIG_MAXIMUM_, _typeMaxValue)
|
||||
|
||||
@ -16,7 +16,9 @@ struct GenChanges
|
||||
// ...
|
||||
};
|
||||
|
||||
u32 GetConfig(enum ConfigTag configTag);
|
||||
#define GetConfig(name) GetConfigInternal(CONFIG_##name)
|
||||
|
||||
u32 GetConfigInternal(enum ConfigTag configTag);
|
||||
void SetConfig(enum ConfigTag configTag, u32 value);
|
||||
|
||||
#if TESTING
|
||||
|
||||
@ -167,6 +167,7 @@ enum RandomTag
|
||||
RNG_QUICK_DRAW,
|
||||
RNG_QUICK_CLAW,
|
||||
RNG_TRACE,
|
||||
RNG_FOREWARN,
|
||||
RNG_FICKLE_BEAM,
|
||||
RNG_AI_ABILITY,
|
||||
RNG_AI_SWITCH_HASBADODDS,
|
||||
|
||||
@ -309,7 +309,7 @@
|
||||
* of `enum ConfigTag`
|
||||
* Example:
|
||||
* GIVEN {
|
||||
* WITH_CONFIG(CONFIG_GALE_WINGS, GEN_6);
|
||||
* WITH_CONFIG(B_GALE_WINGS, GEN_6);
|
||||
* }
|
||||
* The `value` may be inferred from a local variable, e.g. set by
|
||||
* PARAMETRIZE.
|
||||
@ -970,7 +970,7 @@ struct moveWithPP {
|
||||
#define AI_LOG AILogScores(__LINE__)
|
||||
|
||||
#define FLAG_SET(flagId) SetFlagForTest(__LINE__, flagId)
|
||||
#define WITH_CONFIG(configTag, value) TestSetConfig(__LINE__, configTag, value)
|
||||
#define WITH_CONFIG(configTag, value) TestSetConfig(__LINE__, CONFIG_##configTag, value)
|
||||
|
||||
#define PLAYER(species) for (OpenPokemon(__LINE__, B_POSITION_PLAYER_LEFT, species); gBattleTestRunnerState->data.currentMon; ClosePokemon(__LINE__))
|
||||
#define OPPONENT(species) for (OpenPokemon(__LINE__, B_POSITION_OPPONENT_LEFT, species); gBattleTestRunnerState->data.currentMon; ClosePokemon(__LINE__))
|
||||
|
||||
@ -1267,7 +1267,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
|
||||
} // def partner ability checks
|
||||
|
||||
// gen7+ dark type mons immune to priority->elevated moves from prankster
|
||||
if (GetConfig(CONFIG_PRANKSTER_DARK_TYPES) >= GEN_7 && IS_BATTLER_OF_TYPE(battlerDef, TYPE_DARK)
|
||||
if (GetConfig(B_PRANKSTER_DARK_TYPES) >= GEN_7 && IS_BATTLER_OF_TYPE(battlerDef, TYPE_DARK)
|
||||
&& aiData->abilities[battlerAtk] == ABILITY_PRANKSTER && IsBattleMoveStatus(move)
|
||||
&& !(moveTarget & (MOVE_TARGET_OPPONENTS_FIELD | MOVE_TARGET_USER)))
|
||||
RETURN_SCORE_MINUS(10);
|
||||
@ -1729,7 +1729,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
|
||||
ADJUST_SCORE(-10);
|
||||
break;
|
||||
case EFFECT_SHEER_COLD:
|
||||
if (GetConfig(CONFIG_SHEER_COLD_IMMUNITY) >= GEN_7 && IS_BATTLER_OF_TYPE(battlerDef, TYPE_ICE))
|
||||
if (GetConfig(B_SHEER_COLD_IMMUNITY) >= GEN_7 && IS_BATTLER_OF_TYPE(battlerDef, TYPE_ICE))
|
||||
RETURN_SCORE_MINUS(20);
|
||||
// fallthrough
|
||||
case EFFECT_OHKO:
|
||||
@ -3396,7 +3396,7 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
|
||||
case ABILITY_VOLT_ABSORB:
|
||||
if (moveType == TYPE_ELECTRIC)
|
||||
{
|
||||
if (GetConfig(CONFIG_REDIRECT_ABILITY_IMMUNITY) < GEN_5 && atkPartnerAbility == ABILITY_LIGHTNING_ROD)
|
||||
if (GetConfig(B_REDIRECT_ABILITY_IMMUNITY) < GEN_5 && atkPartnerAbility == ABILITY_LIGHTNING_ROD)
|
||||
{
|
||||
RETURN_SCORE_MINUS(10);
|
||||
}
|
||||
@ -3442,7 +3442,7 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
|
||||
case ABILITY_STORM_DRAIN:
|
||||
if (moveType == TYPE_WATER)
|
||||
{
|
||||
if (GetConfig(CONFIG_REDIRECT_ABILITY_IMMUNITY) < GEN_5 && atkPartnerAbility == ABILITY_STORM_DRAIN)
|
||||
if (GetConfig(B_REDIRECT_ABILITY_IMMUNITY) < GEN_5 && atkPartnerAbility == ABILITY_STORM_DRAIN)
|
||||
{
|
||||
RETURN_SCORE_MINUS(10);
|
||||
}
|
||||
@ -5395,7 +5395,7 @@ static s32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move, stru
|
||||
case EFFECT_ION_DELUGE:
|
||||
if ((aiData->abilities[battlerAtk] == ABILITY_VOLT_ABSORB
|
||||
|| aiData->abilities[battlerAtk] == ABILITY_MOTOR_DRIVE
|
||||
|| (GetConfig(CONFIG_REDIRECT_ABILITY_IMMUNITY) >= GEN_5 && aiData->abilities[battlerAtk] == ABILITY_LIGHTNING_ROD))
|
||||
|| (GetConfig(B_REDIRECT_ABILITY_IMMUNITY) >= GEN_5 && aiData->abilities[battlerAtk] == ABILITY_LIGHTNING_ROD))
|
||||
&& predictedType == TYPE_NORMAL)
|
||||
ADJUST_SCORE(DECENT_EFFECT);
|
||||
break;
|
||||
@ -5455,7 +5455,7 @@ static s32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move, stru
|
||||
if (predictedMove != MOVE_NONE
|
||||
&& (aiData->abilities[battlerAtk] == ABILITY_VOLT_ABSORB
|
||||
|| aiData->abilities[battlerAtk] == ABILITY_MOTOR_DRIVE
|
||||
|| (GetConfig(CONFIG_REDIRECT_ABILITY_IMMUNITY) >= GEN_5 && aiData->abilities[battlerAtk] == ABILITY_LIGHTNING_ROD)))
|
||||
|| (GetConfig(B_REDIRECT_ABILITY_IMMUNITY) >= GEN_5 && aiData->abilities[battlerAtk] == ABILITY_LIGHTNING_ROD)))
|
||||
{
|
||||
ADJUST_SCORE(DECENT_EFFECT);
|
||||
}
|
||||
|
||||
@ -298,7 +298,7 @@ static bool32 ShouldSwitchIfHasBadOdds(u32 battler)
|
||||
|
||||
// Check if mon gets one shot
|
||||
if (maxDamageTaken > gBattleMons[battler].hp
|
||||
&& !(gItemsInfo[gBattleMons[battler].item].holdEffect == HOLD_EFFECT_FOCUS_SASH || (!IsMoldBreakerTypeAbility(opposingBattler, gAiLogicData->abilities[opposingBattler]) && GetConfig(CONFIG_STURDY) >= GEN_5 && aiAbility == ABILITY_STURDY)))
|
||||
&& !(gItemsInfo[gBattleMons[battler].item].holdEffect == HOLD_EFFECT_FOCUS_SASH || (!IsMoldBreakerTypeAbility(opposingBattler, gAiLogicData->abilities[opposingBattler]) && GetConfig(B_STURDY) >= GEN_5 && aiAbility == ABILITY_STURDY)))
|
||||
{
|
||||
getsOneShot = TRUE;
|
||||
}
|
||||
@ -534,14 +534,14 @@ static bool32 FindMonThatAbsorbsOpponentsMove(u32 battler)
|
||||
{
|
||||
absorbingTypeAbilities[numAbsorbingAbilities++] = ABILITY_WATER_ABSORB;
|
||||
absorbingTypeAbilities[numAbsorbingAbilities++] = ABILITY_DRY_SKIN;
|
||||
if (GetConfig(CONFIG_REDIRECT_ABILITY_IMMUNITY) >= GEN_5)
|
||||
if (GetConfig(B_REDIRECT_ABILITY_IMMUNITY) >= GEN_5)
|
||||
absorbingTypeAbilities[numAbsorbingAbilities++] = ABILITY_STORM_DRAIN;
|
||||
}
|
||||
if (incomingType == TYPE_ELECTRIC || (isOpposingBattlerChargingOrInvulnerable && incomingType == TYPE_ELECTRIC))
|
||||
{
|
||||
absorbingTypeAbilities[numAbsorbingAbilities++] = ABILITY_VOLT_ABSORB;
|
||||
absorbingTypeAbilities[numAbsorbingAbilities++] = ABILITY_MOTOR_DRIVE;
|
||||
if (GetConfig(CONFIG_REDIRECT_ABILITY_IMMUNITY) >= GEN_5)
|
||||
if (GetConfig(B_REDIRECT_ABILITY_IMMUNITY) >= GEN_5)
|
||||
absorbingTypeAbilities[numAbsorbingAbilities++] = ABILITY_LIGHTNING_ROD;
|
||||
}
|
||||
if (incomingType == TYPE_GRASS || (isOpposingBattlerChargingOrInvulnerable && incomingType == TYPE_GRASS))
|
||||
@ -567,7 +567,7 @@ static bool32 FindMonThatAbsorbsOpponentsMove(u32 battler)
|
||||
}
|
||||
if (IsPowderMove(incomingMove) || (isOpposingBattlerChargingOrInvulnerable && IsPowderMove(incomingMove)))
|
||||
{
|
||||
if (GetConfig(CONFIG_POWDER_OVERCOAT) >= GEN_6)
|
||||
if (GetConfig(B_POWDER_OVERCOAT) >= GEN_6)
|
||||
absorbingTypeAbilities[numAbsorbingAbilities++] = ABILITY_OVERCOAT;
|
||||
}
|
||||
if (numAbsorbingAbilities == 0)
|
||||
@ -720,7 +720,7 @@ static bool32 ShouldSwitchIfBadlyStatused(u32 battler)
|
||||
&& gAiLogicData->abilities[opposingBattler] != ABILITY_UNAWARE
|
||||
&& gAiLogicData->abilities[opposingBattler] != ABILITY_KEEN_EYE
|
||||
&& gAiLogicData->abilities[opposingBattler] != ABILITY_MINDS_EYE
|
||||
&& (GetConfig(CONFIG_ILLUMINATE_EFFECT) >= GEN_9 && gAiLogicData->abilities[opposingBattler] != ABILITY_ILLUMINATE)
|
||||
&& (GetConfig(B_ILLUMINATE_EFFECT) >= GEN_9 && gAiLogicData->abilities[opposingBattler] != ABILITY_ILLUMINATE)
|
||||
&& !gBattleMons[battler].volatiles.foresight
|
||||
&& !gBattleMons[battler].volatiles.miracleEye)
|
||||
switchMon = FALSE;
|
||||
@ -1763,7 +1763,7 @@ static u32 GetSwitchinStatusDamage(u32 battler)
|
||||
{
|
||||
if (status & STATUS1_BURN)
|
||||
{
|
||||
if (GetConfig(CONFIG_BURN_DAMAGE) >= GEN_7 || GetConfig(CONFIG_BURN_DAMAGE) == GEN_1)
|
||||
if (GetConfig(B_BURN_DAMAGE) >= GEN_7 || GetConfig(B_BURN_DAMAGE) == GEN_1)
|
||||
statusDamage = maxHP / 16;
|
||||
else
|
||||
statusDamage = maxHP / 8;
|
||||
@ -1774,7 +1774,7 @@ static u32 GetSwitchinStatusDamage(u32 battler)
|
||||
}
|
||||
else if (status & STATUS1_FROSTBITE)
|
||||
{
|
||||
if (GetConfig(CONFIG_BURN_DAMAGE) >= GEN_7 || GetConfig(CONFIG_BURN_DAMAGE) == GEN_1)
|
||||
if (GetConfig(B_BURN_DAMAGE) >= GEN_7 || GetConfig(B_BURN_DAMAGE) == GEN_1)
|
||||
statusDamage = maxHP / 16;
|
||||
else
|
||||
statusDamage = maxHP / 8;
|
||||
@ -1858,7 +1858,7 @@ static u32 GetSwitchinHitsToKO(s32 damageTaken, u32 battler)
|
||||
currentHP = currentHP - damageTaken;
|
||||
|
||||
// One shot prevention effects
|
||||
if (damageTaken >= maxHP && startingHP == maxHP && (heldItemEffect == HOLD_EFFECT_FOCUS_SASH || (!opponentCanBreakMold && GetConfig(CONFIG_STURDY) >= GEN_5 && ability == ABILITY_STURDY)) && hitsToKO < 1)
|
||||
if (damageTaken >= maxHP && startingHP == maxHP && (heldItemEffect == HOLD_EFFECT_FOCUS_SASH || (!opponentCanBreakMold && GetConfig(B_STURDY) >= GEN_5 && ability == ABILITY_STURDY)) && hitsToKO < 1)
|
||||
currentHP = 1;
|
||||
|
||||
// If mon is still alive, apply weather impact first, as it might KO the mon before it can heal with its item (order is weather -> item -> status)
|
||||
@ -2050,7 +2050,7 @@ static s32 GetMaxPriorityDamagePlayerCouldDealToSwitchin(u32 battler, u32 opposi
|
||||
|
||||
static bool32 CanAbilityTrapOpponent(enum Ability ability, u32 opponent)
|
||||
{
|
||||
if ((GetConfig(CONFIG_GHOSTS_ESCAPE) >= GEN_6 && IS_BATTLER_OF_TYPE(opponent, TYPE_GHOST)))
|
||||
if ((GetConfig(B_GHOSTS_ESCAPE) >= GEN_6 && IS_BATTLER_OF_TYPE(opponent, TYPE_GHOST)))
|
||||
return FALSE;
|
||||
else if (ability == ABILITY_SHADOW_TAG)
|
||||
{
|
||||
|
||||
@ -474,7 +474,7 @@ bool32 AI_CanBattlerEscape(u32 battler)
|
||||
{
|
||||
enum HoldEffect holdEffect = gAiLogicData->holdEffects[battler];
|
||||
|
||||
if (GetConfig(CONFIG_GHOSTS_ESCAPE) >= GEN_6 && IS_BATTLER_OF_TYPE(battler, TYPE_GHOST))
|
||||
if (GetConfig(B_GHOSTS_ESCAPE) >= GEN_6 && IS_BATTLER_OF_TYPE(battler, TYPE_GHOST))
|
||||
return TRUE;
|
||||
if (holdEffect == HOLD_EFFECT_SHED_SHELL)
|
||||
return TRUE;
|
||||
@ -818,7 +818,7 @@ static inline void CalcDynamicMoveDamage(struct DamageContext *ctx, u16 *medianD
|
||||
median = maximum = minimum = max(0, gBattleMons[ctx->battlerDef].hp - gBattleMons[ctx->battlerAtk].hp);
|
||||
break;
|
||||
case EFFECT_BEAT_UP:
|
||||
if (GetConfig(CONFIG_BEAT_UP) >= GEN_5)
|
||||
if (GetConfig(B_BEAT_UP) >= GEN_5)
|
||||
{
|
||||
u32 partyCount = CalculatePartyCount(GetBattlerParty(ctx->battlerAtk));
|
||||
u32 i;
|
||||
@ -873,7 +873,7 @@ static inline bool32 ShouldCalcCritDamage(u32 battlerAtk, u32 battlerDef, u32 mo
|
||||
s32 critChanceIndex = 0;
|
||||
|
||||
// Get crit chance
|
||||
if (GetConfig(CONFIG_CRIT_CHANCE) == GEN_1)
|
||||
if (GetConfig(B_CRIT_CHANCE) == GEN_1)
|
||||
critChanceIndex = CalcCritChanceStageGen1(battlerAtk, battlerDef, move, FALSE, aiData->abilities[battlerAtk], aiData->abilities[battlerDef], aiData->holdEffects[battlerAtk]);
|
||||
else
|
||||
critChanceIndex = CalcCritChanceStage(battlerAtk, battlerDef, move, FALSE, aiData->abilities[battlerAtk], aiData->abilities[battlerDef], aiData->holdEffects[battlerAtk]);
|
||||
@ -882,11 +882,11 @@ static inline bool32 ShouldCalcCritDamage(u32 battlerAtk, u32 battlerDef, u32 mo
|
||||
return TRUE;
|
||||
if (critChanceIndex >= RISKY_AI_CRIT_STAGE_THRESHOLD // Not guaranteed but above Risky threshold
|
||||
&& (gAiThinkingStruct->aiFlags[battlerAtk] & AI_FLAG_RISKY)
|
||||
&& GetConfig(CONFIG_CRIT_CHANCE) != GEN_1)
|
||||
&& GetConfig(B_CRIT_CHANCE) != GEN_1)
|
||||
return TRUE;
|
||||
if (critChanceIndex >= RISKY_AI_CRIT_THRESHOLD_GEN_1 // Not guaranteed but above Risky threshold
|
||||
&& (gAiThinkingStruct->aiFlags[battlerAtk] & AI_FLAG_RISKY)
|
||||
&& GetConfig(CONFIG_CRIT_CHANCE) == GEN_1)
|
||||
&& GetConfig(B_CRIT_CHANCE) == GEN_1)
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
@ -1476,7 +1476,7 @@ bool32 CanEndureHit(u32 battler, u32 battlerTarget, u32 move)
|
||||
|
||||
if (!DoesBattlerIgnoreAbilityChecks(battler, gAiLogicData->abilities[battler], move))
|
||||
{
|
||||
if (GetConfig(CONFIG_STURDY) >= GEN_5 && gAiLogicData->abilities[battlerTarget] == ABILITY_STURDY)
|
||||
if (GetConfig(B_STURDY) >= GEN_5 && gAiLogicData->abilities[battlerTarget] == ABILITY_STURDY)
|
||||
return TRUE;
|
||||
if (IsMimikyuDisguised(battlerTarget))
|
||||
return TRUE;
|
||||
@ -1830,7 +1830,7 @@ u32 AI_GetSwitchinWeather(struct BattlePokemon battleMon)
|
||||
case ABILITY_SAND_STREAM:
|
||||
return B_WEATHER_SANDSTORM;
|
||||
case ABILITY_SNOW_WARNING:
|
||||
return GetConfig(CONFIG_SNOW_WARNING) >= GEN_9 ? B_WEATHER_SNOW : B_WEATHER_HAIL;
|
||||
return GetConfig(B_SNOW_WARNING) >= GEN_9 ? B_WEATHER_SNOW : B_WEATHER_HAIL;
|
||||
default:
|
||||
return gBattleWeather;
|
||||
}
|
||||
@ -1931,7 +1931,7 @@ bool32 IsHazardClearingMove(u32 move)
|
||||
case EFFECT_TIDY_UP:
|
||||
return TRUE;
|
||||
case EFFECT_DEFOG:
|
||||
if (GetConfig(CONFIG_DEFOG_EFFECT_CLEARING) >= GEN_6)
|
||||
if (GetConfig(B_DEFOG_EFFECT_CLEARING) >= GEN_6)
|
||||
return TRUE;
|
||||
break;
|
||||
}
|
||||
@ -2198,7 +2198,7 @@ bool32 CanLowerStat(u32 battlerAtk, u32 battlerDef, struct AiLogicData *aiData,
|
||||
if (stat == STAT_DEF)
|
||||
return FALSE;
|
||||
case ABILITY_ILLUMINATE:
|
||||
if (GetConfig(CONFIG_ILLUMINATE_EFFECT) < GEN_9)
|
||||
if (GetConfig(B_ILLUMINATE_EFFECT) < GEN_9)
|
||||
break;
|
||||
case ABILITY_KEEN_EYE:
|
||||
case ABILITY_MINDS_EYE:
|
||||
@ -2938,7 +2938,7 @@ bool32 IsSwitchOutEffect(enum BattleMoveEffects effect)
|
||||
switch (effect)
|
||||
{
|
||||
case EFFECT_TELEPORT:
|
||||
if (GetConfig(CONFIG_TELEPORT_BEHAVIOR) >= GEN_8)
|
||||
if (GetConfig(B_TELEPORT_BEHAVIOR) >= GEN_8)
|
||||
return TRUE;
|
||||
case EFFECT_HIT_ESCAPE:
|
||||
case EFFECT_PARTING_SHOT:
|
||||
@ -3365,7 +3365,7 @@ enum AIPivot ShouldPivot(u32 battlerAtk, u32 battlerDef, enum Ability defAbility
|
||||
|
||||
if (!IsBattleMoveStatus(move) && ((gAiLogicData->shouldSwitch & (1u << battlerAtk))
|
||||
|| (AI_BattlerAtMaxHp(battlerDef) && (gAiLogicData->holdEffects[battlerDef] == HOLD_EFFECT_FOCUS_SASH
|
||||
|| (GetConfig(CONFIG_STURDY) >= GEN_5 && defAbility == ABILITY_STURDY)
|
||||
|| (GetConfig(B_STURDY) >= GEN_5 && defAbility == ABILITY_STURDY)
|
||||
|| defAbility == ABILITY_MULTISCALE
|
||||
|| defAbility == ABILITY_SHADOW_SHIELD))))
|
||||
return SHOULD_PIVOT; // pivot to break sash/sturdy/multiscale
|
||||
@ -3373,7 +3373,7 @@ enum AIPivot ShouldPivot(u32 battlerAtk, u32 battlerDef, enum Ability defAbility
|
||||
else if (!hasStatBoost)
|
||||
{
|
||||
if (!IsBattleMoveStatus(move) && (AI_BattlerAtMaxHp(battlerDef) && (gAiLogicData->holdEffects[battlerDef] == HOLD_EFFECT_FOCUS_SASH
|
||||
|| (GetConfig(CONFIG_STURDY) >= GEN_5 && defAbility == ABILITY_STURDY)
|
||||
|| (GetConfig(B_STURDY) >= GEN_5 && defAbility == ABILITY_STURDY)
|
||||
|| defAbility == ABILITY_MULTISCALE
|
||||
|| defAbility == ABILITY_SHADOW_SHIELD)))
|
||||
return SHOULD_PIVOT; // pivot to break sash/sturdy/multiscale
|
||||
@ -3829,24 +3829,21 @@ bool32 HasChoiceEffect(u32 battler)
|
||||
}
|
||||
}
|
||||
|
||||
static u32 FindMoveUsedXTurnsAgo(u32 battlerId, u32 x)
|
||||
{
|
||||
s32 i, index = gBattleHistory->moveHistoryIndex[battlerId];
|
||||
for (i = 0; i < x; i++)
|
||||
{
|
||||
if (--index < 0)
|
||||
index = AI_MOVE_HISTORY_COUNT - 1;
|
||||
}
|
||||
return gBattleHistory->moveHistory[battlerId][index];
|
||||
}
|
||||
|
||||
bool32 IsWakeupTurn(u32 battler)
|
||||
{
|
||||
// Check if rest was used 2 turns ago
|
||||
if ((gBattleMons[battler].status1 & STATUS1_SLEEP) == 1 && GetMoveEffect(FindMoveUsedXTurnsAgo(battler, 2)) == EFFECT_REST)
|
||||
return TRUE;
|
||||
else // no way to know
|
||||
u32 sleepTurns = gBattleMons[battler].status1 & STATUS1_SLEEP;
|
||||
u32 toSub;
|
||||
|
||||
if (sleepTurns == 0)
|
||||
return FALSE;
|
||||
|
||||
// Early Bird reduces the sleep timer twice as fast.
|
||||
if (gAiLogicData->abilities[battler] == ABILITY_EARLY_BIRD)
|
||||
toSub = 2;
|
||||
else
|
||||
toSub = 1;
|
||||
|
||||
return sleepTurns <= toSub;
|
||||
}
|
||||
|
||||
bool32 AnyPartyMemberStatused(u32 battlerId, bool32 checkSoundproof)
|
||||
@ -3862,7 +3859,7 @@ bool32 AnyPartyMemberStatused(u32 battlerId, bool32 checkSoundproof)
|
||||
battlerOnField1 = gBattlerPartyIndexes[battlerId];
|
||||
battlerOnField2 = gBattlerPartyIndexes[GetPartnerBattler(battlerId)];
|
||||
// Check partner's status
|
||||
if ((GetConfig(CONFIG_HEAL_BELL_SOUNDPROOF) == GEN_5
|
||||
if ((GetConfig(B_HEAL_BELL_SOUNDPROOF) == GEN_5
|
||||
|| gAiLogicData->abilities[BATTLE_PARTNER(battlerId)] != ABILITY_SOUNDPROOF
|
||||
|| !checkSoundproof)
|
||||
&& GetMonData(&party[battlerOnField2], MON_DATA_STATUS) != STATUS1_NONE
|
||||
@ -3876,8 +3873,8 @@ bool32 AnyPartyMemberStatused(u32 battlerId, bool32 checkSoundproof)
|
||||
}
|
||||
|
||||
// Check attacker's status
|
||||
if ((GetConfig(CONFIG_HEAL_BELL_SOUNDPROOF) == GEN_5
|
||||
|| GetConfig(CONFIG_HEAL_BELL_SOUNDPROOF) >= GEN_8
|
||||
if ((GetConfig(B_HEAL_BELL_SOUNDPROOF) == GEN_5
|
||||
|| GetConfig(B_HEAL_BELL_SOUNDPROOF) >= GEN_8
|
||||
|| gAiLogicData->abilities[battlerId] != ABILITY_SOUNDPROOF || !checkSoundproof)
|
||||
&& GetMonData(&party[battlerOnField1], MON_DATA_STATUS) != STATUS1_NONE
|
||||
&& ShouldCureStatus(battlerId, battlerId, gAiLogicData))
|
||||
@ -3888,7 +3885,7 @@ bool32 AnyPartyMemberStatused(u32 battlerId, bool32 checkSoundproof)
|
||||
{
|
||||
if (i == battlerOnField1 || i == battlerOnField2)
|
||||
continue;
|
||||
if (GetConfig(CONFIG_HEAL_BELL_SOUNDPROOF) < GEN_5
|
||||
if (GetConfig(B_HEAL_BELL_SOUNDPROOF) < GEN_5
|
||||
&& checkSoundproof
|
||||
&& GetMonAbility(&party[i]) == ABILITY_SOUNDPROOF)
|
||||
continue;
|
||||
@ -5783,7 +5780,7 @@ bool32 ShouldTriggerAbility(u32 battlerAtk, u32 battlerDef, enum Ability ability
|
||||
{
|
||||
case ABILITY_LIGHTNING_ROD:
|
||||
case ABILITY_STORM_DRAIN:
|
||||
if (GetConfig(CONFIG_REDIRECT_ABILITY_IMMUNITY) < GEN_5)
|
||||
if (GetConfig(B_REDIRECT_ABILITY_IMMUNITY) < GEN_5)
|
||||
return FALSE;
|
||||
else
|
||||
return (BattlerStatCanRise(battlerDef, ability, STAT_SPATK) && HasMoveWithCategory(battlerDef, DAMAGE_CATEGORY_SPECIAL));
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
#include "global.h"
|
||||
#include "battle_anim.h"
|
||||
#include "battle_anim_internal.h"
|
||||
#include "gpu_regs.h"
|
||||
#include "trig.h"
|
||||
#include "constants/rgb.h"
|
||||
@ -192,27 +193,29 @@ const struct SpriteTemplate gTailGlowOrbSpriteTemplate =
|
||||
|
||||
static void AnimMegahornHorn(struct Sprite *sprite)
|
||||
{
|
||||
CMD_ARGS(x1, y1, x2, y2, duration);
|
||||
|
||||
if (IsContest())
|
||||
{
|
||||
StartSpriteAffineAnim(sprite, 2);
|
||||
gBattleAnimArgs[2] = -gBattleAnimArgs[2];
|
||||
gBattleAnimArgs[0] = -gBattleAnimArgs[0];
|
||||
cmd->x2 = -cmd->x2;
|
||||
cmd->x1 = -cmd->x1;
|
||||
}
|
||||
else if (IsOnPlayerSide(gBattleAnimTarget))
|
||||
{
|
||||
StartSpriteAffineAnim(sprite, 1);
|
||||
gBattleAnimArgs[1] = -gBattleAnimArgs[1];
|
||||
gBattleAnimArgs[2] = -gBattleAnimArgs[2];
|
||||
gBattleAnimArgs[3] = -gBattleAnimArgs[3];
|
||||
gBattleAnimArgs[0] = -gBattleAnimArgs[0];
|
||||
cmd->y1 = -cmd->y1;
|
||||
cmd->x2 = -cmd->x2;
|
||||
cmd->y2 = -cmd->y2;
|
||||
cmd->x1 = -cmd->x1;
|
||||
}
|
||||
|
||||
sprite->x = GetBattlerSpriteCoord2(gBattleAnimTarget, BATTLER_COORD_X_2) + gBattleAnimArgs[0];
|
||||
sprite->y = GetBattlerSpriteCoord2(gBattleAnimTarget, BATTLER_COORD_Y_PIC_OFFSET) + gBattleAnimArgs[1];
|
||||
sprite->data[0] = gBattleAnimArgs[4];
|
||||
sprite->x = GetBattlerSpriteCoord2(gBattleAnimTarget, BATTLER_COORD_X_2) + cmd->x1;
|
||||
sprite->y = GetBattlerSpriteCoord2(gBattleAnimTarget, BATTLER_COORD_Y_PIC_OFFSET) + cmd->y1;
|
||||
sprite->data[0] = cmd->duration;
|
||||
|
||||
sprite->data[2] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_X_2) + gBattleAnimArgs[2];
|
||||
sprite->data[4] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_Y_PIC_OFFSET) + gBattleAnimArgs[3];
|
||||
sprite->data[2] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_X_2) + cmd->x2;
|
||||
sprite->data[4] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_Y_PIC_OFFSET) + cmd->y2;
|
||||
|
||||
sprite->callback = StartAnimLinearTranslation;
|
||||
StoreSpriteCallbackInData6(sprite, DestroyAnimSprite);
|
||||
@ -220,20 +223,22 @@ static void AnimMegahornHorn(struct Sprite *sprite)
|
||||
|
||||
static void AnimLeechLifeNeedle(struct Sprite *sprite)
|
||||
{
|
||||
CMD_ARGS(x, y, duration);
|
||||
|
||||
if (IsContest())
|
||||
{
|
||||
gBattleAnimArgs[0] = -gBattleAnimArgs[0];
|
||||
cmd->x = -cmd->x;
|
||||
StartSpriteAffineAnim(sprite, 2);
|
||||
}
|
||||
else if (IsOnPlayerSide(gBattleAnimTarget))
|
||||
{
|
||||
gBattleAnimArgs[1] = -gBattleAnimArgs[1];
|
||||
gBattleAnimArgs[0] = -gBattleAnimArgs[0];
|
||||
cmd->y = -cmd->y;
|
||||
cmd->x = -cmd->x;
|
||||
}
|
||||
|
||||
sprite->x = GetBattlerSpriteCoord2(gBattleAnimTarget, BATTLER_COORD_X_2) + gBattleAnimArgs[0];
|
||||
sprite->y = GetBattlerSpriteCoord2(gBattleAnimTarget, BATTLER_COORD_Y_PIC_OFFSET) + gBattleAnimArgs[1];
|
||||
sprite->data[0] = gBattleAnimArgs[2];
|
||||
sprite->x = GetBattlerSpriteCoord2(gBattleAnimTarget, BATTLER_COORD_X_2) + cmd->x;
|
||||
sprite->y = GetBattlerSpriteCoord2(gBattleAnimTarget, BATTLER_COORD_Y_PIC_OFFSET) + cmd->y;
|
||||
sprite->data[0] = cmd->duration;
|
||||
|
||||
sprite->data[2] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_X_2);
|
||||
sprite->data[4] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_Y_PIC_OFFSET);
|
||||
@ -244,22 +249,20 @@ static void AnimLeechLifeNeedle(struct Sprite *sprite)
|
||||
|
||||
// Creates a single web thread that travels from attacker to target.
|
||||
// Used by MOVE_STRING_SHOT and MOVE_SPIDER_WEB in their first move phase.
|
||||
// arg 0: x
|
||||
// arg 1: y
|
||||
// arg 2: controls the left-to-right movement
|
||||
// arg 3: amplitude
|
||||
// arg 4: if targets both opponents
|
||||
static void AnimTranslateWebThread(struct Sprite *sprite)
|
||||
{
|
||||
CMD_ARGS(x, y, unk2, amplitude, targetsBoth);
|
||||
|
||||
if (IsContest())
|
||||
gBattleAnimArgs[2] /= 2;
|
||||
cmd->unk2 /= 2;
|
||||
|
||||
InitSpritePosToAnimAttacker(sprite, TRUE);
|
||||
sprite->data[0] = gBattleAnimArgs[2];
|
||||
sprite->data[0] = cmd->unk2;
|
||||
sprite->data[1] = sprite->x;
|
||||
sprite->data[3] = sprite->y;
|
||||
|
||||
if (!gBattleAnimArgs[4])
|
||||
if (!cmd->targetsBoth)
|
||||
{
|
||||
sprite->data[2] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_X_2);
|
||||
sprite->data[4] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_Y_PIC_OFFSET);
|
||||
@ -270,7 +273,7 @@ static void AnimTranslateWebThread(struct Sprite *sprite)
|
||||
}
|
||||
|
||||
InitAnimLinearTranslationWithSpeed(sprite);
|
||||
sprite->data[5] = gBattleAnimArgs[3];
|
||||
sprite->data[5] = cmd->amplitude;
|
||||
sprite->callback = AnimTranslateWebThread_Step;
|
||||
}
|
||||
|
||||
@ -289,13 +292,15 @@ static void AnimTranslateWebThread_Step(struct Sprite *sprite)
|
||||
// Second stage of String Shot
|
||||
static void AnimStringWrap(struct Sprite *sprite)
|
||||
{
|
||||
CMD_ARGS(x, y);
|
||||
|
||||
SetAverageBattlerPositions(gBattleAnimTarget, FALSE, &sprite->x, &sprite->y);
|
||||
if (!IsOnPlayerSide(gBattleAnimAttacker))
|
||||
sprite->x -= gBattleAnimArgs[0];
|
||||
sprite->x -= cmd->x;
|
||||
else
|
||||
sprite->x += gBattleAnimArgs[0];
|
||||
sprite->x += cmd->x;
|
||||
|
||||
sprite->y += gBattleAnimArgs[1];
|
||||
sprite->y += cmd->y;
|
||||
if (IsOnPlayerSide(gBattleAnimTarget))
|
||||
sprite->y += 8;
|
||||
|
||||
@ -365,27 +370,24 @@ static void AnimSpiderWeb_End(struct Sprite *sprite)
|
||||
|
||||
// Translates a stinger sprite linearly to a destination location. The sprite is
|
||||
// initially rotated so that it appears to be traveling in a straight line.
|
||||
// arg 0: initial x pixel offset
|
||||
// arg 1: initial y pixel offset
|
||||
// arg 2: target x pixel offset
|
||||
// arg 3: target y pixel offset
|
||||
// arg 4: duration
|
||||
void AnimTranslateStinger(struct Sprite *sprite)
|
||||
{
|
||||
CMD_ARGS(initialX, intialY, targetX, targetY, duration);
|
||||
|
||||
s16 lVarX, lVarY;
|
||||
u16 rot;
|
||||
|
||||
if (IsContest())
|
||||
{
|
||||
gBattleAnimArgs[2] = -gBattleAnimArgs[2];
|
||||
cmd->targetX = -cmd->targetX;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!IsOnPlayerSide(gBattleAnimAttacker))
|
||||
{
|
||||
gBattleAnimArgs[2] = -gBattleAnimArgs[2];
|
||||
gBattleAnimArgs[1] = -gBattleAnimArgs[1];
|
||||
gBattleAnimArgs[3] = -gBattleAnimArgs[3];
|
||||
cmd->targetX = -cmd->targetX;
|
||||
cmd->intialY = -cmd->intialY;
|
||||
cmd->targetY = -cmd->targetY;
|
||||
}
|
||||
}
|
||||
|
||||
@ -394,20 +396,20 @@ void AnimTranslateStinger(struct Sprite *sprite)
|
||||
if (GetBattlerPosition(gBattleAnimTarget) == B_POSITION_PLAYER_LEFT
|
||||
|| GetBattlerPosition(gBattleAnimTarget) == B_POSITION_OPPONENT_LEFT)
|
||||
{
|
||||
gBattleAnimArgs[2] *= -1;
|
||||
gBattleAnimArgs[0] *= -1;
|
||||
cmd->targetX *= -1;
|
||||
cmd->initialX *= -1;
|
||||
}
|
||||
}
|
||||
|
||||
InitSpritePosToAnimAttacker(sprite, TRUE);
|
||||
|
||||
lVarX = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_X_2) + gBattleAnimArgs[2];
|
||||
lVarY = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_Y_PIC_OFFSET) + gBattleAnimArgs[3];
|
||||
lVarX = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_X_2) + cmd->targetX;
|
||||
lVarY = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_Y_PIC_OFFSET) + cmd->targetY;
|
||||
rot = ArcTan2Neg(lVarX - sprite->x, lVarY - sprite->y);
|
||||
rot += 0xC000;
|
||||
TrySetSpriteRotScale(sprite, FALSE, 0x100, 0x100, rot);
|
||||
|
||||
sprite->data[0] = gBattleAnimArgs[4];
|
||||
sprite->data[0] = cmd->duration;
|
||||
sprite->data[2] = lVarX;
|
||||
sprite->data[4] = lVarY;
|
||||
|
||||
@ -416,23 +418,19 @@ void AnimTranslateStinger(struct Sprite *sprite)
|
||||
}
|
||||
|
||||
// Rotates sprite and moves it in an arc, so that it appears like a missle or arrow traveling.
|
||||
// arg 0: initial x pixel offset
|
||||
// arg 1: initial y pixel offset
|
||||
// arg 2: target x pixel offset
|
||||
// arg 3: target y pixel offset
|
||||
// arg 4: duration
|
||||
// arg 5: wave amplitude
|
||||
void AnimMissileArc(struct Sprite *sprite)
|
||||
{
|
||||
CMD_ARGS(initialX, intialY, targetX, targetY, duration, waveAmplitude);
|
||||
|
||||
InitSpritePosToAnimAttacker(sprite, TRUE);
|
||||
|
||||
if (!IsOnPlayerSide(gBattleAnimAttacker))
|
||||
gBattleAnimArgs[2] = -gBattleAnimArgs[2];
|
||||
cmd->targetX = -cmd->targetX;
|
||||
|
||||
sprite->data[0] = gBattleAnimArgs[4];
|
||||
sprite->data[2] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_X_2) + gBattleAnimArgs[2];
|
||||
sprite->data[4] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_Y_PIC_OFFSET) + gBattleAnimArgs[3];
|
||||
sprite->data[5] = gBattleAnimArgs[5];
|
||||
sprite->data[0] = cmd->duration;
|
||||
sprite->data[2] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_X_2) + cmd->targetX;
|
||||
sprite->data[4] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_Y_PIC_OFFSET) + cmd->targetY;
|
||||
sprite->data[5] = cmd->waveAmplitude;
|
||||
InitAnimArcTranslation(sprite);
|
||||
|
||||
sprite->callback = AnimMissileArc_Step;
|
||||
@ -478,7 +476,9 @@ void AnimMissileArc_Step(struct Sprite *sprite)
|
||||
|
||||
static void AnimTailGlowOrb(struct Sprite *sprite)
|
||||
{
|
||||
if (gBattleAnimArgs[0] == ANIM_ATTACKER)
|
||||
CMD_ARGS(relativeTo);
|
||||
|
||||
if (cmd->relativeTo == ANIM_ATTACKER)
|
||||
{
|
||||
sprite->x = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_X_2);
|
||||
sprite->y = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_Y_PIC_OFFSET) + 18;
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
#include "global.h"
|
||||
#include "battle_anim.h"
|
||||
#include "battle_anim_internal.h"
|
||||
#include "contest.h"
|
||||
#include "gpu_regs.h"
|
||||
#include "graphics.h"
|
||||
@ -290,8 +291,10 @@ static void AnimPunishment(struct Sprite *sprite)
|
||||
|
||||
void AnimTask_AttackerFadeToInvisible(u8 taskId)
|
||||
{
|
||||
CMD_ARGS(stepDelay);
|
||||
|
||||
int battler;
|
||||
gTasks[taskId].data[0] = gBattleAnimArgs[0];
|
||||
gTasks[taskId].data[0] = cmd->stepDelay;
|
||||
battler = gBattleAnimAttacker;
|
||||
gTasks[taskId].data[1] = 16;
|
||||
SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(16, 0));
|
||||
@ -328,7 +331,9 @@ static void AnimTask_AttackerFadeToInvisible_Step(u8 taskId)
|
||||
|
||||
void AnimTask_AttackerFadeFromInvisible(u8 taskId)
|
||||
{
|
||||
gTasks[taskId].data[0] = gBattleAnimArgs[0];
|
||||
CMD_ARGS(stepDelay);
|
||||
|
||||
gTasks[taskId].data[0] = cmd->stepDelay;
|
||||
gTasks[taskId].data[1] = BLDALPHA_BLEND(0, 16);
|
||||
gTasks[taskId].func = AnimTask_AttackerFadeFromInvisible_Step;
|
||||
SetGpuReg(REG_OFFSET_BLDALPHA, gTasks[taskId].data[1]);
|
||||
@ -415,12 +420,14 @@ static void AnimUnusedBagSteal_Step(struct Sprite *sprite)
|
||||
// Move sprite inward for Bite/Crunch and Clamp
|
||||
void AnimBite(struct Sprite *sprite)
|
||||
{
|
||||
sprite->x += gBattleAnimArgs[0];
|
||||
sprite->y += gBattleAnimArgs[1];
|
||||
StartSpriteAffineAnim(sprite, gBattleAnimArgs[2]);
|
||||
sprite->data[0] = gBattleAnimArgs[3];
|
||||
sprite->data[1] = gBattleAnimArgs[4];
|
||||
sprite->data[2] = gBattleAnimArgs[5];
|
||||
CMD_ARGS(x, y, animation, xVelocity, yVelocity, halfDuration);
|
||||
|
||||
sprite->x += cmd->x;
|
||||
sprite->y += cmd->y;
|
||||
StartSpriteAffineAnim(sprite, cmd->animation);
|
||||
sprite->data[0] = cmd->xVelocity;
|
||||
sprite->data[1] = cmd->yVelocity;
|
||||
sprite->data[2] = cmd->halfDuration;
|
||||
sprite->callback = AnimBite_Step1;
|
||||
}
|
||||
|
||||
@ -447,10 +454,12 @@ static void AnimBite_Step2(struct Sprite *sprite)
|
||||
// Launches a tear drop away from the battler. Used by Fake Tears
|
||||
void AnimTearDrop(struct Sprite *sprite)
|
||||
{
|
||||
CMD_ARGS(relativeTo, type);
|
||||
|
||||
u8 battler;
|
||||
s8 xOffset;
|
||||
|
||||
if (gBattleAnimArgs[0] == ANIM_ATTACKER)
|
||||
if (cmd->relativeTo == ANIM_ATTACKER)
|
||||
battler = gBattleAnimAttacker;
|
||||
else
|
||||
battler = gBattleAnimTarget;
|
||||
@ -458,7 +467,7 @@ void AnimTearDrop(struct Sprite *sprite)
|
||||
xOffset = 20;
|
||||
sprite->oam.tileNum += 4;
|
||||
|
||||
switch (gBattleAnimArgs[1])
|
||||
switch (cmd->type)
|
||||
{
|
||||
case 0:
|
||||
sprite->x = GetBattlerSpriteCoordAttr(battler, BATTLER_COORD_ATTR_RIGHT) - 8;
|
||||
@ -899,21 +908,22 @@ void AnimTask_MementoHandleBg(u8 taskId)
|
||||
// Animates a deep slash from a claw. Used by Metal Claw, Dragon Claw, and Crush Claw
|
||||
void AnimClawSlash(struct Sprite *sprite)
|
||||
{
|
||||
sprite->x += gBattleAnimArgs[0];
|
||||
sprite->y += gBattleAnimArgs[1];
|
||||
StartSpriteAnim(sprite, gBattleAnimArgs[2]);
|
||||
CMD_ARGS(x, y, animation);
|
||||
|
||||
sprite->x += cmd->x;
|
||||
sprite->y += cmd->y;
|
||||
StartSpriteAnim(sprite, cmd->animation);
|
||||
sprite->callback = RunStoredCallbackWhenAnimEnds;
|
||||
StoreSpriteCallbackInData6(sprite, DestroyAnimSprite);
|
||||
}
|
||||
|
||||
// Makes the attacker metallic and shining.
|
||||
// Used by MOVE_HARDEN and MOVE_IRON_DEFENSE.
|
||||
// arg0: if true won't change battler's palette back
|
||||
// arg1: if true, use custom color
|
||||
// arg2: custom color
|
||||
// Custom color argument is used in MOVE_POISON_TAIL to make the mon turn purplish/pinkish as if became cloaked in poison.
|
||||
void AnimTask_MetallicShine(u8 taskId)
|
||||
{
|
||||
CMD_ARGS(permanent, useColor, color);
|
||||
|
||||
u16 species;
|
||||
u8 spriteId;
|
||||
u8 newSpriteId;
|
||||
@ -963,15 +973,15 @@ void AnimTask_MetallicShine(u8 taskId)
|
||||
gBattle_BG1_Y = -gSprites[spriteId].y + 32;
|
||||
paletteNum = 16 + gSprites[spriteId].oam.paletteNum;
|
||||
|
||||
if (gBattleAnimArgs[1] == 0)
|
||||
if (cmd->useColor == 0)
|
||||
SetGrayscaleOrOriginalPalette(paletteNum, FALSE);
|
||||
else
|
||||
BlendPalette(BG_PLTT_ID(paletteNum), 16, 11, gBattleAnimArgs[2]);
|
||||
BlendPalette(BG_PLTT_ID(paletteNum), 16, 11, cmd->color);
|
||||
|
||||
gTasks[taskId].data[0] = newSpriteId;
|
||||
gTasks[taskId].data[1] = gBattleAnimArgs[0];
|
||||
gTasks[taskId].data[2] = gBattleAnimArgs[1];
|
||||
gTasks[taskId].data[3] = gBattleAnimArgs[2];
|
||||
gTasks[taskId].data[1] = cmd->permanent;
|
||||
gTasks[taskId].data[2] = cmd->useColor;
|
||||
gTasks[taskId].data[3] = cmd->color;
|
||||
gTasks[taskId].data[6] = priorityChanged;
|
||||
gTasks[taskId].func = AnimTask_MetallicShine_Step;
|
||||
}
|
||||
@ -1020,22 +1030,22 @@ static void AnimTask_MetallicShine_Step(u8 taskId)
|
||||
}
|
||||
|
||||
// Changes battler's palette to either grayscale or original.
|
||||
// arg0: which battler
|
||||
// arg1: FALSE grayscale, TRUE original
|
||||
void AnimTask_SetGrayscaleOrOriginalPal(u8 taskId)
|
||||
{
|
||||
CMD_ARGS(battler, mode);
|
||||
|
||||
u8 spriteId;
|
||||
u8 battler;
|
||||
bool8 calcSpriteId = FALSE;
|
||||
u8 position = B_POSITION_PLAYER_LEFT;
|
||||
|
||||
switch (gBattleAnimArgs[0])
|
||||
switch (cmd->battler)
|
||||
{
|
||||
case ANIM_ATTACKER:
|
||||
case ANIM_TARGET:
|
||||
case ANIM_ATK_PARTNER:
|
||||
case ANIM_DEF_PARTNER:
|
||||
spriteId = GetAnimBattlerSpriteId(gBattleAnimArgs[0]);
|
||||
spriteId = GetAnimBattlerSpriteId(cmd->battler);
|
||||
break;
|
||||
case ANIM_PLAYER_LEFT:
|
||||
position = B_POSITION_PLAYER_LEFT;
|
||||
@ -1068,7 +1078,7 @@ void AnimTask_SetGrayscaleOrOriginalPal(u8 taskId)
|
||||
}
|
||||
|
||||
if (spriteId != SPRITE_NONE)
|
||||
SetGrayscaleOrOriginalPalette(gSprites[spriteId].oam.paletteNum + 16, gBattleAnimArgs[1]);
|
||||
SetGrayscaleOrOriginalPalette(gSprites[spriteId].oam.paletteNum + 16, cmd->mode);
|
||||
|
||||
DestroyAnimVisualTask(taskId);
|
||||
}
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
#include "global.h"
|
||||
#include "battle_anim.h"
|
||||
#include "battle_anim_internal.h"
|
||||
#include "scanline_effect.h"
|
||||
#include "task.h"
|
||||
#include "trig.h"
|
||||
@ -404,24 +405,26 @@ static void AnimSpinningDracoMeteor(struct Sprite *sprite)
|
||||
|
||||
void AnimOutrageFlame(struct Sprite *sprite)
|
||||
{
|
||||
CMD_ARGS(x, y, duration, xVelocity, yVelocity, flickerDuration);
|
||||
|
||||
sprite->x = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_X_2);
|
||||
sprite->y = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_Y_PIC_OFFSET);
|
||||
if (!IsOnPlayerSide(gBattleAnimAttacker))
|
||||
{
|
||||
sprite->x -= gBattleAnimArgs[0];
|
||||
gBattleAnimArgs[3] = -gBattleAnimArgs[3];
|
||||
gBattleAnimArgs[4] = -gBattleAnimArgs[4];
|
||||
sprite->x -= cmd->x;
|
||||
cmd->xVelocity = -cmd->xVelocity;
|
||||
cmd->yVelocity = -cmd->yVelocity;
|
||||
}
|
||||
else
|
||||
{
|
||||
sprite->x += gBattleAnimArgs[0];
|
||||
sprite->x += cmd->x;
|
||||
}
|
||||
|
||||
sprite->y += gBattleAnimArgs[1];
|
||||
sprite->data[0] = gBattleAnimArgs[2];
|
||||
sprite->data[1] = gBattleAnimArgs[3];
|
||||
sprite->data[3] = gBattleAnimArgs[4];
|
||||
sprite->data[5] = gBattleAnimArgs[5];
|
||||
sprite->y += cmd->y;
|
||||
sprite->data[0] = cmd->duration;
|
||||
sprite->data[1] = cmd->xVelocity;
|
||||
sprite->data[3] = cmd->yVelocity;
|
||||
sprite->data[5] = cmd->flickerDuration;
|
||||
sprite->invisible = TRUE;
|
||||
StoreSpriteCallbackInData6(sprite, DestroySpriteAndMatrix);
|
||||
sprite->callback = TranslateSpriteLinearAndFlicker;
|
||||
@ -429,26 +432,28 @@ void AnimOutrageFlame(struct Sprite *sprite)
|
||||
|
||||
static void StartDragonFireTranslation(struct Sprite *sprite)
|
||||
{
|
||||
CMD_ARGS(initialX, initialY, targetX, targetY, duration);
|
||||
|
||||
SetSpriteCoordsToAnimAttackerCoords(sprite);
|
||||
sprite->data[2] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_X_2);
|
||||
sprite->data[4] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_Y_PIC_OFFSET);
|
||||
if (!IsOnPlayerSide(gBattleAnimAttacker))
|
||||
{
|
||||
sprite->x -= gBattleAnimArgs[1];
|
||||
sprite->y += gBattleAnimArgs[1];
|
||||
sprite->data[2] -= gBattleAnimArgs[2];
|
||||
sprite->data[4] += gBattleAnimArgs[3];
|
||||
sprite->x -= cmd->initialY;
|
||||
sprite->y += cmd->initialY;
|
||||
sprite->data[2] -= cmd->targetX;
|
||||
sprite->data[4] += cmd->targetY;
|
||||
}
|
||||
else
|
||||
{
|
||||
sprite->x += gBattleAnimArgs[0];
|
||||
sprite->y += gBattleAnimArgs[1];
|
||||
sprite->data[2] += gBattleAnimArgs[2];
|
||||
sprite->data[4] += gBattleAnimArgs[3];
|
||||
sprite->x += cmd->initialX;
|
||||
sprite->y += cmd->initialY;
|
||||
sprite->data[2] += cmd->targetX;
|
||||
sprite->data[4] += cmd->targetY;
|
||||
StartSpriteAnim(sprite, 1);
|
||||
}
|
||||
|
||||
sprite->data[0] = gBattleAnimArgs[4];
|
||||
sprite->data[0] = cmd->duration;
|
||||
sprite->callback = StartAnimLinearTranslation;
|
||||
StoreSpriteCallbackInData6(sprite, DestroySpriteAndMatrix);
|
||||
}
|
||||
@ -458,7 +463,9 @@ static void StartDragonFireTranslation(struct Sprite *sprite)
|
||||
// args[2] - initial y offset
|
||||
void AnimDragonRageFirePlume(struct Sprite *sprite)
|
||||
{
|
||||
if (gBattleAnimArgs[0] == 0)
|
||||
CMD_ARGS(relativeTo, x, y);
|
||||
|
||||
if (cmd->relativeTo == ANIM_ATTACKER)
|
||||
{
|
||||
sprite->x = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_X);
|
||||
sprite->y = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_Y);
|
||||
@ -469,8 +476,8 @@ void AnimDragonRageFirePlume(struct Sprite *sprite)
|
||||
sprite->y = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_Y);
|
||||
}
|
||||
|
||||
SetAnimSpriteInitialXOffset(sprite, gBattleAnimArgs[1]);
|
||||
sprite->y += gBattleAnimArgs[2];
|
||||
SetAnimSpriteInitialXOffset(sprite, cmd->x);
|
||||
sprite->y += cmd->y;
|
||||
sprite->callback = RunStoredCallbackWhenAnimEnds;
|
||||
StoreSpriteCallbackInData6(sprite, DestroySpriteAndMatrix);
|
||||
}
|
||||
@ -486,13 +493,15 @@ void AnimDragonFireToTarget(struct Sprite *sprite)
|
||||
|
||||
void AnimDragonDanceOrb(struct Sprite *sprite)
|
||||
{
|
||||
CMD_ARGS(angle);
|
||||
|
||||
u16 r5;
|
||||
u16 r0;
|
||||
sprite->x = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_X_2);
|
||||
sprite->y = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_Y_PIC_OFFSET);
|
||||
sprite->data[4] = 0;
|
||||
sprite->data[5] = 1;
|
||||
sprite->data[6] = gBattleAnimArgs[0];
|
||||
sprite->data[6] = cmd->angle;
|
||||
r5 = GetBattlerSpriteCoordAttr(gBattlerAttacker, BATTLER_COORD_ATTR_HEIGHT);
|
||||
r0 = GetBattlerSpriteCoordAttr(gBattlerAttacker, BATTLER_COORD_ATTR_WIDTH);
|
||||
if (r5 > r0)
|
||||
@ -633,14 +642,16 @@ static void UpdateDragonDanceScanlineEffect(struct Task *task)
|
||||
|
||||
void AnimOverheatFlame(struct Sprite *sprite)
|
||||
{
|
||||
int yAmplitude = (gBattleAnimArgs[2] * 3) / 5;
|
||||
CMD_ARGS(speed, unk1, unk2, duration, y);
|
||||
|
||||
int yAmplitude = (cmd->unk2 * 3) / 5;
|
||||
sprite->x = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_X_2);
|
||||
sprite->y = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_Y_PIC_OFFSET) + gBattleAnimArgs[4];
|
||||
sprite->data[1] = Cos(gBattleAnimArgs[1], gBattleAnimArgs[2]);
|
||||
sprite->data[2] = Sin(gBattleAnimArgs[1], yAmplitude);
|
||||
sprite->x += sprite->data[1] * gBattleAnimArgs[0];
|
||||
sprite->y += sprite->data[2] * gBattleAnimArgs[0];
|
||||
sprite->data[3] = gBattleAnimArgs[3];
|
||||
sprite->y = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_Y_PIC_OFFSET) + cmd->y;
|
||||
sprite->data[1] = Cos(cmd->unk1, cmd->unk2);
|
||||
sprite->data[2] = Sin(cmd->unk1, yAmplitude);
|
||||
sprite->x += sprite->data[1] * cmd->speed;
|
||||
sprite->y += sprite->data[2] * cmd->speed;
|
||||
sprite->data[3] = cmd->duration;
|
||||
sprite->callback = AnimOverheatFlame_Step;
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,6 @@
|
||||
#include "global.h"
|
||||
#include "battle_anim.h"
|
||||
#include "battle_anim_internal.h"
|
||||
#include "palette.h"
|
||||
#include "random.h"
|
||||
#include "task.h"
|
||||
@ -339,29 +340,26 @@ static void AnimMovePowerSwapGuardSwap(struct Sprite *sprite)
|
||||
}
|
||||
|
||||
// Moves a spinning duck around the mon's head.
|
||||
// arg 0: initial x pixel offset
|
||||
// arg 1: initial y pixel offset
|
||||
// arg 2: initial wave offset
|
||||
// arg 3: wave period (higher means faster wave)
|
||||
// arg 4: duration
|
||||
static void AnimConfusionDuck(struct Sprite *sprite)
|
||||
{
|
||||
sprite->x += gBattleAnimArgs[0];
|
||||
sprite->y += gBattleAnimArgs[1];
|
||||
sprite->data[0] = gBattleAnimArgs[2];
|
||||
CMD_ARGS(x, y, waveOffset, wavePeriod, duration);
|
||||
|
||||
sprite->x += cmd->x;
|
||||
sprite->y += cmd->y;
|
||||
sprite->data[0] = cmd->waveOffset;
|
||||
if (!IsOnPlayerSide(gBattleAnimAttacker))
|
||||
{
|
||||
sprite->data[1] = -gBattleAnimArgs[3];
|
||||
sprite->data[1] = -cmd->wavePeriod;
|
||||
sprite->data[4] = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
sprite->data[1] = gBattleAnimArgs[3];
|
||||
sprite->data[1] = cmd->wavePeriod;
|
||||
sprite->data[4] = 0;
|
||||
StartSpriteAnim(sprite, 1);
|
||||
}
|
||||
|
||||
sprite->data[3] = gBattleAnimArgs[4];
|
||||
sprite->data[3] = cmd->duration;
|
||||
sprite->callback = AnimConfusionDuck_Step;
|
||||
sprite->callback(sprite);
|
||||
}
|
||||
@ -382,15 +380,12 @@ static void AnimConfusionDuck_Step(struct Sprite *sprite)
|
||||
}
|
||||
|
||||
// Performs a simple color blend on a specified sprite.
|
||||
// arg 0: palette selector
|
||||
// arg 1: delay
|
||||
// arg 2: start blend amount
|
||||
// arg 3: end blend amount
|
||||
// arg 4: blend color
|
||||
static void AnimSimplePaletteBlend(struct Sprite *sprite)
|
||||
{
|
||||
u32 selectedPalettes = UnpackSelectedBattlePalettes(gBattleAnimArgs[0]);
|
||||
BeginNormalPaletteFade(selectedPalettes, gBattleAnimArgs[1], gBattleAnimArgs[2], gBattleAnimArgs[3], gBattleAnimArgs[4]);
|
||||
CMD_ARGS(selector, delay, initialBlendY, targetBlendY, color);
|
||||
|
||||
u32 selectedPalettes = UnpackSelectedBattlePalettes(cmd->selector);
|
||||
BeginNormalPaletteFade(selectedPalettes, cmd->delay, cmd->initialBlendY, cmd->targetBlendY, cmd->color);
|
||||
sprite->invisible = TRUE;
|
||||
sprite->callback = AnimSimplePaletteBlend_Step;
|
||||
}
|
||||
@ -441,21 +436,32 @@ static void AnimSimplePaletteBlend_Step(struct Sprite *sprite)
|
||||
DestroyAnimSprite(sprite);
|
||||
}
|
||||
|
||||
#define sTimer data[0]
|
||||
#define sDelay data[1]
|
||||
#define sNumBlends data[2]
|
||||
#define sColor1 data[3]
|
||||
#define sBlendY1 data[4]
|
||||
#define sColor2 data[5]
|
||||
#define sBlendY2 data[6]
|
||||
#define sPaletteSelector data[7]
|
||||
|
||||
static void AnimComplexPaletteBlend(struct Sprite *sprite)
|
||||
{
|
||||
CMD_ARGS(selector, delay, numBlends, color1, blendY1, color2, blendY2);
|
||||
|
||||
u32 selectedPalettes;
|
||||
|
||||
sprite->data[0] = gBattleAnimArgs[1];
|
||||
sprite->data[1] = gBattleAnimArgs[1];
|
||||
sprite->data[2] = gBattleAnimArgs[2];
|
||||
sprite->data[3] = gBattleAnimArgs[3];
|
||||
sprite->data[4] = gBattleAnimArgs[4];
|
||||
sprite->data[5] = gBattleAnimArgs[5];
|
||||
sprite->data[6] = gBattleAnimArgs[6];
|
||||
sprite->data[7] = gBattleAnimArgs[0];
|
||||
sprite->sTimer = cmd->delay;
|
||||
sprite->sDelay = cmd->delay;
|
||||
sprite->sNumBlends = cmd->numBlends;
|
||||
sprite->sColor1 = cmd->color1;
|
||||
sprite->sBlendY1 = cmd->blendY1;
|
||||
sprite->sColor2 = cmd->color2;
|
||||
sprite->sBlendY2 = cmd->blendY2;
|
||||
sprite->sPaletteSelector = cmd->selector;
|
||||
|
||||
selectedPalettes = UnpackSelectedBattlePalettes(sprite->data[7]);
|
||||
BlendPalettes(selectedPalettes, gBattleAnimArgs[4], gBattleAnimArgs[3]);
|
||||
selectedPalettes = UnpackSelectedBattlePalettes(sprite->sPaletteSelector);
|
||||
BlendPalettes(selectedPalettes, cmd->blendY1, cmd->color1);
|
||||
sprite->invisible = TRUE;
|
||||
sprite->callback = AnimComplexPaletteBlend_Step1;
|
||||
}
|
||||
@ -464,30 +470,30 @@ static void AnimComplexPaletteBlend_Step1(struct Sprite *sprite)
|
||||
{
|
||||
u32 selectedPalettes;
|
||||
|
||||
if (sprite->data[0] > 0)
|
||||
if (sprite->sTimer > 0)
|
||||
{
|
||||
sprite->data[0]--;
|
||||
sprite->sTimer--;
|
||||
return;
|
||||
}
|
||||
|
||||
if (gPaletteFade.active)
|
||||
return;
|
||||
|
||||
if (sprite->data[2] == 0)
|
||||
if (sprite->sNumBlends == 0)
|
||||
{
|
||||
sprite->callback = AnimComplexPaletteBlend_Step2;
|
||||
return;
|
||||
}
|
||||
|
||||
selectedPalettes = UnpackSelectedBattlePalettes(sprite->data[7]);
|
||||
if (sprite->data[1] & 0x100)
|
||||
BlendPalettes(selectedPalettes, sprite->data[4], sprite->data[3]);
|
||||
selectedPalettes = UnpackSelectedBattlePalettes(sprite->sPaletteSelector);
|
||||
if (sprite->sDelay & 0x100)
|
||||
BlendPalettes(selectedPalettes, sprite->sBlendY1, sprite->sColor1);
|
||||
else
|
||||
BlendPalettes(selectedPalettes, sprite->data[6], sprite->data[5]);
|
||||
BlendPalettes(selectedPalettes, sprite->sBlendY2, sprite->sColor2);
|
||||
|
||||
sprite->data[1] ^= 0x100;
|
||||
sprite->data[0] = sprite->data[1] & 0xFF;
|
||||
sprite->data[2]--;
|
||||
sprite->sDelay ^= 0x100;
|
||||
sprite->sTimer = sprite->sDelay & 0xFF;
|
||||
sprite->sNumBlends--;
|
||||
}
|
||||
|
||||
static void AnimComplexPaletteBlend_Step2(struct Sprite *sprite)
|
||||
@ -496,16 +502,27 @@ static void AnimComplexPaletteBlend_Step2(struct Sprite *sprite)
|
||||
|
||||
if (!gPaletteFade.active)
|
||||
{
|
||||
selectedPalettes = UnpackSelectedBattlePalettes(sprite->data[7]);
|
||||
selectedPalettes = UnpackSelectedBattlePalettes(sprite->sPaletteSelector);
|
||||
BlendPalettes(selectedPalettes, 0, 0);
|
||||
DestroyAnimSprite(sprite);
|
||||
}
|
||||
}
|
||||
|
||||
#undef sTimer
|
||||
#undef sDelay
|
||||
#undef sNumBlends
|
||||
#undef sColor1
|
||||
#undef sBlendY1
|
||||
#undef sColor2
|
||||
#undef sBlendY2
|
||||
#undef sPaletteSelector
|
||||
|
||||
static void AnimCirclingSparkle(struct Sprite *sprite)
|
||||
{
|
||||
sprite->x += gBattleAnimArgs[0];
|
||||
sprite->y += gBattleAnimArgs[1];
|
||||
CMD_ARGS(x, y);
|
||||
|
||||
sprite->x += cmd->x;
|
||||
sprite->y += cmd->y;
|
||||
sprite->data[0] = 0;
|
||||
sprite->data[1] = 10;
|
||||
sprite->data[2] = 8;
|
||||
@ -533,12 +550,14 @@ static void AnimCirclingSparkle(struct Sprite *sprite)
|
||||
// Many uses of this task only set a tNumBlends of 2, which has the effect of blending to a color and back once
|
||||
void AnimTask_BlendColorCycle(u8 taskId)
|
||||
{
|
||||
gTasks[taskId].tPalSelector = gBattleAnimArgs[0];
|
||||
gTasks[taskId].tDelay = gBattleAnimArgs[1];
|
||||
gTasks[taskId].tNumBlends = gBattleAnimArgs[2];
|
||||
gTasks[taskId].tInitialBlendY = gBattleAnimArgs[3];
|
||||
gTasks[taskId].tTargetBlendY = gBattleAnimArgs[4];
|
||||
gTasks[taskId].tBlendColor = gBattleAnimArgs[5];
|
||||
CMD_ARGS(selector, delay, numBlends, initialBlendY, targetBlendY, color);
|
||||
|
||||
gTasks[taskId].tPalSelector = cmd->selector;
|
||||
gTasks[taskId].tDelay = cmd->delay;
|
||||
gTasks[taskId].tNumBlends = cmd->numBlends;
|
||||
gTasks[taskId].tInitialBlendY = cmd->initialBlendY;
|
||||
gTasks[taskId].tTargetBlendY = cmd->targetBlendY;
|
||||
gTasks[taskId].tBlendColor = cmd->color;
|
||||
gTasks[taskId].tRestoreBlend = FALSE;
|
||||
BlendColorCycle(taskId, 0, gTasks[taskId].tTargetBlendY);
|
||||
gTasks[taskId].func = AnimTask_BlendColorCycleLoop;
|
||||
@ -593,15 +612,17 @@ static void AnimTask_BlendColorCycleLoop(u8 taskId)
|
||||
// See AnimTask_BlendColorCycle. Same, but excludes Attacker and Target
|
||||
void AnimTask_BlendColorCycleExclude(u8 taskId)
|
||||
{
|
||||
CMD_ARGS(unk0, delay, numBlends, initialBlendY, targetBlendY, color);
|
||||
|
||||
int battler;
|
||||
u32 selectedPalettes = 0;
|
||||
|
||||
gTasks[taskId].data[0] = gBattleAnimArgs[0];
|
||||
gTasks[taskId].tDelay = gBattleAnimArgs[1];
|
||||
gTasks[taskId].tNumBlends = gBattleAnimArgs[2];
|
||||
gTasks[taskId].tInitialBlendY = gBattleAnimArgs[3];
|
||||
gTasks[taskId].tTargetBlendY = gBattleAnimArgs[4];
|
||||
gTasks[taskId].tBlendColor = gBattleAnimArgs[5];
|
||||
gTasks[taskId].data[0] = cmd->unk0;
|
||||
gTasks[taskId].tDelay = cmd->delay;
|
||||
gTasks[taskId].tNumBlends = cmd->numBlends;
|
||||
gTasks[taskId].tInitialBlendY = cmd->initialBlendY;
|
||||
gTasks[taskId].tTargetBlendY = cmd->targetBlendY;
|
||||
gTasks[taskId].tBlendColor = cmd->color;
|
||||
gTasks[taskId].tRestoreBlend = 0;
|
||||
|
||||
for (battler = 0; battler < gBattlersCount; battler++)
|
||||
@ -610,7 +631,7 @@ void AnimTask_BlendColorCycleExclude(u8 taskId)
|
||||
selectedPalettes |= 1 << (battler + 16);
|
||||
}
|
||||
|
||||
if (gBattleAnimArgs[0] == 1)
|
||||
if (cmd->unk0 == 1)
|
||||
selectedPalettes |= 0xE;
|
||||
|
||||
gTasks[taskId].tPalSelectorHi = selectedPalettes >> 16;
|
||||
@ -668,12 +689,14 @@ static void AnimTask_BlendColorCycleExcludeLoop(u8 taskId)
|
||||
// See AnimTask_BlendColorCycle. Same, but selects palette by ANIM_TAG_*
|
||||
void AnimTask_BlendColorCycleByTag(u8 taskId)
|
||||
{
|
||||
gTasks[taskId].tPalTag = gBattleAnimArgs[0];
|
||||
gTasks[taskId].tDelay = gBattleAnimArgs[1];
|
||||
gTasks[taskId].tNumBlends = gBattleAnimArgs[2];
|
||||
gTasks[taskId].tInitialBlendY = gBattleAnimArgs[3];
|
||||
gTasks[taskId].tTargetBlendY = gBattleAnimArgs[4];
|
||||
gTasks[taskId].tBlendColor = gBattleAnimArgs[5];
|
||||
CMD_ARGS(tag, delay, numBlends, initialBlendY, targetBlendY, color);
|
||||
|
||||
gTasks[taskId].tPalTag = cmd->tag;
|
||||
gTasks[taskId].tDelay = cmd->delay;
|
||||
gTasks[taskId].tNumBlends = cmd->numBlends;
|
||||
gTasks[taskId].tInitialBlendY = cmd->initialBlendY;
|
||||
gTasks[taskId].tTargetBlendY = cmd->targetBlendY;
|
||||
gTasks[taskId].tBlendColor = cmd->color;
|
||||
gTasks[taskId].tRestoreBlend = FALSE;
|
||||
|
||||
BlendColorCycleByTag(taskId, 0, gTasks[taskId].tTargetBlendY);
|
||||
@ -738,26 +761,36 @@ static void AnimTask_BlendColorCycleByTagLoop(u8 taskId)
|
||||
#undef tPalSelectorLo
|
||||
|
||||
// Flashes the specified anim tag with given color. Used e.g. to flash the particles red in Hyper Beam
|
||||
#define tTimer data[0]
|
||||
#define tDelay data[1]
|
||||
#define tNumBlends data[2]
|
||||
#define tColor1 data[3]
|
||||
#define tBlendY1 data[4]
|
||||
#define tColor2 data[5]
|
||||
#define tBlendY2 data[6]
|
||||
#define tAnimTag data[7]
|
||||
void AnimTask_FlashAnimTagWithColor(u8 taskId)
|
||||
{
|
||||
CMD_ARGS(tag, delay, numBlends, color1, blendY1, color2, blendY2);
|
||||
|
||||
u8 paletteIndex;
|
||||
|
||||
gTasks[taskId].data[0] = gBattleAnimArgs[1];
|
||||
gTasks[taskId].data[1] = gBattleAnimArgs[1];
|
||||
gTasks[taskId].data[2] = gBattleAnimArgs[2];
|
||||
gTasks[taskId].data[3] = gBattleAnimArgs[3];
|
||||
gTasks[taskId].data[4] = gBattleAnimArgs[4];
|
||||
gTasks[taskId].data[5] = gBattleAnimArgs[5];
|
||||
gTasks[taskId].data[6] = gBattleAnimArgs[6];
|
||||
gTasks[taskId].data[7] = gBattleAnimArgs[0];
|
||||
gTasks[taskId].tTimer = cmd->delay;
|
||||
gTasks[taskId].tDelay = cmd->delay;
|
||||
gTasks[taskId].tNumBlends = cmd->numBlends;
|
||||
gTasks[taskId].tColor1 = cmd->color1;
|
||||
gTasks[taskId].tBlendY1 = cmd->blendY1;
|
||||
gTasks[taskId].tColor2 = cmd->color2;
|
||||
gTasks[taskId].tBlendY2 = cmd->blendY2;
|
||||
gTasks[taskId].tAnimTag = cmd->tag;
|
||||
|
||||
paletteIndex = IndexOfSpritePaletteTag(gBattleAnimArgs[0]);
|
||||
paletteIndex = IndexOfSpritePaletteTag(cmd->tag);
|
||||
BeginNormalPaletteFade(
|
||||
1 << (paletteIndex + 16),
|
||||
0,
|
||||
gBattleAnimArgs[4],
|
||||
gBattleAnimArgs[4],
|
||||
gBattleAnimArgs[3]);
|
||||
cmd->blendY1,
|
||||
cmd->blendY1,
|
||||
cmd->color1);
|
||||
|
||||
gTasks[taskId].func = AnimTask_FlashAnimTagWithColor_Step1;
|
||||
}
|
||||
@ -766,44 +799,44 @@ static void AnimTask_FlashAnimTagWithColor_Step1(u8 taskId)
|
||||
{
|
||||
u32 selectedPalettes;
|
||||
|
||||
if (gTasks[taskId].data[0] > 0)
|
||||
if (gTasks[taskId].tTimer > 0)
|
||||
{
|
||||
gTasks[taskId].data[0]--;
|
||||
gTasks[taskId].tTimer--;
|
||||
return;
|
||||
}
|
||||
|
||||
if (gPaletteFade.active)
|
||||
return;
|
||||
|
||||
if (gTasks[taskId].data[2] == 0)
|
||||
if (gTasks[taskId].tNumBlends == 0)
|
||||
{
|
||||
gTasks[taskId].func = AnimTask_FlashAnimTagWithColor_Step2;
|
||||
return;
|
||||
}
|
||||
|
||||
selectedPalettes = 1 << (IndexOfSpritePaletteTag(gTasks[taskId].data[7]) + 16);
|
||||
if (gTasks[taskId].data[1] & 0x100)
|
||||
selectedPalettes = 1 << (IndexOfSpritePaletteTag(gTasks[taskId].tAnimTag) + 16);
|
||||
if (gTasks[taskId].tDelay & 0x100)
|
||||
{
|
||||
BeginNormalPaletteFade(
|
||||
selectedPalettes,
|
||||
0,
|
||||
gTasks[taskId].data[4],
|
||||
gTasks[taskId].data[4],
|
||||
gTasks[taskId].data[3]);
|
||||
gTasks[taskId].tBlendY1,
|
||||
gTasks[taskId].tBlendY1,
|
||||
gTasks[taskId].tColor1);
|
||||
}
|
||||
else
|
||||
{
|
||||
BeginNormalPaletteFade(
|
||||
selectedPalettes,
|
||||
0,
|
||||
gTasks[taskId].data[6],
|
||||
gTasks[taskId].data[6],
|
||||
gTasks[taskId].data[5]);
|
||||
gTasks[taskId].tBlendY2,
|
||||
gTasks[taskId].tBlendY2,
|
||||
gTasks[taskId].tColor2);
|
||||
}
|
||||
|
||||
gTasks[taskId].data[1] ^= 0x100;
|
||||
gTasks[taskId].data[0] = gTasks[taskId].data[1] & 0xFF;
|
||||
gTasks[taskId].data[2]--;
|
||||
gTasks[taskId].tDelay ^= 0x100;
|
||||
gTasks[taskId].tTimer = gTasks[taskId].tDelay & 0xFF;
|
||||
gTasks[taskId].tNumBlends--;
|
||||
}
|
||||
|
||||
static void AnimTask_FlashAnimTagWithColor_Step2(u8 taskId)
|
||||
@ -812,25 +845,37 @@ static void AnimTask_FlashAnimTagWithColor_Step2(u8 taskId)
|
||||
|
||||
if (!gPaletteFade.active)
|
||||
{
|
||||
selectedPalettes = 1 << (IndexOfSpritePaletteTag(gTasks[taskId].data[7]) + 16);
|
||||
selectedPalettes = 1 << (IndexOfSpritePaletteTag(gTasks[taskId].tAnimTag) + 16);
|
||||
BeginNormalPaletteFade(selectedPalettes, 0, 0, 0, RGB_BLACK);
|
||||
DestroyAnimVisualTask(taskId);
|
||||
}
|
||||
}
|
||||
|
||||
#undef tTimer
|
||||
#undef tDelay
|
||||
#undef tNumBlends
|
||||
#undef tColor1
|
||||
#undef tBlendY1
|
||||
#undef tColor2
|
||||
#undef tBlendY2
|
||||
#undef tAnimTag
|
||||
|
||||
// This function is different compared to pret, and flagsScenery doesn't properly describe what the variable is doing on expansion
|
||||
void AnimTask_InvertScreenColor(u8 taskId)
|
||||
{
|
||||
CMD_ARGS(flagsScenery);
|
||||
|
||||
u32 selectedPalettes = 0;
|
||||
|
||||
if (gBattleAnimArgs[0] & 0x1)
|
||||
if (cmd->flagsScenery & 0x1)
|
||||
selectedPalettes = GetBattlePalettesMask(TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE);
|
||||
if (gBattleAnimArgs[0] & 0x2)
|
||||
if (cmd->flagsScenery & 0x2)
|
||||
selectedPalettes |= (0x10000 << gBattleAnimAttacker);
|
||||
if (gBattleAnimArgs[0] & 0x4)
|
||||
if (cmd->flagsScenery & 0x4)
|
||||
selectedPalettes |= (0x10000 << gBattleAnimTarget);
|
||||
if (gBattleAnimArgs[0] & 0x8 && IsBattlerAlive(BATTLE_PARTNER(gBattleAnimTarget)))
|
||||
if (cmd->flagsScenery & 0x8 && IsBattlerAlive(BATTLE_PARTNER(gBattleAnimTarget)))
|
||||
selectedPalettes |= (0x10000 << BATTLE_PARTNER(gBattleAnimTarget));
|
||||
if (gBattleAnimArgs[0] & 0x10 && IsBattlerAlive(BATTLE_PARTNER(gBattleAnimAttacker)))
|
||||
if (cmd->flagsScenery & 0x10 && IsBattlerAlive(BATTLE_PARTNER(gBattleAnimAttacker)))
|
||||
selectedPalettes |= (0x10000 << BATTLE_PARTNER(gBattleAnimAttacker));
|
||||
|
||||
InvertPlttBuffer(selectedPalettes);
|
||||
@ -848,6 +893,8 @@ void AnimTask_InvertScreenColor(u8 taskId)
|
||||
#define tColorB data[7]
|
||||
void AnimTask_TintPalettes(u8 taskId)
|
||||
{
|
||||
CMD_ARGS(flagsScenery, flagsAttacker, flagsTarget, duration, r, g, b);
|
||||
|
||||
u8 attackerBattler;
|
||||
u8 targetBattler;
|
||||
u8 paletteIndex;
|
||||
@ -855,13 +902,13 @@ void AnimTask_TintPalettes(u8 taskId)
|
||||
|
||||
if (gTasks[taskId].tTimer == 0)
|
||||
{
|
||||
gTasks[taskId].tFlagsScenery = gBattleAnimArgs[0];
|
||||
gTasks[taskId].tFlagsAttacker = gBattleAnimArgs[1];
|
||||
gTasks[taskId].tFlagsTarget = gBattleAnimArgs[2];
|
||||
gTasks[taskId].tLength = gBattleAnimArgs[3];
|
||||
gTasks[taskId].tColorR = gBattleAnimArgs[4];
|
||||
gTasks[taskId].tColorG = gBattleAnimArgs[5];
|
||||
gTasks[taskId].tColorB = gBattleAnimArgs[6];
|
||||
gTasks[taskId].tFlagsScenery = cmd->flagsScenery;
|
||||
gTasks[taskId].tFlagsAttacker = cmd->flagsAttacker;
|
||||
gTasks[taskId].tFlagsTarget = cmd->flagsTarget;
|
||||
gTasks[taskId].tLength = cmd->duration;
|
||||
gTasks[taskId].tColorR = cmd->r;
|
||||
gTasks[taskId].tColorG = cmd->g;
|
||||
gTasks[taskId].tColorB = cmd->b;
|
||||
}
|
||||
|
||||
gTasks[taskId].tTimer++;
|
||||
@ -899,25 +946,34 @@ void AnimTask_TintPalettes(u8 taskId)
|
||||
#undef tColorG
|
||||
#undef tColorB
|
||||
|
||||
#define sShakeVelocity data[0]
|
||||
#define sShakeTimer data[1]
|
||||
#define sShakeDuration data[2]
|
||||
#define sTimer data[3]
|
||||
#define sOriginalValue data[4]
|
||||
#define sType data[5]
|
||||
#define sShakePtrLo data[6]
|
||||
#define sShakePtrHi data[7]
|
||||
|
||||
static void AnimShakeMonOrBattlePlatforms(struct Sprite *sprite)
|
||||
{
|
||||
u16 var0;
|
||||
CMD_ARGS(velocity, shakeTimer, shakeDuration, type, battlerSelector);
|
||||
|
||||
sprite->invisible = TRUE;
|
||||
sprite->data[0] = -gBattleAnimArgs[0];
|
||||
sprite->data[1] = gBattleAnimArgs[1];
|
||||
sprite->data[2] = gBattleAnimArgs[1];
|
||||
sprite->data[3] = gBattleAnimArgs[2];
|
||||
sprite->sShakeVelocity = -cmd->velocity;
|
||||
sprite->sShakeTimer = cmd->shakeTimer;
|
||||
sprite->sShakeDuration = cmd->shakeTimer;
|
||||
sprite->sTimer = cmd->shakeDuration;
|
||||
|
||||
switch (gBattleAnimArgs[3])
|
||||
switch (cmd->type)
|
||||
{
|
||||
case 0:
|
||||
case SHAKE_BG_X:
|
||||
StoreSpriteCallbackInData6(sprite, (void *)&gBattle_BG3_X);
|
||||
break;
|
||||
case 1:
|
||||
case SHAKE_BG_Y:
|
||||
StoreSpriteCallbackInData6(sprite, (void *)&gBattle_BG3_Y);
|
||||
break;
|
||||
case 2:
|
||||
case SHAKE_MON_X:
|
||||
StoreSpriteCallbackInData6(sprite, (void *)&gSpriteCoordOffsetX);
|
||||
break;
|
||||
default:
|
||||
@ -925,10 +981,9 @@ static void AnimShakeMonOrBattlePlatforms(struct Sprite *sprite)
|
||||
break;
|
||||
}
|
||||
|
||||
sprite->data[4] = *(u16 *)(sprite->data[6] | (sprite->data[7] << 16));
|
||||
sprite->data[5] = gBattleAnimArgs[3];
|
||||
var0 = sprite->data[5] - 2;
|
||||
if (var0 < 2)
|
||||
sprite->sOriginalValue = *(u16 *)(sprite->sShakePtrLo | (sprite->sShakePtrHi << 16));
|
||||
sprite->sType = cmd->type;
|
||||
if (sprite->sType == SHAKE_MON_X || sprite->sType == SHAKE_MON_Y)
|
||||
AnimShakeMonOrBattlePlatforms_UpdateCoordOffsetEnabled();
|
||||
|
||||
sprite->callback = AnimShakeMonOrBattlePlatforms_Step;
|
||||
@ -937,27 +992,25 @@ static void AnimShakeMonOrBattlePlatforms(struct Sprite *sprite)
|
||||
static void AnimShakeMonOrBattlePlatforms_Step(struct Sprite *sprite)
|
||||
{
|
||||
u8 i;
|
||||
u16 var0;
|
||||
|
||||
if (sprite->data[3] > 0)
|
||||
if (sprite->sTimer > 0)
|
||||
{
|
||||
sprite->data[3]--;
|
||||
if (sprite->data[1] > 0)
|
||||
sprite->sTimer--;
|
||||
if (sprite->sShakeTimer > 0)
|
||||
{
|
||||
sprite->data[1]--;
|
||||
sprite->sShakeTimer--;
|
||||
}
|
||||
else
|
||||
{
|
||||
sprite->data[1] = sprite->data[2];
|
||||
*(u16 *)(sprite->data[6] | (sprite->data[7] << 16)) += sprite->data[0];
|
||||
sprite->data[0] = -sprite->data[0];
|
||||
sprite->sShakeTimer = sprite->sShakeDuration;
|
||||
*(u16 *)(sprite->sShakePtrLo | (sprite->sShakePtrHi << 16)) += sprite->sShakeVelocity;
|
||||
sprite->sShakeVelocity = -sprite->sShakeVelocity;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
*(u16 *)(sprite->data[6] | (sprite->data[7] << 16)) = sprite->data[4];
|
||||
var0 = sprite->data[5] - 2;
|
||||
if (var0 < 2)
|
||||
*(u16 *)(sprite->sShakePtrLo | (sprite->sShakePtrHi << 16)) = sprite->sOriginalValue;
|
||||
if (sprite->sType == SHAKE_MON_X || sprite->sType == SHAKE_MON_Y)
|
||||
{
|
||||
for (i = 0; i < gBattlersCount; i++)
|
||||
gSprites[gBattlerSpriteIds[i]].coordOffsetEnabled = FALSE;
|
||||
@ -969,23 +1022,35 @@ static void AnimShakeMonOrBattlePlatforms_Step(struct Sprite *sprite)
|
||||
|
||||
static void AnimShakeMonOrBattlePlatforms_UpdateCoordOffsetEnabled(void)
|
||||
{
|
||||
// Matches AnimShakeMonOrBattlePlatforms.
|
||||
CMD_ARGS(velocity, shakeDuration, duration, type, battlerSelector);
|
||||
|
||||
gSprites[gBattlerSpriteIds[gBattleAnimAttacker]].coordOffsetEnabled = FALSE;
|
||||
gSprites[gBattlerSpriteIds[gBattleAnimTarget]].coordOffsetEnabled = FALSE;
|
||||
|
||||
if (gBattleAnimArgs[4] == 2)
|
||||
if (cmd->battlerSelector == 2)
|
||||
{
|
||||
gSprites[gBattlerSpriteIds[gBattleAnimAttacker]].coordOffsetEnabled = TRUE;
|
||||
gSprites[gBattlerSpriteIds[gBattleAnimTarget]].coordOffsetEnabled = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (gBattleAnimArgs[4] == 0)
|
||||
if (cmd->battlerSelector == 0)
|
||||
gSprites[gBattlerSpriteIds[gBattleAnimAttacker]].coordOffsetEnabled = TRUE;
|
||||
else
|
||||
gSprites[gBattlerSpriteIds[gBattleAnimTarget]].coordOffsetEnabled = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
#undef sShakeVelocity
|
||||
#undef sShakeTimer
|
||||
#undef sShakeDuration
|
||||
#undef sTimer
|
||||
#undef sOriginalValue
|
||||
#undef sType
|
||||
#undef sShakePtrLo
|
||||
#undef sShakePtrHi
|
||||
|
||||
// Task data for AnimTask_ShakeBattlePlatforms
|
||||
#define tXOffset data[0]
|
||||
#define tYOffset data[1]
|
||||
@ -994,19 +1059,17 @@ static void AnimShakeMonOrBattlePlatforms_UpdateCoordOffsetEnabled(void)
|
||||
#define tShakeDelay data[8]
|
||||
|
||||
// Can shake battle platforms back and forth on the X or down and back to original pos on Y (cant shake up from orig pos)
|
||||
// arg0: x offset of shake
|
||||
// arg1: y offset of shake
|
||||
// arg2: number of shakes
|
||||
// arg3: time between shakes
|
||||
void AnimTask_ShakeBattlePlatforms(u8 taskId)
|
||||
{
|
||||
gTasks[taskId].tXOffset = gBattleAnimArgs[0];
|
||||
gTasks[taskId].tYOffset = gBattleAnimArgs[1];
|
||||
gTasks[taskId].tNumShakes = gBattleAnimArgs[2];
|
||||
gTasks[taskId].tTimer = gBattleAnimArgs[3];
|
||||
gTasks[taskId].tShakeDelay = gBattleAnimArgs[3];
|
||||
gBattle_BG3_X = gBattleAnimArgs[0];
|
||||
gBattle_BG3_Y = gBattleAnimArgs[1];
|
||||
CMD_ARGS(xOffset, yOffset, shakes, delay);
|
||||
|
||||
gTasks[taskId].tXOffset = cmd->xOffset;
|
||||
gTasks[taskId].tYOffset = cmd->yOffset;
|
||||
gTasks[taskId].tNumShakes = cmd->shakes;
|
||||
gTasks[taskId].tTimer = cmd->delay;
|
||||
gTasks[taskId].tShakeDelay = cmd->delay;
|
||||
gBattle_BG3_X = cmd->xOffset;
|
||||
gBattle_BG3_Y = cmd->yOffset;
|
||||
gTasks[taskId].func = AnimTask_ShakeBattlePlatforms_Step;
|
||||
gTasks[taskId].func(taskId);
|
||||
}
|
||||
@ -1051,8 +1114,10 @@ static void AnimTask_ShakeBattlePlatforms_Step(u8 taskId)
|
||||
// args[3] - affine anim number
|
||||
void AnimHitSplatBasic(struct Sprite *sprite)
|
||||
{
|
||||
StartSpriteAffineAnim(sprite, gBattleAnimArgs[3]);
|
||||
if (gBattleAnimArgs[2] == ANIM_ATTACKER)
|
||||
CMD_ARGS(x, y, relativeTo, animation);
|
||||
|
||||
StartSpriteAffineAnim(sprite, cmd->animation);
|
||||
if (cmd->relativeTo == ANIM_ATTACKER)
|
||||
InitSpritePosToAnimAttacker(sprite, TRUE);
|
||||
else
|
||||
InitSpritePosToAnimTarget(sprite, TRUE);
|
||||
@ -1061,16 +1126,18 @@ void AnimHitSplatBasic(struct Sprite *sprite)
|
||||
StoreSpriteCallbackInData6(sprite, DestroyAnimSprite);
|
||||
}
|
||||
|
||||
// Same as basic hit splat but takes a length of time to persist for (arg4)
|
||||
// Same as basic hit splat but takes a length of time to persist for.
|
||||
static void AnimHitSplatPersistent(struct Sprite *sprite)
|
||||
{
|
||||
StartSpriteAffineAnim(sprite, gBattleAnimArgs[3]);
|
||||
if (gBattleAnimArgs[2] == ANIM_ATTACKER)
|
||||
CMD_ARGS(x, y, relativeTo, animation, duration);
|
||||
|
||||
StartSpriteAffineAnim(sprite, cmd->animation);
|
||||
if (cmd->relativeTo == ANIM_ATTACKER)
|
||||
InitSpritePosToAnimAttacker(sprite, TRUE);
|
||||
else
|
||||
InitSpritePosToAnimTarget(sprite, TRUE);
|
||||
|
||||
sprite->data[0] = gBattleAnimArgs[4];
|
||||
sprite->data[0] = cmd->duration;
|
||||
sprite->callback = RunStoredCallbackWhenAffineAnimEnds;
|
||||
StoreSpriteCallbackInData6(sprite, DestroyAnimSpriteAfterTimer);
|
||||
}
|
||||
@ -1079,20 +1146,25 @@ static void AnimHitSplatPersistent(struct Sprite *sprite)
|
||||
// Used by Twineedle and Spike Cannon
|
||||
static void AnimHitSplatHandleInvert(struct Sprite *sprite)
|
||||
{
|
||||
// Matches AnimHitSplatBasic.
|
||||
CMD_ARGS(x, y, relativeTo, animation);
|
||||
|
||||
if (!IsOnPlayerSide(gBattleAnimAttacker) && !IsContest())
|
||||
gBattleAnimArgs[1] = -gBattleAnimArgs[1];
|
||||
cmd->y = -cmd->y;
|
||||
|
||||
AnimHitSplatBasic(sprite);
|
||||
}
|
||||
|
||||
void AnimHitSplatRandom(struct Sprite *sprite)
|
||||
{
|
||||
if (gBattleAnimArgs[1] == -1)
|
||||
gBattleAnimArgs[1] = Random2() & 3;
|
||||
CMD_ARGS(relativeTo, animation);
|
||||
|
||||
if (!InitSpritePosToAnimBattler(gBattleAnimArgs[0], sprite, FALSE))
|
||||
if (cmd->animation == -1)
|
||||
cmd->animation = Random2() & 3;
|
||||
|
||||
if (!InitSpritePosToAnimBattler(cmd->relativeTo, sprite, FALSE))
|
||||
return;
|
||||
StartSpriteAffineAnim(sprite, gBattleAnimArgs[1]);
|
||||
StartSpriteAffineAnim(sprite, cmd->animation);
|
||||
|
||||
sprite->x2 += (Random2() % 48) - 24;
|
||||
sprite->y2 += (Random2() % 24) - 12;
|
||||
@ -1103,32 +1175,38 @@ void AnimHitSplatRandom(struct Sprite *sprite)
|
||||
|
||||
void AnimHitSplatOnMonEdge(struct Sprite *sprite)
|
||||
{
|
||||
sprite->data[0] = GetAnimBattlerSpriteId(gBattleAnimArgs[0]);
|
||||
CMD_ARGS(relativeTo, x, y, animation);
|
||||
|
||||
sprite->data[0] = GetAnimBattlerSpriteId(cmd->relativeTo);
|
||||
sprite->x = gSprites[sprite->data[0]].x + gSprites[sprite->data[0]].x2;
|
||||
sprite->y = gSprites[sprite->data[0]].y + gSprites[sprite->data[0]].y2;
|
||||
sprite->x2 = gBattleAnimArgs[1];
|
||||
sprite->y2 = gBattleAnimArgs[2];
|
||||
StartSpriteAffineAnim(sprite, gBattleAnimArgs[3]);
|
||||
sprite->x2 = cmd->x;
|
||||
sprite->y2 = cmd->y;
|
||||
StartSpriteAffineAnim(sprite, cmd->animation);
|
||||
StoreSpriteCallbackInData6(sprite, DestroySpriteAndMatrix);
|
||||
sprite->callback = RunStoredCallbackWhenAffineAnimEnds;
|
||||
}
|
||||
|
||||
void AnimCrossImpact(struct Sprite *sprite)
|
||||
{
|
||||
if (gBattleAnimArgs[2] == ANIM_ATTACKER)
|
||||
CMD_ARGS(x, y, relativeTo, duration);
|
||||
|
||||
if (cmd->relativeTo == ANIM_ATTACKER)
|
||||
InitSpritePosToAnimAttacker(sprite, TRUE);
|
||||
else
|
||||
InitSpritePosToAnimTarget(sprite, TRUE);
|
||||
|
||||
sprite->data[0] = gBattleAnimArgs[3];
|
||||
sprite->data[0] = cmd->duration;
|
||||
StoreSpriteCallbackInData6(sprite, DestroyAnimSprite);
|
||||
sprite->callback = WaitAnimForDuration;
|
||||
}
|
||||
|
||||
void AnimFlashingHitSplat(struct Sprite *sprite)
|
||||
{
|
||||
StartSpriteAffineAnim(sprite, gBattleAnimArgs[3]);
|
||||
if (gBattleAnimArgs[2] == ANIM_ATTACKER)
|
||||
CMD_ARGS(x, y, relativeTo, animation);
|
||||
|
||||
StartSpriteAffineAnim(sprite, cmd->animation);
|
||||
if (cmd->relativeTo == ANIM_ATTACKER)
|
||||
InitSpritePosToAnimAttacker(sprite, TRUE);
|
||||
else
|
||||
InitSpritePosToAnimTarget(sprite, TRUE);
|
||||
|
||||
@ -270,7 +270,7 @@ static bool32 HandleEndTurnWish(u32 battler)
|
||||
s32 wishHeal = 0;
|
||||
gBattlerTarget = battler;
|
||||
PREPARE_MON_NICK_WITH_PREFIX_BUFFER(gBattleTextBuff1, battler, gWishFutureKnock.wishPartyId[battler])
|
||||
if (GetConfig(CONFIG_WISH_HP_SOURCE) >= GEN_5)
|
||||
if (GetConfig(B_WISH_HP_SOURCE) >= GEN_5)
|
||||
{
|
||||
if (IsOnPlayerSide(battler))
|
||||
wishHeal = GetMonData(&gPlayerParty[gWishFutureKnock.wishPartyId[battler]], MON_DATA_MAX_HP) / 2;
|
||||
@ -531,7 +531,7 @@ static bool32 HandleEndTurnBurn(u32 battler)
|
||||
&& IsBattlerAlive(battler)
|
||||
&& !IsAbilityAndRecord(battler, ability, ABILITY_MAGIC_GUARD))
|
||||
{
|
||||
s32 burnDamage = GetNonDynamaxMaxHP(battler) / ((GetConfig(CONFIG_BURN_DAMAGE) >= GEN_7 || GetConfig(CONFIG_BURN_DAMAGE) == GEN_1) ? 16 : 8);
|
||||
s32 burnDamage = GetNonDynamaxMaxHP(battler) / ((GetConfig(B_BURN_DAMAGE) >= GEN_7 || GetConfig(B_BURN_DAMAGE) == GEN_1) ? 16 : 8);
|
||||
if (ability == ABILITY_HEATPROOF)
|
||||
{
|
||||
if (burnDamage > (burnDamage / 2) + 1) // Record ability if the burn takes less damage than it normally would.
|
||||
@ -556,7 +556,7 @@ static bool32 HandleEndTurnFrostbite(u32 battler)
|
||||
&& IsBattlerAlive(battler)
|
||||
&& !IsAbilityAndRecord(battler, GetBattlerAbility(battler), ABILITY_MAGIC_GUARD))
|
||||
{
|
||||
SetPassiveDamageAmount(battler, GetNonDynamaxMaxHP(battler) / ((GetConfig(CONFIG_BURN_DAMAGE) >= GEN_7 || GetConfig(CONFIG_BURN_DAMAGE) == GEN_1) ? 16 : 8));
|
||||
SetPassiveDamageAmount(battler, GetNonDynamaxMaxHP(battler) / ((GetConfig(B_BURN_DAMAGE) >= GEN_7 || GetConfig(B_BURN_DAMAGE) == GEN_1) ? 16 : 8));
|
||||
BattleScriptExecute(BattleScript_FrostbiteTurnDmg);
|
||||
effect = TRUE;
|
||||
}
|
||||
|
||||
@ -891,43 +891,66 @@ static u32 ItemRestorePp(u32 battler, u32 itemId, ActivationTiming timing)
|
||||
{
|
||||
enum ItemEffect effect = ITEM_NO_EFFECT;
|
||||
struct Pokemon *mon = GetBattlerMon(battler);
|
||||
u32 i, changedPP = 0;
|
||||
u32 changedPP = 0;
|
||||
u32 restoreMove = MAX_MON_MOVES;
|
||||
u32 missingMove = MAX_MON_MOVES;
|
||||
u32 ppBonuses = GetMonData(mon, MON_DATA_PP_BONUSES);
|
||||
bool32 override = gBattleScripting.overrideBerryRequirements;
|
||||
enum Ability ability = GetBattlerAbility(battler);
|
||||
|
||||
for (i = 0; i < MAX_MON_MOVES; i++)
|
||||
for (u32 i = 0; i < MAX_MON_MOVES; i++)
|
||||
{
|
||||
u32 move = GetMonData(mon, MON_DATA_MOVE1 + i);
|
||||
u32 currentPP = GetMonData(mon, MON_DATA_PP1 + i);
|
||||
u32 ppBonuses = GetMonData(mon, MON_DATA_PP_BONUSES);
|
||||
u32 maxPP = CalculatePPWithBonus(move, ppBonuses, i);
|
||||
if (move && (currentPP == 0 || (gBattleScripting.overrideBerryRequirements && currentPP != maxPP)))
|
||||
if (move == MOVE_NONE)
|
||||
continue;
|
||||
|
||||
if (currentPP == 0)
|
||||
{
|
||||
u32 ppRestored = GetItemHoldEffectParam(itemId);
|
||||
|
||||
if (ability == ABILITY_RIPEN)
|
||||
{
|
||||
ppRestored *= 2;
|
||||
gBattlerAbility = battler;
|
||||
}
|
||||
if (currentPP + ppRestored > maxPP)
|
||||
changedPP = maxPP;
|
||||
else
|
||||
changedPP = currentPP + ppRestored;
|
||||
|
||||
PREPARE_MOVE_BUFFER(gBattleTextBuff1, move);
|
||||
|
||||
if (timing == IsOnSwitchInFirstTurnActivation)
|
||||
BattleScriptExecute(BattleScript_BerryPPHealEnd2);
|
||||
else
|
||||
BattleScriptCall(BattleScript_BerryPPHealRet);
|
||||
|
||||
gBattleScripting.battler = battler;
|
||||
BtlController_EmitSetMonData(battler, B_COMM_TO_CONTROLLER, i + REQUEST_PPMOVE1_BATTLE, 0, 1, &changedPP);
|
||||
MarkBattlerForControllerExec(battler);
|
||||
if (MOVE_IS_PERMANENT(battler, i))
|
||||
gBattleMons[battler].pp[i] = changedPP;
|
||||
effect = ITEM_PP_CHANGE;
|
||||
restoreMove = i;
|
||||
break;
|
||||
}
|
||||
|
||||
if (override && missingMove == MAX_MON_MOVES)
|
||||
{
|
||||
u32 maxPP = CalculatePPWithBonus(move, ppBonuses, i);
|
||||
if (currentPP < maxPP)
|
||||
missingMove = i;
|
||||
}
|
||||
}
|
||||
|
||||
if (restoreMove == MAX_MON_MOVES && override)
|
||||
restoreMove = missingMove;
|
||||
|
||||
if (restoreMove != MAX_MON_MOVES)
|
||||
{
|
||||
u32 move = GetMonData(mon, MON_DATA_MOVE1 + restoreMove);
|
||||
u32 currentPP = GetMonData(mon, MON_DATA_PP1 + restoreMove);
|
||||
u32 maxPP = CalculatePPWithBonus(move, ppBonuses, restoreMove);
|
||||
u32 ppRestored = GetItemHoldEffectParam(itemId);
|
||||
|
||||
if (ability == ABILITY_RIPEN)
|
||||
{
|
||||
ppRestored *= 2;
|
||||
gBattlerAbility = battler;
|
||||
}
|
||||
changedPP = currentPP + ppRestored;
|
||||
if (changedPP > maxPP)
|
||||
changedPP = maxPP;
|
||||
|
||||
PREPARE_MOVE_BUFFER(gBattleTextBuff1, move);
|
||||
|
||||
if (timing == IsOnSwitchInFirstTurnActivation)
|
||||
BattleScriptExecute(BattleScript_BerryPPHealEnd2);
|
||||
else
|
||||
BattleScriptCall(BattleScript_BerryPPHealRet);
|
||||
|
||||
gBattleScripting.battler = battler;
|
||||
BtlController_EmitSetMonData(battler, B_COMM_TO_CONTROLLER, restoreMove + REQUEST_PPMOVE1_BATTLE, 0, 1, &changedPP);
|
||||
MarkBattlerForControllerExec(battler);
|
||||
if (MOVE_IS_PERMANENT(battler, restoreMove))
|
||||
gBattleMons[battler].pp[restoreMove] = changedPP;
|
||||
effect = ITEM_PP_CHANGE;
|
||||
}
|
||||
return effect;
|
||||
}
|
||||
|
||||
@ -3010,7 +3010,7 @@ static void ClearSetBScriptingStruct(void)
|
||||
gBattleScripting.battleStyle = OPTIONS_BATTLE_STYLE_SET;
|
||||
else
|
||||
gBattleScripting.battleStyle = gSaveBlock2Ptr->optionsBattleStyle;
|
||||
gBattleScripting.expOnCatch = (GetConfig(CONFIG_EXP_CATCH) >= GEN_6);
|
||||
gBattleScripting.expOnCatch = (GetConfig(B_EXP_CATCH) >= GEN_6);
|
||||
gBattleScripting.specialTrainerBattleType = specialBattleType;
|
||||
}
|
||||
|
||||
@ -3304,8 +3304,10 @@ const u8* FaintClearSetData(u32 battler)
|
||||
gBattleMons[battler].statStages[i] = DEFAULT_STAT_STAGE;
|
||||
|
||||
bool32 keepGastroAcid = gBattleMons[battler].volatiles.gastroAcid;
|
||||
bool32 keepTransformed = gBattleMons[battler].volatiles.transformed;
|
||||
memset(&gBattleMons[battler].volatiles, 0, sizeof(struct Volatiles));
|
||||
gBattleMons[battler].volatiles.gastroAcid = keepGastroAcid; // Edge case: Keep Gastro Acid if pokemon's ability can have effect after fainting, for example Innards Out.
|
||||
gBattleMons[battler].volatiles.transformed = keepTransformed; // Edge case: Keep Transformed status to prevent triggering FORM_CHANGE_FAINT on transformed mons.
|
||||
|
||||
for (i = 0; i < gBattlersCount; i++)
|
||||
{
|
||||
@ -4106,7 +4108,7 @@ u8 IsRunningFromBattleImpossible(u32 battler)
|
||||
|
||||
if (holdEffect == HOLD_EFFECT_CAN_ALWAYS_RUN)
|
||||
return BATTLE_RUN_SUCCESS;
|
||||
if (GetConfig(CONFIG_GHOSTS_ESCAPE) >= GEN_6 && IS_BATTLER_OF_TYPE(battler, TYPE_GHOST))
|
||||
if (GetConfig(B_GHOSTS_ESCAPE) >= GEN_6 && IS_BATTLER_OF_TYPE(battler, TYPE_GHOST))
|
||||
return BATTLE_RUN_SUCCESS;
|
||||
if (gBattleTypeFlags & BATTLE_TYPE_LINK)
|
||||
return BATTLE_RUN_SUCCESS;
|
||||
@ -4273,7 +4275,7 @@ static void HandleTurnActionSelectionState(void)
|
||||
gBattleStruct->moveTarget[battler] = gBattleResources->bufferB[battler][3];
|
||||
return;
|
||||
}
|
||||
else if (GetConfig(CONFIG_ENCORE_TARGET) < GEN_5 && gDisableStructs[battler].encoredMove != MOVE_NONE)
|
||||
else if (GetConfig(B_ENCORE_TARGET) < GEN_5 && gDisableStructs[battler].encoredMove != MOVE_NONE)
|
||||
{
|
||||
gChosenMoveByBattler[battler] = gDisableStructs[battler].encoredMove;
|
||||
gBattleStruct->chosenMovePositions[battler] = gDisableStructs[battler].encoredMovePos;
|
||||
@ -4815,7 +4817,7 @@ u32 GetBattlerTotalSpeedStat(u32 battler, enum Ability ability, enum HoldEffect
|
||||
|
||||
// paralysis drop
|
||||
if (gBattleMons[battler].status1 & STATUS1_PARALYSIS && ability != ABILITY_QUICK_FEET)
|
||||
speed /= GetConfig(CONFIG_PARALYSIS_SPEED) >= GEN_7 ? 2 : 4;
|
||||
speed /= GetConfig(B_PARALYSIS_SPEED) >= GEN_7 ? 2 : 4;
|
||||
|
||||
if (gSideStatuses[GetBattlerSide(battler)] & SIDE_STATUS_SWAMP)
|
||||
speed /= 4;
|
||||
@ -4854,7 +4856,7 @@ s32 GetBattleMovePriority(u32 battler, enum Ability ability, u32 move)
|
||||
priority = -8;
|
||||
}
|
||||
else if (ability == ABILITY_GALE_WINGS
|
||||
&& (GetConfig(CONFIG_GALE_WINGS) < GEN_7 || IsBattlerAtMaxHp(battler))
|
||||
&& (GetConfig(B_GALE_WINGS) < GEN_7 || IsBattlerAtMaxHp(battler))
|
||||
&& GetMoveType(move) == TYPE_FLYING)
|
||||
{
|
||||
priority++;
|
||||
@ -5212,7 +5214,7 @@ static bool32 TryDoGimmicksBeforeMoves(void)
|
||||
}
|
||||
}
|
||||
|
||||
if (GetConfig(CONFIG_MEGA_EVO_TURN_ORDER) >= GEN_7)
|
||||
if (GetConfig(B_MEGA_EVO_TURN_ORDER) >= GEN_7)
|
||||
TryChangeTurnOrder(); // This will just do nothing if no mon has mega evolved.
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@ -862,7 +862,7 @@ static bool8 DoesTypePreventStatus(u16 species, u32 status)
|
||||
break;
|
||||
case STATUS1_PARALYSIS:
|
||||
if (GetSpeciesType(species, 0) == TYPE_GROUND || GetSpeciesType(species, 1) == TYPE_GROUND
|
||||
|| (GetConfig(CONFIG_PARALYZE_ELECTRIC) >= GEN_6 && (GetSpeciesType(species, 0) == TYPE_ELECTRIC || GetSpeciesType(species, 1) == TYPE_ELECTRIC)))
|
||||
|| (GetConfig(B_PARALYZE_ELECTRIC) >= GEN_6 && (GetSpeciesType(species, 0) == TYPE_ELECTRIC || GetSpeciesType(species, 1) == TYPE_ELECTRIC)))
|
||||
ret = TRUE;
|
||||
break;
|
||||
case STATUS1_BURN:
|
||||
|
||||
@ -1584,11 +1584,11 @@ static const u32 sGen2CriticalHitOdds[] = {17, 32, 64, 85, 128}; // X/256
|
||||
|
||||
static inline u32 GetCriticalHitOdds(u32 critChance)
|
||||
{
|
||||
if (GetConfig(CONFIG_CRIT_CHANCE) >= GEN_7)
|
||||
if (GetConfig(B_CRIT_CHANCE) >= GEN_7)
|
||||
return sGen7CriticalHitOdds[critChance];
|
||||
if (GetConfig(CONFIG_CRIT_CHANCE) == GEN_6)
|
||||
if (GetConfig(B_CRIT_CHANCE) == GEN_6)
|
||||
return sGen6CriticalHitOdds[critChance];
|
||||
if (GetConfig(CONFIG_CRIT_CHANCE) == GEN_2)
|
||||
if (GetConfig(B_CRIT_CHANCE) == GEN_2)
|
||||
return sGen2CriticalHitOdds[critChance];
|
||||
|
||||
return sCriticalHitOdds[critChance];
|
||||
@ -1765,7 +1765,7 @@ static void Cmd_critcalc(void)
|
||||
enum Ability abilityDef = GetBattlerAbility(battlerDef);
|
||||
enum Ability abilityAtk = GetBattlerAbility(gBattlerAttacker);
|
||||
|
||||
if (GetConfig(CONFIG_CRIT_CHANCE) == GEN_1)
|
||||
if (GetConfig(B_CRIT_CHANCE) == GEN_1)
|
||||
gBattleStruct->critChance[battlerDef] = CalcCritChanceStageGen1(gBattlerAttacker, battlerDef, gCurrentMove, TRUE, abilityAtk, abilityDef, holdEffectAtk);
|
||||
else
|
||||
gBattleStruct->critChance[battlerDef] = CalcCritChanceStage(gBattlerAttacker, battlerDef, gCurrentMove, TRUE, abilityAtk, abilityDef, holdEffectAtk);
|
||||
@ -1778,9 +1778,9 @@ static void Cmd_critcalc(void)
|
||||
gSpecialStatuses[battlerDef].criticalHit = TRUE;
|
||||
else
|
||||
{
|
||||
if (GetConfig(CONFIG_CRIT_CHANCE) == GEN_1)
|
||||
if (GetConfig(B_CRIT_CHANCE) == GEN_1)
|
||||
gSpecialStatuses[battlerDef].criticalHit = RandomChance(RNG_CRITICAL_HIT, gBattleStruct->critChance[battlerDef], 256);
|
||||
else if (GetConfig(CONFIG_CRIT_CHANCE) == GEN_2)
|
||||
else if (GetConfig(B_CRIT_CHANCE) == GEN_2)
|
||||
gSpecialStatuses[battlerDef].criticalHit = RandomChance(RNG_CRITICAL_HIT, GetCriticalHitOdds(gBattleStruct->critChance[battlerDef]), 256);
|
||||
else
|
||||
gSpecialStatuses[battlerDef].criticalHit = RandomChance(RNG_CRITICAL_HIT, 1, GetCriticalHitOdds(gBattleStruct->critChance[battlerDef]));
|
||||
@ -1949,7 +1949,7 @@ static void Cmd_adjustdamage(void)
|
||||
gLastUsedItem = gBattleMons[battlerDef].item;
|
||||
gBattleStruct->moveResultFlags[battlerDef] |= MOVE_RESULT_FOE_HUNG_ON;
|
||||
}
|
||||
else if (GetConfig(CONFIG_STURDY) >= GEN_5 && GetBattlerAbility(battlerDef) == ABILITY_STURDY && IsBattlerAtMaxHp(battlerDef))
|
||||
else if (GetConfig(B_STURDY) >= GEN_5 && GetBattlerAbility(battlerDef) == ABILITY_STURDY && IsBattlerAtMaxHp(battlerDef))
|
||||
{
|
||||
enduredHit |= 1u << battlerDef;
|
||||
RecordAbilityBattle(battlerDef, ABILITY_STURDY);
|
||||
@ -2418,7 +2418,7 @@ static void MoveDamageDataHpUpdate(u32 battler, u32 scriptBattler, const u8 *nex
|
||||
gBattleMons[battler].species = SPECIES_MIMIKYU_BUSTED_TOTEM;
|
||||
else
|
||||
gBattleMons[battler].species = SPECIES_MIMIKYU_BUSTED;
|
||||
if (GetConfig(CONFIG_DISGUISE_HP_LOSS) >= GEN_8)
|
||||
if (GetConfig(B_DISGUISE_HP_LOSS) >= GEN_8)
|
||||
SetPassiveDamageAmount(battler, GetNonDynamaxMaxHP(battler) / 8);
|
||||
BattleScriptPush(nextInstr);
|
||||
gBattlescriptCurrInstr = BattleScript_TargetFormChange;
|
||||
@ -2851,7 +2851,7 @@ static void Cmd_printselectionstringfromtable(void)
|
||||
bool32 HasBattlerActedThisTurn(u32 battler)
|
||||
{
|
||||
u32 i;
|
||||
for (i = 0; i < gCurrentTurnActionNumber; i++)
|
||||
for (i = 0; i <= gCurrentTurnActionNumber; i++)
|
||||
{
|
||||
if (gBattlerByTurnOrder[i] == battler)
|
||||
return TRUE;
|
||||
@ -2882,7 +2882,7 @@ void StealTargetItem(u8 battlerStealer, u8 itemBattler)
|
||||
gLastUsedItem = gBattleMons[itemBattler].item;
|
||||
gBattleMons[itemBattler].item = ITEM_NONE;
|
||||
|
||||
if (GetConfig(CONFIG_STEAL_WILD_ITEMS) >= GEN_9
|
||||
if (GetConfig(B_STEAL_WILD_ITEMS) >= GEN_9
|
||||
&& !(gBattleTypeFlags & (BATTLE_TYPE_TRAINER | BATTLE_TYPE_PALACE))
|
||||
&& GetMoveEffect(gCurrentMove) == EFFECT_STEAL_ITEM
|
||||
&& battlerStealer == gBattlerAttacker) // ensure that Pickpocket isn't activating this
|
||||
@ -3094,7 +3094,7 @@ void SetMoveEffect(u32 battler, u32 effectBattler, enum MoveEffect moveEffect, c
|
||||
case MOVE_EFFECT_PARALYSIS:
|
||||
case MOVE_EFFECT_TOXIC:
|
||||
case MOVE_EFFECT_FROSTBITE:
|
||||
if (gSideStatuses[GetBattlerSide(gEffectBattler)] & SIDE_STATUS_SAFEGUARD && !primary)
|
||||
if (IsSafeguardProtected(gBattlerAttacker, gEffectBattler, GetBattlerAbility(gBattlerAttacker)) && !primary)
|
||||
gBattlescriptCurrInstr = battleScript;
|
||||
else if (CanSetNonVolatileStatus(
|
||||
gBattlerAttacker,
|
||||
@ -3108,7 +3108,7 @@ void SetMoveEffect(u32 battler, u32 effectBattler, enum MoveEffect moveEffect, c
|
||||
case MOVE_EFFECT_CONFUSION:
|
||||
if (!CanBeConfused(gEffectBattler)
|
||||
|| gBattleMons[gEffectBattler].volatiles.confusionTurns
|
||||
|| (gSideStatuses[GetBattlerSide(gEffectBattler)] & SIDE_STATUS_SAFEGUARD && !primary))
|
||||
|| (IsSafeguardProtected(gBattlerAttacker, gEffectBattler, GetBattlerAbility(gBattlerAttacker)) && !primary))
|
||||
{
|
||||
gBattlescriptCurrInstr = battleScript;
|
||||
}
|
||||
@ -3236,9 +3236,9 @@ void SetMoveEffect(u32 battler, u32 effectBattler, enum MoveEffect moveEffect, c
|
||||
else
|
||||
{
|
||||
if (GetBattlerHoldEffect(gBattlerAttacker) == HOLD_EFFECT_GRIP_CLAW)
|
||||
gDisableStructs[gEffectBattler].wrapTurns = GetConfig(CONFIG_BINDING_TURNS) >= GEN_5 ? 7 : 5;
|
||||
gDisableStructs[gEffectBattler].wrapTurns = GetConfig(B_BINDING_TURNS) >= GEN_5 ? 7 : 5;
|
||||
else
|
||||
gDisableStructs[gEffectBattler].wrapTurns = GetConfig(CONFIG_BINDING_TURNS) >= GEN_5 ? RandomUniform(RNG_WRAP, 4, 5) : RandomUniform(RNG_WRAP, 2, 5);
|
||||
gDisableStructs[gEffectBattler].wrapTurns = GetConfig(B_BINDING_TURNS) >= GEN_5 ? RandomUniform(RNG_WRAP, 4, 5) : RandomUniform(RNG_WRAP, 2, 5);
|
||||
gBattleMons[gEffectBattler].volatiles.wrapped = TRUE;
|
||||
gBattleMons[gEffectBattler].volatiles.wrappedMove = gCurrentMove;
|
||||
gBattleMons[gEffectBattler].volatiles.wrappedBy = gBattlerAttacker;
|
||||
@ -3497,8 +3497,9 @@ void SetMoveEffect(u32 battler, u32 effectBattler, enum MoveEffect moveEffect, c
|
||||
gBattlescriptCurrInstr = battleScript;
|
||||
break;
|
||||
case MOVE_EFFECT_INCINERATE:
|
||||
if ((gBattleMons[gEffectBattler].item >= FIRST_BERRY_INDEX && gBattleMons[gEffectBattler].item <= LAST_BERRY_INDEX)
|
||||
|| (B_INCINERATE_GEMS >= GEN_6 && GetBattlerHoldEffect(gEffectBattler) == HOLD_EFFECT_GEMS))
|
||||
if (((gBattleMons[gEffectBattler].item >= FIRST_BERRY_INDEX && gBattleMons[gEffectBattler].item <= LAST_BERRY_INDEX)
|
||||
|| (B_INCINERATE_GEMS >= GEN_6 && GetBattlerHoldEffect(gEffectBattler) == HOLD_EFFECT_GEMS))
|
||||
&& battlerAbility != ABILITY_STICKY_HOLD)
|
||||
{
|
||||
gLastUsedItem = gBattleMons[gEffectBattler].item;
|
||||
gBattleMons[gEffectBattler].item = 0;
|
||||
@ -3998,7 +3999,7 @@ void SetMoveEffect(u32 battler, u32 effectBattler, enum MoveEffect moveEffect, c
|
||||
{
|
||||
gBattleMons[battler].volatiles.wrapped = TRUE;
|
||||
if (GetBattlerHoldEffect(gBattlerAttacker) == HOLD_EFFECT_GRIP_CLAW)
|
||||
gDisableStructs[battler].wrapTurns = (GetConfig(CONFIG_BINDING_TURNS) >= GEN_5) ? 7 : 5;
|
||||
gDisableStructs[battler].wrapTurns = (GetConfig(B_BINDING_TURNS) >= GEN_5) ? 7 : 5;
|
||||
else
|
||||
gDisableStructs[battler].wrapTurns = (Random() % 2) + 4;
|
||||
// The Wrap effect does not expire when the user switches, so here's some cheese.
|
||||
@ -5417,7 +5418,7 @@ static void Cmd_isdmgblockedbydisguise(void)
|
||||
gBattleMons[gBattlerAttacker].species = SPECIES_MIMIKYU_BUSTED_TOTEM;
|
||||
else
|
||||
gBattleMons[gBattlerAttacker].species = SPECIES_MIMIKYU_BUSTED;
|
||||
if (GetConfig(CONFIG_DISGUISE_HP_LOSS) >= GEN_8)
|
||||
if (GetConfig(B_DISGUISE_HP_LOSS) >= GEN_8)
|
||||
SetPassiveDamageAmount(gBattlerAttacker, GetNonDynamaxMaxHP(gBattlerAttacker) / 8);
|
||||
BattleScriptPush(BattleScript_MoveEnd);
|
||||
gBattlescriptCurrInstr = BattleScript_TargetFormChange;
|
||||
@ -5744,7 +5745,7 @@ static bool32 HandleMoveEndAbilityBlock(u32 battlerAtk, u32 battlerDef, u32 move
|
||||
if (GetBattlerPartyState(battlerAtk)->battleBondBoost)
|
||||
break;
|
||||
|
||||
if (GetConfig(CONFIG_BATTLE_BOND) < GEN_9 && gBattleMons[battlerAtk].species == SPECIES_GRENINJA_BATTLE_BOND)
|
||||
if (GetConfig(B_BATTLE_BOND) < GEN_9 && gBattleMons[battlerAtk].species == SPECIES_GRENINJA_BATTLE_BOND)
|
||||
{
|
||||
// TODO: Convert this to a proper FORM_CHANGE type.
|
||||
gLastUsedAbility = abilityAtk;
|
||||
@ -5866,7 +5867,7 @@ static bool32 HandleMoveEndMoveBlock(u32 moveEffect)
|
||||
{
|
||||
StealTargetItem(gBattlerAttacker, gBattlerTarget); // Attacker steals target item
|
||||
|
||||
if (!(GetConfig(CONFIG_STEAL_WILD_ITEMS) >= GEN_9
|
||||
if (!(GetConfig(B_STEAL_WILD_ITEMS) >= GEN_9
|
||||
&& !(gBattleTypeFlags & (BATTLE_TYPE_TRAINER | BATTLE_TYPE_PALACE))))
|
||||
{
|
||||
gBattleMons[gBattlerAttacker].item = ITEM_NONE; // Item assigned later on with thief (see MOVEEND_CHANGED_ITEMS)
|
||||
@ -6019,7 +6020,7 @@ static bool32 HandleMoveEndMoveBlock(u32 moveEffect)
|
||||
&& !NoAliveMonsForEitherParty()
|
||||
&& CompareStat(gBattlerAttacker, STAT_ATK, MAX_STAT_STAGE, CMP_LESS_THAN, GetBattlerAbility(gBattlerAttacker)))
|
||||
{
|
||||
SET_STATCHANGER(STAT_ATK, GetConfig(CONFIG_FELL_STINGER_STAT_RAISE) >= GEN_7 ? 3 : 2, FALSE);
|
||||
SET_STATCHANGER(STAT_ATK, GetConfig(B_FELL_STINGER_STAT_RAISE) >= GEN_7 ? 3 : 2, FALSE);
|
||||
PREPARE_STAT_BUFFER(gBattleTextBuff1, STAT_ATK);
|
||||
BattleScriptPushCursor();
|
||||
gBattlescriptCurrInstr = BattleScript_FellStingerRaisesStat;
|
||||
@ -6240,7 +6241,7 @@ static void Cmd_moveend(void)
|
||||
s32 healAmount = (gBattleStruct->moveDamage[gBattlerTarget] * GetMoveAbsorbPercentage(gCurrentMove) / 100);
|
||||
healAmount = GetDrainedBigRootHp(gBattlerAttacker, healAmount);
|
||||
effect = TRUE;
|
||||
if ((moveEffect == EFFECT_DREAM_EATER && GetConfig(CONFIG_DREAM_EATER_LIQUID_OOZE) < GEN_5)
|
||||
if ((moveEffect == EFFECT_DREAM_EATER && GetConfig(B_DREAM_EATER_LIQUID_OOZE) < GEN_5)
|
||||
|| GetBattlerAbility(gBattlerTarget) != ABILITY_LIQUID_OOZE)
|
||||
{
|
||||
SetHealAmount(gBattlerAttacker, healAmount);
|
||||
@ -6333,7 +6334,7 @@ static void Cmd_moveend(void)
|
||||
for (i = 0; i < gBattlersCount; i++)
|
||||
{
|
||||
if ((gSpecialStatuses[i].berryReduced
|
||||
|| (GetConfig(CONFIG_SYMBIOSIS_GEMS) >= GEN_7 && gSpecialStatuses[i].gemBoost))
|
||||
|| (GetConfig(B_SYMBIOSIS_GEMS) >= GEN_7 && gSpecialStatuses[i].gemBoost))
|
||||
&& TryTriggerSymbiosis(i, BATTLE_PARTNER(i)))
|
||||
{
|
||||
BestowItem(BATTLE_PARTNER(i), i);
|
||||
@ -6848,7 +6849,9 @@ static void Cmd_moveend(void)
|
||||
|
||||
for (i = 0; i < gBattlersCount; i++)
|
||||
{
|
||||
if (IsBattlerTurnDamaged(i) && EmergencyExitCanBeTriggered(i))
|
||||
if (!IsBattleMoveStatus(gCurrentMove)
|
||||
&& !(gHitMarker & HITMARKER_UNABLE_TO_USE_MOVE)
|
||||
&& EmergencyExitCanBeTriggered(i))
|
||||
{
|
||||
emergencyExitBattlers |= 1u << i;
|
||||
numEmergencyExitBattlers++;
|
||||
@ -7001,11 +7004,21 @@ static void Cmd_moveend(void)
|
||||
gBattleScripting.moveendState++;
|
||||
break;
|
||||
case MOVEEND_PICKPOCKET:
|
||||
{
|
||||
u16 attackerItem = gBattleMons[gBattlerAttacker].item;
|
||||
bool32 hasPendingStolenItem = FALSE;
|
||||
|
||||
if (attackerItem == ITEM_NONE
|
||||
&& GetMoveEffect(gCurrentMove) == EFFECT_STEAL_ITEM
|
||||
&& gBattleStruct->changedItems[gBattlerAttacker] != ITEM_NONE)
|
||||
{
|
||||
attackerItem = gBattleStruct->changedItems[gBattlerAttacker];
|
||||
hasPendingStolenItem = TRUE;
|
||||
}
|
||||
|
||||
if (IsBattlerAlive(gBattlerAttacker)
|
||||
&& gBattleMons[gBattlerAttacker].item != ITEM_NONE // Attacker must be holding an item
|
||||
&& !(gWishFutureKnock.knockedOffMons[GetBattlerSide(gBattlerAttacker)] & (1u << gBattlerPartyIndexes[gBattlerAttacker])) // But not knocked off
|
||||
&& IsMoveMakingContact(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerAttacker), GetBattlerHoldEffect(gBattlerAttacker), gCurrentMove) // Pickpocket requires contact
|
||||
&& !(gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_NO_EFFECT)) // Obviously attack needs to have worked
|
||||
&& attackerItem != ITEM_NONE // Attacker must have an item (including pending stolen item)
|
||||
&& !(gWishFutureKnock.knockedOffMons[GetBattlerSide(gBattlerAttacker)] & (1u << gBattlerPartyIndexes[gBattlerAttacker]))) // But not knocked off
|
||||
{
|
||||
u8 battlers[4] = {0, 1, 2, 3};
|
||||
SortBattlersBySpeed(battlers, FALSE); // Pickpocket activates for fastest mon without item
|
||||
@ -7016,12 +7029,19 @@ static void Cmd_moveend(void)
|
||||
if (battler != gBattlerAttacker // Cannot pickpocket yourself
|
||||
&& GetBattlerAbility(battler) == ABILITY_PICKPOCKET // Target must have pickpocket ability
|
||||
&& IsBattlerTurnDamaged(battler) // Target needs to have been damaged
|
||||
&& IsMoveMakingContact(gBattlerAttacker, battler, GetBattlerAbility(gBattlerAttacker), GetBattlerHoldEffect(gBattlerAttacker), gCurrentMove) // Pickpocket requires contact
|
||||
&& !(gBattleStruct->moveResultFlags[battler] & MOVE_RESULT_NO_EFFECT) // Move needs to have affected this battler
|
||||
&& !DoesSubstituteBlockMove(gBattlerAttacker, battler, gCurrentMove) // Subsitute unaffected
|
||||
&& IsBattlerAlive(battler) // Battler must be alive to pickpocket
|
||||
&& gBattleMons[battler].item == ITEM_NONE // Pickpocketer can't have an item already
|
||||
&& CanStealItem(battler, gBattlerAttacker, gBattleMons[gBattlerAttacker].item)) // Cannot steal plates, mega stones, etc
|
||||
&& CanStealItem(battler, gBattlerAttacker, attackerItem)) // Cannot steal plates, mega stones, etc
|
||||
{
|
||||
gBattlerTarget = gBattlerAbility = battler;
|
||||
if (hasPendingStolenItem)
|
||||
{
|
||||
gBattleMons[gBattlerAttacker].item = attackerItem;
|
||||
gBattleStruct->changedItems[gBattlerAttacker] = ITEM_NONE;
|
||||
}
|
||||
// Battle scripting is super brittle so we shall do the item exchange now (if possible)
|
||||
if (GetBattlerAbility(gBattlerAttacker) != ABILITY_STICKY_HOLD)
|
||||
StealTargetItem(gBattlerTarget, gBattlerAttacker); // Target takes attacker's item
|
||||
@ -7035,6 +7055,7 @@ static void Cmd_moveend(void)
|
||||
}
|
||||
gBattleScripting.moveendState++;
|
||||
break;
|
||||
}
|
||||
case MOVEEND_THIRD_MOVE_BLOCK:
|
||||
switch (moveEffect)
|
||||
{
|
||||
@ -7983,7 +8004,7 @@ static bool32 DoSwitchInEffectsForBattler(u32 battler)
|
||||
// Starting from Gen8 - it heals only pokemon which can be healed.
|
||||
// In Gen5-7 the effect activates anyways.
|
||||
else if ((gBattleStruct->battlerState[battler].storedHealingWish)
|
||||
&& (GetConfig(CONFIG_HEALING_WISH_SWITCH) < GEN_8
|
||||
&& (GetConfig(B_HEALING_WISH_SWITCH) < GEN_8
|
||||
|| gBattleMons[battler].hp != gBattleMons[battler].maxHP
|
||||
|| gBattleMons[battler].status1 != 0))
|
||||
{
|
||||
@ -7992,7 +8013,7 @@ static bool32 DoSwitchInEffectsForBattler(u32 battler)
|
||||
gBattleStruct->battlerState[battler].storedHealingWish = FALSE;
|
||||
}
|
||||
else if ((gBattleStruct->battlerState[battler].storedLunarDance)
|
||||
&& (GetConfig(CONFIG_HEALING_WISH_SWITCH) < GEN_8
|
||||
&& (GetConfig(B_HEALING_WISH_SWITCH) < GEN_8
|
||||
|| gBattleMons[battler].hp != gBattleMons[battler].maxHP
|
||||
|| gBattleMons[battler].status1 != 0
|
||||
|| gBattleMons[battler].pp[0] < CalculatePPWithBonus(gBattleMons[battler].moves[0], gBattleMons[battler].ppBonuses, 0)
|
||||
@ -8848,7 +8869,7 @@ static bool32 TrySymbiosis(u32 battler, u32 itemId, bool32 moveEnd)
|
||||
&& gBattleStruct->changedItems[battler] == ITEM_NONE
|
||||
&& GetBattlerHoldEffect(battler) != HOLD_EFFECT_EJECT_BUTTON
|
||||
&& GetBattlerHoldEffect(battler) != HOLD_EFFECT_EJECT_PACK
|
||||
&& (GetConfig(CONFIG_SYMBIOSIS_GEMS) < GEN_7 || !(gSpecialStatuses[battler].gemBoost))
|
||||
&& (GetConfig(B_SYMBIOSIS_GEMS) < GEN_7 || !(gSpecialStatuses[battler].gemBoost))
|
||||
&& GetMoveEffect(gCurrentMove) != EFFECT_FLING //Fling and damage-reducing berries are handled separately.
|
||||
&& !gSpecialStatuses[battler].berryReduced
|
||||
&& TryTriggerSymbiosis(battler, BATTLE_PARTNER(battler)))
|
||||
@ -9442,7 +9463,7 @@ static bool32 TryDefogClear(u32 battlerAtk, bool32 clear)
|
||||
DEFOG_CLEAR(SIDE_STATUS_AURORA_VEIL, auroraVeilTimer, BattleScript_SideStatusWoreOffReturn, MOVE_AURORA_VEIL);
|
||||
DEFOG_CLEAR(SIDE_STATUS_SAFEGUARD, safeguardTimer, BattleScript_SideStatusWoreOffReturn, MOVE_SAFEGUARD);
|
||||
}
|
||||
if (GetConfig(CONFIG_DEFOG_EFFECT_CLEARING) >= GEN_6)
|
||||
if (GetConfig(B_DEFOG_EFFECT_CLEARING) >= GEN_6)
|
||||
{
|
||||
gBattlerAttacker = i; // For correct battle string. Ally's / Foe's
|
||||
if (DefogClearHazards(saveBattler, i, clear))
|
||||
@ -9457,7 +9478,7 @@ static bool32 TryDefogClear(u32 battlerAtk, bool32 clear)
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
if (GetConfig(CONFIG_DEFOG_EFFECT_CLEARING) >= GEN_8 && (gFieldStatuses & STATUS_FIELD_TERRAIN_ANY))
|
||||
if (GetConfig(B_DEFOG_EFFECT_CLEARING) >= GEN_8 && (gFieldStatuses & STATUS_FIELD_TERRAIN_ANY))
|
||||
{
|
||||
if (clear)
|
||||
{
|
||||
@ -9561,7 +9582,7 @@ static bool32 IsElectricAbilityAffected(u32 battler, enum Ability ability)
|
||||
moveType = GetMoveType(gCurrentMove);
|
||||
|
||||
if (moveType == TYPE_ELECTRIC
|
||||
&& (ability != ABILITY_LIGHTNING_ROD || GetConfig(CONFIG_REDIRECT_ABILITY_IMMUNITY) >= GEN_5)
|
||||
&& (ability != ABILITY_LIGHTNING_ROD || GetConfig(B_REDIRECT_ABILITY_IMMUNITY) >= GEN_5)
|
||||
&& GetBattlerAbility(battler) == ability)
|
||||
return TRUE;
|
||||
else
|
||||
@ -9691,7 +9712,7 @@ static bool32 ChangeOrderTargetAfterAttacker(void)
|
||||
if (attackerTurnOrderNum > targetTurnOrderNum)
|
||||
return FALSE;
|
||||
if (attackerTurnOrderNum + 1 == targetTurnOrderNum)
|
||||
return GetConfig(CONFIG_AFTER_YOU_TURN_ORDER) >= GEN_8;
|
||||
return GetConfig(B_AFTER_YOU_TURN_ORDER) >= GEN_8;
|
||||
|
||||
for (i = 0; i < MAX_BATTLERS_COUNT; i++)
|
||||
{
|
||||
@ -9734,8 +9755,8 @@ static void TryResetProtectUseCounter(u32 battler)
|
||||
enum BattleMoveEffects lastEffect = GetMoveEffect(lastMove);
|
||||
if (lastMove == MOVE_UNAVAILABLE
|
||||
|| (!gBattleMoveEffects[lastEffect].usesProtectCounter
|
||||
&& ((GetConfig(CONFIG_ALLY_SWITCH_FAIL_CHANCE) >= GEN_9 && lastEffect != EFFECT_ALLY_SWITCH)
|
||||
|| GetConfig(CONFIG_ALLY_SWITCH_FAIL_CHANCE) < GEN_9)))
|
||||
&& ((GetConfig(B_ALLY_SWITCH_FAIL_CHANCE) >= GEN_9 && lastEffect != EFFECT_ALLY_SWITCH)
|
||||
|| GetConfig(B_ALLY_SWITCH_FAIL_CHANCE) < GEN_9)))
|
||||
gDisableStructs[battler].protectUses = 0;
|
||||
}
|
||||
|
||||
@ -9752,8 +9773,8 @@ static void Cmd_setprotectlike(void)
|
||||
notLastTurn = FALSE;
|
||||
|
||||
if ((sProtectSuccessRates[gDisableStructs[gBattlerAttacker].protectUses] >= RandomUniform(RNG_PROTECT_FAIL, 0, USHRT_MAX) && notLastTurn)
|
||||
|| (protectMethod == PROTECT_WIDE_GUARD && GetConfig(CONFIG_WIDE_GUARD) >= GEN_6)
|
||||
|| (protectMethod == PROTECT_QUICK_GUARD && GetConfig(CONFIG_QUICK_GUARD) >= GEN_6)
|
||||
|| (protectMethod == PROTECT_WIDE_GUARD && GetConfig(B_WIDE_GUARD) >= GEN_6)
|
||||
|| (protectMethod == PROTECT_QUICK_GUARD && GetConfig(B_QUICK_GUARD) >= GEN_6)
|
||||
|| (protectMethod == PROTECT_CRAFTY_SHIELD))
|
||||
{
|
||||
if (GetMoveEffect(gCurrentMove) == EFFECT_ENDURE)
|
||||
@ -10210,7 +10231,7 @@ static void TryPlayStatChangeAnimation(u32 battler, enum Ability ability, u32 st
|
||||
}
|
||||
}
|
||||
else if (!((ability == ABILITY_KEEN_EYE || ability == ABILITY_MINDS_EYE) && currStat == STAT_ACC)
|
||||
&& !(GetConfig(CONFIG_ILLUMINATE_EFFECT) >= GEN_9 && ability == ABILITY_ILLUMINATE && currStat == STAT_ACC)
|
||||
&& !(GetConfig(B_ILLUMINATE_EFFECT) >= GEN_9 && ability == ABILITY_ILLUMINATE && currStat == STAT_ACC)
|
||||
&& !(ability == ABILITY_HYPER_CUTTER && currStat == STAT_ATK)
|
||||
&& !(ability == ABILITY_BIG_PECKS && currStat == STAT_DEF))
|
||||
{
|
||||
@ -10302,7 +10323,7 @@ static u32 ChangeStatBuffs(u32 battler, s8 statValue, enum Stat statId, union St
|
||||
{
|
||||
if (gSideTimers[GetBattlerSide(battler)].mistTimer
|
||||
&& !flags.certain && gCurrentMove != MOVE_CURSE
|
||||
&& !(battler == gBattlerTarget && GetBattlerAbility(gBattlerAttacker) == ABILITY_INFILTRATOR))
|
||||
&& !(battler == gBattlerTarget && GetBattlerAbility(gBattlerAttacker) == ABILITY_INFILTRATOR && !IsBattlerAlly(gBattlerAttacker, battler)))
|
||||
{
|
||||
if (flags.allowPtr)
|
||||
{
|
||||
@ -10379,7 +10400,7 @@ static u32 ChangeStatBuffs(u32 battler, s8 statValue, enum Stat statId, union St
|
||||
}
|
||||
else if (!flags.certain
|
||||
&& (((battlerAbility == ABILITY_KEEN_EYE || battlerAbility == ABILITY_MINDS_EYE) && statId == STAT_ACC)
|
||||
|| (GetConfig(CONFIG_ILLUMINATE_EFFECT) >= GEN_9 && battlerAbility == ABILITY_ILLUMINATE && statId == STAT_ACC)
|
||||
|| (GetConfig(B_ILLUMINATE_EFFECT) >= GEN_9 && battlerAbility == ABILITY_ILLUMINATE && statId == STAT_ACC)
|
||||
|| (battlerAbility == ABILITY_HYPER_CUTTER && statId == STAT_ATK)
|
||||
|| (battlerAbility == ABILITY_BIG_PECKS && statId == STAT_DEF)))
|
||||
{
|
||||
@ -11228,8 +11249,8 @@ static void Cmd_setfocusenergy(void)
|
||||
}
|
||||
else
|
||||
{
|
||||
if (GetConfig(CONFIG_FOCUS_ENERGY_CRIT_RATIO) >= GEN_3
|
||||
|| GetConfig(CONFIG_CRIT_CHANCE) == GEN_1)
|
||||
if (GetConfig(B_FOCUS_ENERGY_CRIT_RATIO) >= GEN_3
|
||||
|| GetConfig(B_CRIT_CHANCE) == GEN_1)
|
||||
gBattleMons[battler].volatiles.focusEnergy = TRUE;
|
||||
else
|
||||
gBattleMons[battler].volatiles.dragonCheer = TRUE;
|
||||
@ -11245,6 +11266,7 @@ static void Cmd_transformdataexecution(void)
|
||||
gChosenMove = MOVE_UNAVAILABLE;
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
if (gBattleMons[gBattlerTarget].volatiles.transformed
|
||||
|| DoesSubstituteBlockMove(gBattlerAttacker, gBattlerTarget, gCurrentMove)
|
||||
|| gBattleStruct->illusion[gBattlerTarget].state == ILLUSION_ON
|
||||
|| IsSemiInvulnerable(gBattlerTarget, EXCLUDE_COMMANDER))
|
||||
{
|
||||
@ -11565,7 +11587,7 @@ static void Cmd_settypetorandomresistance(void)
|
||||
u32 moveToCheck;
|
||||
u32 typeToCheck;
|
||||
|
||||
if (GetConfig(CONFIG_UPDATED_CONVERSION_2) < GEN_5)
|
||||
if (GetConfig(B_UPDATED_CONVERSION_2) < GEN_5)
|
||||
{
|
||||
moveToCheck = gLastLandedMoves[gBattlerAttacker];
|
||||
if (GetMoveEffect(moveToCheck) == EFFECT_STRUGGLE)
|
||||
@ -11730,7 +11752,7 @@ static void Cmd_settailwind(void)
|
||||
if (!(gSideStatuses[side] & SIDE_STATUS_TAILWIND))
|
||||
{
|
||||
gSideStatuses[side] |= SIDE_STATUS_TAILWIND;
|
||||
gSideTimers[side].tailwindTimer = (GetConfig(CONFIG_TAILWIND_TURNS) >= GEN_5 ? 4 : 3);
|
||||
gSideTimers[side].tailwindTimer = (GetConfig(B_TAILWIND_TURNS) >= GEN_5 ? 4 : 3);
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
}
|
||||
else
|
||||
@ -11820,8 +11842,8 @@ static void Cmd_healpartystatus(void)
|
||||
struct Pokemon *party = GetBattlerParty(gBattlerAttacker);
|
||||
bool32 isSoundMove = IsSoundMove(gCurrentMove);
|
||||
|
||||
if (GetConfig(CONFIG_HEAL_BELL_SOUNDPROOF) == GEN_5
|
||||
|| GetConfig(CONFIG_HEAL_BELL_SOUNDPROOF) >= GEN_8
|
||||
if (GetConfig(B_HEAL_BELL_SOUNDPROOF) == GEN_5
|
||||
|| GetConfig(B_HEAL_BELL_SOUNDPROOF) >= GEN_8
|
||||
|| !(isSoundMove && GetBattlerAbility(gBattlerAttacker) == ABILITY_SOUNDPROOF))
|
||||
{
|
||||
if (isSoundMove)
|
||||
@ -11841,7 +11863,7 @@ static void Cmd_healpartystatus(void)
|
||||
|
||||
if (IsBattlerAlive(partner))
|
||||
{
|
||||
if (GetConfig(CONFIG_HEAL_BELL_SOUNDPROOF) == GEN_5
|
||||
if (GetConfig(B_HEAL_BELL_SOUNDPROOF) == GEN_5
|
||||
|| !(isSoundMove && GetBattlerAbility(partner) == ABILITY_SOUNDPROOF))
|
||||
{
|
||||
gBattleMons[partner].status1 = 0;
|
||||
@ -11867,10 +11889,10 @@ static void Cmd_healpartystatus(void)
|
||||
bool32 isAttacker = gBattlerPartyIndexes[gBattlerAttacker] == i;
|
||||
bool32 isDoublesPartner = gBattlerPartyIndexes[partner] == i && IsBattlerAlive(partner);
|
||||
|
||||
if (GetConfig(CONFIG_HEAL_BELL_SOUNDPROOF) == GEN_5
|
||||
|| (GetConfig(CONFIG_HEAL_BELL_SOUNDPROOF) >= GEN_8 && isAttacker))
|
||||
if (GetConfig(B_HEAL_BELL_SOUNDPROOF) == GEN_5
|
||||
|| (GetConfig(B_HEAL_BELL_SOUNDPROOF) >= GEN_8 && isAttacker))
|
||||
ability = ABILITY_NONE;
|
||||
else if (GetConfig(CONFIG_HEAL_BELL_SOUNDPROOF) > GEN_5 && !isAttacker && !isDoublesPartner)
|
||||
else if (GetConfig(B_HEAL_BELL_SOUNDPROOF) > GEN_5 && !isAttacker && !isDoublesPartner)
|
||||
ability = ABILITY_NONE;
|
||||
else if (isAttacker)
|
||||
ability = GetBattlerAbility(gBattlerAttacker);
|
||||
@ -12288,7 +12310,15 @@ static void Cmd_copyfoestats(void)
|
||||
{
|
||||
gBattleMons[gBattlerAttacker].statStages[i] = gBattleMons[gBattlerTarget].statStages[i];
|
||||
}
|
||||
gBattleScripting.battler = gBattlerTarget;
|
||||
if (GetConfig(B_PSYCH_UP_CRIT_RATIO) >= GEN_6)
|
||||
{
|
||||
// Copy crit boosts (Focus Energy, Dragon Cheer, G-Max Chi Strike)
|
||||
gBattleMons[gBattlerAttacker].volatiles.focusEnergy = gBattleMons[gBattlerTarget].volatiles.focusEnergy;
|
||||
gBattleMons[gBattlerAttacker].volatiles.dragonCheer = gBattleMons[gBattlerTarget].volatiles.dragonCheer;
|
||||
gBattleMons[gBattlerAttacker].volatiles.bonusCritStages = gBattleMons[gBattlerTarget].volatiles.bonusCritStages;
|
||||
}
|
||||
gEffectBattler = gBattlerTarget;
|
||||
gBattleScripting.battler = gBattlerAttacker;
|
||||
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
}
|
||||
@ -12350,7 +12380,7 @@ static void Cmd_recoverbasedonsunlight(void)
|
||||
else
|
||||
recoverAmount = GetNonDynamaxMaxHP(gBattlerAttacker) / 2;
|
||||
}
|
||||
else if (GetConfig(CONFIG_TIME_OF_DAY_HEALING_MOVES) != GEN_2)
|
||||
else if (GetConfig(B_TIME_OF_DAY_HEALING_MOVES) != GEN_2)
|
||||
{
|
||||
if (!(gBattleWeather & B_WEATHER_ANY) || !HasWeatherEffect() || GetBattlerHoldEffect(gBattlerAttacker) == HOLD_EFFECT_UTILITY_UMBRELLA)
|
||||
recoverAmount = GetNonDynamaxMaxHP(gBattlerAttacker) / 2;
|
||||
@ -12638,7 +12668,7 @@ static void Cmd_settaunt(void)
|
||||
{
|
||||
CMD_ARGS(const u8 *failInstr);
|
||||
|
||||
if (GetConfig(CONFIG_OBLIVIOUS_TAUNT) >= GEN_6 && GetBattlerAbility(gBattlerTarget) == ABILITY_OBLIVIOUS)
|
||||
if (GetConfig(B_OBLIVIOUS_TAUNT) >= GEN_6 && GetBattlerAbility(gBattlerTarget) == ABILITY_OBLIVIOUS)
|
||||
{
|
||||
gBattlescriptCurrInstr = BattleScript_NotAffectedAbilityPopUp;
|
||||
gLastUsedAbility = ABILITY_OBLIVIOUS;
|
||||
@ -13374,6 +13404,10 @@ bool32 DoesSubstituteBlockMove(u32 battlerAtk, u32 battlerDef, u32 move)
|
||||
return FALSE;
|
||||
else if (MoveIgnoresSubstitute(move))
|
||||
return FALSE;
|
||||
else if (GetConfig(B_INFILTRATOR_SUBSTITUTE) < GEN_6)
|
||||
return TRUE;
|
||||
else if (GetMoveEffect(move) == EFFECT_TRANSFORM || GetMoveEffect(move) == EFFECT_SKY_DROP)
|
||||
return TRUE;
|
||||
else if (IsAbilityAndRecord(battlerAtk, GetBattlerAbility(battlerAtk), ABILITY_INFILTRATOR))
|
||||
return FALSE;
|
||||
else
|
||||
@ -14703,7 +14737,7 @@ bool32 CanBurnHitThaw(u16 move)
|
||||
{
|
||||
u8 i;
|
||||
|
||||
if (GetConfig(CONFIG_BURN_HIT_THAW) >= GEN_6)
|
||||
if (GetConfig(B_BURN_HIT_THAW) >= GEN_6)
|
||||
{
|
||||
u32 numAdditionalEffects = GetMoveAdditionalEffectCount(move);
|
||||
for (i = 0; i < numAdditionalEffects; i++)
|
||||
@ -15487,7 +15521,7 @@ void BS_TryAllySwitch(void)
|
||||
{
|
||||
gBattlescriptCurrInstr = cmd->failInstr;
|
||||
}
|
||||
else if (GetConfig(CONFIG_ALLY_SWITCH_FAIL_CHANCE) >= GEN_9)
|
||||
else if (GetConfig(B_ALLY_SWITCH_FAIL_CHANCE) >= GEN_9)
|
||||
{
|
||||
TryResetProtectUseCounter(gBattlerAttacker);
|
||||
if (sProtectSuccessRates[gDisableStructs[gBattlerAttacker].protectUses] < Random())
|
||||
@ -16367,7 +16401,7 @@ void BS_JumpIfIntimidateAbilityPrevented(void)
|
||||
case ABILITY_SCRAPPY:
|
||||
case ABILITY_OWN_TEMPO:
|
||||
case ABILITY_OBLIVIOUS:
|
||||
if (GetConfig(CONFIG_UPDATED_INTIMIDATE) >= GEN_8)
|
||||
if (GetConfig(B_UPDATED_INTIMIDATE) >= GEN_8)
|
||||
{
|
||||
hasAbility = TRUE;
|
||||
gBattlescriptCurrInstr = BattleScript_IntimidatePrevented;
|
||||
@ -17357,21 +17391,26 @@ void BS_TryInstruct(void)
|
||||
gSpecialStatuses[gBattlerTarget].instructedChosenTarget = gBattleStruct->moveTarget[gBattlerTarget] | 0x4;
|
||||
gCalledMove = move;
|
||||
u32 moveIndex;
|
||||
bool32 foundMove = FALSE;
|
||||
for (moveIndex = 0; moveIndex < MAX_MON_MOVES; moveIndex++)
|
||||
{
|
||||
if (gBattleMons[gBattlerTarget].moves[moveIndex] == gCalledMove)
|
||||
{
|
||||
gCurrMovePos = moveIndex;
|
||||
moveIndex = MAX_MON_MOVES;
|
||||
foundMove = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (moveIndex != MAX_MON_MOVES || gBattleMons[gBattlerTarget].pp[gCurrMovePos] == 0)
|
||||
if (!foundMove)
|
||||
{
|
||||
gBattlescriptCurrInstr = cmd->failInstr;
|
||||
}
|
||||
else if (gBattleMons[gBattlerTarget].pp[moveIndex] == 0)
|
||||
{
|
||||
gBattlescriptCurrInstr = cmd->failInstr;
|
||||
}
|
||||
else
|
||||
{
|
||||
gCurrMovePos = moveIndex;
|
||||
gBattleScripting.battler = gBattlerAttacker; // for message
|
||||
gEffectBattler = gBattleStruct->lastMoveTarget[gBattlerTarget];
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
@ -17978,7 +18017,7 @@ void BS_JumpIfAbilityPreventsRest(void)
|
||||
NATIVE_ARGS(u8 battler, const u8 *jumpInstr);
|
||||
u32 battler = GetBattlerForBattleScript(cmd->battler);
|
||||
u32 ability = GetBattlerAbility(battler);
|
||||
if (GetConfig(CONFIG_LEAF_GUARD_PREVENTS_REST) >= GEN_5 && IsLeafGuardProtected(battler, ability))
|
||||
if (GetConfig(B_LEAF_GUARD_PREVENTS_REST) >= GEN_5 && IsLeafGuardProtected(battler, ability))
|
||||
gBattlescriptCurrInstr = cmd->jumpInstr;
|
||||
else if (IsShieldsDownProtected(battler, ability))
|
||||
gBattlescriptCurrInstr = cmd->jumpInstr;
|
||||
@ -18073,7 +18112,7 @@ void BS_BattlerItemToLastUsedItem(void)
|
||||
void BS_JumpIfGenConfigLowerThan(void)
|
||||
{
|
||||
NATIVE_ARGS(u16 tag, u8 gen, const u8 *jumpInstr);
|
||||
if (GetConfig(cmd->tag) < cmd->gen)
|
||||
if (GetConfigInternal(cmd->tag) < cmd->gen)
|
||||
gBattlescriptCurrInstr = cmd->jumpInstr;
|
||||
else
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
|
||||
@ -940,6 +940,7 @@ static bool32 IsPlayerDefeated(u32 battleOutcome)
|
||||
{
|
||||
case B_OUTCOME_LOST:
|
||||
case B_OUTCOME_DREW:
|
||||
case B_OUTCOME_FORFEITED:
|
||||
return TRUE;
|
||||
case B_OUTCOME_WON:
|
||||
case B_OUTCOME_RAN:
|
||||
|
||||
@ -480,7 +480,7 @@ void HandleAction_UseMove(void)
|
||||
{
|
||||
gCurrentMove = gChosenMove = gDisableStructs[gBattlerAttacker].encoredMove;
|
||||
gCurrMovePos = gChosenMovePos = gDisableStructs[gBattlerAttacker].encoredMovePos;
|
||||
if (GetConfig(CONFIG_ENCORE_TARGET) < GEN_5)
|
||||
if (GetConfig(B_ENCORE_TARGET) < GEN_5)
|
||||
gBattleStruct->moveTarget[gBattlerAttacker] = GetBattleMoveTarget(gCurrentMove, NO_TARGET_OVERRIDE);
|
||||
}
|
||||
// check if the encored move wasn't overwritten
|
||||
@ -695,7 +695,7 @@ bool32 TryRunFromBattle(u32 battler)
|
||||
gProtectStructs[battler].fleeType = FLEE_ITEM;
|
||||
effect++;
|
||||
}
|
||||
else if (GetConfig(CONFIG_GHOSTS_ESCAPE) >= GEN_6 && IS_BATTLER_OF_TYPE(battler, TYPE_GHOST))
|
||||
else if (GetConfig(B_GHOSTS_ESCAPE) >= GEN_6 && IS_BATTLER_OF_TYPE(battler, TYPE_GHOST))
|
||||
{
|
||||
effect++;
|
||||
}
|
||||
@ -970,7 +970,7 @@ void HandleAction_ActionFinished(void)
|
||||
gBattleResources->battleScriptsStack->size = 0;
|
||||
gBattleStruct->synchronizeMoveEffect = MOVE_EFFECT_NONE;
|
||||
|
||||
if (GetConfig(CONFIG_RECALC_TURN_AFTER_ACTIONS) >= GEN_8 && !afterYouActive && !gBattleStruct->pledgeMove && !IsPursuitTargetSet())
|
||||
if (GetConfig(B_RECALC_TURN_AFTER_ACTIONS) >= GEN_8 && !afterYouActive && !gBattleStruct->pledgeMove && !IsPursuitTargetSet())
|
||||
{
|
||||
// i starts at `gCurrentTurnActionNumber` because we don't want to recalculate turn order for mon that have already
|
||||
// taken action. It's been previously increased, which we want in order to not recalculate the turn of the mon that just finished its action
|
||||
@ -1245,7 +1245,7 @@ bool32 ShouldDefiantCompetitiveActivate(u32 battler, enum Ability ability)
|
||||
if (IsBattlerAlly(gSpecialStatuses[battler].changedStatsBattlerId, battler) && !gBattleScripting.stickyWebStatDrop)
|
||||
return FALSE;
|
||||
|
||||
if (GetConfig(CONFIG_DEFIANT_STICKY_WEB) >= GEN_9 || !gBattleScripting.stickyWebStatDrop)
|
||||
if (GetConfig(B_DEFIANT_STICKY_WEB) >= GEN_9 || !gBattleScripting.stickyWebStatDrop)
|
||||
return TRUE;
|
||||
// only activate Defiant/Competitive if Web was setup by foe
|
||||
return gSideTimers[side].stickyWebBattlerSide != side;
|
||||
@ -1283,7 +1283,7 @@ void PrepareStringBattle(enum StringID stringId, u32 battler)
|
||||
stringId = STRINGID_STATSWONTINCREASE2;
|
||||
break;
|
||||
case STRINGID_PKMNCUTSATTACKWITH:
|
||||
if (GetConfig(CONFIG_UPDATED_INTIMIDATE) >= GEN_8
|
||||
if (GetConfig(B_UPDATED_INTIMIDATE) >= GEN_8
|
||||
&& targetAbility == ABILITY_RATTLED
|
||||
&& CompareStat(gBattlerTarget, STAT_SPEED, MAX_STAT_STAGE, CMP_LESS_THAN, targetAbility))
|
||||
{
|
||||
@ -1425,7 +1425,7 @@ u32 TrySetCantSelectMoveBattleScript(u32 battler)
|
||||
u16 *choicedMove = &gBattleStruct->choicedMove[battler];
|
||||
enum BattleMoveEffects moveEffect = GetMoveEffect(move);
|
||||
|
||||
if (GetConfig(CONFIG_ENCORE_TARGET) >= GEN_5
|
||||
if (GetConfig(B_ENCORE_TARGET) >= GEN_5
|
||||
&& DYNAMAX_BYPASS_CHECK && GetActiveGimmick(battler) != GIMMICK_Z_MOVE && gDisableStructs[battler].encoredMove != move && gDisableStructs[battler].encoredMove != MOVE_NONE)
|
||||
{
|
||||
gBattleScripting.battler = battler;
|
||||
@ -2282,7 +2282,7 @@ static enum MoveCanceler CancelerConfused(struct BattleContext *ctx)
|
||||
if (gBattleMons[ctx->battlerAtk].volatiles.confusionTurns)
|
||||
{
|
||||
// confusion dmg
|
||||
if (RandomPercentage(RNG_CONFUSION, (GetConfig(CONFIG_CONFUSION_SELF_DMG_CHANCE) >= GEN_7 ? 33 : 50)))
|
||||
if (RandomPercentage(RNG_CONFUSION, (GetConfig(B_CONFUSION_SELF_DMG_CHANCE) >= GEN_7 ? 33 : 50)))
|
||||
{
|
||||
gBattleCommunication[MULTISTRING_CHOOSER] = TRUE;
|
||||
struct DamageContext dmgCtx = {0};
|
||||
@ -2619,7 +2619,7 @@ static enum MoveCanceler CancelerWeatherPrimal(struct BattleContext *ctx)
|
||||
if (HasWeatherEffect() && GetMovePower(ctx->currentMove) > 0)
|
||||
{
|
||||
enum Type moveType = GetBattleMoveType(ctx->currentMove);
|
||||
if (moveType == TYPE_FIRE && (gBattleWeather & B_WEATHER_RAIN_PRIMAL) && (GetConfig(CONFIG_POWDER_RAIN) >= GEN_7 || !TryActivatePowderStatus(ctx->currentMove)))
|
||||
if (moveType == TYPE_FIRE && (gBattleWeather & B_WEATHER_RAIN_PRIMAL) && (GetConfig(B_POWDER_RAIN) >= GEN_7 || !TryActivatePowderStatus(ctx->currentMove)))
|
||||
{
|
||||
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_PRIMAL_WEATHER_FIZZLED_BY_RAIN;
|
||||
effect = MOVE_STEP_FAILURE;
|
||||
@ -2852,7 +2852,7 @@ static enum MoveCanceler CancelerProtean(struct BattleContext *ctx)
|
||||
enum Type moveType = GetBattleMoveType(ctx->currentMove);
|
||||
if (ProteanTryChangeType(ctx->battlerAtk, ctx->abilities[ctx->battlerAtk], ctx->currentMove, moveType))
|
||||
{
|
||||
if (GetConfig(CONFIG_PROTEAN_LIBERO) >= GEN_9)
|
||||
if (GetConfig(B_PROTEAN_LIBERO) >= GEN_9)
|
||||
gDisableStructs[ctx->battlerAtk].usedProteanLibero = TRUE;
|
||||
PREPARE_TYPE_BUFFER(gBattleTextBuff1, moveType);
|
||||
gBattlerAbility = ctx->battlerAtk;
|
||||
@ -2935,7 +2935,7 @@ static enum MoveCanceler CancelerMultihitMoves(struct BattleContext *ctx)
|
||||
&& !GetMonData(&party[i], MON_DATA_IS_EGG)
|
||||
&& !GetMonData(&party[i], MON_DATA_STATUS))
|
||||
{
|
||||
if (GetConfig(CONFIG_BEAT_UP) >= GEN_5)
|
||||
if (GetConfig(B_BEAT_UP) >= GEN_5)
|
||||
gBattleStruct->beatUpSpecies[gMultiHitCounter] = species;
|
||||
else
|
||||
gBattleStruct->beatUpSpecies[gMultiHitCounter] = i;
|
||||
@ -3232,7 +3232,7 @@ bool32 TryChangeBattleWeather(u32 battler, u32 battleWeatherId, u32 ability)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
else if (GetConfig(CONFIG_ABILITY_WEATHER) < GEN_6 && ability != ABILITY_NONE)
|
||||
else if (GetConfig(B_ABILITY_WEATHER) < GEN_6 && ability != ABILITY_NONE)
|
||||
{
|
||||
gBattleWeather = sBattleWeatherInfo[battleWeatherId].flag;
|
||||
for (u32 i = 0; i < gBattlersCount; i++)
|
||||
@ -3335,12 +3335,43 @@ static void ForewarnChooseMove(u32 battler)
|
||||
}
|
||||
}
|
||||
|
||||
for (bestId = 0, i = 1; i < count; i++)
|
||||
if (count == 0)
|
||||
{
|
||||
if (data[i].power > data[bestId].power)
|
||||
bestId = i;
|
||||
else if (data[i].power == data[bestId].power && Random() & 1)
|
||||
Free(data);
|
||||
return;
|
||||
}
|
||||
|
||||
u32 tieCount = 1;
|
||||
u8 bestPower = data[0].power;
|
||||
|
||||
bestId = 0;
|
||||
for (i = 1; i < count; i++)
|
||||
{
|
||||
if (data[i].power > bestPower)
|
||||
{
|
||||
bestPower = data[i].power;
|
||||
bestId = i;
|
||||
tieCount = 1;
|
||||
}
|
||||
else if (data[i].power == bestPower)
|
||||
{
|
||||
tieCount++;
|
||||
}
|
||||
}
|
||||
|
||||
if (tieCount > 1)
|
||||
{
|
||||
u32 tieIndex = RandomUniform(RNG_FOREWARN, 0, tieCount - 1);
|
||||
for (i = 0, bestId = 0; i < count; i++)
|
||||
{
|
||||
if (data[i].power != bestPower)
|
||||
continue;
|
||||
if (tieIndex-- == 0)
|
||||
{
|
||||
bestId = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gEffectBattler = data[bestId].battler;
|
||||
@ -3551,14 +3582,14 @@ bool32 CanAbilityAbsorbMove(u32 battlerAtk, u32 battlerDef, enum Ability ability
|
||||
}
|
||||
break;
|
||||
case ABILITY_LIGHTNING_ROD:
|
||||
if (GetConfig(CONFIG_REDIRECT_ABILITY_IMMUNITY) >= GEN_5 && moveType == TYPE_ELECTRIC && GetBattlerMoveTargetType(battlerAtk, move) != MOVE_TARGET_ALL_BATTLERS)
|
||||
if (GetConfig(B_REDIRECT_ABILITY_IMMUNITY) >= GEN_5 && moveType == TYPE_ELECTRIC && GetBattlerMoveTargetType(battlerAtk, move) != MOVE_TARGET_ALL_BATTLERS)
|
||||
{
|
||||
effect = MOVE_ABSORBED_BY_STAT_INCREASE_ABILITY;
|
||||
statId = STAT_SPATK;
|
||||
}
|
||||
break;
|
||||
case ABILITY_STORM_DRAIN:
|
||||
if (GetConfig(CONFIG_REDIRECT_ABILITY_IMMUNITY) >= GEN_5 && moveType == TYPE_WATER)
|
||||
if (GetConfig(B_REDIRECT_ABILITY_IMMUNITY) >= GEN_5 && moveType == TYPE_WATER)
|
||||
{
|
||||
effect = MOVE_ABSORBED_BY_STAT_INCREASE_ABILITY;
|
||||
statId = STAT_SPATK;
|
||||
@ -4155,7 +4186,7 @@ u32 AbilityBattleEffects(enum AbilityEffect caseID, u32 battler, enum Ability ab
|
||||
}
|
||||
return effect; // Note: It returns effect as to not record the ability if Frisk does not activate.
|
||||
case ABILITY_FOREWARN:
|
||||
if (!gSpecialStatuses[battler].switchInAbilityDone)
|
||||
if (!gSpecialStatuses[battler].switchInAbilityDone && !IsOpposingSideEmpty(battler))
|
||||
{
|
||||
ForewarnChooseMove(battler);
|
||||
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SWITCHIN_FOREWARN;
|
||||
@ -4298,12 +4329,12 @@ u32 AbilityBattleEffects(enum AbilityEffect caseID, u32 battler, enum Ability ab
|
||||
}
|
||||
break;
|
||||
case ABILITY_SNOW_WARNING:
|
||||
if (GetConfig(CONFIG_SNOW_WARNING) >= GEN_9 && TryChangeBattleWeather(battler, BATTLE_WEATHER_SNOW, gLastUsedAbility))
|
||||
if (GetConfig(B_SNOW_WARNING) >= GEN_9 && TryChangeBattleWeather(battler, BATTLE_WEATHER_SNOW, gLastUsedAbility))
|
||||
{
|
||||
BattleScriptPushCursorAndCallback(BattleScript_SnowWarningActivatesSnow);
|
||||
effect++;
|
||||
}
|
||||
else if (GetConfig(CONFIG_SNOW_WARNING) < GEN_9 && TryChangeBattleWeather(battler, BATTLE_WEATHER_HAIL, gLastUsedAbility))
|
||||
else if (GetConfig(B_SNOW_WARNING) < GEN_9 && TryChangeBattleWeather(battler, BATTLE_WEATHER_HAIL, gLastUsedAbility))
|
||||
{
|
||||
BattleScriptPushCursorAndCallback(BattleScript_SnowWarningActivatesHail);
|
||||
effect++;
|
||||
@ -4402,7 +4433,7 @@ u32 AbilityBattleEffects(enum AbilityEffect caseID, u32 battler, enum Ability ab
|
||||
if (!gSpecialStatuses[battler].switchInAbilityDone
|
||||
&& !GetBattlerPartyState(battler)->intrepidSwordBoost)
|
||||
{
|
||||
if (GetConfig(CONFIG_INTREPID_SWORD) == GEN_9)
|
||||
if (GetConfig(B_INTREPID_SWORD) == GEN_9)
|
||||
GetBattlerPartyState(battler)->intrepidSwordBoost = TRUE;
|
||||
gSpecialStatuses[battler].switchInAbilityDone = TRUE;
|
||||
if (CompareStat(battler, STAT_ATK, MAX_STAT_STAGE, CMP_LESS_THAN, gLastUsedAbility))
|
||||
@ -4417,7 +4448,7 @@ u32 AbilityBattleEffects(enum AbilityEffect caseID, u32 battler, enum Ability ab
|
||||
if (!gSpecialStatuses[battler].switchInAbilityDone
|
||||
&& !GetBattlerPartyState(battler)->dauntlessShieldBoost)
|
||||
{
|
||||
if (GetConfig(CONFIG_DAUNTLESS_SHIELD) == GEN_9)
|
||||
if (GetConfig(B_DAUNTLESS_SHIELD) == GEN_9)
|
||||
GetBattlerPartyState(battler)->dauntlessShieldBoost = TRUE;
|
||||
gSpecialStatuses[battler].switchInAbilityDone = TRUE;
|
||||
if (CompareStat(battler, STAT_DEF, MAX_STAT_STAGE, CMP_LESS_THAN, gLastUsedAbility))
|
||||
@ -4602,6 +4633,7 @@ u32 AbilityBattleEffects(enum AbilityEffect caseID, u32 battler, enum Ability ab
|
||||
&& IsBattlerAlive(battler)
|
||||
&& gBattleStruct->battlerState[partner].commanderSpecies == SPECIES_NONE
|
||||
&& gBattleMons[partner].species == SPECIES_DONDOZO
|
||||
&& (gChosenActionByBattler[partner] != B_ACTION_SWITCH || HasBattlerActedThisTurn(partner))
|
||||
&& GET_BASE_SPECIES_ID(GetMonData(GetBattlerMon(battler), MON_DATA_SPECIES)) == SPECIES_TATSUGIRI)
|
||||
{
|
||||
SaveBattlerAttacker(gBattlerAttacker);
|
||||
@ -4686,7 +4718,7 @@ u32 AbilityBattleEffects(enum AbilityEffect caseID, u32 battler, enum Ability ab
|
||||
break;
|
||||
case ABILITY_SHED_SKIN:
|
||||
if ((gBattleMons[battler].status1 & STATUS1_ANY)
|
||||
&& (GetConfig(CONFIG_ABILITY_TRIGGER_CHANCE) == GEN_4 ? RandomPercentage(RNG_SHED_SKIN, 30) : RandomChance(RNG_SHED_SKIN, 1, 3)))
|
||||
&& (GetConfig(B_ABILITY_TRIGGER_CHANCE) == GEN_4 ? RandomPercentage(RNG_SHED_SKIN, 30) : RandomChance(RNG_SHED_SKIN, 1, 3)))
|
||||
{
|
||||
ABILITY_HEAL_MON_STATUS:
|
||||
if (gBattleMons[battler].status1 & (STATUS1_POISON | STATUS1_TOXIC_POISON))
|
||||
@ -4727,7 +4759,7 @@ u32 AbilityBattleEffects(enum AbilityEffect caseID, u32 battler, enum Ability ab
|
||||
if (gDisableStructs[battler].isFirstTurn != 2)
|
||||
{
|
||||
u32 validToRaise = 0, validToLower = 0;
|
||||
u32 statsNum = GetConfig(CONFIG_MOODY_ACC_EVASION) >= GEN_8 ? NUM_STATS : NUM_BATTLE_STATS;
|
||||
u32 statsNum = GetConfig(B_MOODY_ACC_EVASION) >= GEN_8 ? NUM_STATS : NUM_BATTLE_STATS;
|
||||
|
||||
for (i = STAT_ATK; i < statsNum; i++)
|
||||
{
|
||||
@ -5110,7 +5142,7 @@ u32 AbilityBattleEffects(enum AbilityEffect caseID, u32 battler, enum Ability ab
|
||||
{
|
||||
u32 poison, paralysis, sleep;
|
||||
|
||||
if (GetConfig(CONFIG_ABILITY_TRIGGER_CHANCE) >= GEN_5)
|
||||
if (GetConfig(B_ABILITY_TRIGGER_CHANCE) >= GEN_5)
|
||||
{
|
||||
poison = 9;
|
||||
paralysis = 19;
|
||||
@ -5122,7 +5154,7 @@ u32 AbilityBattleEffects(enum AbilityEffect caseID, u32 battler, enum Ability ab
|
||||
}
|
||||
sleep = 30;
|
||||
|
||||
i = RandomUniform(RNG_EFFECT_SPORE, 0, GetConfig(CONFIG_ABILITY_TRIGGER_CHANCE) >= GEN_4 ? 99 : 299);
|
||||
i = RandomUniform(RNG_EFFECT_SPORE, 0, GetConfig(B_ABILITY_TRIGGER_CHANCE) >= GEN_4 ? 99 : 299);
|
||||
if (i < poison)
|
||||
goto POISON_POINT;
|
||||
if (i < paralysis)
|
||||
@ -5148,7 +5180,7 @@ u32 AbilityBattleEffects(enum AbilityEffect caseID, u32 battler, enum Ability ab
|
||||
}
|
||||
break;
|
||||
case ABILITY_POISON_POINT:
|
||||
if (GetConfig(CONFIG_ABILITY_TRIGGER_CHANCE) >= GEN_4 ? RandomPercentage(RNG_POISON_POINT, 30) : RandomChance(RNG_POISON_POINT, 1, 3))
|
||||
if (GetConfig(B_ABILITY_TRIGGER_CHANCE) >= GEN_4 ? RandomPercentage(RNG_POISON_POINT, 30) : RandomChance(RNG_POISON_POINT, 1, 3))
|
||||
{
|
||||
POISON_POINT:
|
||||
{
|
||||
@ -5170,7 +5202,7 @@ u32 AbilityBattleEffects(enum AbilityEffect caseID, u32 battler, enum Ability ab
|
||||
}
|
||||
break;
|
||||
case ABILITY_STATIC:
|
||||
if (GetConfig(CONFIG_ABILITY_TRIGGER_CHANCE) >= GEN_4 ? RandomPercentage(RNG_STATIC, 30) : RandomChance(RNG_STATIC, 1, 3))
|
||||
if (GetConfig(B_ABILITY_TRIGGER_CHANCE) >= GEN_4 ? RandomPercentage(RNG_STATIC, 30) : RandomChance(RNG_STATIC, 1, 3))
|
||||
{
|
||||
STATIC:
|
||||
{
|
||||
@ -5197,7 +5229,7 @@ u32 AbilityBattleEffects(enum AbilityEffect caseID, u32 battler, enum Ability ab
|
||||
&& !CanBattlerAvoidContactEffects(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerAttacker), GetBattlerHoldEffect(gBattlerAttacker), move)
|
||||
&& IsBattlerTurnDamaged(gBattlerTarget)
|
||||
&& CanBeBurned(gBattlerTarget, gBattlerAttacker, GetBattlerAbility(gBattlerAttacker))
|
||||
&& (GetConfig(CONFIG_ABILITY_TRIGGER_CHANCE) >= GEN_4 ? RandomPercentage(RNG_FLAME_BODY, 30) : RandomChance(RNG_FLAME_BODY, 1, 3)))
|
||||
&& (GetConfig(B_ABILITY_TRIGGER_CHANCE) >= GEN_4 ? RandomPercentage(RNG_FLAME_BODY, 30) : RandomChance(RNG_FLAME_BODY, 1, 3)))
|
||||
{
|
||||
gEffectBattler = gBattlerAttacker;
|
||||
gBattleScripting.battler = gBattlerTarget;
|
||||
@ -5212,7 +5244,7 @@ u32 AbilityBattleEffects(enum AbilityEffect caseID, u32 battler, enum Ability ab
|
||||
&& !gProtectStructs[gBattlerAttacker].confusionSelfDmg
|
||||
&& IsBattlerTurnDamaged(gBattlerTarget)
|
||||
&& IsBattlerAlive(gBattlerTarget)
|
||||
&& (GetConfig(CONFIG_ABILITY_TRIGGER_CHANCE) >= GEN_4 ? RandomPercentage(RNG_CUTE_CHARM, 30) : RandomChance(RNG_CUTE_CHARM, 1, 3))
|
||||
&& (GetConfig(B_ABILITY_TRIGGER_CHANCE) >= GEN_4 ? RandomPercentage(RNG_CUTE_CHARM, 30) : RandomChance(RNG_CUTE_CHARM, 1, 3))
|
||||
&& !(gBattleMons[gBattlerAttacker].volatiles.infatuation)
|
||||
&& AreBattlersOfOppositeGender(gBattlerAttacker, gBattlerTarget)
|
||||
&& !IsAbilityAndRecord(gBattlerAttacker, GetBattlerAbility(gBattlerAttacker), ABILITY_OBLIVIOUS)
|
||||
@ -5500,7 +5532,7 @@ u32 AbilityBattleEffects(enum AbilityEffect caseID, u32 battler, enum Ability ab
|
||||
gBattleScripting.battler = gBattlerAbility = gBattlerTarget;
|
||||
RecordAbilityBattle(gBattlerTarget, ABILITY_SYNCHRONIZE);
|
||||
|
||||
if (GetConfig(CONFIG_SYNCHRONIZE_TOXIC) < GEN_5 && gBattleStruct->synchronizeMoveEffect == MOVE_EFFECT_TOXIC)
|
||||
if (GetConfig(B_SYNCHRONIZE_TOXIC) < GEN_5 && gBattleStruct->synchronizeMoveEffect == MOVE_EFFECT_TOXIC)
|
||||
gBattleStruct->synchronizeMoveEffect = MOVE_EFFECT_POISON;
|
||||
|
||||
if (CanSetNonVolatileStatus(
|
||||
@ -5530,7 +5562,7 @@ u32 AbilityBattleEffects(enum AbilityEffect caseID, u32 battler, enum Ability ab
|
||||
gBattleScripting.battler = gBattlerAbility = gBattlerAttacker;
|
||||
RecordAbilityBattle(gBattlerAttacker, ABILITY_SYNCHRONIZE);
|
||||
|
||||
if (GetConfig(CONFIG_SYNCHRONIZE_TOXIC) < GEN_5 && gBattleStruct->synchronizeMoveEffect == MOVE_EFFECT_TOXIC)
|
||||
if (GetConfig(B_SYNCHRONIZE_TOXIC) < GEN_5 && gBattleStruct->synchronizeMoveEffect == MOVE_EFFECT_TOXIC)
|
||||
gBattleStruct->synchronizeMoveEffect = MOVE_EFFECT_POISON;
|
||||
|
||||
if (CanSetNonVolatileStatus(
|
||||
@ -5804,7 +5836,7 @@ u32 IsAbilityOnFieldExcept(u32 battler, enum Ability ability)
|
||||
|
||||
u32 IsAbilityPreventingEscape(u32 battler)
|
||||
{
|
||||
if (GetConfig(CONFIG_GHOSTS_ESCAPE) >= GEN_6 && IS_BATTLER_OF_TYPE(battler, TYPE_GHOST))
|
||||
if (GetConfig(B_GHOSTS_ESCAPE) >= GEN_6 && IS_BATTLER_OF_TYPE(battler, TYPE_GHOST))
|
||||
return 0;
|
||||
|
||||
bool32 isBattlerGrounded = IsBattlerGrounded(battler, GetBattlerAbility(battler), GetBattlerHoldEffect(battler));
|
||||
@ -5832,7 +5864,7 @@ bool32 CanBattlerEscape(u32 battler) // no ability check
|
||||
{
|
||||
if (gBattleStruct->battlerState[battler].commanderSpecies != SPECIES_NONE)
|
||||
return FALSE;
|
||||
else if (GetConfig(CONFIG_GHOSTS_ESCAPE) >= GEN_6 && IS_BATTLER_OF_TYPE(battler, TYPE_GHOST))
|
||||
else if (GetConfig(B_GHOSTS_ESCAPE) >= GEN_6 && IS_BATTLER_OF_TYPE(battler, TYPE_GHOST))
|
||||
return TRUE;
|
||||
else if (gBattleMons[battler].volatiles.escapePrevention)
|
||||
return FALSE;
|
||||
@ -6082,6 +6114,17 @@ bool32 CanGetFrostbite(u32 battlerAtk, u32 battlerDef, enum Ability abilityDef)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
bool32 IsSafeguardProtected(u32 battlerAtk, u32 battlerDef, u32 abilityAtk)
|
||||
{
|
||||
if (!(gSideStatuses[GetBattlerSide(battlerDef)] & SIDE_STATUS_SAFEGUARD))
|
||||
return FALSE;
|
||||
if (IsBattlerAlly(battlerAtk, battlerDef))
|
||||
return TRUE;
|
||||
if (abilityAtk == ABILITY_INFILTRATOR)
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
bool32 CanSetNonVolatileStatus(u32 battlerAtk, u32 battlerDef, enum Ability abilityAtk, enum Ability abilityDef, enum MoveEffect effect, enum FunctionCallOption option)
|
||||
{
|
||||
const u8 *battleScript = NULL;
|
||||
@ -6119,7 +6162,7 @@ bool32 CanSetNonVolatileStatus(u32 battlerAtk, u32 battlerDef, enum Ability abil
|
||||
{
|
||||
battleScript = BattleScript_AlreadyParalyzed;
|
||||
}
|
||||
else if (GetConfig(CONFIG_PARALYZE_ELECTRIC) >= GEN_6 && IS_BATTLER_OF_TYPE(battlerDef, TYPE_ELECTRIC))
|
||||
else if (GetConfig(B_PARALYZE_ELECTRIC) >= GEN_6 && IS_BATTLER_OF_TYPE(battlerDef, TYPE_ELECTRIC))
|
||||
{
|
||||
battleScript = BattleScript_NotAffected;
|
||||
}
|
||||
@ -6236,7 +6279,7 @@ bool32 CanSetNonVolatileStatus(u32 battlerAtk, u32 battlerDef, enum Ability abil
|
||||
abilityDef = ABILITY_FLOWER_VEIL;
|
||||
battleScript = BattleScript_FlowerVeilProtects;
|
||||
}
|
||||
else if (gSideStatuses[GetBattlerSide(battlerDef)] & SIDE_STATUS_SAFEGUARD)
|
||||
else if (IsSafeguardProtected(battlerAtk, battlerDef, abilityAtk))
|
||||
{
|
||||
battleScript = BattleScript_SafeguardProtected;
|
||||
}
|
||||
@ -7264,7 +7307,7 @@ static inline u32 CalcMoveBasePower(struct DamageContext *ctx)
|
||||
basePower *= 2;
|
||||
break;
|
||||
case EFFECT_BEAT_UP:
|
||||
if (GetConfig(CONFIG_BEAT_UP) >= GEN_5)
|
||||
if (GetConfig(B_BEAT_UP) >= GEN_5)
|
||||
basePower = CalcBeatUpPower();
|
||||
break;
|
||||
case EFFECT_PSYBLADE:
|
||||
@ -7378,9 +7421,9 @@ static inline u32 CalcMoveBasePowerAfterModifiers(struct DamageContext *ctx)
|
||||
if (IsBattlerTerrainAffected(battlerAtk, ctx->abilityAtk, ctx->holdEffectAtk, STATUS_FIELD_PSYCHIC_TERRAIN) && moveType == TYPE_PSYCHIC)
|
||||
modifier = uq4_12_multiply(modifier, (B_TERRAIN_TYPE_BOOST >= GEN_8 ? UQ_4_12(1.3) : UQ_4_12(1.5)));
|
||||
if (IsFieldMudSportAffected(ctx->moveType))
|
||||
modifier = uq4_12_multiply(modifier, UQ_4_12(GetConfig(CONFIG_SPORT_DMG_REDUCTION) >= GEN_5 ? 0.33 : 0.5));
|
||||
modifier = uq4_12_multiply(modifier, UQ_4_12(GetConfig(B_SPORT_DMG_REDUCTION) >= GEN_5 ? 0.33 : 0.5));
|
||||
if (IsFieldWaterSportAffected(ctx->moveType))
|
||||
modifier = uq4_12_multiply(modifier, UQ_4_12(GetConfig(CONFIG_SPORT_DMG_REDUCTION) >= GEN_5 ? 0.33 : 0.5));
|
||||
modifier = uq4_12_multiply(modifier, UQ_4_12(GetConfig(B_SPORT_DMG_REDUCTION) >= GEN_5 ? 0.33 : 0.5));
|
||||
|
||||
// attacker's abilities
|
||||
switch (ctx->abilityAtk)
|
||||
@ -7446,22 +7489,22 @@ static inline u32 CalcMoveBasePowerAfterModifiers(struct DamageContext *ctx)
|
||||
break;
|
||||
case ABILITY_PIXILATE:
|
||||
if (moveType == TYPE_FAIRY && gBattleStruct->battlerState[battlerAtk].ateBoost)
|
||||
modifier = uq4_12_multiply(modifier, UQ_4_12(GetConfig(CONFIG_ATE_MULTIPLIER) >= GEN_7 ? 1.2 : 1.3));
|
||||
modifier = uq4_12_multiply(modifier, UQ_4_12(GetConfig(B_ATE_MULTIPLIER) >= GEN_7 ? 1.2 : 1.3));
|
||||
break;
|
||||
case ABILITY_GALVANIZE:
|
||||
if (moveType == TYPE_ELECTRIC && gBattleStruct->battlerState[battlerAtk].ateBoost)
|
||||
modifier = uq4_12_multiply(modifier, UQ_4_12(GetConfig(CONFIG_ATE_MULTIPLIER) >= GEN_7 ? 1.2 : 1.3));
|
||||
modifier = uq4_12_multiply(modifier, UQ_4_12(GetConfig(B_ATE_MULTIPLIER) >= GEN_7 ? 1.2 : 1.3));
|
||||
break;
|
||||
case ABILITY_REFRIGERATE:
|
||||
if (moveType == TYPE_ICE && gBattleStruct->battlerState[battlerAtk].ateBoost)
|
||||
modifier = uq4_12_multiply(modifier, UQ_4_12(GetConfig(CONFIG_ATE_MULTIPLIER) >= GEN_7 ? 1.2 : 1.3));
|
||||
modifier = uq4_12_multiply(modifier, UQ_4_12(GetConfig(B_ATE_MULTIPLIER) >= GEN_7 ? 1.2 : 1.3));
|
||||
break;
|
||||
case ABILITY_AERILATE:
|
||||
if (moveType == TYPE_FLYING && gBattleStruct->battlerState[battlerAtk].ateBoost)
|
||||
modifier = uq4_12_multiply(modifier, UQ_4_12(GetConfig(CONFIG_ATE_MULTIPLIER) >= GEN_7 ? 1.2 : 1.3));
|
||||
modifier = uq4_12_multiply(modifier, UQ_4_12(GetConfig(B_ATE_MULTIPLIER) >= GEN_7 ? 1.2 : 1.3));
|
||||
break;
|
||||
case ABILITY_NORMALIZE:
|
||||
if (moveType == TYPE_NORMAL && gBattleStruct->battlerState[battlerAtk].ateBoost && GetConfig(CONFIG_ATE_MULTIPLIER) >= GEN_7)
|
||||
if (moveType == TYPE_NORMAL && gBattleStruct->battlerState[battlerAtk].ateBoost && GetConfig(B_ATE_MULTIPLIER) >= GEN_7)
|
||||
modifier = uq4_12_multiply(modifier, UQ_4_12(1.2));
|
||||
break;
|
||||
case ABILITY_PUNK_ROCK:
|
||||
@ -7793,7 +7836,7 @@ static inline u32 CalcAttackStat(struct DamageContext *ctx)
|
||||
case ABILITY_TRANSISTOR:
|
||||
if (moveType == TYPE_ELECTRIC)
|
||||
{
|
||||
if (GetConfig(CONFIG_TRANSISTOR_BOOST) >= GEN_9)
|
||||
if (GetConfig(B_TRANSISTOR_BOOST) >= GEN_9)
|
||||
modifier = uq4_12_multiply(modifier, UQ_4_12(1.3));
|
||||
else
|
||||
modifier = uq4_12_multiply(modifier, UQ_4_12(1.5));
|
||||
@ -7902,7 +7945,7 @@ static inline u32 CalcAttackStat(struct DamageContext *ctx)
|
||||
modifier = uq4_12_multiply_half_down(modifier, UQ_4_12(2.0));
|
||||
break;
|
||||
case HOLD_EFFECT_LIGHT_BALL:
|
||||
if (atkBaseSpeciesId == SPECIES_PIKACHU && (GetConfig(CONFIG_LIGHT_BALL_ATTACK_BOOST) >= GEN_4 || IsBattleMoveSpecial(move)))
|
||||
if (atkBaseSpeciesId == SPECIES_PIKACHU && (GetConfig(B_LIGHT_BALL_ATTACK_BOOST) >= GEN_4 || IsBattleMoveSpecial(move)))
|
||||
modifier = uq4_12_multiply_half_down(modifier, UQ_4_12(2.0));
|
||||
break;
|
||||
case HOLD_EFFECT_CHOICE_BAND:
|
||||
@ -8110,7 +8153,7 @@ static inline u32 CalcDefenseStat(struct DamageContext *ctx)
|
||||
}
|
||||
|
||||
// sandstorm sp.def boost for rock types
|
||||
if (GetConfig(CONFIG_SANDSTORM_SPDEF_BOOST) >= GEN_4 && IS_BATTLER_OF_TYPE(battlerDef, TYPE_ROCK) && IsBattlerWeatherAffected(battlerDef, B_WEATHER_SANDSTORM) && !usesDefStat)
|
||||
if (GetConfig(B_SANDSTORM_SPDEF_BOOST) >= GEN_4 && IS_BATTLER_OF_TYPE(battlerDef, TYPE_ROCK) && IsBattlerWeatherAffected(battlerDef, B_WEATHER_SANDSTORM) && !usesDefStat)
|
||||
modifier = uq4_12_multiply_half_down(modifier, UQ_4_12(1.5));
|
||||
// snow def boost for ice types
|
||||
if (IS_BATTLER_OF_TYPE(battlerDef, TYPE_ICE) && IsBattlerWeatherAffected(battlerDef, B_WEATHER_SNOW) && usesDefStat)
|
||||
@ -8188,12 +8231,12 @@ static inline uq4_12_t GetBurnOrFrostBiteModifier(struct DamageContext *ctx)
|
||||
|
||||
if (gBattleMons[ctx->battlerAtk].status1 & STATUS1_BURN
|
||||
&& IsBattleMovePhysical(ctx->move)
|
||||
&& (GetConfig(CONFIG_BURN_FACADE_DMG) < GEN_6 || moveEffect != EFFECT_FACADE)
|
||||
&& (GetConfig(B_BURN_FACADE_DMG) < GEN_6 || moveEffect != EFFECT_FACADE)
|
||||
&& ctx->abilityAtk != ABILITY_GUTS)
|
||||
return UQ_4_12(0.5);
|
||||
if (gBattleMons[ctx->battlerAtk].status1 & STATUS1_FROSTBITE
|
||||
&& IsBattleMoveSpecial(ctx->move)
|
||||
&& (GetConfig(CONFIG_BURN_FACADE_DMG) < GEN_6 || moveEffect != EFFECT_FACADE))
|
||||
&& (GetConfig(B_BURN_FACADE_DMG) < GEN_6 || moveEffect != EFFECT_FACADE))
|
||||
return UQ_4_12(0.5);
|
||||
return UQ_4_12(1.0);
|
||||
}
|
||||
@ -8201,7 +8244,7 @@ static inline uq4_12_t GetBurnOrFrostBiteModifier(struct DamageContext *ctx)
|
||||
static inline uq4_12_t GetCriticalModifier(bool32 isCrit)
|
||||
{
|
||||
if (isCrit)
|
||||
return GetConfig(CONFIG_CRIT_MULTIPLIER) >= GEN_6 ? UQ_4_12(1.5) : UQ_4_12(2.0);
|
||||
return GetConfig(B_CRIT_MULTIPLIER) >= GEN_6 ? UQ_4_12(1.5) : UQ_4_12(2.0);
|
||||
return UQ_4_12(1.0);
|
||||
}
|
||||
|
||||
@ -8262,7 +8305,7 @@ static inline uq4_12_t GetScreensModifier(struct DamageContext *ctx)
|
||||
{
|
||||
return UQ_4_12(1.0);
|
||||
}
|
||||
if (ctx->abilityAtk == ABILITY_INFILTRATOR)
|
||||
if (ctx->abilityAtk == ABILITY_INFILTRATOR && !IsBattlerAlly(ctx->battlerAtk, ctx->battlerDef))
|
||||
{
|
||||
if (ctx->updateFlags)
|
||||
RecordAbilityBattle(ctx->battlerAtk, ctx->abilityDef);
|
||||
@ -8566,7 +8609,7 @@ s32 DoFixedDamageMoveCalc(struct DamageContext *ctx)
|
||||
dmg = GetNonDynamaxHP(ctx->battlerAtk);
|
||||
break;
|
||||
case EFFECT_BEAT_UP:
|
||||
if (GetConfig(CONFIG_BEAT_UP) < GEN_5)
|
||||
if (GetConfig(B_BEAT_UP) < GEN_5)
|
||||
dmg = CalcBeatUpDamage(ctx);
|
||||
else
|
||||
return INT32_MAX;
|
||||
@ -8840,7 +8883,7 @@ static inline uq4_12_t CalcTypeEffectivenessMultiplierInternal(struct DamageCont
|
||||
RecordAbilityBattle(ctx->battlerDef, ABILITY_LEVITATE);
|
||||
}
|
||||
}
|
||||
else if (GetConfig(CONFIG_SHEER_COLD_IMMUNITY) >= GEN_7 && GetMoveEffect(ctx->move) == EFFECT_SHEER_COLD && IS_BATTLER_OF_TYPE(ctx->battlerDef, TYPE_ICE))
|
||||
else if (GetConfig(B_SHEER_COLD_IMMUNITY) >= GEN_7 && GetMoveEffect(ctx->move) == EFFECT_SHEER_COLD && IS_BATTLER_OF_TYPE(ctx->battlerDef, TYPE_ICE))
|
||||
{
|
||||
modifier = UQ_4_12(0.0);
|
||||
}
|
||||
@ -8854,7 +8897,7 @@ static inline uq4_12_t CalcTypeEffectivenessMultiplierInternal(struct DamageCont
|
||||
}
|
||||
|
||||
// Iron Ball ignores type modifiers for flying-type mons if it is the only source of grounding
|
||||
if (GetConfig(CONFIG_IRON_BALL) >= GEN_5
|
||||
if (GetConfig(B_IRON_BALL) >= GEN_5
|
||||
&& ctx->moveType == TYPE_GROUND
|
||||
&& ctx->holdEffectDef == HOLD_EFFECT_IRON_BALL
|
||||
&& IS_BATTLER_OF_TYPE(ctx->battlerDef, TYPE_FLYING)
|
||||
@ -9409,19 +9452,23 @@ bool32 TryBattleFormChange(u32 battler, enum FormChanges method)
|
||||
bool32 DoBattlersShareType(u32 battler1, u32 battler2)
|
||||
{
|
||||
s32 i;
|
||||
s32 j;
|
||||
enum Type types1[3], types2[3];
|
||||
GetBattlerTypes(battler1, FALSE, types1);
|
||||
GetBattlerTypes(battler2, FALSE, types2);
|
||||
|
||||
if (types1[2] == TYPE_MYSTERY)
|
||||
types1[2] = types1[0];
|
||||
if (types2[2] == TYPE_MYSTERY)
|
||||
types2[2] = types2[0];
|
||||
|
||||
for (i = 0; i < 3; i++)
|
||||
{
|
||||
if (types1[i] == types2[0] || types1[i] == types2[1] || types1[i] == types2[2])
|
||||
return TRUE;
|
||||
if (types1[i] == TYPE_MYSTERY)
|
||||
continue;
|
||||
|
||||
for (j = 0; j < 3; j++)
|
||||
{
|
||||
if (types2[j] == TYPE_MYSTERY)
|
||||
continue;
|
||||
if (types1[i] == types2[j])
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
@ -9616,7 +9663,7 @@ u32 TryImmunityAbilityHealStatus(u32 battler, enum AbilityEffect caseID)
|
||||
case ABILITY_OBLIVIOUS:
|
||||
if (gBattleMons[battler].volatiles.infatuation)
|
||||
effect = 3;
|
||||
else if (GetConfig(CONFIG_OBLIVIOUS_TAUNT) >= GEN_6 && gDisableStructs[battler].tauntTimer != 0)
|
||||
else if (GetConfig(B_OBLIVIOUS_TAUNT) >= GEN_6 && gDisableStructs[battler].tauntTimer != 0)
|
||||
effect = 4;
|
||||
break;
|
||||
}
|
||||
@ -9666,7 +9713,7 @@ u32 TryImmunityAbilityHealStatus(u32 battler, enum AbilityEffect caseID)
|
||||
|
||||
uq4_12_t GetBadgeBoostModifier(void)
|
||||
{
|
||||
if (GetConfig(CONFIG_BADGE_BOOST) < GEN_3)
|
||||
if (GetConfig(B_BADGE_BOOST) < GEN_3)
|
||||
return UQ_4_12(1.125);
|
||||
else
|
||||
return UQ_4_12(1.1);
|
||||
@ -9674,7 +9721,7 @@ uq4_12_t GetBadgeBoostModifier(void)
|
||||
|
||||
bool32 ShouldGetStatBadgeBoost(u16 badgeFlag, u32 battler)
|
||||
{
|
||||
if (GetConfig(CONFIG_BADGE_BOOST) <= GEN_3 && badgeFlag != 0)
|
||||
if (GetConfig(B_BADGE_BOOST) <= GEN_3 && badgeFlag != 0)
|
||||
{
|
||||
if (gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_EREADER_TRAINER | BATTLE_TYPE_RECORDED_LINK | BATTLE_TYPE_FRONTIER))
|
||||
return FALSE;
|
||||
@ -9802,9 +9849,10 @@ bool32 CanFling(u32 battler)
|
||||
u16 item = gBattleMons[battler].item;
|
||||
|
||||
if (item == ITEM_NONE
|
||||
|| (GetConfig(CONFIG_KLUTZ_FLING_INTERACTION) >= GEN_5 && GetBattlerAbility(battler) == ABILITY_KLUTZ)
|
||||
|| (GetConfig(B_KLUTZ_FLING_INTERACTION) >= GEN_5 && GetBattlerAbility(battler) == ABILITY_KLUTZ)
|
||||
|| gFieldStatuses & STATUS_FIELD_MAGIC_ROOM
|
||||
|| gBattleMons[battler].volatiles.embargo
|
||||
|| (GetItemTMHMIndex(item) != 0 && GetItemImportance(item) == 1) // don't fling reusable TMs
|
||||
|| GetFlingPowerFromItemId(item) == 0
|
||||
|| !CanBattlerGetOrLoseItem(battler, item))
|
||||
return FALSE;
|
||||
@ -10010,7 +10058,7 @@ bool32 CompareStat(u32 battler, enum Stat statId, u8 cmpTo, u8 cmpKind, enum Abi
|
||||
|
||||
bool32 BlocksPrankster(u16 move, u32 battlerPrankster, u32 battlerDef, bool32 checkTarget)
|
||||
{
|
||||
if (GetConfig(CONFIG_PRANKSTER_DARK_TYPES) < GEN_7)
|
||||
if (GetConfig(B_PRANKSTER_DARK_TYPES) < GEN_7)
|
||||
return FALSE;
|
||||
if (!gProtectStructs[battlerPrankster].pranksterElevated)
|
||||
return FALSE;
|
||||
@ -10029,7 +10077,7 @@ bool32 BlocksPrankster(u16 move, u32 battlerPrankster, u32 battlerDef, bool32 ch
|
||||
bool32 CantPickupItem(u32 battler)
|
||||
{
|
||||
// Used by RandomUniformExcept() for RNG_PICKUP
|
||||
if (battler == gBattlerAttacker && (GetConfig(CONFIG_PICKUP_WILD) < GEN_9 || gBattleTypeFlags & (BATTLE_TYPE_TRAINER | BATTLE_TYPE_LINK)))
|
||||
if (battler == gBattlerAttacker && (GetConfig(B_PICKUP_WILD) < GEN_9 || gBattleTypeFlags & (BATTLE_TYPE_TRAINER | BATTLE_TYPE_LINK)))
|
||||
return TRUE;
|
||||
return !(IsBattlerAlive(battler) && GetBattlerPartyState(battler)->usedHeldItem && gBattleStruct->battlerState[battler].canPickupItem);
|
||||
}
|
||||
@ -10091,7 +10139,7 @@ static void SetRandomMultiHitCounter()
|
||||
{
|
||||
if (GetBattlerHoldEffect(gBattlerAttacker) == HOLD_EFFECT_LOADED_DICE)
|
||||
gMultiHitCounter = RandomUniform(RNG_LOADED_DICE, 4, 5);
|
||||
else if (GetConfig(CONFIG_MULTI_HIT_CHANCE) >= GEN_5)
|
||||
else if (GetConfig(B_MULTI_HIT_CHANCE) >= GEN_5)
|
||||
gMultiHitCounter = RandomWeighted(RNG_HITS, 0, 0, 7, 7, 3, 3); // 35%: 2 hits, 35%: 3 hits, 15% 4 hits, 15% 5 hits.
|
||||
else
|
||||
gMultiHitCounter = RandomWeighted(RNG_HITS, 0, 0, 3, 3, 1, 1); // 37.5%: 2 hits, 37.5%: 3 hits, 12.5% 4 hits, 12.5% 5 hits.
|
||||
@ -10529,7 +10577,7 @@ void ClearDamageCalcResults(void)
|
||||
|
||||
bool32 DoesDestinyBondFail(u32 battler)
|
||||
{
|
||||
return GetConfig(CONFIG_DESTINY_BOND_FAIL) >= GEN_7 && gBattleMons[battler].volatiles.destinyBond;
|
||||
return GetConfig(B_DESTINY_BOND_FAIL) >= GEN_7 && gBattleMons[battler].volatiles.destinyBond;
|
||||
}
|
||||
|
||||
// This check has always to be the last in a condtion statement because of the recording of AI data.
|
||||
@ -10815,7 +10863,7 @@ bool32 CanMoveSkipAccuracyCalc(u32 battlerAtk, u32 battlerDef, enum Ability abil
|
||||
u32 nonVolatileStatus = GetMoveNonVolatileStatus(move);
|
||||
|
||||
if ((gBattleMons[battlerDef].volatiles.lockOn && gDisableStructs[battlerDef].battlerWithSureHit == battlerAtk)
|
||||
|| (GetConfig(CONFIG_TOXIC_NEVER_MISS) >= GEN_6 && nonVolatileStatus == MOVE_EFFECT_TOXIC && IS_BATTLER_OF_TYPE(battlerAtk, TYPE_POISON))
|
||||
|| (GetConfig(B_TOXIC_NEVER_MISS) >= GEN_6 && nonVolatileStatus == MOVE_EFFECT_TOXIC && IS_BATTLER_OF_TYPE(battlerAtk, TYPE_POISON))
|
||||
|| gBattleMons[battlerDef].volatiles.glaiveRush)
|
||||
{
|
||||
effect = TRUE;
|
||||
@ -10902,7 +10950,7 @@ u32 GetTotalAccuracy(u32 battlerAtk, u32 battlerDef, u32 move, enum Ability atkA
|
||||
accStage = gBattleMons[battlerAtk].statStages[STAT_ACC];
|
||||
evasionStage = gBattleMons[battlerDef].statStages[STAT_EVASION];
|
||||
if (atkAbility == ABILITY_UNAWARE || atkAbility == ABILITY_KEEN_EYE || atkAbility == ABILITY_MINDS_EYE
|
||||
|| (GetConfig(CONFIG_ILLUMINATE_EFFECT) >= GEN_9 && atkAbility == ABILITY_ILLUMINATE))
|
||||
|| (GetConfig(B_ILLUMINATE_EFFECT) >= GEN_9 && atkAbility == ABILITY_ILLUMINATE))
|
||||
evasionStage = DEFAULT_STAT_STAGE;
|
||||
if (MoveIgnoresDefenseEvasionStages(move))
|
||||
evasionStage = DEFAULT_STAT_STAGE;
|
||||
@ -11078,8 +11126,8 @@ static bool32 IsOpposingSideEmpty(u32 battler)
|
||||
|
||||
bool32 IsAffectedByPowderMove(u32 battler, u32 ability, enum HoldEffect holdEffect)
|
||||
{
|
||||
if ((GetConfig(CONFIG_POWDER_OVERCOAT) >= GEN_6 && ability == ABILITY_OVERCOAT)
|
||||
|| (GetConfig(CONFIG_POWDER_GRASS) >= GEN_6 && IS_BATTLER_OF_TYPE(battler, TYPE_GRASS))
|
||||
if ((GetConfig(B_POWDER_OVERCOAT) >= GEN_6 && ability == ABILITY_OVERCOAT)
|
||||
|| (GetConfig(B_POWDER_GRASS) >= GEN_6 && IS_BATTLER_OF_TYPE(battler, TYPE_GRASS))
|
||||
|| holdEffect == HOLD_EFFECT_SAFETY_GOGGLES)
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
|
||||
24
src/berry.c
24
src/berry.c
@ -20,6 +20,7 @@ static u8 BerryTreeGetNumStagesWatered(struct BerryTree *tree);
|
||||
static u8 GetNumStagesWateredByBerryTreeId(u8 id);
|
||||
static u8 CalcBerryYieldInternal(u16 max, u16 min, u8 water);
|
||||
static u8 CalcBerryYield(struct BerryTree *tree);
|
||||
static u32 GetBerryTreeAge(u8 id, u8 stage);
|
||||
static u8 GetBerryCountByBerryTreeId(u8 id);
|
||||
static u16 GetStageDurationByBerryType(u8);
|
||||
static u8 GetDrainRateByBerryType(u8);
|
||||
@ -1961,8 +1962,15 @@ void PlantBerryTree(u8 id, u8 berry, u8 stage, bool8 allowGrowth)
|
||||
tree->stage = stage;
|
||||
tree->moistureLevel = 100;
|
||||
if (OW_BERRY_ALWAYS_WATERABLE)
|
||||
tree->berryYield = GetBerryInfo(berry)->maxYield;
|
||||
if (stage == BERRY_STAGE_BERRIES)
|
||||
{
|
||||
// We simulate a tree having grown without water
|
||||
u32 berryTreeAge = GetBerryTreeAge(id, stage);
|
||||
if (GetBerryInfo(berry)->maxYield - berryTreeAge * GetBerryInfo(berry)->maxYield / 5 < GetBerryInfo(berry)->minYield)
|
||||
tree->berryYield = GetBerryInfo(berry)->minYield;
|
||||
else
|
||||
tree->berryYield = GetBerryInfo(berry)->maxYield - berryTreeAge * GetBerryInfo(berry)->maxYield / 5;
|
||||
}
|
||||
else if (stage == BERRY_STAGE_BERRIES)
|
||||
{
|
||||
tree->berryYield = CalcBerryYield(tree);
|
||||
tree->minutesUntilNextStage *= ((tree->mulch == ITEM_TO_MULCH(ITEM_STABLE_MULCH)) ? 6 : 4);
|
||||
@ -2094,6 +2102,17 @@ static u8 CalcBerryYield(struct BerryTree *tree)
|
||||
return result;
|
||||
}
|
||||
|
||||
static u32 GetBerryTreeAge(u8 id, u8 stage)
|
||||
{
|
||||
if (stage == BERRY_STAGE_TRUNK)
|
||||
stage = 5;
|
||||
else if (stage == BERRY_STAGE_BUDDING)
|
||||
stage = 6;
|
||||
else if (stage > 0)
|
||||
stage -= 1;
|
||||
return GetBerryInfo(id)->growthDuration * stage / (OW_BERRY_SIX_STAGES ? 6 : 4);
|
||||
}
|
||||
|
||||
static u8 GetBerryCountByBerryTreeId(u8 id)
|
||||
{
|
||||
return gSaveBlock1Ptr->berryTrees[id].berryYield;
|
||||
@ -2331,7 +2350,6 @@ static const u8 sBerryMutations[][3] = {
|
||||
{ITEM_TO_BERRY(ITEM_IAPAPA_BERRY), ITEM_TO_BERRY(ITEM_MAGO_BERRY), ITEM_TO_BERRY(ITEM_POMEG_BERRY)},
|
||||
{ITEM_TO_BERRY(ITEM_CHESTO_BERRY), ITEM_TO_BERRY(ITEM_PERSIM_BERRY), ITEM_TO_BERRY(ITEM_KELPSY_BERRY)},
|
||||
{ITEM_TO_BERRY(ITEM_ORAN_BERRY), ITEM_TO_BERRY(ITEM_PECHA_BERRY), ITEM_TO_BERRY(ITEM_QUALOT_BERRY)},
|
||||
{ITEM_TO_BERRY(ITEM_CHESTO_BERRY), ITEM_TO_BERRY(ITEM_PERSIM_BERRY), ITEM_TO_BERRY(ITEM_KELPSY_BERRY)},
|
||||
{ITEM_TO_BERRY(ITEM_ASPEAR_BERRY), ITEM_TO_BERRY(ITEM_LEPPA_BERRY), ITEM_TO_BERRY(ITEM_HONDEW_BERRY)},
|
||||
{ITEM_TO_BERRY(ITEM_AGUAV_BERRY), ITEM_TO_BERRY(ITEM_FIGY_BERRY), ITEM_TO_BERRY(ITEM_GREPA_BERRY)},
|
||||
{ITEM_TO_BERRY(ITEM_LUM_BERRY), ITEM_TO_BERRY(ITEM_SITRUS_BERRY), ITEM_TO_BERRY(ITEM_TAMATO_BERRY)},
|
||||
|
||||
@ -9064,8 +9064,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] =
|
||||
#endif
|
||||
.contestEffect = CONTEST_EFFECT_USER_MORE_EASILY_STARTLED,
|
||||
.contestCategory = CONTEST_CATEGORY_COOL,
|
||||
.contestComboStarterId = COMBO_STARTER_CHARGE,
|
||||
.contestComboMoves = {0},
|
||||
.contestComboStarterId = 0,
|
||||
.contestComboMoves = {COMBO_STARTER_CHARGE},
|
||||
.battleAnimScript = gBattleAnimMove_VoltTackle,
|
||||
.validApprenticeMove = TRUE,
|
||||
},
|
||||
@ -13351,8 +13351,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] =
|
||||
.category = DAMAGE_CATEGORY_SPECIAL,
|
||||
.contestEffect = CONTEST_EFFECT_AVOID_STARTLE, //CONTEST_EFFECT_QUICKLY_GROW_BORED
|
||||
.contestCategory = CONTEST_CATEGORY_COOL,
|
||||
.contestComboStarterId = COMBO_STARTER_CHARGE,
|
||||
.contestComboMoves = {0},
|
||||
.contestComboStarterId = 0,
|
||||
.contestComboMoves = {COMBO_STARTER_CHARGE},
|
||||
.battleAnimScript = gBattleAnimMove_VoltSwitch,
|
||||
},
|
||||
|
||||
@ -19483,8 +19483,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] =
|
||||
{
|
||||
.name = COMPOUND_STRING("秘剑千重涛"),
|
||||
.description = COMPOUND_STRING(
|
||||
"用贝壳之剑攻击。散落碎片\n"
|
||||
"会散落在对手脚下成为撒菱。"),
|
||||
"High critical hit ratio. Sets\n"
|
||||
"Splinters that hurt the foe."),
|
||||
.effect = EFFECT_CEASELESS_EDGE,
|
||||
.power = 65,
|
||||
.type = TYPE_DARK,
|
||||
|
||||
@ -796,13 +796,13 @@ static const struct SpriteFrameImage sPicTable_Steelix[] = {
|
||||
};
|
||||
#if P_GENDER_DIFFERENCES
|
||||
static const struct SpriteFrameImage sPicTable_SteelixF[] = {
|
||||
overworld_ascending_frames(gObjectEventPic_SteelixF, 4, 4),
|
||||
overworld_ascending_frames(gObjectEventPic_SteelixF, 8, 8),
|
||||
};
|
||||
#endif //P_GENDER_DIFFERENCES
|
||||
#if OW_BATTLE_ONLY_FORMS
|
||||
#if P_MEGA_EVOLUTIONS
|
||||
static const struct SpriteFrameImage sPicTable_SteelixMega[] = {
|
||||
overworld_ascending_frames(gObjectEventPic_SteelixMega, 4, 4),
|
||||
overworld_ascending_frames(gObjectEventPic_SteelixMega, 8, 8),
|
||||
};
|
||||
#endif // P_MEGA_EVOLUTIONS
|
||||
#endif // OW_BATTLE_ONLY_FORMS
|
||||
@ -2994,7 +2994,7 @@ static const struct SpriteFrameImage sPicTable_Latias[] = {
|
||||
#if OW_BATTLE_ONLY_FORMS
|
||||
#if P_MEGA_EVOLUTIONS
|
||||
static const struct SpriteFrameImage sPicTable_LatiasMega[] = {
|
||||
overworld_ascending_frames(gObjectEventPic_LatiasMega, 4, 4),
|
||||
overworld_ascending_frames(gObjectEventPic_LatiasMega, 8, 8),
|
||||
};
|
||||
#endif // P_MEGA_EVOLUTIONS
|
||||
#endif // OW_BATTLE_ONLY_FORMS
|
||||
@ -3007,7 +3007,7 @@ static const struct SpriteFrameImage sPicTable_Latios[] = {
|
||||
#if OW_BATTLE_ONLY_FORMS
|
||||
#if P_MEGA_EVOLUTIONS
|
||||
static const struct SpriteFrameImage sPicTable_LatiosMega[] = {
|
||||
overworld_ascending_frames(gObjectEventPic_LatiosMega, 4, 4),
|
||||
overworld_ascending_frames(gObjectEventPic_LatiosMega, 8, 8),
|
||||
};
|
||||
#endif // P_MEGA_EVOLUTIONS
|
||||
#endif // OW_BATTLE_ONLY_FORMS
|
||||
@ -3020,7 +3020,7 @@ static const struct SpriteFrameImage sPicTable_Kyogre[] = {
|
||||
#if OW_BATTLE_ONLY_FORMS
|
||||
#if P_PRIMAL_REVERSIONS
|
||||
static const struct SpriteFrameImage sPicTable_KyogrePrimal[] = {
|
||||
overworld_ascending_frames(gObjectEventPic_KyogrePrimal, 4, 4),
|
||||
overworld_ascending_frames(gObjectEventPic_KyogrePrimal, 8, 8),
|
||||
};
|
||||
#endif // P_PRIMAL_REVERSIONS
|
||||
#endif // OW_BATTLE_ONLY_FORMS
|
||||
@ -3033,7 +3033,7 @@ static const struct SpriteFrameImage sPicTable_Groudon[] = {
|
||||
#if OW_BATTLE_ONLY_FORMS
|
||||
#if P_PRIMAL_REVERSIONS
|
||||
static const struct SpriteFrameImage sPicTable_GroudonPrimal[] = {
|
||||
overworld_ascending_frames(gObjectEventPic_GroudonPrimal, 4, 4),
|
||||
overworld_ascending_frames(gObjectEventPic_GroudonPrimal, 8, 8),
|
||||
};
|
||||
#endif // P_PRIMAL_REVERSIONS
|
||||
#endif // OW_BATTLE_ONLY_FORMS
|
||||
@ -3046,7 +3046,7 @@ static const struct SpriteFrameImage sPicTable_Rayquaza[] = {
|
||||
#if OW_BATTLE_ONLY_FORMS
|
||||
#if P_MEGA_EVOLUTIONS
|
||||
static const struct SpriteFrameImage sPicTable_RayquazaMega[] = {
|
||||
overworld_ascending_frames(gObjectEventPic_RayquazaMega, 4, 4),
|
||||
overworld_ascending_frames(gObjectEventPic_RayquazaMega, 8, 8),
|
||||
};
|
||||
#endif // P_MEGA_EVOLUTIONS
|
||||
#endif // OW_BATTLE_ONLY_FORMS
|
||||
|
||||
@ -2255,7 +2255,7 @@ static void DebugAction_Give_PokemonSimple(u8 taskId)
|
||||
gTasks[taskId].tIsComplex = FALSE;
|
||||
|
||||
FreeMonIconPalettes();
|
||||
LoadMonIconPalette(gTasks[taskId].tInput);
|
||||
LoadMonIconPalettePersonality(gTasks[taskId].tInput, 0);
|
||||
gTasks[taskId].tSpriteId = CreateMonIcon(gTasks[taskId].tInput, SpriteCB_MonIcon, DEBUG_NUMBER_ICON_X, DEBUG_NUMBER_ICON_Y, 4, 0);
|
||||
gSprites[gTasks[taskId].tSpriteId].oam.priority = 0;
|
||||
}
|
||||
@ -2289,7 +2289,7 @@ static void DebugAction_Give_PokemonComplex(u8 taskId)
|
||||
gTasks[taskId].tIsComplex = TRUE;
|
||||
|
||||
FreeMonIconPalettes();
|
||||
LoadMonIconPalette(gTasks[taskId].tInput);
|
||||
LoadMonIconPalettePersonality(gTasks[taskId].tInput, 0);
|
||||
gTasks[taskId].tSpriteId = CreateMonIcon(gTasks[taskId].tInput, SpriteCB_MonIcon, DEBUG_NUMBER_ICON_X, DEBUG_NUMBER_ICON_Y, 4, 0);
|
||||
gSprites[gTasks[taskId].tSpriteId].oam.priority = 0;
|
||||
gTasks[taskId].tIterator = 0;
|
||||
@ -2313,7 +2313,7 @@ static void DebugAction_Give_Pokemon_SelectId(u8 taskId)
|
||||
Debug_Display_SpeciesInfo(gTasks[taskId].tInput, gTasks[taskId].tDigit, gTasks[taskId].tSubWindowId);
|
||||
FreeAndDestroyMonIconSprite(&gSprites[gTasks[taskId].tSpriteId]);
|
||||
FreeMonIconPalettes();
|
||||
LoadMonIconPalette(gTasks[taskId].tInput);
|
||||
LoadMonIconPalettePersonality(gTasks[taskId].tInput, 0);
|
||||
gTasks[taskId].tSpriteId = CreateMonIcon(gTasks[taskId].tInput, SpriteCB_MonIcon, DEBUG_NUMBER_ICON_X, DEBUG_NUMBER_ICON_Y, 4, 0);
|
||||
gSprites[gTasks[taskId].tSpriteId].oam.priority = 0;
|
||||
}
|
||||
|
||||
@ -1971,7 +1971,11 @@ struct Pokemon *GetFirstLiveMon(void)
|
||||
for (i = 0; i < PARTY_SIZE; i++)
|
||||
{
|
||||
struct Pokemon *mon = &gPlayerParty[i];
|
||||
if ((OW_FOLLOWERS_ALLOWED_SPECIES && GetMonData(mon, MON_DATA_SPECIES_OR_EGG) != VarGet(OW_FOLLOWERS_ALLOWED_SPECIES))
|
||||
u32 species = GetMonData(mon, MON_DATA_SPECIES_OR_EGG);
|
||||
if (species == SPECIES_NONE)
|
||||
continue;
|
||||
|
||||
if ((OW_FOLLOWERS_ALLOWED_SPECIES && species != VarGet(OW_FOLLOWERS_ALLOWED_SPECIES))
|
||||
|| (OW_FOLLOWERS_ALLOWED_MET_LVL && GetMonData(mon, MON_DATA_MET_LEVEL) != VarGet(OW_FOLLOWERS_ALLOWED_MET_LVL))
|
||||
|| (OW_FOLLOWERS_ALLOWED_MET_LOC && GetMonData(mon, MON_DATA_MET_LOCATION) != VarGet(OW_FOLLOWERS_ALLOWED_MET_LOC)))
|
||||
continue;
|
||||
|
||||
@ -277,9 +277,9 @@ static const u8 sRSAvatarGfxIds[GENDER_COUNT] =
|
||||
[FEMALE] = OBJ_EVENT_GFX_LINK_RS_MAY
|
||||
};
|
||||
|
||||
static const struct __attribute__((packed))
|
||||
static const struct PACKED
|
||||
{
|
||||
u8 graphicsId;
|
||||
u16 graphicsId;
|
||||
u8 playerFlag;
|
||||
} sPlayerAvatarGfxToStateFlag[GENDER_COUNT][5] =
|
||||
{
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
#include "malloc.h"
|
||||
#include "constants/generational_changes.h"
|
||||
|
||||
#define UNPACK_CONFIG_GEN_CHANGES2(_name, _field, ...) ._field = B_##_name,
|
||||
#define UNPACK_CONFIG_GEN_CHANGES2(_name, _field, ...) ._field = _name,
|
||||
|
||||
const struct GenChanges sConfigChanges =
|
||||
{
|
||||
@ -31,7 +31,7 @@ EWRAM_DATA struct GenChanges *gConfigChangesTestOverride = NULL;
|
||||
|
||||
// Gets the value of a volatile status flag for a certain battler
|
||||
// Primarily used for the debug menu and scripts. Outside of it explicit references are preferred
|
||||
u32 GetConfig(enum ConfigTag _genConfig)
|
||||
u32 GetConfigInternal(enum ConfigTag _genConfig)
|
||||
{
|
||||
#if TESTING
|
||||
if (gConfigChangesTestOverride == NULL)
|
||||
|
||||
@ -3725,6 +3725,9 @@ bool8 PokemonUseItemEffects(struct Pokemon *mon, u16 item, u8 partyIndex, u8 mov
|
||||
u8 effectFlags;
|
||||
s8 evChange;
|
||||
u16 evCount;
|
||||
u8 levelBefore;
|
||||
bool8 didLevelUp = FALSE;
|
||||
bool8 isLevelUpItem;
|
||||
|
||||
// Determine the EV cap to use
|
||||
u32 maxAllowedEVs = !B_EV_ITEMS_CAP ? MAX_TOTAL_EVS : GetCurrentEVCap();
|
||||
@ -3746,6 +3749,8 @@ bool8 PokemonUseItemEffects(struct Pokemon *mon, u16 item, u8 partyIndex, u8 mov
|
||||
|
||||
// Get item effect
|
||||
itemEffect = GetItemEffect(item);
|
||||
isLevelUpItem = (itemEffect[3] & ITEM3_LEVEL_UP) != 0;
|
||||
levelBefore = GetMonData(mon, MON_DATA_LEVEL, NULL);
|
||||
|
||||
// Do item effect
|
||||
for (i = 0; i < ITEM_EFFECT_ARG_START; i++)
|
||||
@ -3800,6 +3805,8 @@ bool8 PokemonUseItemEffects(struct Pokemon *mon, u16 item, u8 partyIndex, u8 mov
|
||||
{
|
||||
SetMonData(mon, MON_DATA_EXP, &dataUnsigned);
|
||||
CalculateMonStats(mon);
|
||||
if (GetMonData(mon, MON_DATA_LEVEL, NULL) > levelBefore)
|
||||
didLevelUp = TRUE;
|
||||
retVal = FALSE;
|
||||
}
|
||||
}
|
||||
@ -3918,6 +3925,11 @@ bool8 PokemonUseItemEffects(struct Pokemon *mon, u16 item, u8 partyIndex, u8 mov
|
||||
{
|
||||
u32 currentHP = GetMonData(mon, MON_DATA_HP, NULL);
|
||||
u32 maxHP = GetMonData(mon, MON_DATA_MAX_HP, NULL);
|
||||
if (isLevelUpItem && !didLevelUp && (effectFlags & (ITEM4_REVIVE >> 2)))
|
||||
{
|
||||
itemEffectParam++;
|
||||
break;
|
||||
}
|
||||
// Check use validity.
|
||||
if ((effectFlags & (ITEM4_REVIVE >> 2) && currentHP != 0)
|
||||
|| (!(effectFlags & (ITEM4_REVIVE >> 2)) && currentHP == 0))
|
||||
|
||||
@ -54,7 +54,7 @@ SINGLE_BATTLE_TEST("Aerilate boosts power of affected moves by 20% (Gen7+) or 30
|
||||
PARAMETRIZE { move = MOVE_SKILL_SWAP; genConfig = GEN_6; }
|
||||
|
||||
GIVEN {
|
||||
WITH_CONFIG(CONFIG_ATE_MULTIPLIER, genConfig);
|
||||
WITH_CONFIG(B_ATE_MULTIPLIER, genConfig);
|
||||
ASSUME(GetMoveType(MOVE_TACKLE) == TYPE_NORMAL);
|
||||
ASSUME(GetMoveEffect(MOVE_SKILL_SWAP) == EFFECT_SKILL_SWAP);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
|
||||
@ -47,7 +47,7 @@ SINGLE_BATTLE_TEST("Arena Trap doesn't prevent switch outs via moves that switch
|
||||
GIVEN {
|
||||
ASSUME(GetMoveEffect(move) == effect);
|
||||
ASSUME(GetMoveEffect(MOVE_SOAK) == EFFECT_SOAK);
|
||||
WITH_CONFIG(CONFIG_TELEPORT_BEHAVIOR, GEN_8);
|
||||
WITH_CONFIG(B_TELEPORT_BEHAVIOR, GEN_8);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
PLAYER(SPECIES_WYNAUT);
|
||||
OPPONENT(SPECIES_DIGLETT) { Ability(ABILITY_ARENA_TRAP); }
|
||||
@ -113,7 +113,7 @@ SINGLE_BATTLE_TEST("Arena Trap prevents switch outs from Ghost-type Pokémon (Ge
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(GetSpeciesType(SPECIES_SHUPPET, 0) == TYPE_GHOST);
|
||||
WITH_CONFIG(CONFIG_GHOSTS_ESCAPE, GEN_5);
|
||||
WITH_CONFIG(B_GHOSTS_ESCAPE, GEN_5);
|
||||
PLAYER(SPECIES_SHUPPET);
|
||||
OPPONENT(SPECIES_DIGLETT) { Ability(ABILITY_ARENA_TRAP); }
|
||||
} WHEN {
|
||||
@ -129,7 +129,7 @@ SINGLE_BATTLE_TEST("Arena Trap doesn't prevent switch outs from Ghost-type Poké
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(GetSpeciesType(SPECIES_SHUPPET, 0) == TYPE_GHOST);
|
||||
WITH_CONFIG(CONFIG_GHOSTS_ESCAPE, GEN_6);
|
||||
WITH_CONFIG(B_GHOSTS_ESCAPE, GEN_6);
|
||||
PLAYER(SPECIES_SHUPPET);
|
||||
OPPONENT(SPECIES_DIGLETT) { Ability(ABILITY_ARENA_TRAP); }
|
||||
} WHEN {
|
||||
|
||||
@ -17,7 +17,7 @@ SINGLE_BATTLE_TEST("Battle Bond transforms player's Greninja - Singles")
|
||||
PARAMETRIZE { monsCountPlayer = 2; monsCountOpponent = 2; }
|
||||
|
||||
GIVEN {
|
||||
WITH_CONFIG(CONFIG_BATTLE_BOND, GEN_8);
|
||||
WITH_CONFIG(B_BATTLE_BOND, GEN_8);
|
||||
PLAYER(SPECIES_GRENINJA_BATTLE_BOND);
|
||||
if (monsCountPlayer == 2) {
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
@ -65,7 +65,7 @@ SINGLE_BATTLE_TEST("Battle Bond transforms opponent's Greninja - Singles")
|
||||
PARAMETRIZE { monsCountPlayer = 2; monsCountOpponent = 2; }
|
||||
|
||||
GIVEN {
|
||||
WITH_CONFIG(CONFIG_BATTLE_BOND, GEN_8);
|
||||
WITH_CONFIG(B_BATTLE_BOND, GEN_8);
|
||||
OPPONENT(SPECIES_GRENINJA_BATTLE_BOND);
|
||||
if (monsCountOpponent == 2) {
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
@ -113,7 +113,7 @@ DOUBLE_BATTLE_TEST("Battle Bond transforms player's Greninja when fainting its A
|
||||
PARAMETRIZE { monsCountPlayer = 3; monsCountOpponent = 3; }
|
||||
|
||||
GIVEN {
|
||||
WITH_CONFIG(CONFIG_BATTLE_BOND, GEN_8);
|
||||
WITH_CONFIG(B_BATTLE_BOND, GEN_8);
|
||||
PLAYER(SPECIES_GRENINJA_BATTLE_BOND);
|
||||
PLAYER(SPECIES_WOBBUFFET) { HP(1); }
|
||||
if (monsCountPlayer == 3) {
|
||||
@ -145,7 +145,7 @@ DOUBLE_BATTLE_TEST("Battle Bond transforms player's Greninja when fainting its A
|
||||
SINGLE_BATTLE_TEST("Battle Bond increases Atk, SpAtk and Speed by 1 stage (Gen9+)")
|
||||
{
|
||||
GIVEN {
|
||||
WITH_CONFIG(CONFIG_BATTLE_BOND, GEN_9);
|
||||
WITH_CONFIG(B_BATTLE_BOND, GEN_9);
|
||||
PLAYER(SPECIES_GRENINJA_BATTLE_BOND) { Ability(ABILITY_BATTLE_BOND); }
|
||||
OPPONENT(SPECIES_WOBBUFFET) { HP(1); }
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
@ -166,7 +166,7 @@ SINGLE_BATTLE_TEST("Battle Bond increases Atk, SpAtk and Speed by 1 stage (Gen9+
|
||||
SINGLE_BATTLE_TEST("Battle Bond increases a Stat even if only one can be increased (Gen9+)")
|
||||
{
|
||||
GIVEN {
|
||||
WITH_CONFIG(CONFIG_BATTLE_BOND, GEN_9);
|
||||
WITH_CONFIG(B_BATTLE_BOND, GEN_9);
|
||||
PLAYER(SPECIES_GRENINJA_BATTLE_BOND) { Ability(ABILITY_BATTLE_BOND); }
|
||||
OPPONENT(SPECIES_WOBBUFFET) { HP(1); }
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
|
||||
@ -119,7 +119,7 @@ SINGLE_BATTLE_TEST("Cheek Pouch doesn't activate when using Natural Gift")
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Cheek Pouch doesn't activate when using Fling")
|
||||
SINGLE_BATTLE_TEST("Cheek Pouch doesn't activate when user uses Fling")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(GetMoveEffect(MOVE_FLING) == EFFECT_FLING);
|
||||
|
||||
@ -455,3 +455,22 @@ DOUBLE_BATTLE_TEST("Commander prevent Dondozo from switch out by Dragon Tail")
|
||||
NOT MESSAGE("Wobbuffet was dragged out!");
|
||||
}
|
||||
}
|
||||
|
||||
DOUBLE_BATTLE_TEST("Commander will not activate if partner Dondozo is about to switch out")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
PLAYER(SPECIES_DONDOZO);
|
||||
PLAYER(SPECIES_TATSUGIRI) { Ability(ABILITY_COMMANDER); }
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN {
|
||||
SWITCH(playerLeft, 2);
|
||||
SWITCH(playerRight, 3);
|
||||
}
|
||||
} SCENE {
|
||||
NOT ABILITY_POPUP(playerRight, ABILITY_COMMANDER);
|
||||
}
|
||||
}
|
||||
|
||||
@ -140,7 +140,7 @@ SINGLE_BATTLE_TEST("Competitive activates after Sticky Web lowers Speed")
|
||||
SINGLE_BATTLE_TEST("Competitive doesn't activate after Sticky Web lowers Speed if Court Changed (gen8)")
|
||||
{
|
||||
GIVEN {
|
||||
WITH_CONFIG(CONFIG_DEFIANT_STICKY_WEB, GEN_8);
|
||||
WITH_CONFIG(B_DEFIANT_STICKY_WEB, GEN_8);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
PLAYER(SPECIES_IGGLYBUFF) { Ability(ABILITY_COMPETITIVE); }
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
@ -167,7 +167,7 @@ SINGLE_BATTLE_TEST("Competitive doesn't activate after Sticky Web lowers Speed i
|
||||
SINGLE_BATTLE_TEST("Competitive correctly activates after Sticky Web lowers Speed if Court Changed (Gen8)")
|
||||
{
|
||||
GIVEN {
|
||||
WITH_CONFIG(CONFIG_DEFIANT_STICKY_WEB, GEN_8);
|
||||
WITH_CONFIG(B_DEFIANT_STICKY_WEB, GEN_8);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
PLAYER(SPECIES_IGGLYBUFF) { Ability(ABILITY_COMPETITIVE); }
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
|
||||
@ -66,34 +66,7 @@ SINGLE_BATTLE_TEST("Corrosion does not effect poison type damaging moves if the
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Corrosion can poison Poison- and Steel-type targets if it uses Fling while holding a Toxic Orb or a Poison Barb")
|
||||
{
|
||||
u16 heldItem;
|
||||
|
||||
PARAMETRIZE { heldItem = ITEM_POISON_BARB; }
|
||||
PARAMETRIZE { heldItem = ITEM_TOXIC_ORB; }
|
||||
|
||||
GIVEN {
|
||||
ASSUME(GetMoveEffect(MOVE_FLING) == EFFECT_FLING);
|
||||
ASSUME(gItemsInfo[ITEM_POISON_BARB].holdEffect == HOLD_EFFECT_TYPE_POWER);
|
||||
ASSUME(gItemsInfo[ITEM_POISON_BARB].secondaryId == TYPE_POISON);
|
||||
ASSUME(gItemsInfo[ITEM_TOXIC_ORB].holdEffect == HOLD_EFFECT_TOXIC_ORB);
|
||||
PLAYER(SPECIES_SALANDIT) { Ability(ABILITY_CORROSION); Item(heldItem); }
|
||||
OPPONENT(SPECIES_ODDISH);
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_FLING); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_FLING, player);
|
||||
HP_BAR(opponent);
|
||||
ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_PSN, opponent);
|
||||
if (heldItem == ITEM_POISON_BARB)
|
||||
STATUS_ICON(opponent, poison: TRUE);
|
||||
else
|
||||
STATUS_ICON(opponent, badPoison: TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("If a Poison- or Steel-type Pokémon with Corrosion holds a Toxic Orb, it will badly poison itself")
|
||||
SINGLE_BATTLE_TEST("Corrosion badly poisons its Poison/Steel-type user who holds a Toxic Orb")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(gItemsInfo[ITEM_TOXIC_ORB].holdEffect == HOLD_EFFECT_TOXIC_ORB);
|
||||
@ -107,7 +80,7 @@ SINGLE_BATTLE_TEST("If a Poison- or Steel-type Pokémon with Corrosion holds a T
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("If a Poison- or Steel-type Pokémon with Corrosion poisons a target with Synchronize, Synchronize will not poison Poison- or Steel-type Pokémon")
|
||||
SINGLE_BATTLE_TEST("Corrosion can poison a target with Synchronize and Synchronize will not poison Poison- or Steel-type Pokémon")
|
||||
{
|
||||
u16 move;
|
||||
PARAMETRIZE { move = MOVE_TOXIC; }
|
||||
|
||||
@ -55,7 +55,7 @@ SINGLE_BATTLE_TEST("Cute Charm triggers 1/3 times (Gen3) or 30% (Gen 4+) of the
|
||||
PARAMETRIZE { config = GEN_4; passes = 3; trials = 10; } // 30%
|
||||
PASSES_RANDOMLY(passes, trials, RNG_CUTE_CHARM);
|
||||
GIVEN {
|
||||
WITH_CONFIG(CONFIG_ABILITY_TRIGGER_CHANCE, config);
|
||||
WITH_CONFIG(B_ABILITY_TRIGGER_CHANCE, config);
|
||||
ASSUME(MoveMakesContact(MOVE_SCRATCH));
|
||||
PLAYER(SPECIES_WOBBUFFET) { Gender(MON_MALE); }
|
||||
OPPONENT(SPECIES_CLEFAIRY) { Gender(MON_FEMALE); Ability(ABILITY_CUTE_CHARM); }
|
||||
|
||||
@ -580,7 +580,7 @@ SINGLE_BATTLE_TEST("Dancer user may hit itself in confusion instead of copying a
|
||||
PARAMETRIZE { genConfig = GEN_7; pctChance = 33; }
|
||||
PASSES_RANDOMLY(pctChance, 100, RNG_CONFUSION);
|
||||
GIVEN {
|
||||
WITH_CONFIG(CONFIG_CONFUSION_SELF_DMG_CHANCE, genConfig);
|
||||
WITH_CONFIG(B_CONFUSION_SELF_DMG_CHANCE, genConfig);
|
||||
ASSUME(IsDanceMove(MOVE_DRAGON_DANCE));
|
||||
ASSUME(GetMoveEffect(MOVE_CONFUSE_RAY) == EFFECT_CONFUSE);
|
||||
PLAYER(SPECIES_WOBBUFFET) { Speed(30); }
|
||||
@ -747,7 +747,7 @@ SINGLE_BATTLE_TEST("Dancer can still copy status moves if the user is holding an
|
||||
DOUBLE_BATTLE_TEST("Dancer copies Lunar Dance after the original user faints, but before the replacement is sent out")
|
||||
{
|
||||
GIVEN {
|
||||
WITH_CONFIG(CONFIG_HEALING_WISH_SWITCH, GEN_7);
|
||||
WITH_CONFIG(B_HEALING_WISH_SWITCH, GEN_7);
|
||||
ASSUME(GetMoveEffect(MOVE_LUNAR_DANCE) == EFFECT_LUNAR_DANCE);
|
||||
PLAYER(SPECIES_WOBBUFFET) { Speed(50); }
|
||||
PLAYER(SPECIES_ORICORIO) { Ability(ABILITY_DANCER); Speed(20); }
|
||||
|
||||
@ -20,7 +20,7 @@ SINGLE_BATTLE_TEST("Dauntless Shield raises Defense by one stage")
|
||||
SINGLE_BATTLE_TEST("Dauntless Shield raises Defense by one stage every time it switches in (Gen8)")
|
||||
{
|
||||
GIVEN {
|
||||
WITH_CONFIG(CONFIG_DAUNTLESS_SHIELD, GEN_8);
|
||||
WITH_CONFIG(B_DAUNTLESS_SHIELD, GEN_8);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_ZAMAZENTA) { Ability(ABILITY_DAUNTLESS_SHIELD); }
|
||||
OPPONENT(SPECIES_WYNAUT);
|
||||
@ -42,7 +42,7 @@ SINGLE_BATTLE_TEST("Dauntless Shield raises Defense by one stage every time it s
|
||||
SINGLE_BATTLE_TEST("Dauntless Shield raises Defense by one stage only once per battle (Gen 9+)")
|
||||
{
|
||||
GIVEN {
|
||||
WITH_CONFIG(CONFIG_DAUNTLESS_SHIELD, GEN_9);
|
||||
WITH_CONFIG(B_DAUNTLESS_SHIELD, GEN_9);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_ZAMAZENTA) { Ability(ABILITY_DAUNTLESS_SHIELD); }
|
||||
OPPONENT(SPECIES_WYNAUT);
|
||||
|
||||
@ -142,7 +142,7 @@ SINGLE_BATTLE_TEST("Defiant activates after Sticky Web lowers Speed")
|
||||
SINGLE_BATTLE_TEST("Defiant doesn't activate after Sticky Web lowers Speed if Court Changed (Gen8)")
|
||||
{
|
||||
GIVEN {
|
||||
WITH_CONFIG(CONFIG_DEFIANT_STICKY_WEB, GEN_8);
|
||||
WITH_CONFIG(B_DEFIANT_STICKY_WEB, GEN_8);
|
||||
ASSUME(GetMoveEffect(MOVE_GROWL) == EFFECT_ATTACK_DOWN);
|
||||
ASSUME(GetMoveEffect(MOVE_STICKY_WEB) == EFFECT_STICKY_WEB);
|
||||
ASSUME(GetMoveEffect(MOVE_COURT_CHANGE) == EFFECT_COURT_CHANGE);
|
||||
@ -179,7 +179,7 @@ SINGLE_BATTLE_TEST("Defiant doesn't activate after Sticky Web lowers Speed if Co
|
||||
SINGLE_BATTLE_TEST("Defiant activates after Sticky Web lowers Speed if Court Changed (Gen9)")
|
||||
{
|
||||
GIVEN {
|
||||
WITH_CONFIG(CONFIG_DEFIANT_STICKY_WEB, GEN_9);
|
||||
WITH_CONFIG(B_DEFIANT_STICKY_WEB, GEN_9);
|
||||
ASSUME(GetMoveEffect(MOVE_GROWL) == EFFECT_ATTACK_DOWN);
|
||||
ASSUME(GetMoveEffect(MOVE_STICKY_WEB) == EFFECT_STICKY_WEB);
|
||||
ASSUME(GetMoveEffect(MOVE_COURT_CHANGE) == EFFECT_COURT_CHANGE);
|
||||
|
||||
@ -9,7 +9,7 @@ ASSUMPTIONS
|
||||
SINGLE_BATTLE_TEST("Disguised Mimikyu doesn't lose 1/8 of its max HP upon changing to its busted form (Gen7)")
|
||||
{
|
||||
GIVEN {
|
||||
WITH_CONFIG(CONFIG_DISGUISE_HP_LOSS, GEN_7);
|
||||
WITH_CONFIG(B_DISGUISE_HP_LOSS, GEN_7);
|
||||
PLAYER(SPECIES_MIMIKYU_DISGUISED) { Ability(ABILITY_DISGUISE); }
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
@ -29,7 +29,7 @@ SINGLE_BATTLE_TEST("Disguised Mimikyu will lose 1/8 of its max HP upon changing
|
||||
s16 disguiseDamage;
|
||||
|
||||
GIVEN {
|
||||
WITH_CONFIG(CONFIG_DISGUISE_HP_LOSS, GEN_8);
|
||||
WITH_CONFIG(B_DISGUISE_HP_LOSS, GEN_8);
|
||||
PLAYER(SPECIES_MIMIKYU_DISGUISED) { Ability(ABILITY_DISGUISE); }
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
|
||||
@ -26,7 +26,7 @@ SINGLE_BATTLE_TEST("Drizzle summons rain", s16 damage)
|
||||
SINGLE_BATTLE_TEST("Drizzle sets up rain for 5 turns (Gen6+)")
|
||||
{
|
||||
GIVEN {
|
||||
WITH_CONFIG(CONFIG_ABILITY_WEATHER, GEN_6);
|
||||
WITH_CONFIG(B_ABILITY_WEATHER, GEN_6);
|
||||
PLAYER(SPECIES_POLITOED) { Moves(MOVE_CELEBRATE); Ability(ABILITY_DRIZZLE); }
|
||||
OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_CELEBRATE); }
|
||||
} WHEN {
|
||||
@ -48,7 +48,7 @@ SINGLE_BATTLE_TEST("Drizzle sets up rain for 5 turns (Gen6+)")
|
||||
SINGLE_BATTLE_TEST("Drizzle sets up rain for 8 turns with Damp Rock (Gen6+)")
|
||||
{
|
||||
GIVEN {
|
||||
WITH_CONFIG(CONFIG_ABILITY_WEATHER, GEN_6);
|
||||
WITH_CONFIG(B_ABILITY_WEATHER, GEN_6);
|
||||
PLAYER(SPECIES_POLITOED) { Moves(MOVE_CELEBRATE); Ability(ABILITY_DRIZZLE); Item(ITEM_DAMP_ROCK); }
|
||||
OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_CELEBRATE); }
|
||||
} WHEN {
|
||||
@ -76,7 +76,7 @@ SINGLE_BATTLE_TEST("Drizzle sets up rain for 8 turns with Damp Rock (Gen6+)")
|
||||
SINGLE_BATTLE_TEST("Drizzle sets up permanent rain (Gen3-5)")
|
||||
{
|
||||
GIVEN {
|
||||
WITH_CONFIG(CONFIG_ABILITY_WEATHER, GEN_3);
|
||||
WITH_CONFIG(B_ABILITY_WEATHER, GEN_3);
|
||||
PLAYER(SPECIES_POLITOED) { Moves(MOVE_CELEBRATE); Ability(ABILITY_DRIZZLE); }
|
||||
OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_CELEBRATE); }
|
||||
} WHEN {
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
SINGLE_BATTLE_TEST("Drought sets up sun for 5 turns (Gen6+)")
|
||||
{
|
||||
GIVEN {
|
||||
WITH_CONFIG(CONFIG_ABILITY_WEATHER, GEN_6);
|
||||
WITH_CONFIG(B_ABILITY_WEATHER, GEN_6);
|
||||
PLAYER(SPECIES_NINETALES) { Moves(MOVE_CELEBRATE); Ability(ABILITY_DROUGHT); }
|
||||
OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_CELEBRATE); }
|
||||
} WHEN {
|
||||
@ -26,7 +26,7 @@ SINGLE_BATTLE_TEST("Drought sets up sun for 5 turns (Gen6+)")
|
||||
SINGLE_BATTLE_TEST("Drought sets up sun for 8 turns with Heat Rock (Gen6+)")
|
||||
{
|
||||
GIVEN {
|
||||
WITH_CONFIG(CONFIG_ABILITY_WEATHER, GEN_6);
|
||||
WITH_CONFIG(B_ABILITY_WEATHER, GEN_6);
|
||||
PLAYER(SPECIES_NINETALES) { Moves(MOVE_CELEBRATE); Ability(ABILITY_DROUGHT); Item(ITEM_HEAT_ROCK); }
|
||||
OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_CELEBRATE); }
|
||||
} WHEN {
|
||||
@ -54,7 +54,7 @@ SINGLE_BATTLE_TEST("Drought sets up sun for 8 turns with Heat Rock (Gen6+)")
|
||||
SINGLE_BATTLE_TEST("Drought sets up permanent sun (Gen3-5)")
|
||||
{
|
||||
GIVEN {
|
||||
WITH_CONFIG(CONFIG_ABILITY_WEATHER, GEN_3);
|
||||
WITH_CONFIG(B_ABILITY_WEATHER, GEN_3);
|
||||
PLAYER(SPECIES_NINETALES) { Moves(MOVE_CELEBRATE); Ability(ABILITY_DROUGHT); }
|
||||
OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_CELEBRATE); }
|
||||
} WHEN {
|
||||
|
||||
@ -1,4 +1,49 @@
|
||||
#include "global.h"
|
||||
#include "test/battle.h"
|
||||
|
||||
TO_DO_BATTLE_TEST("TODO: Write Early Bird (Ability) test titles")
|
||||
SINGLE_BATTLE_TEST("Early Bird wakes up if 1 sleep turn is preset")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_DODUO) { Ability(ABILITY_EARLY_BIRD); Status1(STATUS1_SLEEP_TURN(1)); Moves(MOVE_CELEBRATE); }
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_CELEBRATE); }
|
||||
} SCENE {
|
||||
MESSAGE("Doduo woke up!");
|
||||
STATUS_ICON(player, none: TRUE);
|
||||
MESSAGE("Doduo used Celebrate!");
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Early Bird turns a 3-turn sleep into one missed turn")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_DODUO) { Ability(ABILITY_EARLY_BIRD); Status1(STATUS1_SLEEP_TURN(3)); Moves(MOVE_CELEBRATE); }
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_CELEBRATE); }
|
||||
TURN { MOVE(player, MOVE_CELEBRATE); }
|
||||
} SCENE {
|
||||
MESSAGE("Doduo is fast asleep.");
|
||||
MESSAGE("Doduo woke up!");
|
||||
STATUS_ICON(player, none: TRUE);
|
||||
MESSAGE("Doduo used Celebrate!");
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Early Bird reduces Rest sleep to one turn")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_DODUO) { Ability(ABILITY_EARLY_BIRD); MaxHP(99); HP(66); Moves(MOVE_REST, MOVE_CELEBRATE); }
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_REST); }
|
||||
TURN { MOVE(player, MOVE_CELEBRATE); }
|
||||
TURN { MOVE(player, MOVE_CELEBRATE); }
|
||||
} SCENE {
|
||||
MESSAGE("Doduo is fast asleep.");
|
||||
MESSAGE("Doduo woke up!");
|
||||
STATUS_ICON(player, none: TRUE);
|
||||
MESSAGE("Doduo used Celebrate!");
|
||||
}
|
||||
}
|
||||
|
||||
@ -40,7 +40,7 @@ SINGLE_BATTLE_TEST("Effect Spore causes poison 3.3% (Gen3), 10% (Gen4) and 9% (G
|
||||
PARAMETRIZE { config = GEN_5; passes = 9; trials = 100; } // 9%
|
||||
PASSES_RANDOMLY(passes, trials, RNG_EFFECT_SPORE);
|
||||
GIVEN {
|
||||
WITH_CONFIG(CONFIG_ABILITY_TRIGGER_CHANCE, config);
|
||||
WITH_CONFIG(B_ABILITY_TRIGGER_CHANCE, config);
|
||||
ASSUME(MoveMakesContact(MOVE_SCRATCH));
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_BRELOOM) { Ability(ABILITY_EFFECT_SPORE); }
|
||||
@ -63,7 +63,7 @@ SINGLE_BATTLE_TEST("Effect Spore causes paralysis 3.3% (Gen3) and 10% (Gen4+) of
|
||||
PARAMETRIZE { config = GEN_5; passes = 1; trials = 10; } // 10%
|
||||
PASSES_RANDOMLY(passes, trials, RNG_EFFECT_SPORE);
|
||||
GIVEN {
|
||||
WITH_CONFIG(CONFIG_ABILITY_TRIGGER_CHANCE, config);
|
||||
WITH_CONFIG(B_ABILITY_TRIGGER_CHANCE, config);
|
||||
ASSUME(MoveMakesContact(MOVE_SCRATCH));
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_BRELOOM) { Ability(ABILITY_EFFECT_SPORE); }
|
||||
@ -86,7 +86,7 @@ SINGLE_BATTLE_TEST("Effect Spore causes sleep 3.3% (Gen3), 10% (Gen4) and 11% (G
|
||||
PARAMETRIZE { config = GEN_5; passes = 11; trials = 100; } // 11%
|
||||
PASSES_RANDOMLY(passes, trials, RNG_EFFECT_SPORE);
|
||||
GIVEN {
|
||||
WITH_CONFIG(CONFIG_ABILITY_TRIGGER_CHANCE, config);
|
||||
WITH_CONFIG(B_ABILITY_TRIGGER_CHANCE, config);
|
||||
ASSUME(MoveMakesContact(MOVE_SCRATCH));
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_BRELOOM) { Ability(ABILITY_EFFECT_SPORE); }
|
||||
@ -109,7 +109,7 @@ SINGLE_BATTLE_TEST("Effect Spore will check if it can inflict status onto attack
|
||||
PARAMETRIZE { config = GEN_5; passes = 11; trials = 100; } // 11%
|
||||
PASSES_RANDOMLY(passes, trials, RNG_EFFECT_SPORE);
|
||||
GIVEN {
|
||||
WITH_CONFIG(CONFIG_ABILITY_TRIGGER_CHANCE, config);
|
||||
WITH_CONFIG(B_ABILITY_TRIGGER_CHANCE, config);
|
||||
ASSUME(MoveMakesContact(MOVE_SCRATCH));
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_BRELOOM) { Status1(STATUS1_BURN); Ability(ABILITY_EFFECT_SPORE); }
|
||||
|
||||
@ -209,3 +209,73 @@ WILD_BATTLE_TEST("Emergency Exit activates when taking residual damage and falli
|
||||
EXPECT_EQ(gBattleOutcome, B_OUTCOME_PLAYER_TELEPORTED);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Emergency Exit will trigger due to recoil damage")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(GetMoveEffect(MOVE_MIND_BLOWN) == EFFECT_MAX_HP_50_RECOIL);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_GOLISOPOD) { Ability(ABILITY_EMERGENCY_EXIT); MaxHP(263); HP(262); }
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN { MOVE(opponent, MOVE_MIND_BLOWN); SEND_OUT(opponent, 1); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_MIND_BLOWN, opponent);
|
||||
HP_BAR(player);
|
||||
HP_BAR(opponent);
|
||||
ABILITY_POPUP(opponent, ABILITY_EMERGENCY_EXIT);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Emergency Exit will trigger due to confusion damage")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(GetMoveEffect(MOVE_CONFUSE_RAY) == EFFECT_CONFUSE);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_GOLISOPOD) { Ability(ABILITY_EMERGENCY_EXIT); MaxHP(263); HP(133); }
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN {
|
||||
MOVE(player, MOVE_CONFUSE_RAY);
|
||||
MOVE(opponent, MOVE_POUND);
|
||||
}
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_CONFUSE_RAY, player);
|
||||
NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_POUND, opponent);
|
||||
HP_BAR(opponent);
|
||||
NOT ABILITY_POPUP(opponent, ABILITY_EMERGENCY_EXIT);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Emergency Exit is not triggered by Pain Split")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(GetMoveEffect(MOVE_PAIN_SPLIT) == EFFECT_PAIN_SPLIT);
|
||||
PLAYER(SPECIES_WOBBUFFET) { HP(1); }
|
||||
OPPONENT(SPECIES_GOLISOPOD) { Ability(ABILITY_EMERGENCY_EXIT); MaxHP(263); HP(133); }
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_PAIN_SPLIT); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_PAIN_SPLIT, player);
|
||||
HP_BAR(opponent);
|
||||
NOT ABILITY_POPUP(opponent, ABILITY_EMERGENCY_EXIT);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Emergency Exit will trigger due to Jump Kick recoil")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(GetMoveEffect(MOVE_JUMP_KICK) == EFFECT_RECOIL_IF_MISS);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_GOLISOPOD) { Ability(ABILITY_EMERGENCY_EXIT); MaxHP(263); HP(262); }
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN { MOVE(opponent, MOVE_JUMP_KICK, hit: FALSE); SEND_OUT(opponent, 1); }
|
||||
} SCENE {
|
||||
NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_JUMP_KICK, opponent);
|
||||
HP_BAR(opponent);
|
||||
ABILITY_POPUP(opponent, ABILITY_EMERGENCY_EXIT);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -37,7 +37,7 @@ SINGLE_BATTLE_TEST("Flame Body triggers 1/3 times (Gen3) or 30% (Gen 4+) of the
|
||||
PARAMETRIZE { config = GEN_4; passes = 3; trials = 10; } // 30%
|
||||
PASSES_RANDOMLY(passes, trials, RNG_FLAME_BODY);
|
||||
GIVEN {
|
||||
WITH_CONFIG(CONFIG_ABILITY_TRIGGER_CHANCE, config);
|
||||
WITH_CONFIG(B_ABILITY_TRIGGER_CHANCE, config);
|
||||
ASSUME(MoveMakesContact(MOVE_SCRATCH));
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_MAGMAR) { Ability(ABILITY_FLAME_BODY); }
|
||||
|
||||
@ -1,4 +1,84 @@
|
||||
#include "global.h"
|
||||
#include "test/battle.h"
|
||||
|
||||
TO_DO_BATTLE_TEST("TODO: Write Forewarn (Ability) test titles")
|
||||
DOUBLE_BATTLE_TEST("Forewarn warns about the highest power move among all opposing battlers")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_MUSHARNA) { Ability(ABILITY_FOREWARN); }
|
||||
PLAYER(SPECIES_WYNAUT);
|
||||
OPPONENT(SPECIES_ZUBAT) { Moves(MOVE_CRUNCH, MOVE_CELEBRATE); }
|
||||
OPPONENT(SPECIES_EXCADRILL) { Moves(MOVE_FISSURE, MOVE_CELEBRATE); }
|
||||
} WHEN {
|
||||
TURN {}
|
||||
} SCENE {
|
||||
ABILITY_POPUP(playerLeft, ABILITY_FOREWARN);
|
||||
MESSAGE("Forewarn alerted Musharna to the opposing Excadrill's Fissure!");
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Forewarn randomly chooses between same-power moves on one opponent")
|
||||
{
|
||||
PASSES_RANDOMLY(1, 3, RNG_FOREWARN);
|
||||
GIVEN {
|
||||
ASSUME(GetMovePower(MOVE_TACKLE) == GetMovePower(MOVE_POUND));
|
||||
ASSUME(GetMovePower(MOVE_TACKLE) == GetMovePower(MOVE_SCRATCH));
|
||||
PLAYER(SPECIES_MUSHARNA) { Ability(ABILITY_FOREWARN); }
|
||||
OPPONENT(SPECIES_ZUBAT) { Moves(MOVE_TACKLE, MOVE_POUND, MOVE_SCRATCH, MOVE_CELEBRATE); }
|
||||
} WHEN {
|
||||
TURN {}
|
||||
} SCENE {
|
||||
ABILITY_POPUP(player, ABILITY_FOREWARN);
|
||||
MESSAGE("Forewarn alerted Musharna to the opposing Zubat's Tackle!");
|
||||
}
|
||||
}
|
||||
|
||||
DOUBLE_BATTLE_TEST("Forewarn randomly chooses between opponents with same-power moves")
|
||||
{
|
||||
PASSES_RANDOMLY(1, 4, RNG_FOREWARN);
|
||||
GIVEN {
|
||||
ASSUME(GetMovePower(MOVE_TACKLE) == GetMovePower(MOVE_POUND));
|
||||
ASSUME(GetMovePower(MOVE_TACKLE) == GetMovePower(MOVE_SCRATCH));
|
||||
ASSUME(GetMovePower(MOVE_TACKLE) == GetMovePower(MOVE_QUICK_ATTACK));
|
||||
PLAYER(SPECIES_MUSHARNA) { Ability(ABILITY_FOREWARN); }
|
||||
PLAYER(SPECIES_WYNAUT);
|
||||
OPPONENT(SPECIES_ZUBAT) { Moves(MOVE_TACKLE, MOVE_POUND, MOVE_PECK, MOVE_CELEBRATE); }
|
||||
OPPONENT(SPECIES_EXCADRILL) { Moves(MOVE_SCRATCH, MOVE_QUICK_ATTACK, MOVE_ABSORB, MOVE_CELEBRATE); }
|
||||
} WHEN {
|
||||
TURN {}
|
||||
} SCENE {
|
||||
ABILITY_POPUP(playerLeft, ABILITY_FOREWARN);
|
||||
MESSAGE("Forewarn alerted Musharna to the opposing Zubat's Tackle!");
|
||||
}
|
||||
}
|
||||
|
||||
DOUBLE_BATTLE_TEST("Forewarn does not trigger if a mon switches in while the opposing field is empty")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(GetMoveEffect(MOVE_U_TURN) == EFFECT_HIT_ESCAPE);
|
||||
ASSUME(GetMoveEffect(MOVE_HEALING_WISH) == EFFECT_HEALING_WISH);
|
||||
PLAYER(SPECIES_WYNAUT);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
PLAYER(SPECIES_MUSHARNA) { Ability(ABILITY_FOREWARN); }
|
||||
OPPONENT(SPECIES_WYNAUT) { HP(1); }
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_TREECKO);
|
||||
OPPONENT(SPECIES_TORCHIC);
|
||||
} WHEN {
|
||||
TURN {
|
||||
MOVE(opponentRight, MOVE_HEALING_WISH);
|
||||
MOVE(playerLeft, MOVE_U_TURN, target: opponentLeft);
|
||||
SEND_OUT(playerLeft, 2);
|
||||
SEND_OUT(opponentLeft, 2);
|
||||
SEND_OUT(opponentRight, 3);
|
||||
}
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, playerRight);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_HEALING_WISH, opponentRight);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_U_TURN, playerLeft);
|
||||
HP_BAR(opponentLeft);
|
||||
NOT ABILITY_POPUP(playerLeft, ABILITY_FOREWARN);
|
||||
MESSAGE("2 sent out Treecko!");
|
||||
MESSAGE("2 sent out Torchic!");
|
||||
NOT ABILITY_POPUP(playerLeft, ABILITY_FOREWARN);
|
||||
}
|
||||
}
|
||||
|
||||
@ -9,7 +9,7 @@ SINGLE_BATTLE_TEST("Gale Wings only grants priority at full HP (Gen 7+)")
|
||||
PARAMETRIZE { hp = 100; config = GEN_6; }
|
||||
PARAMETRIZE { hp = 99; config = GEN_6; }
|
||||
GIVEN {
|
||||
WITH_CONFIG(CONFIG_GALE_WINGS, config);
|
||||
WITH_CONFIG(B_GALE_WINGS, config);
|
||||
ASSUME(GetMoveType(MOVE_AERIAL_ACE) == TYPE_FLYING);
|
||||
PLAYER(SPECIES_TALONFLAME) { Ability(ABILITY_GALE_WINGS); HP(hp); MaxHP(100); Speed(1); }
|
||||
OPPONENT(SPECIES_WOBBUFFET) { Speed(100); }
|
||||
|
||||
@ -52,7 +52,7 @@ SINGLE_BATTLE_TEST("Galvanize boosts power of affected moves by 20% (Gen7+) or 3
|
||||
PARAMETRIZE { ability = ABILITY_GALVANIZE; genConfig = GEN_6; }
|
||||
|
||||
GIVEN {
|
||||
WITH_CONFIG(CONFIG_ATE_MULTIPLIER, genConfig);
|
||||
WITH_CONFIG(B_ATE_MULTIPLIER, genConfig);
|
||||
PLAYER(SPECIES_GEODUDE_ALOLA) { Ability(ability); Moves(MOVE_TACKLE); }
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
|
||||
@ -37,7 +37,7 @@ SINGLE_BATTLE_TEST("Heatproof halves the damage done by burn from 1/8th to 1/16t
|
||||
PARAMETRIZE { config = GEN_6; burnRate = 16; }
|
||||
|
||||
GIVEN {
|
||||
WITH_CONFIG(CONFIG_BURN_DAMAGE, config);
|
||||
WITH_CONFIG(B_BURN_DAMAGE, config);
|
||||
PLAYER (SPECIES_BRONZONG) { Ability(ABILITY_HEATPROOF); Status1(STATUS1_BURN); }
|
||||
OPPONENT (SPECIES_WOBBUFFET);
|
||||
}
|
||||
@ -49,4 +49,3 @@ SINGLE_BATTLE_TEST("Heatproof halves the damage done by burn from 1/8th to 1/16t
|
||||
HP_BAR(player, damage: maxHP / burnRate);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -117,6 +117,7 @@ SINGLE_BATTLE_TEST("Illusion breaks if user loses Illusion due to Worry Seed")
|
||||
SINGLE_BATTLE_TEST("Illusion breaks when attacked behind a substitute")
|
||||
{
|
||||
GIVEN {
|
||||
WITH_CONFIG(B_INFILTRATOR_SUBSTITUTE, GEN_6);
|
||||
PLAYER(SPECIES_DRAGAPULT) { Ability(ABILITY_INFILTRATOR); Speed(1); }
|
||||
OPPONENT(SPECIES_WOBBUFFET) { Speed(2); }
|
||||
OPPONENT(SPECIES_ZOROARK) { Speed(2); }
|
||||
|
||||
@ -1,4 +1,238 @@
|
||||
#include "global.h"
|
||||
#include "test/battle.h"
|
||||
|
||||
TO_DO_BATTLE_TEST("TODO: Write Infiltrator (Ability) test titles")
|
||||
SINGLE_BATTLE_TEST("Infiltrator bypasses the opponent's Light Screen/Reflect/Aurora Veil", s16 damage)
|
||||
{
|
||||
u32 screenMove, attackingMove, ability;
|
||||
|
||||
PARAMETRIZE { screenMove = MOVE_LIGHT_SCREEN; attackingMove = MOVE_WATER_GUN; ability = ABILITY_INFILTRATOR; }
|
||||
PARAMETRIZE { screenMove = MOVE_LIGHT_SCREEN; attackingMove = MOVE_WATER_GUN; ability = ABILITY_CLEAR_BODY; }
|
||||
PARAMETRIZE { screenMove = MOVE_REFLECT; attackingMove = MOVE_SCRATCH; ability = ABILITY_INFILTRATOR; }
|
||||
PARAMETRIZE { screenMove = MOVE_REFLECT; attackingMove = MOVE_SCRATCH; ability = ABILITY_CLEAR_BODY; }
|
||||
PARAMETRIZE { screenMove = MOVE_AURORA_VEIL; attackingMove = MOVE_WATER_GUN; ability = ABILITY_INFILTRATOR; }
|
||||
PARAMETRIZE { screenMove = MOVE_AURORA_VEIL; attackingMove = MOVE_WATER_GUN; ability = ABILITY_CLEAR_BODY; }
|
||||
|
||||
GIVEN {
|
||||
ASSUME(GetMoveEffect(MOVE_LIGHT_SCREEN) == EFFECT_LIGHT_SCREEN);
|
||||
ASSUME(GetMoveEffect(MOVE_REFLECT) == EFFECT_REFLECT);
|
||||
ASSUME(GetMoveEffect(MOVE_AURORA_VEIL) == EFFECT_AURORA_VEIL);
|
||||
ASSUME(GetMoveCategory(MOVE_WATER_GUN) == DAMAGE_CATEGORY_SPECIAL);
|
||||
ASSUME(GetMoveCategory(MOVE_SCRATCH) == DAMAGE_CATEGORY_PHYSICAL);
|
||||
PLAYER(SPECIES_DRAGAPULT) { Ability(ability); }
|
||||
OPPONENT(SPECIES_ABOMASNOW) { Ability(ABILITY_SNOW_WARNING); }
|
||||
} WHEN {
|
||||
TURN { MOVE(opponent, screenMove); MOVE(player, attackingMove); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, screenMove, opponent);
|
||||
ANIMATION(ANIM_TYPE_MOVE, attackingMove, player);
|
||||
HP_BAR(opponent, captureDamage: &results[i].damage);
|
||||
} FINALLY {
|
||||
EXPECT_MUL_EQ(results[0].damage, UQ_4_12(0.5), results[1].damage);
|
||||
EXPECT_MUL_EQ(results[2].damage, UQ_4_12(0.5), results[3].damage);
|
||||
EXPECT_MUL_EQ(results[4].damage, UQ_4_12(0.5), results[5].damage);
|
||||
}
|
||||
}
|
||||
|
||||
DOUBLE_BATTLE_TEST("Infiltrator doesn't bypass an ally's Light Screen/Reflect/Aurora Veil", s16 damage)
|
||||
{
|
||||
u32 screenMove, attackingMove, ability;
|
||||
|
||||
PARAMETRIZE { screenMove = MOVE_LIGHT_SCREEN; attackingMove = MOVE_WATER_GUN; ability = ABILITY_INFILTRATOR; }
|
||||
PARAMETRIZE { screenMove = MOVE_LIGHT_SCREEN; attackingMove = MOVE_WATER_GUN; ability = ABILITY_CLEAR_BODY; }
|
||||
PARAMETRIZE { screenMove = MOVE_REFLECT; attackingMove = MOVE_SCRATCH; ability = ABILITY_INFILTRATOR; }
|
||||
PARAMETRIZE { screenMove = MOVE_REFLECT; attackingMove = MOVE_SCRATCH; ability = ABILITY_CLEAR_BODY; }
|
||||
PARAMETRIZE { screenMove = MOVE_AURORA_VEIL; attackingMove = MOVE_WATER_GUN; ability = ABILITY_INFILTRATOR; }
|
||||
PARAMETRIZE { screenMove = MOVE_AURORA_VEIL; attackingMove = MOVE_WATER_GUN; ability = ABILITY_CLEAR_BODY; }
|
||||
|
||||
GIVEN {
|
||||
ASSUME(GetMoveEffect(MOVE_LIGHT_SCREEN) == EFFECT_LIGHT_SCREEN);
|
||||
ASSUME(GetMoveEffect(MOVE_REFLECT) == EFFECT_REFLECT);
|
||||
ASSUME(GetMoveEffect(MOVE_AURORA_VEIL) == EFFECT_AURORA_VEIL);
|
||||
ASSUME(GetMoveCategory(MOVE_WATER_GUN) == DAMAGE_CATEGORY_SPECIAL);
|
||||
ASSUME(GetMoveCategory(MOVE_SCRATCH) == DAMAGE_CATEGORY_PHYSICAL);
|
||||
PLAYER(SPECIES_DRAGAPULT) { Ability(ability); }
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_ABOMASNOW) { Ability(ABILITY_SNOW_WARNING); }
|
||||
OPPONENT(SPECIES_WYNAUT);
|
||||
} WHEN {
|
||||
TURN { MOVE(playerRight, screenMove); MOVE(playerLeft, attackingMove, target: playerRight); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, screenMove, playerRight);
|
||||
ANIMATION(ANIM_TYPE_MOVE, attackingMove, playerLeft);
|
||||
HP_BAR(playerRight, captureDamage: &results[i].damage);
|
||||
} FINALLY {
|
||||
EXPECT_EQ(results[0].damage, results[1].damage);
|
||||
EXPECT_EQ(results[2].damage, results[3].damage);
|
||||
EXPECT_EQ(results[4].damage, results[5].damage);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Infiltrator bypasses the opponent's Mist")
|
||||
{
|
||||
u32 ability;
|
||||
|
||||
PARAMETRIZE { ability = ABILITY_CLEAR_BODY; }
|
||||
PARAMETRIZE { ability = ABILITY_INFILTRATOR; }
|
||||
|
||||
GIVEN {
|
||||
ASSUME(GetMoveEffect(MOVE_MIST) == EFFECT_MIST);
|
||||
ASSUME(GetMoveEffect(MOVE_SCREECH) == EFFECT_DEFENSE_DOWN_2);
|
||||
PLAYER(SPECIES_DRAGAPULT) { Ability(ability); }
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN { MOVE(opponent, MOVE_MIST); MOVE(player, MOVE_SCREECH); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_MIST, opponent);
|
||||
if (ability == ABILITY_INFILTRATOR)
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_SCREECH, player);
|
||||
else
|
||||
NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_SCREECH, player);
|
||||
}
|
||||
}
|
||||
|
||||
DOUBLE_BATTLE_TEST("Infiltrator doesn't bypass an ally's Mist")
|
||||
{
|
||||
u32 ability;
|
||||
|
||||
PARAMETRIZE { ability = ABILITY_CLEAR_BODY; }
|
||||
PARAMETRIZE { ability = ABILITY_INFILTRATOR; }
|
||||
|
||||
GIVEN {
|
||||
ASSUME(GetMoveEffect(MOVE_MIST) == EFFECT_MIST);
|
||||
ASSUME(GetMoveEffect(MOVE_SCREECH) == EFFECT_DEFENSE_DOWN_2);
|
||||
PLAYER(SPECIES_DRAGAPULT) { Ability(ability); }
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WYNAUT);
|
||||
} WHEN {
|
||||
TURN { MOVE(playerRight, MOVE_MIST); MOVE(playerLeft, MOVE_SCREECH, target: playerRight); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_MIST, playerRight);
|
||||
NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_SCREECH, playerLeft);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Infiltrator bypasses the opponent's Safeguard")
|
||||
{
|
||||
u32 ability;
|
||||
|
||||
PARAMETRIZE { ability = ABILITY_CLEAR_BODY; }
|
||||
PARAMETRIZE { ability = ABILITY_INFILTRATOR; }
|
||||
|
||||
GIVEN {
|
||||
ASSUME(GetMoveEffect(MOVE_SAFEGUARD) == EFFECT_SAFEGUARD);
|
||||
ASSUME(GetMoveEffect(MOVE_THUNDER_WAVE) == EFFECT_NON_VOLATILE_STATUS);
|
||||
PLAYER(SPECIES_DRAGAPULT) { Ability(ability); }
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN { MOVE(opponent, MOVE_SAFEGUARD); MOVE(player, MOVE_THUNDER_WAVE); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_SAFEGUARD, opponent);
|
||||
if (ability == ABILITY_INFILTRATOR)
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_THUNDER_WAVE, player);
|
||||
else
|
||||
NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_THUNDER_WAVE, player);
|
||||
}
|
||||
}
|
||||
|
||||
DOUBLE_BATTLE_TEST("Infiltrator doesn't bypass an ally's Safeguard")
|
||||
{
|
||||
u32 ability;
|
||||
|
||||
PARAMETRIZE { ability = ABILITY_CLEAR_BODY; }
|
||||
PARAMETRIZE { ability = ABILITY_INFILTRATOR; }
|
||||
|
||||
GIVEN {
|
||||
ASSUME(GetMoveEffect(MOVE_SAFEGUARD) == EFFECT_SAFEGUARD);
|
||||
ASSUME(GetMoveEffect(MOVE_THUNDER_WAVE) == EFFECT_NON_VOLATILE_STATUS);
|
||||
PLAYER(SPECIES_DRAGAPULT) { Ability(ability); }
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WYNAUT);
|
||||
} WHEN {
|
||||
TURN { MOVE(playerRight, MOVE_SAFEGUARD); MOVE(playerLeft, MOVE_THUNDER_WAVE, target: playerRight); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_SAFEGUARD, playerRight);
|
||||
NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_THUNDER_WAVE, playerLeft);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Infiltrator bypasses the opponent's Substitute (Gen 6+)")
|
||||
{
|
||||
u32 ability, config;
|
||||
|
||||
PARAMETRIZE { ability = ABILITY_CLEAR_BODY; config = GEN_5; }
|
||||
PARAMETRIZE { ability = ABILITY_INFILTRATOR; config = GEN_5; }
|
||||
PARAMETRIZE { ability = ABILITY_CLEAR_BODY; config = GEN_6; }
|
||||
PARAMETRIZE { ability = ABILITY_INFILTRATOR; config = GEN_6; }
|
||||
|
||||
GIVEN {
|
||||
WITH_CONFIG(B_INFILTRATOR_SUBSTITUTE, config);
|
||||
ASSUME(GetMoveEffect(MOVE_SUBSTITUTE) == EFFECT_SUBSTITUTE);
|
||||
ASSUME(!MoveIgnoresSubstitute(MOVE_SCRATCH));
|
||||
PLAYER(SPECIES_DRAGAPULT) { Ability(ability); }
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN { MOVE(opponent, MOVE_SUBSTITUTE); MOVE(player, MOVE_SCRATCH); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_SUBSTITUTE, opponent);
|
||||
if (ability == ABILITY_INFILTRATOR && config >= GEN_6) {
|
||||
NOT SUB_HIT(opponent);
|
||||
} else {
|
||||
SUB_HIT(opponent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DOUBLE_BATTLE_TEST("Infiltrator bypasses an ally's Substitute (Gen 6+)")
|
||||
{
|
||||
u32 ability, config;
|
||||
|
||||
PARAMETRIZE { ability = ABILITY_CLEAR_BODY; config = GEN_5; }
|
||||
PARAMETRIZE { ability = ABILITY_INFILTRATOR; config = GEN_5; }
|
||||
PARAMETRIZE { ability = ABILITY_CLEAR_BODY; config = GEN_6; }
|
||||
PARAMETRIZE { ability = ABILITY_INFILTRATOR; config = GEN_6; }
|
||||
|
||||
GIVEN {
|
||||
WITH_CONFIG(B_INFILTRATOR_SUBSTITUTE, config);
|
||||
ASSUME(GetMoveEffect(MOVE_SUBSTITUTE) == EFFECT_SUBSTITUTE);
|
||||
ASSUME(!MoveIgnoresSubstitute(MOVE_SCRATCH));
|
||||
PLAYER(SPECIES_DRAGAPULT) { Ability(ability); }
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WYNAUT);
|
||||
} WHEN {
|
||||
TURN { MOVE(playerRight, MOVE_SUBSTITUTE); MOVE(playerLeft, MOVE_SCRATCH, target: playerRight); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_SUBSTITUTE, playerRight);
|
||||
if (ability == ABILITY_INFILTRATOR && config == GEN_6) {
|
||||
NOT SUB_HIT(playerRight);
|
||||
} else {
|
||||
SUB_HIT(playerRight);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Infiltrator doesn't ignore a battler's Substitute when using Transform or Sky Drop")
|
||||
{
|
||||
u32 ability, move;
|
||||
|
||||
PARAMETRIZE { ability = ABILITY_CLEAR_BODY; move = MOVE_TRANSFORM; }
|
||||
PARAMETRIZE { ability = ABILITY_INFILTRATOR; move = MOVE_TRANSFORM; }
|
||||
PARAMETRIZE { ability = ABILITY_CLEAR_BODY; move = MOVE_SKY_DROP; }
|
||||
PARAMETRIZE { ability = ABILITY_INFILTRATOR; move = MOVE_SKY_DROP; }
|
||||
|
||||
GIVEN {
|
||||
WITH_CONFIG(B_INFILTRATOR_SUBSTITUTE, GEN_6);
|
||||
ASSUME(GetMoveEffect(MOVE_SUBSTITUTE) == EFFECT_SUBSTITUTE);
|
||||
ASSUME(GetMoveEffect(MOVE_TRANSFORM) == EFFECT_TRANSFORM);
|
||||
ASSUME(GetMoveEffect(MOVE_SKY_DROP) == EFFECT_SKY_DROP);
|
||||
PLAYER(SPECIES_DRAGAPULT) { Ability(ability); }
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN { MOVE(opponent, MOVE_SUBSTITUTE); MOVE(player, move); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_SUBSTITUTE, opponent);
|
||||
NOT ANIMATION(ANIM_TYPE_MOVE, move, player);
|
||||
}
|
||||
}
|
||||
|
||||
@ -7,7 +7,7 @@ SINGLE_BATTLE_TEST("Inner Focus doesn't prevent intimidate (Gen3-7)")
|
||||
s16 turnTwoHit;
|
||||
|
||||
GIVEN {
|
||||
WITH_CONFIG(CONFIG_UPDATED_INTIMIDATE, GEN_7);
|
||||
WITH_CONFIG(B_UPDATED_INTIMIDATE, GEN_7);
|
||||
PLAYER(SPECIES_EKANS) { Ability(ABILITY_SHED_SKIN); }
|
||||
PLAYER(SPECIES_EKANS) { Ability(ABILITY_INTIMIDATE); }
|
||||
OPPONENT(SPECIES_ZUBAT) { Ability(ABILITY_INNER_FOCUS); }
|
||||
@ -34,7 +34,7 @@ SINGLE_BATTLE_TEST("Inner Focus prevents intimidate (Gen8+)")
|
||||
s16 turnTwoHit;
|
||||
|
||||
GIVEN {
|
||||
WITH_CONFIG(CONFIG_UPDATED_INTIMIDATE, GEN_8);
|
||||
WITH_CONFIG(B_UPDATED_INTIMIDATE, GEN_8);
|
||||
PLAYER(SPECIES_EKANS) { Ability(ABILITY_SHED_SKIN); }
|
||||
PLAYER(SPECIES_EKANS) { Ability(ABILITY_INTIMIDATE); }
|
||||
OPPONENT(SPECIES_ZUBAT) { Ability(ABILITY_INNER_FOCUS); }
|
||||
|
||||
@ -20,7 +20,7 @@ SINGLE_BATTLE_TEST("Intrepid Sword raises Attack by one stage")
|
||||
SINGLE_BATTLE_TEST("Intrepid Sword raises Attack by one stage every time it switches in (Gen8)")
|
||||
{
|
||||
GIVEN {
|
||||
WITH_CONFIG(CONFIG_INTREPID_SWORD, GEN_8);
|
||||
WITH_CONFIG(B_INTREPID_SWORD, GEN_8);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_ZACIAN) { Ability(ABILITY_INTREPID_SWORD); }
|
||||
OPPONENT(SPECIES_WYNAUT);
|
||||
@ -42,7 +42,7 @@ SINGLE_BATTLE_TEST("Intrepid Sword raises Attack by one stage every time it swit
|
||||
SINGLE_BATTLE_TEST("Intrepid Sword raises Attack by one stage only once per battle (Gen9+)")
|
||||
{
|
||||
GIVEN {
|
||||
WITH_CONFIG(CONFIG_INTREPID_SWORD, GEN_9);
|
||||
WITH_CONFIG(B_INTREPID_SWORD, GEN_9);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_ZACIAN) { Ability(ABILITY_INTREPID_SWORD); }
|
||||
OPPONENT(SPECIES_WYNAUT);
|
||||
|
||||
@ -18,7 +18,7 @@ SINGLE_BATTLE_TEST("Keen Eye, Gen9+ Illuminate & Minds Eye prevent accuracy stag
|
||||
|
||||
PASSES_RANDOMLY(100, 100, RNG_ACCURACY);
|
||||
GIVEN {
|
||||
WITH_CONFIG(CONFIG_ILLUMINATE_EFFECT, GEN_9);
|
||||
WITH_CONFIG(B_ILLUMINATE_EFFECT, GEN_9);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(species) { Ability(ability); }
|
||||
} WHEN {
|
||||
@ -47,7 +47,7 @@ SINGLE_BATTLE_TEST("Keen Eye, Gen9+ Illuminate & Minds Eye ignore target's evasi
|
||||
|
||||
PASSES_RANDOMLY(100, 100, RNG_ACCURACY);
|
||||
GIVEN {
|
||||
WITH_CONFIG(CONFIG_ILLUMINATE_EFFECT, GEN_9);
|
||||
WITH_CONFIG(B_ILLUMINATE_EFFECT, GEN_9);
|
||||
ASSUME(GetMoveEffect(MOVE_DOUBLE_TEAM) == EFFECT_EVASION_UP);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(species) { Ability(ability); }
|
||||
@ -81,7 +81,7 @@ SINGLE_BATTLE_TEST("Keen Eye, Gen9+ Illuminate & Minds Eye are ignored by Mold B
|
||||
|
||||
PASSES_RANDOMLY(GetMoveAccuracy(MOVE_SCRATCH) * 3 / 4, 100, RNG_ACCURACY);
|
||||
GIVEN {
|
||||
WITH_CONFIG(CONFIG_ILLUMINATE_EFFECT, GEN_9);
|
||||
WITH_CONFIG(B_ILLUMINATE_EFFECT, GEN_9);
|
||||
PLAYER(speciesPlayer) { Ability(abilityPlayer); }
|
||||
OPPONENT(speciesOpponent) { Ability(abilityOpponent); }
|
||||
} WHEN {
|
||||
@ -104,7 +104,7 @@ SINGLE_BATTLE_TEST("Keen Eye, Gen9+ Illuminate & Minds Eye don't prevent Topsy-T
|
||||
PARAMETRIZE { species = SPECIES_URSALUNA_BLOODMOON; ability = ABILITY_MINDS_EYE; }
|
||||
|
||||
GIVEN {
|
||||
WITH_CONFIG(CONFIG_ILLUMINATE_EFFECT, GEN_9);
|
||||
WITH_CONFIG(B_ILLUMINATE_EFFECT, GEN_9);
|
||||
ASSUME(GetMoveEffect(MOVE_HONE_CLAWS) == EFFECT_ATTACK_ACCURACY_UP);
|
||||
ASSUME(GetMoveEffect(MOVE_TOPSY_TURVY) == EFFECT_TOPSY_TURVY);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
@ -144,7 +144,7 @@ SINGLE_BATTLE_TEST("Keen Eye, Gen9+ Illuminate & Minds Eye don't prevent receivi
|
||||
PARAMETRIZE { species = SPECIES_URSALUNA_BLOODMOON; ability = ABILITY_MINDS_EYE; }
|
||||
|
||||
GIVEN {
|
||||
WITH_CONFIG(CONFIG_ILLUMINATE_EFFECT, GEN_9);
|
||||
WITH_CONFIG(B_ILLUMINATE_EFFECT, GEN_9);
|
||||
ASSUME(GetMoveEffect(MOVE_BATON_PASS) == EFFECT_BATON_PASS);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
@ -177,7 +177,7 @@ SINGLE_BATTLE_TEST("Keen Eye & Gen9+ Illuminate don't prevent Spectral Thief fro
|
||||
PARAMETRIZE { species = SPECIES_STARYU; ability = ABILITY_ILLUMINATE; }
|
||||
|
||||
GIVEN {
|
||||
WITH_CONFIG(CONFIG_ILLUMINATE_EFFECT, GEN_9);
|
||||
WITH_CONFIG(B_ILLUMINATE_EFFECT, GEN_9);
|
||||
ASSUME(GetMoveEffect(MOVE_HONE_CLAWS) == EFFECT_ATTACK_ACCURACY_UP);
|
||||
ASSUME(GetMoveEffect(MOVE_SPECTRAL_THIEF) == EFFECT_SPECTRAL_THIEF);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
|
||||
@ -121,7 +121,7 @@ SINGLE_BATTLE_TEST("Leaf Guard prevents Rest during sun (Gen 5+)")
|
||||
PARAMETRIZE { gen = GEN_4; }
|
||||
PARAMETRIZE { gen = GEN_5; }
|
||||
GIVEN {
|
||||
WITH_CONFIG(CONFIG_LEAF_GUARD_PREVENTS_REST, gen);
|
||||
WITH_CONFIG(B_LEAF_GUARD_PREVENTS_REST, gen);
|
||||
ASSUME(GetMoveEffect(MOVE_REST) == EFFECT_REST);
|
||||
PLAYER(SPECIES_LEAFEON) { Ability(ABILITY_LEAF_GUARD); HP(100); MaxHP(200); }
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
@ -151,7 +151,7 @@ SINGLE_BATTLE_TEST("Leaf Guard doesn't prevent Rest if Cloud Nine/Air Lock is on
|
||||
PARAMETRIZE { species = SPECIES_RAYQUAZA; ability = ABILITY_AIR_LOCK; }
|
||||
PARAMETRIZE { species = SPECIES_RAYQUAZA; ability = ABILITY_AIR_LOCK; }
|
||||
GIVEN {
|
||||
WITH_CONFIG(CONFIG_LEAF_GUARD_PREVENTS_REST, GEN_5);
|
||||
WITH_CONFIG(B_LEAF_GUARD_PREVENTS_REST, GEN_5);
|
||||
ASSUME(GetMoveEffect(MOVE_REST) == EFFECT_REST);
|
||||
PLAYER(SPECIES_LEAFEON) { Ability(ABILITY_LEAF_GUARD); HP(100); MaxHP(200); }
|
||||
OPPONENT(species) { Ability(ability); }
|
||||
|
||||
@ -7,7 +7,7 @@ SINGLE_BATTLE_TEST("Lightning Rod absorbs Electric-type moves and increases the
|
||||
PARAMETRIZE { config = GEN_4; }
|
||||
PARAMETRIZE { config = GEN_5; }
|
||||
GIVEN {
|
||||
WITH_CONFIG(CONFIG_REDIRECT_ABILITY_IMMUNITY, config);
|
||||
WITH_CONFIG(B_REDIRECT_ABILITY_IMMUNITY, config);
|
||||
ASSUME(GetMoveType(MOVE_THUNDERBOLT) == TYPE_ELECTRIC);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_RAICHU) { Ability(ABILITY_LIGHTNING_ROD); }
|
||||
@ -47,7 +47,7 @@ DOUBLE_BATTLE_TEST("Lightning Rod forces single-target Electric-type moves to ta
|
||||
PARAMETRIZE { config = GEN_4; }
|
||||
PARAMETRIZE { config = GEN_5; }
|
||||
GIVEN {
|
||||
WITH_CONFIG(CONFIG_REDIRECT_ABILITY_IMMUNITY, config);
|
||||
WITH_CONFIG(B_REDIRECT_ABILITY_IMMUNITY, config);
|
||||
ASSUME(GetMoveType(MOVE_THUNDERBOLT) == TYPE_ELECTRIC);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
@ -115,7 +115,7 @@ DOUBLE_BATTLE_TEST("Lightning Rod redirects an ally's attack")
|
||||
DOUBLE_BATTLE_TEST("Lightning Rod absorbs moves that targets all battlers but does not redirect (Gen6+)")
|
||||
{
|
||||
GIVEN {
|
||||
WITH_CONFIG(CONFIG_REDIRECT_ABILITY_IMMUNITY, GEN_5);
|
||||
WITH_CONFIG(B_REDIRECT_ABILITY_IMMUNITY, GEN_5);
|
||||
ASSUME(GetMoveType(MOVE_DISCHARGE) == TYPE_ELECTRIC);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
|
||||
@ -142,7 +142,7 @@ SINGLE_BATTLE_TEST("Liquid Ooze causes Dream Eater users to lose HP instead of h
|
||||
{
|
||||
s16 damage;
|
||||
GIVEN {
|
||||
WITH_CONFIG(CONFIG_DREAM_EATER_LIQUID_OOZE, GEN_5);
|
||||
WITH_CONFIG(B_DREAM_EATER_LIQUID_OOZE, GEN_5);
|
||||
ASSUME(GetMoveEffect(MOVE_SPORE) == EFFECT_NON_VOLATILE_STATUS);
|
||||
ASSUME(GetMoveNonVolatileStatus(MOVE_SPORE) == MOVE_EFFECT_SLEEP);
|
||||
ASSUME(GetMoveEffect(MOVE_DREAM_EATER) == EFFECT_DREAM_EATER);
|
||||
@ -167,7 +167,7 @@ SINGLE_BATTLE_TEST("Liquid Ooze does not cause Dream Eater users to lose HP inst
|
||||
{
|
||||
s16 damage;
|
||||
GIVEN {
|
||||
WITH_CONFIG(CONFIG_DREAM_EATER_LIQUID_OOZE, GEN_3);
|
||||
WITH_CONFIG(B_DREAM_EATER_LIQUID_OOZE, GEN_3);
|
||||
ASSUME(GetMoveEffect(MOVE_SPORE) == EFFECT_NON_VOLATILE_STATUS);
|
||||
ASSUME(GetMoveNonVolatileStatus(MOVE_SPORE) == MOVE_EFFECT_SLEEP);
|
||||
ASSUME(GetMoveEffect(MOVE_DREAM_EATER) == EFFECT_DREAM_EATER);
|
||||
|
||||
@ -42,7 +42,7 @@ SINGLE_BATTLE_TEST("Magic Bounce bounces back powder moves")
|
||||
SINGLE_BATTLE_TEST("Magic Bounce cannot bounce back powder moves against Grass Types")
|
||||
{
|
||||
GIVEN {
|
||||
WITH_CONFIG(CONFIG_POWDER_GRASS, GEN_6);
|
||||
WITH_CONFIG(B_POWDER_GRASS, GEN_6);
|
||||
ASSUME(IsPowderMove(MOVE_STUN_SPORE));
|
||||
ASSUME(GetSpeciesType(SPECIES_ODDISH, 0) == TYPE_GRASS);
|
||||
PLAYER(SPECIES_ODDISH);
|
||||
|
||||
@ -11,7 +11,7 @@ SINGLE_BATTLE_TEST("Moody randomly raises the user's Attack, Defense, Sp. Atk, S
|
||||
// HP is not included
|
||||
PASSES_RANDOMLY(1, statsNum - 1, RNG_MOODY_INCREASE);
|
||||
GIVEN {
|
||||
WITH_CONFIG(CONFIG_MOODY_ACC_EVASION, config);
|
||||
WITH_CONFIG(B_MOODY_ACC_EVASION, config);
|
||||
PLAYER(SPECIES_OCTILLERY) { Ability(ABILITY_MOODY); }
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
@ -36,7 +36,7 @@ SINGLE_BATTLE_TEST("Moody randomly lowers the user's Attack, Defense, Sp. Atk, S
|
||||
// One stat becomes unavailable due to it already increasing
|
||||
PASSES_RANDOMLY(1, statsNum - 2, RNG_MOODY_DECREASE);
|
||||
GIVEN {
|
||||
WITH_CONFIG(CONFIG_MOODY_ACC_EVASION, config);
|
||||
WITH_CONFIG(B_MOODY_ACC_EVASION, config);
|
||||
PLAYER(SPECIES_OCTILLERY) { Ability(ABILITY_MOODY); }
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
@ -60,7 +60,7 @@ SINGLE_BATTLE_TEST("Moody randomly raises the holder's Attack, Defense, Sp. Atk,
|
||||
|
||||
PASSES_RANDOMLY(statsNum - 1, statsNum - 1, RNG_MOODY_DECREASE);
|
||||
GIVEN {
|
||||
WITH_CONFIG(CONFIG_MOODY_ACC_EVASION, config);
|
||||
WITH_CONFIG(B_MOODY_ACC_EVASION, config);
|
||||
PLAYER(SPECIES_OCTILLERY) { Ability(ABILITY_MOODY); }
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
|
||||
@ -87,7 +87,7 @@ SINGLE_BATTLE_TEST("Normalize doesn't boost power of unaffected moves by 20% (<
|
||||
PARAMETRIZE { ability = ABILITY_NORMALIZE; }
|
||||
|
||||
GIVEN {
|
||||
WITH_CONFIG(CONFIG_ATE_MULTIPLIER, GEN_6);
|
||||
WITH_CONFIG(B_ATE_MULTIPLIER, GEN_6);
|
||||
PLAYER(SPECIES_DELCATTY) { Ability(ability); }
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
@ -106,7 +106,7 @@ SINGLE_BATTLE_TEST("Normalize boosts power of unaffected moves by 20% (Gen7+)",
|
||||
PARAMETRIZE { ability = ABILITY_NORMALIZE; }
|
||||
|
||||
GIVEN {
|
||||
WITH_CONFIG(CONFIG_ATE_MULTIPLIER, GEN_7);
|
||||
WITH_CONFIG(B_ATE_MULTIPLIER, GEN_7);
|
||||
PLAYER(SPECIES_DELCATTY) { Ability(ability); }
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
@ -125,7 +125,7 @@ SINGLE_BATTLE_TEST("Normalize doesn't boost power of affected moves by 20% (< Ge
|
||||
PARAMETRIZE { ability = ABILITY_NORMALIZE; }
|
||||
|
||||
GIVEN {
|
||||
WITH_CONFIG(CONFIG_ATE_MULTIPLIER, GEN_6);
|
||||
WITH_CONFIG(B_ATE_MULTIPLIER, GEN_6);
|
||||
PLAYER(SPECIES_SKITTY) { Ability(ability); Moves(MOVE_WATER_GUN); }
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
@ -144,7 +144,7 @@ SINGLE_BATTLE_TEST("Normalize boosts power of affected moves by 20% (Gen7+)", s1
|
||||
PARAMETRIZE { ability = ABILITY_NORMALIZE; }
|
||||
|
||||
GIVEN {
|
||||
WITH_CONFIG(CONFIG_ATE_MULTIPLIER, GEN_7);
|
||||
WITH_CONFIG(B_ATE_MULTIPLIER, GEN_7);
|
||||
PLAYER(SPECIES_SKITTY) { Ability(ability); Moves(MOVE_WATER_GUN); }
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
|
||||
@ -37,7 +37,7 @@ SINGLE_BATTLE_TEST("Oblivious prevents Taunt (Gen6+)")
|
||||
PARAMETRIZE { gen = GEN_5; }
|
||||
PARAMETRIZE { gen = GEN_6; }
|
||||
GIVEN {
|
||||
WITH_CONFIG(CONFIG_OBLIVIOUS_TAUNT, gen);
|
||||
WITH_CONFIG(B_OBLIVIOUS_TAUNT, gen);
|
||||
ASSUME(GetMoveEffect(MOVE_TAUNT) == EFFECT_TAUNT);
|
||||
PLAYER(SPECIES_SLOWPOKE) { Ability(ABILITY_OBLIVIOUS); }
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
@ -66,7 +66,7 @@ SINGLE_BATTLE_TEST("Oblivious prevents Taunt (Gen6+)")
|
||||
SINGLE_BATTLE_TEST("Oblivious doesn't prevent Intimidate (Gen3-7)")
|
||||
{
|
||||
GIVEN {
|
||||
WITH_CONFIG(CONFIG_UPDATED_INTIMIDATE, GEN_7);
|
||||
WITH_CONFIG(B_UPDATED_INTIMIDATE, GEN_7);
|
||||
PLAYER(SPECIES_SLOWPOKE) { Ability(ABILITY_OBLIVIOUS); }
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_EKANS) { Ability(ABILITY_INTIMIDATE); }
|
||||
@ -86,7 +86,7 @@ SINGLE_BATTLE_TEST("Oblivious doesn't prevent Intimidate (Gen3-7)")
|
||||
SINGLE_BATTLE_TEST("Oblivious prevents Intimidate (Gen8+)")
|
||||
{
|
||||
GIVEN {
|
||||
WITH_CONFIG(CONFIG_UPDATED_INTIMIDATE, GEN_8);
|
||||
WITH_CONFIG(B_UPDATED_INTIMIDATE, GEN_8);
|
||||
PLAYER(SPECIES_SLOWPOKE) { Ability(ABILITY_OBLIVIOUS); }
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_EKANS) { Ability(ABILITY_INTIMIDATE); }
|
||||
|
||||
@ -7,7 +7,7 @@ SINGLE_BATTLE_TEST("Overcoat blocks powder and spore moves (Gen6+)")
|
||||
PARAMETRIZE { gen = GEN_5; }
|
||||
PARAMETRIZE { gen = GEN_6; }
|
||||
GIVEN {
|
||||
WITH_CONFIG(CONFIG_POWDER_OVERCOAT, gen);
|
||||
WITH_CONFIG(B_POWDER_OVERCOAT, gen);
|
||||
ASSUME(IsPowderMove(MOVE_STUN_SPORE));
|
||||
PLAYER(SPECIES_WYNAUT);
|
||||
OPPONENT(SPECIES_PINECO) { Ability(ABILITY_OVERCOAT); }
|
||||
@ -77,7 +77,7 @@ SINGLE_BATTLE_TEST("Overcoat blocks Effect Spore's effect (Gen6+)")
|
||||
PARAMETRIZE { config = GEN_5; }
|
||||
PARAMETRIZE { config = GEN_6; }
|
||||
GIVEN {
|
||||
WITH_CONFIG(CONFIG_POWDER_OVERCOAT, config);
|
||||
WITH_CONFIG(B_POWDER_OVERCOAT, config);
|
||||
PLAYER(SPECIES_PINECO) { Ability(ABILITY_OVERCOAT); }
|
||||
OPPONENT(SPECIES_SHROOMISH) { Ability(ABILITY_EFFECT_SPORE); }
|
||||
} WHEN {
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
SINGLE_BATTLE_TEST("Own Tempo doesn't prevent Intimidate (Gen3-7)")
|
||||
{
|
||||
GIVEN {
|
||||
WITH_CONFIG(CONFIG_UPDATED_INTIMIDATE, GEN_7);
|
||||
WITH_CONFIG(B_UPDATED_INTIMIDATE, GEN_7);
|
||||
ASSUME(GetMoveEffect(MOVE_CONFUSE_RAY) == EFFECT_CONFUSE);
|
||||
PLAYER(SPECIES_EKANS) { Ability(ABILITY_INTIMIDATE); }
|
||||
OPPONENT(SPECIES_SLOWPOKE) { Ability(ABILITY_OWN_TEMPO); }
|
||||
@ -22,7 +22,7 @@ SINGLE_BATTLE_TEST("Own Tempo doesn't prevent Intimidate (Gen3-7)")
|
||||
SINGLE_BATTLE_TEST("Own Tempo prevents Intimidate but no other stat down changes (Gen8+)")
|
||||
{
|
||||
GIVEN {
|
||||
WITH_CONFIG(CONFIG_UPDATED_INTIMIDATE, GEN_8);
|
||||
WITH_CONFIG(B_UPDATED_INTIMIDATE, GEN_8);
|
||||
ASSUME(GetMoveEffect(MOVE_CONFUSE_RAY) == EFFECT_CONFUSE);
|
||||
PLAYER(SPECIES_EKANS) { Ability(ABILITY_INTIMIDATE); }
|
||||
OPPONENT(SPECIES_SLOWPOKE) { Ability(ABILITY_OWN_TEMPO); }
|
||||
|
||||
@ -111,7 +111,7 @@ SINGLE_BATTLE_TEST("Parental Bond-converted moves only hit once on Lightning Rod
|
||||
PARAMETRIZE { move = MOVE_THUNDERBOLT; ability = ABILITY_LIGHTNING_ROD; species = SPECIES_RAICHU; type = TYPE_ELECTRIC; }
|
||||
PARAMETRIZE { move = MOVE_SURF; ability = ABILITY_STORM_DRAIN; species = SPECIES_LILEEP; type = TYPE_WATER; }
|
||||
GIVEN {
|
||||
WITH_CONFIG(CONFIG_REDIRECT_ABILITY_IMMUNITY, GEN_5);
|
||||
WITH_CONFIG(B_REDIRECT_ABILITY_IMMUNITY, GEN_5);
|
||||
ASSUME(GetMoveStrikeCount(move) < 2);
|
||||
ASSUME(GetMoveType(move) == type);
|
||||
PLAYER(SPECIES_KANGASKHAN) { Item(ITEM_KANGASKHANITE); }
|
||||
@ -142,7 +142,7 @@ SINGLE_BATTLE_TEST("Parental Bond has no affect on multi hit moves and they stil
|
||||
PASSES_RANDOMLY(passes, trials, RNG_HITS);
|
||||
|
||||
GIVEN {
|
||||
WITH_CONFIG(CONFIG_MULTI_HIT_CHANCE, genConfig);
|
||||
WITH_CONFIG(B_MULTI_HIT_CHANCE, genConfig);
|
||||
ASSUME(GetMoveCategory(MOVE_COMET_PUNCH) != DAMAGE_CATEGORY_STATUS);
|
||||
ASSUME(GetMoveEffect(MOVE_COMET_PUNCH) == EFFECT_MULTI_HIT);
|
||||
PLAYER(SPECIES_KANGASKHAN) { Item(ITEM_KANGASKHANITE); }
|
||||
@ -171,7 +171,7 @@ SINGLE_BATTLE_TEST("Parental Bond has no affect on multi hit moves and they stil
|
||||
PASSES_RANDOMLY(passes, trials, RNG_HITS);
|
||||
|
||||
GIVEN {
|
||||
WITH_CONFIG(CONFIG_MULTI_HIT_CHANCE, genConfig);
|
||||
WITH_CONFIG(B_MULTI_HIT_CHANCE, genConfig);
|
||||
ASSUME(GetMoveCategory(MOVE_COMET_PUNCH) != DAMAGE_CATEGORY_STATUS);
|
||||
ASSUME(GetMoveEffect(MOVE_COMET_PUNCH) == EFFECT_MULTI_HIT);
|
||||
PLAYER(SPECIES_KANGASKHAN) { Item(ITEM_KANGASKHANITE); }
|
||||
@ -201,7 +201,7 @@ SINGLE_BATTLE_TEST("Parental Bond has no affect on multi hit moves and they stil
|
||||
PASSES_RANDOMLY(passes, trials, RNG_HITS);
|
||||
|
||||
GIVEN {
|
||||
WITH_CONFIG(CONFIG_MULTI_HIT_CHANCE, genConfig);
|
||||
WITH_CONFIG(B_MULTI_HIT_CHANCE, genConfig);
|
||||
ASSUME(GetMoveCategory(MOVE_COMET_PUNCH) != DAMAGE_CATEGORY_STATUS);
|
||||
ASSUME(GetMoveEffect(MOVE_COMET_PUNCH) == EFFECT_MULTI_HIT);
|
||||
PLAYER(SPECIES_KANGASKHAN) { Item(ITEM_KANGASKHANITE); }
|
||||
@ -232,7 +232,7 @@ SINGLE_BATTLE_TEST("Parental Bond has no affect on multi hit moves and they stil
|
||||
PASSES_RANDOMLY(passes, trials, RNG_HITS);
|
||||
|
||||
GIVEN {
|
||||
WITH_CONFIG(CONFIG_MULTI_HIT_CHANCE, genConfig);
|
||||
WITH_CONFIG(B_MULTI_HIT_CHANCE, genConfig);
|
||||
ASSUME(GetMoveCategory(MOVE_COMET_PUNCH) != DAMAGE_CATEGORY_STATUS);
|
||||
ASSUME(GetMoveEffect(MOVE_COMET_PUNCH) == EFFECT_MULTI_HIT);
|
||||
PLAYER(SPECIES_KANGASKHAN) { Item(ITEM_KANGASKHANITE); }
|
||||
|
||||
@ -1,4 +1,312 @@
|
||||
#include "global.h"
|
||||
#include "test/battle.h"
|
||||
|
||||
TO_DO_BATTLE_TEST("TODO: Write Pickpocket (Ability) test titles")
|
||||
ASSUMPTIONS
|
||||
{
|
||||
ASSUME(MoveMakesContact(MOVE_BREAKING_SWIPE));
|
||||
ASSUME(MoveMakesContact(MOVE_SCRATCH));
|
||||
}
|
||||
|
||||
DOUBLE_BATTLE_TEST("Pickpocket checks contact/effect per target for spread moves")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(GetSpeciesType(SPECIES_CLEFAIRY, 0) == TYPE_FAIRY);
|
||||
ASSUME(GetMoveType(MOVE_BREAKING_SWIPE) == TYPE_DRAGON);
|
||||
ASSUME(GetMoveTarget(MOVE_BREAKING_SWIPE) == MOVE_TARGET_BOTH);
|
||||
PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_MAGOST_BERRY); }
|
||||
PLAYER(SPECIES_WYNAUT);
|
||||
OPPONENT(SPECIES_SNEASEL) { Ability(ABILITY_PICKPOCKET); }
|
||||
OPPONENT(SPECIES_CLEFAIRY);
|
||||
} WHEN {
|
||||
TURN { MOVE(playerLeft, MOVE_BREAKING_SWIPE); }
|
||||
} SCENE {
|
||||
ABILITY_POPUP(opponentLeft, ABILITY_PICKPOCKET);
|
||||
MESSAGE("The opposing Sneasel stole Wobbuffet's Magost Berry!");
|
||||
} THEN {
|
||||
EXPECT(opponentLeft->item == ITEM_MAGOST_BERRY);
|
||||
EXPECT(playerLeft->item == ITEM_NONE);
|
||||
}
|
||||
}
|
||||
|
||||
DOUBLE_BATTLE_TEST("Pickpocket activates for the fastest itemless target when both are hit by a contact spread move")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(GetMoveTarget(MOVE_BREAKING_SWIPE) == MOVE_TARGET_BOTH);
|
||||
PLAYER(SPECIES_WOBBUFFET) { Speed(20); Item(ITEM_MAGOST_BERRY); }
|
||||
PLAYER(SPECIES_WYNAUT) { Speed(10); }
|
||||
OPPONENT(SPECIES_SNEASEL) { Speed(40); Ability(ABILITY_PICKPOCKET); }
|
||||
OPPONENT(SPECIES_SNEASEL) { Speed(30); Ability(ABILITY_PICKPOCKET); }
|
||||
} WHEN {
|
||||
TURN { MOVE(playerLeft, MOVE_BREAKING_SWIPE); }
|
||||
} SCENE {
|
||||
ABILITY_POPUP(opponentLeft, ABILITY_PICKPOCKET);
|
||||
MESSAGE("The opposing Sneasel stole Wobbuffet's Magost Berry!");
|
||||
} THEN {
|
||||
EXPECT(opponentLeft->item == ITEM_MAGOST_BERRY);
|
||||
EXPECT(opponentRight->item == ITEM_NONE);
|
||||
EXPECT(playerLeft->item == ITEM_NONE);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Pickpocket steals the attacker's item unless it already has one")
|
||||
{
|
||||
bool32 targetHasItem;
|
||||
PARAMETRIZE { targetHasItem = FALSE; }
|
||||
PARAMETRIZE { targetHasItem = TRUE; }
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_MAGOST_BERRY); }
|
||||
OPPONENT(SPECIES_SNEASEL) { Ability(ABILITY_PICKPOCKET); Item(targetHasItem ? ITEM_EVIOLITE : ITEM_NONE); }
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_SCRATCH); }
|
||||
} SCENE {
|
||||
if (targetHasItem) {
|
||||
NONE_OF {
|
||||
ABILITY_POPUP(opponent, ABILITY_PICKPOCKET);
|
||||
MESSAGE("The opposing Sneasel stole Wobbuffet's Magost Berry!");
|
||||
}
|
||||
} else {
|
||||
ABILITY_POPUP(opponent, ABILITY_PICKPOCKET);
|
||||
MESSAGE("The opposing Sneasel stole Wobbuffet's Magost Berry!");
|
||||
}
|
||||
} THEN {
|
||||
if (targetHasItem) {
|
||||
EXPECT(opponent->item == ITEM_EVIOLITE);
|
||||
EXPECT(player->item == ITEM_MAGOST_BERRY);
|
||||
} else {
|
||||
EXPECT(opponent->item == ITEM_MAGOST_BERRY);
|
||||
EXPECT(player->item == ITEM_NONE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Pickpocket does not activate if the user faints")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_MAGOST_BERRY); }
|
||||
OPPONENT(SPECIES_SNEASEL) { Ability(ABILITY_PICKPOCKET); HP(1); }
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_SCRATCH); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_SCRATCH, player);
|
||||
NONE_OF {
|
||||
ABILITY_POPUP(opponent, ABILITY_PICKPOCKET);
|
||||
MESSAGE("The opposing Sneasel stole Wobbuffet's Magost Berry!");
|
||||
}
|
||||
MESSAGE("The opposing Sneasel fainted!");
|
||||
} THEN {
|
||||
EXPECT(opponent->item == ITEM_NONE);
|
||||
EXPECT(player->item == ITEM_MAGOST_BERRY);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Pickpocket cannot steal from Sticky Hold")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_GRIMER) { Ability(ABILITY_STICKY_HOLD); Item(ITEM_MAGOST_BERRY); }
|
||||
OPPONENT(SPECIES_SNEASEL) { Ability(ABILITY_PICKPOCKET); }
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_SCRATCH); }
|
||||
} SCENE {
|
||||
ABILITY_POPUP(opponent, ABILITY_PICKPOCKET);
|
||||
ABILITY_POPUP(player, ABILITY_STICKY_HOLD);
|
||||
MESSAGE("Grimer's item cannot be removed!");
|
||||
} THEN {
|
||||
EXPECT(opponent->item == ITEM_NONE);
|
||||
EXPECT(player->item == ITEM_MAGOST_BERRY);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Pickpocket cannot steal restricted held items")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(gItemsInfo[ITEM_NORMALIUM_Z].holdEffect == HOLD_EFFECT_Z_CRYSTAL);
|
||||
PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_NORMALIUM_Z); }
|
||||
OPPONENT(SPECIES_SNEASEL) { Ability(ABILITY_PICKPOCKET); }
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_SCRATCH); }
|
||||
} SCENE {
|
||||
NONE_OF {
|
||||
ABILITY_POPUP(opponent, ABILITY_PICKPOCKET);
|
||||
}
|
||||
} THEN {
|
||||
EXPECT(opponent->item == ITEM_NONE);
|
||||
EXPECT(player->item == ITEM_NORMALIUM_Z);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Pickpocket activates after the final hit of a multi-strike move")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(GetMoveEffect(MOVE_FURY_SWIPES) == EFFECT_MULTI_HIT);
|
||||
ASSUME(MoveMakesContact(MOVE_FURY_SWIPES));
|
||||
PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_MAGOST_BERRY); }
|
||||
OPPONENT(SPECIES_SNEASEL) { Ability(ABILITY_PICKPOCKET); }
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_FURY_SWIPES, WITH_RNG(RNG_HITS, 3)); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_FURY_SWIPES, player);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_FURY_SWIPES, player);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_FURY_SWIPES, player);
|
||||
MESSAGE("The Pokémon was hit 3 time(s)!");
|
||||
ABILITY_POPUP(opponent, ABILITY_PICKPOCKET);
|
||||
MESSAGE("The opposing Sneasel stole Wobbuffet's Magost Berry!");
|
||||
} THEN {
|
||||
EXPECT(opponent->item == ITEM_MAGOST_BERRY);
|
||||
EXPECT(player->item == ITEM_NONE);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Pickpocket activates after Magician steals an item")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_DELPHOX) { Ability(ABILITY_MAGICIAN); }
|
||||
OPPONENT(SPECIES_SNEASEL) { Ability(ABILITY_PICKPOCKET); Item(ITEM_MAGOST_BERRY); }
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_SCRATCH); }
|
||||
} SCENE {
|
||||
ABILITY_POPUP(player, ABILITY_MAGICIAN);
|
||||
MESSAGE("Delphox stole the opposing Sneasel's Magost Berry!");
|
||||
ABILITY_POPUP(opponent, ABILITY_PICKPOCKET);
|
||||
MESSAGE("The opposing Sneasel stole Delphox's Magost Berry!");
|
||||
} THEN {
|
||||
EXPECT(opponent->item == ITEM_MAGOST_BERRY);
|
||||
EXPECT(player->item == ITEM_NONE);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Pickpocket activates after Sticky Barb transfers")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(gItemsInfo[ITEM_STICKY_BARB].holdEffect == HOLD_EFFECT_STICKY_BARB);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_SNEASEL) { Ability(ABILITY_PICKPOCKET); Item(ITEM_STICKY_BARB); }
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_SCRATCH); }
|
||||
} SCENE {
|
||||
MESSAGE("The Sticky Barb attached itself to Wobbuffet!");
|
||||
ABILITY_POPUP(opponent, ABILITY_PICKPOCKET);
|
||||
MESSAGE("The opposing Sneasel stole Wobbuffet's Sticky Barb!");
|
||||
} THEN {
|
||||
EXPECT(opponent->item == ITEM_STICKY_BARB);
|
||||
EXPECT(player->item == ITEM_NONE);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Pickpocket activates after Thief or Covet steals an item")
|
||||
{
|
||||
u16 move;
|
||||
PARAMETRIZE { move = MOVE_THIEF; }
|
||||
PARAMETRIZE { move = MOVE_COVET; }
|
||||
GIVEN {
|
||||
ASSUME(GetMoveEffect(move) == EFFECT_STEAL_ITEM);
|
||||
ASSUME(MoveMakesContact(move));
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_SNEASEL) { Ability(ABILITY_PICKPOCKET); Item(ITEM_MAGOST_BERRY); }
|
||||
} WHEN {
|
||||
TURN { MOVE(player, move); }
|
||||
} SCENE {
|
||||
MESSAGE("Wobbuffet stole the opposing Sneasel's Magost Berry!");
|
||||
ABILITY_POPUP(opponent, ABILITY_PICKPOCKET);
|
||||
MESSAGE("The opposing Sneasel stole Wobbuffet's Magost Berry!");
|
||||
} THEN {
|
||||
EXPECT(opponent->item == ITEM_MAGOST_BERRY);
|
||||
EXPECT(player->item == ITEM_NONE);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Pickpocket activates after Focus Sash is consumed")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(MoveMakesContact(MOVE_SEISMIC_TOSS));
|
||||
ASSUME(gItemsInfo[ITEM_FOCUS_SASH].holdEffect == HOLD_EFFECT_FOCUS_SASH);
|
||||
PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_MAGOST_BERRY); Level(100); }
|
||||
OPPONENT(SPECIES_SNEASEL) { Ability(ABILITY_PICKPOCKET); Item(ITEM_FOCUS_SASH); MaxHP(6); HP(6); }
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_SEISMIC_TOSS); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_SEISMIC_TOSS, player);
|
||||
MESSAGE("The opposing Sneasel hung on using its Focus Sash!");
|
||||
ABILITY_POPUP(opponent, ABILITY_PICKPOCKET);
|
||||
MESSAGE("The opposing Sneasel stole Wobbuffet's Magost Berry!");
|
||||
} THEN {
|
||||
EXPECT(opponent->item == ITEM_MAGOST_BERRY);
|
||||
EXPECT(player->item == ITEM_NONE);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Pickpocket activates after Knock Off, Bug Bite, or Pluck")
|
||||
{
|
||||
u16 move;
|
||||
PARAMETRIZE { move = MOVE_KNOCK_OFF; }
|
||||
PARAMETRIZE { move = MOVE_BUG_BITE; }
|
||||
PARAMETRIZE { move = MOVE_PLUCK; }
|
||||
GIVEN {
|
||||
ASSUME(MoveMakesContact(move));
|
||||
PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_MAGOST_BERRY); }
|
||||
OPPONENT(SPECIES_SNEASEL) { Ability(ABILITY_PICKPOCKET); Item(ITEM_ORAN_BERRY); }
|
||||
} WHEN {
|
||||
TURN { MOVE(player, move); }
|
||||
} SCENE {
|
||||
ABILITY_POPUP(opponent, ABILITY_PICKPOCKET);
|
||||
MESSAGE("The opposing Sneasel stole Wobbuffet's Magost Berry!");
|
||||
} THEN {
|
||||
EXPECT(opponent->item == ITEM_MAGOST_BERRY);
|
||||
EXPECT(player->item == ITEM_NONE);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Pickpocket steals Life Orb after it activates")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(gItemsInfo[ITEM_LIFE_ORB].holdEffect == HOLD_EFFECT_LIFE_ORB);
|
||||
PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_LIFE_ORB); }
|
||||
OPPONENT(SPECIES_SNEASEL) { Ability(ABILITY_PICKPOCKET); }
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_SCRATCH); }
|
||||
} SCENE {
|
||||
MESSAGE("Wobbuffet was hurt by the Life Orb!");
|
||||
ABILITY_POPUP(opponent, ABILITY_PICKPOCKET);
|
||||
MESSAGE("The opposing Sneasel stole Wobbuffet's Life Orb!");
|
||||
} THEN {
|
||||
EXPECT(opponent->item == ITEM_LIFE_ORB);
|
||||
EXPECT(player->item == ITEM_NONE);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Pickpocket steals Shell Bell after it heals the user")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(gItemsInfo[ITEM_SHELL_BELL].holdEffect == HOLD_EFFECT_SHELL_BELL);
|
||||
PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_SHELL_BELL); MaxHP(100); HP(66); }
|
||||
OPPONENT(SPECIES_SNEASEL) { Ability(ABILITY_PICKPOCKET); }
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_SCRATCH); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_SCRATCH, player);
|
||||
HP_BAR(opponent);
|
||||
HP_BAR(player);
|
||||
ABILITY_POPUP(opponent, ABILITY_PICKPOCKET);
|
||||
MESSAGE("The opposing Sneasel stole Wobbuffet's Shell Bell!");
|
||||
} THEN {
|
||||
EXPECT(opponent->item == ITEM_SHELL_BELL);
|
||||
EXPECT(player->item == ITEM_NONE);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Pickpocket does not prevent King's Rock or Razor Fang flinches")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(gItemsInfo[ITEM_KINGS_ROCK].holdEffect == HOLD_EFFECT_FLINCH);
|
||||
PLAYER(SPECIES_WOBBUFFET) { Speed(20); Item(ITEM_KINGS_ROCK); }
|
||||
OPPONENT(SPECIES_SNEASEL) { Speed(10); Ability(ABILITY_PICKPOCKET); }
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_SCRATCH, WITH_RNG(RNG_HOLD_EFFECT_FLINCH, 1)); MOVE(opponent, MOVE_SCRATCH); }
|
||||
} SCENE {
|
||||
ABILITY_POPUP(opponent, ABILITY_PICKPOCKET);
|
||||
MESSAGE("The opposing Sneasel stole Wobbuffet's King's Rock!");
|
||||
MESSAGE("The opposing Sneasel flinched and couldn't move!");
|
||||
} THEN {
|
||||
EXPECT(opponent->item == ITEM_KINGS_ROCK);
|
||||
EXPECT(player->item == ITEM_NONE);
|
||||
}
|
||||
}
|
||||
|
||||
@ -26,7 +26,7 @@ SINGLE_BATTLE_TEST("Pickup grants an item used by another Pokémon")
|
||||
WILD_BATTLE_TEST("Pickup grants an item used by itself in wild battles (Gen9+)")
|
||||
{
|
||||
GIVEN {
|
||||
WITH_CONFIG(CONFIG_PICKUP_WILD, GEN_9);
|
||||
WITH_CONFIG(B_PICKUP_WILD, GEN_9);
|
||||
PLAYER(SPECIES_ZIGZAGOON) { Ability(ABILITY_PICKUP); MaxHP(100); HP(51); Item(ITEM_SITRUS_BERRY); }
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
|
||||
@ -31,7 +31,7 @@ SINGLE_BATTLE_TEST("Pixilate boosts power of affected moves by 20% (Gen7+) or 30
|
||||
PARAMETRIZE { ability = ABILITY_PIXILATE; genConfig = GEN_6; }
|
||||
|
||||
GIVEN {
|
||||
WITH_CONFIG(CONFIG_ATE_MULTIPLIER, genConfig);
|
||||
WITH_CONFIG(B_ATE_MULTIPLIER, genConfig);
|
||||
PLAYER(SPECIES_SYLVEON) { Ability(ability); Moves(MOVE_TACKLE); }
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
|
||||
@ -38,7 +38,7 @@ SINGLE_BATTLE_TEST("Poison Point triggers 1/3 times (Gen3) or 30% (Gen 4+) of th
|
||||
PARAMETRIZE { config = GEN_4; passes = 3; trials = 10; } // 30%
|
||||
PASSES_RANDOMLY(passes, trials, RNG_POISON_POINT);
|
||||
GIVEN {
|
||||
WITH_CONFIG(CONFIG_ABILITY_TRIGGER_CHANCE, config);
|
||||
WITH_CONFIG(B_ABILITY_TRIGGER_CHANCE, config);
|
||||
ASSUME(MoveMakesContact(MOVE_SCRATCH));
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_NIDORAN_M) { Ability(ABILITY_POISON_POINT); }
|
||||
|
||||
@ -13,7 +13,7 @@ SINGLE_BATTLE_TEST("Prankster-affected moves don't affect Dark-type Pokémon (Ge
|
||||
PARAMETRIZE { gen = GEN_6; }
|
||||
PARAMETRIZE { gen = GEN_7; }
|
||||
GIVEN {
|
||||
WITH_CONFIG(CONFIG_PRANKSTER_DARK_TYPES, gen);
|
||||
WITH_CONFIG(B_PRANKSTER_DARK_TYPES, gen);
|
||||
PLAYER(SPECIES_UMBREON);
|
||||
OPPONENT(SPECIES_VOLBEAT) { Ability(ABILITY_PRANKSTER); }
|
||||
} WHEN {
|
||||
@ -31,7 +31,7 @@ SINGLE_BATTLE_TEST("Prankster-affected moves don't affect Dark-type Pokémon (Ge
|
||||
SINGLE_BATTLE_TEST("Prankster-affected moves don't affect Dark-type Pokémon after they switch-in")
|
||||
{
|
||||
GIVEN {
|
||||
WITH_CONFIG(CONFIG_PRANKSTER_DARK_TYPES, GEN_7);
|
||||
WITH_CONFIG(B_PRANKSTER_DARK_TYPES, GEN_7);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
PLAYER(SPECIES_UMBREON);
|
||||
OPPONENT(SPECIES_VOLBEAT) { Ability(ABILITY_PRANKSTER); }
|
||||
@ -64,7 +64,7 @@ SINGLE_BATTLE_TEST("Prankster-affected moves called via Assist don't affect Dark
|
||||
PARAMETRIZE { gen = GEN_6; }
|
||||
PARAMETRIZE { gen = GEN_7; }
|
||||
GIVEN {
|
||||
WITH_CONFIG(CONFIG_PRANKSTER_DARK_TYPES, gen);
|
||||
WITH_CONFIG(B_PRANKSTER_DARK_TYPES, gen);
|
||||
PLAYER(SPECIES_UMBREON);
|
||||
OPPONENT(SPECIES_VOLBEAT) { Ability(ABILITY_PRANKSTER); }
|
||||
OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_CONFUSE_RAY); }
|
||||
@ -87,7 +87,7 @@ DOUBLE_BATTLE_TEST("Prankster-affected moves called via Instruct do not affect D
|
||||
PARAMETRIZE { gen = GEN_6; }
|
||||
PARAMETRIZE { gen = GEN_7; }
|
||||
GIVEN {
|
||||
WITH_CONFIG(CONFIG_PRANKSTER_DARK_TYPES, gen);
|
||||
WITH_CONFIG(B_PRANKSTER_DARK_TYPES, gen);
|
||||
PLAYER(SPECIES_VOLBEAT) { Speed(20); Ability(ABILITY_PRANKSTER); }
|
||||
PLAYER(SPECIES_WOBBUFFET) { Speed(10); }
|
||||
OPPONENT(SPECIES_UMBREON) { Speed(15); }
|
||||
@ -203,7 +203,7 @@ SINGLE_BATTLE_TEST("Prankster-affected moves which are reflected by Magic Coat c
|
||||
PARAMETRIZE { sableyeAbility = ABILITY_KEEN_EYE; }
|
||||
|
||||
GIVEN {
|
||||
WITH_CONFIG(CONFIG_PRANKSTER_DARK_TYPES, GEN_7);
|
||||
WITH_CONFIG(B_PRANKSTER_DARK_TYPES, GEN_7);
|
||||
PLAYER(SPECIES_SABLEYE) { Ability(sableyeAbility); }
|
||||
OPPONENT(SPECIES_MURKROW) { Ability(ABILITY_PRANKSTER); }
|
||||
} WHEN {
|
||||
|
||||
@ -7,7 +7,7 @@ SINGLE_BATTLE_TEST("Protean/Libero changes the type of the user to the move used
|
||||
PARAMETRIZE { ability = ABILITY_PROTEAN; species = SPECIES_KECLEON; }
|
||||
PARAMETRIZE { ability = ABILITY_LIBERO; species = SPECIES_RABOOT; }
|
||||
GIVEN {
|
||||
WITH_CONFIG(CONFIG_PROTEAN_LIBERO, GEN_6);
|
||||
WITH_CONFIG(B_PROTEAN_LIBERO, GEN_6);
|
||||
PLAYER(SPECIES_REGIROCK);
|
||||
OPPONENT(species) { Ability(ability); }
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
@ -45,7 +45,7 @@ SINGLE_BATTLE_TEST("Protean/Libero changes the type of the user only once per sw
|
||||
PARAMETRIZE { ability = ABILITY_PROTEAN; species = SPECIES_KECLEON; }
|
||||
PARAMETRIZE { ability = ABILITY_LIBERO; species = SPECIES_RABOOT; }
|
||||
GIVEN {
|
||||
WITH_CONFIG(CONFIG_PROTEAN_LIBERO, GEN_9);
|
||||
WITH_CONFIG(B_PROTEAN_LIBERO, GEN_9);
|
||||
PLAYER(SPECIES_REGIROCK);
|
||||
OPPONENT(species) { Ability(ability); }
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
|
||||
@ -59,7 +59,7 @@ SINGLE_BATTLE_TEST("Protosynthesis ability pop up activates only once during the
|
||||
u16 turns;
|
||||
|
||||
GIVEN {
|
||||
WITH_CONFIG(CONFIG_ABILITY_WEATHER, GEN_6);
|
||||
WITH_CONFIG(B_ABILITY_WEATHER, GEN_6);
|
||||
PLAYER(SPECIES_WALKING_WAKE) { Ability(ABILITY_PROTOSYNTHESIS); }
|
||||
OPPONENT(SPECIES_NINETALES) { Ability(ABILITY_DROUGHT); }
|
||||
} WHEN {
|
||||
|
||||
@ -55,7 +55,7 @@ SINGLE_BATTLE_TEST("Rattled boosts speed by 1 when hit by Bug, Dark or Ghost typ
|
||||
SINGLE_BATTLE_TEST("Rattled does not boost speed by 1 when affected by Intimidate (Gen5-7)")
|
||||
{
|
||||
GIVEN {
|
||||
WITH_CONFIG(CONFIG_UPDATED_INTIMIDATE, GEN_7);
|
||||
WITH_CONFIG(B_UPDATED_INTIMIDATE, GEN_7);
|
||||
PLAYER(SPECIES_GYARADOS) { Ability(ABILITY_INTIMIDATE); }
|
||||
OPPONENT(SPECIES_SUDOWOODO) { Ability(ABILITY_RATTLED); }
|
||||
} WHEN {
|
||||
@ -75,7 +75,7 @@ SINGLE_BATTLE_TEST("Rattled does not boost speed by 1 when affected by Intimidat
|
||||
SINGLE_BATTLE_TEST("Rattled boosts speed by 1 when affected by Intimidate (Gen8+)")
|
||||
{
|
||||
GIVEN {
|
||||
WITH_CONFIG(CONFIG_UPDATED_INTIMIDATE, GEN_8);
|
||||
WITH_CONFIG(B_UPDATED_INTIMIDATE, GEN_8);
|
||||
PLAYER(SPECIES_GYARADOS) { Ability(ABILITY_INTIMIDATE); }
|
||||
OPPONENT(SPECIES_SUDOWOODO) { Ability(ABILITY_RATTLED); }
|
||||
} WHEN {
|
||||
|
||||
@ -30,7 +30,7 @@ SINGLE_BATTLE_TEST("Refrigerate boosts power of affected moves by 20% (Gen7+) or
|
||||
PARAMETRIZE { ability = ABILITY_REFRIGERATE; genConfig = GEN_6; }
|
||||
|
||||
GIVEN {
|
||||
WITH_CONFIG(CONFIG_ATE_MULTIPLIER, genConfig);
|
||||
WITH_CONFIG(B_ATE_MULTIPLIER, genConfig);
|
||||
PLAYER(SPECIES_AMAURA) { Ability(ability); Moves(MOVE_TACKLE); }
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
@ -54,7 +54,7 @@ SINGLE_BATTLE_TEST("Refrigerate doesn't affect Weather Ball's type", s16 damage)
|
||||
PARAMETRIZE { move = MOVE_CELEBRATE; ability = ABILITY_REFRIGERATE; }
|
||||
PARAMETRIZE { move = MOVE_SUNNY_DAY; ability = ABILITY_REFRIGERATE; }
|
||||
GIVEN {
|
||||
WITH_CONFIG(CONFIG_SNOW_WARNING, GEN_9); //To prevent capturing hail damage
|
||||
WITH_CONFIG(B_SNOW_WARNING, GEN_9); //To prevent capturing hail damage
|
||||
ASSUME(GetMoveEffect(MOVE_WEATHER_BALL) == EFFECT_WEATHER_BALL);
|
||||
ASSUME(GetSpeciesType(SPECIES_PINSIR, 0) == TYPE_BUG);
|
||||
PLAYER(SPECIES_AMAURA) { Ability(ability); }
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
SINGLE_BATTLE_TEST("Sand Stream sets up sandstorm for 5 turns (Gen6+)")
|
||||
{
|
||||
GIVEN {
|
||||
WITH_CONFIG(CONFIG_ABILITY_WEATHER, GEN_6);
|
||||
WITH_CONFIG(B_ABILITY_WEATHER, GEN_6);
|
||||
PLAYER(SPECIES_HIPPOWDON) { Moves(MOVE_CELEBRATE); Ability(ABILITY_SAND_STREAM); }
|
||||
OPPONENT(SPECIES_SANDSLASH) { Moves(MOVE_CELEBRATE); }
|
||||
} WHEN {
|
||||
@ -26,7 +26,7 @@ SINGLE_BATTLE_TEST("Sand Stream sets up sandstorm for 5 turns (Gen6+)")
|
||||
SINGLE_BATTLE_TEST("Sand Stream sets up sandstorm for 8 turns with Smooth Rock (Gen6+)")
|
||||
{
|
||||
GIVEN {
|
||||
WITH_CONFIG(CONFIG_ABILITY_WEATHER, GEN_6);
|
||||
WITH_CONFIG(B_ABILITY_WEATHER, GEN_6);
|
||||
PLAYER(SPECIES_HIPPOWDON) { Moves(MOVE_CELEBRATE); Ability(ABILITY_SAND_STREAM); Item(ITEM_SMOOTH_ROCK); }
|
||||
OPPONENT(SPECIES_SANDSLASH) { Moves(MOVE_CELEBRATE); }
|
||||
} WHEN {
|
||||
@ -54,7 +54,7 @@ SINGLE_BATTLE_TEST("Sand Stream sets up sandstorm for 8 turns with Smooth Rock (
|
||||
SINGLE_BATTLE_TEST("Sand Stream sets up permanent sandstorm (Gen3-5)")
|
||||
{
|
||||
GIVEN {
|
||||
WITH_CONFIG(CONFIG_ABILITY_WEATHER, GEN_3);
|
||||
WITH_CONFIG(B_ABILITY_WEATHER, GEN_3);
|
||||
PLAYER(SPECIES_HIPPOWDON) { Moves(MOVE_CELEBRATE); Ability(ABILITY_SAND_STREAM); }
|
||||
OPPONENT(SPECIES_SANDSLASH) { Moves(MOVE_CELEBRATE); }
|
||||
} WHEN {
|
||||
|
||||
@ -7,7 +7,7 @@ SINGLE_BATTLE_TEST("Scrappy doesn't prevent Intimidate (Gen4-7)")
|
||||
s16 turnTwoHit;
|
||||
|
||||
GIVEN {
|
||||
WITH_CONFIG(CONFIG_UPDATED_INTIMIDATE, GEN_7);
|
||||
WITH_CONFIG(B_UPDATED_INTIMIDATE, GEN_7);
|
||||
PLAYER(SPECIES_EKANS) { Ability(ABILITY_SHED_SKIN); }
|
||||
PLAYER(SPECIES_EKANS) { Ability(ABILITY_INTIMIDATE); }
|
||||
OPPONENT(SPECIES_KANGASKHAN) { Ability(ABILITY_SCRAPPY); }
|
||||
@ -35,7 +35,7 @@ SINGLE_BATTLE_TEST("Scrappy prevents Intimidate (Gen8+)")
|
||||
s16 turnTwoHit;
|
||||
|
||||
GIVEN {
|
||||
WITH_CONFIG(CONFIG_UPDATED_INTIMIDATE, GEN_8);
|
||||
WITH_CONFIG(B_UPDATED_INTIMIDATE, GEN_8);
|
||||
PLAYER(SPECIES_EKANS) { Ability(ABILITY_SHED_SKIN); }
|
||||
PLAYER(SPECIES_EKANS) { Ability(ABILITY_INTIMIDATE); }
|
||||
OPPONENT(SPECIES_KANGASKHAN) { Ability(ABILITY_SCRAPPY); }
|
||||
|
||||
@ -10,7 +10,7 @@ SINGLE_BATTLE_TEST("Shed Skin triggers 33% (Gen3, Gen5+) or 30% (Gen 4) of the t
|
||||
|
||||
PASSES_RANDOMLY(passes, 100, RNG_SHED_SKIN);
|
||||
GIVEN {
|
||||
WITH_CONFIG(CONFIG_ABILITY_TRIGGER_CHANCE, config);
|
||||
WITH_CONFIG(B_ABILITY_TRIGGER_CHANCE, config);
|
||||
ASSUME(MoveMakesContact(MOVE_SCRATCH));
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_ARBOK) { Status1(STATUS1_POISON); Ability(ABILITY_SHED_SKIN); }
|
||||
|
||||
@ -4,8 +4,8 @@
|
||||
SINGLE_BATTLE_TEST("Snow Warning sets up hail for 5 turns (Gen6-8)")
|
||||
{
|
||||
GIVEN {
|
||||
WITH_CONFIG(CONFIG_SNOW_WARNING, GEN_8);
|
||||
WITH_CONFIG(CONFIG_ABILITY_WEATHER, GEN_6);
|
||||
WITH_CONFIG(B_SNOW_WARNING, GEN_8);
|
||||
WITH_CONFIG(B_ABILITY_WEATHER, GEN_6);
|
||||
PLAYER(SPECIES_ABOMASNOW) { Moves(MOVE_CELEBRATE); Ability(ABILITY_SNOW_WARNING); }
|
||||
OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_CELEBRATE); }
|
||||
} WHEN {
|
||||
@ -27,8 +27,8 @@ SINGLE_BATTLE_TEST("Snow Warning sets up hail for 5 turns (Gen6-8)")
|
||||
SINGLE_BATTLE_TEST("Snow Warning sets up hail for 8 turns with Icy Rock (Gen6-8)")
|
||||
{
|
||||
GIVEN {
|
||||
WITH_CONFIG(CONFIG_SNOW_WARNING, GEN_8);
|
||||
WITH_CONFIG(CONFIG_ABILITY_WEATHER, GEN_6);
|
||||
WITH_CONFIG(B_SNOW_WARNING, GEN_8);
|
||||
WITH_CONFIG(B_ABILITY_WEATHER, GEN_6);
|
||||
PLAYER(SPECIES_ABOMASNOW) { Moves(MOVE_CELEBRATE); Ability(ABILITY_SNOW_WARNING); Item(ITEM_ICY_ROCK); }
|
||||
OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_CELEBRATE); }
|
||||
} WHEN {
|
||||
@ -56,8 +56,8 @@ SINGLE_BATTLE_TEST("Snow Warning sets up hail for 8 turns with Icy Rock (Gen6-8)
|
||||
SINGLE_BATTLE_TEST("Snow Warning sets up permanent hail (Gen4-5)")
|
||||
{
|
||||
GIVEN {
|
||||
WITH_CONFIG(CONFIG_SNOW_WARNING, GEN_8);
|
||||
WITH_CONFIG(CONFIG_ABILITY_WEATHER, GEN_5);
|
||||
WITH_CONFIG(B_SNOW_WARNING, GEN_8);
|
||||
WITH_CONFIG(B_ABILITY_WEATHER, GEN_5);
|
||||
PLAYER(SPECIES_ABOMASNOW) { Moves(MOVE_CELEBRATE); Ability(ABILITY_SNOW_WARNING); }
|
||||
OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_CELEBRATE); }
|
||||
} WHEN {
|
||||
@ -88,8 +88,8 @@ SINGLE_BATTLE_TEST("Snow Warning sets up permanent hail (Gen4-5)")
|
||||
SINGLE_BATTLE_TEST("Snow Warning sets up snow for 5 turns (Gen9+)")
|
||||
{
|
||||
GIVEN {
|
||||
WITH_CONFIG(CONFIG_SNOW_WARNING, GEN_9);
|
||||
WITH_CONFIG(CONFIG_ABILITY_WEATHER, GEN_9);
|
||||
WITH_CONFIG(B_SNOW_WARNING, GEN_9);
|
||||
WITH_CONFIG(B_ABILITY_WEATHER, GEN_9);
|
||||
PLAYER(SPECIES_ABOMASNOW) { Moves(MOVE_CELEBRATE); Ability(ABILITY_SNOW_WARNING); }
|
||||
OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_CELEBRATE); }
|
||||
} WHEN {
|
||||
@ -111,8 +111,8 @@ SINGLE_BATTLE_TEST("Snow Warning sets up snow for 5 turns (Gen9+)")
|
||||
SINGLE_BATTLE_TEST("Snow Warning sets up snow for 8 turns with Icy Rock (Gen9+)")
|
||||
{
|
||||
GIVEN {
|
||||
WITH_CONFIG(CONFIG_SNOW_WARNING, GEN_9);
|
||||
WITH_CONFIG(CONFIG_ABILITY_WEATHER, GEN_9);
|
||||
WITH_CONFIG(B_SNOW_WARNING, GEN_9);
|
||||
WITH_CONFIG(B_ABILITY_WEATHER, GEN_9);
|
||||
PLAYER(SPECIES_ABOMASNOW) { Moves(MOVE_CELEBRATE); Ability(ABILITY_SNOW_WARNING); Item(ITEM_ICY_ROCK); }
|
||||
OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_CELEBRATE); }
|
||||
} WHEN {
|
||||
|
||||
@ -27,7 +27,7 @@ DOUBLE_BATTLE_TEST("Stalwart stops Lightning Rod and Storm Drain from redirectin
|
||||
PARAMETRIZE { ability = ABILITY_LIGHTNING_ROD; species = SPECIES_RAICHU; config = GEN_4; }
|
||||
PARAMETRIZE { ability = ABILITY_LIGHTNING_ROD; species = SPECIES_RAICHU; config = GEN_5; }
|
||||
GIVEN {
|
||||
WITH_CONFIG(CONFIG_REDIRECT_ABILITY_IMMUNITY, config);
|
||||
WITH_CONFIG(B_REDIRECT_ABILITY_IMMUNITY, config);
|
||||
ASSUME(GetMoveType(MOVE_SPARK) == TYPE_ELECTRIC);
|
||||
ASSUME(GetMoveType(MOVE_WATER_GUN) == TYPE_WATER);
|
||||
PLAYER(SPECIES_WOBBUFFET) { Ability(ABILITY_STALWART); }
|
||||
|
||||
@ -37,7 +37,7 @@ SINGLE_BATTLE_TEST("Static triggers 1/3 times (Gen3) or 30% (Gen4+) of the time"
|
||||
PARAMETRIZE { config = GEN_4; passes = 3; trials = 10; } // 30%
|
||||
PASSES_RANDOMLY(passes, trials, RNG_STATIC);
|
||||
GIVEN {
|
||||
WITH_CONFIG(CONFIG_ABILITY_TRIGGER_CHANCE, config);
|
||||
WITH_CONFIG(B_ABILITY_TRIGGER_CHANCE, config);
|
||||
ASSUME(MoveMakesContact(MOVE_SCRATCH));
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_PIKACHU) { Ability(ABILITY_STATIC); }
|
||||
|
||||
@ -16,3 +16,27 @@ SINGLE_BATTLE_TEST("Sticky Hold prevents item theft")
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Sticky Hold prevents Incinerate from destroying berries")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET) { Moves(MOVE_INCINERATE); }
|
||||
OPPONENT(SPECIES_GASTRODON) { Ability(ABILITY_STICKY_HOLD); Item(ITEM_CHERI_BERRY); }
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_INCINERATE); }
|
||||
} THEN {
|
||||
EXPECT_EQ(gBattleMons[B_POSITION_OPPONENT_LEFT].item, ITEM_CHERI_BERRY);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Sticky Hold prevents Incinerate from destroying gems")
|
||||
{
|
||||
GIVEN {
|
||||
WITH_CONFIG(B_INCINERATE_GEMS, GEN_6);
|
||||
PLAYER(SPECIES_WOBBUFFET) { Moves(MOVE_INCINERATE); }
|
||||
OPPONENT(SPECIES_GASTRODON) { Ability(ABILITY_STICKY_HOLD); Item(ITEM_GHOST_GEM); }
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_INCINERATE); }
|
||||
} THEN {
|
||||
EXPECT_EQ(gBattleMons[B_POSITION_OPPONENT_LEFT].item, ITEM_GHOST_GEM);
|
||||
}
|
||||
}
|
||||
|
||||
@ -7,7 +7,7 @@ SINGLE_BATTLE_TEST("Storm Drain absorbs Water-type moves and increases the Sp. A
|
||||
PARAMETRIZE { config = GEN_4; }
|
||||
PARAMETRIZE { config = GEN_5; }
|
||||
GIVEN {
|
||||
WITH_CONFIG(CONFIG_REDIRECT_ABILITY_IMMUNITY, config);
|
||||
WITH_CONFIG(B_REDIRECT_ABILITY_IMMUNITY, config);
|
||||
ASSUME(GetMoveType(MOVE_WATER_GUN) == TYPE_WATER);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_GASTRODON_EAST) { Ability(ABILITY_STORM_DRAIN); }
|
||||
@ -41,7 +41,7 @@ DOUBLE_BATTLE_TEST("Storm Drain forces single-target Water-type moves to target
|
||||
PARAMETRIZE { config = GEN_4; }
|
||||
PARAMETRIZE { config = GEN_5; }
|
||||
GIVEN {
|
||||
WITH_CONFIG(CONFIG_REDIRECT_ABILITY_IMMUNITY, config);
|
||||
WITH_CONFIG(B_REDIRECT_ABILITY_IMMUNITY, config);
|
||||
ASSUME(GetMoveType(MOVE_WATER_GUN) == TYPE_WATER);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
|
||||
@ -24,7 +24,7 @@ SINGLE_BATTLE_TEST("Sturdy prevents OHKOs (Gen5+)")
|
||||
PARAMETRIZE { config = GEN_4; }
|
||||
PARAMETRIZE { config = GEN_5; }
|
||||
GIVEN {
|
||||
WITH_CONFIG(CONFIG_STURDY, config);
|
||||
WITH_CONFIG(B_STURDY, config);
|
||||
PLAYER(SPECIES_GEODUDE) { Ability(ABILITY_STURDY); MaxHP(100); HP(100); }
|
||||
PLAYER(SPECIES_GEODUDE);
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
|
||||
@ -11,7 +11,7 @@ SINGLE_BATTLE_TEST("Super Luck increases the critical hit ratio by 1 stage")
|
||||
PASSES_RANDOMLY(passes, trials, RNG_CRITICAL_HIT);
|
||||
GIVEN {
|
||||
ASSUME(GetSpeciesBaseSpeed(SPECIES_TOGEPI) == 20);
|
||||
WITH_CONFIG(CONFIG_CRIT_CHANCE, genConfig);
|
||||
WITH_CONFIG(B_CRIT_CHANCE, genConfig);
|
||||
PLAYER(SPECIES_TOGEPI) { Ability(ABILITY_SUPER_LUCK); }
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user