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
  2. Boosted shiny rate
  3. Alternate starter choices
  4. Other password ideas

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.

password1 password2

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"

password3

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.

password4 password5 password6

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.