mirror of
https://github.com/pret/pokefirered.git
synced 2026-09-30 12:59:43 -05:00
added missing configs and implemented item configs
This commit is contained in:
21
include/config/level_caps.h
Normal file
21
include/config/level_caps.h
Normal file
@@ -0,0 +1,21 @@
|
||||
#ifndef GUARD_CONFIG_LEVEL_CAP_H
|
||||
#define GUARD_CONFIG_LEVEL_CAP_H
|
||||
|
||||
// Constants
|
||||
#define EXP_CAP_NONE 0 // Regular behavior, no level caps are applied
|
||||
#define EXP_CAP_HARD 1 // Pokémon with a level >= the level cap cannot gain any experience
|
||||
#define EXP_CAP_SOFT 2 // Pokémon with a level >= the level cap will gain reduced experience
|
||||
|
||||
#define LEVEL_CAP_NONE 0 // No level cap, only applicable if B_EXP_CAP_TYPE is EXP_CAP_NONE
|
||||
#define LEVEL_CAP_FLAG_LIST 1 // Level cap is chosen according to the first unset flag in `sLevelCapFlagMap`
|
||||
#define LEVEL_CAP_VARIABLE 2 // Level cap is chosen according to the contents of the event variable specified by B_LEVEL_CAP_VARIABLE
|
||||
|
||||
// Configs
|
||||
#define B_EXP_CAP_TYPE EXP_CAP_NONE // [EXP_CAP_NONE, EXP_CAP_HARD, EXP_CAP_SOFT] choose the type of level cap to apply
|
||||
#define B_LEVEL_CAP_TYPE LEVEL_CAP_NONE // [LEVEL_CAP_NONE, LEVEL_CAP_FLAG_LIST, LEVEL_CAP_VARIABLE] choose the method to derive the level cap
|
||||
#define B_LEVEL_CAP_VARIABLE 0 // event variable used to derive level cap if B_LEVEL_CAP_TYPE is set to LEVEL_CAP_VARIABLE
|
||||
|
||||
#define B_RARE_CANDY_CAP FALSE // If set to true, Rare Candies can't be used to go over the level cap
|
||||
#define B_LEVEL_CAP_EXP_UP FALSE // If set to true, mons under level cap will receive more experience
|
||||
|
||||
#endif /* GUARD_CONFIG_LEVEL_CAP_H */
|
||||
23
include/config/save.h
Normal file
23
include/config/save.h
Normal file
@@ -0,0 +1,23 @@
|
||||
#ifndef GUARD_CONFIG_SAVE_H
|
||||
#define GUARD_CONFIG_SAVE_H
|
||||
|
||||
// SaveBlock1 configs
|
||||
#define FREE_EXTRA_SEEN_FLAGS_SAVEBLOCK1 FALSE // Free up unused Pokédex seen flags (52 bytes).
|
||||
#define FREE_TRAINER_HILL FALSE // Frees up Trainer Hill data (28 bytes).
|
||||
#define FREE_MYSTERY_EVENT_BUFFERS FALSE // Frees up ramScript (1104 bytes).
|
||||
#define FREE_MATCH_CALL FALSE // Frees up match call and rematch / VS Seeker data. (104 bytes).
|
||||
#define FREE_UNION_ROOM_CHAT FALSE // Frees up union room chat (212 bytes).
|
||||
#define FREE_ENIGMA_BERRY FALSE // Frees up E-Reader Enigma Berry data (52 bytes).
|
||||
#define FREE_LINK_BATTLE_RECORDS FALSE // Frees up link battle record data (88 bytes).
|
||||
#define FREE_MYSTERY_GIFT FALSE // Frees up Mystery Gift data (876 bytes).
|
||||
// SaveBlock1 total: 2516 bytes
|
||||
// SaveBlock2 configs
|
||||
#define FREE_BATTLE_TOWER_E_READER FALSE // Frees up Battle Tower E-Reader data (188 bytes).
|
||||
#define FREE_POKEMON_JUMP FALSE // Frees up Pokémon Jump data (16 bytes).
|
||||
#define FREE_RECORD_MIXING_HALL_RECORDS FALSE // Frees up hall records for record mixing (1032 bytes).
|
||||
#define FREE_EXTRA_SEEN_FLAGS_SAVEBLOCK2 FALSE // Free up unused Pokédex seen flags (108 bytes).
|
||||
// SaveBlock2 total: 1274 bytes
|
||||
|
||||
// Grand Total: 3790
|
||||
|
||||
#endif // GUARD_CONFIG_SAVE_H
|
||||
1138
include/config/test.h
Normal file
1138
include/config/test.h
Normal file
File diff suppressed because it is too large
Load Diff
@@ -4,7 +4,7 @@
|
||||
#include "config/battle.h"
|
||||
#include "config/debug.h"
|
||||
#include "config/item.h"
|
||||
// #include "config/level_caps.h"
|
||||
#include "config/level_caps.h"
|
||||
#include "config/pokemon.h"
|
||||
#include "config/overworld.h"
|
||||
|
||||
@@ -134,4 +134,9 @@
|
||||
#define CONNECTION_DIVE 5
|
||||
#define CONNECTION_EMERGE 6
|
||||
|
||||
#if TESTING
|
||||
#include "config/test.h"
|
||||
#endif
|
||||
|
||||
|
||||
#endif //GUARD_CONSTANTS_GLOBAL_H
|
||||
|
||||
@@ -43,6 +43,7 @@ u8 *CopyItemNameHandlePlural(u16 itemId, u8 *string, u32 quantity);
|
||||
bool8 IsBagPocketNonEmpty(u8 pocket);
|
||||
bool8 CheckBagHasItem(u16 itemId, u16 count);
|
||||
bool8 CheckBagHasSpace(u16 itemId, u16 count);
|
||||
u32 GetFreeSpaceForItemInBag(u16 itemId);
|
||||
bool8 RemoveBagItem(u16 itemId, u16 count);
|
||||
u8 GetPocketByItemId(u16 itemId);
|
||||
void ClearItemSlots(struct ItemSlot *itemSlots, u8 b);
|
||||
|
||||
@@ -986,6 +986,8 @@ extern const u8 gText_InBagVar1[];
|
||||
extern const u8 gText_Var1AndYouWantedVar2[];
|
||||
extern const u8 gText_HereYouGoThankYou[];
|
||||
extern const u8 gText_NoMoreRoomForThis[];
|
||||
extern const u8 gText_ThrowInPremierBall[];
|
||||
extern const u8 gText_ThrowInPremierBalls[];
|
||||
|
||||
// pokedex_screen
|
||||
extern const u8 gText_PokedexTableOfContents[];
|
||||
|
||||
@@ -10,6 +10,8 @@
|
||||
|
||||
#define NUM_ALTERING_CAVE_TABLES 9
|
||||
|
||||
#define FISHING_CHAIN_LENGTH_MAX 20
|
||||
|
||||
struct WildPokemon
|
||||
{
|
||||
u8 minLevel;
|
||||
@@ -36,6 +38,7 @@ struct WildPokemonHeader
|
||||
extern const struct WildPokemonHeader gWildMonHeaders[];
|
||||
extern bool8 gIsFishingEncounter;
|
||||
extern bool8 gIsSurfingEncounter;
|
||||
extern u8 gChainFishingDexNavStreak;
|
||||
|
||||
void DisableWildEncounters(bool8 disabled);
|
||||
u8 PickWildMonNature(void);
|
||||
|
||||
44
src/item.c
44
src/item.c
@@ -187,36 +187,36 @@ bool8 HasAtLeastOneBerry(void)
|
||||
|
||||
bool8 CheckBagHasSpace(u16 itemId, u16 count)
|
||||
{
|
||||
u8 i;
|
||||
u8 pocket;
|
||||
|
||||
if (ItemId_GetPocket(itemId) == 0)
|
||||
if (ItemId_GetPocket(itemId) == POCKET_NONE)
|
||||
return FALSE;
|
||||
|
||||
pocket = ItemId_GetPocket(itemId) - 1;
|
||||
// Check for item slots that contain the item
|
||||
return GetFreeSpaceForItemInBag(itemId) >= count;
|
||||
}
|
||||
|
||||
u32 GetFreeSpaceForItemInBag(u16 itemId)
|
||||
{
|
||||
u8 i;
|
||||
u8 pocket = ItemId_GetPocket(itemId) - 1;
|
||||
u16 ownedCount;
|
||||
u32 spaceForItem = 0;
|
||||
|
||||
if (ItemId_GetPocket(itemId) == POCKET_NONE)
|
||||
return 0;
|
||||
|
||||
// Check space in any existing item slots that already contain this item
|
||||
for (i = 0; i < gBagPockets[pocket].capacity; i++)
|
||||
{
|
||||
if (gBagPockets[pocket].itemSlots[i].itemId == itemId)
|
||||
{
|
||||
u16 quantity;
|
||||
// Does this stack have room for more??
|
||||
quantity = GetBagItemQuantity(&gBagPockets[pocket].itemSlots[i].quantity);
|
||||
if (quantity + count <= 999)
|
||||
return TRUE;
|
||||
// RS and Emerald check whether there is enough of the
|
||||
// item across all stacks.
|
||||
// For whatever reason, FR/LG assume there's only one
|
||||
// stack of the item.
|
||||
else
|
||||
return FALSE;
|
||||
ownedCount = GetBagItemQuantity(&gBagPockets[pocket].itemSlots[i].quantity);
|
||||
spaceForItem += max(0, MAX_BAG_ITEM_CAPACITY - ownedCount);
|
||||
}
|
||||
else if (gBagPockets[pocket].itemSlots[i].itemId == ITEM_NONE)
|
||||
{
|
||||
spaceForItem += MAX_BAG_ITEM_CAPACITY;
|
||||
}
|
||||
}
|
||||
|
||||
if (BagPocketGetFirstEmptySlot(pocket) != -1)
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
return spaceForItem;
|
||||
}
|
||||
|
||||
bool8 AddBagItem(u16 itemId, u16 count)
|
||||
|
||||
@@ -1830,10 +1830,12 @@ static void ReturnToBagMenuFromSubmenu_Sell(void)
|
||||
GoToBagMenu(ITEMMENULOCATION_SHOP, OPEN_BAG_LAST, CB2_ReturnToField);
|
||||
}
|
||||
|
||||
#define ITEM_SELL_FACTOR ((I_SELL_VALUE_FRACTION >= GEN_9) ? 4 : 2)
|
||||
|
||||
static void Task_PrintSaleConfirmationText(u8 taskId)
|
||||
{
|
||||
s16 *data = gTasks[taskId].data;
|
||||
ConvertIntToDecimalStringN(gStringVar3, ItemId_GetPrice(BagGetItemIdByPocketPosition(gBagMenuState.pocket + 1, data[1])) / 2 * data[8], STR_CONV_MODE_LEFT_ALIGN, 6);
|
||||
ConvertIntToDecimalStringN(gStringVar3, (ItemId_GetPrice(BagGetItemIdByPocketPosition(gBagMenuState.pocket + 1, data[1])) / ITEM_SELL_FACTOR) * data[8], STR_CONV_MODE_LEFT_ALIGN, 6);
|
||||
StringExpandPlaceholders(gStringVar4, gText_ICanPayThisMuch_WouldThatBeOkay);
|
||||
DisplayItemMessageInBag(taskId, GetDialogBoxFontId(), gStringVar4, Task_ShowSellYesNoMenu);
|
||||
}
|
||||
@@ -1863,7 +1865,7 @@ static void Task_InitSaleQuantitySelectInterface(u8 taskId)
|
||||
ConvertIntToDecimalStringN(gStringVar1, 1, STR_CONV_MODE_LEADING_ZEROS, 2);
|
||||
StringExpandPlaceholders(gStringVar4, gText_TimesStrVar1);
|
||||
BagPrintTextOnWindow(r4, FONT_SMALL, gStringVar4, 4, 10, 1, 0, 0xFF, 1);
|
||||
UpdateSalePriceDisplay(ItemId_GetPrice(BagGetItemIdByPocketPosition(gBagMenuState.pocket + 1, data[1])) / 2 * data[8]);
|
||||
UpdateSalePriceDisplay((ItemId_GetPrice(BagGetItemIdByPocketPosition(gBagMenuState.pocket + 1, data[1])) / ITEM_SELL_FACTOR) * data[8]);
|
||||
BagPrintMoneyAmount();
|
||||
CreatePocketScrollArrowPair_SellQuantity();
|
||||
gTasks[taskId].func = Task_SelectQuantityToSell;
|
||||
@@ -1880,7 +1882,7 @@ static void Task_SelectQuantityToSell(u8 taskId)
|
||||
if (AdjustQuantityAccordingToDPadInput(&data[8], data[2]) == TRUE)
|
||||
{
|
||||
UpdateQuantityToTossOrDeposit(data[8], 2);
|
||||
UpdateSalePriceDisplay(ItemId_GetPrice(BagGetItemIdByPocketPosition(gBagMenuState.pocket + 1, data[1])) / 2 * data[8]);
|
||||
UpdateSalePriceDisplay((ItemId_GetPrice(BagGetItemIdByPocketPosition(gBagMenuState.pocket + 1, data[1])) / ITEM_SELL_FACTOR) * data[8]);
|
||||
}
|
||||
else if (JOY_NEW(A_BUTTON))
|
||||
{
|
||||
@@ -1913,7 +1915,7 @@ static void Task_SellItem_Yes(u8 taskId)
|
||||
PutWindowTilemap(0);
|
||||
ScheduleBgCopyTilemapToVram(0);
|
||||
CopyItemName(gSpecialVar_ItemId, gStringVar1);
|
||||
ConvertIntToDecimalStringN(gStringVar3, ItemId_GetPrice(BagGetItemIdByPocketPosition(gBagMenuState.pocket + 1, data[1])) / 2 * data[8], STR_CONV_MODE_LEFT_ALIGN, 6);
|
||||
ConvertIntToDecimalStringN(gStringVar3, (ItemId_GetPrice(BagGetItemIdByPocketPosition(gBagMenuState.pocket + 1, data[1])) / ITEM_SELL_FACTOR) * data[8], STR_CONV_MODE_LEFT_ALIGN, 6);
|
||||
StringExpandPlaceholders(gStringVar4, gText_TurnedOverItemsWorthYen);
|
||||
DisplayItemMessageInBag(taskId, FONT_NORMAL, gStringVar4, Task_FinalizeSaleToShop);
|
||||
}
|
||||
@@ -1923,7 +1925,7 @@ static void Task_FinalizeSaleToShop(u8 taskId)
|
||||
s16 *data = gTasks[taskId].data;
|
||||
PlaySE(SE_SHOP);
|
||||
RemoveBagItem(gSpecialVar_ItemId, data[8]);
|
||||
AddMoney(&gSaveBlock1Ptr->money, ItemId_GetPrice(gSpecialVar_ItemId) / 2 * data[8]);
|
||||
AddMoney(&gSaveBlock1Ptr->money, (ItemId_GetPrice(gSpecialVar_ItemId) / ITEM_SELL_FACTOR) * data[8]);
|
||||
RecordItemTransaction(gSpecialVar_ItemId, data[8], QL_EVENT_SOLD_ITEM - QL_EVENT_USED_POKEMART);
|
||||
DestroyListMenuTask(data[0], &gBagMenuState.cursorPos[gBagMenuState.pocket], &gBagMenuState.itemsAbove[gBagMenuState.pocket]);
|
||||
Pocket_CalculateNItemsAndMaxShowed(gBagMenuState.pocket);
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#include "field_specials.h"
|
||||
#include "berry.h"
|
||||
#include "recorded_battle.h"
|
||||
#include "wild_encounter.h"
|
||||
#include "constants/items.h"
|
||||
#include "constants/item_effects.h"
|
||||
#include "constants/cries.h"
|
||||
@@ -1266,6 +1267,8 @@ void CreateBoxMon(struct BoxPokemon *boxMon, u16 species, u8 level, u8 fixedIV,
|
||||
totalRerolls += I_SHINY_CHARM_ADDITIONAL_ROLLS;
|
||||
if (LURE_STEP_COUNT != 0)
|
||||
totalRerolls += 1;
|
||||
if (I_FISHING_CHAIN && gIsFishingEncounter)
|
||||
totalRerolls += (1 + (2 * gChainFishingDexNavStreak));
|
||||
|
||||
while (GET_SHINY_VALUE(value, personality) >= SHINY_ODDS && totalRerolls > 0)
|
||||
{
|
||||
|
||||
26
src/shop.c
26
src/shop.c
@@ -995,10 +995,34 @@ static void BuyMenuSubtractMoney(u8 taskId)
|
||||
|
||||
static void Task_ReturnToItemListAfterItemPurchase(u8 taskId)
|
||||
{
|
||||
s16 *data = gTasks[taskId].data;
|
||||
if (JOY_NEW(A_BUTTON) || JOY_NEW(B_BUTTON))
|
||||
{
|
||||
u16 premierBallsToAdd = tItemCount / 10;
|
||||
if (premierBallsToAdd >= 1
|
||||
&& ((I_PREMIER_BALL_BONUS <= GEN_7 && tItemId == ITEM_POKE_BALL)
|
||||
|| (I_PREMIER_BALL_BONUS >= GEN_8 && (ItemId_GetPocket(tItemId) == POCKET_POKE_BALLS))))
|
||||
{
|
||||
u32 spaceAvailable = GetFreeSpaceForItemInBag(ITEM_PREMIER_BALL);
|
||||
if (spaceAvailable < premierBallsToAdd)
|
||||
premierBallsToAdd = spaceAvailable;
|
||||
}
|
||||
else
|
||||
{
|
||||
premierBallsToAdd = 0;
|
||||
}
|
||||
|
||||
PlaySE(SE_SELECT);
|
||||
BuyMenuReturnToItemList(taskId);
|
||||
AddBagItem(ITEM_PREMIER_BALL, premierBallsToAdd);
|
||||
if (premierBallsToAdd > 0)
|
||||
{
|
||||
ConvertIntToDecimalStringN(gStringVar1, premierBallsToAdd, STR_CONV_MODE_LEFT_ALIGN, MAX_ITEM_DIGITS);
|
||||
BuyMenuDisplayMessage(taskId, (premierBallsToAdd >= 2 ? gText_ThrowInPremierBalls : gText_ThrowInPremierBall), BuyMenuReturnToItemList);
|
||||
}
|
||||
else
|
||||
{
|
||||
BuyMenuReturnToItemList(taskId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -246,7 +246,8 @@ const u8 gText_NoMoreRoomForThis[] = _("You have no more room for this\nitem.{PA
|
||||
const u8 gText_SpaceForVar1Full[] = _("{STR_VAR_1}を\nいれる ばしょが いっぱいです{PAUSE_UNTIL_PRESS}");
|
||||
const u8 gText_AnythingElseICanHelp[] = _("Is there anything else I can do?");
|
||||
const u8 gText_CanIHelpWithAnythingElse[] = _("その ほかに\nなにか ちからに なれることは?");
|
||||
const u8 gText_ThrowInPremierBall[] = _("プレミアボ-ル 1コ\nおまけ しておきますね!{PAUSE_UNTIL_PRESS}");
|
||||
const u8 gText_ThrowInPremierBall[] = _("I'll throw in a Premier Ball, too.{PAUSE_UNTIL_PRESS}");
|
||||
const u8 gText_ThrowInPremierBalls[] = _("I'll throw in {STR_VAR_1} Premier Balls, too.{PAUSE_UNTIL_PRESS}");
|
||||
const u8 gText_OhNoICantBuyThat[] = _("{STR_VAR_1}? Oh, no.\nI can't buy that.{PAUSE_UNTIL_PRESS}");
|
||||
const u8 gText_HowManyWouldYouLikeToSell[] = _("{STR_VAR_1}?\nHow many would you like to sell?");
|
||||
const u8 gText_ICanPayThisMuch_WouldThatBeOkay[] = _("I can pay ¥{STR_VAR_3}.\nWould that be okay?");
|
||||
|
||||
@@ -51,9 +51,12 @@ static EWRAM_DATA struct WildEncounterData sWildEncounterData = {};
|
||||
static EWRAM_DATA bool8 sWildEncountersDisabled = FALSE;
|
||||
EWRAM_DATA bool8 gIsFishingEncounter = 0;
|
||||
EWRAM_DATA bool8 gIsSurfingEncounter = 0;
|
||||
EWRAM_DATA u8 gChainFishingDexNavStreak = 0;
|
||||
EWRAM_DATA static u16 sLastFishingSpecies = 0;
|
||||
|
||||
static bool8 UnlockedTanobyOrAreNotInTanoby(void);
|
||||
static u32 GenerateUnownPersonalityByLetter(u8 letter);
|
||||
static void UpdateChainFishingSpeciesAndStreak(u32 species);
|
||||
static bool8 IsWildLevelAllowedByRepel(u8 level);
|
||||
static void ApplyFluteEncounterRateMod(u32 *rate);
|
||||
static u8 GetMaxLevelOfSpeciesInWildTable(const struct WildPokemon *wildMon, u16 species, u8 area);
|
||||
@@ -444,13 +447,15 @@ static bool8 TryGenerateWildMon(const struct WildPokemonInfo * wildMonInfo, u8 a
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static u16 GenerateFishingEncounter(const struct WildPokemonInfo * info, u8 rod)
|
||||
static u16 GenerateFishingEncounter(const struct WildPokemonInfo * wildMonInfo, u8 rod)
|
||||
{
|
||||
u8 wildMonIndex = ChooseWildMonIndex_Fishing(rod);
|
||||
u8 level = ChooseWildMonLevel(info->wildPokemon, wildMonIndex, WILD_AREA_FISHING);
|
||||
u16 wildMonSpecies = wildMonInfo->wildPokemon[wildMonIndex].species;
|
||||
u8 level = ChooseWildMonLevel(wildMonInfo->wildPokemon, wildMonIndex, WILD_AREA_FISHING);
|
||||
|
||||
CreateWildMon(info->wildPokemon[wildMonIndex].species, level, wildMonIndex);
|
||||
return info->wildPokemon[wildMonIndex].species;
|
||||
UpdateChainFishingSpeciesAndStreak(wildMonSpecies);
|
||||
CreateWildMon(wildMonSpecies, level, wildMonIndex);
|
||||
return wildMonSpecies;
|
||||
}
|
||||
|
||||
static bool8 DoWildEncounterRateDiceRoll(u16 encounterRate)
|
||||
@@ -717,6 +722,29 @@ bool8 DoesCurrentMapHaveFishingMons(void)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void HandleChainFishingStreak(u32 species)
|
||||
{
|
||||
if (species != sLastFishingSpecies)
|
||||
{
|
||||
gChainFishingDexNavStreak = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (gChainFishingDexNavStreak >= FISHING_CHAIN_LENGTH_MAX)
|
||||
return;
|
||||
|
||||
gChainFishingDexNavStreak++;
|
||||
}
|
||||
|
||||
static void UpdateChainFishingSpeciesAndStreak(u32 species)
|
||||
{
|
||||
if (!I_FISHING_CHAIN)
|
||||
return;
|
||||
|
||||
HandleChainFishingStreak(species);
|
||||
sLastFishingSpecies = species;
|
||||
}
|
||||
|
||||
void FishingWildEncounter(u8 rod)
|
||||
{
|
||||
GenerateFishingEncounter(gWildMonHeaders[GetCurrentMapWildMonHeaderId()].fishingMonsInfo, rod);
|
||||
|
||||
Reference in New Issue
Block a user