CatStation/Content.Shared/Nutrition/EntitySystems/IngestionSystem.Blockers.cs
Astroskier ed47026296
Foldable Light Riot Helmet (#44851)
* Foldable Visor Test

* Minor edit

* WIP Eating Enabling

* Food working

* Pre-Pull

* Pre-Pull 2 Electric Boogaloo

* This icon will be the death of me

* Small edit

* Fixed icon and touched up srpites

* Delete git status

I have no clue how that got there.

* Removed Whitespace

* Addressed Comment

* Moved Tags

(Same placement as #Basic Helmet

* Updated Credit

Should this be changed it "visor- prefixed .pngs by Astroskier"? Seems a bit wordy for what it's trying to say.

* Removes duplicate tags

* Deleting files before replacement

* Delete Resources/Textures/Clothing/Head/Helmets/light_riot.rsi/visor-equipped-HELMET.png

* Delete Resources/Textures/Clothing/Head/Helmets/light_riot.rsi/visor-icon.png

* Delete Resources/Textures/Clothing/Head/Helmets/light_riot.rsi/visor-inhand-left.png

* Delete Resources/Textures/Clothing/Head/Helmets/light_riot.rsi/visor-inhand-right.png

* Redone Sprites

* DELETE THE ONE GOD DMAN SPRITE INCONSISTENCY LEFT

* FIXED THE FINAL SPRITE INCONSISTENCY

Finally.

* cleanup

* Copyright fix

Co-authored-by: Whatstone <166147148+whatston3@users.noreply.github.com>

* Resolved comment

* Touched up sprites

(Added visor view to south face)

---------

Co-authored-by: beck-thompson <beck314159@hotmail.com>
Co-authored-by: Whatstone <166147148+whatston3@users.noreply.github.com>
2026-08-16 02:13:49 +00:00

171 lines
6 KiB
C#

using System.Linq;
using Content.Shared.Chemistry.Components;
using Content.Shared.Clothing;
using Content.Shared.Containers.ItemSlots;
using Content.Shared.Fluids.Components;
using Content.Shared.Foldable;
using Content.Shared.Interaction.Components;
using Content.Shared.Inventory;
using Content.Shared.Nutrition.Components;
using Content.Shared.Storage;
namespace Content.Shared.Nutrition.EntitySystems;
public sealed partial class IngestionSystem
{
[Dependency] private OpenableSystem _openable = default!;
public void InitializeBlockers()
{
SubscribeLocalEvent<UnremoveableComponent, IngestibleEvent>(OnUnremovableIngestion);
SubscribeLocalEvent<IngestionBlockerComponent, ItemMaskToggledEvent>(OnBlockerMaskToggled);
SubscribeLocalEvent<IngestionBlockerComponent, FoldedEvent>(OnBlockerFolded);
SubscribeLocalEvent<IngestionBlockerComponent, IngestionAttemptEvent>(OnIngestionBlockerAttempt);
SubscribeLocalEvent<IngestionBlockerComponent, InventoryRelayedEvent<IngestionAttemptEvent>>(OnIngestionBlockerAttempt);
// Edible Event
SubscribeLocalEvent<EdibleComponent, EdibleEvent>(OnEdible);
SubscribeLocalEvent<StorageComponent, EdibleEvent>(OnStorageEdible);
SubscribeLocalEvent<ItemSlotsComponent, EdibleEvent>(OnItemSlotsEdible);
SubscribeLocalEvent<OpenableComponent, EdibleEvent>(OnOpenableEdible);
// Digestion Events
SubscribeLocalEvent<EdibleComponent, IsDigestibleEvent>(OnEdibleIsDigestible);
SubscribeLocalEvent<DrainableSolutionComponent, IsDigestibleEvent>(OnDrainableIsDigestible);
SubscribeLocalEvent<PuddleComponent, IsDigestibleEvent>(OnPuddleIsDigestible);
SubscribeLocalEvent<PillComponent, BeforeIngestedEvent>(OnPillBeforeEaten);
}
private void OnUnremovableIngestion(Entity<UnremoveableComponent> entity, ref IngestibleEvent args)
{
// If we can't remove it we probably shouldn't be able to eat it.
// TODO: Separate glue and Unremovable component.
args.Cancelled = true;
}
private void OnBlockerMaskToggled(Entity<IngestionBlockerComponent> entity, ref ItemMaskToggledEvent args)
{
entity.Comp.Enabled = !args.Mask.Comp.IsToggled;
Dirty(entity);
}
private void OnBlockerFolded(Entity<IngestionBlockerComponent> entity, ref FoldedEvent args)
{
entity.Comp.Enabled = !args.IsFolded;
Dirty(entity);
}
private void OnIngestionBlockerAttempt(Entity<IngestionBlockerComponent> entity, ref IngestionAttemptEvent args)
{
if (!args.Cancelled && entity.Comp.Enabled)
args.Cancelled = true;
}
/// <summary>
/// Block ingestion attempts based on the equipped mask or head-wear
/// </summary>
private void OnIngestionBlockerAttempt(Entity<IngestionBlockerComponent> entity, ref InventoryRelayedEvent<IngestionAttemptEvent> args)
{
if (args.Args.Cancelled || !entity.Comp.Enabled)
return;
args.Args.Cancelled = true;
args.Args.Blocker = entity;
}
private void OnEdible(Entity<EdibleComponent> entity, ref EdibleEvent args)
{
if (args.Cancelled || args.Solution != null)
return;
if (entity.Comp.UtensilRequired && !HasRequiredUtensils(args.User, entity.Comp.Utensil))
{
args.Cancelled = true;
return;
}
// Check this last
if (!_solutionContainer.TryGetSolution(entity.Owner, entity.Comp.Solution, out args.Solution) || IsEmpty(entity) && !entity.Comp.DestroyOnEmpty)
{
args.Cancelled = true;
_popup.PopupEntity(Loc.GetString("ingestion-try-use-is-empty", ("entity", entity)), entity, args.User);
return;
}
// Time is additive because I said so.
args.Time += entity.Comp.Delay;
}
private void OnStorageEdible(Entity<StorageComponent> ent, ref EdibleEvent args)
{
if (args.Cancelled)
return;
if (!ent.Comp.Container.ContainedEntities.Any())
return;
args.Cancelled = true;
_popup.PopupEntity(Loc.GetString("edible-has-used-storage", ("food", ent), ("verb", GetEdibleVerb(ent.Owner))), args.User, args.User);
}
private void OnItemSlotsEdible(Entity<ItemSlotsComponent> ent, ref EdibleEvent args)
{
if (args.Cancelled)
return;
if (!ent.Comp.Slots.Any(slot => slot.Value.HasItem))
return;
args.Cancelled = true;
_popup.PopupEntity(Loc.GetString("edible-has-used-storage", ("food", ent), ("verb", GetEdibleVerb(ent.Owner))), args.User, args.User);
}
private void OnOpenableEdible(Entity<OpenableComponent> ent, ref EdibleEvent args)
{
if (args.Cancelled)
return;
if (_openable.IsClosed(ent, args.User, ent.Comp, predicted: true))
args.Cancelled = true;
}
private void OnEdibleIsDigestible(Entity<EdibleComponent> ent, ref IsDigestibleEvent args)
{
if (ent.Comp.RequireDead && _mobState.IsAlive(ent))
return;
args.AddDigestible(ent.Comp.RequiresSpecialDigestion);
}
/// <remarks>
/// Both of these assume that having this component means there's nothing stopping you from slurping up
/// pure reagent juice with absolutely nothing to stop you.
/// </remarks>
private void OnDrainableIsDigestible(Entity<DrainableSolutionComponent> ent, ref IsDigestibleEvent args)
{
args.UniversalDigestion();
}
private void OnPuddleIsDigestible(Entity<PuddleComponent> ent, ref IsDigestibleEvent args)
{
args.UniversalDigestion();
}
/// <remarks>
/// I mean you have to eat the *whole* pill no?
/// </remarks>
private void OnPillBeforeEaten(Entity<PillComponent> ent, ref BeforeIngestedEvent args)
{
if (args.Cancelled || args.Solution is not { } sol)
return;
if (args.TryNewMinimum(sol.Volume))
return;
args.Cancelled = true;
}
}