diff --git a/Content.Client/HealthAnalyzer/UI/HealthAnalyzerWindow.xaml.cs b/Content.Client/HealthAnalyzer/UI/HealthAnalyzerWindow.xaml.cs index 8ed6fc63e40..0c862ca7651 100644 --- a/Content.Client/HealthAnalyzer/UI/HealthAnalyzerWindow.xaml.cs +++ b/Content.Client/HealthAnalyzer/UI/HealthAnalyzerWindow.xaml.cs @@ -1,6 +1,7 @@ using System.Linq; using System.Numerics; using Content.Client.Message; +using Content.Shared._DV.Ailments; // DeltaV using Content.Shared._DV.Traits.Assorted; // DeltaV using Content.Shared.Atmos; using Content.Client.UserInterface.Controls; @@ -38,6 +39,7 @@ public sealed partial class HealthAnalyzerWindow : FancyWindow private readonly IPrototypeManager _prototypes; private readonly IResourceCache _cache; private readonly UnborgableSystem _unborgable; // DeltaV + private readonly SharedAilmentSystem _ailments; // DeltaV // Shitmed Change Start public event Action? OnBodyPartSelected; @@ -60,6 +62,7 @@ public HealthAnalyzerWindow() _prototypes = dependencies.Resolve(); _cache = dependencies.Resolve(); _unborgable = _entityManager.System(); // DeltaV + _ailments = _entityManager.System(); // DeltaV // Shitmed Change Start _bodyPartControls = new Dictionary { @@ -187,8 +190,9 @@ public void Populate(HealthAnalyzerScannedUserMessage msg) // Alerts + var ailments = _ailments.HealthAnalyzerMessages(part is {} partId ? partId : _target.Value); // DeltaV: ailments var unborgable = _unborgable.IsUnborgable(_target.Value); // DeltaV - var showAlerts = msg.Unrevivable == true || msg.Bleeding == true || unborgable; + var showAlerts = msg.Unrevivable == true || msg.Bleeding == true || unborgable || ailments.Count > 0; AlertsDivider.Visible = showAlerts; AlertsContainer.Visible = showAlerts; @@ -220,6 +224,18 @@ public void Populate(HealthAnalyzerScannedUserMessage msg) MaxWidth = 300 }); + // Begin DeltaV: ailments + foreach (var ailment in ailments) + { + AlertsContainer.AddChild(new RichTextLabel + { + Text = ailment, + Margin = new Thickness(0, 4), + MaxWidth = 300 + }); + } + // End DeltaV: ailments + // Damage Groups var damageSortedGroups = diff --git a/Content.Client/_DV/Ailments/AilmentSurgerySystem.cs b/Content.Client/_DV/Ailments/AilmentSurgerySystem.cs new file mode 100644 index 00000000000..3a843815a29 --- /dev/null +++ b/Content.Client/_DV/Ailments/AilmentSurgerySystem.cs @@ -0,0 +1,5 @@ +using Content.Shared._DV.Ailments; + +namespace Content.Client._DV.Ailments; + +public partial class AilmentSurgerySystem : SharedAilmentSurgerySystem; diff --git a/Content.Client/_DV/Ailments/AilmentSystem.cs b/Content.Client/_DV/Ailments/AilmentSystem.cs new file mode 100644 index 00000000000..13908bf3f19 --- /dev/null +++ b/Content.Client/_DV/Ailments/AilmentSystem.cs @@ -0,0 +1,5 @@ +using Content.Shared._DV.Ailments; + +namespace Content.Client._DV.Ailments; + +public partial class AilmentSystem : SharedAilmentSystem; diff --git a/Content.Server/_DV/Ailments/AilmentSurgerySystem.cs b/Content.Server/_DV/Ailments/AilmentSurgerySystem.cs new file mode 100644 index 00000000000..016f3d69615 --- /dev/null +++ b/Content.Server/_DV/Ailments/AilmentSurgerySystem.cs @@ -0,0 +1,5 @@ +using Content.Shared._DV.Ailments; + +namespace Content.Server._DV.Ailments; + +public partial class AilmentSurgerySystem : SharedAilmentSurgerySystem; diff --git a/Content.Server/_DV/Ailments/AilmentSystem.cs b/Content.Server/_DV/Ailments/AilmentSystem.cs new file mode 100644 index 00000000000..bd336180cca --- /dev/null +++ b/Content.Server/_DV/Ailments/AilmentSystem.cs @@ -0,0 +1,5 @@ +using Content.Shared._DV.Ailments; + +namespace Content.Server._DV.Ailments; + +public partial class AilmentSystem : SharedAilmentSystem; diff --git a/Content.Server/_DV/EntityEffects/Conditions/TypeDamage.cs b/Content.Server/_DV/EntityEffects/Conditions/TypeDamage.cs new file mode 100644 index 00000000000..a29994c4706 --- /dev/null +++ b/Content.Server/_DV/EntityEffects/Conditions/TypeDamage.cs @@ -0,0 +1,67 @@ +using Content.Shared.EntityEffects; +using Content.Shared.Damage; +using Content.Shared.Damage.Prototypes; +using Content.Shared.FixedPoint; +using Robust.Shared.Prototypes; + +namespace Content.Server._DV.EntityEffects.EffectConditions; + +public sealed partial class TypeDamage : EntityEffectCondition +{ + [DataField] + public FixedPoint2 Max = FixedPoint2.MaxValue; + + [DataField] + public FixedPoint2 Min = FixedPoint2.Zero; + + [DataField] + public ProtoId? DamageGroup; + + [DataField] + public ProtoId? DamageType; + + public override bool Condition(EntityEffectBaseArgs args) + { + if (args.EntityManager.TryGetComponent(args.TargetEntity, out DamageableComponent? damage)) + { + FixedPoint2 total; + if (DamageGroup is { } group) + total = damage.DamagePerGroup.GetValueOrDefault(group, FixedPoint2.Zero); + else if (DamageType is { } kind) + total = damage.Damage.DamageDict.GetValueOrDefault(kind, FixedPoint2.Zero); + else + total = damage.TotalDamage; + + if (total >= Min && total <= Max) + return true; + } + + return false; + } + + public override string GuidebookExplanation(IPrototypeManager prototype) + { + if (DamageGroup is { } group) + { + var name = prototype.Index(group).LocalizedName; + return Loc.GetString("reagent-effect-condition-guidebook-group-damage", + ("max", Max == FixedPoint2.MaxValue ? (float) int.MaxValue : Max.Float()), + ("min", Min.Float()), + ("group", name)); + } + else if (DamageType is { } kind) + { + var name = prototype.Index(kind).LocalizedName; + return Loc.GetString("reagent-effect-condition-guidebook-type-damage", + ("max", Max == FixedPoint2.MaxValue ? (float) int.MaxValue : Max.Float()), + ("min", Min.Float()), + ("type", name)); + } + else + { + return Loc.GetString("reagent-effect-condition-guidebook-total-damage", + ("max", Max == FixedPoint2.MaxValue ? (float) int.MaxValue : Max.Float()), + ("min", Min.Float())); + } + } +} diff --git a/Content.Shared/_DV/Ailments/AilmentComponent.cs b/Content.Shared/_DV/Ailments/AilmentComponent.cs new file mode 100644 index 00000000000..403a5cec87d --- /dev/null +++ b/Content.Shared/_DV/Ailments/AilmentComponent.cs @@ -0,0 +1,19 @@ +using Content.Shared._DV.Ailments; +using Robust.Shared.Analyzers; +using Robust.Shared.GameStates; +using Robust.Shared.Prototypes; + +namespace Content.Shared._DV.Ailments; + +/// +/// Contains the set of possible ailment packs & the currently active ailments in those packs, similar to a damage container +/// +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState] +public sealed partial class AilmentComponent : Component +{ + [DataField, ViewVariables, AutoNetworkedField] + public List> Packs = default!; + + [DataField, ViewVariables, AutoNetworkedField] + public Dictionary, ProtoId?> ActiveAilments = new(); +} diff --git a/Content.Shared/_DV/Ailments/AilmentPrototype.cs b/Content.Shared/_DV/Ailments/AilmentPrototype.cs new file mode 100644 index 00000000000..08de1b96cb6 --- /dev/null +++ b/Content.Shared/_DV/Ailments/AilmentPrototype.cs @@ -0,0 +1,140 @@ +using Robust.Shared.Prototypes; +using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.Array; +using Content.Shared.EntityEffects; + +namespace Content.Shared._DV.Ailments; + +/// +/// Represents some condition on the body that isn't numerical damage +/// +[Prototype] +public sealed partial class AilmentPrototype : IPrototype, IInheritingPrototype +{ + /// + [IdDataField] + [ViewVariables] + public string ID { get; private set; } = default!; + + /// + /// What this ailment shows up as on the health scanner, if anything + /// + [DataField] + public LocId? HealthAnalyzerDescription { get; set; } = default!; + + [ViewVariables(VVAccess.ReadOnly)] + public string? LocalizedHealthAnalyzerDescription => HealthAnalyzerDescription is null ? null : Loc.GetString(HealthAnalyzerDescription); + + /// + [ParentDataField(typeof(AbstractPrototypeIdArraySerializer))] + [ViewVariables] + public string[]? Parents { get; private set; } = default!; + + [NeverPushInheritance] + [AbstractDataField] + [ViewVariables] + public bool Abstract { get; private set; } = default!; + + /// + /// Entity effects to run when this ailment becomes active + /// + [DataField(serverOnly: true)] + [ViewVariables] + public EntityEffect[] Mount { get; private set; } = default!; + + /// + /// Entity effects to run when this ailment becomes inactive + /// + [DataField(serverOnly: true)] + [ViewVariables] + public EntityEffect[] Unmount { get; private set; } = default!; + + /// + /// Entity effects to run twice per second when this ailment is active + /// + [DataField(serverOnly: true)] + [ViewVariables] + public EntityEffect[] Periodic { get; private set; } = default!; +} + +/// +/// Represents a transition from one ailment to another, e.g. from being fine to having a minor bone fracture +/// +[Prototype] +public sealed partial class AilmentTransitionPrototype : IPrototype, IInheritingPrototype +{ + /// + [IdDataField] + [ViewVariables] + public string ID { get; private set; } = default!; + + /// + [ParentDataField(typeof(AbstractPrototypeIdArraySerializer))] + [ViewVariables] + public string[]? Parents { get; private set; } = default!; + + [NeverPushInheritance] + [AbstractDataField] + [ViewVariables] + public bool Abstract { get; private set; } = default!; + + /// + /// The chance for the transition to trigger if the trigger conditions are met + /// + [ViewVariables] + public float TriggerChance { get; private set; } = 1f; + + /// + /// Conditions for the transition, that when met, will cause the transition to fire without outside intervention + /// + [DataField(serverOnly: true)] + [ViewVariables] + public EntityEffectCondition[]? Triggers { get; private set; } = default!; + + /// + /// Conditions for the transition, that are required but don't cause a transition without outside intervention + /// + [DataField(serverOnly: true)] + [ViewVariables] + public EntityEffectCondition[] Conditions { get; private set; } = new EntityEffectCondition[] {}; + + /// + /// Effects that run when this transition is taken + /// + [DataField(serverOnly: true)] + [ViewVariables] + public EntityEffect[]? Effects { get; private set; } = default!; + + /// + /// Which ailment we're transitioning from + /// + [DataField(required: true)] + [ViewVariables] + public ProtoId? Start { get; private set; } = default!; + + /// + /// Which ailment we're transitioning to + /// + [DataField(required: true)] + [ViewVariables] + public ProtoId? End { get; private set; } = default!; +} + +/// +/// A collection of ailments and transitions between them. Only one ailment in a pack can be active at a time. +/// +[Prototype] +public sealed partial class AilmentPackPrototype : IPrototype +{ + /// + [IdDataField] + [ViewVariables] + public string ID { get; private set; } = default!; + + [DataField] + [ViewVariables] + public ProtoId[] Ailments { get; private set; } = default!; + + [DataField] + [ViewVariables] + public ProtoId[] Transitions { get; private set; } = default!; +} diff --git a/Content.Shared/_DV/Ailments/SharedAilmentSurgerySystem.cs b/Content.Shared/_DV/Ailments/SharedAilmentSurgerySystem.cs new file mode 100644 index 00000000000..fb0b8c75d27 --- /dev/null +++ b/Content.Shared/_DV/Ailments/SharedAilmentSurgerySystem.cs @@ -0,0 +1,52 @@ +using Content.Shared._Shitmed.Medical.Surgery.Conditions; +using Content.Shared._Shitmed.Medical.Surgery.Steps; +using Content.Shared._Shitmed.Medical.Surgery; +using Content.Shared.EntityEffects; +using Robust.Shared.Prototypes; + +namespace Content.Shared._DV.Ailments; + +public abstract partial class SharedAilmentSurgerySystem : EntitySystem +{ + [Dependency] private readonly SharedAilmentSystem _ailments = default!; + + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnAilmentConditionValid); + SubscribeLocalEvent(OnCheckTransitionComplete); + SubscribeLocalEvent(OnAilmentTransition); + } + + private void OnAilmentConditionValid(Entity ent, ref SurgeryValidEvent args) + { + if (!TryComp(args.Part, out var comp)) + { + args.Cancelled = true; + return; + } + + var hasAilment = comp.ActiveAilments.GetValueOrDefault(ent.Comp.Pack) == ent.Comp.Ailment; + args.Cancelled = !hasAilment; + } + + private void OnCheckTransitionComplete(Entity ent, ref SurgeryStepCompleteCheckEvent args) + { + if (!TryComp(args.Part, out var ailments)) + return; + + var eeba = new EntityEffectBaseArgs(args.Body, EntityManager); + var canTakeTransition = _ailments.ValidateTransition(new Entity(args.Part, ailments), ent.Comp.Pack, ent.Comp.Transition, eeba); + args.Cancelled = canTakeTransition; + } + + private void OnAilmentTransition(Entity ent, ref SurgeryStepEvent args) + { + if (!TryComp(args.Part, out var ailments)) + return; + + var eeba = new EntityEffectBaseArgs(args.Body, EntityManager); + _ailments.TryTransition(new Entity(args.Part, ailments), ent.Comp.Pack, ent.Comp.Transition, eeba); + } +} diff --git a/Content.Shared/_DV/Ailments/SharedAilmentSystem.cs b/Content.Shared/_DV/Ailments/SharedAilmentSystem.cs new file mode 100644 index 00000000000..6b317cf24b6 --- /dev/null +++ b/Content.Shared/_DV/Ailments/SharedAilmentSystem.cs @@ -0,0 +1,131 @@ +using Content.Shared._DV.Ailments; +using Content.Shared.Damage; +using Content.Shared.EntityEffects; +using Content.Shared.Popups; +using Robust.Shared.Prototypes; +using Robust.Shared.Random; +using System.Linq; + +namespace Content.Shared._DV.Ailments; + +public abstract class SharedAilmentSystem : EntitySystem +{ + [Dependency] private readonly IPrototypeManager _protoMan = default!; + [Dependency] private readonly IRobustRandom _random = default!; + + public override void Initialize() + { + base.Initialize(); + SubscribeLocalEvent(OnDamageChanged); + } + + private void OnDamageChanged(Entity ent, ref DamageChangedEvent args) + { + EvaluateAilments(ent); + } + + private void EvaluateAilments(Entity ent) + { + var args = new EntityEffectBaseArgs(ent.Owner, EntityManager); + foreach (var packId in ent.Comp.Packs) + { + var pack = _protoMan.Index(packId); + foreach (var transitionId in pack.Transitions) + { + EvaluatePotentialTransition(ent, packId, transitionId, args); + } + } + } + + public List HealthAnalyzerMessages(EntityUid uid) + { + var items = new List(); + if (!TryComp(uid, out var ailments)) + return items; + + foreach (var (_, ailment) in ailments.ActiveAilments) + { + if (ailment is null) + continue; + + if (_protoMan.Index(ailment.Value).LocalizedHealthAnalyzerDescription is {} desc) + items.Add(desc); + } + return items; + } + + public bool ValidateTransition(Entity ent, ProtoId pack, ProtoId transitionId, EntityEffectBaseArgs args) + { + if (!_protoMan.TryIndex(transitionId, out var transition)) + return false; + + var activeAilment = ent.Comp.ActiveAilments.GetValueOrDefault(pack); + var startMatches = transition.Start == activeAilment; + var endMatches = transition.End != activeAilment; + var conditionsMatch = transition.Conditions.All(condition => condition.Condition(args)); + + return startMatches && endMatches && conditionsMatch; + } + + public bool TryTransition(Entity ent, ProtoId pack, ProtoId transitionId, EntityEffectBaseArgs args) + { + if (!_protoMan.TryIndex(transitionId, out var transition)) + return false; + + if (!ValidateTransition(ent, pack, transitionId, args)) + return false; + + if (transition.Start is ProtoId startAilment) + { + RemoveAilment(ent, startAilment, args); + } + if (transition.End is ProtoId endAilment) + { + AddAilment(ent, endAilment, args); + } + + ent.Comp.ActiveAilments[pack] = transition.End; + + if (transition.Effects is not null) foreach (var effect in transition.Effects) + { + effect.Effect(args); + } + + Dirty(ent); + return true; + } + + private void EvaluatePotentialTransition(Entity ent, ProtoId pack, ProtoId transitionId, EntityEffectBaseArgs args) + { + if (!_protoMan.TryIndex(transitionId, out var transition)) + return; + + if (transition.Triggers is null) + return; + + var triggersMatch = transition.Triggers.All(condition => condition.Condition(args)); + + if (triggersMatch && _random.NextFloat() <= transition.TriggerChance) + { + TryTransition(ent, pack, transitionId, args); + } + } + + private void RemoveAilment(Entity ent, ProtoId ailmentId, EntityEffectBaseArgs args) + { + var ailment = _protoMan.Index(ailmentId); + if (ailment.Unmount is not null) foreach (var effect in ailment.Unmount) + { + effect.Effect(args); + } + } + + private void AddAilment(Entity ent, ProtoId ailmentId, EntityEffectBaseArgs args) + { + var ailment = _protoMan.Index(ailmentId); + if (ailment.Mount is not null) foreach (var effect in ailment.Mount) + { + effect.Effect(args); + } + } +} diff --git a/Content.Shared/_DV/Ailments/SurgeryHasAilmentConditionComponent.cs b/Content.Shared/_DV/Ailments/SurgeryHasAilmentConditionComponent.cs new file mode 100644 index 00000000000..c3eb8bb585c --- /dev/null +++ b/Content.Shared/_DV/Ailments/SurgeryHasAilmentConditionComponent.cs @@ -0,0 +1,18 @@ +using Robust.Shared.Analyzers; +using Robust.Shared.GameStates; +using Robust.Shared.Prototypes; + +namespace Content.Shared._DV.Ailments; + +/// +/// Requires that this part has an ailment for the surgery to be done +/// +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState] +public sealed partial class SurgeryHasAilmentConditionComponent : Component +{ + [DataField(required: true), AutoNetworkedField] + public ProtoId Pack; + + [DataField(required: true), AutoNetworkedField] + public ProtoId Ailment; +} diff --git a/Content.Shared/_DV/Ailments/SurgeryStepAilmentTransitionComponent.cs b/Content.Shared/_DV/Ailments/SurgeryStepAilmentTransitionComponent.cs new file mode 100644 index 00000000000..695a1ade545 --- /dev/null +++ b/Content.Shared/_DV/Ailments/SurgeryStepAilmentTransitionComponent.cs @@ -0,0 +1,18 @@ +using Robust.Shared.Analyzers; +using Robust.Shared.GameStates; +using Robust.Shared.Prototypes; + +namespace Content.Shared._DV.Ailments; + +/// +/// A surgery step that attempts to cause the given transition in the given ailment pack +/// +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState] +public sealed partial class SurgeryStepAilmentTransitionComponent : Component +{ + [DataField(required: true), AutoNetworkedField] + public ProtoId Pack; + + [DataField(required: true), AutoNetworkedField] + public ProtoId Transition; +} diff --git a/Resources/Locale/en-US/_DV/guidebook/chemistry/conditions.ftl b/Resources/Locale/en-US/_DV/guidebook/chemistry/conditions.ftl new file mode 100644 index 00000000000..3b3b6963a27 --- /dev/null +++ b/Resources/Locale/en-US/_DV/guidebook/chemistry/conditions.ftl @@ -0,0 +1,17 @@ +reagent-effect-condition-guidebook-type-damage = + { $max -> + [2147483648] it has at least {NATURALFIXED($min, 2)} {$type} damage + *[other] { $min -> + [0] it has at most {NATURALFIXED($max, 2)} {$type} damage + *[other] it has between {NATURALFIXED($min, 2)} and {NATURALFIXED($max, 2)} {$type} damage + } + } + +reagent-effect-condition-guidebook-group-damage = + { $max -> + [2147483648] it has at least {NATURALFIXED($min, 2)} total {$group} damage + *[other] { $min -> + [0] it has at most {NATURALFIXED($max, 2)} total {$group} damage + *[other] it has between {NATURALFIXED($min, 2)} and {NATURALFIXED($max, 2)} total {$group} damage + } + } diff --git a/Resources/Locale/en-US/_DV/surgery/surgery-popup.ftl b/Resources/Locale/en-US/_DV/surgery/surgery-popup.ftl new file mode 100644 index 00000000000..ffd31ce0516 --- /dev/null +++ b/Resources/Locale/en-US/_DV/surgery/surgery-popup.ftl @@ -0,0 +1,3 @@ +surgery-popup-step-SurgeryStepResetDislocatedJoint = {$user} is resetting a dislocated joint on {$target}'s {$part}. +surgery-popup-step-SurgeryStepMendHairlineFractures = {$user} is mending hairline fractures on {$target}'s {$part}. +surgery-popup-step-SurgeryStepMendCompoundFractures = {$user} is mending compound fractures {$target}'s {$part}. diff --git a/Resources/Prototypes/Body/Parts/base.yml b/Resources/Prototypes/Body/Parts/base.yml index e8d1066e3d6..db02eedbb7f 100644 --- a/Resources/Prototypes/Body/Parts/base.yml +++ b/Resources/Prototypes/Body/Parts/base.yml @@ -117,6 +117,9 @@ left hand: id: left hand type: Hand + - type: Ailment # DeltaV: ailments + packs: + - BoneAilments - type: entity abstract: true @@ -135,6 +138,9 @@ right hand: id: right hand type: Hand + - type: Ailment # DeltaV: ailments + packs: + - BoneAilments - type: entity abstract: true @@ -149,6 +155,9 @@ partType: Hand symmetry: Left toolName: "a left hand" # Shitmed Change + - type: Ailment # DeltaV: ailments + packs: + - BoneAilments - type: entity abstract: true @@ -163,6 +172,9 @@ partType: Hand symmetry: Right toolName: "a right hand" # Shitmed Change + - type: Ailment # DeltaV: ailments + packs: + - BoneAilments - type: entity abstract: true @@ -182,6 +194,9 @@ id: left foot type: Foot - type: MovementBodyPart + - type: Ailment # DeltaV: ailments + packs: + - BoneAilments - type: entity abstract: true @@ -201,6 +216,9 @@ id: right foot type: Foot - type: MovementBodyPart + - type: Ailment # DeltaV: ailments + packs: + - BoneAilments - type: entity abstract: true @@ -215,6 +233,9 @@ partType: Foot symmetry: Left toolName: "a left foot" # Shitmed Change + - type: Ailment # DeltaV: ailments + packs: + - BoneAilments - type: entity abstract: true @@ -229,3 +250,6 @@ partType: Foot symmetry: Right toolName: "a right foot" # Shitmed Change + - type: Ailment # DeltaV: ailments + packs: + - BoneAilments diff --git a/Resources/Prototypes/_DV/Ailments/ailments.yml b/Resources/Prototypes/_DV/Ailments/ailments.yml new file mode 100644 index 00000000000..a06a15237ab --- /dev/null +++ b/Resources/Prototypes/_DV/Ailments/ailments.yml @@ -0,0 +1,155 @@ +- type: ailmentPack + id: BoneAilments + ailments: + - JointDislocation + - HairlineFracture + - CompoundFracture + transitions: + # damages + - NullToCompound + - NullToHairline + - NullToJointDislocation + # worsening fractures + - DislocationToCompound + - DislocationToHairline + - HairlineToCompound + # tending to them + - HealDislocation + - HealHairline + - HealCompound + +- type: ailmentTransition + id: NullToJointDislocation + triggerChance: 0.1 + triggers: + - !type:TypeDamage + min: 15 + damageType: Blunt + effects: + - !type:HealthChange + damage: + types: + Blunt: -15 + start: null + end: JointDislocation + +- type: ailmentTransition + id: NullToHairline + triggerChance: 0.3 + triggers: + - !type:TypeDamage + min: 30 + damageType: Blunt + effects: + - !type:HealthChange + damage: + types: + Blunt: -30 + start: null + end: HairlineFracture + +- type: ailmentTransition + id: NullToCompound + triggerChance: 0.6 + triggers: + - !type:TypeDamage + min: 45 + damageType: Blunt + effects: + - !type:HealthChange + damage: + types: + Blunt: -45 + start: null + end: CompoundFracture + +- type: ailmentTransition + id: DislocationToCompound + triggerChance: 0.6 + triggers: + - !type:TypeDamage + min: 30 + damageType: Blunt + effects: + - !type:HealthChange + damage: + types: + Blunt: -30 + start: JointDislocation + end: CompoundFracture + +- type: ailmentTransition + id: DislocationToHairline + triggerChance: 0.3 + triggers: + - !type:TypeDamage + min: 15 + damageType: Blunt + effects: + - !type:HealthChange + damage: + types: + Blunt: -15 + start: JointDislocation + end: HairlineFracture + +- type: ailmentTransition + id: HairlineToCompound + triggerChance: 0.5 + triggers: + - !type:TypeDamage + min: 15 + damageType: Blunt + effects: + - !type:HealthChange + damage: + types: + Blunt: -15 + start: HairlineFracture + end: CompoundFracture + +- type: ailmentTransition + id: HealCompound + conditions: + - !type:TypeDamage + max: 10 + damageType: Blunt + start: CompoundFracture + end: null + +- type: ailmentTransition + id: HealHairline + conditions: + - !type:TypeDamage + max: 30 + damageType: Blunt + start: HairlineFracture + end: null + +- type: ailmentTransition + id: HealDislocation + conditions: + - !type:TypeDamage + max: 50 + damageType: Blunt + start: JointDislocation + end: null + +- type: ailment + id: BaseFracture + abstract: true + +- type: ailment + parent: BaseFracture + id: JointDislocation + healthAnalyzerDescription: The joint is dislocated + +- type: ailment + parent: BaseFracture + id: HairlineFracture + healthAnalyzerDescription: The bones have a thin fracture + +- type: ailment + parent: BaseFracture + id: CompoundFracture + healthAnalyzerDescription: The bones have a large fracture diff --git a/Resources/Prototypes/_DV/Ailments/surgeries.yml b/Resources/Prototypes/_DV/Ailments/surgeries.yml new file mode 100644 index 00000000000..683ed8e3c47 --- /dev/null +++ b/Resources/Prototypes/_DV/Ailments/surgeries.yml @@ -0,0 +1,46 @@ +- type: entity + parent: SurgeryBase + id: SurgeryResetDislocatedJoint + name: Reset Dislocated Joint + categories: [ HideSpawnMenu ] + components: + - type: Surgery + steps: + - SurgeryStepResetDislocatedJoint + - type: SurgeryPartPresentCondition + - type: SurgeryHasAilmentCondition + pack: BoneAilments + ailment: JointDislocation + +- type: entity + parent: SurgeryBase + id: SurgeryMendHairlineFractures + name: Mend Hairline Fractures + categories: [ HideSpawnMenu ] + components: + - type: Surgery + requirement: SurgeryOpenIncision + steps: + - SurgeryStepMendHairlineFractures + - SurgeryStepSealWounds + - type: SurgeryPartPresentCondition + - type: SurgeryHasAilmentCondition + pack: BoneAilments + ailment: HairlineFracture + +- type: entity + parent: SurgeryBase + id: SurgeryMendCompoundFractures + name: Mend Compound Fractures + categories: [ HideSpawnMenu ] + components: + - type: Surgery + requirement: SurgeryOpenIncision + steps: + - SurgeryStepSawBones + - SurgeryStepPriseOpenBones + - SurgeryStepMendCompoundFractures + - type: SurgeryPartPresentCondition + - type: SurgeryHasAilmentCondition + pack: BoneAilments + ailment: CompoundFracture diff --git a/Resources/Prototypes/_DV/Ailments/surgery_steps.yml b/Resources/Prototypes/_DV/Ailments/surgery_steps.yml new file mode 100644 index 00000000000..be9b6458bd4 --- /dev/null +++ b/Resources/Prototypes/_DV/Ailments/surgery_steps.yml @@ -0,0 +1,61 @@ +- type: entity + parent: SurgeryStepBase + id: SurgeryStepResetDislocatedJoint + name: Reset dislocated joint + categories: [ HideSpawnMenu ] + components: + - type: SurgeryStep + tool: + - type: Bonesetter + duration: 8 + - type: Sprite + sprite: _Shitmed/Objects/Specific/Medical/Surgery/bonesetter.rsi + state: bonesetter + - type: SurgeryStepAilmentTransition + pack: BoneAilments + transition: HealDislocation + +- type: entity + parent: SurgeryStepBase + id: SurgeryStepMendHairlineFractures + name: Mend hairline fractures + categories: [ HideSpawnMenu ] + components: + - type: SurgeryStep + tool: + - type: BoneGel + duration: 8 + - type: Sprite + sprite: _Shitmed/Objects/Specific/Medical/Surgery/bone-gel.rsi + state: bone-gel + - type: SurgeryStepAilmentTransition + pack: BoneAilments + transition: HealHairline + - type: SurgeryDamageChangeEffect + sleepModifier: 0.2 + damage: + types: + Slash: 30 + +- type: entity + parent: SurgeryStepBase + id: SurgeryStepMendCompoundFractures + name: Mend compound fractures + categories: [ HideSpawnMenu ] + components: + - type: SurgeryStep + tool: + - type: BoneGel + duration: 16 + - type: Sprite + sprite: _Shitmed/Objects/Specific/Medical/Surgery/bone-gel.rsi + state: bone-gel + - type: SurgeryStepAilmentTransition + pack: BoneAilments + transition: HealCompound + - type: SurgeryDamageChangeEffect # DeltaV + sleepModifier: 0.1 + damage: + types: + Slash: 60 + diff --git a/Resources/Prototypes/_Shitmed/Entities/Surgery/surgeries.yml b/Resources/Prototypes/_Shitmed/Entities/Surgery/surgeries.yml index 4823eb8baf3..6a8167113b5 100644 --- a/Resources/Prototypes/_Shitmed/Entities/Surgery/surgeries.yml +++ b/Resources/Prototypes/_Shitmed/Entities/Surgery/surgeries.yml @@ -60,6 +60,20 @@ part: Torso inverse: true +- type: entity + parent: SurgeryBase + id: SurgeryResetDislocatedJoint + name: Reset Dislocated Joint + categories: [ HideSpawnMenu ] + components: + - type: Surgery + steps: + - SurgeryStepResetDislocatedJoint + - type: SurgeryPartPresentCondition + - type: SurgeryHasAilmentCondition + pack: BoneAilments + ailment: JointDislocation + # I fucking hate hardcoding all of this shit to accomodate for surgery BUI. # If anyone can give me pointers on how to make it better I'd be incredibly grateful.