Multihit refactor and Parental Bond

Port multihit system from the CFRU, implement Parental Bond, refactor certain moves as required and implement all remaining multi hit moves except Dragon Darts.
This commit is contained in:
BuffelSaft 2021-09-23 14:31:21 +12:00
parent a10a8714fc
commit 2f03ac31b9
11 changed files with 590 additions and 333 deletions

View file

@ -48,7 +48,7 @@ gBattleScriptsForMoveEffects::
.4byte BattleScript_EffectBide @ EFFECT_BIDE
.4byte BattleScript_EffectRampage @ EFFECT_RAMPAGE
.4byte BattleScript_EffectRoar @ EFFECT_ROAR
.4byte BattleScript_EffectMultiHit @ EFFECT_MULTI_HIT
.4byte BattleScript_EffectHit @ EFFECT_MULTI_HIT
.4byte BattleScript_EffectConversion @ EFFECT_CONVERSION
.4byte BattleScript_EffectFlinchHit @ EFFECT_FLINCH_HIT
.4byte BattleScript_EffectRestoreHp @ EFFECT_RESTORE_HP
@ -63,11 +63,11 @@ gBattleScriptsForMoveEffects::
.4byte BattleScript_EffectDragonRage @ EFFECT_DRAGON_RAGE
.4byte BattleScript_EffectTrap @ EFFECT_TRAP
.4byte BattleScript_EffectHealBlock @ EFFECT_HEAL_BLOCK
.4byte BattleScript_EffectDoubleHit @ EFFECT_DOUBLE_HIT
.4byte BattleScript_EffectHit @ EFFECT_DOUBLE_HIT
.4byte BattleScript_EffectRecoilIfMiss @ EFFECT_RECOIL_IF_MISS
.4byte BattleScript_EffectMist @ EFFECT_MIST
.4byte BattleScript_EffectFocusEnergy @ EFFECT_FOCUS_ENERGY
.4byte BattleScript_EffectRecoil25 @ EFFECT_RECOIL_25
.4byte BattleScript_EffectHit @ EFFECT_RECOIL_25
.4byte BattleScript_EffectConfuse @ EFFECT_CONFUSE
.4byte BattleScript_EffectAttackUp2 @ EFFECT_ATTACK_UP_2
.4byte BattleScript_EffectDefenseUp2 @ EFFECT_DEFENSE_UP_2
@ -217,7 +217,7 @@ gBattleScriptsForMoveEffects::
.4byte BattleScript_EffectSnatch @ EFFECT_SNATCH
.4byte BattleScript_EffectHit @ EFFECT_LOW_KICK
.4byte BattleScript_EffectSecretPower @ EFFECT_SECRET_POWER
.4byte BattleScript_EffectRecoil33 @ EFFECT_RECOIL_33
.4byte BattleScript_EffectHit @ EFFECT_RECOIL_33
.4byte BattleScript_EffectTeeterDance @ EFFECT_TEETER_DANCE
.4byte BattleScript_EffectHitEscape @ EFFECT_HIT_ESCAPE
.4byte BattleScript_EffectMudSport @ EFFECT_MUD_SPORT
@ -306,9 +306,9 @@ gBattleScriptsForMoveEffects::
.4byte BattleScript_EffectGrowth @ EFFECT_GROWTH
.4byte BattleScript_EffectCloseCombat @ EFFECT_CLOSE_COMBAT
.4byte BattleScript_EffectLastResort @ EFFECT_LAST_RESORT
.4byte BattleScript_EffectRecoil33WithStatus @ EFFECT_RECOIL_33_STATUS
.4byte BattleScript_EffectHit @ EFFECT_RECOIL_33_STATUS
.4byte BattleScript_EffectFlinchWithStatus @ EFFECT_FLINCH_STATUS
.4byte BattleScript_EffectRecoil50 @ EFFECT_RECOIL_50
.4byte BattleScript_EffectHit @ EFFECT_RECOIL_50
.4byte BattleScript_EffectShellSmash @ EFFECT_SHELL_SMASH
.4byte BattleScript_EffectShiftGear @ EFFECT_SHIFT_GEAR
.4byte BattleScript_EffectDefenseUp3 @ EFFECT_DEFENSE_UP_3
@ -407,9 +407,11 @@ BattleScript_EffectBurnUp:
attackstring
ppreduce
jumpiftype BS_ATTACKER, TYPE_FIRE, BattleScript_BurnUpWorks
goto BattleScript_ButItFailed
goto BattleScript_MoveEnd
BattleScript_BurnUpWorks:
accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE
setmoveeffect MOVE_EFFECT_BURN_UP
seteffectwithchance
critcalc
damagecalc
adjustdamage
@ -424,11 +426,14 @@ BattleScript_BurnUpWorks:
waitmessage B_WAIT_TIME_LONG
resultmessage
waitmessage B_WAIT_TIME_LONG
tryfaintmon BS_TARGET, FALSE, NULL
goto BattleScript_MoveEnd
BattleScript_BurnUpRemoveType::
losetype BS_ATTACKER, TYPE_FIRE
printstring STRINGID_ATTACKERLOSTFIRETYPE
waitmessage B_WAIT_TIME_LONG
tryfaintmon BS_TARGET, FALSE, NULL
goto BattleScript_MoveEnd
return
BattleScript_EffectPurify:
attackcanceler
@ -2593,6 +2598,8 @@ BattleScript_MultiHitPrintStrings::
copyarray gBattleTextBuff1, sMULTIHIT_STRING, 6
printstring STRINGID_HITXTIMES
waitmessage B_WAIT_TIME_LONG
return
BattleScript_MultiHitEnd::
seteffectwithchance
tryfaintmon BS_TARGET, FALSE, NULL
@ -3497,57 +3504,16 @@ BattleScript_PartyHealEnd::
BattleScript_EffectTripleKick::
attackcanceler
accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE
attackstring
ppreduce
sethword sTRIPLE_KICK_POWER, 0
initmultihitstring
setmultihit 3
BattleScript_TripleKickLoop::
jumpifhasnohp BS_ATTACKER, BattleScript_TripleKickEnd
jumpifhasnohp BS_TARGET, BattleScript_TripleKickNoMoreHits
jumpifhalfword CMP_EQUAL, gChosenMove, MOVE_SLEEP_TALK, BattleScript_DoTripleKickAttack
jumpifstatus BS_ATTACKER, STATUS1_SLEEP, BattleScript_TripleKickNoMoreHits
BattleScript_DoTripleKickAttack::
accuracycheck BattleScript_TripleKickNoMoreHits, ACC_CURR_MOVE
movevaluescleanup
addbyte sTRIPLE_KICK_POWER, 10
addbyte sMULTIHIT_STRING + 4, 1
critcalc
damagecalc
adjustdamage
jumpifmovehadnoeffect BattleScript_TripleKickNoMoreHits
attackanimation
waitanimation
effectivenesssound
hitanimation BS_TARGET
waitstate
healthbarupdate BS_TARGET
datahpupdate BS_TARGET
critmessage
waitmessage B_WAIT_TIME_LONG
printstring STRINGID_EMPTYSTRING3
waitmessage 1
moveendto MOVEEND_NEXT_TARGET
jumpifbyte CMP_COMMON_BITS, gMoveResultFlags, MOVE_RESULT_FOE_ENDURED, BattleScript_TripleKickPrintStrings
decrementmultihit BattleScript_TripleKickLoop
goto BattleScript_TripleKickPrintStrings
BattleScript_TripleKickNoMoreHits::
pause B_WAIT_TIME_SHORT
jumpifbyte CMP_EQUAL, sMULTIHIT_STRING + 4, 0, BattleScript_TripleKickPrintStrings
bichalfword gMoveResultFlags, MOVE_RESULT_MISSED
BattleScript_TripleKickPrintStrings::
resultmessage
waitmessage B_WAIT_TIME_LONG
jumpifbyte CMP_EQUAL, sMULTIHIT_STRING + 4, 0, BattleScript_TripleKickEnd
jumpifbyte CMP_COMMON_BITS, gMoveResultFlags, MOVE_RESULT_DOESNT_AFFECT_FOE, BattleScript_TripleKickEnd
copyarray gBattleTextBuff1, sMULTIHIT_STRING, 6
printstring STRINGID_HITXTIMES
waitmessage B_WAIT_TIME_LONG
BattleScript_TripleKickEnd::
seteffectwithchance
tryfaintmon BS_TARGET, FALSE, NULL
moveendfrom MOVEEND_UPDATE_LAST_MOVES
end
jumpifmove MOVE_TRIPLE_AXEL BS_TripleAxel
addbyte sTRIPLE_KICK_POWER 10
goto BattleScript_HitFromAtkString
BS_TripleAxel:
addbyte sTRIPLE_KICK_POWER 20
goto BattleScript_HitFromAtkString
BattleScript_EffectThief::
setmoveeffect MOVE_EFFECT_STEAL_ITEM
@ -4064,6 +4030,7 @@ BattleScript_EffectTeleport:
setoutcomeonteleport BS_ATTACKER
goto BattleScript_MoveEnd
.if B_BEAT_UP_DMG < GEN_5
BattleScript_EffectBeatUp::
attackcanceler
accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE
@ -4096,6 +4063,13 @@ BattleScript_BeatUpAttack::
goto BattleScript_BeatUpLoop
BattleScript_BeatUpEnd::
end
.else
BattleScript_EffectBeatUp::
attackcanceler
accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE
addbyte gBattleCommunication, 1
goto BattleScript_HitFromAtkString
.endif
BattleScript_EffectSemiInvulnerable::
jumpifstatus2 BS_ATTACKER, STATUS2_MULTIPLETURNS, BattleScript_SecondTurnSemiInvulnerable
@ -4717,24 +4691,6 @@ BattleScript_EffectSecretPower::
getsecretpowereffect
goto BattleScript_EffectHit
BattleScript_EffectRecoil25:
setmoveeffect MOVE_EFFECT_RECOIL_25 | MOVE_EFFECT_AFFECTS_USER | MOVE_EFFECT_CERTAIN
jumpifnotmove MOVE_STRUGGLE, BattleScript_EffectHit
incrementgamestat GAME_STAT_USED_STRUGGLE
goto BattleScript_EffectHit
BattleScript_EffectRecoil33::
setmoveeffect MOVE_EFFECT_RECOIL_33 | MOVE_EFFECT_AFFECTS_USER | MOVE_EFFECT_CERTAIN
goto BattleScript_EffectHit
BattleScript_EffectRecoil33WithStatus:
setmoveeffect MOVE_EFFECT_RECOIL_33_STATUS | MOVE_EFFECT_AFFECTS_USER | MOVE_EFFECT_CERTAIN
goto BattleScript_EffectHit
BattleScript_EffectRecoil50:
setmoveeffect MOVE_EFFECT_RECOIL_50 | MOVE_EFFECT_AFFECTS_USER | MOVE_EFFECT_CERTAIN
goto BattleScript_EffectHit
BattleScript_EffectTeeterDance::
attackcanceler
attackstring
@ -6657,7 +6613,6 @@ BattleScript_MoveEffectConfusion::
BattleScript_MoveEffectRecoilWithStatus::
argumentstatuseffect
copyword gBattleMoveDamage, sSAVED_DMG
BattleScript_MoveEffectRecoil::
jumpifmove MOVE_STRUGGLE, BattleScript_DoRecoil
jumpifability BS_ATTACKER, ABILITY_ROCK_HEAD, BattleScript_RecoilEnd
@ -7600,6 +7555,7 @@ BattleScript_BerryCureSlpRet::
BattleScript_GemActivates::
playanimation BS_ATTACKER, B_ANIM_HELD_ITEM_EFFECT, NULL
waitanimation
setlastuseditem BS_ATTACKER
printstring STRINGID_GEMACTIVATES
waitmessage B_WAIT_TIME_LONG
removeitem BS_ATTACKER
@ -7608,6 +7564,7 @@ BattleScript_GemActivates::
BattleScript_BerryReduceDmg::
playanimation BS_TARGET, B_ANIM_HELD_ITEM_EFFECT, NULL
waitanimation
setlastuseditem BS_TARGET
printstring STRINGID_TARGETATEITEM
waitmessage B_WAIT_TIME_LONG
removeitem BS_TARGET

View file

@ -162,15 +162,20 @@ struct SpecialStatus
u8 traced:1;
u8 ppNotAffectedByPressure:1;
u8 flag40:1;
u8 focusBanded:1;
// end of byte
u8 focusBanded:1;
u8 focusSashed:1;
u8 sturdied:1;
u8 stormDrainRedirected:1;
u8 switchInAbilityDone:1;
u8 switchInItemDone:1;
u8 switchInItemDone:1;
// end of byte, two bits unused
u8 instructedChosenTarget:3;
u8 berryReduced:1;
u8 gemBoost:1;
u8 parentalBondOn:2;
u8 multiHitOn:1;
// end of byte
u8 gemParam;
u8 damagedMons:4; // Mons that have been damaged directly by using a move, includes substitute.
u8 dancerUsedMove:1;

View file

@ -384,5 +384,7 @@ extern const u8 BattleScript_MentalHerbCureEnd2[];
extern const u8 BattleScript_TerrainPreventsEnd2[];
extern const u8 BattleScript_MistyTerrainPrevents[];
extern const u8 BattleScript_ElectricTerrainPrevents[];
extern const u8 BattleScript_MultiHitPrintStrings[];
extern const u8 BattleScript_BurnUpRemoveType[];
#endif // GUARD_BATTLE_SCRIPTS_H

View file

@ -152,6 +152,7 @@ bool32 CompareStat(u8 battlerId, u8 statId, u8 cmpTo, u8 cmpKind);
bool32 TryRoomService(u8 battlerId);
void BufferStatChange(u8 battlerId, u8 statId, u8 stringId);
void DoBurmyFormChange(u32 monId);
bool8 IsMoveAffectedByParentalBond(u16 move, u8 battlerId);
// ability checks
bool32 IsRolePlayBannedAbilityAtk(u16 ability);
@ -170,4 +171,7 @@ bool32 CanBeFrozen(u8 battlerId);
bool32 CanBeConfused(u8 battlerId);
bool32 IsBattlerTerrainAffected(u8 battlerId, u32 terrainFlag);
// Move checks
bool8 IsTwoStrikesMove(u16 move);
#endif // GUARD_BATTLE_UTIL_H

View file

@ -291,63 +291,60 @@
#define MOVE_EFFECT_PAYDAY 0xB
#define MOVE_EFFECT_CHARGING 0xC
#define MOVE_EFFECT_WRAP 0xD
#define MOVE_EFFECT_RECOIL_25 0xE
#define MOVE_EFFECT_ATK_PLUS_1 0xF
#define MOVE_EFFECT_DEF_PLUS_1 0x10
#define MOVE_EFFECT_SPD_PLUS_1 0x11
#define MOVE_EFFECT_SP_ATK_PLUS_1 0x12
#define MOVE_EFFECT_SP_DEF_PLUS_1 0x13
#define MOVE_EFFECT_ACC_PLUS_1 0x14
#define MOVE_EFFECT_EVS_PLUS_1 0x15
#define MOVE_EFFECT_ATK_MINUS_1 0x16
#define MOVE_EFFECT_DEF_MINUS_1 0x17
#define MOVE_EFFECT_SPD_MINUS_1 0x18
#define MOVE_EFFECT_SP_ATK_MINUS_1 0x19
#define MOVE_EFFECT_SP_DEF_MINUS_1 0x1A
#define MOVE_EFFECT_ACC_MINUS_1 0x1B
#define MOVE_EFFECT_EVS_MINUS_1 0x1C
#define MOVE_EFFECT_RECHARGE 0x1D
#define MOVE_EFFECT_RAGE 0x1E
#define MOVE_EFFECT_STEAL_ITEM 0x1F
#define MOVE_EFFECT_PREVENT_ESCAPE 0x20
#define MOVE_EFFECT_NIGHTMARE 0x21
#define MOVE_EFFECT_ALL_STATS_UP 0x22
#define MOVE_EFFECT_RAPIDSPIN 0x23
#define MOVE_EFFECT_REMOVE_STATUS 0x24
#define MOVE_EFFECT_ATK_DEF_DOWN 0x25
#define MOVE_EFFECT_RECOIL_33 0x26
#define MOVE_EFFECT_ATK_PLUS_2 0x27
#define MOVE_EFFECT_DEF_PLUS_2 0x28
#define MOVE_EFFECT_SPD_PLUS_2 0x29
#define MOVE_EFFECT_SP_ATK_PLUS_2 0x2A
#define MOVE_EFFECT_SP_DEF_PLUS_2 0x2B
#define MOVE_EFFECT_ACC_PLUS_2 0x2C
#define MOVE_EFFECT_EVS_PLUS_2 0x2D
#define MOVE_EFFECT_ATK_MINUS_2 0x2E
#define MOVE_EFFECT_DEF_MINUS_2 0x2F
#define MOVE_EFFECT_SPD_MINUS_2 0x30
#define MOVE_EFFECT_SP_ATK_MINUS_2 0x31
#define MOVE_EFFECT_SP_DEF_MINUS_2 0x32
#define MOVE_EFFECT_ACC_MINUS_2 0x33
#define MOVE_EFFECT_EVS_MINUS_2 0x34
#define MOVE_EFFECT_THRASH 0x35
#define MOVE_EFFECT_KNOCK_OFF 0x36
#define MOVE_EFFECT_DEF_SPDEF_DOWN 0x37
#define MOVE_EFFECT_RECOIL_33_STATUS 0x38
#define MOVE_EFFECT_RECOIL_50 0x39
#define MOVE_EFFECT_CLEAR_SMOG 0x3A
#define MOVE_EFFECT_SP_ATK_TWO_DOWN 0x3B
#define MOVE_EFFECT_SMACK_DOWN 0x3C
#define MOVE_EFFECT_FLAME_BURST 0x3D
#define MOVE_EFFECT_FEINT 0x3E
#define MOVE_EFFECT_SPECTRAL_THIEF 0x3F
#define MOVE_EFFECT_V_CREATE 0x40
#define MOVE_EFFECT_HAPPY_HOUR 0x41
#define MOVE_EFFECT_CORE_ENFORCER 0x42
#define MOVE_EFFECT_THROAT_CHOP 0x43
#define MOVE_EFFECT_INCINERATE 0x44
#define MOVE_EFFECT_BUG_BITE 0x45
#define NUM_MOVE_EFFECTS 0x46
#define MOVE_EFFECT_ATK_PLUS_1 0xE
#define MOVE_EFFECT_DEF_PLUS_1 0xF
#define MOVE_EFFECT_SPD_PLUS_1 0x10
#define MOVE_EFFECT_SP_ATK_PLUS_1 0x11
#define MOVE_EFFECT_SP_DEF_PLUS_1 0x12
#define MOVE_EFFECT_ACC_PLUS_1 0x13
#define MOVE_EFFECT_EVS_PLUS_1 0x14
#define MOVE_EFFECT_ATK_MINUS_1 0x15
#define MOVE_EFFECT_DEF_MINUS_1 0x16
#define MOVE_EFFECT_SPD_MINUS_1 0x17
#define MOVE_EFFECT_SP_ATK_MINUS_1 0x18
#define MOVE_EFFECT_SP_DEF_MINUS_1 0x19
#define MOVE_EFFECT_ACC_MINUS_1 0x1A
#define MOVE_EFFECT_EVS_MINUS_1 0x1B
#define MOVE_EFFECT_RECHARGE 0x1C
#define MOVE_EFFECT_RAGE 0x1D
#define MOVE_EFFECT_STEAL_ITEM 0x1E
#define MOVE_EFFECT_PREVENT_ESCAPE 0x1F
#define MOVE_EFFECT_NIGHTMARE 0x20
#define MOVE_EFFECT_ALL_STATS_UP 0x21
#define MOVE_EFFECT_RAPIDSPIN 0x22
#define MOVE_EFFECT_REMOVE_STATUS 0x23
#define MOVE_EFFECT_ATK_DEF_DOWN 0x24
#define MOVE_EFFECT_ATK_PLUS_2 0x25
#define MOVE_EFFECT_DEF_PLUS_2 0x26
#define MOVE_EFFECT_SPD_PLUS_2 0x27
#define MOVE_EFFECT_SP_ATK_PLUS_2 0x28
#define MOVE_EFFECT_SP_DEF_PLUS_2 0x29
#define MOVE_EFFECT_ACC_PLUS_2 0x2A
#define MOVE_EFFECT_EVS_PLUS_2 0x2B
#define MOVE_EFFECT_ATK_MINUS_2 0x2C
#define MOVE_EFFECT_DEF_MINUS_2 0x2D
#define MOVE_EFFECT_SPD_MINUS_2 0x2E
#define MOVE_EFFECT_SP_ATK_MINUS_2 0x2F
#define MOVE_EFFECT_SP_DEF_MINUS_2 0x30
#define MOVE_EFFECT_ACC_MINUS_2 0x31
#define MOVE_EFFECT_EVS_MINUS_2 0x32
#define MOVE_EFFECT_THRASH 0x33
#define MOVE_EFFECT_KNOCK_OFF 0x34
#define MOVE_EFFECT_DEF_SPDEF_DOWN 0x35
#define MOVE_EFFECT_CLEAR_SMOG 0x36
#define MOVE_EFFECT_SP_ATK_TWO_DOWN 0x37
#define MOVE_EFFECT_SMACK_DOWN 0x38
#define MOVE_EFFECT_FLAME_BURST 0x39
#define MOVE_EFFECT_FEINT 0x3A
#define MOVE_EFFECT_SPECTRAL_THIEF 0x3B
#define MOVE_EFFECT_V_CREATE 0x3C
#define MOVE_EFFECT_HAPPY_HOUR 0x3D
#define MOVE_EFFECT_CORE_ENFORCER 0x3E
#define MOVE_EFFECT_THROAT_CHOP 0x3F
#define MOVE_EFFECT_INCINERATE 0x40
#define MOVE_EFFECT_BUG_BITE 0x41
#define MOVE_EFFECT_BURN_UP 0x42
#define NUM_MOVE_EFFECTS 0x43
#define MOVE_EFFECT_AFFECTS_USER 0x4000
#define MOVE_EFFECT_CERTAIN 0x8000

View file

@ -96,6 +96,7 @@
#define B_RECOIL_IF_MISS_DMG GEN_7 // In Gen5+, Jump Kick and High Jump Kick will always do half of the user's max HP when missing.
#define B_PSYWAVE_DMG GEN_7 // Psywave's damage formula. See Cmd_psywavedamageeffect.
#define B_BADGE_BOOST GEN_7 // In Gen4+, Gym Badges no longer boost a Pokémon's stats.
#define B_BEAT_UP_DMG GEN_8 // In Gen5+, Beat Up uses a different formula to calculate the damage of each hit, and deals Dark-type damage.
// Move data settings
#define B_UPDATED_MOVE_DATA GEN_8 // Updates move data in gBattleMoves, including Power, Accuracy, PP, stat changes, targets, chances of secondary effects, etc.
@ -128,6 +129,7 @@
#define B_FLASH_FIRE_FROZEN GEN_7 // In Gen5+, Flash Fire can trigger even when frozen, when it couldn't before.
#define B_SYNCHRONIZE_NATURE GEN_8 // In Gen8, if the Pokémon with Synchronize is leading the party, it's 100% guaranteed that wild Pokémon will have the same ability, as opposed to 50% previously.
#define B_UPDATED_INTIMIDATE GEN_8 // In Gen8, Intimidate doesn't work on opponents with the Inner Focus, Scrappy, Own Tempo or Oblivious abilities.
#define B_PARENTAL_BOND_DAMAGE GEN_8 // In Gen7+, Parental Bond's second hit does 25% of the initial hits damage. Before, it did 50%.
// Item settings
#define B_HP_BERRIES GEN_7 // In Gen4+, berries which restore hp activate immediately after HP drops to half. In Gen3, the effect occurs at the end of the turn.

View file

@ -217,36 +217,39 @@
#define PARTY_SCREEN_OPTIONAL (1 << 7) // Flag for first argument to openpartyscreen
// cases for Cmd_moveend
#define MOVEEND_PROTECT_LIKE_EFFECT 0
#define MOVEEND_RAGE 1
#define MOVEEND_DEFROST 2
#define MOVEEND_SUM_DAMAGE 0
#define MOVEEND_PROTECT_LIKE_EFFECT 1
#define MOVEEND_RAGE 2
#define MOVEEND_SYNCHRONIZE_TARGET 3
#define MOVEEND_ABILITIES 4
#define MOVEEND_ABILITIES_ATTACKER 5
#define MOVEEND_STATUS_IMMUNITY_ABILITIES 6
#define MOVEEND_SYNCHRONIZE_ATTACKER 7
#define MOVEEND_CHOICE_MOVE 8
#define MOVEEND_CHANGED_ITEMS 9
#define MOVEEND_ATTACKER_INVISIBLE 10
#define MOVEEND_ATTACKER_VISIBLE 11
#define MOVEEND_TARGET_VISIBLE 12
#define MOVEEND_ITEM_EFFECTS_TARGET 13
#define MOVEEND_MOVE_EFFECTS2 14
#define MOVEEND_ITEM_EFFECTS_ALL 15
#define MOVEEND_KINGSROCK 16 // These item effects will occur each strike of a multi-hit move
#define MOVEEND_SUBSTITUTE 17
#define MOVEEND_UPDATE_LAST_MOVES 18
#define MOVEEND_MIRROR_MOVE 19
#define MOVEEND_NEXT_TARGET 20 // Everything up until here is handled for each strike of a multi-hit move
#define MOVEEND_EJECT_BUTTON 21
#define MOVEEND_RED_CARD 22
#define MOVEEND_EJECT_PACK 23
#define MOVEEND_LIFEORB_SHELLBELL 24 // Includes shell bell, throat spray, etc
#define MOVEEND_PICKPOCKET 25
#define MOVEEND_DANCER 26
#define MOVEEND_EMERGENCY_EXIT 27
#define MOVEEND_CLEAR_BITS 28
#define MOVEEND_COUNT 29
#define MOVEEND_ATTACKER_INVISIBLE 9
#define MOVEEND_ATTACKER_VISIBLE 10
#define MOVEEND_TARGET_VISIBLE 11
#define MOVEEND_ITEM_EFFECTS_TARGET 12
#define MOVEEND_ITEM_EFFECTS_ALL 13
#define MOVEEND_KINGSROCK 14
#define MOVEEND_SUBSTITUTE 15
#define MOVEEND_UPDATE_LAST_MOVES 16
#define MOVEEND_MIRROR_MOVE 17
#define MOVEEND_NEXT_TARGET 18 // Everything up until here is handled for each strike of a multi-hit move
#define MOVEEND_MULTIHIT_MOVE 19
#define MOVEEND_MOVE_EFFECTS2 20
#define MOVEEND_RECOIL 21
#define MOVEEND_EJECT_BUTTON 22
#define MOVEEND_RED_CARD 23
#define MOVEEND_EJECT_PACK 24
#define MOVEEND_LIFEORB_SHELLBELL 25 // Includes shell bell, throat spray, etc
#define MOVEEND_CHANGED_ITEMS 26
#define MOVEEND_DEFROST 27
#define MOVEEND_PICKPOCKET 28
#define MOVEEND_DANCER 29
#define MOVEEND_EMERGENCY_EXIT 30
#define MOVEEND_CLEAR_BITS 31
#define MOVEEND_COUNT 32
// switch cases
#define B_SWITCH_NORMAL 0

View file

@ -2894,6 +2894,7 @@ static void BattleStartClearSetData(void)
gBattleScripting.monCaught = FALSE;
gMultiHitCounter = 0;
gBattleScripting.savedDmg = 0;
gBattleOutcome = 0;
gBattleControllerExecFlags = 0;
gPaydayMoney = 0;
@ -4563,6 +4564,8 @@ static void TurnValuesCleanUp(bool8 var0)
if (gDisableStructs[gActiveBattler].substituteHP == 0)
gBattleMons[gActiveBattler].status2 &= ~(STATUS2_SUBSTITUTE);
gSpecialStatuses[gActiveBattler].parentalBondOn = 0;
}
gSideStatuses[0] &= ~(SIDE_STATUS_QUICK_GUARD | SIDE_STATUS_WIDE_GUARD | SIDE_STATUS_CRAFTY_SHIELD | SIDE_STATUS_MAT_BLOCK);

View file

@ -862,8 +862,6 @@ static const u8* const sMoveEffectBS_Ptrs[] =
[MOVE_EFFECT_UPROAR] = BattleScript_MoveEffectUproar,
[MOVE_EFFECT_PAYDAY] = BattleScript_MoveEffectPayDay,
[MOVE_EFFECT_WRAP] = BattleScript_MoveEffectWrap,
[MOVE_EFFECT_RECOIL_25] = BattleScript_MoveEffectRecoil,
[MOVE_EFFECT_RECOIL_33] = BattleScript_MoveEffectRecoil,
};
static const struct WindowTemplate sUnusedWinTemplate = {0, 1, 3, 7, 0xF, 0x1F, 0x3F};
@ -908,6 +906,7 @@ static const u16 sProtectSuccessRates[] = {USHRT_MAX, USHRT_MAX / 2, USHRT_MAX /
#define FORBIDDEN_ASSIST 0x4
#define FORBIDDEN_COPYCAT 0x8
#define FORBIDDEN_SLEEP_TALK 0x10
#define FORBIDDEN_PARENTAL_BOND 0x20
#define FORBIDDEN_INSTRUCT_END 0xFFFF
@ -917,27 +916,34 @@ static const u8 sForbiddenMoves[MOVES_COUNT] =
[MOVE_STRUGGLE] = 0xFF, // Neither Struggle
[MOVE_AFTER_YOU] = FORBIDDEN_METRONOME,
[MOVE_APPLE_ACID] = FORBIDDEN_METRONOME,
[MOVE_ARM_THRUST] = FORBIDDEN_PARENTAL_BOND,
[MOVE_ASSIST] = FORBIDDEN_METRONOME | FORBIDDEN_ASSIST | FORBIDDEN_COPYCAT | FORBIDDEN_SLEEP_TALK,
[MOVE_ASTRAL_BARRAGE] = FORBIDDEN_METRONOME,
[MOVE_AURA_WHEEL] = FORBIDDEN_METRONOME,
[MOVE_BADDY_BAD] = FORBIDDEN_METRONOME,
[MOVE_BANEFUL_BUNKER] = FORBIDDEN_METRONOME | FORBIDDEN_ASSIST | FORBIDDEN_COPYCAT,
[MOVE_BARRAGE] = FORBIDDEN_PARENTAL_BOND,
[MOVE_BEAK_BLAST] = FORBIDDEN_METRONOME | FORBIDDEN_ASSIST | FORBIDDEN_COPYCAT | FORBIDDEN_SLEEP_TALK,
[MOVE_BEAT_UP] = FORBIDDEN_PARENTAL_BOND,
[MOVE_BEHEMOTH_BASH] = FORBIDDEN_METRONOME | FORBIDDEN_COPYCAT,
[MOVE_BEHEMOTH_BLADE] = FORBIDDEN_METRONOME | FORBIDDEN_COPYCAT,
[MOVE_BELCH] = FORBIDDEN_METRONOME | FORBIDDEN_ASSIST | FORBIDDEN_COPYCAT | FORBIDDEN_SLEEP_TALK,
[MOVE_BESTOW] = FORBIDDEN_METRONOME | FORBIDDEN_ASSIST | FORBIDDEN_COPYCAT,
[MOVE_BIDE] = FORBIDDEN_SLEEP_TALK,
[MOVE_BODY_PRESS] = FORBIDDEN_METRONOME,
[MOVE_BOUNCE] = FORBIDDEN_ASSIST | FORBIDDEN_SLEEP_TALK,
[MOVE_BONE_RUSH] = FORBIDDEN_PARENTAL_BOND,
[MOVE_BONEMERANG] = FORBIDDEN_PARENTAL_BOND,
[MOVE_BOUNCE] = FORBIDDEN_ASSIST | FORBIDDEN_SLEEP_TALK | FORBIDDEN_PARENTAL_BOND,
[MOVE_BOUNCY_BUBBLE] = FORBIDDEN_METRONOME,
[MOVE_BRANCH_POKE] = FORBIDDEN_METRONOME,
[MOVE_BREAKING_SWIPE] = FORBIDDEN_METRONOME,
[MOVE_BULLET_SEED] = FORBIDDEN_PARENTAL_BOND,
[MOVE_BUZZY_BUZZ] = FORBIDDEN_METRONOME,
[MOVE_CELEBRATE] = FORBIDDEN_METRONOME | FORBIDDEN_ASSIST | FORBIDDEN_COPYCAT | FORBIDDEN_SLEEP_TALK,
[MOVE_CHATTER] = FORBIDDEN_METRONOME | FORBIDDEN_ASSIST | FORBIDDEN_COPYCAT | FORBIDDEN_MIMIC | FORBIDDEN_SLEEP_TALK,
[MOVE_CIRCLE_THROW] = FORBIDDEN_ASSIST | FORBIDDEN_COPYCAT,
[MOVE_CLANGOROUS_SOUL] = FORBIDDEN_METRONOME,
[MOVE_COMET_PUNCH] = FORBIDDEN_PARENTAL_BOND,
[MOVE_COPYCAT] = FORBIDDEN_METRONOME | FORBIDDEN_ASSIST | FORBIDDEN_COPYCAT | FORBIDDEN_SLEEP_TALK,
[MOVE_COUNTER] = FORBIDDEN_METRONOME | FORBIDDEN_ASSIST | FORBIDDEN_COPYCAT,
[MOVE_COVET] = FORBIDDEN_METRONOME | FORBIDDEN_ASSIST | FORBIDDEN_COPYCAT,
@ -946,36 +952,54 @@ static const u8 sForbiddenMoves[MOVES_COUNT] =
[MOVE_DESTINY_BOND] = FORBIDDEN_METRONOME | FORBIDDEN_ASSIST | FORBIDDEN_COPYCAT,
[MOVE_DETECT] = FORBIDDEN_METRONOME | FORBIDDEN_ASSIST | FORBIDDEN_COPYCAT,
[MOVE_DIAMOND_STORM] = FORBIDDEN_METRONOME,
[MOVE_DIG] = FORBIDDEN_ASSIST | FORBIDDEN_SLEEP_TALK,
[MOVE_DIVE] = FORBIDDEN_ASSIST | FORBIDDEN_SLEEP_TALK,
[MOVE_DOUBLE_IRON_BASH] = FORBIDDEN_METRONOME,
[MOVE_DIG] = FORBIDDEN_ASSIST | FORBIDDEN_SLEEP_TALK | FORBIDDEN_PARENTAL_BOND,
[MOVE_DIVE] = FORBIDDEN_ASSIST | FORBIDDEN_SLEEP_TALK | FORBIDDEN_PARENTAL_BOND,
[MOVE_DOUBLE_IRON_BASH] = FORBIDDEN_METRONOME | FORBIDDEN_PARENTAL_BOND,
[MOVE_DOUBLE_HIT] = FORBIDDEN_PARENTAL_BOND,
[MOVE_DOUBLE_KICK] = FORBIDDEN_PARENTAL_BOND,
[MOVE_DOUBLE_SLAP] = FORBIDDEN_PARENTAL_BOND,
[MOVE_DRAGON_ASCENT] = FORBIDDEN_METRONOME,
[MOVE_DRAGON_ENERGY] = FORBIDDEN_METRONOME,
[MOVE_DRAGON_DARTS] = FORBIDDEN_PARENTAL_BOND,
[MOVE_DRAGON_TAIL] = FORBIDDEN_ASSIST | FORBIDDEN_COPYCAT,
[MOVE_DRUM_BEATING] = FORBIDDEN_METRONOME,
[MOVE_DUAL_CHOP] = FORBIDDEN_PARENTAL_BOND,
[MOVE_DUAL_WINGBEAT] = FORBIDDEN_PARENTAL_BOND,
[MOVE_DYNAMAX_CANNON] = FORBIDDEN_METRONOME | FORBIDDEN_COPYCAT | FORBIDDEN_SLEEP_TALK,
[MOVE_ENDEAVOR] = FORBIDDEN_PARENTAL_BOND,
[MOVE_ENDURE] = FORBIDDEN_METRONOME | FORBIDDEN_ASSIST | FORBIDDEN_COPYCAT,
[MOVE_ETERNABEAM] = FORBIDDEN_METRONOME,
[MOVE_EXPLOSION] = FORBIDDEN_PARENTAL_BOND,
[MOVE_FALSE_SURRENDER] = FORBIDDEN_METRONOME,
[MOVE_FEINT] = FORBIDDEN_METRONOME | FORBIDDEN_ASSIST | FORBIDDEN_COPYCAT,
[MOVE_FIERY_WRATH] = FORBIDDEN_METRONOME,
[MOVE_FINAL_GAMBIT] = FORBIDDEN_PARENTAL_BOND,
[MOVE_FISSURE] = FORBIDDEN_PARENTAL_BOND,
[MOVE_FLEUR_CANNON] = FORBIDDEN_METRONOME,
[MOVE_FLING] = FORBIDDEN_PARENTAL_BOND,
[MOVE_FLOATY_FALL] = FORBIDDEN_METRONOME,
[MOVE_FLY] = FORBIDDEN_ASSIST | FORBIDDEN_SLEEP_TALK,
[MOVE_FLY] = FORBIDDEN_ASSIST | FORBIDDEN_SLEEP_TALK | FORBIDDEN_PARENTAL_BOND,
[MOVE_FOCUS_PUNCH] = FORBIDDEN_METRONOME | FORBIDDEN_ASSIST | FORBIDDEN_COPYCAT | FORBIDDEN_SLEEP_TALK,
[MOVE_FOLLOW_ME] = FORBIDDEN_METRONOME | FORBIDDEN_ASSIST | FORBIDDEN_COPYCAT,
[MOVE_FREEZE_SHOCK] = FORBIDDEN_METRONOME | FORBIDDEN_SLEEP_TALK,
[MOVE_FREEZE_SHOCK] = FORBIDDEN_METRONOME | FORBIDDEN_SLEEP_TALK | FORBIDDEN_PARENTAL_BOND,
[MOVE_FREEZING_GLARE] = FORBIDDEN_METRONOME,
[MOVE_FREEZY_FROST] = FORBIDDEN_METRONOME,
[MOVE_GEOMANCY] = FORBIDDEN_SLEEP_TALK,
[MOVE_FURY_ATTACK] = FORBIDDEN_PARENTAL_BOND,
[MOVE_FURY_SWIPES] = FORBIDDEN_PARENTAL_BOND,
[MOVE_GEAR_GRIND] = FORBIDDEN_PARENTAL_BOND,
[MOVE_GEOMANCY] = FORBIDDEN_SLEEP_TALK | FORBIDDEN_PARENTAL_BOND,
[MOVE_GLACIAL_LANCE] = FORBIDDEN_METRONOME,
[MOVE_GLITZY_GLOW] = FORBIDDEN_METRONOME,
[MOVE_GRAV_APPLE] = FORBIDDEN_METRONOME,
[MOVE_GUILLOTINE] = FORBIDDEN_PARENTAL_BOND,
[MOVE_HELPING_HAND] = FORBIDDEN_METRONOME | FORBIDDEN_ASSIST | FORBIDDEN_COPYCAT,
[MOVE_HOLD_HANDS] = FORBIDDEN_METRONOME | FORBIDDEN_ASSIST | FORBIDDEN_COPYCAT | FORBIDDEN_SLEEP_TALK,
[MOVE_HORN_DRILL] = FORBIDDEN_PARENTAL_BOND,
[MOVE_HYPERSPACE_FURY] = FORBIDDEN_METRONOME,
[MOVE_HYPERSPACE_HOLE] = FORBIDDEN_METRONOME,
[MOVE_ICE_BURN] = FORBIDDEN_METRONOME | FORBIDDEN_SLEEP_TALK,
[MOVE_ICE_BALL] = FORBIDDEN_PARENTAL_BOND,
[MOVE_ICE_BURN] = FORBIDDEN_METRONOME | FORBIDDEN_SLEEP_TALK | FORBIDDEN_PARENTAL_BOND,
[MOVE_ICICLE_SPEAR] = FORBIDDEN_PARENTAL_BOND,
[MOVE_INSTRUCT] = FORBIDDEN_METRONOME,
[MOVE_JUNGLE_HEALING] = FORBIDDEN_METRONOME,
[MOVE_KINGS_SHIELD] = FORBIDDEN_METRONOME | FORBIDDEN_ASSIST | FORBIDDEN_COPYCAT,
@ -984,6 +1008,7 @@ static const u8 sForbiddenMoves[MOVES_COUNT] =
[MOVE_MAT_BLOCK] = FORBIDDEN_METRONOME | FORBIDDEN_ASSIST | FORBIDDEN_COPYCAT,
[MOVE_ME_FIRST] = FORBIDDEN_METRONOME | FORBIDDEN_ASSIST | FORBIDDEN_COPYCAT | FORBIDDEN_SLEEP_TALK,
[MOVE_METEOR_ASSAULT] = FORBIDDEN_METRONOME,
[MOVE_METEOR_BEAM] = FORBIDDEN_PARENTAL_BOND,
[MOVE_METRONOME] = FORBIDDEN_METRONOME | FORBIDDEN_ASSIST | FORBIDDEN_COPYCAT | FORBIDDEN_SLEEP_TALK,
[MOVE_MIMIC] = FORBIDDEN_METRONOME | FORBIDDEN_ASSIST | FORBIDDEN_COPYCAT | FORBIDDEN_MIMIC | FORBIDDEN_SLEEP_TALK,
[MOVE_MIND_BLOWN] = FORBIDDEN_METRONOME,
@ -995,9 +1020,10 @@ static const u8 sForbiddenMoves[MOVES_COUNT] =
[MOVE_OBSTRUCT] = FORBIDDEN_METRONOME | FORBIDDEN_COPYCAT,
[MOVE_ORIGIN_PULSE] = FORBIDDEN_METRONOME,
[MOVE_OVERDRIVE] = FORBIDDEN_METRONOME,
[MOVE_PHANTOM_FORCE] = FORBIDDEN_ASSIST | FORBIDDEN_SLEEP_TALK,
[MOVE_PHANTOM_FORCE] = FORBIDDEN_ASSIST | FORBIDDEN_SLEEP_TALK | FORBIDDEN_PARENTAL_BOND,
[MOVE_PHOTON_GEYSER] = FORBIDDEN_METRONOME,
[MOVE_PIKA_PAPOW] = FORBIDDEN_METRONOME,
[MOVE_PIN_MISSILE] = FORBIDDEN_PARENTAL_BOND,
[MOVE_PLASMA_FISTS] = FORBIDDEN_METRONOME,
[MOVE_PRECIPICE_BLADES] = FORBIDDEN_METRONOME,
[MOVE_PROTECT] = FORBIDDEN_METRONOME | FORBIDDEN_ASSIST | FORBIDDEN_COPYCAT,
@ -1005,27 +1031,33 @@ static const u8 sForbiddenMoves[MOVES_COUNT] =
[MOVE_QUASH] = FORBIDDEN_METRONOME,
[MOVE_QUICK_GUARD] = FORBIDDEN_METRONOME,
[MOVE_RAGE_POWDER] = FORBIDDEN_METRONOME | FORBIDDEN_ASSIST | FORBIDDEN_COPYCAT,
[MOVE_RAZOR_WIND] = FORBIDDEN_SLEEP_TALK,
[MOVE_RAZOR_WIND] = FORBIDDEN_SLEEP_TALK | FORBIDDEN_PARENTAL_BOND,
[MOVE_RELIC_SONG] = FORBIDDEN_METRONOME,
[MOVE_ROAR] = FORBIDDEN_ASSIST | FORBIDDEN_COPYCAT,
[MOVE_ROCK_BLAST] = FORBIDDEN_PARENTAL_BOND,
[MOVE_ROLLOUT] = FORBIDDEN_PARENTAL_BOND,
[MOVE_SAPPY_SEED] = FORBIDDEN_METRONOME,
[MOVE_SCALE_SHOT] = FORBIDDEN_PARENTAL_BOND,
[MOVE_SECRET_SWORD] = FORBIDDEN_METRONOME,
[MOVE_SHADOW_FORCE] = FORBIDDEN_ASSIST | FORBIDDEN_SLEEP_TALK,
[MOVE_SELF_DESTRUCT] = FORBIDDEN_PARENTAL_BOND,
[MOVE_SHADOW_FORCE] = FORBIDDEN_ASSIST | FORBIDDEN_SLEEP_TALK | FORBIDDEN_PARENTAL_BOND,
[MOVE_SHEER_COLD] = FORBIDDEN_PARENTAL_BOND,
[MOVE_SHELL_TRAP] = FORBIDDEN_METRONOME | FORBIDDEN_ASSIST | FORBIDDEN_COPYCAT | FORBIDDEN_SLEEP_TALK,
[MOVE_SIZZLY_SLIDE] = FORBIDDEN_METRONOME,
[MOVE_SKETCH] = FORBIDDEN_METRONOME | FORBIDDEN_ASSIST | FORBIDDEN_COPYCAT | FORBIDDEN_MIMIC | FORBIDDEN_SLEEP_TALK,
[MOVE_SKULL_BASH] = FORBIDDEN_SLEEP_TALK,
[MOVE_SKY_ATTACK] = FORBIDDEN_SLEEP_TALK,
[MOVE_SKY_DROP] = FORBIDDEN_ASSIST | FORBIDDEN_SLEEP_TALK,
[MOVE_SKULL_BASH] = FORBIDDEN_SLEEP_TALK | FORBIDDEN_PARENTAL_BOND,
[MOVE_SKY_ATTACK] = FORBIDDEN_SLEEP_TALK | FORBIDDEN_PARENTAL_BOND,
[MOVE_SKY_DROP] = FORBIDDEN_ASSIST | FORBIDDEN_SLEEP_TALK | FORBIDDEN_PARENTAL_BOND,
[MOVE_SLEEP_TALK] = FORBIDDEN_METRONOME | FORBIDDEN_ASSIST | FORBIDDEN_COPYCAT | FORBIDDEN_SLEEP_TALK,
[MOVE_SNAP_TRAP] = FORBIDDEN_METRONOME,
[MOVE_SNARL] = FORBIDDEN_METRONOME,
[MOVE_SNATCH] = FORBIDDEN_METRONOME | FORBIDDEN_ASSIST | FORBIDDEN_COPYCAT,
[MOVE_SNORE] = FORBIDDEN_METRONOME,
[MOVE_SOLAR_BEAM] = FORBIDDEN_SLEEP_TALK,
[MOVE_SOLAR_BLADE] = FORBIDDEN_SLEEP_TALK,
[MOVE_SOLAR_BEAM] = FORBIDDEN_SLEEP_TALK | FORBIDDEN_PARENTAL_BOND,
[MOVE_SOLAR_BLADE] = FORBIDDEN_SLEEP_TALK | FORBIDDEN_PARENTAL_BOND,
[MOVE_SPARKLY_SWIRL] = FORBIDDEN_METRONOME,
[MOVE_SPECTRAL_THIEF] = FORBIDDEN_METRONOME,
[MOVE_SPIKE_CANNON] = FORBIDDEN_PARENTAL_BOND,
[MOVE_SPIKY_SHIELD] = FORBIDDEN_METRONOME | FORBIDDEN_ASSIST | FORBIDDEN_COPYCAT,
[MOVE_SPIRIT_BREAK] = FORBIDDEN_METRONOME,
[MOVE_SPLISHY_SPLASH] = FORBIDDEN_METRONOME,
@ -1034,8 +1066,9 @@ static const u8 sForbiddenMoves[MOVES_COUNT] =
[MOVE_STEEL_BEAM] = FORBIDDEN_METRONOME,
[MOVE_STRANGE_STEAM] = FORBIDDEN_METRONOME,
[MOVE_SUNSTEEL_STRIKE] = FORBIDDEN_METRONOME,
[MOVE_SURGING_STRIKES] = FORBIDDEN_METRONOME,
[MOVE_SURGING_STRIKES] = FORBIDDEN_METRONOME | FORBIDDEN_PARENTAL_BOND,
[MOVE_SWITCHEROO] = FORBIDDEN_METRONOME | FORBIDDEN_ASSIST | FORBIDDEN_COPYCAT,
[MOVE_TAIL_SLAP] = FORBIDDEN_PARENTAL_BOND,
[MOVE_TECHNO_BLAST] = FORBIDDEN_METRONOME,
[MOVE_THIEF] = FORBIDDEN_METRONOME | FORBIDDEN_ASSIST | FORBIDDEN_COPYCAT,
[MOVE_THOUSAND_ARROWS] = FORBIDDEN_METRONOME,
@ -1044,9 +1077,13 @@ static const u8 sForbiddenMoves[MOVES_COUNT] =
[MOVE_THUNDEROUS_KICK] = FORBIDDEN_METRONOME,
[MOVE_TRANSFORM] = FORBIDDEN_METRONOME | FORBIDDEN_ASSIST | FORBIDDEN_COPYCAT | FORBIDDEN_MIMIC,
[MOVE_TRICK] = FORBIDDEN_METRONOME | FORBIDDEN_ASSIST | FORBIDDEN_COPYCAT,
[MOVE_UPROAR] = FORBIDDEN_SLEEP_TALK,
[MOVE_TRIPLE_AXEL] = FORBIDDEN_PARENTAL_BOND,
[MOVE_TRIPLE_KICK] = FORBIDDEN_PARENTAL_BOND,
[MOVE_TWINEEDLE] = FORBIDDEN_PARENTAL_BOND,
[MOVE_UPROAR] = FORBIDDEN_SLEEP_TALK | FORBIDDEN_PARENTAL_BOND,
[MOVE_V_CREATE] = FORBIDDEN_METRONOME,
[MOVE_VEEVEE_VOLLEY] = FORBIDDEN_METRONOME,
[MOVE_WATER_SHURIKEN] = FORBIDDEN_PARENTAL_BOND,
[MOVE_WHIRLWIND] = FORBIDDEN_ASSIST | FORBIDDEN_COPYCAT,
[MOVE_WICKED_BLOW] = FORBIDDEN_METRONOME,
[MOVE_WIDE_GUARD] = FORBIDDEN_METRONOME,
@ -1341,6 +1378,17 @@ static void Cmd_attackcanceler(void)
if (AtkCanceller_UnableToUseMove())
return;
if (!gSpecialStatuses[gBattlerAttacker].parentalBondOn
&& GetBattlerAbility(gBattlerAttacker) == ABILITY_PARENTAL_BOND
&& IsMoveAffectedByParentalBond(gCurrentMove, gBattlerAttacker)
&& !(gAbsentBattlerFlags & gBitTable[gBattlerTarget]))
{
gSpecialStatuses[gBattlerAttacker].parentalBondOn = 2;
gMultiHitCounter = 2;
PREPARE_BYTE_NUMBER_BUFFER(gBattleScripting.multihitString, 1, 0)
return;
}
// Check Protean activation.
GET_MOVE_TYPE(gCurrentMove, moveType);
if ((GetBattlerAbility(gBattlerAttacker) == ABILITY_PROTEAN || GetBattlerAbility(gBattlerAttacker) == ABILITY_LIBERO)
@ -1669,6 +1717,13 @@ static void Cmd_accuracycheck(void)
else if (!JumpIfMoveAffectedByProtect(0))
gBattlescriptCurrInstr += 7;
}
else if (gSpecialStatuses[gBattlerAttacker].parentalBondOn == 1
|| (gSpecialStatuses[gBattlerAttacker].multiHitOn && (gBattleMoves[move].effect != EFFECT_TRIPLE_KICK
|| GetBattlerAbility(gBattlerAttacker) == ABILITY_SKILL_LINK)))
{
// No acc checks for second hit of Parental Bond or multi hit moves, except Triple Kick/Triple Axel
gBattlescriptCurrInstr += 7;
}
else
{
GET_MOVE_TYPE(move, type);
@ -1749,7 +1804,8 @@ static void Cmd_ppreduce(void)
// For item Metronome, echoed voice
if (gCurrentMove == gLastResultingMoves[gBattlerAttacker]
&& !(gMoveResultFlags & MOVE_RESULT_NO_EFFECT)
&& !WasUnableToUseMove(gBattlerAttacker))
&& !WasUnableToUseMove(gBattlerAttacker)
&& gSpecialStatuses[gBattlerAttacker].parentalBondOn != 2) // Don't increment counter on first hit
gBattleStruct->sameMoveTurns[gBattlerAttacker]++;
else
gBattleStruct->sameMoveTurns[gBattlerAttacker] = 0;
@ -2008,6 +2064,12 @@ static void Cmd_attackanimation(void)
}
else
{
if (gSpecialStatuses[gBattlerAttacker].parentalBondOn == 1) // No animation on second hit
{
gBattlescriptCurrInstr++;
return;
}
if ((gBattleMoves[gCurrentMove].target & MOVE_TARGET_BOTH
|| gBattleMoves[gCurrentMove].target & MOVE_TARGET_FOES_AND_ALLY
|| gBattleMoves[gCurrentMove].target & MOVE_TARGET_DEPENDS)
@ -2295,10 +2357,12 @@ static void Cmd_resultmessage(void)
switch (gMoveResultFlags & (~MOVE_RESULT_MISSED))
{
case MOVE_RESULT_SUPER_EFFECTIVE:
stringId = STRINGID_SUPEREFFECTIVE;
if (!gMultiHitCounter) // Don't print effectiveness on each hit in a multi hit attack
stringId = STRINGID_SUPEREFFECTIVE;
break;
case MOVE_RESULT_NOT_VERY_EFFECTIVE:
stringId = STRINGID_NOTVERYEFFECTIVE;
if (!gMultiHitCounter)
stringId = STRINGID_NOTVERYEFFECTIVE;
break;
case MOVE_RESULT_ONE_HIT_KO:
stringId = STRINGID_ONEHITKO;
@ -2377,7 +2441,6 @@ static void Cmd_resultmessage(void)
if (gSpecialStatuses[gBattlerTarget].berryReduced
&& !(gMoveResultFlags & MOVE_RESULT_NO_EFFECT))
{
gLastUsedItem = gBattleMons[gBattlerTarget].item;
gSpecialStatuses[gBattlerTarget].berryReduced = 0;
BattleScriptPushCursor();
gBattlescriptCurrInstr = BattleScript_PrintBerryReduceString;
@ -2524,6 +2587,10 @@ void SetMoveEffect(bool32 primary, u32 certain)
switch (gBattleScripting.moveEffect) // Set move effects which happen later on
{
case MOVE_EFFECT_KNOCK_OFF:
case MOVE_EFFECT_SMACK_DOWN:
case MOVE_EFFECT_REMOVE_STATUS:
case MOVE_EFFECT_STEAL_ITEM:
case MOVE_EFFECT_BURN_UP:
gBattleStruct->moveEffect2 = gBattleScripting.moveEffect;
gBattlescriptCurrInstr++;
return;
@ -3013,61 +3080,6 @@ void SetMoveEffect(bool32 primary, u32 certain)
gBattleMons[gBattlerAttacker].status2 |= STATUS2_RAGE;
gBattlescriptCurrInstr++;
break;
case MOVE_EFFECT_STEAL_ITEM:
{
if (!CanStealItem(gBattlerAttacker, gBattlerTarget, gBattleMons[gBattlerTarget].item))
{
gBattlescriptCurrInstr++;
break;
}
side = GetBattlerSide(gBattlerAttacker);
if (GetBattlerSide(gBattlerAttacker) == B_SIDE_OPPONENT
&& !(gBattleTypeFlags &
(BATTLE_TYPE_EREADER_TRAINER
| BATTLE_TYPE_FRONTIER
| BATTLE_TYPE_LINK
| BATTLE_TYPE_RECORDED_LINK
| BATTLE_TYPE_SECRET_BASE)))
{
gBattlescriptCurrInstr++;
}
else if (!(gBattleTypeFlags &
(BATTLE_TYPE_EREADER_TRAINER
| BATTLE_TYPE_FRONTIER
| BATTLE_TYPE_LINK
| BATTLE_TYPE_RECORDED_LINK
| BATTLE_TYPE_SECRET_BASE))
&& (gWishFutureKnock.knockedOffMons[side] & gBitTable[gBattlerPartyIndexes[gBattlerAttacker]]))
{
gBattlescriptCurrInstr++;
}
else if (gBattleMons[gBattlerTarget].item
&& gBattleMons[gBattlerTarget].ability == ABILITY_STICKY_HOLD)
{
BattleScriptPushCursor();
gBattlescriptCurrInstr = BattleScript_NoItemSteal;
gLastUsedAbility = gBattleMons[gBattlerTarget].ability;
RecordAbilityBattle(gBattlerTarget, gLastUsedAbility);
}
else if (gBattleMons[gBattlerAttacker].item != 0
|| gBattleMons[gBattlerTarget].item == ITEM_ENIGMA_BERRY
|| gBattleMons[gBattlerTarget].item == 0)
{
gBattlescriptCurrInstr++;
}
else
{
StealTargetItem(gBattlerAttacker, gBattlerTarget); // Attacker steals target item
gBattleMons[gBattlerAttacker].item = 0; // Item assigned later on with thief (see MOVEEND_CHANGED_ITEMS)
gBattleStruct->changedItems[gBattlerAttacker] = gLastUsedItem; // Stolen item to be assigned later
BattleScriptPush(gBattlescriptCurrInstr + 1);
gBattlescriptCurrInstr = BattleScript_ItemSteal;
}
}
break;
case MOVE_EFFECT_PREVENT_ESCAPE:
gBattleMons[gBattlerTarget].status2 |= STATUS2_ESCAPE_PREVENTION;
gDisableStructs[gBattlerTarget].battlerPreventingEscape = gBattlerAttacker;
@ -3085,34 +3097,6 @@ void SetMoveEffect(bool32 primary, u32 certain)
BattleScriptPush(gBattlescriptCurrInstr + 1);
gBattlescriptCurrInstr = BattleScript_RapidSpinAway;
break;
case MOVE_EFFECT_REMOVE_STATUS: // Smelling salts
if (!(gBattleMons[gBattlerTarget].status1 & gBattleMoves[gCurrentMove].argument))
{
gBattlescriptCurrInstr++;
}
else
{
gBattleMons[gBattlerTarget].status1 &= ~(gBattleMoves[gCurrentMove].argument);
gActiveBattler = gBattlerTarget;
BtlController_EmitSetMonData(0, REQUEST_STATUS_BATTLE, 0, 4, &gBattleMons[gActiveBattler].status1);
MarkBattlerForControllerExec(gActiveBattler);
BattleScriptPush(gBattlescriptCurrInstr + 1);
switch (gBattleMoves[gCurrentMove].argument)
{
case STATUS1_PARALYSIS:
gBattlescriptCurrInstr = BattleScript_TargetPRLZHeal;
break;
case STATUS1_SLEEP:
gBattlescriptCurrInstr = BattleScript_TargetWokeUp;
break;
case STATUS1_BURN:
gBattlescriptCurrInstr = BattleScript_TargetBurnHeal;
break;
}
}
break;
case MOVE_EFFECT_ATK_DEF_DOWN: // SuperPower
BattleScriptPush(gBattlescriptCurrInstr + 1);
gBattlescriptCurrInstr = BattleScript_AtkDefDown;
@ -3121,38 +3105,6 @@ void SetMoveEffect(bool32 primary, u32 certain)
BattleScriptPush(gBattlescriptCurrInstr + 1);
gBattlescriptCurrInstr = BattleScript_DefSpDefDown;
break;
case MOVE_EFFECT_RECOIL_25: // Take Down, 25% recoil
gBattleMoveDamage = (gHpDealt) / 4;
if (gBattleMoveDamage == 0)
gBattleMoveDamage = 1;
BattleScriptPush(gBattlescriptCurrInstr + 1);
gBattlescriptCurrInstr = sMoveEffectBS_Ptrs[gBattleScripting.moveEffect];
break;
case MOVE_EFFECT_RECOIL_33: // Double Edge, 33 % recoil
gBattleMoveDamage = gHpDealt / 3;
if (gBattleMoveDamage == 0)
gBattleMoveDamage = 1;
BattleScriptPush(gBattlescriptCurrInstr + 1);
gBattlescriptCurrInstr = sMoveEffectBS_Ptrs[gBattleScripting.moveEffect];
break;
case MOVE_EFFECT_RECOIL_50: // Head Smash, 50 % recoil
gBattleMoveDamage = gHpDealt / 2;
if (gBattleMoveDamage == 0)
gBattleMoveDamage = 1;
BattleScriptPush(gBattlescriptCurrInstr + 1);
gBattlescriptCurrInstr = BattleScript_MoveEffectRecoil;
break;
case MOVE_EFFECT_RECOIL_33_STATUS: // Flare Blitz - can burn, Volt Tackle - can paralyze
gBattleScripting.savedDmg = gHpDealt / 3;
if (gBattleScripting.savedDmg == 0)
gBattleScripting.savedDmg = 1;
BattleScriptPush(gBattlescriptCurrInstr + 1);
gBattlescriptCurrInstr = BattleScript_MoveEffectRecoilWithStatus;
break;
case MOVE_EFFECT_THRASH:
if (gBattleMons[gEffectBattler].status2 & STATUS2_LOCK_CONFUSE)
{
@ -3183,15 +3135,6 @@ void SetMoveEffect(bool32 primary, u32 certain)
gBattlescriptCurrInstr = BattleScript_MoveEffectClearSmog;
}
break;
case MOVE_EFFECT_SMACK_DOWN:
if (!IsBattlerGrounded(gBattlerTarget))
{
gStatuses3[gBattlerTarget] |= STATUS3_SMACKED_DOWN;
gStatuses3[gBattlerTarget] &= ~(STATUS3_MAGNET_RISE | STATUS3_TELEKINESIS | STATUS3_ON_AIR);
BattleScriptPush(gBattlescriptCurrInstr + 1);
gBattlescriptCurrInstr = BattleScript_MoveEffectSmackDown;
}
break;
case MOVE_EFFECT_FLAME_BURST:
if (IsBattlerAlive(BATTLE_PARTNER(gBattlerTarget)) && GetBattlerAbility(BATTLE_PARTNER(gBattlerTarget)) != ABILITY_MAGIC_GUARD)
{
@ -4748,6 +4691,10 @@ static void Cmd_moveend(void)
{
switch (gBattleScripting.moveendState)
{
case MOVEEND_SUM_DAMAGE: // Sum and store damage dealt for multi strike recoil
gBattleScripting.savedDmg += gHpDealt;
gBattleScripting.moveendState++;
break;
case MOVEEND_PROTECT_LIKE_EFFECT:
if (gProtectStructs[gBattlerAttacker].touchedProtectLike)
{
@ -4815,6 +4762,41 @@ static void Cmd_moveend(void)
}
gBattleScripting.moveendState++;
break;
case MOVEEND_RECOIL:
if (!(gMoveResultFlags & MOVE_RESULT_NO_EFFECT)
&& !(gHitMarker & HITMARKER_UNABLE_TO_USE_MOVE)
&& IsBattlerAlive(gBattlerAttacker))
{
switch (gBattleMoves[gCurrentMove].effect)
{
case EFFECT_RECOIL_25: // Take Down, 25% recoil
gBattleMoveDamage = max(1, gBattleScripting.savedDmg / 4);
BattleScriptPushCursor();
gBattlescriptCurrInstr = BattleScript_MoveEffectRecoil;
effect = TRUE;
break;
case EFFECT_RECOIL_33: // Double Edge, 33 % recoil
gBattleMoveDamage = max(1, gBattleScripting.savedDmg / 3);
BattleScriptPushCursor();
gBattlescriptCurrInstr = BattleScript_MoveEffectRecoil;
effect = TRUE;
break;
case EFFECT_RECOIL_50: // Head Smash, 50 % recoil
gBattleMoveDamage = max(1, gBattleScripting.savedDmg / 2);
BattleScriptPushCursor();
gBattlescriptCurrInstr = BattleScript_MoveEffectRecoil;
effect = TRUE;
break;
case EFFECT_RECOIL_33_STATUS: // Flare Blitz - can burn, Volt Tackle - can paralyze
gBattleMoveDamage = max(1, gBattleScripting.savedDmg / 3);
BattleScriptPushCursor();
gBattlescriptCurrInstr = BattleScript_MoveEffectRecoilWithStatus;
effect = TRUE;
break;
}
}
gBattleScripting.moveendState++;
break;
case MOVEEND_SYNCHRONIZE_TARGET: // target synchronize
if (AbilityBattleEffects(ABILITYEFFECT_SYNCHRONIZE, gBattlerTarget, 0, 0, 0))
effect = TRUE;
@ -4882,15 +4864,82 @@ static void Cmd_moveend(void)
gBattleScripting.moveendState++;
break;
case MOVEEND_MOVE_EFFECTS2: // For effects which should happen after target items, for example Knock Off after damage from Rocky Helmet.
{
switch (gBattleStruct->moveEffect2)
{
case MOVE_EFFECT_KNOCK_OFF:
effect = TryKnockOffBattleScript(gBattlerTarget);
break;
case MOVE_EFFECT_SMACK_DOWN:
if (!IsBattlerGrounded(gBattlerTarget) && IsBattlerAlive(gBattlerTarget))
{
gStatuses3[gBattlerTarget] |= STATUS3_SMACKED_DOWN;
gStatuses3[gBattlerTarget] &= ~(STATUS3_MAGNET_RISE | STATUS3_TELEKINESIS | STATUS3_ON_AIR);
effect = TRUE;
BattleScriptPush(gBattlescriptCurrInstr + 1);
gBattlescriptCurrInstr = BattleScript_MoveEffectSmackDown;
}
break;
case MOVE_EFFECT_REMOVE_STATUS: // Smelling salts, Wake-Up Slap, Sparkling Aria
if ((gBattleMons[gBattlerTarget].status1 & gBattleMoves[gCurrentMove].argument) && IsBattlerAlive(gBattlerTarget))
{
gBattleMons[gBattlerTarget].status1 &= ~(gBattleMoves[gCurrentMove].argument);
gActiveBattler = gBattlerTarget;
BtlController_EmitSetMonData(0, REQUEST_STATUS_BATTLE, 0, 4, &gBattleMons[gActiveBattler].status1);
MarkBattlerForControllerExec(gActiveBattler);
effect = TRUE;
BattleScriptPush(gBattlescriptCurrInstr + 1);
switch (gBattleMoves[gCurrentMove].argument)
{
case STATUS1_PARALYSIS:
gBattlescriptCurrInstr = BattleScript_TargetPRLZHeal;
break;
case STATUS1_SLEEP:
gBattlescriptCurrInstr = BattleScript_TargetWokeUp;
break;
case STATUS1_BURN:
gBattlescriptCurrInstr = BattleScript_TargetBurnHeal;
break;
}
}
break; // MOVE_EFFECT_REMOVE_STATUS
case MOVE_EFFECT_STEAL_ITEM:
if (!CanStealItem(gBattlerAttacker, gBattlerTarget, gBattleMons[gBattlerTarget].item)
|| gBattleMons[gBattlerAttacker].item != ITEM_NONE
|| gBattleMons[gBattlerTarget].item == ITEM_ENIGMA_BERRY
|| gBattleMons[gBattlerTarget].item == ITEM_NONE)
{
BattleScriptPushCursor();
gBattlescriptCurrInstr = BattleScript_MoveEnd; // Can't steal item, just do damage
}
else if (gBattleMons[gBattlerTarget].item
&& gBattleMons[gBattlerTarget].ability == ABILITY_STICKY_HOLD) // Can steal item, but ability prevents it
{
BattleScriptPushCursor();
gBattlescriptCurrInstr = BattleScript_NoItemSteal;
gLastUsedAbility = gBattleMons[gBattlerTarget].ability;
RecordAbilityBattle(gBattlerTarget, gLastUsedAbility);
}
else
{
StealTargetItem(gBattlerAttacker, gBattlerTarget); // Attacker steals target item
gBattleStruct->changedItems[gBattlerAttacker] = gLastUsedItem; // Stolen item to be assigned later
BattleScriptPush(gBattlescriptCurrInstr + 1);
gBattlescriptCurrInstr = BattleScript_ItemSteal;
}
break; // MOVE_EFFECT_STEAL_ITEM
case MOVE_EFFECT_BURN_UP:
effect = TRUE;
BattleScriptPush(gBattlescriptCurrInstr + 1);
gBattlescriptCurrInstr = BattleScript_BurnUpRemoveType;
break;
}
gBattleStruct->moveEffect2 = 0;
gBattleScripting.moveendState++;
break;
break; // MOVEEND_MOVE_EFFECTS2
}
case MOVEEND_ITEM_EFFECTS_ALL: // item effects for all battlers
if (ItemBattleEffects(ITEMEFFECT_MOVE_END, 0, FALSE))
effect = TRUE;
@ -5076,6 +5125,56 @@ static void Cmd_moveend(void)
RecordLastUsedMoveBy(gBattlerAttacker, gCurrentMove);
gBattleScripting.moveendState++;
break;
case MOVEEND_MULTIHIT_MOVE:
if (!(gMoveResultFlags & MOVE_RESULT_NO_EFFECT)
&& !(gHitMarker & HITMARKER_UNABLE_TO_USE_MOVE)
&& gMultiHitCounter
&& !(gCurrentMove == MOVE_PRESENT && gBattleStruct->presentBasePower == 0)) // Silly edge case
{
gBattleScripting.multihitString[4]++;
if (--gMultiHitCounter == 0)
{
BattleScriptPushCursor();
gBattlescriptCurrInstr = BattleScript_MultiHitPrintStrings;
effect = 1;
}
else
{
if (gCurrentMove == MOVE_DRAGON_DARTS)
{
// TODO
}
if (gBattleMons[gBattlerAttacker].hp
&& gBattleMons[gBattlerTarget].hp
&& (gChosenMove == MOVE_SLEEP_TALK || !(gBattleMons[gBattlerAttacker].status1 & STATUS1_SLEEP))
&& !(gBattleMons[gBattlerAttacker].status1 & STATUS1_FREEZE))
{
if (gSpecialStatuses[gBattlerAttacker].parentalBondOn)
gSpecialStatuses[gBattlerAttacker].parentalBondOn--;
gHitMarker |= (HITMARKER_NO_PPDEDUCT | HITMARKER_NO_ATTACKSTRING);
gBattleScripting.animTargetsHit = 0;
gBattleScripting.moveendState = 0;
gSpecialStatuses[gBattlerAttacker].multiHitOn = TRUE;
MoveValuesCleanUp();
BattleScriptPush(gBattleScriptsForMoveEffects[gBattleMoves[gCurrentMove].effect]);
gBattlescriptCurrInstr = BattleScript_FlushMessageBox;
return;
}
else
{
BattleScriptPushCursor();
gBattlescriptCurrInstr = BattleScript_MultiHitPrintStrings;
effect = 1;
}
}
}
gMultiHitCounter = 0;
gSpecialStatuses[gBattlerAttacker].parentalBondOn = 0;
gSpecialStatuses[gBattlerAttacker].multiHitOn = 0;
gBattleScripting.moveendState++;
break;
case MOVEEND_EJECT_BUTTON:
if (gCurrentMove != MOVE_DRAGON_TAIL
&& gCurrentMove != MOVE_CIRCLE_THROW
@ -10808,7 +10907,8 @@ static void Cmd_handlefurycutter(void)
}
else
{
if (gDisableStructs[gBattlerAttacker].furyCutterCounter != 5)
if (gDisableStructs[gBattlerAttacker].furyCutterCounter != 5
&& gSpecialStatuses[gBattlerAttacker].parentalBondOn != 2) // Don't increment counter on first hit
gDisableStructs[gBattlerAttacker].furyCutterCounter++;
gBattlescriptCurrInstr++;
@ -10833,27 +10933,37 @@ static void Cmd_presentdamagecalculation(void)
{
u32 rand = Random() & 0xFF;
if (rand < 102)
/* Don't reroll present effect/power for the second hit of Parental Bond.
* Not sure if this is the correct behaviour, but bulbapedia states
* that if present heals the foe, it doesn't strike twice, and if it deals
* damage, the second strike will always deal damage too. This is a simple way
* to replicate that effect.
*/
if (gSpecialStatuses[gBattlerAttacker].parentalBondOn != 1)
{
gBattleStruct->presentBasePower = 40;
}
else if (rand < 178)
{
gBattleStruct->presentBasePower = 80;
}
else if (rand < 204)
{
gBattleStruct->presentBasePower = 120;
}
else
{
gBattleMoveDamage = gBattleMons[gBattlerTarget].maxHP / 4;
if (gBattleMoveDamage == 0)
gBattleMoveDamage = 1;
gBattleMoveDamage *= -1;
if (rand < 102)
{
gBattleStruct->presentBasePower = 40;
}
else if (rand < 178)
{
gBattleStruct->presentBasePower = 80;
}
else if (rand < 204)
{
gBattleStruct->presentBasePower = 120;
}
else
{
gBattleMoveDamage = gBattleMons[gBattlerTarget].maxHP / 4;
if (gBattleMoveDamage == 0)
gBattleMoveDamage = 1;
gBattleMoveDamage *= -1;
gBattleStruct->presentBasePower = 0;
}
}
if (rand < 204)
if (gBattleStruct->presentBasePower)
{
gBattlescriptCurrInstr = BattleScript_HitFromCritCalc;
}
@ -12873,3 +12983,27 @@ static bool32 CriticalCapture(u32 odds)
#endif
}
bool8 IsMoveAffectedByParentalBond(u16 move, u8 battlerId)
{
if (gBattleMoves[move].split != SPLIT_STATUS && !(sForbiddenMoves[move] & FORBIDDEN_PARENTAL_BOND))
{
if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE)
{
switch (gBattleMoves[move].target)
{
case MOVE_TARGET_BOTH:
if (CountAliveMonsInBattle(BATTLE_ALIVE_DEF_SIDE) >= 2) // Check for single target
return FALSE;
break;
case MOVE_TARGET_FOES_AND_ALLY:
if (CountAliveMonsInBattle(BATTLE_ALIVE_EXCEPT_ACTIVE) >= 2) // Count mons on both sides; ignore attacker
return FALSE;
break;
}
}
return TRUE;
}
return FALSE;
}

View file

@ -217,6 +217,37 @@ static const u16 sEntrainmentTargetSimpleBeamBannedAbilities[] =
ABILITY_GULP_MISSILE,
};
static const u16 sTwoStrikeMoves[] =
{
MOVE_BONEMERANG,
MOVE_DOUBLE_HIT,
MOVE_DOUBLE_IRON_BASH,
MOVE_DOUBLE_KICK,
MOVE_DRAGON_DARTS,
MOVE_DUAL_CHOP,
MOVE_DUAL_WINGBEAT,
MOVE_GEAR_GRIND,
MOVE_TWINEEDLE,
0xFFFF
};
static u8 CalcBeatUpPower(void)
{
struct Pokemon *party;
u8 basePower;
u16 species;
if (GetBattlerSide(gBattlerAttacker) == B_SIDE_PLAYER)
party = gPlayerParty;
else
party = gEnemyParty;
// Party slot is set in the battle script for Beat Up
species = GetMonData(&party[gBattleCommunication[0] - 1], MON_DATA_SPECIES);
basePower = (gBaseStats[species].baseAttack / 10) + 5;
return basePower;
}
bool32 IsAffectedByFollowMe(u32 battlerAtk, u32 defSide)
{
u32 ability = GetBattlerAbility(battlerAtk);
@ -248,6 +279,7 @@ void HandleAction_UseMove(void)
gBattleStruct->atkCancellerTracker = 0;
gMoveResultFlags = 0;
gMultiHitCounter = 0;
gBattleScripting.savedDmg = 0;
gBattleCommunication[6] = 0;
gBattleScripting.savedMoveEffect = 0;
gCurrMovePos = gChosenMovePos = *(gBattleStruct->chosenMovePositions + gBattlerAttacker);
@ -3085,6 +3117,7 @@ enum
CANCELLER_POWDER_MOVE,
CANCELLER_POWDER_STATUS,
CANCELLER_THROAT_CHOP,
CANCELLER_MULTIHIT_MOVES,
CANCELLER_END,
CANCELLER_PSYCHIC_TERRAIN,
CANCELLER_END2,
@ -3101,6 +3134,7 @@ u8 AtkCanceller_UnableToUseMove(void)
case CANCELLER_FLAGS: // flags clear
gBattleMons[gBattlerAttacker].status2 &= ~(STATUS2_DESTINY_BOND);
gStatuses3[gBattlerAttacker] &= ~(STATUS3_GRUDGE);
gBattleScripting.tripleKickPower = 0;
gBattleStruct->atkCancellerTracker++;
break;
case CANCELLER_ASLEEP: // check being asleep
@ -3412,6 +3446,95 @@ u8 AtkCanceller_UnableToUseMove(void)
}
gBattleStruct->atkCancellerTracker++;
break;
case CANCELLER_MULTIHIT_MOVES:
if (gBattleMoves[gCurrentMove].effect == EFFECT_MULTI_HIT)
{
u16 ability = gBattleMons[gBattlerAttacker].ability;
if (ability == ABILITY_SKILL_LINK)
{
gMultiHitCounter = 5;
}
#ifdef POKEMON_EXPANSION
else if (ability == ABILITY_BATTLE_BOND
&& gCurrentMove == MOVE_WATER_SHURIKEN
&& gBattleMons[gBattlerAttacker].species == SPECIES_GRENINJA_ASH)
{
gMultiHitCounter = 3;
}
#endif
else
{
if (B_MULTI_HIT_CHANCE >= GEN_5)
{
// 2 and 3 hits: 33.3%
// 4 and 5 hits: 16.7%
gMultiHitCounter = Random() % 4;
if (gMultiHitCounter > 2)
{
gMultiHitCounter = (Random() % 3);
if (gMultiHitCounter < 2)
gMultiHitCounter = 2;
else
gMultiHitCounter = 3;
}
else
gMultiHitCounter += 3;
}
else
{
// 2 and 3 hits: 37.5%
// 4 and 5 hits: 12.5%
gMultiHitCounter = Random() % 4;
if (gMultiHitCounter > 1)
gMultiHitCounter = (Random() % 4) + 2;
else
gMultiHitCounter += 2;
}
}
PREPARE_BYTE_NUMBER_BUFFER(gBattleScripting.multihitString, 1, 0)
}
else if (IsTwoStrikesMove(gCurrentMove))
{
gMultiHitCounter = 2;
PREPARE_BYTE_NUMBER_BUFFER(gBattleScripting.multihitString, 1, 0)
if (gCurrentMove == MOVE_DRAGON_DARTS)
{
// TODO
}
}
else if (gBattleMoves[gCurrentMove].effect == EFFECT_TRIPLE_KICK || gCurrentMove == MOVE_SURGING_STRIKES)
{
gMultiHitCounter = 3;
PREPARE_BYTE_NUMBER_BUFFER(gBattleScripting.multihitString, 1, 0)
}
#if B_BEAT_UP_DMG >= GEN_5
else if (gBattleMoves[gCurrentMove].effect == EFFECT_BEAT_UP)
{
struct Pokemon* party;
int i;
if (GetBattlerSide(gBattlerAttacker) == B_SIDE_PLAYER)
party = gPlayerParty;
else
party = gEnemyParty;
for (i = 0; i < PARTY_SIZE; i++)
{
if (GetMonData(&party[i], MON_DATA_HP)
&& GetMonData(&party[i], MON_DATA_SPECIES) != SPECIES_NONE
&& !GetMonData(&party[i], MON_DATA_IS_EGG)
&& !GetMonData(&party[i], MON_DATA_STATUS))
gMultiHitCounter++;
}
gBattleCommunication[0] = 0; // For later
PREPARE_BYTE_NUMBER_BUFFER(gBattleScripting.multihitString, 1, 0)
}
#endif
gBattleStruct->atkCancellerTracker++;
break;
case CANCELLER_END:
break;
}
@ -7466,6 +7589,11 @@ static u16 CalcMoveBasePower(u16 move, u8 battlerAtk, u8 battlerDef)
if (gBattleMoves[gLastUsedMove].effect == EFFECT_FUSION_COMBO && move != gLastUsedMove)
basePower *= 2;
break;
#if B_BEAT_UP_DMG >= GEN_5
case EFFECT_BEAT_UP:
basePower = CalcBeatUpPower();
break;
#endif
}
if (basePower == 0)
@ -8163,6 +8291,15 @@ static u32 CalcFinalDmg(u32 dmg, u16 move, u8 battlerAtk, u8 battlerDef, u8 move
MulModifier(&finalModifier, UQ_4_12(0.5));
}
// Parental Bond Second Strike
if (gSpecialStatuses[gBattlerAttacker].parentalBondOn == 1)
{
if (B_PARENTAL_BOND_DAMAGE < GEN_7)
MulModifier(&finalModifier, UQ_4_12(0.5));
else
MulModifier(&finalModifier, UQ_4_12(0.25));
}
// attacker's abilities
switch (abilityAtk)
{
@ -9214,3 +9351,16 @@ void DoBurmyFormChange(u32 monId)
}
}
}
// Move Checks
bool8 IsTwoStrikesMove(u16 move)
{
u32 i;
for (i = 0; i < ARRAY_COUNT(sTwoStrikeMoves); i++)
{
if (move == sTwoStrikeMoves[i])
return TRUE;
}
return FALSE;
}

View file

@ -641,7 +641,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] =
[MOVE_TWINEEDLE] =
{
.effect = EFFECT_TWINEEDLE,
.effect = EFFECT_POISON_HIT,
.power = 25,
.type = TYPE_BUG,
.accuracy = 100,
@ -10020,7 +10020,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] =
.type = TYPE_FIRE,
.accuracy = 100,
.pp = 5,
.secondaryEffectChance = 0,
.secondaryEffectChance = 100,
.target = MOVE_TARGET_SELECTED,
.priority = 0,
.flags = FLAG_PROTECT_AFFECTED | FLAG_MIRROR_MOVE_AFFECTED | FLAG_KINGS_ROCK_AFFECTED | FLAG_THAW_USER,
@ -10716,7 +10716,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] =
#else
.flags = FLAG_MAKES_CONTACT | FLAG_PROTECT_AFFECTED | FLAG_MIRROR_MOVE_AFFECTED | FLAG_DMG_MINIMIZE | FLAG_IRON_FIST_BOOST | FLAG_SHEER_FORCE_BOOST,
#endif
.effect = EFFECT_PLACEHOLDER, //TODO (EFFECT_FLINCH_HIT + EFFECT_DOUBLE_HIT)
.effect = EFFECT_FLINCH_HIT,
.power = 60,
.type = TYPE_STEEL,
.accuracy = 100,
@ -11444,7 +11444,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] =
[MOVE_TRIPLE_AXEL] =
{
.effect = EFFECT_TRIPLE_KICK, //TODO: Increase damage by 20 instead of 10
.effect = EFFECT_TRIPLE_KICK,
.power = 20,
.type = TYPE_ICE,
.accuracy = 90,
@ -11513,7 +11513,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] =
[MOVE_SURGING_STRIKES] =
{
.effect = EFFECT_PLACEHOLDER, //TODO (Multi hit + Always Crit)
.effect = EFFECT_ALWAYS_CRIT,
.power = 25,
.type = TYPE_WATER,
.accuracy = 100,