summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/map/mob.c2
-rw-r--r--src/map/skill.c192
-rw-r--r--src/map/skill.h7
-rw-r--r--src/plugins/HPMHooking/HPMHooking.Defs.inc8
-rw-r--r--src/plugins/HPMHooking/HPMHooking_map.Hooks.inc24
5 files changed, 152 insertions, 81 deletions
diff --git a/src/map/mob.c b/src/map/mob.c
index df6deb866..056a1a8b1 100644
--- a/src/map/mob.c
+++ b/src/map/mob.c
@@ -3904,7 +3904,7 @@ static int mob_clone_spawn(struct map_session_data *sd, int16 m, int16 x, int16
mob_skills[i].state = MSS_IDLE;
mob_skills[i].target = MST_AROUND2;
mob_skills[i].delay = 60000;
- } else if (skill->get_unit_target(skill_id) == BCT_ENEMY) { /// Target Enemy.
+ } else if (skill->get_unit_target(skill_id, sd->status.skill[idx].lv) == BCT_ENEMY) { /// Target Enemy.
mob_skills[i].state = MSS_ANYTARGET;
mob_skills[i].target = MST_TARGET;
mob_skills[i].cond1 = MSC_ALWAYS;
diff --git a/src/map/skill.c b/src/map/skill.c
index d57931b54..9b9c17b21 100644
--- a/src/map/skill.c
+++ b/src/map/skill.c
@@ -743,24 +743,48 @@ static int skill_get_unit_range(int skill_id, int skill_lv)
return skill->dbs->db[idx].unit_range[skill_get_lvl_idx(skill_lv)];
}
-static int skill_get_unit_target(int skill_id)
+/**
+ * Gets a skill's unit target by its ID and level.
+ *
+ * @param skill_id The skill's ID.
+ * @param skill_lv The skill's level.
+ * @return The skill's unit target corresponding to the passed level. Defaults to BCT_NOONE (0) in case of error.
+ *
+ **/
+static int skill_get_unit_target(int skill_id, int skill_lv)
{
- int idx;
if (skill_id == 0)
return BCT_NOONE;
- idx = skill->get_index(skill_id);
+
+ Assert_retr(BCT_NOONE, skill_lv > 0);
+
+ int idx = skill->get_index(skill_id);
+
Assert_retr(BCT_NOONE, idx != 0);
- return skill->dbs->db[idx].unit_target & BCT_ALL;
+
+ return (skill->dbs->db[idx].unit_target[skill_get_lvl_idx(skill_lv)] & BCT_ALL);
}
-static int skill_get_unit_bl_target(int skill_id)
+/**
+ * Gets a skill's unit target as bl type by its ID and level.
+ *
+ * @param skill_id The skill's ID.
+ * @param skill_lv The skill's level.
+ * @return The skill's unit target as bl type corresponding to the passed level. Defaults to BL_NUL (0) in case of error.
+ *
+ **/
+static int skill_get_unit_bl_target(int skill_id, int skill_lv)
{
- int idx;
if (skill_id == 0)
return BL_NUL;
- idx = skill->get_index(skill_id);
- Assert_retr(BL_NUL, idx != 0);
- return skill->dbs->db[idx].unit_target & BL_ALL;
+
+ Assert_retr(BCT_NOONE, skill_lv > 0);
+
+ int idx = skill->get_index(skill_id);
+
+ Assert_retr(BCT_NOONE, idx != 0);
+
+ return (skill->dbs->db[idx].unit_target[skill_get_lvl_idx(skill_lv)] & BL_ALL);
}
static int skill_get_unit_flag(int skill_id)
@@ -12115,8 +12139,8 @@ static bool skill_dance_switch(struct skill_unit *su, int flag)
group->skill_id = skill_id;
group->skill_lv = 1;
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->target_flag = skill->get_unit_target(skill_id, 1);
+ group->bl_flag = skill->get_unit_bl_target(skill_id, 1);
group->interval = skill->get_unit_interval(skill_id, 1);
} else {
//Restore
@@ -12151,7 +12175,7 @@ static struct skill_unit_group *skill_unitsetting(struct block_list *src, uint16
limit = skill->get_time(skill_id,skill_lv);
range = skill->get_unit_range(skill_id,skill_lv);
interval = skill->get_unit_interval(skill_id, skill_lv);
- target = skill->get_unit_target(skill_id);
+ target = skill->get_unit_target(skill_id, skill_lv);
unit_flag = skill->get_unit_flag(skill_id);
layout = skill->get_unit_layout(skill_id,skill_lv,src,x,y);
@@ -12520,7 +12544,7 @@ static struct skill_unit_group *skill_unitsetting(struct block_list *src, uint16
group->val2=val2;
group->val3=val3;
group->target_flag=target;
- group->bl_flag= skill->get_unit_bl_target(skill_id);
+ group->bl_flag= skill->get_unit_bl_target(skill_id, skill_lv);
group->state.ammo_consume = (sd && sd->state.arrow_atk && skill_id != GS_GROUNDDRIFT); //Store if this skill needs to consume ammo.
group->state.song_dance = ((unit_flag&(UF_DANCE|UF_SONG)) ? 1 : 0)|((unit_flag&UF_ENSEMBLE) ? 2 : 0); //Signals if this is a song/dance/duet
group->state.guildaura = ( skill_id >= GD_LEADERSHIP && skill_id <= GD_HAWKEYES )?1:0;
@@ -22842,10 +22866,51 @@ static void skill_validate_unit_flag(struct config_setting_t *conf, struct s_ski
}
/**
- * Validates a skill's unit target when reading the skill DB.
+ * Validates a single unit target when reading the skill DB.
+ *
+ * @param target The unit target to validate.
+ * @return A number greater than or equal to 0 if the passed unit target is valid, otherwise -1.
+ *
+ **/
+static int skill_validate_unit_target_sub(const char *target)
+{
+ nullpo_retr(-1, target);
+
+ int ret_val = BCT_NOONE;
+
+ if (strcmpi(target, "NotEnemy") == 0)
+ ret_val = BCT_NOENEMY;
+ else if (strcmpi(target, "NotParty") == 0)
+ ret_val = BCT_NOPARTY;
+ else if (strcmpi(target, "NotGuild") == 0)
+ ret_val = BCT_NOGUILD;
+ else if (strcmpi(target, "Friend") == 0)
+ ret_val = BCT_NOENEMY;
+ else if (strcmpi(target, "Party") == 0)
+ ret_val = BCT_PARTY;
+ else if (strcmpi(target, "Ally") == 0)
+ ret_val = BCT_PARTY|BCT_GUILD;
+ else if (strcmpi(target, "Guild") == 0)
+ ret_val = BCT_GUILD;
+ else if (strcmpi(target, "All") == 0)
+ ret_val = BCT_ALL;
+ else if (strcmpi(target, "Enemy") == 0)
+ ret_val = BCT_ENEMY;
+ else if (strcmpi(target, "Self") == 0)
+ ret_val = BCT_SELF;
+ else if (strcmpi(target, "SameGuild") == 0)
+ ret_val = BCT_SAMEGUILD;
+ else if (strcmpi(target, "None") != 0)
+ ret_val = -1;
+
+ return ret_val;
+}
+
+/**
+ * Validates a skill's unit targets 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 target should be set it.
+ * @param sk The s_skill_db struct where the unit targets should be set it.
*
**/
static void skill_validate_unit_target(struct config_setting_t *conf, struct s_skill_db *sk)
@@ -22853,52 +22918,56 @@ static void skill_validate_unit_target(struct config_setting_t *conf, struct s_s
nullpo_retv(conf);
nullpo_retv(sk);
- sk->unit_target = BCT_NOONE;
-
- const char *unit_target;
-
- if (libconfig->setting_lookup_string(conf, "Target", &unit_target) == CONFIG_TRUE) {
- if (strcmpi(unit_target, "NotEnemy") == 0)
- sk->unit_target = BCT_NOENEMY;
- else if (strcmpi(unit_target, "NotParty") == 0)
- sk->unit_target = BCT_NOPARTY;
- else if (strcmpi(unit_target, "NotGuild") == 0)
- sk->unit_target = BCT_NOGUILD;
- else if (strcmpi(unit_target, "Friend") == 0)
- sk->unit_target = BCT_NOENEMY;
- else if (strcmpi(unit_target, "Party") == 0)
- sk->unit_target = BCT_PARTY;
- else if (strcmpi(unit_target, "Ally") == 0)
- sk->unit_target = BCT_PARTY|BCT_GUILD;
- else if (strcmpi(unit_target, "Guild") == 0)
- sk->unit_target = BCT_GUILD;
- else if (strcmpi(unit_target, "All") == 0)
- sk->unit_target = BCT_ALL;
- else if (strcmpi(unit_target, "Enemy") == 0)
- sk->unit_target = BCT_ENEMY;
- else if (strcmpi(unit_target, "Self") == 0)
- sk->unit_target = BCT_SELF;
- else if (strcmpi(unit_target, "SameGuild") == 0)
- sk->unit_target = BCT_SAMEGUILD;
- else if (strcmpi(unit_target, "None") != 0)
- ShowWarning("%s: Invalid unit target %s specified for skill ID %d in %s! Defaulting to None...\n",
- __func__, unit_target, sk->nameid, conf->file);
- }
-
- if ((sk->unit_flag & UF_DEFNOTENEMY) != 0 && battle_config.defnotenemy != 0)
- sk->unit_target = BCT_NOENEMY;
-
- // By default target just characters.
- sk->unit_target |= BL_CHAR;
-
- if ((sk->unit_flag & UF_NOPC) != 0)
- sk->unit_target &= ~BL_PC;
-
- if ((sk->unit_flag & UF_NOMOB) != 0)
- sk->unit_target &= ~BL_MOB;
-
- if ((sk->unit_flag & UF_SKILL) != 0)
- sk->unit_target |= BL_SKILL;
+ skill->level_set_value(sk->unit_target, BCT_NOONE);
+
+ struct config_setting_t *t = libconfig->setting_get_member(conf, "Target");
+
+ if (t != NULL && config_setting_is_group(t)) {
+ for (int i = 0; i < MAX_SKILL_LEVEL; i++) {
+ char lv[6]; // Big enough to contain "Lv999" in case of custom MAX_SKILL_LEVEL.
+ safesnprintf(lv, sizeof(lv), "Lv%d", i + 1);
+ const char *unit_target;
+
+ if (libconfig->setting_lookup_string(t, lv, &unit_target) == CONFIG_TRUE) {
+ int target = skill->validate_unit_target_sub(unit_target);
+
+ if (target > BCT_NOONE)
+ sk->unit_target[i] = target;
+ else if (target == -1)
+ ShowWarning("%s: Invalid unit target %s specified in level %d for skill ID %d in %s! Defaulting to None...\n",
+ __func__, unit_target, i + 1, sk->nameid, conf->file);
+ }
+ }
+ } else {
+ const char *unit_target;
+
+ if (libconfig->setting_lookup_string(conf, "Target", &unit_target) == CONFIG_TRUE) {
+ int target = skill->validate_unit_target_sub(unit_target);
+
+ if (target > BCT_NOONE)
+ skill->level_set_value(sk->unit_target, target);
+ else if (target == -1)
+ ShowWarning("%s: Invalid unit target %s specified for skill ID %d in %s! Defaulting to None...\n",
+ __func__, unit_target, sk->nameid, conf->file);
+ }
+ }
+
+ for (int i = 0; i < MAX_SKILL_LEVEL; i++) {
+ if ((sk->unit_flag & UF_DEFNOTENEMY) != 0 && battle_config.defnotenemy != 0)
+ sk->unit_target[i] = BCT_NOENEMY;
+
+ // By default target just characters.
+ sk->unit_target[i] |= BL_CHAR;
+
+ if ((sk->unit_flag & UF_NOPC) != 0)
+ sk->unit_target[i] &= ~BL_PC;
+
+ if ((sk->unit_flag & UF_NOMOB) != 0)
+ sk->unit_target[i] &= ~BL_MOB;
+
+ if ((sk->unit_flag & UF_SKILL) != 0)
+ sk->unit_target[i] |= BL_SKILL;
+ }
}
/**
@@ -23410,6 +23479,7 @@ void skill_defaults(void)
skill->validate_unit_interval = skill_validate_unit_interval;
skill->validate_unit_flag_sub = skill_validate_unit_flag_sub;
skill->validate_unit_flag = skill_validate_unit_flag;
+ skill->validate_unit_target_sub = skill_validate_unit_target_sub;
skill->validate_unit_target = skill_validate_unit_target;
skill->validate_unit = skill_validate_unit;
skill->validate_additional_fields = skill_validate_additional_fields;
diff --git a/src/map/skill.h b/src/map/skill.h
index c32a8b639..2d68e695d 100644
--- a/src/map/skill.h
+++ b/src/map/skill.h
@@ -1782,7 +1782,7 @@ struct s_skill_db {
int unit_layout_type[MAX_SKILL_LEVEL];
int unit_range[MAX_SKILL_LEVEL];
int unit_interval[MAX_SKILL_LEVEL];
- int unit_target;
+ int unit_target[MAX_SKILL_LEVEL];
int unit_flag;
};
@@ -2006,9 +2006,9 @@ struct skill_interface {
int (*get_maxcount) (int skill_id, int skill_lv);
int (*get_blewcount) (int skill_id, int skill_lv);
int (*get_unit_flag) (int skill_id);
- int (*get_unit_target) (int skill_id);
+ int (*get_unit_target) (int skill_id, int skill_lv);
int (*get_unit_interval) (int skill_id, int skill_lv);
- int (*get_unit_bl_target) (int skill_id);
+ int (*get_unit_bl_target) (int skill_id, int skill_lv);
int (*get_unit_layout_type) (int skill_id, int skill_lv);
int (*get_unit_range) (int skill_id, int skill_lv);
int (*get_cooldown) (int skill_id, int skill_lv);
@@ -2180,6 +2180,7 @@ struct skill_interface {
void (*validate_unit_interval) (struct config_setting_t *conf, struct s_skill_db *sk);
int (*validate_unit_flag_sub) (const char *type, bool on, struct s_skill_db *sk);
void (*validate_unit_flag) (struct config_setting_t *conf, struct s_skill_db *sk);
+ int (*validate_unit_target_sub) (const char *target);
void (*validate_unit_target) (struct config_setting_t *conf, struct s_skill_db *sk);
void (*validate_unit) (struct config_setting_t *conf, struct s_skill_db *sk);
void (*validate_additional_fields) (struct config_setting_t *conf, struct s_skill_db *sk);
diff --git a/src/plugins/HPMHooking/HPMHooking.Defs.inc b/src/plugins/HPMHooking/HPMHooking.Defs.inc
index e75dbaa97..645afa240 100644
--- a/src/plugins/HPMHooking/HPMHooking.Defs.inc
+++ b/src/plugins/HPMHooking/HPMHooking.Defs.inc
@@ -7304,12 +7304,12 @@ typedef int (*HPMHOOK_pre_skill_get_blewcount) (int *skill_id, int *skill_lv);
typedef int (*HPMHOOK_post_skill_get_blewcount) (int retVal___, int skill_id, int skill_lv);
typedef int (*HPMHOOK_pre_skill_get_unit_flag) (int *skill_id);
typedef int (*HPMHOOK_post_skill_get_unit_flag) (int retVal___, int skill_id);
-typedef int (*HPMHOOK_pre_skill_get_unit_target) (int *skill_id);
-typedef int (*HPMHOOK_post_skill_get_unit_target) (int retVal___, int skill_id);
+typedef int (*HPMHOOK_pre_skill_get_unit_target) (int *skill_id, int *skill_lv);
+typedef int (*HPMHOOK_post_skill_get_unit_target) (int retVal___, int skill_id, int skill_lv);
typedef int (*HPMHOOK_pre_skill_get_unit_interval) (int *skill_id, int *skill_lv);
typedef int (*HPMHOOK_post_skill_get_unit_interval) (int retVal___, int skill_id, int skill_lv);
-typedef int (*HPMHOOK_pre_skill_get_unit_bl_target) (int *skill_id);
-typedef int (*HPMHOOK_post_skill_get_unit_bl_target) (int retVal___, int skill_id);
+typedef int (*HPMHOOK_pre_skill_get_unit_bl_target) (int *skill_id, int *skill_lv);
+typedef int (*HPMHOOK_post_skill_get_unit_bl_target) (int retVal___, int skill_id, int skill_lv);
typedef int (*HPMHOOK_pre_skill_get_unit_layout_type) (int *skill_id, int *skill_lv);
typedef int (*HPMHOOK_post_skill_get_unit_layout_type) (int retVal___, int skill_id, int skill_lv);
typedef int (*HPMHOOK_pre_skill_get_unit_range) (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 80c309a8c..1e29af351 100644
--- a/src/plugins/HPMHooking/HPMHooking_map.Hooks.inc
+++ b/src/plugins/HPMHooking/HPMHooking_map.Hooks.inc
@@ -77768,15 +77768,15 @@ int HP_skill_get_unit_flag(int skill_id) {
}
return retVal___;
}
-int HP_skill_get_unit_target(int skill_id) {
+int HP_skill_get_unit_target(int skill_id, int skill_lv) {
int hIndex = 0;
int retVal___ = 0;
if (HPMHooks.count.HP_skill_get_unit_target_pre > 0) {
- int (*preHookFunc) (int *skill_id);
+ int (*preHookFunc) (int *skill_id, int *skill_lv);
*HPMforce_return = false;
for (hIndex = 0; hIndex < HPMHooks.count.HP_skill_get_unit_target_pre; hIndex++) {
preHookFunc = HPMHooks.list.HP_skill_get_unit_target_pre[hIndex].func;
- retVal___ = preHookFunc(&skill_id);
+ retVal___ = preHookFunc(&skill_id, &skill_lv);
}
if (*HPMforce_return) {
*HPMforce_return = false;
@@ -77784,13 +77784,13 @@ int HP_skill_get_unit_target(int skill_id) {
}
}
{
- retVal___ = HPMHooks.source.skill.get_unit_target(skill_id);
+ retVal___ = HPMHooks.source.skill.get_unit_target(skill_id, skill_lv);
}
if (HPMHooks.count.HP_skill_get_unit_target_post > 0) {
- int (*postHookFunc) (int retVal___, int skill_id);
+ int (*postHookFunc) (int retVal___, int skill_id, int skill_lv);
for (hIndex = 0; hIndex < HPMHooks.count.HP_skill_get_unit_target_post; hIndex++) {
postHookFunc = HPMHooks.list.HP_skill_get_unit_target_post[hIndex].func;
- retVal___ = postHookFunc(retVal___, skill_id);
+ retVal___ = postHookFunc(retVal___, skill_id, skill_lv);
}
}
return retVal___;
@@ -77822,15 +77822,15 @@ int HP_skill_get_unit_interval(int skill_id, int skill_lv) {
}
return retVal___;
}
-int HP_skill_get_unit_bl_target(int skill_id) {
+int HP_skill_get_unit_bl_target(int skill_id, int skill_lv) {
int hIndex = 0;
int retVal___ = 0;
if (HPMHooks.count.HP_skill_get_unit_bl_target_pre > 0) {
- int (*preHookFunc) (int *skill_id);
+ int (*preHookFunc) (int *skill_id, int *skill_lv);
*HPMforce_return = false;
for (hIndex = 0; hIndex < HPMHooks.count.HP_skill_get_unit_bl_target_pre; hIndex++) {
preHookFunc = HPMHooks.list.HP_skill_get_unit_bl_target_pre[hIndex].func;
- retVal___ = preHookFunc(&skill_id);
+ retVal___ = preHookFunc(&skill_id, &skill_lv);
}
if (*HPMforce_return) {
*HPMforce_return = false;
@@ -77838,13 +77838,13 @@ int HP_skill_get_unit_bl_target(int skill_id) {
}
}
{
- retVal___ = HPMHooks.source.skill.get_unit_bl_target(skill_id);
+ retVal___ = HPMHooks.source.skill.get_unit_bl_target(skill_id, skill_lv);
}
if (HPMHooks.count.HP_skill_get_unit_bl_target_post > 0) {
- int (*postHookFunc) (int retVal___, int skill_id);
+ int (*postHookFunc) (int retVal___, int skill_id, int skill_lv);
for (hIndex = 0; hIndex < HPMHooks.count.HP_skill_get_unit_bl_target_post; hIndex++) {
postHookFunc = HPMHooks.list.HP_skill_get_unit_bl_target_post[hIndex].func;
- retVal___ = postHookFunc(retVal___, skill_id);
+ retVal___ = postHookFunc(retVal___, skill_id, skill_lv);
}
}
return retVal___;