diff options
-rw-r--r-- | Infinite-TM-usage.md | 34 |
1 files changed, 33 insertions, 1 deletions
diff --git a/Infinite-TM-usage.md b/Infinite-TM-usage.md index cad173b..f7ca6ab 100644 --- a/Infinite-TM-usage.md +++ b/Infinite-TM-usage.md @@ -6,6 +6,7 @@ This tutorial will make all TMs infinitely reusable, unholdable by Pokemon, unse 1. [Don't consume TMs on use](#1-dont-consumes-tms-on-use) 2. [Treat TMs as HMs in the bag](#2-treat-tms-as-hms-in-the-bag) 3. [Don't allow TM selling and rebuying](#3-dont-allow-tm-selling-and-rebuying) +4. [Don't replenish PP when TMs are used](#4-dont-replenish-pp-when-tms-are-used) ## 1. Don't consume TMs on use Normally, the game checks if the item used was a TM or an HM, and consumes the item if it was a TM. We can just simply remove this check. @@ -137,7 +138,38 @@ Next, we need to replace all of the checks to see if there is room with checks f updatecoinsbox 1, 1 ``` -Repeat for each TM, and that's it! + +Repeat for each TM. + +We are almost done, but there is one final issue to deal with: TMs will replenish PP. It is time to address that. + +## 4. Don't replenish PP when TMs are used +This step is also technically optional (and accurate to Gen 6+ behavior!), but right now, if you overwrite a TM move with another TM and then reteach the old TM, the move will get all its PP back! This is an exploit that can be used to retain infinite PP on that move. Gen 5's solution was to assign the lower of the new PP or the old PP, meaning that TMs cannot be used to gain PP. + +To replicate this, open up `Task_PartyMenuReplaceMove` of [src/party_menu.c](../blob/master/src/party_menu.c): +```diff + static void Task_PartyMenuReplaceMove(u8 taskId) + { + struct Pokemon *mon; + u16 move; ++ u8 oldPP; + + if (IsPartyMenuTextPrinterActive() != TRUE) + { + mon = &gPlayerParty[gPartyMenu.slotId]; + RemoveMonPPBonus(mon, GetMoveSlotToReplace()); ++ oldPP = GetMonData(mon, MON_DATA_PP1 + GetMoveSlotToReplace(), NULL); + move = gPartyMenu.data1; + SetMonMoveSlot(mon, move, GetMoveSlotToReplace()); ++ if (GetMonData(mon, MON_DATA_PP1 + GetMoveSlotToReplace(), NULL) > oldPP) ++ SetMonData(mon, MON_DATA_PP1 + GetMoveSlotToReplace(), &oldPP); + Task_LearnedMove(taskId); + } + } +``` +We remember the PP before replacing the move, and if it's lower than the new PP, we put the old PP back in the move slot. + +And that's it! TMs are now reusable just like in Gen 5!   |