122 lines
3.7 KiB
C#
122 lines
3.7 KiB
C#
using UnityEngine;
|
|
using GeometryTD.Definition;
|
|
using GeometryTD.Entity.EntityData;
|
|
|
|
namespace Components
|
|
{
|
|
[DisallowMultipleComponent]
|
|
public class ShooterBullet : MonoBehaviour
|
|
{
|
|
[SerializeField] [Min(0.1f)] private float _defaultSpeed = 12f;
|
|
[SerializeField] [Min(0.02f)] private float _hitDistance = 0.15f;
|
|
[SerializeField] [Min(0.1f)] private float _maxLifetime = 3f;
|
|
|
|
private Transform _target;
|
|
private float _speed;
|
|
private int _damage;
|
|
private AttackPropertyType _attackPropertyType;
|
|
private float _lifetime;
|
|
private float _runtimeMaxLifetime;
|
|
private bool _isRunning;
|
|
private bool _despawnRequested;
|
|
|
|
public void OnShow(BulletData bulletData)
|
|
{
|
|
_target = bulletData != null ? bulletData.Target : null;
|
|
_damage = bulletData != null ? Mathf.Max(0, bulletData.Damage) : 0;
|
|
_attackPropertyType = bulletData != null ? bulletData.AttackPropertyType : AttackPropertyType.None;
|
|
_speed = bulletData != null && bulletData.Speed > 0f ? bulletData.Speed : _defaultSpeed;
|
|
_runtimeMaxLifetime = bulletData != null && bulletData.MaxLifetime > 0f ? bulletData.MaxLifetime : _maxLifetime;
|
|
_lifetime = 0f;
|
|
_despawnRequested = false;
|
|
_isRunning = _target != null;
|
|
if (!_isRunning)
|
|
{
|
|
_despawnRequested = true;
|
|
}
|
|
}
|
|
|
|
public void OnReset()
|
|
{
|
|
_target = null;
|
|
_speed = 0f;
|
|
_damage = 0;
|
|
_attackPropertyType = AttackPropertyType.None;
|
|
_lifetime = 0f;
|
|
_runtimeMaxLifetime = _maxLifetime;
|
|
_isRunning = false;
|
|
_despawnRequested = false;
|
|
}
|
|
|
|
public void Tick(float deltaTime)
|
|
{
|
|
if (!_isRunning)
|
|
{
|
|
return;
|
|
}
|
|
|
|
_lifetime += Mathf.Max(0f, deltaTime);
|
|
if (_lifetime >= _runtimeMaxLifetime || _target == null)
|
|
{
|
|
_isRunning = false;
|
|
_despawnRequested = true;
|
|
return;
|
|
}
|
|
|
|
Vector3 toTarget = _target.position - transform.position;
|
|
float hitDistanceSquared = _hitDistance * _hitDistance;
|
|
if (toTarget.sqrMagnitude <= hitDistanceSquared)
|
|
{
|
|
HitTarget();
|
|
return;
|
|
}
|
|
|
|
Vector3 forward = toTarget.normalized;
|
|
float moveDistance = _speed * Mathf.Max(0f, deltaTime);
|
|
if (moveDistance * moveDistance >= toTarget.sqrMagnitude)
|
|
{
|
|
transform.position = _target.position;
|
|
HitTarget();
|
|
return;
|
|
}
|
|
|
|
transform.position += forward * moveDistance;
|
|
transform.forward = forward;
|
|
}
|
|
|
|
public bool TryConsumeDespawnRequest()
|
|
{
|
|
if (!_despawnRequested)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
_despawnRequested = false;
|
|
return true;
|
|
}
|
|
|
|
private void HitTarget()
|
|
{
|
|
if (_target == null)
|
|
{
|
|
_isRunning = false;
|
|
_despawnRequested = true;
|
|
return;
|
|
}
|
|
|
|
MonoBehaviour[] components = _target.GetComponentsInParent<MonoBehaviour>();
|
|
for (int i = 0; i < components.Length; i++)
|
|
{
|
|
if (components[i] is IDamageReceiver damageReceiver)
|
|
{
|
|
damageReceiver.TakeDamage(_damage, _attackPropertyType);
|
|
break;
|
|
}
|
|
}
|
|
|
|
_isRunning = false;
|
|
_despawnRequested = true;
|
|
}
|
|
}
|
|
}
|