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 { [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 _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 _contextBuffer; public CircularBuffer ContextBuffer => _contextBuffer; public Difficulty Difficulty => _difficulty; public double NeedNotificationThreshold => _needNotificationThreshold; public Character Player => _player; /// /// Die Transform des Spielers. /// public Transform PlayerTransform => _player.transform; /// /// 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(); _contextBuffer = new CircularBuffer(_maxContextBufferSize); _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; } /// /// Returns the context stored in the contextBuffer seperated with ',' as a string /// /// public string GetContextAsString() { if (_contextBuffer.Count != 0) { string output = ""; foreach (string context in _contextBuffer) { output += context + ", "; } return output; } return null; } /// /// Adds the given string to the context /// /// public void AddContext(string context) { _contextBuffer.Add(context); } }