using Invector; using Lean.Pool; using UnityEngine; namespace DemonBoss.Magic { /// /// Turret component that allows player to destroy crystal turrets /// Implements Invector interfaces for damage system integration /// Attach to turret prefab along with appropriate collider (non-trigger) /// public class DestroyableTurret : MonoBehaviour, vIDamageReceiver, vIHealthController { [Header("Health Configuration")] [Tooltip("Maximum health points of the turret")] public int maxHealth = 50; [Tooltip("Current health points (read-only)")] [SerializeField] private int currentHealth; [Header("Destruction Effects")] [Tooltip("Visual effect played when turret is destroyed")] public GameObject destructionEffect; [Tooltip("Sound played when turret is destroyed")] public AudioClip destructionSound; [Tooltip("Sound played when turret receives damage")] public AudioClip hitSound; [Header("Visual Feedback")] [Tooltip("Material applied when turret is damaged")] public Material damagedMaterial; [Tooltip("HP threshold below which damaged material is applied (percentage)")] [Range(0f, 1f)] public float damagedThreshold = 0.5f; [Header("Debug")] [Tooltip("Enable debug logging")] public bool enableDebug = false; // Private fields private AudioSource audioSource; private CrystalShooterAI shooterAI; private Renderer turretRenderer; private Material originalMaterial; private bool isDestroyed = false; // Invector system events public UnityEngine.Events.UnityEvent OnReceiveDamage { get; set; } public UnityEngine.Events.UnityEvent OnDead { get; set; } // vIHealthController implementation public int currentHealthRecovery { get; set; } public int maxHealthRecovery { get; set; } public bool isDead => currentHealth <= 0; public OnReceiveDamage onStartReceiveDamage => throw new System.NotImplementedException(); public OnReceiveDamage onReceiveDamage => throw new System.NotImplementedException(); public OnDead onDead => throw new System.NotImplementedException(); float vIHealthController.currentHealth => throw new System.NotImplementedException(); public int MaxHealth => throw new System.NotImplementedException(); bool vIHealthController.isDead { get => isDead; set => throw new System.NotImplementedException(); } /// /// Initialize components and validate setup /// private void Awake() { InitializeComponents(); InitializeHealth(); } /// /// Find and configure required components /// private void InitializeComponents() { // Find components shooterAI = GetComponent(); turretRenderer = GetComponent(); // Store original material if (turretRenderer != null) { originalMaterial = turretRenderer.material; } // Setup AudioSource audioSource = GetComponent(); if (audioSource == null && (destructionSound != null || hitSound != null)) { audioSource = gameObject.AddComponent(); audioSource.playOnAwake = false; audioSource.spatialBlend = 1f; // 3D sound } // Validate collider setup Collider col = GetComponent(); if (col != null && col.isTrigger && enableDebug) { Debug.LogWarning("[DestroyableTurret] Collider should not be trigger for damage system!"); } } /// /// Setup initial health values /// private void InitializeHealth() { currentHealth = maxHealth; maxHealthRecovery = maxHealth; currentHealthRecovery = 0; if (enableDebug) Debug.Log($"[DestroyableTurret] Initialized with {currentHealth}/{maxHealth} HP"); } #region vIDamageReceiver Implementation /// /// Handle incoming damage from Invector damage system /// public void TakeDamage(vDamage damage) { if (isDestroyed) return; int damageValue = Mathf.RoundToInt(damage.damageValue); TakeDamage(damageValue); if (enableDebug) Debug.Log($"[DestroyableTurret] Received {damageValue} damage from {damage.sender?.name}"); } /// /// Handle incoming damage with hit reaction parameter /// public void TakeDamage(vDamage damage, bool hitReaction) { TakeDamage(damage); } #endregion vIDamageReceiver Implementation #region vIHealthController Implementation /// /// Apply damage to the turret and handle destruction /// public void TakeDamage(int damage) { if (isDestroyed || currentHealth <= 0) return; currentHealth = Mathf.Max(0, currentHealth - damage); if (enableDebug) Debug.Log($"[DestroyableTurret] HP: {currentHealth}/{maxHealth} (-{damage})"); // Play hit effects PlayHitEffects(); UpdateVisualState(); // Trigger damage event OnReceiveDamage?.Invoke(); // Check if destroyed if (currentHealth <= 0) { DestroyTurret(); } } /// /// Change health by specified amount (positive for healing, negative for damage) /// public void ChangeHealth(int value) { if (isDestroyed) return; if (value < 0) { TakeDamage(-value); } else { currentHealth = Mathf.Min(maxHealth, currentHealth + value); if (enableDebug) Debug.Log($"[DestroyableTurret] Healed by {value}, HP: {currentHealth}/{maxHealth}"); } } /// /// Modify maximum health value /// public void ChangeMaxHealth(int value) { maxHealth = Mathf.Max(1, maxHealth + value); currentHealth = Mathf.Min(currentHealth, maxHealth); } #endregion vIHealthController Implementation /// /// Play sound and visual effects when receiving damage /// private void PlayHitEffects() { // Play hit sound if (audioSource != null && hitSound != null) { audioSource.PlayOneShot(hitSound); } } /// /// Update visual appearance based on current health /// private void UpdateVisualState() { // Change material if turret is heavily damaged if (turretRenderer != null && damagedMaterial != null) { float healthPercent = (float)currentHealth / maxHealth; if (healthPercent <= damagedThreshold && turretRenderer.material != damagedMaterial) { turretRenderer.material = damagedMaterial; if (enableDebug) Debug.Log("[DestroyableTurret] Changed to damaged material"); } } } /// /// Handle turret destruction sequence /// private void DestroyTurret() { if (isDestroyed) return; isDestroyed = true; if (enableDebug) Debug.Log("[DestroyableTurret] Turret has been destroyed!"); // Stop shooting if (shooterAI != null) { shooterAI.StopShooting(); } // Trigger death event OnDead?.Invoke(); // Play destruction effects PlayDestructionEffects(); // Destroy after brief delay (let effects play) StartCoroutine(DestroyAfterDelay(0.1f)); } /// /// Play visual and audio effects for turret destruction /// private void PlayDestructionEffects() { // Spawn visual effect if (destructionEffect != null) { GameObject effect = Instantiate(destructionEffect, transform.position, transform.rotation); Destroy(effect, 5f); } // Play destruction sound if (audioSource != null && destructionSound != null) { audioSource.PlayOneShot(destructionSound); // Keep AudioSource alive to finish playing audioSource.transform.parent = null; Destroy(audioSource.gameObject, destructionSound.length + 1f); } } /// /// Coroutine to destroy turret after specified delay /// private System.Collections.IEnumerator DestroyAfterDelay(float delay) { yield return new UnityEngine.WaitForSeconds(delay); // Remove through Lean Pool (if used) or regular Destroy if (gameObject.scene.isLoaded) // Check if object still exists { LeanPool.Despawn(gameObject); } } /// /// Force immediate turret destruction (e.g., when boss dies) /// public void ForceDestroy() { if (enableDebug) Debug.Log("[DestroyableTurret] Forced destruction"); currentHealth = 0; //isDead = true; DestroyTurret(); } /// /// Returns current health as percentage of maximum health /// public float GetHealthPercentage() { return maxHealth > 0 ? (float)currentHealth / maxHealth : 0f; } #if UNITY_EDITOR /// /// Draw turret status visualization in Scene View /// private void OnDrawGizmosSelected() { // Show turret status if (Application.isPlaying) { Gizmos.color = currentHealth > maxHealth * 0.5f ? Color.green : currentHealth > maxHealth * 0.25f ? Color.yellow : Color.red; } else { Gizmos.color = Color.green; } Gizmos.DrawWireCube(transform.position + Vector3.up * 2f, Vector3.one * 0.5f); // HP text in Scene View if (Application.isPlaying) { UnityEditor.Handles.Label(transform.position + Vector3.up * 2.5f, $"HP: {currentHealth}/{maxHealth}"); } } #endif public void AddHealth(int value) { throw new System.NotImplementedException(); } public void ResetHealth(float health) { throw new System.NotImplementedException(); } public void ResetHealth() { throw new System.NotImplementedException(); } } }