Files
OldThink/Content.Server/_White/SelfHeal/SelfHealSystem.cs

183 lines
6.6 KiB
C#

using Content.Server.Administration.Logs;
using Content.Server.Nutrition.Components;
using Content.Server.Popups;
using Content.Shared.Actions;
using Content.Shared.Damage;
using Content.Shared.Database;
using Content.Shared.DoAfter;
using Content.Shared.Humanoid;
using Content.Shared.Interaction;
using Content.Shared.Inventory;
using Content.Shared._White.SelfHeal;
using Robust.Shared.Audio;
using Robust.Shared.Audio.Systems;
namespace Content.Server._White.SelfHeal;
public sealed class SelfHealSystem : EntitySystem
{
[Dependency] private readonly SharedAudioSystem _audio = default!;
[Dependency] private readonly IAdminLogManager _adminLogger = default!;
[Dependency] private readonly DamageableSystem _damageable = default!;
[Dependency] private readonly SharedDoAfterSystem _doAfter = default!;
[Dependency] private readonly SharedInteractionSystem _interactionSystem = default!;
[Dependency] private readonly PopupSystem _popupSystem = default!;
[Dependency] private readonly InventorySystem _inventorySystem = default!;
[Dependency] private readonly SharedActionsSystem _actionsSystem = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<SelfHealComponent, ComponentInit>(OnInit);
SubscribeLocalEvent<SelfHealComponent, SelfHealEvent>(OnHealingAfterInteract);
SubscribeLocalEvent<DamageableComponent, SelfHealDoAfterEvent>(OnDoAfter);
}
private void OnInit(EntityUid uid, SelfHealComponent component, ComponentInit args)
{
_actionsSystem.AddAction(uid, ref component.ActionEntity, component.Action);
}
private void OnHealingAfterInteract(EntityUid uid, SelfHealComponent component, SelfHealEvent args)
{
if (args.Handled)
return;
TryHeal(args.Performer, args.Target, component);
args.Handled = true;
}
private void OnDoAfter(EntityUid uid, DamageableComponent component, SelfHealDoAfterEvent args)
{
if (!TryComp(args.User, out SelfHealComponent? healing) || args.Target == null)
return;
if (args.Handled || args.Cancelled)
return;
if (healing.DamageContainers is not null
&& component.DamageContainerID is not null
&& !healing.DamageContainers.Contains(component.DamageContainerID))
{
return;
}
if (!CanHeal(args.User, args.Target.Value, healing))
return;
Heal(args.Target.Value, healing, args);
// Logic to determine the whether or not to repeat the healing action
args.Repeat = HasDamage(component, healing);
if (!args.Repeat)
_popupSystem.PopupEntity(Loc.GetString("self-heal-finished-using", ("name", uid)), uid, args.User);
args.Handled = true;
}
private void Heal(EntityUid uid, SelfHealComponent component, SelfHealDoAfterEvent args)
{
var healed = _damageable.TryChangeDamage(uid, component.Damage, true, origin: args.Args.User);
if (healed == null)
return;
var total = healed.GetTotal();
var userString = EntityManager.ToPrettyString(args.User);
var targetString = EntityManager.ToPrettyString(uid);
var healMessage = uid != args.User
? $"{userString:user} healed {targetString:target} for {total:damage} by licking"
: $"{userString:user} healed themselves for {total:damage} by licking";
_adminLogger.Add(LogType.Healed, $"{healMessage}");
if (TryComp<SelfHealComponent>(args.User, out var selfHealComponent))
{
var audio = selfHealComponent.HealingSound;
var audioParams = new AudioParams().WithVariation(2f).WithVolume(-5f);
_audio.PlayPvs(audio, args.User, audioParams);
_popupSystem.PopupEntity(Loc.GetString("self-heal-using-other", ("user", args.Args.User), ("target", uid)),
uid);
}
}
private bool CanHeal(EntityUid user, EntityUid target, SelfHealComponent component)
{
if (!TryComp<DamageableComponent>(target, out var targetDamage) ||
!HasComp<HumanoidAppearanceComponent>(target))
return false;
if (user != target && !_interactionSystem.InRangeUnobstructed(user, target, popup: true))
return false;
if (!HasDamage(targetDamage, component))
{
var popup = Loc.GetString("self-heal-cant-use", ("name", target));
_popupSystem.PopupEntity(popup, user, user);
return false;
}
if (component.DisallowedClothingUser != null)
{
foreach (var clothing in component.DisallowedClothingUser)
{
if (_inventorySystem.TryGetSlotEntity(user, clothing, out var blockedClothing) &&
EntityManager.TryGetComponent<IngestionBlockerComponent>(blockedClothing, out var blocker) &&
blocker.Enabled)
{
var popup = Loc.GetString("self-heal-cant-use-clothing", ("clothing", blockedClothing));
_popupSystem.PopupEntity(popup, user, user);
return false;
}
}
}
if (component.DisallowedClothingTarget != null)
{
foreach (var clothing in component.DisallowedClothingTarget)
{
if (_inventorySystem.TryGetSlotEntity(target, clothing, out var blockedClothing))
{
var popup = Loc.GetString("self-heal-cant-use-clothing-other", ("name", target),
("clothing", blockedClothing));
_popupSystem.PopupEntity(popup, user, user);
return false;
}
}
}
return true;
}
private void TryHeal(EntityUid user, EntityUid target, SelfHealComponent component)
{
if (!CanHeal(user, target, component))
return;
var doAfterEventArgs =
new DoAfterArgs(EntityManager, user, component.Delay, new SelfHealDoAfterEvent(), target, target)
{
BreakOnMove = true,
BreakOnDamage = true,
};
_doAfter.TryStartDoAfter(doAfterEventArgs);
}
private bool HasDamage(DamageableComponent component, SelfHealComponent healing)
{
var damageableDict = component.Damage.DamageDict;
var healingDict = healing.Damage.DamageDict;
foreach (var type in healingDict)
{
if (damageableDict[type.Key].Value > 0)
return true;
}
return false;
}
}