Fixed Utility Umbrella damage calculations (#2835)

* Fixed Utility Umbrella holders not receiving regular damage when being hurt by what would've been weakened rain/sun attacks

* Fixed reading move incorrectly

* Tests: Sun, Rain, Utility Umbrella and Hydro Steam

* [STASH] Skeli changes, needs to remake tests

* Fixed tests

* Removed redundant tests

* Removed unused variable

* Removed Primal Todo tests
This commit is contained in:
Eduardo Quezada D'Ottone 2023-07-18 03:22:05 -04:00 committed by GitHub
parent 38655b9d1f
commit b08c8f85fc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 234 additions and 18 deletions

View File

@ -210,6 +210,7 @@ void BufferStatChange(u8 battlerId, u8 statId, u8 stringId);
bool32 BlocksPrankster(u16 move, u8 battlerPrankster, u8 battlerDef, bool32 checkTarget); bool32 BlocksPrankster(u16 move, u8 battlerPrankster, u8 battlerDef, bool32 checkTarget);
u16 GetUsedHeldItem(u8 battler); u16 GetUsedHeldItem(u8 battler);
bool32 IsBattlerWeatherAffected(u8 battlerId, u32 weatherFlags); bool32 IsBattlerWeatherAffected(u8 battlerId, u32 weatherFlags);
u32 ApplyWeatherDamageMultiplier(u8 battlerAtk, u16 move, u8 moveType, u32 dmg, u16 holdEffectAtk, u16 holdEffectDef);
u32 GetBattlerMoveTargetType(u8 battlerId, u16 move); u32 GetBattlerMoveTargetType(u8 battlerId, u16 move);
bool32 CanTargetBattler(u8 battlerAtk, u8 battlerDef, u16 move); bool32 CanTargetBattler(u8 battlerAtk, u8 battlerDef, u16 move);
bool8 IsMoveAffectedByParentalBond(u16 move, u8 battlerId); bool8 IsMoveAffectedByParentalBond(u16 move, u8 battlerId);

View File

@ -9508,6 +9508,8 @@ static u32 CalcFinalDmg(u32 dmg, u16 move, u8 battlerAtk, u8 battlerDef, u8 move
u32 defSide = GET_BATTLER_SIDE(battlerDef); u32 defSide = GET_BATTLER_SIDE(battlerDef);
u16 finalModifier = UQ_4_12(1.0); u16 finalModifier = UQ_4_12(1.0);
u16 itemDef = gBattleMons[battlerDef].item; u16 itemDef = gBattleMons[battlerDef].item;
u16 holdEffectAtk = GetBattlerHoldEffect(battlerAtk, TRUE);
u16 holdEffectDef = GetBattlerHoldEffect(battlerDef, TRUE);
// check multiple targets in double battle // check multiple targets in double battle
if (GetMoveTargetCount(move, battlerAtk, battlerDef) >= 2) if (GetMoveTargetCount(move, battlerAtk, battlerDef) >= 2)
@ -9537,28 +9539,15 @@ static u32 CalcFinalDmg(u32 dmg, u16 move, u8 battlerAtk, u8 battlerDef, u8 move
dmg = ApplyModifier(UQ_4_12(0.5), dmg); dmg = ApplyModifier(UQ_4_12(0.5), dmg);
// check frostbite // check frostbite
if (gBattleMons[battlerAtk].status1 & STATUS1_FROSTBITE && !IS_MOVE_PHYSICAL(move) if (gBattleMons[battlerAtk].status1 & STATUS1_FROSTBITE && IS_MOVE_SPECIAL(move)
#if B_BURN_FACADE_DMG >= GEN_6 #if B_BURN_FACADE_DMG >= GEN_6
&& gBattleMoves[move].effect != EFFECT_FACADE && gBattleMoves[move].effect != EFFECT_FACADE
#endif #endif
&& abilityAtk != ABILITY_GUTS) && abilityAtk != ABILITY_GUTS)
dmg = ApplyModifier(UQ_4_12(0.5), dmg); dmg = ApplyModifier(UQ_4_12(0.5), dmg);
// check sunny/rain weather // check weather
if (IsBattlerWeatherAffected(battlerAtk, B_WEATHER_RAIN)) dmg = ApplyWeatherDamageMultiplier(battlerAtk, move, moveType, dmg, holdEffectAtk, holdEffectDef);
{
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 (IsBattlerWeatherAffected(battlerAtk, B_WEATHER_SUN))
{
if (moveType == TYPE_FIRE || gBattleMoves[move].effect == EFFECT_HYDRO_STEAM)
dmg = ApplyModifier(UQ_4_12(1.5), dmg);
else if (moveType == TYPE_WATER)
dmg = ApplyModifier(UQ_4_12(0.5), dmg);
}
// check stab // check stab
if (IS_BATTLER_OF_TYPE(battlerAtk, moveType) && move != MOVE_STRUGGLE && move != MOVE_NONE) if (IS_BATTLER_OF_TYPE(battlerAtk, moveType) && move != MOVE_STRUGGLE && move != MOVE_NONE)
@ -9643,7 +9632,7 @@ static u32 CalcFinalDmg(u32 dmg, u16 move, u8 battlerAtk, u8 battlerDef, u8 move
} }
// attacker's hold effect // attacker's hold effect
switch (GetBattlerHoldEffect(battlerAtk, TRUE)) switch (holdEffectAtk)
{ {
case HOLD_EFFECT_METRONOME: case HOLD_EFFECT_METRONOME:
percentBoost = min((gBattleStruct->sameMoveTurns[battlerAtk] * GetBattlerHoldEffectParam(battlerAtk)), 100); percentBoost = min((gBattleStruct->sameMoveTurns[battlerAtk] * GetBattlerHoldEffectParam(battlerAtk)), 100);
@ -9659,7 +9648,7 @@ static u32 CalcFinalDmg(u32 dmg, u16 move, u8 battlerAtk, u8 battlerDef, u8 move
} }
// target's hold effect // target's hold effect
switch (GetBattlerHoldEffect(battlerDef, TRUE)) switch (holdEffectDef)
{ {
// berries reducing dmg // berries reducing dmg
case HOLD_EFFECT_RESIST_BERRY: case HOLD_EFFECT_RESIST_BERRY:
@ -10858,6 +10847,34 @@ bool32 IsBattlerWeatherAffected(u8 battlerId, u32 weatherFlags)
return FALSE; return FALSE;
} }
// Utility Umbrella holders take normal damage from what would be rain- and sun-weakened attacks.
u32 ApplyWeatherDamageMultiplier(u8 battlerAtk, u16 move, u8 moveType, u32 dmg, u16 holdEffectAtk, u16 holdEffectDef)
{
if (WEATHER_HAS_EFFECT)
{
if (gBattleMoves[move].effect == EFFECT_HYDRO_STEAM && (gBattleWeather & B_WEATHER_SUN) && holdEffectAtk != HOLD_EFFECT_UTILITY_UMBRELLA)
dmg = ApplyModifier(UQ_4_12(1.5), dmg);
else if (holdEffectDef != HOLD_EFFECT_UTILITY_UMBRELLA)
{
if (gBattleWeather & B_WEATHER_RAIN)
{
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 (gBattleWeather & B_WEATHER_SUN)
{
if (moveType == TYPE_FIRE)
dmg = ApplyModifier(UQ_4_12(1.5), dmg);
else if (moveType == TYPE_WATER)
dmg = ApplyModifier(UQ_4_12(0.5), dmg);
}
}
}
return dmg;
}
// Gets move target before redirection effects etc. are applied // Gets move target before redirection effects etc. are applied
// Possible return values are defined in battle.h following MOVE_TARGET_SELECTED // Possible return values are defined in battle.h following MOVE_TARGET_SELECTED
u32 GetBattlerMoveTargetType(u8 battlerId, u16 move) u32 GetBattlerMoveTargetType(u8 battlerId, u16 move)

View File

@ -0,0 +1,54 @@
#include "global.h"
#include "test_battle.h"
// Please add Utility Umbrella interactions with move, item and ability effects on their respective files.
ASSUMPTIONS
{
ASSUME(gItems[ITEM_UTILITY_UMBRELLA].holdEffect == HOLD_EFFECT_UTILITY_UMBRELLA);
ASSUME(gBattleMoves[MOVE_EMBER].type == TYPE_FIRE);
ASSUME(gBattleMoves[MOVE_WATER_GUN].type == TYPE_WATER);
}
SINGLE_BATTLE_TEST("Utility Umbrella blocks Sun damage modifiers", s16 damage)
{
u16 setupMove, attackingMove, heldItem;
PARAMETRIZE { setupMove = MOVE_SUNNY_DAY; attackingMove = MOVE_EMBER; heldItem = ITEM_UTILITY_UMBRELLA; }
PARAMETRIZE { setupMove = MOVE_SUNNY_DAY; attackingMove = MOVE_EMBER; heldItem = ITEM_NONE; }
PARAMETRIZE { setupMove = MOVE_SUNNY_DAY; attackingMove = MOVE_WATER_GUN; heldItem = ITEM_UTILITY_UMBRELLA; }
PARAMETRIZE { setupMove = MOVE_SUNNY_DAY; attackingMove = MOVE_WATER_GUN; heldItem = ITEM_NONE; }
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET) { Item(heldItem); };
} WHEN {
TURN { MOVE(opponent, setupMove); }
TURN { MOVE(player, attackingMove); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, attackingMove, player);
HP_BAR(opponent, captureDamage: &results[i].damage);
} FINALLY {
EXPECT_MUL_EQ(results[0].damage, Q_4_12(1.5), results[1].damage);
EXPECT_MUL_EQ(results[2].damage, Q_4_12(0.5), results[3].damage);
}
}
SINGLE_BATTLE_TEST("Utility Umbrella blocks Rain damage modifiers", s16 damage)
{
u16 setupMove, attackingMove, heldItem;
PARAMETRIZE { setupMove = MOVE_RAIN_DANCE; attackingMove = MOVE_EMBER; heldItem = ITEM_UTILITY_UMBRELLA; }
PARAMETRIZE { setupMove = MOVE_RAIN_DANCE; attackingMove = MOVE_EMBER; heldItem = ITEM_NONE; }
PARAMETRIZE { setupMove = MOVE_RAIN_DANCE; attackingMove = MOVE_WATER_GUN; heldItem = ITEM_UTILITY_UMBRELLA; }
PARAMETRIZE { setupMove = MOVE_RAIN_DANCE; attackingMove = MOVE_WATER_GUN; heldItem = ITEM_NONE; }
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET) { Item(heldItem); };
} WHEN {
TURN { MOVE(opponent, setupMove); }
TURN { MOVE(player, attackingMove); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, attackingMove, player);
HP_BAR(opponent, captureDamage: &results[i].damage);
} FINALLY {
EXPECT_MUL_EQ(results[0].damage, Q_4_12(0.5), results[1].damage);
EXPECT_MUL_EQ(results[2].damage, Q_4_12(1.5), results[3].damage);
}
}

View File

@ -0,0 +1,50 @@
#include "global.h"
#include "test_battle.h"
ASSUMPTIONS
{
ASSUME(gBattleMoves[MOVE_HYDRO_STEAM].effect == EFFECT_HYDRO_STEAM);
}
SINGLE_BATTLE_TEST("Hydro Steam deals 1.5x damage under both Sunlight and Rain", s16 damage)
{
u16 setupMove;
PARAMETRIZE { setupMove = MOVE_CELEBRATE; }
PARAMETRIZE { setupMove = MOVE_SUNNY_DAY; }
PARAMETRIZE { setupMove = MOVE_RAIN_DANCE; }
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, setupMove); }
TURN { MOVE(player, MOVE_HYDRO_STEAM); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_HYDRO_STEAM, player);
HP_BAR(opponent, captureDamage: &results[i].damage);
} FINALLY {
EXPECT_MUL_EQ(results[0].damage, Q_4_12(1.5), results[2].damage);
EXPECT_MUL_EQ(results[0].damage, Q_4_12(1.5), results[1].damage);
}
}
SINGLE_BATTLE_TEST("Hydro Steam is affected by Utility Umbrella", s16 damage)
{
u32 itemPlayer;
u32 itemOpponent;
PARAMETRIZE { itemPlayer = ITEM_UTILITY_UMBRELLA; itemOpponent = ITEM_NONE; }
PARAMETRIZE { itemPlayer = ITEM_NONE; itemOpponent = ITEM_UTILITY_UMBRELLA; }
PARAMETRIZE { itemPlayer = ITEM_UTILITY_UMBRELLA; itemOpponent = ITEM_UTILITY_UMBRELLA; }
GIVEN {
PLAYER(SPECIES_WOBBUFFET) { Item(itemPlayer); };
OPPONENT(SPECIES_WOBBUFFET) {Item(itemOpponent); };
} WHEN {
TURN { MOVE(player, MOVE_SUNNY_DAY); }
TURN { MOVE(player, MOVE_HYDRO_STEAM); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_HYDRO_STEAM, player);
HP_BAR(opponent, captureDamage: &results[i].damage);
} FINALLY {
EXPECT_MUL_EQ(results[2].damage, Q_4_12(1.5), results[1].damage);
EXPECT_MUL_EQ(results[2].damage, Q_4_12(0.5), results[0].damage);
}
}

47
test/weather_rain.c Normal file
View File

@ -0,0 +1,47 @@
#include "global.h"
#include "test_battle.h"
// Please add Rain interactions with move, item and ability effects on their respective files.
ASSUMPTIONS
{
ASSUME(gBattleMoves[MOVE_EMBER].type == TYPE_FIRE);
ASSUME(gBattleMoves[MOVE_WATER_GUN].type == TYPE_WATER);
}
SINGLE_BATTLE_TEST("Rain multiplies the power of Fire-type moves by 0.5x", s16 damage)
{
u32 setupMove;
PARAMETRIZE { setupMove = MOVE_CELEBRATE; }
PARAMETRIZE { setupMove = MOVE_RAIN_DANCE; }
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, setupMove); }
TURN { MOVE(player, MOVE_EMBER); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_EMBER, player);
HP_BAR(opponent, captureDamage: &results[i].damage);
} FINALLY {
EXPECT_MUL_EQ(results[0].damage, Q_4_12(0.5), results[1].damage);
}
}
SINGLE_BATTLE_TEST("Rain multiplies the power of Water-type moves by 1.5x", s16 damage)
{
u32 setupMove;
PARAMETRIZE { setupMove = MOVE_CELEBRATE; }
PARAMETRIZE { setupMove = MOVE_RAIN_DANCE; }
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, setupMove); }
TURN { MOVE(player, MOVE_WATER_GUN); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_WATER_GUN, player);
HP_BAR(opponent, captureDamage: &results[i].damage);
} FINALLY {
EXPECT_MUL_EQ(results[0].damage, Q_4_12(1.5), results[1].damage);
}
}

47
test/weather_sunlight.c Normal file
View File

@ -0,0 +1,47 @@
#include "global.h"
#include "test_battle.h"
// Please add Sunlight interactions with move, item and ability effects on their respective files.
ASSUMPTIONS
{
ASSUME(gBattleMoves[MOVE_EMBER].type == TYPE_FIRE);
ASSUME(gBattleMoves[MOVE_WATER_GUN].type == TYPE_WATER);
}
SINGLE_BATTLE_TEST("Sunlight multiplies the power of Fire-type moves by 1.5x", s16 damage)
{
u32 setupMove;
PARAMETRIZE { setupMove = MOVE_CELEBRATE; }
PARAMETRIZE { setupMove = MOVE_SUNNY_DAY; }
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, setupMove); }
TURN { MOVE(player, MOVE_EMBER); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_EMBER, player);
HP_BAR(opponent, captureDamage: &results[i].damage);
} FINALLY {
EXPECT_MUL_EQ(results[0].damage, Q_4_12(1.5), results[1].damage);
}
}
SINGLE_BATTLE_TEST("Sunlight multiplies the power of Water-type moves by 0.5x", s16 damage)
{
u32 setupMove;
PARAMETRIZE { setupMove = MOVE_CELEBRATE; }
PARAMETRIZE { setupMove = MOVE_SUNNY_DAY; }
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, setupMove); }
TURN { MOVE(player, MOVE_WATER_GUN); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_WATER_GUN, player);
HP_BAR(opponent, captureDamage: &results[i].damage);
} FINALLY {
EXPECT_MUL_EQ(results[0].damage, Q_4_12(0.5), results[1].damage);
}
}