Skip to content
Open
Show file tree
Hide file tree
Changes from 11 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
16 changes: 16 additions & 0 deletions Content.Server/ADT/Body/AllergicEvents.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using Content.Shared.Chemistry.Reagent;
using Robust.Shared.Prototypes;

namespace Content.Server.ADT.Body;

/// <summary>
/// When allergy triggered by allergens in bloodstream.
/// </summary>
[ByRefEvent]
public struct AllergyTriggeredEvent;

/// <summary>
/// When allergy stack has faded to zero.
/// </summary>
[ByRefEvent]
public struct AllergyFadedEvent;
66 changes: 66 additions & 0 deletions Content.Server/ADT/Body/AllergicSystem.Shock.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
using System.Linq;
using Content.Shared.ADT.Body.Allergies;
using Content.Shared.ADT.Body.Allergies.Prototypes;
using Content.Shared.EntityEffects;
using Robust.Shared.Timing;

namespace Content.Server.ADT.Body;

public sealed partial class AllergicSystem : EntitySystem
{
private List<AllergicReactionPrototype> _reactions = new();

[Dependency] private IGameTiming _timing = default!;
[Dependency] private SharedEntityEffectsSystem _effectSystem = default!;

public void InitializeShock()
{
SubscribeLocalEvent<AllergicComponent, AllergyFadedEvent>(Unshock);
_reactions = _proto.EnumeratePrototypes<AllergicReactionPrototype>()
.OrderBy(r => r.StackThreshold)
.ToList();
}

private void Unshock(EntityUid uid, AllergicComponent allergic, ref AllergyFadedEvent ev)
{
allergic.NextShockEvent = TimeSpan.Zero;
}

private void AssignNextShockTiming(AllergicComponent allergic)
{
allergic.NextShockEvent = _timing.CurTime + TimeSpan.FromSeconds(_random.NextFloat(allergic.MinimumTimeTilNextShockEvent, allergic.MaximumTimeTilNextShockEvent));
}

private void UpdateShock(EntityUid uid, AllergicComponent allergic)
{
if (allergic.AllergyStack <= 0)
return;

if (allergic.NextShockEvent == TimeSpan.Zero)
{
AssignNextShockTiming(allergic);
return;
}

if (allergic.NextShockEvent > _timing.CurTime)
return;

AllergicReactionPrototype? picked = null;

foreach (var reaction in _reactions)
{
if (allergic.AllergyStack >= reaction.StackThreshold)
picked = reaction;
}

if (picked == null)
return;

foreach (var effect in picked.Effects)
{
_effectSystem.ApplyEffect(uid, effect);
}

AssignNextShockTiming(allergic);
}
}
62 changes: 62 additions & 0 deletions Content.Server/ADT/Body/AllergicSystem.Stacks.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
using System.Linq;
using Content.Shared.ADT.Body.Allergies;
using Content.Shared.Chemistry.Reagent;
using Robust.Shared.Prototypes;

namespace Content.Server.ADT.Body;

public sealed partial class AllergicSystem : EntitySystem
{
#region Events

private void IncrementStackOnTrigger(EntityUid uid, AllergicComponent allergic, ref AllergyTriggeredEvent ev)
{
AdjustAllergyStack(uid, allergic.StackGrow, allergic);
}

#endregion

#region Flow

private void UpdateStack(EntityUid uid, AllergicComponent allergic)
{
if (allergic.AllergyStack <= 0)
return;

if (allergic.NextStackFade > _timing.CurTime)
return;

float newStack = allergic.AllergyStack + allergic.StackFade;
SetAllergyStack(uid, newStack, allergic);

if (newStack <= 0)
{
var faded = new AllergyFadedEvent();
RaiseLocalEvent(uid, ref faded);
}

allergic.NextStackFade = allergic.NextStackFade + allergic.StackFadeRate;
}

#endregion

#region API

public void AdjustAllergyStack(EntityUid uid, float relativeStack, AllergicComponent? allergic = null)
{
if (!Resolve(uid, ref allergic))
return;

SetAllergyStack(uid, allergic.AllergyStack + relativeStack, allergic);
}

public void SetAllergyStack(EntityUid uid, float stack, AllergicComponent? allergic = null)
{
if (!Resolve(uid, ref allergic))
return;

allergic.AllergyStack = MathF.Min(MathF.Max(0, stack), allergic.MaximumStack);
}

#endregion
}
105 changes: 105 additions & 0 deletions Content.Server/ADT/Body/AllergicSystem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
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;
using Robust.Shared.Timing;

namespace Content.Server.ADT.Body;

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

private ProtoId<DamageTypePrototype> _allergyDamageType = "Poison";
private DamageTypePrototype? _allergyDamageTypeProto;

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

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

SubscribeLocalEvent<AllergicComponent, AllergyTriggeredEvent>(OnAllergyTriggered);

InitializeShock();

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

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.25);
var damageEffect = new HealthChange
{
Damage = damageSpecifier
};

AllergyTriggeredEvent triggered = new();
RaiseLocalEvent(uid, ref triggered);

ev.Effects = ev.Effects.Append(damageEffect).ToArray();
}

private void OnAllergyTriggered(EntityUid uid, AllergicComponent allergic, ref AllergyTriggeredEvent ev)
{
IncrementStackOnTrigger(uid, allergic, ref ev);
}

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 override void Update(float frameTime)
{
base.Update(frameTime);

var query = EntityQueryEnumerator<AllergicComponent>();

while (query.MoveNext(out var uid, out var allergic))
{
UpdateStack(uid, allergic);
UpdateShock(uid, allergic);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
using Content.Server.ADT.Body;
using Content.Shared.ADT.Body.Allergies;
using Content.Shared.EntityEffects;
using Content.Shared.EntityEffects.Effects;

namespace Content.Server.ADT.EntityEffects;

/// <summary>
/// Эффект для изменения значения стака аллергии.
/// </summary>
public sealed partial class AdjustAllergicStackEntityEffectSystem : EntityEffectSystem<AllergicComponent, AdjustAllergicStack>
{
[Dependency] private AllergicSystem _allergic = default!;

protected override void Effect(Entity<AllergicComponent> entity, ref EntityEffectEvent<AdjustAllergicStack> args)
{
_allergic.AdjustAllergyStack(entity, args.Effect.Amount * args.Scale);
}
}
Loading
Loading