using System; using System.Collections; using System.Collections.Generic; using System.Linq; using UnityEditor; using UnityEngine; using Utility; public partial class GameManager : MonoBehaviourSingleton { [SerializeField] private Difficulty _difficulty = Difficulty.Medium; public GameObject NeedFullfilledParticleEffect; [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 _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; public Difficulty Difficulty => _difficulty; public double NeedNotificationThreshold => _needNotificationThreshold; /// /// Wie weit das Spiel bereits fortgeschritten ist. /// public double GameProgress => 1.0 - (_remainingGameDurationSeconds / _totalGameDurationSeconds); /// /// Wie Effizient das Team derzeit arbeitet. /// public double CurrentEfficiency => _currentEfficiency; /// /// Wie viele Sekunden das Spiel voraussichtlich noch dauern wird, würde die Effizienz sich nicht verändern. /// public double ExpectedRemainingGameDuration => _remainingGameDurationSeconds / _currentEfficiency; public bool IsGameRunning => _gameRunning.IsTrue; private void Start() { StartGame(); } /// /// Startet ein neues Spiel. /// [ContextMenu("Start Game")] private void StartGame() { TimeManager.Instance.Init(); _difficultySettings = _difficulty.GetSettings(); _totalGameDurationSeconds = TimeManager.Instance.CalculateActualDeveloperTime(_difficultySettings, 4); _remainingGameDurationSeconds = _totalGameDurationSeconds; ResumeGame(); } /// /// Hebt eine Pausierung auf und setzt das Spiel fort, wenn alle Pausierungen aufgehoben wurden. /// /// Hinweis: Für jedes PauseGame muss ein ResumeGame aufgerufen werden. [ContextMenu("Resume Game")] public void ResumeGame() { if (_gameRunning.MakeTruer()) { InvokeRepeating(nameof(UpdateProgress), 0.0f, 1.0f); } } /// /// Pausiert das Spiel. Ist Stapelbar. /// /// Hinweis: Für jedes PauseGame muss ein ResumeGame aufgerufen werden. [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; } }