Happiness is not a destination, it's a way of life ☀️
This commit is contained in:
parent
3f907d13b9
commit
adac70b9a5
|
@ -4,6 +4,7 @@ using System.Collections.Generic;
|
|||
using UnityEngine;
|
||||
using UnityEngine.Serialization;
|
||||
using Utility;
|
||||
using Random = UnityEngine.Random;
|
||||
|
||||
[Serializable]
|
||||
public struct DeveloperStats
|
||||
|
@ -13,18 +14,26 @@ public struct DeveloperStats
|
|||
|
||||
public double CaffeineDrainFactor;
|
||||
public double HungerDrainFactor;
|
||||
[FormerlySerializedAs("UrgeToUrinateFillFactor")] public double UrinationDrainFactor;
|
||||
public double UrinationDrainFactor;
|
||||
public double HappinessDrainFactor;
|
||||
|
||||
public DeveloperStats(double baseEfficiency, int fingers, double caffeineDrainFactor, double hungerDrainFactor, double urinationDrainFactor)
|
||||
// TODO: Not yet used
|
||||
public double CoffeePreference;
|
||||
public double MatePreference;
|
||||
|
||||
public DeveloperStats(double baseEfficiency, int fingers, double caffeineDrainFactor, double hungerDrainFactor, double urinationDrainFactor, double happinessDrainFactor, double coffeePreference, double matePreference)
|
||||
{
|
||||
BaseEfficiency = baseEfficiency;
|
||||
Fingers = fingers;
|
||||
CaffeineDrainFactor = caffeineDrainFactor;
|
||||
HungerDrainFactor = hungerDrainFactor;
|
||||
UrinationDrainFactor = urinationDrainFactor;
|
||||
HappinessDrainFactor = happinessDrainFactor;
|
||||
CoffeePreference = coffeePreference;
|
||||
MatePreference = matePreference;
|
||||
}
|
||||
|
||||
public static readonly DeveloperStats Default = new DeveloperStats(1.0, 10, 1, 1, 1);
|
||||
public static readonly DeveloperStats Default = new DeveloperStats(1.0, 10, 1, 1, 1, 1, 0.5, 0.5);
|
||||
}
|
||||
|
||||
public class Developer : MonoBehaviour
|
||||
|
@ -49,6 +58,9 @@ public class Developer : MonoBehaviour
|
|||
[SerializeField]
|
||||
private double _urgeToUrinateLevel = 1.0;
|
||||
|
||||
[SerializeField]
|
||||
private double _happiness = 0.75;
|
||||
|
||||
[SerializeField, ShowOnly]
|
||||
private bool _isSleeping = false;
|
||||
|
||||
|
@ -78,10 +90,27 @@ public class Developer : MonoBehaviour
|
|||
|
||||
public string Name => _name;
|
||||
|
||||
[Serializable, Flags]
|
||||
public enum WantedConsumable
|
||||
{
|
||||
None,
|
||||
Food = 0x01,
|
||||
Drink = 0x02,
|
||||
Coffee = Drink | 0x04,
|
||||
Mate = Drink | 0x08,
|
||||
Pizza = Food | 0x10
|
||||
}
|
||||
|
||||
[SerializeField]
|
||||
private GameObject _caffeineNeed;
|
||||
|
||||
[SerializeField] private WantedConsumable _wantedDrink;
|
||||
|
||||
[SerializeField]
|
||||
private GameObject _hungerNeed;
|
||||
|
||||
[SerializeField] private WantedConsumable _wantedFood;
|
||||
|
||||
[SerializeField]
|
||||
private GameObject _toiletNeed;
|
||||
|
||||
|
@ -92,63 +121,121 @@ public class Developer : MonoBehaviour
|
|||
_fingersLeft = _baseStats.Fingers;
|
||||
}
|
||||
|
||||
[ContextMenu("Give Drink")]
|
||||
private void TestDrink()
|
||||
[ContextMenu("Give Coffee")]
|
||||
private void TestCoffee()
|
||||
{
|
||||
GiveDrink(0.25);
|
||||
GiveDrink(0.3, WantedConsumable.Coffee);
|
||||
}
|
||||
|
||||
[ContextMenu("Give Mate")]
|
||||
private void TestMate()
|
||||
{
|
||||
GiveDrink(0.3, WantedConsumable.Mate);
|
||||
}
|
||||
|
||||
[ContextMenu("Give Food")]
|
||||
private void TestFood()
|
||||
{
|
||||
GiveFood(0.25);
|
||||
GiveFood(0.3, WantedConsumable.Pizza);
|
||||
}
|
||||
|
||||
[ContextMenu("Drain Bladder")]
|
||||
private void TestPee()
|
||||
{
|
||||
Pee(0.25);
|
||||
Pee(0.3, true);
|
||||
}
|
||||
|
||||
public void GiveDrink(double caffeineAmount)
|
||||
public void GiveDrink(double caffeineAmount, WantedConsumable drinkType)
|
||||
{
|
||||
_caffeineLevel += caffeineAmount;
|
||||
if (!drinkType.HasFlag(WantedConsumable.Drink))
|
||||
throw new ArgumentException(nameof(drinkType),
|
||||
$"{nameof(drinkType)} must be a value with the \"{WantedConsumable.Drink}\" flag");
|
||||
|
||||
_caffeineLevel = Math.Min(_caffeineLevel + caffeineAmount, 2.0);
|
||||
|
||||
if (_caffeineNeed != null && _caffeineLevel > GameManager.Instance.NeedNotificationThreshold)
|
||||
{
|
||||
NeedFullfilled(_caffeineNeed);
|
||||
_caffeineNeed = null;
|
||||
}
|
||||
|
||||
if (_wantedDrink != WantedConsumable.None)
|
||||
{
|
||||
// TODO: Wie wäre es damit, das nicht fest zu coden?
|
||||
if (drinkType == _wantedDrink)
|
||||
_happiness += 0.2;
|
||||
else
|
||||
_happiness -= 0.2;
|
||||
}
|
||||
else
|
||||
{
|
||||
_happiness += 0.2;
|
||||
}
|
||||
|
||||
_wantedDrink = WantedConsumable.None;
|
||||
}
|
||||
|
||||
public void GiveFood(double foodAmount)
|
||||
public void GiveFood(double foodAmount, WantedConsumable foodType)
|
||||
{
|
||||
_hungerLevel += foodAmount;
|
||||
if (!foodType.HasFlag(WantedConsumable.Food))
|
||||
throw new ArgumentException(nameof(foodType),
|
||||
$"{nameof(foodType)} must be a value with the \"{WantedConsumable.Food}\" flag");
|
||||
|
||||
_hungerLevel = Math.Min(_hungerLevel + foodAmount, 1.0);
|
||||
|
||||
if (_hungerNeed != null && _hungerLevel > GameManager.Instance.NeedNotificationThreshold)
|
||||
{
|
||||
NeedFullfilled(_hungerNeed);
|
||||
_hungerNeed = null;
|
||||
}
|
||||
|
||||
if (_wantedFood != WantedConsumable.None)
|
||||
{
|
||||
if (foodType == _wantedFood)
|
||||
_happiness += 0.2;
|
||||
else
|
||||
_happiness -= 0.2;
|
||||
}
|
||||
else
|
||||
{
|
||||
_happiness += 0.2;
|
||||
}
|
||||
|
||||
_wantedFood = WantedConsumable.None;
|
||||
}
|
||||
|
||||
public void Pee(double peeAmount)
|
||||
/// <summary>
|
||||
/// Der Entwickler Pinkelt die angegebene Menge aus.
|
||||
/// </summary>
|
||||
/// <param name="peeAmount">Die Menge die ausgepinkelt wird.</param>
|
||||
/// <param name="onToilet">Wenn true, dann pinkelt der Entwickler auf einer Toilette. Wenn false, dann pinkelt er auf den Boden (was schlecht ist)</param>
|
||||
public void Pee(double peeAmount, bool onToilet)
|
||||
{
|
||||
_urgeToUrinateLevel += peeAmount;
|
||||
_urgeToUrinateLevel = Math.Min(_urgeToUrinateLevel += peeAmount, 1.0);
|
||||
|
||||
if (_toiletNeed != null && _urgeToUrinateLevel > GameManager.Instance.NeedNotificationThreshold)
|
||||
{
|
||||
NeedFullfilled(_toiletNeed);
|
||||
_toiletNeed = null;
|
||||
}
|
||||
|
||||
if (onToilet)
|
||||
_happiness += 0.2;
|
||||
else
|
||||
_happiness -= 0.2;
|
||||
}
|
||||
|
||||
public void UpdateStats(double caffeineDrain, double hungerDrain, double urinationDrain)
|
||||
public void UpdateStats(double caffeineDrain, double hungerDrain, double urinationDrain, double happinessDrain)
|
||||
{
|
||||
_caffeineLevel -= caffeineDrain * _baseStats.CaffeineDrainFactor;
|
||||
_hungerLevel -= hungerDrain * _baseStats.HungerDrainFactor;
|
||||
_urgeToUrinateLevel -= urinationDrain * _baseStats.UrinationDrainFactor;
|
||||
_happiness -= happinessDrain * _baseStats.UrinationDrainFactor;
|
||||
|
||||
_caffeineLevel = Math.Clamp(_caffeineLevel, 0.0, 2.0);
|
||||
_hungerLevel = Math.Clamp(_hungerLevel, 0.0, 1.0);
|
||||
_urgeToUrinateLevel = Math.Clamp(_urgeToUrinateLevel, 0.0, 1.0);
|
||||
_caffeineLevel = Math.Max(_caffeineLevel, 0.0);
|
||||
_hungerLevel = Math.Max(_hungerLevel, 0.0);
|
||||
_urgeToUrinateLevel = Math.Max(_urgeToUrinateLevel, 0.0);
|
||||
_happiness = Math.Max(_happiness, 0.0);
|
||||
|
||||
_isHyperactive = _caffeineLevel > 1.0;
|
||||
_isOvercaffeinated = _caffeineLevel > 1.5;
|
||||
|
@ -156,12 +243,24 @@ public class Developer : MonoBehaviour
|
|||
|
||||
if (_caffeineLevel < GameManager.Instance.NeedNotificationThreshold && _caffeineNeed == null)
|
||||
{
|
||||
_caffeineNeed = _developerNeeds.SpawnCaffeineNeed();
|
||||
// TODO: Wir können hier anhand von Präferenz gewichten.
|
||||
|
||||
if (Random.Range(0.0f, 1.0f) > 0.5f)
|
||||
{
|
||||
_caffeineNeed = _developerNeeds.SpawnMateNeed();
|
||||
_wantedDrink = WantedConsumable.Mate;
|
||||
}
|
||||
else
|
||||
{
|
||||
_caffeineNeed = _developerNeeds.SpawnCoffeeNeed();
|
||||
_wantedDrink = WantedConsumable.Coffee;
|
||||
}
|
||||
}
|
||||
|
||||
if (_hungerLevel < GameManager.Instance.NeedNotificationThreshold && _hungerNeed == null)
|
||||
{
|
||||
_hungerNeed = _developerNeeds.SpawnHungerNeed();
|
||||
_wantedFood = WantedConsumable.Pizza;
|
||||
}
|
||||
|
||||
if (_urgeToUrinateLevel < GameManager.Instance.NeedNotificationThreshold && _toiletNeed == null)
|
||||
|
@ -187,11 +286,12 @@ public class Developer : MonoBehaviour
|
|||
|
||||
public void UpdateEfficiency()
|
||||
{
|
||||
_currentEfficiency = _baseStats.BaseEfficiency * (_fingersLeft / 10.0) * CalculateCaffeineEfficiency() * CalculateHungerEfficiency() * CalculateUrinationEfficiency();
|
||||
_currentEfficiency = _baseStats.BaseEfficiency * (_fingersLeft / 10.0) * CalculateCaffeineEfficiency() * CalculateHungerEfficiency() * CalculateUrinationEfficiency() * CalculateHappinessEfficiency();
|
||||
}
|
||||
|
||||
// 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.
|
||||
// Man könnte ggf. die Funktionen so anpassen, dass sie eine ganze Weile 100% Effizienz geben.
|
||||
// TODO: Das auch nur ansatzweise zu balancieren wird wiztig 🤯
|
||||
|
||||
private double CalculateCaffeineEfficiency()
|
||||
{
|
||||
|
@ -211,16 +311,28 @@ public class Developer : MonoBehaviour
|
|||
|
||||
private double CalculateHungerEfficiency()
|
||||
{
|
||||
if (_hungerLevel > 1.0)
|
||||
return 1.0;
|
||||
|
||||
// https://easings.net/#easeOutCirc
|
||||
return Math.Sqrt(1.0 - Math.Pow(_caffeineLevel - 1.0, 2.0));
|
||||
return Math.Sqrt(1.0 - Math.Pow(_hungerLevel - 1.0, 2.0));
|
||||
}
|
||||
|
||||
private double CalculateUrinationEfficiency()
|
||||
{
|
||||
if (_urgeToUrinateLevel > 1.0)
|
||||
return 1.0;
|
||||
|
||||
// https://easings.net/#easeOutExpo
|
||||
return Math.Abs(_urgeToUrinateLevel - 1.0) < 0.0001f ? 1.0 : 1.0 - Math.Pow(2, -10 * _urgeToUrinateLevel);
|
||||
}
|
||||
|
||||
private double CalculateHappinessEfficiency()
|
||||
{
|
||||
// 50% bei 0 Happiness, 100% bei 0.75 Happiness, 125% bei 1 Happiness
|
||||
return 0.5 + _happiness * 2.0 / 3.0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Der Entwickler wird verletzt und der Idiot bricht sich ausgerechnet einen Finger...
|
||||
/// </summary>
|
||||
|
|
|
@ -25,7 +25,8 @@ 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 SpawnCoffeeNeed() => spawnNeed("coffee");
|
||||
public GameObject SpawnMateNeed() => spawnNeed("mate");
|
||||
public GameObject SpawnToiletNeed() => spawnNeed("toilet");
|
||||
public GameObject SpawnHungerNeed() => spawnNeed("hunger");
|
||||
public GameObject SpawnMoneyNeed() => spawnNeed("money");
|
||||
|
|
|
@ -147,13 +147,15 @@ public partial class GameManager : MonoBehaviourSingleton<GameManager>
|
|||
{
|
||||
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);
|
||||
developer.UpdateStats(caffeineDrain, hungerDrain, urinationDrain, happinessDrain);
|
||||
developer.UpdateEfficiency();
|
||||
developerEfficiency += developer.CurrentEfficiency;
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@ namespace Utility
|
|||
public double CaffeineDrainScaling { get; protected set; }
|
||||
public double HungerDrainScaling { get; protected set; }
|
||||
public double UrinationDrainScaling { get; protected set; }
|
||||
public double HappinessDrainScaling { get; protected set; }
|
||||
}
|
||||
|
||||
public class EasyDifficulty : DifficultySettings
|
||||
|
@ -42,6 +43,7 @@ namespace Utility
|
|||
CaffeineDrainScaling = 1.5;
|
||||
HungerDrainScaling = 1.5;
|
||||
UrinationDrainScaling = 1.5;
|
||||
HappinessDrainScaling = 1.5;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue