Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Roost suppresses the user's Flying-type rather than remove and re-add it. Added tests for EFFECT_ROOST. #3258

Merged
merged 12 commits into from
Oct 5, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion include/battle.h
Original file line number Diff line number Diff line change
Expand Up @@ -723,7 +723,7 @@ STATIC_ASSERT(sizeof(((struct BattleStruct *)0)->palaceFlags) * 8 >= MAX_BATTLER
#define TARGET_TURN_DAMAGED ((gSpecialStatuses[gBattlerTarget].physicalDmg != 0 || gSpecialStatuses[gBattlerTarget].specialDmg != 0))
#define BATTLER_DAMAGED(battlerId) ((gSpecialStatuses[battlerId].physicalDmg != 0 || gSpecialStatuses[battlerId].specialDmg != 0))

#define IS_BATTLER_OF_TYPE(battlerId, type)((gBattleMons[battlerId].type1 == type || gBattleMons[battlerId].type2 == type || (gBattleMons[battlerId].type3 != TYPE_MYSTERY && gBattleMons[battlerId].type3 == type)))
#define IS_BATTLER_OF_TYPE(battlerId, type)((GetBattlerType(battlerId, 0) == type || GetBattlerType(battlerId, 1) == type || (GetBattlerType(battlerId, 2) != TYPE_MYSTERY && GetBattlerType(battlerId, 2) == type)))
#define SET_BATTLER_TYPE(battlerId, type) \
{ \
gBattleMons[battlerId].type1 = type; \
Expand Down
1 change: 1 addition & 0 deletions include/battle_util.h
Original file line number Diff line number Diff line change
Expand Up @@ -248,5 +248,6 @@ void RemoveConfusionStatus(u32 battler);
u8 GetBattlerGender(u32 battler);
bool32 AreBattlersOfOppositeGender(u32 battler1, u32 battler2);
u32 CalcSecondaryEffectChance(u32 battler, u8 secondaryEffectChance);
u8 GetBattlerType(u32 battler, u8 typeIndex);

#endif // GUARD_BATTLE_UTIL_H
18 changes: 9 additions & 9 deletions src/battle_ai_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -2430,9 +2430,9 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
break;
case EFFECT_SOAK:
if (PartnerMoveIsSameAsAttacker(BATTLE_PARTNER(battlerAtk), battlerDef, move, aiData->partnerMove)
|| (gBattleMons[battlerDef].type1 == TYPE_WATER
&& gBattleMons[battlerDef].type2 == TYPE_WATER
&& gBattleMons[battlerDef].type3 == TYPE_MYSTERY))
|| (GetBattlerType(battlerDef, 0) == TYPE_WATER
&& GetBattlerType(battlerDef, 1) == TYPE_WATER
&& GetBattlerType(battlerDef, 2) == TYPE_MYSTERY))
score -= 10; // target is already water-only
break;
case EFFECT_THIRD_TYPE:
Expand Down Expand Up @@ -2582,9 +2582,9 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
case EFFECT_SYNCHRONOISE:
//Check holding ring target or is of same type
if (aiData->holdEffects[battlerDef] == HOLD_EFFECT_RING_TARGET
|| IS_BATTLER_OF_TYPE(battlerDef, gBattleMons[battlerAtk].type1)
|| IS_BATTLER_OF_TYPE(battlerDef, gBattleMons[battlerAtk].type2)
|| IS_BATTLER_OF_TYPE(battlerDef, gBattleMons[battlerAtk].type3))
|| IS_BATTLER_OF_TYPE(battlerDef, GetBattlerType(battlerAtk, 0))
|| IS_BATTLER_OF_TYPE(battlerDef, GetBattlerType(battlerAtk, 1))
|| IS_BATTLER_OF_TYPE(battlerDef, GetBattlerType(battlerAtk, 2)))
break;
else
score -= 10;
Expand Down Expand Up @@ -3025,9 +3025,9 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
break;
case EFFECT_SOAK:
if (atkPartnerAbility == ABILITY_WONDER_GUARD
&& (gBattleMons[battlerAtkPartner].type1 != TYPE_WATER
|| gBattleMons[battlerAtkPartner].type2 != TYPE_WATER
|| gBattleMons[battlerAtkPartner].type3 != TYPE_WATER))
&& (GetBattlerType(battlerAtkPartner, 0) != TYPE_WATER
|| GetBattlerType(battlerAtkPartner, 1) != TYPE_WATER
|| GetBattlerType(battlerAtkPartner, 2) != TYPE_WATER))
{
RETURN_SCORE_PLUS(1);
}
Expand Down
64 changes: 19 additions & 45 deletions src/battle_script_commands.c
Original file line number Diff line number Diff line change
Expand Up @@ -2126,12 +2126,12 @@ static void Cmd_adjustdamage(void)
// of a move that is Super Effective against a Flying-type Pokémon.
if (gBattleWeather & B_WEATHER_STRONG_WINDS)
{
if ((gBattleMons[gBattlerTarget].type1 == TYPE_FLYING
&& GetTypeModifier(moveType, gBattleMons[gBattlerTarget].type1) >= UQ_4_12(2.0))
|| (gBattleMons[gBattlerTarget].type2 == TYPE_FLYING
&& GetTypeModifier(moveType, gBattleMons[gBattlerTarget].type2) >= UQ_4_12(2.0))
|| (gBattleMons[gBattlerTarget].type3 == TYPE_FLYING
&& GetTypeModifier(moveType, gBattleMons[gBattlerTarget].type3) >= UQ_4_12(2.0)))
if ((GetBattlerType(gBattlerTarget, 0) == TYPE_FLYING
&& GetTypeModifier(moveType, GetBattlerType(gBattlerTarget, 0)) >= UQ_4_12(2.0))
|| (GetBattlerType(gBattlerTarget, 1) == TYPE_FLYING
&& GetTypeModifier(moveType, GetBattlerType(gBattlerTarget, 1)) >= UQ_4_12(2.0))
|| (GetBattlerType(gBattlerTarget, 2) == TYPE_FLYING
&& GetTypeModifier(moveType, GetBattlerType(gBattlerTarget, 2)) >= UQ_4_12(2.0)))
{
gBattlerAbility = gBattlerTarget;
BattleScriptPushCursor();
Expand Down Expand Up @@ -4909,34 +4909,8 @@ static void Cmd_setroost(void)
CMD_ARGS();

gBattleResources->flags->flags[gBattlerAttacker] |= RESOURCE_FLAG_ROOST;

// Pure flying type.
if (gBattleMons[gBattlerAttacker].type1 == TYPE_FLYING && gBattleMons[gBattlerAttacker].type2 == TYPE_FLYING)
{
gBattleStruct->roostTypes[gBattlerAttacker][0] = TYPE_FLYING;
gBattleStruct->roostTypes[gBattlerAttacker][1] = TYPE_FLYING;
#if B_ROOST_PURE_FLYING >= GEN_5
SET_BATTLER_TYPE(gBattlerAttacker, TYPE_NORMAL);
#else
SET_BATTLER_TYPE(gBattlerAttacker, TYPE_MYSTERY);
#endif
}
// Dual type with flying type.
else if (gBattleMons[gBattlerAttacker].type1 == TYPE_FLYING || gBattleMons[gBattlerAttacker].type2 == TYPE_FLYING)
{
gBattleStruct->roostTypes[gBattlerAttacker][0] = gBattleMons[gBattlerAttacker].type1;
gBattleStruct->roostTypes[gBattlerAttacker][1] = gBattleMons[gBattlerAttacker].type2;
if (gBattleMons[gBattlerAttacker].type1 == TYPE_FLYING)
gBattleMons[gBattlerAttacker].type1 = TYPE_MYSTERY;
else if (gBattleMons[gBattlerAttacker].type2 == TYPE_FLYING)
gBattleMons[gBattlerAttacker].type2 = TYPE_MYSTERY;
}
// Non-flying type.
else
{
gBattleStruct->roostTypes[gBattlerAttacker][0] = gBattleMons[gBattlerAttacker].type1;
gBattleStruct->roostTypes[gBattlerAttacker][1] = gBattleMons[gBattlerAttacker].type2;
}
gBattleStruct->roostTypes[gBattlerAttacker][0] = gBattleMons[gBattlerAttacker].type1;
gBattleStruct->roostTypes[gBattlerAttacker][1] = gBattleMons[gBattlerAttacker].type2;

gBattlescriptCurrInstr = cmd->nextInstr;
}
Expand Down Expand Up @@ -9442,35 +9416,35 @@ static void Cmd_various(void)
{
gBattlescriptCurrInstr = cmd->failInstr;
}
else if (gBattleMons[gBattlerTarget].type1 == TYPE_MYSTERY && gBattleMons[gBattlerTarget].type2 != TYPE_MYSTERY)
else if (GetBattlerType(gBattlerTarget, 0) == TYPE_MYSTERY && GetBattlerType(gBattlerTarget, 1) != TYPE_MYSTERY)
{
gBattleMons[gBattlerAttacker].type1 = gBattleMons[gBattlerTarget].type2;
gBattleMons[gBattlerAttacker].type2 = gBattleMons[gBattlerTarget].type2;
gBattleMons[gBattlerAttacker].type1 = GetBattlerType(gBattlerTarget, 1);
gBattleMons[gBattlerAttacker].type2 = GetBattlerType(gBattlerTarget, 1);
gBattlescriptCurrInstr = cmd->nextInstr;
}
else if (gBattleMons[gBattlerTarget].type1 != TYPE_MYSTERY && gBattleMons[gBattlerTarget].type2 == TYPE_MYSTERY)
else if (GetBattlerType(gBattlerTarget, 0) != TYPE_MYSTERY && GetBattlerType(gBattlerTarget, 1) == TYPE_MYSTERY)
{
gBattleMons[gBattlerAttacker].type1 = gBattleMons[gBattlerTarget].type1;
gBattleMons[gBattlerAttacker].type2 = gBattleMons[gBattlerTarget].type1;
gBattleMons[gBattlerAttacker].type1 = GetBattlerType(gBattlerTarget, 0);
gBattleMons[gBattlerAttacker].type2 = GetBattlerType(gBattlerTarget, 0);
gBattlescriptCurrInstr = cmd->nextInstr;
}
else if (gBattleMons[gBattlerTarget].type1 == TYPE_MYSTERY && gBattleMons[gBattlerTarget].type2 == TYPE_MYSTERY)
else if (GetBattlerType(gBattlerTarget, 0) == TYPE_MYSTERY && GetBattlerType(gBattlerTarget, 1) == TYPE_MYSTERY)
{
gBattlescriptCurrInstr = cmd->failInstr;
}
else
{
gBattleMons[gBattlerAttacker].type1 = gBattleMons[gBattlerTarget].type1;
gBattleMons[gBattlerAttacker].type2 = gBattleMons[gBattlerTarget].type2;
gBattleMons[gBattlerAttacker].type1 = GetBattlerType(gBattlerTarget, 0);
gBattleMons[gBattlerAttacker].type2 = GetBattlerType(gBattlerTarget, 1);
gBattlescriptCurrInstr = cmd->nextInstr;
}
return;
}
case VARIOUS_TRY_SOAK:
{
VARIOUS_ARGS(const u8 *failInstr);
if (gBattleMons[gBattlerTarget].type1 == gBattleMoves[gCurrentMove].type
&& gBattleMons[gBattlerTarget].type2 == gBattleMoves[gCurrentMove].type)
if (GetBattlerType(gBattlerTarget, 0) == gBattleMoves[gCurrentMove].type
&& GetBattlerType(gBattlerTarget, 1) == gBattleMoves[gCurrentMove].type)
{
gBattlescriptCurrInstr = cmd->failInstr;
}
Expand Down
48 changes: 36 additions & 12 deletions src/battle_util.c
Original file line number Diff line number Diff line change
Expand Up @@ -3065,11 +3065,7 @@ u8 DoBattlerEndTurnEffects(void)
break;
case ENDTURN_ROOST: // Return flying type.
if (gBattleResources->flags->flags[battler] & RESOURCE_FLAG_ROOST)
{
gBattleResources->flags->flags[battler] &= ~RESOURCE_FLAG_ROOST;
gBattleMons[battler].type1 = gBattleStruct->roostTypes[battler][0];
gBattleMons[battler].type2 = gBattleStruct->roostTypes[battler][1];
}
gBattleStruct->turnEffectsTracker++;
break;
case ENDTURN_ELECTRIFY:
Expand Down Expand Up @@ -9990,12 +9986,12 @@ static inline uq4_12_t CalcTypeEffectivenessMultiplierInternal(u32 move, u32 mov
{
u32 illusionSpecies;

MulByTypeEffectiveness(&modifier, move, moveType, battlerDef, gBattleMons[battlerDef].type1, battlerAtk, recordAbilities);
if (gBattleMons[battlerDef].type2 != gBattleMons[battlerDef].type1)
MulByTypeEffectiveness(&modifier, move, moveType, battlerDef, gBattleMons[battlerDef].type2, battlerAtk, recordAbilities);
if (gBattleMons[battlerDef].type3 != TYPE_MYSTERY && gBattleMons[battlerDef].type3 != gBattleMons[battlerDef].type2
&& gBattleMons[battlerDef].type3 != gBattleMons[battlerDef].type1)
MulByTypeEffectiveness(&modifier, move, moveType, battlerDef, gBattleMons[battlerDef].type3, battlerAtk, recordAbilities);
MulByTypeEffectiveness(&modifier, move, moveType, battlerDef, GetBattlerType(battlerDef, 0), battlerAtk, recordAbilities);
if (GetBattlerType(battlerDef, 1) != GetBattlerType(battlerDef, 0))
MulByTypeEffectiveness(&modifier, move, moveType, battlerDef, GetBattlerType(battlerDef, 1), battlerAtk, recordAbilities);
if (GetBattlerType(battlerDef, 2) != TYPE_MYSTERY && GetBattlerType(battlerDef, 2) != GetBattlerType(battlerDef, 1)
&& GetBattlerType(battlerDef, 2) != GetBattlerType(battlerDef, 0))
MulByTypeEffectiveness(&modifier, move, moveType, battlerDef, GetBattlerType(battlerDef, 2), battlerAtk, recordAbilities);

if (recordAbilities && (illusionSpecies = GetIllusionMonSpecies(battlerDef)))
TryNoticeIllusionInTypeEffectiveness(move, moveType, battlerAtk, battlerDef, modifier, illusionSpecies);
Expand Down Expand Up @@ -10506,8 +10502,8 @@ bool32 TryBattleFormChange(u32 battler, u16 method)
bool32 DoBattlersShareType(u32 battler1, u32 battler2)
{
s32 i;
u8 types1[3] = {gBattleMons[battler1].type1, gBattleMons[battler1].type2, gBattleMons[battler1].type3};
u8 types2[3] = {gBattleMons[battler2].type1, gBattleMons[battler2].type2, gBattleMons[battler2].type3};
u8 types1[3] = {GetBattlerType(battler1, 0), GetBattlerType(battler1, 1), GetBattlerType(battler1, 2)};
u8 types2[3] = {GetBattlerType(battler2, 0), GetBattlerType(battler2, 1), GetBattlerType(battler2, 2)};

if (types1[2] == TYPE_MYSTERY)
types1[2] = types1[0];
Expand Down Expand Up @@ -11199,3 +11195,31 @@ bool32 IsGen6ExpShareEnabled(void)
return FlagGet(I_EXP_SHARE_FLAG);
#endif
}


u8 GetBattlerType(u32 battler, u8 typeIndex)
{
u16 types[3] = {0};
types[0] = gBattleMons[battler].type1;
types[1] = gBattleMons[battler].type2;
types[2] = gBattleMons[battler].type3;

// Handle Roost's Flying-type suppression
if (typeIndex == 0 || typeIndex == 1)
{
if (gBattleResources->flags->flags[battler] & RESOURCE_FLAG_ROOST)
{
if (types[0] == TYPE_FLYING && types[1] == TYPE_FLYING)
#if B_ROOST_PURE_FLYING >= GEN_5
return TYPE_NORMAL;
#else
return TYPE_MYSTERY;
#endif
else
return types[typeIndex] == TYPE_FLYING ? TYPE_MYSTERY : types[typeIndex];
}
}

return types[typeIndex];
}

Loading