mirror of
https://github.com/Ninjdai1/pokeemerald.git
synced 2024-11-16 11:37:40 +01:00
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:
parent
38655b9d1f
commit
b08c8f85fc
@ -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);
|
||||||
|
@ -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)
|
||||||
|
54
test/hold_effect_utility_umbrella.c
Normal file
54
test/hold_effect_utility_umbrella.c
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
50
test/move_effect_hydro_steam.c
Normal file
50
test/move_effect_hydro_steam.c
Normal 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
47
test/weather_rain.c
Normal 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
47
test/weather_sunlight.c
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user