Skip to content

Commit

Permalink
Merge pull request pret#1276 from LOuroboros/x_items_BE
Browse files Browse the repository at this point in the history
Reworked the effects of the X Items #1
  • Loading branch information
ExpoSeed authored Jan 15, 2021
2 parents b3a5b70 + 748562b commit 65d0798
Show file tree
Hide file tree
Showing 7 changed files with 188 additions and 8 deletions.
1 change: 1 addition & 0 deletions include/battle_message.h
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,7 @@ extern const u8 gText_BattleWallyName[];
extern const u8 gText_Win[];
extern const u8 gText_Loss[];
extern const u8 gText_Draw[];
extern const u8 gText_StatSharply[];
extern const u8 gText_StatRose[];
extern const u8 gText_PkmnsStatChanged2[];
extern const u8 gText_PkmnGettingPumped[];
Expand Down
1 change: 1 addition & 0 deletions include/constants/battle_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@
// Item settings
#define B_HP_BERRIES GEN_6 // In Gen4+, berries which restore hp activate immediately after hp drops to half. In gen3, the effect occurs at the end of the turn.
#define B_BERRIES_INSTANT GEN_6 // In Gen4+, most berries activate on battle start/switch-in if applicable. In gen3, they only activate either at the move end or turn end.
#define B_X_ITEMS_BUFF GEN_7 // In Gen7+, the X Items raise a stat by 2 stages instead of 1.

// Flag settings
// To use the following features in scripting, replace the 0s with the flag ID you're assigning it to.
Expand Down
12 changes: 12 additions & 0 deletions include/constants/item_effects.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,30 @@
#define GUARD_CONSTANTS_ITEM_EFFECTS_H

// field 0 masks
#ifndef ITEM_EXPANSION
#define ITEM0_X_ATTACK 0x0F
#endif
#define ITEM0_DIRE_HIT 0x30 // Works the same way as the move Focus Energy.
#define ITEM0_SACRED_ASH 0x40
#define ITEM0_INFATUATION 0x80

#ifndef ITEM_EXPANSION
// field 1 masks
#define ITEM1_X_SPEED 0x0F
#define ITEM1_X_DEFEND 0xF0

// field 2 masks
#define ITEM2_X_SPATK 0x0F
#define ITEM2_X_ACCURACY 0xF0
#else
// new field 1 masks
#define ITEM1_X_ATTACK 0x1
#define ITEM1_X_DEFENSE 0x2
#define ITEM1_X_SPEED 0x4
#define ITEM1_X_SPATK 0x8
#define ITEM1_X_SPDEF 0x10
#define ITEM1_X_ACCURACY 0x20
#endif

// field 3 masks
#define ITEM3_CONFUSION 0x1
Expand Down
21 changes: 21 additions & 0 deletions src/battle_ai_switch_items.c
Original file line number Diff line number Diff line change
Expand Up @@ -773,7 +773,11 @@ static u8 GetAI_ItemType(u16 itemId, const u8 *itemEffect)
return AI_ITEM_HEAL_HP;
else if (itemEffect[3] & ITEM3_STATUS_ALL)
return AI_ITEM_CURE_CONDITION;
#ifdef ITEM_EXPANSION
else if ((itemEffect[0] & ITEM0_DIRE_HIT) || itemEffect[1])
#else
else if (itemEffect[0] & (ITEM0_DIRE_HIT | ITEM0_X_ATTACK) || itemEffect[1] != 0 || itemEffect[2] != 0)
#endif
return AI_ITEM_X_STAT;
else if (itemEffect[3] & ITEM3_GUARD_SPEC)
return AI_ITEM_GUARD_SPECS;
Expand Down Expand Up @@ -883,6 +887,7 @@ static bool8 ShouldUseItem(void)
*(gBattleStruct->AI_itemFlags + gActiveBattler / 2) = 0;
if (gDisableStructs[gActiveBattler].isFirstTurn == 0)
break;
#ifndef ITEM_EXPANSION
if (itemEffects[0] & ITEM0_X_ATTACK)
*(gBattleStruct->AI_itemFlags + gActiveBattler / 2) |= 0x1;
if (itemEffects[1] & ITEM1_X_DEFEND)
Expand All @@ -895,6 +900,22 @@ static bool8 ShouldUseItem(void)
*(gBattleStruct->AI_itemFlags + gActiveBattler / 2) |= 0x20;
if (itemEffects[0] & ITEM0_DIRE_HIT)
*(gBattleStruct->AI_itemFlags + gActiveBattler / 2) |= 0x80;
#else
if (itemEffects[1] & ITEM1_X_ATTACK)
*(gBattleStruct->AI_itemFlags + gActiveBattler / 2) |= 0x1;
if (itemEffects[1] & ITEM1_X_DEFENSE)
*(gBattleStruct->AI_itemFlags + gActiveBattler / 2) |= 0x2;
if (itemEffects[1] & ITEM1_X_SPEED)
*(gBattleStruct->AI_itemFlags + gActiveBattler / 2) |= 0x4;
if (itemEffects[1] & ITEM1_X_SPATK)
*(gBattleStruct->AI_itemFlags + gActiveBattler / 2) |= 0x8;
if (itemEffects[1] & ITEM1_X_SPDEF)
*(gBattleStruct->AI_itemFlags + gActiveBattler / 2) |= 0x10;
if (itemEffects[1] & ITEM1_X_ACCURACY)
*(gBattleStruct->AI_itemFlags + gActiveBattler / 2) |= 0x20;
if (itemEffects[0] & ITEM0_DIRE_HIT)
*(gBattleStruct->AI_itemFlags + gActiveBattler / 2) |= 0x40;
#endif
shouldUse = TRUE;
break;
case AI_ITEM_GUARD_SPECS:
Expand Down
4 changes: 2 additions & 2 deletions src/battle_message.c
Original file line number Diff line number Diff line change
Expand Up @@ -305,7 +305,7 @@ static const u8 sText_PkmnsXPreventsFlinching[] = _("{B_EFF_NAME_WITH_PREFIX}'s
static const u8 sText_PkmnsXPreventsYsZ[] = _("{B_ATK_NAME_WITH_PREFIX}'s {B_ATK_ABILITY}\nprevents {B_DEF_NAME_WITH_PREFIX}'s\l{B_DEF_ABILITY} from working!");
static const u8 sText_PkmnsXCuredItsYProblem[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX}'s {B_SCR_ACTIVE_ABILITY}\ncured its {B_BUFF1} problem!");
static const u8 sText_PkmnsXHadNoEffectOnY[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX}'s {B_SCR_ACTIVE_ABILITY}\nhad no effect on {B_EFF_NAME_WITH_PREFIX}!");
static const u8 sText_StatSharply[] = _("sharply ");
const u8 gText_StatSharply[] = _("sharply ");
const u8 gText_StatRose[] = _("rose!");
static const u8 sText_StatHarshly[] = _("harshly ");
static const u8 sText_StatFell[] = _("fell!");
Expand Down Expand Up @@ -925,7 +925,7 @@ const u8 *const gBattleStringsTable[BATTLESTRINGS_COUNT] =
[STRINGID_PKMNPREVENTSSTATLOSSWITH - 12] = sText_PkmnPreventsStatLossWith,
[STRINGID_PKMNHURTSWITH - 12] = sText_PkmnHurtsWith,
[STRINGID_PKMNTRACED - 12] = sText_PkmnTraced,
[STRINGID_STATSHARPLY - 12] = sText_StatSharply,
[STRINGID_STATSHARPLY - 12] = gText_StatSharply,
[STRINGID_STATROSE - 12] = gText_StatRose,
[STRINGID_STATHARSHLY - 12] = sText_StatHarshly,
[STRINGID_STATFELL - 12] = sText_StatFell,
Expand Down
4 changes: 4 additions & 0 deletions src/party_menu.c
Original file line number Diff line number Diff line change
Expand Up @@ -5184,7 +5184,11 @@ u8 GetItemEffectType(u16 item)
else
itemEffect = gItemEffectTable[item - ITEM_POTION];

#ifndef ITEM_EXPANSION
if ((itemEffect[0] & (ITEM0_DIRE_HIT | ITEM0_X_ATTACK)) || itemEffect[1] || itemEffect[2] || (itemEffect[3] & ITEM3_GUARD_SPEC))
#else
if ((itemEffect[0] & ITEM0_DIRE_HIT) || itemEffect[1] || (itemEffect[3] & ITEM3_GUARD_SPEC))
#endif
return ITEM_EFFECT_X_ITEM;
else if (itemEffect[0] & ITEM0_SACRED_ASH)
return ITEM_EFFECT_SACRED_ASH;
Expand Down
153 changes: 147 additions & 6 deletions src/pokemon.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
#include "constants/moves.h"
#include "constants/songs.h"
#include "constants/trainers.h"
#include "constants/battle_config.h"

struct SpeciesItem
{
Expand Down Expand Up @@ -2050,7 +2051,11 @@ static const u8 sGetMonDataEVConstants[] =
// For stat-raising items
static const u8 sStatsToRaise[] =
{
#ifndef ITEM_EXPANSION
STAT_ATK, STAT_ATK, STAT_SPEED, STAT_DEF, STAT_SPATK, STAT_ACC
#else
STAT_ATK, STAT_ATK, STAT_DEF, STAT_SPEED, STAT_SPATK, STAT_SPDEF, STAT_ACC
#endif
};

// 3 modifiers each for how much to change friendship for different ranges
Expand Down Expand Up @@ -4432,29 +4437,41 @@ bool8 PokemonUseItemEffects(struct Pokemon *mon, u16 item, u8 partyIndex, u8 mov
gBattleMons[gActiveBattler].status2 |= STATUS2_FOCUS_ENERGY;
retVal = FALSE;
}
#ifndef ITEM_EXPANSION
if ((itemEffect[cmdIndex] & ITEM0_X_ATTACK)
&& gBattleMons[gActiveBattler].statStages[STAT_ATK] < MAX_STAT_STAGE)
{
gBattleMons[gActiveBattler].statStages[STAT_ATK] += itemEffect[cmdIndex] & ITEM0_X_ATTACK;
if (B_X_ITEMS_BUFF == GEN_7)
gBattleMons[gActiveBattler].statStages[STAT_ATK] += 2;
else
gBattleMons[gActiveBattler].statStages[STAT_ATK] += itemEffect[cmdIndex] & ITEM0_X_ATTACK;
if (gBattleMons[gActiveBattler].statStages[STAT_ATK] > MAX_STAT_STAGE)
gBattleMons[gActiveBattler].statStages[STAT_ATK] = MAX_STAT_STAGE;
retVal = FALSE;
}
#endif
break;
// in-battle stat boosting effects
#ifndef ITEM_EXPANSION
case 1:
if ((itemEffect[cmdIndex] & ITEM1_X_DEFEND)
&& gBattleMons[gActiveBattler].statStages[STAT_DEF] < MAX_STAT_STAGE)
{
gBattleMons[gActiveBattler].statStages[STAT_DEF] += (itemEffect[cmdIndex] & ITEM1_X_DEFEND) >> 4;
if (B_X_ITEMS_BUFF == GEN_7)
gBattleMons[gActiveBattler].statStages[STAT_DEF] += 2;
else
gBattleMons[gActiveBattler].statStages[STAT_DEF] += (itemEffect[cmdIndex] & ITEM1_X_DEFEND) >> 4;
if (gBattleMons[gActiveBattler].statStages[STAT_DEF] > MAX_STAT_STAGE)
gBattleMons[gActiveBattler].statStages[STAT_DEF] = MAX_STAT_STAGE;
retVal = FALSE;
}
if ((itemEffect[cmdIndex] & ITEM1_X_SPEED)
&& gBattleMons[gActiveBattler].statStages[STAT_SPEED] < MAX_STAT_STAGE)
{
gBattleMons[gActiveBattler].statStages[STAT_SPEED] += itemEffect[cmdIndex] & ITEM1_X_SPEED;
if (B_X_ITEMS_BUFF == GEN_7)
gBattleMons[gActiveBattler].statStages[STAT_SPEED] += 2;
else
gBattleMons[gActiveBattler].statStages[STAT_SPEED] += itemEffect[cmdIndex] & ITEM1_X_SPEED;
if (gBattleMons[gActiveBattler].statStages[STAT_SPEED] > MAX_STAT_STAGE)
gBattleMons[gActiveBattler].statStages[STAT_SPEED] = MAX_STAT_STAGE;
retVal = FALSE;
Expand All @@ -4465,20 +4482,100 @@ bool8 PokemonUseItemEffects(struct Pokemon *mon, u16 item, u8 partyIndex, u8 mov
if ((itemEffect[cmdIndex] & ITEM2_X_ACCURACY)
&& gBattleMons[gActiveBattler].statStages[STAT_ACC] < MAX_STAT_STAGE)
{
gBattleMons[gActiveBattler].statStages[STAT_ACC] += (itemEffect[cmdIndex] & ITEM2_X_ACCURACY) >> 4;
if (B_X_ITEMS_BUFF == GEN_7)
gBattleMons[gActiveBattler].statStages[STAT_ACC] += 2;
else
gBattleMons[gActiveBattler].statStages[STAT_ACC] += (itemEffect[cmdIndex] & ITEM2_X_ACCURACY) >> 4;
if (gBattleMons[gActiveBattler].statStages[STAT_ACC] > MAX_STAT_STAGE)
gBattleMons[gActiveBattler].statStages[STAT_ACC] = MAX_STAT_STAGE;
retVal = FALSE;
}
if ((itemEffect[cmdIndex] & ITEM2_X_SPATK)
&& gBattleMons[gActiveBattler].statStages[STAT_SPATK] < MAX_STAT_STAGE)
{
gBattleMons[gActiveBattler].statStages[STAT_SPATK] += itemEffect[cmdIndex] & ITEM2_X_SPATK;
if (B_X_ITEMS_BUFF == GEN_7)
gBattleMons[gActiveBattler].statStages[STAT_SPATK] += 2;
else
gBattleMons[gActiveBattler].statStages[STAT_SPATK] += itemEffect[cmdIndex] & ITEM2_X_SPATK;
if (gBattleMons[gActiveBattler].statStages[STAT_SPATK] > MAX_STAT_STAGE)
gBattleMons[gActiveBattler].statStages[STAT_SPATK] = MAX_STAT_STAGE;
retVal = FALSE;
}
break;
#else
// in-battle stat boosting effects
case 1:
if ((itemEffect[cmdIndex] & ITEM1_X_ATTACK)
&& gBattleMons[gActiveBattler].statStages[STAT_ATK] < MAX_STAT_STAGE)
{
if (B_X_ITEMS_BUFF == GEN_7)
gBattleMons[gActiveBattler].statStages[STAT_ATK] += 2;
else
gBattleMons[gActiveBattler].statStages[STAT_ATK] += 1;
if (gBattleMons[gActiveBattler].statStages[STAT_ATK] > MAX_STAT_STAGE)
gBattleMons[gActiveBattler].statStages[STAT_ATK] = MAX_STAT_STAGE;
retVal = FALSE;
}
if ((itemEffect[cmdIndex] & ITEM1_X_DEFENSE)
&& gBattleMons[gActiveBattler].statStages[STAT_DEF] < MAX_STAT_STAGE)
{
if (B_X_ITEMS_BUFF == GEN_7)
gBattleMons[gActiveBattler].statStages[STAT_DEF] += 2;
else
gBattleMons[gActiveBattler].statStages[STAT_DEF] += 1;
if (gBattleMons[gActiveBattler].statStages[STAT_DEF] > MAX_STAT_STAGE)
gBattleMons[gActiveBattler].statStages[STAT_DEF] = MAX_STAT_STAGE;
retVal = FALSE;
}
if ((itemEffect[cmdIndex] & ITEM1_X_SPEED)
&& gBattleMons[gActiveBattler].statStages[STAT_SPEED] < MAX_STAT_STAGE)
{
if (B_X_ITEMS_BUFF == GEN_7)
gBattleMons[gActiveBattler].statStages[STAT_SPEED] += 2;
else
gBattleMons[gActiveBattler].statStages[STAT_SPEED] += 1;
if (gBattleMons[gActiveBattler].statStages[STAT_SPEED] > MAX_STAT_STAGE)
gBattleMons[gActiveBattler].statStages[STAT_SPEED] = MAX_STAT_STAGE;
retVal = FALSE;
}
if ((itemEffect[cmdIndex] & ITEM1_X_SPATK)
&& gBattleMons[gActiveBattler].statStages[STAT_SPATK] < MAX_STAT_STAGE)
{
if (B_X_ITEMS_BUFF == GEN_7)
gBattleMons[gActiveBattler].statStages[STAT_SPATK] += 2;
else
gBattleMons[gActiveBattler].statStages[STAT_SPATK] += 1;
if (gBattleMons[gActiveBattler].statStages[STAT_SPATK] > MAX_STAT_STAGE)
gBattleMons[gActiveBattler].statStages[STAT_SPATK] = MAX_STAT_STAGE;
retVal = FALSE;
}
if ((itemEffect[cmdIndex] & ITEM1_X_SPDEF)
&& gBattleMons[gActiveBattler].statStages[STAT_SPDEF] < MAX_STAT_STAGE)
{
if (B_X_ITEMS_BUFF == GEN_7)
gBattleMons[gActiveBattler].statStages[STAT_SPDEF] += 2;
else
gBattleMons[gActiveBattler].statStages[STAT_SPDEF] += 1;
if (gBattleMons[gActiveBattler].statStages[STAT_SPDEF] > MAX_STAT_STAGE)
gBattleMons[gActiveBattler].statStages[STAT_SPDEF] = MAX_STAT_STAGE;
retVal = FALSE;
}
if ((itemEffect[cmdIndex] & ITEM1_X_ACCURACY)
&& gBattleMons[gActiveBattler].statStages[STAT_ACC] < MAX_STAT_STAGE)
{
if (B_X_ITEMS_BUFF == GEN_7)
gBattleMons[gActiveBattler].statStages[STAT_ACC] += 2;
else
gBattleMons[gActiveBattler].statStages[STAT_ACC] += 1;
if (gBattleMons[gActiveBattler].statStages[STAT_ACC] > MAX_STAT_STAGE)
gBattleMons[gActiveBattler].statStages[STAT_ACC] = MAX_STAT_STAGE;
retVal = FALSE;
}
break;
// formerly used by the item effects of the X Sp. Atk and the X Accuracy
case 2:
break;
#endif
case 3:
if ((itemEffect[cmdIndex] & ITEM3_GUARD_SPEC)
&& gSideTimers[GetBattlerSide(gActiveBattler)].mistTimer == 0)
Expand Down Expand Up @@ -5026,7 +5123,15 @@ static void BufferStatRoseMessage(s32 arg0)
{
gBattlerTarget = gBattlerInMenuId;
StringCopy(gBattleTextBuff1, gStatNamesTable[sStatsToRaise[arg0]]);
StringCopy(gBattleTextBuff2, gText_StatRose);
if (B_X_ITEMS_BUFF == GEN_7)
{
StringCopy(gBattleTextBuff2, gText_StatSharply);
StringAppend(gBattleTextBuff2, gText_StatRose);
}
else
{
StringCopy(gBattleTextBuff2, gText_StatRose);
}
BattleStringExpandPlaceholdersToDisplayedString(gText_PkmnsStatChanged2);
}

Expand All @@ -5049,6 +5154,7 @@ u8 *UseStatIncreaseItem(u16 itemId)

gPotentialItemEffectBattler = gBattlerInMenuId;

#ifndef ITEM_EXPANSION
for (i = 0; i < 3; i++)
{
if (itemEffect[i] & (ITEM0_X_ATTACK | ITEM1_X_SPEED | ITEM2_X_SPATK))
Expand All @@ -5073,6 +5179,41 @@ u8 *UseStatIncreaseItem(u16 itemId)
gBattlerAttacker = gBattlerInMenuId;
BattleStringExpandPlaceholdersToDisplayedString(gText_PkmnShroudedInMist);
}
#else
if (itemEffect[0] & ITEM0_DIRE_HIT)
{
gBattlerAttacker = gBattlerInMenuId;
BattleStringExpandPlaceholdersToDisplayedString(gText_PkmnGettingPumped);
}

switch (itemEffect[1])
{
case ITEM1_X_ATTACK:
BufferStatRoseMessage(STAT_ATK);
break;
case ITEM1_X_DEFENSE:
BufferStatRoseMessage(STAT_DEF);
break;
case ITEM1_X_SPEED:
BufferStatRoseMessage(STAT_SPEED);
break;
case ITEM1_X_SPATK:
BufferStatRoseMessage(STAT_SPATK);
break;
case ITEM1_X_SPDEF:
BufferStatRoseMessage(STAT_SPDEF);
break;
case ITEM1_X_ACCURACY:
BufferStatRoseMessage(STAT_ACC);
break;
}

if (itemEffect[3] & ITEM3_GUARD_SPEC)
{
gBattlerAttacker = gBattlerInMenuId;
BattleStringExpandPlaceholdersToDisplayedString(gText_PkmnShroudedInMist);
}
#endif

return gDisplayedStringBattle;
}
Expand Down

0 comments on commit 65d0798

Please sign in to comment.