mirror of
https://github.com/rh-hideout/pokeemerald-expansion.git
synced 2026-03-21 18:04:50 -05:00
Fixes Lock On (#9496)
This commit is contained in:
parent
d2cb9eb14b
commit
726588b8b0
|
|
@ -211,7 +211,7 @@ enum VolatileFlags
|
|||
F(VOLATILE_STICKY_SYRUPED_BY, stickySyrupedBy, (enum BattlerId, MAX_BITS(MAX_BATTLERS_COUNT))) \
|
||||
F(VOLATILE_GLAIVE_RUSH, glaiveRush, (u32, 1)) \
|
||||
F(VOLATILE_LEECH_SEED, leechSeed, (enum BattlerId, MAX_BITS(MAX_BATTLERS_COUNT)), V_BATON_PASSABLE) \
|
||||
F(VOLATILE_LOCK_ON, lockOn, (u32, 2), V_BATON_PASSABLE) \
|
||||
F(VOLATILE_LOCK_ON, lockOn, (u32, 2)) \
|
||||
F(VOLATILE_PERISH_SONG, perishSong, (u32, 1), V_BATON_PASSABLE) \
|
||||
F(VOLATILE_MINIMIZE, minimize, (u32, 1)) \
|
||||
F(VOLATILE_CHARGE_TIMER, chargeTimer, (u32, 3)) \
|
||||
|
|
@ -254,7 +254,7 @@ enum VolatileFlags
|
|||
F(VOLATILE_FURY_CUTTER_COUNTER, furyCutterCounter, (u32, UINT8_MAX)) \
|
||||
F(VOLATILE_METRONOME_ITEM_COUNTER, metronomeItemCounter, (u32, UINT8_MAX)) \
|
||||
F(VOLATILE_BATTLER_PREVENTING_ESCAPE, battlerPreventingEscape, (enum BattlerId, MAX_BITS(MAX_BATTLERS_COUNT))) \
|
||||
F(VOLATILE_BATTLER_WITH_SURE_HIT, battlerWithSureHit, (enum BattlerId, MAX_BITS(MAX_BATTLERS_COUNT))) \
|
||||
F(VOLATILE_BATTLER_WITH_SURE_HIT, battlerWithSureHit, (enum BattlerId, MAX_BATTLERS_COUNT)) \
|
||||
F(VOLATILE_MIMICKED_MOVES, mimickedMoves, (u32, MAX_BITS(MAX_MON_MOVES))) \
|
||||
F(VOLATILE_RECHARGE_TIMER, rechargeTimer, (u32, 2)) \
|
||||
F(VOLATILE_AUTOTOMIZE_COUNT, autotomizeCount, (u32, UINT8_MAX)) \
|
||||
|
|
|
|||
|
|
@ -2321,7 +2321,7 @@ static s32 AI_CheckBadMove(enum BattlerId battlerAtk, enum BattlerId battlerDef,
|
|||
//TODO
|
||||
break;
|
||||
case EFFECT_LOCK_ON:
|
||||
if (gBattleMons[battlerDef].volatiles.lockOn
|
||||
if (gBattleMons[battlerAtk].volatiles.battlerWithSureHit == battlerDef + 1
|
||||
|| aiData->abilities[battlerAtk] == ABILITY_NO_GUARD
|
||||
|| aiData->abilities[battlerDef] == ABILITY_NO_GUARD
|
||||
|| DoesPartnerHaveSameMoveEffect(BATTLE_PARTNER(battlerAtk), battlerDef, move, aiData->partnerMove))
|
||||
|
|
@ -4696,7 +4696,7 @@ static s32 AI_CalcMoveEffectScore(enum BattlerId battlerAtk, enum BattlerId batt
|
|||
case EFFECT_OHKO:
|
||||
if (GetActiveGimmick(battlerDef) == GIMMICK_DYNAMAX)
|
||||
break;
|
||||
else if (gBattleMons[battlerAtk].volatiles.lockOn)
|
||||
else if (gBattleMons[battlerAtk].volatiles.battlerWithSureHit == battlerDef + 1)
|
||||
ADJUST_SCORE(BEST_EFFECT);
|
||||
break;
|
||||
case EFFECT_MEAN_LOOK:
|
||||
|
|
|
|||
|
|
@ -1356,7 +1356,7 @@ enum MoveComparisonResult CompareMoveEffects(enum Move move1, enum Move move2, e
|
|||
return MOVE_WON_COMPARISON;
|
||||
if (effect1minus && !effect2minus)
|
||||
return MOVE_LOST_COMPARISON;
|
||||
|
||||
|
||||
if (effect2plus && !effect1plus)
|
||||
return MOVE_LOST_COMPARISON;
|
||||
if (effect1plus && !effect2plus)
|
||||
|
|
@ -2177,10 +2177,8 @@ bool32 ShouldTryOHKO(enum BattlerId battlerAtk, enum BattlerId battlerDef, enum
|
|||
if (!DoesBattlerIgnoreAbilityChecks(battlerAtk, atkAbility, move) && defAbility == ABILITY_STURDY)
|
||||
return FALSE;
|
||||
|
||||
if (((gBattleMons[battlerDef].volatiles.lockOn
|
||||
&& gBattleMons[battlerDef].volatiles.battlerWithSureHit == battlerAtk)
|
||||
|| atkAbility == ABILITY_NO_GUARD || defAbility == ABILITY_NO_GUARD)
|
||||
&& gBattleMons[battlerAtk].level >= gBattleMons[battlerDef].level)
|
||||
bool32 sureHit = (gBattleMons[battlerAtk].volatiles.battlerWithSureHit == battlerDef + 1) || atkAbility == ABILITY_NO_GUARD || defAbility == ABILITY_NO_GUARD;
|
||||
if (sureHit && gBattleMons[battlerAtk].level >= gBattleMons[battlerDef].level)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -60,8 +60,8 @@ static bool32 HandleEndTurnVarious(enum BattlerId battler)
|
|||
if (gBattleMons[i].volatiles.throatChopTimer > 0)
|
||||
gBattleMons[i].volatiles.throatChopTimer--;
|
||||
|
||||
if (gBattleMons[i].volatiles.lockOn > 0)
|
||||
gBattleMons[i].volatiles.lockOn--;
|
||||
if (gBattleMons[i].volatiles.lockOn > 0 && --gBattleMons[i].volatiles.lockOn == 0)
|
||||
gBattleMons[i].volatiles.battlerWithSureHit = 0;
|
||||
|
||||
if (B_CHARGE < GEN_9 && gBattleMons[i].volatiles.chargeTimer > 0)
|
||||
gBattleMons[i].volatiles.chargeTimer--;
|
||||
|
|
|
|||
|
|
@ -3185,11 +3185,9 @@ void SwitchInClearSetData(enum BattlerId battler, struct Volatiles *volatilesCop
|
|||
{
|
||||
if (gBattleMons[i].volatiles.escapePrevention && gBattleMons[i].volatiles.battlerPreventingEscape == battler)
|
||||
gBattleMons[i].volatiles.escapePrevention = FALSE;
|
||||
if (gBattleMons[i].volatiles.lockOn && gBattleMons[i].volatiles.battlerWithSureHit == battler)
|
||||
{
|
||||
gBattleMons[i].volatiles.lockOn = 0;
|
||||
|
||||
if (gBattleMons[i].volatiles.battlerWithSureHit == battler + 1)
|
||||
gBattleMons[i].volatiles.battlerWithSureHit = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (effect != EFFECT_BATON_PASS || GetConfig(B_BATON_PASS_TRAPPING) >= GEN_5)
|
||||
|
|
@ -3215,15 +3213,6 @@ void SwitchInClearSetData(enum BattlerId battler, struct Volatiles *volatilesCop
|
|||
*/
|
||||
|
||||
enum BattlerId i;
|
||||
for (i = 0; i < gBattlersCount; i++)
|
||||
{
|
||||
if (!IsBattlerAlly(battler, i)
|
||||
&& gBattleMons[i].volatiles.lockOn != 0
|
||||
&& (gBattleMons[i].volatiles.battlerWithSureHit == battler))
|
||||
{
|
||||
gBattleMons[i].volatiles.lockOn = 0;
|
||||
}
|
||||
}
|
||||
if (gBattleMons[battler].volatiles.powerTrick)
|
||||
SWAP(gBattleMons[battler].attack, gBattleMons[battler].defense, i);
|
||||
}
|
||||
|
|
@ -3249,7 +3238,6 @@ void SwitchInClearSetData(enum BattlerId battler, struct Volatiles *volatilesCop
|
|||
if (effect == EFFECT_BATON_PASS)
|
||||
{
|
||||
gBattleMons[battler].volatiles.substituteHP = volatilesCopy->substituteHP;
|
||||
gBattleMons[battler].volatiles.battlerWithSureHit = volatilesCopy->battlerWithSureHit;
|
||||
gBattleMons[battler].volatiles.perishSongTimer = volatilesCopy->perishSongTimer;
|
||||
gBattleMons[battler].volatiles.battlerPreventingEscape = volatilesCopy->battlerPreventingEscape;
|
||||
gBattleMons[battler].volatiles.embargoTimer = volatilesCopy->embargoTimer;
|
||||
|
|
@ -3343,6 +3331,8 @@ const u8* FaintClearSetData(enum BattlerId battler)
|
|||
|
||||
for (enum BattlerId i = 0; i < gBattlersCount; i++)
|
||||
{
|
||||
if (gBattleMons[i].volatiles.battlerWithSureHit == battler + 1)
|
||||
gBattleMons[i].volatiles.battlerWithSureHit = 0;
|
||||
if (gBattleMons[i].volatiles.escapePrevention && gBattleMons[i].volatiles.battlerPreventingEscape == battler)
|
||||
gBattleMons[i].volatiles.escapePrevention = FALSE;
|
||||
if (gBattleMons[i].volatiles.infatuation == INFATUATED_WITH(battler))
|
||||
|
|
|
|||
|
|
@ -8897,9 +8897,17 @@ static void Cmd_settypetorandomresistance(void)
|
|||
static void Cmd_setalwayshitflag(void)
|
||||
{
|
||||
CMD_ARGS();
|
||||
gBattleMons[gBattlerTarget].volatiles.lockOn = 2;
|
||||
gBattleMons[gBattlerTarget].volatiles.battlerWithSureHit = gBattlerAttacker;
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
|
||||
if (gBattleMons[gBattlerAttacker].volatiles.battlerWithSureHit == 0)
|
||||
{
|
||||
gBattleMons[gBattlerAttacker].volatiles.lockOn = 2;
|
||||
gBattleMons[gBattlerAttacker].volatiles.battlerWithSureHit = gBattlerTarget + 1;
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
}
|
||||
else
|
||||
{
|
||||
gBattlescriptCurrInstr = BattleScript_ButItFailed;
|
||||
}
|
||||
}
|
||||
|
||||
// Sketch
|
||||
|
|
|
|||
|
|
@ -10309,7 +10309,7 @@ bool32 CanMoveSkipAccuracyCalc(enum BattlerId battlerAtk, enum BattlerId battler
|
|||
enum Ability ability = ABILITY_NONE;
|
||||
enum BattleMoveEffects moveEffect = GetMoveEffect(move);
|
||||
|
||||
if ((gBattleMons[battlerDef].volatiles.lockOn && gBattleMons[battlerDef].volatiles.battlerWithSureHit == battlerAtk)
|
||||
if (gBattleMons[battlerAtk].volatiles.battlerWithSureHit == battlerDef + 1
|
||||
|| CanMoveSkipAccuracyCheck(battlerAtk, move)
|
||||
|| gBattleMons[battlerDef].volatiles.glaiveRush)
|
||||
{
|
||||
|
|
@ -10535,7 +10535,7 @@ bool32 DoesOHKOMoveMissTarget(struct BattleCalcValues *cv)
|
|||
{
|
||||
lands = NO_HIT;
|
||||
}
|
||||
else if ((gBattleMons[cv->battlerDef].volatiles.lockOn && gBattleMons[cv->battlerDef].volatiles.battlerWithSureHit == cv->battlerAtk)
|
||||
else if (gBattleMons[cv->battlerAtk].volatiles.battlerWithSureHit == cv->battlerDef + 1
|
||||
|| IsAbilityAndRecord(cv->battlerAtk, cv->abilities[cv->battlerAtk], ABILITY_NO_GUARD)
|
||||
|| IsAbilityAndRecord(cv->battlerDef, cv->abilities[cv->battlerDef], ABILITY_NO_GUARD))
|
||||
{
|
||||
|
|
@ -10604,7 +10604,7 @@ bool32 BreaksThroughSemiInvulnerablity(enum BattlerId battlerAtk, enum BattlerId
|
|||
return TRUE;
|
||||
if (abilityAtk == ABILITY_NO_GUARD || abilityDef == ABILITY_NO_GUARD)
|
||||
return TRUE;
|
||||
if (gBattleMons[battlerDef].volatiles.lockOn && gBattleMons[battlerDef].volatiles.battlerWithSureHit == battlerAtk)
|
||||
if (gBattleMons[battlerAtk].volatiles.battlerWithSureHit == battlerDef + 1)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,10 @@
|
|||
#include "global.h"
|
||||
#include "test/battle.h"
|
||||
|
||||
TO_DO_BATTLE_TEST("TODO: Write Lock-On/Mind Reader (Move Effect) test titles")
|
||||
ASSUMPTIONS
|
||||
{
|
||||
ASSUME(GetMoveEffect(MOVE_LOCK_ON) == EFFECT_LOCK_ON);
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Lock-On volatile allows to hit through semi-invulnerability")
|
||||
{
|
||||
|
|
@ -15,6 +18,120 @@ SINGLE_BATTLE_TEST("Lock-On volatile allows to hit through semi-invulnerability"
|
|||
ANIMATION(ANIM_TYPE_MOVE, MOVE_LOCK_ON, player);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_FLY, opponent);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_POUND, player);
|
||||
HP_BAR(opponent); // Pound hit
|
||||
HP_BAR(opponent); // Pound hit
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Lock-On skips the accuracy check for 2 turns (Player uses Lock-On)")
|
||||
{
|
||||
PASSES_RANDOMLY(10, 10, RNG_ACCURACY);
|
||||
GIVEN {
|
||||
ASSUME(GetMoveAccuracy(MOVE_SKY_UPPERCUT) == 90);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_LOCK_ON); }
|
||||
TURN { MOVE(player, MOVE_SKY_UPPERCUT); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_LOCK_ON, player);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_SKY_UPPERCUT, player);
|
||||
} THEN {
|
||||
u32 lockOn = gBattleMons[B_BATTLER_0].volatiles.lockOn;
|
||||
u32 battlerWithSureHit = gBattleMons[B_BATTLER_0].volatiles.battlerWithSureHit;
|
||||
EXPECT_EQ(lockOn, 0);
|
||||
EXPECT_EQ(battlerWithSureHit, 0);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Lock-On skips the accuracy check for 2 turns (Opponent uses Lock-On)")
|
||||
{
|
||||
PASSES_RANDOMLY(10, 10, RNG_ACCURACY);
|
||||
GIVEN {
|
||||
ASSUME(GetMoveAccuracy(MOVE_SKY_UPPERCUT) == 90);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN { MOVE(opponent, MOVE_LOCK_ON); }
|
||||
TURN { MOVE(opponent, MOVE_SKY_UPPERCUT); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_LOCK_ON, opponent);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_SKY_UPPERCUT, opponent);
|
||||
} THEN {
|
||||
u32 lockOn = gBattleMons[B_BATTLER_1].volatiles.lockOn;
|
||||
u32 battlerWithSureHit = gBattleMons[B_BATTLER_1].volatiles.battlerWithSureHit;
|
||||
EXPECT_EQ(lockOn, 0);
|
||||
EXPECT_EQ(battlerWithSureHit, 0);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Lock-On: Baton Pass does not transfer Lock-On volatile")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(GetMoveEffect(MOVE_BATON_PASS) == EFFECT_BATON_PASS);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WYNAUT);
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_LOCK_ON); MOVE(opponent, MOVE_BATON_PASS); SEND_OUT(opponent, 1); }
|
||||
TURN { MOVE(player, MOVE_SKY_UPPERCUT); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_LOCK_ON, player);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_BATON_PASS, opponent);
|
||||
} THEN {
|
||||
u32 battlerWithSureHit = gBattleMons[B_BATTLER_0].volatiles.battlerWithSureHit;
|
||||
EXPECT_EQ(battlerWithSureHit, 0);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Lock-On: When locked on attacker faints, the volatile will be removed")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET) { HP(1); }
|
||||
PLAYER(SPECIES_WYNAUT);
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_LOCK_ON); MOVE(opponent, MOVE_POUND); SEND_OUT(player, 1); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_LOCK_ON, player);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_POUND, opponent);
|
||||
} THEN {
|
||||
u32 battlerWithSureHit = gBattleMons[B_BATTLER_0].volatiles.battlerWithSureHit;
|
||||
EXPECT_EQ(battlerWithSureHit, 0);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Lock-On: When locked on target faints, the volatile will be removed")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WOBBUFFET) { HP(1); }
|
||||
OPPONENT(SPECIES_WYNAUT);
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_LOCK_ON); }
|
||||
TURN { MOVE(player, MOVE_POUND); SEND_OUT(opponent, 1); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_LOCK_ON, player);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_POUND, player);
|
||||
} THEN {
|
||||
u32 battlerWithSureHit = gBattleMons[B_BATTLER_0].volatiles.battlerWithSureHit;
|
||||
EXPECT_EQ(battlerWithSureHit, 0);
|
||||
}
|
||||
}
|
||||
|
||||
DOUBLE_BATTLE_TEST("Lock-On fails if a target has been locked on")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
PLAYER(SPECIES_WYNAUT);
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WYNAUT);
|
||||
} WHEN {
|
||||
TURN { MOVE(playerLeft, MOVE_LOCK_ON, target: opponentLeft); }
|
||||
TURN { MOVE(playerLeft, MOVE_LOCK_ON, target: opponentRight); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_LOCK_ON, playerLeft);
|
||||
NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_LOCK_ON, playerLeft);
|
||||
}
|
||||
}
|
||||
|
||||
TO_DO_BATTLE_TEST("TODO: Write Lock-On/Mind Reader (Move Effect) test titles")
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user