using Content.Shared.Alert; using Content.Shared.Damage; using Content.Shared.Nutrition.EntitySystems; using Robust.Shared.GameStates; using Robust.Shared.Serialization; using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom; using Robust.Shared.Serialization.TypeSerializers.Implementations.Generic; namespace Content.Shared.Nutrition.Components; [RegisterComponent, NetworkedComponent, Access(typeof(HungerSystem))] public sealed class HungerComponent : Component { /// /// The current hunger amount of the entity /// [DataField("currentHunger"), ViewVariables(VVAccess.ReadWrite)] public float CurrentHunger; /// /// The base amount at which decays. /// [DataField("baseDecayRate"), ViewVariables(VVAccess.ReadWrite)] public float BaseDecayRate = 0.01666666666f; /// /// The actual amount at which decays. /// Affected by /// [DataField("actualDecayRate"), ViewVariables(VVAccess.ReadWrite)] public float ActualDecayRate; /// /// The last threshold this entity was at. /// Stored in order to prevent recalculating /// [DataField("lastThreshold"), ViewVariables(VVAccess.ReadWrite)] public HungerThreshold LastThreshold; /// /// The current hunger threshold the entity is at /// [DataField("currentThreshold"), ViewVariables(VVAccess.ReadWrite)] public HungerThreshold CurrentThreshold; /// /// A dictionary relating HungerThreshold to the amount of needed for each one /// [DataField("thresholds", customTypeSerializer: typeof(DictionarySerializer))] public Dictionary Thresholds = new() { { HungerThreshold.Overfed, 200.0f }, { HungerThreshold.Okay, 150.0f }, { HungerThreshold.Peckish, 100.0f }, { HungerThreshold.Starving, 50.0f }, { HungerThreshold.Dead, 0.0f } }; /// /// A dictionary relating hunger thresholds to corresponding alerts. /// [DataField("hungerThresholdAlerts", customTypeSerializer: typeof(DictionarySerializer))] public Dictionary HungerThresholdAlerts = new() { { HungerThreshold.Peckish, AlertType.Peckish }, { HungerThreshold.Starving, AlertType.Starving }, { HungerThreshold.Dead, AlertType.Starving } }; /// /// A dictionary relating HungerThreshold to how much they modify . /// [DataField("hungerThresholdDecayModifiers", customTypeSerializer: typeof(DictionarySerializer))] public Dictionary HungerThresholdDecayModifiers = new() { { HungerThreshold.Overfed, 1.2f }, { HungerThreshold.Okay, 1f }, { HungerThreshold.Peckish, 0.8f }, { HungerThreshold.Starving, 0.6f }, { HungerThreshold.Dead, 0.6f } }; /// /// The amount of slowdown applied when an entity is starving /// [DataField("starvingSlowdownModifier"), ViewVariables(VVAccess.ReadWrite)] public float StarvingSlowdownModifier = 0.75f; /// /// Damage dealt when your current threshold is at HungerThreshold.Dead /// [DataField("starvationDamage")] public DamageSpecifier? StarvationDamage; /// /// The time when the hunger will update next. /// [DataField("nextUpdateTime", customTypeSerializer: typeof(TimeOffsetSerializer)), ViewVariables(VVAccess.ReadWrite)] public TimeSpan NextUpdateTime; /// /// The time between each update. /// [ViewVariables(VVAccess.ReadWrite)] public TimeSpan UpdateRate = TimeSpan.FromSeconds(1); } [Serializable, NetSerializable] public sealed class HungerComponentState : ComponentState { public float CurrentHunger; public float BaseDecayRate; public float ActualDecayRate; public HungerThreshold LastHungerThreshold; public HungerThreshold CurrentThreshold; public float StarvingSlowdownModifier; public TimeSpan NextUpdateTime; public HungerComponentState(float currentHunger, float baseDecayRate, float actualDecayRate, HungerThreshold lastHungerThreshold, HungerThreshold currentThreshold, float starvingSlowdownModifier, TimeSpan nextUpdateTime) { CurrentHunger = currentHunger; BaseDecayRate = baseDecayRate; ActualDecayRate = actualDecayRate; LastHungerThreshold = lastHungerThreshold; CurrentThreshold = currentThreshold; StarvingSlowdownModifier = starvingSlowdownModifier; NextUpdateTime = nextUpdateTime; } } [Serializable, NetSerializable] public enum HungerThreshold : byte { Overfed = 1 << 3, Okay = 1 << 2, Peckish = 1 << 1, Starving = 1 << 0, Dead = 0, }