Entwickler haben also Bedürfnisse?
This commit is contained in:
@ -1,26 +1,70 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Serialization;
|
||||
using Utility;
|
||||
|
||||
[Serializable]
|
||||
public struct DeveloperStats
|
||||
{
|
||||
public double BaseEfficiency;
|
||||
public int Fingers;
|
||||
|
||||
public double CaffeineDrainFactor;
|
||||
public double HungerDrainFactor;
|
||||
[FormerlySerializedAs("UrgeToUrinateFillFactor")] public double UrinationDrainFactor;
|
||||
|
||||
public DeveloperStats(double baseEfficiency, int fingers, double caffeineDrainFactor, double hungerDrainFactor, double urinationDrainFactor)
|
||||
{
|
||||
BaseEfficiency = baseEfficiency;
|
||||
Fingers = fingers;
|
||||
CaffeineDrainFactor = caffeineDrainFactor;
|
||||
HungerDrainFactor = hungerDrainFactor;
|
||||
UrinationDrainFactor = urinationDrainFactor;
|
||||
}
|
||||
|
||||
public static readonly DeveloperStats Default = new DeveloperStats(1.0, 10, 1, 1, 1);
|
||||
}
|
||||
|
||||
public class Developer : MonoBehaviour
|
||||
{
|
||||
private string _name;
|
||||
|
||||
[SerializeField]
|
||||
private double _baseEfficiency = 1.0;
|
||||
private DeveloperStats _baseStats = DeveloperStats.Default;
|
||||
|
||||
[SerializeField, ShowOnly]
|
||||
private double _currentCurrentEfficiency = 1.0;
|
||||
[FormerlySerializedAs("_currentCurrentEfficiency")] [SerializeField, ShowOnly]
|
||||
private double _currentEfficiency = 1.0;
|
||||
|
||||
[SerializeField]
|
||||
private int _fingersLeft = 10;
|
||||
|
||||
[SerializeField]
|
||||
private double _caffeineLevel = 1.0;
|
||||
|
||||
[SerializeField]
|
||||
private double _hungerLevel = 1.0;
|
||||
|
||||
[FormerlySerializedAs("_urgeToUrinateLevel")] [SerializeField]
|
||||
private double _urinationDrain = 1.0;
|
||||
|
||||
[SerializeField, ShowOnly]
|
||||
private bool _isSleeping = false;
|
||||
|
||||
[SerializeField, ShowOnly]
|
||||
private bool _isHyperactive = false;
|
||||
|
||||
[SerializeField, ShowOnly]
|
||||
private bool _isOvercaffeinated = false;
|
||||
|
||||
[SerializeField]
|
||||
private DeveloperNeeds _developerNeeds;
|
||||
|
||||
/// <summary>
|
||||
/// Gibt die Grundeffizienz des Entwicklers zurück.
|
||||
/// Gibt die Grunddaten des Entwicklers zurück.
|
||||
/// </summary>
|
||||
public double BaseEfficiency => _baseEfficiency;
|
||||
public DeveloperStats BaseStats => _baseStats;
|
||||
|
||||
/// <summary>
|
||||
/// Gibt die Anzahl der Finger zurück.
|
||||
@ -30,15 +74,153 @@ public class Developer : MonoBehaviour
|
||||
/// <summary>
|
||||
/// Gibt die aktuelle Effizienz des Entwicklers in Prozent zurück.
|
||||
/// </summary>
|
||||
public double CurrentEfficiency => _currentCurrentEfficiency;
|
||||
public double CurrentEfficiency => _currentEfficiency;
|
||||
|
||||
public string Name => _name;
|
||||
|
||||
public void UpdateEfficiency()
|
||||
|
||||
[SerializeField]
|
||||
private GameObject _caffeineNeed;
|
||||
[SerializeField]
|
||||
private GameObject _hungerNeed;
|
||||
[SerializeField]
|
||||
private GameObject _toiletNeed;
|
||||
|
||||
void Start()
|
||||
{
|
||||
_currentCurrentEfficiency = _baseEfficiency * (_fingersLeft / 10.0);
|
||||
_developerNeeds = gameObject.GetComponent<DeveloperNeeds>();
|
||||
|
||||
_fingersLeft = _baseStats.Fingers;
|
||||
}
|
||||
|
||||
[ContextMenu("Give Drink")]
|
||||
private void TestDrink()
|
||||
{
|
||||
GiveDrink(0.25);
|
||||
}
|
||||
|
||||
[ContextMenu("Give Food")]
|
||||
private void TestFood()
|
||||
{
|
||||
GiveFood(0.25);
|
||||
}
|
||||
|
||||
[ContextMenu("Drain Bladder")]
|
||||
private void TestPee()
|
||||
{
|
||||
Pee(0.25);
|
||||
}
|
||||
|
||||
public void GiveDrink(double caffeineAmount)
|
||||
{
|
||||
_caffeineLevel += caffeineAmount;
|
||||
|
||||
if (_caffeineNeed != null && _caffeineLevel > GameManager.Instance.NeedNotificationThreshold)
|
||||
{
|
||||
NeedFullfilled(_caffeineNeed);
|
||||
}
|
||||
}
|
||||
|
||||
public void GiveFood(double foodAmount)
|
||||
{
|
||||
_hungerLevel += foodAmount;
|
||||
|
||||
if (_hungerNeed != null && _hungerLevel > GameManager.Instance.NeedNotificationThreshold)
|
||||
{
|
||||
NeedFullfilled(_hungerNeed);
|
||||
}
|
||||
}
|
||||
|
||||
public void Pee(double peeAmount)
|
||||
{
|
||||
_urinationDrain += peeAmount;
|
||||
|
||||
if (_toiletNeed != null && _urinationDrain > GameManager.Instance.NeedNotificationThreshold)
|
||||
{
|
||||
NeedFullfilled(_toiletNeed);
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdateStats(double caffeineDrain, double hungerDrain, double urinationDrain)
|
||||
{
|
||||
_caffeineLevel -= caffeineDrain * _baseStats.CaffeineDrainFactor;
|
||||
_hungerLevel -= hungerDrain * _baseStats.HungerDrainFactor;
|
||||
_urinationDrain -= urinationDrain * _baseStats.UrinationDrainFactor;
|
||||
|
||||
_caffeineLevel = Math.Clamp(_caffeineLevel, 0.0, 2.0);
|
||||
_hungerLevel = Math.Clamp(_hungerLevel, 0.0, 1.0);
|
||||
_urinationDrain = Math.Clamp(_urinationDrain, 0.0, 1.0);
|
||||
|
||||
_isHyperactive = _caffeineLevel > 1.0;
|
||||
_isOvercaffeinated = _caffeineLevel > 1.5;
|
||||
_isSleeping = _caffeineLevel <= 0.0;
|
||||
|
||||
if (_caffeineLevel < GameManager.Instance.NeedNotificationThreshold && _caffeineNeed == null)
|
||||
{
|
||||
_caffeineNeed = _developerNeeds.SpawnCaffeineNeed();
|
||||
}
|
||||
|
||||
if (_hungerLevel < GameManager.Instance.NeedNotificationThreshold && _hungerNeed == null)
|
||||
{
|
||||
_hungerNeed = _developerNeeds.SpawnHungerNeed();
|
||||
}
|
||||
|
||||
if (_urinationDrain < GameManager.Instance.NeedNotificationThreshold && _toiletNeed == null)
|
||||
{
|
||||
// TODO: Go to toilet
|
||||
|
||||
Debug.Log("Ich muss aufs Klo!");
|
||||
|
||||
_toiletNeed = _developerNeeds.SpawnToiletNeed();
|
||||
}
|
||||
|
||||
if (_hungerLevel <= 0.0)
|
||||
{
|
||||
Die();
|
||||
}
|
||||
}
|
||||
|
||||
private void NeedFullfilled(GameObject needObject)
|
||||
{
|
||||
Instantiate(GameManager.Instance.NeedFullfilledParticleEffect, needObject.transform.position, needObject.transform.rotation);
|
||||
Destroy(needObject);
|
||||
}
|
||||
|
||||
public void UpdateEfficiency()
|
||||
{
|
||||
_currentEfficiency = _baseStats.BaseEfficiency * (_fingersLeft / 10.0) * CalculateCaffeineEfficiency() * CalculateHungerEfficiency() * CalculateUrinationEfficiency();
|
||||
}
|
||||
|
||||
// TODO: Es könnte sich als schwierig erweisen, die Effizienz hoch zu halten.
|
||||
// Man könnte ggf. die Funktionen so anpassen, dass sie eine ganze Weile 100% Effizienz geben.
|
||||
|
||||
private double CalculateCaffeineEfficiency()
|
||||
{
|
||||
if (_isSleeping)
|
||||
return 0.0;
|
||||
|
||||
// Die Formel hat schon recht vielversprechendes Verhalten im Bereich > 1
|
||||
//if (_isHyperactive)
|
||||
// return 1.0 + (_caffeineLevel - 1.0) * (_caffeineLevel - 1.0);
|
||||
|
||||
if (_isOvercaffeinated)
|
||||
return 0.0;
|
||||
|
||||
// https://easings.net/#easeOutCubic
|
||||
return 1.0 - Math.Pow(1.0 - _caffeineLevel, 3.0);
|
||||
}
|
||||
|
||||
private double CalculateHungerEfficiency()
|
||||
{
|
||||
// https://easings.net/#easeOutCirc
|
||||
return Math.Sqrt(1.0 - Math.Pow(_caffeineLevel - 1.0, 2.0));
|
||||
}
|
||||
|
||||
private double CalculateUrinationEfficiency()
|
||||
{
|
||||
// https://easings.net/#easeOutExpo
|
||||
return Math.Abs(_urinationDrain - 1.0) < 0.0001f ? 1.0 : 1.0 - Math.Pow(2, -10 * _urinationDrain);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Der Entwickler wird verletzt und der Idiot bricht sich ausgerechnet einen Finger...
|
||||
/// </summary>
|
||||
|
||||
@ -22,6 +22,14 @@ public class DeveloperNeeds : MonoBehaviour
|
||||
|
||||
}
|
||||
|
||||
// TODO: Enums statt strings verwenden
|
||||
// TODO: Multiple Needs möglich übereinander anzeigen?
|
||||
|
||||
public GameObject SpawnCaffeineNeed() => spawnNeed(Random.Range(0.0f, 1.0f) < 0.5f ? "coffee" : "mate");
|
||||
public GameObject SpawnToiletNeed() => spawnNeed("toilet");
|
||||
public GameObject SpawnHungerNeed() => spawnNeed("hunger");
|
||||
public GameObject SpawnMoneyNeed() => spawnNeed("money");
|
||||
|
||||
public GameObject spawnNeed(string needName)
|
||||
{
|
||||
|
||||
@ -47,6 +55,7 @@ public class DeveloperNeeds : MonoBehaviour
|
||||
context = "The NPC wants a raise, The NPC needs more money";
|
||||
break;
|
||||
default:
|
||||
Debug.LogError($"Unbekannter need \"{needName}\"");
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
@ -7,7 +8,9 @@ using Utility;
|
||||
|
||||
public partial class GameManager : MonoBehaviourSingleton<GameManager>
|
||||
{
|
||||
[SerializeField] private Difficulty _difficulty = Difficulty.Medium;
|
||||
[SerializeField] private Difficulty _difficulty = Difficulty.Medium;
|
||||
|
||||
public GameObject NeedFullfilledParticleEffect;
|
||||
|
||||
[SerializeField]
|
||||
private double _totalGameDurationSeconds;
|
||||
@ -18,14 +21,25 @@ public partial class GameManager : MonoBehaviourSingleton<GameManager>
|
||||
[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;
|
||||
|
||||
public Difficulty Difficulty => _difficulty;
|
||||
|
||||
public double NeedNotificationThreshold => _needNotificationThreshold;
|
||||
|
||||
/// <summary>
|
||||
/// Wie weit das Spiel bereits fortgeschritten ist.
|
||||
/// </summary>
|
||||
@ -57,7 +71,9 @@ public partial class GameManager : MonoBehaviourSingleton<GameManager>
|
||||
{
|
||||
TimeManager.Instance.Init();
|
||||
|
||||
_totalGameDurationSeconds = TimeManager.Instance.CalculateActualDeveloperTime(_difficulty, 4);
|
||||
_difficultySettings = _difficulty.GetSettings();
|
||||
|
||||
_totalGameDurationSeconds = TimeManager.Instance.CalculateActualDeveloperTime(_difficultySettings, 4);
|
||||
|
||||
_remainingGameDurationSeconds = _totalGameDurationSeconds;
|
||||
|
||||
@ -131,8 +147,13 @@ public partial class GameManager : MonoBehaviourSingleton<GameManager>
|
||||
{
|
||||
double developerEfficiency = 0.0f;
|
||||
|
||||
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);
|
||||
|
||||
foreach (Developer developer in _developers)
|
||||
{
|
||||
developer.UpdateStats(caffeineDrain, hungerDrain, urinationDrain);
|
||||
developer.UpdateEfficiency();
|
||||
developerEfficiency += developer.CurrentEfficiency;
|
||||
}
|
||||
|
||||
@ -155,6 +155,7 @@ public class NPC_Behavior : MonoBehaviour
|
||||
/// Deletes the current need and its gameobject.
|
||||
/// </summary>
|
||||
/// <returns>bool: wether successfully deleted the gameobject or not</returns>
|
||||
[ContextMenu("Fullfill Need")]
|
||||
public bool NeedFullfilled()
|
||||
{
|
||||
Destroy(_currentNeed);
|
||||
|
||||
@ -54,11 +54,9 @@ public class TimeManager : MonoBehaviourSingleton<TimeManager>
|
||||
/// <summary>
|
||||
/// Berechnet die (real life) Sekunden, die die Entwickler bei 100% Effizienz benötigen um das Spiel bei gegebener Schwierigkeit zu entwickeln.
|
||||
/// </summary>
|
||||
public double CalculateActualDeveloperTime(Difficulty difficulty, int developerCount)
|
||||
public double CalculateActualDeveloperTime(DifficultySettings difficultySettings, int developerCount)
|
||||
{
|
||||
DifficultySettings settings = difficulty.GetSettings();
|
||||
|
||||
return (_daysUntilRelease * _secondsPerDay * developerCount) / settings.DaysUntilReleaseFactor;
|
||||
return (_daysUntilRelease * _secondsPerDay * developerCount) / difficultySettings.DaysUntilReleaseFactor;
|
||||
}
|
||||
|
||||
void Update()
|
||||
|
||||
@ -9,6 +9,7 @@ namespace Utility
|
||||
Hard
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public abstract class DifficultySettings
|
||||
{
|
||||
public Difficulty Difficulty { get; protected set; }
|
||||
@ -17,6 +18,10 @@ namespace Utility
|
||||
/// Faktor, wie viel mehr Zeit man halt als die Entwickler bei 100% effizienz benötigen.
|
||||
/// </summary>
|
||||
public double DaysUntilReleaseFactor { get; protected set; }
|
||||
|
||||
public double CaffeineDrainScaling { get; protected set; }
|
||||
public double HungerDrainScaling { get; protected set; }
|
||||
public double UrinationDrainScaling { get; protected set; }
|
||||
}
|
||||
|
||||
public class EasyDifficulty : DifficultySettings
|
||||
@ -34,6 +39,9 @@ namespace Utility
|
||||
{
|
||||
Difficulty = Difficulty.Medium;
|
||||
DaysUntilReleaseFactor = 1.5;
|
||||
CaffeineDrainScaling = 1.5;
|
||||
HungerDrainScaling = 1.5;
|
||||
UrinationDrainScaling = 1.5;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user