Master to upcoming merge 01/07/25 (#7267)
This commit is contained in:
commit
ae1d99bb4f
@ -7,6 +7,7 @@ body:
|
||||
value: |
|
||||
Please fill in all fields with as many details as possible.
|
||||
Once your bug is posted, make sure you and your collaborators are added to `CREDITS.md` by [tagging the bot on GitHub](https://github.com/rh-hideout/pokeemerald-expansion/wiki/CREDITS.md-Frequently-Asked-Questions). EVERY contribution matters, even reporting bugs!
|
||||
- type: textarea
|
||||
id: description
|
||||
attributes:
|
||||
label: Description
|
||||
@ -42,9 +43,10 @@ body:
|
||||
label: Version
|
||||
description: What version of pokeemerald-expansion are you using?
|
||||
options:
|
||||
- 1.12.0 (Latest release)
|
||||
- 1.12.1 (Latest release)
|
||||
- master (default, unreleased bugfixes)
|
||||
- upcoming (Edge)
|
||||
- 1.12.0
|
||||
- 1.11.4
|
||||
- 1.11.3
|
||||
- 1.11.2
|
||||
|
||||
@ -43,9 +43,10 @@ body:
|
||||
label: Version
|
||||
description: What version of pokeemerald-expansion are you using?
|
||||
options:
|
||||
- 1.12.0 (Latest release)
|
||||
- 1.12.1 (Latest release)
|
||||
- master (default, unreleased bugfixes)
|
||||
- upcoming (Edge)
|
||||
- 1.12.0
|
||||
- 1.11.4
|
||||
- 1.11.3
|
||||
- 1.11.2
|
||||
|
||||
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.12.0 (Latest release)
|
||||
- 1.12.1 (Latest release)
|
||||
- master (default, unreleased bugfixes)
|
||||
- upcoming (Edge)
|
||||
- 1.12.0
|
||||
- 1.11.4
|
||||
- 1.11.3
|
||||
- 1.11.1
|
||||
|
||||
@ -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.12.0 https://github.com/rh-hideout/pokeemerald-expansion/
|
||||
Based off RHH's pokeemerald-expansion 1.12.1 https://github.com/rh-hideout/pokeemerald-expansion/
|
||||
```
|
||||
|
||||
Please consider [crediting all contributors](CREDITS.md) involved in the project!
|
||||
|
||||
@ -844,8 +844,10 @@
|
||||
.4byte \failInstr
|
||||
.endm
|
||||
|
||||
.macro setstatuswithability
|
||||
.macro checknonvolatiletrigger nonVolatile:req, failInstr:req
|
||||
.byte 0x94
|
||||
.2byte \nonVolatile
|
||||
.4byte \failInstr
|
||||
.endm
|
||||
|
||||
.macro copybidedmg
|
||||
@ -1530,14 +1532,8 @@
|
||||
.4byte \jumpInstr
|
||||
.endm
|
||||
|
||||
.macro jumpifmovepropertyargument argument:req, jumpInstr:req
|
||||
callnative BS_JumpIfMovePropertyArgument
|
||||
.byte \argument
|
||||
.4byte \jumpInstr
|
||||
.endm
|
||||
|
||||
.macro setremoveterrain failInstr:req
|
||||
callnative BS_SetRemoveTerrain
|
||||
.macro setterrain failInstr:req
|
||||
callnative BS_SetTerrain
|
||||
.4byte \failInstr
|
||||
.endm
|
||||
|
||||
|
||||
@ -1469,11 +1469,12 @@ BattleScript_EffectFlowerShield::
|
||||
attackcanceler
|
||||
attackstring
|
||||
ppreduce
|
||||
savetarget
|
||||
selectfirstvalidtarget
|
||||
BattleScript_FlowerShieldIsAnyGrass:
|
||||
jumpiftype BS_TARGET, TYPE_GRASS, BattleScript_FlowerShieldLoopStart
|
||||
jumpifnexttargetvalid BattleScript_FlowerShieldIsAnyGrass
|
||||
goto BattleScript_ButItFailed
|
||||
goto BattleScript_RestoreTargetButItFailed
|
||||
BattleScript_FlowerShieldLoopStart:
|
||||
selectfirstvalidtarget
|
||||
BattleScript_FlowerShieldLoop:
|
||||
@ -1497,6 +1498,7 @@ BattleScript_FlowerShieldString:
|
||||
BattleScript_FlowerShieldMoveTargetEnd:
|
||||
moveendto MOVEEND_NEXT_TARGET
|
||||
jumpifnexttargetvalid BattleScript_FlowerShieldLoop
|
||||
restoretarget
|
||||
end
|
||||
|
||||
BattleScript_EffectRototiller::
|
||||
@ -1770,20 +1772,19 @@ BattleScript_EffectToxicThread::
|
||||
setstatchanger STAT_SPEED, 1, TRUE
|
||||
attackcanceler
|
||||
jumpifsubstituteblocks BattleScript_FailedFromAtkString
|
||||
jumpifstat BS_TARGET, CMP_NOT_EQUAL, STAT_SPEED, MIN_STAT_STAGE, BattleScript_ToxicThreadWorks
|
||||
jumpifstatus BS_TARGET, STATUS1_ANY, BattleScript_FailedFromAtkString
|
||||
BattleScript_ToxicThreadWorks:
|
||||
checknonvolatiletrigger MOVE_EFFECT_POISON, BattleScript_EffectStatDownFromAccCheck
|
||||
accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE
|
||||
attackstring
|
||||
ppreduce
|
||||
attackanimation
|
||||
waitanimation
|
||||
setstatchanger STAT_SPEED, 1, TRUE
|
||||
statbuffchange BS_TARGET, STAT_CHANGE_ALLOW_PTR | STAT_CHANGE_ONLY_CHECKING, BattleScript_ToxicThreadTryPsn
|
||||
jumpifbyte CMP_LESS_THAN, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_DECREASE, BattleScript_ToxicThreadDoAnim
|
||||
jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_FELL_EMPTY, BattleScript_ToxicThreadTryPsn
|
||||
pause B_WAIT_TIME_SHORT
|
||||
goto BattleScript_ToxicThreadPrintString
|
||||
BattleScript_ToxicThreadDoAnim::
|
||||
attackanimation
|
||||
waitanimation
|
||||
statbuffchange BS_TARGET, STAT_CHANGE_ALLOW_PTR, BattleScript_ToxicThreadTryPsn
|
||||
BattleScript_ToxicThreadPrintString::
|
||||
printfromtable gStatDownStringIds
|
||||
@ -2153,7 +2154,7 @@ BattleScript_EffectPsychicTerrain::
|
||||
attackcanceler
|
||||
attackstring
|
||||
ppreduce
|
||||
setremoveterrain BattleScript_ButItFailed
|
||||
setterrain BattleScript_ButItFailed
|
||||
attackanimation
|
||||
waitanimation
|
||||
printfromtable gTerrainStringIds
|
||||
@ -3046,6 +3047,7 @@ BattleScript_EffectEvasionDown::
|
||||
BattleScript_EffectStatDown:
|
||||
attackcanceler
|
||||
jumpifsubstituteblocks BattleScript_FailedFromAtkString
|
||||
BattleScript_EffectStatDownFromAccCheck:
|
||||
accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE
|
||||
BattleScript_StatDownFromAttackString:
|
||||
attackstring
|
||||
@ -4402,6 +4404,9 @@ BattleScript_ButItFailed::
|
||||
BattleScript_RestoreAttackerButItFailed:
|
||||
restoreattacker
|
||||
goto BattleScript_ButItFailed
|
||||
BattleScript_RestoreTargetButItFailed:
|
||||
restoretarget
|
||||
goto BattleScript_ButItFailed
|
||||
|
||||
BattleScript_NotAffected::
|
||||
pause B_WAIT_TIME_SHORT
|
||||
@ -7273,7 +7278,7 @@ BattleScript_EmergencyExit::
|
||||
switchoutabilities BS_SCRIPTING
|
||||
waitstate
|
||||
switchhandleorder BS_SCRIPTING, 2
|
||||
returntoball BS_TARGET, FALSE
|
||||
returntoball BS_SCRIPTING, FALSE
|
||||
getswitchedmondata BS_SCRIPTING
|
||||
switchindataupdate BS_SCRIPTING
|
||||
hpthresholds BS_SCRIPTING
|
||||
@ -7306,7 +7311,7 @@ BattleScript_EmergencyExitEnd2::
|
||||
switchoutabilities BS_ATTACKER
|
||||
waitstate
|
||||
switchhandleorder BS_ATTACKER, 2
|
||||
returntoball BS_TARGET, FALSE
|
||||
returntoball BS_ATTACKER, FALSE
|
||||
getswitchedmondata BS_ATTACKER
|
||||
switchindataupdate BS_ATTACKER
|
||||
hpthresholds BS_ATTACKER
|
||||
@ -8370,6 +8375,7 @@ BattleScript_MoveUsedLoafingAroundMsg::
|
||||
moveendto MOVEEND_NEXT_TARGET
|
||||
end
|
||||
BattleScript_TruantLoafingAround::
|
||||
flushtextbox
|
||||
call BattleScript_AbilityPopUp
|
||||
goto BattleScript_MoveUsedLoafingAroundMsg
|
||||
|
||||
@ -9092,12 +9098,11 @@ BattleScript_ExtremeEvoboostSpDef::
|
||||
BattleScript_ExtremeEvoboostEnd::
|
||||
goto BattleScript_MoveEnd
|
||||
|
||||
BattleScript_EffectHitSetRemoveTerrain::
|
||||
BattleScript_EffectHitSetTerrain::
|
||||
attackcanceler
|
||||
accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE
|
||||
attackstring
|
||||
ppreduce
|
||||
jumpifmovepropertyargument ARG_TRY_REMOVE_TERRAIN_FAIL, BattleScript_RemoveTerrain
|
||||
critcalc
|
||||
damagecalc
|
||||
adjustdamage
|
||||
@ -9112,7 +9117,7 @@ BattleScript_EffectHitSetRemoveTerrain::
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
resultmessage
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
setremoveterrain BattleScript_TryFaint
|
||||
setterrain BattleScript_TryFaint
|
||||
playanimation BS_ATTACKER, B_ANIM_RESTORE_BG
|
||||
printfromtable gTerrainStringIds
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
@ -9120,30 +9125,17 @@ BattleScript_TryFaint:
|
||||
tryfaintmon BS_TARGET
|
||||
goto BattleScript_MoveEnd
|
||||
|
||||
BattleScript_RemoveTerrain:
|
||||
jumpifterrainaffected BS_TARGET, STATUS_FIELD_TERRAIN_ANY, BattleScript_RemoveTerrain_Cont
|
||||
goto BattleScript_ButItFailed
|
||||
BattleScript_RemoveTerrain_Cont:
|
||||
critcalc
|
||||
damagecalc
|
||||
adjustdamage
|
||||
attackanimation
|
||||
waitanimation
|
||||
effectivenesssound
|
||||
hitanimation BS_TARGET
|
||||
waitstate
|
||||
healthbarupdate BS_TARGET
|
||||
datahpupdate BS_TARGET
|
||||
critmessage
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
resultmessage
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
BattleScript_EffectSteelRoller::
|
||||
attackcanceler
|
||||
jumpifhalfword CMP_NO_COMMON_BITS, gFieldStatuses, STATUS_FIELD_TERRAIN_ANY, BattleScript_FailedFromAtkString
|
||||
goto BattleScript_HitFromAccCheck
|
||||
|
||||
BattleScript_RemoveTerrain::
|
||||
removeterrain
|
||||
playanimation BS_ATTACKER, B_ANIM_RESTORE_BG
|
||||
printfromtable gTerrainStringIds
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
tryfaintmon BS_TARGET
|
||||
goto BattleScript_MoveEnd
|
||||
return
|
||||
|
||||
BattleScript_Pickpocket::
|
||||
call BattleScript_AbilityPopUp
|
||||
|
||||
@ -20,6 +20,7 @@
|
||||
- [Day/Night System FAQ](tutorials/dns.md)
|
||||
- [Changelog](./CHANGELOG.md)
|
||||
- [1.12.x]()
|
||||
- [Version 1.12.1](changelogs/1.12.x/1.12.1.md)
|
||||
- [Version 1.12.0](changelogs/1.12.x/1.12.0.md)
|
||||
- [1.11.x]()
|
||||
- [Version 1.11.4](changelogs/1.11.x/1.11.4.md)
|
||||
|
||||
145
docs/changelogs/1.12.x/1.12.1.md
Normal file
145
docs/changelogs/1.12.x/1.12.1.md
Normal file
@ -0,0 +1,145 @@
|
||||
```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.12.1
|
||||
`.
|
||||
```
|
||||
|
||||
|
||||
## 🧬 General 🧬
|
||||
### Changed
|
||||
* Changed trainer tutorial to take into account removed palette compression by @hedara90 in [#7044](https://github.com/rh-hideout/pokeemerald-expansion/pull/7044)
|
||||
* Update CI to ignore allcontributors commits by @pkmnsnfrn in [#7046](https://github.com/rh-hideout/pokeemerald-expansion/pull/7046)
|
||||
* Fixed CI issue introduced 7046 by @pkmnsnfrn in [#7072](https://github.com/rh-hideout/pokeemerald-expansion/pull/7072)
|
||||
* Added loop iterator style by @hedara90 in [#7092](https://github.com/rh-hideout/pokeemerald-expansion/pull/7092)
|
||||
* Fix typo in INSTALL.md by @hedara90 in [#7116](https://github.com/rh-hideout/pokeemerald-expansion/pull/7116)
|
||||
* Use RGB values for DEFAULT_LIGHT_COLOR by @hedara90 in [#7133](https://github.com/rh-hideout/pokeemerald-expansion/pull/7133)
|
||||
* Applied Kasen's documentation improvements by @hedara90 in [#7104](https://github.com/rh-hideout/pokeemerald-expansion/pull/7104)
|
||||
* Fixed description of `FORM_CHANGE_WITHDRAW` by @AsparagusEduardo in [#7152](https://github.com/rh-hideout/pokeemerald-expansion/pull/7152)
|
||||
* Pret merge (19th of June, 2025) by @Bassoonian in [#7163](https://github.com/rh-hideout/pokeemerald-expansion/pull/7163)
|
||||
* Update the description of OW_OBJECT_VANILLA_SHADOWS by @pkmnsnfrn in [#7184](https://github.com/rh-hideout/pokeemerald-expansion/pull/7184)
|
||||
* fix: use BackPickId to calculate player intro ball throw animation palette by @pablopenna in [#7193](https://github.com/rh-hideout/pokeemerald-expansion/pull/7193)
|
||||
|
||||
### Fixed
|
||||
* Added line break between Trainer 1 name and Trainer 2 name in sText_TwoTrainersWantToBattle by @grintoul1 in [#7028](https://github.com/rh-hideout/pokeemerald-expansion/pull/7028)
|
||||
* Fixed Battle Pyramid mon generation by @hedara90 in [#7146](https://github.com/rh-hideout/pokeemerald-expansion/pull/7146)
|
||||
* force sGFRomHeader to always be present by @DizzyEggg in [#7186](https://github.com/rh-hideout/pokeemerald-expansion/pull/7186)
|
||||
* force RHH Rom Header to always be present by @DizzyEggg in [#7187](https://github.com/rh-hideout/pokeemerald-expansion/pull/7187)
|
||||
* Fixed debug flag menu sound by @AsparagusEduardo in [#7190](https://github.com/rh-hideout/pokeemerald-expansion/pull/7190)
|
||||
* Fix BtlController_EmitChosenMonReturnValue UB by @DizzyEggg in [#7197](https://github.com/rh-hideout/pokeemerald-expansion/pull/7197)
|
||||
* Backported Safari catch and add to party fix by @hedara90 in [#7192](https://github.com/rh-hideout/pokeemerald-expansion/pull/7192)
|
||||
* Fix 01_battle_engine_bugs.yaml by @hedara90 in [#7242](https://github.com/rh-hideout/pokeemerald-expansion/pull/7242)
|
||||
|
||||
## 🗺️ Overworld 🗺️
|
||||
### Fixed
|
||||
* Bug fix: clear saved follower NPC door warp when doing dive warp by @Bivurnum in [#7065](https://github.com/rh-hideout/pokeemerald-expansion/pull/7065)
|
||||
* Fix Contest Painting load palette error by @ExMingYan in [#7077](https://github.com/rh-hideout/pokeemerald-expansion/pull/7077)
|
||||
* Bug fix: Follower NPC no longer retains bike sprite after white out by @Bivurnum in [#7120](https://github.com/rh-hideout/pokeemerald-expansion/pull/7120)
|
||||
* Bug fix: clear follower npc surf blob on white out by @Bivurnum in [#7153](https://github.com/rh-hideout/pokeemerald-expansion/pull/7153)
|
||||
|
||||
## 🐉 Pokémon 🐉
|
||||
### Changed
|
||||
* Fixes Rapid Spin description (#7178) by @grintoul1 in [#7181](https://github.com/rh-hideout/pokeemerald-expansion/pull/7181)
|
||||
|
||||
### Fixed
|
||||
* Fixed text width for a lot of forms in HGSS Dex by @AsparagusEduardo in [#7035](https://github.com/rh-hideout/pokeemerald-expansion/pull/7035)
|
||||
* Fixes Roamers not saving shininess by @i0brendan0 in [#7185](https://github.com/rh-hideout/pokeemerald-expansion/pull/7185)
|
||||
* [FIX] Prevent caught Pokémon loss in NPC partner battles by @J2M2 in [#7177](https://github.com/rh-hideout/pokeemerald-expansion/pull/7177)
|
||||
|
||||
## ⚔️ Battle General ⚔️
|
||||
### Changed
|
||||
* Fixes large battle messages being cut off instead of being prompted to advance 2 by @PhallenTree in [#7036](https://github.com/rh-hideout/pokeemerald-expansion/pull/7036)
|
||||
* Battle controller pret documentation by @AlexOn1ine in [#7029](https://github.com/rh-hideout/pokeemerald-expansion/pull/7029)
|
||||
* Fix typos and some cleanup (mainly in battle files) by @PhallenTree in [#7107](https://github.com/rh-hideout/pokeemerald-expansion/pull/7107)
|
||||
|
||||
### Fixed
|
||||
* Fixes multi battle party re-order by @AlexOn1ine in [#7042](https://github.com/rh-hideout/pokeemerald-expansion/pull/7042)
|
||||
* Fixes Aura Wheel + Normalize and Hunger Switch while Transformed/Terastallized by @PhallenTree in [#7061](https://github.com/rh-hideout/pokeemerald-expansion/pull/7061)
|
||||
* Fixes speed calculation order by @AlexOn1ine in [#7064](https://github.com/rh-hideout/pokeemerald-expansion/pull/7064)
|
||||
* Bug fix for Grassy Terrain incorrectly healing non-grounded Pokemon by @LinathanZel in [#7058](https://github.com/rh-hideout/pokeemerald-expansion/pull/7058)
|
||||
* Fixes Wandering Spirit copied ability activation on fainted mon by @AlexOn1ine in [#7066](https://github.com/rh-hideout/pokeemerald-expansion/pull/7066)
|
||||
* Chloroblast fix by @LinathanZel in [#7008](https://github.com/rh-hideout/pokeemerald-expansion/pull/7008)
|
||||
* Fix Normalize not boosting Normal type moves if they were already Normal type by @i0brendan0 in [#7060](https://github.com/rh-hideout/pokeemerald-expansion/pull/7060)
|
||||
* Fixes freeze during a 1v2 double battle by @AlexOn1ine in [#7075](https://github.com/rh-hideout/pokeemerald-expansion/pull/7075)
|
||||
* Fixes Pursuit potentially causing both battlers to switch into the same mon by @PhallenTree in [#7084](https://github.com/rh-hideout/pokeemerald-expansion/pull/7084)
|
||||
* Fixed potential mismatch between players and battlers in tests by @AsparagusEduardo in [#7101](https://github.com/rh-hideout/pokeemerald-expansion/pull/7101)
|
||||
* Fixes Ally Switch in multi battles by @AlexOn1ine in [#7109](https://github.com/rh-hideout/pokeemerald-expansion/pull/7109)
|
||||
* Add missing flag for Berserk Gene by @AlexOn1ine in [#7151](https://github.com/rh-hideout/pokeemerald-expansion/pull/7151)
|
||||
* Fixes Neutralizing Gas leaving the field activating unsuppressable abilities again by @PhallenTree in [#7170](https://github.com/rh-hideout/pokeemerald-expansion/pull/7170)
|
||||
* Fixes Enigma, Kee and Maranga Berry activation timing by @AlexOn1ine in [#7171](https://github.com/rh-hideout/pokeemerald-expansion/pull/7171)
|
||||
* Fixes wrong Future Sight indexing by @AlexOn1ine in [#7198](https://github.com/rh-hideout/pokeemerald-expansion/pull/7198)
|
||||
* Fixes OOB for Teatime and Flower Shield by @AlexOn1ine in [#7214](https://github.com/rh-hideout/pokeemerald-expansion/pull/7214)
|
||||
* Fixes wrong assignment in TrySymbiosis by @AlexOn1ine in [#7221](https://github.com/rh-hideout/pokeemerald-expansion/pull/7221)
|
||||
* Adds missing healBlockTimer for Baton Pass by @AlexOn1ine in [#7220](https://github.com/rh-hideout/pokeemerald-expansion/pull/7220)
|
||||
* Jaboca berry triggers instead of being stolen by bug bite by @ghoulslash in [#7237](https://github.com/rh-hideout/pokeemerald-expansion/pull/7237)
|
||||
* Fixes Scald defrosting target while asleep by @AlexOn1ine in [#7233](https://github.com/rh-hideout/pokeemerald-expansion/pull/7233)
|
||||
* Fixes Emergency Exit sometimes causing an unrelated battler to become invisible by @PhallenTree in [#7241](https://github.com/rh-hideout/pokeemerald-expansion/pull/7241)
|
||||
|
||||
## 🤹 Moves 🤹
|
||||
### Changed
|
||||
* Fix ScaryFace anim for Bitter Malice by @TLM-PsIQ in [#6476](https://github.com/rh-hideout/pokeemerald-expansion/pull/6476)
|
||||
|
||||
### Fixed
|
||||
* Fix savage spin out spider web template by @ghoulslash in [#7137](https://github.com/rh-hideout/pokeemerald-expansion/pull/7137)
|
||||
|
||||
## 🎭 Abilities 🎭
|
||||
### Changed
|
||||
* Flush textbox for Truant Popup by @ghoulslash in [#7252](https://github.com/rh-hideout/pokeemerald-expansion/pull/7252)
|
||||
|
||||
## 🧶 Items 🧶
|
||||
### Fixed
|
||||
* Fix sell price display by @cawtds in [#7123](https://github.com/rh-hideout/pokeemerald-expansion/pull/7123)
|
||||
|
||||
## 🤖 Battle AI 🤖
|
||||
### Fixed
|
||||
* Added AI_FLAG_PP_STALL_PREVENTION to AI_FLAG_SMART_TRAINER by @AlexOn1ine in [#7112](https://github.com/rh-hideout/pokeemerald-expansion/pull/7112)
|
||||
* Fix incorrect function parameters used in AI damage calc by @Pawkkie in [#7130](https://github.com/rh-hideout/pokeemerald-expansion/pull/7130)
|
||||
|
||||
## 🧹 Other Cleanup 🧹
|
||||
* Fix typos and some cleanup (mainly in battle files) by @PhallenTree in [#7107](https://github.com/rh-hideout/pokeemerald-expansion/pull/7107)
|
||||
* Fix typo in INSTALL.md by @hedara90 in [#7116](https://github.com/rh-hideout/pokeemerald-expansion/pull/7116)
|
||||
* Fixed description of `FORM_CHANGE_WITHDRAW` by @AsparagusEduardo in [#7152](https://github.com/rh-hideout/pokeemerald-expansion/pull/7152)
|
||||
* Spruce up `FEATURES.md` by @AsparagusEduardo in [#7159](https://github.com/rh-hideout/pokeemerald-expansion/pull/7159)
|
||||
* Fixes Rapid Spin description (#7178) by @grintoul1 in [#7181](https://github.com/rh-hideout/pokeemerald-expansion/pull/7181)
|
||||
|
||||
## 🧪 Test Runner 🧪
|
||||
### Changed
|
||||
* Wrote some missing tests by @AsparagusEduardo in [#7094](https://github.com/rh-hideout/pokeemerald-expansion/pull/7094)
|
||||
* Fixed KNOWN_FAILING Tera test by @AsparagusEduardo in [#6949](https://github.com/rh-hideout/pokeemerald-expansion/pull/6949)
|
||||
* Add some tests by @ghoulslash in [#7234](https://github.com/rh-hideout/pokeemerald-expansion/pull/7234)
|
||||
* Added tests for Toxic Thread by @hedara90 in [#7244](https://github.com/rh-hideout/pokeemerald-expansion/pull/7244)
|
||||
|
||||
### Fixed
|
||||
* Test runner fixes by @hedara90 in [#7100](https://github.com/rh-hideout/pokeemerald-expansion/pull/7100)
|
||||
* Fixed Aura Wheel `KNOWN_FAILING` test by @AsparagusEduardo in [#7135](https://github.com/rh-hideout/pokeemerald-expansion/pull/7135)
|
||||
* Fix AI party count calc being maintained between tests by @AsparagusEduardo in [#7200](https://github.com/rh-hideout/pokeemerald-expansion/pull/7200)
|
||||
* Fix tests failing with `B_FRIENDSHIP_BOOST` being `TRUE` by @AsparagusEduardo in [#7194](https://github.com/rh-hideout/pokeemerald-expansion/pull/7194)
|
||||
* Jaboca berry triggers instead of being stolen by bug bite by @ghoulslash in [#7237](https://github.com/rh-hideout/pokeemerald-expansion/pull/7237)
|
||||
|
||||
## 📚 Documentation 📚
|
||||
* Changed trainer tutorial to take into account removed palette compression by @hedara90 in [#7044](https://github.com/rh-hideout/pokeemerald-expansion/pull/7044)
|
||||
* Battle controller pret documentation by @AlexOn1ine in [#7029](https://github.com/rh-hideout/pokeemerald-expansion/pull/7029)
|
||||
* Added loop iterator style by @hedara90 in [#7092](https://github.com/rh-hideout/pokeemerald-expansion/pull/7092)
|
||||
* Use RGB values for DEFAULT_LIGHT_COLOR by @hedara90 in [#7133](https://github.com/rh-hideout/pokeemerald-expansion/pull/7133)
|
||||
* Applied Kasen's documentation improvements by @hedara90 in [#7104](https://github.com/rh-hideout/pokeemerald-expansion/pull/7104)
|
||||
* Spruce up `FEATURES.md` by @AsparagusEduardo in [#7159](https://github.com/rh-hideout/pokeemerald-expansion/pull/7159)
|
||||
* Update the description of OW_OBJECT_VANILLA_SHADOWS by @pkmnsnfrn in [#7184](https://github.com/rh-hideout/pokeemerald-expansion/pull/7184)
|
||||
|
||||
## 📦 Branch Synchronisation 📦
|
||||
### pret
|
||||
* 24th of June, 2025 in [#7206](https://github.com/rh-hideout/pokeemerald-expansion/pull/7206)
|
||||
* Move gTradePlatform_Tilemap to header and change to u32 by @DizzyEggg in [pret#2088](https://github.com/pret/pokeemerald/pull/2088)
|
||||
* Fix wrong keep temps files directory in makefile by @DizzyEggg in [pret#2156](https://github.com/pret/pokeemerald/pull/2156)
|
||||
* Fix collision comparison in PlayerNotOnBikeMoving by @GriffinRichards in [pret#2104](https://github.com/pret/pokeemerald/pull/2104)
|
||||
* Match graphics declarations with externs in graphics.h by @DizzyEggg in [pret#2089](https://github.com/pret/pokeemerald/pull/2089)
|
||||
|
||||
## New Contributors
|
||||
* @TLM-PsIQ made their first contribution in [#6476](https://github.com/rh-hideout/pokeemerald-expansion/pull/6476)
|
||||
* @pablopenna made their first contribution in [#7193](https://github.com/rh-hideout/pokeemerald-expansion/pull/7193)
|
||||
* @J2M2 made their first contribution in [#7177](https://github.com/rh-hideout/pokeemerald-expansion/pull/7177)
|
||||
|
||||
**Full Changelog**: https://github.com/rh-hideout/pokeemerald-expansion/compare/expansion/1.12.0...expansion/1.12.1
|
||||
|
||||
|
||||
<!--Last PR: 7252-->
|
||||
<!--Used to keep track of the last PR merged in case new ones come in before the changelog is done.-->
|
||||
@ -296,6 +296,7 @@ extern const u8 BattleScript_CursedBodyActivates[];
|
||||
extern const u8 BattleScript_MummyActivates[];
|
||||
extern const u8 BattleScript_WeakArmorActivates[];
|
||||
extern const u8 BattleScript_FellStingerRaisesStat[];
|
||||
extern const u8 BattleScript_RemoveTerrain[];
|
||||
extern const u8 BattleScript_SnowWarningActivatesHail[];
|
||||
extern const u8 BattleScript_SnowWarningActivatesSnow[];
|
||||
extern const u8 BattleScript_PickupActivates[];
|
||||
@ -344,6 +345,7 @@ extern const u8 BattleScript_MistySurgeActivates[];
|
||||
extern const u8 BattleScript_ElectricSurgeActivates[];
|
||||
extern const u8 BattleScript_EffectSpectralThief[];
|
||||
extern const u8 BattleScript_EffectLifeDew[];
|
||||
extern const u8 BattleScript_EffectSteelRoller[];
|
||||
extern const u8 BattleScript_AbilityRaisesDefenderStat[];
|
||||
extern const u8 BattleScript_PowderMoveNoEffect[];
|
||||
extern const u8 BattleScript_GrassyTerrainHeals[];
|
||||
@ -845,7 +847,7 @@ extern const u8 BattleScript_EffectSkyDrop[];
|
||||
extern const u8 BattleScript_EffectMeteorBeam[];
|
||||
extern const u8 BattleScript_EffectCourtChange[];
|
||||
extern const u8 BattleScript_EffectExtremeEvoboost[];
|
||||
extern const u8 BattleScript_EffectHitSetRemoveTerrain[];
|
||||
extern const u8 BattleScript_EffectHitSetTerrain[];
|
||||
extern const u8 BattleScript_EffectDarkVoid[];
|
||||
extern const u8 BattleScript_EffectVictoryDance[];
|
||||
extern const u8 BattleScript_EffectTeatime[];
|
||||
|
||||
@ -275,7 +275,8 @@ enum ItemHoldEffect GetBattlerHoldEffect(u32 battler, bool32 checkNegating);
|
||||
enum ItemHoldEffect GetBattlerHoldEffectIgnoreAbility(u32 battler, bool32 checkNegating);
|
||||
enum ItemHoldEffect GetBattlerHoldEffectInternal(u32 battler, bool32 checkNegating, bool32 checkAbility);
|
||||
u32 GetBattlerHoldEffectParam(u32 battler);
|
||||
bool32 IsMoveMakingContact(u32 move, u32 battlerAtk);
|
||||
bool32 CanBattlerAvoidContactEffects(u32 battlerAtk, u32 battlerDef, u32 abilityAtk, enum ItemHoldEffect holdEffectAtk, u32 move);
|
||||
bool32 IsMoveMakingContact(u32 battlerAtk, u32 battlerDef, u32 abilityAtk, enum ItemHoldEffect holdEffectAtk, u32 move);
|
||||
bool32 IsBattlerGrounded(u32 battler);
|
||||
u32 GetMoveSlot(u16 *moves, u32 move);
|
||||
u32 GetBattlerWeight(u32 battler);
|
||||
|
||||
@ -310,7 +310,7 @@ enum BattleMoveEffects
|
||||
EFFECT_MAX_HP_50_RECOIL,
|
||||
EFFECT_CHLOROBLAST, // Same effect as EFFECT_MAX_HP_50_RECOIL but follows the same rules as EFFECT_RECOIL
|
||||
EFFECT_EXTREME_EVOBOOST,
|
||||
EFFECT_HIT_SET_REMOVE_TERRAIN,
|
||||
EFFECT_HIT_SET_TERRAIN,
|
||||
EFFECT_DARK_VOID,
|
||||
EFFECT_VICTORY_DANCE,
|
||||
EFFECT_TEATIME,
|
||||
@ -349,6 +349,8 @@ enum BattleMoveEffects
|
||||
EFFECT_RECOIL,
|
||||
EFFECT_SMACK_DOWN,
|
||||
EFFECT_LIFE_DEW,
|
||||
EFFECT_ICE_SPINNER, // Removes terrain unless attacker is removed from field either by fainting or ejected out
|
||||
EFFECT_STEEL_ROLLER, // Will fail if there is no terrain up but removes it regardless if attacker is removed from field or not
|
||||
NUM_BATTLE_MOVE_EFFECTS,
|
||||
};
|
||||
|
||||
|
||||
@ -239,7 +239,7 @@ enum CmdVarious
|
||||
|
||||
#define PARTY_SCREEN_OPTIONAL (1 << 7) // Flag for first argument to openpartyscreen
|
||||
|
||||
// cases for Cmd_moveend
|
||||
// cases for Cmd_moveend - Order matters!
|
||||
enum MoveEndEffects
|
||||
{
|
||||
MOVEEND_SUM_DAMAGE,
|
||||
@ -280,6 +280,7 @@ enum MoveEndEffects
|
||||
MOVEEND_HIT_ESCAPE,
|
||||
MOVEEND_OPPORTUNIST, // Occurs after other stat change items/abilities to try and copy the boosts
|
||||
MOVEEND_PICKPOCKET,
|
||||
MOVEEND_REMOVE_TERRAIN,
|
||||
MOVEEND_WHITE_HERB,
|
||||
MOVEEND_CHANGED_ITEMS,
|
||||
MOVEEND_SAME_MOVE_TURNS,
|
||||
@ -294,11 +295,6 @@ enum MoveEndEffects
|
||||
#define B_SWITCH_HIT 1 // dragon tail, circle throw
|
||||
#define B_SWITCH_RED_CARD 2
|
||||
|
||||
// Argument labels for EFFECT_HIT_SET_REMOVE_TERRAIN
|
||||
#define ARG_SET_PSYCHIC_TERRAIN 0
|
||||
#define ARG_TRY_REMOVE_TERRAIN_HIT 1
|
||||
#define ARG_TRY_REMOVE_TERRAIN_FAIL 2
|
||||
|
||||
enum StatusTrigger
|
||||
{
|
||||
TRIGGER_ON_MOVE,
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
#ifndef GUARD_CONSTANTS_EXPANSION_H
|
||||
#define GUARD_CONSTANTS_EXPANSION_H
|
||||
|
||||
// Last version: 1.12.0
|
||||
// Last version: 1.12.1
|
||||
#define EXPANSION_VERSION_MAJOR 1
|
||||
#define EXPANSION_VERSION_MINOR 13
|
||||
#define EXPANSION_VERSION_PATCH 0
|
||||
|
||||
@ -505,6 +505,11 @@ static inline enum ProtectMethod GetMoveProtectMethod(u32 moveId)
|
||||
return gMovesInfo[SanitizeMoveId(moveId)].argument.protectMethod;
|
||||
}
|
||||
|
||||
static inline u32 GetMoveTerrainFlag(u32 moveId)
|
||||
{
|
||||
return gMovesInfo[SanitizeMoveId(moveId)].argument.moveProperty;
|
||||
}
|
||||
|
||||
static inline u32 GetMoveEffectArg_Status(u32 moveId)
|
||||
{
|
||||
return gMovesInfo[SanitizeMoveId(moveId)].argument.status;
|
||||
|
||||
0
remove_terrain.log
Normal file
0
remove_terrain.log
Normal file
@ -561,8 +561,8 @@ bool32 IsDamageMoveUnusable(struct DamageContext *ctx)
|
||||
if (!IS_BATTLER_OF_TYPE(ctx->battlerAtk, GetMoveArgType(ctx->move)))
|
||||
return TRUE;
|
||||
break;
|
||||
case EFFECT_HIT_SET_REMOVE_TERRAIN:
|
||||
if (!(gFieldStatuses & STATUS_FIELD_TERRAIN_ANY) && GetMoveEffectArg_MoveProperty(ctx->move) == ARG_TRY_REMOVE_TERRAIN_FAIL)
|
||||
case EFFECT_STEEL_ROLLER:
|
||||
if (!(gFieldStatuses & STATUS_FIELD_TERRAIN_ANY))
|
||||
return TRUE;
|
||||
break;
|
||||
case EFFECT_POLTERGEIST:
|
||||
|
||||
@ -3199,6 +3199,7 @@ void SwitchInClearSetData(u32 battler)
|
||||
gDisableStructs[battler].perishSongTimer = disableStructCopy.perishSongTimer;
|
||||
gDisableStructs[battler].battlerPreventingEscape = disableStructCopy.battlerPreventingEscape;
|
||||
gDisableStructs[battler].embargoTimer = disableStructCopy.embargoTimer;
|
||||
gDisableStructs[battler].healBlockTimer = disableStructCopy.healBlockTimer;
|
||||
}
|
||||
else if (effect == EFFECT_SHED_TAIL)
|
||||
{
|
||||
|
||||
@ -65,6 +65,8 @@
|
||||
#include "constants/pokemon.h"
|
||||
#include "config/battle.h"
|
||||
#include "data/battle_move_effects.h"
|
||||
#include "follower_npc.h"
|
||||
#include "load_save.h"
|
||||
|
||||
// table to avoid ugly powing on gba (courtesy of doesnt)
|
||||
// this returns (i^2.5)/4
|
||||
@ -493,7 +495,7 @@ static void Cmd_tryconversiontypechange(void);
|
||||
static void Cmd_givepaydaymoney(void);
|
||||
static void Cmd_setlightscreen(void);
|
||||
static void Cmd_tryKO(void);
|
||||
static void Cmd_unused_0x94(void);
|
||||
static void Cmd_checknonvolatiletrigger(void);
|
||||
static void Cmd_copybidedmg(void);
|
||||
static void Cmd_unused_96(void);
|
||||
static void Cmd_tryinfatuating(void);
|
||||
@ -752,7 +754,7 @@ void (*const gBattleScriptingCommandsTable[])(void) =
|
||||
Cmd_givepaydaymoney, //0x91
|
||||
Cmd_setlightscreen, //0x92
|
||||
Cmd_tryKO, //0x93
|
||||
Cmd_unused_0x94, //0x94
|
||||
Cmd_checknonvolatiletrigger, //0x94
|
||||
Cmd_copybidedmg, //0x95
|
||||
Cmd_unused_96, //0x96
|
||||
Cmd_tryinfatuating, //0x97
|
||||
@ -1382,7 +1384,7 @@ static void Cmd_attackcanceler(void)
|
||||
&& effect != EFFECT_COUNTER
|
||||
&& effect != EFFECT_UPPER_HAND)
|
||||
{
|
||||
if (IsMoveMakingContact(gCurrentMove, gBattlerAttacker))
|
||||
if (!CanBattlerAvoidContactEffects(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerAttacker), GetBattlerHoldEffect(gBattlerAttacker, TRUE), gCurrentMove))
|
||||
gProtectStructs[gBattlerAttacker].touchedProtectLike = TRUE;
|
||||
CancelMultiTurnMoves(gBattlerAttacker, SKY_DROP_ATTACKCANCELLER_CHECK);
|
||||
gBattleStruct->moveResultFlags[gBattlerTarget] |= MOVE_RESULT_MISSED;
|
||||
@ -1398,7 +1400,7 @@ static void Cmd_attackcanceler(void)
|
||||
gBattleCommunication[MISS_TYPE] = B_MSG_PROTECTED;
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
}
|
||||
else if (gProtectStructs[gBattlerTarget].beakBlastCharge && IsMoveMakingContact(gCurrentMove, gBattlerAttacker))
|
||||
else if (gProtectStructs[gBattlerTarget].beakBlastCharge && !CanBattlerAvoidContactEffects(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerAttacker), GetBattlerHoldEffect(gBattlerAttacker, TRUE), gCurrentMove))
|
||||
{
|
||||
gProtectStructs[gBattlerAttacker].touchedProtectLike = TRUE;
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
@ -3775,7 +3777,12 @@ void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certai
|
||||
}
|
||||
break;
|
||||
case MOVE_EFFECT_BUG_BITE:
|
||||
if (GetItemPocket(gBattleMons[gEffectBattler].item) == POCKET_BERRIES
|
||||
if (GetBattlerHoldEffect(gEffectBattler, TRUE) == HOLD_EFFECT_JABOCA_BERRY)
|
||||
{
|
||||
// jaboca berry triggers instead of being stolen
|
||||
gBattlescriptCurrInstr++;
|
||||
}
|
||||
else if (GetItemPocket(gBattleMons[gEffectBattler].item) == POCKET_BERRIES
|
||||
&& battlerAbility != ABILITY_STICKY_HOLD)
|
||||
{
|
||||
// target loses their berry
|
||||
@ -7064,7 +7071,7 @@ static void Cmd_moveend(void)
|
||||
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(gCurrentMove, gBattlerAttacker) // Pickpocket requires contact
|
||||
&& IsMoveMakingContact(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerAttacker), GetBattlerHoldEffect(gBattlerAttacker, TRUE), gCurrentMove) // Pickpocket requires contact
|
||||
&& !(gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_NO_EFFECT)) // Obviously attack needs to have worked
|
||||
{
|
||||
u8 battlers[4] = {0, 1, 2, 3};
|
||||
@ -7173,6 +7180,24 @@ static void Cmd_moveend(void)
|
||||
else
|
||||
gBattleScripting.moveendState++;
|
||||
break;
|
||||
case MOVEEND_REMOVE_TERRAIN:
|
||||
if (GetMoveEffect(gChosenMove) == EFFECT_STEEL_ROLLER // Steel Roller has to check the chosen move, Otherwise it would fail in certain cases
|
||||
&& IsBattlerTurnDamaged(gBattlerTarget))
|
||||
{
|
||||
BattleScriptPushCursor();
|
||||
gBattlescriptCurrInstr = BattleScript_RemoveTerrain;
|
||||
effect = TRUE;
|
||||
}
|
||||
else if (moveEffect == EFFECT_ICE_SPINNER
|
||||
&& IsBattlerAlive(gBattlerAttacker)
|
||||
&& IsBattlerTurnDamaged(gBattlerTarget))
|
||||
{
|
||||
BattleScriptPushCursor();
|
||||
gBattlescriptCurrInstr = BattleScript_RemoveTerrain;
|
||||
effect = TRUE;
|
||||
}
|
||||
gBattleScripting.moveendState++;
|
||||
break;
|
||||
case MOVEEND_SYMBIOSIS:
|
||||
for (i = 0; i < gBattlersCount; i++)
|
||||
{
|
||||
@ -8994,7 +9019,6 @@ static bool32 TrySymbiosis(u32 battler, u32 itemId)
|
||||
BestowItem(BATTLE_PARTNER(battler), battler);
|
||||
gLastUsedAbility = gBattleMons[BATTLE_PARTNER(battler)].ability;
|
||||
gBattleScripting.battler = gBattlerAbility = BATTLE_PARTNER(battler);
|
||||
gBattlerAttacker = battler;
|
||||
BattleScriptPush(gBattlescriptCurrInstr + 2);
|
||||
gBattlescriptCurrInstr = BattleScript_SymbiosisActivates;
|
||||
return TRUE;
|
||||
@ -11554,9 +11578,14 @@ static void Cmd_jumpifnexttargetvalid(void)
|
||||
}
|
||||
|
||||
if (gBattlerTarget >= gBattlersCount)
|
||||
{
|
||||
gBattlerTarget = gBattlersCount - 1;
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
}
|
||||
else
|
||||
{
|
||||
gBattlescriptCurrInstr = jumpInstr;
|
||||
}
|
||||
}
|
||||
|
||||
static void Cmd_tryhealhalfhealth(void)
|
||||
@ -12471,12 +12500,13 @@ static void Cmd_trynonvolatilestatus(void)
|
||||
CMD_ARGS();
|
||||
bool32 canInflictStatus = TRUE;
|
||||
|
||||
if (!CanSetNonVolatileStatus(gBattlerAttacker,
|
||||
gBattlerTarget,
|
||||
GetBattlerAbility(gBattlerAttacker),
|
||||
GetBattlerAbility(gBattlerTarget),
|
||||
GetMoveNonVolatileStatus(gCurrentMove),
|
||||
STATUS_RUN_SCRIPT))
|
||||
if (!CanSetNonVolatileStatus(
|
||||
gBattlerAttacker,
|
||||
gBattlerTarget,
|
||||
GetBattlerAbility(gBattlerAttacker),
|
||||
GetBattlerAbility(gBattlerTarget),
|
||||
GetMoveNonVolatileStatus(gCurrentMove),
|
||||
STATUS_RUN_SCRIPT))
|
||||
canInflictStatus = FALSE;
|
||||
|
||||
if (canInflictStatus && DoesSubstituteBlockMove(gBattlerAttacker, gBattlerTarget, gCurrentMove))
|
||||
@ -12926,8 +12956,22 @@ static void Cmd_tryKO(void)
|
||||
#undef FOCUS_BANDED
|
||||
#undef AFFECTION_ENDURED
|
||||
|
||||
static void Cmd_unused_0x94(void)
|
||||
static void Cmd_checknonvolatiletrigger(void)
|
||||
{
|
||||
CMD_ARGS(u16 nonVolatile, const u8 *failInstr);
|
||||
|
||||
if (!CanSetNonVolatileStatus(
|
||||
gBattlerAttacker,
|
||||
gBattlerTarget,
|
||||
GetBattlerAbility(gBattlerAttacker),
|
||||
GetBattlerAbility(gBattlerTarget),
|
||||
cmd->nonVolatile,
|
||||
STATUS_CHECK_TRIGGER))
|
||||
gBattlescriptCurrInstr = cmd->failInstr;
|
||||
else if (DoesSubstituteBlockMove(gBattlerAttacker, gBattlerTarget, gCurrentMove))
|
||||
gBattlescriptCurrInstr = cmd->failInstr;
|
||||
else
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
}
|
||||
|
||||
static void Cmd_copybidedmg(void)
|
||||
@ -15942,6 +15986,9 @@ static void Cmd_givecaughtmon(void)
|
||||
{
|
||||
CMD_ARGS(const u8 *passInstr);
|
||||
enum GiveCaughtMonStates state = gBattleCommunication[MULTIUSE_STATE];
|
||||
// Restore players party in order to handle properly the case when a wild mon is caught.
|
||||
if (IsNPCFollowerWildBattle())
|
||||
LoadPlayerParty();
|
||||
|
||||
switch (state)
|
||||
{
|
||||
@ -16082,6 +16129,9 @@ static void Cmd_givecaughtmon(void)
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Save the player's party again to not interferes with RestorePartyAfterFollowerNPCBattle() called after battle.
|
||||
if (IsNPCFollowerWildBattle())
|
||||
SavePlayerParty();
|
||||
}
|
||||
|
||||
static void Cmd_trysetcaughtmondexflags(void)
|
||||
@ -17183,17 +17233,7 @@ void BS_ApplySaltCure(void)
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
}
|
||||
|
||||
void BS_JumpIfMovePropertyArgument(void)
|
||||
{
|
||||
NATIVE_ARGS(u8 argument, const u8 *jumpInstr);
|
||||
|
||||
if (GetMoveEffectArg_MoveProperty(gCurrentMove) == cmd->argument)
|
||||
gBattlescriptCurrInstr = cmd->jumpInstr;
|
||||
else
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
}
|
||||
|
||||
void BS_SetRemoveTerrain(void)
|
||||
void BS_SetTerrain(void)
|
||||
{
|
||||
NATIVE_ARGS(const u8 *jumpInstr);
|
||||
u32 statusFlag = 0;
|
||||
@ -17216,48 +17256,19 @@ void BS_SetRemoveTerrain(void)
|
||||
statusFlag = STATUS_FIELD_PSYCHIC_TERRAIN;
|
||||
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_TERRAIN_SET_PSYCHIC;
|
||||
break;
|
||||
case EFFECT_HIT_SET_REMOVE_TERRAIN:
|
||||
switch (GetMoveEffectArg_MoveProperty(gCurrentMove))
|
||||
{
|
||||
case ARG_SET_PSYCHIC_TERRAIN: // Genesis Supernova
|
||||
statusFlag = STATUS_FIELD_PSYCHIC_TERRAIN;
|
||||
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_TERRAIN_SET_PSYCHIC;
|
||||
break;
|
||||
case ARG_TRY_REMOVE_TERRAIN_HIT: // Splintered Stormshards
|
||||
case ARG_TRY_REMOVE_TERRAIN_FAIL: // Steel Roller
|
||||
if (!(gFieldStatuses & STATUS_FIELD_TERRAIN_ANY))
|
||||
{
|
||||
// No terrain to remove, jump to battle script pointer.
|
||||
gBattlescriptCurrInstr = cmd->jumpInstr;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Remove all terrains.
|
||||
RemoveAllTerrains();
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
}
|
||||
return;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
case EFFECT_HIT_SET_TERRAIN:
|
||||
statusFlag = GetMoveTerrainFlag(gCurrentMove);
|
||||
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_TERRAIN_SET_PSYCHIC;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
enum ItemHoldEffect atkHoldEffect = GetBattlerHoldEffect(gBattlerAttacker, TRUE);
|
||||
|
||||
if (gFieldStatuses & statusFlag || statusFlag == 0)
|
||||
{
|
||||
gBattlescriptCurrInstr = cmd->jumpInstr;
|
||||
}
|
||||
else
|
||||
{
|
||||
enum ItemHoldEffect atkHoldEffect = GetBattlerHoldEffect(gBattlerAttacker, TRUE);
|
||||
|
||||
gFieldStatuses &= ~STATUS_FIELD_TERRAIN_ANY;
|
||||
gFieldStatuses |= statusFlag;
|
||||
gFieldTimers.terrainTimer = gBattleTurnCounter + (atkHoldEffect == HOLD_EFFECT_TERRAIN_EXTENDER) ? 8 : 5;
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
}
|
||||
gFieldStatuses &= ~STATUS_FIELD_TERRAIN_ANY;
|
||||
gFieldStatuses |= statusFlag;
|
||||
gFieldTimers.terrainTimer = gBattleTurnCounter + (atkHoldEffect == HOLD_EFFECT_TERRAIN_EXTENDER) ? 8 : 5;
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
}
|
||||
|
||||
void BS_JumpIfTerrainAffected(void)
|
||||
|
||||
@ -4488,8 +4488,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
|
||||
case ABILITY_MUMMY:
|
||||
if (IsBattlerAlive(gBattlerAttacker)
|
||||
&& IsBattlerTurnDamaged(gBattlerTarget)
|
||||
&& GetBattlerHoldEffect(gBattlerAttacker, TRUE) != HOLD_EFFECT_PROTECTIVE_PADS
|
||||
&& IsMoveMakingContact(move, gBattlerAttacker)
|
||||
&& !CanBattlerAvoidContactEffects(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerAttacker), GetBattlerHoldEffect(gBattlerAttacker, TRUE), move)
|
||||
&& gDisableStructs[gBattlerAttacker].overwrittenAbility != GetBattlerAbility(gBattlerTarget)
|
||||
&& gBattleMons[gBattlerAttacker].ability != ABILITY_MUMMY
|
||||
&& gBattleMons[gBattlerAttacker].ability != ABILITY_LINGERING_AROMA
|
||||
@ -4511,8 +4510,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
|
||||
case ABILITY_WANDERING_SPIRIT:
|
||||
if (IsBattlerAlive(gBattlerAttacker)
|
||||
&& IsBattlerTurnDamaged(gBattlerTarget)
|
||||
&& GetBattlerHoldEffect(gBattlerAttacker, TRUE) != HOLD_EFFECT_PROTECTIVE_PADS
|
||||
&& IsMoveMakingContact(move, gBattlerAttacker)
|
||||
&& !CanBattlerAvoidContactEffects(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerAttacker), GetBattlerHoldEffect(gBattlerAttacker, TRUE), move)
|
||||
&& !(GetActiveGimmick(gBattlerTarget) == GIMMICK_DYNAMAX)
|
||||
&& !gAbilitiesInfo[gBattleMons[gBattlerAttacker].ability].cantBeSwapped)
|
||||
{
|
||||
@ -4562,8 +4560,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
|
||||
&& (CompareStat(gBattlerAttacker, STAT_SPEED, MIN_STAT_STAGE, CMP_GREATER_THAN) || GetBattlerAbility(gBattlerAttacker) == ABILITY_MIRROR_ARMOR)
|
||||
&& !gProtectStructs[gBattlerAttacker].confusionSelfDmg
|
||||
&& IsBattlerTurnDamaged(gBattlerTarget)
|
||||
&& GetBattlerHoldEffect(gBattlerAttacker, TRUE) != HOLD_EFFECT_PROTECTIVE_PADS
|
||||
&& IsMoveMakingContact(move, gBattlerAttacker))
|
||||
&& !CanBattlerAvoidContactEffects(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerAttacker), GetBattlerHoldEffect(gBattlerAttacker, TRUE), move))
|
||||
{
|
||||
SET_STATCHANGER(STAT_SPEED, 1, TRUE);
|
||||
PREPARE_ABILITY_BUFFER(gBattleTextBuff1, gLastUsedAbility);
|
||||
@ -4577,8 +4574,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
|
||||
if (IsBattlerAlive(gBattlerAttacker)
|
||||
&& !gProtectStructs[gBattlerAttacker].confusionSelfDmg
|
||||
&& IsBattlerTurnDamaged(gBattlerTarget)
|
||||
&& GetBattlerHoldEffect(gBattlerAttacker, TRUE) != HOLD_EFFECT_PROTECTIVE_PADS
|
||||
&& IsMoveMakingContact(move, gBattlerAttacker))
|
||||
&& !CanBattlerAvoidContactEffects(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerAttacker), GetBattlerHoldEffect(gBattlerAttacker, TRUE), move))
|
||||
{
|
||||
gBattleStruct->moveDamage[gBattlerAttacker] = GetNonDynamaxMaxHP(gBattlerAttacker) / (B_ROUGH_SKIN_DMG >= GEN_4 ? 8 : 16);
|
||||
if (gBattleStruct->moveDamage[gBattlerAttacker] == 0)
|
||||
@ -4592,8 +4588,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
|
||||
if (!(gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_NO_EFFECT)
|
||||
&& !IsBattlerAlive(gBattlerTarget)
|
||||
&& IsBattlerAlive(gBattlerAttacker)
|
||||
&& GetBattlerHoldEffect(gBattlerAttacker, TRUE) != HOLD_EFFECT_PROTECTIVE_PADS
|
||||
&& IsMoveMakingContact(move, gBattlerAttacker))
|
||||
&& !CanBattlerAvoidContactEffects(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerAttacker), GetBattlerHoldEffect(gBattlerAttacker, TRUE), move))
|
||||
{
|
||||
if ((battler = IsAbilityOnField(ABILITY_DAMP)))
|
||||
{
|
||||
@ -4658,8 +4653,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
|
||||
&& !gProtectStructs[gBattlerAttacker].confusionSelfDmg
|
||||
&& IsBattlerTurnDamaged(gBattlerTarget)
|
||||
&& CanBeSlept(gBattlerAttacker, gBattlerTarget, ability, NOT_BLOCKED_BY_SLEEP_CLAUSE)
|
||||
&& GetBattlerHoldEffect(gBattlerAttacker, TRUE) != HOLD_EFFECT_PROTECTIVE_PADS
|
||||
&& IsMoveMakingContact(move, gBattlerAttacker))
|
||||
&& !CanBattlerAvoidContactEffects(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerAttacker), GetBattlerHoldEffect(gBattlerAttacker, TRUE), move))
|
||||
{
|
||||
if (IsSleepClauseEnabled())
|
||||
gBattleStruct->battlerState[gBattlerAttacker].sleepClauseEffectExempt = TRUE;
|
||||
@ -4681,8 +4675,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
|
||||
&& !gProtectStructs[gBattlerAttacker].confusionSelfDmg
|
||||
&& IsBattlerTurnDamaged(gBattlerTarget)
|
||||
&& CanBePoisoned(gBattlerTarget, gBattlerAttacker, gLastUsedAbility, GetBattlerAbility(gBattlerAttacker))
|
||||
&& GetBattlerHoldEffect(gBattlerAttacker, TRUE) != HOLD_EFFECT_PROTECTIVE_PADS
|
||||
&& IsMoveMakingContact(move, gBattlerAttacker))
|
||||
&& !CanBattlerAvoidContactEffects(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerAttacker), GetBattlerHoldEffect(gBattlerAttacker, TRUE), move))
|
||||
{
|
||||
gEffectBattler = gBattlerAttacker;
|
||||
gBattleScripting.battler = gBattlerTarget;
|
||||
@ -4701,8 +4694,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
|
||||
&& !gProtectStructs[gBattlerAttacker].confusionSelfDmg
|
||||
&& IsBattlerTurnDamaged(gBattlerTarget)
|
||||
&& CanBeParalyzed(gBattlerTarget, gBattlerAttacker, GetBattlerAbility(gBattlerAttacker))
|
||||
&& GetBattlerHoldEffect(gBattlerAttacker, TRUE) != HOLD_EFFECT_PROTECTIVE_PADS
|
||||
&& IsMoveMakingContact(move, gBattlerAttacker))
|
||||
&& !CanBattlerAvoidContactEffects(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerAttacker), GetBattlerHoldEffect(gBattlerAttacker, TRUE), move))
|
||||
{
|
||||
gEffectBattler = gBattlerAttacker;
|
||||
gBattleScripting.battler = gBattlerTarget;
|
||||
@ -4716,8 +4708,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
|
||||
case ABILITY_FLAME_BODY:
|
||||
if (IsBattlerAlive(gBattlerAttacker)
|
||||
&& !gProtectStructs[gBattlerAttacker].confusionSelfDmg
|
||||
&& GetBattlerHoldEffect(gBattlerAttacker, TRUE) != HOLD_EFFECT_PROTECTIVE_PADS
|
||||
&& (IsMoveMakingContact(move, gBattlerAttacker))
|
||||
&& !CanBattlerAvoidContactEffects(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerAttacker), GetBattlerHoldEffect(gBattlerAttacker, TRUE), move)
|
||||
&& IsBattlerTurnDamaged(gBattlerTarget)
|
||||
&& CanBeBurned(gBattlerTarget, gBattlerAttacker, GetBattlerAbility(gBattlerAttacker))
|
||||
&& (B_ABILITY_TRIGGER_CHANCE >= GEN_4 ? RandomPercentage(RNG_FLAME_BODY, 30) : RandomChance(RNG_FLAME_BODY, 1, 3)))
|
||||
@ -4738,9 +4729,8 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
|
||||
&& (B_ABILITY_TRIGGER_CHANCE >= GEN_4 ? RandomPercentage(RNG_CUTE_CHARM, 30) : RandomChance(RNG_CUTE_CHARM, 1, 3))
|
||||
&& !(gBattleMons[gBattlerAttacker].status2 & STATUS2_INFATUATION)
|
||||
&& AreBattlersOfOppositeGender(gBattlerAttacker, gBattlerTarget)
|
||||
&& GetBattlerHoldEffect(gBattlerAttacker, TRUE) != HOLD_EFFECT_PROTECTIVE_PADS
|
||||
&& IsMoveMakingContact(move, gBattlerAttacker)
|
||||
&& !IsAbilityAndRecord(gBattlerAttacker, GetBattlerAbility(gBattlerAttacker), ABILITY_OBLIVIOUS)
|
||||
&& !CanBattlerAvoidContactEffects(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerAttacker), GetBattlerHoldEffect(gBattlerAttacker, TRUE), move)
|
||||
&& !IsAbilityOnSide(gBattlerAttacker, ABILITY_AROMA_VEIL))
|
||||
{
|
||||
gBattleMons[gBattlerAttacker].status2 |= STATUS2_INFATUATED_WITH(gBattlerTarget);
|
||||
@ -4800,8 +4790,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
|
||||
if (!gProtectStructs[gBattlerAttacker].confusionSelfDmg
|
||||
&& IsBattlerTurnDamaged(gBattlerTarget)
|
||||
&& IsBattlerAlive(battler)
|
||||
&& GetBattlerHoldEffect(gBattlerAttacker, TRUE) != HOLD_EFFECT_PROTECTIVE_PADS
|
||||
&& (IsMoveMakingContact(move, gBattlerAttacker))
|
||||
&& !CanBattlerAvoidContactEffects(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerAttacker), GetBattlerHoldEffect(gBattlerAttacker, TRUE), move)
|
||||
&& !(gStatuses3[gBattlerAttacker] & STATUS3_PERISH_SONG))
|
||||
{
|
||||
if (!(gStatuses3[battler] & STATUS3_PERISH_SONG))
|
||||
@ -4911,8 +4900,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
|
||||
if (IsBattlerAlive(gBattlerTarget)
|
||||
&& !gProtectStructs[gBattlerAttacker].confusionSelfDmg
|
||||
&& CanBePoisoned(gBattlerAttacker, gBattlerTarget, gLastUsedAbility, GetBattlerAbility(gBattlerTarget))
|
||||
&& GetBattlerHoldEffect(gBattlerAttacker, TRUE) != HOLD_EFFECT_PROTECTIVE_PADS
|
||||
&& IsMoveMakingContact(move, gBattlerAttacker)
|
||||
&& !CanBattlerAvoidContactEffects(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerAttacker), GetBattlerHoldEffect(gBattlerAttacker, TRUE), move)
|
||||
&& IsBattlerTurnDamaged(gBattlerTarget) // Need to actually hit the target
|
||||
&& RandomPercentage(RNG_POISON_TOUCH, 30))
|
||||
{
|
||||
@ -7063,8 +7051,7 @@ u32 ItemBattleEffects(enum ItemCaseId caseID, u32 battler)
|
||||
break;
|
||||
case HOLD_EFFECT_ROCKY_HELMET:
|
||||
if (IsBattlerTurnDamaged(gBattlerTarget)
|
||||
&& GetBattlerHoldEffect(gBattlerAttacker, TRUE) != HOLD_EFFECT_PROTECTIVE_PADS
|
||||
&& IsMoveMakingContact(gCurrentMove, gBattlerAttacker)
|
||||
&& !CanBattlerAvoidContactEffects(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerAttacker), GetBattlerHoldEffect(gBattlerAttacker, TRUE), gCurrentMove)
|
||||
&& IsBattlerAlive(gBattlerAttacker)
|
||||
&& GetBattlerAbility(gBattlerAttacker) != ABILITY_MAGIC_GUARD)
|
||||
{
|
||||
@ -7187,8 +7174,8 @@ u32 ItemBattleEffects(enum ItemCaseId caseID, u32 battler)
|
||||
break;
|
||||
case HOLD_EFFECT_STICKY_BARB:
|
||||
if (IsBattlerTurnDamaged(gBattlerTarget)
|
||||
&& GetBattlerHoldEffect(gBattlerAttacker, TRUE) != HOLD_EFFECT_PROTECTIVE_PADS
|
||||
&& IsMoveMakingContact(gCurrentMove, gBattlerAttacker)
|
||||
&& !(gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_NO_EFFECT)
|
||||
&& !CanBattlerAvoidContactEffects(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerAttacker), GetBattlerHoldEffect(gBattlerAttacker, TRUE), gCurrentMove)
|
||||
&& !DoesSubstituteBlockMove(gBattlerAttacker, battler, gCurrentMove)
|
||||
&& IsBattlerAlive(gBattlerAttacker)
|
||||
&& CanStealItem(gBattlerAttacker, gBattlerTarget, gBattleMons[gBattlerTarget].item)
|
||||
@ -7550,26 +7537,35 @@ u32 GetBattlerHoldEffectParam(u32 battler)
|
||||
return GetItemHoldEffectParam(gBattleMons[battler].item);
|
||||
}
|
||||
|
||||
bool32 IsMoveMakingContact(u32 move, u32 battlerAtk)
|
||||
bool32 CanBattlerAvoidContactEffects(u32 battlerAtk, u32 battlerDef, u32 abilityAtk, enum ItemHoldEffect holdEffectAtk, u32 move)
|
||||
{
|
||||
enum ItemHoldEffect atkHoldEffect = GetBattlerHoldEffect(battlerAtk, TRUE);
|
||||
|
||||
if (!MoveMakesContact(move))
|
||||
if (holdEffectAtk == HOLD_EFFECT_PROTECTIVE_PADS)
|
||||
{
|
||||
if (GetMoveEffect(move) == EFFECT_SHELL_SIDE_ARM && gBattleStruct->shellSideArmCategory[battlerAtk][gBattlerTarget] == DAMAGE_CATEGORY_PHYSICAL)
|
||||
return TRUE;
|
||||
else
|
||||
return FALSE;
|
||||
RecordItemEffectBattle(battlerAtk, HOLD_EFFECT_PROTECTIVE_PADS);
|
||||
return TRUE;
|
||||
}
|
||||
else if ((atkHoldEffect == HOLD_EFFECT_PUNCHING_GLOVE && IsPunchingMove(move))
|
||||
|| GetBattlerAbility(battlerAtk) == ABILITY_LONG_REACH)
|
||||
|
||||
return !IsMoveMakingContact(battlerAtk, battlerDef, abilityAtk, holdEffectAtk, move);
|
||||
}
|
||||
|
||||
bool32 IsMoveMakingContact(u32 battlerAtk, u32 battlerDef, u32 abilityAtk, enum ItemHoldEffect holdEffectAtk, u32 move)
|
||||
{
|
||||
if (!(MoveMakesContact(move) || (GetMoveEffect(move) == EFFECT_SHELL_SIDE_ARM
|
||||
&& gBattleStruct->shellSideArmCategory[battlerAtk][battlerDef] == DAMAGE_CATEGORY_PHYSICAL)))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
else if (holdEffectAtk == HOLD_EFFECT_PUNCHING_GLOVE && IsPunchingMove(move))
|
||||
{
|
||||
return TRUE;
|
||||
RecordItemEffectBattle(battlerAtk, HOLD_EFFECT_PUNCHING_GLOVE);
|
||||
return FALSE;
|
||||
}
|
||||
else if (abilityAtk == ABILITY_LONG_REACH)
|
||||
{
|
||||
RecordAbilityBattle(battlerAtk, ABILITY_LONG_REACH);
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static inline bool32 IsSideProtected(u32 battler, enum ProtectMethod method)
|
||||
@ -7588,7 +7584,8 @@ bool32 IsBattlerProtected(u32 battlerAtk, u32 battlerDef, u32 move)
|
||||
{
|
||||
if (IsZMove(move) || IsMaxMove(move))
|
||||
return FALSE; // Z-Moves and Max Moves bypass protection (except Max Guard).
|
||||
if (IsMoveMakingContact(move, battlerAtk) && IsAbilityAndRecord(battlerAtk, GetBattlerAbility(battlerAtk), ABILITY_UNSEEN_FIST))
|
||||
if (GetBattlerAbility(battlerAtk) == ABILITY_UNSEEN_FIST
|
||||
&& IsMoveMakingContact(battlerAtk, battlerDef, ABILITY_UNSEEN_FIST, GetBattlerHoldEffect(battlerAtk, TRUE), move))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@ -8321,7 +8318,7 @@ static inline u32 CalcMoveBasePowerAfterModifiers(struct DamageContext *ctx)
|
||||
modifier = uq4_12_multiply(modifier, UQ_4_12(1.3));
|
||||
break;
|
||||
case ABILITY_TOUGH_CLAWS:
|
||||
if (IsMoveMakingContact(move, battlerAtk))
|
||||
if (IsMoveMakingContact(battlerAtk, battlerDef, ctx->abilityAtk, ctx->holdEffectAtk, ctx->move))
|
||||
modifier = uq4_12_multiply(modifier, UQ_4_12(1.3));
|
||||
break;
|
||||
case ABILITY_STRONG_JAW:
|
||||
@ -9154,12 +9151,12 @@ static inline uq4_12_t GetDefenderAbilitiesModifier(struct DamageContext *ctx)
|
||||
}
|
||||
break;
|
||||
case ABILITY_FLUFFY:
|
||||
if (!IsMoveMakingContact(ctx->move, ctx->battlerAtk) && ctx->moveType == TYPE_FIRE)
|
||||
if (ctx->moveType == TYPE_FIRE && !IsMoveMakingContact(ctx->battlerAtk, ctx->battlerDef, ABILITY_NONE, ctx->holdEffectAtk, ctx->move))
|
||||
{
|
||||
modifier = UQ_4_12(2.0);
|
||||
recordAbility = TRUE;
|
||||
}
|
||||
else if (IsMoveMakingContact(ctx->move, ctx->battlerAtk) && ctx->moveType != TYPE_FIRE)
|
||||
if (ctx->moveType != TYPE_FIRE && IsMoveMakingContact(ctx->battlerAtk, ctx->battlerDef, ABILITY_NONE, ctx->holdEffectAtk, ctx->move))
|
||||
{
|
||||
modifier = UQ_4_12(0.5);
|
||||
recordAbility = TRUE;
|
||||
|
||||
@ -1978,9 +1978,9 @@ const struct BattleMoveEffect gBattleMoveEffects[NUM_BATTLE_MOVE_EFFECTS] =
|
||||
.battleTvScore = 0, // TODO: Assign points
|
||||
},
|
||||
|
||||
[EFFECT_HIT_SET_REMOVE_TERRAIN] =
|
||||
[EFFECT_HIT_SET_TERRAIN] =
|
||||
{
|
||||
.battleScript = BattleScript_EffectHitSetRemoveTerrain,
|
||||
.battleScript = BattleScript_EffectHitSetTerrain,
|
||||
.battleTvScore = 0, // TODO: Assign points
|
||||
},
|
||||
|
||||
@ -2218,4 +2218,16 @@ const struct BattleMoveEffect gBattleMoveEffects[NUM_BATTLE_MOVE_EFFECTS] =
|
||||
.battleScript = BattleScript_EffectLifeDew,
|
||||
.battleTvScore = 0, // TODO: Assign points
|
||||
},
|
||||
|
||||
[EFFECT_ICE_SPINNER] =
|
||||
{
|
||||
.battleScript = BattleScript_EffectHit,
|
||||
.battleTvScore = 0, // TODO: Assign points
|
||||
},
|
||||
|
||||
[EFFECT_STEEL_ROLLER] =
|
||||
{
|
||||
.battleScript = BattleScript_EffectSteelRoller,
|
||||
.battleTvScore = 0, // TODO: Assign points
|
||||
},
|
||||
};
|
||||
|
||||
@ -18449,7 +18449,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] =
|
||||
.description = COMPOUND_STRING(
|
||||
"Destroys terrain. Fails if\n"
|
||||
"ground isn't terrain."),
|
||||
.effect = EFFECT_HIT_SET_REMOVE_TERRAIN,
|
||||
.effect = EFFECT_STEEL_ROLLER,
|
||||
.power = 130,
|
||||
.type = TYPE_STEEL,
|
||||
.accuracy = 100,
|
||||
@ -18458,7 +18458,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] =
|
||||
.priority = 0,
|
||||
.category = DAMAGE_CATEGORY_PHYSICAL,
|
||||
.makesContact = TRUE,
|
||||
.argument = { .moveProperty = ARG_TRY_REMOVE_TERRAIN_FAIL }, // Remove a field terrain if there is one and hit, otherwise fail.
|
||||
.skyBattleBanned = TRUE,
|
||||
.contestEffect = CONTEST_EFFECT_WORSEN_CONDITION_OF_PREV_MONS,
|
||||
.contestCategory = CONTEST_CATEGORY_TOUGH,
|
||||
@ -19885,7 +19884,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] =
|
||||
.description = COMPOUND_STRING(
|
||||
"Ice-covered feet hit a foe\n"
|
||||
"and destroy the terrain."),
|
||||
.effect = EFFECT_HIT_SET_REMOVE_TERRAIN,
|
||||
.effect = EFFECT_ICE_SPINNER,
|
||||
.power = 80,
|
||||
.type = TYPE_ICE,
|
||||
.accuracy = 100,
|
||||
@ -19894,7 +19893,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] =
|
||||
.priority = 0,
|
||||
.category = DAMAGE_CATEGORY_PHYSICAL,
|
||||
.makesContact = TRUE,
|
||||
.argument = { .moveProperty = ARG_TRY_REMOVE_TERRAIN_HIT }, // Remove the active field terrain if there is one.
|
||||
.skyBattleBanned = B_EXTRAPOLATED_MOVE_FLAGS,
|
||||
.battleAnimScript = gBattleAnimMove_IceSpinner,
|
||||
},
|
||||
@ -21526,7 +21524,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] =
|
||||
.description = COMPOUND_STRING(
|
||||
"Mew attacks with full force.\n"
|
||||
"Psychically charges terrain."),
|
||||
.effect = EFFECT_HIT_SET_REMOVE_TERRAIN,
|
||||
.effect = EFFECT_HIT_SET_TERRAIN,
|
||||
.power = 185,
|
||||
.type = TYPE_PSYCHIC,
|
||||
.accuracy = 0,
|
||||
@ -21534,7 +21532,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] =
|
||||
.target = MOVE_TARGET_SELECTED,
|
||||
.priority = 0,
|
||||
.category = DAMAGE_CATEGORY_SPECIAL,
|
||||
.argument = { .moveProperty = ARG_SET_PSYCHIC_TERRAIN }, // Set Psychic Terrain. If there's a different field terrain active, overwrite it.
|
||||
.argument = { .moveProperty = STATUS_FIELD_PSYCHIC_TERRAIN },
|
||||
.battleAnimScript = gBattleAnimMove_GenesisSupernova,
|
||||
},
|
||||
[MOVE_SINISTER_ARROW_RAID] =
|
||||
@ -21591,7 +21589,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] =
|
||||
.description = COMPOUND_STRING(
|
||||
"Lycanroc attacks with full\n"
|
||||
"force. Removes all terrain."),
|
||||
.effect = EFFECT_HIT_SET_REMOVE_TERRAIN,
|
||||
.effect = EFFECT_ICE_SPINNER,
|
||||
.power = 190,
|
||||
.type = TYPE_ROCK,
|
||||
.accuracy = 0,
|
||||
@ -21599,7 +21597,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] =
|
||||
.target = MOVE_TARGET_SELECTED,
|
||||
.priority = 0,
|
||||
.category = DAMAGE_CATEGORY_PHYSICAL,
|
||||
.argument = { .moveProperty = ARG_TRY_REMOVE_TERRAIN_HIT }, // Remove the active field terrain if there is one.
|
||||
.battleAnimScript = gBattleAnimMove_SplinteredStormshards,
|
||||
},
|
||||
[MOVE_LETS_SNUGGLE_FOREVER] =
|
||||
|
||||
@ -1216,10 +1216,6 @@ void FollowerNPC_HandleSprite(void)
|
||||
else if (gPlayerAvatar.flags & PLAYER_AVATAR_FLAG_ACRO_BIKE)
|
||||
SetFollowerNPCSprite(FOLLOWER_NPC_SPRITE_INDEX_ACRO_BIKE);
|
||||
}
|
||||
else if (gMapHeader.mapType == MAP_TYPE_UNDERWATER)
|
||||
{
|
||||
TryUpdateFollowerNPCSpriteUnderwater();
|
||||
}
|
||||
else if (gPlayerAvatar.flags & PLAYER_AVATAR_FLAG_ON_FOOT)
|
||||
{
|
||||
SetFollowerNPCSprite(FOLLOWER_NPC_SPRITE_INDEX_NORMAL);
|
||||
|
||||
@ -21,7 +21,7 @@ SINGLE_BATTLE_TEST("Fluffy halves damage taken from moves that make direct conta
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_SCRATCH); }
|
||||
} SCENE {
|
||||
MESSAGE("Wobbuffet used Scratch!");
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_SCRATCH, player);
|
||||
HP_BAR(opponent, captureDamage: &results[i].damage);
|
||||
} FINALLY {
|
||||
EXPECT_MUL_EQ(results[0].damage, UQ_4_12(0.5), results[1].damage);
|
||||
@ -39,7 +39,7 @@ SINGLE_BATTLE_TEST("Fluffy doubles damage taken from fire type moves", s16 damag
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_EMBER); }
|
||||
} SCENE {
|
||||
MESSAGE("Wobbuffet used Ember!");
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_EMBER, player);
|
||||
HP_BAR(opponent, captureDamage: &results[i].damage);
|
||||
} FINALLY {
|
||||
EXPECT_MUL_EQ(results[0].damage, UQ_4_12(2.0), results[1].damage);
|
||||
@ -57,7 +57,43 @@ SINGLE_BATTLE_TEST("Fluffy does not alter damage of fire-type moves that make di
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_FIRE_PUNCH); }
|
||||
} SCENE {
|
||||
MESSAGE("Wobbuffet used Fire Punch!");
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_FIRE_PUNCH, player);
|
||||
HP_BAR(opponent, captureDamage: &results[i].damage);
|
||||
} FINALLY {
|
||||
EXPECT_EQ(results[0].damage, results[1].damage);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Fluffy halves damage taken from moves that make direct contact even if protected by Protective Pads", s16 damage)
|
||||
{
|
||||
u32 ability;
|
||||
PARAMETRIZE { ability = ABILITY_KLUTZ; }
|
||||
PARAMETRIZE { ability = ABILITY_FLUFFY; }
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_PROTECTIVE_PADS); }
|
||||
OPPONENT(SPECIES_STUFFUL) { Ability(ability); }
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_SCRATCH); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_SCRATCH, player);
|
||||
HP_BAR(opponent, captureDamage: &results[i].damage);
|
||||
} FINALLY {
|
||||
EXPECT_MUL_EQ(results[0].damage, UQ_4_12(0.5), results[1].damage);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Fluffy does not halve damage taken from moves that make direct contact but are ignored by Punching Glove", s16 damage)
|
||||
{
|
||||
u32 ability;
|
||||
PARAMETRIZE { ability = ABILITY_KLUTZ; }
|
||||
PARAMETRIZE { ability = ABILITY_FLUFFY; }
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_PUNCHING_GLOVE); }
|
||||
OPPONENT(SPECIES_STUFFUL) { Ability(ability); }
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_THUNDER_PUNCH); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_THUNDER_PUNCH, player);
|
||||
HP_BAR(opponent, captureDamage: &results[i].damage);
|
||||
} FINALLY {
|
||||
EXPECT_EQ(results[0].damage, results[1].damage);
|
||||
|
||||
@ -16,3 +16,17 @@ DOUBLE_BATTLE_TEST("Defrost: A fire type spread move will thaw both targets")
|
||||
STATUS_ICON(opponentRight, freeze: FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Defrost: Scald does not thaw targets if user is asleep")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET) { Status1(STATUS1_FROSTBITE); }
|
||||
OPPONENT(SPECIES_WOBBUFFET) { Status1(STATUS1_SLEEP_TURN(3)); }
|
||||
} WHEN {
|
||||
TURN { MOVE(opponent, MOVE_SCALD); MOVE(player, MOVE_CELEBRATE); }
|
||||
} SCENE {
|
||||
NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_SCALD, opponent);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, player);
|
||||
HP_BAR(player);
|
||||
}
|
||||
}
|
||||
|
||||
@ -578,7 +578,7 @@ SINGLE_BATTLE_TEST("(Z-MOVE) Extreme Evoboost boosts all the user's stats by two
|
||||
SINGLE_BATTLE_TEST("(Z-MOVE) Genesis Supernova sets up psychic terrain")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(GetMoveEffect(MOVE_GENESIS_SUPERNOVA) == EFFECT_HIT_SET_REMOVE_TERRAIN);
|
||||
ASSUME(GetMoveEffect(MOVE_GENESIS_SUPERNOVA) == EFFECT_HIT_SET_TERRAIN);
|
||||
PLAYER(SPECIES_MEW) { Item(ITEM_MEWNIUM_Z); }
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
@ -595,7 +595,7 @@ SINGLE_BATTLE_TEST("(Z-MOVE) Genesis Supernova sets up psychic terrain")
|
||||
SINGLE_BATTLE_TEST("(Z-MOVE) Splintered Stormshards removes terrain")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(GetMoveEffect(MOVE_SPLINTERED_STORMSHARDS) == EFFECT_HIT_SET_REMOVE_TERRAIN);
|
||||
ASSUME(GetMoveEffect(MOVE_SPLINTERED_STORMSHARDS) == EFFECT_ICE_SPINNER);
|
||||
PLAYER(SPECIES_LYCANROC_DUSK) { Item(ITEM_LYCANIUM_Z); }
|
||||
OPPONENT(SPECIES_TAPU_LELE) { Ability(ABILITY_PSYCHIC_SURGE); HP(1000); MaxHP(1000); }
|
||||
} WHEN {
|
||||
|
||||
@ -42,7 +42,6 @@ SINGLE_BATTLE_TEST("Jaboca Berry causes the attacker to lose 1/8 of its max HP i
|
||||
|
||||
SINGLE_BATTLE_TEST("Jaboca Berry triggers before Bug Bite can steal it")
|
||||
{
|
||||
KNOWN_FAILING;
|
||||
GIVEN {
|
||||
ASSUME(GetMoveCategory(MOVE_BUG_BITE) == DAMAGE_CATEGORY_PHYSICAL);
|
||||
PLAYER(SPECIES_WYNAUT);
|
||||
|
||||
@ -31,6 +31,23 @@ SINGLE_BATTLE_TEST("Life Orb activates if it hits a Substitute")
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Life Orb does not activate if using status move on a Substitute")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_LIFE_ORB); }
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN { MOVE(opponent, MOVE_SUBSTITUTE); MOVE(player, MOVE_GROWL); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_SUBSTITUTE, opponent);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_GROWL, player);
|
||||
NONE_OF {
|
||||
HP_BAR(player);
|
||||
MESSAGE("Wobbuffet was hurt by the Life Orb!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Life Orb does not activate if using a status move")
|
||||
{
|
||||
GIVEN {
|
||||
|
||||
@ -153,7 +153,7 @@ static void WhenSingles(u32 move, struct BattlePokemon *attacker, struct BattleP
|
||||
{ // Has to be hailing
|
||||
TURN { MOVE(attacker, MOVE_HAIL); }
|
||||
}
|
||||
else if (gMovesInfo[move].effect == EFFECT_HIT_SET_REMOVE_TERRAIN && gMovesInfo[move].argument.moveProperty == ARG_TRY_REMOVE_TERRAIN_FAIL)
|
||||
else if (gMovesInfo[move].effect == EFFECT_STEEL_ROLLER)
|
||||
{ // Needs a terrain
|
||||
TURN { MOVE(attacker, MOVE_ELECTRIC_TERRAIN); }
|
||||
}
|
||||
@ -282,7 +282,7 @@ static void DoublesWhen(u32 move, struct BattlePokemon *attacker, struct BattleP
|
||||
{ // Has to be hailing
|
||||
TURN { MOVE(attacker, MOVE_HAIL); }
|
||||
}
|
||||
else if (gMovesInfo[move].effect == EFFECT_HIT_SET_REMOVE_TERRAIN && gMovesInfo[move].argument.moveProperty == ARG_TRY_REMOVE_TERRAIN_FAIL)
|
||||
else if (gMovesInfo[move].effect == EFFECT_STEEL_ROLLER)
|
||||
{ // Needs a terrain
|
||||
TURN { MOVE(attacker, MOVE_ELECTRIC_TERRAIN); }
|
||||
}
|
||||
|
||||
@ -17,6 +17,7 @@ TO_DO_BATTLE_TEST("Assist cannot call a Mimicked move (Gen4 only)");
|
||||
TO_DO_BATTLE_TEST("Assist can call a Mimicked move but not the original Mimic (Gen5+)");
|
||||
TO_DO_BATTLE_TEST("Assist can call moves in unhatched Eggs (Gen5 only)");
|
||||
TO_DO_BATTLE_TEST("Assist can be used by wild Pokémon in Wild Double Battles, even if the partner faints");
|
||||
TO_DO_BATTLE_TEST("Assist called move does not get boosted by Normalize");
|
||||
|
||||
SINGLE_BATTLE_TEST("Assist fails if there are no valid moves to choose from")
|
||||
{
|
||||
@ -32,3 +33,27 @@ SINGLE_BATTLE_TEST("Assist fails if there are no valid moves to choose from")
|
||||
MESSAGE("But it failed!");
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Assisted move triggers correct weakness berry")
|
||||
{
|
||||
u16 item;
|
||||
PARAMETRIZE { item = ITEM_CHILAN_BERRY; }
|
||||
PARAMETRIZE { item = ITEM_PASSHO_BERRY; }
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET) { Moves(MOVE_ASSIST, MOVE_NONE, MOVE_NONE, MOVE_NONE); }
|
||||
PLAYER(SPECIES_WOBBUFFET) { Moves(MOVE_SURF, MOVE_NONE, MOVE_NONE, MOVE_NONE); }
|
||||
OPPONENT(SPECIES_ARON) { Item(item); }
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_ASSIST); }
|
||||
} SCENE {
|
||||
MESSAGE("Wobbuffet used Assist!");
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_ASSIST, player);
|
||||
MESSAGE("Wobbuffet used Surf!");
|
||||
if (item == ITEM_PASSHO_BERRY) {
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, opponent);
|
||||
} else {
|
||||
NOT ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, opponent);
|
||||
}
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_SURF, player);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,126 +0,0 @@
|
||||
#include "global.h"
|
||||
#include "test/battle.h"
|
||||
|
||||
ASSUMPTIONS
|
||||
{
|
||||
ASSUME(GetMoveEffect(MOVE_ELECTRIC_TERRAIN) == EFFECT_ELECTRIC_TERRAIN);
|
||||
ASSUME(GetMoveEffect(MOVE_PSYCHIC_TERRAIN) == EFFECT_PSYCHIC_TERRAIN);
|
||||
ASSUME(GetMoveEffect(MOVE_GRASSY_TERRAIN) == EFFECT_GRASSY_TERRAIN);
|
||||
ASSUME(GetMoveEffect(MOVE_MISTY_TERRAIN) == EFFECT_MISTY_TERRAIN);
|
||||
ASSUME(GetMoveEffect(MOVE_STEEL_ROLLER) == EFFECT_HIT_SET_REMOVE_TERRAIN);
|
||||
ASSUME(GetMoveEffect(MOVE_ICE_SPINNER) == EFFECT_HIT_SET_REMOVE_TERRAIN);
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Steel Roller and Ice Spinner can remove a terrain from the field")
|
||||
{
|
||||
u32 j;
|
||||
static const u16 terrainMoves[] =
|
||||
{
|
||||
MOVE_ELECTRIC_TERRAIN,
|
||||
MOVE_PSYCHIC_TERRAIN,
|
||||
MOVE_GRASSY_TERRAIN,
|
||||
MOVE_MISTY_TERRAIN,
|
||||
};
|
||||
|
||||
u16 terrainMove = MOVE_NONE;
|
||||
u16 removeTerrainMove = MOVE_NONE;
|
||||
|
||||
for (j = 0; j < ARRAY_COUNT(terrainMoves); j++)
|
||||
{
|
||||
PARAMETRIZE { removeTerrainMove = MOVE_STEEL_ROLLER; terrainMove = terrainMoves[j]; }
|
||||
PARAMETRIZE { removeTerrainMove = MOVE_ICE_SPINNER; terrainMove = terrainMoves[j]; }
|
||||
}
|
||||
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN { MOVE(opponent, terrainMove); MOVE(player, removeTerrainMove); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, terrainMove, opponent);
|
||||
ANIMATION(ANIM_TYPE_MOVE, removeTerrainMove, player);
|
||||
switch (terrainMove)
|
||||
{
|
||||
case MOVE_ELECTRIC_TERRAIN:
|
||||
MESSAGE("The electricity disappeared from the battlefield.");
|
||||
break;
|
||||
case MOVE_PSYCHIC_TERRAIN:
|
||||
MESSAGE("The weirdness disappeared from the battlefield!");
|
||||
break;
|
||||
case MOVE_GRASSY_TERRAIN:
|
||||
MESSAGE("The grass disappeared from the battlefield.");
|
||||
break;
|
||||
case MOVE_MISTY_TERRAIN:
|
||||
MESSAGE("The mist disappeared from the battlefield.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Steel Roller fails if there is no terrain on the field")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_STEEL_ROLLER); }
|
||||
} SCENE {
|
||||
NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_STEEL_ROLLER, player);
|
||||
MESSAGE("But it failed!");
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Ice Spinner doesn't fail if there is no terrain on the field")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_ICE_SPINNER); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_ICE_SPINNER, player);
|
||||
NOT MESSAGE("But it failed!");
|
||||
}
|
||||
}
|
||||
|
||||
AI_SINGLE_BATTLE_TEST("AI will not choose Steel Roller if it might fail")
|
||||
{
|
||||
u32 move;
|
||||
|
||||
PARAMETRIZE { move = MOVE_ELECTRIC_TERRAIN; }
|
||||
PARAMETRIZE { move = MOVE_NONE; }
|
||||
|
||||
GIVEN {
|
||||
AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_STEEL_ROLLER, MOVE_ICE_SHARD); }
|
||||
} WHEN {
|
||||
if (move == MOVE_ELECTRIC_TERRAIN) {
|
||||
TURN { MOVE(player, MOVE_ELECTRIC_TERRAIN); EXPECT_MOVE(opponent, MOVE_ICE_SHARD); }
|
||||
TURN { EXPECT_MOVE(opponent, MOVE_STEEL_ROLLER); }
|
||||
} else {
|
||||
TURN { EXPECT_MOVE(opponent, MOVE_ICE_SHARD); }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AI_SINGLE_BATTLE_TEST("AI will can choose Ice Spinner regardless if there is a terrain or not")
|
||||
{
|
||||
u32 move;
|
||||
|
||||
PARAMETRIZE { move = MOVE_ELECTRIC_TERRAIN; }
|
||||
PARAMETRIZE { move = MOVE_NONE; }
|
||||
|
||||
GIVEN {
|
||||
AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_ICE_SPINNER, MOVE_ICE_SHARD); }
|
||||
} WHEN {
|
||||
if (move == MOVE_ELECTRIC_TERRAIN) {
|
||||
TURN { MOVE(player, MOVE_ELECTRIC_TERRAIN); EXPECT_MOVE(opponent, MOVE_ICE_SPINNER); }
|
||||
TURN { EXPECT_MOVE(opponent, MOVE_ICE_SPINNER); }
|
||||
} else {
|
||||
TURN { EXPECT_MOVE(opponent, MOVE_ICE_SPINNER); }
|
||||
}
|
||||
}
|
||||
}
|
||||
122
test/battle/move_effect/ice_spinner.c
Normal file
122
test/battle/move_effect/ice_spinner.c
Normal file
@ -0,0 +1,122 @@
|
||||
#include "global.h"
|
||||
#include "test/battle.h"
|
||||
|
||||
ASSUMPTIONS
|
||||
{
|
||||
ASSUME(GetMoveEffect(MOVE_ICE_SPINNER) == EFFECT_ICE_SPINNER);
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Ice Spinner and Steel Roller remove a terrain from field")
|
||||
{
|
||||
u32 j;
|
||||
static const u16 terrainMoves[] =
|
||||
{
|
||||
MOVE_ELECTRIC_TERRAIN,
|
||||
MOVE_PSYCHIC_TERRAIN,
|
||||
MOVE_GRASSY_TERRAIN,
|
||||
MOVE_MISTY_TERRAIN,
|
||||
};
|
||||
|
||||
u16 terrainMove = MOVE_NONE;
|
||||
u16 removeTerrainMove = MOVE_NONE;
|
||||
|
||||
for (j = 0; j < ARRAY_COUNT(terrainMoves); j++)
|
||||
{
|
||||
PARAMETRIZE { removeTerrainMove = MOVE_STEEL_ROLLER; terrainMove = terrainMoves[j]; }
|
||||
PARAMETRIZE { removeTerrainMove = MOVE_ICE_SPINNER; terrainMove = terrainMoves[j]; }
|
||||
}
|
||||
|
||||
GIVEN {
|
||||
ASSUME(GetMoveEffect(MOVE_ELECTRIC_TERRAIN) == EFFECT_ELECTRIC_TERRAIN);
|
||||
ASSUME(GetMoveEffect(MOVE_PSYCHIC_TERRAIN) == EFFECT_PSYCHIC_TERRAIN);
|
||||
ASSUME(GetMoveEffect(MOVE_GRASSY_TERRAIN) == EFFECT_GRASSY_TERRAIN);
|
||||
ASSUME(GetMoveEffect(MOVE_MISTY_TERRAIN) == EFFECT_MISTY_TERRAIN);
|
||||
ASSUME(GetMoveEffect(MOVE_STEEL_ROLLER) == EFFECT_STEEL_ROLLER);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN { MOVE(opponent, terrainMove); MOVE(player, removeTerrainMove); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, terrainMove, opponent);
|
||||
ANIMATION(ANIM_TYPE_MOVE, removeTerrainMove, player);
|
||||
switch (terrainMove)
|
||||
{
|
||||
case MOVE_ELECTRIC_TERRAIN:
|
||||
MESSAGE("The electricity disappeared from the battlefield.");
|
||||
break;
|
||||
case MOVE_PSYCHIC_TERRAIN:
|
||||
MESSAGE("The weirdness disappeared from the battlefield!");
|
||||
break;
|
||||
case MOVE_GRASSY_TERRAIN:
|
||||
MESSAGE("The grass disappeared from the battlefield.");
|
||||
break;
|
||||
case MOVE_MISTY_TERRAIN:
|
||||
MESSAGE("The mist disappeared from the battlefield.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Ice Spinner fails to remove terrain if user faints during attack execution")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_LIFE_ORB); HP(1); }
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_ELECTRIC_TERRAIN); MOVE(opponent, MOVE_ICE_SPINNER); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_ELECTRIC_TERRAIN, player);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_ICE_SPINNER, opponent);
|
||||
NOT MESSAGE("The electricity disappeared from the battlefield.");
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Ice Spinner will not be remove Terrain if user is switched out due to Red Card")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_RED_CARD); }
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WYNAUT);
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_ELECTRIC_TERRAIN); MOVE(opponent, MOVE_ICE_SPINNER); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_ELECTRIC_TERRAIN, player);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_ICE_SPINNER, opponent);
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player);
|
||||
NOT MESSAGE("The electricity disappeared from the battlefield.");
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Ice Spinner doesn't fail if there is no terrain on the field")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_ICE_SPINNER); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_ICE_SPINNER, player);
|
||||
NOT MESSAGE("But it failed!");
|
||||
}
|
||||
}
|
||||
|
||||
AI_SINGLE_BATTLE_TEST("Ice Spinner can be chosen by AI regardless if there is a terrain or not")
|
||||
{
|
||||
u32 move;
|
||||
|
||||
PARAMETRIZE { move = MOVE_ELECTRIC_TERRAIN; }
|
||||
PARAMETRIZE { move = MOVE_NONE; }
|
||||
|
||||
GIVEN {
|
||||
AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_ICE_SPINNER, MOVE_ICE_SHARD); }
|
||||
} WHEN {
|
||||
if (move == MOVE_ELECTRIC_TERRAIN) {
|
||||
TURN { MOVE(player, MOVE_ELECTRIC_TERRAIN); EXPECT_MOVE(opponent, MOVE_ICE_SPINNER); }
|
||||
TURN { EXPECT_MOVE(opponent, MOVE_ICE_SPINNER); }
|
||||
} else {
|
||||
TURN { EXPECT_MOVE(opponent, MOVE_ICE_SPINNER); }
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -618,3 +618,20 @@ SINGLE_BATTLE_TEST("Protect: Quick Guard, Wide Guard and Crafty Shield don't red
|
||||
EXPECT_EQ(results[4].damage, results[5].damage);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Protect: Protective Pads protects from secondary effects")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_PROTECTIVE_PADS); }
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN { MOVE(opponent, MOVE_BURNING_BULWARK); MOVE(player, MOVE_SCRATCH); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_BURNING_BULWARK, opponent);
|
||||
NONE_OF {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_SCRATCH, player);
|
||||
HP_BAR(opponent);
|
||||
STATUS_ICON(player, STATUS1_BURN);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
75
test/battle/move_effect/steel_roller.c
Normal file
75
test/battle/move_effect/steel_roller.c
Normal file
@ -0,0 +1,75 @@
|
||||
#include "global.h"
|
||||
#include "test/battle.h"
|
||||
|
||||
ASSUMPTIONS
|
||||
{
|
||||
ASSUME(GetMoveEffect(MOVE_STEEL_ROLLER) == EFFECT_STEEL_ROLLER);
|
||||
}
|
||||
|
||||
// Covered in ice_spinner.c
|
||||
// SINGLE_BATTLE_TEST("Ice Spinner and Steel Roller remove a terrain from field")
|
||||
|
||||
SINGLE_BATTLE_TEST("Steel Roller removes Terrain even if user faints during attack execution")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_LIFE_ORB); HP(1); }
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_ELECTRIC_TERRAIN); MOVE(opponent, MOVE_STEEL_ROLLER); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_ELECTRIC_TERRAIN, player);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_STEEL_ROLLER, opponent);
|
||||
MESSAGE("The electricity disappeared from the battlefield.");
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Steel Roller removes Terrain if user is switched out due to Red Card")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_RED_CARD); }
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WYNAUT);
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_ELECTRIC_TERRAIN); MOVE(opponent, MOVE_STEEL_ROLLER); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_ELECTRIC_TERRAIN, player);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_STEEL_ROLLER, opponent);
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player);
|
||||
MESSAGE("The electricity disappeared from the battlefield.");
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Steel Roller will fail if there is no Terrain")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN { MOVE(opponent, MOVE_STEEL_ROLLER); }
|
||||
} SCENE {
|
||||
NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_STEEL_ROLLER, opponent);
|
||||
MESSAGE("The opposing Wobbuffet used Steel Roller!");
|
||||
MESSAGE("But it failed!");
|
||||
}
|
||||
}
|
||||
|
||||
AI_SINGLE_BATTLE_TEST("Steel Roller wont be chosen by AI if there is no terrain on the field")
|
||||
{
|
||||
u32 move;
|
||||
|
||||
PARAMETRIZE { move = MOVE_ELECTRIC_TERRAIN; }
|
||||
PARAMETRIZE { move = MOVE_NONE; }
|
||||
|
||||
GIVEN {
|
||||
AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_STEEL_ROLLER, MOVE_ICE_SHARD); }
|
||||
} WHEN {
|
||||
if (move == MOVE_ELECTRIC_TERRAIN) {
|
||||
TURN { MOVE(player, MOVE_ELECTRIC_TERRAIN); EXPECT_MOVE(opponent, MOVE_ICE_SHARD); }
|
||||
TURN { EXPECT_MOVE(opponent, MOVE_STEEL_ROLLER); }
|
||||
} else {
|
||||
TURN { EXPECT_MOVE(opponent, MOVE_ICE_SHARD); }
|
||||
}
|
||||
}
|
||||
}
|
||||
165
test/battle/move_effects_combined/toxic_thread.c
Normal file
165
test/battle/move_effects_combined/toxic_thread.c
Normal file
@ -0,0 +1,165 @@
|
||||
#include "global.h"
|
||||
#include "test/battle.h"
|
||||
|
||||
ASSUMPTIONS
|
||||
{
|
||||
ASSUME(GetMoveEffect(MOVE_TOXIC_THREAD) == EFFECT_TOXIC_THREAD);
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Toxic Thread both reduces speed and inflicts Poison")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_TOXIC_THREAD); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_TOXIC_THREAD, player);
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent);
|
||||
ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_PSN, opponent);
|
||||
STATUS_ICON(opponent, poison: TRUE);
|
||||
} THEN {
|
||||
EXPECT_EQ(opponent->statStages[STAT_SPEED], DEFAULT_STAT_STAGE - 1);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Toxic Thread still inflicts Poison if speed can't go lower")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(GetMoveEffect(MOVE_SCARY_FACE) == EFFECT_SPEED_DOWN_2);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_SCARY_FACE); }
|
||||
TURN { MOVE(player, MOVE_SCARY_FACE); }
|
||||
TURN { MOVE(player, MOVE_SCARY_FACE); }
|
||||
TURN { MOVE(player, MOVE_TOXIC_THREAD); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_SCARY_FACE, player);
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_SCARY_FACE, player);
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_SCARY_FACE, player);
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_TOXIC_THREAD, player);
|
||||
NOT ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent);
|
||||
ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_PSN, opponent);
|
||||
STATUS_ICON(opponent, poison: TRUE);
|
||||
} THEN {
|
||||
EXPECT_EQ(opponent->statStages[STAT_SPEED], DEFAULT_STAT_STAGE - 6);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Toxic Thread still inflicts Poison if speed can't be lowered")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_REGICE) { Ability(ABILITY_CLEAR_BODY); }
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_TOXIC_THREAD); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_TOXIC_THREAD, player);
|
||||
NOT ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent);
|
||||
ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_PSN, opponent);
|
||||
STATUS_ICON(opponent, poison: TRUE);
|
||||
} THEN {
|
||||
EXPECT_EQ(opponent->statStages[STAT_SPEED], DEFAULT_STAT_STAGE);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Toxic Thread still lowers speed if the target can't be Poisoned")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(gSpeciesInfo[SPECIES_BRONZOR].types[0] == TYPE_STEEL || gSpeciesInfo[SPECIES_BRONZOR].types[1] == TYPE_STEEL);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_BRONZOR);
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_TOXIC_THREAD); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_TOXIC_THREAD, player);
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent);
|
||||
NOT ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_PSN, opponent);
|
||||
} THEN {
|
||||
EXPECT_EQ(opponent->statStages[STAT_SPEED], DEFAULT_STAT_STAGE - 1);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Toxic Thread still lowers speed if the target is already Poisoned")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(GetMoveEffect(MOVE_POISON_POWDER) == EFFECT_NON_VOLATILE_STATUS);
|
||||
ASSUME(GetMoveNonVolatileStatus(MOVE_POISON_POWDER) == MOVE_EFFECT_POISON);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_POISON_POWDER); }
|
||||
TURN { MOVE(player, MOVE_TOXIC_THREAD); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_POISON_POWDER, player);
|
||||
ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_PSN, opponent);
|
||||
STATUS_ICON(opponent, poison: TRUE);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_TOXIC_THREAD, player);
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent);
|
||||
} THEN {
|
||||
EXPECT_EQ(opponent->statStages[STAT_SPEED], DEFAULT_STAT_STAGE - 1);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Toxic Thread fails if speed can't be lowered and status can't be inflicted")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(GetMoveEffect(MOVE_POISON_POWDER) == EFFECT_NON_VOLATILE_STATUS);
|
||||
ASSUME(GetMoveNonVolatileStatus(MOVE_POISON_POWDER) == MOVE_EFFECT_POISON);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_SCARY_FACE); }
|
||||
TURN { MOVE(player, MOVE_SCARY_FACE); }
|
||||
TURN { MOVE(player, MOVE_SCARY_FACE); }
|
||||
TURN { MOVE(player, MOVE_POISON_POWDER); }
|
||||
TURN { MOVE(player, MOVE_TOXIC_THREAD); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_SCARY_FACE, player);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_SCARY_FACE, player);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_SCARY_FACE, player);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_POISON_POWDER, player);
|
||||
NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_TOXIC_THREAD, player);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Toxic Thread fails if speed can't be lowered due to Clear Body and status can't be inflicted")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(GetMoveEffect(MOVE_POISON_POWDER) == EFFECT_NON_VOLATILE_STATUS);
|
||||
ASSUME(GetMoveNonVolatileStatus(MOVE_POISON_POWDER) == MOVE_EFFECT_POISON);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_REGICE) { Ability(ABILITY_CLEAR_BODY); }
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_POISON_POWDER); }
|
||||
TURN { MOVE(player, MOVE_TOXIC_THREAD); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_POISON_POWDER, player);
|
||||
NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_TOXIC_THREAD, player);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Toxic Thread fails if speed can't be lowered and target is a poison type")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(GetMoveEffect(MOVE_POISON_POWDER) == EFFECT_NON_VOLATILE_STATUS);
|
||||
ASSUME(GetMoveNonVolatileStatus(MOVE_POISON_POWDER) == MOVE_EFFECT_POISON);
|
||||
ASSUME(gSpeciesInfo[SPECIES_ODDISH].types[0] == TYPE_POISON || gSpeciesInfo[SPECIES_ODDISH].types[1] == TYPE_POISON);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_ODDISH);
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_SCARY_FACE); }
|
||||
TURN { MOVE(player, MOVE_SCARY_FACE); }
|
||||
TURN { MOVE(player, MOVE_SCARY_FACE); }
|
||||
TURN { MOVE(player, MOVE_TOXIC_THREAD); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_SCARY_FACE, player);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_SCARY_FACE, player);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_SCARY_FACE, player);
|
||||
NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_TOXIC_THREAD, player);
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user