/** * Get max level for homunculus skill * @param id Skill ID * @param b_class * @return Skill Level */ int hom_skill_tree_get_max(int skill_id, int b_class){ uint8 i; if ((b_class = hom_class2index(b_class)) < 0) return 0; ARR_FIND(0, MAX_HOM_SKILL_TREE, i, hskill_tree[b_class][i].id == skill_id); if (i < MAX_HOM_SKILL_TREE) return hskill_tree[b_class][i].max; return skill_get_max(skill_id); }
/** * Get max level for homunculus skill * @param id Skill ID * @param b_class * @return Skill Level */ int hom_skill_tree_get_max(int skill_id, int b_class){ int i, skid; if ((b_class = hom_class2index(b_class)) < 0) return 0; for (i = 0; (skid = hskill_tree[b_class][i].id) > 0; i++) { if (hom_skill_get_index(skid) < 0) return 0; if (skill_id == skid) return hskill_tree[b_class][i].max; } return skill_get_max(skill_id); }
/** * Get required minimum level to learn the skill * @param class_ Homunculus class * @param skill_id Homunculus skill ID * @return Level required or 0 if invalid **/ uint8 hom_skill_get_min_level(int class_, uint16 skill_id) { short class_idx = hom_class2index(class_), skill_idx = -1; uint8 i; if (class_idx == -1 || (skill_idx = hom_skill_get_index(skill_id)) == -1) return 0; ARR_FIND(0, MAX_HOM_SKILL_REQUIRE, i, hskill_tree[class_idx][i].id == skill_id); if (i == MAX_HOM_SKILL_REQUIRE) return 0; return hskill_tree[class_idx][i].need_level; }
/** * Read homunculus skill db */ static bool read_homunculus_skilldb_sub(char* split[], int columns, int current) {// <hom class>,<skill id>,<max level>[,<job level>],<req id1>,<req lv1>,<req id2>,<req lv2>,<req id3>,<req lv3>,<req id4>,<req lv4>,<req id5>,<req lv5>,<intimacy lv req> int skill_id, class_idx; int i, j; int minJobLevelPresent = 0; if (columns == 14) minJobLevelPresent = 1; // MinJobLvl has been added // check for bounds [celest] if ((class_idx = hom_class2index(atoi(split[0]))) == -1) { ShowWarning("read_homunculus_skilldb: Invalud homunculus class %d.\n", atoi(split[0])); return false; } skill_id = atoi(split[1]); //This is to avoid adding two lines for the same skill. [Skotlex] // Search an empty line or a line with the same skill_id (stored in j) ARR_FIND( 0, MAX_SKILL_TREE, j, !hskill_tree[class_idx][j].id || hskill_tree[class_idx][j].id == skill_id ); if (j == MAX_SKILL_TREE) { ShowWarning("Unable to load skill %d into homunculus %d's tree. Maximum number of skills per class has been reached.\n", skill_id, atoi(split[0])); return false; } hskill_tree[class_idx][j].id = skill_id; hskill_tree[class_idx][j].max = atoi(split[2]); if (minJobLevelPresent) hskill_tree[class_idx][j].joblv = atoi(split[3]); for (i = 0; i < MAX_HOM_SKILL_REQUIRE; i++) { hskill_tree[class_idx][j].need[i].id = atoi(split[3+i*2+minJobLevelPresent]); hskill_tree[class_idx][j].need[i].lv = atoi(split[3+i*2+minJobLevelPresent+1]); } hskill_tree[class_idx][j].intimacylv = atoi(split[13+minJobLevelPresent]); return true; }
/** * Calculates homunculus skill tree * @param hd * @param flag_envolve */ void hom_calc_skilltree(struct homun_data *hd, int flag_evolve) { int i, skill_id = 0; int f = 1; short c = 0; nullpo_retv(hd); /* load previous homunculus form skills first. */ if (hd->homunculus.prev_class != 0 && (c = hom_class2index(hd->homunculus.prev_class)) >= 0) { for (i = 0; i < MAX_SKILL_TREE && (skill_id = hskill_tree[c][i].id) > 0; i++) { int idx = hom_skill_get_index(skill_id); if (idx < 0) continue; if (hd->homunculus.hskill[idx].id) continue; //Skill already known. if (!battle_config.skillfree) { int j; for (j = 0; j < MAX_HOM_SKILL_REQUIRE; j++) { if (hskill_tree[c][i].need[j].id && hom_checkskill(hd,hskill_tree[c][i].need[j].id) < hskill_tree[c][i].need[j].lv) { f = 0; break; } } } if (f) hd->homunculus.hskill[idx].id = skill_id; } f = 1; } if ((c = hom_class2index(hd->homunculus.class_)) < 0) return; for (i = 0; i < MAX_SKILL_TREE && (skill_id = hskill_tree[c][i].id) > 0; i++) { int intimacy; int idx = hom_skill_get_index(skill_id); if (idx < 0) continue; if (hd->homunculus.hskill[idx].id) continue; //Skill already known. intimacy = (flag_evolve) ? 10 : hd->homunculus.intimacy; if (intimacy < hskill_tree[c][i].intimacylv) continue; if (!battle_config.skillfree) { int j; for (j = 0; j < MAX_HOM_SKILL_REQUIRE; j++) { if (hskill_tree[c][i].need[j].id && hom_checkskill(hd,hskill_tree[c][i].need[j].id) < hskill_tree[c][i].need[j].lv) { f = 0; break; } } } if (f) hd->homunculus.hskill[idx].id = skill_id; } if (hd->master) clif_homskillinfoblock(hd->master); }
/** * Calculates homunculus skill tree * @param hd * @param flag_envolve */ void hom_calc_skilltree(struct homun_data *hd, bool flag_evolve) { uint8 i; short c = 0; nullpo_retv(hd); /* load previous homunculus form skills first. */ if (hd->homunculus.prev_class != 0 && (c = hom_class2index(hd->homunculus.prev_class)) >= 0) { for (i = 0; i < MAX_HOM_SKILL_TREE; i++) { uint16 skill_id; short idx = -1; bool fail = false; if (!(skill_id = hskill_tree[c][i].id) || (idx = hom_skill_get_index(skill_id)) == -1) continue; if (hd->homunculus.hskill[idx].id) continue; //Skill already known. if (!battle_config.skillfree) { uint8 j; if (hskill_tree[c][i].need_level > hd->homunculus.level) continue; for (j = 0; j < MAX_HOM_SKILL_REQUIRE; j++) { if (hskill_tree[c][i].need[j].id && hom_checkskill(hd,hskill_tree[c][i].need[j].id) < hskill_tree[c][i].need[j].lv) { fail = true; break; } } } if (!fail) hd->homunculus.hskill[idx].id = skill_id; } } if ((c = hom_class2index(hd->homunculus.class_)) < 0) return; for (i = 0; i < MAX_HOM_SKILL_TREE; i++) { unsigned int intimacy = 0; uint16 skill_id; short idx = -1; bool fail = false; if (!(skill_id = hskill_tree[c][i].id) || (idx = hom_skill_get_index(skill_id)) == -1) continue; if (hd->homunculus.hskill[idx].id) continue; //Skill already known. intimacy = (flag_evolve) ? 10 : hd->homunculus.intimacy; if (intimacy < hskill_tree[c][i].intimacy * 100) continue; if (!battle_config.skillfree) { uint8 j; if (hskill_tree[c][i].need_level > hd->homunculus.level) continue; for (j = 0; j < MAX_HOM_SKILL_REQUIRE; j++) { if (hskill_tree[c][i].need[j].id && hom_checkskill(hd,hskill_tree[c][i].need[j].id) < hskill_tree[c][i].need[j].lv) { fail = true; break; } } } if (!fail) hd->homunculus.hskill[idx].id = skill_id; } if (hd->master) clif_homskillinfoblock(hd->master); }