-
Notifications
You must be signed in to change notification settings - Fork 1k
Hyper Training
Hyper Training is a mechanic introduced in Generation VII where you can exchange Bottle Caps with a "Mr. Hyper" NPC to change your Pokemon's IVs to perfect-31s. This tutorial ports that mechanic to RBY.
Hyper Training can benefit RBY hugely, as in addition to helping with sentimental value towards the player's Pokemon, it has unique gameplay differences that make it arguably essential without additional modifications. There isn't any breeding, TMs are single-use and have to be saved for a perfect catch, and DVs can never be perfect for Pokemon found in tall grass. Hyper Training can effectively nullify all of these issues. Well, except for TMs unless you're accounting for that in your own hack.
As a note, I am not entirely sure about how to change individual DVs, because they're stored as a single number. There's definitely a way, likely involving changing just a specific part of it, but it was just easier for me personally to implement a Gold Bottle Cap. Vanilla RBY generally doesn't have much use for single-DV modifications anyway: You hardly see it in competitive play as-is.
The implementation I'm sharing is taken from my commit for my own ROM Hack, so there's a little bit of theming that you may want to change yourself!
When implementing my Hyper Training NPC, I used James, as he collects Bottle Caps in the anime, making it a little more appropriate for RBY hacks with Yellow content. I also framed it as post-game content, acting as a sort of closure for their appearance in Yellow, as they otherwise just sort of disappear. Ergo, if you use my implementation, you'll want his sprite: This commit should help you, but note that it has a bunch of other stuff, so you may fare better using this tutorial.
If you don't want James, you can change the NPC to Mr. Hyper - simply do a Find/Replace job, changing "James" to "MrHyper", and then change his object in maps/objects/locationnamehere.asm
to like, BALDING_GUY
or something.
Firstly, pick a location where you want your Mr. Hyper to be. Then, in its respective scripts\locationnamehere.asm
file, add the following code. It's not the best - you'll notice some dubious associations with the Bottle Cap item - but it all works. I've included a bunch of comments to help you understand it. It's useful to note that this can also teach you how to work with 16-bit registers!
Location_TextPointers:
...
dw JamesText
...
JamesText:
text_asm
call SaveScreenTilesToBuffer2 ; It really doesn't need to be done this early, it just helps.
; This is taken from the Saffron Guards, Cinnabar Fossils, and Celadon Dept Store Roof.
ld b, BOTTLE_CAP ; Check bag for Bottle Caps. We only need one for this.
predef GetQuantityOfItemInBag
ld a, b
and a
jr z, .NoBottleCap ; If zero, James says something else.
ld hl, JamesSeesBottleCap ; Otherwise, he perks up.
call PrintText
call YesNoChoice ; Yes/No Prompt
ld a, [wCurrentMenuItem]
and a
jr nz, .refused
; Proceed from here if Yes is stated.
; Here, the party menu pops up and the player picks a Pokemon to juice.
xor a
ld [wUpdateSpritesEnabled], a
ld [wPartyMenuTypeOrMessageID], a
ld [wMenuItemToSwap], a
call DisplayPartyMenu
push af
call GBPalWhiteOutWithDelay3
call RestoreScreenTilesAndReloadTilePatterns
call LoadGBPal
pop af
ld hl, JamesDone
call PrintText
; DV increasing process.
; Thanks to Vimescarrot for giving me pointers on this!
ld a, [wWhichPokemon] ; Find the Pokemon's position in party.
ld hl, wPartyMon1DVs ; Load DVs into hl
ld bc, wPartyMon2 - wPartyMon1 ; This gets to the right slot for DVs
call AddNTimes ; Gets us there
ld a, %11111111 ; Load FFFF FFFF, perfect 15s
ld [hli], a ; Load 1111 to Attack + Defence
ld [hl], a ; Now load 1111 to Speed + Special
; And we're done!
; Currently, this doesn't automatically change the stats. Vitamins don't either, so you could say it's consistent, but it's also inconvenient.
; Bottle Cap removal service
ld hl, BottleCapList ; Load a list of Bottle Cap items. This is the same code as the Saffron Guard.
.loop
ld a, [hli]
ldh [hItemToRemoveID], a
and a
ret z
push hl
ld b, a
call IsItemInBag
pop hl
jr z, .loop
farcall RemoveItemByID
jr .done
.NoBottleCap
ld hl, JamesNoCap
call PrintText
jr .done
.refused
ld hl, JamesNo
call PrintText
jr .done
.done
jp TextScriptEnd
; This list is loaded for the Bottle Cap removal script, it otherwise didn't work properly.
BottleCapList:
db BOTTLE_CAP
;db GOLD_BOTTLE_CAP if you ever want to add Gold Bottle caps, you can chuck that in here.
db 0 ; end
...
; These are text pointers for the script to load.
JamesNoCap:
text_far _JamesText
text_end
JamesSeesBottleCap:
text_far _JamesSeesBottleCap
text_end
JamesYes:
text_far _JamesYes
text_end
JamesNo:
text_far _JamesNo
text_end
JamesDone:
text_far _JamesDone
text_end
Look through this tutorial, with BOTTLE CAP being the name. It covers it better than I would! In this case, the Bottle Cap should be an unusable item, making it nice and easy!
In the text/locationnamehere.asm
equivalent for the script you chose, add the following text, changing it as it interests you. This text will be farcalled from the scripts file we edited earlier.
_JamesText::
text "I'm tired..."
para "JESSIE won't stop"
line "nagging us..."
done
_JamesSeesBottleCap::
text "Hey, is that a"
line "BOTTLE CAP? I"
cont "collect these!"
para "Tell you what..."
para "You give me that"
line "BOTTLE CAP, and"
cont "I'll make your"
cont "#MON a little"
cont "stronger!"
done
_JamesYes::
text "Which #MON is"
line "is getting"
cont "juiced?"
done
_JamesNo::
text "But it's so"
line "rare..."
done
_JamesDone::
text "There! Come back"
line "with more if"
cont "you find any!"
done
In data/maps/objects/locationnamehere.asm
, you'll need to add an NPC with the script. Where you see the number next to ; James
, it should match the position JamesText
has in Location_TextPointers:
in scripts/locationnamehere.asm
. Put simply, if it's the 6th entry down, it will be 6, and so on.
LocationNameHere_Object:
...
def_object_events
...
object_event 9, 5, SPRITE_JAMES, STAY, DOWN, 6 ; James
def_warps_to LOCATION_NAME_HERE
And that's it! You now have your own Mr. Hyper (or James!). All you need to do now is distribute the Bottle Cap across Kanto!
There are some shortcomings of my implementation that you may want to try and modify yourself. If you do, feel free to edit this page so everyone else can do a better implementation!
- There's no SFX, which may make it feel less impactful than it should.
- The Bottle Cap system here is solely for Gold Bottle Cap-like functionality. In vanilla RBY, there are situations where you may want lower Attack, such as for confusion damage, but on the other hand, higher Attack means winning Struggle wars. Otherwise, though, there is little reason to implement single Bottle Cap functionality. In fact, it may be better to have a "Rusty Bottle Cap" that tanks the Attack stat instead.
- Stats aren't recalculated immediately - this doesn't happen for vitamins either. Ergo, players need to use the Box Trick or level up to see the results of the training. In trying to do this, I experienced some hardship (even when calling CalcStats), so I'm not entirely sure how to do it.