mirror of
https://github.com/space-syndicate/space-station-14.git
synced 2026-10-09 10:21:18 +03:00
* Scope creep my ass * why was this shit not pushed???? * gone... * fix that * review plus buildd * asfsafsafsafsafas * grug * burber * I'll fix this later * shrimply die * also this * it's snerf or snuthin * assaads * round snend * aaaa * fix this shit for real * actually, don't start GameRules until MapInit now that I think aboot it. * forgot u * don't actually need this part nullable * Deffer comp removal * one liner * do that too * chungus * Honestly makes more sense here, plus WHY are we doing all that shit on "GameRuleAdded" rather than GameRuleStarted(?) * deferred removal :V * aaaaaaaaaaaaaaa * whhop * Whoop * better * landmine that I placed for myself then forgot about lmao * cleanup * FUCKING `!` * gotovo * amogus * please don't check by metadata I beg * waawsasfdfsasfa * sfafsasfafsas * fdsaasffsasfa * code * fix * fasasffasfasfsad * chungaas * I may be stupid * gra * graaaaaaaaaaaaaaaaa * comment * gra * clearing is not predicted and would require major refactors, so don't cache on client. * lame shit :P * last holes * nukeopsfsafsasafsfafsa * why was that shit public bruh * bubrbgwahrghfaka * dynamic * revert change that did nothing lmao
234 lines
8.8 KiB
C#
234 lines
8.8 KiB
C#
using Content.Server.Audio;
|
|
using Content.Server.Light.Components;
|
|
using Content.Server.Power.Components;
|
|
using Content.Server.Power.EntitySystems;
|
|
using Content.Server.Station.Systems;
|
|
using Content.Shared.AlertLevel;
|
|
using Content.Shared.Examine;
|
|
using Content.Shared.Light;
|
|
using Content.Shared.Light.Components;
|
|
using Content.Shared.Power;
|
|
using Content.Shared.Power.Components;
|
|
using Content.Shared.Station.Components;
|
|
using Robust.Server.GameObjects;
|
|
using Color = Robust.Shared.Maths.Color;
|
|
|
|
namespace Content.Server.Light.EntitySystems;
|
|
|
|
public sealed partial class EmergencyLightSystem : SharedEmergencyLightSystem
|
|
{
|
|
[Dependency] private AmbientSoundSystem _ambient = default!;
|
|
[Dependency] private AlertLevelSystem _alert = default!;
|
|
[Dependency] private BatterySystem _battery = default!;
|
|
[Dependency] private PointLightSystem _pointLight = default!;
|
|
[Dependency] private SharedAppearanceSystem _appearance = default!;
|
|
[Dependency] private ServerStationSystem _station = default!;
|
|
|
|
public override void Initialize()
|
|
{
|
|
base.Initialize();
|
|
|
|
SubscribeLocalEvent<EmergencyLightComponent, EmergencyLightEvent>(OnEmergencyLightEvent);
|
|
SubscribeLocalEvent<AlertLevelChangedEvent>(OnAlertLevelChanged);
|
|
SubscribeLocalEvent<EmergencyLightComponent, ExaminedEvent>(OnEmergencyExamine);
|
|
SubscribeLocalEvent<EmergencyLightComponent, PowerChangedEvent>(OnEmergencyPower);
|
|
}
|
|
|
|
private void OnEmergencyPower(Entity<EmergencyLightComponent> entity, ref PowerChangedEvent args)
|
|
{
|
|
var meta = MetaData(entity.Owner);
|
|
|
|
// TODO: PowerChangedEvent shouldn't be issued for paused ents but this is the world we live in.
|
|
if (meta.EntityLifeStage >= EntityLifeStage.Terminating ||
|
|
meta.EntityPaused)
|
|
{
|
|
return;
|
|
}
|
|
|
|
UpdateState(entity);
|
|
}
|
|
|
|
private void OnEmergencyExamine(EntityUid uid, EmergencyLightComponent component, ExaminedEvent args)
|
|
{
|
|
using (args.PushGroup(nameof(EmergencyLightComponent)))
|
|
{
|
|
args.PushMarkup(
|
|
Loc.GetString("emergency-light-component-on-examine",
|
|
("batteryStateText",
|
|
Loc.GetString(component.BatteryStateText[component.State]))));
|
|
|
|
// Show alert level on the light itself.
|
|
if (_station.GetOwningStation(uid) is not { } station)
|
|
return;
|
|
|
|
if (!_alert.TryGetLevel(station, out var level)
|
|
|| !ProtoMan.Resolve(level, out var proto))
|
|
return;
|
|
|
|
args.PushMarkup(
|
|
Loc.GetString("emergency-light-component-on-examine-alert",
|
|
("color", proto.Color.ToHex()),
|
|
("level", proto.LocalizedName)));
|
|
}
|
|
}
|
|
|
|
private void OnEmergencyLightEvent(EntityUid uid, EmergencyLightComponent component, EmergencyLightEvent args)
|
|
{
|
|
switch (args.State)
|
|
{
|
|
case EmergencyLightState.On:
|
|
case EmergencyLightState.Charging:
|
|
EnsureComp<ActiveEmergencyLightComponent>(uid);
|
|
break;
|
|
case EmergencyLightState.Full:
|
|
case EmergencyLightState.Empty:
|
|
RemComp<ActiveEmergencyLightComponent>(uid);
|
|
break;
|
|
default:
|
|
throw new ArgumentOutOfRangeException();
|
|
}
|
|
}
|
|
|
|
private void OnAlertLevelChanged(ref AlertLevelChangedEvent ev)
|
|
{
|
|
if (!ProtoMan.Resolve(ev.AlertLevel, out var level))
|
|
return;
|
|
|
|
var query = EntityQueryEnumerator<EmergencyLightComponent, PointLightComponent, AppearanceComponent, TransformComponent>();
|
|
while (query.MoveNext(out var uid, out var light, out var pointLight, out var appearance, out var xform))
|
|
{
|
|
if (CompOrNull<StationMemberComponent>(xform.GridUid)?.Station != ev.Station)
|
|
continue;
|
|
|
|
_pointLight.SetColor(uid, level.EmergencyLightColor, pointLight);
|
|
_appearance.SetData(uid, EmergencyLightVisuals.Color, level.EmergencyLightColor, appearance);
|
|
|
|
if (level.ForceEnableEmergencyLights && !light.ForciblyEnabled)
|
|
{
|
|
light.ForciblyEnabled = true;
|
|
TurnOn((uid, light));
|
|
}
|
|
else if (!level.ForceEnableEmergencyLights && light.ForciblyEnabled)
|
|
{
|
|
// Previously forcibly enabled, and we went down an alert level.
|
|
light.ForciblyEnabled = false;
|
|
UpdateState((uid, light));
|
|
}
|
|
}
|
|
}
|
|
|
|
public void SetState(EntityUid uid, EmergencyLightComponent component, EmergencyLightState state)
|
|
{
|
|
if (component.State == state) return;
|
|
|
|
component.State = state;
|
|
RaiseLocalEvent(uid, new EmergencyLightEvent(state));
|
|
}
|
|
|
|
public override void Update(float frameTime)
|
|
{
|
|
var query = EntityQueryEnumerator<ActiveEmergencyLightComponent, EmergencyLightComponent, BatteryComponent>();
|
|
while (query.MoveNext(out var uid, out _, out var emergencyLight, out var battery))
|
|
{
|
|
Update((uid, emergencyLight), battery, frameTime);
|
|
}
|
|
}
|
|
|
|
private void Update(Entity<EmergencyLightComponent> entity, BatteryComponent battery, float frameTime)
|
|
{
|
|
if (entity.Comp.State == EmergencyLightState.On)
|
|
{
|
|
if (!_battery.TryUseCharge((entity.Owner, battery), entity.Comp.Wattage * frameTime))
|
|
{
|
|
SetState(entity.Owner, entity.Comp, EmergencyLightState.Empty);
|
|
TurnOff(entity);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
_battery.ChangeCharge((entity.Owner, battery), entity.Comp.ChargingWattage * frameTime * entity.Comp.ChargingEfficiency);
|
|
if (_battery.IsFull((entity.Owner, battery)))
|
|
{
|
|
if (TryComp<ApcPowerReceiverComponent>(entity.Owner, out var receiver))
|
|
{
|
|
receiver.Load = 1;
|
|
}
|
|
|
|
SetState(entity.Owner, entity.Comp, EmergencyLightState.Full);
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Updates the light's power drain, battery drain, sprite and actual light state.
|
|
/// </summary>
|
|
public void UpdateState(Entity<EmergencyLightComponent> entity)
|
|
{
|
|
if (!TryComp<ApcPowerReceiverComponent>(entity.Owner, out var receiver))
|
|
return;
|
|
|
|
// Show alert level on the light itself.
|
|
if (_station.GetOwningStation(entity.Owner) is not { } station
|
|
|| !_alert.TryGetLevel(station, out var level)
|
|
|| !ProtoMan.Resolve(level, out var proto))
|
|
{
|
|
TurnOff(entity, Color.Red); // if no alert, default to off red state
|
|
return;
|
|
}
|
|
|
|
if (receiver.Powered && !entity.Comp.ForciblyEnabled) // Green alert
|
|
{
|
|
receiver.Load = (int)Math.Abs(entity.Comp.Wattage);
|
|
TurnOff(entity, proto.EmergencyLightColor);
|
|
SetState(entity.Owner, entity.Comp, EmergencyLightState.Charging);
|
|
}
|
|
else if (!receiver.Powered) // If internal battery runs out it will end in off red state
|
|
{
|
|
TurnOn(entity, Color.Red);
|
|
SetState(entity.Owner, entity.Comp, EmergencyLightState.On);
|
|
}
|
|
else // Powered and enabled
|
|
{
|
|
TurnOn(entity, proto.EmergencyLightColor);
|
|
SetState(entity.Owner, entity.Comp, EmergencyLightState.On);
|
|
}
|
|
}
|
|
|
|
private void TurnOff(Entity<EmergencyLightComponent> entity)
|
|
{
|
|
_pointLight.SetEnabled(entity.Owner, false);
|
|
_appearance.SetData(entity.Owner, EmergencyLightVisuals.On, false);
|
|
_ambient.SetAmbience(entity.Owner, false);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Turn off emergency light and set color.
|
|
/// </summary>
|
|
private void TurnOff(Entity<EmergencyLightComponent> entity, Color color)
|
|
{
|
|
_pointLight.SetEnabled(entity.Owner, false);
|
|
_pointLight.SetColor(entity.Owner, color);
|
|
_appearance.SetData(entity.Owner, EmergencyLightVisuals.Color, color);
|
|
_appearance.SetData(entity.Owner, EmergencyLightVisuals.On, false);
|
|
_ambient.SetAmbience(entity.Owner, false);
|
|
}
|
|
|
|
private void TurnOn(Entity<EmergencyLightComponent> entity)
|
|
{
|
|
_pointLight.SetEnabled(entity.Owner, true);
|
|
_appearance.SetData(entity.Owner, EmergencyLightVisuals.On, true);
|
|
_ambient.SetAmbience(entity.Owner, true);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Turn on emergency light and set color.
|
|
/// </summary>
|
|
private void TurnOn(Entity<EmergencyLightComponent> entity, Color color)
|
|
{
|
|
_pointLight.SetEnabled(entity.Owner, true);
|
|
_pointLight.SetColor(entity.Owner, color);
|
|
_appearance.SetData(entity.Owner, EmergencyLightVisuals.Color, color);
|
|
_appearance.SetData(entity.Owner, EmergencyLightVisuals.On, true);
|
|
_ambient.SetAmbience(entity.Owner, true);
|
|
}
|
|
}
|