mirror of
https://github.com/rh-hideout/pokeemerald-expansion.git
synced 2026-03-21 18:04:50 -05:00
Refactor synchronize and cure berry timing (#9446)
This commit is contained in:
parent
138a8f90c6
commit
0c20d91508
|
|
@ -218,20 +218,6 @@
|
|||
.4byte \jumpInstr
|
||||
.endm
|
||||
|
||||
.macro movevaluescleanup
|
||||
.byte B_SCR_OP_MOVEVALUESCLEANUP
|
||||
.endm
|
||||
|
||||
.macro setmultihit value:req
|
||||
.byte B_SCR_OP_SETMULTIHIT
|
||||
.byte \value
|
||||
.endm
|
||||
|
||||
.macro decrementmultihit loopInstr:req
|
||||
.byte B_SCR_OP_DECREMENTMULTIHIT
|
||||
.4byte \loopInstr
|
||||
.endm
|
||||
|
||||
.macro goto instr:req
|
||||
.byte B_SCR_OP_GOTO
|
||||
.4byte \instr
|
||||
|
|
@ -1214,6 +1200,10 @@
|
|||
.4byte \failInstr
|
||||
.endm
|
||||
|
||||
.macro trysynchronize
|
||||
.byte B_SCR_OP_TRY_SYNCHRONIZE
|
||||
.endm
|
||||
|
||||
.macro callnative func:req
|
||||
.byte B_SCR_OP_CALLNATIVE
|
||||
.4byte \func
|
||||
|
|
|
|||
|
|
@ -415,7 +415,6 @@ BattleScript_EffectTeatime::
|
|||
checkteatimetargets BattleScript_ButItFailed
|
||||
attackanimation
|
||||
waitanimation
|
||||
movevaluescleanup
|
||||
goto BattleScript_EffectTeatimeGetTarget
|
||||
BattleScript_EffectTeatimeNextTarget:
|
||||
jumpifnoberry BS_TARGET, BattleScript_EffectTeatimeGetTarget
|
||||
|
|
@ -1136,7 +1135,6 @@ BattleScript_FlowerShieldCheckNextTarget:
|
|||
BattleScript_FlowerShieldLoopStart:
|
||||
selectfirstvalidtarget
|
||||
BattleScript_FlowerShieldLoop:
|
||||
movevaluescleanup
|
||||
jumpifvolatile BS_TARGET, VOLATILE_SEMI_INVULNERABLE, BattleScript_FlowerShieldMoveTargetEnd
|
||||
jumpiftype BS_TARGET, TYPE_GRASS, BattleScript_FlowerShieldLoop2
|
||||
goto BattleScript_FlowerShieldMoveTargetEnd
|
||||
|
|
@ -2119,7 +2117,6 @@ BattleScript_EffectGravitySuccess::
|
|||
savetarget
|
||||
selectfirstvalidtarget
|
||||
BattleScript_GravityLoop:
|
||||
movevaluescleanup
|
||||
jumpfifsemiinvulnerable BS_TARGET, STATE_ON_AIR, BattleScript_GravityLoopDrop
|
||||
jumpifvolatile BS_TARGET, VOLATILE_MAGNET_RISE, BattleScript_GravityLoopDrop
|
||||
jumpifvolatile BS_TARGET, VOLATILE_TELEKINESIS, BattleScript_GravityLoopDrop
|
||||
|
|
@ -5828,6 +5825,8 @@ BattleScript_UpdateEffectStatusIconRet::
|
|||
updatestatusicon BS_EFFECT_BATTLER
|
||||
waitstate
|
||||
trytriggerstatusform
|
||||
trysynchronize
|
||||
tryactivateitem BS_EFFECT_BATTLER, ACTIVATION_ON_STATUS_CHANGE
|
||||
flushtextbox
|
||||
return
|
||||
|
||||
|
|
|
|||
|
|
@ -595,13 +595,12 @@ struct BattleStruct
|
|||
u32 savedBattleTypeFlags;
|
||||
u16 abilityPreventingSwitchout;
|
||||
u8 hpScale;
|
||||
u16 synchronizeMoveEffect;
|
||||
u8 anyMonHasTransformed:1; // Only used in battle_tv.c
|
||||
u8 sleepClauseNotBlocked:1;
|
||||
u8 isSkyBattle:1;
|
||||
u8 unableToUseMove:1; // for the current action only, to check if the battler failed to act at end turn use the DisableStruct member
|
||||
u8 triAttackBurn:1;
|
||||
u8 unused:3;
|
||||
enum SynchronizeState synchronizeState:3;
|
||||
void (*savedCallback)(void);
|
||||
u16 chosenItem[MAX_BATTLERS_COUNT];
|
||||
u16 choicedMove[MAX_BATTLERS_COUNT];
|
||||
|
|
|
|||
|
|
@ -5,6 +5,5 @@
|
|||
|
||||
enum CancelerResult DoAttackCanceler(void);
|
||||
enum MoveEndResult DoMoveEnd(enum MoveEndState endMode, enum MoveEndState endState);
|
||||
void MoveValuesCleanUp(void);
|
||||
|
||||
#endif // GUARD_BATTLE_MOVE_RESOLUTION_H
|
||||
|
|
|
|||
|
|
@ -46,8 +46,6 @@ enum AbilityEffect
|
|||
ABILITYEFFECT_COLOR_CHANGE, // Color Change / Berserk / Anger Shell
|
||||
ABILITYEFFECT_MOVE_END,
|
||||
ABILITYEFFECT_IMMUNITY,
|
||||
ABILITYEFFECT_SYNCHRONIZE,
|
||||
ABILITYEFFECT_ATK_SYNCHRONIZE,
|
||||
ABILITYEFFECT_FORM_CHANGE_ON_HIT,
|
||||
ABILITYEFFECT_DANCER,
|
||||
ABILITYEFFECT_MOVE_END_FOES_FAINTED, // Moxie-like abilities / Battle Bond / Magician
|
||||
|
|
|
|||
|
|
@ -83,13 +83,11 @@ enum MoveEndState
|
|||
MOVEEND_PROTECT_LIKE_EFFECT,
|
||||
MOVEEND_ABSORB,
|
||||
MOVEEND_RAGE,
|
||||
MOVEEND_SYNCHRONIZE_TARGET,
|
||||
MOVEEND_ABILITIES,
|
||||
MOVEEND_FORM_CHANGE_ON_HIT, // Disguise / Gulp Missile
|
||||
MOVEEND_ABILITIES_ATTACKER,
|
||||
MOVEEND_QUEUE_DANCER,
|
||||
MOVEEND_STATUS_IMMUNITY_ABILITIES, // TODO: Do berries come before????
|
||||
MOVEEND_SYNCHRONIZE_ATTACKER,
|
||||
MOVEEND_ATTACKER_INVISIBLE,
|
||||
MOVEEND_ATTACKER_VISIBLE,
|
||||
MOVEEND_TARGET_VISIBLE,
|
||||
|
|
|
|||
|
|
@ -39,9 +39,6 @@ enum BattleScriptOpcode
|
|||
B_SCR_OP_JUMPBASEDONTYPE,
|
||||
B_SCR_OP_GETEXP,
|
||||
B_SCR_OP_CHECKTEAMSLOST,
|
||||
B_SCR_OP_MOVEVALUESCLEANUP,
|
||||
B_SCR_OP_SETMULTIHIT,
|
||||
B_SCR_OP_DECREMENTMULTIHIT,
|
||||
B_SCR_OP_GOTO,
|
||||
B_SCR_OP_JUMPIFBYTE,
|
||||
B_SCR_OP_JUMPIFHALFWORD,
|
||||
|
|
@ -228,6 +225,7 @@ enum BattleScriptOpcode
|
|||
B_SCR_OP_JUMPIFCAPTIVATEAFFECTED,
|
||||
B_SCR_OP_SETNONVOLATILESTATUS,
|
||||
B_SCR_OP_TRYOVERWRITEABILITY,
|
||||
B_SCR_OP_TRY_SYNCHRONIZE,
|
||||
|
||||
// Expansion users, please don't use any of the unused commands.
|
||||
// They are reserved for expansion usage.
|
||||
|
|
@ -262,6 +260,8 @@ enum BattleScriptOpcode
|
|||
B_SCR_OP_UNUSED_28,
|
||||
B_SCR_OP_UNUSED_29,
|
||||
B_SCR_OP_UNUSED_30,
|
||||
B_SCR_OP_UNUSED_31,
|
||||
B_SCR_OP_UNUSED_32,
|
||||
B_SCR_OP_CALLNATIVE,
|
||||
};
|
||||
|
||||
|
|
@ -430,4 +430,13 @@ enum FlungItem
|
|||
FLUNG_ITEM_REMOVED,
|
||||
};
|
||||
|
||||
enum SynchronizeState
|
||||
{
|
||||
SYNCH_STATE_NONE,
|
||||
SYNCH_STATE_START,
|
||||
SYNCH_STATE_SET_STATUS,
|
||||
SYNCH_STATE_SHOW_ABILITY_POPUP,
|
||||
SYNCH_STATE_END,
|
||||
};
|
||||
|
||||
#endif // GUARD_CONSTANTS_BATTLE_SCRIPT_COMMANDS_H
|
||||
|
|
|
|||
|
|
@ -2244,15 +2244,6 @@ static enum MoveEndResult MoveEndRage(void)
|
|||
return result;
|
||||
}
|
||||
|
||||
static enum MoveEndResult MoveEndSynchronizeTarget(void)
|
||||
{
|
||||
enum MoveEndResult result = MOVEEND_RESULT_CONTINUE;
|
||||
if (AbilityBattleEffects(ABILITYEFFECT_SYNCHRONIZE, gBattlerTarget, 0, 0, TRUE))
|
||||
result = MOVEEND_RESULT_RUN_SCRIPT;
|
||||
gBattleScripting.moveendState++;
|
||||
return result;
|
||||
}
|
||||
|
||||
static enum MoveEndResult MoveEndAbilities(void)
|
||||
{
|
||||
enum MoveEndResult result = MOVEEND_RESULT_CONTINUE;
|
||||
|
|
@ -2330,17 +2321,6 @@ static enum MoveEndResult MoveEndStatusImmunityAbilities(void)
|
|||
return result;
|
||||
}
|
||||
|
||||
static enum MoveEndResult MoveEndSynchronizeAttacker(void)
|
||||
{
|
||||
enum MoveEndResult result = MOVEEND_RESULT_CONTINUE;
|
||||
|
||||
if (AbilityBattleEffects(ABILITYEFFECT_ATK_SYNCHRONIZE, gBattlerAttacker, 0, 0, TRUE))
|
||||
result = MOVEEND_RESULT_RUN_SCRIPT;
|
||||
|
||||
gBattleScripting.moveendState++;
|
||||
return result;
|
||||
}
|
||||
|
||||
static enum MoveEndResult MoveEndAttackerInvisible(void)
|
||||
{
|
||||
enum MoveEndResult result = MOVEEND_RESULT_CONTINUE;
|
||||
|
|
@ -2726,7 +2706,6 @@ static enum MoveEndResult MoveEndNextTarget(void)
|
|||
BattleScriptPush(GetMoveBattleScript(gCurrentMove));
|
||||
gBattlescriptCurrInstr = BattleScript_FlushMessageBox;
|
||||
gBattleScripting.moveendState = 0;
|
||||
MoveValuesCleanUp();
|
||||
return MOVEEND_RESULT_BREAK;
|
||||
}
|
||||
}
|
||||
|
|
@ -2738,7 +2717,6 @@ static enum MoveEndResult MoveEndNextTarget(void)
|
|||
{
|
||||
gBattleStruct->moveTarget[gBattlerAttacker] = gBattlerTarget = nextTarget; // Fix for moxie spread moves
|
||||
gBattleScripting.moveendState = 0;
|
||||
MoveValuesCleanUp();
|
||||
BattleScriptPush(GetMoveBattleScript(gCurrentMove));
|
||||
gBattlescriptCurrInstr = BattleScript_FlushMessageBox;
|
||||
return MOVEEND_RESULT_BREAK;
|
||||
|
|
@ -2760,7 +2738,6 @@ static enum MoveEndResult MoveEndNextTarget(void)
|
|||
gBattleScripting.moveendState = 0;
|
||||
gBattleScripting.animTurn = 0;
|
||||
gBattleScripting.animTargetsHit = 0;
|
||||
MoveValuesCleanUp();
|
||||
BattleScriptPush(GetMoveBattleScript(gCurrentMove));
|
||||
gBattlescriptCurrInstr = BattleScript_FlushMessageBox;
|
||||
return MOVEEND_RESULT_BREAK;
|
||||
|
|
@ -2829,7 +2806,6 @@ static enum MoveEndResult MoveEndMultihitMove(void)
|
|||
gBattleScripting.animTargetsHit = 0;
|
||||
gBattleScripting.moveendState = 0;
|
||||
gSpecialStatuses[gBattlerAttacker].multiHitOn = TRUE;
|
||||
MoveValuesCleanUp();
|
||||
BattleScriptPush(GetMoveBattleScript(gCurrentMove));
|
||||
gBattlescriptCurrInstr = BattleScript_FlushMessageBox;
|
||||
return MOVEEND_RESULT_BREAK;
|
||||
|
|
@ -3800,13 +3776,11 @@ static enum MoveEndResult (*const sMoveEndHandlers[])(void) =
|
|||
[MOVEEND_PROTECT_LIKE_EFFECT] = MoveEndProtectLikeEffect,
|
||||
[MOVEEND_ABSORB] = MoveEndAbsorb,
|
||||
[MOVEEND_RAGE] = MoveEndRage,
|
||||
[MOVEEND_SYNCHRONIZE_TARGET] = MoveEndSynchronizeTarget,
|
||||
[MOVEEND_ABILITIES] = MoveEndAbilities,
|
||||
[MOVEEND_FORM_CHANGE_ON_HIT] = MoveEndFormChangeOnHit,
|
||||
[MOVEEND_ABILITIES_ATTACKER] = MoveEndAbilitiesAttacker,
|
||||
[MOVEEND_QUEUE_DANCER] = MoveEndQueueDancer,
|
||||
[MOVEEND_STATUS_IMMUNITY_ABILITIES] = MoveEndStatusImmunityAbilities,
|
||||
[MOVEEND_SYNCHRONIZE_ATTACKER] = MoveEndSynchronizeAttacker,
|
||||
[MOVEEND_ATTACKER_INVISIBLE] = MoveEndAttackerInvisible,
|
||||
[MOVEEND_ATTACKER_VISIBLE] = MoveEndAttackerVisible,
|
||||
[MOVEEND_TARGET_VISIBLE] = MoveEndTargetVisible,
|
||||
|
|
@ -3949,14 +3923,6 @@ static inline bool32 IsBattlerUsingBeakBlast(enum BattlerId battler)
|
|||
return !HasBattlerActedThisTurn(battler);
|
||||
}
|
||||
|
||||
// Is there any point in still doing this?
|
||||
void MoveValuesCleanUp(void)
|
||||
{
|
||||
gBattleScripting.moveEffect = MOVE_EFFECT_NONE;
|
||||
gBattleStruct->synchronizeMoveEffect = MOVE_EFFECT_NONE;
|
||||
gBattleCommunication[MISS_TYPE] = 0;
|
||||
}
|
||||
|
||||
static void RequestNonVolatileChange(enum BattlerId battlerAtk)
|
||||
{
|
||||
BtlController_EmitSetMonData(
|
||||
|
|
|
|||
|
|
@ -389,9 +389,6 @@ static void Cmd_jumpifstatignorecontrary(void);
|
|||
static void Cmd_jumpbasedontype(void);
|
||||
static void Cmd_getexp(void);
|
||||
static void Cmd_checkteamslost(void);
|
||||
static void Cmd_movevaluescleanup(void);
|
||||
static void Cmd_setmultihit(void);
|
||||
static void Cmd_decrementmultihit(void);
|
||||
static void Cmd_goto(void);
|
||||
static void Cmd_jumpifbyte(void);
|
||||
static void Cmd_jumpifhalfword(void);
|
||||
|
|
@ -578,6 +575,7 @@ static void Cmd_averagestats(void);
|
|||
static void Cmd_jumpifcaptivateaffected(void);
|
||||
static void Cmd_setnonvolatilestatus(void);
|
||||
static void Cmd_tryoverwriteability(void);
|
||||
static void Cmd_trysynchronize(void);
|
||||
static void Cmd_dummy(void);
|
||||
static void Cmd_callnative(void);
|
||||
|
||||
|
|
@ -619,9 +617,6 @@ void (*const gBattleScriptingCommandsTable[])(void) =
|
|||
[B_SCR_OP_JUMPBASEDONTYPE] = Cmd_jumpbasedontype,
|
||||
[B_SCR_OP_GETEXP] = Cmd_getexp,
|
||||
[B_SCR_OP_CHECKTEAMSLOST] = Cmd_checkteamslost,
|
||||
[B_SCR_OP_MOVEVALUESCLEANUP] = Cmd_movevaluescleanup,
|
||||
[B_SCR_OP_SETMULTIHIT] = Cmd_setmultihit,
|
||||
[B_SCR_OP_DECREMENTMULTIHIT] = Cmd_decrementmultihit,
|
||||
[B_SCR_OP_GOTO] = Cmd_goto,
|
||||
[B_SCR_OP_JUMPIFBYTE] = Cmd_jumpifbyte,
|
||||
[B_SCR_OP_JUMPIFHALFWORD] = Cmd_jumpifhalfword,
|
||||
|
|
@ -808,6 +803,7 @@ void (*const gBattleScriptingCommandsTable[])(void) =
|
|||
[B_SCR_OP_JUMPIFCAPTIVATEAFFECTED] = Cmd_jumpifcaptivateaffected,
|
||||
[B_SCR_OP_SETNONVOLATILESTATUS] = Cmd_setnonvolatilestatus,
|
||||
[B_SCR_OP_TRYOVERWRITEABILITY] = Cmd_tryoverwriteability,
|
||||
[B_SCR_OP_TRY_SYNCHRONIZE] = Cmd_trysynchronize,
|
||||
[B_SCR_OP_UNUSED_1] = Cmd_dummy,
|
||||
[B_SCR_OP_UNUSED_2] = Cmd_dummy,
|
||||
[B_SCR_OP_UNUSED_3] = Cmd_dummy,
|
||||
|
|
@ -838,6 +834,8 @@ void (*const gBattleScriptingCommandsTable[])(void) =
|
|||
[B_SCR_OP_UNUSED_28] = Cmd_dummy,
|
||||
[B_SCR_OP_UNUSED_29] = Cmd_dummy,
|
||||
[B_SCR_OP_UNUSED_30] = Cmd_dummy,
|
||||
[B_SCR_OP_UNUSED_31] = Cmd_dummy,
|
||||
[B_SCR_OP_UNUSED_32] = Cmd_dummy,
|
||||
[B_SCR_OP_CALLNATIVE] = Cmd_callnative,
|
||||
};
|
||||
|
||||
|
|
@ -2285,7 +2283,41 @@ static inline bool32 TrySetLightScreen(enum BattlerId battler)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
static void SetNonVolatileStatus(enum BattlerId effectBattler, enum MoveEffect effect, const u8 *battleScript, enum StatusTrigger trigger)
|
||||
static void TrySynchronizeActivation(enum BattlerId battlerAtk, enum BattlerId effectBattler, enum MoveEffect effect)
|
||||
{
|
||||
if (battlerAtk == effectBattler || gBattleStruct->synchronizeState == SYNCH_STATE_SET_STATUS)
|
||||
return;
|
||||
|
||||
enum Ability effectAbility = GetBattlerAbility(effectBattler);
|
||||
if (effectAbility != ABILITY_SYNCHRONIZE)
|
||||
return;
|
||||
|
||||
if (effect == MOVE_EFFECT_POISON
|
||||
|| effect == MOVE_EFFECT_TOXIC
|
||||
|| effect == MOVE_EFFECT_PARALYSIS
|
||||
|| effect == MOVE_EFFECT_BURN)
|
||||
{
|
||||
if (CanSetNonVolatileStatus(
|
||||
effectBattler,
|
||||
battlerAtk,
|
||||
effectAbility,
|
||||
GetBattlerAbility(battlerAtk),
|
||||
effect,
|
||||
CHECK_TRIGGER))
|
||||
{
|
||||
gBattleStruct->synchronizeState = SYNCH_STATE_START;
|
||||
gBattlerAbility = effectBattler;
|
||||
gBattleScripting.savedBattler = battlerAtk;
|
||||
}
|
||||
else
|
||||
{
|
||||
gBattleStruct->synchronizeState = SYNCH_STATE_SHOW_ABILITY_POPUP;
|
||||
gBattlerAbility = effectBattler;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void SetNonVolatileStatus(enum BattlerId battlerAtk, enum BattlerId effectBattler, enum MoveEffect effect, const u8 *battleScript, enum StatusTrigger trigger)
|
||||
{
|
||||
gEffectBattler = effectBattler;
|
||||
|
||||
|
|
@ -2350,12 +2382,7 @@ static void SetNonVolatileStatus(enum BattlerId effectBattler, enum MoveEffect e
|
|||
|
||||
gBattleScripting.moveEffect = MOVE_EFFECT_NONE;
|
||||
|
||||
// for synchronize
|
||||
if (effect == MOVE_EFFECT_POISON
|
||||
|| effect == MOVE_EFFECT_TOXIC
|
||||
|| effect == MOVE_EFFECT_PARALYSIS
|
||||
|| effect == MOVE_EFFECT_BURN)
|
||||
gBattleStruct->synchronizeMoveEffect = effect;
|
||||
TrySynchronizeActivation(battlerAtk, effectBattler, effect);
|
||||
|
||||
if (effect == MOVE_EFFECT_POISON || effect == MOVE_EFFECT_TOXIC)
|
||||
gBattleStruct->poisonPuppeteerConfusion = TRUE;
|
||||
|
|
@ -2483,7 +2510,7 @@ void SetMoveEffect(enum BattlerId battlerAtk, enum BattlerId effectBattler, enum
|
|||
moveEffect,
|
||||
CHECK_TRIGGER))
|
||||
{
|
||||
SetNonVolatileStatus(gEffectBattler, moveEffect, battleScript, TRIGGER_ON_MOVE);
|
||||
SetNonVolatileStatus(gBattlerAttacker, gEffectBattler, moveEffect, battleScript, TRIGGER_ON_MOVE);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -4621,32 +4648,6 @@ static void Cmd_checkteamslost(void)
|
|||
}
|
||||
}
|
||||
|
||||
static void Cmd_movevaluescleanup(void)
|
||||
{
|
||||
CMD_ARGS();
|
||||
|
||||
MoveValuesCleanUp();
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
}
|
||||
|
||||
static void Cmd_setmultihit(void)
|
||||
{
|
||||
CMD_ARGS(u8 value);
|
||||
|
||||
gMultiHitCounter = cmd->value;
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
}
|
||||
|
||||
static void Cmd_decrementmultihit(void)
|
||||
{
|
||||
CMD_ARGS(const u8 *loopInstr);
|
||||
|
||||
if (--gMultiHitCounter == 0)
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
else
|
||||
gBattlescriptCurrInstr = cmd->loopInstr;
|
||||
}
|
||||
|
||||
static void Cmd_goto(void)
|
||||
{
|
||||
CMD_ARGS(const u8 *instr);
|
||||
|
|
@ -9380,21 +9381,17 @@ static void Cmd_tryactivateitem(void)
|
|||
{
|
||||
case ACTIVATION_ON_USABLE_AGAIN:
|
||||
case ACTIVATION_ON_PICK_UP:
|
||||
if (ItemBattleEffects(battler, 0, GetBattlerHoldEffect(battler), IsForceTriggerItemActivation))
|
||||
return;
|
||||
ItemBattleEffects(battler, 0, GetBattlerHoldEffect(battler), IsForceTriggerItemActivation);
|
||||
break;
|
||||
case ACTIVATION_ON_HARVEST:
|
||||
gLastUsedItem = gBattleMons[battler].item;
|
||||
if (ItemBattleEffects(battler, 0, GetBattlerHoldEffect(battler), IsOnBerryActivation))
|
||||
return;
|
||||
ItemBattleEffects(battler, 0, GetBattlerHoldEffect(battler), IsOnBerryActivation);
|
||||
break;
|
||||
case ACTIVATION_ON_HP_THRESHOLD:
|
||||
if (ItemBattleEffects(battler, 0, GetBattlerHoldEffect(battler), IsOnHpThresholdActivation))
|
||||
return;
|
||||
ItemBattleEffects(battler, 0, GetBattlerHoldEffect(battler), IsOnHpThresholdActivation);
|
||||
break;
|
||||
case ACTIVATION_ON_STATUS_CHANGE:
|
||||
if (ItemBattleEffects(battler, 0, GetBattlerHoldEffect(battler), IsOnStatusChangeActivation))
|
||||
return;
|
||||
ItemBattleEffects(battler, 0, GetBattlerHoldEffect(battler), IsOnStatusChangeActivation);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -11540,13 +11537,13 @@ static void Cmd_setnonvolatilestatus(void)
|
|||
if (gBattleScripting.moveEffect >= MOVE_EFFECT_CONFUSION)
|
||||
SetMoveEffect(gBattleScripting.battler, gEffectBattler, gBattleScripting.moveEffect, cmd->nextInstr, EFFECT_PRIMARY);
|
||||
else
|
||||
SetNonVolatileStatus(gEffectBattler, gBattleScripting.moveEffect, cmd->nextInstr, TRIGGER_ON_ABILITY);
|
||||
SetNonVolatileStatus(gBattleScripting.battler, gEffectBattler, gBattleScripting.moveEffect, cmd->nextInstr, TRIGGER_ON_ABILITY);
|
||||
break;
|
||||
case TRIGGER_ON_MOVE:
|
||||
SetNonVolatileStatus(gBattlerTarget, GetMoveNonVolatileStatus(gCurrentMove), cmd->nextInstr, TRIGGER_ON_MOVE);
|
||||
SetNonVolatileStatus(gBattlerAttacker, gBattlerTarget, GetMoveNonVolatileStatus(gCurrentMove), cmd->nextInstr, TRIGGER_ON_MOVE);
|
||||
break;
|
||||
case TRIGGER_ON_PROTECT:
|
||||
SetNonVolatileStatus(gBattlerAttacker, gBattleScripting.moveEffect, cmd->nextInstr, TRIGGER_ON_PROTECT);
|
||||
SetNonVolatileStatus(gBattlerTarget, gBattlerAttacker, gBattleScripting.moveEffect, cmd->nextInstr, TRIGGER_ON_PROTECT);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -11578,6 +11575,63 @@ static void Cmd_tryoverwriteability(void)
|
|||
}
|
||||
}
|
||||
|
||||
static u32 GetMoveEffectFromStatus(enum BattlerId battler)
|
||||
{
|
||||
switch (gBattleMons[battler].status1)
|
||||
{
|
||||
case STATUS1_POISON:
|
||||
return MOVE_EFFECT_POISON;
|
||||
case STATUS1_TOXIC_POISON:
|
||||
return MOVE_EFFECT_TOXIC;
|
||||
case STATUS1_PARALYSIS:
|
||||
return MOVE_EFFECT_PARALYSIS;
|
||||
case STATUS1_BURN:
|
||||
return MOVE_EFFECT_BURN;
|
||||
default:
|
||||
return MOVE_EFFECT_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
static void Cmd_trysynchronize(void)
|
||||
{
|
||||
CMD_ARGS();
|
||||
enum MoveEffect synchStatus = MOVE_EFFECT_NONE;
|
||||
|
||||
switch (gBattleStruct->synchronizeState)
|
||||
{
|
||||
case SYNCH_STATE_NONE:
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
break;
|
||||
case SYNCH_STATE_START:
|
||||
synchStatus = GetMoveEffectFromStatus(gBattlerAbility);
|
||||
RecordAbilityBattle(gBattlerAbility, ABILITY_SYNCHRONIZE);
|
||||
|
||||
if (GetConfig(B_SYNCHRONIZE_TOXIC) < GEN_5 && synchStatus == MOVE_EFFECT_TOXIC)
|
||||
synchStatus = MOVE_EFFECT_POISON;
|
||||
|
||||
gBattleScripting.battler = gBattlerAbility;
|
||||
gEffectBattler = gBattleScripting.savedBattler;
|
||||
gBattleScripting.moveEffect = synchStatus;
|
||||
gBattleStruct->synchronizeState = SYNCH_STATE_SET_STATUS;
|
||||
PREPARE_ABILITY_BUFFER(gBattleTextBuff1, ABILITY_SYNCHRONIZE);
|
||||
BattleScriptCall(BattleScript_SynchronizeActivates);
|
||||
break;
|
||||
case SYNCH_STATE_SHOW_ABILITY_POPUP: // Synchronize ability pop up still shows up even if status fails
|
||||
gBattleStruct->synchronizeState = SYNCH_STATE_END;
|
||||
BattleScriptCall(BattleScript_AbilityPopUp);
|
||||
break;
|
||||
case SYNCH_STATE_SET_STATUS: // Extra step to skip trysynchronize for battler the status is inflicted on, so gEffectBattler isn't assigned to early
|
||||
gBattleStruct->synchronizeState = SYNCH_STATE_END;
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
break;
|
||||
case SYNCH_STATE_END:
|
||||
gBattleStruct->synchronizeState = SYNCH_STATE_NONE;
|
||||
gEffectBattler = gBattlerAbility; // Restore effect battler that was previously set to the synchronize battler
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void Cmd_dummy(void)
|
||||
{
|
||||
}
|
||||
|
|
@ -13053,7 +13107,7 @@ void BS_SwapStats(void)
|
|||
static void TrySetParalysis(const u8 *nextInstr, const u8 *failInstr)
|
||||
{
|
||||
if (CanBeParalyzed(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerTarget)))
|
||||
SetNonVolatileStatus(gBattlerTarget, MOVE_EFFECT_PARALYSIS, nextInstr, TRIGGER_ON_MOVE);
|
||||
SetNonVolatileStatus(gBattlerAttacker, gBattlerTarget, MOVE_EFFECT_PARALYSIS, nextInstr, TRIGGER_ON_MOVE);
|
||||
else
|
||||
gBattlescriptCurrInstr = failInstr;
|
||||
}
|
||||
|
|
@ -13061,7 +13115,7 @@ static void TrySetParalysis(const u8 *nextInstr, const u8 *failInstr)
|
|||
static void TrySetPoison(const u8 *nextInstr, const u8 *failInstr)
|
||||
{
|
||||
if (CanBePoisoned(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerAttacker), GetBattlerAbility(gBattlerTarget)))
|
||||
SetNonVolatileStatus(gBattlerTarget, MOVE_EFFECT_POISON, nextInstr, TRIGGER_ON_MOVE);
|
||||
SetNonVolatileStatus(gBattlerAttacker, gBattlerTarget, MOVE_EFFECT_POISON, nextInstr, TRIGGER_ON_MOVE);
|
||||
else
|
||||
gBattlescriptCurrInstr = failInstr;
|
||||
}
|
||||
|
|
@ -13069,7 +13123,7 @@ static void TrySetPoison(const u8 *nextInstr, const u8 *failInstr)
|
|||
static void TrySetSleep(const u8 *nextInstr, const u8 *failInstr)
|
||||
{
|
||||
if (CanBeSlept(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerTarget), BLOCKED_BY_SLEEP_CLAUSE))
|
||||
SetNonVolatileStatus(gBattlerTarget, MOVE_EFFECT_SLEEP, nextInstr, TRIGGER_ON_MOVE);
|
||||
SetNonVolatileStatus(gBattlerAttacker, gBattlerTarget, MOVE_EFFECT_SLEEP, nextInstr, TRIGGER_ON_MOVE);
|
||||
else
|
||||
gBattlescriptCurrInstr = failInstr;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -897,7 +897,6 @@ void HandleAction_NothingIsFainted(void)
|
|||
{
|
||||
gCurrentTurnActionNumber++;
|
||||
gCurrentActionFuncId = gActionsByTurnOrder[gCurrentTurnActionNumber];
|
||||
gBattleStruct->synchronizeMoveEffect = MOVE_EFFECT_NONE;
|
||||
}
|
||||
|
||||
void HandleAction_ActionFinished(void)
|
||||
|
|
@ -920,7 +919,6 @@ void HandleAction_ActionFinished(void)
|
|||
gBattleCommunication[3] = 0;
|
||||
gBattleCommunication[4] = 0;
|
||||
gBattleResources->battleScriptsStack->size = 0;
|
||||
gBattleStruct->synchronizeMoveEffect = MOVE_EFFECT_NONE;
|
||||
|
||||
if (GetConfig(B_RECALC_TURN_AFTER_ACTIONS) >= GEN_8 && !afterYouActive && !gBattleStruct->pledgeMove && !IsPursuitTargetSet())
|
||||
{
|
||||
|
|
@ -4650,69 +4648,6 @@ u32 AbilityBattleEffects(enum AbilityEffect caseID, enum BattlerId battler, enum
|
|||
if (effect)
|
||||
return effect;
|
||||
break;
|
||||
case ABILITYEFFECT_SYNCHRONIZE:
|
||||
if (gLastUsedAbility == ABILITY_SYNCHRONIZE && gBattleStruct->synchronizeMoveEffect != MOVE_EFFECT_NONE)
|
||||
{
|
||||
gBattleScripting.battler = gBattlerAbility = gBattlerTarget;
|
||||
RecordAbilityBattle(gBattlerTarget, ABILITY_SYNCHRONIZE);
|
||||
|
||||
if (GetConfig(B_SYNCHRONIZE_TOXIC) < GEN_5 && gBattleStruct->synchronizeMoveEffect == MOVE_EFFECT_TOXIC)
|
||||
gBattleStruct->synchronizeMoveEffect = MOVE_EFFECT_POISON;
|
||||
|
||||
if (CanSetNonVolatileStatus(
|
||||
gBattlerTarget,
|
||||
gBattlerAttacker,
|
||||
gLastUsedAbility,
|
||||
GetBattlerAbility(gBattlerAttacker),
|
||||
gBattleStruct->synchronizeMoveEffect,
|
||||
CHECK_TRIGGER))
|
||||
{
|
||||
gEffectBattler = gBattlerAttacker;
|
||||
gBattleScripting.moveEffect = gBattleStruct->synchronizeMoveEffect;
|
||||
PREPARE_ABILITY_BUFFER(gBattleTextBuff1, ABILITY_SYNCHRONIZE);
|
||||
BattleScriptCall(BattleScript_SynchronizeActivates);
|
||||
effect++;
|
||||
}
|
||||
else // Synchronize ability pop up still shows up even if status fails
|
||||
{
|
||||
BattleScriptCall(BattleScript_AbilityPopUp);
|
||||
}
|
||||
gBattleStruct->synchronizeMoveEffect = MOVE_EFFECT_NONE;
|
||||
}
|
||||
break;
|
||||
case ABILITYEFFECT_ATK_SYNCHRONIZE:
|
||||
if (gLastUsedAbility == ABILITY_SYNCHRONIZE && gBattleStruct->synchronizeMoveEffect != MOVE_EFFECT_NONE)
|
||||
{
|
||||
gBattleScripting.battler = gBattlerAbility = gBattlerAttacker;
|
||||
RecordAbilityBattle(gBattlerAttacker, ABILITY_SYNCHRONIZE);
|
||||
|
||||
if (GetConfig(B_SYNCHRONIZE_TOXIC) < GEN_5 && gBattleStruct->synchronizeMoveEffect == MOVE_EFFECT_TOXIC)
|
||||
gBattleStruct->synchronizeMoveEffect = MOVE_EFFECT_POISON;
|
||||
|
||||
if (CanSetNonVolatileStatus(
|
||||
gBattlerAttacker,
|
||||
gBattlerTarget,
|
||||
gLastUsedAbility,
|
||||
GetBattlerAbility(gBattlerAttacker),
|
||||
gBattleStruct->synchronizeMoveEffect,
|
||||
CHECK_TRIGGER))
|
||||
{
|
||||
if (gBattleStruct->synchronizeMoveEffect == MOVE_EFFECT_TOXIC)
|
||||
gBattleStruct->synchronizeMoveEffect = MOVE_EFFECT_POISON;
|
||||
|
||||
gEffectBattler = gBattlerTarget;
|
||||
gBattleScripting.moveEffect = gBattleStruct->synchronizeMoveEffect;
|
||||
PREPARE_ABILITY_BUFFER(gBattleTextBuff1, ABILITY_SYNCHRONIZE);
|
||||
BattleScriptCall(BattleScript_SynchronizeActivates);
|
||||
effect++;
|
||||
}
|
||||
else // Synchronize ability pop up still shows up even if status fails
|
||||
{
|
||||
BattleScriptCall(BattleScript_AbilityPopUp);
|
||||
}
|
||||
gBattleStruct->synchronizeMoveEffect = MOVE_EFFECT_NONE;
|
||||
}
|
||||
break;
|
||||
case ABILITYEFFECT_TERA_SHIFT:
|
||||
if (TryBattleFormChange(battler, FORM_CHANGE_BATTLE_SWITCH_IN, ability))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -73,3 +73,59 @@ SINGLE_BATTLE_TEST("Synchronize will mirror back static activation")
|
|||
STATUS_ICON(player, paralysis: TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
DOUBLE_BATTLE_TEST("Synchronize will trigger on both targets")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(MoveHasAdditionalEffect(MOVE_MORTAL_SPIN, MOVE_EFFECT_POISON));
|
||||
PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_LUM_BERRY); }
|
||||
PLAYER(SPECIES_WYNAUT);
|
||||
OPPONENT(SPECIES_ABRA) { Item(ITEM_LUM_BERRY); Ability(ABILITY_SYNCHRONIZE); }
|
||||
OPPONENT(SPECIES_ABRA) { Item(ITEM_LUM_BERRY); Ability(ABILITY_SYNCHRONIZE); }
|
||||
} WHEN {
|
||||
TURN { MOVE(playerLeft, MOVE_MORTAL_SPIN); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_MORTAL_SPIN, playerLeft);
|
||||
HP_BAR(opponentLeft);
|
||||
HP_BAR(opponentRight);
|
||||
ABILITY_POPUP(opponentLeft, ABILITY_SYNCHRONIZE);
|
||||
ABILITY_POPUP(opponentRight, ABILITY_SYNCHRONIZE);
|
||||
} THEN {
|
||||
EXPECT_EQ(gBattleMons[B_BATTLER_0].status1, STATUS1_POISON);
|
||||
EXPECT_EQ(gBattleMons[B_BATTLER_1].status1, STATUS1_NONE);
|
||||
EXPECT_EQ(gBattleMons[B_BATTLER_3].status1, STATUS1_NONE);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Synchronize can trigger again during the same attack if user cured it's status")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(MoveHasAdditionalEffect(MOVE_MORTAL_SPIN, MOVE_EFFECT_POISON));
|
||||
ASSUME(MoveMakesContact(MOVE_MORTAL_SPIN));
|
||||
PLAYER(SPECIES_SEISMITOAD) { Ability(ABILITY_POISON_TOUCH); Item(ITEM_LUM_BERRY); }
|
||||
OPPONENT(SPECIES_ABRA) { Ability(ABILITY_SYNCHRONIZE); Item(ITEM_LUM_BERRY); }
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_MORTAL_SPIN); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_MORTAL_SPIN, player);
|
||||
|
||||
ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_PSN, opponent);
|
||||
STATUS_ICON(opponent, poison: TRUE);
|
||||
ABILITY_POPUP(opponent, ABILITY_SYNCHRONIZE);
|
||||
|
||||
ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_PSN, player);
|
||||
STATUS_ICON(player, poison: TRUE);
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player);
|
||||
STATUS_ICON(player, poison: FALSE);
|
||||
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, opponent);
|
||||
STATUS_ICON(opponent, poison: FALSE);
|
||||
|
||||
ABILITY_POPUP(player, ABILITY_POISON_TOUCH);
|
||||
STATUS_ICON(opponent, poison: TRUE);
|
||||
ABILITY_POPUP(opponent, ABILITY_SYNCHRONIZE);
|
||||
STATUS_ICON(player, poison: TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user