Skip to content

Instantly share code, notes, and snippets.

@RobertTheSable
Last active August 21, 2022 23:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save RobertTheSable/448d6537acf2a2279d26c79e9cf042e4 to your computer and use it in GitHub Desktop.
Save RobertTheSable/448d6537acf2a2279d26c79e9cf042e4 to your computer and use it in GitHub Desktop.
FE3 Siege Weapons

Ranged weapons in FE3

You may have noticed that in FE3, if you hack a siege weapon in player inventories, they behave a little oddly.

If you haven't done that, here are the odd things about them:

  • Siege weapons have infinite range.
  • Their animations don't play when PC characters use them.

Here is an Asar patch that fixes animations and adds a range check to limit siege tomes to 10 range:

lorom

if read1($00FFDB) == $01
    !siegeWeaponOffenseEnable = $83B352
    !rangeWeaponEnable = $83A500
    !proceed = $83AA8E
    !checkIf2Range = $83B314
elseif read1($00FFDB) == $00
    !siegeWeaponOffenseEnable = $83B33D
    !rangeWeaponEnable = $83A4EB
    !proceed = $83AA79
    !checkIf2Range = $83B2FF
endif

ORG !checkIf2Range
    nop #4         ; asar pseudo opcode to pad 4 NOPs
                   ; the nop padding replaces a unit alignment check
                   ; if the unit is player controlled,
                   ; the range check is skipped.
                   ; prsumanbly because the devs assumed the played would never
                   ; have siege weapons
                   ; 
    lda $075F,Y    ; in vanilla this is LDA $0760
                   ; which only checks enemy weapons
                   ; the player weapon check is bypassed

ORG !siegeWeaponOffenseEnable
    lda $16 ; changed cpy #$01 -> lda $16
            ; effectivley changes from "is this an enemy attacking"
            ; to "is this unit initiating the attack"

    
; TODO: Investigate if the AI already checks distance so I can hook into that.
ORG !rangeWeaponEnable
    asl A
    asl A
    asl A
    xba 
    sep #$20
    and #$01
    cmp $07D3
    jsl checkDistance
    beq dontSelect
    lda $7F2800,x
    sta $08F2
    ; everything before this enables the range check
    lda #$02
    sta $08F3   
    ; $08F3 needs to be 1 or 2 or battle animations won't play correctly
    rep #$20
    brl proceedLabel
    nop
    nop
dontSelect:
    rep #$20
    rts 
    
ORG !proceed
proceedLabel:

; siege weapons are inifnite range by default, so I added a distance check for them
ORG $CCA6B0
checkDistance:
    php
    phx
    phy
    sep #$10
    ldy #$00
    phy
distanceLoop:
    lda $08EE,y
    sec
    sbc $085E,y
    bpl notNegative
    eor #$FF
    inc A
notNegative:
    clc
    adc 1,s
    sta 1,s
    iny
    cpy #$02
    bne distanceLoop
    pla
    cmp #$0B
    bpl outOfRange
    cmp #$03
    bmi outOfRange
    bra inRange
outOfRange:
    rep #$10
    ply
    plx
    plp
    sep #$02
    bra exitLabel
inRange:
    rep #$10
    ply
    plx
    plp
exitLabel:
    rtl

I assume that AI has some routine to check distance. But I haven't investigated that deeply so I don't know where it's located or if it can be reused here

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment