using System.Collections; using System.Collections.Generic; using Fusion; using UnityEngine; using Opsive.UltimateCharacterController.Traits; public class PoisonGasTrap : TrapBase { private List affectedPlayers = new List(); protected override void OnTriggered(GameObject victim) { // Start the server-side poison gas zone routine StartCoroutine(GasZoneRoutine()); } private IEnumerator GasZoneRoutine() { float elapsed = 0f; float tickInterval = 1.0f; // Deal damage every 1 second float duration = trapData.EffectDuration; float radius = trapData.EffectRadius; float damagePerTick = trapData.Damage; // Sát thương mỗi tick Debug.Log($"[Server] Poison Gas Trap activated. Duration: {duration}s, Radius: {radius}m"); while (elapsed < duration) { // Find all potential targets in radius Collider[] overlaps = Physics.OverlapSphere(transform.position, radius, LayerMask.GetMask("Player")); List currentTicks = new List(); foreach (var col in overlaps) { if (IsTargetValid(col.gameObject)) { currentTicks.Add(col.gameObject); // Apply damage var health = col.gameObject.GetComponent(); if (health != null && health.IsAlive()) { health.Damage(damagePerTick, transform.position, Vector3.zero, 0); Debug.Log($"[Server] Poison Gas applied {damagePerTick} damage to {col.gameObject.name}"); } // If player is newly entered the gas, turn on their UI overlay if (!affectedPlayers.Contains(col.gameObject)) { affectedPlayers.Add(col.gameObject); var netObj = col.gameObject.GetComponent(); if (netObj != null) { RPC_TogglePoisonOverlay(netObj.InputAuthority, netObj.Id, true); } } } } // If player left the gas area, turn off their UI overlay for (int i = affectedPlayers.Count - 1; i >= 0; --i) { var p = affectedPlayers[i]; if (p == null || !currentTicks.Contains(p)) { if (p != null) { var netObj = p.GetComponent(); if (netObj != null) { RPC_TogglePoisonOverlay(netObj.InputAuthority, netObj.Id, false); } } affectedPlayers.RemoveAt(i); } } yield return new WaitForSeconds(tickInterval); elapsed += tickInterval; } // Clean up: turn off overlay for any remaining players in zone foreach (var p in affectedPlayers) { if (p != null) { var netObj = p.GetComponent(); if (netObj != null) { RPC_TogglePoisonOverlay(netObj.InputAuthority, netObj.Id, false); } } } affectedPlayers.Clear(); // Despawn the trap DespawnTrap(); } [Rpc(RpcSources.StateAuthority, RpcTargets.InputAuthority)] private void RPC_TogglePoisonOverlay([RpcTarget] PlayerRef targetPlayer, NetworkId victimId, bool show) { // Resolve the victim GameObject using NetworkId on the client var victimNetObj = Runner.FindObject(victimId); if (victimNetObj != null) { var overlay = victimNetObj.GetComponentInChildren(); if (overlay != null) { overlay.SetOverlayActive(show); } } } // Draw the gas radius in editor for debugging private void OnDrawGizmosSelected() { if (trapData != null) { Gizmos.color = new Color(0, 1, 0, 0.3f); Gizmos.DrawSphere(transform.position, trapData.EffectRadius); } } }