diff --git a/Content.Server/Chemistry/ReagentEffects/ChemCauseDisease.cs b/Content.Server/Chemistry/ReagentEffects/ChemCauseDisease.cs index 33a80795a4..360cab1e92 100644 --- a/Content.Server/Chemistry/ReagentEffects/ChemCauseDisease.cs +++ b/Content.Server/Chemistry/ReagentEffects/ChemCauseDisease.cs @@ -21,12 +21,13 @@ namespace Content.Server.Chemistry.ReagentEffects /// /// The disease to add. /// - [DataField("disease", customTypeSerializer: typeof(PrototypeIdSerializer))] + [DataField("disease", customTypeSerializer: typeof(PrototypeIdSerializer), required: true)] [ViewVariables(VVAccess.ReadWrite)] - public string Disease = string.Empty; + public string Disease = default!; + public override void Effect(ReagentEffectArgs args) { - EntitySystem.Get().TryAddDisease(null, null, Disease, args.SolutionEntity); + EntitySystem.Get().TryAddDisease(args.SolutionEntity, Disease); } } } diff --git a/Content.Server/Disease/Components/DiseaseVaccineComponent.cs b/Content.Server/Disease/Components/DiseaseVaccineComponent.cs index 5e3e4f7f93..130a2649eb 100644 --- a/Content.Server/Disease/Components/DiseaseVaccineComponent.cs +++ b/Content.Server/Disease/Components/DiseaseVaccineComponent.cs @@ -3,10 +3,10 @@ using Content.Shared.Disease; namespace Content.Server.Disease.Components { - [RegisterComponent] /// /// For disease vaccines /// + [RegisterComponent] public sealed class DiseaseVaccineComponent : Component { /// diff --git a/Content.Server/Disease/DiseaseSystem.cs b/Content.Server/Disease/DiseaseSystem.cs index 360bbe334d..ccb3a99328 100644 --- a/Content.Server/Disease/DiseaseSystem.cs +++ b/Content.Server/Disease/DiseaseSystem.cs @@ -15,6 +15,7 @@ using Robust.Shared.Random; using Robust.Shared.Serialization.Manager; using Content.Shared.Inventory.Events; using Content.Server.Nutrition.EntitySystems; +using Robust.Shared.Utility; namespace Content.Server.Disease { @@ -43,7 +44,7 @@ namespace Content.Server.Disease SubscribeLocalEvent(OnUnequipped); SubscribeLocalEvent(OnAfterInteract); SubscribeLocalEvent(OnExamined); - /// Private events stuff + // Private events stuff SubscribeLocalEvent(OnTargetVaxxSuccessful); SubscribeLocalEvent(OnVaxxCancelled); } @@ -60,7 +61,10 @@ namespace Content.Server.Disease { base.Update(frameTime); foreach (var entity in AddQueue) + { EnsureComp(entity); + } + AddQueue.Clear(); foreach (var tuple in CureQueue) @@ -72,16 +76,19 @@ namespace Content.Server.Disease } CureQueue.Clear(); - foreach (var (diseasedComp, carrierComp, mobState) in EntityQuery(false)) + foreach (var (_, carrierComp, mobState) in EntityQuery()) { + DebugTools.Assert(carrierComp.Diseases.Count > 0); + if (mobState.IsDead()) { if (_random.Prob(0.005f * frameTime)) //Mean time to remove is 200 seconds per disease CureDisease(carrierComp, _random.Pick(carrierComp.Diseases)); + continue; } - foreach(var disease in carrierComp.Diseases) + foreach (var disease in carrierComp.Diseases) { var args = new DiseaseEffectArgs(carrierComp.Owner, disease, EntityManager); disease.Accumulator += frameTime; @@ -139,16 +146,16 @@ namespace Content.Server.Disease /// private void OnEquipped(EntityUid uid, DiseaseProtectionComponent component, GotEquippedEvent args) { - /// This only works on clothing + // This only works on clothing if (!TryComp(uid, out var clothing)) return; - /// Is the clothing in its actual slot? + // Is the clothing in its actual slot? if (!clothing.SlotFlags.HasFlag(args.SlotFlags)) return; - /// Give the user the component's disease resist + // Give the user the component's disease resist if(TryComp(args.Equipee, out var carrier)) carrier.DiseaseResist += component.Protection; - /// Set the component to active to the unequip check isn't CBT + // Set the component to active to the unequip check isn't CBT component.IsActive = true; } @@ -159,7 +166,7 @@ namespace Content.Server.Disease /// private void OnUnequipped(EntityUid uid, DiseaseProtectionComponent component, GotUnequippedEvent args) { - /// Only undo the resistance if it was affecting the user + // Only undo the resistance if it was affecting the user if (!component.IsActive) return; if(TryComp(args.Equipee, out var carrier)) @@ -282,12 +289,9 @@ namespace Content.Server.Disease /// to not be guaranteed you are looking /// for TryInfect. /// - public void TryAddDisease(DiseaseCarrierComponent? target, DiseasePrototype? addedDisease, string? diseaseName = null, EntityUid? host = null) + public void TryAddDisease(EntityUid host, DiseasePrototype addedDisease, DiseaseCarrierComponent? target = null) { - if (diseaseName != null && _prototypeManager.TryIndex(diseaseName, out DiseasePrototype? diseaseProto)) - addedDisease = diseaseProto; - - if (!TryComp(host, out target)) + if (!Resolve(host, ref target, false)) return; foreach (var disease in target.AllDiseases) @@ -295,11 +299,23 @@ namespace Content.Server.Disease if (disease.ID == addedDisease?.ID) //ID because of the way protoypes work return; } - var freshDisease = _serializationManager.CreateCopy(addedDisease) ?? default!; + + var freshDisease = _serializationManager.CreateCopy(addedDisease); + + if (freshDisease == null) return; + target.Diseases.Add(freshDisease); AddQueue.Enqueue(target.Owner); } + public void TryAddDisease(EntityUid host, string? addedDisease, DiseaseCarrierComponent? target = null) + { + if (addedDisease == null || !_prototypeManager.TryIndex(addedDisease, out var added)) + return; + + TryAddDisease(host, added, target); + } + /// /// Pits the infection chance against the /// person's disease resistance and @@ -314,7 +330,7 @@ namespace Content.Server.Disease if (infectionChance <= 0) return; if (_random.Prob(infectionChance)) - TryAddDisease(carrier, disease); + TryAddDisease(carrier.Owner, disease, carrier); } /// diff --git a/Content.Server/Medical/Components/HealthAnalyzerComponent.cs b/Content.Server/Medical/Components/HealthAnalyzerComponent.cs index 733c4e8745..7215b23005 100644 --- a/Content.Server/Medical/Components/HealthAnalyzerComponent.cs +++ b/Content.Server/Medical/Components/HealthAnalyzerComponent.cs @@ -27,17 +27,10 @@ namespace Content.Server.Medical.Components public BoundUserInterface? UserInterface => Owner.GetUIOrNull(HealthAnalyzerUiKey.Key); /// - /// Is this actually going to give people the disease below - /// - [DataField("fake")] - [ViewVariables(VVAccess.ReadWrite)] - public bool Fake = false; - - /// - /// The disease this will give people if Fake == true + /// The disease this will give people. /// [DataField("disease", customTypeSerializer: typeof(PrototypeIdSerializer))] [ViewVariables(VVAccess.ReadWrite)] - public string Disease = string.Empty; + public string? Disease; } } diff --git a/Content.Server/Medical/HealthAnalyzerSystem.cs b/Content.Server/Medical/HealthAnalyzerSystem.cs index 891dc2df86..ed75f10b8d 100644 --- a/Content.Server/Medical/HealthAnalyzerSystem.cs +++ b/Content.Server/Medical/HealthAnalyzerSystem.cs @@ -14,6 +14,7 @@ namespace Content.Server.Medical { public sealed class HealthAnalyzerSystem : EntitySystem { + [Dependency] private readonly DiseaseSystem _disease = default!; [Dependency] private readonly DoAfterSystem _doAfterSystem = default!; [Dependency] private readonly PopupSystem _popupSystem = default!; @@ -68,13 +69,13 @@ namespace Content.Server.Medical { args.Component.CancelToken = null; UpdateScannedUser(args.Component.Owner, args.User, args.Target, args.Component); - /// Below is for the traitor item - /// Piggybacking off another component's doafter is complete CBT so I gave up - /// and put it on the same component - if (!args.Component.Fake || args.Component.Disease == string.Empty || args.Target == null) + // Below is for the traitor item + // Piggybacking off another component's doafter is complete CBT so I gave up + // and put it on the same component + if (string.IsNullOrEmpty(args.Component.Disease) || args.Target == null) return; - EntitySystem.Get().TryAddDisease(null, null, args.Component.Disease, args.Target.Value); + _disease.TryAddDisease(args.Target.Value, args.Component.Disease); if (args.User == args.Target) { diff --git a/Content.Server/StationEvents/Events/DiseaseOutbreak.cs b/Content.Server/StationEvents/Events/DiseaseOutbreak.cs index 8a038030be..9c4d0d422d 100644 --- a/Content.Server/StationEvents/Events/DiseaseOutbreak.cs +++ b/Content.Server/StationEvents/Events/DiseaseOutbreak.cs @@ -47,15 +47,17 @@ public sealed class DiseaseOutbreak : StationEvent var diseaseName = _random.Pick(NotTooSeriousDiseases); - if (!_prototypeManager.TryIndex(diseaseName, out DiseasePrototype? disease) || disease == null) + if (!_prototypeManager.TryIndex(diseaseName, out DiseasePrototype? disease)) return; + var diseaseSystem = EntitySystem.Get(); + foreach (var target in targetList) { if (toInfect-- == 0) break; - EntitySystem.Get().TryAddDisease(target, disease); + diseaseSystem.TryAddDisease(target.Owner, disease, target); } _chatManager.DispatchStationAnnouncement(Loc.GetString("station-event-disease-outbreak-announcement")); } diff --git a/Content.Shared/Disease/DiseasePrototype.cs b/Content.Shared/Disease/DiseasePrototype.cs index d158045fa6..18d324f40f 100644 --- a/Content.Shared/Disease/DiseasePrototype.cs +++ b/Content.Shared/Disease/DiseasePrototype.cs @@ -1,11 +1,12 @@ using Robust.Shared.Prototypes; using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; -/// -/// Diseases encompass everything from viruses to cancers to heart disease. -/// It's not just a virology thing. -/// + namespace Content.Shared.Disease { + /// + /// Diseases encompass everything from viruses to cancers to heart disease. + /// It's not just a virology thing. + /// [Prototype("disease")] [DataDefinition] public sealed class DiseasePrototype : IPrototype, IInheritingPrototype