Hunger and thirst HUDs (#18066)

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

* thirst goggles

* set starting hud gear
This commit is contained in:
PrPleGoo
2023-07-18 08:01:22 +02:00
committed by GitHub
parent 9268789618
commit 67e4b626c1
26 changed files with 1027 additions and 95 deletions

View File

@@ -0,0 +1,115 @@
using Content.Shared.Clothing.Components;
using Content.Shared.GameTicking;
using Content.Shared.Inventory;
using Content.Shared.Inventory.Events;
using Robust.Client.GameObjects;
using Robust.Client.Player;
namespace Content.Client.Overlays
{
public abstract class ComponentAddedOverlaySystemBase<T> : EntitySystem where T : IComponent
{
[Dependency] private readonly IPlayerManager _player = default!;
[Dependency] private readonly IEntityManager _entityManager = default!;
private InventorySystem _invSystem = default!;
protected bool IsActive = false;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<T, ComponentInit>(OnInit);
SubscribeLocalEvent<T, ComponentRemove>(OnRemove);
SubscribeLocalEvent<PlayerAttachedEvent>(OnPlayerAttached);
SubscribeLocalEvent<PlayerDetachedEvent>(OnPlayerDetached);
SubscribeLocalEvent<T, GotEquippedEvent>(OnCompEquip);
SubscribeLocalEvent<T, GotUnequippedEvent>(OnCompUnequip);
SubscribeLocalEvent<RoundRestartCleanupEvent>(OnRoundRestart);
_invSystem = _entityManager.System<InventorySystem>();
}
public void ApplyOverlay(T component)
{
IsActive = true;
OnApplyOverlay(component);
}
public void RemoveOverlay()
{
IsActive = false;
OnRemoveOverlay();
}
protected virtual void OnApplyOverlay(T component) { }
protected virtual void OnRemoveOverlay() { }
private void OnInit(EntityUid uid, T component, ComponentInit args)
{
if (_player.LocalPlayer?.ControlledEntity == uid)
{
ApplyOverlay(component);
}
}
private void OnRemove(EntityUid uid, T component, ComponentRemove args)
{
if (_player.LocalPlayer?.ControlledEntity == uid)
{
RemoveOverlay();
}
}
private void OnPlayerAttached(PlayerAttachedEvent args)
{
if (TryComp<T>(args.Entity, out var component))
ApplyOverlay(component);
if (TryComp(args.Entity, out InventoryComponent? inventoryComponent)
&& _invSystem.TryGetSlots(args.Entity, out var slotDefinitions, inventoryComponent))
{
foreach (var slot in slotDefinitions)
{
if (_invSystem.TryGetSlotEntity(args.Entity, slot.Name, out var itemUid)
&& TryComp(itemUid.Value, out component))
{
OnCompEquip(itemUid.Value, component, new GotEquippedEvent(args.Entity, itemUid.Value, slot));
}
}
}
}
private void OnPlayerDetached(PlayerDetachedEvent args)
{
RemoveOverlay();
}
private void OnCompEquip(EntityUid uid, T component, GotEquippedEvent args)
{
if (!TryComp<ClothingComponent>(uid, out var clothing)) return;
if (args.Equipee != _player.LocalPlayer?.ControlledEntity) return;
if (!clothing.Slots.HasFlag(args.SlotFlags)) return;
ApplyOverlay(component);
}
private void OnCompUnequip(EntityUid uid, T component, GotUnequippedEvent args)
{
if (args.Equipee != _player.LocalPlayer?.ControlledEntity) return;
RemoveOverlay();
}
private void OnRoundRestart(RoundRestartCleanupEvent args)
{
RemoveOverlay();
}
}
}

View File

@@ -0,0 +1,74 @@
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 : ComponentAddedOverlaySystemBase<ShowHungerIconsComponent>
{
[Dependency] private readonly IPrototypeManager _prototypeMan = default!;
[Dependency] private readonly IEntityManager _entManager = default!;
private StatusIconPrototype? _overfed;
private StatusIconPrototype? _peckish;
private StatusIconPrototype? _starving;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<HungerComponent, GetStatusIconsEvent>(OnGetStatusIconsEvent);
}
private void OnGetStatusIconsEvent(EntityUid uid, HungerComponent hungerComponent, ref GetStatusIconsEvent @event)
{
if (!IsActive)
return;
var healthIcons = DecideHungerIcon(uid, hungerComponent);
@event.StatusIcons.AddRange(healthIcons);
}
private IReadOnlyList<StatusIconPrototype> DecideHungerIcon(EntityUid uid, HungerComponent hungerComponent)
{
var result = new List<StatusIconPrototype>();
if (_entManager.TryGetComponent<MetaDataComponent>(uid, out var metaDataComponent) &&
metaDataComponent.Flags.HasFlag(MetaDataFlags.InContainer))
{
return result;
}
switch (hungerComponent.CurrentThreshold)
{
case HungerThreshold.Overfed:
if (_overfed != null ||
_prototypeMan.TryIndex("HungerIcon_Overfed", out _overfed))
{
result.Add(_overfed);
}
break;
case HungerThreshold.Peckish:
if (_peckish != null ||
_prototypeMan.TryIndex("HungerIcon_Peckish", out _peckish))
{
result.Add(_peckish);
}
break;
case HungerThreshold.Starving:
if (_starving != null ||
_prototypeMan.TryIndex("HungerIcon_Starving", out _starving))
{
result.Add(_starving);
}
break;
}
return result;
}
}
}

View File

@@ -0,0 +1,90 @@
using Content.Shared.Access.Components;
using Content.Shared.Body.Components;
using Content.Shared.Inventory;
using Content.Shared.Overlays;
using Content.Shared.PDA;
using Content.Shared.StatusIcon;
using Content.Shared.StatusIcon.Components;
using Robust.Shared.Prototypes;
namespace Content.Client.Overlays
{
public sealed class ShowSecurityIconsSystem : ComponentAddedOverlaySystemBase<ShowSecurityIconsComponent>
{
[Dependency] private readonly IPrototypeManager _prototypeMan = default!;
[Dependency] private readonly IEntityManager _entManager = default!;
[Dependency] private readonly InventorySystem _inventorySystem = default!;
private Dictionary<string, StatusIconPrototype> _jobIcons = new();
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<BodyComponent, GetStatusIconsEvent>(OnGetStatusIconsEvent);
}
private void OnGetStatusIconsEvent(EntityUid uid, BodyComponent _, ref GetStatusIconsEvent @event)
{
if (!IsActive)
return;
var healthIcons = DecideSecurityIcon(uid);
@event.StatusIcons.AddRange(healthIcons);
}
private IReadOnlyList<StatusIconPrototype> DecideSecurityIcon(EntityUid uid)
{
var result = new List<StatusIconPrototype>();
if (_entManager.TryGetComponent<MetaDataComponent>(uid, out var metaDataComponent) &&
metaDataComponent.Flags.HasFlag(MetaDataFlags.InContainer))
{
return result;
}
var iconToGet = "NoId";
if (_inventorySystem.TryGetSlotEntity(uid, "id", out var idUid))
{
// PDA
if (EntityManager.TryGetComponent(idUid, out PdaComponent? pda))
{
iconToGet = pda.ContainedId?.JobTitle ?? string.Empty;
}
// ID Card
else if (EntityManager.TryGetComponent(idUid, out IdCardComponent? id))
{
iconToGet = id.JobTitle ?? string.Empty;
}
iconToGet = iconToGet.Replace(" ", "");
}
iconToGet = EnsureIcon(iconToGet, _jobIcons);
result.Add(_jobIcons[iconToGet]);
// Add arrest icons here, WYCI.
return result;
}
private string EnsureIcon(string iconKey, Dictionary<string, StatusIconPrototype> icons)
{
if (!icons.ContainsKey(iconKey))
{
if (_prototypeMan.TryIndex<StatusIconPrototype>($"JobIcon_{iconKey}", out var securityIcon))
{
icons.Add(iconKey, securityIcon);
return iconKey;
}
}
else
{
return iconKey;
}
iconKey = "Unknown";
return EnsureIcon(iconKey, icons);
}
}
}

View File

@@ -0,0 +1,73 @@
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 : ComponentAddedOverlaySystemBase<ShowThirstIconsComponent>
{
[Dependency] private readonly IPrototypeManager _prototypeMan = default!;
[Dependency] private readonly IEntityManager _entManager = default!;
private StatusIconPrototype? _overhydrated;
private StatusIconPrototype? _thirsty;
private StatusIconPrototype? _parched;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<ThirstComponent, GetStatusIconsEvent>(OnGetStatusIconsEvent);
}
private void OnGetStatusIconsEvent(EntityUid uid, ThirstComponent thirstComponent, ref GetStatusIconsEvent @event)
{
if (!IsActive)
return;
var healthIcons = DecideThirstIcon(uid, thirstComponent);
@event.StatusIcons.AddRange(healthIcons);
}
private IReadOnlyList<StatusIconPrototype> DecideThirstIcon(EntityUid uid, ThirstComponent thirstComponent)
{
var result = new List<StatusIconPrototype>();
if (_entManager.TryGetComponent<MetaDataComponent>(uid, out var metaDataComponent) &&
metaDataComponent.Flags.HasFlag(MetaDataFlags.InContainer))
{
return result;
}
switch (thirstComponent.CurrentThirstThreshold)
{
case ThirstThreshold.OverHydrated:
if (_overhydrated != null ||
_prototypeMan.TryIndex("ThirstIcon_Overhydrated", out _overhydrated))
{
result.Add(_overhydrated);
}
break;
case ThirstThreshold.Thirsty:
if (_thirsty != null ||
_prototypeMan.TryIndex("ThirstIcon_Thirsty", out _thirsty))
{
result.Add(_thirsty);
}
break;
case ThirstThreshold.Parched:
if (_parched != null ||
_prototypeMan.TryIndex("ThirstIcon_Parched", out _parched))
{
result.Add(_parched);
}
break;
}
return result;
}
}
}

View File

@@ -1,8 +1,9 @@
using System.Numerics;
using Content.Shared.StatusIcon;
using Content.Shared.StatusIcon.Components;
using Robust.Client.GameObjects;
using Robust.Client.Graphics;
using Robust.Shared.Enums;
using System.Numerics;
namespace Content.Client.StatusIcon;
@@ -57,7 +58,8 @@ public sealed class StatusIconOverlay : Overlay
Matrix3.Multiply(rotationMatrix, scaledWorld, out var matty);
handle.SetTransform(matty);
var count = 0;
var countL = 0;
var countR = 0;
var accOffsetL = 0;
var accOffsetR = 0;
icons.Sort();
@@ -71,13 +73,16 @@ public sealed class StatusIconOverlay : Overlay
// the icons are ordered left to right, top to bottom.
// extra icons that don't fit are just cut off.
if (count % 2 == 0)
if (proto.LocationPreference == StatusIconLocationPreference.Left ||
proto.LocationPreference == StatusIconLocationPreference.None && countL <= countR)
{
if (accOffsetL + texture.Height > sprite.Bounds.Height * EyeManager.PixelsPerMeter)
break;
accOffsetL += texture.Height;
yOffset = (bounds.Height + sprite.Offset.Y) / 2f - (float) accOffsetL / EyeManager.PixelsPerMeter;
xOffset = -(bounds.Width + sprite.Offset.X) / 2f;
countL++;
}
else
{
@@ -86,8 +91,9 @@ public sealed class StatusIconOverlay : Overlay
accOffsetR += texture.Height;
yOffset = (bounds.Height + sprite.Offset.Y) / 2f - (float) accOffsetR / EyeManager.PixelsPerMeter;
xOffset = (bounds.Width + sprite.Offset.X) / 2f - (float) texture.Width / EyeManager.PixelsPerMeter;
countR++;
}
count++;
var position = new Vector2(xOffset, yOffset);
handle.DrawTexture(texture, position);

View File

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

View File

@@ -1,16 +1,11 @@
using Content.Server.Body.Components;
using Content.Server.Body.Systems;
using Content.Server.Chemistry.EntitySystems;
using Content.Server.Fluids.Components;
using Content.Server.Fluids.EntitySystems;
using Content.Server.Forensics;
using Content.Server.Nutrition.Components;
using Content.Server.Nutrition.EntitySystems;
using Content.Server.Popups;
using Content.Server.Stunnable;
using Content.Shared.Audio;
using Content.Shared.Chemistry.Components;
using Content.Shared.Fluids.Components;
using Content.Shared.IdentityManagement;
using Content.Shared.Nutrition.Components;
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 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; } = 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

@@ -0,0 +1,101 @@
using Content.Shared.Alert;
using Content.Shared.Nutrition.EntitySystems;
using Robust.Shared.GameStates;
using Robust.Shared.Serialization;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;
namespace Content.Shared.Nutrition.Components
{
[RegisterComponent, NetworkedComponent, Access(typeof(ThirstSystem))]
public sealed 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;
/// <summary>
/// The time when the hunger will update next.
/// </summary>
[DataField("nextUpdateTime", customTypeSerializer: typeof(TimeOffsetSerializer)), ViewVariables(VVAccess.ReadWrite)]
public TimeSpan NextUpdateTime;
/// <summary>
/// The time between each update.
/// </summary>
[ViewVariables(VVAccess.ReadWrite)]
public TimeSpan UpdateRate = TimeSpan.FromSeconds(1);
[DataField("thresholds")]
public Dictionary<ThirstThreshold, float> ThirstThresholds { get; } = 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},
};
}
[Serializable, NetSerializable]
public sealed class ThirstComponentState : ComponentState
{
public float BaseDecayRate;
public float ActualDecayRate;
public ThirstThreshold CurrentThirstThreshold;
public ThirstThreshold LastThirstThreshold;
public float CurrentThirst;
public TimeSpan NextUpdateTime;
public ThirstComponentState(float baseDecayRate,
float actualDecayRate,
ThirstThreshold currentThirstThreshold,
ThirstThreshold lastThirstThreshold,
float currentThirst,
TimeSpan nextUpdateTime)
{
BaseDecayRate = baseDecayRate;
ActualDecayRate = actualDecayRate;
CurrentThirstThreshold = currentThirstThreshold;
LastThirstThreshold = lastThirstThreshold;
CurrentThirst = currentThirst;
NextUpdateTime = nextUpdateTime;
}
}
[Flags]
public enum ThirstThreshold : byte
{
// Hydrohomies
Dead = 0,
Parched = 1 << 0,
Thirsty = 1 << 1,
Okay = 1 << 2,
OverHydrated = 1 << 3,
}
}

View File

@@ -1,33 +1,71 @@
using Content.Server.Nutrition.Components;
using JetBrains.Annotations;
using Robust.Shared.Random;
using Content.Shared.Movement.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 Robust.Shared.GameStates;
using Robust.Shared.Random;
using Robust.Shared.Timing;
namespace Content.Server.Nutrition.EntitySystems
namespace Content.Shared.Nutrition.EntitySystems
{
[UsedImplicitly]
public sealed class ThirstSystem : EntitySystem
{
[Dependency] private readonly IGameTiming _timing = default!;
[Dependency] private readonly IRobustRandom _random = default!;
[Dependency] private readonly AlertsSystem _alerts = default!;
[Dependency] private readonly MovementSpeedModifierSystem _movement = default!;
[Dependency] private readonly SharedJetpackSystem _jetpack = default!;
private ISawmill _sawmill = default!;
private float _accumulatedFrameTime;
public override void Initialize()
{
base.Initialize();
_sawmill = Logger.GetSawmill("thirst");
SubscribeLocalEvent<ThirstComponent, ComponentGetState>(OnGetState);
SubscribeLocalEvent<ThirstComponent, ComponentHandleState>(OnHandleState);
SubscribeLocalEvent<ThirstComponent, EntityUnpausedEvent>(OnUnpaused);
SubscribeLocalEvent<ThirstComponent, RefreshMovementSpeedModifiersEvent>(OnRefreshMovespeed);
SubscribeLocalEvent<ThirstComponent, ComponentShutdown>(OnShutdown);
SubscribeLocalEvent<ThirstComponent, ComponentStartup>(OnComponentStartup);
SubscribeLocalEvent<ThirstComponent, RejuvenateEvent>(OnRejuvenate);
}
private void OnGetState(EntityUid uid, ThirstComponent component, ref ComponentGetState args)
{
args.State = new ThirstComponentState(component.BaseDecayRate,
component.ActualDecayRate,
component.CurrentThirstThreshold,
component.LastThirstThreshold,
component.CurrentThirst,
component.NextUpdateTime);
}
private void OnHandleState(EntityUid uid, ThirstComponent component, ref ComponentHandleState args)
{
if (args.Current is not ThirstComponentState state)
return;
component.BaseDecayRate = state.BaseDecayRate;
component.ActualDecayRate = state.ActualDecayRate;
component.CurrentThirstThreshold = state.CurrentThirstThreshold;
component.LastThirstThreshold = state.LastThirstThreshold;
component.CurrentThirst = state.CurrentThirst;
component.NextUpdateTime = state.NextUpdateTime;
}
private void OnUnpaused(EntityUid uid, ThirstComponent component, ref EntityUnpausedEvent args)
{
component.NextUpdateTime += args.PausedTime;
}
private void OnShutdown(EntityUid uid, ThirstComponent component, ComponentShutdown args)
{
_alerts.ClearAlertCategory(uid, AlertCategory.Thirst);
}
private void OnComponentStartup(EntityUid uid, ThirstComponent component, ComponentStartup args)
{
// Do not change behavior unless starting value is explicitly defined
@@ -149,23 +187,26 @@ namespace Content.Server.Nutrition.EntitySystems
throw new ArgumentOutOfRangeException($"No thirst threshold found for {component.CurrentThirstThreshold}");
}
}
public override void Update(float frameTime)
{
_accumulatedFrameTime += frameTime;
base.Update(frameTime);
if (_accumulatedFrameTime > 1)
var query = EntityQueryEnumerator<ThirstComponent>();
while (query.MoveNext(out var thirst))
{
foreach (var component in EntityManager.EntityQuery<ThirstComponent>())
if (_timing.CurTime < thirst.NextUpdateTime)
continue;
thirst.NextUpdateTime = _timing.CurTime + thirst.UpdateRate;
UpdateThirst(thirst, -thirst.ActualDecayRate);
var calculatedThirstThreshold = GetThirstThreshold(thirst, thirst.CurrentThirst);
if (calculatedThirstThreshold != thirst.CurrentThirstThreshold)
{
UpdateThirst(component, - component.ActualDecayRate);
var calculatedThirstThreshold = GetThirstThreshold(component, component.CurrentThirst);
if (calculatedThirstThreshold != component.CurrentThirstThreshold)
{
component.CurrentThirstThreshold = calculatedThirstThreshold;
UpdateEffects(component);
thirst.CurrentThirstThreshold = calculatedThirstThreshold;
UpdateEffects(thirst);
}
}
_accumulatedFrameTime -= 1;
Dirty(thirst);
}
}
}

View File

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

View File

@@ -0,0 +1,8 @@
namespace Content.Shared.Overlays
{
/// <summary>
/// This component allows you to see job icons above mobs.
/// </summary>
[RegisterComponent]
public sealed class ShowSecurityIconsComponent : Component { }
}

View File

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

View File

@@ -1,4 +1,5 @@
using Robust.Shared.Prototypes;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization;
using Robust.Shared.Utility;
namespace Content.Shared.StatusIcon;
@@ -22,6 +23,12 @@ public class StatusIconData : IComparable<StatusIconData>
[DataField("priority")]
public int Priority = 10;
/// <summary>
/// A preference for where the icon will be displayed. None | Left | Right
/// </summary>
[DataField("locationPreference")]
public StatusIconLocationPreference LocationPreference = StatusIconLocationPreference.None;
public int CompareTo(StatusIconData? other)
{
return Priority.CompareTo(other?.Priority ?? int.MaxValue);
@@ -38,3 +45,11 @@ public sealed class StatusIconPrototype : StatusIconData, IPrototype
[IdDataField]
public string ID { get; } = default!;
}
[Serializable, NetSerializable]
public enum StatusIconLocationPreference : byte
{
None,
Left,
Right,
}

View File

@@ -1,14 +1,3 @@
- type: entity
parent: ClothingEyesBase
id: ClothingEyesGlassesBeer
name: beer goggles
description: A pair of sunglasses outfitted with apparatus to scan reagents, as well as providing an innate understanding of liquid viscosity while in motion.
components:
- type: Sprite
sprite: Clothing/Eyes/Glasses/beergoggles.rsi
- type: Clothing
sprite: Clothing/Eyes/Glasses/beergoggles.rsi
- type: entity
parent: ClothingEyesBase
id: ClothingEyesGlassesGar

View File

@@ -30,3 +30,40 @@
sprite: Clothing/Eyes/Hud/sec.rsi
- type: Clothing
sprite: Clothing/Eyes/Hud/sec.rsi
- type: ShowSecurityIcons
- type: entity
parent: ClothingEyesBase
id: ClothingEyesHudChef
name: onion goggles
description: Two onion rings that fused together while frying. They scan the humanoids in view and provide accurate data about their peckishness. Can be eaten as a little treat.
components:
- type: Sprite
sprite: Clothing/Eyes/Hud/friedoniongoggles.rsi
- type: Clothing
sprite: Clothing/Eyes/Hud/friedoniongoggles.rsi
- type: ShowHungerIcons
- type: Food
- type: SolutionContainerManager
solutions:
food:
maxVol: 3
reagents:
- ReagentId: Nutriment
Quantity: 3
- type: FlavorProfile
flavors:
- onion
- greasey
- type: entity
parent: ClothingEyesBase
id: ClothingEyesGlassesBeer
name: beer goggles
description: A pair of sunglasses outfitted with apparatus to scan reagents, as well as providing an innate understanding of liquid viscosity while in motion.
components:
- type: Sprite
sprite: Clothing/Eyes/Hud/beergoggles.rsi
- type: Clothing
sprite: Clothing/Eyes/Hud/beergoggles.rsi
- type: ShowThirstIcons

View File

@@ -22,6 +22,7 @@
id: BartenderGear
equipment:
head: ClothingHeadHatTophat
eyes: ClothingEyesGlassesBeer
jumpsuit: ClothingUniformJumpsuitBartender
outerClothing: ClothingOuterVest
back: ClothingBackpackFilled

View File

@@ -23,6 +23,7 @@
equipment:
jumpsuit: ClothingUniformJumpsuitChef
head: ClothingHeadHatChef
eyes: ClothingEyesHudChef
back: ClothingBackpackFilled
mask: ClothingMaskItalianMoustache
shoes: ClothingShoesColorBlack

View File

@@ -0,0 +1,49 @@
#Hunger
- type: statusIcon
id: HungerIcon_Overfed
priority: 5
icon:
sprite: Interface/Misc/food_icons.rsi
state: overfed
locationPreference: Right
- type: statusIcon
id: HungerIcon_Peckish
priority: 5
icon:
sprite: Interface/Misc/food_icons.rsi
state: peckish
locationPreference: Right
- type: statusIcon
id: HungerIcon_Starving
priority: 5
icon:
sprite: Interface/Misc/food_icons.rsi
state: starving
locationPreference: Right
#Thirst
- type: statusIcon
id: ThirstIcon_Overhydrated
priority: 5
icon:
sprite: Interface/Misc/food_icons.rsi
state: overhydrated
locationPreference: Left
- type: statusIcon
id: ThirstIcon_Thirsty
priority: 5
icon:
sprite: Interface/Misc/food_icons.rsi
state: thirsty
locationPreference: Left
- type: statusIcon
id: ThirstIcon_Parched
priority: 5
icon:
sprite: Interface/Misc/food_icons.rsi
state: parched
locationPreference: Left

View File

@@ -0,0 +1,375 @@
- type: statusIcon
id: JobIcon_Detective
priority: 1
icon:
sprite: Interface/Misc/job_icons.rsi
state: Detective
locationPreference: Left
- type: statusIcon
id: JobIcon_QuarterMaster
priority: 1
icon:
sprite: Interface/Misc/job_icons.rsi
state: QuarterMaster
locationPreference: Left
- type: statusIcon
id: JobIcon_Botanist
priority: 1
icon:
sprite: Interface/Misc/job_icons.rsi
state: Botanist
locationPreference: Left
- type: statusIcon
id: JobIcon_Boxer
priority: 1
icon:
sprite: Interface/Misc/job_icons.rsi
state: Boxer
locationPreference: Left
- type: statusIcon
id: JobIcon_AtmosphericTechnician
priority: 1
icon:
sprite: Interface/Misc/job_icons.rsi
state: AtmosphericTechnician
locationPreference: Left
- type: statusIcon
id: JobIcon_Nanotrasen
priority: 1
icon:
sprite: Interface/Misc/job_icons.rsi
state: Nanotrasen
locationPreference: Left
- type: statusIcon
id: JobIcon_Prisoner
priority: 1
icon:
sprite: Interface/Misc/job_icons.rsi
state: Prisoner
locationPreference: Left
- type: statusIcon
id: JobIcon_Janitor
priority: 1
icon:
sprite: Interface/Misc/job_icons.rsi
state: Janitor
locationPreference: Left
- type: statusIcon
id: JobIcon_Chemist
priority: 1
icon:
sprite: Interface/Misc/job_icons.rsi
state: Chemist
locationPreference: Left
- type: statusIcon
id: JobIcon_StationEngineer
priority: 1
icon:
sprite: Interface/Misc/job_icons.rsi
state: StationEngineer
locationPreference: Left
- type: statusIcon
id: JobIcon_SecurityOfficer
priority: 1
icon:
sprite: Interface/Misc/job_icons.rsi
state: SecurityOfficer
locationPreference: Left
- type: statusIcon
id: JobIcon_NoId
priority: 1
icon:
sprite: Interface/Misc/job_icons.rsi
state: NoId
locationPreference: Left
- type: statusIcon
id: JobIcon_ChiefMedicalOfficer
priority: 1
icon:
sprite: Interface/Misc/job_icons.rsi
state: ChiefMedicalOfficer
locationPreference: Left
- type: statusIcon
id: JobIcon_Roboticist
priority: 1
icon:
sprite: Interface/Misc/job_icons.rsi
state: Roboticist
locationPreference: Left
- type: statusIcon
id: JobIcon_Chaplain
priority: 1
icon:
sprite: Interface/Misc/job_icons.rsi
state: Chaplain
locationPreference: Left
- type: statusIcon
id: JobIcon_Lawyer
priority: 1
icon:
sprite: Interface/Misc/job_icons.rsi
state: Lawyer
locationPreference: Left
- type: statusIcon
id: JobIcon_Unknown
priority: 1
icon:
sprite: Interface/Misc/job_icons.rsi
state: Unknown
locationPreference: Left
- type: statusIcon
id: JobIcon_Librarian
priority: 1
icon:
sprite: Interface/Misc/job_icons.rsi
state: Librarian
locationPreference: Left
- type: statusIcon
id: JobIcon_CargoTechnician
priority: 1
icon:
sprite: Interface/Misc/job_icons.rsi
state: CargoTechnician
locationPreference: Left
- type: statusIcon
id: JobIcon_Scientist
priority: 1
icon:
sprite: Interface/Misc/job_icons.rsi
state: Scientist
locationPreference: Left
- type: statusIcon
id: JobIcon_ResearchAssistant
priority: 1
icon:
sprite: Interface/Misc/job_icons.rsi
state: ResearchAssistant
locationPreference: Left
- type: statusIcon
id: JobIcon_Geneticist
priority: 1
icon:
sprite: Interface/Misc/job_icons.rsi
state: Geneticist
locationPreference: Left
- type: statusIcon
id: JobIcon_Clown
priority: 1
icon:
sprite: Interface/Misc/job_icons.rsi
state: Clown
locationPreference: Left
- type: statusIcon
id: JobIcon_Captain
priority: 1
icon:
sprite: Interface/Misc/job_icons.rsi
state: Captain
locationPreference: Left
- type: statusIcon
id: JobIcon_HeadOfPersonnel
priority: 1
icon:
sprite: Interface/Misc/job_icons.rsi
state: HeadOfPersonnel
locationPreference: Left
- type: statusIcon
id: JobIcon_Virologist
priority: 1
icon:
sprite: Interface/Misc/job_icons.rsi
state: Virologist
locationPreference: Left
- type: statusIcon
id: JobIcon_ShaftMiner
priority: 1
icon:
sprite: Interface/Misc/job_icons.rsi
state: ShaftMiner
locationPreference: Left
- type: statusIcon
id: JobIcon_Passenger
priority: 1
icon:
sprite: Interface/Misc/job_icons.rsi
state: Passenger
locationPreference: Left
- type: statusIcon
id: JobIcon_ChiefEngineer
priority: 1
icon:
sprite: Interface/Misc/job_icons.rsi
state: ChiefEngineer
locationPreference: Left
- type: statusIcon
id: JobIcon_Bartender
priority: 1
icon:
sprite: Interface/Misc/job_icons.rsi
state: Bartender
locationPreference: Left
- type: statusIcon
id: JobIcon_HeadOfSecurity
priority: 1
icon:
sprite: Interface/Misc/job_icons.rsi
state: HeadOfSecurity
locationPreference: Left
- type: statusIcon
id: JobIcon_Brigmedic
priority: 1
icon:
sprite: Interface/Misc/job_icons.rsi
state: Brigmedic
locationPreference: Left
- type: statusIcon
id: JobIcon_MedicalDoctor
priority: 1
icon:
sprite: Interface/Misc/job_icons.rsi
state: MedicalDoctor
locationPreference: Left
- type: statusIcon
id: JobIcon_Paramedic
priority: 1
icon:
sprite: Interface/Misc/job_icons.rsi
state: Paramedic
locationPreference: Left
- type: statusIcon
id: JobIcon_Chef
priority: 1
icon:
sprite: Interface/Misc/job_icons.rsi
state: Chef
locationPreference: Left
- type: statusIcon
id: JobIcon_Warden
priority: 1
icon:
sprite: Interface/Misc/job_icons.rsi
state: Warden
locationPreference: Left
- type: statusIcon
id: JobIcon_ResearchDirector
priority: 1
icon:
sprite: Interface/Misc/job_icons.rsi
state: ResearchDirector
locationPreference: Left
- type: statusIcon
id: JobIcon_Mime
priority: 1
icon:
sprite: Interface/Misc/job_icons.rsi
state: Mime
locationPreference: Left
- type: statusIcon
id: JobIcon_Musician
priority: 1
icon:
sprite: Interface/Misc/job_icons.rsi
state: Musician
locationPreference: Left
- type: statusIcon
id: JobIcon_Reporter
priority: 1
icon:
sprite: Interface/Misc/job_icons.rsi
state: Reporter
locationPreference: Left
- type: statusIcon
id: JobIcon_Psychologist
priority: 1
icon:
sprite: Interface/Misc/job_icons.rsi
state: Psychologist
locationPreference: Left
- type: statusIcon
id: JobIcon_MedicalIntern
priority: 1
icon:
sprite: Interface/Misc/job_icons.rsi
state: MedicalIntern
locationPreference: Left
- type: statusIcon
id: JobIcon_TechnicalAssistant
priority: 1
icon:
sprite: Interface/Misc/job_icons.rsi
state: TechnicalAssistant
locationPreference: Left
- type: statusIcon
id: JobIcon_ServiceWorker
priority: 1
icon:
sprite: Interface/Misc/job_icons.rsi
state: ServiceWorker
locationPreference: Left
- type: statusIcon
id: JobIcon_SecurityCadet
priority: 1
icon:
sprite: Interface/Misc/job_icons.rsi
state: SecurityCadet
locationPreference: Left
- type: statusIcon
id: JobIcon_Zombie
priority: 1
icon:
sprite: Interface/Misc/job_icons.rsi
state: Zombie
locationPreference: Left
- type: statusIcon
id: JobIcon_Zookeeper
priority: 1
icon:
sprite: Interface/Misc/job_icons.rsi
state: Zookeeper
locationPreference: Left

View File

Before

Width:  |  Height:  |  Size: 181 B

After

Width:  |  Height:  |  Size: 181 B