예제 #1
0
        //选择目标
        List <ServerNPC> selectTarget(BulletHurtType HurtType, ServerNPC suffer, bool isFinal, WarServerNpcMgr npcMgr, float radius)
        {
            List <ServerNPC> target = new List <ServerNPC>();

            switch (HurtType)
            {
            /// 伤害所有碰见的敌人
            case BulletHurtType.Keep_Dmg:
                target.Add(suffer);
                break;

            /// 伤害最终的敌人
            case BulletHurtType.Final_Target_Radius:
                if (isFinal)
                {
                    /// --- 默认对敌人的各种类型友方产生攻击 ---
                    ///
                    IEnumerable <ServerNPC> itor = SelectorTools.GetNPCInRange(suffer, radius, npcMgr, KindOfNPC.Life, TargetClass.Friendly, NpcStatus.None);
                    target.AddRange(itor);
                }
                break;

            /// 伤害最终的敌人
            case BulletHurtType.Final_Target:
                if (isFinal)
                {
                    target.Add(suffer);
                }
                break;
            }

            return(target);
        }
예제 #2
0
        /// <summary>
        /// 这个Targets不能为空
        /// </summary>
        /// <param name="caster">Caster.</param>
        /// <param name="targets">Targets.</param>
        /// <param name="efCfg">Ef cfg.</param>
        /// <param name="npcMgr">Npc mgr.</param>
        public List <ServerNPC> Select(ServerNPC caster, List <ServerNPC> targets, EffectConfigData efCfg, WarServerNpcMgr npcMgr)
        {
                        #if DEBUG
            Utils.Assert(efCfg == null, "Can't find target unless EffectConfigData isn't null.");
            Utils.Assert(npcMgr == null, "Can't find target unless WarServerNpcMgr isn't null.");
            Utils.Assert(targets == null, "Can't find target unless targets isn't null.");
                        #endif

            List <ServerNPC> reTarget = new List <ServerNPC>();
            //转换为Camp类型,还有一部分的检查不在这里
            //剔除自己的是在Factory里面(即EffectAreaSector)
            CAMP camp = efCfg.Flags.switchTo(caster.Camp);

            int count = targets.Count;
            if (count > 0)
            {
                for (int i = 0; i < count; ++i)
                {
                    UVec3 anchor = targets[i].transform.position;
                    reTarget.AddRange(SelectorTools.GetNPCRadius(anchor, caster.data.configData.radius + efCfg.eParam1, camp, npcMgr));
                }
            }

            return(reTarget);
        }
예제 #3
0
        /// <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);
        }
예제 #4
0
        void HandleDistance()
        {
            List <ServerNPC> outOfRange = new List <ServerNPC>();
            List <int>       Rmed       = new List <int>();

            ServerNPC castor = null;
            int       cnt    = checkList.Count;

            for (int i = 0; i < cnt; ++i)
            {
                Pair  pair   = checkList[i];
                float radius = pair.castor.data.configData.radius +
                               pair.target.data.configData.radius + cfg.Param1 * Consts.OneThousand;
                bool isIn = SelectorTools.IsInRange(pair.castor.transform.position, radius, pair.target.transform.position);
                if (isIn == false)
                {
                    castor = pair.castor;
                    outOfRange.Add(pair.target);
                    Rmed.Add(i);
                }
            }

            if (outOfRange.Count > 0)
            {
                ///
                /// 做一个概率上的检测
                ///
                IEnumerable <ServerNPC> itor = outOfRange.Where(n => PseudoRandom.getInstance().happen(cfg.Prob));
                warMgr.triMgr.trigCastor.cast(castor, itor, cfg);
            }

            if (Rmed.Count > 0)
            {
                int count = Rmed.Count;
                for (int i = 0; i < count; ++i)
                {
                    checkList.RemoveAt(Rmed[i]);
                }
            }
        }
예제 #5
0
        /// <summary>
        /// 扇形选择区域
        /// </summary>
        /// <param name="caster">Caster.</param>
        /// <param name="targets">Targets 不适用,,可以为Null</param>
        /// <param name="efCfg">Effect的配置</param>
        /// <param name="npcMgr">WarNpcManager</param>
        public List <ServerNPC> Select(ServerNPC caster, List <ServerNPC> targets, EffectConfigData efCfg, WarServerNpcMgr npcMgr)
        {
                        #if DEBUG
            Utils.Assert(caster == null, "Can't find targets unless caster isn't null.");
            Utils.Assert(efCfg == null, "Can't find targets unless EffectConfigData isn't null.");
            Utils.Assert(npcMgr == null, "Can't find targets unless WarServerNpcMgr isn't null.");
                        #endif

            //转换为Camp类型,还有一部分的检查不在这里
            //剔除自己的是在Factory里面(即EffectAreaSector)
            CAMP camp = efCfg.Flags.switchTo(caster.Camp);

            Transform trans = caster.transform;
            float     Y     = trans.localPosition.y;
            //角度转化为弧度
            float angel  = Mathf.Deg2Rad * efCfg.eParam2 * 0.5f;
            float radius = efCfg.eParam1 + caster.data.configData.radius;
            float X      = Mathf.Sin(angel) * radius;
            float Z      = Mathf.Cos(angel) * radius;

            //本地坐标
            UVec3[] localVecs = new UVec3[4];
            localVecs[0] = new UVec3()
            {
                x = 0F,
                y = Y,
                z = 0F,
            };

            localVecs[1] = new UVec3()
            {
                x = -X,
                y = Y,
                z = Z,
            };

            localVecs[2] = new UVec3()
            {
                x = 0,
                y = Y,
                z = radius,
            };

            localVecs[3] = new UVec3()
            {
                x = X,
                y = Y,
                z = Z,
            };

            //世界坐标
            UVec3[] worldVecs = new UVec3[4];
            worldVecs[0] = trans.TransformPoint(localVecs[0]);
            worldVecs[1] = trans.TransformPoint(localVecs[1]);
            worldVecs[2] = trans.TransformPoint(localVecs[2]);
            worldVecs[3] = trans.TransformPoint(localVecs[3]);


            //转换为2D坐标
            PointF[] Vecs = new PointF[4];
            Vecs[0] = new PointF()
            {
                X = worldVecs[0].x,
                Y = worldVecs[0].z
            };
            Vecs[1] = new PointF()
            {
                X = worldVecs[1].x,
                Y = worldVecs[1].z
            };
            Vecs[2] = new PointF()
            {
                X = worldVecs[2].x,
                Y = worldVecs[2].z
            };
            Vecs[3] = new PointF()
            {
                X = worldVecs[3].x,
                Y = worldVecs[3].z
            };

            Polygon          polygon    = new Polygon(Vecs);
            List <ServerNPC> TargetList = SelectorTools.GetNPCPolygon(polygon, camp, npcMgr).ToList();
            return(TargetList);
        }
예제 #6
0
        /// <param name="targets">没用的</param>
        public List <ServerNPC> Select(ServerNPC caster, List <ServerNPC> targets, EffectConfigData efCfg, WarServerNpcMgr npcMgr)
        {
                        #if DEBUG
            Utils.Assert(caster == null, "Can't find target unless caster isn't null.");
            Utils.Assert(efCfg == null, "Can't find target unless EffectConfigData isn't null.");
            Utils.Assert(npcMgr == null, "Can't find target unless WarServerNpcMgr isn't null.");
                        #endif

            //转换为Camp类型,还有一部分的检查不在这里
            //剔除自己的是在Factory里面(即EffectAreaSector)
            CAMP camp = efCfg.Flags.switchTo(caster.Camp);

            UTran trans = caster.transform;
            float Y     = trans.localPosition.y;

            float halfWidth = efCfg.eParam2 * 0.5F + caster.data.configData.radius;
            float Height    = efCfg.eParam1 + caster.data.configData.radius;

            UVec3[] localVecs = new UVec3[4];
            localVecs[0] = new UVec3(-halfWidth, Y, 0f);
            localVecs[1] = new UVec3(-halfWidth, Y, Height);
            localVecs[2] = new UVec3(halfWidth, Y, Height);
            localVecs[3] = new UVec3(halfWidth, Y, 0f);


            UVec3[] WorldVecs = new UVec3[4];
            WorldVecs[0] = trans.TransformPoint(localVecs[0]);
            WorldVecs[1] = trans.TransformPoint(localVecs[1]);
            WorldVecs[2] = trans.TransformPoint(localVecs[2]);
            WorldVecs[3] = trans.TransformPoint(localVecs[3]);

            //caster.transform.forward;
            PointF[] vecs = new PointF[4];

            vecs[0] = new PointF()
            {
                X = WorldVecs[0].x,
                Y = WorldVecs[0].z,
            };

            vecs[1] = new PointF()
            {
                X = WorldVecs[1].x,
                Y = WorldVecs[1].z,
            };

            vecs[2] = new PointF()
            {
                X = WorldVecs[2].x,
                Y = WorldVecs[2].z,
            };

            vecs[3] = new PointF()
            {
                X = WorldVecs[3].x,
                Y = WorldVecs[3].z,
            };

            Polygon rectangle = new Polygon(vecs);

            List <ServerNPC> TargetList = SelectorTools.GetNPCPolygon(rectangle, camp, npcMgr).ToList();
            return(TargetList);
        }
예제 #7
0
        /// <summary>
        /// 选择的规则是:
        ///  多目标判定规则
        /// 1. 判定施法者的状态
        /// 2. 判定施法者的上次目标,如果目标在攻击范围内,则选择为最优先目标
        /// 3. 判定施法的范围类型
        /// 4. 目标的状态
        /// 5. 根据施法的距离选择出目标
        /// 6. 根据血量选择出目标
        /// 7. 目标的优先级
        /// 8. 单体攻击敌方,并且有最高优先级的目标
        ///
        ///
        /// 单目标判定规则
        ///
        ///
        ///
        /// </summary>
        /// <returns><c>true</c>, if cast was caned, <c>false</c> otherwise.</returns>
        public IEnumerable <ServerNPC> Select(ServerNPC caster, RtSkData rtOne, Sight sight)
        {
            //枚举器
            IEnumerable <ServerNPC> itor = null, itor1 = null;

                        #if DEBUG
            Utils.Assert(caster == null, "Can't find target unless caster isn't null");
            Utils.Assert(rtOne == null, "Can't find target unless runtime skill isn't null");
                        #endif


            SkillConfigData skillCfg = rtOne.skillCfg;

            /// 视野范围 -- 决定索敌范围
            float CheckDistance = 0F;
            if (sight == Sight.NearSight)
            {
                CheckDistance = skillCfg.Distance;
            }
            else
            {
                CheckDistance = caster.data.rtData.seekRange;
            }

            bool castcan = true;
            //只有LifeNPC才检查施法者的状态
            //1. 判定施法者的状态
            ServerLifeNpc castlife = caster as ServerLifeNpc;
            if (castlife != null)
            {
                if (castlife.curStatus.AnySame(skillCfg.CasterStatusReject))
                {
                    //不可施法
                    castcan = false;
                }
            }

            if (castcan == false)
            {
                return(new List <ServerNPC>().AsEnumerable <ServerNPC>());
            }
            //能进入CD
            rtOne.EnterCD();

            ///
            /// 3. 判定施法的范围类型 .
            /// 单体和AOE都需要在技能配置里选择出目标 , 再次到Effect里面选择目标。 -- 叫做前置判定
            /// 方向性则不需要选择目标,该类型的技能可对空地释放,再次到EffectTarget的目标是skill的目标 -- 叫做后置判定
            ///

            TargetClass rtTargetCls = skillCfg.SkillTarget;

            if (skillCfg.RangeType == RangeClass.Direction)
            {
                //后置判定
                return(new List <ServerNPC>().AsEnumerable <ServerNPC>());
            }

            bool isMultiTarget = skillCfg.RangeType != RangeClass.SingleTarget;
            bool isNoPriority  = skillCfg.TargetPriority == SkTargetPriority.NonePriority;
            bool isTargetSelf  = rtTargetCls.AnySame(TargetClass.Self);
            //单目标
            ServerNPC singlePriority = null;

            LifeNPCType type = skillCfg.TargetType.toPositive();
            ///
            /// 是否为多目标的战斗, 或者是没有优先级的单目标
            ///
            if (isMultiTarget || isNoPriority || isTargetSelf)
            {
                ///
                /// 4. 目标的状态
                ///
                if (rtTargetCls.AnySame(TargetClass.Friendly))
                {
                    //友方
                    itor1 = SelectorTools.GetNPCValideStatus(caster, npcMgr, KindOfNPC.Life, rtTargetCls, NpcStatus.None, type);
                }
                else if (rtTargetCls.AnySame(TargetClass.Hostile))
                {
                    //敌方
                    itor1 = SelectorTools.GetNPCValideStatus(caster, npcMgr, KindOfNPC.Life, rtTargetCls, skillCfg.TargetStatusReject, type);
                }
                else if (rtTargetCls.AnySame(TargetClass.Self))
                {
                    //自己
                    List <ServerNPC> targets = new List <ServerNPC>();
                    targets.Add(caster);
                    itor = targets.AsEnumerable <ServerNPC>();
                    return(targets);
                }
                else
                {
                    itor1 = SelectorTools.GetNPCValideStatus(caster, npcMgr, KindOfNPC.Life, rtTargetCls, skillCfg.TargetStatusReject, type);
                    ConsoleEx.DebugLog("Warning : We should have a Camp. But sometimes, it's Ok.", ConsoleEx.RED);
                }

                ///
                /// 5. 根据施法的距离选择出目标
                ///

                itor1 = SelectorTools.GetNPCInRadius(caster, CheckDistance, rtTargetCls, itor1);

                ///
                /// 6. 根据血量选择出目标
                ///
                itor1 = SelectorTools.GetNPCByHp(caster, rtTargetCls, itor1);

                if (isNoPriority)
                {
                    singlePriority = itor1.FirstOrDefault();
                }
            }
            else
            {
                ///
                /// 获取单目标
                ///

                singlePriority = SelectorTools.GetPrioritiedNpc(caster, rtTargetCls, npcMgr, CheckDistance, skillCfg.TargetStatusReject, skillCfg.TargetPriority, priorityMgr, type);

                //单目标的友方,有可能选择到自己(但并不属于 TargetClass 64.就针对自己)
                if (!rtTargetCls.AnySame(TargetClass.Hostile))
                {
                    List <ServerNPC> broker = new List <ServerNPC>();
                    if (singlePriority != null)
                    {
                        broker.Add(singlePriority);
                    }
                    itor1 = broker.AsEnumerable <ServerNPC>();
                }
            }

            if (isMultiTarget == false)
            {
                ///
                /// 9. 单体攻击敌方,只有打敌方单体的时候,TargetID才会被重新设定
                ///
                if (rtTargetCls.AnySame(TargetClass.Hostile))
                {
                    ServerLifeNpc HighestPriority = null;
                    ///
                    /// 检测嘲讽
                    ///
                    int tarId = caster.getHighestHatred;
                    if (tarId != -1)
                    {
                        //有被嘲讽的目标
                        HighestPriority = npcMgr.GetNPCByUniqueID(tarId) as ServerLifeNpc;
                    }
                    else
                    {
                        //没有被嘲讽的目标

                        ///
                        ///  判定施法者的上次目标,则选择为最优先目标
                        ///  此逻辑,能保证追击残血逃跑的
                        ///

                        if (caster.TargetID != -1)
                        {
                            HighestPriority = npcMgr.GetNPCByUniqueID(caster.TargetID) as ServerLifeNpc;
                            if (HighestPriority != null)
                            {
                                ///
                                /// 如果单一目标的是英雄,
                                ///
                                if (singlePriority != null && singlePriority.data.configData.type == LifeNPCType.Hero &&
                                    HighestPriority.data.configData.type != LifeNPCType.Hero)
                                {
                                    HighestPriority = null;
                                    caster.TargetID = -1;
                                }
                                else
                                {
                                    bool validate1 = true, validate2 = true, validate3 = true;
                                    /// 生命判定
                                    if (HighestPriority.data.rtData.curHp <= 0)
                                    {
                                        validate1 = false;
                                    }

                                    /// 距离判定
                                    float distance = SelectorTools.GetDistance(HighestPriority.transform.position, caster.transform.position);
                                    distance = distance - HighestPriority.data.configData.radius - caster.data.configData.radius;

                                    /// 视野范围
                                    if (distance > CheckDistance)
                                    {
                                        validate2 = false;
                                    }

                                    ///如果有相同的状态,则不让释放技能
                                    validate3 = !HighestPriority.curStatus.AnySame(skillCfg.TargetStatusReject);

                                    /// 失败的判定
                                    bool validate = validate1 & validate2 & validate3;
                                    if (!validate)
                                    {
                                        HighestPriority = null;
                                        caster.TargetID = -1;
                                    }
                                    else
                                    {
                                        caster.RstTimeout();
                                    }
                                }
                            }
                            else
                            {
                                caster.TargetID = -1;
                            }
                        }
                    }

                    //找到普通选择出的目标
                    if (HighestPriority == null)
                    {
                        ServerNPC target = singlePriority;
                        caster.TargetID = target != null ? target.UniqueID : -1;
                        HighestPriority = target as ServerLifeNpc;
                    }

                    List <ServerNPC> high = new List <ServerNPC>();
                    if (HighestPriority != null)
                    {
                        high.Add(HighestPriority);
                    }
                    itor1 = high.AsEnumerable <ServerNPC>();
                }
                else
                {
                    ///
                    /// 10.单体友方
                    ///
                    if (itor1.Any())
                    {
                        itor1 = itor1.Take(1);
                    }
                }
            }


            itor = itor1;
            return(itor);
        }