#nullable enable using System; using System.Collections.Generic; using System.Threading.Tasks; using Content.Server.GameObjects.Components.Nutrition; using Content.Shared.Interfaces.GameObjects.Components; using Content.Shared.Utility; using Robust.Server.GameObjects.EntitySystems; using Robust.Shared.Audio; using Robust.Shared.GameObjects; using Robust.Shared.GameObjects.Systems; using Robust.Shared.Interfaces.GameObjects; using Robust.Shared.Interfaces.Random; using Robust.Shared.IoC; using Robust.Shared.Random; using Robust.Shared.Serialization; using Robust.Shared.ViewVariables; namespace Content.Server.GameObjects.Components.Culinary { [RegisterComponent] public class UtensilComponent : Component, IAfterInteract { public override string Name => "Utensil"; private UtensilType _types = UtensilType.None; [ViewVariables] public UtensilType Types { get => _types; set { if (_types.Equals(value)) return; _types = value; } } /// /// The chance that the utensil has to break with each use. /// A value of 0 means that it is unbreakable. /// [ViewVariables] private float _breakChance; /// /// The sound to be played if the utensil breaks. /// [ViewVariables] private string? _breakSound; public void AddType(UtensilType type) { Types |= type; } public bool HasAnyType(UtensilType type) { return (_types & type) != UtensilType.None; } public bool HasType(UtensilType type) { return (_types & type) != 0; } public void RemoveType(UtensilType type) { Types &= ~type; } internal void TryBreak(IEntity user) { if (_breakSound != null && IoCManager.Resolve().Prob(_breakChance)) { EntitySystem.Get() .PlayFromEntity(_breakSound, user, AudioParams.Default.WithVolume(-2f)); Owner.Delete(); } } public override void ExposeData(ObjectSerializer serializer) { base.ExposeData(serializer); serializer.DataReadWriteFunction("types", new List(), types => types.ForEach(AddType), () => { var types = new List(); foreach (UtensilType type in Enum.GetValues(typeof(UtensilType))) { if ((Types & type) != 0) { types.Add(type); } } return types; }); serializer.DataField(ref _breakChance, "breakChance", 0); serializer.DataField(ref _breakSound, "breakSound", "/Audio/Items/snap.ogg"); } async Task IAfterInteract.AfterInteract(AfterInteractEventArgs eventArgs) { TryUseUtensil(eventArgs.User, eventArgs.Target); return true; } private void TryUseUtensil(IEntity user, IEntity? target) { if (target == null || !target.TryGetComponent(out FoodComponent? food)) { return; } if (!user.InRangeUnobstructed(target, popup: true)) { return; } food.TryUseFood(user, null, this); } } [Flags] public enum UtensilType : byte { None = 0, Fork = 1, Spoon = 1 << 1, Knife = 1 << 2 } }