mirror of
https://github.com/Ninjdai1/pokeemerald.git
synced 2025-01-13 15:13:42 +01:00
Merge pull request #2319 from AsparagusEduardo/RHH/pr/Lures
Implemented Lures and Repel/Lure "use another" menu
This commit is contained in:
commit
c6cb54b54e
@ -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"
|
||||
|
@ -1,6 +1,115 @@
|
||||
EventScript_RepelWoreOff::
|
||||
.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_RepelUseAnother:
|
||||
lock
|
||||
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 1, VAR_LAST_REPEL_LURE_USED
|
||||
playse SE_REPEL
|
||||
lock
|
||||
msgbox Text_UsedNewRepelLure, MSGBOX_SIGN
|
||||
removeitem VAR_LAST_REPEL_LURE_USED, 1
|
||||
waitse
|
||||
callnative HandleUseExpiredRepel
|
||||
release
|
||||
end
|
||||
|
||||
EventScript_LureWoreOff::
|
||||
.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
|
||||
end
|
||||
|
||||
EventScript_LureUseAnother:
|
||||
lock
|
||||
msgbox Text_UseAnotherLure, MSGBOX_YESNO
|
||||
.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 1, VAR_LAST_REPEL_LURE_USED
|
||||
playse SE_REPEL
|
||||
lock
|
||||
msgbox Text_UsedNewRepelLure, MSGBOX_SIGN
|
||||
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}.$"
|
||||
|
@ -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_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
|
||||
|
@ -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.
|
||||
|
||||
// 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
|
||||
|
@ -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);
|
||||
|
@ -938,6 +938,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[];
|
||||
|
@ -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,
|
||||
},
|
||||
|
@ -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_STEP_COUNT == 0)
|
||||
gTasks[taskId].func = Task_StartUseRepel;
|
||||
else if (!InBattlePyramid())
|
||||
DisplayItemMessage(taskId, FONT_NORMAL, gText_RepelEffectsLingered, CloseItemMessage);
|
||||
@ -871,6 +873,9 @@ static void Task_UseRepel(u8 taskId)
|
||||
if (!IsSEPlaying())
|
||||
{
|
||||
VarSet(VAR_REPEL_STEP_COUNT, ItemId_GetHoldEffectParam(gSpecialVar_ItemId));
|
||||
#if VAR_LAST_REPEL_LURE_USED != 0
|
||||
VarSet(VAR_LAST_REPEL_LURE_USED, gSpecialVar_ItemId);
|
||||
#endif
|
||||
RemoveUsedItem();
|
||||
if (!InBattlePyramid())
|
||||
DisplayItemMessage(taskId, FONT_NORMAL, gStringVar4, CloseItemMessage);
|
||||
@ -878,6 +883,57 @@ static void Task_UseRepel(u8 taskId)
|
||||
DisplayItemMessageInBattlePyramid(taskId, gStringVar4, Task_CloseBattlePyramidBagMessage);
|
||||
}
|
||||
}
|
||||
void HandleUseExpiredRepel(void)
|
||||
{
|
||||
#if VAR_LAST_REPEL_LURE_USED != 0
|
||||
VarSet(VAR_REPEL_STEP_COUNT, ItemId_GetHoldEffectParam(VarGet(VAR_LAST_REPEL_LURE_USED)));
|
||||
#endif
|
||||
}
|
||||
|
||||
void ItemUseOutOfBattle_Lure(u8 taskId)
|
||||
{
|
||||
if (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_STEP_COUNT, ItemId_GetHoldEffectParam(gSpecialVar_ItemId) | REPEL_LURE_MASK);
|
||||
#if VAR_LAST_REPEL_LURE_USED != 0
|
||||
VarSet(VAR_LAST_REPEL_LURE_USED, gSpecialVar_ItemId);
|
||||
#endif
|
||||
RemoveUsedItem();
|
||||
if (!InBattlePyramid())
|
||||
DisplayItemMessage(taskId, FONT_NORMAL, gStringVar4, CloseItemMessage);
|
||||
else
|
||||
DisplayItemMessageInBattlePyramid(taskId, gStringVar4, Task_CloseBattlePyramidBagMessage);
|
||||
}
|
||||
}
|
||||
|
||||
void HandleUseExpiredLure(void)
|
||||
{
|
||||
#if VAR_LAST_REPEL_LURE_USED != 0
|
||||
VarSet(VAR_REPEL_STEP_COUNT, ItemId_GetHoldEffectParam(VarGet(VAR_LAST_REPEL_LURE_USED)) | REPEL_LURE_MASK);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void Task_UsedBlackWhiteFlute(u8 taskId)
|
||||
{
|
||||
|
@ -3329,7 +3329,6 @@ void CreateBoxMon(struct BoxPokemon *boxMon, u16 species, u8 level, u8 fixedIV,
|
||||
}
|
||||
else // Player is the OT
|
||||
{
|
||||
u32 shinyValue;
|
||||
value = gSaveBlock2Ptr->playerTrainerId[0]
|
||||
| (gSaveBlock2Ptr->playerTrainerId[1] << 8)
|
||||
| (gSaveBlock2Ptr->playerTrainerId[2] << 16)
|
||||
@ -3337,22 +3336,24 @@ void CreateBoxMon(struct BoxPokemon *boxMon, u16 species, u8 level, u8 fixedIV,
|
||||
|
||||
if (gBaseStats[species].flags & SPECIES_FLAG_SHINY_LOCKED)
|
||||
{
|
||||
do
|
||||
while (GET_SHINY_VALUE(value, personality) < SHINY_ODDS)
|
||||
{
|
||||
// Choose random personalities until one that results in a non-shiny Pokémon
|
||||
personality = Random32();
|
||||
shinyValue = HIHALF(value) ^ LOHALF(value) ^ HIHALF(personality) ^ LOHALF(personality);
|
||||
} while (shinyValue < SHINY_ODDS);
|
||||
}
|
||||
}
|
||||
else if (CheckBagHasItem(ITEM_SHINY_CHARM, 1))
|
||||
else
|
||||
{
|
||||
u32 rolls = 0;
|
||||
do
|
||||
u32 totalRerolls = 0;
|
||||
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)
|
||||
{
|
||||
personality = Random32();
|
||||
shinyValue = HIHALF(value) ^ LOHALF(value) ^ HIHALF(personality) ^ LOHALF(personality);
|
||||
rolls++;
|
||||
} while (shinyValue >= SHINY_ODDS && rolls < I_SHINY_CHARM_REROLLS);
|
||||
totalRerolls--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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]
|
||||
|
@ -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}");
|
||||
|
@ -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
|
||||
|
||||
@ -54,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);
|
||||
|
||||
@ -181,58 +184,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_STEP_COUNT != 0 && (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_STEP_COUNT != 0 && (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_STEP_COUNT != 0 && (Random() % 10 < 2))
|
||||
swap = TRUE;
|
||||
|
||||
switch (rod)
|
||||
{
|
||||
case OLD_ROD:
|
||||
@ -240,6 +267,9 @@ static u8 ChooseWildMonIndex_Fishing(u8 rod)
|
||||
wildMonIndex = 0;
|
||||
else
|
||||
wildMonIndex = 1;
|
||||
|
||||
if (swap)
|
||||
wildMonIndex = 1 - wildMonIndex;
|
||||
break;
|
||||
case GOOD_ROD:
|
||||
if (rand < ENCOUNTER_CHANCE_FISHING_MONS_GOOD_ROD_SLOT_2)
|
||||
@ -248,6 +278,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,46 +293,61 @@ 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;
|
||||
}
|
||||
|
||||
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)
|
||||
@ -461,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))
|
||||
@ -474,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;
|
||||
@ -521,6 +569,8 @@ static bool8 DoWildEncounterRateTest(u32 encounterRate, bool8 ignoreAbility)
|
||||
encounterRate = encounterRate * 80 / 100;
|
||||
ApplyFluteEncounterRateMod(&encounterRate);
|
||||
ApplyCleanseTagEncounterRateMod(&encounterRate);
|
||||
if (LURE_STEP_COUNT != 0)
|
||||
encounterRate *= 2;
|
||||
if (!ignoreAbility && !GetMonData(&gPlayerParty[0], MON_DATA_SANITY_IS_EGG))
|
||||
{
|
||||
u32 ability = GetMonAbility(&gPlayerParty[0]);
|
||||
@ -825,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);
|
||||
@ -892,24 +942,37 @@ u16 GetLocalWaterMon(void)
|
||||
|
||||
bool8 UpdateRepelCounter(void)
|
||||
{
|
||||
u16 steps;
|
||||
u16 repelLureVar = VarGet(VAR_REPEL_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_STEP_COUNT, steps);
|
||||
if (steps == 0)
|
||||
{
|
||||
ScriptContext_SetupScript(EventScript_RepelWoreOff);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
VarSet(VAR_REPEL_STEP_COUNT, steps | REPEL_LURE_MASK);
|
||||
if (steps == 0)
|
||||
{
|
||||
ScriptContext_SetupScript(EventScript_LureWoreOff);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
@ -918,7 +981,7 @@ static bool8 IsWildLevelAllowedByRepel(u8 wildLevel)
|
||||
{
|
||||
u8 i;
|
||||
|
||||
if (!VarGet(VAR_REPEL_STEP_COUNT))
|
||||
if (!REPEL_STEP_COUNT)
|
||||
return TRUE;
|
||||
|
||||
for (i = 0; i < PARTY_SIZE; i++)
|
||||
@ -976,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))
|
||||
|
Loading…
x
Reference in New Issue
Block a user