EV Caps and EV Items (#5269)
* EV Caps and EV Items Introduces EV caps, inspired by level caps, with configurable options for various cap implementations. Additionally, modifies EV items to interact with these caps based on a configurable setting. * EV Caps fixes Changed the EV caps to be less redundant and work better overall. * EV Caps Fix part 2 Set the items back to ItemUseOutOfBattle_Medicine, got rid of ItemUseOutOfBattle_EVItem and ItemUseCB_EVItem, and reverted CB2_ReturnToPartyMenuUsingItem to CB2_ReturnToPartyMenuUsingRareCandy * EV Caps Fixes Part 3 Fixed being able to use EV items to go over 252 limit on single stats. * Update src/ev_caps.c Co-authored-by: Alex <93446519+AlexOn1ine@users.noreply.github.com> --------- Co-authored-by: Alex <93446519+AlexOn1ine@users.noreply.github.com>
This commit is contained in:
parent
484acdc138
commit
de242c8a29
5 changed files with 110 additions and 29 deletions
16
include/config/ev_caps.h
Normal file
16
include/config/ev_caps.h
Normal file
|
@ -0,0 +1,16 @@
|
|||
#ifndef GUARD_CONFIG_EV_CAP_H
|
||||
#define GUARD_CONFIG_EV_CAP_H
|
||||
|
||||
// Constants for EV Cap Types
|
||||
#define EV_CAP_NONE 0 // Regular behavior, no EV caps are applied
|
||||
#define EV_CAP_FLAG_LIST 1 // EV cap is chosen according to the first unset flag in `sEVCapFlagMap`
|
||||
#define EV_CAP_VARIABLE 2 // EV cap is chosen according to the contents of the event variable specified by B_EV_CAP_VARIABLE
|
||||
#define EV_CAP_NO_GAIN 3 // No EVs can be gained
|
||||
|
||||
// Configs for EV Cap
|
||||
#define B_EV_CAP_TYPE EV_CAP_NONE // [EV_CAP_NONE, EV_CAP_FLAG_LIST, EV_CAP_VARIABLE, EV_CAP_NO_GAIN] choose the type of EV cap to apply#define B_EV_CAP_VARIABLE 12 // event variable used to derive EV cap if B_EV_CAP_TYPE is set to EV_CAP_VARIABLE
|
||||
#define B_EV_CAP_VARIABLE 8 // event variable used to derive EV cap if B_EV_CAP_TYPE is set to EV_CAP_VARIABLE
|
||||
|
||||
#define B_EV_ITEMS_CAP FALSE // If set to true, EV-boosting items can't be used to go over the EV cap
|
||||
|
||||
#endif /*GUARD_CONFIG_EV_CAP_H*/
|
|
@ -8,6 +8,7 @@
|
|||
#include "config/level_caps.h"
|
||||
#include "config/pokemon.h"
|
||||
#include "config/overworld.h"
|
||||
#include "config/ev_caps.h"
|
||||
|
||||
// Invalid Versions show as "----------" in Gen 4 and Gen 5's summary screen.
|
||||
// In Gens 6 and 7, invalid versions instead show "a distant land" in the summary screen.
|
||||
|
|
10
include/ev_caps.h
Normal file
10
include/ev_caps.h
Normal file
|
@ -0,0 +1,10 @@
|
|||
#ifndef GUARD_EV_CAP_H
|
||||
#define GUARD_EV_CAP_H
|
||||
|
||||
#if B_EV_CAP_TYPE != EV_CAP_NONE && B_EV_CAP_TYPE != EV_CAP_FLAG_LIST && B_EV_CAP_TYPE != EV_CAP_VARIABLE && B_EV_CAP_TYPE != EV_CAP_NO_GAIN
|
||||
#error "Invalid choice for B_EV_CAP_TYPE, must be one of [EV_CAP_NONE, EV_CAP_FLAG_LIST, EV_CAP_VARIABLE, EV_CAP_NO_GAIN]"
|
||||
#endif
|
||||
|
||||
u32 GetCurrentEVCap(void);
|
||||
|
||||
#endif /* GUARD_EV_CAP_H */
|
41
src/ev_caps.c
Normal file
41
src/ev_caps.c
Normal file
|
@ -0,0 +1,41 @@
|
|||
#include "global.h"
|
||||
#include "battle.h"
|
||||
#include "event_data.h"
|
||||
#include "ev_caps.h"
|
||||
#include "pokemon.h"
|
||||
|
||||
u32 GetCurrentEVCap(void)
|
||||
{
|
||||
|
||||
static const u16 sEvCapFlagMap[][2] = {
|
||||
// Define EV caps for each milestone
|
||||
{FLAG_BADGE01_GET, 30},
|
||||
{FLAG_BADGE02_GET, 90},
|
||||
{FLAG_BADGE03_GET, 150},
|
||||
{FLAG_BADGE04_GET, 210},
|
||||
{FLAG_BADGE05_GET, 270},
|
||||
{FLAG_BADGE06_GET, 330},
|
||||
{FLAG_BADGE07_GET, 390},
|
||||
{FLAG_BADGE08_GET, 450},
|
||||
{FLAG_IS_CHAMPION, MAX_TOTAL_EVS},
|
||||
};
|
||||
|
||||
if (B_EV_CAP_TYPE == EV_CAP_FLAG_LIST)
|
||||
{
|
||||
for (u32 evCap = 0; evCap < ARRAY_COUNT(sEvCapFlagMap); evCap++)
|
||||
{
|
||||
if (!FlagGet(sEvCapFlagMap[evCap][0]))
|
||||
return sEvCapFlagMap[evCap][1];
|
||||
}
|
||||
}
|
||||
else if (B_EV_CAP_TYPE == EV_CAP_VARIABLE)
|
||||
{
|
||||
return VarGet(B_EV_CAP_VARIABLE);
|
||||
}
|
||||
else if (B_EV_CAP_TYPE == EV_CAP_NO_GAIN)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return MAX_TOTAL_EVS;
|
||||
}
|
|
@ -60,6 +60,7 @@
|
|||
#include "constants/union_room.h"
|
||||
#include "constants/weather.h"
|
||||
#include "wild_encounter.h"
|
||||
#include "ev_caps.h"
|
||||
|
||||
#define FRIENDSHIP_EVO_THRESHOLD ((P_FRIENDSHIP_EVO_THRESHOLD >= GEN_9) ? 160 : 220)
|
||||
|
||||
|
@ -3752,6 +3753,9 @@ bool8 PokemonUseItemEffects(struct Pokemon *mon, u16 item, u8 partyIndex, u8 mov
|
|||
s8 evChange;
|
||||
u16 evCount;
|
||||
|
||||
// Determine the EV cap to use
|
||||
u32 maxAllowedEVs = !B_EV_ITEMS_CAP ? MAX_TOTAL_EVS : GetCurrentEVCap();
|
||||
|
||||
// Get item hold effect
|
||||
heldItem = GetMonData(mon, MON_DATA_HELD_ITEM, NULL);
|
||||
if (heldItem == ITEM_ENIGMA_BERRY_E_READER)
|
||||
|
@ -3879,27 +3883,31 @@ bool8 PokemonUseItemEffects(struct Pokemon *mon, u16 item, u8 partyIndex, u8 mov
|
|||
|
||||
if (evChange > 0) // Increasing EV (HP or Atk)
|
||||
{
|
||||
// Has EV increase limit already been reached?
|
||||
if (evCount >= MAX_TOTAL_EVS)
|
||||
// Check if the total EV limit is reached
|
||||
if (evCount >= maxAllowedEVs)
|
||||
return TRUE;
|
||||
|
||||
if (itemEffect[10] & ITEM10_IS_VITAMIN)
|
||||
evCap = EV_ITEM_RAISE_LIMIT;
|
||||
else
|
||||
evCap = MAX_PER_STAT_EVS;
|
||||
|
||||
// Ensure the increase does not exceed the max EV per stat (252)
|
||||
evCap = (itemEffect[10] & ITEM10_IS_VITAMIN) ? EV_ITEM_RAISE_LIMIT : MAX_PER_STAT_EVS;
|
||||
|
||||
// Check if the per-stat limit is reached
|
||||
if (dataSigned >= evCap)
|
||||
break;
|
||||
|
||||
// Limit the increase
|
||||
return TRUE; // Prevents item use if the per-stat cap is already reached
|
||||
|
||||
if (dataSigned + evChange > evCap)
|
||||
temp2 = evCap - (dataSigned + evChange) + evChange;
|
||||
temp2 = evCap - dataSigned;
|
||||
else
|
||||
temp2 = evChange;
|
||||
|
||||
if (evCount + temp2 > MAX_TOTAL_EVS)
|
||||
temp2 += MAX_TOTAL_EVS - (evCount + temp2);
|
||||
// Ensure the total EVs do not exceed the maximum allowed (510)
|
||||
if (evCount + temp2 > maxAllowedEVs)
|
||||
temp2 = maxAllowedEVs - evCount;
|
||||
|
||||
// Prevent item use if no EVs can be increased
|
||||
if (temp2 == 0)
|
||||
return TRUE;
|
||||
|
||||
// Apply the EV increase
|
||||
dataSigned += temp2;
|
||||
}
|
||||
else if (evChange < 0) // Decreasing EV (HP or Atk)
|
||||
|
@ -4064,27 +4072,31 @@ bool8 PokemonUseItemEffects(struct Pokemon *mon, u16 item, u8 partyIndex, u8 mov
|
|||
evChange = temp2;
|
||||
if (evChange > 0) // Increasing EV
|
||||
{
|
||||
// Has EV increase limit already been reached?
|
||||
if (evCount >= MAX_TOTAL_EVS)
|
||||
// Check if the total EV limit is reached
|
||||
if (evCount >= maxAllowedEVs)
|
||||
return TRUE;
|
||||
|
||||
if (itemEffect[10] & ITEM10_IS_VITAMIN)
|
||||
evCap = EV_ITEM_RAISE_LIMIT;
|
||||
else
|
||||
evCap = MAX_PER_STAT_EVS;
|
||||
|
||||
// Ensure the increase does not exceed the max EV per stat (252)
|
||||
evCap = (itemEffect[10] & ITEM10_IS_VITAMIN) ? EV_ITEM_RAISE_LIMIT : MAX_PER_STAT_EVS;
|
||||
|
||||
// Check if the per-stat limit is reached
|
||||
if (dataSigned >= evCap)
|
||||
break;
|
||||
|
||||
// Limit the increase
|
||||
return TRUE; // Prevents item use if the per-stat cap is already reached
|
||||
|
||||
if (dataSigned + evChange > evCap)
|
||||
temp2 = evCap - (dataSigned + evChange) + evChange;
|
||||
temp2 = evCap - dataSigned;
|
||||
else
|
||||
temp2 = evChange;
|
||||
|
||||
if (evCount + temp2 > MAX_TOTAL_EVS)
|
||||
temp2 += MAX_TOTAL_EVS - (evCount + temp2);
|
||||
// Ensure the total EVs do not exceed the maximum allowed (510)
|
||||
if (evCount + temp2 > maxAllowedEVs)
|
||||
temp2 = maxAllowedEVs - evCount;
|
||||
|
||||
// Prevent item use if no EVs can be increased
|
||||
if (temp2 == 0)
|
||||
return TRUE;
|
||||
|
||||
// Apply the EV increase
|
||||
dataSigned += temp2;
|
||||
}
|
||||
else if (evChange < 0) // Decreasing EV
|
||||
|
@ -5195,6 +5207,7 @@ void MonGainEVs(struct Pokemon *mon, u16 defeatedSpecies)
|
|||
int i, multiplier;
|
||||
u8 stat;
|
||||
u8 bonus;
|
||||
u32 currentEVCap = GetCurrentEVCap();
|
||||
|
||||
heldItem = GetMonData(mon, MON_DATA_HELD_ITEM, 0);
|
||||
if (heldItem == ITEM_ENIGMA_BERRY_E_READER)
|
||||
|
@ -5224,7 +5237,7 @@ void MonGainEVs(struct Pokemon *mon, u16 defeatedSpecies)
|
|||
|
||||
for (i = 0; i < NUM_STATS; i++)
|
||||
{
|
||||
if (totalEVs >= MAX_TOTAL_EVS)
|
||||
if (totalEVs >= currentEVCap)
|
||||
break;
|
||||
|
||||
if (CheckPartyHasHadPokerus(mon, 0))
|
||||
|
@ -5275,8 +5288,8 @@ void MonGainEVs(struct Pokemon *mon, u16 defeatedSpecies)
|
|||
if (holdEffect == HOLD_EFFECT_MACHO_BRACE)
|
||||
evIncrease *= 2;
|
||||
|
||||
if (totalEVs + (s16)evIncrease > MAX_TOTAL_EVS)
|
||||
evIncrease = ((s16)evIncrease + MAX_TOTAL_EVS) - (totalEVs + evIncrease);
|
||||
if (totalEVs + (s16)evIncrease > currentEVCap)
|
||||
evIncrease = ((s16)evIncrease + currentEVCap) - (totalEVs + evIncrease);
|
||||
|
||||
if (evs[i] + (s16)evIncrease > MAX_PER_STAT_EVS)
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue