Password system - pret/pokecrystal GitHub Wiki
In Pokémon Fool's Gold, which this tutorial is adapted from, the player is able to input "passwords" upon creating a new save file, which change the game in various ways.
Contents
1. Setting up the password input
Inspecting wram.asm reveals that, in addition to the player's and rival's names, there are three unused variables for other custom names-- wMomsName
, wRedsName
, and wGreensName
. The password system takes advantage of this to allow custom inputs.
Edit constants/menu_constants.asm:
; Naming types (see engine/menus/naming_screen.asm)
const_def
const NAME_MON
const NAME_PLAYER
const NAME_RIVAL
const NAME_MOM
const NAME_BOX
const NAME_FRIEND
const NAME_6 ; duplicate of NAME_MON
const NAME_7 ; duplicate of NAME_MON
+ const NAME_PASSWORD
DEF NUM_NAME_TYPES EQU const_value
Edit engine/menus/naming_screen.asm:
.Jumptable:
; entries correspond to NAME_* constants
dw .Pokemon
dw .Player
dw .Rival
dw .Mom
dw .Box
dw .Tomodachi
dw .Pokemon
dw .Pokemon
+ dw .Password
...
.oTomodachi_no_namae_sutoringu
db "おともだち の なまえは?@"
+.Password:
+ hlcoord 5, 2
+ ld de, .PasswordString
+ call PlaceString
+ call .StoreMonIconParams
+ ret
+
+.PasswordString:
+ db "PASSWORD?@"
Edit engine/menus/intro_menu.asm:
PlayerProfileSetup:
farcall CheckMobileAdapterStatus
jr c, .ok
farcall InitGender
+ ld hl, TextJump_PasswordOption
+ call PrintText
+ call YesNoBox
+ ret c
+
+ call RotateFourPalettesLeft
+ call ClearTileMap
+
+ ld b, NAME_PASSWORD
+ ld de, wGreensName
+ farcall NamingScreen
ret
.ok
ld c, 0
farcall InitMobileProfile
ret
+TextJump_PasswordOption:
+ text_far Text_PasswordOption
+ text_end
Edit data/text/common_2.asm:
_OakText5::
text "But we don't know"
line "everything about"
cont "#MON yet."
para "There are still"
line "many mysteries to"
cont "solve."
para "That's why I study"
line "#MON every day."
prompt
+Text_PasswordOption::
+ text "Enter an optional"
+ line "password?"
+ prompt
At this point, when starting a new game, there will be the option to enter a password, but actually entering the password does nothing.
We've got everything we need to start having fun with passwords. Let's add a couple of effects as examples.
Note: Entering an invalid password does nothing. In addition, there'll be no indication whether a password you enter is valid or not. You might want to add some kind of sound effect or text box letting the player know that the password they've entered is correct; however, this will make guessing passwords through trial and error significantly easier, which you may not want.
2. Boosted shiny rate
An obvious password feature is to boost the shiny rate. Gen II's shiny rate is 1/8192; with this password on, the new shiny rate will be 1/1024 (eight times as common).
For this example, let's use "SHINY" (all caps) as our password-- simple and easy. You're probably going to want to change it to something harder to guess ;)
Edit engine/gfx/color.asm:
CheckShininess:
...
; Speed
ld a, [hl]
and %1111 << 4
cp SHINY_SPD_DV << 4
jr nz, .not_shiny
+; Check if the shiny password is active.
+ push de
+ push hl
+ ld de, ShinyPassword
+ ld hl, wGreensName
+ ld c, 4
+ call CompareBytes
+ jr z, .AltSpecial
+ pop hl
+ pop de
; Special
ld a, [hl]
and %1111
cp SHINY_SPC_DV
jr nz, .not_shiny
+ jr .shiny
+
+.AltSpecial
+ pop hl
+ pop de
+ ld a, [hl]
+ and SHINY_ATK_MASK << 4
+ jr z, .not_shiny
-; shiny
+.shiny
scf
ret
.not_shiny
and a
ret
+ShinyPassword:
+ db "SHINY"
With the password enabled, shiny Pokémon will be a heck of a lot more common!
3. Alternate starter choices
Fool's Gold uses three passwords to change the starter Pokémon to different sets. For this example, we'll do the Gen I starters: Bulbasaur, Charmander, and Squirtle.
To accomplish this, the required password (we'll use "KANTO" as the password here) has to activate a corresponding event flag.
First, edit constants/event_flags.asm to add two new flags: EVENT_PASSWORD_KANTO
and EVENT_PASSWORD_SET
. There are a lot of unused flags you can replace, or you can just add them to the bottom.
Next, edit maps/PlayersHouse1F.asm:
MeetMomScript:
+ scall MomScriptPasswordCheck
opentext
writetext ElmsLookingForYouText
promptbutton
...
PlayersHouse1FReceiveItemStd:
jumpstd ReceiveItemScript
end
+PasswordCheck:
+ checkevent EVENT_PASSWORD_SET
+ iftrue .stop
+ setevent EVENT_PASSWORD_SET
+ callasm .kanto
+ iftrue .kanto2
+.stop
+ end
+
+.kanto
+ xor a
+ ld [wScriptVar], a
+ ld de, KantoPassword
+ ld hl, wGreensName ; check inputted password
+ ld c, 4
+ call CompareBytes
+ ret nz
+ ld a, 1
+ ld [wScriptVar], a
+ ret
+
+.kanto2
+ setevent EVENT_PASSWORD_KANTO
+ end
+
+KantoPassword:
+ db "KANTO"
Edit maps/ElmsLab.asm:
CyndaquilPokeBallScript:
checkevent EVENT_GOT_A_POKEMON_FROM_ELM
iftrue LookAtElmPokeBallScript
turnobject ELMSLAB_ELM, DOWN
refreshscreen
+ checkevent EVENT_PASSWORD_KANTO
+ iftrue CharmanderPokeBallScript
pokepic CYNDAQUIL
cry CYNDAQUIL
...
+CharmanderPokeBallScript:
+ pokepic CHARMANDER
+ cry CHARMANDER
+ waitbutton
+ closepokepic
+ opentext
+ writetext TakeCharmanderText
+ yesorno
+ iffalse DidntChooseStarterScript
+ disappear ELMSLAB_POKE_BALL1
+ setevent EVENT_GOT_CYNDAQUIL_FROM_ELM
+ writetext ChoseStarterText
+ promptbutton
+ waitsfx
+ getmonname STRING_BUFFER_3, CHARMANDER
+ writetext ReceivedStarterText
+ playsound SFX_CAUGHT_MON
+ waitsfx
+ promptbutton
+ givepoke CHARMANDER, 5, BERRY
+ closetext
+ readvar VAR_FACING
+ ifequal RIGHT, ElmDirectionsScript
+ applymovement PLAYER, AfterCyndaquilMovement
+ sjump ElmDirectionsScript
...
TakeCyndaquilText:
text "ELM: You'll take"
line "CYNDAQUIL, the"
cont "fire #MON?"
done
+TakeCharmanderText:
+ text "ELM: You'll take"
+ line "CHARMANDER, the"
+ cont "fire #MON?"
+ done
Here I've just done Charmander; the process is the same for Bulbasaur and Squirtle. Note that the event set (EVENT_GOT_CYNDAQUIL_FROM_ELM
here) and movement (AfterCyndaquilMovement
) are the same.
Using the mom script to set password flags may not be the perfect solution-- this is just how it's done in Fool's Gold. I'm a great believer that an unoptimal solution is way better than none at all. That being said, if you of know a better way, feel free to add it here!
4. Other password ideas
This section isn't as much of a tutorial as it is space for me to encourage brainstorming for more passwords. In addition to the passwords listed here, Fool's Gold also uses the password system to enforce level caps, switch up in-game trades and such to allow late game Pokémon to be accessed earlier, flip the type chart around a la Inverse Battles, and even to allow the player to capture a Mythical Pokémon, in the same vein as Mystery Gift distributions. The big limitation here is space; there have been times where I've wanted to add in a password only to run out of space. Aside from that, the only limit is your ✨imagination✨!
The last (and possibly most important) note is about password acquisition-- unless you want to make passwords a guessing game (which is valid), you probably want some way for the players to actually find out about these passwords.
In Fool's Gold, passwords are gated behind gameplay milestones; for instance, the Kanto starter password is available after defeating Lance, and, in the spirit of the Shiny Charm, the shiny password is revealed upon completing the Pokédex and getting your Diploma from the GAME FREAK employees in Celadon City. Fool's Gold has a fancy screen revealing the password complete with a short blurb about what it does, but the simplest way to accomplish this would be just to reveal it through a text box. You can do something completely different, though! Maybe you could set up an ARG involving the passwords or something. Just like password effects, let your heart lead you.