using Content.Server.Fluids.EntitySystems;
using Content.Server.Forensics.Components;
using Content.Server.Popups;
+using Content.Shared.Popups;
using Content.Shared.Chemistry.Components;
using Content.Shared.DoAfter;
using Content.Shared.Forensics;
using Content.Shared.Inventory;
using Content.Shared.Weapons.Melee.Events;
using Robust.Shared.Random;
+using Content.Shared.Verbs;
namespace Content.Server.Forensics
{
SubscribeLocalEvent<CleansForensicsComponent, AfterInteractEvent>(OnAfterInteract, after: new[] { typeof(AbsorbentSystem) });
SubscribeLocalEvent<ForensicsComponent, CleanForensicsDoAfterEvent>(OnCleanForensicsDoAfter);
SubscribeLocalEvent<DnaComponent, TransferDnaEvent>(OnTransferDnaEvent);
+ SubscribeLocalEvent<CleansForensicsComponent, GetVerbsEvent<UtilityVerb>>(OnUtilityVerb);
+
}
private void OnInteract(EntityUid uid, FingerprintComponent component, ContactInteractionEvent args)
private void OnBeingGibbed(EntityUid uid, DnaComponent component, BeingGibbedEvent args)
{
- foreach(EntityUid part in args.GibbedParts)
+ foreach (EntityUid part in args.GibbedParts)
{
var partComp = EnsureComp<ForensicsComponent>(part);
partComp.DNAs.Add(component.DNA);
private void OnMeleeHit(EntityUid uid, ForensicsComponent component, MeleeHitEvent args)
{
- if((args.BaseDamage.DamageDict.TryGetValue("Blunt", out var bluntDamage) && bluntDamage.Value > 0) ||
+ if ((args.BaseDamage.DamageDict.TryGetValue("Blunt", out var bluntDamage) && bluntDamage.Value > 0) ||
(args.BaseDamage.DamageDict.TryGetValue("Slash", out var slashDamage) && slashDamage.Value > 0) ||
(args.BaseDamage.DamageDict.TryGetValue("Piercing", out var pierceDamage) && pierceDamage.Value > 0))
{
- foreach(EntityUid hitEntity in args.HitEntities)
+ foreach (EntityUid hitEntity in args.HitEntities)
{
- if(TryComp<DnaComponent>(hitEntity, out var hitEntityComp))
+ if (TryComp<DnaComponent>(hitEntity, out var hitEntityComp))
component.DNAs.Add(hitEntityComp.DNA);
}
}
}
}
- private void OnAfterInteract(EntityUid uid, CleansForensicsComponent component, AfterInteractEvent args)
+ private void OnAfterInteract(Entity<CleansForensicsComponent> cleanForensicsEntity, ref AfterInteractEvent args)
{
- if (args.Handled || !args.CanReach)
+ if (args.Handled || !args.CanReach || args.Target == null)
return;
- if (!TryComp<ForensicsComponent>(args.Target, out var forensicsComp))
+ args.Handled = TryStartCleaning(cleanForensicsEntity, args.User, args.Target.Value);
+ }
+
+ private void OnUtilityVerb(Entity<CleansForensicsComponent> entity, ref GetVerbsEvent<UtilityVerb> args)
+ {
+ if (!args.CanInteract || !args.CanAccess)
return;
- if((forensicsComp.DNAs.Count > 0 && forensicsComp.CanDnaBeCleaned) || (forensicsComp.Fingerprints.Count + forensicsComp.Fibers.Count > 0))
+ // These need to be set outside for the anonymous method!
+ var user = args.User;
+ var target = args.Target;
+
+ var verb = new UtilityVerb()
{
- var doAfterArgs = new DoAfterArgs(EntityManager, args.User, component.CleanDelay, new CleanForensicsDoAfterEvent(), uid, target: args.Target, used: args.Used)
+ Act = () => TryStartCleaning(entity, user, target),
+ IconEntity = GetNetEntity(entity),
+ Text = Loc.GetString(Loc.GetString("forensics-verb-text")),
+ Message = Loc.GetString(Loc.GetString("forensics-verb-message")),
+ // This is important because if its true using the cleaning device will count as touching the object.
+ DoContactInteraction = false
+ };
+
+ args.Verbs.Add(verb);
+ }
+
+ /// <summary>
+ /// Attempts to clean the given item with the given CleansForensics entity.
+ /// </summary>
+ /// <param name="cleanForensicsEntity">The entity that is being used to clean the target.</param>
+ /// <param name="user">The user that is using the cleanForensicsEntity.</param>
+ /// <param name="target">The target of the forensics clean.</param>
+ /// <returns>True if the target can be cleaned and has some sort of DNA or fingerprints / fibers and false otherwise.</returns>
+ public bool TryStartCleaning(Entity<CleansForensicsComponent> cleanForensicsEntity, EntityUid user, EntityUid target)
+ {
+ if (!TryComp<ForensicsComponent>(target, out var forensicsComp))
+ {
+ _popupSystem.PopupEntity(Loc.GetString("forensics-cleaning-cannot-clean", ("target", target)), user, user, PopupType.MediumCaution);
+ return false;
+ }
+
+ var totalPrintsAndFibers = forensicsComp.Fingerprints.Count + forensicsComp.Fibers.Count;
+ var hasRemovableDNA = forensicsComp.DNAs.Count > 0 && forensicsComp.CanDnaBeCleaned;
+
+ if (hasRemovableDNA || totalPrintsAndFibers > 0)
+ {
+ var cleanDelay = cleanForensicsEntity.Comp.CleanDelay;
+ var doAfterArgs = new DoAfterArgs(EntityManager, user, cleanDelay, new CleanForensicsDoAfterEvent(), cleanForensicsEntity, target: target, used: cleanForensicsEntity)
{
BreakOnHandChange = true,
NeedHand = true,
};
_doAfterSystem.TryStartDoAfter(doAfterArgs);
- _popupSystem.PopupEntity(Loc.GetString("forensics-cleaning", ("target", args.Target)), args.User, args.User);
- args.Handled = true;
+ _popupSystem.PopupEntity(Loc.GetString("forensics-cleaning", ("target", target)), user, user);
+
+ return true;
+ }
+ else
+ {
+ _popupSystem.PopupEntity(Loc.GetString("forensics-cleaning-cannot-clean", ("target", target)), user, user, PopupType.MediumCaution);
+ return false;
}
+
}
private void OnCleanForensicsDoAfter(EntityUid uid, ForensicsComponent component, CleanForensicsDoAfterEvent args)