3DTD/Assets/Scripts/Tower/BeamTower.cs

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