// © SUNRISE, An EULA/CLA with a hosting restriction, full text: https://github.com/space-sunrise/space-station-14/blob/master/CLA.txt using Robust.Shared.Configuration; using Robust.Shared.Prototypes; using Robust.Shared.Timing; using Content.Shared.Ligyb; using System.Numerics; using Content.Server.Body.Components; using Content.Server.Body.Systems; using Content.Server.Chat.Systems; using Content.Shared.Interaction.Events; using Robust.Server.GameObjects; using Robust.Shared.Audio.Systems; using Robust.Shared.Map; using Robust.Shared.Random; using Content.Shared.Humanoid; using Content.Server.Store.Components; using Content.Server.Store.Systems; using Content.Server.Popups; using Content.Shared.Popups; using Content.Server.Chat; using Content.Shared.Stunnable; using Content.Shared.Damage.Prototypes; using Content.Shared.Damage; using Content.Server.Emoting.Systems; using Content.Server.Speech.EntitySystems; using Content.Shared.Mobs.Systems; using Content.Shared.FixedPoint; using Content.Server.Medical; using Content.Server.Traits.Assorted; using Content.Server.Speech.Muting; using Content.Shared.Traits.Assorted; using Content.Shared.Eye.Blinding.Components; using Content.Shared.Item; using Content.Shared.Speech.Muting; using Content.Shared.Store.Components; namespace Content.Server.Ligyb; public sealed class SickSystem : SharedSickSystem { [Dependency] private readonly AutoEmoteSystem _autoEmote = default!; [Dependency] private readonly StoreSystem _store = default!; [Dependency] private readonly IRobustRandom _robustRandom = default!; [Dependency] private readonly IServerEntityManager _entityManager = default!; [Dependency] private readonly VomitSystem _vomitSystem = default!; [Dependency] private readonly BloodstreamSystem _bloodstream = default!; [Dependency] private readonly IGameTiming _gameTiming = default!; [Dependency] private readonly PopupSystem _popupSystem = default!; [Dependency] private readonly DamageableSystem _damageableSystem = default!; [Dependency] private readonly IPrototypeManager _prototypeManager = default!; [Dependency] private readonly SharedStunSystem _stun = default!; private EntityLookupSystem _lookup => _entityManager.System(); public override void Initialize() { base.Initialize(); SubscribeLocalEvent(OnShut); SubscribeLocalEvent(OnEmote, before: new[] { typeof(VocalSystem), typeof(BodyEmotesSystem) }); } public void OnShut(EntityUid uid, SickComponent component, ComponentShutdown args) { foreach (var emote in EnsureComp(uid).Emotes) { if (emote.Contains("Infected")) { _autoEmote.RemoveEmote(uid, emote); } } foreach (var key in component.Symptoms) { switch (key) { case "Narcolepsy": if (TryComp(uid, out var narc)) { RemComp(uid); } break; case "Muted": if (TryComp(uid, out var mute)) { RemComp(uid); } break; case "Blindness": if (TryComp(uid, out var blind)) { RemComp(uid); } if (HasComp(uid)) { RemComp(uid); } if (HasComp(uid)) { RemComp(uid); } break; case "Slowness": if (TryComp(uid, out var slow)) { RemComp(uid); } break; case "Bleed": if (TryComp(uid, out var bleed)) { RemComp(uid); } break; } } _bloodstream.ChangeBloodReagent(uid, component.BeforeInfectedBloodReagent); } public override void Update(float frameTime) { base.Update(frameTime); var query = EntityQueryEnumerator(); while (query.MoveNext(out var uid, out var component)) { if (TryComp(component.owner, out var diseaseComp)) { UpdateInfection(uid, component, component.owner, diseaseComp); if (!component.Inited) { //Infect if (TryComp(uid, out var stream)) component.BeforeInfectedBloodReagent = stream.BloodReagent; _bloodstream.ChangeBloodReagent(uid, diseaseComp.NewBloodReagent); RaiseNetworkEvent(new ClientInfectEvent(GetNetEntity(uid), GetNetEntity(component.owner))); AddMoney(uid, 5); component.Inited = true; } else { if (_gameTiming.CurTime >= component.NextStadyAt) { component.Stady++; foreach (var emote in EnsureComp(uid).Emotes) { if (emote.Contains("Infected")) { _autoEmote.RemoveEmote(uid, emote); } } component.Symptoms.Clear(); component.NextStadyAt = _gameTiming.CurTime + component.StadyDelay; } } } } } void AddMoney(EntityUid uid, FixedPoint2 value) { if (TryComp(uid, out var component)) { if (TryComp(component.owner, out var diseaseComp)) { if (TryComp(component.owner, out var store)) { bool f = _store.TryAddCurrency(new Dictionary { {diseaseComp.CurrencyPrototype, value} }, component.owner); _store.UpdateUserInterface(component.owner, component.owner, store); } } } } private void UpdateInfection(EntityUid uid, SickComponent component, EntityUid disease, DiseaseRoleComponent diseaseComponent) { foreach ((var key, (var min, var max)) in diseaseComponent.Symptoms) { if (!component.Symptoms.Contains(key)) { if (component.Stady >= min && component.Stady <= max) { component.Symptoms.Add(key); EnsureComp(uid); switch (key) { case "Headache": _autoEmote.AddEmote(uid, "InfectedHeadache"); break; case "Cough": _autoEmote.AddEmote(uid, "InfectedCough"); break; case "Sneeze": _autoEmote.AddEmote(uid, "InfectedSneeze"); break; case "Vomit": _autoEmote.AddEmote(uid, "InfectedVomit"); break; case "Crying": _autoEmote.AddEmote(uid, "InfectedCrying"); break; case "Narcolepsy": if (!HasComp(uid)) { var c = AddComp(uid); EntityManager.EntitySysManager.GetEntitySystem().SetNarcolepsy(uid, new Vector2(10, 30), new Vector2(300, 600), c); } break; case "Muted": EnsureComp(uid); break; case "Blindness": EnsureComp(uid); break; case "Slowness": var ss = EnsureComp(uid); break; case "Bleed": EnsureComp(uid); break; case "Insult": _autoEmote.AddEmote(uid, "InfectedInsult"); break; } } } } } private void OnEmote(EntityUid uid, SickComponent component, ref EmoteEvent args) { if (args.Handled) return; args.Handled = true; if (args.Emote.ID == "Headache") { _popupSystem.PopupEntity("Вы чувствуете лёгкую головную боль.", uid, uid, PopupType.Small); } if (args.Emote.ID == "Cough") { if (_robustRandom.Prob(0.9f)) { if (TryComp(component.owner, out var disease)) { var kind = SuicideKind.Piercing; if (_prototypeManager.TryIndex(kind.ToString(), out var damagePrototype)) { _damageableSystem.TryChangeDamage(uid, new(damagePrototype, 0.25f * disease.Lethal), true, origin: uid); } } EntityCoordinates start = Transform(uid).Coordinates; foreach (var entity in _lookup.GetEntitiesInRange(uid, 0.7f)) { if (HasComp(entity) && !HasComp(entity) && !HasComp(entity)) { OnInfected(entity, component.owner, Comp(component.owner).CoughInfectChance); } } } } if (args.Emote.ID == "Sneeze") { if (_robustRandom.Prob(0.9f)) { EntityCoordinates start = Transform(uid).Coordinates; foreach (var entity in _lookup.GetEntitiesInRange(uid, 1.2f)) { if (HasComp(entity) && !HasComp(entity) && !HasComp(entity)) { OnInfected(entity, component.owner, Comp(component.owner).CoughInfectChance); } } } } if (args.Emote.ID == "Vomit") { if (_robustRandom.Prob(0.4f)) { _vomitSystem.Vomit(uid, -30, -20); } } if (args.Emote.ID == "Insult") { if (TryComp(component.owner, out var disease)) { _stun.TryParalyze(uid, TimeSpan.FromSeconds(5), false); var kind = SuicideKind.Shock; if (_prototypeManager.TryIndex(kind.ToString(), out var damagePrototype)) { _damageableSystem.TryChangeDamage(uid, new(damagePrototype, 0.35f * disease.Lethal), true, origin: uid); } } } } }