Reading view

Adding a Brand-New Character Slot

Adding a Brand-New Character Slot

This guide explains how to add a new playable character slot to the original GameMaker project instead of replacing Jimmy in place.

It is the companion to docs/jimmy-drop-in-replacement.md. That document is for reskinning Jimmy without changing architecture. This one is for creating a genuinely new slot with its own character id, player object, menu presence, HUD portrait, swap logic, and starter weapon.

Recommended approach

Use the GameMaker IDE to duplicate resources whenever possible.

Why:

  • The IDE updates RelicHuntersZero.yyp for new resources.
  • The IDE updates the resource tree folders in views/*.yy.
  • It is much easier to keep object inheritance and event wiring intact.

If you add resources manually on disk, you will also need to register them in the project metadata, not just create files.

Mental model

Each playable character is not just a sprite set. In this project, a character slot is a bundle of:

  • a character enum value such as char_jimmy
  • a player object such as obj_jimmy
  • a character-select button object such as menu_char_jimmy
  • a swap-station object such as obj_swap_jimmy
  • a default weapon object such as obj_pistol_jimmy
  • a pickup object for that default weapon such as obj_pickup_pistol_jimmy
  • gameplay sprites
  • menu button sprites
  • a HUD portrait sprite
  • a large card sprite
  • a hologram sprite for revive and swap presentation
  • stat card text and featured weapon art
  • switch statements that map character id to all of the above

Best starting template

Jimmy is the cleanest template for a new slot because his wiring is straightforward:

  • character id in scripts/macros/macros.gml
  • spawn path in objects/controller_main/Step_0.gml
  • gameplay sprite binding in objects/obj_jimmy/Create_0.gml
  • default weapon spawn in objects/obj_jimmy/Other_10.gml
  • menu art binding in objects/menu_char_jimmy/Create_0.gml
  • swap object binding in objects/obj_swap_jimmy/Create_0.gml

Minimum resource set to create

New objects

Duplicate and rename these Jimmy resources:

  • objects/obj_jimmy -> objects/obj_<newname>
  • objects/menu_char_jimmy -> objects/menu_char_<newname>
  • objects/obj_swap_jimmy -> objects/obj_swap_<newname>
  • objects/obj_pistol_jimmy -> objects/obj_<starterweapon>
  • objects/obj_pickup_pistol_jimmy -> objects/obj_pickup_<starterweapon>

New sprites

Create a full sprite family matching the project's character pattern:

  • spr_<newname>_idle
  • spr_<newname>_walk
  • spr_<newname>_sprint
  • spr_<newname>_dash
  • spr_<newname>_hit
  • spr_<newname>_death
  • spr_<newname>_melee
  • spr_<newname>_dash_fx
  • spr_<newname>_dig
  • spr_<newname>_holo
  • spr_<newname>_teleport_in
  • spr_<newname>_teleport_out
  • spr_char_<newname>Off
  • spr_char_<newname>On
  • spr_char_<newname>Sel
  • spr_char_<newname>Final
  • spr_card_<newname>
  • spr_hud_face_<newname>
  • starter weapon sprite such as spr_<starterweapon>

Files you must update

1. Add the new character id

Edit scripts/macros/macros.gml.

Add a new macro alongside the existing character ids, for example:

#macro char_newhero 8

Rules:

  • Use an unused numeric id.
  • Keep char_random as its own special value.
  • Any code branching on char_jimmy, char_pinky, etc. may need a new branch for your slot.

2. Create the player object

Duplicate Jimmy's player object and rename it, then update Create_0.gml.

Template source:

  • objects/obj_jimmy/obj_jimmy.yy
  • objects/obj_jimmy/Create_0.gml
  • objects/obj_jimmy/Other_10.gml
  • objects/obj_jimmy/Step_1.gml

What to change:

  • playerName
  • stats such as hp_max, energy_max, stamina_max
  • all sprite bindings from Jimmy sprites to your new sprites
  • the starter weapon object spawned in Other_10.gml
  • the character-id guard in Step_1.gml

Jimmy-specific examples currently live here:

  • objects/obj_jimmy/Create_0.gml
  • objects/obj_jimmy/Other_10.gml
  • objects/obj_jimmy/Step_1.gml

3. Add runtime spawn support

Edit objects/controller_main/Step_0.gml.

This file maps global.character[p] to the player object that gets spawned. Add a branch for your new id:

if (global.character[p] == char_newhero) playerSpawned = instance_create_layer(target_spawn.spawnX,target_spawn.spawnY,"Interactive",obj_newhero);

Without this, the new character can be selected but will never spawn into gameplay.

4. Add HUD portrait support

Edit objects/controller_main/Draw_64.gml.

This file maps character ids to HUD portrait sprites. Add a branch for your new face sprite:

if (global.character[playerId] == char_newhero) draw_sprite_ext(spr_hud_face_newhero,sprite_face,charPortraitX,charPortraitY,1.5*charPortraitOrientation,1.5,1,c_white,main_hud_alpha);

spr_hud_face_* should have 3 frames because the HUD uses healthy, hurt, and critical states.

5. Add character-select button support

Duplicate objects/menu_char_jimmy and update its Create_0.gml.

Template source:

  • objects/menu_char_jimmy/Create_0.gml
  • objects/class_menu_btnChar/Create_0.gml

Change:

  • myCharacter
  • labelString
  • spriteOn
  • spriteOff
  • spriteSel
  • spriteFinal

You also need to place the new menu button object in the relevant room if the selection room is authored manually.

6. Add large card support

Edit objects/menu_char_playerCard/Draw_0.gml.

Add a branch mapping your new character id to:

  • a localized display name
  • spr_card_<newname>

Pattern source:

  • objects/menu_char_playerCard/Draw_0.gml

7. Add stats-panel support

Edit objects/menu_char_playerStat/Step_0.gml.

Add a branch for:

  • stat bars
  • featured weapon sprite
  • character description localization key

Pattern source:

  • objects/menu_char_playerStat/Step_0.gml

8. Add swap-station support

Duplicate Jimmy's swap object and update it:

  • objects/obj_swap_jimmy/Create_0.gml

Then update objects/class_character_swap/Step_2.gml and objects/class_character_swap/Draw_0.gml.

You need:

  • a new myCharacter == char_<newname> branch in the draw file so the correct hologram displays
  • a new branch in the interact logic so activating the station spawns obj_<newname>
  • unlock logic if the new character is gated behind a progression flag

If your character should always be available, add an unlock rule similar to Jimmy's always-true behavior.

9. Add revive hologram support

Edit objects/obj_revival_hologram/Create_0.gml.

Add a branch that maps:

  • char_<newname> -> obj_<newname>
  • sprite_index -> spr_<newname>_holo

Without this, dead players using the new character will not revive correctly.

10. Add starter weapon support

Create or duplicate:

  • weapon object
  • weapon pickup object
  • weapon sprite

Template source:

  • objects/obj_pistol_jimmy/Create_0.gml
  • objects/obj_pickup_pistol_jimmy/Create_0.gml

Then point your new character object's startup code to the new weapon object in Other_10.gml.

11. Add weapon restriction support

Edit objects/class_pickup_weapon/Step_2.gml.

This file prevents character-exclusive weapons from being picked up by the wrong character. If your new starter weapon is character-locked, add a new forbidden-weapon clause.

Pattern example:

(gun == obj_pistol_jimmy && global.character[p] != char_jimmy)

12. Add random and daily pool support

Edit:

  • objects/menu_btn_confirm_daily/Step_0.gml
  • objects/menu_char_buttonOk/Step_2.gml

These files define which characters can be chosen in:

  • daily mode
  • random character selection

If you skip these updates, your new slot may be valid in the menu but never appear in random or daily flows.

13. Add optional achievement or unlock support

Review:

  • objects/fx_corpse_boss/Create_0.gml
  • objects/class_character_swap/Step_2.gml

These files include:

  • character-specific unlock conditions
  • character-specific achievements

If your new character has no unlock state and no achievements, you can skip most of this. If it does, you need a new global unlock flag, new conditions, and likely new localization text.

Suggested implementation order

  1. Duplicate Jimmy's player object into obj_<newname>.
  2. Duplicate Jimmy's menu button object into menu_char_<newname>.
  3. Duplicate Jimmy's swap object into obj_swap_<newname>.
  4. Duplicate Jimmy's starter weapon object and pickup object.
  5. Create the new sprite family.
  6. Add a new character id macro.
  7. Add spawn support in controller_main/Step_0.gml.
  8. Add HUD portrait support in controller_main/Draw_64.gml.
  9. Add menu card and stats-panel support.
  10. Add revive hologram and swap support.
  11. Add random/daily support.
  12. Add optional unlock and achievement support.

New slot checklist

Use this as a completion checklist:

  • New char_<newname> macro exists.
  • New player object exists and inherits from class_player.
  • New player object has all sprite bindings updated.
  • New player object spawns the correct starter weapon.
  • New player object self-destructs when global.character[myPlayerId] is no longer its character id.
  • New spawn branch exists in controller_main/Step_0.gml.
  • New HUD face branch exists in controller_main/Draw_64.gml.
  • New menu button object exists and is placed in the menu.
  • New large card branch exists in menu_char_playerCard/Draw_0.gml.
  • New stat-card branch exists in menu_char_playerStat/Step_0.gml.
  • New revive hologram branch exists in obj_revival_hologram/Create_0.gml.
  • New swap branch exists in class_character_swap/Step_2.gml.
  • New hologram draw branch exists in class_character_swap/Draw_0.gml.
  • New character-exclusive weapon rules exist if needed.
  • New random/daily pool entries exist if desired.
  • New localization keys exist for the name and description.

Localization and UI text

At minimum, plan for these text keys or equivalents:

  • character display name such as GENERAL_<NAME>
  • character description such as CHARSELECT_DESC_<NAME>
  • weapon name if a new starter weapon is added
  • unlock requirement text if the slot is locked

Jimmy currently uses:

  • GENERAL_JIMMY
  • CHARSELECT_DESC_JIMMY
  • WPNAME_PISTOLJIMMY

Common failure modes

Character can be selected but does not spawn

Usually missing:

  • new branch in objects/controller_main/Step_0.gml

Character spawns but uses Jimmy art

Usually missing:

  • sprite bindings not updated in the new player object's Create_0.gml

Character swaps incorrectly or destroys itself

Usually missing:

  • character-id guard in the cloned player object's Step_1.gml
  • new branch in objects/class_character_swap/Step_2.gml

HUD portrait is blank or wrong

Usually missing:

  • new branch in objects/controller_main/Draw_64.gml

Revive station shows wrong character or fails

Usually missing:

  • new branch in objects/obj_revival_hologram/Create_0.gml

New character never appears in daily/random

Usually missing:

  • update to objects/menu_btn_confirm_daily/Step_0.gml
  • update to objects/menu_char_buttonOk/Step_2.gml

Character-specific weapon can be used by everyone

Usually missing:

  • new restriction in objects/class_pickup_weapon/Step_2.gml

Practical recommendation

If this is your first extension, do not start from scratch. Duplicate Jimmy end to end, rename the duplicate resources, and then replace the art and stats. That keeps inheritance, events, and room/object behavior aligned with how the project is already structured.