From 189d4a1476f1852b03d20179b6b2922fd3461f75 Mon Sep 17 00:00:00 2001 From: Rouden <149893554+Roudenn@users.noreply.github.com> Date: Sat, 7 Dec 2024 04:26:15 +0300 Subject: [PATCH] [Port] Surgery Fixes (#965) * Major Shitmed Bugfixes (#1003) * Minor Shitmed Bugfixes (#971) * full fucking send * ope forgot to remove the EE scripts * fix test * fix shitcode fail * DELTA THAT VALUE IS NULLABLE * whoopsie daysie * fixed??? * chat is this real * bugfixes * more bugfixes * goobmed * fix * delete goob things * Update throwing_stars.yml * Update SharedBodySystem.Body.cs --------- Co-authored-by: gluesniffler <159397573+gluesniffler@users.noreply.github.com> --- .../Inventory/ClientInventorySystem.cs | 10 -- .../Screens/DefaultGameScreen.xaml.cs | 8 +- .../Systems/Alerts/Widgets/AlertsUI.xaml | 2 +- .../Systems/Alerts/Widgets/AlertsUI.xaml.cs | 1 + .../Backmen/Surgery/SurgerySystem.cs | 46 ++++--- .../Body/Commands/AddHandCommand.cs | 5 +- .../Body/Commands/AttachBodyPartCommand.cs | 9 +- .../Body/BodyPartAppearanceComponent.cs | 3 - .../Body/SharedBodySystem.PartAppearance.cs | 9 +- .../Body/SharedBodySystem.Targeting.cs | 14 +-- .../Subsystems/GenerateChildPartSystem.cs | 4 +- .../Backmen/Surgery/SanitizedComponent.cs | 10 ++ .../Surgery/SharedSurgerySystem.Steps.cs | 13 +- Content.Shared/Backmen/Targeting/Events.cs | 10 -- Content.Shared/Body/Part/BodyPartComponent.cs | 10 +- .../Body/Systems/SharedBodySystem.Body.cs | 27 ++++- .../Body/Systems/SharedBodySystem.Organs.cs | 3 +- .../Body/Systems/SharedBodySystem.Parts.cs | 112 ++++++++++++------ .../Inventory/InventorySystem.Equip.cs | 1 - .../Inventory/InventorySystem.Slots.cs | 27 +++++ .../_Goobstation/research/technologies.ftl | 2 + .../en-US/_Shitmed/inventory/slot-popup.ftl | 1 + .../{ => _Shitmed}/surgery/surgery-popup.ftl | 0 .../en-US/_Shitmed/surgery/surgery-tools.ftl | 10 ++ .../{ => _Shitmed}/surgery/surgery-ui.ftl | 2 + .../_Shitmed/technologies/technologies.ftl | 3 + .../Locale/en-US/research/technologies.ftl | 5 - Resources/Prototypes/Body/Organs/arachnid.yml | 2 + Resources/Prototypes/Body/Organs/human.yml | 2 + Resources/Prototypes/Body/Parts/animal.yml | 3 + Resources/Prototypes/Body/Parts/silicon.yml | 10 ++ .../Catalog/Fills/Backpacks/duffelbag.yml | 2 +- .../Catalog/Fills/Crates/medical.yml | 2 +- .../Entities/Mobs/Cyborgs/borg_chassis.yml | 1 + .../Prototypes/Entities/Objects/Misc/pen.yml | 14 +-- .../Weapons/Throwable/throwing_stars.yml | 8 +- .../Prototypes/Recipes/Lathes/medical.yml | 52 -------- .../Prototypes/Recipes/Lathes/robotics.yml | 84 +------------ .../Prototypes/Recipes/Lathes/security.yml | 14 --- .../Prototypes/Research/civilianservices.yml | 37 ------ .../_Backmen/Body/Prototypes/cybernetic.yml | 4 +- .../_Backmen/Body/Prototypes/generic.yml | 24 ++++ .../_Backmen/Recipes/Lathes/robotics.yml | 80 +++++++++++++ .../_Backmen/Recipes/Lathes/security.yml | 12 ++ .../_Backmen/Recipes/Lathes/surgery.yml | 52 +++++++- .../_Backmen/Research/civilianservices.yml | 52 ++++++++ 46 files changed, 484 insertions(+), 318 deletions(-) create mode 100644 Content.Shared/Backmen/Surgery/SanitizedComponent.cs create mode 100644 Resources/Locale/en-US/_Goobstation/research/technologies.ftl create mode 100644 Resources/Locale/en-US/_Shitmed/inventory/slot-popup.ftl rename Resources/Locale/en-US/{ => _Shitmed}/surgery/surgery-popup.ftl (100%) create mode 100644 Resources/Locale/en-US/_Shitmed/surgery/surgery-tools.ftl rename Resources/Locale/en-US/{ => _Shitmed}/surgery/surgery-ui.ftl (87%) create mode 100644 Resources/Locale/en-US/_Shitmed/technologies/technologies.ftl diff --git a/Content.Client/Inventory/ClientInventorySystem.cs b/Content.Client/Inventory/ClientInventorySystem.cs index bfe0098b23a..6c421b1d66c 100644 --- a/Content.Client/Inventory/ClientInventorySystem.cs +++ b/Content.Client/Inventory/ClientInventorySystem.cs @@ -40,7 +40,6 @@ public override void Initialize() SubscribeLocalEvent(OnPlayerAttached); SubscribeLocalEvent(OnPlayerDetached); - SubscribeLocalEvent(OnRefreshInventorySlots); SubscribeLocalEvent(OnShutdown); SubscribeLocalEvent((_, comp, args) => @@ -182,15 +181,6 @@ public void UpdateSlot(EntityUid owner, InventorySlotsComponent component, strin EntitySlotUpdate?.Invoke(newData); } - public void OnRefreshInventorySlots(EntityUid owner, InventorySlotsComponent component, RefreshInventorySlotsEvent args) - { - if (!component.SlotData.TryGetValue(args.SlotName, out var slotData) - || _playerManager.LocalEntity != owner) - return; - - OnSlotRemoved?.Invoke(slotData); - } - public bool TryAddSlotDef(EntityUid owner, InventorySlotsComponent component, SlotDefinition newSlotDef) { SlotData newSlotData = newSlotDef; //convert to slotData diff --git a/Content.Client/UserInterface/Screens/DefaultGameScreen.xaml.cs b/Content.Client/UserInterface/Screens/DefaultGameScreen.xaml.cs index f960c897294..9e5b71230ad 100644 --- a/Content.Client/UserInterface/Screens/DefaultGameScreen.xaml.cs +++ b/Content.Client/UserInterface/Screens/DefaultGameScreen.xaml.cs @@ -26,8 +26,8 @@ public DefaultGameScreen() Chat.OnResized += ChatOnResized; Chat.OnChatResizeFinish += ChatOnResizeFinish; - MainViewport.OnResized += ResizeActionContainer; + MainViewport.OnResized += ResizeAlertsContainer; Inventory.OnResized += ResizeActionContainer; } @@ -37,6 +37,12 @@ private void ResizeActionContainer() Actions.ActionsContainer.MaxGridHeight = MainViewport.Size.Y - indent; } + private void ResizeAlertsContainer() + { + float indent = Chat.Size.Y + Targeting.Size.Y + 120; + Alerts.AlertContainer.MaxGridHeight = Math.Max(MainViewport.Size.Y - indent, 1); + } + private void ChatOnResizeFinish(Vector2 _) { var marginBottom = Chat.GetValue(MarginBottomProperty); diff --git a/Content.Client/UserInterface/Systems/Alerts/Widgets/AlertsUI.xaml b/Content.Client/UserInterface/Systems/Alerts/Widgets/AlertsUI.xaml index 3b7e6d365ea..213614405db 100644 --- a/Content.Client/UserInterface/Systems/Alerts/Widgets/AlertsUI.xaml +++ b/Content.Client/UserInterface/Systems/Alerts/Widgets/AlertsUI.xaml @@ -4,7 +4,7 @@ MinSize="64 64"> - + diff --git a/Content.Client/UserInterface/Systems/Alerts/Widgets/AlertsUI.xaml.cs b/Content.Client/UserInterface/Systems/Alerts/Widgets/AlertsUI.xaml.cs index d6a79a81c46..636fc8572fd 100644 --- a/Content.Client/UserInterface/Systems/Alerts/Widgets/AlertsUI.xaml.cs +++ b/Content.Client/UserInterface/Systems/Alerts/Widgets/AlertsUI.xaml.cs @@ -20,6 +20,7 @@ public sealed partial class AlertsUI : UIWidget public AlertsUI() { RobustXamlLoader.Load(this); + LayoutContainer.SetGrowHorizontal(this, LayoutContainer.GrowDirection.Begin); } public void SyncControls(AlertsSystem alertsSystem, diff --git a/Content.Server/Backmen/Surgery/SurgerySystem.cs b/Content.Server/Backmen/Surgery/SurgerySystem.cs index 1912591c574..96aa90f718d 100644 --- a/Content.Server/Backmen/Surgery/SurgerySystem.cs +++ b/Content.Server/Backmen/Surgery/SurgerySystem.cs @@ -21,6 +21,7 @@ using Content.Shared.Backmen.Surgery.Tools; using Content.Shared.Bed.Sleep; using Content.Shared.Medical.Surgery; +using Content.Shared.Verbs; namespace Content.Server.Backmen.Surgery; @@ -42,7 +43,7 @@ public override void Initialize() { base.Initialize(); - SubscribeLocalEvent(OnToolAfterInteract); + SubscribeLocalEvent>(OnUtilityVerb); SubscribeLocalEvent(OnSurgeryStepDamage); // You might be wondering "why aren't we using StepEvent for these two?" reason being that StepEvent fires off regardless of success on the previous functions // so this would heal entities even if you had a used or incorrect organ. @@ -101,30 +102,41 @@ private void SetDamage(EntityUid body, targetPart: _body.GetTargetBodyPart(partComp)); } - private void OnToolAfterInteract(Entity ent, ref AfterInteractEvent args) + private void AttemptStartSurgery(Entity ent, EntityUid user, EntityUid target) { - var user = args.User; - if (args.Handled - || !args.CanReach - || args.Target == null - || !HasComp(args.Target) - || !TryComp(args.User, out var surgery) - || !surgery.CanOperate - || !IsLyingDown(args.Target.Value, args.User)) - { + if (!IsLyingDown(target, user)) return; - } - if (user == args.Target && !_config.GetCVar(Shared.Backmen.CCVar.CCVars.CanOperateOnSelf)) + if (user == target && !_config.GetCVar(Shared.Backmen.CCVar.CCVars.CanOperateOnSelf)) { _popup.PopupEntity(Loc.GetString("surgery-error-self-surgery"), user, user); return; } - args.Handled = true; - _ui.OpenUi(args.Target.Value, SurgeryUIKey.Key, user); - Log.Debug("UI opened"); - RefreshUI(args.Target.Value); + _ui.OpenUi(target, SurgeryUIKey.Key, user); + RefreshUI(target); + } + + private void OnUtilityVerb(Entity ent, ref GetVerbsEvent args) + { + if (!args.CanInteract + || !args.CanAccess + || !HasComp(args.Target)) + return; + + var user = args.User; + var target = args.Target; + + var verb = new UtilityVerb() + { + Act = () => AttemptStartSurgery(ent, user, target), + Icon = new SpriteSpecifier.Rsi(new("/Textures/Objects/Specific/Medical/Surgery/scalpel.rsi/"), "scalpel"), + Text = Loc.GetString("surgery-verb-text"), + Message = Loc.GetString("surgery-verb-message"), + DoContactInteraction = true + }; + + args.Verbs.Add(verb); } private void OnSurgeryStepDamage(Entity ent, ref SurgeryStepDamageEvent args) => diff --git a/Content.Server/Body/Commands/AddHandCommand.cs b/Content.Server/Body/Commands/AddHandCommand.cs index 3e006c539c7..eba8a7e5172 100644 --- a/Content.Server/Body/Commands/AddHandCommand.cs +++ b/Content.Server/Body/Commands/AddHandCommand.cs @@ -133,7 +133,10 @@ public void Execute(IConsoleShell shell, string argStr, string[] args) if (attachAt == default) attachAt = bodySystem.GetBodyChildren(entity, body).First(); - var slotId = part.GetHashCode().ToString(); + // Shitmed Change Start + var slotId = $"{part.Symmetry.ToString().ToLower()} {part.GetHashCode().ToString()}"; + part.SlotId = part.GetHashCode().ToString(); + // Shitmed Change End if (!bodySystem.TryCreatePartSlotAndAttach(attachAt.Id, slotId, hand, BodyPartType.Hand, attachAt.Component, part)) { diff --git a/Content.Server/Body/Commands/AttachBodyPartCommand.cs b/Content.Server/Body/Commands/AttachBodyPartCommand.cs index 82f71619370..db8ad3c7db5 100644 --- a/Content.Server/Body/Commands/AttachBodyPartCommand.cs +++ b/Content.Server/Body/Commands/AttachBodyPartCommand.cs @@ -98,8 +98,15 @@ public void Execute(IConsoleShell shell, string argStr, string[] args) return; } - var slotId = $"AttachBodyPartVerb-{partUid}"; + // Shitmed Change Start + var slotId = ""; + if (part.Symmetry != BodyPartSymmetry.None) + slotId = $"{part.Symmetry.ToString().ToLower()} {part.GetHashCode().ToString()}"; + else + slotId = $"{part.GetHashCode().ToString()}"; + part.SlotId = part.GetHashCode().ToString(); + // Shitmed Change End // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract if (body.RootContainer.ContainedEntity != null) { diff --git a/Content.Shared/Backmen/Surgery/Body/BodyPartAppearanceComponent.cs b/Content.Shared/Backmen/Surgery/Body/BodyPartAppearanceComponent.cs index 31165801f38..0b440db3a41 100644 --- a/Content.Shared/Backmen/Surgery/Body/BodyPartAppearanceComponent.cs +++ b/Content.Shared/Backmen/Surgery/Body/BodyPartAppearanceComponent.cs @@ -38,7 +38,4 @@ public sealed partial class BodyPartAppearanceComponent : Component /// [DataField, AutoNetworkedField] public Color? EyeColor { get; set; } - - [DataField, AutoNetworkedField] - public EntityUid? OriginalBody { get; set; } } diff --git a/Content.Shared/Backmen/Surgery/Body/SharedBodySystem.PartAppearance.cs b/Content.Shared/Backmen/Surgery/Body/SharedBodySystem.PartAppearance.cs index e2fa22118a9..a917aaa8ecb 100644 --- a/Content.Shared/Backmen/Surgery/Body/SharedBodySystem.PartAppearance.cs +++ b/Content.Shared/Backmen/Surgery/Body/SharedBodySystem.PartAppearance.cs @@ -32,19 +32,20 @@ private void OnPartAppearanceStartup(EntityUid uid, BodyPartAppearanceComponent return; - if (part.OriginalBody == null - || TerminatingOrDeleted(part.OriginalBody.Value) - || !TryComp(part.OriginalBody.Value, out HumanoidAppearanceComponent? bodyAppearance)) + if (part.BaseLayerId != null) { component.ID = part.BaseLayerId; component.Type = relevantLayer; return; } + if (part.Body is not { Valid: true } body + || !TryComp(body, out HumanoidAppearanceComponent? bodyAppearance)) + return; + var customLayers = bodyAppearance.CustomBaseLayers; var spriteLayers = bodyAppearance.BaseLayers; component.Type = relevantLayer; - component.OriginalBody = part.OriginalBody.Value; part.Species = bodyAppearance.Species; diff --git a/Content.Shared/Backmen/Surgery/Body/SharedBodySystem.Targeting.cs b/Content.Shared/Backmen/Surgery/Body/SharedBodySystem.Targeting.cs index 97f1d694965..cb53658076f 100644 --- a/Content.Shared/Backmen/Surgery/Body/SharedBodySystem.Targeting.cs +++ b/Content.Shared/Backmen/Surgery/Body/SharedBodySystem.Targeting.cs @@ -19,6 +19,7 @@ using Content.Shared.Backmen.Surgery.Steps.Parts; using Content.Shared.Damage.Prototypes; using Content.Shared.FixedPoint; +using Content.Shared.Inventory; // ReSharper disable once CheckNamespace namespace Content.Shared.Body.Systems; @@ -181,23 +182,20 @@ private void OnBodyDamageModify(Entity bodyEnt, ref DamageModifyE if (args.TargetPart != null) { var (targetType, _) = ConvertTargetBodyPart(args.TargetPart.Value); - args.Damage = args.Damage * GetPartDamageModifier(targetType); + args.Damage *= GetPartDamageModifier(targetType); } } private void OnPartDamageModify(Entity partEnt, ref DamageModifyEvent args) { if (partEnt.Comp.Body != null - && TryComp(partEnt.Comp.Body.Value, out DamageableComponent? damageable) - && damageable.DamageModifierSetId != null - && _prototypeManager.TryIndex(damageable.DamageModifierSetId, out var modifierSet)) - // TODO: We need to add a check to see if the given armor covers this part to cancel or not. - args.Damage = DamageSpecifier.ApplyModifierSet(args.Damage, modifierSet); + && TryComp(partEnt.Comp.Body.Value, out InventoryComponent? inventory)) + _inventory.RelayEvent((partEnt.Comp.Body.Value, inventory), ref args); if (_prototypeManager.TryIndex("PartDamage", out var partModifierSet)) args.Damage = DamageSpecifier.ApplyModifierSet(args.Damage, partModifierSet); - args.Damage = args.Damage * GetPartDamageModifier(partEnt.Comp.PartType); + args.Damage *= GetPartDamageModifier(partEnt.Comp.PartType); } private bool TryChangePartDamage(EntityUid entity, @@ -298,7 +296,7 @@ private static TargetBodyPart GetRandomPartSpread(IRobustRandom random, ushort t /// This should be called after body part damage was changed. /// - protected void CheckBodyPart( + public void CheckBodyPart( Entity partEnt, TargetBodyPart? targetPart, bool severed, diff --git a/Content.Shared/Backmen/Surgery/Body/Subsystems/GenerateChildPartSystem.cs b/Content.Shared/Backmen/Surgery/Body/Subsystems/GenerateChildPartSystem.cs index c0ddc5692cf..d2f691e90d7 100644 --- a/Content.Shared/Backmen/Surgery/Body/Subsystems/GenerateChildPartSystem.cs +++ b/Content.Shared/Backmen/Surgery/Body/Subsystems/GenerateChildPartSystem.cs @@ -50,8 +50,6 @@ private void CreatePart(EntityUid uid, GenerateChildPartComponent component) component.Active = true; Dirty(childPart, childPartComp); } - - _bodySystem.ChangeSlotState((uid, partComp), false); } // Still unusued, gotta figure out what I want to do with this function outside of fuckery with mantis blades. @@ -60,7 +58,7 @@ private void DeletePart(EntityUid uid, GenerateChildPartComponent component) if (!TryComp(uid, out BodyPartComponent? partComp)) return; - _bodySystem.ChangeSlotState((uid, partComp), true); + _bodySystem.DropSlotContents((uid, partComp)); var ev = new BodyPartDroppedEvent((uid, partComp)); RaiseLocalEvent(uid, ref ev); QueueDel(uid); diff --git a/Content.Shared/Backmen/Surgery/SanitizedComponent.cs b/Content.Shared/Backmen/Surgery/SanitizedComponent.cs new file mode 100644 index 00000000000..5956313bfd6 --- /dev/null +++ b/Content.Shared/Backmen/Surgery/SanitizedComponent.cs @@ -0,0 +1,10 @@ +using Robust.Shared.GameStates; +using Robust.Shared.Prototypes; + +namespace Content.Shared.Backmen.Surgery; + +/// +/// Prevents the entity from causing toxin damage to entities it does surgery on. +/// +[RegisterComponent, NetworkedComponent] +public sealed partial class SanitizedComponent : Component { } diff --git a/Content.Shared/Backmen/Surgery/SharedSurgerySystem.Steps.cs b/Content.Shared/Backmen/Surgery/SharedSurgerySystem.Steps.cs index 594da55028a..027e71e97bd 100644 --- a/Content.Shared/Backmen/Surgery/SharedSurgerySystem.Steps.cs +++ b/Content.Shared/Backmen/Surgery/SharedSurgerySystem.Steps.cs @@ -15,6 +15,7 @@ using Content.Shared.Popups; using Robust.Shared.Prototypes; using System.Linq; +using Content.Shared.Backmen.Surgery; using Content.Shared.Backmen.Mood; using Content.Shared.Backmen.Surgery.Body.Events; using Content.Shared.Backmen.Surgery.Body.Organs; @@ -23,7 +24,6 @@ using Content.Shared.Backmen.Surgery.Steps.Parts; using Content.Shared.Backmen.Surgery.Tools; using Content.Shared.Containers.ItemSlots; -using Content.Shared.Medical.Surgery; using AmputateAttemptEvent = Content.Shared.Body.Events.AmputateAttemptEvent; namespace Content.Shared.Backmen.Surgery; @@ -127,11 +127,14 @@ private void OnToolStep(Entity ent, ref SurgeryStepEvent a RaiseLocalEvent(args.Body, new MoodEffectEvent("SurgeryPain")); if (!_inventory.TryGetSlotEntity(args.User, "gloves", out var _) - || !_inventory.TryGetSlotEntity(args.User, "mask", out var _)) + || !_inventory.TryGetSlotEntity(args.User, "mask", out var _)) { - var sepsis = new DamageSpecifier(_prototypes.Index("Poison"), 5); - var ev = new SurgeryStepDamageEvent(args.User, args.Body, args.Part, args.Surgery, sepsis, 0.5f); - RaiseLocalEvent(args.Body, ref ev); + if (!HasComp(args.User)) + { + var sepsis = new DamageSpecifier(_prototypes.Index("Poison"), 5); + var ev = new SurgeryStepDamageEvent(args.User, args.Body, args.Part, args.Surgery, sepsis, 0.5f); + RaiseLocalEvent(args.Body, ref ev); + } } } diff --git a/Content.Shared/Backmen/Targeting/Events.cs b/Content.Shared/Backmen/Targeting/Events.cs index dc4ad54619b..fd531964f2f 100644 --- a/Content.Shared/Backmen/Targeting/Events.cs +++ b/Content.Shared/Backmen/Targeting/Events.cs @@ -25,13 +25,3 @@ public TargetIntegrityChangeEvent(NetEntity uid, bool refreshUi = true) RefreshUi = refreshUi; } } - -public sealed class RefreshInventorySlotsEvent : EntityEventArgs -{ - public string SlotName { get; } - - public RefreshInventorySlotsEvent(string slotName) - { - SlotName = slotName; - } -} diff --git a/Content.Shared/Body/Part/BodyPartComponent.cs b/Content.Shared/Body/Part/BodyPartComponent.cs index df1c790e89f..6e2d0ee27a2 100644 --- a/Content.Shared/Body/Part/BodyPartComponent.cs +++ b/Content.Shared/Body/Part/BodyPartComponent.cs @@ -12,7 +12,7 @@ namespace Content.Shared.Body.Part; [RegisterComponent, NetworkedComponent, AutoGenerateComponentState] -[Access(typeof(SharedBodySystem))] +//[Access(typeof(SharedBodySystem))] public sealed partial class BodyPartComponent : Component, ISurgeryToolComponent { // Need to set this on container changes as it may be several transform parents up the hierarchy. @@ -22,9 +22,6 @@ public sealed partial class BodyPartComponent : Component, ISurgeryToolComponent [DataField, AutoNetworkedField] public EntityUid? Body; - [DataField, AutoNetworkedField] - public EntityUid? OriginalBody; - [DataField, AutoNetworkedField] public BodyPartSlot? ParentSlot; @@ -38,6 +35,9 @@ public sealed partial class BodyPartComponent : Component, ISurgeryToolComponent [DataField, AlwaysPushInheritance] public string ToolName { get; set; } = "A body part"; + [DataField, AlwaysPushInheritance] + public string SlotId { get; set; } = ""; + [DataField, AutoNetworkedField] public bool? Used { get; set; } = null; @@ -153,7 +153,7 @@ public sealed partial class BodyPartComponent : Component, ISurgeryToolComponent public bool IsVital; [DataField, AutoNetworkedField] - public BodyPartSymmetry Symmetry = BodyPartSymmetry.None; + public BodyPartSymmetry Symmetry { get; set; } = BodyPartSymmetry.None; /// /// When attached, the part will ensure these components on the entity, and delete them on removal. diff --git a/Content.Shared/Body/Systems/SharedBodySystem.Body.cs b/Content.Shared/Body/Systems/SharedBodySystem.Body.cs index 7cdc088160b..88354b33463 100644 --- a/Content.Shared/Body/Systems/SharedBodySystem.Body.cs +++ b/Content.Shared/Body/Systems/SharedBodySystem.Body.cs @@ -15,6 +15,7 @@ using Content.Shared.Humanoid; using Content.Shared.Humanoid.Events; using Content.Shared.Inventory; +using Content.Shared.Inventory.Events; using Content.Shared.Rejuvenate; using Content.Shared.Silicons.Borgs.Components; using Content.Shared.Standing; @@ -24,6 +25,7 @@ using Robust.Shared.Map; using Robust.Shared.Utility; using Robust.Shared.Timing; + namespace Content.Shared.Body.Systems; public partial class SharedBodySystem @@ -54,6 +56,7 @@ private void InitializeBody() SubscribeLocalEvent(OnBodyCanDrag); SubscribeLocalEvent(OnStandAttempt); SubscribeLocalEvent(OnProfileLoadFinished); + SubscribeLocalEvent(OnBeingEquippedAttempt); } private void OnBodyInserted(Entity ent, ref EntInsertedIntoContainerMessage args) @@ -127,7 +130,6 @@ private void MapInitBody(EntityUid bodyEntity, BodyPrototype prototype) var rootPartUid = SpawnInContainerOrDrop(protoRoot.Part, bodyEntity, BodyRootContainerId); var rootPart = Comp(rootPartUid); rootPart.Body = bodyEntity; - rootPart.OriginalBody = bodyEntity; Dirty(rootPartUid, rootPart); // Setup the rest of the body entities. SetupOrgans((rootPartUid, rootPart), protoRoot.Organs); @@ -187,7 +189,6 @@ private void MapInitParts(EntityUid rootPartId, BodyPartComponent rootPart, Body var childPartComponent = Comp(childPart); var partSlot = CreatePartSlot(parentEntity, connection, childPartComponent.PartType, parentPartComponent); childPartComponent.ParentSlot = partSlot; - childPartComponent.OriginalBody = rootPart.Body; Dirty(childPart, childPartComponent); var cont = Containers.GetContainer(parentEntity, GetPartSlotContainerId(connection)); @@ -394,8 +395,7 @@ public virtual HashSet GibPart( if (IsPartRoot(bodyEnt, partId, part: part) || !part.CanSever) return gibs; - ChangeSlotState((partId, part), true); - + DropSlotContents((partId, part)); RemovePartChildren((partId, part), bodyEnt); foreach (var organ in GetPartOrgans(partId, part)) { @@ -433,7 +433,7 @@ public virtual bool BurnPart(EntityUid partId, if (IsPartRoot(bodyEnt, partId, part: part)) return false; - ChangeSlotState((partId, part), true); + DropSlotContents((partId, part)); RemovePartChildren((partId, part), bodyEnt); QueueDel(partId); return true; @@ -451,4 +451,21 @@ private void OnProfileLoadFinished(EntityUid uid, BodyComponent component, Profi foreach (var part in GetBodyChildren(uid, component)) EnsureComp(part.Id); } + + private void OnBeingEquippedAttempt(Entity ent, ref IsEquippingAttemptEvent args) + { + TryGetPartFromSlotContainer(args.Slot, out var bodyPart); + if (bodyPart is not null) + { + if (!GetBodyChildrenOfType(args.EquipTarget, bodyPart.Value).Any()) + { + if (_timing.IsFirstTimePredicted) + _popup.PopupEntity(Loc.GetString("equip-part-missing-error", + ("target", args.EquipTarget), ("part", bodyPart.Value.ToString())), args.Equipee, args.Equipee); + args.Cancel(); + } + } + } + + // Shitmed Change End } diff --git a/Content.Shared/Body/Systems/SharedBodySystem.Organs.cs b/Content.Shared/Body/Systems/SharedBodySystem.Organs.cs index e44f5e81911..f2c4dac6779 100644 --- a/Content.Shared/Body/Systems/SharedBodySystem.Organs.cs +++ b/Content.Shared/Body/Systems/SharedBodySystem.Organs.cs @@ -72,7 +72,8 @@ private void RemoveOrgan(Entity organEnt, EntityUid parentPartUi RaiseLocalEvent(organEnt, ref removedInBodyEv); } - if (TryComp(parentPartUid, out DamageableComponent? damageable) + if (parentPartUid is { Valid: true } + && TryComp(parentPartUid, out DamageableComponent? damageable) && damageable.TotalDamage > 200) TrySetOrganUsed(organEnt, true, organEnt.Comp); diff --git a/Content.Shared/Body/Systems/SharedBodySystem.Parts.cs b/Content.Shared/Body/Systems/SharedBodySystem.Parts.cs index 5bba1751bcc..0c18ba33c9b 100644 --- a/Content.Shared/Body/Systems/SharedBodySystem.Parts.cs +++ b/Content.Shared/Body/Systems/SharedBodySystem.Parts.cs @@ -30,10 +30,12 @@ private void InitializeParts() // TODO: This doesn't handle comp removal on child ents. // If you modify this also see the Body partial for root parts. - SubscribeLocalEvent(OnMapInit); - SubscribeLocalEvent(OnBodyPartRemove); SubscribeLocalEvent(OnBodyPartInserted); SubscribeLocalEvent(OnBodyPartRemoved); + + // Shitmed Change Start + SubscribeLocalEvent(OnMapInit); + SubscribeLocalEvent(OnBodyPartRemove); SubscribeLocalEvent(OnAmputateAttempt); SubscribeLocalEvent(OnPartEnableChanged); } @@ -85,11 +87,10 @@ private void OnPartEnableChanged(Entity partEnt, ref BodyPart } /// - /// This function handles disabling or enabling equipment slots when an entity is - /// missing all of a given part type, or they get one added to them. - /// It is called right before dropping a part, or right after adding one. + /// Shitmed Change: This function handles dropping the items in an entity's slots if they lose all of a given part. + /// Such as their hands, feet, head, etc. /// - public void ChangeSlotState(Entity partEnt, bool disable) + public void DropSlotContents(Entity partEnt) { if (partEnt.Comp.Body is not null && TryComp(partEnt.Comp.Body, out var inventory) // Prevent error for non-humanoids @@ -97,11 +98,7 @@ public void ChangeSlotState(Entity partEnt, bool disable) && TryGetPartSlotContainerName(partEnt.Comp.PartType, out var containerNames)) { foreach (var containerName in containerNames) - { - _inventorySystem.SetSlotStatus(partEnt.Comp.Body.Value, containerName, disable, inventory); - var ev = new RefreshInventorySlotsEvent(containerName); - RaiseLocalEvent(partEnt.Comp.Body.Value, ev); - } + _inventorySystem.DropSlotContents(partEnt.Comp.Body.Value, containerName, inventory); } } @@ -142,7 +139,7 @@ slot.ContainedEntity is { } childEntity && protected virtual void DropPart(Entity partEnt) { - ChangeSlotState(partEnt, true); + DropSlotContents(partEnt); // I don't know if this can cause issues, since any part that's being detached HAS to have a Body. // though I really just want the compiler to shut the fuck up. var body = partEnt.Comp.Body.GetValueOrDefault(); @@ -170,14 +167,17 @@ private void OnBodyPartInserted(Entity ent, ref EntInsertedIn if (ent.Comp.Body is null) return; - if (TryComp(insertedUid, out BodyPartComponent? part)) + if (TryComp(insertedUid, out BodyPartComponent? part) && slotId.Contains(PartSlotContainerIdPrefix + GetSlotFromBodyPart(part))) // Shitmed Change { AddPart(ent.Comp.Body.Value, (insertedUid, part), slotId); RecursiveBodyUpdate((insertedUid, part), ent.Comp.Body.Value); + CheckBodyPart((insertedUid, part), GetTargetBodyPart(part), false); // Shitmed Change } - if (TryComp(insertedUid, out OrganComponent? organ)) + if (TryComp(insertedUid, out OrganComponent? organ) && slotId.Contains(OrganSlotContainerIdPrefix + organ.SlotId)) // Shitmed Change + { AddOrgan((insertedUid, organ), ent.Comp.Body.Value, ent); + } } private void OnBodyPartRemoved(Entity ent, ref EntRemovedFromContainerMessage args) @@ -185,18 +185,33 @@ private void OnBodyPartRemoved(Entity ent, ref EntRemovedFrom // Body part removed from another body part. var removedUid = args.Entity; var slotId = args.Container.ID; - DebugTools.Assert(!TryComp(removedUid, out BodyPartComponent? b) || b.Body == ent.Comp.Body); - DebugTools.Assert(!TryComp(removedUid, out OrganComponent? o) || o.Body == ent.Comp.Body); - if (TryComp(removedUid, out BodyPartComponent? part) && part.Body is not null) + // Shitmed Change Start + if (TryComp(removedUid, out BodyPartComponent? part)) { - CheckBodyPart((removedUid, part), GetTargetBodyPart(part), true); - RemovePart(part.Body.Value, (removedUid, part), slotId); - RecursiveBodyUpdate((removedUid, part), null); + if (!slotId.Contains(PartSlotContainerIdPrefix + GetSlotFromBodyPart(part))) + return; + + DebugTools.Assert(part.Body == ent.Comp.Body); + + if (part.Body is not null) + { + CheckBodyPart((removedUid, part), GetTargetBodyPart(part), true); + RemovePart(part.Body.Value, (removedUid, part), slotId); + RecursiveBodyUpdate((removedUid, part), null); + } } if (TryComp(removedUid, out OrganComponent? organ)) + { + if (!slotId.Contains(OrganSlotContainerIdPrefix + organ.SlotId)) + return; + + DebugTools.Assert(organ.Body == ent.Comp.Body); + RemoveOrgan((removedUid, organ), ent); + } + // Shitmed Change End } private void RecursiveBodyUpdate(Entity ent, EntityUid? bodyUid) @@ -272,7 +287,6 @@ protected virtual void RemovePart( Dirty(partEnt, partEnt.Comp); // Shitmed Change Start - partEnt.Comp.OriginalBody = partEnt.Comp.Body; if (partEnt.Comp.Body is { Valid: true } body) RaiseLocalEvent(partEnt, new BodyPartComponentsModifyEvent(body, false)); partEnt.Comp.ParentSlot = null; @@ -1014,12 +1028,48 @@ private bool TryGetPartSlotContainerName(BodyPartType partType, out HashSet 0; } - public string GetSlotFromBodyPart(BodyPartComponent part) + private bool TryGetPartFromSlotContainer(string slot, out BodyPartType? partType) + { + partType = slot switch + { + "gloves" => BodyPartType.Hand, + "shoes" => BodyPartType.Foot, + "eyes" or "ears" or "head" or "mask" => BodyPartType.Head, + _ => null + }; + return partType is not null; + } + + public int GetBodyPartCount(EntityUid bodyId, BodyPartType partType, BodyComponent? body = null) { + if (!Resolve(bodyId, ref body, logMissing: false)) + return 0; + + int count = 0; + foreach (var part in GetBodyChildren(bodyId, body)) + { + if (part.Component.PartType == partType) + count++; + } + return count; + } + + public string GetSlotFromBodyPart(BodyPartComponent? part) + { + var slotName = ""; + + if (part is null) + return slotName; + + if (part.SlotId != "") + slotName = part.SlotId; + else + slotName = part.PartType.ToString().ToLower(); + if (part.Symmetry != BodyPartSymmetry.None) - return $"{part.Symmetry.ToString().ToLower()} {part.PartType.ToString().ToLower()}"; + return $"{part.Symmetry.ToString().ToLower()} {slotName}"; else - return part.PartType.ToString().ToLower(); + return slotName; } // Shitmed Change End @@ -1092,19 +1142,5 @@ public bool TryGetBodyPartAdjacentPartsComponents( return false; } - public int GetBodyPartCount(EntityUid bodyId, BodyPartType partType, BodyComponent? body = null) - { - if (!Resolve(bodyId, ref body, logMissing: false)) - return 0; - - int count = 0; - foreach (var part in GetBodyChildren(bodyId, body)) - { - if (part.Component.PartType == partType) - count++; - } - return count; - } - #endregion } diff --git a/Content.Shared/Inventory/InventorySystem.Equip.cs b/Content.Shared/Inventory/InventorySystem.Equip.cs index 8158b8c2f62..e5a431a8135 100644 --- a/Content.Shared/Inventory/InventorySystem.Equip.cs +++ b/Content.Shared/Inventory/InventorySystem.Equip.cs @@ -43,7 +43,6 @@ private void InitializeEquip() //these events ensure that the client also gets its proper events raised when getting its containerstate updated SubscribeLocalEvent(OnEntInserted); SubscribeLocalEvent(OnEntRemoved); - SubscribeAllEvent(OnUseSlot); } diff --git a/Content.Shared/Inventory/InventorySystem.Slots.cs b/Content.Shared/Inventory/InventorySystem.Slots.cs index cea24755f49..21f99c4229f 100644 --- a/Content.Shared/Inventory/InventorySystem.Slots.cs +++ b/Content.Shared/Inventory/InventorySystem.Slots.cs @@ -340,4 +340,31 @@ public bool NextItem(out EntityUid item, [NotNullWhen(true)] out SlotDefinition? return false; } } + + // Shitmed Change Start + public void DropSlotContents(EntityUid uid, string slotName, InventoryComponent? inventory = null) + { + if (!Resolve(uid, ref inventory)) + return; + + foreach (var slot in inventory.Slots) + { + if (slot.Name != slotName) + continue; + + if (!TryGetSlotContainer(uid, slotName, out var container, out _, inventory)) + break; + + if (container.ContainedEntity is { } entityUid && TryComp(entityUid, out TransformComponent? transform) && _gameTiming.IsFirstTimePredicted) + { + _transform.AttachToGridOrMap(entityUid, transform); + _randomHelper.RandomOffset(entityUid, 0.5f); + } + + break; + } + + Dirty(uid, inventory); + } + // Shitmed Change End } diff --git a/Resources/Locale/en-US/_Goobstation/research/technologies.ftl b/Resources/Locale/en-US/_Goobstation/research/technologies.ftl new file mode 100644 index 00000000000..22240155729 --- /dev/null +++ b/Resources/Locale/en-US/_Goobstation/research/technologies.ftl @@ -0,0 +1,2 @@ +research-technology-weapon-plasma-rifle = Experimental plasma rifle +research-technology-medical-defense = Medical Control Gear \ No newline at end of file diff --git a/Resources/Locale/en-US/_Shitmed/inventory/slot-popup.ftl b/Resources/Locale/en-US/_Shitmed/inventory/slot-popup.ftl new file mode 100644 index 00000000000..d921423148c --- /dev/null +++ b/Resources/Locale/en-US/_Shitmed/inventory/slot-popup.ftl @@ -0,0 +1 @@ +equip-part-missing-error = {$target} is missing their {$part}! diff --git a/Resources/Locale/en-US/surgery/surgery-popup.ftl b/Resources/Locale/en-US/_Shitmed/surgery/surgery-popup.ftl similarity index 100% rename from Resources/Locale/en-US/surgery/surgery-popup.ftl rename to Resources/Locale/en-US/_Shitmed/surgery/surgery-popup.ftl diff --git a/Resources/Locale/en-US/_Shitmed/surgery/surgery-tools.ftl b/Resources/Locale/en-US/_Shitmed/surgery/surgery-tools.ftl new file mode 100644 index 00000000000..c1d1f93524a --- /dev/null +++ b/Resources/Locale/en-US/_Shitmed/surgery/surgery-tools.ftl @@ -0,0 +1,10 @@ +surgery-tool-turn-on = Turn it on first! +surgery-tool-reload = Reload it first! +surgery-tool-match-light = Light it first! +surgery-tool-match-replace = Get a new match! + +surgery-tool-examinable-verb-text = Surgery Tool +surgery-tool-examinable-verb-message = Examine the uses of this tool in surgeries. +surgery-tool-header = This can be used in surgeries as: +surgery-tool-unlimited = - {$tool} at [color={$color}]{$speed}x[/color] speed +surgery-tool-used = - {$tool} at [color={$color}]{$speed}x[/color] speed, [color=red]then gets used up[/color] diff --git a/Resources/Locale/en-US/surgery/surgery-ui.ftl b/Resources/Locale/en-US/_Shitmed/surgery/surgery-ui.ftl similarity index 87% rename from Resources/Locale/en-US/surgery/surgery-ui.ftl rename to Resources/Locale/en-US/_Shitmed/surgery/surgery-ui.ftl index f09c9dc102a..415395f7815 100644 --- a/Resources/Locale/en-US/surgery/surgery-ui.ftl +++ b/Resources/Locale/en-US/_Shitmed/surgery/surgery-ui.ftl @@ -1,3 +1,5 @@ +surgery-verb-text = Start surgery +surgery-verb-message = Begin surgery on this entity. surgery-ui-window-title = Surgery surgery-ui-window-require = Requires surgery-ui-window-parts = < Parts diff --git a/Resources/Locale/en-US/_Shitmed/technologies/technologies.ftl b/Resources/Locale/en-US/_Shitmed/technologies/technologies.ftl new file mode 100644 index 00000000000..d5db297ae29 --- /dev/null +++ b/Resources/Locale/en-US/_Shitmed/technologies/technologies.ftl @@ -0,0 +1,3 @@ +research-technology-advanced-treatment = Advanced Treatment +research-technology-high-end-surgery = High End Surgical Tools +research-technology-cybernetic-enhancements = Cybernetic Enhancements \ No newline at end of file diff --git a/Resources/Locale/en-US/research/technologies.ftl b/Resources/Locale/en-US/research/technologies.ftl index 451ab0d0ff4..0b0970ec08f 100644 --- a/Resources/Locale/en-US/research/technologies.ftl +++ b/Resources/Locale/en-US/research/technologies.ftl @@ -71,8 +71,3 @@ research-technology-advanced-spray = Advanced Spray research-technology-bluespace-cargo-transport = Bluespace Cargo Transport research-technology-quantum-fiber-weaving = Quantum Fiber Weaving research-technology-bluespace-chemistry = Bluespace Chemistry - -## Shitmed Change -research-technology-advanced-treatment = Advanced Treatment -research-technology-high-end-surgery = High End Surgical Tools -research-technology-cybernetic-enhancements = Cybernetic Enhancements \ No newline at end of file diff --git a/Resources/Prototypes/Body/Organs/arachnid.yml b/Resources/Prototypes/Body/Organs/arachnid.yml index 42be718e139..584c76821d6 100644 --- a/Resources/Prototypes/Body/Organs/arachnid.yml +++ b/Resources/Prototypes/Body/Organs/arachnid.yml @@ -150,6 +150,8 @@ description: "Filters toxins from the bloodstream." categories: [ HideSpawnMenu ] components: + - type: Organ # Shitmed + slotId: kidneys - type: Sprite layers: - state: kidney-l diff --git a/Resources/Prototypes/Body/Organs/human.yml b/Resources/Prototypes/Body/Organs/human.yml index 42226ebac8f..abce3f89cba 100644 --- a/Resources/Prototypes/Body/Organs/human.yml +++ b/Resources/Prototypes/Body/Organs/human.yml @@ -254,6 +254,8 @@ name: kidneys description: "Filters toxins from the bloodstream." components: + - type: Organ # Shitmed + slotId: kidneys - type: Sprite layers: - state: kidney-l diff --git a/Resources/Prototypes/Body/Parts/animal.yml b/Resources/Prototypes/Body/Parts/animal.yml index bc3d4b935ce..4c79f342bdb 100644 --- a/Resources/Prototypes/Body/Parts/animal.yml +++ b/Resources/Prototypes/Body/Parts/animal.yml @@ -45,6 +45,7 @@ - type: BodyPart partType: Hand symmetry: Left + slotId: hands # Shitmed - type: entity id: LegsAnimal @@ -58,6 +59,7 @@ - state: r_leg - type: BodyPart partType: Leg + slotId: legs # Shitmed - type: MovementBodyPart - type: entity @@ -72,6 +74,7 @@ - state: l_foot - type: BodyPart partType: Foot + slotId: feet # Shitmed - type: entity id: TorsoAnimal diff --git a/Resources/Prototypes/Body/Parts/silicon.yml b/Resources/Prototypes/Body/Parts/silicon.yml index ef0476126f0..577ec2bffce 100644 --- a/Resources/Prototypes/Body/Parts/silicon.yml +++ b/Resources/Prototypes/Body/Parts/silicon.yml @@ -76,6 +76,11 @@ - type: BodyPart partType: Leg symmetry: Left + toolName: "a left leg" # Shitmed Change + children: # Shitmed Change + left foot: + id: "left foot" + type: Foot - type: Sprite state: borg_l_leg - type: Icon @@ -94,6 +99,11 @@ - type: BodyPart partType: Leg symmetry: Right + toolName: "a right leg" # Shitmed Change + children: # Shitmed Change + right foot: + id: "right foot" + type: Foot - type: Sprite state: borg_r_leg - type: Icon diff --git a/Resources/Prototypes/Catalog/Fills/Backpacks/duffelbag.yml b/Resources/Prototypes/Catalog/Fills/Backpacks/duffelbag.yml index 72034c9acc2..1fd3b51bb1f 100644 --- a/Resources/Prototypes/Catalog/Fills/Backpacks/duffelbag.yml +++ b/Resources/Prototypes/Catalog/Fills/Backpacks/duffelbag.yml @@ -7,7 +7,7 @@ - type: StorageFill contents: - id: Hemostat - - id: Saw + - id: SawElectric # Shitmed Change - id: Drill - id: Cautery - id: Retractor diff --git a/Resources/Prototypes/Catalog/Fills/Crates/medical.yml b/Resources/Prototypes/Catalog/Fills/Crates/medical.yml index 24edb83f4f1..5459930a130 100644 --- a/Resources/Prototypes/Catalog/Fills/Crates/medical.yml +++ b/Resources/Prototypes/Catalog/Fills/Crates/medical.yml @@ -65,7 +65,7 @@ - id: Retractor - id: Cautery - id: Drill - - id: Saw + - id: SawElectric # Shitmed Change - id: Hemostat # start-backmen: surgery - id: BoneGel diff --git a/Resources/Prototypes/Entities/Mobs/Cyborgs/borg_chassis.yml b/Resources/Prototypes/Entities/Mobs/Cyborgs/borg_chassis.yml index 8f8a116a4e3..a4d30386121 100644 --- a/Resources/Prototypes/Entities/Mobs/Cyborgs/borg_chassis.yml +++ b/Resources/Prototypes/Entities/Mobs/Cyborgs/borg_chassis.yml @@ -75,6 +75,7 @@ - type: SurgeryTarget - type: TTS # Corvax-TTS voice: TrainingRobot + - type: Sanitized - type: entity id: BorgChassisService diff --git a/Resources/Prototypes/Entities/Objects/Misc/pen.yml b/Resources/Prototypes/Entities/Objects/Misc/pen.yml index 6e02f4be241..45f90f9603b 100644 --- a/Resources/Prototypes/Entities/Objects/Misc/pen.yml +++ b/Resources/Prototypes/Entities/Objects/Misc/pen.yml @@ -42,13 +42,13 @@ damage: types: Piercing: 3 -# - type: Tending # Shitmed TODO: Uncomment this when surgeries arent tied to interaction events, but verbs. -# speed: 0.55 -# - type: SurgeryTool # Shitmed -# startSound: -# path: /Audio/_Shitmed/Medical/Surgery/retractor1.ogg -# endSound: -# path: /Audio/_Shitmed/Medical/Surgery/hemostat1.ogg + - type: Tending # Shitmed + speed: 0.55 + - type: SurgeryTool # Shitmed + startSound: + path: /Audio/_Shitmed/Medical/Surgery/retractor1.ogg + endSound: + path: /Audio/_Shitmed/Medical/Surgery/hemostat1.ogg #TODO: I want the luxury pen to write a cool font like Merriweather in the future. diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Throwable/throwing_stars.yml b/Resources/Prototypes/Entities/Objects/Weapons/Throwable/throwing_stars.yml index 9a41387cbea..46e76f961b0 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/Throwable/throwing_stars.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/Throwable/throwing_stars.yml @@ -10,10 +10,10 @@ - state: icon map: ["base"] - type: Appearance - - type: HolidayVisuals - holidays: - festive: - - FestiveSeason +# - type: HolidayVisuals +# holidays: +# festive: +# - FestiveSeason - type: GenericVisualizer visuals: enum.HolidayVisuals.Holiday: diff --git a/Resources/Prototypes/Recipes/Lathes/medical.yml b/Resources/Prototypes/Recipes/Lathes/medical.yml index a7f444001f6..08250290ec7 100644 --- a/Resources/Prototypes/Recipes/Lathes/medical.yml +++ b/Resources/Prototypes/Recipes/Lathes/medical.yml @@ -215,55 +215,3 @@ materials: Steel: 100 Plastic: 100 - -# Shitmed Recipes - -- type: latheRecipe - id: MedicalCyberneticEyes - result: MedicalCyberneticEyes - category: Robotics - completetime: 5 - materials: - Steel: 1000 - Glass: 500 - Plastic: 500 - Gold: 300 - Silver: 300 - -- type: latheRecipe - id: EnergyScalpel - result: EnergyScalpel - completetime: 2 - materials: - Steel: 600 - Glass: 150 - Gold: 150 - -- type: latheRecipe - id: AdvancedRetractor - result: AdvancedRetractor - completetime: 2 - materials: - Steel: 600 - Glass: 150 - Silver: 150 - -- type: latheRecipe - id: EnergyCautery - result: EnergyCautery - completetime: 2 - materials: - Steel: 600 - Glass: 150 - Plasma: 150 - -- type: latheRecipe - id: OmnimedTool - result: OmnimedTool - completetime: 2 - materials: - Steel: 600 - Glass: 150 - Gold: 150 - Silver: 150 - Plasma: 150 diff --git a/Resources/Prototypes/Recipes/Lathes/robotics.yml b/Resources/Prototypes/Recipes/Lathes/robotics.yml index 12e6087f7d3..f6579096f6e 100644 --- a/Resources/Prototypes/Recipes/Lathes/robotics.yml +++ b/Resources/Prototypes/Recipes/Lathes/robotics.yml @@ -196,85 +196,7 @@ id: BorgModuleHarvesting result: BorgModuleHarvesting -# Shitmed Recipes - -- type: latheRecipe - id: BorgModuleSurgery - result: BorgModuleSurgery - category: Robotics - completetime: 3 - materials: - Steel: 250 - Glass: 250 - Plastic: 250 - -- type: latheRecipe - id: BorgModuleAdvancedSurgery - result: BorgModuleAdvancedSurgery - category: Robotics - completetime: 3 - materials: - Steel: 500 - Glass: 500 - Plastic: 250 - Gold: 50 - -- type: latheRecipe - id: JawsOfLifeLeftArm - result: JawsOfLifeLeftArm - category: Robotics - completetime: 5 - materials: - Steel: 1000 - Glass: 500 - Plastic: 500 - Gold: 300 - Silver: 300 - -- type: latheRecipe - id: JawsOfLifeRightArm - result: JawsOfLifeRightArm - category: Robotics - completetime: 5 - materials: - Steel: 1000 - Glass: 500 - Plastic: 500 - Gold: 300 - Silver: 300 - -- type: latheRecipe - id: SpeedLeftLeg - result: SpeedLeftLeg - category: Robotics - completetime: 5 - materials: - Steel: 1000 - Glass: 500 - Plastic: 500 - Gold: 300 - Silver: 300 - - type: latheRecipe - id: SpeedRightLeg - result: SpeedRightLeg - category: Robotics - completetime: 5 - materials: - Steel: 1000 - Glass: 500 - Plastic: 500 - Gold: 300 - Silver: 300 - -- type: latheRecipe - id: BasicCyberneticEyes - result: BasicCyberneticEyes - category: Robotics - completetime: 5 - materials: - Steel: 1000 - Glass: 500 - Plastic: 500 - Gold: 300 - Silver: 300 + parent: BaseBorgModuleRecipe + id: BorgModuleClowning + result: BorgModuleClowning diff --git a/Resources/Prototypes/Recipes/Lathes/security.yml b/Resources/Prototypes/Recipes/Lathes/security.yml index 43ba8f8be51..bc6f9218401 100644 --- a/Resources/Prototypes/Recipes/Lathes/security.yml +++ b/Resources/Prototypes/Recipes/Lathes/security.yml @@ -689,17 +689,3 @@ Plastic: 1000 Plasma: 500 Glass: 500 - -# Shitmed Recipes - -- type: latheRecipe - id: SecurityCyberneticEyes - result: SecurityCyberneticEyes - category: Robotics - completetime: 5 - materials: - Steel: 1000 - Glass: 500 - Plastic: 500 - Gold: 300 - Silver: 300 diff --git a/Resources/Prototypes/Research/civilianservices.yml b/Resources/Prototypes/Research/civilianservices.yml index 4d7f6f27c10..22092db1669 100644 --- a/Resources/Prototypes/Research/civilianservices.yml +++ b/Resources/Prototypes/Research/civilianservices.yml @@ -129,43 +129,6 @@ - CryostasisBeaker - SyringeCryostasis -# Shitmed Change Start -- type: technology - id: AdvancedTreatment - name: research-technology-advanced-treatment - icon: - sprite: _Shitmed/Objects/Specific/Medical/Surgery/e-scalpel.rsi - state: e-scalpel-on - discipline: CivilianServices - tier: 2 - cost: 5000 - recipeUnlocks: - - BorgModuleAdvancedTreatment - - BorgModuleDefibrillator - - EnergyScalpel - - EnergyCautery - - AdvancedRetractor - - BorgModuleAdvancedSurgery - -- type: technology - id: CyberneticEnhancements - name: research-technology-cybernetic-enhancements - icon: - sprite: _Shitmed/Mobs/Species/IPC/organs.rsi - state: eyes - discipline: CivilianServices - tier: 2 - cost: 15000 - recipeUnlocks: - - JawsOfLifeLeftArm - - JawsOfLifeRightArm - - SpeedLeftLeg - - SpeedRightLeg - - BasicCyberneticEyes - - SecurityCyberneticEyes - - MedicalCyberneticEyes -# Shitmed Change End - - type: technology id: AdvancedCleaning name: research-technology-advanced-cleaning diff --git a/Resources/Prototypes/_Backmen/Body/Prototypes/cybernetic.yml b/Resources/Prototypes/_Backmen/Body/Prototypes/cybernetic.yml index 6e85a42b87c..c4298ed57c6 100644 --- a/Resources/Prototypes/_Backmen/Body/Prototypes/cybernetic.yml +++ b/Resources/Prototypes/_Backmen/Body/Prototypes/cybernetic.yml @@ -154,6 +154,7 @@ - type: BodyPart onAdd: - type: NoSlip + - type: ProtectedFromStepTriggers - type: entity parent: RightLegCybernetic @@ -166,4 +167,5 @@ sprintSpeed: 5.625 - type: BodyPart onAdd: - - type: NoSlip \ No newline at end of file + - type: NoSlip + - type: ProtectedFromStepTriggers diff --git a/Resources/Prototypes/_Backmen/Body/Prototypes/generic.yml b/Resources/Prototypes/_Backmen/Body/Prototypes/generic.yml index d01c105fd61..2f82d6cbd5d 100644 --- a/Resources/Prototypes/_Backmen/Body/Prototypes/generic.yml +++ b/Resources/Prototypes/_Backmen/Body/Prototypes/generic.yml @@ -3,12 +3,24 @@ id: BioSynthLeftArm name: bio-synthetic left arm description: This left arm can be transplanted into any living organism and it will adapt to its recipient. + components: + - type: BodyPart + children: + left hand: + id: "left hand" + type: Hand - type: entity parent: RightArmHuman id: BioSynthRightArm name: bio-synthetic right arm description: This right arm can be transplanted into any living organism and it will adapt to its recipient. + components: + - type: BodyPart + children: + right hand: + id: "right hand" + type: Hand - type: entity parent: LeftHandHuman @@ -27,12 +39,24 @@ id: BioSynthLeftLeg name: bio-synthetic left leg description: This left leg can be transplanted into any living organism and it will adapt to its recipient. + components: + - type: BodyPart + children: + left foot: + id: "left foot" + type: Foot - type: entity parent: RightLegHuman id: BioSynthRightLeg name: bio-synthetic right leg description: This right leg can be transplanted into any living organism and it will adapt to its recipient. + components: + - type: BodyPart + children: + right foot: + id: "right foot" + type: Foot - type: entity parent: LeftFootHuman diff --git a/Resources/Prototypes/_Backmen/Recipes/Lathes/robotics.yml b/Resources/Prototypes/_Backmen/Recipes/Lathes/robotics.yml index c9db0667ef0..25efb88e60b 100644 --- a/Resources/Prototypes/_Backmen/Recipes/Lathes/robotics.yml +++ b/Resources/Prototypes/_Backmen/Recipes/Lathes/robotics.yml @@ -6,3 +6,83 @@ Steel: 500 Plasma: 100 +- type: latheRecipe + id: BorgModuleSurgery + result: BorgModuleSurgery + category: Robotics + completetime: 3 + materials: + Steel: 250 + Glass: 250 + Plastic: 250 + +- type: latheRecipe + id: BorgModuleAdvancedSurgery + result: BorgModuleAdvancedSurgery + category: Robotics + completetime: 3 + materials: + Steel: 500 + Glass: 500 + Plastic: 250 + Gold: 50 + +- type: latheRecipe + id: JawsOfLifeLeftArm + result: JawsOfLifeLeftArm + category: Robotics + completetime: 5 + materials: + Steel: 1000 + Glass: 500 + Plastic: 500 + Gold: 300 + Silver: 300 + +- type: latheRecipe + id: JawsOfLifeRightArm + result: JawsOfLifeRightArm + category: Robotics + completetime: 5 + materials: + Steel: 1000 + Glass: 500 + Plastic: 500 + Gold: 300 + Silver: 300 + +- type: latheRecipe + id: SpeedLeftLeg + result: SpeedLeftLeg + category: Robotics + completetime: 5 + materials: + Steel: 1000 + Glass: 500 + Plastic: 500 + Gold: 300 + Silver: 300 + +- type: latheRecipe + id: SpeedRightLeg + result: SpeedRightLeg + category: Robotics + completetime: 5 + materials: + Steel: 1000 + Glass: 500 + Plastic: 500 + Gold: 300 + Silver: 300 + +- type: latheRecipe + id: BasicCyberneticEyes + result: BasicCyberneticEyes + category: Robotics + completetime: 5 + materials: + Steel: 1000 + Glass: 500 + Plastic: 500 + Gold: 300 + Silver: 300 diff --git a/Resources/Prototypes/_Backmen/Recipes/Lathes/security.yml b/Resources/Prototypes/_Backmen/Recipes/Lathes/security.yml index 1a5c2a5cf51..2e04b730461 100644 --- a/Resources/Prototypes/_Backmen/Recipes/Lathes/security.yml +++ b/Resources/Prototypes/_Backmen/Recipes/Lathes/security.yml @@ -39,3 +39,15 @@ Plastic: 500 Gold: 250 Uranium: 50 + +- type: latheRecipe + id: SecurityCyberneticEyes + result: SecurityCyberneticEyes + category: Robotics + completetime: 5 + materials: + Steel: 1000 + Glass: 500 + Plastic: 500 + Gold: 300 + Silver: 300 diff --git a/Resources/Prototypes/_Backmen/Recipes/Lathes/surgery.yml b/Resources/Prototypes/_Backmen/Recipes/Lathes/surgery.yml index 3195e494ede..29549ed5051 100644 --- a/Resources/Prototypes/_Backmen/Recipes/Lathes/surgery.yml +++ b/Resources/Prototypes/_Backmen/Recipes/Lathes/surgery.yml @@ -1,11 +1,61 @@ - type: latheRecipe id: BoneGel result: BoneGel - completetime: 10 + completetime: 2 materials: Plastic: 200 Plasma: 200 +- type: latheRecipe + id: MedicalCyberneticEyes + result: MedicalCyberneticEyes + category: Robotics + completetime: 5 + materials: + Steel: 1000 + Glass: 500 + Plastic: 500 + Gold: 300 + Silver: 300 + +- type: latheRecipe + id: EnergyScalpel + result: EnergyScalpel + completetime: 2 + materials: + Steel: 600 + Glass: 150 + Gold: 150 + +- type: latheRecipe + id: AdvancedRetractor + result: AdvancedRetractor + completetime: 2 + materials: + Steel: 600 + Glass: 150 + Silver: 150 + +- type: latheRecipe + id: EnergyCautery + result: EnergyCautery + completetime: 2 + materials: + Steel: 600 + Glass: 150 + Plasma: 150 + +- type: latheRecipe + id: OmnimedTool + result: OmnimedTool + completetime: 2 + materials: + Steel: 1200 + Glass: 300 + Gold: 300 + Silver: 300 + Plasma: 300 + - type: latheRecipe id: SynthHeart result: BioSynthHeart diff --git a/Resources/Prototypes/_Backmen/Research/civilianservices.yml b/Resources/Prototypes/_Backmen/Research/civilianservices.yml index c593a09f44b..d673a9f2d83 100644 --- a/Resources/Prototypes/_Backmen/Research/civilianservices.yml +++ b/Resources/Prototypes/_Backmen/Research/civilianservices.yml @@ -46,3 +46,55 @@ - ShadokinStandardTranslatorImplanter - ValyrianStandardTranslatorImplanter +# Tier 1 + +# Tier 2 + +- type: technology + id: AdvancedTreatment + name: research-technology-advanced-treatment + icon: + sprite: _Shitmed/Objects/Specific/Medical/Surgery/e-scalpel.rsi + state: e-scalpel-on + discipline: CivilianServices + tier: 2 + cost: 10000 + recipeUnlocks: + - BorgModuleAdvancedTreatment + - BorgModuleDefibrillator + - EnergyScalpel + - EnergyCautery + - AdvancedRetractor + - BorgModuleAdvancedSurgery + +- type: technology + id: CyberneticEnhancements + name: research-technology-cybernetic-enhancements + icon: + sprite: _Shitmed/Mobs/Species/IPC/organs.rsi + state: eyes + discipline: CivilianServices + tier: 2 + cost: 15000 + recipeUnlocks: + - JawsOfLifeLeftArm + - JawsOfLifeRightArm + - SpeedLeftLeg + - SpeedRightLeg + - BasicCyberneticEyes + - SecurityCyberneticEyes + - MedicalCyberneticEyes + +# Tier 3 + +- type: technology + id: HighEndSurgery + name: research-technology-high-end-surgery + icon: + sprite: _Shitmed/Objects/Specific/Medical/Surgery/omnimed.rsi + state: omnimed + discipline: CivilianServices + tier: 3 + cost: 10000 + recipeUnlocks: + - OmnimedTool