107 lines
3.4 KiB
C#
107 lines
3.4 KiB
C#
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
|
|
public class BeamTower : AimTower
|
|
{
|
|
[SerializeField] private int maxBounces = 4;
|
|
[SerializeField, Range(0f, 50f)] private float damage = 5f;
|
|
[SerializeField] private LayerMask beamMask;
|
|
private const float k_maxBeamDist = 100f;
|
|
[SerializeField] private LineRenderer beam;
|
|
[SerializeField, Range(0.01f, 20f)] private float attackSecondsDelay = 1f;
|
|
[SerializeField] private float beamDuration = 1f;
|
|
|
|
protected override void Awake()
|
|
{
|
|
base.Awake();
|
|
}
|
|
|
|
public override void Placed()
|
|
{
|
|
base.Placed();
|
|
|
|
horizontalArc.Value.AddListener(UpdateBeam);
|
|
verticalArc.Value.AddListener(UpdateBeam);
|
|
|
|
UpdateBeam();
|
|
beam.enabled = false;
|
|
StartCoroutine(AttackLoop());
|
|
}
|
|
|
|
|
|
private IEnumerator AttackLoop()
|
|
{
|
|
do {
|
|
if (GameManager.Instance.CurrentNumEnemies == 0)
|
|
{
|
|
yield return new WaitForEndOfFrame();
|
|
continue;
|
|
}
|
|
int burstsInBeam = (int) (attackSecondsDelay / beamDuration);
|
|
|
|
for (int i = 0; i < burstsInBeam; i++)
|
|
{
|
|
Vector3 origin = barrel.Tip.position;
|
|
Vector3 rayDir = barrel.transform.forward;
|
|
|
|
List<Vector3> hitPoints = new();
|
|
hitPoints.Add(origin);
|
|
for (int j = 0; j < maxBounces; j++)
|
|
{
|
|
Debug.DrawRay(origin, rayDir.normalized * k_maxBeamDist, Color.red, 5f);
|
|
RaycastHit hit;
|
|
if (!Physics.Raycast(origin, rayDir, out hit, k_maxBeamDist, beamMask))
|
|
break;
|
|
|
|
// Is damagable?
|
|
HealthComponent healthComp = hit.collider.gameObject.GetComponent<HealthComponent>();
|
|
if (healthComp != null)
|
|
{
|
|
healthComp.TakeDamage(damage);
|
|
break;
|
|
}
|
|
hitPoints.Add(hit.point);
|
|
rayDir = Vector3.Reflect(rayDir, hit.normal);
|
|
origin = hit.point;
|
|
}
|
|
|
|
beam.positionCount = hitPoints.Count;
|
|
beam.SetPositions(hitPoints.ToArray());
|
|
this.OnAttack?.Invoke();
|
|
yield return new WaitForSeconds(attackSecondsDelay);
|
|
}
|
|
|
|
beam.enabled = !beam.enabled;
|
|
yield return new WaitForSeconds(beamDuration);
|
|
} while (true);
|
|
}
|
|
|
|
private void UpdateBeam(float unused) => UpdateBeam();
|
|
|
|
private void UpdateBeam()
|
|
{
|
|
|
|
Vector3 origin = barrel.Tip.position;
|
|
Vector3 rayDir = barrel.transform.forward;
|
|
|
|
List<Vector3> hitPoints = new();
|
|
hitPoints.Add(origin);
|
|
for (int i = 0; i < maxBounces; i++)
|
|
{
|
|
Debug.DrawRay(origin, rayDir.normalized * k_maxBeamDist, Color.red, 5f);
|
|
RaycastHit hit;
|
|
if (!Physics.Raycast(origin, rayDir, out hit, k_maxBeamDist, beamMask))
|
|
break;
|
|
|
|
hitPoints.Add(hit.point);
|
|
rayDir = Vector3.Reflect(rayDir, hit.normal);
|
|
origin = hit.point;
|
|
}
|
|
|
|
beam.positionCount = hitPoints.Count;
|
|
beam.SetPositions(hitPoints.ToArray());
|
|
}
|
|
}
|