updated up to Cmd_tryKO

This commit is contained in:
cawtds
2024-05-02 02:13:51 +02:00
parent 4203ad1e98
commit 69b94eb97f
3 changed files with 327 additions and 177 deletions

View File

@@ -6332,3 +6332,39 @@ BattleScript_ItemNoStatLoss::
waitmessage B_WAIT_TIME_LONG
return
BattleScript_RoarSuccessSwitch::
call BattleScript_RoarSuccessRet
getswitchedmondata BS_TARGET
switchindataupdate BS_TARGET
trytoclearprimalweather
flushtextbox
switchinanim BS_TARGET, FALSE
waitstate
printstring STRINGID_PKMNWASDRAGGEDOUT
switchineffects BS_TARGET
jumpifbyte CMP_EQUAL, sSWITCH_CASE, B_SWITCH_RED_CARD, BattleScript_RoarSuccessSwitch_Ret
setbyte sSWITCH_CASE, B_SWITCH_NORMAL
goto BattleScript_MoveEnd
BattleScript_RoarSuccessSwitch_Ret:
swapattackerwithtarget @ continuation of RedCardActivates
restoretarget
setbyte sSWITCH_CASE, B_SWITCH_NORMAL
return
BattleScript_RoarSuccessEndBattle::
call BattleScript_RoarSuccessRet
setbyte sSWITCH_CASE, B_SWITCH_NORMAL
setoutcomeonteleport BS_ATTACKER
finishaction
BattleScript_RoarSuccessRet:
jumpifbyte CMP_EQUAL, sSWITCH_CASE, B_SWITCH_HIT, BattleScript_RoarSuccessRet_Ret
jumpifbyte CMP_EQUAL, sSWITCH_CASE, B_SWITCH_RED_CARD, BattleScript_RoarSuccessRet_Ret
attackanimation
waitanimation
BattleScript_RoarSuccessRet_Ret:
switchoutabilities BS_TARGET
returntoball BS_TARGET, FALSE
waitstate
return

View File

@@ -88,6 +88,12 @@
#define SAFE_DIV(a, b) ((a) / (b))
#endif
// The below macro does a%n, but (to match) will switch to a&(n-1) if n is a power of 2.
// There are cases where GF does a&(n-1) where we would really like to have a%n, because
// if n is changed to a value that isn't a power of 2 then a&(n-1) is unlikely to work as
// intended, and a%n for powers of 2 isn't always optimized to use &.
#define MOD(a, n)(((n) & ((n)-1)) ? ((a) % (n)) : ((a) & ((n)-1)))
// Extracts the upper 16 bits of a 32-bit number
#define HIHALF(n) (((n) & 0xFFFF0000) >> 16)

View File

@@ -737,11 +737,11 @@ void (* const gBattleScriptingCommandsTable[])(void) =
Cmd_twoturnmoveschargestringandanimation, //0x8C // done
Cmd_setmultihitcounter, //0x8D // done
Cmd_initmultihitstring, //0x8E // done
Cmd_forcerandomswitch, //0x8F
Cmd_tryconversiontypechange, //0x90
Cmd_givepaydaymoney, //0x91
Cmd_setlightscreen, //0x92
Cmd_tryKO, //0x93
Cmd_forcerandomswitch, //0x8F // done
Cmd_tryconversiontypechange, //0x90 // done
Cmd_givepaydaymoney, //0x91 // done
Cmd_setlightscreen, //0x92 // done
Cmd_tryKO, //0x93 // done
Cmd_damagetohalftargethp, //0x94
Cmd_setsandstorm, //0x95
Cmd_weatherdamage, //0x96
@@ -12161,169 +12161,234 @@ static void Cmd_initmultihitstring(void)
gBattlescriptCurrInstr = cmd->nextInstr;
}
static bool8 TryDoForceSwitchOut(void)
{
if (gBattleMons[gBattlerAttacker].level >= gBattleMons[gBattlerTarget].level)
{
*(gBattleStruct->battlerPartyIndexes + gBattlerTarget) = gBattlerPartyIndexes[gBattlerTarget];
}
else
{
u16 random = Random() & 0xFF;
if ((u32)((random * (gBattleMons[gBattlerAttacker].level + gBattleMons[gBattlerTarget].level) >> 8) + 1) <= (gBattleMons[gBattlerTarget].level / 4))
{
gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 1);
return FALSE;
}
*(gBattleStruct->battlerPartyIndexes + gBattlerTarget) = gBattlerPartyIndexes[gBattlerTarget];
}
gBattlescriptCurrInstr = BattleScript_SuccessForceOut;
return TRUE;
}
#define MON_CAN_BATTLE(mon) (((GetMonData(mon, MON_DATA_SPECIES) && GetMonData(mon, MON_DATA_IS_EGG) != TRUE && GetMonData(mon, MON_DATA_HP))))
static void Cmd_forcerandomswitch(void)
{
if (gBattleTypeFlags & BATTLE_TYPE_TRAINER)
CMD_ARGS(const u8 *failInstr);
s32 i;
s32 battler1PartyId = 0;
s32 battler2PartyId = 0;
s32 firstMonId;
s32 lastMonId = 0; // + 1
struct Pokemon *party = NULL;
u8 validMons[PARTY_SIZE];
s32 validMonsCount = 0;
bool32 redCardForcedSwitch = FALSE;
// Red card checks against wild pokemon. If we have reached here, the player has a mon to switch into
// Red card swaps attacker with target to get the animation correct, so here we check attacker which is really the target. Thanks GF...
if (gBattleScripting.switchCase == B_SWITCH_RED_CARD
&& !(gBattleTypeFlags & BATTLE_TYPE_TRAINER)
&& GetBattlerSide(gBattlerAttacker) == B_SIDE_OPPONENT) // Check opponent's red card activating
{
u8 i;
struct Pokemon *party;
u8 valid;
u8 val;
if (GetBattlerSide(gBattlerTarget) == B_SIDE_PLAYER)
party = gPlayerParty;
else
party = gEnemyParty;
if (gBattleTypeFlags & BATTLE_TYPE_MULTI)
if (!WILD_DOUBLE_BATTLE)
{
valid = 0;
val = 0;
if (GetLinkTrainerFlankId(GetBattlerMultiplayerId(gBattlerTarget)) == 1)
val = PARTY_SIZE / 2;
for (i = val; i < val + (PARTY_SIZE / 2); i++)
{
if (GetMonData(&party[i], MON_DATA_SPECIES) != SPECIES_NONE
&& !GetMonData(&party[i], MON_DATA_IS_EGG)
&& GetMonData(&party[i], MON_DATA_HP) != 0)
++valid;
}
// Wild mon with red card will end single battle
gBattlescriptCurrInstr = BattleScript_RoarSuccessEndBattle;
return;
}
else
{
valid = 0;
for (i = 0; i < PARTY_SIZE; i++)
// Wild double battle, wild mon red card activation on player
if (IS_WHOLE_SIDE_ALIVE(gBattlerTarget))
{
if (GetMonData(&party[i], MON_DATA_SPECIES) != SPECIES_NONE
&& !GetMonData(&party[i], MON_DATA_IS_EGG)
&& GetMonData(&party[i], MON_DATA_HP) != 0)
++valid;
}
}
// Fails if there's only 1 mon left in single battle or there's less than 3 left in non-multi double battle.
if ((valid < 2 && (gBattleTypeFlags & (BATTLE_TYPE_DOUBLE | BATTLE_TYPE_MULTI)) != BATTLE_TYPE_DOUBLE)
|| (valid < 3 && (gBattleTypeFlags & BATTLE_TYPE_DOUBLE) && !(gBattleTypeFlags & BATTLE_TYPE_MULTI)))
{
gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 1);
}
else if (TryDoForceSwitchOut())
{
if (gBattleTypeFlags & BATTLE_TYPE_MULTI)
{
do
{
val = Random() % (PARTY_SIZE / 2);
if (GetLinkTrainerFlankId(GetBattlerMultiplayerId(gBattlerTarget)) == 1)
i = val + (PARTY_SIZE / 2);
else
i = val;
}
while (i == gBattlerPartyIndexes[gBattlerTarget]
|| i == gBattlerPartyIndexes[gBattlerTarget ^ 2]
|| !MON_CAN_BATTLE(&party[i]));
// Both player's battlers are alive
redCardForcedSwitch = FALSE;
}
else
{
if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE)
// Player has only one mon alive -> force red card switch before manually switching to other mon
redCardForcedSwitch = TRUE;
}
}
}
// Swapping pokemon happens in:
// trainer battles
// wild double battles when an opposing pokemon uses it against one of the two alive player mons
// wild double battle when a player pokemon uses it against its partner
if ((gBattleTypeFlags & BATTLE_TYPE_TRAINER)
|| (WILD_DOUBLE_BATTLE
&& GetBattlerSide(gBattlerAttacker) == B_SIDE_OPPONENT
&& GetBattlerSide(gBattlerTarget) == B_SIDE_PLAYER
&& IS_WHOLE_SIDE_ALIVE(gBattlerTarget))
|| (WILD_DOUBLE_BATTLE
&& GetBattlerSide(gBattlerAttacker) == B_SIDE_PLAYER
&& GetBattlerSide(gBattlerTarget) == B_SIDE_PLAYER)
|| redCardForcedSwitch
)
{
party = GetBattlerParty(gBattlerTarget);
if (BATTLE_TWO_VS_ONE_OPPONENT && GetBattlerSide(gBattlerTarget) == B_SIDE_OPPONENT)
{
firstMonId = 0;
lastMonId = 6;
battler2PartyId = gBattlerPartyIndexes[gBattlerTarget];
battler1PartyId = gBattlerPartyIndexes[BATTLE_PARTNER(gBattlerTarget)];
}
else if ((gBattleTypeFlags & BATTLE_TYPE_BATTLE_TOWER && gBattleTypeFlags & BATTLE_TYPE_LINK)
|| (gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER))
{
if ((gBattlerTarget & BIT_FLANK) != B_FLANK_LEFT)
{
firstMonId = PARTY_SIZE / 2;
lastMonId = PARTY_SIZE;
}
else
{
firstMonId = 0;
lastMonId = PARTY_SIZE / 2;
}
battler2PartyId = gBattlerPartyIndexes[gBattlerTarget];
battler1PartyId = gBattlerPartyIndexes[BATTLE_PARTNER(gBattlerTarget)];
}
else if ((gBattleTypeFlags & BATTLE_TYPE_MULTI && gBattleTypeFlags & BATTLE_TYPE_LINK))
{
if (GetLinkTrainerFlankId(GetBattlerMultiplayerId(gBattlerTarget)) == B_FLANK_RIGHT)
{
firstMonId = PARTY_SIZE / 2;
lastMonId = PARTY_SIZE;
}
else
{
firstMonId = 0;
lastMonId = PARTY_SIZE / 2;
}
battler2PartyId = gBattlerPartyIndexes[gBattlerTarget];
battler1PartyId = gBattlerPartyIndexes[BATTLE_PARTNER(gBattlerTarget)];
}
else if (gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS)
{
if (GetBattlerSide(gBattlerTarget) == B_SIDE_PLAYER)
{
firstMonId = 0;
lastMonId = PARTY_SIZE;
}
else
{
if ((gBattlerTarget & BIT_FLANK) != B_FLANK_LEFT)
{
do
{
i = Random() % PARTY_SIZE;
}
while (i == gBattlerPartyIndexes[gBattlerTarget]
|| i == gBattlerPartyIndexes[gBattlerTarget ^ 2]
|| !MON_CAN_BATTLE(&party[i]));
firstMonId = PARTY_SIZE / 2;
lastMonId = PARTY_SIZE;
}
else
{
do
{
i = Random() % PARTY_SIZE;
}
while (i == gBattlerPartyIndexes[gBattlerTarget]
|| !MON_CAN_BATTLE(&party[i]));
firstMonId = 0;
lastMonId = PARTY_SIZE / 2;
}
}
*(gBattleStruct->monToSwitchIntoId + gBattlerTarget) = i;
battler2PartyId = gBattlerPartyIndexes[gBattlerTarget];
battler1PartyId = gBattlerPartyIndexes[BATTLE_PARTNER(gBattlerTarget)];
}
else if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE)
{
firstMonId = 0;
lastMonId = PARTY_SIZE;
battler2PartyId = gBattlerPartyIndexes[gBattlerTarget];
battler1PartyId = gBattlerPartyIndexes[BATTLE_PARTNER(gBattlerTarget)];
}
else
{
firstMonId = 0;
lastMonId = PARTY_SIZE;
battler2PartyId = gBattlerPartyIndexes[gBattlerTarget]; // there is only one Pokémon out in single battles
battler1PartyId = gBattlerPartyIndexes[gBattlerTarget];
}
for (i = firstMonId; i < lastMonId; i++)
{
if (GetMonData(&party[i], MON_DATA_SPECIES) != SPECIES_NONE
&& !GetMonData(&party[i], MON_DATA_IS_EGG)
&& GetMonData(&party[i], MON_DATA_HP) != 0
&& i != battler1PartyId
&& i != battler2PartyId)
{
validMons[validMonsCount++] = i;
}
}
if (validMonsCount == 0)
{
gBattlescriptCurrInstr = cmd->failInstr;
}
else
{
*(gBattleStruct->battlerPartyIndexes + gBattlerTarget) = gBattlerPartyIndexes[gBattlerTarget];
gBattlescriptCurrInstr = BattleScript_RoarSuccessSwitch;
gBattleStruct->forcedSwitch |= gBitTable[gBattlerTarget];
*(gBattleStruct->monToSwitchIntoId + gBattlerTarget) = validMons[RandomUniform(RNG_FORCE_RANDOM_SWITCH, 0, validMonsCount - 1)];
if (!IsMultiBattle())
SwitchPartyOrder(gBattlerTarget);
SwitchPartyOrderLinkMulti(gBattlerTarget, i, 0);
SwitchPartyOrderLinkMulti(gBattlerTarget ^ BIT_FLANK, i, 1);
if ((gBattleTypeFlags & BATTLE_TYPE_LINK && gBattleTypeFlags & BATTLE_TYPE_BATTLE_TOWER)
|| (gBattleTypeFlags & BATTLE_TYPE_LINK && gBattleTypeFlags & BATTLE_TYPE_MULTI))
{
SwitchPartyOrderLinkMulti(gBattlerTarget, i, 0);
SwitchPartyOrderLinkMulti(BATTLE_PARTNER(gBattlerTarget), i, 1);
}
if (gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER)
SwitchPartyOrderInGameMulti(gBattlerTarget, i);
}
}
else
{
TryDoForceSwitchOut();
// In normal wild doubles, Roar will always fail if the user's level is less than the target's.
if (gBattleMons[gBattlerAttacker].level >= gBattleMons[gBattlerTarget].level)
gBattlescriptCurrInstr = BattleScript_RoarSuccessEndBattle;
else
gBattlescriptCurrInstr = cmd->failInstr;
}
}
// Randomly changes user's type to one of its moves' type
static void Cmd_tryconversiontypechange(void)
{
CMD_ARGS(const u8 *failInstr);
u8 validMoves = 0;
u8 moveChecked;
u8 moveType;
u8 moveChecked = 0;
u8 moveType = 0;
while (validMoves < MAX_MON_MOVES)
if (B_UPDATED_CONVERSION >= GEN_6)
{
if (gBattleMons[gBattlerAttacker].moves[validMoves] == MOVE_NONE)
break;
validMoves++;
}
for (moveChecked = 0; moveChecked < validMoves; moveChecked++)
{
moveType = gMovesInfo[gBattleMons[gBattlerAttacker].moves[moveChecked]].type;
if (moveType == TYPE_MYSTERY)
// Changes user's type to its first move's type
for (moveChecked = 0; moveChecked < MAX_MON_MOVES; moveChecked++)
{
if (IS_BATTLER_OF_TYPE(gBattlerAttacker, TYPE_GHOST))
moveType = TYPE_GHOST;
else
moveType = TYPE_NORMAL;
if (gBattleMons[gBattlerAttacker].moves[moveChecked] != MOVE_NONE)
{
moveType = gMovesInfo[gBattleMons[gBattlerAttacker].moves[moveChecked]].type;
break;
}
}
if (moveType != gBattleMons[gBattlerAttacker].type1
&& moveType != gBattleMons[gBattlerAttacker].type2)
if (IS_BATTLER_OF_TYPE(gBattlerAttacker, moveType))
{
break;
gBattlescriptCurrInstr = cmd->failInstr;
}
else
{
SET_BATTLER_TYPE(gBattlerAttacker, moveType);
PREPARE_TYPE_BUFFER(gBattleTextBuff1, moveType);
gBattlescriptCurrInstr = cmd->nextInstr;
}
}
if (moveChecked == validMoves)
{
gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 1);
}
else
{
do
// Randomly changes user's type to one of its moves' type
while (validMoves < MAX_MON_MOVES)
{
while ((moveChecked = Random() & (MAX_MON_MOVES - 1)) >= validMoves);
if (gBattleMons[gBattlerAttacker].moves[validMoves] == MOVE_NONE)
break;
validMoves++;
}
for (moveChecked = 0; moveChecked < validMoves; moveChecked++)
{
moveType = gMovesInfo[gBattleMons[gBattlerAttacker].moves[moveChecked]].type;
if (moveType == TYPE_MYSTERY)
@@ -12333,46 +12398,81 @@ static void Cmd_tryconversiontypechange(void)
else
moveType = TYPE_NORMAL;
}
if (moveType != gBattleMons[gBattlerAttacker].type1
&& moveType != gBattleMons[gBattlerAttacker].type2
&& moveType != gBattleMons[gBattlerAttacker].type3)
{
break;
}
}
while (moveType == gBattleMons[gBattlerAttacker].type1 || moveType == gBattleMons[gBattlerAttacker].type2);
SET_BATTLER_TYPE(gBattlerAttacker, moveType);
PREPARE_TYPE_BUFFER(gBattleTextBuff1, moveType);
if (moveChecked == validMoves)
{
gBattlescriptCurrInstr = cmd->failInstr;
}
else
{
do
{
while ((moveChecked = MOD(Random(), MAX_MON_MOVES)) >= validMoves);
gBattlescriptCurrInstr += 5;
moveType = gMovesInfo[gBattleMons[gBattlerAttacker].moves[moveChecked]].type;
if (moveType == TYPE_MYSTERY)
{
if (IS_BATTLER_OF_TYPE(gBattlerAttacker, TYPE_GHOST))
moveType = TYPE_GHOST;
else
moveType = TYPE_NORMAL;
}
}
while (moveType == gBattleMons[gBattlerAttacker].type1 || moveType == gBattleMons[gBattlerAttacker].type2 || moveType == gBattleMons[gBattlerAttacker].type3);
SET_BATTLER_TYPE(gBattlerAttacker, moveType);
PREPARE_TYPE_BUFFER(gBattleTextBuff1, moveType);
gBattlescriptCurrInstr = cmd->nextInstr;
}
}
}
static void Cmd_givepaydaymoney(void)
{
if (!(gBattleTypeFlags & BATTLE_TYPE_LINK) && gPaydayMoney != 0)
CMD_ARGS();
if (!(gBattleTypeFlags & (BATTLE_TYPE_LINK)) && gPaydayMoney != 0)
{
u32 bonusMoney = gPaydayMoney * gBattleStruct->moneyMultiplier;
AddMoney(&gSaveBlock1Ptr->money, bonusMoney);
PREPARE_HWORD_NUMBER_BUFFER(gBattleTextBuff1, 5, bonusMoney)
BattleScriptPush(gBattlescriptCurrInstr + 1);
BattleScriptPush(cmd->nextInstr);
gBattlescriptCurrInstr = BattleScript_PrintPayDayMoneyString;
}
else
{
gBattlescriptCurrInstr++;
gBattlescriptCurrInstr = cmd->nextInstr;
}
}
static void Cmd_setlightscreen(void)
{
if (gSideStatuses[GET_BATTLER_SIDE(gBattlerAttacker)] & SIDE_STATUS_LIGHTSCREEN)
CMD_ARGS();
if (gSideStatuses[GetBattlerSide(gBattlerAttacker)] & SIDE_STATUS_LIGHTSCREEN)
{
gMoveResultFlags |= MOVE_RESULT_MISSED;
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SIDE_STATUS_FAILED;
}
else
{
gSideStatuses[GET_BATTLER_SIDE(gBattlerAttacker)] |= SIDE_STATUS_LIGHTSCREEN;
gSideTimers[GET_BATTLER_SIDE(gBattlerAttacker)].lightscreenTimer = 5;
gSideTimers[GET_BATTLER_SIDE(gBattlerAttacker)].lightscreenBattlerId = gBattlerAttacker;
gSideStatuses[GetBattlerSide(gBattlerAttacker)] |= SIDE_STATUS_LIGHTSCREEN;
if (GetBattlerHoldEffect(gBattlerAttacker, TRUE) == HOLD_EFFECT_LIGHT_CLAY)
gSideTimers[GetBattlerSide(gBattlerAttacker)].lightscreenTimer = 8;
else
gSideTimers[GetBattlerSide(gBattlerAttacker)].lightscreenTimer = 5;
gSideTimers[GetBattlerSide(gBattlerAttacker)].lightscreenBattlerId = gBattlerAttacker;
if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE && CountAliveMonsInBattle(BATTLE_ALIVE_SIDE, gBattlerAttacker) == 2)
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SET_LIGHTSCREEN_DOUBLE;
@@ -12380,82 +12480,90 @@ static void Cmd_setlightscreen(void)
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SET_LIGHTSCREEN_SINGLE;
}
gBattlescriptCurrInstr++;
gBattlescriptCurrInstr = cmd->nextInstr;
}
static void Cmd_tryKO(void)
{
u8 holdEffect, param;
CMD_ARGS(const u8 *failInstr);
if (gBattleMons[gBattlerTarget].item == ITEM_ENIGMA_BERRY)
{
holdEffect = gEnigmaBerries[gBattlerTarget].holdEffect;
param = gEnigmaBerries[gBattlerTarget].holdEffectParam;
}
else
{
holdEffect = ItemId_GetHoldEffect(gBattleMons[gBattlerTarget].item);
param = ItemId_GetHoldEffectParam(gBattleMons[gBattlerTarget].item);
}
bool32 lands = FALSE;
u32 holdEffect = GetBattlerHoldEffect(gBattlerTarget, TRUE);
u16 targetAbility = GetBattlerAbility(gBattlerTarget);
// TODO: Dynamax
// Dynamaxed Pokemon cannot be hit by OHKO moves.
// if (IsDynamaxed(gBattlerTarget))
// {
// gMoveResultFlags |= MOVE_RESULT_MISSED;
// gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_KO_UNAFFECTED;
// gBattlescriptCurrInstr = cmd->failInstr;
// return;
// }
gPotentialItemEffectBattler = gBattlerTarget;
if (holdEffect == HOLD_EFFECT_FOCUS_BAND && (Random() % 100) < param)
if (holdEffect == HOLD_EFFECT_FOCUS_BAND
&& (Random() % 100) < GetBattlerHoldEffectParam(gBattlerTarget))
{
RecordItemEffectBattle(gBattlerTarget, HOLD_EFFECT_FOCUS_BAND);
gSpecialStatuses[gBattlerTarget].focusBanded = 1;
gSpecialStatuses[gBattlerTarget].focusBanded = TRUE;
RecordItemEffectBattle(gBattlerTarget, holdEffect);
}
else if (holdEffect == HOLD_EFFECT_FOCUS_SASH && BATTLER_MAX_HP(gBattlerTarget))
{
gSpecialStatuses[gBattlerTarget].focusSashed = TRUE;
RecordItemEffectBattle(gBattlerTarget, holdEffect);
}
if (gBattleMons[gBattlerTarget].ability == ABILITY_STURDY)
if (targetAbility == ABILITY_STURDY)
{
gMoveResultFlags |= MOVE_RESULT_MISSED;
gLastUsedAbility = ABILITY_STURDY;
gBattlescriptCurrInstr = BattleScript_SturdyPreventsOHKO;
RecordAbilityBattle(gBattlerTarget, ABILITY_STURDY);
gBattlerAbility = gBattlerTarget;
}
else
{
u16 chance;
if (!(gStatuses3[gBattlerTarget] & STATUS3_ALWAYS_HITS))
if ((((gStatuses3[gBattlerTarget] & STATUS3_ALWAYS_HITS)
&& gDisableStructs[gBattlerTarget].battlerWithSureHit == gBattlerAttacker)
|| GetBattlerAbility(gBattlerAttacker) == ABILITY_NO_GUARD
|| targetAbility == ABILITY_NO_GUARD)
&& gBattleMons[gBattlerAttacker].level >= gBattleMons[gBattlerTarget].level)
{
chance = gMovesInfo[gCurrentMove].accuracy + (gBattleMons[gBattlerAttacker].level - gBattleMons[gBattlerTarget].level);
if (Random() % 100 + 1 < chance && gBattleMons[gBattlerAttacker].level >= gBattleMons[gBattlerTarget].level)
chance = TRUE;
else
chance = FALSE;
}
else if (gDisableStructs[gBattlerTarget].battlerWithSureHit == gBattlerAttacker
&& gBattleMons[gBattlerAttacker].level >= gBattleMons[gBattlerTarget].level)
{
chance = TRUE;
lands = TRUE;
}
else
{
chance = gMovesInfo[gCurrentMove].accuracy + (gBattleMons[gBattlerAttacker].level - gBattleMons[gBattlerTarget].level);
if (Random() % 100 + 1 < chance && gBattleMons[gBattlerAttacker].level >= gBattleMons[gBattlerTarget].level)
chance = TRUE;
else
chance = FALSE;
u16 odds = gMovesInfo[gCurrentMove].accuracy + (gBattleMons[gBattlerAttacker].level - gBattleMons[gBattlerTarget].level);
if (B_SHEER_COLD_ACC >= GEN_7 && gCurrentMove == MOVE_SHEER_COLD && !IS_BATTLER_OF_TYPE(gBattlerAttacker, TYPE_ICE))
odds -= 10;
if (RandomPercentage(RNG_ACCURACY, odds) && gBattleMons[gBattlerAttacker].level >= gBattleMons[gBattlerTarget].level)
lands = TRUE;
}
if (chance)
if (lands)
{
if (gProtectStructs[gBattlerTarget].endured)
{
gBattleMoveDamage = gBattleMons[gBattlerTarget].hp - 1;
gMoveResultFlags |= MOVE_RESULT_FOE_ENDURED;
}
else if (gSpecialStatuses[gBattlerTarget].focusBanded)
else if (gSpecialStatuses[gBattlerTarget].focusBanded || gSpecialStatuses[gBattlerTarget].focusSashed)
{
gBattleMoveDamage = gBattleMons[gBattlerTarget].hp - 1;
gMoveResultFlags |= MOVE_RESULT_FOE_HUNG_ON;
gLastUsedItem = gBattleMons[gBattlerTarget].item;
}
else if (B_AFFECTION_MECHANICS == TRUE && gSpecialStatuses[gBattlerTarget].affectionEndured)
{
gBattleMoveDamage = gBattleMons[gBattlerTarget].hp - 1;
gMoveResultFlags |= MOVE_RESULT_FOE_ENDURED_AFFECTION;
}
else
{
gBattleMoveDamage = gBattleMons[gBattlerTarget].hp;
gMoveResultFlags |= MOVE_RESULT_ONE_HIT_KO;
}
gBattlescriptCurrInstr += 5;
gBattlescriptCurrInstr = cmd->nextInstr;
}
else
{
@@ -12464,7 +12572,7 @@ static void Cmd_tryKO(void)
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_KO_MISS;
else
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_KO_UNAFFECTED;
gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 1);
gBattlescriptCurrInstr = cmd->failInstr;
}
}
}