using System.Collections; using System.Linq; using Unity.BossRoom.Gameplay.GameplayObjects.Character; using Unity.Netcode; using UnityEngine; using DG.Tweening; namespace Unity.Multiplayer.Samples.BossRoom { [RequireComponent(typeof(Collider))] public class Platform : NetworkBehaviour { public NetworkVariable PlatformID = new NetworkVariable(0); public bool IsOccupied { get; private set; } private NetworkVariable occupierId = new NetworkVariable(0, NetworkVariableReadPermission.Everyone, NetworkVariableWritePermission.Server); private Collider platformCollider; private Animator animator; private float occupationTime = 0f; private float penaltyInterval = 3f; private Coroutine penaltyCoroutine; private Coroutine timerCoroutine; [SerializeField] private GameObject barrierObject; [SerializeField] private GameObject AuraObj; [SerializeField] private GameObject TimerObject; private Material timerMaterial; private float maxTime = 10f; private void Awake() { platformCollider = GetComponent(); platformCollider.isTrigger = true; animator = GetComponent(); if (TimerObject != null) { Renderer renderer = TimerObject.GetComponent(); if (renderer != null) { timerMaterial = new Material(renderer.material); renderer.material = timerMaterial; } TimerObject.SetActive(false); } } private void Start() { if (IsServer) { Invoke(nameof(EnableCollider), 2); } } public void RefreshCollider() { if (platformCollider != null) { platformCollider.enabled = false; platformCollider.enabled = true; } } public void AssignID(int id) { if (IsServer) { PlatformID.Value = id; } } private void EnableCollider() { platformCollider.enabled = true; } public void StartRotation() { transform.DOLocalRotate(Vector3.up, 120).SetSpeedBased(true).SetId(PlatformID).SetLoops(-1, LoopType.Incremental); } public void EnableBarrier() { var excludedClient = NetworkManager.Singleton.LocalClientId; var clientRpcParams = new ClientRpcParams { Send = new ClientRpcSendParams { TargetClientIds = NetworkManager.Singleton.ConnectedClientsIds .Where(clientId => clientId != excludedClient) .ToArray() } }; EnableBarrierClientRpc(clientRpcParams); } public void DisableBarrier() { DisableBarrierClientRpc(); } [ClientRpc] private void EnableBarrierClientRpc(ClientRpcParams clientRpcParams = default) { AuraObj.SetActive(true); if (barrierObject != null) { barrierObject.SetActive(true); } } [ClientRpc] private void DisableBarrierClientRpc() { AuraObj.SetActive(false); if (barrierObject != null) { barrierObject.SetActive(false); } } private void OnTriggerEnter(Collider other) { if (IsServer && other.TryGetComponent(out var player) && !IsOccupied) { Occupy(player); } } private void OnTriggerExit(Collider other) { if (IsServer && other.TryGetComponent(out var player)) { Vacate(player); } } public ulong GetOccupierId() { return occupierId.Value; } public void Vacate(ServerCharacter player) { if (!IsServer || !IsOccupied || occupierId.Value != player.OwnerClientId) { return; } IsOccupied = false; occupierId.Value = 0; player.OnLeavingPlatform(PlatformID.Value); DisableBarrier(); if (penaltyCoroutine != null) { StopCoroutine(penaltyCoroutine); penaltyCoroutine = null; } VacateTimeClientRpc(); } [ClientRpc] void VacateTimeClientRpc() { if (timerCoroutine != null) { StopCoroutine(timerCoroutine); timerCoroutine = null; } if (TimerObject != null) { TimerObject.SetActive(false); } } public void PausePlatformAnimation() { if (IsServer) { animator.speed = 0f; PauseClientRpc(); } } public void Occupy(ServerCharacter player) { if (!IsServer) { return; } if (IsOccupied) { return; } // If the player is currently the crow, convert them back into a normal player if (player.IsCrow) { Debug.Log($"[Platform] Crow {player.name} landed on platform {PlatformID.Value}, converting back to player."); CrowManager.Instance.ClearCrow(); // Notify CrowManager to clear the current crow } IsOccupied = true; occupierId.Value = player.OwnerClientId; player.OnArrivalOnPlatform(PlatformID.Value); PausePlatformAnimation(); bool giveScore = player.PreviousPlatformId.HasValue && player.PreviousPlatformId.Value != PlatformID.Value; if (giveScore) { bool isOnTargetedPlatform = player.TargetPlatformId.HasValue && player.TargetPlatformId.Value == this.PlatformID.Value; Platform platformB = isOnTargetedPlatform ? PlatformManager.Instance.GetPlatformById(player.TargetPlatformId.Value) : PlatformManager.Instance.GetPlatformById(this.PlatformID.Value); if (!player.PreviousPlatformId.HasValue) { return; } Platform platformA = PlatformManager.Instance.GetPlatformById(player.PreviousPlatformId.Value); if (platformA == null || platformB == null) { return; } float distance = Vector3.Distance(platformA.transform.position, platformB.transform.position); float multiplier = 1.0f; if (distance < 5f) { multiplier = 1.1f; } else if (distance < 10f) { multiplier = 1.2f; } else if (distance < 20f) { multiplier = 1.5f; } else { multiplier = 2.0f; } int baseScore = (player.TargetPlatformId.HasValue && player.TargetPlatformId.Value == PlatformID.Value) ? 10 : 20; int score = Mathf.RoundToInt(baseScore * multiplier); ScoreManager.Instance.AddPlayerScore(player.OwnerClientId, score); } EnableBarrier(); penaltyCoroutine = StartCoroutine(HandleOccupationPenalty(player)); OccupyTimerClientRpc(); } [ClientRpc] public void OccupyTimerClientRpc() { if (TimerObject != null) { TimerObject.SetActive(true); if (timerCoroutine != null) StopCoroutine(timerCoroutine); timerCoroutine = StartCoroutine(UpdateTimerShader(maxTime)); } } [ClientRpc] private void PauseClientRpc() { animator.speed = 0f; } private IEnumerator HandleOccupationPenalty(ServerCharacter player) { occupationTime = 0f; while (IsOccupied) { occupationTime += Time.deltaTime; if (occupationTime >= 10f) { yield return new WaitForSeconds(penaltyInterval); ScoreManager.Instance.SubtractPlayerScore(player.OwnerClientId, 10,Color.red); } yield return null; } } private IEnumerator UpdateTimerShader(float duration) { float elapsed = 0f; while (elapsed < duration) { elapsed += Time.deltaTime; float progress = Mathf.Clamp01(elapsed / duration); if (timerMaterial != null) { timerMaterial.SetFloat("_ClipUvLeft", 1 - progress); timerMaterial.SetColor("_Color", Color.Lerp(Color.green, Color.red, progress)); } yield return null; } } } } //using System.Collections; //using System.Linq; //using Unity.BossRoom.Gameplay.GameplayObjects.Character; //using Unity.Netcode; //using UnityEngine; //using DG.Tweening; //namespace Unity.Multiplayer.Samples.BossRoom //{ // [RequireComponent(typeof(Collider))] // public class Platform : NetworkBehaviour // { // public NetworkVariable PlatformID = new NetworkVariable(0); // public bool IsOccupied { get; private set; } // private NetworkVariable occupierId = new NetworkVariable(0, NetworkVariableReadPermission.Everyone, NetworkVariableWritePermission.Server); // private Collider platformCollider; // private Animator animator; // private float occupationTime = 0f; // private float penaltyInterval = 3f; // Interval for penalty deduction // private Coroutine penaltyCoroutine; // [SerializeField] private GameObject barrierObject; // [SerializeField] GameObject AuraObj; // [SerializeField] ; // private void Awake() // { // platformCollider = GetComponent(); // platformCollider.isTrigger = true; // animator = GetComponent(); // } // private void Start() // { // if (IsServer) // { // Invoke(nameof(EnableCollider), 2); // Delay collider enabling for server // } // } // public void RefreshCollider() // { // if (platformCollider != null) // { // platformCollider.enabled = false; // Temporarily disable collider // platformCollider.enabled = true; // Re-enable to refresh // } // } // public void AssignID(int id) // { // if (IsServer) // { // PlatformID.Value = id; // } // } // private void EnableCollider() // { // platformCollider.enabled = true; // } // public void StartRotation() // { // transform.DOLocalRotate(Vector3.up, 120).SetSpeedBased(true).SetId(PlatformID).SetLoops(-1, LoopType.Incremental); // } // private void PauseRotation() // { // DOTween.Pause(PlatformID); // } // private void ResumeRotation() // { // DOTween.Play(PlatformID); // } // public void PausePlatformAnimation() // { // if (IsServer) // { // animator.speed = 0f; // PauseClientRpc(); // } // } // public void Resume() // { // if (IsServer) // { // animator.speed = 1f; // ResumeClientRpc(); // } // } // [ClientRpc] // private void PauseClientRpc() // { // animator.speed = 0f; // } // [ClientRpc] // private void ResumeClientRpc() // { // animator.speed = 1f; // } // public void Occupy(ServerCharacter player) // { // if (!IsServer) // { // Debug.LogWarning($"[Occupy] Attempted to occupy platform {PlatformID.Value} on a non-server instance."); // return; // } // if (IsOccupied) // { // Debug.LogWarning($"[Occupy] Platform {PlatformID.Value} is already occupied. Player {player.OwnerClientId} cannot occupy."); // return; // } // IsOccupied = true; // occupierId.Value = player.OwnerClientId; // player.OnArrivalOnPlatform(PlatformID.Value); // Debug.Log($"[Occupy] Player {player.OwnerClientId} is occupying platform {PlatformID.Value}."); // PausePlatformAnimation(); // bool giveScore = player.PreviousPlatformId.HasValue && player.PreviousPlatformId.Value != PlatformID.Value; // Debug.Log($"[Occupy] GiveScore check: PreviousPlatformId = {player.PreviousPlatformId}, CurrentPlatformId = {PlatformID.Value}, Result = {giveScore}"); // if (giveScore) // { // bool isOnTargetedPlatform = player.TargetPlatformId.HasValue && player.TargetPlatformId.Value == this.PlatformID.Value; // Debug.Log($"[Occupy] Is on targeted platform: {isOnTargetedPlatform}"); // Platform platformB = isOnTargetedPlatform // ? PlatformManager.Instance.GetPlatformById(player.TargetPlatformId.Value) // : PlatformManager.Instance.GetPlatformById(this.PlatformID.Value); // if (!player.PreviousPlatformId.HasValue) // { // Debug.LogError($"[Occupy] Error: player.PreviousPlatformId is null! Cannot calculate distance."); // return; // } // Platform platformA = PlatformManager.Instance.GetPlatformById(player.PreviousPlatformId.Value); // if (platformA == null || platformB == null) // { // Debug.LogError($"[Occupy] Platform lookup failed: platformA ({player.PreviousPlatformId.Value}) or platformB ({(isOnTargetedPlatform ? player.TargetPlatformId.Value : this.PlatformID.Value)}) is null!"); // return; // } // // Define distance ranges and their corresponding multipliers // float distance = Vector3.Distance(platformA.transform.position, platformB.transform.position); // Debug.Log($"the distance is: {distance}"); // float multiplier = 1.0f; // if (distance < 5f) // { // multiplier = 1.1f; // Small distance // } // else if (distance < 10f) // { // multiplier = 1.2f; // Medium distance // } // else if (distance < 20f) // { // multiplier = 1.5f; // Large distance // } // else // { // multiplier = 2.0f; // Max multiplier cap // } // Debug.Log($"[Occupy] Distance multiplier: {multiplier} (from {platformA.PlatformID.Value} to {platformB.PlatformID.Value})"); // // Base score calculation // int baseScore = (player.TargetPlatformId.HasValue && player.TargetPlatformId.Value == PlatformID.Value) ? 10 : 20; // int score = Mathf.RoundToInt(baseScore * multiplier); // Debug.Log($"[Occupy] Calculated score for player {player.OwnerClientId}: {score}"); // // Add the calculated score // ScoreManager.Instance.AddPlayerScore(player.OwnerClientId, score); // } // Debug.Log($"[Occupy] Player {player.OwnerClientId} successfully occupied platform {PlatformID.Value}. Starting penalty coroutine."); // penaltyCoroutine = StartCoroutine(HandleOccupationPenalty(player)); // EnableBarrier(); // Debug.Log($"[Occupy] Barrier enabled for platform {PlatformID.Value}."); // } // private IEnumerator HandleOccupationPenalty(ServerCharacter player) // { // occupationTime = 0f; // while (IsOccupied) // { // occupationTime += Time.deltaTime; // if (occupationTime >= 10f) // { // yield return new WaitForSeconds(penaltyInterval); // // Deduct points // ScoreManager.Instance.SubtractPlayerScore(player.OwnerClientId, 10); // Debug.Log($"Player {player.OwnerClientId} lost 10 points for occupying the platform too long."); // } // yield return null; // } // } // public void Vacate(ServerCharacter player) // { // if (!IsServer || !IsOccupied || occupierId.Value != player.OwnerClientId) // { // return; // } // Resume(); // IsOccupied = false; // occupierId.Value = 0; // player.OnLeavingPlatform(PlatformID.Value); // DisableBarrier(); // if (penaltyCoroutine != null) // { // StopCoroutine(penaltyCoroutine); // penaltyCoroutine = null; // } // } // private void EnableBarrier() // { // var excludedClient = NetworkManager.Singleton.LocalClientId; // var clientRpcParams = new ClientRpcParams // { // Send = new ClientRpcSendParams // { // TargetClientIds = NetworkManager.Singleton.ConnectedClientsIds // .Where(clientId => clientId != excludedClient) // .ToArray() // } // }; // EnableBarrierClientRpc(clientRpcParams); // } // private void DisableBarrier() // { // DisableBarrierClientRpc(); // } // [ClientRpc] // private void EnableBarrierClientRpc(ClientRpcParams clientRpcParams = default) // { // AuraObj.SetActive(true); // if (barrierObject != null) // { // barrierObject.SetActive(true); // } // } // [ClientRpc] // private void DisableBarrierClientRpc() // { // AuraObj.SetActive(false); // if (barrierObject != null) // { // barrierObject.SetActive(false); // } // } // private void OnTriggerEnter(Collider other) // { // if (IsServer && other.TryGetComponent(out var player) && !IsOccupied) // { // Occupy(player); // } // } // private void OnTriggerExit(Collider other) // { // if (IsServer && other.TryGetComponent(out var player)) // { // Vacate(player); // } // } // public ulong GetOccupierId() // { // return occupierId.Value; // } // } //}