Find Unit Abilities or Skillsets
Jump to navigation
Jump to search
# ROUTINE: FIND UNIT ABILITIES OR SKILLSETS # Finds abilities or skillsets available to a unit # # Parameters: # r4 = (formationUnitIndex) Index of unit on formation screen (*0x8018ba20) # r5 = (jobID) Job ID # r6 = (slot) Type of list to generate (skillset or ability type) (Action = 0, Reaction = 1, Support = 2, Movement = 3) # r7 = (outputArray) Array to write abilities or skillsets into # *(sp + 16) = (mode) Determines behavior mode of routine # 0 = Stores learned abilities and abilities that could be learned with JP # 1 = Stores learned abilities or skillsets; Returns skillsets if slot = 0 # 2 = Stores learned abilities and abilities that the unit has enough JP to learn # 3 = Doesn't store anything # Returns: # r2 = Number of output abilities or skillsets 801228f0: 27bdffc0 addiu r29,r29,-0x0040 801228f4: afb20020 sw r18,0x0020(r29) 801228f8: 00c09021 addu r18,r6,r0 # slot 801228fc: afb60030 sw r22,0x0030(r29) 80122900: 00e0b021 addu r22,r7,r0 # outputArray 80122904: afb40028 sw r20,0x0028(r29) 80122908: 0080a021 addu r20,r4,r0 # formationUnitIndex 8012290c: afb30024 sw r19,0x0024(r29) 80122910: 8fb30050 lw r19,0x0050(r29) # mode 80122914: 34020001 ori r2,r0,0x0001 # 1 80122918: afbf0038 sw r31,0x0038(r29) 8012291c: afb70034 sw r23,0x0034(r29) 80122920: afb5002c sw r21,0x002c(r29) 80122924: afb1001c sw r17,0x001c(r29) 80122928: 16620009 bne r19,r2,0x80122950 # if ((mode == 1) 8012292c: afb00018 sw r16,0x0018(r29) 80122930: 16400008 bne r18,r0,0x80122954 # and (slot == 0)) 80122934: 00058400 sll r16,r5,0x10 # { 80122938: 00042400 sll r4,r4,0x10 8012293c: 00042403 sra r4,r4,0x10 80122940: 0c0489e4 jal 0x80122790 # return Get known skillsets (formationUnitIndex, outputArray); 80122944: 02c02821 addu r5,r22,r0 80122948: 08048afc j 0x80122bf0 8012294c: 00000000 nop # } 80122950: 00058400 sll r16,r5,0x10 80122954: 00108403 sra r16,r16,0x10 80122958: 0c0489db jal 0x8012276c # skillsetID = Get job's skillset (jobID); 8012295c: 02002021 addu r4,r16,r0 80122960: 00408821 addu r17,r2,r0 # skillsetID 80122964: 0c0488ee jal 0x801223b8 # jobIndex = Get Generic Job Index (jobID); 80122968: 02002021 addu r4,r16,r0 8012296c: 02202021 addu r4,r17,r0 80122970: 0c0488f9 jal 0x801223e4 # jobID = Find Job By Skillset (skillsetID); 80122974: 0040b821 addu r23,r2,r0 80122978: 2403ffff addiu r3,r0,-0x0001 8012297c: 1443000a bne r2,r3,0x801229a8 # if (jobID == -1) { 80122980: 02202021 addu r4,r17,r0 80122984: 00141400 sll r2,r20,0x10 80122988: 00021383 sra r2,r2,0x0e # formationUnitIndex * 4 8012298c: 3c01801d lui r1,0x801d 80122990: 00220821 addu r1,r1,r2 80122994: 8c22d5ec lw r2,-0x2a14(r1) # formationUnit = *formationUnits[formationUnitIndex] 80122998: 00000000 nop 8012299c: 9451005e lhu r17,0x005e(r2) # skillsetID = formationUnit.primarySkillset 801229a0: 00000000 nop 801229a4: 02202021 addu r4,r17,r0 # } 801229a8: 0c01698e jal 0x8005a638 # abilityList = Store Skillset's Abilities (skillsetID, 0x0f); 801229ac: 3405000f ori r5,r0,0x000f 801229b0: 16400004 bne r18,r0,0x801229c4 801229b4: 00408021 addu r16,r2,r0 # abilityList # lowerRangeAbilityID = 1 # upperRangeAbilityID = 0x1fd # if (slot == 0) { // Action 801229b8: 34030001 ori r3,r0,0x0001 # lowerRangeAbilityID = 1 801229bc: 08048a80 j 0x80122a00 801229c0: 340201a5 ori r2,r0,0x01a5 # upperRangeAbilityID = 0x1a5 801229c4: 34020001 ori r2,r0,0x0001 801229c8: 16420004 bne r18,r2,0x801229dc # } else if (slot == 1) { // Reaction 801229cc: 34020002 ori r2,r0,0x0002 801229d0: 340301a6 ori r3,r0,0x01a6 # lowerRangeAbilityID = 0x1a6 801229d4: 08048a80 j 0x80122a00 801229d8: 340201c5 ori r2,r0,0x01c5 # upperRangeAbilityID = 0x1c5 801229dc: 16420004 bne r18,r2,0x801229f0 # } else if (slot == 2) { // Support 801229e0: 34020003 ori r2,r0,0x0003 801229e4: 340301c6 ori r3,r0,0x01c6 # lowerRangeAbilityID = 0x1c6 801229e8: 08048a80 j 0x80122a00 801229ec: 340201e5 ori r2,r0,0x01e5 # upperRangeAbilityID = 0x1e5 801229f0: 16420002 bne r18,r2,0x801229fc # } else if (slot == 3) { // Movement 801229f4: 34030001 ori r3,r0,0x0001 801229f8: 340301e6 ori r3,r0,0x01e6 # lowerRangeAbilityID = 0x1e6 # } 801229fc: 340201fd ori r2,r0,0x01fd 80122a00: 00009021 addu r18,r0,r0 # abilityListIndex = 0 80122a04: 00603021 addu r6,r3,r0 # lowerRangeAbilityID 80122a08: 00402821 addu r5,r2,r0 # upperRangeAbilityID 80122a0c: 02002021 addu r4,r16,r0 # abilityPtr = &abilityList[0] # do { 80122a10: 84830000 lh r3,0x0000(r4) # abilityID = *abilityPtr 80122a14: 00000000 nop 80122a18: 0066102a slt r2,r3,r6 80122a1c: 14400003 bne r2,r0,0x80122a2c # if ((abilityID < lowerRangeAbilityID) 80122a20: 00a3102a slt r2,r5,r3 80122a24: 10400002 beq r2,r0,0x80122a30 # or (abilityID >= upperRangeAbilityID) 80122a28: 00000000 nop # { 80122a2c: a4800000 sh r0,0x0000(r4) # *abilityPtr = 0 // Blank out ability # } 80122a30: 26520001 addiu r18,r18,0x0001 # abilityListIndex = abilityListIndex + 1 80122a34: 2a420018 slti r2,r18,0x0018 80122a38: 1440fff5 bne r2,r0,0x80122a10 80122a3c: 24840002 addiu r4,r4,0x0002 # abilityPtr = abilityPtr + 2 # } while (abilityListIndex < 24); 80122a40: 00008821 addu r17,r0,r0 # numStoredAbilities = 0 80122a44: 00009021 addu r18,r0,r0 # abilityListIndex = 0 80122a48: 00141400 sll r2,r20,0x10 80122a4c: 3c03801d lui r3,0x801d 80122a50: 2463d5ec addiu r3,r3,-0x2a14 # formationUnits 80122a54: 00021383 sra r2,r2,0x0e # formationUnitIndex * 4 80122a58: 00431021 addu r2,r2,r3 # formationUnitPtr = formationUnits[formationUnitIndex] 80122a5c: 0040a821 addu r21,r2,r0 # formationUnitPtr 80122a60: 0200a021 addu r20,r16,r0 # abilityPtr = &abilityList[0] 80122a64: 02c08021 addu r16,r22,r0 # outputPtr = outputArray 80122a68: 00172400 sll r4,r23,0x10 80122a6c: 00042403 sra r4,r4,0x10 # jobID 80122a70: 00041040 sll r2,r4,0x01 # jobID * 2 80122a74: 00442021 addu r4,r2,r4 # jobID * 3 80122a78: 8ea30000 lw r3,0x0000(r21) # formationUnit = *formationUnitPtr 80122a7c: 2484007a addiu r4,r4,0x007a # (jobID * 3) + 0x7a 80122a80: 00431021 addu r2,r2,r3 # formationUnit + (jobID * 2) 80122a84: 945700be lhu r23,0x00be(r2) # jobJP = *(formationUnit + (jobID * 2) + 0xbe) 80122a88: 0c04ac6d jal 0x8012b1b4 # Store Combined Bit Value Pointer (formationUnit + (jobID * 3) + 0x7a); // Stores pointer to learned ability data for current job 80122a8c: 00832021 addu r4,r4,r3 # for (; abilityListIndex < 24; abilityListIndex++) { 80122a90: 8ea20000 lw r2,0x0000(r21) # formationUnit = *formationUnitPtr 80122a94: 00000000 nop 80122a98: 84440024 lh r4,0x0024(r2) # formationUnit.jobID 80122a9c: 0c0482e4 jal 0x80120b90 # isSpecialMonster = Special monster check (formationUnit.jobID); 80122aa0: 00000000 nop 80122aa4: 1440000e bne r2,r0,0x80122ae0 80122aa8: 34030001 ori r3,r0,0x0001 # isAbilityLearned = true # if (isSpecialMonster == false) { 80122aac: 8ea20000 lw r2,0x0000(r21) # formationUnit = *formationUnitPtr 80122ab0: 00000000 nop 80122ab4: 8442003e lh r2,0x003e(r2) # formationUnit.isPrimarySkillsetMonster 80122ab8: 00000000 nop 80122abc: 10400005 beq r2,r0,0x80122ad4 # if ((formationUnit.isPrimarySkillsetMonster) { 80122ac0: 2a420003 slti r2,r18,0x0003 80122ac4: 10400044 beq r2,r0,0x80122bd8 # if (abilityListIndex >= 3) { break; } // Exit the loop 80122ac8: 34020003 ori r2,r0,0x0003 80122acc: 08048ab8 j 0x80122ae0 80122ad0: 00000000 nop # } else { 80122ad4: 0c04ac7b jal 0x8012b1ec # isAbilityLearned = Get Combined Bit Value From Stored Pointer (1); 80122ad8: 34040001 ori r4,r0,0x0001 80122adc: 00401821 addu r3,r2,r0 # isAbilityLearned # } # } 80122ae0: 86850000 lh r5,0x0000(r20) # abilityID = *abilityPtr 80122ae4: 00000000 nop 80122ae8: 10a00036 beq r5,r0,0x80122bc4 80122aec: 00a02021 addu r4,r5,r0 # abilityStoreValue = abilityID # if (abilityID == 0) { continue; } // Go to next iteration 80122af0: 1660000f bne r19,r0,0x80122b30 # if (mode == 0) { 80122af4: 34020001 ori r2,r0,0x0001 80122af8: 1460000b bne r3,r0,0x80122b28 # if (isAbilityLearned) { 80122afc: 000510c0 sll r2,r5,0x03 # abilityID * 8 80122b00: 3c018006 lui r1,0x8006 80122b04: 00220821 addu r1,r1,r2 80122b08: 9022ebf3 lbu r2,-0x140d(r1) # abilities[abilityID].miscFlags 80122b0c: 00000000 nop 80122b10: 000211c2 srl r2,r2,0x07 # canLearnWithJP = abilities[abilityID].miscFlags >> 7 80122b14: 14400003 bne r2,r0,0x80122b24 # if (canLearnWithJP == false) { 80122b18: 00000000 nop 80122b1c: 08048aca j 0x80122b28 80122b20: 34844000 ori r4,r4,0x4000 # abilityStoreValue = abilityStoreValue | 0x4000 # } else { 80122b24: 34846000 ori r4,r4,0x6000 # abilityStoreValue = abilityStoreValue | 0x6000 # } # } 80122b28: 08048aef j 0x80122bbc 80122b2c: a6040000 sh r4,0x0000(r16) # *outputPtr = abilityStoreValue 80122b30: 16620005 bne r19,r2,0x80122b48 # } else if (mode == 1) { 80122b34: 00000000 nop 80122b38: 10600022 beq r3,r0,0x80122bc4 # if (isAbilityLearned == false) { continue; } // Go to next iteration 80122b3c: 00000000 nop 80122b40: 08048aef j 0x80122bbc 80122b44: a6040000 sh r4,0x0000(r16) # *outputPtr = abilityStoreValue 80122b48: 34020002 ori r2,r0,0x0002 80122b4c: 16620016 bne r19,r2,0x80122ba8 # } else if (mode == 2) { 80122b50: 00000000 nop 80122b54: 14600011 bne r3,r0,0x80122b9c # if (isAbilityLearned == false) { 80122b58: 000518c0 sll r3,r5,0x03 # abilityID * 8 80122b5c: 3c018006 lui r1,0x8006 80122b60: 00230821 addu r1,r1,r3 80122b64: 9022ebf3 lbu r2,-0x140d(r1) # abilities[abilityID].miscFlags 80122b68: 00000000 nop 80122b6c: 000211c2 srl r2,r2,0x07 # canLearnWithJP = abilities[abilityID].miscFlags >> 7 80122b70: 14400014 bne r2,r0,0x80122bc4 80122b74: 00171400 sll r2,r23,0x10 80122b78: 3c018006 lui r1,0x8006 80122b7c: 00230821 addu r1,r1,r3 80122b80: 9423ebf0 lhu r3,-0x1410(r1) # abilities[abilityID].jpCost 80122b84: 00021403 sra r2,r2,0x10 # jobJP 80122b88: 0043102a slt r2,r2,r3 80122b8c: 10400004 beq r2,r0,0x80122ba0 # if (jobJP < abilities[abilityID].jpCost) { 80122b90: 00000000 nop 80122b94: 08048ae8 j 0x80122ba0 80122b98: 34844000 ori r4,r4,0x4000 # abilityStoreValue = abilityStoreValue | 0x4000 # } # } else { 80122b9c: 34841000 ori r4,r4,0x1000 # abilityStoreValue = abilityStoreValue | 0x1000 # } 80122ba0: 08048aef j 0x80122bbc 80122ba4: a6040000 sh r4,0x0000(r16) # *outputPtr = abilityStoreValue 80122ba8: 34020003 ori r2,r0,0x0003 # } else if (mode == 3) { 80122bac: 16620005 bne r19,r2,0x80122bc4 # continue; 80122bb0: 00000000 nop 80122bb4: 14600003 bne r3,r0,0x80122bc4 # } else if (isAbilityLearned == false) { 80122bb8: 00000000 nop # continue; # } 80122bbc: 26100002 addiu r16,r16,0x0002 # outputPtr = outputPtr + 2 80122bc0: 26310001 addiu r17,r17,0x0001 # numStoredAbilities = numStoredAbilities + 1 80122bc4: 26520001 addiu r18,r18,0x0001 # (abilityListIndex = abilityListIndex + 1) 80122bc8: 2a420018 slti r2,r18,0x0018 80122bcc: 1440ffb0 bne r2,r0,0x80122a90 80122bd0: 26940002 addiu r20,r20,0x0002 # abilityPtr = abilityPtr + 2 # } 80122bd4: 34020003 ori r2,r0,0x0003 80122bd8: 12620004 beq r19,r2,0x80122bec # if (mode != 3) { 80122bdc: 00111040 sll r2,r17,0x01 # numStoredAbilities * 2 80122be0: 00561021 addu r2,r2,r22 # outputArray + (numStoredAbilities * 2) 80122be4: 2403ffff addiu r3,r0,-0x0001 80122be8: a4430000 sh r3,0x0000(r2) # outputArray[numStoredAbilities] = -1 // Sentinel value at end of array # } 80122bec: 02201021 addu r2,r17,r0 # return numStoredAbilities; 80122bf0: 8fbf0038 lw r31,0x0038(r29) 80122bf4: 8fb70034 lw r23,0x0034(r29) 80122bf8: 8fb60030 lw r22,0x0030(r29) 80122bfc: 8fb5002c lw r21,0x002c(r29) 80122c00: 8fb40028 lw r20,0x0028(r29) 80122c04: 8fb30024 lw r19,0x0024(r29) 80122c08: 8fb20020 lw r18,0x0020(r29) 80122c0c: 8fb1001c lw r17,0x001c(r29) 80122c10: 8fb00018 lw r16,0x0018(r29) 80122c14: 27bd0040 addiu r29,r29,0x0040 80122c18: 03e00008 jr r31 80122c1c: 00000000 nop
Return Locations
00122ca0 : Get Equipable RSM 00122cc4 : Get Equipable RSM 0011a40c : Prep Job Wheel and Skillset Display 0011f774 : Learn Abilities Menu 0011f9c0 : Learn Abilities Menu 0011fb28 : Learn Abilities Menu 0011f06c : 0011f040 - 0011f08c 0011a40c : 0011a378 - 0011a4e0 0011fef0 : 0011fd28 - 001200f4 00120020 : 0011fd28 - 001200f4 0011f774 : 0011f5f0 - 0011fc14 0011f9c0 : 0011f5f0 - 0011fc14 0011fb28 : 0011f5f0 - 0011fc14 0011e8a0 : 0011e630 - 0011ed14