Added player task system. simple interaction with objects. Known issue - no player stats canvas
This commit is contained in:
@@ -0,0 +1,158 @@
|
||||
using Assets.Scripts.Actions.Interfaces;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.AI;
|
||||
|
||||
public enum Tasks { Move, Interact };
|
||||
public enum TaskStatus { Waiting, InProgress, Complete };
|
||||
|
||||
public class Player : MonoBehaviour
|
||||
{
|
||||
public event EventHandler<OnPlayerMovesEventArgs> OnPlayerMoves;
|
||||
private enum States { Idle, Walking, Sleeping };
|
||||
|
||||
public static Player Instance { get; private set; }
|
||||
|
||||
[SerializeField]
|
||||
public NavMeshAgent _navAgent;
|
||||
[SerializeField]
|
||||
public Animator _animator;
|
||||
|
||||
public bool allowMovement = true;
|
||||
private States _state;
|
||||
private Vector3 _groundDeltaPosition;
|
||||
|
||||
public Dictionary<StatsId, Stat> PlayerStats;
|
||||
public IWorkPlace WorkPlace { get; set; }
|
||||
|
||||
private readonly Queue<PlayerTasks> _tasks = new Queue<PlayerTasks>();
|
||||
private PlayerTasks _currentTask;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
if (Instance != null)
|
||||
{
|
||||
Debug.Log("There's more than one player instance");
|
||||
return;
|
||||
}
|
||||
Instance = this;
|
||||
}
|
||||
private void Start()
|
||||
{
|
||||
TimeManager.OnMinuteChanged += UpdatePlayerState;
|
||||
allowMovement = true;
|
||||
_navAgent.updatePosition = false;
|
||||
PlayerStats = GameManager.Instance.PlayerStats;
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
TimeManager.OnMinuteChanged -= UpdatePlayerState;
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (_currentTask == null || _currentTask.Status == TaskStatus.Complete)
|
||||
{
|
||||
_tasks.TryDequeue(out _currentTask);
|
||||
}
|
||||
if (_currentTask != null)
|
||||
{
|
||||
switch (_currentTask.Task)
|
||||
{
|
||||
case Tasks.Move:
|
||||
OnPlayerMoves?.Invoke(this, new OnPlayerMovesEventArgs() { PointToMove = _currentTask.Position });
|
||||
_navAgent.SetDestination(_currentTask.Position);
|
||||
_currentTask.UpdateStatus(MoveToPoint());
|
||||
break;
|
||||
case Tasks.Interact:
|
||||
_currentTask.UpdateStatus(InteractWithObject(_currentTask.Interactable));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private TaskStatus MoveToPoint()
|
||||
{
|
||||
var worldDeltaPosition = _navAgent.nextPosition - transform.position;
|
||||
_groundDeltaPosition.x = Vector3.Dot(transform.right, worldDeltaPosition);
|
||||
_groundDeltaPosition.y = Vector3.Dot(transform.forward, worldDeltaPosition);
|
||||
|
||||
Vector2 velocity = (Time.deltaTime > 1e-5f) ? _groundDeltaPosition / Time.deltaTime : Vector2.zero;
|
||||
var shouldMove = velocity.magnitude > 0.025f && _navAgent.remainingDistance > _navAgent.radius;
|
||||
if (_state != States.Sleeping)
|
||||
{
|
||||
_state = shouldMove ? States.Walking : States.Idle;
|
||||
|
||||
_animator.SetBool("Move", shouldMove);
|
||||
_animator.SetFloat("velY", velocity.y);
|
||||
}
|
||||
|
||||
return pathComplete() ? TaskStatus.Complete : TaskStatus.InProgress;
|
||||
}
|
||||
|
||||
private bool pathComplete()
|
||||
{
|
||||
if (Vector3.Distance(_navAgent.destination, _navAgent.transform.position) <= _navAgent.radius)
|
||||
{
|
||||
if (!_navAgent.hasPath || _navAgent.velocity.sqrMagnitude == 0f)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private TaskStatus InteractWithObject(BaseInteractableObject interactableObject)
|
||||
{
|
||||
interactableObject.Interact();
|
||||
return TaskStatus.Complete;
|
||||
}
|
||||
|
||||
private void OnAnimatorMove()
|
||||
{
|
||||
transform.position = _navAgent.nextPosition;
|
||||
}
|
||||
|
||||
public void AddTask(PlayerTasks task)
|
||||
{
|
||||
_tasks.Enqueue(task);
|
||||
}
|
||||
|
||||
public void UpdatePlayerState()
|
||||
{
|
||||
PlayerStats[StatsId.Food].deduct(0.034m); // 48 hours it's 100, 100/2880=~0.034 per minute
|
||||
switch (_state)
|
||||
{
|
||||
case States.Idle:
|
||||
case States.Walking:
|
||||
PlayerStats[StatsId.Energy].deduct(0.1m); // 24 hours it's 100, 100/1440=~0.096 per minute
|
||||
break;
|
||||
case States.Sleeping:
|
||||
PlayerStats[StatsId.Energy].increase(1m);
|
||||
break;
|
||||
}
|
||||
if (PlayerStats[StatsId.Energy].Value <= 10 && _state != States.Sleeping)
|
||||
{
|
||||
_state = States.Sleeping;
|
||||
allowMovement = false;
|
||||
_animator.SetBool("Fall", true);
|
||||
}
|
||||
if (PlayerStats[StatsId.Energy].Value >= 100 && _state == States.Sleeping)
|
||||
{
|
||||
_state = States.Idle;
|
||||
allowMovement = true;
|
||||
_animator.SetBool("Fall", false);
|
||||
}
|
||||
}
|
||||
|
||||
public void BuyAction(IPlayerAction action)
|
||||
{
|
||||
PlayerStats[StatsId.Money].deduct(((ISellable)action).Price);
|
||||
action.ApplyAction(this);
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user