From fcb5d0f1152607454809d8d5672b85627d7eb618 Mon Sep 17 00:00:00 2001 From: A-Mironov <65418470+Alexnov33X@users.noreply.github.com> Date: Wed, 21 Jan 2026 21:18:48 +0300 Subject: [PATCH 1/7] test --- .../_Sunrise/Disease/UI/DiseaseInfoBui.cs | 49 ++++++++ .../Disease/UI/DiseaseInfoWindow.xaml | 37 ++++++ .../Disease/UI/DiseaseInfoWindow.xaml.cs | 25 ++++ .../_Sunrise/Disease/DiseaseRoleSystem.cs | 118 +++++++++++++++--- Content.Server/_Sunrise/Disease/SickSystem.cs | 1 + .../Disease/SmallDiseaseRuleSystem.cs | 102 +++++++++++++++ .../Components/EntityStorageComponent.cs | 3 +- .../_Sunrise/Disease/CureDiseaseInfection.cs | 11 +- .../_Sunrise/Disease/DiseaseInfoState.cs | 24 ++++ .../_Sunrise/Disease/DiseaseInfoUiKey.cs | 9 ++ .../_Sunrise/Disease/DiseaseRoleComponent.cs | 2 +- .../Disease/SmallDiseaseRuleComponent.cs | 13 ++ .../_Sunrise/Catalog/disease_catalog.yml | 21 ++-- .../_Sunrise/GameRules/smalldisease.yml | 5 + .../_Sunrise/Roles/Antags/disease.yml | 2 + 15 files changed, 385 insertions(+), 37 deletions(-) create mode 100644 Content.Client/_Sunrise/Disease/UI/DiseaseInfoBui.cs create mode 100644 Content.Client/_Sunrise/Disease/UI/DiseaseInfoWindow.xaml create mode 100644 Content.Client/_Sunrise/Disease/UI/DiseaseInfoWindow.xaml.cs create mode 100644 Content.Server/_Sunrise/Disease/SmallDiseaseRuleSystem.cs create mode 100644 Content.Shared/_Sunrise/Disease/DiseaseInfoState.cs create mode 100644 Content.Shared/_Sunrise/Disease/DiseaseInfoUiKey.cs create mode 100644 Content.Shared/_Sunrise/Disease/SmallDiseaseRuleComponent.cs create mode 100644 Resources/Prototypes/_Sunrise/GameRules/smalldisease.yml diff --git a/Content.Client/_Sunrise/Disease/UI/DiseaseInfoBui.cs b/Content.Client/_Sunrise/Disease/UI/DiseaseInfoBui.cs new file mode 100644 index 00000000000..57111da707f --- /dev/null +++ b/Content.Client/_Sunrise/Disease/UI/DiseaseInfoBui.cs @@ -0,0 +1,49 @@ +using Content.Shared._Sunrise.Disease; +using JetBrains.Annotations; +using Robust.Client.GameObjects; +using Robust.Client.UserInterface; + +namespace Content.Client._Sunrise.Disease.UI; + +[UsedImplicitly] +public sealed class DiseaseInfoBui : BoundUserInterface +{ + [ViewVariables] + private DiseaseInfoWindow? _window; + + public DiseaseInfoBui(EntityUid owner, Enum uiKey) : base(owner, uiKey) + { + } + + protected override void Open() + { + base.Open(); + _window = new DiseaseInfoWindow(); + _window.OnClose += Close; + _window.OpenCentered(); + } + + protected override void UpdateState(BoundUserInterfaceState state) + { + base.UpdateState(state); + + if (state is not DiseaseInfoState diseaseState) + return; + + _window?.UpdateState( + diseaseState.BaseInfectChance, + diseaseState.CoughSneezeInfectChance, + diseaseState.Lethal, + diseaseState.Shield, + diseaseState.CurrentInfected, + diseaseState.TotalInfected + ); + } + + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + if (disposing) + _window?.Dispose(); + } +} diff --git a/Content.Client/_Sunrise/Disease/UI/DiseaseInfoWindow.xaml b/Content.Client/_Sunrise/Disease/UI/DiseaseInfoWindow.xaml new file mode 100644 index 00000000000..d57ad7a6526 --- /dev/null +++ b/Content.Client/_Sunrise/Disease/UI/DiseaseInfoWindow.xaml @@ -0,0 +1,37 @@ + + + + diff --git a/Content.Client/_Sunrise/Disease/UI/DiseaseInfoWindow.xaml.cs b/Content.Client/_Sunrise/Disease/UI/DiseaseInfoWindow.xaml.cs new file mode 100644 index 00000000000..21ec833a69e --- /dev/null +++ b/Content.Client/_Sunrise/Disease/UI/DiseaseInfoWindow.xaml.cs @@ -0,0 +1,25 @@ +using Content.Client.UserInterface.Controls; +using Robust.Client.AutoGenerated; +using Robust.Client.UserInterface.CustomControls; +using Robust.Client.UserInterface.XAML; + +namespace Content.Client._Sunrise.Disease.UI; + +[GenerateTypedNameReferences] +public sealed partial class DiseaseInfoWindow : DefaultWindow +{ + public DiseaseInfoWindow() + { + RobustXamlLoader.Load(this); + } + + public void UpdateState(float baseChance, float infectChance, int lethal, int shield, int currentInfected, int totalInfected) + { + BaseChanceLabel.Text = (baseChance * 100).ToString("F0") + "%"; + InfectChanceLabel.Text = (infectChance * 100).ToString("F0") + "%"; + LethalLabel.Text = lethal.ToString(); + ShieldLabel.Text = shield.ToString(); + CurrentInfectedLabel.Text = currentInfected.ToString(); + TotalInfectedLabel.Text = totalInfected.ToString(); + } +} diff --git a/Content.Server/_Sunrise/Disease/DiseaseRoleSystem.cs b/Content.Server/_Sunrise/Disease/DiseaseRoleSystem.cs index d28de0aa333..6f8f7a6b219 100644 --- a/Content.Server/_Sunrise/Disease/DiseaseRoleSystem.cs +++ b/Content.Server/_Sunrise/Disease/DiseaseRoleSystem.cs @@ -19,6 +19,8 @@ namespace Content.Server._Sunrise.Disease; +using Robust.Server.GameObjects; + public sealed class DiseaseRoleSystem : SharedDiseaseRoleSystem { [Dependency] private readonly IRobustRandom _random = default!; @@ -29,6 +31,7 @@ public sealed class DiseaseRoleSystem : SharedDiseaseRoleSystem [Dependency] private readonly IGameTiming _gameTiming = default!; [Dependency] private readonly AudioSystem _audio = default!; [Dependency] private readonly IPlayerManager _playerManager = default!; + [Dependency] private readonly UserInterfaceSystem _ui = default!; private static readonly List _bloodReagents = new() { @@ -76,6 +79,7 @@ private void OnInfects(InfectEvent args) // Play Initial Infected antag audio (only for the disease player) _audio.PlayGlobal("/Audio/Ambience/Antag/zombie_start.ogg", args.Performer); + UpdateUi(args.Performer, component); } } @@ -105,25 +109,21 @@ private void OnShop(EntityUid uid, DiseaseRoleComponent component, DiseaseShopAc private void OnDiseaseInfo(EntityUid uid, DiseaseRoleComponent component, DiseaseInfoEvent args) { - // Create a simple formatted display using StringBuilder for better performance - var infoText = new StringBuilder(); - infoText.AppendLine(Loc.GetString("disease-info-header")); - infoText.AppendLine(); - - // Core Statistics Section - infoText.AppendLine(Loc.GetString("disease-info-core-statistics") + ":"); - infoText.AppendLine("├─ " + Loc.GetString("disease-info-base-chance") + ": " + (component.BaseInfectChance * 100).ToString("F0") + "%"); - infoText.AppendLine("├─ " + Loc.GetString("disease-info-cough-sneeze-chance") + ": " + (component.CoughSneezeInfectChance * 100).ToString("F0") + "%"); - infoText.AppendLine("├─ " + Loc.GetString("disease-info-lethal") + ": " + component.Lethal); - infoText.AppendLine("└─ " + Loc.GetString("disease-info-shield") + ": " + component.Shield); - infoText.AppendLine(); - - // Infection Statistics Section - infoText.AppendLine(Loc.GetString("disease-info-infection-statistics") + ":"); - infoText.AppendLine("├─ " + Loc.GetString("disease-info-infected-count") + ": " + component.Infected.Count); - infoText.Append("└─ " + Loc.GetString("disease-info-total-infected") + ": " + component.SickOfAllTime); - - _popup.PopupEntity(infoText.ToString(), uid, uid, PopupType.Large); + _ui.TryToggleUi(uid, DiseaseInfoUiKey.Key, uid); + UpdateUi(uid, component); + } + + private void UpdateUi(EntityUid uid, DiseaseRoleComponent component) + { + var state = new DiseaseInfoState( + component.BaseInfectChance, + component.CoughSneezeInfectChance, + component.Lethal, + component.Shield, + component.Infected.Count, + component.SickOfAllTime + ); + _ui.SetUiState(uid, DiseaseInfoUiKey.Key, state); } @@ -221,10 +221,84 @@ private void OnStorePurchase(ref StoreBuyFinishedEvent args) _popup.PopupEntity(Loc.GetString("disease-upgrade-max-reached"), storeOwner, PopupType.Medium); } break; + default: + if (!diseaseComp.Symptoms.ContainsKey(args.PurchasedItem.ID)) + { + // Check if it's a symptom listing from the ID + var symptom = args.PurchasedItem.ID; + int minLevel = 0; + int maxLevel = 5; + + // Ideally we should get this from the listing/action metadata, + // but since the previous system relied on hardcoded event args from actions, + // we might need to assume or look it up. + // For now, let's replicate the levels from the removed actions: + + switch (symptom) + { + case "Cough": minLevel = 2; break; + case "Sneeze": minLevel = 3; break; + case "Vomit": minLevel = 3; break; + case "Narcolepsy": minLevel = 3; break; + case "Crying": minLevel = 0; break; + case "Muted": minLevel = 4; break; + case "Slowness": minLevel = 2; break; + case "Bleed": minLevel = 3; break; + case "Blindness": minLevel = 4; break; + case "Insult": minLevel = 2; break; + // Zombie handled separately via special event if needed, or if it's just a symptom? + // The original action raised DiseaseZombieEvent for "Zombie". + // Wait, "Zombie" was a separate category in catalog? + // Checking catalog: "Zombie" listing productAction was ActionDiseaseZombie. + // So Zombie is NOT handled here in default block if we want to keep specific behavior. + } + + if (symptom == "Zombie") + { + // Zombie Logic - previously handled by DiseaseZombieEvent which was raised by InstantAction + // Now we trigger it directly on purchase + // We need to manually construct the event or call the logic. + // But wait, the original logic was: Purchase -> Get Item/Action -> Use Action -> Trigger Event. + // If we enable "instant buy", we trigger logic now. + var zombieArgs = new DiseaseZombieEvent(); // Empty event, needed for handler signature? + // Actually the handler uses the event args to get the action to remove it. + // We can just extract the logic. + + var infected = diseaseComp.Infected.ToArray(); + var convertedCount = 0; + + for (int i = 0; i < infected.Length; i++) + { + var target = infected[i]; + if (target.IsValid() && !Deleted(target)) + { + RemComp(target); + diseaseComp.Infected.Remove(target); + EnsureComp(target); + EnsureComp(target); + convertedCount++; + } + } + + if (convertedCount > 0) + { + _popup.PopupEntity(Loc.GetString("disease-zombie-success", ("count", convertedCount)), storeOwner, PopupType.Medium); + } + } + else + { + // Regular Symptom + diseaseComp.Symptoms.Add(symptom, new SymptomData(minLevel, maxLevel)); + _popup.PopupEntity(Loc.GetString("disease-upgrade-purchased"), storeOwner, PopupType.Medium); + } + } + break; } + UpdateUi(storeOwner, diseaseComp); + } - void AddMoney(EntityUid uid, FixedPoint2 value) + private void AddMoney(EntityUid uid, FixedPoint2 value) { if (TryComp(uid, out var diseaseComp)) { @@ -313,6 +387,10 @@ private void OnInfectedDeath(MobStateChangedEvent args) if (Deleted(args.Target)) return; + // Check if the dying entity was actually infected + if (!HasComp(args.Target)) + return; + // Reward all other disease antagonists when any infected dies var diseaseQuery = EntityQueryEnumerator(); while (diseaseQuery.MoveNext(out var diseaseUid, out var diseaseComp)) diff --git a/Content.Server/_Sunrise/Disease/SickSystem.cs b/Content.Server/_Sunrise/Disease/SickSystem.cs index e9bfce2510e..7810f8bd841 100644 --- a/Content.Server/_Sunrise/Disease/SickSystem.cs +++ b/Content.Server/_Sunrise/Disease/SickSystem.cs @@ -153,6 +153,7 @@ public override void Update(float frameTime) RaiseNetworkEvent(new ClientInfectEvent(GetNetEntity(uid), GetNetEntity(component.owner))); diseaseComp.SickOfAllTime++; AddMoney(component.owner, 5); + _popupSystem.PopupEntity(Loc.GetString("disease-infect-reward", ("points", 5)), component.owner, component.owner, PopupType.Medium); component.Inited = true; } diff --git a/Content.Server/_Sunrise/Disease/SmallDiseaseRuleSystem.cs b/Content.Server/_Sunrise/Disease/SmallDiseaseRuleSystem.cs new file mode 100644 index 00000000000..a218be54e27 --- /dev/null +++ b/Content.Server/_Sunrise/Disease/SmallDiseaseRuleSystem.cs @@ -0,0 +1,102 @@ +using Content.Shared._Sunrise.Disease; +using Content.Server.GameTicking.Rules; +using Content.Shared.GameTicking.Components; +using Robust.Server.GameObjects; +using Robust.Shared.Random; +using Robust.Shared.Prototypes; +using Content.Shared.Store; +using System.Linq; +using Content.Shared.Humanoid; +using Content.Shared.Mobs.Components; +using Content.Shared.Mind; +using Content.Shared.Mind.Components; +using Robust.Shared.Map; + +namespace Content.Server._Sunrise.Disease; + +public sealed class SmallDiseaseRuleSystem : GameRuleSystem +{ + [Dependency] private readonly IPrototypeManager _prototypeManager = default!; + [Dependency] private readonly IRobustRandom _random = default!; + [Dependency] private readonly EntityLookupSystem _lookup = default!; + [Dependency] private readonly SharedTransformSystem _transform = default!; + + protected override void Started(EntityUid uid, SmallDiseaseRuleComponent component, GameRuleComponent gameRule, GameRuleStartedEvent args) + { + base.Started(uid, component, gameRule, args); + + // 1. Find potential victims (Humanoid, Has Mind, Not Dead, Not Sick) + var query = EntityQueryEnumerator(); + var candidates = new List(); + + while (query.MoveNext(out var entity, out _, out _, out _, out var xform)) + { + if (HasComp(entity)) + continue; + + // Simple check to ensure they are on a station/grid generally + if (xform.GridUid == null) + continue; + + candidates.Add(entity); + } + + if (candidates.Count == 0) + return; + + // 2. Spawn the Disease Entity (Dummy) + var diseaseUid = Spawn("MobDisease", MapCoordinates.Nullspace); + if (!TryComp(diseaseUid, out var diseaseComp)) + { + return; + } + + // 3. Configure Symptoms + // Always add Cough + diseaseComp.Symptoms.TryAdd("Cough", new SymptomData(2, 5)); // Cough is level 2 typically + + var currentPoints = 0; + var availableSymptoms = new List(); + + // Gather all symptom listings + foreach (var listing in _prototypeManager.EnumeratePrototypes()) + { + if (listing.Categories.Contains("DiseaseSymptomsCategory")) + { + availableSymptoms.Add(listing); + } + } + + // Randomly add until 50 points + // Safety loop + for (int i = 0; i < 20 && currentPoints < component.TargetSymptomPoints; i++) + { + if (availableSymptoms.Count == 0) break; + + var pick = _random.Pick(availableSymptoms); + var cost = pick.Cost.GetValueOrDefault("DiseasePoints", 0); + + // Avoid adding same symptom twice + if (!diseaseComp.Symptoms.ContainsKey(pick.ID)) + { + // Determine level (rough approximation or default) + // We'll use 0-5 as safe defaults or check ID specific logic if strictly needed + // Using 1-5 generic + diseaseComp.Symptoms.Add(pick.ID, new SymptomData(1, 5)); + currentPoints += cost.Int(); + } + } + + // 4. Infect Targets + _random.Shuffle(candidates); + var targetCount = Math.Min(component.TargetInfectedCount, candidates.Count); + + for (int i = 0; i < targetCount; i++) + { + var victim = candidates[i]; + var sick = EnsureComp(victim); + sick.owner = diseaseUid; + diseaseComp.Infected.Add(victim); + } + } +} diff --git a/Content.Shared/Storage/Components/EntityStorageComponent.cs b/Content.Shared/Storage/Components/EntityStorageComponent.cs index ecfcccc45b7..107555514d1 100644 --- a/Content.Shared/Storage/Components/EntityStorageComponent.cs +++ b/Content.Shared/Storage/Components/EntityStorageComponent.cs @@ -42,7 +42,8 @@ public sealed partial class EntityStorageComponent : Component, IGasMixtureHolde public int MasksToRemove = (int)( CollisionGroup.MidImpassable | CollisionGroup.HighImpassable | - CollisionGroup.LowImpassable); + CollisionGroup.LowImpassable | + CollisionGroup.BulletImpassable); /// /// Collision masks that were removed from ANY layer when the storage was opened; diff --git a/Content.Shared/_Sunrise/Disease/CureDiseaseInfection.cs b/Content.Shared/_Sunrise/Disease/CureDiseaseInfection.cs index 43d8d33c854..3695406e5f5 100644 --- a/Content.Shared/_Sunrise/Disease/CureDiseaseInfection.cs +++ b/Content.Shared/_Sunrise/Disease/CureDiseaseInfection.cs @@ -11,11 +11,14 @@ public sealed partial class CureDiseaseInfectionEntityEffectSystem : EntityEffec protected override void Effect(Entity entity, ref EntityEffectEvent args) { - if (_entityManager.TryGetComponent(entity.Owner, out var disease)) + if (_entityManager.TryGetComponent(entity.Owner, out var sick)) { - var comp = _entityManager.EnsureComponent(entity.Owner); - comp.Immune = args.Effect.Innoculate; - comp.Delay = TimeSpan.FromMinutes(2) + TimeSpan.FromSeconds(disease.Shield * 30); + if (_entityManager.TryGetComponent(sick.owner, out var disease)) + { + var comp = _entityManager.EnsureComponent(entity.Owner); + comp.Immune = args.Effect.Innoculate; + comp.Delay = TimeSpan.FromMinutes(2) + TimeSpan.FromSeconds(disease.Shield * 30); + } } } } diff --git a/Content.Shared/_Sunrise/Disease/DiseaseInfoState.cs b/Content.Shared/_Sunrise/Disease/DiseaseInfoState.cs new file mode 100644 index 00000000000..5f052648060 --- /dev/null +++ b/Content.Shared/_Sunrise/Disease/DiseaseInfoState.cs @@ -0,0 +1,24 @@ +using Robust.Shared.Serialization; + +namespace Content.Shared._Sunrise.Disease; + +[Serializable, NetSerializable] +public sealed class DiseaseInfoState : BoundUserInterfaceState +{ + public float BaseInfectChance; + public float CoughSneezeInfectChance; + public int Lethal; + public int Shield; + public int CurrentInfected; + public int TotalInfected; + + public DiseaseInfoState(float baseInfectChance, float coughSneezeInfectChance, int lethal, int shield, int currentInfected, int totalInfected) + { + BaseInfectChance = baseInfectChance; + CoughSneezeInfectChance = coughSneezeInfectChance; + Lethal = lethal; + Shield = shield; + CurrentInfected = currentInfected; + TotalInfected = totalInfected; + } +} diff --git a/Content.Shared/_Sunrise/Disease/DiseaseInfoUiKey.cs b/Content.Shared/_Sunrise/Disease/DiseaseInfoUiKey.cs new file mode 100644 index 00000000000..ee161ef9429 --- /dev/null +++ b/Content.Shared/_Sunrise/Disease/DiseaseInfoUiKey.cs @@ -0,0 +1,9 @@ +using Robust.Shared.Serialization; + +namespace Content.Shared._Sunrise.Disease; + +[Serializable, NetSerializable] +public enum DiseaseInfoUiKey +{ + Key +} diff --git a/Content.Shared/_Sunrise/Disease/DiseaseRoleComponent.cs b/Content.Shared/_Sunrise/Disease/DiseaseRoleComponent.cs index 414552cf9f5..c15a170efc8 100644 --- a/Content.Shared/_Sunrise/Disease/DiseaseRoleComponent.cs +++ b/Content.Shared/_Sunrise/Disease/DiseaseRoleComponent.cs @@ -38,7 +38,7 @@ public sealed partial class DiseaseRoleComponent : Component [DataField] public int SickOfAllTime = 0; [DataField("newBloodReagent")] - public List NewBloodReagent = new() { "ZombieBlood" }; + public List NewBloodReagent = new(); } [Serializable, NetSerializable] diff --git a/Content.Shared/_Sunrise/Disease/SmallDiseaseRuleComponent.cs b/Content.Shared/_Sunrise/Disease/SmallDiseaseRuleComponent.cs new file mode 100644 index 00000000000..d9af32c2b96 --- /dev/null +++ b/Content.Shared/_Sunrise/Disease/SmallDiseaseRuleComponent.cs @@ -0,0 +1,13 @@ +using Content.Shared.GameTicking.Components; + +namespace Content.Shared._Sunrise.Disease; + +[RegisterComponent] +public sealed partial class SmallDiseaseRuleComponent : Component +{ + [DataField] + public int TargetInfectedCount = 3; + + [DataField] + public int TargetSymptomPoints = 50; +} diff --git a/Resources/Prototypes/_Sunrise/Catalog/disease_catalog.yml b/Resources/Prototypes/_Sunrise/Catalog/disease_catalog.yml index 8d58cabd4cc..7b8a2c35da6 100644 --- a/Resources/Prototypes/_Sunrise/Catalog/disease_catalog.yml +++ b/Resources/Prototypes/_Sunrise/Catalog/disease_catalog.yml @@ -4,7 +4,6 @@ description: listing-disease-cough-description icon: { sprite: /Textures/_Sunrise/Actions/disease.rsi, state: cough } raiseProductEventOnUser: true - productAction: ActionDiseaseCough cost: DiseasePoints: 0 categories: @@ -18,7 +17,7 @@ name: listing-disease-sneeze-name description: listing-disease-sneeze-description icon: { sprite: /Textures/_Sunrise/Actions/disease.rsi, state: sneeze } - productAction: ActionDiseaseSneeze + raiseProductEventOnUser: true cost: DiseasePoints: 20 categories: @@ -32,7 +31,7 @@ name: listing-disease-vomit-name description: listing-disease-vomit-description icon: { sprite: /Textures/_Sunrise/Actions/disease.rsi, state: vomit } - productAction: ActionDiseaseVomit + raiseProductEventOnUser: true cost: DiseasePoints: 25 categories: @@ -46,7 +45,7 @@ name: listing-disease-narcolepsy-name description: listing-disease-narcolepsy-description icon: { sprite: /Textures/_Sunrise/Actions/disease.rsi, state: narcolepsy } - productAction: ActionDiseaseNarcolepsy + raiseProductEventOnUser: true cost: DiseasePoints: 20 categories: @@ -60,7 +59,7 @@ name: listing-disease-cry-name description: listing-disease-cry-description icon: { sprite: /Textures/_Sunrise/Actions/disease.rsi, state: sob } - productAction: ActionDiseaseCrying + raiseProductEventOnUser: true cost: DiseasePoints: 10 categories: @@ -74,7 +73,7 @@ name: listing-disease-muted-name description: listing-disease-muted-description icon: { sprite: /Textures/_Sunrise/Actions/disease.rsi, state: muted } - productAction: ActionDiseaseMuted + raiseProductEventOnUser: true cost: DiseasePoints: 25 categories: @@ -88,7 +87,7 @@ name: listing-disease-slowness-name description: listing-disease-slowness-description icon: { sprite: /Textures/_Sunrise/Actions/disease.rsi, state: slowness } - productAction: ActionDiseaseSlowness + raiseProductEventOnUser: true cost: DiseasePoints: 15 categories: @@ -102,7 +101,7 @@ name: listing-disease-bleed-name description: listing-disease-bleed-description icon: { sprite: /Textures/_Sunrise/Actions/disease.rsi, state: bleed } - productAction: ActionDiseaseBleed + raiseProductEventOnUser: true cost: DiseasePoints: 30 categories: @@ -116,7 +115,7 @@ name: listing-disease-blindness-name description: listing-disease-blindness-description icon: { sprite: /Textures/_Sunrise/Actions/disease.rsi, state: blindness } - productAction: ActionDiseaseBlindness + raiseProductEventOnUser: true cost: DiseasePoints: 40 categories: @@ -130,7 +129,7 @@ name: listing-disease-insult-name description: listing-disease-insult-description icon: { sprite: /Textures/_Sunrise/Actions/disease.rsi, state: lethal } - productAction: ActionDiseaseInsult + raiseProductEventOnUser: true cost: DiseasePoints: 20 categories: @@ -144,7 +143,7 @@ name: listing-disease-zombie-name description: listing-disease-zombie-description icon: { sprite: /Textures/_Sunrise/Actions/disease.rsi, state: lethal } - productAction: ActionDiseaseZombie + raiseProductEventOnUser: true cost: DiseasePoints: 200 categories: diff --git a/Resources/Prototypes/_Sunrise/GameRules/smalldisease.yml b/Resources/Prototypes/_Sunrise/GameRules/smalldisease.yml new file mode 100644 index 00000000000..2da18d2a88a --- /dev/null +++ b/Resources/Prototypes/_Sunrise/GameRules/smalldisease.yml @@ -0,0 +1,5 @@ +- type: entity + id: SmallDisease + parent: BaseGameRule + components: + - type: SmallDiseaseRule diff --git a/Resources/Prototypes/_Sunrise/Roles/Antags/disease.yml b/Resources/Prototypes/_Sunrise/Roles/Antags/disease.yml index 90029d47c48..b469c1d09ac 100644 --- a/Resources/Prototypes/_Sunrise/Roles/Antags/disease.yml +++ b/Resources/Prototypes/_Sunrise/Roles/Antags/disease.yml @@ -60,6 +60,8 @@ interfaces: enum.StoreUiKey.Key: type: StoreBoundUserInterface + enum.DiseaseInfoUiKey.Key: + type: DiseaseInfoBui - type: Visibility layer: 2 #ghost vis layer - type: Store From fb12cc300d9e9533dc368e4fc519e9f795a3e2f4 Mon Sep 17 00:00:00 2001 From: A-Mironov <65418470+Alexnov33X@users.noreply.github.com> Date: Thu, 22 Jan 2026 02:10:19 +0300 Subject: [PATCH 2/7] looks good --- .../_Sunrise/Disease/DiseaseRoleSystem.cs | 9 +- Content.Server/_Sunrise/Disease/SickSystem.cs | 16 +- .../Disease/SmallDiseaseRuleSystem.cs | 8 +- .../_strings/_sunrise/disease/disease.ftl | 6 +- .../_strings/_sunrise/disease/disease.ftl | 6 +- .../_Sunrise/Catalog/disease_catalog.yml | 8 +- .../_Sunrise/Roles/Antags/disease.yml | 2 +- .../Guidebook/_Sunrise/Antagonist/Disease.xml | 208 +++++++++++------- 8 files changed, 159 insertions(+), 104 deletions(-) diff --git a/Content.Server/_Sunrise/Disease/DiseaseRoleSystem.cs b/Content.Server/_Sunrise/Disease/DiseaseRoleSystem.cs index 6f8f7a6b219..13f0e0746fc 100644 --- a/Content.Server/_Sunrise/Disease/DiseaseRoleSystem.cs +++ b/Content.Server/_Sunrise/Disease/DiseaseRoleSystem.cs @@ -69,13 +69,8 @@ private void OnInfects(InfectEvent args) { if (TryComp(args.Performer, out var component)) { - if (TryRemoveMoney(args.Performer, component.InfectCost)) - OnInfect(args, 1.0f); - else - { - _popup.PopupEntity(Loc.GetString("disease-not-enough-evolution-points"), args.Performer, PopupType.Medium); - return; - } + OnInfect(args, 1.0f); + _popup.PopupEntity(Loc.GetString("disease-infect-success"), args.Performer, PopupType.Medium); // Play Initial Infected antag audio (only for the disease player) _audio.PlayGlobal("/Audio/Ambience/Antag/zombie_start.ogg", args.Performer); diff --git a/Content.Server/_Sunrise/Disease/SickSystem.cs b/Content.Server/_Sunrise/Disease/SickSystem.cs index 7810f8bd841..39466de9eea 100644 --- a/Content.Server/_Sunrise/Disease/SickSystem.cs +++ b/Content.Server/_Sunrise/Disease/SickSystem.cs @@ -34,6 +34,8 @@ using Content.Shared.Store.Components; using Content.Shared.Damage.Systems; using Content.Shared.Chemistry.Components; +using Content.Shared.Inventory; +using Content.Shared.Zombies; namespace Content.Server._Sunrise.Disease; public sealed class SickSystem : SharedSickSystem { @@ -223,7 +225,7 @@ private void UpdateInfection(EntityUid uid, SickComponent component, EntityUid d if (!HasComp(uid)) { var c = AddComp(uid); - EntityManager.EntitySysManager.GetEntitySystem().SetNarcolepsy(uid, new Vector2(10, 30), new Vector2(300, 600), c); + EntityManager.EntitySysManager.GetEntitySystem().SetNarcolepsy(uid, new Vector2(60, 80), new Vector2(8, 12), c); } break; case "Muted": @@ -273,7 +275,11 @@ private void OnEmote(EntityUid uid, SickComponent component, ref EmoteEvent args { if (HasComp(entity) && !HasComp(entity) && !HasComp(entity)) { - OnInfected(entity, component.owner, disease.CoughSneezeInfectChance); + var ev = new ZombificationResistanceQueryEvent(SlotFlags.HEAD | SlotFlags.MASK | SlotFlags.OUTERCLOTHING); + RaiseLocalEvent(entity, ev); + + if (_robustRandom.Prob(ev.TotalCoefficient)) + OnInfected(entity, component.owner, disease.CoughSneezeInfectChance); } } } @@ -291,7 +297,11 @@ private void OnEmote(EntityUid uid, SickComponent component, ref EmoteEvent args { if (HasComp(entity) && !HasComp(entity) && !HasComp(entity)) { - OnInfected(entity, component.owner, disease.CoughSneezeInfectChance); + var ev = new ZombificationResistanceQueryEvent(SlotFlags.HEAD | SlotFlags.MASK | SlotFlags.OUTERCLOTHING); + RaiseLocalEvent(entity, ev); + + if (_robustRandom.Prob(ev.TotalCoefficient)) + OnInfected(entity, component.owner, disease.CoughSneezeInfectChance); } } } diff --git a/Content.Server/_Sunrise/Disease/SmallDiseaseRuleSystem.cs b/Content.Server/_Sunrise/Disease/SmallDiseaseRuleSystem.cs index a218be54e27..e2bd6b8436d 100644 --- a/Content.Server/_Sunrise/Disease/SmallDiseaseRuleSystem.cs +++ b/Content.Server/_Sunrise/Disease/SmallDiseaseRuleSystem.cs @@ -47,9 +47,8 @@ protected override void Started(EntityUid uid, SmallDiseaseRuleComponent compone // 2. Spawn the Disease Entity (Dummy) var diseaseUid = Spawn("MobDisease", MapCoordinates.Nullspace); if (!TryComp(diseaseUid, out var diseaseComp)) - { return; - } + // 3. Configure Symptoms // Always add Cough @@ -74,7 +73,10 @@ protected override void Started(EntityUid uid, SmallDiseaseRuleComponent compone if (availableSymptoms.Count == 0) break; var pick = _random.Pick(availableSymptoms); - var cost = pick.Cost.GetValueOrDefault("DiseasePoints", 0); + var cost = pick.Cost.GetValueOrDefault("DiseasePoints", 100); + + if (cost > component.TargetSymptomPoints) + continue; // Avoid adding same symptom twice if (!diseaseComp.Symptoms.ContainsKey(pick.ID)) diff --git a/Resources/Locale/en-US/_strings/_sunrise/disease/disease.ftl b/Resources/Locale/en-US/_strings/_sunrise/disease/disease.ftl index 89078f907c7..9be33ef20c7 100644 --- a/Resources/Locale/en-US/_strings/_sunrise/disease/disease.ftl +++ b/Resources/Locale/en-US/_strings/_sunrise/disease/disease.ftl @@ -36,4 +36,8 @@ disease-infect-charge-max-reached = Already at maximum charges ({ $maxCharges }) disease-death-reward = Received { $points } Disease Points from another disease's death! disease-upgrade-purchased = Upgrade purchased successfully! -disease-upgrade-max-reached = Maximum upgrade level reached! \ No newline at end of file +disease-upgrade-max-reached = Maximum upgrade level reached! + +disease-infect-success = Successful infection! + +disease-info-window-title = Disease Statistics diff --git a/Resources/Locale/ru-RU/_strings/_sunrise/disease/disease.ftl b/Resources/Locale/ru-RU/_strings/_sunrise/disease/disease.ftl index 5469a6b695f..93fa934cce3 100644 --- a/Resources/Locale/ru-RU/_strings/_sunrise/disease/disease.ftl +++ b/Resources/Locale/ru-RU/_strings/_sunrise/disease/disease.ftl @@ -36,4 +36,8 @@ disease-infect-charge-max-reached = Уже максимальное количе disease-death-reward = Получено { $points } очков болезни от смерти другого больного! disease-upgrade-purchased = Улучшение успешно куплено! -disease-upgrade-max-reached = Достигнут максимальный уровень улучшения! \ No newline at end of file +disease-upgrade-max-reached = Достигнут максимальный уровень улучшения! + +disease-infect-success = Успешное заражение! + +disease-info-window-title = Статистика Болезни diff --git a/Resources/Prototypes/_Sunrise/Catalog/disease_catalog.yml b/Resources/Prototypes/_Sunrise/Catalog/disease_catalog.yml index 7b8a2c35da6..d74c3702732 100644 --- a/Resources/Prototypes/_Sunrise/Catalog/disease_catalog.yml +++ b/Resources/Prototypes/_Sunrise/Catalog/disease_catalog.yml @@ -175,7 +175,7 @@ - DiseaseEvolutionCategory conditions: - !type:ListingLimitedStockCondition - stock: 1 + stock: 5 - type: listing id: InfectChance @@ -189,7 +189,7 @@ - DiseaseEvolutionCategory conditions: - !type:ListingLimitedStockCondition - stock: 1 + stock: 3 - type: listing id: Shield @@ -203,7 +203,7 @@ - DiseaseEvolutionCategory conditions: - !type:ListingLimitedStockCondition - stock: 1 + stock: 6 - type: listing id: Lethal @@ -217,5 +217,5 @@ - DiseaseEvolutionCategory conditions: - !type:ListingLimitedStockCondition - stock: 1 + stock: 5 #Sunrise-End diff --git a/Resources/Prototypes/_Sunrise/Roles/Antags/disease.yml b/Resources/Prototypes/_Sunrise/Roles/Antags/disease.yml index b469c1d09ac..802785d2528 100644 --- a/Resources/Prototypes/_Sunrise/Roles/Antags/disease.yml +++ b/Resources/Prototypes/_Sunrise/Roles/Antags/disease.yml @@ -10,7 +10,7 @@ context: "ghost" - type: MovementSpeedModifier baseWalkSpeed: 6 - baseSprintSpeed: 6 + baseSprintSpeed: 20 - type: Sprite noRot: true drawdepth: Ghosts diff --git a/Resources/ServerInfo/Guidebook/_Sunrise/Antagonist/Disease.xml b/Resources/ServerInfo/Guidebook/_Sunrise/Antagonist/Disease.xml index 973718657b7..6305b58216b 100644 --- a/Resources/ServerInfo/Guidebook/_Sunrise/Antagonist/Disease.xml +++ b/Resources/ServerInfo/Guidebook/_Sunrise/Antagonist/Disease.xml @@ -1,87 +1,127 @@ - # Разумная болезнь - - - [color=#999999][italic]"Ты просто простудился... или они уже думают за тебя?"[/italic][/color] - - - - - - Разумная болезнь — это антагонист, способный заражать всех существ, а так-же передаваться, она имеет свойство "мутировать", у нее появляються разные симптомы, увеличиваеться летальность, заразность и устойчивость к лекартсвам. она легко распростроняеться если не принять необходимые меры. - - ## Основные симптомы - - Первыми отличимыми симптомами которые есть у каждой болезни, это головная боль и головокружение, так-же основной переносный симптом - кашель и чих. - - ## Передача - - Передача вируса происходит при кашле и чихе, если рядом с вами находиться зараженный и имеет упомянутые симптомы, вы имеете вероятность заразиться. Эта вероятность уменьшаеться при ношении защитных костюмов, масок и прочих средств. - - Однако, у болезни есть возможность заразить вас игнорируя упомянутые средства защиты, при этом она использует очки эволюции, что означает что вы в любом случае можете заболеть. - - ## Возможные симптомы - - Так-же кроме основных симптомов, у болезни есть перечень других, таких как: - - - Непроизвольные слёзы(10 ОЭ) - - [color=#999999][italic]У заражённых активно слезяться глаза, из-за чего кажется, что они плачут.[/italic][/color] - - - - Изнеможение(15 ОЭ) - - [color=#999999][italic]Вирус вызывает разрушение мышечных волокон, приводящее к атрофие и сопровождающееся слабостью. Снижает общую мобильность[/italic][/color] - - - - Сонливость(20 ОЭ) - - [color=#999999][italic]У заражённых появляется постоянное желание спать, с которым они иногда не могут справиться.[/italic][/color] - - - - Судороги(20 ОЭ) - - [color=#999999][italic]Длительная болезнь вызывает гиперстимуляцию двигательных нейронов, в результате чего больные могут испытывать перенапряжение мышц, приводящие к судорогам.[/italic][/color] - - - - Немота(25 ОЭ) - - [color=#999999][italic]Мутация вызывает повреждение подъязычного нерва, приводя к параличу мышц языка, из-за чего больные теряют возможность нормально говорить.[/italic][/color] - - - - Тошнота(25 ОЭ) - - [color=#999999][italic]Заражённых начинает тоншить, вызывая рвоту.[/italic][/color] - - - - Кровопотеря(30 ОЭ) - - [color=#999999][italic]Вирус вызывает денатурацию гемоглобина крови, из-за чего у всех носителей появляется тяжелая степень анемии.[/italic][/color] - - - - Слепота(40 ОЭ) - - [color=#999999][italic]Длительная болезнь приводит к отмиранию зрительного нерва, что приводит к практически полной слепоте больного.[/italic][/color] - - - ## Базовые противодействия - - Если вы заметили что у вас появились какие-то из симптом, не стоит сразу бежать в вирусологию, но стоит принять минимальные меры, носить маску, избегать контакта с персоналом. - - Если же у вас обноружилось 2 и более семптома, например кашель, головная боль и изнеможение, немедленно отправьтесь в медецинский отдел а так-же оповестите врача о том что вы вероятно заражены. - - ## Вакцина - - Для создания вакцины необходима пробирка, шприц, здоровый человек, заражённый человек и вакцинатор, делаем всё строго в последовательности: - - - Набираем кровь заражённого человека в пробирку - - - Вставляем пробирку в вакцинатор - - - Получаем бумажку, с указаниями для создания вакцины. - - - Делаем всё как указано на листочке. - - Готово, вы получили вакцину. + +[head=1][color=#ff9966]Разумная болезнь[/color][/head] + + +[color=#999999][italic]"Ты просто простудился... или они уже думают за тебя?"[/italic][/color] + + + + + +[color=#cccccc]Разумная болезнь — это антагонист, способный заражать всех существ и передаваться между ними. Болезнь обладает свойством «мутировать»: у неё появляются разные симптомы, а её летальность, заразность и устойчивость к лекарствам увеличиваются. Она легко распространяется, если не принять необходимые меры.[/color] + +[head=2][color=#ffaa66]Основные симптомы[/color][/head] + +[color=#dddddd]Первыми отличимыми симптомами, которые есть у каждой болезни, являются головная боль и головокружение. Также основными переносными симптомами являются кашель и чихание.[/color] + +[head=2][color=#ffaa66]Передача[/color][/head] + +[color=#dddddd]Передача вируса происходит при кашле и чихании. Если рядом с вами находится заражённый, у которого есть упомянутые симптомы, вы с определённой вероятностью можете заразиться. Эта вероятность уменьшается при ношении защитных костюмов, масок и прочих средств.[/color] + +[color=#dddddd]Однако у болезни есть возможность заразить вас, игнорируя упомянутые средства защиты, расходуя на это очки эволюции. Это означает, что вы в любом случае можете заболеть.[/color] + +[head=2][color=#ffaa66]Возможные симптомы[/color][/head] + +[color=#dddddd]Кроме основных симптомов, у болезни есть перечень других, таких как:[/color] + +[head=3][color=#ffbb77]Непроизвольные слёзы (10 ОЭ)[/color][/head] + +[color=#999999][italic]У заражённых активно слезятся глаза, из-за чего кажется, что они плачут.[/italic][/color] + + +[head=3][color=#ffbb77]Изнеможение (15 ОЭ)[/color][/head] + +[color=#999999][italic]Вирус вызывает разрушение мышечных волокон, приводящее к атрофии и сопровождающееся слабостью. Снижает общую мобильность.[/italic][/color] + + +[head=3][color=#ffbb77]Сонливость (20 ОЭ)[/color][/head] + +[color=#999999][italic]У заражённых появляется постоянное желание спать, с которым они иногда не могут справиться.[/italic][/color] + + +[head=3][color=#ffbb77]Судороги (20 ОЭ)[/color][/head] + +[color=#999999][italic]Длительная болезнь вызывает гиперстимуляцию двигательных нейронов, в результате чего больные могут испытывать перенапряжение мышц, приводящее к судорогам.[/italic][/color] + + +[head=3][color=#ffbb77]Немота (25 ОЭ)[/color][/head] + +[color=#999999][italic]Мутация вызывает повреждение подъязычного нерва, приводя к параличу мышц языка, из-за чего больные теряют возможность нормально говорить.[/italic][/color] + + +[head=3][color=#ffbb77]Тошнота (25 ОЭ)[/color][/head] + +[color=#999999][italic]Заражённых начинает тошнить, вызывая рвоту.[/italic][/color] + + +[head=3][color=#ffbb77]Кровопотеря (30 ОЭ)[/color][/head] + +[color=#999999][italic]Вирус вызывает денатурацию гемоглобина крови, из-за чего у всех носителей появляется тяжёлая степень анемии.[/italic][/color] + + +[head=3][color=#ffbb77]Слепота (40 ОЭ)[/color][/head] + +[color=#999999][italic]Длительная болезнь приводит к отмиранию зрительного нерва, что приводит к практически полной слепоте больного.[/italic][/color] + + +[head=2][color=#ffaa66]Базовые противодействия[/color][/head] + +[color=#dddddd]Если вы заметили, что у вас появились какие-то из симптомов, не стоит сразу бежать в вирусологию, но стоит принять минимальные меры: носить маску, избегать контакта с персоналом.[/color] + +[color=#dddddd]Если же у вас обнаружилось 2 и более симптома, например, кашель, головная боль и изнеможение, немедленно отправьтесь в медицинский отдел, а также оповестите врача о том, что вы, вероятно, заражены.[/color] + +[head=2][color=#ffaa66]Вакцина[/color][/head] + +[head=3][color=#ffbb77]Получение рецепта[/color][/head] + +[color=#dddddd]Используйте бумагу на Вакцинаторе. Вы получите рецепт, который зависит от случайной «Группы крови» болезни в этом раунде.[/color] + + + + + + + + +[head=3][color=#ffbb77]Создание заготовки[/color][/head] + +[color=#dddddd]Смешайте указанные в рецепте химикаты с [bold]Кровью заражённого[/bold] (получите у пациента), чтобы создать [color=#83a7b1]Незавершённую вакцину[/color].[/color] + + + + + + +[head=3][color=#ffbb77]Синтез вакцины (Антивирусина)[/color][/head] + +[color=#dddddd]Поместите полученную [color=#83a7b1]Вирусин[/color] и единицу [bold]Чистой крови[/bold] (здорового человека) в Вакцинатор. Он переработает их в [color=#86caf7]Антивирусин[/color] (20ед).[/color] + + + +[head=3][color=#ffbb77]Антивирусин+[/color][/head] + +[color=#dddddd]Можно создать улучшенную версию, смешав обычную [color=#86caf7]Антивирусин[/color] с Криптобиолином, Сигинатом и Кровью заражённого. Она даёт [color=#8192ea]постоянный иммунитет[/color].[/color] + + + + + + + +[head=2][color=#ffaa66]Действие вакцины[/color][/head] + +[color=#dddddd]При инъекции пациенту (10ед обычной или 7ед Антивирусина+):[/color] + +[head=3][color=#ffbb77]Таймер лечения[/color][/head] +[color=#dddddd]Запускается процесс исцеления. Время зависит от уровня защиты («Щита») болезни: [color=#ff9999]2 минуты + 30 сек за каждый уровень щита[/color].[/color] + +[head=3][color=#ffbb77]Побочный эффект[/color][/head] +[color=#dddddd]Пока вакцина действует, [bold]скорость бега пациента снижается в 2 раза[/bold]. Это делает его уязвимым![/color] + +[head=3][color=#ffbb77]Результат[/color][/head] +[color=#dddddd]По истечении таймера болезнь полностью исчезает. Если использовалась Вакцина+, пациент получает [color=#99ff99]иммунитет[/color].[/color] + +[color=#dddddd][bold]Будьте осторожны[/bold]: болезнь может попытаться убить ослабленного пациента, пока вакцина действует![/color] From 70ff8f4f0a2ac8febeb7a12a9263a64b333fc108 Mon Sep 17 00:00:00 2001 From: A-Mironov <65418470+Alexnov33X@users.noreply.github.com> Date: Thu, 22 Jan 2026 02:16:59 +0300 Subject: [PATCH 3/7] Fixes --- .../Disease/UI/DiseaseInfoWindow.xaml | 18 ++++++------- .../Guidebook/_Sunrise/Antagonist/Disease.xml | 26 +++++++------------ 2 files changed, 19 insertions(+), 25 deletions(-) diff --git a/Content.Client/_Sunrise/Disease/UI/DiseaseInfoWindow.xaml b/Content.Client/_Sunrise/Disease/UI/DiseaseInfoWindow.xaml index d57ad7a6526..ee70a34ebbf 100644 --- a/Content.Client/_Sunrise/Disease/UI/DiseaseInfoWindow.xaml +++ b/Content.Client/_Sunrise/Disease/UI/DiseaseInfoWindow.xaml @@ -1,36 +1,36 @@ - diff --git a/Resources/ServerInfo/Guidebook/_Sunrise/Antagonist/Disease.xml b/Resources/ServerInfo/Guidebook/_Sunrise/Antagonist/Disease.xml index 6305b58216b..ea8a506fdb7 100644 --- a/Resources/ServerInfo/Guidebook/_Sunrise/Antagonist/Disease.xml +++ b/Resources/ServerInfo/Guidebook/_Sunrise/Antagonist/Disease.xml @@ -26,44 +26,38 @@ [color=#dddddd]Кроме основных симптомов, у болезни есть перечень других, таких как:[/color] [head=3][color=#ffbb77]Непроизвольные слёзы (10 ОЭ)[/color][/head] - + [color=#999999][italic]У заражённых активно слезятся глаза, из-за чего кажется, что они плачут.[/italic][/color] - + [head=3][color=#ffbb77]Изнеможение (15 ОЭ)[/color][/head] - + [color=#999999][italic]Вирус вызывает разрушение мышечных волокон, приводящее к атрофии и сопровождающееся слабостью. Снижает общую мобильность.[/italic][/color] - + [head=3][color=#ffbb77]Сонливость (20 ОЭ)[/color][/head] - + [color=#999999][italic]У заражённых появляется постоянное желание спать, с которым они иногда не могут справиться.[/italic][/color] - + [head=3][color=#ffbb77]Судороги (20 ОЭ)[/color][/head] - [color=#999999][italic]Длительная болезнь вызывает гиперстимуляцию двигательных нейронов, в результате чего больные могут испытывать перенапряжение мышц, приводящее к судорогам.[/italic][/color] - + [head=3][color=#ffbb77]Немота (25 ОЭ)[/color][/head] - [color=#999999][italic]Мутация вызывает повреждение подъязычного нерва, приводя к параличу мышц языка, из-за чего больные теряют возможность нормально говорить.[/italic][/color] - [head=3][color=#ffbb77]Тошнота (25 ОЭ)[/color][/head] - [color=#999999][italic]Заражённых начинает тошнить, вызывая рвоту.[/italic][/color] - + [head=3][color=#ffbb77]Кровопотеря (30 ОЭ)[/color][/head] - [color=#999999][italic]Вирус вызывает денатурацию гемоглобина крови, из-за чего у всех носителей появляется тяжёлая степень анемии.[/italic][/color] - + [head=3][color=#ffbb77]Слепота (40 ОЭ)[/color][/head] - [color=#999999][italic]Длительная болезнь приводит к отмиранию зрительного нерва, что приводит к практически полной слепоте больного.[/italic][/color] - + [head=2][color=#ffaa66]Базовые противодействия[/color][/head] From 02f965570076769fcbd831889908a553513ab71b Mon Sep 17 00:00:00 2001 From: A-Mironov <65418470+Alexnov33X@users.noreply.github.com> Date: Sat, 24 Jan 2026 23:36:43 +0300 Subject: [PATCH 4/7] =?UTF-8?q?=D0=90=20=D0=B2=D0=B0=D0=BA=D1=86=D0=B8?= =?UTF-8?q?=D0=BD=D0=B0=20=D0=BD=D0=B5=20=D0=BB=D0=B5=D1=87=D0=B8=D0=BB?= =?UTF-8?q?=D0=B0=20=D0=B4=D0=BE=20=D0=BA=D0=BE=D0=BD=D1=86=D0=B0=20=D0=BB?= =?UTF-8?q?=D0=BE=D0=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Content.Server/_Sunrise/Disease/SickSystem.cs | 3 +++ Content.Shared/_Sunrise/Disease/CureDiseaseInfection.cs | 3 +++ Content.Shared/_Sunrise/Disease/DiseaseVaccineTimerSystem.cs | 2 +- Resources/Prototypes/_Sunrise/Roles/Antags/disease.yml | 2 +- 4 files changed, 8 insertions(+), 2 deletions(-) diff --git a/Content.Server/_Sunrise/Disease/SickSystem.cs b/Content.Server/_Sunrise/Disease/SickSystem.cs index 39466de9eea..5f90a91c14b 100644 --- a/Content.Server/_Sunrise/Disease/SickSystem.cs +++ b/Content.Server/_Sunrise/Disease/SickSystem.cs @@ -117,6 +117,9 @@ public void OnShut(EntityUid uid, SickComponent component, ComponentShutdown arg solution.AddReagent(reagentId, FixedPoint2.New((int)stream.BloodReferenceSolution.MaxVolume)); } + if (solution.Volume == 0) + return; + _bloodstream.ChangeBloodReagents(uid, solution); } } diff --git a/Content.Shared/_Sunrise/Disease/CureDiseaseInfection.cs b/Content.Shared/_Sunrise/Disease/CureDiseaseInfection.cs index 3695406e5f5..02a6a21630f 100644 --- a/Content.Shared/_Sunrise/Disease/CureDiseaseInfection.cs +++ b/Content.Shared/_Sunrise/Disease/CureDiseaseInfection.cs @@ -2,12 +2,14 @@ using Content.Shared.EntityEffects; using Robust.Shared.Prototypes; +using Robust.Shared.Timing; namespace Content.Shared._Sunrise.Disease; public sealed partial class CureDiseaseInfectionEntityEffectSystem : EntityEffectSystem { [Dependency] private readonly EntityManager _entityManager = default!; + [Dependency] private readonly IGameTiming _gameTiming = default!; protected override void Effect(Entity entity, ref EntityEffectEvent args) { @@ -18,6 +20,7 @@ protected override void Effect(Entity entity, ref EntityEffectEve var comp = _entityManager.EnsureComponent(entity.Owner); comp.Immune = args.Effect.Innoculate; comp.Delay = TimeSpan.FromMinutes(2) + TimeSpan.FromSeconds(disease.Shield * 30); + comp.ReadyAt = _gameTiming.CurTime + comp.Delay; } } } diff --git a/Content.Shared/_Sunrise/Disease/DiseaseVaccineTimerSystem.cs b/Content.Shared/_Sunrise/Disease/DiseaseVaccineTimerSystem.cs index 0eceeb571d8..07f5721b5a7 100644 --- a/Content.Shared/_Sunrise/Disease/DiseaseVaccineTimerSystem.cs +++ b/Content.Shared/_Sunrise/Disease/DiseaseVaccineTimerSystem.cs @@ -45,7 +45,7 @@ public override void Update(float frameTime) if (!HasComp(uid)) { RemComp(uid); - return; + continue; } RemComp(uid); diff --git a/Resources/Prototypes/_Sunrise/Roles/Antags/disease.yml b/Resources/Prototypes/_Sunrise/Roles/Antags/disease.yml index 802785d2528..b4e199192c1 100644 --- a/Resources/Prototypes/_Sunrise/Roles/Antags/disease.yml +++ b/Resources/Prototypes/_Sunrise/Roles/Antags/disease.yml @@ -10,7 +10,7 @@ context: "ghost" - type: MovementSpeedModifier baseWalkSpeed: 6 - baseSprintSpeed: 20 + baseSprintSpeed: 10 - type: Sprite noRot: true drawdepth: Ghosts From 74733fbc418f95a89469b34aa31fdda9f61f58ed Mon Sep 17 00:00:00 2001 From: A-Mironov <65418470+Alexnov33X@users.noreply.github.com> Date: Wed, 21 Jan 2026 21:18:48 +0300 Subject: [PATCH 5/7] test --- .../_Sunrise/Disease/UI/DiseaseInfoWindow.xaml | 18 +++++++++--------- .../_Sunrise/Disease/SmallDiseaseRuleSystem.cs | 8 +++----- .../_Sunrise/Disease/CureDiseaseInfection.cs | 3 --- 3 files changed, 12 insertions(+), 17 deletions(-) diff --git a/Content.Client/_Sunrise/Disease/UI/DiseaseInfoWindow.xaml b/Content.Client/_Sunrise/Disease/UI/DiseaseInfoWindow.xaml index ee70a34ebbf..d57ad7a6526 100644 --- a/Content.Client/_Sunrise/Disease/UI/DiseaseInfoWindow.xaml +++ b/Content.Client/_Sunrise/Disease/UI/DiseaseInfoWindow.xaml @@ -1,36 +1,36 @@ - diff --git a/Content.Server/_Sunrise/Disease/SmallDiseaseRuleSystem.cs b/Content.Server/_Sunrise/Disease/SmallDiseaseRuleSystem.cs index e2bd6b8436d..a218be54e27 100644 --- a/Content.Server/_Sunrise/Disease/SmallDiseaseRuleSystem.cs +++ b/Content.Server/_Sunrise/Disease/SmallDiseaseRuleSystem.cs @@ -47,8 +47,9 @@ protected override void Started(EntityUid uid, SmallDiseaseRuleComponent compone // 2. Spawn the Disease Entity (Dummy) var diseaseUid = Spawn("MobDisease", MapCoordinates.Nullspace); if (!TryComp(diseaseUid, out var diseaseComp)) + { return; - + } // 3. Configure Symptoms // Always add Cough @@ -73,10 +74,7 @@ protected override void Started(EntityUid uid, SmallDiseaseRuleComponent compone if (availableSymptoms.Count == 0) break; var pick = _random.Pick(availableSymptoms); - var cost = pick.Cost.GetValueOrDefault("DiseasePoints", 100); - - if (cost > component.TargetSymptomPoints) - continue; + var cost = pick.Cost.GetValueOrDefault("DiseasePoints", 0); // Avoid adding same symptom twice if (!diseaseComp.Symptoms.ContainsKey(pick.ID)) diff --git a/Content.Shared/_Sunrise/Disease/CureDiseaseInfection.cs b/Content.Shared/_Sunrise/Disease/CureDiseaseInfection.cs index 02a6a21630f..3695406e5f5 100644 --- a/Content.Shared/_Sunrise/Disease/CureDiseaseInfection.cs +++ b/Content.Shared/_Sunrise/Disease/CureDiseaseInfection.cs @@ -2,14 +2,12 @@ using Content.Shared.EntityEffects; using Robust.Shared.Prototypes; -using Robust.Shared.Timing; namespace Content.Shared._Sunrise.Disease; public sealed partial class CureDiseaseInfectionEntityEffectSystem : EntityEffectSystem { [Dependency] private readonly EntityManager _entityManager = default!; - [Dependency] private readonly IGameTiming _gameTiming = default!; protected override void Effect(Entity entity, ref EntityEffectEvent args) { @@ -20,7 +18,6 @@ protected override void Effect(Entity entity, ref EntityEffectEve var comp = _entityManager.EnsureComponent(entity.Owner); comp.Immune = args.Effect.Innoculate; comp.Delay = TimeSpan.FromMinutes(2) + TimeSpan.FromSeconds(disease.Shield * 30); - comp.ReadyAt = _gameTiming.CurTime + comp.Delay; } } } From c807ee33e0098c9fe4118e59bd9b3acd830fda3a Mon Sep 17 00:00:00 2001 From: A-Mironov <65418470+Alexnov33X@users.noreply.github.com> Date: Sat, 14 Mar 2026 11:15:49 +0300 Subject: [PATCH 6/7] =?UTF-8?q?=D0=90=D0=BD=D0=BE=D0=BD=D1=81=20=D0=B4?= =?UTF-8?q?=D0=BB=D1=8F=20=D1=82=D1=83=D0=BF=D0=BE=D0=B9=20=D0=B1=D0=BE?= =?UTF-8?q?=D0=BB=D0=B5=D0=B7=D0=BD=D0=B8=20+=20=D0=B7=D0=BE=D0=BC=D0=B1?= =?UTF-8?q?=D0=B8=20=D0=BE=D1=87=D0=BA=D0=B8=20=D0=BF=D0=BE=D0=B2=D1=8B?= =?UTF-8?q?=D1=88=D0=B5=D0=BD=D1=8B=20=D0=B4=D0=BE=20500?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../_Sunrise/Disease/SmallDiseaseRuleSystem.cs | 14 +++++++++++--- .../_Sunrise/Catalog/disease_catalog.yml | 2 +- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/Content.Server/_Sunrise/Disease/SmallDiseaseRuleSystem.cs b/Content.Server/_Sunrise/Disease/SmallDiseaseRuleSystem.cs index a218be54e27..31df2924b62 100644 --- a/Content.Server/_Sunrise/Disease/SmallDiseaseRuleSystem.cs +++ b/Content.Server/_Sunrise/Disease/SmallDiseaseRuleSystem.cs @@ -1,16 +1,15 @@ using Content.Shared._Sunrise.Disease; using Content.Server.GameTicking.Rules; using Content.Shared.GameTicking.Components; -using Robust.Server.GameObjects; using Robust.Shared.Random; using Robust.Shared.Prototypes; using Content.Shared.Store; -using System.Linq; using Content.Shared.Humanoid; using Content.Shared.Mobs.Components; -using Content.Shared.Mind; using Content.Shared.Mind.Components; using Robust.Shared.Map; +using Content.Server.Chat.Systems; +using Robust.Shared.Timing; namespace Content.Server._Sunrise.Disease; @@ -20,11 +19,20 @@ public sealed class SmallDiseaseRuleSystem : GameRuleSystem + { + var message = Loc.GetString("disease-biohazard-announcement"); + var sender = Loc.GetString("disease-biohazard-announcement-sender"); + + _chatSystem.DispatchGlobalAnnouncement(message, sender, playDefault: true, colorOverride: Color.Red); + }); + // 1. Find potential victims (Humanoid, Has Mind, Not Dead, Not Sick) var query = EntityQueryEnumerator(); var candidates = new List(); diff --git a/Resources/Prototypes/_Sunrise/Catalog/disease_catalog.yml b/Resources/Prototypes/_Sunrise/Catalog/disease_catalog.yml index d74c3702732..932785b775d 100644 --- a/Resources/Prototypes/_Sunrise/Catalog/disease_catalog.yml +++ b/Resources/Prototypes/_Sunrise/Catalog/disease_catalog.yml @@ -145,7 +145,7 @@ icon: { sprite: /Textures/_Sunrise/Actions/disease.rsi, state: lethal } raiseProductEventOnUser: true cost: - DiseasePoints: 200 + DiseasePoints: 500 categories: - DiseaseSymptomsCategory conditions: From 45614a4263e494c0099a80c74a7ef8046eb330b5 Mon Sep 17 00:00:00 2001 From: A-Mironov <65418470+Alexnov33X@users.noreply.github.com> Date: Sat, 14 Mar 2026 12:19:16 +0300 Subject: [PATCH 7/7] =?UTF-8?q?=D0=9F=D0=BE=20=D0=BF=D1=80=D0=BE=D1=81?= =?UTF-8?q?=D1=8C=D0=B1=D0=B5=20=D0=BA=D1=80=D0=BE=D0=BB=D1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../_Sunrise/Disease/UI/DiseaseInfoWindow.xaml | 18 +++++++++--------- Content.Server/_Sunrise/Disease/SickSystem.cs | 17 +++++++++++------ .../_Sunrise/Catalog/disease_catalog.yml | 2 +- 3 files changed, 21 insertions(+), 16 deletions(-) diff --git a/Content.Client/_Sunrise/Disease/UI/DiseaseInfoWindow.xaml b/Content.Client/_Sunrise/Disease/UI/DiseaseInfoWindow.xaml index d57ad7a6526..ee70a34ebbf 100644 --- a/Content.Client/_Sunrise/Disease/UI/DiseaseInfoWindow.xaml +++ b/Content.Client/_Sunrise/Disease/UI/DiseaseInfoWindow.xaml @@ -1,36 +1,36 @@ - diff --git a/Content.Server/_Sunrise/Disease/SickSystem.cs b/Content.Server/_Sunrise/Disease/SickSystem.cs index 5f90a91c14b..385c6b65483 100644 --- a/Content.Server/_Sunrise/Disease/SickSystem.cs +++ b/Content.Server/_Sunrise/Disease/SickSystem.cs @@ -3,26 +3,20 @@ 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; @@ -50,6 +44,7 @@ public sealed class SickSystem : SharedSickSystem [Dependency] private readonly DamageableSystem _damageableSystem = default!; [Dependency] private readonly IPrototypeManager _prototypeManager = default!; [Dependency] private readonly SharedStunSystem _stun = default!; + [Dependency] private readonly UserInterfaceSystem _ui = default!; private EntityLookupSystem Lookup => _entityManager.System(); public override void Initialize() { @@ -160,6 +155,16 @@ public override void Update(float frameTime) AddMoney(component.owner, 5); _popupSystem.PopupEntity(Loc.GetString("disease-infect-reward", ("points", 5)), component.owner, component.owner, PopupType.Medium); + var state = new DiseaseInfoState( + diseaseComp.BaseInfectChance, + diseaseComp.CoughSneezeInfectChance, + diseaseComp.Lethal, + diseaseComp.Shield, + diseaseComp.Infected.Count, + diseaseComp.SickOfAllTime + ); + _ui.SetUiState(component.owner, DiseaseInfoUiKey.Key, state); + component.Inited = true; } else diff --git a/Resources/Prototypes/_Sunrise/Catalog/disease_catalog.yml b/Resources/Prototypes/_Sunrise/Catalog/disease_catalog.yml index 932785b775d..cb28b2e06ae 100644 --- a/Resources/Prototypes/_Sunrise/Catalog/disease_catalog.yml +++ b/Resources/Prototypes/_Sunrise/Catalog/disease_catalog.yml @@ -7,7 +7,7 @@ cost: DiseasePoints: 0 categories: - - DiseaseInfectCategory + - DiseaseSymptomsCategory conditions: - !type:ListingLimitedStockCondition stock: 1