GameVsJam/3d Prototyp/Assets/Scripts/GameManager.cs

220 lines
6.4 KiB
C#

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using UnityEngine;
using Utility;
using Microsoft.VisualStudio.Utilities;
public partial class GameManager : MonoBehaviourSingleton<GameManager>
{
[SerializeField] private Difficulty _difficulty = Difficulty.Medium;
public GameObject NeedFullfilledParticleEffect;
[SerializeField]
private Character _player;
[SerializeField]
private double _totalGameDurationSeconds;
[SerializeField]
private double _remainingGameDurationSeconds = 0.0;
[SerializeField, ShowOnly]
private double _currentEfficiency = 0.0;
[SerializeField]
private double _generalNeedDrainScaling = 0.001;
[SerializeField]
private List<Developer> _developers = new();
[SerializeField]
private MultiFalsableBool _gameRunning = new(false);
[SerializeField, Tooltip("Der Schwellwert am dem eine Benachrichtigung für das Bedürfnis ausgelöst wird.")]
private double _needNotificationThreshold = 0.25;
[SerializeField]
private DifficultySettings _difficultySettings;
[SerializeField]
private int _maxContextBufferSize = 5;
[SerializeField]
private CircularBuffer<string> _contextBuffer;
public CircularBuffer<string> ContextBuffer => _contextBuffer;
public Difficulty Difficulty => _difficulty;
public double NeedNotificationThreshold => _needNotificationThreshold;
public Character Player => _player;
/// <summary>
/// Die Transform des Spielers.
/// </summary>
public Transform PlayerTransform => _player.transform;
/// <summary>
/// Wie weit das Spiel bereits fortgeschritten ist.
/// </summary>
public double GameProgress => 1.0 - (_remainingGameDurationSeconds / _totalGameDurationSeconds);
/// <summary>
/// Wie Effizient das Team derzeit arbeitet.
/// </summary>
public double CurrentEfficiency => _currentEfficiency;
/// <summary>
/// Wie viele Sekunden das Spiel voraussichtlich noch dauern wird, würde die Effizienz sich nicht verändern.
/// </summary>
public double ExpectedRemainingGameDuration => _remainingGameDurationSeconds / _currentEfficiency;
public bool IsGameRunning => _gameRunning.IsTrue;
private void Start()
{
StartGame();
}
/// <summary>
/// Startet ein neues Spiel.
/// </summary>
[ContextMenu("Start Game")]
private void StartGame()
{
TimeManager.Instance.Init();
_contextBuffer = new CircularBuffer<string>(_maxContextBufferSize);
_difficultySettings = _difficulty.GetSettings();
_totalGameDurationSeconds = TimeManager.Instance.CalculateActualDeveloperTime(_difficultySettings, 4);
_remainingGameDurationSeconds = _totalGameDurationSeconds;
ResumeGame();
}
/// <summary>
/// Hebt eine Pausierung auf und setzt das Spiel fort, wenn alle Pausierungen aufgehoben wurden.
/// </summary>
/// <remarks>Hinweis: Für jedes PauseGame muss ein ResumeGame aufgerufen werden.</remarks>
[ContextMenu("Resume Game")]
public void ResumeGame()
{
if (_gameRunning.MakeTruer())
{
InvokeRepeating(nameof(UpdateProgress), 0.0f, 1.0f);
}
}
/// <summary>
/// Pausiert das Spiel. Ist Stapelbar.
/// </summary>
/// <remarks>Hinweis: Für jedes PauseGame muss ein ResumeGame aufgerufen werden.</remarks>
[ContextMenu("Pause Game")]
public void PauseGame()
{
_gameRunning.MakeFalslier();
CancelInvoke(nameof(UpdateProgress));
}
void UpdateProgress()
{
UpdateEfficiency();
UpdateGameDuration();
CheckGameEndConditions();
}
private void CheckGameEndConditions()
{
if (_remainingGameDurationSeconds <= 0.0)
{
EndGame(EndGameCondition.Win_GamePublished);
}
else if (_developers.Count == 0)
{
EndGame(EndGameCondition.Lose_NoDevelopersLeft);
}
else if (TimeManager.Instance.MissedDeadline)
{
EndGame(EndGameCondition.Lose_DeadlineMissed);
}
}
private void EndGame(EndGameCondition endGameCondition)
{
if (endGameCondition.IsWin())
{
Debug.Log("You won!");
}
else if (endGameCondition.IsLose())
{
Debug.Log("You lost!");
}
Debug.Log(endGameCondition.GetEndGameMessage());
PauseGame();
}
void UpdateEfficiency()
{
double developerEfficiency = 0.0f;
// TODO: Und eine weitere absolut nicht handle-bare variable...
double caffeineDrain = _generalNeedDrainScaling * Math.Pow(2, _difficultySettings.CaffeineDrainScaling * GameProgress);
double hungerDrain = _generalNeedDrainScaling * Math.Pow(2, _difficultySettings.HungerDrainScaling * GameProgress);
double urinationDrain = _generalNeedDrainScaling * Math.Pow(2, _difficultySettings.UrinationDrainScaling * GameProgress);
double happinessDrain = _generalNeedDrainScaling * Math.Pow(2, _difficultySettings.HappinessDrainScaling * GameProgress);
foreach (Developer developer in _developers)
{
developer.UpdateStats(caffeineDrain, hungerDrain, urinationDrain, happinessDrain);
developer.UpdateEfficiency();
developerEfficiency += developer.CurrentEfficiency;
}
_currentEfficiency = developerEfficiency;
}
void UpdateGameDuration()
{
// Entwickler Effizienz ist im Grunde wie viele Entwicklersekunden wir pro Sekunde verrichten können.
_remainingGameDurationSeconds -= _currentEfficiency;
}
/// <summary>
/// Returns the context stored in the contextBuffer seperated with ',' as a string
/// </summary>
/// <returns></returns>
public string GetContextAsString()
{
if (_contextBuffer.Count != 0)
{
string output = "";
foreach (string context in _contextBuffer)
{
output += context + ", ";
}
return output;
}
return null;
}
/// <summary>
/// Adds the given string to the context
/// </summary>
/// <param name="context"></param>
public void AddContext(string context)
{
_contextBuffer.Add(context);
}
}