373 lines
14 KiB
C#
373 lines
14 KiB
C#
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
using Pathfinding;
|
|
|
|
public enum AssignmentType {
|
|
None,
|
|
Table,
|
|
Backroom,
|
|
FrontDesk,
|
|
Bar,
|
|
Order,
|
|
Dishes
|
|
}
|
|
|
|
// To-do item for an employee. The player queues these up,
|
|
// and the employee performs each one best-effort as quickly as they can.
|
|
public class Destination {
|
|
public Transform waypoint;
|
|
public AssignmentType assignmentType;
|
|
public TableController assignedTable;
|
|
public OrderPlacementController order;
|
|
|
|
public Destination(Transform waypoint, AssignmentType assignmentType, TableController assignedTable, OrderPlacementController order) {
|
|
this.waypoint = waypoint;
|
|
this.assignmentType = assignmentType;
|
|
this.assignedTable = assignedTable;
|
|
this.order = order;
|
|
}
|
|
}
|
|
|
|
public class TalentController : MonoBehaviour {
|
|
[SerializeField] List<AudioClip> greetings;
|
|
[SerializeField] List<AudioClip> comply;
|
|
|
|
// Prefab to spawn XP/Money text.
|
|
[SerializeField] GameObject fadingTextProto;
|
|
|
|
[HideInInspector] AudioSource audioSource;
|
|
|
|
[HideInInspector] Animator animator;
|
|
|
|
// Pathfinding related objects.
|
|
[HideInInspector] AIDestinationSetter destination;
|
|
[HideInInspector] AILerp aiLerp;
|
|
|
|
// Not owned.
|
|
[HideInInspector] GameStateController gameStateController;
|
|
|
|
[HideInInspector] bool busy = false;
|
|
|
|
// The distance at which an employee will stop away from a table, if they're
|
|
// walking towards it while it's being serviced by another employee.
|
|
[SerializeField] float maxServiceWaitDistance = 4.0f;
|
|
|
|
// Table service variables.
|
|
[SerializeField] TableController assignedTable = null;
|
|
[HideInInspector] List<Order> heldTickets = new List<Order>();
|
|
[HideInInspector] List<Order> heldFood = new List<Order>();
|
|
[HideInInspector] OrderPlacementController assignedOrder = null;
|
|
[HideInInspector] bool isAtWaypoint = true;
|
|
[HideInInspector] Party seatingParty = null;
|
|
[HideInInspector] bool isHoldingPlates = false;
|
|
[HideInInspector] AssignmentType assignmentType = AssignmentType.None;
|
|
|
|
// TOOD: The list of destinations is overrideable by a visit to the Backroom.
|
|
[SerializeField] Queue<Destination> todo = new Queue<Destination>();
|
|
|
|
[SerializeField] Employee employee = Employee.Elaine;
|
|
|
|
// Start is called before the first frame update
|
|
void Start() {
|
|
audioSource = GetComponent<AudioSource>();
|
|
destination = GetComponent<AIDestinationSetter>();
|
|
animator = GetComponent<Animator>();
|
|
aiLerp = GetComponent<AILerp>();
|
|
gameStateController = GameObject.FindGameObjectWithTag("GameStateController").GetComponent<GameStateController>();
|
|
// TODO: Maybe something safer on GetComponent.
|
|
if (!GameData.IsPlayerUnlocked(employee)) {
|
|
Destroy(gameObject);
|
|
}
|
|
}
|
|
|
|
void NewDestination(Transform waypoint,
|
|
AssignmentType destinationType = AssignmentType.None,
|
|
TableController table = null,
|
|
OrderPlacementController order = null) {
|
|
destination.target = waypoint;
|
|
assignmentType = destinationType;
|
|
assignedTable = table;
|
|
assignedOrder = order;
|
|
isAtWaypoint = false;
|
|
busy = true;
|
|
}
|
|
|
|
// Vector push-back a new Destination onto the employee's to-do list.
|
|
// They will act upon all destinations, in the order they were enqueued by the player.
|
|
public void QueueDestination(Transform waypoint,
|
|
AssignmentType destinationType = AssignmentType.None,
|
|
TableController table = null,
|
|
OrderPlacementController order = null) {
|
|
if (todo.Count == 0 && !busy) {
|
|
PlayRandomSound(comply);
|
|
}
|
|
todo.Enqueue(new Destination(waypoint, destinationType, table, order));
|
|
}
|
|
|
|
public void PlayRandomSound(List<AudioClip> sounds) {
|
|
if (sounds.Count > 0) {
|
|
audioSource.PlayOneShot(sounds[Random.Range(0, sounds.Count)]);
|
|
}
|
|
}
|
|
|
|
public void OnTarget() {
|
|
PlayRandomSound(greetings);
|
|
}
|
|
|
|
private void GainPay(int amount, int tips) {
|
|
Debug.Log("Spawn text with amount + tip amount");
|
|
gameStateController.GainMoney(amount);
|
|
gameStateController.GainTips(employee, tips);
|
|
TextFadeController tfc = Instantiate(fadingTextProto).GetComponent<TextFadeController>();
|
|
tfc.transform.position = transform.position;
|
|
tfc.baseColor = Color.green;
|
|
tfc.text.SetText("+$" + amount.ToString() + " +$" + tips.ToString());
|
|
}
|
|
|
|
private void GainExp(int amount) {
|
|
Debug.Log("Spawn text with exp amount");
|
|
gameStateController.GainExp(employee, amount);
|
|
TextFadeController tfc = Instantiate(fadingTextProto).GetComponent<TextFadeController>();
|
|
tfc.transform.position = transform.position;
|
|
tfc.baseColor = Color.yellow;
|
|
tfc.text.SetText("+" + amount.ToString() + " XP");
|
|
}
|
|
|
|
private IEnumerator PickUpTicket() {
|
|
Debug.Log("TODO: Make dynamic based on employee speed");
|
|
Debug.Log("TODO: Update animation to having conversation");
|
|
Debug.Log("TODO: Implement chance of generating a task instead");
|
|
yield return new WaitForSeconds(2);
|
|
heldTickets.Add(assignedTable.GenerateOrder());
|
|
assignedTable.servicing = false;
|
|
assignedTable = null;
|
|
GainExp(gameStateController.baseExp);
|
|
assignmentType = AssignmentType.None;
|
|
busy = false;
|
|
}
|
|
|
|
private IEnumerator DropOffTickets() {
|
|
Debug.Log("TODO: Make dynamic based on employee speed");
|
|
Debug.Log("TODO: Update animation to dropping off tickets");
|
|
yield return new WaitForSeconds(1);
|
|
gameStateController.Cook(heldTickets);
|
|
heldTickets.Clear();
|
|
GainExp(gameStateController.baseExp);
|
|
assignmentType = AssignmentType.None;
|
|
busy = false;
|
|
}
|
|
|
|
private IEnumerator PickUpFood() {
|
|
Debug.Log("TODO: Make dynamic based on employee speed");
|
|
Debug.Log("TODO: Update animation to grabbing the order");
|
|
yield return new WaitForSeconds(1);
|
|
heldFood.Add(assignedOrder.PickUp());
|
|
assignedOrder = null;
|
|
GainExp(gameStateController.baseExp);
|
|
assignmentType = AssignmentType.None;
|
|
busy = false;
|
|
}
|
|
|
|
private IEnumerator DropOffFood() {
|
|
int i = 0;
|
|
bool droppedOff = false;
|
|
for (; i < heldFood.Count; i++) {
|
|
if (heldFood[i].destination.tableId == assignedTable.tableId) {
|
|
Debug.Log("TODO: Make dynamic based on employee speed");
|
|
Debug.Log("TODO: Update animation to dropping off food");
|
|
yield return new WaitForSeconds(2);
|
|
assignedTable.StartEating();
|
|
GainExp(gameStateController.baseExp);
|
|
droppedOff = true;
|
|
break;
|
|
}
|
|
}
|
|
if (droppedOff) {
|
|
heldFood.RemoveAt(i);
|
|
}
|
|
assignedTable.servicing = false;
|
|
assignedTable = null;
|
|
assignmentType = AssignmentType.None;
|
|
busy = false;
|
|
}
|
|
private IEnumerator PickUpDishes() {
|
|
Debug.Log("TODO: Make dynamic based on employee speed");
|
|
Debug.Log("TODO: Update animation to picking up dishes");
|
|
yield return new WaitForSeconds(2);
|
|
isHoldingPlates = true;
|
|
assignedTable.CleanUpDishes();
|
|
assignedTable.servicing = false;
|
|
assignedTable = null;
|
|
GainExp(gameStateController.baseExp);
|
|
assignmentType = AssignmentType.None;
|
|
busy = false;
|
|
}
|
|
|
|
private IEnumerator PickUpCheck() {
|
|
Debug.Log("TODO: Yay animation");
|
|
yield return new WaitForSeconds(1);
|
|
assignedTable.PickUpCheck();
|
|
GainExp(gameStateController.baseExp);
|
|
GainPay(assignedTable.GetPay(), assignedTable.GetTip());
|
|
assignedTable.servicing = false;
|
|
assignedTable = null;
|
|
assignmentType = AssignmentType.None;
|
|
busy = false;
|
|
}
|
|
|
|
void InteractWithTable() {
|
|
// Set animation and timeout for corresponding action from possibilities:
|
|
// If talent is leading employees, dump them at the table.
|
|
// Otherwise:
|
|
// TableState.Ready -> Table chooses between a food order and task
|
|
// TableState.WaitingOnOrder -> If the employee is holding the table's food, fulfills the order
|
|
// TableState.WaitingOnCheck -> Gather the check and empty the table of plates and guests.
|
|
assignedTable.servicing = true;
|
|
if (seatingParty != null) {
|
|
if (assignedTable.party == null && assignedTable.state == TableState.Empty) {
|
|
Debug.Log("TODO: Convert to Coroutine to take time seating a party");
|
|
assignedTable.AssignParty(seatingParty);
|
|
GainExp(gameStateController.baseExp);
|
|
seatingParty = null;
|
|
}
|
|
} else if (assignedTable.state != TableState.Empty) {
|
|
switch(assignedTable.state) {
|
|
case TableState.WaitingOnOrder:
|
|
// Coroutine should set assignedTable.servicing=false, assignedTable=null, assignmentType=None.
|
|
if (!isHoldingPlates && seatingParty == null && heldTickets.Count == 0) {
|
|
StartCoroutine("DropOffFood");
|
|
return;
|
|
}
|
|
break;
|
|
case TableState.WaitingOnCheck:
|
|
// Coroutine should set assignedTable.servicing=false, assignedTable=null, assignmentType=None.
|
|
StartCoroutine("PickUpCheck");
|
|
return;
|
|
case TableState.ReadyToOrder:
|
|
// Coroutine should set assignedTable.servicing=false, assignedTable=null, assignmentType=None.
|
|
if (!isHoldingPlates && seatingParty == null && heldFood.Count == 0) {
|
|
StartCoroutine("PickUpTicket");
|
|
return;
|
|
}
|
|
break;
|
|
case TableState.Plates:
|
|
// Coroutine should set assignedTable.servicing=false, assignedTable=null, assignmentType=None.
|
|
if (seatingParty == null && heldFood.Count == 0 && heldTickets.Count == 0) {
|
|
StartCoroutine("PickUpDishes");
|
|
return;
|
|
}
|
|
break;
|
|
default:
|
|
Debug.Log("TODO: Sound for un-interactable table, maybe");
|
|
break;
|
|
}
|
|
}
|
|
assignedTable.servicing = false;
|
|
assignmentType = AssignmentType.None;
|
|
assignedTable = null;
|
|
busy = false;
|
|
}
|
|
|
|
void InteractWithBar() {
|
|
// Drop off any held tickets from customers.
|
|
if (heldTickets.Count > 0) {
|
|
StartCoroutine("DropOffTickets");
|
|
return;
|
|
}
|
|
assignmentType = AssignmentType.None;
|
|
busy = false;
|
|
}
|
|
|
|
void InteractWithOrder() {
|
|
// Pick up an order at the waypoint.
|
|
// Should fail if the employee is holding anything other an another order.
|
|
if (assignedOrder.order != null && !isHoldingPlates && heldTickets.Count == 0 && seatingParty == null) {
|
|
StartCoroutine("PickUpFood");
|
|
return;
|
|
}
|
|
assignmentType = AssignmentType.None;
|
|
busy = false;
|
|
}
|
|
|
|
void InteractWithDishes() {
|
|
// Drop off any held dishes at the waypoint.
|
|
// Does nothing else.
|
|
if (isHoldingPlates) {
|
|
Debug.Log("TODO: Make a dish noise?");
|
|
GainExp(gameStateController.baseExp);
|
|
}
|
|
isHoldingPlates = false;
|
|
busy = false;
|
|
}
|
|
|
|
// If the front desk has a party queued, grab the party.
|
|
// Fails if busy or ineligible.
|
|
void InteractWithFrontDesk() {
|
|
if (isHoldingPlates || heldFood.Count > 0 || heldTickets.Count > 0 || seatingParty != null) {
|
|
Debug.Log("TODO: Play sound for failed queue interaction");
|
|
} else if (gameStateController.frontDeskQueue.Count == 0) {
|
|
Debug.Log("TODO: Play sound for empty queue");
|
|
} else {
|
|
Debug.Log("TODO: Parameterize front desk interact for particular party");
|
|
Party candidateParty = gameStateController.frontDeskQueue.Peek();
|
|
if (gameStateController.ValidateParty(candidateParty)) {
|
|
seatingParty = gameStateController.frontDeskQueue.Dequeue();
|
|
} else {
|
|
Debug.Log("TODO: Party grab failure sound");
|
|
}
|
|
}
|
|
busy = false;
|
|
}
|
|
|
|
// Update is called once per frame
|
|
void Update()
|
|
{
|
|
// This is true on the frame at which the employee reaches the waypoint.
|
|
if (!isAtWaypoint && aiLerp.reachedDestination) {
|
|
isAtWaypoint = true;
|
|
if (assignmentType == AssignmentType.Table && assignedTable != null) {
|
|
Debug.Log("I reached the table!");
|
|
InteractWithTable();
|
|
} else if (assignmentType == AssignmentType.Bar) {
|
|
Debug.Log("I reached the bar to drop off a ticket!");
|
|
InteractWithBar();
|
|
} else if (assignmentType == AssignmentType.Order) {
|
|
Debug.Log("I reached the bar to pick up an order!");
|
|
InteractWithOrder();
|
|
} else if (assignmentType == AssignmentType.Dishes) {
|
|
Debug.Log("I reached the dishes!");
|
|
InteractWithDishes();
|
|
} else if (assignmentType == AssignmentType.FrontDesk) {
|
|
Debug.Log("I reached the front desk!");
|
|
InteractWithFrontDesk();
|
|
}
|
|
}
|
|
|
|
// If the employee is available, pop the top of the queue and set it as a destination.
|
|
if (!busy && todo.Count > 0) {
|
|
Destination dest = todo.Dequeue();
|
|
NewDestination(dest.waypoint, dest.assignmentType, dest.assignedTable, dest.order);
|
|
}
|
|
|
|
// If another employee is servicing the assigned table, wait for them to finish.
|
|
if (assignedTable != null &&
|
|
assignedTable.servicing &&
|
|
Vector2.Distance(transform.position, assignedTable.waypoint.transform.position) <= maxServiceWaitDistance) {
|
|
aiLerp.canMove = false;
|
|
} else {
|
|
aiLerp.canMove = true;
|
|
}
|
|
}
|
|
|
|
private void LateUpdate() {
|
|
if (aiLerp.canMove) {
|
|
animator.SetInteger("hSpeed", (int)aiLerp.velocity.x);
|
|
animator.SetInteger("vSpeed", (int)aiLerp.velocity.y);
|
|
} else {
|
|
animator.SetInteger("hSpeed", 0);
|
|
animator.SetInteger("vSpeed", 0);
|
|
}
|
|
}
|
|
}
|