Files

210 lines
4.7 KiB
C#

using UnityEngine;
using DepthsOfGreed.HandbookUI;
public class Turret : MonoBehaviour
{
[Header("Tower Data")]
[SerializeField]
private HandbookTowerEntry towerData;
[Header("Turret Setup")]
[SerializeField]
private Transform turret;
[SerializeField]
private Transform tip;
[SerializeField]
private float rotationSpeed = 360f;
[Header("Projectile Setup")]
[SerializeField]
private GameObject bulletPrefab;
[SerializeField]
private float bulletSpeed = 8f;
private CombatDefinition combatStats;
private float nextAttackTime;
private Enemy currentTarget;
private void Start()
{
if (towerData == null)
{
Debug.LogError(
"TowerShooting: Kein HandbookTowerEntry zugewiesen!",
this
);
enabled = false;
return;
}
if (turret == null || tip == null || bulletPrefab == null)
{
Debug.LogError(
"TowerShooting: Turret, Tip oder Bullet Prefab fehlt!",
this
);
enabled = false;
return;
}
combatStats = towerData.CreateCombatSnapshot(0);
}
private void Update()
{
if (combatStats == null)
return;
// Ziel innerhalb der Reichweite suchen.
currentTarget = FindTarget();
if (currentTarget != null)
{
RotateTowardsTarget();
TryShoot();
}
else
{
// Zur ursprünglichen Ausrichtung zurückkehren.
RotateTowardsOrigin();
}
}
private Enemy FindTarget()
{
Enemy[] enemies =
FindObjectsByType<Enemy>(
FindObjectsSortMode.None
);
Enemy closestEnemy = null;
float closestDistance = float.MaxValue;
float rangeSquared =
combatStats.range * combatStats.range;
foreach (Enemy enemy in enemies)
{
if (enemy == null || enemy.IsDead)
continue;
Vector2 difference =
enemy.transform.position - transform.position;
float distanceSquared = difference.sqrMagnitude;
if (distanceSquared > rangeSquared)
continue;
if (distanceSquared < closestDistance)
{
closestDistance = distanceSquared;
closestEnemy = enemy;
}
}
return closestEnemy;
}
private void RotateTowardsTarget()
{
Vector3 worldDirection =
currentTarget.transform.position - turret.position;
// Richtung in den lokalen Raum der Turmbasis umwandeln.
Vector3 localDirection =
turret.parent != null
? turret.parent.InverseTransformDirection(worldDirection)
: worldDirection;
float targetAngle =
Mathf.Atan2(localDirection.y, localDirection.x)
* Mathf.Rad2Deg - 90f;
Quaternion targetRotation =
Quaternion.Euler(0f, 0f, targetAngle);
turret.localRotation = Quaternion.RotateTowards(
turret.localRotation,
targetRotation,
rotationSpeed * Time.deltaTime
);
}
private void RotateTowardsOrigin()
{
turret.localRotation = Quaternion.RotateTowards(
turret.localRotation,
Quaternion.identity,
rotationSpeed * Time.deltaTime
);
}
private void TryShoot()
{
if (combatStats.attacksPerSecond <= 0f)
return;
if (Time.time < nextAttackTime)
return;
Shoot();
float attackInterval =
1f / combatStats.attacksPerSecond;
nextAttackTime = Time.time + attackInterval;
}
private void Shoot()
{
GameObject bulletObject = Instantiate(
bulletPrefab,
tip.position,
tip.rotation
);
Bullet bullet =
bulletObject.GetComponent<Bullet>();
if (bullet == null)
{
Debug.LogError(
"TowerShooting: Bullet Prefab besitzt kein TowerBullet-Skript!",
bulletObject
);
Destroy(bulletObject);
return;
}
bullet.Initialize(
tip.up,
bulletSpeed,
combatStats.damagePerHit,
combatStats.range
);
}
private void OnDrawGizmosSelected()
{
if (towerData == null)
return;
Gizmos.color = Color.red;
Gizmos.DrawWireSphere(
transform.position,
towerData.combat.range
);
}
}