From d7c79c414a48ba2cf5b4e26d999b69149bdfce67 Mon Sep 17 00:00:00 2001 From: Dmitry <57028746+DIMMoon1@users.noreply.github.com> Date: Mon, 23 Mar 2026 08:09:27 +0700 Subject: [PATCH] ipc super fix --- Content.Client/Corvax/Ipc/IpcSystem.cs | 80 ++++++++++++++++++ Content.Server/Corvax/Ipc/IpcSystem.cs | 98 ++++++++++++----------- Content.Shared/Corvax/Ipc/IpcComponent.cs | 5 +- 3 files changed, 134 insertions(+), 49 deletions(-) create mode 100644 Content.Client/Corvax/Ipc/IpcSystem.cs diff --git a/Content.Client/Corvax/Ipc/IpcSystem.cs b/Content.Client/Corvax/Ipc/IpcSystem.cs new file mode 100644 index 0000000000..b652c7e308 --- /dev/null +++ b/Content.Client/Corvax/Ipc/IpcSystem.cs @@ -0,0 +1,80 @@ +using Content.Shared.Alert; +using Content.Shared.Corvax.Ipc; +using Content.Shared.Power.EntitySystems; +using Content.Shared.PowerCell; +using Robust.Client.Player; +using Robust.Shared.Player; +using Robust.Shared.Timing; + +namespace Content.Client.Corvax.Ipc; +public sealed class IpcSystem : EntitySystem +{ + [Dependency] private readonly PowerCellSystem _powerCell = default!; + [Dependency] private readonly SharedBatterySystem _battery = default!; + [Dependency] private readonly AlertsSystem _alerts = default!; + [Dependency] private readonly IGameTiming _timing = default!; + [Dependency] private readonly IPlayerManager _player = default!; + private static readonly TimeSpan AlertUpdateDelay = TimeSpan.FromSeconds(0.5f); + private TimeSpan _nextAlertUpdate = TimeSpan.Zero; + private EntityQuery _ipcQuery; + public override void Initialize() + { + base.Initialize(); + _ipcQuery = GetEntityQuery(); + SubscribeLocalEvent(OnPlayerAttached); + SubscribeLocalEvent(OnPlayerDetached); + + SubscribeLocalEvent(OnPowerCellChanged); + SubscribeLocalEvent(OnPowerCellEmpty); + } + private void OnPowerCellChanged(EntityUid uid, IpcComponent component, ref PowerCellChangedEvent args) + { + if (_player.LocalEntity != uid) + return; + UpdateBatteryAlert((uid, component)); + } + private void OnPowerCellEmpty(EntityUid uid, IpcComponent component, ref PowerCellSlotEmptyEvent args) + { + if (_player.LocalEntity != uid) + return; + UpdateBatteryAlert((uid, component)); + } + private void OnPlayerAttached(Entity ent, ref LocalPlayerAttachedEvent args) + { + UpdateBatteryAlert(ent); + } + private void OnPlayerDetached(Entity ent, ref LocalPlayerDetachedEvent args) + { + _alerts.ClearAlert(ent.Owner, ent.Comp.BatteryAlert); + _alerts.ClearAlert(ent.Owner, ent.Comp.NoBatteryAlert); + } + private void UpdateBatteryAlert(Entity ent) + { + if (!_powerCell.TryGetBatteryFromSlot(ent.Owner, out var battery) + || _battery.GetCharge(battery.Value.AsNullable()) / battery.Value.Comp.MaxCharge < 0.01f) + { + _alerts.ClearAlert(ent.Owner, ent.Comp.BatteryAlert); + _alerts.ShowAlert(ent.Owner, ent.Comp.NoBatteryAlert); + return; + } + var chargePercent = (short)MathF.Round( + _battery.GetCharge(battery.Value.AsNullable()) / battery.Value.Comp.MaxCharge * 10f); + if (chargePercent == 0 && _powerCell.HasDrawCharge(ent.Owner)) + chargePercent = 1; + _alerts.ClearAlert(ent.Owner, ent.Comp.NoBatteryAlert); + _alerts.ShowAlert(ent.Owner, ent.Comp.BatteryAlert, chargePercent); + } + public override void Update(float frameTime) + { + base.Update(frameTime); + if (_player.LocalEntity is not { } localPlayer) + return; + var curTime = _timing.CurTime; + if (curTime < _nextAlertUpdate) + return; + _nextAlertUpdate = curTime + AlertUpdateDelay; + if (!_ipcQuery.TryComp(localPlayer, out var ipc)) + return; + UpdateBatteryAlert((localPlayer, ipc)); + } +} diff --git a/Content.Server/Corvax/Ipc/IpcSystem.cs b/Content.Server/Corvax/Ipc/IpcSystem.cs index 8ab9166277..6324ba3d99 100644 --- a/Content.Server/Corvax/Ipc/IpcSystem.cs +++ b/Content.Server/Corvax/Ipc/IpcSystem.cs @@ -1,5 +1,4 @@ using Content.Shared.Actions; -using Content.Shared.Alert; using Content.Shared.Body; using Content.Shared.Corvax.Ipc; using Content.Shared.Damage; @@ -8,34 +7,31 @@ using Content.Shared.Emp; using Content.Shared.Humanoid; using Content.Shared.Humanoid.Markings; using Content.Shared.Mobs; -using Content.Shared.Mobs.Systems; using Content.Shared.Movement.Systems; using Content.Shared.Ninja.Components; using Content.Shared.Ninja.Systems; using Content.Shared.Popups; -using Content.Shared.Power; using Content.Shared.Power.EntitySystems; using Content.Shared.PowerCell; -using Content.Shared.PowerCell.Components; 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 readonly SharedActionsSystem _action = default!; - [Dependency] private readonly AlertsSystem _alerts = default!; [Dependency] private readonly SharedBatteryDrainerSystem _batteryDrainer = default!; [Dependency] private readonly SharedPopupSystem _popup = default!; [Dependency] private readonly PowerCellSystem _powerCell = default!; [Dependency] private readonly DamageableSystem _damageable = default!; [Dependency] private readonly MovementSpeedModifierSystem _movementSpeedModifier = default!; - [Dependency] private readonly MobStateSystem _mobState = default!; [Dependency] private readonly SharedUserInterfaceSystem _ui = default!; [Dependency] private readonly SharedBatterySystem _battery = default!; [Dependency] private readonly SharedVisualBodySystem _visualBody = default!; + [Dependency] private readonly IPrototypeManager _prototype = default!; public override void Initialize() { base.Initialize(); @@ -53,23 +49,27 @@ public sealed partial class IpcSystem : EntitySystem subs.Event(OnFaceSelected); }); SubscribeLocalEvent(OnPowerCellEmpty); - SubscribeLocalEvent(OnBatteryStateChanged); - SubscribeLocalEvent(OnChargeChanged); } - + public override void Update(float frameTime) + { + base.Update(frameTime); + var query = EntityQueryEnumerator(); + 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 OnBatteryStateChanged(EntityUid uid, IpcComponent component, ref BatteryStateChangedEvent args) - { - UpdateBatteryAlert((uid, component)); - } - private void OnChargeChanged(EntityUid uid, IpcComponent component, ref ChargeChangedEvent args) - { - UpdateBatteryAlert((uid, component)); - } - private void OnMapInit(EntityUid uid, IpcComponent component, MapInitEvent args) { UpdateBatteryAlert((uid, component)); @@ -77,23 +77,27 @@ public sealed partial class IpcSystem : EntitySystem _action.AddAction(uid, ref component.ChangeFaceActionEntity, component.ChangeFaceAction); _movementSpeedModifier.RefreshMovementSpeedModifiers(uid); + 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, PowerCellChangedEvent args) + 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) @@ -114,34 +118,23 @@ public sealed partial class IpcSystem : EntitySystem var message = component.DrainActivated ? "ipc-component-ready" : "ipc-component-disabled"; _popup.PopupEntity(Loc.GetString(message), uid, uid); } - private void UpdateBatteryAlert(Entity ent, PowerCellSlotComponent? slot = null) + private void UpdateBatteryAlert(Entity ent) { - if (!_powerCell.TryGetBatteryFromSlot(ent.Owner, out var battery) - || _battery.GetCharge(battery.Value.AsNullable()) / battery.Value.Comp.MaxCharge < 0.01f) - { - _alerts.ClearAlert(ent.Owner, ent.Comp.BatteryAlert); - _alerts.ShowAlert(ent.Owner, ent.Comp.NoBatteryAlert); - _movementSpeedModifier.RefreshMovementSpeedModifiers(ent.Owner); - return; - } - var chargePercent = (short)MathF.Round( - _battery.GetCharge(battery.Value.AsNullable()) / battery.Value.Comp.MaxCharge * 10f); - if (chargePercent == 0 && _powerCell.HasDrawCharge(ent.Owner)) - chargePercent = 1; - - _alerts.ClearAlert(ent.Owner, ent.Comp.NoBatteryAlert); - _alerts.ShowAlert(ent.Owner, ent.Comp.BatteryAlert, chargePercent); _movementSpeedModifier.RefreshMovementSpeedModifiers(ent.Owner); } - private void OnRefreshMovementSpeedModifiers(EntityUid uid, IpcComponent comp, RefreshMovementSpeedModifiersEvent args) { - if (!_powerCell.TryGetBatteryFromSlot(uid, out var battery) || _battery.GetCharge(battery.Value.AsNullable()) / battery.Value.Comp.MaxCharge < 0.01f) + if (!_powerCell.TryGetBatteryFromSlot(uid, out var battery) + || _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) @@ -154,12 +147,13 @@ public sealed partial class IpcSystem : EntitySystem _ui.TryToggleUi(uid, IpcFaceUiKey.Face, actor.PlayerSession); args.Handled = true; } - private void OnFaceSelected(Entity ent, ref IpcFaceSelectMessage msg) { 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)) + if (applied.TryGetValue("Head", out var headMarkings) + && headMarkings.TryGetValue(HumanoidVisualLayers.Snout, out var snoutMarkings) + && snoutMarkings.Count > 0) { _visualBody.ApplyMarkings(ent.Owner, new() { @@ -169,25 +163,33 @@ public sealed partial class IpcSystem : EntitySystem }, }); } + else if (_prototype.TryIndex(msg.State, out var proto)) + { + _visualBody.ApplyMarkings(ent.Owner, new() + { + ["Head"] = new() + { + [HumanoidVisualLayers.Snout] = new List() { 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);//ChangeDamage ? + _damageable.TryChangeDamage(uid, damage); } - private void OnMobStateChanged(EntityUid uid, IpcComponent component, ref MobStateChangedEvent args) { - if (_mobState.IsCritical(uid)) + if (args.NewMobState == MobState.Critical) { var sound = EnsureComp(uid); sound.Sound = new SoundPathSpecifier("/Audio/Machines/buzz-two.ogg"); diff --git a/Content.Shared/Corvax/Ipc/IpcComponent.cs b/Content.Shared/Corvax/Ipc/IpcComponent.cs index fe608332ed..a09df4d5fd 100644 --- a/Content.Shared/Corvax/Ipc/IpcComponent.cs +++ b/Content.Shared/Corvax/Ipc/IpcComponent.cs @@ -1,4 +1,4 @@ -using Content.Shared.Actions; +using Content.Shared.Actions; using Content.Shared.Alert; using Robust.Shared.GameStates; using Robust.Shared.Prototypes; @@ -36,6 +36,9 @@ public sealed partial class IpcComponent : Component [DataField, AutoNetworkedField] public ProtoId FaceProfile = "DefaultIpcFaces"; + [DataField] + public bool IsSlowedByBattery; + public bool DrainActivated; }