Learn Job Abilities

From Final Fantasy Hacktics Wiki
Revision as of 05:16, 9 October 2024 by Glain (talk | contribs) (Created page with " # ROUTINE: LEARN JOB ABILITIES # Learns abilities for the specified unit in the specified job. Either learns random abilities, or auto-learns all abiliies in the ap...")
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search
#   ROUTINE: LEARN JOB ABILITIES
#       Learns abilities for the specified unit in the specified job.  Either learns random abilities, or auto-learns all abiliies in the appropriate skillset.
#       Parameters:
#           r4 = (unit)         Unit in-battle data pointer
#           r5 = (jobID)        Job ID, where 0x4A (Squire) symbolizes base job, even if non-generic
#           r6 = (entdUnit)     ENTD Unit pointer

8005ce74: 27bdffd0 addiu r29,r29,-0x0030
8005ce78: 00804021 addu r8,r4,r0                    #   unit
8005ce7c: 00a03821 addu r7,r5,r0                    #   jobID
8005ce80: afb60028 sw r22,0x0028(r29)
8005ce84: 0000b021 addu r22,r0,r0                   #   isAutoLearn = false
8005ce88: 24e9ffb6 addiu r9,r7,-0x004a              #   jobIndex = jobID - 0x4a
8005ce8c: 3402004a ori r2,r0,0x004a                 #   0x4a (Squire)
8005ce90: afbf002c sw r31,0x002c(r29)
8005ce94: afb50024 sw r21,0x0024(r29)
8005ce98: afb40020 sw r20,0x0020(r29)
8005ce9c: afb3001c sw r19,0x001c(r29)
8005cea0: afb20018 sw r18,0x0018(r29)
8005cea4: afb10014 sw r17,0x0014(r29)
8005cea8: 14e20011 bne r7,r2,0x8005cef0             #   if (jobID == 0x4a) {      // Base job
8005ceac: afb00010 sw r16,0x0010(r29)
8005ceb0: 91030000 lbu r3,0x0000(r8)                #       unit.baseClass
8005ceb4: 00000000 nop
8005ceb8: 2462ff80 addiu r2,r3,-0x0080              #       unit.baseClass - 0x80
8005cebc: 304200ff andi r2,r2,0x00ff
8005cec0: 2c420002 sltiu r2,r2,0x0002
8005cec4: 14400016 bne r2,r0,0x8005cf20             #       if ((unit.baseClass < 0x80) || (unit.baseClass > 0x81)) {   // Not generic human
8005cec8: 306300ff andi r3,r3,0x00ff
8005cecc: 34020082 ori r2,r0,0x0082
8005ced0: 14620004 bne r3,r2,0x8005cee4             #           if (unit.baseClass == 0x82) {   // Generic monster
8005ced4: 00000000 nop
8005ced8: 91070003 lbu r7,0x0003(r8)                #               jobID = unit.jobID
8005cedc: 080173c8 j 0x8005cf20                     #           } else {                        // Special character
8005cee0: 00000000 nop
8005cee4: 91070000 lbu r7,0x0000(r8)                #               jobID = unit.baseClass
8005cee8: 080173c8 j 0x8005cf20                     #           }
8005ceec: 00000000 nop                              #       }
                                                    #   } else {
8005cef0: 3c020080 lui r2,0x0080                    #       0x800000
8005cef4: 01228007 srav r16,r2,r9                   #       jobUnlockedMask = 0x800000 >> jobIndex
8005cef8: 91020096 lbu r2,0x0096(r8)                #       unit.jobsUnlocked1
8005cefc: 91030097 lbu r3,0x0097(r8)                #       unit.jobsUnlocked2
8005cf00: 91040098 lbu r4,0x0098(r8)                #       unit.jobsUnlocked3
8005cf04: 00021400 sll r2,r2,0x10                   #       unit.jobsUnlocked1 << 16
8005cf08: 00031a00 sll r3,r3,0x08                   #       unit.jobsUnlocked2 << 8
8005cf0c: 00431021 addu r2,r2,r3                    #       (unit.jobsUnlocked1 << 16) + (unit.jobsUnlocked2 << 8)
8005cf10: 00442821 addu r5,r2,r4                    #       jobsUnlocked = (unit.jobsUnlocked1 << 16) + (unit.jobsUnlocked2 << 8) + unit.jobsUnlocked3
8005cf14: 00b01024 and r2,r5,r16                    #       isJobUnlocked = jobsUnlocked & jobUnlockedMask
8005cf18: 1040005d beq r2,r0,0x8005d090             #       if (!isJobUnlocked) return;     // Exit the routine if the job is not unlocked
8005cf1c: 00000000 nop                              #   }
8005cf20: 91030006 lbu r3,0x0006(r8)                #   unit.Flags
8005cf24: 3402005b ori r2,r0,0x005b                 
8005cf28: 14e20004 bne r7,r2,0x8005cf3c             #   if ((jobID == 0x5b)      // Bard
8005cf2c: 3402005c ori r2,r0,0x005c
8005cf30: 30620040 andi r2,r3,0x0040                #       && (unit.Flags & UNIT_FLAG_FEMALE))
8005cf34: 14400056 bne r2,r0,0x8005d090             #           return;
8005cf38: 3402005c ori r2,r0,0x005c
8005cf3c: 14e20003 bne r7,r2,0x8005cf4c             #   if ((jobID == 0x5c)      // Dancer
8005cf40: 30620080 andi r2,r3,0x0080                #       && (unit.Flags & UNIT_FLAG_MALE))
8005cf44: 14400052 bne r2,r0,0x8005d090             #           return;
8005cf48: 00000000 nop
8005cf4c: 91020003 lbu r2,0x0003(r8)                #   unit.jobID
8005cf50: 00000000 nop
8005cf54: 14e20007 bne r7,r2,0x8005cf74
8005cf58: 00071040 sll r2,r7,0x01                   #   jobID * 2
                                                    #   abilityIndex = 0
                                                    #   if (unit.jobID != jobID) {
8005cf5c: 90c2001d lbu r2,0x001d(r6)                #       entdUnit.primarySkillset
8005cf60: 91150012 lbu r21,0x0012(r8)               #       skillset = unit.primarySkillset
8005cf64: 1440000a bne r2,r0,0x8005cf90             #       if (entdUnit.primarySkillset == 0) {
8005cf68: 00008021 addu r16,r0,r0
8005cf6c: 080173e4 j 0x8005cf90
8005cf70: 34160001 ori r22,r0,0x0001                #           isAutoLearn = true
                                                    #       }
                                                    #   } else {
8005cf74: 00471021 addu r2,r2,r7                    #       jobID * 3
8005cf78: 3c038006 lui r3,0x8006
8005cf7c: 8c636194 lw r3,0x6194(r3)                 #       jobs
8005cf80: 00021100 sll r2,r2,0x04                   #       jobID * 48
8005cf84: 00431021 addu r2,r2,r3                    #       jobs[jobID]     // sizeof(Job) == 48
8005cf88: 90550000 lbu r21,0x0000(r2)               #       skillset = jobs[jobID].skillset
8005cf8c: 00008021 addu r16,r0,r0
                                                    #   }
8005cf90: 00091040 sll r2,r9,0x01                   #   jobIndex * 2
8005cf94: 00489821 addu r19,r2,r8                   #   (unit + (jobIndex * 2))
8005cf98: 00491021 addu r2,r2,r9                    #   jobIndex * 3
8005cf9c: 00481021 addu r2,r2,r8                    #   (unit + (jobIndex * 3))
8005cfa0: 24540099 addiu r20,r2,0x0099              #   (unit + (jobIndex * 3)) + 0x99
8005cfa4: 00009021 addu r18,r0,r0                   #   isAbilityLearned = false
                                                    #   do {                                            // Loop through abilities in skillset
                                                    #       isAbilityLearned = false
8005cfa8: 02a02021 addu r4,r21,r0
8005cfac: 0c01695a jal 0x8005a568                   #       abilityID = Get Ability ID From Skillset (skillset, abilityIndex);
8005cfb0: 02002821 addu r5,r16,r0
8005cfb4: 3042ffff andi r2,r2,0xffff
8005cfb8: 10400031 beq r2,r0,0x8005d080             #       if (abilityID != 0) {
8005cfbc: 000218c0 sll r3,r2,0x03                   #           abilityID * 8
8005cfc0: 3c028006 lui r2,0x8006
8005cfc4: 2442ebf0 addiu r2,r2,-0x1410              #           abilities
8005cfc8: 00628821 addu r17,r3,r2                   #           abilities[abilityIndex]
8005cfcc: 92250002 lbu r5,0x0002(r17)               #           abilities[abilityIndex].chanceToLearn
8005cfd0: 12c00003 beq r22,r0,0x8005cfe0            #           if (isAutoLearn) {
8005cfd4: 00000000 nop
8005cfd8: 08017412 j 0x8005d048                     
8005cfdc: 34120001 ori r18,r0,0x0001                #               isAbilityLearned = true
                                                    #           } else {
8005cfe0: 0c017833 jal 0x8005e0cc                   #               isFail = Pass/Fail Roll (100, abilities[abilityIndex].chanceToLearn);
8005cfe4: 34040064 ori r4,r0,0x0064
8005cfe8: 14400017 bne r2,r0,0x8005d048             #               if (!isFail) {      // Roll succeeds
8005cfec: 00000000 nop
8005cff0: 96230000 lhu r3,0x0000(r17)               #                   abilities[abilityIndex].jpCost
8005cff4: 966200dc lhu r2,0x00dc(r19)               #                   jobJP = *(&unit.baseJobJP + (jobIndex * 2))
8005cff8: 00000000 nop
8005cffc: 0043102b sltu r2,r2,r3
8005d000: 14400011 bne r2,r0,0x8005d048
8005d004: 02002021 addu r4,r16,r0                   #                   abilityIndex
                                                    #                   if (jobJP >= abilities[abilityIndex].jpCost) {
8005d008: 966200dc lhu r2,0x00dc(r19)               #                       jobJP = *(&unit.baseJobJP + (jobIndex * 2))
8005d00c: 00000000 nop
8005d010: 00431023 subu r2,r2,r3                    #                       newJobJP = jobJP - abilities[abilityIndex].jpCost
8005d014: 06010002 bgez r16,0x8005d020
8005d018: a66200dc sh r2,0x00dc(r19)                #                       *(&unit.baseJobJP + (jobIndex * 2)) = newJobJP      // Save new job JP
8005d01c: 26040007 addiu r4,r16,0x0007
8005d020: 34120001 ori r18,r0,0x0001                #                       isAbilityLearned = true
8005d024: 000420c3 sra r4,r4,0x03                   
8005d028: 02842821 addu r5,r20,r4                   #                       learnedAbilitiesPtr = (abilityIndex / 8) + ((unit + (jobIndex * 3)) + 0x99)
8005d02c: 000420c0 sll r4,r4,0x03                   
8005d030: 02042023 subu r4,r16,r4                   #                       abilityIndex % 8  (modulo)
8005d034: 34020080 ori r2,r0,0x0080                                        
8005d038: 90a30000 lbu r3,0x0000(r5)                #                       learnedAbilityValue = *learnedAbilitiesPtr
8005d03c: 00821007 srav r2,r2,r4                    #                       newLearnedAbilityFlag = 0x80 >> (abilityIndex % 8)
8005d040: 00621825 or r3,r3,r2                      #                       learnedAbilityValue = learnedAbilityValue | newLearnedAbilityFlag
8005d044: a0a30000 sb r3,0x0000(r5)                 #                       *learnedAbilitiesPtr = learnedAbilityValue          // Set ability as learned
                                                    #                   }
                                                    #               }
                                                    #           }
8005d048: 1240000d beq r18,r0,0x8005d080            #           if (isAbilityLearned) {
8005d04c: 00000000 nop
8005d050: 06010002 bgez r16,0x8005d05c
8005d054: 02002021 addu r4,r16,r0                   #               abilityIndex
8005d058: 26040007 addiu r4,r16,0x0007
8005d05c: 000420c3 sra r4,r4,0x03                   #               learnedAbilitiesPtr = (abilityIndex / 8) + ((unit + (jobIndex * 3)) + 0x99)         
8005d060: 02842821 addu r5,r20,r4
8005d064: 000420c0 sll r4,r4,0x03
8005d068: 02042023 subu r4,r16,r4                   #               abilityIndex % 8    (modulo)
8005d06c: 34020080 ori r2,r0,0x0080                 
8005d070: 90a30000 lbu r3,0x0000(r5)                #               learnedAbilityValue = *learnedAbilitiesPtr    
8005d074: 00821007 srav r2,r2,r4                    #               newLearnedAbilityFlag = 0x80 >> (abilityIndex % 8)
8005d078: 00621825 or r3,r3,r2                      #               learnedAbilityValue = learnedAbilityValue | newLearnedAbilityFlag
8005d07c: a0a30000 sb r3,0x0000(r5)                 #               *learnedAbilitiesPtr = learnedAbilityValue          // Set ability as learned
                                                    #           }
                                                    #       }
8005d080: 26100001 addiu r16,r16,0x0001             #       abilityIndex = abilityIndex + 1
8005d084: 2a020018 slti r2,r16,0x0018
8005d088: 1440ffc7 bne r2,r0,0x8005cfa8
8005d08c: 00009021 addu r18,r0,r0                   #       isAbilityLearned = false
                                                    #   } while (abilityIndex < 24);
8005d090: 8fbf002c lw r31,0x002c(r29)
8005d094: 8fb60028 lw r22,0x0028(r29)
8005d098: 8fb50024 lw r21,0x0024(r29)
8005d09c: 8fb40020 lw r20,0x0020(r29)
8005d0a0: 8fb3001c lw r19,0x001c(r29)
8005d0a4: 8fb20018 lw r18,0x0018(r29)
8005d0a8: 8fb10014 lw r17,0x0014(r29)
8005d0ac: 8fb00010 lw r16,0x0010(r29)
8005d0b0: 27bd0030 addiu r29,r29,0x0030
8005d0b4: 03e00008 jr r31
8005d0b8: 00000000 nop