utility umbrella effect

This commit is contained in:
ghoulslash 2021-05-24 09:52:45 -06:00
parent f7d6d42e6c
commit 5840b1f0ed
7 changed files with 76 additions and 44 deletions

View File

@ -1768,6 +1768,12 @@
.macro tryactivategrimneigh, battler:req
various \battler, VARIOUS_TRY_ACTIVATE_GRIM_NEIGH
.endm
.macro jumpifweatheraffected battler:req, weather:req, ptr:req
various \battler, VARIOUS_JUMP_IF_WEATHER_AFFECTED
.4byte \weather
.4byte \ptr
.endm
@ helpful macros
.macro setstatchanger stat:req, stages:req, down:req

View File

@ -1288,7 +1288,7 @@ BattleScript_GrowthDoMoveAnim::
waitanimation
setbyte sSTAT_ANIM_PLAYED, FALSE
playstatchangeanimation BS_ATTACKER, BIT_ATK | BIT_SPATK, 0
jumpifhalfword CMP_COMMON_BITS, gBattleWeather, WEATHER_SUN_ANY, BattleScript_GrowthAtk2
jumpifweatheraffected BS_ATTACKER, WEATHER_SUN_ANY, BattleScript_GrowthAtk2
setstatchanger STAT_ATK, 1, FALSE
goto BattleScript_GrowthAtk
BattleScript_GrowthAtk2:
@ -1299,7 +1299,7 @@ BattleScript_GrowthAtk:
printfromtable gStatUpStringIds
waitmessage B_WAIT_TIME_LONG
BattleScript_GrowthTrySpAtk::
jumpifhalfword CMP_COMMON_BITS, gBattleWeather, WEATHER_SUN_ANY, BattleScript_GrowthSpAtk2
jumpifweatheraffected BS_ATTACKER, WEATHER_SUN_ANY, BattleScript_GrowthSpAtk2
setstatchanger STAT_SPATK, 1, FALSE
goto BattleScript_GrowthSpAtk
BattleScript_GrowthSpAtk2:
@ -4015,9 +4015,7 @@ BattleScript_EffectGust::
goto BattleScript_EffectHit
BattleScript_EffectSolarbeam::
jumpifabilitypresent ABILITY_CLOUD_NINE, BattleScript_SolarbeamDecideTurn
jumpifabilitypresent ABILITY_AIR_LOCK, BattleScript_SolarbeamDecideTurn
jumpifhalfword CMP_COMMON_BITS, gBattleWeather, WEATHER_SUN_TEMPORARY | WEATHER_SUN_PERMANENT, BattleScript_SolarbeamOnFirstTurn
jumpifweatheraffected BS_ATTACKER, WEATHER_SUN_ANY, BattleScript_SolarbeamOnFirstTurn
BattleScript_SolarbeamDecideTurn::
jumpifstatus2 BS_ATTACKER, STATUS2_MULTIPLETURNS, BattleScript_TwoTurnMovesSecondTurn
jumpifword CMP_COMMON_BITS, gHitMarker, HITMARKER_NO_ATTACKSTRING, BattleScript_TwoTurnMovesSecondTurn

View File

@ -138,6 +138,7 @@ bool32 IsTelekinesisBannedSpecies(u16 species);
bool32 IsHealBlockPreventingMove(u32 battler, u32 move);
bool32 IsThawingMove(u8 battlerId, u16 move);
bool32 HasEnoughHpToEatBerry(u32 battlerId, u32 hpFraction, u32 itemId);
bool32 IsBattlerWeatherAffected(u8 battlerId, u32 weatherFlags);
// ability checks
bool32 IsRolePlayBannedAbilityAtk(u16 ability);

View File

@ -173,6 +173,7 @@
#define VARIOUS_DESTROY_ABILITY_POPUP 102
#define VARIOUS_TOTEM_BOOST 103
#define VARIOUS_TRY_ACTIVATE_GRIM_NEIGH 104
#define VARIOUS_JUMP_IF_WEATHER_AFFECTED 105
// Cmd_manipulatedamage
#define DMG_CHANGE_SIGN 0

View File

@ -4229,9 +4229,9 @@ u32 GetBattlerTotalSpeedStat(u8 battlerId)
// weather abilities
if (WEATHER_HAS_EFFECT)
{
if (ability == ABILITY_SWIFT_SWIM && gBattleWeather & WEATHER_RAIN_ANY)
if (ability == ABILITY_SWIFT_SWIM && holdEffect != HOLD_EFFECT_UTILITY_UMBRELLA && gBattleWeather & WEATHER_RAIN_ANY)
speed *= 2;
else if (ability == ABILITY_CHLOROPHYLL && gBattleWeather & WEATHER_SUN_ANY)
else if (ability == ABILITY_CHLOROPHYLL && holdEffect != HOLD_EFFECT_UTILITY_UMBRELLA && gBattleWeather & WEATHER_SUN_ANY)
speed *= 2;
else if (ability == ABILITY_SAND_RUSH && gBattleWeather & WEATHER_SANDSTORM_ANY)
speed *= 2;
@ -5002,6 +5002,7 @@ void RunBattleScriptCommands(void)
void SetTypeBeforeUsingMove(u16 move, u8 battlerAtk)
{
u32 moveType, ateType, attackerAbility;
u16 holdEffect = GetBattlerHoldEffect(battlerAtk, TRUE);
if (move == MOVE_STRUGGLE)
return;
@ -5014,11 +5015,11 @@ void SetTypeBeforeUsingMove(u16 move, u8 battlerAtk)
{
if (WEATHER_HAS_EFFECT)
{
if (gBattleWeather & WEATHER_RAIN_ANY)
if (gBattleWeather & WEATHER_RAIN_ANY && holdEffect != HOLD_EFFECT_UTILITY_UMBRELLA)
gBattleStruct->dynamicMoveType = TYPE_WATER | 0x80;
else if (gBattleWeather & WEATHER_SANDSTORM_ANY)
gBattleStruct->dynamicMoveType = TYPE_ROCK | 0x80;
else if (gBattleWeather & WEATHER_SUN_ANY)
else if (gBattleWeather & WEATHER_SUN_ANY && holdEffect != HOLD_EFFECT_UTILITY_UMBRELLA)
gBattleStruct->dynamicMoveType = TYPE_FIRE | 0x80;
else if (gBattleWeather & WEATHER_HAIL_ANY)
gBattleStruct->dynamicMoveType = TYPE_ICE | 0x80;
@ -5042,7 +5043,7 @@ void SetTypeBeforeUsingMove(u16 move, u8 battlerAtk)
}
else if (gBattleMoves[move].effect == EFFECT_CHANGE_TYPE_ON_ITEM)
{
if (GetBattlerHoldEffect(battlerAtk, TRUE) == gBattleMoves[move].argument)
if (holdEffect == gBattleMoves[move].argument)
gBattleStruct->dynamicMoveType = ItemId_GetSecondaryId(gBattleMons[battlerAtk].item) | 0x80;
}
else if (gBattleMoves[move].effect == EFFECT_REVELATION_DANCE)
@ -5098,7 +5099,7 @@ void SetTypeBeforeUsingMove(u16 move, u8 battlerAtk)
// Check if a gem should activate.
GET_MOVE_TYPE(move, moveType);
if (GetBattlerHoldEffect(battlerAtk, TRUE) == HOLD_EFFECT_GEMS
if (holdEffect == HOLD_EFFECT_GEMS
&& moveType == ItemId_GetSecondaryId(gBattleMons[battlerAtk].item))
{
gSpecialStatuses[battlerAtk].gemParam = GetBattlerHoldEffectParam(battlerAtk);

View File

@ -1474,13 +1474,13 @@ static bool32 AccuracyCalcHelper(u16 move)
return TRUE;
}
if ((WEATHER_HAS_EFFECT &&
(((gBattleWeather & WEATHER_RAIN_ANY) && (gBattleMoves[move].effect == EFFECT_THUNDER || gBattleMoves[move].effect == EFFECT_HURRICANE))
|| (((gBattleWeather & WEATHER_HAIL_ANY) && move == MOVE_BLIZZARD))))
|| (gBattleMoves[move].effect == EFFECT_VITAL_THROW)
|| (gBattleMoves[move].accuracy == 0)
|| ((B_MINIMIZE_DMG_ACC >= GEN_6) && (gStatuses3[gBattlerTarget] & STATUS3_MINIMIZED) && (gBattleMoves[move].flags & FLAG_DMG_MINIMIZE)))
if (gBattleMoves[move].effect == EFFECT_VITAL_THROW
|| gBattleMoves[move].accuracy == 0
|| ((B_MINIMIZE_DMG_ACC >= GEN_6) && (gStatuses3[gBattlerTarget] & STATUS3_MINIMIZED) && (gBattleMoves[move].flags & FLAG_DMG_MINIMIZE))
|| (IsBattlerWeatherAffected(gBattlerTarget, WEATHER_RAIN_ANY) && (gBattleMoves[move].effect == EFFECT_THUNDER || gBattleMoves[move].effect == EFFECT_HURRICANE))
|| (gBattleWeather & WEATHER_HAIL_ANY && move == MOVE_BLIZZARD))
{
// thunder/hurricane ignore acc checks in rain unless target is holding utility umbrella
JumpIfMoveFailed(7, move);
return TRUE;
}
@ -1523,8 +1523,8 @@ u32 GetTotalAccuracy(u32 battlerAtk, u32 battlerDef, u32 move)
moveAcc = gBattleMoves[move].accuracy;
// Check Thunder and Hurricane on sunny weather.
if (WEATHER_HAS_EFFECT && gBattleWeather & WEATHER_SUN_ANY
&& (gBattleMoves[move].effect == EFFECT_THUNDER || gBattleMoves[move].effect == EFFECT_HURRICANE))
if (IsBattlerWeatherAffected(battlerDef, WEATHER_SUN_ANY)
&& (gBattleMoves[move].effect == EFFECT_THUNDER || gBattleMoves[move].effect == EFFECT_HURRICANE))
moveAcc = 50;
// Check Wonder Skin.
if (defAbility == ABILITY_WONDER_SKIN && gBattleMoves[move].power == 0)
@ -2552,7 +2552,7 @@ void SetMoveEffect(bool32 primary, u32 certain)
statusChanged = TRUE;
break;
case STATUS1_FREEZE:
if (WEATHER_HAS_EFFECT && gBattleWeather & WEATHER_SUN_ANY)
if (IsBattlerWeatherAffected(gEffectBattler, WEATHER_SUN_ANY))
noSunCanFreeze = FALSE;
if (IS_BATTLER_OF_TYPE(gEffectBattler, TYPE_ICE))
break;
@ -7056,7 +7056,7 @@ u32 IsFlowerVeilProtected(u32 battler)
u32 IsLeafGuardProtected(u32 battler)
{
if (WEATHER_HAS_EFFECT && (gBattleWeather & WEATHER_SUN_ANY))
if (IsBattlerWeatherAffected(battler, WEATHER_SUN_ANY))
return GetBattlerAbility(battler) == ABILITY_LEAF_GUARD;
else
return 0;
@ -8349,6 +8349,15 @@ static void Cmd_various(void)
gBattlescriptCurrInstr += 7; // exit if loop failed (failsafe)
}
return;
case VARIOUS_JUMP_IF_WEATHER_AFFECTED:
{
u32 weatherFlags = T1_READ_32(gBattlescriptCurrInstr + 3);
if (IsBattlerWeatherAffected(gActiveBattler, weatherFlags))
gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 7);
else
gBattlescriptCurrInstr += 11;
}
return;
}
gBattlescriptCurrInstr += 3;
@ -10154,11 +10163,12 @@ static bool8 IsTwoTurnsMove(u16 move)
return FALSE;
}
// unused
static u8 AttacksThisTurn(u8 battlerId, u16 move) // Note: returns 1 if it's a charging turn, otherwise 2
{
// first argument is unused
if (gBattleMoves[move].effect == EFFECT_SOLARBEAM
&& (gBattleWeather & WEATHER_SUN_ANY))
&& IsBattlerWeatherAffected(battlerId, WEATHER_SUN_ANY))
return 2;
if (gBattleMoves[move].effect == EFFECT_SKULL_BASH
@ -10816,7 +10826,7 @@ static void Cmd_recoverbasedonsunlight(void)
{
if (!(gBattleWeather & WEATHER_ANY) || !WEATHER_HAS_EFFECT)
gBattleMoveDamage = gBattleMons[gBattlerAttacker].maxHP / 2;
else if (gBattleWeather & WEATHER_SUN_ANY)
else if (IsBattlerWeatherAffected(gBattlerAttacker, WEATHER_SUN_ANY))
gBattleMoveDamage = 20 * gBattleMons[gBattlerAttacker].maxHP / 30;
else // not sunny weather
gBattleMoveDamage = gBattleMons[gBattlerAttacker].maxHP / 4;

View File

@ -3608,7 +3608,8 @@ u8 TryWeatherFormChange(u8 battler)
{
u8 ret = 0;
bool32 weatherEffect = WEATHER_HAS_EFFECT;
u16 holdEffect = GetBattlerHoldEffect(battler, TRUE);
if (gBattleMons[battler].species == SPECIES_CASTFORM)
{
if (gBattleMons[battler].ability != ABILITY_FORECAST || gBattleMons[battler].hp == 0)
@ -3624,17 +3625,17 @@ u8 TryWeatherFormChange(u8 battler)
{
ret = 0;
}
else if (!(gBattleWeather & (WEATHER_RAIN_ANY | WEATHER_SUN_ANY | WEATHER_HAIL_ANY)) && !IS_BATTLER_OF_TYPE(battler, TYPE_NORMAL))
else if (holdEffect == HOLD_EFFECT_UTILITY_UMBRELLA || (!(gBattleWeather & (WEATHER_RAIN_ANY | WEATHER_SUN_ANY | WEATHER_HAIL_ANY)) && !IS_BATTLER_OF_TYPE(battler, TYPE_NORMAL)))
{
SET_BATTLER_TYPE(battler, TYPE_NORMAL);
ret = 1;
}
else if (gBattleWeather & WEATHER_SUN_ANY && !IS_BATTLER_OF_TYPE(battler, TYPE_FIRE))
else if (gBattleWeather & WEATHER_SUN_ANY && holdEffect != HOLD_EFFECT_UTILITY_UMBRELLA && !IS_BATTLER_OF_TYPE(battler, TYPE_FIRE))
{
SET_BATTLER_TYPE(battler, TYPE_FIRE);
ret = 2;
}
else if (gBattleWeather & WEATHER_RAIN_ANY && !IS_BATTLER_OF_TYPE(battler, TYPE_WATER))
else if (gBattleWeather & WEATHER_RAIN_ANY && holdEffect != HOLD_EFFECT_UTILITY_UMBRELLA && !IS_BATTLER_OF_TYPE(battler, TYPE_WATER))
{
SET_BATTLER_TYPE(battler, TYPE_WATER);
ret = 3;
@ -3649,9 +3650,9 @@ u8 TryWeatherFormChange(u8 battler)
{
if (gBattleMons[battler].ability != ABILITY_FLOWER_GIFT || gBattleMons[battler].hp == 0)
ret = 0;
else if (gBattleMonForms[battler] == 0 && weatherEffect && gBattleWeather & WEATHER_SUN_ANY)
else if (gBattleMonForms[battler] == 0 && weatherEffect && holdEffect != HOLD_EFFECT_UTILITY_UMBRELLA && gBattleWeather & WEATHER_SUN_ANY)
ret = 2;
else if (gBattleMonForms[battler] != 0 && (!weatherEffect || !(gBattleWeather & WEATHER_SUN_ANY)))
else if (gBattleMonForms[battler] != 0 && (!weatherEffect || holdEffect != HOLD_EFFECT_UTILITY_UMBRELLA || !(gBattleWeather & WEATHER_SUN_ANY)))
ret = 1;
}
@ -4258,7 +4259,7 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move
switch (gLastUsedAbility)
{
case ABILITY_HARVEST:
if (((WEATHER_HAS_EFFECT && gBattleWeather & WEATHER_SUN_ANY) || Random() % 2 == 0)
if ((IsBattlerWeatherAffected(battler, WEATHER_SUN_ANY) || Random() % 2 == 0)
&& gBattleMons[battler].item == ITEM_NONE
&& gBattleStruct->changedItems[battler] == ITEM_NONE
&& ItemId_GetPocket(gBattleStruct->usedHeldItems[battler]) == POCKET_BERRIES)
@ -4270,12 +4271,11 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move
}
break;
case ABILITY_DRY_SKIN:
if (gBattleWeather & WEATHER_SUN_ANY)
if (IsBattlerWeatherAffected(battler, WEATHER_SUN_ANY))
goto SOLAR_POWER_HP_DROP;
// Dry Skin works similarly to Rain Dish in Rain
case ABILITY_RAIN_DISH:
if (WEATHER_HAS_EFFECT
&& (gBattleWeather & WEATHER_RAIN_ANY)
if (IsBattlerWeatherAffected(battler, WEATHER_RAIN_ANY)
&& !BATTLER_MAX_HP(battler)
&& !(gStatuses3[battler] & STATUS3_HEAL_BLOCK))
{
@ -4288,8 +4288,7 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move
}
break;
case ABILITY_HYDRATION:
if (WEATHER_HAS_EFFECT
&& (gBattleWeather & WEATHER_RAIN_ANY)
if (IsBattlerWeatherAffected(battler, WEATHER_RAIN_ANY)
&& gBattleMons[battler].status1 & STATUS1_ANY)
{
goto ABILITY_HEAL_MON_STATUS;
@ -4384,7 +4383,7 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move
break;
SOLAR_POWER_HP_DROP:
case ABILITY_SOLAR_POWER:
if (WEATHER_HAS_EFFECT && gBattleWeather & WEATHER_SUN_ANY)
if (IsBattlerWeatherAffected(battler, WEATHER_SUN_ANY))
{
BattleScriptPushCursorAndCallback(BattleScript_SolarPowerActivates);
gBattleMoveDamage = gBattleMons[battler].maxHP / 8;
@ -7467,7 +7466,7 @@ static u32 CalcMoveBasePowerAfterModifiers(u16 move, u8 battlerAtk, u8 battlerDe
// todo
break;
case EFFECT_SOLARBEAM:
if (WEATHER_HAS_EFFECT && gBattleWeather & (WEATHER_HAIL_ANY | WEATHER_SANDSTORM_ANY | WEATHER_RAIN_ANY))
if (IsBattlerWeatherAffected(battlerAtk, (WEATHER_HAIL_ANY | WEATHER_SANDSTORM_ANY | WEATHER_RAIN_ANY)))
MulModifier(&modifier, UQ_4_12(0.5));
break;
case EFFECT_STOMPING_TANTRUM:
@ -7564,7 +7563,7 @@ static u32 CalcAttackStat(u16 move, u8 battlerAtk, u8 battlerDef, u8 moveType, b
MulModifier(&modifier, UQ_4_12(0.5));
break;
case ABILITY_SOLAR_POWER:
if (IS_MOVE_SPECIAL(move) && WEATHER_HAS_EFFECT && gBattleWeather & WEATHER_SUN_ANY)
if (IS_MOVE_SPECIAL(move) && IsBattlerWeatherAffected(battlerAtk, WEATHER_SUN_ANY))
MulModifier(&modifier, UQ_4_12(1.5));
break;
case ABILITY_DEFEATIST:
@ -7601,7 +7600,7 @@ static u32 CalcAttackStat(u16 move, u8 battlerAtk, u8 battlerDef, u8 moveType, b
}
break;
case ABILITY_FLOWER_GIFT:
if (gBattleMons[battlerAtk].species == SPECIES_CHERRIM && WEATHER_HAS_EFFECT && (gBattleWeather & WEATHER_SUN_ANY) && IS_MOVE_PHYSICAL(move))
if (gBattleMons[battlerAtk].species == SPECIES_CHERRIM && IsBattlerWeatherAffected(battlerAtk, WEATHER_SUN_ANY) && IS_MOVE_PHYSICAL(move))
MulModifier(&modifier, UQ_4_12(1.5));
break;
case ABILITY_HUSTLE:
@ -7641,7 +7640,7 @@ static u32 CalcAttackStat(u16 move, u8 battlerAtk, u8 battlerDef, u8 moveType, b
switch (GetBattlerAbility(BATTLE_PARTNER(battlerAtk)))
{
case ABILITY_FLOWER_GIFT:
if (gBattleMons[BATTLE_PARTNER(battlerAtk)].species == SPECIES_CHERRIM && IS_MOVE_PHYSICAL(move))
if (gBattleMons[BATTLE_PARTNER(battlerAtk)].species == SPECIES_CHERRIM && IsBattlerWeatherAffected(BATTLE_PARTNER(battlerAtk), WEATHER_SUN_ANY) && IS_MOVE_PHYSICAL(move))
MulModifier(&modifier, UQ_4_12(1.5));
break;
}
@ -7771,7 +7770,7 @@ static u32 CalcDefenseStat(u16 move, u8 battlerAtk, u8 battlerDef, u8 moveType,
}
break;
case ABILITY_FLOWER_GIFT:
if (gBattleMons[battlerDef].species == SPECIES_CHERRIM && WEATHER_HAS_EFFECT && gBattleWeather & WEATHER_SUN_ANY && !usesDefStat)
if (gBattleMons[battlerDef].species == SPECIES_CHERRIM && IsBattlerWeatherAffected(battlerDef, WEATHER_SUN_ANY) && !usesDefStat)
MulModifier(&modifier, UQ_4_12(1.5));
break;
case ABILITY_PUNK_ROCK:
@ -7786,7 +7785,7 @@ static u32 CalcDefenseStat(u16 move, u8 battlerAtk, u8 battlerDef, u8 moveType,
switch (GetBattlerAbility(BATTLE_PARTNER(battlerDef)))
{
case ABILITY_FLOWER_GIFT:
if (gBattleMons[BATTLE_PARTNER(battlerDef)].species == SPECIES_CHERRIM && !usesDefStat)
if (gBattleMons[BATTLE_PARTNER(battlerDef)].species == SPECIES_CHERRIM && IsBattlerWeatherAffected(BATTLE_PARTNER(battlerDef), WEATHER_SUN_ANY) && !usesDefStat)
MulModifier(&modifier, UQ_4_12(1.5));
break;
}
@ -7852,14 +7851,14 @@ static u32 CalcFinalDmg(u32 dmg, u16 move, u8 battlerAtk, u8 battlerDef, u8 move
dmg = ApplyModifier(UQ_4_12(0.5), dmg);
// check sunny/rain weather
if (WEATHER_HAS_EFFECT && gBattleWeather & WEATHER_RAIN_ANY)
if (IsBattlerWeatherAffected(battlerAtk, WEATHER_RAIN_ANY))
{
if (moveType == TYPE_FIRE)
dmg = ApplyModifier(UQ_4_12(0.5), dmg);
else if (moveType == TYPE_WATER)
dmg = ApplyModifier(UQ_4_12(1.5), dmg);
}
else if (WEATHER_HAS_EFFECT && gBattleWeather & WEATHER_SUN_ANY)
else if (IsBattlerWeatherAffected(battlerAtk, WEATHER_SUN_ANY))
{
if (moveType == TYPE_FIRE)
dmg = ApplyModifier(UQ_4_12(1.5), dmg);
@ -8657,3 +8656,19 @@ bool32 IsEntrainmentTargetOrSimpleBeamBannedAbility(u16 ability)
return FALSE;
}
bool32 IsBattlerWeatherAffected(u8 battlerId, u32 weatherFlags)
{
if (!WEATHER_HAS_EFFECT)
return FALSE;
if (gBattleWeather & weatherFlags)
{
// given weather is active -> check if its sun, rain against utility umbrella ( since only 1 weather can be active at once)
if (gBattleWeather & (WEATHER_SUN_ANY | WEATHER_RAIN_ANY) && GetBattlerHoldEffect(battlerId, TRUE) == HOLD_EFFECT_UTILITY_UMBRELLA)
return FALSE; // utility umbrella blocks sun, rain effects
return TRUE;
}
return FALSE;
}