diff --git a/Add-Nuzlocke-Challenge.md b/Add-Nuzlocke-Challenge.md index 058b6aa..4c9b8d6 100644 --- a/Add-Nuzlocke-Challenge.md +++ b/Add-Nuzlocke-Challenge.md @@ -5,6 +5,8 @@ By devolov ![pokeemerald-0](https://user-images.githubusercontent.com/36523934/211448320-efa34b1d-554a-491e-8f07-0cd2a10dcf60.png) ![pokeemerald-1](https://user-images.githubusercontent.com/36523934/211448331-82a7bde1-80eb-4db8-ab12-93611380b1cb.png) ![pokeemerald-2](https://user-images.githubusercontent.com/36523934/211448326-8184ca37-0a5b-4cbf-b484-a4c9e45deeb2.png) +![pokeemerald_modern-0](https://github.com/pret/pokeemerald/assets/36523934/f87c96ac-6015-4cf8-a60f-88346b5482a3) + The rules for the Nuzlocke challenge: * [If a Pokemon faints, they cannot be revived.](#pokemon-that-faint-cannot-be-revived) @@ -12,6 +14,7 @@ The rules for the Nuzlocke challenge: * Optional: * [Dupes Clause](#Dupes-Clause) * [Can't Overlevel Leaders](#Cant-Overlevel-Leaders) + * [Have Nurse Joy Tell You the Level Cap](#have-nurse-joy-tell-you-the-level-cap) * [No Held Items](#no-held-items) * [No Battle Items](#no-battle-items) * [Force Set Mode](#force-set-mode) @@ -229,7 +232,7 @@ index f2db321a5..9f0894b28 100644 + gText_RegisteredTrainerinPokeNav:: .string "Registered {STR_VAR_1} {STR_VAR_2}\n" - .string "in the POKéNAV.$" + .string "in the POKéNAV.$" ------------ data/maps/LittlerootTown_BrendansHouse_1F/scripts.inc ------------ @@ -408,7 +411,7 @@ index 54ff4d614..4f82d8d75 100644 static void HandleEndTurn_FinishBattle(void) { -+ gNuzlockeCannotCatch = FALSE; // While not necissary, resetting this is nice to stay deterministic ++ gNuzlockeCannotCatch = 0; // While not necissary, resetting this is nice to stay deterministic if (gCurrentActionFuncId == B_ACTION_TRY_FINISH || gCurrentActionFuncId == B_ACTION_FINISHED) { if (!(gBattleTypeFlags & (BATTLE_TYPE_LINK @@ -622,7 +625,7 @@ index 5a1d5bab3..9126aeeb4 100644 bool8 IsTrainerReadyForRematch(void); void ShouldTryGetTrainerScript(void); u16 CountBattledRematchTeams(u16 trainerId); -+bool8 HasWildPokmnOnThisRouteBeenSeen(u8 currLocation, bool8 setVarForThisEnc); ++u8 HasWildPokmnOnThisRouteBeenSeen(u8 currLocation, bool8 setVarForThisEnc); +u8 currLocConvertForNuzlocke(u8 currLocation); + @@ -746,7 +749,7 @@ index b503f8d65..36da06845 100644 return i; } + -+bool8 HasWildPokmnOnThisRouteBeenSeen(u8 currLocation, bool8 setVarForThisEnc){ ++u8 HasWildPokmnOnThisRouteBeenSeen(u8 currLocation, bool8 setVarForThisEnc){ + u8 varToCheck, bitToCheck; + u16 varValue; + const u16 pkmnSeenVars[] = { @@ -763,7 +766,7 @@ index b503f8d65..36da06845 100644 + VarSet(VAR_WILD_PKMN_ROUTE_SEEN_2, 0); + VarSet(VAR_WILD_PKMN_ROUTE_SEEN_3, 0); + VarSet(VAR_WILD_PKMN_ROUTE_SEEN_4, 0); -+ return FALSE; ++ return 0; + } + switch (currLocation) + { @@ -1072,16 +1075,16 @@ index b503f8d65..36da06845 100644 + varToCheck = 4; + bitToCheck = 10; + default: -+ return FALSE; ++ return 0; + } + varValue = VarGet(pkmnSeenVars[varToCheck]); + if ((varValue & (1 << bitToCheck)) != 0){ -+ return TRUE; ++ return 1; + } + else if (setVarForThisEnc){ + VarSet(pkmnSeenVars[varToCheck], varValue | (1 << bitToCheck)); + } -+ return FALSE; ++ return 0; +} + +u8 currLocConvertForNuzlocke(u8 currLocation){ @@ -1156,8 +1159,8 @@ index d663bbeb6..403ff54fa 100755 return; } #endif -- -+ if (gNuzlockeCannotCatch){ + ++ if (gNuzlockeCannotCatch == 1){ + GetMapNameHandleAquaHideout(gStringVar1, currLocConvertForNuzlocke(GetCurrentRegionMapSectionId())); + DisplayItemMessage(taskId, FONT_NORMAL, gText_BallsCannotBeUsedNuz, CloseItemMessage); + return; @@ -1170,31 +1173,6 @@ index d663bbeb6..403ff54fa 100755 ### Dupes Clause: ```diff ----------------------------- include/battle_setup.h ---------------------------- -index 9126aeeb4..feaa30c00 100644 -@@ -16,9 +16,9 @@ extern const struct RematchTrainer gRematchTable[REMATCH_TABLE_ENTRIES]; - - extern u16 gTrainerBattleOpponent_A; - extern u16 gTrainerBattleOpponent_B; - extern u16 gPartnerTrainerId; --extern bool8 gNuzlockeCannotCatch; -+extern u8 gNuzlockeCannotCatch; - - void BattleSetup_StartWildBattle(void); - void BattleSetup_StartBattlePikeWildBattle(void); - void BattleSetup_StartRoamerBattle(void); -@@ -63,9 +63,9 @@ u16 GetLastBeatenRematchTrainerId(u16 trainerId); - bool8 ShouldTryRematchBattle(void); - bool8 IsTrainerReadyForRematch(void); - void ShouldTryGetTrainerScript(void); - u16 CountBattledRematchTeams(u16 trainerId); --bool8 HasWildPokmnOnThisRouteBeenSeen(u8 currLocation, bool8 setVarForThisEnc); -+u8 HasWildPokmnOnThisRouteBeenSeen(u8 currLocation, bool8 setVarForThisEnc); - u8 currLocConvertForNuzlocke(u8 currLocation); - - - void DoStandardWildBattle_Debug(void); - -------------------- include/constants/battle_string_ids.h -------------------- index 26cd431d1..f96aa3333 100644 @@ -7,8 +7,9 @@ @@ -1211,37 +1189,33 @@ index 26cd431d1..f96aa3333 100644 ------------------------------ src/battle_main.c ------------------------------ index fd3986fe8..4d534b447 100644 @@ -3675,12 +3675,18 @@ static void BattleIntroPrintWildMonAttacked(void) - static void BattleIntroQuickRun(void) - { - if (gBattleControllerExecFlags == 0) - { -- if (JOY_HELD(DPAD_RIGHT)) -+ if (JOY_HELD(DPAD_RIGHT)){ - gBattleMainFunc = HandleEndTurn_RanFromBattle; -- else -+ } -+ else{ -+ u16 species_enemy = GetMonData(&gEnemyParty[gBattlerPartyIndexes[GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT)]], MON_DATA_SPECIES2); - gBattleMainFunc = BattleIntroPrintPlayerSendsOut; -+ if (gNuzlockeCannotCatch == 2){ // If Pokemon was first in this route and was already caught -+ PrepareStringBattle(STRINGID_NUZLOCKEDUPS, 0); -+ } -+ } - } - } +static void BattleIntroPrintWildMonAttacked(void) +{ + if (gBattleControllerExecFlags == 0) + { +- gBattleMainFunc = BattleIntroPrintPlayerSendsOut; ++ gBattleMainFunc = BattleIntroNuzlockDups; + PrepareStringBattle(STRINGID_INTROMSG, 0); + } +} -@@ -5204,9 +5211,9 @@ static void HandleEndTurn_MonFled(void) - } - - static void HandleEndTurn_FinishBattle(void) - { -- gNuzlockeCannotCatch = FALSE; // While not necissary, resetting this is nice to stay deterministic -+ gNuzlockeCannotCatch = 0; // While not necissary, resetting this is nice to stay deterministic - if (gCurrentActionFuncId == B_ACTION_TRY_FINISH || gCurrentActionFuncId == B_ACTION_FINISHED) - { - if (!(gBattleTypeFlags & (BATTLE_TYPE_LINK - | BATTLE_TYPE_RECORDED_LINK ++static void BattleIntroNuzlockDups(void) ++{ ++ if (gBattleControllerExecFlags == 0) ++ { ++ if (gNuzlockeCannotCatch == 2){ // If Pokemon was first in this route and was already caught ++ PrepareStringBattle(STRINGID_NUZLOCKEDUPS, 0); ++ } ++ gBattleMainFunc = BattleIntroPrintPlayerSendsOut; ++ } ++} ++ +static void BattleIntroPrintOpponentSendsOut(void) +{ + u32 position; + if (gBattleControllerExecFlags) + return; ----------------------------- src/battle_message.c ----------------------------- index 4b977a229..e6d5a871f 100644 @@ -78,9 +78,10 @@ static const u8 sText_AttackerFainted[] = _("{B_ATK_NAME_WITH_PREFIX}\nfainted!\ @@ -1249,8 +1223,7 @@ index 4b977a229..e6d5a871f 100644 static const u8 sText_PlayerGotMoney[] = _("{B_PLAYER_NAME} got Â¥{B_BUFF1}\nfor winning!\p"); static const u8 sText_PlayerWhiteout[] = _("{B_PLAYER_NAME} is out of\nusable POKéMON!\p"); static const u8 sText_PlayerWhiteout2[] = _("{B_PLAYER_NAME} panicked and lost Â¥{B_BUFF1}…\p{B_PLAYER_NAME} whited out!{PAUSE_UNTIL_PRESS}"); --static const u8 sText_PlayerFailedNuzlocke[] = _("{B_PLAYER_NAME} failed the\nNuzlocke challenge.{PAUSE_UNTIL_PRESS}"); -+static const u8 sText_PlayerFailedNuzlocke[] = _("{B_PLAYER_NAME} failed the\nNuzlocke challenge.\pThe Nuzlocke setting\nhas been turned off.\p"); + static const u8 sText_PlayerFailedNuzlocke[] = _("{B_PLAYER_NAME} failed the\nNuzlocke challenge.\pThe Nuzlocke setting\nhas been turned off.\p"); +static const u8 sText_PlayerDuplicateMon[] = _("Since this type has already been\ncaught, it will not count towards\pthe Nuzlocke challenge.\p"); static const u8 sText_PreventsEscape[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX} prevents\nescape with {B_SCR_ACTIVE_ABILITY}!\p"); static const u8 sText_CantEscape2[] = _("Can't escape!\p"); @@ -1282,50 +1255,10 @@ index 36da06845..19bed4e96 100644 enum { TRANSITION_TYPE_NORMAL, TRANSITION_TYPE_CAVE, -@@ -420,8 +422,9 @@ static void CreateBattleStartTask_Debug(u8 transition, u16 song) - - void BattleSetup_StartWildBattle(void) - { - gNuzlockeCannotCatch = HasWildPokmnOnThisRouteBeenSeen(GetCurrentRegionMapSectionId(), TRUE); -+ - if (GetSafariZoneFlag()) - DoSafariBattle(); - else - DoStandardWildBattle(); -@@ -1953,9 +1956,9 @@ u16 CountBattledRematchTeams(u16 trainerId) - - return i; - } - --bool8 HasWildPokmnOnThisRouteBeenSeen(u8 currLocation, bool8 setVarForThisEnc){ -+u8 HasWildPokmnOnThisRouteBeenSeen(u8 currLocation, bool8 setVarForThisEnc){ - u8 varToCheck, bitToCheck; - u16 varValue; - const u16 pkmnSeenVars[] = { - VAR_WILD_PKMN_ROUTE_SEEN_0, -@@ -1970,9 +1973,9 @@ bool8 HasWildPokmnOnThisRouteBeenSeen(u8 currLocation, bool8 setVarForThisEnc){ - VarSet(VAR_WILD_PKMN_ROUTE_SEEN_1, 0); - VarSet(VAR_WILD_PKMN_ROUTE_SEEN_2, 0); - VarSet(VAR_WILD_PKMN_ROUTE_SEEN_3, 0); - VarSet(VAR_WILD_PKMN_ROUTE_SEEN_4, 0); -- return FALSE; -+ return 0; - } - switch (currLocation) - { - case MAPSEC_LITTLEROOT_TOWN: -@@ -2279,18 +2282,22 @@ bool8 HasWildPokmnOnThisRouteBeenSeen(u8 currLocation, bool8 setVarForThisEnc){ - case MAPSEC_ALTERING_CAVE: - varToCheck = 4; - bitToCheck = 10; - default: -- return FALSE; -+ return 0; - } +@@ -2279,18 +2282,22 @@ u8 HasWildPokmnOnThisRouteBeenSeen(u8 currLocation, bool8 setVarForThisEnc){ varValue = VarGet(pkmnSeenVars[varToCheck]); if ((varValue & (1 << bitToCheck)) != 0){ -- return TRUE; -+ return 1; + return 1; } else if (setVarForThisEnc){ + u16 species_enemy = GetMonData(&gEnemyParty[gBattlerPartyIndexes[GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT)]], MON_DATA_SPECIES2); @@ -1334,26 +1267,8 @@ index 36da06845..19bed4e96 100644 + } VarSet(pkmnSeenVars[varToCheck], varValue | (1 << bitToCheck)); } -- return FALSE; -+ return 0; + return 0; } - - u8 currLocConvertForNuzlocke(u8 currLocation){ - switch (currLocation) - --------------------------------- src/item_use.c -------------------------------- -index 403ff54fa..8e62af305 100755 -@@ -951,9 +951,9 @@ void ItemUseInBattle_PokeBall(u8 taskId) - DisplayItemMessage(taskId, 1, sText_BallsCannotBeUsed, CloseItemMessage); - return; - } - #endif -- if (gNuzlockeCannotCatch){ -+ if (gNuzlockeCannotCatch == 1){ - GetMapNameHandleAquaHideout(gStringVar1, currLocConvertForNuzlocke(GetCurrentRegionMapSectionId())); - DisplayItemMessage(taskId, FONT_NORMAL, gText_BallsCannotBeUsedNuz, CloseItemMessage); - return; - } ``` ## Can't Overlevel Leaders @@ -1365,13 +1280,12 @@ index 6e6f5886e..c5f9baa57 100644 return i; } -+bool8 levelCappedNuzlocke(u8 level){ ++static u8 getLevelCap(void){ + u8 levelCap = 0; + u16 nextLeader, i; + const struct TrainerMonItemCustomMoves *partyData; -+ if (!FlagGet(FLAG_NUZLOCKE)){ -+ return FALSE; -+ } ++ if (!FlagGet(FLAG_NUZLOCKE) || !FlagGet(FLAG_NUZLOCKE_LEVEL_CAP) || FlagGet(FLAG_IS_CHAMPION)) ++ return 100; + if (!FlagGet(FLAG_BADGE01_GET)) + nextLeader = TRAINER_ROXANNE_1; + else if (!FlagGet(FLAG_BADGE02_GET)) @@ -1396,6 +1310,13 @@ index 6e6f5886e..c5f9baa57 100644 + if (partyData[i].lvl > levelCap) + levelCap = partyData[i].lvl; + } ++ return GetScaledLevel(levelCap); ++} ++ ++bool8 levelCappedNuzlocke(u8 level){ ++ u8 levelCap = getLevelCap(); ++ if (!FlagGet(FLAG_NUZLOCKE) || !FlagGet(FLAG_NUZLOCKE_LEVEL_CAP) || FlagGet(FLAG_IS_CHAMPION)) ++ return FALSE; //Redundant since getLevelCap would already return 100 for these, but better to be explicit + if (level >= levelCap) + return TRUE; + return FALSE; @@ -1601,6 +1522,81 @@ index 2b522ebea..b94bbc344 100644 expToNextLevel = 0; ``` +### Have Nurse Joy Tell You the Level Cap +```diff +---------------------- data/scripts/pkmn_center_nurse.inc ---------------------- +index 546385218..978b9eeec 100644 +@@ -51,8 +51,14 @@ EventScript_PkmnCenterNurse_CheckTrainerHillAndUnionRoom:: + + @ VAR_0x8004 is 1 when player has Gold Card + EventScript_PkmnCenterNurse_ReturnPkmn:: + goto_if_eq VAR_0x8004, 1, EventScript_PkmnCenterNurse_ReturnPkmn2 ++ goto_if_unset FLAG_NUZLOCKE, EventScript_PkmnCenterNurse_ReturnPkmnDefault ++ goto_if_unset FLAG_NUZLOCKE_LEVEL_CAP, EventScript_PkmnCenterNurse_ReturnPkmnDefault ++ special LevelCapToString ++ message gText_WeHopeToSeeYouAgain4 ++ return ++EventScript_PkmnCenterNurse_ReturnPkmnDefault:: + message gText_WeHopeToSeeYouAgain3 + return + + EventScript_PkmnCenterNurse_ReturnPkmn2:: + +------------------------------ data/specials.inc ------------------------------ +index a863b6e13..671716581 100644 +@@ -534,4 +534,5 @@ gSpecials:: + def_special TryPrepareSecondApproachingTrainer + def_special RemoveRecordsWindow + def_special CloseDeptStoreElevatorWindow + def_special TrySetBattleTowerLinkType ++ def_special LevelCapToString + +----------------------- data/text/pkmn_center_nurse.inc ----------------------- +index cf2046b76..0d6ad541f 100644 +@@ -53,4 +53,8 @@ gText_WeHopeToSeeYouAgain2:: + gText_WeHopeToSeeYouAgain3:: + .string "Your POKéMON are healed.\n" + .string "We hope to see you again!$" + ++gText_WeHopeToSeeYouAgain4:: ++ .string "Your POKéMON are healed, but cannot\n" ++ .string "level over {STR_VAR_1} due to Nuzlocke.$" ++ + +---------------------------- include/battle_setup.h ---------------------------- +index 26e66761e..32a4e3be0 100644 +@@ -67,8 +67,9 @@ void ShouldTryGetTrainerScript(void); + u16 CountBattledRematchTeams(u16 trainerId); + u8 HasWildPokmnOnThisRouteBeenSeen(u8 currLocation, bool8 setVarForThisEnc); + u8 currLocConvertForNuzlocke(u8 currLocation); + bool8 levelCappedNuzlocke(u8 level); ++void LevelCapToString(void); + + + void DoStandardWildBattle_Debug(void); + void BattleSetup_StartTrainerBattle_Debug(void); + +------------------------------ src/battle_setup.c ------------------------------ +index 3110bd0b6..2f86c26a5 100644 +@@ -1982,19 +1980,32 @@ bool8 levelCappedNuzlocke(u8 level){ +bool8 levelCappedNuzlocke(u8 level){ + u8 levelCap = getLevelCap(); + if (level >= levelCap) + return TRUE; + return FALSE; + } + ++void LevelCapToString(void){ ++ u8 lvl_txt[3]; ++ ConvertIntToDecimalStringN(lvl_txt, getLevelCap(), STR_CONV_MODE_LEFT_ALIGN, 3); ++ StringCopy(gStringVar1, lvl_txt); ++} ++ + u8 HasWildPokmnOnThisRouteBeenSeen(u8 currLocation, bool8 setVarForThisEnc){ + u8 varToCheck, bitToCheck; + u16 varValue; +``` + ## No Held Items ```diff ------------------------------ src/battle_util.c ------------------------------