Adding a new trainer - elementzero23/pokered GitHub Wiki

In this tutorial we will look at how to add a trainer. I will show how to add a trainer to Route 1.

Contents

1. Add the trainer object

Open the file /data/maps/objects/Route1.asm. Trainers must go first so we shift everything up by 1.

    def_bg_events
-	bg_event  9, 27, 3 ; Route1Text4
+       bg_event  9, 27, 4 ; Route1Text4

    def_object_events
+	object_event  4, 28, SPRITE_YOUNGSTER, STAY, RIGHT, 1, OPP_YOUNGSTER, 14 ; trainer 0
-	object_event  5, 24, SPRITE_YOUNGSTER, WALK, UP_DOWN, 1 ; person
+       object_event  5, 24, SPRITE_YOUNGSTER, WALK, UP_DOWN, 2 ; person
-	object_event 15, 13, SPRITE_YOUNGSTER, WALK, LEFT_RIGHT, 2 ; person
+	object_event 15, 13, SPRITE_YOUNGSTER, WALK, LEFT_RIGHT, 3 ; person

The meaning of the arguments are:

  • 4, 28 are the coordinates of that object on the map,
  • SPRITE_YOUNGSTER is the sprite ID (what sprite to use),
  • STAY is the movement (could be WALK but I don't know how this affects trainers),
  • RIGHT is the viewing direction (if you put in WALK before, it would be the walking range, see /constants/map_object_constants.asm),
  • 1 is the text ID, but you can see it as an object ID on that map meaning this one is the first object,
  • OPP_YOUNGSTER is the trainer class (see next step),
  • 14 is the trainer party number. We will see to that in the next step.

2. Define the trainer's party

Open the file /data/trainers/parties.asm. Here you can add and edit the parties of the trainers. Since we picked OPP_YOUNGSTER go to the YoungsterData section and add an entry at the very end:

 ; Unused
     db 17, SPEAROW, RATTATA, RATTATA, SPEAROW, 0
+; Route 1
+    db 3, RATTATA, 0

This is the 14th line under YoungsterData. This number corresponds to the last argument of the object macro explained before. If you put in $FF as first argument of the line, you can define individual levels for each pokémon, see the example below. Otherwise, the first number is the level for all the pokémon in the party. The lines always have to end with 0.

db $FF, 3, RATTATA, 4, PIDGEY, 0

3. Add the trainer script

Open the file /scripts/Route1.asm. At the beginning must be the following sections:

    Route1_Script:
-       jp EnableAutoTextBoxDrawing
+       call EnableAutoTextBoxDrawing
+       ld hl, Route1TrainerHeaders
+       ld de, Route1_ScriptPointers
+       ld a, [wRoute1CurScript]
+       call ExecuteCurMapScriptInTable
+       ld [wRoute1CurScript], a
+       ret

+   Route1_ScriptPointers:
+       dw CheckFightingMapTrainers
+       dw DisplayEnemyTrainerTextAndStartBattle
+       dw EndTrainerBattle

Of course, we want the trainer to talk to us so put in a text pointer next. Remember, trainers go first, so we need to shift everything up by 1 later on.

    Route1_TextPointers:
        dw Route1Text1
        dw Route1Text2
        dw Route1Text3
+       dw Route1Text4

Define the trainer header:

+   Route1TrainerHeaders:
+       def_trainers
+   Route1TrainerHeader0:
+       trainer EVENT_BEAT_ROUTE_1_TRAINER_0, 2, Route1BattleText1, Route1EndBattleText1, Route1AfterBattleText1
+       db -1 ; end
  • EVENT_BEAT_PALLET_ROUTE_1_TRAINER_0 is the event flag which indicates if you have already beaten that trainer. We will see to that later.
  • 2 is the view range.
  • The next arguments are the text just before the battle, the text at the end of the battle and the text the trainer says if you talk to him again later.

To complete the scripts file add the text pointers:

+   Route1Text1:
+       text_asm
+       ld hl, Route1TrainerHeader0
+       call TalkToTrainer
+       jp TextScriptEnd

+   Route1BattleText1:
+       text_far _Route1BattleText1
+       text_end

+   Route1EndBattleText1:
+       text_far _Route1EndBattleText1
+       text_end

+   Route1AfterBattleText1:
+       text_far _Route1AfterBattleText1
+       text_end

Then shift up every text pointer by 1:

-   Route1Text1:
+   Route1Text2:
-   Route1Text2:
+   Route1Text3:
-   Route1Text3:
+   Route1Text4:

Note: You can leave the text pointers marked by an underscore as they are. In this case Route1Text2 refers to _Route1Text1 in the text file as explained in the next step. I would recommend you keep everything consistent, though.

4. Add text for the trainer

Create the file /text/Route1.asm and add the three text pointers defined in the previous step:

+_Route1BattleText1::
+    text "Hey! You have"
+    line "#MON! Come on!"
+    cont "Let's battle'em!"
+    done

+_Route1EndBattleText1::
+    text "No!"
+    line "I lost!"
+    cont "Nooo!"
+    done

+_Route1AfterBattleText1::
+    text "Ssh! Go away! You"
+    line "already beat me!"
+    done

5. Make room for the script pointer index

Open the file /wram.asm. If you added a trainer on a map that already has an entry like wRoute18Gate1FCurScript:: you can skip this step.

There you should look for skipped bits. They are indicated by ds XX after an empty line. Remove one ds line and add a new one like this:

 wPalletTownCurScript:: db
- 	 ds 1
+wRoute1CurScript:: db

6. Define a custom event constant

Open the file /constants/event_constants.asm. Go to the end of the file and add a new event section.

; Route 1 events
	const_next $3C0
	const EVENT_GOT_POTION_SAMPLE
+	const EVENT_BEAT_ROUTE_1_TRAINER_0

Note that if you add a trainer on a completely new map you do this at the end of all the map event sections. In this case look up the value of const_next of the last map event section and add a number at least as big as the number of lines (including skipped ones) for the map event section. If you place it after Seafoam Islands events which has const_next $9C0 and 27 lines in its map event section you have to use something like $9DC as const_next in your new map event section.

7. Recompile

That's it! Now you should be able to fight the youngster on Route 1.