public static bool apply_skill_eff_to(long now, IBaseUnit from, IBaseUnit target, skill_state_conf sk_res, int aff, int percentage) { if (target.isghost() || target.isdie()) return false; if (target.ignore_dmg()) return false; if (sk_res.rate > 0) { if (new Random().Next(0, 100) > sk_res.rate) return false; } if (target.has_state(pl_state_type.PST_SKILL_AVOID)) return false; if (from.iid != target.iid) { if (!skill_conf.skill_target_type_validation(aff, skill_aff_type.SAT_ENERMY)) { if (from.can_atk(target)) return false; if (from.isaily(target)) { if (!skill_conf.skill_target_type_validation(aff, skill_aff_type.SAT_ALLY)) return false; } else { if (!skill_conf.skill_target_type_validation(aff, skill_aff_type.SAT_MID)) return false; } } else { if (from.Is_Player()) { if (target.Is_Player()) { if (target.get_pack_data().in_pczone || from.get_pack_data().in_pczone) return false; if (!from.can_atk(target)) return false; } else if (target.Is_Monster()) { if (target.owner_ply != null) { if (target.owner_ply.iid == from.iid) return false; if (target.owner_ply.get_pack_data().in_pczone || from.get_pack_data().in_pczone) return false; if (!from.can_atk(target)) return false; } } } else { if (!from.can_atk(target)) return false; } } } else { if(!skill_conf.skill_target_type_validation(aff,skill_aff_type.SAT_SELF)) return false; } if (from.Is_Player()) { if(target.can_atk(from)) target.atk_by(from); } if (sk_res.nodmg == 0) { //TODO do damage } if (sk_res.rmv_stat > 0) rmv_stat_from_pl_by_gb(sk_res.rmv_stat,target); if(sk_res.rmv_1_stat >0) rmv_1_stat_from_pl_by_gb(sk_res.rmv_1_stat,target); if (sk_res.tar_state > 0) { IBaseUnit_State state = add_state_to_pl(now, target, sk_res, from, 100); } if (sk_res.force_move_dir != -1) { int dir = sk_res.force_move_dir; if (sk_res.force_move_dir == 2) dir = new Random().Next(0, 2); int delta_x = target.x - from.x; int delta_y = target.y - from.y; if (delta_x != 0 || delta_y != 0) { Point2D vec=new Point2D(delta_x,delta_y); vec = Utility.normalize_vec2(vec); delta_x = (int)(sk_res.force_move_rang*vec.x); delta_y = (int) (sk_res.force_move_rang*vec.y); if (sk_res.force_move_dir == 0) { target.x += delta_x; target.y += delta_y; } else { target.x -= delta_x; target.y -= delta_y; } } target.get_pack_data().moving = null; target.get_pack_data().casting = null; target.get_pack_data().last_mvpts = null; } return true; }
public static MapUnitState add_state_to_pl(long cur_clock_tm, IBaseUnit target, tres_conf state, IBaseUnit frm_sprite, int per, bool bremark = true) { if (target.isdie() || target.isghost()) { // TO DO : 考虑有些技能能作用于尸体 return null; } var pl = target.get_pack_data(); var state_desc = Utility.get_skil_state_desc(state.tar_state); if (state_desc == null) { // Err: state not exist; Utility.trace_err("persist_game add state[" + state.tar_state + "] to[" + pl.iid + "], state not exist!\n"); return null; } var state_tm = state.state_tm; //sys.trace(sys.SLT_DETAIL, "state_tm before["+state_tm+"]\n"); var mul = 1000; var add = 0; // if (0 in pl.stat_red) //{ // mul += pl.stat_red[0].mul; // add += pl.stat_red[0].add; // } // if (state.tar_state in pl.stat_red) //{ // mul += pl.stat_red[state.tar_state].mul; // add += pl.stat_red[state.tar_state].add; // } //sys.trace(sys.SLT_DETAIL, "mul["+mul+"] add["+add+"]\n"); state_tm = (state_tm * 1000 / mul - add); if (state_tm < 1) state_tm = 1; //sys.trace(sys.SLT_DETAIL, "state_tm after["+state_tm+"]\n"); var new_end_tm = cur_clock_tm + state_tm * 100; //sys.trace(sys.SLT_DETAIL, "new_end_tm["+new_end_tm+"]\n"); var remove_stateids = new List<int>(); if (pl.states != null) { if (state_desc.max_cnt > 0) { // 判断状态数量 var own_cnt = 0; foreach (var val in pl.states.state_par) { if (val.id == state.tar_state) { ++own_cnt; if (own_cnt >= state_desc.max_cnt) { // 超过最大数量限制,不在增加状态 return null; } } } if (own_cnt == 0) { //替换掉低级的 if (state_desc.unique != null) { for (var idx = 0; idx < pl.states.state_par.Count; ++idx) { var val = pl.states.state_par[idx]; if (val.desc.unique == null) continue; if (state_desc.unique.uni_tp != val.desc.unique.uni_tp) { continue; } if (state_desc.unique.uni_prior > val.desc.unique.uni_prior) { pl.states.state_par.RemoveAt(idx); --idx; remove_stateids.push(val.desc.id); } } } } } else if (state_desc.unique != null) { // 判断独有状态,根据独有类型实施替换 for (var idx = 0; idx < pl.states.state_par.Count; ++idx) { var val = pl.states.state_par[idx]; if (val.desc.unique == null) continue; if (state_desc.unique.uni_tp != val.desc.unique.uni_tp) { continue; } if (state_desc.unique.uni_prior > val.desc.unique.uni_prior) { if (new_end_tm > val.end_tm) { pl.states.state_par.RemoveAt(idx); --idx; remove_stateids.push(val.desc.id); } else { return null; } } else if (state_desc.unique.uni_prior > val.desc.unique.uni_prior) { pl.states.state_par.RemoveAt(idx); --idx; remove_stateids.push(val.desc.id); } else { return null; } } } } var i = 0; for (; i < state_desc.s_states.Count; ++i) { int state_tp = state_desc.s_states[i].tp; if ((state_tp & (int)pl_state_type.PST_CANT_MOVE) == (int)pl_state_type.PST_CANT_MOVE) { // stop sprite & broadcast msg grid_map.update_pl_move(target, cur_clock_tm); if (pl.moving != null) { // 停止移动 //var data = { tm = cur_clock_tm, iid = pl.iid, x = pl.x, y = pl.y, face = pl.face }; // send stop move msg to clients //target.gmap.broadcast_map_rpc(10, data); //target.broad_cast_zone_msg_and_self(10, data); //delete pl.moving; pl.moving = null; } } if ((state_tp & (int)pl_state_type.PST_CANT_CAST_SKILL) == (int)pl_state_type.PST_CANT_CAST_SKILL) { if (pl.holding != null) {//先 停止聚气 if (target.gmap != null) { target.gmap.update_skill_holding(target, pl, 0); } } if (pl.casting != null) { // 停止施法 //var data = { iid = pl.iid }; // send cancel_casting_res to clients //target.broad_cast_zone_msg_and_self(29, data); //delete pl.casting; pl.casting = null; } } } if (pl.states == null) pl.states = new UnitState(); IMapUnit frm_pl = null; int frm_iid = 0; if (frm_sprite != null) { frm_pl = frm_sprite.get_pack_data(); frm_iid = frm_pl.iid; } MapUnitState obj = new MapUnitState() { id = state.tar_state, par = (int)(state.state_par * per / 1000.0), start_tm = cur_clock_tm, end_tm = new_end_tm, desc = state_desc, frm_iid = frm_iid, per = per, attadj = new Dictionary<string, int>(), }; pl.states.state_par.push(obj); // 首次添加定时状态 if (state_desc.timer != null) { obj.tm_elapsed = 0; var timer = state_desc.timer; if (timer.add_stat != null) { int tar_state = timer.add_stat.tar_state; if (tar_state != state_desc.id) { var state_obj = add_state_to_pl(cur_clock_tm, target, timer.add_stat, frm_sprite, per, false); if (state_obj != null) { // broadcast add state msg; //target.broad_cast_zone_msg_and_self(24, { iid = pl.iid, states =[state_obj]}); } } if (timer.dmg != null) { if (timer.trang != null) { apply_rang_eff(cur_clock_tm, target, new Point2D(pl.x, pl.y), new List<tres_conf>() { timer.dmg.convert2tres() }, timer.trang, 0, obj.par); } else { grid_map.apply_dmg_on_pl(target, frm_sprite, timer.dmg.convert2damage(), cur_clock_tm, obj.par); } } // 增加直接回蓝、回血功能 // if ("dd" in state_desc.timer) //{ // apply_direct_dmg_on_pl(target, frm_sprite, state_desc.timer.dd[0], cur_clock_tm, obj.par); // } if (target.isdie() || target.isghost()) { // TO DO : 考虑有些技能能作用于尸体 return null; } } if (state_desc.absorbdmg != null) { obj.absorbed = 0; obj.maxdmg = (state_desc.absorbdmg.maxdmg * obj.par / 1000); } if (state_desc.atkcnt != null) { obj.atkedcnt = 0; } //if(frm_sprite && "hate" in state_desc && frm_sprite.get_sprite_type() == map_sprite_type.MstPlayer) if (frm_sprite != null && state_desc.hate > 0) { target.onhate(frm_sprite, state_desc.hate); } if (remove_stateids.Count > 0) { // broadcast rmv_state msg //target.broad_cast_zone_msg_and_self(31, { iid = pl.iid, ids = remove_stateids}); } } if (bremark) { _remark_pl_state(target, pl); } return obj; }
//public static bool apply_skill_eff_to(long cur_clock_tm, IBaseUnit from, IBaseUnit target, dmg dmg, int aff, int skill_id, int percentage) //{ // tres sk_res = new tres(); // sk_res.rate = 100; // return apply_skill_eff_to(cur_clock_tm, from, target, sk_res, aff, skill_id, percentage); //} public static bool apply_skill_eff_to(long cur_clock_tm, IBaseUnit from, IBaseUnit target, tres_conf sk_res, int aff, int skill_id, int percentage) { var dflag = true; if (target.isdie() || target.isghost()) { // TO DO : 考虑有些技能能作用于尸体 if (dflag) Utility.debug(" !apply_skill_eff_to false 1"); return false; } if (target.ignore_dmg()) { if (dflag) Utility.debug(" !apply_skill_eff_to false 2"); return false; } //if ( "rate" in sk_res ) if (sk_res.rate > 0) { if (Utility.random(0, 100) > sk_res.rate) { if (dflag) Utility.debug(" !apply_skill_eff_to false 3"); return false; } } var to_pl = target.get_pack_data(); var frm_pl = from.get_pack_data(); //var rpc_data = new Variant(); //rpc_data["hited"] = 3; //rpc_data["sid"] = skill_id; //rpc_data["frm_iid"] = frm_pl.iid; //rpc_data["to_iid"] = to_pl.iid; if (target.has_state(pl_state_type.PST_SKILL_AVOID)) { // 目标技能免疫 // send single_skill_res msg to clients //rpc_data["hited"] = 0;//免疫 //target.broad_cast_zone_msg_and_self(22, rpc_data); if (dflag) Utility.debug(" !apply_skill_eff_to false 4"); return false; } //if(from.get_sprite_type() == map_sprite_type.MST_MONSTER && target.get_sprite_type() == map_sprite_type.MST_MONSTER) //{ // return false; // 一家人不打一家人 //} // TO DO : 根据aff判断敌人、盟友关系从而确定是否受此状态影响 game_err_code check_res = Utility.check_target_type(from, target, aff, target.gmap.pk_seting); if (check_res != game_err_code.RES_OK) return false; if (from.get_sprite_type() == map_sprite_type.MstPlayer) { if (target.can_atk(from)) { target.atk_by(from); } } //if(sk_res.hp_dmg != 0) //{ // rpc_data.hp_dmg <- {}; // rpc_data.hp_dmg.hp_dmg <- sk_res.hp_dmg; // to_pl.hp -= sk_res.hp_dmg; // if(to_pl.hp > to_pl.max_hp) // { // to_pl.hp = to_pl.max_hp; // } //} //if(sk_res.mp_dmg != 0) //{ // rpc_data.mp_dmg <- {}; // rpc_data.mp_dmg.mp_dmg <- sk_res.mp_dmg; // to_pl.mp -= sk_res.mp_dmg; // if(to_pl.mp > to_pl.max_mp) // { // to_pl.mp = to_pl.max_mp; // } //} Utility.debug("apply_skill_eff_to try apply_dmg_on_pl!"); //no_dmg 不计算伤害 if (sk_res.no_dmg == 0) { var ret = grid_map.apply_dmg_on_pl(target, from, sk_res.convert2damage(), cur_clock_tm, percentage, true); Utility.debug("!apply_skill_eff_to apply_dmg_on_pl:" + ret); if (ret["hited"]._int32 != 3) { // 未命中 // send single_skill_res msg to clients //rpc_data["hited"] = ret["hited"]; //target.broad_cast_zone_msg_and_self(22, rpc_data); if (dflag) Utility.debug(" !apply_skill_eff_to false 20"); return false; } } //sys.trace(sys.SLT_DETAIL, "sk_res.rmv_stat ["+sk_res.rmv_stat+"]\n"); if (sk_res.rmv_stat > 0) { int rmv_stat = sk_res.rmv_stat; if (to_pl.states != null) { //sys.dumpobj(to_pl.states); // 移除所有状态 rmv_stat_from_pl_by_gb(rmv_stat, target, to_pl); } } if (sk_res.rmv_1stat > 0) { if (to_pl.states != null) { // 移除一个状态 rmv_1stat_from_pl_by_gb(sk_res.rmv_1stat, target, to_pl); } } if (sk_res.tar_state > 0) { int tar_state = sk_res.tar_state; var add_stat = true; if (sk_res.stat_rat > 0) { // 有几率触发技能效果 var judg = Utility.random(0, 100); if (judg > sk_res.stat_rat) { //sys.trace(sys.SLT_DETAIL, "stat_rat["+sk_res.stat_rat+"] < judg["+judg+"]\n"); if (dflag) Utility.debug(" !apply_skill_eff_to false 21"); add_stat = false; } } if (add_stat) { // add state eff to character var state_obj = add_state_to_pl(cur_clock_tm, target, sk_res, from, percentage); if (state_obj != null) { // rpc_data.states < -state_obj; //rpc_data.states <- {}; //rpc_data.states.id <- state_obj.id; //rpc_data.states.par <- state_obj.par; //rpc_data.states.start_tm <-state_obj.start_tm; //rpc_data.states.end_tm <- state_obj.end_tm; } } } if (sk_res.cd_red != null) { // 减少cd //var skcds = []; foreach (var cd_red in sk_res.cd_red) { int sktp = cd_red.sktp; int cd_reduce = (cd_red.red_tm * percentage / 10); if (sktp == 0) { foreach (int sk_key in to_pl.skill_cd.Keys) { //cd -= (sk_res.cd_red.red_tm * 100 * per / 1000); to_pl.skill_cd[sk_key] -= cd_reduce; //skcds.push({ sktp = sktp, cdtm = cd - cur_clock_tm}); } } else if (to_pl.skill_cd.ContainsKey(sktp)) { to_pl.skill_cd[sktp] -= cd_reduce; //skcds.push({ sktp = cd_red.sktp, cdtm = to_pl.skill_cd[cd_red.sktp] - cur_clock_tm}); } } // if (skcds.len() > 0) // { //// send self_attchange msg //::send_rpc(to_pl.sid, 32, { skcds = skcds}); // } } if (!to_pl.cfmv) { if (sk_res.fmv != null) { var judge = Utility.random(0, 100); int fmv_rate = sk_res.fmv.rate; int fmv_dir = sk_res.fmv.dir; int fmv_rang = sk_res.fmv.rang; if (judge < fmv_rate) { var dir = fmv_dir; if (dir == 2) {//随机前后 dir = Utility.random(0, 2); } // 迫使目标移动 if (dir == 0) { // 远离自己的方向 var dist_x = to_pl.x - frm_pl.x; var dist_y = to_pl.y - frm_pl.y; if ((dist_x != 0) || (dist_y != 0)) { var vec = Utility.normalize_vec2(dist_x, dist_y); var from_x = to_pl.x; var from_y = to_pl.y; to_pl.x += (int)(vec.x * fmv_rang); to_pl.y += (int)(vec.y * fmv_rang); var dest_pos = target.gmap.valpoint_on_vector(to_pl.x, to_pl.y, from_x, from_y, vec); var to_grid_pos = target.gmap.get_grid_by_pt(dest_pos.x, dest_pos.y); //if(!to_grid_pos || (dest_pos.x < 0) || (dest_pos.y < 0)) //{ // // 目标坐标非法,出错 // Utility.trace_err("fmv frm_pl.x["+frm_pl.x+"] frm_pl.y["+frm_pl.y+"] from_x["+from_x+"] y["+from_y+"] to_pl.x["+to_pl.x+"] to_pl.y["+to_pl.y+"] dest_pos.x["+dest_pos.x+"] dest_pos.y["+dest_pos.y+"] vec:\n"); // sys.dumpobj(vec); //} to_pl.x = (int)dest_pos.x; to_pl.y = (int)dest_pos.y; //sys.trace(sys.SLT_DETAIL, "fmv to_pl.x["+to_pl.x+"] ["+to_pl.y+"]\n"); if (target.get_sprite_type() == map_sprite_type.MstPlayer && !target.is_in_lvl) { to_pl.lx = to_pl.x; to_pl.ly = to_pl.y; } } } else if (dir == 1) { // 靠近自己的方向 var dist_x = frm_pl.x - to_pl.x; var dist_y = frm_pl.y - to_pl.y; if ((dist_x != 0) || (dist_y != 0)) { var dist2 = dist_x * dist_x + dist_y * dist_y; var vec = Utility.normalize_vec2(dist_x, dist_y); if (fmv_rang == 0 || fmv_rang * fmv_rang >= dist2) { // 拉近到自己身边一格 var from_x = to_pl.x; var from_y = to_pl.y; to_pl.x = (int)(frm_pl.x - vec.x * game_const.map_grid_pixel); to_pl.y = (int)(frm_pl.y - vec.y * game_const.map_grid_pixel); var dest_pos = target.gmap.valpoint_on_vector(to_pl.x, to_pl.y, from_x, from_y, vec); to_pl.x = (int)dest_pos.x; to_pl.y = (int)dest_pos.y; if (target.get_sprite_type() == map_sprite_type.MstPlayer && !target.is_in_lvl) { to_pl.lx = to_pl.x; to_pl.ly = to_pl.y; } } else { var from_x = to_pl.x; var from_y = to_pl.y; to_pl.x += (int)(vec.x * fmv_rang); to_pl.y += (int)(vec.y * fmv_rang); var dest_pos = target.gmap.valpoint_on_vector(to_pl.x, to_pl.y, from_x, from_y, vec); to_pl.x = (int)dest_pos.x; to_pl.y = (int)dest_pos.y; if (target.get_sprite_type() == map_sprite_type.MstPlayer && !target.is_in_lvl) { to_pl.lx = to_pl.x; to_pl.ly = to_pl.y; } } } } } if (to_pl.moving != null) { // 停止移动 //var data = { tm = cur_clock_tm, iid = to_pl.iid, x = to_pl.x, y = to_pl.y, face = to_pl.face }; // send stop move msg to clients //target.gmap.broadcast_map_rpc(10, data); //target.broad_cast_zone_msg_and_self(10, data); //delete to_pl.moving; to_pl.moving = null; } to_pl.last_mvpts = null; //rpc_data.fmv < - { to_x = to_pl.x, to_y = to_pl.y, dir = sk_res.fmv.dir}; if (to_pl.casting != null) { // 停止施法 //var data = { iid = to_pl.iid }; // send cancel_casting_res to clients //target.broad_cast_zone_msg_and_self(29, data); //delete to_pl.casting; to_pl.casting = null; } } } //var gmap = target.gmap; //if(to_pl.hp <= 0) //{ // // die! // to_pl.hp = 0; // target.die(from); // rpc_data.isdie = true; //} // send single_skill_res msg to clients //gmap.broadcast_map_rpc(22, rpc_data); //target.broad_cast_zone_msg_and_self(22, rpc_data); return true; }
public static void update_pl_atk(IBaseUnit sprite, long cur_clock_tm) { var pl = sprite.get_pack_data(); if (pl.atking == null) return; var cd_tm = sprite.get_atk_cd(); if (pl.casting != null) { // 吟唱中,不更新攻击 _hold_pl_atk(pl, cd_tm, cur_clock_tm); return; } if (pl.holding != null) { // 聚气中,不更新攻击 _hold_pl_atk(pl, cd_tm, cur_clock_tm); return; } if (sprite.has_state(pl_state_type.PST_CANT_ATTACK)) { // can't attack _hold_pl_atk(pl, cd_tm, cur_clock_tm); return; } //Utility.trace_err("update [" + pl.iid +"] attack \n"); if (!sprite.gmap.has_sprite_by_iid(pl.atking.tar_iid)) { // 目标不在同一地图 sprite.cancel_atk(); // TO DO : send msg return; } var tar_sprite = sprite.gmap.map_sprites[pl.atking.tar_iid]; var tar_pl = tar_sprite.get_pack_data(); if (sprite.isghost() || tar_sprite.isghost()) { // 对方是灵魂状态,停止攻击 sprite.cancel_atk(); return; } if (tar_sprite.ignore_dmg()) { _hold_pl_atk(pl, cd_tm, cur_clock_tm); return; } if (cur_clock_tm < pl.skill_gen_cd) { // 与技能共cd _hold_pl_atk(pl, cd_tm, cur_clock_tm); return; } //Utility.trace_err("[" + pl.iid +"] attack ["+pl.atking.tar_iid+"] cur tm: ["+cur_clock_tm+"] atkstarttm["+pl.atking.start_tm+"]\n"); // TO DO : update face var tm_interval = cur_clock_tm - pl.atking.start_tm; //Utility.trace_err("[" + pl.iid +"] attack ["+pl.atking.tar_iid+"] tm_interval: ["+tm_interval+"] cd_tm ["+cd_tm+"]\n"); if (tm_interval < cd_tm) { // 没到攻击间隔 return; } if (tar_pl.invisible > pl.observer) { // 看不到目标 if (sprite.get_sprite_type() == map_sprite_type.MstMonster) { //delete pl.atking; // 停止攻击 pl.atking = null; } else { _hold_pl_atk(pl, cd_tm, cur_clock_tm); } return; } //Utility.trace_err("pl.x [" + pl.x +"] pl.y ["+pl.y+"] tar_pl.x: ["+tar_pl.x+"] tar_pl.y: ["+tar_pl.y+"]\n"); //Utility.trace_err("dist_x [" + dist_x +"] dist_y ["+dist_y+"] atkrange: ["+pl.atkrange+"]\n"); var dist_x = tar_pl.x - pl.x; var dist_y = tar_pl.y - pl.y; var range = pl.atkrange + pl.size + tar_pl.size + 32; // 允许1格误差 if (dist_x * dist_x + dist_y * dist_y > range * range) { // 不在攻击范围内 _hold_pl_atk(pl, cd_tm, cur_clock_tm); return; } var atkcnt_trigered = false; var added_state = false; if (pl.states != null) { // 检查按攻击次数结算状态 foreach (var val in pl.states.state_par) { if (val.atkedcnt < 0 || val.desc.atkcnt == null) continue; ++val.atkedcnt; //Utility.trace_info("val.atkedcnt["+val.atkedcnt+"] val.desc.atkcnt.cnt["+val.desc.atkcnt.cnt+"]") if (val.atkedcnt < val.desc.atkcnt.cnt) { continue; } //sys.dumpobj(val); // 触发结算状态 atkcnt_trigered = true; if (val.desc.atkcnt.add_stat > 0) { var state_obj = Skill.add_state_to_pl(cur_clock_tm, tar_sprite, new tres_conf(val.desc.atkcnt.add_stat), sprite, val.per, false); if (state_obj != null) { added_state = true; // broadcast add state msg; //tar_sprite.broad_cast_zone_msg_and_self(24, { iid = tar_pl.iid, states =[state_obj]}); } } if (val.desc.atkcnt.dmg > 0) { apply_dmg_on_pl(tar_sprite, sprite, new damage() { hp_dmg = val.desc.atkcnt.dmg }, cur_clock_tm, val.par); } } } if (pl.invisible > 0) { // 攻击就现身 Skill.rmv_state_from_pl_by_att("invisible", sprite, pl); } //if(sprite.get_sprite_type()==map_sprite_type.MstPlayer) //{ // // 中断打坐 // sprite.try_stop_recover(); //} tar_sprite.atk_by(sprite); if (atkcnt_trigered) { // 触发了攻击次数结算状态,该次攻击失效 if (added_state) { Skill._remark_pl_state(tar_sprite, tar_pl); } if (pl.atking != null) pl.atking.start_tm = cur_clock_tm; return; } // 计算攻击次数 var atk_count = (tm_interval / cd_tm); var atk_tm_left = tm_interval % cd_tm; var total_dmg = 0; pl.atking.start_tm = cur_clock_tm - atk_tm_left; pl.last_atk_tm = pl.atking.start_tm; pl.skill_gen_cd = pl.atking.start_tm + cd_tm; // 触发技能cd pl.skill_gen_cdst = pl.atking.start_tm; // 触发技能cd起始 var real_cd_tm = pl.skill_gen_cd - cur_clock_tm; if (real_cd_tm < 0) real_cd_tm = 0; // 判断对象是否攻击免疫 if (tar_sprite.has_state(pl_state_type.PST_ATK_AVOID)) { // can't be attack // send avoid attack msg //Utility.trace_err("[" + pl.iid +"] attack ["+pl.atking.tar_iid+"] target avoid attack\n"); //sprite.broad_cast_zone_msg_and_self(18, { hited = 0, frm_iid = pl.iid, to_iid = pl.atking.tar_iid}); return; } //::g_dump( " update_pl_atk() ===>>>> ", "") ; var ret = apply_dmg_on_pl_ex(tar_sprite, sprite, new damage() { dmg_min = 0, dmg_max = 0, noratk = 1, hp_dmg = 0, mp_dmg = 0 }, cur_clock_tm, (int)atk_count * 1000, true, true); //ret.atkcount < -atk_count; //ret.cdtm < -real_cd_tm; // send attack msg sprite.broad_cast_zone_msg_and_self(18, ret); if (tar_sprite.get_sprite_type() == map_sprite_type.MstPlayer) { //目标不在视野 需要补发消息 // if (!sprite.is_ply_inzone(tar_pl.sid)) // { //::send_rpc(tar_pl.sid, 18, ret); // } } }
public cast_skill_res _cast_skill(long cur_clock_tm, Variant rpc, skill_type tar_tp, IBaseUnit caster, IPoint2D to_pos, IBaseUnit tar_sprite, bool precast) { var cur_tm_s = DateTime.Now.ToBinary(); if (caster.isghost()) return new cast_skill_res(game_err_code.YOU_ARE_GHOST); var pl = caster.get_pack_data(); if (pl.casting != null) return new cast_skill_res(game_err_code.SKIL_ALREADY_CASTING_SKILL); if (pl.jumping != null) return new cast_skill_res(game_err_code.SKIL_CANT_CAST_WHEN_JUMP); int skill_id = rpc["sid"]._int32; //有聚气状态 使用任何技能 将触发它 if (pl.holding != null && skill_id != pl.holding.rpc["sid"]._int32) return new cast_skill_res(game_err_code.SKIL_ALREADY_HOLDING_SKILL); var skill_data = Utility.get_skil_skill_desc(skill_id); if (skill_data == null) return new cast_skill_res(game_err_code.SKIL_NOT_EXIST); if (skill_data.tar_tp != (int)tar_tp) { // Err: skill target type wrong return new cast_skill_res(game_err_code.SKIL_CAST_TARGET_TYPE_ERR); } // check caster own the skill and get skill level var caster_skil_data = caster.get_skil_data(skill_id); if (caster_skil_data == null) { caster_skil_data = this.get_map_skill(skill_id); if (caster_skil_data == null) { return new cast_skill_res(game_err_code.SKIL_NOT_LEARN); } } if (tar_sprite != null) { var tar_pl = tar_sprite.get_pack_data(); if (tar_pl.invisible > pl.observer) { // 看不到目标 return new cast_skill_res(game_err_code.SKIL_TARGET_NOT_AVALIBLE); } if (skill_data.tar_tp == (int)skill_type.ST_TARGET) { game_err_code check_res = Utility.check_target_type(caster, tar_sprite, skill_data.aff, this.pk_seting); if (check_res != game_err_code.RES_OK) return null; } } var skill_level_conf = Utility.get_skil_skill_lvl_desc(skill_id, caster_skil_data.sklvl); if (skill_level_conf == null) { // Err: skill data error Utility.trace_err("persist_game cast skill monster iid[" + pl.iid + "] skill [" + skill_id + "] sklvl[" + caster_skil_data.sklvl + "] data error\n"); return new cast_skill_res(game_err_code.SKIL_LVL_ERR); } if (cur_clock_tm < pl.skill_gen_cd) { //Utility.trace_err("persist_game cast skill caster [" + caster.get_iid() +"] skill ["+rpc.sid+"] cd not reach\n"); return new cast_skill_res(game_err_code.SKIL_CD_NOT_REACH); } if (pl.moving != null) update_pl_move(caster, cur_clock_tm); // rang check var cast_rang = pl.size + pl.atkrange; cast_rang += skill_data.cast_rang; if (to_pos != null) { if (tar_sprite != null) { var tar_pl = tar_sprite.get_pack_data(); cast_rang += tar_pl.size; if (tar_pl.moving != null) update_pl_move(tar_sprite, cur_clock_tm); } if (skill_level_conf.jump == null && skill_level_conf.teleport == null) { // 近战技能 var dist_x = to_pos.x - pl.x; var dist_y = to_pos.y - pl.y; var rang = cast_rang + 45; // 允许1格误差 if (dist_x * dist_x + dist_y * dist_y > rang * rang) { //Utility.trace_err("persist_game cast skill caster [" + caster.get_iid() +"] skill ["+rpc.sid+"] ground skill out of rang\n"); return new cast_skill_res(game_err_code.SKIL_CAST_RANG_ERR); } } } // 计算吟唱时间 if (precast && skill_data.cast_tm > 0) { var cast_tm = skill_data.cast_tm; var mul = 0; var add = 0; cast_tm = (cast_tm * 1000 / (1000 + mul) - add); //Utility.trace_info("cast_tm:["+cast_tm+"] \n"); if (cast_tm > 0) { // 需要吟唱 pl.moving = null; pl.casting = new casting() { tar_tp = (int)tar_tp, rpc = rpc, end_tm = (cur_clock_tm + cast_tm * 100) }; return new cast_skill_res(game_err_code.RES_OK); } } var hold_per = 1; if (skill_data.hold_tm > 0) { var hold_tm = skill_data.hold_tm; if (pl.holding != null) { hold_per = (int)(cur_clock_tm - pl.holding.start_tm) / (hold_tm * 100); if (hold_per > 1) hold_per = 1; pl.holding = null; } else { pl.moving = null; pl.holding = new holding() { tar_tp = (int)tar_tp, rpc = rpc, start_tm = cur_clock_tm, end_tm = cur_clock_tm + hold_tm * 100 }; return new cast_skill_res(game_err_code.RES_OK); } } if (pl.invisible > 0) { // 攻击就现身 Skill.rmv_state_from_pl_by_att("invisible", caster, pl); } var cd_tm = skill_level_conf.cd; var cdmul = 0; cd_tm = (cd_tm * 1000 / (1000 + cdmul)); if (cd_tm < 2) cd_tm = 2; //Utility.trace_info("cd_tm:["+cd_tm+"] \n"); pl.skill_gen_cd = cur_clock_tm + cd_tm * 100; pl.skill_gen_cdst = cur_clock_tm; //Utility.trace_err("persist_game cast self skill caster [" + caster.get_iid() +"] skill ["+rpc.sid+"] cd ["+pl.skill_cd[skill_data.cdtp]+"]\n"); var percent = 1000; percent = (percent * hold_per); if (percent <= 0) percent = 1; Variant rpc_data = new Variant(); rpc["res"] = (int)game_err_code.RES_OK; rpc["start_tm"] = rpc["start_tm"]; rpc["frm_iid"] = pl.iid; rpc["sid"] = rpc["sid"]; cast_skill_res cast_skill_res = new cast_skill_res(game_err_code.RES_OK) { skill_data = skill_data, skill_level_conf = skill_level_conf, rpc_data = rpc_data, percent = percent }; if (to_pos != null) { if (skill_level_conf.teleport != null) { // 瞬移 pl.moving = null; pl.last_mvpts = null; var telep_tm = 0; telep_tm = skill_level_conf.teleport.tm * 100; var dest_pos = Utility.valpoint_on_line(pl, to_pos, skill_level_conf.teleport.rang); if (telep_tm == 0) {//立即 pl.x = (int)dest_pos.x; pl.y = (int)dest_pos.y; if (caster.get_sprite_type() == map_sprite_type.MstPlayer && !caster.is_in_lvl) { pl.lx = pl.x; pl.ly = pl.y; } } else { pl.teleping = new teleping() { start_tm = cur_clock_tm, end_tm = (cur_clock_tm + telep_tm), telep = skill_level_conf.teleport, rpc = rpc, percent = percent, dest_x = (int)dest_pos.x, dest_y = (int)dest_pos.y }; } //rpc_data.telep < - { to_x = dest_pos.x, to_y = dest_pos.y, tm = telep_tm}; } else if (skill_level_conf.jump != null) { // 跳跃 pl.moving = null; pl.last_mvpts = null; var sub_len = 0; if (tar_sprite != null) { sub_len = 45; } var dest_pos = Utility.valpoint_on_line(pl, to_pos, skill_level_conf.jump.jump_rang, sub_len); var dist_x = dest_pos.x - pl.x; var dist_y = dest_pos.y - pl.y; var rang = Math.Sqrt(dist_x * dist_x + dist_y * dist_y); long jump_tm = (long)(rang * 1000 / skill_level_conf.jump.speed); if (jump_tm <= 0) jump_tm = 1; //pl.x = dest_pos.x; //pl.y = dest_pos.y; rpc_data["jump"] = new Variant(); rpc_data["jump"]["tm"] = jump_tm; rpc_data["jump"]["to_x"] = dest_pos.x; rpc_data["jump"]["to_y"] = dest_pos.y; var tar_iid = 0; if (tar_sprite != null) tar_iid = tar_sprite.get_pack_data().iid; pl.jumping = new jumping() { start_tm = cur_clock_tm, during_tm = jump_tm, end_tm = (cur_clock_tm + jump_tm), jump = skill_level_conf.jump, rpc = rpc, percent = percent, dest_x = (int)dest_pos.x, dest_y = (int)dest_pos.y, tar_iid = tar_iid }; } // if ("fly" in skill_level_conf && skill_level_conf.fly.speed > 0) //{ // var dest_pos = { x = to_pos.x, y = to_pos.y }; // var dist_x = dest_pos.x - pl.x; // var dist_y = dest_pos.y - pl.y; // var rang = Math.Sqrt(dist_x * dist_x + dist_y * dist_y); // if ("toend" in skill_level_conf.fly ) // { // var max_rang = skill_level_conf.fly.rang + cast_rang; // dest_pos.x = (dist_x * max_rang / rang + pl.x); // dest_pos.y = (dist_y * max_rang / rang + pl.y); // rang = max_rang; // } // var fly_tm = (rang * 1000 / skill_level_conf.fly.speed); // var fly_end_tm = cur_clock_tm + fly_tm; // var tar_iid = 0; // if (tar_sprite) tar_iid = tar_sprite.get_pack_data().iid; // // 记录飞行道具 // this.map_flys.push({ end_tm = fly_end_tm, frm_iid = pl.iid, rpc = rpc, cast_skill_res = cast_skill_res, tar_iid = tar_iid, frm_pos ={ x = pl.x, y = pl.y}, target_pos = dest_pos}); // rpc_data.fly < - { tm = fly_tm, to_x = dest_pos.x, to_y = dest_pos.y}; // } } //::g_dump( "cast_skill_res OK:", cast_skill_res ); return cast_skill_res; }
public cast_skill_res _cast_skill(long now, Dictionary<string, string> rpc, skill_type skill_type, IBaseUnit caster, IBaseUnit target, bool precast = false, Point2D to_pos = null) { if (caster.isghost()) return new cast_skill_res() { res = game_err_code.YOU_ARE_GHOST }; IMapUnit pl = caster.get_pack_data(); if (pl.atking != null) return new cast_skill_res() { res = game_err_code.SKIL_ALREADY_CASTING_SKILL }; if (pl.jumping != null) return new cast_skill_res(game_err_code.SKIL_CANT_CAST_WHEN_JUMP); int skill_id = Convert.ToInt32(rpc["sid"]); if (pl.holding != null && pl.holding.sid != skill_id) return new cast_skill_res(game_err_code.SKIL_ALREADY_HOLDING_SKILL); skill_conf skillConf = Utility.GetSkillConf(skill_id); if (skillConf == null) return new cast_skill_res(game_err_code.SKIL_NOT_EXIST); if (!skillConf.igccstate) { if (caster.has_state(pl_state_type.PST_CANT_CAST_SKILL)) return new cast_skill_res(game_err_code.SKIL_CANT_CAST); } if (skillConf.tar_tp != (int)skill_type) return new cast_skill_res(game_err_code.SKIL_CAST_TARGET_TYPE_ERR); int skill_level = caster.get_skil_data(skill_id); if (skill_level <= 0) { skill_level = this.get_map_skill(skill_id); if (skill_level <= 0) return new cast_skill_res(game_err_code.SKIL_NOT_LEARN); } if (target != null) { IMapUnit tar_pl = target.get_pack_data(); if (tar_pl.invisible > pl.invisible) return new cast_skill_res(game_err_code.SKIL_TARGET_NOT_AVALIBLE); if (skillConf.tar_tp == (int)skill_type.ST_TARGET) { if (caster.iid != target.iid) { if (!skillConf.Is_Target_Enermy()) { if (caster.can_atk(target)) return new cast_skill_res(game_err_code.SKIL_INVALIDE_TAREGET); bool isaly = caster.isaily(target); if (isaly) { if (!skillConf.Is_Target_ALAI()) return new cast_skill_res(game_err_code.SKIL_INVALIDE_TAREGET); } else { if (!skillConf.Is_Target_MID()) return new cast_skill_res(game_err_code.SKIL_INVALIDE_TAREGET); } } else if (caster.Is_Player()) { if (target.Is_Player()) { if (this.pk_seting == map_pk_setting_type.MPST_PEACE) return new cast_skill_res(game_err_code.CANT_PK_IN_PEACE_MAP); if (pl.in_pczone || tar_pl.in_pczone) return new cast_skill_res(game_err_code.CANT_PK_IN_PEACE_ZONE); if (this.pk_seting == map_pk_setting_type.MPST_NORMAL) { if (!target.can_atk_direct()) if (!caster.can_atk(target)) return new cast_skill_res(game_err_code.NULL); } else { if (!caster.can_atk(target)) return new cast_skill_res(game_err_code.NULL); } } else if (target.Is_Monster()) { if (target.owner_ply != null) { IBaseUnit owner_sprite = target.owner_ply; IMapUnit owner_pl = owner_sprite.get_pack_data(); if (owner_sprite.iid == caster.iid) return new cast_skill_res(game_err_code.CANT_ATTACK_SELF_PET); if (this.pk_seting == map_pk_setting_type.MPST_PEACE) return new cast_skill_res(game_err_code.CANT_PK_IN_PEACE_MAP); if (pl.in_pczone || owner_pl.in_pczone) return new cast_skill_res(game_err_code.CANT_PK_IN_PEACE_ZONE); if (this.pk_seting == map_pk_setting_type.MPST_NORMAL) { if (!owner_sprite.can_atk_direct()) if (!caster.can_atk(owner_sprite)) return new cast_skill_res(game_err_code.NULL); } else { if (!caster.can_atk(owner_sprite)) return new cast_skill_res(game_err_code.NULL); } } else { if (!caster.can_atk(target)) return new cast_skill_res(game_err_code.NULL); } } else { if (!skillConf.Is_Target_SELF()) return new cast_skill_res(game_err_code.SKIL_INVALIDE_TAREGET); } } } } } skill_lv_conf skill_level_conf = skillConf.GetSkillLevelConf(skill_level); if (null == skill_level_conf) return new cast_skill_res(game_err_code.SKIL_LVL_ERR); if (caster.Is_Skill_In_CD(skill_id, now)) return new cast_skill_res(game_err_code.SKIL_CD_NOT_REACH); if (pl.moving != null) update_pl_move(caster, now); int cast_rang = pl.size + pl.atkrange; if (skillConf.cast_rang > 0) cast_rang += skillConf.cast_rang; if (to_pos != null) { if (target != null) { cast_rang += target.get_pack_data().size; if (target.get_pack_data().moving != null) update_pl_move(target, now); } if (skill_level_conf.jump == null && skill_level_conf.teleport == null) { double d_x = to_pos.x - caster.x; double d_y = to_pos.y - caster.y; long rang = cast_rang + 45; if (d_x * d_x + d_y * d_y > rang * rang) return new cast_skill_res(game_err_code.SKIL_CAST_RANG_ERR); } } if (precast && skillConf.cast_tm > 0) { pl.moving = null; pl.casting = new casting() { end_tm = now + skillConf.cast_tm * 100, tar_tp = (int)skill_type, rpc = rpc }; return new cast_skill_res(game_err_code.RES_OK); } if (skillConf.hold_tm < 0) { if (pl.holding != null) pl.holding = null; else { pl.moving = null; pl.holding = new holding() { tar_tp = (int)skill_type, rpc = rpc, start_tm = now, end_tm = now + skillConf.hold_tm * 100 }; return new cast_skill_res(game_err_code.RES_OK); } } if (pl.invisible > 0) { oldSkill.rmv_state_from_pl_by_att("invisible", caster); } caster.Set_Skill_CD(skill_id, now, now + skillConf.cd_tm * 100); cast_skill_res res = new cast_skill_res(game_err_code.RES_OK); res.rpc_data = new Dictionary<string, string>(); if (to_pos != null) { if (skill_level_conf.teleport != null) { pl.moving = null; pl.last_mvpts = null; Point2D t_point = Utility.valpoint_on_line(caster, to_pos, skill_level_conf.teleport.rang); if (skill_level_conf.teleport.tm <= 0) { caster.x = (int)t_point.x; caster.y = (int)t_point.y; } else { pl.teleping = new teleping() { dest_x = (int)t_point.x, dest_y = (int)t_point.y, end_tm = now + skill_level_conf.teleport.tm * 100, percent = 100, rpc = rpc, start_tm = now, telep = skill_level_conf.teleport }; } } else if (skill_level_conf.jump != null) { pl.moving = null; pl.last_mvpts = null; int sub_len = 0; if (target != null) sub_len = 45; Point2D dest_pos = Utility.valpoint_on_line(caster, to_pos, skill_level_conf.jump.rang, sub_len); double dist_x = dest_pos.x - caster.x; double dist_y = dest_pos.y - caster.y; double rang = Math.Sqrt(dist_x * dist_x + dist_y * dist_y); int jump_tm = (int)(rang * 1000 / skill_level_conf.jump.speed); if (jump_tm <= 0) jump_tm = 1; pl.jumping = new jumping() { dest_x = (int)dest_pos.x, dest_y = (int)dest_pos.y, during_tm = jump_tm, end_tm = now + jump_tm, start_tm = now, jump = skill_level_conf.jump, percent = 100, rpc = rpc, tar_iid = (target == null) ? 0 : target.iid, }; } } return res; }