Mega fixes

This commit is contained in:
Charlotte Tezuka
2025-11-19 18:58:18 +02:00
parent a6d3ede17f
commit f15fbe5c52
71 changed files with 870 additions and 915 deletions

View File

@@ -1,5 +1,6 @@
using Content.Shared._Offbrand.Wounds;
using Content.Shared.Damage;
using Content.Shared.Damage.Components;
using Content.Shared.FixedPoint;
using Content.Shared.MedicalScanner;
using Robust.Client.AutoGenerated;

View File

@@ -1,5 +1,6 @@
using Content.Shared._Offbrand.Wounds;
using Content.Shared.Damage;
using Content.Shared.Damage.Components;
using Content.Shared.FixedPoint;
using Content.Shared.MedicalScanner;
using Robust.Client.AutoGenerated;

View File

@@ -1,4 +1,5 @@
using Content.Server.Body.Components;
using Content.Shared.Administration.Logs;
using Content.Shared.Body.Events;
using Content.Shared.Body.Organ;
using Content.Shared.Body.Prototypes;
@@ -34,6 +35,10 @@ public sealed class MetabolizerSystem : SharedMetabolizerSystem
[Dependency] private readonly SharedEntityConditionsSystem _entityConditions = default!;
[Dependency] private readonly SharedEntityEffectsSystem _entityEffects = default!;
[Dependency] private readonly SharedSolutionContainerSystem _solutionContainerSystem = default!;
//Start Offbrand WL
[Dependency] private readonly ISharedAdminLogManager _adminLogger = default!;
[Dependency] private readonly Content.Shared.StatusEffectNew.StatusEffectsSystem _statusEffects = default!;
//End Offbrand WL
private EntityQuery<OrganComponent> _organQuery;
private EntityQuery<SolutionContainerManagerComponent> _solutionQuery;
@@ -41,21 +46,14 @@ public sealed class MetabolizerSystem : SharedMetabolizerSystem
public override void Initialize()
{
[Dependency] private readonly IGameTiming _gameTiming = default!;
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
[Dependency] private readonly IRobustRandom _random = default!;
[Dependency] private readonly ISharedAdminLogManager _adminLogger = default!;
[Dependency] private readonly MobStateSystem _mobStateSystem = default!;
[Dependency] private readonly SharedSolutionContainerSystem _solutionContainerSystem = default!;
[Dependency] private readonly Content.Shared.StatusEffectNew.StatusEffectsSystem _statusEffects = default!;
base.Initialize();
_organQuery = GetEntityQuery<OrganComponent>();
_solutionQuery = GetEntityQuery<SolutionContainerManagerComponent>();
SubscribeLocalEvent<MetabolizerComponent, ComponentInit>(OnMetabolizerInit);
SubscribeLocalEvent<MetabolizerComponent, MapInitEvent>(OnMapInit);
SubscribeLocalEvent<MetabolizerComponent, ApplyMetabolicMultiplierEvent>(OnApplyMetabolicMultiplier);
//base.Initialize();
}
private void OnMapInit(Entity<MetabolizerComponent> ent, ref MapInitEvent args)
@@ -71,262 +69,13 @@ public sealed class MetabolizerSystem : SharedMetabolizerSystem
}
else if (_organQuery.CompOrNull(entity)?.Body is { } body)
{
ent.Comp.NextUpdate = _gameTiming.CurTime + ent.Comp.AdjustedUpdateInterval;
entity.Comp.NextUpdate = _gameTiming.CurTime + entity.Comp.AdjustedUpdateInterval;
}
}
private void OnUnpaused(Entity<MetabolizerComponent> ent, ref EntityUnpausedEvent args)
{
ent.Comp.NextUpdate += args.PausedTime;
}
private void OnMetabolizerInit(Entity<MetabolizerComponent> entity, ref ComponentInit args)
{
if (!entity.Comp.SolutionOnBody)
{
_solutionContainerSystem.EnsureSolution(entity.Owner, entity.Comp.SolutionName, out _);
}
else if (_organQuery.CompOrNull(entity)?.Body is { } body)
{
_solutionContainerSystem.EnsureSolution(body, entity.Comp.SolutionName, out _);
}
}
private void OnApplyMetabolicMultiplier(Entity<MetabolizerComponent> ent, ref ApplyMetabolicMultiplierEvent args)
{
ent.Comp.UpdateIntervalMultiplier = args.Multiplier;
}
public override void Update(float frameTime)
{
base.Update(frameTime);
var metabolizers = new ValueList<(EntityUid Uid, MetabolizerComponent Component)>(Count<MetabolizerComponent>());
var query = EntityQueryEnumerator<MetabolizerComponent>();
while (query.MoveNext(out var uid, out var comp))
{
metabolizers.Add((uid, comp));
}
foreach (var (uid, metab) in metabolizers)
{
// Only update as frequently as it should
if (_gameTiming.CurTime < metab.NextUpdate)
continue;
metab.NextUpdate += metab.AdjustedUpdateInterval;
TryMetabolize((uid, metab));
}
}
private void TryMetabolize(Entity<MetabolizerComponent, OrganComponent?, SolutionContainerManagerComponent?> ent)
{
_organQuery.Resolve(ent, ref ent.Comp2, logMissing: false);
// First step is get the solution we actually care about
var solutionName = ent.Comp1.SolutionName;
Solution? solution = null;
Entity<SolutionComponent>? soln = default!;
EntityUid? solutionEntityUid = null;
if (ent.Comp1.SolutionOnBody)
{
if (ent.Comp2?.Body is { } body)
{
if (!_solutionQuery.Resolve(body, ref ent.Comp3, logMissing: false))
return;
_solutionContainerSystem.TryGetSolution((body, ent.Comp3), solutionName, out soln, out solution);
solutionEntityUid = body;
}
}
else
{
if (!_solutionQuery.Resolve(ent, ref ent.Comp3, logMissing: false))
return;
_solutionContainerSystem.TryGetSolution((ent, ent), solutionName, out soln, out solution);
solutionEntityUid = ent;
}
if (solutionEntityUid is null
|| soln is null
|| solution is null
|| (solution.Contents.Count == 0 && ent.Comp1.MetabolizingReagents.Count == 0 && ent.Comp1.Metabolites.Count == 0)) // Offbrand - we need to ensure we clear out metabolizing reagents
{
return;
}
// randomize the reagent list so we don't have any weird quirks
// like alphabetical order or insertion order mattering for processing
var list = solution.Contents.ToArray();
_random.Shuffle(list);
var metabolized = new HashSet<ProtoId<ReagentPrototype>>();
int reagents = 0;
foreach (var (reagent, quantity) in list)
{
if (!_prototypeManager.TryIndex<ReagentPrototype>(reagent.Prototype, out var proto))
continue;
var mostToRemove = FixedPoint2.Zero;
if (proto.Metabolisms is null)
{
if (ent.Comp1.RemoveEmpty)
{
solution.RemoveReagent(reagent, FixedPoint2.New(1));
}
continue;
}
// Begin Offbrand - No we're not
// we're done here entirely if this is true
// if (reagents >= ent.Comp1.MaxReagentsProcessable)
// return;
// End Offbrand
metabolized.Add(reagent.Prototype); // Offbrand
// loop over all our groups and see which ones apply
if (ent.Comp1.MetabolismGroups is null)
continue;
foreach (var group in ent.Comp1.MetabolismGroups)
{
if (!proto.Metabolisms.TryGetValue(group.Id, out var entry))
continue;
var rate = entry.MetabolismRate * group.MetabolismRateModifier;
// Remove $rate, as long as there's enough reagent there to actually remove that much
mostToRemove = FixedPoint2.Clamp(rate, 0, quantity);
float scale = (float) mostToRemove / (float) rate;
// if it's possible for them to be dead, and they are,
// then we shouldn't process any effects, but should probably
// still remove reagents
if (TryComp<MobStateComponent>(solutionEntityUid.Value, out var state))
{
if (!proto.WorksOnTheDead && _mobStateSystem.IsDead(solutionEntityUid.Value, state))
continue;
}
var actualEntity = ent.Comp2?.Body ?? solutionEntityUid.Value;
var args = new EntityEffectReagentArgs(actualEntity, EntityManager, ent, solution, mostToRemove, proto, null, scale);
// Begin Offbrand
foreach (var effect in entry.StatusEffects)
{
if (!effect.ShouldApplyStatusEffect(args))
_statusEffects.TryRemoveStatusEffect(actualEntity, effect.StatusEffect);
else
_statusEffects.TryUpdateStatusEffectDuration(actualEntity, effect.StatusEffect, out _);
}
// End Offbrand
// do all effects, if conditions apply
foreach (var effect in entry.Effects)
{
if (!effect.ShouldApply(args, _random))
continue;
if (effect.ShouldLog)
{
_adminLogger.Add(
LogType.ReagentEffect,
effect.LogImpact,
$"Metabolism effect {effect.GetType().Name:effect}"
+ $" of reagent {proto.LocalizedName:reagent}"
+ $" applied on entity {actualEntity:entity}"
+ $" at {Transform(actualEntity).Coordinates:coordinates}"
);
}
effect.Effect(args);
}
}
// remove a certain amount of reagent
if (mostToRemove > FixedPoint2.Zero)
{
var removed = solution.RemoveReagent(reagent, mostToRemove); // Offbrand
// We have processed a reagant, so count it towards the cap
reagents += 1;
// Begin Offbrand
if (!ent.Comp1.Metabolites.ContainsKey(reagent.Prototype))
ent.Comp1.Metabolites[reagent.Prototype] = 0;
ent.Comp1.Metabolites[reagent.Prototype] += removed;
// End Offbrand
}
}
// Begin Offbrand
foreach (var reagent in ent.Comp1.MetabolizingReagents)
{
if (metabolized.Contains(reagent))
continue;
var proto = _prototypeManager.Index(reagent);
var actualEntity = ent.Comp2?.Body ?? solutionEntityUid.Value;
if (ent.Comp1.MetabolismGroups is null)
continue;
foreach (var group in ent.Comp1.MetabolismGroups)
{
if (proto.Metabolisms is null)
continue;
if (!proto.Metabolisms.TryGetValue(group.Id, out var entry))
continue;
foreach (var effect in entry.StatusEffects)
{
_statusEffects.TryRemoveStatusEffect(actualEntity, effect.StatusEffect);
}
}
}
ent.Comp1.MetabolizingReagents = metabolized;
foreach (var metaboliteReagent in ent.Comp1.Metabolites.Keys)
{
if (ent.Comp1.MetabolizingReagents.Contains(metaboliteReagent))
continue;
if (!_prototypeManager.Resolve(metaboliteReagent, out var proto) || proto.Metabolisms is not { } metabolisms)
continue;
if (ent.Comp1.MetabolismGroups is null)
continue;
ReagentEffectsEntry? entry = null;
var metabolismRateModifier = FixedPoint2.Zero;
foreach (var group in ent.Comp1.MetabolismGroups)
{
if (!proto.Metabolisms.TryGetValue(group.Id, out entry))
continue;
metabolismRateModifier = group.MetabolismRateModifier;
break;
}
if (entry is not { } metabolismEntry)
continue;
var rate = metabolismEntry.MetabolismRate * metabolismRateModifier * ent.Comp1.MetaboliteDecayFactor;
ent.Comp1.Metabolites[metaboliteReagent] -= rate;
if (ent.Comp1.Metabolites[metaboliteReagent] <= 0)
ent.Comp1.Metabolites.Remove(metaboliteReagent);
}
// End Offbrand
_solutionContainerSystem.EnsureSolution(body, entity.Comp.SolutionName, out _);
}
private void OnUnpaused(Entity<MetabolizerComponent> ent, ref EntityUnpausedEvent args)
{
ent.Comp.NextUpdate += args.PausedTime;
}
private void OnApplyMetabolicMultiplier(Entity<MetabolizerComponent> ent, ref ApplyMetabolicMultiplierEvent args)
@@ -390,7 +139,7 @@ public sealed class MetabolizerSystem : SharedMetabolizerSystem
if (solutionEntityUid is null
|| soln is null
|| solution is null
|| solution.Contents.Count == 0)
|| (solution.Contents.Count == 0 && ent.Comp1.MetabolizingReagents.Count == 0 && ent.Comp1.Metabolites.Count == 0)) // Offbrand - we need to ensure we clear out metabolizing reagents
{
return;
}
@@ -400,6 +149,7 @@ public sealed class MetabolizerSystem : SharedMetabolizerSystem
var list = solution.Contents.ToArray();
_random.Shuffle(list);
var metabolized = new HashSet<ProtoId<ReagentPrototype>>();
int reagents = 0;
foreach (var (reagent, quantity) in list)
{
@@ -417,16 +167,17 @@ public sealed class MetabolizerSystem : SharedMetabolizerSystem
continue;
}
// Begin Offbrand - No we're not
// we're done here entirely if this is true
if (reagents >= ent.Comp1.MaxReagentsProcessable)
return;
// if (reagents >= ent.Comp1.MaxReagentsProcessable)
// return;
// End Offbrand
metabolized.Add(reagent.Prototype); // Offbrand
// loop over all our groups and see which ones apply
if (ent.Comp1.MetabolismGroups is null)
continue;
// TODO: Kill MetabolismGroups!
foreach (var group in ent.Comp1.MetabolismGroups)
{
if (!proto.Metabolisms.TryGetValue(group.Id, out var entry))
@@ -437,12 +188,7 @@ public sealed class MetabolizerSystem : SharedMetabolizerSystem
// Remove $rate, as long as there's enough reagent there to actually remove that much
mostToRemove = FixedPoint2.Clamp(rate, 0, quantity);
var scale = (float) mostToRemove;
// TODO: This is a very stupid workaround to lungs heavily relying on scale = reagent quantity. Needs lung and metabolism refactors to remove.
// TODO: Lungs just need to have their scale be equal to the mols consumed, scale needs to be not hardcoded either and configurable per metabolizer...
if (group.Id != Gas)
scale /= (float) entry.MetabolismRate;
float scale = (float) mostToRemove / (float) rate;
// if it's possible for them to be dead, and they are,
// then we shouldn't process any effects, but should probably
@@ -454,6 +200,19 @@ public sealed class MetabolizerSystem : SharedMetabolizerSystem
}
var actualEntity = ent.Comp2?.Body ?? solutionEntityUid.Value;
//var args = new EntityEffectReagentArgs(actualEntity, EntityManager, ent, solution, mostToRemove, proto, null, scale);
// Begin Offbrand
/*
foreach (var effect in entry.StatusEffects)
{
if (!effect.ShouldApplyStatusEffect(args))
_statusEffects.TryRemoveStatusEffect(actualEntity, effect.StatusEffect);
else
_statusEffects.TryUpdateStatusEffectDuration(actualEntity, effect.StatusEffect, out _);
}
*/
// End Offbrand
// do all effects, if conditions apply
foreach (var effect in entry.Effects)
@@ -469,7 +228,6 @@ public sealed class MetabolizerSystem : SharedMetabolizerSystem
continue;
ApplyEffect(effect);
}
// TODO: We should have to do this with metabolism. ReagentEffect struct needs refactoring and so does metabolism!
@@ -493,25 +251,86 @@ public sealed class MetabolizerSystem : SharedMetabolizerSystem
// remove a certain amount of reagent
if (mostToRemove > FixedPoint2.Zero)
{
solution.RemoveReagent(reagent, mostToRemove);
var removed = solution.RemoveReagent(reagent, mostToRemove); // Offbrand
// We have processed a reagant, so count it towards the cap
reagents += 1;
// Begin Offbrand
if (!ent.Comp1.Metabolites.ContainsKey(reagent.Prototype))
ent.Comp1.Metabolites[reagent.Prototype] = 0;
ent.Comp1.Metabolites[reagent.Prototype] += removed;
// End Offbrand
}
}
// Begin Offbrand
/*
foreach (var reagent in ent.Comp1.MetabolizingReagents)
{
if (metabolized.Contains(reagent))
continue;
var proto = _prototypeManager.Index(reagent);
var actualEntity = ent.Comp2?.Body ?? solutionEntityUid.Value;
if (ent.Comp1.MetabolismGroups is null)
continue;
foreach (var group in ent.Comp1.MetabolismGroups)
{
if (proto.Metabolisms is null)
continue;
if (!proto.Metabolisms.TryGetValue(group.Id, out var entry))
continue;
foreach (var effect in entry.StatusEffects)
{
_statusEffects.TryRemoveStatusEffect(actualEntity, effect.StatusEffect);
}
}
}
*/
ent.Comp1.MetabolizingReagents = metabolized;
foreach (var metaboliteReagent in ent.Comp1.Metabolites.Keys)
{
if (ent.Comp1.MetabolizingReagents.Contains(metaboliteReagent))
continue;
if (!_prototypeManager.Resolve(metaboliteReagent, out var proto) || proto.Metabolisms is not { } metabolisms)
continue;
if (ent.Comp1.MetabolismGroups is null)
continue;
ReagentEffectsEntry? entry = null;
var metabolismRateModifier = FixedPoint2.Zero;
foreach (var group in ent.Comp1.MetabolismGroups)
{
if (!proto.Metabolisms.TryGetValue(group.Id, out entry))
continue;
metabolismRateModifier = group.MetabolismRateModifier;
break;
}
if (entry is not { } metabolismEntry)
continue;
var rate = metabolismEntry.MetabolismRate * metabolismRateModifier * ent.Comp1.MetaboliteDecayFactor;
ent.Comp1.Metabolites[metaboliteReagent] -= rate;
if (ent.Comp1.Metabolites[metaboliteReagent] <= 0)
ent.Comp1.Metabolites.Remove(metaboliteReagent);
}
// End Offbrand
_solutionContainerSystem.UpdateChemicals(soln.Value);
}
/// <summary>
/// Public API to check if a certain metabolism effect can be applied to an entity.
/// TODO: With metabolism refactor make this logic smarter and unhardcode the old hardcoding entity effects used to have for metabolism!
/// </summary>
/// <param name="body">The body metabolizing the effects</param>
/// <param name="organ">The organ doing the metabolizing</param>
/// <param name="solution">The solution we are metabolizing from</param>
/// <param name="conditions">The conditions that need to be met to metabolize</param>
/// <returns>True if we can metabolize! False if we cannot!</returns>
public bool CanMetabolizeEffect(EntityUid body, EntityUid organ, Entity<SolutionComponent> solution, EntityCondition[] conditions)
{
foreach (var condition in conditions)
@@ -540,4 +359,3 @@ public sealed class MetabolizerSystem : SharedMetabolizerSystem
return true;
}
}

View File

@@ -211,7 +211,7 @@ public sealed partial class RevenantSystem
//KILL THEMMMM
_damage.TryChangeDamage(args.Args.Target, component.HarvestDamage, true, origin: uid); // Offbrand - use a fixed amount
_damage.TryChangeDamage(args.Args.Target.Value, component.HarvestDamage, true, origin: uid); // Offbrand - use a fixed amount
args.Handled = true;
}

View File

@@ -275,15 +275,15 @@ namespace Content.Server.Zombies
{
if (HasComp<ZombieImmuneComponent>(uid) || cannotSpread)
continue;
if (_mobState.IsIncapacitated(entity, mobState) && !HasComp<ZombieComponent>(entity) && !HasComp<ZombieImmuneComponent>(entity) && !HasComp<WoundableComponent>(entity)) // Offbrand
{
ZombifyEntity(entity);
args.BonusDamage = -args.BaseDamage;
}
else if (mobState.CurrentState == MobState.Alive) //heals when zombies bite live entities
else
{
_damageable.TryChangeDamage(uid, component.HealingOnBite, true, false);
if (HasComp<ZombieImmuneComponent>(uid) || cannotSpread)
continue;
// If the target is dead and can be infected, infect.
ZombifyEntity(uid);
args.Handled = true;
}
}
}

View File

@@ -1,6 +1,8 @@
using Content.Server.Body.Components;
using Content.Shared._Offbrand.EntityEffects;
using Content.Shared.Chemistry.Components;
using Content.Shared.EntityEffects;
using Content.Shared.EntityConditions;
using Content.Shared.FixedPoint;
namespace Content.Server._Offbrand.EntityEffects;
@@ -11,38 +13,32 @@ public sealed class MetaboliteThresholdSystem : EntitySystem
{
base.Initialize();
SubscribeLocalEvent<CheckEntityEffectConditionEvent<MetaboliteThreshold>>(OnCheckMetaboliteThreshold);
SubscribeLocalEvent<MetabolizerComponent, EntityConditionEvent<MetaboliteCondition>>(OnCheckMetaboliteThreshold);
}
private void OnCheckMetaboliteThreshold(ref CheckEntityEffectConditionEvent<MetaboliteThreshold> args)
private void OnCheckMetaboliteThreshold(Entity<MetabolizerComponent> entity, ref EntityConditionEvent<MetaboliteCondition> args)
{
if (args.Args is not EntityEffectReagentArgs reagentArgs)
throw new NotImplementedException();
var reagent = args.Condition.Reagent;
if (reagent == null)
reagent = reagentArgs.Reagent?.ID;
return;
if (reagent is not { } metaboliteReagent)
{
args.Result = true;
return;
}
if (!TryComp<MetabolizerComponent>(reagentArgs.OrganEntity, out var metabolizer))
{
args.Result = true;
if (!TryComp<MetabolizerComponent>(entity, out var metabolizer))
return;
if (!TryComp<SolutionComponent>(entity, out var solution))
return;
}
var metabolites = metabolizer.Metabolites;
var quant = FixedPoint2.Zero;
metabolites.TryGetValue(metaboliteReagent, out quant);
if (args.Condition.IncludeBloodstream && reagentArgs.Source != null)
if (args.Condition.IncludeBloodstream && solution.Solution != null)
{
quant += reagentArgs.Source.GetTotalPrototypeQuantity(metaboliteReagent);
quant += solution.Solution.GetTotalPrototypeQuantity(metaboliteReagent);
}
args.Result = quant >= args.Condition.Min && quant <= args.Condition.Max;

View File

@@ -1,3 +1,4 @@
/*
using Content.Server.Zombies;
using Content.Shared._Offbrand.EntityEffects;
using Content.Shared.EntityEffects;
@@ -15,8 +16,9 @@ public sealed class ZombifySystem : EntitySystem
SubscribeLocalEvent<ExecuteEntityEffectEvent<Zombify>>(OnExecuteZombify);
}
private void OnExecuteZombify(ref ExecuteEntityEffectEvent<Zombify> args)
private void OnExecuteZombify(ref EntityEffectEvent<Zombify> args)
{
_zombie.ZombifyEntity(args.Args.TargetEntity);
}
}
*/

View File

@@ -3,7 +3,9 @@ using Content.Server.Chat.Systems;
using Content.Server.EUI;
using Content.Shared._Offbrand.MMI;
using Content.Shared._Offbrand.Wounds;
using Content.Shared.Body.Components;
using Content.Shared.Body.Systems;
using Content.Shared.Chat;
using Content.Shared.Containers.ItemSlots;
using Content.Shared.DoAfter;
using Content.Shared.Interaction;

View File

@@ -1,9 +1,9 @@
using Content.Server.Temperature.Components;
using Content.Shared._Offbrand.Wounds;
using Content.Shared.Body.Events;
using Content.Shared.Body.Systems;
using Content.Shared.Medical.Cryogenics;
using Content.Shared.Temperature;
using Content.Shared.Temperature.Components;
namespace Content.Server._Offbrand.Wounds;

View File

@@ -1,4 +1,4 @@
using Content.Server.Temperature.Components;
using Content.Shared.Temperature.Components;
using Content.Shared._Offbrand.Wounds;
namespace Content.Server._Offbrand.Wounds;

View File

@@ -6,6 +6,7 @@ using Content.Shared.Body.Prototypes;
using Content.Shared.Chemistry.Reaction;
using Content.Shared.Contraband;
using Content.Shared.EntityEffects;
using Content.Shared.EntityConditions;
using Content.Shared.Localizations;
using Content.Shared.Nutrition;
using Content.Shared.Roles;
@@ -208,9 +209,10 @@ namespace Content.Shared.Chemistry.Reagent
return removed;
}
public IEnumerable<string> GuidebookReagentEffectsDescription(IPrototypeManager prototype, IEntitySystemManager entSys, IEnumerable<EntityEffect> effects, FixedPoint2? metabolism = null)
public IEnumerable<string> GuidebookReagentEffectsDescription(IPrototypeManager prototype, IEntitySystemManager entSys, IEnumerable<EntityEffect> effects, FixedPoint2? metabolism = null/*WL-Offbrand start*List<ReagentStatusEffectEntry> StatusEffects = new()*WL-Offbrand end*/)
{
return effects.Select(x => GuidebookReagentEffectDescription(prototype, entSys, x, metabolism))
//.Concat(StatusEffects.Select(x => x.Describe(prototype, entSys))) // Offbrand
.Where(x => x is not null)
.Select(x => x!)
.ToArray();
@@ -275,8 +277,8 @@ namespace Content.Shared.Chemistry.Reagent
/// <summary>
/// Offbrand: Status effects to apply whilst this reagent is metabolising
/// </summary>
[DataField]
public List<ReagentStatusEffectEntry> StatusEffects = new();
//[DataField]
//public List<ReagentStatusEffectEntry> StatusEffects = new();
/// <summary>
/// A list of effects to apply when these reagents are metabolized.
@@ -289,27 +291,22 @@ namespace Content.Shared.Chemistry.Reagent
public ReagentEffectsGuideEntry MakeGuideEntry(IPrototypeManager prototype, IEntitySystemManager entSys, ReagentPrototype proto)
{
return new ReagentEffectsGuideEntry(MetabolismRate,
Effects
.Select(x => x.GuidebookEffectDescription(prototype, entSys)) // hate.
.Concat(StatusEffects.Select(x => x.Describe(prototype, entSys))) // Offbrand
.Where(x => x is not null)
.Select(x => x!)
.ToArray());
return new ReagentEffectsGuideEntry(MetabolismRate, proto.GuidebookReagentEffectsDescription(prototype, entSys, Effects, MetabolismRate).ToArray());
}
}
// Begin Offbrand
/*
[DataDefinition]
public sealed partial class ReagentStatusEffectEntry
{
[DataField]
public EntityEffectCondition[]? Conditions;
public EntityConditionBase[]? Conditions;
[DataField]
public EntProtoId StatusEffect;
public bool ShouldApplyStatusEffect(EntityEffectBaseArgs args)
public bool ShouldApplyStatusEffect(EntityEffectBase args)
{
if (Conditions != null)
{
@@ -333,10 +330,10 @@ namespace Content.Shared.Chemistry.Reagent
return Loc.GetString("reagent-guidebook-status-effect", ("effect", locName), //WL-Changes-offbrand-ftl-fix // effectProtoData.Name ?? string.Empty -> locName
("conditionCount", Conditions?.Length ?? 0),
("conditions",
Content.Shared.Localizations.ContentLocalizationManager.FormatList(Conditions?.Select(x => x.GuidebookExplanation(prototype)).ToList() ??
new List<string>())));
Content.Shared.Localizations.ContentLocalizationManager.FormatList(Conditions?.Select(x => x.GuidebookExplanation(prototype)).ToList() ?? new List<string>())));
}
}
*/
// End Offbrand
[Serializable, NetSerializable]

View File

@@ -139,7 +139,7 @@ public sealed partial class DamageableSystem
// Begin Offbrand
var beforeCommit = new Content.Shared._Offbrand.Wounds.BeforeDamageCommitEvent(damage, forceRefresh);
RaiseLocalEvent(uid.Value, ref beforeCommit);
RaiseLocalEvent(ent, ref beforeCommit);
damage = beforeCommit.Damage;
// End Offbrand

View File

@@ -272,7 +272,7 @@ public sealed class DamageChangedEvent : EntityEventArgs
DamageSpecifier? damageDelta,
bool interruptsDoAfters,
EntityUid? origin,
ForcedRefresh = forcedRefresh; // Offbrand
bool forcedRefresh = false // Offbrand
)
{
Damageable = damageable;

View File

@@ -1,3 +1,4 @@
using Content.Shared._Offbrand.Wounds;
using Content.Shared.Mobs;
using Content.Shared.Mobs.Components;
using Robust.Shared.Prototypes;
@@ -10,6 +11,8 @@ namespace Content.Shared.EntityConditions.Conditions.Body;
/// <inheritdoc cref="EntityConditionSystem{T, TCondition}"/>
public sealed partial class MobStateEntityConditionSystem : EntityConditionSystem<MobStateComponent, MobStateCondition>
{
[Dependency] private readonly HealthRankingSystem _healthRanking = default!; //Offbrand
protected override void Condition(Entity<MobStateComponent> entity, ref EntityConditionEvent<MobStateCondition> args)
{
if (entity.Comp.CurrentState == args.Condition.Mobstate)
@@ -17,8 +20,7 @@ public sealed partial class MobStateEntityConditionSystem : EntityConditionSyste
// Begin Offbrand
if (args.Condition.Mobstate == MobState.Critical)
{
if (args.EntityManager.System<Content.Shared._Offbrand.Wounds.HealthRankingSystem>()
.IsCritical(args.TargetEntity))
if (_healthRanking.IsCritical(entity))
{
args.Result = true;
}

View File

@@ -1,4 +1,4 @@
using Content.Shared.Mobs.Components;
using Content.Shared.Mobs.Components;
using Content.Shared.Zombies;
using Robust.Shared.Prototypes;

View File

@@ -42,7 +42,7 @@ public sealed partial class StatusEffectsSystem
SubscribeLocalEvent<StatusEffectContainerComponent, Content.Shared._Offbrand.Weapons.RelayedGetMeleeDamageEvent>(RefRelayStatusEffectEvent); // Offbrand
SubscribeLocalEvent<StatusEffectContainerComponent, Content.Shared._Offbrand.Weapons.RelayedGetMeleeAttackRateEvent>(RefRelayStatusEffectEvent); // Offbrand
SubscribeLocalEvent<StatusEffectContainerComponent, Content.Shared._Offbrand.Weapons.RelayedGunRefreshModifiersEvent>(RefRelayStatusEffectEvent); // Offbrand
SubscribeLocalEvent<StatusEffectContainerComponent, Content.Shared.Damage.ModifySlowOnDamageSpeedEvent>(RefRelayStatusEffectEvent); // Offbrand
SubscribeLocalEvent<StatusEffectContainerComponent, Content.Shared.Damage.Systems.ModifySlowOnDamageSpeedEvent>(RefRelayStatusEffectEvent); // Offbrand
SubscribeLocalEvent<StatusEffectContainerComponent, Content.Shared.Eye.Blinding.Systems.GetBlurEvent>(RelayStatusEffectEvent); // Offbrand
SubscribeLocalEvent<StatusEffectContainerComponent, Content.Shared.Eye.Blinding.Systems.CanSeeAttemptEvent>(RelayStatusEffectEvent); // Offbrand
SubscribeLocalEvent<StatusEffectContainerComponent, Content.Shared.IdentityManagement.Components.SeeIdentityAttemptEvent>(RelayStatusEffectEvent); // Offbrand
@@ -50,7 +50,7 @@ public sealed partial class StatusEffectsSystem
SubscribeLocalEvent<StatusEffectContainerComponent, Content.Shared.Movement.Pulling.Events.PullStoppedMessage>(RelayStatusEffectEvent); // Offbrand
SubscribeLocalEvent<StatusEffectContainerComponent, Content.Shared.Weapons.Ranged.Events.SelfBeforeGunShotEvent>(RelayStatusEffectEvent); // Offbrand
SubscribeLocalEvent<StatusEffectContainerComponent, Content.Shared.Chemistry.Hypospray.Events.SelfBeforeHyposprayInjectsEvent>(RelayStatusEffectEvent); // Offbrand
SubscribeLocalEvent<StatusEffectContainerComponent, Content.Shared.Damage.DamageChangedEvent>(RelayStatusEffectEvent); // Offbrand
SubscribeLocalEvent<StatusEffectContainerComponent, Content.Shared.Damage.Systems.DamageChangedEvent>(RelayStatusEffectEvent); // Offbrand
SubscribeLocalEvent<StatusEffectContainerComponent, Content.Shared.Examine.ExaminedEvent>(RelayStatusEffectEvent); // Offbrand
SubscribeLocalEvent<StatusEffectContainerComponent, Content.Shared.Verbs.GetVerbsEvent<Content.Shared.Verbs.AlternativeVerb>>(RelayStatusEffectEvent); // Offbrand
}

View File

@@ -1,54 +0,0 @@
using Content.Shared.Chemistry.Reagent;
using Content.Shared.EntityEffects;
using Content.Shared.FixedPoint;
using Content.Shared.Random.Helpers;
using Robust.Shared.Prototypes;
using Robust.Shared.Random;
using Robust.Shared.Timing;
namespace Content.Shared._Offbrand.EntityEffects;
public sealed partial class AdjustReagentGaussian : EntityEffect
{
[DataField(required: true)]
public ProtoId<ReagentPrototype> Reagent;
[DataField(required: true)]
public double μ;
[DataField(required: true)]
public double σ;
public override void Effect(EntityEffectBaseArgs args)
{
if (args is not EntityEffectReagentArgs reagentArgs)
throw new NotImplementedException();
if (reagentArgs.Source == null)
return;
var timing = IoCManager.Resolve<IGameTiming>();
var seed = SharedRandomExtensions.HashCodeCombine(new() { (int)timing.CurTick.Value, args.EntityManager.GetNetEntity(args.TargetEntity).Id });
var rand = new System.Random(seed);
var amount = rand.NextGaussian(μ, σ);
amount *= reagentArgs.Scale.Double();
if (amount < 0 && reagentArgs.Source.ContainsPrototype(Reagent))
reagentArgs.Source.RemoveReagent(Reagent, -amount);
else if (amount > 0)
reagentArgs.Source.AddReagent(Reagent, amount);
}
protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys)
{
var proto = prototype.Index(Reagent);
return Loc.GetString("reagent-effect-guidebook-adjust-reagent-gaussian",
("chance", Probability),
("deltasign", Math.Sign(μ)),
("reagent", proto.LocalizedName),
("mu", Math.Abs(μ)),
("sigma", Math.Abs(σ)));
}
}

View File

@@ -1,32 +0,0 @@
using Content.Shared._Offbrand.Wounds;
using Content.Shared.EntityEffects;
using Content.Shared.FixedPoint;
using Robust.Shared.Prototypes;
namespace Content.Shared._Offbrand.EntityEffects;
public sealed partial class BrainDamage : EntityEffectCondition
{
[DataField]
public FixedPoint2 Max = FixedPoint2.MaxValue;
[DataField]
public FixedPoint2 Min = FixedPoint2.Zero;
public override bool Condition(EntityEffectBaseArgs args)
{
if (args.EntityManager.TryGetComponent<BrainDamageComponent>(args.TargetEntity, out var brain))
{
return brain.Damage >= Min && brain.Damage <= Max;
}
return false;
}
public override string GuidebookExplanation(IPrototypeManager prototype)
{
return Loc.GetString("reagent-effect-condition-guidebook-brain-damage",
("max", Max == FixedPoint2.MaxValue ? (float) int.MaxValue : Max.Float()),
("min", Min.Float()));
}
}

View File

@@ -1,23 +0,0 @@
using Content.Shared._Offbrand.Wounds;
using Content.Shared.EntityEffects;
using Content.Shared.FixedPoint;
using Robust.Shared.Prototypes;
namespace Content.Shared._Offbrand.EntityEffects;
public sealed partial class ClampWounds : EntityEffect
{
[DataField(required: true)]
public float Chance;
protected override string ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys)
{
return Loc.GetString("reagent-effect-guidebook-clamp-wounds", ("probability", Probability), ("chance", Chance));
}
public override void Effect(EntityEffectBaseArgs args)
{
args.EntityManager.System<WoundableSystem>()
.ClampWounds(args.TargetEntity, Chance);
}
}

View File

@@ -0,0 +1,33 @@
using Content.Shared._Offbrand.Wounds;
using Content.Shared.EntityEffects;
using Content.Shared.EntityConditions;
using Content.Shared.FixedPoint;
using Robust.Shared.Prototypes;
namespace Content.Shared._Offbrand.EntityEffects;
public sealed partial class BrainDamageConditionSystem : EntityConditionSystem<BrainDamageComponent, BrainDamageCondition>
{
protected override void Condition(Entity<BrainDamageComponent> entity, ref EntityConditionEvent<BrainDamageCondition> args)
{
var damage = entity.Comp.Damage;
args.Result = damage >= args.Condition.Min && damage <= args.Condition.Max;
}
}
public sealed partial class BrainDamageCondition : EntityConditionBase<BrainDamageCondition>
{
[DataField]
public FixedPoint2 Max = FixedPoint2.MaxValue;
[DataField]
public FixedPoint2 Min = FixedPoint2.Zero;
public override string EntityConditionGuidebookText(IPrototypeManager prototype)
{
return Loc.GetString("reagent-effect-condition-guidebook-brain-damage",
("max", Max == FixedPoint2.MaxValue ? (float) int.MaxValue : Max.Float()),
("min", Min.Float()));
}
}

View File

@@ -0,0 +1,33 @@
using Content.Shared._Offbrand.Wounds;
using Content.Shared.EntityEffects;
using Content.Shared.EntityConditions;
using Content.Shared.FixedPoint;
using Robust.Shared.Prototypes;
namespace Content.Shared._Offbrand.EntityEffects;
public sealed partial class HeartDamageConditionSystem : EntityConditionSystem<HeartrateComponent, HeartDamageCondition>
{
protected override void Condition(Entity<HeartrateComponent> entity, ref EntityConditionEvent<HeartDamageCondition> args)
{
var damage = entity.Comp.Damage;
args.Result = damage >= args.Condition.Min && damage <= args.Condition.Max;
}
}
public sealed partial class HeartDamageCondition : EntityConditionBase<HeartDamageCondition>
{
[DataField]
public FixedPoint2 Max = FixedPoint2.MaxValue;
[DataField]
public FixedPoint2 Min = FixedPoint2.Zero;
public override string EntityConditionGuidebookText(IPrototypeManager prototype)
{
return Loc.GetString("reagent-effect-condition-guidebook-heart-damage",
("max", Max == FixedPoint2.MaxValue ? (float) int.MaxValue : Max.Float()),
("min", Min.Float()));
}
}

View File

@@ -0,0 +1,27 @@
using Content.Shared.EntityConditions;
using Content.Shared.EntityEffects;
using Content.Shared.Mobs.Components;
using Content.Shared.Zombies;
using Robust.Shared.Prototypes;
namespace Content.Shared._Offbrand.EntityEffects;
/// <inheritdoc cref="EntityConditionSystem{T, TCondition}"/>
public sealed partial class IsZombieConditionSystem : EntityConditionSystem<MobStateComponent, IsZombieCondition>
{
protected override void Condition(Entity<MobStateComponent> entity, ref EntityConditionEvent<IsZombieCondition> args)
{
args.Result = HasComp<ZombieComponent>(entity) ^ args.Condition.Invert;
}
}
public sealed partial class IsZombieCondition : EntityConditionBase<IsZombieCondition>
{
[DataField]
public bool Invert = false;
public override string EntityConditionGuidebookText(IPrototypeManager prototype)
{
return Loc.GetString("reagent-effect-condition-guidebook-is-zombie", ("invert", Invert));
}
}

View File

@@ -0,0 +1,28 @@
using Content.Shared.EntityConditions;
using Content.Shared.EntityEffects;
using Content.Shared.Mobs.Components;
using Content.Shared.Zombies;
using Robust.Shared.Prototypes;
namespace Content.Shared._Offbrand.EntityEffects;
/// <inheritdoc cref="EntityConditionSystem{T, TCondition}"/>
public sealed partial class IsZombieImmuneConditionSystem : EntityConditionSystem<MobStateComponent, IsZombieImmuneCondition>
{
protected override void Condition(Entity<MobStateComponent> entity, ref EntityConditionEvent<IsZombieImmuneCondition> args)
{
args.Result = HasComp<ZombieImmuneComponent>(entity) ^ args.Condition.Invert;
}
}
public sealed partial class IsZombieImmuneCondition : EntityConditionBase<IsZombieImmuneCondition>
{
[DataField]
public bool Invert = false;
public override string EntityConditionGuidebookText(IPrototypeManager prototype)
{
return Loc.GetString("reagent-effect-condition-guidebook-is-zombie", ("invert", Invert));
}
}

View File

@@ -0,0 +1,34 @@
using Content.Shared._Offbrand.Wounds;
using Content.Shared.EntityEffects;
using Content.Shared.EntityConditions;
using Content.Shared.FixedPoint;
using Robust.Shared.Prototypes;
namespace Content.Shared._Offbrand.EntityEffects;
public sealed partial class LungDamageConditionSystem : EntityConditionSystem<LungDamageComponent, LungDamageCondition>
{
protected override void Condition(Entity<LungDamageComponent> entity, ref EntityConditionEvent<LungDamageCondition> args)
{
var damage = entity.Comp.Damage;
args.Result = damage >= args.Condition.Min && damage <= args.Condition.Max;
}
}
public sealed partial class LungDamageCondition : EntityConditionBase<LungDamageCondition>
{
[DataField]
public FixedPoint2 Max = FixedPoint2.MaxValue;
[DataField]
public FixedPoint2 Min = FixedPoint2.Zero;
public override string EntityConditionGuidebookText(IPrototypeManager prototype)
{
return Loc.GetString("reagent-effect-condition-guidebook-lung-damage",
("max", Max == FixedPoint2.MaxValue ? (float) int.MaxValue : Max.Float()),
("min", Min.Float()));
}
}

View File

@@ -1,11 +1,19 @@
using Content.Shared.Chemistry.Reagent;
using Content.Shared.Chemistry.Components;
using Content.Shared.FixedPoint;
using Robust.Shared.Prototypes;
using Content.Shared.EntityEffects;
using Content.Shared.EntityConditions;
namespace Content.Shared._Offbrand.EntityEffects;
public sealed partial class MetaboliteThreshold : EventEntityEffectCondition<MetaboliteThreshold>
public sealed partial class MetaboliteConditionSystem : EntityConditionSystem<SolutionComponent, MetaboliteCondition>
{
protected override void Condition(Entity<SolutionComponent> entity, ref EntityConditionEvent<MetaboliteCondition> args)
{ }
}
public sealed partial class MetaboliteCondition : EntityConditionBase<MetaboliteCondition>
{
[DataField]
public FixedPoint2 Min = FixedPoint2.Zero;
@@ -19,7 +27,7 @@ public sealed partial class MetaboliteThreshold : EventEntityEffectCondition<Met
[DataField]
public bool IncludeBloodstream = true;
public override string GuidebookExplanation(IPrototypeManager prototype)
public override string EntityConditionGuidebookText(IPrototypeManager prototype)
{
ReagentPrototype? reagentProto = null;
if (Reagent is { } reagent)

View File

@@ -0,0 +1,45 @@
using Content.Shared._Offbrand.Wounds;
using Content.Shared.Damage.Components;
using Content.Shared.Damage.Prototypes;
using Content.Shared.EntityEffects;
using Content.Shared.EntityConditions;
using Content.Shared.FixedPoint;
using Robust.Shared.Prototypes;
namespace Content.Shared._Offbrand.EntityEffects;
public sealed partial class TotalGroupDamageConditionSystem : EntityConditionSystem<DamageableComponent, TotalGroupDamageCondition>
{
[Dependency] private readonly IEntityManager _entityManager = default!;
protected override void Condition(Entity<DamageableComponent> entity, ref EntityConditionEvent<TotalGroupDamageCondition> args)
{
var prototype = IoCManager.Resolve<IPrototypeManager>();
var group = prototype.Index(args.Condition.Group);
var total = FixedPoint2.Zero;
entity.Comp.Damage.TryGetDamageInGroup(group, out total);
args.Result = total >= args.Condition.Min && total <= args.Condition.Max;
}
}
public sealed partial class TotalGroupDamageCondition : EntityConditionBase<TotalGroupDamageCondition>
{
[DataField(required: true)]
public ProtoId<DamageGroupPrototype> Group;
[DataField]
public FixedPoint2 Max = FixedPoint2.MaxValue;
[DataField]
public FixedPoint2 Min = FixedPoint2.Zero;
public override string EntityConditionGuidebookText(IPrototypeManager prototype)
{
return Loc.GetString("reagent-effect-condition-guidebook-total-group-damage",
("max", Max == FixedPoint2.MaxValue ? (float) int.MaxValue : Max.Float()),
("min", Min.Float()),
("name", prototype.Index(Group).LocalizedName));
}
}

View File

@@ -0,0 +1,61 @@
using Content.Shared.Chemistry.Reagent;
using Content.Shared.Chemistry.Components;
using Content.Shared.Chemistry.EntitySystems;
using Content.Shared.EntityEffects;
using Content.Shared.FixedPoint;
using Content.Shared.Random.Helpers;
using Robust.Shared.Prototypes;
using Robust.Shared.Random;
using Robust.Shared.Timing;
namespace Content.Shared._Offbrand.EntityEffects;
public sealed partial class AdjustReagentGaussianEntityEffectSystem : EntityEffectSystem<SolutionComponent, AdjustReagentGaussian>
{
[Dependency] private readonly SharedSolutionContainerSystem _solutionContainer = default!;
[Dependency] private readonly IEntityManager _entityManager = default!;
protected override void Effect(Entity<SolutionComponent> entity, ref EntityEffectEvent<AdjustReagentGaussian> args)
{
var timing = IoCManager.Resolve<IGameTiming>();
var seed = SharedRandomExtensions.HashCodeCombine((int)timing.CurTick.Value, _entityManager.GetNetEntity(entity).Id);
var rand = new System.Random(seed);
var amount = rand.NextGaussian(args.Effect.μ, args.Effect.σ);
amount *= (double)args.Scale;
var reagent = args.Effect.Reagent;
if (amount > 0)
_solutionContainer.TryAddReagent(entity, reagent, amount);
else
_solutionContainer.RemoveReagent(entity, reagent, -amount);
}
}
public sealed partial class AdjustReagentGaussian : EntityEffectBase<AdjustReagentGaussian>
{
/// <summary>
/// The reagent ID to add or remove.
/// </summary>
[DataField(required: true)]
public ProtoId<ReagentPrototype> Reagent;
[DataField(required: true)]
public double μ;
[DataField(required: true)]
public double σ;
public override string? EntityEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys)
{
var proto = prototype.Index(Reagent);
return Loc.GetString("reagent-effect-guidebook-adjust-reagent-gaussian",
("chance", Probability),
("deltasign", Math.Sign(μ)),
("reagent", proto.LocalizedName),
("mu", Math.Abs(μ)),
("sigma", Math.Abs(σ)));
}
}

View File

@@ -0,0 +1,31 @@
using Content.Shared._Offbrand.Wounds;
using Content.Shared.EntityEffects;
using Content.Shared.FixedPoint;
using Robust.Shared.Prototypes;
namespace Content.Shared._Offbrand.EntityEffects;
/// <inheritdoc cref="EntityEffectSystem{T,TEffect}"/>
public sealed partial class ClampWoundEffectSystem : EntityEffectSystem<WoundableComponent, ClampWounds>
{
[Dependency] private readonly IEntityManager _entityManager = default!;
protected override void Effect(Entity<WoundableComponent> entity, ref EntityEffectEvent<ClampWounds> args)
{
var nullable = new Entity<WoundableComponent?>(entity, entity.Comp);
_entityManager.System<WoundableSystem>()
.ClampWounds(nullable, args.Effect.Chance);
}
}
/// <inheritdoc cref="EntityEffect"/>
public sealed partial class ClampWounds: EntityEffectBase<ClampWounds>
{
[DataField(required: true)]
public float Chance;
public override string? EntityEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys)
{
return Loc.GetString("reagent-effect-guidebook-clamp-wounds", ("probability", Probability), ("chance", Chance));
}
}

View File

@@ -0,0 +1,33 @@
using Content.Shared._Offbrand.Wounds;
using Content.Shared.EntityEffects;
using Content.Shared.FixedPoint;
using Robust.Shared.Prototypes;
namespace Content.Shared._Offbrand.EntityEffects;
/// <inheritdoc cref="EntityEffectSystem{T,TEffect}"/>
public sealed partial class ModifyBrainDamageEffectSystem : EntityEffectSystem<BrainDamageComponent, ModifyBrainDamage>
{
[Dependency] private readonly IEntityManager _entityManager = default!;
protected override void Effect(Entity<BrainDamageComponent> entity, ref EntityEffectEvent<ModifyBrainDamage> args)
{
var nullable = new Entity<BrainDamageComponent?>(entity, entity.Comp);
_entityManager.System<BrainDamageSystem>()
.TryChangeBrainDamage(nullable, args.Effect.Amount * args.Scale);
}
}
public sealed partial class ModifyBrainDamage : EntityEffectBase<ModifyBrainDamage>
{
[DataField(required: true)]
public FixedPoint2 Amount;
public override string? EntityEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys)
{
if (Amount < FixedPoint2.Zero)
return Loc.GetString("reagent-effect-guidebook-modify-brain-damage-heals", ("chance", Probability), ("amount", -Amount));
else
return Loc.GetString("reagent-effect-guidebook-modify-brain-damage-deals", ("chance", Probability), ("amount", Amount));
}
}

View File

@@ -0,0 +1,34 @@
using Content.Shared._Offbrand.Wounds;
using Content.Shared.EntityEffects;
using Content.Shared.FixedPoint;
using Robust.Shared.Prototypes;
namespace Content.Shared._Offbrand.EntityEffects;
/// <inheritdoc cref="EntityEffectSystem{T,TEffect}"/>
public sealed partial class ModifyBrainOxygenEffectSystem : EntityEffectSystem<BrainDamageComponent, ModifyBrainOxygen>
{
[Dependency] private readonly IEntityManager _entityManager = default!;
protected override void Effect(Entity<BrainDamageComponent> entity, ref EntityEffectEvent<ModifyBrainOxygen> args)
{
var nullable = new Entity<BrainDamageComponent?>(entity, entity.Comp);
_entityManager.System<BrainDamageSystem>()
.TryChangeBrainOxygenation(nullable, args.Effect.Amount * args.Scale);
}
}
public sealed partial class ModifyBrainOxygen : EntityEffectBase<ModifyBrainOxygen>
{
[DataField(required: true)]
public FixedPoint2 Amount;
public override string? EntityEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys)
{
if (Amount < FixedPoint2.Zero)
return Loc.GetString("reagent-effect-guidebook-modify-brain-oxygen-heals", ("chance", Probability), ("amount", Amount));
else
return Loc.GetString("reagent-effect-guidebook-modify-brain-oxygen-deals", ("chance", Probability), ("amount", -Amount));
}
}

View File

@@ -0,0 +1,34 @@
using Content.Shared._Offbrand.Wounds;
using Content.Shared.EntityEffects;
using Content.Shared.FixedPoint;
using Robust.Shared.Prototypes;
namespace Content.Shared._Offbrand.EntityEffects;
/// <inheritdoc cref="EntityEffectSystem{T,TEffect}"/>
public sealed partial class ModifyHeartDamageEffectSystem : EntityEffectSystem<HeartrateComponent, ModifyHeartDamage>
{
[Dependency] private readonly IEntityManager _entityManager = default!;
protected override void Effect(Entity<HeartrateComponent> entity, ref EntityEffectEvent<ModifyHeartDamage> args)
{
var nullable = new Entity<HeartrateComponent?>(entity, entity.Comp);
_entityManager.System<HeartSystem>()
.ChangeHeartDamage(nullable, args.Effect.Amount * args.Scale);
}
}
public sealed partial class ModifyHeartDamage : EntityEffectBase<ModifyHeartDamage>
{
[DataField(required: true)]
public FixedPoint2 Amount;
public override string? EntityEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys)
{
if (Amount < FixedPoint2.Zero)
return Loc.GetString("reagent-effect-guidebook-modify-heart-damage-heals", ("chance", Probability), ("amount", -Amount));
else
return Loc.GetString("reagent-effect-guidebook-modify-heart-damage-deals", ("chance", Probability), ("amount", Amount));
}
}

View File

@@ -0,0 +1,34 @@
using Content.Shared._Offbrand.Wounds;
using Content.Shared.EntityEffects;
using Content.Shared.FixedPoint;
using Robust.Shared.Prototypes;
namespace Content.Shared._Offbrand.EntityEffects;
/// <inheritdoc cref="EntityEffectSystem{T,TEffect}"/>
public sealed partial class ModifyLungDamageEffectSystem : EntityEffectSystem<LungDamageComponent, ModifyLungDamage>
{
[Dependency] private readonly IEntityManager _entityManager = default!;
protected override void Effect(Entity<LungDamageComponent> entity, ref EntityEffectEvent<ModifyLungDamage> args)
{
var nullable = new Entity<LungDamageComponent?>(entity, entity.Comp);
_entityManager.System<LungDamageSystem>()
.TryModifyDamage(nullable, args.Effect.Amount * args.Scale);
}
}
public sealed partial class ModifyLungDamage : EntityEffectBase<ModifyLungDamage>
{
[DataField(required: true)]
public FixedPoint2 Amount;
public override string? EntityEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys)
{
if (Amount < FixedPoint2.Zero)
return Loc.GetString("reagent-effect-guidebook-modify-lung-damage-heals", ("chance", Probability), ("amount", -Amount));
else
return Loc.GetString("reagent-effect-guidebook-modify-lung-damage-deals", ("chance", Probability), ("amount", Amount));
}
}

View File

@@ -0,0 +1,33 @@
using Content.Shared.EntityEffects;
using Content.Shared.StatusEffectNew;
using Content.Shared.StatusEffectNew.Components;
using Robust.Shared.Prototypes;
namespace Content.Shared._Offbrand.EntityEffects;
/// <inheritdoc cref="EntityEffectSystem{T,TEffect}"/>
public sealed partial class RemoveStatusEffectEntityEffectSystem : EntityEffectSystem<StatusEffectContainerComponent, RemoveStatusEffect>
{
[Dependency] private readonly IEntityManager _entityManager = default!;
protected override void Effect(Entity<StatusEffectContainerComponent> entity, ref EntityEffectEvent<RemoveStatusEffect> args)
{
_entityManager.System<StatusEffectsSystem>()
.TryRemoveStatusEffect(entity, args.Effect.EffectProto);
}
}
public sealed partial class RemoveStatusEffect : EntityEffectBase<RemoveStatusEffect>
{
[DataField(required: true)]
public EntProtoId EffectProto;
/// <inheritdoc />
public override string? EntityEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys)
{
return Loc.GetString(
"reagent-effect-guidebook-status-effect-remove",
("chance", Probability),
("key", prototype.Index(EffectProto).Name));
}
}

View File

@@ -0,0 +1,27 @@
using Content.Shared._Offbrand.Wounds;
using Content.Shared.EntityEffects;
using Content.Shared.FixedPoint;
using Robust.Shared.Prototypes;
namespace Content.Shared._Offbrand.EntityEffects;
/// <inheritdoc cref="EntityEffectSystem{T,TEffect}"/>
public sealed partial class StartHeartEntityEffectSystem : EntityEffectSystem<HeartrateComponent, StartHeart>
{
[Dependency] private readonly IEntityManager _entityManager = default!;
protected override void Effect(Entity<HeartrateComponent> entity, ref EntityEffectEvent<StartHeart> args)
{
var nullable = new Entity<HeartrateComponent?>(entity, entity.Comp);
_entityManager.System<HeartSystem>()
.TryRestartHeart(nullable);
}
}
public sealed partial class StartHeart : EntityEffectBase<StartHeart>
{
public override string? EntityEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys)
{
return Loc.GetString("reagent-effect-guidebook-start-heart", ("chance", Probability));
}
}

View File

@@ -0,0 +1,21 @@
using Content.Shared.EntityEffects;
using Content.Shared.FixedPoint;
using Content.Shared.Mobs.Components;
using Robust.Shared.Prototypes;
namespace Content.Shared._Offbrand.EntityEffects;
/// <inheritdoc cref="EntityEffectSystem{T,TEffect}"/>
public sealed partial class ZombidyEntityEffectSystem : EntityEffectSystem<MobStateComponent, Zombify>
{
protected override void Effect(Entity<MobStateComponent> entity, ref EntityEffectEvent<Zombify> args)
{ }
}
public sealed partial class Zombify : EntityEffectBase<Zombify>
{
public override string? EntityEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys)
{
return Loc.GetString("reagent-effect-guidebook-zombify", ("chance", Probability));
}
}

View File

@@ -1,32 +0,0 @@
using Content.Shared._Offbrand.Wounds;
using Content.Shared.EntityEffects;
using Content.Shared.FixedPoint;
using Robust.Shared.Prototypes;
namespace Content.Shared._Offbrand.EntityEffects;
public sealed partial class HeartDamage : EntityEffectCondition
{
[DataField]
public FixedPoint2 Max = FixedPoint2.MaxValue;
[DataField]
public FixedPoint2 Min = FixedPoint2.Zero;
public override bool Condition(EntityEffectBaseArgs args)
{
if (args.EntityManager.TryGetComponent<HeartrateComponent>(args.TargetEntity, out var heartrate))
{
return heartrate.Damage >= Min && heartrate.Damage <= Max;
}
return false;
}
public override string GuidebookExplanation(IPrototypeManager prototype)
{
return Loc.GetString("reagent-effect-condition-guidebook-heart-damage",
("max", Max == FixedPoint2.MaxValue ? (float) int.MaxValue : Max.Float()),
("min", Min.Float()));
}
}

View File

@@ -1,21 +0,0 @@
using Content.Shared.EntityEffects;
using Content.Shared.Zombies;
using Robust.Shared.Prototypes;
namespace Content.Shared._Offbrand.EntityEffects;
public sealed partial class IsZombie : EntityEffectCondition
{
[DataField]
public bool Invert = false;
public override bool Condition(EntityEffectBaseArgs args)
{
return args.EntityManager.HasComponent<ZombieComponent>(args.TargetEntity) ^ Invert;
}
public override string GuidebookExplanation(IPrototypeManager prototype)
{
return Loc.GetString("reagent-effect-condition-guidebook-is-zombie", ("invert", Invert));
}
}

View File

@@ -1,21 +0,0 @@
using Content.Shared.EntityEffects;
using Content.Shared.Zombies;
using Robust.Shared.Prototypes;
namespace Content.Shared._Offbrand.EntityEffects;
public sealed partial class IsZombieImmune : EntityEffectCondition
{
[DataField]
public bool Invert = false;
public override bool Condition(EntityEffectBaseArgs args)
{
return args.EntityManager.HasComponent<ZombieImmuneComponent>(args.TargetEntity) ^ Invert;
}
public override string GuidebookExplanation(IPrototypeManager prototype)
{
return Loc.GetString("reagent-effect-condition-guidebook-is-zombie-immune", ("invert", Invert));
}
}

View File

@@ -1,32 +0,0 @@
using Content.Shared._Offbrand.Wounds;
using Content.Shared.EntityEffects;
using Content.Shared.FixedPoint;
using Robust.Shared.Prototypes;
namespace Content.Shared._Offbrand.EntityEffects;
public sealed partial class LungDamage : EntityEffectCondition
{
[DataField]
public FixedPoint2 Max = FixedPoint2.MaxValue;
[DataField]
public FixedPoint2 Min = FixedPoint2.Zero;
public override bool Condition(EntityEffectBaseArgs args)
{
if (args.EntityManager.TryGetComponent<LungDamageComponent>(args.TargetEntity, out var lungDamage))
{
return lungDamage.Damage >= Min && lungDamage.Damage <= Max;
}
return false;
}
public override string GuidebookExplanation(IPrototypeManager prototype)
{
return Loc.GetString("reagent-effect-condition-guidebook-lung-damage",
("max", Max == FixedPoint2.MaxValue ? (float) int.MaxValue : Max.Float()),
("min", Min.Float()));
}
}

View File

@@ -1,31 +0,0 @@
using Content.Shared._Offbrand.Wounds;
using Content.Shared.EntityEffects;
using Content.Shared.FixedPoint;
using Robust.Shared.Prototypes;
namespace Content.Shared._Offbrand.EntityEffects;
public sealed partial class ModifyBrainDamage : EntityEffect
{
[DataField(required: true)]
public FixedPoint2 Amount;
protected override string ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys)
{
if (Amount < FixedPoint2.Zero)
return Loc.GetString("reagent-effect-guidebook-modify-brain-damage-heals", ("chance", Probability), ("amount", -Amount));
else
return Loc.GetString("reagent-effect-guidebook-modify-brain-damage-deals", ("chance", Probability), ("amount", Amount));
}
public override void Effect(EntityEffectBaseArgs args)
{
var scale = FixedPoint2.New(1);
if (args is EntityEffectReagentArgs reagentArgs)
scale = reagentArgs.Scale;
args.EntityManager.System<BrainDamageSystem>()
.TryChangeBrainDamage(args.TargetEntity, Amount * scale);
}
}

View File

@@ -1,31 +0,0 @@
using Content.Shared._Offbrand.Wounds;
using Content.Shared.EntityEffects;
using Content.Shared.FixedPoint;
using Robust.Shared.Prototypes;
namespace Content.Shared._Offbrand.EntityEffects;
public sealed partial class ModifyBrainOxygen : EntityEffect
{
[DataField(required: true)]
public FixedPoint2 Amount;
protected override string ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys)
{
if (Amount > FixedPoint2.Zero)
return Loc.GetString("reagent-effect-guidebook-modify-brain-oxygen-heals", ("chance", Probability), ("amount", Amount));
else
return Loc.GetString("reagent-effect-guidebook-modify-brain-oxygen-deals", ("chance", Probability), ("amount", -Amount));
}
public override void Effect(EntityEffectBaseArgs args)
{
var scale = FixedPoint2.New(1);
if (args is EntityEffectReagentArgs reagentArgs)
scale = reagentArgs.Scale;
args.EntityManager.System<BrainDamageSystem>()
.TryChangeBrainOxygenation(args.TargetEntity, Amount * scale);
}
}

View File

@@ -1,31 +0,0 @@
using Content.Shared._Offbrand.Wounds;
using Content.Shared.EntityEffects;
using Content.Shared.FixedPoint;
using Robust.Shared.Prototypes;
namespace Content.Shared._Offbrand.EntityEffects;
public sealed partial class ModifyHeartDamage : EntityEffect
{
[DataField(required: true)]
public FixedPoint2 Amount;
protected override string ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys)
{
if (Amount < FixedPoint2.Zero)
return Loc.GetString("reagent-effect-guidebook-modify-heart-damage-heals", ("chance", Probability), ("amount", -Amount));
else
return Loc.GetString("reagent-effect-guidebook-modify-heart-damage-deals", ("chance", Probability), ("amount", Amount));
}
public override void Effect(EntityEffectBaseArgs args)
{
var scale = FixedPoint2.New(1);
if (args is EntityEffectReagentArgs reagentArgs)
scale = reagentArgs.Scale;
args.EntityManager.System<HeartSystem>()
.ChangeHeartDamage(args.TargetEntity, Amount * scale);
}
}

View File

@@ -1,31 +0,0 @@
using Content.Shared._Offbrand.Wounds;
using Content.Shared.EntityEffects;
using Content.Shared.FixedPoint;
using Robust.Shared.Prototypes;
namespace Content.Shared._Offbrand.EntityEffects;
public sealed partial class ModifyLungDamage : EntityEffect
{
[DataField(required: true)]
public FixedPoint2 Amount;
protected override string ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys)
{
if (Amount < FixedPoint2.Zero)
return Loc.GetString("reagent-effect-guidebook-modify-lung-damage-heals", ("chance", Probability), ("amount", -Amount));
else
return Loc.GetString("reagent-effect-guidebook-modify-lung-damage-deals", ("chance", Probability), ("amount", Amount));
}
public override void Effect(EntityEffectBaseArgs args)
{
var scale = FixedPoint2.New(1);
if (args is EntityEffectReagentArgs reagentArgs)
scale = reagentArgs.Scale;
args.EntityManager.System<LungDamageSystem>()
.TryModifyDamage(args.TargetEntity, Amount * scale);
}
}

View File

@@ -1,24 +0,0 @@
using Content.Shared.EntityEffects;
using Content.Shared.StatusEffectNew;
using Robust.Shared.Prototypes;
namespace Content.Shared._Offbrand.EntityEffects;
public sealed partial class RemoveStatusEffect : EntityEffect
{
[DataField(required: true)]
public EntProtoId EffectProto;
public override void Effect(EntityEffectBaseArgs args)
{
args.EntityManager.System<StatusEffectsSystem>()
.TryRemoveStatusEffect(args.TargetEntity, EffectProto);
}
/// <inheritdoc />
protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) =>
Loc.GetString(
"reagent-effect-guidebook-status-effect-remove",
("chance", Probability),
("key", prototype.Index(EffectProto).Name));
}

View File

@@ -1,19 +0,0 @@
using Content.Shared._Offbrand.Wounds;
using Content.Shared.EntityEffects;
using Robust.Shared.Prototypes;
namespace Content.Shared._Offbrand.EntityEffects;
public sealed partial class StartHeart : EntityEffect
{
protected override string ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys)
{
return Loc.GetString("reagent-effect-guidebook-start-heart", ("chance", Probability));
}
public override void Effect(EntityEffectBaseArgs args)
{
args.EntityManager.System<HeartSystem>()
.TryRestartHeart(args.TargetEntity);
}
}

View File

@@ -1,40 +0,0 @@
using Content.Shared.Damage.Prototypes;
using Content.Shared.Damage;
using Content.Shared.EntityEffects;
using Content.Shared.FixedPoint;
using Robust.Shared.Prototypes;
namespace Content.Shared._Offbrand.EntityEffects;
public sealed partial class TotalGroupDamage : EntityEffectCondition
{
[DataField(required: true)]
public ProtoId<DamageGroupPrototype> Group;
[DataField]
public FixedPoint2 Max = FixedPoint2.MaxValue;
[DataField]
public FixedPoint2 Min = FixedPoint2.Zero;
public override bool Condition(EntityEffectBaseArgs args)
{
var prototype = IoCManager.Resolve<IPrototypeManager>();
var group = prototype.Index(Group);
if (!args.EntityManager.TryGetComponent<DamageableComponent>(args.TargetEntity, out var damage))
return false;
var total = FixedPoint2.Zero;
damage.Damage.TryGetDamageInGroup(group, out total);
return total >= Min && total <= Max;
}
public override string GuidebookExplanation(IPrototypeManager prototype)
{
return Loc.GetString("reagent-effect-condition-guidebook-total-group-damage",
("max", Max == FixedPoint2.MaxValue ? (float) int.MaxValue : Max.Float()),
("min", Min.Float()),
("name", prototype.Index(Group).LocalizedName));
}
}

View File

@@ -1,10 +0,0 @@
using Content.Shared.EntityEffects;
using Robust.Shared.Prototypes;
namespace Content.Shared._Offbrand.EntityEffects;
public sealed partial class Zombify : EventEntityEffect<Zombify>
{
protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys)
=> Loc.GetString("reagent-effect-guidebook-zombify", ("chance", Probability));
}

View File

@@ -27,7 +27,7 @@ public sealed class CauseStatusEffectRandomlyStatusEffectSystem : EntitySystem
randomEffects.NextUpdate = _timing.CurTime + randomEffects.UpdateInterval;
Dirty(uid, randomEffects);
var seed = SharedRandomExtensions.HashCodeCombine(new() { (int)_timing.CurTick.Value, GetNetEntity(uid).Id });
var seed = SharedRandomExtensions.HashCodeCombine((int)_timing.CurTick.Value, GetNetEntity(uid).Id);
var rand = new System.Random(seed);
if (!rand.Prob(randomEffects.Probability))

View File

@@ -1,4 +1,5 @@
using Content.Shared.Damage;
using Content.Shared.Damage.Systems;
using Content.Shared.StatusEffectNew.Components;
using Robust.Shared.Prototypes;
using Robust.Shared.Timing;

View File

@@ -1,5 +1,6 @@
using Content.Shared.CombatMode;
using Content.Shared.Damage;
using Content.Shared.Damage.Systems;
using Content.Shared.Mobs.Components;
using Content.Shared.StatusEffectNew.Components;
using Content.Shared.StatusEffectNew;

View File

@@ -38,7 +38,7 @@ public sealed class GunBackfireStatusEffectSystem : EntitySystem
if (args.Args.Cancelled)
return;
var seed = SharedRandomExtensions.HashCodeCombine(new() { (int)_timing.CurTick.Value, GetNetEntity(args.Args.Gun).Id });
var seed = SharedRandomExtensions.HashCodeCombine((int)_timing.CurTick.Value, GetNetEntity(args.Args.Gun).Id);
var rand = new System.Random(seed);
if (!rand.Prob(ent.Comp.Probability))
return;

View File

@@ -32,7 +32,7 @@ public sealed class HyposprayBackfireStatusEffectSystem : EntitySystem
if (args.Args.TargetGettingInjected == args.Args.EntityUsingHypospray)
return;
var seed = SharedRandomExtensions.HashCodeCombine(new() { (int)_timing.CurTick.Value, GetNetEntity(ent).Id });
var seed = SharedRandomExtensions.HashCodeCombine((int)_timing.CurTick.Value, GetNetEntity(ent).Id);
var rand = new System.Random(seed);
if (!rand.Prob(ent.Comp.Probability))
return;

View File

@@ -1,4 +1,5 @@
using Content.Shared.Damage;
using Content.Shared.Damage.Systems;
using Content.Shared.Movement.Systems;
using Content.Shared.StatusEffectNew;

View File

@@ -88,9 +88,9 @@ public sealed class TriggerOnDoAfterSystem : EntitySystem
{
if (TryComp<StackComponent>(used, out var stackComp))
{
_stack.Use(used, 1, stackComp);
_stack.TryUse(used, 1);
if (_stack.GetCount(used, stackComp) <= 0)
if (_stack.GetCount(used) <= 0)
hasMoreItems = false;
}
else

View File

@@ -1,4 +1,6 @@
using Content.Shared.Damage;
using Content.Shared.Damage.Components;
using Content.Shared.Damage.Systems;
using Content.Shared.FixedPoint;
namespace Content.Shared._Offbrand.Wounds;

View File

@@ -223,7 +223,7 @@ public sealed partial class BrainDamageSystem : EntitySystem
{
var oxygenation = _heart.BloodOxygenation((ent.Owner, ent.Comp3));
var seed = SharedRandomExtensions.HashCodeCombine(new() { (int)_timing.CurTick.Value, GetNetEntity(ent).Id });
var seed = SharedRandomExtensions.HashCodeCombine((int)_timing.CurTick.Value, GetNetEntity(ent).Id);
var rand = new System.Random(seed);
DoOxygen(ent, oxygenation, rand);

View File

@@ -54,7 +54,7 @@ public sealed class CprSystem : EntitySystem
{
_statusEffects.TryAddStatusEffectDuration(ent, ent.Comp.Effect, ent.Comp.EffectDuration);
var seed = SharedRandomExtensions.HashCodeCombine(new() { (int)_timing.CurTick.Value, GetNetEntity(ent).Id });
var seed = SharedRandomExtensions.HashCodeCombine((int)_timing.CurTick.Value, GetNetEntity(ent).Id);
var rand = new System.Random(seed);
if (rand.Prob(ent.Comp.WoundProbability) && TryComp<WoundableComponent>(ent, out var woundable))

View File

@@ -1,4 +1,6 @@
using Content.Shared.Damage;
using Content.Shared.Damage.Components;
using Content.Shared.Damage.Systems;
using Content.Shared.FixedPoint;
namespace Content.Shared._Offbrand.Wounds;

View File

@@ -4,6 +4,7 @@ using Content.Shared.Body.Components;
using Content.Shared.Body.Events;
using Content.Shared.Chemistry.EntitySystems;
using Content.Shared.Damage;
using Content.Shared.Damage.Components;
using Content.Shared.FixedPoint;
using Content.Shared.Medical;
using Content.Shared.Random.Helpers;
@@ -102,7 +103,7 @@ public sealed partial class HeartSystem : EntitySystem
var threshold = heartrate.StrainDamageThresholds.HighestMatch(HeartStrain((uid, heartrate)));
if (threshold is (var chance, var amount))
{
var seed = SharedRandomExtensions.HashCodeCombine(new() { (int)_timing.CurTick.Value, GetNetEntity(uid).Id });
var seed = SharedRandomExtensions.HashCodeCombine((int)_timing.CurTick.Value, GetNetEntity(uid).Id);
var rand = new System.Random(seed);
if (rand.Prob(chance))
@@ -170,7 +171,7 @@ public sealed partial class HeartSystem : EntitySystem
private void OnHeartBeatHypovolemia(Entity<HeartStopOnHypovolemiaComponent> ent, ref HeartBeatEvent args)
{
var seed = SharedRandomExtensions.HashCodeCombine(new() { (int)_timing.CurTick.Value, GetNetEntity(ent).Id });
var seed = SharedRandomExtensions.HashCodeCombine((int)_timing.CurTick.Value, GetNetEntity(ent).Id);
var rand = new System.Random(seed);
var volume = BloodVolume((ent.Owner, Comp<HeartrateComponent>(ent)));
@@ -179,7 +180,7 @@ public sealed partial class HeartSystem : EntitySystem
private void OnHeartBeatStrain(Entity<HeartStopOnHighStrainComponent> ent, ref HeartBeatEvent args)
{
var seed = SharedRandomExtensions.HashCodeCombine(new() { (int)_timing.CurTick.Value, GetNetEntity(ent).Id });
var seed = SharedRandomExtensions.HashCodeCombine((int)_timing.CurTick.Value, GetNetEntity(ent).Id);
var rand = new System.Random(seed);
if (_statusEffects.HasEffectComp<PreventHeartStopFromStrainStatusEffectComponent>(ent))
@@ -191,7 +192,7 @@ public sealed partial class HeartSystem : EntitySystem
private void OnHeartBeatBrain(Entity<HeartStopOnBrainHealthComponent> ent, ref HeartBeatEvent args)
{
var seed = SharedRandomExtensions.HashCodeCombine(new() { (int)_timing.CurTick.Value, GetNetEntity(ent).Id });
var seed = SharedRandomExtensions.HashCodeCombine((int)_timing.CurTick.Value, GetNetEntity(ent).Id);
var rand = new System.Random(seed);
if (_statusEffects.HasEffectComp<PreventHeartStopFromStrainStatusEffectComponent>(ent))
@@ -351,7 +352,7 @@ public sealed partial class HeartSystem : EntitySystem
public (FixedPoint2, FixedPoint2) BloodPressure(Entity<HeartrateComponent> ent)
{
var seed = SharedRandomExtensions.HashCodeCombine(new() { (int)_timing.CurTick.Value, GetNetEntity(ent).Id });
var seed = SharedRandomExtensions.HashCodeCombine((int)_timing.CurTick.Value, GetNetEntity(ent).Id);
var rand = new System.Random(seed);
var volume = BloodCirculation(ent);
@@ -370,7 +371,7 @@ public sealed partial class HeartSystem : EntitySystem
if (!ent.Comp.Running)
return 0;
var seed = SharedRandomExtensions.HashCodeCombine(new() { (int)_timing.CurTick.Value, GetNetEntity(ent).Id });
var seed = SharedRandomExtensions.HashCodeCombine((int)_timing.CurTick.Value, GetNetEntity(ent).Id);
var rand = new System.Random(seed);
var strain = HeartStrain(ent);

View File

@@ -1,4 +1,5 @@
using Content.Shared.Damage;
using Content.Shared.Damage.Components;
namespace Content.Shared._Offbrand.Wounds;

View File

@@ -1,4 +1,5 @@
using Content.Shared.Damage;
using Content.Shared.Damage.Components;
using Content.Shared.FixedPoint;
using Robust.Shared.Timing;
using Robust.Shared.Utility;

View File

@@ -141,9 +141,9 @@ public sealed class TendingSystem : EntitySystem
var hasMoreItems = true;
if (TryComp<StackComponent>(args.Used.Value, out var stackComp))
{
_stack.Use(args.Used.Value, 1, stackComp);
_stack.TryUse(args.Used.Value, 1);
if (_stack.GetCount(args.Used.Value, stackComp) <= 0)
if (_stack.GetCount(args.Used.Value) <= 0)
hasMoreItems = false;
}
else

View File

@@ -1,4 +1,6 @@
using Content.Shared.Damage;
using Content.Shared.Damage.Systems;
using Content.Shared.Damage.Components;
using Content.Shared.Random.Helpers;
using Robust.Shared.Random;
using Robust.Shared.Timing;
@@ -22,7 +24,7 @@ public sealed partial class UniqueWoundOnDamageSystem : EntitySystem
if (args.DamageDelta is not { } delta || !args.DamageIncreased)
return;
var seed = SharedRandomExtensions.HashCodeCombine(new() { (int)_timing.CurTick.Value, GetNetEntity(ent).Id });
var seed = SharedRandomExtensions.HashCodeCombine((int)_timing.CurTick.Value, GetNetEntity(ent).Id);
var rand = new System.Random(seed);
var damageable = Comp<DamageableComponent>(ent);

View File

@@ -1,7 +1,9 @@
using System.Linq;
using Content.Shared.Body.Systems;
using Content.Shared.Damage.Prototypes;
using Content.Shared.Damage.Systems;
using Content.Shared.Damage;
using Content.Shared.Damage.Components;
using Content.Shared.FixedPoint;
using Content.Shared.HealthExaminable;
using Content.Shared.IdentityManagement;
@@ -199,7 +201,7 @@ public sealed class WoundableSystem : EntitySystem
if (ent.Comp.Damage.Empty)
return;
_damageable.TryChangeDamage(args.Target, -ent.Comp.Damage.ToSpecifier(), true, false, null, null, forceRefresh: true);
_damageable.TryChangeDamage(args.Target, -ent.Comp.Damage.ToSpecifier(), true, false, null, forceRefresh: true);
ValidateWounds(args.Target, null);
}
@@ -260,7 +262,7 @@ public sealed class WoundableSystem : EntitySystem
comp.CreatedAt = _timing.CurTime;
if (refreshDamage)
_damageable.TryChangeDamage(ent.Owner, new(), true, true, null, null, forceRefresh: true);
_damageable.TryChangeDamage(ent.Owner, new(), true, true, null, forceRefresh: true);
Dirty(wound.Value, comp);
return true;
@@ -361,7 +363,7 @@ public sealed class WoundableSystem : EntitySystem
if (ent.Comp.Clamped)
return;
var seed = SharedRandomExtensions.HashCodeCombine(new() { (int)_timing.CurTick.Value, GetNetEntity(ent).Id });
var seed = SharedRandomExtensions.HashCodeCombine((int)_timing.CurTick.Value, GetNetEntity(ent).Id);
var rand = new System.Random(seed);
if (!rand.Prob(args.Args.Probability))
@@ -453,14 +455,16 @@ public sealed class WoundableSystem : EntitySystem
var changeBy = damage - remainder.ToSpecifier();
changeBy.TrimZeros();
TryComp<DamageableComponent>(woundable, out var comp);
var damageable = new Entity<DamageableComponent?>(woundable, comp);
if (changeBy.AnyNegative())
{
var actualDelta = _damageable.TryChangeDamage(woundable, changeBy, true, false, null, null, forceRefresh: true);
_damageable.TryChangeDamage(damageable, changeBy, out var actualDelta, true, false, null, forceRefresh: true);
DebugTools.Assert(actualDelta is not null);
DebugTools.Assert(changeBy.Equals(actualDelta!), $"{changeBy} == {actualDelta!}");
}
ValidateWounds(woundable, null);
ValidateWounds(damageable, null);
}
Dirty(ent);
}

View File

@@ -176,12 +176,6 @@ ent-ChemistryBottleLeft4Zed = { ent-BaseChemistryBottleFilled }
.desc = { ent-BaseChemistryBottleFilled.desc }
.suffix = Аритразин
ent-ChemistryBottleBarozine = { ent-BaseChemistryBottleFilled }
.desc = { ent-BaseChemistryBottleFilled.desc }
.suffix = Барозин
ent-ChemistryBottleBicaridine = { ent-BaseChemistryBottleFilled }
.desc = { ent-BaseChemistryBottleFilled.desc }
ent-ChemistryBottleEphedrine = { ent-BaseChemistryBottleFilled }
.suffix = Эфедрин
.desc = { ent-BaseChemistryBottleFilled.desc }

View File

@@ -128,8 +128,8 @@
statusEffects:
- statusEffect: StatusEffectPainkillersNegligibleRobustHarvest
conditions:
- !type:OrganType
type: Plant
- !type:MetabolizerTypeCondition
type: [Plant]
effects:
- !type:HealthChange
damage:
@@ -191,20 +191,22 @@
damage:
types:
Poison: 2
- !type:CreateEntityReactionEffect
- !type:SpawnEntity
entity: MobDionaNymph
conditions:
- !type:OrganType
type: Plant
- !type:ReagentThreshold
- !type:MetabolizerTypeCondition
type: [Plant]
- !type:ReagentCondition
reagent: Sedin
min: 40
- !type:AdjustReagent
reagent: Sedin
amount: -20
conditions:
- !type:OrganType
type: Plant
- !type:ReagentThreshold
- !type:MetabolizerTypeCondition
type: [Plant]
- !type:ReagentCondition
reagent: Sedin
min: 40
# End Offbrand
@@ -256,14 +258,14 @@
Caustic: 1
# Begin Offbrand
conditions:
- !type:OrganType
type: Plant
shouldHave: false
- !type:MetabolizerTypeCondition
type: [Plant]
inverted: true
- !type:SatiateHunger
factor: 1
conditions:
- !type:OrganType
type: Plant
- !type:MetabolizerTypeCondition
type: [Plant]
# End Offbrand
Gas:
effects:
@@ -354,9 +356,9 @@
# Begin Offbrand
Caustic: 0.5
conditions:
- !type:OrganType
type: Plant
shouldHave: false
- !type:MetabolizerTypeCondition
type: [Plant]
inverted: true
- !type:HealthChange
damage:
types:
@@ -364,6 +366,6 @@
Cold: -0.5
Shock: -0.5
conditions:
- !type:OrganType
type: Plant
- !type:MetabolizerTypeCondition
type: [Plant]
# End Offbrand

View File

@@ -377,12 +377,12 @@
type: Update
- !type:ModifyStatusEffect # Offbrand
conditions:
- !type:ReagentThreshold
- !type:ReagentCondition
reagent: NitrousOxide
min: 1.8
- !type:OrganType
type: Slime
shouldHave: false
- !type:MetabolizerTypeCondition
type: [ Slime ]
inverted: true
effectProto: StatusEffectPainSuppressionNitrousOxide
time: 3
type: Add

View File

@@ -293,11 +293,11 @@
statusEffects:
- statusEffect: StatusEffectMinorOxygenationCryoxadone
conditions:
- !type:Temperature
- !type:TemperatureCondition
max: 213.0
- statusEffect: StatusEffectHeartStabilizationCryoxadone
conditions:
- !type:Temperature
- !type:TemperatureCondition
max: 213.0
effects:
- !type:ModifyHeartDamage
@@ -313,7 +313,7 @@
- !type:ModifyLungDamage
amount: -0.3
conditions:
- !type:Temperature
- !type:TemperatureCondition
max: 213.0
# WL species start
- !type:MetabolizerTypeCondition
@@ -322,7 +322,7 @@
# WL species end
- !type:EvenHealthChange
conditions:
- !type:Temperature
- !type:TemperatureCondition
max: 213.0
# WL species start
- !type:MetabolizerTypeCondition
@@ -2113,7 +2113,7 @@
- !type:ReduceRotting
seconds: 20
conditions:
- !type:Temperature
- !type:TemperatureCondition
max: 213.0
# End Offbrand - Derotting moved to necrosol
- !type:HealthChange
@@ -2188,15 +2188,17 @@
boozePower: 1
- !type:Jitter
conditions:
- !type:ReagentThreshold
- !type:ReagentCondition
reagent: Mannitol
min: 10.5
- !type:Emote
emote: Scream
probability: 0.2
conditions:
- !type:ReagentThreshold
- !type:ReagentCondition
reagent: Mannitol
min: 10.5
- !type:ChemVomit
- !type:Vomit
conditions:
- !type:ReagentCondition
reagent: Mannitol
@@ -2204,7 +2206,8 @@
probability: 0.1
- !type:HealthChange
conditions:
- !type:ReagentThreshold
- !type:ReagentCondition
reagent: Mannitol
min: 10.5
damage:
types:

View File

@@ -425,28 +425,18 @@
groups:
Airloss: 10
# WL species start
# Android
conditions:
- !type:MetabolizerTypeCondition
type: [ Biorobotic ]
inverted: true
# Golem
- !type:MetabolizerTypeCondition
type: [ Golem ]
type: [ Biorobotic, Golem]
inverted: true
# WL species end
- !type:ModifyLungDamage # Offbrand
amount: 2
# WL species start
# Android
conditions:
- !type:OrganType
type: Biorobotic
shouldHave: false
# Golem
- !type:OrganType
type: Golem
shouldHave: false
- !type:MetabolizerTypeCondition
type: [ Biorobotic, Golem]
inverted: true
# WL species end
@@ -651,20 +641,21 @@
statusEffects:
- statusEffect: StatusEffectHeartStrainRomerol
conditions:
- !type:MetaboliteThreshold
- !type:MetaboliteCondition
reagent: Romerol
min: 15
effects:
- !type:AdjustReagent
reagent: Romerol
amount: -10
conditions:
- !type:IsZombie
- !type:IsZombieCondition
- !type:AdjustReagentGaussian
reagent: Romerol
μ: 0.35
σ: 0.1
conditions:
- !type:IsZombieImmune
- !type:IsZombieImmuneCondition
invert: true
- !type:PopupMessage
type: Local
@@ -676,14 +667,16 @@
- zombification-30-message-4
probability: 0.05
conditions:
- !type:MetaboliteThreshold
- !type:MetaboliteCondition
reagent: Romerol
min: 15
- !type:HealthChange
damage:
types:
Poison: 0.15
conditions:
- !type:MetaboliteThreshold
- !type:MetaboliteCondition
reagent: Romerol
min: 15
- !type:ModifyHeartDamage
amount: 2
@@ -704,39 +697,46 @@
mobstate: Critical
- !type:Zombify
conditions:
- !type:BrainDamage
- !type:BrainDamageCondition
min: 70
- !type:MetaboliteThreshold
- !type:MetaboliteCondition
reagent: Romerol
min: 15
- !type:ModifyBrainDamage
amount: 0.5
conditions:
- !type:MetaboliteThreshold
- !type:MetaboliteCondition
reagent: Romerol
min: 15
- !type:ModifyHeartDamage
amount: 0.2
conditions:
- !type:MetaboliteThreshold
- !type:MetaboliteCondition
reagent: Romerol
min: 15
- !type:ModifyLungDamage
amount: 0.2
conditions:
- !type:MetaboliteThreshold
- !type:MetaboliteCondition
reagent: Romerol
min: 15
- !type:AdjustTemperature
amount: 3000
conditions:
- !type:MetaboliteThreshold
- !type:MetaboliteCondition
reagent: Romerol
min: 15
- !type:Jitter
probability: 0.25
conditions:
- !type:MetaboliteThreshold
- !type:MetaboliteCondition
reagent: Romerol
min: 30
- !type:AdjustTemperature
amount: 6000
conditions:
- !type:MetaboliteThreshold
- !type:MetaboliteCondition
reagent: Romerol
min: 30
- !type:PopupMessage
type: Local
@@ -748,12 +748,14 @@
- zombification-60-message-4
probability: 0.05
conditions:
- !type:MetaboliteThreshold
- !type:MetaboliteCondition
reagent: Romerol
min: 30
- !type:ModifyBrainDamage
amount: 0.25
conditions:
- !type:MetaboliteThreshold
- !type:MetaboliteCondition
reagent: Romerol
min: 45
- !type:HealthChange
damage:
@@ -762,7 +764,8 @@
Blunt: 0.15
Piercing: 0.15
conditions:
- !type:MetaboliteThreshold
- !type:MetaboliteCondition
reagent: Romerol
min: 45
- !type:PopupMessage
type: Local
@@ -774,12 +777,14 @@
- zombification-90-message-4
probability: 0.05
conditions:
- !type:MetaboliteThreshold
- !type:MetaboliteCondition
reagent: Romerol
min: 45
- !type:ModifyBrainDamage
amount: 0.5
conditions:
- !type:MetaboliteThreshold
- !type:MetaboliteCondition
reagent: Romerol
min: 60
- !type:PopupMessage
type: Local
@@ -791,12 +796,14 @@
- zombification-120-message-4
probability: 0.05
conditions:
- !type:MetaboliteThreshold
- !type:MetaboliteCondition
reagent: Romerol
min: 60
- !type:ModifyBrainDamage
amount: 5
conditions:
- !type:MetaboliteThreshold
- !type:MetaboliteCondition
reagent: Romerol
min: 70
- !type:Zombify
conditions:

View File

@@ -12,20 +12,22 @@
statusEffects:
- statusEffect: StatusEffectPainkillersMildParacetamol
conditions:
- !type:ReagentThreshold
- !type:ReagentCondition
reagent: Tramadol
max: 1
- !type:ReagentThreshold
- !type:ReagentCondition
reagent: Oxycodone
max: 1
- statusEffect: StatusEffectPainkillersMildParacetamolOverdose
conditions:
- !type:ReagentThreshold
- !type:ReagentCondition
reagent: Paracetamol
min: 10
effects:
- !type:HealthChange
conditions:
- !type:ReagentThreshold
- !type:ReagentCondition
reagent: Paracetamol
min: 10
damage:
types:
@@ -46,32 +48,35 @@
- statusEffect: StatusEffectPainkillersTramadol
- statusEffect: StatusEffectPainkillersTramadolOverdose
conditions:
- !type:ReagentThreshold
- !type:ReagentCondition
reagent: Tramadol
min: 15
- !type:ReagentThreshold
- !type:ReagentCondition
reagent: Oxycodone
max: 1
- statusEffect: StatusEffectHeartStrainTramadolAlcohol
conditions:
- !type:ReagentThreshold
- !type:ReagentCondition
reagent: Ethanol
min: 1
effects:
- !type:Drunk
boozePower: 1
conditions:
- !type:ReagentThreshold
- !type:ReagentCondition
reagent: Tramadol
min: 15.5
- !type:HealthChange
conditions:
- !type:ReagentThreshold
- !type:ReagentCondition
reagent: Tramadol
min: 25
damage:
types:
Asphyxiation: 0.5
- !type:HealthChange
conditions:
- !type:ReagentThreshold
- !type:ReagentCondition
reagent: Ethanol
min: 1
damage:
@@ -93,29 +98,32 @@
- statusEffect: StatusEffectPainkillersStrongOxycodone
- statusEffect: StatusEffectPainkillersStrongOxycodoneOverdose
conditions:
- !type:ReagentThreshold
- !type:ReagentCondition
reagent: Oxycodone
min: 10
- statusEffect: StatusEffectHeartStrainOxycodoneAlcohol
conditions:
- !type:ReagentThreshold
- !type:ReagentCondition
reagent: Ethanol
min: 1
effects:
- !type:Drunk
boozePower: 2
conditions:
- !type:ReagentThreshold
- !type:ReagentCondition
reagent: Oxycodone
min: 10
- !type:HealthChange
conditions:
- !type:ReagentThreshold
- !type:ReagentCondition
reagent: Oxycodone
min: 15
damage:
types:
Asphyxiation: 0.5
- !type:HealthChange
conditions:
- !type:ReagentThreshold
- !type:ReagentCondition
reagent: Ethanol
min: 1
damage:
@@ -148,7 +156,8 @@
- !type:ModifyBloodLevel
amount: 6
conditions:
- !type:ReagentThreshold
- !type:ReagentCondition
reagent: Sanguine
max: 1
- type: reagent
@@ -167,27 +176,30 @@
- !type:ModifyHeartDamage
amount: -0.4
conditions:
- !type:HeartDamage
- !type:HeartDamageCondition
max: 50
- !type:ModifyLungDamage
amount: -0.4
conditions:
- !type:LungDamage
- !type:LungDamageCondition
max: 50
- !type:HealthChange
conditions:
- !type:ReagentThreshold
- !type:ReagentCondition
reagent: Peridaxon
min: 5.5
damage:
types:
Poison: 0.05
- !type:Jitter
conditions:
- !type:ReagentThreshold
- !type:ReagentCondition
reagent: Peridaxon
min: 5.5
- !type:ChemVomit
- !type:Vomit
conditions:
- !type:ReagentThreshold
- !type:ReagentCondition
reagent: Peridaxon
min: 5.5
probability: 0.1
@@ -204,26 +216,26 @@
statusEffects:
- statusEffect: StatusEffectMajorOxygenationCloneoxadone
conditions:
- !type:Temperature
- !type:TemperatureCondition
max: 170.0
- statusEffect: StatusEffectHeartStabilizationCloneoxadone
conditions:
- !type:Temperature
- !type:TemperatureCondition
max: 170.0
effects:
- !type:ModifyHeartDamage
amount: -0.6
conditions:
- !type:Temperature
- !type:TemperatureCondition
max: 170.0
- !type:ModifyLungDamage
amount: -0.6
conditions:
- !type:Temperature
- !type:TemperatureCondition
max: 170.0
- !type:EvenHealthChange
conditions:
- !type:Temperature
- !type:TemperatureCondition
max: 170.0
damage:
Airloss: -12
@@ -247,17 +259,20 @@
- !type:SatiateThirst
factor: 3
conditions:
- !type:ReagentThreshold
- !type:ReagentCondition
reagent: SalineGlucose
max: 1
- !type:ModifyBloodLevel
amount: 0.5
conditions:
- !type:ReagentThreshold
- !type:ReagentCondition
reagent: SalineGlucose
max: 1
- !type:SatiateHunger
factor: 0.5
conditions:
- !type:ReagentThreshold
- !type:ReagentCondition
reagent: SalineGlucose
max: 1
- !type:HealthChange
damage:
@@ -269,7 +284,8 @@
Shock: -0.6
Cold: -0.6
conditions:
- !type:ReagentThreshold
- !type:ReagentCondition
reagent: SalineGlucose
max: 1
- type: reagent
@@ -287,7 +303,8 @@
effects:
- !type:ClampWounds
chance: 0.4
- !type:RemoveStatusEffect
- !type:ModifyStatusEffect
type: Remove
effectProto: WoundArterialBleeding
probability: 0.2
@@ -303,16 +320,18 @@
metabolisms:
Medicine:
effects:
- !type:RemoveStatusEffect
- !type:ModifyStatusEffect
type: Remove
effectProto: WoundFracture
conditions:
- !type:MetaboliteThreshold
- !type:MetaboliteCondition
reagent: Osseous
min: 5
- !type:AdjustReagent
reagent: Osseous
amount: -5
conditions:
- !type:MetaboliteThreshold
- !type:MetaboliteCondition
min: 5
- type: reagent
@@ -332,7 +351,7 @@
Asphyxiation: -4
Blunt: 1
conditions:
- !type:TotalGroupDamage
- !type:TotalGroupDamageCondition
group: Airloss
min: 4
- !type:HealthChange
@@ -341,9 +360,10 @@
Asphyxiation: -4
Blunt: 1
conditions:
- !type:MetaboliteThreshold
- !type:MetaboliteCondition
reagent: Convermol
min: 10
- !type:TotalGroupDamage
- !type:TotalGroupDamageCondition
group: Airloss
min: 4
- !type:ModifyLungDamage
@@ -363,7 +383,7 @@
statusEffects:
- statusEffect: StatusEffectPainkillersSalicylicAcid
conditions:
- !type:TotalGroupDamage
- !type:TotalGroupDamageCondition
group: Brute
min: 35
effects:
@@ -371,35 +391,40 @@
damage:
Brute: -2
conditions:
- !type:TotalGroupDamage
- !type:TotalGroupDamageCondition
group: Brute
min: 35
- !type:MetaboliteThreshold
- !type:MetaboliteCondition
reagent: SalicylicAcid
max: 15
- !type:EvenHealthChange
damage:
Brute: -2
Burn: 2
conditions:
- !type:MetaboliteThreshold
- !type:MetaboliteCondition
reagent: SalicylicAcid
min: 15
- !type:EvenHealthChange
damage:
Brute: -0.5
conditions:
- !type:TotalGroupDamage
- !type:TotalGroupDamageCondition
group: Brute
max: 35
- !type:RemoveStatusEffect
- !type:ModifyStatusEffect
effectProto: WoundBoneDeath
type: Remove
conditions:
- !type:MetaboliteThreshold
- !type:MetaboliteCondition
reagent: SalicylicAcid
min: 50
- !type:EvenHealthChange
damage:
Burn: 1
conditions:
- !type:MetaboliteThreshold
- !type:MetaboliteCondition
reagent: SalicylicAcid
min: 35
- type: reagent
@@ -416,7 +441,7 @@
statusEffects:
- statusEffect: StatusEffectPainkillersOxandrolone
conditions:
- !type:TotalGroupDamage
- !type:TotalGroupDamageCondition
group: Burn
min: 35
effects:
@@ -424,33 +449,38 @@
damage:
Burn: -3
conditions:
- !type:TotalGroupDamage
- !type:TotalGroupDamageCondition
group: Burn
min: 35
- !type:MetaboliteThreshold
- !type:MetaboliteCondition
reagent: Oxandrolone
max: 15
- !type:EvenHealthChange
damage:
Burn: -3
Brute: 3
conditions:
- !type:MetaboliteThreshold
- !type:MetaboliteCondition
reagent: Oxandrolone
min: 15
- !type:EvenHealthChange
damage:
Burn: -0.5
conditions:
- !type:TotalGroupDamage
- !type:TotalGroupDamageCondition
group: Burn
max: 35
- !type:RemoveStatusEffect
- !type:ModifyStatusEffect
type: Remove
effectProto: WoundHusking
conditions:
- !type:MetaboliteThreshold
- !type:MetaboliteCondition
reagent: Oxandrolone
min: 50
- !type:EvenHealthChange
damage:
Brute: 1
conditions:
- !type:MetaboliteThreshold
- !type:MetaboliteCondition
reagent: Oxandrolone
min: 35

View File

@@ -123,7 +123,7 @@
- reagents: [Water, SpaceCleaner]
methods: [Touch]
effects:
- !type:WashCreamPieReaction
- !type:WashCreamPie
- type: StatusEffects
allowed:
- Electrocution