-
Notifications
You must be signed in to change notification settings - Fork 995
How to Add a New Trainer
In this tutorial we will add a new trainer to the map. Specifically, we will add a YOUNGSTER
to ROUTE_1
. We start by defining the event for when we beat this trainer so that we cannot fight him again:
...
; Route 1 events
const_next $3C0
- const EVENT_GOT_POTION_SAMPLE
+ const_skip 2
+ const EVENT_GOT_POTION_SAMPLE
+ const EVENT_BEAT_ROUTE_1_TRAINER_0
; Route 2 events
...
It's important that the new event EVENT_BEAT_ROUTE_1_TRAINER_0
is placed in the same position of the object we are going to the define in the next step: in this case, it's the 4th event of the route 1 events, which means that is the bit number 3 of the byte in position const_next $3C0
, where the first bit is the bit number 0.
Note how we needed to add a const_skip 2
to make the code treat the new event as the event number 3.
We now would like to place the character into the game map.
...
def_bg_events
- bg_event 9, 27, 3 ; Route1Text3
+ bg_event 9, 27, 4 ; Route1Text3
def_object_events
object_event 5, 24, SPRITE_YOUNGSTER, WALK, UP_DOWN, 1 ; person
object_event 15, 13, SPRITE_YOUNGSTER, WALK, LEFT_RIGHT, 2 ; person
+ object_event 10, 20, SPRITE_YOUNGSTER, STAY, RIGHT, 3, OPP_YOUNGSTER, 1
def_warps_to ROUTE_1
...
The first two numbers after object_event
are the x
and y
coordinates where the trainer will appear. We count tiles from the top left tile of the map. That is, the top left tile of the map is represented by 0, 0
. So this new trainer will appear 10
tiles to the right and 20
tiles down.
SPRITE_YOUNGSTER
indicates that the Youngster overworld sprite is used. The overworld sprites graphics are found in gfx\sprites (the graphics itself) and gfx\sprites.asm (the graphics in-game memory), the constants are found in constants\sprite_constants.asm and the SpriteSheetPointerTable
are found in data\sprites\sprites.asm.
STAY
indicates that the NPC character will not move and RIGHT
indicates the direction the trainer faces.
The 3
after RIGHT
indicates that this is the third object defined.
Important: note how the line about the bg_event
has been edited as well: this line refers to the sign present in Route 1.
Signs object always come after NPCs objects, and trainers NPCs come after non-trainer NPCs.
This is why we need to edit this number for the sign too.
OPP_<trainer class>
determines the trainer class, so we use OPP_YOUNGSTER
for adding the Youngster.
Lastly,
the number after OPP_YOUNGSTER
, 1, indicates which team this trainer will use and can be found in data\trainers\parties.asm.
Specifically, this will be the team of the first Youngster in that file.
Writing "Challenge to Battle", Defeated and Post Battle texts (note how there is not a text for the opponent's victory; in case the player gets defeated, they black out without any text being written for the opponent):
...
line "PALLET TOWN -"
cont "VIRIDIAN CITY"
done
+_Route1BattleText1::
+ text "Hi! I like shorts!"
+ line "They're comfy and"
+ cont "easy to wear!"
+ done
+_Route1EndBattleText1::
+ text "BEEEH!"
+ line "Wrong!"
+ prompt
+_Route1AfterBattleText1::
+ text "I lost, but I'm"
+ line "training hard to"
+ cont "defeated you in"
+ cont "the next round!"
+ done
Now, add _Route1BattleText1
,_Route1EndBattleText1
and _Route1AfterBattleText1
to the game's memory in scripts\Route1.asm.
In case of Route1
, also we need to add <map>TrainerHeaders
, <map>_ScriptPointers
and write a w<map>CurScript
in ram\wram.asm.
The number after EVENT_BEAT_ROUTE_1_TRAINER_0
determines the range to trainer see the player. This means that will be 4
the max to UP
, DOWN
and RIGHT
, and 5
the max to LEFT
.
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
Route1_TextPointers:
dw Route1Text1
dw Route1Text2
- dw Route1Text3
+ dw Route1Text4
+ dw Route1Text3 ; note how text3 is now AFTER text4, because text3 is the one related to the sign, which must be AFTER the trainers' texts
+Route1TrainerHeaders:
+ def_trainers 3
+Route1TrainerHeader0:
+ trainer EVENT_BEAT_ROUTE_1_TRAINER_0, 4, Route1BattleText1, Route1EndBattleText1, Route1AfterBattleText1
+ db -1 ; end
Route1Text1:
text_asm
...
...
Route1Text3:
text_far _Route1Text3
text_end
+Route1Text4:
+ 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
Note how text3 is now AFTER text4, because text3 is the one related to the sign, which must be AFTER the trainers' texts.
Also, note the def_trainers 3
: this has to be 3 because this trainer is the 3rd object defined in the map; the first two objects are the non-trainer NPCs, and the 4th object is the sign.
This number 3 has to match the bit number of the event associated with this trainer, in order for the sight of the trainer to work properly.
...
ds 1
wBluesHouseCurScript:: db
wViridianCityCurScript:: db
- ds 2
+wRoute1CurScript:: db
+ ds 1
wPewterCityCurScript:: db
wRoute3CurScript:: db
wRoute4CurScript:: db
...
And with this we're done! Enjoy your new trainer and your romhacking :)