Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- @ the whole headbutt tree system
- @ it implements jpan's behavior byte hack as well as the headbutt system in the space that the old routine took up. when he said it was overly inefficient, he meant it!
- @ compile this and then go to the offset 0x806D1F0 in the resulting .bin output. copy everything there until the next block of zeros. paste it to offset 0x6D1F0 in your rom.
- @ there are various parameters you can play around with. most of these are primarily the tables halfway through this.
- @ i tried to comment it throughout!
- @ now, in amap, there's the one field that is primarily used in wild encounter spots. it's 2 when wild grass and 4 when surfing on water encounters.
- @ because we won't be walking on the headbutt tree, we can use this field to our advantage.
- @ cur_mapdata_block_get_field_at(s16 x, s16 y, u8 field) references a bunch of other routines, but eventually, it boils down to a bunch of preset fields or'd with the header info.
- @ the first is 0x1FF, or the 9 least significant bits. this is the behavior byte itself.
- @ the second is 0x3E00, or the next 5 bits in terms of significance. this allows for 2^5 (32) bits for use for our table.
- @ note that the entry entered in this table should be multiplied by 2 because of the way that amap (incorrectly) displays the data. this allows the code below to reference it properly.
- @ screens are given in the post.
- .text
- .align 2
- .thumb
- .thumb_func
- .org 0x08044EC8
- @ returns r0 = pseudorandom number
- random:
- .hword 0x4A04
- .org 0x08058F48
- @ returns r0 = (metatile behavior long or blockinfo_bit_masks[field]) >> blockinfo_bit_right_shift_num[field]
- cur_mapdata_block_get_field_at: @ (s16 x, s16 y, u8 field)
- push {r4, lr}
- .org 0x0806CE38
- @ writes the next pos and height to the pointer given in r0
- player_get_next_pos_and_height: @ (*[s16 x, s16 y, u8 height])
- push {r4, r5, lr}
- .org 0x0806D1F0
- @ this assembly routine is a modded version of jpan's behavior byte hack that decreases space required for the table while slightly increasing what's needed for the code
- onpress_a_get_script_tile:
- lsl r1, r1, #0x18
- lsr r0, r1, #0x18
- cmp r0, #0x80
- blt _not_governed @ we don't care about entries less than h80
- sub r0, r0, #0x80
- lsl r0, r0, #0x2
- ldr r1, behavior_table_ref @ load the table pointer here
- add r0, r0, r1
- ldr r0, [r0] @ load the script pointer here
- b _return_loc
- _not_governed:
- mov r0, #0
- _return_loc:
- mov pc, lr
- .align 2
- behavior_table_ref:
- .word behavior_table
- behavior_table: @ for the playerfacing behaviors
- .word 0
- .word 0x081A7606 @ bookshelf
- .word 0x081A760F @ market shelf
- .word 0x081A6955 @ pc
- .word 0
- .word 0x081A6C32 @ town map
- .word 0x081A764E @ tv
- .word 0x081A76E7 @ pokemon center
- .word 0x081A76DE @ pokemon mart
- .word 0x081A7657 @ cabinet
- .word 0x081A7660 @ cooking smells great!
- .word 0x081A7669 @ dresser
- .word 0x081A7672 @ snacks
- .word 0x081BBFD8 @ wireless
- .word 0x081BB8A7 @ not available
- .word 0x081A7702 @ questionnaire
- @ 0x90
- .word 0x081A7618 @ fridge
- .word 0x081A76F0 @ indigo plateau
- .word 0x081A76F9 @ indigo plateau 2
- .word 0x081A763C @ blueprint
- .word 0x081A767B @ pokemon pics
- .word 0x081A7684 @ complex machine. better not touch it!
- .word 0x081A768D @ telephone
- .word 0x081A762A @ complex numbers
- .word 0x081A7696 @ ads
- .word 0x081A769F @ tasty food
- .word 0x081A76A8 @ trash can
- .word 0x081A76B1 @ cup
- .word 0
- .word 0
- .word 0x081A76CC @ lights
- .word 0x081A76D5 @ tools
- @ 0xA0
- .word 0x081A7633 @ random machine
- .word 0x081A7621 @ consoles
- .word 0x081A7645 @ robbery
- .word 0x081C549C @ timer
- @ now, i personally added headbutt_script here, but it can go in any one of the zeros above. just make sure that you note the entry correctly!
- .word headbutt_script @ headbutt tree behavior byte (0xA4)
- .equ table_amount, 3
- .equ terminate, 0xFE @ only rule here is that it isn't a pokemon you want to appear in a tree. if you wanted to use pokemon index 254, go for it i guess, but change this
- .equ var_begin, 0x020270B8
- headbutt_tree:
- push {r4-r6, lr}
- ldr r0, var_8000 @ position_ptr
- @ the below branch will store the position in front of the player's x in var_8000, y in var_8001, and the height in the most significant byte of var_8002
- @ this is because it writes to the pointer in r0
- bl player_get_next_pos_and_height
- ldr r4, var_8000
- ldrh r0, [r4] @ x
- ldrh r1, [r4, #2] @ y
- mov r2, #1 @ field id
- @ the field entry 1 is 5 bits of the second behavior byte thing in advancemap. this means we can have up to 32 headbutt tables denoted by even numbers from 0-64 in amap.
- @ this is explained further above
- bl cur_mapdata_block_get_field_at
- lsl r0, r0, #0x18
- lsr r4, r0, #0x18 @ r4 = table number
- @ part below catches invalid tables and prevents them from working
- cmp r4, #table_amount
- bge _nothingfell
- ldr r0, tableoftables_ref
- lsl r1, r4, #2 @ r1 = table number * 4
- ldr r4, [r0, r1] @ r4 = table pointer to the relevant one
- @ below, generate a random number less than 100 to emulate chance
- bl random @ r0 = random()
- mov r1, #100
- bl __umodsi3 @ r0 = r0 % 100
- mov r5, #0 @ set up the loop counter
- ldr r6, terminate_byte
- @ at this point, r0 = random() % 100, r4 = table pointer, r5 = loop counter, r6 = terminator
- _loop:
- mov r1, #7 @ 7 being the size of each entry
- mul r1, r5, r1
- add r3, r4, r1 @ store the current entry's pointer in r3
- ldrh r2, [r3] @ seems to be very finicky at times, loading random values from the surroundings?
- lsl r2, r2, #0x10
- lsr r2, r2, #0x10
- cmp r2, r6
- beq _nothingfell
- ldrb r2, [r3, #6] @ load the chance of this entry into r2
- cmp r0, r2
- ble _somethingfell
- add r5, r5, #1 @ increment the loop counter
- b _loop
- _somethingfell:
- mov r4, r3
- @ at this point, r4 is the table entry we care about. don't touch it
- bl random @ generate a new random number
- @ r0 = random()
- ldrb r2, [r4, #2] @ load the lower level
- ldrb r1, [r4, #3] @ load the higher level
- sub r1, r1, r2 @ subtract the lower level from the higher level, store it as the parameter for modulo
- bl __umodsi3
- @ r0 = random() % (highlevel - lowlevel)
- ldrb r2, [r4, #2] @ load the lower level again bc umodsi ****in w the value
- add r1, r0, r2 @ level parameter
- ldrh r0, [r4] @ species parameter
- ldrh r2, [r4, #4] @ item parameter
- bl create_scripted_mon
- ldr r0, var_8000
- mov r1, #0
- strh r1, [r0, #0x18] @ store 0 into var_800D
- b _end
- _nothingfell:
- ldr r0, var_8000
- mov r1, #0xFF
- strh r1, [r0, #0x18] @ store 0xFF into var_800D
- _end:
- pop {r4-r6}
- pop {r1} @ this is the return method used by many of the script stuff so
- bx r1
- .align 2
- @ used to store the position struct
- var_8000:
- .word (var_begin + (0x8000 * 2))
- terminate_byte:
- .word terminate
- tableoftables_ref:
- .word tableoftables
- @ note that, in order to expand the tables, you need to add another entry here for each of the tables.
- tableoftables:
- .word lowencounter
- .word medencounter
- .word highencounter
- @ bunch of defines to make the below better readable
- .equ caterpie, 10
- .equ metapod, 11
- .equ butterfree, 12
- .equ weedle, 13
- .equ kakuna, 14
- .equ beedrill, 15
- .equ exeggcute, 102
- .equ exeggutor, 103
- .equ tangela, 114
- .equ pinsir, 127
- .equ snorlax, 143
- .equ pineco, 204
- .equ heracross, 214
- @ a sample item
- .equ brightpowder, 179
- @.org 0x08XXXXXX @ optional repoint of the tables below in case you want a higher amount of pokemon.
- @ here's the table format:
- @ [2 bytes - species] [1 byte - lower level] [1 byte - higher level] [2 bytes] - item it can hold] [1 byte - chance it will appear]
- @ the chance byte at the very end is subtracted from the previous entry in the tables in order to get that specific entry's chance of showing up.
- @ sample entries are below:
- lowencounter:
- .hword weedle @ species
- .byte 5 @ lower level
- .byte 7 @ higher level
- .hword brightpowder @ item
- .byte 20 @ chance
- .hword kakuna @ species
- .byte 12 @ lower level
- .byte 15 @ higher level
- .hword 0 @ no item
- .byte 40 @ chance: 40 - 20 (weedle's entry above) = 20
- .hword beedrill
- .byte 60
- .byte 70
- .hword brightpowder
- .byte 100 @ chance: 100 - 40 (kakuna's entry above) = 60
- .hword terminate
- @ this table represents an instance where we don't have to get a pokemon 100% of the time. the code handles it!
- medencounter:
- .hword caterpie
- .byte 5
- .byte 7
- .hword brightpowder
- .byte 35
- .hword metapod
- .byte 12
- .byte 15
- .hword 0
- .byte 45
- .hword butterfree
- .byte 60
- .byte 70
- .hword brightpowder
- .byte 50
- .hword terminate
- @ 50% of the time, a pokemon won't fall.
- highencounter:
- .hword exeggcute
- .byte 10
- .byte 12
- .hword 0
- .byte 40
- .hword tangela
- .byte 20
- .byte 25
- .hword 0
- .byte 60
- .hword heracross
- .byte 17
- .byte 22
- .hword brightpowder
- .byte 90
- .hword snorlax
- .byte 50
- .byte 60
- .hword brightpowder
- .byte 100
- .hword terminate
- @ optional insert of the script. there's still about hB0 bytes left over after the script is inserted, allowing for about 19 EXTRA mon entries (on top of the 10 there already)
- @ repoint if so desired. the assembly will take care of it!
- @.org 0x08XXXXXX
- .equ headbutt, 0x1D
- .equ lastresult, 0x800D
- headbutt_script: @ this is included here for the dynamic compiling so that you don't have to care. feel free to edit it though
- .byte 0x6A
- .byte 0x7C
- .hword headbutt
- .byte 0x21
- .hword lastresult
- .hword 0x06
- .byte 0x06
- .byte 0x01
- .word no_headbutt_in_party
- .byte 0x9D
- .byte 0x00
- .hword lastresult
- .byte 0x7F
- .byte 0x00
- .hword lastresult
- .byte 0x82
- .byte 0x01
- .hword headbutt
- .byte 0x0F
- .byte 0x00
- .word text_headbutt_in_party
- .byte 0x09
- .byte 0x05
- .byte 0x21
- .hword lastresult
- .hword 0x00
- .byte 0x06
- .byte 0x01
- .word said_no
- .byte 0x0F
- .byte 0x00
- .word text_poke_used_atk
- .byte 0x09
- .byte 0x04
- .byte 0x68
- .byte 0x9C
- .hword 0x2
- .byte 0x27
- @ the callasm is here
- .byte 0x23
- .word headbutt_tree + 1
- @ this comparison here prevents the dowildbattle from happening if lastresult is 0xFF (the chance was higher than the highest chance defined in the table)
- @ lastresult's modification is in the assembly above
- .byte 0x21
- .hword lastresult
- .hword 0xFF
- .byte 0x06
- .byte 0x01
- .word tree_was_undisturbed
- .byte 0x0F
- .byte 0x00
- .word text_exclamation
- .byte 0x09
- .byte 0x06
- .byte 0xB7
- .byte 0x6C
- .byte 0x02
- .byte 0xFF
- no_headbutt_in_party:
- .byte 0x0F
- .byte 0x00
- .word text_cant_headbutt
- .byte 0x09
- .byte 0x06
- .byte 0x6C
- .byte 0x02
- .byte 0xFF
- said_no: @ closes the textbox
- .byte 0x68
- .byte 0x6C
- .byte 0x02
- .byte 0xFF
- tree_was_undisturbed:
- .byte 0x0F
- .byte 0x00
- .word text_tree_undisturbed
- .byte 0x09
- .byte 0x06
- .byte 0x6C
- .byte 0x02
- .byte 0xFF
- text_headbutt_in_party: @ This tree can be headbutted! Would you like to use headbutt?
- .byte 0xCE
- .byte 0xDC
- .byte 0xDD
- .byte 0xE7
- .byte 0x00
- .byte 0xE8
- .byte 0xE6
- .byte 0xD9
- .byte 0xD9
- .byte 0x00
- .byte 0xD7
- .byte 0xD5
- .byte 0xE2
- .byte 0x00
- .byte 0xD6
- .byte 0xD9
- .byte 0x00
- .byte 0xDC
- .byte 0xD9
- .byte 0xD5
- .byte 0xD8
- .byte 0xD6
- .byte 0xE9
- .byte 0xE8
- .byte 0xE8
- .byte 0xD9
- .byte 0xD8
- .byte 0xAB
- .byte 0xFE
- .byte 0xD1
- .byte 0xE3
- .byte 0xE9
- .byte 0xE0
- .byte 0xD8
- .byte 0x00
- .byte 0xED
- .byte 0xE3
- .byte 0xE9
- .byte 0x00
- .byte 0xE0
- .byte 0xDD
- .byte 0xDF
- .byte 0xD9
- .byte 0x00
- .byte 0xE8
- .byte 0xE3
- .byte 0x00
- .byte 0xE9
- .byte 0xE7
- .byte 0xD9
- .byte 0x00
- .byte 0xC2
- .byte 0xD9
- .byte 0xD5
- .byte 0xD8
- .byte 0xD6
- .byte 0xE9
- .byte 0xE8
- .byte 0xE8
- .byte 0xAC
- .byte 0xFF
- .byte 0x00
- .byte 0xFF
- text_poke_used_atk: @ [string1] used [string2]!
- .byte 0xFD
- .byte 0x02
- .byte 0x00
- .byte 0xE9
- .byte 0xE7
- .byte 0xD9
- .byte 0xD8
- .byte 0x00
- .byte 0xFD
- .byte 0x03
- .byte 0xAB
- .byte 0xFF
- .byte 0x00
- .byte 0xFF
- text_exclamation: @ Whoa!
- .byte 0xD1
- .byte 0xDC
- .byte 0xE3
- .byte 0xD5
- .byte 0xAB
- .byte 0xFF
- .byte 0x00
- .byte 0xFF
- text_cant_headbutt: @ This tree looks like Pokémon can live in it.
- .byte 0xCE
- .byte 0xDC
- .byte 0xDD
- .byte 0xE7
- .byte 0x00
- .byte 0xE8
- .byte 0xE6
- .byte 0xD9
- .byte 0xD9
- .byte 0x00
- .byte 0xE0
- .byte 0xE3
- .byte 0xE3
- .byte 0xDF
- .byte 0xE7
- .byte 0x00
- .byte 0xE0
- .byte 0xDD
- .byte 0xDF
- .byte 0xD9
- .byte 0x00
- .byte 0xCA
- .byte 0xE3
- .byte 0xDF
- .byte 0x1B
- .byte 0xE1
- .byte 0xE3
- .byte 0xE2
- .byte 0x00
- .byte 0xD7
- .byte 0xD5
- .byte 0xE2
- .byte 0xFE
- .byte 0xE0
- .byte 0xDD
- .byte 0xEA
- .byte 0xD9
- .byte 0x00
- .byte 0xDD
- .byte 0xE2
- .byte 0x00
- .byte 0xDD
- .byte 0xE8
- .byte 0xAD
- .byte 0xFF
- .byte 0x00
- .byte 0xFF
- text_tree_undisturbed: @ But the tree remained undisturbed...
- .byte 0xBC
- .byte 0xE9
- .byte 0xE8
- .byte 0x00
- .byte 0xE8
- .byte 0xDC
- .byte 0xD9
- .byte 0x00
- .byte 0xE8
- .byte 0xE6
- .byte 0xD9
- .byte 0xD9
- .byte 0x00
- .byte 0xE6
- .byte 0xD9
- .byte 0xE1
- .byte 0xD5
- .byte 0xDD
- .byte 0xE2
- .byte 0xD9
- .byte 0xD8
- .byte 0xFE
- .byte 0xE9
- .byte 0xE2
- .byte 0xD8
- .byte 0xDD
- .byte 0xE7
- .byte 0xE8
- .byte 0xE9
- .byte 0xE6
- .byte 0xD6
- .byte 0xD9
- .byte 0xD8
- .byte 0xAD
- .byte 0xAD
- .byte 0xAD
- .byte 0xFF
- .byte 0x00
- .org 0x080A029C
- create_scripted_mon: @ (u16 species, u8 level, u16 item)
- push {r4-r7, lr}
- .org 0x081E4684
- @ returns r0 = dividend % divisor
- __umodsi3: @ (u16 dividend, u16 divisor)
- cmp r1, #0
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement