Merge branch 'upcoming' into ghoulsaveblock

This commit is contained in:
Bassoonian 2024-02-06 23:36:46 +01:00 committed by GitHub
commit 84686d15d8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
94 changed files with 2216 additions and 1062 deletions

View File

@ -23,9 +23,10 @@ body:
label: Version
description: What version of pokeemerald-expansion are you using as a base?
options:
- 1.7.2 (Latest release)
- 1.7.3 (Latest release)
- master (default when pulling, unreleased bugfixes)
- upcoming (Edge)
- 1.7.2
- 1.7.1
- 1.7.0
- 1.6.2

View File

@ -23,9 +23,10 @@ body:
label: Version
description: What version of pokeemerald-expansion are you using as a base?
options:
- 1.7.2 (Latest release)
- 1.7.3 (Latest release)
- master (default when pulling, unreleased bugfixes)
- upcoming (Edge)
- 1.7.2
- 1.7.1
- 1.7.0
- 1.6.2

View File

@ -17,6 +17,7 @@ jobs:
GAME_LANGUAGE: ENGLISH
MODERN: 0
COMPARE: 0
UNUSED_ERROR: 1
steps:
- name: Checkout
uses: actions/checkout@v2

View File

@ -1,9 +1,10 @@
# Pokeemerald-Expansion Changelogs
## [Version 1.7.2](docs/changelogs/1.7.2.md) - Bugfix Release
## Version 1.7.x
### [Version 1.7.3](docs/changelogs/1.7.3.md) - Bugfix Release
### [Version 1.7.2](docs/changelogs/1.7.2.md) - Bugfix Release
### [Version 1.7.1](docs/changelogs/1.7.1.md) - Bugfix Release
### [Version 1.7.0](docs/changelogs/1.7.0.md) - Feature Release
## [Version 1.7.1](docs/changelogs/1.7.1.md) - Bugfix Release
## [Version 1.7.0](docs/changelogs/1.7.0.md) - Feature Release
## [Version 1.6.2](docs/changelogs/1.6.2.md) - Bugfix Release
## Version 1.6.x
### [Version 1.6.2](docs/changelogs/1.6.2.md) - Bugfix Release

View File

@ -36,13 +36,14 @@ else
EXE :=
endif
TITLE := POKEMON EMER
GAME_CODE := BPEE
MAKER_CODE := 01
REVISION := 0
MODERN ?= 1
TEST ?= 0
ANALYZE ?= 0
TITLE := POKEMON EMER
GAME_CODE := BPEE
MAKER_CODE := 01
REVISION := 0
MODERN ?= 1
TEST ?= 0
ANALYZE ?= 0
UNUSED_ERROR ?= 0
ifeq (agbcc,$(MAKECMDGOALS))
MODERN := 0
@ -127,6 +128,12 @@ override CFLAGS += -mthumb -mthumb-interwork -O2 -mabi=apcs-gnu -mtune=arm7tdmi
ifeq ($(ANALYZE),1)
override CFLAGS += -fanalyzer
endif
# Only throw an error for unused elements if its RH-Hideout's repo
ifeq ($(UNUSED_ERROR),0)
ifneq ($(GITHUB_REPOSITORY_OWNER),rh-hideout)
override CFLAGS += -Wno-error=unused-variable -Wno-error=unused-const-variable -Wno-error=unused-parameter -Wno-error=unused-function -Wno-error=unused-but-set-parameter -Wno-error=unused-but-set-variable -Wno-error=unused-value -Wno-error=unused-local-typedefs
endif
endif
ROM := $(MODERN_ROM_NAME)
OBJ_DIR := $(MODERN_OBJ_DIR_NAME)
LIBPATH := -L "$(dir $(shell $(PATH_MODERNCC) -mthumb -print-file-name=libgcc.a))" -L "$(dir $(shell $(PATH_MODERNCC) -mthumb -print-file-name=libnosys.a))" -L "$(dir $(shell $(PATH_MODERNCC) -mthumb -print-file-name=libc.a))"

View File

@ -7,7 +7,7 @@ pokeemerald-expansion is a decomp hack base project based off pret's [pokeemeral
If you use pokeemerald-expansion in your hack, please add RHH (Rom Hacking Hideout) to your credits list. Optionally, you can list the version used, so it can help players know what features to expect.
You can phrase it as the following:
```
Based off RHH's pokeemerald-expansion v1.7.2 https://github.com/rh-hideout/pokeemerald-expansion/
Based off RHH's pokeemerald-expansion v1.7.3 https://github.com/rh-hideout/pokeemerald-expansion/
```
## What features are included?
@ -167,7 +167,7 @@ With this, you'll get the latest version of pokeemerald-expansion, plus a couple
## **How do I update my version of pokeemerald-expansion?**
- 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.7.2`.
- Once you have your remote set up, run the command `git pull RHH expansion/1.7.3`.
### Please consider crediting the entire [list of contributors](https://github.com/rh-hideout/pokeemerald-expansion/wiki/Credits) in your project, as they have all worked hard to develop this project :)

View File

@ -72,6 +72,10 @@
.2byte \id
.endm
.macro printsavedstring
printstring 0
.endm
.macro printselectionstring id:req
.byte 0x11
.2byte \id
@ -776,8 +780,21 @@
.byte 0x8b
.endm
.macro unused0x8C
.macro twoturnmoveschargestringandanimation
.byte 0x8c
.4byte 1f @animation then attack string
@default - attack string then animation
printsavedstring
waitmessage B_WAIT_TIME_LONG
attackanimation
waitanimation
goto 2f
1:
attackanimation
waitanimation
printsavedstring
waitmessage B_WAIT_TIME_LONG
2:
.endm
.macro setmultihitcounter value:req
@ -1035,12 +1052,20 @@
.4byte \failInstr
.endm
.macro setsemiinvulnerablebit
.macro setsemiinvulnerablebit clear=FALSE
.byte 0xc5
.byte \clear
.endm
.macro clearsemiinvulnerablebit
setsemiinvulnerablebit TRUE
.endm
.macro jumpifweathercheckchargeeffects battler:req, checkChargeTurnEffects:req, jumpInstr:req
.byte 0xc6
.byte \battler
.byte \checkChargeTurnEffects
.4byte \jumpInstr
.endm
.macro setminimize
@ -1337,13 +1362,6 @@
.4byte \jumpInstr
.endm
.macro jumpifholdeffect battler:req, holdEffect:req, jumpInstr:req
callnative BS_JumpIfHoldEffect
.byte \battler
.2byte \holdEffect
.4byte \jumpInstr
.endm
.macro dostockpilestatchangeswearoff, battler:req, statChangeInstr:req
callnative BS_DoStockpileStatChangesWearOff
.byte \battler
@ -2005,10 +2023,15 @@
.4byte \jumpInstr
.endm
.macro jumpifnoholdeffect battler:req, holdEffect:req, jumpInstr:req
various \battler, VARIOUS_JUMP_IF_NO_HOLD_EFFECT
.macro jumpifholdeffect battler:req, holdEffect:req, jumpInstr:req, equal=TRUE
various \battler, VARIOUS_JUMP_IF_HOLD_EFFECT
.byte \holdEffect
.4byte \jumpInstr
.byte \equal
.endm
.macro jumpifnoholdeffect battler:req, holdEffect:req, jumpInstr:req
jumpifholdeffect \battler, \holdEffect, \jumpInstr, FALSE
.endm
.macro infatuatewithbattler battler:req, infatuateWith:req

View File

@ -9278,13 +9278,12 @@ Boomburst_Doubles:
goto Boomburst_Last
Move_FAIRY_LOCK::
loadspritegfx ANIM_TAG_CHAIN_LINK @Chain Colour
loadspritegfx ANIM_TAG_FAIRY_LOCK_CHAINS @AnimTask is missing for Fairy Lock Chain
loadspritegfx ANIM_TAG_FAIRY_LOCK_CHAINS
setalpha 8, 8
monbg ANIM_ATK_PARTNER
createvisualtask AnimTask_BlendBattleAnimPal, 0xa, F_PAL_BG, 0x1, 0x0, 0x8, 0x6B1F
waitforvisualfinish
loopsewithpan SE_M_SCRATCH, SOUND_PAN_TARGET, 0x6, 0x4
loopsewithpan SE_M_SCRATCH, SOUND_PAN_TARGET, 0x6, 0x9
createvisualtask AnimTask_VoltTackleBolt, 0x5, 0x7
createvisualtask AnimTask_VoltTackleBolt, 0x5, 0x33
createvisualtask AnimTask_VoltTackleBolt, 0x5, 0x2
@ -17159,7 +17158,7 @@ Move_RAGING_BULL::
restorebg
waitbgfadein
end
@ Credits to Z-nogyroP. Simple anim that combines Force Palm + Fake Out
Move_UPPER_HAND::
loadspritegfx ANIM_TAG_SHADOW_BALL
@ -17187,12 +17186,53 @@ Move_UPPER_HAND::
blendoff
end
Move_JET_PUNCH:
loadspritegfx ANIM_TAG_ICE_CRYSTALS
loadspritegfx ANIM_TAG_HANDS_AND_FEET
loadspritegfx ANIM_TAG_IMPACT
loadspritegfx ANIM_TAG_SPLASH
loadspritegfx ANIM_TAG_WATER_IMPACT
loadspritegfx ANIM_TAG_SMALL_BUBBLES
monbg ANIM_DEF_PARTNER
setalpha 12, 8
playsewithpan SE_M_DIVE, SOUND_PAN_TARGET
createvisualtask AnimTask_AttackerStretchAndDisappear, 2
createvisualtask AnimTask_TranslateMonEllipticalRespectSide, 1, ANIM_ATTACKER, 24, 6, 1, 5
createvisualtask AnimTask_TraceMonBlended, 2, 0, 4, 7, 3
delay 18
createvisualtask AnimTask_SetAttackerInvisibleWaitForSignal, 2
createvisualtask AnimTask_BlendBattleAnimPal, 10, F_PAL_TARGET, 2, 0, 9, RGB_BLUE
delay 8
createvisualtask AnimTask_ExtremeSpeedMonReappear, 2
createsprite gSmallBubblePairSpriteTemplate, ANIM_TARGET, 2, 0x14, 0xffec, 0x14, ANIM_TARGET
createsprite gSmallBubblePairSpriteTemplate, ANIM_TARGET, 2, 0xa, 0xa, 0x14, ANIM_TARGET
createsprite gFistFootSpriteTemplate, ANIM_TARGET, 3, 0, 0, 8, 1, 0
playsewithpan SE_M_DIVE, SOUND_PAN_TARGET
createsprite gBasicHitSplatSpriteTemplate, ANIM_TARGET, 2, 0, 0, ANIM_TARGET, 1
createvisualtask AnimTask_ShakeMon, 2, ANIM_TARGET, 0, 3, 15, 1
delay 6
createsprite gSmallBubblePairSpriteTemplate, ANIM_TARGET, 2, 0x14, 0xffec, 0x14, ANIM_TARGET
createsprite gSmallBubblePairSpriteTemplate, ANIM_TARGET, 2, 0xa, 0xa, 0x14, ANIM_TARGET
createsprite gWaterHitSplatSpriteTemplate, ANIM_ATTACKER, 3, 0, 13, ANIM_TARGET, 1
createsprite gSmallDriftingBubblesSpriteTemplate, ANIM_ATTACKER, 4, 0, 13
createsprite gSmallDriftingBubblesSpriteTemplate, ANIM_ATTACKER, 4, 0, 13
delay 2
createsprite gWaterHitSplatSpriteTemplate, ANIM_ATTACKER, 3, 0, 8, ANIM_TARGET, 1
createsprite gSmallDriftingBubblesSpriteTemplate, ANIM_ATTACKER, 4, 0, 8
createsprite gSmallDriftingBubblesSpriteTemplate, ANIM_ATTACKER, 4, 0, 8
delay 2
call DiveSetUpWaterDroplets
waitforvisualfinish
createvisualtask AnimTask_BlendBattleAnimPal, 10, F_PAL_TARGET, 0, 9, 0, RGB_BLUE
clearmonbg ANIM_DEF_PARTNER
blendoff
end
Move_TERA_BLAST::
Move_AXE_KICK::
Move_LAST_RESPECTS::
Move_LUMINA_CRASH::
Move_ORDER_UP::
Move_JET_PUNCH::
Move_SPICY_EXTRACT::
Move_SPIN_OUT::
Move_POPULATION_BOMB::

View File

@ -585,46 +585,9 @@ BattleScript_BeakBlastBurn::
call BattleScript_MoveEffectBurn
return
BattleScript_EffectMeteorBeam::
@ DecideTurn
jumpifstatus2 BS_ATTACKER, STATUS2_MULTIPLETURNS, BattleScript_TwoTurnMovesSecondTurn
jumpifword CMP_COMMON_BITS, gHitMarker, HITMARKER_NO_ATTACKSTRING, BattleScript_TwoTurnMovesSecondTurn
jumpifmove MOVE_METEOR_BEAM, BattleScript_SetStringMeteorBeam
jumpifmove MOVE_ELECTRO_SHOT, BattleScript_SetStringElectroShock
BattleScript_TryCharging:
call BattleScript_FirstChargingTurnMeteorBeam
jumpifmove MOVE_METEOR_BEAM, BattleScript_TryMeteorBeam
jumpifweatheraffected BS_ATTACKER, B_WEATHER_RAIN, BattleScript_TwoTurnMovesSecondTurn @ Check for move Electro Shot
BattleScript_TryMeteorBeam:
jumpifnoholdeffect BS_ATTACKER, HOLD_EFFECT_POWER_HERB, BattleScript_MoveEnd
call BattleScript_PowerHerbActivation
goto BattleScript_TwoTurnMovesSecondTurn
BattleScript_SetStringMeteorBeam:
setbyte sTWOTURN_STRINGID, B_MSG_TURN1_METEOR_BEAM
goto BattleScript_TryCharging
BattleScript_SetStringElectroShock:
setbyte sTWOTURN_STRINGID, B_MSG_TURN1_ELECTRO_SHOCK
goto BattleScript_TryCharging
BattleScript_FirstChargingTurnMeteorBeam::
attackcanceler
flushtextbox
ppreduce
attackanimation
waitanimation
orword gHitMarker, HITMARKER_CHARGING
seteffectprimary MOVE_EFFECT_CHARGING | MOVE_EFFECT_AFFECTS_USER
copybyte cMULTISTRING_CHOOSER, sTWOTURN_STRINGID
printfromtable gFirstTurnOfTwoStringIds
waitmessage B_WAIT_TIME_LONG
setadditionaleffects @ only onChargeTurnOnly effects will work here
return
BattleScript_EffectSkyDrop::
jumpifstatus2 BS_ATTACKER, STATUS2_MULTIPLETURNS, BattleScript_SkyDropTurn2
attackcanceler
jumpifstatus2 BS_ATTACKER, STATUS2_MULTIPLETURNS, BattleScript_SkyDropTurn2
ppreduce
accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE
attackstring
@ -638,16 +601,10 @@ BattleScript_EffectSkyDrop::
BattleScript_SkyDropWork:
setskydrop
setbyte sTWOTURN_STRINGID, B_MSG_TURN1_SKY_DROP
setsemiinvulnerablebit
call BattleScriptFirstChargingTurnAfterAttackString
call BattleScript_FirstChargingTurnAfterAttackString
goto BattleScript_MoveEnd
BattleScript_SkyDropTurn2:
attackcanceler
setbyte sB_ANIM_TURN, 0x1
clearstatusfromeffect BS_ATTACKER, MOVE_EFFECT_CHARGING
orword gHitMarker, HITMARKER_NO_PPDEDUCT
clearsemiinvulnerablebit
call BattleScript_TwoTurnMovesSecondTurnRet
attackstring
clearskydrop BattleScript_SkyDropChangedTarget
jumpiftype BS_TARGET, TYPE_FLYING, BattleScript_SkyDropFlyingType
@ -3485,29 +3442,6 @@ BattleScript_KOFail::
waitmessage B_WAIT_TIME_LONG
goto BattleScript_MoveEnd
BattleScript_TwoTurnMovesSecondTurn::
attackcanceler
setbyte sB_ANIM_TURN, 1
clearstatusfromeffect BS_ATTACKER, MOVE_EFFECT_CHARGING
orword gHitMarker, HITMARKER_NO_PPDEDUCT
goto BattleScript_HitFromAccCheck
BattleScriptFirstChargingTurn::
attackcanceler
flushtextbox
ppreduce
attackstring
BattleScriptFirstChargingTurnAfterAttackString:
pause B_WAIT_TIME_LONG
copybyte cMULTISTRING_CHOOSER, sTWOTURN_STRINGID
printfromtable gFirstTurnOfTwoStringIds
waitmessage B_WAIT_TIME_LONG
attackanimation
waitanimation
orword gHitMarker, HITMARKER_CHARGING
seteffectprimary MOVE_EFFECT_CHARGING | MOVE_EFFECT_AFFECTS_USER
return
BattleScript_EffectSuperFang::
attackcanceler
accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE
@ -3579,7 +3513,7 @@ BattleScript_EffectFocusEnergy::
attackcanceler
attackstring
ppreduce
jumpifstatus2 BS_ATTACKER, STATUS2_FOCUS_ENERGY, BattleScript_ButItFailed
jumpifstatus2 BS_ATTACKER, STATUS2_FOCUS_ENERGY_ANY, BattleScript_ButItFailed
setfocusenergy
attackanimation
waitanimation
@ -3784,34 +3718,16 @@ BattleScript_PowerHerbActivation:
BattleScript_EffectTwoTurnsAttack::
jumpifstatus2 BS_ATTACKER, STATUS2_MULTIPLETURNS, BattleScript_TwoTurnMovesSecondTurn
jumpifword CMP_COMMON_BITS, gHitMarker, HITMARKER_NO_ATTACKSTRING, BattleScript_TwoTurnMovesSecondTurn
jumpifmove MOVE_SKY_ATTACK, BattleScript_EffectTwoTurnsAttackSkyAttack
jumpifmove MOVE_RAZOR_WIND, BattleScript_EffectTwoTurnsAttackRazorWind
jumpifmove MOVE_ICE_BURN, BattleScript_EffectTwoTurnsAttackIceBurn
jumpifmove MOVE_FREEZE_SHOCK, BattleScript_EffectTwoTurnsAttackFreezeShock
setbyte sTWOTURN_STRINGID, B_MSG_TURN1_RAZOR_WIND
BattleScript_EffectTwoTurnsAttackContinue:
call BattleScriptFirstChargingTurn
jumpifnoholdeffect BS_ATTACKER, HOLD_EFFECT_POWER_HERB, BattleScript_MoveEnd
call BattleScript_PowerHerbActivation
goto BattleScript_TwoTurnMovesSecondTurn
BattleScript_EffectTwoTurnsAttackSkyAttack:
setbyte sTWOTURN_STRINGID, B_MSG_TURN1_SKY_ATTACK
goto BattleScript_EffectTwoTurnsAttackContinue
BattleScript_EffectTwoTurnsAttackRazorWind:
setbyte sTWOTURN_STRINGID, B_MSG_TURN1_RAZOR_WIND
goto BattleScript_EffectTwoTurnsAttackContinue
BattleScript_EffectTwoTurnsAttackIceBurn:
setbyte sTWOTURN_STRINGID, B_MSG_TURN1_RAZOR_WIND
goto BattleScript_EffectTwoTurnsAttackContinue
BattleScript_EffectTwoTurnsAttackFreezeShock:
setbyte sTWOTURN_STRINGID, B_MSG_TURN1_FREEZE_SHOCK
goto BattleScript_EffectTwoTurnsAttackContinue
jumpifweathercheckchargeeffects BS_ATTACKER, TRUE, BattleScript_EffectHit
call BattleScript_FirstChargingTurn
jumpifweathercheckchargeeffects BS_ATTACKER, FALSE, BattleScript_TwoTurnMovesSecondTurn
jumpifholdeffect BS_ATTACKER, HOLD_EFFECT_POWER_HERB, BattleScript_TwoTurnMovesSecondPowerHerbActivates
goto BattleScript_MoveEnd
BattleScript_EffectGeomancy::
jumpifstatus2 BS_ATTACKER, STATUS2_MULTIPLETURNS, BattleScript_GeomancySecondTurn
jumpifword CMP_COMMON_BITS, gHitMarker, HITMARKER_NO_ATTACKSTRING, BattleScript_GeomancySecondTurn
setbyte sTWOTURN_STRINGID, B_MSG_TURN1_GEOMANCY
call BattleScriptFirstChargingTurn
call BattleScript_FirstChargingTurn
jumpifnoholdeffect BS_ATTACKER, HOLD_EFFECT_POWER_HERB, BattleScript_MoveEnd
call BattleScript_PowerHerbActivation
BattleScript_GeomancySecondTurn:
@ -3848,6 +3764,43 @@ BattleScript_GeomancyTrySpeed::
BattleScript_GeomancyEnd::
goto BattleScript_MoveEnd
BattleScript_FirstChargingTurn::
attackcanceler
.if B_UPDATED_MOVE_DATA >= GEN_5 @ before Gen 5, charge moves did not print an attack string on the charge turn
flushtextbox
attackstring
waitmessage B_WAIT_TIME_LONG
.endif
ppreduce
BattleScript_FirstChargingTurnAfterAttackString:
setsemiinvulnerablebit @ only for moves with EFFECT_SEMI_INVULNERABLE/EFFECT_SKY_DROP
orword gHitMarker, HITMARKER_CHARGING
seteffectprimary MOVE_EFFECT_CHARGING | MOVE_EFFECT_AFFECTS_USER
twoturnmoveschargestringandanimation
setadditionaleffects @ only onChargeTurnOnly effects will work here
return
BattleScript_TwoTurnMovesSecondPowerHerbActivates:
call BattleScript_PowerHerbActivation
call BattleScript_TwoTurnMovesSecondTurnRet
accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE
.if B_UPDATED_MOVE_DATA < GEN_5 @ before Gen 5, charge moves did not print an attack string on the charge turn
attackstring
.endif
goto BattleScript_HitFromCritCalc
BattleScript_TwoTurnMovesSecondTurn::
attackcanceler
call BattleScript_TwoTurnMovesSecondTurnRet
orword gHitMarker, HITMARKER_NO_PPDEDUCT
goto BattleScript_HitFromAccCheck
BattleScript_TwoTurnMovesSecondTurnRet:
setbyte sB_ANIM_TURN, 1
clearstatusfromeffect BS_ATTACKER, MOVE_EFFECT_CHARGING
clearsemiinvulnerablebit @ only for moves with EFFECT_SEMI_INVULNERABLE/EFFECT_SKY_DROP
return
BattleScript_EffectSubstitute::
attackcanceler
ppreduce
@ -4117,26 +4070,7 @@ BattleScript_EffectDestinyBond::
goto BattleScript_MoveEnd
BattleScript_EffectEerieSpell::
attackcanceler
attackstring
ppreduce
accuracycheck BattleScript_ButItFailed, ACC_CURR_MOVE
attackstring
ppreduce
critcalc
damagecalc
adjustdamage
attackanimation
waitanimation
effectivenesssound
hitanimation BS_TARGET
waitstate
healthbarupdate BS_TARGET
datahpupdate BS_TARGET
critmessage
waitmessage B_WAIT_TIME_LONG
resultmessage
waitmessage B_WAIT_TIME_LONG
call BattleScript_EffectHit_Ret
tryfaintmon BS_TARGET
eeriespellppreduce BattleScript_MoveEnd
printstring STRINGID_PKMNREDUCEDPP
@ -4178,17 +4112,6 @@ BattleScript_PartyHealEnd::
waitstate
goto BattleScript_MoveEnd
BattleScript_EffectTripleKick::
attackcanceler
accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE
jumpifmove MOVE_TRIPLE_AXEL BS_TripleAxel
addbyte sTRIPLE_KICK_POWER, 10 @ triple kick gets +10 power
goto BattleScript_HitFromAtkString
BS_TripleAxel:
addbyte sTRIPLE_KICK_POWER, 20 @ triple axel gets +20 power
goto BattleScript_HitFromAtkString
BattleScript_EffectMeanLook::
attackcanceler
attackstring
@ -4654,23 +4577,6 @@ BattleScript_EffectMirrorCoat::
adjustdamage
goto BattleScript_HitFromAtkAnimation
BattleScript_EffectSkullBash::
jumpifstatus2 BS_ATTACKER, STATUS2_MULTIPLETURNS, BattleScript_TwoTurnMovesSecondTurn
jumpifword CMP_COMMON_BITS, gHitMarker, HITMARKER_NO_ATTACKSTRING, BattleScript_TwoTurnMovesSecondTurn
setbyte sTWOTURN_STRINGID, B_MSG_TURN1_SKULL_BASH
call BattleScriptFirstChargingTurn
setstatchanger STAT_DEF, 1, FALSE
statbuffchange MOVE_EFFECT_AFFECTS_USER | STAT_CHANGE_ALLOW_PTR, BattleScript_SkullBashEnd
jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_SkullBashEnd
setgraphicalstatchangevalues
playanimation BS_ATTACKER, B_ANIM_STATS_CHANGE, sB_ANIM_ARG1
printfromtable gStatUpStringIds
waitmessage B_WAIT_TIME_LONG
BattleScript_SkullBashEnd::
jumpifnoholdeffect BS_ATTACKER, HOLD_EFFECT_POWER_HERB, BattleScript_MoveEnd
call BattleScript_PowerHerbActivation
goto BattleScript_TwoTurnMovesSecondTurn
BattleScript_EffectFutureSight::
attackcanceler
attackstring
@ -4682,25 +4588,6 @@ BattleScript_EffectFutureSight::
waitmessage B_WAIT_TIME_LONG
goto BattleScript_MoveEnd
BattleScript_EffectGust::
goto BattleScript_EffectHit
BattleScript_EffectSolarBeam::
jumpifweatheraffected BS_ATTACKER, B_WEATHER_SUN, BattleScript_SolarBeamOnFirstTurn
BattleScript_SolarBeamDecideTurn::
jumpifstatus2 BS_ATTACKER, STATUS2_MULTIPLETURNS, BattleScript_TwoTurnMovesSecondTurn
jumpifword CMP_COMMON_BITS, gHitMarker, HITMARKER_NO_ATTACKSTRING, BattleScript_TwoTurnMovesSecondTurn
setbyte sTWOTURN_STRINGID, B_MSG_TURN1_SOLAR_BEAM
call BattleScriptFirstChargingTurn
jumpifnoholdeffect BS_ATTACKER, HOLD_EFFECT_POWER_HERB, BattleScript_MoveEnd
call BattleScript_PowerHerbActivation
goto BattleScript_TwoTurnMovesSecondTurn
BattleScript_SolarBeamOnFirstTurn::
orword gHitMarker, HITMARKER_CHARGING
seteffectprimary MOVE_EFFECT_CHARGING | MOVE_EFFECT_AFFECTS_USER
ppreduce
goto BattleScript_TwoTurnMovesSecondTurn
BattleScript_EffectTeleport::
.if B_TELEPORT_BEHAVIOR >= GEN_7
jumpifbattletype BATTLE_TYPE_TRAINER, BattleScript_EffectBatonPass
@ -4765,46 +4652,6 @@ BattleScript_BeatUpEnd::
end
.endif
BattleScript_EffectSemiInvulnerable::
jumpifstatus2 BS_ATTACKER, STATUS2_MULTIPLETURNS, BattleScript_SecondTurnSemiInvulnerable
jumpifword CMP_COMMON_BITS, gHitMarker, HITMARKER_NO_ATTACKSTRING, BattleScript_SecondTurnSemiInvulnerable
jumpifmove MOVE_FLY, BattleScript_FirstTurnFly
jumpifmove MOVE_DIVE, BattleScript_FirstTurnDive
jumpifmove MOVE_BOUNCE, BattleScript_FirstTurnBounce
jumpifmove MOVE_PHANTOM_FORCE, BattleScript_FirstTurnPhantomForce
jumpifmove MOVE_SHADOW_FORCE, BattleScript_FirstTurnPhantomForce
setbyte sTWOTURN_STRINGID, B_MSG_TURN1_DIG
goto BattleScript_FirstTurnSemiInvulnerable
BattleScript_FirstTurnBounce::
setbyte sTWOTURN_STRINGID, B_MSG_TURN1_BOUNCE
goto BattleScript_FirstTurnSemiInvulnerable
BattleScript_FirstTurnDive::
setbyte sTWOTURN_STRINGID, B_MSG_TURN1_DIVE
goto BattleScript_FirstTurnSemiInvulnerable
BattleScript_FirstTurnPhantomForce:
setbyte sTWOTURN_STRINGID, B_MSG_TURN1_PHANTOM_FORCE
goto BattleScript_FirstTurnSemiInvulnerable
BattleScript_FirstTurnFly::
setbyte sTWOTURN_STRINGID, B_MSG_TURN1_FLY
BattleScript_FirstTurnSemiInvulnerable::
call BattleScriptFirstChargingTurn
setsemiinvulnerablebit
jumpifnoholdeffect BS_ATTACKER, HOLD_EFFECT_POWER_HERB, BattleScript_MoveEnd
call BattleScript_PowerHerbActivation
BattleScript_SecondTurnSemiInvulnerable::
attackcanceler
setbyte sB_ANIM_TURN, 1
clearstatusfromeffect BS_ATTACKER, MOVE_EFFECT_CHARGING
orword gHitMarker, HITMARKER_NO_PPDEDUCT
BattleScript_SemiInvulnerableTryHit::
accuracycheck BattleScript_SemiInvulnerableMiss, ACC_CURR_MOVE
clearsemiinvulnerablebit
goto BattleScript_HitFromAtkString
BattleScript_SemiInvulnerableMiss::
clearsemiinvulnerablebit
goto BattleScript_PrintMoveMissed
BattleScript_EffectDefenseCurl::
attackcanceler
attackstring
@ -5544,9 +5391,6 @@ BattleScript_CosmicPowerTrySpDef::
BattleScript_CosmicPowerEnd::
goto BattleScript_MoveEnd
BattleScript_EffectSkyUppercut::
goto BattleScript_EffectHit
BattleScript_EffectBulkUp::
attackcanceler
attackstring
@ -9941,10 +9785,8 @@ BattleScript_RaiseCritAlliesLoop:
setstatchanger STAT_ATK, 0, FALSE @ for animation
setgraphicalstatchangevalues
playanimation BS_TARGET, B_ANIM_STATS_CHANGE, sB_ANIM_ARG1
swapattackerwithtarget
printstring STRINGID_PKMNGETTINGPUMPED
waitmessage B_WAIT_TIME_LONG
swapattackerwithtarget
BattleScript_RaiseCritAlliesIncrement:
setbyte sSTAT_ANIM_PLAYED, FALSE
jumpifbytenotequal gBattlerTarget, gBattlerAttacker, BattleScript_RaiseCritAlliesEnd

View File

@ -114,7 +114,7 @@ BattleScript_ItemSetMist::
BattleScript_ItemSetFocusEnergy::
call BattleScript_UseItemMessage
jumpifstatus2 BS_ATTACKER, STATUS2_FOCUS_ENERGY, BattleScript_ButItFailed
jumpifstatus2 BS_ATTACKER, STATUS2_FOCUS_ENERGY_ANY, BattleScript_ButItFailed
setfocusenergy
playmoveanimation BS_ATTACKER, MOVE_FOCUS_ENERGY
waitanimation

77
docs/changelogs/1.7.3.md Normal file
View File

@ -0,0 +1,77 @@
# Version 1.7.3
```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.7.3`.
```
## 🌋 *IMPORTANT CHANGES* 🌋
* Unused warnings are no longer treated as errrors by default by @AsparagusEduardo in https://github.com/rh-hideout/pokeemerald-expansion/pull/4092
* [Critical fix] Backported gHeap alignment fix from upstream pret by @AsparagusEduardo in https://github.com/rh-hideout/pokeemerald-expansion/pull/4089
* Fixes issue that causes graphics to bug when leaving Littleroot for Birch's cutscene.
## 🧬 General 🧬
* Fixed HGSS Dex's dark mode search palette by @ravepossum in https://github.com/rh-hideout/pokeemerald-expansion/pull/4095
## 🐉 Pokémon 🐉
### Changed
* Condensed Oinkologne teachable learnsets (they previously had different tables despite having the same learnsets) by @Bassoonian in https://github.com/rh-hideout/pokeemerald-expansion/pull/4026
* Removed illegal teachable learnset moves that didn't match Gen 7 or 9 by @Bassoonian in https://github.com/rh-hideout/pokeemerald-expansion/pull/4039 and https://github.com/rh-hideout/pokeemerald-expansion/pull/4042
### Fixed
* Fixed incorrect family toggle preproc blocks by @AsparagusEduardo in https://github.com/rh-hideout/pokeemerald-expansion/pull/4024
* Cosplay and Cap Pikachu animations were still being included even if disabled.
* Fixed compile errors when:
* Feebas' family was disabled but not Castform.
* Chatot was disabled but not Spiritomb.
* Virizion was disabled but not Tornadus or Thundurus.
* Zekrom was disabled but not Landorus.
* Kyurem was disabled but not Keldeo or Meloetta.
* Wishiwashi was disabled but not Rockruff.
* Fixed compile error when disabling Gen 4 cross-evolutions while having Kingdra enabled by @Skyeward and @Bassoonian in https://github.com/rh-hideout/pokeemerald-expansion/pull/4044 and https://github.com/rh-hideout/pokeemerald-expansion/pull/4046
## ⚔️ Battle General ⚔️ ##
### Fixed
* Fixed Steven double battle palette error by @johannakullmann in https://github.com/rh-hideout/pokeemerald-expansion/pull/4078
## 🤹 Moves 🤹
### Changed
* Renamed `EFFECT_STEEL_BEAM` to `EFFECT_MAX_HP_50_RECOIL` by @AlexOn1ine in https://github.com/rh-hideout/pokeemerald-expansion/pull/4043
### Fixed
* Fixed Pursuit's effect not working by @ZnogyroP @AlexOn1ine in https://github.com/rh-hideout/pokeemerald-expansion/pull/4086
## 🎭 Abilities 🎭
### Fixed
* Fixed Emergency Exit issues:
* Fixed rounding error that caused it to not switch out when odd-numbered HP was off by 1 by @SBird1337 in https://github.com/rh-hideout/pokeemerald-expansion/pull/4040
* Eg: going from 101 Max HP to 50 HP would've *not* cause it to switch out.
* Fixes Emergency Exit switching out even if the Pokémon was healed above the threshold before it would've triggered by @AlexOn1ine in https://github.com/rh-hideout/pokeemerald-expansion/pull/4041
* Eg: going from 100 Max HP to 45 HP and eating a Sitrus Berry back to 55 HP would've cause it to switch out.
* Cleanup by @AlexOn1ine in https://github.com/rh-hideout/pokeemerald-expansion/pull/4100
* Fixed Corrosion only working for status moves by @AlexOn1ine in https://github.com/rh-hideout/pokeemerald-expansion/pull/4037
* Fixed Magic Guard not preventing Mind Blown recoil damage by @AlexOn1ine in https://github.com/rh-hideout/pokeemerald-expansion/pull/4043
## 🧶 Items 🧶
### Fixed
* Fixed oversight causing chosen fossil to be lost if bag is full by @fakuzatsu in https://github.com/rh-hideout/pokeemerald-expansion/pull/3978
* Fixed other Key Item script oversights by @Bassoonian in https://github.com/rh-hideout/pokeemerald-expansion/pull/4066
* Fixed Life Orb causing damage on switch-in from Eject Pack and Red Card by @AlexOn1ine in https://github.com/rh-hideout/pokeemerald-expansion/pull/4038
* Fixed Glimmering Charm sprite by @SonikkuA-DatH and @AlexOn1ine in https://github.com/rh-hideout/pokeemerald-expansion/pull/4047
## 🤖 Battle AI 🤖
### Fixed
* Fixed AI trying to switch into the same mon twice in the same turn by @DizzyEggg in https://github.com/rh-hideout/pokeemerald-expansion/pull/4098
## 🧪 Test Runner 🧪
### Added
* Corrosion tests by @AlexOn1ine in https://github.com/rh-hideout/pokeemerald-expansion/pull/4037
* Pursuit/Tangling Hair interaction by @ZnogyroP @AlexOn1ine in https://github.com/rh-hideout/pokeemerald-expansion/pull/4086
### Changed
* Passing `KNOWN_FAILING` tests are now listed separately from `PASSED` tests by @AsparagusEduardo in https://github.com/rh-hideout/pokeemerald-expansion/pull/4063
## New Contributors
* @Skyeward made their first contribution in https://github.com/rh-hideout/pokeemerald-expansion/pull/4044
**Full Changelog**: https://github.com/rh-hideout/pokeemerald-expansion/compare/expansion/1.7.2...expansion/1.7.3
<!--Last PR: 4098-->

View File

@ -3,7 +3,7 @@
```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.7.2`.
- Once you have your remote set up, run the command `git pull RHH expansion/1.Y.Z`.
```
## 🌋 *IMPORTANT CHANGES* 🌋
@ -88,6 +88,6 @@
## New Contributors
* Tony
**Full Changelog**: https://github.com/rh-hideout/pokeemerald-expansion/compare/expansion/1.7.1...expansion/1.7.2
**Full Changelog**: https://github.com/rh-hideout/pokeemerald-expansion/compare/expansion/1.Y.Z...expansion/1.Y.Z
<!--Last PR: 3697-->
<!--Last PR: ____-->

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 609 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -0,0 +1,19 @@
JASC-PAL
0100
16
154 212 167
136 73 83
8 8 8
189 126 61
224 90 94
240 225 123
3 33 81
105 99 119
223 226 244
252 253 253
184 181 206
49 93 142
141 132 166
18 56 103
98 133 172
132 109 58

View File

@ -0,0 +1,19 @@
JASC-PAL
0100
16
154 212 167
134 152 175
8 8 8
174 103 68
217 226 242
227 155 106
17 62 103
61 65 71
131 147 160
172 186 203
107 116 127
52 154 201
83 90 99
23 98 141
118 190 214
241 240 251

Binary file not shown.

After

Width:  |  Height:  |  Size: 804 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -0,0 +1,19 @@
JASC-PAL
0100
16
154 212 167
76 44 11
255 222 123
8 8 8
184 148 35
249 199 40
99 86 99
210 212 207
172 158 149
53 140 58
78 198 90
136 17 14
192 25 22
151 77 32
81 36 0
207 114 56

View File

@ -0,0 +1,19 @@
JASC-PAL
0100
16
154 212 167
61 17 25
249 189 116
8 8 8
199 100 36
235 148 37
99 86 99
210 212 207
172 158 149
39 146 176
70 220 210
51 50 50
93 92 92
116 61 52
61 17 25
152 96 57

Binary file not shown.

After

Width:  |  Height:  |  Size: 829 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 550 B

View File

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

View File

@ -0,0 +1,19 @@
JASC-PAL
0100
16
152 208 160
88 56 32
16 16 16
216 136 0
192 80 0
32 72 24
136 88 56
248 208 16
72 128 56
248 232 144
192 168 80
40 96 8
88 168 24
160 216 72
240 200 80
32 88 8

Binary file not shown.

After

Width:  |  Height:  |  Size: 674 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@ -0,0 +1,19 @@
JASC-PAL
0100
16
154 212 167
8 8 8
35 26 26
62 53 44
96 79 70
113 92 83
110 110 110
245 245 245
210 210 210
193 99 32
161 161 161
254 172 53
250 226 167
123 51 30
186 83 52
242 112 4

View File

@ -0,0 +1,19 @@
JASC-PAL
0100
16
154 212 167
8 8 8
82 81 103
149 148 170
203 204 218
249 248 250
91 100 116
228 232 235
191 197 204
193 99 32
148 156 170
254 172 53
250 226 167
97 95 107
150 148 160
209 204 217

Binary file not shown.

After

Width:  |  Height:  |  Size: 765 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 930 B

View File

@ -0,0 +1,19 @@
JASC-PAL
0100
16
154 212 167
0 163 172
96 240 240
210 248 248
8 8 8
179 146 50
122 86 30
130 138 163
240 194 19
1 68 78
19 163 180
59 202 202
19 114 130
60 68 78
202 202 218
162 202 218

View File

@ -0,0 +1,19 @@
JASC-PAL
0100
16
154 212 167
0 163 172
96 240 240
210 248 248
8 8 8
171 172 186
50 60 68
130 138 163
234 234 240
96 96 104
194 194 202
248 248 251
138 146 154
60 68 78
202 202 218
162 202 218

Binary file not shown.

After

Width:  |  Height:  |  Size: 840 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -0,0 +1,19 @@
JASC-PAL
0100
16
154 212 167
80 79 87
8 8 10
8 8 8
86 34 117
123 98 19
255 255 255
114 81 156
165 128 211
192 154 43
247 198 58
149 149 149
198 199 199
197 64 62
143 213 230
118 104 104

View File

@ -0,0 +1,19 @@
JASC-PAL
0100
16
154 212 167
94 82 82
8 8 10
8 8 8
104 84 22
140 73 2
255 255 255
182 149 49
231 206 90
201 118 6
247 159 53
175 160 153
198 199 199
11 125 232
206 206 214
118 104 104

View File

@ -54,7 +54,8 @@ struct __attribute__((packed, aligned(2))) BattleMoveEffect
const u8 *battleScript;
u16 battleTvScore:3;
u16 encourageEncore:1;
u16 flags:12; // coming soon...
u16 semiInvulnerableEffect:1;
u16 flags:11; // coming soon...
};
#define GET_MOVE_BATTLESCRIPT(move) gBattleMoveEffects[gMovesInfo[move].effect].battleScript
@ -846,10 +847,10 @@ struct BattleScripting
s32 bideDmg;
u8 multihitString[6];
bool8 expOnCatch;
u8 twoTurnsMoveStringId;
u8 unused;
u8 animArg1;
u8 animArg2;
u16 tripleKickPower;
u16 savedStringId;
u8 moveendState;
u8 savedStatChanger; // For further use, if attempting to change stat two times(ex. Moody)
u8 shiftSwitched; // When the game tells you the next enemy's pokemon and you switch. Option for noobs but oh well.

View File

@ -108,7 +108,7 @@ bool32 IsStatLoweringMoveEffect(u32 moveEffect);
bool32 IsMoveRedirectionPrevented(u32 move, u32 atkAbility);
bool32 IsMoveEncouragedToHit(u32 battlerAtk, u32 battlerDef, u32 move);
bool32 IsHazardMoveEffect(u32 moveEffect);
bool32 IsChargingMove(u32 battlerAtk, u32 effect);
bool32 IsTwoTurnNotSemiInvulnerableMove(u32 battlerAtk, u32 move);
void ProtectChecks(u32 battlerAtk, u32 battlerDef, u32 move, u32 predictedMove, s32 *score);
bool32 ShouldSetSandstorm(u32 battler, u32 ability, u32 holdEffect);
bool32 ShouldSetHail(u32 battler, u32 ability, u32 holdEffect);

View File

@ -417,6 +417,7 @@ extern const struct OamData gOamData_AffineDouble_ObjNormal_64x64;
extern const struct OamData gOamData_AffineDouble_ObjBlend_64x64;
extern const struct OamData gOamData_AffineDouble_ObjBlend_64x32;
extern const struct OamData gOamData_AffineDouble_ObjNormal_8x16;
extern const struct OamData gOamData_AffineDouble_ObjNormal_64x32;
extern const struct OamData gOamData_AffineOff_ObjBlend_16x16;
extern const struct OamData gOamData_AffineDouble_ObjBlend_16x16;
extern const struct OamData gOamData_AffineNormal_ObjNormal_8x8;

View File

@ -611,7 +611,6 @@ extern const u8 BattleScript_EffectSleepTalk[];
extern const u8 BattleScript_EffectDestinyBond[];
extern const u8 BattleScript_EffectSpite[];
extern const u8 BattleScript_EffectHealBell[];
extern const u8 BattleScript_EffectTripleKick[];
extern const u8 BattleScript_EffectMeanLook[];
extern const u8 BattleScript_EffectNightmare[];
extern const u8 BattleScript_EffectMinimize[];

View File

@ -225,6 +225,7 @@ bool32 MoveHasMoveEffect(u32 move, u32 moveEffect);
bool32 MoveHasMoveEffectWithChance(u32 move, u32 moveEffect, u32 chance);
bool32 MoveHasMoveEffectSelf(u32 move, u32 moveEffect);
bool32 MoveHasMoveEffectSelfArg(u32 move, u32 moveEffect, u32 argument);
bool32 MoveHasChargeTurnMoveEffect(u32 move);
bool32 CanSleep(u32 battler);
bool32 CanBePoisoned(u32 battlerAttacker, u32 battlerTarget);

View File

@ -179,15 +179,15 @@
// Var Settings
// To use the following features in scripting, replace the 0s with the var ID you're assigning it to.
// Eg: Replace with VAR_UNUSED_0x40F7 so you can use VAR_TERRAIN for that feature.
#define VAR_TERRAIN 0 // If this var has a value, assigning a STATUS_FIELD_xx_TERRAIN to it before battle causes the battle to start with that terrain active
// Eg: Replace with VAR_UNUSED_0x40F7 so you can use B_VAR_TERRAIN for that feature.
#define B_VAR_TERRAIN 0 // If this var has a value, assigning a STATUS_FIELD_xx_TERRAIN to it before battle causes the battle to start with that terrain active.
#define B_VAR_TERRAIN_TIMER 0 // If this var has a value greater or equal than 1 field terrains will last that number of turns, otherwise they will last until they're overwritten.
#define B_VAR_WILD_AI_FLAGS 0 // If not 0, you can use this var to add to default wild AI flags. NOT usable with flags above (1 << 15)
// Sky Battles
#define B_FLAG_SKY_BATTLE 0 // If this flag has a value, the player will be able to engage in scripted Sky Battles.
#define B_VAR_SKY_BATTLE 0 // If this var has a value, the game will remember the positions of Pokémon used in Sky Battles.
#define B_SKY_BATTLE_STRICT_ELIGIBILITY FALSE //If TRUE, Sky Battles will use the eligibility from Pokémon XY. If FALSE, all Flying-types or Pokémon with Levitate are allowed.
#define B_FLAG_SKY_BATTLE 0 // If this flag has a value, the player will be able to engage in scripted Sky Battles.
#define B_VAR_SKY_BATTLE 0 // If this var has a value, the game will remember the positions of Pokémon used in Sky Battles.
#define B_SKY_BATTLE_STRICT_ELIGIBILITY FALSE // If TRUE, Sky Battles will use the eligibility from Pokémon XY. If FALSE, all Flying-types or Pokémon with Levitate are allowed.
// Flag and Var settings
#define B_RESET_FLAGS_VARS_AFTER_WHITEOUT TRUE // If TRUE, Overworld_ResetBattleFlagsAndVars will reset battle-related Flags and Vars when the player whites out.

View File

@ -129,7 +129,7 @@
#define STATUS2_FLINCHED (1 << 3)
#define STATUS2_UPROAR (1 << 4 | 1 << 5 | 1 << 6)
#define STATUS2_UPROAR_TURN(num) ((num) << 4)
#define STATUS2_UNUSED (1 << 7)
#define STATUS2_TORMENT (1 << 7)
#define STATUS2_BIDE (1 << 8 | 1 << 9)
#define STATUS2_BIDE_TURN(num) (((num) << 8) & STATUS2_BIDE)
#define STATUS2_LOCK_CONFUSE (1 << 10 | 1 << 11) // e.g. Thrash
@ -139,7 +139,7 @@
#define STATUS2_POWDER (1 << 14)
#define STATUS2_INFATUATION (1 << 16 | 1 << 17 | 1 << 18 | 1 << 19) // 4 bits, one for every battler
#define STATUS2_INFATUATED_WITH(battler) (gBitTable[battler] << 16)
#define STATUS2_FOCUS_ENERGY (1 << 20)
#define STATUS2_DEFENSE_CURL (1 << 20)
#define STATUS2_TRANSFORMED (1 << 21)
#define STATUS2_RECHARGE (1 << 22)
#define STATUS2_RAGE (1 << 23)
@ -149,8 +149,9 @@
#define STATUS2_NIGHTMARE (1 << 27)
#define STATUS2_CURSED (1 << 28)
#define STATUS2_FORESIGHT (1 << 29)
#define STATUS2_DEFENSE_CURL (1 << 30)
#define STATUS2_TORMENT (1 << 31)
#define STATUS2_DRAGON_CHEER (1 << 30)
#define STATUS2_FOCUS_ENERGY (1 << 31)
#define STATUS2_FOCUS_ENERGY_ANY (STATUS2_DRAGON_CHEER | STATUS2_FOCUS_ENERGY)
#define STATUS3_LEECHSEED_BATTLER (1 << 0 | 1 << 1) // The battler to receive HP from Leech Seed
#define STATUS3_LEECHSEED (1 << 2)

View File

@ -414,8 +414,8 @@
// Below are used by AnimTask_ShakeMon2 and AnimTask_SetGrayscaleOrOriginalPal
#define ANIM_PLAYER_LEFT (MAX_BATTLERS_COUNT + 0)
#define ANIM_PLAYER_RIGHT (MAX_BATTLERS_COUNT + 1)
#define ANIM_OPPONENT_LEFT (MAX_BATTLERS_COUNT + 2)
#define ANIM_OPPONENT_LEFT (MAX_BATTLERS_COUNT + 1)
#define ANIM_PLAYER_RIGHT (MAX_BATTLERS_COUNT + 2)
#define ANIM_OPPONENT_RIGHT (MAX_BATTLERS_COUNT + 3)
#define ANIM_ATTACKER_FORCE (MAX_BATTLERS_COUNT + 4)

View File

@ -117,10 +117,8 @@ enum {
EFFECT_BELLY_DRUM,
EFFECT_PSYCH_UP,
EFFECT_MIRROR_COAT,
EFFECT_SKULL_BASH,
EFFECT_EARTHQUAKE,
EFFECT_FUTURE_SIGHT,
EFFECT_GUST,
EFFECT_SOLAR_BEAM,
EFFECT_THUNDER,
EFFECT_TELEPORT,
@ -172,7 +170,6 @@ enum {
EFFECT_WEATHER_BALL,
EFFECT_TICKLE,
EFFECT_COSMIC_POWER,
EFFECT_SKY_UPPERCUT,
EFFECT_BULK_UP,
EFFECT_WATER_SPORT,
EFFECT_CALM_MIND,
@ -318,7 +315,6 @@ enum {
EFFECT_BOLT_BEAK,
EFFECT_SKY_DROP,
EFFECT_EXPANDING_FORCE,
EFFECT_METEOR_BEAM,
EFFECT_RISING_VOLTAGE,
EFFECT_BEAK_BLAST,
EFFECT_COURT_CHANGE,
@ -352,6 +348,7 @@ enum {
EFFECT_RAIN_ALWAYS_HIT, // Unlike EFFECT_THUNDER, it doesn't get its accuracy reduced under sun.
EFFECT_SHED_TAIL,
EFFECT_UPPER_HAND,
EFFECT_DRAGON_CHEER,
NUM_BATTLE_MOVE_EFFECTS,
};

View File

@ -6,10 +6,10 @@
#define sBIDE_DMG (gBattleScripting + 0x04) // bideDmg
#define sMULTIHIT_STRING (gBattleScripting + 0x08) // multihitString
#define sEXP_CATCH (gBattleScripting + 0x0E) // expOnCatch
#define sTWOTURN_STRINGID (gBattleScripting + 0x0F) // twoTurnsMoveStringId
#define sUNUSED (gBattleScripting + 0x0F) // unused
#define sB_ANIM_ARG1 (gBattleScripting + 0x10) // animArg1
#define sB_ANIM_ARG2 (gBattleScripting + 0x11) // animArg2
#define sTRIPLE_KICK_POWER (gBattleScripting + 0x12) // tripleKickPower
#define sSAVED_STRINID (gBattleScripting + 0x12) // savedStringId
#define sMOVEEND_STATE (gBattleScripting + 0x14) // moveendState
#define sSAVED_STAT_CHANGER (gBattleScripting + 0x15) // savedStatChanger
#define sSHIFT_SWITCHED (gBattleScripting + 0x16) // shiftSwitched
@ -181,7 +181,7 @@
#define VARIOUS_TRY_FAIRY_LOCK 89
#define VARIOUS_JUMP_IF_NO_ALLY 90
#define VARIOUS_POISON_TYPE_IMMUNITY 91
#define VARIOUS_JUMP_IF_NO_HOLD_EFFECT 92
#define VARIOUS_JUMP_IF_HOLD_EFFECT 92
#define VARIOUS_INFATUATE_WITH_BATTLER 93
#define VARIOUS_SET_LAST_USED_ITEM 94
#define VARIOUS_PARALYZE_TYPE_IMMUNITY 95
@ -220,25 +220,24 @@
#define VARIOUS_SET_SKY_DROP 128
#define VARIOUS_CLEAR_SKY_DROP 129
#define VARIOUS_SKY_DROP_YAWN 130
#define VARIOUS_JUMP_IF_HOLD_EFFECT 131
#define VARIOUS_CURE_CERTAIN_STATUSES 132
#define VARIOUS_TRY_RESET_NEGATIVE_STAT_STAGES 133
#define VARIOUS_JUMP_IF_LAST_USED_ITEM_BERRY 134
#define VARIOUS_JUMP_IF_LAST_USED_ITEM_HOLD_EFFECT 135
#define VARIOUS_SAVE_BATTLER_ITEM 136
#define VARIOUS_RESTORE_BATTLER_ITEM 137
#define VARIOUS_BATTLER_ITEM_TO_LAST_USED_ITEM 138
#define VARIOUS_SET_BEAK_BLAST 139
#define VARIOUS_SWAP_SIDE_STATUSES 140
#define VARIOUS_SWAP_STATS 141
#define VARIOUS_TEATIME_INVUL 142
#define VARIOUS_TEATIME_TARGETS 143
#define VARIOUS_TRY_WIND_RIDER_POWER 144
#define VARIOUS_ACTIVATE_WEATHER_CHANGE_ABILITIES 145
#define VARIOUS_ACTIVATE_TERRAIN_CHANGE_ABILITIES 146
#define VARIOUS_STORE_HEALING_WISH 147
#define VARIOUS_HIT_SWITCH_TARGET_FAILED 148
#define VARIOUS_TRY_REVIVAL_BLESSING 149
#define VARIOUS_CURE_CERTAIN_STATUSES 131
#define VARIOUS_TRY_RESET_NEGATIVE_STAT_STAGES 132
#define VARIOUS_JUMP_IF_LAST_USED_ITEM_BERRY 133
#define VARIOUS_JUMP_IF_LAST_USED_ITEM_HOLD_EFFECT 134
#define VARIOUS_SAVE_BATTLER_ITEM 135
#define VARIOUS_RESTORE_BATTLER_ITEM 136
#define VARIOUS_BATTLER_ITEM_TO_LAST_USED_ITEM 137
#define VARIOUS_SET_BEAK_BLAST 138
#define VARIOUS_SWAP_SIDE_STATUSES 139
#define VARIOUS_SWAP_STATS 140
#define VARIOUS_TEATIME_INVUL 141
#define VARIOUS_TEATIME_TARGETS 142
#define VARIOUS_TRY_WIND_RIDER_POWER 143
#define VARIOUS_ACTIVATE_WEATHER_CHANGE_ABILITIES 144
#define VARIOUS_ACTIVATE_TERRAIN_CHANGE_ABILITIES 145
#define VARIOUS_STORE_HEALING_WISH 146
#define VARIOUS_HIT_SWITCH_TARGET_FAILED 147
#define VARIOUS_TRY_REVIVAL_BLESSING 148
// Cmd_manipulatedamage
#define DMG_CHANGE_SIGN 0

View File

@ -697,13 +697,14 @@
#define STRINGID_THESWAMPDISAPPEARED 695
#define STRINGID_PKMNTELLCHILLINGRECEPTIONJOKE 696
#define STRINGID_HOSPITALITYRESTORATION 697
#define STRINGID_ELECTROSHOCKCHARGING 698
#define STRINGID_ELECTROSHOTCHARGING 698
#define STRINGID_ITEMWASUSEDUP 699
#define STRINGID_ATTACKERLOSTITSTYPE 700
#define STRINGID_SHEDITSTAIL 701
#define STRINGID_SUPERSWEETAROMAWAFTS 702
#define STRINGID_CLOAKEDINAHARSHLIGHT 702
#define STRINGID_SUPERSWEETAROMAWAFTS 703
#define BATTLESTRINGS_COUNT 703
#define BATTLESTRINGS_COUNT 704
// This is the string id that gBattleStringsTable starts with.
// String ids before this (e.g. STRINGID_INTROMSG) are not in the table,
@ -747,22 +748,6 @@
#define B_MSG_LEECH_SEED_DRAIN 3
#define B_MSG_LEECH_SEED_OOZE 4
// gFirstTurnOfTwoStringIds
#define B_MSG_TURN1_RAZOR_WIND 0
#define B_MSG_TURN1_SOLAR_BEAM 1
#define B_MSG_TURN1_SKULL_BASH 2
#define B_MSG_TURN1_SKY_ATTACK 3
#define B_MSG_TURN1_FLY 4
#define B_MSG_TURN1_DIG 5
#define B_MSG_TURN1_DIVE 6
#define B_MSG_TURN1_BOUNCE 7
#define B_MSG_TURN1_PHANTOM_FORCE 8
#define B_MSG_TURN1_GEOMANCY 9
#define B_MSG_TURN1_FREEZE_SHOCK 10
#define B_MSG_TURN1_SKY_DROP 11
#define B_MSG_TURN1_METEOR_BEAM 12
#define B_MSG_TURN1_ELECTRO_SHOCK 13
// gMoveWeatherChangeStringIds
#define B_MSG_STARTED_RAIN 0
#define B_MSG_STARTED_DOWNPOUR 1

View File

@ -3,7 +3,7 @@
#define EXPANSION_VERSION_MAJOR 1
#define EXPANSION_VERSION_MINOR 7
#define EXPANSION_VERSION_PATCH 2
#define EXPANSION_VERSION_PATCH 3
// FALSE if this this version of Expansion is not a tagged commit, i.e.
// it contains unreleased changes.

View File

@ -123,6 +123,7 @@ extern const union AffineAnimCmd *const gAffineAnims_BattleSpriteContest[];
extern const union AnimCmd sAnim_GeneralFrame0[];
extern const union AnimCmd sAnim_GeneralFrame3[];
extern const union AnimCmd *const gAnims_MonPic[];
extern const union AnimCmd *const sAnims_Trainer[];
extern const struct TrainerSprite gTrainerSprites[];
extern const struct TrainerBacksprite gTrainerBacksprites[];

View File

@ -6,6 +6,7 @@
#include "config.h" // we need to define config before gba headers as print stuff needs the functions nulled before defines.
#include "gba/gba.h"
#include "fpmath.h"
#include "metaprogram.h"
#include "constants/global.h"
#include "constants/flags.h"
#include "constants/vars.h"
@ -66,7 +67,7 @@
// Used in cases where division by 0 can occur in the retail version.
// Avoids invalid opcodes on some emulators, and the otherwise UB.
#ifdef UBFIX
#define SAFE_DIV(a, b) ((b) ? (a) / (b) : 0)
#define SAFE_DIV(a, b) (((b) != 0) ? (a) / (b) : 0)
#else
#define SAFE_DIV(a, b) ((a) / (b))
#endif
@ -124,22 +125,6 @@
#define NUM_FLAG_BYTES ROUND_BITS_TO_BYTES(FLAGS_COUNT)
#define NUM_TRENDY_SAYING_BYTES ROUND_BITS_TO_BYTES(NUM_TRENDY_SAYINGS)
// Calls m0/m1/.../m8 depending on how many arguments are passed.
#define VARARG_8(m, ...) CAT(m, NARG_8(__VA_ARGS__))(__VA_ARGS__)
// This returns the number of arguments passed to it (up to 8).
#define NARG_8(...) NARG_8_(_, ##__VA_ARGS__, 8, 7, 6, 5, 4, 3, 2, 1, 0)
#define NARG_8_(_, a, b, c, d, e, f, g, h, N, ...) N
#define CAT(a, b) CAT_(a, b)
#define CAT_(a, b) a ## b
#define STR(...) STR_(__VA_ARGS__)
#define STR_(...) #__VA_ARGS__
// Converts a string to a compound literal, essentially making it a pointer to const u8
#define COMPOUND_STRING(str) (const u8[]) _(str)
// This produces an error at compile-time if expr is zero.
// It looks like file.c:line: size of array `id' is negative
#define STATIC_ASSERT(expr, id) typedef char id[(expr) ? 1 : -1];

134
include/metaprogram.h Normal file
View File

@ -0,0 +1,134 @@
/* Macros to aid with metaprogramming. */
#ifndef METAPROGRAM_H
#define METAPROGRAM_H
/* Calls m0/m1/.../m8 depending on how many arguments are passed. */
#define VARARG_8(m, ...) CAT(m, NARG_8(__VA_ARGS__))(__VA_ARGS__)
/* Returns the number of arguments passed to it (up to 8). */
#define NARG_8(...) NARG_8_(_, ##__VA_ARGS__, 8, 7, 6, 5, 4, 3, 2, 1, 0)
#define NARG_8_(_, a, b, c, d, e, f, g, h, N, ...) N
/* Expands 'a' and 'b' and then concatenates them. */
#define CAT(a, b) CAT_(a, b)
#define CAT_(a, b) a ## b
/* Expands '__VA_ARGS__' and then stringizes them. */
#define STR(...) STR_(__VA_ARGS__)
#define STR_(...) #__VA_ARGS__
/* Converts a string to a compound literal, essentially making it a pointer to const u8 */
#define COMPOUND_STRING(str) (const u8[]) _(str)
/* Expands to the first/second/third/fourth argument. */
#define FIRST(a, ...) a
#define SECOND(a, ...) __VA_OPT__(FIRST(__VA_ARGS__))
#define THIRD(a, ...) __VA_OPT__(SECOND(__VA_ARGS__))
#define FOURTH(a, ...) __VA_OPT__(THIRD(__VA_ARGS__))
/* Expands to everything but the first x arguments */
#define EXCEPT_1(a, ...) __VA_OPT__(__VA_ARGS__)
#define EXCEPT_2(a, ...) __VA_OPT__(EXCEPT_1(__VA_ARGS__))
#define EXCEPT_3(a, ...) __VA_OPT__(EXCEPT_2(__VA_ARGS__))
#define EXCEPT_4(a, ...) __VA_OPT__(EXCEPT_3(__VA_ARGS__))
/* 'UNPACK (x, y, z)' expands to 'x, y, z'.
* Useful for passing arguments which may contain commas into a macro. */
#define UNPACK(...) __VA_ARGS__
/* Expands to 'macro(...args, ...)'. */
#define INVOKE_WITH(macro, args, ...) INVOKE_WITH_(macro, UNPACK args __VA_OPT__(, __VA_ARGS__))
#define INVOKE_WITH_(macro, ...) macro(__VA_ARGS__)
/* Recursive macros.
* Based on https://www.scs.stanford.edu/~dm/blog/va-opt.html
*
* Macros prefixed with R_ are recursive, to correctly expand them the
* top-level macro which references them should use 'RECURSIVELY' around
* them. 'RECURSIVELY' cannot be nested, hence the top-level macro must
* use it so that a recursive macro is able to reference another
* recursive macro. */
#define RECURSIVELY(...) RECURSIVELY_4(RECURSIVELY_4(RECURSIVELY_4(RECURSIVELY_4(__VA_ARGS__))))
#define RECURSIVELY_4(...) RECURSIVELY_3(RECURSIVELY_3(RECURSIVELY_3(RECURSIVELY_3(__VA_ARGS__))))
#define RECURSIVELY_3(...) RECURSIVELY_2(RECURSIVELY_2(RECURSIVELY_2(RECURSIVELY_2(__VA_ARGS__))))
#define RECURSIVELY_2(...) RECURSIVELY_1(RECURSIVELY_1(RECURSIVELY_1(RECURSIVELY_1(__VA_ARGS__))))
#define RECURSIVELY_1(...) __VA_ARGS__
/* Useful for deferring expansion until the second scan. See
* https://www.scs.stanford.edu/~dm/blog/va-opt.html for more info. */
#define PARENS ()
/* Expands to 'macro(a)' for each 'a' in '...' */
#define R_FOR_EACH(macro, ...) __VA_OPT__(R_FOR_EACH_(macro, __VA_ARGS__))
#define R_FOR_EACH_(macro, a, ...) macro(a) __VA_OPT__(R_FOR_EACH_P PARENS (macro, __VA_ARGS__))
#define R_FOR_EACH_P() R_FOR_EACH_
/* Expands to 'macro(...args, a)' for each 'a' in '...'. */
#define R_FOR_EACH_WITH(macro, args, ...) __VA_OPT__(R_FOR_EACH_WITH_(macro, args, __VA_ARGS__))
#define R_FOR_EACH_WITH_(macro, args, a, ...) INVOKE_WITH(macro, args, a) __VA_OPT__(R_FOR_EACH_WITH_P PARENS (macro, args, __VA_ARGS__))
#define R_FOR_EACH_WITH_P() R_FOR_EACH_WITH_
/* Picks the xth VA_ARG if it exists, otherwise returns a default value */
#define DEFAULT(_default, ...) FIRST(__VA_OPT__(__VA_ARGS__, ) _default)
#define DEFAULT_2(_default, ...) DEFAULT(_default __VA_OPT__(, SECOND(__VA_ARGS__)))
#define DEFAULT_3(_default, ...) DEFAULT(_default __VA_OPT__(, THIRD(__VA_ARGS__)))
#define DEFAULT_4(_default, ...) DEFAULT(_default __VA_OPT__(, FOURTH(__VA_ARGS__)))
/* (Credit to MGriffin) A rather monstrous way of finding the set bit in a word.
Invalid input causes a compiler error. Sample: https://cexplore.karathan.at/z/x1hm7B */
#define BIT_INDEX(n) \
(n) == (1 << 0) ? 0 : \
(n) == (1 << 1) ? 1 : \
(n) == (1 << 2) ? 2 : \
(n) == (1 << 3) ? 3 : \
(n) == (1 << 4) ? 4 : \
(n) == (1 << 5) ? 5 : \
(n) == (1 << 6) ? 6 : \
(n) == (1 << 7) ? 7 : \
(n) == (1 << 8) ? 8 : \
(n) == (1 << 9) ? 9 : \
(n) == (1 << 10) ? 10 : \
(n) == (1 << 11) ? 11 : \
(n) == (1 << 12) ? 12 : \
(n) == (1 << 13) ? 13 : \
(n) == (1 << 14) ? 14 : \
(n) == (1 << 15) ? 15 : \
(n) == (1 << 16) ? 16 : \
(n) == (1 << 17) ? 17 : \
(n) == (1 << 18) ? 18 : \
(n) == (1 << 19) ? 19 : \
(n) == (1 << 20) ? 20 : \
(n) == (1 << 21) ? 21 : \
(n) == (1 << 22) ? 22 : \
(n) == (1 << 23) ? 23 : \
(n) == (1 << 24) ? 24 : \
(n) == (1 << 25) ? 25 : \
(n) == (1 << 26) ? 26 : \
(n) == (1 << 27) ? 27 : \
(n) == (1 << 28) ? 28 : \
(n) == (1 << 29) ? 29 : \
(n) == (1 << 30) ? 30 : \
(n) == (1 << 31) ? 31 : \
*(u32 *)NULL
#define COMPRESS_BITS_0 0, 1
#define COMPRESS_BITS_1 1, 1
#define COMPRESS_BITS_2 2, 1
#define COMPRESS_BITS_3 3, 1
#define COMPRESS_BITS_4 4, 1
#define COMPRESS_BITS_5 5, 1
#define COMPRESS_BITS_6 6, 1
#define COMPRESS_BITS_7 7, 1
/* Will try and compress a set bit (or up to three sequential bits) into a single byte
Input must be of the form (upper << lower) where upper can be up to 3, lower up to 31 */
#define COMPRESS_BITS(_val) COMPRESS_BITS_STEP_2 _val
#define COMPRESS_BITS_STEP_2(_unpacked) COMPRESS_BITS_STEP_3(COMPRESS_BITS_## _unpacked)
#define COMPRESS_BITS_STEP_3(...) COMPRESS_BITS_STEP_4(__VA_ARGS__)
#define COMPRESS_BITS_STEP_4(upper, lower) (((upper % 8) << 5) + (BIT_INDEX(lower)))
/* Will read a compressed bit stored by COMPRESS_BIT into a single byte */
#define UNCOMPRESS_BITS(compressed) ((compressed >> 5) << (compressed & 0x1F))
#endif

View File

@ -813,7 +813,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
if (IsSemiInvulnerable(battlerDef, move) && moveEffect != EFFECT_SEMI_INVULNERABLE && AI_WhoStrikesFirst(battlerAtk, battlerDef, move) == AI_IS_FASTER)
RETURN_SCORE_MINUS(20); // if target off screen and we go first, don't use move
if (IsChargingMove(battlerAtk, moveEffect) && CanTargetFaintAi(battlerDef, battlerAtk))
if (IsTwoTurnNotSemiInvulnerableMove(battlerAtk, move) && CanTargetFaintAi(battlerDef, battlerAtk))
RETURN_SCORE_MINUS(10);
// check if negates type
@ -1477,7 +1477,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
ADJUST_SCORE(-10);
break;
case EFFECT_FOCUS_ENERGY:
if (gBattleMons[battlerAtk].status2 & STATUS2_FOCUS_ENERGY)
if (gBattleMons[battlerAtk].status2 & STATUS2_FOCUS_ENERGY_ANY)
ADJUST_SCORE(-10);
break;
case EFFECT_CONFUSE:
@ -1762,6 +1762,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
break;
case EFFECT_FOLLOW_ME:
case EFFECT_HELPING_HAND:
case EFFECT_DRAGON_CHEER:
if (!isDoubleBattle
|| !IsBattlerAlive(BATTLE_PARTNER(battlerAtk))
|| PartnerHasSameMoveEffectWithoutTarget(BATTLE_PARTNER(battlerAtk), move, aiData->partnerMove)
@ -2781,6 +2782,13 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
RETURN_SCORE_PLUS(DECENT_EFFECT); // partner has earthquake or magnitude -> good idea to use magnet rise
}
break;
case EFFECT_DRAGON_CHEER:
if (gBattleMons[battlerAtkPartner].status2 & STATUS2_FOCUS_ENERGY_ANY || !HasDamagingMove(battlerAtkPartner))
ADJUST_SCORE(-5);
else if (atkPartnerHoldEffect == HOLD_EFFECT_SCOPE_LENS
|| IS_BATTLER_OF_TYPE(battlerAtkPartner, TYPE_DRAGON)
|| gMovesInfo[aiData->partnerMove].criticalHitStage > 0)
ADJUST_SCORE(GOOD_EFFECT);
} // our effect relative to partner
// consider global move effects
@ -3125,7 +3133,7 @@ static s32 AI_CompareDamagingMoves(u32 battlerAtk, u32 battlerDef, u32 currId)
s32 score = 0;
s32 leastHits = 1000;
u16 *moves = GetMovesArray(battlerAtk);
bool8 isChargingMoveEffect[MAX_MON_MOVES];
bool8 isTwoTurnNotSemiInvulnerableMove[MAX_MON_MOVES];
for (i = 0; i < MAX_MON_MOVES; i++)
{
@ -3137,13 +3145,13 @@ static s32 AI_CompareDamagingMoves(u32 battlerAtk, u32 battlerDef, u32 currId)
leastHits = noOfHits[i];
}
viableMoveScores[i] = AI_SCORE_DEFAULT;
isChargingMoveEffect[i] = IsChargingMove(battlerAtk, gMovesInfo[moves[i]].effect);
isTwoTurnNotSemiInvulnerableMove[i] = IsTwoTurnNotSemiInvulnerableMove(battlerAtk, moves[i]);
}
else
{
noOfHits[i] = -1;
viableMoveScores[i] = 0;
isChargingMoveEffect[i] = FALSE;
isTwoTurnNotSemiInvulnerableMove[i] = FALSE;
}
/*
MgbaPrintf_("%S: required hits: %d Dmg: %d", gMoveNames[moves[i]], noOfHits[i], AI_DATA->simulatedDmg[battlerAtk][battlerDef][i]);
@ -3167,9 +3175,9 @@ static s32 AI_CompareDamagingMoves(u32 battlerAtk, u32 battlerDef, u32 currId)
{
multipleBestMoves = TRUE;
// We need to make sure it's the current move which is objectively better.
if (isChargingMoveEffect[i] && !isChargingMoveEffect[currId])
if (isTwoTurnNotSemiInvulnerableMove[i] && !isTwoTurnNotSemiInvulnerableMove[currId])
viableMoveScores[i] -= 3;
else if (!isChargingMoveEffect[i] && isChargingMoveEffect[currId])
else if (!isTwoTurnNotSemiInvulnerableMove[i] && isTwoTurnNotSemiInvulnerableMove[currId])
viableMoveScores[currId] -= 3;
switch (CompareMoveAccuracies(battlerAtk, battlerDef, currId, i))

View File

@ -2088,7 +2088,7 @@ static bool32 ShouldUseItem(u32 battler)
break;
case EFFECT_ITEM_SET_FOCUS_ENERGY:
if (!gDisableStructs[battler].isFirstTurn
|| gBattleMons[battler].status2 & STATUS2_FOCUS_ENERGY
|| gBattleMons[battler].status2 & STATUS2_FOCUS_ENERGY_ANY
|| AI_OpponentCanFaintAiWithMod(battler, 0))
break;
shouldUse = TRUE;

View File

@ -2016,17 +2016,14 @@ bool32 HasSnatchAffectedMove(u32 battler)
CHECK_MOVE_FLAG(snatchAffected);
}
bool32 IsChargingMove(u32 battlerAtk, u32 effect)
bool32 IsTwoTurnNotSemiInvulnerableMove(u32 battlerAtk, u32 move)
{
switch (effect)
switch (gMovesInfo[move].effect)
{
case EFFECT_SOLAR_BEAM:
if (AI_GetWeather(AI_DATA) & B_WEATHER_SUN)
return FALSE;
case EFFECT_SKULL_BASH:
case EFFECT_METEOR_BEAM:
case EFFECT_TWO_TURNS_ATTACK:
return !(AI_DATA->holdEffects[battlerAtk] == HOLD_EFFECT_POWER_HERB);
return !(AI_DATA->holdEffects[battlerAtk] == HOLD_EFFECT_POWER_HERB
|| (AI_GetWeather(AI_DATA) & gMovesInfo[move].argument));
default:
return FALSE;
}

View File

@ -442,28 +442,44 @@ static void Cmd_unloadspritegfx(void)
static u8 GetBattleAnimMoveTargets(u8 battlerArgIndex, u8 *targets)
{
u8 numTargets = 0;
int idx = 0;
u32 battler = gBattleAnimArgs[battlerArgIndex];
switch (GetBattlerMoveTargetType(gBattleAnimAttacker, gAnimMoveIndex))
u32 battlerAnimId = gBattleAnimArgs[battlerArgIndex]; // ANIM_xx input
u32 i;
u32 ignoredTgt = gBattlerAttacker;
u32 target = GetBattlerMoveTargetType(gBattleAnimAttacker, gAnimMoveIndex);
switch (battlerAnimId)
{
case ANIM_ATTACKER:
case ANIM_ATK_PARTNER:
ignoredTgt = gBattlerTarget;
break;
case ANIM_TARGET:
case ANIM_DEF_PARTNER:
ignoredTgt = gBattlerAttacker;
break;
}
switch (target)
{
case MOVE_TARGET_FOES_AND_ALLY:
if (IS_ALIVE_AND_PRESENT(BATTLE_PARTNER(BATTLE_OPPOSITE(battler))))
if (battlerAnimId == ANIM_ATTACKER)
{
targets[idx++] = BATTLE_PARTNER(BATTLE_OPPOSITE(battler));
numTargets++;
targets[numTargets++] = gBattleAnimAttacker;
}
// fallthrough
case MOVE_TARGET_BOTH:
if (IS_ALIVE_AND_PRESENT(battler))
else
{
targets[idx++] = battler;
numTargets++;
for (i = 0; i < gBattlersCount; i++)
{
if (i != gBattleAnimAttacker && IS_ALIVE_AND_PRESENT(i))
targets[numTargets++] = i + MAX_BATTLERS_COUNT; // anim ids for battler ids
}
}
battler = BATTLE_PARTNER(battler);
if (IS_ALIVE_AND_PRESENT(battler))
break;
case MOVE_TARGET_BOTH: // all opponents
for (i = 0; i < gBattlersCount; i++)
{
targets[idx++] = battler;
numTargets++;
if (i != ignoredTgt && !IsAlly(i, ignoredTgt) && IS_ALIVE_AND_PRESENT(i))
targets[numTargets++] = i + MAX_BATTLERS_COUNT;
}
break;
default:
@ -541,7 +557,7 @@ static void Cmd_createsprite(void)
static void CreateSpriteOnTargets(const struct SpriteTemplate *template, u8 argVar, u8 battlerArgIndex, u8 argsCount, bool32 overwriteAnimTgt)
{
u32 i;
u32 i, battler;
u8 targets[MAX_BATTLERS_COUNT];
int ntargets;
s16 subpriority;
@ -560,12 +576,13 @@ static void CreateSpriteOnTargets(const struct SpriteTemplate *template, u8 argV
for (i = 0; i < ntargets; i++)
{
battler = GetAnimBattlerId(targets[i]);
if (overwriteAnimTgt)
gBattleAnimArgs[battlerArgIndex] = targets[i];
if (CreateSpriteAndAnimate(template,
GetBattlerSpriteCoord(targets[i], BATTLER_COORD_X_2),
GetBattlerSpriteCoord(targets[i], BATTLER_COORD_Y_PIC_OFFSET),
GetBattlerSpriteCoord(battler, BATTLER_COORD_X_2),
GetBattlerSpriteCoord(battler, BATTLER_COORD_Y_PIC_OFFSET),
subpriority) != MAX_SPRITES) // Don't increment the task count if the sprite couldn't be created(i.e. there are too many created sprites atm).
{
gAnimVisualTaskCount++;
@ -904,14 +921,20 @@ static void Cmd_monbg(void)
u8 GetAnimBattlerId(u8 wantedBattler)
{
if (wantedBattler == ANIM_ATTACKER)
switch (wantedBattler)
{
case ANIM_ATTACKER:
default:
return gBattleAnimAttacker;
else if (wantedBattler == ANIM_TARGET)
case ANIM_TARGET:
return gBattleAnimTarget;
else if (wantedBattler == ANIM_ATK_PARTNER)
case ANIM_ATK_PARTNER:
return BATTLE_PARTNER(gBattleAnimAttacker);
else
case ANIM_DEF_PARTNER:
return BATTLE_PARTNER(gBattleAnimTarget);
case ANIM_PLAYER_LEFT ... ANIM_OPPONENT_RIGHT:
return wantedBattler - MAX_BATTLERS_COUNT;
}
}
bool8 IsBattlerSpriteVisible(u8 battlerId)

View File

@ -479,6 +479,17 @@ const struct SpriteTemplate gVoltTackleBoltSpriteTemplate =
.callback = AnimVoltTackleBolt,
};
const struct SpriteTemplate gFairyLockChainsSpriteTemplate =
{
.tileTag = ANIM_TAG_FAIRY_LOCK_CHAINS,
.paletteTag = ANIM_TAG_FAIRY_LOCK_CHAINS,
.oam = &gOamData_AffineOff_ObjNormal_64x32,
.anims = gDummySpriteAnimTable,
.images = NULL,
.affineAnims = gDummySpriteAffineAnimTable,
.callback = AnimVoltTackleBolt,
};
const struct SpriteTemplate gGrowingShockWaveOrbSpriteTemplate =
{
.tileTag = ANIM_TAG_CIRCLE_OF_LIGHT,
@ -1190,11 +1201,20 @@ void AnimTask_VoltTackleBolt(u8 taskId)
static bool8 CreateVoltTackleBolt(struct Task *task, u8 taskId)
{
u8 spriteId = CreateSprite(&gVoltTackleBoltSpriteTemplate, task->data[3], task->data[5], 35);
u32 spriteId;
bool32 isFairyLock = (gAnimMoveIndex == MOVE_FAIRY_LOCK);
if (isFairyLock)
spriteId = CreateSprite(&gFairyLockChainsSpriteTemplate, task->data[3], task->data[5] + 10, 35);
else
spriteId = CreateSprite(&gVoltTackleBoltSpriteTemplate, task->data[3], task->data[5], 35);
if (spriteId != MAX_SPRITES)
{
gSprites[spriteId].data[6] = taskId;
gSprites[spriteId].data[7] = 7;
gSprites[spriteId].data[1] = isFairyLock ? 25 : 12; // How long the chains / bolts stay on screen.
gSprites[spriteId].data[2] = isFairyLock; // Whether to destroy the Oam Matrix.
task->data[7]++;
}
@ -1220,10 +1240,11 @@ static bool8 CreateVoltTackleBolt(struct Task *task, u8 taskId)
static void AnimVoltTackleBolt(struct Sprite *sprite)
{
if (++sprite->data[0] > 12)
if (++sprite->data[0] > sprite->data[1])
{
gTasks[sprite->data[6]].data[sprite->data[7]]--;
FreeOamMatrix(sprite->oam.matrixNum);
if (!sprite->data[2])
FreeOamMatrix(sprite->oam.matrixNum);
DestroySprite(sprite);
}
}

View File

@ -474,8 +474,8 @@ void AnimShadowBall(struct Sprite *sprite)
sprite->data[3] = gBattleAnimArgs[2];
sprite->data[4] = sprite->x << 4;
sprite->data[5] = sprite->y << 4;
sprite->data[6] = ((oldPosX - sprite->x) << 4) / (gBattleAnimArgs[0] << 1);
sprite->data[7] = ((oldPosY - sprite->y) << 4) / (gBattleAnimArgs[0] << 1);
sprite->data[6] = SAFE_DIV(((oldPosX - sprite->x) << 4), (gBattleAnimArgs[0] << 1));
sprite->data[7] = SAFE_DIV(((oldPosY - sprite->y) << 4), (gBattleAnimArgs[0] << 1));
sprite->callback = AnimShadowBall_Step;
}

View File

@ -309,45 +309,51 @@ u8 GetBattlerYCoordWithElevation(u8 battlerId)
u8 GetAnimBattlerSpriteId(u8 animBattler)
{
u8 *sprites;
u32 partner;
if (animBattler == ANIM_ATTACKER)
switch (animBattler)
{
case ANIM_ATTACKER:
if (IsBattlerSpritePresent(gBattleAnimAttacker))
{
sprites = gBattlerSpriteIds;
return sprites[gBattleAnimAttacker];
return gBattlerSpriteIds[gBattleAnimAttacker];
}
else
{
return SPRITE_NONE;
}
}
else if (animBattler == ANIM_TARGET)
{
break;
case ANIM_TARGET:
if (IsBattlerSpritePresent(gBattleAnimTarget))
{
sprites = gBattlerSpriteIds;
return sprites[gBattleAnimTarget];
return gBattlerSpriteIds[gBattleAnimTarget];
}
else
{
return SPRITE_NONE;
}
}
else if (animBattler == ANIM_ATK_PARTNER)
{
break;
case ANIM_ATK_PARTNER:
if (!IsBattlerSpriteVisible(BATTLE_PARTNER(gBattleAnimAttacker)))
return SPRITE_NONE;
else
return gBattlerSpriteIds[BATTLE_PARTNER(gBattleAnimAttacker)];
}
else
{
break;
case ANIM_DEF_PARTNER:
if (IsBattlerSpriteVisible(BATTLE_PARTNER(gBattleAnimTarget)))
return gBattlerSpriteIds[BATTLE_PARTNER(gBattleAnimTarget)];
else
return SPRITE_NONE;
break;
case ANIM_PLAYER_LEFT ... ANIM_OPPONENT_RIGHT:
partner = animBattler - MAX_BATTLERS_COUNT;
if (IsBattlerSpriteVisible(partner))
return gBattlerSpriteIds[partner];
else
return SPRITE_NONE;
break;
default:
return SPRITE_NONE;
}
}
@ -1025,8 +1031,8 @@ void InitSpriteDataForLinearTranslation(struct Sprite *sprite)
{
s16 x = (sprite->data[2] - sprite->data[1]) << 8;
s16 y = (sprite->data[4] - sprite->data[3]) << 8;
sprite->data[1] = x / sprite->data[0];
sprite->data[2] = y / sprite->data[0];
sprite->data[1] = SAFE_DIV(x, sprite->data[0]);
sprite->data[2] = SAFE_DIV(y, sprite->data[0]);
sprite->data[4] = 0;
sprite->data[3] = 0;
}

View File

@ -462,9 +462,7 @@ static void LinkOpponentHandleDrawTrainerPic(u32 battler)
}
}
BtlController_HandleDrawTrainerPic(battler, trainerPicId, TRUE,
xPos, 40 + 4 * (8 - gTrainerSprites[trainerPicId].y_offset),
-1);
BtlController_HandleDrawTrainerPic(battler, trainerPicId, TRUE, xPos, 40, -1);
}
static void LinkOpponentHandleTrainerSlide(u32 battler)

View File

@ -484,9 +484,7 @@ static void OpponentHandleDrawTrainerPic(u32 battler)
xPos = 176;
}
BtlController_HandleDrawTrainerPic(battler, trainerPicId, TRUE,
xPos, 40 + 4 * (8 - gTrainerSprites[trainerPicId].y_offset),
-1);
BtlController_HandleDrawTrainerPic(battler, trainerPicId, TRUE, xPos, 40, -1);
}
static void OpponentHandleTrainerSlide(u32 battler)

View File

@ -1882,7 +1882,7 @@ static void PlayerHandleDrawTrainerPic(u32 battler)
if (gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER && gPartnerTrainerId < TRAINER_PARTNER(PARTNER_NONE))
{
xPos = 90;
yPos = (8 - gTrainerSprites[trainerPicId].y_offset) * 4 + 80;
yPos = 80;
}
else
{

View File

@ -307,13 +307,13 @@ static void PlayerPartnerHandleDrawTrainerPic(u32 battler)
{
trainerPicId = gTrainers[gPartnerTrainerId].trainerPic;
xPos = 60;
yPos = (8 - gTrainerSprites[trainerPicId].y_offset) * 4 + 80;
yPos = 80;
}
else
{
trainerPicId = GetFrontierTrainerFrontSpriteId(gPartnerTrainerId);
xPos = 32;
yPos = (8 - gTrainerSprites[trainerPicId].y_offset) * 4 + 80;
yPos = 80;
}
// Use back pic only if the partner Steven or is custom.

View File

@ -420,9 +420,7 @@ static void RecordedOpponentHandleDrawTrainerPic(u32 battler)
}
}
BtlController_HandleDrawTrainerPic(battler, trainerPicId, TRUE,
xPos, 40 + 4 * (8 - gTrainerSprites[trainerPicId].y_offset),
-1);
BtlController_HandleDrawTrainerPic(battler, trainerPicId, TRUE, xPos, 40, -1);
}
static void RecordedOpponentHandleTrainerSlideBack(u32 battler)

View File

@ -393,7 +393,7 @@ static void RecordedPlayerHandleDrawTrainerPic(u32 battler)
if (gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER)
{
xPos = 90;
yPos = (8 - gTrainerSprites[trainerPicId].y_offset) * 4 + 80;
yPos = 80;
}
else
{

View File

@ -2542,10 +2542,7 @@ void BtlController_HandleTrainerSlide(u32 battler, u32 trainerPicId)
{
DecompressTrainerFrontPic(trainerPicId, battler);
SetMultiuseSpriteTemplateToTrainerBack(trainerPicId, GetBattlerPosition(battler));
gBattlerSpriteIds[battler] = CreateSprite(&gMultiuseSpriteTemplate,
176,
(8 - gTrainerSprites[trainerPicId].y_offset) * 4 + 40,
30);
gBattlerSpriteIds[battler] = CreateSprite(&gMultiuseSpriteTemplate, 176, 40, 30);
gSprites[gBattlerSpriteIds[battler]].oam.affineParam = trainerPicId;
gSprites[gBattlerSpriteIds[battler]].oam.paletteNum = IndexOfSpritePaletteTag(gTrainerSprites[trainerPicId].palette.tag);
gSprites[gBattlerSpriteIds[battler]].x2 = 96;

View File

@ -764,6 +764,22 @@ static void PutMovesPointsText(struct BattleDebugMenu *data)
Free(text);
}
static void CleanUpAiInfoWindow(u8 taskId)
{
u32 i;
struct BattleDebugMenu *data = GetStructPtr(taskId);
FreeMonIconPalettes();
for (i = 0; i < MAX_BATTLERS_COUNT; i++)
{
if (data->spriteIds.aiIconSpriteIds[i] != 0xFF)
FreeAndDestroyMonIconSprite(&gSprites[data->spriteIds.aiIconSpriteIds[i]]);
}
FreeAndDestroyMonPicSprite(data->aiMonSpriteId);
ClearWindowTilemap(data->aiMovesWindowId);
RemoveWindow(data->aiMovesWindowId);
}
static void Task_ShowAiPoints(u8 taskId)
{
u32 i, count;
@ -784,6 +800,7 @@ static void Task_ShowAiPoints(u8 taskId)
if (++data->aiBattlerId >= gBattlersCount)
data->aiBattlerId = 0;
}
data->battlerId = data->aiBattlerId;
LoadMonIconPalettes();
for (count = 0, i = 0; i < MAX_BATTLERS_COUNT; i++)
@ -822,7 +839,27 @@ static void Task_ShowAiPoints(u8 taskId)
break;
// Input
case 2:
if (JOY_NEW(SELECT_BUTTON | B_BUTTON))
if (JOY_NEW(R_BUTTON) && IsDoubleBattle())
{
CleanUpAiInfoWindow(taskId);
do {
data->battlerId++;
data->battlerId %= gBattlersCount;
} while (!IsBattlerAlive(data->battlerId));
data->aiViewState = 0;
}
else if (JOY_NEW(L_BUTTON) && IsDoubleBattle())
{
CleanUpAiInfoWindow(taskId);
do {
if (data->battlerId == 0)
data->battlerId = gBattlersCount - 1;
else
data->battlerId--;
} while (!IsBattlerAlive(data->battlerId) || !BattlerHasAi(data->battlerId));
data->aiViewState = 0;
}
else if (JOY_NEW(SELECT_BUTTON | B_BUTTON))
{
SwitchToDebugView(taskId);
HideBg(1);
@ -1093,19 +1130,7 @@ static void SwitchToDebugViewFromAiParty(u8 taskId)
static void SwitchToDebugView(u8 taskId)
{
u32 i;
struct BattleDebugMenu *data = GetStructPtr(taskId);
FreeMonIconPalettes();
for (i = 0; i < MAX_BATTLERS_COUNT; i++)
{
if (data->spriteIds.aiIconSpriteIds[i] != 0xFF)
FreeAndDestroyMonIconSprite(&gSprites[data->spriteIds.aiIconSpriteIds[i]]);
}
FreeAndDestroyMonPicSprite(data->aiMonSpriteId);
ClearWindowTilemap(data->aiMovesWindowId);
RemoveWindow(data->aiMovesWindowId);
CleanUpAiInfoWindow(taskId);
gTasks[taskId].func = Task_DebugMenuProcessInput;
}

View File

@ -322,85 +322,83 @@ const u8 gTypeNames[NUMBER_OF_MON_TYPES][TYPE_NAME_LENGTH + 1] =
[TYPE_FAIRY] = _("Fairy"),
};
#define DEFAULT_MONEY 5
#define DEFAULT_BALL ITEM_POKE_BALL
#define TRAINER_CLASS(trainerClass, trainerName, trainerMoney, trainerBall) \
[TRAINER_CLASS_##trainerClass] = \
{ \
.name = _(trainerName), \
.money = trainerMoney, \
.ball = trainerBall, \
// extra args are money and ball
#define TRAINER_CLASS(trainerClass, trainerName, ...) \
[TRAINER_CLASS_##trainerClass] = \
{ \
.name = _(trainerName), \
.money = DEFAULT(5, __VA_ARGS__), \
.ball = DEFAULT_2(ITEM_POKE_BALL, __VA_ARGS__), \
}
const struct TrainerClass gTrainerClasses[TRAINER_CLASS_COUNT] =
{
TRAINER_CLASS(PKMN_TRAINER_1, "{PKMN} TRAINER", DEFAULT_MONEY, DEFAULT_BALL),
TRAINER_CLASS(PKMN_TRAINER_2, "{PKMN} TRAINER", DEFAULT_MONEY, DEFAULT_BALL),
TRAINER_CLASS(HIKER, "HIKER", 10, DEFAULT_BALL),
TRAINER_CLASS(TEAM_AQUA, "TEAM AQUA", 5, DEFAULT_BALL),
TRAINER_CLASS(PKMN_TRAINER_1, "{PKMN} TRAINER"),
TRAINER_CLASS(PKMN_TRAINER_2, "{PKMN} TRAINER"),
TRAINER_CLASS(HIKER, "HIKER", 10),
TRAINER_CLASS(TEAM_AQUA, "TEAM AQUA"),
TRAINER_CLASS(PKMN_BREEDER, "{PKMN} BREEDER", 10, B_TRAINER_CLASS_POKE_BALLS >= GEN_8 ? ITEM_HEAL_BALL : ITEM_FRIEND_BALL),
TRAINER_CLASS(COOLTRAINER, "COOLTRAINER", 12, ITEM_ULTRA_BALL),
TRAINER_CLASS(BIRD_KEEPER, "BIRD KEEPER", 8, DEFAULT_BALL),
TRAINER_CLASS(BIRD_KEEPER, "BIRD KEEPER", 8),
TRAINER_CLASS(COLLECTOR, "COLLECTOR", 15, ITEM_PREMIER_BALL),
TRAINER_CLASS(SWIMMER_M, "SWIMMER♂", 2, ITEM_DIVE_BALL),
TRAINER_CLASS(TEAM_MAGMA, "TEAM MAGMA", 5, DEFAULT_BALL),
TRAINER_CLASS(EXPERT, "EXPERT", 10, DEFAULT_BALL),
TRAINER_CLASS(AQUA_ADMIN, "AQUA ADMIN", 10, DEFAULT_BALL),
TRAINER_CLASS(TEAM_MAGMA, "TEAM MAGMA"),
TRAINER_CLASS(EXPERT, "EXPERT", 10),
TRAINER_CLASS(AQUA_ADMIN, "AQUA ADMIN", 10),
TRAINER_CLASS(BLACK_BELT, "BLACK BELT", 8, ITEM_ULTRA_BALL),
TRAINER_CLASS(AQUA_LEADER, "AQUA LEADER", 20, ITEM_MASTER_BALL),
TRAINER_CLASS(HEX_MANIAC, "HEX MANIAC", 6, DEFAULT_BALL),
TRAINER_CLASS(AROMA_LADY, "AROMA LADY", 10, DEFAULT_BALL),
TRAINER_CLASS(RUIN_MANIAC, "RUIN MANIAC", 15, DEFAULT_BALL),
TRAINER_CLASS(INTERVIEWER, "INTERVIEWER", 12, DEFAULT_BALL),
TRAINER_CLASS(TUBER_F, "TUBER", 1, DEFAULT_BALL),
TRAINER_CLASS(TUBER_M, "TUBER", 1, DEFAULT_BALL),
TRAINER_CLASS(LADY, "LADY", 50, DEFAULT_BALL),
TRAINER_CLASS(BEAUTY, "BEAUTY", 20, DEFAULT_BALL),
TRAINER_CLASS(RICH_BOY, "RICH BOY", 50, DEFAULT_BALL),
TRAINER_CLASS(POKEMANIAC, "POKéMANIAC", 15, DEFAULT_BALL),
TRAINER_CLASS(GUITARIST, "GUITARIST", 8, DEFAULT_BALL),
TRAINER_CLASS(KINDLER, "KINDLER", 8, DEFAULT_BALL),
TRAINER_CLASS(CAMPER, "CAMPER", 4, DEFAULT_BALL),
TRAINER_CLASS(PICNICKER, "PICNICKER", 4, DEFAULT_BALL),
TRAINER_CLASS(BUG_MANIAC, "BUG MANIAC", 15, DEFAULT_BALL),
TRAINER_CLASS(PSYCHIC, "PSYCHIC", 6, DEFAULT_BALL),
TRAINER_CLASS(HEX_MANIAC, "HEX MANIAC", 6),
TRAINER_CLASS(AROMA_LADY, "AROMA LADY", 10),
TRAINER_CLASS(RUIN_MANIAC, "RUIN MANIAC", 15),
TRAINER_CLASS(INTERVIEWER, "INTERVIEWER", 12),
TRAINER_CLASS(TUBER_F, "TUBER", 1),
TRAINER_CLASS(TUBER_M, "TUBER", 1),
TRAINER_CLASS(LADY, "LADY", 50),
TRAINER_CLASS(BEAUTY, "BEAUTY", 20),
TRAINER_CLASS(RICH_BOY, "RICH BOY", 50),
TRAINER_CLASS(POKEMANIAC, "POKéMANIAC", 15),
TRAINER_CLASS(GUITARIST, "GUITARIST", 8),
TRAINER_CLASS(KINDLER, "KINDLER", 8),
TRAINER_CLASS(CAMPER, "CAMPER", 4),
TRAINER_CLASS(PICNICKER, "PICNICKER", 4),
TRAINER_CLASS(BUG_MANIAC, "BUG MANIAC", 15),
TRAINER_CLASS(PSYCHIC, "PSYCHIC", 6),
TRAINER_CLASS(GENTLEMAN, "GENTLEMAN", 20, ITEM_LUXURY_BALL),
TRAINER_CLASS(ELITE_FOUR, "ELITE FOUR", 25, ITEM_ULTRA_BALL),
TRAINER_CLASS(LEADER, "LEADER", 25, DEFAULT_BALL),
TRAINER_CLASS(SCHOOL_KID, "SCHOOL KID", 5, DEFAULT_BALL),
TRAINER_CLASS(SR_AND_JR, "SR. AND JR.", 4, DEFAULT_BALL),
TRAINER_CLASS(WINSTRATE, "WINSTRATE", 10, DEFAULT_BALL),
TRAINER_CLASS(POKEFAN, "POKéFAN", 20, DEFAULT_BALL),
TRAINER_CLASS(YOUNGSTER, "YOUNGSTER", 4, DEFAULT_BALL),
TRAINER_CLASS(CHAMPION, "CHAMPION", 50, DEFAULT_BALL),
TRAINER_CLASS(LEADER, "LEADER", 25),
TRAINER_CLASS(SCHOOL_KID, "SCHOOL KID"),
TRAINER_CLASS(SR_AND_JR, "SR. AND JR.", 4),
TRAINER_CLASS(WINSTRATE, "WINSTRATE", 10),
TRAINER_CLASS(POKEFAN, "POKéFAN", 20),
TRAINER_CLASS(YOUNGSTER, "YOUNGSTER", 4),
TRAINER_CLASS(CHAMPION, "CHAMPION", 50),
TRAINER_CLASS(FISHERMAN, "FISHERMAN", 10, B_TRAINER_CLASS_POKE_BALLS >= GEN_8 ? ITEM_DIVE_BALL : ITEM_LURE_BALL),
TRAINER_CLASS(TRIATHLETE, "TRIATHLETE", 10, DEFAULT_BALL),
TRAINER_CLASS(DRAGON_TAMER, "DRAGON TAMER", 12, DEFAULT_BALL),
TRAINER_CLASS(NINJA_BOY, "NINJA BOY", 3, DEFAULT_BALL),
TRAINER_CLASS(BATTLE_GIRL, "BATTLE GIRL", 6, DEFAULT_BALL),
TRAINER_CLASS(PARASOL_LADY, "PARASOL LADY", 10, DEFAULT_BALL),
TRAINER_CLASS(TRIATHLETE, "TRIATHLETE", 10),
TRAINER_CLASS(DRAGON_TAMER, "DRAGON TAMER", 12),
TRAINER_CLASS(NINJA_BOY, "NINJA BOY", 3),
TRAINER_CLASS(BATTLE_GIRL, "BATTLE GIRL", 6),
TRAINER_CLASS(PARASOL_LADY, "PARASOL LADY", 10),
TRAINER_CLASS(SWIMMER_F, "SWIMMER♀", 2, ITEM_DIVE_BALL),
TRAINER_CLASS(TWINS, "TWINS", 3, DEFAULT_BALL),
TRAINER_CLASS(SAILOR, "SAILOR", 8, DEFAULT_BALL),
TRAINER_CLASS(COOLTRAINER_2, "COOLTRAINER", DEFAULT_MONEY, ITEM_ULTRA_BALL),
TRAINER_CLASS(MAGMA_ADMIN, "MAGMA ADMIN", 10, DEFAULT_BALL),
TRAINER_CLASS(RIVAL, "{PKMN} TRAINER", 15, DEFAULT_BALL),
TRAINER_CLASS(BUG_CATCHER, "BUG CATCHER", 4, DEFAULT_BALL),
TRAINER_CLASS(PKMN_RANGER, "{PKMN} RANGER", 12, DEFAULT_BALL),
TRAINER_CLASS(TWINS, "TWINS", 3),
TRAINER_CLASS(SAILOR, "SAILOR", 8),
TRAINER_CLASS(COOLTRAINER_2, "COOLTRAINER", 5, ITEM_ULTRA_BALL),
TRAINER_CLASS(MAGMA_ADMIN, "MAGMA ADMIN", 10),
TRAINER_CLASS(RIVAL, "{PKMN} TRAINER", 15),
TRAINER_CLASS(BUG_CATCHER, "BUG CATCHER", 4),
TRAINER_CLASS(PKMN_RANGER, "{PKMN} RANGER", 12),
TRAINER_CLASS(MAGMA_LEADER, "MAGMA LEADER", 20, ITEM_MASTER_BALL),
TRAINER_CLASS(LASS, "LASS", 4, DEFAULT_BALL),
TRAINER_CLASS(YOUNG_COUPLE, "YOUNG COUPLE", 8, DEFAULT_BALL),
TRAINER_CLASS(OLD_COUPLE, "OLD COUPLE", 10, DEFAULT_BALL),
TRAINER_CLASS(SIS_AND_BRO, "SIS AND BRO", 3, DEFAULT_BALL),
TRAINER_CLASS(SALON_MAIDEN, "SALON MAIDEN", DEFAULT_MONEY, DEFAULT_BALL),
TRAINER_CLASS(DOME_ACE, "DOME ACE", DEFAULT_MONEY, DEFAULT_BALL),
TRAINER_CLASS(PALACE_MAVEN, "PALACE MAVEN", DEFAULT_MONEY, DEFAULT_BALL),
TRAINER_CLASS(ARENA_TYCOON, "ARENA TYCOON", DEFAULT_MONEY, DEFAULT_BALL),
TRAINER_CLASS(FACTORY_HEAD, "FACTORY HEAD", DEFAULT_MONEY, DEFAULT_BALL),
TRAINER_CLASS(PIKE_QUEEN, "PIKE QUEEN", DEFAULT_MONEY, DEFAULT_BALL),
TRAINER_CLASS(PYRAMID_KING, "PYRAMID KING", DEFAULT_MONEY, DEFAULT_BALL),
TRAINER_CLASS(RS_PROTAG, "{PKMN} TRAINER", DEFAULT_MONEY, DEFAULT_BALL),
TRAINER_CLASS(LASS, "LASS", 4),
TRAINER_CLASS(YOUNG_COUPLE, "YOUNG COUPLE", 8),
TRAINER_CLASS(OLD_COUPLE, "OLD COUPLE", 10),
TRAINER_CLASS(SIS_AND_BRO, "SIS AND BRO", 3),
TRAINER_CLASS(SALON_MAIDEN, "SALON MAIDEN"),
TRAINER_CLASS(DOME_ACE, "DOME ACE"),
TRAINER_CLASS(PALACE_MAVEN, "PALACE MAVEN"),
TRAINER_CLASS(ARENA_TYCOON, "ARENA TYCOON"),
TRAINER_CLASS(FACTORY_HEAD, "FACTORY HEAD"),
TRAINER_CLASS(PIKE_QUEEN, "PIKE QUEEN"),
TRAINER_CLASS(PYRAMID_KING, "PYRAMID KING"),
TRAINER_CLASS(RS_PROTAG, "{PKMN} TRAINER"),
};
static void (* const sTurnActionsFuncsTable[])(void) =
@ -3110,7 +3108,7 @@ void SwitchInClearSetData(u32 battler)
}
if (gMovesInfo[gCurrentMove].effect == EFFECT_BATON_PASS)
{
gBattleMons[battler].status2 &= (STATUS2_CONFUSION | STATUS2_FOCUS_ENERGY | STATUS2_SUBSTITUTE | STATUS2_ESCAPE_PREVENTION | STATUS2_CURSED);
gBattleMons[battler].status2 &= (STATUS2_CONFUSION | STATUS2_FOCUS_ENERGY_ANY | STATUS2_SUBSTITUTE | STATUS2_ESCAPE_PREVENTION | STATUS2_CURSED);
gStatuses3[battler] &= (STATUS3_LEECHSEED_BATTLER | STATUS3_LEECHSEED | STATUS3_ALWAYS_HITS | STATUS3_PERISH_SONG | STATUS3_ROOTED
| STATUS3_GASTRO_ACID | STATUS3_EMBARGO | STATUS3_TELEKINESIS | STATUS3_MAGNET_RISE | STATUS3_HEAL_BLOCK
| STATUS3_AQUA_RING | STATUS3_POWER_TRICK);

View File

@ -151,6 +151,7 @@ static const u8 sText_PkmnWhippedWhirlwind[] = _("{B_ATK_NAME_WITH_PREFIX} whipp
static const u8 sText_PkmnTookSunlight[] = _("{B_ATK_NAME_WITH_PREFIX} took\nin sunlight!");
static const u8 sText_PkmnLoweredHead[] = _("{B_ATK_NAME_WITH_PREFIX} lowered\nits head!");
static const u8 sText_PkmnIsGlowing[] = _("{B_ATK_NAME_WITH_PREFIX} is glowing!");
static const u8 sText_PkmnIsCloakedInAHarshLight[] = _("{B_ATK_NAME_WITH_PREFIX} became\ncloaked in a harsh light!");
static const u8 sText_PkmnFlewHigh[] = _("{B_ATK_NAME_WITH_PREFIX} flew\nup high!");
static const u8 sText_PkmnDugHole[] = _("{B_ATK_NAME_WITH_PREFIX} dug a hole!");
static const u8 sText_PkmnHidUnderwater[] = _("{B_ATK_NAME_WITH_PREFIX} hid\nunderwater!");
@ -166,7 +167,7 @@ static const u8 sText_PkmnFreedFrom[] = _("{B_ATK_NAME_WITH_PREFIX} was freed\nf
static const u8 sText_PkmnCrashed[] = _("{B_ATK_NAME_WITH_PREFIX} kept going\nand crashed!");
const u8 gText_PkmnShroudedInMist[] = _("{B_ATK_PREFIX2} became\nshrouded in MIST!");
static const u8 sText_PkmnProtectedByMist[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX} is protected\nby MIST!");
const u8 gText_PkmnGettingPumped[] = _("{B_ATK_NAME_WITH_PREFIX} is getting\npumped!");
const u8 gText_PkmnGettingPumped[] = _("{B_DEF_NAME_WITH_PREFIX} is getting\npumped!");
static const u8 sText_PkmnHitWithRecoil[] = _("{B_ATK_NAME_WITH_PREFIX} is hit\nwith recoil!");
static const u8 sText_PkmnProtectedItself2[] = _("{B_ATK_NAME_WITH_PREFIX} protected\nitself!");
static const u8 sText_PkmnBuffetedBySandstorm[] = _("{B_ATK_NAME_WITH_PREFIX} is buffeted\nby the sandstorm!");
@ -834,7 +835,7 @@ static const u8 sText_TheSeaOfFireDisappeared[] = _("The sea of fire around {B_A
static const u8 sText_SwampEnvelopedSide[] = _("A swamp enveloped\n{B_DEF_TEAM2} team!");
static const u8 sText_TheSwampDisappeared[] = _("The swamp around {B_ATK_TEAM2}\nteam disappeared!");
static const u8 sText_HospitalityRestoration[] = _("The {B_ATK_PARTNER_NAME} drank down all\nthe matcha that Sinistcha made!");
static const u8 sText_ElectroShockCharging[] = _("{B_ATK_NAME_WITH_PREFIX} absorbed\nelectricity!");
static const u8 sText_ElectroShotCharging[] = _("{B_ATK_NAME_WITH_PREFIX} absorbed\nelectricity!");
static const u8 sText_ItemWasUsedUp[] = _("The {B_LAST_ITEM}\nwas used up...");
static const u8 sText_AttackerLostItsType[] = _("{B_ATK_NAME_WITH_PREFIX} lost\nits {B_BUFF1} type!");
static const u8 sText_ShedItsTail[] = _("{B_ATK_NAME_WITH_PREFIX} shed its tail\nto create a decoy!");
@ -844,7 +845,7 @@ const u8 *const gBattleStringsTable[BATTLESTRINGS_COUNT] =
{
[STRINGID_SUPERSWEETAROMAWAFTS - BATTLESTRINGS_TABLE_START] = sText_SupersweetAromaWafts,
[STRINGID_SHEDITSTAIL - BATTLESTRINGS_TABLE_START] = sText_ShedItsTail,
[STRINGID_ELECTROSHOCKCHARGING - BATTLESTRINGS_TABLE_START] = sText_ElectroShockCharging,
[STRINGID_ELECTROSHOTCHARGING - BATTLESTRINGS_TABLE_START] = sText_ElectroShotCharging,
[STRINGID_HOSPITALITYRESTORATION - BATTLESTRINGS_TABLE_START] = sText_HospitalityRestoration,
[STRINGID_THESWAMPDISAPPEARED - BATTLESTRINGS_TABLE_START] = sText_TheSwampDisappeared,
[STRINGID_SWAMPENVELOPEDSIDE - BATTLESTRINGS_TABLE_START] = sText_SwampEnvelopedSide,
@ -1533,6 +1534,7 @@ const u8 *const gBattleStringsTable[BATTLESTRINGS_COUNT] =
[STRINGID_TARGETCOVEREDINSTICKYCANDYSYRUP - BATTLESTRINGS_TABLE_START] = sText_TargetCoveredInStickyCandySyrup,
[STRINGID_ITEMWASUSEDUP - BATTLESTRINGS_TABLE_START] = sText_ItemWasUsedUp,
[STRINGID_ATTACKERLOSTITSTYPE - BATTLESTRINGS_TABLE_START] = sText_AttackerLostItsType,
[STRINGID_CLOAKEDINAHARSHLIGHT - BATTLESTRINGS_TABLE_START] = sText_PkmnIsCloakedInAHarshLight,
};
const u16 gTrainerUsedItemStringIds[] =
@ -1758,25 +1760,6 @@ const u16 gStatDownStringIds[] =
[B_MSG_STAT_FELL_EMPTY] = STRINGID_EMPTYSTRING3,
};
// Index read from sTWOTURN_STRINGID
const u16 gFirstTurnOfTwoStringIds[] =
{
[B_MSG_TURN1_RAZOR_WIND] = STRINGID_PKMNWHIPPEDWHIRLWIND,
[B_MSG_TURN1_SOLAR_BEAM] = STRINGID_PKMNTOOKSUNLIGHT,
[B_MSG_TURN1_SKULL_BASH] = STRINGID_PKMNLOWEREDHEAD,
[B_MSG_TURN1_SKY_ATTACK] = STRINGID_PKMNISGLOWING,
[B_MSG_TURN1_FLY] = STRINGID_PKMNFLEWHIGH,
[B_MSG_TURN1_DIG] = STRINGID_PKMNDUGHOLE,
[B_MSG_TURN1_DIVE] = STRINGID_PKMNHIDUNDERWATER,
[B_MSG_TURN1_BOUNCE] = STRINGID_PKMNSPRANGUP,
[B_MSG_TURN1_PHANTOM_FORCE] = STRINGID_VANISHEDINSTANTLY,
[B_MSG_TURN1_GEOMANCY] = STRINGID_PKNMABSORBINGPOWER,
[B_MSG_TURN1_FREEZE_SHOCK] = STRINGID_CLOAKEDINAFREEZINGLIGHT,
[B_MSG_TURN1_SKY_DROP] = STRINGID_PKMNTOOKTARGETHIGH,
[B_MSG_TURN1_METEOR_BEAM] = STRINGID_METEORBEAMCHARGING,
[B_MSG_TURN1_ELECTRO_SHOCK] = STRINGID_ELECTROSHOCKCHARGING,
};
// Index copied from move's index in sTrappingMoves
const u16 gWrappedStringIds[NUM_TRAPPING_MOVES] =
{

View File

@ -498,7 +498,7 @@ static void Cmd_setdrainedhp(void);
static void Cmd_statbuffchange(void);
static void Cmd_normalisebuffs(void);
static void Cmd_setbide(void);
static void Cmd_unused0x8C(void);
static void Cmd_twoturnmoveschargestringandanimation(void);
static void Cmd_setmultihitcounter(void);
static void Cmd_initmultihitstring(void);
static void Cmd_forcerandomswitch(void);
@ -556,7 +556,7 @@ static void Cmd_selectfirstvalidtarget(void);
static void Cmd_trysetfutureattack(void);
static void Cmd_trydobeatup(void);
static void Cmd_setsemiinvulnerablebit(void);
static void Cmd_clearsemiinvulnerablebit(void);
static void Cmd_jumpifweathercheckchargeeffects(void);
static void Cmd_setminimize(void);
static void Cmd_sethail(void);
static void Cmd_trymemento(void);
@ -757,7 +757,7 @@ void (* const gBattleScriptingCommandsTable[])(void) =
Cmd_statbuffchange, //0x89
Cmd_normalisebuffs, //0x8A
Cmd_setbide, //0x8B
Cmd_unused0x8C, //0x8C
Cmd_twoturnmoveschargestringandanimation, //0x8C
Cmd_setmultihitcounter, //0x8D
Cmd_initmultihitstring, //0x8E
Cmd_forcerandomswitch, //0x8F
@ -815,7 +815,7 @@ void (* const gBattleScriptingCommandsTable[])(void) =
Cmd_trysetfutureattack, //0xC3
Cmd_trydobeatup, //0xC4
Cmd_setsemiinvulnerablebit, //0xC5
Cmd_clearsemiinvulnerablebit, //0xC6
Cmd_jumpifweathercheckchargeeffects, //0xC6
Cmd_setminimize, //0xC7
Cmd_sethail, //0xC8
Cmd_trymemento, //0xC9
@ -845,7 +845,7 @@ void (* const gBattleScriptingCommandsTable[])(void) =
Cmd_unused2, //0xE1
Cmd_switchoutabilities, //0xE2
Cmd_jumpifhasnohp, //0xE3
Cmd_jumpifnotcurrentmoveargtype, //0xE4
Cmd_jumpifnotcurrentmoveargtype, //0xE4
Cmd_pickup, //0xE5
Cmd_unused3, //0xE6
Cmd_unused4, //0xE7
@ -1906,6 +1906,7 @@ s32 CalcCritChanceStageArgs(u32 battlerAtk, u32 battlerDef, u32 move, bool32 rec
else
{
critChance = 2 * ((gBattleMons[battlerAtk].status2 & STATUS2_FOCUS_ENERGY) != 0)
+ 1 * ((gBattleMons[battlerAtk].status2 & STATUS2_DRAGON_CHEER) != 0)
+ gMovesInfo[gCurrentMove].criticalHitStage
+ (holdEffectAtk == HOLD_EFFECT_SCOPE_LENS)
+ 2 * (holdEffectAtk == HOLD_EFFECT_LUCKY_PUNCH && gBattleMons[battlerAtk].species == SPECIES_CHANSEY)
@ -2621,7 +2622,7 @@ static void Cmd_printstring(void)
if (gBattleControllerExecFlags == 0)
{
u16 id = cmd->id;
u16 id = (cmd->id == 0 ? gBattleScripting.savedStringId : cmd->id);
gBattlescriptCurrInstr = cmd->nextInstr;
PrepareStringBattle(id, gBattlerAttacker);
@ -2805,11 +2806,9 @@ void SetMoveEffect(bool32 primary, bool32 certain)
// Just in case this flag is still set
gBattleScripting.moveEffect &= ~MOVE_EFFECT_CERTAIN;
if ((battlerAbility == ABILITY_SHIELD_DUST
|| GetBattlerHoldEffect(gEffectBattler, TRUE) == HOLD_EFFECT_COVERT_CLOAK)
if (!primary && affectsUser != MOVE_EFFECT_AFFECTS_USER
&& !(gHitMarker & HITMARKER_STATUS_ABILITY_EFFECT)
&& !primary
&& (gBattleScripting.moveEffect <= MOVE_EFFECT_TRI_ATTACK || gBattleScripting.moveEffect >= MOVE_EFFECT_SMACK_DOWN)) // Exclude stat lowering effects
&& (battlerAbility == ABILITY_SHIELD_DUST || GetBattlerHoldEffect(gEffectBattler, TRUE) == HOLD_EFFECT_COVERT_CLOAK))
{
if (battlerAbility == ABILITY_SHIELD_DUST)
RecordAbilityBattle(gEffectBattler, battlerAbility);
@ -8697,16 +8696,19 @@ static void Cmd_various(void)
}
return;
}
case VARIOUS_JUMP_IF_NO_HOLD_EFFECT:
case VARIOUS_JUMP_IF_HOLD_EFFECT:
{
VARIOUS_ARGS(u8 holdEffect, const u8 *jumpInstr);
if (GetBattlerHoldEffect(battler, TRUE) != cmd->holdEffect)
VARIOUS_ARGS(u8 holdEffect, const u8 *jumpInstr, u8 equal);
if ((GetBattlerHoldEffect(battler, TRUE) == cmd->holdEffect) == cmd->equal)
{
if (cmd->equal)
gLastUsedItem = gBattleMons[battler].item; // For B_LAST_USED_ITEM
gBattlescriptCurrInstr = cmd->jumpInstr;
}
else
{
gLastUsedItem = gBattleMons[battler].item; // For B_LAST_USED_ITEM
if (!cmd->equal)
gLastUsedItem = gBattleMons[battler].item; // For B_LAST_USED_ITEM
gBattlescriptCurrInstr = cmd->nextInstr;
}
return;
@ -11693,8 +11695,15 @@ static void Cmd_setbide(void)
gBattlescriptCurrInstr = cmd->nextInstr;
}
static void Cmd_unused0x8C(void)
static void Cmd_twoturnmoveschargestringandanimation(void)
{
CMD_ARGS(const u8 *animationThenStringPtr);
gBattleScripting.savedStringId = LOHALF(gMovesInfo[gCurrentMove].argument);
if (B_UPDATED_MOVE_DATA < GEN_5 || MoveHasChargeTurnMoveEffect(gCurrentMove))
gBattlescriptCurrInstr = cmd->animationThenStringPtr;
else
gBattlescriptCurrInstr = cmd->nextInstr;
}
static void Cmd_setmultihitcounter(void)
@ -12335,14 +12344,20 @@ static void Cmd_setfocusenergy(void)
{
CMD_ARGS();
if (gBattleMons[gBattlerAttacker].status2 & STATUS2_FOCUS_ENERGY)
if ((gMovesInfo[gCurrentMove].effect == EFFECT_DRAGON_CHEER && (!(gBattleTypeFlags & BATTLE_TYPE_DOUBLE) || (gAbsentBattlerFlags & gBitTable[gBattlerTarget])))
|| gBattleMons[gBattlerTarget].status2 & STATUS2_FOCUS_ENERGY_ANY)
{
gMoveResultFlags |= MOVE_RESULT_FAILED;
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_FOCUS_ENERGY_FAILED;
}
else if (gMovesInfo[gCurrentMove].effect == EFFECT_DRAGON_CHEER && !IS_BATTLER_OF_TYPE(gBattlerTarget, TYPE_DRAGON))
{
gBattleMons[gBattlerTarget].status2 |= STATUS2_DRAGON_CHEER;
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_GETTING_PUMPED;
}
else
{
gBattleMons[gBattlerAttacker].status2 |= STATUS2_FOCUS_ENERGY;
gBattleMons[gBattlerTarget].status2 |= STATUS2_FOCUS_ENERGY;
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_GETTING_PUMPED;
}
gBattlescriptCurrInstr = cmd->nextInstr;
@ -13643,36 +13658,36 @@ static void Cmd_trydobeatup(void)
static void Cmd_setsemiinvulnerablebit(void)
{
CMD_ARGS();
CMD_ARGS(bool8 clear);
switch (gCurrentMove)
if (gBattleMoveEffects[gMovesInfo[gCurrentMove].effect].semiInvulnerableEffect == TRUE)
{
case MOVE_FLY:
case MOVE_BOUNCE:
case MOVE_SKY_DROP:
gStatuses3[gBattlerAttacker] |= STATUS3_ON_AIR;
break;
case MOVE_DIG:
gStatuses3[gBattlerAttacker] |= STATUS3_UNDERGROUND;
break;
case MOVE_DIVE:
gStatuses3[gBattlerAttacker] |= STATUS3_UNDERWATER;
break;
case MOVE_PHANTOM_FORCE:
case MOVE_SHADOW_FORCE:
gStatuses3[gBattlerAttacker] |= STATUS3_PHANTOM_FORCE;
break;
u32 semiInvulnerableEffect = UNCOMPRESS_BITS(HIHALF(gMovesInfo[gCurrentMove].argument));
if (cmd->clear)
gStatuses3[gBattlerAttacker] &= ~semiInvulnerableEffect;
else
gStatuses3[gBattlerAttacker] |= semiInvulnerableEffect;
}
gBattlescriptCurrInstr = cmd->nextInstr;
}
static void Cmd_clearsemiinvulnerablebit(void)
static void Cmd_jumpifweathercheckchargeeffects(void)
{
CMD_ARGS();
CMD_ARGS(u8 battler, bool8 checkChargeTurnEffects, const u8 *jumpInstr);
gStatuses3[gBattlerAttacker] &= ~STATUS3_SEMI_INVULNERABLE;
gBattlescriptCurrInstr = cmd->nextInstr;
/* If this is NOT semi-invulnerable move and we don't have charge turn effects
yet to fire, we can fire the move right away so long as the weather matches
the argument and the battler is affected by it (not blocked by Cloud Nine etc) */
if (gBattleMoveEffects[gMovesInfo[gCurrentMove].effect].semiInvulnerableEffect == FALSE
&& !(cmd->checkChargeTurnEffects && MoveHasChargeTurnMoveEffect(gCurrentMove))
&& IsBattlerWeatherAffected(cmd->battler, HIHALF(gMovesInfo[gCurrentMove].argument)))
{
gBattleScripting.animTurn = 1;
gBattlescriptCurrInstr = cmd->jumpInstr;
}
else
gBattlescriptCurrInstr = cmd->nextInstr;
}
static void Cmd_setminimize(void)
@ -15549,23 +15564,6 @@ void BS_JumpIfMoreThanHalfHP(void)
gBattlescriptCurrInstr = cmd->nextInstr;
}
void BS_JumpIfHoldEffect(void)
{
u8 battler = gBattlescriptCurrInstr[5];
u16 holdEffect = T1_READ_16(gBattlescriptCurrInstr + 6);
if (GetBattlerHoldEffect(battler, TRUE) == holdEffect)
{
gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 8);
}
else
{
RecordItemEffectBattle(battler, holdEffect);
gLastUsedItem = gBattleMons[battler].item; // For B_LAST_USED_ITEM
gBattlescriptCurrInstr += 12;
}
}
void BS_DoStockpileStatChangesWearOff(void)
{
NATIVE_ARGS(u8 battler, const u8 *statChangeInstr);
@ -16543,10 +16541,10 @@ void BS_TryUpperHand(void)
{
NATIVE_ARGS(const u8 *failInstr);
if (GetBattlerTurnOrderNum(gBattlerAttacker) > GetBattlerTurnOrderNum(gBattlerTarget)
|| gChosenMoveByBattler[gBattlerTarget] == MOVE_NONE
|| IS_MOVE_STATUS(gChosenMoveByBattler[gBattlerTarget])
|| GetChosenMovePriority(gBattlerTarget) < 1 || GetChosenMovePriority(gBattlerTarget) > 3) // Fails if priority is less than 1 or greater than 3, if target already moved, or if using a status
if (GetBattlerTurnOrderNum(gBattlerAttacker) > GetBattlerTurnOrderNum(gBattlerTarget)
|| gChosenMoveByBattler[gBattlerTarget] == MOVE_NONE
|| IS_MOVE_STATUS(gChosenMoveByBattler[gBattlerTarget])
|| GetChosenMovePriority(gBattlerTarget) < 1 || GetChosenMovePriority(gBattlerTarget) > 3) // Fails if priority is less than 1 or greater than 3, if target already moved, or if using a status
gBattlescriptCurrInstr = cmd->failInstr;
else
gBattlescriptCurrInstr = cmd->nextInstr;

View File

@ -3192,7 +3192,6 @@ u8 AtkCanceller_UnableToUseMove(u32 moveType)
gBattleMons[gBattlerAttacker].status2 &= ~STATUS2_DESTINY_BOND;
gStatuses3[gBattlerAttacker] &= ~STATUS3_GRUDGE;
gStatuses4[gBattlerAttacker] &= ~ STATUS4_GLAIVE_RUSH;
gBattleScripting.tripleKickPower = 0;
gBattleStruct->atkCancellerTracker++;
break;
case CANCELLER_SKY_DROP:
@ -3607,6 +3606,10 @@ u8 AtkCanceller_UnableToUseMove(u32 moveType)
gBattleStruct->beatUpSlot = 0;
PREPARE_BYTE_NUMBER_BUFFER(gBattleScripting.multihitString, 1, 0)
}
else
{
gMultiHitCounter = 0;
}
gBattleStruct->atkCancellerTracker++;
break;
case CANCELLER_END:
@ -4016,50 +4019,79 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
switch (caseID)
{
case ABILITYEFFECT_SWITCH_IN_TERRAIN:
gBattleScripting.battler = battler;
if (VarGet(VAR_TERRAIN) & STATUS_FIELD_TERRAIN_ANY)
{
u16 terrainFlags = VarGet(VAR_TERRAIN) & STATUS_FIELD_TERRAIN_ANY; // only works for status flag (1 << 15)
gFieldStatuses = terrainFlags | STATUS_FIELD_TERRAIN_PERMANENT; // terrain is permanent
switch (VarGet(VAR_TERRAIN) & STATUS_FIELD_TERRAIN_ANY)
{
case STATUS_FIELD_ELECTRIC_TERRAIN:
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_TERRAIN_SET_ELECTRIC;
break;
case STATUS_FIELD_MISTY_TERRAIN:
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_TERRAIN_SET_MISTY;
break;
case STATUS_FIELD_GRASSY_TERRAIN:
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_TERRAIN_SET_GRASSY;
break;
case STATUS_FIELD_PSYCHIC_TERRAIN:
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_TERRAIN_SET_PSYCHIC;
break;
}
u8 varTerrainTimer = VarGet(B_VAR_TERRAIN_TIMER);
BattleScriptPushCursorAndCallback(BattleScript_OverworldTerrain);
effect++;
gBattleScripting.battler = battler;
if (VarGet(B_VAR_TERRAIN) & STATUS_FIELD_TERRAIN_ANY)
{
u16 terrainFlags = VarGet(B_VAR_TERRAIN) & STATUS_FIELD_TERRAIN_ANY; // only works for status flag (1 << 15)
if (varTerrainTimer == 0)
{
gFieldStatuses = terrainFlags | STATUS_FIELD_TERRAIN_PERMANENT; // terrain is permanent
}
else
{
gFieldStatuses |= terrainFlags;
gFieldTimers.terrainTimer = varTerrainTimer;
}
switch (VarGet(B_VAR_TERRAIN) & STATUS_FIELD_TERRAIN_ANY)
{
case STATUS_FIELD_ELECTRIC_TERRAIN:
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_TERRAIN_SET_ELECTRIC;
break;
case STATUS_FIELD_MISTY_TERRAIN:
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_TERRAIN_SET_MISTY;
break;
case STATUS_FIELD_GRASSY_TERRAIN:
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_TERRAIN_SET_GRASSY;
break;
case STATUS_FIELD_PSYCHIC_TERRAIN:
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_TERRAIN_SET_PSYCHIC;
break;
}
BattleScriptPushCursorAndCallback(BattleScript_OverworldTerrain);
effect++;
}
else if (B_THUNDERSTORM_TERRAIN == TRUE
&& GetCurrentWeather() == WEATHER_RAIN_THUNDERSTORM
&& !(gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN))
{
// overworld weather started rain, so just do electric terrain anim
if (varTerrainTimer == 0)
{
gFieldStatuses = (STATUS_FIELD_ELECTRIC_TERRAIN | STATUS_FIELD_TERRAIN_PERMANENT);
}
else
{
gFieldStatuses |= STATUS_FIELD_ELECTRIC_TERRAIN;
gFieldTimers.terrainTimer = varTerrainTimer;
}
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_TERRAIN_SET_ELECTRIC;
BattleScriptPushCursorAndCallback(BattleScript_OverworldTerrain);
effect++;
}
else if (B_FOG_TERRAIN == TRUE
&& (GetCurrentWeather() == WEATHER_FOG_HORIZONTAL || GetCurrentWeather() == WEATHER_FOG_DIAGONAL)
&& !(gFieldStatuses & STATUS_FIELD_MISTY_TERRAIN))
{
if (varTerrainTimer == 0)
{
gFieldStatuses = (STATUS_FIELD_MISTY_TERRAIN | STATUS_FIELD_TERRAIN_PERMANENT);
}
else
{
gFieldStatuses |= STATUS_FIELD_ELECTRIC_TERRAIN;
gFieldTimers.terrainTimer = varTerrainTimer;
}
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_TERRAIN_SET_MISTY;
BattleScriptPushCursorAndCallback(BattleScript_OverworldTerrain);
effect++;
}
}
else if (B_THUNDERSTORM_TERRAIN == TRUE
&& GetCurrentWeather() == WEATHER_RAIN_THUNDERSTORM
&& !(gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN))
{
// overworld weather started rain, so just do electric terrain anim
gFieldStatuses = (STATUS_FIELD_ELECTRIC_TERRAIN | STATUS_FIELD_TERRAIN_PERMANENT);
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_TERRAIN_SET_ELECTRIC;
BattleScriptPushCursorAndCallback(BattleScript_OverworldTerrain);
effect++;
}
else if (B_FOG_TERRAIN == TRUE
&& (GetCurrentWeather() == WEATHER_FOG_HORIZONTAL || GetCurrentWeather() == WEATHER_FOG_DIAGONAL)
&& !(gFieldStatuses & STATUS_FIELD_MISTY_TERRAIN))
{
gFieldStatuses = (STATUS_FIELD_MISTY_TERRAIN | STATUS_FIELD_TERRAIN_PERMANENT);
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_TERRAIN_SET_MISTY;
BattleScriptPushCursorAndCallback(BattleScript_OverworldTerrain);
effect++;
}
break;
break;
case ABILITYEFFECT_SWITCH_IN_WEATHER:
gBattleScripting.battler = battler;
if (!(gBattleTypeFlags & BATTLE_TYPE_RECORDED))
@ -6859,7 +6891,7 @@ static u8 ItemEffectMoveEnd(u32 battler, u16 holdEffect)
break;
case HOLD_EFFECT_CRITICAL_UP: // lansat berry
if (B_BERRIES_INSTANT >= GEN_4
&& !(gBattleMons[battler].status2 & STATUS2_FOCUS_ENERGY)
&& !(gBattleMons[battler].status2 & STATUS2_FOCUS_ENERGY_ANY)
&& HasEnoughHpToEatBerry(battler, GetBattlerItemHoldEffectParam(battler, gLastUsedItem), gLastUsedItem))
{
gBattleMons[battler].status2 |= STATUS2_FOCUS_ENERGY;
@ -6984,7 +7016,7 @@ u8 ItemBattleEffects(u8 caseID, u32 battler, bool32 moveTurn)
break;
case HOLD_EFFECT_CRITICAL_UP:
if (B_BERRIES_INSTANT >= GEN_4
&& !(gBattleMons[battler].status2 & STATUS2_FOCUS_ENERGY)
&& !(gBattleMons[battler].status2 & STATUS2_FOCUS_ENERGY_ANY)
&& HasEnoughHpToEatBerry(battler, GetBattlerItemHoldEffectParam(battler, gLastUsedItem), gLastUsedItem))
{
gBattleMons[battler].status2 |= STATUS2_FOCUS_ENERGY;
@ -7295,7 +7327,7 @@ u8 ItemBattleEffects(u8 caseID, u32 battler, bool32 moveTurn)
effect = StatRaiseBerry(battler, gLastUsedItem, STAT_SPDEF, TRUE);
break;
case HOLD_EFFECT_CRITICAL_UP:
if (!moveTurn && !(gBattleMons[battler].status2 & STATUS2_FOCUS_ENERGY)
if (!moveTurn && !(gBattleMons[battler].status2 & STATUS2_FOCUS_ENERGY_ANY)
&& HasEnoughHpToEatBerry(battler, GetBattlerItemHoldEffectParam(battler, gLastUsedItem), gLastUsedItem))
{
gBattleMons[battler].status2 |= STATUS2_FOCUS_ENERGY;
@ -7994,6 +8026,7 @@ u8 IsMonDisobedient(void)
} while (gBitTable[gCurrMovePos] & calc);
gCalledMove = gBattleMons[gBattlerAttacker].moves[gCurrMovePos];
SetAtkCancellerForCalledMove();
gBattlescriptCurrInstr = BattleScript_IgnoresAndUsesRandomMove;
gBattlerTarget = GetMoveTarget(gCalledMove, NO_TARGET_OVERRIDE);
gHitMarker |= HITMARKER_DISOBEDIENT_MOVE;
@ -11021,6 +11054,17 @@ bool32 MoveHasMoveEffectSelfArg(u32 move, u32 moveEffect, u32 argument)
return (gMovesInfo[move].argument == argument) && MoveHasMoveEffectSelf(move, moveEffect);
}
bool32 MoveHasChargeTurnMoveEffect(u32 move)
{
u8 i = 0;
for (i = 0; i < gMovesInfo[move].numAdditionalEffects; i++)
{
if (gMovesInfo[move].additionalEffects[i].onChargeTurnOnly)
return TRUE;
}
return FALSE;
}
bool8 CanMonParticipateInSkyBattle(struct Pokemon *mon)
{
u16 species = GetMonData(mon, MON_DATA_SPECIES);

View File

@ -606,7 +606,7 @@ void SetZEffect(void)
}
break;
case Z_EFFECT_BOOST_CRITS:
if (!(gBattleMons[gBattlerAttacker].status2 & STATUS2_FOCUS_ENERGY))
if (!(gBattleMons[gBattlerAttacker].status2 & STATUS2_FOCUS_ENERGY_ANY))
{
gBattleMons[gBattlerAttacker].status2 |= STATUS2_FOCUS_ENERGY;
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_Z_BOOST_CRITS;

View File

@ -220,5 +220,9 @@ const union AnimCmd *const gAnims_MonPic[MAX_MON_PIC_FRAMES] =
sAnim_MonPic_1,
};
const union AnimCmd *const sAnims_Trainer[] ={
sAnim_GeneralFrame0,
};
#include "data/trainer_parties.h"
#include "data/trainers.h"

View File

@ -383,7 +383,7 @@ const struct BattleMoveEffect gBattleMoveEffects[NUM_BATTLE_MOVE_EFFECTS] =
[EFFECT_TWO_TURNS_ATTACK] =
{
.battleScript = BattleScript_EffectTwoTurnsAttack,
.battleTvScore = 0, // TODO: Assign points
.battleTvScore = 3,
},
[EFFECT_SUBSTITUTE] =
@ -527,7 +527,7 @@ const struct BattleMoveEffect gBattleMoveEffects[NUM_BATTLE_MOVE_EFFECTS] =
[EFFECT_TRIPLE_KICK] =
{
.battleScript = BattleScript_EffectTripleKick,
.battleScript = BattleScript_EffectHit,
.battleTvScore = 1,
},
@ -748,12 +748,6 @@ const struct BattleMoveEffect gBattleMoveEffects[NUM_BATTLE_MOVE_EFFECTS] =
.encourageEncore = TRUE,
},
[EFFECT_SKULL_BASH] =
{
.battleScript = BattleScript_EffectSkullBash,
.battleTvScore = 3,
},
[EFFECT_EARTHQUAKE] =
{
.battleScript = BattleScript_EffectHit,
@ -767,15 +761,9 @@ const struct BattleMoveEffect gBattleMoveEffects[NUM_BATTLE_MOVE_EFFECTS] =
.encourageEncore = TRUE,
},
[EFFECT_GUST] =
{
.battleScript = BattleScript_EffectGust,
.battleTvScore = 1,
},
[EFFECT_SOLAR_BEAM] =
{
.battleScript = BattleScript_EffectSolarBeam,
.battleScript = BattleScript_EffectTwoTurnsAttack,
.battleTvScore = 1,
},
@ -799,8 +787,9 @@ const struct BattleMoveEffect gBattleMoveEffects[NUM_BATTLE_MOVE_EFFECTS] =
[EFFECT_SEMI_INVULNERABLE] =
{
.battleScript = BattleScript_EffectSemiInvulnerable,
.battleScript = BattleScript_EffectTwoTurnsAttack,
.battleTvScore = 3,
.semiInvulnerableEffect = TRUE,
},
[EFFECT_DEFENSE_CURL] =
@ -1101,12 +1090,6 @@ const struct BattleMoveEffect gBattleMoveEffects[NUM_BATTLE_MOVE_EFFECTS] =
.encourageEncore = TRUE,
},
[EFFECT_SKY_UPPERCUT] =
{
.battleScript = BattleScript_EffectSkyUppercut,
.battleTvScore = 1,
},
[EFFECT_BULK_UP] =
{
.battleScript = BattleScript_EffectBulkUp,
@ -2016,6 +1999,7 @@ const struct BattleMoveEffect gBattleMoveEffects[NUM_BATTLE_MOVE_EFFECTS] =
{
.battleScript = BattleScript_EffectSkyDrop,
.battleTvScore = 0, // TODO: Assign points
.semiInvulnerableEffect = TRUE,
},
[EFFECT_EXPANDING_FORCE] =
@ -2024,12 +2008,6 @@ const struct BattleMoveEffect gBattleMoveEffects[NUM_BATTLE_MOVE_EFFECTS] =
.battleTvScore = 0, // TODO: Assign points
},
[EFFECT_METEOR_BEAM] =
{
.battleScript = BattleScript_EffectMeteorBeam,
.battleTvScore = 0, // TODO: Assign points
},
[EFFECT_RISING_VOLTAGE] =
{
.battleScript = BattleScript_EffectHit,
@ -2229,4 +2207,11 @@ const struct BattleMoveEffect gBattleMoveEffects[NUM_BATTLE_MOVE_EFFECTS] =
.battleScript = BattleScript_EffectUpperHand,
.battleTvScore = 0, // TODO: Assign points
},
[EFFECT_DRAGON_CHEER] =
{
.battleScript = BattleScript_EffectFocusEnergy,
.battleTvScore = 1,
.encourageEncore = TRUE,
},
};

View File

@ -10994,11 +10994,11 @@ const u8 gMonFootprint_QuestionMark[] = INCBIN_U8("graphics/pokemon/question_mar
// const u8 gMonFootprint_Dipplin[] = INCBIN_U8("graphics/pokemon/dipplin/footprint.1bpp");
#endif //P_FOOTPRINTS
// const u32 gMonFrontPic_Hydrapple[] = INCBIN_U32("graphics/pokemon/hydrapple/front.4bpp.lz");
// const u32 gMonPalette_Hydrapple[] = INCBIN_U32("graphics/pokemon/hydrapple/normal.gbapal.lz");
// const u32 gMonBackPic_Hydrapple[] = INCBIN_U32("graphics/pokemon/hydrapple/back.4bpp.lz");
// const u32 gMonShinyPalette_Hydrapple[] = INCBIN_U32("graphics/pokemon/hydrapple/shiny.gbapal.lz");
// const u8 gMonIcon_Hydrapple[] = INCBIN_U8("graphics/pokemon/hydrapple/icon.4bpp");
const u32 gMonFrontPic_Hydrapple[] = INCBIN_U32("graphics/pokemon/hydrapple/front.4bpp.lz");
const u32 gMonPalette_Hydrapple[] = INCBIN_U32("graphics/pokemon/hydrapple/normal.gbapal.lz");
const u32 gMonBackPic_Hydrapple[] = INCBIN_U32("graphics/pokemon/hydrapple/back.4bpp.lz");
const u32 gMonShinyPalette_Hydrapple[] = INCBIN_U32("graphics/pokemon/hydrapple/shiny.gbapal.lz");
const u8 gMonIcon_Hydrapple[] = INCBIN_U8("graphics/pokemon/hydrapple/icon.4bpp");
#if P_FOOTPRINTS
// const u8 gMonFootprint_Hydrapple[] = INCBIN_U8("graphics/pokemon/hydrapple/footprint.1bpp");
#endif //P_FOOTPRINTS
@ -11574,10 +11574,10 @@ const u8 gMonFootprint_QuestionMark[] = INCBIN_U8("graphics/pokemon/question_mar
#endif //P_GIGANTAMAX_FORMS
#if P_GEN_9_CROSS_EVOS
// const u32 gMonFrontPic_Archaludon[] = INCBIN_U32("graphics/pokemon/archaludon/front.4bpp.lz");
// const u32 gMonPalette_Archaludon[] = INCBIN_U32("graphics/pokemon/archaludon/normal.gbapal.lz");
// const u32 gMonBackPic_Archaludon[] = INCBIN_U32("graphics/pokemon/archaludon/back.4bpp.lz");
// const u32 gMonShinyPalette_Archaludon[] = INCBIN_U32("graphics/pokemon/archaludon/shiny.gbapal.lz");
const u32 gMonFrontPic_Archaludon[] = INCBIN_U32("graphics/pokemon/archaludon/front.4bpp.lz");
const u32 gMonPalette_Archaludon[] = INCBIN_U32("graphics/pokemon/archaludon/normal.gbapal.lz");
const u32 gMonBackPic_Archaludon[] = INCBIN_U32("graphics/pokemon/archaludon/back.4bpp.lz");
const u32 gMonShinyPalette_Archaludon[] = INCBIN_U32("graphics/pokemon/archaludon/shiny.gbapal.lz");
// const u8 gMonIcon_Archaludon[] = INCBIN_U8("graphics/pokemon/archaludon/icon.4bpp");
#if P_FOOTPRINTS
// const u8 gMonFootprint_Archaludon[] = INCBIN_U8("graphics/pokemon/archaludon/footprint.1bpp");
@ -12963,10 +12963,10 @@ const u8 gMonFootprint_QuestionMark[] = INCBIN_U8("graphics/pokemon/question_mar
#endif //P_FAMILY_OGERPON
#if P_FAMILY_GOUGING_FIRE
// const u32 gMonFrontPic_GougingFire[] = INCBIN_U32("graphics/pokemon/gouging_fire/front.4bpp.lz");
// const u32 gMonPalette_GougingFire[] = INCBIN_U32("graphics/pokemon/gouging_fire/normal.gbapal.lz");
// const u32 gMonBackPic_GougingFire[] = INCBIN_U32("graphics/pokemon/gouging_fire/back.4bpp.lz");
// const u32 gMonShinyPalette_GougingFire[] = INCBIN_U32("graphics/pokemon/gouging_fire/shiny.gbapal.lz");
const u32 gMonFrontPic_GougingFire[] = INCBIN_U32("graphics/pokemon/gouging_fire/front.4bpp.lz");
const u32 gMonPalette_GougingFire[] = INCBIN_U32("graphics/pokemon/gouging_fire/normal.gbapal.lz");
const u32 gMonBackPic_GougingFire[] = INCBIN_U32("graphics/pokemon/gouging_fire/back.4bpp.lz");
const u32 gMonShinyPalette_GougingFire[] = INCBIN_U32("graphics/pokemon/gouging_fire/shiny.gbapal.lz");
// const u8 gMonIcon_GougingFire[] = INCBIN_U8("graphics/pokemon/gouging_fire/icon.4bpp");
#if P_FOOTPRINTS
// const u8 gMonFootprint_GougingFire[] = INCBIN_U8("graphics/pokemon/gouging_fire/footprint.1bpp");
@ -12974,10 +12974,10 @@ const u8 gMonFootprint_QuestionMark[] = INCBIN_U8("graphics/pokemon/question_mar
#endif //P_FAMILY_GOUGING_FIRE
#if P_FAMILY_RAGING_BOLT
// const u32 gMonFrontPic_RagingBolt[] = INCBIN_U32("graphics/pokemon/raging_bolt/front.4bpp.lz");
// const u32 gMonPalette_RagingBolt[] = INCBIN_U32("graphics/pokemon/raging_bolt/normal.gbapal.lz");
// const u32 gMonBackPic_RagingBolt[] = INCBIN_U32("graphics/pokemon/raging_bolt/back.4bpp.lz");
// const u32 gMonShinyPalette_RagingBolt[] = INCBIN_U32("graphics/pokemon/raging_bolt/shiny.gbapal.lz");
const u32 gMonFrontPic_RagingBolt[] = INCBIN_U32("graphics/pokemon/raging_bolt/front.4bpp.lz");
const u32 gMonPalette_RagingBolt[] = INCBIN_U32("graphics/pokemon/raging_bolt/normal.gbapal.lz");
const u32 gMonBackPic_RagingBolt[] = INCBIN_U32("graphics/pokemon/raging_bolt/back.4bpp.lz");
const u32 gMonShinyPalette_RagingBolt[] = INCBIN_U32("graphics/pokemon/raging_bolt/shiny.gbapal.lz");
// const u8 gMonIcon_RagingBolt[] = INCBIN_U8("graphics/pokemon/raging_bolt/icon.4bpp");
#if P_FOOTPRINTS
// const u8 gMonFootprint_RagingBolt[] = INCBIN_U8("graphics/pokemon/raging_bolt/footprint.1bpp");
@ -12985,10 +12985,10 @@ const u8 gMonFootprint_QuestionMark[] = INCBIN_U8("graphics/pokemon/question_mar
#endif //P_FAMILY_RAGING_BOLT
#if P_FAMILY_IRON_BOULDER
// const u32 gMonFrontPic_IronBoulder[] = INCBIN_U32("graphics/pokemon/iron_boulder/front.4bpp.lz");
// const u32 gMonPalette_IronBoulder[] = INCBIN_U32("graphics/pokemon/iron_boulder/normal.gbapal.lz");
// const u32 gMonBackPic_IronBoulder[] = INCBIN_U32("graphics/pokemon/iron_boulder/back.4bpp.lz");
// const u32 gMonShinyPalette_IronBoulder[] = INCBIN_U32("graphics/pokemon/iron_boulder/shiny.gbapal.lz");
const u32 gMonFrontPic_IronBoulder[] = INCBIN_U32("graphics/pokemon/iron_boulder/front.4bpp.lz");
const u32 gMonPalette_IronBoulder[] = INCBIN_U32("graphics/pokemon/iron_boulder/normal.gbapal.lz");
const u32 gMonBackPic_IronBoulder[] = INCBIN_U32("graphics/pokemon/iron_boulder/back.4bpp.lz");
const u32 gMonShinyPalette_IronBoulder[] = INCBIN_U32("graphics/pokemon/iron_boulder/shiny.gbapal.lz");
// const u8 gMonIcon_IronBoulder[] = INCBIN_U8("graphics/pokemon/iron_boulder/icon.4bpp");
#if P_FOOTPRINTS
// const u8 gMonFootprint_IronBoulder[] = INCBIN_U8("graphics/pokemon/iron_boulder/footprint.1bpp");
@ -12996,10 +12996,10 @@ const u8 gMonFootprint_QuestionMark[] = INCBIN_U8("graphics/pokemon/question_mar
#endif //P_FAMILY_IRON_BOULDER
#if P_FAMILY_IRON_CROWN
// const u32 gMonFrontPic_IronCrown[] = INCBIN_U32("graphics/pokemon/iron_crown/front.4bpp.lz");
// const u32 gMonPalette_IronCrown[] = INCBIN_U32("graphics/pokemon/iron_crown/normal.gbapal.lz");
// const u32 gMonBackPic_IronCrown[] = INCBIN_U32("graphics/pokemon/iron_crown/back.4bpp.lz");
// const u32 gMonShinyPalette_IronCrown[] = INCBIN_U32("graphics/pokemon/iron_crown/shiny.gbapal.lz");
const u32 gMonFrontPic_IronCrown[] = INCBIN_U32("graphics/pokemon/iron_crown/front.4bpp.lz");
const u32 gMonPalette_IronCrown[] = INCBIN_U32("graphics/pokemon/iron_crown/normal.gbapal.lz");
const u32 gMonBackPic_IronCrown[] = INCBIN_U32("graphics/pokemon/iron_crown/back.4bpp.lz");
const u32 gMonShinyPalette_IronCrown[] = INCBIN_U32("graphics/pokemon/iron_crown/shiny.gbapal.lz");
// const u8 gMonIcon_IronCrown[] = INCBIN_U8("graphics/pokemon/iron_crown/icon.4bpp");
#if P_FOOTPRINTS
// const u8 gMonFootprint_IronCrown[] = INCBIN_U8("graphics/pokemon/iron_crown/footprint.1bpp");

View File

@ -292,116 +292,115 @@ const u8 gTrainerBackPic_Steven[] = INCBIN_U8("graphics/trainers/back_pics/steve
const u32 gTrainerBackPicPalette_Red[] = INCBIN_U32("graphics/trainers/back_pics/red.gbapal.lz");
const u32 gTrainerBackPicPalette_Leaf[] = INCBIN_U32("graphics/trainers/back_pics/leaf.gbapal.lz");
static const union AnimCmd *const sAnims_Trainer[] ={
sAnim_GeneralFrame0,
};
#define TRAINER_SPRITE(trainerPic, file, x, y, rotation) \
// The first two parameters invoke a front pic and palette by
// calling a "TRAINER_PIC" constant (e.g. TRAINER_PIC_HIKER), and
// gTrainerFrontPic/gTrainerPalette pointers, (e.g "gTrainerFrontPic_Hiker" and "gTrainerPalette_Hiker").
// The last three parameters control the X and Y coordinates and rotation of the mugshot on the screen.
// They default to 0, 0, and 0x200 which are default values used by the majority of the game's trainer sprites.
#define TRAINER_SPRITE(trainerPic, file, ...) \
[TRAINER_PIC_##trainerPic] = \
{ \
.y_offset = 8, \
.frontPic = {gTrainerFrontPic_##file, TRAINER_PIC_SIZE, TRAINER_PIC_##trainerPic},\
.palette = {gTrainerPalette_##file, TRAINER_PIC_##trainerPic}, \
.animation = sAnims_Trainer, \
.mugshotCoords = {x, y}, \
.mugshotRotation = rotation, \
.mugshotCoords = {DEFAULT(0, __VA_ARGS__), DEFAULT_2(0, __VA_ARGS__)}, \
.mugshotRotation = DEFAULT_3(0x200, __VA_ARGS__), \
}
const struct TrainerSprite gTrainerSprites[] =
{
TRAINER_SPRITE(HIKER, Hiker, 0, 0, 0x200),
TRAINER_SPRITE(AQUA_GRUNT_M, AquaGruntM, 0, 0, 0x200),
TRAINER_SPRITE(POKEMON_BREEDER_F, PokemonBreederF, 0, 0, 0x200),
TRAINER_SPRITE(COOLTRAINER_M, CoolTrainerM, 0, 0, 0x200),
TRAINER_SPRITE(BIRD_KEEPER, BirdKeeper, 0, 0, 0x200),
TRAINER_SPRITE(COLLECTOR, Collector, 0, 0, 0x200),
TRAINER_SPRITE(AQUA_GRUNT_F, AquaGruntF, 0, 0, 0x200),
TRAINER_SPRITE(SWIMMER_M, SwimmerM, 0, 0, 0x200),
TRAINER_SPRITE(MAGMA_GRUNT_M, MagmaGruntM, 0, 0, 0x200),
TRAINER_SPRITE(EXPERT_M, ExpertM, 0, 0, 0x200),
TRAINER_SPRITE(AQUA_ADMIN_M, AquaAdminM, 0, 0, 0x200),
TRAINER_SPRITE(BLACK_BELT, BlackBelt, 0, 0, 0x200),
TRAINER_SPRITE(AQUA_ADMIN_F, AquaAdminF, 0, 0, 0x200),
TRAINER_SPRITE(AQUA_LEADER_ARCHIE, AquaLeaderArchie, 0, 0, 0x200),
TRAINER_SPRITE(HEX_MANIAC, HexManiac, 0, 0, 0x200),
TRAINER_SPRITE(AROMA_LADY, AromaLady, 0, 0, 0x200),
TRAINER_SPRITE(RUIN_MANIAC, RuinManiac, 0, 0, 0x200),
TRAINER_SPRITE(INTERVIEWER, Interviewer, 0, 0, 0x200),
TRAINER_SPRITE(TUBER_F, TuberF, 0, 0, 0x200),
TRAINER_SPRITE(TUBER_M, TuberM, 0, 0, 0x200),
TRAINER_SPRITE(COOLTRAINER_F, CoolTrainerF, 0, 0, 0x200),
TRAINER_SPRITE(LADY, Lady, 0, 0, 0x200),
TRAINER_SPRITE(BEAUTY, Beauty, 0, 0, 0x200),
TRAINER_SPRITE(RICH_BOY, RichBoy, 0, 0, 0x200),
TRAINER_SPRITE(EXPERT_F, ExpertF, 0, 0, 0x200),
TRAINER_SPRITE(POKEMANIAC, Pokemaniac, 0, 0, 0x200),
TRAINER_SPRITE(MAGMA_GRUNT_F, MagmaGruntF, 0, 0, 0x200),
TRAINER_SPRITE(GUITARIST, Guitarist, 0, 0, 0x200),
TRAINER_SPRITE(KINDLER, Kindler, 0, 0, 0x200),
TRAINER_SPRITE(CAMPER, Camper, 0, 0, 0x200),
TRAINER_SPRITE(PICNICKER, Picnicker, 0, 0, 0x200),
TRAINER_SPRITE(BUG_MANIAC, BugManiac, 0, 0, 0x200),
TRAINER_SPRITE(POKEMON_BREEDER_M, PokemonBreederM, 0, 0, 0x200),
TRAINER_SPRITE(PSYCHIC_M, PsychicM, 0, 0, 0x200),
TRAINER_SPRITE(PSYCHIC_F, PsychicF, 0, 0, 0x200),
TRAINER_SPRITE(GENTLEMAN, Gentleman, 0, 0, 0x200),
TRAINER_SPRITE(ELITE_FOUR_SIDNEY, EliteFourSidney, 0, 0, 0x200),
TRAINER_SPRITE(ELITE_FOUR_PHOEBE, EliteFourPhoebe, 0, 0, 0x200),
TRAINER_SPRITE(HIKER, Hiker),
TRAINER_SPRITE(AQUA_GRUNT_M, AquaGruntM),
TRAINER_SPRITE(POKEMON_BREEDER_F, PokemonBreederF),
TRAINER_SPRITE(COOLTRAINER_M, CoolTrainerM),
TRAINER_SPRITE(BIRD_KEEPER, BirdKeeper),
TRAINER_SPRITE(COLLECTOR, Collector),
TRAINER_SPRITE(AQUA_GRUNT_F, AquaGruntF),
TRAINER_SPRITE(SWIMMER_M, SwimmerM),
TRAINER_SPRITE(MAGMA_GRUNT_M, MagmaGruntM),
TRAINER_SPRITE(EXPERT_M, ExpertM),
TRAINER_SPRITE(AQUA_ADMIN_M, AquaAdminM),
TRAINER_SPRITE(BLACK_BELT, BlackBelt),
TRAINER_SPRITE(AQUA_ADMIN_F, AquaAdminF),
TRAINER_SPRITE(AQUA_LEADER_ARCHIE, AquaLeaderArchie),
TRAINER_SPRITE(HEX_MANIAC, HexManiac),
TRAINER_SPRITE(AROMA_LADY, AromaLady),
TRAINER_SPRITE(RUIN_MANIAC, RuinManiac),
TRAINER_SPRITE(INTERVIEWER, Interviewer),
TRAINER_SPRITE(TUBER_F, TuberF),
TRAINER_SPRITE(TUBER_M, TuberM),
TRAINER_SPRITE(COOLTRAINER_F, CoolTrainerF),
TRAINER_SPRITE(LADY, Lady),
TRAINER_SPRITE(BEAUTY, Beauty),
TRAINER_SPRITE(RICH_BOY, RichBoy),
TRAINER_SPRITE(EXPERT_F, ExpertF),
TRAINER_SPRITE(POKEMANIAC, Pokemaniac),
TRAINER_SPRITE(MAGMA_GRUNT_F, MagmaGruntF),
TRAINER_SPRITE(GUITARIST, Guitarist),
TRAINER_SPRITE(KINDLER, Kindler),
TRAINER_SPRITE(CAMPER, Camper),
TRAINER_SPRITE(PICNICKER, Picnicker),
TRAINER_SPRITE(BUG_MANIAC, BugManiac),
TRAINER_SPRITE(POKEMON_BREEDER_M, PokemonBreederM),
TRAINER_SPRITE(PSYCHIC_M, PsychicM),
TRAINER_SPRITE(PSYCHIC_F, PsychicF),
TRAINER_SPRITE(GENTLEMAN, Gentleman),
TRAINER_SPRITE(ELITE_FOUR_SIDNEY, EliteFourSidney),
TRAINER_SPRITE(ELITE_FOUR_PHOEBE, EliteFourPhoebe),
TRAINER_SPRITE(ELITE_FOUR_GLACIA, EliteFourGlacia, -4, 4, 0x1B0),
TRAINER_SPRITE(ELITE_FOUR_DRAKE, EliteFourDrake, 0, 5, 0x1A0),
TRAINER_SPRITE(LEADER_ROXANNE, LeaderRoxanne, 0, 0, 0x200),
TRAINER_SPRITE(LEADER_BRAWLY, LeaderBrawly, 0, 0, 0x200),
TRAINER_SPRITE(LEADER_WATTSON, LeaderWattson, 0, 0, 0x200),
TRAINER_SPRITE(LEADER_FLANNERY, LeaderFlannery, 0, 0, 0x200),
TRAINER_SPRITE(LEADER_NORMAN, LeaderNorman, 0, 0, 0x200),
TRAINER_SPRITE(LEADER_WINONA, LeaderWinona, 0, 0, 0x200),
TRAINER_SPRITE(LEADER_TATE_AND_LIZA, LeaderTateAndLiza, 0, 0, 0x200),
TRAINER_SPRITE(LEADER_JUAN, LeaderJuan, 0, 0, 0x200),
TRAINER_SPRITE(SCHOOL_KID_M, SchoolKidM, 0, 0, 0x200),
TRAINER_SPRITE(SCHOOL_KID_F, SchoolKidF, 0, 0, 0x200),
TRAINER_SPRITE(SR_AND_JR, SrAndJr, 0, 0, 0x200),
TRAINER_SPRITE(POKEFAN_M, PokefanM, 0, 0, 0x200),
TRAINER_SPRITE(POKEFAN_F, PokefanF, 0, 0, 0x200),
TRAINER_SPRITE(YOUNGSTER, Youngster, 0, 0, 0x200),
TRAINER_SPRITE(LEADER_ROXANNE, LeaderRoxanne),
TRAINER_SPRITE(LEADER_BRAWLY, LeaderBrawly),
TRAINER_SPRITE(LEADER_WATTSON, LeaderWattson),
TRAINER_SPRITE(LEADER_FLANNERY, LeaderFlannery),
TRAINER_SPRITE(LEADER_NORMAN, LeaderNorman),
TRAINER_SPRITE(LEADER_WINONA, LeaderWinona),
TRAINER_SPRITE(LEADER_TATE_AND_LIZA, LeaderTateAndLiza),
TRAINER_SPRITE(LEADER_JUAN, LeaderJuan),
TRAINER_SPRITE(SCHOOL_KID_M, SchoolKidM),
TRAINER_SPRITE(SCHOOL_KID_F, SchoolKidF),
TRAINER_SPRITE(SR_AND_JR, SrAndJr),
TRAINER_SPRITE(POKEFAN_M, PokefanM),
TRAINER_SPRITE(POKEFAN_F, PokefanF),
TRAINER_SPRITE(YOUNGSTER, Youngster),
TRAINER_SPRITE(CHAMPION_WALLACE, ChampionWallace, -8, 7, 0x188),
TRAINER_SPRITE(FISHERMAN, Fisherman, 0, 0, 0x200),
TRAINER_SPRITE(CYCLING_TRIATHLETE_M, CyclingTriathleteM, 0, 0, 0x200),
TRAINER_SPRITE(CYCLING_TRIATHLETE_F, CyclingTriathleteF, 0, 0, 0x200),
TRAINER_SPRITE(RUNNING_TRIATHLETE_M, RunningTriathleteM, 0, 0, 0x200),
TRAINER_SPRITE(RUNNING_TRIATHLETE_F, RunningTriathleteF, 0, 0, 0x200),
TRAINER_SPRITE(SWIMMING_TRIATHLETE_M, SwimmingTriathleteM, 0, 0, 0x200),
TRAINER_SPRITE(SWIMMING_TRIATHLETE_F, SwimmingTriathleteF, 0, 0, 0x200),
TRAINER_SPRITE(DRAGON_TAMER, DragonTamer, 0, 0, 0x200),
TRAINER_SPRITE(NINJA_BOY, NinjaBoy, 0, 0, 0x200),
TRAINER_SPRITE(BATTLE_GIRL, BattleGirl, 0, 0, 0x200),
TRAINER_SPRITE(PARASOL_LADY, ParasolLady, 0, 0, 0x200),
TRAINER_SPRITE(SWIMMER_F, SwimmerF, 0, 0, 0x200),
TRAINER_SPRITE(TWINS, Twins, 0, 0, 0x200),
TRAINER_SPRITE(SAILOR, Sailor, 0, 0, 0x200),
TRAINER_SPRITE(MAGMA_ADMIN, MagmaAdmin, 0, 0, 0x200),
TRAINER_SPRITE(WALLY, Wally, 0, 0, 0x200),
TRAINER_SPRITE(BRENDAN, Brendan, 0, 0, 0x200),
TRAINER_SPRITE(MAY, May, 0, 0, 0x200),
TRAINER_SPRITE(BUG_CATCHER, BugCatcher, 0, 0, 0x200),
TRAINER_SPRITE(POKEMON_RANGER_M, PokemonRangerM, 0, 0, 0x200),
TRAINER_SPRITE(POKEMON_RANGER_F, PokemonRangerF, 0, 0, 0x200),
TRAINER_SPRITE(MAGMA_LEADER_MAXIE, MagmaLeaderMaxie, 0, 0, 0x200),
TRAINER_SPRITE(LASS, Lass, 0, 0, 0x200),
TRAINER_SPRITE(YOUNG_COUPLE, YoungCouple, 0, 0, 0x200),
TRAINER_SPRITE(OLD_COUPLE, OldCouple, 0, 0, 0x200),
TRAINER_SPRITE(SIS_AND_BRO, SisAndBro, 0, 0, 0x200),
TRAINER_SPRITE(FISHERMAN, Fisherman),
TRAINER_SPRITE(CYCLING_TRIATHLETE_M, CyclingTriathleteM),
TRAINER_SPRITE(CYCLING_TRIATHLETE_F, CyclingTriathleteF),
TRAINER_SPRITE(RUNNING_TRIATHLETE_M, RunningTriathleteM),
TRAINER_SPRITE(RUNNING_TRIATHLETE_F, RunningTriathleteF),
TRAINER_SPRITE(SWIMMING_TRIATHLETE_M, SwimmingTriathleteM),
TRAINER_SPRITE(SWIMMING_TRIATHLETE_F, SwimmingTriathleteF),
TRAINER_SPRITE(DRAGON_TAMER, DragonTamer),
TRAINER_SPRITE(NINJA_BOY, NinjaBoy),
TRAINER_SPRITE(BATTLE_GIRL, BattleGirl),
TRAINER_SPRITE(PARASOL_LADY, ParasolLady),
TRAINER_SPRITE(SWIMMER_F, SwimmerF),
TRAINER_SPRITE(TWINS, Twins),
TRAINER_SPRITE(SAILOR, Sailor),
TRAINER_SPRITE(MAGMA_ADMIN, MagmaAdmin),
TRAINER_SPRITE(WALLY, Wally),
TRAINER_SPRITE(BRENDAN, Brendan),
TRAINER_SPRITE(MAY, May),
TRAINER_SPRITE(BUG_CATCHER, BugCatcher),
TRAINER_SPRITE(POKEMON_RANGER_M, PokemonRangerM),
TRAINER_SPRITE(POKEMON_RANGER_F, PokemonRangerF),
TRAINER_SPRITE(MAGMA_LEADER_MAXIE, MagmaLeaderMaxie),
TRAINER_SPRITE(LASS, Lass),
TRAINER_SPRITE(YOUNG_COUPLE, YoungCouple),
TRAINER_SPRITE(OLD_COUPLE, OldCouple),
TRAINER_SPRITE(SIS_AND_BRO, SisAndBro),
TRAINER_SPRITE(STEVEN, Steven, 0, 7, 0x188),
TRAINER_SPRITE(SALON_MAIDEN_ANABEL, SalonMaidenAnabel, 0, 0, 0x200),
TRAINER_SPRITE(DOME_ACE_TUCKER, DomeAceTucker, 0, 0, 0x200),
TRAINER_SPRITE(PALACE_MAVEN_SPENSER, PalaceMavenSpenser, 0, 0, 0x200),
TRAINER_SPRITE(ARENA_TYCOON_GRETA, ArenaTycoonGreta, 0, 0, 0x200),
TRAINER_SPRITE(FACTORY_HEAD_NOLAND, FactoryHeadNoland, 0, 0, 0x200),
TRAINER_SPRITE(PIKE_QUEEN_LUCY, PikeQueenLucy, 0, 0, 0x200),
TRAINER_SPRITE(PYRAMID_KING_BRANDON, PyramidKingBrandon, 0, 0, 0x200),
TRAINER_SPRITE(RED, Red, 0, 0, 0x200),
TRAINER_SPRITE(LEAF, Leaf, 0, 0, 0x200),
TRAINER_SPRITE(RS_BRENDAN, RubySapphireBrendan, 0, 0, 0x200),
TRAINER_SPRITE(RS_MAY, RubySapphireMay, 0, 0, 0x200),
TRAINER_SPRITE(SALON_MAIDEN_ANABEL, SalonMaidenAnabel),
TRAINER_SPRITE(DOME_ACE_TUCKER, DomeAceTucker),
TRAINER_SPRITE(PALACE_MAVEN_SPENSER, PalaceMavenSpenser),
TRAINER_SPRITE(ARENA_TYCOON_GRETA, ArenaTycoonGreta),
TRAINER_SPRITE(FACTORY_HEAD_NOLAND, FactoryHeadNoland),
TRAINER_SPRITE(PIKE_QUEEN_LUCY, PikeQueenLucy),
TRAINER_SPRITE(PYRAMID_KING_BRANDON, PyramidKingBrandon),
TRAINER_SPRITE(RED, Red),
TRAINER_SPRITE(LEAF, Leaf),
TRAINER_SPRITE(RS_BRENDAN, RubySapphireBrendan),
TRAINER_SPRITE(RS_MAY, RubySapphireMay),
};
static const union AnimCmd sAnimCmd_Hoenn[] =

View File

@ -2,6 +2,7 @@
#include "constants/battle.h"
#include "constants/battle_move_effects.h"
#include "constants/battle_script_commands.h"
#include "constants/battle_string_ids.h"
#include "constants/battle_z_move_effects.h"
#include "constants/hold_effects.h"
#include "constants/moves.h"
@ -9,9 +10,8 @@
// The Gen. 4+ contest data comes from urpg's contest movedex.
#define FIRST(a, ...) a
#if B_EXPANDED_MOVE_NAMES == TRUE
#define HANDLE_EXPANDED_MOVE_NAME(_name, ...) COMPOUND_STRING(FIRST(__VA_OPT__(__VA_ARGS__, ) _name))
#define HANDLE_EXPANDED_MOVE_NAME(_name, ...) COMPOUND_STRING(DEFAULT(_name, __VA_ARGS__))
#else
#define HANDLE_EXPANDED_MOVE_NAME(_name, ...) COMPOUND_STRING(_name)
#endif
@ -22,6 +22,11 @@
#define BINDING_TURNS "2 to 5"
#endif
/* First arg is the charge turn string id, second arg depends on effect
EFFECT_SEMI_INVULNERABLE/EFFECT_SKY_DROP: semi-invulnerable STATUS3 to apply to battler
EFFECT_TWO_TURNS_ATTACK/EFFECT_SOLAR_BEAM: weather in which to skip charge turn */
#define TWO_TURN_ARG(stringid, ...) (stringid) __VA_OPT__(| ((__VA_ARGS__) << 16))
// Shared Move Description entries
const u8 gNotDoneYetDescription[] = _(
@ -428,6 +433,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] =
.sleepTalkBanned = TRUE,
.instructBanned = TRUE,
.windMove = B_EXTRAPOLATED_MOVE_FLAGS,
.argument = TWO_TURN_ARG(STRINGID_PKMNWHIPPEDWHIRLWIND),
.contestEffect = CONTEST_EFFECT_AFFECTED_BY_PREV_APPEAL,
.contestCategory = CONTEST_CATEGORY_COOL,
.contestComboStarterId = 0,
@ -485,7 +491,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] =
.description = COMPOUND_STRING(
"Strikes the foe with a gust\n"
"of wind whipped up by wings."),
.effect = EFFECT_GUST,
.effect = EFFECT_HIT,
.power = 40,
.type = TYPE_FLYING,
.accuracy = 100,
@ -570,6 +576,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] =
.sleepTalkBanned = TRUE,
.instructBanned = TRUE,
.assistBanned = TRUE,
.argument = TWO_TURN_ARG(STRINGID_PKMNFLEWHIGH, COMPRESS_BITS(STATUS3_ON_AIR)),
.contestEffect = CONTEST_EFFECT_AVOID_STARTLE,
.contestCategory = CONTEST_CATEGORY_SMART,
.contestComboStarterId = 0,
@ -1933,6 +1940,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] =
.twoTurnMove = TRUE,
.sleepTalkBanned = TRUE,
.instructBanned = TRUE,
.argument = TWO_TURN_ARG(STRINGID_PKMNTOOKSUNLIGHT, B_WEATHER_SUN),
.contestEffect = CONTEST_EFFECT_HIGHLY_APPEALING,
.contestCategory = CONTEST_CATEGORY_COOL,
.contestComboStarterId = 0,
@ -2292,6 +2300,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] =
.instructBanned = TRUE,
.assistBanned = TRUE,
.skyBattleBanned = TRUE,
.argument = TWO_TURN_ARG(STRINGID_PKMNDUGHOLE, COMPRESS_BITS(STATUS3_UNDERGROUND)),
.contestEffect = CONTEST_EFFECT_AVOID_STARTLE,
.contestCategory = CONTEST_CATEGORY_SMART,
.contestComboStarterId = 0,
@ -2884,6 +2893,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] =
.priority = 0,
.category = DAMAGE_CATEGORY_STATUS,
.zMove = { .effect = Z_EFFECT_ACC_UP_1 },
.argument = STATUS2_FOCUS_ENERGY,
.ignoresProtect = TRUE,
.mirrorMoveBanned = TRUE,
.snatchAffected = TRUE,
@ -3221,7 +3231,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] =
.description = COMPOUND_STRING(
"Tucks in the head, then\n"
"attacks on the next turn."),
.effect = EFFECT_SKULL_BASH,
.effect = EFFECT_TWO_TURNS_ATTACK,
.power = B_UPDATED_MOVE_DATA >= GEN_6 ? 130 : 100,
.type = TYPE_NORMAL,
.accuracy = 100,
@ -3233,6 +3243,12 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] =
.makesContact = TRUE,
.sleepTalkBanned = TRUE,
.instructBanned = TRUE,
.argument = TWO_TURN_ARG(STRINGID_PKMNLOWEREDHEAD),
.additionalEffects = ADDITIONAL_EFFECTS({
.moveEffect = MOVE_EFFECT_DEF_PLUS_1,
.self = TRUE,
.onChargeTurnOnly = TRUE,
}),
.contestEffect = CONTEST_EFFECT_BADLY_STARTLE_FRONT_MON,
.contestCategory = CONTEST_CATEGORY_TOUGH,
.contestComboStarterId = 0,
@ -3541,11 +3557,12 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] =
.target = MOVE_TARGET_SELECTED,
.priority = 0,
.category = DAMAGE_CATEGORY_PHYSICAL,
.criticalHitStage = B_UPDATED_MOVE_DATA >= GEN_3 ? 1 : 0,
.criticalHitStage = B_UPDATED_MOVE_DATA >= GEN_3,
.twoTurnMove = TRUE,
.sheerForceBoost = TRUE,
.sleepTalkBanned = TRUE,
.instructBanned = TRUE,
.argument = TWO_TURN_ARG(B_UPDATED_MOVE_DATA >= GEN_4 ? STRINGID_CLOAKEDINAHARSHLIGHT : STRINGID_PKMNISGLOWING),
#if B_UPDATED_MOVE_DATA >= GEN_3
.additionalEffects = ADDITIONAL_EFFECTS({
.moveEffect = MOVE_EFFECT_FLINCH,
@ -7140,6 +7157,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] =
.instructBanned = TRUE,
.assistBanned = TRUE,
.skyBattleBanned = TRUE,
.argument = TWO_TURN_ARG(STRINGID_PKMNHIDUNDERWATER, COMPRESS_BITS(STATUS3_UNDERWATER)),
.contestEffect = CONTEST_EFFECT_AVOID_STARTLE_ONCE,
.contestCategory = CONTEST_CATEGORY_BEAUTY,
.contestComboStarterId = COMBO_STARTER_DIVE,
@ -8000,7 +8018,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] =
.description = COMPOUND_STRING(
"An uppercut thrown as if\n"
"leaping into the sky."),
.effect = EFFECT_SKY_UPPERCUT,
.effect = EFFECT_HIT,
.power = 85,
.type = TYPE_FIGHTING,
.accuracy = 90,
@ -8312,6 +8330,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] =
.sleepTalkBanned = TRUE,
.instructBanned = TRUE,
.assistBanned = TRUE,
.argument = TWO_TURN_ARG(STRINGID_PKMNSPRANGUP, COMPRESS_BITS(STATUS3_ON_AIR)),
.additionalEffects = ADDITIONAL_EFFECTS({
.moveEffect = MOVE_EFFECT_PARALYSIS,
.chance = 30,
@ -11319,6 +11338,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] =
.sleepTalkBanned = TRUE,
.instructBanned = TRUE,
.assistBanned = TRUE,
.argument = TWO_TURN_ARG(STRINGID_VANISHEDINSTANTLY, COMPRESS_BITS(STATUS3_PHANTOM_FORCE)),
.additionalEffects = ADDITIONAL_EFFECTS({
.moveEffect = MOVE_EFFECT_FEINT,
}),
@ -12252,6 +12272,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] =
.sleepTalkBanned = TRUE,
.instructBanned = TRUE,
.assistBanned = TRUE,
.argument = TWO_TURN_ARG(STRINGID_PKMNTOOKTARGETHIGH, COMPRESS_BITS(STATUS3_ON_AIR)),
.contestEffect = CONTEST_EFFECT_AVOID_STARTLE,
.contestCategory = CONTEST_CATEGORY_SMART,
.contestComboStarterId = 0,
@ -13318,6 +13339,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] =
.metronomeBanned = TRUE,
.sleepTalkBanned = TRUE,
.instructBanned = TRUE,
.argument = TWO_TURN_ARG(STRINGID_CLOAKEDINAFREEZINGLIGHT),
.additionalEffects = ADDITIONAL_EFFECTS({
.moveEffect = MOVE_EFFECT_PARALYSIS,
.chance = 30,
@ -13347,6 +13369,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] =
.metronomeBanned = TRUE,
.sleepTalkBanned = TRUE,
.instructBanned = TRUE,
.argument = TWO_TURN_ARG(STRINGID_CLOAKEDINAFREEZINGLIGHT),
.additionalEffects = ADDITIONAL_EFFECTS({
.moveEffect = MOVE_EFFECT_BURN,
.chance = 30,
@ -13648,6 +13671,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] =
.sleepTalkBanned = TRUE,
.instructBanned = TRUE,
.assistBanned = TRUE,
.argument = TWO_TURN_ARG(STRINGID_VANISHEDINSTANTLY, COMPRESS_BITS(STATUS3_PHANTOM_FORCE)),
.additionalEffects = ADDITIONAL_EFFECTS({
.moveEffect = MOVE_EFFECT_FEINT,
}),
@ -14475,6 +14499,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] =
.sleepTalkBanned = TRUE,
.instructBanned = TRUE,
.skyBattleBanned = TRUE,
.argument = TWO_TURN_ARG(STRINGID_PKNMABSORBINGPOWER),
.contestEffect = CONTEST_EFFECT_IMPROVE_CONDITION_PREVENT_NERVOUSNESS,
.contestCategory = CONTEST_CATEGORY_CUTE,
.contestComboStarterId = 0,
@ -14944,9 +14969,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] =
.ignoresSubstitute = TRUE,
.metronomeBanned = TRUE,
.sketchBanned = (B_SKETCH_BANS >= GEN_9),
.additionalEffects = ADDITIONAL_EFFECTS(
.additionalEffects = ADDITIONAL_EFFECTS({
// Feint move effect handled in script as it goes before animation
{
.moveEffect = MOVE_EFFECT_DEF_MINUS_1,
.self = TRUE,
}),
@ -15218,6 +15242,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] =
.slicingMove = TRUE,
.sleepTalkBanned = TRUE,
.instructBanned = TRUE,
.argument = TWO_TURN_ARG(STRINGID_PKMNTOOKSUNLIGHT, B_WEATHER_SUN),
.contestEffect = CONTEST_EFFECT_HIGHLY_APPEALING,
.contestCategory = CONTEST_CATEGORY_TOUGH,
.contestComboStarterId = 0,
@ -17458,7 +17483,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] =
.description = COMPOUND_STRING(
"A 2-turn move that raises\n"
"Sp. Attack before attacking."),
.effect = EFFECT_METEOR_BEAM,
.effect = EFFECT_TWO_TURNS_ATTACK,
.power = 120,
.type = TYPE_ROCK,
.accuracy = 90,
@ -17468,6 +17493,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] =
.category = DAMAGE_CATEGORY_SPECIAL,
.twoTurnMove = TRUE,
.instructBanned = TRUE,
.argument = TWO_TURN_ARG(STRINGID_METEORBEAMCHARGING),
.additionalEffects = ADDITIONAL_EFFECTS({
.moveEffect = MOVE_EFFECT_SP_ATK_PLUS_1,
.self = TRUE,
@ -19714,7 +19740,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] =
.description = COMPOUND_STRING(
"Absorbs electricity in one turn,\n"
"then attacks next turn."),
.effect = EFFECT_METEOR_BEAM,
.effect = EFFECT_TWO_TURNS_ATTACK,
.power = 130,
.type = TYPE_ELECTRIC,
.accuracy = 100,
@ -19723,6 +19749,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] =
.priority = 0,
.category = DAMAGE_CATEGORY_SPECIAL,
.sheerForceBoost = TRUE,
.argument = TWO_TURN_ARG(STRINGID_ELECTROSHOTCHARGING, B_WEATHER_RAIN),
.additionalEffects = ADDITIONAL_EFFECTS({
.moveEffect = MOVE_EFFECT_SP_ATK_PLUS_1,
.self = TRUE,
@ -19859,7 +19886,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] =
.description = COMPOUND_STRING(
"Increases allies' critical hit\n"
"ratio, especially if Dragons."),
.effect = EFFECT_PLACEHOLDER, //EFFECT_DRAGON_CHEER
.effect = EFFECT_DRAGON_CHEER,
.power = 0,
.type = TYPE_DRAGON,
.accuracy = 0,

View File

@ -1977,15 +1977,15 @@ const struct SpeciesInfo gSpeciesInfoGen8[] =
.pokemonOffset = 17,
.trainerScale = 256,
.trainerOffset = 0,
//FRONT_PIC(Hydrapple, 64, 64),
.frontPicYOffset = 0,
FRONT_PIC(Hydrapple, 64, 64),
.frontPicYOffset = 1,
.frontAnimFrames = sAnims_Hydrapple,
//.frontAnimId = ANIM_V_SQUISH_AND_BOUNCE,
//BACK_PIC(Hydrapple, 64, 64),
.frontAnimId = ANIM_V_SQUISH_AND_BOUNCE,
BACK_PIC(Hydrapple, 64, 64),
.backPicYOffset = 0,
//.backAnimId = BACK_ANIM_NONE,
//PALETTES(Hydrapple),
//ICON(Hydrapple, 0),
.backAnimId = BACK_ANIM_NONE,
PALETTES(Hydrapple),
ICON(Hydrapple, 1),
//FOOTPRINT(Hydrapple)
LEARNSETS(Hydrapple),
},
@ -4333,14 +4333,14 @@ const struct SpeciesInfo gSpeciesInfoGen8[] =
.pokemonOffset = 2,
.trainerScale = 286,
.trainerOffset = 1,
//FRONT_PIC(Archaludon, 64, 64),
FRONT_PIC(Archaludon, 64, 64),
.frontPicYOffset = 0,
.frontAnimFrames = sAnims_Archaludon,
//.frontAnimId = ANIM_V_SQUISH_AND_BOUNCE,
//BACK_PIC(Archaludon, 64, 64),
.backPicYOffset = 0,
//.backAnimId = BACK_ANIM_NONE,
//PALETTES(Archaludon),
.frontAnimId = ANIM_V_SQUISH_AND_BOUNCE,
BACK_PIC(Archaludon, 64, 64),
.backPicYOffset = 7,
.backAnimId = BACK_ANIM_NONE,
PALETTES(Archaludon),
//ICON(Archaludon, 0),
//FOOTPRINT(Archaludon)
LEARNSETS(Archaludon),

View File

@ -5468,14 +5468,14 @@ const struct SpeciesInfo gSpeciesInfoGen9[] =
.pokemonOffset = 0,
.trainerScale = 345,
.trainerOffset = 7,
//FRONT_PIC(GougingFire, 64, 64),
.frontPicYOffset = 0,
FRONT_PIC(GougingFire, 64, 64),
.frontPicYOffset = 2,
.frontAnimFrames = sAnims_GougingFire,
//.frontAnimId = ANIM_V_SQUISH_AND_BOUNCE,
//BACK_PIC(GougingFire, 64, 64),
.backPicYOffset = 0,
//.backAnimId = BACK_ANIM_NONE,
//PALETTES(GougingFire),
.frontAnimId = ANIM_V_SQUISH_AND_BOUNCE,
BACK_PIC(GougingFire, 64, 64),
.backPicYOffset = 6,
.backAnimId = BACK_ANIM_NONE,
PALETTES(GougingFire),
//ICON(GougingFire, 0),
//FOOTPRINT(GougingFire)
LEARNSETS(GougingFire),
@ -5518,14 +5518,14 @@ const struct SpeciesInfo gSpeciesInfoGen9[] =
.pokemonOffset = 0,
.trainerScale = 345,
.trainerOffset = 7,
//FRONT_PIC(RagingBolt, 64, 64),
FRONT_PIC(RagingBolt, 64, 64),
.frontPicYOffset = 0,
.frontAnimFrames = sAnims_RagingBolt,
//.frontAnimId = ANIM_V_SQUISH_AND_BOUNCE,
//BACK_PIC(RagingBolt, 64, 64),
.frontAnimId = ANIM_V_SQUISH_AND_BOUNCE,
BACK_PIC(RagingBolt, 64, 64),
.backPicYOffset = 0,
//.backAnimId = BACK_ANIM_NONE,
//PALETTES(RagingBolt),
.backAnimId = BACK_ANIM_NONE,
PALETTES(RagingBolt),
//ICON(RagingBolt, 0),
//FOOTPRINT(RagingBolt)
LEARNSETS(RagingBolt),
@ -5567,14 +5567,14 @@ const struct SpeciesInfo gSpeciesInfoGen9[] =
.pokemonOffset = 1,
.trainerScale = 336,
.trainerOffset = 4,
//FRONT_PIC(IronBoulder, 64, 64),
.frontPicYOffset = 0,
FRONT_PIC(IronBoulder, 64, 64),
.frontPicYOffset = 3,
.frontAnimFrames = sAnims_IronBoulder,
//.frontAnimId = ANIM_V_SQUISH_AND_BOUNCE,
//BACK_PIC(IronBoulder, 64, 64),
.backPicYOffset = 0,
//.backAnimId = BACK_ANIM_NONE,
//PALETTES(IronBoulder),
.frontAnimId = ANIM_V_SQUISH_AND_BOUNCE,
BACK_PIC(IronBoulder, 64, 64),
.backPicYOffset = 12,
.backAnimId = BACK_ANIM_NONE,
PALETTES(IronBoulder),
//ICON(IronBoulder, 0),
//FOOTPRINT(IronBoulder)
LEARNSETS(IronBoulder),
@ -5617,14 +5617,14 @@ const struct SpeciesInfo gSpeciesInfoGen9[] =
.pokemonOffset = 0,
.trainerScale = 365,
.trainerOffset = 7,
//FRONT_PIC(IronCrown, 64, 64),
FRONT_PIC(IronCrown, 64, 64),
.frontPicYOffset = 0,
.frontAnimFrames = sAnims_IronCrown,
//.frontAnimId = ANIM_V_SQUISH_AND_BOUNCE,
//BACK_PIC(IronCrown, 64, 64),
.backPicYOffset = 0,
//.backAnimId = BACK_ANIM_NONE,
//PALETTES(IronCrown),
.frontAnimId = ANIM_V_SQUISH_AND_BOUNCE,
BACK_PIC(IronCrown, 64, 64),
.backPicYOffset = 2,
.backAnimId = BACK_ANIM_NONE,
PALETTES(IronCrown),
//ICON(IronCrown, 0),
//FOOTPRINT(IronCrown)
LEARNSETS(IronCrown),

View File

@ -1192,7 +1192,7 @@ bool32 CannotUseItemsInBattle(u16 itemId, struct Pokemon *mon)
cannotUse = TRUE;
break;
case EFFECT_ITEM_SET_FOCUS_ENERGY:
if (gBattleMons[gBattlerInMenuId].status2 & STATUS2_FOCUS_ENERGY)
if (gBattleMons[gBattlerInMenuId].status2 & STATUS2_FOCUS_ENERGY_ANY)
cannotUse = TRUE;
break;
case EFFECT_ITEM_SET_MIST:

View File

@ -399,10 +399,14 @@ void Overworld_ResetStateAfterDigEscRope(void)
}
#if B_RESET_FLAGS_VARS_AFTER_WHITEOUT == TRUE
void Overworld_ResetBattleFlagsAndVars(void)
void Overworld_ResetBattleFlagsAndVars(void)
{
#if VAR_TERRAIN != 0
VarSet(VAR_TERRAIN, 0);
#if B_VAR_TERRAIN != 0
VarSet(B_VAR_TERRAIN, 0);
#endif
#if B_VAR_TERRAIN_TIMER != 0
VarSet(B_VAR_TERRAIN_TIMER, 0);
#endif
#if B_VAR_WILD_AI_FLAGS != 0

View File

@ -107,9 +107,11 @@ static void CreateAreaUnknownSprites(void);
static void Task_HandlePokedexAreaScreenInput(u8);
static void ResetPokedexAreaMapBg(void);
static void DestroyAreaScreenSprites(void);
static void LoadHGSSScreenSelectBarSubmenu(void);
static const u32 sAreaGlow_Pal[] = INCBIN_U32("graphics/pokedex/area_glow.gbapal");
static const u32 sAreaGlow_Gfx[] = INCBIN_U32("graphics/pokedex/area_glow.4bpp.lz");
static const u32 sPokedexPlusHGSS_ScreenSelectBarSubmenu_Tilemap[] = INCBIN_U32("graphics/pokedex/hgss/SelectBar.bin.lz");
static const u16 sSpeciesHiddenFromAreaScreen[] = { SPECIES_WYNAUT };
@ -639,6 +641,9 @@ static void Task_ShowPokedexAreaScreen(u8 taskId)
BeginNormalPaletteFade(PALETTES_ALL & ~(0x14), 0, 16, 0, RGB_BLACK);
break;
case 10:
if (POKEDEX_PLUS_HGSS)
LoadHGSSScreenSelectBarSubmenu();
SetGpuReg(REG_OFFSET_BLDCNT, BLDCNT_TGT1_BG0 | BLDCNT_EFFECT_BLEND | BLDCNT_TGT2_BG0 | BLDCNT_TGT2_ALL);
StartAreaGlow();
ShowBg(2);
@ -806,3 +811,9 @@ static void CreateAreaUnknownSprites(void)
}
}
}
static void LoadHGSSScreenSelectBarSubmenu(void)
{
CopyToBgTilemapBuffer(1, sPokedexPlusHGSS_ScreenSelectBarSubmenu_Tilemap, 0, 0);
CopyBgTilemapBufferToVram(1);
}

View File

@ -531,7 +531,6 @@ static void Task_LoadSizeScreen(u8);
static void Task_HandleSizeScreenInput(u8);
static void Task_SwitchScreensFromSizeScreen(u8);
static void LoadScreenSelectBarMain(u16);
static void LoadScreenSelectBarSubmenu(u16);
static void HighlightScreenSelectBarItem(u8, u16);
static void Task_HandleCaughtMonPageInput(u8);
static void Task_ExitCaughtMonPage(u8);
@ -4032,7 +4031,6 @@ static void Task_LoadAreaScreen(u8 taskId)
}
break;
case 1:
LoadScreenSelectBarSubmenu(0xD);
LoadPokedexBgPalette(sPokedexView->isSearchResults);
SetGpuReg(REG_OFFSET_BG1CNT, BGCNT_PRIORITY(0) | BGCNT_CHARBASE(0) | BGCNT_SCREENBASE(13) | BGCNT_16COLOR | BGCNT_TXT256x256);
gMain.state++;
@ -4087,12 +4085,6 @@ static void LoadScreenSelectBarMain(u16 unused)
CopyBgTilemapBufferToVram(1);
}
static void LoadScreenSelectBarSubmenu(u16 unused)
{
CopyToBgTilemapBuffer(1, sPokedexPlusHGSS_ScreenSelectBarSubmenu_Tilemap, 0, 0);
CopyBgTilemapBufferToVram(1);
}
static void UNUSED HighlightScreenSelectBarItem(u8 selectedScreen, u16 unused)
{
u8 i;

View File

@ -1927,7 +1927,7 @@ void SetMultiuseSpriteTemplateToTrainerBack(u16 trainerPicId, u8 battlerPosition
gMultiuseSpriteTemplate = gMonSpritesGfxPtr->templates[battlerPosition];
else
gMultiuseSpriteTemplate = gBattlerSpriteTemplates[battlerPosition];
gMultiuseSpriteTemplate.anims = gTrainerSprites[trainerPicId].animation;
gMultiuseSpriteTemplate.anims = sAnims_Trainer;
}
}
@ -1939,7 +1939,7 @@ void SetMultiuseSpriteTemplateToTrainerFront(u16 trainerPicId, u8 battlerPositio
gMultiuseSpriteTemplate = gBattlerSpriteTemplates[battlerPosition];
gMultiuseSpriteTemplate.paletteTag = trainerPicId;
gMultiuseSpriteTemplate.anims = gTrainerSprites[trainerPicId].animation;
gMultiuseSpriteTemplate.anims = sAnims_Trainer;
}
static void EncryptBoxMon(struct BoxPokemon *boxMon)
@ -5151,27 +5151,19 @@ u8 CanLearnTeachableMove(u16 species, u16 move)
switch (move)
{
case MOVE_BADDY_BAD:
case MOVE_BLAST_BURN:
case MOVE_BOUNCY_BUBBLE:
case MOVE_BUZZY_BUZZ:
case MOVE_DRACO_METEOR:
case MOVE_DRAGON_ASCENT:
case MOVE_FIRE_PLEDGE:
case MOVE_FLOATY_FALL:
case MOVE_FREEZY_FROST:
case MOVE_FRENZY_PLANT:
case MOVE_GLITZY_GLOW:
case MOVE_GRASS_PLEDGE:
case MOVE_HYDRO_CANNON:
case MOVE_RELIC_SONG:
case MOVE_SAPPY_SEED:
case MOVE_SECRET_SWORD:
case MOVE_SIZZLY_SLIDE:
case MOVE_SPARKLY_SWIRL:
case MOVE_SPLISHY_SPLASH:
case MOVE_STEEL_BEAM:
case MOVE_VOLT_TACKLE:
case MOVE_WATER_PLEDGE:
case MOVE_ZIPPY_ZAP:
return FALSE;
default:

View File

@ -116,7 +116,7 @@ static void AssignSpriteAnimsTable(bool8 isTrainer)
if (!isTrainer)
sCreatingSpriteTemplate.anims = gAnims_MonPic;
else
sCreatingSpriteTemplate.anims = gTrainerSprites[0].animation;
sCreatingSpriteTemplate.anims = sAnims_Trainer;
}
static u16 CreatePicSprite(u16 species, bool8 isShiny, u32 personality, bool8 isFrontPic, s16 x, s16 y, u8 paletteSlot, u16 paletteTag, bool8 isTrainer)

View File

@ -28,8 +28,7 @@ SINGLE_BATTLE_TEST("Sheer Force boosts power, but removes secondary effects of m
TURN { MOVE(opponent, MOVE_QUICK_ATTACK); MOVE(player, move); }
else
TURN { MOVE(player, move); }
if (gMovesInfo[move].effect == EFFECT_TWO_TURNS_ATTACK || gMovesInfo[move].effect == EFFECT_SEMI_INVULNERABLE
|| gMovesInfo[move].effect == EFFECT_METEOR_BEAM) {
if (gMovesInfo[move].effect == EFFECT_TWO_TURNS_ATTACK || gMovesInfo[move].effect == EFFECT_SEMI_INVULNERABLE) {
TURN { SKIP_TURN(player); }
TURN { ; }
}

View File

@ -0,0 +1,139 @@
#include "global.h"
#include "test/battle.h"
SINGLE_BATTLE_TEST("Shield Dust blocks secondary effects")
{
u16 move;
PARAMETRIZE { move = MOVE_NUZZLE; }
PARAMETRIZE { move = MOVE_INFERNO; }
PARAMETRIZE { move = MOVE_MORTAL_SPIN; }
PARAMETRIZE { move = MOVE_FAKE_OUT; }
PARAMETRIZE { move = MOVE_ROCK_TOMB; }
PARAMETRIZE { move = MOVE_SPIRIT_SHACKLE; }
PARAMETRIZE { move = MOVE_PSYCHIC_NOISE; }
GIVEN {
ASSUME(MoveHasMoveEffectWithChance(MOVE_NUZZLE, MOVE_EFFECT_PARALYSIS, 100) == TRUE);
ASSUME(MoveHasMoveEffectWithChance(MOVE_INFERNO, MOVE_EFFECT_BURN, 100) == TRUE);
ASSUME(MoveHasMoveEffectWithChance(MOVE_MORTAL_SPIN, MOVE_EFFECT_POISON, 100) == TRUE);
ASSUME(MoveHasMoveEffectWithChance(MOVE_FAKE_OUT, MOVE_EFFECT_FLINCH, 100) == TRUE);
ASSUME(MoveHasMoveEffectWithChance(MOVE_ROCK_TOMB, MOVE_EFFECT_SPD_MINUS_1, 100) == TRUE);
ASSUME(MoveHasMoveEffectWithChance(MOVE_SPIRIT_SHACKLE, MOVE_EFFECT_PREVENT_ESCAPE, 100) == TRUE);
ASSUME(MoveHasMoveEffectWithChance(MOVE_PSYCHIC_NOISE, MOVE_EFFECT_PSYCHIC_NOISE, 100) == TRUE);
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_VIVILLON) { Ability(ABILITY_SHIELD_DUST); }
} WHEN {
TURN { MOVE(player, move); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, move, player);
HP_BAR(opponent);
NONE_OF {
MESSAGE("Foe Vivillon is paralyzed! It may be unable to move!");
MESSAGE("Foe Vivillon was burned!");
MESSAGE("Foe Vivillon was poisoned!");
MESSAGE("Foe Vivillon flinched!");
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent);
MESSAGE("Foe Vivillon was prevented from healing!");
}
} THEN { // Can't find good way to test trapping
EXPECT(!(opponent->status2 & STATUS2_ESCAPE_PREVENTION));
}
}
SINGLE_BATTLE_TEST("Shield Dust does not block primary effects")
{
u16 move;
PARAMETRIZE { move = MOVE_INFESTATION; }
PARAMETRIZE { move = MOVE_THOUSAND_ARROWS; }
PARAMETRIZE { move = MOVE_JAW_LOCK; }
PARAMETRIZE { move = MOVE_PAY_DAY; }
GIVEN {
ASSUME(MoveHasMoveEffectWithChance(MOVE_INFESTATION, MOVE_EFFECT_WRAP, 0) == TRUE);
ASSUME(MoveHasMoveEffectWithChance(MOVE_THOUSAND_ARROWS, MOVE_EFFECT_SMACK_DOWN, 0) == TRUE);
ASSUME(MoveHasMoveEffectWithChance(MOVE_JAW_LOCK, MOVE_EFFECT_TRAP_BOTH, 0) == TRUE);
ASSUME(MoveHasMoveEffectWithChance(MOVE_PAY_DAY, MOVE_EFFECT_PAYDAY, 0) == TRUE);
ASSUME(MoveHasMoveEffectWithChance(MOVE_SMACK_DOWN, MOVE_EFFECT_SMACK_DOWN, 0) == TRUE);
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_VIVILLON) { Ability(ABILITY_SHIELD_DUST); }
} WHEN {
TURN { MOVE(player, move); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, move, player);
HP_BAR(opponent);
switch (move)
{
case MOVE_INFESTATION:
MESSAGE("Foe Vivillon has been afflicted with an infestation by Wobbuffet!");
break;
case MOVE_THOUSAND_ARROWS:
MESSAGE("Foe Vivillon fell straight down!");
break;
case MOVE_JAW_LOCK:
MESSAGE("Neither Pokémon can run away!");
break;
case MOVE_PAY_DAY:
MESSAGE("Coins scattered everywhere!");
break;
}
} THEN { // Can't find good way to test trapping
if (move == MOVE_JAW_LOCK) {
EXPECT(opponent->status2 & STATUS2_ESCAPE_PREVENTION);
EXPECT(player->status2 & STATUS2_ESCAPE_PREVENTION);
}
}
}
SINGLE_BATTLE_TEST("Shield Dust does not block self-targeting effects, primary or secondary")
{
u16 move;
PARAMETRIZE { move = MOVE_POWER_UP_PUNCH; }
PARAMETRIZE { move = MOVE_RAPID_SPIN; }
PARAMETRIZE { move = MOVE_LEAF_STORM; }
PARAMETRIZE { move = MOVE_METEOR_ASSAULT; }
GIVEN {
ASSUME(MoveHasMoveEffectSelf(MOVE_POWER_UP_PUNCH, MOVE_EFFECT_ATK_PLUS_1) == TRUE);
ASSUME(MoveHasMoveEffectSelf(MOVE_RAPID_SPIN, MOVE_EFFECT_RAPIDSPIN) == TRUE);
ASSUME(MoveHasMoveEffectSelf(MOVE_LEAF_STORM, MOVE_EFFECT_SP_ATK_TWO_DOWN) == TRUE);
ASSUME(MoveHasMoveEffectSelf(MOVE_METEOR_ASSAULT, MOVE_EFFECT_RECHARGE) == TRUE);
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_VIVILLON) { Ability(ABILITY_SHIELD_DUST); }
} WHEN {
TURN { MOVE(player, move); }
if (move == MOVE_METEOR_ASSAULT) {
TURN { SKIP_TURN(player); }
}
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, move, player);
HP_BAR(opponent);
switch (move)
{
case MOVE_POWER_UP_PUNCH:
case MOVE_RAPID_SPIN:
case MOVE_LEAF_STORM:
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player);
break;
case MOVE_METEOR_ASSAULT: // second turn
MESSAGE("Wobbuffet must recharge!");
break;
}
}
}
DOUBLE_BATTLE_TEST("Shield Dust does not block Sparkling Aria in doubles")
{
KNOWN_FAILING;
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_VIVILLON) { Ability(ABILITY_SHIELD_DUST); Status1(STATUS1_BURN); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(playerLeft, MOVE_SPARKLING_ARIA); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_SPARKLING_ARIA, playerLeft);
MESSAGE("Foe Vivillion's burn was healed.");
STATUS_ICON(opponentLeft, burn: TRUE);
}
}

View File

@ -292,16 +292,39 @@ AI_SINGLE_BATTLE_TEST("AI chooses the safest option to faint the target, taking
// Psychic and Solar Beam are chosen because user is holding Power Herb
PARAMETRIZE { abilityAtk = ABILITY_STURDY; holdItemAtk = ITEM_POWER_HERB; move1 = MOVE_FOCUS_BLAST; move2 = MOVE_SOLAR_BEAM; move3 = MOVE_PSYCHIC; move4 = MOVE_DOUBLE_EDGE;
expectedMove = MOVE_PSYCHIC; expectedMove2 = MOVE_SOLAR_BEAM; }
// Psychic and Skull Bash are chosen because user is holding Power Herb
PARAMETRIZE { abilityAtk = ABILITY_STURDY; holdItemAtk = ITEM_POWER_HERB; move1 = MOVE_FOCUS_BLAST; move2 = MOVE_SKULL_BASH; move3 = MOVE_PSYCHIC; move4 = MOVE_DOUBLE_EDGE;
expectedMove = MOVE_PSYCHIC; expectedMove2 = MOVE_SKULL_BASH; }
// Skull Bash is chosen because it's the most accurate and is holding Power Herb
PARAMETRIZE { abilityAtk = ABILITY_STURDY; holdItemAtk = ITEM_POWER_HERB; move1 = MOVE_FOCUS_BLAST; move2 = MOVE_SKULL_BASH; move3 = MOVE_SLAM; move4 = MOVE_DOUBLE_EDGE;
expectedMove = MOVE_SKULL_BASH; }
GIVEN {
AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT);
PLAYER(SPECIES_WOBBUFFET) { HP(5); }
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_GEODUDE) { Moves(move1, move2, move3, move4); Ability(abilityAtk); Item(holdItemAtk); }
} WHEN {
TURN { if (expectedMove2 == MOVE_NONE) { EXPECT_MOVE(opponent, expectedMove); SEND_OUT(player, 1); }
else {EXPECT_MOVES(opponent, expectedMove, expectedMove2); SCORE_EQ(opponent, expectedMove, expectedMove2); SEND_OUT(player, 1);}
}
}
SCENE {
MESSAGE("Wobbuffet fainted!");
}
}
AI_SINGLE_BATTLE_TEST("AI chooses the safest option to faint the target, taking into account accuracy and move effect failing")
{
u16 move1 = MOVE_NONE, move2 = MOVE_NONE, move3 = MOVE_NONE, move4 = MOVE_NONE;
u16 expectedMove, expectedMove2 = MOVE_NONE;
u16 abilityAtk = ABILITY_NONE, holdItemAtk = ITEM_NONE;
// Fiery Dance and Skull Bash are chosen because user is holding Power Herb
PARAMETRIZE { abilityAtk = ABILITY_STURDY; holdItemAtk = ITEM_POWER_HERB; move1 = MOVE_FOCUS_BLAST; move2 = MOVE_SKULL_BASH; move3 = MOVE_FIERY_DANCE; move4 = MOVE_DOUBLE_EDGE;
expectedMove = MOVE_FIERY_DANCE; expectedMove2 = MOVE_SKULL_BASH; }
// Crabhammer is chosen even if Skull Bash is more accurate, the user has no Power Herb
PARAMETRIZE { abilityAtk = ABILITY_STURDY; move1 = MOVE_FOCUS_BLAST; move2 = MOVE_SKULL_BASH; move3 = MOVE_SLAM; move4 = MOVE_CRABHAMMER;
expectedMove = MOVE_CRABHAMMER; }
KNOWN_FAILING;
GIVEN {
AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT);
PLAYER(SPECIES_WOBBUFFET) { HP(5); }

View File

@ -212,7 +212,6 @@ SINGLE_BATTLE_TEST("Signature items Leek and Lucky Punch increase the critical h
u32 species;
u32 item;
ASSUME(B_CRIT_CHANCE >= GEN_7);
PASSES_RANDOMLY(1, 2, RNG_CRITICAL_HIT);
PARAMETRIZE { species = SPECIES_FARFETCHD; item = ITEM_LEEK; }
@ -250,3 +249,93 @@ SINGLE_BATTLE_TEST("Dire Hit increases a battler's critical hit chance by 2 stag
MESSAGE("A critical hit!");
}
}
SINGLE_BATTLE_TEST("Focus Energy increases critical hit ratio by two")
{
PASSES_RANDOMLY(8, 8, RNG_CRITICAL_HIT);
GIVEN {
ASSUME(gMovesInfo[MOVE_SLASH].criticalHitStage == 1);
ASSUME(gMovesInfo[MOVE_FOCUS_ENERGY].effect == EFFECT_FOCUS_ENERGY);
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, MOVE_FOCUS_ENERGY); }
TURN { MOVE(player, MOVE_SLASH); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_FOCUS_ENERGY, player);
MESSAGE("Wobbuffet is getting pumped!");
ANIMATION(ANIM_TYPE_MOVE, MOVE_SLASH, player);
MESSAGE("A critical hit!");
}
}
SINGLE_BATTLE_TEST("Dragon Cheer fails in a single battle")
{
GIVEN {
ASSUME(gMovesInfo[MOVE_DRAGON_CHEER].effect == EFFECT_DRAGON_CHEER);
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, MOVE_DRAGON_CHEER); }
} SCENE {
MESSAGE("But it failed!");
}
}
DOUBLE_BATTLE_TEST("Dragon Cheer increases critical hit ratio by one on non Dragon types")
{
PASSES_RANDOMLY(1, 8, RNG_CRITICAL_HIT);
GIVEN {
ASSUME(gMovesInfo[MOVE_TACKLE].criticalHitStage == 0);
ASSUME(gMovesInfo[MOVE_DRAGON_CHEER].effect == EFFECT_DRAGON_CHEER);
PLAYER(SPECIES_WOBBUFFET);
PLAYER(SPECIES_WYNAUT);
OPPONENT(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(playerLeft, MOVE_DRAGON_CHEER, target: playerRight); MOVE(playerRight, MOVE_TACKLE, target: opponentLeft); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_DRAGON_CHEER, playerLeft);
MESSAGE("Wynaut is getting pumped!");
ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, playerRight);
MESSAGE("A critical hit!");
}
}
DOUBLE_BATTLE_TEST("Dragon Cheer increases critical hit ratio by two on Dragon types")
{
PASSES_RANDOMLY(1, 2, RNG_CRITICAL_HIT);
GIVEN {
ASSUME(gMovesInfo[MOVE_TACKLE].criticalHitStage == 0);
ASSUME(gMovesInfo[MOVE_DRAGON_CHEER].effect == EFFECT_DRAGON_CHEER);
PLAYER(SPECIES_WOBBUFFET);
PLAYER(SPECIES_DRATINI);
OPPONENT(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(playerLeft, MOVE_DRAGON_CHEER, target: playerRight); MOVE(playerRight, MOVE_TACKLE, target: opponentLeft); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_DRAGON_CHEER, playerLeft);
MESSAGE("Dratini is getting pumped!");
ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, playerRight);
MESSAGE("A critical hit!");
}
}
DOUBLE_BATTLE_TEST("Dragon Cheer fails if critical hit stage was already increased by Focus Energy")
{
GIVEN {
ASSUME(gMovesInfo[MOVE_SLASH].criticalHitStage == 1);
ASSUME(gMovesInfo[MOVE_FOCUS_ENERGY].effect == EFFECT_FOCUS_ENERGY);
ASSUME(gMovesInfo[MOVE_DRAGON_CHEER].effect == EFFECT_DRAGON_CHEER);
PLAYER(SPECIES_WOBBUFFET);
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(playerLeft, MOVE_FOCUS_ENERGY); MOVE(playerRight, MOVE_DRAGON_CHEER, target: playerLeft); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_FOCUS_ENERGY, playerLeft);
MESSAGE("But it failed!");
}
}

View File

@ -1,61 +0,0 @@
#include "global.h"
#include "test/battle.h"
ASSUMPTIONS
{
ASSUME(gMovesInfo[MOVE_ELECTRO_SHOT].effect == EFFECT_METEOR_BEAM);
}
SINGLE_BATTLE_TEST("Electro Shot needs a charging Turn")
{
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, MOVE_ELECTRO_SHOT); }
TURN { SKIP_TURN(player); }
} SCENE {
// Charging turn
ANIMATION(ANIM_TYPE_MOVE, MOVE_ELECTRO_SHOT, player);
MESSAGE("Wobbuffet absorbed electricity!");
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player);
MESSAGE("Wobbuffet's Sp. Atk rose!");
// Attack turn
MESSAGE("Wobbuffet used Electro Shot!");
}
}
SINGLE_BATTLE_TEST("Electro Shot doesn't need to charge when it's raining")
{
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(opponent, MOVE_RAIN_DANCE); MOVE(player, MOVE_ELECTRO_SHOT); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_RAIN_DANCE, opponent);
ANIMATION(ANIM_TYPE_MOVE, MOVE_ELECTRO_SHOT, player);
MESSAGE("Wobbuffet absorbed electricity!");
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player);
MESSAGE("Wobbuffet's Sp. Atk rose!");
MESSAGE("Wobbuffet used Electro Shot!");
}
}
SINGLE_BATTLE_TEST("Electro Shot doesn't need to charge with Power Herb")
{
GIVEN {
PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_POWER_HERB); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, MOVE_ELECTRO_SHOT); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_ELECTRO_SHOT, player);
MESSAGE("Wobbuffet absorbed electricity!");
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player);
MESSAGE("Wobbuffet's Sp. Atk rose!");
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player);
MESSAGE("Wobbuffet became fully charged due to its Power Herb!");
MESSAGE("Wobbuffet used Electro Shot!");
}
}

View File

@ -0,0 +1,250 @@
#include "global.h"
#include "test/battle.h"
ASSUMPTIONS
{
ASSUME(gMovesInfo[MOVE_FLY].effect == EFFECT_SEMI_INVULNERABLE);
ASSUME(UNCOMPRESS_BITS(HIHALF(gMovesInfo[MOVE_FLY].argument)) == STATUS3_ON_AIR);
ASSUME(gMovesInfo[MOVE_DIG].effect == EFFECT_SEMI_INVULNERABLE);
ASSUME(UNCOMPRESS_BITS(HIHALF(gMovesInfo[MOVE_DIG].argument)) == STATUS3_UNDERGROUND);
ASSUME(gMovesInfo[MOVE_BOUNCE].effect == EFFECT_SEMI_INVULNERABLE);
ASSUME(UNCOMPRESS_BITS(HIHALF(gMovesInfo[MOVE_BOUNCE].argument)) == STATUS3_ON_AIR);
ASSUME(gMovesInfo[MOVE_DIVE].effect == EFFECT_SEMI_INVULNERABLE);
ASSUME(UNCOMPRESS_BITS(HIHALF(gMovesInfo[MOVE_DIVE].argument)) == STATUS3_UNDERWATER);
ASSUME(gMovesInfo[MOVE_PHANTOM_FORCE].effect == EFFECT_SEMI_INVULNERABLE);
ASSUME(UNCOMPRESS_BITS(HIHALF(gMovesInfo[MOVE_PHANTOM_FORCE].argument)) == STATUS3_PHANTOM_FORCE);
ASSUME(gMovesInfo[MOVE_SHADOW_FORCE].effect == EFFECT_SEMI_INVULNERABLE);
ASSUME(UNCOMPRESS_BITS(HIHALF(gMovesInfo[MOVE_SHADOW_FORCE].argument)) == STATUS3_PHANTOM_FORCE);
}
SINGLE_BATTLE_TEST("Semi-invulnerable moves make the user semi-invulnerable turn 1, then strike turn 2")
{
u16 move;
PARAMETRIZE { move = MOVE_FLY; }
PARAMETRIZE { move = MOVE_DIG; }
PARAMETRIZE { move = MOVE_BOUNCE; }
PARAMETRIZE { move = MOVE_DIVE; }
PARAMETRIZE { move = MOVE_PHANTOM_FORCE; }
PARAMETRIZE { move = MOVE_SHADOW_FORCE; }
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, move); MOVE(opponent, MOVE_AERIAL_ACE); }
TURN { SKIP_TURN(player); }
} SCENE {
// Charging turn
if (B_UPDATED_MOVE_DATA >= GEN_5)
{
switch (move)
{
case MOVE_FLY:
NOT MESSAGE("Wobbuffet flew up high!");
MESSAGE("Wobbuffet used Fly!");
break;
case MOVE_DIG:
NOT MESSAGE("Wobbuffet dug a hole!");
MESSAGE("Wobbuffet used Dig!");
break;
case MOVE_BOUNCE:
NOT MESSAGE("Wobbuffet sprang up!");
MESSAGE("Wobbuffet used Bounce!");
break;
case MOVE_DIVE:
NOT MESSAGE("Wobbuffet hid underwater!");
MESSAGE("Wobbuffet used Dive!");
break;
case MOVE_PHANTOM_FORCE:
NOT MESSAGE("Wobbuffet vanished instantly!");
MESSAGE("Wobbuffet used PhantomForce!");
break;
case MOVE_SHADOW_FORCE:
NOT MESSAGE("Wobbuffet vanished instantly!");
MESSAGE("Wobbuffet used Shadow Force!");
break;
}
} else {
ANIMATION(ANIM_TYPE_MOVE, move, player);
}
if (B_UPDATED_MOVE_DATA < GEN_5)
{
switch (move)
{
case MOVE_FLY:
MESSAGE("Wobbuffet flew up high!");
break;
case MOVE_DIG:
MESSAGE("Wobbuffet dug a hole!");
break;
case MOVE_BOUNCE:
MESSAGE("Wobbuffet sprang up!");
break;
case MOVE_DIVE:
MESSAGE("Wobbuffet hid underwater!");
break;
case MOVE_PHANTOM_FORCE:
case MOVE_SHADOW_FORCE:
MESSAGE("Wobbuffet vanished instantly!");
break;
}
}
else
ANIMATION(ANIM_TYPE_MOVE, move, player);
// Aerial Ace cannot miss unless the target is semi-invulnerable
MESSAGE("Foe Wobbuffet used Aerial Ace!");
MESSAGE("Foe Wobbuffet's attack missed!");
// Attack turn
switch (move)
{
case MOVE_FLY:
MESSAGE("Wobbuffet used Fly!");
break;
case MOVE_DIG:
MESSAGE("Wobbuffet used Dig!");
break;
case MOVE_BOUNCE:
MESSAGE("Wobbuffet used Bounce!");
break;
case MOVE_DIVE:
MESSAGE("Wobbuffet used Dive!");
break;
case MOVE_PHANTOM_FORCE:
MESSAGE("Wobbuffet used PhantomForce!");
break;
case MOVE_SHADOW_FORCE:
MESSAGE("Wobbuffet used Shadow Force!");
break;
}
ANIMATION(ANIM_TYPE_MOVE, move, player);
HP_BAR(opponent);
}
}
SINGLE_BATTLE_TEST("Semi-invulnerable moves don't need to charge with Power Herb")
{
u16 move;
PARAMETRIZE { move = MOVE_FLY; }
PARAMETRIZE { move = MOVE_DIG; }
PARAMETRIZE { move = MOVE_BOUNCE; }
PARAMETRIZE { move = MOVE_DIVE; }
PARAMETRIZE { move = MOVE_PHANTOM_FORCE; }
PARAMETRIZE { move = MOVE_SHADOW_FORCE; }
GIVEN {
PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_POWER_HERB); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, move); }
} SCENE {
// Charging turn
if (B_UPDATED_MOVE_DATA >= GEN_5)
{
switch (move)
{
case MOVE_FLY:
NOT MESSAGE("Wobbuffet flew up high!");
MESSAGE("Wobbuffet used Fly!");
break;
case MOVE_DIG:
NOT MESSAGE("Wobbuffet dug a hole!");
MESSAGE("Wobbuffet used Dig!");
break;
case MOVE_BOUNCE:
NOT MESSAGE("Wobbuffet sprang up!");
MESSAGE("Wobbuffet used Bounce!");
break;
case MOVE_DIVE:
NOT MESSAGE("Wobbuffet hid underwater!");
MESSAGE("Wobbuffet used Dive!");
break;
case MOVE_PHANTOM_FORCE:
NOT MESSAGE("Wobbuffet vanished instantly!");
MESSAGE("Wobbuffet used PhantomForce!");
break;
case MOVE_SHADOW_FORCE:
NOT MESSAGE("Wobbuffet vanished instantly!");
MESSAGE("Wobbuffet used Shadow Force!");
break;
}
} else {
ANIMATION(ANIM_TYPE_MOVE, move, player);
}
if (B_UPDATED_MOVE_DATA < GEN_5)
{
switch (move)
{
case MOVE_FLY:
MESSAGE("Wobbuffet flew up high!");
break;
case MOVE_DIG:
MESSAGE("Wobbuffet dug a hole!");
break;
case MOVE_BOUNCE:
MESSAGE("Wobbuffet sprang up!");
break;
case MOVE_DIVE:
MESSAGE("Wobbuffet hid underwater!");
break;
case MOVE_PHANTOM_FORCE:
case MOVE_SHADOW_FORCE:
MESSAGE("Wobbuffet vanished instantly!");
break;
}
}
else
ANIMATION(ANIM_TYPE_MOVE, move, player);
MESSAGE("Wobbuffet became fully charged due to its Power Herb!");
if (B_UPDATED_MOVE_DATA < GEN_5)
{
switch (move)
{
case MOVE_FLY:
MESSAGE("Wobbuffet used Fly!");
break;
case MOVE_DIG:
MESSAGE("Wobbuffet used Dig!");
break;
case MOVE_BOUNCE:
MESSAGE("Wobbuffet used Bounce!");
break;
case MOVE_DIVE:
MESSAGE("Wobbuffet used Dive!");
break;
case MOVE_PHANTOM_FORCE:
MESSAGE("Wobbuffet used PhantomForce!");
break;
case MOVE_SHADOW_FORCE:
MESSAGE("Wobbuffet used Shadow Force!");
break;
}
}
ANIMATION(ANIM_TYPE_MOVE, move, player);
HP_BAR(opponent);
}
}
// No way to apply this test with Shadow Force/Phantom Force
SINGLE_BATTLE_TEST("Semi-invulnerable moves apply a status that won't block certain moves")
{
u16 move, opMove;
PARAMETRIZE { move = MOVE_FLY; opMove = MOVE_SKY_UPPERCUT; }
PARAMETRIZE { move = MOVE_DIG; opMove = MOVE_EARTHQUAKE; }
PARAMETRIZE { move = MOVE_BOUNCE; opMove = MOVE_THUNDER; }
PARAMETRIZE { move = MOVE_DIVE; opMove = MOVE_SURF; }
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, move); MOVE(opponent, opMove); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, move, player);
ANIMATION(ANIM_TYPE_MOVE, opMove, opponent);
HP_BAR(player);
}
}

View File

@ -1,167 +0,0 @@
#include "global.h"
#include "test/battle.h"
ASSUMPTIONS
{
ASSUME(gMovesInfo[MOVE_SOLAR_BEAM].effect == EFFECT_SOLAR_BEAM);
ASSUME(gMovesInfo[MOVE_SOLAR_BLADE].effect == EFFECT_SOLAR_BEAM);
}
SINGLE_BATTLE_TEST("Solar Beam and Solar Blade can be used instantly in Sunlight")
{
u32 move;
PARAMETRIZE { move = MOVE_SOLAR_BEAM; }
PARAMETRIZE { move = MOVE_SOLAR_BLADE; }
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(opponent, MOVE_SUNNY_DAY); MOVE(player, move); }
} SCENE {
NOT MESSAGE("Wobbuffet took in sunlight!");
}
}
SINGLE_BATTLE_TEST("Solar Beam's power is halved in Rain", s16 damage)
{
u16 move;
PARAMETRIZE{ move = MOVE_CELEBRATE; }
PARAMETRIZE{ move = MOVE_RAIN_DANCE; }
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(opponent, move); MOVE(player, MOVE_SOLAR_BEAM); }
TURN { SKIP_TURN(player); }
} SCENE {
HP_BAR(opponent, captureDamage: &results[i].damage);
} FINALLY {
EXPECT_MUL_EQ(results[0].damage, Q_4_12(0.5), results[1].damage);
}
}
SINGLE_BATTLE_TEST("Solar Blade's power is halved in Rain", s16 damage)
{
u16 move;
PARAMETRIZE{ move = MOVE_CELEBRATE; }
PARAMETRIZE{ move = MOVE_RAIN_DANCE; }
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WYNAUT);
} WHEN {
TURN { MOVE(opponent, move); MOVE(player, MOVE_SOLAR_BLADE); }
TURN { SKIP_TURN(player); }
} SCENE {
HP_BAR(opponent, captureDamage: &results[i].damage);
} FINALLY {
EXPECT_MUL_EQ(results[0].damage, Q_4_12(0.5), results[1].damage);
}
}
SINGLE_BATTLE_TEST("Solar Beam's power is halved in a Sandstorm", s16 damage)
{
u16 move;
PARAMETRIZE{ move = MOVE_CELEBRATE; }
PARAMETRIZE{ move = MOVE_SANDSTORM; }
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_SAFETY_GOGGLES); };
} WHEN {
TURN { MOVE(opponent, move); MOVE(player, MOVE_SOLAR_BEAM); }
TURN { SKIP_TURN(player); }
} SCENE {
HP_BAR(opponent, captureDamage: &results[i].damage);
} FINALLY {
EXPECT_MUL_EQ(results[0].damage, Q_4_12(0.5), results[1].damage);
}
}
SINGLE_BATTLE_TEST("Solar Blade's power is halved in a Sandstorm", s16 damage)
{
u16 move;
PARAMETRIZE{ move = MOVE_CELEBRATE; }
PARAMETRIZE{ move = MOVE_SANDSTORM; }
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_SAFETY_GOGGLES); };
} WHEN {
TURN { MOVE(opponent, move); MOVE(player, MOVE_SOLAR_BLADE); }
TURN { SKIP_TURN(player); }
} SCENE {
HP_BAR(opponent, captureDamage: &results[i].damage);
} FINALLY {
EXPECT_MUL_EQ(results[0].damage, Q_4_12(0.5), results[1].damage);
}
}
SINGLE_BATTLE_TEST("Solar Beam's power is halved in Hail", s16 damage)
{
u16 move;
PARAMETRIZE{ move = MOVE_CELEBRATE; }
PARAMETRIZE{ move = MOVE_HAIL; }
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_SAFETY_GOGGLES); };
} WHEN {
TURN { MOVE(opponent, move); MOVE(player, MOVE_SOLAR_BEAM); }
TURN { SKIP_TURN(player); }
} SCENE {
HP_BAR(opponent, captureDamage: &results[i].damage);
} FINALLY {
EXPECT_MUL_EQ(results[0].damage, Q_4_12(0.5), results[1].damage);
}
}
SINGLE_BATTLE_TEST("Solar Blade's power is halved in Hail", s16 damage)
{
u16 move;
PARAMETRIZE{ move = MOVE_CELEBRATE; }
PARAMETRIZE{ move = MOVE_HAIL; }
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_SAFETY_GOGGLES); };
} WHEN {
TURN { MOVE(opponent, move); MOVE(player, MOVE_SOLAR_BLADE); }
TURN { SKIP_TURN(player); }
} SCENE {
HP_BAR(opponent, captureDamage: &results[i].damage);
} FINALLY {
EXPECT_MUL_EQ(results[0].damage, Q_4_12(0.5), results[1].damage);
}
}
SINGLE_BATTLE_TEST("Solar Beam's power is halved in Snow", s16 damage)
{
u16 move;
PARAMETRIZE{ move = MOVE_CELEBRATE; }
PARAMETRIZE{ move = MOVE_SNOWSCAPE; }
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(opponent, move); MOVE(player, MOVE_SOLAR_BEAM); }
TURN { SKIP_TURN(player); }
} SCENE {
HP_BAR(opponent, captureDamage: &results[i].damage);
} FINALLY {
EXPECT_MUL_EQ(results[0].damage, Q_4_12(0.5), results[1].damage);
}
}
SINGLE_BATTLE_TEST("Solar Blade's power is halved in Snow", s16 damage)
{
u16 move;
PARAMETRIZE{ move = MOVE_CELEBRATE; }
PARAMETRIZE{ move = MOVE_SNOWSCAPE; }
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WYNAUT);
} WHEN {
TURN { MOVE(opponent, move); MOVE(player, MOVE_SOLAR_BLADE); }
TURN { SKIP_TURN(player); }
} SCENE {
HP_BAR(opponent, captureDamage: &results[i].damage);
} FINALLY {
EXPECT_MUL_EQ(results[0].damage, Q_4_12(0.5), results[1].damage);
}
}

View File

@ -0,0 +1,449 @@
#include "global.h"
#include "test/battle.h"
ASSUMPTIONS
{
ASSUME(gMovesInfo[MOVE_RAZOR_WIND].effect == EFFECT_TWO_TURNS_ATTACK);
ASSUME(gMovesInfo[MOVE_SKULL_BASH].effect == EFFECT_TWO_TURNS_ATTACK);
ASSUME(MoveHasMoveEffectSelf(MOVE_SKULL_BASH, MOVE_EFFECT_DEF_PLUS_1) == TRUE);
ASSUME(gMovesInfo[MOVE_SKY_ATTACK].effect == EFFECT_TWO_TURNS_ATTACK);
// Solar Beam - check for sun
ASSUME(gMovesInfo[MOVE_SOLAR_BEAM].effect == EFFECT_SOLAR_BEAM);
ASSUME(HIHALF(gMovesInfo[MOVE_SOLAR_BLADE].argument) == B_WEATHER_SUN);
ASSUME(gMovesInfo[MOVE_SOLAR_BLADE].effect == EFFECT_SOLAR_BEAM);
ASSUME(HIHALF(gMovesInfo[MOVE_SOLAR_BLADE].argument) == B_WEATHER_SUN);
// Electro shot - check for rain
ASSUME(HIHALF(gMovesInfo[MOVE_ELECTRO_SHOT].argument) == B_WEATHER_RAIN);
ASSUME(gMovesInfo[MOVE_ELECTRO_SHOT].effect == EFFECT_TWO_TURNS_ATTACK);
ASSUME(MoveHasMoveEffectSelf(MOVE_ELECTRO_SHOT, MOVE_EFFECT_SP_ATK_PLUS_1) == TRUE);
}
SINGLE_BATTLE_TEST("Razor Wind needs a charging turn")
{
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, MOVE_RAZOR_WIND); }
TURN { SKIP_TURN(player); }
} SCENE {
// Charging turn
if (B_UPDATED_MOVE_DATA >= GEN_5) {
NOT MESSAGE("Wobbuffet whipped up a whirlwind!");
MESSAGE("Wobbuffet used Razor Wind!");
} else {
ANIMATION(ANIM_TYPE_MOVE, MOVE_RAZOR_WIND, player);
}
if (B_UPDATED_MOVE_DATA < GEN_5)
MESSAGE("Wobbuffet whipped up a whirlwind!");
else
ANIMATION(ANIM_TYPE_MOVE, MOVE_RAZOR_WIND, player);
// Attack turn
MESSAGE("Wobbuffet used Razor Wind!");
ANIMATION(ANIM_TYPE_MOVE, MOVE_RAZOR_WIND, player);
HP_BAR(opponent);
}
}
SINGLE_BATTLE_TEST("Razor Wind doesn't need to charge with Power Herb")
{
KNOWN_FAILING;
GIVEN {
PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_POWER_HERB); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, MOVE_RAZOR_WIND); }
} SCENE {
if (B_UPDATED_MOVE_DATA >= GEN_5) {
NOT MESSAGE("Wobbuffet whipped up a whirlwind!");
MESSAGE("Wobbuffet used Razor Wind!");
} else
ANIMATION(ANIM_TYPE_MOVE, MOVE_RAZOR_WIND, player);
if (B_UPDATED_MOVE_DATA < GEN_5)
MESSAGE("Wobbuffet whipped up a whirlwind!");
else
ANIMATION(ANIM_TYPE_MOVE, MOVE_RAZOR_WIND, player);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player);
MESSAGE("Wobbuffet became fully charged due to its Power Herb!");
if (B_UPDATED_MOVE_DATA < GEN_5)
MESSAGE("Wobbuffet used Razor Wind!");
// For some reason, this breaks with and only with Razor Wind...
ANIMATION(ANIM_TYPE_MOVE, MOVE_RAZOR_WIND, player);
HP_BAR(opponent);
}
}
SINGLE_BATTLE_TEST("Skull Bash needs a charging turn")
{
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, MOVE_SKULL_BASH); }
TURN { SKIP_TURN(player); }
} SCENE {
// Charging turn
if (B_UPDATED_MOVE_DATA >= GEN_5) {
NOT MESSAGE("Wobbuffet lowered its head!");
MESSAGE("Wobbuffet used Skull Bash!");
} else
ANIMATION(ANIM_TYPE_MOVE, MOVE_SKULL_BASH, player);
if (B_UPDATED_MOVE_DATA < GEN_5)
MESSAGE("Wobbuffet lowered its head!");
else
ANIMATION(ANIM_TYPE_MOVE, MOVE_SKULL_BASH, player);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player);
MESSAGE("Wobbuffet's Defense rose!");
// Attack turn
MESSAGE("Wobbuffet used Skull Bash!");
ANIMATION(ANIM_TYPE_MOVE, MOVE_SKULL_BASH, player);
HP_BAR(opponent);
}
}
SINGLE_BATTLE_TEST("Skull Bash doesn't need to charge with Power Herb")
{
GIVEN {
PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_POWER_HERB); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, MOVE_SKULL_BASH); }
} SCENE {
if (B_UPDATED_MOVE_DATA >= GEN_5) {
NOT MESSAGE("Wobbuffet lowered its head!");
MESSAGE("Wobbuffet used Skull Bash!");
} else
ANIMATION(ANIM_TYPE_MOVE, MOVE_SKULL_BASH, player);
if (B_UPDATED_MOVE_DATA < GEN_5)
MESSAGE("Wobbuffet lowered its head!");
else
ANIMATION(ANIM_TYPE_MOVE, MOVE_SKULL_BASH, player);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player);
MESSAGE("Wobbuffet's Defense rose!");
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player);
MESSAGE("Wobbuffet became fully charged due to its Power Herb!");
if (B_UPDATED_MOVE_DATA < GEN_5)
MESSAGE("Wobbuffet used Skull Bash!");
ANIMATION(ANIM_TYPE_MOVE, MOVE_SKULL_BASH, player);
HP_BAR(opponent);
}
}
SINGLE_BATTLE_TEST("Sky Attack needs a charging turn")
{
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, MOVE_SKY_ATTACK); }
TURN { SKIP_TURN(player); }
} SCENE {
// Charging turn
if (B_UPDATED_MOVE_DATA >= GEN_5) {
NONE_OF {
MESSAGE("Wobbuffet became cloaked in a harsh light!");
MESSAGE("Wobbuffet is glowing!");
}
MESSAGE("Wobbuffet used Sky Attack!");
} else
ANIMATION(ANIM_TYPE_MOVE, MOVE_SKY_ATTACK, player);
if (B_UPDATED_MOVE_DATA < GEN_4)
MESSAGE("Wobbuffet is glowing!");
else if (B_UPDATED_MOVE_DATA < GEN_5)
MESSAGE("Wobbuffet became cloaked in a harsh light!");
else
ANIMATION(ANIM_TYPE_MOVE, MOVE_SKY_ATTACK, player);
// Attack turn
MESSAGE("Wobbuffet used Sky Attack!");
ANIMATION(ANIM_TYPE_MOVE, MOVE_SKY_ATTACK, player);
HP_BAR(opponent);
}
}
SINGLE_BATTLE_TEST("Sky Attack doesn't need to charge with Power Herb")
{
GIVEN {
PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_POWER_HERB); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, MOVE_SKY_ATTACK); }
} SCENE {
if (B_UPDATED_MOVE_DATA >= GEN_5) {
NONE_OF {
MESSAGE("Wobbuffet became cloaked in a harsh light!");
MESSAGE("Wobbuffet is glowing!");
}
MESSAGE("Wobbuffet used Sky Attack!");
} else
ANIMATION(ANIM_TYPE_MOVE, MOVE_SKY_ATTACK, player);
if (B_UPDATED_MOVE_DATA < GEN_4)
MESSAGE("Wobbuffet is glowing!");
else if (B_UPDATED_MOVE_DATA < GEN_5)
MESSAGE("Wobbuffet became cloaked in a harsh light!");
else
ANIMATION(ANIM_TYPE_MOVE, MOVE_SKY_ATTACK, player);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player);
MESSAGE("Wobbuffet became fully charged due to its Power Herb!");
if (B_UPDATED_MOVE_DATA < GEN_5)
MESSAGE("Wobbuffet used Sky Attack!");
ANIMATION(ANIM_TYPE_MOVE, MOVE_SKY_ATTACK, player);
HP_BAR(opponent);
}
}
SINGLE_BATTLE_TEST("Solar Beam and Solar Blade can be used instantly in Sunlight")
{
u32 move1, move2;
PARAMETRIZE { move1 = MOVE_SPLASH; move2 = MOVE_SOLAR_BEAM; }
PARAMETRIZE { move1 = MOVE_SUNNY_DAY; move2 = MOVE_SOLAR_BEAM; }
PARAMETRIZE { move1 = MOVE_SPLASH; move2 = MOVE_SOLAR_BLADE; }
PARAMETRIZE { move1 = MOVE_SUNNY_DAY; move2 = MOVE_SOLAR_BLADE; }
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(opponent, move1); MOVE(player, move2); }
TURN { SKIP_TURN(player); }
} SCENE {
if (move1 == MOVE_SUNNY_DAY) {
NOT MESSAGE("Wobbuffet took in sunlight!");
} else {
if (move2 == MOVE_SOLAR_BEAM) {
if (B_UPDATED_MOVE_DATA >= GEN_5)
{
MESSAGE("Wobbuffet used Solar Beam!");
MESSAGE("Wobbuffet took in sunlight!");
ANIMATION(ANIM_TYPE_MOVE, move2, player);
} else {
NOT MESSAGE("Wobbuffet used Solar Beam!");
ANIMATION(ANIM_TYPE_MOVE, move2, player);
MESSAGE("Wobbuffet took in sunlight!");
}
MESSAGE("Wobbuffet used Solar Beam!");
} else {
if (B_UPDATED_MOVE_DATA >= GEN_5) {
MESSAGE("Wobbuffet used Solar Blade!");
MESSAGE("Wobbuffet took in sunlight!");
ANIMATION(ANIM_TYPE_MOVE, move2, player);
} else {
NOT MESSAGE("Wobbuffet used Solar Blade!");
ANIMATION(ANIM_TYPE_MOVE, move2, player);
MESSAGE("Wobbuffet took in sunlight!");
}
MESSAGE("Wobbuffet used Solar Blade!");
}
ANIMATION(ANIM_TYPE_MOVE, move2, player);
HP_BAR(opponent);
}
}
}
SINGLE_BATTLE_TEST("Solar Beam's power is halved in Rain", s16 damage)
{
u16 move;
PARAMETRIZE{ move = MOVE_CELEBRATE; }
PARAMETRIZE{ move = MOVE_RAIN_DANCE; }
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(opponent, move); MOVE(player, MOVE_SOLAR_BEAM); }
TURN { SKIP_TURN(player); }
} SCENE {
HP_BAR(opponent, captureDamage: &results[i].damage);
} FINALLY {
EXPECT_MUL_EQ(results[0].damage, Q_4_12(0.5), results[1].damage);
}
}
SINGLE_BATTLE_TEST("Solar Blade's power is halved in Rain", s16 damage)
{
u16 move;
PARAMETRIZE{ move = MOVE_CELEBRATE; }
PARAMETRIZE{ move = MOVE_RAIN_DANCE; }
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WYNAUT);
} WHEN {
TURN { MOVE(opponent, move); MOVE(player, MOVE_SOLAR_BLADE); }
TURN { SKIP_TURN(player); }
} SCENE {
HP_BAR(opponent, captureDamage: &results[i].damage);
} FINALLY {
EXPECT_MUL_EQ(results[0].damage, Q_4_12(0.5), results[1].damage);
}
}
SINGLE_BATTLE_TEST("Solar Beam's power is halved in a Sandstorm", s16 damage)
{
u16 move;
PARAMETRIZE{ move = MOVE_CELEBRATE; }
PARAMETRIZE{ move = MOVE_SANDSTORM; }
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_SAFETY_GOGGLES); };
} WHEN {
TURN { MOVE(opponent, move); MOVE(player, MOVE_SOLAR_BEAM); }
TURN { SKIP_TURN(player); }
} SCENE {
HP_BAR(opponent, captureDamage: &results[i].damage);
} FINALLY {
EXPECT_MUL_EQ(results[0].damage, Q_4_12(0.5), results[1].damage);
}
}
SINGLE_BATTLE_TEST("Solar Blade's power is halved in a Sandstorm", s16 damage)
{
u16 move;
PARAMETRIZE{ move = MOVE_CELEBRATE; }
PARAMETRIZE{ move = MOVE_SANDSTORM; }
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_SAFETY_GOGGLES); };
} WHEN {
TURN { MOVE(opponent, move); MOVE(player, MOVE_SOLAR_BLADE); }
TURN { SKIP_TURN(player); }
} SCENE {
HP_BAR(opponent, captureDamage: &results[i].damage);
} FINALLY {
EXPECT_MUL_EQ(results[0].damage, Q_4_12(0.5), results[1].damage);
}
}
SINGLE_BATTLE_TEST("Solar Beam's power is halved in Hail", s16 damage)
{
u16 move;
PARAMETRIZE{ move = MOVE_CELEBRATE; }
PARAMETRIZE{ move = MOVE_HAIL; }
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_SAFETY_GOGGLES); };
} WHEN {
TURN { MOVE(opponent, move); MOVE(player, MOVE_SOLAR_BEAM); }
TURN { SKIP_TURN(player); }
} SCENE {
HP_BAR(opponent, captureDamage: &results[i].damage);
} FINALLY {
EXPECT_MUL_EQ(results[0].damage, Q_4_12(0.5), results[1].damage);
}
}
SINGLE_BATTLE_TEST("Solar Blade's power is halved in Hail", s16 damage)
{
u16 move;
PARAMETRIZE{ move = MOVE_CELEBRATE; }
PARAMETRIZE{ move = MOVE_HAIL; }
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_SAFETY_GOGGLES); };
} WHEN {
TURN { MOVE(opponent, move); MOVE(player, MOVE_SOLAR_BLADE); }
TURN { SKIP_TURN(player); }
} SCENE {
HP_BAR(opponent, captureDamage: &results[i].damage);
} FINALLY {
EXPECT_MUL_EQ(results[0].damage, Q_4_12(0.5), results[1].damage);
}
}
SINGLE_BATTLE_TEST("Solar Beam's power is halved in Snow", s16 damage)
{
u16 move;
PARAMETRIZE{ move = MOVE_CELEBRATE; }
PARAMETRIZE{ move = MOVE_SNOWSCAPE; }
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(opponent, move); MOVE(player, MOVE_SOLAR_BEAM); }
TURN { SKIP_TURN(player); }
} SCENE {
HP_BAR(opponent, captureDamage: &results[i].damage);
} FINALLY {
EXPECT_MUL_EQ(results[0].damage, Q_4_12(0.5), results[1].damage);
}
}
SINGLE_BATTLE_TEST("Solar Blade's power is halved in Snow", s16 damage)
{
u16 move;
PARAMETRIZE{ move = MOVE_CELEBRATE; }
PARAMETRIZE{ move = MOVE_SNOWSCAPE; }
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WYNAUT);
} WHEN {
TURN { MOVE(opponent, move); MOVE(player, MOVE_SOLAR_BLADE); }
TURN { SKIP_TURN(player); }
} SCENE {
HP_BAR(opponent, captureDamage: &results[i].damage);
} FINALLY {
EXPECT_MUL_EQ(results[0].damage, Q_4_12(0.5), results[1].damage);
}
}
SINGLE_BATTLE_TEST("Electro Shot needs a charging Turn")
{
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, MOVE_ELECTRO_SHOT); }
TURN { SKIP_TURN(player); }
} SCENE {
// Charging turn
MESSAGE("Wobbuffet used Electro Shot!");
ANIMATION(ANIM_TYPE_MOVE, MOVE_ELECTRO_SHOT, player);
MESSAGE("Wobbuffet absorbed electricity!");
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player);
MESSAGE("Wobbuffet's Sp. Atk rose!");
// Attack turn
MESSAGE("Wobbuffet used Electro Shot!");
HP_BAR(opponent);
}
}
SINGLE_BATTLE_TEST("Electro Shot doesn't need to charge when it's raining")
{
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(opponent, MOVE_RAIN_DANCE); MOVE(player, MOVE_ELECTRO_SHOT); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_RAIN_DANCE, opponent);
MESSAGE("Wobbuffet used Electro Shot!");
ANIMATION(ANIM_TYPE_MOVE, MOVE_ELECTRO_SHOT, player);
MESSAGE("Wobbuffet absorbed electricity!");
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player);
MESSAGE("Wobbuffet's Sp. Atk rose!");
NONE_OF {
MESSAGE("Wobbuffet used Electro Shot!");
}
HP_BAR(opponent);
}
}
SINGLE_BATTLE_TEST("Electro Shot doesn't need to charge with Power Herb")
{
GIVEN {
PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_POWER_HERB); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, MOVE_ELECTRO_SHOT); }
} SCENE {
MESSAGE("Wobbuffet used Electro Shot!");
ANIMATION(ANIM_TYPE_MOVE, MOVE_ELECTRO_SHOT, player);
MESSAGE("Wobbuffet absorbed electricity!");
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player);
MESSAGE("Wobbuffet's Sp. Atk rose!");
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player);
MESSAGE("Wobbuffet became fully charged due to its Power Herb!");
NONE_OF {
MESSAGE("Wobbuffet used Electro Shot!");
}
HP_BAR(opponent);
}
}