using UnityEngine;
///
/// Снаряд ядовитого био-плевка Босса. Летит к игроку, при контакте наносит прямой урон,
/// создает расширяющуюся акустическую волну эхолокации и оставляет токсичную кислотную лужу.
///
public class AcidProjectile : MonoBehaviour
{
public float speed = 19f;
public float directDamage = 18f;
public float maxLifetime = 5f;
public bool isMainGlobule = true;
private Vector3 moveDirection;
private float lifeTimer = 0f;
private bool hasImpacted = false;
public static AcidProjectile Spawn(Vector3 startPos, Vector3 targetPos, float projSpeed = 19f, float damage = 18f, bool isMain = true, float spreadAngle = 0f)
{
GameObject go = new GameObject(isMain ? "Boss_Saliva_Globule" : "Boss_Saliva_Droplet");
go.transform.position = startPos;
Vector3 dir = (targetPos - startPos);
dir.y += 0.22f; // небольшая естественная баллистическая дуга плевка
if (spreadAngle > 0.01f)
{
float pitch = Random.Range(-spreadAngle, spreadAngle);
float yaw = Random.Range(-spreadAngle, spreadAngle);
dir = Quaternion.Euler(pitch, yaw, 0f) * dir;
}
Vector3 normDir = dir.normalized;
go.transform.rotation = Quaternion.LookRotation(normDir);
float baseScale = isMain ? 1f : 0.65f;
// 1. Формируем анатомическую вытянутую каплю слюны (а не плоскую кляксу)
// Основное каплевидное тело (вытянутое вдоль направления полета Z)
GameObject body = GameObject.CreatePrimitive(PrimitiveType.Sphere);
body.name = "Saliva_Body";
body.transform.SetParent(go.transform, false);
body.transform.localScale = new Vector3(0.08f, 0.08f, 0.34f) * baseScale;
body.transform.localPosition = Vector3.zero;
// Переднее утолщение капли слюны
GameObject head = GameObject.CreatePrimitive(PrimitiveType.Sphere);
head.name = "Saliva_Head";
head.transform.SetParent(go.transform, false);
head.transform.localScale = new Vector3(0.11f, 0.11f, 0.14f) * baseScale;
head.transform.localPosition = new Vector3(0f, 0f, 0.11f * baseScale);
// Хвостовая мелкая капелька слизи
GameObject tail = GameObject.CreatePrimitive(PrimitiveType.Sphere);
tail.name = "Saliva_Tail";
tail.transform.SetParent(go.transform, false);
tail.transform.localScale = new Vector3(0.05f, 0.05f, 0.08f) * baseScale;
tail.transform.localPosition = new Vector3(0f, 0f, -0.20f * baseScale);
Destroy(body.GetComponent());
Destroy(head.GetComponent());
Destroy(tail.GetComponent());
// Органический материал токсичной слюны: влажный, глянцевый, полупрозрачный
Material salivaMat = new Material(Shader.Find("Universal Render Pipeline/Lit") ?? Shader.Find("Standard"));
salivaMat.color = new Color(0.35f, 0.95f, 0.2f, 0.85f);
salivaMat.EnableKeyword("_EMISSION");
salivaMat.SetColor("_EmissionColor", new Color(0.2f, 0.85f, 0.15f) * 1.3f);
if (salivaMat.HasProperty("_Smoothness")) salivaMat.SetFloat("_Smoothness", 0.94f);
body.GetComponent().material = salivaMat;
head.GetComponent().material = salivaMat;
tail.GetComponent().material = salivaMat;
// 2. След летящей слюны (TrailRenderer) — нить тягучей слизи за летящим плевком
TrailRenderer trail = go.AddComponent();
trail.time = 0.20f;
trail.startWidth = 0.09f * baseScale;
trail.endWidth = 0.005f;
trail.minVertexDistance = 0.04f;
Material trailMat = new Material(Shader.Find("Sprites/Default") ?? Shader.Find("Universal Render Pipeline/Unlit"));
trailMat.color = new Color(0.4f, 0.95f, 0.25f, 0.7f);
trail.material = trailMat;
Gradient grad = new Gradient();
grad.SetKeys(
new GradientColorKey[] { new GradientColorKey(new Color(0.4f, 1f, 0.25f), 0f), new GradientColorKey(new Color(0.25f, 0.85f, 0.15f), 1f) },
new GradientAlphaKey[] { new GradientAlphaKey(0.75f, 0f), new GradientAlphaKey(0.0f, 1f) }
);
trail.colorGradient = grad;
// 3. Мягкая подсветка капли в полете
GameObject lightObj = new GameObject("SalivaGlow");
lightObj.transform.SetParent(go.transform, false);
Light l = lightObj.AddComponent();
l.type = LightType.Point;
l.color = new Color(0.35f, 1.0f, 0.25f);
l.intensity = isMain ? 0.9f : 0.5f;
l.range = isMain ? 2.0f : 1.2f;
// 4. Коллайдер-триггер на корневом объекте
SphereCollider col = go.AddComponent();
col.isTrigger = true;
col.radius = 0.13f * baseScale;
AcidProjectile proj = go.AddComponent();
proj.speed = projSpeed;
proj.directDamage = damage;
proj.isMainGlobule = isMain;
proj.moveDirection = normDir;
return proj;
}
private void Update()
{
if (hasImpacted) return;
lifeTimer += Time.deltaTime;
if (lifeTimer >= maxLifetime)
{
Destroy(gameObject);
return;
}
// Перемещение снаряда вперед с естественной баллистикой
moveDirection += Vector3.down * (4.0f * Time.deltaTime);
transform.position += moveDirection.normalized * (speed * Time.deltaTime);
// Поворот по вектору движения, чтобы капля летела кончиком вперед
if (moveDirection.sqrMagnitude > 0.001f)
{
transform.rotation = Quaternion.LookRotation(moveDirection);
}
// SphereCast вперед для точной регистрации удара на высокой скорости
if (Physics.SphereCast(transform.position, 0.12f, moveDirection, out RaycastHit hit, speed * Time.deltaTime, ~0, QueryTriggerInteraction.Ignore))
{
OnHit(hit.collider, hit.point);
}
}
private void OnTriggerEnter(Collider other)
{
if (hasImpacted) return;
if (other.GetComponentInParent() != null) return;
if (other.name.Contains("Saliva") || other.name.Contains("Acid")) return;
OnHit(other, transform.position);
}
private void OnHit(Collider hitCollider, Vector3 impactPoint)
{
if (hasImpacted) return;
hasImpacted = true;
// 1. Урон игроку при прямом попадании
PlayerHealth player = hitCollider.GetComponentInParent();
if (player != null)
{
player.TakeDamage(directDamage);
Debug.Log($"[Босс] Плевок слюны попал в игрока! Нанесено {directDamage} урона.");
}
// 2. Волна эхолокации в месте удара (жидкость ударяется о поверхность и разлетается брызгами)
if (EchoTrigger.Instance != null && isMainGlobule)
{
Vector3 echoPos = impactPoint;
if (Physics.Raycast(impactPoint + Vector3.up * 0.5f, Vector3.down, out RaycastHit floorHit, 4f))
{
echoPos = floorHit.point + Vector3.up * 0.05f;
}
EchoTrigger.Instance.TriggerExternalWave(echoPos, 14f, 1.8f);
}
// 3. Создание органического всплеска слюны на полу
if (isMainGlobule)
{
Vector3 poolPos = impactPoint;
if (Physics.Raycast(impactPoint + Vector3.up * 0.5f, Vector3.down, out RaycastHit fHit, 5f))
{
poolPos = fHit.point;
}
AcidPool.Create(poolPos, poolLifetime: 4.5f, poolRadius: 0.85f);
}
// 4. Звук смачного шлепка слюны о поверхность
GameAudioSynthesizer.PlayAcidImpact();
Destroy(gameObject);
}
}