You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

601 lines
19 KiB
C#

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<int> PlatformID = new NetworkVariable<int>(0);
public bool IsOccupied { get; private set; }
private NetworkVariable<ulong> occupierId = new NetworkVariable<ulong>(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<Collider>();
platformCollider.isTrigger = true;
animator = GetComponent<Animator>();
if (TimerObject != null)
{
Renderer renderer = TimerObject.GetComponent<Renderer>();
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<ServerCharacter>(out var player) && !IsOccupied)
{
Occupy(player);
}
}
private void OnTriggerExit(Collider other)
{
if (IsServer && other.TryGetComponent<ServerCharacter>(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;
}
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;
}
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);
}
penaltyCoroutine = StartCoroutine(HandleOccupationPenalty(player));
EnableBarrier();
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);
}
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<int> PlatformID = new NetworkVariable<int>(0);
// public bool IsOccupied { get; private set; }
// private NetworkVariable<ulong> occupierId = new NetworkVariable<ulong>(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<Collider>();
// platformCollider.isTrigger = true;
// animator = GetComponent<Animator>();
// }
// 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<ServerCharacter>(out var player) && !IsOccupied)
// {
// Occupy(player);
// }
// }
// private void OnTriggerExit(Collider other)
// {
// if (IsServer && other.TryGetComponent<ServerCharacter>(out var player))
// {
// Vacate(player);
// }
// }
// public ulong GetOccupierId()
// {
// return occupierId.Value;
// }
// }
//}