Remove diseases (#15684)
This commit is contained in:
@@ -1,8 +0,0 @@
|
|||||||
using Content.Shared.Atmos.Miasma;
|
|
||||||
using Robust.Shared.GameStates;
|
|
||||||
|
|
||||||
namespace Content.Client.Atmos.Miasma;
|
|
||||||
|
|
||||||
[NetworkedComponent, RegisterComponent]
|
|
||||||
public sealed class FliesComponent : SharedFliesComponent
|
|
||||||
{ }
|
|
||||||
@@ -1,41 +0,0 @@
|
|||||||
using Robust.Client.GameObjects;
|
|
||||||
using Robust.Shared.Utility;
|
|
||||||
|
|
||||||
namespace Content.Client.Atmos.Miasma;
|
|
||||||
|
|
||||||
public sealed class FliesSystem : EntitySystem
|
|
||||||
{
|
|
||||||
public override void Initialize()
|
|
||||||
{
|
|
||||||
SubscribeLocalEvent<FliesComponent, ComponentStartup>(FliesAdded);
|
|
||||||
SubscribeLocalEvent<FliesComponent, ComponentShutdown>(FliesRemoved);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void FliesRemoved(EntityUid uid, FliesComponent component, ComponentShutdown args)
|
|
||||||
{
|
|
||||||
if (!TryComp<SpriteComponent>(uid, out var sprite))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (!sprite.LayerMapTryGet(FliesKey.Key, out var layer))
|
|
||||||
return;
|
|
||||||
|
|
||||||
sprite.RemoveLayer(layer);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void FliesAdded(EntityUid uid, FliesComponent component, ComponentStartup args)
|
|
||||||
{
|
|
||||||
if (!TryComp<SpriteComponent>(uid, out var sprite))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (sprite.LayerMapTryGet(FliesKey.Key, out var _))
|
|
||||||
return;
|
|
||||||
|
|
||||||
var layer = sprite.AddLayer(new SpriteSpecifier.Rsi(new ("Objects/Misc/flies.rsi"), "flies"));
|
|
||||||
sprite.LayerMapSet(FliesKey.Key, layer);
|
|
||||||
}
|
|
||||||
|
|
||||||
private enum FliesKey
|
|
||||||
{
|
|
||||||
Key,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
using Robust.Client.GameObjects;
|
|
||||||
using Content.Shared.Disease;
|
|
||||||
|
|
||||||
namespace Content.Client.Disease
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Controls client-side visuals for the
|
|
||||||
/// disease machines.
|
|
||||||
/// </summary>
|
|
||||||
public sealed class DiseaseMachineSystem : VisualizerSystem<DiseaseMachineVisualsComponent>
|
|
||||||
{
|
|
||||||
protected override void OnAppearanceChange(EntityUid uid, DiseaseMachineVisualsComponent component, ref AppearanceChangeEvent args)
|
|
||||||
{
|
|
||||||
if (args.Sprite == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (AppearanceSystem.TryGetData<bool>(uid, DiseaseMachineVisuals.IsOn, out var isOn, args.Component)
|
|
||||||
&& AppearanceSystem.TryGetData<bool>(uid, DiseaseMachineVisuals.IsRunning, out var isRunning, args.Component))
|
|
||||||
{
|
|
||||||
var state = isRunning ? component.RunningState : component.IdleState;
|
|
||||||
args.Sprite.LayerSetVisible(DiseaseMachineVisualLayers.IsOn, isOn);
|
|
||||||
args.Sprite.LayerSetState(DiseaseMachineVisualLayers.IsRunning, state);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public enum DiseaseMachineVisualLayers : byte
|
|
||||||
{
|
|
||||||
IsOn,
|
|
||||||
IsRunning
|
|
||||||
}
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
namespace Content.Client.Disease;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Holds the idle and running state for machines to control
|
|
||||||
/// playing animtions on the client.
|
|
||||||
/// </summary>
|
|
||||||
[RegisterComponent]
|
|
||||||
public sealed class DiseaseMachineVisualsComponent : Component
|
|
||||||
{
|
|
||||||
[DataField("idleState", required: true)]
|
|
||||||
public string IdleState = default!;
|
|
||||||
|
|
||||||
[DataField("runningState", required: true)]
|
|
||||||
public string RunningState = default!;
|
|
||||||
}
|
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using Content.Shared.Damage;
|
using Content.Shared.Damage;
|
||||||
using Content.Shared.Damage.Prototypes;
|
using Content.Shared.Damage.Prototypes;
|
||||||
using Content.Shared.Disease.Components;
|
|
||||||
using Content.Shared.FixedPoint;
|
using Content.Shared.FixedPoint;
|
||||||
using Content.Shared.IdentityManagement;
|
using Content.Shared.IdentityManagement;
|
||||||
using Content.Shared.MedicalScanner;
|
using Content.Shared.MedicalScanner;
|
||||||
@@ -32,20 +31,11 @@ namespace Content.Client.HealthAnalyzer.UI
|
|||||||
entities.TryGetComponent<MetaDataComponent>(msg.TargetEntity.Value, out var metaData))
|
entities.TryGetComponent<MetaDataComponent>(msg.TargetEntity.Value, out var metaData))
|
||||||
entityName = Identity.Name(msg.TargetEntity.Value, entities);
|
entityName = Identity.Name(msg.TargetEntity.Value, entities);
|
||||||
|
|
||||||
IReadOnlyDictionary<string, FixedPoint2> DamagePerGroup = damageable.DamagePerGroup;
|
IReadOnlyDictionary<string, FixedPoint2> damagePerGroup = damageable.DamagePerGroup;
|
||||||
IReadOnlyDictionary<string, FixedPoint2> DamagePerType = damageable.Damage.DamageDict;
|
IReadOnlyDictionary<string, FixedPoint2> damagePerType = damageable.Damage.DamageDict;
|
||||||
|
|
||||||
text.Append($"{Loc.GetString("health-analyzer-window-entity-health-text", ("entityName", entityName))}\n");
|
text.Append($"{Loc.GetString("health-analyzer-window-entity-health-text", ("entityName", entityName))}\n");
|
||||||
|
|
||||||
// Status Effects / Components
|
|
||||||
if (entities.HasComponent<DiseasedComponent>(msg.TargetEntity))
|
|
||||||
{
|
|
||||||
text.Append($"{Loc.GetString("disease-scanner-diseased")}\n");
|
|
||||||
}else
|
|
||||||
{
|
|
||||||
text.Append($"{Loc.GetString("disease-scanner-not-diseased")}\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Damage
|
// Damage
|
||||||
text.Append($"\n{Loc.GetString("health-analyzer-window-entity-damage-total-text", ("amount", damageable.TotalDamage))}\n");
|
text.Append($"\n{Loc.GetString("health-analyzer-window-entity-damage-total-text", ("amount", damageable.TotalDamage))}\n");
|
||||||
|
|
||||||
@@ -54,14 +44,14 @@ namespace Content.Client.HealthAnalyzer.UI
|
|||||||
var protos = IoCManager.Resolve<IPrototypeManager>();
|
var protos = IoCManager.Resolve<IPrototypeManager>();
|
||||||
|
|
||||||
// Show the total damage and type breakdown for each damage group.
|
// Show the total damage and type breakdown for each damage group.
|
||||||
foreach (var (damageGroupId, damageAmount) in DamagePerGroup)
|
foreach (var (damageGroupId, damageAmount) in damagePerGroup)
|
||||||
{
|
{
|
||||||
text.Append($"\n{Loc.GetString("health-analyzer-window-damage-group-text", ("damageGroup", Loc.GetString("health-analyzer-window-damage-group-" + damageGroupId)), ("amount", damageAmount))}");
|
text.Append($"\n{Loc.GetString("health-analyzer-window-damage-group-text", ("damageGroup", Loc.GetString("health-analyzer-window-damage-group-" + damageGroupId)), ("amount", damageAmount))}");
|
||||||
// Show the damage for each type in that group.
|
// Show the damage for each type in that group.
|
||||||
var group = protos.Index<DamageGroupPrototype>(damageGroupId);
|
var group = protos.Index<DamageGroupPrototype>(damageGroupId);
|
||||||
foreach (var type in group.DamageTypes)
|
foreach (var type in group.DamageTypes)
|
||||||
{
|
{
|
||||||
if (DamagePerType.TryGetValue(type, out var typeAmount))
|
if (damagePerType.TryGetValue(type, out var typeAmount))
|
||||||
{
|
{
|
||||||
// If damage types are allowed to belong to more than one damage group, they may appear twice here. Mark them as duplicate.
|
// If damage types are allowed to belong to more than one damage group, they may appear twice here. Mark them as duplicate.
|
||||||
if (!shownTypes.Contains(type))
|
if (!shownTypes.Contains(type))
|
||||||
|
|||||||
9
Content.Client/Medical/DiseaseSystem.cs
Normal file
9
Content.Client/Medical/DiseaseSystem.cs
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
namespace Content.Client.Medical;
|
||||||
|
|
||||||
|
/* Here be dragons */
|
||||||
|
|
||||||
|
public enum DiseaseMachineVisualLayers : byte
|
||||||
|
{
|
||||||
|
IsOn,
|
||||||
|
IsRunning
|
||||||
|
}
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
using System.Threading.Tasks;
|
|
||||||
using Content.Server.Disease;
|
|
||||||
using Content.Shared.Disease;
|
|
||||||
using NUnit.Framework;
|
|
||||||
using Robust.Shared.GameObjects;
|
|
||||||
using Robust.Shared.IoC;
|
|
||||||
using Robust.Shared.Prototypes;
|
|
||||||
|
|
||||||
namespace Content.IntegrationTests.Tests.Disease;
|
|
||||||
|
|
||||||
[TestFixture]
|
|
||||||
[TestOf(typeof(DiseaseSystem))]
|
|
||||||
public sealed class DeviceNetworkTest
|
|
||||||
{
|
|
||||||
[Test]
|
|
||||||
public async Task AddAllDiseases()
|
|
||||||
{
|
|
||||||
await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{NoClient = true});
|
|
||||||
var server = pairTracker.Pair.Server;
|
|
||||||
var testMap = await PoolManager.CreateTestMap(pairTracker);
|
|
||||||
await server.WaitPost(() =>
|
|
||||||
{
|
|
||||||
var protoManager = IoCManager.Resolve<IPrototypeManager>();
|
|
||||||
var entManager = IoCManager.Resolve<IEntityManager>();
|
|
||||||
var entSysManager = IoCManager.Resolve<IEntitySystemManager>();
|
|
||||||
var diseaseSystem = entSysManager.GetEntitySystem<DiseaseSystem>();
|
|
||||||
|
|
||||||
var sickEntity = entManager.SpawnEntity("MobHuman", testMap.GridCoords);
|
|
||||||
foreach (var diseaseProto in protoManager.EnumeratePrototypes<DiseasePrototype>())
|
|
||||||
{
|
|
||||||
diseaseSystem.TryAddDisease(sickEntity, diseaseProto);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,48 +0,0 @@
|
|||||||
using System.Threading.Tasks;
|
|
||||||
using Content.Shared.Disease;
|
|
||||||
using NUnit.Framework;
|
|
||||||
using Robust.Shared.Prototypes;
|
|
||||||
|
|
||||||
namespace Content.IntegrationTests.Tests;
|
|
||||||
|
|
||||||
[TestFixture]
|
|
||||||
public sealed class DiseaseTest
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Asserts that a disease prototype has valid stages for its effects and cures.
|
|
||||||
/// </summary>
|
|
||||||
[Test]
|
|
||||||
public async Task Stages()
|
|
||||||
{
|
|
||||||
await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{NoClient = true});
|
|
||||||
var server = pairTracker.Pair.Server;
|
|
||||||
|
|
||||||
var protoManager = server.ResolveDependency<IPrototypeManager>();
|
|
||||||
|
|
||||||
await server.WaitAssertion(() =>
|
|
||||||
{
|
|
||||||
foreach (var proto in protoManager.EnumeratePrototypes<DiseasePrototype>())
|
|
||||||
{
|
|
||||||
var stagesLength = proto.Stages.Count;
|
|
||||||
|
|
||||||
foreach (var effect in proto.Effects)
|
|
||||||
{
|
|
||||||
for (var i = 0; i < effect.Stages.Length; i++)
|
|
||||||
{
|
|
||||||
Assert.That(i >= 0 && i < stagesLength, $"Disease {proto.ID} has an effect with an incorrect stage, {i}!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var cure in proto.Cures)
|
|
||||||
{
|
|
||||||
for (var i = 0; i < cure.Stages.Length; i++)
|
|
||||||
{
|
|
||||||
Assert.That(i >= 0 && i < stagesLength, $"Disease {proto.ID} has a cure with an incorrect stage, {i}!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
await pairTracker.CleanReturnAsync();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,16 +1,5 @@
|
|||||||
using Content.Server.Atmos.Miasma;
|
|
||||||
using Content.Server.Body.Components;
|
|
||||||
using Content.Server.Body.Systems;
|
|
||||||
using Content.Server.Disease.Components;
|
|
||||||
using Content.Server.Disease;
|
|
||||||
using Content.Server.Nutrition.Components;
|
|
||||||
using Content.Server.Nutrition.EntitySystems;
|
|
||||||
using Content.Shared.Administration;
|
using Content.Shared.Administration;
|
||||||
using Content.Shared.Damage;
|
|
||||||
using Content.Shared.Jittering;
|
|
||||||
using Content.Shared.Nutrition.Components;
|
|
||||||
using Content.Shared.Rejuvenate;
|
using Content.Shared.Rejuvenate;
|
||||||
using Content.Shared.StatusEffect;
|
|
||||||
using Robust.Server.Player;
|
using Robust.Server.Player;
|
||||||
using Robust.Shared.Console;
|
using Robust.Shared.Console;
|
||||||
|
|
||||||
|
|||||||
@@ -6,12 +6,9 @@ using Content.Server.Atmos.EntitySystems;
|
|||||||
using Content.Server.Body.Components;
|
using Content.Server.Body.Components;
|
||||||
using Content.Server.Body.Systems;
|
using Content.Server.Body.Systems;
|
||||||
using Content.Server.Damage.Systems;
|
using Content.Server.Damage.Systems;
|
||||||
using Content.Server.Disease;
|
|
||||||
using Content.Server.Disease.Components;
|
|
||||||
using Content.Server.Electrocution;
|
using Content.Server.Electrocution;
|
||||||
using Content.Server.Explosion.EntitySystems;
|
using Content.Server.Explosion.EntitySystems;
|
||||||
using Content.Server.GhostKick;
|
using Content.Server.GhostKick;
|
||||||
using Content.Server.Interaction.Components;
|
|
||||||
using Content.Server.Medical;
|
using Content.Server.Medical;
|
||||||
using Content.Server.Nutrition.EntitySystems;
|
using Content.Server.Nutrition.EntitySystems;
|
||||||
using Content.Server.Pointing.Components;
|
using Content.Server.Pointing.Components;
|
||||||
@@ -30,7 +27,6 @@ using Content.Shared.Body.Part;
|
|||||||
using Content.Shared.Clothing.Components;
|
using Content.Shared.Clothing.Components;
|
||||||
using Content.Shared.Damage;
|
using Content.Shared.Damage;
|
||||||
using Content.Shared.Database;
|
using Content.Shared.Database;
|
||||||
using Content.Shared.Disease;
|
|
||||||
using Content.Shared.Electrocution;
|
using Content.Shared.Electrocution;
|
||||||
using Content.Shared.Interaction.Components;
|
using Content.Shared.Interaction.Components;
|
||||||
using Content.Shared.Inventory;
|
using Content.Shared.Inventory;
|
||||||
@@ -44,7 +40,6 @@ using Content.Shared.Popups;
|
|||||||
using Content.Shared.Tabletop.Components;
|
using Content.Shared.Tabletop.Components;
|
||||||
using Content.Shared.Verbs;
|
using Content.Shared.Verbs;
|
||||||
using Robust.Server.GameObjects;
|
using Robust.Server.GameObjects;
|
||||||
using Robust.Server.GameStates;
|
|
||||||
using Robust.Shared.Map;
|
using Robust.Shared.Map;
|
||||||
using Robust.Shared.Map.Components;
|
using Robust.Shared.Map.Components;
|
||||||
using Robust.Shared.Physics;
|
using Robust.Shared.Physics;
|
||||||
@@ -53,7 +48,6 @@ using Robust.Shared.Physics.Systems;
|
|||||||
using Robust.Shared.Player;
|
using Robust.Shared.Player;
|
||||||
using Robust.Shared.Random;
|
using Robust.Shared.Random;
|
||||||
using Robust.Shared.Utility;
|
using Robust.Shared.Utility;
|
||||||
using Robust.Shared.Audio;
|
|
||||||
using Timer = Robust.Shared.Timing.Timer;
|
using Timer = Robust.Shared.Timing.Timer;
|
||||||
using Content.Shared.Cluwne;
|
using Content.Shared.Cluwne;
|
||||||
|
|
||||||
@@ -65,7 +59,6 @@ public sealed partial class AdminVerbSystem
|
|||||||
[Dependency] private readonly BloodstreamSystem _bloodstreamSystem = default!;
|
[Dependency] private readonly BloodstreamSystem _bloodstreamSystem = default!;
|
||||||
[Dependency] private readonly BodySystem _bodySystem = default!;
|
[Dependency] private readonly BodySystem _bodySystem = default!;
|
||||||
[Dependency] private readonly CreamPieSystem _creamPieSystem = default!;
|
[Dependency] private readonly CreamPieSystem _creamPieSystem = default!;
|
||||||
[Dependency] private readonly DiseaseSystem _diseaseSystem = default!;
|
|
||||||
[Dependency] private readonly ElectrocutionSystem _electrocutionSystem = default!;
|
[Dependency] private readonly ElectrocutionSystem _electrocutionSystem = default!;
|
||||||
[Dependency] private readonly EntityStorageSystem _entityStorageSystem = default!;
|
[Dependency] private readonly EntityStorageSystem _entityStorageSystem = default!;
|
||||||
[Dependency] private readonly ExplosionSystem _explosionSystem = default!;
|
[Dependency] private readonly ExplosionSystem _explosionSystem = default!;
|
||||||
@@ -196,24 +189,6 @@ public sealed partial class AdminVerbSystem
|
|||||||
};
|
};
|
||||||
args.Verbs.Add(disposalBin);
|
args.Verbs.Add(disposalBin);
|
||||||
|
|
||||||
if (TryComp<DiseaseCarrierComponent>(args.Target, out var carrier))
|
|
||||||
{
|
|
||||||
Verb lungCancer = new()
|
|
||||||
{
|
|
||||||
Text = "Lung Cancer",
|
|
||||||
Category = VerbCategory.Smite,
|
|
||||||
Icon = new SpriteSpecifier.Rsi(new ("/Textures/Mobs/Species/Human/organs.rsi"), "lung-l"),
|
|
||||||
Act = () =>
|
|
||||||
{
|
|
||||||
_diseaseSystem.TryInfect(carrier, _prototypeManager.Index<DiseasePrototype>("StageIIIALungCancer"),
|
|
||||||
1.0f, true);
|
|
||||||
},
|
|
||||||
Impact = LogImpact.Extreme,
|
|
||||||
Message = Loc.GetString("admin-smite-lung-cancer-description")
|
|
||||||
};
|
|
||||||
args.Verbs.Add(lungCancer);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (TryComp<DamageableComponent>(args.Target, out var damageable) &&
|
if (TryComp<DamageableComponent>(args.Target, out var damageable) &&
|
||||||
HasComp<MobStateComponent>(args.Target))
|
HasComp<MobStateComponent>(args.Target))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,11 +0,0 @@
|
|||||||
using Content.Shared.Atmos.Miasma;
|
|
||||||
using Robust.Shared.GameStates;
|
|
||||||
|
|
||||||
namespace Content.Server.Atmos.Miasma;
|
|
||||||
|
|
||||||
[NetworkedComponent, RegisterComponent]
|
|
||||||
public sealed class FliesComponent : SharedFliesComponent
|
|
||||||
{
|
|
||||||
/// Need something to hold the ambient sound, at least until that system becomes more robust
|
|
||||||
public EntityUid VirtFlies;
|
|
||||||
}
|
|
||||||
@@ -26,42 +26,6 @@ public sealed class RottingSystem : EntitySystem
|
|||||||
[Dependency] private readonly MobStateSystem _mobState = default!;
|
[Dependency] private readonly MobStateSystem _mobState = default!;
|
||||||
[Dependency] private readonly TransformSystem _transform = default!;
|
[Dependency] private readonly TransformSystem _transform = default!;
|
||||||
|
|
||||||
/// Miasma Disease Pool
|
|
||||||
/// Miasma outbreaks are not per-entity,
|
|
||||||
/// so this ensures that each entity in the same incident
|
|
||||||
/// receives the same disease.
|
|
||||||
|
|
||||||
public readonly IReadOnlyList<string> MiasmaDiseasePool = new[]
|
|
||||||
{
|
|
||||||
"VentCough",
|
|
||||||
"AMIV",
|
|
||||||
"SpaceCold",
|
|
||||||
"SpaceFlu",
|
|
||||||
"BirdFlew",
|
|
||||||
"VanAusdallsRobovirus",
|
|
||||||
"BleedersBite",
|
|
||||||
"Plague",
|
|
||||||
"TongueTwister",
|
|
||||||
"MemeticAmirmir"
|
|
||||||
};
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The current pool disease.
|
|
||||||
/// </summary>
|
|
||||||
private string _poolDisease = "";
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The target time it waits until..
|
|
||||||
/// After that, it resets current time + _poolRepickTime.
|
|
||||||
/// Any infection will also reset it to current time + _poolRepickTime.
|
|
||||||
/// </summary>
|
|
||||||
private TimeSpan _diseaseTime = TimeSpan.FromMinutes(5);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// How long without an infection before we pick a new disease.
|
|
||||||
/// </summary>
|
|
||||||
private readonly TimeSpan _poolRepickTime = TimeSpan.FromMinutes(5);
|
|
||||||
|
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
{
|
{
|
||||||
base.Initialize();
|
base.Initialize();
|
||||||
@@ -76,13 +40,7 @@ public sealed class RottingSystem : EntitySystem
|
|||||||
SubscribeLocalEvent<RottingComponent, ExaminedEvent>(OnExamined);
|
SubscribeLocalEvent<RottingComponent, ExaminedEvent>(OnExamined);
|
||||||
SubscribeLocalEvent<RottingComponent, RejuvenateEvent>(OnRejuvenate);
|
SubscribeLocalEvent<RottingComponent, RejuvenateEvent>(OnRejuvenate);
|
||||||
|
|
||||||
SubscribeLocalEvent<FliesComponent, ComponentInit>(OnFliesInit);
|
|
||||||
SubscribeLocalEvent<FliesComponent, ComponentShutdown>(OnFliesShutdown);
|
|
||||||
|
|
||||||
SubscribeLocalEvent<TemperatureComponent, IsRottingEvent>(OnTempIsRotting);
|
SubscribeLocalEvent<TemperatureComponent, IsRottingEvent>(OnTempIsRotting);
|
||||||
|
|
||||||
// Init disease pool
|
|
||||||
_poolDisease = _random.Pick(MiasmaDiseasePool);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnPerishableUnpaused(EntityUid uid, PerishableComponent component, ref EntityUnpausedEvent args)
|
private void OnPerishableUnpaused(EntityUid uid, PerishableComponent component, ref EntityUnpausedEvent args)
|
||||||
@@ -106,7 +64,6 @@ public sealed class RottingSystem : EntitySystem
|
|||||||
|
|
||||||
private void OnShutdown(EntityUid uid, RottingComponent component, ComponentShutdown args)
|
private void OnShutdown(EntityUid uid, RottingComponent component, ComponentShutdown args)
|
||||||
{
|
{
|
||||||
RemComp<FliesComponent>(uid);
|
|
||||||
if (TryComp<PerishableComponent>(uid, out var perishable))
|
if (TryComp<PerishableComponent>(uid, out var perishable))
|
||||||
{
|
{
|
||||||
perishable.NextPerishUpdate = TimeSpan.Zero;
|
perishable.NextPerishUpdate = TimeSpan.Zero;
|
||||||
@@ -182,22 +139,6 @@ public sealed class RottingSystem : EntitySystem
|
|||||||
RemCompDeferred<RottingComponent>(uid);
|
RemCompDeferred<RottingComponent>(uid);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Containers
|
|
||||||
|
|
||||||
|
|
||||||
#region Fly stuff
|
|
||||||
private void OnFliesInit(EntityUid uid, FliesComponent component, ComponentInit args)
|
|
||||||
{
|
|
||||||
component.VirtFlies = Spawn("AmbientSoundSourceFlies", Transform(uid).Coordinates);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnFliesShutdown(EntityUid uid, FliesComponent component, ComponentShutdown args)
|
|
||||||
{
|
|
||||||
if (!Terminating(uid) && !Deleted(uid))
|
|
||||||
Del(component.VirtFlies);
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
private void OnTempIsRotting(EntityUid uid, TemperatureComponent component, ref IsRottingEvent args)
|
private void OnTempIsRotting(EntityUid uid, TemperatureComponent component, ref IsRottingEvent args)
|
||||||
{
|
{
|
||||||
if (args.Handled)
|
if (args.Handled)
|
||||||
@@ -205,23 +146,10 @@ public sealed class RottingSystem : EntitySystem
|
|||||||
args.Handled = component.CurrentTemperature > Atmospherics.T0C + 0.85f;
|
args.Handled = component.CurrentTemperature > Atmospherics.T0C + 0.85f;
|
||||||
}
|
}
|
||||||
|
|
||||||
public string RequestPoolDisease()
|
|
||||||
{
|
|
||||||
// We reset the current time on this outbreak so people don't get unlucky at the transition time
|
|
||||||
_diseaseTime = _timing.CurTime + _poolRepickTime;
|
|
||||||
return _poolDisease;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Update(float frameTime)
|
public override void Update(float frameTime)
|
||||||
{
|
{
|
||||||
base.Update(frameTime);
|
base.Update(frameTime);
|
||||||
|
|
||||||
if (_timing.CurTime >= _diseaseTime)
|
|
||||||
{
|
|
||||||
_diseaseTime = _timing.CurTime + _poolRepickTime;
|
|
||||||
_poolDisease = _random.Pick(MiasmaDiseasePool);
|
|
||||||
}
|
|
||||||
|
|
||||||
var perishQuery = EntityQueryEnumerator<PerishableComponent>();
|
var perishQuery = EntityQueryEnumerator<PerishableComponent>();
|
||||||
while (perishQuery.MoveNext(out var uid, out var perishable))
|
while (perishQuery.MoveNext(out var uid, out var perishable))
|
||||||
{
|
{
|
||||||
@@ -237,9 +165,7 @@ public sealed class RottingSystem : EntitySystem
|
|||||||
{
|
{
|
||||||
var rot = AddComp<RottingComponent>(uid);
|
var rot = AddComp<RottingComponent>(uid);
|
||||||
rot.NextRotUpdate = _timing.CurTime + rot.RotUpdateRate;
|
rot.NextRotUpdate = _timing.CurTime + rot.RotUpdateRate;
|
||||||
EnsureComp<FliesComponent>(uid);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var rotQuery = EntityQueryEnumerator<RottingComponent, PerishableComponent, TransformComponent>();
|
var rotQuery = EntityQueryEnumerator<RottingComponent, PerishableComponent, TransformComponent>();
|
||||||
|
|||||||
@@ -1,36 +0,0 @@
|
|||||||
using Content.Shared.Chemistry.Reagent;
|
|
||||||
using Content.Server.Disease;
|
|
||||||
using Content.Shared.Disease;
|
|
||||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
|
||||||
using JetBrains.Annotations;
|
|
||||||
|
|
||||||
namespace Content.Server.Chemistry.ReagentEffects
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Default metabolism for medicine reagents.
|
|
||||||
/// </summary>
|
|
||||||
[UsedImplicitly]
|
|
||||||
public sealed class ChemCauseDisease : ReagentEffect
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Chance it has each tick to cause disease, between 0 and 1
|
|
||||||
/// </summary>
|
|
||||||
[DataField("causeChance")]
|
|
||||||
public float CauseChance = 0.15f;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The disease to add.
|
|
||||||
/// </summary>
|
|
||||||
[DataField("disease", customTypeSerializer: typeof(PrototypeIdSerializer<DiseasePrototype>), required: true)]
|
|
||||||
[ViewVariables(VVAccess.ReadWrite)]
|
|
||||||
public string Disease = default!;
|
|
||||||
|
|
||||||
public override void Effect(ReagentEffectArgs args)
|
|
||||||
{
|
|
||||||
if (args.Scale != 1f)
|
|
||||||
return;
|
|
||||||
|
|
||||||
EntitySystem.Get<DiseaseSystem>().TryAddDisease(args.SolutionEntity, Disease);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
using Content.Shared.Chemistry.Reagent;
|
|
||||||
using Content.Server.Disease;
|
|
||||||
using Content.Shared.Disease.Components;
|
|
||||||
using Robust.Shared.Random;
|
|
||||||
using JetBrains.Annotations;
|
|
||||||
|
|
||||||
namespace Content.Server.Chemistry.ReagentEffects
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Causes a random disease from a list, if the user is not already diseased.
|
|
||||||
/// </summary>
|
|
||||||
[UsedImplicitly]
|
|
||||||
public sealed class ChemCauseRandomDisease : ReagentEffect
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// A disease to choose from.
|
|
||||||
/// </summary>
|
|
||||||
[DataField("diseases", required: true)]
|
|
||||||
[ViewVariables(VVAccess.ReadWrite)]
|
|
||||||
public List<string> Diseases = default!;
|
|
||||||
|
|
||||||
public override void Effect(ReagentEffectArgs args)
|
|
||||||
{
|
|
||||||
if (args.EntityManager.TryGetComponent<DiseasedComponent>(args.SolutionEntity, out var diseased))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (args.Scale != 1f)
|
|
||||||
return;
|
|
||||||
|
|
||||||
var random = IoCManager.Resolve<IRobustRandom>();
|
|
||||||
|
|
||||||
EntitySystem.Get<DiseaseSystem>().TryAddDisease(args.SolutionEntity, random.Pick(Diseases));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
using Content.Shared.Chemistry.Reagent;
|
|
||||||
using Content.Server.Disease;
|
|
||||||
using JetBrains.Annotations;
|
|
||||||
|
|
||||||
namespace Content.Server.Chemistry.ReagentEffects
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Default metabolism for medicine reagents.
|
|
||||||
/// </summary>
|
|
||||||
[UsedImplicitly]
|
|
||||||
public sealed class ChemCureDisease : ReagentEffect
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Chance it has each tick to cure a disease, between 0 and 1
|
|
||||||
/// </summary>
|
|
||||||
[DataField("cureChance")]
|
|
||||||
public float CureChance = 0.15f;
|
|
||||||
|
|
||||||
public override void Effect(ReagentEffectArgs args)
|
|
||||||
{
|
|
||||||
var cureChance = CureChance;
|
|
||||||
|
|
||||||
cureChance *= args.Scale;
|
|
||||||
|
|
||||||
var ev = new CureDiseaseAttemptEvent(cureChance);
|
|
||||||
args.EntityManager.EventBus.RaiseLocalEvent(args.SolutionEntity, ev, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
using Content.Shared.Chemistry.Reagent;
|
|
||||||
using JetBrains.Annotations;
|
|
||||||
using Content.Server.Atmos.Miasma;
|
|
||||||
using Content.Server.Disease;
|
|
||||||
|
|
||||||
namespace Content.Server.Chemistry.ReagentEffects
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// The miasma system rotates between 1 disease at a time.
|
|
||||||
/// This gives all entities the disease the miasme system is currently on.
|
|
||||||
/// For things ingested by one person, you probably want ChemCauseRandomDisease instead.
|
|
||||||
/// </summary>
|
|
||||||
[UsedImplicitly]
|
|
||||||
public sealed class ChemMiasmaPoolSource : ReagentEffect
|
|
||||||
{
|
|
||||||
public override void Effect(ReagentEffectArgs args)
|
|
||||||
{
|
|
||||||
if (args.Scale != 1f)
|
|
||||||
return;
|
|
||||||
|
|
||||||
string disease = EntitySystem.Get<RottingSystem>().RequestPoolDisease();
|
|
||||||
|
|
||||||
EntitySystem.Get<DiseaseSystem>().TryAddDisease(args.SolutionEntity, disease);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -4,7 +4,6 @@ using Content.Server.Atmos.EntitySystems;
|
|||||||
using Content.Server.Body.Components;
|
using Content.Server.Body.Components;
|
||||||
using Content.Server.Body.Systems;
|
using Content.Server.Body.Systems;
|
||||||
using Content.Server.Clothing.Components;
|
using Content.Server.Clothing.Components;
|
||||||
using Content.Server.Disease.Components;
|
|
||||||
using Content.Server.IdentityManagement;
|
using Content.Server.IdentityManagement;
|
||||||
using Content.Server.Nutrition.EntitySystems;
|
using Content.Server.Nutrition.EntitySystems;
|
||||||
using Content.Server.Popups;
|
using Content.Server.Popups;
|
||||||
@@ -15,7 +14,6 @@ using Content.Shared.Clothing.EntitySystems;
|
|||||||
using Content.Shared.IdentityManagement.Components;
|
using Content.Shared.IdentityManagement.Components;
|
||||||
using Content.Shared.Inventory;
|
using Content.Shared.Inventory;
|
||||||
using Content.Shared.Inventory.Events;
|
using Content.Shared.Inventory.Events;
|
||||||
using Robust.Shared.Player;
|
|
||||||
|
|
||||||
namespace Content.Server.Clothing
|
namespace Content.Server.Clothing
|
||||||
{
|
{
|
||||||
@@ -80,8 +78,8 @@ namespace Content.Server.Clothing
|
|||||||
|
|
||||||
private void ToggleMaskComponents(EntityUid uid, MaskComponent mask, EntityUid wearer, bool isEquip = false)
|
private void ToggleMaskComponents(EntityUid uid, MaskComponent mask, EntityUid wearer, bool isEquip = false)
|
||||||
{
|
{
|
||||||
//toggle visuals
|
// toggle visuals
|
||||||
if (TryComp<ClothingComponent>(mask.Owner, out var clothing))
|
if (TryComp<ClothingComponent>(uid, out var clothing))
|
||||||
{
|
{
|
||||||
//TODO: sprites for 'pulled down' state. defaults to invisible due to no sprite with this prefix
|
//TODO: sprites for 'pulled down' state. defaults to invisible due to no sprite with this prefix
|
||||||
_clothing.SetEquippedPrefix(uid, mask.IsToggled ? "toggled" : null, clothing);
|
_clothing.SetEquippedPrefix(uid, mask.IsToggled ? "toggled" : null, clothing);
|
||||||
@@ -93,10 +91,6 @@ namespace Content.Server.Clothing
|
|||||||
if (TryComp<IngestionBlockerComponent>(uid, out var blocker))
|
if (TryComp<IngestionBlockerComponent>(uid, out var blocker))
|
||||||
blocker.Enabled = !mask.IsToggled;
|
blocker.Enabled = !mask.IsToggled;
|
||||||
|
|
||||||
// toggle disease protection
|
|
||||||
if (TryComp<DiseaseProtectionComponent>(uid, out var diseaseProtection))
|
|
||||||
diseaseProtection.IsActive = !mask.IsToggled;
|
|
||||||
|
|
||||||
// toggle identity
|
// toggle identity
|
||||||
if (TryComp<IdentityBlockerComponent>(uid, out var identity))
|
if (TryComp<IdentityBlockerComponent>(uid, out var identity))
|
||||||
identity.Enabled = !mask.IsToggled;
|
identity.Enabled = !mask.IsToggled;
|
||||||
|
|||||||
@@ -1,56 +0,0 @@
|
|||||||
using System.Linq;
|
|
||||||
using Content.Shared.Disease;
|
|
||||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.Set;
|
|
||||||
|
|
||||||
namespace Content.Server.Disease.Components
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Allows the entity to be infected with diseases.
|
|
||||||
/// Please use only on mobs.
|
|
||||||
/// </summary>
|
|
||||||
[RegisterComponent]
|
|
||||||
public sealed class DiseaseCarrierComponent : Component
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Shows the CURRENT diseases on the carrier
|
|
||||||
/// </summary>
|
|
||||||
[ViewVariables(VVAccess.ReadWrite)]
|
|
||||||
public List<DiseasePrototype> Diseases = new();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The carrier's resistance to disease
|
|
||||||
/// </summary>
|
|
||||||
[DataField("diseaseResist")]
|
|
||||||
[ViewVariables(VVAccess.ReadWrite)]
|
|
||||||
public float DiseaseResist = 0f;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Diseases the carrier has had, used for immunity.
|
|
||||||
/// </summary>
|
|
||||||
[ViewVariables(VVAccess.ReadWrite)]
|
|
||||||
public List<DiseasePrototype> PastDiseases = new();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// All the diseases the carrier has or has had.
|
|
||||||
/// Checked against when trying to add a disease
|
|
||||||
/// </summary>
|
|
||||||
[ViewVariables(VVAccess.ReadWrite)]
|
|
||||||
public List<DiseasePrototype> AllDiseases => PastDiseases.Concat(Diseases).ToList();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// A list of diseases which the entity does not
|
|
||||||
/// exhibit direct symptoms from. They still transmit
|
|
||||||
/// these diseases, just without symptoms.
|
|
||||||
/// </summary>
|
|
||||||
[DataField("carrierDiseases", customTypeSerializer: typeof(PrototypeIdHashSetSerializer<DiseasePrototype>))]
|
|
||||||
public HashSet<string>? CarrierDiseases;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// When this component is initialized,
|
|
||||||
/// these diseases will be added to past diseases,
|
|
||||||
/// rendering them immune.
|
|
||||||
/// </summary>
|
|
||||||
[DataField("naturalImmunities")]
|
|
||||||
public List<string>? NaturalImmunities;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
namespace Content.Server.Disease.Components
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// To give the disease diagnosing machine specific behavior
|
|
||||||
/// </summary>
|
|
||||||
[RegisterComponent]
|
|
||||||
public sealed class DiseaseDiagnoserComponent : Component
|
|
||||||
{}
|
|
||||||
}
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
using Content.Shared.Disease;
|
|
||||||
using Robust.Shared.Prototypes;
|
|
||||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
|
||||||
|
|
||||||
namespace Content.Server.Disease.Components
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// For shared behavior between both disease machines
|
|
||||||
/// </summary>
|
|
||||||
[RegisterComponent]
|
|
||||||
public sealed class DiseaseMachineComponent : Component
|
|
||||||
{
|
|
||||||
[DataField("delay")]
|
|
||||||
public float Delay = 5f;
|
|
||||||
/// <summary>
|
|
||||||
/// How much time we've accumulated processing
|
|
||||||
/// </summary>
|
|
||||||
[DataField("accumulator")]
|
|
||||||
public float Accumulator = 0f;
|
|
||||||
/// <summary>
|
|
||||||
/// The disease prototype currently being diagnosed
|
|
||||||
/// </summary>
|
|
||||||
[ViewVariables]
|
|
||||||
public DiseasePrototype? Disease;
|
|
||||||
/// <summary>
|
|
||||||
/// What the machine will spawn
|
|
||||||
/// </summary>
|
|
||||||
[DataField("machineOutput", customTypeSerializer: typeof(PrototypeIdSerializer<EntityPrototype>), required: true)]
|
|
||||||
public string MachineOutput = string.Empty;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
namespace Content.Server.Disease.Components
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// For EntityQuery to keep track of which machines are running
|
|
||||||
/// </summary>
|
|
||||||
[RegisterComponent]
|
|
||||||
public sealed class DiseaseMachineRunningComponent : Component
|
|
||||||
{}
|
|
||||||
}
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
namespace Content.Server.Disease.Components
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Value added to clothing to give its wearer
|
|
||||||
/// protection against infection from diseases
|
|
||||||
/// </summary>
|
|
||||||
[RegisterComponent]
|
|
||||||
public sealed class DiseaseProtectionComponent : Component
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Float value between 0 and 1, will be subtracted
|
|
||||||
/// from the infection chance (which is base 0.7)
|
|
||||||
/// Reference guide is a full biosuit w/gloves & mask
|
|
||||||
/// should add up to exactly 0.7
|
|
||||||
/// </summary>
|
|
||||||
[DataField("protection")]
|
|
||||||
public float Protection = 0.1f;
|
|
||||||
/// <summary>
|
|
||||||
/// Is the component currently being worn and affecting someone's disease
|
|
||||||
/// resistance? Making the unequip check not totally CBT
|
|
||||||
/// </summary>
|
|
||||||
public bool IsActive = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
using Content.Shared.Disease;
|
|
||||||
|
|
||||||
namespace Content.Server.Disease.Components
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// For mouth swabs used to collect and process
|
|
||||||
/// disease samples.
|
|
||||||
/// </summary>
|
|
||||||
[RegisterComponent]
|
|
||||||
public sealed class DiseaseSwabComponent : Component
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// How long it takes to swab someone.
|
|
||||||
/// </summary>
|
|
||||||
[DataField("swabDelay")]
|
|
||||||
public float SwabDelay = 2f;
|
|
||||||
/// <summary>
|
|
||||||
/// If this swab has been used
|
|
||||||
/// </summary>
|
|
||||||
public bool Used = false;
|
|
||||||
/// <summary>
|
|
||||||
/// The disease prototype currently on the swab
|
|
||||||
/// </summary>
|
|
||||||
[ViewVariables]
|
|
||||||
public DiseasePrototype? Disease;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
using System.Threading;
|
|
||||||
using Content.Shared.Disease;
|
|
||||||
|
|
||||||
namespace Content.Server.Disease.Components
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// For disease vaccines
|
|
||||||
/// </summary>
|
|
||||||
[RegisterComponent]
|
|
||||||
public sealed class DiseaseVaccineComponent : Component
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// How long it takes to inject someone
|
|
||||||
/// </summary>
|
|
||||||
[DataField("injectDelay")]
|
|
||||||
public float InjectDelay = 2f;
|
|
||||||
/// <summary>
|
|
||||||
/// If this vaccine has been used
|
|
||||||
/// </summary>
|
|
||||||
public bool Used = false;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The disease prototype currently on the vaccine
|
|
||||||
/// </summary>
|
|
||||||
[ViewVariables(VVAccess.ReadWrite)]
|
|
||||||
public DiseasePrototype? Disease;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
namespace Content.Server.Disease.Components
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Controls disease machine behavior specific to the
|
|
||||||
/// vaccine creating machine
|
|
||||||
/// </summary>
|
|
||||||
[RegisterComponent]
|
|
||||||
public sealed class DiseaseVaccineCreatorComponent : Component
|
|
||||||
{}
|
|
||||||
}
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
using Content.Server.Bed.Components;
|
|
||||||
using Content.Shared.Bed.Sleep;
|
|
||||||
using Content.Shared.Buckle.Components;
|
|
||||||
using Content.Shared.Disease;
|
|
||||||
|
|
||||||
namespace Content.Server.Disease.Cures
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Cures the disease after a certain amount of time
|
|
||||||
/// strapped.
|
|
||||||
/// </summary>
|
|
||||||
public sealed class DiseaseBedrestCure : DiseaseCure
|
|
||||||
{
|
|
||||||
[ViewVariables(VVAccess.ReadWrite)]
|
|
||||||
public int Ticker = 0;
|
|
||||||
|
|
||||||
/// How many extra ticks you get for sleeping.
|
|
||||||
[DataField("sleepMultiplier")]
|
|
||||||
public int SleepMultiplier = 3;
|
|
||||||
|
|
||||||
[DataField("maxLength", required: true)]
|
|
||||||
[ViewVariables(VVAccess.ReadWrite)]
|
|
||||||
public int MaxLength = 60;
|
|
||||||
|
|
||||||
public override bool Cure(DiseaseEffectArgs args)
|
|
||||||
{
|
|
||||||
if (!args.EntityManager.TryGetComponent<BuckleComponent>(args.DiseasedEntity, out var buckle) ||
|
|
||||||
!args.EntityManager.HasComponent<HealOnBuckleComponent>(buckle.BuckledTo))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
var ticks = 1;
|
|
||||||
if (args.EntityManager.HasComponent<SleepingComponent>(args.DiseasedEntity))
|
|
||||||
ticks *= SleepMultiplier;
|
|
||||||
|
|
||||||
if (buckle.Buckled)
|
|
||||||
Ticker += ticks;
|
|
||||||
return Ticker >= MaxLength;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string CureText()
|
|
||||||
{
|
|
||||||
return (Loc.GetString("diagnoser-cure-bedrest", ("time", MaxLength), ("sleep", (MaxLength / SleepMultiplier))));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
using Content.Server.Temperature.Components;
|
|
||||||
using Content.Shared.Disease;
|
|
||||||
|
|
||||||
namespace Content.Server.Disease.Cures
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Cures the disease if temperature is within certain bounds.
|
|
||||||
/// </summary>
|
|
||||||
public sealed class DiseaseBodyTemperatureCure : DiseaseCure
|
|
||||||
{
|
|
||||||
[DataField("min")]
|
|
||||||
public float Min = 0;
|
|
||||||
|
|
||||||
[DataField("max")]
|
|
||||||
public float Max = float.MaxValue;
|
|
||||||
public override bool Cure(DiseaseEffectArgs args)
|
|
||||||
{
|
|
||||||
if (!args.EntityManager.TryGetComponent(args.DiseasedEntity, out TemperatureComponent? temp))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return temp.CurrentTemperature > Min && temp.CurrentTemperature < float.MaxValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string CureText()
|
|
||||||
{
|
|
||||||
if (Min == 0)
|
|
||||||
return Loc.GetString("diagnoser-cure-temp-max", ("max", Math.Round(Max)));
|
|
||||||
if (Max == float.MaxValue)
|
|
||||||
return Loc.GetString("diagnoser-cure-temp-min", ("min", Math.Round(Min)));
|
|
||||||
|
|
||||||
return Loc.GetString("diagnoser-cure-temp-both", ("max", Math.Round(Max)), ("min", Math.Round(Min)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
using Content.Shared.Disease;
|
|
||||||
|
|
||||||
namespace Content.Server.Disease.Cures
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Automatically removes the disease after a
|
|
||||||
/// certain amount of time.
|
|
||||||
/// </summary>
|
|
||||||
public sealed class DiseaseJustWaitCure : DiseaseCure
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// All of these are in seconds
|
|
||||||
/// </summary>
|
|
||||||
[ViewVariables(VVAccess.ReadWrite)]
|
|
||||||
public int Ticker = 0;
|
|
||||||
[DataField("maxLength", required: true)]
|
|
||||||
[ViewVariables(VVAccess.ReadWrite)]
|
|
||||||
public int MaxLength = 150;
|
|
||||||
|
|
||||||
public override bool Cure(DiseaseEffectArgs args)
|
|
||||||
{
|
|
||||||
Ticker++;
|
|
||||||
return Ticker >= MaxLength;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string CureText()
|
|
||||||
{
|
|
||||||
return Loc.GetString("diagnoser-cure-wait", ("time", MaxLength));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,41 +0,0 @@
|
|||||||
using Content.Shared.Disease;
|
|
||||||
using Content.Shared.FixedPoint;
|
|
||||||
using Content.Shared.Chemistry.Reagent;
|
|
||||||
using Content.Server.Body.Components;
|
|
||||||
using Robust.Shared.Prototypes;
|
|
||||||
|
|
||||||
namespace Content.Server.Disease.Cures
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Cures the disease if a certain amount of reagent
|
|
||||||
/// is in the host's chemstream.
|
|
||||||
/// </summary>
|
|
||||||
public sealed class DiseaseReagentCure : DiseaseCure
|
|
||||||
{
|
|
||||||
[DataField("min")]
|
|
||||||
public FixedPoint2 Min = 5;
|
|
||||||
[DataField("reagent")]
|
|
||||||
public string? Reagent;
|
|
||||||
|
|
||||||
public override bool Cure(DiseaseEffectArgs args)
|
|
||||||
{
|
|
||||||
if (!args.EntityManager.TryGetComponent<BloodstreamComponent>(args.DiseasedEntity, out var bloodstream))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
var quant = FixedPoint2.Zero;
|
|
||||||
if (Reagent != null && bloodstream.ChemicalSolution.ContainsReagent(Reagent))
|
|
||||||
{
|
|
||||||
quant = bloodstream.ChemicalSolution.GetReagentQuantity(Reagent);
|
|
||||||
}
|
|
||||||
return quant >= Min;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string CureText()
|
|
||||||
{
|
|
||||||
var prototypeMan = IoCManager.Resolve<IPrototypeManager>();
|
|
||||||
if (Reagent == null || !prototypeMan.TryIndex<ReagentPrototype>(Reagent, out var reagentProt))
|
|
||||||
return string.Empty;
|
|
||||||
return (Loc.GetString("diagnoser-cure-reagent", ("units", Min), ("reagent", reagentProt.LocalizedName)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,403 +0,0 @@
|
|||||||
using Content.Server.Disease.Components;
|
|
||||||
using Content.Server.Nutrition.EntitySystems;
|
|
||||||
using Content.Server.Paper;
|
|
||||||
using Content.Server.Popups;
|
|
||||||
using Content.Server.Power.Components;
|
|
||||||
using Content.Server.Power.EntitySystems;
|
|
||||||
using Content.Server.Station.Systems;
|
|
||||||
using Content.Shared.Disease;
|
|
||||||
using Content.Shared.DoAfter;
|
|
||||||
using Content.Shared.Examine;
|
|
||||||
using Content.Shared.Hands.Components;
|
|
||||||
using Content.Shared.IdentityManagement;
|
|
||||||
using Content.Shared.Interaction;
|
|
||||||
using Content.Shared.Inventory;
|
|
||||||
using Content.Shared.Swab;
|
|
||||||
using Content.Shared.Tools.Components;
|
|
||||||
using Robust.Shared.Audio;
|
|
||||||
using Robust.Shared.Player;
|
|
||||||
using Robust.Shared.Random;
|
|
||||||
using Robust.Shared.Utility;
|
|
||||||
|
|
||||||
namespace Content.Server.Disease
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Everything that's about disease diangosis and machines is in here
|
|
||||||
/// </summary>
|
|
||||||
public sealed class DiseaseDiagnosisSystem : EntitySystem
|
|
||||||
{
|
|
||||||
[Dependency] private readonly SharedDoAfterSystem _doAfterSystem = default!;
|
|
||||||
[Dependency] private readonly PopupSystem _popupSystem = default!;
|
|
||||||
[Dependency] private readonly IRobustRandom _random = default!;
|
|
||||||
[Dependency] private readonly InventorySystem _inventorySystem = default!;
|
|
||||||
[Dependency] private readonly PaperSystem _paperSystem = default!;
|
|
||||||
[Dependency] private readonly StationSystem _stationSystem = default!;
|
|
||||||
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
|
|
||||||
|
|
||||||
public override void Initialize()
|
|
||||||
{
|
|
||||||
base.Initialize();
|
|
||||||
SubscribeLocalEvent<DiseaseSwabComponent, AfterInteractEvent>(OnAfterInteract);
|
|
||||||
SubscribeLocalEvent<DiseaseSwabComponent, ExaminedEvent>(OnExamined);
|
|
||||||
SubscribeLocalEvent<DiseaseDiagnoserComponent, AfterInteractUsingEvent>(OnAfterInteractUsing);
|
|
||||||
SubscribeLocalEvent<DiseaseVaccineCreatorComponent, AfterInteractUsingEvent>(OnAfterInteractUsingVaccine);
|
|
||||||
// Visuals
|
|
||||||
SubscribeLocalEvent<DiseaseMachineComponent, PowerChangedEvent>(OnPowerChanged);
|
|
||||||
// Private Events
|
|
||||||
SubscribeLocalEvent<DiseaseDiagnoserComponent, DiseaseMachineFinishedEvent>(OnDiagnoserFinished);
|
|
||||||
SubscribeLocalEvent<DiseaseVaccineCreatorComponent, DiseaseMachineFinishedEvent>(OnVaccinatorFinished);
|
|
||||||
SubscribeLocalEvent<DiseaseSwabComponent, DiseaseSwabDoAfterEvent>(OnSwabDoAfter);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Queue<EntityUid> AddQueue = new();
|
|
||||||
private Queue<EntityUid> RemoveQueue = new();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This handles running disease machines
|
|
||||||
/// to handle their delay and visuals.
|
|
||||||
/// </summary>
|
|
||||||
public override void Update(float frameTime)
|
|
||||||
{
|
|
||||||
foreach (var uid in AddQueue)
|
|
||||||
{
|
|
||||||
EnsureComp<DiseaseMachineRunningComponent>(uid);
|
|
||||||
}
|
|
||||||
|
|
||||||
AddQueue.Clear();
|
|
||||||
foreach (var uid in RemoveQueue)
|
|
||||||
{
|
|
||||||
RemComp<DiseaseMachineRunningComponent>(uid);
|
|
||||||
}
|
|
||||||
|
|
||||||
RemoveQueue.Clear();
|
|
||||||
|
|
||||||
foreach (var (_, diseaseMachine) in EntityQuery<DiseaseMachineRunningComponent, DiseaseMachineComponent>())
|
|
||||||
{
|
|
||||||
diseaseMachine.Accumulator += frameTime;
|
|
||||||
|
|
||||||
while (diseaseMachine.Accumulator >= diseaseMachine.Delay)
|
|
||||||
{
|
|
||||||
diseaseMachine.Accumulator -= diseaseMachine.Delay;
|
|
||||||
var ev = new DiseaseMachineFinishedEvent(diseaseMachine);
|
|
||||||
RaiseLocalEvent(diseaseMachine.Owner, ev);
|
|
||||||
RemoveQueue.Enqueue(diseaseMachine.Owner);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
///
|
|
||||||
/// Event Handlers
|
|
||||||
///
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This handles using swabs on other people
|
|
||||||
/// and checks that the swab isn't already used
|
|
||||||
/// and the other person's mouth is accessible
|
|
||||||
/// and then adds a random disease from that person
|
|
||||||
/// to the swab if they have any
|
|
||||||
/// </summary>
|
|
||||||
private void OnAfterInteract(EntityUid uid, DiseaseSwabComponent swab, AfterInteractEvent args)
|
|
||||||
{
|
|
||||||
if (args.Target == null || !args.CanReach || !HasComp<DiseaseCarrierComponent>(args.Target))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (swab.Used)
|
|
||||||
{
|
|
||||||
_popupSystem.PopupEntity(Loc.GetString("swab-already-used"), args.User, args.User);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_inventorySystem.TryGetSlotEntity(args.Target.Value, "mask", out var maskUid) &&
|
|
||||||
EntityManager.TryGetComponent<IngestionBlockerComponent>(maskUid, out var blocker) &&
|
|
||||||
blocker.Enabled)
|
|
||||||
{
|
|
||||||
_popupSystem.PopupEntity(Loc.GetString("swab-mask-blocked", ("target", Identity.Entity(args.Target.Value, EntityManager)), ("mask", maskUid)), args.User, args.User);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_doAfterSystem.TryStartDoAfter(new DoAfterArgs(args.User, swab.SwabDelay, new DiseaseSwabDoAfterEvent(), uid, target: args.Target, used: uid)
|
|
||||||
{
|
|
||||||
BreakOnTargetMove = true,
|
|
||||||
BreakOnUserMove = true,
|
|
||||||
NeedHand = true
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This handles the disease diagnoser machine up
|
|
||||||
/// until it's turned on. It has some slight
|
|
||||||
/// differences in checks from the vaccinator.
|
|
||||||
/// </summary>
|
|
||||||
private void OnAfterInteractUsing(EntityUid uid, DiseaseDiagnoserComponent component, AfterInteractUsingEvent args)
|
|
||||||
{
|
|
||||||
var machine = Comp<DiseaseMachineComponent>(uid);
|
|
||||||
if (args.Handled || !args.CanReach)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (HasComp<DiseaseMachineRunningComponent>(uid) || !this.IsPowered(uid, EntityManager))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (!HasComp<HandsComponent>(args.User) || HasComp<ToolComponent>(args.Used)) // Don't want to accidentally breach wrenching or whatever
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (!TryComp<DiseaseSwabComponent>(args.Used, out var swab))
|
|
||||||
{
|
|
||||||
_popupSystem.PopupEntity(Loc.GetString("diagnoser-cant-use-swab", ("machine", uid), ("swab", args.Used)), uid, args.User);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
_popupSystem.PopupEntity(Loc.GetString("machine-insert-item", ("machine", uid), ("item", args.Used), ("user", args.User)), uid, args.User);
|
|
||||||
|
|
||||||
|
|
||||||
machine.Disease = swab.Disease;
|
|
||||||
EntityManager.DeleteEntity(args.Used);
|
|
||||||
|
|
||||||
AddQueue.Enqueue(uid);
|
|
||||||
UpdateAppearance(uid, true, true);
|
|
||||||
SoundSystem.Play("/Audio/Machines/diagnoser_printing.ogg", Filter.Pvs(uid), uid);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This handles the vaccinator machine up
|
|
||||||
/// until it's turned on. It has some slight
|
|
||||||
/// differences in checks from the diagnoser.
|
|
||||||
/// </summary>
|
|
||||||
private void OnAfterInteractUsingVaccine(EntityUid uid, DiseaseVaccineCreatorComponent component, AfterInteractUsingEvent args)
|
|
||||||
{
|
|
||||||
if (args.Handled || !args.CanReach)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (HasComp<DiseaseMachineRunningComponent>(uid) || !this.IsPowered(uid, EntityManager))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (!HasComp<HandsComponent>(args.User) || HasComp<ToolComponent>(args.Used)) //This check ensures tools don't break without yaml ordering jank
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (!TryComp<DiseaseSwabComponent>(args.Used, out var swab) || swab.Disease == null || !swab.Disease.Infectious)
|
|
||||||
{
|
|
||||||
_popupSystem.PopupEntity(Loc.GetString("diagnoser-cant-use-swab", ("machine", uid), ("swab", args.Used)), uid, args.User);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
_popupSystem.PopupEntity(Loc.GetString("machine-insert-item", ("machine", uid), ("item", args.Used), ("user", args.User)), uid, args.User);
|
|
||||||
var machine = Comp<DiseaseMachineComponent>(uid);
|
|
||||||
machine.Disease = swab.Disease;
|
|
||||||
EntityManager.DeleteEntity(args.Used);
|
|
||||||
|
|
||||||
AddQueue.Enqueue(uid);
|
|
||||||
UpdateAppearance(uid, true, true);
|
|
||||||
SoundSystem.Play("/Audio/Machines/vaccinator_running.ogg", Filter.Pvs(uid), uid);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This handles swab examination text
|
|
||||||
/// so you can tell if they are used or not.
|
|
||||||
/// </summary>
|
|
||||||
private void OnExamined(EntityUid uid, DiseaseSwabComponent swab, ExaminedEvent args)
|
|
||||||
{
|
|
||||||
if (args.IsInDetailsRange)
|
|
||||||
{
|
|
||||||
if (swab.Used)
|
|
||||||
args.PushMarkup(Loc.GetString("swab-used"));
|
|
||||||
else
|
|
||||||
args.PushMarkup(Loc.GetString("swab-unused"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
///
|
|
||||||
/// Helper functions
|
|
||||||
///
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This assembles a disease report
|
|
||||||
/// With its basic details and
|
|
||||||
/// specific cures (i.e. not spaceacillin).
|
|
||||||
/// The cure resist field tells you how
|
|
||||||
/// effective spaceacillin etc will be.
|
|
||||||
/// </summary>
|
|
||||||
private FormattedMessage AssembleDiseaseReport(DiseasePrototype disease)
|
|
||||||
{
|
|
||||||
FormattedMessage report = new();
|
|
||||||
var diseaseName = Loc.GetString(disease.Name);
|
|
||||||
report.AddMarkup(Loc.GetString("diagnoser-disease-report-name", ("disease", diseaseName)));
|
|
||||||
report.PushNewline();
|
|
||||||
|
|
||||||
if (disease.Infectious)
|
|
||||||
{
|
|
||||||
report.AddMarkup(Loc.GetString("diagnoser-disease-report-infectious"));
|
|
||||||
report.PushNewline();
|
|
||||||
} else
|
|
||||||
{
|
|
||||||
report.AddMarkup(Loc.GetString("diagnoser-disease-report-not-infectious"));
|
|
||||||
report.PushNewline();
|
|
||||||
}
|
|
||||||
string cureResistLine = string.Empty;
|
|
||||||
cureResistLine += disease.CureResist switch
|
|
||||||
{
|
|
||||||
< 0f => Loc.GetString("diagnoser-disease-report-cureresist-none"),
|
|
||||||
<= 0.05f => Loc.GetString("diagnoser-disease-report-cureresist-low"),
|
|
||||||
<= 0.14f => Loc.GetString("diagnoser-disease-report-cureresist-medium"),
|
|
||||||
_ => Loc.GetString("diagnoser-disease-report-cureresist-high")
|
|
||||||
};
|
|
||||||
report.AddMarkup(cureResistLine);
|
|
||||||
report.PushNewline();
|
|
||||||
|
|
||||||
// Add Cures
|
|
||||||
if (disease.Cures.Count == 0)
|
|
||||||
{
|
|
||||||
report.AddMarkup(Loc.GetString("diagnoser-no-cures"));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
report.PushNewline();
|
|
||||||
report.AddMarkup(Loc.GetString("diagnoser-cure-has"));
|
|
||||||
report.PushNewline();
|
|
||||||
|
|
||||||
foreach (var cure in disease.Cures)
|
|
||||||
{
|
|
||||||
report.AddMarkup(cure.CureText());
|
|
||||||
report.PushNewline();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return report;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool ServerHasDisease(DiseaseServerComponent server, DiseasePrototype disease)
|
|
||||||
{
|
|
||||||
bool has = false;
|
|
||||||
foreach (var serverDisease in server.Diseases)
|
|
||||||
{
|
|
||||||
if (serverDisease.ID == disease.ID)
|
|
||||||
has = true;
|
|
||||||
}
|
|
||||||
return has;
|
|
||||||
}
|
|
||||||
///
|
|
||||||
/// Appearance stuff
|
|
||||||
///
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Appearance helper function to
|
|
||||||
/// set the component's power and running states.
|
|
||||||
/// </summary>
|
|
||||||
private void UpdateAppearance(EntityUid uid, bool isOn, bool isRunning)
|
|
||||||
{
|
|
||||||
if (!TryComp<AppearanceComponent>(uid, out var appearance))
|
|
||||||
return;
|
|
||||||
|
|
||||||
_appearance.SetData(uid, DiseaseMachineVisuals.IsOn, isOn, appearance);
|
|
||||||
_appearance.SetData(uid, DiseaseMachineVisuals.IsRunning, isRunning, appearance);
|
|
||||||
}
|
|
||||||
/// <summary>
|
|
||||||
/// Makes sure the machine is visually off/on.
|
|
||||||
/// </summary>
|
|
||||||
private void OnPowerChanged(EntityUid uid, DiseaseMachineComponent component, ref PowerChangedEvent args)
|
|
||||||
{
|
|
||||||
UpdateAppearance(uid, args.Powered, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Copies a disease prototype to the swab
|
|
||||||
/// after the doafter completes.
|
|
||||||
/// </summary>
|
|
||||||
private void OnSwabDoAfter(EntityUid uid, DiseaseSwabComponent component, DoAfterEvent args)
|
|
||||||
{
|
|
||||||
if (args.Handled || args.Cancelled || !TryComp<DiseaseCarrierComponent>(args.Args.Target, out var carrier) || !TryComp<DiseaseSwabComponent>(args.Args.Used, out var swab))
|
|
||||||
return;
|
|
||||||
|
|
||||||
swab.Used = true;
|
|
||||||
_popupSystem.PopupEntity(Loc.GetString("swab-swabbed", ("target", Identity.Entity(args.Args.Target.Value, EntityManager))), args.Args.Target.Value, args.Args.User);
|
|
||||||
|
|
||||||
if (swab.Disease != null || carrier.Diseases.Count == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
swab.Disease = _random.Pick(carrier.Diseases);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Prints a diagnostic report with its findings.
|
|
||||||
/// Also cancels the animation.
|
|
||||||
/// </summary>
|
|
||||||
private void OnDiagnoserFinished(EntityUid uid, DiseaseDiagnoserComponent component, DiseaseMachineFinishedEvent args)
|
|
||||||
{
|
|
||||||
var isPowered = this.IsPowered(uid, EntityManager);
|
|
||||||
UpdateAppearance(uid, isPowered, false);
|
|
||||||
// spawn a piece of paper.
|
|
||||||
var printed = Spawn(args.Machine.MachineOutput, Transform(uid).Coordinates);
|
|
||||||
|
|
||||||
if (!TryComp<PaperComponent>(printed, out var paper))
|
|
||||||
return;
|
|
||||||
|
|
||||||
string reportTitle;
|
|
||||||
FormattedMessage contents = new();
|
|
||||||
if (args.Machine.Disease != null)
|
|
||||||
{
|
|
||||||
var diseaseName = Loc.GetString(args.Machine.Disease.Name);
|
|
||||||
reportTitle = Loc.GetString("diagnoser-disease-report", ("disease", diseaseName));
|
|
||||||
contents = AssembleDiseaseReport(args.Machine.Disease);
|
|
||||||
|
|
||||||
var known = false;
|
|
||||||
|
|
||||||
foreach (var server in EntityQuery<DiseaseServerComponent>(true))
|
|
||||||
{
|
|
||||||
if (_stationSystem.GetOwningStation(server.Owner) != _stationSystem.GetOwningStation(uid))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (ServerHasDisease(server, args.Machine.Disease))
|
|
||||||
{
|
|
||||||
known = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
server.Diseases.Add(args.Machine.Disease);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!known)
|
|
||||||
{
|
|
||||||
Spawn("ResearchDisk5000", Transform(uid).Coordinates);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
reportTitle = Loc.GetString("diagnoser-disease-report-none");
|
|
||||||
contents.AddMarkup(Loc.GetString("diagnoser-disease-report-none-contents"));
|
|
||||||
}
|
|
||||||
MetaData(printed).EntityName = reportTitle;
|
|
||||||
|
|
||||||
_paperSystem.SetContent(printed, contents.ToMarkup(), paper);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Prints a vaccine that will vaccinate
|
|
||||||
/// against the disease on the inserted swab.
|
|
||||||
/// </summary>
|
|
||||||
private void OnVaccinatorFinished(EntityUid uid, DiseaseVaccineCreatorComponent component, DiseaseMachineFinishedEvent args)
|
|
||||||
{
|
|
||||||
UpdateAppearance(uid, this.IsPowered(uid, EntityManager), false);
|
|
||||||
|
|
||||||
// spawn a vaccine
|
|
||||||
var vaxx = Spawn(args.Machine.MachineOutput, Transform(uid).Coordinates);
|
|
||||||
|
|
||||||
if (!TryComp<DiseaseVaccineComponent>(vaxx, out var vaxxComp))
|
|
||||||
return;
|
|
||||||
|
|
||||||
vaxxComp.Disease = args.Machine.Disease;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Fires when a disease machine is done
|
|
||||||
/// with its production delay and ready to
|
|
||||||
/// create a report or vaccine
|
|
||||||
/// </summary>
|
|
||||||
private sealed class DiseaseMachineFinishedEvent : EntityEventArgs
|
|
||||||
{
|
|
||||||
public DiseaseMachineComponent Machine {get;}
|
|
||||||
public DiseaseMachineFinishedEvent(DiseaseMachineComponent machine)
|
|
||||||
{
|
|
||||||
Machine = machine;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,505 +0,0 @@
|
|||||||
using Content.Server.Body.Systems;
|
|
||||||
using Content.Server.Chat.Systems;
|
|
||||||
using Content.Server.Disease.Components;
|
|
||||||
using Content.Server.Nutrition.EntitySystems;
|
|
||||||
using Content.Server.Popups;
|
|
||||||
using Content.Shared.Clothing.Components;
|
|
||||||
using Content.Shared.Disease;
|
|
||||||
using Content.Shared.Disease.Components;
|
|
||||||
using Content.Shared.Disease.Events;
|
|
||||||
using Content.Shared.DoAfter;
|
|
||||||
using Content.Shared.Examine;
|
|
||||||
using Content.Shared.IdentityManagement;
|
|
||||||
using Content.Shared.Interaction;
|
|
||||||
using Content.Shared.Interaction.Events;
|
|
||||||
using Content.Shared.Inventory;
|
|
||||||
using Content.Shared.Inventory.Events;
|
|
||||||
using Content.Shared.Mobs.Components;
|
|
||||||
using Content.Shared.Mobs.Systems;
|
|
||||||
using Content.Shared.Rejuvenate;
|
|
||||||
using Robust.Shared.Audio;
|
|
||||||
using Robust.Server.GameObjects;
|
|
||||||
using Robust.Shared.Prototypes;
|
|
||||||
using Robust.Shared.Random;
|
|
||||||
using Robust.Shared.Serialization.Manager;
|
|
||||||
using Robust.Shared.Utility;
|
|
||||||
|
|
||||||
namespace Content.Server.Disease
|
|
||||||
{
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Handles disease propagation & curing
|
|
||||||
/// </summary>
|
|
||||||
public sealed class DiseaseSystem : EntitySystem
|
|
||||||
{
|
|
||||||
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
|
||||||
[Dependency] private readonly ISerializationManager _serializationManager = default!;
|
|
||||||
[Dependency] private readonly IRobustRandom _random = default!;
|
|
||||||
[Dependency] private readonly SharedDoAfterSystem _doAfterSystem = default!;
|
|
||||||
[Dependency] private readonly PopupSystem _popupSystem = default!;
|
|
||||||
[Dependency] private readonly EntityLookupSystem _lookup = default!;
|
|
||||||
[Dependency] private readonly SharedInteractionSystem _interactionSystem = default!;
|
|
||||||
[Dependency] private readonly InventorySystem _inventorySystem = default!;
|
|
||||||
[Dependency] private readonly MobStateSystem _mobStateSystem = default!;
|
|
||||||
[Dependency] private readonly ChatSystem _chatSystem = default!;
|
|
||||||
public override void Initialize()
|
|
||||||
{
|
|
||||||
base.Initialize();
|
|
||||||
SubscribeLocalEvent<DiseaseCarrierComponent, ComponentInit>(OnInit);
|
|
||||||
SubscribeLocalEvent<DiseaseCarrierComponent, CureDiseaseAttemptEvent>(OnTryCureDisease);
|
|
||||||
SubscribeLocalEvent<DiseaseCarrierComponent, RejuvenateEvent>(OnRejuvenate);
|
|
||||||
SubscribeLocalEvent<DiseasedComponent, ContactInteractionEvent>(OnContactInteraction);
|
|
||||||
SubscribeLocalEvent<DiseasedComponent, EntitySpokeEvent>(OnEntitySpeak);
|
|
||||||
SubscribeLocalEvent<DiseaseProtectionComponent, GotEquippedEvent>(OnEquipped);
|
|
||||||
SubscribeLocalEvent<DiseaseProtectionComponent, GotUnequippedEvent>(OnUnequipped);
|
|
||||||
SubscribeLocalEvent<DiseaseVaccineComponent, AfterInteractEvent>(OnAfterInteract);
|
|
||||||
SubscribeLocalEvent<DiseaseVaccineComponent, ExaminedEvent>(OnExamined);
|
|
||||||
// Handling stuff from other systems
|
|
||||||
SubscribeLocalEvent<DiseaseCarrierComponent, ApplyMetabolicMultiplierEvent>(OnApplyMetabolicMultiplier);
|
|
||||||
// Private events stuff
|
|
||||||
SubscribeLocalEvent<DiseaseVaccineComponent, VaccineDoAfterEvent>(OnDoAfter);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Queue<EntityUid> AddQueue = new();
|
|
||||||
private Queue<(DiseaseCarrierComponent carrier, DiseasePrototype disease)> CureQueue = new();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// First, adds or removes diseased component from the queues and clears them.
|
|
||||||
/// Then, iterates over every diseased component to check for their effects
|
|
||||||
/// and cures
|
|
||||||
/// </summary>
|
|
||||||
public override void Update(float frameTime)
|
|
||||||
{
|
|
||||||
base.Update(frameTime);
|
|
||||||
foreach (var entity in AddQueue)
|
|
||||||
{
|
|
||||||
EnsureComp<DiseasedComponent>(entity);
|
|
||||||
}
|
|
||||||
|
|
||||||
AddQueue.Clear();
|
|
||||||
|
|
||||||
foreach (var tuple in CureQueue)
|
|
||||||
{
|
|
||||||
if (tuple.carrier.Diseases.Count == 1) //This is reliable unlike testing Count == 0 right after removal for reasons I don't quite get
|
|
||||||
RemComp<DiseasedComponent>(tuple.carrier.Owner);
|
|
||||||
tuple.carrier.PastDiseases.Add(tuple.disease);
|
|
||||||
tuple.carrier.Diseases.Remove(tuple.disease);
|
|
||||||
}
|
|
||||||
CureQueue.Clear();
|
|
||||||
|
|
||||||
foreach (var (_, carrierComp, mobState) in EntityQuery<DiseasedComponent, DiseaseCarrierComponent, MobStateComponent>())
|
|
||||||
{
|
|
||||||
DebugTools.Assert(carrierComp.Diseases.Count > 0);
|
|
||||||
|
|
||||||
if (_mobStateSystem.IsDead(mobState.Owner, mobState))
|
|
||||||
{
|
|
||||||
if (_random.Prob(0.005f * frameTime)) //Mean time to remove is 200 seconds per disease
|
|
||||||
CureDisease(carrierComp, _random.Pick(carrierComp.Diseases));
|
|
||||||
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (var i = 0; i < carrierComp.Diseases.Count; i++) //this is a for-loop so that it doesn't break when new diseases are added
|
|
||||||
{
|
|
||||||
var disease = carrierComp.Diseases[i];
|
|
||||||
disease.Accumulator += frameTime;
|
|
||||||
disease.TotalAccumulator += frameTime;
|
|
||||||
|
|
||||||
if (disease.Accumulator < disease.TickTime) continue;
|
|
||||||
|
|
||||||
// if the disease is on the silent disease list, don't do effects
|
|
||||||
var doEffects = carrierComp.CarrierDiseases?.Contains(disease.ID) != true;
|
|
||||||
var args = new DiseaseEffectArgs(carrierComp.Owner, disease, EntityManager);
|
|
||||||
disease.Accumulator -= disease.TickTime;
|
|
||||||
|
|
||||||
int stage = 0; //defaults to stage 0 because you should always have one
|
|
||||||
float lastThreshold = 0;
|
|
||||||
for (var j = 0; j < disease.Stages.Count; j++)
|
|
||||||
{
|
|
||||||
if (disease.TotalAccumulator >= disease.Stages[j] &&
|
|
||||||
disease.Stages[j] > lastThreshold)
|
|
||||||
{
|
|
||||||
lastThreshold = disease.Stages[j];
|
|
||||||
stage = j;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var cure in disease.Cures)
|
|
||||||
{
|
|
||||||
if (cure.Stages.AsSpan().Contains(stage) && cure.Cure(args))
|
|
||||||
CureDisease(carrierComp, disease);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (doEffects)
|
|
||||||
{
|
|
||||||
foreach (var effect in disease.Effects)
|
|
||||||
{
|
|
||||||
if (effect.Stages.AsSpan().Contains(stage) && _random.Prob(effect.Probability))
|
|
||||||
effect.Effect(args);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
///
|
|
||||||
/// Event Handlers
|
|
||||||
///
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Fill in the natural immunities of this entity.
|
|
||||||
/// </summary>
|
|
||||||
private void OnInit(EntityUid uid, DiseaseCarrierComponent component, ComponentInit args)
|
|
||||||
{
|
|
||||||
if (component.NaturalImmunities == null || component.NaturalImmunities.Count == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
foreach (var immunity in component.NaturalImmunities)
|
|
||||||
{
|
|
||||||
if (_prototypeManager.TryIndex<DiseasePrototype>(immunity, out var disease))
|
|
||||||
component.PastDiseases.Add(disease);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Logger.Error("Failed to index disease prototype + " + immunity + " for " + uid);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Used when something is trying to cure ANY disease on the target,
|
|
||||||
/// not for special disease interactions. Randomly
|
|
||||||
/// tries to cure every disease on the target.
|
|
||||||
/// </summary>
|
|
||||||
private void OnTryCureDisease(EntityUid uid, DiseaseCarrierComponent component, CureDiseaseAttemptEvent args)
|
|
||||||
{
|
|
||||||
foreach (var disease in component.Diseases)
|
|
||||||
{
|
|
||||||
var cureProb = ((args.CureChance / component.Diseases.Count) - disease.CureResist);
|
|
||||||
if (cureProb < 0)
|
|
||||||
return;
|
|
||||||
if (cureProb > 1)
|
|
||||||
{
|
|
||||||
CureDisease(component, disease);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (_random.Prob(cureProb))
|
|
||||||
{
|
|
||||||
CureDisease(component, disease);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnRejuvenate(EntityUid uid, DiseaseCarrierComponent component, RejuvenateEvent args)
|
|
||||||
{
|
|
||||||
CureAllDiseases(uid, component);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Called when a component with disease protection
|
|
||||||
/// is equipped so it can be added to the person's
|
|
||||||
/// total disease resistance
|
|
||||||
/// </summary>
|
|
||||||
private void OnEquipped(EntityUid uid, DiseaseProtectionComponent component, GotEquippedEvent args)
|
|
||||||
{
|
|
||||||
// This only works on clothing
|
|
||||||
if (!TryComp<ClothingComponent>(uid, out var clothing))
|
|
||||||
return;
|
|
||||||
// Is the clothing in its actual slot?
|
|
||||||
if (!clothing.Slots.HasFlag(args.SlotFlags))
|
|
||||||
return;
|
|
||||||
// Give the user the component's disease resist
|
|
||||||
if(TryComp<DiseaseCarrierComponent>(args.Equipee, out var carrier))
|
|
||||||
carrier.DiseaseResist += component.Protection;
|
|
||||||
// Set the component to active to the unequip check isn't CBT
|
|
||||||
component.IsActive = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Called when a component with disease protection
|
|
||||||
/// is unequipped so it can be removed from the person's
|
|
||||||
/// total disease resistance
|
|
||||||
/// </summary>
|
|
||||||
private void OnUnequipped(EntityUid uid, DiseaseProtectionComponent component, GotUnequippedEvent args)
|
|
||||||
{
|
|
||||||
// Only undo the resistance if it was affecting the user
|
|
||||||
if (!component.IsActive)
|
|
||||||
return;
|
|
||||||
if(TryComp<DiseaseCarrierComponent>(args.Equipee, out var carrier))
|
|
||||||
carrier.DiseaseResist -= component.Protection;
|
|
||||||
component.IsActive = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Called when it's already decided a disease will be cured
|
|
||||||
/// so it can be safely queued up to be removed from the target
|
|
||||||
/// and added to past disease history (for immunity)
|
|
||||||
/// </summary>
|
|
||||||
private void CureDisease(DiseaseCarrierComponent carrier, DiseasePrototype disease)
|
|
||||||
{
|
|
||||||
var CureTuple = (carrier, disease);
|
|
||||||
CureQueue.Enqueue(CureTuple);
|
|
||||||
_popupSystem.PopupEntity(Loc.GetString("disease-cured"), carrier.Owner, carrier.Owner);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void CureAllDiseases(EntityUid uid, DiseaseCarrierComponent? carrier = null)
|
|
||||||
{
|
|
||||||
if (!Resolve(uid, ref carrier))
|
|
||||||
return;
|
|
||||||
|
|
||||||
foreach (var disease in carrier.Diseases)
|
|
||||||
{
|
|
||||||
CureDisease(carrier, disease);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// When a diseased person interacts with something, check infection.
|
|
||||||
/// </summary>
|
|
||||||
private void OnContactInteraction(EntityUid uid, DiseasedComponent component, ContactInteractionEvent args)
|
|
||||||
{
|
|
||||||
InteractWithDiseased(uid, args.Other);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnEntitySpeak(EntityUid uid, DiseasedComponent component, EntitySpokeEvent args)
|
|
||||||
{
|
|
||||||
if (TryComp<DiseaseCarrierComponent>(uid, out var carrier))
|
|
||||||
{
|
|
||||||
SneezeCough(uid, _random.Pick(carrier.Diseases), string.Empty);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Called when a vaccine is used on someone
|
|
||||||
/// to handle the vaccination doafter
|
|
||||||
/// </summary>
|
|
||||||
private void OnAfterInteract(EntityUid uid, DiseaseVaccineComponent vaxx, AfterInteractEvent args)
|
|
||||||
{
|
|
||||||
if (args.Target == null || !args.CanReach || args.Handled)
|
|
||||||
return;
|
|
||||||
|
|
||||||
args.Handled = true;
|
|
||||||
|
|
||||||
if (vaxx.Used)
|
|
||||||
{
|
|
||||||
_popupSystem.PopupEntity(Loc.GetString("vaxx-already-used"), args.User, args.User);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_doAfterSystem.TryStartDoAfter(new DoAfterArgs(args.User, vaxx.InjectDelay, new VaccineDoAfterEvent(), uid, target: args.Target, used: uid)
|
|
||||||
{
|
|
||||||
BreakOnTargetMove = true,
|
|
||||||
BreakOnUserMove = true,
|
|
||||||
NeedHand = true
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Called when a vaccine is examined.
|
|
||||||
/// Currently doesn't do much because
|
|
||||||
/// vaccines don't have unique art with a seperate
|
|
||||||
/// state visualizer.
|
|
||||||
/// </summary>
|
|
||||||
private void OnExamined(EntityUid uid, DiseaseVaccineComponent vaxx, ExaminedEvent args)
|
|
||||||
{
|
|
||||||
if (args.IsInDetailsRange)
|
|
||||||
{
|
|
||||||
if (vaxx.Used)
|
|
||||||
args.PushMarkup(Loc.GetString("vaxx-used"));
|
|
||||||
else
|
|
||||||
args.PushMarkup(Loc.GetString("vaxx-unused"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private void OnApplyMetabolicMultiplier(EntityUid uid, DiseaseCarrierComponent component, ApplyMetabolicMultiplierEvent args)
|
|
||||||
{
|
|
||||||
if (args.Apply)
|
|
||||||
{
|
|
||||||
foreach (var disease in component.Diseases)
|
|
||||||
{
|
|
||||||
disease.TickTime *= args.Multiplier;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
foreach (var disease in component.Diseases)
|
|
||||||
{
|
|
||||||
disease.TickTime /= args.Multiplier;
|
|
||||||
if (disease.Accumulator >= disease.TickTime)
|
|
||||||
disease.Accumulator = disease.TickTime;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
///
|
|
||||||
/// Helper functions
|
|
||||||
///
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Tries to infect anyone that
|
|
||||||
/// interacts with a diseased person or body
|
|
||||||
/// </summary>
|
|
||||||
private void InteractWithDiseased(EntityUid diseased, EntityUid target, DiseaseCarrierComponent? diseasedCarrier = null)
|
|
||||||
{
|
|
||||||
if (!Resolve(diseased, ref diseasedCarrier, false) ||
|
|
||||||
diseasedCarrier.Diseases.Count == 0 ||
|
|
||||||
!TryComp<DiseaseCarrierComponent>(target, out var carrier))
|
|
||||||
return;
|
|
||||||
|
|
||||||
var disease = _random.Pick(diseasedCarrier.Diseases);
|
|
||||||
TryInfect(carrier, disease, 0.4f);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Adds a disease to a target
|
|
||||||
/// if it's not already in their current
|
|
||||||
/// or past diseases. If you want this
|
|
||||||
/// to not be guaranteed you are looking
|
|
||||||
/// for TryInfect.
|
|
||||||
/// </summary>
|
|
||||||
public void TryAddDisease(EntityUid host, DiseasePrototype addedDisease, DiseaseCarrierComponent? target = null)
|
|
||||||
{
|
|
||||||
if (!Resolve(host, ref target, false))
|
|
||||||
return;
|
|
||||||
|
|
||||||
foreach (var disease in target.AllDiseases)
|
|
||||||
{
|
|
||||||
if (disease.ID == addedDisease?.ID) //ID because of the way protoypes work
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var freshDisease = _serializationManager.CreateCopy(addedDisease, notNullableOverride: true);
|
|
||||||
|
|
||||||
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<DiseasePrototype>(addedDisease, out var added))
|
|
||||||
return;
|
|
||||||
|
|
||||||
TryAddDisease(host, added, target);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Pits the infection chance against the
|
|
||||||
/// person's disease resistance and
|
|
||||||
/// rolls the dice to see if they get
|
|
||||||
/// the disease.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="carrier">The target of the disease</param>
|
|
||||||
/// <param name="disease">The disease to apply</param>
|
|
||||||
/// <param name="chance">% chance of the disease being applied, before considering resistance</param>
|
|
||||||
/// <param name="forced">Bypass the disease's infectious trait.</param>
|
|
||||||
public void TryInfect(DiseaseCarrierComponent carrier, DiseasePrototype? disease, float chance = 0.7f, bool forced = false)
|
|
||||||
{
|
|
||||||
if(disease == null || !forced && !disease.Infectious)
|
|
||||||
return;
|
|
||||||
var infectionChance = chance - carrier.DiseaseResist;
|
|
||||||
if (infectionChance <= 0)
|
|
||||||
return;
|
|
||||||
if (_random.Prob(infectionChance))
|
|
||||||
TryAddDisease(carrier.Owner, disease, carrier);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void TryInfect(DiseaseCarrierComponent carrier, string? disease, float chance = 0.7f, bool forced = false)
|
|
||||||
{
|
|
||||||
if (disease == null || !_prototypeManager.TryIndex<DiseasePrototype>(disease, out var d))
|
|
||||||
return;
|
|
||||||
|
|
||||||
TryInfect(carrier, d, chance, forced);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Raises an event for systems to cancel the snough if needed
|
|
||||||
/// Plays a sneeze/cough sound and popup if applicable
|
|
||||||
/// and then tries to infect anyone in range
|
|
||||||
/// if the snougher is not wearing a mask.
|
|
||||||
/// </summary>
|
|
||||||
public bool SneezeCough(EntityUid uid, DiseasePrototype? disease, string emoteId, bool airTransmit = true, TransformComponent? xform = null)
|
|
||||||
{
|
|
||||||
if (!Resolve(uid, ref xform)) return false;
|
|
||||||
|
|
||||||
if (_mobStateSystem.IsDead(uid)) return false;
|
|
||||||
|
|
||||||
var attemptSneezeCoughEvent = new AttemptSneezeCoughEvent(uid, emoteId);
|
|
||||||
RaiseLocalEvent(uid, ref attemptSneezeCoughEvent);
|
|
||||||
if (attemptSneezeCoughEvent.Cancelled) return false;
|
|
||||||
|
|
||||||
_chatSystem.TryEmoteWithChat(uid, emoteId);
|
|
||||||
|
|
||||||
if (disease is not { Infectious: true } || !airTransmit)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
if (_inventorySystem.TryGetSlotEntity(uid, "mask", out var maskUid) &&
|
|
||||||
EntityManager.TryGetComponent<IngestionBlockerComponent>(maskUid, out var blocker) &&
|
|
||||||
blocker.Enabled)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
var carrierQuery = GetEntityQuery<DiseaseCarrierComponent>();
|
|
||||||
|
|
||||||
foreach (var entity in _lookup.GetEntitiesInRange(xform.MapPosition, 2f))
|
|
||||||
{
|
|
||||||
if (!carrierQuery.TryGetComponent(entity, out var carrier) ||
|
|
||||||
!_interactionSystem.InRangeUnobstructed(uid, entity)) continue;
|
|
||||||
|
|
||||||
TryInfect(carrier, disease, 0.3f);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Adds a disease to the carrier's
|
|
||||||
/// past diseases to give them immunity
|
|
||||||
/// IF they don't already have the disease.
|
|
||||||
/// </summary>
|
|
||||||
public void Vaccinate(DiseaseCarrierComponent carrier, DiseasePrototype disease)
|
|
||||||
{
|
|
||||||
foreach (var currentDisease in carrier.Diseases)
|
|
||||||
{
|
|
||||||
if (currentDisease.ID == disease.ID) //ID because of the way protoypes work
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
carrier.PastDiseases.Add(disease);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnDoAfter(EntityUid uid, DiseaseVaccineComponent component, DoAfterEvent args)
|
|
||||||
{
|
|
||||||
if (args.Handled || args.Cancelled || !TryComp<DiseaseCarrierComponent>(args.Args.Target, out var carrier) || component.Disease == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
Vaccinate(carrier, component.Disease);
|
|
||||||
EntityManager.DeleteEntity(uid);
|
|
||||||
args.Handled = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This event is fired by chems
|
|
||||||
/// and other brute-force rather than
|
|
||||||
/// specific cures. It will roll the dice to attempt
|
|
||||||
/// to cure each disease on the target
|
|
||||||
/// </summary>
|
|
||||||
public sealed class CureDiseaseAttemptEvent : EntityEventArgs
|
|
||||||
{
|
|
||||||
public float CureChance { get; }
|
|
||||||
public CureDiseaseAttemptEvent(float cureChance)
|
|
||||||
{
|
|
||||||
CureChance = cureChance;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Controls whether the snough is a sneeze, cough
|
|
||||||
/// or neither. If none, will not create
|
|
||||||
/// a popup. Mostly used for talking
|
|
||||||
/// </summary>
|
|
||||||
public enum SneezeCoughType
|
|
||||||
{
|
|
||||||
Sneeze,
|
|
||||||
Cough,
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
using JetBrains.Annotations;
|
|
||||||
using Content.Shared.Disease;
|
|
||||||
|
|
||||||
namespace Content.Server.Disease.Effects
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Adds a component to the diseased entity
|
|
||||||
/// </summary>
|
|
||||||
[UsedImplicitly]
|
|
||||||
public sealed class DiseaseAddComponent : DiseaseEffect
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// The component that is added at the end of build up
|
|
||||||
/// </summary>
|
|
||||||
[DataField("comp")]
|
|
||||||
public string? Comp = null;
|
|
||||||
|
|
||||||
public override void Effect(DiseaseEffectArgs args)
|
|
||||||
{
|
|
||||||
if (Comp == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
EntityUid uid = args.DiseasedEntity;
|
|
||||||
var newComponent = (Component) IoCManager.Resolve<IComponentFactory>().GetComponent(Comp);
|
|
||||||
newComponent.Owner = uid;
|
|
||||||
if (!args.EntityManager.HasComponent(uid, newComponent.GetType()))
|
|
||||||
args.EntityManager.AddComponent(uid, newComponent);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,47 +0,0 @@
|
|||||||
using Content.Server.Chemistry.EntitySystems;
|
|
||||||
using Content.Shared.Chemistry.Reagent;
|
|
||||||
using Content.Shared.FixedPoint;
|
|
||||||
using JetBrains.Annotations;
|
|
||||||
using Content.Server.Body.Components;
|
|
||||||
using Content.Shared.Disease;
|
|
||||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
|
||||||
|
|
||||||
namespace Content.Server.Disease.Effects
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Adds or removes reagents from the
|
|
||||||
/// host's chemstream.
|
|
||||||
/// </summary>
|
|
||||||
[UsedImplicitly]
|
|
||||||
public sealed class DiseaseAdjustReagent : DiseaseEffect
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// The reagent ID to add or remove.
|
|
||||||
/// </summary>
|
|
||||||
[DataField("reagent", customTypeSerializer:typeof(PrototypeIdSerializer<ReagentPrototype>))]
|
|
||||||
public string? Reagent = null;
|
|
||||||
|
|
||||||
[DataField("amount", required: true)]
|
|
||||||
public FixedPoint2 Amount = default!;
|
|
||||||
|
|
||||||
public override void Effect(DiseaseEffectArgs args)
|
|
||||||
{
|
|
||||||
if (!args.EntityManager.TryGetComponent<BloodstreamComponent>(args.DiseasedEntity, out var bloodstream))
|
|
||||||
return;
|
|
||||||
|
|
||||||
var stream = bloodstream.ChemicalSolution;
|
|
||||||
if (stream == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
var solutionSys = args.EntityManager.EntitySysManager.GetEntitySystem<SolutionContainerSystem>();
|
|
||||||
if (Reagent == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (Amount < 0 && stream.ContainsReagent(Reagent))
|
|
||||||
solutionSys.TryRemoveReagent(args.DiseasedEntity, stream, Reagent, -Amount);
|
|
||||||
|
|
||||||
if (Amount > 0)
|
|
||||||
solutionSys.TryAddReagent(args.DiseasedEntity, stream, Reagent, Amount, out _);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,67 +0,0 @@
|
|||||||
using Content.Shared.Disease;
|
|
||||||
using Content.Shared.StatusEffect;
|
|
||||||
using JetBrains.Annotations;
|
|
||||||
|
|
||||||
namespace Content.Server.Disease.Effects
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Adds a generic status effect to the entity.
|
|
||||||
/// Differs from the chem version in its defaults
|
|
||||||
/// to better facilitate adding components that
|
|
||||||
/// last the length of the disease.
|
|
||||||
/// </summary>
|
|
||||||
[UsedImplicitly]
|
|
||||||
public sealed class DiseaseGenericStatusEffect : DiseaseEffect
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// The status effect key
|
|
||||||
/// Prevents other components from being with the same key
|
|
||||||
/// </summary>
|
|
||||||
[DataField("key", required: true)]
|
|
||||||
public string Key = default!;
|
|
||||||
/// <summary>
|
|
||||||
/// The component to add
|
|
||||||
/// </summary>
|
|
||||||
[DataField("component")]
|
|
||||||
public string Component = String.Empty;
|
|
||||||
|
|
||||||
[DataField("time")]
|
|
||||||
public float Time = 1.01f; /// I'm afraid if this was exact the key could get stolen by another thing
|
|
||||||
|
|
||||||
/// <remarks>
|
|
||||||
/// true - refresh status effect time, false - accumulate status effect time
|
|
||||||
/// </remarks>
|
|
||||||
[DataField("refresh")]
|
|
||||||
public bool Refresh = false;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Should this effect add the status effect, remove time from it, or set its cooldown?
|
|
||||||
/// </summary>
|
|
||||||
[DataField("type")]
|
|
||||||
public StatusEffectDiseaseType Type = StatusEffectDiseaseType.Add;
|
|
||||||
|
|
||||||
public override void Effect(DiseaseEffectArgs args)
|
|
||||||
{
|
|
||||||
var statusSys = EntitySystem.Get<StatusEffectsSystem>();
|
|
||||||
if (Type == StatusEffectDiseaseType.Add && Component != String.Empty)
|
|
||||||
{
|
|
||||||
statusSys.TryAddStatusEffect(args.DiseasedEntity, Key, TimeSpan.FromSeconds(Time), Refresh, Component);
|
|
||||||
}
|
|
||||||
else if (Type == StatusEffectDiseaseType.Remove)
|
|
||||||
{
|
|
||||||
statusSys.TryRemoveTime(args.DiseasedEntity, Key, TimeSpan.FromSeconds(Time));
|
|
||||||
}
|
|
||||||
else if (Type == StatusEffectDiseaseType.Set)
|
|
||||||
{
|
|
||||||
statusSys.TrySetTime(args.DiseasedEntity, Key, TimeSpan.FromSeconds(Time));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/// See status effects for how these work
|
|
||||||
public enum StatusEffectDiseaseType
|
|
||||||
{
|
|
||||||
Add,
|
|
||||||
Remove,
|
|
||||||
Set
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
using Content.Shared.Disease;
|
|
||||||
using Content.Shared.Damage;
|
|
||||||
using JetBrains.Annotations;
|
|
||||||
|
|
||||||
namespace Content.Server.Disease.Effects
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Deals or heals damage to the host
|
|
||||||
/// </summary>
|
|
||||||
[UsedImplicitly]
|
|
||||||
public sealed class DiseaseHealthChange : DiseaseEffect
|
|
||||||
{
|
|
||||||
[DataField("damage", required: true)]
|
|
||||||
[ViewVariables(VVAccess.ReadWrite)]
|
|
||||||
public DamageSpecifier Damage = default!;
|
|
||||||
public override void Effect(DiseaseEffectArgs args)
|
|
||||||
{
|
|
||||||
EntitySystem.Get<DamageableSystem>().TryChangeDamage(args.DiseasedEntity, Damage, true, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
using Content.Shared.Chat.Prototypes;
|
|
||||||
using Content.Shared.Disease;
|
|
||||||
using JetBrains.Annotations;
|
|
||||||
using Robust.Shared.Audio;
|
|
||||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
|
||||||
|
|
||||||
namespace Content.Server.Disease
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Makes the diseased honk.
|
|
||||||
/// or neither.
|
|
||||||
/// </summary>
|
|
||||||
[UsedImplicitly]
|
|
||||||
public sealed class DiseaseHonk : DiseaseEffect
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Message to play when honking.
|
|
||||||
/// </summary>
|
|
||||||
[DataField("honkMessage")]
|
|
||||||
public string HonkMessage = "disease-honk";
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Emote to play when honking.
|
|
||||||
/// </summary>
|
|
||||||
[DataField("emote", required: true, customTypeSerializer: typeof(PrototypeIdSerializer<EmotePrototype>))]
|
|
||||||
public string EmoteId = String.Empty;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Whether to spread the disease through the air.
|
|
||||||
/// </summary>
|
|
||||||
[DataField("airTransmit")]
|
|
||||||
public bool AirTransmit = false;
|
|
||||||
|
|
||||||
public override void Effect(DiseaseEffectArgs args)
|
|
||||||
{
|
|
||||||
EntitySystem.Get<DiseaseSystem>().SneezeCough(args.DiseasedEntity, args.Disease, EmoteId, AirTransmit);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
using Content.Server.Polymorph.Systems;
|
|
||||||
using Content.Shared.Audio;
|
|
||||||
using Content.Shared.Disease;
|
|
||||||
using Content.Shared.Polymorph;
|
|
||||||
using Content.Shared.Popups;
|
|
||||||
using JetBrains.Annotations;
|
|
||||||
using Robust.Shared.Audio;
|
|
||||||
using Robust.Shared.Player;
|
|
||||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
|
||||||
|
|
||||||
namespace Content.Server.Disease.Effects
|
|
||||||
{
|
|
||||||
[UsedImplicitly]
|
|
||||||
public sealed class DiseasePolymorph : DiseaseEffect
|
|
||||||
{
|
|
||||||
[DataField("polymorphId", required: true, customTypeSerializer: typeof(PrototypeIdSerializer<PolymorphPrototype>))]
|
|
||||||
[ViewVariables(VVAccess.ReadWrite)]
|
|
||||||
public readonly string PolymorphId = default!;
|
|
||||||
|
|
||||||
[DataField("polymorphSound")]
|
|
||||||
[ViewVariables(VVAccess.ReadWrite)]
|
|
||||||
public SoundSpecifier? PolymorphSound;
|
|
||||||
|
|
||||||
[DataField("polymorphMessage")]
|
|
||||||
[ViewVariables(VVAccess.ReadWrite)]
|
|
||||||
public string? PolymorphMessage;
|
|
||||||
|
|
||||||
public override void Effect(DiseaseEffectArgs args)
|
|
||||||
{
|
|
||||||
EntityUid? polyUid = EntitySystem.Get<PolymorphSystem>().PolymorphEntity(args.DiseasedEntity, PolymorphId);
|
|
||||||
|
|
||||||
if (PolymorphSound != null && polyUid != null)
|
|
||||||
SoundSystem.Play(PolymorphSound.GetSound(), Filter.Pvs(polyUid.Value), polyUid.Value, AudioHelpers.WithVariation(0.2f));
|
|
||||||
|
|
||||||
if (PolymorphMessage != null && polyUid != null)
|
|
||||||
EntitySystem.Get<SharedPopupSystem>().PopupEntity(Loc.GetString(PolymorphMessage), polyUid.Value, polyUid.Value, PopupType.Large);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,43 +0,0 @@
|
|||||||
using Content.Shared.Disease;
|
|
||||||
using Content.Shared.Popups;
|
|
||||||
using Robust.Shared.Player;
|
|
||||||
using JetBrains.Annotations;
|
|
||||||
using Content.Shared.IdentityManagement;
|
|
||||||
|
|
||||||
namespace Content.Server.Disease.Effects
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Plays a popup on the host's transform.
|
|
||||||
/// Supports passing the host's entity metadata
|
|
||||||
/// in PVS ones with {$person}
|
|
||||||
/// </summary>
|
|
||||||
[UsedImplicitly]
|
|
||||||
public sealed class DiseasePopUp : DiseaseEffect
|
|
||||||
{
|
|
||||||
[DataField("message")]
|
|
||||||
public string Message = "disease-sick-generic";
|
|
||||||
|
|
||||||
[DataField("type")]
|
|
||||||
public PopupRecipients Type = PopupRecipients.Local;
|
|
||||||
|
|
||||||
[DataField("visualType")]
|
|
||||||
public PopupType VisualType = PopupType.Small;
|
|
||||||
|
|
||||||
public override void Effect(DiseaseEffectArgs args)
|
|
||||||
{
|
|
||||||
var popupSys = args.EntityManager.EntitySysManager.GetEntitySystem<SharedPopupSystem>();
|
|
||||||
|
|
||||||
if (Type == PopupRecipients.Local)
|
|
||||||
popupSys.PopupEntity(Loc.GetString(Message), args.DiseasedEntity, args.DiseasedEntity, VisualType);
|
|
||||||
else if (Type == PopupRecipients.Pvs)
|
|
||||||
popupSys.PopupEntity(Loc.GetString(Message, ("person", Identity.Entity(args.DiseasedEntity, args.EntityManager))), args.DiseasedEntity, VisualType);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum PopupRecipients
|
|
||||||
{
|
|
||||||
Pvs,
|
|
||||||
Local
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
using Content.Shared.Chat.Prototypes;
|
|
||||||
using Content.Shared.Disease;
|
|
||||||
using JetBrains.Annotations;
|
|
||||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
|
||||||
|
|
||||||
namespace Content.Server.Disease
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Makes the diseased sneeze or cough
|
|
||||||
/// or neither.
|
|
||||||
/// </summary>
|
|
||||||
[UsedImplicitly]
|
|
||||||
public sealed class DiseaseSnough : DiseaseEffect
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Emote to play when snoughing
|
|
||||||
/// </summary>
|
|
||||||
[DataField("emote", required: true, customTypeSerializer: typeof(PrototypeIdSerializer<EmotePrototype>))]
|
|
||||||
public string EmoteId = String.Empty;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Whether to spread the disease through the air
|
|
||||||
/// </summary>
|
|
||||||
[DataField("airTransmit")]
|
|
||||||
public bool AirTransmit = true;
|
|
||||||
|
|
||||||
public override void Effect(DiseaseEffectArgs args)
|
|
||||||
{
|
|
||||||
EntitySystem.Get<DiseaseSystem>().SneezeCough(args.DiseasedEntity, args.Disease, EmoteId, AirTransmit);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
using JetBrains.Annotations;
|
|
||||||
using Content.Shared.Disease;
|
|
||||||
using Content.Server.Medical;
|
|
||||||
|
|
||||||
namespace Content.Server.Disease.Effects
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Forces you to vomit.
|
|
||||||
/// </summary>
|
|
||||||
[UsedImplicitly]
|
|
||||||
public sealed class DiseaseVomit : DiseaseEffect
|
|
||||||
{
|
|
||||||
/// How many units of thirst to add each time we vomit
|
|
||||||
[DataField("thirstAmount")]
|
|
||||||
public float ThirstAmount = -40f;
|
|
||||||
/// How many units of hunger to add each time we vomit
|
|
||||||
[DataField("hungerAmount")]
|
|
||||||
public float HungerAmount = -40f;
|
|
||||||
|
|
||||||
public override void Effect(DiseaseEffectArgs args)
|
|
||||||
{
|
|
||||||
var vomitSys = args.EntityManager.EntitySysManager.GetEntitySystem<VomitSystem>();
|
|
||||||
|
|
||||||
vomitSys.Vomit(args.DiseasedEntity, ThirstAmount, HungerAmount);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
using Content.Shared.Disease;
|
|
||||||
|
|
||||||
|
|
||||||
namespace Content.Server.Disease.Components
|
|
||||||
{
|
|
||||||
[RegisterComponent]
|
|
||||||
public sealed class DiseaseServerComponent : Component
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Which diseases this server has information on.
|
|
||||||
/// </summary>
|
|
||||||
[ViewVariables(VVAccess.ReadWrite)]
|
|
||||||
public List<DiseasePrototype> Diseases = new();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -7,6 +7,5 @@ public sealed class ZombieRuleComponent : Component
|
|||||||
public Dictionary<string, string> InitialInfectedNames = new();
|
public Dictionary<string, string> InitialInfectedNames = new();
|
||||||
|
|
||||||
public string PatientZeroPrototypeID = "InitialInfected";
|
public string PatientZeroPrototypeID = "InitialInfected";
|
||||||
public string InitialZombieVirusPrototype = "PassiveZombieVirus";
|
|
||||||
public const string ZombifySelfActionPrototype = "TurnUndead";
|
public const string ZombifySelfActionPrototype = "TurnUndead";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,8 +2,6 @@ using System.Globalization;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Content.Server.Actions;
|
using Content.Server.Actions;
|
||||||
using Content.Server.Chat.Managers;
|
using Content.Server.Chat.Managers;
|
||||||
using Content.Server.Disease;
|
|
||||||
using Content.Server.Disease.Components;
|
|
||||||
using Content.Server.GameTicking.Rules.Components;
|
using Content.Server.GameTicking.Rules.Components;
|
||||||
using Content.Server.Mind.Components;
|
using Content.Server.Mind.Components;
|
||||||
using Content.Server.Players;
|
using Content.Server.Players;
|
||||||
@@ -38,7 +36,6 @@ public sealed class ZombieRuleSystem : GameRuleSystem<ZombieRuleComponent>
|
|||||||
[Dependency] private readonly IPlayerManager _playerManager = default!;
|
[Dependency] private readonly IPlayerManager _playerManager = default!;
|
||||||
[Dependency] private readonly IServerPreferencesManager _prefs = default!;
|
[Dependency] private readonly IServerPreferencesManager _prefs = default!;
|
||||||
[Dependency] private readonly RoundEndSystem _roundEndSystem = default!;
|
[Dependency] private readonly RoundEndSystem _roundEndSystem = default!;
|
||||||
[Dependency] private readonly DiseaseSystem _diseaseSystem = default!;
|
|
||||||
[Dependency] private readonly PopupSystem _popup = default!;
|
[Dependency] private readonly PopupSystem _popup = default!;
|
||||||
[Dependency] private readonly ActionsSystem _action = default!;
|
[Dependency] private readonly ActionsSystem _action = default!;
|
||||||
[Dependency] private readonly MobStateSystem _mobState = default!;
|
[Dependency] private readonly MobStateSystem _mobState = default!;
|
||||||
@@ -233,7 +230,8 @@ public sealed class ZombieRuleSystem : GameRuleSystem<ZombieRuleComponent>
|
|||||||
var prefList = new List<IPlayerSession>();
|
var prefList = new List<IPlayerSession>();
|
||||||
foreach (var player in allPlayers)
|
foreach (var player in allPlayers)
|
||||||
{
|
{
|
||||||
if (player.AttachedEntity != null && HasComp<DiseaseCarrierComponent>(player.AttachedEntity))
|
// TODO: A
|
||||||
|
if (player.AttachedEntity != null && HasComp<HumanoidAppearanceComponent>(player.AttachedEntity))
|
||||||
{
|
{
|
||||||
playerList.Add(player);
|
playerList.Add(player);
|
||||||
|
|
||||||
@@ -287,7 +285,8 @@ public sealed class ZombieRuleSystem : GameRuleSystem<ZombieRuleComponent>
|
|||||||
var inCharacterName = string.Empty;
|
var inCharacterName = string.Empty;
|
||||||
if (mind.OwnedEntity != null)
|
if (mind.OwnedEntity != null)
|
||||||
{
|
{
|
||||||
_diseaseSystem.TryAddDisease(mind.OwnedEntity.Value, component.InitialZombieVirusPrototype);
|
EnsureComp<PendingZombieComponent>(mind.OwnedEntity.Value);
|
||||||
|
EnsureComp<ZombifyOnDeathComponent>(mind.OwnedEntity.Value);
|
||||||
inCharacterName = MetaData(mind.OwnedEntity.Value).EntityName;
|
inCharacterName = MetaData(mind.OwnedEntity.Value).EntityName;
|
||||||
|
|
||||||
var action = new InstantAction(_prototypeManager.Index<InstantActionPrototype>(ZombieRuleComponent.ZombifySelfActionPrototype));
|
var action = new InstantAction(_prototypeManager.Index<InstantActionPrototype>(ZombieRuleComponent.ZombifySelfActionPrototype));
|
||||||
|
|||||||
@@ -1,9 +1,7 @@
|
|||||||
using Content.Server.UserInterface;
|
using Content.Server.UserInterface;
|
||||||
using Content.Shared.Disease;
|
|
||||||
using Content.Shared.MedicalScanner;
|
using Content.Shared.MedicalScanner;
|
||||||
using Robust.Server.GameObjects;
|
using Robust.Server.GameObjects;
|
||||||
using Robust.Shared.Audio;
|
using Robust.Shared.Audio;
|
||||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
|
||||||
|
|
||||||
namespace Content.Server.Medical.Components
|
namespace Content.Server.Medical.Components
|
||||||
{
|
{
|
||||||
@@ -32,12 +30,5 @@ namespace Content.Server.Medical.Components
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
[DataField("scanningEndSound")]
|
[DataField("scanningEndSound")]
|
||||||
public SoundSpecifier? ScanningEndSound;
|
public SoundSpecifier? ScanningEndSound;
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The disease this will give people.
|
|
||||||
/// </summary>
|
|
||||||
[DataField("disease", customTypeSerializer: typeof(PrototypeIdSerializer<DiseasePrototype>))]
|
|
||||||
[ViewVariables(VVAccess.ReadWrite)]
|
|
||||||
public string? Disease;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,7 @@
|
|||||||
using Content.Server.Disease;
|
|
||||||
using Content.Server.Medical.Components;
|
using Content.Server.Medical.Components;
|
||||||
using Content.Server.Popups;
|
|
||||||
using Content.Server.PowerCell;
|
using Content.Server.PowerCell;
|
||||||
using Content.Server.UserInterface;
|
|
||||||
using Content.Shared.Damage;
|
using Content.Shared.Damage;
|
||||||
using Content.Shared.DoAfter;
|
using Content.Shared.DoAfter;
|
||||||
using Content.Shared.IdentityManagement;
|
|
||||||
using Content.Shared.Interaction;
|
using Content.Shared.Interaction;
|
||||||
using Content.Shared.MedicalScanner;
|
using Content.Shared.MedicalScanner;
|
||||||
using Content.Shared.Mobs.Components;
|
using Content.Shared.Mobs.Components;
|
||||||
@@ -15,8 +11,6 @@ namespace Content.Server.Medical
|
|||||||
{
|
{
|
||||||
public sealed class HealthAnalyzerSystem : EntitySystem
|
public sealed class HealthAnalyzerSystem : EntitySystem
|
||||||
{
|
{
|
||||||
[Dependency] private readonly DiseaseSystem _disease = default!;
|
|
||||||
[Dependency] private readonly PopupSystem _popupSystem = default!;
|
|
||||||
[Dependency] private readonly PowerCellSystem _cell = default!;
|
[Dependency] private readonly PowerCellSystem _cell = default!;
|
||||||
[Dependency] private readonly SharedAudioSystem _audio = default!;
|
[Dependency] private readonly SharedAudioSystem _audio = default!;
|
||||||
[Dependency] private readonly SharedDoAfterSystem _doAfterSystem = default!;
|
[Dependency] private readonly SharedDoAfterSystem _doAfterSystem = default!;
|
||||||
@@ -52,31 +46,6 @@ namespace Content.Server.Medical
|
|||||||
_audio.PlayPvs(component.ScanningEndSound, args.Args.User);
|
_audio.PlayPvs(component.ScanningEndSound, args.Args.User);
|
||||||
|
|
||||||
UpdateScannedUser(uid, args.Args.User, args.Args.Target.Value, component);
|
UpdateScannedUser(uid, args.Args.User, args.Args.Target.Value, 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
|
|
||||||
/*
|
|
||||||
* this code is cursed wuuuuuuut
|
|
||||||
*/
|
|
||||||
if (string.IsNullOrEmpty(component.Disease))
|
|
||||||
{
|
|
||||||
args.Handled = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_disease.TryAddDisease(args.Args.Target.Value, component.Disease);
|
|
||||||
|
|
||||||
if (args.Args.User == args.Args.Target)
|
|
||||||
{
|
|
||||||
_popupSystem.PopupEntity(Loc.GetString("disease-scanner-gave-self", ("disease", component.Disease)),
|
|
||||||
args.Args.User, args.Args.User);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_popupSystem.PopupEntity(Loc.GetString("disease-scanner-gave-other", ("target", Identity.Entity(args.Args.Target.Value, EntityManager)),
|
|
||||||
("disease", component.Disease)), args.Args.User, args.Args.User);
|
|
||||||
}
|
|
||||||
|
|
||||||
args.Handled = true;
|
args.Handled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,8 +11,6 @@ using Robust.Shared.Physics;
|
|||||||
using Content.Shared.Throwing;
|
using Content.Shared.Throwing;
|
||||||
using Content.Server.Storage.EntitySystems;
|
using Content.Server.Storage.EntitySystems;
|
||||||
using Content.Shared.Interaction;
|
using Content.Shared.Interaction;
|
||||||
using Content.Server.Disease;
|
|
||||||
using Content.Server.Disease.Components;
|
|
||||||
using Content.Shared.Item;
|
using Content.Shared.Item;
|
||||||
using Content.Shared.Bed.Sleep;
|
using Content.Shared.Bed.Sleep;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
@@ -26,7 +24,6 @@ using Content.Shared.Mobs;
|
|||||||
using Content.Shared.Mobs.Components;
|
using Content.Shared.Mobs.Components;
|
||||||
using Content.Shared.Mobs.Systems;
|
using Content.Shared.Mobs.Systems;
|
||||||
using Content.Shared.Revenant.Components;
|
using Content.Shared.Revenant.Components;
|
||||||
using Content.Shared.Revenant.EntitySystems;
|
|
||||||
using Robust.Shared.Physics.Components;
|
using Robust.Shared.Physics.Components;
|
||||||
using Robust.Shared.Utility;
|
using Robust.Shared.Utility;
|
||||||
|
|
||||||
@@ -37,7 +34,6 @@ public sealed partial class RevenantSystem
|
|||||||
[Dependency] private readonly IMapManager _mapManager = default!;
|
[Dependency] private readonly IMapManager _mapManager = default!;
|
||||||
[Dependency] private readonly ThrowingSystem _throwing = default!;
|
[Dependency] private readonly ThrowingSystem _throwing = default!;
|
||||||
[Dependency] private readonly EntityStorageSystem _entityStorage = default!;
|
[Dependency] private readonly EntityStorageSystem _entityStorage = default!;
|
||||||
[Dependency] private readonly DiseaseSystem _disease = default!;
|
|
||||||
[Dependency] private readonly EmagSystem _emag = default!;
|
[Dependency] private readonly EmagSystem _emag = default!;
|
||||||
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
|
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
|
||||||
[Dependency] private readonly MobThresholdSystem _mobThresholdSystem = default!;
|
[Dependency] private readonly MobThresholdSystem _mobThresholdSystem = default!;
|
||||||
@@ -308,13 +304,7 @@ public sealed partial class RevenantSystem
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
args.Handled = true;
|
args.Handled = true;
|
||||||
|
// TODO: When disease refactor is in.
|
||||||
var emo = GetEntityQuery<DiseaseCarrierComponent>();
|
|
||||||
foreach (var ent in _lookup.GetEntitiesInRange(uid, component.BlightRadius))
|
|
||||||
{
|
|
||||||
if (emo.TryGetComponent(ent, out var comp))
|
|
||||||
_disease.TryAddDisease(ent, component.BlightDiseasePrototypeId, comp);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnMalfunctionAction(EntityUid uid, RevenantComponent component, RevenantMalfunctionActionEvent args)
|
private void OnMalfunctionAction(EntityUid uid, RevenantComponent component, RevenantMalfunctionActionEvent args)
|
||||||
|
|||||||
@@ -1,25 +0,0 @@
|
|||||||
using Content.Server.StationEvents.Events;
|
|
||||||
|
|
||||||
namespace Content.Server.StationEvents.Components;
|
|
||||||
|
|
||||||
[RegisterComponent, Access(typeof(DiseaseOutbreakRule))]
|
|
||||||
public sealed class DiseaseOutbreakRuleComponent : Component
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Disease prototypes I decided were not too deadly for a random event
|
|
||||||
/// </summary>
|
|
||||||
/// <remarks>
|
|
||||||
/// Fire name
|
|
||||||
/// </remarks>
|
|
||||||
[DataField("notTooSeriousDiseases")]
|
|
||||||
public readonly IReadOnlyList<string> NotTooSeriousDiseases = new[]
|
|
||||||
{
|
|
||||||
"SpaceCold",
|
|
||||||
"VanAusdallsRobovirus",
|
|
||||||
"VentCough",
|
|
||||||
"AMIV",
|
|
||||||
"SpaceFlu",
|
|
||||||
"BirdFlew",
|
|
||||||
"TongueTwister"
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,59 +0,0 @@
|
|||||||
using Content.Server.Disease;
|
|
||||||
using Content.Server.Disease.Components;
|
|
||||||
using Content.Server.GameTicking.Rules.Components;
|
|
||||||
using Content.Server.StationEvents.Components;
|
|
||||||
using Content.Shared.Disease;
|
|
||||||
using Content.Shared.Mobs.Components;
|
|
||||||
using Content.Shared.Mobs.Systems;
|
|
||||||
using Robust.Shared.Random;
|
|
||||||
|
|
||||||
namespace Content.Server.StationEvents.Events;
|
|
||||||
/// <summary>
|
|
||||||
/// Infects a couple people
|
|
||||||
/// with a random disease that isn't super deadly
|
|
||||||
/// </summary>
|
|
||||||
public sealed class DiseaseOutbreakRule : StationEventSystem<DiseaseOutbreakRuleComponent>
|
|
||||||
{
|
|
||||||
[Dependency] private readonly DiseaseSystem _diseaseSystem = default!;
|
|
||||||
[Dependency] private readonly MobStateSystem _mobStateSystem = default!;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Finds 2-5 random, alive entities that can host diseases
|
|
||||||
/// and gives them a randomly selected disease.
|
|
||||||
/// They all get the same disease.
|
|
||||||
/// </summary>
|
|
||||||
protected override void Started(EntityUid uid, DiseaseOutbreakRuleComponent component, GameRuleComponent gameRule, GameRuleStartedEvent args)
|
|
||||||
{
|
|
||||||
base.Started(uid, component, gameRule, args);
|
|
||||||
|
|
||||||
HashSet<EntityUid> stationsToNotify = new();
|
|
||||||
List<DiseaseCarrierComponent> aliveList = new();
|
|
||||||
foreach (var (carrier, mobState) in EntityQuery<DiseaseCarrierComponent, MobStateComponent>())
|
|
||||||
{
|
|
||||||
if (!_mobStateSystem.IsDead(mobState.Owner, mobState))
|
|
||||||
aliveList.Add(carrier);
|
|
||||||
}
|
|
||||||
RobustRandom.Shuffle(aliveList);
|
|
||||||
|
|
||||||
// We're going to filter the above out to only alive mobs. Might change after future mobstate rework
|
|
||||||
var toInfect = RobustRandom.Next(2, 5);
|
|
||||||
|
|
||||||
var diseaseName = RobustRandom.Pick(component.NotTooSeriousDiseases);
|
|
||||||
|
|
||||||
if (!PrototypeManager.TryIndex(diseaseName, out DiseasePrototype? disease))
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Now we give it to people in the list of living disease carriers earlier
|
|
||||||
foreach (var target in aliveList)
|
|
||||||
{
|
|
||||||
if (toInfect-- == 0)
|
|
||||||
break;
|
|
||||||
|
|
||||||
_diseaseSystem.TryAddDisease(target.Owner, disease, target);
|
|
||||||
|
|
||||||
var station = StationSystem.GetOwningStation(target.Owner);
|
|
||||||
if(station == null) continue;
|
|
||||||
stationsToNotify.Add((EntityUid) station);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
using Content.Shared.Chat.Prototypes;
|
|
||||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
|
||||||
|
|
||||||
namespace Content.Server.Traits.Assorted;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This is used for the occasional sneeze or cough.
|
|
||||||
/// </summary>
|
|
||||||
[RegisterComponent]
|
|
||||||
public sealed class UncontrollableSnoughComponent : Component
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Emote to play when snoughing
|
|
||||||
/// </summary>
|
|
||||||
[DataField("emote", required: true, customTypeSerializer: typeof(PrototypeIdSerializer<EmotePrototype>))]
|
|
||||||
public string EmoteId = String.Empty;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The random time between incidents, (min, max).
|
|
||||||
/// </summary>
|
|
||||||
[DataField("timeBetweenIncidents", required: true)]
|
|
||||||
public Vector2 TimeBetweenIncidents { get; }
|
|
||||||
|
|
||||||
public float NextIncidentTime;
|
|
||||||
}
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
using Content.Server.Disease;
|
|
||||||
using Robust.Shared.Random;
|
|
||||||
|
|
||||||
namespace Content.Server.Traits.Assorted;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This handles making people randomly cough/sneeze without a disease.
|
|
||||||
/// </summary>
|
|
||||||
public sealed class UncontrollableSnoughSystem : EntitySystem
|
|
||||||
{
|
|
||||||
[Dependency] private readonly IRobustRandom _random = default!;
|
|
||||||
[Dependency] private readonly DiseaseSystem _diseaseSystem = default!;
|
|
||||||
|
|
||||||
/// <inheritdoc/>
|
|
||||||
public override void Initialize()
|
|
||||||
{
|
|
||||||
SubscribeLocalEvent<UncontrollableSnoughComponent, ComponentStartup>(SetupSnough);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void SetupSnough(EntityUid uid, UncontrollableSnoughComponent component, ComponentStartup args)
|
|
||||||
{
|
|
||||||
component.NextIncidentTime =
|
|
||||||
_random.NextFloat(component.TimeBetweenIncidents.X, component.TimeBetweenIncidents.Y);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Update(float frameTime)
|
|
||||||
{
|
|
||||||
base.Update(frameTime);
|
|
||||||
|
|
||||||
var query = EntityQueryEnumerator<UncontrollableSnoughComponent>();
|
|
||||||
while (query.MoveNext(out var ent, out var snough))
|
|
||||||
{
|
|
||||||
snough.NextIncidentTime -= frameTime;
|
|
||||||
|
|
||||||
if (snough.NextIncidentTime >= 0)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// Set the new time.
|
|
||||||
snough.NextIncidentTime +=
|
|
||||||
_random.NextFloat(snough.TimeBetweenIncidents.X, snough.TimeBetweenIncidents.Y);
|
|
||||||
|
|
||||||
_diseaseSystem.SneezeCough(ent, null, snough.EmoteId, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
using Content.Shared.Disease;
|
|
||||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.List;
|
|
||||||
|
|
||||||
namespace Content.Server.Xenoarchaeology.XenoArtifacts.Effects.Components;
|
|
||||||
/// <summary>
|
|
||||||
/// Spawn a random disease at regular intervals when artifact activated.
|
|
||||||
/// </summary>
|
|
||||||
[RegisterComponent]
|
|
||||||
public sealed class DiseaseArtifactComponent : Component
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// The diseases that the artifact can use.
|
|
||||||
/// </summary>
|
|
||||||
[DataField("diseasePrototype", customTypeSerializer: typeof(PrototypeIdListSerializer<DiseasePrototype>))]
|
|
||||||
public List<string> DiseasePrototypes = new();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Disease the artifact will spawn
|
|
||||||
/// Picks a random one from its list
|
|
||||||
/// </summary>
|
|
||||||
[ViewVariables(VVAccess.ReadWrite)]
|
|
||||||
public DiseasePrototype? SpawnDisease;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// How far away it will check for people
|
|
||||||
/// If empty, picks a random one from its list
|
|
||||||
/// </summary>
|
|
||||||
[DataField("range"), ViewVariables(VVAccess.ReadWrite)]
|
|
||||||
public float Range = 5f;
|
|
||||||
}
|
|
||||||
@@ -1,70 +0,0 @@
|
|||||||
using System.Linq;
|
|
||||||
using Content.Server.Xenoarchaeology.XenoArtifacts.Events;
|
|
||||||
using Content.Server.Xenoarchaeology.XenoArtifacts.Effects.Components;
|
|
||||||
using Content.Shared.Disease;
|
|
||||||
using Content.Server.Disease;
|
|
||||||
using Content.Server.Disease.Components;
|
|
||||||
using Robust.Shared.Prototypes;
|
|
||||||
using Content.Shared.Interaction;
|
|
||||||
|
|
||||||
namespace Content.Server.Xenoarchaeology.XenoArtifacts.Effects.Systems
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Handles disease-producing artifacts
|
|
||||||
/// </summary>
|
|
||||||
public sealed class DiseaseArtifactSystem : EntitySystem
|
|
||||||
{
|
|
||||||
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
|
||||||
[Dependency] private readonly DiseaseSystem _disease = default!;
|
|
||||||
[Dependency] private readonly EntityLookupSystem _lookup = default!;
|
|
||||||
[Dependency] private readonly SharedInteractionSystem _interactionSystem = default!;
|
|
||||||
|
|
||||||
public override void Initialize()
|
|
||||||
{
|
|
||||||
base.Initialize();
|
|
||||||
SubscribeLocalEvent<DiseaseArtifactComponent, ArtifactNodeEnteredEvent>(OnNodeEntered);
|
|
||||||
SubscribeLocalEvent<DiseaseArtifactComponent, ArtifactActivatedEvent>(OnActivate);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Makes sure this artifact is assigned a disease
|
|
||||||
/// </summary>
|
|
||||||
private void OnNodeEntered(EntityUid uid, DiseaseArtifactComponent component, ArtifactNodeEnteredEvent args)
|
|
||||||
{
|
|
||||||
if (component.SpawnDisease != null || !component.DiseasePrototypes.Any())
|
|
||||||
return;
|
|
||||||
var diseaseName = component.DiseasePrototypes[args.RandomSeed % component.DiseasePrototypes.Count];
|
|
||||||
|
|
||||||
if (!_prototypeManager.TryIndex<DiseasePrototype>(diseaseName, out var disease))
|
|
||||||
{
|
|
||||||
Logger.ErrorS("disease", $"Invalid disease {diseaseName} selected from random diseases.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
component.SpawnDisease = disease;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// When activated, blasts everyone in LOS within n tiles
|
|
||||||
/// with a high-probability disease infection attempt
|
|
||||||
/// </summary>
|
|
||||||
private void OnActivate(EntityUid uid, DiseaseArtifactComponent component, ArtifactActivatedEvent args)
|
|
||||||
{
|
|
||||||
if (component.SpawnDisease == null) return;
|
|
||||||
|
|
||||||
var xform = Transform(uid);
|
|
||||||
var carrierQuery = GetEntityQuery<DiseaseCarrierComponent>();
|
|
||||||
|
|
||||||
foreach (var entity in _lookup.GetEntitiesInRange(xform.Coordinates, component.Range))
|
|
||||||
{
|
|
||||||
if (!carrierQuery.TryGetComponent(entity, out var carrier)) continue;
|
|
||||||
|
|
||||||
if (!_interactionSystem.InRangeUnobstructed(uid, entity, component.Range))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
_disease.TryInfect(carrier, component.SpawnDisease, forced: true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
23
Content.Server/Zombies/PendingZombieComponent.cs
Normal file
23
Content.Server/Zombies/PendingZombieComponent.cs
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
using Content.Shared.Damage;
|
||||||
|
using Content.Shared.FixedPoint;
|
||||||
|
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;
|
||||||
|
|
||||||
|
namespace Content.Server.Zombies;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Temporary because diseases suck.
|
||||||
|
/// </summary>
|
||||||
|
[RegisterComponent]
|
||||||
|
public sealed class PendingZombieComponent : Component
|
||||||
|
{
|
||||||
|
[DataField("damage")] public DamageSpecifier Damage = new()
|
||||||
|
{
|
||||||
|
DamageDict = new Dictionary<string, FixedPoint2>()
|
||||||
|
{
|
||||||
|
{ "Blunt", FixedPoint2.New(1) }
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
[DataField("nextTick", customTypeSerializer:typeof(TimeOffsetSerializer))]
|
||||||
|
public TimeSpan NextTick;
|
||||||
|
}
|
||||||
@@ -3,8 +3,6 @@ using Content.Server.Body.Systems;
|
|||||||
using Content.Server.Chat;
|
using Content.Server.Chat;
|
||||||
using Content.Server.Chat.Systems;
|
using Content.Server.Chat.Systems;
|
||||||
using Content.Server.Cloning;
|
using Content.Server.Cloning;
|
||||||
using Content.Server.Disease;
|
|
||||||
using Content.Server.Disease.Components;
|
|
||||||
using Content.Server.Drone.Components;
|
using Content.Server.Drone.Components;
|
||||||
using Content.Server.Humanoid;
|
using Content.Server.Humanoid;
|
||||||
using Content.Server.Inventory;
|
using Content.Server.Inventory;
|
||||||
@@ -12,7 +10,7 @@ using Content.Shared.Bed.Sleep;
|
|||||||
using Content.Shared.Chemistry.Components;
|
using Content.Shared.Chemistry.Components;
|
||||||
using Content.Server.Emoting.Systems;
|
using Content.Server.Emoting.Systems;
|
||||||
using Content.Server.Speech.EntitySystems;
|
using Content.Server.Speech.EntitySystems;
|
||||||
using Content.Shared.Disease.Events;
|
using Content.Shared.Damage;
|
||||||
using Content.Shared.Inventory;
|
using Content.Shared.Inventory;
|
||||||
using Content.Shared.Mobs;
|
using Content.Shared.Mobs;
|
||||||
using Content.Shared.Mobs.Components;
|
using Content.Shared.Mobs.Components;
|
||||||
@@ -26,16 +24,16 @@ namespace Content.Server.Zombies
|
|||||||
{
|
{
|
||||||
public sealed class ZombieSystem : SharedZombieSystem
|
public sealed class ZombieSystem : SharedZombieSystem
|
||||||
{
|
{
|
||||||
[Dependency] private readonly DiseaseSystem _disease = default!;
|
[Dependency] private readonly IGameTiming _timing = default!;
|
||||||
|
[Dependency] private readonly IPrototypeManager _protoManager = default!;
|
||||||
|
[Dependency] private readonly IRobustRandom _random = default!;
|
||||||
[Dependency] private readonly BloodstreamSystem _bloodstream = default!;
|
[Dependency] private readonly BloodstreamSystem _bloodstream = default!;
|
||||||
|
[Dependency] private readonly DamageableSystem _damageable = default!;
|
||||||
[Dependency] private readonly ZombifyOnDeathSystem _zombify = default!;
|
[Dependency] private readonly ZombifyOnDeathSystem _zombify = default!;
|
||||||
[Dependency] private readonly ServerInventorySystem _inv = default!;
|
[Dependency] private readonly ServerInventorySystem _inv = default!;
|
||||||
[Dependency] private readonly ChatSystem _chat = default!;
|
[Dependency] private readonly ChatSystem _chat = default!;
|
||||||
[Dependency] private readonly AutoEmoteSystem _autoEmote = default!;
|
[Dependency] private readonly AutoEmoteSystem _autoEmote = default!;
|
||||||
[Dependency] private readonly EmoteOnDamageSystem _emoteOnDamage = default!;
|
[Dependency] private readonly EmoteOnDamageSystem _emoteOnDamage = default!;
|
||||||
[Dependency] private readonly IGameTiming _gameTiming = default!;
|
|
||||||
[Dependency] private readonly IPrototypeManager _protoManager = default!;
|
|
||||||
[Dependency] private readonly IRobustRandom _robustRandom = default!;
|
|
||||||
[Dependency] private readonly HumanoidAppearanceSystem _humanoidSystem = default!;
|
[Dependency] private readonly HumanoidAppearanceSystem _humanoidSystem = default!;
|
||||||
|
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
@@ -49,8 +47,30 @@ namespace Content.Server.Zombies
|
|||||||
SubscribeLocalEvent<ZombieComponent, MeleeHitEvent>(OnMeleeHit);
|
SubscribeLocalEvent<ZombieComponent, MeleeHitEvent>(OnMeleeHit);
|
||||||
SubscribeLocalEvent<ZombieComponent, MobStateChangedEvent>(OnMobState);
|
SubscribeLocalEvent<ZombieComponent, MobStateChangedEvent>(OnMobState);
|
||||||
SubscribeLocalEvent<ZombieComponent, CloningEvent>(OnZombieCloning);
|
SubscribeLocalEvent<ZombieComponent, CloningEvent>(OnZombieCloning);
|
||||||
SubscribeLocalEvent<ZombieComponent, AttemptSneezeCoughEvent>(OnSneeze);
|
|
||||||
SubscribeLocalEvent<ZombieComponent, TryingToSleepEvent>(OnSleepAttempt);
|
SubscribeLocalEvent<ZombieComponent, TryingToSleepEvent>(OnSleepAttempt);
|
||||||
|
|
||||||
|
SubscribeLocalEvent<PendingZombieComponent, MapInitEvent>(OnPendingMapInit);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnPendingMapInit(EntityUid uid, PendingZombieComponent component, MapInitEvent args)
|
||||||
|
{
|
||||||
|
component.NextTick = _timing.CurTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Update(float frameTime)
|
||||||
|
{
|
||||||
|
base.Update(frameTime);
|
||||||
|
var query = EntityQueryEnumerator<PendingZombieComponent>();
|
||||||
|
var curTime = _timing.CurTime;
|
||||||
|
|
||||||
|
while (query.MoveNext(out var uid, out var comp))
|
||||||
|
{
|
||||||
|
if (comp.NextTick < curTime)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
comp.NextTick += TimeSpan.FromSeconds(1);
|
||||||
|
_damageable.TryChangeDamage(uid, comp.Damage, true, false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnSleepAttempt(EntityUid uid, ZombieComponent component, ref TryingToSleepEvent args)
|
private void OnSleepAttempt(EntityUid uid, ZombieComponent component, ref TryingToSleepEvent args)
|
||||||
@@ -95,11 +115,6 @@ namespace Content.Server.Zombies
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnSneeze(EntityUid uid, ZombieComponent component, ref AttemptSneezeCoughEvent args)
|
|
||||||
{
|
|
||||||
args.Cancelled = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private float GetZombieInfectionChance(EntityUid uid, ZombieComponent component)
|
private float GetZombieInfectionChance(EntityUid uid, ZombieComponent component)
|
||||||
{
|
{
|
||||||
var baseChance = component.MaxZombieInfectionChance;
|
var baseChance = component.MaxZombieInfectionChance;
|
||||||
@@ -151,8 +166,11 @@ namespace Content.Server.Zombies
|
|||||||
if (!TryComp<MobStateComponent>(entity, out var mobState) || HasComp<DroneComponent>(entity))
|
if (!TryComp<MobStateComponent>(entity, out var mobState) || HasComp<DroneComponent>(entity))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (HasComp<DiseaseCarrierComponent>(entity) && _robustRandom.Prob(GetZombieInfectionChance(entity, component)))
|
if (_random.Prob(GetZombieInfectionChance(entity, component)))
|
||||||
_disease.TryAddDisease(entity, "ActiveZombieVirus");
|
{
|
||||||
|
EnsureComp<PendingZombieComponent>(entity);
|
||||||
|
EnsureComp<ZombifyOnDeathComponent>(entity);
|
||||||
|
}
|
||||||
|
|
||||||
if (HasComp<ZombieComponent>(entity))
|
if (HasComp<ZombieComponent>(entity))
|
||||||
args.BonusDamage = -args.BaseDamage * zombieComp.OtherZombieDamageCoefficient;
|
args.BonusDamage = -args.BaseDamage * zombieComp.OtherZombieDamageCoefficient;
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ using Content.Server.Body.Systems;
|
|||||||
using Content.Server.Chat;
|
using Content.Server.Chat;
|
||||||
using Content.Server.Chat.Managers;
|
using Content.Server.Chat.Managers;
|
||||||
using Content.Server.Chat.Systems;
|
using Content.Server.Chat.Systems;
|
||||||
using Content.Server.Disease.Components;
|
|
||||||
using Content.Server.Ghost.Roles.Components;
|
using Content.Server.Ghost.Roles.Components;
|
||||||
using Content.Server.Humanoid;
|
using Content.Server.Humanoid;
|
||||||
using Content.Server.IdentityManagement;
|
using Content.Server.IdentityManagement;
|
||||||
@@ -101,7 +100,6 @@ namespace Content.Server.Zombies
|
|||||||
|
|
||||||
//we need to basically remove all of these because zombies shouldn't
|
//we need to basically remove all of these because zombies shouldn't
|
||||||
//get diseases, breath, be thirst, be hungry, or die in space
|
//get diseases, breath, be thirst, be hungry, or die in space
|
||||||
RemComp<DiseaseCarrierComponent>(target);
|
|
||||||
RemComp<RespiratorComponent>(target);
|
RemComp<RespiratorComponent>(target);
|
||||||
RemComp<BarotraumaComponent>(target);
|
RemComp<BarotraumaComponent>(target);
|
||||||
RemComp<HungerComponent>(target);
|
RemComp<HungerComponent>(target);
|
||||||
|
|||||||
@@ -1,5 +0,0 @@
|
|||||||
namespace Content.Shared.Atmos.Miasma;
|
|
||||||
public abstract class SharedFliesComponent : Component
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
using JetBrains.Annotations;
|
|
||||||
|
|
||||||
namespace Content.Shared.Disease
|
|
||||||
{
|
|
||||||
[ImplicitDataDefinitionForInheritors]
|
|
||||||
[MeansImplicitUse]
|
|
||||||
public abstract class DiseaseCure
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// This returns true if the disease should be cured
|
|
||||||
/// and false otherwise
|
|
||||||
/// </summary>
|
|
||||||
public abstract bool Cure(DiseaseEffectArgs args);
|
|
||||||
/// <summary>
|
|
||||||
/// What stages the cure applies to.
|
|
||||||
/// probably should be all, but go wild
|
|
||||||
/// </summary>
|
|
||||||
[DataField("stages")]
|
|
||||||
public readonly int[] Stages = { 0 };
|
|
||||||
/// <summary>
|
|
||||||
/// This is used by the disease diangoser machine
|
|
||||||
/// to generate reports to tell people all of a disease's
|
|
||||||
/// special cures using in-game methods.
|
|
||||||
/// So it should return a localization string describing
|
|
||||||
/// the cure
|
|
||||||
/// </summary>
|
|
||||||
public abstract string CureText();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
using JetBrains.Annotations;
|
|
||||||
|
|
||||||
namespace Content.Shared.Disease
|
|
||||||
{
|
|
||||||
[ImplicitDataDefinitionForInheritors]
|
|
||||||
[MeansImplicitUse]
|
|
||||||
public abstract class DiseaseEffect
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// What's the chance, from 0 to 1, that this effect will occur?
|
|
||||||
/// </summary>
|
|
||||||
[DataField("probability")]
|
|
||||||
public float Probability = 1.0f;
|
|
||||||
/// <summary>
|
|
||||||
/// What stages this effect triggers on
|
|
||||||
/// </summary>
|
|
||||||
[DataField("stages")]
|
|
||||||
public readonly int[] Stages = { 0 };
|
|
||||||
/// <summary>
|
|
||||||
/// What effect the disease will have.
|
|
||||||
/// </summary>
|
|
||||||
public abstract void Effect(DiseaseEffectArgs args);
|
|
||||||
}
|
|
||||||
/// <summary>
|
|
||||||
/// What you have to work with in any disease effect/cure.
|
|
||||||
/// Includes an entity manager because it is out of scope
|
|
||||||
/// otherwise.
|
|
||||||
/// </summary>
|
|
||||||
public readonly record struct DiseaseEffectArgs(
|
|
||||||
EntityUid DiseasedEntity,
|
|
||||||
DiseasePrototype Disease,
|
|
||||||
IEntityManager EntityManager
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
using Robust.Shared.Serialization;
|
|
||||||
|
|
||||||
namespace Content.Shared.Disease
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Stores bools for if the machine is on
|
|
||||||
/// and if it's currently running.
|
|
||||||
/// Used for the visualizer
|
|
||||||
/// </summary>
|
|
||||||
[Serializable, NetSerializable]
|
|
||||||
public enum DiseaseMachineVisuals : byte
|
|
||||||
{
|
|
||||||
IsOn,
|
|
||||||
IsRunning
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,83 +0,0 @@
|
|||||||
using Robust.Shared.Prototypes;
|
|
||||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.Array;
|
|
||||||
|
|
||||||
namespace Content.Shared.Disease
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Diseases encompass everything from viruses to cancers to heart disease.
|
|
||||||
/// It's not just a virology thing.
|
|
||||||
/// </summary>
|
|
||||||
[Prototype("disease")]
|
|
||||||
[DataDefinition]
|
|
||||||
public sealed class DiseasePrototype : IPrototype, IInheritingPrototype
|
|
||||||
{
|
|
||||||
[ViewVariables]
|
|
||||||
[IdDataField]
|
|
||||||
public string ID { get; } = default!;
|
|
||||||
|
|
||||||
[DataField("name")]
|
|
||||||
public string Name { get; private set; } = string.Empty;
|
|
||||||
|
|
||||||
[ParentDataFieldAttribute(typeof(AbstractPrototypeIdArraySerializer<DiseasePrototype>))]
|
|
||||||
public string[]? Parents { get; private set; }
|
|
||||||
|
|
||||||
[NeverPushInheritance]
|
|
||||||
[AbstractDataFieldAttribute]
|
|
||||||
public bool Abstract { get; private set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Controls how often a disease ticks.
|
|
||||||
/// </summary>
|
|
||||||
[ViewVariables]
|
|
||||||
public float TickTime = 1f;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Since disease isn't mapped to metabolism or anything,
|
|
||||||
/// it needs something to control its tickrate
|
|
||||||
/// </summary>
|
|
||||||
public float Accumulator = 0f;
|
|
||||||
/// <summary>
|
|
||||||
/// Since accumulator is reset with TickTime, this just tracks
|
|
||||||
/// the total amount of time a disease has been present.
|
|
||||||
/// </summary>
|
|
||||||
public float TotalAccumulator = 0f;
|
|
||||||
/// <summary>
|
|
||||||
/// Stores all the separate stages of the disease plus the time
|
|
||||||
/// thresholds for their activation
|
|
||||||
/// int: the disease stage (0 for baseline, 1, 2, etc.)
|
|
||||||
/// float: the time it takes for the stage to begin.
|
|
||||||
/// </summary>
|
|
||||||
[DataField("stages", serverOnly: true)]
|
|
||||||
public readonly List<float> Stages = new() { 0f };
|
|
||||||
/// <summary>
|
|
||||||
/// List of effects the disease has that will
|
|
||||||
/// run every second (by default anyway)
|
|
||||||
/// </summary>
|
|
||||||
[DataField("effects", serverOnly: true)]
|
|
||||||
public readonly List<DiseaseEffect> Effects = new(0);
|
|
||||||
/// <summary>
|
|
||||||
/// List of SPECIFIC CURES the disease has that will
|
|
||||||
/// be checked every second.
|
|
||||||
/// Stuff like spaceacillin operates outside this.
|
|
||||||
/// </summary>
|
|
||||||
[DataField("cures", serverOnly: true)]
|
|
||||||
public readonly List<DiseaseCure> Cures = new(0);
|
|
||||||
/// <summary>
|
|
||||||
/// This flatly reduces the probabilty disease medicine
|
|
||||||
/// has to cure it every tick. Although, since spaceacillin is
|
|
||||||
/// used as a reference and it has 0.15 chance, this is
|
|
||||||
/// a base 33% reduction in cure chance
|
|
||||||
/// </summary>
|
|
||||||
[DataField("cureResist", serverOnly: true)]
|
|
||||||
public float CureResist = 0.05f;
|
|
||||||
/// <summary>
|
|
||||||
/// Whether the disease can infect other people.
|
|
||||||
/// Since this isn't just a virology thing, this
|
|
||||||
/// primary determines what sort of disease it is.
|
|
||||||
/// This also affects things like the vaccine machine.
|
|
||||||
/// You can't print a cancer vaccine
|
|
||||||
/// </summary>
|
|
||||||
[DataField("infectious", serverOnly: true)]
|
|
||||||
public bool Infectious = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
using Robust.Shared.GameStates;
|
|
||||||
|
|
||||||
namespace Content.Shared.Disease.Components
|
|
||||||
{
|
|
||||||
/// This is added to anyone with at least 1 disease
|
|
||||||
/// and helps cull event subscriptions and entity queries
|
|
||||||
/// when they are not relevant.
|
|
||||||
[NetworkedComponent]
|
|
||||||
[RegisterComponent]
|
|
||||||
public sealed class DiseasedComponent : Component
|
|
||||||
{}
|
|
||||||
}
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
namespace Content.Shared.Disease.Events;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Raised by an entity about to sneeze/cough.
|
|
||||||
/// Set Cancelled to true on event handling to suppress the sneeze
|
|
||||||
/// </summary>
|
|
||||||
[ByRefEvent]
|
|
||||||
public record struct AttemptSneezeCoughEvent(EntityUid Uid, string? EmoteId, bool Cancelled = false);
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
using Content.Shared.DoAfter;
|
|
||||||
using Robust.Shared.Serialization;
|
|
||||||
|
|
||||||
namespace Content.Shared.Disease.Events;
|
|
||||||
|
|
||||||
[Serializable, NetSerializable]
|
|
||||||
public sealed class VaccineDoAfterEvent : SimpleDoAfterEvent
|
|
||||||
{
|
|
||||||
}
|
|
||||||
@@ -1,6 +1,4 @@
|
|||||||
using Content.Shared.Bed.Sleep;
|
using Content.Shared.Bed.Sleep;
|
||||||
using Content.Shared.Disease.Events;
|
|
||||||
using Content.Shared.DragDrop;
|
|
||||||
using Content.Shared.Emoting;
|
using Content.Shared.Emoting;
|
||||||
using Content.Shared.Hands;
|
using Content.Shared.Hands;
|
||||||
using Content.Shared.Interaction.Events;
|
using Content.Shared.Interaction.Events;
|
||||||
@@ -38,7 +36,6 @@ public partial class MobStateSystem
|
|||||||
SubscribeLocalEvent<MobStateComponent, UpdateCanMoveEvent>(CheckAct);
|
SubscribeLocalEvent<MobStateComponent, UpdateCanMoveEvent>(CheckAct);
|
||||||
SubscribeLocalEvent<MobStateComponent, StandAttemptEvent>(CheckAct);
|
SubscribeLocalEvent<MobStateComponent, StandAttemptEvent>(CheckAct);
|
||||||
SubscribeLocalEvent<MobStateComponent, TryingToSleepEvent>(OnSleepAttempt);
|
SubscribeLocalEvent<MobStateComponent, TryingToSleepEvent>(OnSleepAttempt);
|
||||||
SubscribeLocalEvent<MobStateComponent, AttemptSneezeCoughEvent>(OnSneezeAttempt);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnStateExitSubscribers(EntityUid target, MobStateComponent component, MobState state)
|
private void OnStateExitSubscribers(EntityUid target, MobStateComponent component, MobState state)
|
||||||
@@ -108,12 +105,6 @@ public partial class MobStateSystem
|
|||||||
args.Cancelled = true;
|
args.Cancelled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnSneezeAttempt(EntityUid target, MobStateComponent component, ref AttemptSneezeCoughEvent args)
|
|
||||||
{
|
|
||||||
if (IsDead(target, component))
|
|
||||||
args.Cancelled = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnGettingStripped(EntityUid target, MobStateComponent component, BeforeGettingStrippedEvent args)
|
private void OnGettingStripped(EntityUid target, MobStateComponent component, BeforeGettingStrippedEvent args)
|
||||||
{
|
{
|
||||||
// Incapacitated or dead targets get stripped two or three times as fast. Makes stripping corpses less tedious.
|
// Incapacitated or dead targets get stripped two or three times as fast. Makes stripping corpses less tedious.
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
using Content.Shared.Disease;
|
|
||||||
using Content.Shared.FixedPoint;
|
using Content.Shared.FixedPoint;
|
||||||
using Content.Shared.Store;
|
using Content.Shared.Store;
|
||||||
using Robust.Shared.GameStates;
|
using Robust.Shared.GameStates;
|
||||||
@@ -153,12 +152,6 @@ public sealed class RevenantComponent : Component
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
[ViewVariables(VVAccess.ReadWrite), DataField("blightRadius")]
|
[ViewVariables(VVAccess.ReadWrite), DataField("blightRadius")]
|
||||||
public float BlightRadius = 3.5f;
|
public float BlightRadius = 3.5f;
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The disease that is given to the victims of the ability.
|
|
||||||
/// </summary>
|
|
||||||
[ViewVariables(VVAccess.ReadWrite), DataField("blightDiseasePrototypeId", customTypeSerializer: typeof(PrototypeIdSerializer<DiseasePrototype>))]
|
|
||||||
public string BlightDiseasePrototypeId = "SpectralTiredness";
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Malfunction Ability
|
#region Malfunction Ability
|
||||||
|
|||||||
@@ -3,11 +3,6 @@ using Robust.Shared.Serialization;
|
|||||||
|
|
||||||
namespace Content.Shared.Swab;
|
namespace Content.Shared.Swab;
|
||||||
|
|
||||||
[Serializable, NetSerializable]
|
|
||||||
public sealed class DiseaseSwabDoAfterEvent : SimpleDoAfterEvent
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
[Serializable, NetSerializable]
|
[Serializable, NetSerializable]
|
||||||
public sealed class BotanySwabDoAfterEvent : SimpleDoAfterEvent
|
public sealed class BotanySwabDoAfterEvent : SimpleDoAfterEvent
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,20 +0,0 @@
|
|||||||
diagnoser-cant-use-swab = {CAPITALIZE(THE($machine))} rejects {THE($swab)}.
|
|
||||||
diagnoser-insert-swab = You insert {THE($swab)} into {THE($machine)}.
|
|
||||||
diagnoser-disease-report = Disease Report: {CAPITALIZE($disease)}
|
|
||||||
diagnoser-disease-report-none = Bill of Good Health
|
|
||||||
diagnoser-disease-report-none-contents = [color=green]No diseases were found in this sample.[/color]
|
|
||||||
diagnoser-disease-report-name = Disease Name: {CAPITALIZE($disease)}
|
|
||||||
diagnoser-disease-report-infectious = Infectious: [color=red]Yes[/color]
|
|
||||||
diagnoser-disease-report-not-infectious = Infectious: [color=green]No[/color]
|
|
||||||
diagnoser-disease-report-cureresist-none = Spaceacillin Resistance: [color=green]None[/color]
|
|
||||||
diagnoser-disease-report-cureresist-low = Spaceacillin Resistance: [color=yellow]Low[/color]
|
|
||||||
diagnoser-disease-report-cureresist-medium = Spaceacillin Resistance: [color=orange]Medium[/color]
|
|
||||||
diagnoser-disease-report-cureresist-high = Spaceacillin Resistance: [color=red]High[/color]
|
|
||||||
diagnoser-no-cures = The disease has no specific cures.
|
|
||||||
diagnoser-cure-has = The disease has the following cures:
|
|
||||||
diagnoser-cure-bedrest = Rest in bed for {$time} seconds, or {$sleep} seconds if sleeping.
|
|
||||||
diagnoser-cure-reagent = Consume at least {$units}u of {$reagent}.
|
|
||||||
diagnoser-cure-wait = It will go away on its own after {$time} seconds.
|
|
||||||
diagnoser-cure-temp = Reach a body temperature below {$max}°K or above {$min}°K.
|
|
||||||
diagnoser-cure-temp-min = Reach a body temperature above {$min}°K.
|
|
||||||
diagnoser-cure-temp-max = Reach a body temperature below {$max}°K.
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
# Noninfectious
|
|
||||||
disease-proto-ultragigacancer = ultragigacancer
|
|
||||||
disease-proto-spectral-tiredness = spectral tiredness
|
|
||||||
disease-proto-lung-cancer = Stage IIIA Lung Cancer
|
|
||||||
|
|
||||||
# Infectious
|
|
||||||
disease-proto-space-cold = space cold
|
|
||||||
disease-proto-vent-cough = vent cough
|
|
||||||
disease-proto-space-flu = space flu
|
|
||||||
disease-proto-bird-flew = bird flew
|
|
||||||
disease-proto-robovirus = Van Ausdall's Robovirus
|
|
||||||
disease-proto-amiv = AMIV
|
|
||||||
disease-proto-amirmir = Memetic Amirmir
|
|
||||||
disease-proto-bleeders = Bleeder's Bite
|
|
||||||
disease-proto-plague = plague
|
|
||||||
disease-proto-owonavirus = OwOnavirus
|
|
||||||
disease-proto-tongue-twister = Tongue Twister
|
|
||||||
|
|
||||||
# Zombie
|
|
||||||
disease-proto-zombie = Zombie Virus
|
|
||||||
disease-proto-zombie-passive = Zombie Virus
|
|
||||||
@@ -1,8 +1 @@
|
|||||||
disease-cured = You feel a bit better.
|
disease-vomit = {CAPITALIZE(THE($person))} vomits.
|
||||||
disease-sick-generic = You feel sick.
|
|
||||||
disease-eaten-inside = You feel like you're being eaten from the inside.
|
|
||||||
disease-banana-compulsion = You really want to eat some bananas.
|
|
||||||
disease-beat-chest-compulsion = {CAPITALIZE(THE($person))} beats {POSS-ADJ($person)} chest.
|
|
||||||
disease-vomit = {CAPITALIZE(THE($person))} vomits.
|
|
||||||
disease-think = You feel like you can't think straight.
|
|
||||||
disease-polymorph = You feel your body twist and change form!
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
miasma-smell = Something smells foul!
|
|
||||||
miasma-rotting = [color=orange]It's rotting![/color]
|
|
||||||
miasma-bloated = [color=orangered]It's bloated![/color]
|
|
||||||
miasma-extremely-bloated = [color=red]It's extremely bloated![/color]
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
disease-scanner-diseased = DISEASED
|
|
||||||
disease-scanner-not-diseased = No diseases
|
|
||||||
disease-scanner-gave-other = You gave {THE($target)} {CAPITALIZE($disease)}!
|
|
||||||
disease-scanner-gave-self = You gave yourself {CAPITALIZE($disease)}! Congratulations!
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
swab-already-used = You already used this swab.
|
|
||||||
swab-swabbed = You swab {THE($target)}'s mouth.
|
|
||||||
swab-mask-blocked = {CAPITALIZE(THE($target))} needs to take off {THE($mask)}.
|
|
||||||
swab-used = It looks like it's been used.
|
|
||||||
swab-unused = It's clean and ready to use.
|
|
||||||
|
|
||||||
botany-swab-from = You carefully collect pollen from the plant.
|
|
||||||
botany-swab-to = You carefully dust pollen on the plant.
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
vaxx-already-used = You already used this vaccine.
|
|
||||||
vaxx-used = It's spent.
|
|
||||||
vaxx-unused = It hasn't been spent.
|
|
||||||
@@ -13,10 +13,10 @@ job-description-chaplain = Preach the good word of your deity and religion, and
|
|||||||
job-description-chef = Keep the station fed with a variety of food items, butcher dead animals to ensure miasma doesn't leak, and help keep the bar lively.
|
job-description-chef = Keep the station fed with a variety of food items, butcher dead animals to ensure miasma doesn't leak, and help keep the bar lively.
|
||||||
job-description-chemist = Produce medicinal drugs for the doctors to use, research ethically dubious rare chemicals, and produce weapons of war when enemies of the station arrive.
|
job-description-chemist = Produce medicinal drugs for the doctors to use, research ethically dubious rare chemicals, and produce weapons of war when enemies of the station arrive.
|
||||||
job-description-clown = Entertain the crew through elaborate slapstick routines or terrible jokes.
|
job-description-clown = Entertain the crew through elaborate slapstick routines or terrible jokes.
|
||||||
job-description-cmo = Manage the resources and personnel of the medical department to keep the crew alive and disease-free.
|
job-description-cmo = Manage the resources and personnel of the medical department to keep the crew alive.
|
||||||
job-description-paramedic = Rescue critically injured patients all over the station, sometimes outside too. Stablize them, give them a ride to medbay, and get back out there!
|
job-description-paramedic = Rescue critically injured patients all over the station, sometimes outside too. Stablize them, give them a ride to medbay, and get back out there!
|
||||||
job-description-detective = Investigate crime scenes using forensic tools, ensure that the guilty party is found, and have a couple smokes.
|
job-description-detective = Investigate crime scenes using forensic tools, ensure that the guilty party is found, and have a couple smokes.
|
||||||
job-description-doctor = Diagnose and heal crewmembers through medicinal chemicals, vaccinations, and disease cures, along with cloning the dead.
|
job-description-doctor = Diagnose and heal crewmembers through medicinal chemicals, vaccinations, along with cloning the dead.
|
||||||
job-description-engineer = Keep the station's main engine & solars active, optimize the power network, and make emergency repairs using your hardsuit.
|
job-description-engineer = Keep the station's main engine & solars active, optimize the power network, and make emergency repairs using your hardsuit.
|
||||||
job-description-ertengineer = Ensure that the station has power and clean air.
|
job-description-ertengineer = Ensure that the station has power and clean air.
|
||||||
job-description-ertjanitor = Ensure that the station is properly cleaned--for morale.
|
job-description-ertjanitor = Ensure that the station is properly cleaned--for morale.
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
station-event-disease-outbreak-announcement = Confirmed outbreak of level 7 biohazard aboard the station. All personnel must contain the outbreak.
|
|
||||||
@@ -6,9 +6,6 @@ trait-narcolepsy-decs = You fall asleep randomly
|
|||||||
|
|
||||||
trait-pacifist-name = Pacifist
|
trait-pacifist-name = Pacifist
|
||||||
|
|
||||||
trait-sneezing-name = Runny nose
|
|
||||||
trait-sneezing-desc = You sneeze and cough uncontrollably
|
|
||||||
|
|
||||||
permanent-blindness-trait-examined = [color=lightblue]{CAPITALIZE(POSS-ADJ($target))} eyes are glassy and unfocused. It doesn't seem like {SUBJECT($target)} can see you.[/color]
|
permanent-blindness-trait-examined = [color=lightblue]{CAPITALIZE(POSS-ADJ($target))} eyes are glassy and unfocused. It doesn't seem like {SUBJECT($target)} can see you.[/color]
|
||||||
|
|
||||||
trait-lightweight-name = Lightweight Drunk
|
trait-lightweight-name = Lightweight Drunk
|
||||||
|
|||||||
@@ -21,13 +21,13 @@
|
|||||||
serverEvent: !type:RevenantOverloadLightsActionEvent
|
serverEvent: !type:RevenantOverloadLightsActionEvent
|
||||||
useDelay: 20
|
useDelay: 20
|
||||||
|
|
||||||
- type: instantAction
|
#- type: instantAction
|
||||||
id: RevenantBlight
|
# id: RevenantBlight
|
||||||
icon: Interface/Actions/blight.png
|
# icon: Interface/Actions/blight.png
|
||||||
name: Blight
|
# name: Blight
|
||||||
description: Costs 50 Essence.
|
# description: Costs 50 Essence.
|
||||||
serverEvent: !type:RevenantBlightActionEvent
|
# serverEvent: !type:RevenantBlightActionEvent
|
||||||
useDelay: 20
|
# useDelay: 20
|
||||||
|
|
||||||
- type: instantAction
|
- type: instantAction
|
||||||
id: RevenantMalfunction
|
id: RevenantMalfunction
|
||||||
@@ -35,4 +35,4 @@
|
|||||||
name: Malfunction
|
name: Malfunction
|
||||||
description: Costs 60 Essence.
|
description: Costs 60 Essence.
|
||||||
serverEvent: !type:RevenantMalfunctionActionEvent
|
serverEvent: !type:RevenantMalfunctionActionEvent
|
||||||
useDelay: 20
|
useDelay: 20
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
name: Defile
|
name: Defile
|
||||||
description: Defiles the surrounding area, ripping up floors, damaging windows, opening containers, and throwing items. Using it leaves you vulnerable to attacks for a short period of time.
|
description: Defiles the surrounding area, ripping up floors, damaging windows, opening containers, and throwing items. Using it leaves you vulnerable to attacks for a short period of time.
|
||||||
productAction: RevenantDefile
|
productAction: RevenantDefile
|
||||||
cost:
|
cost:
|
||||||
StolenEssence: 10
|
StolenEssence: 10
|
||||||
categories:
|
categories:
|
||||||
- RevenantAbilities
|
- RevenantAbilities
|
||||||
@@ -16,7 +16,7 @@
|
|||||||
name: Overload Lights
|
name: Overload Lights
|
||||||
description: Overloads all nearby lights, causing lights to pulse and sending out dangerous lightning. Using it leaves you vulnerable to attacks for a long period of time.
|
description: Overloads all nearby lights, causing lights to pulse and sending out dangerous lightning. Using it leaves you vulnerable to attacks for a long period of time.
|
||||||
productAction: RevenantOverloadLights
|
productAction: RevenantOverloadLights
|
||||||
cost:
|
cost:
|
||||||
StolenEssence: 25
|
StolenEssence: 25
|
||||||
categories:
|
categories:
|
||||||
- RevenantAbilities
|
- RevenantAbilities
|
||||||
@@ -24,25 +24,25 @@
|
|||||||
- !type:ListingLimitedStockCondition
|
- !type:ListingLimitedStockCondition
|
||||||
stock: 1
|
stock: 1
|
||||||
|
|
||||||
- type: listing
|
#- type: listing
|
||||||
id: RevenantBlight
|
# id: RevenantBlight
|
||||||
name: Blight
|
# name: Blight
|
||||||
description: Infects all nearby organisms with an infectious disease that causes toxic buildup and tiredness. Using it leaves you vulnerable to attacks for a medium period of time.
|
# description: Infects all nearby organisms with an infectious disease that causes toxic buildup and tiredness. Using it leaves you vulnerable to attacks for a medium period of time.
|
||||||
productAction: RevenantBlight
|
# productAction: RevenantBlight
|
||||||
cost:
|
# cost:
|
||||||
StolenEssence: 75
|
# StolenEssence: 75
|
||||||
categories:
|
# categories:
|
||||||
- RevenantAbilities
|
# - RevenantAbilities
|
||||||
conditions:
|
# conditions:
|
||||||
- !type:ListingLimitedStockCondition
|
# - !type:ListingLimitedStockCondition
|
||||||
stock: 1
|
# stock: 1
|
||||||
|
|
||||||
- type: listing
|
- type: listing
|
||||||
id: RevenantMalfunction
|
id: RevenantMalfunction
|
||||||
name: Malfunction
|
name: Malfunction
|
||||||
description: Makes nearby electronics stop working properly. Using it leaves you vulnerable to attacks for a long period of time.
|
description: Makes nearby electronics stop working properly. Using it leaves you vulnerable to attacks for a long period of time.
|
||||||
productAction: RevenantMalfunction
|
productAction: RevenantMalfunction
|
||||||
cost:
|
cost:
|
||||||
StolenEssence: 125
|
StolenEssence: 125
|
||||||
categories:
|
categories:
|
||||||
- RevenantAbilities
|
- RevenantAbilities
|
||||||
|
|||||||
@@ -1,60 +0,0 @@
|
|||||||
- type: disease
|
|
||||||
id: ActiveHonkVirus
|
|
||||||
name: disease-proto-honk
|
|
||||||
infectious: false
|
|
||||||
cureResist: 0.2
|
|
||||||
stages:
|
|
||||||
- 0
|
|
||||||
- 120
|
|
||||||
- 780
|
|
||||||
effects:
|
|
||||||
# toxin
|
|
||||||
- !type:DiseaseAdjustReagent
|
|
||||||
probability: 0.07
|
|
||||||
reagent: Toxin
|
|
||||||
amount: 1
|
|
||||||
stages:
|
|
||||||
- 0
|
|
||||||
- 1
|
|
||||||
- 2
|
|
||||||
# honks
|
|
||||||
- !type:DiseaseHonk
|
|
||||||
probability: 0.03
|
|
||||||
emote: Honk
|
|
||||||
stages:
|
|
||||||
- 0
|
|
||||||
- !type:DiseaseHonk
|
|
||||||
probability: 0.04
|
|
||||||
emote: Honk
|
|
||||||
stages:
|
|
||||||
- 1
|
|
||||||
- !type:DiseaseHonk
|
|
||||||
probability: 0.06
|
|
||||||
emote: Honk
|
|
||||||
stages:
|
|
||||||
- 2
|
|
||||||
# stuttering accent chance when speaking
|
|
||||||
- !type:DiseaseGenericStatusEffect
|
|
||||||
probability: 0.3
|
|
||||||
key: Stutter
|
|
||||||
component: StutteringAccent
|
|
||||||
stages:
|
|
||||||
- 1
|
|
||||||
- !type:DiseaseGenericStatusEffect
|
|
||||||
probability: 0.6
|
|
||||||
key: Stutter
|
|
||||||
component: StutteringAccent
|
|
||||||
stages:
|
|
||||||
- 2
|
|
||||||
# possible cluwnification if ignored too long
|
|
||||||
- !type:DiseaseAddComponent
|
|
||||||
comp: Cluwne
|
|
||||||
probability: 0.0007
|
|
||||||
stages:
|
|
||||||
- 2
|
|
||||||
cures:
|
|
||||||
- !type:DiseaseReagentCure
|
|
||||||
reagent: BananaHonk
|
|
||||||
min: 5
|
|
||||||
- !type:DiseaseJustWaitCure
|
|
||||||
maxLength: 900
|
|
||||||
@@ -1,301 +0,0 @@
|
|||||||
- type: disease
|
|
||||||
id: SpaceCold
|
|
||||||
name: disease-proto-space-cold
|
|
||||||
cureResist: 0
|
|
||||||
effects:
|
|
||||||
- !type:DiseaseAdjustReagent
|
|
||||||
probability: 0.2
|
|
||||||
reagent: Histamine
|
|
||||||
amount: 0.5
|
|
||||||
- !type:DiseasePopUp
|
|
||||||
probability: 0.025
|
|
||||||
- !type:DiseaseSnough
|
|
||||||
probability: 0.025
|
|
||||||
emote: Sneeze
|
|
||||||
cures:
|
|
||||||
- !type:DiseaseBedrestCure
|
|
||||||
maxLength: 20
|
|
||||||
- !type:DiseaseJustWaitCure
|
|
||||||
maxLength: 400
|
|
||||||
- !type:DiseaseReagentCure
|
|
||||||
reagent: Ultravasculine
|
|
||||||
### - !type:DiseaseReagentCure ### In Loving Memory, Lean
|
|
||||||
### reagent: Lean ### 2022/03/12 - 2022/03/13
|
|
||||||
|
|
||||||
- type: disease
|
|
||||||
id: VentCough
|
|
||||||
name: disease-proto-vent-cough
|
|
||||||
effects:
|
|
||||||
- !type:DiseasePopUp
|
|
||||||
probability: 0.025
|
|
||||||
message: generic-reagent-effect-burning-insides
|
|
||||||
visualType: Medium
|
|
||||||
- !type:DiseaseSnough
|
|
||||||
probability: 0.025
|
|
||||||
emote: Cough
|
|
||||||
- !type:DiseaseHealthChange
|
|
||||||
probability: 0.015
|
|
||||||
damage:
|
|
||||||
types:
|
|
||||||
Caustic: 1
|
|
||||||
cures:
|
|
||||||
- !type:DiseaseBedrestCure
|
|
||||||
maxLength: 30
|
|
||||||
- !type:DiseaseJustWaitCure
|
|
||||||
maxLength: 600
|
|
||||||
- !type:DiseaseReagentCure
|
|
||||||
reagent: SpaceCleaner
|
|
||||||
|
|
||||||
- type: disease
|
|
||||||
id: SpaceFlu
|
|
||||||
name: disease-proto-space-flu
|
|
||||||
cureResist: 0.08
|
|
||||||
effects:
|
|
||||||
- !type:DiseaseVomit
|
|
||||||
probability: 0.01
|
|
||||||
- !type:DiseasePopUp
|
|
||||||
probability: 0.025
|
|
||||||
- !type:DiseaseSnough
|
|
||||||
probability: 0.025
|
|
||||||
emote: Sneeze
|
|
||||||
- !type:DiseaseHealthChange
|
|
||||||
probability: 0.015
|
|
||||||
damage:
|
|
||||||
types:
|
|
||||||
Heat: 1
|
|
||||||
cures:
|
|
||||||
- !type:DiseaseBedrestCure
|
|
||||||
maxLength: 100
|
|
||||||
|
|
||||||
- type: disease
|
|
||||||
id: BirdFlew
|
|
||||||
name: disease-proto-bird-flew
|
|
||||||
cureResist: 0.08
|
|
||||||
effects:
|
|
||||||
- !type:DiseaseVomit
|
|
||||||
probability: 0.015
|
|
||||||
- !type:DiseasePopUp
|
|
||||||
probability: 0.025
|
|
||||||
- !type:DiseaseSnough
|
|
||||||
probability: 0.025
|
|
||||||
emote: Cough
|
|
||||||
- !type:DiseaseHealthChange
|
|
||||||
probability: 0.05
|
|
||||||
damage:
|
|
||||||
types:
|
|
||||||
Caustic: 1
|
|
||||||
cures:
|
|
||||||
- !type:DiseaseBedrestCure
|
|
||||||
maxLength: 120
|
|
||||||
|
|
||||||
- type: disease
|
|
||||||
id: VanAusdallsRobovirus
|
|
||||||
name: disease-proto-robovirus
|
|
||||||
cureResist: 0.1
|
|
||||||
effects:
|
|
||||||
- !type:DiseaseAdjustReagent
|
|
||||||
probability: 0.025
|
|
||||||
reagent: Licoxide
|
|
||||||
amount: 0.5
|
|
||||||
- !type:DiseaseSnough
|
|
||||||
probability: 0.02
|
|
||||||
emote: RobotBeep
|
|
||||||
cures:
|
|
||||||
- !type:DiseaseJustWaitCure
|
|
||||||
maxLength: 900
|
|
||||||
- !type:DiseaseReagentCure
|
|
||||||
reagent: BeepskySmash
|
|
||||||
|
|
||||||
- type: disease
|
|
||||||
id: AMIV
|
|
||||||
name: disease-proto-amiv
|
|
||||||
cureResist: 0.10
|
|
||||||
stages:
|
|
||||||
- 0
|
|
||||||
- 120
|
|
||||||
- 780
|
|
||||||
effects:
|
|
||||||
# compulsion pop ups
|
|
||||||
- !type:DiseasePopUp
|
|
||||||
probability: 0.015
|
|
||||||
type: Pvs
|
|
||||||
message: disease-beat-chest-compulsion
|
|
||||||
visualType: Medium
|
|
||||||
stages:
|
|
||||||
- 0
|
|
||||||
- 1
|
|
||||||
- 2
|
|
||||||
- !type:DiseasePopUp
|
|
||||||
probability: 0.03
|
|
||||||
message: disease-banana-compulsion
|
|
||||||
visualType: Medium
|
|
||||||
stages:
|
|
||||||
- 0
|
|
||||||
- 1
|
|
||||||
- 2
|
|
||||||
# Screeches - spreads disease
|
|
||||||
- !type:DiseaseSnough
|
|
||||||
probability: 0.01
|
|
||||||
emote: MonkeyScreeches
|
|
||||||
stages:
|
|
||||||
- 0
|
|
||||||
- !type:DiseaseSnough
|
|
||||||
probability: 0.02
|
|
||||||
emote: MonkeyScreeches
|
|
||||||
stages:
|
|
||||||
- 1
|
|
||||||
- !type:DiseaseSnough
|
|
||||||
probability: 0.04
|
|
||||||
emote: MonkeyScreeches
|
|
||||||
stages:
|
|
||||||
- 2
|
|
||||||
# monkey accent chance when speaking
|
|
||||||
- !type:DiseaseGenericStatusEffect
|
|
||||||
probability: 0.2
|
|
||||||
key: Stutter
|
|
||||||
component: MonkeyAccent
|
|
||||||
stages:
|
|
||||||
- 1
|
|
||||||
- !type:DiseaseGenericStatusEffect
|
|
||||||
probability: 0.5
|
|
||||||
key: Stutter
|
|
||||||
component: MonkeyAccent
|
|
||||||
stages:
|
|
||||||
- 2
|
|
||||||
# asphyxiation damage, probably from all the screeching
|
|
||||||
- !type:DiseaseHealthChange
|
|
||||||
probability: 0.53
|
|
||||||
damage:
|
|
||||||
types:
|
|
||||||
Asphyxiation: 1
|
|
||||||
stages:
|
|
||||||
- 1
|
|
||||||
- 2
|
|
||||||
# possible monkefication if ignored too long
|
|
||||||
- !type:DiseasePolymorph
|
|
||||||
probability: 0.000427 ## ~5% chance over 120 secs
|
|
||||||
polymorphId: AMIVMorph
|
|
||||||
polymorphMessage: disease-polymorph
|
|
||||||
polymorphSound:
|
|
||||||
path: /Audio/Animals/monkey_scream.ogg
|
|
||||||
stages:
|
|
||||||
- 2
|
|
||||||
cures:
|
|
||||||
- !type:DiseaseJustWaitCure
|
|
||||||
maxLength: 900
|
|
||||||
stages:
|
|
||||||
- 0
|
|
||||||
- 1
|
|
||||||
- 2
|
|
||||||
- !type:DiseaseReagentCure
|
|
||||||
reagent: BananaHonk
|
|
||||||
stages:
|
|
||||||
- 0
|
|
||||||
- 1
|
|
||||||
- 2
|
|
||||||
|
|
||||||
- type: disease
|
|
||||||
id: MemeticAmirmir
|
|
||||||
name: disease-proto-amirmir
|
|
||||||
effects:
|
|
||||||
- !type:DiseaseGenericStatusEffect
|
|
||||||
probability: 0.015
|
|
||||||
key: ForcedSleep
|
|
||||||
component: ForcedSleeping
|
|
||||||
time: 3
|
|
||||||
type: Add
|
|
||||||
- !type:DiseaseSnough
|
|
||||||
probability: 0.025
|
|
||||||
emote: Yawn
|
|
||||||
|
|
||||||
- type: disease
|
|
||||||
id: BleedersBite
|
|
||||||
name: disease-proto-bleeders
|
|
||||||
effects:
|
|
||||||
- !type:DiseaseAdjustReagent
|
|
||||||
reagent: TranexamicAcid
|
|
||||||
amount: -2.5
|
|
||||||
- !type:DiseaseHealthChange
|
|
||||||
probability: 0.015
|
|
||||||
damage:
|
|
||||||
types:
|
|
||||||
Piercing: 20
|
|
||||||
- !type:DiseasePopUp
|
|
||||||
probability: 0.05
|
|
||||||
message: disease-eaten-inside
|
|
||||||
visualType: Medium
|
|
||||||
cures:
|
|
||||||
- !type:DiseaseJustWaitCure
|
|
||||||
maxLength: 900
|
|
||||||
- !type:DiseaseBodyTemperatureCure
|
|
||||||
min: 360
|
|
||||||
- !type:DiseaseReagentCure
|
|
||||||
reagent: DemonsBlood
|
|
||||||
|
|
||||||
- type: disease
|
|
||||||
id: Plague
|
|
||||||
name: disease-proto-plague
|
|
||||||
cureResist: 0.1
|
|
||||||
effects:
|
|
||||||
- !type:DiseaseVomit
|
|
||||||
probability: 0.005
|
|
||||||
- !type:DiseasePopUp
|
|
||||||
probability: 0.025
|
|
||||||
- !type:DiseaseSnough
|
|
||||||
probability: 0.025
|
|
||||||
emote: Cough
|
|
||||||
- !type:DiseaseHealthChange
|
|
||||||
probability: 0.05
|
|
||||||
damage:
|
|
||||||
types:
|
|
||||||
Poison: 2
|
|
||||||
cures:
|
|
||||||
- !type:DiseaseBedrestCure
|
|
||||||
maxLength: 120
|
|
||||||
- !type:DiseaseJustWaitCure
|
|
||||||
maxLength: 240
|
|
||||||
|
|
||||||
- type: disease
|
|
||||||
id: OwOnavirus
|
|
||||||
name: disease-proto-owonavirus
|
|
||||||
cureResist: 0.25
|
|
||||||
effects:
|
|
||||||
- !type:DiseaseGenericStatusEffect
|
|
||||||
key: Stutter
|
|
||||||
component: OwOAccent
|
|
||||||
- !type:DiseaseAdjustReagent ## 20 / 0.013 / 60 is around 25 minutes before overdose (0.5u metabolize each tick)
|
|
||||||
probability: 0.513
|
|
||||||
reagent: Ephedrine
|
|
||||||
amount: 1
|
|
||||||
- !type:DiseaseSnough
|
|
||||||
probability: 0.01
|
|
||||||
emote: CatMeow
|
|
||||||
- !type:DiseaseSnough
|
|
||||||
probability: 0.01
|
|
||||||
emote: CatHisses
|
|
||||||
cures:
|
|
||||||
- !type:DiseaseBodyTemperatureCure
|
|
||||||
min: 420 ## Reachable with a flamer
|
|
||||||
- !type:DiseaseReagentCure
|
|
||||||
reagent: Theobromine
|
|
||||||
min: 4
|
|
||||||
|
|
||||||
- type: disease
|
|
||||||
id: TongueTwister
|
|
||||||
name: disease-proto-tongue-twister
|
|
||||||
cureResist: 0.1
|
|
||||||
effects:
|
|
||||||
- !type:DiseaseGenericStatusEffect
|
|
||||||
key: Stutter
|
|
||||||
component: ScrambledAccent
|
|
||||||
- !type:DiseaseSnough
|
|
||||||
probability: 0.01
|
|
||||||
emote: Sneeze
|
|
||||||
- !type:DiseasePopUp
|
|
||||||
probability: 0.02
|
|
||||||
message: disease-think
|
|
||||||
cures:
|
|
||||||
- !type:DiseaseBedrestCure
|
|
||||||
maxLength: 30
|
|
||||||
- !type:DiseaseJustWaitCure
|
|
||||||
maxLength: 400
|
|
||||||
@@ -1,66 +0,0 @@
|
|||||||
- type: disease
|
|
||||||
id: Ultragigacancer
|
|
||||||
name: disease-proto-ultragigacancer
|
|
||||||
infectious: false
|
|
||||||
cureResist: 0.15
|
|
||||||
effects:
|
|
||||||
- !type:DiseaseHealthChange
|
|
||||||
probability: 0.3
|
|
||||||
damage:
|
|
||||||
types:
|
|
||||||
Cellular: 1
|
|
||||||
- !type:DiseaseVomit
|
|
||||||
probability: 0.01
|
|
||||||
- !type:DiseasePopUp
|
|
||||||
probability: 0.03
|
|
||||||
cures:
|
|
||||||
- !type:DiseaseReagentCure
|
|
||||||
reagent: Phalanximine
|
|
||||||
min: 15
|
|
||||||
|
|
||||||
- type: disease
|
|
||||||
id: SpectralTiredness
|
|
||||||
name: disease-proto-spectral-tiredness
|
|
||||||
infectious: false
|
|
||||||
effects:
|
|
||||||
- !type:DiseaseGenericStatusEffect
|
|
||||||
probability: 0.03
|
|
||||||
key: ForcedSleep
|
|
||||||
component: ForcedSleeping
|
|
||||||
time: 3
|
|
||||||
type: Add
|
|
||||||
- !type:DiseaseSnough
|
|
||||||
probability: 0.025
|
|
||||||
emote: Yawn
|
|
||||||
- !type:DiseaseHealthChange
|
|
||||||
probability: 0.02
|
|
||||||
damage:
|
|
||||||
types:
|
|
||||||
Poison: 4
|
|
||||||
cures:
|
|
||||||
- !type:DiseaseJustWaitCure
|
|
||||||
maxLength: 240
|
|
||||||
- !type:DiseaseBedrestCure
|
|
||||||
maxLength: 60
|
|
||||||
|
|
||||||
- type: disease
|
|
||||||
id: StageIIIALungCancer
|
|
||||||
name: disease-proto-lung-cancer
|
|
||||||
infectious: false
|
|
||||||
cureResist: 1.0
|
|
||||||
effects:
|
|
||||||
- !type:DiseaseHealthChange
|
|
||||||
probability: 0.3
|
|
||||||
damage:
|
|
||||||
types:
|
|
||||||
Cellular: 1
|
|
||||||
- !type:DiseaseVomit
|
|
||||||
probability: 0.01
|
|
||||||
- !type:DiseaseSnough
|
|
||||||
probability: 0.10
|
|
||||||
emote: Cough
|
|
||||||
- !type:DiseasePopUp
|
|
||||||
probability: 0.03
|
|
||||||
|
|
||||||
|
|
||||||
### Once radiation is refactored I want it to have a small chance of giving you regular cancer
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
- type: disease
|
|
||||||
id: ActiveZombieVirus
|
|
||||||
name: disease-proto-zombie
|
|
||||||
infectious: false
|
|
||||||
cureResist: 0.2
|
|
||||||
effects:
|
|
||||||
- !type:DiseaseHealthChange
|
|
||||||
probability: 0.075
|
|
||||||
damage:
|
|
||||||
types:
|
|
||||||
Blunt: 4
|
|
||||||
- !type:DiseaseAdjustReagent
|
|
||||||
probability: 0.05
|
|
||||||
reagent: Toxin
|
|
||||||
amount: 1
|
|
||||||
- !type:DiseaseSnough
|
|
||||||
probability: 0.01
|
|
||||||
emote: Cough
|
|
||||||
- !type:DiseaseAddComponent
|
|
||||||
comp: ZombifyOnDeath
|
|
||||||
cures:
|
|
||||||
- !type:DiseaseReagentCure
|
|
||||||
reagent: Romerol
|
|
||||||
min: 5
|
|
||||||
|
|
||||||
- type: disease
|
|
||||||
id: PassiveZombieVirus
|
|
||||||
name: disease-proto-zombie-passive
|
|
||||||
infectious: false
|
|
||||||
cureResist: 1 #no cure. Death is your cure.
|
|
||||||
effects:
|
|
||||||
- !type:DiseaseAddComponent
|
|
||||||
comp: ZombifyOnDeath
|
|
||||||
@@ -7,5 +7,3 @@
|
|||||||
state: icon
|
state: icon
|
||||||
- type: Clothing
|
- type: Clothing
|
||||||
slots: [gloves]
|
slots: [gloves]
|
||||||
- type: DiseaseProtection
|
|
||||||
protection: 0.05
|
|
||||||
|
|||||||
@@ -133,8 +133,6 @@
|
|||||||
sprite: Clothing/Hands/Gloves/latex.rsi
|
sprite: Clothing/Hands/Gloves/latex.rsi
|
||||||
- type: Clothing
|
- type: Clothing
|
||||||
sprite: Clothing/Hands/Gloves/latex.rsi
|
sprite: Clothing/Hands/Gloves/latex.rsi
|
||||||
- type: DiseaseProtection
|
|
||||||
protection: 0.1
|
|
||||||
- type: Fiber
|
- type: Fiber
|
||||||
fiberMaterial: fibers-latex
|
fiberMaterial: fibers-latex
|
||||||
- type: FingerprintMask
|
- type: FingerprintMask
|
||||||
@@ -149,8 +147,6 @@
|
|||||||
sprite: Clothing/Hands/Gloves/Color/blue.rsi
|
sprite: Clothing/Hands/Gloves/Color/blue.rsi
|
||||||
- type: Clothing
|
- type: Clothing
|
||||||
sprite: Clothing/Hands/Gloves/Color/blue.rsi
|
sprite: Clothing/Hands/Gloves/Color/blue.rsi
|
||||||
- type: DiseaseProtection
|
|
||||||
protection: 0.15
|
|
||||||
- type: Fiber
|
- type: Fiber
|
||||||
fiberMaterial: fibers-nitrile
|
fiberMaterial: fibers-nitrile
|
||||||
- type: FingerprintMask
|
- type: FingerprintMask
|
||||||
|
|||||||
@@ -122,8 +122,6 @@
|
|||||||
tags:
|
tags:
|
||||||
- HidesHair
|
- HidesHair
|
||||||
- WhitelistChameleon
|
- WhitelistChameleon
|
||||||
- type: DiseaseProtection
|
|
||||||
protection: 0.05
|
|
||||||
- type: IdentityBlocker
|
- type: IdentityBlocker
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
@@ -162,8 +160,6 @@
|
|||||||
tags:
|
tags:
|
||||||
- HidesHair
|
- HidesHair
|
||||||
- WhitelistChameleon
|
- WhitelistChameleon
|
||||||
- type: DiseaseProtection
|
|
||||||
protection: 0.05
|
|
||||||
- type: IdentityBlocker
|
- type: IdentityBlocker
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
|
|||||||
@@ -141,8 +141,6 @@
|
|||||||
- type: PressureProtection
|
- type: PressureProtection
|
||||||
highPressureMultiplier: 0.6
|
highPressureMultiplier: 0.6
|
||||||
lowPressureMultiplier: 5500
|
lowPressureMultiplier: 5500
|
||||||
- type: DiseaseProtection
|
|
||||||
protection: 0.15
|
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: ClothingHeadHardsuitWithLightBase
|
parent: ClothingHeadHardsuitWithLightBase
|
||||||
@@ -256,8 +254,6 @@
|
|||||||
- type: PressureProtection
|
- type: PressureProtection
|
||||||
highPressureMultiplier: 0.6
|
highPressureMultiplier: 0.6
|
||||||
lowPressureMultiplier: 5500
|
lowPressureMultiplier: 5500
|
||||||
- type: DiseaseProtection
|
|
||||||
protection: 0.15
|
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: ClothingHeadHardsuitWithLightBase
|
parent: ClothingHeadHardsuitWithLightBase
|
||||||
@@ -440,8 +436,6 @@
|
|||||||
Piercing: 0.8
|
Piercing: 0.8
|
||||||
Heat: 0.2
|
Heat: 0.2
|
||||||
Radiation: 0.5
|
Radiation: 0.5
|
||||||
- type: DiseaseProtection
|
|
||||||
protection: 0.15
|
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: ClothingHeadHardsuitWithLightBase
|
parent: ClothingHeadHardsuitWithLightBase
|
||||||
@@ -484,8 +478,6 @@
|
|||||||
Shock: 0.1
|
Shock: 0.1
|
||||||
Cold: 0.2
|
Cold: 0.2
|
||||||
Radiation: 0.2
|
Radiation: 0.2
|
||||||
- type: DiseaseProtection
|
|
||||||
protection: 0.25
|
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: ClothingHeadHardsuitBase
|
parent: ClothingHeadHardsuitBase
|
||||||
@@ -559,8 +551,6 @@
|
|||||||
sprite: Clothing/Head/Hardsuits/ERThelmets/ertmedical.rsi
|
sprite: Clothing/Head/Hardsuits/ERThelmets/ertmedical.rsi
|
||||||
- type: PointLight
|
- type: PointLight
|
||||||
color: "#adffec"
|
color: "#adffec"
|
||||||
- type: DiseaseProtection
|
|
||||||
protection: 0.20
|
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: ClothingHeadHelmetHardsuitSyndie
|
parent: ClothingHeadHelmetHardsuitSyndie
|
||||||
|
|||||||
@@ -293,8 +293,6 @@
|
|||||||
- type: Clothing
|
- type: Clothing
|
||||||
sprite: Clothing/Head/Helmets/paramedhelm.rsi
|
sprite: Clothing/Head/Helmets/paramedhelm.rsi
|
||||||
- type: IngestionBlocker
|
- type: IngestionBlocker
|
||||||
- type: DiseaseProtection
|
|
||||||
protection: 0.15
|
|
||||||
- type: TemperatureProtection
|
- type: TemperatureProtection
|
||||||
coefficient: 0.1
|
coefficient: 0.1
|
||||||
- type: Armor
|
- type: Armor
|
||||||
|
|||||||
@@ -9,8 +9,6 @@
|
|||||||
sprite: Clothing/Head/Hoods/Bio/general.rsi
|
sprite: Clothing/Head/Hoods/Bio/general.rsi
|
||||||
- type: Clothing
|
- type: Clothing
|
||||||
sprite: Clothing/Head/Hoods/Bio/general.rsi
|
sprite: Clothing/Head/Hoods/Bio/general.rsi
|
||||||
- type: DiseaseProtection
|
|
||||||
protection: 0.15
|
|
||||||
- type: Tag
|
- type: Tag
|
||||||
tags:
|
tags:
|
||||||
- HidesHair
|
- HidesHair
|
||||||
@@ -26,8 +24,6 @@
|
|||||||
sprite: Clothing/Head/Hoods/Bio/cmo.rsi
|
sprite: Clothing/Head/Hoods/Bio/cmo.rsi
|
||||||
- type: Clothing
|
- type: Clothing
|
||||||
sprite: Clothing/Head/Hoods/Bio/cmo.rsi
|
sprite: Clothing/Head/Hoods/Bio/cmo.rsi
|
||||||
- type: DiseaseProtection
|
|
||||||
protection: 0.25
|
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: ClothingHeadHatHoodBioGeneral
|
parent: ClothingHeadHatHoodBioGeneral
|
||||||
@@ -76,8 +72,6 @@
|
|||||||
sprite: Clothing/Head/Hoods/Bio/virology.rsi
|
sprite: Clothing/Head/Hoods/Bio/virology.rsi
|
||||||
- type: Clothing
|
- type: Clothing
|
||||||
sprite: Clothing/Head/Hoods/Bio/virology.rsi
|
sprite: Clothing/Head/Hoods/Bio/virology.rsi
|
||||||
- type: DiseaseProtection
|
|
||||||
protection: 0.25
|
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: ClothingHeadBase
|
parent: ClothingHeadBase
|
||||||
|
|||||||
@@ -10,8 +10,6 @@
|
|||||||
sprite: Clothing/Mask/gas.rsi
|
sprite: Clothing/Mask/gas.rsi
|
||||||
- type: BreathMask
|
- type: BreathMask
|
||||||
- type: IngestionBlocker
|
- type: IngestionBlocker
|
||||||
- type: DiseaseProtection
|
|
||||||
protection: 0.05
|
|
||||||
- type: IdentityBlocker
|
- type: IdentityBlocker
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
@@ -66,8 +64,6 @@
|
|||||||
sprite: Clothing/Mask/gascaptain.rsi
|
sprite: Clothing/Mask/gascaptain.rsi
|
||||||
- type: BreathMask
|
- type: BreathMask
|
||||||
- type: IngestionBlocker
|
- type: IngestionBlocker
|
||||||
- type: DiseaseProtection
|
|
||||||
protection: 0.05
|
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: ClothingMaskGasAtmos
|
parent: ClothingMaskGasAtmos
|
||||||
@@ -81,8 +77,6 @@
|
|||||||
sprite: Clothing/Mask/gascentcom.rsi
|
sprite: Clothing/Mask/gascentcom.rsi
|
||||||
- type: BreathMask
|
- type: BreathMask
|
||||||
- type: IngestionBlocker
|
- type: IngestionBlocker
|
||||||
- type: DiseaseProtection
|
|
||||||
protection: 0.05
|
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: ClothingMaskGas
|
parent: ClothingMaskGas
|
||||||
@@ -114,8 +108,6 @@
|
|||||||
sprite: Clothing/Mask/medical.rsi
|
sprite: Clothing/Mask/medical.rsi
|
||||||
- type: BreathMask
|
- type: BreathMask
|
||||||
- type: IngestionBlocker
|
- type: IngestionBlocker
|
||||||
- type: DiseaseProtection
|
|
||||||
protection: 0.10
|
|
||||||
- type: Tag
|
- type: Tag
|
||||||
tags:
|
tags:
|
||||||
- PetWearable
|
- PetWearable
|
||||||
@@ -149,8 +141,6 @@
|
|||||||
sprite: Clothing/Mask/breath.rsi
|
sprite: Clothing/Mask/breath.rsi
|
||||||
- type: BreathMask
|
- type: BreathMask
|
||||||
- type: IngestionBlocker
|
- type: IngestionBlocker
|
||||||
- type: DiseaseProtection
|
|
||||||
protection: 0.05
|
|
||||||
- type: Tag
|
- type: Tag
|
||||||
tags:
|
tags:
|
||||||
- PetWearable
|
- PetWearable
|
||||||
@@ -213,8 +203,6 @@
|
|||||||
- type: Clothing
|
- type: Clothing
|
||||||
sprite: Clothing/Mask/sterile.rsi
|
sprite: Clothing/Mask/sterile.rsi
|
||||||
- type: IngestionBlocker
|
- type: IngestionBlocker
|
||||||
- type: DiseaseProtection
|
|
||||||
protection: 0.1
|
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: ClothingMaskBase
|
parent: ClothingMaskBase
|
||||||
@@ -246,8 +234,6 @@
|
|||||||
sprite: Clothing/Mask/plaguedoctormask.rsi
|
sprite: Clothing/Mask/plaguedoctormask.rsi
|
||||||
- type: BreathMask
|
- type: BreathMask
|
||||||
- type: IngestionBlocker
|
- type: IngestionBlocker
|
||||||
- type: DiseaseProtection
|
|
||||||
protection: 0.1
|
|
||||||
- type: IdentityBlocker
|
- type: IdentityBlocker
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
|
|||||||
@@ -67,8 +67,6 @@
|
|||||||
Piercing: 0.95
|
Piercing: 0.95
|
||||||
Heat: 0.90
|
Heat: 0.90
|
||||||
Radiation: 0.25
|
Radiation: 0.25
|
||||||
- type: DiseaseProtection
|
|
||||||
protection: 0.05
|
|
||||||
- type: ToggleableClothing
|
- type: ToggleableClothing
|
||||||
- type: ContainerContainer
|
- type: ContainerContainer
|
||||||
containers:
|
containers:
|
||||||
@@ -94,5 +92,3 @@
|
|||||||
sprintModifier: 0.8
|
sprintModifier: 0.8
|
||||||
- type: Item
|
- type: Item
|
||||||
size: 80
|
size: 80
|
||||||
- type: DiseaseProtection
|
|
||||||
protection: 0.05
|
|
||||||
|
|||||||
@@ -9,8 +9,6 @@
|
|||||||
sprite: Clothing/OuterClothing/Bio/general.rsi
|
sprite: Clothing/OuterClothing/Bio/general.rsi
|
||||||
- type: Clothing
|
- type: Clothing
|
||||||
sprite: Clothing/OuterClothing/Bio/general.rsi
|
sprite: Clothing/OuterClothing/Bio/general.rsi
|
||||||
- type: DiseaseProtection
|
|
||||||
protection: 0.2
|
|
||||||
- type: Armor
|
- type: Armor
|
||||||
modifiers:
|
modifiers:
|
||||||
coefficients:
|
coefficients:
|
||||||
@@ -27,8 +25,6 @@
|
|||||||
sprite: Clothing/OuterClothing/Bio/cmo.rsi
|
sprite: Clothing/OuterClothing/Bio/cmo.rsi
|
||||||
- type: Clothing
|
- type: Clothing
|
||||||
sprite: Clothing/OuterClothing/Bio/cmo.rsi
|
sprite: Clothing/OuterClothing/Bio/cmo.rsi
|
||||||
- type: DiseaseProtection
|
|
||||||
protection: 0.5
|
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: ClothingOuterBioGeneral
|
parent: ClothingOuterBioGeneral
|
||||||
@@ -53,8 +49,6 @@
|
|||||||
sprite: Clothing/OuterClothing/Bio/scientist.rsi
|
sprite: Clothing/OuterClothing/Bio/scientist.rsi
|
||||||
- type: Clothing
|
- type: Clothing
|
||||||
sprite: Clothing/OuterClothing/Bio/scientist.rsi
|
sprite: Clothing/OuterClothing/Bio/scientist.rsi
|
||||||
- type: DiseaseProtection
|
|
||||||
protection: 0.3
|
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: ClothingOuterBioGeneral
|
parent: ClothingOuterBioGeneral
|
||||||
@@ -67,8 +61,6 @@
|
|||||||
sprite: Clothing/OuterClothing/Bio/security.rsi
|
sprite: Clothing/OuterClothing/Bio/security.rsi
|
||||||
- type: Clothing
|
- type: Clothing
|
||||||
sprite: Clothing/OuterClothing/Bio/security.rsi
|
sprite: Clothing/OuterClothing/Bio/security.rsi
|
||||||
- type: DiseaseProtection
|
|
||||||
protection: 0.3
|
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: ClothingOuterBioCmo
|
parent: ClothingOuterBioCmo
|
||||||
@@ -81,5 +73,3 @@
|
|||||||
sprite: Clothing/OuterClothing/Bio/virology.rsi
|
sprite: Clothing/OuterClothing/Bio/virology.rsi
|
||||||
- type: Clothing
|
- type: Clothing
|
||||||
sprite: Clothing/OuterClothing/Bio/virology.rsi
|
sprite: Clothing/OuterClothing/Bio/virology.rsi
|
||||||
- type: DiseaseProtection
|
|
||||||
protection: 0.5
|
|
||||||
|
|||||||
@@ -227,8 +227,6 @@
|
|||||||
- type: PressureProtection
|
- type: PressureProtection
|
||||||
highPressureMultiplier: 0.3
|
highPressureMultiplier: 0.3
|
||||||
lowPressureMultiplier: 5500
|
lowPressureMultiplier: 5500
|
||||||
- type: DiseaseProtection
|
|
||||||
protection: 0.2
|
|
||||||
- type: ClothingSpeedModifier
|
- type: ClothingSpeedModifier
|
||||||
walkModifier: 0.9
|
walkModifier: 0.9
|
||||||
sprintModifier: 0.95
|
sprintModifier: 0.95
|
||||||
@@ -379,8 +377,6 @@
|
|||||||
- type: PressureProtection
|
- type: PressureProtection
|
||||||
highPressureMultiplier: 0.3
|
highPressureMultiplier: 0.3
|
||||||
lowPressureMultiplier: 5500
|
lowPressureMultiplier: 5500
|
||||||
- type: DiseaseProtection
|
|
||||||
protection: 0.2
|
|
||||||
- type: ClothingSpeedModifier
|
- type: ClothingSpeedModifier
|
||||||
walkModifier: 0.8
|
walkModifier: 0.8
|
||||||
sprintModifier: 0.85
|
sprintModifier: 0.85
|
||||||
@@ -555,8 +551,6 @@
|
|||||||
- type: ClothingSpeedModifier
|
- type: ClothingSpeedModifier
|
||||||
walkModifier: 0.9
|
walkModifier: 0.9
|
||||||
sprintModifier: 0.9
|
sprintModifier: 0.9
|
||||||
- type: DiseaseProtection
|
|
||||||
protection: 0.15
|
|
||||||
- type: TemperatureProtection
|
- type: TemperatureProtection
|
||||||
coefficient: 0.1
|
coefficient: 0.1
|
||||||
- type: Armor
|
- type: Armor
|
||||||
@@ -659,8 +653,6 @@
|
|||||||
damageCoefficient: 0.3
|
damageCoefficient: 0.3
|
||||||
- type: ToggleableClothing
|
- type: ToggleableClothing
|
||||||
clothingPrototype: ClothingHeadHelmetHardsuitSyndieElite
|
clothingPrototype: ClothingHeadHelmetHardsuitSyndieElite
|
||||||
- type: DiseaseProtection
|
|
||||||
protection: 0.2
|
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: ClothingOuterHardsuitBase
|
parent: ClothingOuterHardsuitBase
|
||||||
@@ -695,8 +687,6 @@
|
|||||||
damageCoefficient: 0.7
|
damageCoefficient: 0.7
|
||||||
- type: ToggleableClothing
|
- type: ToggleableClothing
|
||||||
clothingPrototype: ClothingHeadHelmetCBURN
|
clothingPrototype: ClothingHeadHelmetCBURN
|
||||||
- type: DiseaseProtection
|
|
||||||
protection: 0.4
|
|
||||||
|
|
||||||
#ERT
|
#ERT
|
||||||
- type: entity
|
- type: entity
|
||||||
@@ -735,8 +725,6 @@
|
|||||||
sprite: Clothing/OuterClothing/Hardsuits/ERTSuits/ertmedical.rsi
|
sprite: Clothing/OuterClothing/Hardsuits/ERTSuits/ertmedical.rsi
|
||||||
- type: ToggleableClothing
|
- type: ToggleableClothing
|
||||||
clothingPrototype: ClothingHeadHelmetHardsuitERTMedical
|
clothingPrototype: ClothingHeadHelmetHardsuitERTMedical
|
||||||
- type: DiseaseProtection
|
|
||||||
protection: 0.25
|
|
||||||
|
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
|
|||||||
@@ -111,8 +111,6 @@
|
|||||||
sprite: Clothing/Uniforms/Jumpskirt/cmo.rsi
|
sprite: Clothing/Uniforms/Jumpskirt/cmo.rsi
|
||||||
- type: Clothing
|
- type: Clothing
|
||||||
sprite: Clothing/Uniforms/Jumpskirt/cmo.rsi
|
sprite: Clothing/Uniforms/Jumpskirt/cmo.rsi
|
||||||
- type: DiseaseProtection
|
|
||||||
protection: 0.15
|
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: ClothingUniformSkirtBase
|
parent: ClothingUniformSkirtBase
|
||||||
@@ -233,8 +231,6 @@
|
|||||||
sprite: Clothing/Uniforms/Jumpskirt/medical.rsi
|
sprite: Clothing/Uniforms/Jumpskirt/medical.rsi
|
||||||
- type: Clothing
|
- type: Clothing
|
||||||
sprite: Clothing/Uniforms/Jumpskirt/medical.rsi
|
sprite: Clothing/Uniforms/Jumpskirt/medical.rsi
|
||||||
- type: DiseaseProtection
|
|
||||||
protection: 0.1
|
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: ClothingUniformSkirtBase
|
parent: ClothingUniformSkirtBase
|
||||||
@@ -257,8 +253,6 @@
|
|||||||
sprite: Clothing/Uniforms/Jumpskirt/paramedic.rsi
|
sprite: Clothing/Uniforms/Jumpskirt/paramedic.rsi
|
||||||
- type: Clothing
|
- type: Clothing
|
||||||
sprite: Clothing/Uniforms/Jumpskirt/paramedic.rsi
|
sprite: Clothing/Uniforms/Jumpskirt/paramedic.rsi
|
||||||
- type: DiseaseProtection
|
|
||||||
protection: 0.1
|
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: ClothingUniformBase
|
parent: ClothingUniformBase
|
||||||
@@ -270,8 +264,6 @@
|
|||||||
sprite: Clothing/Uniforms/Jumpskirt/brigmedic.rsi
|
sprite: Clothing/Uniforms/Jumpskirt/brigmedic.rsi
|
||||||
- type: Clothing
|
- type: Clothing
|
||||||
sprite: Clothing/Uniforms/Jumpskirt/brigmedic.rsi
|
sprite: Clothing/Uniforms/Jumpskirt/brigmedic.rsi
|
||||||
- type: DiseaseProtection
|
|
||||||
protection: 0.1
|
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: ClothingUniformSkirtBase
|
parent: ClothingUniformSkirtBase
|
||||||
|
|||||||
@@ -203,8 +203,6 @@
|
|||||||
sprite: Clothing/Uniforms/Jumpsuit/cmo.rsi
|
sprite: Clothing/Uniforms/Jumpsuit/cmo.rsi
|
||||||
- type: Clothing
|
- type: Clothing
|
||||||
sprite: Clothing/Uniforms/Jumpsuit/cmo.rsi
|
sprite: Clothing/Uniforms/Jumpsuit/cmo.rsi
|
||||||
- type: DiseaseProtection
|
|
||||||
protection: 0.15
|
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: ClothingUniformBase
|
parent: ClothingUniformBase
|
||||||
@@ -358,8 +356,6 @@
|
|||||||
sprite: Clothing/Uniforms/Jumpsuit/medical.rsi
|
sprite: Clothing/Uniforms/Jumpsuit/medical.rsi
|
||||||
- type: Clothing
|
- type: Clothing
|
||||||
sprite: Clothing/Uniforms/Jumpsuit/medical.rsi
|
sprite: Clothing/Uniforms/Jumpsuit/medical.rsi
|
||||||
- type: DiseaseProtection
|
|
||||||
protection: 0.1
|
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: ClothingUniformBase
|
parent: ClothingUniformBase
|
||||||
@@ -382,8 +378,6 @@
|
|||||||
sprite: Clothing/Uniforms/Jumpsuit/paramedic.rsi
|
sprite: Clothing/Uniforms/Jumpsuit/paramedic.rsi
|
||||||
- type: Clothing
|
- type: Clothing
|
||||||
sprite: Clothing/Uniforms/Jumpsuit/paramedic.rsi
|
sprite: Clothing/Uniforms/Jumpsuit/paramedic.rsi
|
||||||
- type: DiseaseProtection
|
|
||||||
protection: 0.1
|
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: ClothingUniformBase
|
parent: ClothingUniformBase
|
||||||
@@ -395,8 +389,6 @@
|
|||||||
sprite: Clothing/Uniforms/Jumpsuit/brigmedic.rsi
|
sprite: Clothing/Uniforms/Jumpsuit/brigmedic.rsi
|
||||||
- type: Clothing
|
- type: Clothing
|
||||||
sprite: Clothing/Uniforms/Jumpsuit/brigmedic.rsi
|
sprite: Clothing/Uniforms/Jumpsuit/brigmedic.rsi
|
||||||
- type: DiseaseProtection
|
|
||||||
protection: 0.1
|
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: ClothingUniformBase
|
parent: ClothingUniformBase
|
||||||
@@ -990,8 +982,6 @@
|
|||||||
sprite: Clothing/Uniforms/Jumpsuit/ert_janitor.rsi
|
sprite: Clothing/Uniforms/Jumpsuit/ert_janitor.rsi
|
||||||
- type: Clothing
|
- type: Clothing
|
||||||
sprite: Clothing/Uniforms/Jumpsuit/ert_janitor.rsi
|
sprite: Clothing/Uniforms/Jumpsuit/ert_janitor.rsi
|
||||||
- type: DiseaseProtection
|
|
||||||
protection: 0.1
|
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: ClothingUniformBase
|
parent: ClothingUniformBase
|
||||||
@@ -1020,8 +1010,6 @@
|
|||||||
sprite: Clothing/Uniforms/Jumpsuit/ert_medic.rsi
|
sprite: Clothing/Uniforms/Jumpsuit/ert_medic.rsi
|
||||||
- type: Clothing
|
- type: Clothing
|
||||||
sprite: Clothing/Uniforms/Jumpsuit/ert_medic.rsi
|
sprite: Clothing/Uniforms/Jumpsuit/ert_medic.rsi
|
||||||
- type: DiseaseProtection
|
|
||||||
protection: 0.15
|
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: ClothingUniformBase
|
parent: ClothingUniformBase
|
||||||
|
|||||||
@@ -929,10 +929,6 @@
|
|||||||
name: action-name-combat
|
name: action-name-combat
|
||||||
- type: Bloodstream
|
- type: Bloodstream
|
||||||
bloodMaxVolume: 50
|
bloodMaxVolume: 50
|
||||||
- type: DiseaseCarrier #The other class lab animal and disease vector
|
|
||||||
naturalImmunities:
|
|
||||||
- AMIV
|
|
||||||
- ActiveHonkVirus
|
|
||||||
- type: CanEscapeInventory
|
- type: CanEscapeInventory
|
||||||
- type: MobPrice
|
- type: MobPrice
|
||||||
price: 50
|
price: 50
|
||||||
@@ -962,8 +958,6 @@
|
|||||||
Base: splat-1
|
Base: splat-1
|
||||||
- type: Bloodstream
|
- type: Bloodstream
|
||||||
bloodMaxVolume: 50
|
bloodMaxVolume: 50
|
||||||
- type: DiseaseCarrier #Why doesn't this save if it's only on the parent wtf
|
|
||||||
|
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: MobMouse
|
parent: MobMouse
|
||||||
@@ -988,8 +982,6 @@
|
|||||||
Base: splat-2
|
Base: splat-2
|
||||||
- type: Bloodstream
|
- type: Bloodstream
|
||||||
bloodMaxVolume: 50
|
bloodMaxVolume: 50
|
||||||
- type: DiseaseCarrier
|
|
||||||
|
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
name: lizard #Weh
|
name: lizard #Weh
|
||||||
|
|||||||
@@ -117,19 +117,6 @@
|
|||||||
spawned:
|
spawned:
|
||||||
- id: ClothingHeadHatFancyCrown #how did that get there?
|
- id: ClothingHeadHatFancyCrown #how did that get there?
|
||||||
amount: 1
|
amount: 1
|
||||||
- type: DiseaseCarrier
|
|
||||||
naturalImmunities:
|
|
||||||
- ActiveHonkVirus
|
|
||||||
carrierDiseases:
|
|
||||||
- VentCough
|
|
||||||
- AMIV
|
|
||||||
- SpaceCold
|
|
||||||
- SpaceFlu
|
|
||||||
- BirdFlew
|
|
||||||
- VanAusdallsRobovirus
|
|
||||||
- BleedersBite
|
|
||||||
- Plague
|
|
||||||
- TongueTwister
|
|
||||||
- type: MobPrice
|
- type: MobPrice
|
||||||
price: 2500 # rat wealth
|
price: 2500 # rat wealth
|
||||||
- type: RandomMetadata
|
- type: RandomMetadata
|
||||||
@@ -271,19 +258,6 @@
|
|||||||
spawned:
|
spawned:
|
||||||
- id: FoodMeatRat
|
- id: FoodMeatRat
|
||||||
amount: 1
|
amount: 1
|
||||||
- type: DiseaseCarrier
|
|
||||||
naturalImmunities:
|
|
||||||
- ActiveHonkVirus
|
|
||||||
carrierDiseases:
|
|
||||||
- VentCough
|
|
||||||
- AMIV
|
|
||||||
- SpaceCold
|
|
||||||
- SpaceFlu
|
|
||||||
- BirdFlew
|
|
||||||
- VanAusdallsRobovirus
|
|
||||||
- BleedersBite
|
|
||||||
- Plague
|
|
||||||
- TongueTwister
|
|
||||||
- type: Vocal
|
- type: Vocal
|
||||||
sounds:
|
sounds:
|
||||||
Male: Mouse
|
Male: Mouse
|
||||||
|
|||||||
@@ -6,8 +6,6 @@
|
|||||||
description: They mostly come at night. Mostly.
|
description: They mostly come at night. Mostly.
|
||||||
components:
|
components:
|
||||||
- type: Insulated
|
- type: Insulated
|
||||||
- type: DiseaseProtection
|
|
||||||
protection: 1
|
|
||||||
- type: CombatMode
|
- type: CombatMode
|
||||||
- type: InputMover
|
- type: InputMover
|
||||||
- type: MobMover
|
- type: MobMover
|
||||||
|
|||||||
@@ -83,7 +83,6 @@
|
|||||||
- ForcedSleep
|
- ForcedSleep
|
||||||
- TemporaryBlindness
|
- TemporaryBlindness
|
||||||
- Pacified
|
- Pacified
|
||||||
- type: DiseaseCarrier
|
|
||||||
- type: Blindable
|
- type: Blindable
|
||||||
# Other
|
# Other
|
||||||
- type: Inventory
|
- type: Inventory
|
||||||
|
|||||||
@@ -28,8 +28,6 @@
|
|||||||
Male: UnisexReptilian
|
Male: UnisexReptilian
|
||||||
Female: UnisexReptilian
|
Female: UnisexReptilian
|
||||||
Unsexed: UnisexReptilian
|
Unsexed: UnisexReptilian
|
||||||
- type: DiseaseCarrier
|
|
||||||
diseaseResist: 0.1
|
|
||||||
- type: Damageable
|
- type: Damageable
|
||||||
damageContainer: Biological
|
damageContainer: Biological
|
||||||
damageModifierSet: Scale
|
damageModifierSet: Scale
|
||||||
|
|||||||
@@ -60,10 +60,6 @@
|
|||||||
types:
|
types:
|
||||||
Asphyxiation: -1.0
|
Asphyxiation: -1.0
|
||||||
maxSaturation: 15
|
maxSaturation: 15
|
||||||
- type: DiseaseCarrier
|
|
||||||
naturalImmunities:
|
|
||||||
- Ultragigacancer
|
|
||||||
- BleedersBite
|
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
save: false
|
save: false
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user