Task/food hud (#19312)

* security HUD now shows a job icon on entities with a body

* thirst goggles

* set starting hud gear

* fix build

* remove from starting gear

* remove

* replace

* fix thirst and hunger icons

* update icons

* space

* space

* ]

* ]

* fix build

* fix comments

* fix

* spacing

* field

* move more namespaces

* use AutoGenerateComponentState

* comments

* fix build

* not all fields

* comments

* unpaused

* fix Dirty warning

---------

Co-authored-by: Slava0135 <super.novalskiy_0135@inbox.ru>
This commit is contained in:
PrPleGoo
2023-09-23 15:14:06 +02:00
committed by GitHub
parent dae18c981f
commit 1a13884961
19 changed files with 335 additions and 151 deletions

View File

@@ -0,0 +1,58 @@
using Content.Shared.Nutrition.Components;
using Content.Shared.Overlays;
using Content.Shared.StatusIcon;
using Content.Shared.StatusIcon.Components;
using Robust.Shared.Prototypes;
namespace Content.Client.Overlays;
public sealed class ShowHungerIconsSystem : EquipmentHudSystem<ShowHungerIconsComponent>
{
[Dependency] private readonly IPrototypeManager _prototypeMan = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<HungerComponent, GetStatusIconsEvent>(OnGetStatusIconsEvent);
}
private void OnGetStatusIconsEvent(EntityUid uid, HungerComponent hungerComponent, ref GetStatusIconsEvent args)
{
if (!IsActive || args.InContainer)
return;
var healthIcons = DecideHungerIcon(uid, hungerComponent);
args.StatusIcons.AddRange(healthIcons);
}
private IReadOnlyList<StatusIconPrototype> DecideHungerIcon(EntityUid uid, HungerComponent hungerComponent)
{
var result = new List<StatusIconPrototype>();
switch (hungerComponent.CurrentThreshold)
{
case HungerThreshold.Overfed:
if (_prototypeMan.TryIndex<StatusIconPrototype>("HungerIconOverfed", out var overfed))
{
result.Add(overfed);
}
break;
case HungerThreshold.Peckish:
if (_prototypeMan.TryIndex<StatusIconPrototype>("HungerIconPeckish", out var peckish))
{
result.Add(peckish);
}
break;
case HungerThreshold.Starving:
if (_prototypeMan.TryIndex<StatusIconPrototype>("HungerIconStarving", out var starving))
{
result.Add(starving);
}
break;
}
return result;
}
}

View File

@@ -0,0 +1,58 @@
using Content.Shared.Nutrition.Components;
using Content.Shared.Overlays;
using Content.Shared.StatusIcon;
using Content.Shared.StatusIcon.Components;
using Robust.Shared.Prototypes;
namespace Content.Client.Overlays;
public sealed class ShowThirstIconsSystem : EquipmentHudSystem<ShowThirstIconsComponent>
{
[Dependency] private readonly IPrototypeManager _prototypeMan = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<ThirstComponent, GetStatusIconsEvent>(OnGetStatusIconsEvent);
}
private void OnGetStatusIconsEvent(EntityUid uid, ThirstComponent thirstComponent, ref GetStatusIconsEvent args)
{
if (!IsActive || args.InContainer)
return;
var healthIcons = DecideThirstIcon(uid, thirstComponent);
args.StatusIcons.AddRange(healthIcons);
}
private IReadOnlyList<StatusIconPrototype> DecideThirstIcon(EntityUid uid, ThirstComponent thirstComponent)
{
var result = new List<StatusIconPrototype>();
switch (thirstComponent.CurrentThirstThreshold)
{
case ThirstThreshold.OverHydrated:
if (_prototypeMan.TryIndex<StatusIconPrototype>("ThirstIconOverhydrated", out var overhydrated))
{
result.Add(overhydrated);
}
break;
case ThirstThreshold.Thirsty:
if (_prototypeMan.TryIndex<StatusIconPrototype>("ThirstIconThirsty", out var thirsty))
{
result.Add(thirsty);
}
break;
case ThirstThreshold.Parched:
if (_prototypeMan.TryIndex<StatusIconPrototype>("ThirstIconParched", out var parched))
{
result.Add(parched);
}
break;
}
return result;
}
}

View File

@@ -1,6 +1,6 @@
using Content.Server.Nutrition.Components;
using Content.Shared.Chemistry.Reagent;
using Content.Server.Nutrition.EntitySystems; using Content.Server.Nutrition.EntitySystems;
using Content.Shared.Chemistry.Reagent;
using Content.Shared.Nutrition.Components;
using Robust.Shared.Prototypes; using Robust.Shared.Prototypes;
namespace Content.Server.Chemistry.ReagentEffects namespace Content.Server.Chemistry.ReagentEffects

View File

@@ -1,16 +1,12 @@
using Content.Server.Body.Components; using Content.Server.Body.Components;
using Content.Server.Body.Systems; using Content.Server.Body.Systems;
using Content.Server.Chemistry.EntitySystems; using Content.Server.Chemistry.EntitySystems;
using Content.Server.Fluids.Components;
using Content.Server.Fluids.EntitySystems; using Content.Server.Fluids.EntitySystems;
using Content.Server.Forensics; using Content.Server.Forensics;
using Content.Server.Nutrition.Components;
using Content.Server.Nutrition.EntitySystems; using Content.Server.Nutrition.EntitySystems;
using Content.Server.Popups; using Content.Server.Popups;
using Content.Server.Stunnable; using Content.Server.Stunnable;
using Content.Shared.Audio;
using Content.Shared.Chemistry.Components; using Content.Shared.Chemistry.Components;
using Content.Shared.Fluids.Components;
using Content.Shared.IdentityManagement; using Content.Shared.IdentityManagement;
using Content.Shared.Nutrition.Components; using Content.Shared.Nutrition.Components;
using Content.Shared.Nutrition.EntitySystems; using Content.Shared.Nutrition.EntitySystems;

View File

@@ -1,54 +0,0 @@
using Content.Shared.Alert;
namespace Content.Server.Nutrition.Components
{
[Flags]
public enum ThirstThreshold : byte
{
// Hydrohomies
Dead = 0,
Parched = 1 << 0,
Thirsty = 1 << 1,
Okay = 1 << 2,
OverHydrated = 1 << 3,
}
[RegisterComponent]
public sealed partial class ThirstComponent : Component
{
// Base stuff
[ViewVariables(VVAccess.ReadWrite)]
[DataField("baseDecayRate")]
public float BaseDecayRate = 0.1f;
[ViewVariables(VVAccess.ReadWrite)]
public float ActualDecayRate;
// Thirst
[ViewVariables(VVAccess.ReadOnly)]
public ThirstThreshold CurrentThirstThreshold;
public ThirstThreshold LastThirstThreshold;
[ViewVariables(VVAccess.ReadWrite)]
[DataField("startingThirst")]
public float CurrentThirst = -1f;
[DataField("thresholds")]
public Dictionary<ThirstThreshold, float> ThirstThresholds { get; private set; } = new()
{
{ThirstThreshold.OverHydrated, 600.0f},
{ThirstThreshold.Okay, 450.0f},
{ThirstThreshold.Thirsty, 300.0f},
{ThirstThreshold.Parched, 150.0f},
{ThirstThreshold.Dead, 0.0f},
};
public static readonly Dictionary<ThirstThreshold, AlertType> ThirstThresholdAlertTypes = new()
{
{ThirstThreshold.Thirsty, AlertType.Thirsty},
{ThirstThreshold.Parched, AlertType.Parched},
{ThirstThreshold.Dead, AlertType.Parched},
};
}
}

View File

@@ -38,6 +38,8 @@ public partial class InventorySystem
// ComponentActivatedClientSystems // ComponentActivatedClientSystems
SubscribeLocalEvent<InventoryComponent, RefreshEquipmentHudEvent<ShowSecurityIconsComponent>>(RelayInventoryEvent); SubscribeLocalEvent<InventoryComponent, RefreshEquipmentHudEvent<ShowSecurityIconsComponent>>(RelayInventoryEvent);
SubscribeLocalEvent<InventoryComponent, RefreshEquipmentHudEvent<ShowHungerIconsComponent>>(RelayInventoryEvent);
SubscribeLocalEvent<InventoryComponent, RefreshEquipmentHudEvent<ShowThirstIconsComponent>>(RelayInventoryEvent);
SubscribeLocalEvent<InventoryComponent, GetVerbsEvent<EquipmentVerb>>(OnGetStrippingVerbs); SubscribeLocalEvent<InventoryComponent, GetVerbsEvent<EquipmentVerb>>(OnGetStrippingVerbs);
} }

View File

@@ -9,12 +9,14 @@ using Robust.Shared.Serialization.TypeSerializers.Implementations.Generic;
namespace Content.Shared.Nutrition.Components; namespace Content.Shared.Nutrition.Components;
[RegisterComponent, NetworkedComponent, Access(typeof(HungerSystem))] [RegisterComponent, NetworkedComponent, Access(typeof(HungerSystem))]
[AutoGenerateComponentState]
public sealed partial class HungerComponent : Component public sealed partial class HungerComponent : Component
{ {
/// <summary> /// <summary>
/// The current hunger amount of the entity /// The current hunger amount of the entity
/// </summary> /// </summary>
[DataField("currentHunger"), ViewVariables(VVAccess.ReadWrite)] [DataField("currentHunger"), ViewVariables(VVAccess.ReadWrite)]
[AutoNetworkedField]
public float CurrentHunger; public float CurrentHunger;
/// <summary> /// <summary>
@@ -28,6 +30,7 @@ public sealed partial class HungerComponent : Component
/// Affected by <seealso cref="CurrentThreshold"/> /// Affected by <seealso cref="CurrentThreshold"/>
/// </summary> /// </summary>
[DataField("actualDecayRate"), ViewVariables(VVAccess.ReadWrite)] [DataField("actualDecayRate"), ViewVariables(VVAccess.ReadWrite)]
[AutoNetworkedField]
public float ActualDecayRate; public float ActualDecayRate;
/// <summary> /// <summary>
@@ -35,18 +38,21 @@ public sealed partial class HungerComponent : Component
/// Stored in order to prevent recalculating /// Stored in order to prevent recalculating
/// </summary> /// </summary>
[DataField("lastThreshold"), ViewVariables(VVAccess.ReadWrite)] [DataField("lastThreshold"), ViewVariables(VVAccess.ReadWrite)]
[AutoNetworkedField]
public HungerThreshold LastThreshold; public HungerThreshold LastThreshold;
/// <summary> /// <summary>
/// The current hunger threshold the entity is at /// The current hunger threshold the entity is at
/// </summary> /// </summary>
[DataField("currentThreshold"), ViewVariables(VVAccess.ReadWrite)] [DataField("currentThreshold"), ViewVariables(VVAccess.ReadWrite)]
[AutoNetworkedField]
public HungerThreshold CurrentThreshold; public HungerThreshold CurrentThreshold;
/// <summary> /// <summary>
/// A dictionary relating HungerThreshold to the amount of <see cref="CurrentHunger"/> needed for each one /// A dictionary relating HungerThreshold to the amount of <see cref="CurrentHunger"/> needed for each one
/// </summary> /// </summary>
[DataField("thresholds", customTypeSerializer: typeof(DictionarySerializer<HungerThreshold, float>))] [DataField("thresholds", customTypeSerializer: typeof(DictionarySerializer<HungerThreshold, float>))]
[AutoNetworkedField(cloneData: true)]
public Dictionary<HungerThreshold, float> Thresholds = new() public Dictionary<HungerThreshold, float> Thresholds = new()
{ {
{ HungerThreshold.Overfed, 200.0f }, { HungerThreshold.Overfed, 200.0f },
@@ -60,6 +66,7 @@ public sealed partial class HungerComponent : Component
/// A dictionary relating hunger thresholds to corresponding alerts. /// A dictionary relating hunger thresholds to corresponding alerts.
/// </summary> /// </summary>
[DataField("hungerThresholdAlerts", customTypeSerializer: typeof(DictionarySerializer<HungerThreshold, AlertType>))] [DataField("hungerThresholdAlerts", customTypeSerializer: typeof(DictionarySerializer<HungerThreshold, AlertType>))]
[AutoNetworkedField(cloneData: true)]
public Dictionary<HungerThreshold, AlertType> HungerThresholdAlerts = new() public Dictionary<HungerThreshold, AlertType> HungerThresholdAlerts = new()
{ {
{ HungerThreshold.Peckish, AlertType.Peckish }, { HungerThreshold.Peckish, AlertType.Peckish },
@@ -71,6 +78,7 @@ public sealed partial class HungerComponent : Component
/// A dictionary relating HungerThreshold to how much they modify <see cref="BaseDecayRate"/>. /// A dictionary relating HungerThreshold to how much they modify <see cref="BaseDecayRate"/>.
/// </summary> /// </summary>
[DataField("hungerThresholdDecayModifiers", customTypeSerializer: typeof(DictionarySerializer<HungerThreshold, float>))] [DataField("hungerThresholdDecayModifiers", customTypeSerializer: typeof(DictionarySerializer<HungerThreshold, float>))]
[AutoNetworkedField(cloneData: true)]
public Dictionary<HungerThreshold, float> HungerThresholdDecayModifiers = new() public Dictionary<HungerThreshold, float> HungerThresholdDecayModifiers = new()
{ {
{ HungerThreshold.Overfed, 1.2f }, { HungerThreshold.Overfed, 1.2f },
@@ -84,6 +92,7 @@ public sealed partial class HungerComponent : Component
/// The amount of slowdown applied when an entity is starving /// The amount of slowdown applied when an entity is starving
/// </summary> /// </summary>
[DataField("starvingSlowdownModifier"), ViewVariables(VVAccess.ReadWrite)] [DataField("starvingSlowdownModifier"), ViewVariables(VVAccess.ReadWrite)]
[AutoNetworkedField]
public float StarvingSlowdownModifier = 0.75f; public float StarvingSlowdownModifier = 0.75f;
/// <summary> /// <summary>
@@ -96,50 +105,17 @@ public sealed partial class HungerComponent : Component
/// The time when the hunger will update next. /// The time when the hunger will update next.
/// </summary> /// </summary>
[DataField("nextUpdateTime", customTypeSerializer: typeof(TimeOffsetSerializer)), ViewVariables(VVAccess.ReadWrite)] [DataField("nextUpdateTime", customTypeSerializer: typeof(TimeOffsetSerializer)), ViewVariables(VVAccess.ReadWrite)]
[AutoNetworkedField]
public TimeSpan NextUpdateTime; public TimeSpan NextUpdateTime;
/// <summary> /// <summary>
/// The time between each update. /// The time between each update.
/// </summary> /// </summary>
[ViewVariables(VVAccess.ReadWrite)] [ViewVariables(VVAccess.ReadWrite)]
[AutoNetworkedField]
public TimeSpan UpdateRate = TimeSpan.FromSeconds(1); 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] [Serializable, NetSerializable]
public enum HungerThreshold : byte public enum HungerThreshold : byte
{ {

View File

@@ -0,0 +1,78 @@
using Content.Server.Nutrition.EntitySystems;
using Content.Shared.Alert;
using Robust.Shared.GameStates;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;
namespace Content.Shared.Nutrition.Components;
[RegisterComponent, NetworkedComponent, Access(typeof(ThirstSystem))]
[AutoGenerateComponentState]
public sealed partial class ThirstComponent : Component
{
// Base stuff
[ViewVariables(VVAccess.ReadWrite)]
[DataField("baseDecayRate")]
[AutoNetworkedField]
public float BaseDecayRate = 0.1f;
[ViewVariables(VVAccess.ReadWrite)]
[AutoNetworkedField]
public float ActualDecayRate;
// Thirst
[ViewVariables(VVAccess.ReadOnly)]
[AutoNetworkedField]
public ThirstThreshold CurrentThirstThreshold;
[ViewVariables(VVAccess.ReadOnly)]
[AutoNetworkedField]
public ThirstThreshold LastThirstThreshold;
[ViewVariables(VVAccess.ReadWrite)]
[DataField("startingThirst")]
[AutoNetworkedField]
public float CurrentThirst = -1f;
/// <summary>
/// The time when the hunger will update next.
/// </summary>
[DataField("nextUpdateTime", customTypeSerializer: typeof(TimeOffsetSerializer)), ViewVariables(VVAccess.ReadWrite)]
[AutoNetworkedField]
public TimeSpan NextUpdateTime;
/// <summary>
/// The time between each update.
/// </summary>
[ViewVariables(VVAccess.ReadWrite)]
[AutoNetworkedField]
public TimeSpan UpdateRate = TimeSpan.FromSeconds(1);
[DataField("thresholds")]
[AutoNetworkedField(cloneData: true)]
public Dictionary<ThirstThreshold, float> ThirstThresholds = new()
{
{ThirstThreshold.OverHydrated, 600.0f},
{ThirstThreshold.Okay, 450.0f},
{ThirstThreshold.Thirsty, 300.0f},
{ThirstThreshold.Parched, 150.0f},
{ThirstThreshold.Dead, 0.0f},
};
public static readonly Dictionary<ThirstThreshold, AlertType> ThirstThresholdAlertTypes = new()
{
{ThirstThreshold.Thirsty, AlertType.Thirsty},
{ThirstThreshold.Parched, AlertType.Parched},
{ThirstThreshold.Dead, AlertType.Parched},
};
}
[Flags]
public enum ThirstThreshold : byte
{
// Hydrohomies
Dead = 0,
Parched = 1 << 0,
Thirsty = 1 << 1,
Okay = 1 << 2,
OverHydrated = 1 << 3,
}

View File

@@ -1,10 +1,9 @@
using Content.Shared.Alert; using Content.Shared.Alert;
using Content.Shared.Damage; using Content.Shared.Damage;
using Content.Shared.Mobs.Systems; using Content.Shared.Mobs.Systems;
using Content.Shared.Movement.Systems; using Content.Shared.Movement.Systems;
using Content.Shared.Nutrition.Components; using Content.Shared.Nutrition.Components;
using Content.Shared.Rejuvenate; using Content.Shared.Rejuvenate;
using Robust.Shared.GameStates;
using Robust.Shared.Random; using Robust.Shared.Random;
using Robust.Shared.Timing; using Robust.Shared.Timing;
@@ -24,8 +23,6 @@ public sealed class HungerSystem : EntitySystem
{ {
base.Initialize(); base.Initialize();
SubscribeLocalEvent<HungerComponent, ComponentGetState>(OnGetState);
SubscribeLocalEvent<HungerComponent, ComponentHandleState>(OnHandleState);
SubscribeLocalEvent<HungerComponent, EntityUnpausedEvent>(OnUnpaused); SubscribeLocalEvent<HungerComponent, EntityUnpausedEvent>(OnUnpaused);
SubscribeLocalEvent<HungerComponent, MapInitEvent>(OnMapInit); SubscribeLocalEvent<HungerComponent, MapInitEvent>(OnMapInit);
SubscribeLocalEvent<HungerComponent, ComponentShutdown>(OnShutdown); SubscribeLocalEvent<HungerComponent, ComponentShutdown>(OnShutdown);
@@ -33,30 +30,6 @@ public sealed class HungerSystem : EntitySystem
SubscribeLocalEvent<HungerComponent, RejuvenateEvent>(OnRejuvenate); SubscribeLocalEvent<HungerComponent, RejuvenateEvent>(OnRejuvenate);
} }
private void OnGetState(EntityUid uid, HungerComponent component, ref ComponentGetState args)
{
args.State = new HungerComponentState(component.CurrentHunger,
component.BaseDecayRate,
component.ActualDecayRate,
component.LastThreshold,
component.CurrentThreshold,
component.StarvingSlowdownModifier,
component.NextUpdateTime);
}
private void OnHandleState(EntityUid uid, HungerComponent component, ref ComponentHandleState args)
{
if (args.Current is not HungerComponentState state)
return;
component.CurrentHunger = state.CurrentHunger;
component.BaseDecayRate = state.BaseDecayRate;
component.ActualDecayRate = state.ActualDecayRate;
component.LastThreshold = state.LastHungerThreshold;
component.CurrentThreshold = state.CurrentThreshold;
component.StarvingSlowdownModifier = state.StarvingSlowdownModifier;
component.NextUpdateTime = state.NextUpdateTime;
}
private void OnUnpaused(EntityUid uid, HungerComponent component, ref EntityUnpausedEvent args) private void OnUnpaused(EntityUid uid, HungerComponent component, ref EntityUnpausedEvent args)
{ {
component.NextUpdateTime += args.PausedTime; component.NextUpdateTime += args.PausedTime;

View File

@@ -1,23 +1,24 @@
using Content.Server.Nutrition.Components; using Content.Shared.Alert;
using Content.Shared.Movement.Components;
using Content.Shared.Movement.Systems;
using Content.Shared.Nutrition.Components;
using Content.Shared.Rejuvenate;
using JetBrains.Annotations; using JetBrains.Annotations;
using Robust.Shared.Random; using Robust.Shared.Random;
using Content.Shared.Movement.Components; using Robust.Shared.Timing;
using Content.Shared.Alert;
using Content.Shared.Movement.Systems;
using Content.Shared.Rejuvenate;
namespace Content.Server.Nutrition.EntitySystems; namespace Content.Server.Nutrition.EntitySystems;
[UsedImplicitly] [UsedImplicitly]
public sealed class ThirstSystem : EntitySystem public sealed class ThirstSystem : EntitySystem
{ {
[Dependency] private readonly IGameTiming _timing = default!;
[Dependency] private readonly IRobustRandom _random = default!; [Dependency] private readonly IRobustRandom _random = default!;
[Dependency] private readonly AlertsSystem _alerts = default!; [Dependency] private readonly AlertsSystem _alerts = default!;
[Dependency] private readonly MovementSpeedModifierSystem _movement = default!; [Dependency] private readonly MovementSpeedModifierSystem _movement = default!;
[Dependency] private readonly SharedJetpackSystem _jetpack = default!; [Dependency] private readonly SharedJetpackSystem _jetpack = default!;
private ISawmill _sawmill = default!; private ISawmill _sawmill = default!;
private float _accumulatedFrameTime;
public override void Initialize() public override void Initialize()
{ {
@@ -28,6 +29,7 @@ public sealed class ThirstSystem : EntitySystem
SubscribeLocalEvent<ThirstComponent, RefreshMovementSpeedModifiersEvent>(OnRefreshMovespeed); SubscribeLocalEvent<ThirstComponent, RefreshMovementSpeedModifiersEvent>(OnRefreshMovespeed);
SubscribeLocalEvent<ThirstComponent, ComponentStartup>(OnComponentStartup); SubscribeLocalEvent<ThirstComponent, ComponentStartup>(OnComponentStartup);
SubscribeLocalEvent<ThirstComponent, RejuvenateEvent>(OnRejuvenate); SubscribeLocalEvent<ThirstComponent, RejuvenateEvent>(OnRejuvenate);
SubscribeLocalEvent<ThirstComponent, EntityUnpausedEvent>(OnUnpaused);
} }
private void OnComponentStartup(EntityUid uid, ThirstComponent component, ComponentStartup args) private void OnComponentStartup(EntityUid uid, ThirstComponent component, ComponentStartup args)
@@ -154,22 +156,30 @@ public sealed class ThirstSystem : EntitySystem
public override void Update(float frameTime) public override void Update(float frameTime)
{ {
_accumulatedFrameTime += frameTime; base.Update(frameTime);
if (_accumulatedFrameTime > 1) var query = EntityQueryEnumerator<ThirstComponent>();
while (query.MoveNext(out var uid, out var thirst))
{ {
var query = EntityManager.EntityQueryEnumerator<ThirstComponent>(); if (_timing.CurTime < thirst.NextUpdateTime)
while (query.MoveNext(out var uid, out var comp)) continue;
{
UpdateThirst(comp, - comp.ActualDecayRate); thirst.NextUpdateTime += thirst.UpdateRate;
var calculatedThirstThreshold = GetThirstThreshold(comp, comp.CurrentThirst);
if (calculatedThirstThreshold != comp.CurrentThirstThreshold) UpdateThirst(thirst, -thirst.ActualDecayRate);
{ var calculatedThirstThreshold = GetThirstThreshold(thirst, thirst.CurrentThirst);
comp.CurrentThirstThreshold = calculatedThirstThreshold;
UpdateEffects(uid, comp); if (calculatedThirstThreshold == thirst.CurrentThirstThreshold)
continue;
thirst.CurrentThirstThreshold = calculatedThirstThreshold;
UpdateEffects(uid, thirst);
Dirty(uid, thirst);
} }
} }
_accumulatedFrameTime -= 1;
} private void OnUnpaused(EntityUid uid, ThirstComponent component, ref EntityUnpausedEvent args)
{
component.NextUpdateTime += args.PausedTime;
} }
} }

View File

@@ -0,0 +1,9 @@
using Robust.Shared.GameStates;
namespace Content.Shared.Overlays;
/// <summary>
/// This component allows you to see the hungriness of mobs.
/// </summary>
[RegisterComponent, NetworkedComponent]
public sealed partial class ShowHungerIconsComponent : Component { }

View File

@@ -1,10 +1,9 @@
using Robust.Shared.GameStates; using Robust.Shared.GameStates;
namespace Content.Shared.Overlays namespace Content.Shared.Overlays;
{
/// <summary> /// <summary>
/// This component allows you to see job icons above mobs. /// This component allows you to see job icons above mobs.
/// </summary> /// </summary>
[RegisterComponent, NetworkedComponent] [RegisterComponent, NetworkedComponent]
public sealed partial class ShowSecurityIconsComponent : Component { } public sealed partial class ShowSecurityIconsComponent : Component { }
}

View File

@@ -0,0 +1,9 @@
using Robust.Shared.GameStates;
namespace Content.Shared.Overlays;
/// <summary>
/// This component allows you to see the thirstiness of mobs.
/// </summary>
[RegisterComponent, NetworkedComponent]
public sealed partial class ShowThirstIconsComponent : Component { }

View File

@@ -42,6 +42,7 @@
sprite: Clothing/Eyes/Hud/beergoggles.rsi sprite: Clothing/Eyes/Hud/beergoggles.rsi
- type: Clothing - type: Clothing
sprite: Clothing/Eyes/Hud/beergoggles.rsi sprite: Clothing/Eyes/Hud/beergoggles.rsi
- type: ShowThirstIcons
- type: entity - type: entity
parent: ClothingEyesBase parent: ClothingEyesBase
@@ -53,6 +54,19 @@
sprite: Clothing/Eyes/Hud/friedonion.rsi sprite: Clothing/Eyes/Hud/friedonion.rsi
- type: Clothing - type: Clothing
sprite: Clothing/Eyes/Hud/friedonion.rsi sprite: Clothing/Eyes/Hud/friedonion.rsi
- type: ShowHungerIcons
- type: Food
- type: SolutionContainerManager
solutions:
food:
maxVol: 3
reagents:
- ReagentId: Nutriment
Quantity: 3
- type: FlavorProfile
flavors:
- onion
- greasey
- type: entity - type: entity
parent: ClothingEyesBase parent: ClothingEyesBase
@@ -64,6 +78,8 @@
sprite: Clothing/Eyes/Hud/onionbeer.rsi sprite: Clothing/Eyes/Hud/onionbeer.rsi
- type: Clothing - type: Clothing
sprite: Clothing/Eyes/Hud/onionbeer.rsi sprite: Clothing/Eyes/Hud/onionbeer.rsi
- type: ShowHungerIcons
- type: ShowThirstIcons
- type: entity - type: entity
parent: ClothingEyesBase parent: ClothingEyesBase
@@ -75,6 +91,7 @@
sprite: Clothing/Eyes/Hud/medonion.rsi sprite: Clothing/Eyes/Hud/medonion.rsi
- type: Clothing - type: Clothing
sprite: Clothing/Eyes/Hud/medonion.rsi sprite: Clothing/Eyes/Hud/medonion.rsi
- type: ShowHungerIcons
- type: entity - type: entity
parent: ClothingEyesBase parent: ClothingEyesBase
@@ -86,6 +103,8 @@
sprite: Clothing/Eyes/Hud/medonionbeer.rsi sprite: Clothing/Eyes/Hud/medonionbeer.rsi
- type: Clothing - type: Clothing
sprite: Clothing/Eyes/Hud/medonionbeer.rsi sprite: Clothing/Eyes/Hud/medonionbeer.rsi
- type: ShowHungerIcons
- type: ShowThirstIcons
- type: entity - type: entity
parent: ClothingEyesBase parent: ClothingEyesBase
@@ -122,3 +141,5 @@
- type: Clothing - type: Clothing
sprite: Clothing/Eyes/Hud/omni.rsi sprite: Clothing/Eyes/Hud/omni.rsi
- type: ShowSecurityIcons - type: ShowSecurityIcons
- type: ShowHungerIcons
- type: ShowThirstIcons

View File

@@ -0,0 +1,49 @@
#Hunger
- type: statusIcon
id: HungerIconOverfed
priority: 5
icon:
sprite: Interface/Misc/food_icons.rsi
state: overfed
locationPreference: Right
- type: statusIcon
id: HungerIconPeckish
priority: 5
icon:
sprite: Interface/Misc/food_icons.rsi
state: peckish
locationPreference: Right
- type: statusIcon
id: HungerIconStarving
priority: 5
icon:
sprite: Interface/Misc/food_icons.rsi
state: starving
locationPreference: Right
#Thirst
- type: statusIcon
id: ThirstIconOverhydrated
priority: 5
icon:
sprite: Interface/Misc/food_icons.rsi
state: overhydrated
locationPreference: Left
- type: statusIcon
id: ThirstIconThirsty
priority: 5
icon:
sprite: Interface/Misc/food_icons.rsi
state: thirsty
locationPreference: Left
- type: statusIcon
id: ThirstIconParched
priority: 5
icon:
sprite: Interface/Misc/food_icons.rsi
state: parched
locationPreference: Left

Binary file not shown.

Before

Width:  |  Height:  |  Size: 292 B

After

Width:  |  Height:  |  Size: 273 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 283 B

After

Width:  |  Height:  |  Size: 234 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 274 B

After

Width:  |  Height:  |  Size: 237 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 296 B

After

Width:  |  Height:  |  Size: 273 B