fish-station/Content.Server/_Sunrise/Disease/SickSystem.cs
2025-12-26 17:44:36 +03:00

318 lines
13 KiB
C#

// © 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.Prototypes;
using Robust.Shared.Timing;
using Content.Shared._Sunrise.Disease;
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.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.FixedPoint;
using Content.Server.Medical;
using Content.Server.Traits.Assorted;
using Content.Shared.Body.Components;
using Content.Shared.Chat;
using Content.Shared.Traits.Assorted;
using Content.Shared.Eye.Blinding.Components;
using Content.Shared.Item;
using Content.Shared.Medical;
using Content.Shared.Speech.Muting;
using Content.Shared.Store.Components;
using Content.Shared.Damage.Systems;
using Content.Shared.Chemistry.Components;
namespace Content.Server._Sunrise.Disease;
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<EntityLookupSystem>();
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<SickComponent, ComponentShutdown>(OnShut);
SubscribeLocalEvent<SickComponent, EmoteEvent>(OnEmote, before:
new[] { typeof(VocalSystem), typeof(BodyEmotesSystem) });
}
public void OnShut(EntityUid uid, SickComponent component, ComponentShutdown args)
{
if (!Exists(uid))
return;
if (TryComp<AutoEmoteComponent>(uid, out var autoEmoteComponent))
{
foreach (var emote in autoEmoteComponent.Emotes)
{
if (emote.Contains("Infected"))
{
_autoEmote.RemoveEmote(uid, emote);
}
}
}
foreach (var key in component.Symptoms)
{
switch (key)
{
case "Narcolepsy":
if (HasComp<SleepyComponent>(uid))
RemComp<SleepyComponent>(uid);
break;
case "Muted":
if (HasComp<MutedComponent>(uid))
RemComp<MutedComponent>(uid);
break;
case "Blindness":
if (HasComp<PermanentBlindnessComponent>(uid))
RemComp<PermanentBlindnessComponent>(uid);
if (HasComp<BlurryVisionComponent>(uid))
RemComp<BlurryVisionComponent>(uid);
if (HasComp<EyeClosingComponent>(uid))
RemComp<EyeClosingComponent>(uid);
break;
case "Slowness":
if (HasComp<SpeedModifierOnComponent>(uid))
RemComp<SpeedModifierOnComponent>(uid);
break;
case "Bleed":
if (HasComp<MinimumBleedComponent>(uid))
RemComp<MinimumBleedComponent>(uid);
break;
}
}
if (TryComp<BloodstreamComponent>(uid, out var stream))
{
var solution = new Solution();
foreach (var reagentId in component.BeforeInfectedBloodReagent)
{
// Количество подставь логичное для твоей механики
solution.AddReagent(reagentId, FixedPoint2.New((int)stream.BloodReferenceSolution.MaxVolume));
}
_bloodstream.ChangeBloodReagents(uid, solution);
}
}
public override void Update(float frameTime)
{
base.Update(frameTime);
var query = EntityQueryEnumerator<SickComponent>();
while (query.MoveNext(out var uid, out var component))
{
if (Terminating(uid))
continue;
if (TryComp<DiseaseRoleComponent>(component.owner, out var diseaseComp))
{
UpdateInfection(uid, component, component.owner, diseaseComp);
if (!component.Inited)
{
if (TryComp<BloodstreamComponent>(uid, out var stream))
{
foreach (var item in stream.BloodReferenceSolution)
{
component.BeforeInfectedBloodReagent.Add(item.Reagent.Prototype);
}
var solution = new Solution();
foreach (var reagentId in diseaseComp.NewBloodReagent)
{
// количество — подставь нужное тебе
solution.AddReagent(reagentId, FixedPoint2.New((int)stream.BloodReferenceSolution.MaxVolume));
}
_bloodstream.ChangeBloodReagents(uid, solution);
}
RaiseNetworkEvent(new ClientInfectEvent(GetNetEntity(uid), GetNetEntity(component.owner)));
diseaseComp.SickOfAllTime++;
AddMoney(component.owner, 5);
component.Inited = true;
}
else
{
if (_gameTiming.CurTime >= component.NextStadyAt)
{
component.Stady++;
foreach (var emote in EnsureComp<AutoEmoteComponent>(uid).Emotes)
{
if (emote.Contains("Infected"))
{
_autoEmote.RemoveEmote(uid, emote);
}
}
component.Symptoms.Clear();
component.NextStadyAt = _gameTiming.CurTime + component.StadyDelay;
}
}
}
}
}
void AddMoney(EntityUid diseaseUid, FixedPoint2 value)
{
if (TryComp<DiseaseRoleComponent>(diseaseUid, out var diseaseComp))
{
if (TryComp<StoreComponent>(diseaseUid, out var store))
{
bool f = _store.TryAddCurrency(new Dictionary<string, FixedPoint2>
{
{diseaseComp.CurrencyPrototype, value}
}, diseaseUid);
_store.UpdateUserInterface(diseaseUid, diseaseUid, store);
}
}
}
private void UpdateInfection(EntityUid uid, SickComponent component, EntityUid disease, DiseaseRoleComponent diseaseComponent)
{
foreach ((var key, var symptomData) in diseaseComponent.Symptoms)
{
if (!component.Symptoms.Contains(key))
{
if (component.Stady >= symptomData.MinLevel && component.Stady <= symptomData.MaxLevel)
{
component.Symptoms.Add(key);
EnsureComp<AutoEmoteComponent>(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<SleepyComponent>(uid))
{
var c = AddComp<SleepyComponent>(uid);
EntityManager.EntitySysManager.GetEntitySystem<SleepySystem>().SetNarcolepsy(uid, new Vector2(10, 30), new Vector2(300, 600), c);
}
break;
case "Muted":
EnsureComp<MutedComponent>(uid);
break;
case "Blindness":
EnsureComp<PermanentBlindnessComponent>(uid);
break;
case "Slowness":
EnsureComp<SpeedModifierOnComponent>(uid);
break;
case "Bleed":
EnsureComp<MinimumBleedComponent>(uid);
break;
case "Insult":
_autoEmote.AddEmote(uid, "InfectedInsult");
break;
}
}
}
}
}
private void OnEmote(EntityUid uid, SickComponent component, ref EmoteEvent args)
{
if (args.Handled)
return;
if (!component.Symptoms.Contains(args.Emote.ID)) return;
switch (args.Emote.ID)
{
case "Headache":
_popupSystem.PopupEntity(Loc.GetString("disease-symptom-headache"), uid, uid, PopupType.Small);
break;
case "Cough":
if (_robustRandom.Prob(0.9f))
{
if (TryComp<DiseaseRoleComponent>(component.owner, out var disease))
{
if (_prototypeManager.TryIndex<DamageTypePrototype>("Piercing", out var damagePrototype))
{
_damageableSystem.TryChangeDamage(uid, new(damagePrototype, 0.25f * disease.Lethal), true, origin: uid);
}
foreach (var entity in Lookup.GetEntitiesInRange(uid, 1.0f))
{
if (_robustRandom.Prob(disease.CoughSneezeInfectChance))
{
if (HasComp<HumanoidAppearanceComponent>(entity) && !HasComp<SickComponent>(entity) && !HasComp<DiseaseImmuneComponent>(entity))
{
OnInfected(entity, component.owner, disease.CoughSneezeInfectChance);
}
}
}
}
}
break;
case "Sneeze":
if (_robustRandom.Prob(0.9f))
{
if (TryComp<DiseaseRoleComponent>(component.owner, out var disease))
{
foreach (var entity in Lookup.GetEntitiesInRange(uid, 1.5f))
{
if (_robustRandom.Prob(disease.CoughSneezeInfectChance))
{
if (HasComp<HumanoidAppearanceComponent>(entity) && !HasComp<SickComponent>(entity) && !HasComp<DiseaseImmuneComponent>(entity))
{
OnInfected(entity, component.owner, disease.CoughSneezeInfectChance);
}
}
}
}
}
break;
case "Vomit":
if (_robustRandom.Prob(0.4f))
{
_vomitSystem.Vomit(uid, -30, -20);
}
break;
case "Insult":
if (TryComp<DiseaseRoleComponent>(component.owner, out var dis))
{
_stun.TryAddParalyzeDuration(uid, TimeSpan.FromSeconds(5));
if (_prototypeManager.TryIndex<DamageTypePrototype>("Shock", out var damagePrototype))
{
_damageableSystem.TryChangeDamage(uid, new(damagePrototype, 0.35f * dis.Lethal), true, origin: uid);
}
}
break;
}
}
}