Add Berserk Gene Item (#2893)

Co-authored-by: Eduardo Quezada D'Ottone <eduardo602002@gmail.com>
This commit is contained in:
Salem 2023-04-25 21:03:57 +02:00 committed by GitHub
parent 9562c7a37a
commit 78c4d07b23
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 340 additions and 9 deletions

View File

@ -10395,3 +10395,30 @@ BattleScript_CouldntFullyProtect::
printstring STRINGID_COULDNTFULLYPROTECT
waitmessage B_WAIT_TIME_LONG
return
BattleScript_BerserkGeneRet::
BattleScript_BerserkGeneRet_Anim:
statbuffchange STAT_CHANGE_ALLOW_PTR, BattleScript_BerserkGeneRet_TryConfuse
setgraphicalstatchangevalues
playanimation BS_SCRIPTING, B_ANIM_HELD_ITEM_EFFECT, sB_ANIM_ARG1
setbyte cMULTISTRING_CHOOSER, B_MSG_STAT_ROSE_ITEM
call BattleScript_StatUp
BattleScript_BerserkGeneRet_TryConfuse:
jumpifability BS_SCRIPTING, ABILITY_OWN_TEMPO, BattleScript_BerserkGeneRet_OwnTempoPrevents
jumpifsafeguard BattleScript_BerserkGeneRet_SafeguardProtected
setmoveeffect MOVE_EFFECT_CONFUSION
seteffectprimary
goto BattleScript_BerserkGeneRet_End
BattleScript_BerserkGeneRet_SafeguardProtected::
pause B_WAIT_TIME_SHORT
printstring STRINGID_PKMNUSEDSAFEGUARD
waitmessage B_WAIT_TIME_LONG
goto BattleScript_BerserkGeneRet_End
BattleScript_BerserkGeneRet_OwnTempoPrevents:
pause B_WAIT_TIME_SHORT
call BattleScript_AbilityPopUp
printstring STRINGID_PKMNPREVENTSCONFUSIONWITH
waitmessage B_WAIT_TIME_LONG
BattleScript_BerserkGeneRet_End:
removeitem BS_SCRIPTING
end3

View File

@ -0,0 +1,19 @@
JASC-PAL
0100
16
212 146 75
49 49 49
131 123 131
98 90 98
74 65 74
164 90 222
230 180 255
255 230 238
255 230 106
255 189 74
255 171 32
238 148 0
255 246 189
123 82 32
0 0 0
0 0 0

Binary file not shown.

After

Width:  |  Height:  |  Size: 356 B

View File

@ -461,6 +461,7 @@ extern const u8 BattleScript_CouldntFullyProtect[];
extern const u8 BattleScript_MoveEffectStockpileWoreOff[];
extern const u8 BattleScript_StealthRockActivates[];
extern const u8 BattleScript_SpikesActivates[];
extern const u8 BattleScript_BerserkGeneRet[];
// zmoves
extern const u8 BattleScript_ZMoveActivateDamaging[];

View File

@ -234,5 +234,6 @@ u32 GetBattlerFriendshipScore(u8 battlerId);
u32 CountBattlerStatIncreases(u8 battlerId, bool32 countEvasionAcc);
bool32 IsMyceliumMightOnField(void);
bool8 ChangeTypeBasedOnTerrain(u8 battlerId);
void RemoveConfusionStatus(u8 battlerId);
#endif // GUARD_BATTLE_UTIL_H

View File

@ -185,6 +185,7 @@
#define STATUS4_PLASMA_FISTS (1 << 1)
#define STATUS4_MUD_SPORT (1 << 2) // Only used if B_SPORT_TURNS < GEN_6
#define STATUS4_WATER_SPORT (1 << 3) // Only used if B_SPORT_TURNS < GEN_6
#define STATUS4_INFINITE_CONFUSION (1 << 4) // Used for Berserk Gene
#define HITMARKER_WAKE_UP_CLEAR (1 << 4) // Cleared when waking up. Never set or checked.
#define HITMARKER_SKIP_DMG_TRACK (1 << 5)

View File

@ -161,6 +161,9 @@
#define HOLD_EFFECT_LOADED_DICE 180
#define HOLD_EFFECT_BOOSTER_ENERGY 181 // Not implemented.
// Gen2 hold effect
#define HOLD_EFFECT_BERSERK_GENE 182
#define HOLD_EFFECT_CHOICE(holdEffect)((holdEffect == HOLD_EFFECT_CHOICE_BAND || holdEffect == HOLD_EFFECT_CHOICE_SCARF || holdEffect == HOLD_EFFECT_CHOICE_SPECS))
// Terrain seed params

View File

@ -972,8 +972,9 @@
#define ITEM_BLACK_AUGURITE 795
#define ITEM_LINKING_CORD 796
#define ITEM_PEAT_BLOCK 797
#define ITEM_BERSERK_GENE 798
#define ITEMS_COUNT 798
#define ITEMS_COUNT 799
#define ITEM_FIELD_ARROW ITEMS_COUNT
// A special item id associated with "Cancel"/"Exit" etc. in a list of items or decorations

View File

@ -8878,6 +8878,8 @@ extern const u32 gItemIcon_GriseousCore[];
extern const u32 gItemIconPalette_GriseousCore[];
extern const u32 gItemIcon_LustrousGlobe[];
extern const u32 gItemIconPalette_LustrousGlobe[];
extern const u32 gItemIcon_BerserkGene[];
extern const u32 gItemIconPalette_BerserkGene[];
extern const u32 gItemIcon_ReturnToFieldArrow[];
extern const u32 gItemIconPalette_ReturnToFieldArrow[];

View File

@ -3227,7 +3227,7 @@ void SwitchInClearSetData(void)
gStatuses3[gActiveBattler] &= (STATUS3_LEECHSEED_BATTLER | STATUS3_LEECHSEED | STATUS3_ALWAYS_HITS | STATUS3_PERISH_SONG | STATUS3_ROOTED
| STATUS3_GASTRO_ACID | STATUS3_EMBARGO | STATUS3_TELEKINESIS | STATUS3_MAGNET_RISE | STATUS3_HEAL_BLOCK
| STATUS3_AQUA_RING | STATUS3_POWER_TRICK);
gStatuses4[gActiveBattler] &= (STATUS4_MUD_SPORT | STATUS4_WATER_SPORT);
gStatuses4[gActiveBattler] &= (STATUS4_MUD_SPORT | STATUS4_WATER_SPORT | STATUS4_INFINITE_CONFUSION);
for (i = 0; i < gBattlersCount; i++)
{
if (GetBattlerSide(gActiveBattler) != GetBattlerSide(i)

View File

@ -16583,6 +16583,8 @@ void BS_ItemCureStatus(void) {
if (GetItemStatus1Mask(gLastUsedItem) & STATUS1_SLEEP)
gBattleMons[gBattlerAttacker].status2 &= ~STATUS2_NIGHTMARE;
if (GetItemStatus2Mask(gLastUsedItem) & STATUS2_CONFUSION)
gStatuses4[gBattlerAttacker] &= ~STATUS4_INFINITE_CONFUSION;
PREPARE_SPECIES_BUFFER(gBattleTextBuff1, GetMonData(&party[gBattleStruct->itemPartyIndex[gBattlerAttacker]], MON_DATA_SPECIES));
gBattlescriptCurrInstr = cmd->nextInstr;

View File

@ -64,6 +64,7 @@ static void SetRandomMultiHitCounter();
static u32 GetBattlerItemHoldEffectParam(u8 battlerId, u16 item);
static u16 GetInverseTypeMultiplier(u16 multiplier);
static u16 GetSupremeOverlordModifier(u8 battlerId);
static bool8 CanBeInfinitelyConfused(u8 battlerId);
extern const u8 *const gBattleScriptsForMoveEffects[];
extern const u8 *const gBattlescriptsForRunningByItem[];
@ -3526,7 +3527,8 @@ u8 AtkCanceller_UnableToUseMove(void)
case CANCELLER_CONFUSED: // confusion
if (gBattleMons[gBattlerAttacker].status2 & STATUS2_CONFUSION)
{
gBattleMons[gBattlerAttacker].status2 -= STATUS2_CONFUSION_TURN(1);
if (!(gStatuses4[gBattlerAttacker] & STATUS4_INFINITE_CONFUSION))
gBattleMons[gBattlerAttacker].status2 -= STATUS2_CONFUSION_TURN(1);
if (gBattleMons[gBattlerAttacker].status2 & STATUS2_CONFUSION)
{
// confusion dmg
@ -5968,7 +5970,7 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move
gBattlescriptCurrInstr = BattleScript_AbilityCuredStatus;
break;
case 2: // get rid of confusion
gBattleMons[battler].status2 &= ~STATUS2_CONFUSION;
RemoveConfusionStatus(battler);
BattleScriptPushCursor();
gBattlescriptCurrInstr = BattleScript_AbilityCuredStatus;
break;
@ -6906,7 +6908,7 @@ static u8 ItemEffectMoveEnd(u32 battlerId, u16 holdEffect)
case HOLD_EFFECT_CURE_CONFUSION:
if (gBattleMons[battlerId].status2 & STATUS2_CONFUSION && !UnnerveOn(battlerId, gLastUsedItem))
{
gBattleMons[battlerId].status2 &= ~STATUS2_CONFUSION;
RemoveConfusionStatus(battlerId);
BattleScriptPushCursor();
gBattlescriptCurrInstr = BattleScript_BerryCureConfusionRet;
effect = ITEM_EFFECT_OTHER;
@ -6947,7 +6949,7 @@ static u8 ItemEffectMoveEnd(u32 battlerId, u16 holdEffect)
StringCopy(gBattleTextBuff1, gStatusConditionString_ConfusionJpn);
gBattleMons[battlerId].status1 = 0;
gBattleMons[battlerId].status2 &= ~STATUS2_CONFUSION;
RemoveConfusionStatus(battlerId);
BattleScriptPushCursor();
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_CURED_PROBLEM;
gBattlescriptCurrInstr = BattleScript_BerryCureChosenStatusRet;
@ -6985,6 +6987,21 @@ static u8 ItemEffectMoveEnd(u32 battlerId, u16 holdEffect)
effect = ITEM_EFFECT_OTHER;
}
break;
case HOLD_EFFECT_BERSERK_GENE:
BufferStatChange(battlerId, STAT_ATK, STRINGID_STATROSE);
gEffectBattler = battlerId;
if (CanBeInfinitelyConfused(gEffectBattler))
{
gStatuses4[gEffectBattler] |= STATUS4_INFINITE_CONFUSION;
}
SET_STATCHANGER(STAT_ATK, 2, FALSE);
gBattleScripting.animArg1 = 14 + STAT_ATK;
gBattleScripting.animArg2 = 0;
BattleScriptPushCursorAndCallback(BattleScript_BerserkGeneRet);
effect = ITEM_STATS_CHANGE;
break;
}
return effect;
@ -7163,7 +7180,7 @@ u8 ItemBattleEffects(u8 caseID, u8 battlerId, bool8 moveTurn)
else
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_NORMALIZED_STATUS;
gBattleMons[battlerId].status1 = 0;
gBattleMons[battlerId].status2 &= ~STATUS2_CONFUSION;
RemoveConfusionStatus(battlerId);
BattleScriptExecute(BattleScript_BerryCureChosenStatusEnd2);
effect = ITEM_STATUS_CHANGE;
}
@ -7224,6 +7241,21 @@ u8 ItemBattleEffects(u8 caseID, u8 battlerId, bool8 moveTurn)
}
}
break;
case HOLD_EFFECT_BERSERK_GENE:
BufferStatChange(battlerId, STAT_ATK, STRINGID_STATROSE);
gEffectBattler = battlerId;
if (CanBeInfinitelyConfused(gEffectBattler))
{
gStatuses4[gEffectBattler] |= STATUS4_INFINITE_CONFUSION;
}
SET_STATCHANGER(STAT_ATK, 2, FALSE);
gBattleScripting.animArg1 = 14 + STAT_ATK;
gBattleScripting.animArg2 = 0;
BattleScriptPushCursorAndCallback(BattleScript_BerserkGeneRet);
effect = ITEM_STATS_CHANGE;
break;
}
if (effect != 0)
{
@ -7444,7 +7476,7 @@ u8 ItemBattleEffects(u8 caseID, u8 battlerId, bool8 moveTurn)
case HOLD_EFFECT_CURE_CONFUSION:
if (gBattleMons[battlerId].status2 & STATUS2_CONFUSION && !UnnerveOn(battlerId, gLastUsedItem))
{
gBattleMons[battlerId].status2 &= ~STATUS2_CONFUSION;
RemoveConfusionStatus(battlerId);
BattleScriptExecute(BattleScript_BerryCureConfusionEnd2);
effect = ITEM_EFFECT_OTHER;
}
@ -7489,7 +7521,7 @@ u8 ItemBattleEffects(u8 caseID, u8 battlerId, bool8 moveTurn)
else
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_NORMALIZED_STATUS;
gBattleMons[battlerId].status1 = 0;
gBattleMons[battlerId].status2 &= ~STATUS2_CONFUSION;
RemoveConfusionStatus(battlerId);
BattleScriptExecute(BattleScript_BerryCureChosenStatusEnd2);
effect = ITEM_STATUS_CHANGE;
}
@ -7507,6 +7539,21 @@ u8 ItemBattleEffects(u8 caseID, u8 battlerId, bool8 moveTurn)
if (!moveTurn)
effect = TrySetMicleBerry(battlerId, gLastUsedItem, TRUE);
break;
case HOLD_EFFECT_BERSERK_GENE:
BufferStatChange(battlerId, STAT_ATK, STRINGID_STATROSE);
gEffectBattler = battlerId;
if (CanBeInfinitelyConfused(gEffectBattler))
{
gStatuses4[gEffectBattler] |= STATUS4_INFINITE_CONFUSION;
}
SET_STATCHANGER(STAT_ATK, 2, FALSE);
gBattleScripting.animArg1 = 14 + STAT_ATK;
gBattleScripting.animArg2 = 0;
BattleScriptPushCursorAndCallback(BattleScript_BerserkGeneRet);
effect = ITEM_STATS_CHANGE;
break;
}
if (effect != 0)
@ -10870,3 +10917,21 @@ static void SetRandomMultiHitCounter()
gMultiHitCounter = 5 - (Random() & 1);
}
}
void RemoveConfusionStatus(u8 battlerId)
{
gBattleMons[battlerId].status2 &= ~STATUS2_CONFUSION;
gStatuses4[battlerId] &= ~STATUS4_INFINITE_CONFUSION;
}
static bool8 CanBeInfinitelyConfused(u8 battlerId)
{
if (gBattleMons[battlerId].ability == ABILITY_OWN_TEMPO
|| IsBattlerTerrainAffected(battlerId, STATUS_FIELD_MISTY_TERRAIN)
|| gSideStatuses[GetBattlerSide(battlerId)] & SIDE_STATUS_SAFEGUARD)
{
return FALSE;
}
return TRUE;
}

View File

@ -1998,3 +1998,6 @@ const u32 gItemIconPalette_GriseousCore[] = INCBIN_U32("graphics/items/icon_pale
const u32 gItemIcon_LustrousGlobe[] = INCBIN_U32("graphics/items/icons/lustrous_globe.4bpp.lz");
const u32 gItemIconPalette_LustrousGlobe[] = INCBIN_U32("graphics/items/icon_palettes/lustrous_globe.gbapal.lz");
const u32 gItemIcon_BerserkGene[] = INCBIN_U32("graphics/items/icons/berserk_gene.4bpp.lz");
const u32 gItemIconPalette_BerserkGene[] = INCBIN_U32("graphics/items/icon_palettes/berserk_gene.gbapal.lz");

View File

@ -843,6 +843,7 @@ const u32 *const gItemIconTable[ITEMS_COUNT + 1][2] =
[ITEM_BLACK_AUGURITE] = {gItemIcon_BlackAugurite, gItemIconPalette_BlackAugurite},
[ITEM_LINKING_CORD] = {gItemIcon_LinkingCord, gItemIconPalette_LinkingCord},
[ITEM_PEAT_BLOCK] = {gItemIcon_PeatBlock, gItemIconPalette_PeatBlock},
[ITEM_BERSERK_GENE] = {gItemIcon_BerserkGene, gItemIconPalette_BerserkGene},
// Return to field arrow
[ITEMS_COUNT] = {gItemIcon_ReturnToFieldArrow, gItemIconPalette_ReturnToFieldArrow},
};

View File

@ -10340,4 +10340,17 @@ const struct Item gItems[] =
.fieldUseFunc = ItemUseOutOfBattle_EvolutionStone,
.flingPower = 30,
},
[ITEM_BERSERK_GENE] =
{
.name = _("Berserk Gene"),
.itemId = ITEM_BERSERK_GENE,
.price = 20,
.holdEffect = HOLD_EFFECT_BERSERK_GENE,
.description = sBerserkGene,
.pocket = POCKET_ITEMS,
.type = ITEM_USE_BAG_MENU,
.fieldUseFunc = ItemUseOutOfBattle_CannotUse,
.flingPower = 10,
},
};

View File

@ -3907,3 +3907,8 @@ static const u8 sLustrousGlobeDesc[] = _(
"A large, glowing gem\n"
"that lets Palkia\n"
"change form.");
static const u8 sBerserkGene[] = _(
"Sharply boosts\n"
"Attack, but causes\n"
"lasting confusion.");

View File

@ -0,0 +1,187 @@
#include "global.h"
#include "test_battle.h"
ASSUMPTIONS
{
ASSUME(gItems[ITEM_BERSERK_GENE].holdEffect == HOLD_EFFECT_BERSERK_GENE);
}
SINGLE_BATTLE_TEST("Berserk Gene sharply raises attack at the start of battle", s16 damage)
{
u16 useItem;
PARAMETRIZE { useItem = FALSE; }
PARAMETRIZE { useItem = TRUE; }
if (useItem) PASSES_RANDOMLY(66, 100, RNG_CONFUSION);
GIVEN {
PLAYER(SPECIES_WOBBUFFET) { if (useItem) Item(ITEM_BERSERK_GENE); };
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN {
MOVE(player, MOVE_TACKLE);
}
} SCENE {
if (useItem)
{
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player);
MESSAGE("Using Berserk Gene, the Attack of Wobbuffet sharply rose!");
ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_CONFUSION, player);
MESSAGE("Wobbuffet became confused!");
}
HP_BAR(opponent, captureDamage: &results[i].damage);
} FINALLY {
EXPECT_MUL_EQ(results[0].damage, Q_4_12(2.0), results[1].damage);
}
}
SINGLE_BATTLE_TEST("Berserk Gene activates on switch in", s16 damage)
{
u16 useItem;
PARAMETRIZE { useItem = FALSE; }
PARAMETRIZE { useItem = TRUE; }
if (useItem) PASSES_RANDOMLY(66, 100, RNG_CONFUSION);
GIVEN {
PLAYER(SPECIES_WYNAUT);
PLAYER(SPECIES_WOBBUFFET) { if (useItem) Item(ITEM_BERSERK_GENE); };
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN {
SWITCH(player, 1);
} TURN {
MOVE(player, MOVE_TACKLE);
}
} SCENE {
if (useItem)
{
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player);
MESSAGE("Using Berserk Gene, the Attack of Wobbuffet sharply rose!");
ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_CONFUSION, player);
MESSAGE("Wobbuffet became confused!");
}
HP_BAR(opponent, captureDamage: &results[i].damage);
} FINALLY {
EXPECT_MUL_EQ(results[0].damage, Q_4_12(2.0), results[1].damage);
}
}
SINGLE_BATTLE_TEST("Berserk Gene does not confuse a Pokemon with Own Tempo but still raises attack sharply", s16 damage)
{
u16 useItem;
PARAMETRIZE { useItem = FALSE; }
PARAMETRIZE { useItem = TRUE; }
GIVEN {
PLAYER(SPECIES_SLOWBRO) { Ability(ABILITY_OWN_TEMPO); if (useItem) Item(ITEM_BERSERK_GENE); };
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN {
MOVE(player, MOVE_TACKLE);
}
} SCENE {
if (useItem)
{
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player);
MESSAGE("Using Berserk Gene, the Attack of Slowbro sharply rose!");
ABILITY_POPUP(player, ABILITY_OWN_TEMPO);
MESSAGE("Slowbro's Own Tempo prevents confusion!");
}
HP_BAR(opponent, captureDamage: &results[i].damage);
NONE_OF
{
MESSAGE("Slowbro became confused!");
}
} FINALLY {
EXPECT_MUL_EQ(results[0].damage, Q_4_12(2.0), results[1].damage);
}
}
SINGLE_BATTLE_TEST("Berserk Gene does not confuse on Misty Terrain but still raises attack sharply")
{
GIVEN {
ASSUME(P_GEN_7_POKEMON == TRUE);
PLAYER(SPECIES_TAPU_FINI) { Ability(ABILITY_MISTY_SURGE); Item(ITEM_BERSERK_GENE); };
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN {
MOVE(player, MOVE_TACKLE);
}
} SCENE {
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player);
MESSAGE("Using Berserk Gene, the Attack of Tapu Fini sharply rose!");
NONE_OF
{
MESSAGE("Tapu Fini became confused!");
}
}
}
SINGLE_BATTLE_TEST("Berserk Gene does not confuse when Safeguard is active")
{
GIVEN {
PLAYER(SPECIES_WYNAUT);
PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_BERSERK_GENE); };
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, MOVE_SAFEGUARD); }
TURN { SWITCH(player, 1); }
} SCENE {
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player);
MESSAGE("Using Berserk Gene, the Attack of Wobbuffet sharply rose!");
MESSAGE("Wobbuffet's party is protected by SAFEGUARD!");
NONE_OF
{
MESSAGE("Wobbuffet became confused!");
}
}
}
SINGLE_BATTLE_TEST("Berserk Gene causes confusion for more than 5 turns") // how else would be check for infinite?
{
GIVEN {
PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_BERSERK_GENE); };
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN {}
TURN {}
TURN {}
TURN {}
TURN {}
TURN {}
} SCENE {
NONE_OF
{
MESSAGE("Wobbuffet snapped out of confusion!");
}
}
}
SINGLE_BATTLE_TEST("Berserk Gene causes infinite confusion") // check if bit is set
{
GIVEN {
PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_BERSERK_GENE); };
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN {}
} SCENE {
} THEN {
EXPECT(gStatuses4[GetBattlerAtPosition(B_POSITION_PLAYER_LEFT)] & STATUS4_INFINITE_CONFUSION);
}
}
SINGLE_BATTLE_TEST("Berserk Gene causes confusion timer to not tick down", u32 status2)
{
u32 turns;
PARAMETRIZE { turns = 1; }
PARAMETRIZE { turns = 2; }
GIVEN {
PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_BERSERK_GENE); };
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
u32 count;
for (count = 0; count < turns; count++) {
TURN {}
}
} THEN {
results[i].status2 = player->status2;
} FINALLY {
EXPECT_EQ(results[0].status2, results[1].status2);
}
}