/// <summary> /// Gets the npc with in range. /// </summary> /// <returns>The npc with in range.</returns> /// <param name="anchor">起点</param> /// <param name="range">范围</param> /// <param name="NpcSource">NPC 容器</param> /// <param name="capm">阵营</param> /// <param name="kind">是否是lifeNpc</param> /// <param name="type">如果是LifeNpc的时候,又是什么子类型</param> public static List <ServerNPC> GetNpcWithInRange(ServerNPC caster, float range, WarServerNpcMgr NpcSource, CAMP camp, KindOfNPC kind, LifeNPCType type = LifeNPCType.SkTarAll) { IEnumerable <ServerNPC> filter = NpcSource.getCampBnpc(camp); if (kind == KindOfNPC.Life) { filter = filter.Where(n => (n.WhatKindOf() == kind) && (type.check(((ServerLifeNpc)n).WhatTypeOf))); } else if (kind == KindOfNPC.NonLife) { filter = filter.Where(n => n.WhatKindOf() == kind); } int count = filter.Count(); if (count > 0) { Vector3 anchor = caster.transform.position; float radius = caster.data.configData.radius; filter = filter.Where(n => IsInRange(anchor, n.data.configData.radius + range + radius, n.transform)); } return(filter.ToList()); }
/// <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> /// 选择的规则是: /// 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> /// 检测伤害技能能否释放, /// 回血,恢复之类的技能不做检测 /// /// 判定顺序是: /// 0. 判定技能的类型 /// 1. 判定是否是相同的阵营 /// 2. 判定施法者的状态 /// 3. 判定目标是什么类型的NPC(比如建筑物,英雄。。。) /// 3. 判定施法的距离 /// 5. 目标的状态 /// /// </summary> /// <returns><c>true</c>, if cast was caned, <c>false</c> otherwise.</returns> public bool canCast(ServerNPC caster, ServerNPC target, RtSkData rtOne, bool ignoreDis = false) { bool can = true; #if DEBUG Utils.Assert(caster == null, "Can't know whether can cast skill unless caster isn't null."); Utils.Assert(target == null, "Can't know whether can cast skill unless target 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 == 0; if (can == false) { return(can); } /// 1.判定是否是相同的阵营 can = caster.Camp != target.Camp; if (can == false) { return(can); } /// 2. 判定施法者的状态 //只有LifeNPC才检查施法者的状态 ServerLifeNpc castlife = caster as ServerLifeNpc; if (castlife != null) { if (skillCfg.CasterStatusReject.AnySame(castlife.curStatus)) { //不可施法 can = false; } } if (can == false) { return(can); } /// 3. 判定目标是什么类型的NPC LifeNPCType type = skillCfg.TargetType.toPositive(); can = type.check(target.data.configData.type); if (can == false) { return(can); } /// 4. 判定施法的距离 if (ignoreDis == false) { can = AITools.IsInRange(caster.transform.position, skillCfg.Distance, target.transform); if (can == false) { return(can); } } /// 5. 目标的状态 ServerLifeNpc targetLife = target as ServerLifeNpc; if (targetLife != null) { if (targetLife.curStatus.AnySame(skillCfg.TargetStatusReject)) { //不可施法 can = false; } } return(can); }
//可以选择单个目标,也可以是多个目标 //提供给SkillSelecotr使用 public static IEnumerable <ServerNPC> GetNPCInRange(ServerNPC caster, float range, WarServerNpcMgr NpcSource, KindOfNPC kind, TargetClass target, NpcStatus TarStatusInCfg, LifeNPCType type = LifeNPCType.SkTarAll) { List <ServerNPC> found = new List <ServerNPC>(); /// /// 枚举器,其实不用返回特定类型,返回枚举器就可以了。(在不需要Copy容器里面的数据时,就是用枚举器) /// IEnumerable <ServerNPC> Itor = found.AsEnumerable(); // 临时枚举器 IEnumerable <ServerNPC> Itor1 = null; Vector3 anchor = caster.transform.position; Transform trans = caster.transform; ServerNPC nearest = null; CAMP camp = CAMP.None; if (target.AnySame(TargetClass.Friendly)) { camp = caster.Camp; } else if (target.AnySame(TargetClass.Hostile)) { camp = caster.Camp.Hostile(); } 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); } bool any = Itor1 != null?Itor1.Any() : false; if (any) { /// /// --- 筛选出有效状态的NPC ---- /// Itor1 = Itor1.Where(n => { ServerLifeNpc lifeTar = n as ServerLifeNpc; if (lifeTar != null) { return(!lifeTar.curStatus.AnySame(TarStatusInCfg)); } else { return(true); } }); /// /// --- 再次根据距离条件筛选出NPC ---- /// float radius = caster.data.configData.radius; Itor1 = Itor1.Where(n => IsInRange(anchor, n.data.configData.radius + radius + range, n.transform)); if (target.AnySame(TargetClass.FarAwary)) { nearest = Itor1.OrderByDescending(n => GetVirtualDistance(trans, n.transform)).FirstOrDefault(); if (nearest != null) { found.Add(nearest); } } else if (target.AnySame(TargetClass.Nearest)) { nearest = Itor1.OrderBy(n => GetVirtualDistance(trans, n.transform)).FirstOrDefault(); if (nearest != null) { found.Add(nearest); } } else { Itor = Itor1; } /// /// --- 判定最大,最小生命值的NPC ----- /// if (target.AnySame(TargetClass.HpLowest)) { ServerNPC lowest = Itor1.OrderBy(n => n.data.rtData.CurHpNested).FirstOrDefault(); if (lowest != null) { found.Add(lowest); } } else if (target.AnySame(TargetClass.HpHighest)) { ServerNPC highest = Itor1.OrderByDescending(n => n.data.rtData.CurHpNested).FirstOrDefault(); if (highest != null) { found.Add(highest); } } } return(Itor); }