Files
wwdpublic/Content.Shared/Sticky/Systems/StickySystem.cs
Will-Oliver-Br 07d2610a86 Port Medical Patches (#2185)
Port medical patches from
[Goob-Station](https://github.com/Goob-Station/Goob-Station).
Prs:
https://github.com/space-wizards/space-station-14/pull/30230
https://github.com/Goob-Station/Goob-Station/pull/493
https://github.com/Goob-Station/Goob-Station/pull/663
https://github.com/Goob-Station/Goob-Station/pull/1086
https://github.com/Goob-Station/Goob-Station/pull/1072
https://github.com/Goob-Station/Goob-Station/pull/1243
https://github.com/Goob-Station/Goob-Station/pull/1246
https://github.com/Goob-Station/Goob-Station/pull/1707

---

<details><summary><h1>Media</h1></summary>
<p>

![Captura de tela 2025-04-06
132934](https://github.com/user-attachments/assets/914fc728-b4cd-452f-9f71-1300d836895a)

</p>
</details>

---

🆑 deltanedas, jorgun, fishbait_x, Huffs-The-Frezone, Teapug, Speebr0,
CerberusWolfie, yglop, botanySupremist, Will-Oliver-Br
- add: Added medical patches
- add: Added a guidebook entry for medical patches.

---------

Signed-off-by: Will-Oliver-Br <164823659+Will-Oliver-Br@users.noreply.github.com>
Co-authored-by: deltanedas <39013340+deltanedas@users.noreply.github.com>
Co-authored-by: fishbait <gnesse@gmail.com>
Co-authored-by: unknown <Administrator@DESKTOP-PMRIVVA.kommune.indresogn.no>
Co-authored-by: Fishbait <Fishbait@git.ml>
Co-authored-by: Theapug <159912420+Teapug@users.noreply.github.com>
Co-authored-by: Speebro <100388782+Speebr0@users.noreply.github.com>
Co-authored-by: Speebro <speebro@notreal.com>
Co-authored-by: John Willis <143434770+CerberusWolfie@users.noreply.github.com>
Co-authored-by: yglop <95057024+yglop@users.noreply.github.com>
Co-authored-by: botanySupremist <160211017+botanySupremist@users.noreply.github.com>
Co-authored-by: botanySupremist <definitelyrealBotSupremist@gmail.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
2025-07-20 13:21:18 +10:00

223 lines
7.5 KiB
C#

using Content.Shared.DoAfter;
using Content.Shared.Hands.EntitySystems;
using Content.Shared.Interaction;
using Content.Shared.Popups;
using Content.Shared.Sticky.Components;
using Content.Shared.Verbs;
using Content.Shared.Whitelist;
using Robust.Shared.Containers;
using Content.Shared.Interaction.Components;
namespace Content.Shared.Sticky.Systems;
public sealed class StickySystem : EntitySystem
{
[Dependency] private readonly EntityWhitelistSystem _whitelist = default!;
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
[Dependency] private readonly SharedContainerSystem _container = default!;
[Dependency] private readonly SharedDoAfterSystem _doAfter = default!;
[Dependency] private readonly SharedHandsSystem _hands = default!;
[Dependency] private readonly SharedInteractionSystem _interaction = default!;
[Dependency] private readonly SharedPopupSystem _popup = default!;
private const string StickerSlotId = "stickers_container";
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<StickyComponent, AfterInteractEvent>(OnAfterInteract);
SubscribeLocalEvent<StickyComponent, StickyDoAfterEvent>(OnStickyDoAfter);
SubscribeLocalEvent<StickyComponent, GetVerbsEvent<Verb>>(OnGetVerbs);
}
private void OnAfterInteract(Entity<StickyComponent> ent, ref AfterInteractEvent args)
{
if (args.Handled || !args.CanReach || args.Target is not {} target)
return;
// try stick object to a clicked target entity
args.Handled = StartSticking(ent, target, args.User);
}
private void OnGetVerbs(Entity<StickyComponent> ent, ref GetVerbsEvent<Verb> args)
{
var (uid, comp) = ent;
if (comp.StuckTo == null || !comp.CanUnstick || !args.CanInteract || args.Hands == null)
return;
// we can't use args.CanAccess, because it stuck in another container
// we also need to ignore entity that it stuck to
var user = args.User;
var inRange = _interaction.InRangeUnobstructed(uid, user,
predicate: entity => comp.StuckTo == entity);
if (!inRange)
return;
args.Verbs.Add(new Verb
{
DoContactInteraction = true,
Text = Loc.GetString(comp.VerbText),
Icon = comp.VerbIcon,
Act = () => StartUnsticking(ent, user)
});
}
private bool StartSticking(Entity<StickyComponent> ent, EntityUid target, EntityUid user)
{
var (uid, comp) = ent;
// check whitelist and blacklist
if (_whitelist.IsWhitelistFail(comp.Whitelist, target) ||
_whitelist.IsBlacklistPass(comp.Blacklist, target))
return false;
var attemptEv = new AttemptEntityStickEvent(target, user);
RaiseLocalEvent(uid, ref attemptEv);
if (attemptEv.Cancelled)
return false;
// skip doafter and popup if it's instant
if (comp.StickDelay <= TimeSpan.Zero)
{
StickToEntity(ent, target, user);
return true;
}
// show message to user
if (comp.StickPopupStart != null)
{
var msg = Loc.GetString(comp.StickPopupStart);
_popup.PopupClient(msg, user, user);
}
// start sticking object to target
_doAfter.TryStartDoAfter(new DoAfterArgs(EntityManager, user, comp.StickDelay, new StickyDoAfterEvent(), uid, target: target, used: uid)
{
BreakOnMove = true,
NeedHand = true,
});
return true;
}
private void OnStickyDoAfter(Entity<StickyComponent> ent, ref StickyDoAfterEvent args)
{
// target is the sticky item when unsticking and the surface when sticking, it will never be null
if (args.Handled || args.Cancelled || args.Args.Target is not {} target)
return;
var user = args.User;
if (ent.Comp.StuckTo == null)
StickToEntity(ent, target, user);
else
UnstickFromEntity(ent, user);
args.Handled = true;
}
private void StartUnsticking(Entity<StickyComponent> ent, EntityUid user)
{
var (uid, comp) = ent;
if (comp.StuckTo is not {} stuckTo)
return;
var attemptEv = new AttemptEntityUnstickEvent(stuckTo, user);
RaiseLocalEvent(uid, ref attemptEv);
if (attemptEv.Cancelled)
return;
// skip doafter and popup if it's instant
if (comp.UnstickDelay <= TimeSpan.Zero)
{
UnstickFromEntity(ent, user);
return;
}
// show message to user
if (comp.UnstickPopupStart != null)
{
var msg = Loc.GetString(comp.UnstickPopupStart);
_popup.PopupClient(msg, user, user);
}
// start unsticking object
_doAfter.TryStartDoAfter(new DoAfterArgs(EntityManager, user, comp.UnstickDelay, new StickyDoAfterEvent(), uid, target: uid)
{
BreakOnMove = true,
NeedHand = true,
});
}
public void StickToEntity(Entity<StickyComponent> ent, EntityUid target, EntityUid user)
{
var (uid, comp) = ent;
var attemptEv = new AttemptEntityStickEvent(target, user);
RaiseLocalEvent(uid, ref attemptEv);
if (attemptEv.Cancelled)
return;
// add container to entity and insert sticker into it
var container = _container.EnsureContainer<Container>(target, StickerSlotId);
container.ShowContents = true;
if (!_container.Insert(uid, container))
return;
// show message to user
if (comp.StickPopupSuccess != null)
{
var msg = Loc.GetString(comp.StickPopupSuccess);
_popup.PopupClient(msg, user, user);
}
// send information to appearance that entity is stuck
_appearance.SetData(uid, StickyVisuals.IsStuck, true);
EnsureComp<UnremoveableComponent>(uid); //Goobstation - MedicalPatch
comp.StuckTo = target;
Dirty(uid, comp);
var ev = new EntityStuckEvent(target, user);
RaiseLocalEvent(uid, ref ev);
}
public void UnstickFromEntity(Entity<StickyComponent> ent, EntityUid user)
{
var (uid, comp) = ent;
if (comp.StuckTo is not {} stuckTo)
return;
var attemptEv = new AttemptEntityUnstickEvent(stuckTo, user);
RaiseLocalEvent(uid, ref attemptEv);
if (attemptEv.Cancelled)
return;
RemComp<UnremoveableComponent>(uid); //Goobstation - MedicalPatch
// try to remove sticky item from target container
if (!_container.TryGetContainer(stuckTo, StickerSlotId, out var container) || !_container.Remove(uid, container))
return;
// delete container if it's now empty
if (container.ContainedEntities.Count == 0)
_container.ShutdownContainer(container);
// try place dropped entity into user hands
_hands.PickupOrDrop(user, uid);
// send information to appearance that entity isn't stuck
_appearance.SetData(uid, StickyVisuals.IsStuck, false);
// show message to user
if (comp.UnstickPopupSuccess != null)
{
var msg = Loc.GetString(comp.UnstickPopupSuccess);
_popup.PopupClient(msg, user, user);
}
comp.StuckTo = null;
Dirty(uid, comp);
var ev = new EntityUnstuckEvent(stuckTo, user);
RaiseLocalEvent(uid, ref ev);
}
}