using System.Collections; using Drawing; using Reset.Core; using Sirenix.OdinInspector; using UnityEngine; using Unity.Netcode; namespace Reset.Units{ public class Player : Unit, IKillable, IInteractable{ [HideInInspector] public PlayerControls controls; public float maxHealth{ get; set; } public float currentHealth{ get; set; } public NetworkVariable _isDowned; public bool IsDowned => _isDowned.Value; private float timeDowned; public GameObject pickupTarget; void Awake(){ controls = GetComponent(); maxHealth = 20f; } public void Attach(){ if (IsLocalPlayer || !UnitIsNetworked()) { // PlayerManager.Player = gameObject; PlayerManager.RequestNewController(); GetComponent().AttachCamera(gameObject); } } public override void UnitStart(){ base.UnitStart(); SetPlayerName(); Attach(); ((IKillable)this).IKillableInitialize(); } private void SetPlayerName(){ name = "Player"; if (UnitIsNetworked()){ name += IsLocalPlayer ? ", Local" : ", Network"; } } public override void UnitUpdate(){ GetComponent().DrawHealthDebug(); } public void TakeDamage(DamageSource[] sources){ foreach (DamageSource source in sources) { TakeDamage(source); } } public void TakeDamage(DamageSource source){ ((IKillable)this).currentHealth -= source.damageDealt; if (UnitIsNetworked()) { SetNewHealthRpc(currentHealth); } } // TODO: Move somewhere not stupid so there's not an identical method in Enemy.cs [Rpc(SendTo.Everyone)] public void SetNewHealthRpc(float health){ currentHealth = health; // NOTE: only here for testing. Move out of here into some "post damage" check method if (((IKillable)this).currentHealth <= 0) { // if (UnitIsNetworked()) { Down(); // } else { // Kill(); // } } } public void Down(){ Graph.SendEvent("Downed"); } public void Kill(){ Graph.SendEvent("Killed"); } public void Interact(){ // Check if the other player can be interacted with at all if (pickupTarget&& pickupTarget.GetComponent().CanInteract()) { // Tell the local player to start picking up the ally and switch states Graph.SendEvent("Picking Up Ally"); // Tell the target player to start getting picked up. pickupTarget.GetComponent().StartPickupRpc(); // Wait for the pickup timer to finish StartCoroutine(PickupTimer()); } } [Rpc(SendTo.Owner)] public void StartPickupRpc(){ // When picked up by another player, move into the pick up state // TODO: Turn all these send events into a goddamn task maybe? State stuff should happen in the state machine. Concurrent stuff should happen in code Graph.SendEvent("Pick Up Start"); } IEnumerator PickupTimer(){ // Start a timer and wait for it to complete float elapsed = 0f; while (elapsed < 7f) { elapsed += 1f * Time.deltaTime; yield return null; } Graph.SendEvent("Pick Up Success"); } public bool CanInteract(){ return IsDowned; } public void CancelInteract(){ Graph.SendEvent("Pick Up Failed"); } public void OnObserverDetected(EnvironmentObserver observer){ // Try and get a Player component from the current hit object // The rest of the logic will continue as expected so long as an pickupTarget = observer.hit.collider.gameObject; DrawInteractStatus(); } void DrawInteractStatus(){ using (Draw.WithColor(Color.blue)) { Draw.ingame.Label2D(transform.position + Vector3.up * 2.5f, "Interactable", Color.orchid); } } [Rpc(SendTo.Everyone)] public void DrawReviveBarRpc(float elapsedTime){ Debug.Log("test is drawn"); using (Draw.ingame.WithLineWidth(5f)) { using (Draw.InLocalSpace(transform)){ float width = .9f; float widthDone = width * elapsedTime / 5f; widthDone = Mathf.Clamp(widthDone, 0, width); Vector3 pos = Vector3.up * 1.8f + Vector3.left * width + Vector3.forward * .01f; Draw.ingame.Line(Camera.main.transform.rotation * pos, Camera.main.transform.rotation * (pos + Vector3.right * width * 2f), Color.rebeccaPurple); Vector3 donePos = Vector3.up * 1.8f + Vector3.left * widthDone; Draw.ingame.Line(Camera.main.transform.rotation * donePos, Camera.main.transform.rotation * (donePos + Vector3.right * widthDone * 2f), Color.red); } } lastKnownReviveTime = elapsedTime; } void LateUpdate(){ // Clear the pickupTarget every frame // NOTE: Will this work online? pickupTarget = null; } } }