Fix various Parental Bond issues

- Dragon Tail and Circle Throw strike twice and then switch the target
- Z moves are unaffected by Parental Bond
- Renamed parentalBondOn to parentalBondState
- Added constants for possible values of parentalBondState
- Fixed broken stat change animations and removed unused MOVE_EFFECT_SKY_DROP
This commit is contained in:
BuffelSaft 2022-10-23 17:37:23 +13:00
parent 3775c5d00c
commit 1b056f9044
6 changed files with 91 additions and 79 deletions

View File

@ -1995,7 +1995,6 @@ BattleScript_EffectHitSwitchTarget:
resultmessage
waitmessage B_WAIT_TIME_LONG
tryfaintmon BS_TARGET
checkparentalbondcounter 2, BattleScript_EffectHitSwitchTargetMoveEnd
moveendall
jumpifability BS_TARGET, ABILITY_SUCTION_CUPS, BattleScript_AbilityPreventsPhasingOut
jumpifstatus3 BS_TARGET, STATUS3_ROOTED, BattleScript_PrintMonIsRooted

View File

@ -174,7 +174,7 @@ struct SpecialStatus
u8 berryReduced:1;
u8 gemBoost:1;
u8 rototillerAffected:1; // to be affected by rototiller
u8 parentalBondOn:2;
u8 parentalBondState:2;
u8 multiHitOn:1;
// End of byte, two bits unused
u8 gemParam;

View File

@ -307,66 +307,65 @@
#define MOVE_EFFECT_PAYDAY 0xB
#define MOVE_EFFECT_CHARGING 0xC
#define MOVE_EFFECT_WRAP 0xD
#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_RECOIL_HP_25 0x42
#define MOVE_EFFECT_RELIC_SONG 0x43
#define MOVE_EFFECT_TRAP_BOTH 0x44
#define MOVE_EFFECT_SKY_DROP 0x45
#define MOVE_EFFECT_SCALE_SHOT 0x46
#define MOVE_EFFECT_BURN_UP 0x47
#define NUM_MOVE_EFFECTS 0x48
#define MOVE_EFFECT_BURN_UP 0xE // MOVE_EFFECT_BURN_UP replaces unused MOVE_EFFECT_RECOIL_25 so that stat change animations don't break
#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_SCALE_SHOT 0x26 // MOVE_EFFECT_SCALE_SHOT replaces unused MOVE_EFFECT_RECOIL_33 so that stat change animations don't break
#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_CLEAR_SMOG 0x38
#define MOVE_EFFECT_SP_ATK_TWO_DOWN 0x39
#define MOVE_EFFECT_SMACK_DOWN 0x3A
#define MOVE_EFFECT_FLAME_BURST 0x3B
#define MOVE_EFFECT_FEINT 0x3C
#define MOVE_EFFECT_SPECTRAL_THIEF 0x3D
#define MOVE_EFFECT_V_CREATE 0x3E
#define MOVE_EFFECT_HAPPY_HOUR 0x3F
#define MOVE_EFFECT_CORE_ENFORCER 0x40
#define MOVE_EFFECT_THROAT_CHOP 0x41
#define MOVE_EFFECT_INCINERATE 0x42
#define MOVE_EFFECT_BUG_BITE 0x43
#define MOVE_EFFECT_RECOIL_HP_25 0x44
#define MOVE_EFFECT_RELIC_SONG 0x45
#define MOVE_EFFECT_TRAP_BOTH 0x46
#define NUM_MOVE_EFFECTS 0x47
#define MOVE_EFFECT_AFFECTS_USER 0x4000
#define MOVE_EFFECT_CERTAIN 0x8000
@ -480,4 +479,9 @@
// For the second argument of GetMoveTarget, when no target override is needed
#define NO_TARGET_OVERRIDE 0
// Constants for Parental Bond
#define PARENTAL_BOND_1ST_HIT 2
#define PARENTAL_BOND_2ND_HIT 1
#define PARENTAL_BOND_OFF 0
#endif // GUARD_CONSTANTS_BATTLE_H

View File

@ -4843,7 +4843,7 @@ static void TurnValuesCleanUp(bool8 var0)
if (gDisableStructs[gActiveBattler].substituteHP == 0)
gBattleMons[gActiveBattler].status2 &= ~(STATUS2_SUBSTITUTE);
gSpecialStatuses[gActiveBattler].parentalBondOn = 0;
gSpecialStatuses[gActiveBattler].parentalBondState = PARENTAL_BOND_OFF;
}
gSideStatuses[0] &= ~(SIDE_STATUS_QUICK_GUARD | SIDE_STATUS_WIDE_GUARD | SIDE_STATUS_CRAFTY_SHIELD | SIDE_STATUS_MAT_BLOCK);

View File

@ -1138,6 +1138,7 @@ static const u16 sFinalStrikeOnlyEffects[] =
EFFECT_HIT_ESCAPE,
EFFECT_RECOIL_HP_25,
EFFECT_HIT_PREVENT_ESCAPE,
EFFECT_HIT_SWITCH_TARGET,
};
static const u16 sNaturePowerMoves[BATTLE_TERRAIN_COUNT] =
@ -1449,12 +1450,13 @@ static void Cmd_attackcanceler(void)
if (AtkCanceller_UnableToUseMove())
return;
if (!gSpecialStatuses[gBattlerAttacker].parentalBondOn
if (!gSpecialStatuses[gBattlerAttacker].parentalBondState
&& GetBattlerAbility(gBattlerAttacker) == ABILITY_PARENTAL_BOND
&& IsMoveAffectedByParentalBond(gCurrentMove, gBattlerAttacker)
&& !(gAbsentBattlerFlags & gBitTable[gBattlerTarget]))
&& !(gAbsentBattlerFlags & gBitTable[gBattlerTarget])
&& gBattleStruct->zmove.toBeUsed[gBattlerAttacker] == MOVE_NONE)
{
gSpecialStatuses[gBattlerAttacker].parentalBondOn = 2;
gSpecialStatuses[gBattlerAttacker].parentalBondState = PARENTAL_BOND_1ST_HIT;
gMultiHitCounter = 2;
PREPARE_BYTE_NUMBER_BUFFER(gBattleScripting.multihitString, 1, 0)
return;
@ -1591,6 +1593,13 @@ static void Cmd_attackcanceler(void)
gMoveResultFlags |= MOVE_RESULT_MISSED;
gLastLandedMoves[gBattlerTarget] = 0;
gLastHitByType[gBattlerTarget] = 0;
if (gSpecialStatuses[gBattlerAttacker].parentalBondState == PARENTAL_BOND_1ST_HIT)
{
gSpecialStatuses[gBattlerAttacker].parentalBondState = PARENTAL_BOND_OFF; // No second hit if first hit was blocked
gSpecialStatuses[gBattlerAttacker].multiHitOn = 0;
gMultiHitCounter = 0;
}
gBattleCommunication[MISS_TYPE] = B_MSG_PROTECTED;
gBattlescriptCurrInstr++;
}
@ -1840,7 +1849,7 @@ static void Cmd_accuracycheck(void)
else if (!JumpIfMoveAffectedByProtect(0))
gBattlescriptCurrInstr += 7;
}
else if (gSpecialStatuses[gBattlerAttacker].parentalBondOn == 1
else if (gSpecialStatuses[gBattlerAttacker].parentalBondState == PARENTAL_BOND_2ND_HIT
|| (gSpecialStatuses[gBattlerAttacker].multiHitOn && (gBattleMoves[move].effect != EFFECT_TRIPLE_KICK
|| GetBattlerAbility(gBattlerAttacker) == ABILITY_SKILL_LINK)))
{
@ -1930,7 +1939,7 @@ static void Cmd_ppreduce(void)
if (gCurrentMove == gLastResultingMoves[gBattlerAttacker]
&& !(gMoveResultFlags & MOVE_RESULT_NO_EFFECT)
&& !WasUnableToUseMove(gBattlerAttacker)
&& gSpecialStatuses[gBattlerAttacker].parentalBondOn != 2) // Don't increment counter on first hit
&& gSpecialStatuses[gBattlerAttacker].parentalBondState != PARENTAL_BOND_1ST_HIT) // Don't increment counter on first hit
gBattleStruct->sameMoveTurns[gBattlerAttacker]++;
else
gBattleStruct->sameMoveTurns[gBattlerAttacker] = 0;
@ -2247,7 +2256,7 @@ static void Cmd_attackanimation(void)
}
else
{
if (gSpecialStatuses[gBattlerAttacker].parentalBondOn == 1) // No animation on second hit
if (gSpecialStatuses[gBattlerAttacker].parentalBondState == PARENTAL_BOND_2ND_HIT) // No animation on second hit
{
gBattlescriptCurrInstr++;
return;
@ -2780,7 +2789,7 @@ void SetMoveEffect(bool32 primary, u32 certain)
u32 flags = 0;
u16 battlerAbility;
if (gSpecialStatuses[gBattlerAttacker].parentalBondOn == 2
if (gSpecialStatuses[gBattlerAttacker].parentalBondState == PARENTAL_BOND_1ST_HIT
&& gBattleMons[gBattlerTarget].hp != 0
&& IsFinalStrikeEffect(gCurrentMove))
{
@ -3156,7 +3165,7 @@ void SetMoveEffect(bool32 primary, u32 certain)
break;
case MOVE_EFFECT_PAYDAY:
// Don't scatter coins on the second hit of Parental Bond
if (GET_BATTLER_SIDE(gBattlerAttacker) == B_SIDE_PLAYER && gSpecialStatuses[gBattlerAttacker].parentalBondOn != 1)
if (GET_BATTLER_SIDE(gBattlerAttacker) == B_SIDE_PLAYER && gSpecialStatuses[gBattlerAttacker].parentalBondState!= PARENTAL_BOND_2ND_HIT)
{
u16 payday = gPaydayMoney;
gPaydayMoney += (gBattleMons[gBattlerAttacker].level * 5);
@ -5682,8 +5691,8 @@ static void Cmd_moveend(void)
&& (gChosenMove == MOVE_SLEEP_TALK || !(gBattleMons[gBattlerAttacker].status1 & STATUS1_SLEEP))
&& !(gBattleMons[gBattlerAttacker].status1 & STATUS1_FREEZE))
{
if (gSpecialStatuses[gBattlerAttacker].parentalBondOn)
gSpecialStatuses[gBattlerAttacker].parentalBondOn--;
if (gSpecialStatuses[gBattlerAttacker].parentalBondState)
gSpecialStatuses[gBattlerAttacker].parentalBondState--;
gHitMarker |= (HITMARKER_NO_PPDEDUCT | HITMARKER_NO_ATTACKSTRING);
gBattleScripting.animTargetsHit = 0;
@ -5706,7 +5715,7 @@ static void Cmd_moveend(void)
}
}
gMultiHitCounter = 0;
gSpecialStatuses[gBattlerAttacker].parentalBondOn = 0;
gSpecialStatuses[gBattlerAttacker].parentalBondState = PARENTAL_BOND_OFF;
gSpecialStatuses[gBattlerAttacker].multiHitOn = 0;
gBattleScripting.moveendState++;
break;
@ -10059,7 +10068,7 @@ static void Cmd_various(void)
// Some effects should only happen on the first or second strike of Parental Bond,
// so a way to check this in battle scripts is useful
u8 counter = T1_READ_8(gBattlescriptCurrInstr + 3);
if (gSpecialStatuses[gBattlerAttacker].parentalBondOn == counter && gBattleMons[gBattlerTarget].hp != 0)
if (gSpecialStatuses[gBattlerAttacker].parentalBondState == counter && gBattleMons[gBattlerTarget].hp != 0)
gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 4);
else
gBattlescriptCurrInstr += 8;
@ -10540,7 +10549,7 @@ static void Cmd_stockpiletobasedamage(void)
if (gBattleCommunication[MISS_TYPE] != B_MSG_PROTECTED)
gBattleScripting.animTurn = gDisableStructs[gBattlerAttacker].stockpileCounter;
if (!(gSpecialStatuses[gBattlerAttacker].parentalBondOn == 2 && gBattleMons[gBattlerTarget].hp != 0))
if (!(gSpecialStatuses[gBattlerAttacker].parentalBondState == PARENTAL_BOND_1ST_HIT && gBattleMons[gBattlerTarget].hp != 0))
{
gDisableStructs[gBattlerAttacker].stockpileCounter = 0;
// Restore stat changes from stockpile.
@ -12438,7 +12447,7 @@ static void Cmd_handlefurycutter(void)
else
{
if (gDisableStructs[gBattlerAttacker].furyCutterCounter != 5
&& gSpecialStatuses[gBattlerAttacker].parentalBondOn != 2) // Don't increment counter on first hit
&& gSpecialStatuses[gBattlerAttacker].parentalBondState != PARENTAL_BOND_1ST_HIT) // Don't increment counter on first hit
gDisableStructs[gBattlerAttacker].furyCutterCounter++;
gBattlescriptCurrInstr++;
@ -12469,7 +12478,7 @@ static void Cmd_presentdamagecalculation(void)
* damage, the second strike will always deal damage too. This is a simple way
* to replicate that effect.
*/
if (gSpecialStatuses[gBattlerAttacker].parentalBondOn != 1)
if (gSpecialStatuses[gBattlerAttacker].parentalBondState != PARENTAL_BOND_2ND_HIT)
{
if (rand < 102)
{

View File

@ -9292,7 +9292,7 @@ static u32 CalcFinalDmg(u32 dmg, u16 move, u8 battlerAtk, u8 battlerDef, u8 move
}
// Parental Bond Second Strike
if (gSpecialStatuses[gBattlerAttacker].parentalBondOn == 1)
if (gSpecialStatuses[gBattlerAttacker].parentalBondState == PARENTAL_BOND_2ND_HIT)
{
if (B_PARENTAL_BOND_DAMAGE < GEN_7)
MulModifier(&finalModifier, UQ_4_12(0.5));