182 lines
5.9 KiB
C#
182 lines
5.9 KiB
C#
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<bool> _isDowned;
|
|
|
|
public bool IsDowned => _isDowned.Value;
|
|
|
|
private float timeDowned;
|
|
|
|
public GameObject pickupTarget;
|
|
|
|
void Awake(){
|
|
controls = GetComponent<PlayerControls>();
|
|
maxHealth = 20f;
|
|
}
|
|
|
|
public void Attach(){
|
|
if (IsLocalPlayer || !UnitIsNetworked()) { //
|
|
PlayerManager.Player = gameObject;
|
|
|
|
PlayerManager.RequestNewController();
|
|
GetComponent<LockOnManager>().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<IKillable>().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<Player>().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<Player>().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;
|
|
}
|
|
}
|
|
} |