using UnityEngine; using UnityEngine.Rendering; // Potrzebne dla Volume using Beyond; // Dla dostępu do Twojej klasy Player using Invector; // Dla vDamage public class PoisonZone : MonoBehaviour { [Header("Damage Settings")] [Tooltip("Amount of damage dealt at each interval.")] public int damageAmount = 5; [Tooltip("Time in seconds between each damage tick.")] public float damageInterval = 1.0f; [Header("Volume Animation Settings")] [Tooltip("Reference to the Volume component to animate.")] public Volume poisonVolume; [Tooltip("Animation curve for ONE CYCLE of the looping Volume weight. X-axis (Time) from 0 to 1. Y-axis (Value) is the weight intensity (e.g., 0 to 1, where 1 is full effect defined by the curve values).")] public AnimationCurve loopingVolumeWeightCurve = new AnimationCurve( new Keyframe(0, 0), new Keyframe(0.5f, 0.8f), // Example: peaks at 0.8 halfway through new Keyframe(1, 0) // Example: returns to 0 at the end of the cycle ); [Tooltip("Duration of one full cycle of the looping animation, in seconds. Must be greater than 0.")] public float loopCycleDuration = 2.0f; [Tooltip("Duration of the fade-in/fade-out effect for the looping animation, in seconds. Set to 0 for instant on/off of the loop.")] public float volumeFadeDuration = 1.0f; [Header("Sound Settings")] [Tooltip("Coughing sound effect to play.")] public AudioClip coughSound; [Tooltip("Interval in seconds for repeating the cough sound while player is in the zone. Set to 0 for no repeat (only on enter).")] public float coughInterval = 4.0f; private Player currentPlayerInZone; private float timeSinceLastDamage = 0f; private float timeSinceLastCough = 0f; private bool playerCurrentlyInZone = false; private float currentLoopProgress = 0f; // Postęp w bieżącym cyklu pętli (0 to 1) private float currentFadeProgress = 0f; // Postęp fade-in/fade-out (0 to 1), kontroluje ogólną intensywność pętli void Start() { Collider col = GetComponent(); if (col == null || !col.isTrigger) { Debug.LogWarning($"PoisonZone: Collider not found or not set to 'Is Trigger' on GameObject: {gameObject.name}", this); } if (poisonVolume == null) { Debug.LogWarning($"PoisonZone: No Volume assigned in Inspector. Post-processing effects will not be animated for {gameObject.name}", this); } else { // Ustaw początkową wagę na 0 (ponieważ currentFadeProgress jest 0) poisonVolume.weight = 0f; poisonVolume.enabled = false; } if (loopCycleDuration <= 0.001f) // Sprawdzenie, czy jest sensownie dodatni { Debug.LogWarning("PoisonZone: Loop Cycle Duration should be greater than 0 for looping animation. Setting to 1s.", this); loopCycleDuration = 1f; // Domyślna wartość, aby uniknąć dzielenia przez zero lub zbyt szybkich pętli } } void Update() { // --- Volume Animation Logic --- if (poisonVolume != null) { // 1. Update Fade Progress (kontroluje ogólną widoczność/intensywność pętli) float targetFadeProgress = playerCurrentlyInZone ? 1.0f : 0.0f; if (volumeFadeDuration > 0.001f) { float fadeStep = (1.0f / volumeFadeDuration) * Time.deltaTime; currentFadeProgress = Mathf.MoveTowards(currentFadeProgress, targetFadeProgress, fadeStep); } else // Natychmiastowe włączenie/wyłączenie pętli (jeśli fade duration jest bliski 0) { currentFadeProgress = targetFadeProgress; } // 2. Update Loop Progress (tylko jeśli efekt jest przynajmniej częściowo "widoczny" lub gracz jest w strefie) // To zapewnia, że pętla rusza, gdy tylko zaczyna się fade-in. if (playerCurrentlyInZone || currentFadeProgress > 0.001f) { currentLoopProgress += Time.deltaTime / loopCycleDuration; // Zapętlanie postępu: if (currentLoopProgress >= 1.0f) currentLoopProgress -= 1.0f; // Lub użycie modulo dla płynniejszego przejścia, gdy Time.deltaTime jest duże: currentLoopProgress = currentLoopProgress % 1.0f; } // 3. Calculate and Apply Volume Weight // Wartość z krzywej pętli jest mnożona przez postęp fade'owania. float loopedWeightValue = loopingVolumeWeightCurve.Evaluate(currentLoopProgress); poisonVolume.weight = loopedWeightValue * currentFadeProgress; // 4. Manage Volume Enabled State // Włączamy Volume, jeśli jego waga jest wystarczająco duża, aby był widoczny. bool shouldBeEnabled = poisonVolume.weight > 0.001f; if (poisonVolume.enabled != shouldBeEnabled) { poisonVolume.enabled = shouldBeEnabled; } } // --- Damage and Sound Logic --- if (playerCurrentlyInZone && currentPlayerInZone != null) { // Zadawanie obrażeń timeSinceLastDamage += Time.deltaTime; if (timeSinceLastDamage >= damageInterval) { ApplyPoisonDamage(); timeSinceLastDamage = 0f; } // Odtwarzanie dźwięku kaszlu if (coughSound != null && coughInterval > 0) { timeSinceLastCough += Time.deltaTime; if (timeSinceLastCough >= coughInterval) { PlayCoughSound(); timeSinceLastCough = 0f; } } } } void OnTriggerEnter(Collider other) { Player enteredPlayer = other.GetComponent(); if (enteredPlayer != null) { if (currentPlayerInZone == null || currentPlayerInZone != enteredPlayer) { currentPlayerInZone = enteredPlayer; playerCurrentlyInZone = true; timeSinceLastDamage = 0f; timeSinceLastCough = 0f; // Reset timera kaszlu // Opcjonalnie: zresetuj postęp pętli, aby zaczynała się od początku. // currentLoopProgress = 0f; // Jeśli chcesz, aby zaczynała się płynnie od początku przy każdym wejściu. if (coughSound != null) { PlayCoughSound(); // Kaszel od razu przy wejściu } //Debug.Log(enteredPlayer.name + " entered poison zone: " + gameObject.name); } } } void OnTriggerExit(Collider other) { Player exitedPlayer = other.GetComponent(); if (exitedPlayer != null && exitedPlayer == currentPlayerInZone) { playerCurrentlyInZone = false; // Nie zerujemy currentPlayerInZone tutaj, currentFadeProgress zajmie się wygaszeniem efektu. //Debug.Log(exitedPlayer.name + " exited poison zone: " + gameObject.name); } } private void ApplyPoisonDamage() { if (currentPlayerInZone != null && currentPlayerInZone.ThirdPersonController != null) { var healthController = currentPlayerInZone.ThirdPersonController; if (healthController != null && !healthController.isDead) { vDamage damageInstance = new vDamage(damageAmount, true); healthController.TakeDamage(damageInstance); } } } private void PlayCoughSound() { if (currentPlayerInZone != null && coughSound != null) { currentPlayerInZone.PlaySingleSound(coughSound, true); } } }