/// <summary> /// 判定某个UniqueID是否处于激活状态 /// </summary> /// <returns><c>true</c>, if under active status was ised, <c>false</c> otherwise.</returns> /// <param name="camp">Camp.</param> /// <param name="UniqueID">Unique I.</param> public ServerLifeNpc findActionNpc(WarUIInfo switchInfo) { ServerLifeNpc activeOne = null; if (switchInfo != null) { WarCamp camp = switchInfo.camp; string UID = switchInfo.ClientID; int UniqueID = switchInfo.uniqueId; List <RoomCharactor> CharactorList = null; bool found = allCharactors.TryGetValue(camp, out CharactorList); if (found) { RoomCharactor existC = CharactorList.Find(c => c.UID == UID); if (existC != null) { WrapperTeam wrapperTeam = (WrapperTeam)existC.team; if (wrapperTeam.activeNpc.UniqueID == UniqueID) { activeOne = wrapperTeam.activeNpc; } } } } return(activeOne); }
//按兵路得到建筑 public List <ServerLifeNpc> GetBuildByWay(CAMP camp, BATTLE_WAY way, bool bAlive = false) { List <ServerLifeNpc> list = GetLifeNPCByType(LifeNPCType.Build, camp); if (list != null && list.Count > 0) { List <ServerLifeNpc> finalList = new List <ServerLifeNpc> (); for (int i = 0; i < list.Count; i++) { ServerLifeNpc bld = list[i]; if (bAlive) { if (bld.dataInScene != null && bld.dataInScene.way == way && bld.IsAlive) { finalList.Add(list [i]); } } else { if (list [i].dataInScene != null && list [i].dataInScene.way == way) { finalList.Add(list [i]); } } } return(finalList); } return(null); }
//清理逻辑 void clearDeadNpcStatus(MsgParam msg, WarServerNpcMgr npcMgr) { WarAnimParam warMsg = msg as WarAnimParam; if (warMsg != null && warMsg.described != null) { int deadNpcId = warMsg.described.srcEnd.param2; ServerNPC npc = npcMgr.GetNPCByUniqueID(deadNpcId); ServerLifeNpc life = npc as ServerLifeNpc; if (life != null) { life.curStatus = NpcStatus.None; /// /// ---- 解除挂载的Trigger ---- /// WarServerManager.Instance.triMgr.RemoveAllTrigger(deadNpcId); /// /// ---- 解除挂载的Buff ---- /// WarServerManager.Instance.bufMgr.rmAllBuff(deadNpcId); //--- 解除仇恨信息 ---- life.clearHatred(); } } }
public override void Update(float deltaTime) { base.Update(deltaTime); #region 更新NPC int count = npcDic.Count; if (count > 0) { foreach (BNPC bnpc in npcDic.Values) { ServerLifeNpc lnpc = bnpc as ServerLifeNpc; if (lnpc != null) { lnpc.UpdateTarget(deltaTime); if (lnpc.runSkMd != null) { lnpc.runSkMd.Update(deltaTime); } } } } #endregion }
/// <summary> /// 这个函数目前没有作用, /// 准备将来用于Buff第一次释放时,需要调用的函数 /// </summary> public void FirstCast(RtBufData rtbf) { /// /// --- 设置NPC的状态 --- /// ServerNPC hang = BFSelector.getHangUp(rtbf); ServerLifeNpc life = hang as ServerLifeNpc; if (life != null) { NpcStatus status = (NpcStatus)Enum.ToObject(typeof(NpcStatus), rtbf.BuffCfg.Status); //去除不需要挂载的状态 status = status.rmDiscrete(); if (status != NpcStatus.None) { life.curStatus = life.curStatus.set(status); } //如果有嘲讽的话 if (status.AnySame(NpcStatus.Taunt)) { life.addHatred(rtbf.CastorNpcID, 1); } } /// /// ---- 释放技能 --- /// castBuff_Skill(rtbf, BuffPhase.Start); }
/// /// 释放技能, pos的第几个技能 /// public void Cast(ServerNPC caster, short pos, Action <MsgParam> Report) { #if DEBUG Utils.Assert(caster == null, "Caster is null when cast skill."); #endif ServerLifeNpc src = caster as ServerLifeNpc; if (src.IsAlive == false) { return; } RtSkData rtSk = src.runSkMd.getRuntimeSkill(pos); /// /// 冷却时间好了吗, 死亡了吗 /// if (rtSk != null && rtSk.canCast) { //进入Skill释放的状态 src.curStatus = src.curStatus.set(NpcStatus.InSkill); IEnumerable <ServerNPC> targets = SelectS.Select(caster, rtSk, Sight.NearSight); EfCastor.Cast(caster, targets, rtSk, Report); } }
/// <summary> /// pos 普通攻击的第几步 /// </summary> public List <MsgParam> NormalAttack(ServerNPC caster, short pos) { container.Clear(); #if DEBUG Utils.Assert(caster == null, "Caster is null when cast skill."); #endif ServerLifeNpc src = caster as ServerLifeNpc; if (src.IsAlive == false) { return(container); } RtSkData rtSk = src.runSkMd.getAttack(pos); if (rtSk != null) { IEnumerable <ServerNPC> targets = SelectS.Select(caster, rtSk, Sight.NearSight); EfCastor.Cast(caster, targets, rtSk, container); } int cnt = container.Count; if (cnt > 0) { for (int i = 0; i < cnt; ++i) { ((WarMsgParam)container[i]).cmdType = WarMsg_Type.Attack; } } return(container); }
public void CastSkill(string CastInfo) { NpcAnimInfo info = JSON.Instance.ToObject <NpcAnimInfo>(CastInfo); ServerLifeNpc npc = monitor.CharactorPool.findActionNpc(info.ui); AsyncTask.QueueOnMainThread( () => { if (npc != null) { npc.SwitchAutoBattle(false); npc.CastSkill(info.index); } }); CastSkillInfo cInfo = new CastSkillInfo() { ClientID = DeviceInfo.GUID, index = info.index, cdTime = npc.runSkMd.getRuntimeSkill(info.index).skillCfg.BaseCD, }; processedMsg = new NetMQMessage(); processedMsg.Append(WarMsgConsts.CastSkRep); processedMsg.Append(JSON.Instance.ToJSON(cInfo)); }
void EnterIncite(RtSkData sk, ServerNPC caster, IEnumerable <ServerNPC> targets) { ConditionConfigure ConCfg = null; //获取激活的判定规则ID列表 int[] IncideCon = sk.skillCfg.Incite; if (IncideCon != null && IncideCon.Length > 0) { int len = IncideCon.Length; for (int i = 0; i < len; ++i) { //获取激活的判定规则ID int CondiId = IncideCon[i]; if (CondiId > 0) { ConCfg = ConModel.get(CondiId); Utils.Assert(ConCfg == null, "Can't find Condition Configure. Condition ID = " + ConCfg); //判定器--- 如果成功就跳出 ICondition decider = Mgr.getImplement(ConCfg.ConditionType); bool suc = decider.check(sk, ConCfg, caster, targets); if (suc) { ServerLifeNpc life = caster as ServerLifeNpc; bool isReset = ConCfg.ConditionClass == SkConditionClass.ResetSkill; life.runSkMd.switchToSkill(sk.pos, ConCfg.TargetSkID, isReset); break; } } } } }
public override void Init() { base.Init(); SelfMilitaryBase = null; EnemyMilitaryBase = null; SelfBuild = new List <ServerLifeNpc>(); EnemyBuild = new List <ServerLifeNpc>(); }
/// <summary> /// 检测回复技能 /// /// 检测逻辑和上面的并不太一致 /// 判定顺序是: /// 0. 判定技能的类型 /// 1. 判定施法者的状态 /// 2. 选在施法的距离(特定范围)内血最少的 英雄 NPC /// </summary> /// <returns><c>true</c>, if cast was caned, <c>false</c> otherwise.</returns> /// <param name="caster">Caster.</param> public bool canCast(ServerNPC caster, RtSkData rtOne) { bool can = true; #if DEBUG Utils.Assert(caster == null, "Can't know whether can cast skill unless caster isn't null."); Utils.Assert(rtOne == null, "Can't know whether can cast skill unless runtime skill isn't null"); #endif SkillConfigData skillCfg = rtOne.skillCfg; /// 0. 判定技能的类型 can = skillCfg.DamageType == 1; if (can == false) { return(can); } /// 1.判定施法者的状态 //只有LifeNPC才检查施法者的状态 ServerLifeNpc castlife = caster as ServerLifeNpc; if (castlife != null) { if (skillCfg.CasterStatusReject.AnySame(castlife.curStatus)) { //不可施法 can = false; } } if (can == false) { return(can); } /// 2. 选在施法的距离(特定范围)内血最少的 英雄 NPC List <ServerNPC> friendlyArmy = SelectorTools.GetNpcWithInRange(caster, skillCfg.Distance, NpcMgr, caster.Camp, KindOfNPC.Life, LifeNPCType.Hero); if (friendlyArmy != null && friendlyArmy.Count > 0) { //选择血最少的 ServerNPC friend = friendlyArmy.OrderBy(npc => (npc.data.rtData.curHp * 1.0f / npc.data.rtData.totalHp)).FirstOrDefault(); if (friend != null) { NPCRuntimeData npcRtdt = friend.data.rtData; float factor = npcRtdt.curHp * 1.0f / npcRtdt.totalHp; //低于20%的 if (factor > 0.2f) { can = false; } } } return(can); }
public void AddNpcMember(ServerLifeNpc npc, int index) { if (realTeam == null) { realTeam = new List <ServerLifeNpc>(); } realTeam.Add(npc); if (index == 0) { activeNpc = npc; } }
/// <summary> /// 获取特定的KindOfNPC,敌友方,有效状态的, 是建筑物还是什么的 活着的NPC /// </summary> /// <returns>ServerNPC 列表</returns> /// <param name="caster">Caster.</param> /// <param name="NpcSource">Npc source.</param> /// <param name="kind">KindOfNPC</param> /// <param name="target">TargetClass</param> /// <param name="TarStatusInCfg">NpcStatus</param> /// <param name="type">LifeNPCType.</param> public static IEnumerable <ServerNPC> GetNPCValideStatus(ServerNPC caster, WarServerNpcMgr NpcSource, KindOfNPC kind, TargetClass target, NpcStatus TarStatusInCfg, LifeNPCType type = LifeNPCType.SkTarAll) { // 临时枚举器 IEnumerable <ServerNPC> Itor1 = null; CAMP camp = CAMP.None; if (target.AnySame(TargetClass.Friendly)) { camp = caster.Camp; } else if (target.AnySame(TargetClass.Hostile)) { camp = caster.Camp.Hostile(); } else { //全阵营 camp = CAMP.All; } Itor1 = NpcSource.getCampBnpc(camp); if (kind == KindOfNPC.Life) { Itor1 = Itor1.Where(n => (n.WhatKindOf() == kind) && (type.check(((ServerLifeNpc)n).WhatTypeOf))); } else if (kind == KindOfNPC.NonLife) { Itor1 = Itor1.Where(n => n.WhatKindOf() == kind); } /// /// --- 筛选出有效状态的NPC ---- /// Itor1 = Itor1.Where(n => { ServerLifeNpc lifeTar = n as ServerLifeNpc; if (lifeTar != null) { return(!lifeTar.curStatus.AnySame(TarStatusInCfg)); } else { return(true); } }); return(Itor1); }
/// <summary> /// 倒计时调用的检查逻辑 /// </summary> /// <param name="fakeSk">Fake sk.</param> public void EnterIncite(RtFakeSkData fakeSk) { ConditionConfigure timeOut = pickUp(fakeSk); Utils.Assert(timeOut == null, "Time out must exist."); float max = timeOut.Param1 * Consts.OneThousand; //超时 if (fakeSk.aliveDur >= max) { ServerLifeNpc life = WarServerManager.Instance.npcMgr.GetNPCByUniqueID(fakeSk.lifeNpcId) as ServerLifeNpc; life.runSkMd.switchToSkill(fakeSk.pos, timeOut.TargetSkID, false); } }
/// <summary> /// 选择的规则是: /// 1. 判定EffectTarget(范围) /// 2. 判定flag-剔除友军,敌军等概念, 进入战斗状态的则再最后判定(状态可能目前并不会去设定) /// 3. 判定EffectTargetType-剔除 /// 4. 每个NPC的概率 /// 5. 判定EffectTargetStatusReject-剔除 /// 6. 选择目标的数量不能超过上限 /// /// </summary> /// <param name="caster">Caster.</param> /// <param name="targets">Targets.</param> /// <param name="efCfg">Ef cfg.</param> public IEnumerable <ServerNPC> Select(ServerNPC caster, IEnumerable <ServerNPC> targets, EffectConfigData efCfg) { #if DEBUG Utils.Assert(efCfg == null, "Effect Selector can't find target unless EffectConfigData isn't null"); #endif List <ServerNPC> reTarget = null; IEnumerable <ServerNPC> itor = null; /// 1. 判定EffectTarget(范围)2. 判定flag-剔除友军,敌军等概念 reTarget = areaSelector.SelectArea(caster, targets, efCfg); /// 3. 判定EffectTargetType-剔除 建筑物 LifeNPCType lifeType = efCfg.EffectTargetType.toPositive(); itor = reTarget.Where(n => lifeType.check(n.data.configData.type)); /// 4. 每个NPC的概率 5.判定EffectTargetStatusReject itor = itor.Where(n => { ServerLifeNpc lifeTar = n as ServerLifeNpc; bool ok = random.happen(efCfg.Prob); if (lifeTar != null) { if (ok) { return(!lifeTar.curStatus.AnySame(efCfg.EffectTargetStatusReject)); } else { return(ok); } } else { return(ok); } } ); ///6. 选择的目标数量不能超过上限 if (efCfg.EffectLimit > 0) { itor = itor.Take(efCfg.EffectLimit); } else if (efCfg.EffectLimit == 0) { itor = new List <ServerNPC>().AsEnumerable <ServerNPC>(); } return(itor); }
/// <summary> /// 返回阵营Camp的LifeNPC列表 /// </summary> /// <returns>The life NPC list by camp.</returns> /// <param name="camp">Camp.</param> public List <ServerLifeNpc> GetLifeNPCListByCamp(CAMP camp) { IEnumerable <ServerNPC> npcs = getCampBnpc(camp); List <ServerLifeNpc> list = new List <ServerLifeNpc>(); foreach (ServerNPC npc in npcs) { ServerLifeNpc life = npc as ServerLifeNpc; if (life != null) { list.Add(life); } } return(list); }
/// <summary> /// 返回可以释放的技能, 这个要一直检测 /// 这个只检查4个技能,不检查普通攻击 /// </summary> /// <returns>The cast.</returns> /// <param name="caster">Caster.</param> /// <param name="target">Target.</param> public List <short> canCast(ServerNPC caster, ServerNPC target) { List <short> skNumList = new List <short>(); #if DEBUG Utils.Assert(caster == null, "Caster is null when check whether can cast skill."); Utils.Assert(target == null, "Target is null when check whether can cast skill."); #endif ServerLifeNpc castLife = caster as ServerLifeNpc; if (castLife.IsAlive == false) { return(skNumList); } short pos = 0; for ( ; pos < Consts.MAX_SKILL_COUNT; ++pos) { RtSkData rtsk = castLife.runSkMd.getRuntimeSkill(pos); if (rtsk != null) { bool can = false; /// /// 冷却时间好了吗 /// can = rtsk.canCast; SkillConfigData skCfg = rtsk.skillCfg; if (skCfg.DamageType == (short)1) { can = can & CanCast.canCast(caster, rtsk); } else if (skCfg.DamageType == (short)0) { can = can & CanCast.canCast(caster, target, rtsk); } //如果可以则加入可释放列表 if (can) { skNumList.Add(pos); } } } return(skNumList); }
//判断target是否是skData的一个有效技能使用目标(不包括cd和距离,值判断能否对target使用) public bool IsValidTarget(ServerNPC caster, ServerNPC target, RtSkData rtsk) { bool isValid = false; ServerLifeNpc castLife = caster as ServerLifeNpc; if (castLife.IsAlive == false) { return(isValid); } if (rtsk != null) { isValid = CanCast.canCast(caster, target, rtsk, true); } return(isValid); }
/// <summary> /// 初始化,采集各种对战所需数据 /// </summary> public override void AnalyzeIfComplete() { //我方基地 List <ServerNPC> npcList = GetNPCListByNum(BASE, CAMP.Player); if (npcList != null && npcList.Count > 0) { SelfMilitaryBase = npcList [0] as ServerLifeNpc; } //敌方基地 npcList = GetNPCListByNum(BASE, CAMP.Enemy); if (npcList != null && npcList.Count > 0) { EnemyMilitaryBase = npcList [0] as ServerLifeNpc; } //我方泉水 npcList = GetNPCListByNum(SPRINGLIFE, CAMP.Player); if (npcList != null && npcList.Count > 0) { SelfSpring = npcList [0]; } //敌方泉水 npcList = GetNPCListByNum(SPRINGLIFE, CAMP.Enemy); if (npcList != null && npcList.Count > 0) { EnemySpring = npcList [0]; } //中立泉水 npcList = GetNPCListByNum(SPRINGLIFE, CAMP.Neutral); if (npcList != null && npcList.Count > 0) { NeutralSpring = npcList [0]; } //己方的建筑 SelfBuild = GetLifeNPCByType(LifeNPCType.Build, CAMP.Player); //敌方的建筑 EnemyBuild = GetLifeNPCByType(LifeNPCType.Build, CAMP.Enemy); }
public void MoveStop(string MoveStopInfo) { AsyncTask.QueueOnMainThread( () => { WarServerManager mgr = WarServerManager.Instance; if (mgr != null) { NpcAnimInfo info = JSON.Instance.ToObject <NpcAnimInfo>(MoveStopInfo); ServerLifeNpc npc = monitor.CharactorPool.findActionNpc(info.ui); WarSrcAnimParam param = new WarSrcAnimParam(); param.cmdType = WarMsg_Type.Stand; param.param = MoveStopInfo; mgr.npcMgr.SendMessageAsync(npc.UniqueID, npc.UniqueID, param); } } ); processedMsg = new NetMQMessage(); processedMsg.Append(WarMsgConsts.MoveStopRep); }
//不检查CD,不检查距离 public bool isVaild(ServerNPC caster, ServerNPC target, short pos) { bool isValid = false; ServerLifeNpc castLife = caster as ServerLifeNpc; if (castLife.IsAlive == false) { return(isValid); } RtSkData rtsk = castLife.runSkMd.getRuntimeSkill(pos); if (rtsk != null) { isValid = CanCast.canCast(caster, target, rtsk, true); } return(isValid); }
public void CastSk(params Object[] args) { if (castor != null && param != null) { WarSrcAnimParam srcParam = param as WarSrcAnimParam; if (srcParam != null) { SelfDescribed sd = srcParam.described; if (sd != null) { EndResult result = sd.srcEnd; // float x = result.param8; // float z = result.param9; Vector3 pos = Vector3.zero; // castor.transform.position = pos; // castor.SendNpcMoveMsg(true); if (castor is ServerLifeNpc) { ServerLifeNpc sCastor = castor as ServerLifeNpc; sCastor.HitAnimReset(); } int clearFlag = result.param1; if (clearFlag == 0) { ServerNPC npc = castor.getOneChildNpc(result.param2); if (npc != null) { pos = npc.transform.position; pos.y = 0.1f; castor.transform.position = pos; castor.SendNpcMoveMsg(true); castor.removeChild(npc); WarServerManager mgr = WarServerManager.Instance; IpcDestroyNpcMsg msg = new IpcDestroyNpcMsg(); msg.id = npc.UniqueID; mgr.realServer.proxyCli.NpcDestroy(msg); UnityEngine.GameObject.Destroy(npc.gameObject); } } } } } }
//切换英雄 public bool SwitchActiveHero(SwitchInfo si) { bool ok = false; if (si != null) { List <RoomCharactor> CharactorList = null; bool found = allCharactors.TryGetValue(si.camp, out CharactorList); if (found) { RoomCharactor existC = CharactorList.Find(c => c.UID == si.ClientID); if (existC != null) { WrapperTeam wTeam = (WrapperTeam)existC.team; ok = true; ServerLifeNpc npc = wTeam.realTeam.Find(s => s.UniqueID == si.UniqueID); wTeam.activeNpc = npc; AsyncTask.QueueOnMainThread( () => { if (npc != null) { //前一个主英雄英雄切换为自动战斗 if (WarServerManager.Instance.battleStart) { wTeam.activeNpc.SwitchAutoBattle(true); } if (WarServerManager.Instance.battleStart) { wTeam.activeNpc.SwitchAutoBattle(existC.autoBattle); } } } ); } } } return(ok); }
public void Attack(string AttackInfo) { AsyncTask.QueueOnMainThread( () => { WarServerManager mgr = WarServerManager.Instance; if (mgr != null) { NpcAnimInfo info = JSON.Instance.ToObject <NpcAnimInfo>(AttackInfo); ServerLifeNpc npc = monitor.CharactorPool.findActionNpc(info.ui); if (npc != null) { npc.Attack(); } } } ); processedMsg = new NetMQMessage(); processedMsg.Append(WarMsgConsts.AttackRep); }
//NPC是否控制的主英雄 public bool IsHeroActive(ServerLifeNpc npc) { WarCamp warCamp = WarCamp2Camp.toWarCamp(npc.Camp); List <RoomCharactor> chaList = get(warCamp); if (chaList != null) { int len = chaList.Count; for (int i = 0; i < len; i++) { WrapperTeam team = chaList[i].team as WrapperTeam; if (team.activeNpc.UniqueID == npc.UniqueID) { return(true); } } } return(false); }
public void Update(float delTime) { foreach (RtBufData buf in OnWork.Values) { if (buf != null) { working.Add(buf); } } int workCnt = working.Count; if (workCnt > 0) { for (int i = 0; i < workCnt; ++i) { RtBufData buf = working[i]; bool alive = buf.Update(delTime); if (!alive) { rmBuff(buf.ID, buf.HangUpNpcID, true); } /// /// 判定当前的是否是引导技能 /// if (buf.canInterrupt) { //检测是否已被打断 ServerNPC npc = NpcMgr.GetNPCByUniqueID(buf.HangUpNpcID); ServerLifeNpc life = npc as ServerLifeNpc; bool interrupt = life.curStatus.AnySame(NpcStatus.Interrupt); if (interrupt) { rmBuff(buf.ID, buf.HangUpNpcID); } } } working.Clear(); } }
/// <summary> /// 根据LifeNPCType类型和camp得到npc /// </summary> /// <returns>The life NPC by type.</returns> /// <param name="type">Type.</param> /// <param name="camp">Camp.</param> public List <ServerLifeNpc> GetLifeNPCByType(LifeNPCType type, CAMP camp) { List <ServerLifeNpc> list = new List <ServerLifeNpc> (); foreach (KeyValuePair <int, ServerNPC> itor in npcDic) { ServerLifeNpc lifenpc = itor.Value as ServerLifeNpc; if (lifenpc != null && lifenpc.WhatTypeOf == type) { if (camp == CAMP.None) { list.Add(lifenpc); } else if (lifenpc.Camp == camp) { list.Add(lifenpc); } } } return(list); }
//按兵路得到建筑 public List <ServerLifeNpc> GetBuildByType(CAMP camp, BuildNPCType type) { List <ServerLifeNpc> list = new List <ServerLifeNpc>(); foreach (KeyValuePair <int, ServerNPC> itor in npcDic) { ServerLifeNpc lifenpc = itor.Value as ServerLifeNpc; if (lifenpc != null && lifenpc.WhatTypeOf == LifeNPCType.Build && lifenpc.IsAlive && lifenpc.data.configData.bldType == type) { if (camp == CAMP.None || camp == CAMP.All) { list.Add(lifenpc); } else if (lifenpc.Camp == camp) { list.Add(lifenpc); } } } return(list); }
public void ManualAuto(string autoInfo) { ManualOrAuto auto = JSON.Instance.ToObject <ManualOrAuto>(autoInfo); processedMsg = new NetMQMessage(); bool isAuto = false; bool ok = monitor.CharactorPool.SwitchManulOrAuto(auto, ref isAuto); if (ok) { processedMsg.Append(WarMsgConsts.ManualOrAutoRep); processedMsg.Append(isAuto ? "1" : "0"); //如果战斗开始了,切换AI if (WarServerManager.Instance.battleStart) { WarUIInfo ui = new WarUIInfo(); ui.camp = auto.camp; ui.ClientID = auto.ClientID; ui.uniqueId = auto.UniqueID; ServerLifeNpc npc = monitor.CharactorPool.findActionNpc(ui); //TODO : switch AI AsyncTask.QueueOnMainThread(() => { if (npc != null) { npc.SwitchAutoBattle(isAuto); } }); } } else { processedMsg.Append(WarMsgConsts.ManualOrAutoRepE); } }
/// <summary> /// 搜索攻击目标 /// </summary> /// <returns>The atk targets.</returns> public IEnumerable <ServerNPC> FindAtkTargets(ServerNPC caster, short pos, Sight sight) { #if DEBUG Utils.Assert(caster == null, "Caster is null when cast skill."); #endif ServerLifeNpc src = caster as ServerLifeNpc; if (src.IsAlive == false) { return(null); } RtSkData rtSk = src.runSkMd.getAttack(pos); if (rtSk != null) { IEnumerable <ServerNPC> targets = SelectS.Select(caster, rtSk, sight); return(targets); } else { return(null); } }