210 lines
4.7 KiB
C#
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
|
|
);
|
|
}
|
|
}
|