Skip to content
RealCataclyptic edited this page May 31, 2026 · 2 revisions

The original poketcg base offers only one game mode, but here in the hacking world, we can add more if we're careful about it. This tutorial will give a bare-bones start on what a new game mode looks like with a brief example of its application.


Contents

  1. Defining a New Mode
  2. Setting Up a New Mode
  3. Example of How To Use

1. Defining a New Mode

This section will focus on making and defining a new game mode in general. However, for the purposes of this tutorial, we will be using a "Hard Mode" as a use case example. You can replace any of these names with whatever mode you choose, like a Prop 15/3 mode, or Little Cup mode, or anything else you can think of.

Step one, as per usual, is to define your new mode. Go to constants -> script_constants.asm to define a new event.

const_def
	const EVENT_TEMP_TRADED_WITH_ISHIHARA              ; $00
...
...
    const EVENT_SAM_MENU_CHOICE                        ; $75
	const EVENT_AARON_DECK_MENU_CHOICE                 ; $76
+	const EVENT_DIFFICULTY_MODE			   ; $77 ; add hard mode
DEF NUM_EVENT_FLAGS EQU const_value

And again define it in engine -> overworld -> scripting.asm because in this case we want to set the difficulty mode from the beginning of the game, which is governed under overworld scripts.

; location in wEventVars of each event var:
; offset - which byte holds the event value
; mask - which bits in the byte hold the value
; events 0-7 are reset when game resets
EventVarMasks:
	table_width 2
	event_def $3f, %10000000 ; EVENT_TEMP_TRADED_WITH_ISHIHARA
...
...
    event_def $1c, %11110000 ; EVENT_SAM_MENU_CHOICE
	event_def $1c, %00001111 ; EVENT_AARON_DECK_MENU_CHOICE
+	event_def $1d, %00000001 ; EVENT_DIFFICULTY_MODE   ; add hard mode
	assert_table_length NUM_EVENT_FLAGS

In this case we are only adding 1 new mode to the game, so a simple binary 0 or 1 will suffice. The lowest significant bit of byte $1d in wEventVars will represent which mode the player picked.

Finally, let's now define all the text that will be used in this particular tutorial. Again, your text may differ depending on what needs your mode has to offer.

In text_offsets,

+textpointer NormalModeText
+	textpointer HardModeText
+	textpointer SelectDifficultyText
+	textpointer NormalModeDescription
+	textpointer HardModeDescription
+	textpointer PlayerChoseNormalModeText
+	textpointer PlayerChoseHardModeText

And in a free text space like text13 for instance,

+NormalModeText:
+	text "Normal Mode"
+	done

+HardModeText:
+	text "Hard Mode"
+	done

+SelectDifficultyText:
+	text "Select the mode you'd like to play."
+	done

+NormalModeDescription:
+	text "The classic"
+	line "mode. No special"
+	line "additions."
+	done

+HardModeDescription:
+	text "All cards cost"
+	line "points. Decks"
+	line "must be at or"
+	line "under 100 pts." ; This text is specific to the example given in this tutorial at the end
+	done

+PlayerChoseNormalModeText:
+	text "You have chosen Normal Mode!"
+	done

+PlayerChoseHardModeText:
+	text "You have chosen Hard mode."
+	line "Good luck!"
+	done

Now that your new mode has been defined, it's time to do something with it by forcing the player to make a choice of what difficulty mode they want at the beginning of the game.


2. Setting Up a New Mode

Let's further define what this mode actually does by creating a new file for its code. Go to src -> main.asm and define a new file in Menus 3, ROMX.

SECTION "Menus 3", ROMX
INCLUDE "engine/menus/debug_main.asm"
INCLUDE "engine/menus/main_menu.asm"
INCLUDE "engine/menus/debug.asm"
INCLUDE "engine/menus/wait_keys.asm"
INCLUDE "engine/gfx/default_palettes.asm"
INCLUDE "engine/menus/naming.asm"
+INCLUDE "engine/menus/select_difficulty.asm" ; add hard mode

Then create a file in engine -> menus named select_difficulty and fill it in with this code:

(Note to better coders than me: The text boxes have a slight delay before they appear. If anyone knows how to get rid of that delay, be my guest and add that and delete this message)

PlayerDifficultySelectionScreen: ; governs what happens on a new "Select Difficulty" screen
	; setup the screen
	xor a
	ld [wTileMapFill], a
	call EmptyScreen
	call ZeroObjectPositions
	ld a, $01
	ld [wVBlankOAMCopyToggle], a
	call LoadSymbolsFont
	lb de, $38, $bf
	call SetupText

	; print text
	ld hl, .TextItems
	call PlaceTextItems
	ldtx hl, SelectDifficultyText
	call DrawWideTextBox_PrintText
	
; Normal mode text box params 
	push af
	lb de, 0, 2
	lb bc, 10, 10
	call DrawRegularTextBox ; draws a box to make it look good.
	
; Hard mode text box params
	
	lb de, 10, 2
	lb bc, 10, 10
	call DrawRegularTextBox
	pop af

	ld hl, DifficultyDescriptions ; loads the difficulty options text
	call PlaceTextItems

	; set parameters for the cursor
	lb de, 2, 1 ; cursor x and y ; sets initial cursor position at "normal mode"
	lb bc, SYM_CURSOR_R, SYM_SPACE
	call SetCursorParametersForTextBox

	; start loop for selection
	ld a, [wCurMenuItem]
	jr .refresh_menu

.loop_input ; loops until a selection is made
	call DoFrame
	call RefreshMenuCursor
	ldh a, [hKeysPressed]
	bit B_PAD_A, a
	jr nz, .selection_made
	ldh a, [hDPadHeld]
	and PAD_RIGHT | PAD_LEFT
	jr z, .loop_input
	ld a, SFX_CURSOR
	call PlaySFX
	call EraseCursor
	ld hl, wCurMenuItem
	ld a, [hl]
	xor $1 ; toggle selected difficulty
	ld [hl], a
.refresh_menu
	or a
	ld a, 1 ; "Normal mode" cursor x ; position of where the cursor must be for normal mode
	jr z, .got_cursor_x
	ld a, 12 ; "Hard mode" cursor x ; position of where the cursor must be for hard mode
.got_cursor_x
	ld [wMenuCursorXOffset], a
	xor a
	ld [wCursorBlinkCounter], a
	jr .loop_input

.selection_made ; player made a selection
	; set the difficulty event value
	ld a, [wCurMenuItem]
	or a
	ld a, EVENT_DIFFICULTY_MODE ; set the variable
	jr nz, .HardModeEnabled    ; If player chose hard mode, jump to there
	farcall ZeroOutEventValue ; bit unset if at normal mode
	ldtx hl, PlayerChoseNormalModeText ; and load the normal mode text
	call DrawWideTextBox_WaitForInput
	ret
.HardModeEnabled
	farcall MaxOutEventValue ; bit set if at hard mode
	ldtx hl, PlayerChoseHardModeText ; and load the hard mode text
	call DrawWideTextBox_WaitForInput
	ret

.TextItems:
	textitem  2, 1, NormalModeText
	textitem 13, 1, HardModeText
	db $ff

DifficultyDescriptions:
	textitem 1, 4, NormalModeDescription
	textitem 11, 3, HardModeDescription
	db $ff
	ret

; An easy reference code to govern what happens if the player chose hard mode or not. 
IsHardModeEnabled: 
	ld a, EVENT_DIFFICULTY_MODE    ; load the value in EVENT_DIFFICULTY_MODE to a
	farcall GetEventValue
	or a
	ret       ; Return to whatever function called this

This will store the event value permanantly into the game, until New Game is selected again. This code also contains a reference to what game mode was picked to be used for other code. After we have to make a simple call to reference this entire thing at the beginning of the game, but only if "New Game" is selected. In engine -> menus -> main_menu, find

MainMenu_NewGame:
	farcall Func_c1b1
+	call PlayerDifficultySelectionScreen ; add difficulty mode
	call DisplayPlayerNamingScreen 
	farcall InitSaveData
	call EnableSRAM

With this, you now have a new screen at the beginning of the game! If you used this tutorial's example, it will look like this:

poketcg

And that's it, you now have a new mode which can do certain things depending on if the variable at the beginning of the game is set or not. The tutorial ends here, but there is one more section in case you want to view an example of how this can be applied to a game.


3. Example of How To Use

Throughout this tutorial, we used an example of "Hard mode" using the Points System. In brief, the points system assigns point values to every card, ranging from 0 to 4. These points can be tallied up for the entire deck and displayed on screen. This fact can be used to create a new, more difficult mode, wherein the NPCs have no restrictions but the player's deck must be below a certain number of points.

To implement that specifically, go to Use Case 2 in the Points System page. This tutorial will not cover it, but suffice it to say that this counts as an alternative mode for the game due to the player being forced to have a certain number of points in their deck.

However, the points system is by far not the only way to use alternate game modes. As stated earlier, Prop 15/3, the popular Hall of Fame format, or anything else you'd like. In addition, this tutorial only covered 1 alternate game mode, it is theoretically possible to do even more game modes.

Clone this wiki locally