summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/map/map.c2
-rw-r--r--src/map/mob.c2
-rw-r--r--src/map/npc.c2
-rw-r--r--src/map/skill.c204
-rw-r--r--src/map/skill.h4
-rw-r--r--src/plugins/HPMHooking/HPMHooking.Defs.inc4
-rw-r--r--src/plugins/HPMHooking/HPMHooking_map.Hooks.inc12
7 files changed, 171 insertions, 59 deletions
diff --git a/src/map/map.c b/src/map/map.c
index 63d05c1c0..4477d109c 100644
--- a/src/map/map.c
+++ b/src/map/map.c
@@ -5265,7 +5265,7 @@ static bool map_zone_mf_cache(int m, char *flag, char *params)
}
}
- if( modifier[0] == '\0' || !( skill_id = skill->name2id(skill_name) ) || !skill->get_unit_id( skill->name2id(skill_name), 0) || atoi(modifier) < 1 || atoi(modifier) > USHRT_MAX ) {
+ if (modifier[0] == '\0' || (skill_id = skill->name2id(skill_name)) == 0 || skill->get_unit_id(skill->name2id(skill_name), 1, 0) == 0 || atoi(modifier) < 1 || atoi(modifier) > USHRT_MAX) {
;/* we don't mind it, the server will take care of it next. */
} else {
int idx = map->list[m].unit_count;
diff --git a/src/map/mob.c b/src/map/mob.c
index b6ba5e5a9..df6deb866 100644
--- a/src/map/mob.c
+++ b/src/map/mob.c
@@ -3871,7 +3871,7 @@ static int mob_clone_spawn(struct map_session_data *sd, int16 m, int16 x, int16
continue;
/// Normal aggressive mob. Disable skills that cannot help fighting against players. (Those with flags UF_NOMOB and UF_NOPC are specific to always aid players!) [Skotlex]
- if (flag == 0 && skill->get_unit_id(skill_id, 0) != 0 &&
+ if (flag == 0 && skill->get_unit_id(skill_id, sd->status.skill[idx].lv, 0) != 0 &&
(skill->get_unit_flag(skill_id) & (UF_NOMOB | UF_NOPC)) > 0)
continue;
diff --git a/src/map/npc.c b/src/map/npc.c
index 2f03623e4..5b009ab21 100644
--- a/src/map/npc.c
+++ b/src/map/npc.c
@@ -5104,7 +5104,7 @@ static const char *npc_parse_mapflag(const char *w1, const char *w2, const char
else if (modifier[0] == '\0') {
ShowWarning("npc_parse_mapflag: Missing 5th param for 'adjust_unit_duration' flag! removing flag from %s in file '%s', line '%d'.\n", map->list[m].name, filepath, strline(buffer,start-buffer));
if (retval) *retval = EXIT_FAILURE;
- } else if( !( skill_id = skill->name2id(skill_name) ) || !skill->get_unit_id( skill->name2id(skill_name), 0) ) {
+ } else if ((skill_id = skill->name2id(skill_name)) == 0 || skill->get_unit_id(skill->name2id(skill_name), 1, 0) == 0) {
ShowWarning("npc_parse_mapflag: Unknown skill (%s) for 'adjust_unit_duration' flag! removing flag from %s in file '%s', line '%d'.\n",skill_name, map->list[m].name, filepath, strline(buffer,start-buffer));
if (retval) *retval = EXIT_FAILURE;
} else if ( atoi(modifier) < 1 || atoi(modifier) > USHRT_MAX ) {
diff --git a/src/map/skill.c b/src/map/skill.c
index 306237565..0761592ca 100644
--- a/src/map/skill.c
+++ b/src/map/skill.c
@@ -682,15 +682,28 @@ static int skill_get_type(int skill_id, int skill_lv)
return skill->dbs->db[idx].skill_type[skill_get_lvl_idx(skill_lv)];
}
-static int skill_get_unit_id(int skill_id, int flag)
+/**
+ * Gets a skill's unit ID by its ID and level.
+ *
+ * @param skill_id The skill's ID.
+ * @param skill_lv The skill's level.
+ * @param flag
+ * @return The skill's unit ID corresponding to the passed level. Defaults to 0 in case of error.
+ *
+ **/
+static int skill_get_unit_id(int skill_id, int skill_lv, int flag)
{
- int idx;
if (skill_id == 0)
return 0;
- idx = skill->get_index(skill_id);
+
+ Assert_ret(skill_lv > 0);
+ Assert_ret(flag >= 0 && flag < ARRAYLENGTH(skill->dbs->db[0].unit_id[0]));
+
+ int idx = skill->get_index(skill_id);
+
Assert_ret(idx != 0);
- Assert_ret(flag >= 0 && flag < ARRAYLENGTH(skill->dbs->db[0].unit_id));
- return skill->dbs->db[idx].unit_id[flag];
+
+ return skill->dbs->db[idx].unit_id[skill_get_lvl_idx(skill_lv)][flag];
}
static int skill_get_unit_interval(int skill_id)
@@ -6220,7 +6233,7 @@ static int skill_castend_nodamage_id(struct block_list *src, struct block_list *
if (skill->castend_nodamage_id_undead_unknown(src, bl, &skill_id, &skill_lv, &tick, &flag))
{
//Skill is actually ground placed.
- if (src == bl && skill->get_unit_id(skill_id,0))
+ if (src == bl && skill->get_unit_id(skill_id, skill_lv, 0) != 0)
return skill->castend_pos2(src,bl->x,bl->y,skill_id,skill_lv,tick,0);
}
break;
@@ -12089,7 +12102,7 @@ static bool skill_dance_switch(struct skill_unit *su, int flag)
// replace
group->skill_id = skill_id;
group->skill_lv = 1;
- group->unit_id = skill->get_unit_id(skill_id,0);
+ group->unit_id = skill->get_unit_id(skill_id, 1, 0);
group->target_flag = skill->get_unit_target(skill_id);
group->bl_flag = skill->get_unit_bl_target(skill_id);
group->interval = skill->get_unit_interval(skill_id);
@@ -12490,7 +12503,7 @@ static struct skill_unit_group *skill_unitsetting(struct block_list *src, uint16
}
nullpo_retr(NULL, layout);
- nullpo_retr(NULL, group=skill->init_unitgroup(src,layout->count,skill_id,skill_lv,skill->get_unit_id(skill_id,flag&1)+subunt, limit, interval));
+ nullpo_retr(NULL, group = skill->init_unitgroup(src, layout->count, skill_id, skill_lv, skill->get_unit_id(skill_id, skill_lv, flag & 1) + subunt, limit, interval));
group->val1=val1;
group->val2=val2;
group->val3=val3;
@@ -17768,7 +17781,7 @@ static int skill_unit_timer_sub(union DBKey key, struct DBData *data, va_list ap
case UNT_WARP_ACTIVE:
// warp portal opens (morph to a UNT_WARP_WAITING cell)
- group->unit_id = skill->get_unit_id(group->skill_id, 1); // UNT_WARP_WAITING
+ group->unit_id = skill->get_unit_id(group->skill_id, group->skill_lv, 1); // UNT_WARP_WAITING
clif->changelook(&su->bl, LOOK_BASE, group->unit_id);
// restart timers
group->limit = skill->get_time(group->skill_id,group->skill_lv);
@@ -22402,68 +22415,167 @@ static int skill_validate_unit_id_sub(int unit_id)
}
/**
- * Validates a skill's unit IDs when reading the skill DB.
+ * Validates a skill's unit IDs if specified as single value when reading the skill DB.
*
- * @param conf The libconfig settings block which contains the skill's data.
+ * @param conf The libconfig settings block which contains the skill's unit ID data.
* @param sk The s_skill_db struct where the unit IDs should be set it.
+ * @param index The array index to use. (-1 for whole array.)
+ * @param unit_id The unit ID to validate.
*
**/
-static void skill_validate_unit_id(struct config_setting_t *conf, struct s_skill_db *sk)
+static void skill_validate_unit_id_value(struct config_setting_t *conf, struct s_skill_db *sk, int index, int unit_id)
{
nullpo_retv(conf);
nullpo_retv(sk);
- sk->unit_id[0] = 0;
- sk->unit_id[1] = 0;
+ if (skill->validate_unit_id_sub(unit_id) == -1) {
+ char level_string[14]; // Big enough to contain "in level 999 " in case of custom MAX_SKILL_LEVEL.
- struct config_setting_t *t = libconfig->setting_get_member(conf, "Id");
+ if (index == -1)
+ *level_string = '\0';
+ else
+ safesnprintf(level_string, sizeof(level_string), "in level %d ", index + 1);
- if (t != NULL && config_setting_is_array(t)) {
- if (libconfig->setting_length(t) == 0) {
- ShowWarning("%s: No unit ID(s) specified for skill ID %d in %s! Defaulting to 0...\n",
- __func__, sk->nameid, conf->file);
- return;
- }
+ ShowWarning("%s: Invalid unit ID %d specified %sfor skill ID %d in %s! Must be greater than or equal to 0. Defaulting to 0...\n",
+ __func__, unit_id, level_string, sk->nameid, conf->file);
+
+ return;
+ }
+
+ if (index == -1) {
+ for (int i = 0; i < MAX_SKILL_LEVEL; i++)
+ sk->unit_id[i][0] = unit_id;
+ } else {
+ sk->unit_id[index][0] = unit_id;
+ }
+}
+
+/**
+ * Validates a skill's unit IDs if specified as array when reading the skill DB.
+ *
+ * @param conf The libconfig settings block which contains the skill's unit ID data.
+ * @param sk The s_skill_db struct where the unit IDs should be set it.
+ * @param index The array index to use. (-1 for whole array.)
+ *
+ **/
+static void skill_validate_unit_id_array(struct config_setting_t *conf, struct s_skill_db *sk, int index)
+{
+ nullpo_retv(conf);
+ nullpo_retv(sk);
+
+ char level_string[14]; // Big enough to contain "in level 999 " in case of custom MAX_SKILL_LEVEL.
+
+ if (index == -1)
+ *level_string = '\0';
+ else
+ safesnprintf(level_string, sizeof(level_string), "in level %d ", index + 1);
+
+ if (libconfig->setting_length(conf) == 0) {
+ ShowWarning("%s: No unit ID(s) specified %sfor skill ID %d in %s! Defaulting to 0...\n",
+ __func__, level_string, sk->nameid, conf->file);
+ return;
+ }
+
+ if (libconfig->setting_length(conf) > 2)
+ ShowWarning("%s: Specified more than two unit IDs %sfor skill ID %d in %s! Reading only the first two...\n",
+ __func__, level_string, sk->nameid, conf->file);
+
+ int unit_id1 = libconfig->setting_get_int_elem(conf, 0);
- if (libconfig->setting_length(t) > 2)
- ShowWarning("%s: Specified more than two unit IDs for skill ID %d in %s! Reading only the first two...\n",
- __func__, sk->nameid, conf->file);
+ if (skill->validate_unit_id_sub(unit_id1) == -1) {
+ ShowWarning("%s: Invalid unit ID %d specified %sfor skill ID %d in %s! Must be greater than or equal to 0. Defaulting to 0...\n",
+ __func__, unit_id1, level_string, sk->nameid, conf->file);
+ unit_id1 = 0;
+ }
+
+ int unit_id2 = 0;
- int unit_id1 = libconfig->setting_get_int_elem(t, 0);
+ if (libconfig->setting_length(conf) > 1) {
+ unit_id2 = libconfig->setting_get_int_elem(conf, 1);
- if (skill->validate_unit_id_sub(unit_id1) == -1) {
- ShowWarning("%s: Unknown unit ID %d specified for skill ID %d in %s! Defaulting to 0...\n",
- __func__, unit_id1, sk->nameid, conf->file);
- unit_id1 = 0;
+ if (skill->validate_unit_id_sub(unit_id2) == -1) {
+ ShowWarning("%s: Invalid unit ID %d specified %sfor skill ID %d in %s! Must be greater than or equal to 0. Defaulting to 0...\n",
+ __func__, unit_id2, level_string, sk->nameid, conf->file);
+ unit_id2 = 0;
}
+ }
- int unit_id2 = 0;
+ if (unit_id1 == 0 && unit_id2 == 0)
+ return;
- if (libconfig->setting_length(t) > 1) {
- unit_id2 = libconfig->setting_get_int_elem(t, 1);
+ if (index == -1) {
+ for (int i = 0; i < MAX_SKILL_LEVEL; i++) {
+ sk->unit_id[i][0] = unit_id1;
+ sk->unit_id[i][1] = unit_id2;
+ }
+ } else {
+ sk->unit_id[index][0] = unit_id1;
+ sk->unit_id[index][1] = unit_id2;
+ }
+}
- if (skill->validate_unit_id_sub(unit_id2) == -1) {
- ShowWarning("%s: Unknown unit ID %d specified for skill ID %d in %s! Defaulting to 0...\n",
- __func__, unit_id2, sk->nameid, conf->file);
- unit_id2 = 0;
- }
+/**
+ * Validates a skill's unit IDs if specified as group when reading the skill DB.
+ *
+ * @param conf The libconfig settings block which contains the skill's unit ID data.
+ * @param sk The s_skill_db struct where the unit IDs should be set it.
+ *
+ **/
+static void skill_validate_unit_id_group(struct config_setting_t *conf, struct s_skill_db *sk)
+{
+ nullpo_retv(conf);
+ nullpo_retv(sk);
+
+ for (int i = 0; i < MAX_SKILL_LEVEL; i++) {
+ struct config_setting_t *t;
+ char lv[6]; // Big enough to contain "Lv999" in case of custom MAX_SKILL_LEVEL.
+ safesnprintf(lv, sizeof(lv), "Lv%d", i + 1);
+
+ if ((t = libconfig->setting_get_member(conf, lv)) != NULL && config_setting_is_array(t)) {
+ skill_validate_unit_id_array(t, sk, i);
+ continue;
}
- sk->unit_id[0] = unit_id1;
- sk->unit_id[1] = unit_id2;
+ int unit_id;
+
+ if (libconfig->setting_lookup_int(conf, lv, &unit_id) == CONFIG_TRUE)
+ skill_validate_unit_id_value(conf, sk, i, unit_id);
+ }
+}
+/**
+ * Validates a skill's unit IDs when reading the skill DB.
+ *
+ * @param conf The libconfig settings block which contains the skill's data.
+ * @param sk The s_skill_db struct where the unit IDs should be set it.
+ *
+ **/
+static void skill_validate_unit_id(struct config_setting_t *conf, struct s_skill_db *sk)
+{
+ nullpo_retv(conf);
+ nullpo_retv(sk);
+
+ for (int i = 0; i < MAX_SKILL_LEVEL; i++) {
+ sk->unit_id[i][0] = 0;
+ sk->unit_id[i][1] = 0;
+ }
+
+ struct config_setting_t *t = libconfig->setting_get_member(conf, "Id");
+
+ if (t != NULL && config_setting_is_group(t)) {
+ skill_validate_unit_id_group(t, sk);
+ return;
+ }
+
+ if (t != NULL && config_setting_is_array(t)) {
+ skill_validate_unit_id_array(t, sk, -1);
return;
}
int unit_id;
- if (libconfig->setting_lookup_int(conf, "Id", &unit_id) == CONFIG_TRUE) {
- if (skill->validate_unit_id_sub(unit_id) == -1)
- ShowWarning("%s: Unknown unit ID %d specified for skill ID %d in %s! Defaulting to 0...\n",
- __func__, unit_id, sk->nameid, conf->file);
- else
- sk->unit_id[0] = unit_id;
- }
+ if (libconfig->setting_lookup_int(conf, "Id", &unit_id) == CONFIG_TRUE)
+ skill_validate_unit_id_value(conf, sk, -1, unit_id);
}
/**
diff --git a/src/map/skill.h b/src/map/skill.h
index daa03d24e..b5d38e6e2 100644
--- a/src/map/skill.h
+++ b/src/map/skill.h
@@ -1778,7 +1778,7 @@ struct s_skill_db {
int spiritball[MAX_SKILL_LEVEL];
int itemid[MAX_SKILL_ITEM_REQUIRE],amount[MAX_SKILL_ITEM_REQUIRE];
int castnodex[MAX_SKILL_LEVEL], delaynodex[MAX_SKILL_LEVEL];
- int unit_id[2];
+ int unit_id[MAX_SKILL_LEVEL][2];
int unit_layout_type[MAX_SKILL_LEVEL];
int unit_range[MAX_SKILL_LEVEL];
int unit_interval;
@@ -2000,7 +2000,7 @@ struct skill_interface {
int (*get_weapontype) (int skill_id);
int (*get_ammotype) (int skill_id);
int (*get_ammo_qty) (int skill_id, int skill_lv);
- int (*get_unit_id) (int skill_id, int flag);
+ int (*get_unit_id) (int skill_id, int skill_lv, int flag);
int (*get_inf2) (int skill_id);
int (*get_castcancel) (int skill_id, int skill_lv);
int (*get_maxcount) (int skill_id, int skill_lv);
diff --git a/src/plugins/HPMHooking/HPMHooking.Defs.inc b/src/plugins/HPMHooking/HPMHooking.Defs.inc
index 8a4aa7712..494634bc0 100644
--- a/src/plugins/HPMHooking/HPMHooking.Defs.inc
+++ b/src/plugins/HPMHooking/HPMHooking.Defs.inc
@@ -7292,8 +7292,8 @@ typedef int (*HPMHOOK_pre_skill_get_ammotype) (int *skill_id);
typedef int (*HPMHOOK_post_skill_get_ammotype) (int retVal___, int skill_id);
typedef int (*HPMHOOK_pre_skill_get_ammo_qty) (int *skill_id, int *skill_lv);
typedef int (*HPMHOOK_post_skill_get_ammo_qty) (int retVal___, int skill_id, int skill_lv);
-typedef int (*HPMHOOK_pre_skill_get_unit_id) (int *skill_id, int *flag);
-typedef int (*HPMHOOK_post_skill_get_unit_id) (int retVal___, int skill_id, int flag);
+typedef int (*HPMHOOK_pre_skill_get_unit_id) (int *skill_id, int *skill_lv, int *flag);
+typedef int (*HPMHOOK_post_skill_get_unit_id) (int retVal___, int skill_id, int skill_lv, int flag);
typedef int (*HPMHOOK_pre_skill_get_inf2) (int *skill_id);
typedef int (*HPMHOOK_post_skill_get_inf2) (int retVal___, int skill_id);
typedef int (*HPMHOOK_pre_skill_get_castcancel) (int *skill_id, int *skill_lv);
diff --git a/src/plugins/HPMHooking/HPMHooking_map.Hooks.inc b/src/plugins/HPMHooking/HPMHooking_map.Hooks.inc
index 46682e33c..d8685e1c5 100644
--- a/src/plugins/HPMHooking/HPMHooking_map.Hooks.inc
+++ b/src/plugins/HPMHooking/HPMHooking_map.Hooks.inc
@@ -77606,15 +77606,15 @@ int HP_skill_get_ammo_qty(int skill_id, int skill_lv) {
}
return retVal___;
}
-int HP_skill_get_unit_id(int skill_id, int flag) {
+int HP_skill_get_unit_id(int skill_id, int skill_lv, int flag) {
int hIndex = 0;
int retVal___ = 0;
if (HPMHooks.count.HP_skill_get_unit_id_pre > 0) {
- int (*preHookFunc) (int *skill_id, int *flag);
+ int (*preHookFunc) (int *skill_id, int *skill_lv, int *flag);
*HPMforce_return = false;
for (hIndex = 0; hIndex < HPMHooks.count.HP_skill_get_unit_id_pre; hIndex++) {
preHookFunc = HPMHooks.list.HP_skill_get_unit_id_pre[hIndex].func;
- retVal___ = preHookFunc(&skill_id, &flag);
+ retVal___ = preHookFunc(&skill_id, &skill_lv, &flag);
}
if (*HPMforce_return) {
*HPMforce_return = false;
@@ -77622,13 +77622,13 @@ int HP_skill_get_unit_id(int skill_id, int flag) {
}
}
{
- retVal___ = HPMHooks.source.skill.get_unit_id(skill_id, flag);
+ retVal___ = HPMHooks.source.skill.get_unit_id(skill_id, skill_lv, flag);
}
if (HPMHooks.count.HP_skill_get_unit_id_post > 0) {
- int (*postHookFunc) (int retVal___, int skill_id, int flag);
+ int (*postHookFunc) (int retVal___, int skill_id, int skill_lv, int flag);
for (hIndex = 0; hIndex < HPMHooks.count.HP_skill_get_unit_id_post; hIndex++) {
postHookFunc = HPMHooks.list.HP_skill_get_unit_id_post[hIndex].func;
- retVal___ = postHookFunc(retVal___, skill_id, flag);
+ retVal___ = postHookFunc(retVal___, skill_id, skill_lv, flag);
}
}
return retVal___;