mirror of
https://github.com/rh-hideout/pokeemerald-expansion.git
synced 2026-03-21 18:04:50 -05:00
Refactor OHKO Moves (#8916)
This commit is contained in:
parent
3ceaec2e60
commit
6c05a08750
|
|
@ -2675,18 +2675,6 @@ BattleScript_AbilityPreventsRest::
|
|||
waitmessage B_WAIT_TIME_LONG
|
||||
goto BattleScript_MoveEnd
|
||||
|
||||
BattleScript_EffectOHKO::
|
||||
attackcanceler
|
||||
typecalc
|
||||
jumpifmovehadnoeffect BattleScript_HitFromAtkAnimation
|
||||
tryKO BattleScript_KOFail
|
||||
goto BattleScript_HitFromAtkAnimation
|
||||
BattleScript_KOFail::
|
||||
pause B_WAIT_TIME_LONG
|
||||
printfromtable gKOFailedStringIds
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
goto BattleScript_MoveEnd
|
||||
|
||||
BattleScript_RecoilIfMiss::
|
||||
printstring STRINGID_PKMNCRASHED
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
|
|
|
|||
|
|
@ -587,7 +587,6 @@ extern const u8 BattleScript_EffectLightScreen[];
|
|||
extern const u8 BattleScript_EffectRest[];
|
||||
extern const u8 BattleScript_RestIsAlreadyAsleep[];
|
||||
extern const u8 BattleScript_InsomniaProtects[];
|
||||
extern const u8 BattleScript_EffectOHKO[];
|
||||
extern const u8 BattleScript_EffectHealBlock[];
|
||||
extern const u8 BattleScript_RecoilIfMiss[];
|
||||
extern const u8 BattleScript_EffectMist[];
|
||||
|
|
|
|||
|
|
@ -463,6 +463,8 @@ bool32 IsHazardOnSideAndClear(enum BattleSide side, enum Hazards hazardType);
|
|||
void RemoveHazardFromField(enum BattleSide side, enum Hazards hazardType);
|
||||
bool32 CanMoveSkipAccuracyCalc(u32 battlerAtk, u32 battlerDef, enum Ability abilityAtk, enum Ability abilityDef, enum Move move, enum ResultOption option);
|
||||
u32 GetTotalAccuracy(u32 battlerAtk, u32 battlerDef, enum Move move, enum Ability atkAbility, enum Ability defAbility, enum HoldEffect atkHoldEffect, enum HoldEffect defHoldEffect);
|
||||
bool32 DoesOHKOMoveMissTarget(struct BattleCalcValues *cv);
|
||||
bool32 DoesMoveMissTarget(struct BattleCalcValues *cv);
|
||||
bool32 IsSemiInvulnerable(u32 battler, enum SemiInvulnerableExclusion excludeCommander);
|
||||
bool32 BreaksThroughSemiInvulnerablity(u32 battlerAtk, u32 battlerDef, enum Ability abilityAtk, enum Ability abilityDef, enum Move move);
|
||||
bool32 HasPartnerTrainer(u32 battler);
|
||||
|
|
|
|||
|
|
@ -406,11 +406,13 @@ enum TypeSideHazard
|
|||
#define MOVE_RESULT_NOT_VERY_EFFECTIVE (1 << 2)
|
||||
#define MOVE_RESULT_DOESNT_AFFECT_FOE (1 << 3)
|
||||
#define MOVE_RESULT_ONE_HIT_KO (1 << 4)
|
||||
#define MOVE_RESULT_FAILED (1 << 5)
|
||||
#define MOVE_RESULT_FOE_ENDURED (1 << 6)
|
||||
#define MOVE_RESULT_FOE_HUNG_ON (1 << 7)
|
||||
#define MOVE_RESULT_STURDIED (1 << 8)
|
||||
#define MOVE_RESULT_FOE_ENDURED_AFFECTION (1 << 9)
|
||||
#define MOVE_RESULT_ONE_HIT_KO_NO_AFFECT (1 << 5)
|
||||
#define MOVE_RESULT_ONE_HIT_KO_STURDY (1 << 6)
|
||||
#define MOVE_RESULT_FAILED (1 << 7)
|
||||
#define MOVE_RESULT_FOE_ENDURED (1 << 8)
|
||||
#define MOVE_RESULT_FOE_HUNG_ON (1 << 9)
|
||||
#define MOVE_RESULT_STURDIED (1 << 10)
|
||||
#define MOVE_RESULT_FOE_ENDURED_AFFECTION (1 << 11)
|
||||
#define MOVE_RESULT_AVOIDED_ATTACK (MOVE_RESULT_MISSED | MOVE_RESULT_FAILED)
|
||||
#define MOVE_RESULT_NO_EFFECT (MOVE_RESULT_MISSED | MOVE_RESULT_FAILED | MOVE_RESULT_DOESNT_AFFECT_FOE)
|
||||
|
||||
|
|
|
|||
|
|
@ -33,7 +33,6 @@ enum __attribute__((packed)) BattleMoveEffects
|
|||
EFFECT_LIGHT_SCREEN,
|
||||
EFFECT_REST,
|
||||
EFFECT_OHKO,
|
||||
EFFECT_SHEER_COLD, // Same as EFFECT_OHKO but Ice-types are immune to it and has decreased accuracy for non Ice-type users.
|
||||
EFFECT_FUSION_COMBO,
|
||||
EFFECT_FIXED_PERCENT_DAMAGE,
|
||||
EFFECT_FIXED_HP_DAMAGE,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
#ifndef GUARD_MOVES_H
|
||||
#define GUARD_MOVES_H
|
||||
|
||||
#include "generational_changes.h"
|
||||
#include "contest_effect.h"
|
||||
#include "constants/battle.h"
|
||||
#include "constants/battle_factory.h"
|
||||
|
|
@ -94,6 +95,7 @@ struct MoveInfo
|
|||
u32 criticalHitStage:2;
|
||||
bool32 alwaysCriticalHit:1;
|
||||
u32 numAdditionalEffects:3; // limited to 7
|
||||
|
||||
// Flags
|
||||
bool32 makesContact:1;
|
||||
bool32 ignoresProtect:1;
|
||||
|
|
@ -126,6 +128,12 @@ struct MoveInfo
|
|||
bool32 alwaysHitsInRain:1;
|
||||
bool32 accuracy50InSun:1;
|
||||
bool32 alwaysHitsInHailSnow:1;
|
||||
bool32 alwaysHitsOnSameType:1; // Always hits if user is of same type as move
|
||||
bool32 noAffectOnSameTypeTarget:1; // Fails if target is of same type as move
|
||||
bool32 accIncreaseByTenOnSameType:1; // Accuracy is increased by 10% if user is of same type as move
|
||||
bool32 padding1:15;
|
||||
// end of word
|
||||
|
||||
// Ban flags
|
||||
bool32 gravityBanned:1;
|
||||
bool32 mirrorMoveBanned:1;
|
||||
|
|
@ -143,7 +151,7 @@ struct MoveInfo
|
|||
bool32 dampBanned:1;
|
||||
//Other
|
||||
bool32 validApprenticeMove:1;
|
||||
u32 padding:3;
|
||||
u32 padding2:17;
|
||||
// end of word
|
||||
|
||||
union {
|
||||
|
|
@ -165,7 +173,7 @@ struct MoveInfo
|
|||
} reflectDamage;
|
||||
struct {
|
||||
u16 terrain;
|
||||
u16 percent:14;
|
||||
u16 percent:13;
|
||||
enum TerrainGroundCheck groundCheck:2;
|
||||
u16 hitsBothFoes:1;
|
||||
} terrainBoost;
|
||||
|
|
@ -458,6 +466,29 @@ static inline bool32 MoveAlwaysHitsInHailSnow(enum Move moveId)
|
|||
return gMovesInfo[SanitizeMoveId(moveId)].alwaysHitsInHailSnow;
|
||||
}
|
||||
|
||||
static inline bool32 MoveAlwaysHitsOnSameType(enum Move moveId)
|
||||
{
|
||||
#if TESTING
|
||||
if (moveId == MOVE_TOXIC && GetConfig(CONFIG_TOXIC_NEVER_MISS) < GEN_6)
|
||||
return FALSE;
|
||||
#endif
|
||||
return gMovesInfo[SanitizeMoveId(moveId)].alwaysHitsOnSameType;
|
||||
}
|
||||
|
||||
static inline bool32 MoveHasNoEffectOnSameType(enum Move moveId)
|
||||
{
|
||||
#if TESTING
|
||||
if (moveId == MOVE_SHEER_COLD && GetConfig(CONFIG_SHEER_COLD_IMMUNITY) < GEN_7)
|
||||
return FALSE;
|
||||
#endif
|
||||
return gMovesInfo[SanitizeMoveId(moveId)].noAffectOnSameTypeTarget;
|
||||
}
|
||||
|
||||
static inline bool32 MoveHasIncreasedAccByTenOnSameType(enum Move moveId)
|
||||
{
|
||||
return gMovesInfo[SanitizeMoveId(moveId)].accIncreaseByTenOnSameType;
|
||||
}
|
||||
|
||||
static inline bool32 IsMoveGravityBanned(enum Move moveId)
|
||||
{
|
||||
return gMovesInfo[SanitizeMoveId(moveId)].gravityBanned;
|
||||
|
|
|
|||
|
|
@ -1098,18 +1098,14 @@ void Environment_(u32 sourceLine, u32 environment);
|
|||
|
||||
static inline bool8 IsMultibattleTest(void)
|
||||
{
|
||||
if (TESTING)
|
||||
#if TESTING
|
||||
{
|
||||
if (((gBattleTypeFlags & BATTLE_MULTI_TEST) == BATTLE_MULTI_TEST)
|
||||
|| ((gBattleTypeFlags & BATTLE_TWO_VS_ONE_TEST) == BATTLE_TWO_VS_ONE_TEST))
|
||||
|| ((gBattleTypeFlags & BATTLE_TWO_VS_ONE_TEST) == BATTLE_TWO_VS_ONE_TEST))
|
||||
return TRUE;
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
#endif
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Created for easy use of EXPECT_MOVES, so the user can provide 1, 2, 3 or 4 moves for AI which can pass the test.
|
||||
|
|
|
|||
|
|
@ -1805,10 +1805,6 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, enum Move move, s32 s
|
|||
|| !(weather & (B_WEATHER_ICY_ANY)))
|
||||
ADJUST_SCORE(-10);
|
||||
break;
|
||||
case EFFECT_SHEER_COLD:
|
||||
if (GetConfig(CONFIG_SHEER_COLD_IMMUNITY) >= GEN_7 && IS_BATTLER_OF_TYPE(battlerDef, TYPE_ICE))
|
||||
RETURN_SCORE_MINUS(20);
|
||||
// fallthrough
|
||||
case EFFECT_OHKO:
|
||||
if (!ShouldTryOHKO(battlerAtk, battlerDef, aiData->abilities[battlerAtk], aiData->abilities[battlerDef], move))
|
||||
ADJUST_SCORE(-10);
|
||||
|
|
@ -4638,7 +4634,6 @@ static s32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, enum Move move
|
|||
}
|
||||
break;
|
||||
case EFFECT_OHKO:
|
||||
case EFFECT_SHEER_COLD:
|
||||
if (GetActiveGimmick(battlerDef) == GIMMICK_DYNAMAX)
|
||||
break;
|
||||
else if (gBattleMons[battlerAtk].volatiles.lockOn)
|
||||
|
|
@ -4758,7 +4753,7 @@ static s32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, enum Move move
|
|||
ADJUST_SCORE(BEST_EFFECT);
|
||||
break;
|
||||
case EFFECT_LOCK_ON:
|
||||
if (HasMoveWithEffect(battlerAtk, EFFECT_OHKO) || HasMoveWithEffect(battlerAtk, EFFECT_SHEER_COLD))
|
||||
if (HasMoveWithEffect(battlerAtk, EFFECT_OHKO))
|
||||
ADJUST_SCORE(GOOD_EFFECT);
|
||||
else if (HasMoveWithLowAccuracy(battlerAtk, battlerDef, 85, TRUE))
|
||||
ADJUST_SCORE(GOOD_EFFECT);
|
||||
|
|
@ -6344,7 +6339,6 @@ static s32 AI_Risky(u32 battlerAtk, u32 battlerDef, enum Move move, s32 score)
|
|||
case EFFECT_FLATTER:
|
||||
case EFFECT_ATTRACT:
|
||||
case EFFECT_OHKO:
|
||||
case EFFECT_SHEER_COLD:
|
||||
ADJUST_SCORE(AVERAGE_RISKY_EFFECT);
|
||||
break;
|
||||
case EFFECT_HIT:
|
||||
|
|
|
|||
|
|
@ -2171,7 +2171,7 @@ bool32 ShouldTryOHKO(u32 battlerAtk, u32 battlerDef, enum Ability atkAbility, en
|
|||
else // test the odds
|
||||
{
|
||||
u32 odds = accuracy + (gBattleMons[battlerAtk].level - gBattleMons[battlerDef].level);
|
||||
if (B_SHEER_COLD_ACC >= GEN_7 && GetMoveEffect(move) == EFFECT_SHEER_COLD && !IS_BATTLER_OF_TYPE(gBattlerAttacker, TYPE_ICE))
|
||||
if (MoveHasIncreasedAccByTenOnSameType(move) && !IS_BATTLER_OF_TYPE(battlerAtk, GetMoveType(move)))
|
||||
odds -= 10;
|
||||
if (Random() % 100 + 1 < odds && gBattleMons[battlerAtk].level >= gBattleMons[battlerDef].level)
|
||||
return TRUE;
|
||||
|
|
|
|||
|
|
@ -344,8 +344,9 @@ static void PlayerPartnerHandleChoosePokemon(u32 battler)
|
|||
gBattleStruct->AI_monToSwitchIntoId[battler] = PARTY_SIZE;
|
||||
gBattleStruct->monToSwitchIntoId[battler] = chosenMonId;
|
||||
}
|
||||
if (TESTING)
|
||||
TestRunner_Battle_CheckSwitch(battler, chosenMonId);
|
||||
#if TESTING
|
||||
TestRunner_Battle_CheckSwitch(battler, chosenMonId);
|
||||
#endif
|
||||
BtlController_EmitChosenMonReturnValue(battler, B_COMM_TO_ENGINE, chosenMonId, NULL);
|
||||
BtlController_Complete(battler);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3945,7 +3945,6 @@ static bool32 IsDomeLuckyMove(enum Move move)
|
|||
return FALSE;
|
||||
// fallthrough
|
||||
case EFFECT_OHKO:
|
||||
case EFFECT_SHEER_COLD:
|
||||
case EFFECT_METRONOME:
|
||||
case EFFECT_MIRROR_MOVE:
|
||||
case EFFECT_SKETCH:
|
||||
|
|
|
|||
|
|
@ -402,7 +402,6 @@ static enum MaxPowerTier GetMaxPowerTier(enum Move move)
|
|||
case EFFECT_FINAL_GAMBIT:
|
||||
return MAX_POWER_TIER_2;
|
||||
case EFFECT_OHKO:
|
||||
case EFFECT_SHEER_COLD:
|
||||
case EFFECT_RETURN:
|
||||
case EFFECT_FRUSTRATION:
|
||||
case EFFECT_HEAT_CRASH:
|
||||
|
|
|
|||
|
|
@ -44,10 +44,11 @@ bool32 CanActivateGimmick(u32 battler, enum Gimmick gimmick)
|
|||
bool32 IsGimmickSelected(u32 battler, enum Gimmick gimmick)
|
||||
{
|
||||
// There's no player select in tests, but some gimmicks need to test choice before they are fully activated.
|
||||
if (TESTING)
|
||||
return (gBattleStruct->gimmick.toActivate & (1u << battler)) && gBattleStruct->gimmick.usableGimmick[battler] == gimmick;
|
||||
else
|
||||
return gBattleStruct->gimmick.usableGimmick[battler] == gimmick && gBattleStruct->gimmick.playerSelect;
|
||||
#if TESTING
|
||||
return (gBattleStruct->gimmick.toActivate & (1u << battler)) && gBattleStruct->gimmick.usableGimmick[battler] == gimmick;
|
||||
#else
|
||||
return gBattleStruct->gimmick.usableGimmick[battler] == gimmick && gBattleStruct->gimmick.playerSelect;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Sets a battler as having a gimmick active using their party index.
|
||||
|
|
@ -66,13 +67,11 @@ enum Gimmick GetActiveGimmick(u32 battler)
|
|||
bool32 ShouldTrainerBattlerUseGimmick(u32 battler, enum Gimmick gimmick)
|
||||
{
|
||||
// There are no trainer party settings in battles, but the AI needs to know which gimmick to use.
|
||||
if (TESTING)
|
||||
{
|
||||
return gimmick == TestRunner_Battle_GetChosenGimmick(GetBattlerTrainer(battler), gBattlerPartyIndexes[battler]);
|
||||
}
|
||||
#if TESTING
|
||||
return gimmick == TestRunner_Battle_GetChosenGimmick(GetBattlerTrainer(battler), gBattlerPartyIndexes[battler]);
|
||||
#else
|
||||
// The player can bypass these checks because they can choose through the controller.
|
||||
else if (IsOnPlayerSide(battler)
|
||||
&& !((gBattleTypeFlags & BATTLE_TYPE_MULTI) && battler == B_POSITION_PLAYER_RIGHT))
|
||||
if (IsOnPlayerSide(battler) && !((gBattleTypeFlags & BATTLE_TYPE_MULTI) && battler == B_POSITION_PLAYER_RIGHT))
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
|
@ -84,6 +83,7 @@ bool32 ShouldTrainerBattlerUseGimmick(u32 battler, enum Gimmick gimmick)
|
|||
if (gimmick == GIMMICK_DYNAMAX && gBattleStruct->opponentMonCanDynamax & 1 << gBattlerPartyIndexes[battler])
|
||||
return TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -567,11 +567,10 @@ static void CB2_InitBattleInternal(void)
|
|||
TryFormChange(i, B_SIDE_OPPONENT, FORM_CHANGE_BEGIN_BATTLE);
|
||||
}
|
||||
|
||||
if (TESTING)
|
||||
{
|
||||
gPlayerPartyCount = CalculatePartyCount(gPlayerParty);
|
||||
gEnemyPartyCount = CalculatePartyCount(gEnemyParty);
|
||||
}
|
||||
#if TESTING
|
||||
gPlayerPartyCount = CalculatePartyCount(gPlayerParty);
|
||||
gEnemyPartyCount = CalculatePartyCount(gEnemyParty);
|
||||
#endif
|
||||
|
||||
gBattleCommunication[MULTIUSE_STATE] = 0;
|
||||
}
|
||||
|
|
@ -2989,10 +2988,10 @@ static void ClearSetBScriptingStruct(void)
|
|||
memset(&gBattleScripting, 0, sizeof(gBattleScripting));
|
||||
|
||||
gBattleScripting.windowsType = temp;
|
||||
if (TESTING)
|
||||
gBattleScripting.battleStyle = gSaveBlock2Ptr->optionsBattleStyle;
|
||||
#if TESTING
|
||||
gBattleScripting.battleStyle = OPTIONS_BATTLE_STYLE_SET;
|
||||
else
|
||||
gBattleScripting.battleStyle = gSaveBlock2Ptr->optionsBattleStyle;
|
||||
#endif
|
||||
gBattleScripting.expOnCatch = (GetConfig(CONFIG_EXP_CATCH) >= GEN_6);
|
||||
gBattleScripting.specialTrainerBattleType = specialBattleType;
|
||||
}
|
||||
|
|
@ -6030,8 +6029,7 @@ void SetTypeBeforeUsingMove(enum Move move, u32 battler)
|
|||
if (holdEffect == HOLD_EFFECT_GEMS
|
||||
&& GetBattleMoveType(move) == GetItemSecondaryId(heldItem)
|
||||
&& effect != EFFECT_PLEDGE
|
||||
&& effect != EFFECT_OHKO
|
||||
&& effect != EFFECT_SHEER_COLD)
|
||||
&& effect != EFFECT_OHKO)
|
||||
{
|
||||
gSpecialStatuses[battler].gemParam = GetBattlerHoldEffectParam(battler);
|
||||
gSpecialStatuses[battler].gemBoost = TRUE;
|
||||
|
|
|
|||
|
|
@ -1117,9 +1117,8 @@ static void AccuracyCheck(bool32 recalcDragonDarts, const u8 *nextInstr, const u
|
|||
{
|
||||
enum Ability abilityAtk = GetBattlerAbility(gBattlerAttacker);
|
||||
enum HoldEffect holdEffectAtk = GetBattlerHoldEffect(gBattlerAttacker);
|
||||
enum BattleMoveEffects effect = GetMoveEffect(gCurrentMove);
|
||||
|
||||
if (ShouldSkipAccuracyCalcPastFirstHit(gBattlerAttacker, abilityAtk, holdEffectAtk, effect)
|
||||
if (ShouldSkipAccuracyCalcPastFirstHit(gBattlerAttacker, abilityAtk, holdEffectAtk, GetMoveEffect(gCurrentMove))
|
||||
|| IsMaxMove(gCurrentMove)
|
||||
|| IsZMove(gCurrentMove))
|
||||
{
|
||||
|
|
@ -1143,23 +1142,19 @@ static void AccuracyCheck(bool32 recalcDragonDarts, const u8 *nextInstr, const u
|
|||
continue;
|
||||
|
||||
numTargets++;
|
||||
enum Ability abilityDef = GetBattlerAbility(battlerDef);
|
||||
|
||||
if (CanMoveSkipAccuracyCalc(gBattlerAttacker, battlerDef, abilityAtk, abilityDef, gCurrentMove, RUN_SCRIPT))
|
||||
continue;
|
||||
struct BattleCalcValues cv = {0};
|
||||
cv.move = gCurrentMove;
|
||||
cv.battlerAtk = gBattlerAttacker;
|
||||
cv.battlerDef = battlerDef;
|
||||
cv.abilities[gBattlerAttacker] = abilityAtk;
|
||||
cv.abilities[battlerDef] = GetBattlerAbility(battlerDef);
|
||||
cv.holdEffects[gBattlerAttacker] = holdEffectAtk;
|
||||
cv.holdEffects[battlerDef] = GetBattlerHoldEffect(battlerDef);
|
||||
|
||||
u32 holdEffectDef = GetBattlerHoldEffect(battlerDef);
|
||||
u32 accuracy = GetTotalAccuracy(gBattlerAttacker,
|
||||
battlerDef,
|
||||
gCurrentMove,
|
||||
abilityAtk,
|
||||
abilityDef,
|
||||
holdEffectAtk,
|
||||
holdEffectDef);
|
||||
|
||||
if (!RandomPercentage(RNG_ACCURACY, accuracy))
|
||||
if (DoesMoveMissTarget(&cv))
|
||||
{
|
||||
gBattleStruct->moveResultFlags[battlerDef] = MOVE_RESULT_MISSED;
|
||||
gBattleStruct->moveResultFlags[battlerDef] |= MOVE_RESULT_MISSED;
|
||||
gBattleCommunication[MISS_TYPE] = B_MSG_MISSED;
|
||||
numMisses++;
|
||||
|
||||
|
|
@ -1192,10 +1187,24 @@ static void AccuracyCheck(bool32 recalcDragonDarts, const u8 *nextInstr, const u
|
|||
|
||||
if (gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_MISSED)
|
||||
{
|
||||
gBattleStruct->moveResultFlags[gBattlerTarget] = MOVE_RESULT_MISSED;
|
||||
gLastLandedMoves[gBattlerTarget] = 0;
|
||||
gLastHitByType[gBattlerTarget] = 0;
|
||||
gBattlescriptCurrInstr = failInstr;
|
||||
|
||||
if (gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_ONE_HIT_KO_STURDY)
|
||||
{
|
||||
gLastUsedAbility = ABILITY_STURDY;
|
||||
gBattlescriptCurrInstr = BattleScript_SturdyPreventsOHKO;
|
||||
gBattlerAbility = gBattlerTarget;
|
||||
}
|
||||
else
|
||||
{
|
||||
gBattlescriptCurrInstr = failInstr;
|
||||
}
|
||||
|
||||
if (gBattleStruct->moveResultFlags[gBattlerTarget] & (MOVE_RESULT_ONE_HIT_KO_NO_AFFECT | MOVE_RESULT_ONE_HIT_KO_STURDY))
|
||||
gBattleStruct->moveResultFlags[gBattlerTarget] = MOVE_RESULT_DOESNT_AFFECT_FOE;
|
||||
else
|
||||
gBattleStruct->moveResultFlags[gBattlerTarget] = MOVE_RESULT_MISSED;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -8338,126 +8347,9 @@ static void Cmd_setlightscreen(void)
|
|||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
}
|
||||
|
||||
// for var lands
|
||||
#define NO_HIT 0
|
||||
#define CALC_ACC 1
|
||||
#define SURE_HIT 2
|
||||
// for var endured
|
||||
#define NOT_ENDURED 0
|
||||
#define FOCUS_SASHED 1
|
||||
#define FOCUS_BANDED 2
|
||||
#define AFFECTION_ENDURED 3
|
||||
static void Cmd_tryKO(void)
|
||||
{
|
||||
CMD_ARGS(const u8 *failInstr);
|
||||
|
||||
enum BattleMoveEffects effect = GetMoveEffect(gCurrentMove);
|
||||
enum HoldEffect holdEffect = GetBattlerHoldEffect(gBattlerTarget);
|
||||
enum Ability targetAbility = GetBattlerAbility(gBattlerTarget);
|
||||
u32 rand = Random() % 100;
|
||||
u32 affectionScore = GetBattlerAffectionHearts(gBattlerTarget);
|
||||
u32 endured = NOT_ENDURED;
|
||||
|
||||
// Dynamaxed Pokemon cannot be hit by OHKO moves.
|
||||
if ((GetActiveGimmick(gBattlerTarget) == GIMMICK_DYNAMAX))
|
||||
{
|
||||
gBattleStruct->moveResultFlags[gBattlerTarget] |= MOVE_RESULT_MISSED;
|
||||
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_KO_UNAFFECTED;
|
||||
gBattlescriptCurrInstr = cmd->failInstr;
|
||||
return;
|
||||
}
|
||||
|
||||
gPotentialItemEffectBattler = gBattlerTarget;
|
||||
if (holdEffect == HOLD_EFFECT_FOCUS_BAND
|
||||
&& (Random() % 100) < GetBattlerHoldEffectParam(gBattlerTarget))
|
||||
{
|
||||
endured = FOCUS_BANDED;
|
||||
RecordItemEffectBattle(gBattlerTarget, holdEffect);
|
||||
}
|
||||
else if (holdEffect == HOLD_EFFECT_FOCUS_SASH && IsBattlerAtMaxHp(gBattlerTarget))
|
||||
{
|
||||
endured = FOCUS_SASHED;
|
||||
RecordItemEffectBattle(gBattlerTarget, holdEffect);
|
||||
}
|
||||
else if (B_AFFECTION_MECHANICS == TRUE && IsOnPlayerSide(gBattlerTarget) && affectionScore >= AFFECTION_THREE_HEARTS)
|
||||
{
|
||||
if ((affectionScore == AFFECTION_FIVE_HEARTS && rand < 20)
|
||||
|| (affectionScore == AFFECTION_FOUR_HEARTS && rand < 15)
|
||||
|| (affectionScore == AFFECTION_THREE_HEARTS && rand < 10))
|
||||
endured = AFFECTION_ENDURED;
|
||||
}
|
||||
|
||||
if (targetAbility == ABILITY_STURDY)
|
||||
{
|
||||
gBattleStruct->moveResultFlags[gBattlerTarget] |= MOVE_RESULT_MISSED;
|
||||
gLastUsedAbility = ABILITY_STURDY;
|
||||
gBattlescriptCurrInstr = BattleScript_SturdyPreventsOHKO;
|
||||
gBattlerAbility = gBattlerTarget;
|
||||
}
|
||||
else
|
||||
{
|
||||
u32 lands = NO_HIT;
|
||||
if (gBattleMons[gBattlerTarget].level > gBattleMons[gBattlerAttacker].level)
|
||||
lands = NO_HIT;
|
||||
else if ((gBattleMons[gBattlerTarget].volatiles.lockOn && gBattleMons[gBattlerTarget].volatiles.battlerWithSureHit == gBattlerAttacker)
|
||||
|| IsAbilityAndRecord(gBattlerAttacker, GetBattlerAbility(gBattlerAttacker), ABILITY_NO_GUARD)
|
||||
|| IsAbilityAndRecord(gBattlerTarget, targetAbility, ABILITY_NO_GUARD))
|
||||
lands = SURE_HIT;
|
||||
else
|
||||
lands = CALC_ACC;
|
||||
|
||||
if (lands == CALC_ACC)
|
||||
{
|
||||
u16 odds = GetMoveAccuracy(gCurrentMove) + (gBattleMons[gBattlerAttacker].level - gBattleMons[gBattlerTarget].level);
|
||||
if (B_SHEER_COLD_ACC >= GEN_7 && effect == EFFECT_SHEER_COLD && !IS_BATTLER_OF_TYPE(gBattlerAttacker, TYPE_ICE))
|
||||
odds -= 10;
|
||||
if (RandomPercentage(RNG_ACCURACY, odds) && gBattleMons[gBattlerAttacker].level >= gBattleMons[gBattlerTarget].level)
|
||||
lands = SURE_HIT;
|
||||
}
|
||||
|
||||
if (lands == SURE_HIT)
|
||||
{
|
||||
if (gBattleMons[gBattlerTarget].volatiles.endured)
|
||||
{
|
||||
gBattleStruct->moveDamage[gBattlerTarget] = gBattleMons[gBattlerTarget].hp - 1;
|
||||
gBattleStruct->moveResultFlags[gBattlerTarget] |= MOVE_RESULT_FOE_ENDURED;
|
||||
}
|
||||
else if (endured == FOCUS_BANDED || endured == FOCUS_SASHED)
|
||||
{
|
||||
gBattleStruct->moveDamage[gBattlerTarget] = gBattleMons[gBattlerTarget].hp - 1;
|
||||
gBattleStruct->moveResultFlags[gBattlerTarget] |= MOVE_RESULT_FOE_HUNG_ON;
|
||||
gLastUsedItem = gBattleMons[gBattlerTarget].item;
|
||||
}
|
||||
else if (endured == AFFECTION_ENDURED)
|
||||
{
|
||||
gBattleStruct->moveDamage[gBattlerTarget] = gBattleMons[gBattlerTarget].hp - 1;
|
||||
gBattleStruct->moveResultFlags[gBattlerTarget] |= MOVE_RESULT_FOE_ENDURED_AFFECTION;
|
||||
}
|
||||
else
|
||||
{
|
||||
gBattleStruct->moveDamage[gBattlerTarget] = gBattleMons[gBattlerTarget].hp;
|
||||
gBattleStruct->moveResultFlags[gBattlerTarget] |= MOVE_RESULT_ONE_HIT_KO;
|
||||
}
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
}
|
||||
else
|
||||
{
|
||||
gBattleStruct->moveResultFlags[gBattlerTarget] |= MOVE_RESULT_MISSED;
|
||||
if (gBattleMons[gBattlerAttacker].level >= gBattleMons[gBattlerTarget].level)
|
||||
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_KO_MISS;
|
||||
else
|
||||
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_KO_UNAFFECTED;
|
||||
gBattlescriptCurrInstr = cmd->failInstr;
|
||||
}
|
||||
}
|
||||
}
|
||||
#undef NO_HIT
|
||||
#undef CALC_ACC
|
||||
#undef SURE_HIT
|
||||
#undef NOT_ENDURED
|
||||
#undef FOCUS_SASHED
|
||||
#undef FOCUS_BANDED
|
||||
#undef AFFECTION_ENDURED
|
||||
|
||||
static void Cmd_checknonvolatiletrigger(void)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -3853,7 +3853,6 @@ static void ForewarnChooseMove(u32 battler)
|
|||
switch (GetMoveEffect(data[count].moveId))
|
||||
{
|
||||
case EFFECT_OHKO:
|
||||
case EFFECT_SHEER_COLD:
|
||||
data[count].power = 150;
|
||||
break;
|
||||
case EFFECT_REFLECT_DAMAGE:
|
||||
|
|
@ -4880,9 +4879,7 @@ u32 AbilityBattleEffects(enum AbilityEffect caseID, u32 battler, enum Ability ab
|
|||
ctx.isAnticipation = TRUE;
|
||||
modifier = CalcTypeEffectivenessMultiplier(&ctx);
|
||||
|
||||
if (modifier >= UQ_4_12(2.0)
|
||||
|| moveEffect == EFFECT_OHKO
|
||||
|| moveEffect == EFFECT_SHEER_COLD)
|
||||
if (modifier >= UQ_4_12(2.0) || moveEffect == EFFECT_OHKO)
|
||||
{
|
||||
effect++;
|
||||
break;
|
||||
|
|
@ -9508,6 +9505,9 @@ s32 DoFixedDamageMoveCalc(struct BattleContext *ctx)
|
|||
dmg = GetNonDynamaxHP(ctx->battlerDef) - gBattleMons[ctx->battlerAtk].hp;
|
||||
}
|
||||
break;
|
||||
case EFFECT_OHKO:
|
||||
dmg = gBattleMons[ctx->battlerDef].hp;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
@ -10028,7 +10028,7 @@ static inline uq4_12_t CalcTypeEffectivenessMultiplierInternal(struct BattleCont
|
|||
ctx->airBalloonBlocked = TRUE;
|
||||
}
|
||||
}
|
||||
else if (GetConfig(CONFIG_SHEER_COLD_IMMUNITY) >= GEN_7 && GetMoveEffect(ctx->move) == EFFECT_SHEER_COLD && IS_BATTLER_OF_TYPE(ctx->battlerDef, TYPE_ICE))
|
||||
else if (MoveHasNoEffectOnSameType(ctx->move) && IS_BATTLER_OF_TYPE(ctx->battlerDef, GetMoveType(ctx->move)))
|
||||
{
|
||||
modifier = UQ_4_12(0.0);
|
||||
}
|
||||
|
|
@ -12058,11 +12058,9 @@ void RemoveHazardFromField(enum BattleSide side, enum Hazards hazardType)
|
|||
}
|
||||
}
|
||||
|
||||
static bool32 CanToxicSkipAccuracyCheck(u32 battlerAtk, u32 move)
|
||||
static bool32 CanMoveSkipAccuracyCheck(u32 battlerAtk, u32 move)
|
||||
{
|
||||
if (GetConfig(CONFIG_TOXIC_NEVER_MISS) < GEN_6)
|
||||
return FALSE;
|
||||
return move == MOVE_TOXIC && IS_BATTLER_OF_TYPE(battlerAtk, TYPE_POISON);
|
||||
return MoveAlwaysHitsOnSameType(move) && IS_BATTLER_OF_TYPE(battlerAtk, GetMoveType(move));
|
||||
}
|
||||
|
||||
bool32 CanMoveSkipAccuracyCalc(u32 battlerAtk, u32 battlerDef, enum Ability abilityAtk, enum Ability abilityDef, enum Move move, enum ResultOption option)
|
||||
|
|
@ -12072,7 +12070,7 @@ bool32 CanMoveSkipAccuracyCalc(u32 battlerAtk, u32 battlerDef, enum Ability abil
|
|||
enum BattleMoveEffects moveEffect = GetMoveEffect(move);
|
||||
|
||||
if ((gBattleMons[battlerDef].volatiles.lockOn && gBattleMons[battlerDef].volatiles.battlerWithSureHit == battlerAtk)
|
||||
|| CanToxicSkipAccuracyCheck(battlerAtk, move)
|
||||
|| CanMoveSkipAccuracyCheck(battlerAtk, move)
|
||||
|| gBattleMons[battlerDef].volatiles.glaiveRush)
|
||||
{
|
||||
effect = TRUE;
|
||||
|
|
@ -12095,8 +12093,7 @@ bool32 CanMoveSkipAccuracyCalc(u32 battlerAtk, u32 battlerDef, enum Ability abil
|
|||
// If the target is under the effects of Telekinesis, and the move isn't a OH-KO move, move hits.
|
||||
else if (gBattleMons[battlerDef].volatiles.telekinesis
|
||||
&& !IsSemiInvulnerable(battlerDef, CHECK_ALL)
|
||||
&& moveEffect != EFFECT_OHKO
|
||||
&& moveEffect != EFFECT_SHEER_COLD)
|
||||
&& moveEffect != EFFECT_OHKO)
|
||||
{
|
||||
effect = TRUE;
|
||||
}
|
||||
|
|
@ -12223,6 +12220,9 @@ u32 GetTotalAccuracy(u32 battlerAtk, u32 battlerDef, enum Move move, enum Abilit
|
|||
break;
|
||||
}
|
||||
|
||||
if (MoveHasIncreasedAccByTenOnSameType(move) && !IS_BATTLER_OF_TYPE(battlerAtk, GetMoveType(move)))
|
||||
calc = (calc * 110) / 100;
|
||||
|
||||
// Attacker's hold effect
|
||||
switch (atkHoldEffect)
|
||||
{
|
||||
|
|
@ -12268,6 +12268,85 @@ u32 GetTotalAccuracy(u32 battlerAtk, u32 battlerDef, enum Move move, enum Abilit
|
|||
return calc;
|
||||
}
|
||||
|
||||
bool32 DoesOHKOMoveMissTarget(struct BattleCalcValues *cv)
|
||||
{
|
||||
enum OHKOResult {
|
||||
NO_HIT,
|
||||
CALC_ACC,
|
||||
SURE_HIT,
|
||||
};
|
||||
|
||||
// Dynamaxed Pokemon cannot be hit by OHKO moves.
|
||||
if (GetActiveGimmick(cv->battlerDef) == GIMMICK_DYNAMAX)
|
||||
{
|
||||
gBattleStruct->moveResultFlags[cv->battlerDef] |= MOVE_RESULT_ONE_HIT_KO_NO_AFFECT;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (cv->abilities[cv->battlerDef] == ABILITY_STURDY)
|
||||
{
|
||||
gBattleStruct->moveResultFlags[cv->battlerDef] |= MOVE_RESULT_ONE_HIT_KO_STURDY;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
enum OHKOResult lands = NO_HIT;
|
||||
|
||||
if (gBattleMons[cv->battlerDef].level > gBattleMons[cv->battlerAtk].level)
|
||||
{
|
||||
lands = NO_HIT;
|
||||
}
|
||||
else if ((gBattleMons[cv->battlerDef].volatiles.lockOn && gBattleMons[cv->battlerDef].volatiles.battlerWithSureHit == cv->battlerAtk)
|
||||
|| IsAbilityAndRecord(cv->battlerAtk, cv->abilities[cv->battlerAtk], ABILITY_NO_GUARD)
|
||||
|| IsAbilityAndRecord(cv->battlerDef, cv->abilities[cv->battlerDef], ABILITY_NO_GUARD))
|
||||
{
|
||||
lands = SURE_HIT;
|
||||
}
|
||||
else
|
||||
{
|
||||
lands = CALC_ACC;
|
||||
}
|
||||
|
||||
if (lands == CALC_ACC)
|
||||
{
|
||||
u32 odds = GetMoveAccuracy(cv->move) + (gBattleMons[cv->battlerAtk].level - gBattleMons[cv->battlerDef].level);
|
||||
if (MoveHasIncreasedAccByTenOnSameType(cv->move) && !IS_BATTLER_OF_TYPE(cv->battlerAtk, GetMoveType(cv->move)))
|
||||
odds -= 10;
|
||||
if (RandomPercentage(RNG_ACCURACY, odds) && gBattleMons[cv->battlerAtk].level >= gBattleMons[cv->battlerDef].level)
|
||||
lands = SURE_HIT;
|
||||
}
|
||||
|
||||
if (lands == SURE_HIT)
|
||||
{
|
||||
gBattleStruct->moveResultFlags[cv->battlerDef] |= MOVE_RESULT_ONE_HIT_KO_NO_AFFECT;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (gBattleMons[cv->battlerAtk].level < gBattleMons[cv->battlerDef].level)
|
||||
gBattleStruct->moveResultFlags[cv->battlerDef] |= MOVE_RESULT_ONE_HIT_KO_NO_AFFECT;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
bool32 DoesMoveMissTarget(struct BattleCalcValues *cv)
|
||||
{
|
||||
if (GetMoveEffect(cv->move) == EFFECT_OHKO)
|
||||
return DoesOHKOMoveMissTarget(cv);
|
||||
|
||||
if (CanMoveSkipAccuracyCalc(cv->battlerAtk, cv->battlerDef, cv->abilities[cv->battlerAtk], cv->abilities[cv->battlerDef], cv->move, RUN_SCRIPT))
|
||||
return FALSE;
|
||||
|
||||
u32 accuracy = GetTotalAccuracy(
|
||||
cv->battlerAtk,
|
||||
cv->battlerDef,
|
||||
cv->move,
|
||||
cv->abilities[cv->battlerAtk],
|
||||
cv->abilities[cv->battlerDef],
|
||||
cv->holdEffects[cv->battlerAtk],
|
||||
cv->holdEffects[cv->battlerDef]
|
||||
);
|
||||
return !RandomPercentage(RNG_ACCURACY, accuracy);
|
||||
}
|
||||
|
||||
bool32 IsSemiInvulnerable(u32 battler, enum SemiInvulnerableExclusion excludeCommander)
|
||||
{
|
||||
if (gBattleMons[battler].volatiles.semiInvulnerable == STATE_COMMANDER)
|
||||
|
|
@ -12281,7 +12360,7 @@ bool32 BreaksThroughSemiInvulnerablity(u32 battlerAtk, u32 battlerDef, enum Abil
|
|||
|
||||
if (state != STATE_COMMANDER)
|
||||
{
|
||||
if (CanToxicSkipAccuracyCheck(battlerAtk, move))
|
||||
if (CanMoveSkipAccuracyCheck(battlerAtk, move))
|
||||
return TRUE;
|
||||
if (abilityAtk == ABILITY_NO_GUARD || abilityDef == ABILITY_NO_GUARD)
|
||||
return TRUE;
|
||||
|
|
|
|||
|
|
@ -548,7 +548,7 @@ u32 GetZMovePower(enum Move move)
|
|||
if (GetMoveCategory(move) == DAMAGE_CATEGORY_STATUS)
|
||||
return 0;
|
||||
enum BattleMoveEffects moveEffect = GetMoveEffect(move);
|
||||
if (moveEffect == EFFECT_OHKO || moveEffect == EFFECT_SHEER_COLD)
|
||||
if (moveEffect == EFFECT_OHKO)
|
||||
return 180;
|
||||
|
||||
u32 power = GetMoveZPowerOverride(move);
|
||||
|
|
|
|||
|
|
@ -216,17 +216,11 @@ const struct BattleMoveEffect gBattleMoveEffects[NUM_BATTLE_MOVE_EFFECTS] =
|
|||
|
||||
[EFFECT_OHKO] =
|
||||
{
|
||||
.battleScript = BattleScript_EffectOHKO,
|
||||
.battleScript = BattleScript_EffectHit,
|
||||
.battleTvScore = 7,
|
||||
.battleFactoryStyle = FACTORY_STYLE_HIGH_RISK,
|
||||
},
|
||||
|
||||
[EFFECT_SHEER_COLD] =
|
||||
{
|
||||
.battleScript = BattleScript_EffectOHKO,
|
||||
.battleTvScore = 7,
|
||||
},
|
||||
|
||||
[EFFECT_FUSION_COMBO] =
|
||||
{
|
||||
.battleScript = BattleScript_EffectHit,
|
||||
|
|
|
|||
|
|
@ -2544,6 +2544,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] =
|
|||
.argument = { .nonVolatileStatus = MOVE_EFFECT_TOXIC },
|
||||
.zMove = { .effect = Z_EFFECT_DEF_UP_1 },
|
||||
.magicCoatAffected = TRUE,
|
||||
.alwaysHitsOnSameType = B_TOXIC_NEVER_MISS >= GEN_6,
|
||||
.contestEffect = CONTEST_EFFECT_WORSEN_CONDITION_OF_PREV_MONS,
|
||||
.contestCategory = CONTEST_CATEGORY_SMART,
|
||||
.contestComboStarterId = COMBO_STARTER_TOXIC,
|
||||
|
|
@ -8839,13 +8840,15 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] =
|
|||
.description = COMPOUND_STRING(
|
||||
"A chilling attack that\n"
|
||||
"causes fainting if it hits."),
|
||||
.effect = EFFECT_SHEER_COLD,
|
||||
.effect = EFFECT_OHKO,
|
||||
.power = 1,
|
||||
.type = TYPE_ICE,
|
||||
.accuracy = 30,
|
||||
.pp = 5,
|
||||
.target = TARGET_SELECTED,
|
||||
.priority = 0,
|
||||
.noAffectOnSameTypeTarget = B_SHEER_COLD_IMMUNITY >= GEN_7,
|
||||
.accIncreaseByTenOnSameType = B_SHEER_COLD_ACC >= GEN_7,
|
||||
.category = DAMAGE_CATEGORY_SPECIAL,
|
||||
.contestEffect = CONTEST_EFFECT_BADLY_STARTLE_MONS_WITH_GOOD_APPEALS,
|
||||
.contestCategory = CONTEST_CATEGORY_BEAUTY,
|
||||
|
|
|
|||
|
|
@ -299,7 +299,7 @@ AI_DOUBLE_BATTLE_TEST("AI can use all moves, 301-400")
|
|||
switch (effect)
|
||||
{
|
||||
//TODO: AI HANDLING
|
||||
case EFFECT_SHEER_COLD: // Guillotine is crashing the test entirely.
|
||||
case EFFECT_OHKO: // Guillotine is crashing the test entirely.
|
||||
case EFFECT_WATER_SPORT:
|
||||
case EFFECT_LUCKY_CHANT:
|
||||
case EFFECT_ME_FIRST:
|
||||
|
|
|
|||
|
|
@ -224,7 +224,7 @@ SINGLE_BATTLE_TEST("Dynamax: Dynamaxed Pokemon cannot be hit by OHKO moves")
|
|||
} SCENE {
|
||||
MESSAGE("Wobbuffet used Max Strike!");
|
||||
MESSAGE("The opposing Machamp used Fissure!");
|
||||
MESSAGE("Wobbuffet is unaffected!");
|
||||
MESSAGE("It doesn't affect Wobbuffet…");
|
||||
NONE_OF { HP_BAR(player); }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -310,7 +310,7 @@ static void WhenSingles(enum Move move, struct BattlePokemon *attacker, struct B
|
|||
MOVE(attacker, move);
|
||||
MOVE(defender, MOVE_SWORDS_DANCE);
|
||||
}
|
||||
else if (effect == EFFECT_OHKO || effect == EFFECT_SHEER_COLD)
|
||||
else if (effect == EFFECT_OHKO)
|
||||
{ // defender needs to send out a different team member
|
||||
MOVE(attacker, move);
|
||||
SEND_OUT(defender, 1);
|
||||
|
|
@ -526,7 +526,7 @@ static void DoublesWhen(enum Move move, struct BattlePokemon *attacker, struct B
|
|||
MOVE(attacker, move, target: target);
|
||||
MOVE(target, MOVE_SWORDS_DANCE);
|
||||
}
|
||||
else if (effect == EFFECT_OHKO || effect == EFFECT_SHEER_COLD)
|
||||
else if (effect == EFFECT_OHKO)
|
||||
{ // Opponent needs to send out a different team member
|
||||
MOVE(attacker, move, target: target);
|
||||
SEND_OUT(target, 2);
|
||||
|
|
|
|||
|
|
@ -83,6 +83,51 @@ SINGLE_BATTLE_TEST("OHKO moves fail if target protects")
|
|||
NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_FISSURE, player);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Sheer Cold can hit semi-invulnerable mons when the user has No-Guard")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(GetItemHoldEffect(ITEM_FOCUS_SASH) == HOLD_EFFECT_FOCUS_SASH);
|
||||
PLAYER(SPECIES_WOBBUFFET) { Ability(ABILITY_NO_GUARD); }
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN { MOVE(opponent, MOVE_FLY); }
|
||||
TURN { MOVE(player, MOVE_SHEER_COLD); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_SHEER_COLD, player);
|
||||
HP_BAR(opponent, hp: 0);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Sheer Cold can be endured by Focus Sash")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_FOCUS_SASH); }
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_SHEER_COLD); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_SHEER_COLD, player);
|
||||
HP_BAR(opponent, hp: 1);
|
||||
MESSAGE("The opposing Wobbuffet hung on using its Focus Sash!");
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Sheer Cold can be endured by Sturdy")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_GEODUDE) { Ability(ABILITY_STURDY); }
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_SHEER_COLD); }
|
||||
} SCENE {
|
||||
NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_SHEER_COLD, player);
|
||||
ABILITY_POPUP(opponent, ABILITY_STURDY);
|
||||
}
|
||||
}
|
||||
|
||||
TO_DO_BATTLE_TEST("OHKO moves faints the target, skipping regular damage calculations")
|
||||
TO_DO_BATTLE_TEST("OHKO moves's accuracy increases by 1% for every level the user has over the target")
|
||||
TO_DO_BATTLE_TEST("OHKO moves's ignores non-stage accuracy modifiers") // Gravity, Wide Lens, Compound Eyes
|
||||
TO_DO_BATTLE_TEST("OHKO moves ignore non-stage accuracy modifiers") // Gravity, Wide Lens, Compound Eyes
|
||||
TO_DO_BATTLE_TEST("OHKO: Sheer Cold's accuracy decreasaes by 10% if the user is not Ice type")
|
||||
|
|
|
|||
|
|
@ -1,86 +0,0 @@
|
|||
#include "global.h"
|
||||
#include "test/battle.h"
|
||||
|
||||
ASSUMPTIONS
|
||||
{
|
||||
ASSUME(GetMoveEffect(MOVE_SHEER_COLD) == EFFECT_SHEER_COLD);
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Sheer Cold doesn't affect Ice-type Pokémon (Gen3-6)")
|
||||
{
|
||||
GIVEN {
|
||||
WITH_CONFIG(CONFIG_SHEER_COLD_IMMUNITY, GEN_6);
|
||||
ASSUME(GetSpeciesType(SPECIES_GLALIE, 0) == TYPE_ICE);
|
||||
PLAYER(SPECIES_WYNAUT);
|
||||
OPPONENT(SPECIES_GLALIE);
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_SHEER_COLD); }
|
||||
} SCENE {
|
||||
NOT MESSAGE("It doesn't affect the opposing Glalie…");
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_SHEER_COLD, player);
|
||||
HP_BAR(opponent, hp: 0);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Sheer Cold doesn't affect Ice-type Pokémon (Gen7+)")
|
||||
{
|
||||
GIVEN {
|
||||
WITH_CONFIG(CONFIG_SHEER_COLD_IMMUNITY, GEN_7);
|
||||
ASSUME(GetSpeciesType(SPECIES_GLALIE, 0) == TYPE_ICE);
|
||||
PLAYER(SPECIES_WYNAUT);
|
||||
OPPONENT(SPECIES_GLALIE);
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_SHEER_COLD); }
|
||||
} SCENE {
|
||||
NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_SHEER_COLD, player);
|
||||
MESSAGE("It doesn't affect the opposing Glalie…");
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Sheer Cold can hit semi-invulnerable mons when the user has No-Guard")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(GetItemHoldEffect(ITEM_FOCUS_SASH) == HOLD_EFFECT_FOCUS_SASH);
|
||||
PLAYER(SPECIES_WOBBUFFET) { Ability(ABILITY_NO_GUARD); }
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN { MOVE(opponent, MOVE_FLY); }
|
||||
TURN { MOVE(player, MOVE_SHEER_COLD); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_SHEER_COLD, player);
|
||||
HP_BAR(opponent, hp: 0);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Sheer Cold can be endured by Focus Sash")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_FOCUS_SASH); }
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_SHEER_COLD); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_SHEER_COLD, player);
|
||||
HP_BAR(opponent, hp: 1);
|
||||
MESSAGE("The opposing Wobbuffet hung on using its Focus Sash!");
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Sheer Cold can be endured by Sturdy")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_GEODUDE) { Ability(ABILITY_STURDY); }
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_SHEER_COLD); }
|
||||
} SCENE {
|
||||
NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_SHEER_COLD, player);
|
||||
ABILITY_POPUP(opponent, ABILITY_STURDY);
|
||||
}
|
||||
}
|
||||
|
||||
TO_DO_BATTLE_TEST("Sheer Cold faints the target, skipping regular damage calculations")
|
||||
TO_DO_BATTLE_TEST("Sheer Cold always fails if the target has a higher level than the user")
|
||||
TO_DO_BATTLE_TEST("Sheer Cold's accuracy increases by 1% for every level the user has over the target")
|
||||
TO_DO_BATTLE_TEST("Sheer Cold's accuracy decreasaes by 10% if the user is not Ice type")
|
||||
TO_DO_BATTLE_TEST("Sheer Cold's ignores non-stage accuracy modifiers") // Gravity, Wide Lens, Compound Eyes
|
||||
39
test/battle/move_flags/move_has_no_effect_on_same_type.c
Normal file
39
test/battle/move_flags/move_has_no_effect_on_same_type.c
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
#include "global.h"
|
||||
#include "test/battle.h"
|
||||
|
||||
ASSUMPTIONS
|
||||
{
|
||||
ASSUME(MoveHasNoEffectOnSameType(MOVE_SHEER_COLD));
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Sheer Cold does affect Ice-type Pokémon (Gen3-6)")
|
||||
{
|
||||
GIVEN {
|
||||
WITH_CONFIG(CONFIG_SHEER_COLD_IMMUNITY, GEN_6);
|
||||
ASSUME(GetSpeciesType(SPECIES_GLALIE, 0) == TYPE_ICE);
|
||||
PLAYER(SPECIES_WYNAUT);
|
||||
OPPONENT(SPECIES_GLALIE);
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_SHEER_COLD); }
|
||||
} SCENE {
|
||||
NOT MESSAGE("It doesn't affect the opposing Glalie…");
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_SHEER_COLD, player);
|
||||
HP_BAR(opponent, hp: 0);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Sheer Cold doesn't affect Ice-type Pokémon (Gen7+)")
|
||||
{
|
||||
GIVEN {
|
||||
WITH_CONFIG(CONFIG_SHEER_COLD_IMMUNITY, GEN_7);
|
||||
ASSUME(GetSpeciesType(SPECIES_GLALIE, 0) == TYPE_ICE);
|
||||
PLAYER(SPECIES_WYNAUT);
|
||||
OPPONENT(SPECIES_GLALIE);
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_SHEER_COLD); }
|
||||
} SCENE {
|
||||
NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_SHEER_COLD, player);
|
||||
MESSAGE("It doesn't affect the opposing Glalie…");
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user