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.
HighGroundRoyaleNetcode/Assets/Scripts/Gameplay/Platform.cs

261 lines
8.4 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; // Interval for penalty deduction
private Coroutine penaltyCoroutine;
[SerializeField] private GameObject barrierObject;
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 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;
}
int multiplier = (int)Vector3.Distance(platformA.transform.position, platformB.transform.position);
Debug.Log($"[Occupy] Distance multiplier: {multiplier} (from {platformA.PlatformID.Value} to {platformB.PlatformID.Value})");
int score = (player.TargetPlatformId.HasValue && player.TargetPlatformId.Value == PlatformID.Value) ? 10 : 20;
score *= multiplier;
Debug.Log($"[Occupy] Calculated score for player {player.OwnerClientId}: {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)
{
if (barrierObject != null)
{
barrierObject.SetActive(true);
}
}
[ClientRpc]
private void DisableBarrierClientRpc()
{
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;
}
}
}