Insanely huge initial commit

This commit is contained in:
2026-02-21 17:04:05 -08:00
parent 9cdd36191a
commit 613d75914a
22525 changed files with 4035207 additions and 0 deletions

View File

@@ -0,0 +1,459 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Pathfinding;
using Com.LuisPedroFonseca.ProCamera2D;
using TMPro;
using UnityEngine.UI;
public enum PatronType {
Default
}
public class Party {
// Gameplay stats.
// Set of patrons to be seated. The size determines eligible tables.
// The type determines what sprites to use.
public List<PatronType> patrons;
// Default amount of time before the party walks out when waiting on something.
public int patience = 5;
// Chance for a party to give a task instead of an order.
public int baseTaskRate = 50;
// Default speed at which a party decides on an order and eats.
public int baseSpeed = 10;
public Party(List<PatronType> patrons, int patience, int baseTaskRate, int baseSpeed) {
this.patrons = patrons;
this.patience = patience;
this.baseTaskRate = baseTaskRate;
this.baseSpeed = baseSpeed;
}
}
public class TalentState {
public int energy { get; set; } = 100;
public int tips { get; set; } = 0;
public int exp { get; set; } = 0;
// Not owned.
public TableController assignedTable { get; set; } = null;
// public StageSlotController assignedStageSlot = null;
// public int assignedBackroom = -1;
// public bool atFrontDesk = false;
}
public class GameStateController : MonoBehaviour {
[SerializeField] TalentListController talentList;
[HideInInspector] GameAudioController audioController;
[HideInInspector] int selectedTab = -1;
[HideInInspector] ProCamera2D proCamera2D;
[HideInInspector] ProCamera2DPanAndZoom proCamera2DPan;
[HideInInspector] ProCamera2DTransitionsFX proCamera2DTransition;
[HideInInspector] Animator expandedCG;
[HideInInspector] SummaryController summaryController;
// List of all tables in the map.
// Used to validate party seating eligibility.
[HideInInspector] private List<TableController> tables = new List<TableController>();
[SerializeField] public List<OrderPlacementController> orderPlacements;
// Game loop stats.
[HideInInspector] public int moneyEarned = 0;
[HideInInspector] public int currentTime = 0;
[HideInInspector] public int patrons = 0;
[HideInInspector] public Queue<Party> frontDeskQueue = new Queue<Party>();
[HideInInspector] public Queue<Order> orderBacklog = new Queue<Order>();
[HideInInspector] public bool gameRunning = false;
// Game init values.
[SerializeField] int secondsPerTick = 10;
[SerializeField] int maxTime = 30;
[SerializeField] int openingHour = 6;
// Game init values (configurable).
// Varies based on progress in the game. Will be loaded dynamically.
// Max number of parties waiting to be seated.
[SerializeField] int queueCapacity = 3;
// Spawn speed of new parties per minute.
[SerializeField] int baseSpawnRate = 1;
// Seconds to wait before spawning the first party.
[SerializeField] int firstSpawnTime = 3;
// EXP earned for completing actions.
// Subject to bonuses based on what the talent does.
[SerializeField] public int baseExp = 5;
// Probability distribution of party size, starting at 1.
// Works the same as the Grand Star item lottery.
// Must add to 100.
[SerializeField] List<int> partySizeDistribution =
new List<int>() { 25, 50, 20, 5 };
// Multiplier distribution to receive different letter grades.
// C, B, A, S, SS. You get an F if you're below the goal.
[SerializeField] public List<float> gradeDistribution =
new List<float>() { 1.0f, 1.5f, 2.0f, 2.5f, 3.0f };
// Goal for the day. You fail and the day resets if you don't hit this goal.
[SerializeField] public int moneyGoal = 100;
// Base multiplier for earned money per patron.
[SerializeField] public float baseMoneyMultiplier = 100.0f;
// Base difficulty for patron patience and tipping.
[SerializeField] public float difficulty = 1.0f;
// Status indicators.
// Not owned.
[SerializeField] public TextMeshProUGUI text_CurrentTime;
[SerializeField] public TextMeshProUGUI text_CurrentMoney;
[SerializeField] public TextMeshProUGUI text_CurrentPatrons;
// Guaranteed waypoints.
// Not owned.
// Backroom is targeted automatically when a talent receives a task.
[HideInInspector] public Transform backroom;
// Bar is targeted with a hotkey (B).
[HideInInspector] public Transform bar;
// Front desk is targeted with a hotkey (F).
[HideInInspector] public Transform frontDesk;
// Dishes can be targeted with a hotkey (D).
[HideInInspector] public Transform dishes;
// Should load from GameData later.
public TalentState[] talentState = {
// Elaine
new TalentState() {
energy = GameData.GLOBAL
.employeeStats[(int)Employee.Elaine].maxEnergy
},
new TalentState() {
energy = GameData.GLOBAL
.employeeStats[(int)Employee.Irida].maxEnergy
},
new TalentState() {
energy = GameData.GLOBAL
.employeeStats[(int)Employee.Clem].maxEnergy
},
new TalentState() {
energy = GameData.GLOBAL
.employeeStats[(int)Employee.Schroder].maxEnergy
},
};
private void EndTimer() {
Debug.Log("TODO: Make all employees stop what they're doing");
gameRunning = false;
summaryController.gameObject.SetActive(true);
summaryController.SetText();
}
IEnumerator GameTimer() {
while (currentTime < maxTime) {
yield return new WaitForSeconds(secondsPerTick);
currentTime += 1;
}
EndTimer();
}
IEnumerator SpawnTimer() {
yield return new WaitForSeconds(firstSpawnTime);
if (frontDeskQueue.Count < queueCapacity) {
NewParty();
}
while (gameRunning) {
yield return new WaitForSeconds(60 / baseSpawnRate);
if (frontDeskQueue.Count < queueCapacity) {
NewParty();
}
}
}
private void StartTimer() {
if (currentTime < maxTime) {
gameRunning = true;
StartCoroutine("GameTimer");
StartCoroutine("SpawnTimer");
}
}
private PatronType GeneratePatron() {
Debug.Log("TODO: Patron type variance");
return PatronType.Default;
}
private void NewParty() {
int lotto = Random.Range(0, 100);
int lottoSum = 0;
int i = 0;
List<PatronType> patrons = new List<PatronType>() {
GeneratePatron()
};
while (i < partySizeDistribution.Count && partySizeDistribution[i] + lottoSum < lotto) {
lottoSum += partySizeDistribution[i];
i += 1;
patrons.Add(GeneratePatron());
}
Debug.Log("TODO: Party stat variance");
frontDeskQueue.Enqueue(new Party(
patrons,
/*patience =*/ 5,
/*baseTaskRate =*/ 10,
/*baseSpeed =*/ 15));
Debug.Log("New Party (" + frontDeskQueue.Count.ToString() + ")");
}
// Start is called before the first frame update
void Start() {
audioController = GetComponent<GameAudioController>();
backroom = GameObject.FindGameObjectWithTag("BackroomWaypoint").transform;
bar = GameObject.FindGameObjectWithTag("BarWaypoint").transform;
frontDesk = GameObject.FindGameObjectWithTag("FrontDeskWaypoint").transform;
dishes = GameObject.FindGameObjectWithTag("DishesWaypoint").transform;
proCamera2D = GameObject.FindGameObjectWithTag("MainCamera").GetComponent<ProCamera2D>();
proCamera2DPan = proCamera2D.GetComponent<ProCamera2DPanAndZoom>();
proCamera2DTransition = proCamera2D.GetComponent<ProCamera2DTransitionsFX>();
expandedCG = GameObject.FindGameObjectWithTag("ExpandedCG").GetComponent<Animator>();
expandedCG.gameObject.SetActive(false);
summaryController = GameObject.FindGameObjectWithTag("Summary").GetComponent<SummaryController>();
summaryController.gameObject.SetActive(false);
proCamera2DTransition.TransitionEnter();
int i = 1;
foreach (GameObject g in GameObject.FindGameObjectsWithTag("Table")) {
TableController table = g.GetComponent<TableController>();
table.tableId = i;
i++;
tables.Add(table);
}
Debug.Log("TODO: Move this to a ready-set-go");
StartTimer();
}
TalentController GetSelectedEmployee() {
GameObject employee = GameObject.FindGameObjectWithTag(((Employee)selectedTab).ToString());
if (employee != null) {
return employee.GetComponent<TalentController>();
}
return null;
}
public void GainExp(Employee e, int amount) {
talentState[(int)e].exp += amount;
}
public void GainTips(Employee e, int amount) {
moneyEarned += amount;
talentState[(int)e].tips += amount;
}
public void GainMoney(int amount) {
moneyEarned += amount;
}
// Attempt to select the [tabIndex]'th Talent.
public void HandleSelect(int tabIndex) {
if (selectedTab == tabIndex) {
// Deselect tab
Debug.Log("Attempting to de-select tab " + tabIndex.ToString());
talentList.setActiveTab(-1);
selectedTab = -1;
audioController.sound.PlayOneShot(
audioController.talentTabClose);
// Return pan to the player.
proCamera2D.RemoveAllCameraTargets();
proCamera2DPan.enabled = true;
} else {
// Select tab
Debug.Log("Attempting to select tab " + tabIndex.ToString());
talentList.setActiveTab(tabIndex);
selectedTab = tabIndex;
audioController.sound.PlayOneShot(
audioController.talentTabOpen);
// Switch target to the newly selected employee if in target mode.
if (proCamera2DPan.enabled == false) {
HandleTargetSelection();
}
}
}
void HandleShowCG() {
if (expandedCG.isActiveAndEnabled) {
talentList.gameObject.SetActive(true);
expandedCG.gameObject.SetActive(false);
Debug.Log("TODO: Stop loop sound for animation");
} else if (selectedTab != -1) {
talentList.gameObject.SetActive(false);
expandedCG.gameObject.SetActive(true);
Debug.Log("TODO: Set animator float for CG of " + ((Employee)selectedTab).ToString());
Debug.Log("TODO: Play loop sound for animation");
}
}
void HandleTargetSelection() {
if (!proCamera2DPan.enabled) {
// Turn off targeting.
proCamera2D.RemoveAllCameraTargets();
proCamera2DPan.enabled = true;
} else if (selectedTab != -1) {
TalentController talent = GetSelectedEmployee();
if (talent != null) {
talent.OnTarget();
// Targeting takes pan away from the player.
proCamera2DPan.enabled = false;
proCamera2D.RemoveAllCameraTargets();
proCamera2D.AddCameraTarget(talent.transform, 1, 1, 1);
}
}
}
// If an employee is selected, have them tend to the table.
public void HandleTableClick(TableController table) {
if (selectedTab != -1 &&
table.waypoint != null) {
// The target employee's name should be the object tag associated with their selection index.
// Elaine = 0, Irida = 1, Clem = 2, Schroder = 3.
TalentController talent = GetSelectedEmployee();
if (talent != null) {
Debug.Log("Queueing " + ((Employee)selectedTab).ToString() + " to a table.");
talent.QueueDestination(table.waypoint, AssignmentType.Table, table);
}
}
}
// If an employee is selected, have them visit this order waypoint.
public void HandleOrderClick(OrderPlacementController order) {
if (selectedTab != -1 &&
order.waypoint != null) {
// The target employee's name should be the object tag associated with their selection index.
// Elaine = 0, Irida = 1, Clem = 2, Schroder = 3.
TalentController talent = GetSelectedEmployee();
if (talent != null) {
Debug.Log("Queueing " + ((Employee)selectedTab).ToString() + " to pick up an order.");
talent.QueueDestination(order.waypoint, AssignmentType.Order, null, order);
}
}
}
private IEnumerator FinishCooking(Order o, float time) {
yield return new WaitForSeconds(time);
bool orderAccepted = false;
foreach (OrderPlacementController placement in orderPlacements) {
if (placement.order == null) {
placement.TakeOrder(o);
orderAccepted = true;
break;
}
}
if (!orderAccepted) {
orderBacklog.Enqueue(o);
}
}
// Starts coroutines to cook a list of orders.
public void Cook(List<Order> orders) {
foreach (Order o in orders) {
Debug.Log("TODO: Cook time based on difficulty");
StartCoroutine(FinishCooking(o, Random.Range(1.0f, 5.0f)));
}
}
// Returns true iff an open table with sufficient capacity is available for seating.
public bool ValidateParty(Party p) {
foreach (TableController t in tables) {
if (t.chairs.Count >= p.patrons.Count && t.party == null) {
return true;
}
}
return false;
}
// Check if the front desk is already occupied.
// If not, attempt to assign the selected talent to the front desk.
void HandleFrontDeskClick() {
if (selectedTab != -1) {
TalentController talent = GetSelectedEmployee();
if (talent != null) {
Debug.Log("Queueing " + ((Employee)selectedTab).ToString() + " to the front desk.");
talent.QueueDestination(frontDesk, AssignmentType.FrontDesk);
}
}
}
// Attempt to assign the selected talent to the bar.
void HandleBarClick() {
if (selectedTab != -1) {
TalentController talent = GetSelectedEmployee();
if (talent != null) {
Debug.Log("Queueing " + ((Employee)selectedTab).ToString() + " to the bar.");
talent.QueueDestination(bar, AssignmentType.Bar);
}
}
}
// Attempt to assign the selected talent to the bar.
void HandleDishesClick() {
if (selectedTab != -1) {
TalentController talent = GetSelectedEmployee();
if (talent != null) {
Debug.Log("Queueing " + ((Employee)selectedTab).ToString() + " to the dishes.");
talent.QueueDestination(dishes, AssignmentType.Dishes);
}
}
}
// Turn a time tick into XX:YY PM/AM.
// Starting time is set by openingHour and each tick is 15 minutes.
// So tick 5 with openingHour 6 is 7:15 PM.
private string BuildTimeString(int time) {
int minute = (time % 4) * 15;
int hour = (time / 4 + openingHour) % 12;
if (hour == 0) hour = 12;
return hour.ToString() + ":"
+ minute.ToString().PadLeft(2, '0')
+ ((hour < openingHour || hour == 12) ? " AM" : " PM");
}
private void LateUpdate() {
text_CurrentTime.SetText(BuildTimeString(currentTime));
text_CurrentMoney.SetText("$" + moneyEarned.ToString());
text_CurrentPatrons.SetText(patrons.ToString());
}
// Update is called once per frame
void Update() {
if (Input.GetKeyDown(KeyCode.Alpha1)) {
HandleSelect(0);
} else if (Input.GetKeyDown(KeyCode.Alpha2)) {
HandleSelect(1);
} else if (Input.GetKeyDown(KeyCode.Alpha3)) {
HandleSelect(2);
} else if (Input.GetKeyDown(KeyCode.Alpha4)) {
HandleSelect(3);
} else if (Input.GetKeyDown(KeyCode.Alpha5)) {
HandleSelect(4);
} else if (Input.GetKeyDown(KeyCode.Alpha6)) {
HandleSelect(5);
} else if (Input.GetKeyDown(KeyCode.E)) {
HandleShowCG();
} else if (Input.GetKeyDown(KeyCode.T)) {
HandleTargetSelection();
} else if (Input.GetKeyDown(KeyCode.F)) {
HandleFrontDeskClick();
} else if (Input.GetKeyDown(KeyCode.B)) {
HandleBarClick();
} else if (Input.GetKeyDown(KeyCode.D)) {
HandleDishesClick();
}
}
}