From c67c2b7435a13d7ce17b2075e22dc5c6036f702a Mon Sep 17 00:00:00 2001 From: Ben Longbons Date: Mon, 4 Feb 2013 00:49:50 -0800 Subject: Remove some more Skill-related stuff --- src/common/extract.hpp | 2 +- src/common/nullpo.cpp | 1 + src/common/nullpo.hpp | 19 +- src/common/timer.cpp | 2 + src/common/timer.hpp | 1 + src/map/atcommand.cpp | 43 +- src/map/battle.cpp | 535 +---- src/map/battle.hpp | 19 +- src/map/battle.t.hpp | 137 ++ src/map/chat.cpp | 3 +- src/map/chrif.cpp | 3 +- src/map/clif.cpp | 202 +- src/map/clif.hpp | 5 +- src/map/itemdb.cpp | 3 +- src/map/magic-expr-eval.hpp | 7 - src/map/magic-expr.cpp | 21 +- src/map/magic-interpreter.t.hpp | 15 + src/map/magic-stmt.cpp | 6 +- src/map/map.cpp | 104 +- src/map/map.hpp | 162 +- src/map/map.t.hpp | 183 +- src/map/mob.cpp | 501 +--- src/map/mob.hpp | 14 +- src/map/mob.t.hpp | 79 +- src/map/npc.cpp | 48 +- src/map/npc.hpp | 2 +- src/map/path.cpp | 46 +- src/map/pc.cpp | 449 +--- src/map/pc.hpp | 8 +- src/map/script.cpp | 9 - src/map/skill.cpp | 4882 +++++++-------------------------------- src/map/skill.hpp | 39 - src/map/skill.t.hpp | 7 +- src/map/storage.cpp | 9 +- 34 files changed, 1558 insertions(+), 6008 deletions(-) diff --git a/src/common/extract.hpp b/src/common/extract.hpp index c60ce2a..3198d5d 100644 --- a/src/common/extract.hpp +++ b/src/common/extract.hpp @@ -67,7 +67,7 @@ bool extract(const_string str, T *iv) // defer to integer version if (!extract(str, &v)) return false; - // TODO check bounds ... + // TODO check bounds using enum min/max as in SSCANF *iv = static_cast(v); return true; } diff --git a/src/common/nullpo.cpp b/src/common/nullpo.cpp index d7d489c..423ed8c 100644 --- a/src/common/nullpo.cpp +++ b/src/common/nullpo.cpp @@ -5,6 +5,7 @@ #include "../poison.hpp" /// Actual output function +static void nullpo_info(const char *file, int line, const char *func) { if (!file) diff --git a/src/common/nullpo.hpp b/src/common/nullpo.hpp index ad1084a..2d8644f 100644 --- a/src/common/nullpo.hpp +++ b/src/common/nullpo.hpp @@ -1,22 +1,22 @@ /// return wrappers for unexpected NULL pointers #ifndef NULLPO_HPP #define NULLPO_HPP -/// Comment this out to live dangerously -# define NULLPO_CHECK +/// Uncomment this to live dangerously +/// (really exist to detect mostly-unused variables) +//# define BUG_FREE /// All functions print to standard error (was: standard output) /// nullpo_ret(cond) - return 0 if given pointer is NULL /// nullpo_retv(cond) - just return (function returns void) /// nullpo_retr(rv, cond) - return given value instead -# ifdef NULLPO_CHECK -# define NLP_MARK __FILE__, __LINE__, __func__ +# ifndef BUG_FREE # define nullpo_retr(ret, t) \ - if (nullpo_chk(NLP_MARK, t)) \ + if (nullpo_chk(__FILE__, __LINE__, __func__, t)) \ return ret; -# else // NULLPO_CHECK -# define nullpo_retr(ret, t) t; -# endif // NULLPO_CHECK +# else // BUG_FREE +# define nullpo_retr(ret, t) /*t*/ +# endif // BUG_FREE # define nullpo_ret(t) nullpo_retr(0, t) # define nullpo_retv(t) nullpo_retr(, t) @@ -27,7 +27,4 @@ bool nullpo_chk(const char *file, int line, const char *func, const void *target); -/// Used only by map/battle.c -void nullpo_info(const char *file, int line, const char *func); - #endif // NULLPO_HPP diff --git a/src/common/timer.cpp b/src/common/timer.cpp index 65f04e0..92d284c 100644 --- a/src/common/timer.cpp +++ b/src/common/timer.cpp @@ -185,11 +185,13 @@ void delete_timer(timer_id id, timer_func func) FPRINTF(stderr, "delete_timer error : no such timer %d\n", id); abort(); } +#ifndef delete_timer if (timer_data[id].func != func) { FPRINTF(stderr, "Timer mismatch\n"); abort(); } +#endif // "to let them disappear" - is this just in case? timer_data[id].func = NULL; timer_data[id].type = TIMER_ONCE_AUTODEL; diff --git a/src/common/timer.hpp b/src/common/timer.hpp index db4dedd..b00d48d 100644 --- a/src/common/timer.hpp +++ b/src/common/timer.hpp @@ -52,6 +52,7 @@ tick_t gettick(void); timer_id add_timer(tick_t, timer_func, custom_id_t, custom_data_t); timer_id add_timer_interval(tick_t, timer_func, custom_id_t, custom_data_t, interval_t); +//#define delete_timer(tid, func) delete_timer(tid) void delete_timer(timer_id, timer_func); tick_t addtick_timer(timer_id, interval_t); diff --git a/src/map/atcommand.cpp b/src/map/atcommand.cpp index 211baac..a6994d5 100644 --- a/src/map/atcommand.cpp +++ b/src/map/atcommand.cpp @@ -1594,7 +1594,7 @@ int atcommand_heal(const int fd, struct map_session_data *sd, } if (hp < 0) // display like damage - clif_damage(&sd->bl, &sd->bl, gettick(), 0, 0, -hp, 0, 4, 0); + clif_damage(&sd->bl, &sd->bl, gettick(), 0, 0, -hp, 0, DamageType::RETURNED, 0); if (hp != 0 || sp != 0) { @@ -4614,11 +4614,10 @@ int atcommand_mapinfo(const int fd, struct map_session_data *sd, struct npc_data *nd = NULL; struct chat_data *cd = NULL; char map_name[100]; - char direction[12]; + const char *direction = NULL; int m_id, i, chat_num, list = 0; memset(map_name, '\0', sizeof(map_name)); - memset(direction, '\0', sizeof(direction)); sscanf(message, "%d %99[^\n]", &list, map_name); @@ -4716,35 +4715,37 @@ int atcommand_mapinfo(const int fd, struct map_session_data *sd, nd = map[m_id].npc[i]; switch (nd->dir) { - case 0: - strcpy(direction, "North"); + case DIR_S: + direction = "North"; break; - case 1: - strcpy(direction, "North West"); + case DIR_SW: + direction = "North West"; break; - case 2: - strcpy(direction, "West"); + case DIR_W: + direction = "West"; break; - case 3: - strcpy(direction, "South West"); + case DIR_NW: + direction = "South West"; break; - case 4: - strcpy(direction, "South"); + case DIR_N: + direction = "South"; break; - case 5: - strcpy(direction, "South East"); + case DIR_NE: + direction = "South East"; break; - case 6: - strcpy(direction, "East"); + case DIR_E: + direction = "East"; break; - case 7: - strcpy(direction, "North East"); + case DIR_SE: + direction = "North East"; break; +#if 0 case 9: - strcpy(direction, "North"); + direction = "North"; break; +#endif default: - strcpy(direction, "Unknown"); + direction = "Unknown"; break; } output = STRPRINTF( diff --git a/src/map/battle.cpp b/src/map/battle.cpp index 4d98b45..b431662 100644 --- a/src/map/battle.cpp +++ b/src/map/battle.cpp @@ -58,15 +58,15 @@ int battle_get_class(struct block_list *bl) * 戻りは整数で0以上 *------------------------------------------ */ -int battle_get_dir(struct block_list *bl) +DIR battle_get_dir(struct block_list *bl) { - nullpo_ret(bl); + nullpo_retr(DIR_S, bl); if (bl->type == BL_MOB && (struct mob_data *) bl) return ((struct mob_data *) bl)->dir; else if (bl->type == BL_PC && (struct map_session_data *) bl) return ((struct map_session_data *) bl)->dir; else - return 0; + return DIR_S; } /*========================================== @@ -591,22 +591,17 @@ int battle_get_matk2(struct block_list *bl) int battle_get_def(struct block_list *bl) { eptr sc_data; - int def = 0, skilltimer = -1; - SkillID skillid = SkillID::ZERO; + int def = 0; nullpo_ret(bl); sc_data = battle_get_sc_data(bl); if (bl->type == BL_PC && (struct map_session_data *) bl) { def = ((struct map_session_data *) bl)->def; - skilltimer = ((struct map_session_data *) bl)->skilltimer; - skillid = ((struct map_session_data *) bl)->skillid; } else if (bl->type == BL_MOB && (struct mob_data *) bl) { def = ((struct mob_data *) bl)->stats[MOB_DEF]; - skilltimer = ((struct mob_data *) bl)->skilltimer; - skillid = ((struct mob_data *) bl)->skillid; } if (def < 1000000) @@ -622,13 +617,6 @@ int battle_get_def(struct block_list *bl) && sc_data[SC_STONE].val2 == 0)) def >>= 1; } - //詠唱中は詠唱時減算率に基づいて減算 - if (skilltimer != -1) - { - int def_rate = skill_get_castdef(skillid); - if (def_rate != 0) - def = (def * (100 - def_rate)) / 100; - } } if (def < 0) def = 0; @@ -842,24 +830,22 @@ int battle_get_dmotion(struct block_list *bl) return ret; } -int battle_get_element(struct block_list *bl) +LevelElement battle_get_element(struct block_list *bl) { - int ret = 20; + LevelElement ret = {2, Element::neutral}; eptr sc_data; nullpo_retr(ret, bl); sc_data = battle_get_sc_data(bl); if (bl->type == BL_MOB && (struct mob_data *) bl) // 10の位=Lv*2、1の位=属性 ret = ((struct mob_data *) bl)->def_ele; - else if (bl->type == BL_PC && (struct map_session_data *) bl) - ret = 20 + ((struct map_session_data *) bl)->def_ele; // 防御属性Lv1 if (sc_data) { if (sc_data[SC_FREEZE].timer != -1) // 凍結 - ret = 21; + ret = LevelElement{2, Element::water}; if (sc_data[SC_STONE].timer != -1 && sc_data[SC_STONE].val2 == 0) - ret = 22; + ret = LevelElement{2, Element::earth}; } return ret; @@ -877,21 +863,18 @@ int battle_get_party_id(struct block_list *bl) return -md->master_id; return -md->bl.id; } - else if (bl->type == BL_SKILL && (struct skill_unit *) bl) - return ((struct skill_unit *) bl)->group->party_id; - else - return 0; + return 0; } -int battle_get_race(struct block_list *bl) +Race battle_get_race(struct block_list *bl) { - nullpo_ret(bl); + nullpo_retr(Race::formless, bl); if (bl->type == BL_MOB && (struct mob_data *) bl) return mob_db[((struct mob_data *) bl)->mob_class].race; else if (bl->type == BL_PC && (struct map_session_data *) bl) - return 7; + return Race::demihuman; else - return 0; + return Race::formless; } MobMode battle_get_mode(struct block_list *bl) @@ -1072,21 +1055,9 @@ int battle_damage(struct block_list *bl, struct block_list *target, struct map_session_data *tsd = (struct map_session_data *) target; - if (tsd && tsd->skilltimer != -1) - { // 詠唱妨害 - // フェンカードや妨害されないスキルかの検査 - if (!tsd->special_state.no_castcancel - && tsd->state.skillcastcancel - && !tsd->special_state.no_castcancel2) - skill_castcancel(target, 0); - } - return pc_damage(bl, tsd, damage); } - else if (target->type == BL_SKILL) - return skill_unit_ondamaged((struct skill_unit *) target, bl, damage, - gettick()); return 0; } @@ -1143,43 +1114,12 @@ int battle_calc_damage(struct block_list *, struct block_list *bl, SkillID, int, BF flag) { struct mob_data *md = NULL; - eptr sc_data; - short *sc_count; nullpo_ret(bl); if (bl->type == BL_MOB) md = (struct mob_data *) bl; - sc_data = battle_get_sc_data(bl); - sc_count = battle_get_sc_count(bl); - - if (sc_count != NULL && *sc_count > 0) - { - - if (sc_data[SC_SAFETYWALL].timer != -1 - && damage > 0 - && bool(flag & BF_WEAPON) - && bool(flag & BF_SHORT)) - { - // セーフティウォール - struct skill_unit *unit = - (struct skill_unit *) sc_data[SC_SAFETYWALL].val2; - if (unit && unit->alive && (--unit->group->val2) <= 0) - skill_delunit(unit); - skill_unit_move(bl, gettick(), 1); // 重ね掛けチェック - damage = 0; - } - if (sc_data[SC_PNEUMA].timer != -1 - && damage > 0 - && bool(flag & BF_WEAPON) - && bool(flag & BF_LONG)) - { - // ニューマ - damage = 0; - } - } - if (battle_config.skill_min_damage || bool(flag & BF_MISC)) { @@ -1211,21 +1151,18 @@ struct Damage battle_calc_mob_weapon_attack(struct block_list *src, int def1 = battle_get_def(target); int def2 = battle_get_def2(target); int t_vit = battle_get_vit(target); - struct Damage wd; - int damage, damage2 = 0, type, div_, blewcount = - skill_get_blewcount(skill_num, skill_lv); + struct Damage wd {}; + int damage, damage2 = 0; + DamageType type; + int div_; BF flag; int ac_flag = 0; ATK dmg_lv = ATK::ZERO; eptr sc_data, t_sc_data; - //return前の処理があるので情報出力部のみ変更 - if (src == NULL || target == NULL || md == NULL) - { - nullpo_info(NLP_MARK); - memset(&wd, 0, sizeof(wd)); - return wd; - } + nullpo_retr(wd, src); + nullpo_retr(wd, target); + nullpo_retr(wd, md); sc_data = battle_get_sc_data(src); @@ -1268,7 +1205,7 @@ struct Damage battle_calc_mob_weapon_attack(struct block_list *src, } hitrate = battle_get_hit(src) - flee + 80; - type = 0; // normal + type = DamageType::NORMAL; div_ = 1; // single attack if (battle_config.enemy_str) @@ -1309,7 +1246,7 @@ struct Damage battle_calc_mob_weapon_attack(struct block_list *src, // 敵の判定 { damage += atkmax; - type = 0x0a; + type = DamageType::CRITICAL; } else { @@ -1417,7 +1354,7 @@ struct Damage battle_calc_mob_weapon_attack(struct block_list *src, t_sc_data[SC_STAN].timer != -1 || // スタンは必中 t_sc_data[SC_FREEZE].timer != -1 || (t_sc_data[SC_STONE].timer != -1 && t_sc_data[SC_STONE].val2 == 0)))) // 凍結は必中 hitrate = 1000000; - if (type == 0 && MRAND(100) >= hitrate) + if (type == DamageType::NORMAL && MRAND(100) >= hitrate) { damage = damage2 = 0; dmg_lv = ATK_FLEE; @@ -1427,16 +1364,6 @@ struct Damage battle_calc_mob_weapon_attack(struct block_list *src, dmg_lv = ATK_DEF; } - if (tsd) - { - int cardfix = 100; - if (bool(flag & BF_LONG)) - cardfix = cardfix * (100 - tsd->long_attack_def_rate) / 100; - if (bool(flag & BF_SHORT)) - cardfix = cardfix * (100 - tsd->near_attack_def_rate) / 100; - damage = damage * cardfix / 100; - } - if (damage < 0) damage = 0; @@ -1445,7 +1372,7 @@ struct Damage battle_calc_mob_weapon_attack(struct block_list *src, && MRAND(1000) < battle_get_flee2(target)) { damage = 0; - type = 0x0b; + type = DamageType::FLEE2; dmg_lv = ATK_LUCKY; } @@ -1455,7 +1382,7 @@ struct Damage battle_calc_mob_weapon_attack(struct block_list *src, && MRAND(1000) < battle_get_flee2(target)) { damage = 0; - type = 0x0b; + type = DamageType::FLEE2; dmg_lv = ATK_LUCKY; } } @@ -1464,9 +1391,6 @@ struct Damage battle_calc_mob_weapon_attack(struct block_list *src, if (bool(t_mode & MobMode::PLANT) && damage > 0) damage = 1; - if (tsd && tsd->special_state.no_weapon_damage) - damage = 0; - damage = battle_calc_damage(src, target, damage, div_, skill_num, skill_lv, flag); @@ -1476,7 +1400,6 @@ struct Damage battle_calc_mob_weapon_attack(struct block_list *src, wd.div_ = div_; wd.amotion = battle_get_amotion(src); wd.dmotion = battle_get_dmotion(target); - wd.blewcount = blewcount; wd.flag = flag; wd.dmg_lv = dmg_lv; return wd; @@ -1516,27 +1439,23 @@ struct Damage battle_calc_pc_weapon_attack(struct block_list *src, int def1 = battle_get_def(target); int def2 = battle_get_def2(target); int t_vit = battle_get_vit(target); - struct Damage wd; - int damage, damage2, type, div_, blewcount = - skill_get_blewcount(skill_num, skill_lv); + struct Damage wd {}; + int damage, damage2; + DamageType type; + int div_; BF flag; ATK dmg_lv = ATK::ZERO; - int t_race = 0; eptr sc_data, t_sc_data; int atkmax_ = 0, atkmin_ = 0; //二刀流用 - int watk, watk_, cardfix, t_ele; + int watk, watk_; bool da = false; int ac_flag = 0; int idef_flag = 0, idef_flag_ = 0; int target_distance; - //return前の処理があるので情報出力部のみ変更 - if (src == NULL || target == NULL || sd == NULL) - { - nullpo_info(NLP_MARK); - memset(&wd, 0, sizeof(wd)); - return wd; - } + nullpo_retr(wd, src); + nullpo_retr(wd, target); + nullpo_retr(wd, sd); // アタッカー sc_data = battle_get_sc_data(src); //ステータス異常 @@ -1548,8 +1467,6 @@ struct Damage battle_calc_pc_weapon_attack(struct block_list *src, tsd = (struct map_session_data *) target; //tsdに代入(tmdはNULL) else if (target->type == BL_MOB) //対象がMobなら tmd = (struct mob_data *) target; //tmdに代入(tsdはNULL) - t_race = battle_get_race(target); //対象の種族 - t_ele = battle_get_elem_type(target); //対象の属性 MobMode t_mode = battle_get_mode(target); //対象のMode t_sc_data = battle_get_sc_data(target); //対象のステータス異常 @@ -1597,7 +1514,7 @@ struct Damage battle_calc_pc_weapon_attack(struct block_list *src, watk = battle_get_atk(src); //ATK watk_ = battle_get_atk_(src); //ATK左手 - type = 0; // normal + type = DamageType::NORMAL; div_ = 1; // single attack { @@ -1634,24 +1551,10 @@ struct Damage battle_calc_pc_weapon_attack(struct block_list *src, sd->state.arrow_atk = 1; //arrow_atk有効化 } - // サイズ修正 - // ペコ騎乗していて、槍で攻撃した場合は中型のサイズ修正を100にする - // ウェポンパーフェクション,ドレイクC - if (sd->special_state.no_sizefix) - { //ペコ騎乗していて、槍で中型を攻撃 - atkmax = watk; - atkmax_ = watk_; - } - else { atkmax = watk; atkmax_ = watk_; } - if (sd->special_state.no_sizefix) - { // ウェポンパーフェクション || ドレイクカード - atkmax = watk; - atkmax_ = watk_; - } if (atkmin > atkmax && !(sd->state.arrow_atk)) atkmin = atkmax; //弓は最低が上回る場合あり @@ -1699,7 +1602,7 @@ struct Damage battle_calc_pc_weapon_attack(struct block_list *src, } if (sd->state.arrow_atk) damage += sd->arrow_atk; - type = 0x0a; + type = DamageType::CRITICAL; } else { @@ -1726,48 +1629,6 @@ struct Damage battle_calc_pc_weapon_attack(struct block_list *src, hitrate += sd->arrow_hit; } - if (def1 < 1000000) - { - if (sd->def_ratio_atk_ele & (1 << t_ele) - || sd->def_ratio_atk_race & (1 << t_race)) - { - damage = (damage * (def1 + def2)) / 100; - idef_flag = 1; - } - if (sd->def_ratio_atk_ele_ & (1 << t_ele) - || sd->def_ratio_atk_race_ & (1 << t_race)) - { - damage2 = (damage2 * (def1 + def2)) / 100; - idef_flag_ = 1; - } - if (bool(t_mode & MobMode::BOSS)) - { - if (!idef_flag && sd->def_ratio_atk_race & (1 << 10)) - { - damage = (damage * (def1 + def2)) / 100; - idef_flag = 1; - } - if (!idef_flag_ && sd->def_ratio_atk_race_ & (1 << 10)) - { - damage2 = (damage2 * (def1 + def2)) / 100; - idef_flag_ = 1; - } - } - else - { - if (!idef_flag && sd->def_ratio_atk_race & (1 << 11)) - { - damage = (damage * (def1 + def2)) / 100; - idef_flag = 1; - } - if (!idef_flag_ && sd->def_ratio_atk_race_ & (1 << 11)) - { - damage2 = (damage2 * (def1 + def2)) / 100; - idef_flag_ = 1; - } - } - } - if (skill_num != SkillID::ZERO && skill_num != SkillID::NEGATIVE) { flag = (flag & ~BF_SKILLMASK) | BF_SKILL; @@ -1835,26 +1696,6 @@ struct Damage battle_calc_pc_weapon_attack(struct block_list *src, } t_def = def2 * 8 / 10; vitbonusmax = (t_vit / 20) * (t_vit / 20) - 1; - if (sd->ignore_def_ele & (1 << t_ele) - || sd->ignore_def_race & (1 << t_race)) - idef_flag = 1; - if (sd->ignore_def_ele_ & (1 << t_ele) - || sd->ignore_def_race_ & (1 << t_race)) - idef_flag_ = 1; - if (bool(t_mode & MobMode::BOSS)) - { - if (sd->ignore_def_race & (1 << 10)) - idef_flag = 1; - if (sd->ignore_def_race_ & (1 << 10)) - idef_flag_ = 1; - } - else - { - if (sd->ignore_def_race & (1 << 11)) - idef_flag = 1; - if (sd->ignore_def_race_ & (1 << 11)) - idef_flag_ = 1; - } if (!idef_flag) { @@ -1927,7 +1768,7 @@ struct Damage battle_calc_pc_weapon_attack(struct block_list *src, t_sc_data[SC_STAN].timer != -1 || // スタンは必中 t_sc_data[SC_FREEZE].timer != -1 || (t_sc_data[SC_STONE].timer != -1 && t_sc_data[SC_STONE].val2 == 0)))) // 凍結は必中 hitrate = 1000000; - if (type == 0 && MRAND(100) >= hitrate) + if (type == DamageType::NORMAL && MRAND(100) >= hitrate) { damage = damage2 = 0; dmg_lv = ATK_FLEE; @@ -1937,18 +1778,6 @@ struct Damage battle_calc_pc_weapon_attack(struct block_list *src, dmg_lv = ATK_DEF; } - if (tsd) - { //対象がPCの場合 - cardfix = 100; - if (bool(flag & BF_LONG)) - cardfix = cardfix * (100 - tsd->long_attack_def_rate) / 100; //遠距離攻撃はダメージ減少(ホルンCとか) - if (bool(flag & BF_SHORT)) - cardfix = cardfix * (100 - tsd->near_attack_def_rate) / 100; //近距離攻撃はダメージ減少(該当無し?) - damage = damage * cardfix / 100; //カード補正によるダメージ減少 - damage2 = damage2 * cardfix / 100; //カード補正による左手ダメージ減少 - } -//カードによるダメージ減衰処理ここまで - if (damage < 0) damage = 0; if (damage2 < 0) @@ -1993,7 +1822,7 @@ struct Damage battle_calc_pc_weapon_attack(struct block_list *src, { //ダブルアタックが発動しているか div_ = 2; damage += damage; - type = 0x08; + type = DamageType::DOUBLED; } if (sd->status.weapon == 16) @@ -2009,7 +1838,7 @@ struct Damage battle_calc_pc_weapon_attack(struct block_list *src, && MRAND(1000) < battle_get_flee2(target)) { damage = damage2 = 0; - type = 0x0b; + type = DamageType::FLEE2; dmg_lv = ATK_LUCKY; } @@ -2020,7 +1849,7 @@ struct Damage battle_calc_pc_weapon_attack(struct block_list *src, && MRAND(1000) < battle_get_flee2(target)) { damage = damage2 = 0; - type = 0x0b; + type = DamageType::FLEE2; dmg_lv = ATK_LUCKY; } } @@ -2034,10 +1863,6 @@ struct Damage battle_calc_pc_weapon_attack(struct block_list *src, damage2 = 1; } - //bNoWeaponDamage(設定アイテム無し?)でグランドクロスじゃない場合はダメージが0 - if (tsd && tsd->special_state.no_weapon_damage) - damage = damage2 = 0; - if (damage > 0 || damage2 > 0) { if (damage2 < 1) // ダメージ最終修正 @@ -2061,27 +1886,12 @@ struct Damage battle_calc_pc_weapon_attack(struct block_list *src, } } - /* For executioner card [Valaris] */ - if (src->type == BL_PC && sd->random_attack_increase_add > 0 - && sd->random_attack_increase_per > 0 && skill_num == SkillID::ZERO) - { - if (MRAND(100) < sd->random_attack_increase_per) - { - if (damage > 0) - damage *= sd->random_attack_increase_add / 100; - if (damage2 > 0) - damage2 *= sd->random_attack_increase_add / 100; - } - } - /* End addition */ - wd.damage = damage; wd.damage2 = damage2; wd.type = type; wd.div_ = div_; wd.amotion = battle_get_amotion(src); wd.dmotion = battle_get_dmotion(target); - wd.blewcount = blewcount; wd.flag = flag; wd.dmg_lv = dmg_lv; @@ -2098,23 +1908,15 @@ struct Damage battle_calc_weapon_attack(struct block_list *src, SkillID skill_num, int skill_lv, int wflag) { - struct Damage wd; + struct Damage wd {}; - //return前の処理があるので情報出力部のみ変更 - if (src == NULL || target == NULL) - { - nullpo_info(NLP_MARK); - memset(&wd, 0, sizeof(wd)); - return wd; - } + nullpo_retr(wd, src); + nullpo_retr(wd, target); - else if (src->type == BL_PC) + if (src->type == BL_PC) wd = battle_calc_pc_weapon_attack(src, target, skill_num, skill_lv, wflag); // weapon breaking [Valaris] else if (src->type == BL_MOB) - wd = battle_calc_mob_weapon_attack(src, target, skill_num, skill_lv, - wflag); - else - memset(&wd, 0, sizeof(wd)); + wd = battle_calc_mob_weapon_attack(src, target, skill_num, skill_lv, wflag); if (battle_config.equipment_breaking && src->type == BL_PC && (wd.damage > 0 || wd.damage2 > 0)) @@ -2123,7 +1925,7 @@ struct Damage battle_calc_weapon_attack(struct block_list *src, if (sd->status.weapon && sd->status.weapon != 11) { int breakrate = 1; - if (wd.type == 0x0a) + if (wd.type == DamageType::CRITICAL) breakrate *= 2; if (MRAND(10000) < breakrate * battle_config.equipment_break_rate / 100 @@ -2139,7 +1941,7 @@ struct Damage battle_calc_weapon_attack(struct block_list *src, && (wd.damage > 0 || wd.damage2 > 0)) { int breakrate = 1; - if (wd.type == 0x0a) + if (wd.type == DamageType::CRITICAL) breakrate *= 2; if (MRAND(10000) < breakrate * battle_config.equipment_break_rate / 100 @@ -2163,25 +1965,16 @@ struct Damage battle_calc_magic_attack(struct block_list *bl, { int mdef1 = battle_get_mdef(target); int mdef2 = battle_get_mdef2(target); - int matk1, matk2, damage = 0, div_ = 1, blewcount = - skill_get_blewcount(skill_num, skill_lv), rdamage = 0; - struct Damage md; + int matk1, matk2, damage = 0, div_ = 1; + struct Damage md {}; int normalmagic_flag = 1; - int t_ele = 0, t_race = 7, cardfix; - struct map_session_data *sd = NULL, *tsd = NULL; + struct map_session_data *sd = NULL; - //return前の処理があるので情報出力部のみ変更 - if (bl == NULL || target == NULL) - { - nullpo_info(NLP_MARK); - memset(&md, 0, sizeof(md)); - return md; - } + nullpo_retr(md, bl); + nullpo_retr(md, target); matk1 = battle_get_matk1(bl); matk2 = battle_get_matk2(bl); - t_ele = battle_get_elem_type(target); - t_race = battle_get_race(target); MobMode t_mode = battle_get_mode(target); #define MATK_FIX( a,b ) { matk1=matk1*(a)/(b); matk2=matk2*(a)/(b); } @@ -2193,8 +1986,6 @@ struct Damage battle_calc_magic_attack(struct block_list *bl, MATK_FIX(sd->matk_rate, 100); sd->state.arrow_atk = 0; } - if (target->type == BL_PC) - tsd = (struct map_session_data *) target; BF aflag = BF_MAGIC | BF_LONG | BF_SKILL; @@ -2205,22 +1996,7 @@ struct Damage battle_calc_magic_attack(struct block_list *bl, damage = matk2 + MRAND((matk1 - matk2 + 1)); else damage = matk2; - if (sd) - { - if (sd->ignore_mdef_ele & (1 << t_ele) - || sd->ignore_mdef_race & (1 << t_race)) - imdef_flag = 1; - if (bool(t_mode & MobMode::BOSS)) - { - if (sd->ignore_mdef_race & (1 << 10)) - imdef_flag = 1; - } - else - { - if (sd->ignore_mdef_race & (1 << 11)) - imdef_flag = 1; - } - } + if (!imdef_flag) { if (battle_config.magic_defense_type) @@ -2239,12 +2015,6 @@ struct Damage battle_calc_magic_attack(struct block_list *bl, damage = 1; } - if (tsd) - { - cardfix = 100; - cardfix = cardfix * (100 - tsd->magic_def_rate) / 100; - damage = damage * cardfix / 100; - } if (damage < 0) damage = 0; @@ -2257,38 +2027,14 @@ struct Damage battle_calc_magic_attack(struct block_list *bl, if (bool(t_mode & MobMode::PLANT) && damage > 0) damage = 1; - if (tsd && tsd->special_state.no_magic_damage) - { - if (battle_config.gtb_pvp_only != 0) - { // [MouseJstr] - if (map[target->m].flag.pvp - && target->type == BL_PC) - damage = (damage * (100 - battle_config.gtb_pvp_only)) / 100; - } - else - damage = 0; // 黄 金蟲カード(魔法ダメージ0) - } - damage = battle_calc_damage(bl, target, damage, div_, skill_num, skill_lv, aflag); // 最終修正 - /* magic_damage_return by [AppleGirl] and [Valaris] */ - if (target->type == BL_PC && tsd && tsd->magic_damage_return > 0) - { - rdamage += damage * tsd->magic_damage_return / 100; - if (rdamage < 1) - rdamage = 1; - clif_damage(target, bl, gettick(), 0, 0, rdamage, 0, 0, 0); - battle_damage(target, bl, rdamage, 0); - } - /* end magic_damage_return */ - md.damage = damage; md.div_ = div_; md.amotion = battle_get_amotion(bl); md.dmotion = battle_get_dmotion(target); md.damage2 = 0; - md.type = 0; - md.blewcount = blewcount; + md.type = DamageType::NORMAL; md.flag = aflag; return md; @@ -2303,22 +2049,15 @@ struct Damage battle_calc_misc_attack(struct block_list *bl, struct block_list *target, SkillID skill_num, int skill_lv, int) { - int cardfix; - struct map_session_data *sd = NULL, *tsd = NULL; - int damage = 0, div_ = 1, blewcount = - skill_get_blewcount(skill_num, skill_lv); - struct Damage md; + struct map_session_data *sd = NULL; + int damage = 0, div_ = 1; + struct Damage md {}; int damagefix = 1; BF aflag = BF_MISC | BF_LONG | BF_SKILL; - //return前の処理があるので情報出力部のみ変更 - if (bl == NULL || target == NULL) - { - nullpo_info(NLP_MARK); - memset(&md, 0, sizeof(md)); - return md; - } + nullpo_retr(md, bl); + nullpo_retr(md, target); if (bl->type == BL_PC && (sd = (struct map_session_data *) bl)) { @@ -2326,9 +2065,6 @@ struct Damage battle_calc_misc_attack(struct block_list *bl, sd->state.arrow_atk = 0; } - if (target->type == BL_PC) - tsd = (struct map_session_data *) target; - switch (skill_num) { case NPC_SELFDESTRUCTION: // 自爆 @@ -2341,15 +2077,6 @@ struct Damage battle_calc_misc_attack(struct block_list *bl, { if (damage < 1) damage = 1; - - if (tsd) - { - cardfix = 100; - cardfix = cardfix * (100 - tsd->misc_def_rate) / 100; - damage = damage * cardfix / 100; - } - if (damage < 0) - damage = 0; } div_ = skill_get_num(skill_num, skill_lv); @@ -2371,8 +2098,7 @@ struct Damage battle_calc_misc_attack(struct block_list *bl, md.amotion = battle_get_amotion(bl); md.dmotion = battle_get_dmotion(target); md.damage2 = 0; - md.type = 0; - md.blewcount = blewcount; + md.type = DamageType::NORMAL; md.flag = aflag; return md; @@ -2415,11 +2141,10 @@ struct Damage battle_calc_attack(BF attack_type, *------------------------------------------ */ ATK battle_weapon_attack(struct block_list *src, struct block_list *target, - unsigned int tick, BCT flag) + unsigned int tick, BCT) { struct map_session_data *sd = NULL; eptr t_sc_data = battle_get_sc_data(target); - int damage, rdamage = 0; struct Damage wd; nullpo_retr(ATK::ZERO, src); @@ -2480,53 +2205,15 @@ ATK battle_weapon_attack(struct block_list *src, struct block_list *target, "MAGIC-ABSORB-DMG %d", reduction); } - if ((damage = wd.damage + wd.damage2) > 0 && src != target) - { - if (bool(wd.flag & BF_SHORT)) - { - if (target->type == BL_PC) - { - struct map_session_data *tsd = - (struct map_session_data *) target; - if (tsd && tsd->short_weapon_damage_return > 0) - { - rdamage += - damage * tsd->short_weapon_damage_return / 100; - if (rdamage < 1) - rdamage = 1; - } - } - } - else if (bool(wd.flag & BF_LONG)) - { - if (target->type == BL_PC) - { - struct map_session_data *tsd = - (struct map_session_data *) target; - if (tsd && tsd->long_weapon_damage_return > 0) - { - rdamage += - damage * tsd->long_weapon_damage_return / 100; - if (rdamage < 1) - rdamage = 1; - } - } - } - - if (rdamage > 0) - clif_damage(src, src, tick, wd.amotion, 0, rdamage, 1, 4, 0); - } - { clif_damage(src, target, tick, wd.amotion, wd.dmotion, wd.damage, wd.div_, wd.type, wd.damage2); //二刀流左手とカタール追撃のミス表示(無理やり〜) if (sd && sd->status.weapon >= 16 && wd.damage2 == 0) clif_damage(src, target, tick + 10, wd.amotion, wd.dmotion, - 0, 1, 0, 0); + 0, 1, DamageType::NORMAL, 0); } - if (sd && sd->splash_range > 0 && (wd.damage > 0 || wd.damage2 > 0)) - skill_castend_damage_id(src, target, SkillID::ZERO, -1, tick, BCT_ZERO); + map_freeblock_lock(); if (src->type == BL_PC) @@ -2573,46 +2260,6 @@ ATK battle_weapon_attack(struct block_list *src, struct block_list *target, } if (sd) { - if (sd->autospell_id != SkillID::ZERO - && sd->autospell_id != SkillID::NEGATIVE - && sd->autospell_lv > 0 - && MRAND(100) < sd->autospell_rate) - { - int skilllv = sd->autospell_lv, i, f = 0, sp; - i = MRAND(100); - if (i >= 50) - skilllv -= 2; - else if (i >= 15) - skilllv--; - if (skilllv < 1) - skilllv = 1; - sp = skill_get_sp(sd->autospell_id, skilllv) * 2 / 3; - if (sd->status.sp >= sp) - { - if ((i = skill_get_inf(sd->autospell_id) == 2) - || i == 32) - f = 0; - else - { - switch (skill_get_nk(sd->autospell_id)) - { - case 0: - case 2: - f = skill_castend_damage_id(src, target, - sd->autospell_id, skilllv, - tick, flag); - break; - case 1: /* 支援系 */ - f = skill_castend_nodamage_id(src, target, - sd->autospell_id, skilllv, - tick, flag); - break; - } - } - if (!f) - pc_heal(sd, 0, -sp); - } - } if (bool(wd.flag & BF_WEAPON) && src != target && (wd.damage > 0 || wd.damage2 > 0)) @@ -2643,32 +2290,25 @@ ATK battle_weapon_attack(struct block_list *src, struct block_list *target, } } - if (rdamage > 0) - battle_damage(target, src, rdamage, 0); - map_freeblock_unlock(); } return wd.dmg_lv; } -int battle_check_undead(int race, int element) +bool battle_check_undead(Race race, Element element) { if (battle_config.undead_detect_type == 0) { - if (element == 9) - return 1; + return element == Element::undead; } else if (battle_config.undead_detect_type == 1) { - if (race == 1) - return 1; + return race == Race::undead; } else { - if (element == 9 || race == 1) - return 1; + return element == Element::undead || race == Race::undead; } - return 0; } /*========================================== @@ -2705,46 +2345,10 @@ int battle_check_target(struct block_list *src, struct block_list *target, return -1; } - if (src->type == BL_SKILL && target->type == BL_SKILL) // 対象がスキルユニットなら無条件肯定 - return -1; - if (target->type == BL_PC && ((struct map_session_data *) target)->invincible_timer != -1) return -1; - if (target->type == BL_SKILL) - { - switch (((struct skill_unit *) target)->group->unit_id) - { - case 0x8d: - case 0x8f: - case 0x98: - return 0; - } - } - - // スキルユニットの場合、親を求める - if (src->type == BL_SKILL) - { - int inf2 = - skill_get_inf2(((struct skill_unit *) src)->group->skill_id); - if ((ss = - map_id2bl(((struct skill_unit *) src)->group->src_id)) == NULL) - return -1; - if (ss->prev == NULL) - return -1; - if (inf2 & 0x80 && (map[src->m].flag.pvp || pc_iskiller((struct map_session_data *) src, (struct map_session_data *) target)) && // [MouseJstr] - !(target->type == BL_PC - && pc_isinvisible((struct map_session_data *) target))) - return 0; - if (ss == target) - { - if (inf2 & 0x100) - return 0; - if (inf2 & 0x200) - return -1; - } - } // Mobでmaster_idがあってspecial_mob_aiなら、召喚主を求める if (src->type == BL_MOB) { @@ -2809,16 +2413,11 @@ int battle_check_target(struct block_list *src, struct block_list *target, if (ss->type == BL_PC && target->type == BL_PC) { // 両方PVPモードなら否定(敵) - struct skill_unit *su = NULL; - if (src->type == BL_SKILL) - su = (struct skill_unit *) src; if (map[ss->m].flag.pvp || pc_iskiller((struct map_session_data *) ss, (struct map_session_data *) target)) { // [MouseJstr] - if (su && su->group->target_flag == BCT_NOENEMY) - return 1; - else if (battle_config.pk_mode) + if (battle_config.pk_mode) return 1; // prevent novice engagement in pk_mode [Valaris] else if (map[ss->m].flag.pvp_noparty && s_p > 0 && t_p > 0 && s_p == t_p) diff --git a/src/map/battle.hpp b/src/map/battle.hpp index 56b3a9f..c4b4601 100644 --- a/src/map/battle.hpp +++ b/src/map/battle.hpp @@ -3,6 +3,7 @@ #include "battle.t.hpp" +#include "magic-interpreter.t.hpp" #include "map.t.hpp" #include "skill.t.hpp" @@ -10,9 +11,9 @@ struct Damage { int damage, damage2; - int type, div_; + DamageType type; + int div_; int amotion, dmotion; - int blewcount; BF flag; ATK dmg_lv; }; @@ -43,7 +44,7 @@ ATK battle_weapon_attack(struct block_list *bl, struct block_list *target, int battle_is_unarmed(struct block_list *bl); int battle_get_class(struct block_list *bl); -int battle_get_dir(struct block_list *bl); +DIR battle_get_dir(struct block_list *bl); int battle_get_lv(struct block_list *bl); int battle_get_range(struct block_list *bl); int battle_get_hp(struct block_list *bl); @@ -62,10 +63,14 @@ int battle_get_speed(struct block_list *bl); int battle_get_adelay(struct block_list *bl); int battle_get_amotion(struct block_list *bl); int battle_get_dmotion(struct block_list *bl); -int battle_get_element(struct block_list *bl); -#define battle_get_elem_type(bl) (battle_get_element(bl)%10) +LevelElement battle_get_element(struct block_list *bl); +inline +Element battle_get_elem_type(struct block_list *bl) +{ + return battle_get_element(bl).element; +} int battle_get_party_id(struct block_list *bl); -int battle_get_race(struct block_list *bl); +Race battle_get_race(struct block_list *bl); MobMode battle_get_mode(struct block_list *bl); int battle_get_mexp(struct block_list *bl); int battle_get_stat(SP stat_id, struct block_list *bl); @@ -77,7 +82,7 @@ Opt2 *battle_get_opt2(struct block_list *bl); Opt3 *battle_get_opt3(struct block_list *bl); Option *battle_get_option(struct block_list *bl); -int battle_check_undead(int race, int element); +bool battle_check_undead(Race race, Element element); int battle_check_target(struct block_list *src, struct block_list *target, BCT flag); int battle_check_range(struct block_list *src, struct block_list *bl, diff --git a/src/map/battle.t.hpp b/src/map/battle.t.hpp index f88fb71..94bdd50 100644 --- a/src/map/battle.t.hpp +++ b/src/map/battle.t.hpp @@ -44,6 +44,7 @@ struct BCT uint8_t level:4; // 0x 00 f0 00 00 uint8_t unused; // 0x ff 00 00 00 + explicit operator bool() { return lo || mid || classic || level || unused; } }; @@ -93,4 +94,140 @@ BCT BCT_mid_x80 = {0x00, 0x80, 0x0, 0x0, 0x00}; constexpr BCT BCT_highnib = {0x00, 0x00, 0x0, 0xf, 0x00}; +enum class Element : uint8_t +{ + neutral = 0, + water = 1, + earth = 2, + fire = 3, + wind = 4, + poison = 5, + _holy = 6, + dark = 7, + _spirit = 8, + undead = 9, + + COUNT = 10, +}; + +enum class Race : uint8_t +{ + formless = 0, + undead = 1, + _brute = 2, + plant = 3, + _insect = 4, + _fish = 5, + _demon = 6, + demihuman = 7, + _angel = 8, + _dragon = 9, + // special - one of these is applied in addition + boss = 10, + other = 11, + + COUNT = 12, +}; + +struct LevelElement +{ + uint8_t level; + Element element; + + static + LevelElement unpack(int packed) + { + LevelElement le; + le.element = static_cast(packed % 10); + le.level = packed / 10; + return le; + } + int pack() const + { + return level * 10 + static_cast(element); + } +}; + +namespace e +{ +enum class Elements : uint16_t +{ + ZERO = 0x0000, + neutral = 1 << 0, + water = 1 << 1, + earth = 1 << 2, + fire = 1 << 3, + wind = 1 << 4, + poison = 1 << 5, + _holy = 1 << 6, + dark = 1 << 7, + _spirit = 1 << 8, + undead = 1 << 9, +}; +ENUM_BITWISE_OPERATORS(Elements) + +enum class Races : uint16_t +{ + ZERO = 0x0000, + formless = 1 << 0, + undead = 1 << 1, + _brute = 1 << 2, + plant = 1 << 3, + _insect = 1 << 4, + _fish = 1 << 5, + _demon = 1 << 6, + demihuman = 1 << 7, + _angel = 1 << 8, + _dragon = 1 << 9, + // special - one of these is applied in addition + boss = 1 << 10, + other = 1 << 11, +}; +ENUM_BITWISE_OPERATORS(Races) +} +using e::Elements; +using e::Races; + +constexpr +earray element_shift //= +{{ + Elements::neutral, + Elements::water, + Elements::earth, + Elements::fire, + Elements::wind, + Elements::poison, + Elements::_holy, + Elements::dark, + Elements::_spirit, + Elements::undead, +}}; + +constexpr +earray race_shift //= +{{ + Races::formless, + Races::undead, + Races::_brute, + Races::plant, + Races::_insect, + Races::_fish, + Races::_demon, + Races::demihuman, + Races::_angel, + Races::_dragon, + Races::boss, + Races::other, +}}; + +enum class DamageType : uint8_t +{ + NORMAL = 0x00, + TAKEITEM = 0x01, + RETURNED = 0x04, + DOUBLED = 0x08, + CRITICAL = 0x0a, + FLEE2 = 0x0b, +}; + #endif // BATTLE_T_HPP diff --git a/src/map/chat.cpp b/src/map/chat.cpp index 1f9f433..75b45e9 100644 --- a/src/map/chat.cpp +++ b/src/map/chat.cpp @@ -117,7 +117,8 @@ int chat_deletenpcchat(struct npc_data *nd) struct chat_data *cd; nullpo_ret(nd); - nullpo_ret(cd = (struct chat_data *) map_id2bl(nd->chat_id)); + cd = (struct chat_data *) map_id2bl(nd->chat_id); + nullpo_ret(cd); chat_npckickall(cd); map_delobject(cd->bl.id, BL_CHAT); // freeまでしてくれる diff --git a/src/map/chrif.cpp b/src/map/chrif.cpp index 018c659..302d04c 100644 --- a/src/map/chrif.cpp +++ b/src/map/chrif.cpp @@ -752,7 +752,8 @@ int chrif_divorce(int char_id, int partner_id) } } - nullpo_ret(sd = map_nick2sd(map_charid2nick(partner_id))); + sd = map_nick2sd(map_charid2nick(partner_id)); + nullpo_ret(sd); if (sd->status.partner_id == char_id) sd->status.partner_id = 0; diff --git a/src/map/clif.cpp b/src/map/clif.cpp index ba3123a..e719430 100644 --- a/src/map/clif.cpp +++ b/src/map/clif.cpp @@ -155,7 +155,6 @@ static struct in_addr map_ip; static int map_port = 5121; -char talkie_mes[80]; static int clif_changelook_towards(struct block_list *bl, LOOK type, int val, @@ -777,7 +776,7 @@ int clif_set0078(struct map_session_data *sd, unsigned char *buf) WBUFW(buf, 26) = sd->status.head_mid; WBUFW(buf, 28) = sd->status.hair_color; WBUFW(buf, 30) = sd->status.clothes_color; - WBUFW(buf, 32) = sd->head_dir; + WBUFW(buf, 32) = static_cast(sd->head_dir); WBUFL(buf, 34) = 0 /*guild_id*/; WBUFW(buf, 38) = 0 /*guild_emblem_id*/; WBUFW(buf, 40) = sd->status.manner; @@ -785,7 +784,9 @@ int clif_set0078(struct map_session_data *sd, unsigned char *buf) WBUFB(buf, 44) = sd->status.karma; WBUFB(buf, 45) = sd->sex; WBUFPOS(buf, 46, sd->bl.x, sd->bl.y); - WBUFB(buf, 48) |= sd->dir & 0x0f; + // work around ICE in gcc 4.6 + uint8_t dir = static_cast(sd->dir); + WBUFB(buf, 48) |= dir; WBUFW(buf, 49) = (pc_isGM(sd) == 60 || pc_isGM(sd) == 99) ? 0x80 : 0; WBUFB(buf, 51) = sd->state.dead_sit; WBUFW(buf, 52) = 0; @@ -837,7 +838,7 @@ int clif_set007b(struct map_session_data *sd, unsigned char *buf) WBUFW(buf, 30) = sd->status.head_mid; WBUFW(buf, 32) = sd->status.hair_color; WBUFW(buf, 34) = sd->status.clothes_color; - WBUFW(buf, 36) = sd->head_dir; + WBUFW(buf, 36) = static_cast(sd->head_dir); WBUFL(buf, 38) = 0/*guild_id*/; WBUFW(buf, 42) = 0/*guild_emblem_id*/; WBUFW(buf, 44) = sd->status.manner; @@ -874,7 +875,9 @@ int clif_mob0078(struct mob_data *md, unsigned char *buf) WBUFW(buf, 14) = md->mob_class; // snip: stuff do do with disguise as a PC WBUFPOS(buf, 46, md->bl.x, md->bl.y); - WBUFB(buf, 48) |= md->dir & 0x0f; + // work around ICE in gcc 4.6 + uint8_t dir = static_cast(md->dir); + WBUFB(buf, 48) |= dir; WBUFB(buf, 49) = 5; WBUFB(buf, 50) = 5; WBUFW(buf, 52) = @@ -935,7 +938,9 @@ int clif_npc0078(struct npc_data *nd, unsigned char *buf) WBUFW(buf, 6) = nd->speed; WBUFW(buf, 14) = nd->npc_class; WBUFPOS(buf, 46, nd->bl.x, nd->bl.y); - WBUFB(buf, 48) |= nd->dir & 0x0f; + // work around ICE in gcc 4.6 + uint8_t dir = static_cast(nd->dir); + WBUFB(buf, 48) |= dir; WBUFB(buf, 49) = 5; WBUFB(buf, 50) = 5; @@ -1737,7 +1742,8 @@ int clif_storageitemlist(struct map_session_data *sd, struct storage *stor) continue; struct item_data *id; - nullpo_ret(id = itemdb_search(stor->storage_[i].nameid)); + id = itemdb_search(stor->storage_[i].nameid); + nullpo_ret(id); if (itemdb_isequip2(id)) continue; @@ -1782,7 +1788,8 @@ int clif_storageequiplist(struct map_session_data *sd, struct storage *stor) continue; struct item_data *id; - nullpo_ret(id = itemdb_search(stor->storage_[i].nameid)); + id = itemdb_search(stor->storage_[i].nameid); + nullpo_ret(id); if (!itemdb_isequip2(id)) continue; WFIFOW(fd, n * 20 + 4) = i + 1; @@ -2809,7 +2816,7 @@ int clif_fixpcpos(struct map_session_data *sd) */ int clif_damage(struct block_list *src, struct block_list *dst, unsigned int tick, int sdelay, int ddelay, int damage, - int div, int type, int damage2) + int div, DamageType type, int damage2) { unsigned char buf[256]; eptr sc_data; @@ -2827,7 +2834,7 @@ int clif_damage(struct block_list *src, struct block_list *dst, WBUFL(buf, 18) = ddelay; WBUFW(buf, 22) = (damage > 0x7fff) ? 0x7fff : damage; WBUFW(buf, 24) = div; - WBUFB(buf, 26) = type; + WBUFB(buf, 26) = static_cast(type); WBUFW(buf, 27) = damage2; clif_send(buf, packet_len_table[0x8a], src, AREA); @@ -2913,8 +2920,6 @@ void clif_getareachar(struct block_list *bl, struct map_session_data *sd) case BL_ITEM: clif_getareachar_item(sd, (struct flooritem_data *) bl); break; - case BL_SKILL: - break; default: if (battle_config.error_log) PRINTF("get area char ??? %d\n", @@ -2954,8 +2959,6 @@ void clif_pcoutsight(struct block_list *bl, struct map_session_data *sd) case BL_ITEM: clif_clearflooritem((struct flooritem_data *) bl, sd->fd); break; - case BL_SKILL: - break; } } @@ -2989,8 +2992,6 @@ void clif_pcinsight(struct block_list *bl, struct map_session_data *sd) case BL_ITEM: clif_getareachar_item(sd, (struct flooritem_data *) bl); break; - case BL_SKILL: - break; } } @@ -3938,9 +3939,6 @@ void clif_parse_WalkToXY(int fd, struct map_session_data *sd) if (sd->npc_id != 0 || sd->state.storage_open) return; - if (sd->skilltimer != -1) - return; - if (sd->chatID) return; @@ -3952,8 +3950,6 @@ void clif_parse_WalkToXY(int fd, struct map_session_data *sd) || sd->sc_data[SC_ANKLE].timer != -1 //アンクルスネア ) return; - if (bool(sd->status.option & Option::HIDE2)) - return; if (sd->invincible_timer != -1) pc_delinvincibletimer(sd); @@ -3981,7 +3977,7 @@ void clif_parse_QuitGame(int fd, struct map_session_data *sd) && (sd->opt1 != Opt1::ZERO || (sd->opt2 != Opt2::ZERO && !(night_flag == 1 && sd->opt2 == Opt2::BLIND)))) - || sd->skilltimer != -1 || (DIFF_TICK(tick, sd->canact_tick) < 0) + || (DIFF_TICK(tick, sd->canact_tick) < 0) ) { WFIFOW(fd, 2) = 1; @@ -4198,12 +4194,13 @@ static void clif_parse_ChangeDir(int fd, struct map_session_data *sd) { unsigned char buf[64]; - short dir; nullpo_retv(sd); -// RFIFOW(fd,2); // Apparently does nothing? - dir = RFIFOB(fd, 4); + // RFIFOW(fd, 2) is always 0 + DIR dir = static_cast(RFIFOB(fd, 4)); + if (dir >= DIR::COUNT) + return; if (dir == sd->dir) return; @@ -4213,7 +4210,7 @@ void clif_parse_ChangeDir(int fd, struct map_session_data *sd) WBUFW(buf, 0) = 0x9c; WBUFL(buf, 2) = sd->bl.id; WBUFW(buf, 6) = 0; - WBUFB(buf, 8) = dir; + WBUFB(buf, 8) = static_cast(dir); clif_send(buf, packet_len_table[0x9c], &sd->bl, AREA_WOS); @@ -4274,7 +4271,6 @@ void clif_parse_ActionRequest(int fd, struct map_session_data *sd) } if (sd->npc_id != 0 || bool(sd->opt1) - || bool(sd->status.option & Option::HIDE2) || sd->state.storage_open) return; @@ -4793,150 +4789,6 @@ void clif_parse_SkillUp(int fd, struct map_session_data *sd) pc_skillup(sd, SkillID(RFIFOW(fd, 2))); } -/*========================================== - * スキル使用(ID指定) - *------------------------------------------ - */ -static -void clif_parse_UseSkillToId(int fd, struct map_session_data *sd) -{ - int skilllv, lv, target_id; - unsigned int tick = gettick(); - - nullpo_retv(sd); - - if (sd->chatID || sd->npc_id != 0 || sd->state.storage_open) - return; - - skilllv = RFIFOW(fd, 2); - SkillID skillnum = SkillID(RFIFOW(fd, 4)); - target_id = RFIFOL(fd, 6); - - if (sd->skilltimer != -1) - { - return; - } - else if (DIFF_TICK(tick, sd->canact_tick) < 0) - { - clif_skill_fail(sd, skillnum, 4, 0); - return; - } - - if (sd->sc_data[SC_NOCHAT].timer != -1) - return; - if (sd->invincible_timer != -1) - pc_delinvincibletimer(sd); - if (sd->skillitem != SkillID::NEGATIVE && sd->skillitem == skillnum) - { - if (skilllv != sd->skillitemlv) - skilllv = sd->skillitemlv; - skill_use_id(sd, target_id, skillnum, skilllv); - } - else - { - sd->skillitem = SkillID::NEGATIVE; - sd->skillitemlv = -1; - if ((lv = pc_checkskill(sd, skillnum)) > 0) - { - if (skilllv > lv) - skilllv = lv; - skill_use_id(sd, target_id, skillnum, skilllv); - if (sd->state.skill_flag) - sd->state.skill_flag = 0; - } - } -} - -/*========================================== - * スキル使用(場所指定) - *------------------------------------------ - */ -static -void clif_parse_UseSkillToPos(int fd, struct map_session_data *sd) -{ - int skilllv, lv, x, y; - unsigned int tick = gettick(); - int skillmoreinfo; - - nullpo_retv(sd); - - if (sd->npc_id != 0 || sd->state.storage_open) - return; - if (sd->chatID) - return; - - skillmoreinfo = -1; - skilllv = RFIFOW(fd, 2); - SkillID skillnum = SkillID(RFIFOW(fd, 4)); - x = RFIFOW(fd, 6); - y = RFIFOW(fd, 8); - if (RFIFOW(fd, 0) == 0x190) - skillmoreinfo = 10; - - if (skillmoreinfo != -1) - { - if (pc_issit(sd)) - { - clif_skill_fail(sd, skillnum, 0, 0); - return; - } - memcpy(talkie_mes, RFIFOP(fd, skillmoreinfo), 80); - } - - if (sd->skilltimer != -1) - return; - else if (DIFF_TICK(tick, sd->canact_tick) < 0) - { - clif_skill_fail(sd, skillnum, 4, 0); - return; - } - - if (sd->sc_data[SC_NOCHAT].timer != -1) - return; - if (sd->invincible_timer != -1) - pc_delinvincibletimer(sd); - if (sd->skillitem != SkillID::NEGATIVE && sd->skillitem == skillnum) - { - if (skilllv != sd->skillitemlv) - skilllv = sd->skillitemlv; - skill_use_pos(sd, x, y, skillnum, skilllv); - } - else - { - sd->skillitem = SkillID::NEGATIVE; - sd->skillitemlv = -1; - if ((lv = pc_checkskill(sd, skillnum)) > 0) - { - if (skilllv > lv) - skilllv = lv; - skill_use_pos(sd, x, y, skillnum, skilllv); - } - } -} - -/*========================================== - * スキル使用(map指定) - *------------------------------------------ - */ -static -void clif_parse_UseSkillMap(int fd, struct map_session_data *sd) -{ - nullpo_retv(sd); - - if (sd->chatID) - return; - - if (sd->npc_id != 0 - || sd->sc_data[SC_NOCHAT].timer != -1) - return; - - if (sd->invincible_timer != -1) - pc_delinvincibletimer(sd); - - SkillID skill_id = SkillID(RFIFOW(fd, 2)); - skill_castend_map(sd, skill_id, (const char *)RFIFOP(fd, 4)); -} - /*========================================== * *------------------------------------------ @@ -5537,15 +5389,15 @@ func_table clif_parse_func_table[0x220] = { NULL, 0 }, // 110 { NULL, 0 }, // 111 { clif_parse_SkillUp, -1 }, // 112 - { clif_parse_UseSkillToId, 0 }, // 113 + { NULL, 0 }, // 113 { NULL, 0 }, // 114 { NULL, 0 }, // 115 - { clif_parse_UseSkillToPos, 0 }, // 116 + { NULL, 0 }, // 116 { NULL, 0 }, // 117 { clif_parse_StopAttack, 0 }, // 118 { NULL, 0 }, // 119 { NULL, 0 }, // 11a - { clif_parse_UseSkillMap, 0 }, // 11b + { NULL, 0 }, // 11b { NULL, 0 }, // 11c { NULL, 0 }, // 11d { NULL, 0 }, // 11e @@ -5662,7 +5514,7 @@ func_table clif_parse_func_table[0x220] = { NULL, 0 }, // 18d { NULL, 0 }, // 18e { NULL, 0 }, // 18f - { clif_parse_UseSkillToPos, 0 }, // 190 + { NULL, 0 }, // 190 { NULL, 0 }, // 191 { NULL, 0 }, // 192 { NULL, 0 }, // 193 diff --git a/src/map/clif.hpp b/src/map/clif.hpp index 51ee4aa..bfbca4d 100644 --- a/src/map/clif.hpp +++ b/src/map/clif.hpp @@ -5,6 +5,7 @@ #include "../common/const_array.hpp" +#include "battle.t.hpp" #include "map.t.hpp" #include "pc.t.hpp" #include "skill.t.hpp" @@ -53,8 +54,8 @@ int clif_viewpoint(struct map_session_data *, int, int, int, int, int, int); // int clif_additem(struct map_session_data *, int, int, PickupFail); //self int clif_delitem(struct map_session_data *, int, int); //self int clif_updatestatus(struct map_session_data *, SP); //self -int clif_damage(struct block_list *, struct block_list *, unsigned int, int, int, int, int, int, int); // area -#define clif_takeitem(src,dst) clif_damage(src,dst,0,0,0,0,0,1,0) +int clif_damage(struct block_list *, struct block_list *, unsigned int, int, int, int, int, DamageType, int); // area +#define clif_takeitem(src,dst) clif_damage(src,dst,0,0,0,0,0,DamageType::TAKEITEM,0) int clif_changelook(struct block_list *, LOOK, int); // area void clif_changelook_accessories(struct block_list *bl, struct map_session_data *dst); // area or target; list gloves, boots etc. int clif_arrowequip(struct map_session_data *sd, int val); //self diff --git a/src/map/itemdb.cpp b/src/map/itemdb.cpp index b6a841e..62331f1 100644 --- a/src/map/itemdb.cpp +++ b/src/map/itemdb.cpp @@ -525,7 +525,8 @@ void itemdb_final(db_key_t, db_val_t data) { struct item_data *id; - nullpo_retv(id = (struct item_data *)data); + id = (struct item_data *)data; + nullpo_retv(id); if (id->use_script) free(const_cast(id->use_script)); diff --git a/src/map/magic-expr-eval.hpp b/src/map/magic-expr-eval.hpp index ae9699d..1c4e1d2 100644 --- a/src/map/magic-expr-eval.hpp +++ b/src/map/magic-expr-eval.hpp @@ -7,13 +7,6 @@ /* Helper definitions for dealing with functions and operations */ -static -earray heading_x //= -{{ 0, -1, -1, -1, 0, 1, 1, 1 }}; -static -earray heading_y //= -{{ 1, 1, 0, -1, -1, -1, 0, 1 }}; - int magic_signature_check(const char *opname, const char *funname, const char *signature, int args_nr, val_t *args, int line, int column); diff --git a/src/map/magic-expr.cpp b/src/map/magic-expr.cpp index 6ad2cef..9431ecb 100644 --- a/src/map/magic-expr.cpp +++ b/src/map/magic-expr.cpp @@ -110,8 +110,6 @@ const char *show_entity(entity_t *entity) return ((struct item_data *) (&((struct flooritem_data *) entity)-> item_data))->name; - case BL_SKILL: - return "%skill"; case BL_SPELL: return "%invocation(ERROR:this-should-not-be-an-entity)"; default: @@ -629,7 +627,12 @@ BATTLE_GETTER(hp) BATTLE_GETTER(mdef) BATTLE_GETTER(def) BATTLE_GETTER(max_hp) -BATTLE_GETTER(dir) +static +int fun_get_dir(env_t *, int, val_t *result, val_t *args) +{ + RESULTDIR = battle_get_dir(ARGENTITY(0)); + return 0; +} #define MMO_GETTER(name) \ static \ @@ -833,8 +836,8 @@ static int fun_awayfrom(env_t *, int, val_t *result, val_t *args) { location_t *loc = &ARGLOCATION(0); - int dx = heading_x[ARGDIR(1)]; - int dy = heading_y[ARGDIR(1)]; + int dx = dirx[ARGDIR(1)]; + int dy = diry[ARGDIR(1)]; int distance = ARGINT(2); while (distance-- && !map_is_solid(loc->m, loc->x + dx, loc->y + dy)) { @@ -971,8 +974,8 @@ void magic_random_location(location_t *dest, area_t *area) for (i = 0; i < 10 && map_is_solid(m, x, y); i++) { - x += heading_x[dir]; - y += heading_y[dir]; + x += dirx[dir]; + y += diry[dir]; } dir = DIR((uint8_t(dir) + 1) % 8); @@ -1054,14 +1057,14 @@ int fun_status_option(env_t *, int, val_t *result, val_t *args) static int fun_element(env_t *, int, val_t *result, val_t *args) { - RESULTINT = battle_get_element(ARGENTITY(0)) % 10; + RESULTINT = static_cast(battle_get_element(ARGENTITY(0)).element); return 0; } static int fun_element_level(env_t *, int, val_t *result, val_t *args) { - RESULTINT = battle_get_element(ARGENTITY(0)) / 10; + RESULTINT = battle_get_element(ARGENTITY(0)).level; return 0; } diff --git a/src/map/magic-interpreter.t.hpp b/src/map/magic-interpreter.t.hpp index 49fd3e1..26dc8d9 100644 --- a/src/map/magic-interpreter.t.hpp +++ b/src/map/magic-interpreter.t.hpp @@ -64,6 +64,21 @@ enum class DIR : uint8_t COUNT, }; +constexpr +earray dirx //= +{{ + 0, -1, -1, -1, 0, 1, 1, 1, +}}, diry //= +{{ + 1, 1, 0, -1, -1, -1, 0, 1, +}}; + +constexpr +bool dir_is_diagonal(DIR d) +{ + return static_cast(d) & 1; +} + enum class AREA : uint8_t { LOCATION, diff --git a/src/map/magic-stmt.cpp b/src/map/magic-stmt.cpp index f39fc1f..65f6336 100644 --- a/src/map/magic-stmt.cpp +++ b/src/map/magic-stmt.cpp @@ -461,8 +461,8 @@ int op_move(env_t *, int, val_t *args) entity_t *subject = ARGENTITY(0); DIR dir = ARGDIR(1); - int newx = subject->x + heading_x[dir]; - int newy = subject->y + heading_y[dir]; + int newx = subject->x + dirx[dir]; + int newy = subject->y + diry[dir]; if (!map_is_solid(subject->m, newx, newy)) entity_warp(subject, subject->m, newx, newy); @@ -762,7 +762,7 @@ int op_injure(env_t *env, int, val_t *args) damage_caused = 0; // display damage first, because dealing damage may deallocate the target. - clif_damage(caster, target, gettick(), 0, 0, damage_caused, 0, 0, 0); + clif_damage(caster, target, gettick(), 0, 0, damage_caused, 0, DamageType::NORMAL, 0); if (caster->type == BL_PC) { diff --git a/src/map/map.cpp b/src/map/map.cpp index a6aff48..86737a2 100644 --- a/src/map/map.cpp +++ b/src/map/map.cpp @@ -1084,8 +1084,6 @@ int map_quit(struct map_session_data *sd) skill_stop_dancing(&sd->bl, 1); // ダンス/演奏中断 skill_status_change_clear(&sd->bl, 1); // ステータス異常を解除する - skill_clear_unitgroup(&sd->bl); // スキルユニットグループの削除 - skill_cleartimerskill(&sd->bl); pc_stop_walking(sd, 0); pc_stopattack(sd); pc_delinvincibletimer(sd); @@ -1380,100 +1378,73 @@ int map_mapname2ipport(const char *name, struct in_addr *ip, int *port) return 0; } -/*========================================== - * - *------------------------------------------ - */ -int map_check_dir(int s_dir, int t_dir) +/// Check compatibility of directions. +/// Directions are compatible if they are at most 45° apart. +/// +/// @return false if compatible, true if incompatible. +bool map_check_dir(const DIR s_dir, const DIR t_dir) { if (s_dir == t_dir) - return 0; - switch (s_dir) - { - case 0: - if (t_dir == 7 || t_dir == 1 || t_dir == 0) - return 0; - break; - case 1: - if (t_dir == 0 || t_dir == 2 || t_dir == 1) - return 0; - break; - case 2: - if (t_dir == 1 || t_dir == 3 || t_dir == 2) - return 0; - break; - case 3: - if (t_dir == 2 || t_dir == 4 || t_dir == 3) - return 0; - break; - case 4: - if (t_dir == 3 || t_dir == 5 || t_dir == 4) - return 0; - break; - case 5: - if (t_dir == 4 || t_dir == 6 || t_dir == 5) - return 0; - break; - case 6: - if (t_dir == 5 || t_dir == 7 || t_dir == 6) - return 0; - break; - case 7: - if (t_dir == 6 || t_dir == 0 || t_dir == 7) - return 0; - break; - } - return 1; + return false; + + const uint8_t sdir = static_cast(s_dir); + const uint8_t tdir = static_cast(t_dir); + if ((sdir + 1) % 8 == tdir) + return false; + if (sdir == (tdir + 1) % 8) + return false; + + return true; } /*========================================== * 彼我の方向を計算 *------------------------------------------ */ -int map_calc_dir(struct block_list *src, int x, int y) +DIR map_calc_dir(struct block_list *src, int x, int y) { - int dir = 0; + DIR dir = DIR_S; int dx, dy; - nullpo_ret(src); + nullpo_retr(DIR_S, src); dx = x - src->x; dy = y - src->y; if (dx == 0 && dy == 0) - { // 彼我の場所一致 - dir = 0; // 上 + { + dir = DIR_S; } else if (dx >= 0 && dy >= 0) - { // 方向的に右上 - dir = 7; // 右上 + { + dir = DIR_SE; if (dx * 3 - 1 < dy) - dir = 0; // 上 + dir = DIR_S; if (dx > dy * 3) - dir = 6; // 右 + dir = DIR_E; } else if (dx >= 0 && dy <= 0) - { // 方向的に右下 - dir = 5; // 右下 + { + dir = DIR_NE; if (dx * 3 - 1 < -dy) - dir = 4; // 下 + dir = DIR_N; if (dx > -dy * 3) - dir = 6; // 右 + dir = DIR_E; } else if (dx <= 0 && dy <= 0) - { // 方向的に左下 - dir = 3; // 左下 + { + dir = DIR_NW; if (dx * 3 + 1 > dy) - dir = 4; // 下 + dir = DIR_N; if (dx < dy * 3) - dir = 2; // 左 + dir = DIR_W; } else - { // 方向的に左上 - dir = 1; // 左上 + { + dir = DIR_SW; if (-dx * 3 - 1 < dy) - dir = 0; // 上 + dir = DIR_S; if (-dx > dy * 3) - dir = 2; // 左 + dir = DIR_W; } return dir; } @@ -1947,9 +1918,6 @@ void cleanup_sub(struct block_list *bl) case BL_ITEM: map_clearflooritem(bl->id); break; - case BL_SKILL: - skill_delunit((struct skill_unit *) bl); - break; case BL_SPELL: spell_free_invocation((struct invocation *) bl); break; diff --git a/src/map/map.hpp b/src/map/map.hpp index f9754e3..eab75c4 100644 --- a/src/map/map.hpp +++ b/src/map/map.hpp @@ -11,6 +11,7 @@ #include "../common/timer.hpp" #include "battle.t.hpp" +#include "magic-interpreter.t.hpp" #include "mob.t.hpp" #include "script.hpp" // change to script.t.hpp #include "skill.t.hpp" @@ -26,8 +27,6 @@ #define MAX_SKILLUNITGROUP 32 #define MAX_MOBSKILLUNITGROUP 8 #define MAX_SKILLUNITGROUPTICKSET 128 -#define MAX_SKILLTIMERSKILL 32 -#define MAX_MOBSKILLTIMERSKILL 10 #define MAX_MOBSKILL 32 #define MAX_EVENTQUEUE 2 #define MAX_EVENTTIMER 32 @@ -51,7 +50,7 @@ struct block_list struct walkpath_data { unsigned char path_len, path_pos, path_half; - unsigned char path[MAX_WALKPATH]; + DIR path[MAX_WALKPATH]; }; struct script_reg { @@ -74,78 +73,6 @@ struct status_change struct invocation; -struct skill_unit_group; -struct skill_unit -{ - struct block_list bl; - - struct skill_unit_group *group; - - int limit; - int val1, val2; - short alive, range; -}; -struct skill_unit_group -{ - int src_id; - int party_id; - int map, range; - BCT target_flag; - unsigned int tick; - int limit, interval; - - SkillID skill_id; - int skill_lv; - int val1, val2; - char *valstr; - int unit_id; - int group_id; - int unit_count, alive_count; - struct skill_unit *unit; -}; -struct skill_unit_group_tickset -{ - unsigned int tick; - int group_id; -}; -struct skill_timerskill -{ - int timer; - int src_id; - int target_id; - int map; - short x, y; - SkillID skill_id; - short skill_lv; - union sktst - { - int32_t n; - struct { uint16_t x, y; } xy; - BF bf; - - static sktst from_n(int32_t n) - { - sktst r; - r.n = n; - return r; - } - static sktst from_xy(uint16_t x, uint16_t y) - { - sktst r; - r.xy.x = x; - r.xy.y = y; - return r; - } - static sktst from_bf(BF bf) - { - sktst r; - r.bf = bf; - return r; - } - } type; - BCT flag; -}; - struct npc_data; struct item_data; struct square; @@ -179,7 +106,6 @@ struct map_session_data unsigned gangsterparadise:1; unsigned produce_flag:1; unsigned make_arrow_flag:1; - unsigned potionpitcher_flag:1; unsigned storage_open:1; unsigned shroud_active:1; unsigned shroud_hides_name_talking:1; @@ -190,16 +116,8 @@ struct map_session_data { unsigned killer:1; unsigned killable:1; - unsigned restart_full_recover:1; - unsigned no_castcancel:1; - unsigned no_castcancel2:1; - unsigned no_sizefix:1; - unsigned no_magic_damage:1; - unsigned no_weapon_damage:1; - unsigned no_gemstone:1; unsigned unbreakable_weapon:1; unsigned unbreakable_armor:1; - unsigned infinite_autospell:1; unsigned deaf:1; } special_state; int char_id, login_id1, login_id2, sex; @@ -216,7 +134,7 @@ struct map_session_data Opt1 opt1; Opt2 opt2; Opt3 opt3; - char dir, head_dir; + DIR dir, head_dir; unsigned int client_tick, server_tick; struct walkpath_data walkpath; int walktimer; @@ -257,22 +175,6 @@ struct map_session_data //_current slowly approximates _target, and _target is determined by equipment. short attackrange, attackrange_; - int skilltimer; - int skilltarget; - short skillx, skilly; - SkillID skillid; - short skilllv; - SkillID skillitem; - short skillitemlv; - SkillID skillid_old; - short skilllv_old; - SkillID skillid_dance; - short skilllv_dance; - struct skill_unit_group skillunit[MAX_SKILLUNITGROUP]; - struct skill_unit_group_tickset skillunittick[MAX_SKILLUNITGROUPTICKSET]; - struct skill_timerskill skilltimerskill[MAX_SKILLTIMERSKILL]; - int cloneskill_id, cloneskill_lv; - int potion_hp, potion_sp, potion_per_hp, potion_per_sp; // [Fate] Used for gradual healing; amount of enqueued regeneration struct quick_regeneration quick_regeneration_hp, quick_regeneration_sp; @@ -288,54 +190,34 @@ struct map_session_data inchealspiritsptick; // -- moonsoul (new tick for berserk self-damage) int berserkdamagetick; - int fame; short weapontype1, weapontype2; earray paramb, paramc, parame, paramcard; int hit, flee, flee2, aspd, amotion, dmotion; int watk, watk2; int def, def2, mdef, mdef2, critical, matk1, matk2; - int atk_ele, def_ele, star, overrefine; - int castrate, hprate, sprate, dsprate; - earray addeff, addeff2, reseff; + int star, overrefine; + int hprate, sprate, dsprate; int watk_, watk_2; - int atk_ele_, star_, overrefine_; //二刀流のために追加 + int star_, overrefine_; //二刀流のために追加 int base_atk, atk_rate; - int arrow_atk, arrow_ele, arrow_cri, arrow_hit, arrow_range; - earray arrow_addeff, arrow_addeff2; + int arrow_atk; + int arrow_cri, arrow_hit, arrow_range; int nhealhp, nhealsp, nshealhp, nshealsp, nsshealhp, nsshealsp; int aspd_rate, speed_rate, hprecov_rate, sprecov_rate, critical_def, double_rate; - int near_attack_def_rate, long_attack_def_rate, magic_def_rate, - misc_def_rate; - int matk_rate, ignore_def_ele, ignore_def_race, ignore_def_ele_, - ignore_def_race_; - int ignore_mdef_ele, ignore_mdef_race; - int perfect_hit, get_zeny_num; + int matk_rate; + int perfect_hit; int critical_rate, hit_rate, flee_rate, flee2_rate, def_rate, def2_rate, mdef_rate, mdef2_rate; - int def_ratio_atk_ele, def_ratio_atk_ele_, def_ratio_atk_race, - def_ratio_atk_race_; - short monster_drop_item_count; - short monster_drop_itemid[10]; - int monster_drop_race[10], monster_drop_itemrate[10]; - int double_add_rate, speed_add_rate, aspd_add_rate, perfect_hit_add, - get_zeny_add_num; - short splash_range, splash_add_range; - SkillID autospell_id; - short autospell_lv, autospell_rate; + int double_add_rate, speed_add_rate, aspd_add_rate, perfect_hit_add; short hp_drain_rate, hp_drain_per, sp_drain_rate, sp_drain_per; short hp_drain_rate_, hp_drain_per_, sp_drain_rate_, sp_drain_per_; - int short_weapon_damage_return, long_weapon_damage_return; short break_weapon_rate, break_armor_rate; short add_steal_rate; short spiritball, spiritball_old; int spirit_timer[MAX_SKILL_LEVEL]; - int magic_damage_return; // AppleGirl Was Here - int random_attack_increase_add, random_attack_increase_per; // [Valaris] - int perfect_hiding; // [Valaris] - int unbreakable; int die_counter; short doridori_counter; @@ -369,9 +251,6 @@ struct map_session_data char eventqueue[MAX_EVENTQUEUE][50]; int eventtimer[MAX_EVENTTIMER]; - SkillID last_skillid; - int last_skilllv; - struct { char name[24]; @@ -414,7 +293,8 @@ struct npc_data { struct block_list bl; short n; - short npc_class, dir; + short npc_class; + DIR dir; short speed; char name[24]; char exname[24]; @@ -460,7 +340,8 @@ struct mob_data { struct block_list bl; short n; - short mob_class, dir; + short mob_class; + DIR dir; MobMode mode; short m, x0, y0, xs, ys; char name[24]; @@ -468,7 +349,7 @@ struct mob_data struct { MS state; - MSS skillstate; + MobSkillState skillstate; unsigned attackable:1; unsigned steal_flag:1; unsigned steal_coin_flag:1; @@ -513,12 +394,9 @@ struct mob_data SkillID skillid; short skilllv, skillidx; unsigned int skilldelay[MAX_MOBSKILL]; - int def_ele; + LevelElement def_ele; int master_id, master_dist; int exclusion_src, exclusion_party; - struct skill_timerskill skilltimerskill[MAX_MOBSKILLTIMERSKILL]; - struct skill_unit_group skillunit[MAX_MOBSKILLUNITGROUP]; - struct skill_unit_group_tickset skillunittick[MAX_SKILLUNITGROUPTICKSET]; char npc_event[50]; // [Fate] mob-specific stats earray stats; @@ -630,8 +508,6 @@ extern int night_flag; // 0=day, 1=night [Yor] extern char motd_txt[]; extern char help_txt[]; -extern char talkie_mes[]; - extern char wisp_server_name[]; // 鯖全体情報 @@ -717,8 +593,8 @@ int map_getcell(int, int, int); int map_setcell(int, int, int, int); // その他 -int map_check_dir(int s_dir, int t_dir); -int map_calc_dir(struct block_list *src, int x, int y); +bool map_check_dir(DIR s_dir, DIR t_dir); +DIR map_calc_dir(struct block_list *src, int x, int y); // path.cより int path_search(struct walkpath_data *, int, int, int, int, int, int); diff --git a/src/map/map.t.hpp b/src/map/map.t.hpp index 0f2e47f..b7abc59 100644 --- a/src/map/map.t.hpp +++ b/src/map/map.t.hpp @@ -12,26 +12,13 @@ enum class Option : uint16_t { ZERO = 0x0000, - SIGHT = 0x0001, - // apparently some weaker non-GM hide - HIDE2 = 0x0002, - CLOAK = 0x0004, // [Fate] This is the GM `@hide' flag HIDE = 0x0040, - ORC_HEAD = 0x0800, // [Fate] Complete invisibility to other clients INVISIBILITY = 0x1000, - _wedding = 0x1000, - // [Fate] Auto-logging of nearby comments - SCRIBE = 0x2000, - CHASEWALK = 0x4000, - sign = 0x8000, - // ? - REAL_ANY_HIDE = HIDE | CLOAK | HIDE2, - OLD_ANY_HIDE = CHASEWALK | CLOAK | HIDE2, - MASK = sign | CHASEWALK | _wedding, + REAL_ANY_HIDE = HIDE, }; enum class Opt1 : uint16_t { @@ -92,8 +79,6 @@ enum class BL : uint8_t #define BL_ITEM BL::ITEM CHAT, #define BL_CHAT BL::CHAT - SKILL, -#define BL_SKILL BL::SKILL SPELL, #define BL_SPELL BL::SPELL }; @@ -179,104 +164,148 @@ enum class ATK enum class SP : uint16_t { + // sent to client SPEED = 0, #define SP_SPEED SP::SPEED // when used as "no stat" ZERO = 0, + // sent to client BASEEXP = 1, #define SP_BASEEXP SP::BASEEXP + // sent to client JOBEXP = 2, #define SP_JOBEXP SP::JOBEXP +#if 0 KARMA = 3, #define SP_KARMA SP::KARMA +#endif + // sent to client HP = 5, #define SP_HP SP::HP + // sent to client MAXHP = 6, #define SP_MAXHP SP::MAXHP + // sent to client SP = 7, #define SP_SP SP::SP + // sent to client MAXSP = 8, #define SP_MAXSP SP::MAXSP + // sent to client STATUSPOINT = 9, #define SP_STATUSPOINT SP::STATUSPOINT + // sent to client BASELEVEL = 11, #define SP_BASELEVEL SP::BASELEVEL + // sent to client SKILLPOINT = 12, #define SP_SKILLPOINT SP::SKILLPOINT + // sent to client STR = 13, #define SP_STR SP::STR + // sent to client AGI = 14, #define SP_AGI SP::AGI + // sent to client VIT = 15, #define SP_VIT SP::VIT + // sent to client INT = 16, #define SP_INT SP::INT + // sent to client DEX = 17, #define SP_DEX SP::DEX + // sent to client LUK = 18, #define SP_LUK SP::LUK CLASS = 19, #define SP_CLASS SP::CLASS + // sent to client ZENY = 20, #define SP_ZENY SP::ZENY SEX = 21, #define SP_SEX SP::SEX + // sent to client NEXTBASEEXP = 22, #define SP_NEXTBASEEXP SP::NEXTBASEEXP + // sent to client NEXTJOBEXP = 23, #define SP_NEXTJOBEXP SP::NEXTJOBEXP + // sent to client WEIGHT = 24, #define SP_WEIGHT SP::WEIGHT + // sent to client MAXWEIGHT = 25, #define SP_MAXWEIGHT SP::MAXWEIGHT + // sent to client USTR = 32, #define SP_USTR SP::USTR + // sent to client UAGI = 33, #define SP_UAGI SP::UAGI + // sent to client UVIT = 34, #define SP_UVIT SP::UVIT + // sent to client UINT = 35, #define SP_UINT SP::UINT + // sent to client UDEX = 36, #define SP_UDEX SP::UDEX + // sent to client ULUK = 37, #define SP_ULUK SP::ULUK + // sent to client ATK1 = 41, #define SP_ATK1 SP::ATK1 + // sent to client ATK2 = 42, #define SP_ATK2 SP::ATK2 + // sent to client MATK1 = 43, #define SP_MATK1 SP::MATK1 + // sent to client MATK2 = 44, #define SP_MATK2 SP::MATK2 + // sent to client DEF1 = 45, #define SP_DEF1 SP::DEF1 + // sent to client DEF2 = 46, #define SP_DEF2 SP::DEF2 + // sent to client MDEF1 = 47, #define SP_MDEF1 SP::MDEF1 + // sent to client MDEF2 = 48, #define SP_MDEF2 SP::MDEF2 + // sent to client HIT = 49, #define SP_HIT SP::HIT + // sent to client FLEE1 = 50, #define SP_FLEE1 SP::FLEE1 + // sent to client FLEE2 = 51, #define SP_FLEE2 SP::FLEE2 + // sent to client CRITICAL = 52, #define SP_CRITICAL SP::CRITICAL + // sent to client ASPD = 53, #define SP_ASPD SP::ASPD + // sent to client JOBLEVEL = 55, #define SP_JOBLEVEL SP::JOBLEVEL +#if 0 PARTNER = 57, #define SP_PARTNER SP::PARTNER CART = 58, @@ -285,125 +314,213 @@ enum class SP : uint16_t #define SP_FAME SP::FAME UNBREAKABLE = 60, #define SP_UNBREAKABLE SP::UNBREAKABLE +#endif DEAF = 70, #define SP_DEAF SP::DEAF + // sent to client GM = 500, #define SP_GM SP::GM + // sent to client ATTACKRANGE = 1000, #define SP_ATTACKRANGE SP::ATTACKRANGE +#if 0 ATKELE = 1001, #define SP_ATKELE SP::ATKELE +#endif +#if 0 DEFELE = 1002, #define SP_DEFELE SP::DEFELE +#endif +#if 0 CASTRATE = 1003, #define SP_CASTRATE SP::CASTRATE +#endif MAXHPRATE = 1004, #define SP_MAXHPRATE SP::MAXHPRATE +#if 0 MAXSPRATE = 1005, #define SP_MAXSPRATE SP::MAXSPRATE +#endif +#if 0 SPRATE = 1006, #define SP_SPRATE SP::SPRATE +#endif +#if 0 ADDEFF = 1012, #define SP_ADDEFF SP::ADDEFF +#endif +#if 0 RESEFF = 1013, #define SP_RESEFF SP::RESEFF +#endif BASE_ATK = 1014, #define SP_BASE_ATK SP::BASE_ATK ASPD_RATE = 1015, #define SP_ASPD_RATE SP::ASPD_RATE HP_RECOV_RATE = 1016, #define SP_HP_RECOV_RATE SP::HP_RECOV_RATE +#if 0 SP_RECOV_RATE = 1017, #define SP_SP_RECOV_RATE SP::SP_RECOV_RATE +#endif +#if 0 SPEED_RATE = 1018, #define SP_SPEED_RATE SP::SPEED_RATE +#endif +#if 0 CRITICAL_DEF = 1019, #define SP_CRITICAL_DEF SP::CRITICAL_DEF +#endif +#if 0 NEAR_ATK_DEF = 1020, #define SP_NEAR_ATK_DEF SP::NEAR_ATK_DEF +#endif +#if 0 LONG_ATK_DEF = 1021, #define SP_LONG_ATK_DEF SP::LONG_ATK_DEF +#endif +#if 0 DOUBLE_RATE = 1022, #define SP_DOUBLE_RATE SP::DOUBLE_RATE +#endif DOUBLE_ADD_RATE = 1023, #define SP_DOUBLE_ADD_RATE SP::DOUBLE_ADD_RATE +#if 0 MATK = 1024, #define SP_MATK SP::MATK +#endif +#if 0 MATK_RATE = 1025, #define SP_MATK_RATE SP::MATK_RATE +#endif +#if 0 IGNORE_DEF_ELE = 1026, #define SP_IGNORE_DEF_ELE SP::IGNORE_DEF_ELE +#endif +#if 0 IGNORE_DEF_RACE = 1027, #define SP_IGNORE_DEF_RACE SP::IGNORE_DEF_RACE +#endif +#if 0 ATK_RATE = 1028, #define SP_ATK_RATE SP::ATK_RATE +#endif SPEED_ADDRATE = 1029, #define SP_SPEED_ADDRATE SP::SPEED_ADDRATE +#if 0 ASPD_ADDRATE = 1030, #define SP_ASPD_ADDRATE SP::ASPD_ADDRATE +#endif +#if 0 MAGIC_ATK_DEF = 1031, #define SP_MAGIC_ATK_DEF SP::MAGIC_ATK_DEF +#endif +#if 0 MISC_ATK_DEF = 1032, #define SP_MISC_ATK_DEF SP::MISC_ATK_DEF +#endif +#if 0 IGNORE_MDEF_ELE = 1033, #define SP_IGNORE_MDEF_ELE SP::IGNORE_MDEF_ELE +#endif +#if 0 IGNORE_MDEF_RACE = 1034, #define SP_IGNORE_MDEF_RACE SP::IGNORE_MDEF_RACE +#endif +#if 0 PERFECT_HIT_RATE = 1038, #define SP_PERFECT_HIT_RATE SP::PERFECT_HIT_RATE +#endif +#if 0 PERFECT_HIT_ADD_RATE = 1039, #define SP_PERFECT_HIT_ADD_RATE SP::PERFECT_HIT_ADD_RATE +#endif +#if 0 CRITICAL_RATE = 1040, #define SP_CRITICAL_RATE SP::CRITICAL_RATE +#endif +#if 0 GET_ZENY_NUM = 1041, #define SP_GET_ZENY_NUM SP::GET_ZENY_NUM +#endif +#if 0 ADD_GET_ZENY_NUM = 1042, #define SP_ADD_GET_ZENY_NUM SP::ADD_GET_ZENY_NUM +#endif +#if 0 ADD_MONSTER_DROP_ITEM = 1047, #define SP_ADD_MONSTER_DROP_ITEM SP::ADD_MONSTER_DROP_ITEM +#endif +#if 0 DEF_RATIO_ATK_ELE = 1048, #define SP_DEF_RATIO_ATK_ELE SP::DEF_RATIO_ATK_ELE +#endif +#if 0 DEF_RATIO_ATK_RACE = 1049, #define SP_DEF_RATIO_ATK_RACE SP::DEF_RATIO_ATK_RACE +#endif +#if 0 ADD_SPEED = 1050, #define SP_ADD_SPEED SP::ADD_SPEED +#endif +#if 0 HIT_RATE = 1051, #define SP_HIT_RATE SP::HIT_RATE +#endif +#if 0 FLEE_RATE = 1052, #define SP_FLEE_RATE SP::FLEE_RATE +#endif +#if 0 FLEE2_RATE = 1053, #define SP_FLEE2_RATE SP::FLEE2_RATE +#endif DEF_RATE = 1054, #define SP_DEF_RATE SP::DEF_RATE DEF2_RATE = 1055, #define SP_DEF2_RATE SP::DEF2_RATE +#if 0 MDEF_RATE = 1056, #define SP_MDEF_RATE SP::MDEF_RATE +#endif +#if 0 MDEF2_RATE = 1057, #define SP_MDEF2_RATE SP::MDEF2_RATE +#endif +#if 0 SPLASH_RANGE = 1058, #define SP_SPLASH_RANGE SP::SPLASH_RANGE +#endif +#if 0 SPLASH_ADD_RANGE = 1059, #define SP_SPLASH_ADD_RANGE SP::SPLASH_ADD_RANGE - AUTOSPELL = 1060, -#define SP_AUTOSPELL SP::AUTOSPELL +#endif + HP_DRAIN_RATE = 1061, #define SP_HP_DRAIN_RATE SP::HP_DRAIN_RATE +#if 0 SP_DRAIN_RATE = 1062, #define SP_SP_DRAIN_RATE SP::SP_DRAIN_RATE +#endif +#if 0 SHORT_WEAPON_DAMAGE_RETURN = 1063, #define SP_SHORT_WEAPON_DAMAGE_RETURN SP::SHORT_WEAPON_DAMAGE_RETURN +#endif +#if 0 LONG_WEAPON_DAMAGE_RETURN = 1064, #define SP_LONG_WEAPON_DAMAGE_RETURN SP::LONG_WEAPON_DAMAGE_RETURN +#endif +#if 0 ADDEFF2 = 1067, #define SP_ADDEFF2 SP::ADDEFF2 +#endif BREAK_WEAPON_RATE = 1068, #define SP_BREAK_WEAPON_RATE SP::BREAK_WEAPON_RATE BREAK_ARMOR_RATE = 1069, @@ -412,36 +529,10 @@ enum class SP : uint16_t #define SP_ADD_STEAL_RATE SP::ADD_STEAL_RATE MAGIC_DAMAGE_RETURN = 1071, #define SP_MAGIC_DAMAGE_RETURN SP::MAGIC_DAMAGE_RETURN +#if 0 RANDOM_ATTACK_INCREASE = 1072, #define SP_RANDOM_ATTACK_INCREASE SP::RANDOM_ATTACK_INCREASE - ALL_STATS = 1073, -#define SP_ALL_STATS SP::ALL_STATS - AGI_VIT = 1074, -#define SP_AGI_VIT SP::AGI_VIT - AGI_DEX_STR = 1075, -#define SP_AGI_DEX_STR SP::AGI_DEX_STR - PERFECT_HIDE = 1076, -#define SP_PERFECT_HIDE SP::PERFECT_HIDE - - RESTART_FULL_RECORVER = 2000, -#define SP_RESTART_FULL_RECORVER SP::RESTART_FULL_RECORVER - NO_CASTCANCEL = 2001, -#define SP_NO_CASTCANCEL SP::NO_CASTCANCEL - NO_SIZEFIX = 2002, -#define SP_NO_SIZEFIX SP::NO_SIZEFIX - NO_MAGIC_DAMAGE = 2003, -#define SP_NO_MAGIC_DAMAGE SP::NO_MAGIC_DAMAGE - NO_WEAPON_DAMAGE = 2004, -#define SP_NO_WEAPON_DAMAGE SP::NO_WEAPON_DAMAGE - NO_GEMSTONE = 2005, -#define SP_NO_GEMSTONE SP::NO_GEMSTONE - NO_CASTCANCEL2 = 2006, -#define SP_NO_CASTCANCEL2 SP::NO_CASTCANCEL2 - - UNBREAKABLE_WEAPON = 2008, -#define SP_UNBREAKABLE_WEAPON SP::UNBREAKABLE_WEAPON - SP_UNBREAKABLE_ARMOR = 2009, -#define SP_UNBREAKABLE_ARMOR SP::UNBREAKABLE_ARMOR +#endif }; constexpr diff --git a/src/map/mob.cpp b/src/map/mob.cpp index f19cd63..47e3e16 100644 --- a/src/map/mob.cpp +++ b/src/map/mob.cpp @@ -609,8 +609,7 @@ int mob_can_move(struct mob_data *md) nullpo_ret(md); if (md->canmove_tick > gettick() - || (bool(md->opt1) && md->opt1 != Opt1::_stone6) - || bool(md->option & Option::HIDE2)) + || (bool(md->opt1) && md->opt1 != Opt1::_stone6)) return 0; // アンクル中で動けないとか if (md->sc_data[SC_ANKLE].timer != -1) @@ -630,7 +629,7 @@ int calc_next_walk_step(struct mob_data *md) if (md->walkpath.path_pos >= md->walkpath.path_len) return -1; - if (md->walkpath.path[md->walkpath.path_pos] & 1) + if (dir_is_diagonal(md->walkpath.path[md->walkpath.path_pos])) return battle_get_speed(&md->bl) * 14 / 10; return battle_get_speed(&md->bl); } @@ -647,8 +646,6 @@ int mob_walk(struct mob_data *md, unsigned int tick, int data) { int moveblock; int i, ctype; - static int dirx[8] = { 0, -1, -1, -1, 0, 1, 1, 1 }; - static int diry[8] = { 1, 1, 0, -1, -1, -1, 0, 1 }; int x, y, dx, dy; nullpo_ret(md); @@ -670,7 +667,7 @@ int mob_walk(struct mob_data *md, unsigned int tick, int data) } else { - if (md->walkpath.path[md->walkpath.path_pos] >= 8) + if (md->walkpath.path[md->walkpath.path_pos] >= DIR::COUNT) return 1; x = md->bl.x; @@ -718,11 +715,6 @@ int mob_walk(struct mob_data *md, unsigned int tick, int data) x + AREA_SIZE, y + AREA_SIZE, -dx, -dy, BL_PC); md->state.state = MS_IDLE; - - if (bool(md->option & Option::CLOAK)) - skill_check_cloaking(&md->bl); - - skill_unit_move(&md->bl, tick, 1); // Inspection of a skill unit } if ((i = calc_next_walk_step(md)) > 0) { @@ -751,7 +743,7 @@ int mob_check_attack(struct mob_data *md) struct mob_data *tmd = NULL; MobMode mode; - int race, range; + int range; nullpo_ret(md); @@ -762,8 +754,7 @@ int mob_check_attack(struct mob_data *md) if (md->skilltimer != -1) return 0; - if (bool(md->opt1) - || bool(md->option & Option::HIDE2)) + if (bool(md->opt1)) return 0; if ((tbl = map_id2bl(md->target_id)) == NULL) @@ -807,7 +798,7 @@ int mob_check_attack(struct mob_data *md) else mode = md->mode; - race = mob_db[md->mob_class].race; + Race race = mob_db[md->mob_class].race; if (!bool(mode & MobMode::CAN_ATTACK)) { md->target_id = 0; @@ -816,9 +807,9 @@ int mob_check_attack(struct mob_data *md) } if (tsd && !bool(mode & MobMode::BOSS) - && ((pc_ishiding(tsd) || tsd->state.gangsterparadise) - && race != 4 - && race != 6)) + && (tsd->state.gangsterparadise + && race != Race::_insect + && race != Race::_demon)) { md->target_id = 0; md->state.attackable = false; @@ -865,7 +856,7 @@ int mob_attack(struct mob_data *md, unsigned int tick, int) //clif_fixmobpos(md); md->state.skillstate = MSS_ATTACK; - if (mobskill_use(md, tick, MSC::NEVER_EQUAL)) + if (mobskill_use(md, tick, MobSkillCondition::NEVER_EQUAL)) return 0; md->target_lv = battle_weapon_attack(&md->bl, tbl, tick, BCT_ZERO); @@ -957,10 +948,7 @@ int mob_changestate(struct mob_data *md, MS state, int type) md->last_deadtime = gettick(); // Since it died, all aggressors' attack to this mob is stopped. clif_foreachclient(std::bind(mob_stopattacked, ph::_1, md->bl.id)); - skill_unit_out_all(&md->bl, gettick(), 1); skill_status_change_clear(&md->bl, 2); // The abnormalities in status are canceled. - skill_clear_unitgroup(&md->bl); // All skill unit groups are deleted. - skill_cleartimerskill(&md->bl); if (md->deletetimer != -1) delete_timer(md->deletetimer, mob_timer_delete); md->deletetimer = -1; @@ -982,19 +970,16 @@ void mob_timer(timer_id tid, tick_t tick, custom_id_t id, custom_data_t data) { struct mob_data *md; struct block_list *bl; - - if ((bl = map_id2bl(id)) == NULL) + bl = map_id2bl(id); + if (bl == NULL) { //攻撃してきた敵がもういないのは正常のようだ return; } - if (!bl || bl->type == BL_NUL || bl->type != BL_MOB) + if (bl->type == BL_NUL || bl->type != BL_MOB) return; - nullpo_retv(md = (struct mob_data *) bl); - - if (md->bl.type == BL_NUL || md->bl.type != BL_MOB) - return; + md = (struct mob_data *) bl; if (md->timer != tid) { @@ -1109,7 +1094,8 @@ int mob_setdelayspawn(int id) if (!bl || bl->type == BL_NUL || bl->type != BL_MOB) return -1; - nullpo_retr(-1, md = (struct mob_data *) bl); + md = (struct mob_data *) bl; + nullpo_retr(-1, md); if (!md || md->bl.type != BL_MOB) return -1; @@ -1159,12 +1145,14 @@ int mob_spawn(int id) struct mob_data *md; struct block_list *bl; - nullpo_retr(-1, bl = map_id2bl(id)); + bl = map_id2bl(id); + nullpo_retr(-1, bl); if (!bl || bl->type == BL_NUL || bl->type != BL_MOB) return -1; - nullpo_retr(-1, md = (struct mob_data *) bl); + md = (struct mob_data *) bl; + nullpo_retr(-1, md); if (!md || md->bl.type == BL_NUL || md->bl.type != BL_MOB) return -1; @@ -1173,7 +1161,6 @@ int mob_spawn(int id) if (md->bl.prev != NULL) { // clif_clearchar_area(&md->bl,3); - skill_unit_out_all(&md->bl, gettick(), 1); map_delblock(&md->bl); } @@ -1207,7 +1194,7 @@ int mob_spawn(int id) md->to_x = md->bl.x = x; md->to_y = md->bl.y = y; - md->dir = 0; + md->dir = DIR_S; map_addblock(&md->bl); @@ -1245,9 +1232,6 @@ int mob_spawn(int id) memset(md->lootitem, 0, sizeof(*md->lootitem)); md->lootitem_count = 0; - for (int i = 0; i < MAX_MOBSKILLTIMERSKILL; i++) - md->skilltimerskill[i].timer = -1; - for (StatusChange i : erange(StatusChange(), MAX_STATUSCHANGE)) { md->sc_data[i].timer = -1; @@ -1260,9 +1244,6 @@ int mob_spawn(int id) md->opt3 = Opt3::ZERO; md->option = Option::ZERO; - memset(md->skillunit, 0, sizeof(md->skillunit)); - memset(md->skillunittick, 0, sizeof(md->skillunittick)); - md->hp = battle_get_max_hp(&md->bl); if (md->hp <= 0) { @@ -1416,14 +1397,13 @@ int mob_target(struct mob_data *md, struct block_list *bl, int dist) struct map_session_data *sd; eptr sc_data; MobMode mode; - int race; nullpo_ret(md); nullpo_ret(bl); sc_data = battle_get_sc_data(bl); Option *option = battle_get_option(bl); - race = mob_db[md->mob_class].race; + Race race = mob_db[md->mob_class].race; if (md->mode == MobMode::ZERO) { @@ -1445,16 +1425,17 @@ int mob_target(struct mob_data *md, struct block_list *bl, int dist) // Coercion is exerted if it is MVPMOB. if (bool(mode & MobMode::BOSS) - || ((option != NULL && !bool(*option & (Option::CLOAK | Option::HIDE2))) - || race == 4 - || race == 6)) + || (option != NULL + || race == Race::_insect + || race == Race::_demon)) { if (bl->type == BL_PC) { - nullpo_ret(sd = (struct map_session_data *) bl); + sd = (struct map_session_data *) bl; + nullpo_ret(sd); if (sd->invincible_timer != -1 || pc_isinvisible(sd)) return 0; - if (!bool(mode & MobMode::BOSS) && race != 4 && race != 6 + if (!bool(mode & MobMode::BOSS) && race != Race::_insect && race != Race::_demon && sd->state.gangsterparadise) return 0; } @@ -1482,7 +1463,7 @@ void mob_ai_sub_hard_activesearch(struct block_list *bl, struct map_session_data *tsd = NULL; struct mob_data *tmd = NULL; MobMode mode; - int race, dist; + int dist; nullpo_retv(bl); nullpo_retv(smd); @@ -1507,7 +1488,7 @@ void mob_ai_sub_hard_activesearch(struct block_list *bl, // アクティブでターゲット射程内にいるなら、ロックする if (bool(mode & MobMode::AGGRESSIVE)) { - race = mob_db[smd->mob_class].race; + Race race = mob_db[smd->mob_class].race; //対象がPCの場合 if (tsd && !pc_isdead(tsd) && @@ -1518,10 +1499,9 @@ void mob_ai_sub_hard_activesearch(struct block_list *bl, distance(smd->bl.x, smd->bl.y, tsd->bl.x, tsd->bl.y)) < 9) { if (bool(mode & MobMode::BOSS) - || ((!pc_ishiding(tsd) - && !tsd->state.gangsterparadise) - || race == 4 - || race == 6)) + || (!tsd->state.gangsterparadise + || race == Race::_insect + || race == Race::_demon)) { // 妨害がないか判定 if (mob_can_reach(smd, bl, 12) && // 到達可能性判定 MRAND(1000) < 1000 / (++(*pcc))) @@ -1632,7 +1612,7 @@ int mob_ai_sub_hard_slavemob(struct mob_data *md, unsigned int tick) struct mob_data *mmd = NULL; struct block_list *bl; MobMode mode; - int race, old_dist; + int old_dist; nullpo_ret(md); @@ -1733,11 +1713,11 @@ int mob_ai_sub_hard_slavemob(struct mob_data *md, unsigned int tick) && !pc_isinvisible(sd)) { - race = mob_db[md->mob_class].race; + Race race = mob_db[md->mob_class].race; if (bool(mode & MobMode::BOSS) - || ((!pc_ishiding(sd) && !sd->state.gangsterparadise) - || race == 4 - || race == 6)) + || (!sd->state.gangsterparadise + || race == Race::_insect + || race == Race::_demon)) { // 妨害がないか判定 md->target_id = sd->bl.id; @@ -1787,7 +1767,8 @@ int mob_randomwalk(struct mob_data *md, int tick) if (d < 5) d = 5; for (i = 0; i < retrycount; i++) - { // Search of a movable place + { + // Search of a movable place int r = mt_random(); x = md->bl.x + r % (d * 2 + 1) - d; y = md->bl.y + r / (d * 2 + 1) % (d * 2 + 1) - d; @@ -1811,8 +1792,9 @@ int mob_randomwalk(struct mob_data *md, int tick) } } for (i = c = 0; i < md->walkpath.path_len; i++) - { // The next walk start time is calculated. - if (md->walkpath.path[i] & 1) + { + // The next walk start time is calculated. + if (dir_is_diagonal(md->walkpath.path[i])) c += speed * 14 / 10; else c += speed; @@ -1838,7 +1820,6 @@ void mob_ai_sub_hard(struct block_list *bl, unsigned int tick) int i, dx, dy, ret, dist; int attack_type = 0; MobMode mode; - int race; nullpo_retv(bl); md = (struct mob_data *) bl; @@ -1859,7 +1840,7 @@ void mob_ai_sub_hard(struct block_list *bl, unsigned int tick) else mode = md->mode; - race = mob_db[md->mob_class].race; + Race race = mob_db[md->mob_class].race; // Abnormalities if ((bool(md->opt1) && md->opt1 != Opt1::_stone6) @@ -1967,9 +1948,9 @@ void mob_ai_sub_hard(struct block_list *bl, unsigned int tick) tbl->y)) >= md->min_chase) mob_unlocktarget(md, tick); // 別マップか、視界外 else if (tsd && !bool(mode & MobMode::BOSS) - && ((pc_ishiding(tsd) - || tsd->state.gangsterparadise) && race != 4 - && race != 6)) + && (tsd->state.gangsterparadise + && race != Race::_insect + && race != Race::_demon)) mob_unlocktarget(md, tick); // スキルなどによる策敵妨害 else if (!battle_check_range(&md->bl, tbl, mob_db[md->mob_class].range)) { @@ -1982,7 +1963,7 @@ void mob_ai_sub_hard(struct block_list *bl, unsigned int tick) if (!mob_can_move(md)) // 動けない状態にある return; md->state.skillstate = MSS_CHASE; // 突撃時スキル - mobskill_use(md, tick, MSC::ANY); + mobskill_use(md, tick, MobSkillCondition::ANY); // if(md->timer != -1 && (DIFF_TICK(md->next_walktime,tick)<0 || distance(md->to_x,md->to_y,tsd->bl.x,tsd->bl.y)<2) ) if (md->timer != -1 && md->state.state != MS_ATTACK && (DIFF_TICK(md->next_walktime, tick) < 0 @@ -2086,7 +2067,7 @@ void mob_ai_sub_hard(struct block_list *bl, unsigned int tick) if (!mob_can_move(md)) // 動けない状態にある return; md->state.skillstate = MSS_LOOT; // ルート時スキル使用 - mobskill_use(md, tick, MSC::ANY); + mobskill_use(md, tick, MobSkillCondition::ANY); // if(md->timer != -1 && (DIFF_TICK(md->next_walktime,tick)<0 || distance(md->to_x,md->to_y,tbl->x,tbl->y)<2) ) if (md->timer != -1 && md->state.state != MS_ATTACK && (DIFF_TICK(md->next_walktime, tick) < 0 @@ -2144,7 +2125,7 @@ void mob_ai_sub_hard(struct block_list *bl, unsigned int tick) } // It is skill use at the time of /standby at the time of a walk. - if (mobskill_use(md, tick, MSC::ANY)) + if (mobskill_use(md, tick, MobSkillCondition::ANY)) return; // 歩行処理 @@ -2300,7 +2281,8 @@ void mob_delay_item_drop(timer_id, tick_t, custom_id_t id, custom_data_t) struct item temp_item; PickupFail flag; - nullpo_retv(ditem = (struct delay_item_drop *) id); + ditem = (struct delay_item_drop *) id; + nullpo_retv(ditem); memset(&temp_item, 0, sizeof(temp_item)); temp_item.nameid = ditem->nameid; @@ -2339,7 +2321,8 @@ void mob_delay_item_drop2(timer_id, tick_t, custom_id_t id, custom_data_t) struct delay_item_drop2 *ditem; PickupFail flag; - nullpo_retv(ditem = (struct delay_item_drop2 *) id); + ditem = (struct delay_item_drop2 *) id; + nullpo_retv(ditem); if (battle_config.item_auto_get == 1) { @@ -2500,7 +2483,7 @@ int mob_damage(struct block_list *src, struct mob_data *md, int damage, { mob_changestate(md, MS_DEAD, 0); // It is skill at the time of death. - mobskill_use(md, tick, MSC::ANY); + mobskill_use(md, tick, MobSkillCondition::ANY); clif_clearchar_area(&md->bl, 1); map_delblock(&md->bl); @@ -2599,9 +2582,6 @@ int mob_damage(struct block_list *src, struct mob_data *md, int damage, md->hp -= damage; - if (bool(md->option & Option::HIDE2)) - skill_status_change_end(&md->bl, SC_HIDING, -1); - if (md->hp > 0) { return 0; @@ -2613,7 +2593,7 @@ int mob_damage(struct block_list *src, struct mob_data *md, int damage, map_freeblock_lock(); mob_changestate(md, MS_DEAD, 0); - mobskill_use(md, tick, MSC::ANY); + mobskill_use(md, tick, MobSkillCondition::ANY); memset(tmpsd, 0, sizeof(tmpsd)); memset(pt, 0, sizeof(pt)); @@ -2777,42 +2757,6 @@ int mob_damage(struct block_list *src, struct mob_data *md, int damage, ditem->third_sd = third_sd; add_timer(tick + 500 + i, mob_delay_item_drop, (int) ditem, 0); } - if (sd && sd->state.attack_type == BF_WEAPON) - { - for (int i = 0; i < sd->monster_drop_item_count; i++) - { - struct delay_item_drop *ditem; - int race = battle_get_race(&md->bl); - if (sd->monster_drop_itemid[i] <= 0) - continue; - if (sd->monster_drop_race[i] & (1 << race) || - (bool(mob_db[md->mob_class].mode & MobMode::BOSS) - && sd->monster_drop_race[i] & 1 << 10) - || (!bool(mob_db[md->mob_class].mode & MobMode::BOSS) - && sd->monster_drop_race[i] & 1 << 11)) - { - if (sd->monster_drop_itemrate[i] <= MRAND(10000)) - continue; - - ditem = (struct delay_item_drop *) - calloc(1, sizeof(struct delay_item_drop)); - ditem->nameid = sd->monster_drop_itemid[i]; - ditem->amount = 1; - ditem->m = md->bl.m; - ditem->x = md->bl.x; - ditem->y = md->bl.y; - ditem->first_sd = mvp_sd; - ditem->second_sd = second_sd; - ditem->third_sd = third_sd; - add_timer(tick + 520 + i, mob_delay_item_drop, - (int) ditem, 0); - } - } - if (sd->get_zeny_num > 0) - pc_getzeny(sd, - mob_db[md->mob_class].lv * 10 + - MRAND((sd->get_zeny_num + 1))); - } if (md->lootitem) { for (int i = 0; i < md->lootitem_count; i++) @@ -2991,9 +2935,6 @@ int mob_class_change(struct mob_data *md, int *value) md->lootitem = (struct item *) calloc(LOOTITEM_SIZE, sizeof(struct item)); - skill_clear_unitgroup(&md->bl); - skill_cleartimerskill(&md->bl); - clif_clearchar_area(&md->bl, 0); clif_spawnmob(md); @@ -3068,7 +3009,6 @@ int mob_warp(struct mob_data *md, int m, int x, int y, int type) return 0; clif_clearchar_area(&md->bl, type); } - skill_unit_out_all(&md->bl, gettick(), 1); map_delblock(&md->bl); if (bx > 0 && by > 0) @@ -3090,7 +3030,7 @@ int mob_warp(struct mob_data *md, int m, int x, int y, int type) y = MPRAND(1, (map[m].ys - 2)); } } - md->dir = 0; + md->dir = DIR_S; if (i < 1000) { md->bl.x = md->to_x = x; @@ -3370,13 +3310,14 @@ void mobskill_castend_pos(timer_id tid, tick_t tick, custom_id_t id, custom_data { struct mob_data *md = NULL; struct block_list *bl; - int range, maxcount; + int range; //mobskill_castend_id同様詠唱したMobが詠唱完了時にもういないというのはありそうなのでnullpoから除外 if ((bl = map_id2bl(id)) == NULL) return; - nullpo_retv(md = (struct mob_data *) bl); + md = (struct mob_data *) bl; + nullpo_retv(md); if (md->bl.type != BL_MOB || md->bl.prev == NULL) return; @@ -3389,23 +3330,6 @@ void mobskill_castend_pos(timer_id tid, tick_t tick, custom_id_t id, custom_data if (bool(md->opt1)) return; - if (battle_config.monster_land_skill_limit == 1) - { - maxcount = skill_get_maxcount(md->skillid); - if (maxcount > 0) - { - int i, c; - for (i = c = 0; i < MAX_MOBSKILLUNITGROUP; i++) - { - if (md->skillunit[i].alive_count > 0 - && md->skillunit[i].skill_id == md->skillid) - c++; - } - if (c >= maxcount) - return; - } - } - range = skill_get_range(md->skillid, md->skilllv); if (range < 0) range = battle_get_range(&md->bl) - (range + 1); @@ -3433,7 +3357,8 @@ int mobskill_use_id(struct mob_data *md, struct block_list *target, int skill_lv; nullpo_ret(md); - nullpo_ret(ms = &mob_db[md->mob_class].skill[skill_idx]); + ms = &mob_db[md->mob_class].skill[skill_idx]; + nullpo_ret(ms); if (target == NULL && (target = map_id2bl(md->target_id)) == NULL) return 0; @@ -3447,9 +3372,6 @@ int mobskill_use_id(struct mob_data *md, struct block_list *target, if (bool(md->opt1)) return 0; - if (bool(md->option & Option::HIDE2)) - return 0; - if (skill_get_inf2(skill_id) & 0x200 && md->bl.id == target->id) return 0; @@ -3511,7 +3433,8 @@ int mobskill_use_pos(struct mob_data *md, int skill_lv; nullpo_ret(md); - nullpo_ret(ms = &mob_db[md->mob_class].skill[skill_idx]); + ms = &mob_db[md->mob_class].skill[skill_idx]; + nullpo_ret(ms); if (md->bl.prev == NULL) return 0; @@ -3522,9 +3445,6 @@ int mobskill_use_pos(struct mob_data *md, if (bool(md->opt1)) return 0; - if (bool(md->option & Option::HIDE2)) - return 0; - // 射程と障害物チェック bl.type = BL_NUL; bl.m = md->bl.m; @@ -3570,100 +3490,20 @@ int mobskill_use_pos(struct mob_data *md, return 1; } -/*========================================== - * Friendly Mob whose HP is decreasing by a nearby MOB is looked for. - *------------------------------------------ - */ -static -void mob_getfriendhpltmaxrate_sub(struct block_list *bl, struct mob_data *mmd, int rate, struct mob_data **fr) -{ - struct mob_data *md; - - nullpo_retv(bl); - nullpo_retv(mmd); - - md = (struct mob_data *) bl; - - if (mmd->bl.id == bl->id) - return; - - if (md->hp < mob_db[md->mob_class].max_hp * rate / 100) - (*fr) = md; -} - -static -struct mob_data *mob_getfriendhpltmaxrate(struct mob_data *md, int rate) -{ - struct mob_data *fr = NULL; - const int r = 8; - - nullpo_retr(NULL, md); - - map_foreachinarea(std::bind(mob_getfriendhpltmaxrate_sub, ph::_1, md, rate, &fr), - md->bl.m, md->bl.x - r, md->bl.y - r, - md->bl.x + r, md->bl.y + r, BL_MOB); - return fr; -} - -/*========================================== - * What a status state suits by nearby MOB is looked for. - *------------------------------------------ - */ -static -void mob_getfriendstatus_sub(struct block_list *bl, struct mob_data *mmd, MSC cond1, StatusChange cond2, struct mob_data **fr) -{ - struct mob_data *md; - int flag = 0; - - nullpo_retv(bl); - md = (struct mob_data *) bl; - - if (mmd->bl.id == bl->id) - return; - - if (cond2 == StatusChange::ANY_BAD) - { - for (StatusChange j : MAJOR_STATUS_EFFECTS) - { - flag = (md->sc_data[j].timer != -1); - if (flag) - break; - } - } - else - flag = (md->sc_data[cond2].timer != -1); - if (flag ^ (cond1 == MSC_FRIENDSTATUSOFF)) - (*fr) = md; -} - -static -struct mob_data *mob_getfriendstatus(struct mob_data *md, - MSC cond1, StatusChange cond2) -{ - struct mob_data *fr = NULL; - const int r = 8; - - nullpo_ret(md); - - map_foreachinarea(std::bind(mob_getfriendstatus_sub, ph::_1, md, cond1, cond2, &fr), - md->bl.m, md->bl.x - r, md->bl.y - r, - md->bl.x + r, md->bl.y + r, BL_MOB); - return fr; -} - /*========================================== * Skill use judging *------------------------------------------ */ int mobskill_use(struct mob_data *md, unsigned int tick, - MSC event, SkillID skill) + MobSkillCondition event, SkillID) { struct mob_skill *ms; // struct block_list *target=NULL; int max_hp; nullpo_ret(md); - nullpo_ret(ms = mob_db[md->mob_class].skill); + ms = mob_db[md->mob_class].skill; + nullpo_ret(ms); max_hp = battle_get_max_hp(&md->bl); @@ -3679,17 +3519,16 @@ int mobskill_use(struct mob_data *md, unsigned int tick, for (int ii = 0; ii < mob_db[md->mob_class].maxskill; ii++) { int flag = 0; - struct mob_data *fmd = NULL; // ディレイ中 if (DIFF_TICK(tick, md->skilldelay[ii]) < ms[ii].delay) continue; // 状態判定 - if (ms[ii].state != MSS::ANY && ms[ii].state != md->state.skillstate) + if (ms[ii].state != MobSkillState::ANY && ms[ii].state != md->state.skillstate) continue; - // Note: these *may* both be MSC::ANY + // Note: these *may* both be MobSkillCondition::ANY flag = (event == ms[ii].cond1); if (!flag) { @@ -3701,54 +3540,15 @@ int mobskill_use(struct mob_data *md, unsigned int tick, case MSC_MYHPLTMAXRATE: // HP< maxhp% flag = (md->hp < max_hp * ms[ii].cond2i / 100); break; - case MSC_MYSTATUSON: // status[num] on - case MSC_MYSTATUSOFF: // status[num] off - if (ms[ii].cond2sc() == StatusChange::ANY_BAD) - { - for (StatusChange j : MAJOR_STATUS_EFFECTS) - { - flag = (md->sc_data[j].timer != -1); - if (flag) - break; - } - } - else - flag = (md->sc_data[ms[ii].cond2sc()].timer != -1); - flag ^= (ms[ii].cond1 == MSC_MYSTATUSOFF); - break; - case MSC_FRIENDHPLTMAXRATE: // friend HP < maxhp% - flag = - ((fmd = - mob_getfriendhpltmaxrate(md, - ms[ii].cond2i)) != NULL); - break; - case MSC_FRIENDSTATUSON: // friend status[num] on - case MSC_FRIENDSTATUSOFF: // friend status[num] off - flag = - ((fmd = - mob_getfriendstatus(md, ms[ii].cond1, - ms[ii].cond2sc())) != NULL); - break; case MSC_NOTINTOWN: // Only outside of towns. flag = !map[md->bl.m].flag.town; break; case MSC_SLAVELT: // slave < num flag = (mob_countslave(md) < ms[ii].cond2i); break; - case MSC_ATTACKPCGT: // attack pc > num - flag = (mob_counttargeted(md, NULL, ATK::ZERO) > ms[ii].cond2i); - break; case MSC_SLAVELE: // slave <= num flag = (mob_countslave(md) <= ms[ii].cond2i); break; - case MSC_ATTACKPCGE: // attack pc >= num - flag = (mob_counttargeted(md, NULL, ATK::ZERO) >= ms[ii].cond2i); - break; - case MSC_SKILLUSED: // specificated skill used - flag = (event == MSC_SKILLUSED - && (skill == ms[ii].cond2sk() - || ms[ii].cond2sk() == SkillID::ZERO)); - break; } } @@ -3761,22 +3561,11 @@ int mobskill_use(struct mob_data *md, unsigned int tick, // 場所指定 struct block_list *bl = NULL; int x = 0, y = 0; - if (ms[ii].target <= MST_AROUND) { - if (ms[ii].target == MST_MASTER) { - bl = &md->bl; - if (md->master_id) - bl = map_id2bl(md->master_id); - } - else - { - bl = ((ms[ii].target == MST_TARGET - || ms[ii].target == - MST_AROUND5) ? map_id2bl(md-> - target_id) - : (ms[ii].target == - MST_FRIEND) ? &fmd->bl : &md->bl); + bl = ms[ii].target == MST_TARGET + ? map_id2bl(md->target_id) + : &md->bl; } if (bl) @@ -3787,72 +3576,16 @@ int mobskill_use(struct mob_data *md, unsigned int tick, } if (x <= 0 || y <= 0) continue; - // 自分の周囲 - if (ms[ii].target >= MST_AROUND1) - { - int bx, by, i = 0, c, m = bl->m; - // the enum values for radii are adjacent - int r = int(ms[i].target) - int(MST_AROUND1); - do - { - bx = x + MRAND((r * 2 + 3)) - r; - by = y + MRAND((r * 2 + 3)) - r; - } - while ((bx <= 0 || by <= 0 || bx >= map[m].xs - || by >= map[m].ys - || ((c = read_gat(m, bx, by)) == 1 || c == 5)) - && (i++) < 1000); - if (i < 1000) - { - x = bx; - y = by; - } - } - // 相手の周囲 - if (ms[ii].target >= MST_AROUND5) - { - int bx, by, i = 0, c, m = bl->m; - int r = int(ms[i].target) - int(MST_AROUND5) + 1; - do - { - bx = x + MRAND((r * 2 + 1)) - r; - by = y + MRAND((r * 2 + 1)) - r; - } - while ((bx <= 0 || by <= 0 || bx >= map[m].xs - || by >= map[m].ys - || ((c = read_gat(m, bx, by)) == 1 || c == 5)) - && (i++) < 1000); - if (i < 1000) - { - x = bx; - y = by; - } - } if (!mobskill_use_pos(md, x, y, ii)) return 0; - } else { - if (ms[ii].target == MST_MASTER) - { - struct block_list *bl = &md->bl; - if (md->master_id) - bl = map_id2bl(md->master_id); - - if (bl && !mobskill_use_id(md, bl, ii)) - return 0; - } - // ID指定 - if (ms[ii].target <= MST_FRIEND) { struct block_list *bl = NULL; - bl = ((ms[ii].target == - MST_TARGET) ? map_id2bl(md-> - target_id) : (ms[ii].target - == - MST_FRIEND) - ? &fmd->bl : &md->bl); + bl = (ms[ii].target == MST_TARGET) + ? map_id2bl(md->target_id) + : &md->bl; if (bl && !mobskill_use_id(md, bl, ii)) return 0; } @@ -3874,13 +3607,14 @@ int mobskill_event(struct mob_data *md, BF flag) { nullpo_ret(md); - if (flag == BF::NEGATIVE_1 && mobskill_use(md, gettick(), MSC_CASTTARGETED)) + if (flag == BF::NEGATIVE_1 + && mobskill_use(md, gettick(), MobSkillCondition::ANY)) return 1; if (bool(flag & BF_SHORT) - && mobskill_use(md, gettick(), MSC_CLOSEDATTACKED)) + && mobskill_use(md, gettick(), MobSkillCondition::ANY)) return 1; if (bool(flag & BF_LONG) - && mobskill_use(md, gettick(), MSC_LONGRANGEATTACKED)) + && mobskill_use(md, gettick(), MobSkillCondition::ANY)) return 1; return 0; } @@ -3917,9 +3651,9 @@ int mob_makedummymobdb(int mob_class) mob_db[mob_class].attrs[ATTR::LUK] = 2; mob_db[mob_class].range2 = 10; mob_db[mob_class].range3 = 10; - mob_db[mob_class].size = 0; - mob_db[mob_class].race = 0; - mob_db[mob_class].element = 0; + mob_db[mob_class].size = 0; // 1 + mob_db[mob_class].race = Race::formless; + mob_db[mob_class].element = LevelElement{0, Element::neutral}; mob_db[mob_class].mode = MobMode::ZERO; mob_db[mob_class].speed = 300; mob_db[mob_class].adelay = 1000; @@ -4038,9 +3772,9 @@ int mob_readdb(void) mob_db[mob_class].attrs[ATTR::LUK] = atoi(str[18]); mob_db[mob_class].range2 = atoi(str[19]); mob_db[mob_class].range3 = atoi(str[20]); - mob_db[mob_class].size = atoi(str[21]); - mob_db[mob_class].race = atoi(str[22]); - mob_db[mob_class].element = atoi(str[23]); + mob_db[mob_class].size = atoi(str[21]); // always 1 + mob_db[mob_class].race = static_cast(atoi(str[22])); + mob_db[mob_class].element = LevelElement::unpack(atoi(str[23])); mob_db[mob_class].mode = static_cast(atoi(str[24])); mob_db[mob_class].speed = atoi(str[25]); mob_db[mob_class].adelay = atoi(str[26]); @@ -4196,78 +3930,34 @@ int mob_readskilldb(void) const struct { char str[32]; - MSC id; + MobSkillCondition id; } cond1[] = { {"always", MSC_ALWAYS}, {"myhpltmaxrate", MSC_MYHPLTMAXRATE}, - {"friendhpltmaxrate", MSC_FRIENDHPLTMAXRATE}, - {"mystatuson", MSC_MYSTATUSON}, - {"mystatusoff", MSC_MYSTATUSOFF}, - {"friendstatuson", MSC_FRIENDSTATUSON}, - {"friendstatusoff", MSC_FRIENDSTATUSOFF}, {"notintown", MSC_NOTINTOWN}, - {"attackpcgt", MSC_ATTACKPCGT}, - {"attackpcge", MSC_ATTACKPCGE}, {"slavelt", MSC_SLAVELT}, {"slavele", MSC_SLAVELE}, - {"closedattacked", MSC_CLOSEDATTACKED}, - {"longrangeattacked", MSC_LONGRANGEATTACKED}, - {"skillused", MSC_SKILLUSED}, - {"casttargeted", MSC_CASTTARGETED}, - }; - const struct - { - char str[32]; - StatusChange id; - } cond2[] = - { - {"anybad", StatusChange::ANY_BAD}, - {"stone", SC_STONE}, - {"freeze", SC_FREEZE}, - {"stan", SC_STAN}, - {"sleep", SC_SLEEP}, - {"poison", SC_POISON}, - {"curse", SC_CURSE}, - {"silence", SC_SILENCE}, - {"confusion", SC_CONFUSION}, - {"blind", SC_BLIND}, - {"hiding", SC_HIDING}, - {"sight", SC_SIGHT}, }; const struct { char str[32]; - MSS id; + MobSkillState id; } state[] = { - {"any", MSS::ANY}, + {"any", MobSkillState::ANY}, {"idle", MSS_IDLE}, {"walk", MSS_WALK}, {"attack", MSS_ATTACK}, - {"dead", MSS_DEAD}, - {"loot", MSS_LOOT}, - {"chase", MSS_CHASE}, }; const struct { char str[32]; - MST id; + MobSkillTarget id; } target[] = { {"target", MST_TARGET}, {"self", MST_SELF}, - {"friend", MST_FRIEND}, - {"master", MST_MASTER}, - {"around5", MST_AROUND5}, - {"around6", MST_AROUND6}, - {"around7", MST_AROUND7}, - {"around8", MST_AROUND8}, - {"around1", MST_AROUND1}, - {"around2", MST_AROUND2}, - {"around3", MST_AROUND3}, - {"around4", MST_AROUND4}, - {"around", MST_AROUND}, }; int x; @@ -4322,7 +4012,7 @@ int mob_readskilldb(void) continue; } - ms->state = MSS(atoi(sp[2])); + ms->state = static_cast(atoi(sp[2])); for (j = 0; j < sizeof(state) / sizeof(state[0]); j++) { if (strcmp(sp[2], state[j].str) == 0) @@ -4337,26 +4027,19 @@ int mob_readskilldb(void) ms->cancel = atoi(sp[8]); if (strcmp(sp[8], "yes") == 0) ms->cancel = 1; - ms->target = MST(atoi(sp[9])); + ms->target = static_cast(atoi(sp[9])); for (j = 0; j < sizeof(target) / sizeof(target[0]); j++) { if (strcmp(sp[9], target[j].str) == 0) ms->target = target[j].id; } - ms->cond1 = MSC::ANY; + ms->cond1 = MobSkillCondition::ANY; for (j = 0; j < sizeof(cond1) / sizeof(cond1[0]); j++) { if (strcmp(sp[10], cond1[j].str) == 0) ms->cond1 = cond1[j].id; } - // sometimes legitimately an integer - // in fact, with current data it always is. Yay! ms->cond2i = atoi(sp[11]); - for (j = 0; j < sizeof(cond2) / sizeof(cond2[0]); j++) - { - if (strcmp(sp[11], cond2[j].str) == 0) - ms->cond2i = int(cond2[j].id); - } ms->val[0] = atoi(sp[12]); ms->val[1] = atoi(sp[13]); ms->val[2] = atoi(sp[14]); diff --git a/src/map/mob.hpp b/src/map/mob.hpp index 8247102..2d51eb0 100644 --- a/src/map/mob.hpp +++ b/src/map/mob.hpp @@ -13,17 +13,16 @@ struct mob_skill { - MSS state; + MobSkillState state; SkillID skill_id; short skill_lv; short permillage; int casttime, delay; short cancel; - MSC cond1; + MobSkillCondition cond1; int cond2i; - StatusChange cond2sc() { return StatusChange(cond2i); } SkillID cond2sk() { return SkillID(cond2i); } - MST target; + MobSkillTarget target; int val[5]; short emotion; }; @@ -38,7 +37,10 @@ struct mob_db int def, mdef; earray attrs; int range, range2, range3; - int size, race, element; + // always 1 + int size; + Race race; + LevelElement element; MobMode mode; int speed, adelay, amotion, dmotion; int mexp, mexpper; @@ -106,7 +108,7 @@ int mob_class_change(struct mob_data *md, int *value); int mob_warp(struct mob_data *md, int m, int x, int y, int type); int mobskill_use(struct mob_data *md, unsigned int tick, - MSC event, SkillID skill=SkillID::ZERO); + MobSkillCondition event, SkillID skill=SkillID::ZERO); int mobskill_event(struct mob_data *md, BF flag); void mobskill_castend_id(timer_id tid, tick_t tick, custom_id_t id, custom_data_t data); void mobskill_castend_pos(timer_id tid, tick_t tick, custom_id_t id, custom_data_t data); diff --git a/src/map/mob.t.hpp b/src/map/mob.t.hpp index 3c20e07..0fcd7f5 100644 --- a/src/map/mob.t.hpp +++ b/src/map/mob.t.hpp @@ -3,93 +3,52 @@ #include -enum class MST +enum class MobSkillTarget { MST_TARGET = 0, -#define MST_TARGET MST::MST_TARGET +#define MST_TARGET MobSkillTarget::MST_TARGET MST_SELF, -#define MST_SELF MST::MST_SELF - MST_FRIEND, -#define MST_FRIEND MST::MST_FRIEND - MST_MASTER, -#define MST_MASTER MST::MST_MASTER - MST_AROUND5, -#define MST_AROUND5 MST::MST_AROUND5 - MST_AROUND6, -#define MST_AROUND6 MST::MST_AROUND6 - MST_AROUND7, -#define MST_AROUND7 MST::MST_AROUND7 - MST_AROUND8, -#define MST_AROUND8 MST::MST_AROUND8 - MST_AROUND1, -#define MST_AROUND1 MST::MST_AROUND1 - MST_AROUND2, -#define MST_AROUND2 MST::MST_AROUND2 - MST_AROUND3, -#define MST_AROUND3 MST::MST_AROUND3 - MST_AROUND4, -#define MST_AROUND4 MST::MST_AROUND4 - MST_AROUND = MST_AROUND4, -#define MST_AROUND MST::MST_AROUND +#define MST_SELF MobSkillTarget::MST_SELF }; -enum class MSC : uint16_t +/// Used as a condition when trying to apply the chosen mob skill. +enum class MobSkillCondition : uint16_t { // used as something that never compares true NEVER_EQUAL = 0xfffe, ANY = 0xffff, MSC_ALWAYS = 0x0000, -#define MSC_ALWAYS MSC::MSC_ALWAYS +#define MSC_ALWAYS MobSkillCondition::MSC_ALWAYS MSC_MYHPLTMAXRATE = 0x0001, -#define MSC_MYHPLTMAXRATE MSC::MSC_MYHPLTMAXRATE - MSC_FRIENDHPLTMAXRATE = 0x0010, -#define MSC_FRIENDHPLTMAXRATE MSC::MSC_FRIENDHPLTMAXRATE - MSC_MYSTATUSON = 0x0020, -#define MSC_MYSTATUSON MSC::MSC_MYSTATUSON - MSC_MYSTATUSOFF = 0x0021, -#define MSC_MYSTATUSOFF MSC::MSC_MYSTATUSOFF - MSC_FRIENDSTATUSON = 0x0030, -#define MSC_FRIENDSTATUSON MSC::MSC_FRIENDSTATUSON - MSC_FRIENDSTATUSOFF = 0x0031, -#define MSC_FRIENDSTATUSOFF MSC::MSC_FRIENDSTATUSOFF +#define MSC_MYHPLTMAXRATE MobSkillCondition::MSC_MYHPLTMAXRATE + MSC_NOTINTOWN = 0x0032, -#define MSC_NOTINTOWN MSC::MSC_NOTINTOWN +#define MSC_NOTINTOWN MobSkillCondition::MSC_NOTINTOWN - MSC_ATTACKPCGT = 0x0100, -#define MSC_ATTACKPCGT MSC::MSC_ATTACKPCGT - MSC_ATTACKPCGE = 0x0101, -#define MSC_ATTACKPCGE MSC::MSC_ATTACKPCGE MSC_SLAVELT = 0x0110, -#define MSC_SLAVELT MSC::MSC_SLAVELT +#define MSC_SLAVELT MobSkillCondition::MSC_SLAVELT MSC_SLAVELE = 0x0111, -#define MSC_SLAVELE MSC::MSC_SLAVELE - MSC_CLOSEDATTACKED = 0x1000, -#define MSC_CLOSEDATTACKED MSC::MSC_CLOSEDATTACKED - MSC_LONGRANGEATTACKED = 0x1001, -#define MSC_LONGRANGEATTACKED MSC::MSC_LONGRANGEATTACKED - MSC_SKILLUSED = 0x1010, -#define MSC_SKILLUSED MSC::MSC_SKILLUSED - MSC_CASTTARGETED = 0x1011, -#define MSC_CASTTARGETED MSC::MSC_CASTTARGETED +#define MSC_SLAVELE MobSkillCondition::MSC_SLAVELE }; -enum class MSS : uint8_t +/// Used as a filter when trying to choose a mob skill to use. +enum class MobSkillState : uint8_t { ANY = 0xff, MSS_IDLE = 0, -#define MSS_IDLE MSS::MSS_IDLE +#define MSS_IDLE MobSkillState::MSS_IDLE MSS_WALK, -#define MSS_WALK MSS::MSS_WALK +#define MSS_WALK MobSkillState::MSS_WALK MSS_ATTACK, -#define MSS_ATTACK MSS::MSS_ATTACK +#define MSS_ATTACK MobSkillState::MSS_ATTACK MSS_DEAD, -#define MSS_DEAD MSS::MSS_DEAD +#define MSS_DEAD MobSkillState::MSS_DEAD MSS_LOOT, -#define MSS_LOOT MSS::MSS_LOOT +#define MSS_LOOT MobSkillState::MSS_LOOT MSS_CHASE, -#define MSS_CHASE MSS::MSS_CHASE +#define MSS_CHASE MobSkillState::MSS_CHASE }; #endif // MOB_T_HPP diff --git a/src/map/npc.cpp b/src/map/npc.cpp index c6cab1d..8501dc7 100644 --- a/src/map/npc.cpp +++ b/src/map/npc.cpp @@ -81,35 +81,23 @@ void npc_enable_sub(struct block_list *bl, struct npc_data *nd) free(name); } -int npc_enable(const char *name, int flag) +int npc_enable(const char *name, bool flag) { struct npc_data *nd = (struct npc_data *)strdb_search(npcname_db, name); if (nd == NULL) return 0; - if (flag & 1) + if (flag) { // 有効化 nd->flag &= ~1; clif_spawnnpc(nd); } - else if (flag & 2) - { - nd->flag &= ~1; - nd->option = Option::ZERO; - clif_changeoption(&nd->bl); - } - else if (flag & 4) - { - nd->flag |= 1; - nd->option = Option::HIDE2; - clif_changeoption(&nd->bl); - } else { // 無効化 nd->flag |= 1; clif_clearchar(&nd->bl, 0); } - if (flag & 3 && (nd->u.scr.xs > 0 || nd->u.scr.ys > 0)) + if (flag && (nd->u.scr.xs > 0 || nd->u.scr.ys > 0)) map_foreachinarea(std::bind(npc_enable_sub, ph::_1, nd), nd->bl.m, nd->bl.x - nd->u.scr.xs, nd->bl.y - nd->u.scr.ys, nd->bl.x + nd->u.scr.xs, nd->bl.y + nd->u.scr.ys, BL_PC); @@ -209,7 +197,8 @@ void npc_event_doall_sub(db_key_t key, db_val_t data, const char *p = key.s; struct event_data *ev; - nullpo_retv(ev = (struct event_data *) data); + ev = (struct event_data *) data; + nullpo_retv(ev); if ((p = strchr(p, ':')) && p && strcasecmp(name, p) == 0) { @@ -237,7 +226,8 @@ void npc_event_do_sub(db_key_t key, db_val_t data, const char *p = key.s; struct event_data *ev; - nullpo_retv(ev = (struct event_data *) data); + ev = (struct event_data *) data; + nullpo_retv(ev); if (p && strcasecmp(name, p) == 0) { @@ -1090,7 +1080,7 @@ int npc_parse_warp(const char *w1, const char *, const char *w3, const char *w4) nd->bl.m = m; nd->bl.x = x; nd->bl.y = y; - nd->dir = 0; + nd->dir = DIR_S; nd->flag = 0; memcpy(nd->name, w3, 24); memcpy(nd->exname, w3, 24); @@ -1144,18 +1134,23 @@ static int npc_parse_shop(char *w1, char *, char *w3, char *w4) { char *p; - int x, y, dir, m; + int x, y; + DIR dir; + int m; int max = 100, pos = 0; char mapname[24]; struct npc_data *nd; // 引数の個数チェック - if (sscanf(w1, "%[^,],%d,%d,%d", mapname, &x, &y, &dir) != 4 || - strchr(w4, ',') == NULL) + int dir_; // TODO use SSCANF or extract + if (sscanf(w1, "%[^,],%d,%d,%d", mapname, &x, &y, &dir_) != 4 + || dir_ < 0 || dir_ >= 8 + || strchr(w4, ',') == NULL) { PRINTF("bad shop line : %s\n", w3); return 1; } + dir = static_cast(dir_); m = map_mapname2mapid(mapname); nd = (struct npc_data *) calloc(1, sizeof(struct npc_data) + @@ -1282,7 +1277,9 @@ static int npc_parse_script(char *w1, char *w2, char *w3, char *w4, const char *first_line, FILE * fp, int *lines) { - int x, y, dir = 0, m, xs = 0, ys = 0, npc_class = 0; // [Valaris] thanks to fov + int x, y; + DIR dir = DIR_S; + int m, xs = 0, ys = 0, npc_class = 0; // [Valaris] thanks to fov char mapname[24]; char *srcbuf = NULL; const ScriptCode *script = NULL; @@ -1306,12 +1303,15 @@ int npc_parse_script(char *w1, char *w2, char *w3, char *w4, else { // 引数の個数チェック - if (sscanf(w1, "%[^,],%d,%d,%d", mapname, &x, &y, &dir) != 4 || - (strcmp(w2, "script") == 0 && strchr(w4, ',') == NULL)) + int dir_; // TODO use SSCANF or extract + if (sscanf(w1, "%[^,],%d,%d,%d", mapname, &x, &y, &dir_) != 4 + || dir_ < 0 || dir_ >= 8 + || (strcmp(w2, "script") == 0 && strchr(w4, ',') == NULL)) { PRINTF("bad script line : %s\n", w3); return 1; } + dir = static_cast(dir_); m = map_mapname2mapid(mapname); } diff --git a/src/map/npc.hpp b/src/map/npc.hpp index 9af2721..09fb1dc 100644 --- a/src/map/npc.hpp +++ b/src/map/npc.hpp @@ -21,7 +21,7 @@ int npc_buylist(struct map_session_data *, int, const uint16_t *); int npc_selllist(struct map_session_data *, int, const uint16_t *); int npc_parse_warp(const char *w1, const char *w2, const char *w3, const char *w4); -int npc_enable(const char *name, int flag); +int npc_enable(const char *name, bool flag); struct npc_data *npc_name2id(const char *name); int npc_get_new_npc_id(void); diff --git a/src/map/path.cpp b/src/map/path.cpp index 3766999..b764e7f 100644 --- a/src/map/path.cpp +++ b/src/map/path.cpp @@ -12,7 +12,8 @@ struct tmp_path { short x, y, dist, before, cost; - char dir, flag; + DIR dir; + char flag; }; #define calc_index(x,y) (((x)+(y)*MAX_WALKPATH) & (MAX_WALKPATH*MAX_WALKPATH-1)) @@ -128,7 +129,7 @@ int calc_cost(struct tmp_path *p, int x1, int y1) */ static int add_path(int *heap, struct tmp_path *tp, int x, int y, int dist, - int dir, int before, int x1, int y1) + DIR dir, int before, int x1, int y1) { int i; @@ -195,8 +196,7 @@ int can_place(struct map_data *m, int x, int y, int flag) *------------------------------------------ */ static -int can_move(struct map_data *m, int x0, int y0, int x1, int y1, - int flag) +int can_move(struct map_data *m, int x0, int y0, int x1, int y1, int flag) { nullpo_ret(m); @@ -270,8 +270,7 @@ int path_blownpos(int m, int x0, int y0, int dx, int dy, int count) * path探索 (x0,y0)->(x1,y1) *------------------------------------------ */ -int path_search(struct walkpath_data *wpd, int m, int x0, int y0, int x1, - int y1, int flag) +int path_search(struct walkpath_data *wpd, int m, int x0, int y0, int x1, int y1, int flag) { int heap[MAX_HEAP + 1]; struct tmp_path tp[MAX_WALKPATH * MAX_WALKPATH]; @@ -301,22 +300,23 @@ int path_search(struct walkpath_data *wpd, int m, int x0, int y0, int x1, break; x += dx; y += dy; - wpd->path[i++] = - (dx < 0) ? ((dy > 0) ? 1 : 3) : ((dy < 0) ? 5 : 7); + wpd->path[i++] = (dx < 0) + ? ((dy > 0) ? DIR_SW : DIR_NW) + : ((dy < 0) ? DIR_NE : DIR_SE); } else if (x != x1) { if (!can_move(md, x, y, x + dx, y, flag)) break; x += dx; - wpd->path[i++] = (dx < 0) ? 2 : 6; + wpd->path[i++] = (dx < 0) ? DIR_W : DIR_E; } else { // y!=y1 if (!can_move(md, x, y, x, y + dy, flag)) break; y += dy; - wpd->path[i++] = (dy > 0) ? 0 : 4; + wpd->path[i++] = (dy > 0) ? DIR_S : DIR_N; } if (x == x1 && y == y1) { @@ -335,7 +335,7 @@ int path_search(struct walkpath_data *wpd, int m, int x0, int y0, int x1, tp[i].x = x0; tp[i].y = y0; tp[i].dist = 0; - tp[i].dir = 0; + tp[i].dir = DIR_S; tp[i].before = 0; tp[i].cost = calc_cost(&tp[i], x1, y1); tp[i].flag = 0; @@ -367,29 +367,21 @@ int path_search(struct walkpath_data *wpd, int m, int x0, int y0, int x1, return 0; } if (can_move(md, x, y, x + 1, y - 1, flag)) - e += add_path(heap, tp, x + 1, y - 1, tp[rp].dist + 14, 5, rp, - x1, y1); + e += add_path(heap, tp, x + 1, y - 1, tp[rp].dist + 14, DIR_NE, rp, x1, y1); if (can_move(md, x, y, x + 1, y, flag)) - e += add_path(heap, tp, x + 1, y, tp[rp].dist + 10, 6, rp, x1, - y1); + e += add_path(heap, tp, x + 1, y, tp[rp].dist + 10, DIR_E, rp, x1, y1); if (can_move(md, x, y, x + 1, y + 1, flag)) - e += add_path(heap, tp, x + 1, y + 1, tp[rp].dist + 14, 7, rp, - x1, y1); + e += add_path(heap, tp, x + 1, y + 1, tp[rp].dist + 14, DIR_SE, rp, x1, y1); if (can_move(md, x, y, x, y + 1, flag)) - e += add_path(heap, tp, x, y + 1, tp[rp].dist + 10, 0, rp, x1, - y1); + e += add_path(heap, tp, x, y + 1, tp[rp].dist + 10, DIR_S, rp, x1, y1); if (can_move(md, x, y, x - 1, y + 1, flag)) - e += add_path(heap, tp, x - 1, y + 1, tp[rp].dist + 14, 1, rp, - x1, y1); + e += add_path(heap, tp, x - 1, y + 1, tp[rp].dist + 14, DIR_SW, rp, x1, y1); if (can_move(md, x, y, x - 1, y, flag)) - e += add_path(heap, tp, x - 1, y, tp[rp].dist + 10, 2, rp, x1, - y1); + e += add_path(heap, tp, x - 1, y, tp[rp].dist + 10, DIR_W, rp, x1, y1); if (can_move(md, x, y, x - 1, y - 1, flag)) - e += add_path(heap, tp, x - 1, y - 1, tp[rp].dist + 14, 3, rp, - x1, y1); + e += add_path(heap, tp, x - 1, y - 1, tp[rp].dist + 14, DIR_NW, rp, x1, y1); if (can_move(md, x, y, x, y - 1, flag)) - e += add_path(heap, tp, x, y - 1, tp[rp].dist + 10, 4, rp, x1, - y1); + e += add_path(heap, tp, x, y - 1, tp[rp].dist + 10, DIR_N, rp, x1, y1); tp[rp].flag = 1; if (e || heap[0] >= MAX_HEAP - 5) return -1; diff --git a/src/map/pc.cpp b/src/map/pc.cpp index dc7c77c..9826323 100644 --- a/src/map/pc.cpp +++ b/src/map/pc.cpp @@ -191,11 +191,6 @@ static int stat_p[MAX_LEVEL] = 8670,8736,8802,8868,8935, 9002, }; -static -int dirx[8] = { 0, -1, -1, -1, 0, 1, 1, 1 }; -static -int diry[8] = { 1, 1, 0, -1, -1, -1, 0, 1 }; - static earray equip_pos //= {{ @@ -431,14 +426,6 @@ int pc_setrestartvalue(struct map_session_data *sd, int type) { nullpo_ret(sd); - //----------------------- - // 死亡した - if (sd->special_state.restart_full_recover) - { // オシリスカード - sd->status.hp = sd->status.max_hp; - sd->status.sp = sd->status.max_sp; - } - else { if (battle_config.restart_hp_rate < 50) sd->status.hp = (sd->status.max_hp) / 2; @@ -728,7 +715,7 @@ int pc_breakweapon(struct map_session_data *sd) if (sd == NULL) return -1; - if (sd->unbreakable >= MRAND(100)) + if (!MRAND(100)) return 0; for (i = 0; i < MAX_INVENTORY; i++) @@ -767,7 +754,7 @@ int pc_breakarmor(struct map_session_data *sd) { if (sd == NULL) return -1; - if (sd->unbreakable >= MRAND(100)) + if (!MRAND(100)) return 0; for (int i = 0; i < MAX_INVENTORY; i++) @@ -839,15 +826,12 @@ int pc_authok(int id, int login_id2, time_t connect_until_time, sd->weapontype1 = sd->weapontype2 = 0; sd->speed = DEFAULT_WALK_SPEED; sd->state.dead_sit = 0; - sd->dir = 0; - sd->head_dir = 0; + sd->dir = DIR_S; + sd->head_dir = DIR_S; sd->state.auth = 1; sd->walktimer = -1; sd->attacktimer = -1; sd->followtimer = -1; // [MouseJstr] - sd->skilltimer = -1; - sd->skillitem = SkillID::NEGATIVE; - sd->skillitemlv = -1; sd->invincible_timer = -1; sd->sg_count = 0; @@ -877,8 +861,6 @@ int pc_authok(int id, int login_id2, time_t connect_until_time, sd->spiritball = 0; for (int i = 0; i < MAX_SKILL_LEVEL; i++) sd->spirit_timer[i] = -1; - for (int i = 0; i < MAX_SKILLTIMERSKILL; i++) - sd->skilltimerskill[i].timer = -1; memset(&sd->dev, 0, sizeof(struct square)); for (int i = 0; i < 5; i++) @@ -904,13 +886,9 @@ int pc_authok(int id, int login_id2, time_t connect_until_time, sd->sc_count = 0; if ((battle_config.atc_gmonly == 0 || pc_isGM(sd)) && (pc_isGM(sd) >= get_atcommand_level(AtCommand_Hide))) - sd->status.option &= (Option::MASK | Option::HIDE); + sd->status.option &= Option::HIDE; else - sd->status.option &= Option::MASK; - - // スキルユニット関係の初期化 - memset(sd->skillunit, 0, sizeof(sd->skillunit)); - memset(sd->skillunittick, 0, sizeof(sd->skillunittick)); + sd->status.option = Option::ZERO; // init ignore list memset(sd->ignore, 0, sizeof(sd->ignore)); @@ -1135,7 +1113,7 @@ int pc_calcstatus(struct map_session_data *sd, int first) int b_base_atk; earray b_skill; int bl, index; - int aspd_rate, wele, wele_, def_ele, refinedef = 0; + int aspd_rate, refinedef = 0; int str, dstr, dex; nullpo_ret(sd); @@ -1217,8 +1195,6 @@ int pc_calcstatus(struct map_session_data *sd, int first) sd->status.max_sp = 0; sd->attackrange = 0; sd->attackrange_ = 0; - sd->atk_ele = 0; - sd->def_ele = 0; sd->star = 0; sd->overrefine = 0; sd->matk1 = 0; @@ -1226,26 +1202,17 @@ int pc_calcstatus(struct map_session_data *sd, int first) sd->speed = DEFAULT_WALK_SPEED; sd->hprate = 100; sd->sprate = 100; - sd->castrate = 100; sd->dsprate = 100; sd->base_atk = 0; sd->arrow_atk = 0; - sd->arrow_ele = 0; sd->arrow_hit = 0; sd->arrow_range = 0; sd->nhealhp = sd->nhealsp = sd->nshealhp = sd->nshealsp = sd->nsshealhp = sd->nsshealsp = 0; - for (int& ire : sd->addeff) - ire = 0; - for (int& ire : sd->addeff2) - ire = 0; - for (int& ire : sd->reseff) - ire = 0; memset(&sd->special_state, 0, sizeof(sd->special_state)); sd->watk_ = 0; //二刀流用(仮) sd->watk_2 = 0; - sd->atk_ele_ = 0; sd->star_ = 0; sd->overrefine_ = 0; @@ -1255,38 +1222,17 @@ int pc_calcstatus(struct map_session_data *sd, int first) sd->sprecov_rate = 100; sd->critical_def = 0; sd->double_rate = 0; - sd->near_attack_def_rate = sd->long_attack_def_rate = 0; sd->atk_rate = sd->matk_rate = 100; - sd->ignore_def_ele = sd->ignore_def_race = 0; - sd->ignore_def_ele_ = sd->ignore_def_race_ = 0; - sd->ignore_mdef_ele = sd->ignore_mdef_race = 0; sd->arrow_cri = 0; - sd->magic_def_rate = sd->misc_def_rate = 0; - for (int& ire : sd->arrow_addeff) - ire = 0; - for (int& ire : sd->arrow_addeff2) - ire = 0; sd->perfect_hit = 0; sd->critical_rate = sd->hit_rate = sd->flee_rate = sd->flee2_rate = 100; sd->def_rate = sd->def2_rate = sd->mdef_rate = sd->mdef2_rate = 100; - sd->def_ratio_atk_ele = sd->def_ratio_atk_ele_ = 0; - sd->def_ratio_atk_race = sd->def_ratio_atk_race_ = 0; - sd->get_zeny_num = 0; - sd->monster_drop_item_count = 0; - memset(sd->monster_drop_race, 0, sizeof(sd->monster_drop_race)); - memset(sd->monster_drop_itemrate, 0, sizeof(sd->monster_drop_itemrate)); sd->speed_add_rate = sd->aspd_add_rate = 100; - sd->double_add_rate = sd->perfect_hit_add = sd->get_zeny_add_num = 0; - sd->splash_range = sd->splash_add_range = 0; - sd->autospell_id = SkillID::ZERO; - sd->autospell_lv = sd->autospell_rate = 0; + sd->double_add_rate = sd->perfect_hit_add = 0; sd->hp_drain_rate = sd->hp_drain_per = sd->sp_drain_rate = sd->sp_drain_per = 0; sd->hp_drain_rate_ = sd->hp_drain_per_ = sd->sp_drain_rate_ = sd->sp_drain_per_ = 0; - sd->short_weapon_damage_return = sd->long_weapon_damage_return = 0; - sd->magic_damage_return = 0; //AppleGirl Was Here - sd->random_attack_increase_add = sd->random_attack_increase_per = 0; sd->spellpower_bonus_target = 0; @@ -1371,9 +1317,6 @@ int pc_calcstatus(struct map_session_data *sd, int first) if (sd->spellpower_bonus_target < sd->spellpower_bonus_current) sd->spellpower_bonus_current = sd->spellpower_bonus_target; - wele = sd->atk_ele; - wele_ = sd->atk_ele_; - def_ele = sd->def_ele; sd->paramcard = sd->parame; // 装備品によるステータス変化はここで実行 @@ -1409,7 +1352,6 @@ int pc_calcstatus(struct map_session_data *sd, int first) if (sd->status.inventory[index].card[0] == 0x00ff) { // 製造武器 sd->star_ = (sd->status.inventory[index].card[1] >> 8); // 星のかけら - wele_ = (sd->status.inventory[index].card[1] & 0x0f); // 属 性 } sd->attackrange_ += sd->inventory_data[index]->range; sd->state.lr_flag = 1; @@ -1440,7 +1382,6 @@ int pc_calcstatus(struct map_session_data *sd, int first) if (sd->status.inventory[index].card[0] == 0x00ff) { // 製造武器 sd->star += (sd->status.inventory[index].card[1] >> 8); // 星のかけら - wele = (sd->status.inventory[index].card[1] & 0x0f); // 属 性 } sd->attackrange += sd->inventory_data[index]->range; run_script_l(sd->inventory_data[index]->equip_script, 0, @@ -1498,16 +1439,8 @@ int pc_calcstatus(struct map_session_data *sd, int first) sd->attackrange = sd->attackrange_; if (sd->status.weapon == 11) sd->attackrange += sd->arrow_range; - if (wele > 0) - sd->atk_ele = wele; - if (wele_ > 0) - sd->atk_ele_ = wele_; - if (def_ele > 0) - sd->def_ele = def_ele; sd->double_rate += sd->double_add_rate; sd->perfect_hit += sd->perfect_hit_add; - sd->get_zeny_num += sd->get_zeny_add_num; - sd->splash_range += sd->splash_add_range; if (sd->speed_add_rate != 100) sd->speed_rate += sd->speed_add_rate - 100; if (sd->aspd_add_rate != 100) @@ -1821,7 +1754,6 @@ int pc_calcstatus(struct map_session_data *sd, int first) * 装 備品による能力等のボーナス設定 *------------------------------------------ */ -// TODO: in each pc_bonus*, purge all 'type' not used by scripts int pc_bonus(struct map_session_data *sd, SP type, int val) { nullpo_ret(sd); @@ -1837,49 +1769,56 @@ int pc_bonus(struct map_session_data *sd, SP type, int val) if (sd->state.lr_flag != 2) sd->parame[sp_to_attr(type)] += val; break; +#if 0 case SP_ATK1: if (!sd->state.lr_flag) sd->watk += val; else if (sd->state.lr_flag == 1) sd->watk_ += val; break; +#endif +#if 0 case SP_ATK2: if (!sd->state.lr_flag) sd->watk2 += val; else if (sd->state.lr_flag == 1) sd->watk_2 += val; break; +#endif +#if 0 case SP_BASE_ATK: if (sd->state.lr_flag != 2) sd->base_atk += val; break; +#endif +#if 0 case SP_MATK1: if (sd->state.lr_flag != 2) sd->matk1 += val; break; +#endif +#if 0 case SP_MATK2: if (sd->state.lr_flag != 2) sd->matk2 += val; break; - case SP_MATK: - if (sd->state.lr_flag != 2) - { - sd->matk1 += val; - sd->matk2 += val; - } - break; +#endif +#if 0 case SP_DEF1: if (sd->state.lr_flag != 2) sd->def += val; break; +#endif case SP_MDEF1: if (sd->state.lr_flag != 2) sd->mdef += val; break; +#if 0 case SP_MDEF2: if (sd->state.lr_flag != 2) sd->mdef += val; break; +#endif case SP_HIT: if (sd->state.lr_flag != 2) sd->hit += val; @@ -1890,28 +1829,18 @@ int pc_bonus(struct map_session_data *sd, SP type, int val) if (sd->state.lr_flag != 2) sd->flee += val; break; +#if 0 case SP_FLEE2: if (sd->state.lr_flag != 2) sd->flee2 += val * 10; break; +#endif case SP_CRITICAL: if (sd->state.lr_flag != 2) sd->critical += val * 10; else sd->arrow_cri += val * 10; break; - case SP_ATKELE: - if (!sd->state.lr_flag) - sd->atk_ele = val; - else if (sd->state.lr_flag == 1) - sd->atk_ele_ = val; - else if (sd->state.lr_flag == 2) - sd->arrow_ele = val; - break; - case SP_DEFELE: - if (sd->state.lr_flag != 2) - sd->def_ele = val; - break; case SP_MAXHP: if (sd->state.lr_flag != 2) sd->status.max_hp += val; @@ -1920,22 +1849,22 @@ int pc_bonus(struct map_session_data *sd, SP type, int val) if (sd->state.lr_flag != 2) sd->status.max_sp += val; break; - case SP_CASTRATE: - if (sd->state.lr_flag != 2) - sd->castrate += val; - break; case SP_MAXHPRATE: if (sd->state.lr_flag != 2) sd->hprate += val; break; +#if 0 case SP_MAXSPRATE: if (sd->state.lr_flag != 2) sd->sprate += val; break; +#endif +#if 0 case SP_SPRATE: if (sd->state.lr_flag != 2) sd->dsprate += val; break; +#endif case SP_ATTACKRANGE: if (!sd->state.lr_flag) sd->attackrange += val; @@ -1944,10 +1873,13 @@ int pc_bonus(struct map_session_data *sd, SP type, int val) else if (sd->state.lr_flag == 2) sd->arrow_range += val; break; +#if 0 case SP_ADD_SPEED: if (sd->state.lr_flag != 2) sd->speed -= val; break; +#endif +#if 0 case SP_SPEED_RATE: if (sd->state.lr_flag != 2) { @@ -1955,14 +1887,17 @@ int pc_bonus(struct map_session_data *sd, SP type, int val) sd->speed_rate = 100 - val; } break; +#endif case SP_SPEED_ADDRATE: if (sd->state.lr_flag != 2) sd->speed_add_rate = sd->speed_add_rate * (100 - val) / 100; break; +#if 0 case SP_ASPD: if (sd->state.lr_flag != 2) sd->aspd -= val * 10; break; +#endif case SP_ASPD_RATE: if (sd->state.lr_flag != 2) { @@ -1970,118 +1905,86 @@ int pc_bonus(struct map_session_data *sd, SP type, int val) sd->aspd_rate = 100 - val; } break; +#if 0 case SP_ASPD_ADDRATE: if (sd->state.lr_flag != 2) sd->aspd_add_rate = sd->aspd_add_rate * (100 - val) / 100; break; +#endif case SP_HP_RECOV_RATE: if (sd->state.lr_flag != 2) sd->hprecov_rate += val; break; +#if 0 case SP_SP_RECOV_RATE: if (sd->state.lr_flag != 2) sd->sprecov_rate += val; break; +#endif +#if 0 case SP_CRITICAL_DEF: if (sd->state.lr_flag != 2) sd->critical_def += val; break; - case SP_NEAR_ATK_DEF: - if (sd->state.lr_flag != 2) - sd->near_attack_def_rate += val; - break; - case SP_LONG_ATK_DEF: - if (sd->state.lr_flag != 2) - sd->long_attack_def_rate += val; - break; +#endif +#if 0 case SP_DOUBLE_RATE: if (sd->state.lr_flag == 0 && sd->double_rate < val) sd->double_rate = val; break; +#endif case SP_DOUBLE_ADD_RATE: if (sd->state.lr_flag == 0) sd->double_add_rate += val; break; +#if 0 case SP_MATK_RATE: if (sd->state.lr_flag != 2) sd->matk_rate += val; break; - case SP_IGNORE_DEF_ELE: - if (!sd->state.lr_flag) - sd->ignore_def_ele |= 1 << val; - else if (sd->state.lr_flag == 1) - sd->ignore_def_ele_ |= 1 << val; - break; - case SP_IGNORE_DEF_RACE: - if (!sd->state.lr_flag) - sd->ignore_def_race |= 1 << val; - else if (sd->state.lr_flag == 1) - sd->ignore_def_race_ |= 1 << val; - break; +#endif +#if 0 case SP_ATK_RATE: if (sd->state.lr_flag != 2) sd->atk_rate += val; break; - case SP_MAGIC_ATK_DEF: - if (sd->state.lr_flag != 2) - sd->magic_def_rate += val; - break; - case SP_MISC_ATK_DEF: - if (sd->state.lr_flag != 2) - sd->misc_def_rate += val; - break; - case SP_IGNORE_MDEF_ELE: - if (sd->state.lr_flag != 2) - sd->ignore_mdef_ele |= 1 << val; - break; - case SP_IGNORE_MDEF_RACE: - if (sd->state.lr_flag != 2) - sd->ignore_mdef_race |= 1 << val; - break; +#endif +#if 0 case SP_PERFECT_HIT_RATE: if (sd->state.lr_flag != 2 && sd->perfect_hit < val) sd->perfect_hit = val; break; +#endif +#if 0 case SP_PERFECT_HIT_ADD_RATE: if (sd->state.lr_flag != 2) sd->perfect_hit_add += val; break; +#endif +#if 0 case SP_CRITICAL_RATE: if (sd->state.lr_flag != 2) sd->critical_rate += val; break; - case SP_GET_ZENY_NUM: - if (sd->state.lr_flag != 2 && sd->get_zeny_num < val) - sd->get_zeny_num = val; - break; - case SP_ADD_GET_ZENY_NUM: - if (sd->state.lr_flag != 2) - sd->get_zeny_add_num += val; - break; - case SP_DEF_RATIO_ATK_ELE: - if (!sd->state.lr_flag) - sd->def_ratio_atk_ele |= 1 << val; - else if (sd->state.lr_flag == 1) - sd->def_ratio_atk_ele_ |= 1 << val; - break; - case SP_DEF_RATIO_ATK_RACE: - if (!sd->state.lr_flag) - sd->def_ratio_atk_race |= 1 << val; - else if (sd->state.lr_flag == 1) - sd->def_ratio_atk_race_ |= 1 << val; - break; +#endif +#if 0 case SP_HIT_RATE: if (sd->state.lr_flag != 2) sd->hit_rate += val; break; +#endif +#if 0 case SP_FLEE_RATE: if (sd->state.lr_flag != 2) sd->flee_rate += val; break; +#endif +#if 0 case SP_FLEE2_RATE: if (sd->state.lr_flag != 2) sd->flee2_rate += val; break; +#endif case SP_DEF_RATE: if (sd->state.lr_flag != 2) sd->def_rate += val; @@ -2090,107 +1993,18 @@ int pc_bonus(struct map_session_data *sd, SP type, int val) if (sd->state.lr_flag != 2) sd->def2_rate += val; break; +#if 0 case SP_MDEF_RATE: if (sd->state.lr_flag != 2) sd->mdef_rate += val; break; +#endif +#if 0 case SP_MDEF2_RATE: if (sd->state.lr_flag != 2) sd->mdef2_rate += val; break; - case SP_RESTART_FULL_RECORVER: - if (sd->state.lr_flag != 2) - sd->special_state.restart_full_recover = 1; - break; - case SP_NO_CASTCANCEL: - if (sd->state.lr_flag != 2) - sd->special_state.no_castcancel = 1; - break; - case SP_NO_CASTCANCEL2: - if (sd->state.lr_flag != 2) - sd->special_state.no_castcancel2 = 1; - break; - case SP_NO_SIZEFIX: - if (sd->state.lr_flag != 2) - sd->special_state.no_sizefix = 1; - break; - case SP_NO_MAGIC_DAMAGE: - if (sd->state.lr_flag != 2) - sd->special_state.no_magic_damage = 1; - break; - case SP_NO_WEAPON_DAMAGE: - if (sd->state.lr_flag != 2) - sd->special_state.no_weapon_damage = 1; - break; - case SP_NO_GEMSTONE: - if (sd->state.lr_flag != 2) - sd->special_state.no_gemstone = 1; - break; - case SP_SPLASH_RANGE: - if (sd->state.lr_flag != 2 && sd->splash_range < val) - sd->splash_range = val; - break; - case SP_SPLASH_ADD_RANGE: - if (sd->state.lr_flag != 2) - sd->splash_add_range += val; - break; - case SP_SHORT_WEAPON_DAMAGE_RETURN: - if (sd->state.lr_flag != 2) - sd->short_weapon_damage_return += val; - break; - case SP_LONG_WEAPON_DAMAGE_RETURN: - if (sd->state.lr_flag != 2) - sd->long_weapon_damage_return += val; - break; - case SP_MAGIC_DAMAGE_RETURN: //AppleGirl Was Here - if (sd->state.lr_flag != 2) - sd->magic_damage_return += val; - break; - case SP_ALL_STATS: // [Valaris] - if (sd->state.lr_flag != 2) - { - for (ATTR attr : ATTRs) - sd->parame[attr] += val; - clif_updatestatus(sd, SP_STR); - clif_updatestatus(sd, SP_AGI); - clif_updatestatus(sd, SP_VIT); - clif_updatestatus(sd, SP_INT); - clif_updatestatus(sd, SP_DEX); - clif_updatestatus(sd, SP_LUK); - } - break; - case SP_AGI_VIT: // [Valaris] - if (sd->state.lr_flag != 2) - { - sd->parame[ATTR::AGI] += val; - sd->parame[ATTR::VIT] += val; - clif_updatestatus(sd, SP_AGI); - clif_updatestatus(sd, SP_VIT); - } - break; - case SP_AGI_DEX_STR: // [Valaris] - if (sd->state.lr_flag != 2) - { - sd->parame[ATTR::AGI] += val; - sd->parame[ATTR::DEX] += val; - sd->parame[ATTR::STR] += val; - clif_updatestatus(sd, SP_AGI); - clif_updatestatus(sd, SP_DEX); - clif_updatestatus(sd, SP_STR); - } - break; - case SP_PERFECT_HIDE: // [Valaris] - if (sd->state.lr_flag != 2) - { - sd->perfect_hiding = 1; - } - break; - case SP_UNBREAKABLE: - if (sd->state.lr_flag != 2) - { - sd->unbreakable += val; - } - break; +#endif case SP_DEAF: sd->special_state.deaf = 1; break; @@ -2213,22 +2027,6 @@ int pc_bonus2(struct map_session_data *sd, SP type, int type2, int val) switch (type) { - case SP_ADDEFF: - if (sd->state.lr_flag != 2) - sd->addeff[BadSC(type2)] += val; - else - sd->arrow_addeff[BadSC(type2)] += val; - break; - case SP_ADDEFF2: - if (sd->state.lr_flag != 2) - sd->addeff2[BadSC(type2)] += val; - else - sd->arrow_addeff2[BadSC(type2)] += val; - break; - case SP_RESEFF: - if (sd->state.lr_flag != 2) - sd->reseff[BadSC(type2)] += val; - break; case SP_HP_DRAIN_RATE: if (!sd->state.lr_flag) { @@ -2241,6 +2039,7 @@ int pc_bonus2(struct map_session_data *sd, SP type, int type2, int val) sd->hp_drain_per_ += val; } break; +#if 0 case SP_SP_DRAIN_RATE: if (!sd->state.lr_flag) { @@ -2253,14 +2052,7 @@ int pc_bonus2(struct map_session_data *sd, SP type, int type2, int val) sd->sp_drain_per_ += val; } break; - case SP_RANDOM_ATTACK_INCREASE: // [Valaris] - if (sd->state.lr_flag != 2) - { - sd->random_attack_increase_add = type2; - sd->random_attack_increase_per += val; - break; - } // end addition - break; +#endif default: if (battle_config.error_log) PRINTF("pc_bonus2: unknown type %d %d %d!\n", @@ -2270,56 +2062,6 @@ int pc_bonus2(struct map_session_data *sd, SP type, int type2, int val) return 0; } -int pc_bonus3(struct map_session_data *sd, SP type, int type2, int type3, - int val) -{ - int i; - switch (type) - { - case SP_ADD_MONSTER_DROP_ITEM: - if (sd->state.lr_flag != 2) - { - for (i = 0; i < sd->monster_drop_item_count; i++) - { - if (sd->monster_drop_itemid[i] == type2) - { - sd->monster_drop_race[i] |= 1 << type3; - if (sd->monster_drop_itemrate[i] < val) - sd->monster_drop_itemrate[i] = val; - break; - } - } - if (i >= sd->monster_drop_item_count - && sd->monster_drop_item_count < 10) - { - sd->monster_drop_itemid[sd->monster_drop_item_count] = - type2; - sd->monster_drop_race[sd->monster_drop_item_count] |= - 1 << type3; - sd->monster_drop_itemrate[sd->monster_drop_item_count] = - val; - sd->monster_drop_item_count++; - } - } - break; - case SP_AUTOSPELL: - if (sd->state.lr_flag != 2) - { - sd->autospell_id = SkillID(type2); - sd->autospell_lv = type3; - sd->autospell_rate = val; - } - break; - default: - if (battle_config.error_log) - PRINTF("pc_bonus3: unknown type %d %d %d %d!\n", - type, type2, type3, val); - break; - } - - return 0; -} - /*========================================== * スクリプトによるスキル所得 *------------------------------------------ @@ -2982,9 +2724,6 @@ int pc_setpos(struct map_session_data *sd, const char *mapname_org, int x, int y skill_gangsterparadise(sd, 0); } - if (bool(sd->status.option & Option::HIDE2)) - skill_status_change_end(&sd->bl, SC_HIDING, -1); - memcpy(mapname, mapname_org, 24); mapname[16] = 0; if (strstr(mapname, ".gat") == NULL && strlen(mapname) < 16) @@ -3002,7 +2741,6 @@ int pc_setpos(struct map_session_data *sd, const char *mapname_org, int x, int y if (map_mapname2ipport(mapname, &ip, &port) == 0) { skill_stop_dancing(&sd->bl, 1); - skill_unit_out_all(&sd->bl, gettick(), 1); clif_clearchar_area(&sd->bl, clrtype & 0xffff); skill_gangsterparadise(sd, 0); map_delblock(&sd->bl); @@ -3047,7 +2785,6 @@ int pc_setpos(struct map_session_data *sd, const char *mapname_org, int x, int y if (sd->mapname[0] && sd->bl.prev != NULL) { - skill_unit_out_all(&sd->bl, gettick(), 1); clif_clearchar_area(&sd->bl, clrtype & 0xffff); skill_gangsterparadise(sd, 0); map_delblock(&sd->bl); @@ -3135,7 +2872,7 @@ int calc_next_walk_step(struct map_session_data *sd) if (sd->walkpath.path_pos >= sd->walkpath.path_len) return -1; - if (sd->walkpath.path[sd->walkpath.path_pos] & 1) + if (dir_is_diagonal(sd->walkpath.path[sd->walkpath.path_pos])) return sd->speed * 14 / 10; return sd->speed; @@ -3184,7 +2921,7 @@ void pc_walk(timer_id tid, tick_t tick, custom_id_t id, custom_data_t data) } else { // マス目境界へ到着 - if (sd->walkpath.path[sd->walkpath.path_pos] >= 8) + if (sd->walkpath.path[sd->walkpath.path_pos] >= DIR::COUNT) return; x = sd->bl.x; @@ -3196,8 +2933,8 @@ void pc_walk(timer_id tid, tick_t tick, custom_id_t id, custom_data_t data) return; } sd->dir = sd->head_dir = sd->walkpath.path[sd->walkpath.path_pos]; - dx = dirx[(int) sd->dir]; - dy = diry[(int) sd->dir]; + dx = dirx[sd->dir]; + dy = diry[sd->dir]; ctype = map_getcell(sd->bl.m, x + dx, y + dy); if (ctype == 1 || ctype == 5) { @@ -3247,9 +2984,7 @@ void pc_walk(timer_id tid, tick_t tick, custom_id_t id, custom_data_t data) sd->party_hp = -1; } } - // クローキングの消滅検査 - if (bool(sd->status.option & Option::CLOAK)) - skill_check_cloaking(&sd->bl); + // ディボーション検査 for (i = 0; i < 5; i++) if (sd->dev.val1[i]) @@ -3258,8 +2993,6 @@ void pc_walk(timer_id tid, tick_t tick, custom_id_t id, custom_data_t data) break; } - skill_unit_move(&sd->bl, tick, 1); // スキルユニットの検査 - if (map_getcell(sd->bl.m, x, y) & 0x80) npc_touch_areanpc(sd, sd->bl.m, x, y); else @@ -3377,7 +3110,7 @@ void pc_touch_all_relevant_npcs(struct map_session_data *sd) int pc_movepos(struct map_session_data *sd, int dst_x, int dst_y) { int moveblock; - int dx, dy, dist; + int dx, dy; struct walkpath_data wpd; @@ -3390,7 +3123,6 @@ int pc_movepos(struct map_session_data *sd, int dst_x, int dst_y) dx = dst_x - sd->bl.x; dy = dst_y - sd->bl.y; - dist = distance(sd->bl.x, sd->bl.y, dst_x, dst_y); moveblock = (sd->bl.x / BLOCK_SIZE != dst_x / BLOCK_SIZE || sd->bl.y / BLOCK_SIZE != dst_y / BLOCK_SIZE); @@ -3430,12 +3162,6 @@ int pc_movepos(struct map_session_data *sd, int dst_x, int dst_y) } } - // クローキングの消滅検査 - if (bool(sd->status.option & Option::CLOAK)) - skill_check_cloaking(&sd->bl); - - skill_unit_move(&sd->bl, gettick(), dist + 7); // スキルユニットの検査 - pc_touch_all_relevant_npcs(sd); return 0; } @@ -3515,17 +3241,13 @@ void pc_attack_timer(timer_id tid, tick_t tick, custom_id_t id, custom_data_t) return; // 異常などで攻撃できない - if (sd->opt1 != Opt1::ZERO - || bool(sd->status.option & (Option::OLD_ANY_HIDE))) + if (sd->opt1 != Opt1::ZERO) return; Option *opt = battle_get_option(bl); if (opt != NULL && bool(*opt & Option::REAL_ANY_HIDE)) return; - if (sd->skilltimer != -1) - return; - if (!battle_config.sdelay_attack_enable) { if (DIFF_TICK(tick, sd->canact_tick) < 0) @@ -4192,9 +3914,6 @@ int pc_damage(struct block_list *src, struct map_session_data *sd, sd->status.hp -= damage; - if (bool(sd->status.option & Option::HIDE2)) - skill_status_change_end(&sd->bl, SC_HIDING, -1); - if (sd->status.hp > 0) { // まだ生きているならHP更新 @@ -4227,7 +3946,6 @@ int pc_damage(struct block_list *src, struct map_session_data *sd, pc_stop_walking(sd, 0); skill_castcancel(&sd->bl, 0); // 詠唱の中止 clif_clearchar_area(&sd->bl, 1); - skill_unit_out_all(&sd->bl, gettick(), 1); pc_setglobalreg(sd, "PC_DIE_COUNTER", ++sd->die_counter); //死にカウンター書き込み skill_status_change_clear(&sd->bl, 0); // ステータス異常を解除する clif_updatestatus(sd, SP_HP); @@ -4476,9 +4194,6 @@ int pc_readparam(struct map_session_data *sd, SP type) case SP_LUK: val = sd->status.attrs[sp_to_attr(type)]; break; - case SP_FAME: - val = sd->fame; - break; } return val; @@ -4595,9 +4310,6 @@ int pc_setparam(struct map_session_data *sd, SP type, int val) case SP_LUK: sd->status.attrs[sp_to_attr(type)] = val; break; - case SP_FAME: - sd->fame = val; - break; } clif_updatestatus(sd, type); @@ -4734,13 +4446,6 @@ int pc_itemheal_effect(struct map_session_data *sd, int hp, int sp) { nullpo_ret(sd); - if (sd->state.potionpitcher_flag) - { - sd->potion_hp = hp; - sd->potion_sp = sp; - return 0; - } - if (pc_checkoverhp(sd)) { if (hp > 0) @@ -4791,13 +4496,6 @@ int pc_percentheal(struct map_session_data *sd, int hp, int sp) { nullpo_ret(sd); - if (sd->state.potionpitcher_flag) - { - sd->potion_per_hp = hp; - sd->potion_per_sp = sp; - return 0; - } - if (pc_checkoverhp(sd)) { if (hp > 0) @@ -5742,7 +5440,8 @@ int pc_calc_pvprank(struct map_session_data *sd) struct map_data *m; nullpo_ret(sd); - nullpo_ret(m = &map[sd->bl.m]); + m = &map[sd->bl.m]; + nullpo_ret(m); if (!(m->flag.pvp)) return 0; @@ -6117,7 +5816,7 @@ void pc_natural_heal_sub(struct map_session_data *sd) || battle_config.natural_heal_weight_rate > 100 || sd->weight * 100 / sd->max_weight < battle_config.natural_heal_weight_rate) && !pc_isdead(sd) - && !pc_ishiding(sd) && sd->sc_data[SC_POISON].timer == -1) + && sd->sc_data[SC_POISON].timer == -1) { pc_natural_heal_hp(sd); pc_natural_heal_sp(sd); diff --git a/src/map/pc.hpp b/src/map/pc.hpp index 6670293..9b0f4ef 100644 --- a/src/map/pc.hpp +++ b/src/map/pc.hpp @@ -22,7 +22,7 @@ bool pc_issit(struct map_session_data *sd) return sd->state.dead_sit == 2; } inline -void pc_setdir(struct map_session_data *sd, int b) +void pc_setdir(struct map_session_data *sd, DIR b) { sd->dir = (b); } @@ -32,11 +32,6 @@ void pc_setchatid(struct map_session_data *sd, int n) sd->chatID = n; } inline -bool pc_ishiding(struct map_session_data *sd) -{ - return bool(sd->status.option & Option::OLD_ANY_HIDE); -} -inline bool pc_isinvisible(struct map_session_data *sd) { return bool(sd->status.option & Option::HIDE); @@ -98,7 +93,6 @@ int pc_checkweighticon(struct map_session_data *sd); int pc_calcstatus(struct map_session_data *, int); int pc_bonus(struct map_session_data *, SP, int); int pc_bonus2(struct map_session_data *sd, SP, int, int); -int pc_bonus3(struct map_session_data *sd, SP, int, int, int); int pc_skill(struct map_session_data *, SkillID, int, int); int pc_steal_item(struct map_session_data *sd, struct block_list *bl); diff --git a/src/map/script.cpp b/src/map/script.cpp index 4304640..c7bd9cd 100644 --- a/src/map/script.cpp +++ b/src/map/script.cpp @@ -3232,9 +3232,6 @@ void builtin_sc_start(ScriptState *st) bl = map_id2bl(conv_num(st, &(st->stack->stack_data[st->start + 5]))); else bl = map_id2bl(st->rid); - if (bl->type == BL_PC - && ((struct map_session_data *) bl)->state.potionpitcher_flag) - bl = map_id2bl(((struct map_session_data *) bl)->skilltarget); skill_status_change_start(bl, type, val1, 0, 0, 0, tick, 0); } @@ -3248,9 +3245,6 @@ void builtin_sc_end(ScriptState *st) struct block_list *bl; StatusChange type = StatusChange(conv_num(st, &(st->stack->stack_data[st->start + 2]))); bl = map_id2bl(st->rid); - if (bl->type == BL_PC - && ((struct map_session_data *) bl)->state.potionpitcher_flag) - bl = map_id2bl(((struct map_session_data *) bl)->skilltarget); skill_status_change_end(bl, type, -1); // if(battle_config.etc_log) // PRINTF("sc_end : %d %d\n",st->rid,type); @@ -3262,9 +3256,6 @@ void builtin_sc_check(ScriptState *st) struct block_list *bl; StatusChange type = StatusChange(conv_num(st, &(st->stack->stack_data[st->start + 2]))); bl = map_id2bl(st->rid); - if (bl->type == BL_PC - && ((struct map_session_data *) bl)->state.potionpitcher_flag) - bl = map_id2bl(((struct map_session_data *) bl)->skilltarget); push_val(st->stack, ScriptCode::INT, skill_status_change_active(bl, type)); diff --git a/src/map/skill.cpp b/src/map/skill.cpp index aac7e1f..a93f375 100644 --- a/src/map/skill.cpp +++ b/src/map/skill.cpp @@ -18,478 +18,6 @@ #include "../poison.hpp" -#define SKILLUNITTIMER_INVERVAL 100 - -// This table is wrong. -// The only used skill with a status effect is NPC_SELFDESTRUCT, -// and due to the misnumber, it wasn't active anyway. -static __attribute__((deprecated)) -earray SkillStatusChangeTable //= -{{ - // 0- - StatusChange::NEGATIVE1, // (none) - StatusChange::NEGATIVE1, // NV_BASIC - StatusChange::NEGATIVE1, // SM_SWORD - StatusChange::NEGATIVE1, // SM_TWOHAND - StatusChange::NEGATIVE1, // SM_RECOVERY - StatusChange::NEGATIVE1, // SM_BASH - StatusChange::NEGATIVE1, // SM_PROVOKE - StatusChange::NEGATIVE1, // SM_MAGNUM - StatusChange::NEGATIVE1, // SM_ENDURE - StatusChange::NEGATIVE1, // MG_SRECOVERY - // 10- - StatusChange::NEGATIVE1, // MG_SIGHT - StatusChange::NEGATIVE1, // MG_NAPALMBEAT - StatusChange::NEGATIVE1, // MG_SAFETYWALL - StatusChange::NEGATIVE1, // MG_SOULSTRIKE - StatusChange::NEGATIVE1, // MG_COLDBOLT - StatusChange::NEGATIVE1, // MG_FROSTDIVER - StatusChange::NEGATIVE1, // MG_STONECURSE - StatusChange::NEGATIVE1, // MG_FIREBALL - StatusChange::NEGATIVE1, // MG_FIREWALL - StatusChange::NEGATIVE1, // MG_FIREBOLT - // 20- - StatusChange::NEGATIVE1, // MG_LIGHTNINGBOLT - StatusChange::NEGATIVE1, // MG_THUNDERSTORM - StatusChange::NEGATIVE1, // AL_DP - StatusChange::NEGATIVE1, // AL_DEMONBANE - StatusChange::NEGATIVE1, // AL_RUWACH - StatusChange::NEGATIVE1, // AL_PNEUMA - StatusChange::NEGATIVE1, // AL_TELEPORT - StatusChange::NEGATIVE1, // AL_WARP - StatusChange::NEGATIVE1, // AL_HEAL - StatusChange::NEGATIVE1, // AL_INCAGI - // 30- - StatusChange::NEGATIVE1, // AL_DECAGI - StatusChange::NEGATIVE1, // AL_HOLYWATER - StatusChange::NEGATIVE1, // AL_CRUCIS - StatusChange::NEGATIVE1, // AL_ANGELUS - StatusChange::NEGATIVE1, // AL_BLESSING - StatusChange::NEGATIVE1, // AL_CURE - StatusChange::NEGATIVE1, // MC_INCCARRY - StatusChange::NEGATIVE1, // MC_DISCOUNT - StatusChange::NEGATIVE1, // MC_OVERCHARGE - StatusChange::NEGATIVE1, // MC_PUSHCART - // 40- - StatusChange::NEGATIVE1, // MC_IDENTIFY - StatusChange::NEGATIVE1, // MC_VENDING - StatusChange::NEGATIVE1, // MC_MAMMONITE - StatusChange::NEGATIVE1, // AC_OWL - StatusChange::NEGATIVE1, // AC_VULTURE - StatusChange::NEGATIVE1, // AC_CONCENTRATION - StatusChange::NEGATIVE1, // AC_DOUBLE - StatusChange::NEGATIVE1, // AC_SHOWER - StatusChange::NEGATIVE1, // TF_DOUBLE - StatusChange::NEGATIVE1, // TF_MISS - // 50- - StatusChange::NEGATIVE1, // TF_STEAL - StatusChange::NEGATIVE1, // TF_HIDING - StatusChange::NEGATIVE1, // TF_POISON - StatusChange::NEGATIVE1, // TF_DETOXIFY - StatusChange::NEGATIVE1, // ALL_RESURRECTION - StatusChange::NEGATIVE1, // KN_SPEARMASTERY - StatusChange::NEGATIVE1, // KN_PIERCE - StatusChange::NEGATIVE1, // KN_BRANDISHSPEAR - StatusChange::NEGATIVE1, // KN_SPEARSTAB - StatusChange::NEGATIVE1, // KN_SPEARBOOMERANG - // 60- - StatusChange::NEGATIVE1, // KN_TWOHANDQUICKEN - StatusChange::NEGATIVE1, // KN_AUTOCOUNTER - StatusChange::NEGATIVE1, // KN_BOWLINGBASH - StatusChange::NEGATIVE1, // KN_RIDING - StatusChange::NEGATIVE1, // KN_CAVALIERMASTERY - StatusChange::NEGATIVE1, // PR_MACEMASTERY - StatusChange::NEGATIVE1, // PR_IMPOSITIO - StatusChange::NEGATIVE1, // PR_SUFFRAGIUM - StatusChange::NEGATIVE1, // PR_ASPERSIO - StatusChange::NEGATIVE1, // PR_BENEDICTIO - // 70- - StatusChange::NEGATIVE1, // PR_SANCTUARY - StatusChange::NEGATIVE1, // PR_SLOWPOISON - StatusChange::NEGATIVE1, // PR_STRECOVERY - StatusChange::NEGATIVE1, // PR_KYRIE - StatusChange::NEGATIVE1, // PR_MAGNIFICAT - StatusChange::NEGATIVE1, // PR_GLORIA - StatusChange::NEGATIVE1, // PR_LEXDIVINA - StatusChange::NEGATIVE1, // PR_TURNUNDEAD - StatusChange::NEGATIVE1, // PR_LEXAETERNA - StatusChange::NEGATIVE1, // PR_MAGNUS - // 80- - StatusChange::NEGATIVE1, // WZ_FIREPILLAR - StatusChange::NEGATIVE1, // WZ_SIGHTRASHER - StatusChange::NEGATIVE1, // WZ_FIREIVY - StatusChange::NEGATIVE1, // WZ_METEOR - StatusChange::NEGATIVE1, // WZ_JUPITEL - StatusChange::NEGATIVE1, // WZ_VERMILION - StatusChange::NEGATIVE1, // WZ_WATERBALL - StatusChange::NEGATIVE1, // WZ_ICEWALL - StatusChange::NEGATIVE1, // WZ_FROSTNOVA - StatusChange::NEGATIVE1, // WZ_STORMGUST - // 90- - StatusChange::NEGATIVE1, // WZ_EARTHSPIKE - StatusChange::NEGATIVE1, // WZ_HEAVENDRIVE - StatusChange::NEGATIVE1, // WZ_QUAGMIRE - StatusChange::NEGATIVE1, // WZ_ESTIMATION - StatusChange::NEGATIVE1, // BS_IRON - StatusChange::NEGATIVE1, // BS_STEEL - StatusChange::NEGATIVE1, // BS_ENCHANTEDSTONE - StatusChange::NEGATIVE1, // BS_ORIDEOCON - StatusChange::NEGATIVE1, // BS_DAGGER - StatusChange::NEGATIVE1, // BS_SWORD - // 100- - StatusChange::NEGATIVE1, // BS_TWOHANDSWORD - StatusChange::NEGATIVE1, // BS_AXE - StatusChange::NEGATIVE1, // BS_MACE - StatusChange::NEGATIVE1, // BS_KNUCKLE - StatusChange::NEGATIVE1, // BS_SPEAR - StatusChange::NEGATIVE1, // BS_HILTBINDING - StatusChange::NEGATIVE1, // BS_FINDINGORE - StatusChange::NEGATIVE1, // BS_WEAPONRESEARCH - StatusChange::NEGATIVE1, // BS_REPAIRWEAPON - StatusChange::NEGATIVE1, // BS_SKINTEMPER - // 110- - StatusChange::NEGATIVE1, // BS_HAMMERFALL - StatusChange::NEGATIVE1, // BS_ADRENALINE - StatusChange::NEGATIVE1, // BS_WEAPONPERFECT - StatusChange::NEGATIVE1, // BS_OVERTHRUST - StatusChange::NEGATIVE1, // BS_MAXIMIZE - StatusChange::NEGATIVE1, // HT_SKIDTRAP - StatusChange::NEGATIVE1, // HT_LANDMINE - StatusChange::NEGATIVE1, // HT_ANKLESNARE - StatusChange::NEGATIVE1, // HT_SHOCKWAVE - StatusChange::NEGATIVE1, // HT_SANDMAN - // 120- - StatusChange::NEGATIVE1, // HT_FLASHER - StatusChange::NEGATIVE1, // HT_FREEZINGTRAP - StatusChange::NEGATIVE1, // HT_BLASTMINE - StatusChange::NEGATIVE1, // HT_CLAYMORETRAP - StatusChange::NEGATIVE1, // HT_REMOVETRAP - StatusChange::NEGATIVE1, // HT_TALKIEBOX - StatusChange::NEGATIVE1, // HT_BEASTBANE - StatusChange::NEGATIVE1, // HT_FALCON - StatusChange::NEGATIVE1, // HT_STEELCROW - StatusChange::NEGATIVE1, // HT_BLITZBEAT - // 130- - StatusChange::NEGATIVE1, // HT_DETECTING - StatusChange::NEGATIVE1, // HT_SPRINGTRAP - StatusChange::NEGATIVE1, // AS_RIGHT - StatusChange::NEGATIVE1, // AS_LEFT - StatusChange::NEGATIVE1, // AS_KATAR - StatusChange::NEGATIVE1, // AS_CLOAKING - StatusChange::NEGATIVE1, // AS_SONICBLOW - StatusChange::NEGATIVE1, // AS_GRIMTOOTH - StatusChange::NEGATIVE1, // AS_ENCHANTPOISON - StatusChange::NEGATIVE1, // AS_POISONREACT - // 140- - StatusChange::NEGATIVE1, // AS_VENOMDUST - StatusChange::NEGATIVE1, // AS_SPLASHER - StatusChange::NEGATIVE1, // NV_FIRSTAID - StatusChange::NEGATIVE1, // NV_TRICKDEAD - StatusChange::NEGATIVE1, // SM_MOVINGRECOVERY - StatusChange::NEGATIVE1, // SM_FATALBLOW - StatusChange::NEGATIVE1, // SM_AUTOBERSERK - StatusChange::NEGATIVE1, // AC_MAKINGARROW - StatusChange::NEGATIVE1, // AC_CHARGEARROW - StatusChange::NEGATIVE1, // TF_SPRINKLESAND - // 150- - StatusChange::NEGATIVE1, // TF_BACKSLIDING - StatusChange::NEGATIVE1, // TF_PICKSTONE - StatusChange::NEGATIVE1, // TF_THROWSTONE - StatusChange::NEGATIVE1, // MC_CARTREVOLUTION - StatusChange::NEGATIVE1, // MC_CHANGECART - StatusChange::NEGATIVE1, // MC_LOUD - StatusChange::NEGATIVE1, // AL_HOLYLIGHT - StatusChange::NEGATIVE1, // MG_ENERGYCOAT - StatusChange::NEGATIVE1, // NPC_PIERCINGATT - StatusChange::NEGATIVE1, // NPC_MENTALBREAKER - // 160- - StatusChange::NEGATIVE1, // NPC_RANGEATTACK - StatusChange::NEGATIVE1, // NPC_ATTRICHANGE - StatusChange::NEGATIVE1, // NPC_CHANGEWATER - StatusChange::NEGATIVE1, // NPC_CHANGEGROUND - StatusChange::NEGATIVE1, // NPC_CHANGEFIRE - StatusChange::NEGATIVE1, // NPC_CHANGEWIND - StatusChange::NEGATIVE1, // NPC_CHANGEPOISON - StatusChange::NEGATIVE1, // NPC_CHANGEHOLY - StatusChange::NEGATIVE1, // NPC_CHANGEDARKNESS - StatusChange::NEGATIVE1, // NPC_CHANGETELEKINESIS - // 170- - StatusChange::NEGATIVE1, // NPC_CRITICALSLASH - StatusChange::NEGATIVE1, // NPC_COMBOATTACK - StatusChange::NEGATIVE1, // NPC_GUIDEDATTACK - SC_SELFDESTRUCTION, // NPC_SELFDESTRUCTION - StatusChange::NEGATIVE1, // NPC_SPLASHATTACK - StatusChange::NEGATIVE1, // NPC_SUICIDE - StatusChange::NEGATIVE1, // NPC_POISON - StatusChange::NEGATIVE1, // NPC_BLINDATTACK - StatusChange::NEGATIVE1, // NPC_SILENCEATTACK - StatusChange::NEGATIVE1, // NPC_STUNATTACK - // 180- - StatusChange::NEGATIVE1, // NPC_PETRIFYATTACK - StatusChange::NEGATIVE1, // NPC_CURSEATTACK - StatusChange::NEGATIVE1, // NPC_SLEEPATTACK - StatusChange::NEGATIVE1, // NPC_RANDOMATTACK - StatusChange::NEGATIVE1, // NPC_WATERATTACK - StatusChange::NEGATIVE1, // NPC_GROUNDATTACK - StatusChange::NEGATIVE1, // NPC_FIREATTACK - StatusChange::NEGATIVE1, // NPC_WINDATTACK - StatusChange::NEGATIVE1, // NPC_POISONATTACK - StatusChange::NEGATIVE1, // NPC_HOLYATTACK - // 190- - StatusChange::NEGATIVE1, // NPC_DARKNESSATTACK - StatusChange::NEGATIVE1, // NPC_TELEKINESISATTACK - StatusChange::NEGATIVE1, // NPC_MAGICALATTACK - StatusChange::NEGATIVE1, // NPC_METAMORPHOSIS - StatusChange::NEGATIVE1, // NPC_PROVOCATION - StatusChange::NEGATIVE1, // NPC_SMOKING - StatusChange::NEGATIVE1, // NPC_SUMMONSLAVE - StatusChange::NEGATIVE1, // NPC_EMOTION - StatusChange::NEGATIVE1, // NPC_TRANSFORMATION - StatusChange::NEGATIVE1, // NPC_BLOODDRAIN - // 200- - StatusChange::NEGATIVE1, // NPC_ENERGYDRAIN - StatusChange::NEGATIVE1, // NPC_KEEPING - StatusChange::NEGATIVE1, // NPC_DARKBREATH - StatusChange::NEGATIVE1, // NPC_DARKBLESSING - StatusChange::NEGATIVE1, // NPC_BARRIER - StatusChange::NEGATIVE1, // NPC_DEFENDER - StatusChange::NEGATIVE1, // NPC_LICK - StatusChange::NEGATIVE1, // NPC_HALLUCINATION - StatusChange::NEGATIVE1, // NPC_REBIRTH - StatusChange::NEGATIVE1, // NPC_SUMMONMONSTER - // 210- - StatusChange::NEGATIVE1, // RG_SNATCHER - StatusChange::NEGATIVE1, // RG_STEALCOIN - StatusChange::NEGATIVE1, // RG_BACKSTAP - StatusChange::NEGATIVE1, // RG_TUNNELDRIVE - StatusChange::NEGATIVE1, // RG_RAID - StatusChange::NEGATIVE1, // RG_STRIPWEAPON - StatusChange::NEGATIVE1, // RG_STRIPSHIELD - StatusChange::NEGATIVE1, // RG_STRIPARMOR - StatusChange::NEGATIVE1, // RG_STRIPHELM - StatusChange::NEGATIVE1, // RG_INTIMIDATE - // 220- - StatusChange::NEGATIVE1, // RG_GRAFFITI - StatusChange::NEGATIVE1, // RG_FLAGGRAFFITI - StatusChange::NEGATIVE1, // RG_CLEANER - StatusChange::NEGATIVE1, // RG_GANGSTER - StatusChange::NEGATIVE1, // RG_COMPULSION - StatusChange::NEGATIVE1, // RG_PLAGIARISM - StatusChange::NEGATIVE1, // AM_AXEMASTERY - StatusChange::NEGATIVE1, // AM_LEARNINGPOTION - StatusChange::NEGATIVE1, // AM_PHARMACY - StatusChange::NEGATIVE1, // AM_DEMONSTRATION - // 230- - StatusChange::NEGATIVE1, // AM_ACIDTERROR - StatusChange::NEGATIVE1, // AM_POTIONPITCHER - StatusChange::NEGATIVE1, // AM_CANNIBALIZE - StatusChange::NEGATIVE1, // AM_SPHEREMINE - StatusChange::NEGATIVE1, // AM_CP_WEAPON - StatusChange::NEGATIVE1, // AM_CP_SHIELD - StatusChange::NEGATIVE1, // AM_CP_ARMOR - StatusChange::NEGATIVE1, // AM_CP_HELM - StatusChange::NEGATIVE1, // AM_BIOETHICS - StatusChange::NEGATIVE1, // AM_BIOTECHNOLOGY - // 240- - StatusChange::NEGATIVE1, // AM_CREATECREATURE - StatusChange::NEGATIVE1, // AM_CULTIVATION - StatusChange::NEGATIVE1, // AM_FLAMECONTROL - StatusChange::NEGATIVE1, // AM_CALLHOMUN - StatusChange::NEGATIVE1, // AM_REST - StatusChange::NEGATIVE1, // AM_DRILLMASTER - StatusChange::NEGATIVE1, // AM_HEALHOMUN - StatusChange::NEGATIVE1, // AM_RESURRECTHOMUN - StatusChange::NEGATIVE1, // CR_TRUST - StatusChange::NEGATIVE1, // CR_AUTOGUARD - // 250- - StatusChange::NEGATIVE1, // CR_SHIELDCHARGE - StatusChange::NEGATIVE1, // CR_SHIELDBOOMERANG - StatusChange::NEGATIVE1, // CR_REFLECTSHIELD - StatusChange::NEGATIVE1, // CR_HOLYCROSS - StatusChange::NEGATIVE1, // CR_GRANDCROSS - StatusChange::NEGATIVE1, // CR_DEVOTION - StatusChange::NEGATIVE1, // CR_PROVIDENCE - StatusChange::NEGATIVE1, // CR_DEFENDER - StatusChange::NEGATIVE1, // CR_SPEARQUICKEN - StatusChange::NEGATIVE1, // MO_IRONHAND - // 260- - StatusChange::NEGATIVE1, // MO_SPIRITSRECOVERY - StatusChange::NEGATIVE1, // MO_CALLSPIRITS - StatusChange::NEGATIVE1, // MO_ABSORBSPIRITS - StatusChange::NEGATIVE1, // MO_TRIPLEATTACK - StatusChange::NEGATIVE1, // MO_BODYRELOCATION - StatusChange::NEGATIVE1, // MO_DODGE - StatusChange::NEGATIVE1, // MO_INVESTIGATE - StatusChange::NEGATIVE1, // MO_FINGEROFFENSIVE - StatusChange::NEGATIVE1, // MO_STEELBODY - StatusChange::NEGATIVE1, // MO_BLADESTOP - // 270- - StatusChange::NEGATIVE1, // MO_EXPLOSIONSPIRITS - StatusChange::NEGATIVE1, // MO_EXTREMITYFIST - StatusChange::NEGATIVE1, // MO_CHAINCOMBO - StatusChange::NEGATIVE1, // MO_COMBOFINISH - StatusChange::NEGATIVE1, // SA_ADVANCEDBOOK - StatusChange::NEGATIVE1, // SA_CASTCANCEL - StatusChange::NEGATIVE1, // SA_MAGICROD - StatusChange::NEGATIVE1, // SA_SPELLBREAKER - StatusChange::NEGATIVE1, // SA_FREECAST - StatusChange::NEGATIVE1, // SA_AUTOSPELL - // 280- - StatusChange::NEGATIVE1, // SA_FLAMELAUNCHER - StatusChange::NEGATIVE1, // SA_FROSTWEAPON - StatusChange::NEGATIVE1, // SA_LIGHTNINGLOADER - StatusChange::NEGATIVE1, // SA_SEISMICWEAPON - StatusChange::NEGATIVE1, // SA_DRAGONOLOGY - StatusChange::NEGATIVE1, // SA_VOLCANO - StatusChange::NEGATIVE1, // SA_DELUGE - StatusChange::NEGATIVE1, // SA_VIOLENTGALE - StatusChange::NEGATIVE1, // SA_LANDPROTECTOR - StatusChange::NEGATIVE1, // SA_DISPELL - // 290- - StatusChange::NEGATIVE1, // SA_ABRACADABRA - StatusChange::NEGATIVE1, // SA_MONOCELL - StatusChange::NEGATIVE1, // SA_CLASSCHANGE - StatusChange::NEGATIVE1, // SA_SUMMONMONSTER - StatusChange::NEGATIVE1, // SA_REVERSEORCISH - StatusChange::NEGATIVE1, // SA_DEATH - StatusChange::NEGATIVE1, // SA_FORTUNE - StatusChange::NEGATIVE1, // SA_TAMINGMONSTER - StatusChange::NEGATIVE1, // SA_QUESTION - StatusChange::NEGATIVE1, // SA_GRAVITY - // 300- - StatusChange::NEGATIVE1, // SA_LEVELUP - StatusChange::NEGATIVE1, // SA_INSTANTDEATH - StatusChange::NEGATIVE1, // SA_FULLRECOVERY - StatusChange::NEGATIVE1, // SA_COMA - StatusChange::NEGATIVE1, // BD_ADAPTATION - StatusChange::NEGATIVE1, // BD_ENCORE - StatusChange::NEGATIVE1, // BD_LULLABY - StatusChange::NEGATIVE1, // BD_RICHMANKIM - StatusChange::NEGATIVE1, // BD_ETERNALCHAOS - StatusChange::NEGATIVE1, // BD_DRUMBATTLEFIELD - // 310- - StatusChange::NEGATIVE1, // BD_RINGNIBELUNGEN - StatusChange::NEGATIVE1, // BD_ROKISWEIL - StatusChange::NEGATIVE1, // BD_INTOABYSS - StatusChange::NEGATIVE1, // BD_SIEGFRIED - StatusChange::NEGATIVE1, // BD_RAGNAROK - StatusChange::NEGATIVE1, // BA_MUSICALLESSON - StatusChange::NEGATIVE1, // BA_MUSICALSTRIKE - StatusChange::NEGATIVE1, // BA_DISSONANCE - StatusChange::NEGATIVE1, // BA_FROSTJOKE - StatusChange::NEGATIVE1, // BA_WHISTLE - // 320- - StatusChange::NEGATIVE1, // BA_ASSASSINCROSS - StatusChange::NEGATIVE1, // BA_POEMBRAGI - StatusChange::NEGATIVE1, // BA_APPLEIDUN - StatusChange::NEGATIVE1, // DC_DANCINGLESSON - StatusChange::NEGATIVE1, // DC_THROWARROW - StatusChange::NEGATIVE1, // DC_UGLYDANCE - StatusChange::NEGATIVE1, // DC_SCREAM - StatusChange::NEGATIVE1, // DC_HUMMING - StatusChange::NEGATIVE1, // DC_DONTFORGETME - StatusChange::NEGATIVE1, // DC_FORTUNEKISS - // 330- - StatusChange::NEGATIVE1, // DC_SERVICEFORYOU - StatusChange::NEGATIVE1, // NPC_SELFDESTRUCTION2 - StatusChange::NEGATIVE1, // (none) - StatusChange::NEGATIVE1, // (none) - StatusChange::NEGATIVE1, // WE_MALE - StatusChange::NEGATIVE1, // WE_FEMALE - StatusChange::NEGATIVE1, // WE_CALLPARTNER - StatusChange::NEGATIVE1, // (none) - StatusChange::NEGATIVE1, // NPC_DARKCROSS - StatusChange::NEGATIVE1, // (none) - // 340- - StatusChange::NEGATIVE1, // (none) - StatusChange::NEGATIVE1, // (none) - StatusChange::NEGATIVE1, // (none) - StatusChange::NEGATIVE1, // (none) - StatusChange::NEGATIVE1, // (none) - StatusChange::NEGATIVE1, // (none) - StatusChange::NEGATIVE1, // (none) - StatusChange::NEGATIVE1, // (none) - StatusChange::NEGATIVE1, // (none) - StatusChange::NEGATIVE1, // (none) - // 350- - StatusChange::NEGATIVE1, // (none) - StatusChange::NEGATIVE1, // (none) - StatusChange::NEGATIVE1, // (none) - StatusChange::NEGATIVE1, // (none) - StatusChange::NEGATIVE1, // (none) - StatusChange::NEGATIVE1, // LK_AURABLADE - StatusChange::NEGATIVE1, // LK_PARRYING - StatusChange::NEGATIVE1, // LK_CONCENTRATION - StatusChange::NEGATIVE1, // LK_TENSIONRELAX - StatusChange::NEGATIVE1, // LK_BERSERK - // 360- - StatusChange::NEGATIVE1, // LK_FURY - StatusChange::NEGATIVE1, // HP_ASSUMPTIO - StatusChange::NEGATIVE1, // HP_BASILICA - StatusChange::NEGATIVE1, // HP_MEDITATIO - StatusChange::NEGATIVE1, // HW_SOULDRAIN - StatusChange::NEGATIVE1, // HW_MAGICCRASHER - StatusChange::NEGATIVE1, // HW_MAGICPOWER - StatusChange::NEGATIVE1, // PA_PRESSURE - StatusChange::NEGATIVE1, // PA_SACRIFICE - StatusChange::NEGATIVE1, // PA_GOSPEL - // 370- - StatusChange::NEGATIVE1, // CH_PALMSTRIKE - StatusChange::NEGATIVE1, // CH_TIGERFIST - StatusChange::NEGATIVE1, // CH_CHAINCRUSH - StatusChange::NEGATIVE1, // PF_HPCONVERSION - StatusChange::NEGATIVE1, // PF_SOULCHANGE - StatusChange::NEGATIVE1, // PF_SOULBURN - StatusChange::NEGATIVE1, // ASC_KATAR - StatusChange::NEGATIVE1, // ASC_HALLUCINATION - StatusChange::NEGATIVE1, // ASC_EDP - StatusChange::NEGATIVE1, // ASC_BREAKER - // 380- - StatusChange::NEGATIVE1, // SN_SIGHT - StatusChange::NEGATIVE1, // SN_FALCONASSAULT - StatusChange::NEGATIVE1, // SN_SHARPSHOOTING - StatusChange::NEGATIVE1, // SN_WINDWALK - StatusChange::NEGATIVE1, // WS_MELTDOWN - StatusChange::NEGATIVE1, // WS_CREATECOIN - StatusChange::NEGATIVE1, // WS_CREATENUGGET - StatusChange::NEGATIVE1, // WS_CARTBOOST - StatusChange::NEGATIVE1, // WS_SYSTEMCREATE - StatusChange::NEGATIVE1, // ST_CHASEWALK - // 390- - StatusChange::NEGATIVE1, // ST_REJECTSWORD - StatusChange::NEGATIVE1, // ST_STEALBACKPACK - StatusChange::NEGATIVE1, // CR_ALCHEMY - StatusChange::NEGATIVE1, // CR_SYNTHESISPOTION - StatusChange::NEGATIVE1, // CG_ARROWVULCAN - StatusChange::NEGATIVE1, // CG_MOONLIT - StatusChange::NEGATIVE1, // CG_MARIONETTE - StatusChange::NEGATIVE1, // LK_SPIRALPIERCE - StatusChange::NEGATIVE1, // LK_HEADCRUSH - StatusChange::NEGATIVE1, // LK_JOINTBEAT - // 400- - StatusChange::NEGATIVE1, // HW_NAPALMVULCAN - StatusChange::NEGATIVE1, // CH_SOULCOLLECT - StatusChange::NEGATIVE1, // PF_MINDBREAKER - StatusChange::NEGATIVE1, // PF_MEMORIZE - StatusChange::NEGATIVE1, // PF_FOGWALL - StatusChange::NEGATIVE1, // PF_SPIDERWEB - StatusChange::NEGATIVE1, // ASC_METEORASSAULT - StatusChange::NEGATIVE1, // ASC_CDP - StatusChange::NEGATIVE1, // WE_BABY - StatusChange::NEGATIVE1, // WE_CALLPARENT - // 410- - StatusChange::NEGATIVE1, // WE_CALLBABY - StatusChange::NEGATIVE1, // TK_RUN - StatusChange::NEGATIVE1, // TK_READYSTORM - StatusChange::NEGATIVE1, // TK_STORMKICK - StatusChange::NEGATIVE1, // TK_READYDOWN - StatusChange::NEGATIVE1, // TK_DOWNKICK - StatusChange::NEGATIVE1, // TK_READYTURN - StatusChange::NEGATIVE1, // TK_TURNKICK - StatusChange::NEGATIVE1, // TK_READYCOUNTER - StatusChange::NEGATIVE1, // TK_COUNTER -}}; - struct skill_name_db skill_names[] = { {AC_OWL, "OWL", "Owl's_Eye"}, @@ -522,14 +50,6 @@ struct skill_name_db skill_names[] = {SkillID::ZERO, nullptr, nullptr} }; -static -const int dirx[8] = { 0, -1, -1, -1, 0, 1, 1, 1 }; -static -const int diry[8] = { 1, 1, 0, -1, -1, -1, 0, 1 }; - -static -int rdamage; - earray skill_db; @@ -538,25 +58,11 @@ int skill_attack(BF attack_type, struct block_list *src, struct block_list *dsrc, struct block_list *bl, SkillID skillid, int skilllv, unsigned int tick, BCT flag); static -int skill_delunitgroup(struct skill_unit_group *group); -static void skill_devotion_end(struct map_session_data *md, struct map_session_data *sd, int target); static -struct skill_unit *skill_initunit(struct skill_unit_group *group, int idx, - int x, int y); -static -struct skill_unit_group *skill_initunitgroup(struct block_list *src, - int count, SkillID skillid, int skilllv, int unit_id); -static void skill_status_change_timer(timer_id tid, tick_t tick, custom_id_t id, custom_data_t data); -static -int skill_unitgrouptickset_delete(struct block_list *bl, int group_id); -static -struct skill_unit_group_tickset *skill_unitgrouptickset_search( - struct block_list *bl, int group_id); - int skill_get_hit(SkillID id) { @@ -568,11 +74,6 @@ int skill_get_inf(SkillID id) return skill_db[id].inf; } -int skill_get_pl(SkillID id) -{ - return skill_db[id].pl; -} - int skill_get_nk(SkillID id) { return skill_db[id].nk; @@ -593,23 +94,11 @@ int skill_get_range(SkillID id, int lv) return (lv <= 0) ? 0 : skill_db[id].range[lv - 1]; } -static -int skill_get_hp(SkillID id, int lv) -{ - return (lv <= 0) ? 0 : skill_db[id].hp[lv - 1]; -} - int skill_get_sp(SkillID id, int lv) { return (lv <= 0) ? 0 : skill_db[id].sp[lv - 1]; } -static -int skill_get_zeny(SkillID id, int lv) -{ - return (lv <= 0) ? 0 : skill_db[id].zeny[lv - 1]; -} - int skill_get_num(SkillID id, int lv) { return (lv <= 0) ? 0 : skill_db[id].num[lv - 1]; @@ -625,26 +114,6 @@ int skill_get_delay(SkillID id, int lv) return (lv <= 0) ? 0 : skill_db[id].delay[lv - 1]; } -int skill_get_time(SkillID id, int lv) -{ - return (lv <= 0) ? 0 : skill_db[id].upkeep_time[lv - 1]; -} - -int skill_get_time2(SkillID id, int lv) -{ - return (lv <= 0) ? 0 : skill_db[id].upkeep_time2[lv - 1]; -} - -int skill_get_castdef(SkillID id) -{ - return skill_db[id].cast_def_rate; -} - -int skill_get_weapontype(SkillID id) -{ - return skill_db[id].weapon; -} - int skill_get_inf2(SkillID id) { return skill_db[id].inf2; @@ -655,42 +124,12 @@ int skill_get_maxcount(SkillID id) return skill_db[id].maxcount; } -int skill_get_blewcount(SkillID id, int lv) -{ - return (lv <= 0) ? 0 : skill_db[id].blewcount[lv - 1]; -} - -static -int skill_get_mhp(SkillID id, int lv) -{ - return (lv <= 0) ? 0 : skill_db[id].mhp[lv - 1]; -} - static int skill_get_castnodex(SkillID id, int lv) { return (lv <= 0) ? 0 : skill_db[id].castnodex[lv - 1]; } -/* プロトタイプ */ -static -struct skill_unit_group *skill_unitsetting(struct block_list *src, - SkillID skillid, int skilllv, - int x, int y, int flag); -static -int skill_check_condition(struct map_session_data *sd, int type); -static -void skill_status_change_timer_sub(struct block_list *bl, - struct block_list *src, StatusChange type, unsigned int tick); -static -void skill_landprotector(struct block_list *bl, SkillID skillid, int *alive); -static -void skill_trap_splash(struct block_list *bl, - struct block_list *src, int tick, int splash_count); -static -void skill_count_target(struct block_list *bl, - struct block_list *src, int *c); - static int distance(int x0, int y0, int x1, int y1) { @@ -706,7 +145,7 @@ int distance(int x0, int y0, int x1, int y1) *------------------------------------------ */ int skill_additional_effect(struct block_list *src, struct block_list *bl, - SkillID skillid, int skilllv, BF attack_type, + SkillID skillid, int skilllv, BF, unsigned int) { struct map_session_data *sd = NULL; @@ -715,7 +154,6 @@ int skill_additional_effect(struct block_list *src, struct block_list *bl, int luk; int sc_def_mdef, sc_def_vit, sc_def_int, sc_def_luk; - int sc_def_mdef2, sc_def_vit2, sc_def_int2, sc_def_luk2; int sc_def_phys_shield_spell; nullpo_ret(src); @@ -726,11 +164,13 @@ int skill_additional_effect(struct block_list *src, struct block_list *bl, if (src->type == BL_PC) { - nullpo_ret(sd = (struct map_session_data *) src); + sd = (struct map_session_data *) src; + nullpo_ret(sd); } else if (src->type == BL_MOB) { - nullpo_ret(md = (struct mob_data *) src); //未使用? + md = (struct mob_data *) src; + nullpo_ret(md); //未使用? } sc_def_phys_shield_spell = 0; @@ -746,10 +186,7 @@ int skill_additional_effect(struct block_list *src, struct block_list *bl, sc_def_luk = 100 - (3 + luk); //自分の耐性 luk = battle_get_luk(src); - sc_def_mdef2 = 100 - (3 + battle_get_mdef(src) + luk / 3); - sc_def_vit2 = 100 - (3 + battle_get_vit(src) + luk / 3); - sc_def_int2 = 100 - (3 + battle_get_int(src) + luk / 3); - sc_def_luk2 = 100 - (3 + luk); + if (bl->type == BL_MOB) { if (sc_def_mdef > 50) @@ -779,206 +216,6 @@ int skill_additional_effect(struct block_list *src, struct block_list *bl, break; } - if (not (sd && bool(attack_type & BF_WEAPON))) - return 0; - earray arr_sc_def_card1 //= - {{ - sc_def_mdef, // stone - sc_def_mdef, // freeze - sc_def_vit, // stan - sc_def_int, // sleep - sc_def_vit, // poison - sc_def_luk, // curse - sc_def_vit, // silence - sc_def_int, // confusion - sc_def_int, // blind - }}, arr_sc_def_card2 //= - {{ - sc_def_mdef2, // stone - sc_def_mdef2, // freeze - sc_def_vit2, // stan - sc_def_int2, // sleep - sc_def_vit2, // poison - sc_def_luk2, // curse - sc_def_vit2, // silence - sc_def_int2, // confusion - sc_def_int2, // blind - }}; - - for (BadSC bi : erange(BadSC(), BadSC::COUNT)) - { - StatusChange si = BadSC_to_SC(bi); - int sc_def_card1 = arr_sc_def_card1[bi]; - int eff1 = sd->addeff[bi]; - if (sd->state.arrow_atk) - eff1 += sd->arrow_addeff[bi]; - if (MRAND(10000) < eff1 * sc_def_card1 / 100) - { - if (battle_config.battle_log) - PRINTF("PC %d skill_addeff: cardによる異常発動 %d %d\n", - sd->bl.id, si, eff1); - - skill_status_change_start(bl, si, 7, 0, 0, 0, - (bi == BadSC::CONFUSION) - ? 10000 + 7000 - : 0, - 0); - } - - int sc_def_card2 = arr_sc_def_card2[bi]; - int eff2 = sd->addeff2[bi]; - - if (MRAND(10000) < eff2 * sc_def_card2 / 100) - { - if (battle_config.battle_log) - PRINTF("PC %d skill_addeff: cardによる異常発動 %d %d\n", - src->id, si, eff2); - skill_status_change_start(src, si, 7, 0, 0, 0, - (bi == BadSC::CONFUSION) - ? 10000 + 7000 - : 0, - 0); - } - } - return 0; -} - -/*========================================================================= - スキル攻撃吹き飛ばし処理 --------------------------------------------------------------------------*/ -static -int skill_blown(struct block_list *src, struct block_list *target, int count) -{ - int dx = 0, dy = 0, nx, ny; - int x = target->x, y = target->y; - int ret; - MS prev_state = MS_IDLE; - int moveblock; - struct map_session_data *sd = NULL; - struct mob_data *md = NULL; - struct skill_unit *su = NULL; - - nullpo_ret(src); - nullpo_ret(target); - - if (target->type == BL_PC) - { - nullpo_ret(sd = (struct map_session_data *) target); - } - else if (target->type == BL_MOB) - { - nullpo_ret(md = (struct mob_data *) target); - } - else if (target->type == BL_SKILL) - { - nullpo_ret(su = (struct skill_unit *) target); - } - else - return 0; - - if (!(count & 0x10000 && (sd || md || su))) - { /* 指定なしなら位置関係から方向を求める */ - dx = target->x - src->x; - dx = (dx > 0) ? 1 : ((dx < 0) ? -1 : 0); - dy = target->y - src->y; - dy = (dy > 0) ? 1 : ((dy < 0) ? -1 : 0); - } - if (dx == 0 && dy == 0) - { - int dir = battle_get_dir(target); - if (dir >= 0 && dir < 8) - { - dx = -dirx[dir]; - dy = -diry[dir]; - } - } - - ret = path_blownpos(target->m, x, y, dx, dy, count & 0xffff); - nx = ret >> 16; - ny = ret & 0xffff; - moveblock = (x / BLOCK_SIZE != nx / BLOCK_SIZE - || y / BLOCK_SIZE != ny / BLOCK_SIZE); - - if (count & 0x20000) - { - battle_stopwalking(target, 1); - if (sd) - { - sd->to_x = nx; - sd->to_y = ny; - sd->walktimer = 1; - clif_walkok(sd); - clif_movechar(sd); - } - else if (md) - { - md->to_x = nx; - md->to_y = ny; - prev_state = md->state.state; - md->state.state = MS_WALK; - clif_fixmobpos(md); - } - } - else - battle_stopwalking(target, 2); - - dx = nx - x; - dy = ny - y; - - if (sd) /* 画面外に出たので消去 */ - map_foreachinmovearea(std::bind(clif_pcoutsight, ph::_1, sd), - target->m, x - AREA_SIZE, y - AREA_SIZE, - x + AREA_SIZE, y + AREA_SIZE, - dx, dy, BL_NUL); - else if (md) - map_foreachinmovearea(std::bind(clif_moboutsight, ph::_1, md), - target->m, x - AREA_SIZE, y - AREA_SIZE, - x + AREA_SIZE, y + AREA_SIZE, - dx, dy, BL_PC); - - if (su) - { - skill_unit_move_unit_group(su->group, target->m, dx, dy); - } - else - { -// eptr sc_data=battle_get_sc_data(target); - if (moveblock) - map_delblock(target); - target->x = nx; - target->y = ny; - if (moveblock) - map_addblock(target); -/*ダンス中にエフェクトは移動しないらしい - if (sc_data && sc_data[SC_DANCING].timer!=-1){ //対象がダンス中なのでエフェクトも移動 - struct skill_unit_group *sg= (struct skill_unit_group *)sc_data[SC_DANCING].val2; - if (sg) - skill_unit_move_unit_group(sg,target->m,dx,dy); - } -*/ - } - - if (sd) - { /* 画面内に入ってきたので表示 */ - map_foreachinmovearea(std::bind(clif_pcinsight, ph::_1, sd), - target->m, nx - AREA_SIZE, ny - AREA_SIZE, - nx + AREA_SIZE, ny + AREA_SIZE, - -dx, -dy, BL_NUL); - if (count & 0x20000) - sd->walktimer = -1; - } - else if (md) - { - map_foreachinmovearea(std::bind(clif_mobinsight, ph::_1, md), - target->m, nx - AREA_SIZE, ny - AREA_SIZE, - nx + AREA_SIZE, ny + AREA_SIZE, - -dx, -dy, BL_PC); - if (count & 0x20000) - md->state.state = prev_state; - } - - skill_unit_move(target, gettick(), (count & 0xffff) + 7); /* スキルユニットの判定 */ - return 0; } @@ -1002,7 +239,6 @@ int skill_attack(BF attack_type, struct block_list *src, eptr sc_data; int type, lv, damage; - rdamage = 0; nullpo_ret(src); nullpo_ret(dsrc); nullpo_ret(bl); @@ -1020,11 +256,6 @@ int skill_attack(BF attack_type, struct block_list *src, return 0; if (bl->type == BL_PC && pc_isdead((struct map_session_data *) bl)) //対象がPCですでに死んでいたら何もしない return 0; - if (sc_data && sc_data[SC_HIDING].timer != -1) - { //ハイディング状態で - if (skill_get_pl(skillid) != 2) //スキルの属性が地属性でなければ何もしない - return 0; - } if (src->type == BL_PC && ((struct map_session_data *) src)->chatID) //術者がPCでチャット中なら何もしない return 0; if (dsrc->type == BL_PC && ((struct map_session_data *) dsrc)->chatID) //術者がPCでチャット中なら何もしない @@ -1033,76 +264,16 @@ int skill_attack(BF attack_type, struct block_list *src, //何もしない判定ここまで type = -1; - lv = (flag >> 20) & 0xf; - dmg = battle_calc_attack(attack_type, src, bl, skillid, skilllv, flag & 0xff); //ダメージ計算 + lv = flag.level; + dmg = battle_calc_attack(attack_type, src, bl, skillid, skilllv, flag.lo); //ダメージ計算 damage = dmg.damage + dmg.damage2; if (lv == 15) lv = -1; - if (flag & 0xff00) - type = (flag & 0xff00) >> 8; - - if (damage <= 0 || damage < dmg.div_) //吹き飛ばし判定?※ - dmg.blewcount = 0; - -//武器スキル?ここから - //AppleGirl Was Here - if (bool(attack_type & BF_MAGIC) - && damage > 0 - && src != bl - && src == dsrc) - { //Blah Blah - if (bl->type == BL_PC) - { //Blah Blah - struct map_session_data *tsd = (struct map_session_data *) bl; - if (tsd->magic_damage_return > 0) - { //More Blah - rdamage += damage * tsd->magic_damage_return / 100; - if (rdamage < 1) - rdamage = 1; - } - } - } - //Stop Here - if (bool(attack_type & BF_WEAPON) - && damage > 0 - && src != bl - && src == dsrc) - { //武器スキル&ダメージあり&使用者と対象者が違う&src=dsrc - if (bool(dmg.flag & BF_SHORT)) - { //近距離攻撃時?※ - if (bl->type == BL_PC) - { //対象がPCの時 - struct map_session_data *tsd = (struct map_session_data *) bl; - nullpo_ret(tsd); - if (tsd->short_weapon_damage_return > 0) - { //近距離攻撃跳ね返し?※ - rdamage += damage * tsd->short_weapon_damage_return / 100; - if (rdamage < 1) - rdamage = 1; - } - } - } - else if (bool(dmg.flag & BF_LONG)) - { //遠距離攻撃時?※ - if (bl->type == BL_PC) - { //対象がPCの時 - struct map_session_data *tsd = (struct map_session_data *) bl; - nullpo_ret(tsd); - if (tsd->long_weapon_damage_return > 0) - { //遠距離攻撃跳ね返し?※ - rdamage += damage * tsd->long_weapon_damage_return / 100; - if (rdamage < 1) - rdamage = 1; - } - } - } - if (rdamage > 0) - clif_damage(src, src, tick, dmg.amotion, 0, rdamage, 1, 4, 0); - } -//武器スキル?ここまで + if (flag.mid) + type = flag.mid; switch (skillid) { @@ -1114,14 +285,6 @@ int skill_attack(BF attack_type, struct block_list *src, (lv != 0) ? lv : skilllv, (skillid == SkillID::ZERO) ? 5 : type); } - if (dmg.blewcount > 0) - { /* 吹き飛ばし処理とそのパケット */ - skill_blown(dsrc, bl, dmg.blewcount); - if (bl->type == BL_MOB) - clif_fixmobpos((struct mob_data *) bl); - else - clif_fixpos(bl); - } map_freeblock_lock(); /* 実際にダメージ処理を行う */ @@ -1147,11 +310,11 @@ int skill_attack(BF attack_type, struct block_list *src, target = md->target_id; if (src->type == BL_PC) md->target_id = src->id; - mobskill_use(md, tick, MSC_SKILLUSED, skillid); + mobskill_use(md, tick, MobSkillCondition::ANY, skillid); md->target_id = target; } else - mobskill_use(md, tick, MSC_SKILLUSED, skillid); + mobskill_use(md, tick, MobSkillCondition::ANY, skillid); } } } @@ -1189,9 +352,6 @@ int skill_attack(BF attack_type, struct block_list *src, pc_heal(sd, hp, sp); } - if (rdamage > 0) - battle_damage(bl, src, rdamage, 0); - map_freeblock_unlock(); return (dmg.damage + dmg.damage2); /* 与ダメを返す */ @@ -1208,143 +368,13 @@ void skill_area_sub(struct block_list *bl, { nullpo_retv(bl); - if (bl->type != BL_PC && bl->type != BL_MOB && bl->type != BL_SKILL) + if (bl->type != BL_PC && bl->type != BL_MOB) return; if (battle_check_target(src, bl, flag) > 0) func(src, bl, skill_id, skill_lv, tick, flag); } -int skill_check_unit_range(int, int, int, int, SkillID) -{ - return 0; -} - -static -void skill_check_unit_range2_sub(struct block_list *bl, int *c) -{ - nullpo_retv(bl); - nullpo_retv(c); - - if (bl->prev == NULL || (bl->type != BL_PC && bl->type != BL_MOB)) - return; - - if (bl->type == BL_PC && pc_isdead((struct map_session_data *) bl)) - return; - - (*c)++; -} - -int skill_check_unit_range2(int m, int x, int y, int range) -{ - int c = 0; - - map_foreachinarea(std::bind(skill_check_unit_range2_sub, ph::_1, &c), - m, x - range, y - range, - x + range, y + range, BL_NUL); - - return c; -} - -/*========================================== - * - *------------------------------------------ - */ -static -void skill_timer(timer_id, tick_t tick, custom_id_t id, custom_data_t data) -{ - struct map_session_data *sd = NULL; - struct mob_data *md = NULL; - struct block_list *src = map_id2bl(id), *target; - struct skill_timerskill *skl = NULL; - - nullpo_retv(src); - - if (src->prev == NULL) - return; - - if (src->type == BL_PC) - { - nullpo_retv(sd = (struct map_session_data *) src); - skl = &sd->skilltimerskill[data]; - } - else if (src->type == BL_MOB) - { - nullpo_retv(md = (struct mob_data *) src); - skl = &md->skilltimerskill[data]; - } - - else - return; - - nullpo_retv(skl); - - skl->timer = -1; - if (skl->target_id) - { - target = map_id2bl(skl->target_id); - if (target == NULL) - return; - if (target->prev == NULL) - return; - if (src->m != target->m) - return; - if (sd && pc_isdead(sd)) - return; - if (target->type == BL_PC - && pc_isdead((struct map_session_data *) target)) - return; - - switch (skl->skill_id) - { - default: - skill_attack(skl->type.bf, src, src, target, skl->skill_id, - skl->skill_lv, tick, skl->flag); - break; - } - } -} - -/*========================================== - * - *------------------------------------------ - */ -int skill_cleartimerskill(struct block_list *src) -{ - int i; - - nullpo_ret(src); - - if (src->type == BL_PC) - { - struct map_session_data *sd = (struct map_session_data *) src; - nullpo_ret(sd); - for (i = 0; i < MAX_SKILLTIMERSKILL; i++) - { - if (sd->skilltimerskill[i].timer != -1) - { - delete_timer(sd->skilltimerskill[i].timer, skill_timer); - sd->skilltimerskill[i].timer = -1; - } - } - } - else if (src->type == BL_MOB) - { - struct mob_data *md = (struct mob_data *) src; - nullpo_ret(md); - for (i = 0; i < MAX_MOBSKILLTIMERSKILL; i++) - { - if (md->skilltimerskill[i].timer != -1) - { - delete_timer(md->skilltimerskill[i].timer, skill_timer); - md->skilltimerskill[i].timer = -1; - } - } - } - - return 0; -} - /* 範囲スキル使用処理小分けここまで * ------------------------------------------------------------------------- */ @@ -1386,7 +416,7 @@ int skill_castend_damage_id(struct block_list *src, struct block_list *bl, break; case NPC_SELFDESTRUCTION: /* 自爆 */ - if (flag & 1) + if (flag.lo & 1) { /* 個別にダメージを与える */ if (src->type == BL_MOB) @@ -1420,7 +450,7 @@ int skill_castend_damage_id(struct block_list *src, struct block_list *bl, case SkillID::ZERO: if (sd) { - if (flag & 3) + if (flag.lo & 3) { if (bl->id != skill_area_temp_id) skill_attack(BF_WEAPON, src, src, bl, skillid, @@ -1428,11 +458,11 @@ int skill_castend_damage_id(struct block_list *src, struct block_list *bl, } else { - int ar = sd->splash_range; + // TODO does this happen? skill_area_temp_id = bl->id; map_foreachinarea(std::bind(skill_area_sub, ph::_1, src, skillid, skilllv, tick, flag | BCT_ENEMY | BCT_lo_x01, skill_castend_damage_id), - bl->m, bl->x - ar, bl->y - ar, - bl->x + ar, bl->y + ar, BL_NUL); + bl->m, bl->x - 0, bl->y - 0, + bl->x + 0, bl->y + 0, BL_NUL); } } break; @@ -1450,6 +480,8 @@ int skill_castend_damage_id(struct block_list *src, struct block_list *bl, * スキル使用(詠唱完了、ID指定支援系) *------------------------------------------ */ +// skillid.nk == 1 +// so skillid in (NPC_SUMMONSLAVE, NPC_EMOTION) int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, SkillID skillid, int skilllv, unsigned int, BCT) @@ -1475,11 +507,13 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, if (bl->type == BL_PC) { - nullpo_retr(1, dstsd = (struct map_session_data *) bl); + dstsd = (struct map_session_data *) bl; + nullpo_retr(1, dstsd); } else if (bl->type == BL_MOB) { - nullpo_retr(1, dstmd = (struct mob_data *) bl); + dstmd = (struct mob_data *) bl; + nullpo_retr(1, dstmd); if (sc_def_vit > 50) sc_def_vit = 50; if (sc_def_mdef > 50) @@ -1502,32 +536,21 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, map_freeblock_lock(); switch (skillid) { - case NPC_SELFDESTRUCTION: /* 自爆 */ - skill_status_change_start(bl, SkillStatusChangeTable[skillid], - skilllv, uint16_t(skillid), 0, 0, - skill_get_time(skillid, skilllv), 0); - break; - - case NPC_SUMMONSLAVE: /* 手下召喚 */ + case NPC_SUMMONSLAVE: if (md && !md->master_id) { mob_summonslave(md, - mob_db[md->mob_class].skill[md->skillidx].val, - skilllv, - (true) ? 1 : 0); + mob_db[md->mob_class].skill[md->skillidx].val, + skilllv, + (true) ? 1 : 0); } break; - case NPC_EMOTION: /* エモーション */ + case NPC_EMOTION: if (md) clif_emotion(&md->bl, - mob_db[md->mob_class].skill[md->skillidx].val[0]); + mob_db[md->mob_class].skill[md->skillidx].val[0]); break; - - default: - PRINTF("Unknown skill used:%d\n", skillid); - map_freeblock_unlock(); - return 1; } map_freeblock_unlock(); @@ -1535,3264 +558,986 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, } /*========================================== - * スキル使用(詠唱完了、ID指定) + * 詠唱時間計算 *------------------------------------------ */ -static -void skill_castend_id(timer_id tid, tick_t tick, custom_id_t id, custom_data_t) +int skill_castfix(struct block_list *bl, int time) { - struct map_session_data *sd = map_id2sd(id) /*,*target_sd=NULL */ ; - struct block_list *bl; - int range, inf2; - - nullpo_retv( sd); - - if (sd->bl.prev == NULL) //prevが無いのはありなの? - return; + struct mob_data *md; // [Valaris] + eptr sc_data; + int dex; + int castrate = 100; + SkillID skill; + int lv, castnodex; - if (sd->skilltimer != tid) /* タイマIDの確認 */ - return; - sd->skilltimer = -1; + nullpo_ret(bl); - if ((bl = map_id2bl(sd->skilltarget)) == NULL || bl->prev == NULL) - { - sd->canact_tick = tick; - sd->canmove_tick = tick; - sd->skillitem = SkillID::NEGATIVE; - sd->skillitemlv = -1; - return; - } - if (sd->bl.m != bl->m || pc_isdead(sd)) - { //マップが違うか自分が死んでいる - sd->canact_tick = tick; - sd->canmove_tick = tick; - sd->skillitem = SkillID::NEGATIVE; - sd->skillitemlv = -1; - return; + if (bl->type == BL_MOB) + { // Crash fix [Valaris] + md = (struct mob_data *) bl; + skill = md->skillid; + lv = md->skilllv; } - - inf2 = skill_get_inf2(sd->skillid); - if (((skill_get_inf(sd->skillid) & 1) || inf2 & 4) && // 彼我敵対関係チェック - battle_check_target(&sd->bl, bl, BCT_ENEMY) <= 0) + else { - sd->canact_tick = tick; - sd->canmove_tick = tick; - sd->skillitem = SkillID::NEGATIVE; - sd->skillitemlv = -1; - return; - } - if (inf2 & 0xC00 && sd->bl.id != bl->id) - { - int fail_flag = 1; - if (inf2 & 0x400 && battle_check_target(&sd->bl, bl, BCT_PARTY) > 0) - fail_flag = 0; - if (fail_flag) - { - clif_skill_fail(sd, sd->skillid, 0, 0); - sd->canact_tick = tick; - sd->canmove_tick = tick; - sd->skillitem = SkillID::NEGATIVE; - sd->skillitemlv = -1; - return; - } + skill = SkillID::ZERO; + lv = 0; } - range = skill_get_range(sd->skillid, sd->skilllv); - if (range < 0) - range = battle_get_range(&sd->bl) - (range + 1); - range += battle_config.pc_skill_add_range; - if (battle_config.skill_out_range_consume) - { - // changed to allow casting when target walks out of range [Valaris] - if (range < distance(sd->bl.x, sd->bl.y, bl->x, bl->y)) - { - clif_skill_fail(sd, sd->skillid, 0, 0); - sd->canact_tick = tick; - sd->canmove_tick = tick; - sd->skillitem = SkillID::NEGATIVE; - sd->skillitemlv = -1; - return; - } - } - if (!skill_check_condition(sd, 1)) - { /* 使用条件チェック */ - sd->canact_tick = tick; - sd->canmove_tick = tick; - sd->skillitem = SkillID::NEGATIVE; - sd->skillitemlv = -1; - return; - } - sd->skillitem = SkillID::NEGATIVE; - sd->skillitemlv = -1; - if (battle_config.skill_out_range_consume) - { - if (range < distance(sd->bl.x, sd->bl.y, bl->x, bl->y)) - { - clif_skill_fail(sd, sd->skillid, 0, 0); - sd->canact_tick = tick; - sd->canmove_tick = tick; - return; - } - } + sc_data = battle_get_sc_data(bl); + dex = battle_get_dex(bl); + + if (skill > MAX_SKILL_DB /*|| skill < SkillID()*/) + return 0; - if (battle_config.pc_skill_log) - PRINTF("PC %d skill castend skill=%d\n", - sd->bl.id, sd->skillid); - pc_stop_walking(sd, 0); + castnodex = skill_get_castnodex(skill, lv); - switch (skill_get_nk(sd->skillid)) + if (time == 0) + return 0; + if (castnodex > 0 && bl->type == BL_PC) + castrate = 100; + else if (castnodex <= 0 && bl->type == BL_PC) { - /* 攻撃系/吹き飛ばし系 */ - case 0: - case 2: - skill_castend_damage_id(&sd->bl, bl, - sd->skillid, sd->skilllv, - tick, BCT_ZERO); - break; - case 1: /* 支援系 */ - skill_castend_nodamage_id(&sd->bl, bl, - sd->skillid, sd->skilllv, - tick, BCT_ZERO); - break; + castrate = 100; + time = + time * castrate * (battle_config.castrate_dex_scale - + dex) / (battle_config.castrate_dex_scale * + 100); + time = time * battle_config.cast_rate / 100; } + + return (time > 0) ? time : 0; } /*========================================== - * スキル使用(詠唱完了、map指定) + * ディレイ計算 *------------------------------------------ */ -int skill_castend_map(struct map_session_data *sd, SkillID skill_num, - const char *mapname) +int skill_delayfix(struct block_list *bl, int time) { - nullpo_ret(sd); - if (sd->bl.prev == NULL || pc_isdead(sd)) - return 0; + eptr sc_data; - if (bool(sd->opt1) - || bool(sd->status.option & Option::HIDE2)) - return 0; + nullpo_ret(bl); - if (skill_num != sd->skillid) /* 不正パケットらしい */ + sc_data = battle_get_sc_data(bl); + if (time <= 0) return 0; - pc_stopattack(sd); - - if (battle_config.pc_skill_log) - PRINTF("PC %d skill castend skill =%d map=%s\n", - sd->bl.id, skill_num, mapname); - pc_stop_walking(sd, 0); - - if (strcmp(mapname, "cancel") == 0) - return 0; + if (bl->type == BL_PC) + { + if (battle_config.delay_dependon_dex) /* dexの影響を計算する */ + time = + time * (battle_config.castrate_dex_scale - + battle_get_dex(bl)) / + battle_config.castrate_dex_scale; + time = time * battle_config.delay_rate / 100; + } - return 0; + return (time > 0) ? time : 0; } /*========================================== - * スキルユニット設定処理 + * スキル詠唱キャンセル *------------------------------------------ */ -struct skill_unit_group *skill_unitsetting(struct block_list *src, - SkillID skillid, int skilllv, - int x, int y, int) +int skill_castcancel(struct block_list *bl, int) { - struct skill_unit_group *group; - int i, count = 1, limit_ = 10000, val1_ = 0, val2_ = 0; - BCT target = BCT_ENEMY; - int interval = 1000, range_ = 0; + int inf; - nullpo_ret(src); + nullpo_ret(bl); + + if (bl->type == BL_PC) + { + struct map_session_data *sd = (struct map_session_data *) bl; + unsigned long tick = gettick(); + nullpo_ret(sd); + sd->canact_tick = tick; + sd->canmove_tick = tick; - nullpo_retr(NULL, group = skill_initunitgroup(src, count, skillid, skilllv, 0)); - group->limit = limit_; - group->val1 = val1_; - group->val2 = val2_; - group->target_flag = target; - group->interval = interval; - group->range = range_; - for (i = 0; i < count; i++) + return 0; + } + else if (bl->type == BL_MOB) { - struct skill_unit *unit; - int ux = x, uy = y, val1 = skilllv, val2 = 0, limit = - group->limit, alive = 1; - int range = group->range; - //直上スキルの場合設置座標上にランドプロテクターがないかチェック - if (range <= 0) - map_foreachinarea(std::bind(skill_landprotector, ph::_1, skillid, &alive), - src->m, ux, uy, - ux, uy, BL_SKILL); - - if (alive) + struct mob_data *md = (struct mob_data *) bl; + nullpo_ret(md); + if (md->skilltimer != -1) { - nullpo_retr(NULL, unit = skill_initunit(group, i, ux, uy)); - unit->val1 = val1; - unit->val2 = val2; - unit->limit = limit; - unit->range = range; + if ((inf = skill_get_inf(md->skillid)) == 2 || inf == 32) + delete_timer(md->skilltimer, mobskill_castend_pos); + else + delete_timer(md->skilltimer, mobskill_castend_id); + md->skilltimer = -1; + clif_skillcastcancel(bl); } + return 0; } - return group; + return 1; } /*========================================== - * スキルユニットの発動イベント + * ディボーション 有効確認 *------------------------------------------ */ -static -int skill_unit_onplace(struct skill_unit *src, struct block_list *bl, - unsigned int tick) +void skill_devotion(struct map_session_data *md, int) { - struct skill_unit_group *sg; - struct block_list *ss; - struct skill_unit_group_tickset *ts; - struct map_session_data *srcsd = NULL; - int diff, goflag, splash_count = 0; - - nullpo_ret(src); - nullpo_ret(bl); - - if (bl->prev == NULL || !src->alive - || (bl->type == BL_PC && pc_isdead((struct map_session_data *) bl))) - return 0; - - nullpo_ret(sg = src->group); - nullpo_ret(ss = map_id2bl(sg->src_id)); - - if (ss->type == BL_PC) - nullpo_ret(srcsd = (struct map_session_data *) ss); - if (srcsd && srcsd->chatID) - return 0; - - if (bl->type != BL_PC && bl->type != BL_MOB) - return 0; - nullpo_ret(ts = skill_unitgrouptickset_search(bl, sg->group_id)); - diff = DIFF_TICK(tick, ts->tick); - goflag = (diff > sg->interval || diff < 0); - - //対象がLP上に居る場合は無効 - map_foreachinarea(std::bind(skill_landprotector, ph::_1, SkillID::ZERO, &goflag), - bl->m, bl->x, bl->y, - bl->x, bl->y, BL_SKILL); + // 総確認 + int n; - if (!goflag) - return 0; - ts->tick = tick; - ts->group_id = sg->group_id; + nullpo_retv(md); - switch (sg->unit_id) + for (n = 0; n < 5; n++) { - case 0x83: /* サンクチュアリ */ - { - int race = battle_get_race(bl); - int damage_flag = - (battle_check_undead(race, battle_get_elem_type(bl)) - || race == 6) ? 1 : 0; - - if (battle_get_hp(bl) >= battle_get_max_hp(bl) && !damage_flag) - break; - - if ((sg->val1--) <= 0) - { - skill_delunitgroup(sg); - return 0; - } - if (!damage_flag) - { - int heal = sg->val2; - if (bl->type == BL_PC - && ((struct map_session_data *) bl)-> - special_state.no_magic_damage) - heal = 0; /* 黄金蟲カード(ヒール量0) */ - battle_heal(NULL, bl, heal, 0, 0); - } - else - skill_attack(BF_MAGIC, ss, &src->bl, bl, sg->skill_id, - sg->skill_lv, tick, BCT_ZERO); - } - break; - - case 0x84: /* マグヌスエクソシズム */ - { - int race = battle_get_race(bl); - int damage_flag = - (battle_check_undead(race, battle_get_elem_type(bl)) - || race == 6) ? 1 : 0; - - if (!damage_flag) - return 0; - skill_attack(BF_MAGIC, ss, &src->bl, bl, sg->skill_id, - sg->skill_lv, tick, BCT_ZERO); - } - break; - - case 0x85: /* ニューマ */ - { - struct skill_unit *unit2; - eptr sc_data = battle_get_sc_data(bl); - if (sc_data && sc_data[SC_PNEUMA].timer == -1) - skill_status_change_start(bl, SC_PNEUMA, sg->skill_lv, - (int) src, 0, 0, 0, 0); - else if ((unit2 = (struct skill_unit *) sc_data[SC_PNEUMA].val2) - && unit2 != src) - { - if (DIFF_TICK(sg->tick, unit2->group->tick) > 0) - skill_status_change_start(bl, SC_PNEUMA, sg->skill_lv, - (int) src, 0, 0, 0, 0); - ts->tick -= sg->interval; - } - } - break; - case 0x7e: /* セイフティウォール */ + if (md->dev.val1[n]) { - struct skill_unit *unit2; - eptr sc_data = battle_get_sc_data(bl); - if (sc_data && sc_data[SC_SAFETYWALL].timer == -1) - skill_status_change_start(bl, SC_SAFETYWALL, sg->skill_lv, - (int) src, 0, 0, 0, 0); - else if ((unit2 = (struct skill_unit *) sc_data[SC_SAFETYWALL].val2) - && unit2 != src) + struct map_session_data *sd = map_id2sd(md->dev.val1[n]); + // 相手が見つからない // 相手をディボしてるのが自分じゃない // 距離が離れてる + if (sd == NULL + || (md->bl.id != 0/* was something else - TODO remove this */) + || skill_devotion3(&md->bl, md->dev.val1[n])) { - if (sg->val1 < unit2->group->val1) - skill_status_change_start(bl, SC_SAFETYWALL, sg->skill_lv, - (int) src, 0, 0, 0, 0); - ts->tick -= sg->interval; + skill_devotion_end(md, sd, n); } } - break; - - case 0x86: /* ロードオブヴァーミリオン(&ストームガスト &グランドクロス) */ - skill_attack(BF_MAGIC, ss, &src->bl, bl, sg->skill_id, - sg->skill_lv, tick, BCT_ZERO); - break; - - case 0x7f: /* ファイヤーウォール */ - if ((src->val2--) > 0) - skill_attack(BF_MAGIC, ss, &src->bl, bl, - sg->skill_id, sg->skill_lv, tick, BCT_ZERO); - if (src->val2 <= 0) - skill_delunit(src); - break; - - case 0x87: /* ファイアーピラー(発動前) */ - skill_delunit(src); - skill_unitsetting(ss, sg->skill_id, sg->skill_lv, src->bl.x, - src->bl.y, 1); - break; - - case 0x88: /* ファイアーピラー(発動後) */ - if (DIFF_TICK(tick, sg->tick) < 150) - skill_attack(BF_MAGIC, ss, &src->bl, bl, sg->skill_id, - sg->skill_lv, tick, BCT_ZERO); - break; - - case 0x90: /* スキッドトラップ */ - { - int i, c = skill_get_blewcount(sg->skill_id, sg->skill_lv); - for (i = 0; i < c; i++) - skill_blown(&src->bl, bl, 1 | 0x30000); - sg->unit_id = 0x8c; - clif_changelook(&src->bl, LOOK_BASE, sg->unit_id); - sg->limit = DIFF_TICK(tick, sg->tick) + 1500; - } - break; - - case 0x93: /* ランドマイン */ - skill_attack(BF_MISC, ss, &src->bl, bl, sg->skill_id, - sg->skill_lv, tick, BCT_ZERO); - sg->unit_id = 0x8c; - clif_changelook(&src->bl, LOOK_BASE, 0x88); - sg->limit = DIFF_TICK(tick, sg->tick) + 1500; - break; - - case 0x8f: /* ブラストマイン */ - case 0x94: /* ショックウェーブトラップ */ - case 0x95: /* サンドマン */ - case 0x96: /* フラッシャー */ - case 0x97: /* フリージングトラップ */ - case 0x98: /* クレイモアートラップ */ - map_foreachinarea(std::bind(skill_count_target, ph::_1, &src->bl, &splash_count), - src->bl.m, src->bl.x - src->range, src->bl.y - src->range, - src->bl.x + src->range, src->bl.y + src->range, BL_NUL); - map_foreachinarea(std::bind(skill_trap_splash, ph::_1, &src->bl, tick, splash_count), - src->bl.m, src->bl.x - src->range, src->bl.y - src->range, - src->bl.x + src->range, src->bl.y + src->range, BL_NUL); - sg->unit_id = 0x8c; - clif_changelook(&src->bl, LOOK_BASE, sg->unit_id); - sg->limit = DIFF_TICK(tick, sg->tick) + 1500; - break; + } +} - case 0x91: /* アンクルスネア */ - { - eptr sc_data = battle_get_sc_data(bl); - if (sg->val2 == 0 && sc_data && sc_data[SC_ANKLE].timer == -1) - { - int moveblock = (bl->x / BLOCK_SIZE != src->bl.x / BLOCK_SIZE - || bl->y / BLOCK_SIZE != - src->bl.y / BLOCK_SIZE); - int sec = skill_get_time2(sg->skill_id, - sg->skill_lv) - - (double) battle_get_agi(bl) * 0.1; - if (bool(battle_get_mode(bl) & MobMode::BOSS)) - sec = sec / 5; - battle_stopwalking(bl, 1); - skill_status_change_start(bl, SC_ANKLE, - sg->skill_lv, 0, 0, 0, - sec, 0); - - if (moveblock) - map_delblock(bl); - bl->x = src->bl.x; - bl->y = src->bl.y; - if (moveblock) - map_addblock(bl); - if (bl->type == BL_MOB) - clif_fixmobpos((struct mob_data *) bl); - else - clif_fixpos(bl); - sg->limit = DIFF_TICK(tick, sg->tick) + sec; - sg->val2 = bl->id; - } - } - break; +int skill_devotion3(struct block_list *bl, int target) +{ + // クルセが歩いた時の距離チェック + struct map_session_data *md; + struct map_session_data *sd; + int n, r = 0; - case 0x80: /* ワープポータル(発動後) */ - if (bl->type == BL_PC) - { - struct map_session_data *sd = (struct map_session_data *) bl; - if (sd && src->bl.m == bl->m && src->bl.x == bl->x - && src->bl.y == bl->y && src->bl.x == sd->to_x - && src->bl.y == sd->to_y) - { - if (battle_config.chat_warpportal || !sd->chatID) - { - if ((sg->val1--) > 0) - { - pc_setpos(sd, sg->valstr, sg->val2 >> 16, - sg->val2 & 0xffff, 3); - if (sg->src_id == bl->id - || (strcmp(map[src->bl.m].name, sg->valstr) - == 0 && src->bl.x == (sg->val2 >> 16) - && src->bl.y == (sg->val2 & 0xffff))) - skill_delunitgroup(sg); - } - else - skill_delunitgroup(sg); - } - } - } - else if (bl->type == BL_MOB && battle_config.mob_warpportal) - { - int m = map_mapname2mapid(sg->valstr); - mob_warp((struct mob_data *) bl, m, sg->val2 >> 16, - sg->val2 & 0xffff, 3); - } - break; + nullpo_retr(1, bl); - case 0x8e: /* クァグマイア */ - { - StatusChange type = SkillStatusChangeTable[sg->skill_id]; - if (bl->type == BL_PC - && ((struct map_session_data *) bl)-> - special_state.no_magic_damage) - break; - if (battle_get_sc_data(bl)[type].timer == -1) - skill_status_change_start(bl, type, sg->skill_lv, (int) src, - 0, 0, - skill_get_time2(sg->skill_id, - sg->skill_lv), 0); - } - break; - case 0x92: /* ベノムダスト */ - { - eptr sc_data = battle_get_sc_data(bl); - StatusChange type = SkillStatusChangeTable[sg->skill_id]; - if (sc_data && sc_data[type].timer == -1) - skill_status_change_start(bl, type, sg->skill_lv, (int) src, - 0, 0, - skill_get_time2(sg->skill_id, - sg->skill_lv), 0); - } - break; - case 0x9a: /* ボルケーノ */ - case 0x9b: /* デリュージ */ - case 0x9c: /* バイオレントゲイル */ - { - struct skill_unit *unit2; - eptr sc_data = battle_get_sc_data(bl); - StatusChange type = SkillStatusChangeTable[sg->skill_id]; - if (sc_data && sc_data[type].timer == -1) - skill_status_change_start(bl, type, sg->skill_lv, (int) src, - 0, 0, - skill_get_time2(sg->skill_id, - sg->skill_lv), 0); - else if ((unit2 = (struct skill_unit *) sc_data[type].val2) - && unit2 != src) - { - if (DIFF_TICK(sg->tick, unit2->group->tick) > 0) - skill_status_change_start(bl, type, sg->skill_lv, - (int) src, 0, 0, - skill_get_time2(sg->skill_id, - sg->skill_lv), - 0); - ts->tick -= sg->interval; - } - } break; - - case 0x9e: /* 子守唄 */ - case 0x9f: /* ニヨルドの宴 */ - case 0xa0: /* 永遠の混沌 */ - case 0xa1: /* 戦太鼓の響き */ - case 0xa2: /* ニーベルングの指輪 */ - case 0xa3: /* ロキの叫び */ - case 0xa4: /* 深淵の中に */ - case 0xa5: /* 不死身のジークフリード */ - case 0xa6: /* 不協和音 */ - case 0xa7: /* 口笛 */ - case 0xa8: /* 夕陽のアサシンクロス */ - case 0xa9: /* ブラギの詩 */ - case 0xab: /* 自分勝手なダンス */ - case 0xac: /* ハミング */ - case 0xad: /* 私を忘れないで… */ - case 0xae: /* 幸運のキス */ - case 0xaf: /* サービスフォーユー */ - case 0xb4: - { - struct skill_unit *unit2; - eptr sc_data = battle_get_sc_data(bl); - StatusChange type = SkillStatusChangeTable[sg->skill_id]; - if (sg->src_id == bl->id) - break; - if (sc_data && sc_data[type].timer == -1) - skill_status_change_start(bl, type, sg->skill_lv, sg->val1, - sg->val2, (int) src, - skill_get_time2(sg->skill_id, - sg->skill_lv), 0); - else if ((unit2 = (struct skill_unit *) sc_data[type].val4) - && unit2 != src) - { - if (unit2->group - && DIFF_TICK(sg->tick, unit2->group->tick) > 0) - skill_status_change_start(bl, type, sg->skill_lv, - sg->val1, sg->val2, (int) src, - skill_get_time2(sg->skill_id, - sg->skill_lv), - 0); - ts->tick -= sg->interval; - } - } break; + if ((md = (struct map_session_data *) bl) == NULL + || (sd = map_id2sd(target)) == NULL) + return 1; + else + r = distance(bl->x, bl->y, sd->bl.x, sd->bl.y); - case 0xaa: /* イドゥンの林檎 */ - { - struct skill_unit *unit2; - eptr sc_data = battle_get_sc_data(bl); - StatusChange type = SkillStatusChangeTable[sg->skill_id]; - if (sg->src_id == bl->id) - break; - if (sc_data && sc_data[type].timer == -1) - skill_status_change_start(bl, type, sg->skill_lv, - (sg->val1) >> 16, - (sg->val1) & 0xffff, (int) src, - skill_get_time2(sg->skill_id, - sg->skill_lv), 0); - else if ((unit2 = (struct skill_unit *) sc_data[type].val4) - && unit2 != src) - { - if (DIFF_TICK(sg->tick, unit2->group->tick) > 0) - skill_status_change_start(bl, type, sg->skill_lv, - (sg->val1) >> 16, - (sg->val1) & 0xffff, (int) src, - skill_get_time2(sg->skill_id, - sg->skill_lv), - 0); - ts->tick -= sg->interval; - } - } break; - - case 0xb1: /* デモンストレーション */ - skill_attack(BF_WEAPON, ss, &src->bl, bl, sg->skill_id, - sg->skill_lv, tick, BCT_ZERO); - if (bl->type == BL_PC && MRAND(100) < sg->skill_lv - && battle_config.equipment_breaking) - pc_breakweapon((struct map_session_data *) bl); - break; - case 0x99: /* トーキーボックス */ - if (sg->src_id == bl->id) //自分が踏んでも発動しない - break; - if (sg->val2 == 0) - { - sg->unit_id = 0x8c; - clif_changelook(&src->bl, LOOK_BASE, sg->unit_id); - sg->limit = DIFF_TICK(tick, sg->tick) + 5000; - sg->val2 = -1; //踏んだ - } - break; - case 0xb2: /* あなたを_会いたいです */ - case 0xb3: /* ゴスペル */ - case 0xb6: /* フォグウォール */ - //とりあえず何もしない - break; + if ( + 6 < r) + { // 許容範囲を超えてた + for (n = 0; n < 5; n++) + if (md->dev.val1[n] == target) + md->dev.val2[n] = 0; // 離れた時は、糸を切るだけ + return 1; + } + return 0; +} - case 0xb7: /* スパイダーウェッブ */ - if (sg->val2 == 0) - { - int moveblock = (bl->x / BLOCK_SIZE != src->bl.x / BLOCK_SIZE - || bl->y / BLOCK_SIZE != - src->bl.y / BLOCK_SIZE); - skill_additional_effect(ss, bl, sg->skill_id, sg->skill_lv, - BF_MISC, tick); - if (moveblock) - map_delblock(bl); - bl->x = (&src->bl)->x; - bl->y = (&src->bl)->y; - if (moveblock) - map_addblock(bl); - if (bl->type == BL_MOB) - clif_fixmobpos((struct mob_data *) bl); - else - clif_fixpos(bl); - sg->limit = - DIFF_TICK(tick, - sg->tick) + skill_get_time2(sg->skill_id, - sg->skill_lv); - sg->val2 = bl->id; - } - break; +void skill_devotion_end(struct map_session_data *md, + struct map_session_data *, int target) +{ + // クルセと被ディボキャラのリセット + nullpo_retv(md); -/* default: - if (battle_config.error_log) - PRINTF("skill_unit_onplace: Unknown skill unit id=%d block=%d\n",sg->unit_id,bl->id); - break;*/ - } - if (bl->type == BL_MOB && ss != bl) /* スキル使用条件のMOBスキル */ - { - if (battle_config.mob_changetarget_byskill == 1) - { - int target = ((struct mob_data *) bl)->target_id; - if (ss->type == BL_PC) - ((struct mob_data *) bl)->target_id = ss->id; - mobskill_use((struct mob_data *) bl, tick, - MSC_SKILLUSED, sg->skill_id); - ((struct mob_data *) bl)->target_id = target; - } - else - mobskill_use((struct mob_data *) bl, tick, - MSC_SKILLUSED, sg->skill_id); - } + md->dev.val1[target] = md->dev.val2[target] = 0; +} +int skill_gangsterparadise(struct map_session_data *, int) +{ return 0; } +/*---------------------------------------------------------------------------- + * ステータス異常 + *---------------------------------------------------------------------------- + */ + /*========================================== - * スキルユニットから離脱する(もしくはしている)場合 + * ステータス異常終了 *------------------------------------------ */ -static -int skill_unit_onout(struct skill_unit *src, struct block_list *bl, - unsigned int tick) +int skill_status_change_active(struct block_list *bl, StatusChange type) { - struct skill_unit_group *sg; + eptr sc_data; - nullpo_ret(src); nullpo_ret(bl); - nullpo_ret(sg = src->group); - - if (bl->prev == NULL || !src->alive) + if (bl->type != BL_PC && bl->type != BL_MOB) + { + if (battle_config.error_log) + PRINTF("skill_status_change_active: neither MOB nor PC !\n"); return 0; + } - if (bl->type != BL_PC && bl->type != BL_MOB) + sc_data = battle_get_sc_data(bl); + if (not sc_data) return 0; - switch (sg->unit_id) - { - case 0x7e: /* セイフティウォール */ - case 0x85: /* ニューマ */ - case 0x8e: /* クァグマイア */ - { - eptr sc_data = battle_get_sc_data(bl); - StatusChange type = - (sg->unit_id == 0x85) ? SC_PNEUMA : SC_SAFETYWALL; - if (sc_data - && sc_data[type].timer != -1 - && ((struct skill_unit *) sc_data[type].val2) == src) - { - skill_status_change_end(bl, type, -1); - } - } break; + return sc_data[type].timer != -1; +} - case 0x91: /* アンクルスネア */ - { - struct block_list *target = map_id2bl(sg->val2); - if (target && target == bl) +int skill_status_change_end(struct block_list *bl, StatusChange type, int tid) +{ + eptr sc_data; + int opt_flag = 0, calc_flag = 0; + short *sc_count; + Option *option; + Opt1 *opt1; + Opt2 *opt2; + Opt3 *opt3; + + nullpo_ret(bl); + if (bl->type != BL_PC && bl->type != BL_MOB) + { + if (battle_config.error_log) + PRINTF("skill_status_change_end: neither MOB nor PC !\n"); + return 0; + } + sc_data = battle_get_sc_data(bl); + if (not sc_data) + return 0; + sc_count = battle_get_sc_count(bl); + nullpo_ret(sc_count); + option = battle_get_option(bl); + nullpo_ret(option); + opt1 = battle_get_opt1(bl); + nullpo_ret(opt1); + opt2 = battle_get_opt2(bl); + nullpo_ret(opt2); + opt3 = battle_get_opt3(bl); + nullpo_ret(opt3); + + if ((*sc_count) > 0 && sc_data[type].timer != -1 + && (sc_data[type].timer == tid || tid == -1)) + { + + if (tid == -1) // タイマから呼ばれていないならタイマ削除をする + delete_timer(sc_data[type].timer, skill_status_change_timer); + + /* 該当の異常を正常に戻す */ + sc_data[type].timer = -1; + (*sc_count)--; + + switch (type) + { /* 異常の種類ごとの処理 */ + case SC_SPEEDPOTION0: /* 増速ポーション */ + case SC_ATKPOT: /* attack potion [Valaris] */ + case SC_MATKPOT: /* magic attack potion [Valaris] */ + case SC_PHYS_SHIELD: + case SC_HASTE: + calc_flag = 1; + break; { - skill_status_change_end(bl, SC_ANKLE, -1); - sg->limit = DIFF_TICK(tick, sg->tick) + 1000; + struct map_session_data *md = map_id2sd(sc_data[type].val1); + sc_data[type].val1 = sc_data[type].val2 = 0; + skill_devotion(md, bl->id); + calc_flag = 1; } - } - break; - case 0xb5: - case 0xb8: - { - sg->limit = DIFF_TICK(tick, sg->tick) + 1000; - } - break; - case 0xb6: - { - sg->limit = DIFF_TICK(tick, sg->tick) + 1000; - } - break; - case 0x9a: /* ボルケーノ */ - case 0x9b: /* デリュージ */ - case 0x9c: /* バイオレントゲイル */ - { - eptr sc_data = battle_get_sc_data(bl); - struct skill_unit *su; - StatusChange type = SkillStatusChangeTable[sg->skill_id]; - if (sc_data && sc_data[type].timer != -1 - && (su = ((struct skill_unit *) sc_data[type].val2)) - && su == src) + break; + case SC_NOCHAT: //チャット禁止状態 + break; + case SC_SELFDESTRUCTION: /* 自爆 */ { - skill_status_change_end(bl, type, -1); + //自分のダメージは0にして + struct mob_data *md = NULL; + if (bl->type == BL_MOB && (md = (struct mob_data *) bl)) + skill_castend_damage_id(bl, bl, + static_cast(sc_data[type].val2), sc_data[type].val1, + gettick(), BCT_ZERO); } - } - break; + break; + /* option1 */ + case SC_FREEZE: + sc_data[type].val3 = 0; + break; - case 0x9e: /* 子守唄 */ - case 0x9f: /* ニヨルドの宴 */ - case 0xa0: /* 永遠の混沌 */ - case 0xa1: /* 戦太鼓の響き */ - case 0xa2: /* ニーベルングの指輪 */ - case 0xa3: /* ロキの叫び */ - case 0xa4: /* 深淵の中に */ - case 0xa5: /* 不死身のジークフリード */ - case 0xa6: /* 不協和音 */ - case 0xa7: /* 口笛 */ - case 0xa8: /* 夕陽のアサシンクロス */ - case 0xa9: /* ブラギの詩 */ - case 0xaa: /* イドゥンの林檎 */ - case 0xab: /* 自分勝手なダンス */ - case 0xac: /* ハミング */ - case 0xad: /* 私を忘れないで… */ - case 0xae: /* 幸運のキス */ - case 0xaf: /* サービスフォーユー */ - case 0xb4: - { - eptr sc_data = battle_get_sc_data(bl); - struct skill_unit *su; - StatusChange type = SkillStatusChangeTable[sg->skill_id]; - if (sc_data && sc_data[type].timer != -1 - && (su = ((struct skill_unit *) sc_data[type].val4)) - && su == src) - { - skill_status_change_end(bl, type, -1); - } - } - break; - case 0xb7: /* スパイダーウェッブ */ - { - sg->limit = DIFF_TICK(tick, sg->tick) + 1000; + /* option2 */ + case SC_POISON: /* 毒 */ + case SC_BLIND: /* 暗黒 */ + case SC_CURSE: + calc_flag = 1; + break; } - break; -/* default: - if (battle_config.error_log) - PRINTF("skill_unit_onout: Unknown skill unit id=%d block=%d\n",sg->unit_id,bl->id); - break;*/ - } - skill_unitgrouptickset_delete(bl, sg->group_id); - return 0; -} + if (bl->type == BL_PC && type < SC_SENDMAX) + clif_status_change(bl, type, 0); /* アイコン消去 */ -/*========================================== - * スキルユニットの削除イベント - *------------------------------------------ - */ -static -int skill_unit_ondelete(struct skill_unit *src, struct block_list *bl, - unsigned int tick) -{ - struct skill_unit_group *sg; + switch (type) + { /* 正常に戻るときなにか処理が必要 */ + case SC_STONE: + case SC_FREEZE: + case SC_STAN: + case SC_SLEEP: + *opt1 = Opt1::ZERO; + opt_flag = 1; + break; - nullpo_ret(src); - nullpo_ret(bl); - nullpo_ret(sg = src->group); + case SC_POISON: + *opt2 &= ~Opt2::_poison; + opt_flag = 1; + break; - if (bl->prev == NULL || !src->alive) - return 0; + case SC_CURSE: + *opt2 &= ~Opt2::_curse; + opt_flag = 1; + break; - if (bl->type != BL_PC && bl->type != BL_MOB) - return 0; + case SC_SILENCE: + *opt2 &= ~Opt2::_silence; + opt_flag = 1; + break; - switch (sg->unit_id) - { - case 0x85: /* ニューマ */ - case 0x7e: /* セイフティウォール */ - case 0x8e: /* クァグマイヤ */ - case 0x9a: /* ボルケーノ */ - case 0x9b: /* デリュージ */ - case 0x9c: /* バイオレントゲイル */ - case 0x9e: /* 子守唄 */ - case 0x9f: /* ニヨルドの宴 */ - case 0xa0: /* 永遠の混沌 */ - case 0xa1: /* 戦太鼓の響き */ - case 0xa2: /* ニーベルングの指輪 */ - case 0xa3: /* ロキの叫び */ - case 0xa4: /* 深淵の中に */ - case 0xa5: /* 不死身のジークフリード */ - case 0xa6: /* 不協和音 */ - case 0xa7: /* 口笛 */ - case 0xa8: /* 夕陽のアサシンクロス */ - case 0xa9: /* ブラギの詩 */ - case 0xaa: /* イドゥンの林檎 */ - case 0xab: /* 自分勝手なダンス */ - case 0xac: /* ハミング */ - case 0xad: /* 私を忘れないで… */ - case 0xae: /* 幸運のキス */ - case 0xaf: /* サービスフォーユー */ - case 0xb4: - return skill_unit_onout(src, bl, tick); - -/* default: - if (battle_config.error_log) - PRINTF("skill_unit_ondelete: Unknown skill unit id=%d block=%d\n",sg->unit_id,bl->id); - break;*/ - } - skill_unitgrouptickset_delete(bl, sg->group_id); - return 0; -} + case SC_BLIND: + *opt2 &= ~Opt2::BLIND; + opt_flag = 1; + break; -/*========================================== - * スキルユニットの限界イベント - *------------------------------------------ - */ -static -int skill_unit_onlimit(struct skill_unit *src, unsigned int) -{ - struct skill_unit_group *sg; + case SC_SLOWPOISON: + if (sc_data[SC_POISON].timer != -1) + *opt2 |= Opt2::_poison; + *opt2 &= ~Opt2::_slowpoison; + opt_flag = 1; + break; - nullpo_ret(src); - nullpo_ret(sg = src->group); + case SC_SPEEDPOTION0: + *opt2 &= ~Opt2::_speedpotion0; + opt_flag = 1; + break; - switch (sg->unit_id) - { - case 0x81: /* ワープポータル(発動前) */ - { - struct skill_unit_group *group = - skill_unitsetting(map_id2bl(sg->src_id), sg->skill_id, - sg->skill_lv, - src->bl.x, src->bl.y, 1); - if (group == NULL) - return 0; - CREATE(group->valstr, char, 24); - memcpy(group->valstr, sg->valstr, 24); - group->val2 = sg->val2; + case SC_ATKPOT: + *opt2 &= ~Opt2::_atkpot; + opt_flag = 1; + break; } - break; - - case 0x8d: /* アイスウォール */ - map_setcell(src->bl.m, src->bl.x, src->bl.y, src->val2); - break; - case 0xb2: /* あなたに会いたい */ - { - struct map_session_data *sd = NULL; - struct map_session_data *p_sd = NULL; - if ((sd = - (struct map_session_data *)(map_id2bl(sg->src_id))) == - NULL) - return 0; - if ((p_sd = pc_get_partner(sd)) == NULL) - return 0; - pc_setpos(p_sd, map[src->bl.m].name, src->bl.x, src->bl.y, 3); + if (night_flag == 1 + && !bool(*opt2 & Opt2::BLIND) + && bl->type == BL_PC) + { // by [Yor] + *opt2 |= Opt2::BLIND; + opt_flag = 1; } - break; + + if (opt_flag) /* optionの変更を伝える */ + clif_changeoption(bl); + + if (bl->type == BL_PC && calc_flag) + pc_calcstatus((struct map_session_data *) bl, 0); /* ステータス再計算 */ } + return 0; } -/*========================================== - * スキルユニットのダメージイベント - *------------------------------------------ - */ -int skill_unit_ondamaged(struct skill_unit *src, struct block_list *bl, - int damage, unsigned int) +int skill_update_heal_animation(struct map_session_data *sd) { - struct skill_unit_group *sg; + const Opt2 mask = Opt2::_heal; - nullpo_ret(src); - nullpo_ret(sg = src->group); + nullpo_ret(sd); + bool was_active = bool(sd->opt2 & mask); + bool is_active = sd->quick_regeneration_hp.amount > 0; - switch (sg->unit_id) - { - case 0x8d: /* アイスウォール */ - src->val1 -= damage; - break; - case 0x8f: /* ブラストマイン */ - case 0x98: /* クレイモアートラップ */ - skill_blown(bl, &src->bl, 2); //吹き飛ばしてみる - break; - default: - damage = 0; - break; - } - return damage; -} + if (was_active == is_active) + return 0; // no update + + if (is_active) + sd->opt2 |= mask; + else + sd->opt2 &= ~mask; -/*---------------------------------------------------------------------------- */ + return clif_changeoption(&sd->bl); +} /*========================================== - * スキル使用(詠唱完了、場所指定) + * ステータス異常終了タイマー *------------------------------------------ */ -static -void skill_castend_pos(timer_id tid, tick_t tick, custom_id_t id, custom_data_t) +void skill_status_change_timer(timer_id tid, tick_t tick, custom_id_t id, custom_data_t data) { - struct map_session_data *sd = map_id2sd(id) /*,*target_sd=NULL */ ; - int maxcount; - - nullpo_retv(sd); + StatusChange type = static_cast(data); + struct block_list *bl; + struct map_session_data *sd = NULL; + eptr sc_data; + //short *sc_count; //使ってない? - if (sd->bl.prev == NULL) - return; - if (sd->skilltimer != tid) /* タイマIDの確認 */ + if ((bl = map_id2bl(id)) == NULL) return; - sd->skilltimer = -1; - if (pc_isdead(sd)) - { - sd->canact_tick = tick; - sd->canmove_tick = tick; - sd->skillitem = SkillID::NEGATIVE; - sd->skillitemlv = -1; + //該当IDがすでに消滅しているというのはいかにもありそうなのでスルーしてみる + sc_data = battle_get_sc_data(bl); + if (not sc_data) return; - } - if (battle_config.pc_land_skill_limit) - { - maxcount = skill_get_maxcount(sd->skillid); - if (maxcount > 0) - { - int i, c; - for (i = c = 0; i < MAX_SKILLUNITGROUP; i++) - { - if (sd->skillunit[i].alive_count > 0 - && sd->skillunit[i].skill_id == sd->skillid) - c++; - } - if (c >= maxcount) - { - clif_skill_fail(sd, sd->skillid, 0, 0); - sd->canact_tick = tick; - sd->canmove_tick = tick; - sd->skillitem = SkillID::NEGATIVE; - sd->skillitemlv = -1; - return; - } - } - } + if (bl->type == BL_PC) + sd = (struct map_session_data *) bl; - int range = skill_get_range(sd->skillid, sd->skilllv); - if (range < 0) - range = battle_get_range(&sd->bl) - (range + 1); - range += battle_config.pc_skill_add_range; - if (battle_config.skill_out_range_consume) - { // changed to allow casting when target walks out of range [Valaris] - if (range < distance(sd->bl.x, sd->bl.y, sd->skillx, sd->skilly)) - { - clif_skill_fail(sd, sd->skillid, 0, 0); - sd->canact_tick = tick; - sd->canmove_tick = tick; - sd->skillitem = SkillID::NEGATIVE; - sd->skillitemlv = -1; - return; - } - } - if (!skill_check_condition(sd, 1)) - { /* 使用条件チェック */ - sd->canact_tick = tick; - sd->canmove_tick = tick; - sd->skillitem = SkillID::NEGATIVE; - sd->skillitemlv = -1; - return; - } - sd->skillitem = SkillID::NEGATIVE; - sd->skillitemlv = -1; - if (battle_config.skill_out_range_consume) + //sc_count=battle_get_sc_count(bl); //使ってない? + + if (sc_data[type].timer != tid) { - if (range < distance(sd->bl.x, sd->bl.y, sd->skillx, sd->skilly)) - { - clif_skill_fail(sd, sd->skillid, 0, 0); - sd->canact_tick = tick; - sd->canmove_tick = tick; - return; - } + if (battle_config.error_log) + PRINTF("skill_status_change_timer %d != %d\n", tid, + sc_data[type].timer); } - if (battle_config.pc_skill_log) - PRINTF("PC %d skill castend skill=%d\n", - sd->bl.id, sd->skillid); - pc_stop_walking(sd, 0); -} - + if (sc_data[type].spell_invocation) + { // Must report termination + spell_effect_report_termination(sc_data[type].spell_invocation, + bl->id, type, 0); + sc_data[type].spell_invocation = 0; + } -/*========================================== - * スキル使用条件(偽で使用失敗) - *------------------------------------------ - */ -int skill_check_condition(struct map_session_data *sd, int type) -{ - int hp, sp, hp_rate, sp_rate, zeny, weapon, spiritball, - lv, mhp; - int index[10], itemid[10], amount[10]; - - nullpo_ret(sd); - - if (battle_config.gm_skilluncond > 0 - && pc_isGM(sd) >= battle_config.gm_skilluncond) - { - sd->skillitem = SkillID::NEGATIVE; - sd->skillitemlv = -1; - return 1; - } - - if (bool(sd->opt1)) - { - clif_skill_fail(sd, sd->skillid, 0, 0); - sd->skillitem = SkillID::NEGATIVE; - sd->skillitemlv = -1; - return 0; - } - if (pc_is90overweight(sd)) - { - clif_skill_fail(sd, sd->skillid, 9, 0); - sd->skillitem = SkillID::NEGATIVE; - sd->skillitemlv = -1; - return 0; - } - - if (sd->skillitem == sd->skillid) - { /* アイテムの場合無条件成功 */ - if (type & 1) - { - sd->skillitem = SkillID::NEGATIVE; - sd->skillitemlv = -1; - } - return 1; - } - if (bool(sd->opt1)) - { - clif_skill_fail(sd, sd->skillid, 0, 0); - return 0; - } - - SkillID skill = sd->skillid; - lv = sd->skilllv; - hp = skill_get_hp(skill, lv); /* 消費HP */ - sp = skill_get_sp(skill, lv); /* 消費SP */ - hp_rate = (lv <= 0) ? 0 : skill_db[skill].hp_rate[lv - 1]; - sp_rate = (lv <= 0) ? 0 : skill_db[skill].sp_rate[lv - 1]; - zeny = skill_get_zeny(skill, lv); - weapon = skill_db[skill].weapon; - spiritball = (lv <= 0) ? 0 : skill_db[skill].spiritball[lv - 1]; - mhp = skill_get_mhp(skill, lv); /* 消費HP */ - for (int i = 0; i < 10; i++) - { - itemid[i] = skill_db[skill].itemid[i]; - amount[i] = skill_db[skill].amount[i]; - } - if (mhp > 0) - hp += (sd->status.max_hp * mhp) / 100; - if (hp_rate > 0) - hp += (sd->status.hp * hp_rate) / 100; - else - hp += (sd->status.max_hp * abs(hp_rate)) / 100; - if (sp_rate > 0) - sp += (sd->status.sp * sp_rate) / 100; - else - sp += (sd->status.max_sp * abs(sp_rate)) / 100; - if (sd->dsprate != 100) - sp = sp * sd->dsprate / 100; /* 消費SP修正 */ - - if (!(type & 2)) - { - if (hp > 0 && sd->status.hp < hp) - { /* HPチェック */ - clif_skill_fail(sd, skill, 2, 0); /* HP不足:失敗通知 */ - return 0; - } - if (sp > 0 && sd->status.sp < sp) - { /* SPチェック */ - clif_skill_fail(sd, skill, 1, 0); /* SP不足:失敗通知 */ - return 0; - } - if (zeny > 0 && sd->status.zeny < zeny) - { - clif_skill_fail(sd, skill, 5, 0); - return 0; - } - if (!(weapon & (1 << sd->status.weapon))) - { - clif_skill_fail(sd, skill, 6, 0); - return 0; - } - if (spiritball > 0 && sd->spiritball < spiritball) - { - clif_skill_fail(sd, skill, 0, 0); // 氣球不足 - return 0; - } - } - - for (int i = 0; i < 10; i++) - { - index[i] = -1; - if (itemid[i] <= 0) - continue; - if (itemid[i] >= 715 && itemid[i] <= 717 - && sd->special_state.no_gemstone) - continue; - - index[i] = pc_search_inventory(sd, itemid[i]); - if (index[i] < 0 || sd->status.inventory[index[i]].amount < amount[i]) - { - if (itemid[i] == 716 || itemid[i] == 717) - clif_skill_fail(sd, skill, (7 + (itemid[i] - 716)), 0); - else - clif_skill_fail(sd, skill, 0, 0); - return 0; - } - } - - if (!(type & 1)) - return 1; - - { - for (int i = 0; i < 10; i++) - { - if (index[i] >= 0) - pc_delitem(sd, index[i], amount[i], 0); // アイテム消費 - } - } - - if (type & 2) - return 1; - - pc_heal(sd, -sp, -hp); // [Fate] This might suppress some dupe messages - - if (zeny > 0) // Zeny消費 - pc_payzeny(sd, zeny); - if (spiritball > 0) // 氣球消費 - pc_delspiritball(sd, spiritball, 0); - - return 1; -} - -/*========================================== - * 詠唱時間計算 - *------------------------------------------ - */ -int skill_castfix(struct block_list *bl, int time) -{ - struct map_session_data *sd; - struct mob_data *md; // [Valaris] - eptr sc_data; - int dex; - int castrate = 100; - SkillID skill; - int lv, castnodex; - - nullpo_ret(bl); - - if (bl->type == BL_MOB) - { // Crash fix [Valaris] - md = (struct mob_data *) bl; - skill = md->skillid; - lv = md->skilllv; - } - - else - { - sd = (struct map_session_data *) bl; - skill = sd->skillid; - lv = sd->skilllv; - } - - sc_data = battle_get_sc_data(bl); - dex = battle_get_dex(bl); - - if (skill > MAX_SKILL_DB /*|| skill < SkillID()*/) - return 0; - - castnodex = skill_get_castnodex(skill, lv); - - if (time == 0) - return 0; - if (castnodex > 0 && bl->type == BL_PC) - castrate = ((struct map_session_data *) bl)->castrate; - else if (castnodex <= 0 && bl->type == BL_PC) - { - castrate = ((struct map_session_data *) bl)->castrate; - time = - time * castrate * (battle_config.castrate_dex_scale - - dex) / (battle_config.castrate_dex_scale * - 100); - time = time * battle_config.cast_rate / 100; - } - - return (time > 0) ? time : 0; -} - -/*========================================== - * ディレイ計算 - *------------------------------------------ - */ -int skill_delayfix(struct block_list *bl, int time) -{ - eptr sc_data; - - nullpo_ret(bl); - - sc_data = battle_get_sc_data(bl); - if (time <= 0) - return 0; - - if (bl->type == BL_PC) - { - if (battle_config.delay_dependon_dex) /* dexの影響を計算する */ - time = - time * (battle_config.castrate_dex_scale - - battle_get_dex(bl)) / - battle_config.castrate_dex_scale; - time = time * battle_config.delay_rate / 100; - } - - return (time > 0) ? time : 0; -} - -/*========================================== - * スキル使用(ID指定) - *------------------------------------------ - */ -int skill_use_id(struct map_session_data *sd, int target_id, - SkillID skill_num, int skill_lv) -{ - unsigned int tick; - int casttime = 0, delay = 0, range_; - int forcecast = 0; - struct block_list *bl; - eptr sc_data; - tick = gettick(); - - nullpo_ret(sd); - - if ((bl = map_id2bl(target_id)) == NULL) - { -/* if (battle_config.error_log) - PRINTF("skill target not found %d\n",target_id); */ - return 0; - } - if (sd->bl.m != bl->m || pc_isdead(sd)) - return 0; - - sc_data = sd->sc_data; - - /* 沈黙や異常(ただし、グリムなどの判定をする) */ - if (bool(sd->opt1)) - return 0; - - if (bool(sd->status.option & Option::HIDE2)) - return 0; - - if (skill_get_inf2(skill_num) & 0x200 && sd->bl.id == target_id) - return 0; - - sd->skillid = skill_num; - sd->skilllv = skill_lv; - - if (!skill_check_condition(sd, 0)) - return 0; - - /* 射程と障害物チェック */ - range_ = skill_get_range(skill_num, skill_lv); - if (range_ < 0) - range_ = battle_get_range(&sd->bl) - (range_ + 1); - if (!battle_check_range(&sd->bl, bl, range_)) - return 0; - - pc_stopattack(sd); - - casttime = skill_castfix(&sd->bl, skill_get_cast(skill_num, skill_lv)); - delay = skill_delayfix(&sd->bl, skill_get_delay(skill_num, skill_lv)); - sd->state.skillcastcancel = skill_db[skill_num].castcancel; - - if (battle_config.pc_skill_log) - PRINTF("PC %d skill use target_id=%d skill=%d lv=%d cast=%d\n", - sd->bl.id, target_id, skill_num, skill_lv, casttime); - - if (casttime > 0 || forcecast) - { /* 詠唱が必要 */ - struct mob_data *md; - - /* 詠唱反応モンスター */ - if (bl->type == BL_MOB && (md = (struct mob_data *) bl) - && bool(mob_db[md->mob_class].mode & MobMode::CAST_SENSOR) - && md->state.state != MS_ATTACK - && sd->invincible_timer == -1) - { - md->target_id = sd->bl.id; - md->state.attackable = true; - md->min_chase = 13; - } - } - - if (casttime <= 0) /* 詠唱の無いものはキャンセルされない */ - sd->state.skillcastcancel = 0; - - sd->skilltarget = target_id; - sd->skillx = 0; - sd->skilly = 0; - sd->canact_tick = tick + casttime + delay; - sd->canmove_tick = tick; - - if (casttime > 0) - { - sd->skilltimer = add_timer(tick + casttime, skill_castend_id, sd->bl.id, 0); - pc_stop_walking(sd, 0); - } - else - { - sd->skilltimer = -1; - skill_castend_id(sd->skilltimer, tick, sd->bl.id, 0); - } - - return 0; -} - -/*========================================== - * スキル使用(場所指定) - *------------------------------------------ - */ -int skill_use_pos(struct map_session_data *sd, - int skill_x, int skill_y, - SkillID skill_num, int skill_lv) -{ - struct block_list bl; - eptr sc_data; - unsigned int tick; - int casttime = 0, delay = 0, range; - - nullpo_ret(sd); - - if (pc_isdead(sd)) - return 0; - - sc_data = sd->sc_data; - - if (bool(sd->opt1)) - return 0; - - if (bool(sd->status.option & Option::HIDE2)) - return 0; - - sd->skillid = skill_num; - sd->skilllv = skill_lv; - sd->skillx = skill_x; - sd->skilly = skill_y; - if (!skill_check_condition(sd, 0)) - return 0; - - /* 射程と障害物チェック */ - bl.type = BL_NUL; - bl.m = sd->bl.m; - bl.x = skill_x; - bl.y = skill_y; - range = skill_get_range(skill_num, skill_lv); - if (range < 0) - range = battle_get_range(&sd->bl) - (range + 1); - if (!battle_check_range(&sd->bl, &bl, range)) - return 0; - - pc_stopattack(sd); - - casttime = skill_castfix(&sd->bl, skill_get_cast(skill_num, skill_lv)); - delay = skill_delayfix(&sd->bl, skill_get_delay(skill_num, skill_lv)); - sd->state.skillcastcancel = skill_db[skill_num].castcancel; - - if (battle_config.pc_skill_log) - PRINTF("PC %d skill use target_pos= (%d,%d) skill=%d lv=%d cast=%d\n", - sd->bl.id, skill_x, skill_y, - skill_num, skill_lv, casttime); - - if (casttime <= 0) /* 詠唱の無いものはキャンセルされない */ - sd->state.skillcastcancel = 0; - - sd->skilltarget = 0; - tick = gettick(); - sd->canact_tick = tick + casttime + delay; - sd->canmove_tick = tick; - - if (casttime > 0) - { - sd->skilltimer = add_timer(tick + casttime, skill_castend_pos, sd->bl.id, 0); - pc_stop_walking(sd, 0); - } - else - { - sd->skilltimer = -1; - skill_castend_pos(sd->skilltimer, tick, sd->bl.id, 0); - } - - return 0; -} - -/*========================================== - * スキル詠唱キャンセル - *------------------------------------------ - */ -int skill_castcancel(struct block_list *bl, int type) -{ - int inf; - - nullpo_ret(bl); - - if (bl->type == BL_PC) - { - struct map_session_data *sd = (struct map_session_data *) bl; - unsigned long tick = gettick(); - nullpo_ret(sd); - sd->canact_tick = tick; - sd->canmove_tick = tick; - if (sd->skilltimer != -1) - { - if (!type) - { - if ((inf = skill_get_inf(sd->skillid)) == 2 || inf == 32) - delete_timer(sd->skilltimer, skill_castend_pos); - else - delete_timer(sd->skilltimer, skill_castend_id); - } - else - { - if ((inf = skill_get_inf(sd->skillid_old)) == 2 || inf == 32) - delete_timer(sd->skilltimer, skill_castend_pos); - else - delete_timer(sd->skilltimer, skill_castend_id); - } - sd->skilltimer = -1; - clif_skillcastcancel(bl); - } - - return 0; - } - else if (bl->type == BL_MOB) - { - struct mob_data *md = (struct mob_data *) bl; - nullpo_ret(md); - if (md->skilltimer != -1) - { - if ((inf = skill_get_inf(md->skillid)) == 2 || inf == 32) - delete_timer(md->skilltimer, mobskill_castend_pos); - else - delete_timer(md->skilltimer, mobskill_castend_id); - md->skilltimer = -1; - clif_skillcastcancel(bl); - } - return 0; - } - return 1; -} - -/*========================================== - * ディボーション 有効確認 - *------------------------------------------ - */ -void skill_devotion(struct map_session_data *md, int) -{ - // 総確認 - int n; - - nullpo_retv(md); - - for (n = 0; n < 5; n++) - { - if (md->dev.val1[n]) - { - struct map_session_data *sd = map_id2sd(md->dev.val1[n]); - // 相手が見つからない // 相手をディボしてるのが自分じゃない // 距離が離れてる - if (sd == NULL - || (md->bl.id != 0/* was something else - TODO remove this */) - || skill_devotion3(&md->bl, md->dev.val1[n])) - { - skill_devotion_end(md, sd, n); - } - } - } -} - -void skill_devotion2(struct block_list *bl, int crusader) -{ - // 被ディボーションが歩いた時の距離チェック - struct map_session_data *sd = map_id2sd(crusader); - - nullpo_retv(bl); - - if (sd) - skill_devotion3(&sd->bl, bl->id); -} - -int skill_devotion3(struct block_list *bl, int target) -{ - // クルセが歩いた時の距離チェック - struct map_session_data *md; - struct map_session_data *sd; - int n, r = 0; - - nullpo_retr(1, bl); - - if ((md = (struct map_session_data *) bl) == NULL - || (sd = map_id2sd(target)) == NULL) - return 1; - else - r = distance(bl->x, bl->y, sd->bl.x, sd->bl.y); - - if ( + 6 < r) - { // 許容範囲を超えてた - for (n = 0; n < 5; n++) - if (md->dev.val1[n] == target) - md->dev.val2[n] = 0; // 離れた時は、糸を切るだけ - return 1; - } - return 0; -} - -void skill_devotion_end(struct map_session_data *md, - struct map_session_data *sd, int target) -{ - // クルセと被ディボキャラのリセット - nullpo_retv(md); - nullpo_retv(sd); - - md->dev.val1[target] = md->dev.val2[target] = 0; -} - -int skill_gangsterparadise(struct map_session_data *, int) -{ - return 0; -} - -/*========================================== - * ランドプロテクターチェック(foreachinarea) - *------------------------------------------ - */ -void skill_landprotector(struct block_list *, SkillID, int *) -{ -} - -/*========================================== - * イドゥンの林檎の回復処理(foreachinarea) - *------------------------------------------ - */ -static -void skill_idun_heal(struct block_list *bl, struct skill_unit *unit) -{ - struct skill_unit_group *sg; - int heal; - - nullpo_retv(bl); - nullpo_retv(unit); - nullpo_retv(sg = unit->group); - - heal = - 30 + sg->skill_lv * 5 + ((sg->val1) >> 16) * 5 + - ((sg->val1) & 0xfff) / 2; - - if (bl->type == BL_SKILL || bl->id == sg->src_id) - return; - - if (bl->type == BL_PC || bl->type == BL_MOB) - { - battle_heal(NULL, bl, heal, 0, 0); - } -} - -/*========================================== - * 指定範囲内でsrcに対して有効なターゲットのblの数を数える(foreachinarea) - *------------------------------------------ - */ -void skill_count_target(struct block_list *bl, - struct block_list *src, int *c) -{ - nullpo_retv(bl); - - if (src == NULL) - return; - if (c == NULL) - return; - if (battle_check_target(src, bl, BCT_ENEMY) > 0) - (*c)++; -} - -/*========================================== - * トラップ範囲処理(foreachinarea) - *------------------------------------------ - */ -void skill_trap_splash(struct block_list *bl, - struct block_list *src, int tick, int splash_count) -{ - struct skill_unit *unit; - struct skill_unit_group *sg; - struct block_list *ss; - int i; - - nullpo_retv(bl); - nullpo_retv(src); - unit = (struct skill_unit *) src; - nullpo_retv(sg = unit->group); - nullpo_retv(ss = map_id2bl(sg->src_id)); - - if (battle_check_target(src, bl, BCT_ENEMY) > 0) - { - switch (sg->unit_id) - { - case 0x95: /* サンドマン */ - case 0x96: /* フラッシャー */ - case 0x94: /* ショックウェーブトラップ */ - skill_additional_effect(ss, bl, sg->skill_id, sg->skill_lv, - BF_MISC, tick); - break; - case 0x8f: /* ブラストマイン */ - case 0x98: /* クレイモアートラップ */ - for (i = 0; i < splash_count; i++) - { - skill_attack(BF_MISC, ss, src, bl, sg->skill_id, - sg->skill_lv, tick, - (sg->val2) ? BCT_mid_x05 : BCT_ZERO); - } - // TODO: determine if this was supposed to break - FALLTHROUGH; - case 0x97: /* フリージングトラップ */ - skill_attack(BF_WEAPON, ss, src, bl, sg->skill_id, - sg->skill_lv, tick, (sg->val2) ? BCT_mid_x05 : BCT_ZERO); - break; - default: - break; - } - } -} - -/*---------------------------------------------------------------------------- - * ステータス異常 - *---------------------------------------------------------------------------- - */ - -/*========================================== - * ステータス異常タイマー範囲処理 - *------------------------------------------ - */ -void skill_status_change_timer_sub(struct block_list *bl, - struct block_list *src, StatusChange type, unsigned int) -{ - nullpo_retv(bl); - nullpo_retv(src); - - if (bl->type != BL_PC && bl->type != BL_MOB) - return; - - switch (type) - { - case SC_SIGHT: /* サイト */ - if (bool((*battle_get_option(bl)) & (Option::HIDE2 | Option::CLOAK))) - { - skill_status_change_end(bl, SC_HIDING, -1); - } - break; - } -} - -/*========================================== - * ステータス異常終了 - *------------------------------------------ - */ -int skill_status_change_active(struct block_list *bl, StatusChange type) -{ - eptr sc_data; - - nullpo_ret(bl); - if (bl->type != BL_PC && bl->type != BL_MOB) - { - if (battle_config.error_log) - PRINTF("skill_status_change_active: neither MOB nor PC !\n"); - return 0; - } - - sc_data = battle_get_sc_data(bl); - if (not sc_data) - return 0; - - return sc_data[type].timer != -1; -} - -int skill_status_change_end(struct block_list *bl, StatusChange type, int tid) -{ - eptr sc_data; - int opt_flag = 0, calc_flag = 0; - short *sc_count; - Option *option; - Opt1 *opt1; - Opt2 *opt2; - Opt3 *opt3; - - nullpo_ret(bl); - if (bl->type != BL_PC && bl->type != BL_MOB) - { - if (battle_config.error_log) - PRINTF("skill_status_change_end: neither MOB nor PC !\n"); - return 0; - } - sc_data = battle_get_sc_data(bl); - if (not sc_data) - return 0; - nullpo_ret(sc_count = battle_get_sc_count(bl)); - nullpo_ret(option = battle_get_option(bl)); - nullpo_ret(opt1 = battle_get_opt1(bl)); - nullpo_ret(opt2 = battle_get_opt2(bl)); - nullpo_ret(opt3 = battle_get_opt3(bl)); - - if ((*sc_count) > 0 && sc_data[type].timer != -1 - && (sc_data[type].timer == tid || tid == -1)) - { - - if (tid == -1) // タイマから呼ばれていないならタイマ削除をする - delete_timer(sc_data[type].timer, skill_status_change_timer); - - /* 該当の異常を正常に戻す */ - sc_data[type].timer = -1; - (*sc_count)--; - - switch (type) - { /* 異常の種類ごとの処理 */ - case SC_HIDING: - case SC_SPEEDPOTION0: /* 増速ポーション */ - case SC_ATKPOT: /* attack potion [Valaris] */ - case SC_MATKPOT: /* magic attack potion [Valaris] */ - case SC_PHYS_SHIELD: - case SC_HASTE: - calc_flag = 1; - break; - { - struct map_session_data *md = map_id2sd(sc_data[type].val1); - sc_data[type].val1 = sc_data[type].val2 = 0; - skill_devotion(md, bl->id); - calc_flag = 1; - } - break; - case SC_NOCHAT: //チャット禁止状態 - break; - case SC_SELFDESTRUCTION: /* 自爆 */ - { - //自分のダメージは0にして - struct mob_data *md = NULL; - if (bl->type == BL_MOB && (md = (struct mob_data *) bl)) - skill_castend_damage_id(bl, bl, - SkillID( sc_data[type].val2), sc_data[type].val1, - gettick(), BCT_ZERO); - } - break; - /* option1 */ - case SC_FREEZE: - sc_data[type].val3 = 0; - break; - - /* option2 */ - case SC_POISON: /* 毒 */ - case SC_BLIND: /* 暗黒 */ - case SC_CURSE: - calc_flag = 1; - break; - } - - if (bl->type == BL_PC && type < SC_SENDMAX) - clif_status_change(bl, type, 0); /* アイコン消去 */ - - switch (type) - { /* 正常に戻るときなにか処理が必要 */ - case SC_STONE: - case SC_FREEZE: - case SC_STAN: - case SC_SLEEP: - *opt1 = Opt1::ZERO; - opt_flag = 1; - break; - - case SC_POISON: - *opt2 &= ~Opt2::_poison; - opt_flag = 1; - break; - - case SC_CURSE: - *opt2 &= ~Opt2::_curse; - opt_flag = 1; - break; - - case SC_SILENCE: - *opt2 &= ~Opt2::_silence; - opt_flag = 1; - break; - - case SC_BLIND: - *opt2 &= ~Opt2::BLIND; - opt_flag = 1; - break; - - case SC_SLOWPOISON: - if (sc_data[SC_POISON].timer != -1) - *opt2 |= Opt2::_poison; - *opt2 &= ~Opt2::_slowpoison; - opt_flag = 1; - break; - - case SC_SPEEDPOTION0: - *opt2 &= ~Opt2::_speedpotion0; - opt_flag = 1; - break; - - case SC_ATKPOT: - *opt2 &= ~Opt2::_atkpot; - opt_flag = 1; - break; - - case SC_HIDING: - *option &= ~Option::HIDE2; - opt_flag = 1; - break; - - case SC_SIGHT: - *option &= ~Option::SIGHT; - opt_flag = 1; - break; - } - - if (night_flag == 1 - && !bool(*opt2 & Opt2::BLIND) - && bl->type == BL_PC) - { // by [Yor] - *opt2 |= Opt2::BLIND; - opt_flag = 1; - } - - if (opt_flag) /* optionの変更を伝える */ - clif_changeoption(bl); - - if (bl->type == BL_PC && calc_flag) - pc_calcstatus((struct map_session_data *) bl, 0); /* ステータス再計算 */ - } - - return 0; -} - -int skill_update_heal_animation(struct map_session_data *sd) -{ - const Opt2 mask = Opt2::_heal; - - nullpo_ret(sd); - bool was_active = bool(sd->opt2 & mask); - bool is_active = sd->quick_regeneration_hp.amount > 0; - - if (was_active == is_active) - return 0; // no update - - if (is_active) - sd->opt2 |= mask; - else - sd->opt2 &= ~mask; - - return clif_changeoption(&sd->bl); -} - -/*========================================== - * ステータス異常終了タイマー - *------------------------------------------ - */ -void skill_status_change_timer(timer_id tid, tick_t tick, custom_id_t id, custom_data_t data) -{ - StatusChange type = StatusChange(data); - struct block_list *bl; - struct map_session_data *sd = NULL; - eptr sc_data; - //short *sc_count; //使ってない? - - if ((bl = map_id2bl(id)) == NULL) - return; - //該当IDがすでに消滅しているというのはいかにもありそうなのでスルーしてみる - sc_data = battle_get_sc_data(bl); - if (not sc_data) - return; - - if (bl->type == BL_PC) - sd = (struct map_session_data *) bl; - - //sc_count=battle_get_sc_count(bl); //使ってない? - - if (sc_data[type].timer != tid) - { - if (battle_config.error_log) - PRINTF("skill_status_change_timer %d != %d\n", tid, - sc_data[type].timer); - } - - if (sc_data[type].spell_invocation) - { // Must report termination - spell_effect_report_termination(sc_data[type].spell_invocation, - bl->id, type, 0); - sc_data[type].spell_invocation = 0; - } - - switch (type) - { /* 特殊な処理になる場合 */ - case SC_HIDING: /* ハイディング */ - if (sd) - { /* SPがあって、時間制限の間は持続 */ - if (sd->status.sp > 0 && (--sc_data[type].val2) > 0) - { - if (sc_data[type].val2 % (sc_data[type].val1 + 3) == 0) - { - sd->status.sp--; - clif_updatestatus(sd, SP_SP); - } - sc_data[type].timer = add_timer( /* タイマー再設定 */ - 1000 + tick, - skill_status_change_timer, - bl->id, data); - return; - } - } - break; - - case SC_SIGHT: /* サイト */ - { - const int range = 7; - map_foreachinarea(std::bind(skill_status_change_timer_sub, ph::_1, bl, type, tick), - bl->m, bl->x - range, bl->y - range, - bl->x + range, bl->y + range, BL_NUL); - - if ((--sc_data[type].val2) > 0) - { - sc_data[type].timer = add_timer( /* タイマー再設定 */ - 250 + tick, - skill_status_change_timer, - bl->id, data); - return; - } - } - break; - - case SC_STONE: - if (sc_data[type].val2 != 0) - { - Opt1 *opt1 = battle_get_opt1(bl); - sc_data[type].val2 = 0; - sc_data[type].val4 = 0; - battle_stopwalking(bl, 1); - if (opt1) - { - *opt1 = Opt1::_stone1; - clif_changeoption(bl); - } - sc_data[type].timer = - add_timer(1000 + tick, skill_status_change_timer, bl->id, - data); - return; - } - else if ((--sc_data[type].val3) > 0) - { - int hp = battle_get_max_hp(bl); - if ((++sc_data[type].val4) % 5 == 0 - && battle_get_hp(bl) > hp >> 2) - { - hp = hp / 100; - if (hp < 1) - hp = 1; - if (bl->type == BL_PC) - pc_heal((struct map_session_data *) bl, -hp, 0); - else if (bl->type == BL_MOB) - { - struct mob_data *md; - if ((md = ((struct mob_data *) bl)) == NULL) - break; - md->hp -= hp; - } - } - sc_data[type].timer = - add_timer(1000 + tick, skill_status_change_timer, bl->id, - data); - return; - } - break; - case SC_POISON: - if (sc_data[SC_SLOWPOISON].timer == -1) - { - const int resist_poison = - skill_power_bl(bl, TMW_RESIST_POISON) >> 3; - if (resist_poison) - sc_data[type].val1 -= MRAND(resist_poison + 1); - - if ((--sc_data[type].val1) > 0) - { - - int hp = battle_get_max_hp(bl); - if (battle_get_hp(bl) > hp >> 4) - { - if (bl->type == BL_PC) - { - hp = 3 + hp * 3 / 200; - pc_heal((struct map_session_data *) bl, -hp, 0); - } - else if (bl->type == BL_MOB) - { - struct mob_data *md; - if ((md = ((struct mob_data *) bl)) == NULL) - break; - hp = 3 + hp / 200; - md->hp -= hp; - } - } - sc_data[type].timer = - add_timer(1000 + tick, skill_status_change_timer, - bl->id, data); - } - } - else - sc_data[type].timer = - add_timer(2000 + tick, skill_status_change_timer, bl->id, - data); - break; - - /* 時間切れ無し?? */ - case SC_WEIGHT50: - case SC_WEIGHT90: - case SC_BROKNWEAPON: - case SC_BROKNARMOR: - if (sc_data[type].timer == tid) - sc_data[type].timer = - add_timer(1000 * 600 + tick, skill_status_change_timer, - bl->id, data); - return; - - case SC_NOCHAT: //チャット禁止状態 - if (sd && battle_config.muting_players) - { - time_t timer; - if ((++sd->status.manner) - && time(&timer) < - ((sc_data[type].val2) + 60 * (0 - sd->status.manner))) - { //開始からstatus.manner分経ってないので継続 - sc_data[type].timer = add_timer( /* タイマー再設定(60秒) */ - 60000 + tick, - skill_status_change_timer, - bl->id, data); - return; - } - } - break; - case SC_SELFDESTRUCTION: /* 自爆 */ - if (--sc_data[type].val3 > 0) - { - struct mob_data *md; - if (bl->type == BL_MOB && (md = (struct mob_data *) bl) - && md->stats[MOB_SPEED] > 250) - { - md->stats[MOB_SPEED] -= 250; - md->next_walktime = tick; - } - sc_data[type].timer = add_timer( /* タイマー再設定 */ - 1000 + tick, - skill_status_change_timer, - bl->id, data); - return; - } - break; - - case SC_FLYING_BACKPACK: - clif_updatestatus(sd, SP_WEIGHT); - break; - - } - - skill_status_change_end(bl, type, tid); -} - -/*========================================== - * ステータス異常開始 - *------------------------------------------ - */ -int skill_status_change_start(struct block_list *bl, StatusChange type, - int val1, int val2, int val3, int val4, - int tick, int flag) -{ - return skill_status_effect(bl, type, val1, val2, val3, val4, tick, flag, - 0); -} - -int skill_status_effect(struct block_list *bl, StatusChange type, - int val1, int val2, int val3, int val4, - int tick, int flag, int spell_invocation) -{ - struct map_session_data *sd = NULL; - eptr sc_data; - short *sc_count; - Option *option; - Opt1 *opt1; - Opt2 *opt2; - Opt3 *opt3; - int opt_flag = 0, calc_flag = 0; - int race, elem, undead_flag; - SP updateflag = SP::ZERO; - int scdef = 0; - - nullpo_ret(bl); - if (bl->type == BL_SKILL) - return 0; - sc_data = battle_get_sc_data(bl); - if (not sc_data) - return 0; - nullpo_ret(sc_count = battle_get_sc_count(bl)); - nullpo_ret(option = battle_get_option(bl)); - nullpo_ret(opt1 = battle_get_opt1(bl)); - nullpo_ret(opt2 = battle_get_opt2(bl)); - nullpo_ret(opt3 = battle_get_opt3(bl)); - - race = battle_get_race(bl); - MobMode mode = battle_get_mode(bl); - elem = battle_get_elem_type(bl); - undead_flag = battle_check_undead(race, elem); - - switch (type) - { - case SC_STONE: - case SC_FREEZE: - scdef = 3 + battle_get_mdef(bl) + battle_get_luk(bl) / 3; - break; - case SC_STAN: - case SC_SILENCE: - case SC_POISON: - scdef = 3 + battle_get_vit(bl) + battle_get_luk(bl) / 3; - break; - case SC_SLEEP: - case SC_BLIND: - scdef = 3 + battle_get_int(bl) + battle_get_luk(bl) / 3; - break; - case SC_CURSE: - scdef = 3 + battle_get_luk(bl); - break; - -// case SC_CONFUSION: - default: - scdef = 0; - } - if (scdef >= 100) - return 0; - if (bl->type == BL_PC) - { - sd = (struct map_session_data *) bl; - - if (SC_STONE <= type && type <= SC_BLIND) - { - BadSC bsc = BadSC_from_SC(type); - /* カードによる耐性 */ - if (sd && sd->reseff[bsc] > 0 - && MRAND(10000) < sd->reseff[bsc]) - { - if (battle_config.battle_log) - PRINTF("PC %d skill_sc_start: cardによる異常耐性発動\n", - sd->bl.id); - return 0; - } - } - } - else if (bl->type == BL_MOB) - { - } - else - { - if (battle_config.error_log) - PRINTF("skill_status_change_start: neither MOB nor PC !\n"); - return 0; - } - - if (type == SC_FREEZE && undead_flag && !(flag & 1)) - return 0; - - if (bool(mode & MobMode::BOSS) - && (type == SC_STONE - || type == SC_FREEZE - || type == SC_STAN - || type == SC_SLEEP - || type == SC_SILENCE - ) - && !(flag & 1)) - { - /* ボスには効かない(ただしカードによる効果は適用される) */ - return 0; - } - if (type == SC_FREEZE || type == SC_STAN || type == SC_SLEEP) - battle_stopwalking(bl, 1); - - if (sc_data[type].timer != -1) - { /* すでに同じ異常になっている場合タイマ解除 */ - if (sc_data[type].val1 > val1 - && type != SC_SPEEDPOTION0 - && type != SC_ATKPOT - && type != SC_MATKPOT) // added atk and matk potions [Valaris] - return 0; - if (type >= SC_STAN && type <= SC_BLIND) - return 0; /* 継ぎ足しができない状態異常である時は状態異常を行わない */ - { - (*sc_count)--; - delete_timer(sc_data[type].timer, skill_status_change_timer); - sc_data[type].timer = -1; - } - } - - switch (type) - { /* 異常の種類ごとの処理 */ - case SC_SLOWPOISON: - if (sc_data[SC_POISON].timer == -1) - return 0; - break; - - case SC_SPEEDPOTION0: /* 増速ポーション */ - *opt2 |= Opt2::_speedpotion0; - calc_flag = 1; - tick = 1000 * tick; -// val2 = 5*(2+type-SC_SPEEDPOTION0); - break; - - /* atk & matk potions [Valaris] */ - case SC_ATKPOT: - *opt2 |= Opt2::_atkpot; - FALLTHROUGH; - case SC_MATKPOT: - calc_flag = 1; - tick = 1000 * tick; - break; - - case SC_NOCHAT: //チャット禁止状態 - { - time_t timer; - - if (!battle_config.muting_players) - break; - - tick = 60000; - if (!val2) - val2 = time(&timer); - // updateflag = SP_MANNER; - } - break; - case SC_SELFDESTRUCTION: //自爆 - val3 = tick / 1000; - tick = 1000; - break; - - /* option1 */ - case SC_STONE: /* 石化 */ - if (!(flag & 2)) - { - int sc_def = battle_get_mdef(bl) * 200; - tick = tick - sc_def; - } - val3 = tick / 1000; - if (val3 < 1) - val3 = 1; - tick = 5000; - val2 = 1; - break; - case SC_SLEEP: /* 睡眠 */ - if (!(flag & 2)) - { -// int sc_def = 100 - (battle_get_int(bl) + battle_get_luk(bl)/3); -// tick = tick * sc_def / 100; -// if(tick < 1000) tick = 1000; - tick = 30000; //睡眠はステータス耐性に関わらず30秒 - } - break; - case SC_FREEZE: /* 凍結 */ - if (!(flag & 2)) - { - int sc_def = 100 - battle_get_mdef(bl); - tick = tick * sc_def / 100; - } - break; - case SC_STAN: /* スタン(val2にミリ秒セット) */ - if (!(flag & 2)) - { - int sc_def = - 100 - (battle_get_vit(bl) + battle_get_luk(bl) / 3); - tick = tick * sc_def / 100; - } - break; - - /* option2 */ - case SC_POISON: /* 毒 */ - calc_flag = 1; - if (!(flag & 2)) - { - int sc_def = - 100 - (battle_get_vit(bl) + battle_get_luk(bl) / 5); - tick = tick * sc_def / 100; - } - val3 = tick / 1000; - if (val3 < 1) - val3 = 1; - tick = 1000; - break; - case SC_SILENCE: /* 沈黙(レックスデビーナ) */ - if (!(flag & 2)) - { - int sc_def = 100 - battle_get_vit(bl); - tick = tick * sc_def / 100; - } - break; - case SC_BLIND: /* 暗黒 */ - calc_flag = 1; - if (!(flag & 2)) - { - int sc_def = - battle_get_lv(bl) / 10 + battle_get_int(bl) / 15; - tick = 30000 - sc_def; - } - break; - case SC_CURSE: - calc_flag = 1; - if (!(flag & 2)) - { - int sc_def = 100 - battle_get_vit(bl); - tick = tick * sc_def / 100; - } - break; - - /* option */ - case SC_HIDING: /* ハイディング */ - calc_flag = 1; - if (bl->type == BL_PC) - { - val2 = tick / 1000; /* 持続時間 */ - tick = 1000; - } - break; - - case SC_SIGHT: /* サイト/ルアフ */ - val2 = tick / 250; - tick = 10; - break; - - /* セーフティウォール、ニューマ */ - case SC_SAFETYWALL: - case SC_PNEUMA: - tick = ((struct skill_unit *) val2)->group->limit; - break; - - /* アンクル */ - case SC_ANKLE: - break; - - case SC_WEIGHT50: - case SC_WEIGHT90: - case SC_BROKNWEAPON: - case SC_BROKNARMOR: - tick = 600 * 1000; - break; - - case SC_HASTE: - calc_flag = 1; - break; - case SC_PHYS_SHIELD: - case SC_MBARRIER: - case SC_HALT_REGENERATE: - case SC_HIDE: - break; - case SC_FLYING_BACKPACK: - updateflag = SP_WEIGHT; - break; - default: - if (battle_config.error_log) - PRINTF("UnknownStatusChange [%d]\n", type); - return 0; - } - - if (bl->type == BL_PC && type < SC_SENDMAX) - clif_status_change(bl, type, 1); /* アイコン表示 */ - - /* optionの変更 */ switch (type) - { + { /* 特殊な処理になる場合 */ case SC_STONE: - case SC_FREEZE: - case SC_STAN: - case SC_SLEEP: - battle_stopattack(bl); /* 攻撃停止 */ - skill_stop_dancing(bl, 0); /* 演奏/ダンスの中断 */ - /* 同時に掛からないステータス異常を解除 */ - for (StatusChange i : MAJOR_STATUS_EFFECTS_1) + if (sc_data[type].val2 != 0) { - if (sc_data[i].timer != -1) + Opt1 *opt1 = battle_get_opt1(bl); + sc_data[type].val2 = 0; + sc_data[type].val4 = 0; + battle_stopwalking(bl, 1); + if (opt1) { - (*sc_count)--; - delete_timer(sc_data[i].timer, - skill_status_change_timer); - sc_data[i].timer = -1; + *opt1 = Opt1::_stone1; + clif_changeoption(bl); } + sc_data[type].timer = + add_timer(1000 + tick, skill_status_change_timer, bl->id, + data); + return; } - switch (type) + else if ((--sc_data[type].val3) > 0) { - case SC_STONE: *opt1 = Opt1::_stone6; break; - case SC_FREEZE: *opt1 = Opt1::_freeze; break; - case SC_STAN: *opt1 = Opt1::_stan; break; - case SC_SLEEP: *opt1 = Opt1::_sleep; break; + int hp = battle_get_max_hp(bl); + if ((++sc_data[type].val4) % 5 == 0 + && battle_get_hp(bl) > hp >> 2) + { + hp = hp / 100; + if (hp < 1) + hp = 1; + if (bl->type == BL_PC) + pc_heal((struct map_session_data *) bl, -hp, 0); + else if (bl->type == BL_MOB) + { + struct mob_data *md; + if ((md = ((struct mob_data *) bl)) == NULL) + break; + md->hp -= hp; + } + } + sc_data[type].timer = + add_timer(1000 + tick, skill_status_change_timer, bl->id, + data); + return; } - opt_flag = 1; break; case SC_POISON: if (sc_data[SC_SLOWPOISON].timer == -1) { - *opt2 |= Opt2::_poison; - opt_flag = 1; - } - break; + const int resist_poison = + skill_power_bl(bl, TMW_RESIST_POISON) >> 3; + if (resist_poison) + sc_data[type].val1 -= MRAND(resist_poison + 1); - case SC_CURSE: - *opt2 |= Opt2::_curse; - opt_flag = 1; - break; - case SC_SILENCE: - *opt2 |= Opt2::_silence; - opt_flag = 1; - break; - case SC_BLIND: - *opt2 |= Opt2::BLIND; - opt_flag = 1; - break; + if ((--sc_data[type].val1) > 0) + { - case SC_SLOWPOISON: - *opt2 &= ~Opt2::_poison; - *opt2 |= Opt2::_slowpoison; - opt_flag = 1; - break; - case SC_HIDING: - battle_stopattack(bl); /* 攻撃停止 */ - *option |= Option::HIDE2; - opt_flag = 1; - break; - case SC_SIGHT: - *option |= Option::SIGHT; - opt_flag = 1; + int hp = battle_get_max_hp(bl); + if (battle_get_hp(bl) > hp >> 4) + { + if (bl->type == BL_PC) + { + hp = 3 + hp * 3 / 200; + pc_heal((struct map_session_data *) bl, -hp, 0); + } + else if (bl->type == BL_MOB) + { + struct mob_data *md; + if ((md = ((struct mob_data *) bl)) == NULL) + break; + hp = 3 + hp / 200; + md->hp -= hp; + } + } + sc_data[type].timer = + add_timer(1000 + tick, skill_status_change_timer, + bl->id, data); + } + } + else + sc_data[type].timer = + add_timer(2000 + tick, skill_status_change_timer, bl->id, + data); break; - } - - if (opt_flag) /* optionの変更 */ - clif_changeoption(bl); - - (*sc_count)++; /* ステータス異常の数 */ - - sc_data[type].val1 = val1; - sc_data[type].val2 = val2; - sc_data[type].val3 = val3; - sc_data[type].val4 = val4; - if (sc_data[type].spell_invocation) // Supplant by newer spell - spell_effect_report_termination(sc_data[type].spell_invocation, - bl->id, type, 1); - - sc_data[type].spell_invocation = spell_invocation; - - /* タイマー設定 */ - sc_data[type].timer = - add_timer(gettick() + tick, skill_status_change_timer, bl->id, - custom_data_t(type)); - - if (bl->type == BL_PC && calc_flag) - pc_calcstatus(sd, 0); /* ステータス再計算 */ - - if (bl->type == BL_PC && updateflag != SP::ZERO) - clif_updatestatus(sd, updateflag); /* ステータスをクライアントに送る */ - - return 0; -} - -/*========================================== - * ステータス異常全解除 - *------------------------------------------ - */ -int skill_status_change_clear(struct block_list *bl, int type) -{ - eptr sc_data; - short *sc_count; - Option *option; - Opt1 *opt1; - Opt2 *opt2; - Opt3 *opt3; - - nullpo_ret(bl); - sc_data = battle_get_sc_data(bl); - if (not sc_data) - return 0; - nullpo_ret(sc_count = battle_get_sc_count(bl)); - nullpo_ret(option = battle_get_option(bl)); - nullpo_ret(opt1 = battle_get_opt1(bl)); - nullpo_ret(opt2 = battle_get_opt2(bl)); - nullpo_ret(opt3 = battle_get_opt3(bl)); - - if (*sc_count == 0) - return 0; - for (StatusChange i : erange(StatusChange(), MAX_STATUSCHANGE)) - { - if (sc_data[i].timer != -1) - { - skill_status_change_end(bl, i, -1); - } - } - *sc_count = 0; - *opt1 = Opt1::ZERO; - *opt2 = Opt2::ZERO; - *opt3 = Opt3::ZERO; - *option &= Option::MASK; - - if (night_flag == 1 && type == 1) // by [Yor] - *opt2 |= Opt2::BLIND; - - if (type == 0 || type & 2) - clif_changeoption(bl); - - return 0; -} - -/* クローキング検査(周りに移動不可能地帯があるか) */ -int skill_check_cloaking(struct block_list *bl) -{ - static int dx[] = { -1, 0, 1, -1, 1, -1, 0, 1 }; - static int dy[] = { -1, -1, -1, 0, 0, 1, 1, 1 }; - int end = 1, i; - - nullpo_ret(bl); - - if (bl->type == BL_PC && battle_config.pc_cloak_check_type & 1) - return 0; - if (bl->type == BL_MOB && battle_config.monster_cloak_check_type & 1) - return 0; - for (i = 0; i < sizeof(dx) / sizeof(dx[0]); i++) - { - int c = map_getcell(bl->m, bl->x + dx[i], bl->y + dy[i]); - if (c == 1 || c == 5) - end = 0; - } - if (end) - { - *battle_get_option(bl) &= ~Option::CLOAK; /* 念のための処理 */ - } - return end; -} - -/* - *---------------------------------------------------------------------------- - * スキルユニット - *---------------------------------------------------------------------------- - */ - -/*========================================== - * 演奏/ダンスをやめる - * flag 1で合奏中なら相方にユニットを任せる - * - *------------------------------------------ - */ -void skill_stop_dancing(struct block_list *, int) -{ - // TODO remove this -} - -/*========================================== - * スキルユニット初期化 - *------------------------------------------ - */ -struct skill_unit *skill_initunit(struct skill_unit_group *group, int idx, - int x, int y) -{ - struct skill_unit *unit; - - nullpo_retr(NULL, group); - nullpo_retr(NULL, unit = &group->unit[idx]); - - if (!unit->alive) - group->alive_count++; - - unit->bl.id = map_addobject(&unit->bl); - unit->bl.type = BL_SKILL; - unit->bl.m = group->map; - unit->bl.x = x; - unit->bl.y = y; - unit->group = group; - unit->val1 = unit->val2 = 0; - unit->alive = 1; - - map_addblock(&unit->bl); - return unit; -} - -void skill_unit_timer_sub_ondelete(struct block_list *bl, - struct block_list *src, unsigned int tick); -/*========================================== - * スキルユニット削除 - *------------------------------------------ - */ -int skill_delunit(struct skill_unit *unit) -{ - struct skill_unit_group *group; - int range; - - nullpo_ret(unit); - if (!unit->alive) - return 0; - nullpo_ret(group = unit->group); - - /* onlimitイベント呼び出し */ - skill_unit_onlimit(unit, gettick()); - - /* ondeleteイベント呼び出し */ - range = group->range; - map_foreachinarea(std::bind(skill_unit_timer_sub_ondelete, ph::_1, &unit->bl, gettick()), - unit->bl.m, unit->bl.x - range, unit->bl.y - range, - unit->bl.x + range, unit->bl.y + range, BL_NUL); - - unit->group = NULL; - unit->alive = 0; - map_delobjectnofree(unit->bl.id, BL_SKILL); - if (group->alive_count > 0 && (--group->alive_count) <= 0) - skill_delunitgroup(group); - - return 0; -} - -/*========================================== - * スキルユニットグループ初期化 - *------------------------------------------ - */ -static -int skill_unit_group_newid = 10; -struct skill_unit_group *skill_initunitgroup(struct block_list *src, - int count, SkillID skillid, int skilllv, int unit_id) -{ - int i; - struct skill_unit_group *group = NULL, *list = NULL; - int maxsug = 0; - nullpo_retr(NULL, src); + /* 時間切れ無し?? */ + case SC_WEIGHT50: + case SC_WEIGHT90: + case SC_BROKNWEAPON: + case SC_BROKNARMOR: + if (sc_data[type].timer == tid) + sc_data[type].timer = + add_timer(1000 * 600 + tick, skill_status_change_timer, + bl->id, data); + return; - if (src->type == BL_PC) - { - list = ((struct map_session_data *) src)->skillunit; - maxsug = MAX_SKILLUNITGROUP; - } - else if (src->type == BL_MOB) - { - list = ((struct mob_data *) src)->skillunit; - maxsug = MAX_MOBSKILLUNITGROUP; - } - if (list) - { - for (i = 0; i < maxsug; i++) /* 空いているもの検索 */ - if (list[i].group_id == 0) + case SC_NOCHAT: //チャット禁止状態 + if (sd && battle_config.muting_players) { - group = &list[i]; - break; + time_t timer; + if ((++sd->status.manner) + && time(&timer) < + ((sc_data[type].val2) + 60 * (0 - sd->status.manner))) + { //開始からstatus.manner分経ってないので継続 + sc_data[type].timer = add_timer( /* タイマー再設定(60秒) */ + 60000 + tick, + skill_status_change_timer, + bl->id, data); + return; + } } - - if (group == NULL) - { /* 空いてないので古いもの検索 */ - int j = 0; - unsigned maxdiff = 0, x, tick = gettick(); - for (i = 0; i < maxsug; i++) - if ((x = DIFF_TICK(tick, list[i].tick)) > maxdiff) + break; + case SC_SELFDESTRUCTION: /* 自爆 */ + if (--sc_data[type].val3 > 0) + { + struct mob_data *md; + if (bl->type == BL_MOB && (md = (struct mob_data *) bl) + && md->stats[MOB_SPEED] > 250) { - maxdiff = x; - j = i; + md->stats[MOB_SPEED] -= 250; + md->next_walktime = tick; } - skill_delunitgroup(&list[j]); - group = &list[j]; - } - } - - if (group == NULL) - { - PRINTF("skill_initunitgroup: error unit group !\n"); - exit(1); - } - - group->src_id = src->id; - group->party_id = battle_get_party_id(src); - group->group_id = skill_unit_group_newid++; - if (skill_unit_group_newid <= 0) - skill_unit_group_newid = 10; - CREATE(group->unit, struct skill_unit, count); - group->unit_count = count; - group->val1 = group->val2 = 0; - group->skill_id = skillid; - group->skill_lv = skilllv; - group->unit_id = unit_id; - group->map = src->m; - group->range = 0; - group->limit = 10000; - group->interval = 1000; - group->tick = gettick(); - group->valstr = NULL; - - return group; -} - -/*========================================== - * スキルユニットグループ削除 - *------------------------------------------ - */ -int skill_delunitgroup(struct skill_unit_group *group) -{ - int i; + sc_data[type].timer = add_timer( /* タイマー再設定 */ + 1000 + tick, + skill_status_change_timer, + bl->id, data); + return; + } + break; - nullpo_ret(group); - if (group->unit_count <= 0) - return 0; + case SC_FLYING_BACKPACK: + clif_updatestatus(sd, SP_WEIGHT); + break; - group->alive_count = 0; - if (group->unit != NULL) - { - for (i = 0; i < group->unit_count; i++) - if (group->unit[i].alive) - skill_delunit(&group->unit[i]); - } - if (group->valstr != NULL) - { - map_freeblock(group->valstr); - group->valstr = NULL; } - map_freeblock(group->unit); /* free()の替わり */ - group->unit = NULL; - group->src_id = 0; - group->group_id = 0; - group->unit_count = 0; - return 0; + skill_status_change_end(bl, type, tid); } /*========================================== - * スキルユニットグループ全削除 + * ステータス異常開始 *------------------------------------------ */ -int skill_clear_unitgroup(struct block_list *src) +int skill_status_change_start(struct block_list *bl, StatusChange type, + int val1, int val2, int val3, int val4, + int tick, int flag) { - struct skill_unit_group *group = NULL; - int maxsug = 0; - - nullpo_ret(src); - - if (src->type == BL_PC) - { - group = ((struct map_session_data *) src)->skillunit; - maxsug = MAX_SKILLUNITGROUP; - } - else if (src->type == BL_MOB) - { - group = ((struct mob_data *) src)->skillunit; - maxsug = MAX_MOBSKILLUNITGROUP; - } - if (group) - { - int i; - for (i = 0; i < maxsug; i++) - if (group[i].group_id > 0 && group[i].src_id == src->id) - skill_delunitgroup(&group[i]); - } - return 0; + return skill_status_effect(bl, type, val1, val2, val3, val4, tick, flag, + 0); } -/*========================================== - * スキルユニットグループの被影響tick検索 - *------------------------------------------ - */ -struct skill_unit_group_tickset *skill_unitgrouptickset_search( - struct block_list *bl, int group_id) +int skill_status_effect(struct block_list *bl, StatusChange type, + int val1, int val2, int val3, int val4, + int tick, int flag, int spell_invocation) { - int i, j = 0, k, s = group_id % MAX_SKILLUNITGROUPTICKSET; - struct skill_unit_group_tickset *set = NULL; + struct map_session_data *sd = NULL; + eptr sc_data; + short *sc_count; + Option *option; + Opt1 *opt1; + Opt2 *opt2; + Opt3 *opt3; + int opt_flag = 0, calc_flag = 0; + int undead_flag; + SP updateflag = SP::ZERO; + int scdef = 0; nullpo_ret(bl); + sc_data = battle_get_sc_data(bl); + if (not sc_data) + return 0; + sc_count = battle_get_sc_count(bl); + nullpo_ret(sc_count); + option = battle_get_option(bl); + nullpo_ret(option); + opt1 = battle_get_opt1(bl); + nullpo_ret(opt1); + opt2 = battle_get_opt2(bl); + nullpo_ret(opt2); + opt3 = battle_get_opt3(bl); + nullpo_ret(opt3); + + Race race = battle_get_race(bl); + MobMode mode = battle_get_mode(bl); + Element elem = battle_get_elem_type(bl); + undead_flag = battle_check_undead(race, elem); - if (bl->type == BL_PC) - { - set = ((struct map_session_data *) bl)->skillunittick; - } - else + switch (type) { - set = ((struct mob_data *) bl)->skillunittick; + case SC_STONE: + case SC_FREEZE: + scdef = 3 + battle_get_mdef(bl) + battle_get_luk(bl) / 3; + break; + case SC_STAN: + case SC_SILENCE: + case SC_POISON: + scdef = 3 + battle_get_vit(bl) + battle_get_luk(bl) / 3; + break; + case SC_SLEEP: + case SC_BLIND: + scdef = 3 + battle_get_int(bl) + battle_get_luk(bl) / 3; + break; + case SC_CURSE: + scdef = 3 + battle_get_luk(bl); + break; + +// case SC_CONFUSION: + default: + scdef = 0; } - if (set == NULL) + if (scdef >= 100) return 0; - for (i = 0; i < MAX_SKILLUNITGROUPTICKSET; i++) - if (set[(k = (i + s) % MAX_SKILLUNITGROUPTICKSET)].group_id == - group_id) - return &set[k]; - else if (set[k].group_id == 0) - j = k; - - return &set[j]; -} - -/*========================================== - * スキルユニットグループの被影響tick削除 - *------------------------------------------ - */ -int skill_unitgrouptickset_delete(struct block_list *bl, int group_id) -{ - int i, s = group_id % MAX_SKILLUNITGROUPTICKSET; - struct skill_unit_group_tickset *set = NULL, *ts; - - nullpo_ret(bl); - if (bl->type == BL_PC) { - set = ((struct map_session_data *) bl)->skillunittick; + sd = (struct map_session_data *) bl; } - else + else if (bl->type == BL_MOB) { - set = ((struct mob_data *) bl)->skillunittick; } - - if (set != NULL) + else { + if (battle_config.error_log) + PRINTF("skill_status_change_start: neither MOB nor PC !\n"); + return 0; + } - for (i = 0; i < MAX_SKILLUNITGROUPTICKSET; i++) - if ((ts = - &set[(i + s) % MAX_SKILLUNITGROUPTICKSET])->group_id == - group_id) - ts->group_id = 0; + if (type == SC_FREEZE && undead_flag && !(flag & 1)) + return 0; + if (bool(mode & MobMode::BOSS) + && (type == SC_STONE + || type == SC_FREEZE + || type == SC_STAN + || type == SC_SLEEP + || type == SC_SILENCE + ) + && !(flag & 1)) + { + /* ボスには効かない(ただしカードによる効果は適用される) */ + return 0; } - return 0; -} + if (type == SC_FREEZE || type == SC_STAN || type == SC_SLEEP) + battle_stopwalking(bl, 1); -/*========================================== - * スキルユニットタイマー発動処理用(foreachinarea) - *------------------------------------------ - */ -static -void skill_unit_timer_sub_onplace(struct block_list *bl, - struct block_list *src, unsigned int tick) -{ - struct skill_unit *su; + if (sc_data[type].timer != -1) + { /* すでに同じ異常になっている場合タイマ解除 */ + if (sc_data[type].val1 > val1 + && type != SC_SPEEDPOTION0 + && type != SC_ATKPOT + && type != SC_MATKPOT) // added atk and matk potions [Valaris] + return 0; + if (type >= SC_STAN && type <= SC_BLIND) + return 0; /* 継ぎ足しができない状態異常である時は状態異常を行わない */ + { + (*sc_count)--; + delete_timer(sc_data[type].timer, skill_status_change_timer); + sc_data[type].timer = -1; + } + } - nullpo_retv(bl); + switch (type) + { /* 異常の種類ごとの処理 */ + case SC_SLOWPOISON: + if (sc_data[SC_POISON].timer == -1) + return 0; + break; - su = (struct skill_unit *) src; + case SC_SPEEDPOTION0: /* 増速ポーション */ + *opt2 |= Opt2::_speedpotion0; + calc_flag = 1; + tick = 1000 * tick; +// val2 = 5*(2+type-SC_SPEEDPOTION0); + break; - if (su && su->alive) - { - struct skill_unit_group *sg; - sg = su->group; - if (sg && battle_check_target(src, bl, sg->target_flag) > 0) - skill_unit_onplace(su, bl, tick); - } -} + /* atk & matk potions [Valaris] */ + case SC_ATKPOT: + *opt2 |= Opt2::_atkpot; + FALLTHROUGH; + case SC_MATKPOT: + calc_flag = 1; + tick = 1000 * tick; + break; -/*========================================== - * スキルユニットタイマー削除処理用(foreachinarea) - *------------------------------------------ - */ -void skill_unit_timer_sub_ondelete(struct block_list *bl, - struct block_list *src, unsigned int tick) -{ - struct skill_unit *su; + case SC_NOCHAT: //チャット禁止状態 + { + time_t timer; - nullpo_retv(bl); + if (!battle_config.muting_players) + break; - su = (struct skill_unit *) src; + tick = 60000; + if (!val2) + val2 = time(&timer); + // updateflag = SP_MANNER; + } + break; + case SC_SELFDESTRUCTION: //自爆 + val3 = tick / 1000; + tick = 1000; + break; - if (su && su->alive) - { - struct skill_unit_group *sg; - sg = su->group; - if (sg && battle_check_target(src, bl, sg->target_flag) > 0) - skill_unit_ondelete(su, bl, tick); - } -} + /* option1 */ + case SC_STONE: /* 石化 */ + if (!(flag & 2)) + { + int sc_def = battle_get_mdef(bl) * 200; + tick = tick - sc_def; + } + val3 = tick / 1000; + if (val3 < 1) + val3 = 1; + tick = 5000; + val2 = 1; + break; + case SC_SLEEP: /* 睡眠 */ + if (!(flag & 2)) + { +// int sc_def = 100 - (battle_get_int(bl) + battle_get_luk(bl)/3); +// tick = tick * sc_def / 100; +// if(tick < 1000) tick = 1000; + tick = 30000; //睡眠はステータス耐性に関わらず30秒 + } + break; + case SC_FREEZE: /* 凍結 */ + if (!(flag & 2)) + { + int sc_def = 100 - battle_get_mdef(bl); + tick = tick * sc_def / 100; + } + break; + case SC_STAN: /* スタン(val2にミリ秒セット) */ + if (!(flag & 2)) + { + int sc_def = + 100 - (battle_get_vit(bl) + battle_get_luk(bl) / 3); + tick = tick * sc_def / 100; + } + break; -/*========================================== - * スキルユニットタイマー処理用(foreachobject) - *------------------------------------------ - */ -static -void skill_unit_timer_sub(struct block_list *bl, unsigned int tick) -{ - struct skill_unit *unit; - struct skill_unit_group *group; - int range; + /* option2 */ + case SC_POISON: /* 毒 */ + calc_flag = 1; + if (!(flag & 2)) + { + int sc_def = + 100 - (battle_get_vit(bl) + battle_get_luk(bl) / 5); + tick = tick * sc_def / 100; + } + val3 = tick / 1000; + if (val3 < 1) + val3 = 1; + tick = 1000; + break; + case SC_SILENCE: /* 沈黙(レックスデビーナ) */ + if (!(flag & 2)) + { + int sc_def = 100 - battle_get_vit(bl); + tick = tick * sc_def / 100; + } + break; + case SC_BLIND: /* 暗黒 */ + calc_flag = 1; + if (!(flag & 2)) + { + int sc_def = + battle_get_lv(bl) / 10 + battle_get_int(bl) / 15; + tick = 30000 - sc_def; + } + break; + case SC_CURSE: + calc_flag = 1; + if (!(flag & 2)) + { + int sc_def = 100 - battle_get_vit(bl); + tick = tick * sc_def / 100; + } + break; - nullpo_retv(bl); - unit = (struct skill_unit *) bl; - nullpo_retv(group = unit->group); + case SC_WEIGHT50: + case SC_WEIGHT90: + case SC_BROKNWEAPON: + case SC_BROKNARMOR: + tick = 600 * 1000; + break; - if (!unit->alive) - return; + case SC_HASTE: + calc_flag = 1; + break; + case SC_PHYS_SHIELD: + case SC_MBARRIER: + case SC_HALT_REGENERATE: + case SC_HIDE: + break; + case SC_FLYING_BACKPACK: + updateflag = SP_WEIGHT; + break; + default: + if (battle_config.error_log) + PRINTF("UnknownStatusChange [%d]\n", type); + return 0; + } - range = (unit->range != 0) ? unit->range : group->range; + if (bl->type == BL_PC && type < SC_SENDMAX) + clif_status_change(bl, type, 1); /* アイコン表示 */ - /* onplaceイベント呼び出し */ - if (unit->alive && unit->range >= 0) - { - map_foreachinarea(std::bind(skill_unit_timer_sub_onplace, ph::_1, bl, tick), - bl->m, bl->x - range, bl->y - range, - bl->x + range, bl->y + range, BL_NUL); - if (group->unit_id == 0xaa - && DIFF_TICK(tick, group->tick) >= 6000 * group->val2) - { - map_foreachinarea(std::bind(skill_idun_heal, ph::_1, unit), - bl->m, bl->x - range, bl->y - range, - bl->x + range, bl->y + range, BL_NUL); - group->val2++; - } - } - /* 時間切れ削除 */ - if (unit->alive && - (DIFF_TICK(tick, group->tick) >= group->limit - || DIFF_TICK(tick, group->tick) >= unit->limit)) + /* optionの変更 */ + switch (type) { - switch (group->unit_id) - { - - case 0x8f: /* ブラストマイン */ - group->unit_id = 0x8c; - clif_changelook(bl, LOOK_BASE, group->unit_id); - group->limit = DIFF_TICK(tick + 1500, group->tick); - unit->limit = DIFF_TICK(tick + 1500, group->tick); - break; - case 0x90: /* スキッドトラップ */ - case 0x91: /* アンクルスネア */ - case 0x93: /* ランドマイン */ - case 0x94: /* ショックウェーブトラップ */ - case 0x95: /* サンドマン */ - case 0x96: /* フラッシャー */ - case 0x97: /* フリージングトラップ */ - case 0x98: /* クレイモアートラップ */ - case 0x99: /* トーキーボックス */ + case SC_STONE: + case SC_FREEZE: + case SC_STAN: + case SC_SLEEP: + battle_stopattack(bl); /* 攻撃停止 */ + skill_stop_dancing(bl, 0); /* 演奏/ダンスの中断 */ + /* 同時に掛からないステータス異常を解除 */ + for (StatusChange i : MAJOR_STATUS_EFFECTS_1) { - struct block_list *src = map_id2bl(group->src_id); - if (group->unit_id == 0x91 && group->val2) - ; - else + if (sc_data[i].timer != -1) { - if (src && src->type == BL_PC) - { - struct item item_tmp; - memset(&item_tmp, 0, sizeof(item_tmp)); - item_tmp.nameid = 1065; - item_tmp.identify = 1; - map_addflooritem(&item_tmp, 1, bl->m, bl->x, bl->y, NULL, NULL, NULL, 0); // 罠返還 - } + (*sc_count)--; + delete_timer(sc_data[i].timer, + skill_status_change_timer); + sc_data[i].timer = -1; } } - // TODO: determine if this was supposed to be break - FALLTHROUGH; - default: - skill_delunit(unit); - } - } - - if (group->unit_id == 0x8d) - { - unit->val1 -= 5; - if (unit->val1 <= 0 && unit->limit + group->tick > tick + 700) - unit->limit = DIFF_TICK(tick + 700, group->tick); - } -} - -/*========================================== - * スキルユニットタイマー処理 - *------------------------------------------ - */ -static -void skill_unit_timer(timer_id, tick_t tick, custom_id_t, custom_data_t) -{ - map_freeblock_lock(); - - map_foreachobject(std::bind(skill_unit_timer_sub, ph::_1, tick), BL_SKILL); - - map_freeblock_unlock(); -} + switch (type) + { + case SC_STONE: *opt1 = Opt1::_stone6; break; + case SC_FREEZE: *opt1 = Opt1::_freeze; break; + case SC_STAN: *opt1 = Opt1::_stan; break; + case SC_SLEEP: *opt1 = Opt1::_sleep; break; + } + opt_flag = 1; + break; + case SC_POISON: + if (sc_data[SC_SLOWPOISON].timer == -1) + { + *opt2 |= Opt2::_poison; + opt_flag = 1; + } + break; -/*========================================== - * スキルユニット移動時処理用(foreachinarea) - *------------------------------------------ - */ -static -void skill_unit_out_all_sub(struct block_list *bl, - struct block_list *src, unsigned int tick) -{ - struct skill_unit *unit; - struct skill_unit_group *group; - int range; + case SC_CURSE: + *opt2 |= Opt2::_curse; + opt_flag = 1; + break; + case SC_SILENCE: + *opt2 |= Opt2::_silence; + opt_flag = 1; + break; + case SC_BLIND: + *opt2 |= Opt2::BLIND; + opt_flag = 1; + break; - nullpo_retv(bl); - nullpo_retv(src); - unit = (struct skill_unit *) bl; - nullpo_retv(group = unit->group); + case SC_SLOWPOISON: + *opt2 &= ~Opt2::_poison; + *opt2 |= Opt2::_slowpoison; + opt_flag = 1; + break; + } - if (!unit->alive || src->prev == NULL) - return; + if (opt_flag) /* optionの変更 */ + clif_changeoption(bl); - range = (unit->range != 0) ? unit->range : group->range; + (*sc_count)++; /* ステータス異常の数 */ - if (range < 0 || battle_check_target(bl, src, group->target_flag) <= 0) - return; + sc_data[type].val1 = val1; + sc_data[type].val2 = val2; + sc_data[type].val3 = val3; + sc_data[type].val4 = val4; + if (sc_data[type].spell_invocation) // Supplant by newer spell + spell_effect_report_termination(sc_data[type].spell_invocation, + bl->id, type, 1); - if (src->x >= bl->x - range && src->x <= bl->x + range && - src->y >= bl->y - range && src->y <= bl->y + range) - skill_unit_onout(unit, src, tick); -} + sc_data[type].spell_invocation = spell_invocation; -/*========================================== - * スキルユニット移動時処理 - *------------------------------------------ - */ -int skill_unit_out_all(struct block_list *bl, unsigned int tick, int range) -{ - nullpo_ret(bl); + /* タイマー設定 */ + sc_data[type].timer = + add_timer(gettick() + tick, skill_status_change_timer, bl->id, + custom_data_t(type)); - if (bl->prev == NULL) - return 0; + if (bl->type == BL_PC && calc_flag) + pc_calcstatus(sd, 0); /* ステータス再計算 */ - if (range < 7) - range = 7; - map_foreachinarea(std::bind(skill_unit_out_all_sub, ph::_1, bl, tick), - bl->m, bl->x - range, bl->y - range, - bl->x + range, bl->y + range, BL_SKILL); + if (bl->type == BL_PC && updateflag != SP::ZERO) + clif_updatestatus(sd, updateflag); /* ステータスをクライアントに送る */ return 0; } /*========================================== - * スキルユニット移動時処理用(foreachinarea) + * ステータス異常全解除 *------------------------------------------ */ -static -void skill_unit_move_sub(struct block_list *bl, - struct block_list *src, unsigned int tick) +int skill_status_change_clear(struct block_list *bl, int type) { - struct skill_unit *unit; - struct skill_unit_group *group; - int range; - - nullpo_retv(bl); - nullpo_retv(unit = (struct skill_unit *) bl); - nullpo_retv(src); - - if (!unit->alive || src->prev == NULL) - return; - - if ((group = unit->group) == NULL) - return; - range = (unit->range != 0) ? unit->range : group->range; - - if (range < 0 || battle_check_target(bl, src, group->target_flag) <= 0) - return; - - if (src->x >= bl->x - range && src->x <= bl->x + range && - src->y >= bl->y - range && src->y <= bl->y + range) - skill_unit_onplace(unit, src, tick); - else - skill_unit_onout(unit, src, tick); -} + eptr sc_data; + short *sc_count; + Option *option; + Opt1 *opt1; + Opt2 *opt2; + Opt3 *opt3; -/*========================================== - * スキルユニット移動時処理 - *------------------------------------------ - */ -int skill_unit_move(struct block_list *bl, unsigned int tick, int range) -{ nullpo_ret(bl); + sc_data = battle_get_sc_data(bl); + if (not sc_data) + return 0; + sc_count = battle_get_sc_count(bl); + nullpo_ret(sc_count); + option = battle_get_option(bl); + nullpo_ret(option); + opt1 = battle_get_opt1(bl); + nullpo_ret(opt1); + opt2 = battle_get_opt2(bl); + nullpo_ret(opt2); + opt3 = battle_get_opt3(bl); + nullpo_ret(opt3); - if (bl->prev == NULL) + if (*sc_count == 0) return 0; + for (StatusChange i : erange(StatusChange(), MAX_STATUSCHANGE)) + { + if (sc_data[i].timer != -1) + { + skill_status_change_end(bl, i, -1); + } + } + *sc_count = 0; + *opt1 = Opt1::ZERO; + *opt2 = Opt2::ZERO; + *opt3 = Opt3::ZERO; + *option = Option::ZERO; + + if (night_flag == 1 && type == 1) // by [Yor] + *opt2 |= Opt2::BLIND; - if (range < 7) - range = 7; - map_foreachinarea(std::bind(skill_unit_move_sub, ph::_1, bl, tick), - bl->m, bl->x - range, bl->y - range, - bl->x + range, bl->y + range, BL_SKILL); + if (type == 0 || type & 2) + clif_changeoption(bl); return 0; } -/*========================================== - * スキルユニット自体の移動時処理(foreachinarea) - *------------------------------------------ +/* + *---------------------------------------------------------------------------- + * スキルユニット + *---------------------------------------------------------------------------- */ -static -void skill_unit_move_unit_group_sub(struct block_list *bl, - struct block_list *src, unsigned int tick) -{ - struct skill_unit *unit; - struct skill_unit_group *group; - int range; - - nullpo_retv(bl); - nullpo_retv(src); - unit = (struct skill_unit *) src; - nullpo_retv(group = unit->group); - - if (!unit->alive || bl->prev == NULL) - return; - - range = (unit->range != 0) ? unit->range : group->range; - - if (range < 0 || battle_check_target(src, bl, group->target_flag) <= 0) - return; - if (bl->x >= src->x - range && bl->x <= src->x + range && - bl->y >= src->y - range && bl->y <= src->y + range) - skill_unit_onplace(unit, bl, tick); - else - skill_unit_onout(unit, bl, tick); -} /*========================================== - * スキルユニット自体の移動時処理 - * 引数はグループと移動量 + * 演奏/ダンスをやめる + * flag 1で合奏中なら相方にユニットを任せる + * *------------------------------------------ */ -int skill_unit_move_unit_group(struct skill_unit_group *group, int m, int dx, - int dy) +void skill_stop_dancing(struct block_list *, int) { - nullpo_ret(group); - - if (group->unit_count <= 0) - return 0; - - if (group->unit != NULL) - { - if (!battle_config.unit_movement_type) - { - int i; - for (i = 0; i < group->unit_count; i++) - { - struct skill_unit *unit = &group->unit[i]; - if (unit->alive && !(m == unit->bl.m && dx == 0 && dy == 0)) - { - int range = unit->range; - map_delblock(&unit->bl); - unit->bl.m = m; - unit->bl.x += dx; - unit->bl.y += dy; - map_addblock(&unit->bl); - if (range > 0) - { - if (range < 7) - range = 7; - map_foreachinarea(std::bind(skill_unit_move_unit_group_sub, ph::_1, &unit->bl, gettick()), - unit->bl.m, unit->bl.x - range, unit->bl.y - range, - unit->bl.x + range, unit->bl.y + range, BL_NUL); - } - } - } - } - else - { - int i, j, *r_flag, *s_flag, *m_flag; - struct skill_unit *unit1; - struct skill_unit *unit2; - r_flag = (int *) malloc(sizeof(int) * group->unit_count); - s_flag = (int *) malloc(sizeof(int) * group->unit_count); - m_flag = (int *) malloc(sizeof(int) * group->unit_count); - memset(r_flag, 0, sizeof(int) * group->unit_count); // 継承フラグ - memset(s_flag, 0, sizeof(int) * group->unit_count); // 継承フラグ - memset(m_flag, 0, sizeof(int) * group->unit_count); // 継承フラグ - - //先にフラグを全部決める - for (i = 0; i < group->unit_count; i++) - { - int move_check = 0; // かぶりフラグ - unit1 = &group->unit[i]; - for (j = 0; j < group->unit_count; j++) - { - unit2 = &group->unit[j]; - if (unit1->bl.m == m && unit1->bl.x + dx == unit2->bl.x - && unit1->bl.y + dy == unit2->bl.y) - { - //移動先にユニットがかぶってたら - s_flag[i] = 1; // 移動前のユニットナンバーの継承フラグon - r_flag[j] = 1; // かぶるユニットナンバーの残留フラグon - move_check = 1; //ユニットがかぶった。 - break; - } - } - if (!move_check) // ユニットがかぶってなかったら - m_flag[i] = 1; // 移動前ユニットナンバーの移動フラグon - } - - //フラグに基づいてユニット移動 - for (i = 0; i < group->unit_count; i++) - { - unit1 = &group->unit[i]; - if (m_flag[i]) - { // 移動フラグがonで - if (!r_flag[i]) - { // 残留フラグがoffなら - //単純移動(rangeも継承の必要無し) - int range = unit1->range; - map_delblock(&unit1->bl); - unit1->bl.m = m; - unit1->bl.x += dx; - unit1->bl.y += dy; - map_addblock(&unit1->bl); - if (range > 0) - { - if (range < 7) - range = 7; - map_foreachinarea(std::bind(skill_unit_move_unit_group_sub, ph::_1, &unit1->bl, gettick()), - - unit1->bl.m, unit1->bl.x - range, unit1->bl.y - range, - unit1->bl.x + range, unit1->bl.y + range, BL_NUL); - } - } - else - { // 残留フラグがonなら - //空ユニットになるので、継承可能なユニットを探す - for (j = 0; j < group->unit_count; j++) - { - unit2 = &group->unit[j]; - if (s_flag[j] && !r_flag[j]) - { - // 継承移動(range継承付き) - int range = unit1->range; - map_delblock(&unit2->bl); - unit2->bl.m = m; - unit2->bl.x = unit1->bl.x + dx; - unit2->bl.y = unit1->bl.y + dy; - unit2->range = unit1->range; - map_addblock(&unit2->bl); - if (range > 0) - { - if (range < 7) - range = 7; - map_foreachinarea(std::bind(skill_unit_move_unit_group_sub, ph::_1, &unit2->bl, gettick()), - - unit2->bl.m, unit2->bl.x - range, unit2->bl.y - range, - unit2->bl.x + range, unit2->bl.y + range, BL_NUL); - } - s_flag[j] = 0; // 継承完了したのでoff - break; - } - } - } - } - } - free(r_flag); - free(s_flag); - free(m_flag); - } - } - return 0; + // TODO remove this } +void skill_unit_timer_sub_ondelete(struct block_list *bl, + struct block_list *src, unsigned int tick); + /*---------------------------------------------------------------------------- * アイテム合成 *---------------------------------------------------------------------------- @@ -4904,28 +1649,12 @@ int skill_readdb(void) skill_db[i].castcancel = 1; else skill_db[i].castcancel = 0; - skill_db[i].cast_def_rate = atoi(split[9]); - skill_db[i].inf2 = atoi(split[10]); - skill_db[i].maxcount = atoi(split[11]); - if (strcasecmp(split[13], "weapon") == 0) - skill_db[i].skill_type = BF_WEAPON; - else if (strcasecmp(split[12], "magic") == 0) - skill_db[i].skill_type = BF_MAGIC; - else if (strcasecmp(split[12], "misc") == 0) - skill_db[i].skill_type = BF_MISC; - else - skill_db[i].skill_type = BF::ZERO; + skill_db[i].cast_def_rate = atoi(split[10]); + skill_db[i].inf2 = atoi(split[11]); + skill_db[i].maxcount = atoi(split[12]); + // split[13] was one of: BF_WEAPON, BF_MAGIC, BF_MISC, BF::ZERO memset(split2, 0, sizeof(split2)); - for (j = 0, p = split[14]; j < MAX_SKILL_LEVEL && p; j++) - { - split2[j] = p; - p = strchr(p, ':'); - if (p) - *p++ = 0; - } - for (k = 0; k < MAX_SKILL_LEVEL; k++) - skill_db[i].blewcount[k] = - (split2[k]) ? atoi(split2[k]) : atoi(split2[0]); + // split[14] was colon-separated blow counts. if (!strcasecmp(split[15], "passive")) { @@ -4981,9 +1710,6 @@ int do_init_skill(void) { skill_readdb(); - add_timer_interval(gettick() + SKILLUNITTIMER_INVERVAL, - skill_unit_timer, 0, 0, SKILLUNITTIMER_INVERVAL); - return 0; } diff --git a/src/map/skill.hpp b/src/map/skill.hpp index 0966d68..7ecdd37 100644 --- a/src/map/skill.hpp +++ b/src/map/skill.hpp @@ -21,8 +21,6 @@ struct skill_db int upkeep_time[MAX_SKILL_LEVEL], upkeep_time2[MAX_SKILL_LEVEL]; int castcancel, cast_def_rate; int inf2, maxcount; - BF skill_type; - int blewcount[MAX_SKILL_LEVEL]; int hp[MAX_SKILL_LEVEL], sp[MAX_SKILL_LEVEL], mhp[MAX_SKILL_LEVEL], hp_rate[MAX_SKILL_LEVEL], sp_rate[MAX_SKILL_LEVEL], zeny[MAX_SKILL_LEVEL]; @@ -48,15 +46,12 @@ skill_name_db& skill_lookup_by_name(const char *name); struct block_list; struct map_session_data; -struct skill_unit; -struct skill_unit_group; int do_init_skill(void); // スキルデータベースへのアクセサ int skill_get_hit(SkillID id); int skill_get_inf(SkillID id); -int skill_get_pl(SkillID id); int skill_get_nk(SkillID id); int skill_get_max(SkillID id); int skill_get_max_raise(SkillID id); @@ -65,44 +60,16 @@ int skill_get_sp(SkillID id, int lv); int skill_get_num(SkillID id, int lv); int skill_get_cast(SkillID id, int lv); int skill_get_delay(SkillID id, int lv); -int skill_get_time(SkillID id, int lv); -int skill_get_time2(SkillID id, int lv); -int skill_get_castdef(SkillID id); -int skill_get_weapontype(SkillID id); int skill_get_inf2(SkillID id); int skill_get_maxcount(SkillID id); -int skill_get_blewcount(SkillID id, int lv); - -// スキルの使用 -int skill_use_id(struct map_session_data *sd, int target_id, - SkillID skill_num, int skill_lv); -int skill_use_pos(struct map_session_data *sd, - int skill_x, int skill_y, SkillID skill_num, int skill_lv); - -int skill_castend_map(struct map_session_data *sd, SkillID skill_num, - const char *map); - -int skill_cleartimerskill(struct block_list *src); // 追加効果 int skill_additional_effect(struct block_list *src, struct block_list *bl, SkillID skillid, int skilllv, BF attack_type, unsigned int tick); -int skill_delunit(struct skill_unit *unit); -int skill_clear_unitgroup(struct block_list *src); - -int skill_unit_ondamaged(struct skill_unit *src, struct block_list *bl, - int damage, unsigned int tick); - int skill_castfix(struct block_list *bl, int time); int skill_delayfix(struct block_list *bl, int time); -int skill_check_unit_range(int m, int x, int y, int range, SkillID skillid); -int skill_check_unit_range2(int m, int x, int y, int range); -int skill_unit_out_all(struct block_list *bl, unsigned int tick, int range); -int skill_unit_move(struct block_list *bl, unsigned int tick, int range); -int skill_unit_move_unit_group(struct skill_unit_group *group, - int m, int dx, int dy); void skill_stop_dancing(struct block_list *src, int flag); @@ -111,14 +78,8 @@ int skill_castcancel(struct block_list *bl, int type); int skill_gangsterparadise(struct map_session_data *sd, int type); void skill_devotion(struct map_session_data *md, int target); -void skill_devotion2(struct block_list *bl, int crusader); int skill_devotion3(struct block_list *bl, int target); -#define skill_calc_heal(bl,skill_lv) (( battle_get_lv(bl)+battle_get_int(bl) )/8 *(4+ skill_lv*8)) - -// その他 -int skill_check_cloaking(struct block_list *bl); - // ステータス異常 int skill_status_effect(struct block_list *bl, StatusChange type, int val1, int val2, int val3, int val4, diff --git a/src/map/skill.t.hpp b/src/map/skill.t.hpp index 9dadce0..69dab85 100644 --- a/src/map/skill.t.hpp +++ b/src/map/skill.t.hpp @@ -28,9 +28,6 @@ enum class StatusChange : uint16_t #define CLIF_OPTION_SC_SCRIBE StatusChange::CLIF_OPTION_SC_SCRIBE // the rest are the normal effects - SC_HIDING = 4, // ? (opt) ?bad -#define SC_HIDING StatusChange::SC_HIDING - SC_SLOWPOISON = 14, // item script #define SC_SLOWPOISON StatusChange::SC_SLOWPOISON @@ -76,9 +73,6 @@ enum class StatusChange : uint16_t SC_ANKLE = 143, // ?skill.cpp skill_unit thingies #define SC_ANKLE StatusChange::SC_ANKLE - SC_SIGHT = 150, // ?unbad -#define SC_SIGHT StatusChange::SC_SIGHT - SC_ATKPOT = 185, // item script #define SC_ATKPOT StatusChange::SC_ATKPOT SC_MATKPOT = 186, // unused, but kept for parallel @@ -147,6 +141,7 @@ enum class BadSC BLIND = 8, COUNT = 9, // formerly 10, + // there is apocryphal evidence of a "bleeding" effect }; constexpr diff --git a/src/map/storage.cpp b/src/map/storage.cpp index 0f3cd10..bcdf8bc 100644 --- a/src/map/storage.cpp +++ b/src/map/storage.cpp @@ -214,7 +214,8 @@ int storage_storageadd(struct map_session_data *sd, int index, int amount) struct storage *stor; nullpo_ret(sd); - nullpo_ret(stor = account2storage2(sd->status.account_id)); + stor = account2storage2(sd->status.account_id); + nullpo_ret(stor); if ((stor->storage_amount > MAX_STORAGE) || !stor->storage_status) return 0; // storage full / storage closed @@ -249,7 +250,8 @@ int storage_storageget(struct map_session_data *sd, int index, int amount) PickupFail flag; nullpo_ret(sd); - nullpo_ret(stor = account2storage2(sd->status.account_id)); + stor = account2storage2(sd->status.account_id); + nullpo_ret(stor); if (index < 0 || index >= MAX_STORAGE) return 0; @@ -277,7 +279,8 @@ int storage_storageclose(struct map_session_data *sd) struct storage *stor; nullpo_ret(sd); - nullpo_ret(stor = account2storage2(sd->status.account_id)); + stor = account2storage2(sd->status.account_id); + nullpo_ret(stor); clif_storageclose(sd); if (stor->storage_status) -- cgit v1.2.3-60-g2f50