Example #1
0
    public override void DoBehavior(CharacterAttackController controller)
    {
        List <Collider2D> possibleTargets = new List <Collider2D>();

        Vector2 selfPosition = controller.transform.position;

        Team selfTeam = controller.GetComponent <TeamAssigner>().team;

        foreach (Collider2D collider in Physics2D.OverlapCircleAll(selfPosition, attackRadius))
        {
            TeamAssigner assigner = collider.GetComponent <TeamAssigner>();
            if (assigner != null && selfTeam != assigner.team)
            {
                possibleTargets.Add(collider);
            }
        }

        float      closestDistance = Mathf.Infinity;
        Collider2D closestTarget   = null;

        foreach (Collider2D possibleTarget in possibleTargets)
        {
            // Check if we have line of sight
            Vector2 targetPosition = possibleTarget.transform.position;
            Vector2 direction      = targetPosition - selfPosition;
            float   distance       = direction.magnitude;

            bool lineOfSight = true;
            foreach (RaycastHit2D hit in Physics2D.RaycastAll(controller.transform.position, direction, distance))
            {
                if (hit.collider.gameObject.GetComponent <VisionOccluder>() != null)
                {
                    lineOfSight = false;
                }
            }

            if (lineOfSight && distance <= closestDistance)
            {
                closestTarget   = possibleTarget;
                closestDistance = distance;
            }
        }

        if (closestTarget != null)
        {
            controller.Attack(closestTarget.transform.position);
        }
    }
Example #2
0
    public override void Use(CharacterAttackController attackController, Vector2 target)
    {
        Team firingTeam = attackController.GetComponent <TeamAssigner>().team;

        Vector2 firePoint = attackController.attackBasePoint.transform.position;
        Vector2 delta     = target - firePoint;

        Vector2 fireDirection = delta.normalized;

        bool isRight = delta.x > 0;

        if (autoTarget)
        {
            float sqrtTerm = Mathf.Pow(launchSpeed, 4) - gravity * (gravity * Mathf.Pow(delta.x, 2) + 2 * delta.y * Mathf.Pow(launchSpeed, 2));
            if (sqrtTerm >= 0)
            {
                float sol1 = Mathf.Atan((Mathf.Pow(launchSpeed, 2) + Mathf.Sqrt(sqrtTerm)) / (Mathf.Abs(delta.x * gravity)));
                float sol2 = Mathf.Atan((Mathf.Pow(launchSpeed, 2) - Mathf.Sqrt(sqrtTerm)) / (Mathf.Abs(delta.x * gravity)));

                Vector2 fireDirection1 = new Vector2(Mathf.Cos(sol1) * (isRight ? 1.0f : -1.0f), Mathf.Sin(sol1));
                Vector2 fireDirection2 = new Vector2(Mathf.Cos(sol2) * (isRight ? 1.0f : -1.0f), Mathf.Sin(sol2));

                bool canHit1 = true;
                bool canHit2 = true;

                // Check if we can hit the target without a collision:
                if (Vector2.Angle(attackController.transform.up, fireDirection1) * Mathf.Deg2Rad > upAngleBounds)
                {
                    canHit1 = false;
                }
                else
                {
                    foreach (RaycastHit2D hit in PhysicsUtility.GravityRaycast(firePoint, fireDirection1 * launchSpeed, target, gravity, autoTargetDeltaTime, hitRadius))
                    {
                        if (hit.collider.GetComponent <AutoProjectileBlocker>() != null)
                        {
                            canHit1 = false;
                            break;
                        }
                    }
                }

                if (Vector2.Angle(attackController.transform.up, fireDirection2) * Mathf.Deg2Rad > upAngleBounds)
                {
                    canHit2 = false;
                }
                else
                {
                    foreach (RaycastHit2D hit in PhysicsUtility.GravityRaycast(firePoint, fireDirection2 * launchSpeed, target, gravity, autoTargetDeltaTime, hitRadius))
                    {
                        if (hit.collider.GetComponent <AutoProjectileBlocker>() != null)
                        {
                            canHit2 = false;
                            break;
                        }
                    }
                }

                float?bestAngle = null;

                if (canHit1 && canHit2)
                {
                    float time1 = (launchSpeed * Mathf.Sin(sol1) + Mathf.Sqrt(Mathf.Pow(launchSpeed * Mathf.Sin(sol1), 2) + Mathf.Abs(2 * gravity * delta.y))) / gravity;
                    float time2 = (launchSpeed * Mathf.Sin(sol2) + Mathf.Sqrt(Mathf.Pow(launchSpeed * Mathf.Sin(sol2), 2) + Mathf.Abs(2 * gravity * delta.y))) / gravity;

                    bestAngle = (time1 > time2) ? sol2 : sol1;
                }
                else
                {
                    if (canHit1)
                    {
                        bestAngle = sol1;
                    }
                    else if (canHit2)
                    {
                        bestAngle = sol2;
                    }
                }

                if (bestAngle.HasValue)
                {
                    fireDirection = new Vector2(Mathf.Cos(bestAngle.Value) * (isRight ? 1.0f : -1.0f), Mathf.Sin(bestAngle.Value));
                }
            }
        }

        if (Vector2.Angle(attackController.transform.up, fireDirection) * Mathf.Deg2Rad <= upAngleBounds)
        {
            ProjectileController newProjectile = Instantiate(projectileToFirePrefab.gameObject).GetComponent <ProjectileController>();
            newProjectile.Fire(firePoint, fireDirection, firingTeam, this);
        }
    }