mirror of
https://github.com/space-syndicate/space-station-14.git
synced 2026-10-09 18:31:17 +03:00
212 lines
8.6 KiB
C#
212 lines
8.6 KiB
C#
using Content.Shared.Actions;
|
|
using Content.Shared.Body;
|
|
using Content.Shared.Corvax.Ipc;
|
|
using Content.Shared.Damage;
|
|
using Content.Shared.Damage.Systems;
|
|
using Content.Shared.Emp;
|
|
using Content.Shared.Humanoid;
|
|
using Content.Shared.Humanoid.Markings;
|
|
using Content.Shared.Mobs;
|
|
using Content.Shared.Movement.Systems;
|
|
using Content.Shared.Ninja.Components;
|
|
using Content.Shared.Ninja.Systems;
|
|
using Content.Shared.Popups;
|
|
using Content.Shared.Power.EntitySystems;
|
|
using Content.Shared.PowerCell;
|
|
using Content.Shared.Sound.Components;
|
|
using Robust.Shared.Audio;
|
|
using Robust.Shared.Player;
|
|
using Robust.Shared.Prototypes;
|
|
|
|
namespace Content.Server.Corvax.Ipc;
|
|
|
|
public sealed partial class IpcSystem : EntitySystem
|
|
{
|
|
[Dependency] private SharedActionsSystem _action = default!;
|
|
[Dependency] private SharedBatteryDrainerSystem _batteryDrainer = default!;
|
|
[Dependency] private SharedPopupSystem _popup = default!;
|
|
[Dependency] private PowerCellSystem _powerCell = default!;
|
|
[Dependency] private DamageableSystem _damageable = default!;
|
|
[Dependency] private MovementSpeedModifierSystem _movementSpeedModifier = default!;
|
|
[Dependency] private SharedUserInterfaceSystem _ui = default!;
|
|
[Dependency] private SharedBatterySystem _battery = default!;
|
|
[Dependency] private SharedVisualBodySystem _visualBody = default!;
|
|
[Dependency] private IPrototypeManager _prototype = default!;
|
|
public override void Initialize()
|
|
{
|
|
base.Initialize();
|
|
|
|
SubscribeLocalEvent<IpcComponent, MapInitEvent>(OnMapInit);
|
|
SubscribeLocalEvent<IpcComponent, ComponentShutdown>(OnComponentShutdown);
|
|
SubscribeLocalEvent<IpcComponent, PowerCellChangedEvent>(OnPowerCellChanged);
|
|
SubscribeLocalEvent<IpcComponent, ToggleDrainActionEvent>(OnToggleAction);
|
|
SubscribeLocalEvent<IpcComponent, EmpPulseEvent>(OnEmpPulse);
|
|
SubscribeLocalEvent<IpcComponent, RefreshMovementSpeedModifiersEvent>(OnRefreshMovementSpeedModifiers);
|
|
SubscribeLocalEvent<IpcComponent, MobStateChangedEvent>(OnMobStateChanged);
|
|
SubscribeLocalEvent<IpcComponent, OpenIpcFaceActionEvent>(OnOpenFaceAction);
|
|
Subs.BuiEvents<IpcComponent>(IpcFaceUiKey.Face, subs =>
|
|
{
|
|
subs.Event<IpcFaceSelectMessage>(OnFaceSelected);
|
|
});
|
|
SubscribeLocalEvent<IpcComponent, PowerCellSlotEmptyEvent>(OnPowerCellEmpty);
|
|
}
|
|
public override void Update(float frameTime)
|
|
{
|
|
base.Update(frameTime);
|
|
var query = EntityQueryEnumerator<IpcComponent>();
|
|
while (query.MoveNext(out var uid, out var comp))
|
|
{
|
|
if (!comp.IsSlowedByBattery)
|
|
continue;
|
|
if (_powerCell.TryGetBatteryFromSlot(uid, out var battery)
|
|
&& _battery.GetCharge(battery.Value.AsNullable()) / battery.Value.Comp.MaxCharge >= 0.01f)
|
|
{
|
|
comp.IsSlowedByBattery = false;
|
|
_movementSpeedModifier.RefreshMovementSpeedModifiers(uid);
|
|
}
|
|
}
|
|
}
|
|
private void OnPowerCellEmpty(EntityUid uid, IpcComponent component, ref PowerCellSlotEmptyEvent args)
|
|
{
|
|
UpdateBatteryAlert((uid, component));
|
|
}
|
|
private void OnMapInit(EntityUid uid, IpcComponent component, MapInitEvent args)
|
|
{
|
|
UpdateBatteryAlert((uid, component));
|
|
_action.AddAction(uid, ref component.ActionEntity, component.DrainBatteryAction);
|
|
_action.AddAction(uid, ref component.ChangeFaceActionEntity, component.ChangeFaceAction);
|
|
_movementSpeedModifier.RefreshMovementSpeedModifiers(uid);
|
|
|
|
if (!HasComp<VisualBodyComponent>(uid))
|
|
return;
|
|
if (_visualBody.TryGatherMarkingsData(uid, null, out _, out _, out var applied)
|
|
&& applied.TryGetValue("Head", out var headMarkings)
|
|
&& headMarkings.TryGetValue(HumanoidVisualLayers.Snout, out var snoutMarkings)
|
|
&& snoutMarkings.Count > 0)
|
|
{
|
|
component.SelectedFace = snoutMarkings[0].MarkingId;
|
|
Dirty(uid, component);
|
|
}
|
|
}
|
|
private void OnComponentShutdown(EntityUid uid, IpcComponent component, ComponentShutdown args)
|
|
{
|
|
_action.RemoveAction(uid, component.ActionEntity);
|
|
_action.RemoveAction(uid, component.ChangeFaceActionEntity);
|
|
}
|
|
private void OnPowerCellChanged(EntityUid uid, IpcComponent component, ref PowerCellChangedEvent args)
|
|
{
|
|
if (MetaData(uid).EntityLifeStage >= EntityLifeStage.Terminating)
|
|
return;
|
|
|
|
UpdateBatteryAlert((uid, component));
|
|
}
|
|
private void OnToggleAction(EntityUid uid, IpcComponent component, ToggleDrainActionEvent args)
|
|
{
|
|
if (args.Handled)
|
|
return;
|
|
|
|
component.DrainActivated = !component.DrainActivated;
|
|
_action.SetToggled(component.ActionEntity, component.DrainActivated);
|
|
args.Handled = true;
|
|
|
|
if (component.DrainActivated && _powerCell.TryGetBatteryFromSlot(uid, out var battery))
|
|
{
|
|
EnsureComp<BatteryDrainerComponent>(uid);
|
|
_batteryDrainer.SetBattery(uid, battery.Value.Owner);
|
|
}
|
|
else
|
|
RemComp<BatteryDrainerComponent>(uid);
|
|
|
|
var message = component.DrainActivated ? "ipc-component-ready" : "ipc-component-disabled";
|
|
_popup.PopupEntity(Loc.GetString(message), uid, uid);
|
|
}
|
|
private void UpdateBatteryAlert(Entity<IpcComponent> ent)
|
|
{
|
|
_movementSpeedModifier.RefreshMovementSpeedModifiers(ent.Owner);
|
|
}
|
|
private void OnRefreshMovementSpeedModifiers(EntityUid uid, IpcComponent comp, RefreshMovementSpeedModifiersEvent args)
|
|
{
|
|
if (!_powerCell.TryGetBatteryFromSlot(uid, out var battery)
|
|
|| battery.Value.Comp.MaxCharge <= 0
|
|
|| _battery.GetCharge(battery.Value.AsNullable()) / battery.Value.Comp.MaxCharge < 0.01f)
|
|
{
|
|
args.ModifySpeed(0.2f);
|
|
comp.IsSlowedByBattery = true;
|
|
}
|
|
else
|
|
{
|
|
comp.IsSlowedByBattery = false;
|
|
}
|
|
}
|
|
private void OnOpenFaceAction(EntityUid uid, IpcComponent comp, OpenIpcFaceActionEvent args)
|
|
{
|
|
if (args.Handled)
|
|
return;
|
|
|
|
if (!TryComp<ActorComponent>(uid, out var actor))
|
|
return;
|
|
|
|
_ui.SetUiState(uid, IpcFaceUiKey.Face, new IpcFaceBuiState(comp.FaceProfile, comp.SelectedFace));
|
|
_ui.TryToggleUi(uid, IpcFaceUiKey.Face, actor.PlayerSession);
|
|
args.Handled = true;
|
|
}
|
|
private void OnFaceSelected(Entity<IpcComponent> ent, ref IpcFaceSelectMessage msg)
|
|
{
|
|
if (!_prototype.TryIndex<IpcFaceProfilePrototype>(ent.Comp.FaceProfile, out var faceProfile)
|
|
|| !faceProfile.Faces.Contains(msg.State))
|
|
return;
|
|
if (_visualBody.TryGatherMarkingsData(ent.Owner, null, out var profiles, out var markings, out var applied))
|
|
{
|
|
if (applied.TryGetValue("Head", out var headMarkings)
|
|
&& headMarkings.TryGetValue(HumanoidVisualLayers.Snout, out var snoutMarkings)
|
|
&& snoutMarkings.Count > 0)
|
|
{
|
|
_visualBody.ApplyMarkings(ent.Owner, new()
|
|
{
|
|
["Head"] = new()
|
|
{
|
|
[HumanoidVisualLayers.Snout] = new List<Marking>() { new(msg.State, snoutMarkings[0].MarkingColors.Count) },
|
|
},
|
|
});
|
|
}
|
|
else if (_prototype.TryIndex<MarkingPrototype>(msg.State, out var proto))
|
|
{
|
|
_visualBody.ApplyMarkings(ent.Owner, new()
|
|
{
|
|
["Head"] = new()
|
|
{
|
|
[HumanoidVisualLayers.Snout] = new List<Marking>() { proto.AsMarking() },
|
|
},
|
|
});
|
|
}
|
|
}
|
|
|
|
ent.Comp.SelectedFace = msg.State;
|
|
Dirty(ent);
|
|
_ui.CloseUi(ent.Owner, IpcFaceUiKey.Face);
|
|
}
|
|
private void OnEmpPulse(EntityUid uid, IpcComponent component, ref EmpPulseEvent args)
|
|
{
|
|
args.Affected = true;
|
|
|
|
var damage = new DamageSpecifier();
|
|
damage.DamageDict.Add("Shock", 30);
|
|
_damageable.TryChangeDamage(uid, damage);
|
|
}
|
|
private void OnMobStateChanged(EntityUid uid, IpcComponent component, ref MobStateChangedEvent args)
|
|
{
|
|
if (args.NewMobState == MobState.Critical)
|
|
{
|
|
var sound = EnsureComp<SpamEmitSoundComponent>(uid);
|
|
sound.Sound = new SoundPathSpecifier("/Audio/Machines/buzz-two.ogg");
|
|
sound.MinInterval = TimeSpan.FromSeconds(15);
|
|
sound.MaxInterval = TimeSpan.FromSeconds(30);
|
|
sound.PopUp = Loc.GetString("sleep-ipc");
|
|
Dirty(uid, sound);
|
|
}
|
|
else
|
|
{
|
|
RemComp<SpamEmitSoundComponent>(uid);
|
|
}
|
|
}
|
|
}
|