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 DeveloperStats _baseStats = DeveloperStats.Default; [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; /// /// Gibt die Grunddaten des Entwicklers zurück. /// public DeveloperStats BaseStats => _baseStats; /// /// Gibt die Anzahl der Finger zurück. /// public int FingersLeft => _fingersLeft; /// /// Gibt die aktuelle Effizienz des Entwicklers in Prozent zurück. /// public double CurrentEfficiency => _currentEfficiency; public string Name => _name; [SerializeField] private GameObject _caffeineNeed; [SerializeField] private GameObject _hungerNeed; [SerializeField] private GameObject _toiletNeed; void Start() { _developerNeeds = gameObject.GetComponent(); _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); } /// /// Der Entwickler wird verletzt und der Idiot bricht sich ausgerechnet einen Finger... /// public void Hurt() { _fingersLeft--; // Ob er stirbt oder nicht, für uns hat er auf jeden Fall seinen Nutzen verloren. if (_fingersLeft == 0) Die(); } private void Die() { Debug.Log($"{Name} ist verreckt."); } }