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

105 lines
3.9 KiB
C#
Raw Normal View History

2024-04-20 13:15:33 +02:00
using System;
using System.Collections;
2024-04-20 15:56:26 +02:00
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Assertions;
public class ProjectileTower : Tower
{
2024-04-20 19:33:01 +02:00
[SerializeField] protected EditableArc horizontalArc;
[SerializeField] protected EditableArc verticalArc;
2024-04-20 13:15:33 +02:00
[SerializeField, Range(0.01f, 20f)] private float attackSecondsDelay = 1f;
[SerializeField] private ProjectilePattern[] projectileSequence;
2024-04-20 16:28:46 +02:00
[SerializeField] private Barrel barrel;
2024-04-20 15:56:26 +02:00
[SerializeField] private LineRenderer trajectory;
[SerializeField] private int trajectoryBounces = 2;
private const float k_trajectory_maxdist = 100f;
private ProjectileSpawner projectileSpawner;
2024-04-20 19:22:52 +02:00
public Vector3 AimDirection => barrel.transform.forward;
2024-04-20 19:33:01 +02:00
public Vector2 HorizontalRotationMinMax => horizontalArc.RotationMinMax;
public Vector2 VerticalRotationMinMax => verticalArc.RotationMinMax;
public float HorizontalRotation => horizontalArc.Value;
public float VerticalRotation => verticalArc.Value;
2024-04-20 13:15:33 +02:00
protected override void Awake()
{
base.Awake();
projectileSpawner = GetComponent<ProjectileSpawner>();
Assert.IsNotNull(projectileSpawner);
2024-04-20 13:15:33 +02:00
horizontalArc.Value.AddListener(UpdateBarrelRotation);
verticalArc.Value.AddListener(UpdateBarrelRotation);
2024-04-20 15:56:26 +02:00
horizontalArc.Value.AddListener(UpdateTrajectory);
verticalArc.Value.AddListener(UpdateTrajectory);
2024-04-20 19:33:01 +02:00
horizontalArc.Value.AddListener(SnapVerticalToHorizontal);
2024-04-20 13:15:33 +02:00
UpdateBarrelRotation();
2024-04-20 15:56:26 +02:00
UpdateTrajectory();
2024-04-20 13:15:33 +02:00
StartCoroutine(AttackLoop());
}
2024-04-20 19:33:01 +02:00
private void SnapVerticalToHorizontal(float horizontalAngle)
{
verticalArc.transform.rotation = Quaternion.Euler(verticalArc.transform.rotation.eulerAngles.x, horizontalAngle, verticalArc.transform.rotation.eulerAngles.z);
}
2024-04-20 15:56:26 +02:00
private void UpdateTrajectory(float unused) => UpdateTrajectory();
private void UpdateTrajectory()
{
if (trajectory == null) return;
2024-04-20 16:28:46 +02:00
Vector3 origin = barrel.Tip.position;
Vector3 dir = barrel.transform.forward;
2024-04-20 15:56:26 +02:00
List<Vector3> pointsInTrajectory = new();
2024-04-20 16:28:46 +02:00
pointsInTrajectory.Add(origin);
2024-04-20 15:56:26 +02:00
for (int i = 0; i < trajectoryBounces; i++)
{
2024-04-20 16:28:46 +02:00
Debug.DrawRay(origin, dir.normalized * k_trajectory_maxdist, Color.red, 5f);
2024-04-20 15:56:26 +02:00
RaycastHit hit;
if (!Physics.Raycast(origin, dir, out hit, k_trajectory_maxdist))
break;
pointsInTrajectory.Add(hit.point);
dir = Vector3.Reflect(dir, hit.normal);
origin = hit.point;
}
trajectory.positionCount = pointsInTrajectory.Count;
trajectory.SetPositions(pointsInTrajectory.ToArray());
}
2024-04-20 13:15:33 +02:00
protected override void OnDestroy()
{
horizontalArc.Value.RemoveListener(UpdateBarrelRotation);
verticalArc.Value.RemoveListener(UpdateBarrelRotation);
2024-04-20 19:33:01 +02:00
horizontalArc.Value.RemoveListener(SnapVerticalToHorizontal);
2024-04-20 13:15:33 +02:00
}
private IEnumerator AttackLoop()
{
do {
yield return new WaitForSeconds(attackSecondsDelay);
UpdateBarrelRotation();
Debug.DrawRay(transform.position, horizontalArc.ToKnobVector, Color.red, attackSecondsDelay);
Debug.DrawRay(transform.position, verticalArc.ToKnobVector, Color.green, attackSecondsDelay);
Debug.DrawRay(transform.position, AimDirection, Color.yellow, attackSecondsDelay);
2024-04-20 19:22:52 +02:00
projectileSpawner.RunBulletSequence(barrel.transform.position, transform.up, AimDirection, projectileSequence);
2024-04-20 13:15:33 +02:00
} while (true);
}
private void UpdateBarrelRotation(float unused) => UpdateBarrelRotation();
// Rotate barrel to match rotation
private void UpdateBarrelRotation()
{
2024-04-20 18:12:49 +02:00
barrel.transform.localRotation = Quaternion.Euler(-verticalArc.Value, horizontalArc.Value, 0f);
}
}