Adds missing cases for Revenge and Assurance doubling power (#8453)

Co-authored-by: PhallenTree <168426989+PhallenTree@users.noreply.github.com>
This commit is contained in:
Alex 2025-12-06 19:04:48 +01:00 committed by GitHub
parent 520c31dc33
commit 445cc2ace9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 112 additions and 14 deletions

View File

@ -171,7 +171,8 @@ struct ProtectStruct
u16 helpingHand:3;
u16 assuranceDoubled:1;
u16 myceliumMight:1;
u16 padding:11;
u16 revengeDoubled:4;
u16 padding:7;
// End of 16-bit bitfield
u16 physicalDmg;
u16 specialDmg;

View File

@ -1026,7 +1026,7 @@ static void TryClearChargeVolatile(u32 moveType)
if (moveType == TYPE_ELECTRIC && gBattleMons[gBattlerAttacker].volatiles.chargeTimer == 1)
gBattleMons[gBattlerAttacker].volatiles.chargeTimer = 0;
for (u32 battler = 0; battler < gBattlersCount; battler++)
{
if (gBattleMons[battler].volatiles.chargeTimer == 2) // Has been set this turn by move
@ -2332,6 +2332,8 @@ static void PassiveDataHpUpdate(u32 battler, const u8 *nextInstr)
gBattleMons[battler].hp -= gBattleStruct->passiveHpUpdate[battler];
else
gBattleMons[battler].hp = 0;
// Since this is reset for the next turn, it should be fine to set it here.
gProtectStructs[battler].assuranceDoubled = TRUE;
}
// Send updated HP
@ -2431,7 +2433,6 @@ static void MoveDamageDataHpUpdate(u32 battler, u32 scriptBattler, const u8 *nex
gProtectStructs[battler].physicalBattlerId = gBattlerAttacker;
else
gProtectStructs[battler].physicalBattlerId = gBattlerTarget;
gProtectStructs[battler].assuranceDoubled = TRUE;
}
else // Physical move
{
@ -2441,8 +2442,10 @@ static void MoveDamageDataHpUpdate(u32 battler, u32 scriptBattler, const u8 *nex
gProtectStructs[battler].specialBattlerId = gBattlerAttacker;
else
gProtectStructs[battler].specialBattlerId = gBattlerTarget;
gProtectStructs[battler].assuranceDoubled = TRUE;
}
gProtectStructs[battler].assuranceDoubled = TRUE;
gProtectStructs[battler].revengeDoubled |= 1u << gBattlerAttacker;
}
// Send updated HP
BtlController_EmitSetMonData(battler, B_COMM_TO_CONTROLLER, REQUEST_HP_BATTLE, 0, sizeof(gBattleMons[battler].hp), &gBattleMons[battler].hp);

View File

@ -7036,10 +7036,7 @@ static inline u32 CalcMoveBasePower(struct DamageContext *ctx)
basePower = 100 * gDisableStructs[battlerAtk].stockpileCounter;
break;
case EFFECT_REVENGE:
if ((gProtectStructs[battlerAtk].physicalDmg
&& gProtectStructs[battlerAtk].physicalBattlerId == battlerDef)
|| (gProtectStructs[battlerAtk].specialDmg
&& gProtectStructs[battlerAtk].specialBattlerId == battlerDef))
if (gProtectStructs[battlerAtk].revengeDoubled & 1u << battlerDef)
basePower *= 2;
break;
case EFFECT_WEATHER_BALL:

View File

@ -1,6 +1,11 @@
#include "global.h"
#include "test/battle.h"
ASSUMPTIONS
{
ASSUME(gItemsInfo[ITEM_LIFE_ORB].holdEffect == HOLD_EFFECT_LIFE_ORB);
}
SINGLE_BATTLE_TEST("Life Orb activates when users attack is succesful")
{
GIVEN {

View File

@ -1,11 +1,10 @@
#include "global.h"
#include "test/battle.h"
TO_DO_BATTLE_TEST("Assurance doubles in power if the target has been damaged in the same turn - Recoil");
TO_DO_BATTLE_TEST("Assurance doubles in power if the target has been damaged in the same turn - Life Orb");
TO_DO_BATTLE_TEST("Assurance doubles in power if the target has been damaged in the same turn - Crash");
TO_DO_BATTLE_TEST("Assurance doubles in power if the target has been damaged in the same turn - Confusion");
TO_DO_BATTLE_TEST("Assurance doubles in power if the target has been damaged in the same turn - Rocky Helmet");
ASSUMPTIONS
{
ASSUME(GetMoveEffect(MOVE_ASSURANCE) == EFFECT_ASSURANCE);
}
DOUBLE_BATTLE_TEST("Assurance doubles in power if False Swipe connected but didn't do any damage")
{
@ -33,3 +32,31 @@ DOUBLE_BATTLE_TEST("Assurance doubles in power if False Swipe connected but didn
EXPECT_MUL_EQ(hits[0], Q_4_12(2.0), hits[1]);
}
}
SINGLE_BATTLE_TEST("Assurance doubles in power if the target has been damaged in the same turn - Life Orb")
{
s16 hits[2];
GIVEN {
ASSUME(gItemsInfo[ITEM_LIFE_ORB].holdEffect == HOLD_EFFECT_LIFE_ORB);
PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_LIFE_ORB); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, MOVE_CELEBRATE); MOVE(opponent, MOVE_ASSURANCE); }
TURN { MOVE(player, MOVE_POUND); MOVE(opponent, MOVE_ASSURANCE); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_ASSURANCE, opponent);
HP_BAR(player, captureDamage: &hits[0]);
ANIMATION(ANIM_TYPE_MOVE, MOVE_POUND, player);
MESSAGE("Wobbuffet was hurt by the Life Orb!");
HP_BAR(player, captureDamage: &hits[1]);
} THEN {
EXPECT_MUL_EQ(hits[0], Q_4_12(2.0), hits[1]);
}
}
TO_DO_BATTLE_TEST("Assurance doubles in power if the target has been damaged in the same turn - Recoil");
TO_DO_BATTLE_TEST("Assurance doubles in power if the target has been damaged in the same turn - Crash");
TO_DO_BATTLE_TEST("Assurance doubles in power if the target has been damaged in the same turn - Confusion");
TO_DO_BATTLE_TEST("Assurance doubles in power if the target has been damaged in the same turn - Rocky Helmet");

View File

@ -1,4 +1,69 @@
#include "global.h"
#include "test/battle.h"
TO_DO_BATTLE_TEST("TODO: Write Revenge (Move Effect) test titles")
ASSUMPTIONS
{
ASSUME(GetMoveEffect(MOVE_REVENGE) == EFFECT_REVENGE);
}
SINGLE_BATTLE_TEST("Revenge doubles in power if False Swipe connected but didn't do any damage")
{
s16 hits[3];
GIVEN {
PLAYER(SPECIES_WOBBUFFET) { HP(1); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(opponent, MOVE_CELEBRATE); MOVE(player, MOVE_REVENGE); }
TURN { MOVE(opponent, MOVE_FALSE_SWIPE); MOVE(player, MOVE_REVENGE); }
TURN { MOVE(opponent, MOVE_CELEBRATE); MOVE(player, MOVE_REVENGE); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_REVENGE, player);
HP_BAR(opponent, captureDamage: &hits[0]);
ANIMATION(ANIM_TYPE_MOVE, MOVE_FALSE_SWIPE, opponent);
ANIMATION(ANIM_TYPE_MOVE, MOVE_REVENGE, player);
HP_BAR(opponent, captureDamage: &hits[1]);
ANIMATION(ANIM_TYPE_MOVE, MOVE_REVENGE, player);
HP_BAR(opponent, captureDamage: &hits[2]);
} THEN {
EXPECT_MUL_EQ(hits[0], Q_4_12(2.0), hits[1]);
EXPECT_EQ(hits[0], hits[2]);
}
}
DOUBLE_BATTLE_TEST("Revenge doesn't double in power if user was not hit by target in doubles")
{
s16 hits[3];
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN {
MOVE(opponentLeft, MOVE_REVENGE, target: playerRight); }
TURN {
MOVE(playerRight, MOVE_POUND, target: opponentRight);
MOVE(opponentLeft, MOVE_REVENGE, target: playerRight);
}
TURN {
MOVE(playerRight, MOVE_POUND, target: opponentLeft);
MOVE(opponentLeft, MOVE_REVENGE, target: playerRight);
}
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_REVENGE, opponentLeft);
HP_BAR(playerRight, captureDamage: &hits[0]);
ANIMATION(ANIM_TYPE_MOVE, MOVE_POUND, playerRight);
ANIMATION(ANIM_TYPE_MOVE, MOVE_REVENGE, opponentLeft);
HP_BAR(playerRight, captureDamage: &hits[1]);
ANIMATION(ANIM_TYPE_MOVE, MOVE_POUND, playerRight);
ANIMATION(ANIM_TYPE_MOVE, MOVE_REVENGE, opponentLeft);
HP_BAR(playerRight, captureDamage: &hits[2]);
} THEN {
EXPECT_EQ(hits[0], hits[1]);
EXPECT_MUL_EQ(hits[1], Q_4_12(2.0), hits[2]);
}
}