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

86 lines
2.7 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;
protected override void Awake()
{
base.Awake();
horizontalArc.Value.AddListener(UpdateBeam);
verticalArc.Value.AddListener(UpdateBeam);
StartCoroutine(AttackLoop());
}
private IEnumerator AttackLoop()
{
do {
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;
// Is damagable?
HealthComponent healthComp = hit.collider.gameObject.GetComponent<HealthComponent>();
if (healthComp != null)
{
Debug.Log($"hitting {healthComp.name} {i}");
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());
yield return new WaitForSeconds(attackSecondsDelay);
} 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());
}
}