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); } }
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); } }