Skip to content
Open
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions Content.Client/HealthAnalyzer/UI/HealthAnalyzerWindow.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@
<Label Name="BloodLabel" />
<Label Text="{Loc 'health-analyzer-window-entity-damage-total-text'}" />
<Label Name="DamageLabel" />
<!-- ADT-Tweak-Start -->
<Label Name="AllergyText" Text="{Loc 'health-analyzer-window-entity-allergy-text'}" />
<!-- ADT-Tweak-End -->
</GridContainer>
</BoxContainer>

Expand Down
6 changes: 6 additions & 0 deletions Content.Client/HealthAnalyzer/UI/HealthAnalyzerWindow.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
using Robust.Client.ResourceManagement;
using Robust.Shared.Prototypes;
using Robust.Shared.Utility;
using Content.Shared.ADT.Body.Allergies;

namespace Content.Client.HealthAnalyzer.UI
{
Expand Down Expand Up @@ -131,6 +132,11 @@ public void Populate(HealthAnalyzerScannedUserMessage msg)

DamageLabel.Text = damageable.TotalDamage.ToString();

// ADT-Tweak-Start
bool allergic = _entityManager.HasComponent<AllergicComponent>(target.Value);
AllergyText.Visible = allergic;
// ADT-Tweak-End

// Alerts

var showAlerts = msg.Unrevivable == true || msg.Bleeding == true;
Expand Down
81 changes: 81 additions & 0 deletions Content.Server/ADT/Body/AllergicSystem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
using System.Linq;
using Content.Server.Body.Systems;
using Content.Shared.ADT.Body.Allergies;
using Content.Shared.Chemistry.Reagent;
using Content.Shared.Damage;
using Content.Shared.Damage.Prototypes;
using Content.Shared.EntityEffects.Effects;
using Robust.Shared.Prototypes;
using Robust.Shared.Random;

namespace Content.Server.ADT.Body;

public sealed class AllergicSystem : EntitySystem
{
[Dependency] private readonly IRobustRandom _random = default!;

[Dependency] private readonly IPrototypeManager _proto = default!;

private ProtoId<DamageGroupPrototype> _allergyDamageGroup = "Poison";

private DamageTypePrototype? _allergyDamageTypeProto;

public override void Initialize()
{
base.Initialize();

SubscribeLocalEvent<AllergicComponent, ComponentInit>(OnInit);
SubscribeLocalEvent<AllergicComponent, GetReagentEffectsEvent>(OnGetReagentEffects);

_allergyDamageTypeProto = _proto.Index<DamageTypePrototype>(_allergyDamageGroup);
}

private List<ProtoId<ReagentPrototype>> GetRandomAllergies(int min, int max)
{
int reagentsCount = _proto.Count<ReagentPrototype>();

if (reagentsCount == 0)
return new();

int safeMin = Math.Clamp(min, 0, reagentsCount);
int safeMax = Math.Clamp(max, safeMin, reagentsCount);
int allergiesCount = _random.Next(safeMin, safeMax + 1);

var picked = new HashSet<int>();
while (picked.Count < allergiesCount)
{
picked.Add(_random.Next(reagentsCount));
}

int index = 0;
List<ProtoId<ReagentPrototype>> allergies = new();

foreach (var proto in _proto.EnumeratePrototypes<ReagentPrototype>())
{
if (picked.Contains(index))
allergies.Add(proto.ID);
index++;
}

return allergies;
}

public void OnInit(EntityUid uid, AllergicComponent component, ComponentInit args)
{
component.Triggers = GetRandomAllergies(component.Min, component.Max);
}

public void OnGetReagentEffects(EntityUid uid, AllergicComponent component, ref GetReagentEffectsEvent ev)
{
if (!component.Triggers.Contains(ev.Reagent.Prototype))
return;

var damageSpecifier = new DamageSpecifier(_allergyDamageTypeProto!, 0.5);
var damageEffect = new HealthChange
{
Damage = damageSpecifier
};

ev.Effects = ev.Effects.Append(damageEffect).ToArray();
}
}
172 changes: 172 additions & 0 deletions Content.Server/ADT/Medical/EntitySystems/DiseaseDiagnoserSystem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
using System.Linq;
using System.Text;
using Content.Server.Botany;
using Content.Server.Power.EntitySystems;
using Content.Shared.ADT.Medical;
using Content.Shared.Chemistry.Reagent;
using Content.Shared.Interaction;
using Content.Shared.Paper;
using Content.Shared.Popups;
using Content.Shared.Power;
using Robust.Shared.Audio.Systems;
using Robust.Shared.Containers;
using Robust.Shared.Prototypes;
using Robust.Shared.Timing;

namespace Content.Server.ADT.Medical.EntitySystems;

public sealed class DiseaseDiagnoserSystem : EntitySystem
{
[Dependency] private readonly IGameTiming _timing = default!;
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
[Dependency] private readonly SharedAudioSystem _audio = default!;
[Dependency] private readonly SharedContainerSystem _container = default!;
[Dependency] private readonly SharedPopupSystem _popup = default!;
[Dependency] private readonly PaperSystem _paperSystem = default!;
[Dependency] private readonly IPrototypeManager _proto = default!;

public override void Initialize()
{
base.Initialize();

SubscribeLocalEvent<DiseaseDiagnoserComponent, ActivateInWorldEvent>(OnActivateInWorld);
SubscribeLocalEvent<DiseaseDiagnoserComponent, ContainerIsRemovingAttemptEvent>(OnRemoveAttempt);
SubscribeLocalEvent<DiseaseDiagnoserComponent, PowerChangedEvent>(OnPowerChanged);
}

#region Events

private void OnActivateInWorld(Entity<DiseaseDiagnoserComponent> entity, ref ActivateInWorldEvent args)
{
if (args.Handled || !args.Complex)
return;

TryStart(entity, args.User);
args.Handled = true;
}

private void OnRemoveAttempt(Entity<DiseaseDiagnoserComponent> ent, ref ContainerIsRemovingAttemptEvent args)
{
if (args.Container.ID == ent.Comp.ContainerId && ent.Comp.Working)
args.Cancel();
}

private void OnPowerChanged(Entity<DiseaseDiagnoserComponent> ent, ref PowerChangedEvent args)
{
if (!args.Powered)
Stop(ent);
}

#endregion

#region Lifecycle

public void TryStart(Entity<DiseaseDiagnoserComponent> entity, EntityUid? user)
{
var (uid, comp) = entity;
if (comp.Working)
return;

if (!HasPower(entity))
{
if (user != null)
_popup.PopupClient(Loc.GetString("solution-container-mixer-no-power"), entity, user.Value);
return;
}

if (!_container.TryGetContainer(uid, comp.ContainerId, out var container) || container.Count == 0)
{
if (user != null)
_popup.PopupClient(Loc.GetString("solution-container-mixer-popup-nothing-to-mix"), entity, user.Value);
return;
}

comp.Working = true;
comp.WorkingSoundEntity = _audio.PlayPvs(comp.WorkingSound, entity, comp.WorkingSound?.Params.WithLoop(true));
comp.WorkTimeEnd = _timing.CurTime + comp.WorkDuration;
_appearance.SetData(entity, DiseaseDiagnoserVisuals.Printing, true);
Dirty(uid, comp);
}

public void Stop(Entity<DiseaseDiagnoserComponent> entity)
{
var (uid, comp) = entity;
if (!comp.Working)
return;
_audio.Stop(comp.WorkingSoundEntity);
_appearance.SetData(entity, DiseaseDiagnoserVisuals.Printing, false);
comp.Working = false;
comp.WorkingSoundEntity = null;
Dirty(uid, comp);
}

public string GetReport(BotanySwabComponent swabComponent)
{
StringBuilder builder = new();

if (swabComponent.AllergicTriggers == null || swabComponent.AllergicTriggers.Count() == 0)
builder.Append(Loc.GetString("paper-allergy-prefix", ("allergies", Loc.GetString("paper-allergy-no"))));
else
{
List<string> localizedNames = new();
foreach (ProtoId<ReagentPrototype> trigger in swabComponent.AllergicTriggers)
{
localizedNames.Add(_proto.Index<ReagentPrototype>(trigger).LocalizedName.ToLower());
}

builder.Append(Loc.GetString("paper-allergy-prefix", ("allergies", String.Join(", ", localizedNames))));
}

return builder.ToString();
}

public void Finish(Entity<DiseaseDiagnoserComponent> entity)
{
var (uid, comp) = entity;
if (!comp.Working)
return;
Stop(entity);

if (!TryComp<DiseaseDiagnoserComponent>(entity, out var reactionMixer)
|| !_container.TryGetContainer(uid, comp.ContainerId, out var container))
return;

if (container.ContainedEntities.Count == 0)
return;

var swabEnt = container.ContainedEntities.First();
if (!TryComp<BotanySwabComponent>(swabEnt, out var swabComponent))
return;

var printed = Spawn("DiagnosisReportPaper", Transform(uid).Coordinates);

if (TryComp<PaperComponent>(printed, out var paper))
{
_paperSystem.SetContent((printed, paper), GetReport(swabComponent));
}
}

public override void Update(float frameTime)
{
base.Update(frameTime);

var query = EntityQueryEnumerator<DiseaseDiagnoserComponent>();
while (query.MoveNext(out var uid, out var comp))
{
if (!comp.Working)
continue;

if (_timing.CurTime < comp.WorkTimeEnd)
continue;

Finish((uid, comp));
}
}

#endregion

public bool HasPower(Entity<DiseaseDiagnoserComponent> entity)
{
return this.IsPowered(entity, EntityManager);
}
}
13 changes: 12 additions & 1 deletion Content.Server/Body/Systems/MetabolizerSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -194,8 +194,15 @@ private void TryMetabolize(Entity<MetabolizerComponent, OrganComponent?, Solutio

var actualEntity = ent.Comp2?.Body ?? solutionEntityUid.Value;

// ADT-Tweak-Start
var ev = new GetReagentEffectsEvent(reagent, entry.Effects);
RaiseLocalEvent(solutionEntityUid.Value, ref ev);

var effects = ev.Effects;
// ADT-Tweak-End

// do all effects, if conditions apply
foreach (var effect in entry.Effects)
foreach (var effect in effects) // ADT-Tweak: effects
{
if (scale < effect.MinScale)
continue;
Expand Down Expand Up @@ -280,3 +287,7 @@ public bool CanMetabolizeEffect(EntityUid body, EntityUid organ, Entity<Solution
}
}

// ADT-Tweak-Start
[ByRefEvent]
public record struct GetReagentEffectsEvent(ReagentId Reagent, EntityEffect[] Effects);
// ADT-Tweak-End
11 changes: 10 additions & 1 deletion Content.Server/Botany/Components/BotanySwabComponent.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Threading;
using Content.Shared.Chemistry.Reagent;
using Robust.Shared.Prototypes;

namespace Content.Server.Botany
{
Expand All @@ -15,5 +16,13 @@ public sealed partial class BotanySwabComponent : Component
/// SeedData from the first plant that got swabbed.
/// </summary>
public SeedData? SeedData;

/// <summary>
/// Allergic triggers from players swabbed.
/// </summary>
// ADT-Tweak-Start
[DataField]
public List<ProtoId<ReagentPrototype>>? AllergicTriggers;
// ADT-Tweak-End
}
}
Loading
Loading