public static void _update_pl_tracing(IBaseUnit sprite, Tracing trace, int frang, int trang, int cur_clock_tm) { bool can_reach = true; IMapUnit pl = sprite.get_pack_data(); if (trace.trace_tm_left > 0 || cur_clock_tm - sprite.last_trace_target_tm > 500) { } }
public IBaseUnit new_pet_mon(IBaseUnit ply, map_mon_conf monconf) { // 分配战斗宠物实例 IBaseUnit mon = null; IMapUnit mondata = null; List<IBaseUnit> list = null; this.petmon_cache.TryGetValue(monconf.mid, out list); if (list == null || list.Count <= 0) { mon = this.create_monster_byconf(monconf); if (mon == null) { Utility.trace_err("Err: in map [" + this.mapid + "] add_pet_mon mid [" + monconf.mid + "] create error!\n"); return mon; } mon.gmap = this; mondata = mon.get_pack_data(); this.map_mons[mondata.iid] = mon; this.map_sprites[mondata.iid] = mon; list = null; if (this.map_mon_bymid.TryGetValue(mondata.mid, out list)) list.Add(mon); else { list = new List<IBaseUnit>(); list.Add(mon); this.map_mon_bymid[mondata.mid] = list; } } else { mon = list.pop<IBaseUnit>(); mondata = mon.get_pack_data(); } IMapUnit pl = ply.get_pack_data(); var ply_grid = this.get_grid_by_pt(pl.x, pl.y); mondata.org_init_x = (int)ply_grid.x; mondata.org_init_y = (int)ply_grid.y; mon.owner_ply = ply; mondata.owner_cid = pl.cid; mon.respawn(100, false); //var dest_pos = line_find_canwalk_grid(ply_grid.x, ply_grid.y, 3, 9); //mon._move_to(dest_pos.x, dest_pos.y); return mon; }
public bool isaily(IBaseUnit spr) { if (spr.get_sprite_type() == map_sprite_type.MstMonster && spr.owner_ply != null) spr = spr.owner_ply; // 用主人代替宠物检查敌我关系 IMapUnit pl = spr.get_pack_data(); if (pl.iid == this.pinfo.iid) return true; if (pl.lvlsideid != 0 && pinfo.lvlsideid == pl.lvlsideid) return true; if (pl.teamid == 0 || pinfo.teamid == 0) return false; if (pl.teamid == pinfo.teamid) return true; if (pl.clanid == 0 || pinfo.clanid == 0) return false; if (pl.clanid == pinfo.clanid) return true; return false; }
public void die(IBaseUnit killer) { if (this.dying) { return; } this.dying = true; long cur_clock_tm = DateTime.Now.ToBinary(); // 尝试触发死亡ai动作 this._trig_dying_act(cur_clock_tm); // TO DO : player die // 中断打坐 //this.try_stop_recover(); this.respawn_tm = cur_clock_tm + 30000; // 30 秒后安全复活 this.pinfo.isdie = true; pinfo.atking = null; pinfo.moving = null; if (pinfo.states != null) { bool _remark_pl_state = false; if (this.pinfo.states.state_par.Count > 0) { for (var idx = 0; idx < this.pinfo.states.state_par.Count; ++idx) { var val = this.pinfo.states.state_par[idx]; if (val.desc.die_keep == 1) continue; this.pinfo.states.state_par.RemoveAt(idx); --idx; _remark_pl_state = true; } } //pinfo.states.state = 0; //pinfo.states.mov_spd_mul = 1.0; //pinfo.states.atk_spd_mul = 1.0; //pinfo.states.mp2hp = 0; //pinfo.states.dmglnkper = 0; //re_calc_cha_data(); if (_remark_pl_state) Skill._remark_pl_state(this, pinfo); } if (pinfo.jumping != null) { // 跳跃中死亡,落在目标点 pinfo.x = pinfo.jumping.dest_x; pinfo.y = pinfo.jumping.dest_y; if (!this.is_in_lvl) { pinfo.lx = pinfo.x; pinfo.ly = pinfo.y; } pinfo.jumping = null; } if (gmap != null) { if (gmap.blvlmap) { //if (this.gmap.worldsvr.is_lvlmis_lvl()) //{ // this.allow_respawn_tm = sys.clock_time() + 6000; // 侠客行副本中,必须6秒后复活 //} this.gmap.worldsvr.on_ply_die(this); } else { if (gmap.pk_seting != map_pk_setting_type.MPST_PK) {//经验惩罚 } } if (killer != null && killer.get_sprite_type() == map_sprite_type.MstMonster) { if (killer.owner_ply != null) { killer = killer.owner_ply; // 宠物击杀相当于玩家角色击杀 } } if (killer != null && killer.get_sprite_type() == map_sprite_type.MstPlayer) { IMapUnit killer_pl = killer.get_pack_data(); //local pkdp = true; if (!gmap.blvlmap) { // 添加仇敌 //_add_foes(this, killer.pinfo); //计算pk值 //是否为中立地图 if (gmap.pk_seting == map_pk_setting_type.MPST_NORMAL) { if (!this.can_atk_direct()) { //自己为正义玩家 //sys.dumpobj( defend_tm_map ); //sys.trace( sys.SLT_ERR, "killer.pinfo.cid = " + killer.pinfo.cid + "sys.time()" + sys.time() + "\n") int killer_cid = killer_pl.cid; long defend_en_tm = 0; long now_s = DateTime.Now.ToBinary(); defend_tm_map.TryGetValue(killer_cid, out defend_en_tm); if (defend_en_tm > 0) { //自己是正当防卫 则 if (defend_en_tm >= now_s) { //增加对方pk值 int add_val = 1; int pkv = killer_pl.pk_v; if (pkv < 0) {//击杀者 有正义值 则清除 add_val = 1 - pkv; } killer.add_pk_v(add_val); } else { defend_tm_map.Remove(killer_cid); } } } else {//可直接攻击的玩家 if (killer.is_justice()) {//击杀者 为正义玩家 降低PK值 killer.sub_pk_v(1, true); } } } this.check_tsk_attribute(true); } else { // 在副本中 // 增加击杀值 killer_pl.kp++; killer_pl.cur_kp++; this.gmap.worldsvr.on_kp(killer, this); } } // remove atking from atker // TO DO : 增加被锁定列表,死亡后清理被锁定列表中的对象的攻击信息即可 foreach (var val in gmap.map_sprites.Values) { val.on_spr_die(pinfo.iid); } } // 清理助攻列表 if (this.kp_asist_rec) { this.beatk_ply_cids.Clear(); } }
public bool can_atk(IBaseUnit spr) { if (null != this.owner_ply) { return this.owner_ply.can_atk(spr); } if (this.get_sprite_type() == map_sprite_type.MstMonster && null != spr.owner_ply) spr = spr.owner_ply; IMapUnit pl = spr.get_pack_data(); if (pl.lvlsideid > 0) return this.mondata.lvlsideid != pl.lvlsideid; if (this.mondata.lvlsideid == 0 && spr.get_sprite_type() == map_sprite_type.MstMonster) return false; return true; }
public void ondmg(IBaseUnit atker, int dmg) { if (!this.shkilawd) return; if (this.get_sprite_type() == map_sprite_type.MstMonster) return; int cid = atker.get_pack_data().cid; if (this.dmglist.ContainsKey(cid)) this.dmglist[cid] += dmg; else { this.dmglist[cid] = dmg; } this.lastdmgtm = DateTime.Now.ToBinary(); }
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 int distance2(IBaseUnit a, IBaseUnit b) { IMapUnit ma = a.get_pack_data(); IMapUnit mb = a.get_pack_data(); if (ma == null || mb == null) return 0; return (int)(Math.Pow(ma.x - mb.x, 2) + Math.Pow(ma.y - mb.y, 2)); }
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); // } } }
//当单位配置中 keepdist = 1 时,攻击时将尽量保持与目标间的距离为自己的攻击距离 public static void update_keep_atk_range(IBaseUnit sprite, long tm_elasped_s) { var pl = sprite.get_pack_data(); if (pl.atking == null) { return; } if (sprite.has_state(pl_state_type.PST_CANT_MOVE)) { // can't move return; } var gmap = sprite.gmap; if (gmap.has_sprite_by_iid(pl.atking.tar_iid)) { //Utility.trace_err("monster["+this.mondata.iid+"] atking tar_iid[" + this.mondata.atking.tar_iid +"] cur tm[" +cur_clock_tm+"] last_trace_tm ["+ last_trace_target_tm +"] \n"); var target = gmap.map_sprites[pl.atking.tar_iid]; var tar_pl = target.get_pack_data(); double dist_x = pl.x - tar_pl.x; double dist_y = pl.y - tar_pl.y; var dist2 = dist_x * dist_x + dist_y * dist_y; var dist = Math.Sqrt(dist2); var atk_rang2 = pl.atkrange * pl.atkrange; // 处于最佳攻击距离 var best_atk_rang = pl.atkrange; if (dist.CompareTo(best_atk_rang) <= 0) { //Utility.trace_info("atk_trace stop:"+dist2+"="+atk_rang2+"\n"); if (pl.moving != null) { //// 停止移动 ////var cur_grid_pos = {x=(pl.x/game_const.map_grid_pixel), y=(pl.y/game_const.map_grid_pixel)} //var data = {tm=sys.clock_time()- pl.atking.trace_tm_left, iid=pl.iid, x=pl.x, y=pl.y, face=pl.face}; //// send stop move msg to clients ////gmap.broadcast_map_rpc(10, data); //sprite.broad_cast_zone_msg_and_self(10, data); //delete pl.moving; pl.moving = null; } } else { //if(dist > best_atk_rang) //{ // Utility.trace_info("atk_trace:"+dist+">"+best_atk_rang+"\n"); //} //else if(dist < best_atk_rang) //{ // Utility.trace_info("atk_trace:"+dist+"<"+best_atk_rang+"\n"); //} // 保持距离 //var cur_pos = gmap.get_grid_by_pt(pl.x, pl.y); //var tar_pos = gmap.get_grid_by_pt(tar_pl.x, tar_pl.y); //var k = (best_atk_rang / dist); //var best_pos = {}; //best_pos.x <- (tar_pos.x + (cur_pos.x - tar_pos.x) * k); //best_pos.y <- (tar_pos.y + (cur_pos.y - tar_pos.y) * k); // 计算和目标之间的角度atan(a),范围为[-PI/2, PI/2],为了获得整个圆周的范围,当(x<0)时角度为:PI+atan(a) /* * | * (-,-)|(+,-) * -----O------>X * (-,+)|(+,+) * | * \/Y */ double alpha = 0; if (dist != 0) { alpha = Math.PI / 2; if (dist_x != 0) { alpha = Math.Atan((dist_y / dist_x)); if (dist_x < 0) { alpha += Math.PI; } } else if (dist_y < 0) { alpha = -Math.PI / 2; } } //Utility.trace_info("atan("+dist_y+"/"+dist_x+"="+k+")="+alpha+"\n"); // 在最佳攻击距离圈上选取最近可达点 var new_pos = gmap.valpoint_on_round(tar_pl.x, tar_pl.y, best_atk_rang, alpha); if (new_pos != null) { new_pos = gmap.get_grid_by_pt(new_pos.x, new_pos.y); sprite._move_to(new_pos.x, new_pos.y); } //Utility.trace_info("keep range pos:("+tar_pos.x+","+tar_pos.y+","+best_atk_rang+")->("+new_pos.x+","+new_pos.y+")\n"); } } }
public static void update_pl_follow_tracing(IBaseUnit sprite, long cur_clock_tm) { var pl = sprite.get_pack_data(); if (pl.follow == null) { return; } if (sprite.has_state(pl_state_type.PST_CANT_MOVE)) { // can't move return; } var gmap = sprite.gmap; if (gmap.map_sprites.ContainsKey(pl.follow.tar_iid)) { _update_pl_tracing(sprite, pl.follow.ToVariant(), pl.follow.frang, pl.follow.trang, cur_clock_tm); } else { //delete pl.follow; pl.follow = null; } }
public static void update_pl_atk_tracing(IBaseUnit sprite, long cur_clock_tm) { // attack target // TO DO : 追击问题? // 追击情况下,攻击者的移动以被攻击者的位置为目标,当被攻击者移动时,攻击者的路径将随时变化,如何同步才能保证客户端与服务器位置同步且通信效率最优? var pl = sprite.get_pack_data(); if (pl.atking != null) { return; } if (sprite.has_state(pl_state_type.PST_CANT_MOVE)) { // can't move return; } var gmap = sprite.gmap; if (gmap.map_sprites.ContainsKey(pl.atking.tar_iid)) { var atkrang = gmap.map_sprites[pl.atking.tar_iid].get_pack_data().size + pl.atkrange + pl.size; atkrang = atkrang * atkrang; _update_pl_tracing(sprite, pl.atking.ToVariant(), atkrang, atkrang, cur_clock_tm); } else { //delete pl.atking; pl.atking = null; } }
public static bool _update_pl_tracing(IBaseUnit sprite, Variant trace, int frang, int trang, long cur_clock_tm) { var can_reach = true; var pl = sprite.get_pack_data(); // 1秒搜索2次目标 if (trace["trace_tm_left"]._int32 > 0 || cur_clock_tm - sprite.last_trace_target_tm > 500) { var target = sprite.gmap.map_sprites[trace["tar_iid"]._int32]; var tar_pl = target.get_pack_data(); double dist_x = pl.x - tar_pl.x; double dist_y = pl.y - tar_pl.y; double dist2 = dist_x * dist_x + dist_y * dist_y; if (dist2 > frang) { // 不在攻击范围,追击 if (pl.speed > 0) { Point2D cur_grid_pos = new Point2D() { x = (pl.x / game_const.map_grid_pixel), y = (pl.y / game_const.map_grid_pixel) }; Point2D tar_grid_pos = new Point2D() { x = (tar_pl.x / game_const.map_grid_pixel), y = (tar_pl.y / game_const.map_grid_pixel) }; var path = sprite.gmap.find_path(cur_grid_pos.x, cur_grid_pos.y, tar_grid_pos.x, tar_grid_pos.y); // 在路径中删除当前格子 if (path != null && path.Count > 0) path.pop(); if (path != null && path.Count > 0) { var i = 0; for (; i < path.Count; ++i) { var pt = path[i]; var to_x = pt.x * game_const.map_grid_pixel + 16; var to_y = pt.y * game_const.map_grid_pixel + 16; dist_x = to_x - tar_pl.x; dist_y = to_y - tar_pl.y; if (dist_x * dist_x + dist_y * dist_y > trang) { break; } } //Utility.trace_err("monster["+this.mondata.iid+"] trace tar_iid[" + trace.tar_iid +"] break on i[" +i+"]\n"); if (i == path.Count) { // TO DO : in attack range? // 转化之后的格子坐标在攻击范围内,当前像素位置不在攻击范围之内! var pt = path.pop(); path.Clear(); path.push(pt); } else if (i > 0) { path = path.slice(i - 1); } else { // 移动到路劲终点亦无法攻击对象?! can_reach = false; } if (path.Count > 0 && (path[0].x.CompareTo(cur_grid_pos.x) > 0 || path[0].y.CompareTo(cur_grid_pos.y) > 0)) { // 移动 var start_tm = cur_clock_tm - trace["trace_tm_left"]._int32; //Utility.trace_err("sprite ["+pl.iid+"] trace tar_iid[" + trace.tar_iid +"] cur tm["+ cur_clock_tm +"] start tm[" +start_tm+"]\n"); pl.moving = new moving() { start_tm = start_tm, pts = path, to_x = path[0].x, to_y = path[0].y, float_x = (pl.x), float_y = (pl.y) }; //var data = {start_tm=pl.moving.start_tm, iid=pl.iid, frm_x=pl.x, frm_y=pl.y, to_x=path[0].x, to_y=path[0].y}; //// send move msg to clients ////gmap.broadcast_map_rpc(9, data); //sprite.broad_cast_zone_msg_and_self(9, data); } } else { // TO DO : path not found? // delete this.mondata.atking; can_reach = false; } } } // 在攻击范围, else if (dist2 <= trang) { // 在攻击范围, if (pl.moving != null) { // 停止移动 //var cur_grid_pos = {x=(pl.x/game_const.map_grid_pixel), y=(pl.y/game_const.map_grid_pixel)} //var data = {tm=cur_clock_tm- trace.trace_tm_left, iid=pl.iid, x=pl.x, y=pl.y, face=pl.face}; //// send stop move msg to clients ////gmap.broadcast_map_rpc(10, data); //sprite.broad_cast_zone_msg_and_self(10, data); //delete pl.moving; pl.moving = null; } } sprite.last_trace_target_tm = cur_clock_tm; } return can_reach; }
public bool is_player_in_pc_zone(IBaseUnit ply) { if (this.map_conf.pk_zone.Count <= 0) return false; IMapUnit pl = ply.get_pack_data(); foreach (var z in map_conf.pk_zone) { if (pl.x > z.x && pl.x < z.x + z.width && pl.y > z.y && pl.y < z.y + z.height) { return true; } } return false; }
public void release_pet_mon(IBaseUnit mon) { // 回收战斗宠物实例 IMapUnit mondata = mon.get_pack_data(); List<IBaseUnit> list = null; if (this.petmon_cache.TryGetValue(mondata.mid, out list)) list.Add(mon); else { list = new List<IBaseUnit>(); list.Add(mon); this.petmon_cache.Add(mondata.mid, list); } }
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 void apply_rang_eff(long cur_clock_tm, IBaseUnit from, IPoint2D center, List<tres_conf> sk_res, rang_conf trang, int sid, int per) { var gmap = from.gmap; var maxi = trang.maxi; if (maxi == 0) maxi = 0x7fffffff; int aff_count = 0; Utility.debug(" ================= apply_rang_eff ================= "); //var test_cost_tm = sys.clock_time(); int cirang = trang.cirang; if (cirang > 0) { // 以center中心、cirang为半径的圆形区域 var pow_range = cirang * cirang; //var inzoneplys = from.get_inz_plys(); foreach (var val in gmap.map_players.Values) { if (val.isdie() || val.isghost()) { continue; } var pl_data = val.get_pack_data(); var dist_x = Math.Abs(pl_data.x - center.x); if (dist_x > cirang) { Utility.debug("pow_range[" + pow_range + "] <= dist_x[" + dist_x + "] center.x[" + center.x + "] , center.y[" + center.y + "] pl_data.x[" + pl_data.x + "] , pl_data.y[" + pl_data.y + "]"); continue; // 不在范围内 } var dist_y = Math.Abs(pl_data.y - center.y); if (dist_y > cirang) { Utility.debug("pow_range[" + pow_range + "] <= dist_y[" + dist_y + "] center.x[" + center.x + "] , center.y[" + center.y + "] pl_data.x[" + pl_data.x + "] , pl_data.y[" + pl_data.y + "]"); continue; // 不在范围内 } var rang1 = dist_x * dist_x + dist_y * dist_y; if (rang1 > pow_range) { Utility.debug("pow_range[" + pow_range + "] <= rang1[" + rang1 + "] center.x[" + center.x + "] , center.y[" + center.y + "] pl_data.x[" + pl_data.x + "] , pl_data.y[" + pl_data.y + "]"); continue; } var affed = false; foreach (var tres in sk_res) { var ret = apply_skill_eff_to(cur_clock_tm, from, val, tres, tres.aff, sid, per); if (ret) { affed = true; } } if (affed) { ++aff_count; if (aff_count >= maxi) { break; } } } if (aff_count < maxi) { //var inzonemons = from.get_inz_mons(); foreach (IBaseUnit val in gmap.map_mons.Values) { if (val.isdie() || val.isghost()) { continue; } var pl_data = val.get_pack_data(); var dist_x = Math.Abs(pl_data.x - center.x); if (dist_x - pl_data.size > cirang) continue; // 不在范围内 var dist_y = Math.Abs(pl_data.y - center.y); if (dist_y - pl_data.size > cirang) continue; // 不在范围内 var rang1 = Math.Sqrt(dist_x * dist_x + dist_y * dist_y); if (rang1 - pl_data.size > cirang) { continue; // 不在范围内 } var affed = false; foreach (var tres in sk_res) { var ret = apply_skill_eff_to(cur_clock_tm, from, val, tres, tres.aff, sid, per); if (ret) { affed = true; } } if (affed) { ++aff_count; if (aff_count >= maxi) { break; } } } } } else if (trang.fan != null) { int fan_angle = trang.fan.angle; int fan_rang = trang.fan.rang; // 以from为中心,center为目标,fan.rang为半径,fan.angle为角度的扇形区域 var frm_pl = from.get_pack_data(); var x1 = center.x - frm_pl.x; var y1 = center.y - frm_pl.y; var rang1 = x1 * x1 + y1 * y1; if (rang1 != 0) { rang1 = Math.Sqrt(rang1); var h_angle = Math.Cos(fan_angle / 360.0 * Math.PI); var maxrange = fan_rang; var pow_maxrange = maxrange * maxrange; //var inzoneplys = from.get_inz_plys(); foreach (var val in gmap.map_players.Values) { if (val.isdie() || val.isghost()) { continue; } var pl_data = val.get_pack_data(); var x2 = pl_data.x - frm_pl.x; if (Math.Abs(x2) >= maxrange) continue; // 不在范围内 var y2 = pl_data.y - frm_pl.y; if (Math.Abs(y2) >= maxrange) continue; // 不在范围内 double rang2 = x2 * x2 + y2 * y2; //sys.trace( sys.SLT_DETAIL, "x2 = " + x2 + " y2 = " + y2 + "\n" ); if (rang2 >= pow_maxrange) { continue; // 不在范围内 } rang2 = Math.Sqrt(rang2); var angleVal = (rang2 != 0) ? (x1 * x2 + y1 * y2) / (rang2 * rang1) : 1; //sys.trace( sys.SLT_DETAIL, "apply_rang_eff rang2 = " + rang2 + "rang1 = " + rang1 + "\n" ); //sys.trace( sys.SLT_DETAIL, "apply_rang_eff angleVal = " + angleVal + "h_angle = " + h_angle + "\n" ); if (angleVal < h_angle) { continue;// 不在范围内 } var new_per = per; if (trang.fan.decay != null && trang.fan.decay.Count > 0) {//衰减 var dist = rang2; foreach (var decay in trang.fan.decay) { if (decay.min <= dist && decay.max > dist) { new_per *= (int)(decay.per / 100.0); break; } } } var affed = false; foreach (var tres in sk_res) { var ret = apply_skill_eff_to(cur_clock_tm, from, val, tres, tres.aff, sid, new_per); if (ret) { affed = true; } } if (affed) { ++aff_count; if (aff_count >= maxi) break; } } if (aff_count < maxi) { //var inzonemons = from.get_inz_mons(); foreach (IBaseUnit val in gmap.map_mons.Values) { if (val.isdie() || val.isghost()) { continue; } var pl_data = val.get_pack_data(); var x2 = pl_data.x - frm_pl.x; if (Math.Abs(x2) - pl_data.size >= maxrange) continue; // 不在范围内 var y2 = pl_data.y - frm_pl.y; if (Math.Abs(y2) - pl_data.size >= maxrange) continue; // 不在范围内 var rang2 = Math.Sqrt(x2 * x2 + y2 * y2); //sys.trace( sys.SLT_DETAIL, "x2 = " + x2 + " y2 = " + y2 + "\n" ); if (rang2 - pl_data.size >= maxrange) { continue; // 不在范围内 } var angleVal = (rang2 != 0) ? (x1 * x2 + y1 * y2) / (rang2 * rang1) : 1; //sys.trace( sys.SLT_DETAIL, "apply_rang_eff rang2 = " + rang2 + "rang1 = " + rang1 + "\n" ); //sys.trace( sys.SLT_DETAIL, "apply_rang_eff angleVal = " + angleVal + "h_angle = " + h_angle + "\n" ); if (angleVal < h_angle) { continue;// 不在范围内 } var new_per = per; if (trang.fan.decay != null && trang.fan.decay.Count > 0) {//衰减 var dist = rang2; foreach (var decay in trang.fan.decay) { if (decay.min <= dist && decay.max > dist) { new_per *= (int)(decay.per / 100.0); break; } } } var affed = false; foreach (var tres in sk_res) { var ret = apply_skill_eff_to(cur_clock_tm, from, val, tres, tres.aff, sid, new_per); if (ret) { affed = true; } } if (affed) { ++aff_count; if (aff_count >= maxi) break; } } } } } else if (trang.ray != null) { // 以from为中心,center为目标,fan.dist为距离,fan.width为宽度的矩形区域 var ray = trang.ray; var frm_pl = from.get_pack_data(); var x1 = center.x - frm_pl.x; var y1 = center.y - frm_pl.y; var rang1 = x1 * x1 + y1 * y1; if (rang1 != 0) { rang1 = Math.Sqrt(rang1); var hwidth = ray.width / 2.0; //var inzoneplys = from.get_inz_plys(); foreach (var val in gmap.map_players.Values) { if (val.isdie() || val.isghost()) { continue; } var pl_data = val.get_pack_data(); var x2 = pl_data.x - frm_pl.x; var y2 = pl_data.y - frm_pl.y; var dotVal = x1 * x2 + y1 * y2; //sys.trace( sys.SLT_DETAIL, " iid = " + pl_data.iid + " dotVal = " + dotVal + "\n" ); if (dotVal < 0) { continue;// 不在范围内 } var projVal = dotVal / rang1; //sys.trace( sys.SLT_DETAIL, " dotVal = " + dotVal + " projVal = " + projVal + "\n" ); if (projVal - pl_data.size > ray.dist) { continue;// 不在范围内 } var vertVal = x2 * x2 + y2 * y2 - projVal * projVal;//小数会产生误差 出现负数的情况 //sys.trace( sys.SLT_DETAIL, "apply_rang_eff vertVal = " + vertVal + " pl_data.size =" + pl_data.size + "\n" ); if (vertVal > 0 && Math.Sqrt(vertVal) > hwidth) { continue;// 不在范围内 } var affed = false; foreach (var tres in sk_res) { var ret = apply_skill_eff_to(cur_clock_tm, from, val, tres, tres.aff, sid, per); if (ret) { affed = true; } } if (affed) { ++aff_count; if (aff_count >= maxi) break; } } if (aff_count < maxi) { //var inzonemons = from.get_inz_mons(); foreach (var val in gmap.map_mons.Values) { if (val.isdie() || val.isghost()) { continue; } var pl_data = val.get_pack_data(); var x2 = pl_data.x - frm_pl.x; var y2 = pl_data.y - frm_pl.y; var dotVal = x1 * x2 + y1 * y2; //sys.trace( sys.SLT_DETAIL, " iid = " + pl_data.iid + " dotVal = " + dotVal + "\n" ); if (dotVal < 0) { continue;// 不在范围内 } var projVal = dotVal / rang1; //sys.trace( sys.SLT_DETAIL, " dotVal = " + dotVal + " projVal = " + projVal + "\n" ); if (projVal - pl_data.size > ray.dist) { continue;// 不在范围内 } var vertVal = x2 * x2 + y2 * y2 - projVal * projVal;//小数会产生误差 出现负数的情况 //sys.trace( sys.SLT_DETAIL, "apply_rang_eff vertVal = " + vertVal + " pl_data.size =" + pl_data.size + "\n" ); if (vertVal > 0 && Math.Sqrt(vertVal) > hwidth) { continue;// 不在范围内 } var affed = false; foreach (var tres in sk_res) { var ret = apply_skill_eff_to(cur_clock_tm, from, val, tres, tres.aff, sid, per); if (ret) { affed = true; } } if (affed) { ++aff_count; if (aff_count >= maxi) break; } } } } } //sys.trace( sys.SLT_DETAIL, " apply_rang_eff tm= " + (sys.clock_time()-test_cost_tm) + " \n" ); }
// { // level = 1, // atktp = atk_type.ATKTP_ATK, // atk_min = 100, // atk_max = 100, // matk_min = 100, // matk_max = 100, // atk_rate = 1000, // 命中率 // miss_rate = 0, // 闪避 // pkatkrate = 100, // pkmisrate = 100, // criatk = 0, // criatk_debuffs = 0, //暴击抵抗,相对 criatk 的抵抗 ,千分比, 算法:受到暴击击的概率降低xx // cridmg = 0, // exatk = 0, // exatk_debuffs = 0, // 卓越一击率抵抗, 相对 exatk 的抵抗 ,千分比, 算法:受到卓越一击的概率降低xx // exdmg = 0, // dobrate = 0, // igdef_rate = 0, // igdef_rate_debuffs = 0, // 抵抗无视防御几率 // def_red = 0, // dmg_red = 0, // atk_dmg_mul = 0, // igdmg_red = 0, // 无视伤害减免几率,千分比 // igatk_dmg_mul = 0,// 无视伤害增益几率,千分比 // hpsuck = 0, // 每次攻击吸收生命值 // hpsuck_dmgmul = 0, // 每次攻击吸收生命值增加伤害比例 // addResist = [0,0,0,0,0,0,0], // 属性攻击 // clansred = 0, // iid = 0, //}; // damage { noratk: } ?? public static Variant apply_dmg_on_pl_ex(IBaseUnit tar_sprite, IBaseUnit frm_sprite, damage damage, long cur_clock_tm, int per, bool wpnatk = false, bool direct_dmg = false) { // TO DO : 优化: per = 1000时不需要计算增益 //direct_dmg 默认伤害....? 技能伤害, 追击伤害, 有miss几率 //wpnatk 是否默认攻击 //::g_dump( "apply_dmg [ damage ] ===>>>> ", damage ) ; //::g_dump( "apply_dmg [ flags ] ===>>>> ", { wpnatk = wpnatk, direct_dmg = direct_dmg } ) ; if (frm_sprite != null) { frm_sprite.on_hurt(tar_sprite); } tar_sprite.on_be_hurt(frm_sprite); var tar_pl = tar_sprite.get_pack_data(); // 取不到状态添加对象情况下,本函数frm_sprite可能为空,则需要默认的计算参数 var pl = default(IMapUnit);// g_dmg_calc_def_pl; if (frm_sprite != null) { pl = frm_sprite.get_pack_data(); pl.last_atk_tm = cur_clock_tm; // 触发普通攻击cd } var ret = new Variant(); ret["hited"] = 3; ret["criatk"] = 0; ret["dmg"] = 0; ret["dobdmg"] = false; ret["isdie"] = false; ret["frm_iid"] = pl.iid; ret["to_iid"] = tar_pl.iid; // 计算玩家 VS NPC 等级调整伤害 //var dmg_per_add = 0; var is_pvp = true; if (frm_sprite != null) { if (frm_sprite.get_sprite_type() == map_sprite_type.MstMonster) { is_pvp = false; } } if (tar_sprite.get_sprite_type() == map_sprite_type.MstMonster) { is_pvp = false; } // miss check var bAllMiss = false; if (direct_dmg) { if (is_pvp) { // pvp var atk_rate = 100 * (pl.pkatkrate / (pl.pkatkrate + tar_pl.pkmisrate)/* * (pl.level/(pl.level + tar_pl.level))*/); var lvl_dist = tar_pl.level - pl.level; if (lvl_dist >= 300) { atk_rate -= 15; } else if (lvl_dist >= 200) { atk_rate -= 10; } else if (lvl_dist >= 100) { atk_rate -= 5; } var judg = Utility.random(0, 100); if (judg > atk_rate) { // miss ret["hited"] = 1; return ret; } } else { // pve var atk_rate = 100.0 * (pl.atk_rate - tar_pl.miss_rate) / pl.atk_rate; if (atk_rate < 5) { if (atk_rate < 0) { bAllMiss = true; } atk_rate = 5; } var judg = Utility.random(0, 100); if (judg > atk_rate) { // miss ret["hited"] = 1; return ret; } } } double targetDef = tar_pl.def; if (is_pvp) targetDef += tar_pl.pkdef; targetDef = (targetDef - targetDef * (pl.def_red / 1000.0)); var igdef_rate = pl.igdef_rate - tar_pl.igdef_rate_debuffs; if (igdef_rate > 0) { var judg = Utility.random(0, 1000); if (judg < igdef_rate) { targetDef = 0; ret["criatk"] = 1; // 无视防御 } } //Utility.trace_info("apply_dmg_on_pl frm_sprite:["+frm_sprite+"] per["+per+"]\n"); //sys.dumpobj(pl); //var combat_conf = get_general_combat_conf(); double total_dmg = 0; // TO DO : 计算伤害 damage 是否是物理伤害 if (pl.atktp == atk_type.ATKTP_MATK && !wpnatk && (damage.plyatk != 1)) { //pl.atktp == atk_type.ATKTP_MATK 是 魔攻攻击分类角色 // !wpnatk 不是默认攻击 // (!("plyatk" in damage) || damage.plyatk!=1) 不是物理攻击 // 根据魔法攻击计算伤害 int dmg_min = damage.dmg_min + pl.matk_min * damage.noratk; int dmg_max = damage.dmg_max + pl.matk_max * damage.noratk; if (is_pvp && pl.pkmatk != 0) {//pvp魔法攻击增加 dmg_min += pl.pkmatk; dmg_max += pl.pkmatk; } if (damage.attr >= 0) {// 属性攻击 dmg_min += pl.addResist[damage.attr]; dmg_max += pl.addResist[damage.attr]; } // TO DO : 根据装备武器不同来计算伤害 //if(direct_dmg && frm_sprite) //{ // //frm_sprite.get_equip_by_pos(6); // 获取装备的武器 //} double dmg = 0; var dmg_calced = false; if (damage.noratk > 0 && (pl.criatk - pl.criatk_debuffs > 0 || pl.exatk - pl.exatk_debuffs > 0)) { var judg = Utility.random(0, 1000); if (judg < pl.exatk - pl.exatk_debuffs) {//卓越一击几率 dmg = dmg_max - targetDef; dmg += dmg_max * (0.2 + pl.exper_add / 1000.0); dmg += pl.exdmg; ret["criatk"] = 2; // 卓越一击 dmg_calced = true; } else { judg = Utility.random(0, 1000); if (judg < pl.criatk - pl.criatk_debuffs) {// 会心一击几率 dmg = dmg_max - targetDef; dmg += pl.cridmg; ret["criatk"] = 3; // 会心一击 dmg_calced = true; } } } if (!dmg_calced) { dmg = Utility.random(dmg_min, dmg_max + 1); //if(is_pvp) //{ // dmg = dmg - (targetDef*tar_sprite.game_conf.pvp_def_per/100.0); //} //else //{ // dmg = dmg - targetDef; //} } if (frm_sprite != null && frm_sprite.get_sprite_type() == map_sprite_type.MstPlayer) { //// 技能攻击,技能额外加成 //int dmg_mul = damage["noratk"]; //var baseatt_conf = frm_sprite.carr_gen_conf.baseatt[0]; //if( ("inte2atk" in baseatt_conf) && baseatt_conf.inte2atk != 0 ) //{ // dmg_mul += pl.inte/(pl.inte+baseatt_conf.inte2atk); //} ////sys.trace( sys.SLT_DETAIL, "atk_type.ATKTP_MATK dmg_mul=" + dmg_mul + " baseatt_conf.inte2atk =" + baseatt_conf.inte2atk + "\n") //dmg = dmg * dmg_mul; } if (dmg <= 0) { dmg = 1; } total_dmg += dmg; } else { // 根据攻击力计算伤害 var skil_dmg_min = damage.dmg_min + pl.atk_min; var skil_dmg_max = damage.dmg_max + pl.atk_max; if (is_pvp && pl.pkatk != 0) { skil_dmg_min += pl.pkatk; skil_dmg_max += pl.pkatk; } if (damage.attr >= 0) { skil_dmg_min += pl.addResist[damage.attr]; skil_dmg_max += pl.addResist[damage.attr]; } double dmg = 0; var dmg_calced = false; if (damage.noratk > 0 && (pl.criatk - pl.criatk_debuffs > 0 || pl.exatk - pl.exatk_debuffs > 0)) { var judg = Utility.random(0, 1000); if (judg < pl.exatk - pl.exatk_debuffs) { dmg = skil_dmg_max; dmg += skil_dmg_max * (0.2 + pl.exper_add / 1000.0); dmg += pl.cridmg; dmg += pl.exdmg; ret["criatk"] = 2; // 卓越一击 dmg_calced = true; } else { judg = Utility.random(0, 1000); if (judg < pl.criatk - pl.criatk_debuffs) { dmg = skil_dmg_max; dmg += pl.cridmg; ret["criatk"] = 3; // 会心一击 dmg_calced = true; } } } if (!dmg_calced) { dmg = Utility.random(skil_dmg_min, skil_dmg_max + 1); } //if(is_pvp) //{ // dmg = dmg - (targetDef*tar_sprite.game_conf.pvp_def_per/100.0); //} //else //{ // dmg = dmg - targetDef; //} if (!wpnatk && frm_sprite != null && frm_sprite.get_sprite_type() == map_sprite_type.MstPlayer) { // 物理技能攻击,技能额外加成 var dmg_mul = damage.noratk; //var baseatt_conf = frm_sprite.carr_gen_conf.baseatt[0]; //if( ("inte2atk" in baseatt_conf) && baseatt_conf.inte2atk != 0 ) //{ // dmg_mul += pl.inte/(pl.inte+baseatt_conf.inte2atk); //} //sys.trace( sys.SLT_DETAIL, "atk_type.ATKTP_ATK dmg_mul=" + dmg_mul + "\n") dmg = dmg * dmg_mul; } if (dmg <= 0) { dmg = 1; } total_dmg += dmg; } if (bAllMiss) {//pve中 攻击者攻击几率 小于 被攻击者 miss几率时,攻击减益到30% total_dmg = (total_dmg * 30) / 100; } if (tar_pl.dmg_red != 1) {//伤害减免 if (pl.igdmg_red <= 0) { //无视伤害减免几率 total_dmg = (total_dmg * tar_pl.dmg_red); } else { var judg = Utility.random(0, 1000); if (judg >= pl.igdmg_red) { total_dmg = (total_dmg * tar_pl.dmg_red); } } } if (is_pvp && tar_pl.pkdmg_red != 1) { //pvp 伤害减免 total_dmg = (total_dmg * tar_pl.pkdmg_red); } var tlevel = pl.level / 10; if (total_dmg >= 0 && total_dmg < tlevel) { if (tlevel < 1) { tlevel = 1; } total_dmg = tlevel; } // TO DO : sprite damage, 小精灵伤害 if (direct_dmg) { // 计算生命损耗伤害加成 if (frm_sprite != null && pl.hpsuck > 0) { // 损耗自己生命 if (pl.hp > pl.hpsuck) { pl.hp -= pl.hpsuck; if (pl.hp < 0) pl.hp = 0; // broadcast hpchange msg //frm_sprite.broad_cast_zone_msg_and_self(26, {iid=pl.iid, hpchange={hpadd=-pl.hpsuck, die=(pl.hp <= 0), frm_iid=pl.iid}}); //if(pl.cid >0) //{ // var tid = team.get_ply_teamid(pl.cid); // if(tid > 0) // { // // 在队伍中,发送队友属性变化消息 // team_bcast_rpc_except(tid, 138, {cid=pl.cid, hp=pl.hp}, pl.sid); // } //} if (pl.hpsuck_dmgmul > 0) { // 增加攻击伤害 total_dmg = total_dmg * ((1000.0 + pl.hpsuck_dmgmul) / 1000.0); } } } var atk_dmg_mul = pl.atk_dmg_mul; if (pl.igatk_dmg_mul > 0) { //无视伤害增益几率 var judg = Utility.random(0, 1000); if (judg < pl.igatk_dmg_mul) { atk_dmg_mul = 0; } } if (is_pvp) { total_dmg += (total_dmg * ((atk_dmg_mul + pl.pkatk_dmg_mul) / 1000.0)); } else { total_dmg += (total_dmg * (atk_dmg_mul / 1000.0)); } //// 计算技能伤害的属性加成值 //if(damage.ContainsKey("attdmg_mul")) //{ // foreach(var attdmg in damage["attdmg_mul"]) // { // var val = 0; // if(attdmg.name in pl) // { // val = pl[attdmg.name]; // } // total_dmg *= ((attdmg.base + val * attdmg.val ) / attdmg.basediv); // } //} //if("attdmg_add" in damage) //{ // foreach(attdmg in damage.attdmg_add) // { // var val = 0; // if(attdmg.name in pl) // { // val = pl[attdmg.name]; // } // total_dmg += ((attdmg.base + val * attdmg.val ) / attdmg.basediv); // } //} //if((tar_sprite.get_sprite_type()==map_sprite_type.MstMonster) && tar_pl.clanatt_eff) //{ // // 需要计算副本中帮派科技伤害减免 // var clanper = 1000 - tar_pl.clanred + pl.clansred; // //Utility.trace_info("calc clanatt total_dmg["+total_dmg+"] clanper["+clanper+"] pl.clansred["+pl.clansred+"] tar_pl.clanred["+tar_pl.clanred+"]\n"); // total_dmg = (total_dmg * ((clanper)/1000.0)); // //Utility.trace_info("calc clanatt total_dmg["+total_dmg+"]\n"); //} // TO DO : 吸蓝 mpsteal } total_dmg += damage.hp_dmg; total_dmg = (total_dmg * (per / 1000.0)); //sys.dumpobj(damage); //Utility.trace_info("total_dmg:["+total_dmg+"]\n"); if (total_dmg.CompareTo(0) > 0) { var real_atk_dmg = total_dmg; if (total_dmg > 0) { if (frm_sprite != null) { tar_sprite.onhate(frm_sprite, total_dmg); tar_sprite.ondmg(frm_sprite, total_dmg); if (frm_sprite.get_sprite_type() == map_sprite_type.MstPlayer) { if (frm_sprite.gmap.blvlmap) { frm_sprite.gmap.worldsvr.on_dmg(frm_sprite, tar_sprite, total_dmg); } } if (direct_dmg) { frm_sprite.calc_weapon_dura(total_dmg); // 计算装备耐久损耗 frm_sprite.on_make_direct_dmg(); } } if (direct_dmg) { tar_sprite.calc_eqp_dura(total_dmg); // 计算装备耐久损耗 // 计算双倍伤害 if (pl.dobrate > 0) { var judg = Utility.random(0, 1000); if (judg < pl.dobrate) { total_dmg += total_dmg; ret["dobdmg"] = true; } } } // 吸收伤害 total_dmg = pl_absorb_dmg(tar_sprite, tar_pl, total_dmg); // 魔法抵扣生命 total_dmg = pl_hpdmg_2_mpdmg(tar_sprite, tar_pl, total_dmg); // 伤害链接 pl_dmg_link(tar_sprite, tar_pl, total_dmg); } if (is_pvp && total_dmg > 0) { var pkignore_dp = false;//无视dp var pkigdp_rate = pl.pkigdp_rate - tar_pl.pkigdp_rate_debuffs; if (pkigdp_rate > 0) { var judg = Utility.random(0, 1000); pkignore_dp = judg < pkigdp_rate; } if (!pkignore_dp) { if (tar_pl.dp < total_dmg) { var dp_dmg = tar_pl.dp; tar_pl.dp = 0; //剩余值 10倍作用于hp total_dmg = ((total_dmg - dp_dmg));//*tar_sprite.game_conf.ply_hp_dmg_factor); tar_pl.hp -= (int)total_dmg; if (tar_pl.hp < 0) tar_pl.hp = 0; ret["dp_dmg"] = dp_dmg; } else { tar_pl.dp -= (int)total_dmg; if (tar_pl.dp > tar_pl.max_dp) tar_pl.dp = tar_pl.max_dp; ret["dp_dmg"] = total_dmg; total_dmg = 0; } } else { //剩余值 10倍作用于hp total_dmg = (total_dmg * 10);//tar_sprite.game_conf.ply_hp_dmg_factor); tar_pl.hp -= (int)total_dmg; if (tar_pl.hp < 0) tar_pl.hp = 0; } //sys.trace( sys.SLT_DETAIL, "tar_pl.cid =" + tar_pl.cid + " tar_pl.dp = " + tar_pl.dp + " tar_pl.hp = " + tar_pl.hp + "\n"); } else { tar_pl.hp -= (int)total_dmg; if (tar_pl.hp < 0) tar_pl.hp = 0; if (tar_pl.hp > tar_pl.max_hp) tar_pl.hp = tar_pl.max_hp; } // broadcast hpchange msg //tar_sprite.broad_cast_zone_msg_and_self(26, {iid=tar_pl.iid, hpchange={hpadd=-total_dmg, die=(tar_pl.hp <= 0), frm_iid=pl.iid}}); ret["isdie"] = (tar_pl.hp <= 0); ret["dmg"] = total_dmg; //if(tar_pl.cid >0) //{ // var tid = team.get_ply_teamid(tar_pl.cid); // if(tid > 0) // { // // 在队伍中,发送队友属性变化消息 // if( is_pvp ) // { // team_bcast_rpc_except(tid, 138, {cid=tar_pl.cid, hp=tar_pl.hp, dp=tar_pl.dp}, tar_pl.sid); // } // else // { // team_bcast_rpc_except(tid, 138, {cid=tar_pl.cid, hp=tar_pl.hp}, tar_pl.sid); // } // } //} if (tar_pl.hp <= 0) { // die! tar_sprite.die(frm_sprite); } //目标死亡,本次伤害不反弹 if (frm_sprite != null && real_atk_dmg > 0 && tar_pl.iid != pl.iid && tar_pl.hp > 0) { // 反弹伤害 double dmg = 0; if (tar_pl.rev_dmg_mul > 0) { dmg = (real_atk_dmg * ((tar_pl.rev_dmg_mul) / 1000.0)); if (dmg <= 0) dmg = 1; } if (tar_pl.rev_atk > 0) { var judg = Utility.random(0, 1000); if (judg < tar_pl.rev_atk) { dmg += real_atk_dmg; } } //if(is_pvp) //{ // dmg = (dmg * combat_conf.pk_dmg_per/100); //} if (dmg > 0) { // 吸收伤害 dmg = pl_absorb_dmg(frm_sprite, pl, dmg); // 魔法抵扣生命 dmg = pl_hpdmg_2_mpdmg(frm_sprite, pl, dmg); frm_sprite.onhate(tar_sprite, dmg); frm_sprite.ondmg(tar_sprite, dmg); //var frm_hpchange = {frm_iid=tar_pl.iid} if (is_pvp) { //sys.trace( sys.SLT_DETAIL, "pl.dp =" + pl.dp + "pl.hp = "+ pl.hp + "\n"); if (pl.dp < dmg) { var dp_dmg = pl.dp; pl.dp = 0; //剩余值 10倍作用于hp dmg = ((dmg - dp_dmg));//*tar_sprite.game_conf.ply_hp_dmg_factor); pl.hp -= (int)dmg; if (pl.hp < 0) pl.hp = 0; //frm_hpchange.dpadd <- -dp_dmg; //frm_hpchange.hpadd <- -dmg; //frm_hpchange.die <- pl.hp <= 0; } else { pl.dp -= (int)dmg; //frm_hpchange.dpadd <- -dmg; } //sys.dumpobj( frm_hpchange ); } else { pl.hp -= (int)dmg; if (pl.hp < 0) pl.hp = 0; //frm_hpchange.hpadd <- -dmg; //frm_hpchange.die <- pl.hp <= 0; } // broadcast hpchange msg //frm_sprite.broad_cast_zone_msg_and_self(26, {iid=pl.iid, hpchange=frm_hpchange}); //if(pl.cid > 0) ////if("cid" in pl) //{ // var tid = team.get_ply_teamid(pl.cid); // if(tid > 0) // { // // 在队伍中,发送队友属性变化消息 // if ( is_pvp ) // { // team_bcast_rpc_except(tid, 138, {cid=pl.cid, hp=pl.hp, dp=pl.dp}, pl.sid); // } // else // { // team_bcast_rpc_except(tid, 138, {cid=pl.cid, hp=pl.hp}, pl.sid); // } // } //} if (pl.hp <= 0) { // 被弹死了 frm_sprite.die(tar_sprite); } } } } // 魔法值、怒气值调整 var mpchanged = false; //var mpchange_rpc = {}; if (damage.mp_dmg != 0) { var mpdmg = (damage.mp_dmg * per / 1000); tar_pl.mp -= mpdmg; if (tar_pl.mp < 0) tar_pl.mp = 0; if (tar_pl.mp > tar_pl.max_mp) tar_pl.mp = tar_pl.max_mp; //mpchange_rpc.mpadd <- -mpdmg; mpchanged = true; if (frm_sprite != null) { tar_sprite.onhate(frm_sprite, mpdmg); } } if (mpchanged && tar_sprite.get_sprite_type() == map_sprite_type.MstPlayer) { // send mpchange msg //::send_rpc(tar_pl.sid, 32, mpchange_rpc); } return ret; }
public static game_err_code check_target_type(IBaseUnit caster, IBaseUnit tar_sprite, int aff, map_pk_setting_type map_pk_seting) { IMapUnit pl = caster.get_pack_data(); IMapUnit tar_pl = tar_sprite.get_pack_data(); if (pl.iid != tar_pl.iid) { // 作用于其他角色 if ((aff & (int)skill_aff_type.SAT_ENERMY) != (int)skill_aff_type.SAT_ENERMY) { if (caster.can_atk(tar_sprite)) return game_err_code.SKIL_INVALIDE_TAREGET;//敌人 // 根据aff判断盟友关系从而确定是否受此状态影响 var isaily = caster.isaily(tar_sprite); if (isaily) { if ((aff & (int)skill_aff_type.SAT_ALLY) != (int)skill_aff_type.SAT_ALLY) return game_err_code.SKIL_INVALIDE_TAREGET; // 不对盟友产生影响 } else {//中立方 if ((aff & (int)skill_aff_type.SAT_MID) != (int)skill_aff_type.SAT_MID) return game_err_code.SKIL_INVALIDE_TAREGET; } } else if (caster.get_sprite_type() == map_sprite_type.MstPlayer) {// 根据地图、个人pk状态决定是否可以释放技能 if (tar_sprite.get_sprite_type() == map_sprite_type.MstPlayer) { if (map_pk_seting == map_pk_setting_type.MPST_PEACE) return game_err_code.CANT_PK_IN_PEACE_MAP; if (pl.in_pczone || tar_pl.in_pczone) return game_err_code.CANT_PK_IN_PEACE_ZONE; if (map_pk_seting == map_pk_setting_type.MPST_NORMAL) { if (!tar_sprite.can_atk_direct()) { //不可攻击的玩家 if (!caster.can_atk(tar_sprite)) return game_err_code.CANT_ATK; } } else { //pk地图 if (!caster.can_atk(tar_sprite)) return game_err_code.CANT_ATK; } } else if (tar_sprite.get_sprite_type() == map_sprite_type.MstMonster) { if (tar_sprite.owner_ply != null) { //战宠 var owner_sprite = tar_sprite.owner_ply; var ower_pl = owner_sprite.get_pack_data(); if (ower_pl.iid == pl.iid) return game_err_code.CANT_ATTACK_SELF_PET; if (map_pk_seting == map_pk_setting_type.MPST_PEACE) return game_err_code.CANT_PK_IN_PEACE_MAP; if (pl.in_pczone || ower_pl.in_pczone) return game_err_code.CANT_PK_IN_PEACE_ZONE; if (map_pk_seting == map_pk_setting_type.MPST_NORMAL) { if (!owner_sprite.can_atk_direct()) { //不可攻击的玩家 if (!caster.can_atk(owner_sprite)) return game_err_code.CANT_ATK; } } else { //pk地图 if (!caster.can_atk(owner_sprite)) return game_err_code.CANT_ATK; } } else { if (!caster.can_atk(tar_sprite)) return game_err_code.CANT_ATK; } } } else { if (!caster.can_atk(tar_sprite)) return game_err_code.CANT_ATK; } } else { // 作用于自己 if ((aff & (int)skill_aff_type.SAT_SELF) != (int)skill_aff_type.SAT_SELF) return game_err_code.SKIL_INVALIDE_TAREGET; // 不对自己产生影响 } return game_err_code.RES_OK; }
public static void update_pl_state(long cur_clock_tm, IBaseUnit sprite) { var pl = sprite.get_pack_data(); if (pl.states != null) return; var changed = false; //var add_state_rpc = { states =[] }; //var rmv_state_rpc = { iid = pl.iid, ids =[] } var i = 0; for (; i < pl.states.state_par.Count; ++i) { var tm_elapsed = cur_clock_tm - pl.states.state_par[i].start_tm; var val = pl.states.state_par[i]; var rmved = false; IBaseUnit frm_sprite = sprite.gmap.get_sprite_by_iid(val.frm_iid); if (val.end_tm <= cur_clock_tm) { tm_elapsed = val.end_tm - val.start_tm; // time reach, remove pl.states.state_par.RemoveAt(i); --i; changed = true; rmved = true; //rmv_state_rpc.ids.push(val.desc.id); } // update time change states if (tm_elapsed > 500 || rmved) { if (!rmved && tm_elapsed > 500) { tm_elapsed = 500; } var j = 0; var desc_s_states = val.desc.s_states; for (; j < desc_s_states.Count; ++j) { var s_state = desc_s_states[j]; // update hp change if ((s_state.tp & (int)pl_state_type.PST_HP_TIME_ADD) == (int)pl_state_type.PST_HP_TIME_ADD) { int hp_add = (int)((s_state.par * val.par / 1000.0) * tm_elapsed / 1000.0); //Utility.trace_err("pl.iid [" + pl.iid +"] hp_add ["+hp_add+"] \n"); pl.hp += hp_add; if (pl.hp < 0) { pl.hp = 0; // TO DO : die! sprite.die(frm_sprite); //var die_msg_rpc = { iid = pl.iid }; //if (frm_sprite) //{ // die_msg_rpc.frm_iid < -val.frm_iid; //} //// broad cast die msg ////sprite.gmap.broadcast_map_rpc(25, die_msg_rpc); //sprite.broad_cast_zone_msg_and_self(25, die_msg_rpc); // player die, no more update return; } else if (pl.hp > pl.max_hp) { pl.hp = pl.max_hp; } } // update mp change if ((s_state.tp & (int)pl_state_type.PST_MP_TIME_ADD) == (int)pl_state_type.PST_MP_TIME_ADD) { int mp_add = (int)((s_state.par * val.par / 1000.0) * tm_elapsed / 1000.0); //Utility.trace_err("pl.iid [" + pl.iid +"] mp_add ["+mp_add+"] \n"); pl.mp += mp_add; if (pl.mp < 0) { pl.mp = 0; } else if (pl.mp > pl.max_mp) { pl.mp = pl.max_mp; } } } // 处理定时获得指定状态的状态 if (val.desc.timer != null) { var timer = val.desc.timer; val.tm_elapsed += tm_elapsed; int interval = timer.interval; if (val.tm_elapsed >= interval * 100) { val.tm_elapsed -= interval * 100; if (timer.add_stat != null) { var add_stat = timer.add_stat; if (add_stat.tar_state != val.desc.id) { var state_obj = add_state_to_pl(cur_clock_tm, sprite, add_stat, frm_sprite, val.per, false); if (state_obj != null) { changed = true; //add_state_rpc.states.push(state_obj); } } if (timer.dmg != null) { if (timer.rang != null) { apply_rang_eff(cur_clock_tm, sprite, new Point2D(pl.x, pl.y), new List<tres_conf>() { timer.dmg.convert2tres() }, timer.rang, 0, val.par); } else { grid_map.apply_dmg_on_pl(sprite, frm_sprite, timer.dmg.convert2damage(), cur_clock_tm, val.par); } } // 增加直接回蓝、回血功能 // if ("dd" in val.desc.timer) // { // apply_direct_dmg_on_pl(sprite, frm_sprite, val.desc.timer.dd[0], cur_clock_tm, val.par); //} } } } val.start_tm += tm_elapsed; } if (pl.states == null) break; } if (changed) { //sys.trace(sys.SLT_DETAIL, "pl.iid [" + pl.iid +"] state changed \n"); _remark_pl_state(sprite, pl); } //if (add_state_rpc.states.len() > 0) //{ // // broadcast add state msg; // add_state_rpc.iid < -pl.iid; // sprite.broad_cast_zone_msg_and_self(24, add_state_rpc); //} //if (rmv_state_rpc.ids.len() > 0) //{ // // broadcast rmv_state msg // sprite.broad_cast_zone_msg_and_self(31, rmv_state_rpc); //} }
public bool onhate(IBaseUnit atker, int hate_value, bool callhatp = true) { if (this.collect_tar > 0) return false; if (this.mondata.revange == 0) return false; if (this.running_tm > 0) return false; if (atker.isdie()) return false; if (atker.get_sprite_type() == map_sprite_type.MstMonster) if (atker.collect_tar > 0) return false; if (!can_atk(atker)) return false; int atker_iid = atker.get_pack_data().iid; if (this.iid == atker_iid) return false; if (this.monconf.ai.hate_add > 0) { hate_value = this.monconf.ai.hate_add; } if (this.hatelist.ContainsKey(atker_iid)) this.hatelist[atker_iid] += hate_value; else { this.hatelist[atker_iid] = hate_value; if (this.monconf.ai.hatp > 0) { long dist2 = this.mondata.defrang * this.mondata.defrang; foreach (KeyValuePair<int, IBaseUnit> pair in this.gmap.map_mons) { var m = pair.Value as Monster; if (m.iid == this.iid) continue; if (m.monconf.ai.hatp <= 0) continue; if (!same_hatp(m)) continue; if (m.hatelist.ContainsKey(atker_iid)) continue; if (Utility.distance2(this, m) < dist2) { m.onhate(atker, hate_value, false); } } } } if (this.mondata.atking == null) { if (this.mondata.patrol != null && this.mondata.patrol.tracing == null) { this.mondata.patrol.movto.trinitx = (int)this.mondata.x; this.mondata.patrol.movto.trinity = (int)this.mondata.y; this.mondata.patrol.movto.tracing = true; } long now = DateTime.Now.ToBinary(); //Dictionary<string,long> this.mondata.atking = new atking() { tar_iid = atker.iid, start_tm = now - this.mondata.atkcdtm, trace_tm_left = 0 }; //TODO broadcast this.broad_cast_zone_msg(12, new NetMsgData()); } return true; }
//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 bool isaily(IBaseUnit spr) { if (null != this.owner_ply) return this.owner_ply.isaily(spr); if (spr.get_sprite_type() == map_sprite_type.MstMonster && null != spr.owner_ply) { spr = spr.owner_ply; } IMapUnit pl = spr.get_pack_data(); if (pl.lvlsideid > 0) { return pl.lvlsideid == this.mondata.lvlsideid; } if (spr.get_sprite_type() == map_sprite_type.MstMonster) return true; return false; }
public static game_err_code _add_bstate_to_ply(int bstate_id, IBaseUnit ply) { long cur_tm_s = DateTime.Now.ToBinary(); var bstate_conf = Utility.get_bstate_desc(bstate_id); if (bstate_conf == null) { return game_err_code.CONFIG_ERR; } BState cur_exist_bstate = null; //var ret_state = null; IMapUnit pl = ply.get_pack_data(); if (pl.bstates != null) { foreach (var bstate in pl.bstates) { if (bstate.conf.id == bstate_id) { // 已经有这个祝福状态了 cur_exist_bstate = bstate; break; } if (bstate.conf.uni_tp == bstate_conf.uni_tp) { //// 有相同类型的祝福状态(但id不同),不能添加 //return game_err_code.BSTATE_SAME_TP_BSTATE_EXIST; // 移除相同类型不同id的祝福状态 pl.bstates.Remove(bstate); // send bstate_change msg //::send_rpc(ply.pinfo.sid, 19, { rmvid = bstate.id}); break; } } } else { pl.bstates = new List<BState>(); } if (cur_exist_bstate != null) { // 已有同一祝福状态,增加持续时间,更改参数 //ret_state = { id = bstate_conf.id}; if (bstate_conf.eff.maxpar > 0) { if (cur_exist_bstate.par + bstate_conf.eff.par > bstate_conf.eff.maxpar) { // 超出允许叠加参数上限 return game_err_code.MAX_BSTATE_PAR_REACHED; } cur_exist_bstate.par += bstate_conf.eff.par; //ret_state.par < -cur_exist_bstate.par; } if (bstate_conf.merg_tm == 1) { cur_exist_bstate.end_tm = cur_exist_bstate.end_tm + bstate_conf.tm; // 延迟持续时间 } else { cur_exist_bstate.end_tm = cur_tm_s + bstate_conf.tm; // 延迟持续时间 } //ret_state.end_tm < -cur_exist_bstate.end_tm; } else { long ticktm = 0; if (bstate_conf.eff.ticktm > 0) { ticktm = cur_tm_s + bstate_conf.eff.ticktm; } BState bstate = new BState() { id = bstate_conf.id, par = bstate_conf.eff.par, end_tm = cur_tm_s + bstate_conf.tm, ticktm = ticktm, conf = bstate_conf }; pl.bstates.push(bstate); //ret_state = bstate; } // send bstate_change msg //::send_rpc(ply.pinfo.sid, 19, { mod = ret_state}); return game_err_code.RES_OK; }
public void call_petmon(int mid, long fintm) { // 创建出战战斗宠物 if (this.gmap == null) { return; } //相同 战宠 已招则取消召唤 if (petmon_inst != null && petmon_inst.get_pack_data().mid == mid) { release_petmon(); return; } release_petmon(false, false); map_mon_conf monconf = new map_mon_conf() { mid = mid, x = 0, y = 0, r_x = 8, r_y = 8, spwan_time = 0 }; petmon_inst = this.gmap.new_pet_mon(this, monconf); if (null == petmon_inst) { return; } this.pet_mon.mid = mid; this.pet_mon.fintm = fintm; IMapUnit mondata = petmon_inst.get_pack_data(); mondata.follow = new follow() { start_tm = Utility.time(), tar_iid = pinfo.iid, trace_tm_left = 0, frang = 78400, trang = 8100, do_ai = true };//280*280 }
// 移除指定祝福状态 public static void rmv_bstate(int sid, Variant rpc, IBaseUnit ply) { IMapUnit pl = ply.get_pack_data(); if (pl.bstates == null || pl.bstates.Count <= 0) return; int removed_id = rpc["id"]._int32; var to_rmv_idx = 0; BState to_rmv_bstate = null; for (int i = 0; i < pl.bstates.Count; i++) { if (pl.bstates[i].id == removed_id) { to_rmv_bstate = pl.bstates[i]; to_rmv_idx = i; pl.bstates.RemoveAt(i); break; } } if (to_rmv_bstate == null) return; // send bstate_change msg //::send_rpc(ply.pinfo.sid, 19, { rmvid = to_rmv_bstate.id}); }
public void ondmg(IBaseUnit atker, int dmg) { int atker_cid = atker.get_pack_data().cid; long now_s = DateTime.Now.ToBinary(); // 被攻击 if (this.kp_asist_rec) { // 需要记录助攻 if (atker.get_sprite_type() == map_sprite_type.MstMonster) { return; } this.beatk_ply_cids[atker_cid] = now_s; // 记录攻击者cid this.lastdmgtm = now_s; // 记录最后一次受伤害时间 } if (gmap.pk_seting == map_pk_setting_type.MPST_NORMAL) { if (atker.get_sprite_type() == map_sprite_type.MstPlayer) { if (atker_cid != pinfo.cid && !this.can_atk_direct()) { if (!atker.defend_tm_map.ContainsKey(pinfo.cid)) { //是否被正当防御 //是否第一次记录 defend_tm_map[atker_cid] = now_s + 10000; } } } } }
//获取祝福的掉落倍率 public static int _get_bstate_rate_mul(IBaseUnit ply) { IMapUnit pl = ply.get_pack_data(); if (pl.bstates == null || pl.bstates.Count <= 0) return 0; foreach (var bstate in pl.bstates) { if (bstate.conf.eff.tp == (int)bstate_eff_type.BET_RATE_MUL) { return bstate.conf.eff.par; } } return 0; }
public bool can_atk(IBaseUnit spr) { if (spr.get_sprite_type() == map_sprite_type.MstMonster && spr.owner_ply != null) spr = spr.owner_ply; // 用主人代替宠物检查敌我关系 IMapUnit pl = spr.get_pack_data(); if (pl.iid == this.pinfo.iid) return false; //if (spr.get_sprite_type() == map_sprite_type.MstPlayer && pl.level < game_conf.pk_safe_lvl) //{ // return false; //} if (pl.lvlsideid != 0) { if (pinfo.lvlsideid != pl.lvlsideid) return true; if ((gmap != null && !gmap.ignore_side) || spr.get_sprite_type() == map_sprite_type.MstMonster) return false; } bool cannt_pk = false; switch (pinfo.pk_state) { case pk_state_type.PKST_PEACE: cannt_pk = spr.get_sprite_type() == map_sprite_type.MstPlayer; break; case pk_state_type.PKST_PK_ALL: cannt_pk = false; break; case pk_state_type.PKST_PK_TEAM: if (pl.teamid == 0 || pinfo.teamid == 0) cannt_pk = false; else cannt_pk = pl.teamid == pinfo.teamid; break; case pk_state_type.PKST_PK_CLAN: if (pl.clanid == 0 || pinfo.clanid == 0) cannt_pk = false; else cannt_pk = pl.clanid == pinfo.clanid; break; } return !cannt_pk; }
public static void _update_pl_bstate(long cur_tm_s, IBaseUnit ply) { IMapUnit pl = ply.get_pack_data(); if (pl.bstates == null || pl.bstates.Count <= 0) return; var bstates = pl.bstates; for (var idx = 0; idx < bstates.Count; ++idx) { var bstate = bstates[idx]; if (bstate.end_tm < cur_tm_s) { // 到时间,结束状态 bstates.RemoveAt(idx); --idx; // send bstate_change msg //::send_rpc(ply.pinfo.sid, 19, { rmvid = bstate.id}); continue; } if (bstate.ticktm > 0 && bstate.ticktm < cur_tm_s) { // 达到定时触发时间 bstate.ticktm = cur_tm_s + bstate.conf.eff.ticktm; // 更新下次触发时间 var par_change = 0; if (bstate.conf.eff.tp == (int)bstate_eff_type.BET_ADD_HP) { // 增加生命状态 var hp_add = pl.max_hp - pl.hp; if (hp_add <= 0) { continue; } if (hp_add > bstate.conf.eff.add) { hp_add = bstate.conf.eff.add; } if (hp_add > bstate.par) { hp_add = bstate.par; } ply.modify_hp(hp_add); bstate.par -= hp_add; // 扣除存储值 } else if (bstate.conf.eff.tp == (int)bstate_eff_type.BET_ADD_MP) { // 增加法力状态 var mp_add = pl.max_mp - pl.mp; if (mp_add <= 0) { continue; } if (mp_add > bstate.conf.eff.add) { mp_add = bstate.conf.eff.add; } if (mp_add > bstate.par) { mp_add = bstate.par; } ply.modify_mp(mp_add); bstate.par -= mp_add; // 扣除存储值 } else { // err,错误的状态,需要删除 bstate.par = 0; } //var ret_msg = null; if (bstate.par > 0) { //ret_msg = { mod ={ id = bstate.id, par = bstate.par} }; } else { // 消耗完了存储值,删除状态 //ret_msg = { rmvid = bstate.id}; bstates.RemoveAt(idx); --idx; } // send bstate_change msg //::send_rpc(ply.pinfo.sid, 19, ret_msg); } } //if (ply.pinfo.bstates.len() <= 0) //{ // delete ply.pinfo.bstates; //} }