Refactor move Synchronise (#7271)
This commit is contained in:
parent
0422a013c4
commit
7ae97ab6e9
@ -2461,6 +2461,11 @@
|
|||||||
.byte \battler
|
.byte \battler
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
|
.macro trysynchronoise jumpInstr:req
|
||||||
|
callnative BS_TrySynchronoise
|
||||||
|
.4byte \jumpInstr
|
||||||
|
.endm
|
||||||
|
|
||||||
.macro setallytonexttarget jumpInstr:req
|
.macro setallytonexttarget jumpInstr:req
|
||||||
jumpifbyte CMP_GREATER_THAN, gBattlerTarget, 0x1, 1f
|
jumpifbyte CMP_GREATER_THAN, gBattlerTarget, 0x1, 1f
|
||||||
addbyte gBattlerTarget, 0x2
|
addbyte gBattlerTarget, 0x2
|
||||||
|
|||||||
@ -1622,42 +1622,20 @@ BattleScript_EffectPsychoShiftCanWork:
|
|||||||
BattleScript_EffectSynchronoise::
|
BattleScript_EffectSynchronoise::
|
||||||
attackcanceler
|
attackcanceler
|
||||||
attackstring
|
attackstring
|
||||||
|
pause B_WAIT_TIME_MED
|
||||||
ppreduce
|
ppreduce
|
||||||
selectfirstvalidtarget
|
trysynchronoise BattleScript_MoveEnd
|
||||||
BattleScript_SynchronoiseLoop:
|
accuracycheck BattleScript_ButItFailed, ACC_CURR_MOVE
|
||||||
movevaluescleanup
|
goto BattleScript_HitFromCritCalc
|
||||||
jumpifcantusesynchronoise BattleScript_SynchronoiseNoEffect
|
|
||||||
accuracycheck BattleScript_SynchronoiseMissed, ACC_CURR_MOVE
|
BattleScript_ItDoesntAffectFoe::
|
||||||
critcalc
|
savetarget
|
||||||
damagecalc
|
copybyte gBattlerTarget, sBATTLER
|
||||||
adjustdamage
|
printstring STRINGID_ITDOESNTAFFECT
|
||||||
attackanimation
|
waitmessage B_WAIT_TIME_SHORT
|
||||||
waitanimation
|
|
||||||
effectivenesssound
|
|
||||||
hitanimation BS_TARGET
|
|
||||||
waitstate
|
|
||||||
healthbarupdate BS_TARGET
|
|
||||||
datahpupdate BS_TARGET
|
|
||||||
critmessage
|
|
||||||
waitmessage B_WAIT_TIME_LONG
|
|
||||||
resultmessage
|
|
||||||
waitmessage B_WAIT_TIME_LONG
|
|
||||||
flushtextbox
|
flushtextbox
|
||||||
tryfaintmon BS_TARGET
|
restoretarget
|
||||||
BattleScript_SynchronoiseMoveTargetEnd:
|
return
|
||||||
moveendto MOVEEND_NEXT_TARGET
|
|
||||||
jumpifnexttargetvalid BattleScript_SynchronoiseLoop
|
|
||||||
end
|
|
||||||
BattleScript_SynchronoiseMissed:
|
|
||||||
pause B_WAIT_TIME_SHORT
|
|
||||||
resultmessage
|
|
||||||
waitmessage B_WAIT_TIME_LONG
|
|
||||||
goto BattleScript_SynchronoiseMoveTargetEnd
|
|
||||||
BattleScript_SynchronoiseNoEffect:
|
|
||||||
pause B_WAIT_TIME_SHORT
|
|
||||||
printstring STRINGID_NOEFFECTONTARGET
|
|
||||||
waitmessage B_WAIT_TIME_LONG
|
|
||||||
goto BattleScript_SynchronoiseMoveTargetEnd
|
|
||||||
|
|
||||||
BattleScript_MoveEffectSmackDown::
|
BattleScript_MoveEffectSmackDown::
|
||||||
printstring STRINGID_FELLSTRAIGHTDOWN
|
printstring STRINGID_FELLSTRAIGHTDOWN
|
||||||
|
|||||||
@ -526,7 +526,6 @@ extern const u8 BattleScript_TeraShellDistortingTypeMatchups[];
|
|||||||
extern const u8 BattleScript_TeraFormChange[];
|
extern const u8 BattleScript_TeraFormChange[];
|
||||||
extern const u8 BattleScript_SleepClausePreventsEnd[];
|
extern const u8 BattleScript_SleepClausePreventsEnd[];
|
||||||
extern const u8 BattleScript_PowerConstruct[];
|
extern const u8 BattleScript_PowerConstruct[];
|
||||||
|
|
||||||
extern const u8 BattleScript_AbilityProtectsDoesntAffect[];
|
extern const u8 BattleScript_AbilityProtectsDoesntAffect[];
|
||||||
extern const u8 BattleScript_ImmunityProtected[];
|
extern const u8 BattleScript_ImmunityProtected[];
|
||||||
extern const u8 BattleScript_SafeguardProtected[];
|
extern const u8 BattleScript_SafeguardProtected[];
|
||||||
@ -538,6 +537,7 @@ extern const u8 BattleScript_AlreadyPoisoned[];
|
|||||||
extern const u8 BattleScript_AlreadyParalyzed[];
|
extern const u8 BattleScript_AlreadyParalyzed[];
|
||||||
extern const u8 BattleScript_AlreadyBurned[];
|
extern const u8 BattleScript_AlreadyBurned[];
|
||||||
extern const u8 BattleScript_PrintAbilityMadeIneffective[];
|
extern const u8 BattleScript_PrintAbilityMadeIneffective[];
|
||||||
|
extern const u8 BattleScript_ItDoesntAffectFoe[];
|
||||||
|
|
||||||
// zmoves
|
// zmoves
|
||||||
extern const u8 BattleScript_ZMoveActivateDamaging[];
|
extern const u8 BattleScript_ZMoveActivateDamaging[];
|
||||||
|
|||||||
@ -345,6 +345,7 @@ enum TypeSideHazard
|
|||||||
#define MOVE_RESULT_FOE_HUNG_ON (1 << 7)
|
#define MOVE_RESULT_FOE_HUNG_ON (1 << 7)
|
||||||
#define MOVE_RESULT_STURDIED (1 << 8)
|
#define MOVE_RESULT_STURDIED (1 << 8)
|
||||||
#define MOVE_RESULT_FOE_ENDURED_AFFECTION (1 << 9)
|
#define MOVE_RESULT_FOE_ENDURED_AFFECTION (1 << 9)
|
||||||
|
#define MOVE_RESULT_SYNCHRONOISE_AFFECTED (1 << 10)
|
||||||
#define MOVE_RESULT_NO_EFFECT (MOVE_RESULT_MISSED | MOVE_RESULT_DOESNT_AFFECT_FOE | MOVE_RESULT_FAILED)
|
#define MOVE_RESULT_NO_EFFECT (MOVE_RESULT_MISSED | MOVE_RESULT_DOESNT_AFFECT_FOE | MOVE_RESULT_FAILED)
|
||||||
|
|
||||||
enum BattleWeather
|
enum BattleWeather
|
||||||
|
|||||||
@ -1242,22 +1242,24 @@ static void Cmd_attackcanceler(void)
|
|||||||
|
|
||||||
|
|
||||||
u32 abilityDef = GetBattlerAbility(gBattlerTarget);
|
u32 abilityDef = GetBattlerAbility(gBattlerTarget);
|
||||||
if (CanAbilityBlockMove(gBattlerAttacker,
|
if (CanAbilityBlockMove(
|
||||||
gBattlerTarget,
|
gBattlerAttacker,
|
||||||
GetBattlerAbility(gBattlerAttacker),
|
gBattlerTarget,
|
||||||
abilityDef,
|
GetBattlerAbility(gBattlerAttacker),
|
||||||
gCurrentMove,
|
abilityDef,
|
||||||
ABILITY_RUN_SCRIPT))
|
gCurrentMove,
|
||||||
|
ABILITY_RUN_SCRIPT))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (GetMoveNonVolatileStatus(gCurrentMove) == MOVE_EFFECT_PARALYSIS)
|
if (GetMoveNonVolatileStatus(gCurrentMove) == MOVE_EFFECT_PARALYSIS)
|
||||||
{
|
{
|
||||||
if (CanAbilityAbsorbMove(gBattlerAttacker,
|
if (CanAbilityAbsorbMove(
|
||||||
gBattlerTarget,
|
gBattlerAttacker,
|
||||||
abilityDef,
|
gBattlerTarget,
|
||||||
gCurrentMove,
|
abilityDef,
|
||||||
GetBattleMoveType(gCurrentMove),
|
gCurrentMove,
|
||||||
ABILITY_RUN_SCRIPT))
|
GetBattleMoveType(gCurrentMove),
|
||||||
|
ABILITY_RUN_SCRIPT))
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2418,6 +2420,7 @@ static bool32 ProcessPreAttackAnimationFuncs(void)
|
|||||||
if (IsDoubleSpreadMove())
|
if (IsDoubleSpreadMove())
|
||||||
{
|
{
|
||||||
u32 moveTarget = GetBattlerMoveTargetType(gBattlerAttacker, gCurrentMove);
|
u32 moveTarget = GetBattlerMoveTargetType(gBattlerAttacker, gCurrentMove);
|
||||||
|
|
||||||
if (!gBattleStruct->printedStrongWindsWeakenedAttack)
|
if (!gBattleStruct->printedStrongWindsWeakenedAttack)
|
||||||
{
|
{
|
||||||
for (u32 battlerDef = 0; battlerDef < gBattlersCount; battlerDef++)
|
for (u32 battlerDef = 0; battlerDef < gBattlersCount; battlerDef++)
|
||||||
@ -5957,9 +5960,10 @@ static u32 GetNextTarget(u32 moveTarget, bool32 excludeCurrent)
|
|||||||
u32 battler;
|
u32 battler;
|
||||||
for (battler = 0; battler < MAX_BATTLERS_COUNT; battler++)
|
for (battler = 0; battler < MAX_BATTLERS_COUNT; battler++)
|
||||||
{
|
{
|
||||||
if (battler != gBattlerAttacker
|
if (battler == gBattlerAttacker || !IsBattlerAlive(battler))
|
||||||
&& !(excludeCurrent && battler == gBattlerTarget)
|
continue;
|
||||||
&& IsBattlerAlive(battler)
|
|
||||||
|
if (!(excludeCurrent && battler == gBattlerTarget)
|
||||||
&& !gBattleStruct->battlerState[gBattlerAttacker].targetsDone[battler]
|
&& !gBattleStruct->battlerState[gBattlerAttacker].targetsDone[battler]
|
||||||
&& (!IsBattlerAlly(battler, gBattlerAttacker) || moveTarget == MOVE_TARGET_FOES_AND_ALLY))
|
&& (!IsBattlerAlly(battler, gBattlerAttacker) || moveTarget == MOVE_TARGET_FOES_AND_ALLY))
|
||||||
break;
|
break;
|
||||||
@ -6665,8 +6669,9 @@ static void Cmd_moveend(void)
|
|||||||
MoveValuesCleanUp();
|
MoveValuesCleanUp();
|
||||||
gBattleScripting.moveEffect = gBattleScripting.savedMoveEffect;
|
gBattleScripting.moveEffect = gBattleScripting.savedMoveEffect;
|
||||||
|
|
||||||
if (moveEffect == EFFECT_EXPLOSION || moveEffect == EFFECT_MISTY_EXPLOSION)
|
if (moveEffect == EFFECT_EXPLOSION || moveEffect == EFFECT_MISTY_EXPLOSION // Edge case for Explosion not changing targets
|
||||||
BattleScriptPush(gBattleMoveEffects[EFFECT_HIT].battleScript); // Edge case for Explosion not changing targets
|
|| moveEffect == EFFECT_SYNCHRONOISE) // So we don't go back to the Synchronoise script
|
||||||
|
BattleScriptPush(gBattleMoveEffects[EFFECT_HIT].battleScript);
|
||||||
else
|
else
|
||||||
BattleScriptPush(GetMoveBattleScript(gCurrentMove));
|
BattleScriptPush(GetMoveBattleScript(gCurrentMove));
|
||||||
gBattlescriptCurrInstr = BattleScript_FlushMessageBox;
|
gBattlescriptCurrInstr = BattleScript_FlushMessageBox;
|
||||||
@ -17907,7 +17912,6 @@ void BS_JumpIfSleepClause(void)
|
|||||||
void BS_FickleBeamDamageCalculation(void)
|
void BS_FickleBeamDamageCalculation(void)
|
||||||
{
|
{
|
||||||
NATIVE_ARGS();
|
NATIVE_ARGS();
|
||||||
gBattleStruct->fickleBeamBoosted = FALSE;
|
|
||||||
|
|
||||||
if (RandomPercentage(RNG_FICKLE_BEAM, 30))
|
if (RandomPercentage(RNG_FICKLE_BEAM, 30))
|
||||||
{
|
{
|
||||||
@ -18671,3 +18675,36 @@ void BS_TryActivateAbilityShield(void)
|
|||||||
BattleScriptCall(BattleScript_AbilityShieldProtects);
|
BattleScriptCall(BattleScript_AbilityShieldProtects);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BS_TrySynchronoise(void)
|
||||||
|
{
|
||||||
|
NATIVE_ARGS(const u8 *jumpInstr);
|
||||||
|
bool32 atleastOneSharedType = FALSE;
|
||||||
|
|
||||||
|
for (u32 battlerDef = 0; battlerDef < gBattlersCount; battlerDef++)
|
||||||
|
{
|
||||||
|
if (gBattleStruct->moveResultFlags[battlerDef] & MOVE_RESULT_SYNCHRONOISE_AFFECTED
|
||||||
|
|| gBattlerAttacker == battlerDef
|
||||||
|
|| !IsBattlerAlive(battlerDef))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (DoBattlersShareType(gBattlerAttacker, battlerDef))
|
||||||
|
{
|
||||||
|
atleastOneSharedType = TRUE;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!DoBattlersShareType(gBattlerAttacker, battlerDef))
|
||||||
|
{
|
||||||
|
gBattleScripting.battler = battlerDef;
|
||||||
|
gBattleStruct->moveResultFlags[battlerDef] |= MOVE_RESULT_NO_EFFECT | MOVE_RESULT_SYNCHRONOISE_AFFECTED;
|
||||||
|
BattleScriptCall(BattleScript_ItDoesntAffectFoe);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (atleastOneSharedType)
|
||||||
|
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||||
|
else
|
||||||
|
gBattlescriptCurrInstr = cmd->jumpInstr;
|
||||||
|
}
|
||||||
|
|||||||
@ -2513,6 +2513,7 @@ static enum MoveCanceller CancellerMultiTargetMoves(void)
|
|||||||
|
|
||||||
if (gBattlerAttacker == battlerDef
|
if (gBattlerAttacker == battlerDef
|
||||||
|| !IsBattlerAlive(battlerDef)
|
|| !IsBattlerAlive(battlerDef)
|
||||||
|
|| (GetMoveEffect(gCurrentMove) == EFFECT_SYNCHRONOISE && !DoBattlersShareType(gBattlerAttacker, battlerDef))
|
||||||
|| (moveTarget == MOVE_TARGET_BOTH && gBattlerAttacker == BATTLE_PARTNER(battlerDef))
|
|| (moveTarget == MOVE_TARGET_BOTH && gBattlerAttacker == BATTLE_PARTNER(battlerDef))
|
||||||
|| IsBattlerProtected(gBattlerAttacker, battlerDef, gCurrentMove)) // Missing Invulnerable check
|
|| IsBattlerProtected(gBattlerAttacker, battlerDef, gCurrentMove)) // Missing Invulnerable check
|
||||||
{
|
{
|
||||||
@ -7914,7 +7915,7 @@ static inline u32 IsFieldMudSportAffected(u32 moveType)
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -385,7 +385,7 @@ SINGLE_BATTLE_TEST("(TERA) Synchronoise uses a Terastallized Pokemon's Tera Type
|
|||||||
} SCENE {
|
} SCENE {
|
||||||
// turn 1
|
// turn 1
|
||||||
MESSAGE("The opposing Wobbuffet used Synchronoise!");
|
MESSAGE("The opposing Wobbuffet used Synchronoise!");
|
||||||
MESSAGE("It won't have any effect on Wobbuffet!");
|
MESSAGE("It doesn't affect Wobbuffet…");
|
||||||
// turn 2
|
// turn 2
|
||||||
MESSAGE("The opposing Wobbuffet used Synchronoise!");
|
MESSAGE("The opposing Wobbuffet used Synchronoise!");
|
||||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_SYNCHRONOISE, opponent);
|
ANIMATION(ANIM_TYPE_MOVE, MOVE_SYNCHRONOISE, opponent);
|
||||||
|
|||||||
@ -1,4 +1,74 @@
|
|||||||
#include "global.h"
|
#include "global.h"
|
||||||
#include "test/battle.h"
|
#include "test/battle.h"
|
||||||
|
|
||||||
|
DOUBLE_BATTLE_TEST("Synchronoise hits all Pokemon that share a type with the attacker")
|
||||||
|
{
|
||||||
|
GIVEN {
|
||||||
|
PLAYER(SPECIES_WOBBUFFET);
|
||||||
|
PLAYER(SPECIES_WOBBUFFET);
|
||||||
|
OPPONENT(SPECIES_WOBBUFFET);
|
||||||
|
OPPONENT(SPECIES_WOBBUFFET);
|
||||||
|
} WHEN {
|
||||||
|
TURN { MOVE(playerLeft, MOVE_SYNCHRONOISE); }
|
||||||
|
} SCENE {
|
||||||
|
ANIMATION(ANIM_TYPE_MOVE, MOVE_SYNCHRONOISE, playerLeft);
|
||||||
|
HP_BAR(opponentLeft);
|
||||||
|
HP_BAR(playerRight);
|
||||||
|
HP_BAR(opponentRight);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DOUBLE_BATTLE_TEST("Synchronoise will fail if there is no corresponding typing on the field")
|
||||||
|
{
|
||||||
|
GIVEN {
|
||||||
|
PLAYER(SPECIES_WOBBUFFET);
|
||||||
|
PLAYER(SPECIES_BULBASAUR);
|
||||||
|
OPPONENT(SPECIES_BULBASAUR);
|
||||||
|
OPPONENT(SPECIES_BULBASAUR);
|
||||||
|
} WHEN {
|
||||||
|
TURN { MOVE(playerLeft, MOVE_SYNCHRONOISE); }
|
||||||
|
} SCENE {
|
||||||
|
NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_SYNCHRONOISE, playerLeft);
|
||||||
|
MESSAGE("Wobbuffet used Synchronoise!");
|
||||||
|
MESSAGE("It doesn't affect the opposing Bulbasaur…");
|
||||||
|
MESSAGE("It doesn't affect Bulbasaur…");
|
||||||
|
MESSAGE("It doesn't affect the opposing Bulbasaur…");
|
||||||
|
NOT MESSAGE("But it failed!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DOUBLE_BATTLE_TEST("Synchronoise will hit if there is at least one target")
|
||||||
|
{
|
||||||
|
GIVEN {
|
||||||
|
PLAYER(SPECIES_WOBBUFFET);
|
||||||
|
PLAYER(SPECIES_BULBASAUR);
|
||||||
|
OPPONENT(SPECIES_WOBBUFFET);
|
||||||
|
OPPONENT(SPECIES_BULBASAUR);
|
||||||
|
} WHEN {
|
||||||
|
TURN { MOVE(playerLeft, MOVE_SYNCHRONOISE); }
|
||||||
|
} SCENE {
|
||||||
|
ANIMATION(ANIM_TYPE_MOVE, MOVE_SYNCHRONOISE, playerLeft);
|
||||||
|
HP_BAR(opponentLeft);
|
||||||
|
NONE_OF {
|
||||||
|
HP_BAR(playerRight);
|
||||||
|
HP_BAR(opponentRight);
|
||||||
|
MESSAGE("But it failed!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DOUBLE_BATTLE_TEST("Synchronoise will fail if the corresponding typing mon protects")
|
||||||
|
{
|
||||||
|
GIVEN {
|
||||||
|
PLAYER(SPECIES_WOBBUFFET);
|
||||||
|
PLAYER(SPECIES_BULBASAUR);
|
||||||
|
OPPONENT(SPECIES_WOBBUFFET);
|
||||||
|
OPPONENT(SPECIES_BULBASAUR);
|
||||||
|
} WHEN {
|
||||||
|
TURN { MOVE(opponentLeft, MOVE_PROTECT); MOVE(playerLeft, MOVE_SYNCHRONOISE); }
|
||||||
|
} SCENE {
|
||||||
|
NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_SYNCHRONOISE, playerLeft);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
TO_DO_BATTLE_TEST("TODO: Write Synchronoise (Move Effect) test titles")
|
TO_DO_BATTLE_TEST("TODO: Write Synchronoise (Move Effect) test titles")
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user