Thread: Development: Trainers with EVs
View Single Post
  #1    
Old August 20th, 2013 (8:09 PM). Edited August 26th, 2013 by DoesntKnowHowToPlay.
DoesntKnowHowToPlay's Avatar
DoesntKnowHowToPlay DoesntKnowHowToPlay is offline
Tiny Umbrella with Lots and Lots of Good
     
    Join Date: Jan 2012
    Posts: 258
    I see a lot of talk about how to make hacks "difficult". The typical solutions are to:

    -give trainers teams full of legendaries
    -make the level curve absurdly steep
    -inflate the base stats of everything
    -give the AI illegal moves and custom attacks with absurd BP
    -make every dungeon a flash maze where you can't use flash

    Because I hate everyone who plays romhacks for fun am a nice person, I've decided to release a bit of code that gives us another option- letting trainer pokemon have custom EVs. Normally, trainer pokemon have 0 EVs in every stat outside of the RSE Battle Tower/Frontier.

    First you will need to insert this ASM:

    Fire Red:
    Spoiler:
    Code:
    #EV spread table format
    #Each spread is 16 bytes
    #0x0 = Nature
    #0x4 = IVs (from 0-31, not 0-255, used for all IVs)
    # (if you want hidden powers, recall the ai can't handle -- bp moves)
    #0x5 = HP EVs
    #0x6 = Atk EVs
    #0x7 = Def EVs
    #0x8 = Speed EVs
    #0x9 = SAtk EVs
    #0xA = SDef EVs
    #0xB = Pokeball
    #last four bytes are filler
    
    .align 2
    .thumb
    .thumb_func
    
    .org 0x115f6
    mov r0, r1
    mov r6, r0
    b 0x11604
    
    .org 0x1162c
    ldr r0, .Method_Addr
    bx r0
    
    .Method_Addr: .word 0x08F90001
    
    .org 0x3dc70
    b 0x3dcd0
    
    
    .org 0xF90000
    
    LoadItem:
    add r5, #0x6
    add r0, r4, #0x0
    mov r1, #0xc
    add r2, r5, #0x0
    bl Insert_Element
    
    LoadHPEV:
    lsl r0, r6, #0x4
    ldr r2, .EV_Table
    add r2, r0
    add r2, #0x5
    mov r1, #0x1A
    mov r0, r4
    bl Insert_Element
    
    LoadAtkEV:
    lsl r0, r6, #0x4
    ldr r2, .EV_Table
    add r2, r0
    add r2, #0x6
    mov r1, #0x1B
    mov r0, r4
    bl Insert_Element
    
    LoadDefEV:
    lsl r0, r6, #0x4
    ldr r2, .EV_Table
    add r2, r0
    add r2, #0x7
    mov r1, #0x1C
    mov r0, r4
    bl Insert_Element
    
    LoadSpeedEV:
    lsl r0, r6, #0x4
    ldr r2, .EV_Table
    add r2, r0
    add r2, #0x8
    mov r1, #0x1D
    mov r0, r4
    bl Insert_Element
    
    LoadSAtkEV:
    lsl r0, r6, #0x4
    ldr r2, .EV_Table
    add r2, r0
    add r2, #0x9
    mov r1, #0x1E
    mov r0, r4
    bl Insert_Element
    
    LoadSDefEV:
    lsl r0, r6, #0x4
    ldr r2, .EV_Table
    add r2, r0
    add r2, #0xA
    mov r1, #0x1F
    mov r0, r4
    bl Insert_Element
    
    LoadBall:
    lsl r0, r6, #0x4
    ldr r2, .EV_Table
    add r2, r0
    add r2, #0xB
    mov r1, #0x26
    mov r0, r4
    bl Insert_Element
    
    StartNatureLoop:
    lsl r0, r6, #0x4
    ldr r2, .EV_Table
    add r2, r0
    ldrb r5, [r2, #0x0]
    cmp r5, #0x0
    beq LoadIVs
    ldr r0, [r4, #0x0]
    ldr r1, [r4, #0x4]
    eor r1, r0, r1
    str r1, [r4, #0x4]
    
    NatureLoop:
    ldr r0, [r4, #0x0]
    add r0, r0, #0x18
    str r0, [r4, #0x0]
    mov r1, #0x19
    bl Mod
    cmp r0, r5
    bne NatureLoop
    
    EndNatureLoop:
    ldr r0, [r4, #0x0]
    ldr r1, [r4, #0x4]
    eor r1, r0, r1
    str r1, [r4, #0x4]
    
    LoadIVs:
    lsl r0, r6, #0x4
    ldr r2, .EV_Table
    add r2, r0
    ldrb r6, [r2, #0x4]
    push {r6}
    
    StartIVLoop:
    mov r5, #0x27
    
    IVLoop:
    mov r0, r4
    mov r1, r5
    mov r2, sp
    bl Insert_Element
    add r5, r5, #0x1
    cmp r5, #0x2D
    bne IVLoop
    
    End:
    pop {r6}
    bl Recalculate_Stats
    ldr r1, .Return_Addr
    bx r1
    
    Insert_Element:
    ldr r3, .Insert_Addr
    bx r3
    
    Recalculate_Stats:
    mov r0, r4
    ldr r1, .Recalc_Addr
    bx r1
    
    Mod:
    ldr r3, .Mod_Addr
    bx r3
    
    .align 2
    .Return_Addr: .word 0x08011639
    .EV_Table: .word 0x08F00000
    .Insert_Addr: .word 0x0804037d
    .Recalc_Addr: .word 0x0803e47d
    .Mod_Addr: .word 0x081e4685


    Emerald:
    Spoiler:
    Code:
    #EV spread table format
    #Each spread is 16 bytes
    #0x0 = Nature
    #0x4 = IVs (from 0-31, not 0-255, used for all IVs)
    # (if you want hidden powers, recall the ai can't handle -- bp moves)
    #0x5 = HP EVs
    #0x6 = Atk EVs
    #0x7 = Def EVs
    #0x8 = Speed EVs
    #0x9 = SAtk EVs
    #0xA = SDef EVs
    #0xB = Pokeball
    #last four bytes are filler
    
    .align 2
    .thumb
    .thumb_func
    
    .org 0x38936
    mov r0, r1
    mov r6, r0
    b 0x38944
    
    .org 0x3896c
    ldr r0, .Method_Addr
    bx r0
    
    .Method_Addr: .word 0x08F90001
    
    .org 0x67d68
    b 0x67dc8
    
    .org 0xF90000
    
    LoadItem:
    add r5, #0x6
    add r0, r4, #0x0
    mov r1, #0xc
    add r2, r5, #0x0
    bl Insert_Element
    
    LoadHPEV:
    lsl r0, r6, #0x4
    ldr r2, .EV_Table
    add r2, r0
    add r2, #0x5
    mov r1, #0x1A
    mov r0, r4
    bl Insert_Element
    
    LoadAtkEV:
    lsl r0, r6, #0x4
    ldr r2, .EV_Table
    add r2, r0
    add r2, #0x6
    mov r1, #0x1B
    mov r0, r4
    bl Insert_Element
    
    LoadDefEV:
    lsl r0, r6, #0x4
    ldr r2, .EV_Table
    add r2, r0
    add r2, #0x7
    mov r1, #0x1C
    mov r0, r4
    bl Insert_Element
    
    LoadSpeedEV:
    lsl r0, r6, #0x4
    ldr r2, .EV_Table
    add r2, r0
    add r2, #0x8
    mov r1, #0x1D
    mov r0, r4
    bl Insert_Element
    
    LoadSAtkEV:
    lsl r0, r6, #0x4
    ldr r2, .EV_Table
    add r2, r0
    add r2, #0x9
    mov r1, #0x1E
    mov r0, r4
    bl Insert_Element
    
    LoadSDefEV:
    lsl r0, r6, #0x4
    ldr r2, .EV_Table
    add r2, r0
    add r2, #0xA
    mov r1, #0x1F
    mov r0, r4
    bl Insert_Element
    
    LoadBall:
    lsl r0, r6, #0x4
    ldr r2, .EV_Table
    add r2, r0
    add r2, #0xB
    mov r1, #0x26
    mov r0, r4
    bl Insert_Element
    
    StartNatureLoop:
    lsl r0, r6, #0x4
    ldr r2, .EV_Table
    add r2, r0
    ldrb r5, [r2, #0x0]
    cmp r5, #0x0
    beq LoadIVs
    ldr r0, [r4, #0x0]
    ldr r1, [r4, #0x4]
    eor r1, r0, r1
    str r1, [r4, #0x4]
    
    NatureLoop:
    ldr r0, [r4, #0x0]
    add r0, r0, #0x18
    str r0, [r4, #0x0]
    mov r1, #0x19
    bl Mod
    cmp r0, r5
    bne NatureLoop
    
    EndNatureLoop:
    ldr r0, [r4, #0x0]
    ldr r1, [r4, #0x4]
    eor r1, r0, r1
    str r1, [r4, #0x4]
    
    LoadIVs:
    lsl r0, r6, #0x4
    ldr r2, .EV_Table
    add r2, r0
    ldrb r6, [r2, #0x4]
    push {r6}
    
    StartIVLoop:
    mov r5, #0x27
    
    IVLoop:
    mov r0, r4
    mov r1, r5
    mov r2, sp
    bl Insert_Element
    add r5, r5, #0x1
    cmp r5, #0x2D
    bne IVLoop
    
    End:
    pop {r6}
    bl Recalculate_Stats
    ldr r1, .Return_Addr
    bx r1
    
    Insert_Element:
    ldr r3, .Insert_Addr
    bx r3
    
    Recalculate_Stats:
    mov r0, r4
    ldr r1, .Recalc_Addr
    bx r1
    
    Mod:
    ldr r3, .Mod_Addr
    bx r3
    
    .align 2
    .Return_Addr: .word 0x08038979
    .EV_Table: .word 0x08EF0000
    .Insert_Addr: .word 0x0806acad
    .Recalc_Addr: .word 0x08068d0d
    .Mod_Addr: .word 0x082e7be1


    The bulk of this code is at xF90000- that part doesn't have to go there, it can be moved to wherever you have free space. Just make sure you change Method_Addr to whatever you change the offset to + 1.

    You will also need to find x1000 bytes of space, and change the .EV_Table variable in the method to point to it (I used xF00000). This is where the spreads will go. The method gives you 256 spreads to use- this is not full control, but it is more than you are likely to need (the Emerald Battle Frontier only uses around 36 IIRC). The EV Spread table format is:

    - Nature
    - 3 unused bytes
    - HP EV
    - Attack EV
    - Defense EV
    - Speed EV
    - Special Attack EV
    - Special Defense EV
    - What pokeball the mon comes out in
    - 4 more unused bytes (I may update the method later to do something with these)

    To assign an EV spread to a trainer's pokemon, set the value that was formerly their IVs to which slot in the table you want that pokemon to use. If you are using A-Trainer, this value is erroneously marked as AI Value. Note that the method only works for trainers with custom movesets and items- if they use default movesets or items, it will only affect IVs. It will still work if you manually give the trainer the moves it would have by default or explicitly define their mons as being empty-handed though.

    This hack now allows custom natures. The natures are enumerated like so:
    x0 - Arbitrary
    x1 - Lonely (+Atk, -Def)
    x2 - Brave (+Atk, -Speed)
    x3 - Adamant (+Atk, -SpAtk)
    x4 - Naughty (+Atk, -SpDef)
    x5 - Bold (+Def, -Atk)
    x6 - Docile (Neutral)
    x7 - Relaxed (+Def, -Speed)
    x8 - Impish (+Def, -SpAtk)
    x9 - Lax (+Def, -SpDef)
    xA - Timid (+Speed, -Atk)
    xB - Hasty (+Speed, -Def)
    xC - Serious (Neutral)
    xD - Jolly (+Speed, -SpAtk)
    xE - Naive (+Speed, -SpDef)
    xF - Modest (+SpAtk, -Atk)
    x10 - Mild (+SpAtk, -Def)
    x11 - Quiet (+SpAtk, -Speed)
    x12 - Bashful (Neutral)
    x13 - Rash (+SpAtk, -SpDef)
    x14 - Calm (+SpDef, -Atk)
    x15 - Gentle (+SpDef, -Def)
    x16 - Sassy (+SpDef, -Speed)
    x17 - Careful (+SpDef, -SpAtk)
    x18 - Quirky (Neutral)

    Hardy is unavailable due to the way the method works, but that doesn't really matter since it's neutral. Higher values will crash the game. If 0 is used, the method does not touch nature, so it will be determined semi-randomly like normally.

    It is worth nothing that this method allows you to give trainer pokemon more than 510 EVs if you are feeling exceptionally rude.
    __________________

    Yet Another Fire Red Hack

    Physical/Special Split
    Reply With Quote