243 lines
7.2 KiB
C#
243 lines
7.2 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;
|
|
public GameObject ZombieDeathByDisableParticleEffect;
|
|
[SerializeField]
|
|
public List<GameObject> Needs = new List<GameObject>();
|
|
|
|
[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 = 3;
|
|
|
|
[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);
|
|
_contextBuffer.Add("The Developer is greatful to work at this office with Gottfried");
|
|
_contextBuffer.Add("The Developer excited to develope the new game");
|
|
|
|
_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 string.Empty;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Adds the given string to the context
|
|
/// </summary>
|
|
/// <param name="context"></param>
|
|
public void AddContext(string context)
|
|
{
|
|
_contextBuffer.Add(context);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Removes the given string from the context
|
|
/// </summary>
|
|
/// <param name="context"></param>
|
|
public void RemoveContext(string context)
|
|
{
|
|
if ( _contextBuffer.Contains(context) )
|
|
{
|
|
List<string> contextAsList = _contextBuffer.ToArray().ToList();
|
|
_contextBuffer.Clear();
|
|
contextAsList.Remove(context);
|
|
foreach (var c in contextAsList)
|
|
{
|
|
_contextBuffer.Add(c);
|
|
}
|
|
}
|
|
}
|
|
}
|