From 3d06abbc3b917b2ce1df8245a5856904e7e1fd53 Mon Sep 17 00:00:00 2001 From: Kenpachi Developer Date: Sat, 11 Apr 2020 08:56:52 +0200 Subject: Add missing constants for global skill assignment --- src/map/mob.h | 7 +++++++ src/map/script.c | 5 +++++ 2 files changed, 12 insertions(+) (limited to 'src') diff --git a/src/map/mob.h b/src/map/mob.h index 4cfddc2cd..577e4db91 100644 --- a/src/map/mob.h +++ b/src/map/mob.h @@ -323,6 +323,13 @@ enum { MSC_SPAWN, }; +/** Special monster(-name) constants used to assign skills to a group of monsters. **/ +enum mob_group { + ALL_MOBS_NONBOSS = -1, + ALL_MOBS_BOSS = -2, + ALL_MOBS = -3, +}; + /** * Mob IDs */ diff --git a/src/map/script.c b/src/map/script.c index c08f5e829..5cdd16367 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -27847,6 +27847,11 @@ static void script_hardcoded_constants(void) script->set_constant("MST_AROUND4", MST_AROUND4, false, false); script->set_constant("MST_AROUND", MST_AROUND , false, false); + script->constdb_comment("Monster group constants"); + script->set_constant("ALL_MOBS_NONBOSS", ALL_MOBS_NONBOSS, false, false); + script->set_constant("ALL_MOBS_BOSS", ALL_MOBS_BOSS, false, false); + script->set_constant("ALL_MOBS", ALL_MOBS, false, false); + script->constdb_comment("pc block constants, use with *setpcblock* and *checkpcblock*"); script->set_constant("PCBLOCK_NONE", PCBLOCK_NONE, false, false); script->set_constant("PCBLOCK_MOVE", PCBLOCK_MOVE, false, false); -- cgit v1.2.3-70-g09d2 From c475c1eb2077fa9178561f9ea11c360285d432ee Mon Sep 17 00:00:00 2001 From: Kenpachi Developer Date: Tue, 14 Apr 2020 07:49:24 +0200 Subject: Adjust mob_getfriendstatus() to consider characters as friends for summoned monsters like mob_getfriendhprate() does --- src/map/mob.c | 42 ++++++++++++++----------- src/map/mob.h | 2 +- src/plugins/HPMHooking/HPMHooking.Defs.inc | 4 +-- src/plugins/HPMHooking/HPMHooking_map.Hooks.inc | 8 ++--- 4 files changed, 30 insertions(+), 26 deletions(-) (limited to 'src') diff --git a/src/map/mob.c b/src/map/mob.c index 51a32abd9..5a20c20d2 100644 --- a/src/map/mob.c +++ b/src/map/mob.c @@ -3393,42 +3393,49 @@ static struct block_list *mob_getmasterhpltmaxrate(struct mob_data *md, int rate static int mob_getfriendstatus_sub(struct block_list *bl, va_list ap) { int cond1,cond2; - struct mob_data **fr = NULL, *md = NULL, *mmd = NULL; + struct block_list **fr = NULL; + struct mob_data *md = NULL; int flag=0; nullpo_ret(bl); - Assert_ret(bl->type == BL_MOB); - md = BL_UCAST(BL_MOB, bl); - nullpo_ret(mmd=va_arg(ap,struct mob_data *)); + nullpo_ret(md = va_arg(ap, struct mob_data *)); - if( mmd->bl.id == bl->id && !(battle_config.mob_ai&0x10) ) + if (md->bl.id == bl->id && (battle_config.mob_ai & 0x10) == 0) return 0; - if (battle->check_target(&mmd->bl,bl,BCT_ENEMY)>0) + if (battle->check_target(&md->bl, bl, BCT_ENEMY) > 0) return 0; cond1=va_arg(ap,int); cond2=va_arg(ap,int); - fr=va_arg(ap,struct mob_data **); + fr = va_arg(ap, struct block_list **); + + if ((*fr) != NULL) // A friend was already found. + return 0; + + struct status_change *sc = status->get_sc(bl); + if( cond2==-1 ){ int j; for(j=SC_COMMON_MIN;j<=SC_COMMON_MAX && !flag;j++){ - if ((flag=(md->sc.data[j] != NULL))) //Once an effect was found, break out. [Skotlex] + if ((flag = (sc->data[j] != NULL)) != 0) // Once an effect was found, break out. [Skotlex] break; } }else - flag=( md->sc.data[cond2] != NULL ); + flag = (sc->data[cond2] != NULL); if( flag^( cond1==MSC_FRIENDSTATUSOFF ) ) - (*fr)=md; + (*fr) = bl; return 0; } -static struct mob_data *mob_getfriendstatus(struct mob_data *md, int cond1, int cond2) +static struct block_list *mob_getfriendstatus(struct mob_data *md, int cond1, int cond2) { - struct mob_data* fr = NULL; + struct block_list *fr = NULL; nullpo_ret(md); - map->foreachinrange(mob->getfriendstatus_sub, &md->bl, 8,BL_MOB, md,cond1,cond2,&fr); + int type = (md->special_state.ai != AI_NONE) ? BL_PC : BL_MOB; + + map->foreachinrange(mob->getfriendstatus_sub, &md->bl, 8, type, md, cond1, cond2, &fr); return fr; } @@ -3440,7 +3447,6 @@ static int mobskill_use(struct mob_data *md, int64 tick, int event) struct mob_skill *ms; struct block_list *fbl = NULL; //Friend bl, which can either be a BL_PC or BL_MOB depending on the situation. [Skotlex] struct block_list *bl; - struct mob_data *fmd = NULL; int i,j,n; nullpo_ret(md); @@ -3512,7 +3518,8 @@ static int mobskill_use(struct mob_data *md, int64 tick, int event) flag = ((fbl = mob->getfriendhprate(md, ms[i].cond2, ms[i].val[0])) != NULL); break; case MSC_FRIENDSTATUSON: // friend status[num] on case MSC_FRIENDSTATUSOFF: // friend status[num] off - flag = ((fmd = mob->getfriendstatus(md, ms[i].cond1, ms[i].cond2)) != NULL); break; + flag = ((fbl = mob->getfriendstatus(md, ms[i].cond1, ms[i].cond2)) != NULL); + break; case MSC_SLAVELT: // slave < num flag = (mob->countslave(&md->bl) < c2 ); break; case MSC_ATTACKPCGT: // attack pc > num @@ -3564,7 +3571,7 @@ static int mobskill_use(struct mob_data *md, int64 tick, int event) break; FALLTHROUGH case MST_FRIEND: - bl = fbl?fbl:(fmd?&fmd->bl:&md->bl); + bl = (fbl != NULL) ? fbl : &md->bl; break; default: bl = &md->bl; @@ -3610,9 +3617,6 @@ static int mobskill_use(struct mob_data *md, int64 tick, int event) if (fbl) { bl = fbl; break; - } else if (fmd) { - bl = &fmd->bl; - break; } // else fall through FALLTHROUGH default: diff --git a/src/map/mob.h b/src/map/mob.h index 577e4db91..6ad1ce705 100644 --- a/src/map/mob.h +++ b/src/map/mob.h @@ -573,7 +573,7 @@ struct mob_interface { struct block_list* (*getfriendhprate) (struct mob_data *md, int min_rate, int max_rate); struct block_list* (*getmasterhpltmaxrate) (struct mob_data *md, int rate); int (*getfriendstatus_sub) (struct block_list *bl, va_list ap); - struct mob_data* (*getfriendstatus) (struct mob_data *md, int cond1, int cond2); + struct block_list *(*getfriendstatus) (struct mob_data *md, int cond1, int cond2); int (*skill_use) (struct mob_data *md, int64 tick, int event); int (*skill_event) (struct mob_data *md, struct block_list *src, int64 tick, int flag); int (*is_clone) (int class_); diff --git a/src/plugins/HPMHooking/HPMHooking.Defs.inc b/src/plugins/HPMHooking/HPMHooking.Defs.inc index b8aa5ae61..3bd0b7fe6 100644 --- a/src/plugins/HPMHooking/HPMHooking.Defs.inc +++ b/src/plugins/HPMHooking/HPMHooking.Defs.inc @@ -5452,8 +5452,8 @@ typedef struct block_list* (*HPMHOOK_pre_mob_getmasterhpltmaxrate) (struct mob_d typedef struct block_list* (*HPMHOOK_post_mob_getmasterhpltmaxrate) (struct block_list* retVal___, struct mob_data *md, int rate); typedef int (*HPMHOOK_pre_mob_getfriendstatus_sub) (struct block_list **bl, va_list ap); typedef int (*HPMHOOK_post_mob_getfriendstatus_sub) (int retVal___, struct block_list *bl, va_list ap); -typedef struct mob_data* (*HPMHOOK_pre_mob_getfriendstatus) (struct mob_data **md, int *cond1, int *cond2); -typedef struct mob_data* (*HPMHOOK_post_mob_getfriendstatus) (struct mob_data* retVal___, struct mob_data *md, int cond1, int cond2); +typedef struct block_list *(*HPMHOOK_pre_mob_getfriendstatus) (struct mob_data **md, int *cond1, int *cond2); +typedef struct block_list *(*HPMHOOK_post_mob_getfriendstatus) (struct mob_data* retVal___, struct mob_data *md, int cond1, int cond2); typedef int (*HPMHOOK_pre_mob_skill_use) (struct mob_data **md, int64 *tick, int *event); typedef int (*HPMHOOK_post_mob_skill_use) (int retVal___, struct mob_data *md, int64 tick, int event); typedef int (*HPMHOOK_pre_mob_skill_event) (struct mob_data **md, struct block_list **src, int64 *tick, int *flag); diff --git a/src/plugins/HPMHooking/HPMHooking_map.Hooks.inc b/src/plugins/HPMHooking/HPMHooking_map.Hooks.inc index 940f96ca2..57351b808 100644 --- a/src/plugins/HPMHooking/HPMHooking_map.Hooks.inc +++ b/src/plugins/HPMHooking/HPMHooking_map.Hooks.inc @@ -53703,11 +53703,11 @@ int HP_mob_getfriendstatus_sub(struct block_list *bl, va_list ap) { } return retVal___; } -struct mob_data* HP_mob_getfriendstatus(struct mob_data *md, int cond1, int cond2) { +struct block_list *HP_mob_getfriendstatus(struct mob_data *md, int cond1, int cond2) { int hIndex = 0; - struct mob_data* retVal___ = NULL; + struct block_list *retVal___ = NULL; if (HPMHooks.count.HP_mob_getfriendstatus_pre > 0) { - struct mob_data* (*preHookFunc) (struct mob_data **md, int *cond1, int *cond2); + struct block_list *(*preHookFunc) (struct mob_data **md, int *cond1, int *cond2); *HPMforce_return = false; for (hIndex = 0; hIndex < HPMHooks.count.HP_mob_getfriendstatus_pre; hIndex++) { preHookFunc = HPMHooks.list.HP_mob_getfriendstatus_pre[hIndex].func; @@ -53722,7 +53722,7 @@ struct mob_data* HP_mob_getfriendstatus(struct mob_data *md, int cond1, int cond retVal___ = HPMHooks.source.mob.getfriendstatus(md, cond1, cond2); } if (HPMHooks.count.HP_mob_getfriendstatus_post > 0) { - struct mob_data* (*postHookFunc) (struct mob_data* retVal___, struct mob_data *md, int cond1, int cond2); + struct block_list *(*postHookFunc) (struct block_list *retVal___, struct mob_data *md, int cond1, int cond2); for (hIndex = 0; hIndex < HPMHooks.count.HP_mob_getfriendstatus_post; hIndex++) { postHookFunc = HPMHooks.list.HP_mob_getfriendstatus_post[hIndex].func; retVal___ = postHookFunc(retVal___, md, cond1, cond2); -- cgit v1.2.3-70-g09d2 From 4121c52ab55a72d92a33d9fc3b6c36f5ddcb8cf9 Mon Sep 17 00:00:00 2001 From: Kenpachi Developer Date: Tue, 14 Apr 2020 07:50:42 +0200 Subject: Allow MSC_AFTERSKILL to trigger every skill if ConditionData is set to 0 (like MSC_SKILLUSED) --- src/map/mob.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/map/mob.c b/src/map/mob.c index 5a20c20d2..207184aca 100644 --- a/src/map/mob.c +++ b/src/map/mob.c @@ -3529,7 +3529,8 @@ static int mobskill_use(struct mob_data *md, int64 tick, int event) case MSC_ATTACKPCGE: // attack pc >= num flag = (unit->counttargeted(&md->bl) >= c2); break; case MSC_AFTERSKILL: - flag = (md->ud.skill_id == c2); break; + flag = (md->ud.skill_id == c2 || c2 == 0); + break; case MSC_RUDEATTACKED: flag = (md->state.attacked_count >= RUDE_ATTACKED_COUNT); if (flag) md->state.attacked_count = 0; //Rude attacked count should be reset after the skill condition is met. Thanks to Komurka [Skotlex] -- cgit v1.2.3-70-g09d2 From 2962a442c2019a80cb370ea5ccb50209ee30307e Mon Sep 17 00:00:00 2001 From: Kenpachi Developer Date: Tue, 14 Apr 2020 07:51:59 +0200 Subject: Add error message for exceeding MAX_MOBSKILL in global skill assignment --- src/map/mob.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/map/mob.c b/src/map/mob.c index 207184aca..789b9b11f 100644 --- a/src/map/mob.c +++ b/src/map/mob.c @@ -5655,8 +5655,11 @@ static bool mob_skill_db_libconfig_sub_skill(struct config_setting_t *it, int n, continue; } ARR_FIND(0, MAX_MOBSKILL, j, mob->db_data[i]->skill[j].skill_id == 0); - if (j == MAX_MOBSKILL) + if (j == MAX_MOBSKILL) { + ShowError("mob_skill_db_libconfig_sub_skill: Too many skills for monster %d. (Global ID %d.)\n", + i, -mob_id); continue; + } memcpy(&mob->db_data[i]->skill[j], ms, sizeof(struct mob_skill)); mob->db_data[i]->maxskill = j + 1; -- cgit v1.2.3-70-g09d2 From cec50890c0f8a8f0c099dd5ae67b28ccef0a0087 Mon Sep 17 00:00:00 2001 From: Kenpachi Developer Date: Tue, 14 Apr 2020 07:52:47 +0200 Subject: Add error message for unsupported global skill clearing --- src/map/mob.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/map/mob.c b/src/map/mob.c index 789b9b11f..aae09380c 100644 --- a/src/map/mob.c +++ b/src/map/mob.c @@ -5516,8 +5516,11 @@ static bool mob_skill_db_libconfig_sub_skill(struct config_setting_t *it, int n, // If ClearSkills flag is enabled clear all the previous skills. if (libconfig->setting_lookup_bool_real(it, "ClearSkills", &clearskills) && clearskills) { - if (mob_id < 0) // Clearing skills globaly is not supported + if (mob_id < 0) { + ShowError("mob_skill_db_libconfig_sub_skill: Global skill clearing is not supported. (Global ID %d.)\n", + mob_id); return false; + } memset(mob->db_data[mob_id]->skill, 0, sizeof(struct mob_skill) * MAX_MOBSKILL); mob->db_data[mob_id]->maxskill = 0; return true; -- cgit v1.2.3-70-g09d2 From f8a7e273ad8b459e21fa6217bc65b8135e8c61e8 Mon Sep 17 00:00:00 2001 From: Kenpachi Developer Date: Tue, 14 Apr 2020 07:53:56 +0200 Subject: Add proper defaulting and capping to mob_skill_db_libconfig_sub_skill() --- src/map/mob.c | 48 ++++++++++++++++++++++++------------------------ 1 file changed, 24 insertions(+), 24 deletions(-) (limited to 'src') diff --git a/src/map/mob.c b/src/map/mob.c index aae09380c..68b255e27 100644 --- a/src/map/mob.c +++ b/src/map/mob.c @@ -78,6 +78,7 @@ struct mob_interface *mob; // Move probability for mobs away from players (rate of 1000 minute) // in Aegis, this is 100% for mobs that have been activated by players and none otherwise. #define MOB_LAZYMOVEPERC(md) ((md)->state.spotted?1000:0) +#define MOB_MAX_CASTTIME (10 * 60 * 1000) // Maximum cast time for monster skills. (10 minutes) #define MOB_MAX_DELAY (24*3600*1000) #define MAX_MINCHASE 30 //Max minimum chase value to use for mobs. #define RUDE_ATTACKED_COUNT 2 //After how many rude-attacks should the skill be used? @@ -5499,7 +5500,6 @@ static bool mob_skill_db_libconfig_sub(struct config_setting_t *it, int n) static bool mob_skill_db_libconfig_sub_skill(struct config_setting_t *it, int n, int mob_id) { int i, j, idx = 0; - int i32; int skill_id = 0; int skill_idx = 0; bool clearskills = false; @@ -5539,19 +5539,19 @@ static bool mob_skill_db_libconfig_sub_skill(struct config_setting_t *it, int n, } ms->skill_id = skill_id; + int i32 = MSS_ANY; if (mob->lookup_const(it, "SkillState", &i32) && (i32 < MSS_ANY || i32 > MSS_ANYTARGET)) { ShowWarning("mob_skill_db_libconfig_sub_skill: Invalid skill state %d for skill id %d in monster %d, defaulting to MSS_ANY.\n", i32, skill_id, mob_id); i32 = MSS_ANY; } ms->state = i32; - if (!libconfig->setting_lookup_int(it, "SkillLevel", &i32) || i32 <= 0) - i32 = 1; - ms->skill_lv = i32 > battle_config.mob_max_skilllvl ? battle_config.mob_max_skilllvl : i32; //we strip max skill level + int res = libconfig->setting_lookup_int(it, "SkillLevel", &i32); + ms->skill_lv = (res == CONFIG_FALSE) ? 1 : cap_value(i32, 1, battle_config.mob_max_skilllvl); //Apply battle_config modifiers to rate (permillage) and delay [Skotlex] - if (libconfig->setting_lookup_int(it, "Rate", &i32)) - ms->permillage = i32; + res = libconfig->setting_lookup_int(it, "Rate", &i32); + ms->permillage = (res == CONFIG_FALSE) ? 1 : cap_value(i32, 1, 10000); if (battle_config.mob_skill_rate != 100) ms->permillage = ms->permillage * battle_config.mob_skill_rate / 100; @@ -5560,22 +5560,24 @@ static bool mob_skill_db_libconfig_sub_skill(struct config_setting_t *it, int n, else if (ms->permillage == 0 && battle_config.mob_skill_rate) ms->permillage = 1; - if (libconfig->setting_lookup_int(it, "CastTime", &i32) && i32 > 0) - ms->casttime = i32; + res = libconfig->setting_lookup_int(it, "CastTime", &i32); + ms->casttime = (res == CONFIG_FALSE) ? 0 : cap_value(i32, 0, MOB_MAX_CASTTIME); + + res = libconfig->setting_lookup_int(it, "Delay", &i32); + ms->delay = (res == CONFIG_FALSE) ? 0 : cap_value(i32, 0, MOB_MAX_DELAY); - if (libconfig->setting_lookup_int(it, "Delay", &i32)) - ms->delay = i32; if (battle_config.mob_skill_delay != 100) ms->delay = ms->delay * battle_config.mob_skill_delay / 100; - if (ms->delay < 0 || ms->delay > MOB_MAX_DELAY) //time overflow? - ms->delay = MOB_MAX_DELAY; - if (libconfig->setting_lookup_bool(it, "Cancelable", &i32)) - ms->cancel = (i32 == 0) ? 0 : 1; + ms->delay = min(ms->delay, MOB_MAX_DELAY); + + res = libconfig->setting_lookup_bool(it, "Cancelable", &i32); + ms->cancel = (res == CONFIG_FALSE) ? 0 : cap_value(i32, 0, 1); + i32 = MST_TARGET; if (mob->lookup_const(it, "SkillTarget", &i32) && (i32 < MST_TARGET || i32 > MST_AROUND)) { ShowWarning("mob_skill_db_libconfig_sub_skill: Invalid skill target %d for skill id %d in monster %d, defaulting to MST_TARGET.\n", i32, skill_id, mob_id); - ms->target = MST_TARGET; + i32 = MST_TARGET; } ms->target = i32; @@ -5595,14 +5597,14 @@ static bool mob_skill_db_libconfig_sub_skill(struct config_setting_t *it, int n, ms->target = MST_TARGET; } + i32 = MSC_ALWAYS; if (mob->lookup_const(it, "CastCondition", &i32) && (i32 < MSC_ALWAYS || i32 > MSC_SPAWN)) { ShowWarning("mob_skill_db_libconfig_sub_skill: Invalid skill condition %d for skill id %d in monster %d, defaulting to MSC_ALWAYS.\n", i32, skill_id, mob_id); - ms->cond1 = MSC_ALWAYS; + i32 = MSC_ALWAYS; } ms->cond1 = i32; - if (mob->lookup_const(it, "ConditionData", &i32)) - ms->cond2 = i32; + ms->cond2 = !mob->lookup_const(it, "ConditionData", &i32) ? 0 : cap_value(i32, SHRT_MIN, SHRT_MAX); for (i = 0; i < 5; i++) { char valname[16]; @@ -5631,13 +5633,11 @@ static bool mob_skill_db_libconfig_sub_skill(struct config_setting_t *it, int n, ms->val[1] = MD_NONE; //Do not "set" it. } - if (libconfig->setting_lookup_int(it, "Emotion", &i32)) - ms->emotion = i32; - else - ms->emotion = -1; + res = libconfig->setting_lookup_int(it, "Emotion", &i32); + ms->emotion = (res == CONFIG_FALSE) ? -1 : cap_value(i32, -1, SHRT_MAX); - if (libconfig->setting_lookup_int(it, "ChatMsgID", &i32) && i32 > 0 && i32 <= MAX_MOB_CHAT) { - if (mob->chat_db[i32] == NULL) { + if (libconfig->setting_lookup_int(it, "ChatMsgID", &i32) == CONFIG_TRUE) { + if (i32 <= 0 || i32 > MAX_MOB_CHAT || mob->chat_db[i32] == NULL) { ShowWarning("mob_skill_db_libconfig_sub_skill: Invalid msg id %d for skill id %d in monster %d, ignoring.\n", i32, skill_id, mob_id); } else { ms->msg_id = i32; -- cgit v1.2.3-70-g09d2 From a719b01d46a6285a205b1a90a36ce61482038cf8 Mon Sep 17 00:00:00 2001 From: Kenpachi Developer Date: Tue, 14 Apr 2020 07:55:04 +0200 Subject: Remove unnecessary skill target check for ground skills from mob_skill_db_libconfig_sub_skill() --- src/map/mob.c | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/map/mob.c b/src/map/mob.c index 68b255e27..2f9fc3e99 100644 --- a/src/map/mob.c +++ b/src/map/mob.c @@ -5581,19 +5581,11 @@ static bool mob_skill_db_libconfig_sub_skill(struct config_setting_t *it, int n, } ms->target = i32; - //Check that the target condition is right for the skill type. [Skotlex] + // Check the target condition for non-ground skills. (Ground skills can use every target.) skill_idx = skill->get_index(skill_id); - if (skill->get_casttype2(skill_idx) == CAST_GROUND) {//Ground skill. - if (ms->target > MST_AROUND) { - ShowWarning("mob_skill_db_libconfig_sub_skill: Wrong mob skill target for ground skill %d (%s) for %s.\n", - ms->skill_id, skill->dbs->db[skill_idx].name, - mob_id < 0 ? "all mobs" : mob->db_data[mob_id]->sprite); - ms->target = MST_TARGET; - } - } else if (ms->target > MST_MASTER) { + if (skill->get_casttype2(skill_idx) != CAST_GROUND && ms->target > MST_MASTER) { ShowWarning("mob_skill_db_libconfig_sub_skill: Wrong mob skill target 'around' for non-ground skill %d (%s) for %s.\n", - ms->skill_id, skill->dbs->db[skill_idx].name, - mob_id < 0 ? "all mobs" : mob->db_data[mob_id]->sprite); + ms->skill_id, skill->dbs->db[skill_idx].name, mob_id < 0 ? "all mobs" : mob->db_data[mob_id]->sprite); ms->target = MST_TARGET; } -- cgit v1.2.3-70-g09d2 From 55544037331569a5431751cb1df9d5576023b338 Mon Sep 17 00:00:00 2001 From: Kenpachi Developer Date: Tue, 14 Apr 2020 07:57:04 +0200 Subject: Apply code style to mob_getfriendstatus() --- src/map/mob.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/map/mob.c b/src/map/mob.c index 2f9fc3e99..843eabb8d 100644 --- a/src/map/mob.c +++ b/src/map/mob.c @@ -3429,14 +3429,25 @@ static int mob_getfriendstatus_sub(struct block_list *bl, va_list ap) return 0; } +/** + * Gets a random monster/character within a range of 8 cells around md. + * If md is summoned (no monster slave!) a character is picker, otherwise a monster. + * + * @param md The monster which tries to cast a skill. + * @param cond1 Whether to check for active or inactive status change. (MSC_FRIENDSTATUSON/MSC_FRIENDSTATUSOFF) + * @param cond2 The status change (SC_* flag) to check. + * @return A randomly picked monster/character within range. + * + **/ static struct block_list *mob_getfriendstatus(struct mob_data *md, int cond1, int cond2) { - struct block_list *fr = NULL; nullpo_ret(md); int type = (md->special_state.ai != AI_NONE) ? BL_PC : BL_MOB; + struct block_list *fr = NULL; map->foreachinrange(mob->getfriendstatus_sub, &md->bl, 8, type, md, cond1, cond2, &fr); + return fr; } -- cgit v1.2.3-70-g09d2 From 349b2f2f9cf81bf869aca7adf76f7766352dee67 Mon Sep 17 00:00:00 2001 From: Kenpachi Developer Date: Tue, 14 Apr 2020 08:00:57 +0200 Subject: Apply code style to mob_getfriendstatus_sub() --- src/map/mob.c | 44 ++++++++++++++++++++++++++------------------ 1 file changed, 26 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/map/mob.c b/src/map/mob.c index 843eabb8d..3fee89d8d 100644 --- a/src/map/mob.c +++ b/src/map/mob.c @@ -3388,42 +3388,50 @@ static struct block_list *mob_getmasterhpltmaxrate(struct mob_data *md, int rate return NULL; } -/*========================================== - * What a status state suits by nearby MOB is looked for. - *------------------------------------------*/ + +/** + * Checks if the passed monster/character meets the passed status change requirements + * and returns it by reference parameter on success. + * + * @param bl The monster/character to check. + * @param ap List of arguments. (Source monster, MSC_* flag, SC_* flag, reference bl.) + * @return Always 0. + * + **/ static int mob_getfriendstatus_sub(struct block_list *bl, va_list ap) { - int cond1,cond2; - struct block_list **fr = NULL; - struct mob_data *md = NULL; - int flag=0; - nullpo_ret(bl); - nullpo_ret(md = va_arg(ap, struct mob_data *)); + + struct mob_data *md = va_arg(ap, struct mob_data *); + + nullpo_ret(md); if (md->bl.id == bl->id && (battle_config.mob_ai & 0x10) == 0) return 0; if (battle->check_target(&md->bl, bl, BCT_ENEMY) > 0) return 0; - cond1=va_arg(ap,int); - cond2=va_arg(ap,int); - fr = va_arg(ap, struct block_list **); + + int cond1 = va_arg(ap, int); + int cond2 = va_arg(ap, int); + struct block_list **fr = va_arg(ap, struct block_list **); if ((*fr) != NULL) // A friend was already found. return 0; + int flag = 0; struct status_change *sc = status->get_sc(bl); - if( cond2==-1 ){ - int j; - for(j=SC_COMMON_MIN;j<=SC_COMMON_MAX && !flag;j++){ - if ((flag = (sc->data[j] != NULL)) != 0) // Once an effect was found, break out. [Skotlex] + if (cond2 == -1) { // Check for any of the common status alignments. + for (int i = SC_COMMON_MIN; i <= SC_COMMON_MAX; i++) { + if ((flag = (sc->data[i] != NULL)) != 0) // Once an effect was found, break out. [Skotlex] break; } - }else + } else { flag = (sc->data[cond2] != NULL); - if( flag^( cond1==MSC_FRIENDSTATUSOFF ) ) + } + + if ((flag ^ (cond1 == MSC_FRIENDSTATUSOFF)) != 0) (*fr) = bl; return 0; -- cgit v1.2.3-70-g09d2 From 9df5181b9e2cdd2bf549aada4e844d624c5cccc9 Mon Sep 17 00:00:00 2001 From: Kenpachi Developer Date: Tue, 14 Apr 2020 08:10:53 +0200 Subject: Apply code style to mob_skill_use() --- src/map/mob.c | 396 ++++++++++++++++++++++++++++++++-------------------------- 1 file changed, 222 insertions(+), 174 deletions(-) (limited to 'src') diff --git a/src/map/mob.c b/src/map/mob.c index 3fee89d8d..78ba4e712 100644 --- a/src/map/mob.c +++ b/src/map/mob.c @@ -3459,225 +3459,273 @@ static struct block_list *mob_getfriendstatus(struct mob_data *md, int cond1, in return fr; } -/*========================================== - * Skill use judging - *------------------------------------------*/ -static int mobskill_use(struct mob_data *md, int64 tick, int event) +/** + * Checks if skill cast condition in fulfilled and executes the skill in case of success. + * + * @param md The monster which tries to cast a skill. + * @param tick The timestamp of skill execution. + * @param event The MSC_* flag which triggered the skill execution. (-1 for non-event skill conditions.) + * @return 1 on success, 0 on failure. + * + **/ +static int mob_skill_use(struct mob_data *md, int64 tick, int event) { - struct mob_skill *ms; - struct block_list *fbl = NULL; //Friend bl, which can either be a BL_PC or BL_MOB depending on the situation. [Skotlex] - struct block_list *bl; - int i,j,n; - nullpo_ret(md); - nullpo_ret(ms = md->db->skill); - if (!battle_config.mob_skill_rate || md->ud.skilltimer != INVALID_TIMER || !md->db->maxskill) + struct mob_skill *ms = md->db->skill; + + nullpo_ret(ms); + + if (battle_config.mob_skill_rate == 0 || md->ud.skilltimer != INVALID_TIMER || md->db->maxskill == 0) return 0; if (event == -1 && DIFF_TICK(md->ud.canact_tick, tick) > 0) - return 0; //Skill act delay only affects non-event skills. + return 0; // Skill act delay only affects non-event skill conditions. - //Pick a starting position and loop from that. - i = (battle_config.mob_ai&0x100) ? rnd()%md->db->maxskill : 0; - for (n = 0; n < md->db->maxskill; i++, n++) { - int c2, flag = 0; + // Pick a starting position and loop from that. + int skill_idx = ((battle_config.mob_ai & 0x100) != 0) ? rnd() % md->db->maxskill : 0; - if (i == md->db->maxskill) - i = 0; + for (int i = 0; i < md->db->maxskill; skill_idx++, i++) { + if (skill_idx == md->db->maxskill) + skill_idx = 0; - if (DIFF_TICK(tick, md->skilldelay[i]) < ms[i].delay) + if (DIFF_TICK(tick, md->skilldelay[skill_idx]) < ms[skill_idx].delay) continue; - c2 = ms[i].cond2; + enum MobSkillState state = ms[skill_idx].state; - if (ms[i].state != md->state.skillstate) { - if (md->state.skillstate != MSS_DEAD && (ms[i].state == MSS_ANY || - (ms[i].state == MSS_ANYTARGET && md->target_id && md->state.skillstate != MSS_LOOT) - )) //ANYTARGET works with any state as long as there's a target. [Skotlex] - ; - else + if (state != md->state.skillstate) { + bool state_dead = (md->state.skillstate == MSS_DEAD); + bool any_target = (state == MSS_ANYTARGET && md->target_id != 0 && md->state.skillstate != MSS_LOOT); + + // MSS_ANYTARGET works with any state as long as there's a target. [Skotlex] + if (state_dead || (state != MSS_ANY && !any_target)) continue; } - if (rnd() % 10000 > ms[i].permillage) //Lupus (max value = 10000) + + if (rnd() % 10000 > ms[skill_idx].permillage) continue; - if (ms[i].cond1 == event) - flag = 1; //Trigger skill. - else if (ms[i].cond1 == MSC_SKILLUSED) - flag = ((event & 0xffff) == MSC_SKILLUSED && ((event >> 16) == c2 || c2 == 0)); - else if(event == -1){ - //Avoid entering on defined events to avoid "hyper-active skill use" due to the overflow of calls to this function in battle. - switch (ms[i].cond1) - { - case MSC_ALWAYS: - flag = 1; break; - case MSC_MYHPLTMAXRATE: // HP< maxhp% - flag = get_percentage(md->status.hp, md->status.max_hp); - flag = (flag <= c2); - break; - case MSC_MYHPINRATE: - flag = get_percentage(md->status.hp, md->status.max_hp); - flag = (flag >= c2 && flag <= ms[i].val[0]); - break; - case MSC_MYSTATUSON: // status[num] on - case MSC_MYSTATUSOFF: // status[num] off - if (!md->sc.count) { - flag = 0; - } else if (ms[i].cond2 == -1) { - for (j = SC_COMMON_MIN; j <= SC_COMMON_MAX; j++) - if ((flag = (md->sc.data[j]!=NULL)) != 0) - break; - } else { - flag = (md->sc.data[ms[i].cond2]!=NULL); + int cast_cond = ms[skill_idx].cond1; + int cond_data = ms[skill_idx].cond2; + int flag = 0; + struct block_list *fbl = NULL; // Friend bl, which can either be a BL_PC or BL_MOB depending on the situation. [Skotlex] + + if (cast_cond == event) { + flag = 1; // Trigger skill. + } else if (cast_cond == MSC_SKILLUSED) { + flag = ((event & 0xFFFF) == MSC_SKILLUSED && ((event >> 16) == cond_data || cond_data == 0)); + } else if (event == -1) { + // Avoid entering on defined events to avoid "hyper-active skill use" due to the overflow of calls to this function in battle. + switch (cast_cond) { + case MSC_ALWAYS: + flag = 1; + break; + case MSC_MYHPLTMAXRATE: // HP <= x% + flag = get_percentage(md->status.hp, md->status.max_hp); + flag = (flag <= cond_data); + break; + case MSC_MYHPINRATE: // HP >= x% && HP <= y% + flag = get_percentage(md->status.hp, md->status.max_hp); + flag = (flag >= cond_data && flag <= ms[skill_idx].val[0]); + break; + case MSC_MYSTATUSON: // Status change x is active. + case MSC_MYSTATUSOFF: // Status change x is inactive. + if (cond_data == -1) { // Check for any of the common status alignments. + for (int j = SC_COMMON_MIN; j <= SC_COMMON_MAX; j++) { + if ((flag = (md->sc.data[j] != NULL)) != 0) + break; } - flag ^= (ms[i].cond1 == MSC_MYSTATUSOFF); break; - case MSC_FRIENDHPLTMAXRATE: // friend HP < maxhp% - flag = ((fbl = mob->getfriendhprate(md, 0, ms[i].cond2)) != NULL); break; - case MSC_FRIENDHPINRATE: - flag = ((fbl = mob->getfriendhprate(md, ms[i].cond2, ms[i].val[0])) != NULL); break; - case MSC_FRIENDSTATUSON: // friend status[num] on - case MSC_FRIENDSTATUSOFF: // friend status[num] off - flag = ((fbl = mob->getfriendstatus(md, ms[i].cond1, ms[i].cond2)) != NULL); - break; - case MSC_SLAVELT: // slave < num - flag = (mob->countslave(&md->bl) < c2 ); break; - case MSC_ATTACKPCGT: // attack pc > num - flag = (unit->counttargeted(&md->bl) > c2); break; - case MSC_SLAVELE: // slave <= num - flag = (mob->countslave(&md->bl) <= c2 ); break; - case MSC_ATTACKPCGE: // attack pc >= num - flag = (unit->counttargeted(&md->bl) >= c2); break; - case MSC_AFTERSKILL: - flag = (md->ud.skill_id == c2 || c2 == 0); - break; - case MSC_RUDEATTACKED: - flag = (md->state.attacked_count >= RUDE_ATTACKED_COUNT); - if (flag) md->state.attacked_count = 0; //Rude attacked count should be reset after the skill condition is met. Thanks to Komurka [Skotlex] - break; - case MSC_MASTERHPLTMAXRATE: - flag = ((fbl = mob->getmasterhpltmaxrate(md, ms[i].cond2)) != NULL); break; - case MSC_MASTERATTACKED: - flag = (md->master_id > 0 && (fbl=map->id2bl(md->master_id)) != NULL && unit->counttargeted(fbl) > 0); - break; - case MSC_ALCHEMIST: - flag = (md->state.alchemist); - break; + } else { + flag = (md->sc.data[cond_data] != NULL); + } + + flag ^= (cast_cond == MSC_MYSTATUSOFF); + break; + case MSC_FRIENDHPLTMAXRATE: // FriendHP <= x% + flag = ((fbl = mob->getfriendhprate(md, 0, cond_data)) != NULL); + break; + case MSC_FRIENDHPINRATE: // FriendHP >= x% && FriendHP <= y% + flag = ((fbl = mob->getfriendhprate(md, cond_data, ms[skill_idx].val[0])) != NULL); + break; + case MSC_FRIENDSTATUSON: // Friend's status change x is active. + case MSC_FRIENDSTATUSOFF: // Friend's status change x is inactive. + flag = ((fbl = mob->getfriendstatus(md, cast_cond, cond_data)) != NULL); + break; + case MSC_SLAVELT: // Monster has less than x active slaves. + flag = (mob->countslave(&md->bl) < cond_data); + break; + case MSC_ATTACKPCGT: // Monster is attacked by more than x units. + flag = (unit->counttargeted(&md->bl) > cond_data); + break; + case MSC_SLAVELE: // Monster has x or less active slaves. + flag = (mob->countslave(&md->bl) <= cond_data); + break; + case MSC_ATTACKPCGE: // Monster is attacked by x or more units. + flag = (unit->counttargeted(&md->bl) >= cond_data); + break; + case MSC_AFTERSKILL: // Monster used skill x, or any skill if x is 0. + flag = (md->ud.skill_id == cond_data || cond_data == 0); + break; + case MSC_RUDEATTACKED: // Monster was rude attacked RUDE_ATTACKED_COUNT or more times. + flag = (md->state.attacked_count >= RUDE_ATTACKED_COUNT); + + // Rude attacked count should be reset after the skill condition is met. Thanks to Komurka [Skotlex] + if (flag) + md->state.attacked_count = 0; + + break; + case MSC_MASTERHPLTMAXRATE: // MasterHP < x% + flag = ((fbl = mob->getmasterhpltmaxrate(md, cond_data)) != NULL); + break; + case MSC_MASTERATTACKED: // Monster's master is under attack. + flag = (md->master_id > 0 && (fbl = map->id2bl(md->master_id)) != NULL); + flag = (fbl != NULL && unit->counttargeted(fbl) > 0); + break; + case MSC_ALCHEMIST: // Monster was summoned by an Alchemist. + flag = (md->state.alchemist != 0); + break; } } - if (!flag) - continue; //Skill requisite failed to be fulfilled. + if (flag == 0) // Skill cast condition not fulfilled. + continue; - //Execute skill - if (skill->get_casttype(ms[i].skill_id) == CAST_GROUND) {//Ground skill. - short x, y; - switch (ms[i].target) { - case MST_RANDOM: //Pick a random enemy within skill range. - bl = battle->get_enemy(&md->bl, DEFAULT_ENEMY_TYPE(md), - skill->get_range2(&md->bl, ms[i].skill_id, ms[i].skill_lv)); - break; - case MST_TARGET: - case MST_AROUND5: - case MST_AROUND6: - case MST_AROUND7: - case MST_AROUND8: - bl = map->id2bl(md->target_id); - break; - case MST_MASTER: - bl = &md->bl; - if (md->master_id) - bl = map->id2bl(md->master_id); - if (bl) //Otherwise, fall through. - break; - FALLTHROUGH - case MST_FRIEND: - bl = (fbl != NULL) ? fbl : &md->bl; - break; - default: - bl = &md->bl; + // Execute skill. + if (skill->get_casttype(ms[skill_idx].skill_id) == CAST_GROUND) { // Ground skill. + int target_type = ms[skill_idx].target; + int skill_range = skill->get_range2(&md->bl, ms[skill_idx].skill_id, ms[skill_idx].skill_lv); + struct block_list *bl; + + switch (target_type) { + case MST_RANDOM: // Pick a random enemy within skill range. Skill center is monster position. + bl = battle->get_enemy(&md->bl, DEFAULT_ENEMY_TYPE(md), skill_range); + break; + case MST_TARGET: // Monster's current target is within skill range. Skill center is monster position. + case MST_AROUND5: // Monster's current target is within skill range. Skill center is a random cell within a range of 1. + case MST_AROUND6: // Monster's current target is within skill range. Skill center is a random cell within a range of 2. + case MST_AROUND7: // Monster's current target is within skill range. Skill center is a random cell within a range of 3. + case MST_AROUND8: // Monster's current target is within skill range. Skill center is a random cell within a range of 4. + bl = map->id2bl(md->target_id); + break; + case MST_MASTER: // Monster's master is within skill range. Skill center is monster position. + // If monster has no master, use the monster as target, + bl = (md->master_id != 0) ? map->id2bl(md->master_id) : &md->bl; + + if (bl != NULL) break; + + // If monster has a master but master wasn't found, try a friend. + FALLTHROUGH + case MST_FRIEND: // Monster's friend is within skill range. Skill center is monster position. + bl = (fbl != NULL) ? fbl : &md->bl; + break; + default: // Monster is within skill range. Skill center is monster position. + bl = &md->bl; + break; } - if (!bl) continue; - - x = bl->x; - y = bl->y; - // Look for an area to cast the spell around... - if (ms[i].target >= MST_AROUND1 || ms[i].target >= MST_AROUND5) { - j = ms[i].target >= MST_AROUND1? - (ms[i].target-MST_AROUND1) +1: - (ms[i].target-MST_AROUND5) +1; - map->search_freecell(&md->bl, md->bl.m, &x, &y, j, j, 3); + + if (bl == NULL) // No target found. + continue; + + short x = bl->x; + short y = bl->y; + + // Find a target cell. + if (target_type >= MST_AROUND5 && target_type <= MST_AROUND) { + int range = target_type - ((target_type >= MST_AROUND1) ? MST_AROUND1 : MST_AROUND5) + 1; + map->search_freecell(&md->bl, md->bl.m, &x, &y, range, range, 3); } - md->skill_idx = i; + + md->skill_idx = skill_idx; map->freeblock_lock(); - if( !battle->check_range(&md->bl,bl,skill->get_range2(&md->bl, ms[i].skill_id,ms[i].skill_lv)) - || !unit->skilluse_pos2(&md->bl, x, y,ms[i].skill_id, ms[i].skill_lv,ms[i].casttime, ms[i].cancel) - ) { + + uint16 sk_id = ms[skill_idx].skill_id; + uint16 sk_lv = ms[skill_idx].skill_lv; + int casttime = ms[skill_idx].casttime; + short cancel = ms[skill_idx].cancel; + + if (!battle->check_range(&md->bl, bl, skill_range) + || unit->skilluse_pos2(&md->bl, x, y, sk_id, sk_lv, casttime, cancel) == 0) { map->freeblock_unlock(); continue; } - } else { - //Targeted skill - switch (ms[i].target) { - case MST_RANDOM: //Pick a random enemy within skill range. - bl = battle->get_enemy(&md->bl, DEFAULT_ENEMY_TYPE(md), - skill->get_range2(&md->bl, ms[i].skill_id, ms[i].skill_lv)); - break; - case MST_TARGET: - bl = map->id2bl(md->target_id); - break; - case MST_MASTER: - bl = &md->bl; - if (md->master_id) - bl = map->id2bl(md->master_id); - if (bl) //Otherwise, fall through. - break; - FALLTHROUGH - case MST_FRIEND: - if (fbl) { - bl = fbl; - break; - } // else fall through - FALLTHROUGH - default: - bl = &md->bl; + } else { // Targeted skill. + int skill_range = skill->get_range2(&md->bl, ms[skill_idx].skill_id, ms[skill_idx].skill_lv); + struct block_list *bl; + + switch (ms[skill_idx].target) { + case MST_RANDOM: // Pick a random enemy within skill range. + bl = battle->get_enemy(&md->bl, DEFAULT_ENEMY_TYPE(md), skill_range); + break; + case MST_TARGET: // Monster's current target is within skill range. + bl = map->id2bl(md->target_id); + break; + case MST_MASTER: // Monster's master is within skill range. + // If monster has no master, use the monster as target, + bl = (md->master_id != 0) ? map->id2bl(md->master_id) : &md->bl; + + if (bl != NULL) break; + + // If monster has a master but master wasn't found, try a friend. + FALLTHROUGH + case MST_FRIEND: // Monster's friend is within skill range. + bl = (fbl != NULL) ? fbl : &md->bl; + break; + default: // Monster is within skill range. + bl = &md->bl; + break; } - if (!bl) continue; - md->skill_idx = i; + if (bl == NULL) // No target found. + continue; + + md->skill_idx = skill_idx; map->freeblock_lock(); - if( !battle->check_range(&md->bl,bl,skill->get_range2(&md->bl, ms[i].skill_id,ms[i].skill_lv)) - || !unit->skilluse_id2(&md->bl, bl->id,ms[i].skill_id, ms[i].skill_lv,ms[i].casttime, ms[i].cancel) - ) { + + uint16 sk_id = ms[skill_idx].skill_id; + uint16 sk_lv = ms[skill_idx].skill_lv; + int casttime = ms[skill_idx].casttime; + short cancel = ms[skill_idx].cancel; + + if (!battle->check_range(&md->bl, bl, skill_range) + || unit->skilluse_id2(&md->bl, bl->id, sk_id, sk_lv, casttime, cancel) == 0) { map->freeblock_unlock(); continue; } } - //Skill used. Post-setups... - if ( ms[ i ].msg_id ){ //Display color message [SnakeDrak] - struct mob_chat *mc = mob->chat(ms[i].msg_id); + + // Skill used. + if (ms[skill_idx].msg_id != 0) { // Display color message. [SnakeDrak] char temp[CHAT_SIZE_MAX]; char name[NAME_LENGTH]; - snprintf(name, sizeof name,"%s", md->name); - strtok(name, "#"); // discard extra name identifier if present [Daegaladh] - safesnprintf(temp, sizeof temp,"%s : %s", name, mc->msg); + struct mob_chat *mc = mob->chat(ms[skill_idx].msg_id); + + snprintf(name, sizeof(name), "%s", md->name); + strtok(name, "#"); // Discard extra name identifier if present. [Daegaladh] + safesnprintf(temp, sizeof(temp), "%s : %s", name, mc->msg); clif->messagecolor(&md->bl, mc->color, temp); } - if(!(battle_config.mob_ai&0x200)) { //pass on delay to same skill. - for (j = 0; j < md->db->maxskill; j++) - if (md->db->skill[j].skill_id == ms[i].skill_id) - md->skilldelay[j]=tick; - } else - md->skilldelay[i]=tick; + + if ((battle_config.mob_ai & 0x200) == 0) { // Pass on delay to same skill. + for (int j = 0; j < md->db->maxskill; j++) { + if (md->db->skill[j].skill_id == ms[skill_idx].skill_id) + md->skilldelay[j] = tick; + } + } else { + md->skilldelay[skill_idx] = tick; + } + map->freeblock_unlock(); return 1; } - //No skill was used. + + // No skill was used. md->skill_idx = -1; return 0; } + /*========================================== * Skill use event processing *------------------------------------------*/ @@ -6081,7 +6129,7 @@ void mob_defaults(void) mob->getmasterhpltmaxrate = mob_getmasterhpltmaxrate; mob->getfriendstatus_sub = mob_getfriendstatus_sub; mob->getfriendstatus = mob_getfriendstatus; - mob->skill_use = mobskill_use; + mob->skill_use = mob_skill_use; mob->skill_event = mobskill_event; mob->is_clone = mob_is_clone; mob->clone_spawn = mob_clone_spawn; -- cgit v1.2.3-70-g09d2 From 452b603ae4812bac490b4591f08a6f08d1571515 Mon Sep 17 00:00:00 2001 From: Kenpachi Developer Date: Tue, 14 Apr 2020 08:12:24 +0200 Subject: Adjust return value of mob_skill_use() and mobskill_event() according to code style --- src/map/mob.c | 20 ++++++++++---------- src/map/unit.c | 4 ++-- 2 files changed, 12 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/map/mob.c b/src/map/mob.c index 78ba4e712..94a032a94 100644 --- a/src/map/mob.c +++ b/src/map/mob.c @@ -1520,7 +1520,7 @@ static int mob_unlocktarget(struct mob_data *md, int64 tick) FALLTHROUGH case MSS_IDLE: // Idle skill. - if (!(++md->ud.walk_count%IDLE_SKILL_INTERVAL) && mob->skill_use(md, tick, -1)) + if ((++md->ud.walk_count % IDLE_SKILL_INTERVAL) == 0 && mob->skill_use(md, tick, -1) == 0) break; //Random walk. if (!md->master_id && @@ -1700,7 +1700,7 @@ static bool mob_ai_sub_hard(struct mob_data *md, int64 tick) || !mob->can_reach(md, tbl, md->min_chase, MSS_RUSH) ) && md->state.attacked_count++ >= RUDE_ATTACKED_COUNT - && !mob->skill_use(md, tick, MSC_RUDEATTACKED) // If can't rude Attack + && mob->skill_use(md, tick, MSC_RUDEATTACKED) == 0 // If can't rude Attack && can_move && unit->escape(&md->bl, tbl, rnd()%10 +1) // Attempt escape ) { //Escaped @@ -1728,7 +1728,7 @@ static bool mob_ai_sub_hard(struct mob_data *md, int64 tick) ) { // Rude attacked if (md->state.attacked_count++ >= RUDE_ATTACKED_COUNT - && !mob->skill_use(md, tick, MSC_RUDEATTACKED) && can_move + && mob->skill_use(md, tick, MSC_RUDEATTACKED) == 0 && can_move != 0 && !tbl && unit->escape(&md->bl, abl, rnd()%10 +1) ) { //Escaped. @@ -3465,7 +3465,7 @@ static struct block_list *mob_getfriendstatus(struct mob_data *md, int cond1, in * @param md The monster which tries to cast a skill. * @param tick The timestamp of skill execution. * @param event The MSC_* flag which triggered the skill execution. (-1 for non-event skill conditions.) - * @return 1 on success, 0 on failure. + * @return 0 on success, 1 on failure. * **/ static int mob_skill_use(struct mob_data *md, int64 tick, int event) @@ -3477,10 +3477,10 @@ static int mob_skill_use(struct mob_data *md, int64 tick, int event) nullpo_ret(ms); if (battle_config.mob_skill_rate == 0 || md->ud.skilltimer != INVALID_TIMER || md->db->maxskill == 0) - return 0; + return 1; if (event == -1 && DIFF_TICK(md->ud.canact_tick, tick) > 0) - return 0; // Skill act delay only affects non-event skill conditions. + return 1; // Skill act delay only affects non-event skill conditions. // Pick a starting position and loop from that. int skill_idx = ((battle_config.mob_ai & 0x100) != 0) ? rnd() % md->db->maxskill : 0; @@ -3718,12 +3718,12 @@ static int mob_skill_use(struct mob_data *md, int64 tick, int event) } map->freeblock_unlock(); - return 1; + return 0; } // No skill was used. md->skill_idx = -1; - return 0; + return 1; } /*========================================== @@ -3736,7 +3736,7 @@ static int mobskill_event(struct mob_data *md, struct block_list *src, int64 tic nullpo_ret(md); nullpo_ret(src); if(md->bl.prev == NULL || md->status.hp <= 0) - return 0; + return 1; if (md->special_state.ai == AI_SPHERE) {//LOne WOlf explained that ANYONE can trigger the marine countdown skill. [Skotlex] md->state.alchemist = 1; @@ -3756,7 +3756,7 @@ static int mobskill_event(struct mob_data *md, struct block_list *src, int64 tic else if (flag&BF_LONG && !(flag&BF_MAGIC)) //Long-attacked should not include magic. res = mob->skill_use(md, tick, MSC_LONGRANGEATTACKED); - if (!res) + if (res != 0) //Restore previous target only if skill condition failed to trigger. [Skotlex] md->target_id = target_id; //Otherwise check if the target is an enemy, and unlock if needed. diff --git a/src/map/unit.c b/src/map/unit.c index d484056f9..19f09f83c 100644 --- a/src/map/unit.c +++ b/src/map/unit.c @@ -436,7 +436,7 @@ static int unit_walk_toxy_timer(int tid, int64 tick, int id, intptr_t data) // Walk skills are triggered regardless of target due to the idle-walk mob state. // But avoid triggering on stop-walk calls. if (tid != INVALID_TIMER && (ud->walk_count % WALK_SKILL_INTERVAL) == 0 - && map->list[bl->m].users > 0 && mob->skill_use(md, tick, -1) == 1) { + && map->list[bl->m].users > 0 && mob->skill_use(md, tick, -1) == 0) { // Walk skills are supposed to be used while walking if (!(ud->skill_id == NPC_SELFDESTRUCTION && ud->skilltimer != INVALID_TIMER) && md->state.skillstate != MSS_WALK) { @@ -2345,7 +2345,7 @@ static int unit_attack_timer_sub(struct block_list *src, int tid, int64 tick) if(md) { //First attack is always a normal attack if(md->state.skillstate == MSS_ANGRY || md->state.skillstate == MSS_BERSERK) { - if (mob->skill_use(md,tick,-1)) { + if (mob->skill_use(md, tick, -1) == 0) { map->freeblock_unlock(); return 1; } -- cgit v1.2.3-70-g09d2 From f42ae14666dd65fa8a71e03eb61f3b9ca9828cf1 Mon Sep 17 00:00:00 2001 From: Kenpachi Developer Date: Tue, 14 Apr 2020 08:13:22 +0200 Subject: Add Windows support for predefined identifier __func__ __func__ is supported since VS 2015, which is Hercules' oldest supported version. --- src/common/cbasetypes.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/common/cbasetypes.h b/src/common/cbasetypes.h index 0b5613316..6053d86d9 100644 --- a/src/common/cbasetypes.h +++ b/src/common/cbasetypes.h @@ -95,7 +95,7 @@ // debug function name #ifndef __NETBSD__ #if !defined(__STDC_VERSION__) || __STDC_VERSION__ < 199901L -# if __GNUC__ >= 2 +# if __GNUC__ >= 2 || defined(WIN32) # define __func__ __FUNCTION__ # else # define __func__ "" -- cgit v1.2.3-70-g09d2 From e8d6a43de1ad1efe19f7091ce62b0ea52aaf3617 Mon Sep 17 00:00:00 2001 From: Kenpachi Developer Date: Tue, 14 Apr 2020 08:14:10 +0200 Subject: Apply code style to mob_skill_db_libconfig_sub_skill() --- src/map/mob.c | 124 +++++++++++++++++++++++++++++++++++----------------------- 1 file changed, 75 insertions(+), 49 deletions(-) (limited to 'src') diff --git a/src/map/mob.c b/src/map/mob.c index 94a032a94..347c42439 100644 --- a/src/map/mob.c +++ b/src/map/mob.c @@ -5564,51 +5564,70 @@ static bool mob_skill_db_libconfig_sub(struct config_setting_t *it, int n) return true; } +/** + * Reads a single monster skill from DB. + * + * @param it The libconfig settings block, which contains the skill data. + * @param n The skill data block's index within the parent monster block. + * @param mob_id The monster's ID. + * @return true on success, false on failure. + * + **/ static bool mob_skill_db_libconfig_sub_skill(struct config_setting_t *it, int n, int mob_id) { - int i, j, idx = 0; - int skill_id = 0; - int skill_idx = 0; - bool clearskills = false; - const char *name = config_setting_name(it); - struct mob_skill *ms, gms; - nullpo_retr(false, it); Assert_retr(false, mob_id <= 0 || mob->db(mob_id) != mob->dummy); - if (!(skill_id = skill->name2id(name))) { - ShowWarning("mob_skill_db_libconfig_sub_skill: Non existant skill id %d in monster %d, skipping.\n", skill_id, mob_id); + int skill_id = 0; + const char *name = config_setting_name(it); + const char *mob_str = (mob_id < 0) ? "global ID" : "monster"; + + if ((skill_id = skill->name2id(name)) == 0) { + ShowWarning("%s: Non existant skill %d in %s %d, skipping.\n", __func__, skill_id, mob_str, mob_id); return false; } + const char *skill_name = skill->get_name(skill_id); + bool clearskills = false; + // If ClearSkills flag is enabled clear all the previous skills. - if (libconfig->setting_lookup_bool_real(it, "ClearSkills", &clearskills) && clearskills) { + if (libconfig->setting_lookup_bool_real(it, "ClearSkills", &clearskills) == CONFIG_TRUE && clearskills) { if (mob_id < 0) { - ShowError("mob_skill_db_libconfig_sub_skill: Global skill clearing is not supported. (Global ID %d.)\n", - mob_id); + ShowError("%s: Global skill clearing is not supported, skipping. (Global ID %d, skill %d (%s).)\n", + __func__, mob_id, skill_id, skill_name); return false; } + memset(mob->db_data[mob_id]->skill, 0, sizeof(struct mob_skill) * MAX_MOBSKILL); mob->db_data[mob_id]->maxskill = 0; return true; } - if (mob_id < 0) { - // Prepare global skill. [Skotlex] + struct mob_skill *ms; + + if (mob_id < 0) { // Prepare global skill. [Skotlex] + struct mob_skill gms; memset(&gms, 0, sizeof (struct mob_skill)); ms = &gms; } else { + int idx = 0; + ARR_FIND(0, MAX_MOBSKILL, idx, (ms = &mob->db_data[mob_id]->skill[idx])->skill_id == 0); + if (idx == MAX_MOBSKILL) { - ShowError("mob_skill_db_libconfig_sub_skill: Too many skills for monster %d\n", mob_id); + ShowError("%s: Too many skills for monster %d, skipping.\n", __func__, mob_id); return false; } + + mob->db_data[mob_id]->maxskill = idx + 1; } + ms->skill_id = skill_id; int i32 = MSS_ANY; if (mob->lookup_const(it, "SkillState", &i32) && (i32 < MSS_ANY || i32 > MSS_ANYTARGET)) { - ShowWarning("mob_skill_db_libconfig_sub_skill: Invalid skill state %d for skill id %d in monster %d, defaulting to MSS_ANY.\n", i32, skill_id, mob_id); + ShowWarning("%s: Invalid skill state %d for skill %d (%s) in %s %d, defaulting to MSS_ANY.\n", + __func__, i32, skill_id, skill_name, mob_str, mob_id); i32 = MSS_ANY; } ms->state = i32; @@ -5616,15 +5635,16 @@ static bool mob_skill_db_libconfig_sub_skill(struct config_setting_t *it, int n, int res = libconfig->setting_lookup_int(it, "SkillLevel", &i32); ms->skill_lv = (res == CONFIG_FALSE) ? 1 : cap_value(i32, 1, battle_config.mob_max_skilllvl); - //Apply battle_config modifiers to rate (permillage) and delay [Skotlex] res = libconfig->setting_lookup_int(it, "Rate", &i32); ms->permillage = (res == CONFIG_FALSE) ? 1 : cap_value(i32, 1, 10000); + // Apply battle_config modifier to rate (permillage). if (battle_config.mob_skill_rate != 100) ms->permillage = ms->permillage * battle_config.mob_skill_rate / 100; + if (ms->permillage > 10000) ms->permillage = 10000; - else if (ms->permillage == 0 && battle_config.mob_skill_rate) + else if (ms->permillage == 0 && battle_config.mob_skill_rate != 0) ms->permillage = 1; res = libconfig->setting_lookup_int(it, "CastTime", &i32); @@ -5633,6 +5653,7 @@ static bool mob_skill_db_libconfig_sub_skill(struct config_setting_t *it, int n, res = libconfig->setting_lookup_int(it, "Delay", &i32); ms->delay = (res == CONFIG_FALSE) ? 0 : cap_value(i32, 0, MOB_MAX_DELAY); + // Apply battle_config modifier to delay. if (battle_config.mob_skill_delay != 100) ms->delay = ms->delay * battle_config.mob_skill_delay / 100; @@ -5643,32 +5664,34 @@ static bool mob_skill_db_libconfig_sub_skill(struct config_setting_t *it, int n, i32 = MST_TARGET; if (mob->lookup_const(it, "SkillTarget", &i32) && (i32 < MST_TARGET || i32 > MST_AROUND)) { - ShowWarning("mob_skill_db_libconfig_sub_skill: Invalid skill target %d for skill id %d in monster %d, defaulting to MST_TARGET.\n", i32, skill_id, mob_id); + ShowWarning("%s: Invalid skill target %d for skill %d (%s) in %s %d, defaulting to MST_TARGET.\n", + __func__, i32, skill_id, skill_name, mob_str, mob_id); i32 = MST_TARGET; } ms->target = i32; // Check the target condition for non-ground skills. (Ground skills can use every target.) - skill_idx = skill->get_index(skill_id); - if (skill->get_casttype2(skill_idx) != CAST_GROUND && ms->target > MST_MASTER) { - ShowWarning("mob_skill_db_libconfig_sub_skill: Wrong mob skill target 'around' for non-ground skill %d (%s) for %s.\n", - ms->skill_id, skill->dbs->db[skill_idx].name, mob_id < 0 ? "all mobs" : mob->db_data[mob_id]->sprite); + if (skill->get_casttype2(skill->get_index(skill_id)) != CAST_GROUND && ms->target > MST_MASTER) { + ShowWarning("%s: Wrong skill target %d for non-ground skill %d (%s) in %s %d, defaulting to MST_TARGET.\n", + __func__, ms->target, skill_id, skill_name, mob_str, mob_id); ms->target = MST_TARGET; } i32 = MSC_ALWAYS; if (mob->lookup_const(it, "CastCondition", &i32) && (i32 < MSC_ALWAYS || i32 > MSC_SPAWN)) { - ShowWarning("mob_skill_db_libconfig_sub_skill: Invalid skill condition %d for skill id %d in monster %d, defaulting to MSC_ALWAYS.\n", i32, skill_id, mob_id); + ShowWarning("%s: Invalid skill condition %d for skill id %d (%s) in %s %d, defaulting to MSC_ALWAYS.\n", + __func__, i32, skill_id, skill_name, mob_str, mob_id); i32 = MSC_ALWAYS; } ms->cond1 = i32; ms->cond2 = !mob->lookup_const(it, "ConditionData", &i32) ? 0 : cap_value(i32, SHRT_MIN, SHRT_MAX); - for (i = 0; i < 5; i++) { + for (int i = 0; i < 5; i++) { char valname[16]; sprintf(valname, "val%1d", i); - if (libconfig->setting_lookup_int(it, valname, &i32)) + + if (libconfig->setting_lookup_int(it, valname, &i32) == CONFIG_TRUE) ms->val[i] = i32; } @@ -5679,17 +5702,17 @@ static bool mob_skill_db_libconfig_sub_skill(struct config_setting_t *it, int n, if (mob_id > 0 && (uint32)ms->val[1] == mob->db(mob_id)->status.mode) { ms->val[1] = MD_NONE; - ms->val[4] = 1; //request to return mode to normal. + ms->val[4] = 1; // Request to return mode to normal. } } if (ms->skill_id == NPC_EMOTION_ON && mob_id > 0 && ms->val[1] != MD_NONE) { - //Adds a mode to the mob. - //Remove aggressive mode when the new mob type is passive. - if (!(ms->val[1] & MD_AGGRESSIVE)) + // Add a mode to the mob and remove aggressive mode if the new mode is passive. + if ((ms->val[1] & MD_AGGRESSIVE) == 0) ms->val[3] |= MD_AGGRESSIVE; - ms->val[2] |= (uint32)ms->val[1]; //Add the new mode. - ms->val[1] = MD_NONE; //Do not "set" it. + + ms->val[2] |= (uint32)ms->val[1]; // Add the new mode. + ms->val[1] = MD_NONE; // Do not "set" it. } res = libconfig->setting_lookup_int(it, "Emotion", &i32); @@ -5697,43 +5720,46 @@ static bool mob_skill_db_libconfig_sub_skill(struct config_setting_t *it, int n, if (libconfig->setting_lookup_int(it, "ChatMsgID", &i32) == CONFIG_TRUE) { if (i32 <= 0 || i32 > MAX_MOB_CHAT || mob->chat_db[i32] == NULL) { - ShowWarning("mob_skill_db_libconfig_sub_skill: Invalid msg id %d for skill id %d in monster %d, ignoring.\n", i32, skill_id, mob_id); + ShowWarning("%s: Invalid message ID %d for skill %d (%s) in %s %d, ignoring.\n", + __func__, i32, skill_id, skill_name, mob_str, mob_id); } else { ms->msg_id = i32; } } - if (mob_id < 0) { - // Set this skill to ALL mobs. [Skotlex] - mob_id *= -1; - for (i = 1; i < MAX_MOB_DB; i++) { + if (mob_id < 0) { // Global skill assignment. + mob_id = -mob_id; + + for (int i = 1; i < MAX_MOB_DB; i++) { if (mob->db_data[i] == NULL) continue; - if (mob->db_data[i]->status.mode & MD_BOSS) { - if (!(mob_id & 2)) //Skill not for bosses + + if ((mob->db_data[i]->status.mode & MD_BOSS) != 0) { + if ((mob_id & 2) == 0) // Skill not for boss monsters. continue; } else { - if (!(mob_id & 1)) //Skill not for normal enemies. + if ((mob_id & 1) == 0) // Skill not for normal monsters. continue; } - ARR_FIND(0, MAX_MOBSKILL, j, mob->db_data[i]->skill[j].skill_id == 0); - if (j == MAX_MOBSKILL) { - ShowError("mob_skill_db_libconfig_sub_skill: Too many skills for monster %d. (Global ID %d.)\n", - i, -mob_id); + + int idx; + + ARR_FIND(0, MAX_MOBSKILL, idx, mob->db_data[i]->skill[idx].skill_id == 0); + + if (idx == MAX_MOBSKILL) { + ShowError("%s: Too many skills for monster %d in global ID %d, skipping.\n", + __func__, i, -mob_id); continue; } - memcpy(&mob->db_data[i]->skill[j], ms, sizeof(struct mob_skill)); - mob->db_data[i]->maxskill = j + 1; + memcpy(&mob->db_data[i]->skill[idx], ms, sizeof(struct mob_skill)); + mob->db_data[i]->maxskill = idx + 1; } - } else { //Skill set on a single mob. - mob->db_data[mob_id]->maxskill = idx + 1; } return true; } - /*========================================== * mob_skill_db.txt reading *------------------------------------------*/ -- cgit v1.2.3-70-g09d2