From 66177e795824676ac20aafa6edb35fdc961088d4 Mon Sep 17 00:00:00 2001 From: Eduardo Quezada Date: Sun, 11 Sep 2022 13:54:55 -0400 Subject: [PATCH 1/9] Reworked shiny charm rerolls allow adding additional rerolls when necessary --- include/pokemon.h | 2 +- src/pokemon.c | 16 +++++++--------- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/include/pokemon.h b/include/pokemon.h index 39f6e406b0..af14e18e41 100644 --- a/include/pokemon.h +++ b/include/pokemon.h @@ -385,7 +385,7 @@ struct FormChange | (((personality) & 0x00000003) >> 0) \ ) % NUM_UNOWN_FORMS) -#define GET_SHINY_VALUE(otId, personality)HIHALF(otId) ^ LOHALF(otId) ^ HIHALF(personality) ^ LOHALF(personality) +#define GET_SHINY_VALUE(otId, personality) (HIHALF(otId) ^ LOHALF(otId) ^ HIHALF(personality) ^ LOHALF(personality)) extern u8 gPlayerPartyCount; extern struct Pokemon gPlayerParty[PARTY_SIZE]; diff --git a/src/pokemon.c b/src/pokemon.c index b421e5aced..19498810a3 100644 --- a/src/pokemon.c +++ b/src/pokemon.c @@ -3300,21 +3300,19 @@ void CreateBoxMon(struct BoxPokemon *boxMon, u16 species, u8 level, u8 fixedIV, } else // Player is the OT { + u32 totalRerolls = 0; value = gSaveBlock2Ptr->playerTrainerId[0] | (gSaveBlock2Ptr->playerTrainerId[1] << 8) | (gSaveBlock2Ptr->playerTrainerId[2] << 16) | (gSaveBlock2Ptr->playerTrainerId[3] << 24); - + if (CheckBagHasItem(ITEM_SHINY_CHARM, 1)) + totalRerolls += I_SHINY_CHARM_REROLLS; + + while (GET_SHINY_VALUE(value, personality) >= SHINY_ODDS && totalRerolls > 0) { - u32 shinyValue; - u32 rolls = 0; - do - { - personality = Random32(); - shinyValue = HIHALF(value) ^ LOHALF(value) ^ HIHALF(personality) ^ LOHALF(personality); - rolls++; - } while (shinyValue >= SHINY_ODDS && rolls < I_SHINY_CHARM_REROLLS); + personality = Random32(); + totalRerolls--; } } From e3c19f5df52b8fde36ad1ff57fccbc3d3314b95d Mon Sep 17 00:00:00 2001 From: Deokishisu <6993375+Deokishisu@users.noreply.github.com> Date: Sat, 27 Aug 2022 19:46:59 -0400 Subject: [PATCH 2/9] Implement B2W2 Repel System The game now asks if the player would like to use another Repel when the one they used runs out. # Conflicts: # include/constants/vars.h --- data/scripts/repel.inc | 32 ++++++++++++++++++++++++++++++++ include/constants/vars.h | 2 +- src/item.c | 5 +++++ src/item_use.c | 1 + 4 files changed, 39 insertions(+), 1 deletion(-) diff --git a/data/scripts/repel.inc b/data/scripts/repel.inc index fc178603c0..2c4e075f43 100644 --- a/data/scripts/repel.inc +++ b/data/scripts/repel.inc @@ -1,6 +1,38 @@ EventScript_RepelWoreOff:: + checkitem VAR_LAST_REPEL_USED, 1 + compare VAR_RESULT, TRUE + goto_if_eq EventScript_UseAnother + lock msgbox Text_RepelWoreOff, MSGBOX_SIGN + release + end + +EventScript_UseAnother: + lock + msgbox Text_UseAnother, MSGBOX_YESNO + compare VAR_RESULT, YES + goto_if_eq EventScript_UsedRepel + release + end + +EventScript_UsedRepel: + bufferitemname 0, VAR_LAST_REPEL_USED + playse SE_REPEL + lock + msgbox Text_UsedNewRepel, MSGBOX_SIGN + removeitem VAR_LAST_REPEL_USED, 1 + waitse + callnative HandleUseExpiredRepel + release end Text_RepelWoreOff: .string "REPEL's effect wore off…$" + +Text_UseAnother:: + .string "REPEL's effect wore off!\n" + .string "Use another?$" + +Text_UsedNewRepel:: + .string "{PLAYER} used the\n" + .string "{STR_VAR_1}.$" diff --git a/include/constants/vars.h b/include/constants/vars.h index 8128b6f321..aba1125c04 100644 --- a/include/constants/vars.h +++ b/include/constants/vars.h @@ -271,7 +271,7 @@ #define VAR_UNUSED_0x40FC 0x40FC // Unused Var #define VAR_UNUSED_0x40FD 0x40FD // Unused Var #define VAR_UNUSED_0x40FE 0x40FE // Unused Var -#define VAR_UNUSED_0x40FF 0x40FF // Unused Var +#define VAR_LAST_REPEL_USED 0x40FF // Unused Var #define VARS_END 0x40FF #define VARS_COUNT (VARS_END - VARS_START + 1) diff --git a/src/item.c b/src/item.c index f93e7adad3..3a62d83e4a 100644 --- a/src/item.c +++ b/src/item.c @@ -952,3 +952,8 @@ u8 ItemId_GetFlingPower(u16 itemId) { return gItems[SanitizeItemId(itemId)].flingPower; } + +void HandleUseExpiredRepel(void) +{ + VarSet(VAR_REPEL_STEP_COUNT, ItemId_GetHoldEffectParam(VarGet(VAR_LAST_REPEL_USED))); +} diff --git a/src/item_use.c b/src/item_use.c index 5cd162519f..e5e38c871b 100644 --- a/src/item_use.c +++ b/src/item_use.c @@ -871,6 +871,7 @@ static void Task_UseRepel(u8 taskId) if (!IsSEPlaying()) { VarSet(VAR_REPEL_STEP_COUNT, ItemId_GetHoldEffectParam(gSpecialVar_ItemId)); + VarSet(VAR_LAST_REPEL_USED, gSpecialVar_ItemId); RemoveUsedItem(); if (!InBattlePyramid()) DisplayItemMessage(taskId, FONT_NORMAL, gStringVar4, CloseItemMessage); From 2d78ac019226615a66b5aea34dfbcac2c3472f3a Mon Sep 17 00:00:00 2001 From: Eduardo Quezada Date: Sun, 11 Sep 2022 19:48:27 -0400 Subject: [PATCH 3/9] Implemented Lures using the same vars as repels --- data/scripts/repel.inc | 39 ++++++++++++++- include/constants/item.h | 6 +++ include/constants/vars.h | 2 +- include/item_use.h | 1 + include/strings.h | 1 + src/data/items.h | 6 +-- src/item.c | 5 -- src/item_use.c | 51 +++++++++++++++++++- src/strings.c | 1 + src/wild_encounter.c | 102 +++++++++++++++++++++++++++++---------- 10 files changed, 175 insertions(+), 39 deletions(-) diff --git a/data/scripts/repel.inc b/data/scripts/repel.inc index 2c4e075f43..e5ecbcb41a 100644 --- a/data/scripts/repel.inc +++ b/data/scripts/repel.inc @@ -19,7 +19,7 @@ EventScript_UsedRepel: bufferitemname 0, VAR_LAST_REPEL_USED playse SE_REPEL lock - msgbox Text_UsedNewRepel, MSGBOX_SIGN + msgbox Text_UsedNewRepelLure, MSGBOX_SIGN removeitem VAR_LAST_REPEL_USED, 1 waitse callnative HandleUseExpiredRepel @@ -33,6 +33,41 @@ Text_UseAnother:: .string "REPEL's effect wore off!\n" .string "Use another?$" -Text_UsedNewRepel:: +Text_UsedNewRepelLure:: .string "{PLAYER} used the\n" .string "{STR_VAR_1}.$" + +EventScript_LureWoreOff:: + checkitem VAR_LAST_REPEL_USED, 1 + compare VAR_RESULT, TRUE + goto_if_eq EventScript_LureUseAnother + lock + msgbox Text_LureWoreOff, MSGBOX_SIGN + release + end + +EventScript_LureUseAnother: + lock + msgbox Text_UseAnotherLure, MSGBOX_YESNO + compare VAR_RESULT, YES + goto_if_eq EventScript_UsedLure + release + end + +EventScript_UsedLure: + bufferitemname 0, VAR_LAST_REPEL_USED + playse SE_REPEL + lock + msgbox Text_UsedNewRepelLure, MSGBOX_SIGN + removeitem VAR_LAST_REPEL_USED, 1 + waitse + callnative HandleUseExpiredLure + release + end + +Text_LureWoreOff: + .string "Lure's effect wore off…$" + +Text_UseAnotherLure:: + .string "Lure's effect wore off!\n" + .string "Use another?$" diff --git a/include/constants/item.h b/include/constants/item.h index a224291faf..9b574417a7 100644 --- a/include/constants/item.h +++ b/include/constants/item.h @@ -16,4 +16,10 @@ #define KEYITEMS_POCKET 4 #define POCKETS_COUNT 5 +#define REPEL_LURE_MASK (1 << 15) +#define IS_LAST_USED_LURE(var) (var & REPEL_LURE_MASK) +#define REPEL_LURE_STEPS(var) (var & (REPEL_LURE_MASK - 1)) +#define LURE_STEPS(var) (IS_LAST_USED_LURE(var) ? REPEL_LURE_STEPS(var) : 0) +#define REPEL_STEPS(var) (!IS_LAST_USED_LURE(var) ? REPEL_LURE_STEPS(var) : 0) + #endif // GUARD_ITEM_CONSTANTS_H diff --git a/include/constants/vars.h b/include/constants/vars.h index aba1125c04..5118f0533d 100644 --- a/include/constants/vars.h +++ b/include/constants/vars.h @@ -47,7 +47,7 @@ // general purpose vars #define VAR_RECYCLE_GOODS 0x4020 -#define VAR_REPEL_STEP_COUNT 0x4021 +#define VAR_REPEL_LURE_STEP_COUNT 0x4021 #define VAR_ICE_STEP_COUNT 0x4022 #define VAR_STARTER_MON 0x4023 // 0=Treecko, 1=Torchic, 2=Mudkip #define VAR_MIRAGE_RND_H 0x4024 diff --git a/include/item_use.h b/include/item_use.h index d55f7cf0d7..bdbf2cdeac 100644 --- a/include/item_use.h +++ b/include/item_use.h @@ -20,6 +20,7 @@ void ItemUseOutOfBattle_PPUp(u8); void ItemUseOutOfBattle_RareCandy(u8); void ItemUseOutOfBattle_TMHM(u8); void ItemUseOutOfBattle_Repel(u8); +void ItemUseOutOfBattle_Lure(u8); void ItemUseOutOfBattle_EscapeRope(u8); void ItemUseOutOfBattle_BlackWhiteFlute(u8); void ItemUseOutOfBattle_EvolutionStone(u8); diff --git a/include/strings.h b/include/strings.h index 25a96eef08..626d633821 100644 --- a/include/strings.h +++ b/include/strings.h @@ -936,6 +936,7 @@ extern const u8 gText_BootedUpTM[]; extern const u8 gText_TMHMContainedVar1[]; extern const u8 gText_PlayerUsedVar2[]; extern const u8 gText_RepelEffectsLingered[]; +extern const u8 gText_LureEffectsLingered[]; extern const u8 gText_UsedVar2WildLured[]; extern const u8 gText_UsedVar2WildRepelled[]; extern const u8 gText_BoxFull[]; diff --git a/src/data/items.h b/src/data/items.h index b0b53c31f5..5087ca03b5 100644 --- a/src/data/items.h +++ b/src/data/items.h @@ -1565,7 +1565,7 @@ const struct Item gItems[] = .description = sLureDesc, .pocket = POCKET_ITEMS, .type = ITEM_USE_BAG_MENU, - .fieldUseFunc = ItemUseOutOfBattle_CannotUse, + .fieldUseFunc = ItemUseOutOfBattle_Lure, .secondaryId = 0, .flingPower = 30, }, @@ -1579,7 +1579,7 @@ const struct Item gItems[] = .description = sSuperLureDesc, .pocket = POCKET_ITEMS, .type = ITEM_USE_BAG_MENU, - .fieldUseFunc = ItemUseOutOfBattle_CannotUse, + .fieldUseFunc = ItemUseOutOfBattle_Lure, .secondaryId = 0, .flingPower = 30, }, @@ -1593,7 +1593,7 @@ const struct Item gItems[] = .description = sMaxLureDesc, .pocket = POCKET_ITEMS, .type = ITEM_USE_BAG_MENU, - .fieldUseFunc = ItemUseOutOfBattle_CannotUse, + .fieldUseFunc = ItemUseOutOfBattle_Lure, .secondaryId = 0, .flingPower = 30, }, diff --git a/src/item.c b/src/item.c index 3a62d83e4a..f93e7adad3 100644 --- a/src/item.c +++ b/src/item.c @@ -952,8 +952,3 @@ u8 ItemId_GetFlingPower(u16 itemId) { return gItems[SanitizeItemId(itemId)].flingPower; } - -void HandleUseExpiredRepel(void) -{ - VarSet(VAR_REPEL_STEP_COUNT, ItemId_GetHoldEffectParam(VarGet(VAR_LAST_REPEL_USED))); -} diff --git a/src/item_use.c b/src/item_use.c index e5e38c871b..1dddc57386 100644 --- a/src/item_use.c +++ b/src/item_use.c @@ -67,7 +67,9 @@ static void Task_ShowTMHMContainedMessage(u8); static void UseTMHMYesNo(u8); static void UseTMHM(u8); static void Task_StartUseRepel(u8); +static void Task_StartUseLure(u8 taskId); static void Task_UseRepel(u8); +static void Task_UseLure(u8 taskId); static void Task_CloseCantUseKeyItemMessage(u8); static void SetDistanceOfClosestHiddenItem(u8, s16, s16); static void CB2_OpenPokeblockFromBag(void); @@ -846,7 +848,7 @@ static void RemoveUsedItem(void) void ItemUseOutOfBattle_Repel(u8 taskId) { - if (VarGet(VAR_REPEL_STEP_COUNT) == 0) + if (REPEL_STEPS(VarGet(VAR_REPEL_LURE_STEP_COUNT)) == 0) gTasks[taskId].func = Task_StartUseRepel; else if (!InBattlePyramid()) DisplayItemMessage(taskId, FONT_NORMAL, gText_RepelEffectsLingered, CloseItemMessage); @@ -870,7 +872,7 @@ static void Task_UseRepel(u8 taskId) { if (!IsSEPlaying()) { - VarSet(VAR_REPEL_STEP_COUNT, ItemId_GetHoldEffectParam(gSpecialVar_ItemId)); + VarSet(VAR_REPEL_LURE_STEP_COUNT, ItemId_GetHoldEffectParam(gSpecialVar_ItemId)); VarSet(VAR_LAST_REPEL_USED, gSpecialVar_ItemId); RemoveUsedItem(); if (!InBattlePyramid()) @@ -879,6 +881,51 @@ static void Task_UseRepel(u8 taskId) DisplayItemMessageInBattlePyramid(taskId, gStringVar4, Task_CloseBattlePyramidBagMessage); } } +void HandleUseExpiredRepel(void) +{ + VarSet(VAR_REPEL_LURE_STEP_COUNT, ItemId_GetHoldEffectParam(VarGet(VAR_LAST_REPEL_USED))); +} + +void ItemUseOutOfBattle_Lure(u8 taskId) +{ + if (LURE_STEPS(VarGet(VAR_REPEL_LURE_STEP_COUNT)) == 0) + gTasks[taskId].func = Task_StartUseLure; + else if (!InBattlePyramid()) + DisplayItemMessage(taskId, FONT_NORMAL, gText_LureEffectsLingered, CloseItemMessage); + else + DisplayItemMessageInBattlePyramid(taskId, gText_LureEffectsLingered, Task_CloseBattlePyramidBagMessage); +} + +static void Task_StartUseLure(u8 taskId) +{ + s16* data = gTasks[taskId].data; + + if (++data[8] > 7) + { + data[8] = 0; + PlaySE(SE_REPEL); + gTasks[taskId].func = Task_UseLure; + } +} + +static void Task_UseLure(u8 taskId) +{ + if (!IsSEPlaying()) + { + VarSet(VAR_REPEL_LURE_STEP_COUNT, ItemId_GetHoldEffectParam(gSpecialVar_ItemId) | REPEL_LURE_MASK); + VarSet(VAR_LAST_REPEL_USED, gSpecialVar_ItemId); + RemoveUsedItem(); + if (!InBattlePyramid()) + DisplayItemMessage(taskId, FONT_NORMAL, gStringVar4, CloseItemMessage); + else + DisplayItemMessageInBattlePyramid(taskId, gStringVar4, Task_CloseBattlePyramidBagMessage); + } +} + +void HandleUseExpiredLure(void) +{ + VarSet(VAR_REPEL_LURE_STEP_COUNT, ItemId_GetHoldEffectParam(VarGet(VAR_LAST_REPEL_USED)) | REPEL_LURE_MASK); +} static void Task_UsedBlackWhiteFlute(u8 taskId) { diff --git a/src/strings.c b/src/strings.c index d199b92d4b..4375adad24 100644 --- a/src/strings.c +++ b/src/strings.c @@ -244,6 +244,7 @@ const u8 gText_BootedUpHM[] = _("Booted up an HM."); const u8 gText_TMHMContainedVar1[] = _("It contained\n{STR_VAR_1}.\pTeach {STR_VAR_1}\nto a POKéMON?"); const u8 gText_PlayerUsedVar2[] = _("{PLAYER} used the\n{STR_VAR_2}.{PAUSE_UNTIL_PRESS}"); const u8 gText_RepelEffectsLingered[] = _("But the effects of a REPEL\nlingered from earlier.{PAUSE_UNTIL_PRESS}"); +const u8 gText_LureEffectsLingered[] = _("But the effects of a Lure\nlingered from earlier.{PAUSE_UNTIL_PRESS}"); const u8 gText_UsedVar2WildLured[] = _("{PLAYER} used the\n{STR_VAR_2}.\pWild POKéMON will be lured.{PAUSE_UNTIL_PRESS}"); const u8 gText_UsedVar2WildRepelled[] = _("{PLAYER} used the\n{STR_VAR_2}.\pWild POKéMON will be repelled.{PAUSE_UNTIL_PRESS}"); const u8 gText_BoxFull[] = _("The BOX is full.{PAUSE_UNTIL_PRESS}"); diff --git a/src/wild_encounter.c b/src/wild_encounter.c index e49d09f54d..1ac3487939 100644 --- a/src/wild_encounter.c +++ b/src/wild_encounter.c @@ -20,11 +20,13 @@ #include "constants/abilities.h" #include "constants/battle_config.h" #include "constants/game_stat.h" +#include "constants/item.h" #include "constants/items.h" #include "constants/layouts.h" #include "constants/weather.h" extern const u8 EventScript_RepelWoreOff[]; +extern const u8 EventScript_LureWoreOff[]; #define MAX_ENCOUNTER_RATE 2880 @@ -181,58 +183,82 @@ static void FeebasSeedRng(u16 seed) // LAND_WILD_COUNT static u8 ChooseWildMonIndex_Land(void) { + u8 wildMonIndex = 0; + bool8 swap = FALSE; u8 rand = Random() % ENCOUNTER_CHANCE_LAND_MONS_TOTAL; if (rand < ENCOUNTER_CHANCE_LAND_MONS_SLOT_0) - return 0; + wildMonIndex = 0; else if (rand >= ENCOUNTER_CHANCE_LAND_MONS_SLOT_0 && rand < ENCOUNTER_CHANCE_LAND_MONS_SLOT_1) - return 1; + wildMonIndex = 1; else if (rand >= ENCOUNTER_CHANCE_LAND_MONS_SLOT_1 && rand < ENCOUNTER_CHANCE_LAND_MONS_SLOT_2) - return 2; + wildMonIndex = 2; else if (rand >= ENCOUNTER_CHANCE_LAND_MONS_SLOT_2 && rand < ENCOUNTER_CHANCE_LAND_MONS_SLOT_3) - return 3; + wildMonIndex = 3; else if (rand >= ENCOUNTER_CHANCE_LAND_MONS_SLOT_3 && rand < ENCOUNTER_CHANCE_LAND_MONS_SLOT_4) - return 4; + wildMonIndex = 4; else if (rand >= ENCOUNTER_CHANCE_LAND_MONS_SLOT_4 && rand < ENCOUNTER_CHANCE_LAND_MONS_SLOT_5) - return 5; + wildMonIndex = 5; else if (rand >= ENCOUNTER_CHANCE_LAND_MONS_SLOT_5 && rand < ENCOUNTER_CHANCE_LAND_MONS_SLOT_6) - return 6; + wildMonIndex = 6; else if (rand >= ENCOUNTER_CHANCE_LAND_MONS_SLOT_6 && rand < ENCOUNTER_CHANCE_LAND_MONS_SLOT_7) - return 7; + wildMonIndex = 7; else if (rand >= ENCOUNTER_CHANCE_LAND_MONS_SLOT_7 && rand < ENCOUNTER_CHANCE_LAND_MONS_SLOT_8) - return 8; + wildMonIndex = 8; else if (rand >= ENCOUNTER_CHANCE_LAND_MONS_SLOT_8 && rand < ENCOUNTER_CHANCE_LAND_MONS_SLOT_9) - return 9; + wildMonIndex = 9; else if (rand >= ENCOUNTER_CHANCE_LAND_MONS_SLOT_9 && rand < ENCOUNTER_CHANCE_LAND_MONS_SLOT_10) - return 10; + wildMonIndex = 10; else - return 11; + wildMonIndex = 11; + + if (LURE_STEPS(VarGet(VAR_REPEL_LURE_STEP_COUNT)) && (Random() % 10 < 2)) + swap = TRUE; + + if (swap) + wildMonIndex = 11 - wildMonIndex; + + return wildMonIndex; } // ROCK_WILD_COUNT / WATER_WILD_COUNT static u8 ChooseWildMonIndex_WaterRock(void) { + u8 wildMonIndex = 0; + bool8 swap = FALSE; u8 rand = Random() % ENCOUNTER_CHANCE_WATER_MONS_TOTAL; if (rand < ENCOUNTER_CHANCE_WATER_MONS_SLOT_0) - return 0; + wildMonIndex = 0; else if (rand >= ENCOUNTER_CHANCE_WATER_MONS_SLOT_0 && rand < ENCOUNTER_CHANCE_WATER_MONS_SLOT_1) - return 1; + wildMonIndex = 1; else if (rand >= ENCOUNTER_CHANCE_WATER_MONS_SLOT_1 && rand < ENCOUNTER_CHANCE_WATER_MONS_SLOT_2) - return 2; + wildMonIndex = 2; else if (rand >= ENCOUNTER_CHANCE_WATER_MONS_SLOT_2 && rand < ENCOUNTER_CHANCE_WATER_MONS_SLOT_3) - return 3; + wildMonIndex = 3; else - return 4; + wildMonIndex = 4; + + if (LURE_STEPS(VarGet(VAR_REPEL_LURE_STEP_COUNT)) && (Random() % 10 < 2)) + swap = TRUE; + + if (swap) + wildMonIndex = 4 - wildMonIndex; + + return wildMonIndex; } // FISH_WILD_COUNT static u8 ChooseWildMonIndex_Fishing(u8 rod) { u8 wildMonIndex = 0; + bool8 swap = FALSE; u8 rand = Random() % max(max(ENCOUNTER_CHANCE_FISHING_MONS_OLD_ROD_TOTAL, ENCOUNTER_CHANCE_FISHING_MONS_GOOD_ROD_TOTAL), ENCOUNTER_CHANCE_FISHING_MONS_SUPER_ROD_TOTAL); + if (LURE_STEPS(VarGet(VAR_REPEL_LURE_STEP_COUNT)) && (Random() % 10 < 2)) + swap = TRUE; + switch (rod) { case OLD_ROD: @@ -241,6 +267,9 @@ static u8 ChooseWildMonIndex_Fishing(u8 rod) else wildMonIndex = 1; break; + + if (swap) + wildMonIndex = 1 - wildMonIndex; case GOOD_ROD: if (rand < ENCOUNTER_CHANCE_FISHING_MONS_GOOD_ROD_SLOT_2) wildMonIndex = 2; @@ -248,6 +277,9 @@ static u8 ChooseWildMonIndex_Fishing(u8 rod) wildMonIndex = 3; if (rand >= ENCOUNTER_CHANCE_FISHING_MONS_GOOD_ROD_SLOT_3 && rand < ENCOUNTER_CHANCE_FISHING_MONS_GOOD_ROD_SLOT_4) wildMonIndex = 4; + + if (swap) + wildMonIndex = 6 - wildMonIndex; break; case SUPER_ROD: if (rand < ENCOUNTER_CHANCE_FISHING_MONS_SUPER_ROD_SLOT_5) @@ -260,6 +292,9 @@ static u8 ChooseWildMonIndex_Fishing(u8 rod) wildMonIndex = 8; if (rand >= ENCOUNTER_CHANCE_FISHING_MONS_SUPER_ROD_SLOT_8 && rand < ENCOUNTER_CHANCE_FISHING_MONS_SUPER_ROD_SLOT_9) wildMonIndex = 9; + + if (swap) + wildMonIndex = 14 - wildMonIndex; break; } return wildMonIndex; @@ -521,6 +556,8 @@ static bool8 DoWildEncounterRateTest(u32 encounterRate, bool8 ignoreAbility) encounterRate = encounterRate * 80 / 100; ApplyFluteEncounterRateMod(&encounterRate); ApplyCleanseTagEncounterRateMod(&encounterRate); + if (LURE_STEPS(VarGet(VAR_REPEL_LURE_STEP_COUNT)) != 0) + encounterRate *= 2; if (!ignoreAbility && !GetMonData(&gPlayerParty[0], MON_DATA_SANITY_IS_EGG)) { u32 ability = GetMonAbility(&gPlayerParty[0]); @@ -892,24 +929,37 @@ u16 GetLocalWaterMon(void) bool8 UpdateRepelCounter(void) { - u16 steps; + u16 repelLureVar = VarGet(VAR_REPEL_LURE_STEP_COUNT); + u16 steps = REPEL_LURE_STEPS(repelLureVar); + bool32 isLure = IS_LAST_USED_LURE(repelLureVar); if (InBattlePike() || InBattlePyramid()) return FALSE; if (InUnionRoom() == TRUE) return FALSE; - steps = VarGet(VAR_REPEL_STEP_COUNT); - if (steps != 0) { steps--; - VarSet(VAR_REPEL_STEP_COUNT, steps); - if (steps == 0) + if (!isLure) { - ScriptContext_SetupScript(EventScript_RepelWoreOff); - return TRUE; + VarSet(VAR_REPEL_LURE_STEP_COUNT, steps); + if (steps == 0) + { + ScriptContext_SetupScript(EventScript_RepelWoreOff); + return TRUE; + } } + else + { + VarSet(VAR_REPEL_LURE_STEP_COUNT, steps | REPEL_LURE_MASK); + if (steps == 0) + { + ScriptContext_SetupScript(EventScript_LureWoreOff); + return TRUE; + } + } + } return FALSE; } @@ -918,7 +968,7 @@ static bool8 IsWildLevelAllowedByRepel(u8 wildLevel) { u8 i; - if (!VarGet(VAR_REPEL_STEP_COUNT)) + if (!VarGet(VAR_REPEL_LURE_STEP_COUNT)) return TRUE; for (i = 0; i < PARTY_SIZE; i++) @@ -1006,7 +1056,7 @@ bool8 TryDoDoubleWildBattle(void) { if (GetSafariZoneFlag() || GetMonsStateToDoubles() != PLAYER_HAS_TWO_USABLE_MONS) return FALSE; -#if B_FLAG_FORCE_DOUBLE_WILD != 0 +#if B_FLAG_FORCE_DOUBLE_WILD != 0 else if (FlagGet(B_FLAG_FORCE_DOUBLE_WILD)) return TRUE; #endif From e3005e5275c04f2a09918577d8f47fdca167b398 Mon Sep 17 00:00:00 2001 From: Eduardo Quezada Date: Sun, 11 Sep 2022 21:33:40 -0300 Subject: [PATCH 4/9] Item config for repel prompt --- data/event_scripts.s | 1 + data/scripts/repel.inc | 12 ++++++------ include/constants/item_config.h | 5 +++++ include/constants/vars.h | 2 +- src/item_use.c | 16 ++++++++++++---- src/wild_encounter.c | 2 +- 6 files changed, 26 insertions(+), 12 deletions(-) diff --git a/data/event_scripts.s b/data/event_scripts.s index 848a831fea..d77b9b9de5 100644 --- a/data/event_scripts.s +++ b/data/event_scripts.s @@ -30,6 +30,7 @@ #include "constants/frontier_util.h" #include "constants/game_stat.h" #include "constants/item.h" +#include "constants/item_config.h" #include "constants/items.h" #include "constants/heal_locations.h" #include "constants/layouts.h" diff --git a/data/scripts/repel.inc b/data/scripts/repel.inc index e5ecbcb41a..c57004a3c2 100644 --- a/data/scripts/repel.inc +++ b/data/scripts/repel.inc @@ -1,5 +1,5 @@ EventScript_RepelWoreOff:: - checkitem VAR_LAST_REPEL_USED, 1 + checkitem I_VAR_LAST_REPEL_LURE_USED, 1 compare VAR_RESULT, TRUE goto_if_eq EventScript_UseAnother lock @@ -16,11 +16,11 @@ EventScript_UseAnother: end EventScript_UsedRepel: - bufferitemname 0, VAR_LAST_REPEL_USED + bufferitemname 0, I_VAR_LAST_REPEL_LURE_USED playse SE_REPEL lock msgbox Text_UsedNewRepelLure, MSGBOX_SIGN - removeitem VAR_LAST_REPEL_USED, 1 + removeitem I_VAR_LAST_REPEL_LURE_USED, 1 waitse callnative HandleUseExpiredRepel release @@ -38,7 +38,7 @@ Text_UsedNewRepelLure:: .string "{STR_VAR_1}.$" EventScript_LureWoreOff:: - checkitem VAR_LAST_REPEL_USED, 1 + checkitem I_VAR_LAST_REPEL_LURE_USED, 1 compare VAR_RESULT, TRUE goto_if_eq EventScript_LureUseAnother lock @@ -55,11 +55,11 @@ EventScript_LureUseAnother: end EventScript_UsedLure: - bufferitemname 0, VAR_LAST_REPEL_USED + bufferitemname 0, I_VAR_LAST_REPEL_LURE_USED playse SE_REPEL lock msgbox Text_UsedNewRepelLure, MSGBOX_SIGN - removeitem VAR_LAST_REPEL_USED, 1 + removeitem I_VAR_LAST_REPEL_LURE_USED, 1 waitse callnative HandleUseExpiredLure release diff --git a/include/constants/item_config.h b/include/constants/item_config.h index 9261241a5f..584970f846 100644 --- a/include/constants/item_config.h +++ b/include/constants/item_config.h @@ -9,4 +9,9 @@ #define I_SITRUS_BERRY_HEAL GEN_LATEST // In Gen4+, Sitrus Berry was changed from healing 30 HP to healing 25% of Max HP. #define I_VITAMIN_EV_CAP GEN_LATEST // In Gen8, the Vitamins no longer have a cap of 100 EV per stat. +// Var settings +// To use the following features, replace the 0s with the var ID you're assigning it to. +// Eg: Replace with VAR_UNUSED_0x40F7 so you can use I_VAR_LAST_REPEL_LURE_USED for that feature. +#define I_VAR_LAST_REPEL_LURE_USED 0 // If this var has been assigned, B2W2's Repel prompt will trigger once it runs out. It also applies to Lures. + #endif // GUARD_CONSTANTS_ITEM_CONFIG_H diff --git a/include/constants/vars.h b/include/constants/vars.h index 5118f0533d..a7a229a61b 100644 --- a/include/constants/vars.h +++ b/include/constants/vars.h @@ -271,7 +271,7 @@ #define VAR_UNUSED_0x40FC 0x40FC // Unused Var #define VAR_UNUSED_0x40FD 0x40FD // Unused Var #define VAR_UNUSED_0x40FE 0x40FE // Unused Var -#define VAR_LAST_REPEL_USED 0x40FF // Unused Var +#define VAR_UNUSED_0x40FF 0x40FF // Unused Var #define VARS_END 0x40FF #define VARS_COUNT (VARS_END - VARS_START + 1) diff --git a/src/item_use.c b/src/item_use.c index 1dddc57386..9957983310 100644 --- a/src/item_use.c +++ b/src/item_use.c @@ -873,7 +873,9 @@ static void Task_UseRepel(u8 taskId) if (!IsSEPlaying()) { VarSet(VAR_REPEL_LURE_STEP_COUNT, ItemId_GetHoldEffectParam(gSpecialVar_ItemId)); - VarSet(VAR_LAST_REPEL_USED, gSpecialVar_ItemId); + #if I_VAR_LAST_REPEL_LURE_USED != 0 + VarSet(I_VAR_LAST_REPEL_LURE_USED, gSpecialVar_ItemId); + #endif RemoveUsedItem(); if (!InBattlePyramid()) DisplayItemMessage(taskId, FONT_NORMAL, gStringVar4, CloseItemMessage); @@ -883,7 +885,9 @@ static void Task_UseRepel(u8 taskId) } void HandleUseExpiredRepel(void) { - VarSet(VAR_REPEL_LURE_STEP_COUNT, ItemId_GetHoldEffectParam(VarGet(VAR_LAST_REPEL_USED))); +#if I_VAR_LAST_REPEL_LURE_USED != 0 + VarSet(VAR_REPEL_LURE_STEP_COUNT, ItemId_GetHoldEffectParam(VarGet(I_VAR_LAST_REPEL_LURE_USED))); +#endif } void ItemUseOutOfBattle_Lure(u8 taskId) @@ -913,7 +917,9 @@ static void Task_UseLure(u8 taskId) if (!IsSEPlaying()) { VarSet(VAR_REPEL_LURE_STEP_COUNT, ItemId_GetHoldEffectParam(gSpecialVar_ItemId) | REPEL_LURE_MASK); - VarSet(VAR_LAST_REPEL_USED, gSpecialVar_ItemId); + #if I_VAR_LAST_REPEL_LURE_USED != 0 + VarSet(I_VAR_LAST_REPEL_LURE_USED, gSpecialVar_ItemId); + #endif RemoveUsedItem(); if (!InBattlePyramid()) DisplayItemMessage(taskId, FONT_NORMAL, gStringVar4, CloseItemMessage); @@ -924,7 +930,9 @@ static void Task_UseLure(u8 taskId) void HandleUseExpiredLure(void) { - VarSet(VAR_REPEL_LURE_STEP_COUNT, ItemId_GetHoldEffectParam(VarGet(VAR_LAST_REPEL_USED)) | REPEL_LURE_MASK); +#if I_VAR_LAST_REPEL_LURE_USED != 0 + VarSet(VAR_REPEL_LURE_STEP_COUNT, ItemId_GetHoldEffectParam(VarGet(I_VAR_LAST_REPEL_LURE_USED)) | REPEL_LURE_MASK); +#endif } static void Task_UsedBlackWhiteFlute(u8 taskId) diff --git a/src/wild_encounter.c b/src/wild_encounter.c index 1ac3487939..2a68f4e4d4 100644 --- a/src/wild_encounter.c +++ b/src/wild_encounter.c @@ -968,7 +968,7 @@ static bool8 IsWildLevelAllowedByRepel(u8 wildLevel) { u8 i; - if (!VarGet(VAR_REPEL_LURE_STEP_COUNT)) + if (!REPEL_STEPS(VarGet(VAR_REPEL_LURE_STEP_COUNT))) return TRUE; for (i = 0; i < PARTY_SIZE; i++) From 0944232059c7289ec3ba70c98a0f150f495613a7 Mon Sep 17 00:00:00 2001 From: Eduardo Quezada Date: Mon, 12 Sep 2022 07:58:38 -0300 Subject: [PATCH 5/9] Added shiny rerolls to Lures + reverted repel var name --- include/constants/item.h | 4 ++-- include/constants/vars.h | 2 +- src/item_use.c | 12 ++++++------ src/pokemon.c | 2 ++ src/wild_encounter.c | 16 ++++++++-------- 5 files changed, 19 insertions(+), 17 deletions(-) diff --git a/include/constants/item.h b/include/constants/item.h index 9b574417a7..a32f4545af 100644 --- a/include/constants/item.h +++ b/include/constants/item.h @@ -19,7 +19,7 @@ #define REPEL_LURE_MASK (1 << 15) #define IS_LAST_USED_LURE(var) (var & REPEL_LURE_MASK) #define REPEL_LURE_STEPS(var) (var & (REPEL_LURE_MASK - 1)) -#define LURE_STEPS(var) (IS_LAST_USED_LURE(var) ? REPEL_LURE_STEPS(var) : 0) -#define REPEL_STEPS(var) (!IS_LAST_USED_LURE(var) ? REPEL_LURE_STEPS(var) : 0) +#define LURE_STEP_COUNT (IS_LAST_USED_LURE(VarGet(VAR_REPEL_STEP_COUNT)) ? REPEL_LURE_STEPS(VarGet(VAR_REPEL_STEP_COUNT)) : 0) +#define REPEL_STEP_COUNT (!IS_LAST_USED_LURE(VarGet(VAR_REPEL_STEP_COUNT)) ? REPEL_LURE_STEPS(VarGet(VAR_REPEL_STEP_COUNT)) : 0) #endif // GUARD_ITEM_CONSTANTS_H diff --git a/include/constants/vars.h b/include/constants/vars.h index a7a229a61b..8128b6f321 100644 --- a/include/constants/vars.h +++ b/include/constants/vars.h @@ -47,7 +47,7 @@ // general purpose vars #define VAR_RECYCLE_GOODS 0x4020 -#define VAR_REPEL_LURE_STEP_COUNT 0x4021 +#define VAR_REPEL_STEP_COUNT 0x4021 #define VAR_ICE_STEP_COUNT 0x4022 #define VAR_STARTER_MON 0x4023 // 0=Treecko, 1=Torchic, 2=Mudkip #define VAR_MIRAGE_RND_H 0x4024 diff --git a/src/item_use.c b/src/item_use.c index 9957983310..e3d65d5a3b 100644 --- a/src/item_use.c +++ b/src/item_use.c @@ -848,7 +848,7 @@ static void RemoveUsedItem(void) void ItemUseOutOfBattle_Repel(u8 taskId) { - if (REPEL_STEPS(VarGet(VAR_REPEL_LURE_STEP_COUNT)) == 0) + if (REPEL_STEP_COUNT == 0) gTasks[taskId].func = Task_StartUseRepel; else if (!InBattlePyramid()) DisplayItemMessage(taskId, FONT_NORMAL, gText_RepelEffectsLingered, CloseItemMessage); @@ -872,7 +872,7 @@ static void Task_UseRepel(u8 taskId) { if (!IsSEPlaying()) { - VarSet(VAR_REPEL_LURE_STEP_COUNT, ItemId_GetHoldEffectParam(gSpecialVar_ItemId)); + VarSet(VAR_REPEL_STEP_COUNT, ItemId_GetHoldEffectParam(gSpecialVar_ItemId)); #if I_VAR_LAST_REPEL_LURE_USED != 0 VarSet(I_VAR_LAST_REPEL_LURE_USED, gSpecialVar_ItemId); #endif @@ -886,13 +886,13 @@ static void Task_UseRepel(u8 taskId) void HandleUseExpiredRepel(void) { #if I_VAR_LAST_REPEL_LURE_USED != 0 - VarSet(VAR_REPEL_LURE_STEP_COUNT, ItemId_GetHoldEffectParam(VarGet(I_VAR_LAST_REPEL_LURE_USED))); + VarSet(VAR_REPEL_STEP_COUNT, ItemId_GetHoldEffectParam(VarGet(I_VAR_LAST_REPEL_LURE_USED))); #endif } void ItemUseOutOfBattle_Lure(u8 taskId) { - if (LURE_STEPS(VarGet(VAR_REPEL_LURE_STEP_COUNT)) == 0) + if (LURE_STEP_COUNT == 0) gTasks[taskId].func = Task_StartUseLure; else if (!InBattlePyramid()) DisplayItemMessage(taskId, FONT_NORMAL, gText_LureEffectsLingered, CloseItemMessage); @@ -916,7 +916,7 @@ static void Task_UseLure(u8 taskId) { if (!IsSEPlaying()) { - VarSet(VAR_REPEL_LURE_STEP_COUNT, ItemId_GetHoldEffectParam(gSpecialVar_ItemId) | REPEL_LURE_MASK); + VarSet(VAR_REPEL_STEP_COUNT, ItemId_GetHoldEffectParam(gSpecialVar_ItemId) | REPEL_LURE_MASK); #if I_VAR_LAST_REPEL_LURE_USED != 0 VarSet(I_VAR_LAST_REPEL_LURE_USED, gSpecialVar_ItemId); #endif @@ -931,7 +931,7 @@ static void Task_UseLure(u8 taskId) void HandleUseExpiredLure(void) { #if I_VAR_LAST_REPEL_LURE_USED != 0 - VarSet(VAR_REPEL_LURE_STEP_COUNT, ItemId_GetHoldEffectParam(VarGet(I_VAR_LAST_REPEL_LURE_USED)) | REPEL_LURE_MASK); + VarSet(VAR_REPEL_STEP_COUNT, ItemId_GetHoldEffectParam(VarGet(I_VAR_LAST_REPEL_LURE_USED)) | REPEL_LURE_MASK); #endif } diff --git a/src/pokemon.c b/src/pokemon.c index 19498810a3..2e6cee221a 100644 --- a/src/pokemon.c +++ b/src/pokemon.c @@ -3308,6 +3308,8 @@ void CreateBoxMon(struct BoxPokemon *boxMon, u16 species, u8 level, u8 fixedIV, if (CheckBagHasItem(ITEM_SHINY_CHARM, 1)) totalRerolls += I_SHINY_CHARM_REROLLS; + if (LURE_STEP_COUNT != 0) + totalRerolls += 1; while (GET_SHINY_VALUE(value, personality) >= SHINY_ODDS && totalRerolls > 0) { diff --git a/src/wild_encounter.c b/src/wild_encounter.c index 2a68f4e4d4..bbf444d3ab 100644 --- a/src/wild_encounter.c +++ b/src/wild_encounter.c @@ -212,7 +212,7 @@ static u8 ChooseWildMonIndex_Land(void) else wildMonIndex = 11; - if (LURE_STEPS(VarGet(VAR_REPEL_LURE_STEP_COUNT)) && (Random() % 10 < 2)) + if (LURE_STEP_COUNT != 0 && (Random() % 10 < 2)) swap = TRUE; if (swap) @@ -239,7 +239,7 @@ static u8 ChooseWildMonIndex_WaterRock(void) else wildMonIndex = 4; - if (LURE_STEPS(VarGet(VAR_REPEL_LURE_STEP_COUNT)) && (Random() % 10 < 2)) + if (LURE_STEP_COUNT != 0 && (Random() % 10 < 2)) swap = TRUE; if (swap) @@ -256,7 +256,7 @@ static u8 ChooseWildMonIndex_Fishing(u8 rod) u8 rand = Random() % max(max(ENCOUNTER_CHANCE_FISHING_MONS_OLD_ROD_TOTAL, ENCOUNTER_CHANCE_FISHING_MONS_GOOD_ROD_TOTAL), ENCOUNTER_CHANCE_FISHING_MONS_SUPER_ROD_TOTAL); - if (LURE_STEPS(VarGet(VAR_REPEL_LURE_STEP_COUNT)) && (Random() % 10 < 2)) + if (LURE_STEP_COUNT != 0 && (Random() % 10 < 2)) swap = TRUE; switch (rod) @@ -556,7 +556,7 @@ static bool8 DoWildEncounterRateTest(u32 encounterRate, bool8 ignoreAbility) encounterRate = encounterRate * 80 / 100; ApplyFluteEncounterRateMod(&encounterRate); ApplyCleanseTagEncounterRateMod(&encounterRate); - if (LURE_STEPS(VarGet(VAR_REPEL_LURE_STEP_COUNT)) != 0) + if (LURE_STEP_COUNT != 0) encounterRate *= 2; if (!ignoreAbility && !GetMonData(&gPlayerParty[0], MON_DATA_SANITY_IS_EGG)) { @@ -929,7 +929,7 @@ u16 GetLocalWaterMon(void) bool8 UpdateRepelCounter(void) { - u16 repelLureVar = VarGet(VAR_REPEL_LURE_STEP_COUNT); + u16 repelLureVar = VarGet(VAR_REPEL_STEP_COUNT); u16 steps = REPEL_LURE_STEPS(repelLureVar); bool32 isLure = IS_LAST_USED_LURE(repelLureVar); @@ -943,7 +943,7 @@ bool8 UpdateRepelCounter(void) steps--; if (!isLure) { - VarSet(VAR_REPEL_LURE_STEP_COUNT, steps); + VarSet(VAR_REPEL_STEP_COUNT, steps); if (steps == 0) { ScriptContext_SetupScript(EventScript_RepelWoreOff); @@ -952,7 +952,7 @@ bool8 UpdateRepelCounter(void) } else { - VarSet(VAR_REPEL_LURE_STEP_COUNT, steps | REPEL_LURE_MASK); + VarSet(VAR_REPEL_STEP_COUNT, steps | REPEL_LURE_MASK); if (steps == 0) { ScriptContext_SetupScript(EventScript_LureWoreOff); @@ -968,7 +968,7 @@ static bool8 IsWildLevelAllowedByRepel(u8 wildLevel) { u8 i; - if (!REPEL_STEPS(VarGet(VAR_REPEL_LURE_STEP_COUNT))) + if (!REPEL_STEP_COUNT) return TRUE; for (i = 0; i < PARTY_SIZE; i++) From ca048e1bc33717cc7ca332a012cfc67c78b10061 Mon Sep 17 00:00:00 2001 From: Eduardo Quezada Date: Mon, 12 Sep 2022 10:18:09 -0300 Subject: [PATCH 6/9] Lures now increase the level of encountered mon to max + 1 --- src/wild_encounter.c | 95 +++++++++++++++++++++++++++++++------------- 1 file changed, 68 insertions(+), 27 deletions(-) diff --git a/src/wild_encounter.c b/src/wild_encounter.c index bbf444d3ab..4a49efcbd8 100644 --- a/src/wild_encounter.c +++ b/src/wild_encounter.c @@ -56,6 +56,7 @@ static void FeebasSeedRng(u16 seed); static bool8 IsWildLevelAllowedByRepel(u8 level); static void ApplyFluteEncounterRateMod(u32 *encRate); static void ApplyCleanseTagEncounterRateMod(u32 *encRate); +static u8 GetMaxLevelOfSpeciesInWildTable(const struct WildPokemon *wildMon, u16 species, u8 area); static bool8 TryGetAbilityInfluencedWildMonIndex(const struct WildPokemon *wildMon, u8 type, u16 ability, u8 *monIndex); static bool8 IsAbilityAllowingEncounter(u8 level); @@ -300,41 +301,53 @@ static u8 ChooseWildMonIndex_Fishing(u8 rod) return wildMonIndex; } -static u8 ChooseWildMonLevel(const struct WildPokemon *wildPokemon) +static u8 ChooseWildMonLevel(const struct WildPokemon *wildPokemon, u8 wildMonIndex, u8 area) { u8 min; u8 max; u8 range; u8 rand; - // Make sure minimum level is less than maximum level - if (wildPokemon->maxLevel >= wildPokemon->minLevel) + if (LURE_STEP_COUNT == 0) { - min = wildPokemon->minLevel; - max = wildPokemon->maxLevel; + // Make sure minimum level is less than maximum level + if (wildPokemon[wildMonIndex].maxLevel >= wildPokemon[wildMonIndex].minLevel) + { + min = wildPokemon[wildMonIndex].minLevel; + max = wildPokemon[wildMonIndex].maxLevel; + } + else + { + min = wildPokemon[wildMonIndex].maxLevel; + max = wildPokemon[wildMonIndex].minLevel; + } + range = max - min + 1; + rand = Random() % range; + + // check ability for max level mon + if (!GetMonData(&gPlayerParty[0], MON_DATA_SANITY_IS_EGG)) + { + u16 ability = GetMonAbility(&gPlayerParty[0]); + if (ability == ABILITY_HUSTLE || ability == ABILITY_VITAL_SPIRIT || ability == ABILITY_PRESSURE) + { + if (Random() % 2 == 0) + return max; + + if (rand != 0) + rand--; + } + } + return min + rand; } else { - min = wildPokemon->maxLevel; - max = wildPokemon->minLevel; + // Looks for the max level of all slots that share the same species as the selected slot. + max = GetMaxLevelOfSpeciesInWildTable(wildPokemon, wildPokemon[wildMonIndex].species, area); + if (max > 0) + return max + 1; + else // Failsafe + return wildPokemon[wildMonIndex].maxLevel + 1; } - range = max - min + 1; - rand = Random() % range; - - // check ability for max level mon - if (!GetMonData(&gPlayerParty[0], MON_DATA_SANITY_IS_EGG)) - { - u16 ability = GetMonAbility(&gPlayerParty[0]); - if (ability == ABILITY_HUSTLE || ability == ABILITY_VITAL_SPIRIT || ability == ABILITY_PRESSURE) - { - if (Random() % 2 == 0) - return max; - - if (rand != 0) - rand--; - } - } - return min + rand; } static u16 GetCurrentMapWildMonHeaderId(void) @@ -496,7 +509,7 @@ static bool8 TryGenerateWildMon(const struct WildPokemonInfo *wildMonInfo, u8 ar break; } - level = ChooseWildMonLevel(&wildMonInfo->wildPokemon[wildMonIndex]); + level = ChooseWildMonLevel(wildMonInfo->wildPokemon, wildMonIndex, area); if (flags & WILD_CHECK_REPEL && !IsWildLevelAllowedByRepel(level)) return FALSE; if (gMapHeader.mapLayoutId != LAYOUT_BATTLE_FRONTIER_BATTLE_PIKE_ROOM_WILD_MONS && flags & WILD_CHECK_KEEN_EYE && !IsAbilityAllowingEncounter(level)) @@ -509,7 +522,7 @@ static bool8 TryGenerateWildMon(const struct WildPokemonInfo *wildMonInfo, u8 ar static u16 GenerateFishingWildMon(const struct WildPokemonInfo *wildMonInfo, u8 rod) { u8 wildMonIndex = ChooseWildMonIndex_Fishing(rod); - u8 level = ChooseWildMonLevel(&wildMonInfo->wildPokemon[wildMonIndex]); + u8 level = ChooseWildMonLevel(wildMonInfo->wildPokemon, wildMonIndex, WILD_AREA_FISHING); CreateWildMon(wildMonInfo->wildPokemon[wildMonIndex].species, level); return wildMonInfo->wildPokemon[wildMonIndex].species; @@ -862,7 +875,7 @@ void FishingWildEncounter(u8 rod) if (CheckFeebas() == TRUE) { - u8 level = ChooseWildMonLevel(&sWildFeebas); + u8 level = ChooseWildMonLevel(&sWildFeebas, 0, WILD_AREA_FISHING); species = sWildFeebas.species; CreateWildMon(species, level); @@ -1026,6 +1039,34 @@ static bool8 TryGetRandomWildMonIndexByType(const struct WildPokemon *wildMon, u return TRUE; } +#include "data.h" + +static u8 GetMaxLevelOfSpeciesInWildTable(const struct WildPokemon *wildMon, u16 species, u8 area) +{ + u8 i, maxLevel = 0, numMon = 0; + + switch (area) + { + case WILD_AREA_LAND: + numMon = LAND_WILD_COUNT; + break; + case WILD_AREA_WATER: + numMon = WATER_WILD_COUNT; + break; + case WILD_AREA_ROCKS: + numMon = ROCK_WILD_COUNT; + break; + } + + for (i = 0; i < numMon; i++) + { + if (wildMon[i].species == species && wildMon[i].maxLevel > maxLevel) + maxLevel = wildMon[i].maxLevel; + } + + return maxLevel; +} + static bool8 TryGetAbilityInfluencedWildMonIndex(const struct WildPokemon *wildMon, u8 type, u16 ability, u8 *monIndex) { if (GetMonData(&gPlayerParty[0], MON_DATA_SANITY_IS_EGG)) From dc423ef7ff1ea54036e3655993af04e1e7487dd0 Mon Sep 17 00:00:00 2001 From: Eduardo Quezada Date: Wed, 14 Sep 2022 00:17:04 -0300 Subject: [PATCH 7/9] Handling repel/lure menu --- data/scripts/repel.inc | 96 +++++++++++++++++++++++---------- include/constants/item_config.h | 8 +-- src/item_use.c | 16 +++--- src/script_menu.c | 82 ++++++++++++++++++++++++++-- 4 files changed, 160 insertions(+), 42 deletions(-) diff --git a/data/scripts/repel.inc b/data/scripts/repel.inc index c57004a3c2..fc32df1d9c 100644 --- a/data/scripts/repel.inc +++ b/data/scripts/repel.inc @@ -1,46 +1,64 @@ EventScript_RepelWoreOff:: - checkitem I_VAR_LAST_REPEL_LURE_USED, 1 - compare VAR_RESULT, TRUE - goto_if_eq EventScript_UseAnother +.if I_REPEL_LURE_MENU == TRUE + checkitem ITEM_REPEL, 1 + goto_if_eq VAR_RESULT, TRUE, EventScript_RepelUseAnother + checkitem ITEM_SUPER_REPEL, 1 + goto_if_eq VAR_RESULT, TRUE, EventScript_RepelUseAnother + checkitem ITEM_MAX_REPEL, 1 + goto_if_eq VAR_RESULT, TRUE, EventScript_RepelUseAnother +.else + checkitem VAR_LAST_REPEL_LURE_USED, 1 + goto_if_eq VAR_RESULT, TRUE, EventScript_RepelUseAnother +.endif lock msgbox Text_RepelWoreOff, MSGBOX_SIGN release end -EventScript_UseAnother: +EventScript_RepelUseAnother: lock - msgbox Text_UseAnother, MSGBOX_YESNO - compare VAR_RESULT, YES - goto_if_eq EventScript_UsedRepel + msgbox Text_UseAnotherRepel, MSGBOX_YESNO +.if I_REPEL_LURE_MENU == TRUE + callnative TryDrawRepelMenu + goto_if_eq VAR_RESULT, FALSE, EventScript_RepelWoreOff_Chose + waitstate + goto_if_eq VAR_RESULT, 127, EventScript_RepelWoreOff_End +EventScript_RepelWoreOff_Chose: + callnative HandleRepelMenuChoice + bufferitemname 1, VAR_0x8004 + removeitem VAR_0x8004, 1 + playse SE_REPEL + msgbox Text_UsedNewRepelLure, MSGBOX_SIGN +.else + goto_if_eq VAR_RESULT, YES, EventScript_UsedRepel +.endif +EventScript_RepelWoreOff_End: release end EventScript_UsedRepel: - bufferitemname 0, I_VAR_LAST_REPEL_LURE_USED + bufferitemname 1, VAR_LAST_REPEL_LURE_USED playse SE_REPEL lock msgbox Text_UsedNewRepelLure, MSGBOX_SIGN - removeitem I_VAR_LAST_REPEL_LURE_USED, 1 + removeitem VAR_LAST_REPEL_LURE_USED, 1 waitse callnative HandleUseExpiredRepel release end -Text_RepelWoreOff: - .string "REPEL's effect wore off…$" - -Text_UseAnother:: - .string "REPEL's effect wore off!\n" - .string "Use another?$" - -Text_UsedNewRepelLure:: - .string "{PLAYER} used the\n" - .string "{STR_VAR_1}.$" - EventScript_LureWoreOff:: - checkitem I_VAR_LAST_REPEL_LURE_USED, 1 - compare VAR_RESULT, TRUE - goto_if_eq EventScript_LureUseAnother +.if I_REPEL_LURE_MENU == TRUE + checkitem ITEM_LURE, 1 + goto_if_eq VAR_RESULT, TRUE, EventScript_LureUseAnother + checkitem ITEM_SUPER_LURE, 1 + goto_if_eq VAR_RESULT, TRUE, EventScript_LureUseAnother + checkitem ITEM_MAX_LURE, 1 + goto_if_eq VAR_RESULT, TRUE, EventScript_LureUseAnother +.else + checkitem VAR_LAST_REPEL_LURE_USED, 1 + goto_if_eq VAR_RESULT, TRUE, EventScript_LureUseAnother +.endif lock msgbox Text_LureWoreOff, MSGBOX_SIGN release @@ -49,25 +67,49 @@ EventScript_LureWoreOff:: EventScript_LureUseAnother: lock msgbox Text_UseAnotherLure, MSGBOX_YESNO - compare VAR_RESULT, YES - goto_if_eq EventScript_UsedLure +.if I_REPEL_LURE_MENU == TRUE + callnative TryDrawLureMenu + goto_if_eq VAR_RESULT, FALSE, EventScript_LureWoreOff_Chose + waitstate + goto_if_eq VAR_RESULT, 127, EventScript_LureWoreOff_End +EventScript_LureWoreOff_Chose: + callnative HandleLureMenuChoice + bufferitemname 1, VAR_0x8004 + removeitem VAR_0x8004, 1 + playse SE_REPEL + msgbox Text_UsedNewRepelLure, MSGBOX_SIGN +.else + goto_if_eq VAR_RESULT, YES, EventScript_UsedLure +.endif +EventScript_LureWoreOff_End: release end EventScript_UsedLure: - bufferitemname 0, I_VAR_LAST_REPEL_LURE_USED + bufferitemname 1, VAR_LAST_REPEL_LURE_USED playse SE_REPEL lock msgbox Text_UsedNewRepelLure, MSGBOX_SIGN - removeitem I_VAR_LAST_REPEL_LURE_USED, 1 + removeitem VAR_LAST_REPEL_LURE_USED, 1 waitse callnative HandleUseExpiredLure release end +Text_RepelWoreOff: + .string "REPEL's effect wore off…$" + +Text_UseAnotherRepel:: + .string "REPEL's effect wore off!\n" + .string "Use another?$" + Text_LureWoreOff: .string "Lure's effect wore off…$" Text_UseAnotherLure:: .string "Lure's effect wore off!\n" .string "Use another?$" + +Text_UsedNewRepelLure:: + .string "{PLAYER} used the\n" + .string "{STR_VAR_2}.$" diff --git a/include/constants/item_config.h b/include/constants/item_config.h index 584970f846..e645b301da 100644 --- a/include/constants/item_config.h +++ b/include/constants/item_config.h @@ -9,9 +9,9 @@ #define I_SITRUS_BERRY_HEAL GEN_LATEST // In Gen4+, Sitrus Berry was changed from healing 30 HP to healing 25% of Max HP. #define I_VITAMIN_EV_CAP GEN_LATEST // In Gen8, the Vitamins no longer have a cap of 100 EV per stat. -// Var settings -// To use the following features, replace the 0s with the var ID you're assigning it to. -// Eg: Replace with VAR_UNUSED_0x40F7 so you can use I_VAR_LAST_REPEL_LURE_USED for that feature. -#define I_VAR_LAST_REPEL_LURE_USED 0 // If this var has been assigned, B2W2's Repel prompt will trigger once it runs out. It also applies to Lures. +// Repel/Lure config +// These two settings are both independent and complementary. +#define VAR_LAST_REPEL_LURE_USED 0 // If this var has been assigned, last Repel/Lure used will be saved and the player will get prompted with the vanilla repel YES/NO option, unless I_REPEL_LURE_MENU is set to TRUE. +#define I_REPEL_LURE_MENU TRUE // If TRUE, the player is able to choose which Repel/Lure to use once the previous one runs out. Cursor position is saved by VAR_LAST_REPEL_LURE_USED if not 0. #endif // GUARD_CONSTANTS_ITEM_CONFIG_H diff --git a/src/item_use.c b/src/item_use.c index e3d65d5a3b..e91da96bee 100644 --- a/src/item_use.c +++ b/src/item_use.c @@ -873,8 +873,8 @@ static void Task_UseRepel(u8 taskId) if (!IsSEPlaying()) { VarSet(VAR_REPEL_STEP_COUNT, ItemId_GetHoldEffectParam(gSpecialVar_ItemId)); - #if I_VAR_LAST_REPEL_LURE_USED != 0 - VarSet(I_VAR_LAST_REPEL_LURE_USED, gSpecialVar_ItemId); + #if VAR_LAST_REPEL_LURE_USED != 0 + VarSet(VAR_LAST_REPEL_LURE_USED, gSpecialVar_ItemId); #endif RemoveUsedItem(); if (!InBattlePyramid()) @@ -885,8 +885,8 @@ static void Task_UseRepel(u8 taskId) } void HandleUseExpiredRepel(void) { -#if I_VAR_LAST_REPEL_LURE_USED != 0 - VarSet(VAR_REPEL_STEP_COUNT, ItemId_GetHoldEffectParam(VarGet(I_VAR_LAST_REPEL_LURE_USED))); +#if VAR_LAST_REPEL_LURE_USED != 0 + VarSet(VAR_REPEL_STEP_COUNT, ItemId_GetHoldEffectParam(VarGet(VAR_LAST_REPEL_LURE_USED))); #endif } @@ -917,8 +917,8 @@ static void Task_UseLure(u8 taskId) if (!IsSEPlaying()) { VarSet(VAR_REPEL_STEP_COUNT, ItemId_GetHoldEffectParam(gSpecialVar_ItemId) | REPEL_LURE_MASK); - #if I_VAR_LAST_REPEL_LURE_USED != 0 - VarSet(I_VAR_LAST_REPEL_LURE_USED, gSpecialVar_ItemId); + #if VAR_LAST_REPEL_LURE_USED != 0 + VarSet(VAR_LAST_REPEL_LURE_USED, gSpecialVar_ItemId); #endif RemoveUsedItem(); if (!InBattlePyramid()) @@ -930,8 +930,8 @@ static void Task_UseLure(u8 taskId) void HandleUseExpiredLure(void) { -#if I_VAR_LAST_REPEL_LURE_USED != 0 - VarSet(VAR_REPEL_STEP_COUNT, ItemId_GetHoldEffectParam(VarGet(I_VAR_LAST_REPEL_LURE_USED)) | REPEL_LURE_MASK); +#if VAR_LAST_REPEL_LURE_USED != 0 + VarSet(VAR_REPEL_STEP_COUNT, ItemId_GetHoldEffectParam(VarGet(VAR_LAST_REPEL_LURE_USED)) | REPEL_LURE_MASK); #endif } diff --git a/src/script_menu.c b/src/script_menu.c index d25f28cb29..d411f4a1cf 100644 --- a/src/script_menu.c +++ b/src/script_menu.c @@ -90,12 +90,10 @@ static u16 GetLengthWithExpandedPlayerName(const u8 *str) return length; } -static void DrawMultichoiceMenu(u8 left, u8 top, u8 multichoiceId, bool8 ignoreBPress, u8 cursorPos) +static void DrawMultichoiceMenuInternal(u8 left, u8 top, u8 multichoiceId, bool8 ignoreBPress, u8 cursorPos, const struct MenuAction *actions, int count) { int i; u8 windowId; - u8 count = sMultichoiceLists[multichoiceId].count; - const struct MenuAction *actions = sMultichoiceLists[multichoiceId].list; int width = 0; u8 newWidth; @@ -114,6 +112,84 @@ static void DrawMultichoiceMenu(u8 left, u8 top, u8 multichoiceId, bool8 ignoreB InitMultichoiceCheckWrap(ignoreBPress, count, windowId, multichoiceId); } +static void DrawMultichoiceMenu(u8 left, u8 top, u8 multichoiceId, bool8 ignoreBPress, u8 cursorPos) +{ + DrawMultichoiceMenuInternal(left, top, multichoiceId, ignoreBPress, cursorPos, sMultichoiceLists[multichoiceId].list, sMultichoiceLists[multichoiceId].count); +} + +#if I_REPEL_LURE_MENU == TRUE +void TryDrawRepelMenu(void) +{ + static const u16 repelItems[] = {ITEM_REPEL, ITEM_SUPER_REPEL, ITEM_MAX_REPEL}; + struct MenuAction menuItems[ARRAY_COUNT(repelItems) + 1] = {NULL}; + int i, count = 0, menuPos = 0; + + for (i = 0; i < ARRAY_COUNT(repelItems); i++) + { + if (CheckBagHasItem(repelItems[i], 1)) + { + VarSet(VAR_0x8004 + count, repelItems[i]); + #if VAR_LAST_REPEL_LURE_USED != 0 + if (VarGet(VAR_LAST_REPEL_LURE_USED) == repelItems[i]) + menuPos = count; + #endif + menuItems[count].text = ItemId_GetName(repelItems[i]); + count++; + } + } + + if (count > 1) + DrawMultichoiceMenuInternal(0, 0, 0, FALSE, menuPos, menuItems, count); + + gSpecialVar_Result = (count > 1); +} + +void HandleRepelMenuChoice(void) +{ + gSpecialVar_0x8004 = VarGet(VAR_0x8004 + gSpecialVar_Result); // Get item Id; + VarSet(VAR_REPEL_STEP_COUNT, ItemId_GetHoldEffectParam(gSpecialVar_0x8004)); +#if VAR_LAST_REPEL_LURE_USED != 0 + VarSet(VAR_LAST_REPEL_LURE_USED, gSpecialVar_0x8004); +#endif +} + +void TryDrawLureMenu(void) +{ + static const u16 lureItems[] = {ITEM_LURE, ITEM_SUPER_LURE, ITEM_MAX_LURE}; + struct MenuAction menuItems[ARRAY_COUNT(lureItems) + 1] = {NULL}; + int i, count = 0, menuPos = 0; + + + for (i = 0; i < ARRAY_COUNT(lureItems); i++) + { + if (CheckBagHasItem(lureItems[i], 1)) + { + VarSet(VAR_0x8004 + count, lureItems[i]); + #if VAR_LAST_REPEL_LURE_USED != 0 + if (VarGet(VAR_LAST_REPEL_LURE_USED) == lureItems[i]) + menuPos = count; + #endif + menuItems[count].text = ItemId_GetName(lureItems[i]); + count++; + } + } + + if (count > 1) + DrawMultichoiceMenuInternal(0, 0, 0, FALSE, menuPos, menuItems, count); + + gSpecialVar_Result = (count > 1); +} + +void HandleLureMenuChoice(void) +{ + gSpecialVar_0x8004 = VarGet(VAR_0x8004 + gSpecialVar_Result); // Get item Id; + VarSet(VAR_REPEL_STEP_COUNT, ItemId_GetHoldEffectParam(gSpecialVar_0x8004) | REPEL_LURE_MASK); +#if VAR_LAST_REPEL_LURE_USED != 0 + VarSet(VAR_LAST_REPEL_LURE_USED, gSpecialVar_0x8004); +#endif +} +#endif //I_REPEL_LURE_MENU == TRUE + #define tLeft data[0] #define tTop data[1] #define tRight data[2] From b0bd5f98798fc6f009605cdfe607c47efcda4237 Mon Sep 17 00:00:00 2001 From: Eduardo Quezada Date: Fri, 16 Sep 2022 14:42:11 -0300 Subject: [PATCH 8/9] Cleaned up trailing spaces and spaces instead of tabs --- src/wild_encounter.c | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/src/wild_encounter.c b/src/wild_encounter.c index 4a49efcbd8..a87b04252e 100644 --- a/src/wild_encounter.c +++ b/src/wild_encounter.c @@ -71,7 +71,7 @@ static const struct WildPokemon sWildFeebas = {20, 25, SPECIES_FEEBAS}; static const u16 sRoute119WaterTileData[] = { -//yMin, yMax, numSpots in previous sections +//yMin, yMax, numSpots in previous sections 0, 45, 0, 46, 91, NUM_FISHING_SPOTS_1, 92, 139, NUM_FISHING_SPOTS_1 + NUM_FISHING_SPOTS_2, @@ -149,7 +149,7 @@ static bool8 CheckFeebas(void) feebasSpots[i] = FeebasRandom() % NUM_FISHING_SPOTS; if (feebasSpots[i] == 0) feebasSpots[i] = NUM_FISHING_SPOTS; - + // < 1 below is a pointless check, it will never be TRUE. // >= 4 to skip fishing spots 1-3, because these are inaccessible // spots at the top of the map, at (9,7), (7,13), and (15,16). @@ -184,8 +184,8 @@ static void FeebasSeedRng(u16 seed) // LAND_WILD_COUNT static u8 ChooseWildMonIndex_Land(void) { - u8 wildMonIndex = 0; - bool8 swap = FALSE; + u8 wildMonIndex = 0; + bool8 swap = FALSE; u8 rand = Random() % ENCOUNTER_CHANCE_LAND_MONS_TOTAL; if (rand < ENCOUNTER_CHANCE_LAND_MONS_SLOT_0) @@ -216,17 +216,17 @@ static u8 ChooseWildMonIndex_Land(void) if (LURE_STEP_COUNT != 0 && (Random() % 10 < 2)) swap = TRUE; - if (swap) - wildMonIndex = 11 - wildMonIndex; + if (swap) + wildMonIndex = 11 - wildMonIndex; - return wildMonIndex; + return wildMonIndex; } // ROCK_WILD_COUNT / WATER_WILD_COUNT static u8 ChooseWildMonIndex_WaterRock(void) { - u8 wildMonIndex = 0; - bool8 swap = FALSE; + u8 wildMonIndex = 0; + bool8 swap = FALSE; u8 rand = Random() % ENCOUNTER_CHANCE_WATER_MONS_TOTAL; if (rand < ENCOUNTER_CHANCE_WATER_MONS_SLOT_0) @@ -243,17 +243,17 @@ static u8 ChooseWildMonIndex_WaterRock(void) if (LURE_STEP_COUNT != 0 && (Random() % 10 < 2)) swap = TRUE; - if (swap) - wildMonIndex = 4 - wildMonIndex; + if (swap) + wildMonIndex = 4 - wildMonIndex; - return wildMonIndex; + return wildMonIndex; } // FISH_WILD_COUNT static u8 ChooseWildMonIndex_Fishing(u8 rod) { u8 wildMonIndex = 0; - bool8 swap = FALSE; + bool8 swap = FALSE; u8 rand = Random() % max(max(ENCOUNTER_CHANCE_FISHING_MONS_OLD_ROD_TOTAL, ENCOUNTER_CHANCE_FISHING_MONS_GOOD_ROD_TOTAL), ENCOUNTER_CHANCE_FISHING_MONS_SUPER_ROD_TOTAL); @@ -269,8 +269,8 @@ static u8 ChooseWildMonIndex_Fishing(u8 rod) wildMonIndex = 1; break; - if (swap) - wildMonIndex = 1 - wildMonIndex; + if (swap) + wildMonIndex = 1 - wildMonIndex; case GOOD_ROD: if (rand < ENCOUNTER_CHANCE_FISHING_MONS_GOOD_ROD_SLOT_2) wildMonIndex = 2; @@ -279,8 +279,8 @@ static u8 ChooseWildMonIndex_Fishing(u8 rod) if (rand >= ENCOUNTER_CHANCE_FISHING_MONS_GOOD_ROD_SLOT_3 && rand < ENCOUNTER_CHANCE_FISHING_MONS_GOOD_ROD_SLOT_4) wildMonIndex = 4; - if (swap) - wildMonIndex = 6 - wildMonIndex; + if (swap) + wildMonIndex = 6 - wildMonIndex; break; case SUPER_ROD: if (rand < ENCOUNTER_CHANCE_FISHING_MONS_SUPER_ROD_SLOT_5) @@ -294,8 +294,8 @@ static u8 ChooseWildMonIndex_Fishing(u8 rod) if (rand >= ENCOUNTER_CHANCE_FISHING_MONS_SUPER_ROD_SLOT_8 && rand < ENCOUNTER_CHANCE_FISHING_MONS_SUPER_ROD_SLOT_9) wildMonIndex = 9; - if (swap) - wildMonIndex = 14 - wildMonIndex; + if (swap) + wildMonIndex = 14 - wildMonIndex; break; } return wildMonIndex; From b2b308fe9ec6129439c302b9ca779ebdce174eeb Mon Sep 17 00:00:00 2001 From: Eduardo Quezada Date: Fri, 16 Sep 2022 15:16:51 -0300 Subject: [PATCH 9/9] Fixed Old Rod Lure swap --- src/wild_encounter.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/wild_encounter.c b/src/wild_encounter.c index a87b04252e..69f60182f6 100644 --- a/src/wild_encounter.c +++ b/src/wild_encounter.c @@ -267,10 +267,10 @@ static u8 ChooseWildMonIndex_Fishing(u8 rod) wildMonIndex = 0; else wildMonIndex = 1; - break; if (swap) wildMonIndex = 1 - wildMonIndex; + break; case GOOD_ROD: if (rand < ENCOUNTER_CHANCE_FISHING_MONS_GOOD_ROD_SLOT_2) wildMonIndex = 2;