ipc super fix

This commit is contained in:
Dmitry 2026-03-23 08:09:27 +07:00
parent 9f97b146bc
commit d7c79c414a
3 changed files with 134 additions and 49 deletions

View file

@ -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<IpcComponent> _ipcQuery;
public override void Initialize()
{
base.Initialize();
_ipcQuery = GetEntityQuery<IpcComponent>();
SubscribeLocalEvent<IpcComponent, LocalPlayerAttachedEvent>(OnPlayerAttached);
SubscribeLocalEvent<IpcComponent, LocalPlayerDetachedEvent>(OnPlayerDetached);
SubscribeLocalEvent<IpcComponent, PowerCellChangedEvent>(OnPowerCellChanged);
SubscribeLocalEvent<IpcComponent, PowerCellSlotEmptyEvent>(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<IpcComponent> ent, ref LocalPlayerAttachedEvent args)
{
UpdateBatteryAlert(ent);
}
private void OnPlayerDetached(Entity<IpcComponent> ent, ref LocalPlayerDetachedEvent args)
{
_alerts.ClearAlert(ent.Owner, ent.Comp.BatteryAlert);
_alerts.ClearAlert(ent.Owner, ent.Comp.NoBatteryAlert);
}
private void UpdateBatteryAlert(Entity<IpcComponent> 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));
}
}

View file

@ -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<IpcFaceSelectMessage>(OnFaceSelected);
});
SubscribeLocalEvent<IpcComponent, PowerCellSlotEmptyEvent>(OnPowerCellEmpty);
SubscribeLocalEvent<IpcComponent, BatteryStateChangedEvent>(OnBatteryStateChanged);
SubscribeLocalEvent<IpcComponent, ChargeChangedEvent>(OnChargeChanged);
}
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 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<IpcComponent> ent, PowerCellSlotComponent? slot = null)
private void UpdateBatteryAlert(Entity<IpcComponent> 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<IpcComponent> 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<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);//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<SpamEmitSoundComponent>(uid);
sound.Sound = new SoundPathSpecifier("/Audio/Machines/buzz-two.ogg");

View file

@ -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<IpcFaceProfilePrototype> FaceProfile = "DefaultIpcFaces";
[DataField]
public bool IsSlowedByBattery;
public bool DrainActivated;
}