예제 #1
0
        private void GetAreaOfEffectPrediction(PredictionInput input, PredictionOutput output)
        {
            var targets = new List <PredictionOutput>();

            // aoe targets
            foreach (var target in input.AreaOfEffectTargets.Where(e => e.Handle != output.Unit.Handle))
            {
                var targetPrediction = this.GetSimplePrediction(input.WithTarget(target));

                if (this.IsInRange(input, targetPrediction.UnitPosition))
                {
                    targets.Add(targetPrediction);
                }
            }

            switch (input.PredictionSkillshotType)
            {
            case PredictionSkillshotType.SkillshotCircle:

                if (input.AreaOfEffectHitMainTarget)
                {
                    // main target
                    targets.Insert(0, output);

                    while (targets.Count > 1)
                    {
                        var mecResult = MEC.GetMec(targets.Select((target) => target.UnitPosition.ToVector2()).ToList());

                        // add hullradius?
                        if (mecResult.Radius != 0f && mecResult.Radius < input.Radius && this.IsInRange(input, mecResult.Center.ToVector3()))
                        {
                            output.CastPosition = new Vector3(
                                targets.Count <= 2 ? (targets[0].UnitPosition.ToVector2() + targets[1].UnitPosition.ToVector2()) / 2 : mecResult.Center,
                                output.CastPosition.Z);
                            output.AoeTargetsHit = targets.Where((target) => output.CastPosition.IsInRange(target.UnitPosition, input.Radius)).ToList();
                            break;
                        }

                        var itemToRemove = targets.MaxOrDefault((target) => targets[0].UnitPosition.DistanceSquared(target.UnitPosition));
                        targets.Remove(itemToRemove);
                    }
                }
                else
                {
                    // TODO: handle the AreaOfEffectHitMainTarget=false case
                }

                break;

            case PredictionSkillshotType.SkillshotCone:
                break;

            case PredictionSkillshotType.SkillshotLine:
                break;
            }
        }
예제 #2
0
        public PredictionOutput GetPrediction(PredictionInput input)
        {
            var result = this.GetSimplePrediction(input);

            // Handle AreaOfEffect
            if (input.AreaOfEffect)
            {
                result = this.GetAreaOfEffectPrediction(input, result);
            }

            // check range
            if (input.Range != float.MaxValue)
            {
                if (!this.IsInRange(input, result.CastPosition, false))
                {
                    result.HitChance = HitChance.OutOfRange;
                }
                else if (!this.IsInRange(input, result.UnitPosition, true))
                {
                    result.HitChance = HitChance.OutOfRange;
                }
            }

            // check collision
            if (input.CollisionTypes != CollisionTypes.None)
            {
                var scanRange        = input.Owner.Distance2D(result.CastPosition);
                var movingObjects    = new List <Unit>();
                var collisionObjects = new List <CollisionObject>();

                if (input.CollisionTypes.HasFlag(CollisionTypes.AllyCreeps))
                {
                    movingObjects.AddRange(
                        EntityManager <Creep> .Entities.Where(
                            unit => unit.IsAlly(input.Owner) && unit.IsValidTarget(float.MaxValue, false) && input.Owner.IsInRange(unit, scanRange)));
                }

                if (input.CollisionTypes.HasFlag(CollisionTypes.EnemyCreeps))
                {
                    movingObjects.AddRange(
                        EntityManager <Creep> .Entities.Where(
                            unit => unit.IsEnemy(input.Owner) && unit.IsValidTarget(float.MaxValue, false) && input.Owner.IsInRange(unit, scanRange)));
                }

                if (input.CollisionTypes.HasFlag(CollisionTypes.AllyHeroes))
                {
                    movingObjects.AddRange(
                        EntityManager <Hero> .Entities.Where(
                            unit => unit.IsAlly(input.Owner) &&
                            unit.IsValidTarget(float.MaxValue, false) &&
                            input.Owner.IsInRange(unit, scanRange) &&
                            unit != input.Owner));
                }

                if (input.CollisionTypes.HasFlag(CollisionTypes.EnemyHeroes))
                {
                    movingObjects.AddRange(
                        EntityManager <Hero> .Entities.Where(
                            unit => unit.IsEnemy(input.Owner) &&
                            unit.IsValidTarget(float.MaxValue, false) &&
                            input.Owner.IsInRange(unit, scanRange) &&
                            unit != input.Target));
                }

                // add units
                foreach (var unit in movingObjects)
                {
                    var predictedPos = this.GetSimplePrediction(input.WithTarget(unit));
                    collisionObjects.Add(new CollisionObject(unit, predictedPos.UnitPosition, unit.HullRadius + 10f));
                    collisionObjects.Add(new CollisionObject(unit, unit.NetworkPosition, unit.HullRadius)); // optional
                }

                // add trees and buildings, use NavMeshCellFlags for less lag?
                if (input.CollisionTypes.HasFlag(CollisionTypes.Trees))
                {
                    foreach (var tree in EntityManager <Tree> .Entities.Where(unit => input.Owner.IsInRange(unit, scanRange)))
                    {
                        collisionObjects.Add(new CollisionObject(tree, tree.NetworkPosition, 75f));
                    }
                }

                var collisionResult = Collision.Collision.GetCollision(input.Owner.NetworkPosition.ToVector2(), result.CastPosition.ToVector2(), input.Radius, collisionObjects);
                if (collisionResult.Collides)
                {
                    result.HitChance = HitChance.Collision;
                }

                result.CollisionResult = collisionResult;
            }

            return(result);
        }