Arc Range Calculation Routine

From Final Fantasy Hacktics Wiki
Jump to navigation Jump to search
ASM duplicate of Set initial panels.

Computes and marks the tiles within range of a longbow attack.

Iterates through all tiles on the map.

  • If the tile is within 3 squares of the caster, skip.
  • Calculate the height effect on range: [(casterHeight - tileHeight)/4].
  • Checks effective distance + height effect against weapon range.
  • Marks tiles within effective range.
Calculate Arc Range
r4 = Caster Data
r5 = Weapon Range
001798b0:
00000000: 27bdffd0 addiu r29,r29,-0x0030
00000004: afb00020 sw r16,0x0020(r29)
00000008: 00808021 addu r16,r4,r0               r16 = Caster Data
0000000c: afb10024 sw r17,0x0024(r29)
00000010: afbf0028 sw r31,0x0028(r29)
00000014: 0c05e5ed jal 0x001797b4               Caster Height from Water Supports and Float
00000018: 00a08821 addu r17,r5,r0               r17 = Weapon Range
0000001c: 00401821 addu r3,r2,r0                r3 = Height Value (Return)
00000020: 920c0047 lbu r12,0x0047(r16)          r12 = Caster X
00000024: 3c02800e lui r2,0x800e
00000028: 90424ea0 lbu r2,0x4ea0(r2)            r2 = Max Map Y
0000002c: 920d0048 lbu r13,0x0048(r16)          r13 = Caster Y
00000030: 18400049 blez r2,0x00000158           Exit if Max Y is negative
00000034: 00004821 addu r9,r0,r0                r9 = Y Counter
00000038: 3c108019 lui r16,0x8019
0000003c: 2610f8cc addiu r16,r16,-0x0734        r16 = Tile Data Array (18f8cc)
00000040: 306e00ff andi r14,r3,0x00ff           r14 = CasterHeight2 (Caster's effective height, times 2)
00000044: 322500ff andi r5,r17,0x00ff           r5 = Weapon Range
00000048: 340f0001 ori r15,r0,0x0001            r15 = 0x0001
0000004c: 01a9102a slt r2,r13,r9                If Caster Y < Y Counter
00000050: 14400002 bne r2,r0,0x0000005c         Branch if True
00000054: 012d5823 subu r11,r9,r13              r11 = Y Counter - Caster Y
00000058: 01a95823 subu r11,r13,r9              r11 = Caster Y - Y Counter
0000005c: 3c02800e lui r2,0x800e
00000060: 90424e9c lbu r2,0x4e9c(r2)            r2 = Max Map X
00000064: 00000000 nop
00000068: 18400035 blez r2,0x00000140           Branch if Max X is negative
0000006c: 00004021 addu r8,r0,r0                r8 = X Counter
00000070: 0188102a slt r2,r12,r8                If Caster X < X Counter
00000074: 14400002 bne r2,r0,0x00000080         Branch if true
00000078: 010c1023 subu r2,r8,r12               r2 = X Counter - Caster X
0000007c: 01881023 subu r2,r12,r8               r2 = Caster X - Counter X
00000080: 004b5021 addu r10,r2,r11              r10 = 2D Distance to Current Position
00000084: 29420003 slti r2,r10,0x0003           If Distance < 3 (within min range)
00000088: 14400027 bne r2,r0,0x00000128         Branch if True (skip this XY position)
0000008c: 00000000 nop
00000090: 00003821 addu r7,r0,r0                r7 = Level Counter
00000094: 3c02800e lui r2,0x800e
00000098: 90424e9c lbu r2,0x4e9c(r2)            r2 = Max Map X
0000009c: 00000000 nop
000000a0: 01220018 mult r9,r2                   Y Counter * Max X
000000a4: 00071a00 sll r3,r7,0x08
000000a8: 00001012 mflo r2
000000ac: 00621821 addu r3,r3,r2                Y Counter * Max X + Level Counter
000000b0: 00683021 addu r6,r3,r8                r6 = Y Counter * Max X + Level Counter + X Counter
000000b4: 000610c0 sll r2,r6,0x03
000000b8: 00501021 addu r2,r2,r16               r2 = Current Tile Data
000000bc: 90430002 lbu r3,0x0002(r2)            Current Tile's Height (int part)
000000c0: 90440003 lbu r4,0x0003(r2)            Current Tile's Height (halves and depth)
000000c4: 90420003 lbu r2,0x0003(r2)            Current Tile's Height (halves and depth)
000000c8: 00031840 sll r3,r3,0x01
000000cc: 3084001f andi r4,r4,0x001f            r4 = Height(halves)
000000d0: 00641821 addu r3,r3,r4                r3 = Height*2 + Height(halves)
000000d4: 00021142 srl r2,r2,0x05               r2 = Height(depth)
000000d8: 00021040 sll r2,r2,0x01               r2 = Height(depth) * 2
000000dc: 00621821 addu r3,r3,r2                r3 = Height*2 + Halves + Depth*2
000000e0: 306300ff andi r3,r3,0x00ff            Cast to unsigned byte
000000e4: 01c31023 subu r2,r14,r3               r2 = Caster Height*2 - Tile Height*2
000000e8: 04410002 bgez r2,0x000000f4           If r2 is negative:
000000ec: 00000000 nop
000000f0: 24420003 addiu r2,r2,0x0003           >   r2 += 0x0003 (causes negatives to round up)
000000f4: 00021083 sra r2,r2,0x02               r2 = trunc(r2 / 4) (height effect on range)
000000f8: 01421023 subu r2,r10,r2               r2 = Distance - HeightEffect
000000fc: 00a2102a slt r2,r5,r2                 If Weapon Range < Distance - HeightEffect
00000100: 14400006 bne r2,r0,0x0000011c         Branch if True (Effective distance is still too high.)
00000104: 24e70001 addiu r7,r7,0x0001           Level Counter++
00000108: 00061080 sll r2,r6,0x02               
0000010c: 00461021 addu r2,r2,r6                r2 = Current Tile Index
00000110: 3c018019 lui r1,0x8019
00000114: 00220821 addu r1,r1,r2
00000118: a02f2dd8 sb r15,0x2dd8(r1)            AoE = 1 to Current Tile (Tile is part of Range)
0000011c: 28e20002 slti r2,r7,0x0002            If Level Counter < 2
00000120: 1440ffdc bne r2,r0,0x00000094         Loop if True (Repeat for High Tile)
00000124: 00000000 nop
00000128: 3c02800e lui r2,0x800e
0000012c: 90424e9c lbu r2,0x4e9c(r2)            r2 = Max Map X
00000130: 25080001 addiu r8,r8,0x0001           X Counter++
00000134: 0102102a slt r2,r8,r2                 If X Counter < Max X
00000138: 1440ffce bne r2,r0,0x00000074         Loop if True
0000013c: 0188102a slt r2,r12,r8                If Caster X < X Counter
00000140: 3c02800e lui r2,0x800e
00000144: 90424ea0 lbu r2,0x4ea0(r2)            r2 = Max Map Y
00000148: 25290001 addiu r9,r9,0x0001           Y Counter++
0000014c: 0122102a slt r2,r9,r2                 If Y Counter < Max Y
00000150: 1440ffbf bne r2,r0,0x00000050         Loop if True
00000154: 01a9102a slt r2,r13,r9                If Caster Y < Y Counter
00000158: 8fbf0028 lw r31,0x0028(r29)
0000015c: 8fb10024 lw r17,0x0024(r29)
00000160: 8fb00020 lw r16,0x0020(r29)
00000164: 27bd0030 addiu r29,r29,0x0030
00000168: 03e00008 jr r31
0000016c: 00000000 nop