Simplify defrosting/thawing and expand target thawing config (#9271)

This commit is contained in:
PhallenTree 2026-02-23 16:11:05 +00:00 committed by GitHub
parent 12d16aad16
commit 8e3183a7a9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
14 changed files with 183 additions and 125 deletions

View File

@ -5644,26 +5644,14 @@ BattleScript_MoveUsedIsFrozen::
statusanimation BS_ATTACKER
goto BattleScript_MoveEnd
BattleScript_MoveUsedUnfroze::
BattleScript_BattlerDefrosted::
printfromtable gGotDefrostedStringIds
waitmessage B_WAIT_TIME_LONG
updatestatusicon BS_ATTACKER
return
BattleScript_MoveUsedUnfrostbite::
printfromtable gFrostbiteHealedStringIds
waitmessage B_WAIT_TIME_LONG
updatestatusicon BS_ATTACKER
return
BattleScript_DefrostedViaFireMove::
printstring STRINGID_PKMNWASDEFROSTED
waitmessage B_WAIT_TIME_LONG
updatestatusicon BS_SCRIPTING
return
BattleScript_FrostbiteHealedViaFireMove::
printstring STRINGID_PKMNFROSTBITEHEALED
BattleScript_BattlerFrostbiteHealed::
printfromtable gFrostbiteHealedStringIds
waitmessage B_WAIT_TIME_LONG
updatestatusicon BS_SCRIPTING
return

View File

@ -601,7 +601,8 @@ struct BattleStruct
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 unused:4;
u8 triAttackBurn:1;
u8 unused:3;
void (*savedCallback)(void);
u16 chosenItem[MAX_BATTLERS_COUNT];
u16 choicedMove[MAX_BATTLERS_COUNT];

View File

@ -68,7 +68,9 @@ bool32 ProteanTryChangeType(enum BattlerId battler, enum Ability ability, enum M
u8 GetFirstFaintedPartyIndex(enum BattlerId battler);
void SaveBattlerTarget(enum BattlerId battler);
void SaveBattlerAttacker(enum BattlerId battler);
bool32 CanBurnHitThaw(enum Ability abilityAtk, enum Move move);
bool32 CanBurnHitThaw(enum Move move);
bool32 CanMoveThawTarget(enum Ability abilityAtk, enum Move move);
bool32 CanFireMoveThawTarget(enum Move move);
extern void (*const gBattleScriptingCommandsTable[])(void);
extern const struct StatFractions gAccuracyStageRatios[];

View File

@ -126,10 +126,8 @@ extern const u8 BattleScript_PoisonTurnDmg[];
extern const u8 BattleScript_BurnTurnDmg[];
extern const u8 BattleScript_FrostbiteTurnDmg[];
extern const u8 BattleScript_MoveUsedIsFrozen[];
extern const u8 BattleScript_MoveUsedUnfroze[];
extern const u8 BattleScript_MoveUsedUnfrostbite[];
extern const u8 BattleScript_DefrostedViaFireMove[];
extern const u8 BattleScript_FrostbiteHealedViaFireMove[];
extern const u8 BattleScript_BattlerDefrosted[];
extern const u8 BattleScript_BattlerFrostbiteHealed[];
extern const u8 BattleScript_MoveUsedIsParalyzed[];
extern const u8 BattleScript_MoveUsedFlinched[];
extern const u8 BattleScript_PrintUproarOverTurns[];

View File

@ -113,7 +113,7 @@
#define B_TELEPORT_BEHAVIOR GEN_LATEST // In LGPE onwards (Gen8+ here), Teleport allows the user to swap out with another party member.
#define B_BEAT_UP GEN_LATEST // In Gen5+, Beat Up uses a different formula to calculate its damage, and deals Dark-type damage. Prior to Gen 5, each hit also announces the party member's name.
#define B_DARK_VOID_FAIL GEN_LATEST // In Gen7+, only Darkrai can use Dark Void.
#define B_BURN_HIT_THAW GEN_LATEST // In Gen6+, damaging moves with a chance of burn will thaw the target, regardless if they're fire-type moves or not.
#define B_HIT_THAW GEN_LATEST // In Gen6+, damaging moves that thaw the user will thaw the target. In Gen 3+, Fire-type moves thaw the target. In Gen 1-2, damaging moves that can burn will thaw the target, regardless if they can be burned or not.
#define B_HEALING_WISH_SWITCH GEN_LATEST // In Gen5+, the mon receiving Healing Wish is sent out at the end of the turn.
// Additionally, in gen8+ the Healing Wish's effect will be stored until the user switches into a statused or hurt mon.
#define B_DEFOG_EFFECT_CLEARING GEN_LATEST // In Gen5+, Defog does not lower Evasion of target behind Subsitute. In Gen6+, Defog clears Spikes, Toxic Spikes, Stealth Rock and Sticky Web from both sides. In Gen8+, Defog also clears active Terrain.

View File

@ -53,7 +53,6 @@ enum StringID
STRINGID_PKMNFROZENBY,
STRINGID_PKMNISFROZEN,
STRINGID_PKMNWASDEFROSTED,
STRINGID_PKMNWASDEFROSTED2,
STRINGID_PKMNWASDEFROSTEDBY,
STRINGID_PKMNWASPARALYZED,
STRINGID_PKMNWASPARALYZEDBY,
@ -629,7 +628,6 @@ enum StringID
STRINGID_PKMNSITEMHEALEDFROSTBITE,
STRINGID_ATTACKERHEALEDITSFROSTBITE,
STRINGID_PKMNFROSTBITEHEALED,
STRINGID_PKMNFROSTBITEHEALED2,
STRINGID_PKMNFROSTBITEHEALEDBY,
STRINGID_MIRRORHERBCOPIED,
STRINGID_STARTEDSNOW,

View File

@ -104,7 +104,7 @@
F(B_TELEPORT_BEHAVIOR, teleportBehavior, (u32, GEN_COUNT - 1)) \
F(B_BEAT_UP, beatUp, (u32, GEN_COUNT - 1)) \
F(B_DARK_VOID_FAIL, darkVoidFail, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
F(B_BURN_HIT_THAW, burnHitThaw, (u32, GEN_COUNT - 1)) \
F(B_HIT_THAW, hitThaw, (u32, GEN_COUNT - 1)) \
F(B_HEALING_WISH_SWITCH, healingWishSwitch, (u32, GEN_COUNT - 1)) \
F(B_DEFOG_EFFECT_CLEARING, defogEffectClearing, (u32, GEN_COUNT - 1)) \
F(B_STOCKPILE_RAISES_DEFS, stockpileRaisesDefs, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \

View File

@ -1203,13 +1203,14 @@ static s32 AI_CheckBadMove(enum BattlerId battlerAtk, enum BattlerId battlerDef,
}
// Don't use anything but super effective thawing moves if target is frozen if any other attack available
if (((GetMoveType(move) == TYPE_FIRE && GetMovePower(move) != 0) || CanBurnHitThaw(abilityAtk, move)) && effectiveness < UQ_4_12(2.0) && (gBattleMons[battlerDef].status1 & STATUS1_ICY_ANY))
if ((CanFireMoveThawTarget(move) || CanBurnHitThaw(move) || CanMoveThawTarget(abilityAtk, move))
&& effectiveness < UQ_4_12(2.0) && (gBattleMons[battlerDef].status1 & STATUS1_ICY_ANY))
{
enum Move aiMove;
for (u32 moveIndex = 0; moveIndex < MAX_MON_MOVES; moveIndex++)
{
aiMove = gBattleMons[battlerAtk].moves[moveIndex];
if (GetMoveType(aiMove) != TYPE_FIRE && !CanBurnHitThaw(abilityAtk, aiMove) && GetMovePower(gBattleMons[battlerAtk].moves[moveIndex]) != 0)
if (!CanFireMoveThawTarget(aiMove) && !CanBurnHitThaw(aiMove) && !CanMoveThawTarget(abilityAtk, aiMove))
{
ADJUST_SCORE(-1);
break;

View File

@ -230,8 +230,7 @@ const u8 *const gBattleStringsTable[STRINGID_COUNT] =
[STRINGID_PKMNFROZENBY] = COMPOUND_STRING("{B_SCR_NAME_WITH_PREFIX}'s {B_BUFF1} froze {B_EFF_NAME_WITH_PREFIX2} solid!"), //not in gen 5+, ability popup
[STRINGID_PKMNISFROZEN] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX} is frozen solid!"),
[STRINGID_PKMNWASDEFROSTED] = COMPOUND_STRING("{B_SCR_NAME_WITH_PREFIX} thawed out!"),
[STRINGID_PKMNWASDEFROSTED2] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX} thawed out!"),
[STRINGID_PKMNWASDEFROSTEDBY] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX}'s {B_CURRENT_MOVE} melted the ice!"),
[STRINGID_PKMNWASDEFROSTEDBY] = COMPOUND_STRING("{B_SCR_NAME_WITH_PREFIX}'s {B_CURRENT_MOVE} melted the ice!"),
[STRINGID_PKMNWASPARALYZED] = COMPOUND_STRING("{B_EFF_NAME_WITH_PREFIX} is paralyzed, so it may be unable to move!"),
[STRINGID_PKMNWASPARALYZEDBY] = COMPOUND_STRING("{B_SCR_NAME_WITH_PREFIX}'s {B_BUFF1} paralyzed {B_EFF_NAME_WITH_PREFIX2}, so it may be unable to move!"), //not in gen 5+, ability popup
[STRINGID_PKMNISPARALYZED] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX} couldn't move because it's paralyzed!"),
@ -806,8 +805,7 @@ const u8 *const gBattleStringsTable[STRINGID_COUNT] =
[STRINGID_PKMNSITEMHEALEDFROSTBITE] = COMPOUND_STRING("{B_SCR_NAME_WITH_PREFIX}'s {B_LAST_ITEM} cured its frostbite!"),
[STRINGID_ATTACKERHEALEDITSFROSTBITE] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX} cured its frostbite through sheer determination so you wouldn't worry!"),
[STRINGID_PKMNFROSTBITEHEALED] = COMPOUND_STRING("{B_SCR_NAME_WITH_PREFIX}'s frostbite was cured!"),
[STRINGID_PKMNFROSTBITEHEALED2] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX}'s frostbite was cured!"),
[STRINGID_PKMNFROSTBITEHEALEDBY] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX}'s {B_CURRENT_MOVE} cured its frostbite!"),
[STRINGID_PKMNFROSTBITEHEALEDBY] = COMPOUND_STRING("{B_SCR_NAME_WITH_PREFIX}'s {B_CURRENT_MOVE} cured its frostbite!"),
[STRINGID_MIRRORHERBCOPIED] = COMPOUND_STRING("{B_SCR_NAME_WITH_PREFIX} used its Mirror Herb to mirror its opponent's stat changes!"),
[STRINGID_STARTEDSNOW] = COMPOUND_STRING("It started to snow!"),
[STRINGID_SNOWCONTINUES] = COMPOUND_STRING("Snow continues to fall."), //not in gen 5+ (lol)
@ -1212,7 +1210,7 @@ const u16 gGotFrostbiteStringIds[] =
const u16 gFrostbiteHealedStringIds[] =
{
[B_MSG_FROSTBITE_HEALED] = STRINGID_PKMNFROSTBITEHEALED2,
[B_MSG_FROSTBITE_HEALED] = STRINGID_PKMNFROSTBITEHEALED,
[B_MSG_FROSTBITE_HEALED_BY_MOVE] = STRINGID_PKMNFROSTBITEHEALEDBY
};
@ -1224,7 +1222,7 @@ const u16 gGotFrozenStringIds[] =
const u16 gGotDefrostedStringIds[] =
{
[B_MSG_DEFROSTED] = STRINGID_PKMNWASDEFROSTED2,
[B_MSG_DEFROSTED] = STRINGID_PKMNWASDEFROSTED,
[B_MSG_DEFROSTED_BY_MOVE] = STRINGID_PKMNWASDEFROSTEDBY
};

View File

@ -17,7 +17,7 @@ static enum Move GetOriginallyUsedMove(enum Move chosenMove);
static void SetSameMoveTurnValues(enum BattleMoveEffects moveEffect);
static void TryClearChargeVolatile(enum Type moveType);
static inline bool32 IsBattlerUsingBeakBlast(enum BattlerId battler);
static void RequestNonVolatileChangee(enum BattlerId battlerAtk);
static void RequestNonVolatileChange(enum BattlerId battlerAtk);
static bool32 CanBattlerBounceBackMove(struct BattleContext *ctx);
static bool32 TryMagicBounce(struct BattleContext *ctx);
static bool32 TryMagicCoat(struct BattleContext *ctx);
@ -97,6 +97,13 @@ static enum CancelerResult CancelerChillyReception(struct BattleContext *ctx)
return CANCELER_RESULT_SUCCESS;
}
static void DefrostBattler(enum BattlerId battler, u32 status)
{
gBattleScripting.battler = battler;
gBattleMons[battler].status1 &= ~status;
RequestNonVolatileChange(battler);
}
static enum CancelerResult CancelerAsleepOrFrozen(struct BattleContext *ctx)
{
enum CancelerResult result = CANCELER_RESULT_BREAK;
@ -153,7 +160,7 @@ static enum CancelerResult CancelerAsleepOrFrozen(struct BattleContext *ctx)
BattleScriptCall(BattleScript_MoveUsedWokeUp);
}
}
RequestNonVolatileChangee(ctx->battlerAtk);
RequestNonVolatileChange(ctx->battlerAtk);
}
else if (gBattleMons[ctx->battlerAtk].status1 & STATUS1_FREEZE && !MoveThawsUser(ctx->move))
{
@ -164,12 +171,11 @@ static enum CancelerResult CancelerAsleepOrFrozen(struct BattleContext *ctx)
}
else // unfreeze
{
gBattleMons[ctx->battlerAtk].status1 &= ~STATUS1_FREEZE;
DefrostBattler(ctx->battlerAtk, STATUS1_FREEZE);
result = CANCELER_RESULT_BREAK;
BattleScriptCall(BattleScript_MoveUsedUnfroze);
BattleScriptCall(BattleScript_BattlerDefrosted);
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_DEFROSTED;
}
RequestNonVolatileChangee(ctx->battlerAtk);
}
return result;
@ -564,35 +570,36 @@ static enum CancelerResult CancelerThaw(struct BattleContext *ctx)
{
enum CancelerResult result = CANCELER_RESULT_BREAK;
if (MoveThawsUser(ctx->move))
{
if (gBattleMons[ctx->battlerAtk].status1 & STATUS1_FREEZE)
{
if (!(IsMoveEffectRemoveSpeciesType(ctx->move, MOVE_EFFECT_REMOVE_ARG_TYPE, TYPE_FIRE) && !IS_BATTLER_OF_TYPE(ctx->battlerAtk, TYPE_FIRE)))
if (!IsMoveEffectRemoveSpeciesType(ctx->move, MOVE_EFFECT_REMOVE_ARG_TYPE, TYPE_FIRE) || IS_BATTLER_OF_TYPE(ctx->battlerAtk, TYPE_FIRE))
{
gBattleMons[ctx->battlerAtk].status1 &= ~STATUS1_FREEZE;
DefrostBattler(ctx->battlerAtk, STATUS1_FREEZE);
result = CANCELER_RESULT_BREAK;
BattleScriptCall(BattleScript_MoveUsedUnfroze);
BattleScriptCall(BattleScript_BattlerDefrosted);
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_DEFROSTED_BY_MOVE;
}
else
{
result = CANCELER_RESULT_FAILURE;
}
RequestNonVolatileChangee(ctx->battlerAtk);
}
else if (gBattleMons[ctx->battlerAtk].status1 & STATUS1_FROSTBITE && MoveThawsUser(ctx->move))
else if (gBattleMons[ctx->battlerAtk].status1 & STATUS1_FROSTBITE)
{
if (!(IsMoveEffectRemoveSpeciesType(ctx->move, MOVE_EFFECT_REMOVE_ARG_TYPE, TYPE_FIRE) && !IS_BATTLER_OF_TYPE(ctx->battlerAtk, TYPE_FIRE)))
if (!IsMoveEffectRemoveSpeciesType(ctx->move, MOVE_EFFECT_REMOVE_ARG_TYPE, TYPE_FIRE) || IS_BATTLER_OF_TYPE(ctx->battlerAtk, TYPE_FIRE))
{
gBattleMons[ctx->battlerAtk].status1 &= ~STATUS1_FROSTBITE;
DefrostBattler(ctx->battlerAtk, STATUS1_FROSTBITE);
result = CANCELER_RESULT_BREAK;
BattleScriptCall(BattleScript_MoveUsedUnfrostbite);
BattleScriptCall(BattleScript_BattlerFrostbiteHealed);
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_FROSTBITE_HEALED_BY_MOVE;
}
else
{
result = CANCELER_RESULT_FAILURE;
}
RequestNonVolatileChangee(ctx->battlerAtk);
}
}
return result;
}
@ -2827,17 +2834,10 @@ static enum MoveEndResult MoveEndMultihitMove(void)
return result;
}
static void DefrostBattler(enum BattlerId battler, u32 status)
{
gBattleScripting.battler = battler;
gBattleMons[battler].status1 &= ~status;
BtlController_EmitSetMonData(battler, B_COMM_TO_CONTROLLER, REQUEST_STATUS_BATTLE, 0, sizeof(gBattleMons[battler].status1), &gBattleMons[battler].status1);
MarkBattlerForControllerExec(battler);
}
static enum MoveEndResult MoveEndDefrost(void)
{
enum Ability abilityAtk = GetBattlerAbility(gBattlerAttacker);
const u8 *battleScript = NULL;
while (gBattleStruct->eventState.moveEndBattler < gBattlersCount)
{
@ -2846,32 +2846,29 @@ static enum MoveEndResult MoveEndDefrost(void)
if (battler == gBattlerAttacker)
continue;
if (gBattleMons[battler].status1 & STATUS1_FREEZE
&& IsBattlerTurnDamaged(battler)
&& IsBattlerAlive(battler)
&& GetBattleMoveType(gCurrentMove) == TYPE_FIRE)
if (!(gBattleMons[battler].status1 & STATUS1_ICY_ANY)
|| !IsBattlerTurnDamaged(battler)
|| !IsBattlerAlive(battler))
continue;
if (gBattleMons[battler].status1 & STATUS1_FREEZE)
battleScript = BattleScript_BattlerDefrosted;
else
battleScript = BattleScript_BattlerFrostbiteHealed;
if ((CanFireMoveThawTarget(gCurrentMove) || CanBurnHitThaw(gCurrentMove)) && gBattleMons[battler].status1 & STATUS1_FREEZE)
{
DefrostBattler(battler, STATUS1_FREEZE);
BattleScriptCall(BattleScript_DefrostedViaFireMove);
DefrostBattler(battler, gBattleMons[battler].status1);
BattleScriptCall(battleScript);
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_DEFROSTED;
return MOVEEND_RESULT_RUN_SCRIPT;
}
else if (gBattleMons[battler].status1 & STATUS1_FREEZE
&& IsBattlerTurnDamaged(battler)
&& IsBattlerAlive(battler)
&& IsBattlerAlive(gBattlerAttacker)
&& CanBurnHitThaw(abilityAtk, gCurrentMove))
else if (IsBattlerAlive(gBattlerAttacker)
&& CanMoveThawTarget(abilityAtk, gCurrentMove))
{
DefrostBattler(battler, STATUS1_FREEZE);
BattleScriptCall(BattleScript_DefrostedViaFireMove);
return MOVEEND_RESULT_RUN_SCRIPT;
}
else if (gBattleMons[battler].status1 & STATUS1_FROSTBITE
&& IsBattlerTurnDamaged(battler)
&& IsBattlerAlive(battler)
&& MoveThawsUser(GetOriginallyUsedMove(gChosenMove)))
{
DefrostBattler(battler, STATUS1_FROSTBITE);
BattleScriptCall(BattleScript_FrostbiteHealedViaFireMove);
DefrostBattler(battler, gBattleMons[battler].status1);
BattleScriptCall(battleScript);
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_DEFROSTED;
return MOVEEND_RESULT_RUN_SCRIPT;
}
}
@ -3692,6 +3689,7 @@ static enum MoveEndResult MoveEndClearBits(void)
gBattleStruct->swapDamageCategory = FALSE;
gBattleStruct->categoryOverride = FALSE;
gBattleStruct->additionalEffectsCounter = 0;
gBattleStruct->triAttackBurn = FALSE;
gBattleStruct->poisonPuppeteerConfusion = FALSE;
gBattleStruct->fickleBeamBoosted = FALSE;
gBattleStruct->battlerState[gBattlerAttacker].usedMicleBerry = FALSE;
@ -3964,14 +3962,14 @@ void MoveValuesCleanUp(void)
gBattleCommunication[MISS_TYPE] = 0;
}
static void RequestNonVolatileChangee(enum BattlerId battlerAtk)
static void RequestNonVolatileChange(enum BattlerId battlerAtk)
{
BtlController_EmitSetMonData(
battlerAtk,
B_COMM_TO_CONTROLLER,
REQUEST_STATUS_BATTLE,
0,
4,
sizeof(gBattleMons[battlerAtk].status1),
&gBattleMons[battlerAtk].status1);
MarkBattlerForControllerExec(battlerAtk);
}

View File

@ -2554,11 +2554,6 @@ void SetMoveEffect(enum BattlerId battlerAtk, enum BattlerId effectBattler, enum
gBattlescriptCurrInstr = battleScript;
break;
case MOVE_EFFECT_TRI_ATTACK:
if (gBattleMons[gEffectBattler].status1)
{
gBattlescriptCurrInstr = battleScript;
}
else
{
static const u8 sTriAttackEffects[] =
{
@ -2566,9 +2561,14 @@ void SetMoveEffect(enum BattlerId battlerAtk, enum BattlerId effectBattler, enum
MOVE_EFFECT_FREEZE_OR_FROSTBITE,
MOVE_EFFECT_PARALYSIS
};
SetMoveEffect(battlerAtk, effectBattler, RandomElement(RNG_TRI_ATTACK, sTriAttackEffects), battleScript, effectFlags);
}
u32 chosenMoveEffect = RandomUniform(RNG_TRI_ATTACK, 0, ARRAY_COUNT(sTriAttackEffects) - 1);
if (sTriAttackEffects[chosenMoveEffect] == MOVE_EFFECT_BURN)
gBattleStruct->triAttackBurn = TRUE;
if (!gBattleMons[effectBattler].status1)
SetMoveEffect(battlerAtk, effectBattler, sTriAttackEffects[chosenMoveEffect], battleScript, effectFlags);
break;
}
case MOVE_EFFECT_WRAP:
if (gBattleMons[gEffectBattler].volatiles.wrapped)
{
@ -3438,6 +3438,7 @@ void SetMoveEffect(enum BattlerId battlerAtk, enum BattlerId effectBattler, enum
if ((gBattleMons[gEffectBattler].status1 & argStatus)
&& (NumAffectedSpreadMoveTargets() > 1 || !IsMoveEffectBlockedByTarget(abilities[gEffectBattler])))
{
gBattleScripting.battler = gEffectBattler;
gBattleMons[gEffectBattler].status1 &= ~(argStatus);
BtlController_EmitSetMonData(gEffectBattler, 0, REQUEST_STATUS_BATTLE, 0, 4, &gBattleMons[gEffectBattler].status1);
MarkBattlerForControllerExec(gEffectBattler);
@ -3456,10 +3457,10 @@ void SetMoveEffect(enum BattlerId battlerAtk, enum BattlerId effectBattler, enum
gBattlescriptCurrInstr = BattleScript_TargetBurnHeal;
break;
case STATUS1_FREEZE:
gBattlescriptCurrInstr = BattleScript_DefrostedViaFireMove;
gBattlescriptCurrInstr = BattleScript_BattlerDefrosted;
break;
case STATUS1_FROSTBITE:
gBattlescriptCurrInstr = BattleScript_FrostbiteHealedViaFireMove;
gBattlescriptCurrInstr = BattleScript_BattlerFrostbiteHealed;
break;
case STATUS1_POISON:
case STATUS1_TOXIC_POISON:
@ -11652,11 +11653,11 @@ static bool32 CanAbilityPreventStatLoss(enum Ability abilityDef)
return FALSE;
}
bool32 CanBurnHitThaw(enum Ability abilityAtk, enum Move move)
bool32 CanBurnHitThaw(enum Move move)
{
u8 i;
if (GetConfig(B_BURN_HIT_THAW) >= GEN_6 && abilityAtk != ABILITY_SHEER_FORCE)
if (GetConfig(B_HIT_THAW) <= GEN_2)
{
u32 numAdditionalEffects = GetMoveAdditionalEffectCount(move);
for (i = 0; i < numAdditionalEffects; i++)
@ -11664,11 +11665,25 @@ bool32 CanBurnHitThaw(enum Ability abilityAtk, enum Move move)
const struct AdditionalEffect *additionalEffect = GetMoveAdditionalEffectById(move, i);
if (additionalEffect->moveEffect == MOVE_EFFECT_BURN)
return TRUE;
if (additionalEffect->moveEffect == MOVE_EFFECT_TRI_ATTACK
&& gBattleStruct->triAttackBurn)
return TRUE;
}
}
return FALSE;
}
bool32 CanMoveThawTarget(enum Ability abilityAtk, enum Move move)
{
return GetConfig(B_HIT_THAW) >= GEN_6 && !IsSheerForceAffected(move, abilityAtk) && MoveThawsUser(move);
}
bool32 CanFireMoveThawTarget(enum Move move)
{
return GetConfig(B_HIT_THAW) >= GEN_3 && GetMoveType(move) == TYPE_FIRE && GetMovePower(move) != 0;
}
void BS_CheckParentalBondCounter(void)
{
NATIVE_ARGS(u8 counter, const u8 *jumpInstr);

View File

@ -189,7 +189,8 @@ u32 BattlePalace_TryEscapeStatus(enum BattlerId battler)
{
// Unfreeze
gBattleMons[battler].status1 &= ~(STATUS1_FREEZE);
BattleScriptCall(BattleScript_MoveUsedUnfroze);
gBattleScripting.battler = battler;
BattleScriptCall(BattleScript_BattlerDefrosted);
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_DEFROSTED;
}
effect = 2;

View File

@ -687,7 +687,7 @@ AI_SINGLE_BATTLE_TEST("AI won't use thawing moves if target is frozen unless it
PARAMETRIZE { status = STATUS1_FROSTBITE; aiMove = MOVE_EMBER; aiFlags = AI_FLAG_CHECK_BAD_MOVE; }
GIVEN {
WITH_CONFIG(B_BURN_HIT_THAW, GEN_6); // In Gen 5, non-Fire burning moves didn't cause thawing
WITH_CONFIG(B_HIT_THAW, GEN_6); // In Gen 5, moves that thawed the user didn't thaw the target
ASSUME(GetMoveType(MOVE_EMBER) == TYPE_FIRE);
ASSUME(GetMoveCategory(MOVE_TACKLE) == DAMAGE_CATEGORY_PHYSICAL);
ASSUME(GetMoveCategory(MOVE_WATER_GUN) == DAMAGE_CATEGORY_SPECIAL);

View File

@ -14,25 +14,27 @@ SINGLE_BATTLE_TEST("Freeze has a 20% chance of being thawed")
}
}
SINGLE_BATTLE_TEST("Freeze is thawed by opponent's Fire-type attacks")
SINGLE_BATTLE_TEST("Freeze is thawed by opponent's Fire-type attacks (Gen 3+)")
{
GIVEN {
ASSUME(GetMoveType(MOVE_EMBER) == TYPE_FIRE);
WITH_CONFIG(B_HIT_THAW, GEN_3);
ASSUME(GetMoveType(MOVE_FIRE_SPIN) == TYPE_FIRE);
PLAYER(SPECIES_WOBBUFFET) { Status1(STATUS1_FREEZE); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(opponent, MOVE_EMBER); MOVE(player, MOVE_CELEBRATE); }
TURN { MOVE(opponent, MOVE_FIRE_SPIN); MOVE(player, MOVE_CELEBRATE); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_EMBER, opponent);
ANIMATION(ANIM_TYPE_MOVE, MOVE_FIRE_SPIN, opponent);
MESSAGE("Wobbuffet thawed out!");
STATUS_ICON(player, none: TRUE);
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, player);
}
}
SINGLE_BATTLE_TEST("Freeze is thawed by opponent's Fire-type attacks even if Sheer Force affected")
SINGLE_BATTLE_TEST("Freeze is thawed by opponent's Fire-type attacks even if Sheer Force affected (Gen 3+)")
{
GIVEN {
WITH_CONFIG(B_HIT_THAW, GEN_3);
ASSUME(GetMoveType(MOVE_EMBER) == TYPE_FIRE);
PLAYER(SPECIES_WOBBUFFET) { Status1(STATUS1_FREEZE); }
OPPONENT(SPECIES_TAUROS) { Ability(ABILITY_SHEER_FORCE); }
@ -46,11 +48,46 @@ SINGLE_BATTLE_TEST("Freeze is thawed by opponent's Fire-type attacks even if She
}
}
SINGLE_BATTLE_TEST("Freeze is thawed by opponent's attack that can burn (Gen 6+)")
SINGLE_BATTLE_TEST("Freeze is thawed by opponent's attack that can burn (Gen 1-2)")
{
GIVEN {
WITH_CONFIG(B_BURN_HIT_THAW, GEN_6);
ASSUME(MoveHasAdditionalEffect(MOVE_SCALD, MOVE_EFFECT_BURN));
WITH_CONFIG(B_HIT_THAW, GEN_2);
ASSUME(MoveHasAdditionalEffect(MOVE_EMBER, MOVE_EFFECT_BURN));
PLAYER(SPECIES_WOBBUFFET) { Status1(STATUS1_FREEZE); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(opponent, MOVE_EMBER); MOVE(player, MOVE_CELEBRATE); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_EMBER, opponent);
MESSAGE("Wobbuffet thawed out!");
STATUS_ICON(player, none: TRUE);
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, player);
}
}
SINGLE_BATTLE_TEST("Freeze is thawed by opponent's Tri Attack 1/3 of the time (Gen 1-2)")
{
PASSES_RANDOMLY(1, 3, RNG_TRI_ATTACK);
GIVEN {
WITH_CONFIG(B_HIT_THAW, GEN_2);
ASSUME(MoveHasAdditionalEffect(MOVE_TRI_ATTACK, MOVE_EFFECT_TRI_ATTACK));
PLAYER(SPECIES_WOBBUFFET) { Status1(STATUS1_FREEZE); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(opponent, MOVE_TRI_ATTACK); MOVE(player, MOVE_CELEBRATE, WITH_RNG(RNG_FROZEN, FALSE)); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_TRI_ATTACK, opponent);
MESSAGE("Wobbuffet thawed out!");
STATUS_ICON(player, none: TRUE);
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, player);
}
}
SINGLE_BATTLE_TEST("Freeze is thawed by opponent's attack that can thaw the user (Gen 6+)")
{
GIVEN {
WITH_CONFIG(B_HIT_THAW, GEN_6);
ASSUME(MoveThawsUser(MOVE_SCALD));
PLAYER(SPECIES_WOBBUFFET) { Status1(STATUS1_FREEZE); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
@ -62,24 +99,45 @@ SINGLE_BATTLE_TEST("Freeze is thawed by opponent's attack that can burn (Gen 6+)
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, player);
}
}
SINGLE_BATTLE_TEST("Freeze isn't thawed by opponent's attack that can burn if Sheer Force affected (Gen 6+)")
SINGLE_BATTLE_TEST("Freeze isn't thawed by opponent's attack that can thaw the user if Sheer Force affected (Gen 6+)")
{
GIVEN {
WITH_CONFIG(B_BURN_HIT_THAW, GEN_6);
ASSUME(MoveHasAdditionalEffect(MOVE_SCALD, MOVE_EFFECT_BURN));
WITH_CONFIG(B_HIT_THAW, GEN_6);
ASSUME(MoveThawsUser(MOVE_SCALD));
ASSUME(MoveIsAffectedBySheerForce(MOVE_SCALD));
PLAYER(SPECIES_WOBBUFFET) { Status1(STATUS1_FREEZE); }
OPPONENT(SPECIES_TAUROS) { Ability(ABILITY_SHEER_FORCE); }
} WHEN {
TURN { MOVE(opponent, MOVE_SCALD); }
TURN { MOVE(opponent, MOVE_SCALD); MOVE(player, MOVE_CELEBRATE, WITH_RNG(RNG_FROZEN, FALSE)); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_SCALD, opponent);
NONE_OF {
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, player);
MESSAGE("Wobbuffet thawed out!");
STATUS_ICON(player, none: TRUE);
}
}
}
SINGLE_BATTLE_TEST("Freeze is thawed by opponent's attack that can thaw the user if not Sheer Force affected (Gen 6+)")
{
GIVEN {
WITH_CONFIG(B_HIT_THAW, GEN_6);
ASSUME(MoveThawsUser(MOVE_HYDRO_STEAM));
ASSUME(!MoveIsAffectedBySheerForce(MOVE_HYDRO_STEAM));
PLAYER(SPECIES_WOBBUFFET) { Status1(STATUS1_FREEZE); }
OPPONENT(SPECIES_TAUROS) { Ability(ABILITY_SHEER_FORCE); }
} WHEN {
TURN { MOVE(opponent, MOVE_HYDRO_STEAM); MOVE(player, MOVE_CELEBRATE); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_HYDRO_STEAM, opponent);
MESSAGE("Wobbuffet thawed out!");
STATUS_ICON(player, none: TRUE);
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, player);
}
}
SINGLE_BATTLE_TEST("Freeze is thawed by user's Flame Wheel")
{
GIVEN {