From de6b7e31359640825275d71401406ea2fc7128e3 Mon Sep 17 00:00:00 2001 From: Spatison <137375981+Spatison@users.noreply.github.com> Date: Sat, 12 Oct 2024 03:47:22 +0300 Subject: [PATCH 1/3] add: mindslave implant --- .../MindSlave/MindSlaveIconsSystem.cs | 60 +++++++ Content.Server/Implants/ImplanterSystem.cs | 12 +- .../_White/Implants/ImplantsSystem.cs | 147 ++++++++++++++++-- .../Implants/SharedImplanterSystem.cs | 40 +++-- .../Implants/MindSlave/MindSlaveComponent.cs | 21 +++ .../en-US/_white/mindslave/mindslave.ftl | 11 ++ .../en-US/_white/store/uplink-catalog.ftl | 3 + .../ru-RU/_white/implants/mindslave.ftl | 16 -- .../ru-RU/_white/mindslave/mindslave.ftl | 11 ++ .../entities/objects/misc/implanters.ftl | 5 + .../objects/misc/subdermal_implants.ftl | 3 + .../ru-RU/_white/store/uplink-catalog.ftl | 3 + .../_White/Catalog/uplink_catalog.yml | 11 ++ .../Entities/Objects/Misc/implanters.yml | 8 + .../Objects/Misc/subdermal_implants.yml | 12 ++ .../_White/StatusIcon/mindslave.yml | 17 ++ Resources/Prototypes/_White/tags.yml | 5 +- .../Textures/Effects/ssd.rsi/default0.png | Bin 200 -> 524 bytes Resources/Textures/Effects/ssd.rsi/meta.json | 6 +- .../_White/Overlays/mindslave.rsi/master.png | Bin 0 -> 682 bytes .../_White/Overlays/mindslave.rsi/meta.json | 17 ++ .../_White/Overlays/mindslave.rsi/slave.png | Bin 0 -> 646 bytes 22 files changed, 357 insertions(+), 51 deletions(-) create mode 100644 Content.Client/_White/Overlays/MindSlave/MindSlaveIconsSystem.cs create mode 100644 Content.Shared/_White/Implants/MindSlave/MindSlaveComponent.cs create mode 100644 Resources/Locale/en-US/_white/mindslave/mindslave.ftl delete mode 100644 Resources/Locale/ru-RU/_white/implants/mindslave.ftl create mode 100644 Resources/Locale/ru-RU/_white/mindslave/mindslave.ftl create mode 100644 Resources/Prototypes/_White/StatusIcon/mindslave.yml create mode 100644 Resources/Textures/_White/Overlays/mindslave.rsi/master.png create mode 100644 Resources/Textures/_White/Overlays/mindslave.rsi/meta.json create mode 100644 Resources/Textures/_White/Overlays/mindslave.rsi/slave.png diff --git a/Content.Client/_White/Overlays/MindSlave/MindSlaveIconsSystem.cs b/Content.Client/_White/Overlays/MindSlave/MindSlaveIconsSystem.cs new file mode 100644 index 0000000000..a844f94457 --- /dev/null +++ b/Content.Client/_White/Overlays/MindSlave/MindSlaveIconsSystem.cs @@ -0,0 +1,60 @@ +using Content.Client.Overlays; +using Content.Shared._White.Implants.MindSlave; +using Content.Shared.StatusIcon; +using Content.Shared.StatusIcon.Components; +using Robust.Client.Player; +using Robust.Shared.Prototypes; + +namespace Content.Client._White.Overlays.MindSlave; + +public sealed class MindSlaveIconsSystem : EquipmentHudSystem +{ + [Dependency] private readonly IPrototypeManager _prototype = default!; + [Dependency] private readonly IPlayerManager _player = default!; + + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnGetStatusIconsEvent); + } + + private void OnGetStatusIconsEvent( + EntityUid uid, + MindSlaveComponent mindSlaveComponent, + ref GetStatusIconsEvent args) + { + if (!IsActive + || args.InContainer + || !TryComp(_player.LocalEntity, out MindSlaveComponent? ownerMindSlave)) + return; + + var mindSlaveIcon = MindslaveIcon(uid, ownerMindSlave); + args.StatusIcons.AddRange(mindSlaveIcon); + } + + private IEnumerable MindslaveIcon(EntityUid uid, MindSlaveComponent mindSlave) + { + var result = new List(); + string iconType; + var netUid = GetNetEntity(uid); + + if (mindSlave.Master == netUid) + { + iconType = mindSlave.MasterStatusIcon; + } + else if (mindSlave.Slaves.Contains(netUid)) + { + iconType = mindSlave.SlaveStatusIcon; + } + else + { + return result; + } + + if (_prototype.TryIndex(iconType, out var mindslaveIcon)) + result.Add(mindslaveIcon); + + return result; + } +} diff --git a/Content.Server/Implants/ImplanterSystem.cs b/Content.Server/Implants/ImplanterSystem.cs index 3cfa3a9f5f..754c9a7374 100644 --- a/Content.Server/Implants/ImplanterSystem.cs +++ b/Content.Server/Implants/ImplanterSystem.cs @@ -43,16 +43,20 @@ private void OnImplanterAfterInteract(EntityUid uid, ImplanterComponent componen } else { - if (!CanImplant(args.User, target, uid, component, out var implant, out _)) + if (!CanImplant(args.User, target, uid, component, out var implant, out _, out var popup)) // WD EDIT { // no popup if implant doesn't exist if (implant == null) return; // show popup to the user saying implant failed - var name = Identity.Name(target, EntityManager, args.User); - var msg = Loc.GetString("implanter-component-implant-failed", ("implant", implant), ("target", name)); - _popup.PopupEntity(msg, target, args.User); + if (popup) // WD EDIT + { + var name = Identity.Name(target, EntityManager, args.User); + var msg = Loc.GetString("implanter-component-implant-failed", ("implant", implant), + ("target", name)); + _popup.PopupEntity(msg, target, args.User); + } // prevent further interaction since popup was shown args.Handled = true; return; diff --git a/Content.Server/_White/Implants/ImplantsSystem.cs b/Content.Server/_White/Implants/ImplantsSystem.cs index 81123097c4..30ba249601 100644 --- a/Content.Server/_White/Implants/ImplantsSystem.cs +++ b/Content.Server/_White/Implants/ImplantsSystem.cs @@ -1,8 +1,12 @@ using Content.Server.Administration.Logs; +using Content.Server.Chat.Managers; using Content.Server.Mind; using Content.Server.Popups; using Content.Server.Roles; +using Content.Server.Roles.Jobs; +using Content.Shared._White.Implants.MindSlave; using Content.Shared._White.Implants.NeuroStabilization; +using Content.Shared.Chat; using Content.Shared.Database; using Content.Shared.Implants; using Content.Shared.Implants.Components; @@ -14,11 +18,13 @@ namespace Content.Server._White.Implants; public sealed class ImplantsSystem : EntitySystem { - [Dependency] private readonly IAdminLogManager _adminLogManager = default!; - [Dependency] private readonly RoleSystem _roleSystem = default!; - [Dependency] private readonly MindSystem _mindSystem = default!; + [Dependency] private readonly IAdminLogManager _adminLog = default!; + [Dependency] private readonly RoleSystem _role = default!; + [Dependency] private readonly MindSystem _mind = default!; [Dependency] private readonly TagSystem _tag = default!; - [Dependency] private readonly PopupSystem _popupSystem = default!; + [Dependency] private readonly PopupSystem _popup = default!; + [Dependency] private readonly IChatManager _chat = default!; + [Dependency] private readonly JobSystem _job = default!; [ValidatePrototypeId] private const string MindShieldTag = "MindShield"; @@ -26,21 +32,28 @@ public sealed class ImplantsSystem : EntitySystem [ValidatePrototypeId] private const string NeuroStabilizationTag = "NeuroStabilization"; + [ValidatePrototypeId] + private const string MindSlaveTag = "MindSlave"; + public override void Initialize() { base.Initialize(); SubscribeLocalEvent(OnImplantInserted); SubscribeLocalEvent(OnImplantRemoved); + SubscribeLocalEvent(AttemptImplantInserted); } private void OnImplantInserted(EntityUid uid, SubdermalImplantComponent component, SubdermalImplantInserted args) { if (_tag.HasTag(uid, MindShieldTag) - && RevolutionCheck(uid, args.Target)) + && MindShieldCheck(uid, args.Target)) EnsureComp(args.Target); if (_tag.HasTag(uid, NeuroStabilizationTag)) EnsureComp(args.Target); + + if (_tag.HasTag(uid, MindSlaveTag)) + MindSlaveInserted(args.User, args.Target); } private void OnImplantRemoved(EntityUid uid, SubdermalImplantComponent component, SubdermalImplantRemoved args) @@ -50,27 +63,139 @@ private void OnImplantRemoved(EntityUid uid, SubdermalImplantComponent component if (_tag.HasTag(uid, NeuroStabilizationTag)) RemComp(args.Target); + + if (_tag.HasTag(uid, MindSlaveTag)) + MindSlaveRemoved(args.User, args.Target); + } + + private void AttemptImplantInserted(EntityUid uid, SubdermalImplantComponent component, ref AttemptSubdermalImplantInserted args) + { + if (_tag.HasTag(uid, MindSlaveTag) + && !MindSlaveCheck(args.User, args.Target)) + { + args.Popup = false; + args.Cancel(); + } } + #region MindShield + /// /// Checks if the implanted person was a Rev or Head Rev and remove role or destroy mindshield respectively. /// - private bool RevolutionCheck(EntityUid uid, EntityUid target) + private bool MindShieldCheck(EntityUid uid, EntityUid target) { - if (HasComp(target)) + if (HasComp(target) + || HasComp(target)) { - _popupSystem.PopupEntity(Loc.GetString("head-rev-break-mindshield"), target); + _popup.PopupEntity(Loc.GetString("head-rev-break-mindshield"), target); QueueDel(uid); return false; } - if (_mindSystem.TryGetMind(target, out var mindId, out _) - && _roleSystem.MindTryRemoveRole(mindId)) + if (_mind.TryGetMind(target, out var mindId, out _) + && _role.MindTryRemoveRole(mindId)) { - _adminLogManager.Add(LogType.Mind, LogImpact.Medium, + _adminLog.Add(LogType.Mind, LogImpact.Medium, $"{ToPrettyString(target)} was deconverted due to being implanted with a Mindshield."); } return true; } + + #endregion + + #region MindSlave + + private void MindSlaveInserted(EntityUid user, EntityUid target) + { + var slaveComponent = EnsureComp(target); + slaveComponent.Master = GetNetEntity(user); + + var masterComponent = EnsureComp(user); + masterComponent.Slaves.Add(GetNetEntity(target)); + + Dirty(user, masterComponent); + Dirty(target, slaveComponent); + + if (!_mind.TryGetMind(target, out var targetMindId, out var targetMind) + || targetMind.Session is null) + return; + + var jobName = _job.MindTryGetJobName(user); + + // send message to chat + var message = Loc.GetString("mindslave-chat-message", ("player", user), ("role", jobName)); + var wrappedMessage = Loc.GetString("chat-manager-server-wrap-message", ("message", message)); + _chat.ChatMessageToOne(ChatChannel.Server, message, wrappedMessage, default, false, + targetMind.Session.Channel, Color.FromHex("#5e9cff")); + + // add briefing in character menu + if (TryComp(targetMindId, out var roleBriefing)) + { + roleBriefing.Briefing += Loc.GetString("mindslave-briefing", ("player", user), ("role", jobName)); + Dirty(targetMindId, roleBriefing); + } + else + { + _role.MindAddRole(targetMindId, new RoleBriefingComponent + { + Briefing = Loc.GetString("mindslave-briefing", ("player", user), ("role", jobName)) + }, targetMind); + } + + _adminLog.Add(LogType.Mind, LogImpact.High, + $"{ToPrettyString(user)} MindSlaved {ToPrettyString(target)}"); + } + + private void MindSlaveRemoved(EntityUid user, EntityUid target) + { + if (!TryComp(target, out MindSlaveComponent? mindslave) + || !mindslave.Master.HasValue) + return; + + var master = GetEntity(mindslave.Master.Value); + if (_mind.TryGetMind(target, out var mindId, out _)) + { + _role.MindTryRemoveRole(mindId); + _popup.PopupEntity(Loc.GetString("mindslave-freed", ("player", master)), target, target); + } + + if (TryComp(master, out MindSlaveComponent? masterMindslave)) + { + masterMindslave.Slaves.Remove(GetNetEntity(target)); + if (masterMindslave.Slaves.Count == 0) + RemComp(master); + } + + RemComp(target); + + _adminLog.Add(LogType.Mind, LogImpact.High, + $"{ToPrettyString(user)} UnMindSlaved {ToPrettyString(target)}"); + } + + /// + /// Checks if the target can be an MindSlaved + /// + private bool MindSlaveCheck(EntityUid user, EntityUid target) + { + string? message = null; + if (target == user) + message = Loc.GetString("mindslave-target-self"); + + if (HasComp(target) + || HasComp(target) + || !_mind.TryGetMind(target, out _, out _) + || (TryComp(target, out var mindSlave) + && mindSlave.Master.HasValue)) + message = Loc.GetString("mindslave-cant-insert"); + + if (message == null) + return true; + + _popup.PopupEntity(message, target, user); + return false; + } + + #endregion } diff --git a/Content.Shared/Implants/SharedImplanterSystem.cs b/Content.Shared/Implants/SharedImplanterSystem.cs index dce599ef15..1ab82f3113 100644 --- a/Content.Shared/Implants/SharedImplanterSystem.cs +++ b/Content.Shared/Implants/SharedImplanterSystem.cs @@ -88,9 +88,11 @@ public bool CanImplant( EntityUid implanter, ImplanterComponent component, [NotNullWhen(true)] out EntityUid? implant, - [NotNullWhen(true)] out SubdermalImplantComponent? implantComp) + [NotNullWhen(true)] out SubdermalImplantComponent? implantComp, + out bool popup) // WD EDIT { implant = component.ImplanterSlot.ContainerSlot?.ContainedEntities.FirstOrNull(); + popup = true; // WD EDIF if (!TryComp(implant, out implantComp)) return false; @@ -100,8 +102,12 @@ public bool CanImplant( return false; } - var ev = new AddImplantAttemptEvent(user, target, implant.Value, implanter); - RaiseLocalEvent(target, ev); + // WD EDIT START + var ev = new AttemptSubdermalImplantInserted(user, target); + RaiseLocalEvent(implant.Value, ev); + + popup = ev.Popup; + // WD EDIT END return !ev.Cancelled; } @@ -214,23 +220,25 @@ public sealed partial class DrawEvent : SimpleDoAfterEvent { } -public sealed class AddImplantAttemptEvent : CancellableEntityEventArgs +// WD EDIT START +public sealed class AttemptSubdermalImplantInserted(EntityUid user, EntityUid target, bool popup = true) : CancellableEntityEventArgs { - public readonly EntityUid User; - public readonly EntityUid Target; - public readonly EntityUid Implant; - public readonly EntityUid Implanter; + /// + /// Entity who implants + /// + public EntityUid User = user; - public AddImplantAttemptEvent(EntityUid user, EntityUid target, EntityUid implant, EntityUid implanter) - { - User = user; - Target = target; - Implant = implant; - Implanter = implanter; - } + /// + /// Entity being implanted + /// + public EntityUid Target = target; + + /// + /// Popup if implanted failed + /// + public bool Popup = popup; } -// WD EDIT START public sealed class SubdermalImplantInserted(EntityUid user, EntityUid target) { /// diff --git a/Content.Shared/_White/Implants/MindSlave/MindSlaveComponent.cs b/Content.Shared/_White/Implants/MindSlave/MindSlaveComponent.cs new file mode 100644 index 0000000000..d2c75ecc42 --- /dev/null +++ b/Content.Shared/_White/Implants/MindSlave/MindSlaveComponent.cs @@ -0,0 +1,21 @@ +using Content.Shared.StatusIcon; +using Robust.Shared.GameStates; +using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; + +namespace Content.Shared._White.Implants.MindSlave; + +[RegisterComponent, AutoGenerateComponentState, NetworkedComponent] +public sealed partial class MindSlaveComponent : Component +{ + [ViewVariables(VVAccess.ReadOnly), AutoNetworkedField] + public List Slaves = []; + + [ViewVariables(VVAccess.ReadOnly), AutoNetworkedField] + public NetEntity? Master; + + [DataField(customTypeSerializer: typeof(PrototypeIdSerializer))] + public string SlaveStatusIcon = "SlaveMindSlaveIcon"; + + [DataField(customTypeSerializer: typeof(PrototypeIdSerializer))] + public string MasterStatusIcon = "MasterMindSlaveIcon"; +} diff --git a/Resources/Locale/en-US/_white/mindslave/mindslave.ftl b/Resources/Locale/en-US/_white/mindslave/mindslave.ftl new file mode 100644 index 0000000000..56ef3a3d8e --- /dev/null +++ b/Resources/Locale/en-US/_white/mindslave/mindslave.ftl @@ -0,0 +1,11 @@ +mindslave-briefing = Serve and protect {$player}, {$role}. Follow + { GENDER($player) -> + [male] his every order. He is + [female] her every order. She is + *[other] their every order. they are + } absolute power to you. +mindslave-chat-message = Fragments of your memories fly in front of your eyes in an instant, after which a white veil covers your consciousness. In a flash of bright red light, you remember your purpose - to serve {$player}, {$role}. +mindslave-freed = You no longer serve {$player}! + +mindslave-target-self = You can't make yourself your own slave. +mindslave-cant-insert = The mind of this creature is already fixated on something \ No newline at end of file diff --git a/Resources/Locale/en-US/_white/store/uplink-catalog.ftl b/Resources/Locale/en-US/_white/store/uplink-catalog.ftl index 38e64879eb..31229ea48f 100644 --- a/Resources/Locale/en-US/_white/store/uplink-catalog.ftl +++ b/Resources/Locale/en-US/_white/store/uplink-catalog.ftl @@ -18,3 +18,6 @@ uplink-implanter-desc = An advanced implant that allows you to quickly insert an uplink-smoke-implant-name = Smoke implant uplink-smoke-implant-desc = Releases a cloud of smoke when activated. + +uplink-mind-slave = Mindslave implant +uplink-mind-slave-desc = Capture the mind of a living being and order him to throw explosive pies at the captain. \ No newline at end of file diff --git a/Resources/Locale/ru-RU/_white/implants/mindslave.ftl b/Resources/Locale/ru-RU/_white/implants/mindslave.ftl deleted file mode 100644 index 8d98357654..0000000000 --- a/Resources/Locale/ru-RU/_white/implants/mindslave.ftl +++ /dev/null @@ -1,16 +0,0 @@ -mindslave-briefing = Служите и защищайте {$player}, {$role}. Выполняйте каждый их приказ. Они для вас - абсолютная власть. -mindslave-chat-message = Перед вашим глазами в мгновение пролетают осколки ваших воспоминаний, после чего сознание застилает белая пелена. Во вспышке ярко-красного света вы вспоминаете свое предназначение - служить {$player}, {$role}. -mindslave-freed = Вы больше не служите {$player}! - -mindslave-target-self = Вы не можете сделать себя своим же рабом -mindslave-cant-insert = Разум данного существа уже на чем-то зациклен - -uplink-mind-slave = Имплант подчинения -uplink-mind-slave-desc = Захватите разум живого существа и прикажите ему закидать капитана взрывными пирогами. - -ent-MindSlaveImplanter = { ent-BaseImplanter } - .desc = { "" } - .suffix = майдслейв - -ent-MindslaveImplant = Имплант подчинения - .desc = Сделайте из кого-то свою личную куклу. diff --git a/Resources/Locale/ru-RU/_white/mindslave/mindslave.ftl b/Resources/Locale/ru-RU/_white/mindslave/mindslave.ftl new file mode 100644 index 0000000000..8b9c38c107 --- /dev/null +++ b/Resources/Locale/ru-RU/_white/mindslave/mindslave.ftl @@ -0,0 +1,11 @@ +mindslave-briefing = Служите и защищайте {$player}, {$role}. Выполняйте каждый + { GENDER($player) -> + [male] его приказ. Он + [female] её приказ. Она + *[other] их приказ. Они + } для вас - абсолютная власть. +mindslave-chat-message = Перед вашим глазами в мгновение пролетают осколки ваших воспоминаний, после чего сознание застилает белая пелена. Во вспышке ярко-красного света вы вспоминаете свое предназначение - служить {$player}, {$role}. +mindslave-freed = Вы больше не служите {$player}! + +mindslave-target-self = Вы не можете сделать себя своим же рабом +mindslave-cant-insert = Разум данного существа уже на чем-то зациклен \ No newline at end of file diff --git a/Resources/Locale/ru-RU/_white/prototypes/entities/objects/misc/implanters.ftl b/Resources/Locale/ru-RU/_white/prototypes/entities/objects/misc/implanters.ftl index 788abf0a8a..dabe2096c6 100644 --- a/Resources/Locale/ru-RU/_white/prototypes/entities/objects/misc/implanters.ftl +++ b/Resources/Locale/ru-RU/_white/prototypes/entities/objects/misc/implanters.ftl @@ -7,3 +7,8 @@ ent-ImplanterSyndi = { ent-BaseImplanter } ent-SmokeImplanter = { ent-BaseImplanter } .desc = { ent-BaseImplanter.desc } + .suffix = дым + +ent-MindSlaveImplanter = { ent-BaseImplanter } + .desc = { ent-BaseImplanter.desc } + .suffix = подчинение diff --git a/Resources/Locale/ru-RU/_white/prototypes/entities/objects/misc/subdermal_implants.ftl b/Resources/Locale/ru-RU/_white/prototypes/entities/objects/misc/subdermal_implants.ftl index 02d7d7bdf4..816c25dafd 100644 --- a/Resources/Locale/ru-RU/_white/prototypes/entities/objects/misc/subdermal_implants.ftl +++ b/Resources/Locale/ru-RU/_white/prototypes/entities/objects/misc/subdermal_implants.ftl @@ -3,3 +3,6 @@ ent-NeuroStabilizationImplant = имплант нейро стабализаци ent-SmokeImplant = имплант дыма .desc = Этот имплант выпускает облако дыма при активации. + +ent-MindSlaveImplant = имплант подчинения + .desc = Сделайте из кого-то свою личную куклу. \ No newline at end of file diff --git a/Resources/Locale/ru-RU/_white/store/uplink-catalog.ftl b/Resources/Locale/ru-RU/_white/store/uplink-catalog.ftl index 0149d91986..0d68bbdfd0 100644 --- a/Resources/Locale/ru-RU/_white/store/uplink-catalog.ftl +++ b/Resources/Locale/ru-RU/_white/store/uplink-catalog.ftl @@ -18,3 +18,6 @@ uplink-implanter-desc = Продвинутый имплантер, позвол uplink-smoke-implant-name = Имплант дыма uplink-smoke-implant-desc = Выпускает облако дыма при активации. + +uplink-mind-slave = Имплант подчинения +uplink-mind-slave-desc = Захватите разум живого существа и прикажите ему закидать капитана взрывными пирогами. diff --git a/Resources/Prototypes/_White/Catalog/uplink_catalog.yml b/Resources/Prototypes/_White/Catalog/uplink_catalog.yml index fd6b69be96..566d40570a 100644 --- a/Resources/Prototypes/_White/Catalog/uplink_catalog.yml +++ b/Resources/Prototypes/_White/Catalog/uplink_catalog.yml @@ -81,3 +81,14 @@ Telecrystal: 2 categories: - UplinkImplants + +- type: listing + id: UplinkMindSlaveImplanter + name: uplink-mind-slave + description: uplink-mind-slave-desc + icon: { sprite: /Textures/_White/Overlays/mindslave.rsi, state: master } + productEntity: MindSlaveImplanter + cost: + Telecrystal: 6 + categories: + - UplinkImplants diff --git a/Resources/Prototypes/_White/Entities/Objects/Misc/implanters.yml b/Resources/Prototypes/_White/Entities/Objects/Misc/implanters.yml index 43d1bbd593..a66b420ac9 100644 --- a/Resources/Prototypes/_White/Entities/Objects/Misc/implanters.yml +++ b/Resources/Prototypes/_White/Entities/Objects/Misc/implanters.yml @@ -26,3 +26,11 @@ components: - type: Implanter implant: SmokeImplant + +- type: entity + parent: BaseImplantOnlyImplanterSyndi + id: MindSlaveImplanter + suffix: mindslave + components: + - type: Implanter + implant: MindSlaveImplant diff --git a/Resources/Prototypes/_White/Entities/Objects/Misc/subdermal_implants.yml b/Resources/Prototypes/_White/Entities/Objects/Misc/subdermal_implants.yml index 1a727e98ad..f3ecd5229b 100644 --- a/Resources/Prototypes/_White/Entities/Objects/Misc/subdermal_implants.yml +++ b/Resources/Prototypes/_White/Entities/Objects/Misc/subdermal_implants.yml @@ -25,3 +25,15 @@ duration: 15 - type: SoundOnTrigger sound: /Audio/Effects/smoke.ogg + +- type: entity + parent: BaseSubdermalImplant + id: MindSlaveImplant + name: mindslave implant + description: Make someone a proper doll for your use. + noSpawn: true + components: + - type: SubdermalImplant + - type: Tag + tags: + - MindSlave \ No newline at end of file diff --git a/Resources/Prototypes/_White/StatusIcon/mindslave.yml b/Resources/Prototypes/_White/StatusIcon/mindslave.yml new file mode 100644 index 0000000000..aee851fc18 --- /dev/null +++ b/Resources/Prototypes/_White/StatusIcon/mindslave.yml @@ -0,0 +1,17 @@ +- type: statusIcon + id: MasterMindSlaveIcon + priority: 3 + locationPreference: Left + isShaded: true + icon: + sprite: /Textures/_White/Overlays/mindslave.rsi + state: master + +- type: statusIcon + id: SlaveMindSlaveIcon + priority: 3 + locationPreference: Left + isShaded: true + icon: + sprite: /Textures/_White/Overlays/mindslave.rsi + state: slave diff --git a/Resources/Prototypes/_White/tags.yml b/Resources/Prototypes/_White/tags.yml index fe2392f438..ca84c8038b 100644 --- a/Resources/Prototypes/_White/tags.yml +++ b/Resources/Prototypes/_White/tags.yml @@ -2,4 +2,7 @@ id: EnergySword - type: Tag - id: NeuroStabilization \ No newline at end of file + id: NeuroStabilization + +- type: Tag + id: MindSlave \ No newline at end of file diff --git a/Resources/Textures/Effects/ssd.rsi/default0.png b/Resources/Textures/Effects/ssd.rsi/default0.png index bfd8c84da99a874861d8ef47b8c7f4891adf1901..962a7298cf390486a7cce55807e8f7f37876500c 100644 GIT binary patch literal 524 zcmV+n0`vWeP)EX>4Tx04R}tkv&MmKpe$iQ?()$2ZM+>1gS3CMMWG-6^me@v=v%)FuC+YXws0h zxHt-~1qVMCs}3&Cx;nTDg5U>;vxAeOiqYdvy6CZAq~&*bq^n3@4`IG``n+SSIt=r@JYlGW|$S?b>f-L ziotoGSY$<6B|ayfFzJHCk6c$=e&bwlSm2qWnNH3Ti^Ni)jg>ZLMN=c5CJw2ZPWeK{ zWtH<5XRTCa&3p0}26Osyit99o5yK+lNI-&uDmG9;1z}osQY<8CKkDHha{LK$DdgG! zBgZ_-&>%a0@IUz7t(Bjebd!Qnp!3DHKSqJTF3_mi_V=-EH%AO zrG<`wzHQ**x}_<5z~v4w_+-eY>_~o^LOu_?pV2pEf&N>dXVvYkxsTHaAWdB@-2exN zz*vE@*F4_c-QL^3XPW)}0QMVl+o@b*A z>^!DBKmq|yP!a%h<49Aq65s$tU$QTJ<}4w~JlQVuEQ>bs_seLnM@=j)VGN}B{OCvk O0000sCu*ji*FV&-O}tMesBGd6M!n}jZ6ZublGDZCDc)yD?mBLf-*DNVMd9WF+a~{y ooB{uYtC&5K8W`Cm5}<^1V+enV!Z diff --git a/Resources/Textures/Effects/ssd.rsi/meta.json b/Resources/Textures/Effects/ssd.rsi/meta.json index 6c5e7b24e3..6e9db0d8de 100644 --- a/Resources/Textures/Effects/ssd.rsi/meta.json +++ b/Resources/Textures/Effects/ssd.rsi/meta.json @@ -1,10 +1,10 @@ { "version": 1, "license": "CC-BY-SA-3.0", - "copyright": "Take from https://github.com/Skyrat-SS13/Skyrat-tg/blob/92377cd6203bc4d93a6e289d7b857e19bb6cf338/modular_skyrat/modules/indicators/icons/ssd_indicator.dmi", + "copyright": "Take from https://github.com/Skyrat-SS13/Skyrat-tg/blob/92377cd6203bc4d93a6e289d7b857e19bb6cf338/modular_skyrat/modules/indicators/icons/ssd_indicator.dmi and changed by Macoron", "size": { - "x": 32, - "y": 32 + "x": 8, + "y": 8 }, "states": [ { diff --git a/Resources/Textures/_White/Overlays/mindslave.rsi/master.png b/Resources/Textures/_White/Overlays/mindslave.rsi/master.png new file mode 100644 index 0000000000000000000000000000000000000000..36e71896de27b46465a9b54da22ea754364bced1 GIT binary patch literal 682 zcmV;b0#*HqP)EX>4Tx04R}tkv&MmKpe$iTcuK494sQ@kfFM0K~%(1s#pXIrLEAagUO{|(4-+r zad8w}3l4rPRvlcNb#-tR1i=pwX9p)m7b)?7NufoI2gm(*ckglc4)8WAOfkA907W(R zR6HhRbE|^?6#?{O0AmP=%+M0)#SC1>*F8LZy^HcJ_j7-akeoLd;1P)Dn5LV=8^kl4 zrp9@nILu0-Ongo}uG0mHAGt0${KmOxvzKRv^-OA>I7}=QJ6P&qR?-#XY2t{isFd%` zIxKVE;;d9^taVTR!eCxqNpqd%FydH30!avvP(v9Nn26GMN&)jR=w&%l-1_E#Ig>?i5< zwiY=8`nG|K>$WEC0hc?#;FBimqAmGodJ6^M{fxdT2lU?pfi-jfDCoDd;=UD z0;5IBUUzwSPiJrco@w>>1B>HwvCd{h3IG5A24YJ`L;(K){{a7>y{D4^000SaNLh0L z01FcU01FcV0GgZ_00007bV*G`2j~h57A-KfDj9A7005>*L_t&-(|wOC4#GeH1*bq# zS=X>)9Y5K1tXx%5OVbln_5e5(H)stPfCG>;7!pL0Jp=;H$5bt%A>kKBj(C~pXcbxh z&;f{jgY*PNo>Al((i6nK0iY|zXmRT`%$G9)9nzNrhGUoY?!dLVgI1BPtI~c_SEbb| zvK@dxhX5odB{3c}*5j~)%+dJhr9sg$I!ccwEZmjh7;+?VRRjz7(zO>>HJ@A>e_@HDXJMg83^!k$ zPMB=WoYK+)QI>=J0_p7PuHu>>>pd5`_OKuSTT%YL@H^iJGc6y(U1|)jre8yB)KZF9 zH~kl7{F20w%+Yz~g3!yOJTb?w+uGFZ?f#_my|}(_!W?sn2Z9~XXDpk2MEZ#F>}AI) z=UbfdTI5sXXS41yYp489J=V zg-iCxaIbJ`%=mrq|AX@FZi!i!Jh_fFyc0kDOM>ywZimfzk@t^JyK2K&bN;~8Ti?Q^ z54=%-`E{F^CDX5Mjoq)esl8>KZhhdvWVKg|bbn@4akD=7+p|xT{mXr(M$_fnui5#@ zH}I5htznjtVOs2ZDz3b;+&?}4|Gdnv-<>&pIui(5=znR$_w5m2bf)5S4F;&Sp9lP~|yH?VIo z0D_h-OCyVGuNQc{$=`Em!>_A#9ZbioWZVAsh6jiM#SPY+yLbM;kpl+~BqY2%2c!-p z=$||X!VNmdSS~Y8c1Sli1R68Pd(NQ*6MJ^O3={kIhcS;tT9{HiQ(Sp~pa(?k*i-fA cPna9SvnMk5!h=c@fUaTiboFyt=akR{0H;k682|tP literal 0 HcmV?d00001 From 6096831e3546955b15d3d7b3563433a01e1ccd93 Mon Sep 17 00:00:00 2001 From: Spatison <137375981+Spatison@users.noreply.github.com> Date: Sat, 12 Oct 2024 03:58:40 +0300 Subject: [PATCH 2/3] fix --- Content.Server/_White/Implants/ImplantsSystem.cs | 3 ++- Content.Shared/Implants/SharedImplanterSystem.cs | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Content.Server/_White/Implants/ImplantsSystem.cs b/Content.Server/_White/Implants/ImplantsSystem.cs index 30ba249601..b0847b8fae 100644 --- a/Content.Server/_White/Implants/ImplantsSystem.cs +++ b/Content.Server/_White/Implants/ImplantsSystem.cs @@ -86,7 +86,8 @@ private void AttemptImplantInserted(EntityUid uid, SubdermalImplantComponent com private bool MindShieldCheck(EntityUid uid, EntityUid target) { if (HasComp(target) - || HasComp(target)) + || (TryComp(target, out var mindSlave) + && mindSlave.Master.HasValue)) { _popup.PopupEntity(Loc.GetString("head-rev-break-mindshield"), target); QueueDel(uid); diff --git a/Content.Shared/Implants/SharedImplanterSystem.cs b/Content.Shared/Implants/SharedImplanterSystem.cs index 1ab82f3113..545aa17314 100644 --- a/Content.Shared/Implants/SharedImplanterSystem.cs +++ b/Content.Shared/Implants/SharedImplanterSystem.cs @@ -56,7 +56,7 @@ private void OnExamine(EntityUid uid, ImplanterComponent component, ExaminedEven //Set to draw mode if not implant only public void Implant(EntityUid user, EntityUid target, EntityUid implanter, ImplanterComponent component) { - if (!CanImplant(user, target, implanter, component, out var implant, out var implantComp)) + if (!CanImplant(user, target, implanter, component, out var implant, out var implantComp, out _)) return; //If the target doesn't have the implanted component, add it. From a7109e338620301e0eef78de47a9ee80361f8723 Mon Sep 17 00:00:00 2001 From: Spatison <137375981+Spatison@users.noreply.github.com> Date: Sat, 12 Oct 2024 12:00:05 +0300 Subject: [PATCH 3/3] fix --- .../MindSlave/MindSlaveIconsSystem.cs | 4 ++-- .../_White/Implants/ImplantsSystem.cs | 22 +++++++++++-------- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/Content.Client/_White/Overlays/MindSlave/MindSlaveIconsSystem.cs b/Content.Client/_White/Overlays/MindSlave/MindSlaveIconsSystem.cs index a844f94457..ff481bd617 100644 --- a/Content.Client/_White/Overlays/MindSlave/MindSlaveIconsSystem.cs +++ b/Content.Client/_White/Overlays/MindSlave/MindSlaveIconsSystem.cs @@ -29,11 +29,11 @@ private void OnGetStatusIconsEvent( || !TryComp(_player.LocalEntity, out MindSlaveComponent? ownerMindSlave)) return; - var mindSlaveIcon = MindslaveIcon(uid, ownerMindSlave); + var mindSlaveIcon = MindSlaveIcon(uid, ownerMindSlave); args.StatusIcons.AddRange(mindSlaveIcon); } - private IEnumerable MindslaveIcon(EntityUid uid, MindSlaveComponent mindSlave) + private IEnumerable MindSlaveIcon(EntityUid uid, MindSlaveComponent mindSlave) { var result = new List(); string iconType; diff --git a/Content.Server/_White/Implants/ImplantsSystem.cs b/Content.Server/_White/Implants/ImplantsSystem.cs index b0847b8fae..ed0ffc10c5 100644 --- a/Content.Server/_White/Implants/ImplantsSystem.cs +++ b/Content.Server/_White/Implants/ImplantsSystem.cs @@ -180,19 +180,23 @@ private void MindSlaveRemoved(EntityUid user, EntityUid target) /// private bool MindSlaveCheck(EntityUid user, EntityUid target) { - string? message = null; + string message; if (target == user) + { message = Loc.GetString("mindslave-target-self"); - - if (HasComp(target) - || HasComp(target) - || !_mind.TryGetMind(target, out _, out _) - || (TryComp(target, out var mindSlave) - && mindSlave.Master.HasValue)) + } + else if (HasComp(target) + || HasComp(target) + || !_mind.TryGetMind(target, out _, out _) + || (TryComp(target, out var mindSlave) + && mindSlave.Master.HasValue)) + { message = Loc.GetString("mindslave-cant-insert"); - - if (message == null) + } + else + { return true; + } _popup.PopupEntity(message, target, user); return false;